mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
widget/material: manage widget colors with Palette type
This introduces a new material.Palette type that captures the color information necessary to render a widget. This type is embedded in the material.Theme to make it easier to swap to a different palette for part of the UI by reassinging the Palette field. Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
@@ -52,9 +52,9 @@ type IconButtonStyle struct {
|
||||
func Button(th *Theme, button *widget.Clickable, txt string) ButtonStyle {
|
||||
return ButtonStyle{
|
||||
Text: txt,
|
||||
Color: rgb(0xffffff),
|
||||
Color: th.Palette.ContrastFg,
|
||||
CornerRadius: unit.Dp(4),
|
||||
Background: th.Color.Primary,
|
||||
Background: th.Palette.ContrastBg,
|
||||
TextSize: th.TextSize.Scale(14.0 / 16.0),
|
||||
Inset: layout.Inset{
|
||||
Top: unit.Dp(10), Bottom: unit.Dp(10),
|
||||
@@ -68,15 +68,15 @@ func Button(th *Theme, button *widget.Clickable, txt string) ButtonStyle {
|
||||
func ButtonLayout(th *Theme, button *widget.Clickable) ButtonLayoutStyle {
|
||||
return ButtonLayoutStyle{
|
||||
Button: button,
|
||||
Background: th.Color.Primary,
|
||||
Background: th.Palette.ContrastBg,
|
||||
CornerRadius: unit.Dp(4),
|
||||
}
|
||||
}
|
||||
|
||||
func IconButton(th *Theme, button *widget.Clickable, icon *widget.Icon) IconButtonStyle {
|
||||
return IconButtonStyle{
|
||||
Background: th.Color.Primary,
|
||||
Color: th.Color.InvText,
|
||||
Background: th.Palette.ContrastBg,
|
||||
Color: th.Palette.ContrastFg,
|
||||
Icon: icon,
|
||||
Size: unit.Dp(24),
|
||||
Inset: layout.UniformInset(unit.Dp(12)),
|
||||
|
||||
@@ -18,8 +18,8 @@ func CheckBox(th *Theme, checkBox *widget.Bool, label string) CheckBoxStyle {
|
||||
CheckBox: checkBox,
|
||||
checkable: checkable{
|
||||
Label: label,
|
||||
Color: th.Color.Text,
|
||||
IconColor: th.Color.Primary,
|
||||
Color: th.Palette.Fg,
|
||||
IconColor: th.Palette.ContrastBg,
|
||||
TextSize: th.TextSize.Scale(14.0 / 16.0),
|
||||
Size: unit.Dp(26),
|
||||
shaper: th.Shaper,
|
||||
|
||||
@@ -32,10 +32,10 @@ func Editor(th *Theme, editor *widget.Editor, hint string) EditorStyle {
|
||||
return EditorStyle{
|
||||
Editor: editor,
|
||||
TextSize: th.TextSize,
|
||||
Color: th.Color.Text,
|
||||
Color: th.Palette.Fg,
|
||||
shaper: th.Shaper,
|
||||
Hint: hint,
|
||||
HintColor: th.Color.Hint,
|
||||
HintColor: f32color.MulAlpha(th.Palette.Fg, 0xbb),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ func Caption(th *Theme, txt string) LabelStyle {
|
||||
func Label(th *Theme, size unit.Value, txt string) LabelStyle {
|
||||
return LabelStyle{
|
||||
Text: txt,
|
||||
Color: th.Color.Text,
|
||||
Color: th.Palette.Fg,
|
||||
TextSize: size,
|
||||
shaper: th.Shaper,
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ type LoaderStyle struct {
|
||||
|
||||
func Loader(th *Theme) LoaderStyle {
|
||||
return LoaderStyle{
|
||||
Color: th.Color.Primary,
|
||||
Color: th.Palette.ContrastBg,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,16 @@ import (
|
||||
)
|
||||
|
||||
type ProgressBarStyle struct {
|
||||
Color color.NRGBA
|
||||
Progress int
|
||||
Color color.NRGBA
|
||||
TrackColor color.NRGBA
|
||||
Progress int
|
||||
}
|
||||
|
||||
func ProgressBar(th *Theme, progress int) ProgressBarStyle {
|
||||
return ProgressBarStyle{
|
||||
Progress: progress,
|
||||
Color: th.Color.Primary,
|
||||
Progress: progress,
|
||||
Color: th.Palette.ContrastBg,
|
||||
TrackColor: f32color.MulAlpha(th.Palette.Fg, 0x88),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,10 +57,7 @@ func (p ProgressBarStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
|
||||
return layout.Stack{Alignment: layout.W}.Layout(gtx,
|
||||
layout.Stacked(func(gtx layout.Context) layout.Dimensions {
|
||||
// Use a transparent equivalent of progress color.
|
||||
bgCol := f32color.MulAlpha(p.Color, 150)
|
||||
|
||||
return shader(progressBarWidth, bgCol)
|
||||
return shader(progressBarWidth, p.TrackColor)
|
||||
}),
|
||||
layout.Stacked(func(gtx layout.Context) layout.Dimensions {
|
||||
fillWidth := (progressBarWidth / 100) * float32(progress)
|
||||
|
||||
@@ -22,8 +22,8 @@ func RadioButton(th *Theme, group *widget.Enum, key, label string) RadioButtonSt
|
||||
checkable: checkable{
|
||||
Label: label,
|
||||
|
||||
Color: th.Color.Text,
|
||||
IconColor: th.Color.Primary,
|
||||
Color: th.Palette.Fg,
|
||||
IconColor: th.Palette.ContrastBg,
|
||||
TextSize: th.TextSize.Scale(14.0 / 16.0),
|
||||
Size: unit.Dp(26),
|
||||
shaper: th.Shaper,
|
||||
|
||||
@@ -21,7 +21,7 @@ func Slider(th *Theme, float *widget.Float, min, max float32) SliderStyle {
|
||||
return SliderStyle{
|
||||
Min: min,
|
||||
Max: max,
|
||||
Color: th.Color.Primary,
|
||||
Color: th.Palette.ContrastBg,
|
||||
Float: float,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ type SwitchStyle struct {
|
||||
Color struct {
|
||||
Enabled color.NRGBA
|
||||
Disabled color.NRGBA
|
||||
Track color.NRGBA
|
||||
}
|
||||
Switch *widget.Bool
|
||||
}
|
||||
@@ -29,8 +30,9 @@ func Switch(th *Theme, swtch *widget.Bool) SwitchStyle {
|
||||
sw := SwitchStyle{
|
||||
Switch: swtch,
|
||||
}
|
||||
sw.Color.Enabled = th.Color.Primary
|
||||
sw.Color.Disabled = rgb(0xffffff)
|
||||
sw.Color.Enabled = th.Palette.ContrastBg
|
||||
sw.Color.Disabled = th.Palette.Bg
|
||||
sw.Color.Track = f32color.MulAlpha(th.Palette.Fg, 0x88)
|
||||
return sw
|
||||
}
|
||||
|
||||
@@ -55,7 +57,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
if gtx.Queue == nil {
|
||||
col = f32color.MulAlpha(col, 150)
|
||||
}
|
||||
trackColor := f32color.MulAlpha(col, 150)
|
||||
trackColor := s.Color.Track
|
||||
op.Offset(f32.Point{Y: trackOff}).Add(gtx.Ops)
|
||||
clip.RRect{
|
||||
Rect: trackRect,
|
||||
|
||||
+31
-10
@@ -11,14 +11,28 @@ import (
|
||||
"golang.org/x/exp/shiny/materialdesign/icons"
|
||||
)
|
||||
|
||||
// Palette contains the minimal set of colors that a widget may need to
|
||||
// draw itself.
|
||||
type Palette struct {
|
||||
// Bg is the background color atop which content is currently being
|
||||
// drawn.
|
||||
Bg color.NRGBA
|
||||
|
||||
// Fg is a color suitable for drawing on top of Bg.
|
||||
Fg color.NRGBA
|
||||
|
||||
// ContrastBg is a color used to draw attention to active,
|
||||
// important, interactive widgets such as buttons.
|
||||
ContrastBg color.NRGBA
|
||||
|
||||
// ContrastFg is a color suitable for content drawn on top of
|
||||
// ContrastBg.
|
||||
ContrastFg color.NRGBA
|
||||
}
|
||||
|
||||
type Theme struct {
|
||||
Shaper text.Shaper
|
||||
Color struct {
|
||||
Primary color.NRGBA
|
||||
Text color.NRGBA
|
||||
Hint color.NRGBA
|
||||
InvText color.NRGBA
|
||||
}
|
||||
Palette
|
||||
TextSize unit.Value
|
||||
Icon struct {
|
||||
CheckBoxChecked *widget.Icon
|
||||
@@ -32,10 +46,12 @@ func NewTheme(fontCollection []text.FontFace) *Theme {
|
||||
t := &Theme{
|
||||
Shaper: text.NewCache(fontCollection),
|
||||
}
|
||||
t.Color.Primary = rgb(0x3f51b5)
|
||||
t.Color.Text = rgb(0x000000)
|
||||
t.Color.Hint = rgb(0xbbbbbb)
|
||||
t.Color.InvText = rgb(0xffffff)
|
||||
t.Palette = Palette{
|
||||
Fg: rgb(0x000000),
|
||||
Bg: rgb(0xffffff),
|
||||
ContrastBg: rgb(0x3f51b5),
|
||||
ContrastFg: rgb(0xffffff),
|
||||
}
|
||||
t.TextSize = unit.Sp(16)
|
||||
|
||||
t.Icon.CheckBoxChecked = mustIcon(widget.NewIcon(icons.ToggleCheckBox))
|
||||
@@ -46,6 +62,11 @@ func NewTheme(fontCollection []text.FontFace) *Theme {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t Theme) WithPalette(p Palette) Theme {
|
||||
t.Palette = p
|
||||
return t
|
||||
}
|
||||
|
||||
func mustIcon(ic *widget.Icon, err error) *widget.Icon {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
Reference in New Issue
Block a user