v0.23.3 fc8669a

modal_sizing.go RawHistoryFolder

1package component
2
3import (
4	"github.com/bnema/dumber/internal/ui/layout"
5	"github.com/jwijenbergh/puregotk/v4/gtk"
6)
7
8// ModalSizeConfig holds configuration for modal sizing calculations.
9type ModalSizeConfig struct {
10	WidthPct       float64 // Percentage of parent width (e.g., 0.6)
11	MaxWidth       int     // Maximum width in pixels
12	TopMarginPct   float64 // Top margin as percentage of parent height
13	FallbackWidth  int     // Fallback when parent not allocated
14	FallbackHeight int     // Fallback height
15}
16
17// RowHeightDefaults holds default (unscaled) row heights for list-based modals.
18// These are base pixel values that should be multiplied by UI scale.
19type RowHeightDefaults struct {
20	Standard int // Standard list row (e.g., session row, history row)
21	Compact  int // Compact row (e.g., tree row, sub-item)
22	Divider  int // Divider/separator row
23}
24
25// ListDisplayDefaults holds display limits for list-based modals.
26type ListDisplayDefaults struct {
27	MaxVisibleRows int // Maximum rows visible before scrolling
28	MaxResults     int // Maximum results to fetch/display
29}
30
31// Package-level defaults for row heights.
32var DefaultRowHeights = RowHeightDefaults{
33	Standard: 50,
34	Compact:  28,
35	Divider:  30,
36}
37
38// OmniboxSizeDefaults provides default sizing for omnibox modal.
39var OmniboxSizeDefaults = ModalSizeConfig{
40	WidthPct:       0.8,
41	MaxWidth:       800,
42	TopMarginPct:   0.2,
43	FallbackWidth:  800,
44	FallbackHeight: 600,
45}
46
47// OmniboxListDefaults provides display limits for omnibox modal.
48var OmniboxListDefaults = ListDisplayDefaults{
49	MaxVisibleRows: 10,
50	MaxResults:     10,
51}
52
53// SessionManagerSizeDefaults provides default sizing for session manager modal.
54var SessionManagerSizeDefaults = ModalSizeConfig{
55	WidthPct:       0.6,
56	MaxWidth:       600,
57	TopMarginPct:   0.15,
58	FallbackWidth:  600,
59	FallbackHeight: 600,
60}
61
62// SessionManagerListDefaults provides display limits for session manager modal.
63var SessionManagerListDefaults = ListDisplayDefaults{
64	MaxVisibleRows: 6,
65	MaxResults:     50,
66}
67
68// TabPickerSizeDefaults provides default sizing for tab picker modal.
69var TabPickerSizeDefaults = ModalSizeConfig{
70	WidthPct:       0.6,
71	MaxWidth:       600,
72	TopMarginPct:   0.15,
73	FallbackWidth:  600,
74	FallbackHeight: 600,
75}
76
77// TabPickerListDefaults provides display limits for tab picker modal.
78var TabPickerListDefaults = ListDisplayDefaults{
79	MaxVisibleRows: 8,
80	MaxResults:     20,
81}
82
83// CalculateModalDimensions computes width and top margin based on parent overlay.
84// Returns calculated width and top margin in pixels.
85func CalculateModalDimensions(parent layout.OverlayWidget, cfg ModalSizeConfig) (width, marginTop int) {
86	var parentWidth, parentHeight int
87
88	if parent != nil {
89		parentWidth = parent.GetAllocatedWidth()
90		parentHeight = parent.GetAllocatedHeight()
91	}
92
93	if parentWidth <= 0 {
94		parentWidth = cfg.FallbackWidth
95	}
96	if parentHeight <= 0 {
97		parentHeight = cfg.FallbackHeight
98	}
99
100	width = int(float64(parentWidth) * cfg.WidthPct)
101	if width > cfg.MaxWidth {
102		width = cfg.MaxWidth
103	}
104
105	marginTop = int(float64(parentHeight) * cfg.TopMarginPct)
106	return width, marginTop
107}
108
109// SetScrolledWindowHeight safely sets min/max content height on a ScrolledWindow.
110// Resets min to -1 first to avoid GTK assertion (min <= max) when shrinking.
111func SetScrolledWindowHeight(sw *gtk.ScrolledWindow, height int) {
112	if sw == nil {
113		return
114	}
115	sw.SetMinContentHeight(-1)
116	sw.SetMaxContentHeight(height)
117	sw.SetMinContentHeight(height)
118}
119
120// MeasureWidgetHeight returns the natural height of a widget for a given width.
121// Returns 0 if widget is nil or measurement fails.
122func MeasureWidgetHeight(widget *gtk.Widget, forWidth int) int {
123	if widget == nil {
124		return 0
125	}
126	var minH, natH int
127	widget.Measure(gtk.OrientationVerticalValue, forWidth, &minH, &natH, nil, nil)
128	return natH
129}
130
131// ScaleValue scales a base pixel value by UI scale factor.
132// Returns the base value if scale is <= 0.
133func ScaleValue(base int, uiScale float64) int {
134	if uiScale <= 0 {
135		uiScale = 1.0
136	}
137	return int(float64(base) * uiScale)
138}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close