]> git.sesse.net Git - vlc/commitdiff
Improvements to playtree
authorClément Stenac <zorglub@videolan.org>
Sun, 4 Dec 2005 15:35:28 +0000 (15:35 +0000)
committerClément Stenac <zorglub@videolan.org>
Sun, 4 Dec 2005 15:35:28 +0000 (15:35 +0000)
* Don't expand nodes by default
* Distinguish notification types from document to view
  ( update of one item, global change, append of one item)
* Handle item-append
   - Add a command/callback
   - TODO: Only rebuild the tree image if the newly appended item is
     visible
* Rename m_lastPos to m_firstPos as it represents the first position
* Beginning of a general ensureVisible function (not working yet)

modules/gui/skins2/commands/cmd_vars.cpp
modules/gui/skins2/commands/cmd_vars.hpp
modules/gui/skins2/controls/ctrl_tree.cpp
modules/gui/skins2/controls/ctrl_tree.hpp
modules/gui/skins2/src/vlcproc.cpp
modules/gui/skins2/src/vlcproc.hpp
modules/gui/skins2/utils/var_tree.cpp
modules/gui/skins2/utils/var_tree.hpp
modules/gui/skins2/vars/playtree.cpp
modules/gui/skins2/vars/playtree.hpp

index a3aa46cf42ab34356627c1bca4727cdb2e328e74..ba3154643a3846d8b06e68c3def496f06d56c0c2 100644 (file)
@@ -48,7 +48,7 @@ void CmdPlaytreeUpdate::execute()
 {
     // Notify  the playtree variable
     Playtree &rVar = VlcProc::instance( getIntf() )->getPlaytreeVar();
-    rVar.onUpdate( m_id );
+    rVar.onUpdateItem( m_id );
 }
 
 bool CmdPlaytreeUpdate::checkRemove( CmdGeneric *pQueuedCommand ) const
@@ -64,6 +64,13 @@ bool CmdPlaytreeUpdate::checkRemove( CmdGeneric *pQueuedCommand ) const
 }
 
 
+void CmdPlaytreeAppend::execute()
+{
+    // Notify  the playtree variable
+    Playtree &rVar = VlcProc::instance( getIntf() )->getPlaytreeVar();
+    rVar.onAppend( m_pAdd );
+}
+
 void CmdSetText::execute()
 {
     // Change the text variable
index 9a30fe11b04d06667b9373327e0d1ad7cc53ff81..4983c8721f68d3a53ac91e522f9c8d92d0cb7f05 100644 (file)
@@ -59,6 +59,24 @@ class CmdPlaytreeUpdate: public CmdGeneric
         int m_id;
 };
 
+/// Command to notify the playtree of an item append
+class CmdPlaytreeAppend: public CmdGeneric
+{
+    public:
+        CmdPlaytreeAppend( intf_thread_t *pIntf, playlist_add_t *p_add ) :
+            CmdGeneric( pIntf ), m_pAdd( p_add ) {}
+        virtual ~CmdPlaytreeAppend() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "playtree append"; }
+
+    private:
+        playlist_add_t * m_pAdd;
+};
+
 
 /// Command to set a text variable
 class CmdSetText: public CmdGeneric
index 3dce075d2f7fceed7d1055834a1786b19f69334f..6e6d2fe35c74a24438624fe8b2d8d115689c4abf 100644 (file)
@@ -67,7 +67,7 @@ CtrlTree::CtrlTree( intf_thread_t *pIntf,
     m_rTree.addObserver( this );
     m_rTree.getPositionVar().addObserver( this );
 
-    m_lastPos = m_rTree.begin();
+    m_firstPos = m_rTree.begin();
 
     makeImage();
 }
@@ -130,10 +130,26 @@ int CtrlTree::maxItems()
 }
 
 
-void CtrlTree::onUpdate( Subject<VarTree, int> &rTree,  int arg )
+void CtrlTree::onUpdate( Subject<VarTree, tree_update*> &rTree,
+                         tree_update *arg )
 {
-    fprintf( stderr, "Doing update type %i\n", arg );
-    autoScroll();
+    if( arg->i_type == 0 ) // Item update
+    {
+        autoScroll();
+        makeImage();
+    }
+    else if ( arg->i_type == 1 ) // Global change or deletion
+    {
+        makeImage();
+    }
+    else if ( arg->i_type == 2 ) // Item-append
+    {
+        /* TODO: Check if the item should be visible. If it is, makeImage
+         * Else, do nothing
+         */
+        makeImage();
+    }
+    notifyLayout();
     m_pLastSelected = NULL;
 }
 
@@ -153,10 +169,10 @@ void CtrlTree::onUpdate( Subject<VarPercent, void*> &rPercent, void* arg)
 #endif
         it = m_rTree.getVisibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1);
     }
-    if( m_lastPos != it )
+    if( m_firstPos != it )
     {
         // Redraw the control if the position has changed
-        m_lastPos = it;
+        m_firstPos = it;
         makeImage();
         notifyLayout();
     }
@@ -164,7 +180,7 @@ void CtrlTree::onUpdate( Subject<VarPercent, void*> &rPercent, void* arg)
 
 void CtrlTree::onResize()
 {
-// FIXME : shouldn't be the same as the onUpdate function ... but i'm lazy
+    // FIXME : shouldn't be the same as the onUpdate function ... but i'm lazy
     // Determine what is the first item to display
     VarTree::Iterator it = m_rTree.begin();
 
@@ -180,34 +196,9 @@ void CtrlTree::onResize()
         it = m_rTree.getVisibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1);
     }
     // Redraw the control if the position has changed
-    m_lastPos = it;
+    m_firstPos = it;
     makeImage();
     notifyLayout();
-#if 0
-    // Determine what is the first item to display
-    VarTree::Iterator it = m_rTree.begin();
-
-    int excessItems = m_rTree.visibleItems() - maxItems();
-
-    if( excessItems > 0)
-    {
-        /* FIXME VarPercent &rVarPos = m_rTree.getPositionVar();
-        double newVal = 1.0 - (double)m_lastPos / excessItems;
-        if( newVal >= 0 )
-        {
-            // Change the position to keep the same first displayed item
-            rVarPos.set( 1.0 - (double)m_lastPos / excessItems );
-        }
-        else
-        {
-            // We cannot keep the current first item
-            m_lastPos = excessItems;
-        }*/
-        it = m_rTree.getVisibleItem( excessItems );
-    }
-    makeImage();
-    notifyLayout();
-#endif
 }
 
 void CtrlTree::onPositionChange()
@@ -241,6 +232,7 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
                         m_pLastSelected = &*it;
                     }
                 }
+                //ensureVisible( it );
             }
             else if( key == KEY_DOWN )
             {
@@ -260,6 +252,7 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
                 {
                     previousWasSelected = ( &*it == m_pLastSelected );
                 }
+                //ensureVisible( it );
             }
             else if( key == KEY_RIGHT )
             {
@@ -468,47 +461,66 @@ void CtrlTree::draw( OSGraphics &rImage, int xDest, int yDest )
     }
 }
 
-void CtrlTree::autoScroll()
+bool CtrlTree::ensureVisible( VarTree::Iterator item )
 {
-    // Find the current playing stream
-    int playIndex = 0;
+    // Find the item to focus
+    int focusItemIndex = 0;
     VarTree::Iterator it;
     for( it = m_rTree.begin(); it != m_rTree.end();
          it = m_rTree.getNextVisibleItem( it ) )
     {
         if( it->m_playing ) break;
-        playIndex++;
+        focusItemIndex++;
     }
+   return  ensureVisible( focusItemIndex );
+}
 
-    if( it == m_rTree.end() ) return;
-
-    // Find  m_lastPos
-    int lastPosIndex = 0;
+bool CtrlTree::ensureVisible( int focusItemIndex )
+{
+    // Find  m_firstPos
+    VarTree::Iterator it;
+    int firstPosIndex = 0;
     for( it = m_rTree.begin(); it != m_rTree.end();
          it = m_rTree.getNextVisibleItem( it ) )
     {
-        if( it == m_lastPos ) break;
-        lastPosIndex++;
+        if( it == m_firstPos ) break;
+        firstPosIndex++;
     }
 
-    if( it == m_rTree.end() ) return;
+    if( it == m_rTree.end() ) return false;
 
 
     if( it != m_rTree.end()
-        && ( playIndex < lastPosIndex
-           || playIndex > lastPosIndex + maxItems() ) )
+        && ( focusItemIndex < firstPosIndex
+           || focusItemIndex > firstPosIndex + maxItems() ) )
     {
         // Scroll to have the playing stream visible
         VarPercent &rVarPos = m_rTree.getPositionVar();
-        rVarPos.set( 1.0 - (double)playIndex / (double)m_rTree.visibleItems() );
+        rVarPos.set( 1.0 - (double)focusItemIndex /
+                           (double)m_rTree.visibleItems() );
+        return true;
     }
-    else
+    return false;
+}
+
+void CtrlTree::autoScroll()
+{
+    // Find the current playing stream
+    int playIndex = 0;
+    VarTree::Iterator it;
+    for( it = m_rTree.begin(); it != m_rTree.end();
+         it = m_rTree.getNextVisibleItem( it ) )
     {
-        makeImage();
-        notifyLayout();
+        if( it->m_playing ) break;
+        playIndex++;
     }
+
+    if( it == m_rTree.end() ) return;
+
+    ensureVisible( playIndex );
 }
 
+
 void CtrlTree::makeImage()
 {
     if( m_pImage )
@@ -531,7 +543,7 @@ void CtrlTree::makeImage()
     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
     m_pImage = pOsFactory->createOSGraphics( width, height );
 
-    VarTree::Iterator it = m_lastPos;
+    VarTree::Iterator it = m_firstPos;
 
     if( m_pBgBitmap )
     {
@@ -579,7 +591,7 @@ void CtrlTree::makeImage()
     int bitmapWidth = itemImageWidth();
 
     int yPos = 0;
-    it = m_lastPos;
+    it = m_firstPos;
     while( it != m_rTree.end() && yPos < height )
     {
         const GenericBitmap *m_pCurBitmap;
@@ -628,14 +640,17 @@ void CtrlTree::makeImage()
         }
         it = m_rTree.getNextVisibleItem( it );
     }
+    /* TODO: Reposition percentage var to accomodate if it's not suitable anymore
+     * (if we expanded a node)
+     */
 }
 
 VarTree::Iterator CtrlTree::findItemAtPos( int pos )
 {
-    // The first item is m_lastPos.
+    // The first item is m_firstPos.
     // We decrement pos as we try the other items, until pos == 0.
     VarTree::Iterator it;
-    for( it = m_lastPos; it != m_rTree.end() && pos != 0;
+    for( it = m_firstPos; it != m_rTree.end() && pos != 0;
          it = m_rTree.getNextVisibleItem( it ) )
     {
         pos--;
@@ -643,4 +658,3 @@ VarTree::Iterator CtrlTree::findItemAtPos( int pos )
 
     return it;
 }
-
index e8f13f5ee0143eee9defbd8bfe566601f581c48d..03e9fffa12d699d3cabee33d01297fa1d36bf45e 100644 (file)
@@ -33,7 +33,7 @@ class GenericFont;
 class GenericBitmap;
 
 /// Class for control tree
-class CtrlTree: public CtrlGeneric, public Observer<VarTree, int>,
+class CtrlTree: public CtrlGeneric, public Observer<VarTree, tree_update*>,
     public Observer<VarPercent, void*>
 {
     public:
@@ -71,6 +71,16 @@ class CtrlTree: public CtrlGeneric, public Observer<VarTree, int>,
         /// Get the type of control (custom RTTI)
         virtual string getType() const { return "tree"; }
 
+        /// Make sure an item is visible
+        /// \param item an iterator to a tree item
+        /// \return true if it changed the position
+        bool CtrlTree::ensureVisible( VarTree::Iterator item );
+
+        /// Make sure an item is visible
+        /// \param itemIndex the absolute index in the tree
+        /// \return true if it changed the position
+        bool CtrlTree::ensureVisible( int itemIndex );
+
     private:
         /// Tree associated to the control
         VarTree &m_rTree;
@@ -98,11 +108,12 @@ class CtrlTree: public CtrlGeneric, public Observer<VarTree, int>,
         VarTree *m_pLastSelected;
         /// Image of the control
         OSGraphics *m_pImage;
-        /// Last position
-        VarTree::Iterator m_lastPos;
+        /// First item in the visible area
+        VarTree::Iterator m_firstPos;
 
         /// Method called when the tree variable is modified
-        virtual void onUpdate( Subject<VarTree, int> &rTree , int);
+        virtual void onUpdate( Subject<VarTree, tree_update*> &rTree ,
+                               tree_update *);
 
         // Method called when the position variable of the tree is modified
         virtual void onUpdate( Subject<VarPercent, void *> &rPercent , void *);
index 504e480c8b25e4d3eab7d252d23db719b2fdc02b..6b6bd198872d5cb162f28e715eac2ffb16892e8f 100644 (file)
@@ -122,9 +122,8 @@ VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ),
     var_AddCallback( pIntf->p_sys->p_playlist, "intf-change",
                      onIntfChange, this );
     // Called when a playlist item is added
-    // TODO: properly handle item-append
     var_AddCallback( pIntf->p_sys->p_playlist, "item-append",
-                     onIntfChange, this );
+                     onItemAppend, this );
     // Called when a playlist item is deleted
     // TODO: properly handle item-deleted
     var_AddCallback( pIntf->p_sys->p_playlist, "item-deleted",
@@ -167,7 +166,7 @@ VlcProc::~VlcProc()
     var_DelCallback( getIntf()->p_sys->p_playlist, "intf-change",
                      onIntfChange, this );
     var_DelCallback( getIntf()->p_sys->p_playlist, "item-append",
-                     onIntfChange, this );
+                     onItemAppend, this );
     var_DelCallback( getIntf()->p_sys->p_playlist, "item-deleted",
                      onIntfChange, this );
     var_DelCallback( getIntf()->p_sys->p_playlist, "intf-show",
@@ -411,6 +410,33 @@ int VlcProc::onItemChange( vlc_object_t *pObj, const char *pVariable,
     return VLC_SUCCESS;
 }
 
+int VlcProc::onItemAppend( vlc_object_t *pObj, const char *pVariable,
+                           vlc_value_t oldVal, vlc_value_t newVal,
+                           void *pParam )
+{
+    VlcProc *pThis = (VlcProc*)pParam;
+
+    playlist_add_t *p_add = (playlist_add_t*)malloc( sizeof(
+                                                playlist_add_t ) ) ;
+
+    memcpy( p_add, newVal.p_address, sizeof( playlist_add_t ) ) ;
+
+    // Create a playlist notify command (for old style playlist)
+    CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
+
+    // Create a playtree notify command (for new style playtree)
+    CmdPlaytreeAppend *pCmdTree = new CmdPlaytreeAppend( pThis->getIntf(),
+                                                         p_add );
+
+    // Push the command in the asynchronous command queue
+    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
+    pQueue->push( CmdGenericPtr( pCmd ) );
+    pQueue->push( CmdGenericPtr( pCmdTree ), false );
+
+    return VLC_SUCCESS;
+}
+
+
 
 int VlcProc::onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
                                vlc_value_t oldVal, vlc_value_t newVal,
index 16e65804e5868e13b7ae9a3c358fa7dca18620ff..5c72ed22b020941d9f84dccbfbb8a2e52ecf11db 100644 (file)
@@ -168,6 +168,11 @@ class VlcProc: public SkinObject
                                  vlc_value_t oldVal, vlc_value_t newVal,
                                  void *pParam );
 
+        /// Callback for item-change variable
+        static int onItemAppend( vlc_object_t *pObj, const char *pVariable,
+                                 vlc_value_t oldVal, vlc_value_t newVal,
+                                 void *pParam );
+
         /// Callback for playlist-current variable
         static int onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
                                      vlc_value_t oldVal, vlc_value_t newVal,
index 2550b659179050e0c77d2b91453c6ebdd6bf8cc9..b9753c76f756b2b7e4e793342ee88e677606c2b9 100644 (file)
@@ -2,7 +2,7 @@
  * var_tree.cpp
  *****************************************************************************
  * Copyright (C) 2005 VideoLAN
- * $Id: var_bool.hpp 9934 2005-02-15 13:55:08Z courmisch $
+ * $Id$
  *
  * Authors: Antoine Cellerier <dionoea@videolan.org>
  *
@@ -28,7 +28,7 @@ const string VarTree::m_type = "tree";
 
 VarTree::VarTree( intf_thread_t *pIntf )
     : Variable( pIntf ), m_id( 0 ), m_selected( false ), m_playing( false ),
-    m_expanded( true ), m_pData( NULL ), m_pParent( NULL )
+    m_expanded( false ), m_pData( NULL ), m_pParent( NULL )
 {
     // Create the position variable
     m_cPosition = VariablePtr( new VarPercent( pIntf ) );
@@ -57,7 +57,6 @@ void VarTree::add( int id, const UStringPtr &rcString, bool selected,
 {
     m_children.push_back( VarTree( getIntf(), this, id, rcString, selected,
                                    playing, expanded, pData ) );
-    notify();
 }
 
 void VarTree::delSelected()
@@ -79,7 +78,6 @@ void VarTree::delSelected()
             it++;
         }
     }
-    notify();
 }
 
 void VarTree::clear()
index 9e9b8d3b88f7649bf4b84117184a76ac5eed0e61..de93deaa98be7913db722781bc5d58791d361981 100644 (file)
 #include "ustring.hpp"
 #include "var_percent.hpp"
 
+/// Description of an update to the tree
+typedef struct tree_update
+{
+     int i_type;
+     int i_parent;
+     int i_id;
+} tree_update;
+
 /// Tree variable
-class VarTree: public Variable, public Subject<VarTree, int>
+class VarTree: public Variable, public Subject<VarTree, tree_update*>
 {
     public:
         VarTree( intf_thread_t *pIntf );
index 66d18c832a63f38b587c6467d76953eeb7aec1d8..0f3b28267d049e93b8e153726f4293c186b0f5f3 100644 (file)
@@ -78,7 +78,9 @@ void Playtree::delSelected()
         }
     }
     buildTree();
-    notify( 1 );
+    tree_update descr;
+    descr.i_type = 1;
+    notify( &descr );
 }
 
 void Playtree::action( VarTree *pItem )
@@ -106,10 +108,12 @@ void Playtree::action( VarTree *pItem )
 void Playtree::onChange()
 {
     buildTree();
-    notify( 1 );
+    tree_update descr;
+    descr.i_type = 1;
+    notify( &descr );
 }
 
