scrollarea.cpp

00001 /*      _______   __   __   __   ______   __   __   _______   __   __
00002  *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
00003  *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
00004  *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
00005  *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
00006  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
00007  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
00008  *
00009  * Copyright (c) 2004, 2005, 2006, 2007 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/widgets/scrollarea.hpp"
00062 
00063 #include "guichan/exception.hpp"
00064 #include "guichan/graphics.hpp"
00065 
00066 namespace gcn
00067 {
00068     ScrollArea::ScrollArea()
00069     {
00070         mVScroll = 0;
00071         mHScroll = 0;
00072         mHPolicy = SHOW_AUTO;
00073         mVPolicy = SHOW_AUTO;
00074         mScrollbarWidth = 12;
00075         mUpButtonPressed = false;
00076         mDownButtonPressed = false;
00077         mLeftButtonPressed = false;
00078         mRightButtonPressed = false;
00079         mUpButtonScrollAmount = 10;
00080         mDownButtonScrollAmount = 10;
00081         mLeftButtonScrollAmount = 10;
00082         mRightButtonScrollAmount = 10;
00083         mIsVerticalMarkerDragged = false;
00084         mIsHorizontalMarkerDragged =false;
00085 
00086         addMouseListener(this);
00087     }
00088 
00089     ScrollArea::ScrollArea(Widget *content)
00090     {
00091         mVScroll = 0;
00092         mHScroll = 0;
00093         mHPolicy = SHOW_AUTO;
00094         mVPolicy = SHOW_AUTO;
00095         mScrollbarWidth = 12;
00096         mUpButtonPressed = false;
00097         mDownButtonPressed = false;
00098         mLeftButtonPressed = false;
00099         mRightButtonPressed = false;
00100         mUpButtonScrollAmount = 10;
00101         mDownButtonScrollAmount = 10;
00102         mLeftButtonScrollAmount = 10;
00103         mRightButtonScrollAmount = 10;
00104         mIsVerticalMarkerDragged = false;
00105         mIsHorizontalMarkerDragged =false;
00106 
00107         setContent(content);
00108         addMouseListener(this);
00109     }
00110 
00111     ScrollArea::ScrollArea(Widget *content, 
00112                            ScrollPolicy hPolicy, 
00113                            ScrollPolicy vPolicy)
00114     {
00115         mVScroll = 0;
00116         mHScroll = 0;
00117         mHPolicy = hPolicy;
00118         mVPolicy = vPolicy;
00119         mScrollbarWidth = 12;
00120         mUpButtonPressed = false;
00121         mDownButtonPressed = false;
00122         mLeftButtonPressed = false;
00123         mRightButtonPressed = false;
00124         mUpButtonScrollAmount = 10;
00125         mDownButtonScrollAmount = 10;
00126         mLeftButtonScrollAmount = 10;
00127         mRightButtonScrollAmount = 10;
00128         mIsVerticalMarkerDragged = false;
00129         mIsHorizontalMarkerDragged =false;
00130 
00131         setContent(content);
00132         addMouseListener(this);
00133     }
00134 
00135     ScrollArea::~ScrollArea()
00136     {
00137         setContent(NULL);
00138     }
00139 
00140     void ScrollArea::setContent(Widget* widget)
00141     {
00142         if (widget != NULL)
00143         {
00144             clear();
00145             add(widget);
00146             widget->setPosition(0,0);
00147         }
00148         else
00149         {
00150             clear();
00151         }
00152 
00153         checkPolicies();
00154     }
00155 
00156     Widget* ScrollArea::getContent()
00157     {
00158         if (mWidgets.size() > 0)
00159         {
00160             return *mWidgets.begin();
00161         }
00162 
00163         return NULL;
00164     }
00165 
00166     void ScrollArea::setHorizontalScrollPolicy(ScrollPolicy hPolicy)
00167     {
00168         mHPolicy = hPolicy;
00169         checkPolicies();
00170     }
00171 
00172     ScrollArea::ScrollPolicy ScrollArea::getHorizontalScrollPolicy() const
00173     {
00174         return mHPolicy;
00175     }
00176 
00177     void ScrollArea::setVerticalScrollPolicy(ScrollPolicy vPolicy)
00178     {
00179         mVPolicy = vPolicy;
00180         checkPolicies();
00181     }
00182 
00183     ScrollArea::ScrollPolicy ScrollArea::getVerticalScrollPolicy() const
00184     {
00185         return mVPolicy;
00186     }
00187 
00188     void ScrollArea::setScrollPolicy(ScrollPolicy hPolicy, ScrollPolicy vPolicy)
00189     {
00190         mHPolicy = hPolicy;
00191         mVPolicy = vPolicy;
00192         checkPolicies();
00193     }
00194 
00195     void ScrollArea::setVerticalScrollAmount(int vScroll)
00196     {
00197         int max = getVerticalMaxScroll();
00198 
00199         mVScroll = vScroll;
00200 
00201         if (vScroll > max)
00202         {
00203             mVScroll = max;
00204         }
00205 
00206         if (vScroll < 0)
00207         {
00208             mVScroll = 0;
00209         }
00210     }
00211 
00212     int ScrollArea::getVerticalScrollAmount() const
00213     {
00214         return mVScroll;
00215     }
00216 
00217     void ScrollArea::setHorizontalScrollAmount(int hScroll)
00218     {
00219         int max = getHorizontalMaxScroll();
00220 
00221         mHScroll = hScroll;
00222 
00223         if (hScroll > max)
00224         {
00225             mHScroll = max;
00226         }
00227         else if (hScroll < 0)
00228         {
00229             mHScroll = 0;
00230         }
00231     }
00232 
00233     int ScrollArea::getHorizontalScrollAmount() const
00234     {
00235         return mHScroll;
00236     }
00237 
00238     void ScrollArea::setScrollAmount(int hScroll, int vScroll)
00239     {
00240         setHorizontalScrollAmount(hScroll);
00241         setVerticalScrollAmount(vScroll);
00242     }
00243 
00244     int ScrollArea::getHorizontalMaxScroll()
00245     {
00246         checkPolicies();
00247 
00248         if (getContent() == NULL)
00249         {
00250             return 0;
00251         }
00252 
00253         int value = getContent()->getWidth() - getChildrenArea().width +
00254             2 * getContent()->getFrameSize();
00255 
00256         if (value < 0)
00257         {
00258             return 0;
00259         }
00260 
00261         return value;
00262     }
00263 
00264     int ScrollArea::getVerticalMaxScroll()
00265     {
00266         checkPolicies();
00267 
00268         if (getContent() == NULL)
00269         {
00270             return 0;
00271         }
00272 
00273         int value;
00274 
00275         value = getContent()->getHeight() - getChildrenArea().height +
00276             2 * getContent()->getFrameSize();
00277 
00278         if (value < 0)
00279         {
00280             return 0;
00281         }
00282 
00283         return value;
00284     }
00285 
00286     void ScrollArea::setScrollbarWidth(int width)
00287     {
00288         if (width > 0)
00289         {
00290             mScrollbarWidth = width;
00291         }
00292         else
00293         {
00294             throw GCN_EXCEPTION("Width should be greater then 0.");
00295         }
00296     }
00297 
00298     int ScrollArea::getScrollbarWidth() const
00299     {
00300         return mScrollbarWidth;
00301     }
00302 
00303     void ScrollArea::mousePressed(MouseEvent& mouseEvent)
00304     {
00305         int x = mouseEvent.getX();
00306         int y = mouseEvent.getY();
00307 
00308         if (getUpButtonDimension().isPointInRect(x, y))
00309         {
00310             setVerticalScrollAmount(getVerticalScrollAmount()
00311                                     - mUpButtonScrollAmount);
00312             mUpButtonPressed = true;
00313         }
00314         else if (getDownButtonDimension().isPointInRect(x, y))
00315         {
00316             setVerticalScrollAmount(getVerticalScrollAmount()
00317                                     + mDownButtonScrollAmount);
00318             mDownButtonPressed = true;
00319         }
00320         else if (getLeftButtonDimension().isPointInRect(x, y))
00321         {
00322             setHorizontalScrollAmount(getHorizontalScrollAmount()
00323                                       - mLeftButtonScrollAmount);
00324             mLeftButtonPressed = true;
00325         }
00326         else if (getRightButtonDimension().isPointInRect(x, y))
00327         {
00328             setHorizontalScrollAmount(getHorizontalScrollAmount()
00329                                       + mRightButtonScrollAmount);
00330             mRightButtonPressed = true;
00331         }
00332         else if (getVerticalMarkerDimension().isPointInRect(x, y))
00333         {
00334             mIsHorizontalMarkerDragged = false;
00335             mIsVerticalMarkerDragged = true;
00336 
00337             mVerticalMarkerDragOffset = y - getVerticalMarkerDimension().y;
00338         }
00339         else if (getVerticalBarDimension().isPointInRect(x,y))
00340         {
00341             if (y < getVerticalMarkerDimension().y)
00342             {
00343                 setVerticalScrollAmount(getVerticalScrollAmount()
00344                                         - (int)(getChildrenArea().height * 0.95));
00345             }
00346             else
00347             {
00348                 setVerticalScrollAmount(getVerticalScrollAmount()
00349                                         + (int)(getChildrenArea().height * 0.95));
00350             }
00351         }
00352         else if (getHorizontalMarkerDimension().isPointInRect(x, y))
00353         {
00354             mIsHorizontalMarkerDragged = true;
00355             mIsVerticalMarkerDragged = false;
00356 
00357             mHorizontalMarkerDragOffset = x - getHorizontalMarkerDimension().x;
00358         }
00359         else if (getHorizontalBarDimension().isPointInRect(x,y))
00360         {
00361             if (x < getHorizontalMarkerDimension().x)
00362             {
00363                 setHorizontalScrollAmount(getHorizontalScrollAmount()
00364                                           - (int)(getChildrenArea().width * 0.95));
00365             }
00366             else
00367             {
00368                 setHorizontalScrollAmount(getHorizontalScrollAmount()
00369                                           + (int)(getChildrenArea().width * 0.95));
00370             }
00371         }
00372     }
00373 
00374     void ScrollArea::mouseReleased(MouseEvent& mouseEvent)
00375     {
00376         mUpButtonPressed = false;
00377         mDownButtonPressed = false;
00378         mLeftButtonPressed = false;
00379         mRightButtonPressed = false;
00380         mIsHorizontalMarkerDragged = false;
00381         mIsVerticalMarkerDragged = false;
00382 
00383         mouseEvent.consume();
00384     }
00385 
00386     void ScrollArea::mouseDragged(MouseEvent& mouseEvent)
00387     {
00388         if (mIsVerticalMarkerDragged)
00389         {
00390             int pos = mouseEvent.getY() - getVerticalBarDimension().y  - mVerticalMarkerDragOffset;
00391             int length = getVerticalMarkerDimension().height;
00392 
00393             Rectangle barDim = getVerticalBarDimension();
00394 
00395             if ((barDim.height - length) > 0)
00396             {
00397                 setVerticalScrollAmount((getVerticalMaxScroll() * pos)
00398                                          / (barDim.height - length));
00399             }
00400             else
00401             {
00402                 setVerticalScrollAmount(0);
00403             }
00404         }
00405 
00406         if (mIsHorizontalMarkerDragged)
00407         {
00408             int pos = mouseEvent.getX() - getHorizontalBarDimension().x  - mHorizontalMarkerDragOffset;
00409             int length = getHorizontalMarkerDimension().width;
00410 
00411             Rectangle barDim = getHorizontalBarDimension();
00412 
00413             if ((barDim.width - length) > 0)
00414             {
00415                 setHorizontalScrollAmount((getHorizontalMaxScroll() * pos)
00416                                           / (barDim.width - length));
00417             }
00418             else
00419             {
00420                 setHorizontalScrollAmount(0);
00421             }
00422         }
00423 
00424         mouseEvent.consume();
00425     }
00426 
00427     void ScrollArea::draw(Graphics *graphics)
00428     {
00429         drawBackground(graphics);
00430 
00431         if (mVBarVisible)
00432         {
00433             drawUpButton(graphics);
00434             drawDownButton(graphics);
00435             drawVBar(graphics);
00436             drawVMarker(graphics);
00437         }
00438 
00439         if (mHBarVisible)
00440         {
00441             drawLeftButton(graphics);
00442             drawRightButton(graphics);
00443             drawHBar(graphics);
00444             drawHMarker(graphics);
00445         }
00446 
00447         if (mHBarVisible && mVBarVisible)
00448         {
00449             graphics->setColor(getBaseColor());
00450             graphics->fillRectangle(Rectangle(getWidth() - mScrollbarWidth,
00451                                               getHeight() - mScrollbarWidth,
00452                                               mScrollbarWidth,
00453                                               mScrollbarWidth));
00454         }
00455 
00456         drawChildren(graphics);
00457     }
00458 
00459     void ScrollArea::drawHBar(Graphics* graphics)
00460     {
00461         Rectangle dim = getHorizontalBarDimension();
00462 
00463         graphics->pushClipArea(dim);
00464 
00465         int alpha = getBaseColor().a;
00466         Color trackColor = getBaseColor() - 0x101010;
00467         trackColor.a = alpha;
00468         Color shadowColor = getBaseColor() - 0x303030;
00469         shadowColor.a = alpha;
00470 
00471         graphics->setColor(trackColor);
00472         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00473 
00474         graphics->setColor(shadowColor);
00475         graphics->drawLine(0, 0, dim.width, 0);
00476 
00477         graphics->popClipArea();
00478     }
00479 
00480     void ScrollArea::drawVBar(Graphics* graphics)
00481     {
00482         Rectangle dim = getVerticalBarDimension();
00483 
00484         graphics->pushClipArea(dim);
00485 
00486         int alpha = getBaseColor().a;
00487         Color trackColor = getBaseColor() - 0x101010;
00488         trackColor.a = alpha;
00489         Color shadowColor = getBaseColor() - 0x303030;
00490         shadowColor.a = alpha;
00491 
00492         graphics->setColor(trackColor);
00493         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00494 
00495         graphics->setColor(shadowColor);
00496         graphics->drawLine(0, 0, 0, dim.height);
00497 
00498         graphics->popClipArea();
00499     }
00500 
00501     void ScrollArea::drawBackground(Graphics *graphics)
00502     {
00503         graphics->setColor(getBackgroundColor());
00504         graphics->fillRectangle(getChildrenArea());
00505     }
00506 
00507     void ScrollArea::drawUpButton(Graphics* graphics)
00508     {
00509         Rectangle dim = getUpButtonDimension();
00510         graphics->pushClipArea(dim);
00511 
00512         Color highlightColor;
00513         Color shadowColor;
00514         Color faceColor;
00515         int offset;
00516         int alpha = getBaseColor().a;
00517 
00518         if (mUpButtonPressed)
00519         {
00520             faceColor = getBaseColor() - 0x303030;
00521             faceColor.a = alpha;
00522             highlightColor = faceColor - 0x303030;
00523             highlightColor.a = alpha;
00524             shadowColor = getBaseColor();
00525             shadowColor.a = alpha;
00526 
00527             offset = 1;
00528         }
00529         else
00530         {
00531             faceColor = getBaseColor();
00532             faceColor.a = alpha;
00533             highlightColor = faceColor + 0x303030;
00534             highlightColor.a = alpha;
00535             shadowColor = faceColor - 0x303030;
00536             shadowColor.a = alpha;
00537 
00538             offset = 0;
00539         }
00540 
00541         graphics->setColor(faceColor);
00542         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00543 
00544         graphics->setColor(highlightColor);
00545         graphics->drawLine(0, 0, dim.width - 1, 0);
00546         graphics->drawLine(0, 1, 0, dim.height - 1);
00547 
00548         graphics->setColor(shadowColor);
00549         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00550         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00551 
00552         graphics->setColor(getForegroundColor());
00553 
00554         int i;
00555         int w = dim.height / 2;
00556         int h = w / 2 + 2;
00557         for (i = 0; i < w / 2; ++i)
00558         {
00559             graphics->drawLine(w - i + offset,
00560                                i + h + offset,
00561                                w + i + offset,
00562                                i + h + offset);
00563         }
00564 
00565         graphics->popClipArea();
00566     }
00567 
00568     void ScrollArea::drawDownButton(Graphics* graphics)
00569     {
00570         Rectangle dim = getDownButtonDimension();
00571         graphics->pushClipArea(dim);
00572 
00573         Color highlightColor;
00574         Color shadowColor;
00575         Color faceColor;
00576         int offset;
00577         int alpha = getBaseColor().a;
00578 
00579         if (mDownButtonPressed)
00580         {
00581             faceColor = getBaseColor() - 0x303030;
00582             faceColor.a = alpha;
00583             highlightColor = faceColor - 0x303030;
00584             highlightColor.a = alpha;
00585             shadowColor = getBaseColor();
00586             shadowColor.a = alpha;
00587 
00588             offset = 1;
00589         }
00590         else
00591         {
00592             faceColor = getBaseColor();
00593             faceColor.a = alpha;
00594             highlightColor = faceColor + 0x303030;
00595             highlightColor.a = alpha;
00596             shadowColor = faceColor - 0x303030;
00597             shadowColor.a = alpha;
00598 
00599             offset = 0;
00600         }
00601 
00602         graphics->setColor(faceColor);
00603         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00604 
00605         graphics->setColor(highlightColor);
00606         graphics->drawLine(0, 0, dim.width - 1, 0);
00607         graphics->drawLine(0, 1, 0, dim.height - 1);
00608 
00609         graphics->setColor(shadowColor);
00610         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00611         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00612 
00613         graphics->setColor(getForegroundColor());
00614 
00615         int i;
00616         int w = dim.height / 2;
00617         int h = w + 1;
00618         for (i = 0; i < w / 2; ++i)
00619         {
00620             graphics->drawLine(w - i + offset,
00621                                -i + h + offset,
00622                                w + i + offset,
00623                                -i + h + offset);
00624         }
00625 
00626         graphics->popClipArea();
00627     }
00628 
00629     void ScrollArea::drawLeftButton(Graphics* graphics)
00630     {
00631         Rectangle dim = getLeftButtonDimension();
00632         graphics->pushClipArea(dim);
00633 
00634         Color highlightColor;
00635         Color shadowColor;
00636         Color faceColor;
00637         int offset;
00638         int alpha = getBaseColor().a;
00639 
00640         if (mLeftButtonPressed)
00641         {
00642             faceColor = getBaseColor() - 0x303030;
00643             faceColor.a = alpha;
00644             highlightColor = faceColor - 0x303030;
00645             highlightColor.a = alpha;
00646             shadowColor = getBaseColor();
00647             shadowColor.a = alpha;
00648 
00649             offset = 1;
00650         }
00651         else
00652         {
00653             faceColor = getBaseColor();
00654             faceColor.a = alpha;
00655             highlightColor = faceColor + 0x303030;
00656             highlightColor.a = alpha;
00657             shadowColor = faceColor - 0x303030;
00658             shadowColor.a = alpha;
00659 
00660             offset = 0;
00661         }
00662 
00663         graphics->setColor(faceColor);
00664         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00665 
00666         graphics->setColor(highlightColor);
00667         graphics->drawLine(0, 0, dim.width - 1, 0);
00668         graphics->drawLine(0, 1, 0, dim.height - 1);
00669 
00670         graphics->setColor(shadowColor);
00671         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00672         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00673 
00674         graphics->setColor(getForegroundColor());
00675 
00676         int i;
00677         int w = dim.width / 2;
00678         int h = w - 2;
00679         for (i = 0; i < w / 2; ++i)
00680         {
00681             graphics->drawLine(i + h + offset,
00682                                w - i + offset,
00683                                i + h + offset,
00684                                w + i + offset);
00685         }
00686 
00687         graphics->popClipArea();
00688     }
00689 
00690     void ScrollArea::drawRightButton(Graphics* graphics)
00691     {
00692         Rectangle dim = getRightButtonDimension();
00693         graphics->pushClipArea(dim);
00694 
00695         Color highlightColor;
00696         Color shadowColor;
00697         Color faceColor;
00698         int offset;
00699         int alpha = getBaseColor().a;
00700 
00701         if (mRightButtonPressed)
00702         {
00703             faceColor = getBaseColor() - 0x303030;
00704             faceColor.a = alpha;
00705             highlightColor = faceColor - 0x303030;
00706             highlightColor.a = alpha;
00707             shadowColor = getBaseColor();
00708             shadowColor.a = alpha;
00709 
00710             offset = 1;
00711         }
00712         else
00713         {
00714             faceColor = getBaseColor();
00715             faceColor.a = alpha;
00716             highlightColor = faceColor + 0x303030;
00717             highlightColor.a = alpha;
00718             shadowColor = faceColor - 0x303030;
00719             shadowColor.a = alpha;
00720 
00721             offset = 0;
00722         }
00723 
00724         graphics->setColor(faceColor);
00725         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00726 
00727         graphics->setColor(highlightColor);
00728         graphics->drawLine(0, 0, dim.width - 1, 0);
00729         graphics->drawLine(0, 1, 0, dim.height - 1);
00730 
00731         graphics->setColor(shadowColor);
00732         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00733         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00734 
00735         graphics->setColor(getForegroundColor());
00736 
00737         int i;
00738         int w = dim.width / 2;
00739         int h = w + 1;
00740         for (i = 0; i < w / 2; ++i)
00741         {
00742             graphics->drawLine(-i + h + offset,
00743                                w - i + offset,
00744                                -i + h + offset,
00745                                w + i + offset);
00746         }
00747 
00748         graphics->popClipArea();
00749     }
00750 
00751     void ScrollArea::drawVMarker(Graphics* graphics)
00752     {
00753         Rectangle dim = getVerticalMarkerDimension();
00754         graphics->pushClipArea(dim);
00755 
00756         int alpha = getBaseColor().a;
00757         Color faceColor = getBaseColor();
00758         faceColor.a = alpha;
00759         Color highlightColor = faceColor + 0x303030;
00760         highlightColor.a = alpha;
00761         Color shadowColor = faceColor - 0x303030;
00762         shadowColor.a = alpha;
00763 
00764         graphics->setColor(faceColor);
00765         graphics->fillRectangle(Rectangle(1, 1, dim.width - 1, dim.height - 1));
00766 
00767         graphics->setColor(highlightColor);
00768         graphics->drawLine(0, 0, dim.width - 1, 0);
00769         graphics->drawLine(0, 1, 0, dim.height - 1);
00770 
00771         graphics->setColor(shadowColor);
00772         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00773         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00774 
00775         graphics->popClipArea();
00776     }
00777 
00778     void ScrollArea::drawHMarker(Graphics* graphics)
00779     {
00780         Rectangle dim = getHorizontalMarkerDimension();
00781         graphics->pushClipArea(dim);
00782 
00783         int alpha = getBaseColor().a;
00784         Color faceColor = getBaseColor();
00785         faceColor.a = alpha;
00786         Color highlightColor = faceColor + 0x303030;
00787         highlightColor.a = alpha;
00788         Color shadowColor = faceColor - 0x303030;
00789         shadowColor.a = alpha;
00790 
00791         graphics->setColor(faceColor);
00792         graphics->fillRectangle(Rectangle(1, 1, dim.width - 1, dim.height - 1));
00793 
00794         graphics->setColor(highlightColor);
00795         graphics->drawLine(0, 0, dim.width - 1, 0);
00796         graphics->drawLine(0, 1, 0, dim.height - 1);
00797 
00798         graphics->setColor(shadowColor);
00799         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00800         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00801 
00802         graphics->popClipArea();
00803     }
00804 
00805     void ScrollArea::logic()
00806     {
00807         checkPolicies();
00808 
00809         setVerticalScrollAmount(getVerticalScrollAmount());
00810         setHorizontalScrollAmount(getHorizontalScrollAmount());
00811 
00812         if (getContent() != NULL)
00813         {
00814             getContent()->setPosition(-mHScroll + getContent()->getFrameSize(),
00815                                       -mVScroll + getContent()->getFrameSize());
00816             getContent()->logic();
00817         }
00818     }
00819 
00820     void ScrollArea::checkPolicies()
00821     {
00822         int w = getWidth();
00823         int h = getHeight();
00824 
00825         mHBarVisible = false;
00826         mVBarVisible = false;
00827 
00828 
00829         if (!getContent())
00830         {
00831             mHBarVisible = (mHPolicy == SHOW_ALWAYS);
00832             mVBarVisible = (mVPolicy == SHOW_ALWAYS);
00833             return;
00834         }
00835 
00836         if (mHPolicy == SHOW_AUTO &&
00837             mVPolicy == SHOW_AUTO)
00838         {
00839             if (getContent()->getWidth() <= w
00840                 && getContent()->getHeight() <= h)
00841             {
00842                 mHBarVisible = false;
00843                 mVBarVisible = false;
00844             }
00845 
00846             if (getContent()->getWidth() > w)
00847             {
00848                 mHBarVisible = true;
00849             }
00850 
00851             if ((getContent()->getHeight() > h)
00852                 || (mHBarVisible && getContent()->getHeight() > h - mScrollbarWidth))
00853             {
00854                 mVBarVisible = true;
00855             }
00856 
00857             if (mVBarVisible && getContent()->getWidth() > w - mScrollbarWidth)
00858             {
00859                 mHBarVisible = true;
00860             }
00861 
00862             return;
00863         }
00864 
00865         switch (mHPolicy)
00866         {
00867           case SHOW_NEVER:
00868               mHBarVisible = false;
00869               break;
00870 
00871           case SHOW_ALWAYS:
00872               mHBarVisible = true;
00873               break;
00874 
00875           case SHOW_AUTO:
00876               if (mVPolicy == SHOW_NEVER)
00877               {
00878                   mHBarVisible = getContent()->getWidth() > w;
00879               }
00880               else // (mVPolicy == SHOW_ALWAYS)
00881               {
00882                   mHBarVisible = getContent()->getWidth() > w - mScrollbarWidth;
00883               }
00884               break;
00885 
00886           default:
00887               throw GCN_EXCEPTION("Horizontal scroll policy invalid.");
00888         }
00889 
00890         switch (mVPolicy)
00891         {
00892           case SHOW_NEVER:
00893               mVBarVisible = false;
00894               break;
00895 
00896           case SHOW_ALWAYS:
00897               mVBarVisible = true;
00898               break;
00899 
00900           case SHOW_AUTO:
00901               if (mHPolicy == SHOW_NEVER)
00902               {
00903                   mVBarVisible = getContent()->getHeight() > h;
00904               }
00905               else // (mHPolicy == SHOW_ALWAYS)
00906               {
00907                   mVBarVisible = getContent()->getHeight() > h - mScrollbarWidth;
00908               }
00909               break;
00910           default:
00911               throw GCN_EXCEPTION("Vertical scroll policy invalid.");
00912         }
00913     }
00914 
00915     Rectangle ScrollArea::getUpButtonDimension()
00916     {
00917         if (!mVBarVisible)
00918         {
00919             return Rectangle(0, 0, 0, 0);
00920         }
00921 
00922         return Rectangle(getWidth() - mScrollbarWidth,
00923                          0,
00924                          mScrollbarWidth,
00925                          mScrollbarWidth);
00926     }
00927 
00928     Rectangle ScrollArea::getDownButtonDimension()
00929     {
00930         if (!mVBarVisible)
00931         {
00932             return Rectangle(0, 0, 0, 0);
00933         }
00934 
00935         if (mVBarVisible && mHBarVisible)
00936         {
00937             return Rectangle(getWidth() - mScrollbarWidth,
00938                              getHeight() - mScrollbarWidth*2,
00939                              mScrollbarWidth,
00940                              mScrollbarWidth);
00941         }
00942 
00943         return Rectangle(getWidth() - mScrollbarWidth,
00944                          getHeight() - mScrollbarWidth,
00945                          mScrollbarWidth,
00946                          mScrollbarWidth);
00947     }
00948 
00949     Rectangle ScrollArea::getLeftButtonDimension()
00950     {
00951         if (!mHBarVisible)
00952         {
00953             return Rectangle(0, 0, 0, 0);
00954         }
00955 
00956         return Rectangle(0,
00957                          getHeight() - mScrollbarWidth,
00958                          mScrollbarWidth,
00959                          mScrollbarWidth);
00960     }
00961 
00962     Rectangle ScrollArea::getRightButtonDimension()
00963     {
00964         if (!mHBarVisible)
00965         {
00966             return Rectangle(0, 0, 0, 0);
00967         }
00968 
00969         if (mVBarVisible && mHBarVisible)
00970         {
00971             return Rectangle(getWidth() - mScrollbarWidth*2,
00972                              getHeight() - mScrollbarWidth,
00973                              mScrollbarWidth,
00974                              mScrollbarWidth);
00975         }
00976 
00977         return Rectangle(getWidth() - mScrollbarWidth,
00978                          getHeight() - mScrollbarWidth,
00979                          mScrollbarWidth,
00980                          mScrollbarWidth);
00981     }
00982 
00983     Rectangle ScrollArea::getChildrenArea()
00984     {
00985         if (mVBarVisible && mHBarVisible)
00986         {
00987             return Rectangle(0, 0, getWidth() - mScrollbarWidth,
00988                              getHeight() - mScrollbarWidth);
00989         }
00990 
00991         if (mVBarVisible)
00992         {
00993             return Rectangle(0, 0, getWidth() - mScrollbarWidth, getHeight());
00994         }
00995 
00996         if (mHBarVisible)
00997         {
00998             return Rectangle(0, 0, getWidth(), getHeight() - mScrollbarWidth);
00999         }
01000 
01001         return Rectangle(0, 0, getWidth(), getHeight());
01002     }
01003 
01004     Rectangle ScrollArea::getVerticalBarDimension()
01005     {
01006         if (!mVBarVisible)
01007         {
01008             return Rectangle(0, 0, 0, 0);
01009         }
01010 
01011         if (mHBarVisible)
01012         {
01013             return Rectangle(getWidth() - mScrollbarWidth,
01014                              getUpButtonDimension().height,
01015                              mScrollbarWidth,
01016                              getHeight()
01017                              - getUpButtonDimension().height
01018                              - getDownButtonDimension().height
01019                              - mScrollbarWidth);
01020         }
01021 
01022         return Rectangle(getWidth() - mScrollbarWidth,
01023                          getUpButtonDimension().height,
01024                          mScrollbarWidth,
01025                          getHeight()
01026                          - getUpButtonDimension().height
01027                          - getDownButtonDimension().height);
01028     }
01029 
01030     Rectangle ScrollArea::getHorizontalBarDimension()
01031     {
01032         if (!mHBarVisible)
01033         {
01034             return Rectangle(0, 0, 0, 0);
01035         }
01036 
01037         if (mVBarVisible)
01038         {
01039             return Rectangle(getLeftButtonDimension().width,
01040                              getHeight() - mScrollbarWidth,
01041                              getWidth()
01042                              - getLeftButtonDimension().width
01043                              - getRightButtonDimension().width
01044                              - mScrollbarWidth,
01045                              mScrollbarWidth);
01046         }
01047 
01048         return Rectangle(getLeftButtonDimension().width,
01049                          getHeight() - mScrollbarWidth,
01050                          getWidth()
01051                          - getLeftButtonDimension().width
01052                          - getRightButtonDimension().width,
01053                          mScrollbarWidth);
01054     }
01055 
01056     Rectangle ScrollArea::getVerticalMarkerDimension()
01057     {
01058         if (!mVBarVisible)
01059         {
01060             return Rectangle(0, 0, 0, 0);
01061         }
01062 
01063         int length, pos;
01064         Rectangle barDim = getVerticalBarDimension();
01065 
01066         if (getContent() && getContent()->getHeight() != 0)
01067         {
01068             length = (barDim.height * getChildrenArea().height)
01069                 / getContent()->getHeight();
01070         }
01071         else
01072         {
01073             length = barDim.height;
01074         }
01075 
01076         if (length < mScrollbarWidth)
01077         {
01078             length = mScrollbarWidth;
01079         }
01080 
01081         if (length > barDim.height)
01082         {
01083             length = barDim.height;
01084         }
01085 
01086         if (getVerticalMaxScroll() != 0)
01087         {
01088             pos = ((barDim.height - length) * getVerticalScrollAmount())
01089                 / getVerticalMaxScroll();
01090         }
01091         else
01092         {
01093             pos = 0;
01094         }
01095 
01096         return Rectangle(barDim.x, barDim.y + pos, mScrollbarWidth, length);
01097     }
01098 
01099     Rectangle ScrollArea::getHorizontalMarkerDimension()
01100     {
01101         if (!mHBarVisible)
01102         {
01103             return Rectangle(0, 0, 0, 0);
01104         }
01105 
01106         int length, pos;
01107         Rectangle barDim = getHorizontalBarDimension();
01108 
01109         if (getContent() && getContent()->getWidth() != 0)
01110         {
01111             length = (barDim.width * getChildrenArea().width)
01112                 / getContent()->getWidth();
01113         }
01114         else
01115         {
01116             length = barDim.width;
01117         }
01118 
01119         if (length < mScrollbarWidth)
01120         {
01121             length = mScrollbarWidth;
01122         }
01123 
01124         if (length > barDim.width)
01125         {
01126             length = barDim.width;
01127         }
01128 
01129         if (getHorizontalMaxScroll() != 0)
01130         {
01131             pos = ((barDim.width - length) * getHorizontalScrollAmount())
01132                 / getHorizontalMaxScroll();
01133         }
01134         else
01135         {
01136             pos = 0;
01137         }
01138 
01139         return Rectangle(barDim.x + pos, barDim.y, length, mScrollbarWidth);
01140     }
01141 
01142     void ScrollArea::showWidgetPart(Widget* widget, Rectangle area)
01143     {
01144         if (widget != getContent())
01145         {
01146             throw GCN_EXCEPTION("Widget not content widget");
01147         }
01148 
01149         BasicContainer::showWidgetPart(widget, area);
01150 
01151         setHorizontalScrollAmount(getContent()->getFrameSize() - getContent()->getX());
01152         setVerticalScrollAmount(getContent()->getFrameSize() - getContent()->getY());
01153     }
01154 
01155     Widget *ScrollArea::getWidgetAt(int x, int y)
01156     {
01157         if (getChildrenArea().isPointInRect(x, y))
01158         {
01159             return getContent();
01160         }
01161 
01162         return NULL;
01163     }
01164 
01165     void ScrollArea::mouseWheelMovedUp(MouseEvent& mouseEvent)
01166     {
01167         if (mouseEvent.isConsumed())
01168         {
01169             return;
01170         }
01171         
01172         setVerticalScrollAmount(getVerticalScrollAmount() - getChildrenArea().height / 8);
01173 
01174         mouseEvent.consume();
01175     }
01176 
01177     void ScrollArea::mouseWheelMovedDown(MouseEvent& mouseEvent)
01178     {
01179         if (mouseEvent.isConsumed())
01180         {
01181             return;
01182         }
01183 
01184         setVerticalScrollAmount(getVerticalScrollAmount() + getChildrenArea().height / 8);
01185 
01186         mouseEvent.consume();
01187     }
01188 
01189     void ScrollArea::setWidth(int width)
01190     {
01191         Widget::setWidth(width);
01192         checkPolicies();
01193     }
01194 
01195     void ScrollArea::setHeight(int height)
01196     {
01197         Widget::setHeight(height);
01198         checkPolicies();
01199     }
01200 
01201     void ScrollArea::setDimension(const Rectangle& dimension)
01202     {
01203         Widget::setDimension(dimension);
01204         checkPolicies();
01205     }
01206 
01207     void ScrollArea::setLeftButtonScrollAmount(int amount)
01208     {
01209         mLeftButtonScrollAmount = amount;
01210     }
01211 
01212     void ScrollArea::setRightButtonScrollAmount(int amount)
01213     {
01214         mRightButtonScrollAmount = amount;
01215     }
01216 
01217     void ScrollArea::setUpButtonScrollAmount(int amount)
01218     {
01219         mUpButtonScrollAmount = amount;
01220     }
01221 
01222     void ScrollArea::setDownButtonScrollAmount(int amount)
01223     {
01224         mDownButtonScrollAmount = amount;
01225     }
01226 
01227     int ScrollArea::getLeftButtonScrollAmount() const
01228     {
01229         return mLeftButtonScrollAmount;
01230     }
01231 
01232     int ScrollArea::getRightButtonScrollAmount() const
01233     {
01234         return mRightButtonScrollAmount;
01235     }
01236 
01237     int ScrollArea::getUpButtonScrollAmount() const
01238     {
01239         return mUpButtonScrollAmount;
01240     }
01241 
01242     int ScrollArea::getDownButtonScrollAmount() const
01243     {
01244         return mDownButtonScrollAmount;
01245     }
01246 }
01247 
01248 /*
01249  * Wow! This is a looooong source file.
01250  */

Generated on Sun Jan 20 21:48:14 2008 for Guichan by  doxygen 1.5.2