mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 18:35:34 +00:00
widget/material: move Icon to its own file and add Color; add CornerRadius to Button
This commit is contained in:
committed by
Elias Naur
parent
ec0c2498a1
commit
2a06f3d3b2
@@ -6,7 +6,6 @@ package material
|
|||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/draw"
|
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
@@ -16,7 +15,6 @@ import (
|
|||||||
"gioui.org/text"
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
"gioui.org/widget"
|
"gioui.org/widget"
|
||||||
"golang.org/x/exp/shiny/iconvg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Button struct {
|
type Button struct {
|
||||||
@@ -25,26 +23,18 @@ type Button struct {
|
|||||||
Color color.RGBA
|
Color color.RGBA
|
||||||
Font text.Font
|
Font text.Font
|
||||||
Background color.RGBA
|
Background color.RGBA
|
||||||
|
CornerRadius unit.Value
|
||||||
shaper *text.Shaper
|
shaper *text.Shaper
|
||||||
}
|
}
|
||||||
|
|
||||||
type IconButton struct {
|
type IconButton struct {
|
||||||
Background color.RGBA
|
Background color.RGBA
|
||||||
|
Color color.RGBA
|
||||||
Icon *Icon
|
Icon *Icon
|
||||||
Size unit.Value
|
Size unit.Value
|
||||||
Padding unit.Value
|
Padding unit.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
type Icon struct {
|
|
||||||
src []byte
|
|
||||||
size unit.Value
|
|
||||||
|
|
||||||
// Cached values.
|
|
||||||
op paint.ImageOp
|
|
||||||
imgSize int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Theme) Button(txt string) Button {
|
func (t *Theme) Button(txt string) Button {
|
||||||
return Button{
|
return Button{
|
||||||
Text: txt,
|
Text: txt,
|
||||||
@@ -57,18 +47,10 @@ func (t *Theme) Button(txt string) Button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIcon returns a new Icon from IconVG data.
|
|
||||||
func NewIcon(data []byte) (*Icon, error) {
|
|
||||||
_, err := iconvg.DecodeMetadata(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Icon{src: data}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Theme) IconButton(icon *Icon) IconButton {
|
func (t *Theme) IconButton(icon *Icon) IconButton {
|
||||||
return IconButton{
|
return IconButton{
|
||||||
Background: t.Color.Primary,
|
Background: t.Color.Primary,
|
||||||
|
Color: t.Color.InvText,
|
||||||
Icon: icon,
|
Icon: icon,
|
||||||
Size: unit.Dp(56),
|
Size: unit.Dp(56),
|
||||||
Padding: unit.Dp(16),
|
Padding: unit.Dp(16),
|
||||||
@@ -114,6 +96,7 @@ func (b IconButton) Layout(gtx *layout.Context, button *widget.Button) {
|
|||||||
layout.UniformInset(b.Padding).Layout(gtx, func() {
|
layout.UniformInset(b.Padding).Layout(gtx, func() {
|
||||||
size := gtx.Px(b.Size) - 2*gtx.Px(b.Padding)
|
size := gtx.Px(b.Size) - 2*gtx.Px(b.Padding)
|
||||||
if b.Icon != nil {
|
if b.Icon != nil {
|
||||||
|
b.Icon.Color = b.Color
|
||||||
b.Icon.Layout(gtx, unit.Px(float32(size)))
|
b.Icon.Layout(gtx, unit.Px(float32(size)))
|
||||||
}
|
}
|
||||||
gtx.Dimensions = layout.Dimensions{
|
gtx.Dimensions = layout.Dimensions{
|
||||||
@@ -140,35 +123,6 @@ func (b IconButton) Layout(gtx *layout.Context, button *widget.Button) {
|
|||||||
st.Layout(gtx, bg, ico)
|
st.Layout(gtx, bg, ico)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ic *Icon) Layout(gtx *layout.Context, sz unit.Value) {
|
|
||||||
ico := ic.image(gtx.Px(sz))
|
|
||||||
ico.Add(gtx.Ops)
|
|
||||||
paint.PaintOp{
|
|
||||||
Rect: f32.Rectangle{
|
|
||||||
Max: toPointF(ico.Size()),
|
|
||||||
},
|
|
||||||
}.Add(gtx.Ops)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ic *Icon) image(sz int) paint.ImageOp {
|
|
||||||
if sz == ic.imgSize {
|
|
||||||
return ic.op
|
|
||||||
}
|
|
||||||
m, _ := iconvg.DecodeMetadata(ic.src)
|
|
||||||
dx, dy := m.ViewBox.AspectRatio()
|
|
||||||
img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: int(float32(sz) * dy / dx)}})
|
|
||||||
var ico iconvg.Rasterizer
|
|
||||||
ico.SetDstImage(img, img.Bounds(), draw.Src)
|
|
||||||
// Use white for icons.
|
|
||||||
m.Palette[0] = color.RGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff}
|
|
||||||
iconvg.Decode(&ico, ic.src, &iconvg.DecodeOptions{
|
|
||||||
Palette: &m.Palette,
|
|
||||||
})
|
|
||||||
ic.op = paint.NewImageOp(img)
|
|
||||||
ic.imgSize = sz
|
|
||||||
return ic.op
|
|
||||||
}
|
|
||||||
|
|
||||||
func toPointF(p image.Point) f32.Point {
|
func toPointF(p image.Point) f32.Point {
|
||||||
return f32.Point{X: float32(p.X), Y: float32(p.Y)}
|
return f32.Point{X: float32(p.X), Y: float32(p.Y)}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
|
// Package material implements the Material design.
|
||||||
|
package material
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/draw"
|
||||||
|
|
||||||
|
"gioui.org/f32"
|
||||||
|
"gioui.org/layout"
|
||||||
|
"gioui.org/op/paint"
|
||||||
|
"gioui.org/unit"
|
||||||
|
"golang.org/x/exp/shiny/iconvg"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Icon struct {
|
||||||
|
Color color.RGBA
|
||||||
|
src []byte
|
||||||
|
size unit.Value
|
||||||
|
// Cached values.
|
||||||
|
op paint.ImageOp
|
||||||
|
imgSize int
|
||||||
|
imgColor color.RGBA
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIcon returns a new Icon from IconVG data.
|
||||||
|
func NewIcon(data []byte) (*Icon, error) {
|
||||||
|
_, err := iconvg.DecodeMetadata(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Icon{src: data, Color: rgb(0x000000)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ic *Icon) Layout(gtx *layout.Context, sz unit.Value) {
|
||||||
|
ico := ic.image(gtx.Px(sz))
|
||||||
|
ico.Add(gtx.Ops)
|
||||||
|
paint.PaintOp{
|
||||||
|
Rect: f32.Rectangle{
|
||||||
|
Max: toPointF(ico.Size()),
|
||||||
|
},
|
||||||
|
}.Add(gtx.Ops)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ic *Icon) image(sz int) paint.ImageOp {
|
||||||
|
if sz == ic.imgSize && ic.Color == ic.imgColor {
|
||||||
|
return ic.op
|
||||||
|
}
|
||||||
|
m, _ := iconvg.DecodeMetadata(ic.src)
|
||||||
|
dx, dy := m.ViewBox.AspectRatio()
|
||||||
|
img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: int(float32(sz) * dy / dx)}})
|
||||||
|
var ico iconvg.Rasterizer
|
||||||
|
ico.SetDstImage(img, img.Bounds(), draw.Src)
|
||||||
|
m.Palette[0] = ic.Color
|
||||||
|
iconvg.Decode(&ico, ic.src, &iconvg.DecodeOptions{
|
||||||
|
Palette: &m.Palette,
|
||||||
|
})
|
||||||
|
ic.op = paint.NewImageOp(img)
|
||||||
|
ic.imgSize = sz
|
||||||
|
ic.imgColor = ic.Color
|
||||||
|
return ic.op
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
"gioui.org/text"
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
|
"golang.org/x/exp/shiny/materialdesign/icons"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Theme struct {
|
type Theme struct {
|
||||||
@@ -22,8 +23,11 @@ type Theme struct {
|
|||||||
Primary color.RGBA
|
Primary color.RGBA
|
||||||
Text color.RGBA
|
Text color.RGBA
|
||||||
Hint color.RGBA
|
Hint color.RGBA
|
||||||
|
InvText color.RGBA
|
||||||
}
|
}
|
||||||
TextSize unit.Value
|
TextSize unit.Value
|
||||||
|
checkedStateIcon *Icon
|
||||||
|
uncheckedStateIcon *Icon
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTheme() *Theme {
|
func NewTheme() *Theme {
|
||||||
@@ -33,10 +37,22 @@ func NewTheme() *Theme {
|
|||||||
t.Color.Primary = rgb(0x3f51b5)
|
t.Color.Primary = rgb(0x3f51b5)
|
||||||
t.Color.Text = rgb(0x000000)
|
t.Color.Text = rgb(0x000000)
|
||||||
t.Color.Hint = rgb(0xbbbbbb)
|
t.Color.Hint = rgb(0xbbbbbb)
|
||||||
|
t.Color.InvText = rgb(0xffffff)
|
||||||
t.TextSize = unit.Sp(16)
|
t.TextSize = unit.Sp(16)
|
||||||
|
|
||||||
|
t.checkedStateIcon = mustIcon(NewIcon(icons.ToggleCheckBox))
|
||||||
|
t.uncheckedStateIcon = mustIcon(NewIcon(icons.ToggleCheckBoxOutlineBlank))
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustIcon(ic *Icon, err error) *Icon {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return ic
|
||||||
|
}
|
||||||
|
|
||||||
func rgb(c uint32) color.RGBA {
|
func rgb(c uint32) color.RGBA {
|
||||||
return argb(0xff000000 | c)
|
return argb(0xff000000 | c)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user