Version: HEAD (using KDE KDE 3.5.1) OS: Linux STEPS TO REPRODUCE: Start Kst Create an ellipse object Switch to layout mode Select the ellipse object Click on the right centre drag-box Move it slightly to the left or right while dragging Release the mouse button RESULTS: The ellipse outline has no height and when the mouse is released the newly sized ellipse similarly has no height EXPECTED RESULTS: The ellipse outline and newly sized ellipse retain the existing height NOTE: Analogous problems occur for any of the centre drag-boxes
Duncan, could you check this fix in to the 1.5 branch before the 1.4 release so we can backport if necessary.
SVN commit 659768 by dhanson: CCBUG:143804 most straightforward solution-- non-centered resizing of ellipses when edges are dragged. M +5 -12 kstviewellipse.cpp --- branches/work/kst/1.5/kst/src/libkstapp/kstviewellipse.cpp #659767:659768 @@ -95,22 +95,15 @@ } } - const QRect g(geometry()); - int bw(_borderWidth * p.lineWidthAdjustmentFactor()); - if (bw > g.width()/2) { - bw = g.width()/2; - } - if (bw > g.height()/2) { - bw = g.height()/2; - } + const int bw(_borderWidth * p.lineWidthAdjustmentFactor()); QPen pen(bw > 0 ? _borderColor : _foregroundColor, bw); p.setPen(pen); if (_transparentFill) { - p.setBrush(Qt::NoBrush); + p.setBrush(Qt::NoBrush); } else { p.setBrush(_foregroundColor); } - + const QRect g(geometry()); p.drawEllipse(g.x() + bw/2, g.y() + bw/2, g.width() - bw, g.height() - bw); p.restore(); } @@ -185,8 +178,8 @@ signed int KstViewEllipse::directionFor(const QPoint& pos) { signed int direction = KstViewObject::directionFor(pos); - if (direction != 0) { - // not moving, so in any resize direction, we want it centred + if (!(((direction & (UP|DOWN)) == 0) || ((direction & (LEFT|RIGHT)) == 0))) { + // not an edge. direction |= CENTEREDRESIZE; } return direction;
There is one remaining problems with this fix: resizing from a corner leaves the center fixed, resizing from an edge does not. This behaviour should be made consistent to avoid confusing the user.
We could do that... my own thought is that it would be nicest to just have ellipses resize in the same way as rectangles (boxes?) We could have ellipses `resize from center' when you drag their edges, but I think that will give you exactly the same functionality as resizing from a corner. I can't see anyone getting confused by the way that things are now. For both drag types, there are separate visual cues to tip you off to what is happening. So-- I don't think that anything should be done. Duncan. On 30 Apr 2007 23:26:52 -0000, Andrew Walker <arwalker@sumusltd.com> wrote: [bugs.kde.org quoted mail]
The existing functionality shouldn't be changed because of a bug report without at least some discussion first. 'Resize from center' for an ellipse from the edges (the pre-existing functionality if there had been no bug) would behave differently than from the corners as the former would change only the width or height, while the latter would change both width and height.
SVN commit 660202 by arwalker: BUG:143804 fix problem with resizing of ellipses while maintaining intended functionality M +72 -32 kstgfxmousehandlerutils.cpp M +2 -0 kstgfxmousehandlerutils.h M +23 -4 ksttoplevelview.cpp M +1 -1 ksttoplevelview.h M +2 -2 kstviewellipse.cpp --- branches/work/kst/1.5/kst/src/libkstapp/kstgfxmousehandlerutils.cpp #660201:660202 @@ -92,12 +92,12 @@ newHalfHeight = kMin(newHalfHeight,bounds.bottom() - anchorPoint.y()); QSize newSize(originalRect.size()); - newSize.scale(2*newHalfWidth,2*newHalfHeight,QSize::ScaleMin); + newSize.scale(2*newHalfWidth, 2*newHalfHeight, QSize::ScaleMin); newRect.setSize(newSize); newRect.moveCenter(anchorPoint); } else { - newRect = QRect(0,0,2*newHalfWidth,2*newHalfHeight); + newRect = QRect(0, 0, 2*newHalfWidth, 2*newHalfHeight); newRect.moveCenter(anchorPoint); newRect = newRect.intersect(bounds); } @@ -110,51 +110,91 @@ QRect newSize(originalSize); if (movePoint.y() == anchorPoint.y()) { - int newWidth = pos.x() - anchorPoint.x(); //defined differently than in QRect. + int newWidth = pos.x() - anchorPoint.x(); //defined differently than in QRect. - if (maintainAspect) { - double newHalfHeight = originalSize.height() * (abs(newWidth) + 1) / originalSize.width() / 2.0; //defined with the QRect convention (height = bot - top + 1) + if (maintainAspect) { + double newHalfHeight = originalSize.height() * (abs(newWidth) + 1) / originalSize.width() / 2.0; //defined with the QRect convention (height = bot - top + 1) - newHalfHeight = kMin(double(movePoint.y() - bounds.top()) + 1, newHalfHeight); // ensure we are still within the bounds. - newHalfHeight = kMin(double(bounds.bottom() - movePoint.y()) + 1, newHalfHeight); + newHalfHeight = kMin(double(movePoint.y() - bounds.top()) + 1, newHalfHeight); // ensure we are still within the bounds. + newHalfHeight = kMin(double(bounds.bottom() - movePoint.y()) + 1, newHalfHeight); - if (newWidth == 0) { // anything better to be done? - newWidth = 1; - } + if (newWidth == 0) { // anything better to be done? + newWidth = 1; + } - newWidth = (int(originalSize.width() * (newHalfHeight * 2.0) / originalSize.height()) - 1)*newWidth/abs(newWidth); // consistency of width w/ the newly calculated height. + newWidth = (int(originalSize.width() * (newHalfHeight * 2.0) / originalSize.height()) - 1)*newWidth/abs(newWidth); // consistency of width w/ the newly calculated height. - newSize.setTop(anchorPoint.y() + int(newHalfHeight - 0.5)); - newSize.setBottom(anchorPoint.y() - int(newHalfHeight - 0.5)); + newSize.setTop(anchorPoint.y() + int(newHalfHeight - 0.5)); + newSize.setBottom(anchorPoint.y() - int(newHalfHeight - 0.5)); + } + + newSize.setLeft(anchorPoint.x()); + newSize.setRight(anchorPoint.x() + newWidth); // +1 for the way widths are defined in QRect. + } else if (movePoint.x() == anchorPoint.x()) { + // mimic the case for (movePoint.y() == anchorPoint.y()). comments are there. + int newHeight = pos.y() - anchorPoint.y(); + + if (maintainAspect) { + double newHalfWidth = originalSize.width() * (abs(newHeight) + 1) / originalSize.height() / 2.0; + + newHalfWidth = kMin(double(movePoint.x() - bounds.left() + 1), newHalfWidth); + newHalfWidth = kMin(double(bounds.right() - movePoint.x() + 1), newHalfWidth); + + if (newHeight == 0) { + newHeight = 1; } - newSize.setLeft(anchorPoint.x()); - newSize.setRight(anchorPoint.x() + newWidth); // +1 for the way widths are defined in QRect. + newHeight = (int(originalSize.height() * newHalfWidth * 2.0 / originalSize.width()) - 1)*newHeight/abs(newHeight); + newSize.setLeft(anchorPoint.x() + int(newHalfWidth - 0.5)); + newSize.setRight(anchorPoint.x() - int(newHalfWidth - 0.5)); + } - } else if (movePoint.x() == anchorPoint.x()) { - // mimic the case for (movePoint.y() == anchorPoint.y()). comments are there. - int newHeight = pos.y() - anchorPoint.y(); + newSize.setTop(anchorPoint.y()); + newSize.setBottom(anchorPoint.y() + newHeight); + } - if (maintainAspect) { - double newHalfWidth = originalSize.width() * (abs(newHeight) + 1) / originalSize.height() / 2.0; + return newSize.normalize(); +} - newHalfWidth = kMin(double(movePoint.x() - bounds.left() + 1), newHalfWidth); - newHalfWidth = kMin(double(bounds.right() - movePoint.x() + 1), newHalfWidth); - if (newHeight == 0) { - newHeight = 1; - } +QRect KstGfxMouseHandlerUtils::resizeRectFromEdgeCentered(const QRect& originalRect, const QPoint& anchorPoint, const QPoint& movePoint, const QPoint& pos, const QRect& bounds, bool maintainAspect) { + QRect newRect; + bool vertical; + int newHalfWidth = abs((pos - anchorPoint).x()); + int newHalfHeight = abs((pos - anchorPoint).y()); - newHeight = (int(originalSize.height() * newHalfWidth * 2.0 / originalSize.width()) - 1)*newHeight/abs(newHeight); - newSize.setLeft(anchorPoint.x() + int(newHalfWidth - .5)); - newSize.setRight(anchorPoint.x() - int(newHalfWidth - .5)); - } + if (movePoint.x() == anchorPoint.x()) { + vertical = true; + } else { + vertical = false; + } - newSize.setTop(anchorPoint.y()); - newSize.setBottom(anchorPoint.y() + newHeight); + if (maintainAspect) { + QSize newSize(originalRect.size()); + + if (vertical) { + newHalfHeight = kMin(newHalfHeight, anchorPoint.y() - bounds.top()); + newHalfHeight = kMin(newHalfHeight, bounds.bottom() - anchorPoint.y()); + newSize.scale(originalRect.width(), 2*newHalfHeight, QSize::ScaleMin); + } else { + newHalfWidth = kMin(newHalfWidth, anchorPoint.x() - bounds.left()); + newHalfWidth = kMin(newHalfWidth, bounds.right() - anchorPoint.x()); + newSize.scale(2*newHalfWidth, originalRect.height(), QSize::ScaleMin); } - return newSize.normalize(); + newRect.setSize(newSize); + newRect.moveCenter(anchorPoint); + } else { + if (vertical) { + newRect = QRect(0, 0, originalRect.width(), 2*newHalfHeight); + } else { + newRect = QRect(0, 0, 2*newHalfWidth, originalRect.height()); + } + newRect.moveCenter(anchorPoint); + newRect = newRect.intersect(bounds); + } + + return newRect; } --- branches/work/kst/1.5/kst/src/libkstapp/kstgfxmousehandlerutils.h #660201:660202 @@ -30,6 +30,8 @@ QRect resizeRectFromCornerCentered(const QRect& originalRect, const QPoint& pos, const QRect& bounds, bool maintainAspect); // resizes a rect from an edge, keeping anchorPoint fixed. movePoint = center of edge being dragged. anchorPoint = center of opposite edge. anchorPoint and movePoint must be inside bounds already. QRect resizeRectFromEdge(const QRect& originalSize, const QPoint& anchorPoint, const QPoint& movePoint, const QPoint& pos, const QRect &bounds, bool maintainAspect); + // resizes a rect from an edge, keeping anchorPoint fixed. movePoint = center of edge being dragged. anchorPoint = center of opposite edge. anchorPoint and movePoint must be inside bounds already. + QRect resizeRectFromEdgeCentered(const QRect& originalRect, const QPoint& anchorPoint, const QPoint& movePoint, const QPoint& pos, const QRect& bounds, bool maintainAspect); // returns a new rectangle. mouseOrigin must be inside bounds already. QRect newRect(const QPoint& pos, const QPoint& mouseOrigin, const QRect& bounds, bool squareAspect); // returns a new rectangle, mouseOrigin must be inside bounds already. --- branches/work/kst/1.5/kst/src/libkstapp/ksttoplevelview.cpp #660201:660202 @@ -433,13 +433,14 @@ if ( ((direction & (UP|DOWN)) == 0) || ((direction & (LEFT|RIGHT)) == 0) ) { //resizing from edge. return KstGfxMouseHandlerUtils::resizeRectFromEdge(originalSize, anchor_pt, move_pt, npos, bounds, maintainAspect); } else { //resizing from corner. - return KstGfxMouseHandlerUtils::resizeRectFromCorner(anchor_pt, move_pt, npos, bounds,maintainAspect); + return KstGfxMouseHandlerUtils::resizeRectFromCorner(anchor_pt, move_pt, npos, bounds, maintainAspect); } } -QRect KstTopLevelView::newSizeCentered(const QRect& oldSize, const QRect& bounds, const QPoint& pos, bool maintainAspect) { +QRect KstTopLevelView::newSizeCentered(const QRect& originalSize, const QRect& bounds, int direction, const QPoint& pos, bool maintainAspect) { + QPoint anchor_pt, move_pt; QPoint npos = pos; npos.setX(kMax(npos.x(), bounds.left())); @@ -447,7 +448,25 @@ npos.setY(kMin(npos.y(), bounds.bottom())); npos.setY(kMax(npos.y(), bounds.top())); - return KstGfxMouseHandlerUtils::resizeRectFromCornerCentered(oldSize, npos, bounds, maintainAspect); + anchor_pt = move_pt = originalSize.center(); + + if ((direction & UP) != 0) { + move_pt.setY(originalSize.top()); + } else if ((direction & DOWN) != 0) { + move_pt.setY(originalSize.bottom()); + } + + if ((direction & LEFT) != 0) { + move_pt.setX(originalSize.left()); + } else if ((direction & RIGHT) != 0) { + move_pt.setX(originalSize.right()); + } + + if ( ((direction & (UP|DOWN)) == 0) || ((direction & (LEFT|RIGHT)) == 0) ) { //resizing from edge. + return KstGfxMouseHandlerUtils::resizeRectFromEdgeCentered(originalSize, anchor_pt, move_pt, npos, bounds, maintainAspect); + } else { //resizing from corner. + return KstGfxMouseHandlerUtils::resizeRectFromCornerCentered(originalSize, npos, bounds, maintainAspect); + } } @@ -836,7 +855,7 @@ //centered resize means that the center of the object stays constant const QRect old(_prevBand); - _prevBand = newSizeCentered(_pressTarget->geometry(), _pressTarget->_parent->geometry(), pos, maintainAspect); + _prevBand = newSizeCentered(_pressTarget->geometry(), _pressTarget->_parent->geometry(), _pressDirection, pos, maintainAspect); if (_prevBand != old) { KstPainter p; --- branches/work/kst/1.5/kst/src/libkstapp/ksttoplevelview.h #660201:660202 @@ -126,7 +126,7 @@ bool popupMenu(KPopupMenu *menu, const QPoint& pos); void correctPosition(KstViewObjectPtr pObject, QPoint point); QRect newSize(const QRect& originalSize, const QRect& bounds, int direction, const QPoint& pos, bool maintainAspect = false); - QRect newSizeCentered(const QRect& oldSize, const QRect& bounds, const QPoint& pos, bool maintainAspect); + QRect newSizeCentered(const QRect& oldSize, const QRect& bounds, int direction, const QPoint& pos, bool maintainAspect); QRect correctWidthForRatio(const QRect& oldRect, double ratio, int direction); QRect correctHeightForRatio(const QRect& oldRect, double ratio, int direction, int origRight, int origLeft); void moveSnapToBorders(int *xMin, int *yMin, const KstViewObjectPtr &obj, const QRect &r) const; --- branches/work/kst/1.5/kst/src/libkstapp/kstviewellipse.cpp #660201:660202 @@ -185,8 +185,8 @@ signed int KstViewEllipse::directionFor(const QPoint& pos) { signed int direction = KstViewObject::directionFor(pos); - if (!(((direction & (UP|DOWN)) == 0) || ((direction & (LEFT|RIGHT)) == 0))) { - // not an edge + + if (direction != 0) { direction |= CENTEREDRESIZE; } return direction;