From 4fadf71992ffd469b297c1994d05acb2c5716409 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 10 Jul 2019 22:55:16 +0200 Subject: [PATCH] ui/pointer: split AreaOp into RectAreaOp and EllipseAreaOp Now that the pass through mode is moved into its own PassOp op, it doesn't make sense to collect all area types into one exported type. Add RectAreaOp and EllipseAreaOp for clients; the internal representation is still a single op. It can be changed later without breaking clients. Signed-off-by: Elias Naur --- ui/input/pointer.go | 60 ++++++++++++++++++++++++++++++++++-- ui/layout/list.go | 2 +- ui/pointer/pointer.go | 71 ++++++++++++------------------------------- ui/text/editor.go | 2 +- 4 files changed, 80 insertions(+), 55 deletions(-) diff --git a/ui/input/pointer.go b/ui/input/pointer.go index 4bd79457..6fc3eaa4 100644 --- a/ui/input/pointer.go +++ b/ui/input/pointer.go @@ -3,6 +3,9 @@ package input import ( + "encoding/binary" + "image" + "gioui.org/ui" "gioui.org/ui/f32" "gioui.org/ui/internal/ops" @@ -41,12 +44,24 @@ type pointerHandler struct { wantsGrab bool } +type areaOp struct { + kind areaKind + size image.Point +} + type areaNode struct { trans ui.Transform next int - area pointer.AreaOp + area areaOp } +type areaKind uint8 + +const ( + areaRect areaKind = iota + areaEllipse +) + func (q *pointerQueue) collectHandlers(r *ui.OpsReader, events handlerEvents, t ui.Transform, area, node int, pass bool) { for { encOp, ok := r.Decode() @@ -63,7 +78,7 @@ func (q *pointerQueue) collectHandlers(r *ui.OpsReader, events handlerEvents, t op.Decode(encOp.Data) pass = op.Pass case ops.TypeArea: - var op pointer.AreaOp + var op areaOp op.Decode(encOp.Data) q.areas = append(q.areas, areaNode{trans: t, next: area, area: op}) area = len(q.areas) - 1 @@ -257,3 +272,44 @@ func (q *pointerQueue) Push(e pointer.Event, events handlerEvents) { } } } + +func (op *areaOp) Decode(d []byte) { + if ops.OpType(d[0]) != ops.TypeArea { + panic("invalid op") + } + bo := binary.LittleEndian + size := image.Point{ + X: int(bo.Uint32(d[2:])), + Y: int(bo.Uint32(d[6:])), + } + *op = areaOp{ + kind: areaKind(d[1]), + size: size, + } +} + +func (op *areaOp) Hit(pos f32.Point) bool { + switch op.kind { + case areaRect: + if 0 <= pos.X && pos.X < float32(op.size.X) && + 0 <= pos.Y && pos.Y < float32(op.size.Y) { + return true + } else { + return false + } + case areaEllipse: + rx := float32(op.size.X) / 2 + ry := float32(op.size.Y) / 2 + rx2 := rx * rx + ry2 := ry * ry + xh := pos.X - rx + yk := pos.Y - ry + if xh*xh*ry2+yk*yk*rx2 <= rx2*ry2 { + return true + } else { + return false + } + default: + panic("invalid area kind") + } +} diff --git a/ui/layout/list.go b/ui/layout/list.go index 8a63ad37..476f591f 100644 --- a/ui/layout/list.go +++ b/ui/layout/list.go @@ -209,7 +209,7 @@ func (l *List) Layout() Dimens { } dims := axisPoint(l.Axis, mainc.Constrain(pos), maxCross) block := ops.End() - pointer.AreaRect(dims).Add(ops) + pointer.RectAreaOp{Size: dims}.Add(ops) l.scroll.Add(ops) block.Add(ops) return Dimens{Size: dims} diff --git a/ui/pointer/pointer.go b/ui/pointer/pointer.go index 325cadb5..5ed446d4 100644 --- a/ui/pointer/pointer.go +++ b/ui/pointer/pointer.go @@ -23,7 +23,16 @@ type Event struct { Scroll f32.Point } -type AreaOp struct { +type RectAreaOp struct { + Size image.Point +} + +type EllipseAreaOp struct { + Size image.Point +} + +// Must match the structure in input.areaOp +type areaOp struct { kind areaKind size image.Point } @@ -46,6 +55,7 @@ type Type uint8 type Priority uint8 type Source uint8 +// Must match input.areaKind type areaKind uint8 const ( @@ -71,21 +81,21 @@ const ( areaEllipse ) -func AreaRect(size image.Point) AreaOp { - return AreaOp{ +func (op RectAreaOp) Add(ops *ui.Ops) { + areaOp{ kind: areaRect, - size: size, - } + size: op.Size, + }.add(ops) } -func AreaEllipse(size image.Point) AreaOp { - return AreaOp{ +func (op EllipseAreaOp) Add(ops *ui.Ops) { + areaOp{ kind: areaEllipse, - size: size, - } + size: op.Size, + }.add(ops) } -func (op AreaOp) Add(o *ui.Ops) { +func (op areaOp) add(o *ui.Ops) { data := make([]byte, ops.TypeAreaLen) data[0] = byte(ops.TypeArea) data[1] = byte(op.kind) @@ -95,47 +105,6 @@ func (op AreaOp) Add(o *ui.Ops) { o.Write(data) } -func (op *AreaOp) Decode(d []byte) { - if ops.OpType(d[0]) != ops.TypeArea { - panic("invalid op") - } - bo := binary.LittleEndian - size := image.Point{ - X: int(bo.Uint32(d[2:])), - Y: int(bo.Uint32(d[6:])), - } - *op = AreaOp{ - kind: areaKind(d[1]), - size: size, - } -} - -func (op *AreaOp) Hit(pos f32.Point) bool { - switch op.kind { - case areaRect: - if 0 <= pos.X && pos.X < float32(op.size.X) && - 0 <= pos.Y && pos.Y < float32(op.size.Y) { - return true - } else { - return false - } - case areaEllipse: - rx := float32(op.size.X) / 2 - ry := float32(op.size.Y) / 2 - rx2 := rx * rx - ry2 := ry * ry - xh := pos.X - rx - yk := pos.Y - ry - if xh*xh*ry2+yk*yk*rx2 <= rx2*ry2 { - return true - } else { - return false - } - default: - panic("invalid area kind") - } -} - func (h HandlerOp) Add(o *ui.Ops) { data := make([]byte, ops.TypePointerHandlerLen) data[0] = byte(ops.TypePointerHandler) diff --git a/ui/text/editor.go b/ui/text/editor.go index 767c1e87..0e21791e 100644 --- a/ui/text/editor.go +++ b/ui/text/editor.go @@ -259,7 +259,7 @@ func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens { ui.PopOp{}.Add(ops) baseline := e.padTop + e.dims.Baseline - pointer.AreaRect(e.viewSize).Add(ops) + pointer.RectAreaOp{Size: e.viewSize}.Add(ops) e.scroller.Add(ops) e.clicker.Add(ops) return layout.Dimens{Size: e.viewSize, Baseline: baseline}