aboutsummaryrefslogtreecommitdiff
path: root/gui/internal/ui/plan.go
diff options
context:
space:
mode:
Diffstat (limited to 'gui/internal/ui/plan.go')
-rw-r--r--gui/internal/ui/plan.go58
1 files changed, 50 insertions, 8 deletions
diff --git a/gui/internal/ui/plan.go b/gui/internal/ui/plan.go
index fd2f563..f6f2952 100644
--- a/gui/internal/ui/plan.go
+++ b/gui/internal/ui/plan.go
@@ -112,7 +112,7 @@ func newPlanView(w *Window) *planView {
panes.SetResizeStartChild(true)
panes.SetResizeEndChild(false)
panes.SetShrinkEndChild(false)
- panes.SetPosition(640)
+ panes.SetPosition(780)
panes.SetVExpand(true)
p.root.Append(bar)
@@ -346,15 +346,37 @@ func (p *planView) fillList() {
if p.tab == nil {
return
}
+ w := p.widths()
for i, r := range p.tab.Rows {
- p.list.Append(p.rowWidget(i, r))
+ p.list.Append(p.rowWidget(i, r, w))
}
p.apply.SetLabel(fmt.Sprintf("Apply %d selected", p.tab.SelectedCount()))
p.apply.SetSensitive(!p.tab.Applied && p.tab.SelectedCount() > 0)
}
+// widths is how wide each column has to be for this plan: enough for the
+// longest value it holds, within limits, so a rule name or an outcome is
+// shown whole rather than cut to an ellipsis. The list scrolls sideways
+// when the total does not fit (his report, 2026-09-16).
+func (p *planView) widths() [4]int {
+ w := [4]int{16, 16, 8, 6}
+ root := p.dirRoot()
+ for _, r := range p.tab.Rows {
+ w[0] = max(w[0], len([]rune(r.Rel)))
+ w[1] = max(w[1], len([]rune(rowLabel(r, root))))
+ w[2] = max(w[2], len([]rune(r.Rule)))
+ w[3] = max(w[3], len([]rune(r.Outcome)))
+ }
+ // Past these a single long value would push every other column off the
+ // window; the details pane holds the whole text either way.
+ for i, cap := range [4]int{40, 52, 34, 24} {
+ w[i] = min(w[i], cap)
+ }
+ return w
+}
+
// rowWidget is one line of the list.
-func (p *planView) rowWidget(i int, r model.Row) *gtk.ListBoxRow {
+func (p *planView) rowWidget(i int, r model.Row, w [4]int) *gtk.ListBoxRow {
box := gtk.NewBox(gtk.OrientationHorizontal, 8)
box.SetMarginStart(6)
box.SetMarginEnd(6)
@@ -373,11 +395,14 @@ func (p *planView) rowWidget(i int, r model.Row) *gtk.ListBoxRow {
})
box.Append(check)
- box.Append(column(escape(r.Rel), 24, true))
- box.Append(column(escape(rowLabel(r, p.dirRoot())), 30, false))
- box.Append(column(escape(r.Rule), 12, false))
+ // The name and what-would-happen columns share whatever space is left
+ // and shrink first; the rule keeps its width, so it is never the column
+ // cut to an ellipsis.
+ box.Append(column(escape(r.Rel), w[0], true))
+ box.Append(columnMin(escape(rowLabel(r, p.dirRoot())), w[1], 18, true))
+ box.Append(column(escape(r.Rule), w[2], false))
if r.Outcome != "" {
- box.Append(column(escape(r.Outcome), 12, false))
+ box.Append(column(escape(r.Outcome), w[3], false))
}
row := gtk.NewListBoxRow()
row.SetChild(box)
@@ -395,17 +420,34 @@ func (p *planView) dirRoot() string {
// column is one cell of a row: left-aligned, and ellipsized to chars so
// that a long name or warning cannot widen the window past the screen. The
// whole text is in the details pane beside the list.
+//
+// The expanding column - the file's name - may shrink to yieldChars when
+// the window is too narrow for every column, so it is the one that gives
+// way and the columns beside it (what would happen, and which rule decided)
+// stay readable. A fixed column keeps its width and the list scrolls.
func column(text string, chars int, expand bool) *gtk.Label {
+ return columnMin(text, chars, yieldChars, expand)
+}
+
+// columnMin is column with the width it may shrink to given explicitly.
+func columnMin(text string, chars, floor int, expand bool) *gtk.Label {
l := gtk.NewLabel(text)
l.SetXAlign(0)
l.SetEllipsize(pango.EllipsizeEnd)
- l.SetWidthChars(chars)
+ if expand {
+ l.SetWidthChars(min(chars, floor))
+ } else {
+ l.SetWidthChars(chars)
+ }
l.SetMaxWidthChars(chars)
l.SetHExpand(expand)
l.SetTooltipText(text)
return l
}
+// yieldChars is how narrow an expanding column may become.
+const yieldChars = 14
+
// showDetails writes the selected file's steps and warnings into the pane.
func (p *planView) showDetails(i int) {
if p.tab == nil || i < 0 || i >= len(p.tab.Rows) {