forked from google/gxui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfocus_controller.go
127 lines (106 loc) · 2.6 KB
/
focus_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gxui
type FocusController struct {
window *WindowImpl
focus Focusable
detachSubscription EventSubscription
setFocusCount int
}
func CreateFocusController(window *WindowImpl) *FocusController {
return &FocusController{window: window}
}
func (c *FocusController) SetFocus(target Focusable) {
c.setFocusCount++
if c.focus == target {
return
}
if c.focus != nil {
o := c.focus
c.focus = nil
c.detachSubscription.Forget()
o.LostFocus()
if c.focus != nil {
return // Something in LostFocus() called SetFocus(). Respect their call.
}
}
c.focus = target
if c.focus != nil {
c.detachSubscription = c.focus.OnDetach(func() { c.SetFocus(nil) })
c.focus.GainedFocus()
}
}
func (c *FocusController) SetFocusCount() int {
return c.setFocusCount
}
func (c *FocusController) Focus() Focusable {
return c.focus
}
func (c *FocusController) FocusNext() {
c.SetFocus(c.NextFocusable(c.focus, true))
}
func (c *FocusController) FocusPrev() {
c.SetFocus(c.NextFocusable(c.focus, false))
}
func (c *FocusController) NextFocusable(control Control, forwards bool) Focusable {
container, _ := control.(Container)
if container != nil {
child := c.NextChildFocusable(container, nil, forwards)
if child != nil {
return child
}
}
for control != nil {
parent := control.Parent()
if parent != nil {
child := c.NextChildFocusable(parent, control, forwards)
if child != nil {
return child
}
}
control, _ = parent.(Control)
}
return c.NextChildFocusable(c.window, nil, forwards)
}
func (c *FocusController) NextChildFocusable(parent Parent, control Control, forwards bool) Focusable {
examineNext := control == nil
children := parent.Children()
index := 0
numChildren := len(children)
if !forwards {
index = len(children) - 1
numChildren = -1
}
for index != numChildren {
child := children[index]
if forwards {
index++
} else {
index--
}
if !examineNext {
if child.Control == control {
examineNext = true
}
continue
}
if target := c.Focusable(child.Control); target != nil {
return target
}
if container, ok := child.Control.(Container); ok {
focusable := c.NextChildFocusable(container, nil, forwards)
if focusable != nil {
return focusable
}
}
}
return nil
}
func (c *FocusController) Focusable(control Control) Focusable {
target, _ := control.(Focusable)
if target != nil && target.IsFocusable() {
return target
}
return nil
}