public RealTimeInkSheetDataMessage(RealTimeInkSheetModel sheet, int stylusId, int strokeId, int[] packets)
     : base(sheet.Id)
 {
     this.StylusId = stylusId;
     this.StrokeId = strokeId;
     this.Packets = packets;
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Performs a deep copy of the given SheetModel and resets the disposition to remote.
        /// This seems to be a little more complicated than it needs to be because the disposition is read only.
        /// If the given sheetmodel is an InkSheet or an editable sheet, it is copied, otherwise, it returns itself.
        /// </summary>
        /// <param name="s">The SheetModel to copy</param>
        /// <returns>A deep copy of an InkSheet or an Editable Sheet,  otherwise,  itself</returns>
        public static SheetModel SheetDeepRemoteCopyHelper(SheetModel s)
        {
            using (Synchronizer.Lock(s.SyncRoot)) {
                SheetModel t = null;
                // Only copy InkSheetModels
                if (s is InkSheetModel || s is EditableSheetModel)
                {
                    if (s is RealTimeInkSheetModel)
                    {
                        // Make a deep copy of the SheetModel
                        t = new RealTimeInkSheetModel(Guid.NewGuid(), s.Disposition | SheetDisposition.Remote, s.Bounds, ((RealTimeInkSheetModel)s).Ink.Clone());
                        using (Synchronizer.Lock(t.SyncRoot)) {
                            ((RealTimeInkSheetModel)t).CurrentDrawingAttributes = ((RealTimeInkSheetModel)s).CurrentDrawingAttributes;
                        }
                    }
                    else if (s is InkSheetModel)
                    {
                        // Make a deep copy of the SheetModel
                        t = new InkSheetModel(Guid.NewGuid(), s.Disposition | SheetDisposition.Remote, s.Bounds, ((InkSheetModel)s).Ink.Clone());
                    }
                    else if (s is EditableSheetModel)
                    {
                        t = (EditableSheetModel)((EditableSheetModel)s).CloneToRemote();
                    }
                    // This is a new object so add it to the local references
                    // TODO CMPRINCE: Make this a callback or something
                    UW.ClassroomPresenter.Network.Messages.Message.AddLocalRef(t.Id, t);
                    return(t);
                }
            }

            return(s);
        }
        /// <summary>
        /// Creates a new RealTimeInkSheetRenderer, which will draw ink from the specified
        /// <see cref="RealTimeInkSheetModel"/> on <see cref="Graphics"/> obtained
        /// from the specified <see cref="InkSheetRendererParent"/>.
        /// </summary>
        /// <remarks>
        /// By default, rendering of real-time ink is enabled.  It may be disabled by setting the
        /// <see cref="RealTimeInkEnabled"/> property.
        /// <para>
        /// Drawing of "static" ink is always enabled, but it is only drawn when the parent
        /// <see cref="SlideRenderer"/> is invalidated.  It is <em>not</em> drawn when new ink
        /// is added to the <see cref="InkSheetModel"/>, for it is assumed that a "third-party"
        /// <see cref="TransformableDynamicRenderer"/> or other renderer is doing the job.
        /// </para>
        /// </remarks>
        public RealTimeInkSheetRenderer(SlideDisplayModel display, RealTimeInkSheetModel sheet)
            : base(display, sheet)
        {
            this.m_Sheet = sheet;

            // FIXME: When the SlideViewer that created the SlideDisplayModel is invalidated, invoke TransformableDynamicRenderer.Refresh().
            this.m_Renderer = new TransformableDynamicRenderer.Core.RealTimeInkAdapter(display, sheet);

            if((this.m_Sheet.Disposition & SheetDisposition.Remote) == 0) {
                this.SlideDisplay.Changed["RenderLocalRealTimeInk"].Add(new PropertyEventHandler(this.HandleRenderRealTimeInkChanged));
                this.HandleRenderRealTimeInkChanged(this.SlideDisplay, null);
            } else {
                this.RenderRealTimeInk = true;
            }
        }
        public RealTimeInkSheetNetworkService(SendingQueue sender, PresentationModel presentation, DeckModel deck, SlideModel slide, RealTimeInkSheetModel sheet, SheetMessage.SheetCollection selector)
            : base(sender, presentation, deck, slide, sheet, selector)
        {
            this.m_Sheet = sheet;

            using (Synchronizer.Lock(slide.SyncRoot)) {
                m_SlideID = slide.Id;
            }

            this.PacketBuffers = new Dictionary<int, List<int>>();
            this.PacketFlushTimes = new Dictionary<int, long>();

            this.m_CurrentDrawingAttributesChangedDispatcher = new EventQueue.PropertyEventDispatcher(this.Sender, new PropertyEventHandler(this.HandleCurrentDrawingAttributesChanged));
            this.m_Sheet.Changed["CurrentDrawingAttributes"].Add(this.m_CurrentDrawingAttributesChangedDispatcher.Dispatcher);
            this.m_Sheet.StylusUp += new RealTimeInkSheetModel.StylusUpEventHandler(this.HandleStylusUp);
            this.m_Sheet.Packets += new RealTimeInkSheetModel.PacketsEventHandler(this.HandlePackets);
            this.m_Sheet.StylusDown += new RealTimeInkSheetModel.StylusDownEventHandler(this.HandleStylusDown);
        }
        /// <summary>
        /// Create the matching between two real time ink sheets
        /// </summary>
        /// <param name="sender">The event queue to invoke async events on</param>
        /// <param name="srcSheet">The source sheet to marshal packets/events from</param>
        /// <param name="dstSheet">The destination sheet to marshal packets/events to</param>
        public RealTimeInkSheetMatch(EventQueue sender, RealTimeInkSheetModel srcSheet, RealTimeInkSheetModel dstSheet )
            : base(sender, srcSheet, dstSheet)
        {
            // Save the parameters
            this.m_SourceSheet = srcSheet;
            this.m_DestSheet = dstSheet;

            // Setup event handlers for the source sheet
            this.m_CurrentDrawingAttributesChangedDispatcher = new EventQueue.PropertyEventDispatcher(this.m_Sender, new PropertyEventHandler(this.HandleCurrentDrawingAttributesChanged));
            this.m_SourceSheet.Changed["CurrentDrawingAttributes"].Add(this.m_CurrentDrawingAttributesChangedDispatcher.Dispatcher);
            this.m_SourceSheet.StylusUp += new RealTimeInkSheetModel.StylusUpEventHandler(this.HandleStylusUp);
            this.m_SourceSheet.Packets += new RealTimeInkSheetModel.PacketsEventHandler(this.HandlePackets);
            this.m_SourceSheet.StylusDown += new RealTimeInkSheetModel.StylusDownEventHandler(this.HandleStylusDown);

            // Setup the initial values for the Drawing Attributes
            this.m_Sender.Post(delegate() {
                this.m_CurrentDrawingAttributesChangedDispatcher.Dispatcher(this, null);
            });
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Performs a deep copy of the given SheetModel.
        /// If the given sheetmodel is not an InkSheet, then returns itself.
        /// </summary>
        /// <param name="s">The SheetModel to copy</param>
        /// <returns>The given sheetmodel if not an InkSheetModel, otherwise a deep copy of the InkSheetModel</returns>
        protected SheetModel InkSheetDeepCopyHelper( SheetModel s )
        {
            using( Synchronizer.Lock( s.SyncRoot ) ) {
                InkSheetModel t;
                // Only copy InkSheetModels
                if( s is InkSheetModel ) {
                    if( s is RealTimeInkSheetModel ) {
                        // Make a deep copy of the SheetModel
                        t = new RealTimeInkSheetModel( Guid.NewGuid(), s.Disposition | SheetDisposition.Remote, s.Bounds, ((RealTimeInkSheetModel)s).Ink.Clone() );
                        using( Synchronizer.Lock( t.SyncRoot ) ) {
                            ((RealTimeInkSheetModel)t).CurrentDrawingAttributes = ((RealTimeInkSheetModel)s).CurrentDrawingAttributes;
                        }
                    } else {
                        // Make a deep copy of the SheetModel
                        t = new InkSheetModel( Guid.NewGuid(), s.Disposition, s.Bounds, ((InkSheetModel)s).Ink.Clone() );
                    }
                    // This is a new object so add it to the local references
                    Message.AddLocalRef(t.Id, t);
                    return t;
                }
            }

            return s;
        }
Ejemplo n.º 7
0
            protected override object SetUpMember(int index, object member)
            {
                SheetModel sheet = ((SheetModel) member);

                // Add the SheetMatch to the collection of matches
                using( Synchronizer.Lock( sheet.SyncRoot ) ) {
                    using (Synchronizer.Lock( this.m_Owner.m_DestSlide.SyncRoot ) ) {
                        if( sheet is RealTimeInkSheetModel ) {
                            // Add the sheet
                            RealTimeInkSheetModel m = new RealTimeInkSheetModel( Guid.NewGuid(), sheet.Disposition, sheet.Bounds );
                            this.m_Owner.m_DestSlide.AnnotationSheets.Add( m );

                            // Add the sheet match
                            SheetMatch toAdd = SheetMatch.ForSheet(this.m_Owner.m_Sender, sheet, m );
                            this.m_Owner.m_SheetMatches.Add( toAdd );
                        }
                        else if( sheet is InkSheetModel ) {
                            // Add the sheet
                            InkSheetModel m = new InkSheetModel( Guid.NewGuid(), sheet.Disposition, sheet.Bounds );
                            this.m_Owner.m_DestSlide.AnnotationSheets.Add( m );

                            // Add the sheet match
                            SheetMatch toAdd = SheetMatch.ForSheet(this.m_Owner.m_Sender, sheet, m );
                            this.m_Owner.m_SheetMatches.Add( toAdd );
                        }
                    }
                }

                return null;
            }
 public RealTimeInkSheetMessage(RealTimeInkSheetModel sheet, SheetMessage.SheetCollection collection)
     : base(sheet, collection)
 {
     using(Synchronizer.Lock(sheet.SyncRoot)) {
         this.CurrentDrawingAttributes = sheet.CurrentDrawingAttributes == null ? null
             : new DrawingAttributesSerializer(sheet.CurrentDrawingAttributes);
     }
 }
Ejemplo n.º 9
0
        public static Message RemoteForSheet( SheetModel sheet, SheetCollection collection)
        {
            SheetModel newModel = null;
            if( sheet is ImageSheetModel )
                newModel = sheet;
            else if( sheet is RealTimeInkSheetModel ) {
                using( Synchronizer.Lock( sheet.SyncRoot ) ) {
                    newModel = new RealTimeInkSheetModel( sheet.Id, sheet.Disposition | SheetDisposition.Remote, sheet.Bounds );
                    using( Synchronizer.Lock( newModel.SyncRoot ) )
                        ((RealTimeInkSheetModel)newModel).CurrentDrawingAttributes = ((RealTimeInkSheetModel)sheet).CurrentDrawingAttributes;
                }
            } else if( sheet is InkSheetModel )
                newModel = sheet;
            else if( sheet is TextSheetModel )
                newModel = sheet;
            else if( sheet is QuickPollSheetModel )
                newModel = sheet;

            return SheetMessage.ForSheet( newModel, collection );
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="server"></param>
        /// <param name="deckIndex"></param>
        /// <param name="slideIndex"></param>
        /// <param name="strokes">SimpleWebInk objects that make up the strokes.</param>
        public void HandleStudentSubmission( object server, int deckIndex, int slideIndex, ArrayList strokes )
        {
            SlideModel slide = null;
            DeckModel deck = null;
            using (Synchronizer.Lock(this.m_Presentation.SyncRoot))
            {
                using (Synchronizer.Lock(this.m_Presentation.DeckTraversals[deckIndex].SyncRoot))
                {
                    using( Synchronizer.Lock(this.m_Presentation.DeckTraversals[deckIndex].Current.SyncRoot) ) {
                        // Get the slide model
                        slide = this.m_Presentation.DeckTraversals[deckIndex].Current.Slide;
                    }

                    deck = this.m_Presentation.DeckTraversals[deckIndex].Deck;
                }
            }

            // Get the student submissions deck or create it if it doesn't exist
            DeckModel ssDeck = this.m_Presentation.GetStudentSubmissionDeck();
            if (ssDeck == null) {
                // Create the student submissions deck
                Guid ssGuid = new Guid("{78696D29-AA11-4c5b-BCF8-8E6406077FD4}");
                Guid ssTraversalGuid = new Guid("{4884044B-DAE1-4249-AEF2-3A2304F52E97}");
                ssDeck = new DeckModel(ssGuid, DeckDisposition.StudentSubmission, "Student Submissions");
                ssDeck.Group = Group.Submissions;
                ssDeck.current_subs = true;
            //                AddLocalRef(ssGuid, ssDeck);
                DeckTraversalModel traversal = new SlideDeckTraversalModel(ssTraversalGuid, ssDeck);
            //                AddLocalRef(ssTraversalGuid, traversal);

                // Add the new student submission deck to the presentation
                using (Synchronizer.Lock(this.m_Presentation.SyncRoot)) {
                   this.m_Presentation.DeckTraversals.Add(traversal);
                }
            }

            // Create the new slide to add
            SlideModel newSlide = new SlideModel( new Guid(), new LocalId(), SlideDisposition.Remote | SlideDisposition.StudentSubmission );

            // Make a list of image content sheets that need to be added to the deck.
            List<ImageSheetModel> images = new List<ImageSheetModel>();

            // Update the fields of the slide
            using (Synchronizer.Lock(newSlide.SyncRoot))
            {
                using (Synchronizer.Lock(slide.SyncRoot))
                {
                    newSlide.Title = slide.Title;
                    newSlide.Bounds = slide.Bounds;
                    newSlide.Zoom = slide.Zoom;
                    newSlide.BackgroundColor = slide.BackgroundColor;
                    newSlide.BackgroundTemplate = slide.BackgroundTemplate;
                    newSlide.SubmissionSlideGuid = slide.SubmissionSlideGuid;
                    newSlide.SubmissionStyle = slide.SubmissionStyle;

                    //If the slide background is null, then update the slide background with deck setting
                    using (Synchronizer.Lock(deck.SyncRoot))
                    {
                        if (slide.BackgroundColor == System.Drawing.Color.Empty)
                        {
                            newSlide.BackgroundColor = deck.DeckBackgroundColor;
                        }
                        if (slide.BackgroundTemplate == null)
                        {
                            newSlide.BackgroundTemplate = deck.DeckBackgroundTemplate;
                        }
                    }

                    // Copy all of the content sheets.
                    // Because ContentSheets do not change, there is no
                    // need to do a deep copy (special case for ImageSheetModels).
                    foreach (SheetModel s in slide.ContentSheets)
                    {
                        newSlide.ContentSheets.Add(s);

                        // Queue up any image content to be added the deck below.
                        ImageSheetModel ism = s as ImageSheetModel;
                        if (ism != null)
                            images.Add(ism);
                    }

                    // Make a deep copy of all the ink sheets
                    foreach (SheetModel s in slide.AnnotationSheets)
                    {
                        SheetModel newSheet = UW.ClassroomPresenter.Model.Presentation.SheetModel.SheetDeepRemoteCopyHelper(s);
                        newSlide.AnnotationSheets.Add(newSheet);

                        // Queue up any image content to be added the deck below.
                        ImageSheetModel ism = s as ImageSheetModel;
                        if (ism != null)
                            images.Add(ism);
                    }
                }
            }

            // Add the slide content to the deck.
            using (Synchronizer.Lock(ssDeck.SyncRoot)) {
                foreach (ImageSheetModel ism in images) {
                    System.Drawing.Image image = ism.Image;
                    if (image == null)
                        using (Synchronizer.Lock(ism.Deck.SyncRoot))
                        using (Synchronizer.Lock(ism.SyncRoot))
                            image = ism.Deck.GetSlideContent(ism.MD5);
                    if (image != null)
                        ssDeck.AddSlideContent(ism.MD5, image);
                }

                // Add the slide to the deck.
                ssDeck.InsertSlide(newSlide);
            }

            // Add an entry to the deck traversal so that we can navigate to the slide
            using (Synchronizer.Lock(ssDeck.TableOfContents.SyncRoot)) {
                TableOfContentsModel.Entry e = new TableOfContentsModel.Entry( new Guid(), ssDeck.TableOfContents, newSlide);
                ssDeck.TableOfContents.Entries.Add(e);
            }

            // Add the ink to the slide now
            using (Synchronizer.Lock(newSlide.SyncRoot))
            {
                RealTimeInkSheetModel sheet = new RealTimeInkSheetModel(new Guid(), SheetDisposition.All | SheetDisposition.Remote, newSlide.Bounds);

                // Add the sheet
                newSlide.AnnotationSheets.Add(sheet);

                // Now add the ink
                using (Synchronizer.Lock(sheet.Ink.Strokes.SyncRoot))
                {
                    foreach (SimpleWebInk stroke in strokes) {
                        Microsoft.Ink.Stroke s = sheet.Ink.CreateStroke(stroke.Pts);
                        s.DrawingAttributes.Color =
                            System.Drawing.Color.FromArgb(stroke.R, stroke.G, stroke.B);
                        s.DrawingAttributes.RasterOperation =
                            (stroke.Opacity < 255) ?
                            Microsoft.Ink.RasterOperation.MaskPen :
                            Microsoft.Ink.RasterOperation.CopyPen;
                        s.DrawingAttributes.Width = stroke.Width * 30.00f;
                    }
                }
            }
        }
        protected override bool UpdateTarget(ReceiveContext context)
        {
            RealTimeInkSheetModel sheet = this.Target as RealTimeInkSheetModel;
            if(sheet == null) {
                this.Target = sheet = new RealTimeInkSheetModel(((Guid) this.TargetId), this.Disposition | SheetDisposition.Remote, this.Bounds);

                using(Synchronizer.Lock(sheet.SyncRoot)) {
                    if(this.CurrentDrawingAttributes != null)
                        sheet.CurrentDrawingAttributes = this.CurrentDrawingAttributes.CreateDrawingAttributes();
                }
            } else {
                using(Synchronizer.Lock(sheet.SyncRoot)) {
                    if(this.CurrentDrawingAttributes != null) {
                        DrawingAttributes changed = sheet.CurrentDrawingAttributes;
                        if(changed == null || this.CurrentDrawingAttributes.NeedsUpdate(changed)) {
                            changed = this.CurrentDrawingAttributes.CreateDrawingAttributes();
                            sheet.CurrentDrawingAttributes = changed;
                        }
                    } else {
                        sheet.CurrentDrawingAttributes = null;
                    }
                }
            }

            base.UpdateTarget(context);

            return true;
        }
                /// <summary>
                /// Constructs a new <see cref="RealTimeInkAdapater"/> instance, which will render ink
                /// generated received from the <see cref="RealTimeInkSheetModel"/> onto the graphics device
                /// specified by the <see cref="SlideDisplayModel"/>
                /// </summary>
                public RealTimeInkAdapter(SlideDisplayModel display, RealTimeInkSheetModel rti)
                    : base(display)
                {
                    this.m_RTI = rti;

                    this.m_CurrentDrawingAttributesChangedDispatcher = new EventQueue.PropertyEventDispatcher(this.m_SlideDisplay.EventQueue, new PropertyEventHandler(this.HandleCurrentDrawingAttributesChanged));
                    this.m_RTI.Changed["CurrentDrawingAttributes"].Add(this.m_CurrentDrawingAttributesChangedDispatcher.Dispatcher);
                    this.m_RTI.StylusDown += new RealTimeInkSheetModel.StylusDownEventHandler(this.HandleStylusDown);
                    this.m_RTI.StylusUp += new RealTimeInkSheetModel.StylusUpEventHandler(this.HandleStylusUp);
                    this.m_RTI.Packets += new RealTimeInkSheetModel.PacketsEventHandler(this.HandlePackets);

                    this.m_CurrentDrawingAttributesChangedDispatcher.Dispatcher(this.m_RTI, null);
                }
 public RealTimeInkSheetInformationMessage(RealTimeInkSheetModel sheet, SheetMessage.SheetCollection collection)
     : base(sheet, collection)
 {
 }
Ejemplo n.º 14
0
        protected Guid SendStudentSubmission( Guid TOCEntryGuid )
        {
            Guid newSlideGuid = Guid.Empty;

            UW.ClassroomPresenter.Network.Messages.Message pres, deck, slide, sheet;
            // Add the presentation
            if( this.m_Presentation == null )
                return Guid.Empty;
            pres = new PresentationInformationMessage( this.m_Presentation );
            pres.Group = Groups.Group.Submissions;

            //Add the current deck model that corresponds to this slide deck at the remote location
            deck = new DeckInformationMessage( this.m_Deck );
            deck.Group = Groups.Group.Submissions;
            pres.InsertChild( deck );

            // Add the Slide Message
            newSlideGuid = Guid.NewGuid();
            TOCEntryGuid = Guid.NewGuid();
            slide = new StudentSubmissionSlideInformationMessage( this.m_Slide, newSlideGuid, TOCEntryGuid );
            slide.Group = Groups.Group.Submissions;
            deck.InsertChild( slide );

            // Find the correct user ink layer to send
            RealTimeInkSheetModel m_Sheet = null;
            using( Synchronizer.Lock( this.m_Slide.SyncRoot ) ) {
                foreach( SheetModel s in this.m_Slide.AnnotationSheets ) {
                    if( s is RealTimeInkSheetModel && (s.Disposition & SheetDisposition.Remote) == 0 ) {
                        m_Sheet = (RealTimeInkSheetModel)s;
                        break;
                    }
                }
            }

            // Find the existing ink on the slide
            Microsoft.Ink.Ink extracted;
            using( Synchronizer.Lock( m_Sheet.Ink.Strokes.SyncRoot ) ) {
                // Ensure that each stroke has a Guid which will uniquely identify it on the remote side
                foreach( Microsoft.Ink.Stroke stroke in m_Sheet.Ink.Strokes ) {
                    if( !stroke.ExtendedProperties.DoesPropertyExist( InkSheetMessage.StrokeIdExtendedProperty ) )
                        stroke.ExtendedProperties.Add( InkSheetMessage.StrokeIdExtendedProperty, Guid.NewGuid().ToString() );
                }
                // Extract all of the strokes
                extracted = m_Sheet.Ink.ExtractStrokes( m_Sheet.Ink.Strokes, Microsoft.Ink.ExtractFlags.CopyFromOriginal );
            }

            // Find the Realtime ink on the slide
            RealTimeInkSheetModel newSheet = null;
            using( Synchronizer.Lock( m_Sheet.SyncRoot ) ) {
                newSheet = new RealTimeInkSheetModel( Guid.NewGuid(), m_Sheet.Disposition | SheetDisposition.Remote, m_Sheet.Bounds );
                using( Synchronizer.Lock( newSheet.SyncRoot ) ) {
                    newSheet.CurrentDrawingAttributes = m_Sheet.CurrentDrawingAttributes;
                }
            }

            // Add the Sheet Message for the existing ink
            sheet = new InkSheetStrokesAddedMessage(newSheet, (Guid)slide.TargetId, SheetMessage.SheetCollection.AnnotationSheets, extracted);
            sheet.Group = Groups.Group.Submissions;
            slide.InsertChild( sheet );

            // Add the Sheet Message for the real-time ink
            sheet = SheetMessage.ForSheet( newSheet, SheetMessage.SheetCollection.AnnotationSheets );
            sheet.Group = Groups.Group.Submissions;
            slide.AddOldestPredecessor( sheet );

            // Send the message
            this.m_Sender.Send( pres );

            return newSlideGuid;
        }
        /// <summary>
        /// Send the current ink as a student submission slide
        /// </summary>
        /// <param name="sender">The object which sent this event, i.e. this class</param>
        /// <param name="args">The parameters for the property</param>
        private void HandleSendSubmission( object sender, PropertyEventArgs args )
        {
            if (this.m_SendingLock) return;

            using (Synchronizer.Lock(SubmissionStatusModel.GetInstance().SyncRoot)) {
                SubmissionStatusModel.GetInstance().SubmissionStatus = SubmissionStatusModel.Status.NotReceived;
            }

            ///declare variables we will be using
            UW.ClassroomPresenter.Network.Messages.Message pres, deck, slide, sheet;
            // Construct the message to send
            using( this.m_Model.Workspace.Lock() ) {
                // Add the presentation
                if( this.m_Model.Workspace.CurrentPresentation == null )
                    return;
                ///the presentation message we will be sending
                pres = new PresentationInformationMessage( this.m_Model.Workspace.CurrentPresentation );
                pres.Group = Groups.Group.Submissions;

                //Add the current deck model that corresponds to this slide deck at the remote location
                if( (~this.m_Model.Workspace.CurrentDeckTraversal) == null )
                    return;
                using( Synchronizer.Lock( (~this.m_Model.Workspace.CurrentDeckTraversal).SyncRoot ) ) {
                    DeckModel dModel = (~this.m_Model.Workspace.CurrentDeckTraversal).Deck;
                    foreach( DeckPairModel match in this.m_Model.Workspace.DeckMatches ) {
                        ///check to see if the decks are the same
                        if( match.LocalDeckTraversal.Deck == (~this.m_Model.Workspace.CurrentDeckTraversal).Deck )
                            dModel = match.RemoteDeckTraversal.Deck;
                    }
                    ///create the deck message from this matched deck
                    deck = new DeckInformationMessage( dModel );
                    ///make the deck a submission type deck.
                    deck.Group = Groups.Group.Submissions;
                    ///tack this message onto the end.
                    pres.InsertChild( deck );

                    ///add the particular slide we're on the to message.
                    if( (~this.m_Model.Workspace.CurrentDeckTraversal).Current == null )
                        return;
                    using( Synchronizer.Lock( (~this.m_Model.Workspace.CurrentDeckTraversal).Current.Slide.SyncRoot ) ) {
                        // Add the Slide Message
                        slide = new StudentSubmissionSlideInformationMessage( (~this.m_Model.Workspace.CurrentDeckTraversal).Current.Slide, Guid.NewGuid(), Guid.NewGuid() );
                        slide.Group = Groups.Group.Submissions;
                        deck.InsertChild( slide );

                        // Find the correct user ink layer to send
                        RealTimeInkSheetModel m_Sheet = null;
                        int count = 0;
                        foreach( SheetModel s in (~this.m_Model.Workspace.CurrentDeckTraversal).Current.Slide.AnnotationSheets ) {
                            if( s is RealTimeInkSheetModel && (s.Disposition & SheetDisposition.Remote) == 0 ) {
                                m_Sheet = (RealTimeInkSheetModel)s;
                                count++;
                            }
                        }

                        // DEBUGGING
                        if( count > 1 )
                            Debug.Assert( true, "Bad Count", "Bad" );

                        // Find the existing ink on the slide
                        Ink extracted;
                        using( Synchronizer.Lock( m_Sheet.Ink.Strokes.SyncRoot ) ) {
                            // Ensure that each stroke has a Guid which will uniquely identify it on the remote side
                            foreach( Stroke stroke in m_Sheet.Ink.Strokes ) {
                                if( !stroke.ExtendedProperties.DoesPropertyExist( InkSheetMessage.StrokeIdExtendedProperty ) )
                                    stroke.ExtendedProperties.Add( InkSheetMessage.StrokeIdExtendedProperty, Guid.NewGuid().ToString() );
                            }
                            // Extract all of the strokes
                            extracted = m_Sheet.Ink.ExtractStrokes( m_Sheet.Ink.Strokes, ExtractFlags.CopyFromOriginal );
                        }

                        // Find the Realtime ink on the slide
                        RealTimeInkSheetModel newSheet = null;
                        using( Synchronizer.Lock( m_Sheet.SyncRoot ) ) {
                            newSheet = new RealTimeInkSheetModel( Guid.NewGuid(), m_Sheet.Disposition | SheetDisposition.Remote, m_Sheet.Bounds );
                            using( Synchronizer.Lock( newSheet.SyncRoot ) ) {
                                newSheet.CurrentDrawingAttributes = m_Sheet.CurrentDrawingAttributes;
                            }
                        }

                        // Add a message to *create* the student's RealTimeInkSheetModel on the instructor client (without any ink).
                        sheet = SheetMessage.ForSheet(newSheet, SheetMessage.SheetCollection.AnnotationSheets);
                        sheet.Group = Groups.Group.Submissions;
                        slide.InsertChild(sheet);

                        //Scale the ink if necessary
                        if (ViewerStateModel.NonStandardDpi) {
                            extracted.Strokes.Transform(ViewerStateModel.DpiNormalizationSendMatrix);
                        }

                        // Add a message to copy the ink from the student's RealTimeInkSheetModel to the just-created sheet on the instructor.
                        sheet = new InkSheetStrokesAddedMessage(newSheet, (Guid)slide.TargetId, SheetMessage.SheetCollection.AnnotationSheets, extracted);
                        sheet.Group = Groups.Group.Submissions;
                        slide.InsertChild( sheet );

                        ///Add each text and image sheet into the message as children of the ink sheet if it is public
                        foreach( SheetModel s in (~this.m_Model.Workspace.CurrentDeckTraversal).Current.Slide.AnnotationSheets ) {
                            if( s is TextSheetModel && !(s is StatusLabel) && (s.Disposition & SheetDisposition.Remote) == 0) {
                                TextSheetModel text_sheet = (TextSheetModel) s;
                                text_sheet = (TextSheetModel) text_sheet.Clone();
                                ///some ugly code here due to synchronization
                                bool sheet_is_public;
                                using (Synchronizer.Lock(text_sheet.SyncRoot)) {
                                    sheet_is_public = text_sheet.IsPublic;
                                }
                                if (sheet_is_public) {
                                    TextSheetMessage t_message = new TextSheetMessage(text_sheet, SheetMessage.SheetCollection.AnnotationSheets);
                                    t_message.Group = Groups.Group.Submissions;
                                    slide.InsertChild(t_message);
                                }
                            }
                            if (s is ImageSheetModel && !(s is StatusLabel) && (s.Disposition & SheetDisposition.Remote) == 0) {
                                ImageSheetModel image_sheet = (ImageSheetModel)s;
                                image_sheet = (ImageSheetModel) image_sheet.Clone();
                                ImageSheetMessage i_message = new ImageSheetMessage(image_sheet, SheetMessage.SheetCollection.AnnotationSheets);
                                i_message.Group = Groups.Group.Submissions;
                                slide.InsertChild(i_message);

                            }
                        }
                        //Lock the current sending.
                        this.LockSending();

                        // Send the message
                        this.m_Sender.Send(pres);
                    }
                }
            }
        }
 public RealTimeInkSheetStylusUpMessage(RealTimeInkSheetModel sheet, int stylusId, int strokeId, int[] packets)
     : base(sheet, stylusId, strokeId, packets)
 {
 }
 public RealTimeInkSheetStylusDownMessage(RealTimeInkSheetModel sheet, int stylusId, int strokeId, int[] packets, TabletPropertyDescriptionCollection tabletProperties)
     : base(sheet, stylusId, strokeId, packets)
 {
     this.TabletProperties = new TabletPropertyDescriptionCollectionInformation(tabletProperties);
 }
Ejemplo n.º 18
0
        private void HandleSlideChanged(object sender, PropertyEventArgs args)
        {
            using(Synchronizer.Lock(this)) {
                SlideModel slide;
                using(Synchronizer.Lock(this.m_SlideDisplay.SyncRoot)) {
                    slide = this.m_SlideDisplay.Slide;
                    // Release the reader lock immediately, because it is not possible (or at least easy)
                    // to guarantee consistent locking order between the SlideDisplayModel and the SlideModel.
                    // Most of the SheetRenderer classes will obtain a lock on the SlideModel *first*
                    // and the SlideDisplayModel *second* because they react to changes in the slide;
                    // but that order is not possible here.
                }

                if(slide == null) {
                    this.m_Adaptee.InkSheetModel = null;
                    this.m_Adaptee.RealTimeInkSheetModel = null;
                }

                else {
                    using(Synchronizer.Lock(slide.SyncRoot)) {
                        try {
                            InkSheetModel inks = null;
                            RealTimeInkSheetModel rti = null;

                            // TODO: This code is duplicated in SlideToolBarButtons.ClearInkSheetToolBarButton.  Extract to a "ActiveInkAnnotationSheet" property of the SlideModel.
                            // Find the *top-most* InkSheetModel and RealTimeInkSheetModel in the annotation layer.
                            foreach(SheetModel sheet in slide.AnnotationSheets) {
                                // Only consider local sheets.
                                if((sheet.Disposition & SheetDisposition.Remote) != 0) {
                                    continue;

                                // RealTimeInkSheetModels get priority.
                                } else if(sheet is RealTimeInkSheetModel) {
                                    inks = rti = ((RealTimeInkSheetModel) sheet);

                                // Regular InkSheetModels are our second choice.
                                } else if(sheet is InkSheetModel) {
                                    inks = ((InkSheetModel) sheet);
                                    rti = null;

                                // Only consider the *top-most* non-remote sheet (the last one in the collection).
                                } else {
                                    continue;
                                }
                            }

                            if(inks == null && rti == null) {
                                // If the slide does not have an ink annotation sheet, create one.
                                inks = rti = new RealTimeInkSheetModel(Guid.NewGuid(), SheetDisposition.All, Rectangle.Empty);

                                // Add it to the slide.
                                slide.AnnotationSheets.Add(rti);
                            }

                            // Start collecting ink into the InkSheetModel's Ink object
                            // (after the sheet is added to the slide, so renderers don't get out of sync).
                            // Also start sending events to InkSheetModel.RealTimeInk.
                            this.m_Adaptee.InkSheetModel = rti == null ? inks : rti;
                            this.m_Adaptee.RealTimeInkSheetModel = rti;
                        }

                        catch {
                            // We were unable to get an Ink annotation sheet, so disable inking.
                            this.m_Adaptee.InkSheetModel = null;
                            this.m_Adaptee.RealTimeInkSheetModel = null;
                            throw;
                        }
                    }
                }
            }
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Performs a deep copy of the given SheetModel.
        /// If the given sheetmodel is an InkSheet or an editable sheet, it is copied, otherwise, it returns itself. 
        /// </summary>
        /// <param name="s">The SheetModel to copy</param>
        /// <returns>A deep copy of an InkSheet or an Editable Sheet,  otherwise,  itself</returns>
        public static SheetModel SheetDeepCopyHelper(SheetModel s)
        {
            using (Synchronizer.Lock(s.SyncRoot)) {
                SheetModel t = null;
                // Only copy InkSheetModels
                if (s is InkSheetModel || s is EditableSheetModel) {
                    if (s is RealTimeInkSheetModel) {
                        // Make a deep copy of the SheetModel
            //                        t = new RealTimeInkSheetModel(Guid.NewGuid(), SheetDisposition.All, s.Bounds, ((RealTimeInkSheetModel)s).Ink.Clone());
                        t = new RealTimeInkSheetModel(Guid.NewGuid(), s.Disposition, s.Bounds, ((RealTimeInkSheetModel)s).Ink.Clone());
                        using (Synchronizer.Lock(t.SyncRoot)) {
                            ((RealTimeInkSheetModel)t).CurrentDrawingAttributes = ((RealTimeInkSheetModel)s).CurrentDrawingAttributes;
                        }
                    }
                    else if (s is InkSheetModel) {
                        // Make a deep copy of the SheetModel
                        t = new InkSheetModel(Guid.NewGuid(), s.Disposition, s.Bounds, ((InkSheetModel)s).Ink.Clone());
                    }
                    else if (s is EditableSheetModel) {
                        t = (EditableSheetModel)((EditableSheetModel)s).Clone();
                    }
                    // This is a new object so add it to the local references
                    // TODO CMPRINCE: Make this a callback or something
                    UW.ClassroomPresenter.Network.Messages.Message.AddLocalRef(t.Id, t);
                    return t;
                }
            }

            return s;
        }