示例#1
0
        /// <summary>
        /// Given an obstacle and its attempted destination, determines the correct landing
        /// spot for an obstacle.
        /// </summary>
        /// <param name="movingObstacle">The obstacle that is moving.</param>
        /// <param name="newLocation">The upper-left coordinate of the obstacle's original intended destination.</param>
        /// <returns>
        /// A Point that determines where the obstacle should be placed instead. If there are no adjustments
        /// required to the obstacle's desintation, then the return value will be equal to newLocation.
        /// </returns>
        /// <remarks>
        /// movingObstacle's SnapDescription will also be updated. The caller of this method is required
        /// to update the SnapObstacle with the new, adjusted location.
        /// </remarks>
        public Point AdjustObstacleDestination(SnapObstacle movingObstacle, Point newLocation)
        {
            Point adjusted1 = AdjustObstacleDestination(movingObstacle, newLocation, false);
            Point adjusted2 = AdjustObstacleDestination(movingObstacle, adjusted1, true);

            return(adjusted2);
        }
示例#2
0
        public void ParkObstacle(SnapObstacle obstacle, SnapObstacle snappedTo, HorizontalSnapEdge hEdge, VerticalSnapEdge vEdge)
        {
            SnapDescription sd = new SnapDescription(snappedTo, hEdge, vEdge, obstacle.SnapDistance, obstacle.SnapDistance);

            this.obstacles[obstacle] = sd;
            ParkObstacle(obstacle, sd);
        }
示例#3
0
        public Point AdjustObstacleDestination(SnapObstacle movingObstacle, Point newLocation, bool considerStickies)
        {
            Point           adjustedLocation = newLocation;
            SnapDescription sd    = this.obstacles[movingObstacle];
            SnapDescription newSD = null;

            foreach (SnapObstacle avoidee in this.obstacles.Keys)
            {
                if (avoidee.StickyEdges != considerStickies)
                {
                    continue;
                }

                if (avoidee.Enabled && !object.ReferenceEquals(avoidee, movingObstacle))
                {
                    SnapDescription newSD2 = DetermineNewSnapDescription(movingObstacle, adjustedLocation, avoidee, newSD);

                    if (newSD2 != null)
                    {
                        Point adjustedLocation2 = AdjustNewLocation(movingObstacle, adjustedLocation, newSD2);
                        newSD            = newSD2;
                        adjustedLocation = adjustedLocation2;
                        Rectangle newBounds = new Rectangle(adjustedLocation, movingObstacle.Bounds.Size);
                    }
                }
            }

            if (sd == null || !sd.SnappedTo.StickyEdges || newSD == null || newSD.SnappedTo.StickyEdges)
            {
                this.obstacles[movingObstacle] = newSD;
            }

            return(adjustedLocation);
        }
示例#4
0
        private void SnapObstacle_BoundsChanged(object sender, EventArgs <Rectangle> e)
        {
            SnapObstacle senderSO = (SnapObstacle)sender;
            Rectangle    fromRect = e.Data;
            Rectangle    toRect   = senderSO.Bounds;

            UpdateDependentObstacles(senderSO, fromRect, toRect);
        }
示例#5
0
        private static void ParkObstacle(SnapObstacle avoider, SnapDescription snapDescription)
        {
            Point     newLocation      = avoider.Bounds.Location;
            Point     adjustedLocation = AdjustNewLocation(avoider, newLocation, snapDescription);
            Rectangle newBounds        = new Rectangle(adjustedLocation, avoider.Bounds.Size);

            avoider.RequestBoundsChange(newBounds);
        }
示例#6
0
        private void LoadSnapObstacleData(ISimpleCollection <string, string> loadFrom, SnapObstacle so)
        {
            string          prefix = so.Name + ".";
            SnapDescription sd;

            string isSnappedString = loadFrom.Get(prefix + isSnappedValueName);
            bool   isSnapped       = bool.Parse(isSnappedString);

            if (isSnapped)
            {
                string       snappedToString = loadFrom.Get(prefix + snappedToValueName);
                SnapObstacle snappedTo       = FindObstacle(snappedToString);

                string             horizontalEdgeString = loadFrom.Get(prefix + horizontalEdgeValueName);
                HorizontalSnapEdge horizontalEdge       = (HorizontalSnapEdge)Enum.Parse(typeof(HorizontalSnapEdge), horizontalEdgeString, true);

                string           verticalEdgeString = loadFrom.Get(prefix + verticalEdgeValueName);
                VerticalSnapEdge verticalEdge       = (VerticalSnapEdge)Enum.Parse(typeof(VerticalSnapEdge), verticalEdgeString, true);

                string xOffsetString = loadFrom.Get(prefix + xOffsetValueName);
                int    xOffset       = int.Parse(xOffsetString, CultureInfo.InvariantCulture);

                string yOffsetString = loadFrom.Get(prefix + yOffsetValueName);
                int    yOffset       = int.Parse(yOffsetString, CultureInfo.InvariantCulture);

                sd = new SnapDescription(snappedTo, horizontalEdge, verticalEdge, xOffset, yOffset);
            }
            else
            {
                sd = null;
            }

            this.obstacles[so] = sd;

            string leftString = loadFrom.Get(prefix + leftValueName);
            int    left       = int.Parse(leftString, CultureInfo.InvariantCulture);

            string topString = loadFrom.Get(prefix + topValueName);
            int    top       = int.Parse(topString, CultureInfo.InvariantCulture);

            string widthString = loadFrom.Get(prefix + widthValueName);
            int    width       = int.Parse(widthString, CultureInfo.InvariantCulture);

            string heightString = loadFrom.Get(prefix + heightValueName);
            int    height       = int.Parse(heightString, CultureInfo.InvariantCulture);

            Rectangle newBounds = new Rectangle(left, top, width, height);

            so.RequestBoundsChange(newBounds);

            if (sd != null)
            {
                ParkObstacle(so, sd);
            }
        }
