ctrl_slider.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:15k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * ctrl_slider.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 the VideoLAN team
  5.  * $Id: b7c982926e454b61db8b8c819fa185da7bbe3946 $
  6.  *
  7.  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  8.  *          Olivier Teulière <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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 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/scaled_bitmap.hpp"
  30. #include "../src/top_window.hpp"
  31. #include "../src/os_factory.hpp"
  32. #include "../src/os_graphics.hpp"
  33. #include "../utils/position.hpp"
  34. #include "../utils/var_percent.hpp"
  35. #define RANGE 40
  36. #define SCROLL_STEP 0.05f
  37. CtrlSliderCursor::CtrlSliderCursor( intf_thread_t *pIntf,
  38.                                     const GenericBitmap &rBmpUp,
  39.                                     const GenericBitmap &rBmpOver,
  40.                                     const GenericBitmap &rBmpDown,
  41.                                     const Bezier &rCurve,
  42.                                     VarPercent &rVariable,
  43.                                     VarBool *pVisible,
  44.                                     const UString &rTooltip,
  45.                                     const UString &rHelp ):
  46.     CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
  47.     m_rVariable( rVariable ), m_tooltip( rTooltip ),
  48.     m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
  49.     m_cmdOverDown( this ), m_cmdDownOver( this ),
  50.     m_cmdOverUp( this ), m_cmdUpOver( this ),
  51.     m_cmdMove( this ), m_cmdScroll( this ),
  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.                                  void *arg  )
  140. {
  141.     // The position has changed
  142.     refreshLayout();
  143. }
  144. void CtrlSliderCursor::CmdOverDown::execute()
  145. {
  146.     EvtMouse *pEvtMouse = (EvtMouse*)m_pParent->m_pEvt;
  147.     // Compute the resize factors
  148.     float factorX, factorY;
  149.     m_pParent->getResizeFactors( factorX, factorY );
  150.     // Get the position of the control
  151.     const Position *pPos = m_pParent->getPosition();
  152.     // Compute the offset
  153.     int tempX, tempY;
  154.     m_pParent->m_rCurve.getPoint( m_pParent->m_rVariable.get(), tempX, tempY );
  155.     m_pParent->m_xOffset = pEvtMouse->getXPos() - pPos->getLeft()
  156.                        - (int)(tempX * factorX);
  157.     m_pParent->m_yOffset = pEvtMouse->getYPos() - pPos->getTop()
  158.                        - (int)(tempY * factorY);
  159.     m_pParent->captureMouse();
  160.     m_pParent->m_pImg = m_pParent->m_pImgDown;
  161.     m_pParent->refreshLayout();
  162. }
  163. void CtrlSliderCursor::CmdDownOver::execute()
  164. {
  165.     // Save the position
  166.     m_pParent->m_lastPercentage = m_pParent->m_rVariable.get();
  167.     m_pParent->releaseMouse();
  168.     m_pParent->m_pImg = m_pParent->m_pImgUp;
  169.     m_pParent->refreshLayout();
  170. }
  171. void CtrlSliderCursor::CmdUpOver::execute()
  172. {
  173.     m_pParent->m_pImg = m_pParent->m_pImgOver;
  174.     m_pParent->refreshLayout();
  175. }
  176. void CtrlSliderCursor::CmdOverUp::execute()
  177. {
  178.     m_pParent->m_pImg = m_pParent->m_pImgUp;
  179.     m_pParent->refreshLayout();
  180. }
  181. void CtrlSliderCursor::CmdMove::execute()
  182. {
  183.     EvtMouse *pEvtMouse = (EvtMouse*)m_pParent->m_pEvt;
  184.     // Get the position of the control
  185.     const Position *pPos = m_pParent->getPosition();
  186.     // Compute the resize factors
  187.     float factorX, factorY;
  188.     m_pParent->getResizeFactors( factorX, factorY );
  189.     // Compute the relative position of the centre of the cursor
  190.     float relX = pEvtMouse->getXPos() - pPos->getLeft() - m_pParent->m_xOffset;
  191.     float relY = pEvtMouse->getYPos() - pPos->getTop() - m_pParent->m_yOffset;
  192.     // Ponderate with the resize factors
  193.     int relXPond = (int)(relX / factorX);
  194.     int relYPond = (int)(relY / factorY);
  195.     // Update the position
  196.     if( m_pParent->m_rCurve.getMinDist( relXPond, relYPond ) < RANGE )
  197.     {
  198.         float percentage = m_pParent->m_rCurve.getNearestPercent( relXPond,
  199.                                                               relYPond );
  200.         m_pParent->m_rVariable.set( percentage );
  201.     }
  202.     else
  203.     {
  204.         m_pParent->m_rVariable.set( m_pParent->m_lastPercentage );
  205.     }
  206. }
  207. void CtrlSliderCursor::CmdScroll::execute()
  208. {
  209.     EvtScroll *pEvtScroll = (EvtScroll*)m_pParent->m_pEvt;
  210.     int direction = pEvtScroll->getDirection();
  211.     float percentage = m_pParent->m_rVariable.get();
  212.     if( direction == EvtScroll::kUp )
  213.     {
  214.         percentage += SCROLL_STEP;
  215.     }
  216.     else
  217.     {
  218.         percentage -= SCROLL_STEP;
  219.     }
  220.     m_pParent->m_rVariable.set( percentage );
  221. }
  222. void CtrlSliderCursor::getResizeFactors( float &rFactorX,
  223.                                          float &rFactorY ) const
  224. {
  225.     // Get the position of the control
  226.     const Position *pPos = getPosition();
  227.     rFactorX = 1.0;
  228.     rFactorY = 1.0;
  229.     // Compute the resize factors
  230.     if( m_width > 0 )
  231.     {
  232.         rFactorX = (float)pPos->getWidth() / (float)m_width;
  233.     }
  234.     if( m_height > 0 )
  235.     {
  236.         rFactorY = (float)pPos->getHeight() / (float)m_height;
  237.     }
  238. }
  239. void CtrlSliderCursor::refreshLayout()
  240. {
  241.     if( m_pImg )
  242.     {
  243.         // Compute the resize factors
  244.         float factorX, factorY;
  245.         getResizeFactors( factorX, factorY );
  246.         notifyLayout( (int)(m_rCurve.getWidth() * factorX) + m_pImg->getWidth(),
  247.                       (int)(m_rCurve.getHeight() * factorY) + m_pImg->getHeight(),
  248.                       - m_pImg->getWidth() / 2,
  249.                       - m_pImg->getHeight() / 2 );
  250.     }
  251.     else
  252.         notifyLayout();
  253. }
  254. CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf,
  255.                             const Bezier &rCurve, VarPercent &rVariable,
  256.                             int thickness, GenericBitmap *pBackground,
  257.                             int nbHoriz, int nbVert, int padHoriz, int padVert,
  258.                             VarBool *pVisible, const UString &rHelp ):
  259.     CtrlGeneric( pIntf, rHelp, pVisible ), m_pCursor( NULL ),
  260.     m_rVariable( rVariable ), m_thickness( thickness ), m_rCurve( rCurve ),
  261.     m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
  262.     m_pImgSeq( pBackground ), m_nbHoriz( nbHoriz ), m_nbVert( nbVert ),
  263.     m_padHoriz( padHoriz ), m_padVert( padVert ), m_bgWidth( 0 ),
  264.     m_bgHeight( 0 ), m_position( 0 )
  265. {
  266.     if( pBackground )
  267.     {
  268.         // Build the background image sequence
  269.         // Note: we suppose that the last padding is not included in the
  270.         // given image
  271.         // TODO: we should probably change this assumption, as it would make
  272.         // the code a bit simpler and it would be more natural for the skins
  273.         // designers
  274.         m_bgWidth = (pBackground->getWidth() + m_padHoriz) / nbHoriz;
  275.         m_bgHeight = (pBackground->getHeight() + m_padVert) / nbVert;
  276.         // Observe the position variable
  277.         m_rVariable.addObserver( this );
  278.         // Initial position
  279.         m_position = (int)( m_rVariable.get() * (m_nbHoriz * m_nbVert - 1) );
  280.     }
  281. }
  282. CtrlSliderBg::~CtrlSliderBg()
  283. {
  284.     m_rVariable.delObserver( this );
  285. }
  286. bool CtrlSliderBg::mouseOver( int x, int y ) const
  287. {
  288.     // Compute the resize factors
  289.     float factorX, factorY;
  290.     getResizeFactors( factorX, factorY );
  291.     return (m_rCurve.getMinDist( (int)(x / factorX), (int)(y / factorY),
  292.                                  factorX, factorY ) < m_thickness );
  293. }
  294. void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest )
  295. {
  296.     if( m_pImgSeq )
  297.     {
  298.         if( m_bgWidth > 0 && m_bgHeight > 0 )
  299.         {
  300.             // Compute the resize factors
  301.             float factorX, factorY;
  302.             getResizeFactors( factorX, factorY );
  303.             // Rescale the image with the actual size of the control
  304.             ScaledBitmap bmp( getIntf(), *m_pImgSeq,
  305.                  m_bgWidth * m_nbHoriz - (int)(m_padHoriz * factorX),
  306.                  m_bgHeight * m_nbVert - (int)(m_padVert * factorY) );
  307.             // Locate the right image in the background bitmap
  308.             int x = m_bgWidth * ( m_position % m_nbHoriz );
  309.             int y = m_bgHeight * ( m_position / m_nbHoriz );
  310.             // Draw the background image
  311.             rImage.drawBitmap( bmp, x, y, xDest, yDest,
  312.                                m_bgWidth - (int)(m_padHoriz * factorX),
  313.                                m_bgHeight - (int)(m_padVert * factorY) );
  314.         }
  315.     }
  316. }
  317. void CtrlSliderBg::handleEvent( EvtGeneric &rEvent )
  318. {
  319.     if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos )
  320.     {
  321.         // Compute the resize factors
  322.         float factorX, factorY;
  323.         getResizeFactors( factorX, factorY );
  324.         // Get the position of the control
  325.         const Position *pPos = getPosition();
  326.         // Get the value corresponding to the position of the mouse
  327.         EvtMouse &rEvtMouse = (EvtMouse&)rEvent;
  328.         int x = rEvtMouse.getXPos();
  329.         int y = rEvtMouse.getYPos();
  330.         m_rVariable.set( m_rCurve.getNearestPercent(
  331.                             (int)((x - pPos->getLeft()) / factorX),
  332.                             (int)((y - pPos->getTop()) / factorY) ) );
  333.         // Forward the clic to the cursor
  334.         EvtMouse evt( getIntf(), x, y, EvtMouse::kLeft, EvtMouse::kDown );
  335.         TopWindow *pWin = getWindow();
  336.         if( pWin && m_pCursor )
  337.         {
  338.             EvtEnter evtEnter( getIntf() );
  339.             // XXX It was not supposed to be implemented like that !!
  340.             pWin->forwardEvent( evtEnter, *m_pCursor );
  341.             pWin->forwardEvent( evt, *m_pCursor );
  342.         }
  343.     }
  344.     else if( rEvent.getAsString().find( "scroll" ) != string::npos )
  345.     {
  346.         int direction = ((EvtScroll&)rEvent).getDirection();
  347.         float percentage = m_rVariable.get();
  348.         if( direction == EvtScroll::kUp )
  349.         {
  350.             percentage += SCROLL_STEP;
  351.         }
  352.         else
  353.         {
  354.             percentage -= SCROLL_STEP;
  355.         }
  356.         m_rVariable.set( percentage );
  357.     }
  358. }
  359. void CtrlSliderBg::onResize()
  360. {
  361.     if( m_pImgSeq )
  362.     {
  363.         // Compute only the new size of an elementary image.
  364.         // The actual resizing is done in the draw() method for now...
  365.         // Compute the resize factors
  366.         float factorX, factorY;
  367.         getResizeFactors( factorX, factorY );
  368.         // Size of one elementary background image (padding included)
  369.         m_bgWidth = (int)((m_pImgSeq->getWidth() + m_padHoriz) * factorX / m_nbHoriz);
  370.         m_bgHeight = (int)((m_pImgSeq->getHeight() + m_padVert) * factorY / m_nbVert);
  371.     }
  372. }
  373. void CtrlSliderBg::associateCursor( CtrlSliderCursor &rCursor )
  374. {
  375.     m_pCursor = &rCursor;
  376. }
  377. void CtrlSliderBg::onUpdate( Subject<VarPercent> &rVariable, void*arg )
  378. {
  379.     m_position = (int)( m_rVariable.get() * (m_nbHoriz * m_nbVert - 1) );
  380.     notifyLayout( m_bgWidth, m_bgHeight );
  381. }
  382. void CtrlSliderBg::getResizeFactors( float &rFactorX, float &rFactorY ) const
  383. {
  384.     // Get the position of the control
  385.     const Position *pPos = getPosition();
  386.     rFactorX = 1.0;
  387.     rFactorY = 1.0;
  388.     // Compute the resize factors
  389.     if( m_width > 0 )
  390.     {
  391.         rFactorX = (float)pPos->getWidth() / (float)m_width;
  392.     }
  393.     if( m_height > 0 )
  394.     {
  395.         rFactorY = (float)pPos->getHeight() / (float)m_height;
  396.     }
  397. }