Ejemplo n.º 1
0
        /// <summary>
        /// Snap single element to close elements on canvas
        /// </summary>
        /// <param name="movedItem">Item to snap</param>
        /// <param name="canvas">Main canvas holding all items</param>
        private void SnapElement(ContentPresenter movedItem, CustomCanvas canvas)
        {
            double            itemLeft = Canvas.GetLeft(movedItem);
            double            itemTop  = Canvas.GetTop(movedItem);
            TemplateViewModel context  = (TemplateViewModel)canvas.DataContext;

            // get list of close items according to snapDeltaPixels value
            List <ContentPresenter> presenters  = ControlHelper.GetUnselectedChildPresenters(canvas).ToList();
            List <ContentPresenter> closeByLeft = presenters.Where(x => Math.Abs(Canvas.GetLeft(x) - itemLeft) <= snapDeltaPixels).ToList();
            List <ContentPresenter> closeByTop  = presenters.Where(x => Math.Abs(Canvas.GetTop(x) - itemTop) <= snapDeltaPixels).ToList();

            List <Line> resultingSnapLines = new List <Line>();

            if (closeByLeft.Count > 0)
            {
                // closest by left position and then by top
                ContentPresenter closest = closeByLeft.OrderBy(x => Math.Abs(Canvas.GetLeft(x) - itemLeft))
                                           .ThenBy(x => Math.Abs(Canvas.GetTop(x) - itemTop)).First();

                // move snapped item to desired position
                double targetLeft = Canvas.GetLeft(closest);
                double targetTop  = Canvas.GetTop(closest);
                Canvas.SetLeft(movedItem, targetLeft);

                // add lowest item height to the line length
                double itemHeight = targetTop > itemTop ? closest.Height : movedItem.Height;

                // draw snap line and add to the list
                Line line = new Line();
                line.X1 = line.X2 = targetLeft;
                line.Y1 = Math.Max(Math.Min(itemTop, targetTop) - snapLineTail, 0);
                line.Y2 = Math.Max(itemTop, targetTop) + itemHeight + snapLineTail;

                resultingSnapLines.Add(line);
            }

            if (closeByTop.Count > 0)
            {
                // closes by top position and then by left
                ContentPresenter closest = closeByTop.OrderBy(x => Math.Abs(Canvas.GetTop(x) - itemTop))
                                           .ThenBy(x => Math.Abs(Canvas.GetLeft(x) - itemLeft)).First();

                // move snapped item to desired position
                double targetLeft = Canvas.GetLeft(closest);
                double targetTop  = Canvas.GetTop(closest);
                Canvas.SetTop(movedItem, targetTop);

                double itemWidth = targetLeft > itemLeft ? closest.Width : movedItem.Width;

                // draw snap line and add to the list
                Line line = new Line();
                line.Y1 = line.Y2 = targetTop;
                line.X1 = Math.Max(Math.Min(itemLeft, targetLeft) - snapLineTail, 0);
                line.X2 = Math.Max(itemLeft, targetLeft) + itemWidth + snapLineTail;

                resultingSnapLines.Add(line);
            }

            if (context.GotSnapLines)
            {
                context.CleanSnapLines();
            }

            // draw snap lines
            foreach (Line snapLine in resultingSnapLines)
            {
                context.AddLine(snapLine);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Snap group of elements
        /// </summary>
        /// <param name="movedGroup">Group of elements to snap</param>
        /// <param name="canvas">Main canvas holding all items</param>
        private void SnapGroup(List <ContentPresenter> movedGroup, CustomCanvas canvas)
        {
            // get bounding box Rect of snap group
            Rect boundingBox = GetBoundingBox(movedGroup);

            TemplateViewModel       context     = (TemplateViewModel)canvas.DataContext;
            List <ContentPresenter> canvasItems = ControlHelper.GetUnselectedChildPresenters(canvas).ToList();

            // get list of close items according to snapDeltaPixels value
            List <Line>             resultingSnapLines = new List <Line>();
            List <ContentPresenter> closeByLeft        = canvasItems.Where(x => Math.Abs(Canvas.GetLeft(x) - boundingBox.Left) <= snapDeltaPixels).ToList();
            List <ContentPresenter> closeByTop         = canvasItems.Where(x => Math.Abs(Canvas.GetTop(x) - boundingBox.Top) <= snapDeltaPixels).ToList();

            if (closeByLeft.Count > 0)
            {
                // closes by left position and then by top
                ContentPresenter closest = closeByLeft.OrderBy(x => Math.Abs(Canvas.GetLeft(x) - boundingBox.Left))
                                           .ThenBy(x => Math.Abs(Canvas.GetTop(x) - boundingBox.Top)).First();

                double targetLeft = Canvas.GetLeft(closest);
                double targetTop  = Canvas.GetTop(closest);

                // snap each item of the group according to calculated distance to the target
                double moveDelta = boundingBox.Left - targetLeft;
                movedGroup.ForEach(x => Canvas.SetLeft(x, Canvas.GetLeft(x) - moveDelta));

                // add lowest item height to the line length
                double itemHeight = targetTop > boundingBox.Top ? closest.Height : boundingBox.Height;

                // draw snap line and add to the list
                Line line = new Line();
                line.X1 = line.X2 = targetLeft;
                line.Y1 = Math.Max(Math.Min(boundingBox.Top, targetTop) - snapLineTail, 0);
                line.Y2 = Math.Max(boundingBox.Top, targetTop) + itemHeight + snapLineTail;

                resultingSnapLines.Add(line);
            }

            if (closeByTop.Count > 0)
            {
                // closes by top position and then by left
                ContentPresenter closest = closeByTop.OrderBy(x => Math.Abs(Canvas.GetTop(x) - boundingBox.Top))
                                           .ThenBy(x => Math.Abs(Canvas.GetLeft(x) - boundingBox.Left)).First();

                double targetLeft = Canvas.GetLeft(closest);
                double targetTop  = Canvas.GetTop(closest);

                // snap each item of the group according to calculated distance to the target
                double moveDelta = boundingBox.Top - targetTop;
                movedGroup.ForEach(x => Canvas.SetTop(x, Canvas.GetTop(x) - moveDelta));

                double itemWidth = targetLeft > boundingBox.Left ? closest.Width : boundingBox.Width;

                // draw snap line and add to the list
                Line line = new Line();
                line.Y1 = line.Y2 = targetTop;
                line.X1 = Math.Max(Math.Min(boundingBox.Left, targetLeft) - snapLineTail, 0);
                line.X2 = Math.Max(boundingBox.Left, targetLeft) + itemWidth + snapLineTail;

                resultingSnapLines.Add(line);
            }

            if (context.GotSnapLines)
            {
                context.CleanSnapLines();
            }

            // draw snap lines
            foreach (Line snapLine in resultingSnapLines)
            {
                context.AddLine(snapLine);
            }
        }