Centre or right-align the lines of symbol texts with an automatic width (#1348)

A symbol text on a folio with its width on "Auto" kept every line of a
multi-line text on the left, whatever its alignment: a QTextDocument
with no text width has no width to centre or right-align lines in. It
only worked once the user gave the text a width wide enough.

With the width on Auto and a centre or right alignment, give the
document the width of its longest line. The size of the text does not
change, only where the shorter lines sit. The fit is redone when the
text, the alignment, the width or the font changes; on a font change
the text's anchor is kept, as the font change itself does.

textWidth() now returns the width the user set (-1 for Auto), the value
that is saved, rather than the document's, as IndependentTextItem
already does. Readers (properties panel, resize-handle undo, script
API, project database) see -1 for Auto as before.

Checked: every folio of the 25 example projects renders identically to
master (136 PNGs); a centred and a right-aligned two-line text now
render aligned; changing their font size leaves the same box and anchor
as master, and without the font-change refit the lines wrap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-10-07 13:12:22 +13:00
parent 0708338bce
commit 36df4b3010
2 changed files with 34 additions and 0 deletions
@@ -75,6 +75,16 @@ DynamicElementTextItem::DynamicElementTextItem(Element *parent_element) :
QTextOption option = document()->defaultTextOption();
option.setAlignment(alignment & Qt::AlignHorizontal_Mask);
document()->setDefaultTextOption(option);
fitAutoTextWidth();
});
connect(document(), &QTextDocument::contentsChanged, this, &DynamicElementTextItem::fitAutoTextWidth);
//The new font can make the lines wider or narrower than the width
//fitted for the old one: fit again, keeping the text's anchor
connect(this, &DiagramTextItem::fontChanged, this, [this]()
{
prepareAlignment();
fitAutoTextWidth();
finishAlignment();
});
}
@@ -1796,9 +1806,28 @@ void DynamicElementTextItem::setTextWidth(qreal width)
{
this->document()->setTextWidth(width);
m_text_width = width;
fitAutoTextWidth();
emit textWidthChanged(width);
}
/**
@brief DynamicElementTextItem::fitAutoTextWidth
With no width set by the user, a QTextDocument has no width to centre
or right-align its lines in, so every line of a multi-line text stays
on the left whatever the alignment. Give the document the width of its
longest line instead. This does not change the size of the text, only
where the shorter lines sit.
*/
void DynamicElementTextItem::fitAutoTextWidth()
{
if (m_text_width > 0)
return;
document()->setTextWidth(-1);
if (alignment() & (Qt::AlignHCenter | Qt::AlignRight))
document()->setTextWidth(document()->idealWidth());
}
void DynamicElementTextItem::setXref_item(Qt::AlignmentFlag m_exHrefPos, int slave_offset)
{
QRectF r = boundingRect();
@@ -112,6 +112,10 @@ class DynamicElementTextItem : public DiagramTextItem
QUuid uuid() const;
void updateXref();
void setPlainText(const QString &text);
//Hide QGraphicsTextItem::textWidth(): with the width on "auto"
//the document is given the text's own width so its lines can be
//centred or right-aligned, but the width is still "auto" (-1).
qreal textWidth() const {return m_text_width;}
void setTextWidth(qreal width);
void setXref_item(Qt::AlignmentFlag m_exHrefPos, int slave_offset = 0);
@@ -161,6 +165,7 @@ class DynamicElementTextItem : public DiagramTextItem
void addResizeHandles();
void removeResizeHandles();
void updateResizeHandlesPos();
void fitAutoTextWidth();
void handlerMousePressEvent(QetGraphicsHandlerItem *handle, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent(QetGraphicsHandlerItem *handle, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent(QetGraphicsHandlerItem *handle, QGraphicsSceneMouseEvent *event);