示例#7
0
        private void LoadSnapObstacleData(ISimpleCollection<string, string> loadFrom, SnapObstacle so)
        {
            string prefix = so.Name + ".";
            SnapDescription sd;

            string isSnappedString = loadFrom.Get(prefix + isSnappedValueName);
            bool isSnapped = bool.Parse(isSnappedString);

            if (isSnapped)
            {
                string snappedToString = loadFrom.Get(prefix + snappedToValueName);
                SnapObstacle snappedTo = FindObstacle(snappedToString);

                string horizontalEdgeString = loadFrom.Get(prefix + horizontalEdgeValueName);
                HorizontalSnapEdge horizontalEdge = (HorizontalSnapEdge)Enum.Parse(typeof(HorizontalSnapEdge), horizontalEdgeString, true);

                string verticalEdgeString = loadFrom.Get(prefix + verticalEdgeValueName);
                VerticalSnapEdge verticalEdge = (VerticalSnapEdge)Enum.Parse(typeof(VerticalSnapEdge), verticalEdgeString, true);

                string xOffsetString = loadFrom.Get(prefix + xOffsetValueName);
                int xOffset = int.Parse(xOffsetString, CultureInfo.InvariantCulture);

                string yOffsetString = loadFrom.Get(prefix + yOffsetValueName);
                int yOffset = int.Parse(yOffsetString, CultureInfo.InvariantCulture);

                sd = new SnapDescription(snappedTo, horizontalEdge, verticalEdge, xOffset, yOffset);
            }
            else
            {
                sd = null;
            }

            this.obstacles[so] = sd;

            string leftString = loadFrom.Get(prefix + leftValueName);
            int left = int.Parse(leftString, CultureInfo.InvariantCulture);

            string topString = loadFrom.Get(prefix + topValueName);
            int top = int.Parse(topString, CultureInfo.InvariantCulture);

            string widthString = loadFrom.Get(prefix + widthValueName);
            int width = int.Parse(widthString, CultureInfo.InvariantCulture);

            string heightString = loadFrom.Get(prefix + heightValueName);
            int height = int.Parse(heightString, CultureInfo.InvariantCulture);

            Rectangle newBounds = new Rectangle(left, top, width, height);
            so.RequestBoundsChange(newBounds);

            if (sd != null)
            {
                ParkObstacle(so, sd);
            }
        }
示例#8
0
        public void ReparkObstacle(SnapObstacle obstacle)
        {
            if (this.obstacles.ContainsKey(obstacle))
            {
                SnapDescription sd = this.obstacles[obstacle];

                if (sd != null)
                {
                    ParkObstacle(obstacle, sd);
                }
            }
        }
示例#9
0
        public void AddSnapObstacle(SnapObstacle snapObstacle)
        {
            if (!this.obstacles.ContainsKey(snapObstacle))
            {
                this.obstacles.Add(snapObstacle, null);

                if (snapObstacle.StickyEdges)
                {
                    snapObstacle.BoundsChanging += SnapObstacle_BoundsChanging;
                    snapObstacle.BoundsChanged  += SnapObstacle_BoundsChanged;
                }
            }
        }
示例#10
0
        public void RemoveSnapObstacle(SnapObstacle snapObstacle)
        {
            if (this.obstacles.ContainsKey(snapObstacle))
            {
                this.obstacles.Remove(snapObstacle);

                if (snapObstacle.StickyEdges)
                {
                    snapObstacle.BoundsChanging -= SnapObstacle_BoundsChanging;
                    snapObstacle.BoundsChanged  -= SnapObstacle_BoundsChanged;
                }
            }
        }
示例#11
0
        public void Load(ISimpleCollection <string, string> loadFrom)
        {
            SnapObstacle[] newObstacles = new SnapObstacle[this.obstacles.Count];
            this.obstacles.Keys.CopyTo(newObstacles, 0);

            foreach (SnapObstacle obstacle in newObstacles)
            {
                if (obstacle.EnableSave)
                {
                    LoadSnapObstacleData(loadFrom, obstacle);
                }
            }
        }
