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

ctrl_slider.cpp

00001 /*****************************************************************************
00002  * ctrl_slider.cpp
00003  *****************************************************************************
00004  * Copyright (C) 2003 the VideoLAN team
00005  * $Id: ctrl_slider.cpp 12207 2005-08-15 15:54:32Z asmax $
00006  *
00007  * Authors: Cyril Deguet     <[email protected]>
00008  *          Olivier Teulière <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 #include "ctrl_slider.hpp"
00026 #include "../events/evt_enter.hpp"
00027 #include "../events/evt_mouse.hpp"
00028 #include "../events/evt_scroll.hpp"
00029 #include "../src/generic_bitmap.hpp"
00030 #include "../src/top_window.hpp"
00031 #include "../src/os_factory.hpp"
00032 #include "../src/os_graphics.hpp"
00033 #include "../utils/position.hpp"
00034 #include "../utils/var_percent.hpp"
00035 
00036 
00037 #define RANGE 40
00038 #define SCROLL_STEP 0.05f
00039 
00040 
00041 CtrlSliderCursor::CtrlSliderCursor( intf_thread_t *pIntf,
00042                                     const GenericBitmap &rBmpUp,
00043                                     const GenericBitmap &rBmpOver,
00044                                     const GenericBitmap &rBmpDown,
00045                                     const Bezier &rCurve,
00046                                     VarPercent &rVariable,
00047                                     VarBool *pVisible,
00048                                     const UString &rTooltip,
00049                                     const UString &rHelp ):
00050     CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
00051     m_rVariable( rVariable ), m_tooltip( rTooltip ),
00052     m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
00053     m_cmdOverDown( this ), m_cmdDownOver( this ),
00054     m_cmdOverUp( this ), m_cmdUpOver( this ),
00055     m_cmdMove( this ), m_cmdScroll( this ),
00056     m_lastPercentage( 0 ), m_xOffset( 0 ), m_yOffset( 0 ),
00057     m_pEvt( NULL ), m_rCurve( rCurve )
00058 {
00059     // Build the images of the cursor
00060     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
00061     m_pImgUp = pOsFactory->createOSGraphics( rBmpUp.getWidth(),
00062                                              rBmpUp.getHeight() );
00063     m_pImgUp->drawBitmap( rBmpUp, 0, 0 );
00064     m_pImgDown = pOsFactory->createOSGraphics( rBmpDown.getWidth(),
00065                                                rBmpDown.getHeight() );
00066     m_pImgDown->drawBitmap( rBmpDown, 0, 0 );
00067     m_pImgOver = pOsFactory->createOSGraphics( rBmpOver.getWidth(),
00068                                                rBmpOver.getHeight() );
00069     m_pImgOver->drawBitmap( rBmpOver, 0, 0 );
00070 
00071     // States
00072     m_fsm.addState( "up" );
00073     m_fsm.addState( "over" );
00074     m_fsm.addState( "down" );
00075 
00076     // Transitions
00077     m_fsm.addTransition( "over", "mouse:left:down", "down",
00078                          &m_cmdOverDown );
00079     m_fsm.addTransition( "down", "mouse:left:up", "over",
00080                          &m_cmdDownOver );
00081     m_fsm.addTransition( "over", "leave", "up", &m_cmdOverUp );
00082     m_fsm.addTransition( "up", "enter", "over", &m_cmdUpOver );
00083     m_fsm.addTransition( "down", "motion", "down", &m_cmdMove );
00084     m_fsm.addTransition( "over", "scroll", "over", &m_cmdScroll );
00085 
00086     // Initial state
00087     m_fsm.setState( "up" );
00088     m_pImg = m_pImgUp;
00089 
00090     // Observe the position variable
00091     m_rVariable.addObserver( this );
00092 
00093     // Initial position of the cursor
00094     m_lastPercentage = m_rVariable.get();
00095 }
00096 
00097 
00098 CtrlSliderCursor::~CtrlSliderCursor()
00099 {
00100     m_rVariable.delObserver( this );
00101     SKINS_DELETE( m_pImgUp );
00102     SKINS_DELETE( m_pImgDown );
00103     SKINS_DELETE( m_pImgOver );
00104 }
00105 
00106 
00107 void CtrlSliderCursor::handleEvent( EvtGeneric &rEvent )
00108 {
00109     // Save the event to use it in callbacks
00110     m_pEvt = &rEvent;
00111 
00112     m_fsm.handleTransition( rEvent.getAsString() );
00113 }
00114 
00115 
00116 bool CtrlSliderCursor::mouseOver( int x, int y ) const
00117 {
00118     if( m_pImg )
00119     {
00120         // Compute the position of the cursor
00121         int xPos, yPos;
00122         m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
00123 
00124         // Compute the resize factors
00125         float factorX, factorY;
00126         getResizeFactors( factorX, factorY );
00127         xPos = (int)(xPos * factorX);
00128         yPos = (int)(yPos * factorY);
00129 
00130         return m_pImg->hit( x - xPos + m_pImg->getWidth() / 2,
00131                             y - yPos + m_pImg->getHeight() / 2 );
00132     }
00133     else
00134     {
00135         return false;
00136     }
00137 }
00138 
00139 
00140 void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest )
00141 {
00142     if( m_pImg )
00143     {
00144         // Compute the position of the cursor
00145         int xPos, yPos;
00146         m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
00147 
00148         // Compute the resize factors
00149         float factorX, factorY;
00150         getResizeFactors( factorX, factorY );
00151         xPos = (int)(xPos * factorX);
00152         yPos = (int)(yPos * factorY);
00153 
00154         // Draw the current image
00155         rImage.drawGraphics( *m_pImg, 0, 0,
00156                              xDest + xPos - m_pImg->getWidth() / 2,
00157                              yDest + yPos - m_pImg->getHeight() / 2 );
00158     }
00159 }
00160 
00161 
00162 void CtrlSliderCursor::onUpdate( Subject<VarPercent> &rVariable )
00163 {
00164     // The position has changed
00165     if( m_pImg )
00166     {
00167         notifyLayout( m_rCurve.getWidth() + m_pImg->getWidth(),
00168                       m_rCurve.getHeight() + m_pImg->getHeight(),
00169                       - m_pImg->getWidth() / 2,
00170                       - m_pImg->getHeight() / 2 );
00171     }
00172     else
00173         notifyLayout();
00174 }
00175 
00176 
00177 void CtrlSliderCursor::CmdOverDown::execute()
00178 {
00179     EvtMouse *pEvtMouse = (EvtMouse*)m_pParent->m_pEvt;
00180 
00181     // Compute the resize factors
00182     float factorX, factorY;
00183     m_pParent->getResizeFactors( factorX, factorY );
00184 
00185     // Get the position of the control
00186     const Position *pPos = m_pParent->getPosition();
00187 
00188     // Compute the offset
00189     int tempX, tempY;
00190     m_pParent->m_rCurve.getPoint( m_pParent->m_rVariable.get(), tempX, tempY );
00191     m_pParent->m_xOffset = pEvtMouse->getXPos() - pPos->getLeft()
00192                        - (int)(tempX * factorX);
00193     m_pParent->m_yOffset = pEvtMouse->getYPos() - pPos->getTop()
00194                        - (int)(tempY * factorY);
00195 
00196     m_pParent->captureMouse();
00197     m_pParent->m_pImg = m_pParent->m_pImgDown;
00198     if( m_pParent->m_pImg )
00199     {
00200         m_pParent->notifyLayout(
00201             m_pParent->m_rCurve.getWidth() + m_pParent->m_pImg->getWidth(),
00202             m_pParent->m_rCurve.getHeight() + m_pParent->m_pImg->getHeight(),
00203             - m_pParent->m_pImg->getWidth() / 2,
00204             - m_pParent->m_pImg->getHeight() / 2 );
00205     }
00206     else
00207         m_pParent->notifyLayout();
00208 }
00209 
00210 
00211 void CtrlSliderCursor::CmdDownOver::execute()
00212 {
00213     // Save the position
00214     m_pParent->m_lastPercentage = m_pParent->m_rVariable.get();
00215 
00216     m_pParent->releaseMouse();
00217     m_pParent->m_pImg = m_pParent->m_pImgUp;
00218     if( m_pParent->m_pImg )
00219     {
00220         m_pParent->notifyLayout(
00221             m_pParent->m_rCurve.getWidth() + m_pParent->m_pImg->getWidth(),
00222             m_pParent->m_rCurve.getHeight() + m_pParent->m_pImg->getHeight(),
00223             - m_pParent->m_pImg->getWidth() / 2,
00224             - m_pParent->m_pImg->getHeight() / 2 );
00225     }
00226     else
00227         m_pParent->notifyLayout();
00228 }
00229 
00230 
00231 void CtrlSliderCursor::CmdUpOver::execute()
00232 {
00233     m_pParent->m_pImg = m_pParent->m_pImgOver;
00234     if( m_pParent->m_pImg )
00235     {
00236         m_pParent->notifyLayout(
00237             m_pParent->m_rCurve.getWidth() + m_pParent->m_pImg->getWidth(),
00238             m_pParent->m_rCurve.getHeight() + m_pParent->m_pImg->getHeight(),
00239             - m_pParent->m_pImg->getWidth() / 2,
00240             - m_pParent->m_pImg->getHeight() / 2 );
00241     }
00242     else
00243         m_pParent->notifyLayout();
00244 }
00245 
00246 
00247 void CtrlSliderCursor::CmdOverUp::execute()
00248 {
00249     m_pParent->m_pImg = m_pParent->m_pImgUp;
00250     if( m_pParent->m_pImg )
00251     {
00252         m_pParent->notifyLayout(
00253             m_pParent->m_rCurve.getWidth() + m_pParent->m_pImg->getWidth(),
00254             m_pParent->m_rCurve.getHeight() + m_pParent->m_pImg->getHeight(),
00255             - m_pParent->m_pImg->getWidth() / 2,
00256             - m_pParent->m_pImg->getHeight() / 2 );
00257     }
00258     else
00259         m_pParent->notifyLayout();
00260 }
00261 
00262 
00263 void CtrlSliderCursor::CmdMove::execute()
00264 {
00265     EvtMouse *pEvtMouse = (EvtMouse*)m_pParent->m_pEvt;
00266 
00267     // Get the position of the control
00268     const Position *pPos = m_pParent->getPosition();
00269 
00270     // Compute the resize factors
00271     float factorX, factorY;
00272     m_pParent->getResizeFactors( factorX, factorY );
00273 
00274     // Compute the relative position of the centre of the cursor
00275     float relX = pEvtMouse->getXPos() - pPos->getLeft() - m_pParent->m_xOffset;
00276     float relY = pEvtMouse->getYPos() - pPos->getTop() - m_pParent->m_yOffset;
00277     // Ponderate with the resize factors
00278     int relXPond = (int)(relX / factorX);
00279     int relYPond = (int)(relY / factorY);
00280 
00281     // Update the position
00282     if( m_pParent->m_rCurve.getMinDist( relXPond, relYPond ) < RANGE )
00283     {
00284         float percentage = m_pParent->m_rCurve.getNearestPercent( relXPond,
00285                                                               relYPond );
00286         m_pParent->m_rVariable.set( percentage );
00287     }
00288     else
00289     {
00290         m_pParent->m_rVariable.set( m_pParent->m_lastPercentage );
00291     }
00292 }
00293 
00294 void CtrlSliderCursor::CmdScroll::execute()
00295 {
00296     EvtScroll *pEvtScroll = (EvtScroll*)m_pParent->m_pEvt;
00297 
00298     int direction = pEvtScroll->getDirection();
00299 
00300     float percentage = m_pParent->m_rVariable.get();
00301     if( direction == EvtScroll::kUp )
00302     {
00303         percentage += SCROLL_STEP;
00304     }
00305     else
00306     {
00307         percentage -= SCROLL_STEP;
00308     }
00309 
00310     m_pParent->m_rVariable.set( percentage );
00311 }
00312 
00313 
00314 void CtrlSliderCursor::getResizeFactors( float &rFactorX,
00315                                          float &rFactorY ) const
00316 {
00317     // Get the position of the control
00318     const Position *pPos = getPosition();
00319 
00320     rFactorX = 1.0;
00321     rFactorY = 1.0;
00322 
00323     // Compute the resize factors
00324     if( m_width > 0 )
00325     {
00326         rFactorX = (float)pPos->getWidth() / (float)m_width;
00327     }
00328     if( m_height > 0 )
00329     {
00330         rFactorY = (float)pPos->getHeight() / (float)m_height;
00331     }
00332 }
00333 
00334 
00335 
00336 CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf, CtrlSliderCursor &rCursor,
00337                             const Bezier &rCurve, VarPercent &rVariable,
00338                             int thickness, VarBool *pVisible,
00339                             const UString &rHelp ):
00340     CtrlGeneric( pIntf, rHelp, pVisible ), m_rCursor( rCursor ),
00341     m_rVariable( rVariable ), m_thickness( thickness ), m_rCurve( rCurve ),
00342     m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() )
00343 {
00344 }
00345 
00346 
00347 bool CtrlSliderBg::mouseOver( int x, int y ) const
00348 {
00349     // Compute the resize factors
00350     float factorX, factorY;
00351     getResizeFactors( factorX, factorY );
00352 
00353     return (m_rCurve.getMinDist( (int)(x / factorX),
00354                                  (int)(y / factorY) ) < m_thickness );
00355 }
00356 
00357 
00358 void CtrlSliderBg::handleEvent( EvtGeneric &rEvent )
00359 {
00360     if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos )
00361     {
00362         // Compute the resize factors
00363         float factorX, factorY;
00364         getResizeFactors( factorX, factorY );
00365 
00366         // Get the position of the control
00367         const Position *pPos = getPosition();
00368 
00369         // Get the value corresponding to the position of the mouse
00370         EvtMouse &rEvtMouse = (EvtMouse&)rEvent;
00371         int x = rEvtMouse.getXPos();
00372         int y = rEvtMouse.getYPos();
00373         m_rVariable.set( m_rCurve.getNearestPercent(
00374                             (int)((x - pPos->getLeft()) / factorX),
00375                             (int)((y - pPos->getTop()) / factorY) ) );
00376 
00377         // Forward the clic to the cursor
00378         EvtMouse evt( getIntf(), x, y, EvtMouse::kLeft, EvtMouse::kDown );
00379         TopWindow *pWin = getWindow();
00380         if( pWin )
00381         {
00382             EvtEnter evtEnter( getIntf() );
00383             // XXX It was not supposed to be implemented like that !!
00384             pWin->forwardEvent( evtEnter, m_rCursor );
00385             pWin->forwardEvent( evt, m_rCursor );
00386         }
00387     }
00388     else if( rEvent.getAsString().find( "scroll" ) != string::npos )
00389     {
00390         int direction = ((EvtScroll&)rEvent).getDirection();
00391 
00392         float percentage = m_rVariable.get();
00393         if( direction == EvtScroll::kUp )
00394         {
00395             percentage += SCROLL_STEP;
00396         }
00397         else
00398         {
00399             percentage -= SCROLL_STEP;
00400         }
00401 
00402         m_rVariable.set( percentage );
00403     }
00404 }
00405 
00406 
00407 void CtrlSliderBg::getResizeFactors( float &rFactorX, float &rFactorY ) const
00408 {
00409     // Get the position of the control
00410     const Position *pPos = getPosition();
00411 
00412     rFactorX = 1.0;
00413     rFactorY = 1.0;
00414 
00415     // Compute the resize factors
00416     if( m_width > 0 )
00417     {
00418         rFactorX = (float)pPos->getWidth() / (float)m_width;
00419     }
00420     if( m_height > 0 )
00421     {
00422         rFactorY = (float)pPos->getHeight() / (float)m_height;
00423     }
00424 }
00425 

Generated on Tue Dec 20 10:14:41 2005 for vlc-0.8.4a by  doxygen 1.4.2