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 <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-07-10 22:55:16 +02:00
parent f44ccec043
commit 4fadf71992
4 changed files with 80 additions and 55 deletions
+58 -2
View File
@@ -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")
}
}
+1 -1
View File
@@ -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}
+20 -51
View File
@@ -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)
+1 -1
View File
@@ -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}