1 /*      _______   __   __   __   ______   __   __   _______   __   __
2  *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
3  *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
4  *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
5  *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
6  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
7  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
8  *
9  * Copyright (c) 2004, 2005 darkbits                        Js_./
10  * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
11  * Olof Naess�n a.k.a jansem/yakslem                _asww7!uY`>  )\a//
12  *                                                 _Qhm`] _f "'c  1!5m
13  * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
14  *                                               .)j(] .d_/ '-(  P .   S
15  * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
16  * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
17  * binary forms, with or without                 )4d[#7r, .   '     )d`)[
18  * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
19  * that the following conditions are met:       j<<WP+k/);.        _W=j f
20  * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
21  *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
22  *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
23  *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
24  * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
25  *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
26  *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
27  *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
28  *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
29  *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
30  * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
31  *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
32  *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
33  *    from this software without specific        (js, \[QQW$QWW#?!V"".
34  *    prior written permission.                    ]y:.<\..          .
35  *                                                 -]n w/ '         [.
36  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
37  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
38  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
39  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
40  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
41  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
42  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
43  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
44  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
45  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
46  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
47  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
51  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
52  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53  */
54 
55 /*
56  * For comments regarding functions please see the header file.
57  */
58 
59 #include <ctype.h>  // for isascii
60 #include <assert.h>
61 #include "guichan/focushandler.h"
62 #include "guichan/exception.h"
63 
64 namespace gcn
65 {
FocusHandler()66     FocusHandler::FocusHandler()
67     {
68         mFocusedWidget = NULL;
69         mDraggedWidget = NULL;
70         mToBeFocused = NULL;
71         mToBeDragged = NULL;
72         mModalFocusedWidget = NULL;
73     }
74 
requestFocus(Widget * widget)75     void FocusHandler::requestFocus(Widget* widget)
76     {
77         mToBeFocused = widget;
78     }
79 
setFocus(Widget * widget)80     void FocusHandler::setFocus(Widget* widget)
81     {
82         mFocusedWidget = widget;
83     }
84 
requestDrag(Widget * widget)85     void FocusHandler::requestDrag(Widget* widget)
86     {
87         mToBeDragged = widget;
88     }
89 
requestModalFocus(Widget * widget)90     void FocusHandler::requestModalFocus(Widget* widget)
91     {
92         if (mModalFocusedWidget != NULL && mModalFocusedWidget != widget)
93         {
94       		assert(!"Another widget allready has modal focus.");
95             //throw GCN_EXCEPTION("Another widget allready has modal focus.");
96         }
97 
98         mModalFocusedWidget = widget;
99 
100         if (mFocusedWidget != NULL && !mFocusedWidget->hasModalFocus())
101         {
102             focusNone();
103         }
104 
105         if (mDraggedWidget != NULL && !mDraggedWidget->hasModalFocus())
106         {
107             dragNone();
108         }
109     }
110 
releaseModalFocus(Widget * widget)111     void FocusHandler::releaseModalFocus(Widget* widget)
112     {
113         if (mModalFocusedWidget == widget)
114         {
115             mModalFocusedWidget = NULL;
116         }
117     }
118 
getFocused() const119     Widget* FocusHandler::getFocused() const
120     {
121         return mFocusedWidget;
122     }
123 
getDragged() const124     Widget* FocusHandler::getDragged() const
125     {
126         return mDraggedWidget;
127     }
128 
getModalFocused() const129     Widget* FocusHandler::getModalFocused() const
130     {
131         return mModalFocusedWidget;
132     }
133 
focusNext()134     void FocusHandler::focusNext()
135     {
136         int i;
137         int focusedWidget = -1;
138         for (i = 0; i < (int)mWidgets.size(); ++i)
139         {
140             if (mWidgets[i] == mFocusedWidget)
141             {
142                 focusedWidget = i;
143             }
144         }
145         int focused = focusedWidget;
146 
147         // i is a counter that ensures that the following loop
148         // won't get stuck in an infinite loop
149         i = (int)mWidgets.size();
150         do
151         {
152             ++focusedWidget;
153 
154             if (i==0)
155             {
156                 focusedWidget = -1;
157                 break;
158             }
159 
160             --i;
161 
162             if (focusedWidget >= (int)mWidgets.size())
163             {
164                 focusedWidget = 0;
165             }
166 
167             if (focusedWidget == focused)
168             {
169                 return;
170             }
171         }
172         while (!mWidgets.at(focusedWidget)->isFocusable());
173 
174         if (focusedWidget >= 0)
175         {
176             mFocusedWidget = mWidgets.at(focusedWidget);
177             mWidgets.at(focusedWidget)->gotFocus();
178         }
179 
180         if (focused >= 0)
181         {
182             mWidgets.at(focused)->lostFocus();
183         }
184     }
185 
focusPrevious()186     void FocusHandler::focusPrevious()
187     {
188         if (mWidgets.size() == 0)
189         {
190             mFocusedWidget = NULL;
191             return;
192         }
193 
194         int i;
195         int focusedWidget = -1;
196         for (i = 0; i < (int)mWidgets.size(); ++i)
197         {
198             if (mWidgets[i] == mFocusedWidget)
199             {
200                 focusedWidget = i;
201             }
202         }
203         int focused = focusedWidget;
204 
205         // i is a counter that ensures that the following loop
206         // won't get stuck in an infinite loop
207         i = (int)mWidgets.size();
208         do
209         {
210             --focusedWidget;
211 
212             if (i==0)
213             {
214                 focusedWidget = -1;
215                 break;
216             }
217 
218             --i;
219 
220             if (focusedWidget <= 0)
221             {
222                 focusedWidget = mWidgets.size() - 1;
223             }
224 
225             if (focusedWidget == focused)
226             {
227                 return;
228             }
229         }
230         while (!mWidgets.at(focusedWidget)->isFocusable());
231 
232         if (focusedWidget >= 0)
233         {
234             mFocusedWidget = mWidgets.at(focusedWidget);
235             mWidgets.at(focusedWidget)->gotFocus();
236         }
237 
238         if (focused >= 0)
239         {
240             mWidgets.at(focused)->lostFocus();
241         }
242     }
243 
hasFocus(const Widget * widget) const244     bool FocusHandler::hasFocus(const Widget* widget) const
245     {
246         return mFocusedWidget == widget;
247     }
248 
isDragged(const Widget * widget) const249      bool FocusHandler::isDragged(const Widget* widget) const
250      {
251         return mDraggedWidget == widget;
252      }
253 
add(Widget * widget)254     void FocusHandler::add(Widget* widget)
255     {
256         mWidgets.push_back(widget);
257     }
258 
remove(Widget * widget)259     void FocusHandler::remove(Widget* widget)
260     {
261         if (widget == mFocusedWidget)
262         {
263             mFocusedWidget = NULL;
264         }
265         if (widget == mDraggedWidget)
266         {
267             mDraggedWidget = NULL;
268         }
269         if (widget == mToBeFocused)
270         {
271             mToBeFocused = NULL;
272         }
273         if (widget == mToBeDragged)
274         {
275             mToBeDragged = NULL;
276         }
277 
278         if (hasFocus(widget))
279         {
280             mFocusedWidget = NULL;
281             mToBeFocused = NULL;
282         }
283 
284         int i = 0;
285         WidgetIterator iter;
286 
287         for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter)
288         {
289             ++i;
290 
291             if ((*iter) == widget)
292             {
293                 mWidgets.erase(iter);
294                 return;
295             }
296         }
297     }
298 
focusNone()299     void FocusHandler::focusNone()
300     {
301 
302         if (mFocusedWidget != NULL)
303         {
304             Widget* focused = mFocusedWidget;
305             mFocusedWidget = NULL;
306             focused->lostFocus();
307         }
308 
309         mToBeFocused = NULL;
310     }
311 
dragNone()312     void FocusHandler::dragNone()
313     {
314         mDraggedWidget = NULL;
315     }
316 
checkHotKey(const KeyInput & keyInput)317     void FocusHandler::checkHotKey(const KeyInput &keyInput)
318     {
319         int keyin = keyInput.getKey().getValue();
320 
321         for (int i = 0; i < (int)mWidgets.size(); ++i)
322         {
323             int hotKey = mWidgets[i]->getHotKey();
324 
325             if (hotKey == 0)
326             {
327                 continue;
328             }
329 
330             if ((isascii(keyin) && tolower(keyin) == hotKey) || keyin == hotKey)
331             {
332                 if (keyInput.getType() == KeyInput::PRESS)
333                 {
334                     mWidgets[i]->hotKeyPress();
335                     if (mWidgets[i]->isFocusable())
336                     {
337                         this->requestFocus(mWidgets[i]);
338                     }
339                 }
340                 else
341                 {
342                     mWidgets[i]->hotKeyRelease();
343                 }
344                 break;
345             }
346         }
347     }
348 
tabNext()349     void FocusHandler::tabNext()
350     {
351         if (mFocusedWidget != NULL)
352         {
353             if (!mFocusedWidget->isTabOutEnabled())
354             {
355                 return;
356             }
357         }
358 
359         if (mWidgets.size() == 0)
360         {
361             mFocusedWidget = NULL;
362             return;
363         }
364 
365         int i;
366         int focusedWidget = -1;
367         for (i = 0; i < (int)mWidgets.size(); ++i)
368         {
369             if (mWidgets[i] == mFocusedWidget)
370             {
371                 focusedWidget = i;
372             }
373         }
374         int focused = focusedWidget;
375         bool done = false;
376 
377         // i is a counter that ensures that the following loop
378         // won't get stuck in an infinite loop
379         i = (int)mWidgets.size();
380         do
381         {
382             ++focusedWidget;
383 
384             if (i==0)
385             {
386                 focusedWidget = -1;
387                 break;
388             }
389 
390             --i;
391 
392             if (focusedWidget >= (int)mWidgets.size())
393             {
394                 focusedWidget = 0;
395             }
396 
397             if (focusedWidget == focused)
398             {
399                 return;
400             }
401 
402             if (mWidgets.at(focusedWidget)->isFocusable() &&
403                 mWidgets.at(focusedWidget)->isTabInEnabled() &&
404                 (mModalFocusedWidget == NULL ||
405                  mWidgets.at(focusedWidget)->hasModalFocus()))
406             {
407                 done = true;
408             }
409         }
410         while (!done);
411 
412         if (focusedWidget >= 0)
413         {
414             mFocusedWidget = mWidgets.at(focusedWidget);
415             mWidgets.at(focusedWidget)->gotFocus();
416         }
417 
418         if (focused >= 0)
419         {
420             mWidgets.at(focused)->lostFocus();
421         }
422     }
423 
tabPrevious()424     void FocusHandler::tabPrevious()
425     {
426         if (mFocusedWidget != NULL)
427         {
428             if (!mFocusedWidget->isTabOutEnabled())
429             {
430                 return;
431             }
432         }
433 
434         if (mWidgets.size() == 0)
435         {
436             mFocusedWidget = NULL;
437             return;
438         }
439 
440         int i;
441         int focusedWidget = -1;
442         for (i = 0; i < (int)mWidgets.size(); ++i)
443         {
444             if (mWidgets[i] == mFocusedWidget)
445             {
446                 focusedWidget = i;
447             }
448         }
449         int focused = focusedWidget;
450         bool done = false;
451 
452         // i is a counter that ensures that the following loop
453         // won't get stuck in an infinite loop
454         i = (int)mWidgets.size();
455         do
456         {
457             --focusedWidget;
458 
459             if (i==0)
460             {
461                 focusedWidget = -1;
462                 break;
463             }
464 
465             --i;
466 
467             if (focusedWidget <= 0)
468             {
469                 focusedWidget = mWidgets.size() - 1;
470             }
471 
472             if (focusedWidget == focused)
473             {
474                 return;
475             }
476 
477             if (mWidgets.at(focusedWidget)->isFocusable() &&
478                 mWidgets.at(focusedWidget)->isTabInEnabled() &&
479                 (mModalFocusedWidget == NULL ||
480                  mWidgets.at(focusedWidget)->hasModalFocus()))
481             {
482                 done = true;
483             }
484         }
485         while (!done);
486 
487         if (focusedWidget >= 0)
488         {
489             mFocusedWidget = mWidgets.at(focusedWidget);
490             mWidgets.at(focusedWidget)->gotFocus();
491         }
492 
493         if (focused >= 0)
494         {
495             mWidgets.at(focused)->lostFocus();
496         }
497     }
498 
applyChanges()499     void FocusHandler::applyChanges()
500     {
501         if (mToBeFocused != NULL)
502         {
503             unsigned int i = 0;
504             int toBeFocusedIndex = -1;
505             for (i = 0; i < mWidgets.size(); ++i)
506             {
507                 if (mWidgets[i] == mToBeFocused)
508                 {
509                     toBeFocusedIndex = i;
510                     break;
511                 }
512             }
513 
514             if (toBeFocusedIndex < 0)
515             {
516             	assert(!"Trying to focus a none existing widget.");
517                 //throw GCN_EXCEPTION("Trying to focus a none existing widget.");
518             }
519 
520             Widget *oldFocused = mFocusedWidget;
521 
522             if (oldFocused != mToBeFocused)
523             {
524                 mFocusedWidget = mWidgets.at(toBeFocusedIndex);
525 
526                 if (oldFocused != NULL)
527                 {
528                     oldFocused->lostFocus();
529                 }
530 
531                 mWidgets.at(toBeFocusedIndex)->gotFocus();
532             }
533             mToBeFocused = NULL;
534         }
535 
536         if (mToBeDragged != NULL)
537         {
538             unsigned int i = 0;
539             int toBeDraggedIndex = -1;
540             for (i = 0; i < mWidgets.size(); ++i)
541             {
542                 if (mWidgets[i] == mToBeDragged)
543                 {
544                     toBeDraggedIndex = i;
545                     break;
546                 }
547             }
548 
549             if (toBeDraggedIndex < 0)
550             {
551             	assert(!"Trying to give drag to a none existing widget.");
552                 //throw GCN_EXCEPTION("Trying to give drag to a none existing widget");
553             }
554 
555              mDraggedWidget = mWidgets.at(toBeDraggedIndex);
556              mToBeDragged = NULL;
557         }
558     }
559 }
560