M component/app_bar.go => component/app_bar.go +9 -6
@@ 83,7 83,7 @@ func (a *actionGroup) setActions(actions []AppBarAction, overflows []OverflowAct
a.overflowState = make([]widget.Clickable, len(a.actions)+len(a.overflow))
}
-func (a *actionGroup) layout(gtx C, th *material.Theme, overflowBtn *widget.Clickable) D {
+func (a *actionGroup) layout(gtx C, th *material.Theme, overflowBtn *widget.Clickable, overflowDesc string) D {
overflowedActions := len(a.actions)
gtx.Constraints.Min.Y = 0
widthDp := float32(gtx.Constraints.Max.X) / gtx.Metric.PxPerDp
@@ 114,7 114,7 @@ func (a *actionGroup) layout(gtx C, th *material.Theme, overflowBtn *widget.Clic
if len(a.overflow)+overflowedActions > 0 {
actions = append(actions, layout.Rigid(func(gtx C) D {
gtx.Constraints.Min.Y = gtx.Constraints.Max.Y
- btn := material.IconButton(th, overflowBtn, moreIcon)
+ btn := material.IconButton(th, overflowBtn, moreIcon, overflowDesc)
btn.Size = unit.Dp(24)
btn.Background = th.Palette.Bg
btn.Color = th.Palette.Fg
@@ 366,8 366,11 @@ func SwapPairs(p material.Palette) material.Palette {
}
// Layout renders the app bar. It will span all available horizontal
-// space (gtx.Constraints.Max.X), but has a fixed height.
-func (a *AppBar) Layout(gtx layout.Context, theme *material.Theme) layout.Dimensions {
+// space (gtx.Constraints.Max.X), but has a fixed height. The navDesc
+// is an accessibility description for the navigation icon button, and
+// the overflowDesc is an accessibility description for the overflow
+// action button.
+func (a *AppBar) Layout(gtx layout.Context, theme *material.Theme, navDesc, overflowDesc string) layout.Dimensions {
a.initialize()
gtx.Constraints.Max.Y = gtx.Px(unit.Dp(56))
th := *theme
@@ 403,7 406,7 @@ func (a *AppBar) Layout(gtx layout.Context, theme *material.Theme) layout.Dimens
if a.contextualAnim.Visible() {
icon = cancelIcon
}
- button := material.IconButton(&th, &a.NavigationButton, icon)
+ button := material.IconButton(&th, &a.NavigationButton, icon, navDesc)
button.Size = unit.Dp(24)
button.Background = th.Palette.Bg
button.Color = th.Fg
@@ 424,7 427,7 @@ func (a *AppBar) Layout(gtx layout.Context, theme *material.Theme) layout.Dimens
layout.Flexed(1, func(gtx C) D {
gtx.Constraints.Min.Y = gtx.Constraints.Max.Y
return layout.E.Layout(gtx, func(gtx C) D {
- return actionSet.layout(gtx, &th, &a.overflowMenu.Clickable)
+ return actionSet.layout(gtx, &th, &a.overflowMenu.Clickable, overflowDesc)
})
}),
)
M component/discloser.go => component/discloser.go +1 -4
@@ 77,10 77,7 @@ func (d DiscloserStyle) Layout(gtx C, control, summary, detail layout.Widget) D
}.Layout(gtx,
layout.Rigid(func(gtx C) D {
controlWidget := func(gtx C) D {
- return layout.Stack{}.Layout(gtx,
- layout.Stacked(control),
- layout.Expanded(d.Clickable.Layout),
- )
+ return d.Clickable.Layout(gtx, control)
}
return layout.Flex{
Alignment: layout.Middle,
M component/scrim.go => component/scrim.go +30 -28
@@ 20,21 20,22 @@ type Scrim struct {
// Layout draws the scrim using the provided animation. If the animation indicates
// that the scrim is not visible, this is a no-op.
func (s *Scrim) Layout(gtx layout.Context, th *material.Theme, anim *VisibilityAnimation) layout.Dimensions {
- if !anim.Visible() {
- return layout.Dimensions{}
- }
- gtx.Constraints.Min = gtx.Constraints.Max
- currentAlpha := s.FinalAlpha
- if anim.Animating() {
- revealed := anim.Revealed(gtx)
- currentAlpha = uint8(float32(s.FinalAlpha) * revealed)
- }
- color := th.Fg
- color.A = currentAlpha
- fill := WithAlpha(color, currentAlpha)
- paintRect(gtx, gtx.Constraints.Max, fill)
- s.Clickable.Layout(gtx)
- return layout.Dimensions{Size: gtx.Constraints.Max}
+ return s.Clickable.Layout(gtx, func(gtx C) D {
+ if !anim.Visible() {
+ return layout.Dimensions{}
+ }
+ gtx.Constraints.Min = gtx.Constraints.Max
+ currentAlpha := s.FinalAlpha
+ if anim.Animating() {
+ revealed := anim.Revealed(gtx)
+ currentAlpha = uint8(float32(s.FinalAlpha) * revealed)
+ }
+ color := th.Fg
+ color.A = currentAlpha
+ fill := WithAlpha(color, currentAlpha)
+ paintRect(gtx, gtx.Constraints.Max, fill)
+ return layout.Dimensions{Size: gtx.Constraints.Max}
+ })
}
// ScrimState defines persistent state for a scrim.
@@ 61,17 62,18 @@ func NewScrim(th *material.Theme, scrim *ScrimState, alpha uint8) ScrimStyle {
}
func (scrim ScrimStyle) Layout(gtx C) D {
- if !scrim.Visible() {
- return D{}
- }
- gtx.Constraints.Min = gtx.Constraints.Max
- alpha := scrim.FinalAlpha
- if scrim.Animating() {
- alpha = uint8(float32(scrim.FinalAlpha) * scrim.Revealed(gtx))
- }
- defer scrim.Clickable.Layout(gtx)
- return Rect{
- Color: WithAlpha(scrim.Color, alpha),
- Size: gtx.Constraints.Max,
- }.Layout(gtx)
+ return scrim.Clickable.Layout(gtx, func(gtx C) D {
+ if !scrim.Visible() {
+ return D{}
+ }
+ gtx.Constraints.Min = gtx.Constraints.Max
+ alpha := scrim.FinalAlpha
+ if scrim.Animating() {
+ alpha = uint8(float32(scrim.FinalAlpha) * scrim.Revealed(gtx))
+ }
+ return Rect{
+ Color: WithAlpha(scrim.Color, alpha),
+ Size: gtx.Constraints.Max,
+ }.Layout(gtx)
+ })
}
M component/text_field.go => component/text_field.go +14 -52
@@ 7,6 7,7 @@ import (
"time"
"gioui.org/f32"
+ "gioui.org/gesture"
"gioui.org/io/pointer"
"gioui.org/layout"
"gioui.org/op"
@@ 21,8 22,9 @@ import (
type TextField struct {
// Editor contains the edit buffer.
widget.Editor
- // Hoverable detects mouse hovers.
- Hoverable Hoverable
+ // click detects when the mouse pointer clicks or hovers
+ // within the textfield.
+ click gesture.Click
// Alignment specifies where to anchor the text.
Alignment layout.Alignment
@@ 115,11 117,13 @@ func (in *TextField) TextTooLong() bool {
func (in *TextField) Update(gtx C, th *material.Theme, hint string) {
disabled := gtx.Queue == nil
- for in.Hoverable.Clicked() {
+ for range in.click.Events(gtx) {
+ }
+ if in.click.Pressed() {
in.Editor.Focus()
}
in.state = inactive
- if in.Hoverable.Hovered() && !disabled {
+ if in.click.Hovered() && !disabled {
in.state = hovered
}
if in.Editor.Len() > 0 {
@@ 333,7 337,12 @@ func (in *TextField) Layout(gtx C, th *material.Theme, hint string) D {
)
}),
layout.Expanded(func(gtx C) D {
- return in.Hoverable.Layout(gtx)
+ defer pointer.PassOp{}.Push(gtx.Ops).Pop()
+ defer pointer.Rect(image.Rectangle{
+ Max: gtx.Constraints.Min,
+ }).Push(gtx.Ops).Pop()
+ in.click.Add(gtx.Ops)
+ return D{}
}),
)
}),
@@ 401,50 410,3 @@ func (in *TextField) Layout(gtx C, th *material.Theme, hint string) D {
func lerp(start, end, progress float32) float32 {
return start + (end-start)*progress
}
-
-// Hoverable tracks mouse hovers over some area.
-type Hoverable struct {
- widget.Clickable
- hovered bool
-}
-
-// Hovered if mouse has entered the area.
-func (h *Hoverable) Hovered() bool {
- return h.hovered
-}
-
-// Layout Hoverable according to min constraints.
-func (h *Hoverable) Layout(gtx C) D {
- {
- pt := pointer.PassOp{}.Push(gtx.Ops)
- stack := pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Push(gtx.Ops)
- h.Clickable.Layout(gtx)
- stack.Pop()
- pt.Pop()
- }
- h.update(gtx)
- {
- pt := pointer.PassOp{}.Push(gtx.Ops)
- stack := pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Push(gtx.Ops)
- pointer.InputOp{
- Tag: h,
- Types: pointer.Enter | pointer.Leave | pointer.Cancel,
- }.Add(gtx.Ops)
- stack.Pop()
- pt.Pop()
- }
- return D{Size: gtx.Constraints.Min}
-}
-
-func (h *Hoverable) update(gtx C) {
- for _, event := range gtx.Events(h) {
- if event, ok := event.(pointer.Event); ok {
- switch event.Type {
- case pointer.Enter:
- h.hovered = true
- case pointer.Leave, pointer.Cancel:
- h.hovered = false
- }
- }
- }
-}
M component/tooltip.go => component/tooltip.go +1 -1
@@ 246,7 246,7 @@ type TipIconButtonStyle struct {
// TipIconButton creates a TipIconButtonStyle.
func TipIconButton(th *material.Theme, area *TipArea, button *widget.Clickable, label string, icon *widget.Icon) TipIconButtonStyle {
return TipIconButtonStyle{
- IconButtonStyle: material.IconButton(th, button, icon),
+ IconButtonStyle: material.IconButton(th, button, icon, label),
State: area,
Tooltip: PlatformTooltip(th, label),
}
M go.mod => go.mod +1 -1
@@ 3,7 3,7 @@ module gioui.org/x
go 1.16
require (
- gioui.org v0.0.0-20211026101311-1eab4b84a6d3
+ gioui.org v0.0.0-20211201162354-9a5298914282
github.com/yuin/goldmark v1.4.0
golang.org/x/exp v0.0.0-20210722180016-6781d3edade3
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
M go.sum => go.sum +8 -0
@@ 5,6 5,14 @@ gioui.org v0.0.0-20211026101311-1eab4b84a6d3 h1:kgz+ANJMlCF5Qd9Rqu8Xu1CKl4asi9AK
gioui.org v0.0.0-20211026101311-1eab4b84a6d3/go.mod h1:yoWOxPng6WkDpsud+NRmkoftmyWn3rkKsYGEcWHpjTI=
gioui.org v0.0.0-20211026101311-9cf7cc75f468 h1:8lKC0jESs/gMz+kYbJWzFB1bkwMdlux36LYvBB9UDtw=
gioui.org v0.0.0-20211026101311-9cf7cc75f468/go.mod h1:yoWOxPng6WkDpsud+NRmkoftmyWn3rkKsYGEcWHpjTI=
+gioui.org v0.0.0-20211130134758-67847733ac6a h1:kox8u+S7s6/8wT44rdK/LqJk2tEtfdxN/6fvoZ9WknM=
+gioui.org v0.0.0-20211130134758-67847733ac6a/go.mod h1:yoWOxPng6WkDpsud+NRmkoftmyWn3rkKsYGEcWHpjTI=
+gioui.org v0.0.0-20211130141120-dfedb065df27 h1:RCKtmko2wvGzpcxMQMniW12qPGPt2I3e0WXhkN12jc8=
+gioui.org v0.0.0-20211130141120-dfedb065df27/go.mod h1:yoWOxPng6WkDpsud+NRmkoftmyWn3rkKsYGEcWHpjTI=
+gioui.org v0.0.0-20211130163955-919827027682 h1:oVq/wQFIEPjKve5KUl7yE3Y7yNH1Wo8H9Lnk9m2eeLw=
+gioui.org v0.0.0-20211130163955-919827027682/go.mod h1:yoWOxPng6WkDpsud+NRmkoftmyWn3rkKsYGEcWHpjTI=
+gioui.org v0.0.0-20211201162354-9a5298914282 h1:AhBq0mtPYfXW7XyJ5ixFi7VA0/gwPC7HykpTTHTR9Lc=
+gioui.org v0.0.0-20211201162354-9a5298914282/go.mod h1:yoWOxPng6WkDpsud+NRmkoftmyWn3rkKsYGEcWHpjTI=
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=