1 //
2 // This file is part of libyacurs.
3 // Copyright (C) 2013 Rafael Ostertag
4 //
5 // This program is free software: you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation, either version 3 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see
17 // <http://www.gnu.org/licenses/>.
18 //
19 //
20 // $Id$
21
22 #include <cassert>
23
24 #include "eventqueue.h"
25 #include "focusmanager.h"
26 #include "yacursdbg.h"
27 #include "yacursex.h"
28
29 using namespace YACURS;
30
31 const FocusManager::fgid_t FocusManager::nfgid = (FocusManager::fgid_t)-1;
32 FocusManager::fgid_t FocusManager::_active_focusgroup = FocusManager::nfgid;
33 std::vector<FocusGroup*> FocusManager::_focus_groups;
34
35 //
36 // Private
37 //
focus_change_handler(Event & e)38 void FocusManager::focus_change_handler(Event& e) {
39 assert(e == EVT_FOCUS_NEXT || e == EVT_FOCUS_PREVIOUS);
40
41 if (_focus_groups.empty()) return;
42 assert(_active_focusgroup < _focus_groups.size());
43 assert(_focus_groups[_active_focusgroup] != 0);
44 assert(_focus_groups[_active_focusgroup]->active());
45
46 if (e.type() == EVT_FOCUS_NEXT) {
47 _focus_groups[_active_focusgroup]->focus_next();
48 DEBUGOUT(DBG_FOCUSMGR, "focus_next() on " << _active_focusgroup);
49 } else if (e.type() == EVT_FOCUS_PREVIOUS) {
50 _focus_groups[_active_focusgroup]->focus_previous();
51 DEBUGOUT(DBG_FOCUSMGR, "focus_previous() on " << _active_focusgroup);
52 } else {
53 throw EXCEPTIONS::UnexpectedEvent();
54 }
55 }
56
57 //
58 // Protected
59 //
60
61 //
62 // Public
63 //
64
init()65 void FocusManager::init() {
66 DEBUGOUT(DBG_FOCUSMGR, "Initialize Focus Manager");
67 EventQueue::connect_event(EventConnectorFunction1(
68 EVT_FOCUS_NEXT, FocusManager::focus_change_handler));
69 EventQueue::connect_event(EventConnectorFunction1(
70 EVT_FOCUS_PREVIOUS, FocusManager::focus_change_handler));
71 }
72
uninit()73 void FocusManager::uninit() {
74 DEBUGOUT(DBG_FOCUSMGR, "Uninitialize Focus Manager");
75 EventQueue::disconnect_event(EventConnectorFunction1(
76 EVT_FOCUS_NEXT, FocusManager::focus_change_handler));
77 EventQueue::disconnect_event(EventConnectorFunction1(
78 EVT_FOCUS_PREVIOUS, FocusManager::focus_change_handler));
79
80 for (fgid_t i = 0; i < _focus_groups.size(); i++)
81 if (_focus_groups[i] != 0) {
82 delete _focus_groups[i];
83 _focus_groups[i] = 0;
84 }
85 }
86
new_focus_group()87 FocusManager::fgid_t FocusManager::new_focus_group() {
88 fgid_t id = FocusManager::nfgid;
89
90 if (_focus_groups.empty()) {
91 id = _focus_groups.size(); // == 0
92 _focus_groups.push_back(new FocusGroup);
93 DEBUGOUT(DBG_FOCUSMGR, "New Focus Group (first) "
94 << (void*)(_focus_groups[id])
95 << " with ID: " << id);
96 } else {
97 // Search for a free slot in the vector
98 for (fgid_t i = 0; i < _focus_groups.size(); i++) {
99 if (_focus_groups[i] == 0) {
100 // found free slot
101 id = i;
102 _focus_groups[i] = new FocusGroup;
103 DEBUGOUT(DBG_FOCUSMGR, "New Focus Group (reuse slot) "
104 << (void*)(_focus_groups[id])
105 << " with ID: " << id);
106 break;
107 }
108 }
109
110 // Check if we have found a free slot, i.e. id has been set
111 if (id == FocusManager::nfgid) {
112 // No, no free slot, so create new slot.
113 id = _focus_groups.size();
114 _focus_groups.push_back(new FocusGroup);
115 DEBUGOUT(DBG_FOCUSMGR, "New Focus Group (new slot) "
116 << (void*)(_focus_groups[id])
117 << " with ID: " << id);
118 }
119 }
120
121 assert(id != FocusManager::nfgid);
122 assert(id < _focus_groups.size());
123 return id;
124 }
125
destroy_focus_group(fgid_t id)126 void FocusManager::destroy_focus_group(fgid_t id) {
127 assert(!_focus_groups.empty());
128 assert(id < _focus_groups.size());
129
130 // check if the FocusGroup still exists.
131 //
132 // It is possible that the Focus Groups have been destroyed by a
133 // call to ::uninit() due to termination of the event loop, but
134 // destruction of Windows were still not done. See the test
135 // 'listbox2.cc' for an example of this bevavior
136 if (_focus_groups[id] == 0) return;
137
138 // Destructor of FocusGroup is supposed to take care of removing
139 // focus, so we simply destroy the group.
140 delete _focus_groups[id];
141 _focus_groups[id] = 0;
142 DEBUGOUT(DBG_FOCUSMGR, "Destroy Focus Group " << (void*)(_focus_groups[id])
143 << " with ID: " << id);
144
145 if (_active_focusgroup == id) _active_focusgroup = FocusManager::nfgid;
146 }
147
focus_group_add(fgid_t id,WidgetBase * w)148 void FocusManager::focus_group_add(fgid_t id, WidgetBase* w) {
149 assert(w != 0);
150 assert(!_focus_groups.empty());
151 assert(id < _focus_groups.size());
152 assert(_focus_groups[id] != 0);
153
154 _focus_groups[id]->add(w);
155
156 DEBUGOUT(DBG_FOCUSMGR, "Add widget " << (void*)(w) << " to Focus Group "
157 << (void*)(_focus_groups[id])
158 << " with ID: " << id);
159 }
160
focus_group_remove(fgid_t id,WidgetBase * w)161 void FocusManager::focus_group_remove(fgid_t id, WidgetBase* w) {
162 assert(w != 0);
163 assert(id != FocusManager::nfgid);
164
165 // check if the FocusGroup still exists.
166 //
167 // It is possible that the Focus Groups have been destroyed by a
168 // call to ::uninit() due to termination of the event loop, but
169 // destruction of Windows were still not done. See the test
170 // 'listbox2.cc' for an example of this bevavior
171 if (_focus_groups[id] == 0) return;
172
173 _focus_groups[id]->remove(w);
174
175 DEBUGOUT(DBG_FOCUSMGR, "Remove widget " << (void*)(w) << " to Focus Group "
176 << (void*)(_focus_groups[id])
177 << " with ID: " << id);
178 }
179
focus_group_activate(fgid_t id)180 void FocusManager::focus_group_activate(fgid_t id) {
181 assert(!_focus_groups.empty());
182 assert(id < _focus_groups.size());
183 assert(_focus_groups[id] != 0);
184 // We cannot assert this here, because fgid_t is probably of
185 // unsigned type and initially set to -1, so we cannot get past
186 // this assertion, since the first call which would make
187 // subsequent calls pass, always fails.
188 //
189 // assert(_active_focusgroup<_focus_groups.size());
190
191 // Deactivate the current Active Focus Group, if any.
192 if (_active_focusgroup != FocusManager::nfgid && // not initialized yet
193 _focus_groups[_active_focusgroup] != 0 /* Focus Group destroyed */) {
194 assert(_active_focusgroup < _focus_groups.size());
195 _focus_groups[_active_focusgroup]->deactivate();
196 DEBUGOUT(DBG_FOCUSMGR, "Deactivated Focus Group "
197 << (void*)(_focus_groups[_active_focusgroup])
198 << " with ID: " << _active_focusgroup);
199 }
200
201 _focus_groups[id]->activate();
202 _active_focusgroup = id;
203 DEBUGOUT(DBG_FOCUSMGR, "Activated Focus Group "
204 << (void*)(_focus_groups[id])
205 << " with ID: " << id);
206 }
207
refocus()208 void FocusManager::refocus() {
209 if (_focus_groups.empty()) return;
210
211 assert(_active_focusgroup != FocusManager::nfgid);
212 assert(_focus_groups[_active_focusgroup] != 0);
213 // This would make many tests fail. Also, it should be no problem
214 // if we don't assert.
215 //
216 // assert(!_focus_groups.empty());
217
218 _focus_groups[_active_focusgroup]->refocus();
219 DEBUGOUT(DBG_FOCUSMGR, "Refocus Focus Group "
220 << (void*)(_focus_groups[_active_focusgroup])
221 << " with ID: " << _active_focusgroup);
222 }
223
reset()224 void FocusManager::reset() {
225 if (_focus_groups.empty()) return;
226 assert(_active_focusgroup != FocusManager::nfgid);
227 assert(_focus_groups[_active_focusgroup] != 0);
228 _focus_groups[_active_focusgroup]->reset();
229 DEBUGOUT(DBG_FOCUSMGR, "Reset Focus Group "
230 << (void*)(_focus_groups[_active_focusgroup])
231 << " with ID: " << _active_focusgroup);
232 }
233
active_focus_group()234 FocusManager::fgid_t FocusManager::active_focus_group() {
235 return _active_focusgroup;
236 }
237