feat(tracker/gioui): add scrollbars to menus

This commit is contained in:
5684185+vsariola@users.noreply.github.com 2023-10-19 14:07:09 +03:00
parent 64270eaf68
commit d6abb14b08
2 changed files with 60 additions and 50 deletions

View File

@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased ## Unreleased
### Added ### Added
- Scroll bars to menus, shown when a menu is too long to fit.
- Save the GUI state periodically to a recovery file and load it on - Save the GUI state periodically to a recovery file and load it on
startup of the app, if present. The recovery files are located in the startup of the app, if present. The recovery files are located in the
app config directory (e.g. AppData/Roaming/Sointu on Windows). app config directory (e.g. AppData/Roaming/Sointu on Windows).

View File

@ -21,6 +21,7 @@ type Menu struct {
clicks []int clicks []int
hover int hover int
list layout.List list layout.List
scrollBar ScrollBar
} }
type MenuStyle struct { type MenuStyle struct {
@ -80,56 +81,64 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D {
} }
} }
m.Menu.list.Axis = layout.Vertical m.Menu.list.Axis = layout.Vertical
return m.Menu.list.Layout(gtx, len(items), func(gtx C, i int) D { m.Menu.scrollBar.Axis = layout.Vertical
defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() return layout.Stack{Alignment: layout.SE}.Layout(gtx,
var macro op.MacroOp layout.Expanded(func(gtx C) D {
item := &items[i] return m.Menu.list.Layout(gtx, len(items), func(gtx C, i int) D {
if i == m.Menu.hover-1 && !item.Disabled { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
macro = op.Record(gtx.Ops) var macro op.MacroOp
} item := &items[i]
icon := widgetForIcon(item.IconBytes) if i == m.Menu.hover-1 && !item.Disabled {
iconColor := m.IconColor macro = op.Record(gtx.Ops)
if item.Disabled { }
iconColor = mediumEmphasisTextColor icon := widgetForIcon(item.IconBytes)
} iconColor := m.IconColor
iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)} if item.Disabled {
textLabel := LabelStyle{Text: item.Text, FontSize: m.FontSize, Color: m.TextColor} iconColor = mediumEmphasisTextColor
if item.Disabled { }
textLabel.Color = mediumEmphasisTextColor iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)}
} textLabel := LabelStyle{Text: item.Text, FontSize: m.FontSize, Color: m.TextColor}
shortcutLabel := LabelStyle{Text: item.ShortcutText, FontSize: m.FontSize, Color: m.ShortCutColor} if item.Disabled {
shortcutInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(12), Bottom: unit.Dp(2), Top: unit.Dp(2)} textLabel.Color = mediumEmphasisTextColor
dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, }
layout.Rigid(func(gtx C) D { shortcutLabel := LabelStyle{Text: item.ShortcutText, FontSize: m.FontSize, Color: m.ShortCutColor}
return iconInset.Layout(gtx, func(gtx C) D { shortcutInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(12), Bottom: unit.Dp(2), Top: unit.Dp(2)}
p := gtx.Dp(unit.Dp(m.IconSize)) dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
gtx.Constraints.Min = image.Pt(p, p) layout.Rigid(func(gtx C) D {
return icon.Layout(gtx, iconColor) return iconInset.Layout(gtx, func(gtx C) D {
}) p := gtx.Dp(unit.Dp(m.IconSize))
}), gtx.Constraints.Min = image.Pt(p, p)
layout.Rigid(textLabel.Layout), return icon.Layout(gtx, iconColor)
layout.Flexed(1, func(gtx C) D { return D{Size: image.Pt(gtx.Constraints.Max.X, 1)} }), })
layout.Rigid(func(gtx C) D { }),
return shortcutInset.Layout(gtx, shortcutLabel.Layout) layout.Rigid(textLabel.Layout),
}), layout.Flexed(1, func(gtx C) D { return D{Size: image.Pt(gtx.Constraints.Max.X, 1)} }),
) layout.Rigid(func(gtx C) D {
if i == m.Menu.hover-1 && !item.Disabled { return shortcutInset.Layout(gtx, shortcutLabel.Layout)
recording := macro.Stop() }),
paint.FillShape(gtx.Ops, m.HoverColor, clip.Rect{ )
Max: image.Pt(dims.Size.X, dims.Size.Y), if i == m.Menu.hover-1 && !item.Disabled {
}.Op()) recording := macro.Stop()
recording.Add(gtx.Ops) paint.FillShape(gtx.Ops, m.HoverColor, clip.Rect{
} Max: image.Pt(dims.Size.X, dims.Size.Y),
if !item.Disabled { }.Op())
rect := image.Rect(0, 0, dims.Size.X, dims.Size.Y) recording.Add(gtx.Ops)
area := clip.Rect(rect).Push(gtx.Ops) }
pointer.InputOp{Tag: &m.Menu.tags[i], if !item.Disabled {
Types: pointer.Press | pointer.Enter | pointer.Leave, rect := image.Rect(0, 0, dims.Size.X, dims.Size.Y)
}.Add(gtx.Ops) area := clip.Rect(rect).Push(gtx.Ops)
area.Pop() pointer.InputOp{Tag: &m.Menu.tags[i],
} Types: pointer.Press | pointer.Enter | pointer.Leave,
return dims }.Add(gtx.Ops)
}) area.Pop()
}
return dims
})
}),
layout.Expanded(func(gtx C) D {
return m.Menu.scrollBar.Layout(gtx, unit.Dp(10), len(items), &m.Menu.list.Position)
}),
)
} }
popup := Popup(&m.Menu.Visible) popup := Popup(&m.Menu.Visible)
popup.NE = unit.Dp(0) popup.NE = unit.Dp(0)