diff --git a/ui/dr-ui/ui/app.slint b/ui/dr-ui/ui/app.slint index adea532..8460f8e 100644 --- a/ui/dr-ui/ui/app.slint +++ b/ui/dr-ui/ui/app.slint @@ -1839,156 +1839,161 @@ in property panel-visible: true; // the column instead. // Pinned: the strip is how the column is navigated, so it // cannot be somewhere you have to navigate to. - GroupStrip { - enabled: root.adjust-enabled; - tabs: root.adjust-tabs; - active-tab: root.adjust-active-tab; - picked(i) => { root.adjust-tab-picked(i); } - } - - Flickable { - viewport-height: column.preferred-height; - interactive: !adjust.slider-dragging; - - column := VerticalLayout { - InfoPanel { - camera: root.camera; - exposure: root.exposure; - dimensions: root.dimensions; - } - - Rectangle { - height: 1px; - background: Theme.rule; - } - - // Directly under the capture metadata and above every - // control, because it is the thing the controls are - // judged against: exposure, blacks and whites are all - // set by watching this move (FR-DSP-7). An instrument - // below the sliders it reports on would have the - // photographer looking away from it to use it. - HistogramPanel { - data: root.histogram; - } - - Rectangle { - height: 1px; - background: Theme.rule; - } - - // Framing above the colour work, matching how the edit is - // made rather than how it is applied: the frame is decided - // by eye first and the pipeline runs it last (see - // `dr_pipeline::framing` on the coordinate order). - GeometryPanel { + // A layout, because the parent is a Rectangle: two children of one + // would both sit at its origin and overlap. The strip is pinned by + // being outside the Flickable rather than by any coordinate. + VerticalLayout { + GroupStrip { enabled: root.adjust-enabled; - crop-mode: root.crop-mode; - angle: root.straighten; - max-straighten: root.max-straighten; - flip-h: root.flip-h; - flip-v: root.flip-v; - modified: root.framing-modified; - - crop-toggled(on) => { root.crop-mode-toggled(on); } - rotate(turns) => { root.rotate-quarters(turns); } - flip-h-toggled => { root.flip-h-toggled(); } - flip-v-toggled => { root.flip-v-toggled(); } - angle-changed(v) => { root.straighten-changed(v); } - angle-reset => { root.straighten-changed(0); } - reset => { root.framing-reset(); } + tabs: root.adjust-tabs; + active-tab: root.adjust-active-tab; + picked(i) => { root.adjust-tab-picked(i); } } - Rectangle { - height: 1px; - background: Theme.rule; - } + Flickable { + viewport-height: column.preferred-height; + interactive: !adjust.slider-dragging; - // 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. - TransferPanel { - enabled: root.adjust-enabled; - armed: root.settings-armed; - summary: root.settings-summary; - framing-withheld: root.settings-framing-withheld; - copy => { root.copy-settings(); } - paste => { root.paste-settings(); } - } + column := VerticalLayout { + InfoPanel { + camera: root.camera; + exposure: root.exposure; + dimensions: root.dimensions; + } - Rectangle { - height: 1px; - background: Theme.rule; - } + Rectangle { + height: 1px; + background: Theme.rule; + } - // Above the adjust panel, because it decides what - // those sliders act on. Below it, the photographer - // would set an exposure and only then discover which - // scope it landed in. - MaskPanel { - enabled: root.adjust-enabled; - masks: root.mask-rows; - subjects: root.subject-rows; - segmented: root.segmented; - segmenting: root.segmenting; - overlay: root.overlay-on; - picking: root.region-picking; - editing-mask: root.editing-mask; + // Directly under the capture metadata and above every + // control, because it is the thing the controls are + // judged against: exposure, blacks and whites are all + // set by watching this move (FR-DSP-7). An instrument + // below the sliders it reports on would have the + // photographer looking away from it to use it. + HistogramPanel { + data: root.histogram; + } - segment => { root.segment-image(); } - overlay-toggled(on) => { root.overlay-toggled(on); } - picking-toggled(on) => { root.region-picking-toggled(on); } - mask-selected(id) => { root.mask-selected(id); } - mask-removed(id) => { root.mask-removed(id); } - mask-toggled(id, on) => { root.mask-toggled(id, on); } - mask-invert-toggled(id, on) => { - root.mask-invert-toggled(id, on); + Rectangle { + height: 1px; + background: Theme.rule; } - mask-opacity-changed(id, v) => { - root.mask-opacity-changed(id, v); - } - mask-feather-changed(id, v) => { - root.mask-feather-changed(id, v); - } - mask-falloff-picked(id, i) => { - root.mask-falloff-picked(id, i); - } - mask-morphology-picked(id, i) => { - root.mask-morphology-picked(id, i); - } - mask-morph-radius-changed(id, v) => { - root.mask-morph-radius-changed(id, v); - } - add-gradient(radial) => { root.add-gradient-mask(radial); } - add-subject(i) => { root.add-subject-mask(i); } - } - Rectangle { - height: 1px; - background: Theme.rule; - } + // Framing above the colour work, matching how the edit is + // made rather than how it is applied: the frame is decided + // by eye first and the pipeline runs it last (see + // `dr_pipeline::framing` on the coordinate order). + GeometryPanel { + enabled: root.adjust-enabled; + crop-mode: root.crop-mode; + angle: root.straighten; + max-straighten: root.max-straighten; + flip-h: root.flip-h; + flip-v: root.flip-v; + modified: root.framing-modified; - adjust := AdjustPanel { - rows: root.adjust-rows; - enabled: root.adjust-enabled; - curve-samples: root.curve-samples; - param-changed(op, param, value) => { - root.param-changed(op, param, value); + crop-toggled(on) => { root.crop-mode-toggled(on); } + rotate(turns) => { root.rotate-quarters(turns); } + flip-h-toggled => { root.flip-h-toggled(); } + flip-v-toggled => { root.flip-v-toggled(); } + angle-changed(v) => { root.straighten-changed(v); } + angle-reset => { root.straighten-changed(0); } + reset => { root.framing-reset(); } + } + + 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. + TransferPanel { + enabled: root.adjust-enabled; + armed: root.settings-armed; + summary: root.settings-summary; + framing-withheld: root.settings-framing-withheld; + copy => { root.copy-settings(); } + paste => { root.paste-settings(); } + } + + Rectangle { + height: 1px; + background: Theme.rule; + } + + // Above the adjust panel, because it decides what + // those sliders act on. Below it, the photographer + // would set an exposure and only then discover which + // scope it landed in. + MaskPanel { + enabled: root.adjust-enabled; + masks: root.mask-rows; + subjects: root.subject-rows; + segmented: root.segmented; + segmenting: root.segmenting; + overlay: root.overlay-on; + picking: root.region-picking; + editing-mask: root.editing-mask; + + segment => { root.segment-image(); } + overlay-toggled(on) => { root.overlay-toggled(on); } + picking-toggled(on) => { root.region-picking-toggled(on); } + mask-selected(id) => { root.mask-selected(id); } + mask-removed(id) => { root.mask-removed(id); } + mask-toggled(id, on) => { root.mask-toggled(id, on); } + mask-invert-toggled(id, on) => { + root.mask-invert-toggled(id, on); + } + mask-opacity-changed(id, v) => { + root.mask-opacity-changed(id, v); + } + mask-feather-changed(id, v) => { + root.mask-feather-changed(id, v); + } + mask-falloff-picked(id, i) => { + root.mask-falloff-picked(id, i); + } + mask-morphology-picked(id, i) => { + root.mask-morphology-picked(id, i); + } + mask-morph-radius-changed(id, v) => { + root.mask-morph-radius-changed(id, v); + } + add-gradient(radial) => { root.add-gradient-mask(radial); } + add-subject(i) => { root.add-subject-mask(i); } + } + + Rectangle { + height: 1px; + background: Theme.rule; + } + + adjust := AdjustPanel { + rows: root.adjust-rows; + enabled: root.adjust-enabled; + curve-samples: root.curve-samples; + param-changed(op, param, value) => { + root.param-changed(op, param, value); + } + param-reset(op, param) => { + root.param-reset(op, param); + } + curve-reset(op) => { root.curve-reset(op); } + // A section's reset and a curve's reset are the same + // action — every parameter of one operation back to + // its default — so they share the one callback rather + // than duplicating a handler that would have to be + // kept in step with it. + op-reset(op) => { root.curve-reset(op); } + reset-all => { root.reset-all(); } } - param-reset(op, param) => { - root.param-reset(op, param); } - curve-reset(op) => { root.curve-reset(op); } - // A section's reset and a curve's reset are the same - // action — every parameter of one operation back to - // its default — so they share the one callback rather - // than duplicating a handler that would have to be - // kept in step with it. - op-reset(op) => { root.curve-reset(op); } - reset-all => { root.reset-all(); } - } } }