1 /* _______ __ __ __ ______ __ __ _______ __ __ 2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 8 * 9 * Copyright (c) 2004 - 2008 Olof Naess�n and Per Larsson 10 * 11 * 12 * Per Larsson a.k.a finalman 13 * Olof Naess�n a.k.a jansem/yakslem 14 * 15 * Visit: http://guichan.sourceforge.net 16 * 17 * License: (BSD) 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in 25 * the documentation and/or other materials provided with the 26 * distribution. 27 * 3. Neither the name of Guichan nor the names of its contributors may 28 * be used to endorse or promote products derived from this software 29 * without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 37 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 38 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 39 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 40 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 /* 45 * For comments regarding functions please see the header file. 46 */ 47 48 #include "guichan/widget.hpp" 49 50 #include "guichan/actionevent.hpp" 51 #include "guichan/actionlistener.hpp" 52 #include "guichan/basiccontainer.hpp" 53 #include "guichan/deathlistener.hpp" 54 #include "guichan/defaultfont.hpp" 55 #include "guichan/event.hpp" 56 #include "guichan/exception.hpp" 57 #include "guichan/focushandler.hpp" 58 #include "guichan/graphics.hpp" 59 #include "guichan/keyinput.hpp" 60 #include "guichan/keylistener.hpp" 61 #include "guichan/mouseinput.hpp" 62 #include "guichan/mouselistener.hpp" 63 #include "guichan/widgetlistener.hpp" 64 65 namespace gcn 66 { 67 Font* Widget::mGlobalFont = NULL; 68 DefaultFont Widget::mDefaultFont; 69 std::list<Widget*> Widget::mWidgets; 70 Widget()71 Widget::Widget() 72 : mForegroundColor(0x000000), 73 mBackgroundColor(0xffffff), 74 mBaseColor(0x808090), 75 mSelectionColor(0xc3d9ff), 76 mFocusHandler(NULL), 77 mInternalFocusHandler(NULL), 78 mParent(NULL), 79 mFrameSize(0), 80 mFocusable(false), 81 mVisible(true), 82 mTabIn(true), 83 mTabOut(true), 84 mEnabled(true), 85 mCurrentFont(NULL) 86 { 87 mWidgets.push_back(this); 88 } 89 ~Widget()90 Widget::~Widget() 91 { 92 DeathListenerIterator iter; 93 94 for (iter = mDeathListeners.begin(); iter != mDeathListeners.end(); ++iter) 95 { 96 Event event(this); 97 (*iter)->death(event); 98 } 99 100 _setFocusHandler(NULL); 101 102 mWidgets.remove(this); 103 } 104 drawFrame(Graphics * graphics)105 void Widget::drawFrame(Graphics* graphics) 106 { 107 Color faceColor = getBaseColor(); 108 Color highlightColor, shadowColor; 109 int alpha = getBaseColor().a; 110 int width = getWidth() + getFrameSize() * 2 - 1; 111 int height = getHeight() + getFrameSize() * 2 - 1; 112 highlightColor = faceColor + 0x303030; 113 highlightColor.a = alpha; 114 shadowColor = faceColor - 0x303030; 115 shadowColor.a = alpha; 116 117 unsigned int i; 118 for (i = 0; i < getFrameSize(); ++i) 119 { 120 graphics->setColor(shadowColor); 121 graphics->drawLine(i,i, width - i, i); 122 graphics->drawLine(i,i + 1, i, height - i - 1); 123 graphics->setColor(highlightColor); 124 graphics->drawLine(width - i,i + 1, width - i, height - i); 125 graphics->drawLine(i,height - i, width - i - 1, height - i); 126 } 127 } 128 _setParent(Widget * parent)129 void Widget::_setParent(Widget* parent) 130 { 131 mParent = parent; 132 } 133 getParent() const134 Widget* Widget::getParent() const 135 { 136 return mParent; 137 } 138 setWidth(int width)139 void Widget::setWidth(int width) 140 { 141 Rectangle newDimension = mDimension; 142 newDimension.width = width; 143 144 setDimension(newDimension); 145 } 146 getWidth() const147 int Widget::getWidth() const 148 { 149 return mDimension.width; 150 } 151 setHeight(int height)152 void Widget::setHeight(int height) 153 { 154 Rectangle newDimension = mDimension; 155 newDimension.height = height; 156 157 setDimension(newDimension); 158 } 159 getHeight() const160 int Widget::getHeight() const 161 { 162 return mDimension.height; 163 } 164 setX(int x)165 void Widget::setX(int x) 166 { 167 Rectangle newDimension = mDimension; 168 newDimension.x = x; 169 170 setDimension(newDimension); 171 } 172 getX() const173 int Widget::getX() const 174 { 175 return mDimension.x; 176 } 177 setY(int y)178 void Widget::setY(int y) 179 { 180 Rectangle newDimension = mDimension; 181 newDimension.y = y; 182 183 setDimension(newDimension); 184 } 185 getY() const186 int Widget::getY() const 187 { 188 return mDimension.y; 189 } 190 setPosition(int x,int y)191 void Widget::setPosition(int x, int y) 192 { 193 Rectangle newDimension = mDimension; 194 newDimension.x = x; 195 newDimension.y = y; 196 197 setDimension(newDimension); 198 } 199 setDimension(const Rectangle & dimension)200 void Widget::setDimension(const Rectangle& dimension) 201 { 202 Rectangle oldDimension = mDimension; 203 mDimension = dimension; 204 205 if (mDimension.width != oldDimension.width 206 || mDimension.height != oldDimension.height) 207 { 208 distributeResizedEvent(); 209 } 210 211 if (mDimension.x != oldDimension.x 212 || mDimension.y != oldDimension.y) 213 { 214 distributeMovedEvent(); 215 } 216 } 217 setFrameSize(unsigned int frameSize)218 void Widget::setFrameSize(unsigned int frameSize) 219 { 220 mFrameSize = frameSize; 221 } 222 getFrameSize() const223 unsigned int Widget::getFrameSize() const 224 { 225 return mFrameSize; 226 } 227 getDimension() const228 const Rectangle& Widget::getDimension() const 229 { 230 return mDimension; 231 } 232 getActionEventId() const233 const std::string& Widget::getActionEventId() const 234 { 235 return mActionEventId; 236 } 237 setActionEventId(const std::string & actionEventId)238 void Widget::setActionEventId(const std::string& actionEventId) 239 { 240 mActionEventId = actionEventId; 241 } 242 isFocused() const243 bool Widget::isFocused() const 244 { 245 if (!mFocusHandler) 246 { 247 return false; 248 } 249 250 return (mFocusHandler->isFocused(this)); 251 } 252 setFocusable(bool focusable)253 void Widget::setFocusable(bool focusable) 254 { 255 if (!focusable && isFocused()) 256 { 257 mFocusHandler->focusNone(); 258 } 259 260 mFocusable = focusable; 261 } 262 isFocusable() const263 bool Widget::isFocusable() const 264 { 265 return mFocusable && isVisible() && isEnabled(); 266 } 267 requestFocus()268 void Widget::requestFocus() 269 { 270 if (mFocusHandler == NULL) 271 { 272 throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?)."); 273 } 274 275 if (isFocusable()) 276 { 277 mFocusHandler->requestFocus(this); 278 } 279 } 280 requestMoveToTop()281 void Widget::requestMoveToTop() 282 { 283 if (mParent) 284 { 285 mParent->moveToTop(this); 286 } 287 } 288 requestMoveToBottom()289 void Widget::requestMoveToBottom() 290 { 291 if (mParent) 292 { 293 mParent->moveToBottom(this); 294 } 295 } 296 setVisible(bool visible)297 void Widget::setVisible(bool visible) 298 { 299 if (!visible && isFocused()) 300 { 301 mFocusHandler->focusNone(); 302 } 303 304 if (visible) 305 { 306 distributeShownEvent(); 307 } 308 else if(!visible) 309 { 310 distributeHiddenEvent(); 311 } 312 313 mVisible = visible; 314 } 315 isVisible() const316 bool Widget::isVisible() const 317 { 318 if (getParent() == NULL) 319 { 320 return mVisible; 321 } 322 else 323 { 324 return mVisible && getParent()->isVisible(); 325 } 326 } 327 setBaseColor(const Color & color)328 void Widget::setBaseColor(const Color& color) 329 { 330 mBaseColor = color; 331 } 332 getBaseColor() const333 const Color& Widget::getBaseColor() const 334 { 335 return mBaseColor; 336 } 337 setForegroundColor(const Color & color)338 void Widget::setForegroundColor(const Color& color) 339 { 340 mForegroundColor = color; 341 } 342 getForegroundColor() const343 const Color& Widget::getForegroundColor() const 344 { 345 return mForegroundColor; 346 } 347 setBackgroundColor(const Color & color)348 void Widget::setBackgroundColor(const Color& color) 349 { 350 mBackgroundColor = color; 351 } 352 getBackgroundColor() const353 const Color& Widget::getBackgroundColor() const 354 { 355 return mBackgroundColor; 356 } 357 setSelectionColor(const Color & color)358 void Widget::setSelectionColor(const Color& color) 359 { 360 mSelectionColor = color; 361 } 362 getSelectionColor() const363 const Color& Widget::getSelectionColor() const 364 { 365 return mSelectionColor; 366 } 367 _setFocusHandler(FocusHandler * focusHandler)368 void Widget::_setFocusHandler(FocusHandler* focusHandler) 369 { 370 if (mFocusHandler) 371 { 372 releaseModalFocus(); 373 mFocusHandler->remove(this); 374 } 375 376 if (focusHandler) 377 { 378 focusHandler->add(this); 379 } 380 381 mFocusHandler = focusHandler; 382 } 383 _getFocusHandler()384 FocusHandler* Widget::_getFocusHandler() 385 { 386 return mFocusHandler; 387 } 388 addActionListener(ActionListener * actionListener)389 void Widget::addActionListener(ActionListener* actionListener) 390 { 391 mActionListeners.push_back(actionListener); 392 } 393 removeActionListener(ActionListener * actionListener)394 void Widget::removeActionListener(ActionListener* actionListener) 395 { 396 mActionListeners.remove(actionListener); 397 } 398 addDeathListener(DeathListener * deathListener)399 void Widget::addDeathListener(DeathListener* deathListener) 400 { 401 mDeathListeners.push_back(deathListener); 402 } 403 removeDeathListener(DeathListener * deathListener)404 void Widget::removeDeathListener(DeathListener* deathListener) 405 { 406 mDeathListeners.remove(deathListener); 407 } 408 addKeyListener(KeyListener * keyListener)409 void Widget::addKeyListener(KeyListener* keyListener) 410 { 411 mKeyListeners.push_back(keyListener); 412 } 413 removeKeyListener(KeyListener * keyListener)414 void Widget::removeKeyListener(KeyListener* keyListener) 415 { 416 mKeyListeners.remove(keyListener); 417 } 418 addFocusListener(FocusListener * focusListener)419 void Widget::addFocusListener(FocusListener* focusListener) 420 { 421 mFocusListeners.push_back(focusListener); 422 } 423 removeFocusListener(FocusListener * focusListener)424 void Widget::removeFocusListener(FocusListener* focusListener) 425 { 426 mFocusListeners.remove(focusListener); 427 } 428 addMouseListener(MouseListener * mouseListener)429 void Widget::addMouseListener(MouseListener* mouseListener) 430 { 431 mMouseListeners.push_back(mouseListener); 432 } 433 removeMouseListener(MouseListener * mouseListener)434 void Widget::removeMouseListener(MouseListener* mouseListener) 435 { 436 mMouseListeners.remove(mouseListener); 437 } 438 addWidgetListener(WidgetListener * widgetListener)439 void Widget::addWidgetListener(WidgetListener* widgetListener) 440 { 441 mWidgetListeners.push_back(widgetListener); 442 } 443 removeWidgetListener(WidgetListener * widgetListener)444 void Widget::removeWidgetListener(WidgetListener* widgetListener) 445 { 446 mWidgetListeners.remove(widgetListener); 447 } 448 getAbsolutePosition(int & x,int & y) const449 void Widget::getAbsolutePosition(int& x, int& y) const 450 { 451 if (getParent() == NULL) 452 { 453 x = mDimension.x; 454 y = mDimension.y; 455 return; 456 } 457 458 int parentX; 459 int parentY; 460 461 getParent()->getAbsolutePosition(parentX, parentY); 462 463 x = parentX + mDimension.x + getParent()->getChildrenArea().x; 464 y = parentY + mDimension.y + getParent()->getChildrenArea().y; 465 } 466 getFont() const467 Font* Widget::getFont() const 468 { 469 if (mCurrentFont == NULL) 470 { 471 if (mGlobalFont == NULL) 472 { 473 return &mDefaultFont; 474 } 475 476 return mGlobalFont; 477 } 478 479 return mCurrentFont; 480 } 481 setGlobalFont(Font * font)482 void Widget::setGlobalFont(Font* font) 483 { 484 mGlobalFont = font; 485 486 std::list<Widget*>::iterator iter; 487 for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter) 488 { 489 if ((*iter)->mCurrentFont == NULL) 490 { 491 (*iter)->fontChanged(); 492 } 493 } 494 } 495 setFont(Font * font)496 void Widget::setFont(Font* font) 497 { 498 mCurrentFont = font; 499 fontChanged(); 500 } 501 widgetExists(const Widget * widget)502 bool Widget::widgetExists(const Widget* widget) 503 { 504 bool result = false; 505 506 std::list<Widget*>::iterator iter; 507 for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter) 508 { 509 if (*iter == widget) 510 { 511 return true; 512 } 513 } 514 515 return result; 516 } 517 isTabInEnabled() const518 bool Widget::isTabInEnabled() const 519 { 520 return mTabIn; 521 } 522 setTabInEnabled(bool enabled)523 void Widget::setTabInEnabled(bool enabled) 524 { 525 mTabIn = enabled; 526 } 527 isTabOutEnabled() const528 bool Widget::isTabOutEnabled() const 529 { 530 return mTabOut; 531 } 532 setTabOutEnabled(bool enabled)533 void Widget::setTabOutEnabled(bool enabled) 534 { 535 mTabOut = enabled; 536 } 537 setSize(int width,int height)538 void Widget::setSize(int width, int height) 539 { 540 Rectangle newDimension = mDimension; 541 newDimension.width = width; 542 newDimension.height = height; 543 544 setDimension(newDimension); 545 } 546 setEnabled(bool enabled)547 void Widget::setEnabled(bool enabled) 548 { 549 mEnabled = enabled; 550 } 551 isEnabled() const552 bool Widget::isEnabled() const 553 { 554 return mEnabled && isVisible(); 555 } 556 requestModalFocus()557 void Widget::requestModalFocus() 558 { 559 if (mFocusHandler == NULL) 560 { 561 throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?)."); 562 } 563 564 mFocusHandler->requestModalFocus(this); 565 } 566 requestModalMouseInputFocus()567 void Widget::requestModalMouseInputFocus() 568 { 569 if (mFocusHandler == NULL) 570 { 571 throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?)."); 572 } 573 574 mFocusHandler->requestModalMouseInputFocus(this); 575 } 576 releaseModalFocus()577 void Widget::releaseModalFocus() 578 { 579 if (mFocusHandler == NULL) 580 { 581 return; 582 } 583 584 mFocusHandler->releaseModalFocus(this); 585 } 586 releaseModalMouseInputFocus()587 void Widget::releaseModalMouseInputFocus() 588 { 589 if (mFocusHandler == NULL) 590 { 591 return; 592 } 593 594 mFocusHandler->releaseModalMouseInputFocus(this); 595 } 596 isModalFocused() const597 bool Widget::isModalFocused() const 598 { 599 if (mFocusHandler == NULL) 600 { 601 throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?)."); 602 } 603 604 if (getParent() != NULL) 605 { 606 return (mFocusHandler->getModalFocused() == this) 607 || getParent()->isModalFocused(); 608 } 609 610 return mFocusHandler->getModalFocused() == this; 611 } 612 isModalMouseInputFocused() const613 bool Widget::isModalMouseInputFocused() const 614 { 615 if (mFocusHandler == NULL) 616 { 617 throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?)."); 618 } 619 620 if (getParent() != NULL) 621 { 622 return (mFocusHandler->getModalMouseInputFocused() == this) 623 || getParent()->isModalMouseInputFocused(); 624 } 625 626 return mFocusHandler->getModalMouseInputFocused() == this; 627 } 628 getWidgetAt(int x,int y)629 Widget *Widget::getWidgetAt(int x, int y) 630 { 631 return NULL; 632 } 633 _getMouseListeners()634 const std::list<MouseListener*>& Widget::_getMouseListeners() 635 { 636 return mMouseListeners; 637 } 638 _getKeyListeners()639 const std::list<KeyListener*>& Widget::_getKeyListeners() 640 { 641 return mKeyListeners; 642 } 643 _getFocusListeners()644 const std::list<FocusListener*>& Widget::_getFocusListeners() 645 { 646 return mFocusListeners; 647 } 648 getChildrenArea()649 Rectangle Widget::getChildrenArea() 650 { 651 return Rectangle(0, 0, 0, 0); 652 } 653 _getInternalFocusHandler()654 FocusHandler* Widget::_getInternalFocusHandler() 655 { 656 return mInternalFocusHandler; 657 } 658 setInternalFocusHandler(FocusHandler * focusHandler)659 void Widget::setInternalFocusHandler(FocusHandler* focusHandler) 660 { 661 mInternalFocusHandler = focusHandler; 662 } 663 setId(const std::string & id)664 void Widget::setId(const std::string& id) 665 { 666 mId = id; 667 } 668 getId()669 const std::string& Widget::getId() 670 { 671 return mId; 672 } 673 distributeResizedEvent()674 void Widget::distributeResizedEvent() 675 { 676 WidgetListenerIterator iter; 677 678 for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter) 679 { 680 Event event(this); 681 (*iter)->widgetResized(event); 682 } 683 } 684 distributeMovedEvent()685 void Widget::distributeMovedEvent() 686 { 687 WidgetListenerIterator iter; 688 689 for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter) 690 { 691 Event event(this); 692 (*iter)->widgetMoved(event); 693 } 694 } 695 distributeHiddenEvent()696 void Widget::distributeHiddenEvent() 697 { 698 WidgetListenerIterator iter; 699 700 for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter) 701 { 702 Event event(this); 703 (*iter)->widgetHidden(event); 704 } 705 } 706 distributeActionEvent()707 void Widget::distributeActionEvent() 708 { 709 ActionListenerIterator iter; 710 for (iter = mActionListeners.begin(); iter != mActionListeners.end(); ++iter) 711 { 712 ActionEvent actionEvent(this, mActionEventId); 713 (*iter)->action(actionEvent); 714 } 715 } 716 distributeShownEvent()717 void Widget::distributeShownEvent() 718 { 719 WidgetListenerIterator iter; 720 721 for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter) 722 { 723 Event event(this); 724 (*iter)->widgetShown(event); 725 } 726 } 727 showPart(Rectangle rectangle)728 void Widget::showPart(Rectangle rectangle) 729 { 730 if (mParent != NULL) 731 { 732 mParent->showWidgetPart(this, rectangle); 733 } 734 } 735 } 736