-
Notifications
You must be signed in to change notification settings - Fork 124
/
widgets.go
127 lines (109 loc) · 2.72 KB
/
widgets.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"image"
"image/color"
"time"
"gioui.org/font"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget"
"gioui.org/widget/material"
)
// SourceLine is a single-line of text.
type SourceLine struct {
TopLeft image.Point
Width int
Text string
TextHeight unit.Sp
Italic bool
Bold bool
Color color.NRGBA
}
// Layout draws the text.
func (line SourceLine) Layout(th *material.Theme, gtx layout.Context) {
gtx.Constraints.Min.X = 0
gtx.Constraints.Max.X = maxLineWidth
gtx.Constraints.Min.Y = 0
gtx.Constraints.Max.Y = maxLineWidth
defer op.Offset(line.TopLeft).Push(gtx.Ops).Pop()
if line.Width > 0 {
maxSize := image.Pt(line.Width, gtx.Metric.Sp(line.TextHeight))
defer clip.Rect{Max: maxSize}.Push(gtx.Ops).Pop()
}
f := font.Font{Typeface: "override-monospace,Go,monospace", Weight: font.Normal}
if line.Italic {
f.Style = font.Italic
}
if line.Bold {
f.Weight = font.Black
}
paint.ColorOp{Color: line.Color}.Add(gtx.Ops)
widget.Label{MaxLines: 1}.Layout(gtx, th.Shaper, f, line.TextHeight, line.Text, op.CallOp{})
}
type VerticalLine struct {
Width unit.Dp
Color color.NRGBA
}
func (line VerticalLine) Layout(gtx layout.Context) layout.Dimensions {
size := image.Point{
X: gtx.Metric.Dp(line.Width),
Y: gtx.Constraints.Min.Y,
}
paint.FillShape(gtx.Ops, line.Color, clip.Rect{Max: size}.Op())
return layout.Dimensions{
Size: size,
}
}
type HorizontalLine struct {
Height unit.Dp
Color color.NRGBA
}
func (line HorizontalLine) Layout(gtx layout.Context) layout.Dimensions {
size := image.Point{
X: gtx.Constraints.Min.X,
Y: gtx.Metric.Dp(line.Height),
}
paint.FillShape(gtx.Ops, line.Color, clip.Rect{Max: size}.Op())
return layout.Dimensions{
Size: size,
}
}
type ScrollAnimation struct {
active bool
from, to float32
duration time.Duration
start time.Time
}
func (anim *ScrollAnimation) Start(gtx layout.Context, from, to float32, duration time.Duration) {
anim.active = true
anim.from = from
anim.to = to
anim.duration = duration
anim.start = gtx.Now
op.InvalidateOp{}.Add(gtx.Ops)
}
func (anim *ScrollAnimation) Stop() { anim.active = false }
func (anim *ScrollAnimation) Update(gtx layout.Context) (float32, bool) {
if !anim.active {
return anim.to, false
}
op.InvalidateOp{}.Add(gtx.Ops)
elapsed := gtx.Now.Sub(anim.start)
if elapsed > anim.duration {
anim.active = false
return anim.to, true
}
progress := float32(elapsed) / float32(anim.duration)
progress = easeInOutCubic(progress)
pos := anim.from + progress*(anim.to-anim.from)
return pos, true
}
func easeInOutCubic(t float32) float32 {
if t < .5 {
return 4 * t * t * t
}
return (t-1)*(2*t-2)*(2*t-2) + 1
}