示例#12
0
        private void UpdateDependentObstacles(SnapObstacle senderSO, Rectangle fromRect, Rectangle toRect)
        {
            int leftDelta   = toRect.Left - fromRect.Left;
            int topDelta    = toRect.Top - fromRect.Top;
            int rightDelta  = toRect.Right - fromRect.Right;
            int bottomDelta = toRect.Bottom - fromRect.Bottom;

            foreach (SnapObstacle obstacle in this.obstacles.Keys)
            {
                if (!object.ReferenceEquals(senderSO, obstacle))
                {
                    SnapDescription sd = this.obstacles[obstacle];

                    if (sd != null && object.ReferenceEquals(sd.SnappedTo, senderSO))
                    {
                        int deltaX;

                        if (sd.VerticalEdge == VerticalSnapEdge.Right)
                        {
                            deltaX = rightDelta;
                        }
                        else
                        {
                            deltaX = leftDelta;
                        }

                        int deltaY;

                        if (sd.HorizontalEdge == HorizontalSnapEdge.Bottom)
                        {
                            deltaY = bottomDelta;
                        }
                        else
                        {
                            deltaY = topDelta;
                        }

                        Rectangle oldBounds    = obstacle.Bounds;
                        Point     newLocation1 = new Point(oldBounds.Left + deltaX, oldBounds.Top + deltaY);
                        Point     newLocation2 = AdjustNewLocation(obstacle, newLocation1, sd);
                        Rectangle newBounds    = new Rectangle(newLocation2, oldBounds.Size);

                        obstacle.RequestBoundsChange(newBounds);

                        // Recursively update anything snapped to this obstacle
                        UpdateDependentObstacles(obstacle, oldBounds, newBounds);
                    }
                }
            }
        }
示例#13
0
        public SnapDescription(
            SnapObstacle snappedTo,
            HorizontalSnapEdge horizontalEdge,
            VerticalSnapEdge verticalEdge,
            int xOffset,
            int yOffset)
        {
            if (snappedTo == null)
            {
                throw new ArgumentNullException("snappedTo");
            }

            this.snappedTo = snappedTo;
            this.horizontalEdge = horizontalEdge;
            this.verticalEdge = verticalEdge;
            this.xOffset = xOffset;
            this.yOffset = yOffset;
        }
示例#14
0
        public SnapDescription(
            SnapObstacle snappedTo,
            HorizontalSnapEdge horizontalEdge,
            VerticalSnapEdge verticalEdge,
            int xOffset,
            int yOffset)
        {
            if (snappedTo == null)
            {
                throw new ArgumentNullException("snappedTo");
            }

            this.snappedTo      = snappedTo;
            this.horizontalEdge = horizontalEdge;
            this.verticalEdge   = verticalEdge;
            this.xOffset        = xOffset;
            this.yOffset        = yOffset;
        }
示例#15
0
        private void SaveSnapObstacleData(ISimpleCollection<string, string> saveTo, SnapObstacle so)
        {
            string prefix = so.Name + ".";
            SnapDescription sd = this.obstacles[so];

            bool isSnappedValue = (sd != null);            
            saveTo.Set(prefix + isSnappedValueName, isSnappedValue.ToString(CultureInfo.InvariantCulture));

            if (isSnappedValue)
            {
                saveTo.Set(prefix + snappedToValueName, sd.SnappedTo.Name);
                saveTo.Set(prefix + horizontalEdgeValueName, sd.HorizontalEdge.ToString());
                saveTo.Set(prefix + verticalEdgeValueName, sd.VerticalEdge.ToString());
                saveTo.Set(prefix + xOffsetValueName, sd.XOffset.ToString(CultureInfo.InvariantCulture));
                saveTo.Set(prefix + yOffsetValueName, sd.YOffset.ToString(CultureInfo.InvariantCulture));
            }

            saveTo.Set(prefix + leftValueName, so.Bounds.Left.ToString(CultureInfo.InvariantCulture));
            saveTo.Set(prefix + topValueName, so.Bounds.Top.ToString(CultureInfo.InvariantCulture));
            saveTo.Set(prefix + widthValueName, so.Bounds.Width.ToString(CultureInfo.InvariantCulture));
            saveTo.Set(prefix + heightValueName, so.Bounds.Height.ToString(CultureInfo.InvariantCulture));
        }
