Hello , I am a WPF programmer And I met a problem recently.I use a custom ghaph control through an external assembly to make people cube View, but when the ghaph control's width and height is reduced to a certain range the internal nodes of ghaph will chaos. I can't solve it .Here is Front desk code reference the control and when Height and width is smaller the control can't work normal.
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="400" Width="400">
<graph:Graph Name="theGraph" NodesBindingPath="ChildNodes" Height="400" Width="400"
NodeTemplateSelector="{StaticResource nodeTemplateSelector}">
</graph:Graph>
</Grid>
The source of custom ghaph control in external assembly is here:
using J832.Wpf;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Microsoft.Samples.KMoore.WPFSamples.Graph
{
public class Graph : FrameworkElement
{
private class GraphContentPresenter : ContentPresenter
{
public bool New = true;
public Vector Velocity;
public bool WasCenter;
public ScaleTransform ScaleTransform;
private Point _location;
private Size _actualDesiredSize;
private Size _actualRenderSize;
private Vector _centerVector;
private Point _parentCenter;
private TranslateTransform _translateTransform;
public Point Location
{
get
{
return this._location;
}
set
{
if (this._location != value)
{
this._location = value;
this.updateTransform();
}
}
}
public Point ParentCenter
{
get
{
return this._parentCenter;
}
set
{
if (this._parentCenter != value)
{
this._parentCenter = value;
this.updateTransform();
}
}
}
public Point ActualLocation
{
get
{
return new Point(this._location.X + this._parentCenter.X, this._location.Y + this._parentCenter.Y);
}
}
public GraphContentPresenter(object content, BindingBase nodeTemplateBinding, BindingBase nodeTemplateSelectorBinding, bool offsetCenter)
{
base.Content = content;
base.SetBinding(ContentPresenter.ContentTemplateProperty, nodeTemplateBinding);
base.SetBinding(ContentPresenter.ContentTemplateSelectorProperty, nodeTemplateSelectorBinding);
this.ScaleTransform = new ScaleTransform();
if (offsetCenter)
{
this._translateTransform = new TranslateTransform(Graph.Rnd.NextDouble() - 0.5, Graph.Rnd.NextDouble() - 0.5);
}
else
{
this._translateTransform = new TranslateTransform();
}
base.RenderTransform = new TransformGroup
{
Children =
{
this.ScaleTransform,
this._translateTransform
}
};
DoubleAnimation animation = new DoubleAnimation(0.5, 1.0, Graph.s_showDuration);
base.BeginAnimation(UIElement.OpacityProperty, animation);
this.ScaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, animation);
this.ScaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, animation);
}
protected override Size MeasureOverride(Size availableSize)
{
this._actualDesiredSize = base.MeasureOverride(new Size(double.PositiveInfinity, double.PositiveInfinity));
return default(Size);
}
protected override Size ArrangeOverride(Size finalSize)
{
this._actualRenderSize = base.ArrangeOverride(this._actualDesiredSize);
this.ScaleTransform.CenterX = this._actualRenderSize.Width / 2.0;
this.ScaleTransform.CenterY = this._actualRenderSize.Height / 2.0;
this._centerVector.X = -this._actualRenderSize.Width / 2.0;
this._centerVector.Y = -this._actualRenderSize.Height / 2.0;
this.updateTransform();
return default(Size);
}
private void updateTransform()//??????
{
this._translateTransform.X = this._centerVector.X + this._location.X + this._parentCenter.X;
this._translateTransform.Y = this._centerVector.Y + this._location.Y + this._parentCenter.Y;
}
}
private const double s_terminalVelocity = 150.0;
private const double s_minVelocity = 0.05;
private const double c_minDampening = 0.01;
private const double c_maxDampening = 0.99;
public static readonly DependencyProperty CenterObjectProperty;
public static readonly DependencyProperty NodesBindingPathProperty;
public static readonly DependencyProperty NodeTemplateProperty;
public static readonly DependencyProperty NodeTemplateSelectorProperty;
public static readonly DependencyProperty DampeningProperty;
public static readonly DependencyProperty AttractionProperty;
public static readonly DependencyProperty LinePenProperty;
private static Pen DefaultPen;
private static readonly DependencyProperty NodesProperty;
private int _childCount;
private bool _isChildCountValid;
private object _centerDataInUse;
private IList _nodesInUse;
private bool _centerChanged;
private bool _nodesChanged;
private bool _nodeCollectionChanged;
private Graph.GraphContentPresenter m_centerGraphContentPresenter;
private bool _measureInvalidated;
private bool _stillMoving;
private Vector[,] _springForces;
private Point m_controlCenterPoint;
private int m_milliseconds = -2147483648;
private readonly NotifyCollectionChangedEventHandler _nodesChangedHandler;
private readonly List<Graph.GraphContentPresenter> _nodePresenters;
private readonly List<Graph.GraphContentPresenter> _fadingGCPList = new List<Graph.GraphContentPresenter>();
private readonly Binding m_nodeTemplateBinding;
private readonly Binding m_nodeTemplateSelectorBinding;
private readonly CompositionTargetRenderingListener m_listener = new CompositionTargetRenderingListener();
private readonly List<Graph.GraphContentPresenter> _needsMeasure = new List<Graph.GraphContentPresenter>();
private readonly List<Graph.GraphContentPresenter> _needsArrange = new List<Graph.GraphContentPresenter>();
private static readonly Random Rnd;
private static readonly Vector s_verticalVector;
private static readonly Vector s_horizontalVector;
private static readonly Duration s_hideDuration;
private static readonly Duration s_showDuration;
private static readonly TimeSpan s_maxSettleTime;
private static readonly Rect s_emptyRect;
protected override int VisualChildrenCount
{
get
{
if (!this._isChildCountValid)
{
this._childCount = 0;
if (this.m_centerGraphContentPresenter != null)
{
this._childCount++;
}
if (this._nodePresenters != null)
{
this._childCount += this._nodePresenters.Count;
}
this._childCount += this._fadingGCPList.Count;
this._isChildCountValid = true;
}
return this._childCount;
}
}
public object CenterObject
{
get
{
return base.GetValue(Graph.CenterObjectProperty);
}
set
{
base.SetValue(Graph.CenterObjectProperty, value);
}
}
public string NodesBindingPath
{
get
{
return (string)base.GetValue(Graph.NodesBindingPathProperty);
}
set
{
base.SetValue(Graph.NodesBindingPathProperty, value);
}
}
public DataTemplate NodeTemplate
{
get
{
return (DataTemplate)base.GetValue(Graph.NodeTemplateProperty);
}
set
{
base.SetValue(Graph.NodeTemplateProperty, value);
}
}
public DataTemplateSelector NodeTemplateSelector
{
get
{
return (DataTemplateSelector)base.GetValue(Graph.NodeTemplateSelectorProperty);
}
set
{
base.SetValue(Graph.NodeTemplateSelectorProperty, value);
}
}
public double Dampening
{
get
{
return (double)base.GetValue(Graph.DampeningProperty);
}
set
{
base.SetValue(Graph.DampeningProperty, value);
}
}
public double Attraction
{
get
{
return (double)base.GetValue(Graph.AttractionProperty);
}
set
{
base.SetValue(Graph.AttractionProperty, value);
}
}
public Pen LinePen
{
get
{
return (Pen)base.GetValue(Graph.LinePenProperty);
}
set
{
base.SetValue(Graph.LinePenProperty, value);
}
}
private IList Nodes
{
get
{
return (IList)base.GetValue(Graph.NodesProperty);
}
}
static Graph()
{
Graph.CenterObjectProperty = DependencyProperty.Register("CenterObject", typeof(object), typeof(Graph), Graph.getCenterObjectPropertyMetadata());
Graph.NodesBindingPathProperty = DependencyProperty.Register("NodesBindingPath", typeof(string), typeof(Graph), new FrameworkPropertyMetadata(new PropertyChangedCallback(Graph.NodesBindingPathPropertyChanged)));
Graph.NodeTemplateProperty = DependencyProperty.Register("NodeTemplate", typeof(DataTemplate), typeof(Graph), new FrameworkPropertyMetadata(null));
Graph.NodeTemplateSelectorProperty = DependencyProperty.Register("NodeTemplateSelector", typeof(DataTemplateSelector), typeof(Graph), new FrameworkPropertyMetadata(null));
Graph.DampeningProperty = DependencyProperty.Register("Dampening", typeof(double), typeof(Graph), new FrameworkPropertyMetadata(0.9, null, new CoerceValueCallback(Graph.CoerceDampeningPropertyCallback)));
Graph.AttractionProperty = DependencyProperty.Register("Attraction", typeof(double), typeof(Graph), new FrameworkPropertyMetadata(0.4, null, new CoerceValueCallback(Graph.CoerceAttractionPropertyCallback)));
Graph.LinePenProperty = DependencyProperty.Register("LinePen", typeof(Pen), typeof(Graph), new PropertyMetadata(Graph.GetPen()));
Graph.NodesProperty = DependencyProperty.Register("Nodes", typeof(IList), typeof(Graph), Graph.getNodesPropertyMetadata());
Graph.Rnd = new Random();
Graph.s_verticalVector = new Vector(0.0, 1.0);
Graph.s_horizontalVector = new Vector(1.0, 0.0);
Graph.s_hideDuration = new Duration(new TimeSpan(0, 0, 1));
Graph.s_showDuration = new Duration(new TimeSpan(0, 0, 0, 0, 500));
Graph.s_maxSettleTime = new TimeSpan(0, 0, 8);
Graph.s_emptyRect = default(Rect);
UIElement.ClipToBoundsProperty.OverrideMetadata(typeof(Graph), new FrameworkPropertyMetadata(true));
}
public Graph()
{
this.m_listener.WireParentLoadedUnloaded(this);
this.m_listener.Rendering += new EventHandler(this.compositionTarget_rendering);
this.m_nodeTemplateBinding = new Binding(Graph.NodeTemplateProperty.Name);
this.m_nodeTemplateBinding.Source = this;
this.m_nodeTemplateSelectorBinding = new Binding(Graph.NodeTemplateSelectorProperty.Name);
this.m_nodeTemplateSelectorBinding.Source = this;
this._nodesChangedHandler = delegate(object sender, NotifyCollectionChangedEventArgs e)
{
base.VerifyAccess();
base.InvalidateMeasure();
this._nodeCollectionChanged = true;
};
this._nodePresenters = new List<Graph.GraphContentPresenter>();
}
protected override Size MeasureOverride(Size availableSize)
{
this.handleChanges();
this._measureInvalidated = true;
this.m_listener.StartListening();
for (int i = 0; i < this._needsMeasure.Count; i++)
{
this._needsMeasure[i].Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
}
this._needsMeasure.Clear();
return default(Size);
}
protected override Size ArrangeOverride(Size finalSize)//?????
{
this.m_controlCenterPoint.X = finalSize.Width / 2.0;
this.m_controlCenterPoint.Y = finalSize.Height / 2.0;
for (int i = 0; i < this._needsArrange.Count; i++)
{
this._needsArrange[i].Arrange(Graph.s_emptyRect);
}
this._needsArrange.Clear();
return finalSize;
}
protected override Visual GetVisualChild(int index)
{
Visual result;
if (index < this._fadingGCPList.Count)
{
result = this._fadingGCPList[index];
}
else
{
index -= this._fadingGCPList.Count;
if (this._nodePresenters != null)
{
if (index < this._nodePresenters.Count)
{
result = this._nodePresenters[index];
return result;
}
index -= this._nodePresenters.Count;
}
if (index != 0)
{
throw new Exception("not a valid index");
}
result = this.m_centerGraphContentPresenter;
}
return result;
}
protected override void OnRender(DrawingContext drawingContext)
{
if (this.LinePen != null)
{
Pen linePen = this.LinePen;
if (this._nodePresenters != null && this.m_centerGraphContentPresenter != null)
{
for (int i = 0; i < this._nodePresenters.Count; i++)
{
drawingContext.DrawLine(linePen, this.m_centerGraphContentPresenter.ActualLocation, this._nodePresenters[i].ActualLocation);
}
}
}
}
private static PropertyMetadata getCenterObjectPropertyMetadata()
{
return new FrameworkPropertyMetadata
{
AffectsMeasure = true,
PropertyChangedCallback = new PropertyChangedCallback(Graph.CenterObjectPropertyChanged)
};
}
private static void CenterObjectPropertyChanged(DependencyObject element, DependencyPropertyChangedEventArgs args)
{
((Graph)element).CenterObjectPropertyChanged();
}
private void CenterObjectPropertyChanged()
{
this._centerChanged = true;
this.resetNodesBinding();
}
private static void NodesBindingPathPropertyChanged(DependencyObject element, DependencyPropertyChangedEventArgs e)
{
Graph graph = (Graph)element;
graph.resetNodesBinding();
}
private static object CoerceDampeningPropertyCallback(DependencyObject element, object baseValue)
{
return Graph.CoerceDampeningPropertyCallback((double)baseValue);
}
private static double CoerceDampeningPropertyCallback(double baseValue)
{
double result;
if (baseValue <= 0.01)
{
result = 0.01;
}
else
{
if (baseValue >= 0.99)
{
result = 0.99;
}
else
{
result = baseValue;
}
}
return result;
}
private static object CoerceAttractionPropertyCallback(DependencyObject element, object baseValue)
{
return Graph.CoerceAttractionPropertyCallback((double)baseValue);
}
private static double CoerceAttractionPropertyCallback(double baseValue)
{
double result;
if (baseValue <= 0.01)
{
result = 0.01;
}
else
{
if (baseValue >= 0.99)
{
result = 0.99;
}
else
{
result = baseValue;
}
}
return result;
}
private static Pen GetPen()
{
if (Graph.DefaultPen == null)
{
Graph.DefaultPen = new Pen(Brushes.Gray, 1.0);
Graph.DefaultPen.Freeze();
}
return Graph.DefaultPen;
}
private void resetNodesBinding()
{
if (this.NodesBindingPath == null)
{
BindingOperations.ClearBinding(this, Graph.NodesProperty);
}
else
{
Binding binding = Graph.GetBinding(this.NodesBindingPath, this.CenterObject);
if (binding == null)
{
BindingOperations.ClearBinding(this, Graph.NodesProperty);
}
else
{
BindingOperations.SetBinding(this, Graph.NodesProperty, binding);
}
}
}
private void compositionTarget_rendering(object sender, EventArgs args)
{
Debug.Assert(this._nodePresenters != null);
if (this._springForces == null)
{
this._springForces = new Vector[this._nodePresenters.Count, this._nodePresenters.Count];
}
else
{
if (this._springForces.GetUpperBound(0) + 1 < this._nodePresenters.Count)
{
this._springForces = new Vector[this._nodePresenters.Count, this._nodePresenters.Count];
}
}
bool flag = false;
if (this._measureInvalidated || this._stillMoving)
{
if (this._measureInvalidated)
{
this.m_milliseconds = Environment.TickCount;
}
if (this.m_centerGraphContentPresenter != null)
{
if (this.m_centerGraphContentPresenter.New)
{
this.m_centerGraphContentPresenter.ParentCenter = this.m_controlCenterPoint;
this.m_centerGraphContentPresenter.New = false;
flag = true;
}
else
{
Vector vector = Graph.GetAttractionForce(Graph.ensureNonzeroVector((Vector)this.m_centerGraphContentPresenter.Location));
if (Graph.updateGraphCP(this.m_centerGraphContentPresenter, vector, this.Dampening, this.Attraction, this.m_controlCenterPoint))
{
flag = true;
}
}
}
for (int i = 0; i < this._nodePresenters.Count; i++)
{
Graph.GraphContentPresenter graphContentPresenter = this._nodePresenters[i];
if (graphContentPresenter.New)
{
graphContentPresenter.New = false;
flag = true;
}
for (int j = i + 1; j < this._nodePresenters.Count; j++)
{
Vector x = Graph.ensureNonzeroVector(graphContentPresenter.Location - this._nodePresenters[j].Location);
Vector repulsiveForce = Graph.GetRepulsiveForce(x);
this._springForces[i, j] = repulsiveForce;
}
}
Point point = (this.m_centerGraphContentPresenter != null) ? this.m_centerGraphContentPresenter.Location : default(Point);
for (int i = 0; i < this._nodePresenters.Count; i++)
{
Vector vector = default(Vector) + Graph.GetVectorSum(i, this._nodePresenters.Count, this._springForces);
vector += Graph.GetSpringForce(Graph.ensureNonzeroVector(this._nodePresenters[i].Location - point));
vector += Graph.GetWallForce(base.RenderSize, this._nodePresenters[i].Location);
if (Graph.updateGraphCP(this._nodePresenters[i], vector, this.Dampening, this.Attraction, this.m_controlCenterPoint))
{
flag = true;
}
}
for (int i = 0; i < this._fadingGCPList.Count; i++)
{
if (!this._fadingGCPList[i].WasCenter)
{
Vector vector2 = Graph.ensureNonzeroVector(this._fadingGCPList[i].Location - point);
vector2.Normalize();
vector2 *= 20.0;
if (Graph.updateGraphCP(this._fadingGCPList[i], vector2, this.Dampening, this.Attraction, this.m_controlCenterPoint))
{
flag = true;
}
}
}
if (flag && this.belowMaxSettleTime())
{
this._stillMoving = true;
base.InvalidateVisual();
}
else
{
this._stillMoving = false;
this.m_listener.StopListening();
}
this._measureInvalidated = false;
}
}
private bool belowMaxSettleTime()
{
Debug.Assert(this.m_milliseconds != -2147483648);
return Graph.s_maxSettleTime > TimeSpan.FromMilliseconds((double)(Environment.TickCount - this.m_milliseconds));
}
private static Vector ensureNonzeroVector(Vector vector)
{
Vector result;
if (vector.Length > 0.0)
{
result = vector;
}
else
{
result = new Vector(Graph.Rnd.NextDouble() - 0.5, Graph.Rnd.NextDouble() - 0.5);
}
return result;
}
private static bool updateGraphCP(Graph.GraphContentPresenter graphContentPresenter, Vector forceVector, double coefficientOfDampening, double frameRate, Point parentCenter)
{
bool flag = graphContentPresenter.ParentCenter != parentCenter;
if (flag)
{
graphContentPresenter.ParentCenter = parentCenter;
}
Debug.Assert(coefficientOfDampening > 0.0);
Debug.Assert(coefficientOfDampening < 1.0);
graphContentPresenter.Velocity *= 1.0 - coefficientOfDampening * frameRate;
graphContentPresenter.Velocity += forceVector * frameRate;
if (graphContentPresenter.Velocity.Length > 150.0)
{
graphContentPresenter.Velocity *= 150.0 / graphContentPresenter.Velocity.Length;
}
bool result;
if (graphContentPresenter.Velocity.Length > 0.05 && forceVector.Length > 0.05)
{
graphContentPresenter.Location += graphContentPresenter.Velocity * frameRate;
result = true;
}
else
{
graphContentPresenter.Velocity = default(Vector);
result = flag;
}
return result;
}
private void beginRemoveAnimation(Graph.GraphContentPresenter graphContentPresenter, bool isCenter)
{
Debug.Assert(VisualTreeHelper.GetParent(graphContentPresenter) == this);
base.InvalidateVisual();
this._fadingGCPList.Add(graphContentPresenter);
this._isChildCountValid = false;
graphContentPresenter.IsHitTestVisible = false;
if (isCenter)
{
graphContentPresenter.WasCenter = true;
}
ScaleTransform scaleTransform = graphContentPresenter.ScaleTransform;
DoubleAnimation doubleAnimation = new DoubleAnimation(0.0, Graph.s_hideDuration);
doubleAnimation.Completed += delegate(object sender, EventArgs e)
{
this.CleanUpGCP(graphContentPresenter);
};
doubleAnimation.FillBehavior = FillBehavior.Stop;
doubleAnimation.Freeze();
scaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, doubleAnimation);
scaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, doubleAnimation);
graphContentPresenter.BeginAnimation(UIElement.OpacityProperty, doubleAnimation);
}
private void CleanUpGCP(Graph.GraphContentPresenter contentPresenter)
{
if (this._fadingGCPList.Contains(contentPresenter))
{
Debug.Assert(VisualTreeHelper.GetParent(contentPresenter) == this);
base.RemoveVisualChild(contentPresenter);
this._isChildCountValid = false;
this._fadingGCPList.Remove(contentPresenter);
}
}
private void handleChanges()
{
this.handleNodesChangedWiring();
if (this._centerChanged && this._nodeCollectionChanged && this.CenterObject != null && this.m_centerGraphContentPresenter != null)
{
Debug.Assert(!this.CenterObject.Equals(this._centerDataInUse));
Debug.Assert(this.m_centerGraphContentPresenter.Content == null || this.m_centerGraphContentPresenter.Content.Equals(this._centerDataInUse));
this._centerDataInUse = this.CenterObject;
Graph.GraphContentPresenter graphContentPresenter = null;
for (int i = 0; i < this._nodePresenters.Count; i++)
{
if (this._nodePresenters[i].Content.Equals(this.CenterObject))
{
graphContentPresenter = this._nodePresenters[i];
this._nodePresenters[i] = null;
break;
}
}
int num = -1;
Graph.GraphContentPresenter graphContentPresenter2 = null;
for (int i = 0; i < this._nodesInUse.Count; i++)
{
if (this._nodesInUse[i] != null && this.m_centerGraphContentPresenter.Content != null && this._nodesInUse[i].Equals(this.m_centerGraphContentPresenter.Content))
{
num = i;
graphContentPresenter2 = this.m_centerGraphContentPresenter;
this.m_centerGraphContentPresenter = null;
break;
}
}
Graph.GraphContentPresenter[] array = new Graph.GraphContentPresenter[this._nodesInUse.Count];
if (graphContentPresenter2 != null)
{
array[num] = graphContentPresenter2;
}
for (int i = 0; i < this._nodesInUse.Count; i++)
{
if (array[i] == null)
{
for (int j = 0; j < this._nodePresenters.Count; j++)
{
if (this._nodePresenters[j] != null)
{
if (this._nodesInUse[i].Equals(this._nodePresenters[j].Content))
{
Debug.Assert(array[i] == null);
array[i] = this._nodePresenters[j];
this._nodePresenters[j] = null;
break;
}
}
}
}
}
if (this.m_centerGraphContentPresenter == null)
{
if (graphContentPresenter == null)
{
this.m_centerGraphContentPresenter = this.GetGraphContentPresenter(this.CenterObject, this.m_nodeTemplateBinding, this.m_nodeTemplateSelectorBinding, false);
base.AddVisualChild(this.m_centerGraphContentPresenter);
}
else
{
this.m_centerGraphContentPresenter = graphContentPresenter;
Debug.Assert(VisualTreeHelper.GetParent(graphContentPresenter) == this);
}
}
else
{
if (graphContentPresenter == null)
{
this.m_centerGraphContentPresenter.Content = this.CenterObject;
}
else
{
this.beginRemoveAnimation(this.m_centerGraphContentPresenter, true);
this.m_centerGraphContentPresenter = graphContentPresenter;
Debug.Assert(VisualTreeHelper.GetParent(graphContentPresenter) == this);
}
}
for (int i = 0; i < this._nodePresenters.Count; i++)
{
if (this._nodePresenters[i] != null)
{
this.beginRemoveAnimation(this._nodePresenters[i], false);
}
}
for (int i = 0; i < this._nodesInUse.Count; i++)
{
if (array[i] == null)
{
Graph.GraphContentPresenter graphContentPresenter3 = this.GetGraphContentPresenter(this._nodesInUse[i], this.m_nodeTemplateBinding, this.m_nodeTemplateSelectorBinding, true);
base.AddVisualChild(graphContentPresenter3);
array[i] = graphContentPresenter3;
}
}
this._nodePresenters.Clear();
this._nodePresenters.AddRange(array);
this._isChildCountValid = false;
this._centerChanged = false;
this._nodeCollectionChanged = false;
}
else
{
if (this._centerChanged)
{
this._centerDataInUse = this.CenterObject;
if (this.m_centerGraphContentPresenter != null)
{
Debug.Assert(this._centerDataInUse == null);
this.beginRemoveAnimation(this.m_centerGraphContentPresenter, true);
this.m_centerGraphContentPresenter = null;
}
if (this._centerDataInUse != null)
{
this.SetUpCleanCenter(this._centerDataInUse);
}
this._centerChanged = false;
}
if (this._nodeCollectionChanged)
{
this.SetupNodes(this.Nodes);
this._nodesInUse = this.Nodes;
this._nodeCollectionChanged = false;
}
}
if (this.CenterObject != null)
{
this.CenterObject.Equals(this._centerDataInUse);
Debug.Assert(this.m_centerGraphContentPresenter != null);
}
else
{
Debug.Assert(this._centerDataInUse == null);
}
if (this.Nodes != null)
{
Debug.Assert(this._nodePresenters != null);
Debug.Assert(this.Nodes.Count == this._nodePresenters.Count);
Debug.Assert(this._nodesInUse == this.Nodes);
}
else
{
Debug.Assert(this._nodesInUse == null);
if (this._nodePresenters != null)
{
Debug.Assert(this._nodePresenters.Count == 0);
}
}
}
private void handleNodesChangedWiring()
{
if (this._nodesChanged)
{
INotifyCollectionChanged notifyCollectionChanged = this._nodesInUse as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged -= this._nodesChangedHandler;
}
INotifyCollectionChanged notifyCollectionChanged2 = this.Nodes as INotifyCollectionChanged;
if (notifyCollectionChanged2 != null)
{
notifyCollectionChanged2.CollectionChanged += this._nodesChangedHandler;
}
this._nodesInUse = this.Nodes;
this._nodesChanged = false;
}
}
private void SetupNodes(IList nodes)
{
for (int i = 0; i < this._nodePresenters.Count; i++)
{
Debug.Assert(this._nodePresenters[i] != null);
Debug.Assert(VisualTreeHelper.GetParent(this._nodePresenters[i]) == this);
}
int num = (nodes == null) ? 0 : nodes.Count;
Graph.GraphContentPresenter[] array = new Graph.GraphContentPresenter[num];
for (int i = 0; i < num; i++)
{
for (int j = 0; j < this._nodePresenters.Count; j++)
{
if (this._nodePresenters[j] != null)
{
if (nodes[i] == this._nodePresenters[j].Content)
{
array[i] = this._nodePresenters[j];
this._nodePresenters[j] = null;
break;
}
}
}
}
for (int i = 0; i < this._nodePresenters.Count; i++)
{
if (this._nodePresenters[i] != null)
{
this.beginRemoveAnimation(this._nodePresenters[i], false);
this._nodePresenters[i] = null;
}
}
for (int i = 0; i < array.Length; i++)
{
if (array[i] == null)
{
array[i] = this.GetGraphContentPresenter(nodes[i], this.m_nodeTemplateBinding, this.m_nodeTemplateSelectorBinding, true);
base.AddVisualChild(array[i]);
}
}
for (int i = 0; i < this._nodePresenters.Count; i++)
{
Debug.Assert(this._nodePresenters[i] == null);
}
for (int i = 0; i < array.Length; i++)
{
Debug.Assert(array[i] != null);
Debug.Assert(VisualTreeHelper.GetParent(array[i]) == this);
Debug.Assert(array[i].Content == nodes[i]);
}
this._nodePresenters.Clear();
this._nodePresenters.AddRange(array);
this._isChildCountValid = false;
}
private void SetUpCleanCenter(object newCenter)
{
Debug.Assert(this.m_centerGraphContentPresenter == null);
this.m_centerGraphContentPresenter = this.GetGraphContentPresenter(newCenter, this.m_nodeTemplateBinding, this.m_nodeTemplateSelectorBinding, false);
base.AddVisualChild(this.m_centerGraphContentPresenter);
this._isChildCountValid = false;
}
private static PropertyMetadata getNodesPropertyMetadata()
{
return new FrameworkPropertyMetadata
{
AffectsMeasure = true,
PropertyChangedCallback = new PropertyChangedCallback(Graph.NodesPropertyChanged)
};
}
private static void NodesPropertyChanged(DependencyObject element, DependencyPropertyChangedEventArgs args)
{
((Graph)element).NodesPropertyChanged();
}
private void NodesPropertyChanged()
{
this._nodeCollectionChanged = true;
this._nodesChanged = true;
}
private Graph.GraphContentPresenter GetGraphContentPresenter(object content, BindingBase nodeTemplateBinding, BindingBase nodeTemplateSelectorBinding, bool offsetCenter)
{
Graph.GraphContentPresenter graphContentPresenter = new Graph.GraphContentPresenter(content, nodeTemplateBinding, nodeTemplateSelectorBinding, offsetCenter);
this._needsMeasure.Add(graphContentPresenter);
this._needsArrange.Add(graphContentPresenter);
return graphContentPresenter;
}
private static Binding GetBinding(string bindingPath, object source)
{
Binding binding = null;
try
{
binding = new Binding(bindingPath);
binding.Source = source;
binding.Mode = BindingMode.OneWay;
}
catch (InvalidOperationException)
{
}
return binding;
}
private static PropertyPath ClonePropertyPath(PropertyPath path)
{
return new PropertyPath(path.Path, new object[]
{
path.PathParameters
});
}
private static Vector GetVectorSum(int itemIndex, int itemCount, Vector[,] vectors)
{
Debug.Assert(itemIndex >= 0);
Debug.Assert(itemIndex < itemCount);
Vector vector = default(Vector);
for (int i = 0; i < itemCount; i++)
{
if (i != itemIndex)
{
vector += Graph.GetVector(itemIndex, i, vectors);
}
}
return vector;
}
private static Vector GetVector(int a, int b, Vector[,] vectors)
{
Debug.Assert(a != b);
Vector result;
if (a < b)
{
result = vectors[a, b];
}
else
{
result = -vectors[b, a];
}
return result;
}
private static Point GetRandomPoint(Size range)
{
return new Point(Graph.Rnd.NextDouble() * range.Width, Graph.Rnd.NextDouble() * range.Height);
}
private static Rect GetCenteredRect(Size elementSize, Point center)
{
double x = center.X - elementSize.Width / 2.0;
double y = center.Y - elementSize.Height / 2.0;
return new Rect(x, y, elementSize.Width, elementSize.Height);
}
private static Vector GetSpringForce(Vector x)
{
Vector vector = default(Vector) + Graph.GetAttractionForce(x);
vector += Graph.GetRepulsiveForce(x);
Debug.Assert(Graph.IsGoodVector(vector));
return vector;
}
private static Vector GetAttractionForce(Vector x)
{
Vector vector = -0.2 * Graph.Normalize(x) * x.Length;
Debug.Assert(Graph.IsGoodVector(vector));
return vector;
}
private static Vector GetRepulsiveForce(Vector x)
{
Vector vector = 0.1 * Graph.Normalize(x) / Math.Pow(x.Length / 1000.0, 2.0);
Debug.Assert(Graph.IsGoodVector(vector));
return vector;
}
private static Vector Normalize(Vector v)
{
v.Normalize();
Debug.Assert(Graph.IsGoodVector(v));
return v;
}
private static Vector GetWallForce(Size area, Point location)
{
Vector vector = default(Vector) + Graph.s_verticalVector * Graph.GetForce(-location.Y - area.Height / 2.0);
vector += -Graph.s_verticalVector * Graph.GetForce(location.Y - area.Height / 2.0);
vector += Graph.s_horizontalVector * Graph.GetForce(-location.X - area.Width / 2.0);
vector += -Graph.s_horizontalVector * Graph.GetForce(location.X - area.Width / 2.0);
return vector * 1000.0;
}
private static double GetForce(double x)
{
return Graph.GetSCurve((x + 100.0) / 200.0);
}
private static bool IsGoodDouble(double d)
{
return !double.IsNaN(d) && !double.IsInfinity(d);
}
private static bool IsGoodVector(Vector v)
{
return Graph.IsGoodDouble(v.X) && Graph.IsGoodDouble(v.Y);
}
private static double GetSCurve(double x)
{
return 0.5 + Math.Sin(Math.Abs(x * 1.5707963267948966) - Math.Abs(x * 1.5707963267948966 - 1.5707963267948966)) / 2.0;
}
}
}