126 lines
2.9 KiB
Go
126 lines
2.9 KiB
Go
|
package mobile
|
||
|
|
||
|
import (
|
||
|
"image/color"
|
||
|
|
||
|
"fyne.io/fyne/v2"
|
||
|
"fyne.io/fyne/v2/canvas"
|
||
|
"fyne.io/fyne/v2/container"
|
||
|
"fyne.io/fyne/v2/layout"
|
||
|
"fyne.io/fyne/v2/theme"
|
||
|
"fyne.io/fyne/v2/widget"
|
||
|
)
|
||
|
|
||
|
type menuLabel struct {
|
||
|
widget.BaseWidget
|
||
|
|
||
|
menu *fyne.Menu
|
||
|
bar *fyne.Container
|
||
|
canvas *mobileCanvas
|
||
|
}
|
||
|
|
||
|
func (m *menuLabel) Tapped(*fyne.PointEvent) {
|
||
|
pos := fyne.CurrentApp().Driver().AbsolutePositionForObject(m)
|
||
|
menu := widget.NewPopUpMenu(m.menu, m.canvas)
|
||
|
menu.ShowAtPosition(fyne.NewPos(pos.X+m.Size().Width, pos.Y))
|
||
|
|
||
|
menuDismiss := menu.OnDismiss // this dismisses the menu stack
|
||
|
menu.OnDismiss = func() {
|
||
|
menuDismiss()
|
||
|
m.bar.Hide() // dismiss the overlay menu bar
|
||
|
m.canvas.setMenu(nil)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *menuLabel) CreateRenderer() fyne.WidgetRenderer {
|
||
|
label := widget.NewLabel(m.menu.Label)
|
||
|
box := container.NewHBox(layout.NewSpacer(), label, layout.NewSpacer(), widget.NewIcon(theme.MenuExpandIcon()))
|
||
|
|
||
|
return &menuLabelRenderer{menu: m, content: box}
|
||
|
}
|
||
|
|
||
|
func newMenuLabel(item *fyne.Menu, parent *fyne.Container, c *mobileCanvas) *menuLabel {
|
||
|
l := &menuLabel{menu: item, bar: parent, canvas: c}
|
||
|
l.ExtendBaseWidget(l)
|
||
|
return l
|
||
|
}
|
||
|
|
||
|
func (c *mobileCanvas) showMenu(menu *fyne.MainMenu) {
|
||
|
var panel *fyne.Container
|
||
|
top := container.NewHBox(widget.NewButtonWithIcon("", theme.CancelIcon(), func() {
|
||
|
panel.Hide()
|
||
|
c.setMenu(nil)
|
||
|
}))
|
||
|
panel = container.NewVBox(top)
|
||
|
for _, item := range menu.Items {
|
||
|
panel.Add(newMenuLabel(item, panel, c))
|
||
|
}
|
||
|
if c.padded {
|
||
|
panel = container.NewPadded(panel)
|
||
|
}
|
||
|
|
||
|
bg := canvas.NewRectangle(theme.BackgroundColor())
|
||
|
shadow := canvas.NewHorizontalGradient(theme.ShadowColor(), color.Transparent)
|
||
|
|
||
|
safePos, safeSize := c.InteractiveArea()
|
||
|
bg.Move(safePos)
|
||
|
bg.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), safeSize.Height))
|
||
|
panel.Move(safePos)
|
||
|
panel.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), safeSize.Height))
|
||
|
shadow.Resize(fyne.NewSize(theme.Padding()/2, safeSize.Height))
|
||
|
shadow.Move(fyne.NewPos(panel.Size().Width+safePos.X, safePos.Y))
|
||
|
|
||
|
c.setMenu(container.NewWithoutLayout(bg, panel, shadow))
|
||
|
}
|
||
|
|
||
|
func (d *mobileDriver) findMenu(win *window) *fyne.MainMenu {
|
||
|
if win.menu != nil {
|
||
|
return win.menu
|
||
|
}
|
||
|
|
||
|
matched := false
|
||
|
for x := len(d.windows) - 1; x >= 0; x-- {
|
||
|
w := d.windows[x]
|
||
|
if !matched {
|
||
|
if w == win {
|
||
|
matched = true
|
||
|
}
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if w.(*window).menu != nil {
|
||
|
return w.(*window).menu
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type menuLabelRenderer struct {
|
||
|
menu *menuLabel
|
||
|
content *fyne.Container
|
||
|
}
|
||
|
|
||
|
func (m *menuLabelRenderer) BackgroundColor() color.Color {
|
||
|
return theme.BackgroundColor()
|
||
|
}
|
||
|
|
||
|
func (m *menuLabelRenderer) Destroy() {
|
||
|
}
|
||
|
|
||
|
func (m *menuLabelRenderer) Layout(size fyne.Size) {
|
||
|
m.content.Resize(size)
|
||
|
}
|
||
|
|
||
|
func (m *menuLabelRenderer) MinSize() fyne.Size {
|
||
|
return m.content.MinSize()
|
||
|
}
|
||
|
|
||
|
func (m *menuLabelRenderer) Objects() []fyne.CanvasObject {
|
||
|
return []fyne.CanvasObject{m.content}
|
||
|
}
|
||
|
|
||
|
func (m *menuLabelRenderer) Refresh() {
|
||
|
m.content.Refresh()
|
||
|
}
|