Beispiel #1
0
 internal /*?? protected */ virtual void ChangeModelState(ModelChangedEventArgs e, bool undo)
 {
     if ((int)e.Change > (int)ModelChange.Property)
     {
         ModelHelper.Error((IDiagramModel)this, "ChangeModelState did not handle ModelChange." + e.Change.ToString());
     }
 }
Beispiel #2
0
 /// <summary>
 /// Raise the <see cref="PropertyChanged"/> event.
 /// </summary>
 /// <param name="e"></param>
 public virtual void OnPropertyChanged(ModelChangedEventArgs e)
 {
     if (this.PropertyChanged != null)
     {
         this.PropertyChanged(this, e);
     }
 }
Beispiel #3
0
 /// <summary>
 /// This is called during undo or redo to effect state changes to this model.
 /// </summary>
 /// <param name="e">an edit describing the change to be performed</param>
 /// <param name="undo">true if undoing; false if redoing</param>
 /// <remarks>
 /// <para>
 /// This is called by <see cref="ChangeModel"/>.
 /// You will want to override this method to handle properties that you
 /// have added to your derived model class.
 /// </para>
 /// <para>
 /// By default this uses reflection to set the <see cref="PropertyChangedEventArgs.PropertyName"/>
 /// to the <see cref="ModelChangedEventArgs.OldValue"/> or the
 /// <see cref="ModelChangedEventArgs.NewValue"/>, depending on the value of <paramref name="undo"/>.
 /// </para>
 /// <para>
 /// If you override this method, remember to call the base method for all
 /// cases that your override method does not handle.
 /// </para>
 /// </remarks>
 protected virtual void ChangeModelValue(ModelChangedEventArgs e, bool undo)
 {
     if (e == null)
     {
         return;
     }
     if (e.PropertyName == "Name")
     {
         this.Name = (String)e.GetValue(undo);
     }
     else if (e.PropertyName == "DataFormat")
     {
         this.DataFormat = (String)e.GetValue(undo);
     }
     else if (e.PropertyName == "Modifiable")
     {
         this.Modifiable = (bool)e.GetValue(undo);
     }
     else if (ModelHelper.SetProperty(e.PropertyName, this, e.GetValue(undo)))
     {
         return; // successful set of model property
     }
     else
     {
         ModelHelper.Error((IDiagramModel)this, "Override ChangeModelValue to handle ModelChangedEventArgs of a model property: " + e.ToString());
     }
 }
Beispiel #4
0
        /// <summary>
        /// This is called during an Undo or a Redo to actually make state
        /// changes to this model or to this model's data.
        /// </summary>
        /// <param name="e">an edit describing the change to be performed</param>
        /// <param name="undo">true if undoing; false if redoing</param>
        /// <remarks>
        /// <para>
        /// When <paramref name="e"/>'s <see cref="ModelChangedEventArgs.Change"/>
        /// value is <see cref="ModelChange.Property"/>,
        /// this calls <see cref="ChangeModelValue"/>
        /// if the <see cref="ModelChangedEventArgs.Data"/> is this model,
        /// or else it calls <see cref="ChangeDataValue"/>.
        /// </para>
        /// <para>
        /// This method handles all other <see cref="ModelChange"/> cases,
        /// since they are all predefined.
        /// </para>
        /// </remarks>
        public void ChangeModel(ModelChangedEventArgs e, bool undo)
        {
            if (e == null)
            {
                return;
            }
            bool old = this.IsChangingModel;

            //ModelHelper.Trace((undo ? "undo: " : "redo: ") + e.ToString());
            try {
                this.IsChangingModel = true;
                if (e.Change == ModelChange.Property)
                {
                    Object data = e.Data;
                    if (data == null)
                    {
                        data = this;
                    }
                    if (data == this) // changes to programmer defined properties on the model
                    {
                        ChangeModelValue(e, undo);
                    }
                    else // changes to some data inside the model
                    {
                        ChangeDataValue(e, undo);
                    }
                }
                else
                {
                    ChangeModelState(e, undo);
                }
            } finally {
                this.IsChangingModel = old;
            }
        }
