overlay_stack.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package internal
  2. import (
  3. "sync"
  4. "fyne.io/fyne/v2"
  5. "fyne.io/fyne/v2/internal/app"
  6. "fyne.io/fyne/v2/internal/widget"
  7. )
  8. // OverlayStack implements fyne.OverlayStack
  9. type OverlayStack struct {
  10. OnChange func()
  11. Canvas fyne.Canvas
  12. focusManagers []*app.FocusManager
  13. overlays []fyne.CanvasObject
  14. propertyLock sync.RWMutex
  15. }
  16. var _ fyne.OverlayStack = (*OverlayStack)(nil)
  17. // Add puts an overlay on the stack.
  18. //
  19. // Implements: fyne.OverlayStack
  20. func (s *OverlayStack) Add(overlay fyne.CanvasObject) {
  21. if overlay == nil {
  22. return
  23. }
  24. if s.OnChange != nil {
  25. defer s.OnChange()
  26. }
  27. s.propertyLock.Lock()
  28. defer s.propertyLock.Unlock()
  29. s.overlays = append(s.overlays, overlay)
  30. // TODO this should probably apply to all once #707 is addressed
  31. if _, ok := overlay.(*widget.OverlayContainer); ok {
  32. safePos, safeSize := s.Canvas.InteractiveArea()
  33. overlay.Resize(safeSize)
  34. overlay.Move(safePos)
  35. }
  36. s.focusManagers = append(s.focusManagers, app.NewFocusManager(overlay))
  37. }
  38. // List returns all overlays on the stack from bottom to top.
  39. //
  40. // Implements: fyne.OverlayStack
  41. func (s *OverlayStack) List() []fyne.CanvasObject {
  42. s.propertyLock.RLock()
  43. defer s.propertyLock.RUnlock()
  44. return s.overlays
  45. }
  46. // ListFocusManagers returns all focus managers on the stack from bottom to top.
  47. func (s *OverlayStack) ListFocusManagers() []*app.FocusManager {
  48. s.propertyLock.RLock()
  49. defer s.propertyLock.RUnlock()
  50. return s.focusManagers
  51. }
  52. // Remove deletes an overlay and all overlays above it from the stack.
  53. //
  54. // Implements: fyne.OverlayStack
  55. func (s *OverlayStack) Remove(overlay fyne.CanvasObject) {
  56. if s.OnChange != nil {
  57. defer s.OnChange()
  58. }
  59. s.propertyLock.Lock()
  60. defer s.propertyLock.Unlock()
  61. overlayIdx := -1
  62. for i, o := range s.overlays {
  63. if o == overlay {
  64. overlayIdx = i
  65. break
  66. }
  67. }
  68. if overlayIdx == -1 {
  69. return
  70. }
  71. // set removed elements in backing array to nil to release memory references
  72. for i := overlayIdx; i < len(s.overlays); i++ {
  73. s.overlays[i] = nil
  74. s.focusManagers[i] = nil
  75. }
  76. s.overlays = s.overlays[:overlayIdx]
  77. s.focusManagers = s.focusManagers[:overlayIdx]
  78. }
  79. // Top returns the top-most overlay of the stack.
  80. //
  81. // Implements: fyne.OverlayStack
  82. func (s *OverlayStack) Top() fyne.CanvasObject {
  83. s.propertyLock.RLock()
  84. defer s.propertyLock.RUnlock()
  85. if len(s.overlays) == 0 {
  86. return nil
  87. }
  88. return s.overlays[len(s.overlays)-1]
  89. }
  90. // TopFocusManager returns the app.FocusManager assigned to the top-most overlay of the stack.
  91. func (s *OverlayStack) TopFocusManager() *app.FocusManager {
  92. s.propertyLock.RLock()
  93. defer s.propertyLock.RUnlock()
  94. return s.topFocusManager()
  95. }
  96. func (s *OverlayStack) topFocusManager() *app.FocusManager {
  97. var fm *app.FocusManager
  98. if len(s.focusManagers) > 0 {
  99. fm = s.focusManagers[len(s.focusManagers)-1]
  100. }
  101. return fm
  102. }