Ejemplo n.º 1
0
        protected virtual void HandleInkAdded(object sender, StrokesEventArgs e)
        {
            Rectangle invalid = Rectangle.Empty;

            // HACK: It would be much simpler and more efficient to just use
            // Ink.CreateStrokes(e.StrokeIds).GetBoundingBox(), but CreateStrokes has
            // a tendency to throw "ComException HRESULT 0x80040222" (see Bug 726).
            // This hack manually iterates through the strokes looking for the added ones;
            // there doesn't seem to be any way to make this more efficient with a table
            // lookup, at least not with the APIs exposed by Microsoft.Ink.Ink.

            using (Synchronizer.Lock(this.m_Sheet.Ink.Strokes.SyncRoot)) {
                foreach (Stroke stroke in this.m_Sheet.Ink.Strokes)
                {
                    if (Array.IndexOf <int>(e.StrokeIds, stroke.Id) >= 0)
                    {
                        invalid = (invalid == Rectangle.Empty)
                            ? stroke.GetBoundingBox()
                            : Rectangle.Union(invalid, stroke.GetBoundingBox());
                    }
                }
            }

            this.InvalidateInkSpaceRectangle(invalid);
        }
        private IEnumerable <IEnumerable <Point> > GetSignatureStrokes()
        {
            var args = new StrokesEventArgs();

            StrokesRequested?.Invoke(this, args);
            return(args.Strokes);
        }
Ejemplo n.º 3
0
        protected override bool UpdateTarget(ReceiveContext context)
        {
            bool update = base.UpdateTarget(context);

            InkSheetModel sheet = this.Target as InkSheetModel;

            if (sheet == null)
            {
                return(update);
            }

            ArrayList deleting = new ArrayList(this.StrokeIds.Length);

            foreach (Stroke existing in sheet.Ink.Strokes)
            {
                if (existing.ExtendedProperties.DoesPropertyExist(StrokeIdExtendedProperty))
                {
                    if (Array.IndexOf(this.StrokeIds, existing.ExtendedProperties[StrokeIdExtendedProperty].Data) >= 0)
                    {
                        deleting.Add(existing.Id);
                    }
                }
            }

            int[] ids = ((int[])deleting.ToArray(typeof(int)));
            using (Strokes strokes = sheet.Ink.CreateStrokes(ids)) {
                StrokesEventArgs args = new StrokesEventArgs(ids);
                sheet.OnInkDeleting(args);
                sheet.Ink.DeleteStrokes(strokes);
                sheet.OnInkDeleted(args);
            }

            return(update);
        }
