* Playtree start. Basic functionalities work. Still needs a lot of
authorAntoine Cellerier <dionoea@videolan.org>
Sat, 20 Aug 2005 00:31:27 +0000 (00:31 +0000)
committerAntoine Cellerier <dionoea@videolan.org>
Sat, 20 Aug 2005 00:31:27 +0000 (00:31 +0000)
   work, cleaning and fixing. I'll continue this weekend.

24 files changed:
modules/gui/skins2/Modules.am
modules/gui/skins2/commands/cmd_dialogs.hpp
modules/gui/skins2/commands/cmd_playtree.cpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_playtree.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_vars.cpp
modules/gui/skins2/commands/cmd_vars.hpp
modules/gui/skins2/controls/ctrl_list.cpp
modules/gui/skins2/controls/ctrl_tree.cpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_tree.hpp [new file with mode: 0644]
modules/gui/skins2/parser/builder.cpp
modules/gui/skins2/parser/builder.hpp
modules/gui/skins2/parser/builder_data.def
modules/gui/skins2/parser/builder_data.hpp
modules/gui/skins2/parser/gen_builder.py
modules/gui/skins2/parser/interpreter.cpp
modules/gui/skins2/parser/interpreter.hpp
modules/gui/skins2/parser/skin_parser.cpp
modules/gui/skins2/src/dialogs.cpp
modules/gui/skins2/src/vlcproc.cpp
modules/gui/skins2/src/vlcproc.hpp
modules/gui/skins2/utils/var_tree.cpp [new file with mode: 0644]
modules/gui/skins2/utils/var_tree.hpp [new file with mode: 0644]
modules/gui/skins2/vars/playtree.cpp [new file with mode: 0644]
modules/gui/skins2/vars/playtree.hpp [new file with mode: 0644]

index a189dc4..6853d81 100644 (file)
@@ -20,6 +20,8 @@ SOURCES_skins2 = \
        commands/cmd_on_top.hpp \
        commands/cmd_playlist.cpp \
        commands/cmd_playlist.hpp \
+       commands/cmd_playtree.cpp \
+       commands/cmd_playtree.hpp \
        commands/cmd_minimize.cpp \
        commands/cmd_minimize.hpp \
        commands/cmd_quit.cpp \
@@ -41,6 +43,8 @@ SOURCES_skins2 = \
        controls/ctrl_image.hpp \
        controls/ctrl_list.cpp \
        controls/ctrl_list.hpp \
+       controls/ctrl_tree.cpp \
+       controls/ctrl_tree.hpp \
        controls/ctrl_move.cpp \
        controls/ctrl_move.hpp \
        controls/ctrl_resize.cpp \
@@ -153,9 +157,13 @@ SOURCES_skins2 = \
        utils/var_percent.hpp \
        utils/var_text.cpp \
        utils/var_text.hpp \
+       utils/var_tree.cpp \
+       utils/var_tree.hpp \
        \
        vars/playlist.cpp \
        vars/playlist.hpp \
+       vars/playtree.cpp \
+       vars/playtree.hpp \
        vars/time.cpp \
        vars/time.hpp \
        vars/volume.cpp \
index 03c4dbc..508e765 100644 (file)
@@ -48,6 +48,8 @@ typedef CmdDialogs<12> CmdDlgPlaylistLoad;
 typedef CmdDialogs<13> CmdDlgPlaylistSave;
 typedef CmdDialogs<14> CmdDlgDirectory;
 typedef CmdDialogs<15> CmdDlgStreamingWizard;
+typedef CmdDialogs<16> CmdDlgPlaytreeLoad;
+typedef CmdDialogs<17> CmdDlgPlaytreeSave;
 
 
 /// Generic "Open dialog" command
