124 lines
2.8 KiB
Go
124 lines
2.8 KiB
Go
|
package internal
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
|
||
|
"fyne.io/fyne/v2"
|
||
|
"fyne.io/fyne/v2/internal/app"
|
||
|
"fyne.io/fyne/v2/internal/widget"
|
||
|
)
|
||
|
|
||
|
// OverlayStack implements fyne.OverlayStack
|
||
|
type OverlayStack struct {
|
||
|
OnChange func()
|
||
|
Canvas fyne.Canvas
|
||
|
focusManagers []*app.FocusManager
|
||
|
overlays []fyne.CanvasObject
|
||
|
propertyLock sync.RWMutex
|
||
|
}
|
||
|
|
||
|
var _ fyne.OverlayStack = (*OverlayStack)(nil)
|
||
|
|
||
|
// Add puts an overlay on the stack.
|
||
|
//
|
||
|
// Implements: fyne.OverlayStack
|
||
|
func (s *OverlayStack) Add(overlay fyne.CanvasObject) {
|
||
|
if overlay == nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if s.OnChange != nil {
|
||
|
defer s.OnChange()
|
||
|
}
|
||
|
|
||
|
s.propertyLock.Lock()
|
||
|
defer s.propertyLock.Unlock()
|
||
|
s.overlays = append(s.overlays, overlay)
|
||
|
|
||
|
// TODO this should probably apply to all once #707 is addressed
|
||
|
if _, ok := overlay.(*widget.OverlayContainer); ok {
|
||
|
safePos, safeSize := s.Canvas.InteractiveArea()
|
||
|
|
||
|
overlay.Resize(safeSize)
|
||
|
overlay.Move(safePos)
|
||
|
}
|
||
|
|
||
|
s.focusManagers = append(s.focusManagers, app.NewFocusManager(overlay))
|
||
|
}
|
||
|
|
||
|
// List returns all overlays on the stack from bottom to top.
|
||
|
//
|
||
|
// Implements: fyne.OverlayStack
|
||
|
func (s *OverlayStack) List() []fyne.CanvasObject {
|
||
|
s.propertyLock.RLock()
|
||
|
defer s.propertyLock.RUnlock()
|
||
|
|
||
|
return s.overlays
|
||
|
}
|
||
|
|
||
|
// ListFocusManagers returns all focus managers on the stack from bottom to top.
|
||
|
func (s *OverlayStack) ListFocusManagers() []*app.FocusManager {
|
||
|
s.propertyLock.RLock()
|
||
|
defer s.propertyLock.RUnlock()
|
||
|
|
||
|
return s.focusManagers
|
||
|
}
|
||
|
|
||
|
// Remove deletes an overlay and all overlays above it from the stack.
|
||
|
//
|
||
|
// Implements: fyne.OverlayStack
|
||
|
func (s *OverlayStack) Remove(overlay fyne.CanvasObject) {
|
||
|
if s.OnChange != nil {
|
||
|
defer s.OnChange()
|
||
|
}
|
||
|
|
||
|
s.propertyLock.Lock()
|
||
|
defer s.propertyLock.Unlock()
|
||
|
|
||
|
overlayIdx := -1
|
||
|
for i, o := range s.overlays {
|
||
|
if o == overlay {
|
||
|
overlayIdx = i
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if overlayIdx == -1 {
|
||
|
return
|
||
|
}
|
||
|
// set removed elements in backing array to nil to release memory references
|
||
|
for i := overlayIdx; i < len(s.overlays); i++ {
|
||
|
s.overlays[i] = nil
|
||
|
s.focusManagers[i] = nil
|
||
|
}
|
||
|
s.overlays = s.overlays[:overlayIdx]
|
||
|
s.focusManagers = s.focusManagers[:overlayIdx]
|
||
|
}
|
||
|
|
||
|
// Top returns the top-most overlay of the stack.
|
||
|
//
|
||
|
// Implements: fyne.OverlayStack
|
||
|
func (s *OverlayStack) Top() fyne.CanvasObject {
|
||
|
s.propertyLock.RLock()
|
||
|
defer s.propertyLock.RUnlock()
|
||
|
|
||
|
if len(s.overlays) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return s.overlays[len(s.overlays)-1]
|
||
|
}
|
||
|
|
||
|
// TopFocusManager returns the app.FocusManager assigned to the top-most overlay of the stack.
|
||
|
func (s *OverlayStack) TopFocusManager() *app.FocusManager {
|
||
|
s.propertyLock.RLock()
|
||
|
defer s.propertyLock.RUnlock()
|
||
|
return s.topFocusManager()
|
||
|
}
|
||
|
|
||
|
func (s *OverlayStack) topFocusManager() *app.FocusManager {
|
||
|
var fm *app.FocusManager
|
||
|
if len(s.focusManagers) > 0 {
|
||
|
fm = s.focusManagers[len(s.focusManagers)-1]
|
||
|
}
|
||
|
return fm
|
||
|
}
|