diff --git a/ui/dr-ui/ui/masks.slint b/ui/dr-ui/ui/masks.slint index 1851779..aacccea 100644 --- a/ui/dr-ui/ui/masks.slint +++ b/ui/dr-ui/ui/masks.slint @@ -137,10 +137,18 @@ component MaskEntry inherits Rectangle { alignment: center; spacing: 0px; + // Both lines below are bounded for the reason the subject + // row is: a mask's label and kind come from the model, and an + // unbounded `Text` asks for its whole string at layout time + // even when `elide` means it will never draw it. A mask *is* a + // segmentation result, so without this the column moved when a + // subject was clicked as well as when one was found. Label { text: root.data.label; emphasised: root.data.selected || touch.has-hover; overflow: elide; + min-width: 0px; + max-width: 160px; } Caption { @@ -148,6 +156,8 @@ component MaskEntry inherits Rectangle { // targets in a row, and wrapping would give the rows of a // stack different heights for no gain. overflow: elide; + min-width: 0px; + max-width: 160px; // Three states worth distinguishing, and each has a // different remedy: stale needs the segmentation re-run, // unadjusted needs a slider moved, and the ordinary case @@ -418,6 +428,30 @@ export component MaskPanel inherits Rectangle { emphasised: subject-row.has-hover; horizontal-stretch: 1; overflow: elide; + // **`elide` is a paint-time behaviour, and this is a + // layout-time problem.** A `Text` asks for the width of + // its whole string whether or not it will draw all of + // it, so without a stated maximum this row asked for + // whatever the model happened to return, that became + // `layout.preferred-width`, the panel publishes that as + // its `min-width`, and the develop column takes the + // widest minimum any panel declares. The column + // therefore moved the instant segmentation finished — + // a photograph the user was looking at, jumping + // sideways because a label said "traffic light". + // + // Stated as a maximum for the reason `ChipGrid` + // declares its width from its column count rather than + // from its options: what a panel asks for must follow + // from its structure, never from its data. Past this + // the row elides, which is what `elide` was for. + // + // 160px is the same judgement as `ChipGrid`'s 88px + // chip — comfortable for the class names this model + // returns, and narrow enough that a subject list + // cannot be what sets the column. + min-width: 0px; + max-width: 160px; } Value { text: round(subject.score * 100) + "%"; } }