adam-gui/vendor/fyne.io/fyne/v2/internal/overlay_stack.go
2024-04-29 19:13:50 +02:00

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
}