source: trunk/CrypPlugins/WorkspaceManager/View/VisualComponents/CryptoLineView/CryptoLineView.cs @ 2935

Last change on this file since 2935 was 2935, checked in by kopal, 11 years ago

the color of the lines now change if the lines are "active" during the execution

File size: 34.2 KB
Line 
1using System;
2using System.ComponentModel;
3using System.Windows;
4using System.Windows.Media;
5using System.Windows.Input;
6using System.Windows.Controls;
7using System.Windows.Shapes;
8using System.Reflection;
9using System.Windows.Threading;
10using WorkspaceManager.View.Interface;
11using WorkspaceManager.Model;
12using System.Windows.Documents;
13using System.Collections.Generic;
14using System.Threading;
15using WorkspaceManager.View.Container;
16using System.Collections;
17using WorkspaceManager.View.VisualComponents.StackFrameDijkstra;
18using System.Windows.Data;
19using WorkspaceManagerModel.Model.Interfaces;
20using WorkspaceManagerModel.Model.Operations;
21
22namespace WorkspaceManager.View.VisualComponents
23{
24        public sealed class CryptoLineView : Shape, IConnection, IUpdateableView
25    {
26        #region Variables
27
28        public static readonly DependencyProperty IsDraggingDependencyProperty = DependencyProperty.Register("IsDragging", typeof(bool), typeof(CryptoLineView), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnDraggingPropertyChanged)));
29
30        [TypeConverter(typeof(bool))]
31        public bool IsDragging
32        {
33            get { return (bool)base.GetValue(IsDraggingDependencyProperty); }
34            set
35            {
36                base.SetValue(IsDraggingDependencyProperty, value);
37            }
38        }
39
40        private static void OnDraggingPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
41        {
42            CryptoLineView line = (CryptoLineView)d;
43            Panel p = (line.Parent as Panel);
44            if (p == null)
45                return;
46            foreach (UIElement shape in p.Children)
47            {
48                if (shape is CryptoLineView)
49                    shape.InvalidateVisual();
50            }
51        }
52
53        private IntersectPoint intersectPoint;
54        private List<FromTo> pointList = new List<FromTo>();
55        public HashSet<CryptoLineView> UpdateList = new HashSet<CryptoLineView>();
56
57        private ConnectionModel model;
58        public ConnectionModel Model
59        {
60            get { return model; }
61            private set { model = value; }
62        }
63        private static double offset = 6;
64
65        #endregion
66
67        #region Dependency Properties
68
69        public static readonly DependencyProperty StartPointProperty = DependencyProperty.Register("StartPoint", typeof(Point), typeof(CryptoLineView), new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
70        public static readonly DependencyProperty EndPointProperty = DependencyProperty.Register("EndPoint", typeof(Point), typeof(CryptoLineView), new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
71       
72                #endregion
73
74                #region CLR Properties
75
76        public Point StartPoint
77        {
78            get { return (Point)GetValue(StartPointProperty); }
79            set 
80            {
81                SetValue(StartPointProperty, value);
82            }
83        }
84
85        public Point EndPoint
86        {
87            get { return (Point)GetValue(EndPointProperty); }
88            set 
89            {
90                SetValue(EndPointProperty, value);
91            }
92        }
93
94                #endregion
95
96        public CryptoLineView()
97        {
98            Stroke = Brushes.Black;
99            StrokeThickness = 2;
100        }
101
102        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
103        {
104            base.OnPropertyChanged(e);
105        }
106
107        protected override void OnMouseDown(MouseButtonEventArgs args)
108        {
109            if (args.RightButton == MouseButtonState.Pressed)
110            {
111                if (this.model != null && !((WorkspaceManager)this.model.WorkspaceModel.MyEditor).isExecuting())
112                {
113                    this.model.WorkspaceModel.ModifyModel(new DeleteConnectionModelOperation(this.model));
114                }
115            }           
116        }
117
118        public CryptoLineView(ConnectionModel connectionModel, ConnectorView source, ConnectorView target)
119        {
120            this.Loaded += new RoutedEventHandler(CryptoLineView_Loaded);
121            this.Model = connectionModel;
122            this.StartPointSource = source;
123            this.EndPointSource = target;
124        }
125
126        void CryptoLineView_Loaded(object sender, RoutedEventArgs e)
127        {
128            Color color = ColorHelper.GetLineColor(this.Model.ConnectionType);
129            Stroke = new SolidColorBrush(color);
130            StrokeThickness = 2;
131        }
132
133        private void makeBinding(ConnectorView source, ConnectorView target)
134        {
135            MultiBinding multiBinding = new MultiBinding();
136            multiBinding.Converter = new MultiDragValueConverter();
137
138            Binding bind = new Binding();
139            bind.Source = source.Parent;
140            bind.Path = new PropertyPath(PluginContainerView.IsDragStartedDependencyProperty);
141            multiBinding.Bindings.Add(bind);
142
143            bind = new Binding();
144            bind.Source = target.Parent;
145            bind.Path = new PropertyPath(PluginContainerView.IsDragStartedDependencyProperty);
146            multiBinding.Bindings.Add(bind);
147
148            SetBinding(CryptoLineView.IsDraggingDependencyProperty, multiBinding);
149        }
150
151                #region Overrides
152
153                protected override Geometry DefiningGeometry
154                {
155                        get
156                        {
157                                StreamGeometry geometry = new StreamGeometry();
158                                geometry.FillRule = FillRule.EvenOdd;
159
160                                using (StreamGeometryContext context = geometry.Open())
161                                {
162                    internalGeometryDraw(context);
163                                }
164
165                                geometry.Freeze();
166                                return geometry;
167                        }
168                }               
169
170                #endregion
171
172                #region Privates
173        private bool isBetween(double min, double max, double between)
174        {
175            return min <= between && between <= max;
176        }
177
178        private bool findIntersection(Point StartPoint, Point EndPoint, Point StartPointSec, Point EndPointSec)
179        {
180            if (StartPoint.X != EndPoint.X &&
181                StartPoint.Y != EndPoint.Y)
182            {
183                return false;
184            }
185            if (StartPointSec.X != EndPointSec.X &&
186                StartPointSec.Y != EndPointSec.Y)
187            {
188                return false;
189            }
190
191            // parallel, also overlapping case
192            if (StartPoint.X == EndPoint.X && StartPointSec.X == EndPointSec.X ||
193                StartPoint.Y == EndPoint.Y && StartPointSec.Y == EndPointSec.Y)
194            {
195                return false;
196            }
197            else
198            {
199                // orthogonal but maybe not intersected
200                Point up, down, left, right;
201                if (StartPoint.X == EndPoint.X)
202                {
203                    up = StartPoint;
204                    down = EndPoint;
205                    left = StartPointSec;
206                    right = EndPointSec;
207                }
208                else
209                {
210                    up = StartPointSec;
211                    down = EndPointSec;
212                    left = StartPoint;
213                    right = EndPoint;
214                }
215
216                if (up.Y < down.Y)
217                {
218                    double swap = up.Y;
219                    up.Y = down.Y;
220                    down.Y = swap;
221                }
222
223                if (left.X > right.X)
224                {
225                    double swap = left.X;
226                    left.X = right.X;
227                    right.X = swap;
228                }
229                 //check if is intersected at all
230                if(isBetween(down.Y, up.Y, left.Y) && isBetween(left.X, right.X, up.X))
231                {
232                    if (up.Y == left.Y ||
233                        down.Y == left.Y ||
234                        left.X == up.X || right.X == up.X)
235                    {
236                        intersectPoint = new IntersectPoint(new Point(up.X, left.Y), IntersectPointMode.InnerIntersect);
237                    }
238                    else
239                    {
240                        intersectPoint = new IntersectPoint(new Point(up.X, left.Y), IntersectPointMode.NormalIntersect);
241                    }
242                    return true;
243                }
244                return false;
245            }
246        }
247
248                private void internalGeometryDraw(StreamGeometryContext context)
249                {
250            makeOrthogonalPoints();
251            foreach (var element in (Parent as Panel).Children)
252            {
253                if (element is CryptoLineView && !element.Equals(this))
254                {
255                    CryptoLineView result = element as CryptoLineView;
256                    foreach (FromTo fromTo in pointList)
257                    {
258                        foreach (FromTo resultFromTo in result.pointList)
259                        {
260                            if (findIntersection(fromTo.From, fromTo.To, resultFromTo.From, resultFromTo.To))
261                            {
262                                fromTo.Intersection.Add(intersectPoint);
263
264                                if (fromTo.DirSort == DirSort.Y_ASC || fromTo.DirSort == DirSort.Y_DESC)
265                                    this.UpdateList.Add(result);
266                            }
267                        }
268                    }
269                }
270            }
271
272            context.BeginFigure(StartPoint, true, false);
273
274            foreach (FromTo fromTo in pointList)
275            {
276                if (fromTo.Intersection.Count > 0)
277                {
278                    foreach (IntersectPoint interPoint in fromTo.Intersection)
279                    {
280                        switch (fromTo.DirSort)
281                        {
282                            case DirSort.X_ASC:
283                                if (interPoint.Mode == IntersectPointMode.NormalIntersect)
284                                {
285                                    context.LineTo(new Point(interPoint.Point.X - offset, interPoint.Point.Y), true, true);
286                                    context.QuadraticBezierTo(new Point(interPoint.Point.X, interPoint.Point.Y - offset), new Point(interPoint.Point.X + offset, interPoint.Point.Y), true, true);
287                                }
288                                else if (interPoint.Mode == IntersectPointMode.InnerIntersect)
289                                {
290                                    context.LineTo(new Point(interPoint.Point.X - 2.5, interPoint.Point.Y), true, true);
291                                    context.QuadraticBezierTo(new Point(interPoint.Point.X, interPoint.Point.Y - 3.5), new Point(interPoint.Point.X + 2.5, interPoint.Point.Y), true, true);
292                                    context.QuadraticBezierTo(new Point(interPoint.Point.X, interPoint.Point.Y + 3.5), new Point(interPoint.Point.X - 2.5, interPoint.Point.Y), true, true);
293                                }
294                                break;
295                            case DirSort.X_DESC:
296                                if (interPoint.Mode == IntersectPointMode.NormalIntersect)
297                                {
298                                    context.LineTo(new Point(interPoint.Point.X + offset, interPoint.Point.Y), true, true);
299                                    context.QuadraticBezierTo(new Point(interPoint.Point.X, interPoint.Point.Y - offset), new Point(interPoint.Point.X - offset, interPoint.Point.Y), true, true);
300                                }
301                                else if (interPoint.Mode == IntersectPointMode.InnerIntersect)
302                                {
303                                    context.LineTo(new Point(interPoint.Point.X + 2.5, interPoint.Point.Y), true, true);
304                                    context.QuadraticBezierTo(new Point(interPoint.Point.X, interPoint.Point.Y - 3.5), new Point(interPoint.Point.X - 2.5, interPoint.Point.Y), true, true);
305                                    context.QuadraticBezierTo(new Point(interPoint.Point.X, interPoint.Point.Y + 3.5), new Point(interPoint.Point.X + 2.5, interPoint.Point.Y), true, true);
306                                }
307                                break;
308                            //case DirSort.Y_ASC:
309                            //    context.LineTo(new Point(interPoint.X, interPoint.Y - offset), true, true);
310                            //    context.QuadraticBezierTo(new Point(interPoint.X + offset, interPoint.Y), new Point(interPoint.X, interPoint.Y + offset), true, true);
311                            //    break;
312                            //case DirSort.Y_DESC:
313                            //    context.LineTo(new Point(interPoint.X, interPoint.Y + offset), true, true);
314                            //    context.QuadraticBezierTo(new Point(interPoint.X + offset, interPoint.Y), new Point(interPoint.X, interPoint.Y - offset), true, true);
315                            //    break;
316                        }
317                    }
318                    context.LineTo(fromTo.To, true, true);
319                }
320                else
321                {
322                    context.LineTo(fromTo.To, true, true);
323                }
324            }
325        }
326
327
328
329        //private bool isConnectionPossible(Point p1, Point p2, QuadTreeLib.QuadTree<FakeNode> quad)
330        //{
331        //    if (p1.X != p2.X && p1.Y != p2.Y)
332        //        throw new ArgumentException("only 90° allowed");
333
334        //    if (p1.Y != p2.Y)
335        //    {
336        //        Point up = p2.Y < p1.Y ? p2 : p1;
337        //        Point down = p2.Y < p1.Y ? p1 : p2;
338
339        //        Panel parent = (Parent as Panel);
340        //        foreach (var element in parent.Children)
341        //        {
342        //            PluginContainerView plug1 = element as PluginContainerView;
343        //            if (plug1 == null)
344        //                continue;
345        //            Point pos = new Point((plug1.RenderTransform as TranslateTransform).X, (plug1.RenderTransform as TranslateTransform).Y);
346
347        //            if (!isBetween(pos.X, pos.X + plug1.ActualWidth, up.X))
348        //                continue;
349
350        //            // case 1: one point is inside the plugin
351        //            if (isBetween(pos.Y, pos.Y + plug1.ActualHeight, up.Y) ||
352        //                isBetween(pos.Y, pos.Y + plug1.ActualHeight, down.Y))
353        //            {
354        //                return false;
355        //            }
356
357        //            // case 2: goes through
358        //            if (pos.Y > up.Y && pos.Y + plug1.ActualHeight < down.Y)
359        //            {
360        //                return false;
361        //            }
362        //        }
363        //    }
364        //    else
365        //    {
366        //        Point left = p2.X < p1.X ? p2 : p1;
367        //        Point right = p2.X < p1.X ? p1 : p2;
368
369        //        Panel parent = (Parent as Panel);
370        //        foreach (var element in parent.Children)
371        //        {
372        //            PluginContainerView plug1 = element as PluginContainerView;
373        //            if (plug1 == null)
374        //                continue;
375        //            Point pos = new Point((plug1.RenderTransform as TranslateTransform).X, (plug1.RenderTransform as TranslateTransform).Y);
376        //            if (!isBetween(pos.Y, pos.Y + plug1.ActualHeight, left.Y))
377        //                continue;
378        //            // case 1: one point is inside the plugin
379        //            if (isBetween(pos.X, pos.X + plug1.ActualWidth, left.X) ||
380        //                isBetween(pos.X, pos.X + plug1.ActualWidth, right.X))
381        //            {
382        //                return false;
383        //            }
384        //            // case 2: goes through
385        //            if (pos.X > left.X && pos.X + plug1.ActualWidth < right.X)
386        //            {
387        //                return false;
388        //            }
389        //        }
390        //    }
391        //    return true;
392        //}
393
394        private bool isConnectionPossible(Point p1, Point p2, QuadTreeLib.QuadTree<FakeNode> quadTree)
395        {
396            if (p1.X != p2.X && p1.Y != p2.Y)
397                throw new ArgumentException("only 90° allowed");
398
399            System.Drawing.RectangleF queryRect;
400            if (p1.Y != p2.Y)
401            {
402                Point up = p2.Y < p1.Y ? p2 : p1;
403                Point down = p2.Y < p1.Y ? p1 : p2;
404
405                queryRect = new System.Drawing.RectangleF((float)up.X, (float)up.Y, 1, (float)(down.Y - up.Y));
406            }
407            else
408            {
409                Point left = p2.X < p1.X ? p2 : p1;
410                Point right = p2.X < p1.X ? p1 : p2;
411
412                queryRect = new System.Drawing.RectangleF((float)left.X, (float)left.Y, (float)(right.X - left.X), 1);
413            }
414            return !quadTree.QueryAny(queryRect);
415        }
416
417        private bool performOrthogonalPointConnection(Node n1, Point p2, Node n3, List<Node> nodeList, QuadTreeLib.QuadTree<FakeNode> quadTreePlugins, QuadTreeLib.QuadTree<FakeNode> quadTreeLines)
418        {
419            //bool isHorizontal;
420            //Point help1, help2;
421            //foreach (FakeNode FKNode in getQueriesFromLine(n1.Point, p2, quadTreeLines, out isHorizontal))
422            //{
423            //    if (isHorizontal)
424            //    {
425            //        if (FKNode.Source != this.source)
426            //            continue;
427
428            //        help1 = new Point(n1.Point.X, 2);
429            //        help2 = new Point(p
430            //    }
431            //    else
432            //    {
433            //        if (FKNode.Source != this.source)
434            //            continue;
435            //    }
436            //}
437
438            //foreach (FakeNode FKNode in getQueriesFromLine(p2, n3.Point, quadTreeLines, out isHorizontal))
439            //{
440            //    if (isHorizontal)
441            //    {
442
443            //    }
444            //    else
445            //    {
446
447            //    }
448            //}
449
450            if (isConnectionPossible(n1.Point, p2, quadTreePlugins) && isConnectionPossible(p2, n3.Point, quadTreePlugins))
451            {
452                Node n2 = new Node() { Point = p2 };
453                n1.Vertices.Add(n2);
454
455                n2.Vertices.Add(n1);
456                n2.Vertices.Add(n3);
457
458                n3.Vertices.Add(n2);
459
460                nodeList.Add(n2);
461                return true;
462            }
463
464            return false;
465        }
466
467        private List<FakeNode> getQueriesFromLine(Point p1,Point p2,QuadTreeLib.QuadTree<FakeNode> quadTreeLines, out bool isHorizontal)
468        {
469            if (p1.X != p2.X && p1.Y != p2.Y)
470                throw new ArgumentException("only 90° allowed");
471
472            System.Drawing.RectangleF queryRect;
473
474            if (p1.Y != p2.Y)
475            {
476                Point up = p2.Y < p1.Y ? p2 : p1;
477                Point down = p2.Y < p1.Y ? p1 : p2;
478                isHorizontal = false;
479
480                queryRect = new System.Drawing.RectangleF((float)up.X, (float)up.Y, 1, (float)(down.Y - up.Y));
481            }
482            else
483            {
484                Point left = p2.X < p1.X ? p2 : p1;
485                Point right = p2.X < p1.X ? p1 : p2;
486                isHorizontal = true;
487
488                queryRect = new System.Drawing.RectangleF((float)left.X, (float)left.Y, (float)(right.X - left.X), 1);
489            }
490
491            return quadTreeLines.Query(queryRect);
492        }
493
494        //private bool isSimpleOrthogonalConnectionPossible(Point p1, Point p2, QuadTreeLib.QuadTree<FakeNode> quadTree)
495        //{
496        //    if (p1.X != p2.X && p1.Y != p2.Y)
497        //        throw new ArgumentException("only 90° allowed");
498
499        //    List<FakeNode> list;
500        //    System.Drawing.RectangleF queryRect;
501        //    if (p1.Y != p2.Y)
502        //    {
503        //        Point up = p2.Y < p1.Y ? p2 : p1;
504        //        Point down = p2.Y < p1.Y ? p1 : p2;
505
506        //        queryRect = new System.Drawing.RectangleF((float)up.X, (float)up.Y, (float)5, (float)(down.Y - up.Y));
507        //    }
508        //    else
509        //    {
510        //        Point left = p2.X < p1.X ? p2 : p1;
511        //        Point right = p2.X < p1.X ? p1 : p2;
512
513        //        queryRect = new System.Drawing.RectangleF((float)left.X, (float)left.Y, (float)(right.X - left.X), (float)5);
514        //    }
515
516        //    list = quadTree.Query(queryRect);
517
518        //    return !quadTree.Query(queryRect);
519        //}
520
521        private void performOrthogonalPointConnection(Node p1, Node p2, QuadTreeLib.QuadTree<FakeNode> quadTree)
522        {
523            if (isConnectionPossible(p1.Point, p2.Point, quadTree))
524            {
525                p1.Vertices.Add(p2);
526                p2.Vertices.Add(p1);
527            }
528        }
529
530        internal class FakeNode : QuadTreeLib.IHasRect
531        {
532            public System.Drawing.RectangleF Rectangle { get; set; }
533            public ConnectorView Source { get; set; }
534            public ConnectorView Target { get; set; }
535        }
536
537        private void makeOrthogonalPoints()
538        {
539            if (StartPointSource != null && EndPointSource != null && IsDragging == false)
540            {
541                List<Node> nodeList = new List<Node>();
542                Panel parent = (Parent as Panel);
543
544                // add start and end. Index will be 0 and 1
545                Node startNode = new Node() { Point = cheat42(StartPoint , StartPointSource, 1)},
546                    endNode = new Node() { Point = cheat42(EndPoint, EndPointSource, -1) };
547                nodeList.Add(startNode);
548                nodeList.Add(endNode);
549
550                float actualWidth = (float)parent.ActualWidth, actualHeight = (float)parent.ActualWidth;
551                //Consider zoom factor
552                QuadTreeLib.QuadTree<FakeNode> quadTreePlugins = new QuadTreeLib.QuadTree<FakeNode>
553                    (new System.Drawing.RectangleF(-actualWidth, -actualHeight, actualWidth * 5, actualHeight * 5));
554
555                QuadTreeLib.QuadTree<FakeNode> quadTreeLines = new QuadTreeLib.QuadTree<FakeNode>
556                    (new System.Drawing.RectangleF(-actualWidth, -actualHeight, actualWidth * 5, actualHeight * 5));
557
558
559
560                //foreach (var element in parent.Children)
561                //{
562                //    if (element is PluginContainerView)
563                //    {
564                //        PluginContainerView p1 = element as PluginContainerView;
565                //        foreach (var routPoint in p1.RoutingPoints)
566                //        {
567                //            nodeList.Add(new Node() { Point = routPoint });
568                //        }
569                //        quadTree.Insert(new FakeNode() { Rectangle = new System.Drawing.RectangleF((float)(p1.RenderTransform as TranslateTransform).X,
570                //                                                                                    (float)(p1.RenderTransform as TranslateTransform).Y,
571                //                                                                                    (float)p1.ActualWidth,
572                //                                                                                    (float)p1.ActualHeight)});
573                //    }
574                //}
575                for (int routPoint = 0; routPoint < 4; ++routPoint)
576                {
577                    foreach (var element in parent.Children)
578                    {
579                        if (element is PluginContainerView)
580                        {
581                            PluginContainerView p1 = element as PluginContainerView;
582                            nodeList.Add(new Node() { Point = p1.GetRoutingPoint(routPoint) });
583                            if (routPoint == 0)
584                            {
585                                quadTreePlugins.Insert(new FakeNode()
586                                {
587                                    Rectangle = new System.Drawing.RectangleF((float)p1.GetPosition().X,
588                                                                               (float)p1.GetPosition().Y + (float)p1.ControlPanel.ActualHeight,
589                                                                               (float)p1.PluginBase.ActualWidth,
590                                                                               (float)p1.PluginBase.ActualHeight - (float)p1.ControlPanel.ActualHeight)
591                                });
592                            }
593                        }
594
595                        if (routPoint != 0)
596                            continue;
597
598                        if (element is CryptoLineView)
599                        {
600                            CryptoLineView l1 = element as CryptoLineView;
601                            foreach (FromTo fromto in l1.pointList)
602                            {
603                                Point p1 = fromto.From, p2 = fromto.To;
604                                if (p1.Y != p2.Y)
605                                {
606                                    Point up = p2.Y < p1.Y ? p2 : p1;
607                                    Point down = p2.Y < p1.Y ? p1 : p2;
608
609                                    quadTreeLines.Insert(new FakeNode()
610                                    {
611                                        Source = l1.StartPointSource,
612                                        Target = l1.EndPointSource,
613                                        Rectangle = new System.Drawing.RectangleF((float)up.X, (float)up.Y, 1, (float)(down.Y - up.Y))
614                                    });
615                                }
616                                else
617                                {
618                                    Point left = p2.X < p1.X ? p2 : p1;
619                                    Point right = p2.X < p1.X ? p1 : p2;
620
621                                    quadTreeLines.Insert(new FakeNode()
622                                    {
623                                        Source = l1.StartPointSource,
624                                        Target = l1.EndPointSource,
625                                        Rectangle = new System.Drawing.RectangleF((float)left.X, (float)left.Y, (float)(right.X - left.X), 1)
626                                    });
627                                }
628                            }
629
630                        }
631                    }
632                }
633
634                // connect points
635                int loopCount = nodeList.Count;
636                const int performanceTradeoffAt = 10;
637
638                LinkedList<Node> path = null;
639
640                for (int i = 0; i < loopCount; ++i)
641                {
642                    if (performanceTradeoffAt != 0 &&
643                           i == performanceTradeoffAt)
644                    {
645                        StackFrameDijkstra.Dijkstra<Node> dijkstra = new StackFrameDijkstra.Dijkstra<Node>();
646                        path = dijkstra.findPath(nodeList, startNode, endNode);
647                        if (path != null)
648                        {
649                            break;
650                        }
651                    }
652
653                    var p1 = nodeList[i];
654                    // TODO: inner loop restriction! n²-n!
655                    // is k=i instead of k=0 correct?
656                    for (int k = i; k < loopCount; ++k)
657                    {
658
659
660                        var p2 = nodeList[k];
661                        if (p1 == p2)
662                            continue;
663                        if (p1.Vertices.Contains(p2))
664                            continue;
665
666                        // no helping point required?
667                        if (p1.Point.X == p2.Point.X ||
668                            p1.Point.Y == p2.Point.Y)
669                        {
670                            performOrthogonalPointConnection(p1, p2, quadTreePlugins);
671                        }
672                        else
673                        {
674                            Point help = new Point(p1.Point.X, p2.Point.Y);
675
676                            if (!performOrthogonalPointConnection(p1, help, p2, nodeList, quadTreePlugins, quadTreeLines))
677                            {
678                                help = new Point(p2.Point.X, p1.Point.Y);
679                                if (!performOrthogonalPointConnection(p1, help, p2, nodeList, quadTreePlugins, quadTreeLines))
680                                {
681                                    // optional todo: double edge helping routes
682                                }
683                            }
684
685                        }
686                    }
687                }
688
689                if (path == null)
690                {
691                    StackFrameDijkstra.Dijkstra<Node> dijkstra = new StackFrameDijkstra.Dijkstra<Node>();
692                    path = dijkstra.findPath(nodeList, startNode, endNode);
693                }
694
695                if (path != null)
696                {
697                    pointList.Clear();
698                    Point prevPoint = StartPoint;
699
700                    foreach (var i in path)
701                    {
702                        Point thisPoint = i.Point;
703                        this.pointList.Add(new FromTo(prevPoint, thisPoint));
704                        prevPoint = thisPoint;
705                    }
706                    this.pointList.Add(new FromTo(prevPoint, EndPoint));
707                    return;
708                }
709            }
710            //Failsafe
711            if (StartPoint.X < EndPoint.X)
712            {
713                pointList.Clear();
714                pointList.Add(new FromTo(StartPoint, new Point((EndPoint.X + StartPoint.X) / 2, StartPoint.Y)));
715                pointList.Add(new FromTo(new Point((EndPoint.X + StartPoint.X) / 2, StartPoint.Y), new Point((EndPoint.X + StartPoint.X) / 2, EndPoint.Y)));
716                pointList.Add(new FromTo(new Point((EndPoint.X + StartPoint.X) / 2, EndPoint.Y), EndPoint));
717            }
718            else
719            {
720                if (StartPoint.X > EndPoint.X)
721                {
722                    pointList.Clear();
723                    pointList.Add(new FromTo(StartPoint, new Point((StartPoint.X + EndPoint.X) / 2, StartPoint.Y)));
724                    pointList.Add(new FromTo(new Point((StartPoint.X + EndPoint.X) / 2, StartPoint.Y), new Point((StartPoint.X + EndPoint.X) / 2, EndPoint.Y)));
725                    pointList.Add(new FromTo(new Point((StartPoint.X + EndPoint.X) / 2, EndPoint.Y), EndPoint));
726                }
727            }
728        }
729
730        private static Point cheat42(Point EndPoint, ConnectorView EndPointSource, int flipper)
731        {
732            double xoffset = 0;
733            double yoffset = 0;
734            double baseoffset = 15;
735            switch (EndPointSource.Orientation)
736            {
737                case ConnectorOrientation.East:
738                    xoffset = baseoffset;
739                    break;
740                case ConnectorOrientation.West:
741                    xoffset = -baseoffset;
742                    break;
743                case ConnectorOrientation.North:
744                    yoffset = -baseoffset;
745                    break;
746                case ConnectorOrientation.South:
747                    yoffset = baseoffset;
748                    break;
749            }
750            //xoffset *= flipper;
751            //yoffset *= flipper;
752            return new Point(EndPoint.X + xoffset, EndPoint.Y + yoffset);
753        }
754               
755                #endregion
756
757        #region IUpdateableView Members
758
759        private Brush ActiveColorBrush;
760        private Brush NonActiveColorBrush;
761
762        public void update()
763        {
764            if (this.Model.Active)
765            {
766                if (ActiveColorBrush == null)
767                {
768                    Color ActiveColor = ColorHelper.GetLineColor(this.Model.ConnectionType);
769                    ActiveColor.ScR = (ActiveColor.ScR * 2f < 255 ? ActiveColor.ScR * 2f : 255f);
770                    ActiveColor.ScG = (ActiveColor.ScG * 2f < 255 ? ActiveColor.ScG * 2f : 255f);
771                    ActiveColor.ScB = (ActiveColor.ScB * 2f < 255 ? ActiveColor.ScB * 2f : 255f);
772                    ActiveColorBrush = new SolidColorBrush(ActiveColor);
773                }
774                Stroke = ActiveColorBrush;               
775                StrokeThickness = 4;
776            }
777            else
778            {
779                Reset();
780            }
781        }
782
783        #endregion
784
785        internal void Reset()
786        {
787            if (NonActiveColorBrush == null)
788            {
789                NonActiveColorBrush = new SolidColorBrush(ColorHelper.GetLineColor(Model.ConnectionType));
790            }
791            Stroke = NonActiveColorBrush;
792            StrokeThickness = 2;
793        }
794
795
796        private ConnectorView startPointSource;
797        public ConnectorView StartPointSource
798        { 
799            get { return startPointSource; } 
800            set 
801            {
802                startPointSource = value; 
803                if (endPointSource == null || startPointSource == null)
804                    return;
805                makeBinding(startPointSource, endPointSource); 
806            } 
807        }
808
809        private ConnectorView endPointSource;
810        public ConnectorView EndPointSource
811        { 
812            get { return endPointSource; } 
813            set 
814            { 
815                endPointSource = value;
816                if (endPointSource == null || startPointSource == null)
817                    return;
818                makeBinding(startPointSource, endPointSource); 
819            } 
820        }
821    }
822
823    public class MultiDragValueConverter : IMultiValueConverter
824    {
825        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
826        {
827            bool a = (bool)values[0], b = (bool)values[1];
828            if (a == true || b == true)
829                return true;
830            else
831                return false;
832        }
833
834        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
835        {
836            throw new NotImplementedException();
837        }
838    }
839
840}
Note: See TracBrowser for help on using the repository browser.