theme.go raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 package material
4
5 import (
6 "image/color"
7
8 "golang.org/x/exp/shiny/materialdesign/icons"
9
10 "github.com/p9c/p9/pkg/gel/gio/text"
11 "github.com/p9c/p9/pkg/gel/gio/unit"
12 "github.com/p9c/p9/pkg/gel/gio/widget"
13 )
14
15 // Palette contains the minimal set of colors that a widget may need to
16 // draw itself.
17 type Palette struct {
18 // Bg is the background color atop which content is currently being
19 // drawn.
20 Bg color.NRGBA
21
22 // Fg is a color suitable for drawing on top of Bg.
23 Fg color.NRGBA
24
25 // ContrastBg is a color used to draw attention to active,
26 // important, interactive widgets such as buttons.
27 ContrastBg color.NRGBA
28
29 // ContrastFg is a color suitable for content drawn on top of
30 // ContrastBg.
31 ContrastFg color.NRGBA
32 }
33
34 type Theme struct {
35 Shaper text.Shaper
36 Palette
37 TextSize unit.Value
38 Icon struct {
39 CheckBoxChecked *widget.Icon
40 CheckBoxUnchecked *widget.Icon
41 RadioChecked *widget.Icon
42 RadioUnchecked *widget.Icon
43 }
44
45 // FingerSize is the minimum touch target size.
46 FingerSize unit.Value
47 }
48
49 func NewTheme(fontCollection []text.FontFace) *Theme {
50 t := &Theme{
51 Shaper: text.NewCache(fontCollection),
52 }
53 t.Palette = Palette{
54 Fg: rgb(0x000000),
55 Bg: rgb(0xffffff),
56 ContrastBg: rgb(0x3f51b5),
57 ContrastFg: rgb(0xffffff),
58 }
59 t.TextSize = unit.Sp(16)
60
61 t.Icon.CheckBoxChecked = mustIcon(widget.NewIcon(icons.ToggleCheckBox))
62 t.Icon.CheckBoxUnchecked = mustIcon(widget.NewIcon(icons.ToggleCheckBoxOutlineBlank))
63 t.Icon.RadioChecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonChecked))
64 t.Icon.RadioUnchecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonUnchecked))
65
66 // 38dp is on the lower end of possible finger size.
67 t.FingerSize = unit.Dp(38)
68
69 return t
70 }
71
72 func (t Theme) WithPalette(p Palette) Theme {
73 t.Palette = p
74 return t
75 }
76
77 func mustIcon(ic *widget.Icon, err error) *widget.Icon {
78 if err != nil {
79 panic(err)
80 }
81 return ic
82 }
83
84 func rgb(c uint32) color.NRGBA {
85 return argb(0xff000000 | c)
86 }
87
88 func argb(c uint32) color.NRGBA {
89 return color.NRGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)}
90 }
91