Move copy, paste and presets into the develop top bar

They sat in the develop column under a "SETTINGS" heading, which read as
application settings, and went away with the panel toggle and in the
mask and spot modes. The strip is where undo already is for the same
reason: these act on the whole edit, not on any one panel.

The paste button still names what it would apply. The TransferPanel
component is gone; the Transfer global and its Rust wiring are
unchanged.
This commit is contained in:
2026-09-22 21:37:31 -04:00
parent aee355fada
commit 9ebaa15099
7 changed files with 83 additions and 115 deletions
-58
View File
@@ -886,64 +886,6 @@ export global Transfer {
callback open-presets();
}
// TRACES: FR-DEV-6
// Copying this photograph's settings, and pasting settings onto it.
//
// Buttons rather than a keyboard shortcut *alone*, because this has to work on
// a tablet where there is no modifier key to hold and no menu bar to hang the
// action from. The desktop shortcuts exist as well, wired in Rust; they are an
// accelerator for a control that is on screen either way, which is what keeps
// the feature discoverable on both platforms.
//
// The paste button carries what would be pasted rather than the bare word.
// "Paste" alone asks the user to remember what they copied and, crucially,
// whether the crop is coming with it — a question the label answers by
// naming the count the *current* scope would apply.
export component TransferPanel inherits VerticalLayout {
padding: Theme.gap;
spacing: Theme.gap-sm;
HorizontalLayout {
PanelHeading { text: "SETTINGS"; }
Rectangle { horizontal-stretch: 1; }
}
HorizontalLayout {
spacing: Theme.gap-sm;
Button {
text: "Copy";
enabled: Develop.enabled;
horizontal-stretch: 1;
clicked => { Transfer.copy(); }
}
Button {
text: "Paste";
// Enabled on `armed` rather than on the summary being non-empty,
// so pasting a neutral copy — which clears this image — stays
// available. Still needs an image to paste *onto*.
enabled: Develop.enabled && Transfer.armed;
horizontal-stretch: 1;
clicked => { Transfer.paste(); }
}
}
// TRACES: FR-DEV-6
// The saved half. On its own row rather than a third of the one above,
// because copy and paste are a pair — one arms the other — and a button
// that does neither sitting between them would read as part of that pair.
Button {
text: "Presets…";
enabled: Develop.enabled;
clicked => { Transfer.open-presets(); }
}
if Transfer.armed: Caption {
text: Transfer.summary + (Transfer.framing-withheld ? " · crop not included" : "");
}
}
/// TRACES: FR-DEV-3
/// The generated controls: what they show, what they are pointed at, and what
/// pressing one means.
+8 -21
View File
@@ -1,6 +1,6 @@
import { Theme } from "theme.slint";
import { Develop, ViewMode } from "session.slint";
import { AdjustPanel, Adjustments, ComposePanel, Framing, GroupStrip, ParamRow, Transfer, TransferPanel } from "adjust.slint";
import { AdjustPanel, Adjustments, ComposePanel, Framing, GroupStrip, ParamRow, Transfer } from "adjust.slint";
import { CategoryRow, GradientHandle, GradientHandles, HandleRole, MaskPanel, MaskRow, Masking, SubjectRow } from "masks.slint";
import { Repair, SpotHandle, SpotHandles, SpotPanel, SpotRole } from "spots.slint";
import { CropOverlay } from "crop.slint";
@@ -2205,10 +2205,10 @@ in property <bool> panel-visible: true;
}
// GESTURE: Copy the settings from this photograph
// where: Develop
// touch: Press Copy in the Settings panel
// pointer: Press Copy in the Settings panel
// touch: Press Copy in the top bar
// pointer: Press Copy in the top bar
// keys: Ctrl+C
// why: The panel is the copy that has to
// why: The button is the copy that has to
// work: a tablet has no modifier key
// to hold and no menu bar to hang the
// action from. The shortcut is an
@@ -2217,8 +2217,8 @@ in property <bool> panel-visible: true;
//
// GESTURE: Paste the settings onto this photograph
// where: Develop
// touch: Press Paste in the Settings panel
// pointer: Press Paste in the Settings panel
// touch: Press Paste in the top bar
// pointer: Press Paste in the top bar
// keys: Ctrl+V
// why: The button names what would be
// pasted — "3 adjustments", and
@@ -2227,9 +2227,8 @@ in property <bool> panel-visible: true;
// paste the same scope.
//
// TRACES: FR-DEV-6
// The desktop accelerators for the two buttons in
// the Settings panel, which until now the panel's
// own comment claimed existed and nothing bound.
// The desktop accelerators for the Copy and Paste
// buttons in the top bar.
// Guarded on `settings-armed` for the reason the
// button is: a paste with nothing copied is not a
// clear, it is a keystroke that should do nothing.
@@ -2741,18 +2740,6 @@ in property <bool> panel-visible: true;
// `dr_pipeline::framing` on the coordinate order).
if !Develop.local-mode && !Develop.repairing: ComposePanel { }
if !Develop.local-mode && !Develop.repairing: Rectangle {
height: 1px;
background: Theme.rule;
}
// Between the framing and the colour work, because it
// acts on both: a paste is about the whole edit, and
// burying it under thirty sliders would put the one
// control that operates on all of them below all of
// them.
if !Develop.local-mode && !Develop.repairing: TransferPanel { }
Rectangle {
height: 1px;
background: Theme.rule;
+38
View File
@@ -8,6 +8,8 @@
// front of it.
import { Theme } from "theme.slint";
import { Develop } from "session.slint";
import { Transfer } from "adjust.slint";
import { Button, PanelHeading, Label, Value, Caption, Panel } from "widgets.slint";
// Status strip — surfaces the GPU backend and adapter, which matters during
@@ -160,6 +162,42 @@ export component StatusBar inherits Rectangle {
clicked => { root.redo(); }
}
// TRACES: FR-DEV-6
// Copy and paste, in the strip beside undo for the reason undo is
// here: they act on the whole edit, not on any one panel, and the
// column can be put away. They sat in the column under a "SETTINGS"
// heading, which read as application settings and hid them behind a
// scroll and behind the panel toggle.
//
// The paste button names what would be pasted — "3 adjustments", and
// whether the crop is staying behind — because "Paste" alone asks the
// user to remember what they copied.
Button {
text: "Copy";
enabled: Develop.enabled;
y: (parent.height - self.height) / 2;
clicked => { Transfer.copy(); }
}
// Enabled on `armed` rather than on a non-empty summary, so pasting a
// neutral copy — which clears this image — stays available.
Button {
text: !Transfer.armed ? "Paste"
: "Paste " + Transfer.summary
+ (Transfer.framing-withheld ? ", no crop" : "");
enabled: Develop.enabled && Transfer.armed;
y: (parent.height - self.height) / 2;
clicked => { Transfer.paste(); }
}
// The saved half: this edit, kept under a name.
Button {
text: "Presets…";
enabled: Develop.enabled;
y: (parent.height - self.height) / 2;
clicked => { Transfer.open-presets(); }
}
// Show or hide the develop column. On a tablet the panel is 280px of a
// screen that is mostly photograph, and the whole point of opening an
// image is to look at it — so being able to put the instruments away