widgets, widgets/material: add RadioButton & Enum

Signed-off-by: Alexander Arin <fralx@yandex.ru>
This commit is contained in:
Alexander Arin
2019-11-06 12:55:19 +03:00
committed by Elias Naur
parent 82e51019e1
commit 089ae31f0c
6 changed files with 198 additions and 73 deletions
+18 -4
View File
@@ -62,10 +62,11 @@ var (
SingleLine: true,
Submit: true,
}
button = new(widget.Button)
greenButton = new(widget.Button)
iconButton = new(widget.Button)
list = &layout.List{
button = new(widget.Button)
greenButton = new(widget.Button)
iconButton = new(widget.Button)
radioButtonsGroup = new(widget.Enum)
list = &layout.List{
Axis: layout.Vertical,
}
green = true
@@ -125,6 +126,19 @@ func kitchen(gtx *layout.Context, th *material.Theme) {
func() {
th.CheckBox("Checkbox").Layout(gtx, checkbox)
},
func() {
group := layout.Flex{}
r1 := group.Rigid(gtx, func() {
th.RadioButton("r1", "RadioButton1").Layout(gtx, radioButtonsGroup)
})
r2 := group.Rigid(gtx, func() {
th.RadioButton("r2", "RadioButton2").Layout(gtx, radioButtonsGroup)
})
r3 := group.Rigid(gtx, func() {
th.RadioButton("r3", "RadioButton3").Layout(gtx, radioButtonsGroup)
})
group.Layout(gtx, r1, r2, r3)
},
}
list.Layout(gtx, len(widgets), func(i int) {
layout.UniformInset(unit.Dp(16)).Layout(gtx, widgets[i])
+51
View File
@@ -0,0 +1,51 @@
package widget
import (
"gioui.org/gesture"
"gioui.org/layout"
)
type Enum struct {
clicks []gesture.Click
values []string
value string
}
func index(vs []string, t string) int {
for i, v := range vs {
if v == t {
return i
}
}
return -1
}
// Value processes events and returns the last selected value, or
// the empty string.
func (e *Enum) Value(gtx *layout.Context) string {
for i := range e.clicks {
for _, ev := range e.clicks[i].Events(gtx) {
switch ev.Type {
case gesture.TypeClick:
e.value = e.values[i]
}
}
}
return e.value
}
// Layout adds the event handler for key.
func (rg *Enum) Layout(gtx *layout.Context, key string) {
if index(rg.values, key) == -1 {
rg.values = append(rg.values, key)
rg.clicks = append(rg.clicks, gesture.Click{})
rg.clicks[len(rg.clicks)-1].Add(gtx.Ops)
} else {
idx := index(rg.values, key)
rg.clicks[idx].Add(gtx.Ops)
}
}
func (rg *Enum) SetValue(value string) {
rg.value = value
}
+14 -65
View File
@@ -4,85 +4,34 @@
package material
import (
"gioui.org/io/pointer"
"gioui.org/layout"
"gioui.org/op/paint"
"gioui.org/text"
"gioui.org/unit"
"gioui.org/widget"
"image"
"image/color"
)
type CheckBox struct {
Text string
// Color is the text color.
Color color.RGBA
Font text.Font
IconColor color.RGBA
Size unit.Value
shaper *text.Shaper
checkedStateIcon *Icon
uncheckedStateIcon *Icon
checkable
}
func (t *Theme) CheckBox(txt string) CheckBox {
func (t *Theme) CheckBox(label string) CheckBox {
return CheckBox{
Text: txt,
Color: t.Color.Text,
IconColor: t.Color.Primary,
Font: text.Font{
Size: t.TextSize.Scale(14.0 / 16.0),
checkable{
Label: label,
Color: t.Color.Text,
IconColor: t.Color.Primary,
Font: text.Font{
Size: t.TextSize.Scale(14.0 / 16.0),
},
Size: unit.Dp(26),
shaper: t.Shaper,
checkedStateIcon: t.checkBoxCheckedIcon,
uncheckedStateIcon: t.checkBoxUncheckedIcon,
},
Size: unit.Dp(26),
shaper: t.Shaper,
checkedStateIcon: t.checkedStateIcon,
uncheckedStateIcon: t.uncheckedStateIcon,
}
}
func (c CheckBox) Layout(gtx *layout.Context, checkBox *widget.CheckBox) {
textColor := c.Color
iconColor := c.IconColor
var icon *Icon
if checkBox.Checked(gtx) {
icon = c.checkedStateIcon
} else {
icon = c.uncheckedStateIcon
}
hmin := gtx.Constraints.Width.Min
vmin := gtx.Constraints.Height.Min
flex := layout.Flex{Alignment: layout.Middle}
ico := flex.Rigid(gtx, func() {
layout.Align(layout.Center).Layout(gtx, func() {
layout.UniformInset(unit.Dp(2)).Layout(gtx, func() {
size := gtx.Px(c.Size)
icon.Color = iconColor
icon.Layout(gtx, unit.Px(float32(size)))
gtx.Dimensions = layout.Dimensions{
Size: image.Point{X: size, Y: size},
}
})
})
})
lbl := flex.Rigid(gtx, func() {
gtx.Constraints.Width.Min = hmin
gtx.Constraints.Height.Min = vmin
layout.Align(layout.Start).Layout(gtx, func() {
layout.UniformInset(unit.Dp(2)).Layout(gtx, func() {
paint.ColorOp{Color: textColor}.Add(gtx.Ops)
widget.Label{}.Layout(gtx, c.shaper, c.Font, c.Text)
})
})
})
flex.Layout(gtx, ico, lbl)
pointer.RectAreaOp{Rect: image.Rectangle{Max: gtx.Dimensions.Size}}.Add(gtx.Ops)
c.layout(gtx, checkBox.Checked(gtx))
checkBox.Layout(gtx)
}
+65
View File
@@ -0,0 +1,65 @@
package material
import (
"image"
"image/color"
"gioui.org/io/pointer"
"gioui.org/layout"
"gioui.org/op/paint"
"gioui.org/text"
"gioui.org/unit"
"gioui.org/widget"
)
type checkable struct {
Label string
Color color.RGBA
Font text.Font
IconColor color.RGBA
Size unit.Value
shaper *text.Shaper
checkedStateIcon *Icon
uncheckedStateIcon *Icon
}
func (c *checkable) layout(gtx *layout.Context, checked bool) {
var icon *Icon
if checked {
icon = c.checkedStateIcon
} else {
icon = c.uncheckedStateIcon
}
hmin := gtx.Constraints.Width.Min
vmin := gtx.Constraints.Height.Min
flex := layout.Flex{Alignment: layout.Middle}
ico := flex.Rigid(gtx, func() {
layout.Align(layout.Center).Layout(gtx, func() {
layout.UniformInset(unit.Dp(2)).Layout(gtx, func() {
size := gtx.Px(c.Size)
icon.Color = c.IconColor
icon.Layout(gtx, unit.Px(float32(size)))
gtx.Dimensions = layout.Dimensions{
Size: image.Point{X: size, Y: size},
}
})
})
})
lbl := flex.Rigid(gtx, func() {
gtx.Constraints.Width.Min = hmin
gtx.Constraints.Height.Min = vmin
layout.Align(layout.Start).Layout(gtx, func() {
layout.UniformInset(unit.Dp(2)).Layout(gtx, func() {
paint.ColorOp{Color: c.Color}.Add(gtx.Ops)
widget.Label{}.Layout(gtx, c.shaper, c.Font, c.Label)
})
})
})
flex.Layout(gtx, ico, lbl)
pointer.RectAreaOp{Rect: image.Rectangle{Max: gtx.Dimensions.Size}}.Add(gtx.Ops)
}
+8 -4
View File
@@ -25,8 +25,10 @@ type Theme struct {
InvText color.RGBA
}
TextSize unit.Value
checkedStateIcon *Icon
uncheckedStateIcon *Icon
checkBoxCheckedIcon *Icon
checkBoxUncheckedIcon *Icon
radioCheckedIcon *Icon
radioUncheckedIcon *Icon
}
func NewTheme() *Theme {
@@ -39,8 +41,10 @@ func NewTheme() *Theme {
t.Color.InvText = rgb(0xffffff)
t.TextSize = unit.Sp(16)
t.checkedStateIcon = mustIcon(NewIcon(icons.ToggleCheckBox))
t.uncheckedStateIcon = mustIcon(NewIcon(icons.ToggleCheckBoxOutlineBlank))
t.checkBoxCheckedIcon = mustIcon(NewIcon(icons.ToggleCheckBox))
t.checkBoxUncheckedIcon = mustIcon(NewIcon(icons.ToggleCheckBoxOutlineBlank))
t.radioCheckedIcon = mustIcon(NewIcon(icons.ToggleRadioButtonChecked))
t.radioUncheckedIcon = mustIcon(NewIcon(icons.ToggleRadioButtonUnchecked))
return t
}
+42
View File
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: Unlicense OR MIT
// Package material implements the Material design.
package material
import (
"gioui.org/layout"
"gioui.org/text"
"gioui.org/unit"
"gioui.org/widget"
)
type RadioButton struct {
checkable
Key string
}
// RadioButton returns a RadioButton with a label. The key specifies
// the value for the Enum.
func (t *Theme) RadioButton(key, label string) RadioButton {
return RadioButton{
checkable: checkable{
Label: label,
Color: t.Color.Text,
IconColor: t.Color.Primary,
Font: text.Font{
Size: t.TextSize.Scale(14.0 / 16.0),
},
Size: unit.Dp(26),
shaper: t.Shaper,
checkedStateIcon: t.radioCheckedIcon,
uncheckedStateIcon: t.radioUncheckedIcon,
},
Key: key,
}
}
func (r RadioButton) Layout(gtx *layout.Context, enum *widget.Enum) {
r.layout(gtx, enum.Value(gtx) == r.Key)
enum.Layout(gtx, r.Key)
}