Example #1
0
 public MagnetEdge GetOppsiteEdge()
 {
     return(new MagnetEdge {
         EdgeDir = MagnetUtils.OppsiteEdge(EdgeDir), End = End, Start = Start, Window = null
     });
 }
Example #2
0
        private int FindClosestEdge(MagnetEdge refEdge)
        {
            if (refEdge == null)
            {
                return(int.MinValue);
            }

            // get all forms edges list
            var edges = Forms
                        .Where(frm => (frm != m_OriginalForm) && frm.Visible)
                        .SelectMany(MagnetUtils.FormToEdges)
                        .Where(t => !m_MoveLocks.Any(q => (q.Item1 == t.Window) && (q.Item2 == MagnetUtils.OppsiteEdge(t.EdgeDir))))
                        .ToList();
            var corners = Forms
                          .Where(frm => (frm != m_OriginalForm) && frm.Visible)
                          .SelectMany(MagnetUtils.FormToCorners)
                          .Where(t => !m_ResizeLocks.Any(q => (q.Item1 == t.Window) && (q.Item2 == t.AttractsEdge)))
                          .ToList();

            var bestDist = int.MaxValue;

            foreach (var edge in edges)
            {
                var dist = edge.MeasureAttraction(refEdge);
                if (dist != int.MinValue)
                {
                    if (Math.Abs(dist) < bestDist)
                    {
                        bestDist = dist;
                    }
                }
            }

            foreach (var corner in corners)
            {
                var dist = corner.MeasureAttraction(refEdge);
                if (dist != int.MinValue)
                {
                    if (Math.Abs(dist) < bestDist)
                    {
                        bestDist = dist;
                    }
                }
            }

            return(bestDist);
        }
