overlay_stack.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. for i, o := range s.overlays {
  62. if o == overlay {
  63. s.overlays = s.overlays[:i]
  64. s.focusManagers = s.focusManagers[:i]
  65. break
  66. }
  67. }
  68. }
  69. // Top returns the top-most overlay of the stack.
  70. //
  71. // Implements: fyne.OverlayStack
  72. func (s *OverlayStack) Top() fyne.CanvasObject {
  73. s.propertyLock.RLock()
  74. defer s.propertyLock.RUnlock()
  75. if len(s.overlays) == 0 {
  76. return nil
  77. }
  78. return s.overlays[len(s.overlays)-1]
  79. }
  80. // TopFocusManager returns the app.FocusManager assigned to the top-most overlay of the stack.
  81. func (s *OverlayStack) TopFocusManager() *app.FocusManager {
  82. s.propertyLock.RLock()
  83. defer s.propertyLock.RUnlock()
  84. return s.topFocusManager()
  85. }
  86. func (s *OverlayStack) topFocusManager() *app.FocusManager {
  87. var fm *app.FocusManager
  88. if len(s.focusManagers) > 0 {
  89. fm = s.focusManagers[len(s.focusManagers)-1]
  90. }
  91. return fm
  92. }