Skip to content

Development Strip Editor Code Map

Bartłomiej Mucha edited this page Oct 13, 2026 · 3 revisions

Strip editor — code map

Where the code for each part of the screen lives, what each folder may use, and how the parts talk. The why is in the tool framework; the file-by-file recipes for adding a tool, a shape or a kind of object are in Extending the strip editor.

The screen is the folder tree

Every folder under widgets/stripeditor/ is one region of the editor, named as it is on screen.

┌───────────────┬──────────────────────────────────┬───────────────────────┐
│ TOOL RAIL     │                                  │ OBJECT STATE          │
│ toolrail/     │                                  │ objectstate/          │
│               │          CANVAS                  │                       │
├───────────────┤          canvas/                 ├───────────────────────┤
│ TOOL OPTIONS  │                                  │ OBJECT STACK          │
│ tooloptions/  │   what is drawn on it: objects/  │ objectstack/          │
└───────────────┴──────────────────────────────────┴───────────────────────┘
      editor.* (the root) builds all five and wires them together

Two folders are not regions. objects/ is what sits on the canvas and the controller that owns it. properties/ holds the editors that TOOL OPTIONS and OBJECT STATE both show.

Folders and their files

widgets/stripeditor/
├── editor.{hpp,cpp,ui}        the shell: builds the regions, wires them, zoom, the grade's glue
├── presetstore.*              named looks: built-ins, the user library, packs
├── scrolledpage.hpp           wraps a panel page in a scroll area
├── toolrail/                  LEFT, TOP
│   ├── toolregistry.*           the tool table: one row per tool, what it does to the canvas
│   ├── toolrail.*               a tile per row, and the colour pair under them
│   ├── colourpair.*             primary/secondary colours: furniture, not a tool
│   └── cursors.*                which cursor, from the tool and what is under the pointer
├── tooloptions/               LEFT, BOTTOM: what the next object will be
│   ├── tooloptionsstack.*       one page per tool, and the page for tools with none
│   ├── bubbletooloptions.*      Speech bubble and Text
│   ├── artworktooloptions.*     Artwork: which picture the next placement puts down
│   └── gradetooloptions.*/.ui   Colour correction
├── canvas/                    CENTRE: the strip and what a press on it does
│   ├── stripitem.*              draws every page as one seam-free item
│   ├── pagesource.*             page memory: proxy, sharp and graded images
│   ├── canvasinput.*            the viewport's event filter, routed by the armed tool
│   └── sampling.*               the colour under the eyedropper
├── objects/                   what is placed on the strip
│   ├── object.*                 the base every object answers to
│   ├── bubbleobject.*           a balloon or lettering Platemaker drew (plain text is a
│   │                            bubble with no balloon)
│   ├── artworkobject.*          imported artwork, raster or vector
│   ├── objectcontroller.*       the objects, the selection, the drag, and every operation
│   ├── placement.*              a Create tool's drag: the rubber band and what it places
│   ├── resize.*                 the eight grips' resize maths, a pure function
│   ├── selectionchrome.*        the selection's box, grips and tail handles, above every object
│   └── striplayout.*            the strip's pages: where each sits, what an overlay anchors to
├── properties/                SHARED by TOOL OPTIONS and OBJECT STATE: one editor per group
│   ├── propertygroup.*          the group list
│   ├── propertygroupeditor.*    the base: live `changed`, settled `committed`
│   ├── propertygroupset.*       a balloon's four look editors, and the rules for applying them
│   ├── shapeeditor.* skineditor.* styleeditor.* texteditor.*
│   ├── taileditor.* taillisteditor.* nexttaileditor.*
│   ├── blendeditor.*            the one property every kind carries
│   └── colouradjustment.*       one named part of the grade
├── objectstate/               RIGHT, TOP: what the selected thing is
│   ├── objectstatestack.*       which panel shows, from what is selected
│   ├── objectstate.*            an object, several, or a tail
│   └── stripstate.*             the strip or a page
└── objectstack/               RIGHT, BOTTOM: every object in composite order
    ├── objectstack.*            the tree: rows, chips, drag to reorder, mute
    ├── objectmenu.*             the right-click menu, on the stack and the canvas alike
    └── rowglyph.*               the object drawn small for its row

widgets/objectrecord/          outside the editor: the project and the main window use it too
├── objectrecord.hpp           what a bubble is: the record an overlay is rendered from
├── propertygroups.hpp         the groups a record is made of: Shape, Skin, Style, Text, Tails
├── recordpainter.*            draws a record (namespace Painter)
├── recordsvg.*                a record as SVG and back (namespace Svg)
└── recordstore.*              every open project's records, by project uid