Ejemplo n.º 4
0
        private void HandleInkDeleting(object sender, StrokesEventArgs e)
        {
            // We must extract the deleted ink immediately, or else it won't be around
            // by the time we process the event on another thread.
            // Compile a list of all of the Guids which identify the strokes to be removed.
            // The Guids are created by HandleInkAdded above.
            // If a stroke does not have a Guid, then it was not broadcast and therefore
            // we don't need to worry about telling the remote clients to remove it.
            string[] ids;
            using (Synchronizer.Lock(this.m_Sheet.Ink.Strokes.SyncRoot)) {
                int[]     strokeIds = e.StrokeIds;
                ArrayList guids     = new ArrayList(strokeIds.Length);
                using (Strokes strokes = this.m_Sheet.Ink.CreateStrokes(strokeIds)) {
                    foreach (Stroke stroke in strokes)
                    {
                        if (stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                        {
                            guids.Add(stroke.ExtendedProperties[InkSheetMessage.StrokeIdExtendedProperty].Data);
                        }
                    }
                }
                ids = ((string[])guids.ToArray(typeof(string)));
            }

            if (ids.Length > 0)
            {
                this.Sender.Post(delegate() {
                    this.HandleInkDeletingHelper(ids);
                });
            }
        }
Ejemplo n.º 5
0
        private void HandleInkAdded(object sender, StrokesEventArgs e)
        {
            // We must extract the added ink immediately so it can't be deleted before the
            // message is sent on another thread.

            Ink extracted;

            using (Synchronizer.Lock(this.m_Sheet.Ink.Strokes.SyncRoot)) {
                using (Strokes strokes = this.m_Sheet.Ink.CreateStrokes(e.StrokeIds)) {
                    // Ensure that each stroke has a Guid which will uniquely identify it on the remote side.
                    foreach (Stroke stroke in strokes)
                    {
                        if (!stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                        {
                            stroke.ExtendedProperties.Add(InkSheetMessage.StrokeIdExtendedProperty, Guid.NewGuid().ToString());
                        }
                    }

                    extracted = this.m_Sheet.Ink.ExtractStrokes(strokes, ExtractFlags.CopyFromOriginal);
                }
            }

            this.Sender.Post(delegate() {
                this.HandleInkAddedHelper(extracted, Group.AllParticipant);
            });
        }
Ejemplo n.º 6
0
    private int[] neweststrokeids;     // Note: Ink.AddStrokesAtRectangle doesn't return
    // the new stroke ids, so we must get them ourselves, from the InkAdded event.

    private void inkoverlay_Ink_InkAdded(object sender, StrokesEventArgs e)
    {
        // This event fires on a background thread, which creates a race condition
        // when you access neweststrokeids.
        // Return to the UI thread before continuing.
        if (this.InvokeRequired)
        {
            this.Invoke(
                new StrokesEventHandler(inkoverlay_Ink_InkAdded),
                new object[] { sender, e });
            return;
        }

        dbg.WriteLine("----- inkoverlay_Ink_InkAdded -----");

        try         // To prevent exceptions from propagating back to ink runtime.
        {
            neweststrokeids = e.StrokeIds;
        }
        catch (Exception ex)
        {
            // Log the error.
            Global.HandleThreadException(this, new System.Threading.ThreadExceptionEventArgs(ex));
        }
    }
Ejemplo n.º 7
0
        private void LoadInkIntoTarget(InkSheetModel sheet, Ink extracted, out int[] ids)
        {
            Ink restored = extracted;

            using (Synchronizer.Lock(sheet.Ink.Strokes.SyncRoot)) {
                ids = new int[restored.Strokes.Count];

                for (int i = 0; i < ids.Length; i++)
                {
                    Stroke stroke = restored.Strokes[i];

                    // Remove any strokes that have the same remote Id as the new one.
                    // Unfortunately, because the InkSheetUndoService cannot preserve stroke referential identity,
                    // we must do a full search each time and cannot simply keep a table.
                    if (stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                    {
                        object id = stroke.ExtendedProperties[InkSheetMessage.StrokeIdExtendedProperty].Data;
                        foreach (Stroke existing in sheet.Ink.Strokes)
                        {
                            if (existing.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                            {
                                if (id.Equals(existing.ExtendedProperties[InkSheetMessage.StrokeIdExtendedProperty].Data))
                                {
                                    StrokesEventArgs args = new StrokesEventArgs(new int[] { existing.Id });
                                    sheet.OnInkDeleting(args);
                                    sheet.Ink.DeleteStroke(existing);
                                    sheet.OnInkDeleted(args);
                                }
                            }
                        }
                    }

                    // The stroke has no association with the current Ink object.
                    // Therefore, we have to recreate it by copying the raw packet data.
                    // This first requires recreating the TabletPropertyDescriptionCollection,
                    // which, for some stupid reason, must be done manually for lack of a better API.
                    TabletPropertyDescriptionCollection properties = new TabletPropertyDescriptionCollection();
                    foreach (Guid property in stroke.PacketDescription)
                    {
                        properties.Add(new TabletPropertyDescription(property, stroke.GetPacketDescriptionPropertyMetrics(property)));
                    }

                    // Create a new stroke from the raw packet data.
                    Stroke created = sheet.Ink.CreateStroke(stroke.GetPacketData(), properties);

                    // Copy the DrawingAttributes and all application data
                    // (especially the StrokesIdExtendedProperty) to the new stroke.
                    created.DrawingAttributes = stroke.DrawingAttributes;
                    foreach (ExtendedProperty prop in stroke.ExtendedProperties)
                    {
                        created.ExtendedProperties.Add(prop.Id, prop.Data);
                    }

                    ids[i] = created.Id;
                }
            }
        }
Ejemplo n.º 8
0
            /// <summary>
            /// Handle the button being clicked
            /// </summary>
            /// <param name="args">The event args</param>
            protected override void OnClick(EventArgs args)
            {
                if (this.m_Slide == null)
                {
                    return;
                }

                using (Synchronizer.Lock(this.m_Slide.SyncRoot)) {
                    InkSheetModel inks = null;

                    // TODO: This code is duplicated in InkSheetAdapter.  Extract to a "ActiveInkAnnotationSheet" property of the SlideModel.
                    // Find the *top-most* *local* InkSheetModel in the annotation layer.
                    for (int i = m_Slide.AnnotationSheets.Count - 1; i >= 0; i--)
                    {
                        SheetModel sheet = m_Slide.AnnotationSheets[i];
                        if ((sheet.Disposition & SheetDisposition.Remote) != 0)
                        {
                            continue;
                        }

                        if (sheet is InkSheetModel)
                        {
                            inks = ((InkSheetModel)sheet);
                        }
                        //else if (sheet is EditableSheetModel ) {
                        //    ///only erase the sheet model if the user made it
                        //    ///(i.e. it is editable. If this is sent from another
                        //    ///person, don't erase it).
                        //    EditableSheetModel edit_sheet = (EditableSheetModel)sheet;
                        //    if (edit_sheet.IsEditable) {
                        //        m_Slide.AnnotationSheets.Remove(sheet);
                        //    }
                        //}
                    }

                    if (inks != null)
                    {
                        using (Synchronizer.Lock(inks.SyncRoot)) {
                            Strokes strokes = inks.Ink.Strokes;
                            using (Synchronizer.Lock(strokes.SyncRoot)) {
                                int[] ids = new int[inks.Ink.Strokes.Count];
                                for (int j = 0; j < strokes.Count; j++)
                                {
                                    ids[j] = strokes[j].Id;
                                }

                                StrokesEventArgs sea = new StrokesEventArgs(ids);
                                inks.OnInkDeleting(sea);
                                inks.Ink.DeleteStrokes();
                                inks.OnInkDeleted(sea);
                            }
                        }
                    }
                }

                base.OnClick(args);
            }
Ejemplo n.º 9
0
            private void AddInk()
            {
                using (Synchronizer.Lock(this)) {
                    // Create an array of stroke Ids in order to fire the InkAdded event later.
                    int[] ids = new int[this.m_StrokesToAdd.Count];

                    using (Synchronizer.Lock(this.m_Watcher.m_InkSheet.Ink.Strokes.SyncRoot)) {
                        for (int i = 0; i < ids.Length; i++)
                        {
                            Stroke stroke = this.m_StrokesToAdd[i];

                            // The stroke probably has no association with the current Ink object.
                            // Therefore, we have to recreate it by copying the raw packet data.
                            // This first requires recreating the TabletPropertyDescriptionCollection,
                            // which, for some stupid reason, must be done manually for lack of a better API.
                            TabletPropertyDescriptionCollection properties = new TabletPropertyDescriptionCollection();
                            foreach (Guid property in stroke.PacketDescription)
                            {
                                properties.Add(new TabletPropertyDescription(property, stroke.GetPacketDescriptionPropertyMetrics(property)));
                            }

                            // Create a new stroke from the raw packet data.
                            Stroke created = this.m_Watcher.m_InkSheet.Ink.CreateStroke(stroke.GetPacketData(), properties);

                            // Copy the DrawingAttributes and all application data
                            // (especially the StrokesIdExtendedProperty) to the new stroke.
                            created.DrawingAttributes = stroke.DrawingAttributes;
                            foreach (ExtendedProperty prop in stroke.ExtendedProperties)
                            {
                                created.ExtendedProperties.Add(prop.Id, prop.Data);
                            }

                            // Get the new stroke's Id so we can fire the InkAdded event.
                            ids[i] = created.Id;
                        }

                        // If the added strokes don't yet have StrokeIdExtendedProperty properties,
                        // create new Guids for them.  Regardless, set this.m_StrokesToRemove
                        // to the list of stroke Guids.
                        this.UpdateAndSetStrokesToRemoveIds(this.m_StrokesToAdd);

                        // Then, unset this.m_StrokesToAdd since they're already added.
                        this.m_StrokesToAdd = null;
                    }

                    // Create the event arguments and add them to the ignore list so the
                    // InkSheetUndoService won't create an InkUndoer for this change.
                    StrokesEventArgs args = new StrokesEventArgs(ids);
                    using (Synchronizer.Lock(this.m_Watcher.m_Ignore.SyncRoot)) {
                        this.m_Watcher.m_Ignore.Add(args);
                    }

                    // Finally fire the appropriate InkAdded event from the InkSheetModel.
                    this.m_Watcher.m_InkSheet.OnInkAdded(args);
                }
            }
Ejemplo n.º 10
0
 public void OnInkDeleted(StrokesEventArgs args)
 {
     // The default event add/remove methods lock(this), so we need to do the same to make sure the delegates don't change.
     using (Synchronizer.Lock(this)) {
         if (this.m_InkDeletedDelegate != null)
         {
             this.m_InkDeletedDelegate(this, args);
         }
     }
 }
Ejemplo n.º 11
0
            private void RemoveInk()
            {
                using (Synchronizer.Lock(this)) {
                    // Collect all of the strokes we're supposed to delete.
                    using (Synchronizer.Lock(this.m_Watcher.m_InkSheet.Ink.Strokes.SyncRoot)) {
                        Strokes deleting = this.m_Watcher.m_InkSheet.Ink.CreateStrokes();
                        foreach (Stroke stroke in this.m_Watcher.m_InkSheet.Ink.Strokes)
                        {
                            if (stroke.ExtendedProperties.DoesPropertyExist(StrokeIdExtendedProperty))
                            {
                                if (Array.IndexOf(this.m_StrokesToRemove, stroke.ExtendedProperties[StrokeIdExtendedProperty].Data) >= 0)
                                {
                                    deleting.Add(stroke);
                                }
                            }
                        }

                        // It's possible that some of the strokes have been deleted elsewhere.
                        // But this shouldn't happen because doing so should have caused an InkUndoer to be
                        // pushed onto the Undo stack.  So, for now, this check is "merely" a Debug.Assert.
                        // TODO: Decide whether this should be an error, or at least whether it should
                        //   invalidate the rest of the undo stack.
                        Debug.Assert(deleting.Count == this.m_StrokesToRemove.Length);

                        // Get the stroke Ids so we can make a copy of the ink and fire the OnDeleting and OnDeleted events.
                        int[] ids = new int[deleting.Count];
                        for (int i = 0; i < ids.Length; i++) // Is there a better way to get the array of Ids?
                        {
                            ids[i] = deleting[i].Id;
                        }

                        // Make a copy of the strokes, because if the original ink is later deleted
                        // from the Ink object then it will become unusable.
                        Ink ink = this.m_Watcher.m_InkSheet.Ink.ExtractStrokes(deleting, ExtractFlags.CopyFromOriginal);
                        this.m_StrokesToAdd    = ink.Strokes;
                        this.m_StrokesToRemove = null;

                        // Create the event arguments and add them to the ignore list so the
                        // InkSheetUndoService won't create an InkUndoer for this change.
                        StrokesEventArgs args = new StrokesEventArgs(ids);
                        using (Synchronizer.Lock(this.m_Watcher.m_Ignore.SyncRoot)) {
                            this.m_Watcher.m_Ignore.Add(args);
                        }

                        // Actually delete the ink, firing the appropriate events on the InkSheetModel.
                        this.m_Watcher.m_InkSheet.OnInkDeleting(args);
                        this.m_Watcher.m_InkSheet.Ink.DeleteStrokes(deleting);
                        this.m_Watcher.m_InkSheet.OnInkDeleted(args);
                    }
                }
            }
Ejemplo n.º 12
0
        private void HandleInkAdded(object sender, StrokesEventArgs e)
        {
            using(Synchronizer.Lock(this.m_Ignore.SyncRoot)) {
                if(this.m_Ignore.Contains(e)) {
                    this.m_Ignore.Remove(e);
                    return;
                }
            }

            // Make a copy of the strokes that were added.  This must be done immediately
            // or the strokes might not exist by the time we need them.
            Strokes strokes = this.m_InkSheet.Ink.CreateStrokes(e.StrokeIds);
            SetStrokeIds(strokes);
            Ink ink = this.m_InkSheet.Ink.ExtractStrokes(strokes, ExtractFlags.CopyFromOriginal);
            this.m_EventQueue.Post(delegate() {
                this.m_HandleInkChangedDelegate(sender, ink.Strokes, true);
            });
        }
Ejemplo n.º 13
0
        private void HandleInkDeleting(object sender, StrokesEventArgs e)
        {
            using (Synchronizer.Lock(this.m_Ignore.SyncRoot)) {
                if (this.m_Ignore.Contains(e))
                {
                    this.m_Ignore.Remove(e);
                    return;
                }
            }

            // Make a copy of the strokes that were removed.  This must be done immediately
            // or the strokes _will_not_ exist by the time we need them.
            Strokes strokes = this.m_InkSheet.Ink.CreateStrokes(e.StrokeIds);

            SetStrokeIds(strokes);
            Ink ink = this.m_InkSheet.Ink.ExtractStrokes(strokes, ExtractFlags.CopyFromOriginal);

            this.m_EventQueue.Post(delegate() {
                this.m_HandleInkChangedDelegate(sender, ink.Strokes, false);
            });
        }
Ejemplo n.º 14
0
        private void HandleInkAdded(object sender, StrokesEventArgs e)
        {
            // We must extract the added ink immediately so it can't be deleted before the
            // message is sent on another thread.

            Ink extracted;
            using( Synchronizer.Lock(this.m_SourceSheet.Ink.Strokes.SyncRoot) ) {
                using(Strokes strokes = this.m_SourceSheet.Ink.CreateStrokes(e.StrokeIds)) {
                    // Ensure that each stroke has a Guid which will uniquely identify it on the remote side.
                    foreach(Stroke stroke in strokes) {
                        if(!stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                            stroke.ExtendedProperties.Add(InkSheetMessage.StrokeIdExtendedProperty, Guid.NewGuid().ToString());
                    }

                    extracted = this.m_SourceSheet.Ink.ExtractStrokes(strokes, ExtractFlags.CopyFromOriginal);
                }
            }

            this.m_Sender.Post(delegate() {
                this.HandleInkAddedHelper(extracted);
            });
        }
Ejemplo n.º 15
0
/*
 *      private void SendExistingInk(Group receivers) {
 *          Ink extracted;
 *          using(Synchronizer.Lock(this.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 this.m_Sheet.Ink.Strokes) {
 *                  if(!stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
 *                      stroke.ExtendedProperties.Add(InkSheetMessage.StrokeIdExtendedProperty, Guid.NewGuid().ToString());
 *              }
 *
 *              // Extract all of the strokes.
 *              extracted = this.m_Sheet.Ink.ExtractStrokes(this.m_Sheet.Ink.Strokes, ExtractFlags.CopyFromOriginal);
 *          }
 *
 *          // Send a message as if the already-existing ink was just added to the sheet.
 *          this.Sender.Post(delegate() {
 *              this.HandleInkAddedHelper(extracted, receivers);
 *          });
 *      }
 */
        /// <summary>
        /// Handle when ink is added to the slide
        /// </summary>
        /// <param name="sender">The sender of this event</param>
        /// <param name="e">The parameters for this event</param>
        private void HandleInkAdded(object sender, StrokesEventArgs e)
        {
            // Always copy all strokes for now...
            Ink extracted;

            using (Synchronizer.Lock(this.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 this.m_Sheet.Ink.Strokes)
                {
                    if (!stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                    {
                        stroke.ExtendedProperties.Add(InkSheetMessage.StrokeIdExtendedProperty, Guid.NewGuid().ToString());
                    }
                }

                // Extract all of the strokes.
                extracted = this.m_Sheet.Ink.ExtractStrokes(this.m_Sheet.Ink.Strokes, ExtractFlags.CopyFromOriginal);
            }

            // Send a message as if the already-existing ink was just added to the sheet.
            this.Sender.Post(delegate() {
                this.HandleInkAddedHelper(extracted);
            });
        }
Ejemplo n.º 16
0
 protected virtual void HandleInkDeleted(object sender, StrokesEventArgs e)
 {
     using (Synchronizer.Lock(this.m_Sheet.SyncRoot)) {
         this.SlideDisplay.Invalidate(this.m_Sheet.Bounds);
     }
 }
Ejemplo n.º 17
0
            /// <summary>
            /// Handle the button being clicked
            /// </summary>
            /// <param name="args">The event args</param>
            protected override void OnClick( EventArgs args )
            {
                if( this.m_Slide == null ) return;

                using( Synchronizer.Lock( this.m_Slide.SyncRoot ) ) {

                    InkSheetModel inks = null;

                    // TODO: This code is duplicated in InkSheetAdapter.  Extract to a "ActiveInkAnnotationSheet" property of the SlideModel.
                    // Find the *top-most* *local* InkSheetModel in the annotation layer.
                    for (int i = m_Slide.AnnotationSheets.Count - 1; i >= 0; i--) {
                        SheetModel sheet = m_Slide.AnnotationSheets[i];
                        if ((sheet.Disposition & SheetDisposition.Remote) != 0)
                            continue;

                        if (sheet is InkSheetModel) {
                            inks = ((InkSheetModel)sheet);
                        }
                        //else if (sheet is EditableSheetModel ) {
                        //    ///only erase the sheet model if the user made it
                        //    ///(i.e. it is editable. If this is sent from another
                        //    ///person, don't erase it).
                        //    EditableSheetModel edit_sheet = (EditableSheetModel)sheet;
                        //    if (edit_sheet.IsEditable) {
                        //        m_Slide.AnnotationSheets.Remove(sheet);
                        //    }
                        //}
                    }

                    if (inks != null) {
                        using (Synchronizer.Lock(inks.SyncRoot)) {
                            Strokes strokes = inks.Ink.Strokes;
                            using (Synchronizer.Lock(strokes.SyncRoot)) {
                                int[] ids = new int[inks.Ink.Strokes.Count];
                                for (int j = 0; j < strokes.Count; j++)
                                    ids[j] = strokes[j].Id;

                                StrokesEventArgs sea = new StrokesEventArgs(ids);
                                inks.OnInkDeleting(sea);
                                inks.Ink.DeleteStrokes();
                                inks.OnInkDeleted(sea);
                            }
                        }

                    }
                }

                base.OnClick( args );
            }
Ejemplo n.º 18
0
 public void OnInkDeleting(StrokesEventArgs args)
 {
     // The default event add/remove methods lock(this), so we need to do the same to make sure the delegates don't change.
     using(Synchronizer.Lock(this)) {
         if(this.m_InkDeletingDelegate != null) {
             this.m_InkDeletingDelegate(this, args);
         }
     }
 }
Ejemplo n.º 19
0
    private void inkoverlay_Ink_InkAdded(object sender, StrokesEventArgs e)
    {
        // This event fires on a background thread, which creates a race condition
        // when you access neweststrokeids.
        // Return to the UI thread before continuing.
        if (this.InvokeRequired)
        {
            this.Invoke(
                new StrokesEventHandler(inkoverlay_Ink_InkAdded),
                new object[] { sender, e });
            return;
        }

        dbg.WriteLine("----- inkoverlay_Ink_InkAdded -----");

        try // To prevent exceptions from propagating back to ink runtime.
        {
            neweststrokeids = e.StrokeIds;
        }
        catch (Exception ex)
        {
            // Log the error.
            Global.HandleThreadException(this, new System.Threading.ThreadExceptionEventArgs(ex));
        }
    }
Ejemplo n.º 20
0
            private void AddInk()
            {
                using(Synchronizer.Lock(this)) {
                    // Create an array of stroke Ids in order to fire the InkAdded event later.
                    int[] ids = new int[this.m_StrokesToAdd.Count];

                    using (Synchronizer.Lock(this.m_Watcher.m_InkSheet.Ink.Strokes.SyncRoot)) {
                        for (int i = 0; i < ids.Length; i++) {
                            Stroke stroke = this.m_StrokesToAdd[i];

                            // The stroke probably has no association with the current Ink object.
                            // Therefore, we have to recreate it by copying the raw packet data.
                            // This first requires recreating the TabletPropertyDescriptionCollection,
                            // which, for some stupid reason, must be done manually for lack of a better API.
                            TabletPropertyDescriptionCollection properties = new TabletPropertyDescriptionCollection();
                            foreach (Guid property in stroke.PacketDescription)
                                properties.Add(new TabletPropertyDescription(property, stroke.GetPacketDescriptionPropertyMetrics(property)));

                            // Create a new stroke from the raw packet data.
                            Stroke created = this.m_Watcher.m_InkSheet.Ink.CreateStroke(stroke.GetPacketData(), properties);

                            // Copy the DrawingAttributes and all application data
                            // (especially the StrokesIdExtendedProperty) to the new stroke.
                            created.DrawingAttributes = stroke.DrawingAttributes;
                            foreach (ExtendedProperty prop in stroke.ExtendedProperties)
                                created.ExtendedProperties.Add(prop.Id, prop.Data);

                            // Get the new stroke's Id so we can fire the InkAdded event.
                            ids[i] = created.Id;
                        }

                        // If the added strokes don't yet have StrokeIdExtendedProperty properties,
                        // create new Guids for them.  Regardless, set this.m_StrokesToRemove
                        // to the list of stroke Guids.
                        this.UpdateAndSetStrokesToRemoveIds(this.m_StrokesToAdd);

                        // Then, unset this.m_StrokesToAdd since they're already added.
                        this.m_StrokesToAdd = null;
                    }

                    // Create the event arguments and add them to the ignore list so the
                    // InkSheetUndoService won't create an InkUndoer for this change.
                    StrokesEventArgs args = new StrokesEventArgs(ids);
                    using(Synchronizer.Lock(this.m_Watcher.m_Ignore.SyncRoot)) {
                        this.m_Watcher.m_Ignore.Add(args);
                    }

                    // Finally fire the appropriate InkAdded event from the InkSheetModel.
                    this.m_Watcher.m_InkSheet.OnInkAdded(args);
                }
            }
Ejemplo n.º 21
0
        protected override bool UpdateTarget(ReceiveContext context)
        {
            bool update = base.UpdateTarget(context);

            InkSheetModel sheet = this.Target as InkSheetModel;
            if(sheet == null)
                return update;

            ArrayList deleting = new ArrayList(this.StrokeIds.Length);

            foreach(Stroke existing in sheet.Ink.Strokes) {
                if(existing.ExtendedProperties.DoesPropertyExist(StrokeIdExtendedProperty)) {
                    if(Array.IndexOf(this.StrokeIds, existing.ExtendedProperties[StrokeIdExtendedProperty].Data) >= 0) {
                        deleting.Add(existing.Id);
                    }
                }
            }

            int[] ids = ((int[]) deleting.ToArray(typeof(int)));
            using(Strokes strokes = sheet.Ink.CreateStrokes(ids)) {
                StrokesEventArgs args = new StrokesEventArgs(ids);
                sheet.OnInkDeleting(args);
                sheet.Ink.DeleteStrokes(strokes);
                sheet.OnInkDeleted(args);
            }

            return update;
        }
Ejemplo n.º 22
0
        private void LoadInkIntoTarget(InkSheetModel sheet, byte[] saved, out int[] ids)
        {
            Ink restored = new Ink();
            restored.Load(saved);

            using(Synchronizer.Lock(sheet.Ink.Strokes.SyncRoot)) {
                ids = new int[restored.Strokes.Count];

                for(int i = 0; i < ids.Length; i++) {
                    Stroke stroke = restored.Strokes[i];

                    // Remove any strokes that have the same remote Id as the new one.
                    // Unfortunately, because the InkSheetUndoService cannot preserve stroke referential identity,
                    // we must do a full search each time and cannot simply keep a table.
                    if(stroke.ExtendedProperties.DoesPropertyExist(StrokeIdExtendedProperty)) {
                        object id = stroke.ExtendedProperties[StrokeIdExtendedProperty].Data;
                        foreach(Stroke existing in sheet.Ink.Strokes) {
                            if(existing.ExtendedProperties.DoesPropertyExist(StrokeIdExtendedProperty)) {
                                if(id.Equals(existing.ExtendedProperties[StrokeIdExtendedProperty].Data)) {
                                    StrokesEventArgs args = new StrokesEventArgs(new int[] { existing.Id });
                                    sheet.OnInkDeleting(args);
                                    sheet.Ink.DeleteStroke(existing);
                                    sheet.OnInkDeleted(args);
                                }
                            }
                        }
                    }

                    // The stroke has no association with the current Ink object.
                    // Therefore, we have to recreate it by copying the raw packet data.
                    // This first requires recreating the TabletPropertyDescriptionCollection,
                    // which, for some stupid reason, must be done manually for lack of a better API.
                    TabletPropertyDescriptionCollection properties = new TabletPropertyDescriptionCollection();
                    foreach(Guid property in stroke.PacketDescription)
                        properties.Add(new TabletPropertyDescription(property, stroke.GetPacketDescriptionPropertyMetrics(property)));

                    // Create a new stroke from the raw packet data.
                    Stroke created = sheet.Ink.CreateStroke(stroke.GetPacketData(), properties);

                    // Copy the DrawingAttributes and all application data
                    // (especially the StrokesIdExtendedProperty) to the new stroke.
                    created.DrawingAttributes = stroke.DrawingAttributes;
                    foreach(ExtendedProperty prop in stroke.ExtendedProperties)
                        created.ExtendedProperties.Add(prop.Id, prop.Data);

                    ids[i] = created.Id;

                    if (ViewerStateModel.NonStandardDpi)
                        created.Transform(ViewerStateModel.DpiNormalizationReceiveMatrix);

                }
            }
        }
Ejemplo n.º 23
0
 protected virtual void HandleInkDeleted(object sender, StrokesEventArgs e)
 {
     using(Synchronizer.Lock(this.m_Sheet.SyncRoot)) {
         this.SlideDisplay.Invalidate(this.m_Sheet.Bounds);
     }
 }
Ejemplo n.º 24
0
        protected virtual void HandleInkAdded(object sender, StrokesEventArgs e)
        {
            Rectangle invalid = Rectangle.Empty;

            // HACK: It would be much simpler and more efficient to just use
            // Ink.CreateStrokes(e.StrokeIds).GetBoundingBox(), but CreateStrokes has
            // a tendency to throw "ComException HRESULT 0x80040222" (see Bug 726).
            // This hack manually iterates through the strokes looking for the added ones;
            // there doesn't seem to be any way to make this more efficient with a table
            // lookup, at least not with the APIs exposed by Microsoft.Ink.Ink.

            using (Synchronizer.Lock(this.m_Sheet.Ink.Strokes.SyncRoot)) {
                foreach (Stroke stroke in this.m_Sheet.Ink.Strokes) {
                    if (Array.IndexOf<int>(e.StrokeIds, stroke.Id) >= 0) {
                        invalid = (invalid == Rectangle.Empty)
                            ? stroke.GetBoundingBox()
                            : Rectangle.Union(invalid, stroke.GetBoundingBox());
                    }
                }
            }

            this.InvalidateInkSpaceRectangle(invalid);
        }
Ejemplo n.º 25
0
            private void RemoveInk()
            {
                using (Synchronizer.Lock(this)) {
                    // Collect all of the strokes we're supposed to delete.
                    using (Synchronizer.Lock(this.m_Watcher.m_InkSheet.Ink.Strokes.SyncRoot)) {
                        Strokes deleting = this.m_Watcher.m_InkSheet.Ink.CreateStrokes();
                        foreach (Stroke stroke in this.m_Watcher.m_InkSheet.Ink.Strokes)
                            if (stroke.ExtendedProperties.DoesPropertyExist(StrokeIdExtendedProperty))
                                if (Array.IndexOf(this.m_StrokesToRemove, stroke.ExtendedProperties[StrokeIdExtendedProperty].Data) >= 0)
                                    deleting.Add(stroke);

                        // It's possible that some of the strokes have been deleted elsewhere.
                        // But this shouldn't happen because doing so should have caused an InkUndoer to be
                        // pushed onto the Undo stack.  So, for now, this check is "merely" a Debug.Assert.
                        // TODO: Decide whether this should be an error, or at least whether it should
                        //   invalidate the rest of the undo stack.
                        Debug.Assert(deleting.Count == this.m_StrokesToRemove.Length);

                        // Get the stroke Ids so we can make a copy of the ink and fire the OnDeleting and OnDeleted events.
                        int[] ids = new int[deleting.Count];
                        for (int i = 0; i < ids.Length; i++) // Is there a better way to get the array of Ids?
                            ids[i] = deleting[i].Id;

                        // Make a copy of the strokes, because if the original ink is later deleted
                        // from the Ink object then it will become unusable.
                        Ink ink = this.m_Watcher.m_InkSheet.Ink.ExtractStrokes(deleting, ExtractFlags.CopyFromOriginal);
                        this.m_StrokesToAdd = ink.Strokes;
                        this.m_StrokesToRemove = null;

                        // Create the event arguments and add them to the ignore list so the
                        // InkSheetUndoService won't create an InkUndoer for this change.
                        StrokesEventArgs args = new StrokesEventArgs(ids);
                        using (Synchronizer.Lock(this.m_Watcher.m_Ignore.SyncRoot)) {
                            this.m_Watcher.m_Ignore.Add(args);
                        }

                        // Actually delete the ink, firing the appropriate events on the InkSheetModel.
                        this.m_Watcher.m_InkSheet.OnInkDeleting(args);
                        this.m_Watcher.m_InkSheet.Ink.DeleteStrokes(deleting);
                        this.m_Watcher.m_InkSheet.OnInkDeleted(args);
                    }
                }
            }
        private void HandleInkDeleting(object sender, StrokesEventArgs e)
        {
            // We must extract the deleted ink immediately, or else it won't be around
            // by the time we process the event on another thread.
            // Compile a list of all of the Guids which identify the strokes to be removed.
            // The Guids are created by HandleInkAdded above.
            // If a stroke does not have a Guid, then it was not broadcast and therefore
            // we don't need to worry about telling the remote clients to remove it.
            string[] ids;
            using(Synchronizer.Lock(this.m_Sheet.Ink.Strokes.SyncRoot)) {
                int[] strokeIds = e.StrokeIds;
                ArrayList guids = new ArrayList(strokeIds.Length);
                using(Strokes strokes = this.m_Sheet.Ink.CreateStrokes(strokeIds)) {
                    foreach(Stroke stroke in strokes) {
                        if(stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                            guids.Add(stroke.ExtendedProperties[InkSheetMessage.StrokeIdExtendedProperty].Data);
                    }
                }
                ids = ((string[]) guids.ToArray(typeof(string)));
            }

            if (ids.Length > 0)
                this.Sender.Post(delegate() {
                    this.HandleInkDeletingHelper(ids);
                });
        }
Ejemplo n.º 27
0
        /*
        private void SendExistingInk(Group receivers) {
            Ink extracted;
            using(Synchronizer.Lock(this.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 this.m_Sheet.Ink.Strokes) {
                    if(!stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                        stroke.ExtendedProperties.Add(InkSheetMessage.StrokeIdExtendedProperty, Guid.NewGuid().ToString());
                }

                // Extract all of the strokes.
                extracted = this.m_Sheet.Ink.ExtractStrokes(this.m_Sheet.Ink.Strokes, ExtractFlags.CopyFromOriginal);
            }

            // Send a message as if the already-existing ink was just added to the sheet.
            this.Sender.Post(delegate() {
                this.HandleInkAddedHelper(extracted, receivers);
            });
        }
        */
        /// <summary>
        /// Handle when ink is added to the slide
        /// </summary>
        /// <param name="sender">The sender of this event</param>
        /// <param name="e">The parameters for this event</param>
        private void HandleInkAdded(object sender, StrokesEventArgs e)
        {
            // Always copy all strokes for now...
            Ink extracted;
            using (Synchronizer.Lock(this.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 this.m_Sheet.Ink.Strokes) {
                    if (!stroke.ExtendedProperties.DoesPropertyExist(InkSheetMessage.StrokeIdExtendedProperty))
                        stroke.ExtendedProperties.Add(InkSheetMessage.StrokeIdExtendedProperty, Guid.NewGuid().ToString());
                }

                // Extract all of the strokes.
                extracted = this.m_Sheet.Ink.ExtractStrokes(this.m_Sheet.Ink.Strokes, ExtractFlags.CopyFromOriginal);
            }

            // Send a message as if the already-existing ink was just added to the sheet.
            this.Sender.Post(delegate() {
                this.HandleInkAddedHelper(extracted);
            });
        }