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}