Esempio n. 1
0
        public Point NextFreePosition0(Point start, Size sizeNeeded, Dimension dimension, IEnumerable <TItem> ignore, double distance)
        {
            var result = new Rectangle(start, sizeNeeded);
            var loc    = new GraphSceneItemShapeLocator <TItem, TEdge> {
                GraphScene = this.GraphScene
            };
            var measure = new MeasureVisitBuilder <TItem> (loc);

            var iRect = result;

            while (!iRect.IsEmpty)
            {
                var elems = GraphScene.ElementsIn(iRect).Where(e => !(e is TEdge)).Except(ignore);
                if (!elems.Any())
                {
                    break;
                }
                Action <TItem> visit = null;
                var            frect = measure.Bounds(ref visit);
                foreach (var item in elems)
                {
                    visit(item);
                }
                iRect = frect();
                if (!iRect.IsEmpty)
                {
                    iRect  = new Rectangle(new Point(iRect.Right + distance, result.Top), sizeNeeded);
                    result = iRect;
                }
            }


            return(result.Location);
        }
Esempio n. 2
0
        protected Rectangle ReportExtent(IEnumerable <IVisual> elms, ILocator <IVisual> locator, AlignerOptions options)
        {
            var measure            = new MeasureVisitBuilder <IVisual> (locator);
            Action <IVisual> visit = null;
            var fSizeToFit         = measure.SizeToFit(ref visit, options.Distance, options.Dimension);
            var fBounds            = measure.Bounds(ref visit);
            var fMinSize           = measure.MinSize(ref visit);

            elms.ForEach(e => visit(e));
            ReportDetail("Bounds {1}\tSizeToFit {0}\tMinSize  {2}", fSizeToFit(), fBounds(), fMinSize());
            return(fBounds());
        }
