Position X/Y of a symbol text is the point chosen by its alignment

The text properties showed and edited the top-left corner of a text,
whatever its alignment, and changing the alignment did not move the
text. A right-aligned label next to a symbol therefore needed a
different X for every text length to keep the same gap (#1155).

Position X/Y is now the anchor point: the point of the text chosen by
the alignment (right edge for "right", middle for "centre"...). Typing a
position puts that point there, and changing the alignment moves the
text so that the new anchor point is on the same X/Y. It is the same
point that already stays fixed when the text changes.

Applies to the element text properties on a folio and to the text
field properties in the symbol editor. The saved x/y is still the
top-left corner, so projects and symbols load and save unchanged and
look the same; only the numbers shown for texts that are not top-left
aligned change.

The geometry is in textanchor.h, shared by DiagramTextItem and
PartDynamicTextField, and tested in tst_textanchor.

Not changed: static texts of the symbol editor (PartText), whose
position is tied to the font baseline; texts inside a text group, which
have no position or alignment of their own; rotation still pivots on
the top-left corner (or the centre), not on the anchor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-09-30 18:12:43 +13:00
parent 784a663c19
commit bdc1d5878d
9 changed files with 334 additions and 12 deletions
@@ -19,6 +19,7 @@
#include "../../QPropertyUndoCommand/qpropertyundocommand.h"
#include "../../qetapp.h"
#include "../../textanchor.h"
#include "../elementscene.h"
#include "../../utils/qetutils.h"
#include <QApplication>
@@ -474,6 +475,41 @@ Qt::Alignment PartDynamicTextField::alignment() const
return m_alignment;
}
/**
@brief PartDynamicTextField::anchorPos
@return the anchor point of this text, in parent coordinates:
the point of the text chosen by the alignment (top-left, right edge,
centre...). For a top-left aligned text this is pos().
Same as DiagramTextItem::anchorPos().
*/
QPointF PartDynamicTextField::anchorPos() const
{
return TextAnchor::pos(this, m_alignment);
}
/**
@brief PartDynamicTextField::setAnchorPos
Move this text so that its anchor point (see anchorPos()) is at anchor.
@param anchor : in parent coordinates
*/
void PartDynamicTextField::setAnchorPos(const QPointF &anchor)
{
setPos(TextAnchor::itemPosFor(this, m_alignment, anchor));
}
/**
@brief PartDynamicTextField::setAlignmentAtAnchor
Change the alignment and move the text so that its new anchor point
is where the previous one was.
@param alignment
*/
void PartDynamicTextField::setAlignmentAtAnchor(Qt::Alignment alignment)
{
const QPointF anchor = anchorPos();
setAlignment(alignment);
setAnchorPos(anchor);
}
void PartDynamicTextField::setFont(const QFont &font) {
if (font == this -> font()) {
return;