diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.cpp b/sources/qetgraphicsitem/dynamicelementtextitem.cpp index 0a04a63b9..78db79049 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.cpp +++ b/sources/qetgraphicsitem/dynamicelementtextitem.cpp @@ -1054,9 +1054,26 @@ void DynamicElementTextItem::handlerMousePressEvent(QetGraphicsHandlerItem *hand //drawing program: remember it in the parent's coordinates, which //take the text's rotation into account m_resize_start_pos = pos(); + m_resize_fixed_parent = mapToParent(resizeAnchor(handle == m_left_resize_handle)); +} + +/** + @brief DynamicElementTextItem::resizeAnchor + @param left_handle : the left width handle is dragged + @return the point of the text, in its own coordinates, that a drag on + a width handle keeps in place: on the opposite edge, and at the top, + the middle or the bottom as the text is aligned. A text that wraps onto + more lines while it narrows then grows away from that point, down for + a text aligned at the top, instead of moving into its neighbours. +*/ +QPointF DynamicElementTextItem::resizeAnchor(bool left_handle) const +{ const QRectF br = boundingRect(); - m_resize_fixed_parent = mapToParent(QPointF(handle == m_left_resize_handle ? br.right() : br.left(), - br.center().y())); + const Qt::Alignment v = alignment() & Qt::AlignVertical_Mask; + const qreal y = (v & Qt::AlignBottom) ? br.bottom() + : (v & Qt::AlignVCenter) ? br.center().y() + : br.top(); + return QPointF(left_handle ? br.right() : br.left(), y); } /** @@ -1079,13 +1096,10 @@ void DynamicElementTextItem::handlerMouseMoveEvent(QetGraphicsHandlerItem *handl qreal new_width = qMax(m_resize_baseline_width + delta, qreal(10)); setTextWidth(new_width); - //The text grows and shrinks on its right side: dragging the left - //handle moves the text so that its right edge stays in place - if (handle == m_left_resize_handle) - { - const QRectF br = boundingRect(); - setPos(pos() + m_resize_fixed_parent - mapToParent(QPointF(br.right(), br.center().y()))); - } + //Keep the opposite edge in place, and the top, middle or bottom + //as the text is aligned, whatever the new number of lines + setPos(pos() + m_resize_fixed_parent + - mapToParent(resizeAnchor(handle == m_left_resize_handle))); updateResizeHandlesPos(); } diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.h b/sources/qetgraphicsitem/dynamicelementtextitem.h index 4fc22b5a8..3077282c7 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.h +++ b/sources/qetgraphicsitem/dynamicelementtextitem.h @@ -170,6 +170,7 @@ class DynamicElementTextItem : public DiagramTextItem void addResizeHandles(); void removeResizeHandles(); void updateResizeHandlesPos(); + QPointF resizeAnchor(bool left_handle) const; void fitAutoTextWidth(); void handlerMousePressEvent(QetGraphicsHandlerItem *handle, QGraphicsSceneMouseEvent *event); void handlerMouseMoveEvent(QetGraphicsHandlerItem *handle, QGraphicsSceneMouseEvent *event); diff --git a/tests/qttest/element_text_resize_probe.cpp b/tests/qttest/element_text_resize_probe.cpp index 199c66e8f..ee7d02896 100644 --- a/tests/qttest/element_text_resize_probe.cpp +++ b/tests/qttest/element_text_resize_probe.cpp @@ -5,7 +5,8 @@ // its right edge in place; dragging the right handle keeps its left edge, // as in a drawing program. Before, the text always kept its left edge, so // a drag on the left handle moved the right edge and the text jumped. -// Undo puts back the width and the position together. Checked for an +// Undo puts back the width and the position together. A text narrowed +// until it wraps grows downwards from its top corner. Checked for an // upright and a rotated text. #include #include @@ -56,10 +57,11 @@ static QetGraphicsHandlerItem *handle(DynamicElementTextItem *text, bool left) return found; } +/// The top corner of the text on the left or right, in the folio. static QPointF edge(DynamicElementTextItem *text, bool left) { const QRectF br = text->boundingRect(); - return text->mapToScene(QPointF(left ? br.left() : br.right(), br.center().y())); + return text->mapToScene(QPointF(left ? br.left() : br.right(), br.top())); } /// Drag one handle by dx along the text's own baseline. @@ -101,6 +103,16 @@ static void checkText(Diagram *scene, Element *element, DynamicElementTextItem * check(near(edge(text, true), left), "dragging the right handle keeps the left edge in place"); scene->undoStack().undo(); check(near(text->pos(), pos), "undo of the right handle leaves the position alone"); + + // Narrowed until it wraps onto more lines with the left handle: the + // text grows downwards from its top right corner, it does not move up + // into what stands above it. + const qreal height = text->boundingRect().height(); + drag(scene, text, true, width - 25); + check(text->boundingRect().height() > height + 5, "narrowing the text wraps it onto more lines"); + check(near(edge(text, false), right), "a text that wraps keeps its top right corner in place"); + scene->undoStack().undo(); + check(near(text->pos(), pos), "undo puts the wrapped text back"); element->setSelected(false); } @@ -130,6 +142,9 @@ int main(int argc, char **argv) for (DynamicElementTextItem *t : e->dynamicTextItems()) if (!text) { text = t; element = e; } check(text, "the fixture has a symbol with a text"); + // Several words, so that narrowing it makes it wrap + text->setTextFrom(DynamicElementTextItem::UserText); + text->setText(QStringLiteral("Sockets bathroom first floor, 5")); checkText(scene, element, text); // The same on a text turned by 90 degrees: the fixed edge is