PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/CARE 2.0/GraphLayout/Layout.cs

#
C# | 327 lines | 267 code | 46 blank | 14 comment | 23 complexity | 1c4b2a82543e2520c2763835f65bdf55 MD5 | raw file
  1. using System.Windows.Shapes;
  2. using System.Windows;
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Windows.Controls;
  7. using GraphLayout.Interface;
  8. using System.Windows.Threading;
  9. using GraphLayout.GraphRepresentation;
  10. using System.Windows.Media;
  11. using System.Reflection;
  12. namespace prefuse.action.layout
  13. {
  14. /**
  15. * Abstract base class providing convenience methods for layout algorithms.
  16. *
  17. * @author <a href="http://jheer.org">jeffrey heer</a>
  18. */
  19. public abstract class Layout : Canvas
  20. {
  21. internal double mouseVerticalPosition;
  22. internal double mouseHorizontalPosition;
  23. internal Boolean isMouseCaptured;
  24. internal NodeItem dragedElement;
  25. public bool IsMouseCaptured {
  26. get {
  27. return isMouseCaptured;
  28. }
  29. }
  30. public static String LayoutName()
  31. {
  32. return String.Empty;
  33. }
  34. public static Dictionary<String, Type> ChildTypesNames(Type t)
  35. {
  36. Assembly asm = t.Assembly;
  37. Dictionary<String, Type> classlist = new Dictionary<String, Type>();
  38. foreach (Type type in asm.GetTypes())
  39. {
  40. if (type.BaseType == t)
  41. {
  42. if (type.IsAbstract)
  43. {
  44. var c = ChildTypesNames(type);
  45. foreach (var item in c)
  46. {
  47. classlist.Add(item.Key, item.Value);
  48. }
  49. }
  50. else
  51. {
  52. String val = (String)type.GetMethod("LayoutName").Invoke(null, null);
  53. if(!classlist.ContainsKey(val))
  54. classlist.Add(val, type);
  55. }
  56. }
  57. }
  58. return classlist;
  59. }
  60. /** The explicitly set layout bounds. May be null. */
  61. protected Nullable<Rect> m_bounds = null;
  62. /** The explicitly set anchor point at which the layout can
  63. * be centered or rooted. May be null. */
  64. protected Point m_anchor;
  65. private IGraph m_Graph;
  66. public IGraph Graph
  67. {
  68. get { return m_Graph; }
  69. set
  70. {
  71. m_Graph = value;
  72. m_Graph.NewEdges += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Graph_NewEdges);
  73. m_Graph.OldElements += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Graph_OldElements);
  74. }
  75. }
  76. protected Boolean m_margin = false;
  77. protected double[] m_bpts = new double[4];
  78. protected Rect m_tmpb = new Rect();
  79. protected Point m_tmpa = new Point();
  80. private DispatcherTimer _timer;
  81. private Nullable<DateTime> m_duration = null;
  82. private Double m_steps = 0;
  83. private Double m_maxSteps = 0;
  84. protected Dictionary<VisualItem, float[]> newPosition; // new position of all nodes
  85. protected Dictionary<VisualItem, VisualItem> referrers;
  86. #region Constructor
  87. public Layout()
  88. {
  89. _timer = new DispatcherTimer();
  90. _timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
  91. _timer.Tick += new EventHandler(_timer_Tick);
  92. this.MouseMove += new System.Windows.Input.MouseEventHandler(Layout_MouseMove);
  93. }
  94. public Layout(String group)
  95. : this()
  96. {
  97. }
  98. public Layout(String group, long duration)
  99. : this()
  100. {
  101. }
  102. #endregion
  103. public ILayoutControler Controller
  104. {
  105. get;
  106. set;
  107. }
  108. void Graph_NewEdges(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
  109. {
  110. switch (e.Action)
  111. {
  112. case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
  113. foreach (EdgeItem item in e.NewItems)
  114. {
  115. var line = DrawLine(item.Source.X + ((GraphLayout.GraphRepresentation.NodeItem)item.Source).Width / 2, item.Source.Y + ((GraphLayout.GraphRepresentation.NodeItem)item.Source).Height / 2,
  116. item.Target.X + ((GraphLayout.GraphRepresentation.NodeItem)item.Target).Width / 2,
  117. item.Target.Y + ((GraphLayout.GraphRepresentation.NodeItem)item.Target).Height / 2);
  118. item.VisualLine = line;
  119. item.Children.Add(line);
  120. item.SetValue(Canvas.ZIndexProperty, -10);
  121. this.Children.Add(item);
  122. }
  123. break;
  124. case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
  125. foreach (EdgeItem item in e.OldItems)
  126. {
  127. this.Children.Remove(item);
  128. }
  129. break;
  130. case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
  131. break;
  132. case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
  133. break;
  134. default:
  135. break;
  136. }
  137. }
  138. void Graph_OldElements(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) {
  139. if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
  140. {
  141. foreach (NodeItem node in e.OldItems)
  142. {
  143. this.Children.Remove(node);
  144. }
  145. }
  146. }
  147. public static Line DrawLine(double pX1, double pY1, double pX2, double pY2)
  148. {
  149. LinearGradientBrush lgb = new LinearGradientBrush();
  150. lgb.GradientStops.Add(new GradientStop() { Color = Colors.White, Offset = 0 });
  151. lgb.GradientStops.Add(new GradientStop() { Color = Color.FromArgb(255, 128, 0, 0), Offset = 0.5 });
  152. lgb.GradientStops.Add(new GradientStop() { Color = Colors.White, Offset = 1.0 });
  153. Line edge = new Line()
  154. {
  155. X1 = pX1,
  156. X2 = pX2,
  157. Y1 = pY1,
  158. Y2 = pY2,
  159. //Stroke = lgb,
  160. Stroke = new SolidColorBrush(Color.FromArgb(255, 192, 192, 192)),
  161. StrokeThickness = 2.0
  162. };
  163. return edge;
  164. }
  165. void Layout_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
  166. {
  167. if (isMouseCaptured)
  168. {
  169. NodeItem item = dragedElement;
  170. // Calculate the current position of the object.
  171. double deltaV = e.GetPosition(null).Y - mouseVerticalPosition;
  172. double deltaH = e.GetPosition(null).X - mouseHorizontalPosition;
  173. double newTop = deltaV + item.Y;
  174. double newLeft = deltaH + item.X;
  175. // Set new position of object.
  176. //item.SetValue(Canvas.TopProperty, newTop);
  177. //item.SetValue(Canvas.LeftProperty, newLeft);
  178. item.X = (float)newLeft;
  179. item.Y = (float)newTop;
  180. // Update position global variables.
  181. mouseVerticalPosition = e.GetPosition(null).Y;
  182. mouseHorizontalPosition = e.GetPosition(null).X;
  183. }
  184. }
  185. void _timer_Tick(object sender, EventArgs e)
  186. {
  187. m_steps++;
  188. if (!m_duration.HasValue)
  189. {
  190. m_duration = DateTime.Now;
  191. }
  192. run(getPace(m_steps));
  193. if (m_steps >= m_maxSteps) {
  194. m_steps = 0;
  195. if (Controller != null)
  196. {
  197. Controller.ResumeLayout();
  198. }
  199. _timer.Stop();
  200. }
  201. }
  202. private double getPace(Double elapsedTime)
  203. {
  204. Double duration = getDuration();
  205. double frac = (duration == 0L ? 0.0 : ((double)elapsedTime) / duration);
  206. frac = Math.Min(1, Math.Max(0, frac));
  207. return pace(frac);
  208. }
  209. private Double getDuration()
  210. {
  211. return m_duration.HasValue ? m_maxSteps : 0; ;
  212. }
  213. private double pace(double f)
  214. {
  215. return (f == 0.0 || f == 1.0 ? f : sigmoid(f));
  216. }
  217. private double sigmoid(double x)
  218. {
  219. x = 12.0 * x - 6.0;
  220. return (1.0 / (1.0 + Math.Exp(-1.0 * x)));
  221. }
  222. public Rect getLayoutBounds()
  223. {
  224. if (!m_bounds.HasValue)
  225. {
  226. Double x = (Double) this.GetValue(Canvas.TopProperty);
  227. Double y = (Double) this.GetValue(Canvas.LeftProperty);
  228. Double width = (Double) this.GetValue(Canvas.WidthProperty);
  229. Double height = (Double) this.GetValue(Canvas.HeightProperty);
  230. m_bounds = new Rect(x,y,width,height);
  231. }
  232. return m_bounds.Value;
  233. }
  234. public Point getLayoutAnchor()
  235. {
  236. if (m_anchor != null)
  237. return m_anchor;
  238. else
  239. return new Point(0, 0);
  240. }
  241. public void setLayoutAnchor(Point a)
  242. {
  243. m_anchor = a;
  244. }
  245. public virtual bool Init()
  246. {
  247. newPosition = new Dictionary<VisualItem, float[]>(Graph.Nodes.Count);
  248. referrers = new Dictionary<VisualItem, VisualItem>(Graph.Nodes.Count);
  249. ((Graph)Graph).Visited = new Dictionary<VisualItem, bool>();
  250. foreach (var node in Graph.Nodes) {
  251. newPosition[node] = new float[2];
  252. referrers[node] = null;
  253. }
  254. if (((Graph)Graph).SelectedNode == null)
  255. ((NodeItem)Graph.Nodes[0]).Select();
  256. return true;
  257. }
  258. public virtual NodeItem getLayoutRoot()
  259. {
  260. return null;
  261. }
  262. protected abstract void run(double frac);
  263. public void DrawLayout(double frac)
  264. {
  265. {
  266. if (Controller != null)
  267. {
  268. Controller.SuspendLayout();
  269. }
  270. _timer.Interval = new TimeSpan(1000);
  271. m_maxSteps = frac;
  272. _timer.Start();
  273. }
  274. }
  275. protected void MoveToNewPosition(double frac) {
  276. foreach (var node in Graph.Nodes)
  277. node.MoveTo(referrers[node], (float)(node.X + (newPosition[node][0] - node.X) * frac),
  278. (float)(node.Y + (newPosition[node][1] - node.Y) * frac));
  279. }
  280. } // end of abstract class Layout
  281. }