leonsal 8 лет назад
Родитель
Сommit
395d043f80
1 измененных файлов с 56 добавлено и 0 удалено
  1. 56 0
      gui/root.go

+ 56 - 0
gui/root.go

@@ -11,6 +11,7 @@ import (
 	"sort"
 )
 
+// Root is the container and dispatcher of panel events
 type Root struct {
 	Panel                            // embedded panel
 	core.TimerManager                // embedded TimerManager
@@ -20,6 +21,7 @@ type Root struct {
 	keyFocus          IPanel         // current child panel with key focus
 	mouseFocus        IPanel         // current child panel with mouse focus
 	scrollFocus       IPanel         // current child panel with scroll focus
+	modalPanel        IPanel         // current modal panel
 	targets           listPanelZ     // preallocated list of target panels
 }
 
@@ -74,6 +76,14 @@ func (r *Root) Add(ipan IPanel) {
 	r.Panel.Add(ipan)
 }
 
+// SetModal sets the modal panel.
+// If there is a modal panel, only events for this panel are dispatched
+// To remove the modal panel call this function with a nil panel.
+func (r *Root) SetModal(ipan IPanel) {
+
+	r.modalPanel = ipan
+}
+
 // SetKeyFocus sets the panel which will receive all keyboard events
 // Passing nil will remove the focus (if any)
 func (r *Root) SetKeyFocus(ipan IPanel) {
@@ -177,6 +187,10 @@ func (r *Root) onKey(evname string, ev interface{}) {
 	if r.keyFocus == nil {
 		return
 	}
+	// Checks modal panel
+	if !r.canDispatch(r.keyFocus) {
+		return
+	}
 	// Dispatch window.KeyEvent to focused panel subscribers
 	r.stopPropagation = 0
 	r.keyFocus.GetPanel().Dispatch(evname, ev)
@@ -193,6 +207,10 @@ func (r *Root) onChar(evname string, ev interface{}) {
 	if r.keyFocus == nil {
 		return
 	}
+	// Checks modal panel
+	if !r.canDispatch(r.keyFocus) {
+		return
+	}
 	// Dispatch window.CharEvent to focused panel subscribers
 	r.stopPropagation = 0
 	r.keyFocus.GetPanel().Dispatch(evname, ev)
@@ -222,6 +240,10 @@ func (r *Root) sendPanels(x, y float32, evname string, ev interface{}) {
 
 	// If there is panel with MouseFocus send only to this panel
 	if r.mouseFocus != nil {
+		// Checks modal panel
+		if !r.canDispatch(r.mouseFocus) {
+			return
+		}
 		r.mouseFocus.GetPanel().Dispatch(evname, ev)
 		if (r.stopPropagation & Stop3D) != 0 {
 			r.win.CancelDispatch()
@@ -290,6 +312,10 @@ func (r *Root) sendPanels(x, y float32, evname string, ev interface{}) {
 
 	// Send events to panels
 	for _, ipan := range r.targets {
+		// Checks modal panel
+		if !r.canDispatch(ipan) {
+			continue
+		}
 		pan := ipan.GetPanel()
 		// Cursor position event
 		if evname == OnCursor {
@@ -345,6 +371,36 @@ func (r *Root) onFrame(evname string, ev interface{}) {
 	r.TimerManager.ProcessTimers()
 }
 
+// canDispatch returns if event can be dispatched to the specified panel
+// An event cannot be dispatched if there is a modal panel and the specified
+// panel is not the modal panel or any of its children.
+func (r *Root) canDispatch(ipan IPanel) bool {
+
+	if r.modalPanel == nil {
+		return true
+	}
+	if r.modalPanel == ipan {
+		return true
+	}
+
+	// Internal function to check panel children recursively
+	var checkChildren func(iparent IPanel) bool
+	checkChildren = func(iparent IPanel) bool {
+		parent := iparent.GetPanel()
+		for _, child := range parent.Children() {
+			if child == ipan {
+				return true
+			}
+			res := checkChildren(child.(IPanel))
+			if res {
+				return res
+			}
+		}
+		return false
+	}
+	return checkChildren(r.modalPanel)
+}
+
 // For sorting panels by Z coordinate
 type listPanelZ []IPanel