zhu hong

zhu hong

  • NA
  • 1
  • 1.6k

people cube

May 18 2013 3:59 AM

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;
  }
 }
}