示例#16
0
        private void SaveSnapObstacleData(ISimpleCollection <string, string> saveTo, SnapObstacle so)
        {
            string          prefix = so.Name + ".";
            SnapDescription sd     = this.obstacles[so];

            bool isSnappedValue = (sd != null);

            saveTo.Set(prefix + isSnappedValueName, isSnappedValue.ToString(CultureInfo.InvariantCulture));

            if (isSnappedValue)
            {
                saveTo.Set(prefix + snappedToValueName, sd.SnappedTo.Name);
                saveTo.Set(prefix + horizontalEdgeValueName, sd.HorizontalEdge.ToString());
                saveTo.Set(prefix + verticalEdgeValueName, sd.VerticalEdge.ToString());
                saveTo.Set(prefix + xOffsetValueName, sd.XOffset.ToString(CultureInfo.InvariantCulture));
                saveTo.Set(prefix + yOffsetValueName, sd.YOffset.ToString(CultureInfo.InvariantCulture));
            }

            saveTo.Set(prefix + leftValueName, so.Bounds.Left.ToString(CultureInfo.InvariantCulture));
            saveTo.Set(prefix + topValueName, so.Bounds.Top.ToString(CultureInfo.InvariantCulture));
            saveTo.Set(prefix + widthValueName, so.Bounds.Width.ToString(CultureInfo.InvariantCulture));
            saveTo.Set(prefix + heightValueName, so.Bounds.Height.ToString(CultureInfo.InvariantCulture));
        }
示例#17
0
        public Point AdjustObstacleDestination(SnapObstacle movingObstacle, Point newLocation, bool considerStickies)
        {
            Point adjustedLocation = newLocation;
            SnapDescription sd = this.obstacles[movingObstacle];
            SnapDescription newSD = null;

            foreach (SnapObstacle avoidee in this.obstacles.Keys)
            {
                if (avoidee.StickyEdges != considerStickies)
                {
                    continue;
                }

                if (avoidee.Enabled && !object.ReferenceEquals(avoidee, movingObstacle))
                {
                    SnapDescription newSD2 = DetermineNewSnapDescription(movingObstacle, adjustedLocation, avoidee, newSD);

                    if (newSD2 != null)
                    {
                        Point adjustedLocation2 = AdjustNewLocation(movingObstacle, adjustedLocation, newSD2);
                        newSD = newSD2;
                        adjustedLocation = adjustedLocation2;
                        Rectangle newBounds = new Rectangle(adjustedLocation, movingObstacle.Bounds.Size);
                    }
                }
            }

            if (sd == null || !sd.SnappedTo.StickyEdges || newSD == null || newSD.SnappedTo.StickyEdges)
            {
                this.obstacles[movingObstacle] = newSD;
            }

            return adjustedLocation;
        }
示例#18
0
        private static Point AdjustNewLocation(SnapObstacle obstacle, Point newLocation, SnapDescription snapDescription)
        {
            if (snapDescription == null ||
                (snapDescription.HorizontalEdge == HorizontalSnapEdge.Neither &&
                 snapDescription.VerticalEdge == VerticalSnapEdge.Neither))
            {
                return(obstacle.Bounds.Location);
            }

            Rectangle          obstacleRect  = new Rectangle(newLocation, obstacle.Bounds.Size);
            Rectangle          snappedToRect = snapDescription.SnappedTo.Bounds;
            HorizontalSnapEdge hEdge         = snapDescription.HorizontalEdge;
            VerticalSnapEdge   vEdge         = snapDescription.VerticalEdge;
            SnapRegion         region        = snapDescription.SnappedTo.SnapRegion;

            int deltaY = 0;

            if (hEdge == HorizontalSnapEdge.Top && region == SnapRegion.Exterior)
            {
                int newBottomEdge = snappedToRect.Top - snapDescription.YOffset;
                deltaY = obstacleRect.Bottom - newBottomEdge;
            }
            else if (hEdge == HorizontalSnapEdge.Bottom && region == SnapRegion.Exterior)
            {
                int newTopEdge = snappedToRect.Bottom + snapDescription.YOffset;
                deltaY = obstacleRect.Top - newTopEdge;
            }
            else if (hEdge == HorizontalSnapEdge.Top && region == SnapRegion.Interior)
            {
                int newTopEdge = Math.Min(snappedToRect.Bottom, snappedToRect.Top + snapDescription.YOffset);
                deltaY = obstacleRect.Top - newTopEdge;
            }
            else if (hEdge == HorizontalSnapEdge.Bottom && region == SnapRegion.Interior)
            {
                int newBottomEdge = Math.Max(snappedToRect.Top, snappedToRect.Bottom - snapDescription.YOffset);
                deltaY = obstacleRect.Bottom - newBottomEdge;
            }

            int deltaX = 0;

            if (vEdge == VerticalSnapEdge.Left && region == SnapRegion.Exterior)
            {
                int newRightEdge = snappedToRect.Left - snapDescription.XOffset;
                deltaX = obstacleRect.Right - newRightEdge;
            }
            else if (vEdge == VerticalSnapEdge.Right && region == SnapRegion.Exterior)
            {
                int newLeftEdge = snappedToRect.Right + snapDescription.XOffset;
                deltaX = obstacleRect.Left - newLeftEdge;
            }
            else if (vEdge == VerticalSnapEdge.Left && region == SnapRegion.Interior)
            {
                int newLeftEdge = Math.Min(snappedToRect.Right, snappedToRect.Left + snapDescription.XOffset);
                deltaX = obstacleRect.Left - newLeftEdge;
            }
            else if (vEdge == VerticalSnapEdge.Right && region == SnapRegion.Interior)
            {
                int newRightEdge = Math.Max(snappedToRect.Left, snappedToRect.Right - snapDescription.XOffset);
                deltaX = obstacleRect.Right - newRightEdge;
            }

            Point adjustedLocation = new Point(obstacleRect.Left - deltaX, obstacleRect.Top - deltaY);

            return(adjustedLocation);
        }
