mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 02:15:34 +00:00
op: add package op for operations
Extract operation types from package ui into package op. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -12,11 +12,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/app/internal/gl"
|
"gioui.org/app/internal/gl"
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
"gioui.org/internal/ops"
|
"gioui.org/internal/ops"
|
||||||
|
"gioui.org/op"
|
||||||
"gioui.org/paint"
|
"gioui.org/paint"
|
||||||
"golang.org/x/image/draw"
|
"golang.org/x/image/draw"
|
||||||
)
|
)
|
||||||
@@ -74,7 +74,7 @@ type drawOps struct {
|
|||||||
|
|
||||||
type drawState struct {
|
type drawState struct {
|
||||||
clip f32.Rectangle
|
clip f32.Rectangle
|
||||||
t ui.TransformOp
|
t op.TransformOp
|
||||||
cpath *pathOp
|
cpath *pathOp
|
||||||
rect bool
|
rect bool
|
||||||
z int
|
z int
|
||||||
@@ -398,7 +398,7 @@ func (g *GPU) Refresh() {
|
|||||||
g.setErr(<-g.refreshErr)
|
g.setErr(<-g.refreshErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GPU) Draw(profile bool, viewport image.Point, root *ui.Ops) {
|
func (g *GPU) Draw(profile bool, viewport image.Point, root *op.Ops) {
|
||||||
if g.err != nil {
|
if g.err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -678,7 +678,7 @@ func (d *drawOps) reset(cache *resourceCache, viewport image.Point) {
|
|||||||
d.pathOpCache = d.pathOpCache[:0]
|
d.pathOpCache = d.pathOpCache[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *drawOps) collect(cache *resourceCache, root *ui.Ops, viewport image.Point) {
|
func (d *drawOps) collect(cache *resourceCache, root *op.Ops, viewport image.Point) {
|
||||||
d.reset(cache, viewport)
|
d.reset(cache, viewport)
|
||||||
clip := f32.Rectangle{
|
clip := f32.Rectangle{
|
||||||
Max: f32.Point{X: float32(viewport.X), Y: float32(viewport.Y)},
|
Max: f32.Point{X: float32(viewport.X), Y: float32(viewport.Y)},
|
||||||
@@ -704,8 +704,8 @@ loop:
|
|||||||
for encOp, ok := r.Decode(); ok; encOp, ok = r.Decode() {
|
for encOp, ok := r.Decode(); ok; encOp, ok = r.Decode() {
|
||||||
switch opconst.OpType(encOp.Data[0]) {
|
switch opconst.OpType(encOp.Data[0]) {
|
||||||
case opconst.TypeTransform:
|
case opconst.TypeTransform:
|
||||||
op := ops.DecodeTransformOp(encOp.Data)
|
dop := ops.DecodeTransformOp(encOp.Data)
|
||||||
state.t = state.t.Multiply(ui.TransformOp(op))
|
state.t = state.t.Multiply(op.TransformOp(dop))
|
||||||
case opconst.TypeAux:
|
case opconst.TypeAux:
|
||||||
aux = encOp.Data[opconst.TypeAuxLen:]
|
aux = encOp.Data[opconst.TypeAuxLen:]
|
||||||
auxKey = encOp.Key
|
auxKey = encOp.Key
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"gioui.org/internal/ops"
|
"gioui.org/internal/ops"
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
"gioui.org/io/key"
|
"gioui.org/io/key"
|
||||||
"gioui.org/ui"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TextInputState uint8
|
type TextInputState uint8
|
||||||
@@ -44,7 +44,7 @@ func (q *keyQueue) InputState() TextInputState {
|
|||||||
return q.state
|
return q.state
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *keyQueue) Frame(root *ui.Ops, events *handlerEvents) {
|
func (q *keyQueue) Frame(root *op.Ops, events *handlerEvents) {
|
||||||
if q.handlers == nil {
|
if q.handlers == nil {
|
||||||
q.handlers = make(map[event.Key]*keyHandler)
|
q.handlers = make(map[event.Key]*keyHandler)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"gioui.org/internal/ops"
|
"gioui.org/internal/ops"
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
"gioui.org/ui"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pointerQueue struct {
|
type pointerQueue struct {
|
||||||
@@ -42,7 +42,7 @@ type pointerInfo struct {
|
|||||||
type pointerHandler struct {
|
type pointerHandler struct {
|
||||||
area int
|
area int
|
||||||
active bool
|
active bool
|
||||||
transform ui.TransformOp
|
transform op.TransformOp
|
||||||
wantsGrab bool
|
wantsGrab bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ type areaOp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type areaNode struct {
|
type areaNode struct {
|
||||||
trans ui.TransformOp
|
trans op.TransformOp
|
||||||
next int
|
next int
|
||||||
area areaOp
|
area areaOp
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ const (
|
|||||||
areaEllipse
|
areaEllipse
|
||||||
)
|
)
|
||||||
|
|
||||||
func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t ui.TransformOp, area, node int, pass bool) {
|
func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t op.TransformOp, area, node int, pass bool) {
|
||||||
for encOp, ok := r.Decode(); ok; encOp, ok = r.Decode() {
|
for encOp, ok := r.Decode(); ok; encOp, ok = r.Decode() {
|
||||||
switch opconst.OpType(encOp.Data[0]) {
|
switch opconst.OpType(encOp.Data[0]) {
|
||||||
case opconst.TypePush:
|
case opconst.TypePush:
|
||||||
@@ -86,8 +86,8 @@ func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t u
|
|||||||
})
|
})
|
||||||
node = len(q.hitTree) - 1
|
node = len(q.hitTree) - 1
|
||||||
case opconst.TypeTransform:
|
case opconst.TypeTransform:
|
||||||
op := ops.DecodeTransformOp(encOp.Data)
|
dop := ops.DecodeTransformOp(encOp.Data)
|
||||||
t = t.Multiply(ui.TransformOp(op))
|
t = t.Multiply(op.TransformOp(dop))
|
||||||
case opconst.TypePointerInput:
|
case opconst.TypePointerInput:
|
||||||
op := decodePointerInputOp(encOp.Data, encOp.Refs)
|
op := decodePointerInputOp(encOp.Data, encOp.Refs)
|
||||||
q.hitTree = append(q.hitTree, hitNode{
|
q.hitTree = append(q.hitTree, hitNode{
|
||||||
@@ -158,7 +158,7 @@ func (q *pointerQueue) init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *pointerQueue) Frame(root *ui.Ops, events *handlerEvents) {
|
func (q *pointerQueue) Frame(root *op.Ops, events *handlerEvents) {
|
||||||
q.init()
|
q.init()
|
||||||
for _, h := range q.handlers {
|
for _, h := range q.handlers {
|
||||||
// Reset handler.
|
// Reset handler.
|
||||||
@@ -167,7 +167,7 @@ func (q *pointerQueue) Frame(root *ui.Ops, events *handlerEvents) {
|
|||||||
q.hitTree = q.hitTree[:0]
|
q.hitTree = q.hitTree[:0]
|
||||||
q.areas = q.areas[:0]
|
q.areas = q.areas[:0]
|
||||||
q.reader.Reset(root)
|
q.reader.Reset(root)
|
||||||
q.collectHandlers(&q.reader, events, ui.TransformOp{}, -1, -1, false)
|
q.collectHandlers(&q.reader, events, op.TransformOp{}, -1, -1, false)
|
||||||
for k, h := range q.handlers {
|
for k, h := range q.handlers {
|
||||||
if !h.active {
|
if !h.active {
|
||||||
q.dropHandler(k)
|
q.dropHandler(k)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
"gioui.org/io/key"
|
"gioui.org/io/key"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
"gioui.org/io/profile"
|
"gioui.org/io/profile"
|
||||||
"gioui.org/ui"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Router is a Queue implementation that routes events from
|
// Router is a Queue implementation that routes events from
|
||||||
@@ -53,7 +53,7 @@ func (q *Router) Events(k event.Key) []event.Event {
|
|||||||
return events
|
return events
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Router) Frame(ops *ui.Ops) {
|
func (q *Router) Frame(ops *op.Ops) {
|
||||||
q.handlers.Clear()
|
q.handlers.Clear()
|
||||||
q.wakeup = false
|
q.wakeup = false
|
||||||
q.profHandlers = q.profHandlers[:0]
|
q.profHandlers = q.profHandlers[:0]
|
||||||
@@ -160,12 +160,12 @@ func decodeProfileOp(d []byte, refs []interface{}) profile.Op {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInvalidateOp(d []byte) ui.InvalidateOp {
|
func decodeInvalidateOp(d []byte) op.InvalidateOp {
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
if opconst.OpType(d[0]) != opconst.TypeInvalidate {
|
if opconst.OpType(d[0]) != opconst.TypeInvalidate {
|
||||||
panic("invalid op")
|
panic("invalid op")
|
||||||
}
|
}
|
||||||
var o ui.InvalidateOp
|
var o op.InvalidateOp
|
||||||
if nanos := bo.Uint64(d[1:]); nanos > 0 {
|
if nanos := bo.Uint64(d[1:]); nanos > 0 {
|
||||||
o.At = time.Unix(0, int64(nanos))
|
o.At = time.Unix(0, int64(nanos))
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -12,6 +12,7 @@ import (
|
|||||||
"gioui.org/app/internal/input"
|
"gioui.org/app/internal/input"
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
"gioui.org/io/profile"
|
"gioui.org/io/profile"
|
||||||
|
"gioui.org/op"
|
||||||
"gioui.org/ui"
|
"gioui.org/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ type Window struct {
|
|||||||
in chan event.Event
|
in chan event.Event
|
||||||
ack chan struct{}
|
ack chan struct{}
|
||||||
invalidates chan struct{}
|
invalidates chan struct{}
|
||||||
frames chan *ui.Ops
|
frames chan *op.Ops
|
||||||
|
|
||||||
stage Stage
|
stage Stage
|
||||||
animating bool
|
animating bool
|
||||||
@@ -99,7 +100,7 @@ func NewWindow(options ...WindowOption) *Window {
|
|||||||
out: make(chan event.Event),
|
out: make(chan event.Event),
|
||||||
ack: make(chan struct{}),
|
ack: make(chan struct{}),
|
||||||
invalidates: make(chan struct{}, 1),
|
invalidates: make(chan struct{}, 1),
|
||||||
frames: make(chan *ui.Ops),
|
frames: make(chan *op.Ops),
|
||||||
}
|
}
|
||||||
go w.run(opts)
|
go w.run(opts)
|
||||||
return w
|
return w
|
||||||
@@ -120,11 +121,11 @@ func (w *Window) Queue() *Queue {
|
|||||||
// window contents, input operations declare input handlers,
|
// window contents, input operations declare input handlers,
|
||||||
// and so on. The supplied operations list completely replaces
|
// and so on. The supplied operations list completely replaces
|
||||||
// the window state from previous calls.
|
// the window state from previous calls.
|
||||||
func (w *Window) Update(frame *ui.Ops) {
|
func (w *Window) Update(frame *op.Ops) {
|
||||||
w.frames <- frame
|
w.frames <- frame
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Window) draw(size image.Point, frame *ui.Ops) {
|
func (w *Window) draw(size image.Point, frame *op.Ops) {
|
||||||
var drawDur time.Duration
|
var drawDur time.Duration
|
||||||
if !w.drawStart.IsZero() {
|
if !w.drawStart.IsZero() {
|
||||||
drawDur = time.Since(w.drawStart)
|
drawDur = time.Since(w.drawStart)
|
||||||
@@ -265,7 +266,7 @@ func (w *Window) run(opts *windowOptions) {
|
|||||||
w.drawStart = time.Now()
|
w.drawStart = time.Now()
|
||||||
w.hasNextFrame = false
|
w.hasNextFrame = false
|
||||||
w.out <- e
|
w.out <- e
|
||||||
var frame *ui.Ops
|
var frame *op.Ops
|
||||||
// Wait for either a frame or the ack event,
|
// Wait for either a frame or the ack event,
|
||||||
// which meant that the client didn't draw.
|
// which meant that the client didn't draw.
|
||||||
select {
|
select {
|
||||||
|
|||||||
Vendored
+1
-2
@@ -7,7 +7,6 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/app"
|
"gioui.org/app"
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/paint"
|
"gioui.org/paint"
|
||||||
@@ -25,7 +24,7 @@ func main() {
|
|||||||
|
|
||||||
func loop(w *app.Window) error {
|
func loop(w *app.Window) error {
|
||||||
background := color.RGBA{255, 0, 0, 255}
|
background := color.RGBA{255, 0, 0, 255}
|
||||||
ops := new(ui.Ops)
|
ops := new(op.Ops)
|
||||||
for {
|
for {
|
||||||
e := <-w.Events()
|
e := <-w.Events()
|
||||||
switch e := e.(type) {
|
switch e := e.(type) {
|
||||||
|
|||||||
+4
-3
@@ -16,6 +16,7 @@ import (
|
|||||||
"gioui.org/internal/fling"
|
"gioui.org/internal/fling"
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
|
"gioui.org/op"
|
||||||
"gioui.org/ui"
|
"gioui.org/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ const (
|
|||||||
var touchSlop = ui.Dp(3)
|
var touchSlop = ui.Dp(3)
|
||||||
|
|
||||||
// Add the handler to the operation list to receive click events.
|
// Add the handler to the operation list to receive click events.
|
||||||
func (c *Click) Add(ops *ui.Ops) {
|
func (c *Click) Add(ops *op.Ops) {
|
||||||
op := pointer.InputOp{Key: c}
|
op := pointer.InputOp{Key: c}
|
||||||
op.Add(ops)
|
op.Add(ops)
|
||||||
}
|
}
|
||||||
@@ -140,11 +141,11 @@ func (c *Click) Events(q event.Queue) []ClickEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the handler to the operation list to receive scroll events.
|
// Add the handler to the operation list to receive scroll events.
|
||||||
func (s *Scroll) Add(ops *ui.Ops) {
|
func (s *Scroll) Add(ops *op.Ops) {
|
||||||
oph := pointer.InputOp{Key: s, Grab: s.grab}
|
oph := pointer.InputOp{Key: s, Grab: s.grab}
|
||||||
oph.Add(ops)
|
oph.Add(ops)
|
||||||
if s.flinger.Active() {
|
if s.flinger.Active() {
|
||||||
ui.InvalidateOp{}.Add(ops)
|
op.InvalidateOp{}.Add(ops)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -6,17 +6,17 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DecodeTransformOp(d []byte) ui.TransformOp {
|
func DecodeTransformOp(d []byte) op.TransformOp {
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
if opconst.OpType(d[0]) != opconst.TypeTransform {
|
if opconst.OpType(d[0]) != opconst.TypeTransform {
|
||||||
panic("invalid op")
|
panic("invalid op")
|
||||||
}
|
}
|
||||||
return ui.TransformOp{}.Offset(f32.Point{
|
return op.TransformOp{}.Offset(f32.Point{
|
||||||
X: math.Float32frombits(bo.Uint32(d[1:])),
|
X: math.Float32frombits(bo.Uint32(d[1:])),
|
||||||
Y: math.Float32frombits(bo.Uint32(d[5:])),
|
Y: math.Float32frombits(bo.Uint32(d[5:])),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ package ops
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reader parses an ops list.
|
// Reader parses an ops list.
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
pc pc
|
pc pc
|
||||||
stack []macro
|
stack []macro
|
||||||
ops *ui.Ops
|
ops *op.Ops
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodedOp represents an encoded op returned by
|
// EncodedOp represents an encoded op returned by
|
||||||
@@ -26,14 +26,14 @@ type EncodedOp struct {
|
|||||||
|
|
||||||
// Key is a unique key for a given op.
|
// Key is a unique key for a given op.
|
||||||
type Key struct {
|
type Key struct {
|
||||||
ops *ui.Ops
|
ops *op.Ops
|
||||||
pc int
|
pc int
|
||||||
version int
|
version int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shadow of ui.MacroOp.
|
// Shadow of op.MacroOp.
|
||||||
type macroOp struct {
|
type macroOp struct {
|
||||||
ops *ui.Ops
|
ops *op.Ops
|
||||||
version int
|
version int
|
||||||
pc pc
|
pc pc
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ type pc struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type macro struct {
|
type macro struct {
|
||||||
ops *ui.Ops
|
ops *op.Ops
|
||||||
retPC pc
|
retPC pc
|
||||||
endPC pc
|
endPC pc
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ type opAux struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset start reading from the op list.
|
// Reset start reading from the op list.
|
||||||
func (r *Reader) Reset(ops *ui.Ops) {
|
func (r *Reader) Reset(ops *op.Ops) {
|
||||||
r.stack = r.stack[:0]
|
r.stack = r.stack[:0]
|
||||||
r.pc = pc{}
|
r.pc = pc{}
|
||||||
r.ops = ops
|
r.ops = ops
|
||||||
@@ -170,7 +170,7 @@ func (m *macroOp) decode(data []byte, refs []interface{}) {
|
|||||||
refsIdx := int(int32(bo.Uint32(data[5:])))
|
refsIdx := int(int32(bo.Uint32(data[5:])))
|
||||||
version := int(int32(bo.Uint32(data[9:])))
|
version := int(int32(bo.Uint32(data[9:])))
|
||||||
*m = macroOp{
|
*m = macroOp{
|
||||||
ops: refs[0].(*ui.Ops),
|
ops: refs[0].(*op.Ops),
|
||||||
pc: pc{
|
pc: pc{
|
||||||
data: dataIdx,
|
data: dataIdx,
|
||||||
refs: refsIdx,
|
refs: refsIdx,
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ The following example declares a handler ready for key input:
|
|||||||
|
|
||||||
import gioui.org/io/key
|
import gioui.org/io/key
|
||||||
|
|
||||||
ops := new(ui.Ops)
|
ops := new(op.Ops)
|
||||||
var h *Handler = ...
|
var h *Handler = ...
|
||||||
key.InputOp{Key: h}.Add(ops)
|
key.InputOp{Key: h}.Add(ops)
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -12,7 +12,7 @@ package key
|
|||||||
import (
|
import (
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
"gioui.org/ui"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InputOp declares a handler ready for key events.
|
// InputOp declares a handler ready for key events.
|
||||||
@@ -86,7 +86,7 @@ func (m Modifiers) Contain(m2 Modifiers) bool {
|
|||||||
return m&m2 == m2
|
return m&m2 == m2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h InputOp) Add(o *ui.Ops) {
|
func (h InputOp) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypeKeyInputLen)
|
data := make([]byte, opconst.TypeKeyInputLen)
|
||||||
data[0] = byte(opconst.TypeKeyInput)
|
data[0] = byte(opconst.TypeKeyInput)
|
||||||
if h.Focus {
|
if h.Focus {
|
||||||
@@ -95,7 +95,7 @@ func (h InputOp) Add(o *ui.Ops) {
|
|||||||
o.Write(data, h.Key)
|
o.Write(data, h.Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h HideInputOp) Add(o *ui.Ops) {
|
func (h HideInputOp) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypeHideInputLen)
|
data := make([]byte, opconst.TypeHideInputLen)
|
||||||
data[0] = byte(opconst.TypeHideInput)
|
data[0] = byte(opconst.TypeHideInput)
|
||||||
o.Write(data)
|
o.Write(data)
|
||||||
|
|||||||
+3
-3
@@ -15,7 +15,7 @@ subsequent InputOp are active.
|
|||||||
|
|
||||||
For example, to set up a rectangular hit area:
|
For example, to set up a rectangular hit area:
|
||||||
|
|
||||||
var ops ui.Ops
|
var ops op.Ops
|
||||||
var h *Handler = ...
|
var h *Handler = ...
|
||||||
|
|
||||||
r := image.Rectangle{...}
|
r := image.Rectangle{...}
|
||||||
@@ -33,8 +33,8 @@ with the most recent node.
|
|||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
ops := new(ui.Ops)
|
ops := new(op.Ops)
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
var h1, h2 *Handler
|
var h1, h2 *Handler
|
||||||
|
|
||||||
stack.Push(ops)
|
stack.Push(ops)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
"gioui.org/ui"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Event is a pointer event.
|
// Event is a pointer event.
|
||||||
@@ -33,7 +33,7 @@ type Event struct {
|
|||||||
// outside it.
|
// outside it.
|
||||||
Hit bool
|
Hit bool
|
||||||
// Position is the position of the event, relative to
|
// Position is the position of the event, relative to
|
||||||
// the current transformation, as set by ui.TransformOp.
|
// the current transformation, as set by op.TransformOp.
|
||||||
Position f32.Point
|
Position f32.Point
|
||||||
// Scroll is the scroll amount, if any.
|
// Scroll is the scroll amount, if any.
|
||||||
Scroll f32.Point
|
Scroll f32.Point
|
||||||
@@ -124,21 +124,21 @@ const (
|
|||||||
areaEllipse
|
areaEllipse
|
||||||
)
|
)
|
||||||
|
|
||||||
func (op RectAreaOp) Add(ops *ui.Ops) {
|
func (op RectAreaOp) Add(ops *op.Ops) {
|
||||||
areaOp{
|
areaOp{
|
||||||
kind: areaRect,
|
kind: areaRect,
|
||||||
rect: op.Rect,
|
rect: op.Rect,
|
||||||
}.add(ops)
|
}.add(ops)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (op EllipseAreaOp) Add(ops *ui.Ops) {
|
func (op EllipseAreaOp) Add(ops *op.Ops) {
|
||||||
areaOp{
|
areaOp{
|
||||||
kind: areaEllipse,
|
kind: areaEllipse,
|
||||||
rect: op.Rect,
|
rect: op.Rect,
|
||||||
}.add(ops)
|
}.add(ops)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (op areaOp) add(o *ui.Ops) {
|
func (op areaOp) add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypeAreaLen)
|
data := make([]byte, opconst.TypeAreaLen)
|
||||||
data[0] = byte(opconst.TypeArea)
|
data[0] = byte(opconst.TypeArea)
|
||||||
data[1] = byte(op.kind)
|
data[1] = byte(op.kind)
|
||||||
@@ -150,7 +150,7 @@ func (op areaOp) add(o *ui.Ops) {
|
|||||||
o.Write(data)
|
o.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h InputOp) Add(o *ui.Ops) {
|
func (h InputOp) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypePointerInputLen)
|
data := make([]byte, opconst.TypePointerInputLen)
|
||||||
data[0] = byte(opconst.TypePointerInput)
|
data[0] = byte(opconst.TypePointerInput)
|
||||||
if h.Grab {
|
if h.Grab {
|
||||||
@@ -159,7 +159,7 @@ func (h InputOp) Add(o *ui.Ops) {
|
|||||||
o.Write(data, h.Key)
|
o.Write(data, h.Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (op PassOp) Add(o *ui.Ops) {
|
func (op PassOp) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypePassLen)
|
data := make([]byte, opconst.TypePassLen)
|
||||||
data[0] = byte(opconst.TypePass)
|
data[0] = byte(opconst.TypePass)
|
||||||
if op.Pass {
|
if op.Pass {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ package profile
|
|||||||
import (
|
import (
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
"gioui.org/ui"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Op registers a handler for receiving
|
// Op registers a handler for receiving
|
||||||
@@ -23,7 +23,7 @@ type Event struct {
|
|||||||
Timings string
|
Timings string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Op) Add(o *ui.Ops) {
|
func (p Op) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypeProfileLen)
|
data := make([]byte, opconst.TypeProfileLen)
|
||||||
data[0] = byte(opconst.TypeProfile)
|
data[0] = byte(opconst.TypeProfile)
|
||||||
o.Write(data, p.Key)
|
o.Write(data, p.Key)
|
||||||
|
|||||||
+5
-5
@@ -6,7 +6,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/ui"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flex lays out child elements along an axis,
|
// Flex lays out child elements along an axis,
|
||||||
@@ -21,7 +21,7 @@ type Flex struct {
|
|||||||
Alignment Alignment
|
Alignment Alignment
|
||||||
|
|
||||||
ctx *Context
|
ctx *Context
|
||||||
macro ui.MacroOp
|
macro op.MacroOp
|
||||||
mode flexMode
|
mode flexMode
|
||||||
size int
|
size int
|
||||||
rigidSize int
|
rigidSize int
|
||||||
@@ -33,7 +33,7 @@ type Flex struct {
|
|||||||
|
|
||||||
// FlexChild is the layout result of a call End.
|
// FlexChild is the layout result of a call End.
|
||||||
type FlexChild struct {
|
type FlexChild struct {
|
||||||
macro ui.MacroOp
|
macro op.MacroOp
|
||||||
dims Dimensions
|
dims Dimensions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,9 +189,9 @@ func (f *Flex) Layout(children ...FlexChild) {
|
|||||||
cross = f.maxBaseline - b
|
cross = f.maxBaseline - b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
stack.Push(f.ctx.Ops)
|
stack.Push(f.ctx.Ops)
|
||||||
ui.TransformOp{}.Offset(toPointF(axisPoint(f.Axis, mainSize, cross))).Add(f.ctx.Ops)
|
op.TransformOp{}.Offset(toPointF(axisPoint(f.Axis, mainSize, cross))).Add(f.ctx.Ops)
|
||||||
child.macro.Add(f.ctx.Ops)
|
child.macro.Add(f.ctx.Ops)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
mainSize += axisMain(f.Axis, dims.Size)
|
mainSize += axisMain(f.Axis, dims.Size)
|
||||||
|
|||||||
+8
-7
@@ -6,6 +6,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
|
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
|
"gioui.org/op"
|
||||||
"gioui.org/ui"
|
"gioui.org/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ type Context struct {
|
|||||||
|
|
||||||
ui.Config
|
ui.Config
|
||||||
event.Queue
|
event.Queue
|
||||||
*ui.Ops
|
*op.Ops
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -97,7 +98,7 @@ func (c *Context) Reset(cfg ui.Config, cs Constraints) {
|
|||||||
c.Dimensions = Dimensions{}
|
c.Dimensions = Dimensions{}
|
||||||
c.Config = cfg
|
c.Config = cfg
|
||||||
if c.Ops == nil {
|
if c.Ops == nil {
|
||||||
c.Ops = new(ui.Ops)
|
c.Ops = new(op.Ops)
|
||||||
}
|
}
|
||||||
c.Ops.Reset()
|
c.Ops.Reset()
|
||||||
}
|
}
|
||||||
@@ -157,9 +158,9 @@ func (in Inset) Layout(gtx *Context, w Widget) {
|
|||||||
if mcs.Height.Max < mcs.Height.Min {
|
if mcs.Height.Max < mcs.Height.Min {
|
||||||
mcs.Height.Max = mcs.Height.Min
|
mcs.Height.Max = mcs.Height.Min
|
||||||
}
|
}
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
stack.Push(gtx.Ops)
|
stack.Push(gtx.Ops)
|
||||||
ui.TransformOp{}.Offset(toPointF(image.Point{X: left, Y: top})).Add(gtx.Ops)
|
op.TransformOp{}.Offset(toPointF(image.Point{X: left, Y: top})).Add(gtx.Ops)
|
||||||
dims := gtx.Layout(mcs, w)
|
dims := gtx.Layout(mcs, w)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
gtx.Dimensions = Dimensions{
|
gtx.Dimensions = Dimensions{
|
||||||
@@ -176,7 +177,7 @@ func UniformInset(v ui.Value) Inset {
|
|||||||
|
|
||||||
// Layout a widget.
|
// Layout a widget.
|
||||||
func (a Align) Layout(gtx *Context, w Widget) {
|
func (a Align) Layout(gtx *Context, w Widget) {
|
||||||
var macro ui.MacroOp
|
var macro op.MacroOp
|
||||||
macro.Record(gtx.Ops)
|
macro.Record(gtx.Ops)
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
mcs := cs
|
mcs := cs
|
||||||
@@ -204,9 +205,9 @@ func (a Align) Layout(gtx *Context, w Widget) {
|
|||||||
case SW, S, SE:
|
case SW, S, SE:
|
||||||
p.Y = sz.Y - dims.Size.Y
|
p.Y = sz.Y - dims.Size.Y
|
||||||
}
|
}
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
stack.Push(gtx.Ops)
|
stack.Push(gtx.Ops)
|
||||||
ui.TransformOp{}.Offset(toPointF(p)).Add(gtx.Ops)
|
op.TransformOp{}.Offset(toPointF(p)).Add(gtx.Ops)
|
||||||
macro.Add(gtx.Ops)
|
macro.Add(gtx.Ops)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
gtx.Dimensions = Dimensions{
|
gtx.Dimensions = Dimensions{
|
||||||
|
|||||||
+6
-6
@@ -7,13 +7,13 @@ import (
|
|||||||
|
|
||||||
"gioui.org/gesture"
|
"gioui.org/gesture"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
|
"gioui.org/op"
|
||||||
"gioui.org/paint"
|
"gioui.org/paint"
|
||||||
"gioui.org/ui"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type scrollChild struct {
|
type scrollChild struct {
|
||||||
size image.Point
|
size image.Point
|
||||||
macro ui.MacroOp
|
macro op.MacroOp
|
||||||
}
|
}
|
||||||
|
|
||||||
// List displays a subsection of a potentially infinitely
|
// List displays a subsection of a potentially infinitely
|
||||||
@@ -33,8 +33,8 @@ type List struct {
|
|||||||
beforeEnd bool
|
beforeEnd bool
|
||||||
|
|
||||||
ctx *Context
|
ctx *Context
|
||||||
macro ui.MacroOp
|
macro op.MacroOp
|
||||||
child ui.MacroOp
|
child op.MacroOp
|
||||||
scroll gesture.Scroll
|
scroll gesture.Scroll
|
||||||
scrollDelta int
|
scrollDelta int
|
||||||
|
|
||||||
@@ -246,10 +246,10 @@ func (l *List) layout() Dimensions {
|
|||||||
Min: axisPoint(l.Axis, min, -inf),
|
Min: axisPoint(l.Axis, min, -inf),
|
||||||
Max: axisPoint(l.Axis, max, inf),
|
Max: axisPoint(l.Axis, max, inf),
|
||||||
}
|
}
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
stack.Push(ops)
|
stack.Push(ops)
|
||||||
paint.RectClip(r).Add(ops)
|
paint.RectClip(r).Add(ops)
|
||||||
ui.TransformOp{}.Offset(toPointF(axisPoint(l.Axis, pos, cross))).Add(ops)
|
op.TransformOp{}.Offset(toPointF(axisPoint(l.Axis, pos, cross))).Add(ops)
|
||||||
child.macro.Add(ops)
|
child.macro.Add(ops)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
pos += childSize
|
pos += childSize
|
||||||
|
|||||||
+5
-5
@@ -5,7 +5,7 @@ package layout
|
|||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
"gioui.org/ui"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stack lays out child elements on top of each other,
|
// Stack lays out child elements on top of each other,
|
||||||
@@ -15,7 +15,7 @@ type Stack struct {
|
|||||||
// smaller than the available space.
|
// smaller than the available space.
|
||||||
Alignment Direction
|
Alignment Direction
|
||||||
|
|
||||||
macro ui.MacroOp
|
macro op.MacroOp
|
||||||
constrained bool
|
constrained bool
|
||||||
ctx *Context
|
ctx *Context
|
||||||
maxSZ image.Point
|
maxSZ image.Point
|
||||||
@@ -24,7 +24,7 @@ type Stack struct {
|
|||||||
|
|
||||||
// StackChild is the layout result of a call to End.
|
// StackChild is the layout result of a call to End.
|
||||||
type StackChild struct {
|
type StackChild struct {
|
||||||
macro ui.MacroOp
|
macro op.MacroOp
|
||||||
dims Dimensions
|
dims Dimensions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,9 +99,9 @@ func (s *Stack) Layout(children ...StackChild) {
|
|||||||
case SW, S, SE:
|
case SW, S, SE:
|
||||||
p.Y = s.maxSZ.Y - sz.Y
|
p.Y = s.maxSZ.Y - sz.Y
|
||||||
}
|
}
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
stack.Push(s.ctx.Ops)
|
stack.Push(s.ctx.Ops)
|
||||||
ui.TransformOp{}.Offset(toPointF(p)).Add(s.ctx.Ops)
|
op.TransformOp{}.Offset(toPointF(p)).Add(s.ctx.Ops)
|
||||||
ch.macro.Add(s.ctx.Ops)
|
ch.macro.Add(s.ctx.Ops)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -10,10 +10,11 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
|
"gioui.org/op"
|
||||||
"gioui.org/paint"
|
"gioui.org/paint"
|
||||||
"gioui.org/text"
|
"gioui.org/text"
|
||||||
|
"gioui.org/ui"
|
||||||
"golang.org/x/image/font"
|
"golang.org/x/image/font"
|
||||||
"golang.org/x/image/font/sfnt"
|
"golang.org/x/image/font/sfnt"
|
||||||
"golang.org/x/image/math/fixed"
|
"golang.org/x/image/math/fixed"
|
||||||
@@ -34,7 +35,7 @@ type cachedLayout struct {
|
|||||||
|
|
||||||
type cachedPath struct {
|
type cachedPath struct {
|
||||||
active bool
|
active bool
|
||||||
path ui.MacroOp
|
path op.MacroOp
|
||||||
}
|
}
|
||||||
|
|
||||||
type layoutKey struct {
|
type layoutKey struct {
|
||||||
@@ -128,7 +129,7 @@ func (f *Face) Layout(str string, opts text.LayoutOptions) *text.Layout {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Face) Path(str text.String) ui.MacroOp {
|
func (f *Face) Path(str text.String) op.MacroOp {
|
||||||
ppem := fixed.Int26_6(f.faces.config.Px(f.size) * 64)
|
ppem := fixed.Int26_6(f.faces.config.Px(f.size) * 64)
|
||||||
pk := pathKey{
|
pk := pathKey{
|
||||||
f: f.font.Font,
|
f: f.font.Font,
|
||||||
@@ -234,14 +235,14 @@ func layoutText(ppem fixed.Int26_6, str string, f *opentype, opts text.LayoutOpt
|
|||||||
return &text.Layout{Lines: lines}
|
return &text.Layout{Lines: lines}
|
||||||
}
|
}
|
||||||
|
|
||||||
func textPath(ppem fixed.Int26_6, f *opentype, str text.String) ui.MacroOp {
|
func textPath(ppem fixed.Int26_6, f *opentype, str text.String) op.MacroOp {
|
||||||
var lastPos f32.Point
|
var lastPos f32.Point
|
||||||
var builder paint.PathBuilder
|
var builder paint.PathBuilder
|
||||||
ops := new(ui.Ops)
|
ops := new(op.Ops)
|
||||||
builder.Init(ops)
|
builder.Init(ops)
|
||||||
var x fixed.Int26_6
|
var x fixed.Int26_6
|
||||||
var advIdx int
|
var advIdx int
|
||||||
var m ui.MacroOp
|
var m op.MacroOp
|
||||||
m.Record(ops)
|
m.Record(ops)
|
||||||
for _, r := range str.String {
|
for _, r := range str.String {
|
||||||
if !unicode.IsSpace(r) {
|
if !unicode.IsSpace(r) {
|
||||||
|
|||||||
+115
-1
@@ -1,10 +1,67 @@
|
|||||||
// SPDX-License-Identifier: Unlicense OR MIT
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
package ui
|
/*
|
||||||
|
|
||||||
|
Package op implements operations for updating a user interface.
|
||||||
|
|
||||||
|
Gio programs use operations, or ops, for describing their user
|
||||||
|
interfaces. There are operations for drawing, defining input
|
||||||
|
handlers, changing window properties as well as operations for
|
||||||
|
controlling the execution of other operations.
|
||||||
|
|
||||||
|
Ops represents a list of operations. The most important use
|
||||||
|
for an Ops list is to describe a complete user interface update
|
||||||
|
to a ui/app.Window's Update method.
|
||||||
|
|
||||||
|
Drawing a colored square:
|
||||||
|
|
||||||
|
import "gioui.org/ui"
|
||||||
|
import "gioui.org/app"
|
||||||
|
import "gioui.org/paint"
|
||||||
|
|
||||||
|
var w app.Window
|
||||||
|
ops := new(op.Ops)
|
||||||
|
...
|
||||||
|
ops.Reset()
|
||||||
|
paint.ColorOp{Color: ...}.Add(ops)
|
||||||
|
paint.PaintOp{Rect: ...}.Add(ops)
|
||||||
|
w.Update(ops)
|
||||||
|
|
||||||
|
State
|
||||||
|
|
||||||
|
An Ops list can be viewed as a very simple virtual machine: it has an implicit
|
||||||
|
mutable state stack and execution flow can be controlled with macros.
|
||||||
|
|
||||||
|
The StackOp saves the current state to the state stack and restores it later:
|
||||||
|
|
||||||
|
ops := new(op.Ops)
|
||||||
|
var stack op.StackOp
|
||||||
|
// Save the current state, in particular the transform.
|
||||||
|
stack.Push(ops)
|
||||||
|
// Apply a transform to subsequent operations.
|
||||||
|
op.TransformOp{}.Offset(...).Add(ops)
|
||||||
|
...
|
||||||
|
// Restore the previous transform.
|
||||||
|
stack.Pop()
|
||||||
|
|
||||||
|
The MacroOp records a list of operations to be executed later:
|
||||||
|
|
||||||
|
ops := new(op.Ops)
|
||||||
|
var macro op.MacroOp
|
||||||
|
macro.Record()
|
||||||
|
// Record operations by adding them.
|
||||||
|
op.InvalidateOp{}.Add(ops)
|
||||||
|
...
|
||||||
|
|
||||||
|
*/
|
||||||
|
package op
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -45,6 +102,18 @@ type MacroOp struct {
|
|||||||
pc pc
|
pc pc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InvalidateOp requests a redraw at the given time. Use
|
||||||
|
// the zero value to request an immediate redraw.
|
||||||
|
type InvalidateOp struct {
|
||||||
|
At time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransformOp applies a transform to the current transform.
|
||||||
|
type TransformOp struct {
|
||||||
|
// TODO: general transformations.
|
||||||
|
offset f32.Point
|
||||||
|
}
|
||||||
|
|
||||||
type pc struct {
|
type pc struct {
|
||||||
data int
|
data int
|
||||||
refs int
|
refs int
|
||||||
@@ -208,3 +277,48 @@ func (m MacroOp) Add(o *Ops) {
|
|||||||
bo.PutUint32(data[9:], uint32(m.version))
|
bo.PutUint32(data[9:], uint32(m.version))
|
||||||
o.Write(data, m.ops)
|
o.Write(data, m.ops)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r InvalidateOp) Add(o *Ops) {
|
||||||
|
data := make([]byte, opconst.TypeRedrawLen)
|
||||||
|
data[0] = byte(opconst.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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset the transformation.
|
||||||
|
func (t TransformOp) Offset(o f32.Point) TransformOp {
|
||||||
|
return t.Multiply(TransformOp{o})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert the transformation.
|
||||||
|
func (t TransformOp) Invert() TransformOp {
|
||||||
|
return TransformOp{offset: t.offset.Mul(-1)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform a point.
|
||||||
|
func (t TransformOp) Transform(p f32.Point) f32.Point {
|
||||||
|
return p.Add(t.offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply by a transformation.
|
||||||
|
func (t TransformOp) Multiply(t2 TransformOp) TransformOp {
|
||||||
|
return TransformOp{
|
||||||
|
offset: t.offset.Add(t2.offset),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t TransformOp) Add(o *Ops) {
|
||||||
|
data := make([]byte, opconst.TypeTransformLen)
|
||||||
|
data[0] = byte(opconst.TypeTransform)
|
||||||
|
bo := binary.LittleEndian
|
||||||
|
bo.PutUint32(data[1:], math.Float32bits(t.offset.X))
|
||||||
|
bo.PutUint32(data[5:], math.Float32bits(t.offset.Y))
|
||||||
|
o.Write(data)
|
||||||
|
}
|
||||||
+4
-4
@@ -8,9 +8,9 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImageOp sets the material to a section of an
|
// ImageOp sets the material to a section of an
|
||||||
@@ -33,7 +33,7 @@ type PaintOp struct {
|
|||||||
Rect f32.Rectangle
|
Rect f32.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i ImageOp) Add(o *ui.Ops) {
|
func (i ImageOp) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypeImageLen)
|
data := make([]byte, opconst.TypeImageLen)
|
||||||
data[0] = byte(opconst.TypeImage)
|
data[0] = byte(opconst.TypeImage)
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
@@ -44,7 +44,7 @@ func (i ImageOp) Add(o *ui.Ops) {
|
|||||||
o.Write(data, i.Src)
|
o.Write(data, i.Src)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ColorOp) Add(o *ui.Ops) {
|
func (c ColorOp) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypeColorLen)
|
data := make([]byte, opconst.TypeColorLen)
|
||||||
data[0] = byte(opconst.TypeColor)
|
data[0] = byte(opconst.TypeColor)
|
||||||
data[1] = c.Color.R
|
data[1] = c.Color.R
|
||||||
@@ -54,7 +54,7 @@ func (c ColorOp) Add(o *ui.Ops) {
|
|||||||
o.Write(data)
|
o.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d PaintOp) Add(o *ui.Ops) {
|
func (d PaintOp) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypePaintLen)
|
data := make([]byte, opconst.TypePaintLen)
|
||||||
data[0] = byte(opconst.TypePaint)
|
data[0] = byte(opconst.TypePaint)
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
|
|||||||
+4
-4
@@ -7,10 +7,10 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
"gioui.org/internal/path"
|
"gioui.org/internal/path"
|
||||||
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PathBuilder builds and adds a general ClipOp clip path
|
// PathBuilder builds and adds a general ClipOp clip path
|
||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
// dynamic paths; path data is stored directly in the Ops
|
// dynamic paths; path data is stored directly in the Ops
|
||||||
// list supplied to Init.
|
// list supplied to Init.
|
||||||
type PathBuilder struct {
|
type PathBuilder struct {
|
||||||
ops *ui.Ops
|
ops *op.Ops
|
||||||
firstVert int
|
firstVert int
|
||||||
nverts int
|
nverts int
|
||||||
maxy float32
|
maxy float32
|
||||||
@@ -33,7 +33,7 @@ type ClipOp struct {
|
|||||||
bounds f32.Rectangle
|
bounds f32.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ClipOp) Add(o *ui.Ops) {
|
func (p ClipOp) Add(o *op.Ops) {
|
||||||
data := make([]byte, opconst.TypeClipLen)
|
data := make([]byte, opconst.TypeClipLen)
|
||||||
data[0] = byte(opconst.TypeClip)
|
data[0] = byte(opconst.TypeClip)
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
@@ -46,7 +46,7 @@ func (p ClipOp) Add(o *ui.Ops) {
|
|||||||
|
|
||||||
// Init the builder and specify the operations list for
|
// Init the builder and specify the operations list for
|
||||||
// storing the path data and final ClipOp.
|
// storing the path data and final ClipOp.
|
||||||
func (p *PathBuilder) Init(ops *ui.Ops) {
|
func (p *PathBuilder) Init(ops *op.Ops) {
|
||||||
p.ops = ops
|
p.ops = ops
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -14,6 +14,7 @@ import (
|
|||||||
"gioui.org/io/key"
|
"gioui.org/io/key"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
|
"gioui.org/op"
|
||||||
"gioui.org/paint"
|
"gioui.org/paint"
|
||||||
"gioui.org/ui"
|
"gioui.org/ui"
|
||||||
|
|
||||||
@@ -33,12 +34,12 @@ type Editor struct {
|
|||||||
Submit bool
|
Submit bool
|
||||||
|
|
||||||
// Material for drawing the text.
|
// Material for drawing the text.
|
||||||
Material ui.MacroOp
|
Material op.MacroOp
|
||||||
// Hint contains the text displayed to the user when the
|
// Hint contains the text displayed to the user when the
|
||||||
// Editor is empty.
|
// Editor is empty.
|
||||||
Hint string
|
Hint string
|
||||||
// Mmaterial is used to draw the hint.
|
// Mmaterial is used to draw the hint.
|
||||||
HintMaterial ui.MacroOp
|
HintMaterial op.MacroOp
|
||||||
|
|
||||||
oldScale int
|
oldScale int
|
||||||
blinkStart time.Time
|
blinkStart time.Time
|
||||||
@@ -218,7 +219,7 @@ func (e *Editor) Layout(gtx *layout.Context) {
|
|||||||
Width: e.viewWidth(),
|
Width: e.viewWidth(),
|
||||||
Offset: off,
|
Offset: off,
|
||||||
}
|
}
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
stack.Push(gtx.Ops)
|
stack.Push(gtx.Ops)
|
||||||
// Apply material. Set a default color in case the material is empty.
|
// Apply material. Set a default color in case the material is empty.
|
||||||
if e.rr.len() > 0 {
|
if e.rr.len() > 0 {
|
||||||
@@ -233,9 +234,9 @@ func (e *Editor) Layout(gtx *layout.Context) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
stack.Push(gtx.Ops)
|
stack.Push(gtx.Ops)
|
||||||
ui.TransformOp{}.Offset(lineOff).Add(gtx.Ops)
|
op.TransformOp{}.Offset(lineOff).Add(gtx.Ops)
|
||||||
e.Face.Path(str).Add(gtx.Ops)
|
e.Face.Path(str).Add(gtx.Ops)
|
||||||
paint.PaintOp{Rect: toRectF(clip).Sub(lineOff)}.Add(gtx.Ops)
|
paint.PaintOp{Rect: toRectF(clip).Sub(lineOff)}.Add(gtx.Ops)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
@@ -267,7 +268,7 @@ func (e *Editor) Layout(gtx *layout.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if blinking {
|
if blinking {
|
||||||
redraw := ui.InvalidateOp{At: nextBlink}
|
redraw := op.InvalidateOp{At: nextBlink}
|
||||||
redraw.Add(gtx.Ops)
|
redraw.Add(gtx.Ops)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -8,9 +8,9 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
|
"gioui.org/op"
|
||||||
"gioui.org/paint"
|
"gioui.org/paint"
|
||||||
|
|
||||||
"golang.org/x/image/math/fixed"
|
"golang.org/x/image/math/fixed"
|
||||||
@@ -22,7 +22,7 @@ type Label struct {
|
|||||||
Face Face
|
Face Face
|
||||||
// Material is a macro recording the material to draw the
|
// Material is a macro recording the material to draw the
|
||||||
// text. Use a ColorOp for colored text.
|
// text. Use a ColorOp for colored text.
|
||||||
Material ui.MacroOp
|
Material op.MacroOp
|
||||||
// Alignment specify the text alignment.
|
// Alignment specify the text alignment.
|
||||||
Alignment Alignment
|
Alignment Alignment
|
||||||
// Text is the string to draw.
|
// Text is the string to draw.
|
||||||
@@ -118,9 +118,9 @@ func (l Label) Layout(gtx *layout.Context) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
lclip := toRectF(clip).Sub(off)
|
lclip := toRectF(clip).Sub(off)
|
||||||
var stack ui.StackOp
|
var stack op.StackOp
|
||||||
stack.Push(gtx.Ops)
|
stack.Push(gtx.Ops)
|
||||||
ui.TransformOp{}.Offset(off).Add(gtx.Ops)
|
op.TransformOp{}.Offset(off).Add(gtx.Ops)
|
||||||
l.Face.Path(str).Add(gtx.Ops)
|
l.Face.Path(str).Add(gtx.Ops)
|
||||||
// Set a default color in case the material is empty.
|
// Set a default color in case the material is empty.
|
||||||
paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(gtx.Ops)
|
paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(gtx.Ops)
|
||||||
|
|||||||
+2
-2
@@ -6,8 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
"gioui.org/ui"
|
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
|
"gioui.org/op"
|
||||||
"golang.org/x/image/math/fixed"
|
"golang.org/x/image/math/fixed"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ type Face interface {
|
|||||||
// options.
|
// options.
|
||||||
Layout(s string, opts LayoutOptions) *Layout
|
Layout(s string, opts LayoutOptions) *Layout
|
||||||
// Path returns the ClipOp outline of a text recorded in a macro.
|
// Path returns the ClipOp outline of a text recorded in a macro.
|
||||||
Path(s String) ui.MacroOp
|
Path(s String) op.MacroOp
|
||||||
}
|
}
|
||||||
|
|
||||||
type Alignment uint8
|
type Alignment uint8
|
||||||
|
|||||||
@@ -4,64 +4,6 @@
|
|||||||
Package ui defines operations buffers, units and common operations
|
Package ui defines operations buffers, units and common operations
|
||||||
for GUI programs written with the Gio module.
|
for GUI programs written with the Gio module.
|
||||||
|
|
||||||
Operations
|
|
||||||
|
|
||||||
Gio programs use operations, or ops, for describing their user
|
|
||||||
interfaces. There are operations for drawing, defining input
|
|
||||||
handlers, changing window properties as well as operations for
|
|
||||||
controlling the execution of other operations.
|
|
||||||
|
|
||||||
Ops represents a list of operations. The most important use
|
|
||||||
for an Ops list is to describe a complete user interface update
|
|
||||||
to a ui/app.Window's Update method.
|
|
||||||
|
|
||||||
Drawing a colored square:
|
|
||||||
|
|
||||||
import "gioui.org/ui"
|
|
||||||
import "gioui.org/app"
|
|
||||||
import "gioui.org/paint"
|
|
||||||
|
|
||||||
var w app.Window
|
|
||||||
ops := new(ui.Ops)
|
|
||||||
...
|
|
||||||
ops.Reset()
|
|
||||||
paint.ColorOp{Color: ...}.Add(ops)
|
|
||||||
paint.PaintOp{Rect: ...}.Add(ops)
|
|
||||||
w.Update(ops)
|
|
||||||
|
|
||||||
State
|
|
||||||
|
|
||||||
An Ops list can be viewed as a very simple virtual machine: it has an implicit
|
|
||||||
mutable state stack and execution flow can be controlled with macros.
|
|
||||||
|
|
||||||
The StackOp saves the current state to the state stack and restores it later:
|
|
||||||
|
|
||||||
ops := new(ui.Ops)
|
|
||||||
var stack ui.StackOp
|
|
||||||
// Save the current state, in particular the transform.
|
|
||||||
stack.Push(ops)
|
|
||||||
// Apply a transform to subsequent operations.
|
|
||||||
ui.TransformOp{}.Offset(...).Add(ops)
|
|
||||||
...
|
|
||||||
// Restore the previous transform.
|
|
||||||
stack.Pop()
|
|
||||||
|
|
||||||
The MacroOp records a list of operations to be executed later:
|
|
||||||
|
|
||||||
ops := new(ui.Ops)
|
|
||||||
var macro ui.MacroOp
|
|
||||||
macro.Record()
|
|
||||||
// Record operations by adding them.
|
|
||||||
ui.InvalidateOp{}.Add(ops)
|
|
||||||
...
|
|
||||||
macro.Stop()
|
|
||||||
...
|
|
||||||
// Execute the recorded operations.
|
|
||||||
macro.Add(ops)
|
|
||||||
|
|
||||||
Note that operations added between Record and Stop are not executed until
|
|
||||||
the macro is Added.
|
|
||||||
|
|
||||||
Units
|
Units
|
||||||
|
|
||||||
A Value is a value with a Unit attached.
|
A Value is a value with a Unit attached.
|
||||||
|
|||||||
@@ -3,12 +3,7 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"math"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gioui.org/f32"
|
|
||||||
"gioui.org/internal/opconst"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config define the essential properties of
|
// Config define the essential properties of
|
||||||
@@ -19,60 +14,3 @@ type Config interface {
|
|||||||
// Px converts a Value to pixels.
|
// Px converts a Value to pixels.
|
||||||
Px(v Value) int
|
Px(v Value) int
|
||||||
}
|
}
|
||||||
|
|
||||||
// InvalidateOp requests a redraw at the given time. Use
|
|
||||||
// the zero value to request an immediate redraw.
|
|
||||||
type InvalidateOp struct {
|
|
||||||
At time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransformOp applies a transform to the current transform.
|
|
||||||
type TransformOp struct {
|
|
||||||
// TODO: general transformations.
|
|
||||||
offset f32.Point
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r InvalidateOp) Add(o *Ops) {
|
|
||||||
data := make([]byte, opconst.TypeRedrawLen)
|
|
||||||
data[0] = byte(opconst.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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset the transformation.
|
|
||||||
func (t TransformOp) Offset(o f32.Point) TransformOp {
|
|
||||||
return t.Multiply(TransformOp{o})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invert the transformation.
|
|
||||||
func (t TransformOp) Invert() TransformOp {
|
|
||||||
return TransformOp{offset: t.offset.Mul(-1)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform a point.
|
|
||||||
func (t TransformOp) Transform(p f32.Point) f32.Point {
|
|
||||||
return p.Add(t.offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiply by a transformation.
|
|
||||||
func (t TransformOp) Multiply(t2 TransformOp) TransformOp {
|
|
||||||
return TransformOp{
|
|
||||||
offset: t.offset.Add(t2.offset),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t TransformOp) Add(o *Ops) {
|
|
||||||
data := make([]byte, opconst.TypeTransformLen)
|
|
||||||
data[0] = byte(opconst.TypeTransform)
|
|
||||||
bo := binary.LittleEndian
|
|
||||||
bo.PutUint32(data[1:], math.Float32bits(t.offset.X))
|
|
||||||
bo.PutUint32(data[5:], math.Float32bits(t.offset.Y))
|
|
||||||
o.Write(data)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user