/release 0.1.1/Designer/Editors/base/NeuronEditor.cs
C# | 301 lines | 183 code | 32 blank | 86 comment | 53 complexity | 26dc8956b9250942c7ebf90109f0b3e6 MD5 | raw file
- using System;
- using System.ComponentModel;
- using System.Windows;
- using System.Windows.Threading;
- using System.Xml.Serialization;
- namespace NeuralNetworkDesigne.HAB.Designer
- {
- /// <summary>
- /// Base class for all editor types that also wrap a neuron.
- /// </summary>
- /// <remarks>
- /// When read from xml, use <see cref="NeuronEditor.RegisterItem"/> to properly attach the item.
- /// </remarks>
- abstract public class NeuronEditor : EditorBase, INeuronWrapper, INeuronInfo, IWeakEventListener
- {
- #region Fields
- private Neuron fItem;
- private NeuronData fData;
- #endregion Fields
- #region ctor
- /// <summary>
- /// Initializes a new instance of the <see cref="NeuronEditor"/> class.
- /// </summary>
- public NeuronEditor()
- {
- NeuronChangedEventManager.AddListener(Brain.Current, this);
- }
- /// <summary>
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// <see cref="CodeEditor"/> is reclaimed by garbage collection.
- /// </summary>
- /// <remarks>
- /// We have got a problem here: when a code editor is open during app shutdown, this one fails.
- /// </remarks>
- ~NeuronEditor()
- {
- try
- {
- if (App.Current != null && App.Current.Dispatcher.HasShutdownStarted == false) //don't need to do this when shutting down. Could cause exceptions.
- {
- NeuronChangedEventManager.RemoveListener(Brain.Current, this);
- if (NeuronInfo != null && App.Current != null)
- PropertyChangedEventManager.RemoveListener(fData, this, "DisplayTitle");
- }
- }
- catch
- {
- }
- }
- #endregion ctor
- #region Prop
- #region Item (INeuronWrapper Members)
- /// <summary>
- /// Gets the Neuron that this object provides a wraper for.
- /// </summary>
- /// <value>The item.</value>
- public Neuron Item
- {
- get { return fItem; }
- }
- #endregion Item (INeuronWrapper Members)
- #region ItemID
- /// <summary>
- /// Gets or sets the ID of the item that this object provides an editor for.
- /// </summary>
- /// <remarks>
- /// When read from xml, use <see cref="NeuronEditor.RegisterItem"/> to properly attach the item.
- /// </remarks>
- /// <value>The ID of the item.</value>
- public virtual ulong ItemID
- {
- get
- {
- if (fItem != null)
- return fItem.ID;
- else
- return Neuron.EmptyId;
- }
- set
- {
- if (value != ItemID)
- {
- if (fData != null)
- PropertyChangedEventManager.RemoveListener(fData, this, "DisplayTitle");
- if (value != Neuron.EmptyId)
- fItem = Brain.Current[value];
- else
- fItem = null;
- if (Item != null && BrainData.Current != null && BrainData.Current.NeuronInfo != null) //NeuronInfo == null while loading a project, in that case, RegisterItem is called.
- {
- fData = BrainData.Current.NeuronInfo[value];
- PropertyChangedEventManager.AddListener(fData, this, "DisplayTitle");
- }
- else
- fData = null;
- OnPropertyChanged("Item");
- OnPropertyChanged("NeuronInfo");
- OnPropertyChanged("ItemID");
- }
- }
- }
- /// <summary>
- /// Registers the item that was read from xml.
- /// </summary>
- /// <remarks>
- /// This must be called when the editor is read from xml. In that situation, the
- /// brainData isn't always loaded properly yet. At this point, this can be resolved.
- /// It is called by the brainData.
- /// </remarks>
- public virtual void RegisterItem()
- {
- if (fData != null)
- PropertyChangedEventManager.RemoveListener(fData, this, "DisplayTitle");
- if (Item != null)
- {
- fData = BrainData.Current.NeuronInfo[ItemID];
- PropertyChangedEventManager.AddListener(fData, this, "DisplayTitle");
- }
- else
- fData = null;
- OnPropertyChanged("Item");
- OnPropertyChanged("NeuronInfo");
- OnPropertyChanged("ItemID");
- }
- #endregion ItemID
- #region NeuronInfo (INeuronInfo Members)
- /// <summary>
- /// Gets the extra info for the specified neuron. Can be null.
- /// </summary>
- /// <value></value>
- public NeuronData NeuronInfo
- {
- get
- {
- return fData;
- }
- }
- #endregion NeuronInfo (INeuronInfo Members)
- /// <summary>
- /// Gets the text that should be added to the front of the name to display as default value.
- /// </summary>
- /// <value>The name prefix.</value>
- [XmlIgnore]
- public abstract string NamePrefix
- {
- get;
- }
- #endregion Prop
- #region overrides
- /// <summary>
- /// Called when property changed has changed.
- /// </summary>
- /// <remarks>
- /// We override to check if name is changed, if so, we update displaytitle. This is a bit bogus but name doesn't provide an override.
- /// </remarks>
- /// <param name="aName">A name.</param>
- protected override void OnPropertyChanged(string aName)
- {
- base.OnPropertyChanged(aName);
- if (NeuronInfo != null && aName == "Name")
- {
- if (Name.StartsWith(NamePrefix + ": ") == false) //if the name starts with Code: or similar, we need to strip the first part. If we don't, we get a stack overflow because this with the fData_PropertyChanged callback keep calling each other.
- NeuronInfo.DisplayTitle = Name;
- else
- NeuronInfo.DisplayTitle = Name.Substring(NamePrefix.Length + 2);
- }
- }
- /// <summary>
- /// Reads the fields/properties of the class.
- /// </summary>
- /// <param name="reader">The reader.</param>
- /// <returns>
- /// True if the item was properly read, otherwise false.
- /// </returns>
- /// <remarks>
- /// This function is called for each element that is found, so this function should check which element it is
- /// and only read that element accordingly.
- /// </remarks>
- protected override bool ReadXmlInternal(System.Xml.XmlReader reader)
- {
- if (base.ReadXmlInternal(reader) == false)
- {
- if (reader.Name == "Item")
- {
- ulong iVal = XmlStore.ReadElement<ulong>(reader, "Item");
- if (iVal != Neuron.EmptyId)
- fItem = Brain.Current[iVal];
- else
- fItem = null;
- return true;
- }
- return false;
- }
- else
- return true;
- }
- /// <summary>
- /// Converts an object into its XML representation.
- /// </summary>
- /// <param name="writer">The <see cref="T:System.Xml.XmlWriter"/> stream to which the object is serialized.</param>
- public override void WriteXml(System.Xml.XmlWriter writer)
- {
- XmlStore.WriteElement<string>(writer, "Name", Name); //we don't write out the complete base cause this also generates the description, but we don't store this, it comes from the NeuronData object that we ref.
- XmlStore.WriteElement<ulong>(writer, "Item", ItemID);
- }
- #endregion overrides
- #region IWeakEventListener
- /// <summary>
- /// Receives events from the centralized event manager.
- /// </summary>
- /// <param name="managerType">The type of the <see cref="T:System.Windows.WeakEventManager"/> calling this method.</param>
- /// <param name="sender">Object that originated the event.</param>
- /// <param name="e">Event data.</param>
- /// <returns>
- /// true if the listener handled the event. It is considered an error by the <see cref="T:System.Windows.WeakEventManager"/> handling in WPF to register a listener for an event that the listener does not handle. Regardless, the method should return false if it receives an event that it does not recognize or handle.
- /// </returns>
- public virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
- {
- if (managerType == typeof(NeuronChangedEventManager))
- {
- if (Item == ((NeuronChangedEventArgs)e).OriginalSource) //only call if the wrapped item was changed.
- App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action<NeuronChangedEventArgs>(Item_NeuronChanged), e);
- return true;
- }
- else if (managerType == typeof(PropertyChangedEventManager))
- {
- fData_PropertyChanged(sender, (PropertyChangedEventArgs)e);
- return true;
- }
- else
- return false;
- }
- /// <summary>
- /// Called when the wrapped item is changed. When removed, makes certain that the <see cref="BrainData.CodeEditors"/> list is updated.
- /// </summary>
- /// <param name="e">The <see cref="NeuralNetworkDesigne.HAB.NeuronChangedEventArgs"/> instance containing the event data.</param>
- protected virtual void Item_NeuronChanged(NeuronChangedEventArgs e)
- {
- if (!(e is NeuronPropChangedEventArgs)) //don't need to respond to a prop changed event.
- {
- switch (e.Action)
- {
- case BrainAction.Changed:
- fItem = e.NewValue;
- break;
- case BrainAction.Removed:
- BrainData.Current.Editors.RemoveRecursive(this);
- break;
- default:
- break;
- }
- }
- }
- /// <summary>
- /// Handles the PropertyChanged event of the fData control.
- /// </summary>
- /// <remarks>
- /// Need to update the title of the code Editor if appropriate.
- /// </remarks>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
- private void fData_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if (string.IsNullOrEmpty(Name) == false && Name.StartsWith(NamePrefix + ": ") == true && Name != fData.DisplayTitle) //name != displayTitle cause when name is changed,sometimes displaytitle might also get
- Name = NamePrefix + ": " + fData.DisplayTitle;
- }
- #endregion IWeakEventListener
- }
- }