Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

scrollarea.cpp

00001 /*      _______   __   __   __   ______   __   __   _______   __   __                 
00002  *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\                
00003  *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /                 
00004  *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /                  
00005  *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /                   
00006  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /                    
00007  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/                      
00008  *
00009  * Copyright (c) 2004, 2005 darkbits                        Js_./
00010  * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
00011  * Olof Naessén a.k.a jansem/yakslem                _asww7!uY`>  )\a//
00012  *                                                 _Qhm`] _f "'c  1!5m
00013  * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
00014  *                                               .)j(] .d_/ '-(  P .   S
00015  * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
00016  * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
00017  * binary forms, with or without                 )4d[#7r, .   '     )d`)[
00018  * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
00019  * that the following conditions are met:       j<<WP+k/);.        _W=j f
00020  * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
00021  *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
00022  *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
00023  *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
00024  * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
00025  *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
00026  *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
00027  *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
00028  *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
00029  *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
00030  * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
00031  *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
00032  *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
00033  *    from this software without specific        (js, \[QQW$QWW#?!V"".
00034  *    prior written permission.                    ]y:.<\..          .
00035  *                                                 -]n w/ '         [.
00036  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
00037  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
00038  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
00039  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
00040  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
00041  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
00042  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
00043  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
00044  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
00045  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
00046  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
00047  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
00048  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00049  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00050  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00051  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00052  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00053  */
00054 
00055 /*
00056  * For comments regarding functions please see the header file. 
00057  */
00058 
00059 #include "guichan/exception.hpp"
00060 #include "guichan/widgets/scrollarea.hpp"
00061 
00062 namespace gcn
00063 {
00064     ScrollArea::ScrollArea()
00065     {
00066         mVScroll = 0;
00067         mHScroll = 0;
00068         mHPolicy = SHOW_AUTO;
00069         mVPolicy = SHOW_AUTO;
00070         mScrollbarWidth = 12;
00071         mContent = NULL;
00072         mUpButtonPressed = false;
00073         mDownButtonPressed = false;
00074         mLeftButtonPressed = false;
00075         mRightButtonPressed = false;
00076         mVerticalMarkerPressed = false;
00077         mVerticalMarkerMousePosition = 0;
00078         mHorizontalMarkerPressed = false;
00079         mHorizontalMarkerMousePosition = 0;
00080 
00081         addMouseListener(this);
00082     }
00083 
00084     ScrollArea::ScrollArea(Widget *content)
00085     {
00086         mVScroll = 0;
00087         mHScroll = 0;
00088         mHPolicy = SHOW_AUTO;
00089         mVPolicy = SHOW_AUTO;
00090         mScrollbarWidth = 12;
00091         mContent = NULL;
00092         mUpButtonPressed = false;
00093         mDownButtonPressed = false;
00094         mLeftButtonPressed = false;
00095         mRightButtonPressed = false;
00096         mVerticalMarkerPressed = false;
00097         mVerticalMarkerMousePosition = 0;
00098         mHorizontalMarkerPressed = false;
00099         mHorizontalMarkerMousePosition = 0;
00100 
00101         setContent(content);
00102         addMouseListener(this);
00103     }
00104 
00105     ScrollArea::ScrollArea(Widget *content, unsigned int hPolicy, unsigned int vPolicy)
00106     {
00107         mVScroll = 0;
00108         mHScroll = 0;
00109         mHPolicy = hPolicy;
00110         mVPolicy = vPolicy;
00111         mScrollbarWidth = 12;
00112         mContent = NULL;
00113         mUpButtonPressed = false;
00114         mDownButtonPressed = false;
00115         mLeftButtonPressed = false;
00116         mRightButtonPressed = false;
00117         mVerticalMarkerPressed = false;
00118         mVerticalMarkerMousePosition = 0;
00119         mHorizontalMarkerPressed = false;
00120         mHorizontalMarkerMousePosition = 0;
00121 
00122         setContent(content);
00123         addMouseListener(this); 
00124     }
00125 
00126     ScrollArea::~ScrollArea()
00127     {
00128         setContent(NULL);        
00129     }
00130     
00131     void ScrollArea::setContent(Widget* widget)
00132     {
00133         if (mContent != NULL)
00134         {
00135             mContent->_setFocusHandler(NULL);
00136             mContent->_setParent(NULL);
00137         }
00138     
00139         mContent = widget;
00140 
00141         if (mContent != NULL)
00142         {
00143             mContent->_setFocusHandler(_getFocusHandler());
00144             mContent->_setParent(this);
00145         }
00146 
00147         checkPolicies();
00148     }
00149   
00150     Widget* ScrollArea::getContent()
00151     {
00152         return mContent;
00153     }
00154 
00155     void ScrollArea::setHorizontalScrollPolicy(unsigned int hPolicy)
00156     {
00157         mHPolicy = hPolicy;
00158         checkPolicies();
00159     }
00160 
00161     unsigned int ScrollArea::getHorizontalScrollPolicy()
00162     {
00163         return mHPolicy;
00164     }
00165 
00166     void ScrollArea::setVerticalScrollPolicy(unsigned int vPolicy)
00167     {
00168         mVPolicy = vPolicy;
00169         checkPolicies();
00170     }
00171 
00172     unsigned int ScrollArea::getVerticalScrollPolicy()
00173     {
00174         return mVPolicy;
00175     }
00176 
00177     void ScrollArea::setScrollPolicy(unsigned int hPolicy, unsigned int vPolicy)
00178     {
00179         mHPolicy = hPolicy;
00180         mVPolicy = vPolicy;
00181         checkPolicies();
00182     }
00183 
00184     void ScrollArea::setVerticalScrollAmount(int vScroll)
00185     {
00186         int max = getVerticalMaxScroll();
00187 
00188         mVScroll = vScroll;
00189     
00190         if (vScroll > max)
00191         {
00192             mVScroll = max;
00193         }
00194     
00195         if (vScroll < 0)
00196         {
00197             mVScroll = 0;
00198         }
00199     }
00200 
00201     int ScrollArea::getVerticalScrollAmount()
00202     {
00203         return mVScroll;
00204     }
00205 
00206     void ScrollArea::setHorizontalScrollAmount(int hScroll)
00207     {
00208         int max = getHorizontalMaxScroll();
00209     
00210         mHScroll = hScroll;
00211     
00212         if (hScroll > max)
00213         {
00214             mHScroll = max;
00215         }
00216         else if (hScroll < 0)
00217         {
00218             mHScroll = 0;
00219         }
00220     }
00221 
00222     int ScrollArea::getHorizontalScrollAmount()
00223     {
00224         return mHScroll;
00225     }
00226 
00227     void ScrollArea::setScrollAmount(int hScroll, int vScroll)
00228     {
00229         setHorizontalScrollAmount(hScroll);
00230         setVerticalScrollAmount(vScroll);
00231     }
00232 
00233     int ScrollArea::getHorizontalMaxScroll()
00234     {
00235         checkPolicies();
00236 
00237         if (mContent == NULL)
00238         {
00239             return 0;
00240         }
00241         
00242         int value = mContent->getWidth() - getContentDimension().width + 2 * mContent->getBorderSize();
00243 
00244         if (value < 0)
00245         {
00246             return 0;
00247         }
00248 
00249         return value;
00250     } 
00251 
00252     int ScrollArea::getVerticalMaxScroll()
00253     {
00254         checkPolicies();
00255 
00256         if (mContent == NULL)
00257         {
00258             return 0;
00259         }
00260 
00261         int value;
00262     
00263         value = mContent->getHeight() - getContentDimension().height + 2 * mContent->getBorderSize();
00264     
00265         if (value < 0)
00266         {
00267             return 0;
00268         }
00269 
00270         return value;
00271     } 
00272 
00273     void ScrollArea::setScrollbarWidth(int width)
00274     {
00275         if (width > 0)
00276         {
00277             mScrollbarWidth = width;
00278         }
00279         else
00280         {
00281             throw GCN_EXCEPTION("Width should be greater then 0.");
00282         }
00283     }
00284 
00285     int ScrollArea::getScrollbarWidth()
00286     {
00287         return mScrollbarWidth;
00288     }
00289 
00290     void ScrollArea::_setFocusHandler(FocusHandler* focusHandler)
00291     {
00292         BasicContainer::_setFocusHandler(focusHandler);
00293 
00294         if (mContent)
00295         {
00296             mContent->_setFocusHandler(focusHandler);
00297         }
00298     }
00299 
00300     void ScrollArea::_mouseInputMessage(const MouseInput &mouseInput)
00301     {
00302         BasicContainer::_mouseInputMessage(mouseInput);        
00303     
00304         if (getContentDimension().isPointInRect(mouseInput.x, mouseInput.y))
00305         {
00306             if (mContent != NULL)
00307             {
00308                 if (!mContent->hasMouse())
00309                 {
00310                     mContent->_mouseInMessage();          
00311                 }
00312         
00313                 MouseInput mi = mouseInput;
00314                 
00315                 mi.x -= mContent->getX();
00316                 mi.y -= mContent->getY();
00317                                 
00318                 mContent->_mouseInputMessage(mi);
00319             }      
00320         }
00321         else if (mContent && mContent->hasMouse())
00322         {
00323             mContent->_mouseOutMessage();
00324         }
00325     }
00326 
00327     void ScrollArea::_mouseOutMessage()
00328     {
00329         if (mContent && mContent->hasMouse())
00330         {
00331             mContent->_mouseOutMessage();
00332         }
00333     
00334         BasicContainer::_mouseOutMessage();
00335     }
00336   
00337     void ScrollArea::mousePress(int x, int y, int button)
00338     {
00339         if (getUpButtonDimension().isPointInRect(x, y))
00340         {
00341             setVerticalScrollAmount(getVerticalScrollAmount() - 10);
00342             mUpButtonPressed = true;
00343         }
00344         else if (getDownButtonDimension().isPointInRect(x, y))
00345         {
00346             setVerticalScrollAmount(getVerticalScrollAmount() + 10);
00347             mDownButtonPressed = true;
00348         }
00349         else if (getLeftButtonDimension().isPointInRect(x, y))
00350         {
00351             setHorizontalScrollAmount(getHorizontalScrollAmount() - 10);
00352             mLeftButtonPressed = true;
00353         }
00354         else if (getRightButtonDimension().isPointInRect(x, y))
00355         {
00356             setHorizontalScrollAmount(getHorizontalScrollAmount() + 10);
00357             mRightButtonPressed = true;
00358         }        
00359         else if (getVerticalMarkerDimension().isPointInRect(x, y))
00360         {
00361             mVerticalMarkerPressed = true;
00362             mVerticalMarkerMousePosition = y - getVerticalMarkerDimension().y;
00363         }
00364         else if (getHorizontalMarkerDimension().isPointInRect(x, y))
00365         {
00366             mHorizontalMarkerPressed = true;
00367             mHorizontalMarkerMousePosition = x - getHorizontalMarkerDimension().x;
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         graphics->setColor(getBackgroundColor());
00422         graphics->fillRectangle(getContentDimension());
00423       
00424         int alpha = getBaseColor().a;
00425         Color highlightColor = getBaseColor() + 0x303030;
00426         highlightColor.a = alpha;    
00427         Color shadowColor = getBaseColor() - 0x303030;      
00428         shadowColor.a = alpha;
00429       
00430         if (mVBarVisible)
00431         {
00432             drawUpButton(graphics);
00433             drawDownButton(graphics);
00434             drawVBar(graphics);
00435             drawVMarker(graphics);
00436         }
00437       
00438         if (mHBarVisible)
00439         {
00440             drawLeftButton(graphics);
00441             drawRightButton(graphics);
00442             drawHBar(graphics);
00443             drawHMarker(graphics);
00444         }
00445       
00446         if (mHBarVisible && mVBarVisible)
00447         {
00448             graphics->setColor(getBaseColor());
00449             graphics->fillRectangle(Rectangle(getWidth() - mScrollbarWidth,
00450                                               getHeight() - mScrollbarWidth,
00451                                               mScrollbarWidth,
00452                                               mScrollbarWidth));
00453         }
00454 
00455         if (mContent)
00456         {
00457             Rectangle contdim = mContent->getDimension();        
00458             graphics->pushClipArea(getContentDimension());
00459 
00460             if (mContent->getBorderSize() > 0)
00461             {
00462                 Rectangle rec = mContent->getDimension();
00463                 rec.x -= mContent->getBorderSize();
00464                 rec.y -= mContent->getBorderSize();
00465                 rec.width += 2 * mContent->getBorderSize();
00466                 rec.height += 2 * mContent->getBorderSize();                    
00467                 graphics->pushClipArea(rec);
00468                 mContent->drawBorder(graphics);
00469                 graphics->popClipArea();
00470             }
00471                 
00472             graphics->pushClipArea(contdim);
00473             mContent->draw(graphics);
00474             graphics->popClipArea();
00475             graphics->popClipArea();
00476         }
00477     }
00478 
00479     void ScrollArea::drawBorder(Graphics* graphics)
00480     {
00481         Color faceColor = getBaseColor();
00482         Color highlightColor, shadowColor;
00483         int alpha = getBaseColor().a;
00484         int width = getWidth() + getBorderSize() * 2 - 1;
00485         int height = getHeight() + getBorderSize() * 2 - 1;
00486         highlightColor = faceColor + 0x303030;
00487         highlightColor.a = alpha;
00488         shadowColor = faceColor - 0x303030;
00489         shadowColor.a = alpha;
00490         
00491         unsigned int i;
00492         for (i = 0; i < getBorderSize(); ++i)
00493         {
00494             graphics->setColor(shadowColor);
00495             graphics->drawLine(i,i, width - i, i);
00496             graphics->drawLine(i,i + 1, i, height - i - 1);
00497             graphics->setColor(highlightColor);
00498             graphics->drawLine(width - i,i + 1, width - i, height - i); 
00499             graphics->drawLine(i,height - i, width - i - 1, height - i); 
00500         }
00501     }
00502     
00503     void ScrollArea::drawHBar(Graphics* graphics)
00504     {
00505         Rectangle dim = getHorizontalBarDimension();
00506 
00507         graphics->pushClipArea(dim);
00508 
00509         int alpha = getBaseColor().a;
00510         Color trackColor = getBaseColor() - 0x101010;
00511         trackColor.a = alpha;
00512         Color shadowColor = getBaseColor() - 0x303030;
00513         shadowColor.a = alpha;
00514         
00515         graphics->setColor(trackColor);
00516         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00517 
00518         graphics->setColor(shadowColor);
00519         graphics->drawLine(0, 0, dim.width, 0);
00520 
00521         graphics->popClipArea();    
00522     }
00523   
00524     void ScrollArea::drawVBar(Graphics* graphics)
00525     {
00526         Rectangle dim = getVerticalBarDimension();
00527 
00528         graphics->pushClipArea(dim);
00529 
00530         int alpha = getBaseColor().a;
00531         Color trackColor = getBaseColor() - 0x101010;
00532         trackColor.a = alpha;
00533         Color shadowColor = getBaseColor() - 0x303030;
00534         shadowColor.a = alpha;
00535 
00536         graphics->setColor(trackColor);
00537         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00538     
00539         graphics->setColor(shadowColor);
00540         graphics->drawLine(0, 0, 0, dim.height);
00541         
00542         graphics->popClipArea();
00543     }
00544   
00545     void ScrollArea::drawUpButton(Graphics* graphics)
00546     {
00547         Rectangle dim = getUpButtonDimension();
00548         graphics->pushClipArea(dim);
00549     
00550         Color highlightColor;
00551         Color shadowColor;
00552         Color faceColor;
00553         int offset;
00554         int alpha = getBaseColor().a;
00555         
00556         if (mUpButtonPressed)
00557         {
00558             faceColor = getBaseColor() - 0x303030;      
00559             faceColor.a = alpha;
00560             highlightColor = faceColor - 0x303030;
00561             highlightColor.a = alpha;
00562             shadowColor = getBaseColor();
00563             shadowColor.a = alpha;
00564 
00565             offset = 1;
00566         }
00567         else
00568         {
00569             faceColor = getBaseColor();
00570             faceColor.a = alpha;
00571             highlightColor = faceColor + 0x303030;
00572             highlightColor.a = alpha;
00573             shadowColor = faceColor - 0x303030;
00574             shadowColor.a = alpha;
00575 
00576             offset = 0;
00577         }
00578 
00579         graphics->setColor(faceColor);      
00580         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00581 
00582         graphics->setColor(highlightColor);
00583         graphics->drawLine(0, 0, dim.width - 1, 0);
00584         graphics->drawLine(0, 1, 0, dim.height - 1);
00585     
00586         graphics->setColor(shadowColor);
00587         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00588         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00589     
00590         graphics->setColor(getForegroundColor());
00591     
00592         int i;
00593         int w = dim.height / 2;
00594         int h = w / 2 + 2;
00595         for (i = 0; i < w / 2; ++i)
00596         {
00597             graphics->drawLine(w - i + offset,
00598                                i + h + offset,
00599                                w + i + offset,
00600                                i + h + offset);
00601         }
00602     
00603         graphics->popClipArea();
00604     }
00605 
00606     void ScrollArea::drawDownButton(Graphics* graphics)
00607     {    
00608         Rectangle dim = getDownButtonDimension();
00609         graphics->pushClipArea(dim);
00610 
00611         Color highlightColor;
00612         Color shadowColor;
00613         Color faceColor;
00614         int offset;
00615         int alpha = getBaseColor().a;
00616         
00617         if (mDownButtonPressed)
00618         {
00619             faceColor = getBaseColor() - 0x303030;      
00620             faceColor.a = alpha;
00621             highlightColor = faceColor - 0x303030;
00622             highlightColor.a = alpha;
00623             shadowColor = getBaseColor();
00624             shadowColor.a = alpha;
00625 
00626             offset = 1;
00627         }
00628         else
00629         {
00630             faceColor = getBaseColor();
00631             faceColor.a = alpha;
00632             highlightColor = faceColor + 0x303030;
00633             highlightColor.a = alpha;
00634             shadowColor = faceColor - 0x303030;
00635             shadowColor.a = alpha;
00636 
00637             offset = 0;
00638         }
00639         
00640         graphics->setColor(faceColor);      
00641         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00642 
00643         graphics->setColor(highlightColor);
00644         graphics->drawLine(0, 0, dim.width - 1, 0);
00645         graphics->drawLine(0, 1, 0, dim.height - 1);
00646     
00647         graphics->setColor(shadowColor);
00648         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00649         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00650     
00651         graphics->setColor(getForegroundColor());
00652     
00653         int i;
00654         int w = dim.height / 2;
00655         int h = w + 1;
00656         for (i = 0; i < w / 2; ++i)
00657         {
00658             graphics->drawLine(w - i + offset,
00659                                -i + h + offset,
00660                                w + i + offset,
00661                                -i + h + offset);      
00662         }
00663     
00664         graphics->popClipArea();
00665     }
00666 
00667     void ScrollArea::drawLeftButton(Graphics* graphics)
00668     {
00669         Rectangle dim = getLeftButtonDimension();
00670         graphics->pushClipArea(dim);
00671 
00672         Color highlightColor;
00673         Color shadowColor;
00674         Color faceColor;
00675         int offset;
00676         int alpha = getBaseColor().a;
00677         
00678         if (mLeftButtonPressed)
00679         {
00680             faceColor = getBaseColor() - 0x303030;      
00681             faceColor.a = alpha;
00682             highlightColor = faceColor - 0x303030;
00683             highlightColor.a = alpha;
00684             shadowColor = getBaseColor();
00685             shadowColor.a = alpha;
00686 
00687             offset = 1;
00688         }
00689         else
00690         {
00691             faceColor = getBaseColor();
00692             faceColor.a = alpha;
00693             highlightColor = faceColor + 0x303030;
00694             highlightColor.a = alpha;
00695             shadowColor = faceColor - 0x303030;
00696             shadowColor.a = alpha;
00697 
00698             offset = 0;
00699         }
00700     
00701         graphics->setColor(faceColor);      
00702         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00703 
00704         graphics->setColor(highlightColor);
00705         graphics->drawLine(0, 0, dim.width - 1, 0);
00706         graphics->drawLine(0, 1, 0, dim.height - 1);
00707     
00708         graphics->setColor(shadowColor);
00709         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00710         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00711     
00712         graphics->setColor(getForegroundColor());
00713 
00714         int i;
00715         int w = dim.width / 2;
00716         int h = w - 2;
00717         for (i = 0; i < w / 2; ++i)
00718         {
00719             graphics->drawLine(i + h + offset,
00720                                w - i + offset,
00721                                i + h + offset,
00722                                w + i + offset);      
00723         }
00724     
00725         graphics->popClipArea();
00726     }
00727 
00728     void ScrollArea::drawRightButton(Graphics* graphics)
00729     {
00730         Rectangle dim = getRightButtonDimension();
00731         graphics->pushClipArea(dim);
00732 
00733         Color highlightColor;
00734         Color shadowColor;
00735         Color faceColor;
00736         int offset;
00737         int alpha = getBaseColor().a;
00738         
00739         if (mRightButtonPressed)
00740         {
00741             faceColor = getBaseColor() - 0x303030;      
00742             faceColor.a = alpha;
00743             highlightColor = faceColor - 0x303030;
00744             highlightColor.a = alpha;
00745             shadowColor = getBaseColor();
00746             shadowColor.a = alpha;
00747 
00748             offset = 1;
00749         }
00750         else
00751         {
00752             faceColor = getBaseColor();
00753             faceColor.a = alpha;
00754             highlightColor = faceColor + 0x303030;
00755             highlightColor.a = alpha;
00756             shadowColor = faceColor - 0x303030;
00757             shadowColor.a = alpha;
00758 
00759             offset = 0;
00760         }
00761     
00762         graphics->setColor(faceColor);      
00763         graphics->fillRectangle(Rectangle(0, 0, dim.width, dim.height));
00764 
00765         graphics->setColor(highlightColor);
00766         graphics->drawLine(0, 0, dim.width - 1, 0);
00767         graphics->drawLine(0, 1, 0, dim.height - 1);
00768     
00769         graphics->setColor(shadowColor);
00770         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00771         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00772     
00773         graphics->setColor(getForegroundColor());
00774     
00775         int i;
00776         int w = dim.width / 2;
00777         int h = w + 1;
00778         for (i = 0; i < w / 2; ++i)
00779         {
00780             graphics->drawLine(-i + h + offset,
00781                                w - i + offset,
00782                                -i + h + offset,
00783                                w + i + offset);      
00784         }
00785 
00786         graphics->popClipArea(); 
00787     }
00788 
00789     void ScrollArea::drawVMarker(Graphics* graphics)
00790     {
00791         Rectangle dim = getVerticalMarkerDimension();
00792         graphics->pushClipArea(dim);
00793 
00794         int alpha = getBaseColor().a;
00795         Color faceColor = getBaseColor();
00796         faceColor.a = alpha;
00797         Color highlightColor = faceColor + 0x303030;
00798         highlightColor.a = alpha;
00799         Color shadowColor = faceColor - 0x303030;
00800         shadowColor.a = alpha;
00801         
00802         graphics->setColor(faceColor);
00803         graphics->fillRectangle(Rectangle(1, 1, dim.width - 1, dim.height - 1));
00804     
00805         graphics->setColor(highlightColor);
00806         graphics->drawLine(0, 0, dim.width - 1, 0);
00807         graphics->drawLine(0, 1, 0, dim.height - 1);
00808     
00809         graphics->setColor(shadowColor);    
00810         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00811         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00812 
00813         graphics->popClipArea();
00814     }
00815 
00816     void ScrollArea::drawHMarker(Graphics* graphics)
00817     {
00818         Rectangle dim = getHorizontalMarkerDimension();
00819         graphics->pushClipArea(dim);
00820         
00821         int alpha = getBaseColor().a;
00822         Color faceColor = getBaseColor();
00823         faceColor.a = alpha;
00824         Color highlightColor = faceColor + 0x303030;
00825         highlightColor.a = alpha;
00826         Color shadowColor = faceColor - 0x303030;
00827         shadowColor.a = alpha;
00828 
00829         graphics->setColor(faceColor);      
00830         graphics->fillRectangle(Rectangle(1, 1, dim.width - 1, dim.height - 1));
00831     
00832         graphics->setColor(highlightColor);
00833         graphics->drawLine(0, 0, dim.width - 1, 0);
00834         graphics->drawLine(0, 1, 0, dim.height - 1);
00835     
00836         graphics->setColor(shadowColor);    
00837         graphics->drawLine(1, dim.height - 1, dim.width - 1, dim.height - 1);
00838         graphics->drawLine(dim.width - 1, 0, dim.width - 1, dim.height - 1);
00839 
00840         graphics->popClipArea();
00841     }
00842   
00843     void ScrollArea::logic()
00844     {
00845         checkPolicies();
00846 
00847         setVerticalScrollAmount(getVerticalScrollAmount());
00848         setHorizontalScrollAmount(getHorizontalScrollAmount());
00849         
00850         if (mContent != NULL)
00851         {
00852             mContent->setPosition(-mHScroll + getContentDimension().x + mContent->getBorderSize(),
00853                                   -mVScroll + getContentDimension().y + mContent->getBorderSize());
00854 
00855             mContent->logic();
00856         }    
00857     }
00858 
00859     void ScrollArea::moveToTop(Widget* widget)
00860     {
00861         if (widget == mContent)
00862         {
00863             if (getParent())
00864             {
00865                 getParent()->moveToTop(this);
00866             }
00867         }
00868         else
00869         {
00870             throw GCN_EXCEPTION("Only a ScrollArea's content may be moved to top.");
00871         }
00872     }
00873 
00874     void ScrollArea::moveToBottom(Widget* widget)
00875     {
00876         if (widget == mContent)
00877         {
00878             if (getParent())
00879             {
00880                 getParent()->moveToBottom(this);
00881             }
00882         }
00883         else
00884         {
00885             throw GCN_EXCEPTION("Only a ScrollArea's content may be moved to bottom.");
00886         }
00887     }
00888 
00889     void ScrollArea::_announceDeath(Widget *widget)
00890     {
00891         if (widget == mContent)
00892         {
00893             mContent = NULL;
00894             checkPolicies();
00895         }
00896         else
00897         {
00898             throw GCN_EXCEPTION("Called by not-child.");
00899         }
00900     }
00901 
00902     void ScrollArea::getDrawSize(int& width, int& height, Widget* widget)
00903     {
00904         if (mContent == widget)
00905         {
00906             width = getContentDimension().width;
00907             height = getContentDimension().height;
00908         }
00909         else
00910         {
00911             throw GCN_EXCEPTION("Widget not in scrollarea.");
00912         }    
00913     }
00914   
00915     void ScrollArea::drawContent(Graphics* graphics)
00916     {
00917         if (mContent)
00918         {
00919             mContent->draw(graphics);
00920         }
00921     }
00922   
00923     void ScrollArea::checkPolicies()
00924     {
00925         int w = getWidth();
00926         int h = getHeight();
00927     
00928         mHBarVisible = false;
00929         mVBarVisible = false;
00930     
00931     
00932         if (!mContent)
00933         {
00934             mHBarVisible = (mHPolicy == SHOW_ALWAYS);
00935             mVBarVisible = (mVPolicy == SHOW_ALWAYS);
00936             return;
00937         }
00938     
00939         if (mHPolicy == SHOW_AUTO &&
00940             mVPolicy == SHOW_AUTO)
00941         {
00942             if (mContent->getWidth() <= w
00943                 && mContent->getHeight() <= h)
00944             {
00945                 mHBarVisible = false;
00946                 mVBarVisible = false;
00947             }
00948 
00949             if (mContent->getWidth() > w)
00950             {
00951                 mHBarVisible = true;
00952             }
00953 
00954             if ((mContent->getHeight() > h)
00955                 || (mHBarVisible && mContent->getHeight() > h - mScrollbarWidth))
00956             {
00957                 mVBarVisible = true;
00958             }
00959 
00960             if (mVBarVisible && mContent->getWidth() > w - mScrollbarWidth)
00961             {
00962                 mHBarVisible = true;
00963             }
00964       
00965             return;
00966         }
00967     
00968         switch (mHPolicy)
00969         {
00970           case SHOW_NEVER:
00971               mHBarVisible = false;
00972               break;
00973 
00974           case SHOW_ALWAYS:
00975               mHBarVisible = true;
00976               break;
00977 
00978           case SHOW_AUTO:
00979               if (mVPolicy == SHOW_NEVER)
00980               {
00981                   mHBarVisible = mContent->getWidth() > w;
00982               }
00983               else // (mVPolicy == SHOW_ALWAYS)
00984               {
00985                   mHBarVisible = mContent->getWidth() > w - mScrollbarWidth;
00986               }
00987               break;
00988 
00989           default:
00990               throw GCN_EXCEPTION("Horizontal scroll policy invalid.");
00991         }
00992 
00993         switch (mVPolicy)
00994         {
00995           case SHOW_NEVER:
00996               mVBarVisible = false;
00997               break;
00998 
00999           case SHOW_ALWAYS:
01000               mVBarVisible = true;
01001               break;
01002 
01003           case SHOW_AUTO:
01004               if (mHPolicy == SHOW_NEVER)
01005               {
01006                   mVBarVisible = mContent->getHeight() > h;
01007               }
01008               else // (mHPolicy == SHOW_ALWAYS)
01009               {
01010                   mVBarVisible = mContent->getHeight() > h - mScrollbarWidth;
01011               }
01012               break;
01013           default:
01014               throw GCN_EXCEPTION("Vertical scroll policy invalid.");
01015         }
01016     }
01017 
01018     Rectangle ScrollArea::getUpButtonDimension()
01019     {
01020         if (!mVBarVisible)
01021         {
01022             return Rectangle(0, 0, 0, 0);
01023         }
01024     
01025         return Rectangle(getWidth() - mScrollbarWidth,
01026                          0,
01027                          mScrollbarWidth,
01028                          mScrollbarWidth);
01029     }
01030 
01031     Rectangle ScrollArea::getDownButtonDimension()
01032     {
01033         if (!mVBarVisible)
01034         {
01035             return Rectangle(0, 0, 0, 0);
01036         }
01037 
01038         if (mVBarVisible && mHBarVisible)
01039         {
01040             return Rectangle(getWidth() - mScrollbarWidth,
01041                              getHeight() - mScrollbarWidth*2,
01042                              mScrollbarWidth,
01043                              mScrollbarWidth);
01044         }
01045     
01046         return Rectangle(getWidth() - mScrollbarWidth,
01047                          getHeight() - mScrollbarWidth,
01048                          mScrollbarWidth,
01049                          mScrollbarWidth);          
01050     }
01051 
01052     Rectangle ScrollArea::getLeftButtonDimension()
01053     {
01054         if (!mHBarVisible)
01055         {
01056             return Rectangle(0, 0, 0, 0);
01057         }
01058     
01059         return Rectangle(0,
01060                          getHeight() - mScrollbarWidth,
01061                          mScrollbarWidth,
01062                          mScrollbarWidth);    
01063     }
01064 
01065     Rectangle ScrollArea::getRightButtonDimension()
01066     {
01067         if (!mHBarVisible)
01068         {
01069             return Rectangle(0, 0, 0, 0);
01070         }
01071 
01072         if (mVBarVisible && mHBarVisible)
01073         {
01074             return Rectangle(getWidth() - mScrollbarWidth*2,
01075                              getHeight() - mScrollbarWidth,
01076                              mScrollbarWidth,
01077                              mScrollbarWidth);
01078         }
01079 
01080         return Rectangle(getWidth() - mScrollbarWidth,
01081                          getHeight() - mScrollbarWidth,
01082                          mScrollbarWidth,
01083                          mScrollbarWidth);          
01084     }
01085 
01086     Rectangle ScrollArea::getContentDimension()
01087     {
01088         if (mVBarVisible && mHBarVisible)
01089         {
01090             return Rectangle(0, 0, getWidth() - mScrollbarWidth, 
01091                              getHeight() - mScrollbarWidth);
01092         }
01093 
01094         if (mVBarVisible)
01095         {
01096             return Rectangle(0, 0, getWidth() - mScrollbarWidth, getHeight());
01097         }
01098 
01099         if (mHBarVisible)
01100         {
01101             return Rectangle(0, 0, getWidth(), getHeight() - mScrollbarWidth);
01102         }
01103     
01104         return Rectangle(0, 0, getWidth(), getHeight());
01105     }
01106 
01107     Rectangle ScrollArea::getVerticalBarDimension()
01108     {
01109         if (!mVBarVisible)
01110         {
01111             return Rectangle(0, 0, 0, 0);
01112         }
01113 
01114         if (mHBarVisible)
01115         {
01116             return Rectangle(getWidth() - mScrollbarWidth,
01117                              getUpButtonDimension().height,
01118                              mScrollbarWidth,
01119                              getHeight() 
01120                              - getUpButtonDimension().height
01121                              - getDownButtonDimension().height
01122                              - mScrollbarWidth);
01123         }
01124     
01125         return Rectangle(getWidth() - mScrollbarWidth,
01126                          getUpButtonDimension().height,
01127                          mScrollbarWidth,
01128                          getHeight() 
01129                          - getUpButtonDimension().height
01130                          - getDownButtonDimension().height);
01131     } 
01132 
01133     Rectangle ScrollArea::getHorizontalBarDimension()
01134     {
01135         if (!mHBarVisible)
01136         {
01137             return Rectangle(0, 0, 0, 0);
01138         }
01139 
01140         if (mVBarVisible)
01141         {
01142             return Rectangle(getLeftButtonDimension().width,
01143                              getHeight() - mScrollbarWidth,
01144                              getWidth() 
01145                              - getLeftButtonDimension().width
01146                              - getRightButtonDimension().width
01147                              - mScrollbarWidth, 
01148                              mScrollbarWidth);
01149         }
01150 
01151         return Rectangle(getLeftButtonDimension().width,
01152                          getHeight() - mScrollbarWidth,
01153                          getWidth() 
01154                          - getLeftButtonDimension().width
01155                          - getRightButtonDimension().width,
01156                          mScrollbarWidth);
01157     }
01158 
01159     Rectangle ScrollArea::getVerticalMarkerDimension()
01160     {
01161         if (!mVBarVisible)
01162         {
01163             return Rectangle(0, 0, 0, 0);
01164         }
01165 
01166         int length, pos;
01167         Rectangle barDim = getVerticalBarDimension();
01168 
01169         if (mContent && mContent->getHeight() != 0)
01170         {      
01171             length = (barDim.height * getContentDimension().height) 
01172                 / mContent->getHeight();
01173         }
01174         else
01175         {
01176             length = barDim.height;
01177         }
01178 
01179         if (length < mScrollbarWidth)
01180         {
01181             length = mScrollbarWidth;
01182         }
01183 
01184         if (length > barDim.height)
01185         {
01186             length = barDim.height;
01187         }
01188 
01189         if (getVerticalMaxScroll() != 0)
01190         {
01191             pos = ((barDim.height - length) * getVerticalScrollAmount())
01192                 / getVerticalMaxScroll();
01193         }
01194         else
01195         {
01196             pos = 0;
01197         }
01198     
01199         return Rectangle(barDim.x, barDim.y + pos, mScrollbarWidth, length);
01200     }
01201 
01202     Rectangle ScrollArea::getHorizontalMarkerDimension()
01203     {
01204         if (!mHBarVisible)
01205         {
01206             return Rectangle(0, 0, 0, 0);
01207         }
01208 
01209         int length, pos;
01210         Rectangle barDim = getHorizontalBarDimension();
01211 
01212         if (mContent && mContent->getWidth() != 0)
01213         {      
01214             length = (barDim.width * getContentDimension().width) 
01215                 / mContent->getWidth();
01216         }
01217         else
01218         {
01219             length = barDim.width;
01220         }
01221 
01222         if (length < mScrollbarWidth)
01223         {
01224             length = mScrollbarWidth;
01225         }
01226 
01227         if (length > barDim.width)
01228         {
01229             length = barDim.width;
01230         }
01231     
01232         if (getHorizontalMaxScroll() != 0)
01233         {
01234             pos = ((barDim.width - length) * getHorizontalScrollAmount())
01235                 / getHorizontalMaxScroll();
01236         }
01237         else
01238         {
01239             pos = 0;
01240         }
01241 
01242         return Rectangle(barDim.x + pos, barDim.y, length, mScrollbarWidth);
01243     }
01244 
01245     void ScrollArea::scrollToRectangle(const Rectangle& rectangle)
01246     {
01247         Rectangle contentDim = getContentDimension();
01248     
01249         if (rectangle.x + rectangle.width
01250             > getHorizontalScrollAmount() + contentDim.width)
01251         {
01252             setHorizontalScrollAmount(rectangle.x + rectangle.width - contentDim.width);
01253         }
01254     
01255         if (rectangle.y + rectangle.height
01256             > getVerticalScrollAmount() + contentDim.height)
01257         {
01258             setVerticalScrollAmount(rectangle.y + rectangle.height - contentDim.height);
01259         }
01260 
01261         if (rectangle.x < getHorizontalScrollAmount())
01262         {
01263             setHorizontalScrollAmount(rectangle.x);
01264         }
01265     
01266         if (rectangle.y < getVerticalScrollAmount())
01267         {
01268             setVerticalScrollAmount(rectangle.y);
01269         }
01270     }
01271 
01272     void ScrollArea::mouseWheelUp(int x, int y)
01273     {    
01274         if (hasMouse())
01275         {
01276             setVerticalScrollAmount(getVerticalScrollAmount() - getContentDimension().height / 8);
01277         }    
01278     }
01279 
01280     void ScrollArea::mouseWheelDown(int x, int y)
01281     {    
01282         if (hasMouse())
01283         {
01284             setVerticalScrollAmount(getVerticalScrollAmount() + getContentDimension().height / 8);
01285         }    
01286     }
01287 }
01288 
01289 /*
01290  * Wow! This is a looooong source file. 1291 lines!
01291  */

Generated on Tue May 17 21:23:26 2005 for Guichan by  doxygen 1.4.1