PageRenderTime 134ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/release 0.1.1/Designer/Editors/MindMap/MindMapNeuron.cs

https://gitlab.com/Tiger66639/neural_network_designer
C# | 429 lines | 283 code | 45 blank | 101 comment | 34 complexity | 7ad86ecf01c0bdf7fdf0c975ed7f5bdd MD5 | raw file
  1. using System.Collections.Generic;
  2. using System.ComponentModel;
  3. using System.Windows;
  4. using System.Windows.Documents;
  5. using System.Windows.Media;
  6. using System.Windows.Shapes;
  7. using System.Xml;
  8. using System.Xml.Serialization;
  9. namespace NeuralNetworkDesigne.HAB.Designer
  10. {
  11. /// <summary>
  12. /// An item that can be displayed on a <see cref="MindMap"/> and that represents a <see cref="Neuron"/>.
  13. /// </summary>
  14. public class MindMapNeuron : PositionedMindMapItem, INeuronInfo, INeuronWrapper
  15. {
  16. #region fields
  17. Neuron fItem;
  18. NeuronData fItemData;
  19. int fChildCount;
  20. Shape fShape; //stores the shape that represents the neuron, required for drawing links.
  21. List<EdgePoint> fEdgePoints; //stores the edgepoints calculated on the shape.
  22. #endregion
  23. #region ctor
  24. /// <summary>
  25. /// Initializes a new instance of the <see cref="MindMapNeuron"/> class.
  26. /// </summary>
  27. /// <remarks>
  28. /// This is a private function so that the Create function needs to be used.
  29. /// </remarks>
  30. internal MindMapNeuron(Neuron item)
  31. {
  32. Item = item;
  33. }
  34. /// <summary>
  35. /// Initializes a new instance of the <see cref="MindMapNeuron"/> class.
  36. /// </summary>
  37. /// <remarks>
  38. /// This constructor is provided for streaming, should be fixed later on
  39. /// </remarks>
  40. public MindMapNeuron()
  41. {
  42. }
  43. public static MindMapNeuron CreateFor(Neuron item)
  44. {
  45. if (item is NeuronCluster)
  46. return new MindMapCluster((NeuronCluster)item);
  47. else
  48. return new MindMapNeuron(item);
  49. }
  50. #endregion
  51. #region prop
  52. #region NeuronInfo
  53. /// <summary>
  54. /// Gets the extra info stored about the <see cref="MindMapNeuron.Item"/>.
  55. /// </summary>
  56. [XmlIgnore]
  57. public NeuronData NeuronInfo
  58. {
  59. get
  60. {
  61. if (fItemData == null && Brain.Current != null && fItem != null)
  62. {
  63. fItemData = BrainData.Current.NeuronInfo[fItem.ID];
  64. if (fItemData != null)
  65. fItemData.PropertyChanged += new PropertyChangedEventHandler(ItemData_PropertyChanged);
  66. }
  67. return fItemData;
  68. }
  69. internal set { fItemData = value; }
  70. }
  71. #endregion
  72. #region Item
  73. /// <summary>
  74. /// Gets/sets the neuron that this mind map item represents.
  75. /// </summary>
  76. [XmlIgnore]
  77. public virtual Neuron Item
  78. {
  79. get
  80. {
  81. return fItem;
  82. }
  83. set
  84. {
  85. if (fItemData != null)
  86. fItemData.PropertyChanged -= new PropertyChangedEventHandler(ItemData_PropertyChanged);
  87. OnPropertyChanging("Item", fItem, value);
  88. fItem = value;
  89. fItemData = null;
  90. OnPropertyChanged("Item");
  91. OnPropertyChanged("Description"); //whenever ItemData changes, these 2 props are also triggered, cause we use the global data.
  92. OnPropertyChanged("DescriptionTitle");
  93. }
  94. }
  95. /// <summary>
  96. /// need to pass along the prop change, cause this is where we get the values for titel and
  97. /// description.
  98. /// </summary>
  99. /// <param name="sender"></param>
  100. /// <param name="e"></param>
  101. void ItemData_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
  102. {
  103. OnPropertyChanged(e.PropertyName);
  104. }
  105. #endregion
  106. #region ItemId
  107. /// <summary>
  108. /// Gets/sets the id of the neuron that this item represents.
  109. /// </summary>
  110. /// <remarks>
  111. /// This is primarely provided so we can easely stream this info.
  112. /// </remarks>
  113. [XmlElement("Neuron")]
  114. public ulong ItemID
  115. {
  116. get
  117. {
  118. if (fItem != null)
  119. return fItem.ID;
  120. else
  121. return Neuron.EmptyId;
  122. }
  123. set
  124. {
  125. if (value == Neuron.EmptyId)
  126. Item = null;
  127. else
  128. Item = Brain.Current[value];
  129. }
  130. }
  131. #endregion
  132. #region Shape
  133. /// <summary>
  134. /// Gets/sets the Shape that draws this neuron. This is used to calculate the edge for placing links.
  135. /// </summary>
  136. /// <remarks>
  137. /// We need the shape, not just the geometry, cause if we retrieve this, it is a snapshot and doesn't get
  138. /// updated.
  139. /// </remarks>
  140. [XmlIgnore]
  141. public Shape Shape
  142. {
  143. get
  144. {
  145. return fShape;
  146. }
  147. set
  148. {
  149. if (fShape != value)
  150. {
  151. fShape = value;
  152. fEdgePoints = null; //we must make certain that edgepoints are recalculated.
  153. OnPropertyChanged("Shape");
  154. }
  155. }
  156. }
  157. #endregion
  158. #region EdgePoints
  159. /// <summary>
  160. /// Gets the list of all the edgepoints for this object.
  161. /// </summary>
  162. [XmlIgnore]
  163. public List<EdgePoint> EdgePoints
  164. {
  165. get
  166. {
  167. if (fEdgePoints == null)
  168. {
  169. fEdgePoints = new List<EdgePoint>(360);
  170. PathGeometry iPath = Shape.RenderedGeometry.GetOutlinedPathGeometry(1, ToleranceType.Absolute); //need the outline of the object.
  171. TransformGroup iTransform = new TransformGroup(); //need to scale it a bit (bigger) for the margin.
  172. ScaleTransform iScale = new ScaleTransform(1 + (MindMapLink.Margin / iPath.Bounds.Width), 1 + (MindMapLink.Margin / iPath.Bounds.Height)); //margin is expressed in absolute values, so we need to convert it to relative to the width/height of the item
  173. iScale.CenterX = iPath.Bounds.Width / 2;
  174. iScale.CenterY = iPath.Bounds.Height / 2;
  175. iTransform.Children.Add(iScale);
  176. iTransform.Children.Add(new TranslateTransform(X, Y));
  177. iPath.Transform = iTransform;
  178. Point iTangent;
  179. Point iFound;
  180. Point iCenter = new Point(X + (Width / 2), Y + (Height / 2));
  181. for (int i = 0; i < 360; i++)
  182. {
  183. EdgePoint iEdge = new EdgePoint();
  184. fEdgePoints.Add(iEdge);
  185. iPath.GetPointAtFractionLength(i / 360.0, out iFound, out iTangent);
  186. iEdge.Point = iFound;
  187. iEdge.Angle = Helper.GetAnlge(iCenter, iEdge.Point);
  188. }
  189. }
  190. return fEdgePoints;
  191. }
  192. }
  193. #endregion
  194. #region Description
  195. /// <summary>
  196. /// We always use the global description data for neurons, so we don't store it and get the data from the braindata.
  197. /// </summary>
  198. [XmlIgnore]
  199. public override FlowDocument Description
  200. {
  201. get
  202. {
  203. if (NeuronInfo != null)
  204. return NeuronInfo.Description;
  205. else return null;
  206. }
  207. set
  208. {
  209. if (NeuronInfo != null)
  210. NeuronInfo.Description = value;
  211. }
  212. }
  213. #endregion
  214. #region DescriptionTitle
  215. /// <summary>
  216. /// used as the header of the description editor frame.
  217. /// </summary>
  218. public override string DescriptionTitle
  219. {
  220. get
  221. {
  222. if (NeuronInfo != null && string.IsNullOrEmpty(NeuronInfo.DisplayTitle) == false)
  223. return NeuronInfo.DisplayTitle;
  224. else if (fItem != null)
  225. return fItem.ToString();
  226. return null;
  227. }
  228. }
  229. #endregion
  230. #region ChildCount
  231. /// <summary>
  232. /// Gets the nr of times this neuron is a child of a cluster.
  233. /// </summary>
  234. /// <remarks>
  235. /// This property is automatically managed by the <see cref="MindMapCluster"/> objects.
  236. /// It can be used in the UI to indicate if an item is directly on the design surface or not.
  237. /// </remarks>
  238. [XmlIgnore]
  239. public int ChildCount
  240. {
  241. get
  242. {
  243. return fChildCount;
  244. }
  245. internal set
  246. {
  247. fChildCount = value;
  248. OnPropertyChanged("ChildCount");
  249. }
  250. }
  251. #endregion
  252. /// <summary>
  253. /// Gets/sets the height of the item.
  254. /// </summary>
  255. /// <value></value>
  256. /// <remarks>
  257. /// virtual so that <see cref="MindMapCluster"/> can check and change val as desired, depending on children.
  258. /// need to reset the edgepoints
  259. /// </remarks>
  260. public override double Height
  261. {
  262. get
  263. {
  264. return base.Height;
  265. }
  266. set
  267. {
  268. fEdgePoints = null; //we must make certain that edgepoints are recalculated.
  269. base.Height = value;
  270. }
  271. }
  272. /// <summary>
  273. /// Gets/sets the width of the item.
  274. /// </summary>
  275. /// <value>The width.</value>
  276. /// <remarks>
  277. /// virtual so that <see cref="MindMapCluster"/> can check and change val as desired, depending on children.
  278. /// need to reset the edgepoints
  279. /// </remarks>
  280. public override double Width
  281. {
  282. get
  283. {
  284. return base.Width;
  285. }
  286. set
  287. {
  288. fEdgePoints = null; //we must make certain that edgepoints are recalculated.
  289. base.Width = value;
  290. }
  291. }
  292. /// <summary>
  293. /// Gets/sets the horizontal offset of the item on the graph.
  294. /// </summary>
  295. /// <value></value>
  296. /// <remarks>
  297. /// virtual so that <see cref="MindMapCluster"/> can check and change val as desired, depending on children.
  298. /// need to reset the edgepoints
  299. /// </remarks>
  300. public override double X
  301. {
  302. get
  303. {
  304. return base.X;
  305. }
  306. set
  307. {
  308. fEdgePoints = null; //we must make certain that edgepoints are recalculated.
  309. base.X = value;
  310. }
  311. }
  312. /// <summary>
  313. /// Gets/sets the vertical offset of the item on the graph.
  314. /// </summary>
  315. /// <value></value>
  316. /// <remarks>
  317. /// virtual so that <see cref="MindMapCluster"/> can check and change val as desired, depending on children.
  318. /// need to reset the edgepoints
  319. /// </remarks>
  320. public override double Y
  321. {
  322. get
  323. {
  324. return base.Y;
  325. }
  326. set
  327. {
  328. fEdgePoints = null; //we must make certain that edgepoints are recalculated.
  329. base.Y = value;
  330. }
  331. }
  332. #region INeuronWrapper Members
  333. /// <summary>
  334. /// Gets the item.
  335. /// </summary>
  336. /// <value>The item.</value>
  337. Neuron INeuronWrapper.Item
  338. {
  339. get { return Item; }
  340. }
  341. #endregion
  342. #endregion
  343. #region Functions
  344. /// <returns>A deep copy of this object.</returns>
  345. public override MindMapItem Duplicate()
  346. {
  347. MindMapNeuron iRes = (MindMapNeuron)base.Duplicate();
  348. iRes.fItem = fItem;
  349. return iRes;
  350. }
  351. /// <summary>
  352. /// Copies the field values.
  353. /// </summary>
  354. /// <param name="from">from where to copy the data.</param>
  355. internal void CopyValues(MindMapNeuron from)
  356. {
  357. X = from.X;
  358. Y = from.Y;
  359. Width = from.Width;
  360. Height = from.Height;
  361. ZIndex = from.ZIndex;
  362. ChildCount = from.ChildCount;
  363. }
  364. /// <summary>
  365. /// Assigns this neuron to all the mindmap clusters in the list.
  366. /// </summary>
  367. /// <param name="clusters">The clusters.</param>
  368. internal void AssignToClusters(IEnumerable<MindMapCluster> clusters)
  369. {
  370. foreach (MindMapCluster i in clusters)
  371. {
  372. using (ChildrenAccessor iList = i.Cluster.Children)
  373. {
  374. if (iList.Contains(Item) == true)
  375. {
  376. i.MonditorChild(this);
  377. i.Children.Add(this);
  378. }
  379. }
  380. }
  381. }
  382. #endregion
  383. }
  384. }