public override void LeaveRow(ToolStrip toolStripToDrag) { // this code is here to properly add space to the next control when the // toolStripToDrag has been removed from the row. Row.SuspendLayout(); int index = Row.ControlsInternal.IndexOf(toolStripToDrag); if (index >= 0) { if (index < Row.ControlsInternal.Count - 1 /*not the last one in the row*/) { ToolStripPanelCell cell = (ToolStripPanelCell)Row.Cells[index]; if (cell.Visible) { int spaceOccupiedByCell = cell.Margin.Vertical + cell.Bounds.Height; // add the space occupied by the cell to the next one. ToolStripPanelCell nextCell = GetNextVisibleCell(index + 1, /*forward*/ true); if (nextCell != null) { Padding nextCellMargin = nextCell.Margin; nextCellMargin.Top += spaceOccupiedByCell; nextCell.Margin = nextCellMargin; } } } // remove the control from the row. ((IList)Row.Cells).RemoveAt(index); } Row.ResumeLayout(true); }
public ToolStripPanelCell GetNextVisibleCell(int index, bool forward) { if (forward) { for (int i = index; i < Row.Cells.Count; i++) { ToolStripPanelCell cell = Row.Cells[i] as ToolStripPanelCell; if ((cell.Visible || (Row.ToolStripPanel.Visible && cell.ControlInDesignMode)) && cell.ToolStripPanelRow == Row) { return(cell); } } } else { for (int i = index; i >= 0; i--) { ToolStripPanelCell cell = Row.Cells[i] as ToolStripPanelCell; if ((cell.Visible || (Row.ToolStripPanel.Visible && cell.ControlInDesignMode)) && cell.ToolStripPanelRow == Row) { return(cell); } } } return(null); }
public void RemoveAt(int index) { if (index >= 0 && index < Count) { Control control = GetControl(index); ToolStripPanelCell cell = InnerList[index] as ToolStripPanelCell; InnerList.RemoveAt(index); OnAfterRemove(control, index); } }
private int IndexOfControl(Control c) { for (int i = 0; i < Count; i++) { ToolStripPanelCell cell = (ToolStripPanelCell)(InnerList[i]); if (cell.Control == c) { return(i); } } return(-1); }
private Control GetControl(int index) { Control control = null; ToolStripPanelCell cell = null; if (index < Count && index >= 0) { cell = (ToolStripPanelCell)(InnerList[index]); control = cell?.Control; } return(control); }
private void ApplyCachedBounds() { for (int i = 0; i < Cells.Count; i++) { IArrangedElement element = Cells[i] as IArrangedElement; if (element.ParticipatesInLayout) { ToolStripPanelCell cell = element as ToolStripPanelCell; element.SetBounds(cell.CachedBounds, BoundsSpecified.None); // Debug.Assert( cell.Control is null || cell.CachedBounds.Location == cell.Control.Bounds.Location, "CachedBounds out of sync with bounds!"); } } }
protected virtual int Grow(int index, int growBy) { int freedSpace = 0; if (index >= 0 && index < Row.ControlsInternal.Count - 1) { ToolStripPanelCell cell = (ToolStripPanelCell)Row.Cells[index]; if (cell.Visible) { freedSpace = cell.Grow(growBy); } } return(freedSpace); }
protected internal override int FreeSpaceFromRow(int spaceToFree) { int requiredSpace = spaceToFree; // take a look at the last guy. if his right edge exceeds // the new bounds, then we should go ahead and push him into view. if (spaceToFree > 0) { // we should shrink the last guy and then move him. ToolStripPanelCell lastCellOnRow = GetNextVisibleCell(Row.Cells.Count - 1, /*forward*/ false); if (lastCellOnRow is null) { return(0); } Padding cellMargin = lastCellOnRow.Margin; // only check margin.left as we are only concerned with getting right edge of // the toolstrip into view. (space after the fact doesnt count). if (cellMargin.Top >= spaceToFree) { cellMargin.Top -= spaceToFree; cellMargin.Bottom = 0; spaceToFree = 0; } else { spaceToFree -= lastCellOnRow.Margin.Top; cellMargin.Top = 0; cellMargin.Bottom = 0; } lastCellOnRow.Margin = cellMargin; // start moving the toolstrips before this guy. spaceToFree -= MoveUp(Row.Cells.Count - 1, spaceToFree); if (spaceToFree > 0) { spaceToFree -= lastCellOnRow.Shrink(spaceToFree); } } return(requiredSpace - Math.Max(0, spaceToFree)); }
protected internal override void OnBoundsChanged(Rectangle oldBounds, Rectangle newBounds) { base.OnBoundsChanged(oldBounds, newBounds); // if our bounds have changed - we should shove the toolbars up so they're in view. if (Row.Cells.Count > 0) { // take a look at the last guy. if his right edge exceeds // the new bounds, then we should go ahead and push him into view. ToolStripPanelCell lastCell = GetNextVisibleCell(Row.Cells.Count - 1, /*forward=*/ false); int spaceToFree = (lastCell != null) ? lastCell.Bounds.Bottom - newBounds.Height : 0; if (spaceToFree > 0) { // we should shrink the last guy and then move him. ToolStripPanelCell lastCellOnRow = GetNextVisibleCell(Row.Cells.Count - 1, /*forward*/ false); Padding cellMargin = lastCellOnRow.Margin; // only check margin.left as we are only concerned with getting bottom edge of // the toolstrip into view. (space after the fact doesnt count). if (cellMargin.Top >= spaceToFree) { cellMargin.Top -= spaceToFree; cellMargin.Bottom = 0; lastCellOnRow.Margin = cellMargin; spaceToFree = 0; } else { spaceToFree -= lastCellOnRow.Margin.Top; cellMargin.Top = 0; cellMargin.Bottom = 0; lastCellOnRow.Margin = cellMargin; } spaceToFree -= lastCellOnRow.Shrink(spaceToFree); // start moving the toolstrips before this guy. MoveUp(Row.Cells.Count - 1, spaceToFree); } } }
protected virtual void OnLayout(LayoutEventArgs e) { if (Initialized && !_state[s_stateInLayout]) { _state[s_stateInLayout] = true; try { Margin = DefaultMargin; CachedBoundsMode = true; try { // dont layout in the constructor that's just tacky. bool parentNeedsLayout = LayoutEngine.Layout(this, e); } finally { CachedBoundsMode = false; } ToolStripPanelCell cell = RowManager.GetNextVisibleCell(Cells.Count - 1, /*forward*/ false); if (cell is null) { ApplyCachedBounds(); } else if (Orientation == Orientation.Horizontal) { OnLayoutHorizontalPostFix(); } else { OnLayoutVerticalPostFix(); } } finally { _state[s_stateInLayout] = false; } } }
public override void JoinRow(ToolStrip toolStripToDrag, Point locationToDrag) { Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "Vertical JoinRow called "); int index; if (!Row.ControlsInternal.Contains(toolStripToDrag)) { Row.SuspendLayout(); try { if (Row.ControlsInternal.Count > 0) { // walk through the columns and determine which column you want to insert into. for (index = 0; index < Row.Cells.Count; index++) { ToolStripPanelCell cell = Row.Cells[index] as ToolStripPanelCell; if (!cell.Visible && !cell.ControlInDesignMode) { continue; } // [: ] [: x ] if (cell.Bounds.Contains(locationToDrag)) { break; } // take into account the following scenarios // [: ] x [: ] // x [: ] [: ] if (cell.Bounds.Y >= locationToDrag.Y) { break; } } Control controlToPushAside = Row.ControlsInternal[index]; // Plop the new control in the midst of the row in question. if (index < Row.ControlsInternal.Count) { Row.ControlsInternal.Insert(index, toolStripToDrag); } else { Row.ControlsInternal.Add(toolStripToDrag); } // since layout is suspended the control may not be set to its preferred size yet int controlToDragWidth = (toolStripToDrag.AutoSize) ? toolStripToDrag.PreferredSize.Height : toolStripToDrag.Height; // // now make it look like it belongs in the row. // // PUSH the controls after it to the right int requiredSpace = controlToDragWidth; if (index == 0) { // make sure we account for the left side requiredSpace += locationToDrag.Y; } int freedSpace = 0; if (index < Row.ControlsInternal.Count - 1) { ToolStripPanelCell nextCell = GetNextVisibleCell(index + 1, /*forward*/ true); if (nextCell != null) { Padding nextCellMargin = nextCell.Margin; // if we've already got the empty space // (available to us via the margin) use that. if (nextCellMargin.Top > requiredSpace) { nextCellMargin.Top -= requiredSpace; nextCell.Margin = nextCellMargin; freedSpace = requiredSpace; } else { // otherwise we've got to // push all controls after this point to the right // this dumps the extra stuff into the margin of index+1 freedSpace = MoveDown(index + 1, requiredSpace - freedSpace); // refetch the margin for "index+1" and remove the freed space // from it - we want to actually put this to use on the control // before this one - we're making room for the control at // position "index" if (freedSpace > 0) { nextCellMargin = nextCell.Margin; nextCellMargin.Top -= freedSpace; nextCell.Margin = nextCellMargin; } } } } else { // we're adding to the end. ToolStripPanelCell nextCell = GetNextVisibleCell(Row.Cells.Count - 2, /*forward*/ false); ToolStripPanelCell lastCell = GetNextVisibleCell(Row.Cells.Count - 1, /*forward*/ false); // count the stuff at the end of the row as freed space if (nextCell != null && lastCell != null) { Padding lastCellMargin = lastCell.Margin; lastCellMargin.Top = Math.Max(0, locationToDrag.Y - nextCell.Bounds.Bottom); lastCell.Margin = lastCellMargin; freedSpace = requiredSpace; } } // If we still need more space, then... // PUSH the controls before it to the left if (freedSpace < requiredSpace && index > 0) { freedSpace = MoveUp(index - 1, requiredSpace - freedSpace); } if (index == 0) { // if the index is zero and there were controls in the row // we need to take care of pushing over the new cell. if (freedSpace - controlToDragWidth > 0) { ToolStripPanelCell newCell = Row.Cells[index] as ToolStripPanelCell; Padding newCellMargin = newCell.Margin; newCellMargin.Top = freedSpace - controlToDragWidth; newCell.Margin = newCellMargin; } } } else { // we're adding to the beginning. Row.ControlsInternal.Add(toolStripToDrag); #if DEBUG ISupportToolStripPanel ctg = toolStripToDrag as ISupportToolStripPanel; ToolStripPanelRow newPanelRow = ctg.ToolStripPanelRow; Debug.Assert(newPanelRow == Row, "we should now be in the new panel row."); #endif if (Row.Cells.Count > 0) { ToolStripPanelCell cell = GetNextVisibleCell(Row.Cells.Count - 1, /*forward*/ false); if (cell != null) { Padding cellMargin = cell.Margin; cellMargin.Top = Math.Max(0, locationToDrag.Y - Row.Margin.Top); cell.Margin = cellMargin; } } } } finally { Row.ResumeLayout(true); } } }
private int MoveDown(int index, int spaceToFree) { Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveDown: " + spaceToFree.ToString(CultureInfo.InvariantCulture)); int freedSpace = 0; Row.SuspendLayout(); try { if (spaceToFree == 0 || index < 0 || index >= Row.ControlsInternal.Count) { Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveDown Early EXIT - 0 "); return(0); } ToolStripPanelCell cell; Padding cellMargin; // remove all margins after this point in the index. for (int i = index + 1; i < Row.Cells.Count; i++) { cell = (ToolStripPanelCell)Row.Cells[i]; if (!cell.Visible && !cell.ControlInDesignMode) { continue; } int requiredSpace = spaceToFree - freedSpace; cellMargin = cell.Margin; if (cellMargin.Vertical >= requiredSpace) { freedSpace += requiredSpace; cellMargin.Top -= requiredSpace; cellMargin.Bottom = 0; cell.Margin = cellMargin; } else { freedSpace += cell.Margin.Vertical; cellMargin.Top = 0; cellMargin.Bottom = 0; cell.Margin = cellMargin; } break; } // add in the space at the end of the row. if (Row.Cells.Count > 0 && (spaceToFree > freedSpace)) { ToolStripPanelCell lastCell = GetNextVisibleCell(Row.Cells.Count - 1, /*forward*/ false); if (lastCell != null) { freedSpace += DisplayRectangle.Bottom - lastCell.Bounds.Bottom; } else { freedSpace += DisplayRectangle.Height; } } // set the margin of the control that's moving. if (spaceToFree <= freedSpace) { // add the space we freed to the first guy. cell = (ToolStripPanelCell)Row.Cells[index]; cellMargin = cell.Margin; cellMargin.Top += spaceToFree; cell.Margin = cellMargin; Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveDown Recovered (Margin only): " + spaceToFree.ToString(CultureInfo.InvariantCulture)); return(spaceToFree); } // Now start shrinking. for (int i = index + 1; i < Row.Cells.Count; i++) { cell = (ToolStripPanelCell)Row.Cells[i]; if (!cell.Visible && !cell.ControlInDesignMode) { continue; } int requiredSpace = spaceToFree - freedSpace; freedSpace += cell.Shrink(requiredSpace); if (spaceToFree >= freedSpace) { Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveDown Recovered (Shrink): " + spaceToFree.ToString(CultureInfo.InvariantCulture)); Row.ResumeLayout(true); return(spaceToFree); } } if (Row.Cells.Count == 1) { cell = GetNextVisibleCell(index, /*forward*/ true); if (cell != null) { cellMargin = cell.Margin; cellMargin.Top += freedSpace; cell.Margin = cellMargin; } } } finally { Row.ResumeLayout(true); } int recoveredSpace = spaceToFree - freedSpace; Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveDown Recovered Partial (Shrink): " + recoveredSpace.ToString(CultureInfo.InvariantCulture)); return(recoveredSpace); }
private int MoveUp(int index, int spaceToFree) { Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveUp: " + spaceToFree.ToString(CultureInfo.InvariantCulture)); int freedSpace = 0; Row.SuspendLayout(); try { if (spaceToFree == 0 || index < 0) { Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveUp Early EXIT - 0 "); return(0); } // remove all margins starting from the index. for (int i = index; i >= 0; i--) { ToolStripPanelCell cell = (ToolStripPanelCell)Row.Cells[i]; if (!cell.Visible && !cell.ControlInDesignMode) { continue; } int requiredSpace = spaceToFree - freedSpace; Padding cellMargin = cell.Margin; if (cellMargin.Vertical >= requiredSpace) { freedSpace += requiredSpace; cellMargin.Top -= requiredSpace; cellMargin.Bottom = 0; cell.Margin = cellMargin; } else { freedSpace += cell.Margin.Vertical; cellMargin.Top = 0; cellMargin.Bottom = 0; cell.Margin = cellMargin; } if (freedSpace >= spaceToFree) { // add the space we freed to the next guy. if (index + 1 < Row.Cells.Count) { cell = GetNextVisibleCell(index + 1, /*forward*/ true); if (cell != null) { cellMargin = cell.Margin; cellMargin.Top += spaceToFree; cell.Margin = cellMargin; } } Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveUp Recovered (Margin only): " + spaceToFree.ToString(CultureInfo.InvariantCulture)); return(spaceToFree); } } } finally { Row.ResumeLayout(true); } Debug.WriteLineIf(ToolStripPanelMouseDebug.TraceVerbose, "MoveLeft Recovered Partial (Shrink): " + freedSpace.ToString(CultureInfo.InvariantCulture)); return(freedSpace); }
private void OnLayoutVerticalPostFix() { ToolStripPanelCell cell = RowManager.GetNextVisibleCell(Cells.Count - 1, /*forward*/ false); // figure out how much space we actually need to free. int spaceToFree = cell.CachedBounds.Bottom - RowManager.DisplayRectangle.Bottom; if (spaceToFree <= 0) { // we're all good. Just apply the cached bounds. ApplyCachedBounds(); return; } // STEP 1 remove empty space in the row. // since layout sisuspended, we'll need to watch changes to the margin // as a result of calling FreeSpaceFromRow. int[] margins = new int[Cells.Count]; for (int i = 0; i < Cells.Count; i++) { ToolStripPanelCell c = Cells[i] as ToolStripPanelCell; margins[i] = c.Margin.Top; } spaceToFree -= RowManager.FreeSpaceFromRow(spaceToFree); // now apply those changes to the cached bounds. for (int i = 0; i < Cells.Count; i++) { ToolStripPanelCell c = Cells[i] as ToolStripPanelCell; Rectangle cachedBounds = c.CachedBounds; cachedBounds.X = Math.Max(0, cachedBounds.X - margins[i] - c.Margin.Top); c.CachedBounds = cachedBounds; } if (spaceToFree <= 0) { ApplyCachedBounds(); return; } // STEP 2 change the size of the remaing ToolStrips from Bottom to Top. int[] cellOffsets = null; for (int i = Cells.Count - 1; i >= 0; i--) { ToolStripPanelCell currentCell = Cells[i] as ToolStripPanelCell; if (currentCell.Visible) { Size minSize = GetMinimumSize(currentCell.Control as ToolStrip); Rectangle cachedBounds = currentCell.CachedBounds; // found some space to free. if (cachedBounds.Height > minSize.Height) { spaceToFree -= (cachedBounds.Height - minSize.Height); // make sure we dont take more space than we need - if spaceToFree is less than 0, add back in. cachedBounds.Height = (spaceToFree < 0) ? minSize.Height + -spaceToFree : minSize.Height; // we're not reperforming a layout, so we need to adjust the next cell for (int j = i + 1; j < Cells.Count; j++) { if (cellOffsets is null) { cellOffsets = new int[Cells.Count]; } cellOffsets[j] += Math.Max(0, currentCell.CachedBounds.Height - cachedBounds.Height); } currentCell.CachedBounds = cachedBounds; } } if (spaceToFree <= 0) { break; } } // fixup for items before it shrinking. if (cellOffsets != null) { for (int i = 0; i < Cells.Count; i++) { ToolStripPanelCell c = Cells[i] as ToolStripPanelCell; Rectangle cachedBounds = c.CachedBounds; cachedBounds.Y -= cellOffsets[i]; c.CachedBounds = cachedBounds; } } ApplyCachedBounds(); }