widget.cpp

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/widget.hpp"
00062 
00063 #include "guichan/actionlistener.hpp"
00064 #include "guichan/basiccontainer.hpp"
00065 #include "guichan/defaultfont.hpp"
00066 #include "guichan/exception.hpp"
00067 #include "guichan/focushandler.hpp"
00068 #include "guichan/keyinput.hpp"
00069 #include "guichan/keylistener.hpp"
00070 #include "guichan/mouseinput.hpp"
00071 #include "guichan/mouselistener.hpp"
00072 
00073 
00074 namespace gcn
00075 {
00076     Font* Widget::mGlobalFont = NULL;
00077     DefaultFont Widget::mDefaultFont;
00078     std::list<Widget*> Widget::mWidgets;
00079 
00080     Widget::Widget()
00081     {
00082         mParent = NULL;
00083         mForegroundColor = Color(0x000000);
00084         mBackgroundColor = Color(0xffffff);
00085         mBaseColor = Color(0x808090);
00086         mBorderSize = 0;
00087         mFocusHandler = NULL;
00088         mFocusable = false;
00089         mClickTimeStamp = 0;
00090         mClickCount = 0;
00091         mHasMouse = false;
00092         mVisible = true;
00093         mTabIn = true;
00094         mTabOut = true;
00095         mEnabled = true;
00096         mClickButton = 0;
00097 
00098         mCurrentFont = NULL;
00099         mWidgets.push_back(this);
00100     }
00101 
00102     Widget::~Widget()
00103     {
00104         if (getParent() != NULL)
00105         {
00106             getParent()->_announceDeath(this);
00107         }
00108 
00109         _setFocusHandler(NULL);
00110 
00111         mWidgets.remove(this);
00112     }
00113 
00114     void Widget::_setParent(BasicContainer* parent)
00115     {
00116         mParent = parent;
00117     }
00118 
00119     BasicContainer* Widget::getParent() const
00120     {
00121         return mParent;
00122     }
00123 
00124     void Widget::setWidth(int width)
00125     {
00126         mDimension.width = width;
00127     }
00128 
00129     int Widget::getWidth() const
00130     {
00131         return mDimension.width;
00132     }
00133 
00134     void Widget::setHeight(int height)
00135     {
00136         mDimension.height = height;
00137     }
00138 
00139     int Widget::getHeight() const
00140     {
00141         return mDimension.height;
00142     }
00143 
00144     void Widget::setX(int x)
00145     {
00146         mDimension.x = x;
00147     }
00148 
00149     int Widget::getX() const
00150     {
00151         return mDimension.x;
00152     }
00153 
00154     void Widget::setY(int y)
00155     {
00156         mDimension.y = y;
00157     }
00158 
00159     int Widget::getY() const
00160     {
00161         return mDimension.y;
00162     }
00163 
00164     void Widget::setPosition(int x, int y)
00165     {
00166         mDimension.x = x;
00167         mDimension.y = y;
00168     }
00169 
00170     void Widget::setDimension(const Rectangle& dimension)
00171     {
00172         mDimension = dimension;
00173     }
00174 
00175     void Widget::setBorderSize(unsigned int borderSize)
00176     {
00177         mBorderSize = borderSize;
00178     }
00179 
00180     unsigned int Widget::getBorderSize() const
00181     {
00182         return mBorderSize;
00183     }
00184 
00185     const Rectangle& Widget::getDimension() const
00186     {
00187         return mDimension;
00188     }
00189 
00190     const std::string& Widget::getEventId() const
00191     {
00192         return mEventId;
00193     }
00194 
00195     void Widget::setEventId(const std::string& eventId)
00196     {
00197         mEventId = eventId;
00198     }
00199 
00200     bool Widget::isFocused() const
00201     {
00202         if (!mFocusHandler)
00203         {
00204             return false;
00205         }
00206 
00207         return (mFocusHandler->isFocused(this));
00208     }
00209 
00210     bool Widget::hasMouse() const
00211     {
00212         return mHasMouse;
00213     }
00214 
00215     void Widget::setFocusable(bool focusable)
00216     {
00217         if (!focusable && isFocused())
00218         {
00219             mFocusHandler->focusNone();
00220         }
00221 
00222         mFocusable = focusable;
00223     }
00224 
00225     bool Widget::isFocusable() const
00226     {
00227         return mFocusable && isVisible() && isEnabled();
00228     }
00229 
00230     void Widget::requestFocus()
00231     {
00232         if (mFocusHandler == NULL)
00233         {
00234             throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
00235         }
00236 
00237         if (isFocusable())
00238         {
00239             mFocusHandler->requestFocus(this);
00240         }
00241     }
00242 
00243     void Widget::requestMoveToTop()
00244     {
00245         if (mParent)
00246         {
00247             mParent->moveToTop(this);
00248         }
00249     }
00250 
00251     void Widget::requestMoveToBottom()
00252     {
00253         if (mParent)
00254         {
00255             mParent->moveToBottom(this);
00256         }
00257     }
00258 
00259     void Widget::setVisible(bool visible)
00260     {
00261         if (!visible && isFocused())
00262         {
00263             mFocusHandler->focusNone();
00264         }
00265         mVisible = visible;
00266     }
00267 
00268     bool Widget::isVisible() const
00269     {
00270         if (getParent() == NULL)
00271         {
00272             return mVisible;
00273         }
00274         else
00275         {
00276             return mVisible && getParent()->isVisible();
00277         }
00278     }
00279 
00280     void Widget::setBaseColor(const Color& color)
00281     {
00282         mBaseColor = color;
00283     }
00284 
00285     const Color& Widget::getBaseColor() const
00286     {
00287         return mBaseColor;
00288     }
00289 
00290     void Widget::setForegroundColor(const Color& color)
00291     {
00292         mForegroundColor = color;
00293     }
00294 
00295     const Color& Widget::getForegroundColor() const
00296     {
00297         return mForegroundColor;
00298     }
00299 
00300     void Widget::setBackgroundColor(const Color& color)
00301     {
00302         mBackgroundColor = color;
00303     }
00304 
00305     const Color& Widget::getBackgroundColor() const
00306     {
00307         return mBackgroundColor;
00308     }
00309 
00310     void Widget::_setFocusHandler(FocusHandler* focusHandler)
00311     {
00312         if (mFocusHandler)
00313         {
00314             releaseModalFocus();
00315             mFocusHandler->remove(this);
00316         }
00317 
00318         if (focusHandler)
00319         {
00320             focusHandler->add(this);
00321         }
00322 
00323         mFocusHandler = focusHandler;
00324     }
00325 
00326     FocusHandler* Widget::_getFocusHandler()
00327     {
00328         return mFocusHandler;
00329     }
00330 
00331     void Widget::addActionListener(ActionListener* actionListener)
00332     {
00333         mActionListeners.push_back(actionListener);
00334     }
00335 
00336     void Widget::removeActionListener(ActionListener* actionListener)
00337     {
00338         mActionListeners.remove(actionListener);
00339     }
00340 
00341     void Widget::addKeyListener(KeyListener* keyListener)
00342     {
00343         mKeyListeners.push_back(keyListener);
00344     }
00345 
00346     void Widget::removeKeyListener(KeyListener* keyListener)
00347     {
00348         mKeyListeners.remove(keyListener);
00349     }
00350 
00351     void Widget::addMouseListener(MouseListener* mouseListener)
00352     {
00353         mMouseListeners.push_back(mouseListener);
00354     }
00355 
00356     void Widget::removeMouseListener(MouseListener* mouseListener)
00357     {
00358         mMouseListeners.remove(mouseListener);
00359     }
00360 
00361     void Widget::_mouseInputMessage(const MouseInput& mouseInput)
00362     {
00363         if (mFocusHandler == NULL)
00364         {
00365             throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
00366         }
00367 
00368         if (!mEnabled || (mFocusHandler->getModalFocused() != NULL &&
00369                           !hasModalFocus()))
00370         {
00371             return;
00372         }
00373 
00374         int x = mouseInput.x;
00375         int y = mouseInput.y;
00376         int b = mouseInput.getButton();
00377         int ts = mouseInput.getTimeStamp();
00378 
00379         MouseListenerIterator iter;
00380 
00381         switch(mouseInput.getType())
00382         {
00383           case MouseInput::MOTION:
00384               for (iter = mMouseListeners.begin(); iter != mMouseListeners.end(); ++iter)
00385               {
00386                   (*iter)->mouseMotion(x, y);
00387               }
00388               break;
00389 
00390           case MouseInput::PRESS:
00391               if (hasMouse())
00392               {
00393                   requestFocus();
00394                   mFocusHandler->requestDrag(this);
00395               }
00396 
00397               if (b != MouseInput::WHEEL_UP && b != MouseInput::WHEEL_DOWN)
00398               {
00399 
00400                   for (iter = mMouseListeners.begin(); iter != mMouseListeners.end(); ++iter)
00401                   {
00402                       (*iter)->mousePress(x, y, b);
00403                   }
00404 
00405                   if (hasMouse())
00406                   {
00407                       if (ts - mClickTimeStamp < 300 && mClickButton == b)
00408                       {
00409                           mClickCount++;
00410                       }
00411                       else
00412                       {
00413                           mClickCount = 0;
00414                       }
00415                       mClickButton = b;
00416                       mClickTimeStamp = ts;
00417                   }
00418                   else
00419                   {
00420                       mClickButton = 0;
00421                   }
00422               }
00423               else if (b == MouseInput::WHEEL_UP)
00424               {
00425                   for (iter = mMouseListeners.begin(); iter != mMouseListeners.end(); ++iter)
00426                   {
00427                       (*iter)->mouseWheelUp(x, y);
00428                   }
00429               }
00430               else
00431               {
00432                   for (iter = mMouseListeners.begin(); iter != mMouseListeners.end(); ++iter)
00433                   {
00434                       (*iter)->mouseWheelDown(x, y);
00435                   }
00436               }
00437               break;
00438 
00439           case MouseInput::RELEASE:
00440               if (isDragged())
00441               {
00442                   mFocusHandler->dragNone();
00443               }
00444 
00445               if (b != MouseInput::WHEEL_UP && b != MouseInput::WHEEL_DOWN)
00446               {
00447                   for (iter = mMouseListeners.begin(); iter != mMouseListeners.end(); ++iter)
00448                   {
00449                       (*iter)->mouseRelease(x, y, b);
00450                   }
00451               }
00452 
00453               if (mHasMouse)
00454               {
00455                   if (b == mClickButton)
00456                   {
00457                       for (iter = mMouseListeners.begin(); iter != mMouseListeners.end(); ++iter)
00458                       {
00459                           (*iter)->mouseClick(x, y, b, mClickCount + 1);
00460                       }
00461                   }
00462                   else
00463                   {
00464                       mClickButton = 0;
00465                       mClickCount = 0;
00466                   }
00467               }
00468               else
00469               {
00470                   mClickCount = 0;
00471                   mClickTimeStamp = 0;
00472               }
00473               break;
00474         }
00475     }
00476 
00477     void Widget::_keyInputMessage(const KeyInput& keyInput)
00478     {
00479         if (mFocusHandler == NULL)
00480         {
00481             throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
00482         }
00483 
00484         if (!mEnabled || (mFocusHandler->getModalFocused() != NULL &&
00485                           !hasModalFocus()))
00486         {
00487             return;
00488         }
00489 
00490         KeyListenerIterator iter;
00491 
00492         switch(keyInput.getType())
00493         {
00494           case KeyInput::PRESS:
00495               for (iter = mKeyListeners.begin(); iter != mKeyListeners.end(); ++iter)
00496               {
00497                   (*iter)->keyPress(keyInput.getKey());
00498               }
00499               break;
00500 
00501           case KeyInput::RELEASE:
00502               for (iter = mKeyListeners.begin(); iter != mKeyListeners.end(); ++iter)
00503               {
00504                   (*iter)->keyRelease(keyInput.getKey());
00505               }
00506               break;
00507         }
00508     }
00509 
00510     void Widget::_mouseInMessage()
00511     {
00512         if (!mEnabled)
00513         {
00514             return;
00515         }
00516 
00517         mHasMouse = true;
00518 
00519         MouseListenerIterator iter;
00520         for (iter = mMouseListeners.begin(); iter != mMouseListeners.end(); ++iter)
00521         {
00522             (*iter)->mouseIn();
00523         }
00524     }
00525 
00526     void Widget::_mouseOutMessage()
00527     {
00528         mHasMouse = false;
00529 
00530         MouseListenerIterator iter;
00531         for (iter = mMouseListeners.begin(); iter != mMouseListeners.end(); ++iter)
00532         {
00533             (*iter)->mouseOut();
00534         }
00535     }
00536 
00537     void Widget::getAbsolutePosition(int& x, int& y) const
00538     {
00539         if (getParent() == NULL)
00540         {
00541             x = mDimension.x;
00542             y = mDimension.y;
00543             return;
00544         }
00545 
00546         int parentX;
00547         int parentY;
00548 
00549         getParent()->getAbsolutePosition(parentX, parentY);
00550 
00551         x = parentX + mDimension.x + getParent()->getChildrenArea().x;
00552         y = parentY + mDimension.y + getParent()->getChildrenArea().y;
00553     }
00554 
00555     void Widget::generateAction()
00556     {
00557         ActionListenerIterator iter;
00558         for (iter = mActionListeners.begin(); iter != mActionListeners.end(); ++iter)
00559         {
00560             (*iter)->action(mEventId, this);
00561         }
00562     }
00563 
00564     Font* Widget::getFont() const
00565     {
00566         if (mCurrentFont == NULL)
00567         {
00568             if (mGlobalFont == NULL)
00569             {
00570                 return &mDefaultFont;
00571             }
00572 
00573             return mGlobalFont;
00574         }
00575 
00576         return mCurrentFont;
00577     }
00578 
00579     void Widget::setGlobalFont(Font* font)
00580     {
00581         mGlobalFont = font;
00582 
00583         std::list<Widget*>::iterator iter;
00584         for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter)
00585         {
00586             if ((*iter)->mCurrentFont == NULL)
00587             {
00588                 (*iter)->fontChanged();
00589             }
00590         }
00591     }
00592 
00593     void Widget::setFont(Font* font)
00594     {
00595         mCurrentFont = font;
00596         fontChanged();
00597     }
00598 
00599     bool Widget::widgetExists(const Widget* widget)
00600     {
00601         bool result = false;
00602 
00603         std::list<Widget*>::iterator iter;
00604         for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter)
00605         {
00606             if (*iter == widget)
00607             {
00608                 return true;
00609             }
00610         }
00611 
00612         return result;
00613     }
00614 
00615     bool Widget::isTabInEnabled() const
00616     {
00617         return mTabIn;
00618     }
00619 
00620     void Widget::setTabInEnabled(bool enabled)
00621     {
00622         mTabIn = enabled;
00623     }
00624 
00625     bool Widget::isTabOutEnabled() const
00626     {
00627         return mTabOut;
00628     }
00629 
00630     void Widget::setTabOutEnabled(bool enabled)
00631     {
00632         mTabOut = enabled;
00633     }
00634 
00635     void Widget::setSize(int width, int height)
00636     {
00637         setWidth(width);
00638         setHeight(height);
00639     }
00640 
00641     void Widget::setEnabled(bool enabled)
00642     {
00643         mEnabled = enabled;
00644     }
00645 
00646     bool Widget::isEnabled() const
00647     {
00648         return mEnabled && isVisible();
00649     }
00650 
00651     bool Widget::isDragged() const
00652     {
00653         if (mFocusHandler == NULL)
00654         {
00655             throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
00656         }
00657 
00658         return mFocusHandler->isDragged(this);
00659     }
00660 
00661     void Widget::requestModalFocus()
00662     {
00663         if (mFocusHandler == NULL)
00664         {
00665             throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
00666         }
00667 
00668         mFocusHandler->requestModalFocus(this);
00669     }
00670 
00671     void Widget::releaseModalFocus()
00672     {
00673         if (mFocusHandler == NULL)
00674         {
00675             return;
00676         }
00677 
00678         mFocusHandler->releaseModalFocus(this);
00679     }
00680 
00681     bool Widget::hasModalFocus() const
00682     {
00683         if (mFocusHandler == NULL)
00684         {
00685             throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
00686         }
00687 
00688         if (getParent() != NULL)
00689         {
00690             return (mFocusHandler->getModalFocused() == this) || getParent()->hasModalFocus();
00691         }
00692 
00693         return mFocusHandler->getModalFocused() == this;
00694     }
00695 }

Generated on Sat Jul 29 19:38:48 2006 for Guichan by  doxygen 1.4.7