okami.mom/ultraviolet

git clone https://git.nkp.pet/okami.mom/ultraviolet

Ayman Bagabasdocs(layout): add ratatui acknowledgement89c142e

main
7.8 KiB174 linesraw
1package layout
2
3import (
4	"fmt"
5	"io"
6)
7
8// Constraint describes how a single segment of a [Layout] should be sized.
9//
10// Each constraint type expresses a different kind of sizing rule:
11// fixed ([Len]), proportional ([Percent], [Ratio]), bounded ([Min], [Max]),
12// or greedy ([Fill]). Proportional constraints are evaluated against the
13// full area being split rather than the remaining space after fixed
14// constraints have been applied.
15//
16// When the solver cannot satisfy every constraint, it resolves conflicts
17// according to the following priority order (highest first):
18//
19//   - [Min]
20//   - [Max]
21//   - [Len]
22//   - [Percent]
23//   - [Ratio]
24//   - [Fill]
25type Constraint interface {
26	hash(w io.Writer)
27
28	// isConstraint is a private method to prevent users implementing the
29	// interface making it a sealed enum.
30	isConstraint()
31}
32
33type (
34	// Min ensures the segment is no smaller than the given number of cells.
35	//
36	// # Examples
37	//
38	// 	[Percent(100), Min(20)]
39	//
40	// 	┌────────────────────────────┐┌──────────────────┐
41	// 	│            30 px           ││       20 px      │
42	// 	└────────────────────────────┘└──────────────────┘
43	//
44	// 	[Percent(100), Min(10)]
45	//
46	// 	┌──────────────────────────────────────┐┌────────┐
47	// 	│                 40 px                ││  10 px │
48	// 	└──────────────────────────────────────┘└────────┘
49	Min int
50
51	// Max caps the segment at the given number of cells.
52	//
53	// # Examples
54	//
55	// 	[Percent(0), Max(20)]
56	//
57	// 	┌────────────────────────────┐┌──────────────────┐
58	// 	│            30 px           ││       20 px      │
59	// 	└────────────────────────────┘└──────────────────┘
60	//
61	// 	[Percent(0), Max(10)]
62	//
63	// 	┌──────────────────────────────────────┐┌────────┐
64	// 	│                 40 px                ││  10 px │
65	// 	└──────────────────────────────────────┘└────────┘
66	Max int
67
68	// Len fixes the segment to exactly the given number of cells.
69	//
70	// # Examples
71	//
72	// 	[Len(20), Len(20)]
73	//
74	// 	┌──────────────────┐┌──────────────────┐
75	// 	│       20 px      ││       20 px      │
76	// 	└──────────────────┘└──────────────────┘
77	//
78	// 	[Len(20), Len(30)]
79	//
80	// 	┌──────────────────┐┌────────────────────────────┐
81	// 	│       20 px      ││            30 px           │
82	// 	└──────────────────┘└────────────────────────────┘
83	Len int
84
85	// Percent sizes the segment as a fraction of the total area.
86	//
87	// The integer value is treated as a percentage (0-100+) and multiplied
88	// by the total area; the result is rounded to the nearest cell.
89	//
90	// Because only whole integers are accepted, some fractions (e.g. 1/3)
91	// cannot be represented exactly. Consider [Ratio] or [Fill] instead.
92	//
93	// # Examples
94	//
95	// 	[Percent(75), Fill(1)]
96	//
97	// 	┌────────────────────────────────────┐┌──────────┐
98	// 	│                38 px               ││   12 px  │
99	// 	└────────────────────────────────────┘└──────────┘
100	//
101	// 	[Percent(50), Fill(1)]
102	//
103	// 	┌───────────────────────┐┌───────────────────────┐
104	// 	│         25 px         ││         25 px         │
105	// 	└───────────────────────┘└───────────────────────┘
106	Percent int
107
108	// Ratio sizes the segment as a numerator/denominator fraction of the total area.
109	//
110	// The fraction is converted to a float, multiplied by the area, and
111	// rounded to the nearest cell.
112	//
113	// # Examples
114	//
115	// 	[Ratio(1, 2) ; 2]
116	//
117	// 	┌───────────────────────┐┌───────────────────────┐
118	// 	│         25 px         ││         25 px         │
119	// 	└───────────────────────┘└───────────────────────┘
120	//
121	// 	[Ratio(1, 4) ; 4]
122	//
123	// 	┌───────────┐┌──────────┐┌───────────┐┌──────────┐
124	// 	│   13 px   ││   12 px  ││   13 px   ││   12 px  │
125	// 	└───────────┘└──────────┘└───────────┘└──────────┘
126	Ratio struct{ Num, Den int }
127
128	// Fill distributes remaining space proportionally among all Fill segments
129	// according to their respective weights.
130	//
131	// A Fill segment only expands into space left over after higher-priority
132	// constraints have been satisfied. Multiple Fill segments share that
133	// leftover in proportion to their integer values.
134	//
135	// # Examples
136	//
137	//
138	// 	[Fill(1), Fill(2), Fill(3)]
139	//
140	// 	┌──────┐┌───────────────┐┌───────────────────────┐
141	// 	│ 8 px ││     17 px     ││         25 px         │
142	// 	└──────┘└───────────────┘└───────────────────────┘
143	//
144	// 	[Fill(1), Percent(50), Fill(1)]
145	//
146	// 	┌───────────┐┌───────────────────────┐┌──────────┐
147	// 	│   13 px   ││         25 px         ││   12 px  │
148	// 	└───────────┘└───────────────────────┘└──────────┘
149	Fill int
150)
151
152func (m Min) String() string   { return fmt.Sprintf("Min(%d)", m) }
153func (m Min) hash(w io.Writer) { fmt.Fprint(w, "min", m) }
154func (Min) isConstraint()      {}
155
156func (m Max) String() string   { return fmt.Sprintf("Max(%d)", m) }
157func (m Max) hash(w io.Writer) { fmt.Fprint(w, "max", m) }
158func (Max) isConstraint()      {}
159
160func (l Len) String() string   { return fmt.Sprintf("Len(%d)", l) }
161func (l Len) hash(w io.Writer) { fmt.Fprint(w, "len", l) }
162func (Len) isConstraint()      {}
163
164func (p Percent) String() string   { return fmt.Sprintf("Percent(%d)", p) }
165func (p Percent) hash(w io.Writer) { fmt.Fprint(w, "percent", p) }
166func (Percent) isConstraint()      {}
167
168func (r Ratio) String() string   { return fmt.Sprintf("Ratio(%d / %d)", r.Num, r.Den) }
169func (r Ratio) hash(w io.Writer) { fmt.Fprint(w, "ratio", r.Num, r.Den) }
170func (Ratio) isConstraint()      {}
171
172func (f Fill) String() string   { return fmt.Sprintf("Fill(%d)", f) }
173func (f Fill) hash(w io.Writer) { fmt.Fprint(w, "fill", f) }
174func (Fill) isConstraint()      {}