private void HandleInkAddedHelper(Ink extracted)
        {
            Message message, deck, slide, sheet;

            message = new PresentationInformationMessage(this.Presentation);
            message.InsertChild(deck = new DeckInformationMessage(this.Deck));
            deck.InsertChild(slide   = new SlideInformationMessage(GetSubmissionSlideModel(), false));
            slide.InsertChild(sheet  = new InkSheetStrokesAddedMessage(this.m_Sheet, (Guid)slide.TargetId, this.SheetCollectionSelector, extracted));
            sheet.AddOldestPredecessor(SheetMessage.RemoteForSheet(this.m_Sheet, this.SheetCollectionSelector));
            this.Sender.Send(message);
        }
Example #2
0
        protected override MergeAction MergeInto(Message other_)
        {
            if (other_ is InkSheetStrokesAddedMessage)
            {
                InkSheetStrokesAddedMessage other = ((InkSheetStrokesAddedMessage)other_);
                byte[][] merged = new byte[other.SavedInks.Length + this.SavedInks.Length][];
                other.SavedInks.CopyTo(merged, 0);
                this.SavedInks.CopyTo(merged, other.SavedInks.Length);
                other.SavedInks = merged;
                return(MergeAction.DiscardThis);
            }

            return(base.MergeInto(other_));
        }
        private void HandleInkAddedHelper(Ink extracted, Group receivers)
        {
            if (ViewerStateModel.NonStandardDpi)
            {
                extracted.Strokes.Transform(ViewerStateModel.DpiNormalizationSendMatrix, true);
            }

            try
            {
                Message message = new InkSheetStrokesAddedMessage(this.m_Sheet, m_SlideID, this.SheetCollectionSelector, extracted);
                message.Group               = receivers;
                message.Tags                = new MessageTags();
                message.Tags.SlideID        = m_SlideID;
                message.Tags.BridgePriority = MessagePriority.Higher;
                this.Sender.Send(message);
            }
            catch (OutOfMemoryException e)
            {
                Trace.WriteLine(e.ToString());
                GC.Collect();
            }
        }
        private void HandleInkAddedHelper(Ink extracted, Group receivers)
        {
            if (ViewerStateModel.NonStandardDpi) {
                extracted.Strokes.Transform(ViewerStateModel.DpiNormalizationSendMatrix, true);
            }

            try
            {
                Message message = new InkSheetStrokesAddedMessage(this.m_Sheet, m_SlideID, this.SheetCollectionSelector, extracted);
                message.Group = receivers;
                message.Tags = new MessageTags();
                message.Tags.SlideID = m_SlideID;
                message.Tags.BridgePriority = MessagePriority.Higher;
                this.Sender.Send(message);
            }
            catch (OutOfMemoryException e)
            {
                Trace.WriteLine(e.ToString());
                GC.Collect();
            }
        }
        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;
        }
        protected Guid SendStudentSubmission()
        {
            Guid newSlideGuid = Guid.Empty;

            UW.ClassroomPresenter.Network.Messages.Message pres, deck, slide, sheet;
            // Add the presentation
            if (this.Presentation == null)
            {
                return(Guid.Empty);
            }
            pres       = new PresentationInformationMessage(this.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.Deck);
            deck.Group = Groups.Group.Submissions;
            pres.InsertChild(deck);

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

            // Find the correct user ink layer to send
            RealTimeInkSheetModel m_Sheet = null;

            using (Synchronizer.Lock(this.Slide.SyncRoot)) {
                foreach (SheetModel s in this.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
            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);
        }
 private void HandleInkAddedHelper(Ink extracted)
 {
     Message message, deck, slide, sheet;
     message = new PresentationInformationMessage(this.Presentation);
     message.InsertChild(deck = new DeckInformationMessage(this.Deck));
     deck.InsertChild(slide = new SlideInformationMessage( GetSubmissionSlideModel(), false ));
     slide.InsertChild(sheet = new InkSheetStrokesAddedMessage(this.m_Sheet, (Guid)slide.TargetId, this.SheetCollectionSelector, extracted));
     sheet.AddOldestPredecessor( SheetMessage.RemoteForSheet( this.m_Sheet, this.SheetCollectionSelector ) );
     this.Sender.Send(message);
 }
Example #8
0
        /// <summary>
        /// This is the message received when there is a completed stroke. Translate to RTDrawStroke.
        /// </summary>
        /// <param name="issam"></param>
        /// <returns></returns>
        internal RTDrawStroke AddInkSheetStrokesAdded(CP3Msgs.InkSheetStrokesAddedMessage issam)
        {
            //Notice that we tend to get a fair number of these messages that have nothing in the SavedInks property.. presenter bug?
            byte[][] saved = issam.SavedInks;
            if (saved.Length == 0)
            {
                return(null);
            }
            if (saved[0].Length == 0)
            {
                return(null);
            }
            if (saved.Length > 1)
            {
                //This does not seem to occur in practice.  If it ever does, we need to generate multiple RTDrawStroke messages:
                warning += "Warning: Valid ink may be ignored because we only support one byte[] per ink message.  ";
            }
            Ink ink = new Ink();

            ink.Load(saved[0]);
            if (ink.Strokes.Count <= 0)
            {
                return(null);
            }

            //This message has a targetID identifying a Sheet which we use to look up a toc entry.
            Debug.WriteLine("***** InkSheetStrokesAdded targetid=" + issam.TargetId.ToString());

            if (!sheetToSlideLookup.ContainsKey(issam.TargetId))
            {
                if (issam.SlideId.Equals(Guid.Empty))
                {
                    //Don't think this should ever happen.
                    warning += "Warning: InkSheetStrokesAdded does not match a known sheet.  Ignoring ink.  ";
                    return(null);
                }
                sheetToSlideLookup.Add(issam.TargetId, issam.SlideId);
            }

            Guid slideId = (Guid)sheetToSlideLookup[issam.TargetId];

            //Get DeckID and Slide index from toc.  Return RTDrawStroke.
            TableOfContents.TocEntry tocEntry = toc.LookupBySlideId(slideId);
            if (tocEntry == null)
            {
                //In some cases ink arrives before the TOC entry.
                //    Save the ink to send later when the TOC entry is available.
                if (!pendingInk.ContainsKey(slideId))
                {
                    pendingInk.Add(slideId, new List <Ink>());
                }
                pendingInk[slideId].Add(ink);
                Debug.WriteLine("InkSheetStrokesAdded does not have a Toc entry.  Caching for later.");
                return(null);
            }

            Guid strokeId = Guid.NewGuid();

            //Pull out the identifier which is used if we need to delete the stroke later:
            if (ink.Strokes[0].ExtendedProperties.DoesPropertyExist(StrokeIdExtendedProperty))
            {
                strokeId = new Guid((string)ink.Strokes[0].ExtendedProperties[StrokeIdExtendedProperty].Data);
            }
            else
            {
                warning += "Warning: Failed to find stroke Id.  ";
            }
            //WebViewer looks for the CP2 extended property, so add it too.
            ink.Strokes[0].ExtendedProperties.Add(CP2StrokeIdExtendedProperty, (object)strokeId.ToString());
            //WebViewer wants ink to be scaled to 500x500
            ink.Strokes.Scale(500f / getCurrentSlideWidth(), 500f / getCurrentSlideHeight());
            //Debug.WriteLine("***** Adding Stroke ID=" + strokeId.ToString());
            RTDrawStroke rtds = new RTDrawStroke(ink, strokeId, true, tocEntry.DeckId, tocEntry.SlideIndex);

            //Add the stroke to our list to optimize deletes
            if (!strokeCountsBySlideId.ContainsKey(slideId))
            {
                strokeCountsBySlideId.Add(slideId, 1);
            }
            else
            {
                strokeCountsBySlideId[slideId]++;
            }

            return(rtds);
        }
        /// <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);
                    }
                }
            }
        }