widget,widget/material: remove Color field from Icon

Icons are meant to be shared among multiple widgets, but their Color
state may end up with unexpected values after use. Replace the state
with and explicit argument to Layout.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-07-28 14:19:39 +02:00
parent ea38195e2e
commit 6e9bb7b91c
4 changed files with 15 additions and 17 deletions
+8 -9
View File
@@ -18,8 +18,7 @@ import (
) )
type Icon struct { type Icon struct {
Color color.NRGBA src []byte
src []byte
// Cached values. // Cached values.
op paint.ImageOp op paint.ImageOp
imgSize int imgSize int
@@ -34,11 +33,11 @@ func NewIcon(data []byte) (*Icon, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Icon{src: data, Color: color.NRGBA{A: 0xff}}, nil return &Icon{src: data}, nil
} }
// Layout displays the icon with its size set to the X minimum constraint. // Layout displays the icon with its size set to the X minimum constraint.
func (ic *Icon) Layout(gtx layout.Context) layout.Dimensions { func (ic *Icon) Layout(gtx layout.Context, color color.NRGBA) layout.Dimensions {
sz := gtx.Constraints.Min.X sz := gtx.Constraints.Min.X
if sz == 0 { if sz == 0 {
sz = gtx.Metric.Px(defaultIconSize) sz = gtx.Metric.Px(defaultIconSize)
@@ -47,7 +46,7 @@ func (ic *Icon) Layout(gtx layout.Context) layout.Dimensions {
defer op.Save(gtx.Ops).Load() defer op.Save(gtx.Ops).Load()
clip.Rect{Max: size}.Add(gtx.Ops) clip.Rect{Max: size}.Add(gtx.Ops)
ico := ic.image(size.X) ico := ic.image(size.X, color)
ico.Add(gtx.Ops) ico.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops)
return layout.Dimensions{ return layout.Dimensions{
@@ -55,8 +54,8 @@ func (ic *Icon) Layout(gtx layout.Context) layout.Dimensions {
} }
} }
func (ic *Icon) image(sz int) paint.ImageOp { func (ic *Icon) image(sz int, color color.NRGBA) paint.ImageOp {
if sz == ic.imgSize && ic.Color == ic.imgColor { if sz == ic.imgSize && color == ic.imgColor {
return ic.op return ic.op
} }
m, _ := iconvg.DecodeMetadata(ic.src) m, _ := iconvg.DecodeMetadata(ic.src)
@@ -64,12 +63,12 @@ func (ic *Icon) image(sz int) paint.ImageOp {
img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: int(float32(sz) * dy / dx)}}) img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: int(float32(sz) * dy / dx)}})
var ico iconvg.Rasterizer var ico iconvg.Rasterizer
ico.SetDstImage(img, img.Bounds(), draw.Src) ico.SetDstImage(img, img.Bounds(), draw.Src)
m.Palette[0] = f32color.NRGBAToLinearRGBA(ic.Color) m.Palette[0] = f32color.NRGBAToLinearRGBA(color)
iconvg.Decode(&ico, ic.src, &iconvg.DecodeOptions{ iconvg.Decode(&ico, ic.src, &iconvg.DecodeOptions{
Palette: &m.Palette, Palette: &m.Palette,
}) })
ic.op = paint.NewImageOp(img) ic.op = paint.NewImageOp(img)
ic.imgSize = sz ic.imgSize = sz
ic.imgColor = ic.Color ic.imgColor = color
return ic.op return ic.op
} }
+3 -3
View File
@@ -19,14 +19,14 @@ func TestIcon_Alpha(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
icon.Color = color.NRGBA{B: 0xff, A: 0x40} col := color.NRGBA{B: 0xff, A: 0x40}
gtx := layout.Context{ gtx := layout.Context{
Ops: new(op.Ops), Ops: new(op.Ops),
Constraints: layout.Exact(image.Pt(100, 100)), Constraints: layout.Exact(image.Pt(100, 100)),
} }
_ = icon.Layout(gtx) _ = icon.Layout(gtx, col)
} }
// TestWidgetConstraints tests that widgets returns dimensions within their constraints. // TestWidgetConstraints tests that widgets returns dimensions within their constraints.
@@ -41,7 +41,7 @@ func TestWidgetConstraints(t *testing.T) {
label: "Icon", label: "Icon",
widget: func(gtx layout.Context) layout.Dimensions { widget: func(gtx layout.Context) layout.Dimensions {
ic, _ := NewIcon(icons.ToggleCheckBox) ic, _ := NewIcon(icons.ToggleCheckBox)
return ic.Layout(gtx) return ic.Layout(gtx, color.NRGBA{A: 0xff})
}, },
constraints: _cs( constraints: _cs(
layout.Constraints{ layout.Constraints{
+1 -2
View File
@@ -169,9 +169,8 @@ func (b IconButtonStyle) Layout(gtx layout.Context) layout.Dimensions {
return b.Inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions { return b.Inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
size := gtx.Px(b.Size) size := gtx.Px(b.Size)
if b.Icon != nil { if b.Icon != nil {
b.Icon.Color = b.Color
gtx.Constraints.Min = image.Point{X: size} gtx.Constraints.Min = image.Point{X: size}
b.Icon.Layout(gtx) b.Icon.Layout(gtx, b.Color)
} }
return layout.Dimensions{ return layout.Dimensions{
Size: image.Point{X: size, Y: size}, Size: image.Point{X: size, Y: size},
+3 -3
View File
@@ -63,12 +63,12 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim
layout.Stacked(func(gtx layout.Context) layout.Dimensions { layout.Stacked(func(gtx layout.Context) layout.Dimensions {
return layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx layout.Context) layout.Dimensions { return layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
size := gtx.Px(c.Size) size := gtx.Px(c.Size)
icon.Color = c.IconColor col := c.IconColor
if gtx.Queue == nil { if gtx.Queue == nil {
icon.Color = f32color.Disabled(icon.Color) col = f32color.Disabled(col)
} }
gtx.Constraints.Min = image.Point{X: size} gtx.Constraints.Min = image.Point{X: size}
icon.Layout(gtx) icon.Layout(gtx, col)
return layout.Dimensions{ return layout.Dimensions{
Size: image.Point{X: size, Y: size}, Size: image.Point{X: size, Y: size},
} }