Esempio n. 3
0
        public virtual Rectangle AlignByPath <TItem, TEdge> (IEnumerable <LevelItem <TItem> > walk, AlignerOptions options, Aligner <TItem, TEdge> aligner, Point startPoint)
            where TEdge : IEdge <TItem>, TItem
        {
            var bounds = new Rectangle(startPoint, Size.Zero);

            // contains levelitems with backtracked path
            var trackedSteps = new Dictionary <TItem, LevelItem <TItem> > ();

            // used to backtrack path
            var steps = new Dictionary <TItem, LevelItem <TItem> > ();

            var trackBounds      = new Dictionary <TItem, Rectangle> ();
            var trackBoundsToken = new HashSet <TItem> ();

            Func <TItem, TEdge> asEdge = node => node is TEdge ? (TEdge)node : default(TEdge);

            Func <TItem, bool> isVisibleNode = node => !(node is TEdge);

            Func <LevelItem <TItem>, TItem> findPath = step => {
                var visibleNode = isVisibleNode(step.Node);

                while (step.Path != null)
                {
                    if (isVisibleNode(step.Path))
                    {
                        return(step.Path);
                    }

                    if ((step.Node as IEdge <TItem>).IsEdgeOfEdges())
                    {
                        return(step.Path);
                    }

                    if ((step.Path as IEdge <TItem>).IsEdgeOfEdges())
                    {
                        return(step.Path);
                    }


                    if (step.StepIsEdgeToEdge() && visibleNode)
                    {
                        return(step.Node);
                    }

                    if (trackBounds.ContainsKey(step.Path))
                    {
                        return(step.Path);
                    }

                    step = steps [step.Path];
                }

                TrackBounds = trackBounds.Values;
                return(step.Path);
            };

            // steps up the paths and sums the size of trackBounds
            Action <LevelItem <TItem>, Rectangle> sumTrackBounds = (trackedStep, trackBound) => {
                var adjDimension = options.Dimension.Adjacent();
                while (trackedStep.Path != null)
                {
                    var trackStep = trackedSteps [trackedStep.Path];

                    if (trackStep.Path != null)
                    {
                        var backTrackBound = trackBounds [trackStep.Path].MaxExtend(trackBound, adjDimension);
                        trackBounds [trackStep.Path] = backTrackBound;
                        trackBound = backTrackBound;
                    }
                    trackedStep = trackStep;
                }
            };

            // gets the trackBounds of the trackedStep.Path; ensures that the path has trackBounds
            Func <LevelItem <TItem>, Rectangle, Rectangle> getTrackBounds = (trackedStep, trackBound) => {
                while (trackedStep.Path != null)
                {
                    var gb = new Rectangle();
                    if (trackBounds.TryGetValue(trackedStep.Path, out gb))
                    {
                        return(gb);
                    }
                    else
                    {
                        // TODO: ensure that all paths have trackBounds, not only the first uppath
                        var trackStep = trackedSteps [trackedStep.Path];
                        if (trackStep.Path != null)
                        {
                            var backTrackBound = trackBounds [trackStep.Path];
                            trackBound.X = backTrackBound.Right;
                            trackBound.Y = backTrackBound.Bottom;
                        }
                        trackBounds [trackedStep.Path] = trackBound;
                        break;
                    }
                }
                return(trackBound);
            };


            foreach (var step in walk)
            {
                steps.Add(step.Node, step);

                var visibleNode = isVisibleNode(step.Node);
                var nonAdjacent = !step.StepIsAdjacent();

                var isStepEdgeToEdge  = step.StepIsEdgeToEdge();
                var isNodeEdgeOfEdges = (step.Node as IEdge <TItem>).IsEdgeOfEdges();

                var trackedStep = new LevelItem <TItem> (step.Node, findPath(step), step.Level);
                trackedSteps [step.Node] = trackedStep;
                ReportDetail($"\t{trackedStep}");

                if (!(visibleNode || isStepEdgeToEdge))
                {
                    continue;
                }

                var gb = new Rectangle(startPoint, options.Distance.InitSum(options.Dimension));

                var trackBound = new Rectangle(startPoint, new Size());
                if (trackedStep.Path != null)
                {
                    trackBound = getTrackBounds(trackedStep, gb);
                    gb.X       = trackBound.Right;
                    gb.Y       = trackBound.Bottom;
                }

                if (isStepEdgeToEdge)
                {
                    trackBounds [step.Node] = new Rectangle(gb.Location, new Size());
                    ReportDetail($"{step.Node}\t{trackBounds [step.Node]}\t{trackedStep.Path}\t{trackBound}");
                }

                if (visibleNode)
                {
                    var loc        = gb.Location;
                    var nodeBounds = aligner.MeasureItem(step.Node, options.Dimension, options.Distance, ref gb);
                    nodeBounds.Location = gb.Location.Max(loc);

                    aligner.Locator.SetLocation(step.Node, nodeBounds.Location);

                    trackBounds [step.Node] = new Rectangle(nodeBounds.Location, gb.Size.InitSum(options.Dimension));

                    if (trackedStep.Path != null)
                    {
                        trackBound.Size = trackBound.Size.SumSize(nodeBounds.Size + options.Distance, options.Dimension.Adjacent());
                        trackBounds [trackedStep.Path] = trackBound;
                        trackBoundsToken.Add(trackedStep.Path);
                    }

                    ReportDetail($"{step.Node}\t{nodeBounds}\t{trackedStep.Path}\t{trackBound}");
                }

                sumTrackBounds(trackedStep, trackBound);
            }

            // aligns

            foreach (var trackBound in trackBounds.ToArray())
            {
                if (trackBound.Value.Width == 0)
                {
                    trackBounds [trackBound.Key] = new Rectangle(trackBound.Value.Location, new Size(options.Distance.Width / 2, trackBound.Value.Height));
                }
            }
            foreach (var kvp in trackBounds.ToArray())
            {
                var step = trackedSteps [kvp.Key];
                if (step.Path == null)
                {
                    continue;
                }
                var lbounds = kvp.Value;
                var sum     = 0d;
                while (step.Path != null)
                {
                    var trackBound = trackBounds [step.Path];
                    sum  = Math.Max(trackBound.Right, sum);
                    step = trackedSteps [step.Path];
                }
                if (lbounds.X != sum)
                {
                    trackBounds [kvp.Key] = new Rectangle(new Point(sum, lbounds.Y), lbounds.Size);
                }
            }

            Action <TItem> visitMeasure = null;
            var            measure      = new MeasureVisitBuilder <TItem> (aligner.Locator);
            var            fBounds      = measure.Bounds(ref visitMeasure);

            foreach (var step in trackedSteps.Values.Where(l => !(l.Node is TEdge)))
            {
                var nodeBounds = trackBounds [step.Node];
                var loc        = aligner.Locator.GetLocation(step.Node);
                var size       = aligner.Locator.GetSize(step.Node);

                if (options.Dimension == Dimension.X)
                {
                    if (nodeBounds.Height != 0)
                    {
                        loc.Y += options.AlignY.Delta(nodeBounds.Height - options.Distance.Height, size.Height);;
                    }
                    loc.X = nodeBounds.X;
                }
                else
                {
                    if (nodeBounds.Width != 0)
                    {
                        loc.X += options.AlignX.Delta(nodeBounds.Width - options.Distance.Width, size.Width);
                    }
                    loc.Y = nodeBounds.Y;
                }


                aligner.Locator.SetLocation(step.Node, loc);

                visitMeasure(step.Node);
            }

            bounds = fBounds();
            return(bounds);
        }