chore(v2): vendor dependencies for offline/China builds
go mod vendor pins onnxruntime_go v1.12.1, Gio and the rest into v2/vendor so go run/build work without hitting proxy.golang.org (blocked/slow in China). Verified: CGO_ENABLED=1 go build -mod=vendor ./internal/spike and GOOS=windows go build -mod=vendor ./internal/ui both pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+344
@@ -0,0 +1,344 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package layout
|
||||
|
||||
import (
|
||||
"image"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/op"
|
||||
"gioui.org/unit"
|
||||
)
|
||||
|
||||
// Constraints represent the minimum and maximum size of a widget.
|
||||
//
|
||||
// A widget does not have to treat its constraints as "hard". For
|
||||
// example, if it's passed a constraint with a minimum size that's
|
||||
// smaller than its actual minimum size, it should return its minimum
|
||||
// size dimensions instead. Parent widgets should deal appropriately
|
||||
// with child widgets that return dimensions that do not fit their
|
||||
// constraints (for example, by clipping).
|
||||
type Constraints struct {
|
||||
Min, Max image.Point
|
||||
}
|
||||
|
||||
// Dimensions are the resolved size and baseline for a widget.
|
||||
//
|
||||
// Baseline is the distance from the bottom of a widget to the baseline of
|
||||
// any text it contains (or 0). The purpose is to be able to align text
|
||||
// that span multiple widgets.
|
||||
type Dimensions struct {
|
||||
Size image.Point
|
||||
Baseline int
|
||||
}
|
||||
|
||||
// Axis is the Horizontal or Vertical direction.
|
||||
type Axis uint8
|
||||
|
||||
// Alignment is the mutual alignment of a list of widgets.
|
||||
type Alignment uint8
|
||||
|
||||
// Direction is the alignment of widgets relative to a containing
|
||||
// space.
|
||||
type Direction uint8
|
||||
|
||||
// Widget is a function scope for drawing, processing events and
|
||||
// computing dimensions for a user interface element.
|
||||
type Widget func(gtx Context) Dimensions
|
||||
|
||||
const (
|
||||
Start Alignment = iota
|
||||
End
|
||||
Middle
|
||||
Baseline
|
||||
)
|
||||
|
||||
const (
|
||||
NW Direction = iota
|
||||
N
|
||||
NE
|
||||
E
|
||||
SE
|
||||
S
|
||||
SW
|
||||
W
|
||||
Center
|
||||
)
|
||||
|
||||
const (
|
||||
Horizontal Axis = iota
|
||||
Vertical
|
||||
)
|
||||
|
||||
// Exact returns the Constraints with the minimum and maximum size
|
||||
// set to size.
|
||||
func Exact(size image.Point) Constraints {
|
||||
return Constraints{
|
||||
Min: size, Max: size,
|
||||
}
|
||||
}
|
||||
|
||||
// FPt converts an point to a f32.Point.
|
||||
func FPt(p image.Point) f32.Point {
|
||||
return f32.Point{
|
||||
X: float32(p.X), Y: float32(p.Y),
|
||||
}
|
||||
}
|
||||
|
||||
// Constrain a size so each dimension is in the range [min;max].
|
||||
func (c Constraints) Constrain(size image.Point) image.Point {
|
||||
if min := c.Min.X; size.X < min {
|
||||
size.X = min
|
||||
}
|
||||
if min := c.Min.Y; size.Y < min {
|
||||
size.Y = min
|
||||
}
|
||||
if max := c.Max.X; size.X > max {
|
||||
size.X = max
|
||||
}
|
||||
if max := c.Max.Y; size.Y > max {
|
||||
size.Y = max
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
// AddMin returns a copy of Constraints with the Min constraint enlarged by up to delta
|
||||
// while still fitting within the Max constraint. The Max is unchanged, and the Min constraint
|
||||
// will not go negative.
|
||||
func (c Constraints) AddMin(delta image.Point) Constraints {
|
||||
c.Min = c.Min.Add(delta)
|
||||
if c.Min.X < 0 {
|
||||
c.Min.X = 0
|
||||
}
|
||||
if c.Min.Y < 0 {
|
||||
c.Min.Y = 0
|
||||
}
|
||||
c.Min = c.Constrain(c.Min)
|
||||
return c
|
||||
}
|
||||
|
||||
// SubMax returns a copy of Constraints with the Max constraint shrunk by up to delta
|
||||
// while not going negative. The values of delta are expected to be positive.
|
||||
// The Min constraint is adjusted to fit within the new Max constraint.
|
||||
func (c Constraints) SubMax(delta image.Point) Constraints {
|
||||
c.Max = c.Max.Sub(delta)
|
||||
if c.Max.X < 0 {
|
||||
c.Max.X = 0
|
||||
}
|
||||
if c.Max.Y < 0 {
|
||||
c.Max.Y = 0
|
||||
}
|
||||
c.Min = c.Constrain(c.Min)
|
||||
return c
|
||||
}
|
||||
|
||||
// Inset adds space around a widget by decreasing its maximum
|
||||
// constraints. The minimum constraints will be adjusted to ensure
|
||||
// they do not exceed the maximum.
|
||||
type Inset struct {
|
||||
Top, Bottom, Left, Right unit.Dp
|
||||
}
|
||||
|
||||
// Layout a widget.
|
||||
func (in Inset) Layout(gtx Context, w Widget) Dimensions {
|
||||
top := gtx.Dp(in.Top)
|
||||
right := gtx.Dp(in.Right)
|
||||
bottom := gtx.Dp(in.Bottom)
|
||||
left := gtx.Dp(in.Left)
|
||||
mcs := gtx.Constraints
|
||||
mcs.Max.X -= left + right
|
||||
if mcs.Max.X < 0 {
|
||||
left = 0
|
||||
right = 0
|
||||
mcs.Max.X = 0
|
||||
}
|
||||
if mcs.Min.X > mcs.Max.X {
|
||||
mcs.Min.X = mcs.Max.X
|
||||
}
|
||||
mcs.Max.Y -= top + bottom
|
||||
if mcs.Max.Y < 0 {
|
||||
bottom = 0
|
||||
top = 0
|
||||
mcs.Max.Y = 0
|
||||
}
|
||||
if mcs.Min.Y > mcs.Max.Y {
|
||||
mcs.Min.Y = mcs.Max.Y
|
||||
}
|
||||
gtx.Constraints = mcs
|
||||
trans := op.Offset(image.Pt(left, top)).Push(gtx.Ops)
|
||||
dims := w(gtx)
|
||||
trans.Pop()
|
||||
return Dimensions{
|
||||
Size: dims.Size.Add(image.Point{X: right + left, Y: top + bottom}),
|
||||
Baseline: dims.Baseline + bottom,
|
||||
}
|
||||
}
|
||||
|
||||
// UniformInset returns an Inset with a single inset applied to all
|
||||
// edges.
|
||||
func UniformInset(v unit.Dp) Inset {
|
||||
return Inset{Top: v, Right: v, Bottom: v, Left: v}
|
||||
}
|
||||
|
||||
// Layout a widget according to the direction.
|
||||
// The widget is called with the context constraints minimum cleared.
|
||||
func (d Direction) Layout(gtx Context, w Widget) Dimensions {
|
||||
macro := op.Record(gtx.Ops)
|
||||
csn := gtx.Constraints.Min
|
||||
switch d {
|
||||
case N, S:
|
||||
gtx.Constraints.Min.Y = 0
|
||||
case E, W:
|
||||
gtx.Constraints.Min.X = 0
|
||||
default:
|
||||
gtx.Constraints.Min = image.Point{}
|
||||
}
|
||||
dims := w(gtx)
|
||||
call := macro.Stop()
|
||||
sz := dims.Size
|
||||
if sz.X < csn.X {
|
||||
sz.X = csn.X
|
||||
}
|
||||
if sz.Y < csn.Y {
|
||||
sz.Y = csn.Y
|
||||
}
|
||||
|
||||
p := d.Position(dims.Size, sz)
|
||||
defer op.Offset(p).Push(gtx.Ops).Pop()
|
||||
call.Add(gtx.Ops)
|
||||
|
||||
return Dimensions{
|
||||
Size: sz,
|
||||
Baseline: dims.Baseline + sz.Y - dims.Size.Y - p.Y,
|
||||
}
|
||||
}
|
||||
|
||||
// Position calculates widget position according to the direction.
|
||||
func (d Direction) Position(widget, bounds image.Point) image.Point {
|
||||
var p image.Point
|
||||
|
||||
switch d {
|
||||
case N, S, Center:
|
||||
p.X = (bounds.X - widget.X) / 2
|
||||
case NE, SE, E:
|
||||
p.X = bounds.X - widget.X
|
||||
}
|
||||
|
||||
switch d {
|
||||
case W, Center, E:
|
||||
p.Y = (bounds.Y - widget.Y) / 2
|
||||
case SW, S, SE:
|
||||
p.Y = bounds.Y - widget.Y
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// Spacer adds space between widgets.
|
||||
type Spacer struct {
|
||||
Width, Height unit.Dp
|
||||
}
|
||||
|
||||
func (s Spacer) Layout(gtx Context) Dimensions {
|
||||
return Dimensions{
|
||||
Size: gtx.Constraints.Constrain(image.Point{
|
||||
X: gtx.Dp(s.Width),
|
||||
Y: gtx.Dp(s.Height),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func (a Alignment) String() string {
|
||||
switch a {
|
||||
case Start:
|
||||
return "Start"
|
||||
case End:
|
||||
return "End"
|
||||
case Middle:
|
||||
return "Middle"
|
||||
case Baseline:
|
||||
return "Baseline"
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a point in (x, y) coordinates to (main, cross) coordinates,
|
||||
// or vice versa. Specifically, Convert((x, y)) returns (x, y) unchanged
|
||||
// for the horizontal axis, or (y, x) for the vertical axis.
|
||||
func (a Axis) Convert(pt image.Point) image.Point {
|
||||
if a == Horizontal {
|
||||
return pt
|
||||
}
|
||||
return image.Pt(pt.Y, pt.X)
|
||||
}
|
||||
|
||||
// FConvert a point in (x, y) coordinates to (main, cross) coordinates,
|
||||
// or vice versa. Specifically, FConvert((x, y)) returns (x, y) unchanged
|
||||
// for the horizontal axis, or (y, x) for the vertical axis.
|
||||
func (a Axis) FConvert(pt f32.Point) f32.Point {
|
||||
if a == Horizontal {
|
||||
return pt
|
||||
}
|
||||
return f32.Pt(pt.Y, pt.X)
|
||||
}
|
||||
|
||||
// mainConstraint returns the min and max main constraints for axis a.
|
||||
func (a Axis) mainConstraint(cs Constraints) (int, int) {
|
||||
if a == Horizontal {
|
||||
return cs.Min.X, cs.Max.X
|
||||
}
|
||||
return cs.Min.Y, cs.Max.Y
|
||||
}
|
||||
|
||||
// crossConstraint returns the min and max cross constraints for axis a.
|
||||
func (a Axis) crossConstraint(cs Constraints) (int, int) {
|
||||
if a == Horizontal {
|
||||
return cs.Min.Y, cs.Max.Y
|
||||
}
|
||||
return cs.Min.X, cs.Max.X
|
||||
}
|
||||
|
||||
// constraints returns the constraints for axis a.
|
||||
func (a Axis) constraints(mainMin, mainMax, crossMin, crossMax int) Constraints {
|
||||
if a == Horizontal {
|
||||
return Constraints{Min: image.Pt(mainMin, crossMin), Max: image.Pt(mainMax, crossMax)}
|
||||
}
|
||||
return Constraints{Min: image.Pt(crossMin, mainMin), Max: image.Pt(crossMax, mainMax)}
|
||||
}
|
||||
|
||||
func (a Axis) String() string {
|
||||
switch a {
|
||||
case Horizontal:
|
||||
return "Horizontal"
|
||||
case Vertical:
|
||||
return "Vertical"
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func (d Direction) String() string {
|
||||
switch d {
|
||||
case NW:
|
||||
return "NW"
|
||||
case N:
|
||||
return "N"
|
||||
case NE:
|
||||
return "NE"
|
||||
case E:
|
||||
return "E"
|
||||
case SE:
|
||||
return "SE"
|
||||
case S:
|
||||
return "S"
|
||||
case SW:
|
||||
return "SW"
|
||||
case W:
|
||||
return "W"
|
||||
case Center:
|
||||
return "Center"
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user