Example #3
0
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_ENTERSIZEMOVE)
            {
                // Reset move tracking
                var currRect = new WinRect();
                GetWindowRect(Handle, ref currRect);
                m_MoveSum     = new Point(currRect.Left, currRect.Top);
                m_MovePrevPos = new Point(currRect.Left, currRect.Top);

                // Scan for move locks
                m_MoveLocks.Clear();
                var otherEdges = Forms
                                 .Where(frm => (frm != m_OriginalForm) && frm.Visible)
                                 .Where(frm => Forms.IndexOf(m_OriginalForm) == 0)
                                 .SelectMany(MagnetUtils.FormToEdges).ToList();

                var windowEdges = MagnetUtils.RectToEdges(currRect.ToRectangle());
                foreach (var windowEdge in windowEdges)
                {
                    foreach (var otherEdge in otherEdges)
                    {
                        if (windowEdge.MeasureAttraction(otherEdge) == 0)
                        {
                            m_MoveLocks.Add(new Tuple <Form, EdgeDirection>(otherEdge.Window, windowEdge.EdgeDir));
                        }
                    }
                }

                // Scan for resize locks
                m_ResizeLocks.Clear();
                foreach (var windowEdge in windowEdges)
                {
                    foreach (var otherEdge in otherEdges)
                    {
                        if ((windowEdge.EdgeDir == otherEdge.EdgeDir) &&
                            ((windowEdge.Start == otherEdge.End) ||
                             (windowEdge.End == otherEdge.Start)))
                        {
                            m_ResizeLocks.Add(new Tuple <Form, EdgeDirection>(otherEdge.Window, otherEdge.EdgeDir));
                        }
                    }
                }

                // Remove resize locks duplications
                m_ResizeLocks = m_ResizeLocks.GroupBy(a => a.Item1.GetHashCode() ^ a.Item2.GetHashCode()).Select(grp => grp.First()).ToList();
            }

            else if (m.Msg == WM_SIZING)
            {
                var rc = (WinRect)Marshal.PtrToStructure(m.LParam, typeof(WinRect));

                // Convert WinRect into edge list
                var resizeRect  = rc.ToRectangle();
                var windowEdges = MagnetUtils.RectToEdges(resizeRect).ToDictionary(edge => edge.EdgeDir, edge => edge);

                // Create resize map
                var map = new Dictionary <int, EdgeDirection[]>
                {
                    { WMSZ_LEFT, new[] { EdgeDirection.Left } },
                    { WMSZ_RIGHT, new[] { EdgeDirection.Right } },
                    { WMSZ_TOP, new[] { EdgeDirection.Top } },
                    { WMSZ_BOTTOM, new[] { EdgeDirection.Bottom } },
                    { WMSZ_LEFT + WMSZ_TOP, new[] { EdgeDirection.Left, EdgeDirection.Top } },
                    { WMSZ_LEFT + WMSZ_BOTTOM, new[] { EdgeDirection.Left, EdgeDirection.Bottom } },
                    { WMSZ_RIGHT + WMSZ_TOP, new[] { EdgeDirection.Right, EdgeDirection.Top } },
                    { WMSZ_RIGHT + WMSZ_BOTTOM, new[] { EdgeDirection.Right, EdgeDirection.Bottom } },
                };

                // Edge list
                EdgeDirection[] edgeList;
                if (!map.TryGetValue(m.WParam.ToInt32(), out edgeList))
                {
                    edgeList = new EdgeDirection[0];
                }

                // Handle horizontal resize
                foreach (var edgeDir in edgeList)
                {
                    var movingEdge  = windowEdges[edgeDir];
                    var magDistance = FindClosestEdge(movingEdge);
                    if (Math.Abs(magDistance) < 20)
                    {
                        resizeRect = MagnetUtils.ShiftRectangleEdge(resizeRect, edgeDir, magDistance);
                    }
                }

                // Rebuild new position edges
                windowEdges = MagnetUtils.RectToEdges(resizeRect).ToDictionary(a => a.EdgeDir, a => a);

                // Enforce resize locks
                foreach (var resizeLock in m_ResizeLocks)
                {
                    var otherRect = resizeLock.Item1.Bounds;
                    otherRect = MagnetUtils.SetRectangleEdge(otherRect, windowEdges[resizeLock.Item2]);
                    resizeLock.Item1.SetBounds(otherRect.X, otherRect.Y, otherRect.Width, otherRect.Height);
                }

                // Enfore move-on-resize windows
                foreach (var moveLock in m_MoveLocks)
                {
                    var otherRect = moveLock.Item1.Bounds;
                    otherRect = MagnetUtils.SetEntireRectangleEdge(otherRect, windowEdges[moveLock.Item2].GetOppsiteEdge());
                    moveLock.Item1.SetBounds(otherRect.X, otherRect.Y, otherRect.Width, otherRect.Height);
                }

                // Convert rect to LParam
                rc = WinRect.FromRectangle(resizeRect);
                Marshal.StructureToPtr(rc, m.LParam, true);

                m.Result = new IntPtr(1);
            }

            else if (m.Msg == WM_MOVING)
            {
                var rc = (WinRect)Marshal.PtrToStructure(m.LParam, typeof(WinRect));

                // Update MoveSum
                m_MoveSum.X += rc.Left - m_MovePrevPos.X;
                m_MoveSum.Y += rc.Top - m_MovePrevPos.Y;

                // Convert WinRect into edge list
                var moveRect = rc.ToRectangle();
                moveRect.Location = m_MoveSum;

                // Do magnetics twice, this has to be done so edge-to-edge works first and only then edge-to-corner works
                for (int i = 0; i < 2; i++)
                {
                    // Scan all edges directions and check if we can stick to other windows
                    foreach (EdgeDirection edgeType in Enum.GetValues(typeof(EdgeDirection)))
                    {
                        // Get edge info
                        var edge = MagnetUtils.RectToEdges(moveRect).First(t => t.EdgeDir == edgeType);

                        // Stick to other windows
                        var magDistance = FindClosestEdge(edge);
                        if (Math.Abs(magDistance) < 20)
                        {
                            moveRect = MagnetUtils.ShiftEntireRectangle(moveRect, edge.EdgeDir, magDistance);
                        }
                    }
                }

                // Move other windows
                foreach (var lockedWindows in m_MoveLocks)
                {
                    var otherRect = lockedWindows.Item1.Bounds;
                    otherRect.Offset(moveRect.Location.X - m_MovePrevPos.X, moveRect.Location.Y - m_MovePrevPos.Y);
                    lockedWindows.Item1.SetBounds(otherRect.X, otherRect.Y, otherRect.Width, otherRect.Height);
                }

                // Save position to track delta
                m_MovePrevPos = moveRect.Location;

                // Convert rect to LParam
                rc = WinRect.FromRectangle(moveRect);
                Marshal.StructureToPtr(rc, m.LParam, true);

                m.Result = new IntPtr(1);
            }

            base.WndProc(ref m);
        }