menu.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. if c.padded {
  49. panel = container.NewPadded(panel)
  50. }
  51. bg := canvas.NewRectangle(theme.BackgroundColor())
  52. shadow := canvas.NewHorizontalGradient(theme.ShadowColor(), color.Transparent)
  53. safePos, safeSize := c.InteractiveArea()
  54. bg.Move(safePos)
  55. bg.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), safeSize.Height))
  56. panel.Move(safePos)
  57. panel.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), safeSize.Height))
  58. shadow.Resize(fyne.NewSize(theme.Padding()/2, safeSize.Height))
  59. shadow.Move(fyne.NewPos(panel.Size().Width+safePos.X, safePos.Y))
  60. c.setMenu(container.NewWithoutLayout(bg, panel, shadow))
  61. }
  62. func (d *mobileDriver) findMenu(win *window) *fyne.MainMenu {
  63. if win.menu != nil {
  64. return win.menu
  65. }
  66. matched := false
  67. for x := len(d.windows) - 1; x >= 0; x-- {
  68. w := d.windows[x]
  69. if !matched {
  70. if w == win {
  71. matched = true
  72. }
  73. continue
  74. }
  75. if w.(*window).menu != nil {
  76. return w.(*window).menu
  77. }
  78. }
  79. return nil
  80. }
  81. type menuLabelRenderer struct {
  82. menu *menuLabel
  83. content *fyne.Container
  84. }
  85. func (m *menuLabelRenderer) BackgroundColor() color.Color {
  86. return theme.BackgroundColor()
  87. }
  88. func (m *menuLabelRenderer) Destroy() {
  89. }
  90. func (m *menuLabelRenderer) Layout(size fyne.Size) {
  91. m.content.Resize(size)
  92. }
  93. func (m *menuLabelRenderer) MinSize() fyne.Size {
  94. return m.content.MinSize()
  95. }
  96. func (m *menuLabelRenderer) Objects() []fyne.CanvasObject {
  97. return []fyne.CanvasObject{m.content}
  98. }
  99. func (m *menuLabelRenderer) Refresh() {
  100. m.content.Refresh()
  101. }