What may include what

toolrail ─────┐
tooloptions ──┼──► properties ──► widgets/objectrecord
objectstate ──┘         ▲
objectstack ──► objects ┘
canvas ───────► objects
editor (root) ──► everything — the only place the regions meet
  • A region never includes another region. TOOL OPTIONS and OBJECT STATE meet through properties/ (the same editor classes) and through Editor (the wiring).
  • Nothing includes editor.hpp. The root's other files (presetstore, scrolledpage) are shared.
  • Includes name their folder: #include "objects/object.hpp". widgets/stripeditor is the only include root, so an include line is the dependency, and an unqualified one does not compile.

It is checked on every build. cmake/check_layers.cmake runs before Platemaker compiles, and as the strip_editor_layers test. A violation stops the build with file:line: error: tooloptions/ may not include objectstate/.

A few headers are allowed across a region line. The script lists each one with its reason, and warns when one is no longer used. Today they are:

  • the tool table and the cursor rule (toolrail/toolregistry, toolrail/cursors), for the canvas, TOOL OPTIONS and the objects;
  • the strip's layout, for OBJECT STATE;
  • loadArtwork(), for the Artwork tool's preview;
  • the colour pair, for the object menu.

How the parts talk

                 MainWindow / Project  (persistence, one undo history per project)
                   ▲ recordCreated, overlaysCommitted,            │ setOverlaySource,
                   │ artworkImportRequested,                      │ setColourCorrection,
                   │ colourCorrectionCommitted                    ▼ setPreviewSource
               ┌───────────────────────────── Editor ─────────────────────────────┐
               │                                                                  │
 TOOL RAIL ── toolPicked ──► Editor::setTool ──► TOOL OPTIONS page, CanvasInput   │
                                                                                  │
 CanvasInput ── a Create drag ─────────► Placement ──► ObjectController           │
             ── sampleRequested ───────► Editor ──► sampleCanvas ──► ColourPair   │
             ── colourApplyRequested ──► Editor ──► ObjectController              │
             ── artworkDropped, zoomStepRequested ──► Editor                      │
                                                                                  │
 OBJECT STATE ── changed / committed ──────────────────► ObjectController         │
              ◄─ boundToRecord, boundToTail, boundToRecords… ─┘   (via Editor)    │
                                                                                  │
 OBJECT STACK, object menu ── read the controller's getters, call its methods     │
                           ◄─ stackChanged, selectionChanged, subjectRowChanged   │
               └──────────────────────────────────────────────────────────────────┘
  • ObjectController is the model and the selection. It holds no widget of any region. The stack and the menu are views of it, the way a list view is a view of a model. OBJECT STATE may not include it, so the controller tells it what to show by signal, and the Editor connects the two.
  • No edit is final in the editor. Every change leaves as a signal, MainWindow pushes it onto the project's undo history, and the result comes back through setOverlaySource(). See History and undo.
  • Live and settled have one spelling. …changed is live (preview, no history step); …committed is settled (one undo step). Every editor and panel uses the pair.

I want to… → look in

I want to… Look in
add a kind of object objects/ (a subclass of Object); its record in widgets/objectrecord/
add or change a property the struct in widgets/objectrecord/propertygroups.hpp, its editor in properties/, the group in properties/propertygroup.hpp
add a tool a row in toolrail/toolregistry.cpp; its page in tooloptions/, registered by the Editor (the stack asserts every tool has one)
link a tool's options to an object's properties properties/propertygroupset.* and the page's prototype()
use the colour pair toolrail/colourpair.*; it is read by the bucket (canvas/canvasinput → ObjectController::applyColourAt), written by the eyedropper (canvas/sampling), and read by the menu's Fill and Outline
change what the strip or a page shows objects/striplayout.* (geometry), canvas/stripitem.* (drawing), objectstate/stripstate.* (its panel)
add a filter like the grade toolrail/ (row) + tooloptions/gradetooloptions.*; the glue is in editor.cpp
make a filter reach the render the library: a model field, its codec, the strip builder. No GUI folder makes that cheap
change what a right-click offers objectstack/objectmenu.* for the entries; the operation itself in objects/objectcontroller.*
change a cursor toolrail/cursors.*

See also: Tool framework · Object state and tool options · Architecture

Clone this wiki locally