The open stock list showed ten rows, None to Kodak Kodachrome 64, and the other eighteen - all seven black-and-white stocks among them - could not be reached. The data was whole; the list could not be scrolled. Reproduced on the manual rig (Xvfb, xdotool, the automation hook): - a drag on the list scrolled the develop column, never the list; - a wheel run over the list scrolled the column past it, whenever the column had scrolled under that pointer in the last 800 ms - which is how the list is reached, by wheeling the column down to it. After a pause and a pointer move the wheel did reach the list; - no key did anything. The cause is Slint's routing, not the list. Since2d878c2the list was a Flickable inside the develop column's Flickable, and Slint offers every pointer event to the outermost Flickable first (input_event_filter_before_children, i-slint-core 1.17.1 flickable.rs). The column holds a press back (DelayForwarding) and intercepts the first move past 8 px on the axis it can scroll, so the list never saw a drag. For the wheel it intercepts while its own last wheel event is under 800 ms old and within 2 px, and always for a touchpad gesture that opens with TouchPhase::Started - so on a touchpad the list could get no wheel at all. The list is now a PopupWindow under the Film row. A popup is its own item tree: while it is open, events go to it and to nothing beneath it, so the list scrolls by wheel, drag and flick however the panel is nested and whatever the column did last. The alternative, standing the column down while the pointer is over the list (the sliders' hover trick), fixes the drag but not the wheel - `interactive: false` does not gate wheel interception - so it would have left the bug for touchpad users. The reason2d878c2bounded the list still holds: it is at most 320 px and never lengthens the column, and now it covers the sliders instead of pushing them down. The column cannot be scrolled while it is open, which suits a one-click question; it closes on choosing, on Escape or Back, or on a press outside it. Keys, with the list open: Up and Down move along it from the chosen stock and scroll it into view, Enter chooses, Escape or Back closes it unchanged. A popup is its own focus tree, so the keys are taken when it opens and Slint returns focus to the develop view's scope when it closes. The Film row gains a button role, so a screen reader and the automation hook can name it.
332 lines
15 KiB
Markdown
332 lines
15 KiB
Markdown
# DarkRoom, shown
|
|
|
|
A tour of what the application does, one picture per thing. Every image on
|
|
this page was captured from the desktop build driving itself — nothing is a
|
|
mock-up, and nothing has been retouched outside DarkRoom. Where a feature is
|
|
better seen moving, it moves.
|
|
|
|
The requirements behind each feature are in [requirements.md](../dev/requirements.md);
|
|
the reasoning is in the design documents linked from each section. This page
|
|
is only about what you see.
|
|
|
|
The photographs are the author's. None show a person.
|
|
|
|
## Opening a library
|
|
|
|
DarkRoom opens on a library: a folder on this machine, a folder a sync
|
|
client keeps, or a Nextcloud account. A folder needs no password and uploads
|
|
nothing.
|
|
|
|

|
|
|
|
Once a folder is named, it is the library — you are not asked for it again,
|
|
and `Open library` opens it whole. `Subfolder…` narrows the scan to part of
|
|
it. The formats ticked are what the scan looks for; RAW is on and JPEG off
|
|
by default, because a RAW editor's sensible default is the file the camera
|
|
wrote first.
|
|
|
|

|
|
|
|
## The library
|
|
|
|

|
|
|
|
Photographs are ordered by capture time, with a month heading where each
|
|
begins. The strip on the left is the timeline — drag it to jump to a year.
|
|
The bar above the grid filters by rating, flag, colour label and where the
|
|
file is (on this device, or only on the server).
|
|
|
|
### Rating and flagging
|
|
|
|
Hover a cell and the stars appear; click one. The filter chips above the grid
|
|
count what each rating holds, and clicking `3+` shows only those.
|
|
|
|

|
|
|
|
Colour labels work as Lightroom's do: `6` red, `7` yellow, `8` green, `9`
|
|
blue, on the photograph under the pointer or on the selection, and the same
|
|
key again takes the label off. `Label` on the selection bar offers all five,
|
|
purple included, and `None`. Each label is drawn with its initial on it, so
|
|
it reads without telling the colours apart, and the filter bar has a chip for
|
|
each. In develop, the top bar names the open photograph's label and sets it,
|
|
and the same keys work there.
|
|
|
|

|
|
|
|
### Getting about
|
|
|
|
Drag the timeline to scrub through years; Ctrl and the wheel resize the
|
|
thumbnails.
|
|
|
|

|
|
|
|

|
|
|
|
### Selecting several
|
|
|
|
`Select` in the header — or Ctrl-click — starts a selection. Shift-click picks
|
|
a range. The bar at the foot of the grid is everything a selection can be done
|
|
to: collections, keywords, presets, export, and merging to a panorama.
|
|
|
|

|
|
|
|
`Keywords` on that bar opens a sheet; type a word and press return, and it
|
|
is on every photograph selected. The list below the field is every keyword
|
|
the library has, ticked where the selection carries it.
|
|
|
|

|
|
|
|
### Collections
|
|
|
|
`+` at the head of the sidebar makes one. Drag a photograph — or the whole
|
|
selection — onto its row to file it there; click the row to see it. A
|
|
photograph can be in several, and the badge on its cell counts them.
|
|
|
|

|
|
|
|
Collections nest. Drag one onto another to put it inside; `+` with a
|
|
collection selected — or `New collection inside` from its menu — makes a
|
|
child. A parent shows everything its children hold, and its count says so.
|
|
Right-click a row (hold it, on a tablet) for the menu: rename, nest,
|
|
move back to the top level, keep it offline, delete.
|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|
### Bursts
|
|
|
|
Frames taken a moment apart that look alike fold into one cell, with a badge
|
|
counting them. Click the badge — tap it, on a tablet — to open the burst in
|
|
the grid, and again to fold it back. A folded burst shows its earliest frame;
|
|
to have it show another, open it and click the ring on the frame you want.
|
|
|
|
With faces indexed, narrowing the grid to a person puts `Eyes open` beside
|
|
their name on the filter bar, which leaves out the frames where they blinked.
|
|
|
|
### Duplicate originals
|
|
|
|
A library put together by hand often holds the same RAW more than once — a
|
|
dated folder, a `bck` folder beside it, a renamed copy another program
|
|
exported. When the catalog finds files with the same camera, capture time
|
|
and size in more than one place, `Duplicate originals` appears under the
|
|
trash in the sidebar with how many there are; Settings offers the same page
|
|
beside the other whole-library passes.
|
|
|
|
The page lists each group with its picture and its paths. One copy is
|
|
marked `Stays`: the one outside a folder named like a backup (`bck`,
|
|
`backup`, `copy`, `old`…), then the one still named the way the camera named
|
|
it (`_MG_4623`, `IMG_0001`, `DSC_0042`), then the one catalogued first. Tap
|
|
another path to keep that copy instead, and untick `Include` to leave a
|
|
group alone.
|
|
|
|
Nothing moves until `Check` has read the first and last megabyte of every
|
|
copy and each copy's sidecar. A group whose files differ, or whose copies
|
|
carry two different edits, is marked skipped and says why — two edits of
|
|
one frame are kept for virtual copies. What the check reads is kept, so a
|
|
second visit costs nothing. The line under each group says what the copy
|
|
that stays will gain: the highest rating, every keyword and collection, a
|
|
flag or label the copies agree on, faces and the names on them, and the
|
|
edit if only a copy had one. Where the copies disagree on a flag or a
|
|
label, the one that stays keeps its own and the line says so.
|
|
|
|
`Move N copies to trash` does it, one group at a time: each group is merged
|
|
and its spare copies moved together, or not at all. The copies go to the
|
|
trash, not away — select them in the trash view and `Restore` puts them
|
|
back where they were.
|
|
|
|
## Developing a photograph
|
|
|
|
Click a thumbnail to open it. The column on the right is every adjustment;
|
|
the strip at its head narrows it to one group.
|
|
|
|

|
|
|
|

|
|
|
|
### Light
|
|
|
|
Exposure, contrast, highlights, shadows, blacks, whites and a tone curve.
|
|
Hold `Before` to see the photograph as it was.
|
|
|
|

|
|
|
|
### Looking closer
|
|
|
|
Double-click for 1:1; drag to move about; double-click again to fit. The
|
|
wheel zooms to any amount in between. Past 1:1 the file's own pixels are
|
|
drawn as hard-edged blocks rather than smoothed, so what you see is what
|
|
the sensor recorded.
|
|
|
|

|
|
|
|
### Moving between photographs
|
|
|
|
The roll along the foot of the canvas holds the photographs the grid was
|
|
showing; click one to open it. The right arrow, `D` or space opens the next,
|
|
and the left arrow or `A` the one before. The edit on screen is saved on the
|
|
way, so stepping along a shoot loses nothing.
|
|
|
|
### White balance from the photograph
|
|
|
|
Press `pick` in the White Balance group, then click something neutral —
|
|
a white wall, a grey card, the air conditioner here. The picker sets the
|
|
sliders from the photograph, not from where they were: below, the frame
|
|
is dragged cold first and one click puts it right. A blown highlight is
|
|
refused, since a clipped pixel has no colour left to balance.
|
|
|
|

|
|
|
|
### Composing
|
|
|
|
Crop by dragging the frame's corners, straighten with the slider, lock a
|
|
ratio from the chips. `Done composing` returns to the photograph.
|
|
|
|

|
|
|
|
`Vertical` and `Horizontal`, under `Straighten`, correct the lines that
|
|
converge when the camera is tilted up at a building; the crop refits to
|
|
what is left.
|
|
|
|

|
|
|
|
A crop that leaves a mask wholly outside the frame says so, and offers to
|
|
take the crop back or keep it.
|
|
|
|

|
|
|
|
### Local adjustments
|
|
|
|
`Local` in the rail turns the column into a mask stack. `Find subjects` runs a
|
|
segmentation model over the photograph; what it recognises appears as a list
|
|
of categories with how much of the frame each covers. Click one and it is a
|
|
mask — then every slider below edits only that region.
|
|
|
|

|
|
|
|

|
|
|
|
A mask is a stack of parts. Paint into it, subtract a gradient from it, grow
|
|
or shrink its edge, choose how it falls off. `Show masks as` draws the mask
|
|
tinted, as alpha, or as an outline; the eye on its row switches it off.
|
|
|
|

|
|
|
|
Linear and radial gradients, a tone range and a colour range are the other
|
|
ways to make one; each can be combined with any other. `∩ Intersect` keeps
|
|
only where the new part and the mask agree: below, a gradient over the
|
|
lower half, then two strokes that survive only where the gradient is.
|
|
|
|

|
|
|
|
### Repair
|
|
|
|
`Repair` in the rail: click a mark and it is covered from a source DarkRoom
|
|
chooses beside it. Drag either circle to move it; the size, feather and
|
|
opacity are in the panel. Heal blends; clone copies.
|
|
|
|

|
|
|
|
### Film
|
|
|
|
The `Film` chooser at the head of Adjust applies a spectral simulation of a
|
|
named stock; below it, the print exposure and push controls a film has and a
|
|
sensor does not. The list opens over the column and scrolls on its own — by
|
|
wheel, drag or flick, or with `Up`, `Down` and `Enter` — down to the
|
|
black-and-white stocks at its end.
|
|
|
|

|
|
|
|
### History, snapshots, presets
|
|
|
|
Every change is a step; `Undo` and the History panel walk them. `Snapshot`
|
|
keeps the current state under a name. `Presets…` saves the settings to
|
|
apply elsewhere, and imports `.xmp` from other applications.
|
|
|
|

|
|
|
|
### Copying settings
|
|
|
|
`Copy` in the top bar, or Ctrl+C, takes this photograph's settings; `Paste`,
|
|
or Ctrl+V, puts them on another, and says what it would paste — how many
|
|
adjustments, and whether the crop comes too. In the grid, `Paste to N` on the
|
|
selection bar pastes onto every photograph selected. Which kinds of edit a
|
|
copy carries is chosen in `Presets…`, or with Ctrl+Shift+C: a look carried
|
|
across a shoot usually leaves each frame's own crop alone.
|
|
|
|
## Merging a panorama
|
|
|
|
Select the frames, then `Merge to panorama` from the selection bar. The
|
|
frames are read, aligned, and drawn on the suggested projection with each one
|
|
outlined where it landed — twelve hand-held portrait frames across an alpine
|
|
valley, here. Change the projection (a 150° sweep on a flat perspective is
|
|
what the middle of the film shows, and why cylindrical is suggested), ask for
|
|
the border to be filled rather than cropped, then `Merge`. The composite is
|
|
written beside its sources as a DNG and appears in the grid with the merge
|
|
as the first step in its history.
|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|
## Export
|
|
|
|
`Export` in the develop header, or `Export N` from a selection. Format,
|
|
size, colour space, sharpening, naming and where the file goes are in
|
|
Settings, and apply to every export until changed. An export with no folder
|
|
set is refused, and the header says so.
|
|
|
|

|
|
|
|
## Settings
|
|
|
|

|
|
|
|
Background activity with progress, thumbnail and face indexing, storage on
|
|
this device, display and colour, export defaults, what is written to XMP
|
|
sidecars, and a diagnostics bundle for a bug report.
|
|
|
|
## People
|
|
|
|
Face detection and identity run over the library and group faces by person;
|
|
the `Identity` page is where suggestions are confirmed, rejected and split,
|
|
and `People` on the filter bar narrows the grid to someone. Not pictured
|
|
here, for the obvious reason — [faces.md](../dev/faces.md) has the design.
|
|
|
|
## Where things are written down
|
|
|
|
| Feature | Design |
|
|
|---|---|
|
|
| Local masks and segmentation | [segmentation.md](../dev/segmentation.md), [mask-editing.md](../dev/mask-editing.md) |
|
|
| Repair | [spot-removal.md](../dev/spot-removal.md) |
|
|
| Panorama | [panorama.md](../dev/panorama.md) |
|
|
| Faces and identity | [faces.md](../dev/faces.md) |
|
|
| Gestures, generated from the code | [gestures.md](../gestures.md) |
|
|
| Navigation and layout | [ui-navigation.md](../dev/ui-navigation.md) |
|
|
| Sync and storage | [storage.md](../dev/storage.md) |
|
|
|
|
## How this page is made
|
|
|
|
[`tools/manual/`](../../tools/manual/README.md) drives the desktop build on
|
|
a private X server and records each scene; `record.sh <library>` re-makes
|
|
every picture here. Run it after a change to the interface and commit what
|
|
changed. The pictures are in LFS.
|
|
|
|
The application carries this page. `cargo run -p traceability -- manual`
|
|
renders it to `index.html` beside it, which the packages install with the
|
|
pictures and the app opens from Help, from Settings, and from the "See it"
|
|
link beside a gesture on the help sheet. CI fails when the two differ.
|
|
|
|
Making it the first time turned up nine faults, each fixed in its own
|
|
commit before the pictures were taken: the folder picker could not choose
|
|
the top level, month headings overprinted each other, a category mask
|
|
widened the column off the window, the mask tint outlived its mode, the
|
|
first sync uploaded an empty thumbnail shard, a merge that ran out of GPU
|
|
memory left the page on Stop for ever, the export settings promised to ask
|
|
for a folder and did not, the keyword sheet sent its keys to the grid, and
|
|
an empty trash told you to check your library folder.
|