PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/release 0.1.1/Designer/Editors/base/NeuronEditor.cs

https://gitlab.com/Tiger66639/neural_network_designer
C# | 301 lines | 183 code | 32 blank | 86 comment | 53 complexity | 26dc8956b9250942c7ebf90109f0b3e6 MD5 | raw file
  1. using System;
  2. using System.ComponentModel;
  3. using System.Windows;
  4. using System.Windows.Threading;
  5. using System.Xml.Serialization;
  6. namespace NeuralNetworkDesigne.HAB.Designer
  7. {
  8. /// <summary>
  9. /// Base class for all editor types that also wrap a neuron.
  10. /// </summary>
  11. /// <remarks>
  12. /// When read from xml, use <see cref="NeuronEditor.RegisterItem"/> to properly attach the item.
  13. /// </remarks>
  14. abstract public class NeuronEditor : EditorBase, INeuronWrapper, INeuronInfo, IWeakEventListener
  15. {
  16. #region Fields
  17. private Neuron fItem;
  18. private NeuronData fData;
  19. #endregion Fields
  20. #region ctor
  21. /// <summary>
  22. /// Initializes a new instance of the <see cref="NeuronEditor"/> class.
  23. /// </summary>
  24. public NeuronEditor()
  25. {
  26. NeuronChangedEventManager.AddListener(Brain.Current, this);
  27. }
  28. /// <summary>
  29. /// Releases unmanaged resources and performs other cleanup operations before the
  30. /// <see cref="CodeEditor"/> is reclaimed by garbage collection.
  31. /// </summary>
  32. /// <remarks>
  33. /// We have got a problem here: when a code editor is open during app shutdown, this one fails.
  34. /// </remarks>
  35. ~NeuronEditor()
  36. {
  37. try
  38. {
  39. if (App.Current != null && App.Current.Dispatcher.HasShutdownStarted == false) //don't need to do this when shutting down. Could cause exceptions.
  40. {
  41. NeuronChangedEventManager.RemoveListener(Brain.Current, this);
  42. if (NeuronInfo != null && App.Current != null)
  43. PropertyChangedEventManager.RemoveListener(fData, this, "DisplayTitle");
  44. }
  45. }
  46. catch
  47. {
  48. }
  49. }
  50. #endregion ctor
  51. #region Prop
  52. #region Item (INeuronWrapper Members)
  53. /// <summary>
  54. /// Gets the Neuron that this object provides a wraper for.
  55. /// </summary>
  56. /// <value>The item.</value>
  57. public Neuron Item
  58. {
  59. get { return fItem; }
  60. }
  61. #endregion Item (INeuronWrapper Members)
  62. #region ItemID
  63. /// <summary>
  64. /// Gets or sets the ID of the item that this object provides an editor for.
  65. /// </summary>
  66. /// <remarks>
  67. /// When read from xml, use <see cref="NeuronEditor.RegisterItem"/> to properly attach the item.
  68. /// </remarks>
  69. /// <value>The ID of the item.</value>
  70. public virtual ulong ItemID
  71. {
  72. get
  73. {
  74. if (fItem != null)
  75. return fItem.ID;
  76. else
  77. return Neuron.EmptyId;
  78. }
  79. set
  80. {
  81. if (value != ItemID)
  82. {
  83. if (fData != null)
  84. PropertyChangedEventManager.RemoveListener(fData, this, "DisplayTitle");
  85. if (value != Neuron.EmptyId)
  86. fItem = Brain.Current[value];
  87. else
  88. fItem = null;
  89. if (Item != null && BrainData.Current != null && BrainData.Current.NeuronInfo != null) //NeuronInfo == null while loading a project, in that case, RegisterItem is called.
  90. {
  91. fData = BrainData.Current.NeuronInfo[value];
  92. PropertyChangedEventManager.AddListener(fData, this, "DisplayTitle");
  93. }
  94. else
  95. fData = null;
  96. OnPropertyChanged("Item");
  97. OnPropertyChanged("NeuronInfo");
  98. OnPropertyChanged("ItemID");
  99. }
  100. }
  101. }
  102. /// <summary>
  103. /// Registers the item that was read from xml.
  104. /// </summary>
  105. /// <remarks>
  106. /// This must be called when the editor is read from xml. In that situation, the
  107. /// brainData isn't always loaded properly yet. At this point, this can be resolved.
  108. /// It is called by the brainData.
  109. /// </remarks>
  110. public virtual void RegisterItem()
  111. {
  112. if (fData != null)
  113. PropertyChangedEventManager.RemoveListener(fData, this, "DisplayTitle");
  114. if (Item != null)
  115. {
  116. fData = BrainData.Current.NeuronInfo[ItemID];
  117. PropertyChangedEventManager.AddListener(fData, this, "DisplayTitle");
  118. }
  119. else
  120. fData = null;
  121. OnPropertyChanged("Item");
  122. OnPropertyChanged("NeuronInfo");
  123. OnPropertyChanged("ItemID");
  124. }
  125. #endregion ItemID
  126. #region NeuronInfo (INeuronInfo Members)
  127. /// <summary>
  128. /// Gets the extra info for the specified neuron. Can be null.
  129. /// </summary>
  130. /// <value></value>
  131. public NeuronData NeuronInfo
  132. {
  133. get
  134. {
  135. return fData;
  136. }
  137. }
  138. #endregion NeuronInfo (INeuronInfo Members)
  139. /// <summary>
  140. /// Gets the text that should be added to the front of the name to display as default value.
  141. /// </summary>
  142. /// <value>The name prefix.</value>
  143. [XmlIgnore]
  144. public abstract string NamePrefix
  145. {
  146. get;
  147. }
  148. #endregion Prop
  149. #region overrides
  150. /// <summary>
  151. /// Called when property changed has changed.
  152. /// </summary>
  153. /// <remarks>
  154. /// 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.
  155. /// </remarks>
  156. /// <param name="aName">A name.</param>
  157. protected override void OnPropertyChanged(string aName)
  158. {
  159. base.OnPropertyChanged(aName);
  160. if (NeuronInfo != null && aName == "Name")
  161. {
  162. 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.
  163. NeuronInfo.DisplayTitle = Name;
  164. else
  165. NeuronInfo.DisplayTitle = Name.Substring(NamePrefix.Length + 2);
  166. }
  167. }
  168. /// <summary>
  169. /// Reads the fields/properties of the class.
  170. /// </summary>
  171. /// <param name="reader">The reader.</param>
  172. /// <returns>
  173. /// True if the item was properly read, otherwise false.
  174. /// </returns>
  175. /// <remarks>
  176. /// This function is called for each element that is found, so this function should check which element it is
  177. /// and only read that element accordingly.
  178. /// </remarks>
  179. protected override bool ReadXmlInternal(System.Xml.XmlReader reader)
  180. {
  181. if (base.ReadXmlInternal(reader) == false)
  182. {
  183. if (reader.Name == "Item")
  184. {
  185. ulong iVal = XmlStore.ReadElement<ulong>(reader, "Item");
  186. if (iVal != Neuron.EmptyId)
  187. fItem = Brain.Current[iVal];
  188. else
  189. fItem = null;
  190. return true;
  191. }
  192. return false;
  193. }
  194. else
  195. return true;
  196. }
  197. /// <summary>
  198. /// Converts an object into its XML representation.
  199. /// </summary>
  200. /// <param name="writer">The <see cref="T:System.Xml.XmlWriter"/> stream to which the object is serialized.</param>
  201. public override void WriteXml(System.Xml.XmlWriter writer)
  202. {
  203. 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.
  204. XmlStore.WriteElement<ulong>(writer, "Item", ItemID);
  205. }
  206. #endregion overrides
  207. #region IWeakEventListener
  208. /// <summary>
  209. /// Receives events from the centralized event manager.
  210. /// </summary>
  211. /// <param name="managerType">The type of the <see cref="T:System.Windows.WeakEventManager"/> calling this method.</param>
  212. /// <param name="sender">Object that originated the event.</param>
  213. /// <param name="e">Event data.</param>
  214. /// <returns>
  215. /// 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.
  216. /// </returns>
  217. public virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
  218. {
  219. if (managerType == typeof(NeuronChangedEventManager))
  220. {
  221. if (Item == ((NeuronChangedEventArgs)e).OriginalSource) //only call if the wrapped item was changed.
  222. App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action<NeuronChangedEventArgs>(Item_NeuronChanged), e);
  223. return true;
  224. }
  225. else if (managerType == typeof(PropertyChangedEventManager))
  226. {
  227. fData_PropertyChanged(sender, (PropertyChangedEventArgs)e);
  228. return true;
  229. }
  230. else
  231. return false;
  232. }
  233. /// <summary>
  234. /// Called when the wrapped item is changed. When removed, makes certain that the <see cref="BrainData.CodeEditors"/> list is updated.
  235. /// </summary>
  236. /// <param name="e">The <see cref="NeuralNetworkDesigne.HAB.NeuronChangedEventArgs"/> instance containing the event data.</param>
  237. protected virtual void Item_NeuronChanged(NeuronChangedEventArgs e)
  238. {
  239. if (!(e is NeuronPropChangedEventArgs)) //don't need to respond to a prop changed event.
  240. {
  241. switch (e.Action)
  242. {
  243. case BrainAction.Changed:
  244. fItem = e.NewValue;
  245. break;
  246. case BrainAction.Removed:
  247. BrainData.Current.Editors.RemoveRecursive(this);
  248. break;
  249. default:
  250. break;
  251. }
  252. }
  253. }
  254. /// <summary>
  255. /// Handles the PropertyChanged event of the fData control.
  256. /// </summary>
  257. /// <remarks>
  258. /// Need to update the title of the code Editor if appropriate.
  259. /// </remarks>
  260. /// <param name="sender">The source of the event.</param>
  261. /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
  262. private void fData_PropertyChanged(object sender, PropertyChangedEventArgs e)
  263. {
  264. if (string.IsNullOrEmpty(Name) == false && Name.StartsWith(NamePrefix + ": ") == true && Name != fData.DisplayTitle) //name != displayTitle cause when name is changed,sometimes displaytitle might also get
  265. Name = NamePrefix + ": " + fData.DisplayTitle;
  266. }
  267. #endregion IWeakEventListener
  268. }
  269. }