Skip to content

Complete section editor on WebUI canvas - #858

Open
briemla wants to merge 6 commits into
mainfrom
webui/04-section-editor
Open

briemla wants to merge 6 commits into
mainfrom
webui/04-section-editor

Conversation

@briemla

@briemla briemla commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

OP#10515

Problem

The section editor of the WebUI canvas (canvas_form.py) could do much less than the editor of the customtkinter GUI (line_section.py: SectionBuilder, SectionGeometryEditor, SectionPainter, ArrowPainter):

  • Drawing showed no preview line. It could only be finished with Enter, even with a single point, and new areas were saved without their closing coordinate, which the domain Area rejects.
  • Editing could only drag existing knobs. There was no hover highlight, no inserting, deleting or reordering of knobs, and no right click to save.
  • Areas were drawn as open polylines. Section names (text) and arrow_style were ignored, flows had no arrow head, and disable()/enable() did nothing.
  • Every key press on the page was evaluated, including key up, even when no editor was active. Escape outside an editor called cancel_action().

Solution

Split into commits A (drawing), B (editing) and C (presentation), plus two small follow-ups:

  1. A, drawing (SectionBuilder.update):
    • A preview line follows the mouse from the last point, using mousemove on the interactive image.
    • Right click finishes like Enter. The canvas suppresses the context menu.
    • A section is only finished with at least 2 points for lines and 3 for areas. Otherwise a warning is shown (CanvasKeys.MESSAGE_NOT_ENOUGH_POINTS).
    • Areas are closed before they are saved.
    • Keys are only handled on key down and only while an editor is active.
    • Mouse moves are only subscribed while an editor is active.
  2. B, editing (SectionGeometryEditor.update):
    • The knob under the mouse is highlighted.
    • A knob can be selected and placed by click and click, or dragged and released.
    • + inserts a knob at the mouse position into the closest segment. On a line, a point beyond either end extends the line at that end.
    • Delete/Backspace deletes the selected knob but keeps at least 2 knobs for lines and 3 for areas.
    • Arrow left/right moves the selected knob back or forward in the order of knobs, wrapping around for areas.
    • Enter or right click saves. Escape first drops the knob selection (and undoes an unplaced insert), then cancels.
    • The new hotkeys are in HotKeys of the ResourceManager.
    • The geometry logic is in UI independent functions in section_geometry.py.
  3. C, presentation (SectionPainter/ArrowPainter):
    • Area sections are drawn as closed, semi-transparent polygons (new svg/polygon.py).
    • Section names are drawn as SVG text (new svg/text.py).
    • Flows are drawn as arrows with heads, using the color, width and dash of arrow_style (new svg/arrow.py).
    • disable() makes the canvas ignore input while an action runs. An editor started by that action enables the canvas again, because the viewmodel disables the canvas right before it starts the editor.
  4. Starting an editor takes the focus away from the button that started it. Before, NiceGUI's keyboard ignored the editor hotkeys until the user clicked into the canvas.
  5. Acceptance tests for drawing and editing.

The customtkinter GUI, the ViewModel and the UiFactory are unchanged.

Notes:

  • The ViewModel does not pass text or arrow_style today (in the customtkinter GUI either). The WebUI now draws them when they are passed, but the visible result does not change yet.
  • The planned + affordance on segment midpoints (docs/plans/2026-03-02-insert-intermediate-section-point*.md) is not part of this PR. Inserting uses the + hotkey like the customtkinter GUI.

Tests

  • Unit tests:
    • tests/unit/OTAnalytics/plugin_ui/nicegui_gui/pages/canvas_and_files_form/ (test_canvas_form.py, new test_section_geometry.py)
    • tests/unit/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/ (new test_polygon.py, test_text.py, test_arrow.py)
    • 135 passed
  • Broader run of tests/unit/OTAnalytics/plugin_ui, tests/unit/OTAnalytics/application and tests/unit/OTAnalytics/adapter_ui: 848 passed, 5 skipped.
  • Acceptance tests (Playwright, headless Chromium, run locally), all 3 passing tests in tests/acceptance/test_sections_and_flows.py pass (3 tests there were already skipped):
    • New TestSectionEditorOnCanvas::test_draw_line_section_with_preview_and_right_click
    • New TestSectionEditorOnCanvas::test_insert_and_delete_knob_of_section
    • Existing test_create_sections_two_times
  • pre-commit (flake8, black, isort, mypy) passes on the changed files. pre-commit run --all-files also reports failures that come from the local environment and not from this change (end-of-file in a test data file, update-mypy-dependencies, ShellCheck about a missing .venv). Those hook changes were not committed.

🤖 Generated with Claude Code

briemla and others added 5 commits October 13, 2026 13:46
Show a preview line from the last point to the mouse position, finish
drawing with a right click in addition to Enter and only finish if
enough points have been added (two for lines, three for areas).
Areas are closed before they are saved. Key presses are only evaluated
while an editor is active and only on key down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Highlight the knob under the mouse, select knobs by click or drag, move
and place them. Add hotkeys to insert a knob at the mouse position
between the closest knobs (+), delete the selected knob while keeping
the minimum number of knobs (Delete/Backspace) and shift the selected
knob in the order of knobs (arrow left/right). Enter or a right click
saves, Escape deselects the knob or cancels editing.

The geometry logic lives in UI independent functions in
section_geometry.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Draw area sections closed and semi-transparently filled, show section
names passed as text, draw flows as arrows that respect the given
arrow style and ignore canvas input while an action is running unless
the editor was started by this action.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Key presses are ignored while a button has the focus. Starting an editor
via the section buttons kept the focus on the button, so hotkeys only
worked after clicking into the canvas. Release the focus when an editor
starts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@briemla
briemla requested a review from schubsen October 15, 2026 07:25
@briemla
briemla enabled auto-merge October 15, 2026 07:25

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant