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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * generic_layout.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 the VideoLAN team
  5.  * $Id: dbc3cf67f56127efe61287e9449ecf353a01d099 $
  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 "generic_layout.hpp"
  25. #include "top_window.hpp"
  26. #include "os_factory.hpp"
  27. #include "os_graphics.hpp"
  28. #include "var_manager.hpp"
  29. #include "anchor.hpp"
  30. #include "../controls/ctrl_generic.hpp"
  31. #include "../controls/ctrl_video.hpp"
  32. #include "../utils/var_bool.hpp"
  33. #include <set>
  34. GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
  35.                               int minWidth, int maxWidth, int minHeight,
  36.                               int maxHeight ):
  37.     SkinObject( pIntf ), m_pWindow( NULL ), m_rect( 0, 0, width, height ),
  38.     m_minWidth( minWidth ), m_maxWidth( maxWidth ),
  39.     m_minHeight( minHeight ), m_maxHeight( maxHeight ), m_pVideoCtrlSet(),
  40.     m_visible( false ), m_pVarActive( NULL )
  41. {
  42.     // Get the OSFactory
  43.     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
  44.     // Create the graphics buffer
  45.     m_pImage = pOsFactory->createOSGraphics( width, height );
  46.     // Create the "active layout" variable and register it in the manager
  47.     m_pVarActive = new VarBoolImpl( pIntf );
  48.     VarManager::instance( pIntf )->registerVar( VariablePtr( m_pVarActive ) );
  49. }
  50. GenericLayout::~GenericLayout()
  51. {
  52.     delete m_pImage;
  53.     list<Anchor*>::const_iterator it;
  54.     for( it = m_anchorList.begin(); it != m_anchorList.end(); it++ )
  55.     {
  56.         delete *it;
  57.     }
  58. }
  59. void GenericLayout::setWindow( TopWindow *pWindow )
  60. {
  61.     m_pWindow = pWindow;
  62. }
  63. void GenericLayout::onControlCapture( const CtrlGeneric &rCtrl )
  64. {
  65.     // Just forward the request to the window
  66.     TopWindow *pWindow = getWindow();
  67.     if( pWindow )
  68.     {
  69.         pWindow->onControlCapture( rCtrl );
  70.     }
  71. }
  72. void GenericLayout::onControlRelease( const CtrlGeneric &rCtrl )
  73. {
  74.     // Just forward the request to the window
  75.     TopWindow *pWindow = getWindow();
  76.     if( pWindow )
  77.     {
  78.         pWindow->onControlRelease( rCtrl );
  79.     }
  80. }
  81. void GenericLayout::addControl( CtrlGeneric *pControl,
  82.                                 const Position &rPosition, int layer )
  83. {
  84.     if( pControl )
  85.     {
  86.         // Associate this layout to the control
  87.         pControl->setLayout( this, rPosition );
  88.         // Draw the control
  89.         pControl->draw( *m_pImage, rPosition.getLeft(), rPosition.getTop() );
  90.         // Add the control in the list.
  91.         // This list must remain sorted by layer order
  92.         list<LayeredControl>::iterator it;
  93.         for( it = m_controlList.begin(); it != m_controlList.end(); it++ )
  94.         {
  95.             if( layer < (*it).m_layer )
  96.             {
  97.                 m_controlList.insert( it, LayeredControl( pControl, layer ) );
  98.                 break;
  99.             }
  100.         }
  101.         // If this control is in front of all the previous ones
  102.         if( it == m_controlList.end() )
  103.         {
  104.             m_controlList.push_back( LayeredControl( pControl, layer ) );
  105.         }
  106.         // Check if it is a video control
  107.         if( pControl->getType() == "video" )
  108.         {
  109.             m_pVideoCtrlSet.insert( (CtrlVideo*)pControl );
  110.         }
  111.     }
  112.     else
  113.     {
  114.         msg_Dbg( getIntf(), "adding NULL control in the layout" );
  115.     }
  116. }
  117. const list<LayeredControl> &GenericLayout::getControlList() const
  118. {
  119.     return m_controlList;
  120. }
  121. void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
  122.                                      int width, int height,
  123.                                      int xOffSet, int yOffSet )
  124. {
  125.     // The size is not valid, refresh the whole layout
  126.     if( width <= 0 || height <= 0 )
  127.     {
  128.         refreshAll();
  129.         return;
  130.     }
  131.     const Position *pPos = rCtrl.getPosition();
  132.     if( pPos )
  133.     {
  134.         refreshRect( pPos->getLeft() + xOffSet,
  135.                      pPos->getTop() + yOffSet,
  136.                      width, height );
  137.     }
  138. }
  139. void GenericLayout::resize( int width, int height )
  140. {
  141.     // Update the window size
  142.     m_rect = SkinsRect( 0, 0 , width, height );
  143.     // Recreate a new image
  144.     if( m_pImage )
  145.     {
  146.         delete m_pImage;
  147.         OSFactory *pOsFactory = OSFactory::instance( getIntf() );
  148.         m_pImage = pOsFactory->createOSGraphics( width, height );
  149.     }
  150.     // Notify all the controls that the size has changed and redraw them
  151.     list<LayeredControl>::const_iterator iter;
  152.     for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
  153.     {
  154.         iter->m_pControl->onResize();
  155.     }
  156.     // Resize and refresh the associated window
  157.     TopWindow *pWindow = getWindow();
  158.     if( pWindow )
  159.     {
  160.         // Resize the window
  161.         pWindow->resize( width, height );
  162.         refreshAll();
  163.         // Change the shape of the window and redraw it
  164.         pWindow->updateShape();
  165.         refreshAll();
  166.     }
  167. }
  168. void GenericLayout::refreshAll()
  169. {
  170.     refreshRect( 0, 0, m_rect.getWidth(), m_rect.getHeight() );
  171. }
  172. void GenericLayout::refreshRect( int x, int y, int width, int height )
  173. {
  174.     // Do nothing if the layout is hidden
  175.     if( !m_visible )
  176.         return;
  177.     // Draw all the controls of the layout
  178.     list<LayeredControl>::const_iterator iter;
  179.     list<LayeredControl>::const_iterator iterVideo = m_controlList.end();
  180.     for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
  181.     {
  182.         CtrlGeneric *pCtrl = (*iter).m_pControl;
  183.         const Position *pPos = pCtrl->getPosition();
  184.         if( pPos && pCtrl->isVisible() )
  185.         {
  186.             pCtrl->draw( *m_pImage, pPos->getLeft(), pPos->getTop() );
  187.         }
  188.     }
  189.     // Refresh the associated window
  190.     TopWindow *pWindow = getWindow();
  191.     if( pWindow )
  192.     {
  193.         // Check boundaries
  194.         if( x < 0 )
  195.             x = 0;
  196.         if( y < 0)
  197.             y = 0;
  198.         if( x + width > m_rect.getWidth() )
  199.             width = m_rect.getWidth() - x;
  200.         if( y + height > m_rect.getHeight() )
  201.             height = m_rect.getHeight() - y;
  202.         // Refresh the window... but do not paint on a visible video control!
  203.         if( !m_pVideoCtrlSet.size() )
  204.         {
  205.             // No video control, we can safely repaint the rectangle
  206.             pWindow->refresh( x, y, width, height );
  207.         }
  208.         else
  209.         {
  210.             // video control(s) present, we need more calculations
  211.             computeRefresh( x, y, width, height );
  212.         }
  213.     }
  214. }
  215. class rect
  216. {
  217. public:
  218.   rect( int v_x = 0, int v_y = 0,
  219.           int v_width = 0, int v_height = 0 )
  220.      : x( v_x), y( v_y ), width( v_width), height( v_height)
  221.     {}
  222.     ~rect(){}
  223.     int x;
  224.     int y;
  225.     int width;
  226.     int height;
  227.     static bool isIncluded( rect& rect2, rect& rect1 )
  228.     {
  229.         int x1 = rect1.x;
  230.         int y1 = rect1.y;
  231.         int w1 = rect1.width;
  232.         int h1 = rect1.height;
  233.         int x2 = rect2.x;
  234.         int y2 = rect2.y;
  235.         int w2 = rect2.width;
  236.         int h2 = rect2.height;
  237.         return  x2 >= x1 && x2 < x1 + w1
  238.             &&  y2 >= y1 && y2 < y1 + h1
  239.             &&  w2 <= w1
  240.             &&  h2 <= h1;
  241.     }
  242. };
  243. void GenericLayout::computeRefresh( int x, int y, int width, int height )
  244. {
  245.     int w = width;
  246.     int h = height;
  247.     TopWindow *pWindow = getWindow();
  248.     set<int> x_set;
  249.     set<int> y_set;
  250.     vector<rect> rect_set;
  251.     x_set.insert( x + w );
  252.     y_set.insert( y + h );
  253.     // retrieve video controls being used
  254.     // and remember their rectangles
  255.     set<CtrlVideo*>::const_iterator it;
  256.     for( it = m_pVideoCtrlSet.begin(); it != m_pVideoCtrlSet.end(); it++ )
  257.     {
  258.         if( (*it)->isUsed() )
  259.         {
  260.             int xx = (*it)->getPosition()->getLeft();
  261.             int yy = (*it)->getPosition()->getTop();
  262.             int ww = (*it)->getPosition()->getWidth();
  263.             int hh = (*it)->getPosition()->getHeight();
  264.             rect r(xx, yy, ww, hh );
  265.             rect_set.push_back( r );
  266.             if( xx > x && xx < x + w )
  267.                 x_set.insert( xx );
  268.             if( xx + ww > x && xx + ww < x + w )
  269.                 x_set.insert( xx + ww );
  270.             if( yy > y && yy < y + h )
  271.                 y_set.insert( yy );
  272.             if( yy + hh > y && yy + hh < y + h )
  273.                 y_set.insert( yy + hh );
  274.         }
  275.     }
  276.     // for each subregion, test whether they are part
  277.     // of the video control(s) or not
  278.     set<int>::const_iterator it_x;
  279.     set<int>::const_iterator it_y;
  280.     int x_prev, y_prev;
  281.     for( x_prev = x, it_x = x_set.begin();
  282.          it_x != x_set.end(); x_prev = *it_x, it_x++ )
  283.     {
  284.         int x0 = x_prev;
  285.         int w0 = *it_x - x_prev;
  286.         for( y_prev = y, it_y = y_set.begin();
  287.              it_y != y_set.end(); y_prev = *it_y, it_y++ )
  288.         {
  289.             int y0 = y_prev;
  290.             int h0 = *it_y - y_prev;
  291.             rect r( x0, y0, w0, h0 );
  292.             bool b_refresh = true;
  293.             vector<rect>::iterator it;
  294.             for( it = rect_set.begin(); it != rect_set.end(); it++ )
  295.             {
  296.                 rect r_ctrl = *it;
  297.                 if( rect::isIncluded( r, r_ctrl ) )
  298.                 {
  299.                     b_refresh = false;
  300.                     break;
  301.                 }
  302.             }
  303.             // subregion is not part of a video control
  304.             // needs to be refreshed
  305.             if( b_refresh )
  306.                 pWindow->refresh( x0, y0, w0 ,h0 );
  307.         }
  308.     }
  309. }
  310. const list<Anchor*>& GenericLayout::getAnchorList() const
  311. {
  312.     return m_anchorList;
  313. }
  314. void GenericLayout::addAnchor( Anchor *pAnchor )
  315. {
  316.     m_anchorList.push_back( pAnchor );
  317. }
  318. void GenericLayout::onShow()
  319. {
  320.     m_visible = true;
  321.     refreshAll();
  322. }
  323. void GenericLayout::onHide()
  324. {
  325.     m_visible = false;
  326. }