From 4c9bc9f83ab1ad5db283f621d959c8db498f3e39 Mon Sep 17 00:00:00 2001 From: Leandro Dorileo Date: Wed, 18 Apr 2018 16:26:07 -0700 Subject: [PATCH 1/3] clui: simplify NextControl() method This patch simplifies the implementation of NextControl(), FindLastControl() and FindFirstControl() methods. --- ctrlutil.go | 119 +++++++++++++++++++++------------------------------- 1 file changed, 48 insertions(+), 71 deletions(-) diff --git a/ctrlutil.go b/ctrlutil.go index 48e6398..b12cf7d 100644 --- a/ctrlutil.go +++ b/ctrlutil.go @@ -148,37 +148,25 @@ func IsMouseClickEvent(ev Event) bool { // FindFirstControl returns the first child for that fn returns true. // The function is used to find active or tab-stop control func FindFirstControl(parent Control, fn func(Control) bool) Control { - for _, child := range parent.Children() { - if fn(child) { - return child - } - - ch := FindFirstControl(child, fn) - if ch != nil { - return ch - } + linear := getLinearControlList(parent, fn) + if len(linear) == 0 { + return nil } - return nil + return linear[0] } // FindLastControl returns the first child for that fn returns true. // The function is used by TAB processing method if a user goes backwards // with TAB key - not supported now func FindLastControl(parent Control, fn func(Control) bool) Control { - var last Control - for _, child := range parent.Children() { - if fn(child) { - last = child - } + linear := getLinearControlList(parent, fn) - ch := FindLastControl(child, fn) - if ch != nil { - last = ch - } + if len(linear) == 0 { + return nil } - return last + return linear[len(linear)-1] } // ActiveControl returns the active child of the parent or nil if no child is @@ -190,43 +178,25 @@ func ActiveControl(parent Control) Control { return FindFirstControl(parent, fnActive) } -func _nextControl(parent Control, curr, prev Control, foundPrev, next bool) (bool, Control) { - found := foundPrev - if parent == curr { - if next { - found = true - } else { - return false, prev +func getLinearControlList(parent Control, fn func(Control) bool) []Control { + result := []Control{} + + for _, curr := range parent.Children() { + if fn(curr) { + result = append(result, curr) + } + + if len(curr.Children()) == 0 { + continue + } + + ch := getLinearControlList(curr, fn) + if len(ch) != 0 { + result = append(result, ch...) } } - p := prev - for _, ctrl := range parent.Children() { - if ctrl == curr { - if next { - found = true - continue - } else { - return found, p - } - } - - if ctrl.Enabled() && ctrl.TabStop() && ctrl.Visible() { - if found { - return found, ctrl - } else if !next { - p = ctrl - } - } - - fnd, nn := _nextControl(ctrl, curr, p, found, next) - if nn != nil { - return fnd, nn - } - found = fnd - } - - return found, nil + return result } // NextControl returns the next or previous child (depends on next parameter) @@ -236,26 +206,33 @@ func NextControl(parent Control, curr Control, next bool) Control { return c.TabStop() && c.Visible() } - var defControl Control + linear := getLinearControlList(parent, fnTab) + + var pIndex, nIndex int + + for i, ch := range linear { + if ch != curr { + continue + } + + pIndex = i - 1 + nIndex = i + 1 + break + } + + if nIndex > len(linear)-1 { + nIndex = 0 + } + + if pIndex < 0 { + pIndex = len(linear) - 1 + } + if next { - defControl = FindFirstControl(parent, fnTab) + return linear[nIndex] } else { - defControl = FindLastControl(parent, fnTab) + return linear[pIndex] } - - if defControl == nil { - return nil - } - if curr == nil { - return defControl - } - - _, cNext := _nextControl(parent, curr, nil, false, next) - if cNext == nil { - cNext = defControl - } - - return cNext } // SendEventToChild tries to find a child control that should recieve the evetn From 212c6b3a4154c13c8d7800aae3010c54090bea99 Mon Sep 17 00:00:00 2001 From: Leandro Dorileo Date: Wed, 18 Apr 2018 16:27:01 -0700 Subject: [PATCH 2/3] clui: control selection Implements the control selection with keyUp and keyDown besides the KeyTab selection. --- window.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/window.go b/window.go index 9a2f750..d8e108a 100644 --- a/window.go +++ b/window.go @@ -226,9 +226,13 @@ func (c *Window) ProcessEvent(ev Event) bool { } return true case EventKey: - if ev.Key == term.KeyTab { + if ev.Key == term.KeyTab || ev.Key == term.KeyArrowUp || ev.Key == term.KeyArrowDown { + if SendEventToChild(c, ev) { + return true + } + aC := ActiveControl(c) - nC := NextControl(c, aC, true) + nC := NextControl(c, aC, ev.Key != term.KeyArrowUp) if nC != aC { if aC != nil { aC.SetActive(false) From 0b2b6067c14b05f8107acad8404ad54f52b9d720 Mon Sep 17 00:00:00 2001 From: Leandro Dorileo Date: Wed, 18 Apr 2018 16:27:48 -0700 Subject: [PATCH 3/3] clui: NextControl() also filter out disabled controls When selecting previous or next controls in we want to also filter out the disabled controls - since they will never get focused. --- ctrlutil.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctrlutil.go b/ctrlutil.go index b12cf7d..6ec926a 100644 --- a/ctrlutil.go +++ b/ctrlutil.go @@ -203,7 +203,7 @@ func getLinearControlList(parent Control, fn func(Control) bool) []Control { // that has tab-stop feature on. Used by library when processing TAB key func NextControl(parent Control, curr Control, next bool) Control { fnTab := func(c Control) bool { - return c.TabStop() && c.Visible() + return c.TabStop() && c.Visible() && c.Enabled() } linear := getLinearControlList(parent, fnTab)