示例#19
0
 public bool ContainsSnapObstacle(SnapObstacle snapObstacle)
 {
     return this.obstacles.ContainsKey(snapObstacle);
 }
示例#20
0
        private SnapDescription DetermineNewSnapDescription(
            SnapObstacle avoider,
            Point newLocation,
            SnapObstacle avoidee,
            SnapDescription currentSnapDescription)
        {
            int ourSnapProximity;

            if (currentSnapDescription != null &&
                (currentSnapDescription.HorizontalEdge != HorizontalSnapEdge.Neither ||
                 currentSnapDescription.VerticalEdge != VerticalSnapEdge.Neither))
            {
                // the avoider is already snapped to the avoidee -- make it more difficult to un-snap
                ourSnapProximity = avoidee.SnapProximity * 2;
            }
            else
            {
                ourSnapProximity = avoidee.SnapProximity;
            }

            Rectangle avoiderRect = avoider.Bounds;

            avoiderRect.Location = newLocation;
            Rectangle avoideeRect = avoidee.Bounds;

            // Are the vertical edges close enough for snapping?
            bool vertProximity = AreEdgesClose(avoiderRect.Top, avoiderRect.Bottom, avoideeRect.Top, avoideeRect.Bottom);

            // Are the horizontal edges close enough for snapping?
            bool horizProximity = AreEdgesClose(avoiderRect.Left, avoiderRect.Right, avoideeRect.Left, avoideeRect.Right);

            // Compute distances from pertinent edges
            // (e.g. if SnapRegion.Interior, figure out distance from avoider's right edge to avoidee's right edge,
            //       if SnapRegion.Exterior, figure out distance from avoider's right edge to avoidee's left edge)
            int leftDistance;
            int rightDistance;
            int topDistance;
            int bottomDistance;

            switch (avoidee.SnapRegion)
            {
            case SnapRegion.Interior:
                leftDistance   = Math.Abs(avoiderRect.Left - avoideeRect.Left);
                rightDistance  = Math.Abs(avoiderRect.Right - avoideeRect.Right);
                topDistance    = Math.Abs(avoiderRect.Top - avoideeRect.Top);
                bottomDistance = Math.Abs(avoiderRect.Bottom - avoideeRect.Bottom);
                break;

            case SnapRegion.Exterior:
                leftDistance   = Math.Abs(avoiderRect.Left - avoideeRect.Right);
                rightDistance  = Math.Abs(avoiderRect.Right - avoideeRect.Left);
                topDistance    = Math.Abs(avoiderRect.Top - avoideeRect.Bottom);
                bottomDistance = Math.Abs(avoiderRect.Bottom - avoideeRect.Top);
                break;

            default:
                throw new InvalidEnumArgumentException("avoidee.SnapRegion");
            }

            bool leftClose   = (leftDistance < ourSnapProximity);
            bool rightClose  = (rightDistance < ourSnapProximity);
            bool topClose    = (topDistance < ourSnapProximity);
            bool bottomClose = (bottomDistance < ourSnapProximity);

            VerticalSnapEdge vEdge = VerticalSnapEdge.Neither;

            if (vertProximity)
            {
                if ((leftClose && avoidee.SnapRegion == SnapRegion.Exterior) ||
                    (rightClose && avoidee.SnapRegion == SnapRegion.Interior))
                {
                    vEdge = VerticalSnapEdge.Right;
                }
                else if ((rightClose && avoidee.SnapRegion == SnapRegion.Exterior) ||
                         (leftClose && avoidee.SnapRegion == SnapRegion.Interior))
                {
                    vEdge = VerticalSnapEdge.Left;
                }
            }

            HorizontalSnapEdge hEdge = HorizontalSnapEdge.Neither;

            if (horizProximity)
            {
                if ((topClose && avoidee.SnapRegion == SnapRegion.Exterior) ||
                    (bottomClose && avoidee.SnapRegion == SnapRegion.Interior))
                {
                    hEdge = HorizontalSnapEdge.Bottom;
                }
                else if ((bottomClose && avoidee.SnapRegion == SnapRegion.Exterior) ||
                         (topClose && avoidee.SnapRegion == SnapRegion.Interior))
                {
                    hEdge = HorizontalSnapEdge.Top;
                }
            }

            SnapDescription sd;

            if (hEdge != HorizontalSnapEdge.Neither || vEdge != VerticalSnapEdge.Neither)
            {
                int xOffset = avoider.SnapDistance;
                int yOffset = avoider.SnapDistance;

                if (hEdge == HorizontalSnapEdge.Neither)
                {
                    if (avoidee.SnapRegion == SnapRegion.Interior)
                    {
                        yOffset = avoiderRect.Top - avoideeRect.Top;
                        hEdge   = HorizontalSnapEdge.Top;
                    }
                }

                if (vEdge == VerticalSnapEdge.Neither)
                {
                    if (avoidee.SnapRegion == SnapRegion.Interior)
                    {
                        xOffset = avoiderRect.Left - avoideeRect.Left;
                        vEdge   = VerticalSnapEdge.Left;
                    }
                }

                sd = new SnapDescription(avoidee, hEdge, vEdge, xOffset, yOffset);
            }
            else
            {
                sd = null;
            }

            return(sd);
        }
