Files
gio-patched/widget/button.go
T
Elias Naur fd2cb4a7a1 widget,widget/material: use constraints for setting up hit area
Before this change, the widget.Button.Layout method assumed the caller had set
up the pointer hit area before. Further, the very common rectangular hit
areas needed both an AreaOp and a widget.Button.Layout call.

Make widget.Button less subtle and more useful by setting up a
pointer hit area given by the incoming minimum constraints.

Drop a pointer.AreaOp made redundant by the change.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-11 12:37:08 +02:00

77 lines
1.4 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
package widget
import (
"image"
"time"
"gioui.org/f32"
"gioui.org/gesture"
"gioui.org/io/pointer"
"gioui.org/layout"
"gioui.org/op"
)
type Button struct {
click gesture.Click
// clicks tracks the number of unreported clicks.
clicks int
history []Click
}
// Click represents a past click.
type Click struct {
Position f32.Point
Time time.Time
}
func (b *Button) Clicked(gtx *layout.Context) bool {
b.processEvents(gtx)
if b.clicks > 0 {
b.clicks--
if b.clicks > 0 {
// Ensure timely delivery of remaining clicks.
op.InvalidateOp{}.Add(gtx.Ops)
}
return true
}
return false
}
func (b *Button) History() []Click {
return b.history
}
func (b *Button) Layout(gtx *layout.Context) {
// Flush clicks from before the previous frame.
b.processEvents(gtx)
var st op.StackOp
st.Push(gtx.Ops)
pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min()}).Add(gtx.Ops)
b.click.Add(gtx.Ops)
st.Pop()
for len(b.history) > 0 {
c := b.history[0]
if gtx.Now().Sub(c.Time) < 1*time.Second {
break
}
copy(b.history, b.history[1:])
b.history = b.history[:len(b.history)-1]
}
}
func (b *Button) processEvents(gtx *layout.Context) {
for _, e := range b.click.Events(gtx) {
switch e.Type {
case gesture.TypeClick:
b.clicks++
case gesture.TypePress:
b.history = append(b.history, Click{
Position: e.Position,
Time: gtx.Now(),
})
}
}
}