00001 /* _______ __ __ __ ______ __ __ _______ __ __ 00002 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 00003 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 00004 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 00005 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 00006 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 00007 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 00008 * 00009 * Copyright (c) 2004, 2005, 2006 Olof Naessén and Per Larsson 00010 * 00011 * Js_./ 00012 * Per Larsson a.k.a finalman _RqZ{a<^_aa 00013 * Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a// 00014 * _Qhm`] _f "'c 1!5m 00015 * Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[ 00016 * .)j(] .d_/ '-( P . S 00017 * License: (BSD) <Td/Z <fP"5(\"??"\a. .L 00018 * Redistribution and use in source and _dV>ws?a-?' ._/L #' 00019 * binary forms, with or without )4d[#7r, . ' )d`)[ 00020 * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam' 00021 * that the following conditions are met: j<<WP+k/);. _W=j f 00022 * 1. Redistributions of source code must .$%w\/]Q . ."' . mj$ 00023 * retain the above copyright notice, ]E.pYY(Q]>. a J@\ 00024 * this list of conditions and the j(]1u<sE"L,. . ./^ ]{a 00025 * following disclaimer. 4'_uomm\. )L);-4 (3= 00026 * 2. Redistributions in binary form must )_]X{Z('a_"a7'<a"a, ]"[ 00027 * reproduce the above copyright notice, #}<]m7`Za??4,P-"'7. ).m 00028 * this list of conditions and the ]d2e)Q(<Q( ?94 b- LQ/ 00029 * following disclaimer in the <B!</]C)d_, '(<' .f. =C+m 00030 * documentation and/or other materials .Z!=J ]e []('-4f _ ) -.)m]' 00031 * provided with the distribution. .w[5]' _[ /.)_-"+? _/ <W" 00032 * 3. Neither the name of Guichan nor the :$we` _! + _/ . j? 00033 * names of its contributors may be used =3)= _f (_yQmWW$#( " 00034 * to endorse or promote products derived - W, sQQQQmZQ#Wwa].. 00035 * from this software without specific (js, \[QQW$QWW#?!V"". 00036 * prior written permission. ]y:.<\.. . 00037 * -]n w/ ' [. 00038 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT )/ )/ ! 00039 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY < (; sac , ' 00040 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, ]^ .- % 00041 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF c < r 00042 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR aga< <La 00043 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 5% )P'-3L 00044 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR _bQf` y`..)a 00045 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ,J?4P'.P"_(\?d'., 00046 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES _Pa,)!f/<[]/ ?" 00047 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT _2-..:. .r+_,.. . 00048 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ?a.<%"' " -'.a_ _, 00049 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ^ 00050 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00051 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00052 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00053 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00054 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00055 */ 00056 00057 /* 00058 * For comments regarding functions please see the header file. 00059 */ 00060 00061 #include "guichan/focushandler.hpp" 00062 00063 #include "guichan/exception.hpp" 00064 #include "guichan/widget.hpp" 00065 00066 namespace gcn 00067 { 00068 FocusHandler::FocusHandler() 00069 { 00070 mFocusedWidget = NULL; 00071 mDraggedWidget = NULL; 00072 mToBeFocused = NULL; 00073 mToBeDragged = NULL; 00074 mModalFocusedWidget = NULL; 00075 } 00076 00077 void FocusHandler::requestFocus(Widget* widget) 00078 { 00079 mToBeFocused = widget; 00080 } 00081 00082 void FocusHandler::requestDrag(Widget* widget) 00083 { 00084 mToBeDragged = widget; 00085 } 00086 00087 void FocusHandler::requestModalFocus(Widget* widget) 00088 { 00089 if (mModalFocusedWidget != NULL && mModalFocusedWidget != widget) 00090 { 00091 throw GCN_EXCEPTION("Another widget allready has modal focus."); 00092 } 00093 00094 mModalFocusedWidget = widget; 00095 00096 if (mFocusedWidget != NULL && !mFocusedWidget->hasModalFocus()) 00097 { 00098 focusNone(); 00099 } 00100 00101 if (mDraggedWidget != NULL && !mDraggedWidget->hasModalFocus()) 00102 { 00103 dragNone(); 00104 } 00105 } 00106 00107 void FocusHandler::releaseModalFocus(Widget* widget) 00108 { 00109 if (mModalFocusedWidget == widget) 00110 { 00111 mModalFocusedWidget = NULL; 00112 } 00113 } 00114 00115 Widget* FocusHandler::getFocused() const 00116 { 00117 return mFocusedWidget; 00118 } 00119 00120 Widget* FocusHandler::getDragged() const 00121 { 00122 return mDraggedWidget; 00123 } 00124 00125 Widget* FocusHandler::getModalFocused() const 00126 { 00127 return mModalFocusedWidget; 00128 } 00129 00130 void FocusHandler::focusNext() 00131 { 00132 int i; 00133 int focusedWidget = -1; 00134 for (i = 0; i < (int)mWidgets.size(); ++i) 00135 { 00136 if (mWidgets[i] == mFocusedWidget) 00137 { 00138 focusedWidget = i; 00139 } 00140 } 00141 int focused = focusedWidget; 00142 00143 // i is a counter that ensures that the following loop 00144 // won't get stuck in an infinite loop 00145 i = (int)mWidgets.size(); 00146 do 00147 { 00148 ++focusedWidget; 00149 00150 if (i==0) 00151 { 00152 focusedWidget = -1; 00153 break; 00154 } 00155 00156 --i; 00157 00158 if (focusedWidget >= (int)mWidgets.size()) 00159 { 00160 focusedWidget = 0; 00161 } 00162 00163 if (focusedWidget == focused) 00164 { 00165 return; 00166 } 00167 } 00168 while (!mWidgets.at(focusedWidget)->isFocusable()); 00169 00170 if (focusedWidget >= 0) 00171 { 00172 mFocusedWidget = mWidgets.at(focusedWidget); 00173 mWidgets.at(focusedWidget)->gotFocus(); 00174 } 00175 00176 if (focused >= 0) 00177 { 00178 mWidgets.at(focused)->lostFocus(); 00179 } 00180 } 00181 00182 void FocusHandler::focusPrevious() 00183 { 00184 if (mWidgets.size() == 0) 00185 { 00186 mFocusedWidget = NULL; 00187 return; 00188 } 00189 00190 int i; 00191 int focusedWidget = -1; 00192 for (i = 0; i < (int)mWidgets.size(); ++i) 00193 { 00194 if (mWidgets[i] == mFocusedWidget) 00195 { 00196 focusedWidget = i; 00197 } 00198 } 00199 int focused = focusedWidget; 00200 00201 // i is a counter that ensures that the following loop 00202 // won't get stuck in an infinite loop 00203 i = (int)mWidgets.size(); 00204 do 00205 { 00206 --focusedWidget; 00207 00208 if (i==0) 00209 { 00210 focusedWidget = -1; 00211 break; 00212 } 00213 00214 --i; 00215 00216 if (focusedWidget <= 0) 00217 { 00218 focusedWidget = mWidgets.size() - 1; 00219 } 00220 00221 if (focusedWidget == focused) 00222 { 00223 return; 00224 } 00225 } 00226 while (!mWidgets.at(focusedWidget)->isFocusable()); 00227 00228 if (focusedWidget >= 0) 00229 { 00230 mFocusedWidget = mWidgets.at(focusedWidget); 00231 mWidgets.at(focusedWidget)->gotFocus(); 00232 } 00233 00234 if (focused >= 0) 00235 { 00236 mWidgets.at(focused)->lostFocus(); 00237 } 00238 } 00239 00240 bool FocusHandler::isFocused(const Widget* widget) const 00241 { 00242 return mFocusedWidget == widget; 00243 } 00244 00245 bool FocusHandler::isDragged(const Widget* widget) const 00246 { 00247 return mDraggedWidget == widget; 00248 } 00249 00250 void FocusHandler::add(Widget* widget) 00251 { 00252 mWidgets.push_back(widget); 00253 } 00254 00255 void FocusHandler::remove(Widget* widget) 00256 { 00257 if (widget == mToBeFocused) 00258 { 00259 mToBeFocused = NULL; 00260 } 00261 if (widget == mToBeDragged) 00262 { 00263 mToBeDragged = NULL; 00264 } 00265 00266 if (isFocused(widget)) 00267 { 00268 mFocusedWidget = NULL; 00269 mToBeFocused = NULL; 00270 } 00271 00272 int i = 0; 00273 WidgetIterator iter; 00274 00275 for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter) 00276 { 00277 ++i; 00278 00279 if ((*iter) == widget) 00280 { 00281 mWidgets.erase(iter); 00282 return; 00283 } 00284 } 00285 } 00286 00287 void FocusHandler::focusNone() 00288 { 00289 00290 if (mFocusedWidget != NULL) 00291 { 00292 Widget* focused = mFocusedWidget; 00293 mFocusedWidget = NULL; 00294 focused->lostFocus(); 00295 } 00296 00297 mToBeFocused = NULL; 00298 } 00299 00300 void FocusHandler::dragNone() 00301 { 00302 mDraggedWidget = NULL; 00303 } 00304 00305 void FocusHandler::tabNext() 00306 { 00307 if (mFocusedWidget != NULL) 00308 { 00309 if (!mFocusedWidget->isTabOutEnabled()) 00310 { 00311 return; 00312 } 00313 } 00314 00315 if (mWidgets.size() == 0) 00316 { 00317 mFocusedWidget = NULL; 00318 return; 00319 } 00320 00321 int i; 00322 int focusedWidget = -1; 00323 for (i = 0; i < (int)mWidgets.size(); ++i) 00324 { 00325 if (mWidgets[i] == mFocusedWidget) 00326 { 00327 focusedWidget = i; 00328 } 00329 } 00330 int focused = focusedWidget; 00331 bool done = false; 00332 00333 // i is a counter that ensures that the following loop 00334 // won't get stuck in an infinite loop 00335 i = (int)mWidgets.size(); 00336 do 00337 { 00338 ++focusedWidget; 00339 00340 if (i==0) 00341 { 00342 focusedWidget = -1; 00343 break; 00344 } 00345 00346 --i; 00347 00348 if (focusedWidget >= (int)mWidgets.size()) 00349 { 00350 focusedWidget = 0; 00351 } 00352 00353 if (focusedWidget == focused) 00354 { 00355 return; 00356 } 00357 00358 if (mWidgets.at(focusedWidget)->isFocusable() && 00359 mWidgets.at(focusedWidget)->isTabInEnabled() && 00360 (mModalFocusedWidget == NULL || 00361 mWidgets.at(focusedWidget)->hasModalFocus())) 00362 { 00363 done = true; 00364 } 00365 } 00366 while (!done); 00367 00368 if (focusedWidget >= 0) 00369 { 00370 mFocusedWidget = mWidgets.at(focusedWidget); 00371 mWidgets.at(focusedWidget)->gotFocus(); 00372 } 00373 00374 if (focused >= 0) 00375 { 00376 mWidgets.at(focused)->lostFocus(); 00377 } 00378 } 00379 00380 void FocusHandler::tabPrevious() 00381 { 00382 if (mFocusedWidget != NULL) 00383 { 00384 if (!mFocusedWidget->isTabOutEnabled()) 00385 { 00386 return; 00387 } 00388 } 00389 00390 if (mWidgets.size() == 0) 00391 { 00392 mFocusedWidget = NULL; 00393 return; 00394 } 00395 00396 int i; 00397 int focusedWidget = -1; 00398 for (i = 0; i < (int)mWidgets.size(); ++i) 00399 { 00400 if (mWidgets[i] == mFocusedWidget) 00401 { 00402 focusedWidget = i; 00403 } 00404 } 00405 int focused = focusedWidget; 00406 bool done = false; 00407 00408 // i is a counter that ensures that the following loop 00409 // won't get stuck in an infinite loop 00410 i = (int)mWidgets.size(); 00411 do 00412 { 00413 --focusedWidget; 00414 00415 if (i==0) 00416 { 00417 focusedWidget = -1; 00418 break; 00419 } 00420 00421 --i; 00422 00423 if (focusedWidget <= 0) 00424 { 00425 focusedWidget = mWidgets.size() - 1; 00426 } 00427 00428 if (focusedWidget == focused) 00429 { 00430 return; 00431 } 00432 00433 if (mWidgets.at(focusedWidget)->isFocusable() && 00434 mWidgets.at(focusedWidget)->isTabInEnabled() && 00435 (mModalFocusedWidget == NULL || 00436 mWidgets.at(focusedWidget)->hasModalFocus())) 00437 { 00438 done = true; 00439 } 00440 } 00441 while (!done); 00442 00443 if (focusedWidget >= 0) 00444 { 00445 mFocusedWidget = mWidgets.at(focusedWidget); 00446 mWidgets.at(focusedWidget)->gotFocus(); 00447 } 00448 00449 if (focused >= 0) 00450 { 00451 mWidgets.at(focused)->lostFocus(); 00452 } 00453 } 00454 00455 void FocusHandler::applyChanges() 00456 { 00457 if (mToBeFocused != NULL) 00458 { 00459 unsigned int i = 0; 00460 int toBeFocusedIndex = -1; 00461 for (i = 0; i < mWidgets.size(); ++i) 00462 { 00463 if (mWidgets[i] == mToBeFocused) 00464 { 00465 toBeFocusedIndex = i; 00466 break; 00467 } 00468 } 00469 00470 if (toBeFocusedIndex < 0) 00471 { 00472 throw GCN_EXCEPTION("Trying to focus a none existing widget."); 00473 } 00474 00475 Widget *oldFocused = mFocusedWidget; 00476 00477 if (oldFocused != mToBeFocused) 00478 { 00479 mFocusedWidget = mWidgets.at(toBeFocusedIndex); 00480 00481 if (oldFocused != NULL) 00482 { 00483 oldFocused->lostFocus(); 00484 } 00485 00486 mWidgets.at(toBeFocusedIndex)->gotFocus(); 00487 } 00488 mToBeFocused = NULL; 00489 } 00490 00491 if (mToBeDragged != NULL) 00492 { 00493 unsigned int i = 0; 00494 int toBeDraggedIndex = -1; 00495 for (i = 0; i < mWidgets.size(); ++i) 00496 { 00497 if (mWidgets[i] == mToBeDragged) 00498 { 00499 toBeDraggedIndex = i; 00500 break; 00501 } 00502 } 00503 00504 if (toBeDraggedIndex < 0) 00505 { 00506 throw GCN_EXCEPTION("Trying to give drag to a none existing widget"); 00507 } 00508 00509 mDraggedWidget = mWidgets.at(toBeDraggedIndex); 00510 mToBeDragged = NULL; 00511 } 00512 } 00513 }