diff --git a/modules/gui/skins2/commands/cmd_playtree.cpp b/modules/gui/skins2/commands/cmd_playtree.cpp
new file mode 100644 (file)
index 0000000..5504e34
--- /dev/null
@@ -0,0 +1,71 @@
+/*****************************************************************************
+ * cmd_playtree.cpp
+ *****************************************************************************
+ * Copyright (C) 2005 VideoLAN
+ * $Id: cmd_playlist.cpp 10101 2005-03-02 16:47:31Z robux4 $
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_playtree.hpp"
+#include "../src/vlcproc.hpp"
+#include "../utils/var_bool.hpp"
+
+void CmdPlaytreeDel::execute()
+{
+    m_rTree.delSelected();
+}
+
+void CmdPlaytreeSort::execute()
+{
+    // TODO
+}
+
+void CmdPlaytreeNext::execute()
+{
+    // TODO
+}
+
+void CmdPlaytreePrevious::execute()
+{
+    // TODO
+}
+
+void CmdPlaytreeRandom::execute()
+{
+    // TODO
+}
+
+void CmdPlaytreeLoop::execute()
+{
+    // TODO
+}
+
+void CmdPlaytreeRepeat::execute()
+{
+    // TODO
+}
+
+void CmdPlaytreeLoad::execute()
+{
+    // TODO
+}
+
+void CmdPlaytreeSave::execute()
+{
+    // TODO
+}
diff --git a/modules/gui/skins2/commands/cmd_playtree.hpp b/modules/gui/skins2/commands/cmd_playtree.hpp
new file mode 100644 (file)
index 0000000..eb3d2a4
--- /dev/null
@@ -0,0 +1,155 @@
+/*****************************************************************************
+ * cmd_playtree.hpp
+ *****************************************************************************
+ * Copyright (C) 2005 VideoLAN
+ * $Id: cmd_playlist.hpp 9934 2005-02-15 13:55:08Z courmisch $
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_PLAYTREE_HPP
+#define CMD_PLAYTREE_HPP
+
+#include "cmd_generic.hpp"
+#include "../utils/var_tree.hpp"
+
+// TODO : implement branch specific stuff
+
+/// Command to delete the selected items from a tree
+class CmdPlaytreeDel: public CmdGeneric
+{
+    public:
+        CmdPlaytreeDel( intf_thread_t *pIntf, VarTree &rTree ):
+            CmdGeneric( pIntf ), m_rTree( rTree ) {}
+        virtual ~CmdPlaytreeDel() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "playtree del"; }
+
+    private:
+        /// Tree
+        VarTree &m_rTree;
+};
+
+/// Command to sort the playtree
+DEFINE_COMMAND( PlaytreeSort, "playtree sort" )
+
+/// Command to jump to the next item
+DEFINE_COMMAND( PlaytreeNext, "playtree next" )
+
+/// Command to jump to the previous item
+DEFINE_COMMAND( PlaytreePrevious, "playtree previous" )
+
+/// Command to set the random state
+class CmdPlaytreeRandom: public CmdGeneric
+{
+    public:
+        CmdPlaytreeRandom( intf_thread_t *pIntf, bool value ):
+            CmdGeneric( pIntf ), m_value( value ) {}
+        virtual ~CmdPlaytreeRandom() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "playtree random"; }
+
+    private:
+        /// Random state
+        bool m_value;
+};
+
+/// Command to set the loop state
+class CmdPlaytreeLoop: public CmdGeneric
+{
+    public:
+        CmdPlaytreeLoop( intf_thread_t *pIntf, bool value ):
+            CmdGeneric( pIntf ), m_value( value ) {}
+        virtual ~CmdPlaytreeLoop() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "playtree loop"; }
+
+    private:
+        /// Loop state
+        bool m_value;
+};
+
+/// Command to set the repeat state
+class CmdPlaytreeRepeat: public CmdGeneric
+{
+    public:
+        CmdPlaytreeRepeat( intf_thread_t *pIntf, bool value ):
+            CmdGeneric( pIntf ), m_value( value ) {}
+        virtual ~CmdPlaytreeRepeat() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "playtree repeat"; }
+
+    private:
+        /// Loop state
+        bool m_value;
+};
+
+/// Command to load a playlist
+class CmdPlaytreeLoad: public CmdGeneric
+{
+    public:
+        CmdPlaytreeLoad( intf_thread_t *pIntf, bool value ):
+            CmdGeneric( pIntf ), m_value( value ) {}
+        virtual ~CmdPlaytreeLoad() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "playtree load"; }
+
+    private:
+        /// Loop state
+        bool m_value;
+};
+
+/// Command to save a playlist
+class CmdPlaytreeSave: public CmdGeneric
+{
+    public:
+        CmdPlaytreeSave( intf_thread_t *pIntf, bool value ):
+            CmdGeneric( pIntf ), m_value( value ) {}
+        virtual ~CmdPlaytreeSave() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "playtree save"; }
+
+    private:
+        /// Loop state
+        bool m_value;
+};
+
+#endif
index 167ede3..f859a1a 100644 (file)
@@ -25,6 +25,7 @@
 #include "../src/vlcproc.hpp"
 #include "../utils/var_text.hpp"
 #include "../vars/playlist.hpp"
+#include "../vars/playtree.hpp"
 
 
 void CmdNotifyPlaylist::execute()
@@ -34,6 +35,13 @@ void CmdNotifyPlaylist::execute()
     rVar.onChange();
 }
 
+void CmdNotifyPlaytree::execute()
+{
+    // Notify  the playtree variable
+    Playtree &rVar = VlcProc::instance( getIntf() )->getPlaytreeVar();
+    rVar.onChange();
+}
+
 
 void CmdSetText::execute()
 {
index 2d5bb5c..ebb1429 100644 (file)
@@ -31,6 +31,8 @@ class VarText;
 
 /// Command to notify the playlist of a change
 DEFINE_COMMAND( NotifyPlaylist, "notify playlist" )
+/// Command to notify the playtree of a change
+DEFINE_COMMAND( NotifyPlaytree, "notify playtree" )
 
 
 /// Command to set a text variable
index df62b82..204164a 100644 (file)
@@ -481,8 +481,8 @@ void CtrlList::makeImage()
     int yPos = 0;
     for( it = m_rList[m_lastPos]; it != m_rList.end() && yPos < height; it++ )
     {
-        UString *pStr = (UString*)((*it).m_cString.get());
-        uint32_t color = ( (*it).m_playing ? m_playColor : m_fgColor );
+        UString *pStr = (UString*)(it->m_cString.get());
+        uint32_t color = ( it->m_playing ? m_playColor : m_fgColor );
 
         // Draw the text
         GenericBitmap *pText = m_rFont.drawString( *pStr, color, width );
diff --git a/modules/gui/skins2/controls/ctrl_tree.cpp b/modules/gui/skins2/controls/ctrl_tree.cpp
new file mode 100644 (file)
index 0000000..71afa8b
--- /dev/null
@@ -0,0 +1,509 @@
+/*****************************************************************************
+ * ctrl_tree.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_list.cpp 11009 2005-05-14 14:39:05Z ipkiss $
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <math.h>
+#include "ctrl_tree.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_graphics.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/generic_font.hpp"
+#include "../src/scaled_bitmap.hpp"
+#include "../utils/position.hpp"
+#include "../utils/ustring.hpp"
+#include "../events/evt_key.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_scroll.hpp"
+#include "vlc_keys.h"
+#ifdef sun
+#   include "solaris_specific.h" // for lrint
+#endif
+
+#define SCROLL_STEP 0.05
+#define LINE_INTERVAL 1  // Number of pixels inserted between 2 lines
+
+CtrlTree::CtrlTree( intf_thread_t *pIntf,
+                  VarTree &rTree,
+                  const GenericFont &rFont,
+                  const GenericBitmap *pBgBitmap,
+                  const GenericBitmap *pItemBitmap,
+                  const GenericBitmap *pOpenBitmap,
+                  const GenericBitmap *pClosedBitmap,
+                  uint32_t fgColor,
+                  uint32_t playColor,
+                  uint32_t bgColor1,
+                  uint32_t bgColor2,
+                  uint32_t selColor,
+                  const UString &rHelp,
+                  VarBool *pVisible ):
+    CtrlGeneric( pIntf,rHelp, pVisible), m_rTree( rTree), m_rFont( rFont ),
+    m_pBgBitmap( pBgBitmap ), m_pItemBitmap( pItemBitmap ),
+    m_pOpenBitmap( pOpenBitmap ), m_pClosedBitmap( pClosedBitmap ),
+    m_fgColor( fgColor ), m_playColor( playColor ), m_bgColor1( bgColor1 ),
+    m_bgColor2( bgColor2 ), m_selColor( selColor ),
+    m_pLastSelected( NULL ), m_pImage( NULL )
+{
+    // Observe the tree and position variables
+    m_rTree.addObserver( this );
+    m_rTree.getPositionVar().addObserver( this );
+
+    m_lastPos = m_rTree.begin();
+
+    makeImage();
+}
+
+CtrlTree::~CtrlTree()
+{
+    m_rTree.getPositionVar().delObserver( this );
+    m_rTree.delObserver( this );
+    if( m_pImage )
+    {
+        delete m_pImage;
+    }
+}
+
+int CtrlTree::itemHeight()
+{
+    int itemHeight = m_rFont.getSize();
+    if( m_pClosedBitmap )
+    {
+        itemHeight = __MAX( m_pClosedBitmap->getHeight(), itemHeight );
+    }
+    if( m_pOpenBitmap )
+    {
+        itemHeight = __MAX( m_pOpenBitmap->getHeight(), itemHeight );
+    }
+    if( m_pItemBitmap )
+    {
+        itemHeight = __MAX( m_pItemBitmap->getHeight(), itemHeight );
+    }
+    itemHeight += LINE_INTERVAL;
+    return itemHeight;
+}
+
+int CtrlTree::maxItems()
+{
+    const Position *pPos = getPosition();
+    if( !pPos )
+    {
+        return -1;
+    }
+    return pPos->getHeight() / itemHeight();
+}
+
+
+void CtrlTree::onUpdate( Subject<VarTree> &rTree )
+{
+    autoScroll();
+    m_pLastSelected = NULL;
+}
+
+void CtrlTree::onUpdate( Subject<VarPercent> &rPercent )
+{
+    // Determine what is the first item to display
+    VarTree::Iterator it = m_rTree.begin();
+
+    int excessItems = m_rTree.visibleItems() - maxItems();
+
+    if( excessItems > 0)
+    {
+        VarPercent &rVarPos = m_rTree.getPositionVar();
+        // a simple (int)(...) causes rounding errors !
+#ifdef _MSC_VER
+#   define lrint (int)
+#endif
+        it = m_rTree.visibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1); /* FIXME : shouldn't need this +1 */
+    }
+    if( m_lastPos != it )
+    {
+        // Redraw the control if the position has changed
+        m_lastPos = it;
+        makeImage();
+        notifyLayout();
+    }
+}
+
+void CtrlTree::onResize()
+{
+// 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();
+
+    int excessItems = m_rTree.visibleItems() - maxItems();
+
+    if( excessItems > 0)
+    {
+        VarPercent &rVarPos = m_rTree.getPositionVar();
+        // a simple (int)(...) causes rounding errors !
+#ifdef _MSC_VER
+#   define lrint (int)
+#endif
+        it = m_rTree.visibleItem(lrint( (1.0 - rVarPos.get()) * (double)excessItems ) + 1); /* FIXME : shouldn't need this +1 */
+    }
+    // Redraw the control if the position has changed
+    m_lastPos = 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.visibleItem( excessItems );
+    }
+    makeImage();
+    notifyLayout();
+#endif
+}
+
+void CtrlTree::onPositionChange()
+{
+    makeImage();
+    notifyLayout();
+}
+
+#define IT_DISP_LOOP_END( a )  \
+                if( a ->m_expanded && a ->size() ) \
+                { \
+                    a = a ->begin(); \
+                } \
+                else \
+                { \
+                    VarTree::Iterator it_old = a; \
+                    a ++; \
+                    if( it_old->parent() && it_old->parent()->end() == a ) \
+                    { \
+                        a = it_old->uncle(); \
+                    } \
+                }
+void CtrlTree::handleEvent( EvtGeneric &rEvent )
+{
+    // TODO TODO FIXME TODO TODO
+    if( rEvent.getAsString().find( "key:down" ) != string::npos )
+    {
+        int key = ((EvtKey&)rEvent).getKey();
+        VarTree::Iterator it = m_rTree.begin();
+        bool previousWasSelected = false;
+        while( it != m_rTree.end() )
+        {
+            VarTree::Iterator next = it;
+            IT_DISP_LOOP_END( next );
+            if( key == KEY_UP )
+            {
+                //Scroll up one item
+                if( ( it->parent()
+                      && it != it->parent()->begin() )
+                    || &*it != m_pLastSelected )
+                {
+                    bool nextWasSelected = ( &*next == m_pLastSelected );
+                    it->m_selected = nextWasSelected;
+                    if( nextWasSelected )
+                    {
+                        m_pLastSelected = &*it;
+                    }
+                }
+            }
+            else if( key == KEY_DOWN )
+            {
+                // Scroll down one item
+                if( ( it->parent()
+                      && next != it->parent()->end() )
+                    || &*it != m_pLastSelected )
+                {
+                    (*it).m_selected = previousWasSelected;
+                }
+                if( previousWasSelected )
+                {
+                    m_pLastSelected = &*it;
+                    previousWasSelected = false;
+                }
+                else
+                {
+                    previousWasSelected = ( &*it == m_pLastSelected );
+                }
+            }
+            else if( key == KEY_RIGHT )
+            {
+                // Go down one level
+                if( it->m_expanded )
+                {
+                    if( it->size() )
+                    {
+                        /* FIXME : finir */
+                        m_pLastSelected = &*(it->begin());
+                    }
+                }
+                else
+                {
+                    it->m_expanded = true;
+                }
+            }
+            else if( key == KEY_LEFT )
+            {
+                // Go up one level (and close node)
+                // TODO
+                it->m_expanded = false;
+            }
+            it = next;
+        }
+
+        // Redraw the control
+        makeImage();
+        notifyLayout();
+    }
+
+    else if( rEvent.getAsString().find( "mouse:left" ) != string::npos )
+    {
+        EvtMouse &rEvtMouse = (EvtMouse&)rEvent;
+        const Position *pos = getPosition();
+        int yPos = ( rEvtMouse.getYPos() - pos->getTop() ) / itemHeight();
+        VarTree::Iterator it;
+        int index = 0;
+
+        // TODO : add all other mouse controls
+        /**/ if( rEvent.getAsString().find( "mouse:left:down" ) !=
+                 string::npos )
+        {
+            for( it = m_lastPos; it != m_rTree.end(); )
+            {
+                if( index == yPos )
+                {
+                    it->m_selected = true;
+                    m_pLastSelected = &*it;
+                }
+                else
+                {
+                    it->m_selected = false;
+                }
+                index ++;
+                IT_DISP_LOOP_END( it );
+            }
+        }
+
+        else if( rEvent.getAsString().find( "mouse:left:dblclick" ) !=
+                 string::npos )
+        {
+            for( it = m_lastPos; it != m_rTree.end(); )
+            {
+                if( index == yPos )
+                {
+                    it->m_selected = true;
+                    m_pLastSelected = &*it;
+                    // Execute the action associated to this item
+                    m_rTree.action( &*it );
+                }
+                else
+                {
+                    it->m_selected = false;
+                }
+                index ++;
+                IT_DISP_LOOP_END( it );
+            }
+        }
+
+        // Redraw the control
+        makeImage();
+        notifyLayout();
+    }
+
+    else if( rEvent.getAsString().find( "scroll" ) != string::npos )
+    {
+        int direction = ((EvtScroll&)rEvent).getDirection();
+
+        double percentage = m_rTree.getPositionVar().get();
+        if( direction == EvtScroll::kUp )
+        {
+            percentage += SCROLL_STEP;
+        }
+        else
+        {
+            percentage -= SCROLL_STEP;
+        }
+        m_rTree.getPositionVar().set( percentage );
+    }
+}
+
+bool CtrlTree::mouseOver( int x, int y ) const
+{
+    const Position *pPos = getPosition();
+    return ( pPos
+       ? x >= 0 && x <= pPos->getWidth() && y >= 0 && y <= pPos->getHeight()
+       : false);
+}
+
+void CtrlTree::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    if( m_pImage )
+    {
+        rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
+    }
+}
+
+void CtrlTree::autoScroll()
+{
+    // TODO FIXME TODO
+    makeImage();
+    notifyLayout();
+}
+
+void CtrlTree::makeImage()
+{
+    if( m_pImage )
+    {
+        delete m_pImage;
+    }
+
+    // Get the size of the control
+    const Position *pPos = getPosition();
+    if( !pPos )
+    {
+        return;
+    }
+    int width = pPos->getWidth();
+    int height = pPos->getHeight();
+
+    int i_itemHeight = itemHeight();
+
+    // Create an image
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+    m_pImage = pOsFactory->createOSGraphics( width, height );
+
+    VarTree::Iterator it = m_lastPos;
+
+    if( m_pBgBitmap )
+    {
+        // Draw the background bitmap
+        ScaledBitmap bmp( getIntf(), *m_pBgBitmap, width, height );
+        m_pImage->drawBitmap( bmp, 0, 0 );
+
+        // FIXME : Take care of the selection color
+        for( int yPos = 0; yPos < height; yPos += i_itemHeight )
+        {
+            int rectHeight = __MIN( i_itemHeight, height - yPos );
+            if( it != m_rTree.end() )
+            {
+                if( (*it).m_selected )
+                {
+                    m_pImage->fillRect( 0, yPos, width, rectHeight,
+                                        m_selColor );
+                }
+                IT_DISP_LOOP_END( it );
+            }
+        }
+    }
+    else
+    {
+        // FIXME (TRYME)
+        // Fill background with background color
+        uint32_t bgColor = m_bgColor1;
+        m_pImage->fillRect( 0, 0, width, height, bgColor );
+        for( int yPos = 0; yPos < height; yPos += i_itemHeight )
+        {
+            int rectHeight = __MIN( i_itemHeight, height - yPos );
+            if( it != m_rTree.end() )
+            {
+                uint32_t color = ( it->m_selected ? m_selColor : bgColor );
+                m_pImage->fillRect( 0, yPos, width, rectHeight, color );
+                IT_DISP_LOOP_END( it );
+            }
+            else
+            {
+                m_pImage->fillRect( 0, yPos, width, rectHeight, bgColor );
+            }
+            bgColor = ( bgColor == m_bgColor1 ? m_bgColor2 : m_bgColor1 );
+        }
+    }
+//    fprintf( stderr, "done\n");
+
+    int bitmapWidth = 5;
+    if( m_pClosedBitmap )
+    {
+        bitmapWidth = __MAX( m_pClosedBitmap->getWidth(), bitmapWidth );
+    }
+    if( m_pOpenBitmap )
+    {
+        bitmapWidth = __MAX( m_pOpenBitmap->getWidth(), bitmapWidth );
+    }
+    if( m_pItemBitmap )
+    {
+        bitmapWidth = __MAX( m_pItemBitmap->getWidth(), bitmapWidth );
+    }
+    bitmapWidth += 2;
+
+    // FIXME : Draw the items
+    int yPos = 0;
+    it = m_lastPos;
+    while( it != m_rTree.end() && yPos < height )
+    {
+        const GenericBitmap *m_pCurBitmap;
+        UString *pStr = (UString*)(it->m_cString.get());
+        uint32_t color = ( it->m_playing ? m_playColor : m_fgColor );
+        // Draw the text
+        if( pStr != NULL ){
+            int depth = it->depth();
+            GenericBitmap *pText = m_rFont.drawString( *pStr, color, width - bitmapWidth * depth );
+            if( !pText )
+            {
+                return;
+            }
+            m_pCurBitmap = it->size() ? ( it->m_expanded ? m_pOpenBitmap : m_pClosedBitmap ) : m_pItemBitmap ;
+            if( m_pCurBitmap )
+            {
+                int yPos2 = yPos+(i_itemHeight-m_pCurBitmap->getHeight()+1)/2;
+                m_pImage->drawBitmap( *m_pCurBitmap, 0, 0, bitmapWidth * (depth - 1 ), yPos2, m_pCurBitmap->getWidth(), __MIN( m_pCurBitmap->getHeight(), height -  yPos2), true );
+            }
+            else
+            {
+                /* it would be nice to draw something */
+            }
+            yPos += i_itemHeight - pText->getHeight();
+            int ySrc = 0;
+            if( yPos < 0 )
+            {
+                ySrc = - yPos;
+                yPos = 0;
+            }
+            int lineHeight =  __MIN( pText->getHeight() - ySrc, height - yPos );
+            m_pImage->drawBitmap( *pText, 0, ySrc, bitmapWidth * depth, yPos,
+                                  pText->getWidth(),
+                                  lineHeight, true );
+            yPos += (pText->getHeight() - ySrc );
+            delete pText;
+        }
+        IT_DISP_LOOP_END( it );
+    }
+}
diff --git a/modules/gui/skins2/controls/ctrl_tree.hpp b/modules/gui/skins2/controls/ctrl_tree.hpp
new file mode 100644 (file)
index 0000000..50aa48e
--- /dev/null
@@ -0,0 +1,126 @@
+/*****************************************************************************
+ * ctrl_tree.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_list.hpp 11009 2005-05-14 14:39:05Z ipkiss $
+ *
+ * Authors: Antoine Cellerier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_TREE_HPP
+#define CTRL_TREE_HPP
+
+#include "ctrl_generic.hpp"
+#include "../utils/observer.hpp"
+#include "../utils/var_tree.hpp"
+
+class OSGraphics;
+class GenericFont;
+class GenericBitmap;
+
+/// Class for control tree
+class CtrlTree: public CtrlGeneric, public Observer<VarTree>,
+    public Observer<VarPercent>
+{
+    public:
+        CtrlTree( intf_thread_t *pIntf,
+                  VarTree &rTree,
+                  const GenericFont &rFont,
+                  const GenericBitmap *pBgBitmap,
+                  const GenericBitmap *pItemBitmap,
+                  const GenericBitmap *pOpenBitmap,
+                  const GenericBitmap *pClosedBitmap,
+                  uint32_t fgColor,
+                  uint32_t playColor,
+                  uint32_t bgColor1,
+                  uint32_t bgColor2,
+                  uint32_t selColor,
+                  const UString &rHelp,
+                  VarBool *pVisible );
+        virtual ~CtrlTree();
+
+        /// Handle an event on the control
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+        /// Called when the layout is resized
+        virtual void onResize();
+
+        /// Return true if the control can gain the focus
+        virtual bool isFocusable() const { return true; }
+
+        /// Get the type of control (custom RTTI)
+        virtual string getType() const { return "tree"; }
+
+    private:
+        /// Tree associated to the control
+        VarTree &m_rTree;
+        /// Font
+        const GenericFont &m_rFont;
+        /// Background bitmap
+        const GenericBitmap *m_pBgBitmap;
+        /// Item (leaf) bitmap
+        // (TODO : add different bitmaps for different item types
+        //         like in the wx playlist)
+        const GenericBitmap *m_pItemBitmap;
+        /// Open (expanded) node bitmap
+        const GenericBitmap *m_pOpenBitmap;
+        /// Closed node bitmap
+        const GenericBitmap *m_pClosedBitmap;
+        /// Color of normal test
+        uint32_t m_fgColor;
+        /// Color of the playing item
+        uint32_t m_playColor;
+        /// Background colors, used when no background bitmap is given
+        uint32_t m_bgColor1, m_bgColor2;
+        /// Background of selected items
+        uint32_t m_selColor;
+        /// Pointer on the last selected item in the tree
+        VarTree *m_pLastSelected;
+        /// Image of the control
+        OSGraphics *m_pImage;
+        /// Last position
+        VarTree::Iterator m_lastPos;
+
+        /// Method called when the tree variable is modified
+        virtual void onUpdate( Subject<VarTree> &rTree );
+
+        // Method called when the position variable of the tree is modified
+        virtual void onUpdate( Subject<VarPercent> &rPercent );
+
+        /// Called when the position is set
+        virtual void onPositionChange();
+
+        /// Compute the number of lines that can be displayed
+        int maxItems();
+
+        /// Compute the item's height (depends on fonts and images used)
+        int itemHeight();
+
+        /// Check if the tree must be scrolled
+        void autoScroll();
+
+        /// Draw the image of the control
+        void makeImage();
+};
+
+#endif
index 50f929f..c8a68e3 100644 (file)
@@ -43,6 +43,7 @@
 #include "../controls/ctrl_slider.hpp"
 #include "../controls/ctrl_radialslider.hpp"
 #include "../controls/ctrl_text.hpp"
+#include "../controls/ctrl_tree.hpp"
 #include "../controls/ctrl_video.hpp"
 #include "../utils/position.hpp"
 #include "../utils/var_bool.hpp"
@@ -101,6 +102,7 @@ Theme *Builder::build()
     ADD_OBJECTS( RadialSlider );
     ADD_OBJECTS( Slider );
     ADD_OBJECTS( List );
+    ADD_OBJECTS( Tree );
     ADD_OBJECTS( Video );
 
     return m_pTheme;
@@ -628,6 +630,62 @@ void Builder::addList( const BuilderData::List &rData )
     m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pList );
 }
 
+void Builder::addTree( const BuilderData::Tree &rData )
+{
+    // Get the bitmaps, if any
+    GenericBitmap *pBgBmp = NULL;
+    GenericBitmap *pItemBmp = NULL;
+    GenericBitmap *pOpenBmp = NULL;
+    GenericBitmap *pClosedBmp = NULL;
+    GET_BMP( pBgBmp, rData.m_bgImageId );
+    GET_BMP( pItemBmp, rData.m_itemImageId );
+    GET_BMP( pOpenBmp, rData.m_openImageId );
+    GET_BMP( pClosedBmp, rData.m_closedImageId );
+
+    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    if( pLayout == NULL )
+    {
+        msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
+        return;
+    }
+
+    GenericFont *pFont = getFont( rData.m_fontId );
+    if( pFont == NULL )
+    {
+        msg_Err( getIntf(), "Unknown font id: %s", rData.m_fontId.c_str() );
+        return;
+    }
+
+    // Get the list variable
+    Interpreter *pInterpreter = Interpreter::instance( getIntf() );
+    VarTree *pVar = pInterpreter->getVarTree( rData.m_var, m_pTheme );
+    if( pVar == NULL )
+    {
+        msg_Err( getIntf(), "No such list variable: %s", rData.m_var.c_str() );
+        return;
+    }
+
+    // Get the visibility variable
+    // XXX check when it is null
+    VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
+
+    // Create the list control
+    CtrlTree *pTree = new CtrlTree( getIntf(), *pVar, *pFont, pBgBmp,
+       pItemBmp, pOpenBmp, pClosedBmp,
+       rData.m_fgColor, rData.m_playColor, rData.m_bgColor1,
+       rData.m_bgColor2, rData.m_selColor,
+       UString( getIntf(), rData.m_help.c_str() ), pVisible );
+
+    // Compute the position of the control
+    const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
+                                       rData.m_xPos, rData.m_yPos,
+                                       rData.m_width, rData.m_height,
+                                       *pLayout );
+
+    pLayout->addControl( pTree, pos, rData.m_layer );
+
+    m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pTree );
+}
 
 void Builder::addVideo( const BuilderData::Video &rData )
 {
index 999c46e..84023fb 100644 (file)
@@ -77,6 +77,7 @@ class Builder: public SkinObject
         void addRadialSlider( const BuilderData::RadialSlider &rData );
         void addSlider( const BuilderData::Slider &rData );
         void addList( const BuilderData::List &rData );
+        void addTree( const BuilderData::Tree &rData );
         void addVideo( const BuilderData::Video &rData );
 
        /// Compute the position of a control
index 89f4dc8..146f534 100644 (file)
@@ -12,4 +12,5 @@ Text id:string xPos:int yPos:int visible:string fontId:string text:string width:
 RadialSlider id:string visible:string xPos:int yPos:int leftTop:string rightBottom:string sequence:string nbImages:int minAngle:float maxAngle:float value:string tooltip:string help:string layer:int windowId:string layoutId:string
 Slider id:string visible:string xPos:int yPos:int leftTop:string rightBottom:string upId:string downId:string overId:string points:string thickness:int value:string tooltip:string help:string layer:int windowId:string layoutId:string
 List id:string xPos:int yPos:int visible:string width:int height:int leftTop:string rightBottom:string fontId:string var:string bgImageId:string fgColor:uint32_t playColor:uint32_t bgColor1:uint32_t bgColor2:uint32_t selColor:uint32_t help:string layer:int windowId:string layoutId:string
+Tree id:string xPos:int yPos:int visible:string width:int height:int leftTop:string rightBottom:string fontId:string var:string bgImageId:string itemImageId:string openImageId:string closedImageId:string fgColor:uint32_t playColor:uint32_t bgColor1:uint32_t bgColor2:uint32_t selColor:uint32_t help:string layer:int windowId:string layoutId:string
 Video id:string xPos:int yPos:int width:int height:int leftTop:string rightBottom:string visible:string help:string layer:int windowId:string layoutId:string
index 1fef25e..2470615 100644 (file)
@@ -5,7 +5,7 @@
  * $Id$
  *
  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
- *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          Olivier Teuliere <ipkiss@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -328,6 +328,39 @@ m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_visible( visible ), m_width( width
     /// List
     list<List> m_listList;
 
+    /// Type definition
+    struct Tree
+    {
+        Tree( const string & id, int xPos, int yPos, const string & visible, int width, int height, const string & leftTop, const string & rightBottom, const string & fontId, const string & var, const string & bgImageId, const string & itemImageId, const string & openImageId, const string & closedImageId, uint32_t fgColor, uint32_t playColor, uint32_t bgColor1, uint32_t bgColor2, uint32_t selColor, const string & help, int layer, const string & windowId, const string & layoutId ):
+m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_visible( visible ), m_width( width ), m_height( height ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_fontId( fontId ), m_var( var ), m_bgImageId( bgImageId ), m_itemImageId( itemImageId ), m_openImageId( openImageId ), m_closedImageId( closedImageId ), m_fgColor( fgColor ), m_playColor( playColor ), m_bgColor1( bgColor1 ), m_bgColor2( bgColor2 ), m_selColor( selColor ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ) {}
+
+        const string m_id;
+        int m_xPos;
+        int m_yPos;
+        const string m_visible;
+        int m_width;
+        int m_height;
+        const string m_leftTop;
+        const string m_rightBottom;
+        const string m_fontId;
+        const string m_var;
+        const string m_bgImageId;
+        const string m_itemImageId;
+        const string m_openImageId;
+        const string m_closedImageId;
+        uint32_t m_fgColor;
+        uint32_t m_playColor;
+        uint32_t m_bgColor1;
+        uint32_t m_bgColor2;
+        uint32_t m_selColor;
+        const string m_help;
+        int m_layer;
+        const string m_windowId;
+        const string m_layoutId;
+    };
+    /// List
+    list<Tree> m_listTree;
+
     /// Type definition
     struct Video
     {
index c4d90ce..ad7614a 100755 (executable)
@@ -18,7 +18,7 @@ hppfile.write(
  * $Id$
  *
  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
- *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          Olivier Teuliere <ipkiss@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 33cb53c..b97a423 100644 (file)
@@ -26,6 +26,7 @@
 #include "expr_evaluator.hpp"
 #include "../commands/cmd_muxer.hpp"
 #include "../commands/cmd_playlist.hpp"
+#include "../commands/cmd_playtree.hpp"
 #include "../commands/cmd_dialogs.hpp"
 #include "../commands/cmd_dummy.hpp"
 #include "../commands/cmd_layout.hpp"
@@ -79,6 +80,27 @@ Interpreter::Interpreter( intf_thread_t *pIntf ): SkinObject( pIntf )
         CmdGenericPtr( new CmdPlaylistRepeat( getIntf(), true ) );
     m_commandMap["playlist.setRepeat(false)"] =
         CmdGenericPtr( new CmdPlaylistRepeat( getIntf(), false ) );
+    REGISTER_CMD( "playtree.load()", CmdDlgPlaytreeLoad )
+    REGISTER_CMD( "playtree.save()", CmdDlgPlaytreeSave )
+    REGISTER_CMD( "playtree.add()", CmdDlgAdd )
+    VarTree &rVarTree = VlcProc::instance( getIntf() )->getPlaytreeVar();
+    m_commandMap["playtree.del()"] =
+        CmdGenericPtr( new CmdPlaytreeDel( getIntf(), rVarTree ) );
+    REGISTER_CMD( "playtree.next()", CmdPlaytreeNext )
+    REGISTER_CMD( "playtree.previous()", CmdPlaytreePrevious )
+    REGISTER_CMD( "playtree.sort()", CmdPlaytreeSort )
+    m_commandMap["playtree.setRandom(true)"] =
+        CmdGenericPtr( new CmdPlaytreeRandom( getIntf(), true ) );
+    m_commandMap["playtree.setRandom(false)"] =
+        CmdGenericPtr( new CmdPlaytreeRandom( getIntf(), false ) );
+    m_commandMap["playtree.setLoop(true)"] =
+        CmdGenericPtr( new CmdPlaytreeLoop( getIntf(), true ) );
+    m_commandMap["playtree.setLoop(false)"] =
+        CmdGenericPtr( new CmdPlaytreeLoop( getIntf(), false ) );
+    m_commandMap["playtree.setRepeat(true)"] =
+        CmdGenericPtr( new CmdPlaytreeRepeat( getIntf(), true ) );
+    m_commandMap["playtree.setRepeat(false)"] =
+        CmdGenericPtr( new CmdPlaytreeRepeat( getIntf(), false ) );
     REGISTER_CMD( "vlc.fullscreen()", CmdFullscreen )
     REGISTER_CMD( "vlc.play()", CmdPlay )
     REGISTER_CMD( "vlc.pause()", CmdPause )
@@ -362,3 +384,10 @@ VarList *Interpreter::getVarList( const string &rName, Theme *pTheme )
     return pVar;
 }
 
+VarTree *Interpreter::getVarTree( const string &rName, Theme *pTheme )
+{
+    // Try to get the variable from the variable manager
+    VarManager *pVarManager = VarManager::instance( getIntf() );
+    VarTree *pVar = (VarTree*)pVarManager->getVar( rName, "tree" );
+    return pVar;
+}
index 572ddbe..30b9177 100644 (file)
@@ -31,6 +31,7 @@
 class Theme;
 class VarBool;
 class VarList;
+class VarTree;
 class VarPercent;
 
 
@@ -59,6 +60,9 @@ class Interpreter: public SkinObject
         /// Returns the list variable corresponding to the given name
         VarList *getVarList( const string &rName, Theme *pTheme );
 
+        /// Returns the tree variable corresponding to the given name
+        VarTree *getVarTree( const string &rName, Theme *pTheme );
+
     private:
         /// Map of global commands
         map<string, CmdGenericPtr> m_commandMap;
index 00f91dd..64553bb 100644 (file)
@@ -239,6 +239,46 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
         m_data.m_listList.push_back( listData );
     }
 
+    else if( rName == "Playtree" )
+    {
+        RequireDefault( "id" );
+        RequireDefault( "font" );
+        CheckDefault( "visible", "true" );
+        CheckDefault( "x", "0" );
+        CheckDefault( "y", "0" );
+        CheckDefault( "width", "0" );
+        CheckDefault( "height", "0" );
+        CheckDefault( "lefttop", "lefttop" );
+        CheckDefault( "rightbottom", "lefttop" );
+        CheckDefault( "bgimage", "none" );
+        CheckDefault( "itemimage", "none" );
+        CheckDefault( "openimage", "none" );
+        CheckDefault( "closedimage", "none" );
+        CheckDefault( "fgcolor", "#000000" );
+        CheckDefault( "playcolor", "#FF0000" );
+        CheckDefault( "bgcolor1", "#FFFFFF" );
+        CheckDefault( "bgcolor2", "#FFFFFF" );
+        CheckDefault( "selcolor", "#0000FF" );
+        CheckDefault( "help", "" );
+
+        m_curListId = uniqueId( attr["id"] );
+        const BuilderData::Tree treeData( m_curListId, atoi( attr["x"] ) +
+                m_xOffset, atoi( attr["y"] ) + m_yOffset, attr["visible"],
+                atoi( attr["width"]), atoi( attr["height"] ),
+                attr["lefttop"], attr["rightbottom"],
+                attr["font"], "playtree",
+                attr["bgimage"], attr["itemimage"],
+                attr["openimage"], attr["closedimage"],
+                convertColor( attr["fgcolor"] ),
+                convertColor( attr["playcolor"] ),
+                convertColor( attr["bgcolor1"] ),
+                convertColor( attr["bgcolor2"] ),
+                convertColor( attr["selcolor"] ), attr["help"],
+                m_curLayer, m_curWindowId, m_curLayoutId );
+        m_curLayer++;
+        m_data.m_listTree.push_back( treeData );
+    }
+
     else if( rName == "RadialSlider" )
     {
         RequireDefault( "sequence" );
@@ -291,6 +331,8 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
         {
             // Slider associated to a list
             newValue = "playlist.slider";
+            // FIXME
+            newValue = "playtree.slider";
         }
         const BuilderData::Slider slider( uniqueId( attr["id"] ),
                 attr["visible"],
@@ -409,7 +451,7 @@ void SkinParser::handleEndElement( const string &rName )
         m_yOffsetList.pop_back();
     }
 
-    else if( rName == "Playlist" )
+    else if( rName == "Playlist" || rName == "Playtree" )
     {
         m_curListId = "";
     }
index 713d8c3..afd400e 100644 (file)
@@ -27,6 +27,7 @@
 #include "../commands/cmd_change_skin.hpp"
 #include "../commands/cmd_quit.hpp"
 #include "../commands/cmd_playlist.hpp"
+#include "../commands/cmd_playtree.hpp"
 
 
 /// Callback called when a new skin is chosen
@@ -71,6 +72,7 @@ void Dialogs::showPlaylistLoadCB( intf_dialog_args_t *pArg )
         // Push the command in the asynchronous command queue
         AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
         pQueue->remove( "load playlist" );
+        pQueue->remove( "load playtree" );
         pQueue->push( CmdGenericPtr( pCmd ) );
     }
 }
@@ -89,6 +91,7 @@ void Dialogs::showPlaylistSaveCB( intf_dialog_args_t *pArg )
         // Push the command in the asynchronous command queue
         AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
         pQueue->remove( "load playlist" );
+        pQueue->remove( "load playtree" );
         pQueue->push( CmdGenericPtr( pCmd ) );
     }
 }
index 80543cb..fc9d94c 100644 (file)
@@ -80,6 +80,12 @@ VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ), m_pVout( NULL ),
     REGISTER_VAR( m_cVarRandom, VarBoolImpl, "playlist.isRandom" )
     REGISTER_VAR( m_cVarLoop, VarBoolImpl, "playlist.isLoop" )
     REGISTER_VAR( m_cVarRepeat, VarBoolImpl, "playlist.isRepeat" )
+    REGISTER_VAR( m_cPlaytree, Playtree, "playtree" )
+    pVarManager->registerVar( getPlaytreeVar().getPositionVarPtr(),
+                              "playtree.slider" );
+    REGISTER_VAR( m_cVarRandom, VarBoolImpl, "playtree.isRandom" )
+    REGISTER_VAR( m_cVarLoop, VarBoolImpl, "playtree.isLoop" )
+    REGISTER_VAR( m_cVarRepeat, VarBoolImpl, "playtree.isRepeat" )
     REGISTER_VAR( m_cVarTime, StreamTime, "time" )
     REGISTER_VAR( m_cVarVolume, Volume, "volume" )
     REGISTER_VAR( m_cVarMute, VarBoolImpl, "vlc.isMute" )
@@ -292,11 +298,15 @@ int VlcProc::onIntfChange( vlc_object_t *pObj, const char *pVariable,
 
     // Create a playlist notify command
     CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
+    // Create a playtree notify command
+    CmdNotifyPlaytree *pCmdTree = new CmdNotifyPlaytree( pThis->getIntf() );
 
     // Push the command in the asynchronous command queue
     AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
     pQueue->remove( "notify playlist" );
+    pQueue->remove( "notify playtree" );
     pQueue->push( CmdGenericPtr( pCmd ) );
+    pQueue->push( CmdGenericPtr( pCmdTree ) );
 
     return VLC_SUCCESS;
 }
@@ -337,11 +347,15 @@ int VlcProc::onItemChange( vlc_object_t *pObj, const char *pVariable,
     // Create a playlist notify command
     // TODO: selective update
     CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
+    // Create a playtree notify command
+    CmdNotifyPlaytree *pCmdTree = new CmdNotifyPlaytree( pThis->getIntf() );
 
     // Push the command in the asynchronous command queue
     AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
     pQueue->remove( "notify playlist" );
+    pQueue->remove( "notify playtree" );
     pQueue->push( CmdGenericPtr( pCmd ) );
+    pQueue->push( CmdGenericPtr( pCmdTree ) );
 
     return VLC_SUCCESS;
 }
@@ -362,10 +376,14 @@ int VlcProc::onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
     // Create a playlist notify command
     // TODO: selective update
     CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
+    // Create a playtree notify command
+    CmdNotifyPlaytree *pCmdTree = new CmdNotifyPlaytree( pThis->getIntf() );
 
     // Push the command in the asynchronous command queue
     pQueue->remove( "notify playlist" );
+    pQueue->remove( "notify playtree" );
     pQueue->push( CmdGenericPtr( pCmd ) );
+    pQueue->push( CmdGenericPtr( pCmdTree ) );
 
     return VLC_SUCCESS;
 }
index b894b9e..2ec1a1f 100644 (file)
@@ -28,6 +28,7 @@
 #include <set>
 
 #include "../vars/playlist.hpp"
+#include "../vars/playtree.hpp"
 #include "../vars/time.hpp"
 #include "../vars/volume.hpp"
 #include "../utils/var_text.hpp"
@@ -51,6 +52,9 @@ class VlcProc: public SkinObject
         /// Getter for the playlist variable
         Playlist &getPlaylistVar() { return *((Playlist*)m_cPlaylist.get()); }
 
+        /// Getter for the playtree variable
+        Playtree &getPlaytreeVar() { return *((Playtree*)m_cPlaytree.get()); }
+
         /// Getter for the time variable
         StreamTime &getTimeVar() { return *((StreamTime*)(m_cVarTime.get())); }
 
@@ -88,6 +92,8 @@ class VlcProc: public SkinObject
         OSTimer *m_pTimer;
         /// Playlist variable
         VariablePtr m_cPlaylist;
+        /// Playtree variable FIXME
+        VariablePtr m_cPlaytree;
         VariablePtr m_cVarRandom;
         VariablePtr m_cVarLoop;
         VariablePtr m_cVarRepeat;
diff --git a/modules/gui/skins2/utils/var_tree.cpp b/modules/gui/skins2/utils/var_tree.cpp
new file mode 100644 (file)
index 0000000..c5e5caa
--- /dev/null
@@ -0,0 +1,183 @@
+/*****************************************************************************
+ * var_tree.cpp
+ *****************************************************************************
+ * Copyright (C) 2005 VideoLAN
+ * $Id: var_bool.hpp 9934 2005-02-15 13:55:08Z courmisch $
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "var_tree.hpp"
+
+const string VarTree::m_type = "tree";
+
+VarTree::VarTree( intf_thread_t *pIntf, VarTree *m_pParent2 )
+      :Variable( pIntf )
+{
+    m_selected = false;
+    m_playing = false;
+    m_expanded = true;
+    m_pData = NULL;
+    m_pParent = m_pParent2;
+
+    // Create the position variable
+    m_cPosition = VariablePtr( new VarPercent( pIntf ) );
+    getPositionVar().set( 1.0 );
+}
+
+VarTree::~VarTree()
+{
+// TODO : check that children are deleted
+}
+
+void VarTree::add( const UStringPtr &rcString, bool selected, bool playing, bool expanded, void *pData )
+{
+    m_children.push_back( VarTree( getIntf(), this ) );
+    back().m_cString = rcString;
+    back().m_selected = selected;
+    back().m_playing = playing;
+    back().m_expanded = expanded;
+    back().m_pData = pData;
+
+    notify();
+}
+
+void VarTree::delSelected()
+{
+    Iterator it = begin();
+    while( it != end() )
+    {
+        //dig down the tree
+        if( size() ) it->delSelected();
+        //stay on some level
+        if( it->m_selected )
+        {
+            Iterator oldIt = it;
+            it++;
+            m_children.erase( oldIt );
+        }
+        else
+        {
+            it++;
+        }
+    }
+    notify();
+}
+
+void VarTree::clear()
+{
+    m_children.clear();
+}
+
+VarTree::Iterator VarTree::operator[]( int n )
+{
+    Iterator it;
+    int i;
+    for( it = begin(), i = 0;
+         i < n && it != end();
+         it++, i++ );
+    return it;
+}
+
+VarTree::ConstIterator VarTree::operator[]( int n ) const
+{
+    ConstIterator it;
+    int i;
+    for( it = begin(), i = 0;
+         i < n && it != end();
+         it++, i++ );
+    return it;
+}
+
+/* find iterator to next ancestor
+ * ... which means parent++ or grandparent++ or grandgrandparent++ ... */
+VarTree::Iterator VarTree::uncle()
+{
+//    fprintf( stderr, "trying to find uncle\n");
+    VarTree *p_parent = parent();
+    if( p_parent != NULL )
+    {
+        VarTree *p_grandparent = p_parent->parent();
+        while( p_grandparent != NULL )
+        {
+            Iterator it = p_grandparent->begin();
+            while( !(it == p_grandparent->end()) && &(*it) != p_parent ) it++;
+            if( it != p_grandparent->end() )
+            {
+                it++;
+                if( it != p_grandparent->end() )
+                {
+                    return it;
+                }
+            }
+            if( p_grandparent->parent() )
+            {
+                p_parent = p_grandparent;
+                p_grandparent = p_parent->parent();
+            }
+            else
+                p_grandparent = NULL;
+        }
+    }
+
+    /* if we didn't return before, it means that we've reached the end */
+    return root()->end();
+}
+
+void VarTree::checkParents( VarTree *m_pParent2 )
+{
+    m_pParent = m_pParent2;
+    Iterator it = begin();
+    while( it!=end() )
+    {
+        it->checkParents( this );
+        it++;
+    }
+}
+
+int VarTree::visibleItems()
+{
+    int i_count = size();
+    Iterator it = begin();
+    while( it != end() )
+    {
+        if( it->m_expanded )
+        {
+            i_count += it->visibleItems();
+        }
+        it++;
+    }
+    return i_count;
+}
+
+VarTree::Iterator VarTree::visibleItem( int n )
+{
+    Iterator it = begin();
+    while( it != end() )
+    {
+        n--;
+        if( n <= 0 ) return it;
+        if( it->m_expanded )
+        {
+            int i = n - it->visibleItems();
+            if( i <= 0 ) return it->visibleItem( n );
+            n = i;
+        }
+        it++;
+    }
+    return end();
+}
diff --git a/modules/gui/skins2/utils/var_tree.hpp b/modules/gui/skins2/utils/var_tree.hpp
new file mode 100644 (file)
index 0000000..5d56176
--- /dev/null
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * var_tree.hpp
+ *****************************************************************************
+ * Copyright (C) 2005 VideoLAN
+ * $Id: var_bool.hpp 9934 2005-02-15 13:55:08Z courmisch $
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VAR_TREE_HPP
+#define VAR_TREE_HPP
+
+#include <list>
+
+#include "variable.hpp"
+#include "observer.hpp"
+#include "ustring.hpp"
+#include "var_percent.hpp"
+
+/// Tree variable
+class VarTree: public Variable, public Subject<VarTree>
+{
+    public:
+        VarTree( intf_thread_t *pIntf, VarTree *m_pParent2 );
+        virtual ~VarTree();
+
+        /// Get the variable type
+        virtual const string &getType() const { return m_type; }
+
+        /// Add a pointer on string in the children's list
+        virtual void add( const UStringPtr &rcString, bool selected=true, bool playing=true, bool expanded=true, void *pData=NULL );
+
+        /// Remove the selected item from the children's list
+        virtual void delSelected();
+
+        /// Remove all elements from the children's list
+        virtual void clear();
+
+        UStringPtr m_cString;
+        bool m_selected;
+        bool m_playing;
+        bool m_expanded;
+        void *m_pData;
+
+        /// Get the number of children
+        int size() const { return m_children.size(); }
+
+        /// Iterators
+        typedef list<VarTree>::iterator Iterator;
+        typedef list<VarTree>::const_iterator ConstIterator;
+
+        /// Begining of the children's list
+        Iterator begin() { return m_children.begin(); }
+        ConstIterator begin() const { return m_children.begin(); }
+
+        /// End of children's list
+        Iterator end() { return m_children.end(); }
+        ConstIterator end() const { return m_children.end(); }
+
+        /// Back of children's list
+        VarTree &back() { return m_children.back(); }
+
+        /// Return an iterator on the n'th element of the children's list
+        Iterator operator[]( int n );
+        ConstIterator operator[]( int n ) const;
+
+        /// Parent node
+        VarTree *parent() { return m_pParent; }
+        void VarTree::checkParents( VarTree *m_pParent2 );
+
+        Iterator uncle();
+
+        /// Get root node
+        VarTree *root() { VarTree *parent=this; while( parent->parent() != NULL ) parent = parent->parent(); return parent; }
+
+        /// Get depth (root depth is 0)
+        int depth() { VarTree *parent=this; int depth=0; while( ( parent = parent->parent() ) != NULL ) depth++; return depth; }
+
+        /// Execute the action associated to this item
+        virtual void action( VarTree *pItem ) {}
+
+        /// Get a reference on the position variable
+        VarPercent &getPositionVar() const
+            { return *((VarPercent*)m_cPosition.get()); }
+
+        /// Get a counted pointer on the position variable
+        const VariablePtr &getPositionVarPtr() const { return m_cPosition; }
+
+        /// Count the number of items that should be displayed if the playlist window wasn't limited
+        int visibleItems();
+
+        /// Return iterator to the n'th visible item
+        Iterator visibleItem( int n );
+
+    private:
+//        intf_thread_t *pIntf;
+
+        ///list of children
+        list<VarTree> m_children;
+
+        ///Pointer to parent node
+        VarTree *m_pParent;
+
+        ///Variable type
+        static const string m_type;
+
+        /// Position variable
+        VariablePtr m_cPosition;
+};
+
+#endif
diff --git a/modules/gui/skins2/vars/playtree.cpp b/modules/gui/skins2/vars/playtree.cpp
new file mode 100644 (file)
index 0000000..ee845a2
--- /dev/null
@@ -0,0 +1,133 @@
+/*****************************************************************************
+ * playtree.cpp
+ *****************************************************************************
+ * Copyright (C) 2005 VideoLAN
+ * $Id: playlist.hpp 8659 2004-09-07 21:16:49Z gbazin $
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <vlc/vlc.h>
+
+#include "playtree.hpp"
+#include "../utils/ustring.hpp"
+
+#include "charset.h"
+
+Playtree::Playtree( intf_thread_t *pIntf )
+         :VarTree( pIntf, /*m_parent = */NULL )
+{
+    // Get the VLC playlist object
+    m_pPlaylist = pIntf->p_sys->p_playlist;
+
+    // Try to guess the current charset
+    char *pCharset;
+    vlc_current_charset( &pCharset );
+    iconvHandle = vlc_iconv_open( "UTF-8", pCharset );
+    msg_Dbg( pIntf, "Using character encoding: %s", pCharset );
+    free( pCharset );
+
+    if( iconvHandle == (vlc_iconv_t)-1 )
+    {
+        msg_Warn( pIntf, "Unable to do requested conversion" );
+    }
+
+    buildTree();
+}
+
+Playtree::~Playtree()
+{
+    if( iconvHandle != (vlc_iconv_t)-1 ) vlc_iconv_close( iconvHandle );
+    // TODO : check that everything is destroyed
+}
+
+void Playtree::delSelected()
+{
+    // TODO
+    notify();
+}
+
+void Playtree::action( VarTree *pItem )
+{
+    vlc_mutex_lock( &m_pPlaylist->object_lock );
+    VarTree::Iterator it;
+    if( pItem->size() )
+    {
+        it = pItem->begin();
+        while( it->size() ) it = it->begin();
+    }
+    playlist_Control( m_pPlaylist,
+                      PLAYLIST_VIEWPLAY,
+                      m_pPlaylist->status.i_view,
+                      pItem->size()
+                          ? (playlist_item_t *)pItem->m_pData
+                          : (playlist_item_t *)pItem->parent()->m_pData,
+                      pItem->size()
+                          ? (playlist_item_t *)it->m_pData
+                          : (playlist_item_t *)pItem->m_pData
+                    );
+    vlc_mutex_unlock( &m_pPlaylist->object_lock );
+}
+
+void Playtree::onChange()
+{
+    /* FIXME : updateTree could be a nice idea so we don't have to
+     * start from scratch each time the playlist changes */
+    buildTree();
+    notify();
+}
+
+void Playtree::buildNode( playlist_item_t *p_node, VarTree &m_pNode )
+{
+    fprintf( stderr, "\e[32;1mPlaytree::buildNode\e[0m\n");
+    for( int i = 0; i < p_node->i_children; i++ )
+    {
+        fprintf( stderr, "\e[33;1m"__FILE__ "%d :\e[0m adding playtree item : %s\n", __LINE__, p_node->pp_children[i]->input.psz_name );
+        UString *pName = new UString( getIntf(), p_node->pp_children[i]->input.psz_name );
+        m_pNode.add( UStringPtr( pName ),
+                     false,
+                     m_pPlaylist->status.p_item == p_node->pp_children[i],
+                     true,
+                     p_node->pp_children[i] );
+        if( p_node->pp_children[i]->i_children )
+        {
+            buildNode( p_node->pp_children[i], m_pNode.back() );
+        }
+    }
+}
+
+void Playtree::buildTree()
+{
+    clear();
+    vlc_mutex_lock( &m_pPlaylist->object_lock );
+
+    playlist_view_t *p_view;
+    p_view = playlist_ViewFind( m_pPlaylist, VIEW_CATEGORY );
+    /* TODO : let the user chose the view type */
+
+    clear();
+    /* XXX : do we need Playlist::clear() instead of VarTree::clear() ? */
+
+    /* Set the root's name */
+    UString *pName = new UString( getIntf(), p_view->p_root->input.psz_name );
+    m_cString = UStringPtr( pName );
+
+    buildNode( p_view->p_root, *this );
+
+    vlc_mutex_unlock( &m_pPlaylist->object_lock );
+    checkParents( NULL );
+}
diff --git a/modules/gui/skins2/vars/playtree.hpp b/modules/gui/skins2/vars/playtree.hpp
new file mode 100644 (file)
index 0000000..5c5836c
--- /dev/null
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ * playtree.hpp
+ *****************************************************************************
+ * Copyright (C) 2005 VideoLAN
+ * $Id: playlist.hpp 8659 2004-09-07 21:16:49Z gbazin $
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef PLAYTREE_HPP
+#define PLAYTREE_HPP
+
+#include "../utils/var_tree.hpp"
+
+/// Variable for VLC playlist (new tree format)
+class Playtree: public VarTree
+{
+    public:
+        Playtree( intf_thread_t *pIntf );
+        virtual ~Playtree();
+
+        /// Remove the selected elements from the list
+        virtual void delSelected();
+
+        /// Execute the action associated to this item
+        virtual void action( VarTree *pItem );
+
+        /// Function called to notify playlist changes
+        void onChange();
+
+    private:
+        /// VLC playlist object
+        playlist_t *m_pPlaylist;
+        /// Iconv handle
+        vlc_iconv_t iconvHandle;
+
+        /// Build the list from the VLC playlist
+        void buildTree();
+
+        /// Update Node's children
+        void buildNode( playlist_item_t *p_node, VarTree &m_pNode );
+};
+
+#endif