-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathpopup_menu.go
157 lines (139 loc) · 4.2 KB
/
popup_menu.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package widget
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/internal/widget"
)
var _ fyne.Widget = (*PopUpMenu)(nil)
var _ fyne.Focusable = (*PopUpMenu)(nil)
// PopUpMenu is a Menu which displays itself in an OverlayContainer.
type PopUpMenu struct {
*Menu
canvas fyne.Canvas
overlay *widget.OverlayContainer
}
// NewPopUpMenu creates a new, reusable popup menu. You can show it using ShowAtPosition.
//
// Since: 2.0
func NewPopUpMenu(menu *fyne.Menu, c fyne.Canvas) *PopUpMenu {
m := &Menu{}
m.setMenu(menu)
p := &PopUpMenu{Menu: m, canvas: c}
p.ExtendBaseWidget(p)
p.Menu.Resize(p.Menu.MinSize())
p.Menu.customSized = true
o := widget.NewOverlayContainer(p, c, p.Dismiss)
o.Resize(o.MinSize())
p.overlay = o
p.OnDismiss = func() {
p.Hide()
}
return p
}
// ShowPopUpMenuAtPosition creates a PopUp menu populated with items from the passed menu structure.
// It will automatically be positioned at the provided location and shown as an overlay on the specified canvas.
func ShowPopUpMenuAtPosition(menu *fyne.Menu, c fyne.Canvas, pos fyne.Position) {
m := NewPopUpMenu(menu, c)
m.ShowAtPosition(pos)
}
// ShowPopUpMenuAtRelativePosition creates a PopUp menu populated with meny items from the passed menu structure.
// It will automatically be positioned at the given position relative to stated object and shown as an overlay on the specified canvas.
//
// Since 2.4
func ShowPopUpMenuAtRelativePosition(menu *fyne.Menu, c fyne.Canvas, rel fyne.Position, to fyne.CanvasObject) {
withRelativePosition(rel, to, func(pos fyne.Position) {
ShowPopUpMenuAtPosition(menu, c, pos)
})
}
// FocusGained is triggered when the object gained focus. For the pop-up menu it does nothing.
//
// Implements: fyne.Focusable
func (p *PopUpMenu) FocusGained() {}
// FocusLost is triggered when the object lost focus. For the pop-up menu it does nothing.
//
// Implements: fyne.Focusable
func (p *PopUpMenu) FocusLost() {}
// Hide hides the pop-up menu.
//
// Implements: fyne.Widget
func (p *PopUpMenu) Hide() {
p.overlay.Hide()
p.Menu.Hide()
}
// Move moves the pop-up menu.
// The position is absolute because pop-up menus are shown in an overlay which covers the whole canvas.
//
// Implements: fyne.Widget
func (p *PopUpMenu) Move(pos fyne.Position) {
p.BaseWidget.Move(p.adjustedPosition(pos, p.Size()))
}
// Resize changes the size of the pop-up menu.
//
// Implements: fyne.Widget
func (p *PopUpMenu) Resize(size fyne.Size) {
p.BaseWidget.Move(p.adjustedPosition(p.Position(), size))
p.Menu.Resize(size)
}
// Show makes the pop-up menu visible.
//
// Implements: fyne.Widget
func (p *PopUpMenu) Show() {
p.Menu.alignment = p.alignment
p.Menu.Refresh()
p.overlay.Show()
p.Menu.Show()
if !fyne.CurrentDevice().IsMobile() {
p.canvas.Focus(p)
}
}
// ShowAtPosition shows the pop-up menu at the specified position.
func (p *PopUpMenu) ShowAtPosition(pos fyne.Position) {
p.Move(pos)
p.Show()
}
// ShowAtRelativePosition shows the pop-up menu at the position relative to given object.
//
// Since 2.4
func (p *PopUpMenu) ShowAtRelativePosition(rel fyne.Position, to fyne.CanvasObject) {
withRelativePosition(rel, to, p.ShowAtPosition)
}
// TypedKey handles key events. It allows keyboard control of the pop-up menu.
//
// Implements: fyne.Focusable
func (p *PopUpMenu) TypedKey(e *fyne.KeyEvent) {
switch e.Name {
case fyne.KeyDown:
p.ActivateNext()
case fyne.KeyEnter, fyne.KeyReturn, fyne.KeySpace:
p.TriggerLast()
case fyne.KeyEscape:
p.Dismiss()
case fyne.KeyLeft:
p.DeactivateLastSubmenu()
case fyne.KeyRight:
p.ActivateLastSubmenu()
case fyne.KeyUp:
p.ActivatePrevious()
}
}
// TypedRune handles text events. For pop-up menus this does nothing.
//
// Implements: fyne.Focusable
func (p *PopUpMenu) TypedRune(rune) {}
func (p *PopUpMenu) adjustedPosition(pos fyne.Position, size fyne.Size) fyne.Position {
x := pos.X
y := pos.Y
_, areaSize := p.canvas.InteractiveArea()
if x+size.Width > areaSize.Width {
x = areaSize.Width - size.Width
if x < 0 {
x = 0 // TODO here we may need a scroller as it's wider than our canvas
}
}
if y+size.Height > areaSize.Height {
y = areaSize.Height - size.Height
if y < 0 {
y = 0 // TODO here we may need a scroller as it's longer than our canvas
}
}
return fyne.NewPos(x, y)
}