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