00001 /* _______ __ __ __ ______ __ __ _______ __ __ 00002 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 00003 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 00004 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 00005 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 00006 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 00007 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 00008 * 00009 * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson 00010 * 00011 * 00012 * Per Larsson a.k.a finalman 00013 * Olof Naessén a.k.a jansem/yakslem 00014 * 00015 * Visit: http://guichan.sourceforge.net 00016 * 00017 * License: (BSD) 00018 * Redistribution and use in source and binary forms, with or without 00019 * modification, are permitted provided that the following conditions 00020 * are met: 00021 * 1. Redistributions of source code must retain the above copyright 00022 * notice, this list of conditions and the following disclaimer. 00023 * 2. Redistributions in binary form must reproduce the above copyright 00024 * notice, this list of conditions and the following disclaimer in 00025 * the documentation and/or other materials provided with the 00026 * distribution. 00027 * 3. Neither the name of Guichan nor the names of its contributors may 00028 * be used to endorse or promote products derived from this software 00029 * without specific prior written permission. 00030 * 00031 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00032 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00033 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00034 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00035 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00036 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00037 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00038 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00039 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00040 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00041 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00042 */ 00043 00044 /* 00045 * For comments regarding functions please see the header file. 00046 */ 00047 00048 #include "guichan/focushandler.hpp" 00049 00050 #include "guichan/focuslistener.hpp" 00051 #include "guichan/exception.hpp" 00052 #include "guichan/widget.hpp" 00053 00054 namespace gcn 00055 { 00056 FocusHandler::FocusHandler() 00057 :mFocusedWidget(NULL), 00058 mModalFocusedWidget(NULL), 00059 mModalMouseInputFocusedWidget(NULL), 00060 mDraggedWidget(NULL), 00061 mLastWidgetWithMouse(NULL), 00062 mLastWidgetWithModalFocus(NULL), 00063 mLastWidgetWithModalMouseInputFocus(NULL), 00064 mLastWidgetPressed(NULL) 00065 { 00066 00067 } 00068 00069 void FocusHandler::requestFocus(Widget* widget) 00070 { 00071 if (widget == NULL 00072 || widget == mFocusedWidget) 00073 { 00074 return; 00075 } 00076 00077 unsigned int i = 0; 00078 int toBeFocusedIndex = -1; 00079 for (i = 0; i < mWidgets.size(); ++i) 00080 { 00081 if (mWidgets[i] == widget) 00082 { 00083 toBeFocusedIndex = i; 00084 break; 00085 } 00086 } 00087 00088 if (toBeFocusedIndex < 0) 00089 { 00090 throw GCN_EXCEPTION("Trying to focus a none existing widget."); 00091 } 00092 00093 Widget *oldFocused = mFocusedWidget; 00094 00095 if (oldFocused != widget) 00096 { 00097 mFocusedWidget = mWidgets.at(toBeFocusedIndex); 00098 00099 if (oldFocused != NULL) 00100 { 00101 Event focusEvent(oldFocused); 00102 distributeFocusLostEvent(focusEvent); 00103 } 00104 00105 Event focusEvent(mWidgets.at(toBeFocusedIndex)); 00106 distributeFocusGainedEvent(focusEvent); 00107 } 00108 } 00109 00110 void FocusHandler::requestModalFocus(Widget* widget) 00111 { 00112 if (mModalFocusedWidget != NULL && mModalFocusedWidget != widget) 00113 { 00114 throw GCN_EXCEPTION("Another widget already has modal focus."); 00115 } 00116 00117 mModalFocusedWidget = widget; 00118 00119 if (mFocusedWidget != NULL 00120 && !mFocusedWidget->isModalFocused()) 00121 { 00122 focusNone(); 00123 } 00124 } 00125 00126 void FocusHandler::requestModalMouseInputFocus(Widget* widget) 00127 { 00128 if (mModalMouseInputFocusedWidget != NULL 00129 && mModalMouseInputFocusedWidget != widget) 00130 { 00131 throw GCN_EXCEPTION("Another widget already has modal input focus."); 00132 } 00133 00134 mModalMouseInputFocusedWidget = widget; 00135 } 00136 00137 void FocusHandler::releaseModalFocus(Widget* widget) 00138 { 00139 if (mModalFocusedWidget == widget) 00140 { 00141 mModalFocusedWidget = NULL; 00142 } 00143 } 00144 00145 void FocusHandler::releaseModalMouseInputFocus(Widget* widget) 00146 { 00147 if (mModalMouseInputFocusedWidget == widget) 00148 { 00149 mModalMouseInputFocusedWidget = NULL; 00150 } 00151 } 00152 00153 Widget* FocusHandler::getFocused() const 00154 { 00155 return mFocusedWidget; 00156 } 00157 00158 Widget* FocusHandler::getModalFocused() const 00159 { 00160 return mModalFocusedWidget; 00161 } 00162 00163 Widget* FocusHandler::getModalMouseInputFocused() const 00164 { 00165 return mModalMouseInputFocusedWidget; 00166 } 00167 00168 void FocusHandler::focusNext() 00169 { 00170 int i; 00171 int focusedWidget = -1; 00172 for (i = 0; i < (int)mWidgets.size(); ++i) 00173 { 00174 if (mWidgets[i] == mFocusedWidget) 00175 { 00176 focusedWidget = i; 00177 } 00178 } 00179 int focused = focusedWidget; 00180 00181 // i is a counter that ensures that the following loop 00182 // won't get stuck in an infinite loop 00183 i = (int)mWidgets.size(); 00184 do 00185 { 00186 ++focusedWidget; 00187 00188 if (i==0) 00189 { 00190 focusedWidget = -1; 00191 break; 00192 } 00193 00194 --i; 00195 00196 if (focusedWidget >= (int)mWidgets.size()) 00197 { 00198 focusedWidget = 0; 00199 } 00200 00201 if (focusedWidget == focused) 00202 { 00203 return; 00204 } 00205 } 00206 while (!mWidgets.at(focusedWidget)->isFocusable()); 00207 00208 if (focusedWidget >= 0) 00209 { 00210 mFocusedWidget = mWidgets.at(focusedWidget); 00211 00212 Event focusEvent(mFocusedWidget); 00213 distributeFocusGainedEvent(focusEvent); 00214 } 00215 00216 if (focused >= 0) 00217 { 00218 Event focusEvent(mWidgets.at(focused)); 00219 distributeFocusLostEvent(focusEvent); 00220 } 00221 } 00222 00223 void FocusHandler::focusPrevious() 00224 { 00225 if (mWidgets.size() == 0) 00226 { 00227 mFocusedWidget = NULL; 00228 return; 00229 } 00230 00231 int i; 00232 int focusedWidget = -1; 00233 for (i = 0; i < (int)mWidgets.size(); ++i) 00234 { 00235 if (mWidgets[i] == mFocusedWidget) 00236 { 00237 focusedWidget = i; 00238 } 00239 } 00240 int focused = focusedWidget; 00241 00242 // i is a counter that ensures that the following loop 00243 // won't get stuck in an infinite loop 00244 i = (int)mWidgets.size(); 00245 do 00246 { 00247 --focusedWidget; 00248 00249 if (i==0) 00250 { 00251 focusedWidget = -1; 00252 break; 00253 } 00254 00255 --i; 00256 00257 if (focusedWidget <= 0) 00258 { 00259 focusedWidget = mWidgets.size() - 1; 00260 } 00261 00262 if (focusedWidget == focused) 00263 { 00264 return; 00265 } 00266 } 00267 while (!mWidgets.at(focusedWidget)->isFocusable()); 00268 00269 if (focusedWidget >= 0) 00270 { 00271 mFocusedWidget = mWidgets.at(focusedWidget); 00272 Event focusEvent(mFocusedWidget); 00273 distributeFocusGainedEvent(focusEvent); 00274 } 00275 00276 if (focused >= 0) 00277 { 00278 Event focusEvent(mWidgets.at(focused)); 00279 distributeFocusLostEvent(focusEvent); 00280 } 00281 } 00282 00283 bool FocusHandler::isFocused(const Widget* widget) const 00284 { 00285 return mFocusedWidget == widget; 00286 } 00287 00288 void FocusHandler::add(Widget* widget) 00289 { 00290 mWidgets.push_back(widget); 00291 } 00292 00293 void FocusHandler::remove(Widget* widget) 00294 { 00295 if (isFocused(widget)) 00296 { 00297 mFocusedWidget = NULL; 00298 } 00299 00300 WidgetIterator iter; 00301 00302 for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter) 00303 { 00304 if ((*iter) == widget) 00305 { 00306 mWidgets.erase(iter); 00307 break; 00308 } 00309 } 00310 00311 if (mDraggedWidget == widget) 00312 { 00313 mDraggedWidget = NULL; 00314 return; 00315 } 00316 00317 if (mLastWidgetWithMouse == widget) 00318 { 00319 mLastWidgetWithMouse = NULL; 00320 return; 00321 } 00322 00323 if (mLastWidgetWithModalFocus == widget) 00324 { 00325 mLastWidgetWithModalFocus = NULL; 00326 return; 00327 } 00328 00329 if (mLastWidgetWithModalMouseInputFocus == widget) 00330 { 00331 mLastWidgetWithModalMouseInputFocus = NULL; 00332 return; 00333 } 00334 00335 if (mLastWidgetPressed == widget) 00336 { 00337 mLastWidgetPressed = NULL; 00338 return; 00339 } 00340 } 00341 00342 void FocusHandler::focusNone() 00343 { 00344 if (mFocusedWidget != NULL) 00345 { 00346 Widget* focused = mFocusedWidget; 00347 mFocusedWidget = NULL; 00348 00349 Event focusEvent(focused); 00350 distributeFocusLostEvent(focusEvent); 00351 } 00352 } 00353 00354 void FocusHandler::tabNext() 00355 { 00356 if (mFocusedWidget != NULL) 00357 { 00358 if (!mFocusedWidget->isTabOutEnabled()) 00359 { 00360 return; 00361 } 00362 } 00363 00364 if (mWidgets.size() == 0) 00365 { 00366 mFocusedWidget = NULL; 00367 return; 00368 } 00369 00370 int i; 00371 int focusedWidget = -1; 00372 for (i = 0; i < (int)mWidgets.size(); ++i) 00373 { 00374 if (mWidgets[i] == mFocusedWidget) 00375 { 00376 focusedWidget = i; 00377 } 00378 } 00379 int focused = focusedWidget; 00380 bool done = false; 00381 00382 // i is a counter that ensures that the following loop 00383 // won't get stuck in an infinite loop 00384 i = (int)mWidgets.size(); 00385 do 00386 { 00387 ++focusedWidget; 00388 00389 if (i==0) 00390 { 00391 focusedWidget = -1; 00392 break; 00393 } 00394 00395 --i; 00396 00397 if (focusedWidget >= (int)mWidgets.size()) 00398 { 00399 focusedWidget = 0; 00400 } 00401 00402 if (focusedWidget == focused) 00403 { 00404 return; 00405 } 00406 00407 if (mWidgets.at(focusedWidget)->isFocusable() && 00408 mWidgets.at(focusedWidget)->isTabInEnabled() && 00409 (mModalFocusedWidget == NULL || 00410 mWidgets.at(focusedWidget)->isModalFocused())) 00411 { 00412 done = true; 00413 } 00414 } 00415 while (!done); 00416 00417 if (focusedWidget >= 0) 00418 { 00419 mFocusedWidget = mWidgets.at(focusedWidget); 00420 Event focusEvent(mFocusedWidget); 00421 distributeFocusGainedEvent(focusEvent); 00422 } 00423 00424 if (focused >= 0) 00425 { 00426 Event focusEvent(mWidgets.at(focused)); 00427 distributeFocusLostEvent(focusEvent); 00428 } 00429 } 00430 00431 void FocusHandler::tabPrevious() 00432 { 00433 if (mFocusedWidget != NULL) 00434 { 00435 if (!mFocusedWidget->isTabOutEnabled()) 00436 { 00437 return; 00438 } 00439 } 00440 00441 if (mWidgets.size() == 0) 00442 { 00443 mFocusedWidget = NULL; 00444 return; 00445 } 00446 00447 int i; 00448 int focusedWidget = -1; 00449 for (i = 0; i < (int)mWidgets.size(); ++i) 00450 { 00451 if (mWidgets[i] == mFocusedWidget) 00452 { 00453 focusedWidget = i; 00454 } 00455 } 00456 int focused = focusedWidget; 00457 bool done = false; 00458 00459 // i is a counter that ensures that the following loop 00460 // won't get stuck in an infinite loop 00461 i = (int)mWidgets.size(); 00462 do 00463 { 00464 --focusedWidget; 00465 00466 if (i==0) 00467 { 00468 focusedWidget = -1; 00469 break; 00470 } 00471 00472 --i; 00473 00474 if (focusedWidget <= 0) 00475 { 00476 focusedWidget = mWidgets.size() - 1; 00477 } 00478 00479 if (focusedWidget == focused) 00480 { 00481 return; 00482 } 00483 00484 if (mWidgets.at(focusedWidget)->isFocusable() && 00485 mWidgets.at(focusedWidget)->isTabInEnabled() && 00486 (mModalFocusedWidget == NULL || 00487 mWidgets.at(focusedWidget)->isModalFocused())) 00488 { 00489 done = true; 00490 } 00491 } 00492 while (!done); 00493 00494 if (focusedWidget >= 0) 00495 { 00496 mFocusedWidget = mWidgets.at(focusedWidget); 00497 Event focusEvent(mFocusedWidget); 00498 distributeFocusGainedEvent(focusEvent); 00499 } 00500 00501 if (focused >= 0) 00502 { 00503 Event focusEvent(mWidgets.at(focused)); 00504 distributeFocusLostEvent(focusEvent); 00505 } 00506 } 00507 00508 void FocusHandler::distributeFocusLostEvent(const Event& focusEvent) 00509 { 00510 Widget* sourceWidget = focusEvent.getSource(); 00511 00512 std::list<FocusListener*> focusListeners = sourceWidget->_getFocusListeners(); 00513 00514 // Send the event to all focus listeners of the widget. 00515 for (std::list<FocusListener*>::iterator it = focusListeners.begin(); 00516 it != focusListeners.end(); 00517 ++it) 00518 { 00519 (*it)->focusLost(focusEvent); 00520 } 00521 } 00522 00523 void FocusHandler::distributeFocusGainedEvent(const Event& focusEvent) 00524 { 00525 Widget* sourceWidget = focusEvent.getSource(); 00526 00527 std::list<FocusListener*> focusListeners = sourceWidget->_getFocusListeners(); 00528 00529 // Send the event to all focus listeners of the widget. 00530 for (std::list<FocusListener*>::iterator it = focusListeners.begin(); 00531 it != focusListeners.end(); 00532 ++it) 00533 { 00534 (*it)->focusGained(focusEvent); 00535 } 00536 } 00537 00538 Widget* FocusHandler::getDraggedWidget() 00539 { 00540 return mDraggedWidget; 00541 } 00542 00543 void FocusHandler::setDraggedWidget(Widget* draggedWidget) 00544 { 00545 mDraggedWidget = draggedWidget; 00546 } 00547 00548 Widget* FocusHandler::getLastWidgetWithMouse() 00549 { 00550 return mLastWidgetWithMouse; 00551 } 00552 00553 void FocusHandler::setLastWidgetWithMouse(Widget* lastWidgetWithMouse) 00554 { 00555 mLastWidgetWithMouse = lastWidgetWithMouse; 00556 } 00557 00558 Widget* FocusHandler::getLastWidgetWithModalFocus() 00559 { 00560 return mLastWidgetWithModalFocus; 00561 } 00562 00563 void FocusHandler::setLastWidgetWithModalFocus(Widget* lastWidgetWithModalFocus) 00564 { 00565 mLastWidgetWithModalFocus = lastWidgetWithModalFocus; 00566 } 00567 00568 Widget* FocusHandler::getLastWidgetWithModalMouseInputFocus() 00569 { 00570 return mLastWidgetWithModalMouseInputFocus; 00571 } 00572 00573 void FocusHandler::setLastWidgetWithModalMouseInputFocus(Widget* lastWidgetWithModalMouseInputFocus) 00574 { 00575 mLastWidgetWithModalMouseInputFocus = lastWidgetWithModalMouseInputFocus; 00576 } 00577 00578 Widget* FocusHandler::getLastWidgetPressed() 00579 { 00580 return mLastWidgetPressed; 00581 } 00582 00583 void FocusHandler::setLastWidgetPressed(Widget* lastWidgetPressed) 00584 { 00585 mLastWidgetPressed = lastWidgetPressed; 00586 } 00587 }