~eliasnaur/gio

a87a520ae8258d1bbc05014c031bc523730900ec — Chris Waldon 10 months ago 47ba975
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>
M widget/material/button.go => widget/material/button.go +5 -5
@@ 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)),

M widget/material/checkbox.go => widget/material/checkbox.go +2 -2
@@ 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,

M widget/material/editor.go => widget/material/editor.go +2 -2
@@ 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),
	}
}


M widget/material/label.go => widget/material/label.go +1 -1
@@ 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,
	}

M widget/material/loader.go => widget/material/loader.go +1 -1
@@ 22,7 22,7 @@ type LoaderStyle struct {

func Loader(th *Theme) LoaderStyle {
	return LoaderStyle{
		Color: th.Color.Primary,
		Color: th.Palette.ContrastBg,
	}
}


M widget/material/progressbar.go => widget/material/progressbar.go +7 -8
@@ 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)

M widget/material/radiobutton.go => widget/material/radiobutton.go +2 -2
@@ 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,

M widget/material/slider.go => widget/material/slider.go +1 -1
@@ 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,
	}
}

M widget/material/switch.go => widget/material/switch.go +5 -3
@@ 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,

M widget/material/theme.go => widget/material/theme.go +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)