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

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