示例#21
0
 public bool ContainsSnapObstacle(SnapObstacle snapObstacle)
 {
     return(this.obstacles.ContainsKey(snapObstacle));
 }
示例#22
0
 public void ParkObstacle(SnapObstacle obstacle, SnapObstacle snappedTo, HorizontalSnapEdge hEdge, VerticalSnapEdge vEdge)
 {
     SnapDescription sd = new SnapDescription(snappedTo, hEdge, vEdge, obstacle.SnapDistance, obstacle.SnapDistance);
     this.obstacles[obstacle] = sd;
     ParkObstacle(obstacle, sd);
 }
示例#23
0
        public void ReparkObstacle(SnapObstacle obstacle)
        {
            if (this.obstacles.ContainsKey(obstacle))
            {
                SnapDescription sd = this.obstacles[obstacle];

                if (sd != null)
                {
                    ParkObstacle(obstacle, sd);
                }
            }
        }
示例#24
0
        public void RemoveSnapObstacle(SnapObstacle snapObstacle)
        {
            if (this.obstacles.ContainsKey(snapObstacle))
            {
                this.obstacles.Remove(snapObstacle);

                if (snapObstacle.StickyEdges)
                {
                    snapObstacle.BoundsChanging -= SnapObstacle_BoundsChanging;
                    snapObstacle.BoundsChanged -= SnapObstacle_BoundsChanged;
                }
            }
        }
示例#25
0
        private static Point AdjustNewLocation(SnapObstacle obstacle, Point newLocation, SnapDescription snapDescription)
        {
            if (snapDescription == null ||
                (snapDescription.HorizontalEdge == HorizontalSnapEdge.Neither &&
                 snapDescription.VerticalEdge == VerticalSnapEdge.Neither))
            {
                return obstacle.Bounds.Location;
            }

            Rectangle obstacleRect = new Rectangle(newLocation, obstacle.Bounds.Size);
            Rectangle snappedToRect = snapDescription.SnappedTo.Bounds;
            HorizontalSnapEdge hEdge = snapDescription.HorizontalEdge;
            VerticalSnapEdge vEdge = snapDescription.VerticalEdge;
            SnapRegion region = snapDescription.SnappedTo.SnapRegion;

            int deltaY = 0;

            if (hEdge == HorizontalSnapEdge.Top && region == SnapRegion.Exterior)
            {
                int newBottomEdge = snappedToRect.Top - snapDescription.YOffset;
                deltaY = obstacleRect.Bottom - newBottomEdge;
            }
            else if (hEdge == HorizontalSnapEdge.Bottom && region == SnapRegion.Exterior)
            {
                int newTopEdge = snappedToRect.Bottom + snapDescription.YOffset;
                deltaY = obstacleRect.Top - newTopEdge;
            }
            else if (hEdge == HorizontalSnapEdge.Top && region == SnapRegion.Interior)
            {
                int newTopEdge = Math.Min(snappedToRect.Bottom, snappedToRect.Top + snapDescription.YOffset);
                deltaY = obstacleRect.Top - newTopEdge;
            }
            else if (hEdge == HorizontalSnapEdge.Bottom && region == SnapRegion.Interior)
            {
                int newBottomEdge = Math.Max(snappedToRect.Top, snappedToRect.Bottom - snapDescription.YOffset);
                deltaY = obstacleRect.Bottom - newBottomEdge;
            }

            int deltaX = 0;

            if (vEdge == VerticalSnapEdge.Left && region == SnapRegion.Exterior)
            {
                int newRightEdge = snappedToRect.Left - snapDescription.XOffset;
                deltaX = obstacleRect.Right - newRightEdge;
            }
            else if (vEdge == VerticalSnapEdge.Right && region == SnapRegion.Exterior)
            {
                int newLeftEdge = snappedToRect.Right + snapDescription.XOffset;
                deltaX = obstacleRect.Left - newLeftEdge;
            }
            else if (vEdge == VerticalSnapEdge.Left && region == SnapRegion.Interior)
            {
                int newLeftEdge = Math.Min(snappedToRect.Right, snappedToRect.Left + snapDescription.XOffset);
                deltaX = obstacleRect.Left - newLeftEdge;
            }
            else if (vEdge == VerticalSnapEdge.Right && region == SnapRegion.Interior)
            {
                int newRightEdge = Math.Max(snappedToRect.Left, snappedToRect.Right - snapDescription.XOffset);
                deltaX = obstacleRect.Right - newRightEdge;
            }

            Point adjustedLocation = new Point(obstacleRect.Left - deltaX, obstacleRect.Top - deltaY);
            return adjustedLocation;
        }