Beispiel #5
0
        /// <summary>
        /// Create an <see cref="IUndoableEdit"/> for a <see cref="IDiagramModel.Changed"/> event.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks>
        /// This calls <see cref="SkipEvent"/> if for some reason we should ignore
        /// the <paramref name="e"/>.
        /// This then creates a <see cref="ModelChangedEventArgs"/> and adds it to the
        /// <see cref="CurrentEdit"/>, a <see cref="UndoManager.CompoundEdit"/> which it allocates
        /// if needed.
        /// This method always ignores all Changed events while we are performing an
        /// <see cref="Undo"/> or <see cref="Redo"/>.
        /// </remarks>
        public virtual void HandleModelChanged(Object sender, ModelChangedEventArgs e)
        {
            // changes caused by performing an undo or redo should be ignored!
            if (this.IsUndoingRedoing)
            {
                return;
            }

            if (!SkipEvent(e))
            {
                CompoundEdit cedit = this.CurrentEdit;
                //ModelHelper.Trace(this.TransactionLevel, e.ToString());
                if (cedit == null)
                {
                    cedit            = new CompoundEdit();
                    this.CurrentEdit = cedit;
                }

                // make a copy of the event to save as an edit in the list
                ModelChangedEventArgs edit = new ModelChangedEventArgs(e);
                cedit.Edits.Add(edit);
                if (this.ChecksTransactionLevel && this.TransactionLevel <= 0)
                {
                    ModelHelper.Trace("Change not within a transaction: " + edit.ToString());
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Raise a <see cref="Changed"/> event, given before and after values for a particular property.
        /// </summary>
        /// <param name="propname">a property name</param>
        /// <param name="data">the object whose property has just changed</param>
        /// <param name="oldval">the previous value for the property</param>
        /// <param name="newval">the new value for the property</param>
        /// <remarks>
        /// This is the mostly commonly used way to notify about changes to the model or to the model's data.
        /// </remarks>
        /// <seealso cref="RaiseChanged(ModelChangedEventArgs)"/>
        /// <seealso cref="RaisePropertyChanged(String, Object, Object, Object, Object, Object)"/>
        public void RaisePropertyChanged(String propname, Object data, Object oldval, Object newval)
        {
            ModelChangedEventArgs e = new ModelChangedEventArgs(propname, data, oldval, newval);

            e.Model  = (IDiagramModel)this;
            e.Change = ModelChange.Property;
            OnChanged(e);
        }
Beispiel #7
0
 /// <summary>
 /// This predicate is responsible for deciding if a <see cref="ModelChangedEventArgs"/>
 /// is not interesting enough to be recorded.
 /// </summary>
 /// <param name="evt"></param>
 /// <returns>normally false, which causes the given event to be remembered;
 /// but true for negative valued enumerations of <see cref="ModelChange"/>.</returns>
 /// <remarks>
 /// </remarks>
 protected virtual bool SkipEvent(ModelChangedEventArgs evt)
 {
     if (evt == null)
     {
         return(true);
     }
     return((int)evt.Change < (int)ModelChange.Property);
 }
Beispiel #8
0
 /// <summary>
 /// This method implements the <see cref="IChangeDataValue"/> interface,
 /// used to perform state changes for undo and redo.
 /// </summary>
 /// <param name="e">an edit describing the change to be performed</param>
 /// <param name="undo">true if undoing; false if redoing</param>
 /// <remarks>
 /// Unless you override this method to explicitly handle each property that you define,
 /// this implementation uses reflection to set the property.
 /// </remarks>
 public virtual void ChangeDataValue(ModelChangedEventArgs e, bool undo)
 {
     if (e == null)
     {
         return;
     }
     if (e.PropertyName == "Location")
     {
         this.Location = (Point)e.GetValue(undo);
     }
     else if (e.PropertyName == "Text")
     {
         this.Text = (String)e.GetValue(undo);
     }
     else if (e.PropertyName == "Key")
     {
         this.Key = (NodeKey)e.GetValue(undo);
     }
     else if (e.PropertyName == "FromKeys")
     {
         this.FromKeys = (IList <NodeKey>)e.GetValue(undo);
     }
     else if (e.PropertyName == "ToKeys")
     {
         this.ToKeys = (IList <NodeKey>)e.GetValue(undo);
     }
     else if (e.PropertyName == "IsSubGraph")
     {
         this.IsSubGraph = (bool)e.GetValue(undo);
     }
     else if (e.PropertyName == "IsSubGraphExpanded")
     {
         this.IsSubGraphExpanded = (bool)e.GetValue(undo);
     }
     else if (e.PropertyName == "WasSubGraphExpanded")
     {
         this.WasSubGraphExpanded = (bool)e.GetValue(undo);
     }
     else if (e.PropertyName == "SubGraphKey")
     {
         this.SubGraphKey = (NodeKey)e.GetValue(undo);
     }
     else if (e.PropertyName == "MemberKeys")
     {
         this.MemberKeys = (IList <NodeKey>)e.GetValue(undo);
     }
     else if (e.PropertyName == "Category")
     {
         this.Category = (String)e.GetValue(undo);
     }
     else if (e.Change == ModelChange.Property)
     {
         if (!ModelHelper.SetProperty(e.PropertyName, e.Data, e.GetValue(undo)))
         {
             ModelHelper.Error("ERROR: Unrecognized property name: " + e.PropertyName != null ? e.PropertyName : "(noname)" + " in GraphModelNodeData.ChangeDataValue");
         }
     }
 }
Beispiel #9
0
        private void RaiseChanged(IDiagramModel model, ModelChange change, Object data, Object oldval, Object newval)
        {
            ModelChangedEventArgs e = new ModelChangedEventArgs();

            e.Model    = model;
            e.Change   = change;
            e.Data     = data;
            e.OldValue = oldval;
            e.NewValue = newval;
            model.RaiseChanged(e);
        }
Beispiel #10
0
        internal void RaiseModelChanged(ModelChange change, Object data, Object oldval, Object newval)
        {
            ModelChangedEventArgs e = new ModelChangedEventArgs();

            e.Model    = (IDiagramModel)this;
            e.Change   = change;
            e.Data     = data;
            e.OldValue = oldval;
            e.NewValue = newval;
            OnChanged(e);
        }
    /// <summary>
    /// This is basically a "copy constructor", making a copy of the given <see cref="ModelChangedEventArgs"/>.
    /// </summary>
    /// <param name="e"></param>
    public ModelChangedEventArgs(ModelChangedEventArgs e) : base(e.PropertyName) {  // "copy constructor"
      if (e != null) {
        this.Model = e.Model;
        this.Change = e.Change;
        this.Data = e.Data;
        this.OldValue = e.OldValue;
        this.OldParam = e.OldParam;
        this.NewValue = e.NewValue;
        this.NewParam = e.NewParam;
      }

      //if (this.Model != null) {
      //  this.Model.CopyOldValueForUndo(this);  //?? optimize memory usage
      //  this.Model.CopyNewValueForRedo(this);
      //}
    }
        /// <summary>
        /// This is basically a "copy constructor", making a copy of the given <see cref="ModelChangedEventArgs"/>.
        /// </summary>
        /// <param name="e"></param>
        public ModelChangedEventArgs(ModelChangedEventArgs e) : base(e.PropertyName) // "copy constructor"
        {
            if (e != null)
            {
                this.Model    = e.Model;
                this.Change   = e.Change;
                this.Data     = e.Data;
                this.OldValue = e.OldValue;
                this.OldParam = e.OldParam;
                this.NewValue = e.NewValue;
                this.NewParam = e.NewParam;
            }

            //if (this.Model != null) {
            //  this.Model.CopyOldValueForUndo(this);  //?? optimize memory usage
            //  this.Model.CopyNewValueForRedo(this);
            //}
        }
Beispiel #13
0
        /// <summary>
        /// This is called during undo or redo to effect state changes to model data.
        /// </summary>
        /// <param name="e">an edit describing the change to be performed</param>
        /// <param name="undo">true if undoing; false if redoing</param>
        /// <remarks>
        /// <para>
        /// This is called by <see cref="ChangeModel"/>.
        /// You will want to override this method to handle properties that you
        /// have added to your model data classes.
        /// Or you can have your data classes implement <see cref="IChangeDataValue"/>
        /// to achieve the same effect.
        /// </para>
        /// <para>
        /// By default this just calls <see cref="IChangeDataValue.ChangeDataValue"/>
        /// if the <see cref="ModelChangedEventArgs.Data"/> implements <see cref="IChangeDataValue"/>.
        /// Otherwise this uses reflection to set the <see cref="PropertyChangedEventArgs.PropertyName"/>
        /// to the <see cref="ModelChangedEventArgs.OldValue"/> or the
        /// <see cref="ModelChangedEventArgs.NewValue"/>, depending on the value of <paramref name="undo"/>.
        /// </para>
        /// <para>
        /// If you override this method, remember to call the base method for all
        /// cases that your override method does not handle.
        /// </para>
        /// </remarks>
        protected virtual void ChangeDataValue(ModelChangedEventArgs e, bool undo)
        {
            if (e == null)
            {
                return;
            }
            Object           data       = e.Data;
            IChangeDataValue changeable = data as IChangeDataValue;

            if (changeable != null)
            {
                changeable.ChangeDataValue(e, undo);
            }
            else if (ModelHelper.SetProperty(e.PropertyName, data, e.GetValue(undo)))
            {
                return; // successful set of data property
            }
            else
            {
                ModelHelper.Error((IDiagramModel)this, "Override ChangeDataValue to handle ModelChangedEventArgs.Data, or have data implement IChangeDataValue: " + data.ToString());
            }
        }
Beispiel #14
0
        /// <summary>
        /// Given an <see cref="IUndoableEdit"/> return an edited object
        /// that represents what was modified.
        /// </summary>
        /// <param name="edit">
        /// an <see cref="IUndoableEdit"/>,
        /// usually either a <see cref="ModelChangedEventArgs"/> or a <see cref="CompoundEdit"/>
        /// </param>
        /// <returns>
        /// typically a <see cref="Node"/> or a <see cref="Link"/>,
        /// but this may be null if there is no such object,
        /// perhaps because a model property was modified,
        /// or because there were no real edits in the argument <paramref name="edit"/>.
        /// </returns>
        public virtual Object FindPrimaryObject(IUndoableEdit edit)
        {
            ModelChangedEventArgs ea = edit as ModelChangedEventArgs;

            if (ea != null)
            {
                return(ea.Data);
            }
            CompoundEdit ce = edit as CompoundEdit;

            if (ce != null)
            {
                foreach (IUndoableEdit e in ce.Edits)
                {
                    Object data = FindPrimaryObject(e);
                    if (data != null)
                    {
                        return(data);
                    }
                }
            }
            return(null);
        }
Beispiel #15
0
        /// <summary>
        /// Raises the <see cref="Changed"/> event.
        /// </summary>
        /// <param name="e">an edit describing the change that just happened</param>
        /// <remarks>
        /// If you override this method, be sure to call the base method first.
        /// </remarks>
        protected virtual void OnChanged(ModelChangedEventArgs e)
        {
            if (e == null)
            {
                return;
            }
            if (_ChangedEvent != null)
            {
                _ChangedEvent(this, e);
            }

            if (!this.SkipsUndoManager && !this.Initializing)
            {
                UndoManager um = this.UndoManager;
                if (um != null)
                {
                    um.HandleModelChanged(this, e);
                }
                if (((int)e.Change) >= (int)ModelChange.Property)
                {
                    this.IsModified = true;
                }
            }
        }
Beispiel #16
0
 /// <summary>
 /// This is called during undo or redo to effect state changes to model data.
 /// </summary>
 /// <param name="e">an edit describing the change to be performed</param>
 /// <param name="undo">true if undoing; false if redoing</param>
 /// <remarks>
 /// <para>
 /// This is called by <see cref="ChangeModel"/>.
 /// You will want to override this method to handle properties that you
 /// have added to your model data classes.
 /// Or you can have your data classes implement <see cref="IChangeDataValue"/>
 /// to achieve the same effect.
 /// </para>
 /// <para>
 /// By default this just calls <see cref="IChangeDataValue.ChangeDataValue"/>
 /// if the <see cref="ModelChangedEventArgs.Data"/> implements <see cref="IChangeDataValue"/>.
 /// Otherwise this uses reflection to set the <see cref="PropertyChangedEventArgs.PropertyName"/>
 /// to the <see cref="ModelChangedEventArgs.OldValue"/> or the
 /// <see cref="ModelChangedEventArgs.NewValue"/>, depending on the value of <paramref name="undo"/>.
 /// </para>
 /// <para>
 /// If you override this method, remember to call the base method for all
 /// cases that your override method does not handle.
 /// </para>
 /// </remarks>
 protected virtual void ChangeDataValue(ModelChangedEventArgs e, bool undo) {
   if (e == null) return;
   Object data = e.Data;
   IChangeDataValue changeable = data as IChangeDataValue;
   if (changeable != null) {
     changeable.ChangeDataValue(e, undo);
   } else if (ModelHelper.SetProperty(e.PropertyName, data, e.GetValue(undo))) {
     return;  // successful set of data property
   } else {
     ModelHelper.Error((IDiagramModel)this, "Override ChangeDataValue to handle ModelChangedEventArgs.Data, or have data implement IChangeDataValue: " + data.ToString());
   }
 }
Beispiel #17
0
 /// <summary>
 /// This is called during undo or redo to effect state changes to this model.
 /// </summary>
 /// <param name="e">an edit describing the change to be performed</param>
 /// <param name="undo">true if undoing; false if redoing</param>
 /// <remarks>
 /// <para>
 /// This is called by <see cref="ChangeModel"/>.
 /// You will want to override this method to handle properties that you
 /// have added to your derived model class.
 /// </para>
 /// <para>
 /// By default this uses reflection to set the <see cref="PropertyChangedEventArgs.PropertyName"/>
 /// to the <see cref="ModelChangedEventArgs.OldValue"/> or the
 /// <see cref="ModelChangedEventArgs.NewValue"/>, depending on the value of <paramref name="undo"/>.
 /// </para>
 /// <para>
 /// If you override this method, remember to call the base method for all
 /// cases that your override method does not handle.
 /// </para>
 /// </remarks>
 protected virtual void ChangeModelValue(ModelChangedEventArgs e, bool undo) {
   if (e == null) return;
   if (e.PropertyName == "Name") {
     this.Name = (String)e.GetValue(undo);
   } else if (e.PropertyName == "DataFormat") {
     this.DataFormat = (String)e.GetValue(undo);
   } else if (e.PropertyName == "Modifiable") {
     this.Modifiable = (bool)e.GetValue(undo);
   } else if (ModelHelper.SetProperty(e.PropertyName, this, e.GetValue(undo))) {
     return;  // successful set of model property
   } else {
     ModelHelper.Error((IDiagramModel)this, "Override ChangeModelValue to handle ModelChangedEventArgs of a model property: " + e.ToString());
   }
 }
Beispiel #18
0
 /// <summary>
 /// This is called during an Undo or a Redo to actually make state
 /// changes to this model or to this model's data.
 /// </summary>
 /// <param name="e">an edit describing the change to be performed</param>
 /// <param name="undo">true if undoing; false if redoing</param>
 /// <remarks>
 /// <para>
 /// When <paramref name="e"/>'s <see cref="ModelChangedEventArgs.Change"/>
 /// value is <see cref="ModelChange.Property"/>,
 /// this calls <see cref="ChangeModelValue"/>
 /// if the <see cref="ModelChangedEventArgs.Data"/> is this model,
 /// or else it calls <see cref="ChangeDataValue"/>.
 /// </para>
 /// <para>
 /// This method handles all other <see cref="ModelChange"/> cases,
 /// since they are all predefined.
 /// </para>
 /// </remarks>
 public void ChangeModel(ModelChangedEventArgs e, bool undo) {
   if (e == null) return;
   bool old = this.IsChangingModel;
   //ModelHelper.Trace((undo ? "undo: " : "redo: ") + e.ToString());
   try {
     this.IsChangingModel = true;
     if (e.Change == ModelChange.Property) {
       Object data = e.Data;
       if (data == null) data = this;
       if (data == this) {  // changes to programmer defined properties on the model
         ChangeModelValue(e, undo);
       } else {  // changes to some data inside the model
         ChangeDataValue(e, undo);
       }
     } else {
       ChangeModelState(e, undo);
     }
   } finally {
     this.IsChangingModel = old;
   }
 }
Beispiel #19
0
 internal void RaiseModelChanged(ModelChange change, Object data, Object oldval, Object oldparam, Object newval, Object newparam) {
   ModelChangedEventArgs e = new ModelChangedEventArgs();
   e.Model = (IDiagramModel)this;
   e.Change = change;
   e.Data = data;
   e.OldValue = oldval;
   e.OldParam = oldparam;
   e.NewValue = newval;
   e.NewParam = newparam;
   OnChanged(e);
 }
Beispiel #20
0
 /// <summary>
 /// Raise a <see cref="Changed"/> event for a property change.
 /// </summary>
 /// <param name="propname">a property name</param>
 /// <param name="data">the object whose property has just changed</param>
 /// <param name="oldval">the previous value for the property</param>
 /// <param name="oldparam">additional information for the old value</param>
 /// <param name="newval">the new value for the property</param>
 /// <param name="newparam">additional information for the new value</param>
 /// <remarks>
 /// This is not used as frequently as <see cref="RaisePropertyChanged(String, Object, Object, Object)"/>.
 /// Typically the parameter values are used as indexes into the <paramref name="data"/>,
 /// to identify the particular value that was changed.
 /// </remarks>
 /// <seealso cref="RaiseChanged(ModelChangedEventArgs)"/>
 /// <seealso cref="RaisePropertyChanged(String, Object, Object, Object)"/>
 public void RaisePropertyChanged(String propname, Object data, Object oldval, Object oldparam, Object newval, Object newparam) {
   ModelChangedEventArgs e = new ModelChangedEventArgs(propname, data, oldval, newval);
   e.Model = (IDiagramModel)this;
   e.Change = ModelChange.Property;
   e.OldParam = oldparam;
   e.NewParam = newparam;
   OnChanged(e);
 }
Beispiel #21
0
 /// <summary>
 /// Raise a <see cref="Changed"/> event, given a <see cref="ModelChangedEventArgs"/>.
 /// </summary>
 /// <param name="e">an edit describing the change that just happened</param>
 /// <remarks>
 /// This just calls <see cref="OnChanged"/>.
 /// This method is public because it is part of the implementation of <see cref="IDiagramModel"/>.
 /// </remarks>
 public void RaiseChanged(ModelChangedEventArgs e) {
   OnChanged(e);
 }
Beispiel #22
0
 /// <summary>
 /// This predicate is responsible for deciding if a <see cref="ModelChangedEventArgs"/>
 /// is not interesting enough to be recorded.
 /// </summary>
 /// <param name="evt"></param>
 /// <returns>normally false, which causes the given event to be remembered;
 /// but true for negative valued enumerations of <see cref="ModelChange"/>.</returns>
 /// <remarks>
 /// </remarks>
 protected virtual bool SkipEvent(ModelChangedEventArgs evt) {
   if (evt == null) return true;
   return (int)evt.Change < (int)ModelChange.Property;
 }
Beispiel #23
0
    /// <summary>
    /// This is called for each <see cref="Northwoods.GoXam.Model.IDiagramModel.Changed"/> event.
    /// </summary>
    /// <param name="e"></param>
    /// <remarks>
    /// <para>
    /// The implementation of this method and the methods that it calls should not modify the model.
    /// </para>
    /// <para>
    /// For small changes such as the addition or removal of node data from the model,
    /// this calls the <see cref="AddNodeForData"/> or <see cref="RemoveNodeForData"/> method.
    /// </para>
    /// <para>
    /// For changes in link relationships in the model, this calls
    /// <see cref="AddLinkForData(Object, Northwoods.GoXam.Model.IDiagramModel)"/>,
    /// <see cref="AddLinkForData(Object, Object, Northwoods.GoXam.Model.IDiagramModel)"/>,
    /// <see cref="RemoveLinkForData(Object, Northwoods.GoXam.Model.IDiagramModel)"/>, or
    /// <see cref="RemoveLinkForData(Object, Object, Northwoods.GoXam.Model.IDiagramModel)"/>.
    /// </para>
    /// <para>
    /// For more wholescale changes, such as a change in the <see cref="Northwoods.GoXam.Model.IDiagramModel.NodesSource"/>,
    /// this will call <see cref="RebuildNodeElements"/> to discard all existing nodes and links and reconstruct
    /// them using the appropriate (and perhaps changed) data templates.
    /// For widespread changes only involving links, this will call <see cref="RebuildLinkElements"/>.
    /// </para>
    /// </remarks>
    public virtual void OnModelChanged(ModelChangedEventArgs e) {
      if (e == null) return;
      if (e.Change == ModelChange.Property) {
        if (this.UpdatesRouteDataPoints && e.PropertyName == "Points") {
          Link link = FindLinkForData(e.Data, this.Diagram.Model);
          if (link != null && !this.IsUpdatingRouteDataPoints) {
            this.IsUpdatingRouteDataPoints = true;
            IList<Point> pts = e.NewValue as IList<Point>;
            if (pts != null && pts.Count() > 1) {
              link.Route.Points = pts;
            } else {
              link.Route.ClearPoints();
            }
            this.IsUpdatingRouteDataPoints = false;
          }
        }
        return;
      }
      VerifyAccess();
      switch (e.Change) {
        // data properties
        case ModelChange.ReplacedReference:
          if (FindNodeForData(e.OldValue, e.Model) != null) {
            RemoveNodeForData(e.OldValue, e.Model);
          }
          if (FindLinkForData(e.OldValue, e.Model) != null) {
            RemoveLinkForData(e.OldValue, e.Model);
          }
          break;

        // model contents and relationships
        case ModelChange.AddedNode:
          AddNodeForData(e.Data, e.Model);
          break;
        case ModelChange.RemovingNode:
          // called before node data is actually removed from the model,
          // when relationships (e.g. with containing group) are known;
          // but won't be called if Model.NodesSource is changed directly,
          // but will be called if someone calls Model.RemoveNode/DeleteNode
          RemoveNodeForData(e.Data, e.Model);
          break;
        case ModelChange.RemovedNode:
          // called after node data is actually removed from the model,
          // but old node data relationships might already be lost
          RemoveNodeForData(e.Data, e.Model);
          break;
        case ModelChange.ChangedParentNodeKey: {
            IDiagramModel model = e.Model;
            if (model != null) {
              Object child = e.Data;
              if (e.OldValue != null) RemoveLinkForData(model.FindNodeByKey(e.OldValue), child, model);
              if (e.NewValue != null) AddLinkForData(model.FindNodeByKey(e.NewValue), child, model);
            }
            break;
          }
        case ModelChange.AddedFromNodeKey: {
            IDiagramModel model = e.Model;
            if (model != null) {
              AddLinkForData(model.FindNodeByKey(e.NewValue), e.Data, model);
            }
            break;
          }
        case ModelChange.RemovedFromNodeKey: {
            IDiagramModel model = e.Model;
            if (model != null) {
              RemoveLinkForData(model.FindNodeByKey(e.OldValue), e.Data, model);
            }
            break;
          }
        case ModelChange.AddedChildNodeKey:
        case ModelChange.AddedToNodeKey: {
            IDiagramModel model = e.Model;
            if (model != null) {
              AddLinkForData(e.Data, model.FindNodeByKey(e.NewValue), model);
            }
            break;
          }
        case ModelChange.RemovedChildNodeKey:
        case ModelChange.RemovedToNodeKey: {
            IDiagramModel model = e.Model;
            if (model != null) {
              RemoveLinkForData(e.Data, model.FindNodeByKey(e.OldValue), model);
            }
            break;
          }
        case ModelChange.ChangedFromNodeKeys: {
            Object node = e.Data;
            if (node != null) {
              IDiagramModel model = e.Model;
              if (model != null) {
                System.Collections.IEnumerable oldneighborkeys = e.OldValue as System.Collections.IEnumerable;
                System.Collections.IEnumerable newneighborkeys = e.NewValue as System.Collections.IEnumerable;
                if (oldneighborkeys != null) {
                  foreach (Object n in oldneighborkeys) {
                    if (newneighborkeys == null || !ContainsKey(newneighborkeys, n)) {
                      RemoveLinkForData(model.FindNodeByKey(n), node, model);
                    }
                  }
                }
                if (newneighborkeys != null) {
                  foreach (Object n in newneighborkeys) {
                    if (oldneighborkeys == null || !ContainsKey(oldneighborkeys, n)) {
                      AddLinkForData(model.FindNodeByKey(n), node, model);
                    }
                  }
                }
              }
            }
            break;
          }
        case ModelChange.ChangedChildNodeKeys:
        case ModelChange.ChangedToNodeKeys: {
            Object node = e.Data;
            if (node != null) {
              IDiagramModel model = e.Model;
              if (model != null) {
                System.Collections.IEnumerable oldneighborkeys = e.OldValue as System.Collections.IEnumerable;
                System.Collections.IEnumerable newneighborkeys = e.NewValue as System.Collections.IEnumerable;
                if (oldneighborkeys != null && model != null) {
                  foreach (Object n in oldneighborkeys) {
                    if (newneighborkeys == null || !ContainsKey(newneighborkeys, n)) {
                      RemoveLinkForData(node, model.FindNodeByKey(n), model);
                    }
                  }
                }
                if (newneighborkeys != null && model != null) {
                  foreach (Object n in newneighborkeys) {
                    if (oldneighborkeys == null || !ContainsKey(oldneighborkeys, n)) {
                      AddLinkForData(node, model.FindNodeByKey(n), model);
                    }
                  }
                }
              }
            }
            break;
          }
        case ModelChange.ChangedGroupNodeKey: {
            IDiagramModel model = e.Model;
            if (model != null) {
              Node oldsg = FindNodeForData(model.FindNodeByKey(e.OldValue), model);
              if (oldsg != null) {
                oldsg.InvalidateRelationships("GroupNodeChanged");
              }
              Node newsg = FindNodeForData(model.FindNodeByKey(e.NewValue), model);
              if (newsg != null) {
                newsg.InvalidateRelationships("GroupNodeChanged");
                newsg.SortZOrder();
              }
              Node node = FindNodeForData(e.Data, model);
              if (node != null) {
                foreach (Link l in node.LinksConnected) UpdateCachedMembership(model, l);
                if (oldsg != null)
                  OnMemberRemoved(oldsg, node);
                else if (newsg != null)  // and oldsg == null
                  InvalidateDiagramLayout(node, LayoutChange.NodeRemoved);
                if (newsg != null)
                  OnMemberAdded(newsg, node);
                else if (oldsg != null)  // and newsg == null
                  InvalidateDiagramLayout(node, LayoutChange.NodeAdded);
              }
            }
            break;
          }
        case ModelChange.ChangedMemberNodeKeys: {
            Object node = e.Data;
            if (node != null) {
              IDiagramModel model = e.Model;
              if (model != null) {
                Node groupnode = FindNodeForData(node, model);
                System.Collections.IEnumerable oldmemberkeys = e.OldValue as System.Collections.IEnumerable;
                System.Collections.IEnumerable newmemberkeys = e.NewValue as System.Collections.IEnumerable;
                if (oldmemberkeys != null && model != null) {
                  foreach (Object mk in oldmemberkeys) {
                    if (newmemberkeys == null || !ContainsKey(newmemberkeys, mk)) {
                      Node oldmember = FindNodeForData(model.FindNodeByKey(mk), model);
                      if (oldmember != null) {
                        oldmember.InvalidateRelationships("MemberNodeChanged");
                        foreach (Link l in oldmember.LinksConnected) UpdateCachedMembership(model, l);
                        if (groupnode != null)
                          OnMemberRemoved(groupnode, oldmember);
                        else
                          InvalidateDiagramLayout(oldmember, LayoutChange.NodeRemoved);
                      }
                    }
                  }
                }
                if (newmemberkeys != null && model != null) {
                  foreach (Object n in newmemberkeys) {
                    if (oldmemberkeys == null || !ContainsKey(oldmemberkeys, n)) {
                      Node newmember = FindNodeForData(model.FindNodeByKey(n), model);
                      if (newmember != null) {
                        newmember.InvalidateRelationships("MemberNodeChanged");
                        foreach (Link l in newmember.LinksConnected) UpdateCachedMembership(model, l);
                        newmember.SortZOrder();
                        if (groupnode != null)
                          OnMemberAdded(groupnode, newmember);
                        else
                          InvalidateDiagramLayout(newmember, LayoutChange.NodeAdded);
                      }
                    }
                  }
                }
              }
            }
            break;
          }
        case ModelChange.AddedMemberNodeKey: {
            Object nkey = e.NewValue;
            IDiagramModel model = e.Model;
            if (model != null) {
              Node newmember = FindNodeForData(model.FindNodeByKey(nkey), model);
              if (newmember != null) {
                newmember.InvalidateRelationships("MemberNodeAdded");
                foreach (Link l in newmember.LinksConnected) UpdateCachedMembership(model, l);
                newmember.SortZOrder();
                Node groupnode = FindNodeForData(e.Data, model);
                if (groupnode != null)
                  OnMemberAdded(groupnode, newmember);
                else
                  InvalidateDiagramLayout(newmember, LayoutChange.NodeAdded);
              }
            }
            break;
          }
        case ModelChange.RemovedMemberNodeKey: {
            Object okey = e.OldValue;
            IDiagramModel model = e.Model;
            if (model != null) {
              Node oldmember = FindNodeForData(model.FindNodeByKey(okey), model);
              if (oldmember != null) {
                oldmember.InvalidateRelationships("MemberNodeRemoved");
                foreach (Link l in oldmember.LinksConnected) UpdateCachedMembership(model, l);
                Node groupnode = FindNodeForData(e.Data, model);
                if (groupnode != null)
                  OnMemberRemoved(groupnode, oldmember);
                else
                  InvalidateDiagramLayout(oldmember, LayoutChange.NodeRemoved);
              }
            }
            break;
          }

        case ModelChange.AddedLink:
          AddLinkForData(e.Data, e.Model);
          break;
        case ModelChange.RemovingLink:
          RemoveLinkForData(e.Data, e.Model);
          break;
        case ModelChange.RemovedLink:
          RemoveLinkForData(e.Data, e.Model);
          break;
        case ModelChange.ChangedLinkFromPort:
        case ModelChange.ChangedLinkToPort: {
            Link link = FindLinkForData(e.Data, e.Model);
            if (link != null) {
              if (e.NewValue != null) {
                // don't invalidate the route when disconnecting, only when connecting or reconnecting
                link.Route.InvalidateRoute();
              }
              // reset the data binding, in case of bindings such as 
              //  Stroke="{Binding Path=Link.FromNode.Data.Brush}"
              PartBinding data = new PartBinding(link, e.Data);
              link.Content = data;
              link.DataContext = data;
            }
            break;
          }
        case ModelChange.ChangedLinkGroupNodeKey: {
            Link link = FindLinkForData(e.Data, e.Model);
            if (link != null) link.InvalidateRelationships("LinkGroupChanged");
            IDiagramModel model = e.Model;
            if (model != null) {
              Node oldsg = FindNodeForData(model.FindNodeByKey(e.OldValue), model);
              if (oldsg != null) oldsg.InvalidateRelationships("LinkGroupChanged");
              Node newsg = FindNodeForData(model.FindNodeByKey(e.NewValue), model);
              if (newsg != null) {
                Group sg = newsg as Group;
                if (sg != null && link != null) {
                  bool vis = sg.IsExpandedSubGraph;
                  if (link.Visible != vis) link.Visible = vis;
                }
                newsg.InvalidateRelationships("LinkGroupChanged");
              }
            }
            break;
          }
        case ModelChange.ChangedLinkLabelKey: {
            Link link = FindLinkForData(e.Data, e.Model);
            if (link != null) link.InvalidateRelationships("LinkLabelChanged");
            break;
          }
        case ModelChange.ChangedNodeKey: {
            Node n = FindNodeForData(e.Data, e.Model);
            if (n != null) {
              n.InvalidateRelationships("NodeKeyChanged");
            }
            break;
          }
        case ModelChange.ChangedNodeCategory: {
            Object nodedata = e.Data;
            IDiagramModel model = e.Model;
            Node node = FindNodeForData(nodedata, model);
            if (node != null) {
              bool wasselected = node.IsSelected;
              RemoveNodeForData(nodedata, model);
              AddNodeForData(nodedata, model);
              if (wasselected) {
                Node newnode = FindNodeForData(nodedata, model);
                if (newnode != null) newnode.IsSelected = wasselected;
              }
            }
            break;
          }
        case ModelChange.ChangedLinkCategory: {
            Object linkdata = e.Data;
            IDiagramModel model = e.Model;
            Link link = FindLinkForData(linkdata, model);
            if (link != null) {
              bool wasselected = link.IsSelected;
              RemoveLinkForData(linkdata, model);
              AddLinkForData(linkdata, model);
              if (wasselected) {
                Link newlink = FindLinkForData(linkdata, model);
                if (newlink != null) newlink.IsSelected = wasselected;
              }
            }
            break;
          }
        case ModelChange.InvalidateRelationships: {
            Node node = FindNodeForData(e.Data, e.Model);
            if (node != null) {
              node.Remeasure();
              Diagram.InvokeLater(this.Diagram, () => { node.InvalidateRelationships("ChangedNodeGeometry"); });
            }
            break;
          }

        // model discovery
        case ModelChange.ChangedNodesSource: {
            Diagram diagram = this.Diagram;
            IDiagramModel model = e.Model;
            if (diagram != null && model != null && diagram.NodesSource != model.NodesSource) {
              diagram.NodesSource = model.NodesSource;
            }
            RebuildNodeElements();  // also calls RebuildLinkElements
            if (diagram != null && model != null && !model.IsChangingModel) {
              diagram.RelayoutDiagram();
            }
            break;
          }
        case ModelChange.ChangedNodeKeyPath:
        case ModelChange.ChangedNodeCategoryPath:
        case ModelChange.ChangedNodeIsGroupPath:
        case ModelChange.ChangedGroupNodePath:
        case ModelChange.ChangedMemberNodesPath:
        case ModelChange.ChangedNodeIsLinkLabelPath: {
            RebuildNodeElements();  // also calls RebuildLinkElements
            Diagram diagram = this.Diagram;
            IDiagramModel model = e.Model;
            if (diagram != null && model != null && !model.IsChangingModel) {
              diagram.RelayoutDiagram();
            }
            break;
          }
        case ModelChange.ChangedLinksSource: {
            Diagram diagram = this.Diagram;
            IDiagramModel model = e.Model;
            if (diagram != null && model != null) {
              ILinksModel lmodel = model as ILinksModel;
              if (lmodel != null && diagram.LinksSource != lmodel.LinksSource) {
                diagram.LinksSource = lmodel.LinksSource;
              }
            }
            RebuildLinkElements();
            if (diagram != null && model != null && !model.IsChangingModel) {
              diagram.RelayoutDiagram();
            }
            break;
          }
        case ModelChange.ChangedLinkFromPath:
        case ModelChange.ChangedLinkToPath:
        case ModelChange.ChangedFromNodesPath:
        case ModelChange.ChangedToNodesPath:
        case ModelChange.ChangedLinkLabelNodePath: {
            RebuildLinkElements();
            Diagram diagram = this.Diagram;
            IDiagramModel model = e.Model;
            if (diagram != null && model != null && !model.IsChangingModel) {
              diagram.RelayoutDiagram();
            }
            break;
          }
        //case ModelChange.ChangedParentPortParameterPath:
        //case ModelChange.ChangedChildPortParameterPath:
        case ModelChange.ChangedLinkFromParameterPath:
        case ModelChange.ChangedLinkToParameterPath:
        case ModelChange.ChangedLinkCategoryPath:
          RebuildLinkElements();
          break;

        case ModelChange.StartedTransaction:
          //?? produce routed event
          break;
        case ModelChange.CommittedTransaction: {
            //?? produce routed event
            String reason = e.Data as String;
            if (reason != "Layout" && reason != "DelayedRouting") {  // check for this case to avoid infinite loop
              Diagram diagram = this.Diagram;
              if (diagram == null) break;
              IDiagramModel model = diagram.Model;
              if (model != null) model.ClearUnresolvedReferences();
              DiagramPanel panel = diagram.Panel;
              if (panel != null) panel.UpdateScrollTransform();
              LayoutManager laymgr = diagram.LayoutManager;
              if (laymgr != null) laymgr.InvokeLayoutDiagram("CommittedTransaction");
              diagram.UpdateCommands();
            }
            break;
          }
        case ModelChange.RolledBackTransaction: {
            //?? produce routed event
            String reason = e.Data as String;
            if (reason != "Layout" && reason != "DelayedRouting") {  // check for this case to avoid infinite loop
              Diagram diagram = this.Diagram;
              if (diagram == null) break;
              IDiagramModel model = diagram.Model;
              if (model != null) model.ClearUnresolvedReferences();
              diagram.UpdateCommands();
            }
            break;
          }

        case ModelChange.StartingUndo:
        case ModelChange.StartingRedo:
          break;
        case ModelChange.FinishedUndo:
        case ModelChange.FinishedRedo: {
            //?? produce routed event
            Diagram diagram = this.Diagram;
            if (diagram == null) break;
            DiagramPanel panel = diagram.Panel;
            if (panel == null) break;
            // force everything to be remeasured
            foreach (UIElement elt in panel.Children) {
              NodeLayer nlay = elt as NodeLayer;
              if (nlay != null) {
                if (nlay.IsTemporary) continue;
                foreach (Node n in nlay.Nodes) {
                  n.Remeasure();
                }
              } else {
                LinkLayer llay = elt as LinkLayer;
                if (llay != null) {
                  if (llay.IsTemporary) continue;
                  foreach (Link l in llay.Links) {
                    l.Remeasure();
                  }
                }
              }
            }
            panel.UpdateScrollTransform();
            panel.InvokeUpdateDiagramBounds("Undo/Redo");
            diagram.UpdateCommands();
            break;
          }

        // model state
        case ModelChange.ChangedName:
        case ModelChange.ChangedDataFormat:
        case ModelChange.ChangedModifiable:
        case ModelChange.ChangedValidCycle:
        case ModelChange.ChangedValidUnconnectedLinks: {
            Diagram diagram = this.Diagram;
            if (diagram == null) break;
            diagram.UpdateCommands();
            break;
          }
        case ModelChange.ChangedCopyingGroupCopiesMembers:
        case ModelChange.ChangedCopyingLinkCopiesLabel:
        case ModelChange.ChangedRemovingGroupRemovesMembers:
        case ModelChange.ChangedRemovingLinkRemovesLabel:
          break;
        default:
          Diagram.Error("Diagram did not handle Model change: " + e.Change.ToString());
          break;
      }
    }
Beispiel #24
0
 private void ObservedPanel_AnimatingChanged(object sender, ModelChangedEventArgs e) {
   if (sender is DiagramPanel) {
     this.IsAnimatingScrolling = (bool)e.NewValue;
     UpdateBox();
   } else if (sender is LayoutManager) {
     this.IsAnimatingLayout = (bool)e.NewValue;
     // UpdateNodesAndLinks when no longer IsAnimating
     if (!this.IsAnimatingLayout) {
       UpdateNodesAndLinks();
     }
   }
 }
Beispiel #25
0
 /// <summary>
 /// Raise a <see cref="Changed"/> event, given a <see cref="ModelChangedEventArgs"/>.
 /// </summary>
 /// <param name="e">an edit describing the change that just happened</param>
 /// <remarks>
 /// This just calls <see cref="OnChanged"/>.
 /// This method is public because it is part of the implementation of <see cref="IDiagramModel"/>.
 /// </remarks>
 public void RaiseChanged(ModelChangedEventArgs e)
 {
     OnChanged(e);
 }
Beispiel #26
0
 private void RaiseChanged(IDiagramModel model, ModelChange change, Object data, Object oldval, Object newval) {
   ModelChangedEventArgs e = new ModelChangedEventArgs();
   e.Model = model;
   e.Change = change;
   e.Data = data;
   e.OldValue = oldval;
   e.NewValue = newval;
   model.RaiseChanged(e);
 }
Beispiel #27
0
 internal /*?? protected */ virtual void ChangeModelState(ModelChangedEventArgs e, bool undo) {
   if ((int)e.Change > (int)ModelChange.Property) {
     ModelHelper.Error((IDiagramModel)this, "ChangeModelState did not handle ModelChange." + e.Change.ToString());
   }
 }
Beispiel #28
0
    /// <summary>
    /// Raises the <see cref="Changed"/> event.
    /// </summary>
    /// <param name="e">an edit describing the change that just happened</param>
    /// <remarks>
    /// If you override this method, be sure to call the base method first.
    /// </remarks>
    protected virtual void OnChanged(ModelChangedEventArgs e) {
      if (e == null) return;
      if (_ChangedEvent != null) _ChangedEvent(this, e);

      if (!this.SkipsUndoManager && !this.Initializing) {
        UndoManager um = this.UndoManager;
        if (um != null) um.HandleModelChanged(this, e);
        if (((int)e.Change) >= (int)ModelChange.Property) this.IsModified = true;
      }
    }
Beispiel #29
0
    /// <summary>
    /// Create an <see cref="IUndoableEdit"/> for a <see cref="IDiagramModel.Changed"/> event.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <remarks>
    /// This calls <see cref="SkipEvent"/> if for some reason we should ignore
    /// the <paramref name="e"/>.
    /// This then creates a <see cref="ModelChangedEventArgs"/> and adds it to the
    /// <see cref="CurrentEdit"/>, a <see cref="UndoManager.CompoundEdit"/> which it allocates
    /// if needed.
    /// This method always ignores all Changed events while we are performing an
    /// <see cref="Undo"/> or <see cref="Redo"/>.
    /// </remarks>
    public virtual void HandleModelChanged(Object sender, ModelChangedEventArgs e) {
      // changes caused by performing an undo or redo should be ignored!
      if (this.IsUndoingRedoing) return;

      if (!SkipEvent(e)) {
        CompoundEdit cedit = this.CurrentEdit;
        //ModelHelper.Trace(this.TransactionLevel, e.ToString());
        if (cedit == null) {
          cedit = new CompoundEdit();
          this.CurrentEdit = cedit;
        }

        // make a copy of the event to save as an edit in the list
        ModelChangedEventArgs edit = new ModelChangedEventArgs(e);
        cedit.Edits.Add(edit);
        if (this.ChecksTransactionLevel && this.TransactionLevel <= 0) {
          ModelHelper.Trace("Change not within a transaction: " + edit.ToString());
        }
      }
    }