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}