helpers.go raw

   1  package gel
   2  
   3  import (
   4  	"errors"
   5  	"image"
   6  	"image/color"
   7  	"time"
   8  	
   9  	"github.com/p9c/gio/f32"
  10  	"github.com/p9c/gio/io/system"
  11  	l "github.com/p9c/gio/layout"
  12  	"github.com/p9c/gio/op"
  13  	"github.com/p9c/gio/text"
  14  )
  15  
  16  // Defining these as types gives flexibility later to create methods that modify them
  17  
  18  type Fonts map[string]text.Typeface
  19  type Icons map[string]*Icon
  20  type Collection []text.FontFace
  21  
  22  func (c Collection) Font(font string) (out text.Font, e error) {
  23  	for i := range c {
  24  		if c[i].Font.Typeface == text.Typeface(font) {
  25  			out = c[i].Font
  26  			return
  27  		}
  28  	}
  29  	return out, errors.New("font " + font + " not found")
  30  	
  31  }
  32  
  33  const Inf = 1e6
  34  
  35  // Fill is a general fill function that covers the background of the current context space
  36  func Fill(gtx l.Context, col color.NRGBA) l.Dimensions {
  37  	cs := gtx.Constraints
  38  	d := cs.Min
  39  	// dr := f32.Rectangle{
  40  	// 	Max: f32.Point{X: float32(d.X), Y: float32(d.Y)},
  41  	// }
  42  	// paint.ColorOp{Color: col}.Add(gtx.Ops)
  43  	// paint.PaintOp{Rect: dr}.Add(gtx.Ops)
  44  	fill(gtx, col, d, 0, 0)
  45  	return l.Dimensions{Size: d}
  46  }
  47  
  48  // func (th *Theme) GetFont(font string) *text.Font {
  49  // 	for i := range th.collection {
  50  // 		if th.collection[i].Font.Typeface == text.Typeface(font) {
  51  // 			return &th.collection[i].Font
  52  // 		}
  53  // 	}
  54  // 	return nil
  55  // }
  56  
  57  // func rgb(c uint32) color.RGBA {
  58  // 	return argb(0xff000000 | c)
  59  // }
  60  
  61  func argb(c uint32) color.RGBA {
  62  	return color.RGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)}
  63  }
  64  
  65  // FPt converts an point to a f32.Point.
  66  func Fpt(p image.Point) f32.Point {
  67  	return f32.Point{
  68  		X: float32(p.X), Y: float32(p.Y),
  69  	}
  70  }
  71  
  72  func axisPoint(a l.Axis, main, cross int) image.Point {
  73  	if a == l.Horizontal {
  74  		return image.Point{X: main, Y: cross}
  75  	} else {
  76  		return image.Point{X: cross, Y: main}
  77  	}
  78  }
  79  
  80  // axisConvert a point in (x, y) coordinates to (main, cross) coordinates,
  81  // or vice versa. Specifically, Convert((x, y)) returns (x, y) unchanged
  82  // for the horizontal axis, or (y, x) for the vertical axis.
  83  func axisConvert(a l.Axis, pt image.Point) image.Point {
  84  	if a == l.Horizontal {
  85  		return pt
  86  	}
  87  	return image.Pt(pt.Y, pt.X)
  88  }
  89  
  90  func axisMain(a l.Axis, sz image.Point) int {
  91  	if a == l.Horizontal {
  92  		return sz.X
  93  	}
  94  		return sz.Y
  95  }
  96  
  97  func axisCross(a l.Axis, sz image.Point) int {
  98  	if a == l.Horizontal {
  99  		return sz.Y
 100  	}
 101  		return sz.X
 102  }
 103  
 104  func axisMainConstraint(a l.Axis, cs l.Constraints) (int, int) {
 105  	if a == l.Horizontal {
 106  		return cs.Min.X, cs.Max.X
 107  	}
 108  	return cs.Min.Y, cs.Max.Y
 109  }
 110  
 111  func axisCrossConstraint(a l.Axis, cs l.Constraints) (int, int) {
 112  	if a == l.Horizontal {
 113  		return cs.Min.Y, cs.Max.Y
 114  	}
 115  	return cs.Min.X, cs.Max.X
 116  }
 117  
 118  func axisConstraints(a l.Axis, mainMin, mainMax, crossMin, crossMax int) l.Constraints {
 119  	if a == l.Horizontal {
 120  		return l.Constraints{Min: image.Pt(mainMin, crossMin), Max: image.Pt(mainMax, crossMax)}
 121  	}
 122  	return l.Constraints{Min: image.Pt(crossMin, mainMin), Max: image.Pt(crossMax, mainMax)}
 123  }
 124  
 125  func EmptySpace(x, y int) func(gtx l.Context) l.Dimensions {
 126  	return func(gtx l.Context) l.Dimensions {
 127  		return l.Dimensions{
 128  			Size: image.Point{
 129  				X: x,
 130  				Y: y,
 131  			},
 132  		}
 133  	}
 134  }
 135  
 136  func EmptyFromSize(size image.Point) func(gtx l.Context) l.Dimensions {
 137  	return func(gtx l.Context) l.Dimensions {
 138  		return l.Dimensions{
 139  			Size: size,
 140  		}
 141  	}
 142  }
 143  
 144  func EmptyMaxWidth() func(gtx l.Context) l.Dimensions {
 145  	return func(gtx l.Context) l.Dimensions {
 146  		return l.Dimensions{
 147  			Size:     image.Point{X: gtx.Constraints.Max.X, Y: gtx.Constraints.Min.Y},
 148  			Baseline: 0,
 149  		}
 150  	}
 151  }
 152  func EmptyMaxHeight() func(gtx l.Context) l.Dimensions {
 153  	return func(gtx l.Context) l.Dimensions {
 154  		return l.Dimensions{Size: image.Point{X: gtx.Constraints.Min.X, Y: gtx.Constraints.Min.Y}}
 155  	}
 156  }
 157  
 158  func EmptyMinWidth() func(gtx l.Context) l.Dimensions {
 159  	return func(gtx l.Context) l.Dimensions {
 160  		return l.Dimensions{
 161  			Size:     image.Point{X: gtx.Constraints.Min.X, Y: gtx.Constraints.Min.Y},
 162  			Baseline: 0,
 163  		}
 164  	}
 165  }
 166  func EmptyMinHeight() func(gtx l.Context) l.Dimensions {
 167  	return func(gtx l.Context) l.Dimensions {
 168  		return l.Dimensions{Size: image.Point{Y: gtx.Constraints.Min.Y}}
 169  	}
 170  }
 171  
 172  // CopyContextDimensionsWithMaxAxis copies the dimensions out with the max set by an image.Point along the axis
 173  func CopyContextDimensionsWithMaxAxis(gtx l.Context, axis l.Axis) l.Context {
 174  	ip := image.Point{}
 175  	if axis == l.Horizontal {
 176  		ip.Y = gtx.Constraints.Max.Y
 177  		ip.X = gtx.Constraints.Max.X
 178  	} else {
 179  		ip.Y = gtx.Constraints.Max.Y
 180  		ip.X = gtx.Constraints.Max.X
 181  	}
 182  	var ops op.Ops
 183  	gtx1 := l.NewContext(
 184  		&ops, system.FrameEvent{
 185  			Now:    time.Now(),
 186  			Metric: gtx.Metric,
 187  			Size:   ip,
 188  		},
 189  	)
 190  	if axis == l.Horizontal {
 191  		gtx1.Constraints.Min.X = 0
 192  		gtx1.Constraints.Min.Y = gtx.Constraints.Min.Y
 193  	} else {
 194  		gtx1.Constraints.Min.X = gtx.Constraints.Min.X
 195  		gtx1.Constraints.Min.Y = 0
 196  	}
 197  	return gtx1
 198  }
 199  
 200  // GetInfContext creates a context with infinite max constraints
 201  func GetInfContext(gtx l.Context) l.Context {
 202  	ip := image.Point{}
 203  	ip.Y = Inf
 204  	ip.X = Inf
 205  	var ops op.Ops
 206  	gtx1 := l.NewContext(
 207  		&ops, system.FrameEvent{
 208  			Now:    time.Now(),
 209  			Metric: gtx.Metric,
 210  			Size:   ip,
 211  		},
 212  	)
 213  	return gtx1
 214  }
 215  
 216  func If(value bool, t, f l.Widget) l.Widget {
 217  	if value {
 218  		return t
 219  	} else {
 220  		return f
 221  	}
 222  }
 223  
 224  func (th *Theme) SliceToWidget(w []l.Widget, axis l.Axis) l.Widget {
 225  	var out *Flex
 226  	if axis == l.Horizontal {
 227  		out = th.Flex().AlignStart()
 228  	} else {
 229  		out = th.VFlex().AlignStart()
 230  	}
 231  	for i := range w {
 232  		out.Rigid(w[i])
 233  	}
 234  	return out.Fn
 235  }
 236