progressbar.go raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 package material
4
5 import (
6 "image"
7 "image/color"
8
9 "github.com/p9c/p9/pkg/gel/gio/f32"
10 "github.com/p9c/p9/pkg/gel/gio/internal/f32color"
11 "github.com/p9c/p9/pkg/gel/gio/layout"
12 "github.com/p9c/p9/pkg/gel/gio/op/clip"
13 "github.com/p9c/p9/pkg/gel/gio/op/paint"
14 "github.com/p9c/p9/pkg/gel/gio/unit"
15 )
16
17 type ProgressBarStyle struct {
18 Color color.NRGBA
19 TrackColor color.NRGBA
20 Progress float32
21 }
22
23 func ProgressBar(th *Theme, progress float32) ProgressBarStyle {
24 return ProgressBarStyle{
25 Progress: progress,
26 Color: th.Palette.ContrastBg,
27 TrackColor: f32color.MulAlpha(th.Palette.Fg, 0x88),
28 }
29 }
30
31 func (p ProgressBarStyle) Layout(gtx layout.Context) layout.Dimensions {
32 shader := func(width float32, color color.NRGBA) layout.Dimensions {
33 maxHeight := unit.Dp(4)
34 rr := float32(gtx.Px(unit.Dp(2)))
35
36 d := image.Point{X: int(width), Y: gtx.Px(maxHeight)}
37
38 height := float32(gtx.Px(maxHeight))
39 clip.UniformRRect(f32.Rectangle{Max: f32.Pt(width, height)}, rr).Add(gtx.Ops)
40 paint.ColorOp{Color: color}.Add(gtx.Ops)
41 paint.PaintOp{}.Add(gtx.Ops)
42
43 return layout.Dimensions{Size: d}
44 }
45
46 progressBarWidth := float32(gtx.Constraints.Max.X)
47 return layout.Stack{Alignment: layout.W}.Layout(gtx,
48 layout.Stacked(func(gtx layout.Context) layout.Dimensions {
49 return shader(progressBarWidth, p.TrackColor)
50 }),
51 layout.Stacked(func(gtx layout.Context) layout.Dimensions {
52 fillWidth := progressBarWidth * clamp1(p.Progress)
53 fillColor := p.Color
54 if gtx.Queue == nil {
55 fillColor = f32color.Disabled(fillColor)
56 }
57 return shader(fillWidth, fillColor)
58 }),
59 )
60 }
61
62 // clamp1 limits v to range [0..1].
63 func clamp1(v float32) float32 {
64 if v >= 1 {
65 return 1
66 } else if v <= 0 {
67 return 0
68 } else {
69 return v
70 }
71 }
72