private void Control_MouseDown(Object sender, MouseEventArgs e) { Rectangle rect = new Rectangle(0, 0, Width, Height); Point mousePoint = PointToClient(Cursor.Position); for (int i = 0; i < windowInfo.Count; i++) { if (windowInfo[i].hasGrip) { switch (windowInfo[i].dock) { case dockMode.Right: case dockMode.Left: Rectangle gripRectRL = new Rectangle(windowInfo[i].window.Left, windowInfo[i].window.Top + windowInfo[i].window.Height, windowInfo[i].window.Width, gripSize); if (gripRectRL.Contains(mousePoint)) { Cursor.Current = Cursors.HSplit; drag = true; dragIndex = i; dragMousePosition = Cursor.Position; dragMode = resizeMode.windowOnly; dragSize = windowInfo[i].window.Size; int belowWindow = getBelowWindow(getRectangle(windowInfo[i].window), windowInfo[i].dock, i); if (belowWindow > -1) dragNearWindowLocation = windowInfo[belowWindow].window.Location; return; } break; case dockMode.Bottom: case dockMode.Top: Rectangle gripRectBT = new Rectangle(windowInfo[i].window.Left + windowInfo[i].window.Width, windowInfo[i].window.Top, gripSize, windowInfo[i].window.Height); if (gripRectBT.Contains(mousePoint)) { Cursor.Current = Cursors.VSplit; drag = true; dragIndex = i; dragMousePosition = Cursor.Position; dragMode = resizeMode.windowOnly; dragSize = windowInfo[i].window.Size; int rightWindow = getRightWindow(getRectangle(windowInfo[i].window), windowInfo[i].dock, i); if (rightWindow > -1) dragNearWindowLocation = windowInfo[rightWindow].window.Location; return; } break; } } } Rectangle rightDockDrag = new Rectangle(((rect.X + rect.Width) - rightDockWidth) - gripSize, rect.Y, gripSize, rect.Height); Rectangle leftDockDrag = new Rectangle(rect.X + leftDockWidth, rect.Y, gripSize, rect.Height); Rectangle bottomDockDrag = new Rectangle(rect.X, ((rect.Y + rect.Height) - bottomDockHeight) - gripSize, rect.Width, gripSize); Rectangle topDockDrag = new Rectangle(rect.X, rect.Y + topDockHeight, rect.Width, gripSize); if ((windowCount(dockMode.Right) > 0) && rightDockDrag.Contains(mousePoint)) { Cursor.Current = Cursors.VSplit; drag = true; dragMousePosition = Cursor.Position; dragMode = resizeMode.entireSide; dragSide = dockMode.Right; } else if ((windowCount(dockMode.Left) > 0) && leftDockDrag.Contains(mousePoint)) { Cursor.Current = Cursors.VSplit; drag = true; dragMousePosition = Cursor.Position; dragMode = resizeMode.entireSide; dragSide = dockMode.Left; } else if ((windowCount(dockMode.Bottom) > 0) && bottomDockDrag.Contains(mousePoint)) { Cursor.Current = Cursors.HSplit; drag = true; dragMousePosition = Cursor.Position; dragMode = resizeMode.entireSide; dragSide = dockMode.Bottom; } else if ((windowCount(dockMode.Top) > 0) && topDockDrag.Contains(mousePoint)) { Cursor.Current = Cursors.HSplit; drag = true; dragMousePosition = Cursor.Position; dragMode = resizeMode.entireSide; dragSide = dockMode.Top; } }
/// <summary> /// Get the Rectangle of the total area of a given dock side. /// </summary> /// <param name="dock"></param> /// <returns></returns> private Rectangle getDockRect(dockMode dock) { Rectangle rect = new Rectangle(0, 0, Width, Height); Rectangle rightDock = new Rectangle((rect.X + rect.Width) - rightDockWidth, rect.Y, rightDockWidth, rect.Height); Rectangle leftDock = new Rectangle(rect.X, rect.Y, leftDockWidth, rect.Height); Rectangle bottomDock = new Rectangle(rect.X, (rect.Y + rect.Height) - bottomDockHeight, rect.Width, bottomDockHeight); Rectangle topDock = new Rectangle(rect.X, rect.Y, rect.Width, topDockHeight); Rectangle centerDock = new Rectangle(rect.Location, rect.Size); //Redimensiona os espaços de dock de acordo com outros Dock Sides existentes if (windowCount(dockMode.Right) > 0) { bottomDock.Width -= (rightDockWidth + gripSize); topDock.Width -= (rightDockWidth + gripSize); centerDock.Width -= (rightDockWidth + gripSize); } if (windowCount(dockMode.Left) > 0) { bottomDock.X += leftDockWidth + gripSize; bottomDock.Width -= (leftDockWidth + gripSize); topDock.X += leftDockWidth + gripSize; topDock.Width -= (leftDockWidth + gripSize); centerDock.X += leftDockWidth + gripSize; centerDock.Width -= (leftDockWidth + gripSize); } if (windowCount(dockMode.Bottom) > 0) centerDock.Height -= (bottomDockHeight + gripSize); if (windowCount(dockMode.Top) > 0) { centerDock.Y += topDockHeight + gripSize; centerDock.Height -= (topDockHeight + gripSize); } switch (dock) { case dockMode.Right: return rightDock; case dockMode.Left: return leftDock; case dockMode.Bottom: return bottomDock; case dockMode.Top: return topDock; case dockMode.Center: return centerDock; } return Rectangle.Empty; }
private void resize(Rectangle rect, dockMode dock) { Rectangle dockRect = getDockRect(dock); int top = dockRect.Top; int left = dockRect.Left; List<int> indexList = new List<int>(); switch (dock) { case dockMode.Right: case dockMode.Left: int indexRL = getTopmostWindow(dock); while (indexRL > -1) { indexList.Add(indexRL); indexRL = getBelowWindow(getRectangle(windowInfo[indexRL].window), dock, indexRL); } for (int i = 0; i < indexList.Count; i++) { int index = indexList[i]; windowInfo[index].window.Top = top; windowInfo[index].window.Left = dockRect.Left; windowInfo[index].window.Width = dockRect.Width; if (i != indexList.Count - 1) { windowInfo[index].window.Height = (int)(rect.Height * windowInfo[index].windowProportions.Height) - gripSize; windowInfo[index].hasGrip = true; } else { windowInfo[index].window.Height = ((dockRect.Y + dockRect.Height) - windowInfo[index].window.Top); windowInfo[index].hasGrip = false; } top += windowInfo[index].window.Height + gripSize; } break; case dockMode.Bottom: case dockMode.Top: int indexBT = getLeftmostWindow(dock); while (indexBT > -1) { indexList.Add(indexBT); indexBT = getRightWindow(getRectangle(windowInfo[indexBT].window), dock, indexBT); } for (int i = 0; i < indexList.Count; i++) { int index = indexList[i]; windowInfo[index].window.Top = dockRect.Top; windowInfo[index].window.Left = left; windowInfo[index].window.Height = dockRect.Height; if (i != indexList.Count - 1) { windowInfo[index].window.Width = (int)(rect.Width * windowInfo[index].windowProportions.Width) - gripSize; windowInfo[index].hasGrip = true; } else { windowInfo[index].window.Width = ((dockRect.X + dockRect.Width) - windowInfo[index].window.Left); windowInfo[index].hasGrip = false; } left += windowInfo[index].window.Width + gripSize; } break; case dockMode.Center: int centerIndex = getCenterWindow(); if (centerIndex > -1) { windowInfo[centerIndex].window.Location = dockRect.Location; windowInfo[centerIndex].window.Size = dockRect.Size; } break; } }
/// <summary> /// Get the last window from left to right of a given dock side. /// </summary> /// <param name="dock">Top or Bottom dock side</param> /// <returns></returns> private int getRightmostWindow(dockMode dock) { int index = -1; int left = 0; for (int i = 0; i < windowInfo.Count; i++) { if (windowInfo[i].dock == dock) { if (windowInfo[i].window.Left >= left) { left = windowInfo[i].window.Left; index = i; } } } return index; }
/// <summary> /// Try to get enough space to create a dock side, reducing existing dock sides. /// </summary> /// <param name="dock">Target dock side</param> /// <param name="newSpace">Necessary space to be freed</param> /// <returns>Returns true if it get enough space or false if it doesn't</returns> private bool getSpaceToCreateDockSide(dockMode dock, int newSpace) { switch (dock) { case dockMode.Right: case dockMode.Left: int bottomIndex = -1, topIndex = -1; bool centerHasSpace = false; int width = newSpace + gripSize; //Primeiro verifica se é possivel encontrar um controle nos 3 docks do meio que dê para reduzir para caber o novo Dock Side int bIndex = dock == dockMode.Right ? getRightmostWindow(dockMode.Bottom) : getLeftmostWindow(dockMode.Bottom); //Bottom while (bIndex > -1) { if ((windowInfo[bIndex].window.Width - width) >= minimumWidth) { bottomIndex = bIndex; break; } Rectangle w = getRectangle(windowInfo[bIndex].window); bIndex = dock == dockMode.Right ? getLeftWindow(w, dockMode.Bottom, bIndex) : getRightWindow(w, dockMode.Bottom, bIndex); } int tIndex = dock == dockMode.Right ? getRightmostWindow(dockMode.Top) : getLeftmostWindow(dockMode.Top); //Top while (tIndex > -1) { if ((windowInfo[tIndex].window.Width - width) >= minimumWidth) { topIndex = tIndex; break; } Rectangle w = getRectangle(windowInfo[tIndex].window); tIndex = dock == dockMode.Right ? getLeftWindow(w, dockMode.Top, tIndex) : getRightWindow(w, dockMode.Top, tIndex); } foreach (windowInfoStruct w in windowInfo.Where(w => w.dock == dockMode.Center && (w.window.Width - width) >= minimumWidth)) { centerHasSpace = true; } //Redimensiona e reposiciona os Windows para dar espaço ao novo Dock Side bool result = (bottomIndex > -1 || windowCount(dockMode.Bottom) == 0) && (topIndex > -1 || windowCount(dockMode.Top) == 0) && (centerHasSpace || windowCount(dockMode.Center) == 0); if (width + (windowCount(dockMode.Right) > 0 ? rightDockWidth : 0) + (windowCount(dockMode.Left) > 0 ? leftDockWidth : 0) + gripSize * 2 > Width) result = false; if (result) { if (dock == dockMode.Right) //Lado direito { if (bottomIndex > -1) { windowInfo[bottomIndex].window.Width -= width; int index = getRightWindow(getRectangle(windowInfo[bottomIndex].window), dockMode.Bottom, bottomIndex); while (index > -1) { windowInfo[index].window.Left -= width; index = getRightWindow(getRectangle(windowInfo[index].window), dockMode.Bottom, index); } } if (topIndex > -1) { windowInfo[topIndex].window.Width -= width; int index = getRightWindow(getRectangle(windowInfo[topIndex].window), dockMode.Top, topIndex); while (index > -1) { windowInfo[index].window.Left -= width; index = getRightWindow(getRectangle(windowInfo[index].window), dockMode.Top, index); } } if (windowCount(dockMode.Center) > 0) { int index = getCenterWindow(); windowInfo[index].window.Width -= width; } } else //Lado esquerdo { if (bottomIndex > -1) { windowInfo[bottomIndex].window.Width -= width; windowInfo[bottomIndex].window.Left += width; int index = getLeftWindow(getRectangle(windowInfo[bottomIndex].window), dockMode.Bottom, bottomIndex); while (index > -1) { windowInfo[index].window.Left += width; index = getLeftWindow(getRectangle(windowInfo[index].window), dockMode.Bottom, index); } } if (topIndex > -1) { windowInfo[topIndex].window.Width -= width; windowInfo[topIndex].window.Left += width; int index = getLeftWindow(getRectangle(windowInfo[topIndex].window), dockMode.Top, topIndex); while (index > -1) { windowInfo[index].window.Left += width; index = getLeftWindow(getRectangle(windowInfo[index].window), dockMode.Top, index); } } if (windowCount(dockMode.Center) > 0) { int index = getCenterWindow(); windowInfo[index].window.Width -= width; windowInfo[index].window.Left += width; } } } return result; case dockMode.Bottom: int bottomHeight = newSpace + gripSize; bool hasBottom = windowCount(dockMode.Top) == 0 || ((Height - topDockHeight) >= bottomHeight); if (bottomHeight + (windowCount(dockMode.Bottom) > 0 ? bottomDockHeight : 0) + (windowCount(dockMode.Top) > 0 ? topDockHeight : 0) + gripSize * 2 > Height) hasBottom = false; if (windowCount(dockMode.Center) > 0) { int index = getCenterWindow(); if (windowInfo[index].window.Height - bottomHeight >= minimumHeight) windowInfo[index].window.Height -= bottomHeight; else hasBottom = false; } return hasBottom; case dockMode.Top: int topHeight = newSpace + gripSize; bool hasTop = windowCount(dockMode.Bottom) == 0 || ((Height - bottomDockHeight) >= topHeight); if (topHeight + (windowCount(dockMode.Bottom) > 0 ? bottomDockHeight : 0) + (windowCount(dockMode.Top) > 0 ? topDockHeight : 0) + gripSize * 2 > Height) hasTop = false; if (windowCount(dockMode.Center) > 0) { int index = getCenterWindow(); if (windowInfo[index].window.Height - topHeight >= minimumHeight) { windowInfo[index].window.Height -= topHeight; windowInfo[index].window.Top += topHeight; } else hasTop = false; } return hasTop; } return false; }
/// <summary> /// Get the last window from top to bottom of a given dock side. /// </summary> /// <param name="dock">Left or Right dock side</param> /// <returns></returns> private int getBottommostWindow(dockMode dock) { int index = -1; int top = 0; for (int i = 0; i < windowInfo.Count; i++) { if (windowInfo[i].dock == dock) { if (windowInfo[i].window.Top >= top) { top = windowInfo[i].window.Top; index = i; } } } return index; }
/// <summary> /// Get the first window from left to right of a given dock side. /// </summary> /// <param name="dock">Top or Bottom dock side</param> /// <returns></returns> private int getLeftmostWindow(dockMode dock) { int index = -1; int left = int.MaxValue; for (int i = 0; i < windowInfo.Count; i++) { if (windowInfo[i].dock == dock) { if (windowInfo[i].window.Left < left) { left = windowInfo[i].window.Left; index = i; } } } return index; }
/// <summary> /// Get the first window from top to bottom of a given dock side. /// </summary> /// <param name="dock">Left or Right dock side</param> /// <returns></returns> private int getTopmostWindow(dockMode dock) { int index = -1; int top = int.MaxValue; for (int i = 0; i < windowInfo.Count; i++) { if (windowInfo[i].dock == dock) { if (windowInfo[i].window.Top < top) { top = windowInfo[i].window.Top; index = i; } } } return index; }
/// <summary> /// Counts the number of Windows on a given dock side. /// </summary> /// <param name="dock"></param> /// <returns></returns> private int windowCount(dockMode dock) { return windowInfo.Count(t => t.dock == dock); }
/// <summary> /// Automatically arrange the Windows on a given dock side when a Window is removed. /// </summary> /// <param name="dock"></param> /// <param name="dockRect"></param> private void autoArrange(dockMode dock, Rectangle dockRect) { int top = dockRect.Top; int left = dockRect.Left; switch (dock) { case dockMode.Right: case dockMode.Left: int indexRL = getTopmostWindow(dock); while (indexRL > -1) { int belowWindow = getBelowWindow(getRectangle(windowInfo[indexRL].window), dock, indexRL); windowInfo[indexRL].window.Top = top; windowInfo[indexRL].window.Left = dockRect.Left; windowInfo[indexRL].window.Width = dockRect.Width; if (belowWindow > -1) { windowInfo[indexRL].window.Height = (windowInfo[belowWindow].window.Top - windowInfo[indexRL].window.Top) - gripSize; windowInfo[indexRL].hasGrip = true; } else { windowInfo[indexRL].window.Height = ((dockRect.Y + dockRect.Height) - windowInfo[indexRL].window.Top); windowInfo[indexRL].hasGrip = false; } top += windowInfo[indexRL].window.Height + gripSize; indexRL = belowWindow; } break; case dockMode.Bottom: case dockMode.Top: int indexBT = getLeftmostWindow(dock); while (indexBT > -1) { int rightWindow = getRightWindow(getRectangle(windowInfo[indexBT].window), dock, indexBT); windowInfo[indexBT].window.Top = dockRect.Top; windowInfo[indexBT].window.Left = left; windowInfo[indexBT].window.Height = dockRect.Height; if (rightWindow > -1) { windowInfo[indexBT].window.Width = (windowInfo[rightWindow].window.Left - windowInfo[indexBT].window.Left) - gripSize; windowInfo[indexBT].hasGrip = true; } else { windowInfo[indexBT].window.Width = ((dockRect.X + dockRect.Width) - windowInfo[indexBT].window.Left); windowInfo[indexBT].hasGrip = false; } left += windowInfo[indexBT].window.Width + gripSize; indexBT = rightWindow; } break; } }
/// <summary> /// Get the Window placed exactly at the right side of Rectangle passed to the function. /// Returns -1 if it can't find any Window at the right. /// </summary> /// <param name="rect">The rectangle at where your window is located</param> /// <param name="dock">The docking mode that will be used</param> /// <param name="ignoreIndex">Index of the Window used to be ignored</param> /// <returns>Returns the Index for the Window on the list, or -1 if it can't be found</returns> private int getRightWindow(Rectangle rect, dockMode dock, int ignoreIndex) { int index = -1; int left = int.MaxValue; for (int i = 0; i < windowInfo.Count; i++) { if (windowInfo[i].dock == dock && windowInfo[i].window.Left >= rect.X && i != ignoreIndex) { if (windowInfo[i].window.Left < left) { left = windowInfo[i].window.Left; index = i; } } } return index; }
/// <summary> /// Get the Window placed exactly below the Rectangle passed to the function. /// Returns -1 if it can't find any Window below. /// </summary> /// <param name="rect">The rectangle at where your window is located</param> /// <param name="dock">The docking mode that will be used</param> /// <param name="ignoreIndex">Index of the Window used to be ignored</param> /// <returns>Returns the Index for the Window on the list, or -1 if it can't be found</returns> private int getBelowWindow(Rectangle rect, dockMode dock, int ignoreIndex) { int index = -1; int top = int.MaxValue; for (int i = 0; i < windowInfo.Count; i++) { if (windowInfo[i].dock == dock && windowInfo[i].window.Top >= rect.Y && i != ignoreIndex) { if (windowInfo[i].window.Top < top) { top = windowInfo[i].window.Top; index = i; } } } return index; }