示例#26
0
 private static void ParkObstacle(SnapObstacle avoider, SnapDescription snapDescription)
 {
     Point newLocation = avoider.Bounds.Location;
     Point adjustedLocation = AdjustNewLocation(avoider, newLocation, snapDescription);
     Rectangle newBounds = new Rectangle(adjustedLocation, avoider.Bounds.Size);
     avoider.RequestBoundsChange(newBounds);
 }
示例#27
0
        private SnapDescription DetermineNewSnapDescription(
            SnapObstacle avoider,
            Point newLocation,
            SnapObstacle avoidee,
            SnapDescription currentSnapDescription)
        {
            int ourSnapProximity;

            if (currentSnapDescription != null &&
                (currentSnapDescription.HorizontalEdge != HorizontalSnapEdge.Neither ||
                 currentSnapDescription.VerticalEdge != VerticalSnapEdge.Neither))
            {
                // the avoider is already snapped to the avoidee -- make it more difficult to un-snap
                ourSnapProximity = avoidee.SnapProximity * 2;
            }
            else
            {
                ourSnapProximity = avoidee.SnapProximity;
            }

            Rectangle avoiderRect = avoider.Bounds;
            avoiderRect.Location = newLocation;
            Rectangle avoideeRect = avoidee.Bounds;

            // Are the vertical edges close enough for snapping?
            bool vertProximity = AreEdgesClose(avoiderRect.Top, avoiderRect.Bottom, avoideeRect.Top, avoideeRect.Bottom);

            // Are the horizontal edges close enough for snapping?
            bool horizProximity = AreEdgesClose(avoiderRect.Left, avoiderRect.Right, avoideeRect.Left, avoideeRect.Right);

            // Compute distances from pertinent edges
            // (e.g. if SnapRegion.Interior, figure out distance from avoider's right edge to avoidee's right edge,
            //       if SnapRegion.Exterior, figure out distance from avoider's right edge to avoidee's left edge)
            int leftDistance;
            int rightDistance;
            int topDistance;
            int bottomDistance;

            switch (avoidee.SnapRegion)
            {
                case SnapRegion.Interior:
                    leftDistance = Math.Abs(avoiderRect.Left - avoideeRect.Left);
                    rightDistance = Math.Abs(avoiderRect.Right - avoideeRect.Right);
                    topDistance = Math.Abs(avoiderRect.Top - avoideeRect.Top);
                    bottomDistance = Math.Abs(avoiderRect.Bottom - avoideeRect.Bottom);
                    break;

                case SnapRegion.Exterior:
                    leftDistance = Math.Abs(avoiderRect.Left - avoideeRect.Right);
                    rightDistance = Math.Abs(avoiderRect.Right - avoideeRect.Left);
                    topDistance = Math.Abs(avoiderRect.Top - avoideeRect.Bottom);
                    bottomDistance = Math.Abs(avoiderRect.Bottom - avoideeRect.Top);
                    break;

                default:
                    throw new InvalidEnumArgumentException("avoidee.SnapRegion");
            }

            bool leftClose = (leftDistance < ourSnapProximity);
            bool rightClose = (rightDistance < ourSnapProximity);
            bool topClose = (topDistance < ourSnapProximity);
            bool bottomClose = (bottomDistance < ourSnapProximity);

            VerticalSnapEdge vEdge = VerticalSnapEdge.Neither;

            if (vertProximity)
            {
                if ((leftClose && avoidee.SnapRegion == SnapRegion.Exterior) ||
                    (rightClose && avoidee.SnapRegion == SnapRegion.Interior))
                {
                    vEdge = VerticalSnapEdge.Right;
                }
                else if ((rightClose && avoidee.SnapRegion == SnapRegion.Exterior) ||
                         (leftClose && avoidee.SnapRegion == SnapRegion.Interior))
                {
                    vEdge = VerticalSnapEdge.Left;
                }
            }

            HorizontalSnapEdge hEdge = HorizontalSnapEdge.Neither;

            if (horizProximity)
            {
                if ((topClose && avoidee.SnapRegion == SnapRegion.Exterior) ||
                    (bottomClose && avoidee.SnapRegion == SnapRegion.Interior))
                {
                    hEdge = HorizontalSnapEdge.Bottom;
                }
                else if ((bottomClose && avoidee.SnapRegion == SnapRegion.Exterior) ||
                         (topClose && avoidee.SnapRegion == SnapRegion.Interior))
                {
                    hEdge = HorizontalSnapEdge.Top;
                }
            }

            SnapDescription sd;

            if (hEdge != HorizontalSnapEdge.Neither || vEdge != VerticalSnapEdge.Neither)
            {
                int xOffset = avoider.SnapDistance;
                int yOffset = avoider.SnapDistance;

                if (hEdge == HorizontalSnapEdge.Neither)
                {
                    if (avoidee.SnapRegion == SnapRegion.Interior)
                    {
                        yOffset = avoiderRect.Top - avoideeRect.Top;
                        hEdge = HorizontalSnapEdge.Top;
                    }
                }

                if (vEdge == VerticalSnapEdge.Neither)
                {
                    if (avoidee.SnapRegion == SnapRegion.Interior)
                    {
                        xOffset = avoiderRect.Left - avoideeRect.Left;
                        vEdge = VerticalSnapEdge.Left;
                    }
                }

                sd = new SnapDescription(avoidee, hEdge, vEdge, xOffset, yOffset);
            }
            else
            {
                sd = null;
            }

            return sd;
        }
