/CARE 2.0/GraphLayout/Layout.cs
# · C# · 327 lines · 267 code · 46 blank · 14 comment · 23 complexity · 1c4b2a82543e2520c2763835f65bdf55 MD5 · raw file
- using System.Windows.Shapes;
- using System.Windows;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Windows.Controls;
- using GraphLayout.Interface;
- using System.Windows.Threading;
- using GraphLayout.GraphRepresentation;
- using System.Windows.Media;
- using System.Reflection;
-
- namespace prefuse.action.layout
- {
-
- /**
- * Abstract base class providing convenience methods for layout algorithms.
- *
- * @author <a href="http://jheer.org">jeffrey heer</a>
- */
- public abstract class Layout : Canvas
- {
- internal double mouseVerticalPosition;
- internal double mouseHorizontalPosition;
- internal Boolean isMouseCaptured;
- internal NodeItem dragedElement;
-
- public bool IsMouseCaptured {
- get {
- return isMouseCaptured;
- }
- }
-
- public static String LayoutName()
- {
- return String.Empty;
- }
-
- public static Dictionary<String, Type> ChildTypesNames(Type t)
- {
- Assembly asm = t.Assembly;
-
- Dictionary<String, Type> classlist = new Dictionary<String, Type>();
-
- foreach (Type type in asm.GetTypes())
- {
- if (type.BaseType == t)
- {
- if (type.IsAbstract)
- {
- var c = ChildTypesNames(type);
- foreach (var item in c)
- {
- classlist.Add(item.Key, item.Value);
- }
- }
- else
- {
- String val = (String)type.GetMethod("LayoutName").Invoke(null, null);
- if(!classlist.ContainsKey(val))
- classlist.Add(val, type);
- }
- }
- }
-
- return classlist;
- }
-
- /** The explicitly set layout bounds. May be null. */
- protected Nullable<Rect> m_bounds = null;
- /** The explicitly set anchor point at which the layout can
- * be centered or rooted. May be null. */
- protected Point m_anchor;
- private IGraph m_Graph;
-
- public IGraph Graph
- {
- get { return m_Graph; }
- set
- {
- m_Graph = value;
- m_Graph.NewEdges += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Graph_NewEdges);
- m_Graph.OldElements += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Graph_OldElements);
- }
- }
- protected Boolean m_margin = false;
- protected double[] m_bpts = new double[4];
- protected Rect m_tmpb = new Rect();
- protected Point m_tmpa = new Point();
- private DispatcherTimer _timer;
- private Nullable<DateTime> m_duration = null;
- private Double m_steps = 0;
- private Double m_maxSteps = 0;
-
- protected Dictionary<VisualItem, float[]> newPosition; // new position of all nodes
- protected Dictionary<VisualItem, VisualItem> referrers;
-
- #region Constructor
- public Layout()
- {
- _timer = new DispatcherTimer();
- _timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
- _timer.Tick += new EventHandler(_timer_Tick);
- this.MouseMove += new System.Windows.Input.MouseEventHandler(Layout_MouseMove);
- }
-
- public Layout(String group)
- : this()
- {
- }
-
- public Layout(String group, long duration)
- : this()
- {
- }
- #endregion
-
- public ILayoutControler Controller
- {
- get;
- set;
- }
-
- void Graph_NewEdges(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
- {
- switch (e.Action)
- {
- case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
- foreach (EdgeItem item in e.NewItems)
- {
- var line = DrawLine(item.Source.X + ((GraphLayout.GraphRepresentation.NodeItem)item.Source).Width / 2, item.Source.Y + ((GraphLayout.GraphRepresentation.NodeItem)item.Source).Height / 2,
- item.Target.X + ((GraphLayout.GraphRepresentation.NodeItem)item.Target).Width / 2,
- item.Target.Y + ((GraphLayout.GraphRepresentation.NodeItem)item.Target).Height / 2);
-
- item.VisualLine = line;
- item.Children.Add(line);
- item.SetValue(Canvas.ZIndexProperty, -10);
- this.Children.Add(item);
- }
- break;
- case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
- foreach (EdgeItem item in e.OldItems)
- {
- this.Children.Remove(item);
- }
- break;
- case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
- break;
- case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
- break;
- default:
- break;
- }
- }
-
- void Graph_OldElements(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) {
- if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
- {
- foreach (NodeItem node in e.OldItems)
- {
- this.Children.Remove(node);
- }
- }
-
-
- }
-
- public static Line DrawLine(double pX1, double pY1, double pX2, double pY2)
- {
- LinearGradientBrush lgb = new LinearGradientBrush();
- lgb.GradientStops.Add(new GradientStop() { Color = Colors.White, Offset = 0 });
- lgb.GradientStops.Add(new GradientStop() { Color = Color.FromArgb(255, 128, 0, 0), Offset = 0.5 });
- lgb.GradientStops.Add(new GradientStop() { Color = Colors.White, Offset = 1.0 });
-
- Line edge = new Line()
- {
- X1 = pX1,
- X2 = pX2,
- Y1 = pY1,
- Y2 = pY2,
- //Stroke = lgb,
- Stroke = new SolidColorBrush(Color.FromArgb(255, 192, 192, 192)),
- StrokeThickness = 2.0
- };
-
- return edge;
- }
-
- void Layout_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
- {
- if (isMouseCaptured)
- {
- NodeItem item = dragedElement;
- // Calculate the current position of the object.
- double deltaV = e.GetPosition(null).Y - mouseVerticalPosition;
- double deltaH = e.GetPosition(null).X - mouseHorizontalPosition;
- double newTop = deltaV + item.Y;
- double newLeft = deltaH + item.X;
-
- // Set new position of object.
- //item.SetValue(Canvas.TopProperty, newTop);
- //item.SetValue(Canvas.LeftProperty, newLeft);
-
- item.X = (float)newLeft;
- item.Y = (float)newTop;
-
- // Update position global variables.
- mouseVerticalPosition = e.GetPosition(null).Y;
- mouseHorizontalPosition = e.GetPosition(null).X;
- }
- }
-
- void _timer_Tick(object sender, EventArgs e)
- {
- m_steps++;
- if (!m_duration.HasValue)
- {
- m_duration = DateTime.Now;
- }
- run(getPace(m_steps));
-
- if (m_steps >= m_maxSteps) {
- m_steps = 0;
- if (Controller != null)
- {
- Controller.ResumeLayout();
- }
- _timer.Stop();
- }
- }
-
- private double getPace(Double elapsedTime)
- {
- Double duration = getDuration();
- double frac = (duration == 0L ? 0.0 : ((double)elapsedTime) / duration);
- frac = Math.Min(1, Math.Max(0, frac));
- return pace(frac);
- }
-
- private Double getDuration()
- {
- return m_duration.HasValue ? m_maxSteps : 0; ;
- }
-
- private double pace(double f)
- {
- return (f == 0.0 || f == 1.0 ? f : sigmoid(f));
- }
-
- private double sigmoid(double x)
- {
- x = 12.0 * x - 6.0;
- return (1.0 / (1.0 + Math.Exp(-1.0 * x)));
- }
-
- public Rect getLayoutBounds()
- {
- if (!m_bounds.HasValue)
- {
- Double x = (Double) this.GetValue(Canvas.TopProperty);
- Double y = (Double) this.GetValue(Canvas.LeftProperty);
- Double width = (Double) this.GetValue(Canvas.WidthProperty);
- Double height = (Double) this.GetValue(Canvas.HeightProperty);
-
- m_bounds = new Rect(x,y,width,height);
- }
- return m_bounds.Value;
- }
-
- public Point getLayoutAnchor()
- {
- if (m_anchor != null)
- return m_anchor;
- else
- return new Point(0, 0);
- }
-
- public void setLayoutAnchor(Point a)
- {
- m_anchor = a;
- }
-
- public virtual bool Init()
- {
- newPosition = new Dictionary<VisualItem, float[]>(Graph.Nodes.Count);
- referrers = new Dictionary<VisualItem, VisualItem>(Graph.Nodes.Count);
- ((Graph)Graph).Visited = new Dictionary<VisualItem, bool>();
-
- foreach (var node in Graph.Nodes) {
- newPosition[node] = new float[2];
- referrers[node] = null;
- }
-
- if (((Graph)Graph).SelectedNode == null)
- ((NodeItem)Graph.Nodes[0]).Select();
-
- return true;
- }
-
- public virtual NodeItem getLayoutRoot()
- {
- return null;
- }
-
- protected abstract void run(double frac);
-
- public void DrawLayout(double frac)
- {
- {
- if (Controller != null)
- {
- Controller.SuspendLayout();
- }
- _timer.Interval = new TimeSpan(1000);
- m_maxSteps = frac;
- _timer.Start();
- }
- }
-
- protected void MoveToNewPosition(double frac) {
- foreach (var node in Graph.Nodes)
- node.MoveTo(referrers[node], (float)(node.X + (newPosition[node][0] - node.X) * frac),
- (float)(node.Y + (newPosition[node][1] - node.Y) * frac));
- }
-
- } // end of abstract class Layout
- }