forked from joejulian/gio
widget,gesture: fade out cancelled inkwells
While here, adjust inkwell sizes to match gtx.Constraints.Min. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -147,6 +147,8 @@ func (c *Click) Events(q event.Queue) []ClickEvent {
|
|||||||
}
|
}
|
||||||
c.clickedAt = e.Time
|
c.clickedAt = e.Time
|
||||||
events = append(events, ClickEvent{Type: TypeClick, Position: e.Position, Source: e.Source, Modifiers: e.Modifiers, NumClicks: c.clicks})
|
events = append(events, ClickEvent{Type: TypeClick, Position: e.Position, Source: e.Source, Modifiers: e.Modifiers, NumClicks: c.clicks})
|
||||||
|
} else {
|
||||||
|
events = append(events, ClickEvent{Type: TypeCancel})
|
||||||
}
|
}
|
||||||
case pointer.Cancel:
|
case pointer.Cancel:
|
||||||
wasPressed := c.state == StatePressed
|
wasPressed := c.state == StatePressed
|
||||||
@@ -304,6 +306,8 @@ func (ct ClickType) String() string {
|
|||||||
return "TypePress"
|
return "TypePress"
|
||||||
case TypeClick:
|
case TypeClick:
|
||||||
return "TypeClick"
|
return "TypeClick"
|
||||||
|
case TypeCancel:
|
||||||
|
return "TypeCancel"
|
||||||
default:
|
default:
|
||||||
panic("invalid ClickType")
|
panic("invalid ClickType")
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -2,6 +2,7 @@ package widget
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gioui.org/gesture"
|
"gioui.org/gesture"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
@@ -31,8 +32,10 @@ func (b *Bool) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
for _, e := range b.gesture.Events(gtx) {
|
for _, e := range b.gesture.Events(gtx) {
|
||||||
switch e.Type {
|
switch e.Type {
|
||||||
case gesture.TypeClick:
|
case gesture.TypeClick:
|
||||||
|
now := gtx.Now()
|
||||||
b.Last = Press{
|
b.Last = Press{
|
||||||
Time: gtx.Now(),
|
Start: now,
|
||||||
|
End: now.Add(time.Second),
|
||||||
Position: e.Position,
|
Position: e.Position,
|
||||||
}
|
}
|
||||||
b.Value = !b.Value
|
b.Value = !b.Value
|
||||||
|
|||||||
+15
-5
@@ -33,8 +33,13 @@ type Click struct {
|
|||||||
|
|
||||||
// Press represents a past pointer press.
|
// Press represents a past pointer press.
|
||||||
type Press struct {
|
type Press struct {
|
||||||
|
// Position of the press.
|
||||||
Position f32.Point
|
Position f32.Point
|
||||||
Time time.Time
|
// Start is when the press began.
|
||||||
|
Start time.Time
|
||||||
|
// End is when the press was ended by a release or cancel.
|
||||||
|
// A zero End means it hasn't ended yet.
|
||||||
|
End time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clicked reports whether there are pending clicks as would be
|
// Clicked reports whether there are pending clicks as would be
|
||||||
@@ -73,7 +78,7 @@ func (b *Clickable) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
stack.Pop()
|
stack.Pop()
|
||||||
for len(b.history) > 0 {
|
for len(b.history) > 0 {
|
||||||
c := b.history[0]
|
c := b.history[0]
|
||||||
if gtx.Now().Sub(c.Time) < 1*time.Second {
|
if c.End.IsZero() || gtx.Now().Sub(c.Start) < 1*time.Second {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
n := copy(b.history, b.history[1:])
|
n := copy(b.history, b.history[1:])
|
||||||
@@ -91,17 +96,22 @@ func (b *Clickable) update(gtx layout.Context) {
|
|||||||
|
|
||||||
for _, e := range b.click.Events(gtx) {
|
for _, e := range b.click.Events(gtx) {
|
||||||
switch e.Type {
|
switch e.Type {
|
||||||
case gesture.TypeCancel:
|
|
||||||
b.history = nil
|
|
||||||
case gesture.TypeClick:
|
case gesture.TypeClick:
|
||||||
b.clicks = append(b.clicks, Click{
|
b.clicks = append(b.clicks, Click{
|
||||||
Modifiers: e.Modifiers,
|
Modifiers: e.Modifiers,
|
||||||
NumClicks: e.NumClicks,
|
NumClicks: e.NumClicks,
|
||||||
})
|
})
|
||||||
|
fallthrough
|
||||||
|
case gesture.TypeCancel:
|
||||||
|
for i := range b.history {
|
||||||
|
if b.history[i].End.IsZero() {
|
||||||
|
b.history[i].End = gtx.Now()
|
||||||
|
}
|
||||||
|
}
|
||||||
case gesture.TypePress:
|
case gesture.TypePress:
|
||||||
b.history = append(b.history, Press{
|
b.history = append(b.history, Press{
|
||||||
Position: e.Position,
|
Position: e.Position,
|
||||||
Time: gtx.Now(),
|
Start: gtx.Now(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package material
|
|||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
"math"
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
@@ -190,20 +191,37 @@ func (b IconButtonStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
|
|
||||||
func drawInk(gtx layout.Context, c widget.Press) {
|
func drawInk(gtx layout.Context, c widget.Press) {
|
||||||
now := gtx.Now()
|
now := gtx.Now()
|
||||||
age := now.Sub(c.Time)
|
age := now.Sub(c.Start)
|
||||||
t := float32(age.Seconds())
|
t := float32(age.Seconds())
|
||||||
const duration = 0.5
|
const duration = 0.4
|
||||||
if t > duration {
|
t = t / duration
|
||||||
|
if t > 1.0 {
|
||||||
|
if c.Start.IsZero() || !c.End.IsZero() {
|
||||||
// Too old.
|
// Too old.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t = t / duration
|
t = 1.0
|
||||||
|
}
|
||||||
defer op.Push(gtx.Ops).Pop()
|
defer op.Push(gtx.Ops).Pop()
|
||||||
size := float32(gtx.Px(unit.Dp(700))) * t
|
t2 := t
|
||||||
rr := size * .5
|
if t2 > 1.0 {
|
||||||
col := byte(0xcc * t * t)
|
t2 = 2.0 - t2
|
||||||
ink := paint.ColorOp{Color: color.RGBA{A: col, R: col, G: col, B: col}}
|
}
|
||||||
|
bezierBlend := t2 * t2 * (3.0 - 2.0*t2)
|
||||||
|
size := float32(gtx.Constraints.Min.X)
|
||||||
|
if h := float32(gtx.Constraints.Min.Y); h > size {
|
||||||
|
size = h
|
||||||
|
}
|
||||||
|
// Cover the entire constraints min rectangle.
|
||||||
|
size *= 2 * float32(math.Sqrt(2))
|
||||||
|
// Animate.
|
||||||
|
size *= bezierBlend
|
||||||
|
alpha := 0.7 * bezierBlend
|
||||||
|
const col = 0.8
|
||||||
|
ba, bc := byte(alpha*0xff), byte(alpha*col*0xff)
|
||||||
|
ink := paint.ColorOp{Color: color.RGBA{A: ba, R: bc, G: bc, B: bc}}
|
||||||
ink.Add(gtx.Ops)
|
ink.Add(gtx.Ops)
|
||||||
|
rr := size * .5
|
||||||
op.TransformOp{}.Offset(c.Position).Offset(f32.Point{
|
op.TransformOp{}.Offset(c.Position).Offset(f32.Point{
|
||||||
X: -rr,
|
X: -rr,
|
||||||
Y: -rr,
|
Y: -rr,
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
},
|
},
|
||||||
NE: rr, NW: rr, SE: rr, SW: rr,
|
NE: rr, NW: rr, SE: rr, SW: rr,
|
||||||
}.Op(gtx.Ops).Add(gtx.Ops)
|
}.Op(gtx.Ops).Add(gtx.Ops)
|
||||||
|
dims := image.Point{X: trackWidth, Y: thumbSize}
|
||||||
|
gtx.Constraints.Min = dims
|
||||||
drawInk(gtx, s.Switch.Last)
|
drawInk(gtx, s.Switch.Last)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
|
|
||||||
@@ -108,7 +110,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
s.Switch.Layout(gtx)
|
s.Switch.Layout(gtx)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
|
|
||||||
return layout.Dimensions{Size: image.Point{X: trackWidth, Y: thumbSize}}
|
return layout.Dimensions{Size: dims}
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawDisc(ops *op.Ops, sz float32, col color.RGBA) {
|
func drawDisc(ops *op.Ops, sz float32, col color.RGBA) {
|
||||||
|
|||||||
Reference in New Issue
Block a user