示例#28
0
 /// <summary>
 /// Given an obstacle and its attempted destination, determines the correct landing
 /// spot for an obstacle.
 /// </summary>
 /// <param name="movingObstacle">The obstacle that is moving.</param>
 /// <param name="newLocation">The upper-left coordinate of the obstacle's original intended destination.</param>
 /// <returns>
 /// A Point that determines where the obstacle should be placed instead. If there are no adjustments
 /// required to the obstacle's desintation, then the return value will be equal to newLocation.
 /// </returns>
 /// <remarks>
 /// movingObstacle's SnapDescription will also be updated. The caller of this method is required
 /// to update the SnapObstacle with the new, adjusted location.
 /// </remarks>
 public Point AdjustObstacleDestination(SnapObstacle movingObstacle, Point newLocation)
 {
     Point adjusted1 = AdjustObstacleDestination(movingObstacle, newLocation, false);
     Point adjusted2 = AdjustObstacleDestination(movingObstacle, adjusted1, true);
     return adjusted2;
 }
示例#29
0
        public void Load(ISimpleCollection<string, string> loadFrom)
        {
            SnapObstacle[] newObstacles = new SnapObstacle[this.obstacles.Count];
            this.obstacles.Keys.CopyTo(newObstacles, 0);

            foreach (SnapObstacle obstacle in newObstacles)
            {
                if (obstacle.EnableSave)
                {
                    LoadSnapObstacleData(loadFrom, obstacle);
                }
            }
        }
示例#30
0
        public void AddSnapObstacle(SnapObstacle snapObstacle)
        {
            if (!this.obstacles.ContainsKey(snapObstacle))
            {
                this.obstacles.Add(snapObstacle, null);

                if (snapObstacle.StickyEdges)
                {
                    snapObstacle.BoundsChanging += SnapObstacle_BoundsChanging;
                    snapObstacle.BoundsChanged += SnapObstacle_BoundsChanged;
                }
            }
        }
示例#31
0
        private void UpdateDependentObstacles(SnapObstacle senderSO, Rectangle fromRect, Rectangle toRect)
        {
            int leftDelta = toRect.Left - fromRect.Left;
            int topDelta = toRect.Top - fromRect.Top;
            int rightDelta = toRect.Right - fromRect.Right;
            int bottomDelta = toRect.Bottom - fromRect.Bottom;

            foreach (SnapObstacle obstacle in this.obstacles.Keys)
            {
                if (!object.ReferenceEquals(senderSO, obstacle))
                {
                    SnapDescription sd = this.obstacles[obstacle];

                    if (sd != null && object.ReferenceEquals(sd.SnappedTo, senderSO))
                    {
                        int deltaX;

                        if (sd.VerticalEdge == VerticalSnapEdge.Right)
                        {
                            deltaX = rightDelta;
                        }
                        else
                        {
                            deltaX = leftDelta;
                        }

                        int deltaY;

                        if (sd.HorizontalEdge == HorizontalSnapEdge.Bottom)
                        {
                            deltaY = bottomDelta;
                        }
                        else
                        {
                            deltaY = topDelta;
                        }

                        Rectangle oldBounds = obstacle.Bounds;
                        Point newLocation1 = new Point(oldBounds.Left + deltaX, oldBounds.Top + deltaY);
                        Point newLocation2 = AdjustNewLocation(obstacle, newLocation1, sd);
                        Rectangle newBounds = new Rectangle(newLocation2, oldBounds.Size);

                        obstacle.RequestBoundsChange(newBounds);

                        // Recursively update anything snapped to this obstacle
                        UpdateDependentObstacles(obstacle, oldBounds, newBounds);
                    }
                }
            }
        }