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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * ctrl_text.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: ctrl_text.cpp 8347 2004-08-01 20:46:01Z 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_text.hpp"
  25. #include "../events/evt_generic.hpp"
  26. #include "../events/evt_mouse.hpp"
  27. #include "../src/generic_bitmap.hpp"
  28. #include "../src/generic_font.hpp"
  29. #include "../src/os_factory.hpp"
  30. #include "../src/os_graphics.hpp"
  31. #include "../src/os_timer.hpp"
  32. #include "../utils/position.hpp"
  33. #include "../utils/ustring.hpp"
  34. #include "../utils/var_text.hpp"
  35. #define MOVING_TEXT_STEP 1
  36. #define MOVING_TEXT_DELAY 30
  37. #define SEPARATOR_STRING "   "
  38. CtrlText::CtrlText( intf_thread_t *pIntf, VarText &rVariable,
  39.                     const GenericFont &rFont, const UString &rHelp,
  40.                     uint32_t color, VarBool *pVisible ):
  41.     CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
  42.     m_rVariable( rVariable ), m_cmdToManual( this, &transToManual ),
  43.     m_cmdManualMoving( this, &transManualMoving ),
  44.     m_cmdManualStill( this, &transManualStill ),
  45.     m_cmdMove( this, &transMove ),
  46.     m_pEvt( NULL ), m_rFont( rFont ), m_color( color ),
  47.     m_pImg( NULL ), m_pImgDouble( NULL ), m_pCurrImg( NULL ),
  48.     m_xPos( 0 ), m_xOffset( 0 )
  49. {
  50.     m_pTimer = OSFactory::instance( getIntf() )->createOSTimer(
  51.         Callback( this, &updateText ) );
  52.     // States
  53.     m_fsm.addState( "still" );
  54.     m_fsm.addState( "moving" );
  55.     m_fsm.addState( "manual1" );
  56.     m_fsm.addState( "manual2" );
  57.     m_fsm.addState( "outStill" );
  58.     m_fsm.addState( "outMoving" );
  59.     // Transitions
  60.     m_fsm.addTransition( "still", "mouse:left:down", "manual1",
  61.                          &m_cmdToManual );
  62.     m_fsm.addTransition( "manual1", "mouse:left:up", "moving",
  63.                          &m_cmdManualMoving );
  64.     m_fsm.addTransition( "moving", "mouse:left:down", "manual2",
  65.                          &m_cmdToManual );
  66.     m_fsm.addTransition( "manual2", "mouse:left:up", "still",
  67.                          &m_cmdManualStill );
  68.     m_fsm.addTransition( "manual1", "motion", "manual1", &m_cmdMove );
  69.     m_fsm.addTransition( "manual2", "motion", "manual2", &m_cmdMove );
  70.     m_fsm.addTransition( "still", "leave", "outStill" );
  71.     m_fsm.addTransition( "outStill", "enter", "still" );
  72.     m_fsm.addTransition( "moving", "leave", "outMoving" );
  73.     m_fsm.addTransition( "outMoving", "enter", "moving" );
  74.     // Initial state
  75.     m_fsm.setState( "moving" );
  76.     // Observe the variable
  77.     m_rVariable.addObserver( this );
  78.     // Set the text
  79.     displayText( m_rVariable.get() );
  80. }
  81. CtrlText::~CtrlText()
  82. {
  83.     m_rVariable.delObserver( this );
  84.     if( m_pTimer )
  85.     {
  86.         delete m_pTimer;
  87.     }
  88.     if( m_pImg )
  89.     {
  90.         delete m_pImg;
  91.     }
  92.     if( m_pImgDouble )
  93.     {
  94.         delete m_pImgDouble;
  95.     }
  96. }
  97. void CtrlText::handleEvent( EvtGeneric &rEvent )
  98. {
  99.     // Save the event to use it in callbacks
  100.     m_pEvt = &rEvent;
  101.     m_fsm.handleTransition( rEvent.getAsString() );
  102. }
  103. bool CtrlText::mouseOver( int x, int y ) const
  104. {
  105.     if( m_pCurrImg )
  106.     {
  107.         // We have 3 different ways of deciding when to return true here:
  108.         //  1) the mouse is exactly over the text (so if you click between two
  109.         //     letters, the text control doesn't catch the event)
  110.         //  2) the mouse is over the rectangle of the control
  111.         //  3) the mouse is over the rectangle of the visible text
  112.         // I don't know which one is the best...
  113. #if 0
  114.         return( x >= 0 && x < getPosition()->getWidth()
  115.              && m_pCurrImg->hit( x - m_xPos, y ) );
  116. #endif
  117. #if 1
  118.         return( x >= 0 && x < getPosition()->getWidth()
  119.              && y >= 0 && y < getPosition()->getHeight() );
  120. #endif
  121. #if 0
  122.         return( x >= 0 && x < getPosition()->getWidth()
  123.              && y >= 0 && y < getPosition()->getHeight()
  124.              && x < m_pCurrImg->getWidth() && x < m_pCurrImg->getHeight() );
  125. #endif
  126.     }
  127.     else
  128.     {
  129.         return false;
  130.     }
  131. }
  132. void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
  133. {
  134.     if( m_pCurrImg )
  135.     {
  136.         // Compute the dimensions to draw
  137.         int width = min( m_pCurrImg->getWidth() + m_xPos,
  138.                          getPosition()->getWidth() );
  139.         int height = min( m_pCurrImg->getHeight(), getPosition()->getHeight() );
  140.         // Draw the current image
  141.         if( width > 0 && height > 0 )
  142.         {
  143.             rImage.drawBitmap( *m_pCurrImg, -m_xPos, 0, xDest, yDest,
  144.                             width, height );
  145.         }
  146.     }
  147. }
  148. void CtrlText::setText( const UString &rText, uint32_t color )
  149. {
  150.     // Change the color
  151.     if( color != 0xFFFFFFFF )
  152.     {
  153.         m_color = color;
  154.     }
  155.     // Change the text
  156.     m_rVariable.set( rText );
  157. }
  158. void CtrlText::onUpdate( Subject<VarText> &rVariable )
  159. {
  160.     displayText( m_rVariable.get() );
  161. }
  162. void CtrlText::displayText( const UString &rText )
  163. {
  164.     // Create the images ('normal' and 'double') from the text
  165.     // 'Normal' image
  166.     if( m_pImg )
  167.     {
  168.         delete m_pImg;
  169.     }
  170.     m_pImg = m_rFont.drawString( rText, m_color );
  171.     if( !m_pImg )
  172.     {
  173.         return;
  174.     }
  175.     // 'Double' image
  176.     const UString doubleStringWithSep = rText + SEPARATOR_STRING + rText;
  177.     if( m_pImgDouble )
  178.     {
  179.         delete m_pImgDouble;
  180.     }
  181.     m_pImgDouble = m_rFont.drawString( doubleStringWithSep, m_color );
  182.     // Update the current image used, as if the control size had changed
  183.     onChangePosition();
  184.     m_xPos = 0;
  185.     if( getPosition() )
  186.     {
  187.         // If the control was in the moving state, check if the scrolling is
  188.         // still necessary
  189.         const string &rState = m_fsm.getState();
  190.         if( rState == "moving" || rState == "outMoving" )
  191.         {
  192.             if( m_pImg && m_pImg->getWidth() >= getPosition()->getWidth() )
  193.             {
  194.                 m_pCurrImg = m_pImgDouble;
  195.                 m_pTimer->start( MOVING_TEXT_DELAY, false );
  196.             }
  197.             else
  198.             {
  199.                 m_pTimer->stop();
  200.             }
  201.         }
  202.         notifyLayout();
  203.     }
  204. }
  205. void CtrlText::onChangePosition()
  206. {
  207.     if( m_pImg && getPosition() )
  208.     {
  209.         if( m_pImg->getWidth() < getPosition()->getWidth() )
  210.         {
  211.             m_pCurrImg = m_pImg;
  212.         }
  213.         else
  214.         {
  215.             m_pCurrImg = m_pImgDouble;
  216.         }
  217.     }
  218.     else
  219.     {
  220.         // m_pImg is a better default value than m_pImgDouble, but anyway we
  221.         // don't care because the control is never drawn without position :)
  222.         m_pCurrImg = m_pImg;
  223.     }
  224. }
  225. void CtrlText::transToManual( SkinObject *pCtrl )
  226. {
  227.     CtrlText *pThis = (CtrlText*)pCtrl;
  228.     EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
  229.     // Compute the offset
  230.     pThis->m_xOffset = pEvtMouse->getXPos() - pThis->m_xPos;
  231.     pThis->m_pTimer->stop();
  232.     pThis->captureMouse();
  233. }
  234. void CtrlText::transManualMoving( SkinObject *pCtrl )
  235. {
  236.     CtrlText *pThis = (CtrlText*)pCtrl;
  237.     pThis->releaseMouse();
  238.     // Start the automatic movement, but only if the text is wider than the
  239.     // control
  240.     if( pThis->m_pImg &&
  241.         pThis->m_pImg->getWidth() >= pThis->getPosition()->getWidth() )
  242.     {
  243.         // The current image may have been set incorrectly in displayText(), so
  244.         // set the correct value
  245.         pThis->m_pCurrImg = pThis->m_pImgDouble;
  246.         pThis->m_pTimer->start( MOVING_TEXT_DELAY, false );
  247.     }
  248. }
  249. void CtrlText::transManualStill( SkinObject *pCtrl )
  250. {
  251.     CtrlText *pThis = (CtrlText*)pCtrl;
  252.     pThis->releaseMouse();
  253. }
  254. void CtrlText::transMove( SkinObject *pCtrl )
  255. {
  256.     CtrlText *pThis = (CtrlText*)pCtrl;
  257.     EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
  258.     // Do nothing if the text fits in the control
  259.     if( pThis->m_pImg &&
  260.         pThis->m_pImg->getWidth() >= pThis->getPosition()->getWidth() )
  261.     {
  262.         // The current image may have been set incorrectly in displayText(), so
  263.         // we set the correct value
  264.         pThis->m_pCurrImg = pThis->m_pImgDouble;
  265.         // Compute the new position of the left side, and make sure it is
  266.         // in the correct range
  267.         pThis->m_xPos = (pEvtMouse->getXPos() - pThis->m_xOffset);
  268.         pThis->adjust( pThis->m_xPos );
  269.         pThis->notifyLayout();
  270.     }
  271. }
  272. void CtrlText::updateText( SkinObject *pCtrl )
  273. {
  274.     CtrlText *pThis = (CtrlText*)pCtrl;
  275.     pThis->m_xPos -= MOVING_TEXT_STEP;
  276.     pThis->adjust( pThis->m_xPos );
  277.     pThis->notifyLayout();
  278. }
  279. void CtrlText::adjust( int &position )
  280. {
  281.     // {m_pImgDouble->getWidth()  - m_pImg->getWidth()} is the period of the
  282.     // bitmap; remember that the string used to generate m_pImgDouble is of the
  283.     // form: "foo  foo", the number of spaces being a parameter
  284.     if( !m_pImg )
  285.     {
  286.         return;
  287.     }
  288.     position %= m_pImgDouble->getWidth() - m_pImg->getWidth();
  289.     if( position > 0 )
  290.     {
  291.         position -= m_pImgDouble->getWidth() - m_pImg->getWidth();
  292.     }
  293. }