A proof-of-concept docking/tiling panel GUI in Slint, evaluating Slint for the
ImSwitch GUI rewrite. See FINDINGS.md for the assessment.
Part of an initiative to replace micromanager-ImageJ GUI. tech demo only
Using the Makefile:
make all # profile release build (cargo build --release)
make run # build release, then start the GUI (panel gallery)
make run-dock # build release, then start the docking demo
make test # run the unit tests
make clean # cargo cleanOr with cargo directly:
cargo build --release # release build
cargo run --release -- --gallery # panel gallery
cargo run --release # docking demo (default, no args)Requirements: a Rust toolchain and a C/C++ compiler (for native deps); no Skia build is
needed. build.rs enables the Slint experimental features automatically. First build is
slow (large dependency tree); rebuilds are fast.
- Two dock regions split by a draggable divider.
- Each region has a tab strip; drag a tab from one region and drop it into the other to re-dock it.
- Tab content is a dynamically-loaded panel (compiled at runtime by the Slint
interpreter), chosen by the tab's
kind:form— Laser-Control-style widgets (slider / spinbox / checkbox / button)plot— a live waveform (animated)image— a live procedural "camera" pattern (animated)
ui/app.slint— dock shell: regions, tab strip, splitter, drag-drop,ComponentContainers.src/main.rs— Rust-owned dock model (VecModels), themove-tabdocking logic (with unit tests), and wiring of panel factories.src/panels.rs— the three panel.slintsources + interpreter-backedComponentFactoryconstruction.build.rs— compilesui/app.slintand enables Slint experimental features (DragArea/DropArea).
- Requires the experimental flag (set automatically in
build.rs) for drag-and-drop. - Depends on
slint-interpreter'sinternalfeature for embedding dynamic panels. - Tested on macOS with the femtovg/software renderer (no Skia build required).
cargo test # covers the docking move logicWindow::take_snapshot() lets the app render a frame to a PNG with no screen-recording
permission — handy for automated visual checks:
cargo run -- --screenshot out.png
# start the right region on the Image tab (verification aid):
IMSWITCH_DEMO_IMAGE_FIRST=1 cargo run -- --screenshot out.pngui/panels/*.slint is a library of ~13 self-contained panel components resembling the
ImSwitch widget screenshots (Laser, Positioner, Recording, Focus Lock, Scan, Detector,
SLM, FFT, Bead Rec, Rotation Scan, Rotator, Tiling, Data). Browse them with the gallery:
cargo run -- --gallery # sidebar list + preview (click to switch)
cargo run -- --gallery --panel 6 # preselect panel 6 (SLM), e.g. for screenshots
SLINT_SCALE_FACTOR=1 cargo run -- --gallery --panel 6 --screenshot slm.png--panel N (N = 0..12) is the deterministic way to view/screenshot a specific panel.
--driver reads newline commands from stdin and drives the live UI with synthetic
pointer/key events (via Window::dispatch_event) plus on-demand screenshots. This lets
the GUI be exercised and visually checked entirely programmatically. Coordinates are in
logical pixels, which equal screenshot pixels (1:1).
printf '%s\n' \
'sleep 900' \
'shot before.png' \
'click 572 19' \
'drag 147 19 670 300' \
'shot after.png' \
'quit' | cargo run -- --driverCommands: move X Y, click X Y, press X Y, release X Y, drag X1 Y1 X2 Y2,
key TEXT, shot PATH, sleep MS, quit (see src/driver.rs).
Reliability notes (important for automated testing):
--screenshot,--panel N,move, anddragare reliable.dragworks because Slint processesmovedsynchronously.- Synthetic
clickis FLAKY. Slint emitsclickedon a later event-loop tick, so it only fires if the loop keeps ticking after the release.clickpumps extra moves to help, and it lands most reliably on animated windows /DragArea-wrapped targets (e.g. the dock tabs), but it is not guaranteed — especially on fully static plain-TouchAreatargets (e.g. the gallery sidebar). Prefer--panel N/ state flags over clicking for deterministic verification. - Set
SLINT_SCALE_FACTOR=1when driving: the window's scale factor is otherwise nondeterministic between launches (snapshots come out 1120×720 or 2240×1440), which breaks fixed click coordinates. Forcing scale 1 makes snapshot px == logical px == click coordinates. - For continuous/interactive control, run
--driveras a background process with stdin connected to a FIFO and write commands to it over time; screenshots appear as files.