/// <summary> /// update the movement value according the dimension placement value. /// copies from ctrl.cpp updateMoveValue /// </summary> /// <param name="placementData"></param> /// <param name="actualMove"></param> /// <param name="placementDim"></param> /// <returns></returns> static int updateMoveValue(PlacementData placementData, int actualMove, PlacementDim placementDim, int prevAxeMove, bool containerRightToLeft) { float remainder; float result; int move; int place = placementData.getPlacement(placementDim, containerRightToLeft); float accMove = placementData.getAccCtrlMove(placementDim); if (place > 0 && place < 100) { result = (float)(actualMove * place) / 100; move = (int)((actualMove * place) / 100); remainder = result - move; accMove += remainder; if (accMove >= 1 || accMove <= -1) { move += (int)accMove; if (move > 0) { accMove -= 1; } else { accMove += 1; } } } else if (place == 0) // no placement { move = 0; } else { move = actualMove; // placement is 100% } placementData.setAccCtrlMove(placementDim, accMove); return(move); }
/// <summary> limit placement check if one of the ctrl's caused the scrollbar to be shown or removed, if so limit the /// movement. dx & dy are the actual window movement. Will return the allowed movement before scrollbars. /// this code is based on GUI::LimitPlacement method in gui.cpp /// </summary> /// <param name="composite"></param> /// <param name="dx">delta X</param> /// <param name="dy">delta Y</param> /// <param name="newContainerRect">new Recatngle of container</param> /// <returns> new dx,dy</returns> private Point limitPlacement(Control containerControl, int dx, int dy, Rectangle newContainerRect) { int totalPlaceX, totalPlaceY; int fromPrevToCtrlX, fromPrevToCtrlY; int bottom; Rectangle place = new Rectangle(0, 0, 0, 0); ArrayList controlsList; bool containerRightToLeft = isRTL(containerControl); bool canHaveScrollbar = (containerControl is ScrollableControl && ((ScrollableControl)containerControl).AutoScroll); if (!canHaveScrollbar) //QCR #982071, if control does not support scrollbars - tab, group - we should not limit placement { return(new Point(dx, dy)); } if (CanLimitPlacement(containerControl) && (dx < 0 || dy < 0)) { controlsList = GetControlsList(containerControl); foreach (Object obj in controlsList) { #if PocketPC if (containerControl is Panel && obj == ((Panel)containerControl).dummy) { continue; } #endif //ignore editors, they will be handled by logical controls Control control = obj as Control; if (!ShouldLimitPlacement(control)) //it will be handled by its logicalcontrol { continue; } Rectangle rect = Bounds(obj); PlacementData placementData = PlacementData(obj); if (placementData != null) { place = placementData.Placement; } else { place = new Rectangle(0, 0, 0, 0); } if (containerRightToLeft) { totalPlaceX = (100 - place.X) + place.Width; } else { totalPlaceX = place.X + place.Width; } totalPlaceY = place.Y + place.Height; if (obj is TableControl) { GetTableTotalPlaceX((TableControl)obj, place, dx, ref totalPlaceX); } int childRight = rect.X + rect.Width; int childBottom = rect.Y + rect.Height; fromPrevToCtrlX = _prevRect.Width - childRight; fromPrevToCtrlY = _prevRect.Height - childBottom; int right = 0; // Checks which of the controls will be the closest one to the right border of the form if (dx < 0 && totalPlaceX < 100 && fromPrevToCtrlX >= 0 && newContainerRect.Width < childRight) { right = -((fromPrevToCtrlX * 100) / (100 - totalPlaceX)); dx = Math.Max(dx, right); } if (containerRightToLeft && dx < 0) //QCR #974011, 805098 { long totalPlaceXLeft = (100 - place.X) - place.Width; long left = rect.X + (dx * totalPlaceXLeft / 100); //new left coordinate of control if (left < right /* not hidden*/ && left < 0) { dx = Math.Max(-rect.Left, dx); } } // Checks which of the controls will be the closest one to the bottom border of the form if (dy < 0 && totalPlaceY < 100 && fromPrevToCtrlY >= 0 && newContainerRect.Height < childBottom) { bottom = -((fromPrevToCtrlY * 100) / (100 - totalPlaceY)); dy = Math.Max(dy, bottom); } } } if (dx > 0) { // if there was a horizontal scrollbar and after the current resizing it might won't be if (_prevRect.Width < _prevLogicalSize.X && newContainerRect.Width >= _prevLogicalSize.X) { dx = newContainerRect.Width - _prevLogicalSize.X; } } if (dy > 0) { // if there was a vertical scrollbar and after the current resizing it might won't be if (_prevRect.Height < _prevLogicalSize.Y && newContainerRect.Height >= _prevLogicalSize.Y) { dy = newContainerRect.Height - _prevLogicalSize.Y; } } return(new Point(dx, dy)); }
/// <summary> /// Fix Rounding mistakes caused by placement calculations /// </summary> /// <param name="originPlacement"> placement of the origine (x or y placement) </param> /// <param name="lengthPlacement"> widht or height placement (dx or dy placement)</param> /// <param name="totalChange"> total change for control</param> /// <param name="axe"> X or Y axe</param> /// <param name="placementData"> placement data</param> /// <param name="containerRightToLeft">RightToLeft</param> /// <returns></returns> static int fixRounding(int originPlacement, int lengthPlacement, int totalChange, Axe axe, PlacementData placementData, bool containerRightToLeft) { PlacementDim originPlacementDim = axe == Axe.X ? PlacementDim.PLACE_X : PlacementDim.PLACE_Y; PlacementDim lengthPlacementDim = axe == Axe.X ? PlacementDim.PLACE_DX : PlacementDim.PLACE_DY; if (placementData.getPlacement(originPlacementDim, containerRightToLeft) + placementData.getPlacement(lengthPlacementDim, containerRightToLeft) == 100) { //total placement is 100% this means that originPlacement + lengthPlacement MUST BE EQUAL to totalChange //there are may be some mistakes caused by rounding of float numbers to integer, we must fix them //If these small mistakes are not fix - scroll bar might be created when it is not needed if (Math.Abs(originPlacement + lengthPlacement) != Math.Abs(totalChange)) { int diff = totalChange - (originPlacement + lengthPlacement); float accMove = placementData.getAccCtrlMove(lengthPlacementDim); //recalculate length placement lengthPlacement += diff; //update AccCtrlMove for future placement placementData.setAccCtrlMove(lengthPlacementDim, accMove + diff); } } return(lengthPlacement); }
/// <summary> /// controls placement /// </summary> /// <param name="control"></param> /// <param name="actualPlacement"></param> public void ControlPlacement(Object obj, Point actualPlacement) { if (obj is Control) { Control control = (Control)obj; if (!ShouldApplyPlacement(control)) { return; } int dx, dy; Rectangle rect = Bounds(control); #if !PocketPC //tmp bool containerRightToLeft = control.Parent.RightToLeft == RightToLeft.Yes; #else bool containerRightToLeft = false; #endif PlacementData placementData = PlacementData(control); if (placementData == null) { return; } // process placement for all children int xChange = updateMoveValue(placementData, actualPlacement.X, PlacementDim.PLACE_X, 0, containerRightToLeft); rect.X += xChange; int yChange = updateMoveValue(placementData, actualPlacement.Y, PlacementDim.PLACE_Y, 0, containerRightToLeft); rect.Y += yChange; // compute width and height placement // compute width and height placement dx = updateMoveValue(placementData, actualPlacement.X, PlacementDim.PLACE_DX, xChange, containerRightToLeft); dy = updateMoveValue(placementData, actualPlacement.Y, PlacementDim.PLACE_DY, yChange, containerRightToLeft); //QCR #288201, due to calculation problems caused by rounding float to int sometimes scrollbar is shown //This is fix for the case when total placement is 100 % dx = fixRounding(xChange, dx, actualPlacement.X, Axe.X, placementData, containerRightToLeft); dy = fixRounding(yChange, dy, actualPlacement.Y, Axe.Y, placementData, containerRightToLeft); if (control is TableControl) { ExecuteTableControlPlacement((TableControl)control, dx, dy, rect); } else { //QCR #933614, negative width and height turned to 0 in setBounds, //so we must save then on the control's data Rectangle?savedRect = GetSavedBounds(control); if (savedRect != null) { rect.Width = ((Rectangle)savedRect).Width; rect.Height = ((Rectangle)savedRect).Height; } rect.Width += dx; if (containerRightToLeft) { rect.X -= dx; } rect.Height += dy; SetBounds(control, rect); } } else if (obj is PlacementDrivenLogicalControl) { ReCalculateAndRefresh(obj); } }