ctrl_slider.cpp
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:12k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * ctrl_slider.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: ctrl_slider.cpp 7073 2004-03-14 14:33:12Z asmax $
  6.  *
  7.  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  8.  *          Olivier Teuli鑢e <ipkiss@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. #include "ctrl_slider.hpp"
  25. #include "../events/evt_enter.hpp"
  26. #include "../events/evt_mouse.hpp"
  27. #include "../events/evt_scroll.hpp"
  28. #include "../src/generic_bitmap.hpp"
  29. #include "../src/top_window.hpp"
  30. #include "../src/os_factory.hpp"
  31. #include "../src/os_graphics.hpp"
  32. #include "../utils/position.hpp"
  33. #include "../utils/var_percent.hpp"
  34. #define RANGE 40
  35. #define SCROLL_STEP 0.05
  36. CtrlSliderCursor::CtrlSliderCursor( intf_thread_t *pIntf,
  37.                                     const GenericBitmap &rBmpUp,
  38.                                     const GenericBitmap &rBmpOver,
  39.                                     const GenericBitmap &rBmpDown,
  40.                                     const Bezier &rCurve,
  41.                                     VarPercent &rVariable,
  42.                                     VarBool *pVisible,
  43.                                     const UString &rTooltip,
  44.                                     const UString &rHelp ):
  45.     CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
  46.     m_rVariable( rVariable ), m_tooltip( rTooltip ),
  47.     m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
  48.     m_cmdOverDown( this, &transOverDown ),
  49.     m_cmdDownOver( this, &transDownOver ), m_cmdOverUp( this, &transOverUp ),
  50.     m_cmdUpOver( this, &transUpOver ), m_cmdMove( this, &transMove ),
  51.     m_cmdScroll( this, &transScroll ),
  52.     m_lastPercentage( 0 ), m_xOffset( 0 ), m_yOffset( 0 ),
  53.     m_pEvt( NULL ), m_rCurve( rCurve )
  54. {
  55.     // Build the images of the cursor
  56.     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
  57.     m_pImgUp = pOsFactory->createOSGraphics( rBmpUp.getWidth(),
  58.                                              rBmpUp.getHeight() );
  59.     m_pImgUp->drawBitmap( rBmpUp, 0, 0 );
  60.     m_pImgDown = pOsFactory->createOSGraphics( rBmpDown.getWidth(),
  61.                                                rBmpDown.getHeight() );
  62.     m_pImgDown->drawBitmap( rBmpDown, 0, 0 );
  63.     m_pImgOver = pOsFactory->createOSGraphics( rBmpOver.getWidth(),
  64.                                                rBmpOver.getHeight() );
  65.     m_pImgOver->drawBitmap( rBmpOver, 0, 0 );
  66.     // States
  67.     m_fsm.addState( "up" );
  68.     m_fsm.addState( "over" );
  69.     m_fsm.addState( "down" );
  70.     // Transitions
  71.     m_fsm.addTransition( "over", "mouse:left:down", "down",
  72.                          &m_cmdOverDown );
  73.     m_fsm.addTransition( "down", "mouse:left:up", "over",
  74.                          &m_cmdDownOver );
  75.     m_fsm.addTransition( "over", "leave", "up", &m_cmdOverUp );
  76.     m_fsm.addTransition( "up", "enter", "over", &m_cmdUpOver );
  77.     m_fsm.addTransition( "down", "motion", "down", &m_cmdMove );
  78.     m_fsm.addTransition( "over", "scroll", "over", &m_cmdScroll );
  79.     // Initial state
  80.     m_fsm.setState( "up" );
  81.     m_pImg = m_pImgUp;
  82.     // Observe the position variable
  83.     m_rVariable.addObserver( this );
  84.     // Initial position of the cursor
  85.     m_lastPercentage = m_rVariable.get();
  86. }
  87. CtrlSliderCursor::~CtrlSliderCursor()
  88. {
  89.     m_rVariable.delObserver( this );
  90.     SKINS_DELETE( m_pImgUp );
  91.     SKINS_DELETE( m_pImgDown );
  92.     SKINS_DELETE( m_pImgOver );
  93. }
  94. void CtrlSliderCursor::handleEvent( EvtGeneric &rEvent )
  95. {
  96.     // Save the event to use it in callbacks
  97.     m_pEvt = &rEvent;
  98.     m_fsm.handleTransition( rEvent.getAsString() );
  99. }
  100. bool CtrlSliderCursor::mouseOver( int x, int y ) const
  101. {
  102.     if( m_pImg )
  103.     {
  104.         // Compute the position of the cursor
  105.         int xPos, yPos;
  106.         m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
  107.         // Compute the resize factors
  108.         float factorX, factorY;
  109.         getResizeFactors( factorX, factorY );
  110.         xPos = (int)(xPos * factorX);
  111.         yPos = (int)(yPos * factorY);
  112.         return m_pImg->hit( x - xPos + m_pImg->getWidth() / 2,
  113.                             y - yPos + m_pImg->getHeight() / 2 );
  114.     }
  115.     else
  116.     {
  117.         return false;
  118.     }
  119. }
  120. void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest )
  121. {
  122.     if( m_pImg )
  123.     {
  124.         // Compute the position of the cursor
  125.         int xPos, yPos;
  126.         m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
  127.         // Compute the resize factors
  128.         float factorX, factorY;
  129.         getResizeFactors( factorX, factorY );
  130.         xPos = (int)(xPos * factorX);
  131.         yPos = (int)(yPos * factorY);
  132.         // Draw the current image
  133.         rImage.drawGraphics( *m_pImg, 0, 0,
  134.                              xDest + xPos - m_pImg->getWidth() / 2,
  135.                              yDest + yPos - m_pImg->getHeight() / 2 );
  136.     }
  137. }
  138. void CtrlSliderCursor::onUpdate( Subject<VarPercent> &rVariable )
  139. {
  140.     // The position has changed
  141.     notifyLayout();
  142. }
  143. void CtrlSliderCursor::transOverDown( SkinObject *pCtrl )
  144. {
  145.     CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
  146.     EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
  147.     // Compute the resize factors
  148.     float factorX, factorY;
  149.     pThis->getResizeFactors( factorX, factorY );
  150.     // Get the position of the control
  151.     const Position *pPos = pThis->getPosition();
  152.     // Compute the offset
  153.     int tempX, tempY;
  154.     pThis->m_rCurve.getPoint( pThis->m_rVariable.get(), tempX, tempY );
  155.     pThis->m_xOffset = pEvtMouse->getXPos() - pPos->getLeft()
  156.                        - (int)(tempX * factorX);
  157.     pThis->m_yOffset = pEvtMouse->getYPos() - pPos->getTop()
  158.                        - (int)(tempY * factorY);
  159.     pThis->captureMouse();
  160.     pThis->m_pImg = pThis->m_pImgDown;
  161.     pThis->notifyLayout();
  162. }
  163. void CtrlSliderCursor::transDownOver( SkinObject *pCtrl )
  164. {
  165.     CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
  166.     // Save the position
  167.     pThis->m_lastPercentage = pThis->m_rVariable.get();
  168.     pThis->releaseMouse();
  169.     pThis->m_pImg = pThis->m_pImgUp;
  170.     pThis->notifyLayout();
  171. }
  172. void CtrlSliderCursor::transUpOver( SkinObject *pCtrl )
  173. {
  174.     CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
  175.     pThis->m_pImg = pThis->m_pImgOver;
  176.     pThis->notifyLayout();
  177. }
  178. void CtrlSliderCursor::transOverUp( SkinObject *pCtrl )
  179. {
  180.     CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
  181.     pThis->m_pImg = pThis->m_pImgUp;
  182.     pThis->notifyLayout();
  183. }
  184. void CtrlSliderCursor::transMove( SkinObject *pCtrl )
  185. {
  186.     CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
  187.     EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
  188.     // Get the position of the control
  189.     const Position *pPos = pThis->getPosition();
  190.     // Compute the resize factors
  191.     float factorX, factorY;
  192.     pThis->getResizeFactors( factorX, factorY );
  193.     // Compute the relative position of the centre of the cursor
  194.     float relX = pEvtMouse->getXPos() - pPos->getLeft() - pThis->m_xOffset;
  195.     float relY = pEvtMouse->getYPos() - pPos->getTop() - pThis->m_yOffset;
  196.     // Ponderate with the resize factors
  197.     int relXPond = (int)(relX / factorX);
  198.     int relYPond = (int)(relY / factorY);
  199.     // Update the position
  200.     if( pThis->m_rCurve.getMinDist( relXPond, relYPond ) < RANGE )
  201.     {
  202.         float percentage = pThis->m_rCurve.getNearestPercent( relXPond,
  203.                                                               relYPond );
  204.         pThis->m_rVariable.set( percentage );
  205.     }
  206.     else
  207.     {
  208.         pThis->m_rVariable.set( pThis->m_lastPercentage );
  209.     }
  210. }
  211. void CtrlSliderCursor::transScroll( SkinObject *pCtrl )
  212. {
  213.     CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
  214.     EvtScroll *pEvtScroll = (EvtScroll*)pThis->m_pEvt;
  215.     int direction = pEvtScroll->getDirection();
  216.     float percentage = pThis->m_rVariable.get();
  217.     if( direction == EvtScroll::kUp )
  218.     {
  219.         percentage += SCROLL_STEP;
  220.     }
  221.     else
  222.     {
  223.         percentage -= SCROLL_STEP;
  224.     }
  225.     pThis->m_rVariable.set( percentage );
  226. }
  227. void CtrlSliderCursor::getResizeFactors( float &rFactorX,
  228.                                          float &rFactorY ) const
  229. {
  230.     // Get the position of the control
  231.     const Position *pPos = getPosition();
  232.     rFactorX = 1.0;
  233.     rFactorY = 1.0;
  234.     // Compute the resize factors
  235.     if( m_width > 0 )
  236.     {
  237.         rFactorX = (float)pPos->getWidth() / (float)m_width;
  238.     }
  239.     if( m_height > 0 )
  240.     {
  241.         rFactorY = (float)pPos->getHeight() / (float)m_height;
  242.     }
  243. }
  244. CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf, CtrlSliderCursor &rCursor,
  245.                             const Bezier &rCurve, VarPercent &rVariable,
  246.                             int thickness, VarBool *pVisible,
  247.                             const UString &rHelp ):
  248.     CtrlGeneric( pIntf, rHelp, pVisible ), m_rCursor( rCursor ),
  249.     m_rVariable( rVariable ), m_thickness( thickness ), m_rCurve( rCurve ),
  250.     m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() )
  251. {
  252. }
  253. bool CtrlSliderBg::mouseOver( int x, int y ) const
  254. {
  255.     // Compute the resize factors
  256.     float factorX, factorY;
  257.     getResizeFactors( factorX, factorY );
  258.     return (m_rCurve.getMinDist( (int)(x / factorX),
  259.                                  (int)(y / factorY) ) < m_thickness );
  260. }
  261. void CtrlSliderBg::handleEvent( EvtGeneric &rEvent )
  262. {
  263.     if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos )
  264.     {
  265.         // Compute the resize factors
  266.         float factorX, factorY;
  267.         getResizeFactors( factorX, factorY );
  268.         // Get the position of the control
  269.         const Position *pPos = getPosition();
  270.         // Get the value corresponding to the position of the mouse
  271.         EvtMouse &rEvtMouse = (EvtMouse&)rEvent;
  272.         int x = rEvtMouse.getXPos();
  273.         int y = rEvtMouse.getYPos();
  274.         m_rVariable.set( m_rCurve.getNearestPercent(
  275.                             (int)((x - pPos->getLeft()) / factorX),
  276.                             (int)((y - pPos->getTop()) / factorY) ) );
  277.         // Forward the clic to the cursor
  278.         EvtMouse evt( getIntf(), x, y, EvtMouse::kLeft, EvtMouse::kDown );
  279.         TopWindow *pWin = getWindow();
  280.         if( pWin )
  281.         {
  282.             EvtEnter evtEnter( getIntf() );
  283.             // XXX It was not supposed to be implemented like that !!
  284.             pWin->forwardEvent( evtEnter, m_rCursor );
  285.             pWin->forwardEvent( evt, m_rCursor );
  286.         }
  287.     }
  288.     else if( rEvent.getAsString().find( "scroll" ) != string::npos )
  289.     {
  290.         int direction = ((EvtScroll&)rEvent).getDirection();
  291.         float percentage = m_rVariable.get();
  292.         if( direction == EvtScroll::kUp )
  293.         {
  294.             percentage += SCROLL_STEP;
  295.         }
  296.         else
  297.         {
  298.             percentage -= SCROLL_STEP;
  299.         }
  300.         m_rVariable.set( percentage );
  301.     }
  302. }
  303. void CtrlSliderBg::getResizeFactors( float &rFactorX, float &rFactorY ) const
  304. {
  305.     // Get the position of the control
  306.     const Position *pPos = getPosition();
  307.     rFactorX = 1.0;
  308.     rFactorY = 1.0;
  309.     // Compute the resize factors
  310.     if( m_width > 0 )
  311.     {
  312.         rFactorX = (float)pPos->getWidth() / (float)m_width;
  313.     }
  314.     if( m_height > 0 )
  315.     {
  316.         rFactorY = (float)pPos->getHeight() / (float)m_height;
  317.     }
  318. }