Skip to content

feat(editor): wrap text at a dragged width or the canvas edge - #59

Open
jondkinney wants to merge 2 commits into
tobi:mainfrom
jondkinney:feat/text-wrap
Open

feat(editor): wrap text at a dragged width or the canvas edge#59
jondkinney wants to merge 2 commits into
tobi:mainfrom
jondkinney:feat/text-wrap

Conversation

@jondkinney

Copy link
Copy Markdown
Contributor

Stacked on #58. The diff below has that commit in it too; only the second one is this PR. I'll rebase once it lands.

Long text ran straight off the capture and took its handle with it, so you couldn't read it or drag it back.

Text layers carry a textWidth now (0 means automatic). layoutAnnotationText() word-wraps with QTextLayout, and rendering, bounds and the per-line pills follow the wrapped lines; automatic text wraps at the canvas' right edge. The bottom-right handle sets the wrap width, the wheel scales it along with the font, and text that wrapped at the edge freezes that shape on commit, so moving it later never reflows the paragraph you just placed.

Wrapping happens while you type, not just on commit: the inline QLineEdit is only a text/caret/selection model now, and the editor draws the draft through the same paintAnnotation() path as a committed layer, so the draft can't drift from the result. TextLine records each line's range, which maps caret, click and selection onto the wrapped lines.

Two behaviors changed on purpose: committing keeps the text tool armed like every other tool and leaves the layer selected, and a click that commits now does only that, rather than also starting the next text and dropping what you'd just typed.

Worth knowing: the double-click is detected in mousePressEvent, not mouseDoubleClickEvent. Qt only synthesizes MouseButtonDblClick when the platform stamps button events with increasing timestamps, and Hyprland sends zero for every pointer event, so that event never arrives.

I also made two existing checks explicit rather than leave them leaning on which tool a commit happens to arm: the double-click case starts from Select, and the pill-default case steps out to Select before pressing T, since T with a text selected restyles that layer.

runTextWrapRenderingCheck (exit 104) for the layout; runTextWrapSmoke (exit 105) over typing, dragging the wrap width, committing, moving without reflow, and re-editing.

Text rendered bare in the annotation color, so text placed on a shape of
the same color, the common "label this box" move, was unreadable. Every
text layer now carries a `TextBackground` (Pill by default): a cream
rounded rectangle under the glyphs whose bounds also become the layer's
hit target.

The inline editor shows the same pill while typing, and paints its own
caret spanning the glyphs' cap height (530 ms blink, reset on move) with
the QLineEdit transparent and its native caret hidden through a
QProxyStyle.

`T` again flips the default for new text; with a text layer selected it
toggles that layer as an undoable edit.

The dashed selection box follows the pill, since a rounded background
inside a square frame reads as a mistake.

Smoke: a render check that the pill hugs the glyphs, plus an interactive
sequence over the default, the toggle, undo and re-editing.
A text layer carries a `textWidth` (0 = automatic);
`layoutAnnotationText()` word-wraps with QTextLayout, and rendering,
bounds and per-line pills all follow the wrapped lines. Automatic text
wraps at the canvas' right edge rather than running off the capture
where its handle is unreachable. The bottom-right handle sets the wrap
width, the wheel scales it with the font, and text wrapped at the edge
freezes that shape on commit so moving it never reflows.

Wrapping happens while typing, not only on commit: the inline QLineEdit
now just holds text, caret and selection, and the editor draws the draft
through the same `paintAnnotation()` path as a committed layer.
`TextLine` records each line's range so caret, click and selection map
onto the wrapped lines.

Committing keeps the text tool armed, like every other tool, and leaves
the new layer selected so it can be moved or wrapped straight away. A
click that commits does nothing more, so the next click starts the next
text rather than the same one dropping what was typed. With text armed,
clicking a text layer edits it; double-clicking one from any tool
selects, arms and edits it. Double-clicks are detected in
mousePressEvent, because Qt only synthesizes MouseButtonDblClick from
increasing timestamps and Hyprland delivers zero.

An empty editor still just follows the click, since nothing was
committed to position. Two upstream checks were made explicit rather
than relying on which tool a commit leaves armed: the
double-click-detection case now runs from Select, and the pill-default
case steps out to Select before pressing T, because T with a text
selected restyles that layer instead.

Smoke: a layout check, plus an interactive sequence over typing, dragging
the wrap width, committing, moving without reflow and re-editing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant