This repository has been archived by the owner on Nov 5, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 297
/
focus_controller.go
126 lines (108 loc) · 2.48 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
// 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 Window
focus Focusable
setFocusCount int
detachSubscription EventSubscription
}
func CreateFocusController(window Window) *FocusController {
return &FocusController{
window: window,
}
}
func (c *FocusController) SetFocus(f Focusable) {
c.setFocusCount++
if c.focus == f {
return
}
if c.focus != nil {
o := c.focus
c.focus = nil
c.detachSubscription.Unlisten()
o.LostFocus()
if c.focus != nil {
return // Something in LostFocus() called SetFocus(). Respect their call.
}
}
c.focus = f
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(after Control, forwards bool) Focusable {
container, _ := after.(Container)
if container != nil {
f := c.NextChildFocusable(container, nil, forwards)
if f != nil {
return f
}
}
for after != nil {
parent := after.Parent()
if parent != nil {
f := c.NextChildFocusable(parent, after, forwards)
if f != nil {
return f
}
}
after, _ = parent.(Control)
}
return c.NextChildFocusable(c.window, nil, forwards)
}
func (c *FocusController) NextChildFocusable(p Parent, after Control, forwards bool) Focusable {
examineNext := after == nil
children := p.Children()
i := 0
e := len(children)
if !forwards {
i = len(children) - 1
e = -1
}
for i != e {
f := children[i]
if forwards {
i++
} else {
i--
}
if !examineNext {
if f.Control == after {
examineNext = true
}
continue
}
if focusable := c.Focusable(f.Control); focusable != nil {
return focusable
}
if container, ok := f.Control.(Container); ok {
focusable := c.NextChildFocusable(container, nil, forwards)
if focusable != nil {
return focusable
}
}
}
return nil
}
func (c *FocusController) Focusable(ctrl Control) Focusable {
focusable, _ := ctrl.(Focusable)
if focusable != nil && focusable.IsFocusable() {
return focusable
}
return nil
}