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 // Use fallback if parent not allocated or too small to be useful
94 // A width < 100 is too small for any meaningful modal
95 if parentWidth < 100 {
96 parentWidth = cfg.FallbackWidth
97 }
98 if parentHeight < 100 {
99 parentHeight = cfg.FallbackHeight
100 }
101
102 width = int(float64(parentWidth) * cfg.WidthPct)
103 if width > cfg.MaxWidth {
104 width = cfg.MaxWidth
105 }
106
107 marginTop = int(float64(parentHeight) * cfg.TopMarginPct)
108 return width, marginTop
109}
110
111// SetScrolledWindowHeight safely sets min/max content height on a ScrolledWindow.
112// Resets min to -1 first to avoid GTK assertion (min <= max) when shrinking.
113func SetScrolledWindowHeight(sw *gtk.ScrolledWindow, height int) {
114 if sw == nil {
115 return
116 }
117 sw.SetMinContentHeight(-1)
118 sw.SetMaxContentHeight(height)
119 sw.SetMinContentHeight(height)
120}
121
122// MeasureWidgetHeight returns the natural height of a widget for a given width.
123// Returns 0 if widget is nil or measurement fails.
124func MeasureWidgetHeight(widget *gtk.Widget, forWidth int) int {
125 if widget == nil {
126 return 0
127 }
128 var minH, natH int
129 widget.Measure(gtk.OrientationVerticalValue, forWidth, &minH, &natH, nil, nil)
130 return natH
131}
132
133// ScaleValue scales a base pixel value by UI scale factor.
134// Returns the base value if scale is <= 0.
135func ScaleValue(base int, uiScale float64) int {
136 if uiScale <= 0 {
137 uiScale = 1.0
138 }
139 return int(float64(base) * uiScale)
140}