/// <summary> /// perform layout after splitter was moved /// </summary> /// <param name="splitter"></param> /// <param name="e"></param> internal void onSplitterMoved(Splitter splitter, SplitterEventArgs e) { MgSplitContainer mgSplitContainer = (MgSplitContainer)splitter.Parent; mgSplitContainer.IgnoreLayout = false; mgSplitContainer.PerformLayout(); }
///// <summary> handle the paint of the splitter ///// ///// </summary> ///// <param name="event"> ///// </param> internal void onPaint(Splitter splitter, PaintEventArgs e) { if (splitter.Parent is MgSplitContainer) { MgSplitContainer mgSahsForm = (MgSplitContainer)splitter.Parent; Graphics G = e.Graphics; Pen pen = new Pen(Color.Black, 1); Rectangle rect = splitter.Bounds; System.Console.WriteLine(rect); if (mgSahsForm.getOrientation() == MgSplitContainer.SPLITTER_STYLE_VERTICAL) { pen.Color = SystemColors.ControlLightLight; G.DrawLine(pen, 0, 0, rect.Width - 2, 0); G.DrawLine(pen, 0, 1, rect.Width - 2, 1); pen.Color = SystemColors.ControlDark; G.DrawLine(pen, 0, 2, rect.Width - 2, 2); pen.Color = Color.Black; G.DrawLine(pen, 0, 3, rect.Width - 3, 3); } else if (mgSahsForm.getOrientation() == MgSplitContainer.SPLITTER_STYLE_HORIZONTAL) { pen.Color = SystemColors.ControlLightLight; G.DrawLine(pen, 0, 0, 0, rect.Height - 2); G.DrawLine(pen, 1, 0, 1, rect.Height - 2); pen.Color = SystemColors.ControlDark; G.DrawLine(pen, 2, 0, 2, rect.Height - 2); pen.Color = Color.Black; G.DrawLine(pen, 3, 0, 3, rect.Height - 3); } pen.Dispose(); } }
/// <summary> /// handle the resize of the splitter, need to re paint the 4 prev pix /// </summary> /// <param name = "event"> /// </param> internal void onResize() { MgSplitContainer mgSahsForm = this; TagData tagData = null; for (int i = 0; i < mgSahsForm.Splitters.Count; i++) { Splitter splitter = mgSahsForm.Splitters[i]; tagData = ((TagData)splitter.Tag); if (tagData.RepaintRect != null) { Rectangle paintRect = (Rectangle)tagData.RepaintRect; Rectangle drawRect = new Rectangle(); if (mgSahsForm.getOrientation() == SPLITTER_STYLE_VERTICAL) { drawRect = new Rectangle(paintRect.Width - 3, 0, 3, paintRect.Height); } else { drawRect = new Rectangle(0, paintRect.Height - 3, paintRect.Width, 3); } splitter.Invalidate(drawRect, true); tagData.RepaintRect = null; } } if (((TagData)mgSahsForm.Tag).RepaintRect != null) { tagData = ((TagData)mgSahsForm.Tag); Rectangle paintRect = (Rectangle)tagData.RepaintRect; paintRect.Width = Math.Min(paintRect.Width, mgSahsForm.Bounds.Width); paintRect.Height = Math.Min(paintRect.Height, mgSahsForm.Bounds.Height); Rectangle drawRect = new Rectangle(); drawRect = new Rectangle(paintRect.Width - 3, 0, 3, paintRect.Height); mgSahsForm.Invalidate(drawRect, true); drawRect = new Rectangle(0, paintRect.Height - 3, paintRect.Width, 3); mgSahsForm.Invalidate(drawRect, true); tagData.RepaintRect = null; } }
/// <summary> handle the event of the MgSplitContainer</summary> internal override void handleEvent(EventType type, Object sender, EventArgs e) { MgSplitContainer mgSplitContainer = (MgSplitContainer)sender; DefaultHandler defaultHandler = DefaultHandler.getInstance(); switch (type) { case EventType.PAINT: Graphics G = ((PaintEventArgs)e).Graphics; if (GuiUtils.isOutmostMgSplitContainer(mgSplitContainer)) { Rectangle rect = ((Control)mgSplitContainer).ClientRectangle; Pen pen = new Pen(Color.Black, 1); // draw top horizontal lines - pen.Color = SystemColors.ButtonShadow; G.DrawLine(pen, rect.X, rect.Y, rect.Width - 2, rect.Y); pen.Color = Color.Black; G.DrawLine(pen, rect.X + 1, rect.Y + 1, rect.Width - 4, rect.Y + 1); // draw left vertical lines |- pen.Color = SystemColors.ButtonShadow; G.DrawLine(pen, rect.X, rect.Y, rect.X, rect.Height - 3); pen.Color = Color.Black; G.DrawLine(pen, rect.X + 1, rect.Y + 1, rect.X + 1, rect.Height - 4); // draw bottom horizontal lines _ pen.Color = SystemColors.ButtonHighlight; G.DrawLine(pen, rect.X + 1, rect.Height - 2, rect.Width - 2, rect.Height - 2); //// draw right vertical lines -| pen.Color = SystemColors.ButtonHighlight; G.DrawLine(pen, rect.Width - 2, rect.Y, rect.Width - 2, rect.Height - 1); pen.Dispose(); } break; case EventType.KEY_DOWN: defaultHandler.handleEvent(type, sender, e); break; case EventType.RESIZE: mgSplitContainer.onResize(); break; } }
/// <summary> update the or size according to the send parameters and orientation /// /// </summary> /// <param name="controlBefore"> /// </param> /// <param name="newBeforeControlBounds"> /// </param> /// <param name="controlAfter"> /// </param> /// <param name="newAfterControlBounds"> /// </param> private void setOrgSize(MgSplitContainer mgSplitContainer, Control controlBefore, Rectangle newBeforeControlBounds, Control controlAfter, Rectangle newAfterControlBounds) { // get the layout, is not exist then create the layout for the before\after control MgSplitContainerData layoutDataBeforeControl = GuiUtils.getMgSplitContainerData(controlBefore); MgSplitContainerData layoutDataAfterControl = GuiUtils.getMgSplitContainerData(controlAfter); if (mgSplitContainer.getOrientation() == MgSplitContainer.SPLITTER_STYLE_HORIZONTAL) { layoutDataBeforeControl.orgWidth = newBeforeControlBounds.Width; layoutDataAfterControl.orgWidth = newAfterControlBounds.Width; } else { layoutDataBeforeControl.orgHeight = newBeforeControlBounds.Height; layoutDataAfterControl.orgHeight = newAfterControlBounds.Height; } }
/// <summary> The dynamic client area is calculated by taking the client area and subtracting the non-allowed /// placement frames and if reducing the size then also subtract frames that have reached their minimum /// size. /// /// </summary> /// <param name="MgSplitContainer"> /// </param> /// <param name="clientArea"> /// </param> /// <param name="controls"> /// </param> /// <param name="splitters"> /// </param> /// <returns> /// </returns> private int calcAreaS(MgSplitContainer mgSplitContainer, Rectangle clientArea, Control[] controls, Splitter [] splitters, bool checkProperties, bool checkMinSize, bool calWithMinSize) { // 1- calculate the width of all the splitters int allSplittersWidth = MgSplitContainer.SPLITTER_WIDTH; //TODO: Border size is all the time 0 //if (splitters.Length > 0) //allSplittersWidth = Splitters.Length * (MgSplitContainer.SPLITTER_WIDTH + Splitters[0].getBorderWidth() * 2); // 2- calculate the original area- width and height, of all the controls that NOT in placement int widthControlsNoInPlacement = getTotalSizeOfControls(controls, mgSplitContainer.getOrientation(), false, calWithMinSize, checkProperties, checkMinSize); // 3 - calculate the area,client area - all the Splitter width - all the controls that not include in // placement int areaS = (mgSplitContainer.getOrientation() == MgSplitContainer.SPLITTER_STYLE_HORIZONTAL ? clientArea.Width : clientArea.Height); areaS -= (allSplittersWidth + widthControlsNoInPlacement); return(areaS); }
/// <summary> /// /// </summary> /// <param name="MgSplitContainer"></param> /// <param name="e"></param> /// <param name="selectedSplitterBounds"></param> /// <param name="beforeControlBounds"></param> /// <param name="beforeControlMinimumSize"></param> /// <param name="afterControlBounds"></param> /// <param name="afterControlMinimumSize"></param> /// <returns></returns> private int getShift(MgSplitContainer mgSplitContainer, SplitterEventArgs e, Rectangle selectedSplitterBounds, Rectangle beforeControlBounds, int beforeControlMinimumSize, Rectangle afterControlBounds, int afterControlMinimumSize) { int shift = 0; if (mgSplitContainer.getOrientation() == MgSplitContainer.SPLITTER_STYLE_HORIZONTAL) { shift = e.SplitX - selectedSplitterBounds.X; if (shift < 0) // we need to check the allow of the before control { if (beforeControlBounds.Width > beforeControlMinimumSize) { if (beforeControlBounds.Width + shift < beforeControlMinimumSize) { shift = beforeControlMinimumSize - beforeControlBounds.Width; e.SplitX = selectedSplitterBounds.X + shift; } } else { shift = 0; e.SplitX = selectedSplitterBounds.X; } } // if (shift > 0)//we need to check the allow of the after control else { if (afterControlBounds.Width > afterControlMinimumSize) { if (afterControlBounds.Width + (-shift) < afterControlMinimumSize) { shift = afterControlBounds.Width - afterControlMinimumSize; e.SplitX = selectedSplitterBounds.X - (shift); } } else { shift = 0; e.SplitX = selectedSplitterBounds.X; } } } // if (getOrientation() == SWT.VERTICAL) else { shift = e.SplitY - selectedSplitterBounds.Y; if (shift < 0) //// we need to check the allow of the before control { if (beforeControlBounds.Height > beforeControlMinimumSize) { if (beforeControlBounds.Height + shift < beforeControlMinimumSize) { shift = beforeControlMinimumSize - beforeControlBounds.Height; e.SplitY = selectedSplitterBounds.Y + shift; } } else { shift = 0; e.SplitY = selectedSplitterBounds.Y; } } // if (shift > 0)//we need to check the allow of the after control else { if (afterControlBounds.Height > afterControlMinimumSize) { if (afterControlBounds.Height + (-shift) < afterControlMinimumSize) { shift = afterControlBounds.Height - afterControlMinimumSize; e.SplitY = selectedSplitterBounds.Y - (shift); } } else { shift = 0; e.SplitY = selectedSplitterBounds.Y; } } } System.Console.WriteLine("shift : " + shift); return(shift); }
/// <summary> handle the drag of the splitter /// and update the org size /// </summary> /// <param name="event"> /// </param> internal void onSplitterMoving(Splitter splitter, SplitterEventArgs e) { MgSplitContainer mgSplitContainer = (MgSplitContainer)splitter.Parent; mgSplitContainer.IgnoreLayout = true; int shift = 0; int beforeControlminimumSize = 0; int afterControlminimumSize = 0; // Rectangle splitterBounds - get the bound of the selected splitter- the new bound after the resize Rectangle boundsSelectedSplitter = splitter.Bounds; // check only when there is movement in the Splitter place bool isHorizontal = mgSplitContainer.getOrientation() == MgSplitContainer.SPLITTER_STYLE_HORIZONTAL; if ((isHorizontal && e.SplitX == boundsSelectedSplitter.X) || (!isHorizontal && e.SplitY == boundsSelectedSplitter.Y)) { mgSplitContainer.IgnoreLayout = false; return; } int SplitterIndex = -1; // found the Splitter that was selected in the array Splitter for (int i = 0; i < mgSplitContainer.Splitters.Count; i++) { if (mgSplitContainer.Splitters[i] == splitter) { SplitterIndex = i; break; } } // if not found return if (SplitterIndex == -1) { mgSplitContainer.IgnoreLayout = false; return; } Control[] controls = mgSplitContainer.getControls(true); // fixed bug#:769214 if (controls.Length <= SplitterIndex + 1) { mgSplitContainer.IgnoreLayout = false; return; } // get the control BEFORE the selected Splitter from the control array Control controlBefore = controls[SplitterIndex]; // get the control AFTER the selected Splitter from the control array Control controlAfter = controls[SplitterIndex + 1]; // get the minimum size of the before\After control MinSizeInfo beforeControlMinSizeInfo = GuiUtils.getMinSizeInfo(controlBefore); MinSizeInfo afterControlMinSizeInfo = GuiUtils.getMinSizeInfo(controlAfter); Point minSize; if (beforeControlMinSizeInfo != null) { minSize = beforeControlMinSizeInfo.getMinSize(false); beforeControlminimumSize = isHorizontal ? minSize.X : minSize.Y; } if (afterControlMinSizeInfo != null) { minSize = afterControlMinSizeInfo.getMinSize(false); afterControlminimumSize = isHorizontal ? minSize.X : minSize.Y; } // get the bounds of the two controls Rectangle beforeControlBounds = new Rectangle(controlBefore.Bounds.Location.X, controlBefore.Bounds.Location.Y, controlBefore.Bounds.Size.Width, controlBefore.Bounds.Size.Height); Rectangle afterControlBounds = new Rectangle(controlAfter.Bounds.Location.X, controlAfter.Bounds.Location.Y, controlAfter.Bounds.Size.Width, controlAfter.Bounds.Size.Height); ////do the movement if (isHorizontal) { // found the allow shift until the minimum size shift = getShift(mgSplitContainer, e, boundsSelectedSplitter, beforeControlBounds, beforeControlminimumSize, afterControlBounds, afterControlminimumSize); if (shift == 0) { return; } else { // update the bounds of the Splitter control by the shift value beforeControlBounds.Width += shift; afterControlBounds.X += shift; afterControlBounds.Width -= shift; e.SplitX = beforeControlBounds.Width; setOrgSize(mgSplitContainer, controlBefore, beforeControlBounds, controlAfter, afterControlBounds); } } else { // found the allow shift until the minimum size shift = getShift(mgSplitContainer, e, boundsSelectedSplitter, beforeControlBounds, beforeControlminimumSize, afterControlBounds, afterControlminimumSize); if (shift == 0) { return; } else { // update the bounds of the Splitter control by the shift value beforeControlBounds.Height += shift; afterControlBounds.Y += shift; afterControlBounds.Height -= shift; setOrgSize(mgSplitContainer, controlBefore, beforeControlBounds, controlAfter, afterControlBounds); } } }
/// <summary> /// adds events for MgSplitContainer /// </summary> /// <param name="mgSplitContainer"></param> internal void addHandler(MgSplitContainer mgSplitContainer) { mgSplitContainer.KeyDown += KeyDownHandler; mgSplitContainer.Paint += PaintHandler; mgSplitContainer.Resize += ResizeHandler; }
/// <summary> /// </summary> /// <param name="container"></param> /// <param name="layoutEventArgs"></param> /// <returns></returns> public override bool Layout(object composite, LayoutEventArgs layoutEventArgs) { /// <summary> layout the MgSplitContainer and all his children</summary> //protected internal void layout(Composite composite, bool flushCache) //{ MgSplitContainer mgSplitContainer = (MgSplitContainer)composite; //Sometime we need to ignore the layout, when we doing move to control if (mgSplitContainer.IgnoreLayout) { return(true); } double[] ratios = null; int totalOrgSize = 0; Rectangle clientArea = mgSplitContainer.ClientRectangle; if (clientArea.Width <= 1 || clientArea.Height <= 1) { return(false); } // get the controls on the mgSplitContainer (without the splitter, and only the visible) Control[] controls = mgSplitContainer.getControls(false); if (controls.Length == 0) { return(false); } // if (allControlsHaveBounds(controls) == false) // return; // check the splitter controls // checkSplitterControls(MgSplitContainer, controls); // check the direction shell was reduce or increased bool parentReduced = false; Rectangle lastClientArea = mgSplitContainer.LastClientArea; if (clientArea.Width < lastClientArea.Width || clientArea.Height < lastClientArea.Height) { parentReduced = true; } ((TagData)mgSplitContainer.Tag).RepaintRect = lastClientArea; // save the last client Area, for the next time mgSplitContainer.LastClientArea = GuiUtils.copyRect(clientArea); // get the array to the splitter controls Splitter[] splitters = new Splitter[mgSplitContainer.Splitters.Count]; for (int i = 0; i < mgSplitContainer.Splitters.Count; i++) { Splitter s = mgSplitContainer.Splitters[i]; splitters[i] = s; } //MOVE TO mgSplitContainer!!! // for the out most MgSplitContainer form we need to change the client rect, not to include the offset if (GuiUtils.isOutmostMgSplitContainer(mgSplitContainer)) { clientArea.X += (MgSplitContainer.SPLITTER_WIDTH / 2); clientArea.Y += (MgSplitContainer.SPLITTER_WIDTH / 2); clientArea.Width -= MgSplitContainer.SPLITTER_WIDTH; clientArea.Height -= MgSplitContainer.SPLITTER_WIDTH; } // check if we need to update the original size at the end of the method? bool saveSizeAtTheEnd = ratiosWillChange(parentReduced, mgSplitContainer.getOrientation(), controls); bool checkPlacement = true; bool checkMinimumSize = parentReduced; bool calcByMinSize = true; // get the dynamic client area by checking the placement & minimum size(only when we decrease) int areaS = calcAreaS(mgSplitContainer, clientArea, controls, splitters, checkPlacement, checkMinimumSize, false); // get the total minimum size by checking the placement & minimum size(only when we decrease) int totalMinimumSize = getTotalSizeOfControls(controls, mgSplitContainer.getOrientation(), true, calcByMinSize, checkPlacement, checkMinimumSize); // flag to set if we ignore the minimum size: Minimum size is ignored when // 1. increasing the size // or // 2. reducing the size and the total minimum size is greater than the dynamic client area // and when we not on outmost MgSplitContainer bool ignoreMinSize = false; if (!GuiUtils.isOutmostMgSplitContainer(mgSplitContainer) && !GuiUtils.isDirectChildOfOutmostMgSplitContainer(mgSplitContainer)) { ignoreMinSize = true; } checkPlacement = false; checkMinimumSize = false; calcByMinSize = false; if (areaS > 0) { if (!parentReduced) { output(mgSplitContainer.getOrientation(), "Area ", "1"); // Check the placement property and ignore the minimum size ignoreMinSize = true; checkPlacement = true; checkMinimumSize = false; } else if (areaS < totalMinimumSize) // parentReduced is true { output(mgSplitContainer.getOrientation(), "Area ", "2"); // when reduce and the dynamic client area is > total minimum size we need to ignore also the // placement and the minimum size, all the controls will be in the resize ignoreMinSize = true; checkPlacement = false; checkMinimumSize = false; } else { output(mgSplitContainer.getOrientation(), "Area ", "3"); // when parentReduced && areaS > totalMinimumSize, check the placement and minimum size checkPlacement = true; checkMinimumSize = true; } } // If the dynamic client area is little than or equal to zero then // if (areaS <= 0) else { output(mgSplitContainer.getOrientation(), "Area ", "<0"); output(mgSplitContainer.getOrientation(), "areaS < totalMinimumSize? ", " " + (areaS < totalMinimumSize)); // when we on outmost MgSplitContainer :use the minimum sizes as the weights. if (GuiUtils.isOutmostMgSplitContainer(mgSplitContainer)) { Debug.Assert(false); // output(mgSplitContainer.getOrientation(), "calByMinSize ", " " + calcByMinSize); // checkPlacement = false; // checkMinimumSize = false; // calcByMinSize = true; } // when we not in outmost MgSplitContainer :save the size in the org size and cal with ignore all the // placemetn & min size // if (!GuiUtils.isOutmostMgSplitContainer(mgSplitContainer)) else { output(mgSplitContainer.getOrientation(), "calByMinSize ", " " + calcByMinSize); checkPlacement = false; checkMinimumSize = false; calcByMinSize = false; } } // get the dynamic client area according to the init members areaS = calcAreaS(mgSplitContainer, clientArea, controls, splitters, checkPlacement, checkMinimumSize, calcByMinSize); // get the total size according to the init members totalOrgSize = getTotalSizeOfControls(controls, mgSplitContainer.getOrientation(), true, calcByMinSize, checkPlacement, checkMinimumSize); // get the ratios according to the init members ratios = calcRatios(controls, mgSplitContainer.getOrientation(), totalOrgSize, checkPlacement, checkMinimumSize, calcByMinSize, areaS, ref saveSizeAtTheEnd); output(mgSplitContainer.getOrientation(), "areaS ", " " + areaS); // 6. order the controls and splitters //TODOR: border is all the time 0 // int splitterWidth = splitters.Length > 0 ? MgSplitContainer.SPLITTER_WIDTH + splitters[0].getBorderWidth() * 2 : MgSplitContainer.SPLITTER_WIDTH; int splitterWidth = MgSplitContainer.SPLITTER_WIDTH; if (mgSplitContainer.getOrientation() == MgSplitContainer.SPLITTER_STYLE_HORIZONTAL) { int width = ratios[0] != -1 ? (int)(areaS * ratios[0]) : getOrgSize(controls[0]).X; if (!ignoreMinSize) { width = Math.Max(width, getMinimunSize(controls[0]).X); } int x = clientArea.X; // fixed bug #:293109, while the user is do resize we need to save te bound GuiUtils.controlSetBounds(controls[0], x, clientArea.Y, (int)width, clientArea.Height); SetNewSaveBound(controls[0], x, clientArea.Y, (int)width, clientArea.Height); x += width; if (controls.Length > 1) { ((TagData)splitters[splitters.Length - 1].Tag).RepaintRect = splitters[splitters.Length - 1].Bounds; GuiUtils.controlSetBounds(splitters[splitters.Length - 1], x, clientArea.Y, splitterWidth, clientArea.Height); x += splitterWidth; width = clientArea.Width - (x - clientArea.X); if (!ignoreMinSize) { width = Math.Max(width, getMinimunSize(controls[controls.Length - 1]).X); } GuiUtils.controlSetBounds(controls[controls.Length - 1], x, clientArea.Y, width, clientArea.Height); SetNewSaveBound(controls[controls.Length - 1], x, clientArea.Y, width, clientArea.Height); } } else if (mgSplitContainer.getOrientation() == MgSplitContainer.SPLITTER_STYLE_VERTICAL) { int height = ratios[0] != -1 ? (int)(areaS * ratios[0]) : getOrgSize(controls[0]).Y; if (!ignoreMinSize) { height = Math.Max(height, getMinimunSize(controls[0]).Y); } int y = clientArea.Y; GuiUtils.controlSetBounds(controls[0], clientArea.X, clientArea.Y, clientArea.Width, height); SetNewSaveBound(controls[0], clientArea.X, clientArea.Y, clientArea.Width, height); y += height; if (controls.Length > 1) { ((TagData)splitters[splitters.Length - 1].Tag).RepaintRect = splitters[splitters.Length - 1].Bounds; GuiUtils.controlSetBounds(splitters[splitters.Length - 1], clientArea.X, y, clientArea.Width, splitterWidth); SetNewSaveBound(splitters[splitters.Length - 1], clientArea.X, y, clientArea.Width, splitterWidth); y += splitterWidth; height = clientArea.Height - (y - clientArea.Y); if (!ignoreMinSize) { height = Math.Max(height, getMinimunSize(controls[controls.Length - 1]).Y); } GuiUtils.controlSetBounds(controls[controls.Length - 1], clientArea.X, y, clientArea.Width, height); SetNewSaveBound(controls[controls.Length - 1], clientArea.X, y, clientArea.Width, height); } } if (saveSizeAtTheEnd) { for (int k = 0; k < controls.Length; k++) { Rectangle rect = controls[k].Bounds; setOrgSizeBy(controls[k], rect.Width, rect.Height); } } return(true); }