Move the library grid's cells and selection onto their own Slint global
AppWindow carried the grid's loaded window of cells, the keyboard cursor, drag and drop, the held-row long-press state, columns and cell size, the scroll and viewport bookkeeping, the photo roll's pick and centre-request, and the local-only/reorder/collection-filing gestures that act on a selection, as properties and callbacks on the root component. That state now lives in the `Library` global declared in library.slint, next to the structs (LibraryCell, TimelineBar, KeywordRow, PersonChip) it and the grid's other components already share; Rust reaches it through window.global::<Library>() instead of window.set_/get_/on_/invoke_ on the root, the same change collections.slint's `Collections` global made for the sidebar. library-visible stays on AppWindow: it is computed from active-page and active-view, the shell's own routing state, which a global cannot read. Everything else still prefixed library- — the timeline, the filter bar, ratings and flags, keywording, and the routes and status lines — stays on the window for now and moves in the commits that follow.
This commit is contained in:
+51
-158
@@ -7,7 +7,7 @@ import { CropOverlay } from "crop.slint";
|
||||
import { HistoryPanel, HistoryRow, Steps } from "history.slint";
|
||||
import { LaunchScreen } from "launch.slint";
|
||||
import { IdentityScreen, IdentityPerson, IdentityFace } from "identity.slint";
|
||||
import { LibraryGrid, LibraryCell, TimelineBar, PhotoRoll, KeywordRow, PersonChip } from "library.slint";
|
||||
import { LibraryGrid, LibraryCell, TimelineBar, PhotoRoll, KeywordRow, PersonChip, Library } from "library.slint";
|
||||
import { GestureRow } from "gestures.slint";
|
||||
import { Button, PanelHeading, Label, Value, Caption, Panel, EmptyState, ProgressBar, ActivityRow } from "widgets.slint";
|
||||
import { CollectionsPanel, CollectionRow, Collections, OfflinePrompt, CollectionMenu,
|
||||
@@ -32,6 +32,7 @@ export { ViewMode, GradientHandle, HandleRole, SpotHandle, SpotRole }
|
||||
// panels take their wiring this way and why there is one global per family.
|
||||
export { Develop, Capture, Levels, Peaking, Adjustments, Framing, Transfer, Masking, Repair, Steps }
|
||||
export { Collections }
|
||||
export { Library }
|
||||
|
||||
/// Which top-level screen is on display. Exactly one at a time — replacing
|
||||
/// the `show-launch` / `show-library` / `show-identity` booleans, with
|
||||
@@ -288,8 +289,6 @@ export component AppWindow inherits Window {
|
||||
/// the two can drift apart again.
|
||||
out property <bool> library-visible:
|
||||
root.active-page == Page.none && root.active-view == View.library;
|
||||
in-out property <[LibraryCell]> library-cells;
|
||||
in property <int> library-total: 0;
|
||||
// --- background activity (FR-CAT-1, FR-NC-6c) ---
|
||||
//
|
||||
// Every background job in one register, filled by `activity.rs`. The
|
||||
@@ -338,28 +337,9 @@ export component AppWindow inherits Window {
|
||||
in property <bool> library-offline: false;
|
||||
in property <string> library-offline-reason: "";
|
||||
in property <string> library-offline-since: "";
|
||||
// Narrows the grid to images whose RAW is stored locally — the ones that
|
||||
// can actually be opened while offline. Off by default: the catalog is the
|
||||
// library, and hiding most of it the moment a connection drops would read
|
||||
// as data loss rather than as a filter.
|
||||
in-out property <bool> library-local-only: false;
|
||||
in property <int> library-local-count: 0;
|
||||
callback library-toggle-local-only();
|
||||
/// Whether the grid is narrowed to the timeline's visible span.
|
||||
in-out property <bool> library-range-active: false;
|
||||
callback library-toggle-date-range();
|
||||
/// TRACES: FR-CAT-5
|
||||
callback library-clear-selection();
|
||||
callback library-select-all();
|
||||
/// TRACES: FR-CAT-7
|
||||
/// Whether the grid is showing something with a manual order to change —
|
||||
/// a single manual collection, not a set and not a saved filter.
|
||||
in property <bool> library-reorderable: false;
|
||||
/// Move the selection beside the photograph at this row of the loaded
|
||||
/// window: after it where the drop landed on the cell's trailing half,
|
||||
/// before it otherwise.
|
||||
callback library-reorder-to(int, bool);
|
||||
callback library-collection-from-selection(string);
|
||||
/// TRACES: FR-CAT-6
|
||||
in property <string> library-range-from;
|
||||
in property <string> library-range-to;
|
||||
@@ -425,7 +405,6 @@ export component AppWindow inherits Window {
|
||||
callback library-timeline-pinch(float);
|
||||
callback library-timeline-pan(float);
|
||||
callback library-timeline-zoom(int);
|
||||
in-out property <int> library-columns: 1;
|
||||
in property <bool> library-syncing: false;
|
||||
/// TRACES: FR-CAT-3 | FR-NC-3
|
||||
/// The whole-library thumbnail pass, launched from the settings page.
|
||||
@@ -496,42 +475,10 @@ export component AppWindow inherits Window {
|
||||
callback identity-check-coverage();
|
||||
callback identity-delete-all();
|
||||
callback library-thumbnail-all();
|
||||
in-out property <length> library-cell-size: 180px;
|
||||
/// Whether this session is a touch one, which decides if the rating strip
|
||||
/// waits to be hovered or stands open. Seeded from the platform by Rust
|
||||
/// and latched by the grid on the first finger it sees.
|
||||
in-out property <bool> library-touched: false;
|
||||
callback library-zoom-cells(int);
|
||||
/// A pinch step on the grid: the ratio since the last update.
|
||||
callback library-pinch-cells(float);
|
||||
/// A pinch on the grid has begun, so the press that opened it was not one.
|
||||
callback library-pinch-started();
|
||||
in property <int> library-scroll-to: 0;
|
||||
in property <int> library-scroll-token: 0;
|
||||
/// Which row of the loaded window is the photograph currently open in
|
||||
/// develop, so the roll can mark it. `-1` when it is not in the window.
|
||||
in property <int> library-roll-current: -1;
|
||||
/// Whether the photo roll is out. Owned here rather than by the roll, so
|
||||
/// it survives the develop view being torn down and rebuilt.
|
||||
in-out property <bool> roll-open: false;
|
||||
/// Centre the roll on the open photograph the next time the strip settles.
|
||||
///
|
||||
/// Raised by Rust when a develop session begins — a photograph opened from
|
||||
/// the grid — and cleared by the strip itself once honoured. Owned here for
|
||||
/// the same reason `roll-open` is: the develop view is rebuilt whenever an
|
||||
/// overlay screen covers it, and a request raised before that must survive
|
||||
/// it. See `PhotoRoll::centre-request`.
|
||||
in-out property <bool> library-roll-centre: false;
|
||||
/// A photograph was chosen from the roll: the row within the loaded
|
||||
/// window, which is what a cell click reports too.
|
||||
callback library-roll-pick(int);
|
||||
callback library-sync-now();
|
||||
callback library-columns-changed();
|
||||
callback library-scrolled(int);
|
||||
/// How many cells the grid's viewport shows at once. Rust sizes the
|
||||
/// loaded window from it — see `library_ui::window_move`.
|
||||
callback library-viewport-cells(int);
|
||||
callback library-cell-clicked(int);
|
||||
callback library-rescan();
|
||||
/// Grid → launch screen, to pick a different folder or account.
|
||||
callback library-change();
|
||||
@@ -559,11 +506,6 @@ export component AppWindow inherits Window {
|
||||
/// Ask about a collection's local copies: the tray on a row, or a long
|
||||
/// press anywhere on it.
|
||||
callback collection-offline-menu(int);
|
||||
/// TRACES: FR-CAT-7 | FR-UI-4
|
||||
/// File the grid's selection in a collection without dragging it there:
|
||||
/// the target's id, and whether to take the images out of the collection
|
||||
/// currently being shown.
|
||||
callback library-file-in-collection(int, bool);
|
||||
/// TRACES: FR-CAT-5 | FR-CAT-6
|
||||
/// Keywording the grid's selection. The catalog has been searchable by
|
||||
/// keyword since it existed and there was nowhere to type one; this is it.
|
||||
@@ -583,58 +525,9 @@ export component AppWindow inherits Window {
|
||||
/// Take a keyword off the selection. Never deletes the keyword itself —
|
||||
/// it stays in the vocabulary and on every other photograph that carries it.
|
||||
callback library-unassign-keyword(string);
|
||||
/// TRACES: FR-UI-2
|
||||
/// Whether a tap in the grid selects rather than opens, and the button
|
||||
/// that turns it on. The long press does the same thing without it.
|
||||
in property <bool> library-select-mode: false;
|
||||
callback library-toggle-select-mode();
|
||||
/// TRACES: FR-CAT-7 | FR-UI-4
|
||||
/// The row a press has held long enough to pick up, or `-1`.
|
||||
///
|
||||
/// Set by the same hold that turns on selection mode and cleared by the
|
||||
/// grid when the press ends — `in-out` because both ends write it. See
|
||||
/// `held-row` in `library.slint` for what it draws and what it stops.
|
||||
in-out property <int> library-held-row: -1;
|
||||
/// A press on a cell ended, so the long-press timer can be cancelled.
|
||||
callback library-cell-press-ended();
|
||||
|
||||
// --- drag and drop ---
|
||||
//
|
||||
// Slint's own `DragArea`/`DropArea` carry this: pointer capture, the
|
||||
// click-versus-drag threshold, arbitration against the grid's Flickable,
|
||||
// and the image drawn under the cursor. So there is no badge to position
|
||||
// and no hover state to mirror here — only the payload, which Rust builds
|
||||
// from the selection, and the count the header shows.
|
||||
/// The drag payload, built by Rust from the current selection.
|
||||
pure callback library-drag-payload() -> data-transfer;
|
||||
/// The bitmap that travels under the cursor: one thumbnail, or a fanned
|
||||
/// stack where several images are being dragged. Composited in Rust.
|
||||
in property <image> library-drag-image;
|
||||
/// A drag began on a cell, so an unselected one can be promoted before the
|
||||
/// payload is read.
|
||||
callback library-drag-started(int);
|
||||
callback library-drag-finished();
|
||||
in property <int> library-selected-count: 0;
|
||||
|
||||
callback library-cell-pressed(int, bool, bool);
|
||||
callback library-remove-from-collection();
|
||||
|
||||
// --- where the selection is filed (FR-CAT-7) ---------------------------
|
||||
//
|
||||
// `library-remove-from-collection` can only ever mean the collection the
|
||||
// grid is scoped to — it is the only one that button can name. Opens the
|
||||
// membership sheet, whose state (`Collections.membership-open` and
|
||||
// `.membership-rows`) is on the sidebar's own global — only the library
|
||||
// side knows the selection has changed enough to be worth recomputing
|
||||
// the sheet against.
|
||||
callback library-open-membership();
|
||||
|
||||
// The keyboard cursor: where the arrows are in the library, as an image
|
||||
// ordinal. Rust owns it — clamping it needs the library's length, and
|
||||
// moving it may have to swap the loaded window underneath.
|
||||
in property <int> library-cursor: -1;
|
||||
callback library-move-cursor(int, bool);
|
||||
callback library-open-cursor();
|
||||
|
||||
// --- ratings and flags (FR-CAT-5, FR-CULL-4) ---
|
||||
//
|
||||
@@ -1560,7 +1453,7 @@ in property <bool> panel-visible: true;
|
||||
height: 100%;
|
||||
rows: Collections.collection-rows;
|
||||
selected-id: root.collection-selected;
|
||||
total-images: root.library-total;
|
||||
total-images: Library.library-total;
|
||||
error: Collections.collection-error;
|
||||
|
||||
// TRACES: FR-NC-6a
|
||||
@@ -1592,7 +1485,7 @@ in property <bool> panel-visible: true;
|
||||
rename-cancel() => { Collections.collection-rename-cancel(); }
|
||||
trash-count: Collections.trash-count;
|
||||
trash-label: Collections.trash-label;
|
||||
selected-count: root.library-selected-count;
|
||||
selected-count: Library.library-selected-count;
|
||||
|
||||
dropped-on(id) => { Collections.collection-dropped(id); }
|
||||
collection-drag-payload(id) => { return Collections.collection-drag-payload(id); }
|
||||
@@ -1610,8 +1503,8 @@ in property <bool> panel-visible: true;
|
||||
// 768 logical pixels, which fits the title and the status
|
||||
// line but not the library's buttons beside them.
|
||||
expanded: root.expanded;
|
||||
cells: root.library-cells;
|
||||
total: root.library-total;
|
||||
cells: Library.library-cells;
|
||||
total: Library.library-total;
|
||||
scanning: root.library-scanning;
|
||||
opening: root.library-opening;
|
||||
scan-status: root.library-status;
|
||||
@@ -1621,17 +1514,17 @@ in property <bool> panel-visible: true;
|
||||
offline-reason: root.library-offline-reason;
|
||||
offline-since: root.library-offline-since;
|
||||
retry-connection() => { root.library-retry-connection(); }
|
||||
local-only: root.library-local-only;
|
||||
local-count: root.library-local-count;
|
||||
toggle-local-only() => { root.library-toggle-local-only(); }
|
||||
local-only: Library.library-local-only;
|
||||
local-count: Library.library-local-count;
|
||||
toggle-local-only() => { Library.library-toggle-local-only(); }
|
||||
range-active: root.library-range-active;
|
||||
toggle-date-range() => { root.library-toggle-date-range(); }
|
||||
clear-selection() => { root.library-clear-selection(); }
|
||||
select-all() => { root.library-select-all(); }
|
||||
reorderable: root.library-reorderable;
|
||||
reorder-to(row, after) => { root.library-reorder-to(row, after); }
|
||||
clear-selection() => { Library.library-clear-selection(); }
|
||||
select-all() => { Library.library-select-all(); }
|
||||
reorderable: Library.library-reorderable;
|
||||
reorder-to(row, after) => { Library.library-reorder-to(row, after); }
|
||||
collection-from-selection(name) => {
|
||||
root.library-collection-from-selection(name);
|
||||
Library.library-collection-from-selection(name);
|
||||
}
|
||||
range-from: root.library-range-from;
|
||||
range-to: root.library-range-to;
|
||||
@@ -1653,7 +1546,7 @@ in property <bool> panel-visible: true;
|
||||
timeline-label: root.library-timeline-label;
|
||||
window-label: root.library-window-label;
|
||||
offset: root.library-offset;
|
||||
selected-count: root.library-selected-count;
|
||||
selected-count: Library.library-selected-count;
|
||||
scope-label: Collections.collection-scope-label;
|
||||
settings-armed: Transfer.armed;
|
||||
paste-settings-to-selection => {
|
||||
@@ -1664,7 +1557,7 @@ in property <bool> panel-visible: true;
|
||||
// sheet says it would act on and what the apply handler
|
||||
// reads back to decide it means the batch.
|
||||
open-presets => {
|
||||
root.preset-apply-count = root.library-selected-count;
|
||||
root.preset-apply-count = Library.library-selected-count;
|
||||
root.preset-can-save = false;
|
||||
root.presets-open = true;
|
||||
}
|
||||
@@ -1689,23 +1582,23 @@ in property <bool> panel-visible: true;
|
||||
timeline-pan(d) => { root.library-timeline-pan(d); }
|
||||
timeline-zoom(d) => { root.library-timeline-zoom(d); }
|
||||
syncing: root.library-syncing;
|
||||
requested-cell-size: root.library-cell-size;
|
||||
touched <=> root.library-touched;
|
||||
zoom-cells(d) => { root.library-zoom-cells(d); }
|
||||
pinch-cells(r) => { root.library-pinch-cells(r); }
|
||||
pinch-started() => { root.library-pinch-started(); }
|
||||
scroll-to: root.library-scroll-to;
|
||||
scroll-token: root.library-scroll-token;
|
||||
requested-cell-size: Library.library-cell-size;
|
||||
touched <=> Library.library-touched;
|
||||
zoom-cells(d) => { Library.library-zoom-cells(d); }
|
||||
pinch-cells(r) => { Library.library-pinch-cells(r); }
|
||||
pinch-started() => { Library.library-pinch-started(); }
|
||||
scroll-to: Library.library-scroll-to;
|
||||
scroll-token: Library.library-scroll-token;
|
||||
sync-now() => { root.library-sync-now(); }
|
||||
columns-changed(n) => {
|
||||
root.library-columns = n;
|
||||
Library.library-columns = n;
|
||||
// Which cell begins a row just changed, and month headings sit on
|
||||
// row-leading cells — so they must be recomputed, not just moved.
|
||||
root.library-columns-changed();
|
||||
Library.library-columns-changed();
|
||||
}
|
||||
scrolled(i) => { root.library-scrolled(i); }
|
||||
viewport-cells-changed(n) => { root.library-viewport-cells(n); }
|
||||
cell-clicked(i) => { root.library-cell-clicked(i); }
|
||||
scrolled(i) => { Library.library-scrolled(i); }
|
||||
viewport-cells-changed(n) => { Library.library-viewport-cells(n); }
|
||||
cell-clicked(i) => { Library.library-cell-clicked(i); }
|
||||
rescan() => { root.library-rescan(); }
|
||||
can-import: root.import-supported;
|
||||
open-import() => { root.import-open(); }
|
||||
@@ -1713,35 +1606,35 @@ in property <bool> panel-visible: true;
|
||||
open-people() => { root.identity-open(); }
|
||||
|
||||
cell-pressed(i, ctrl, shift) => {
|
||||
root.library-cell-pressed(i, ctrl, shift);
|
||||
Library.library-cell-pressed(i, ctrl, shift);
|
||||
}
|
||||
cell-press-ended() => { root.library-cell-press-ended(); }
|
||||
select-mode: root.library-select-mode;
|
||||
toggle-select-mode() => { root.library-toggle-select-mode(); }
|
||||
held-row <=> root.library-held-row;
|
||||
cell-press-ended() => { Library.library-cell-press-ended(); }
|
||||
select-mode: Library.library-select-mode;
|
||||
toggle-select-mode() => { Library.library-toggle-select-mode(); }
|
||||
held-row <=> Library.library-held-row;
|
||||
// The sidebar's rows, not a second model: the sheet files
|
||||
// into the same tree the sidebar draws.
|
||||
collections: Collections.collection-rows;
|
||||
file-in-collection(id, moves) => {
|
||||
root.library-file-in-collection(id, moves);
|
||||
Library.library-file-in-collection(id, moves);
|
||||
}
|
||||
keywords: root.library-keywords;
|
||||
keywords-opened() => { root.library-keywords-opened(); }
|
||||
assign-keyword(word) => { root.library-assign-keyword(word); }
|
||||
unassign-keyword(word) => { root.library-unassign-keyword(word); }
|
||||
cursor: root.library-cursor;
|
||||
cursor: Library.library-cursor;
|
||||
move-cursor(delta, extend) => {
|
||||
root.library-move-cursor(delta, extend);
|
||||
Library.library-move-cursor(delta, extend);
|
||||
}
|
||||
open-cursor() => { root.library-open-cursor(); }
|
||||
drag-image: root.library-drag-image;
|
||||
drag-payload() => { return root.library-drag-payload(); }
|
||||
drag-started(i) => { root.library-drag-started(i); }
|
||||
drag-finished() => { root.library-drag-finished(); }
|
||||
open-cursor() => { Library.library-open-cursor(); }
|
||||
drag-image: Library.library-drag-image;
|
||||
drag-payload() => { return Library.library-drag-payload(); }
|
||||
drag-started(i) => { Library.library-drag-started(i); }
|
||||
drag-finished() => { Library.library-drag-finished(); }
|
||||
remove-from-collection() => {
|
||||
root.library-remove-from-collection();
|
||||
Library.library-remove-from-collection();
|
||||
}
|
||||
open-membership() => { root.library-open-membership(); }
|
||||
open-membership() => { Library.library-open-membership(); }
|
||||
|
||||
filter-people: root.library-filter-people;
|
||||
filter-people-all: root.library-filter-people-all;
|
||||
@@ -1805,7 +1698,7 @@ in property <bool> panel-visible: true;
|
||||
position: root.total > 0 ? root.index + 1 + " / " + root.total : "";
|
||||
// Only where a library was opened; command-line files have no
|
||||
// grid to return to.
|
||||
can-return-to-library: root.library-total > 0;
|
||||
can-return-to-library: Library.library-total > 0;
|
||||
panel-visible: root.panel-visible;
|
||||
export-label: root.export-label;
|
||||
export-busy: root.export-busy;
|
||||
@@ -2657,7 +2550,7 @@ in property <bool> panel-visible: true;
|
||||
// instead — the controls ride on top of the roll's
|
||||
// band, at whatever height it currently stands.
|
||||
property <length> roll-clear:
|
||||
root.library-total > 0
|
||||
Library.library-total > 0
|
||||
? (root.roll-open
|
||||
? Theme.roll-strip + Theme.roll-reach
|
||||
: Theme.roll-reach)
|
||||
@@ -2770,14 +2663,14 @@ in property <bool> panel-visible: true;
|
||||
//
|
||||
// Last in the canvas, so it draws over the photograph
|
||||
// rather than under it.
|
||||
if root.library-total > 0: PhotoRoll {
|
||||
if Library.library-total > 0: PhotoRoll {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cells: root.library-cells;
|
||||
current: root.library-roll-current;
|
||||
cells: Library.library-cells;
|
||||
current: Library.library-roll-current;
|
||||
open <=> root.roll-open;
|
||||
centre-request <=> root.library-roll-centre;
|
||||
pick(i) => { root.library-roll-pick(i); }
|
||||
centre-request <=> Library.library-roll-centre;
|
||||
pick(i) => { Library.library-roll-pick(i); }
|
||||
}
|
||||
|
||||
// Report size changes so the render target can be resized to
|
||||
@@ -3179,7 +3072,7 @@ in property <bool> panel-visible: true;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
open: Collections.membership-open;
|
||||
selected-count: root.library-selected-count;
|
||||
selected-count: Library.library-selected-count;
|
||||
rows: Collections.membership-rows;
|
||||
remove(id) => { Collections.membership-remove(id); }
|
||||
dismiss() => { Collections.membership-dismiss(); }
|
||||
|
||||
@@ -479,6 +479,129 @@ export struct LibraryCell {
|
||||
burst-representative: bool,
|
||||
}
|
||||
|
||||
// TRACES: FR-CAT-3 | FR-CAT-4 | FR-CAT-5 | FR-CAT-6 | FR-CAT-7 | FR-CULL-4 | FR-CULL-5
|
||||
// The library grid's own state: the loaded window of cells, the selection,
|
||||
// the timeline, the filter bar, ratings and flags, keywording, drag and drop,
|
||||
// and the routes into and out of the screen.
|
||||
//
|
||||
// A global rather than properties and callbacks on the window root — see
|
||||
// `session.slint` for why the develop panels stopped taking their wiring
|
||||
// through the window root, and `collections.slint` for the sidebar's own
|
||||
// global; the same reasoning applies here. What is shared with the sidebar
|
||||
// (the collection the grid is scoped to, whether the sidebar is shown) stays
|
||||
// on the window, because `run()`'s panel-layout wiring and the sidebar's own
|
||||
// Rust still reach it there.
|
||||
export global Library {
|
||||
in-out property <[LibraryCell]> library-cells;
|
||||
in property <int> library-total: 0;
|
||||
// Narrows the grid to images whose RAW is stored locally — the ones that
|
||||
// can actually be opened while offline. Off by default: the catalog is the
|
||||
// library, and hiding most of it the moment a connection drops would read
|
||||
// as data loss rather than as a filter.
|
||||
in-out property <bool> library-local-only: false;
|
||||
in property <int> library-local-count: 0;
|
||||
callback library-toggle-local-only();
|
||||
/// TRACES: FR-CAT-5
|
||||
callback library-clear-selection();
|
||||
callback library-select-all();
|
||||
/// TRACES: FR-CAT-7
|
||||
/// Whether the grid is showing something with a manual order to change —
|
||||
/// a single manual collection, not a set and not a saved filter.
|
||||
in property <bool> library-reorderable: false;
|
||||
/// Move the selection beside the photograph at this row of the loaded
|
||||
/// window: after it where the drop landed on the cell's trailing half,
|
||||
/// before it otherwise.
|
||||
callback library-reorder-to(int, bool);
|
||||
callback library-collection-from-selection(string);
|
||||
in-out property <int> library-columns: 1;
|
||||
in-out property <length> library-cell-size: 180px;
|
||||
/// Whether this session is a touch one, which decides if the rating strip
|
||||
/// waits to be hovered or stands open. Seeded from the platform by Rust
|
||||
/// and latched by the grid on the first finger it sees.
|
||||
in-out property <bool> library-touched: false;
|
||||
callback library-zoom-cells(int);
|
||||
/// A pinch step on the grid: the ratio since the last update.
|
||||
callback library-pinch-cells(float);
|
||||
/// A pinch on the grid has begun, so the press that opened it was not one.
|
||||
callback library-pinch-started();
|
||||
in property <int> library-scroll-to: 0;
|
||||
in property <int> library-scroll-token: 0;
|
||||
/// Which row of the loaded window is the photograph currently open in
|
||||
/// develop, so the roll can mark it. `-1` when it is not in the window.
|
||||
in property <int> library-roll-current: -1;
|
||||
/// Centre the roll on the open photograph the next time the strip settles.
|
||||
///
|
||||
/// Raised by Rust when a develop session begins — a photograph opened from
|
||||
/// the grid — and cleared by the strip itself once honoured. Owned here for
|
||||
/// the same reason `roll-open` is: the develop view is rebuilt whenever an
|
||||
/// overlay screen covers it, and a request raised before that must survive
|
||||
/// it. See `PhotoRoll::centre-request`.
|
||||
in-out property <bool> library-roll-centre: false;
|
||||
/// A photograph was chosen from the roll: the row within the loaded
|
||||
/// window, which is what a cell click reports too.
|
||||
callback library-roll-pick(int);
|
||||
callback library-columns-changed();
|
||||
callback library-scrolled(int);
|
||||
/// How many cells the grid's viewport shows at once. Rust sizes the
|
||||
/// loaded window from it — see `library_ui::window_move`.
|
||||
callback library-viewport-cells(int);
|
||||
callback library-cell-clicked(int);
|
||||
/// TRACES: FR-CAT-7 | FR-UI-4
|
||||
/// File the grid's selection in a collection without dragging it there:
|
||||
/// the target's id, and whether to take the images out of the collection
|
||||
/// currently being shown.
|
||||
callback library-file-in-collection(int, bool);
|
||||
/// TRACES: FR-UI-2
|
||||
/// Whether a tap in the grid selects rather than opens, and the button
|
||||
/// that turns it on. The long press does the same thing without it.
|
||||
in property <bool> library-select-mode: false;
|
||||
callback library-toggle-select-mode();
|
||||
/// TRACES: FR-CAT-7 | FR-UI-4
|
||||
/// The row a press has held long enough to pick up, or `-1`.
|
||||
///
|
||||
/// Set by the same hold that turns on selection mode and cleared by the
|
||||
/// grid when the press ends — `in-out` because both ends write it. See
|
||||
/// `held-row` in `library.slint` for what it draws and what it stops.
|
||||
in-out property <int> library-held-row: -1;
|
||||
/// A press on a cell ended, so the long-press timer can be cancelled.
|
||||
callback library-cell-press-ended();
|
||||
// --- drag and drop ---
|
||||
//
|
||||
// Slint's own `DragArea`/`DropArea` carry this: pointer capture, the
|
||||
// click-versus-drag threshold, arbitration against the grid's Flickable,
|
||||
// and the image drawn under the cursor. So there is no badge to position
|
||||
// and no hover state to mirror here — only the payload, which Rust builds
|
||||
// from the selection, and the count the header shows.
|
||||
/// The drag payload, built by Rust from the current selection.
|
||||
pure callback library-drag-payload() -> data-transfer;
|
||||
/// The bitmap that travels under the cursor: one thumbnail, or a fanned
|
||||
/// stack where several images are being dragged. Composited in Rust.
|
||||
in property <image> library-drag-image;
|
||||
/// A drag began on a cell, so an unselected one can be promoted before the
|
||||
/// payload is read.
|
||||
callback library-drag-started(int);
|
||||
callback library-drag-finished();
|
||||
in property <int> library-selected-count: 0;
|
||||
|
||||
callback library-cell-pressed(int, bool, bool);
|
||||
callback library-remove-from-collection();
|
||||
// --- where the selection is filed (FR-CAT-7) ---------------------------
|
||||
//
|
||||
// `library-remove-from-collection` can only ever mean the collection the
|
||||
// grid is scoped to — it is the only one that button can name. Opens the
|
||||
// membership sheet, whose state (`Collections.membership-open` and
|
||||
// `.membership-rows`) is on the sidebar's own global — only the library
|
||||
// side knows the selection has changed enough to be worth recomputing
|
||||
// the sheet against.
|
||||
callback library-open-membership();
|
||||
// The keyboard cursor: where the arrows are in the library, as an image
|
||||
// ordinal. Rust owns it — clamping it needs the library's length, and
|
||||
// moving it may have to swap the loaded window underneath.
|
||||
in property <int> library-cursor: -1;
|
||||
callback library-move-cursor(int, bool);
|
||||
callback library-open-cursor();
|
||||
}
|
||||
|
||||
// The photo roll: the grid's loaded window along the foot of the develop view.
|
||||
//
|
||||
// # Why this exists
|
||||
|
||||
Reference in New Issue
Block a user