okami.mom/ultraviolet
git clone https://git.nkp.pet/okami.mom/ultraviolet
89c142e
main
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 { 26hash (w io.Writer ) 27 28// isConstraint is a private method to prevent users implementing the 29// interface making it a sealed enum. 30isConstraint () 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// └──────────────────────────────────────┘└────────┘ 49Min 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// └──────────────────────────────────────┘└────────┘ 66Max 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// └──────────────────┘└────────────────────────────┘ 83Len 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// └───────────────────────┘└───────────────────────┘ 106Percent 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// └───────────┘└──────────┘└───────────┘└──────────┘ 126Ratio 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// └───────────┘└───────────────────────┘└──────────┘ 149Fill 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 () {}