-void Playtree::onUpdate( int id )
+void Playtree::onUpdateItem( int id )
 {
     Iterator it = findById( id );
     if( it != end() )
@@ -124,8 +128,32 @@ void Playtree::onUpdate( int id )
     {
         msg_Warn(getIntf(), "Cannot find node with id %d", id );
     }
-    // TODO update only the right node
-    notify( 0 );
+    tree_update descr;
+    descr.i_type = 0;
+    notify( &descr );
+}
+
+void Playtree::onAppend( playlist_add_t *p_add )
+{
+    Iterator node = findById( p_add->i_node );
+    if( node != end() )
+    {
+        Iterator item =  findById( p_add->i_item );
+        if( item == end() )
+        {
+            playlist_item_t *p_item = playlist_ItemGetById(
+                                        m_pPlaylist, p_add->i_item );
+            if( !p_item ) return;
+            UString *pName = new UString( getIntf(), p_item->input.psz_name );
+            node->add( p_add->i_item, UStringPtr( pName ),
+                      false,false, false, p_item );
+        }
+    }
+    tree_update descr;
+    descr.i_id = p_add->i_item;
+    descr.i_parent = p_add->i_node;
+    descr.i_type = 2;
+    notify( &descr );
 }
 
 void Playtree::buildNode( playlist_item_t *pNode, VarTree &rTree )
@@ -137,7 +165,7 @@ void Playtree::buildNode( playlist_item_t *pNode, VarTree &rTree )
         rTree.add( pNode->pp_children[i]->input.i_id, UStringPtr( pName ),
                      false,
                      m_pPlaylist->status.p_item == pNode->pp_children[i],
-                     true, pNode->pp_children[i] );
+                     false, pNode->pp_children[i] );
         if( pNode->pp_children[i]->i_children )
         {
             buildNode( pNode->pp_children[i], rTree.back() );
index b7a942deca27ba30e1422e44fccad6d472668cee..0dbff10af190397eeb321cfbf608cfc936b78ee6 100644 (file)
@@ -2,7 +2,7 @@
  * playtree.hpp
  *****************************************************************************
  * Copyright (C) 2005 VideoLAN
- * $Id: playlist.hpp 8659 2004-09-07 21:16:49Z gbazin $
+ * $Id$
  *
  * Authors: Antoine Cellerier <dionoea@videolan.org>
  *
@@ -43,7 +43,10 @@ class Playtree: public VarTree
         void onChange();
 
         /// Function called to notify playlist item update
-        void onUpdate( int id );
+        void onUpdateItem( int id );
+
+        /// Function called to notify playlist item  append
+        void onAppend( playlist_add_t * );
 
     private:
         /// VLC playlist object