menu.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package mobile
  2. import (
  3. "image/color"
  4. "fyne.io/fyne/v2"
  5. "fyne.io/fyne/v2/canvas"
  6. "fyne.io/fyne/v2/container"
  7. "fyne.io/fyne/v2/layout"
  8. "fyne.io/fyne/v2/theme"
  9. "fyne.io/fyne/v2/widget"
  10. )
  11. type menuLabel struct {
  12. widget.BaseWidget
  13. menu *fyne.Menu
  14. bar *fyne.Container
  15. canvas *mobileCanvas
  16. }
  17. func (m *menuLabel) Tapped(*fyne.PointEvent) {
  18. pos := fyne.CurrentApp().Driver().AbsolutePositionForObject(m)
  19. menu := widget.NewPopUpMenu(m.menu, m.canvas)
  20. menu.ShowAtPosition(fyne.NewPos(pos.X+m.Size().Width, pos.Y))
  21. menuDismiss := menu.OnDismiss // this dismisses the menu stack
  22. menu.OnDismiss = func() {
  23. menuDismiss()
  24. m.bar.Hide() // dismiss the overlay menu bar
  25. m.canvas.setMenu(nil)
  26. }
  27. }
  28. func (m *menuLabel) CreateRenderer() fyne.WidgetRenderer {
  29. label := widget.NewLabel(m.menu.Label)
  30. box := container.NewHBox(layout.NewSpacer(), label, layout.NewSpacer(), widget.NewIcon(theme.MenuExpandIcon()))
  31. return &menuLabelRenderer{menu: m, content: box}
  32. }
  33. func newMenuLabel(item *fyne.Menu, parent *fyne.Container, c *mobileCanvas) *menuLabel {
  34. l := &menuLabel{menu: item, bar: parent, canvas: c}
  35. l.ExtendBaseWidget(l)
  36. return l
  37. }
  38. func (c *mobileCanvas) showMenu(menu *fyne.MainMenu) {
  39. var panel *fyne.Container
  40. top := container.NewHBox(widget.NewButtonWithIcon("", theme.CancelIcon(), func() {
  41. panel.Hide()
  42. c.setMenu(nil)
  43. }))
  44. panel = container.NewVBox(top)
  45. for _, item := range menu.Items {
  46. panel.Add(newMenuLabel(item, panel, c))
  47. }
  48. bg := canvas.NewRectangle(theme.BackgroundColor())
  49. shadow := canvas.NewHorizontalGradient(theme.ShadowColor(), color.Transparent)
  50. safePos, safeSize := c.InteractiveArea()
  51. bg.Move(safePos)
  52. bg.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), safeSize.Height))
  53. panel.Move(safePos)
  54. panel.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), safeSize.Height))
  55. shadow.Resize(fyne.NewSize(theme.Padding()/2, safeSize.Height))
  56. shadow.Move(fyne.NewPos(panel.Size().Width+safePos.X, safePos.Y))
  57. c.setMenu(container.NewWithoutLayout(bg, panel, shadow))
  58. }
  59. func (d *mobileDriver) findMenu(win *window) *fyne.MainMenu {
  60. if win.menu != nil {
  61. return win.menu
  62. }
  63. matched := false
  64. for x := len(d.windows) - 1; x >= 0; x-- {
  65. w := d.windows[x]
  66. if !matched {
  67. if w == win {
  68. matched = true
  69. }
  70. continue
  71. }
  72. if w.(*window).menu != nil {
  73. return w.(*window).menu
  74. }
  75. }
  76. return nil
  77. }
  78. type menuLabelRenderer struct {
  79. menu *menuLabel
  80. content *fyne.Container
  81. }
  82. func (m *menuLabelRenderer) BackgroundColor() color.Color {
  83. return theme.BackgroundColor()
  84. }
  85. func (m *menuLabelRenderer) Destroy() {
  86. }
  87. func (m *menuLabelRenderer) Layout(size fyne.Size) {
  88. m.content.Resize(size)
  89. }
  90. func (m *menuLabelRenderer) MinSize() fyne.Size {
  91. return m.content.MinSize()
  92. }
  93. func (m *menuLabelRenderer) Objects() []fyne.CanvasObject {
  94. return []fyne.CanvasObject{m.content}
  95. }
  96. func (m *menuLabelRenderer) Refresh() {
  97. m.content.Refresh()
  98. }