mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 15:45:38 +00:00
7aa7bb3be4
Match Go's FooError name pattern. While we're here, rename RedrawOp to InvalidateOp. Signed-off-by: Elias Naur <mail@eliasnaur.com>
148 lines
3.0 KiB
Go
148 lines
3.0 KiB
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package ui
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"math"
|
|
"time"
|
|
|
|
"gioui.org/ui/f32"
|
|
"gioui.org/ui/internal/ops"
|
|
)
|
|
|
|
// Config contains the essential configuration for
|
|
// updating and drawing a user interface.
|
|
type Config struct {
|
|
// Device pixels per dp.
|
|
PxPerDp float32
|
|
// Device pixels per sp.
|
|
PxPerSp float32
|
|
// The current time for animation.
|
|
Now time.Time
|
|
}
|
|
|
|
// Dp converts a value in dp units to pixels.
|
|
func (c *Config) Dp(dp float32) float32 {
|
|
return c.PxPerDp * dp
|
|
}
|
|
|
|
// Sp converts a value in sp units to pixels.
|
|
func (c *Config) Sp(sp float32) float32 {
|
|
return c.PxPerSp * sp
|
|
}
|
|
|
|
// Val converts a value to pixels.
|
|
func (c *Config) Val(v Value) float32 {
|
|
switch v.U {
|
|
case UnitPx:
|
|
return v.V
|
|
case UnitDp:
|
|
return c.PxPerDp * v.V
|
|
case UnitSp:
|
|
return c.PxPerSp * v.V
|
|
default:
|
|
panic("unknown unit")
|
|
}
|
|
}
|
|
|
|
// LayerOp represents a semantic layer of UI.
|
|
type LayerOp struct {
|
|
}
|
|
|
|
// InvalidateOp requests a redraw at the given time. Use
|
|
// the zero value to request an immediate redraw.
|
|
type InvalidateOp struct {
|
|
At time.Time
|
|
}
|
|
|
|
// TransformOp transforms an op.
|
|
type TransformOp struct {
|
|
Transform Transform
|
|
}
|
|
|
|
type Transform struct {
|
|
// TODO: general transforms.
|
|
offset f32.Point
|
|
}
|
|
|
|
func (r InvalidateOp) Add(o *Ops) {
|
|
data := make([]byte, ops.TypeRedrawLen)
|
|
data[0] = byte(ops.TypeInvalidate)
|
|
bo := binary.LittleEndian
|
|
// UnixNano cannot represent the zero time.
|
|
if t := r.At; !t.IsZero() {
|
|
nanos := t.UnixNano()
|
|
if nanos > 0 {
|
|
bo.PutUint64(data[1:], uint64(nanos))
|
|
}
|
|
}
|
|
o.Write(data)
|
|
}
|
|
|
|
func (r *InvalidateOp) Decode(d []byte) {
|
|
bo := binary.LittleEndian
|
|
if ops.OpType(d[0]) != ops.TypeInvalidate {
|
|
panic("invalid op")
|
|
}
|
|
if nanos := bo.Uint64(d[1:]); nanos > 0 {
|
|
r.At = time.Unix(0, int64(nanos))
|
|
}
|
|
}
|
|
|
|
func (t Transform) InvTransform(p f32.Point) f32.Point {
|
|
return p.Sub(t.offset)
|
|
}
|
|
|
|
func (t Transform) Transform(p f32.Point) f32.Point {
|
|
return p.Add(t.offset)
|
|
}
|
|
|
|
func (t Transform) Mul(t2 Transform) Transform {
|
|
return Transform{
|
|
offset: t.offset.Add(t2.offset),
|
|
}
|
|
}
|
|
|
|
func (t TransformOp) Add(o *Ops) {
|
|
data := make([]byte, ops.TypeTransformLen)
|
|
data[0] = byte(ops.TypeTransform)
|
|
bo := binary.LittleEndian
|
|
bo.PutUint32(data[1:], math.Float32bits(t.Transform.offset.X))
|
|
bo.PutUint32(data[5:], math.Float32bits(t.Transform.offset.Y))
|
|
o.Write(data)
|
|
}
|
|
|
|
func (t *TransformOp) Decode(d []byte) {
|
|
bo := binary.LittleEndian
|
|
if ops.OpType(d[0]) != ops.TypeTransform {
|
|
panic("invalid op")
|
|
}
|
|
*t = TransformOp{
|
|
Transform: Offset(f32.Point{
|
|
X: math.Float32frombits(bo.Uint32(d[1:])),
|
|
Y: math.Float32frombits(bo.Uint32(d[5:])),
|
|
}),
|
|
}
|
|
}
|
|
|
|
func (l LayerOp) Add(o *Ops) {
|
|
data := make([]byte, ops.TypeLayerLen)
|
|
data[0] = byte(ops.TypeLayer)
|
|
o.Write(data)
|
|
}
|
|
|
|
func (l *LayerOp) Decode(d []byte) {
|
|
if ops.OpType(d[0]) != ops.TypeLayer {
|
|
panic("invalid op")
|
|
}
|
|
*l = LayerOp{}
|
|
}
|
|
|
|
func Offset(o f32.Point) Transform {
|
|
return Transform{o}
|
|
}
|
|
|
|
// Inf is the int value that represents an unbounded maximum constraint.
|
|
const Inf = int(^uint(0) >> 1)
|