00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include "guichan/basiccontainer.hpp"
00062
00063 #include <algorithm>
00064
00065 #include "guichan/exception.hpp"
00066 #include "guichan/focushandler.hpp"
00067 #include "guichan/graphics.hpp"
00068 #include "guichan/mouseinput.hpp"
00069
00070 namespace gcn
00071 {
00072 BasicContainer::BasicContainer()
00073 {
00074 mWidgetWithMouse = NULL;
00075 mMouseInputPolicy = NOT_ON_CHILD;
00076 mInternalFocusHandler = NULL;
00077 }
00078
00079 BasicContainer::~BasicContainer()
00080 {
00081 clear();
00082 }
00083
00084 void BasicContainer::moveToTop(Widget* widget)
00085 {
00086 WidgetListIterator iter;
00087 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
00088 {
00089 if (*iter == widget)
00090 {
00091 mWidgets.erase(iter);
00092 mWidgets.push_back(widget);
00093 return;
00094 }
00095 }
00096
00097 throw GCN_EXCEPTION("There is no such widget in this container.");
00098 }
00099
00100 void BasicContainer::moveToBottom(Widget* widget)
00101 {
00102 WidgetListIterator iter;
00103 iter = find(mWidgets.begin(), mWidgets.end(), widget);
00104
00105 if (iter == mWidgets.end())
00106 {
00107 throw GCN_EXCEPTION("There is no such widget in this container.");
00108 }
00109 mWidgets.erase(iter);
00110 mWidgets.push_front(widget);
00111 }
00112
00113 void BasicContainer::_announceDeath(Widget *widget)
00114 {
00115 if (mWidgetWithMouse == widget)
00116 {
00117 mWidgetWithMouse = NULL;
00118 }
00119
00120 WidgetListIterator iter;
00121 iter = find(mWidgets.begin(), mWidgets.end(), widget);
00122
00123 if (iter == mWidgets.end())
00124 {
00125 throw GCN_EXCEPTION("There is no such widget in this container.");
00126 }
00127
00128 mWidgets.erase(iter);
00129 }
00130
00131 Rectangle BasicContainer::getChildrenArea()
00132 {
00133 return Rectangle(0, 0, getWidth(), getHeight());
00134 }
00135
00136 void BasicContainer::focusNext()
00137 {
00138 WidgetListIterator it;
00139
00140 for (it = mWidgets.begin(); it != mWidgets.end(); it++)
00141 {
00142 if ((*it)->isFocused())
00143 {
00144 break;
00145 }
00146 }
00147
00148 WidgetListIterator end = it;
00149
00150 if (it == mWidgets.end())
00151 {
00152 it = mWidgets.begin();
00153 }
00154
00155 it++;
00156
00157 for ( ; it != end; it++)
00158 {
00159 if (it == mWidgets.end())
00160 {
00161 it = mWidgets.begin();
00162 }
00163
00164 if ((*it)->isFocusable())
00165 {
00166 (*it)->requestFocus();
00167 return;
00168 }
00169 }
00170 }
00171
00172 void BasicContainer::focusPrevious()
00173 {
00174 WidgetListReverseIterator it;
00175
00176 for (it = mWidgets.rbegin(); it != mWidgets.rend(); it++)
00177 {
00178 if ((*it)->isFocused())
00179 {
00180 break;
00181 }
00182 }
00183
00184 WidgetListReverseIterator end = it;
00185
00186 it++;
00187
00188 if (it == mWidgets.rend())
00189 {
00190 it = mWidgets.rbegin();
00191 }
00192
00193 for ( ; it != end; it++)
00194 {
00195 if (it == mWidgets.rend())
00196 {
00197 it = mWidgets.rbegin();
00198 }
00199
00200 if ((*it)->isFocusable())
00201 {
00202 (*it)->requestFocus();
00203 return;
00204 }
00205 }
00206 }
00207
00208 Widget *BasicContainer::getWidgetAt(int x, int y)
00209 {
00210 Rectangle r = getChildrenArea();
00211
00212 if (!r.isPointInRect(x, y))
00213 {
00214 return NULL;
00215 }
00216
00217 x -= r.x;
00218 y -= r.y;
00219
00220 WidgetListReverseIterator it;
00221 for (it = mWidgets.rbegin(); it != mWidgets.rend(); it++)
00222 {
00223 if ((*it)->isVisible() && (*it)->getDimension().isPointInRect(x, y))
00224 {
00225 return (*it);
00226 }
00227 }
00228
00229 return NULL;
00230 }
00231
00232 void BasicContainer::logic()
00233 {
00234 logicChildren();
00235 }
00236
00237 void BasicContainer::_setFocusHandler(FocusHandler* focusHandler)
00238 {
00239 Widget::_setFocusHandler(focusHandler);
00240
00241 if (mInternalFocusHandler != NULL)
00242 {
00243 return;
00244 }
00245
00246
00247 WidgetListIterator iter;
00248 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
00249 {
00250 (*iter)->_setFocusHandler(focusHandler);
00251 }
00252 }
00253
00254 void BasicContainer::_mouseInputMessage(const MouseInput& mouseInput)
00255 {
00256 Widget *newWidgetWithMouse;
00257
00258 newWidgetWithMouse = getWidgetAt(mouseInput.x, mouseInput.y);
00259
00260 if (newWidgetWithMouse != mWidgetWithMouse)
00261 {
00262 if (mWidgetWithMouse != NULL)
00263 {
00264 mWidgetWithMouse->_mouseOutMessage();
00265 }
00266
00267 if (newWidgetWithMouse != NULL)
00268 {
00269 newWidgetWithMouse->_mouseInMessage();
00270 }
00271
00272 mWidgetWithMouse = newWidgetWithMouse;
00273 }
00274
00275 if (mWidgetWithMouse != NULL)
00276 {
00277 MouseInput mi = mouseInput;
00278 Rectangle ca = getChildrenArea();
00279 mi.x -= mWidgetWithMouse->getX() + ca.x;
00280 mi.y -= mWidgetWithMouse->getY() + ca.y;
00281
00282
00283 if (mi.x < 0)
00284 {
00285 mi.x = 0;
00286 }
00287
00288 if (mi.y < 0)
00289 {
00290 mi.y = 0;
00291 }
00292
00293 if (mi.x >= mWidgetWithMouse->getWidth())
00294 {
00295 mi.x = mWidgetWithMouse->getWidth() - 1;
00296 }
00297
00298 if (mi.y >= mWidgetWithMouse->getHeight())
00299 {
00300 mi.y = mWidgetWithMouse->getHeight() - 1;
00301 }
00302
00303 mWidgetWithMouse->_mouseInputMessage(mi);
00304 }
00305
00306 if (mInternalFocusHandler != NULL)
00307 {
00308 Widget *f = mInternalFocusHandler->getFocused();
00309 Widget *d = mInternalFocusHandler->getDragged();
00310
00311 if (f != NULL && !f->hasMouse() && isFocused())
00312 {
00313 MouseInput mi = mouseInput;
00314 Rectangle ca = getChildrenArea();
00315 mi.x -= f->getX() + ca.x;
00316 mi.y -= f->getY() + ca.y;
00317
00318 f->_mouseInputMessage(mi);
00319 }
00320
00321 if (d != NULL && f != d && !d->hasMouse() && isDragged())
00322 {
00323 MouseInput mi = mouseInput;
00324 Rectangle ca = getChildrenArea();
00325 mi.x -= d->getX() + ca.x;
00326 mi.y -= d->getY() + ca.y;
00327
00328 d->_mouseInputMessage(mi);
00329 }
00330 }
00331
00332 bool toContainer = isDragged();
00333
00334 switch (mMouseInputPolicy)
00335 {
00336 case NEVER:
00337 break;
00338 case ALWAYS:
00339 toContainer = true;
00340 break;
00341 case NOT_ON_CHILD:
00342 if (mWidgetWithMouse == NULL)
00343 {
00344 toContainer = true;
00345 }
00346 break;
00347 case NOT_IN_CHILDREN_AREA:
00348 if (!getChildrenArea().isPointInRect(mouseInput.x, mouseInput.y))
00349 {
00350 toContainer = true;
00351 }
00352 default:
00353 throw GCN_EXCEPTION("Unknown mouse input policy");
00354 }
00355
00356 if (toContainer)
00357 {
00358 Widget::_mouseInputMessage(mouseInput);
00359 }
00360 }
00361
00362 void BasicContainer::_mouseOutMessage()
00363 {
00364 if (mWidgetWithMouse != NULL)
00365 {
00366 mWidgetWithMouse->_mouseOutMessage();
00367 mWidgetWithMouse = NULL;
00368 }
00369
00370 Widget::_mouseOutMessage();
00371 }
00372
00373 void BasicContainer::add(Widget* widget)
00374 {
00375 mWidgets.push_back(widget);
00377
00378 if (mInternalFocusHandler == NULL)
00379 {
00380 widget->_setFocusHandler(_getFocusHandler());
00381 }
00382 else
00383 {
00384 widget->_setFocusHandler(mInternalFocusHandler);
00385 }
00386
00387 widget->_setParent(this);
00388 }
00389
00390 void BasicContainer::remove(Widget* widget)
00391 {
00392 if (widget == mWidgetWithMouse)
00393 {
00394 mWidgetWithMouse = NULL;
00395 }
00396
00397 WidgetListIterator iter;
00398 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
00399 {
00400 if (*iter == widget)
00401 {
00402 mWidgets.erase(iter);
00403 widget->_setFocusHandler(NULL);
00404 widget->_setParent(NULL);
00405 return;
00406 }
00407 }
00408
00409 throw GCN_EXCEPTION("There is no such widget in this container.");
00410 }
00411
00412 void BasicContainer::clear()
00413 {
00414 mWidgetWithMouse = NULL;
00415
00416 WidgetListIterator iter;
00417
00418 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
00419 {
00420 (*iter)->_setFocusHandler(NULL);
00421 (*iter)->_setParent(NULL);
00422 }
00423
00424 mWidgets.clear();
00425 }
00426
00427 void BasicContainer::drawChildren(Graphics* graphics)
00428 {
00429 graphics->pushClipArea(getChildrenArea());
00430
00431 WidgetListIterator iter;
00432 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
00433 {
00434 if ((*iter)->isVisible())
00435 {
00436
00437
00438 if ((*iter)->getBorderSize() > 0)
00439 {
00440 Rectangle rec = (*iter)->getDimension();
00441 rec.x -= (*iter)->getBorderSize();
00442 rec.y -= (*iter)->getBorderSize();
00443 rec.width += 2 * (*iter)->getBorderSize();
00444 rec.height += 2 * (*iter)->getBorderSize();
00445 graphics->pushClipArea(rec);
00446 (*iter)->drawBorder(graphics);
00447 graphics->popClipArea();
00448 }
00449
00450 graphics->pushClipArea((*iter)->getDimension());
00451 (*iter)->draw(graphics);
00452 graphics->popClipArea();
00453 }
00454 }
00455
00456 graphics->popClipArea();
00457 }
00458
00459 void BasicContainer::logicChildren()
00460 {
00461 WidgetListIterator iter;
00462 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
00463 {
00464 (*iter)->logic();
00465 }
00466 }
00467
00468 void BasicContainer::setMouseInputPolicy(unsigned int policy)
00469 {
00470 mMouseInputPolicy = policy;
00471 }
00472
00473 unsigned int BasicContainer::getMouseInputPolicy()
00474 {
00475 return mMouseInputPolicy;
00476 }
00477
00478 void BasicContainer::showWidgetPart(Widget* widget, Rectangle area)
00479 {
00480 Rectangle widgetArea = getChildrenArea();
00481 area.x += widget->getX();
00482 area.y += widget->getY();
00483
00484 if (area.x + area.width > widgetArea.width)
00485 {
00486 widget->setX(widget->getX() - area.x - area.width + widgetArea.width);
00487 }
00488
00489 if (area.y + area.height > widgetArea.height)
00490 {
00491 widget->setY(widget->getY() - area.y - area.height + widgetArea.height);
00492 }
00493
00494 if (area.x < 0)
00495 {
00496 widget->setX(widget->getX() - area.x);
00497 }
00498
00499 if (area.y < 0)
00500 {
00501 widget->setY(widget->getY() - area.y);
00502 }
00503 }
00504
00505 FocusHandler* BasicContainer::getInternalFocusHandler()
00506 {
00507 return mFocusHandler;
00508 }
00509
00510 void BasicContainer::setInternalFocusHandler(FocusHandler* focusHandler)
00511 {
00512 mInternalFocusHandler = focusHandler;
00513
00514 WidgetListIterator iter;
00515 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
00516 {
00517 if (mInternalFocusHandler == NULL)
00518 {
00519 (*iter)->_setFocusHandler(_getFocusHandler());
00520 }
00521 else
00522 {
00523 (*iter)->_setFocusHandler(mInternalFocusHandler);
00524 }
00525 }
00526 }
00527
00528 void BasicContainer::_keyInputMessage(const KeyInput& keyInput)
00529 {
00530 if (mInternalFocusHandler != NULL && mInternalFocusHandler->getFocused() != NULL)
00531 {
00532 mInternalFocusHandler->getFocused()->_keyInputMessage(keyInput);
00533 }
00534 else
00535 {
00536 Widget::_keyInputMessage(keyInput);
00537 }
00538 }
00539 }