Skip to content

feat: add document layers#1780

Open
awerty-noob wants to merge 5 commits into
flxzt:mainfrom
awerty-noob:feat-layer
Open

feat: add document layers#1780
awerty-noob wants to merge 5 commits into
flxzt:mainfrom
awerty-noob:feat-layer

Conversation

@awerty-noob

@awerty-noob awerty-noob commented May 24, 2026

Copy link
Copy Markdown

Summary

Add document layers (similar to image editors like Photoshop/GIMP) to Rnote. Closes #1253.

Each document now has a list of layers with name, visible, locked states. Strokes belong to a layer; only the active layer is drawn/edited on by default.

Changes

Data model (crates/rnote-engine/src/store/layer_comp.rs)

  • New types: DocumentLayer, DocumentLayerId, LayerComponent.
  • StrokeStore gains layers, layer_components, active_layer_id, layer_counter.
  • Old .rnote files without layer data are backward-compatible — all strokes default to Layer 1.

Rendering order

Sorting in chrono_comp.rs now respects document layer orderexisting StrokeLayerchrono timestamp.

Per-layer filtering

  • Render: only visible layers are rendered (stroke_keys_as_rendered, regenerate_rendering_in_viewport_threaded).
  • Selection: only active, editable (visible & unlocked) layer strokes are selectable.
  • Eraser: only editable active layer strokes are erased/split.
  • Thumbnails: hidden layers are excluded.
  • Export: uses the render path, so hidden layers are excluded.

Engine API

Public methods added on Engine:

  • layers(), active_layer_id()
  • set_active_layer(), add_layer(), delete_layer(), rename_layer()
  • set_layer_visible(), set_layer_locked()
  • move_layer_up(), move_layer_down()

All layer mutations enter undo/redo history.

Xournal++ (.xopp) import/export preservation

.xopp files now preserve document layer structure on import and export:

  • Import: xopp layers are mapped to rnote DocumentLayers by name (merge across pages), preserving layer names and stroke-to-layer assignment.
  • Export: each rnote DocumentLayer produces a named <layer> in the xopp output, with elements ordered to match rnote z-order (images below strokes). Empty named layers are written as placeholders; hidden layers are excluded.

UI (crates/rnote-ui)

A new "Layers" page in the sidebar with controls to:

  • Add/delete layers
  • Rename (inline entry)
  • Toggle visibility and lock
  • Move up/down
  • Set as active layer

Layer buttons use symbolic SVG icons instead of text. Sidebar has i18n support for all layer-related labels.

Tests

Engine unit tests cover:

  • Stroke insertion respects active layer
  • Hidden layers are excluded from rendering/thumbnails
  • Locked/hidden layers cannot be selected
  • Layer order controls render order
  • Layer mutations are undoable/redoable
  • .rnote snapshot preserves layer metadata (name, order, visible, locked)
  • Old snapshots without layer data assign default layer
  • Renaming to same name is a no-op
  • Xopp XML layer elements roundtrip with elements field
  • Xopp import preserves named layers, merges across pages by name
  • Xopp import handles unnamed layers correctly (index-based merge)
  • Xopp export preserves layer names and excludes hidden/empty layers

Build verification

All targets pass:

  • meson compile ui-cargo-check
  • meson compile cli-cargo-check
  • meson test (validation tests: 3/3 OK)
  • cargo test --workspace (18 passed, 1 ignored)
  • meson compile cargo-fmt-check (pass)

- Active indicator: CheckButton radio group (dot radio pattern from appmenu)

- Up/Down: dir-up-symbolic / dir-down-symbolic with flat CSS

- Delete: selection-trash-symbolic with flat CSS
@awerty-noob awerty-noob marked this pull request as ready for review May 24, 2026 16:23
- Add ordered elements field to XoppLayer for correct z-order
- Import: merge xopp layers by name across pages into rnote DocumentLayers
- Export: group strokes by DocumentLayer with layer names preserved
- Write empty named layers to xopp for metadata preservation
- Filter hidden layers from export (all formats)
- Add tests for xopp layer roundtrip, merge-by-name, named/unnamed/empty layers
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.

Add layers to document

1 participant