]> git.sesse.net Git - vlc/commitdiff
* skins2: support for custom popup menus, and win32 implementation.
authorOlivier Teulière <ipkiss@videolan.org>
Sun, 4 Dec 2005 14:47:26 +0000 (14:47 +0000)
committerOlivier Teulière <ipkiss@videolan.org>
Sun, 4 Dec 2005 14:47:26 +0000 (14:47 +0000)
   XML example:
       <PopupMenu id="sample_menu">
           <MenuItem label="Play" action="vlc.play()" />
           <MenuItem label="Pause" action="vlc.pause()" />
           <MenuSeparator />
           <MenuItem label="Show playlist" action="playlist_window.show()" />
           <MenuItem label="Hide playlist" action="playlist_window.hide()" />
           <MenuSeparator />
           <MenuItem label="Quick open file" action="dialogs.fileSimple()" />
       </PopupMenu>

   To call the menu:
       <Button action="sample_menu.show()" ... />

   Known bug: the popup disappears when the user clicks "too fast" on the
   button: the control refreshes itself in an asynchronous way, and the popup
   dislikes it... so click slowly :)

41 files changed:
modules/gui/skins2/Modules.am
modules/gui/skins2/commands/cmd_show_window.hpp
modules/gui/skins2/events/evt_menu.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_motion.hpp
modules/gui/skins2/macosx/macosx_factory.cpp
modules/gui/skins2/macosx/macosx_factory.hpp
modules/gui/skins2/macosx/macosx_popup.cpp [new file with mode: 0644]
modules/gui/skins2/macosx/macosx_popup.hpp [new file with mode: 0644]
modules/gui/skins2/macosx/macosx_tooltip.hpp
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/interpreter.cpp
modules/gui/skins2/parser/skin_parser.cpp
modules/gui/skins2/parser/skin_parser.hpp
modules/gui/skins2/src/generic_window.cpp
modules/gui/skins2/src/generic_window.hpp
modules/gui/skins2/src/os_factory.hpp
modules/gui/skins2/src/os_popup.hpp [new file with mode: 0644]
modules/gui/skins2/src/os_tooltip.hpp
modules/gui/skins2/src/popup.cpp [new file with mode: 0644]
modules/gui/skins2/src/popup.hpp [new file with mode: 0644]
modules/gui/skins2/src/theme.cpp
modules/gui/skins2/src/theme.hpp
modules/gui/skins2/src/top_window.cpp
modules/gui/skins2/src/top_window.hpp
modules/gui/skins2/src/window_manager.cpp
modules/gui/skins2/src/window_manager.hpp
modules/gui/skins2/win32/win32_factory.cpp
modules/gui/skins2/win32/win32_factory.hpp
modules/gui/skins2/win32/win32_loop.cpp
modules/gui/skins2/win32/win32_popup.cpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_popup.hpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_tooltip.hpp
modules/gui/skins2/x11/x11_factory.cpp
modules/gui/skins2/x11/x11_factory.hpp
modules/gui/skins2/x11/x11_popup.cpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_popup.hpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_tooltip.hpp
share/skins2/skin.dtd

index 343764ef84905576503bc728b42adb415ab474c4..b9aa0569937b11e9a4a3a4d098d58b80140da8a3 100644 (file)
@@ -61,13 +61,14 @@ SOURCES_skins2 = \
        controls/ctrl_video.hpp \
        \
        events/evt_enter.hpp \
-       events/evt_generic.hpp \
        events/evt_focus.hpp \
+       events/evt_generic.hpp \
        events/evt_input.cpp \
        events/evt_input.hpp \
        events/evt_key.cpp \
        events/evt_key.hpp \
        events/evt_leave.hpp \
+       events/evt_menu.hpp \
        events/evt_motion.hpp \
        events/evt_mouse.cpp \
        events/evt_mouse.hpp \
@@ -116,9 +117,12 @@ SOURCES_skins2 = \
        src/os_factory.hpp \
        src/os_graphics.hpp \
        src/os_loop.hpp \
+       src/os_popup.hpp \
        src/os_timer.hpp \
        src/os_window.hpp \
        src/os_tooltip.hpp \
+       src/popup.cpp \
+       src/popup.hpp \
        src/scaled_bitmap.cpp \
        src/scaled_bitmap.hpp \
        src/skin_main.cpp \
@@ -183,6 +187,8 @@ SOURCES_skins2 = \
        win32/win32_graphics.hpp \
        win32/win32_loop.cpp \
        win32/win32_loop.hpp \
+       win32/win32_popup.cpp \
+       win32/win32_popup.hpp \
        win32/win32_timer.cpp \
        win32/win32_timer.hpp \
        win32/win32_tooltip.cpp \
@@ -200,6 +206,8 @@ SOURCES_skins2 = \
        x11/x11_graphics.hpp \
        x11/x11_loop.cpp \
        x11/x11_loop.hpp \
+       x11/x11_popup.cpp \
+       x11/x11_popup.hpp \
        x11/x11_timer.cpp \
        x11/x11_timer.hpp \
        x11/x11_window.cpp \
@@ -215,6 +223,8 @@ SOURCES_skins2 = \
        macosx/macosx_graphics.hpp \
        macosx/macosx_loop.cpp \
        macosx/macosx_loop.hpp \
+       macosx/macosx_popup.cpp \
+       macosx/macosx_popup.hpp \
        macosx/macosx_timer.cpp \
        macosx/macosx_timer.hpp \
        macosx/macosx_window.cpp \
index 7537019f13c83ca8f9272b8d7355d6123b9d12e0..a88064086ce3b085b843f324f7cf01c0773996ec 100644 (file)
 #define CMD_SHOW_WINDOW_HPP
 
 #include "cmd_generic.hpp"
+#include "../src/os_factory.hpp"
 #include "../src/top_window.hpp"
 #include "../src/window_manager.hpp"
+#include "../src/popup.hpp"
 
 
 /// Command to show a window
@@ -95,4 +97,30 @@ class CmdRaiseAll: public CmdGeneric
         WindowManager &m_rWinManager;
 };
 
+
+/// Command to show a popup menu
+class CmdShowPopup: public CmdGeneric
+{
+    public:
+        CmdShowPopup( intf_thread_t *pIntf, Popup &rPopup ):
+            CmdGeneric( pIntf ), m_rPopup( rPopup ) {}
+        virtual ~CmdShowPopup() {}
+
+        /// This method does the real job of the command
+        virtual void execute()
+        {
+            int x, y;
+            OSFactory::instance( getIntf() )->getMousePos( x, y );
+            m_rPopup.show( x, y );
+        }
+
+        /// Return the type of the command
+        virtual string getType() const { return "show popup"; }
+
+    private:
+        /// Reference to the popup
+        Popup &m_rPopup;
+};
+
+
 #endif
diff --git a/modules/gui/skins2/events/evt_menu.hpp b/modules/gui/skins2/events/evt_menu.hpp
new file mode 100644 (file)
index 0000000..db9023e
--- /dev/null
@@ -0,0 +1,50 @@
+/*****************************************************************************
+ * evt_menu.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id:$
+ *
+ * Authors: Olivier Teulière <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
+ * 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 EVT_MENU_HPP
+#define EVT_MENU_HPP
+
+#include "evt_generic.hpp"
+
+
+/// Mouse move event
+class EvtMenu: public EvtGeneric
+{
+    public:
+        EvtMenu( intf_thread_t *pIntf, int itemId ):
+            EvtGeneric( pIntf ), m_itemId( itemId ) {}
+        virtual ~EvtMenu() {}
+
+        /// Return the type of event
+        virtual const string getAsString() const { return "menu"; }
+
+        // Getter
+        int getItemId() const { return m_itemId; }
+
+    private:
+        /// Coordinates of the mouse (absolute or relative)
+        int m_itemId;
+};
+
+
+#endif
index 931c68f339149f87b1662fd5ed6e07e9b29fd69f..c43e28a88ef8640410707b07305bae55cca0b6cf 100644 (file)
@@ -45,9 +45,11 @@ class EvtMotion: public EvtInput
 
     private:
         /// Coordinates of the mouse (absolute or relative)
-        /// The coordinates are absolute when the event is sent to the
-        /// GenericWindow, but are relative to the window when the event is
-        /// forwarded to the controls
+        /**
+         * The coordinates are absolute when the event is sent to the
+         * GenericWindow, but are relative to the window when the event is
+         * forwarded to the controls
+         */
         int m_xPos, m_yPos;
 };
 
index d94f6d9161ff3e0d4793ee960906c010f43972a2..4369b7772c7ece5a1fdcf9b8549d8f9016d1aada 100644 (file)
@@ -93,6 +93,12 @@ OSTooltip *MacOSXFactory::createOSTooltip()
 }
 
 
+OSPopup *MacOSXFactory::createOSPopup()
+{
+    return new MacOSXPopup( getIntf() );
+}
+
+
 int MacOSXFactory::getScreenWidth() const
 {
     // TODO
index bf172302d0db395128201d0f2169930a8f6d2ce1..e8521fd2ef84422f6f7bd58634f2c611afd99605 100644 (file)
@@ -37,13 +37,13 @@ class MacOSXFactory: public OSFactory
         /// Initialization method
         virtual bool init();
 
-        /// Instantiate an object OSGraphics.
+        /// Instantiate an object OSGraphics
         virtual OSGraphics *createOSGraphics( int width, int height );
 
-        /// Get the instance of the singleton OSLoop.
+        /// Get the instance of the singleton OSLoop
         virtual OSLoop *getOSLoop();
 
-        /// Destroy the instance of OSLoop.
+        /// Destroy the instance of OSLoop
         virtual void destroyOSLoop();
 
         /// Instantiate an OSTimer with the given callback
@@ -57,9 +57,12 @@ class MacOSXFactory: public OSFactory
                                           bool dragDrop, bool playOnDrop,
                                           OSWindow *pParent );
 
-        /// Instantiate an object OSTooltip.
+        /// Instantiate an object OSTooltip
         virtual OSTooltip *createOSTooltip();
 
+        /// Instantiate an object OSPopup
+        virtual OSPopup *createOSPopup();
+
         /// Get the directory separator
         virtual const string &getDirSeparator() const { return m_dirSep; }
 
diff --git a/modules/gui/skins2/macosx/macosx_popup.cpp b/modules/gui/skins2/macosx/macosx_popup.cpp
new file mode 100644 (file)
index 0000000..df89dde
--- /dev/null
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * macosx_popup.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <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
+ * 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.
+ *****************************************************************************/
+
+#ifdef MACOSX_SKINS
+
+#include "macosx_popup.hpp"
+
+
+MacOSXPopup::MacOSXPopup( intf_thread_t *pIntf )
+    : OSPopup( pIntf )
+{
+    // TODO
+}
+
+
+MacOSXPopup::~MacOSXPopup()
+{
+    // TODO
+}
+
+
+void MacOSXPopup::show( int xPos, int yPos )
+{
+    // TODO
+}
+
+
+void MacOSXPopup::hide()
+{
+    // TODO
+}
+
+
+void MacOSXPopup::addItem( const string &rLabel, int pos )
+{
+    // TODO
+}
+
+
+void MacOSXPopup::addSeparator( int pos )
+{
+    // TODO
+}
+
+
+int MacOSXPopup::getPosFromId( int id ) const
+{
+    // TODO
+}
+
+
+#endif
+
diff --git a/modules/gui/skins2/macosx/macosx_popup.hpp b/modules/gui/skins2/macosx/macosx_popup.hpp
new file mode 100644 (file)
index 0000000..ed52010
--- /dev/null
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * macosx_popup.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <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
+ * 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 MACOSX_POPUP_HPP
+#define MACOSX_POPUP_HPP
+
+#include "../src/os_popup.hpp"
+
+
+/// MacOSX implementation of OSPopup
+class MacOSXPopup: public OSPopup
+{
+    public:
+        MacOSXPopup( intf_thread_t *pIntf );
+
+        virtual ~MacOSXPopup();
+
+        /// Show the popup menu at the given (absolute) corrdinates
+        virtual void show( int xPos, int yPos );
+
+        /// Hide the popup menu
+        virtual void hide();
+
+        /// Append a new menu item with the given label to the popup menu
+        virtual void addItem( const string &rLabel, int pos );
+
+        /// Create a dummy menu item to separate sections
+        virtual void addSeparator( int pos );
+
+        /// Return the position of the item identified by the given id
+        virtual int getPosFromId( int id ) const;
+};
+
+
+#endif
index 44b862e9182d2d6563ffd0ca5a50cbbd508b3dee..cd04855b947383b606ab7b1d28b2d80592ebfa0a 100644 (file)
@@ -37,10 +37,10 @@ class MacOSXTooltip: public OSTooltip
 
         virtual ~MacOSXTooltip();
 
-        // Show the tooltip
+        /// Show the tooltip
         virtual void show( int left, int top, OSGraphics &rText );
 
-        // Hide the tooltip
+        /// Hide the tooltip
         virtual void hide();
 
     private:
index 5f9b4fa3d7f278400d8a7f0e24363d6c7c1dbf85..49444c9c21f43d956b38d7710ab7a667bcc07617 100644 (file)
 #include "../src/anchor.hpp"
 #include "../src/bitmap_font.hpp"
 #include "../src/ft2_font.hpp"
+#include "../src/generic_layout.hpp"
+#include "../src/popup.hpp"
 #include "../src/theme.hpp"
+#include "../commands/cmd_generic.hpp"
 #include "../controls/ctrl_button.hpp"
 #include "../controls/ctrl_checkbox.hpp"
 #include "../controls/ctrl_image.hpp"
@@ -45,6 +48,7 @@
 #include "../controls/ctrl_text.hpp"
 #include "../controls/ctrl_tree.hpp"
 #include "../controls/ctrl_video.hpp"
+#include "../utils/bezier.hpp"
 #include "../utils/position.hpp"
 #include "../utils/var_bool.hpp"
 #include "../utils/var_text.hpp"
@@ -95,6 +99,9 @@ Theme *Builder::build()
     ADD_OBJECTS( BitmapFont );
     ADD_OBJECTS( Font );
     ADD_OBJECTS( Window );
+    // XXX: PopupMenus are created after the windows, so that the Win32Factory
+    // (at least) can give a valid window handle to the OSPopup objects
+    ADD_OBJECTS( PopupMenu );
     ADD_OBJECTS( Layout );
     ADD_OBJECTS( Anchor );
     ADD_OBJECTS( Button );
@@ -106,6 +113,10 @@ Theme *Builder::build()
     ADD_OBJECTS( List );
     ADD_OBJECTS( Tree );
     ADD_OBJECTS( Video );
+    // MenuItems must be created after all the rest, so that the IDs of the
+    // other elements exist and can be parsed in the actions
+    ADD_OBJECTS( MenuItem );
+    ADD_OBJECTS( MenuSeparator );
 
     return m_pTheme;
 }
@@ -258,6 +269,47 @@ void Builder::addFont( const BuilderData::Font &rData )
 }
 
 
+void Builder::addPopupMenu( const BuilderData::PopupMenu &rData )
+{
+    Popup *pPopup = new Popup( getIntf(), m_pTheme->getWindowManager() );
+
+    m_pTheme->m_popups[rData.m_id] = PopupPtr( pPopup );
+}
+
+
+void Builder::addMenuItem( const BuilderData::MenuItem &rData )
+{
+    Popup *pPopup = m_pTheme->getPopupById( rData.m_popupId );
+    if( pPopup == NULL )
+    {
+        msg_Err( getIntf(), "Unknown popup id: %s", rData.m_popupId.c_str() );
+        return;
+    }
+
+    CmdGeneric *pCommand = parseAction( rData.m_action );
+    if( pCommand == NULL )
+    {
+        msg_Err( getIntf(), "Invalid action: %s", rData.m_action.c_str() );
+        return;
+    }
+
+    pPopup->addItem( rData.m_label, *pCommand, rData.m_pos );
+}
+
+
+void Builder::addMenuSeparator( const BuilderData::MenuSeparator &rData )
+{
+    Popup *pPopup = m_pTheme->getPopupById( rData.m_popupId );
+    if( pPopup == NULL )
+    {
+        msg_Err( getIntf(), "Unknown popup id: %s", rData.m_popupId.c_str() );
+        return;
+    }
+
+    pPopup->addSeparator( rData.m_pos );
+}
+
+
 void Builder::addWindow( const BuilderData::Window &rData )
 {
     TopWindow *pWin =
@@ -272,7 +324,7 @@ void Builder::addWindow( const BuilderData::Window &rData )
 
 void Builder::addLayout( const BuilderData::Layout &rData )
 {
-    TopWindow *pWin = m_pTheme->getWindowById(rData.m_windowId);
+    TopWindow *pWin = m_pTheme->getWindowById( rData.m_windowId );
     if( pWin == NULL )
     {
         msg_Err( getIntf(), "unknown window id: %s", rData.m_windowId.c_str() );
@@ -298,7 +350,7 @@ void Builder::addLayout( const BuilderData::Layout &rData )
 
 void Builder::addAnchor( const BuilderData::Anchor &rData )
 {
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
@@ -333,7 +385,7 @@ void Builder::addButton( const BuilderData::Button &rData )
     GenericBitmap *pBmpOver = pBmpUp;
     GET_BMP( pBmpOver, rData.m_overId );
 
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
@@ -390,7 +442,7 @@ void Builder::addCheckbox( const BuilderData::Checkbox &rData )
     GenericBitmap *pBmpOver2 = pBmpUp2;
     GET_BMP( pBmpOver2, rData.m_over2Id );
 
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
@@ -449,14 +501,14 @@ void Builder::addImage( const BuilderData::Image &rData )
     GenericBitmap *pBmp = NULL;
     GET_BMP( pBmp, rData.m_bmpId );
 
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
         return;
     }
 
-    TopWindow *pWindow = m_pTheme->getWindowById(rData.m_windowId);
+    TopWindow *pWindow = m_pTheme->getWindowById( rData.m_windowId );
     if( pWindow == NULL )
     {
         msg_Err( getIntf(), "unknown window id: %s", rData.m_windowId.c_str() );
@@ -526,7 +578,7 @@ void Builder::addImage( const BuilderData::Image &rData )
 
 void Builder::addText( const BuilderData::Text &rData )
 {
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
@@ -607,7 +659,7 @@ void Builder::addRadialSlider( const BuilderData::RadialSlider &rData )
     GenericBitmap *pSeq = NULL;
     GET_BMP( pSeq, rData.m_sequence );
 
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
@@ -661,7 +713,7 @@ void Builder::addSlider( const BuilderData::Slider &rData )
         GET_BMP( pBgImage, rData.m_imageId );
     }
 
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
@@ -737,7 +789,7 @@ void Builder::addList( const BuilderData::List &rData )
     GenericBitmap *pBgBmp = NULL;
     GET_BMP( pBgBmp, rData.m_bgImageId );
 
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
@@ -793,7 +845,7 @@ void Builder::addTree( const BuilderData::Tree &rData )
     GET_BMP( pOpenBmp, rData.m_openImageId );
     GET_BMP( pClosedBmp, rData.m_closedImageId );
 
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
@@ -840,7 +892,7 @@ void Builder::addTree( const BuilderData::Tree &rData )
 
 void Builder::addVideo( const BuilderData::Video &rData )
 {
-    GenericLayout *pLayout = m_pTheme->getLayoutById(rData.m_layoutId);
+    GenericLayout *pLayout = m_pTheme->getLayoutById( rData.m_layoutId );
     if( pLayout == NULL )
     {
         msg_Err( getIntf(), "unknown layout id: %s", rData.m_layoutId.c_str() );
index 80c80a10325c69b71eaca65f00b8bcee2878b77f..49b4f4e6e9b5ea2b01d86a7449f10b46310ebdfe 100644 (file)
 #define BUILDER_HPP
 
 #include "builder_data.hpp"
-#include "../src/os_graphics.hpp"
-#include "../src/generic_window.hpp"
-#include "../src/generic_layout.hpp"
-#include "../src/generic_bitmap.hpp"
-#include "../src/generic_font.hpp"
-#include "../commands/cmd_generic.hpp"
-#include "../controls/ctrl_generic.hpp"
-#include "../utils/bezier.hpp"
+#include "../src/skin_common.hpp"
 
 #include <string>
 #include <list>
 #include <map>
 
 class Theme;
+class Bezier;
+class CmdGeneric;
+class GenericFont;
+class Position;
+class Box;
 
 
 /// Class for skin construction
@@ -71,6 +69,9 @@ class Builder: public SkinObject
         void addSubBitmap( const BuilderData::SubBitmap &rData );
         void addBitmapFont( const BuilderData::BitmapFont &rData );
         void addFont( const BuilderData::Font &rData );
+        void addPopupMenu( const BuilderData::PopupMenu &rData );
+        void addMenuItem( const BuilderData::MenuItem &rData );
+        void addMenuSeparator( const BuilderData::MenuSeparator &rData );
         void addWindow( const BuilderData::Window &rData );
         void addLayout( const BuilderData::Layout &rData );
         void addAnchor( const BuilderData::Anchor &rData );
@@ -84,7 +85,7 @@ class Builder: public SkinObject
         void addTree( const BuilderData::Tree &rData );
         void addVideo( const BuilderData::Video &rData );
 
-       /// Compute the position of a control
+        /// Compute the position of a control
         const Position makePosition( const string &rLeftTop,
                                      const string &rRightBottom,
                                      int xPos, int yPos, int width, int height,
index a534166f3baa3c609b6e38f16ab4c52ce8c27f4d..937fec38b248dada9fb39ef1b76a71b7f8abe6b1 100644 (file)
@@ -3,6 +3,9 @@ Bitmap id:string fileName:string alphaColor:uint32_t nbFrames:int fps:int
 SubBitmap id:string parent:string x:int y:int width:int height:int nbFrames:int fps:int
 BitmapFont id:string file:string type:string
 Font id:string fontFile:string size:int
+PopupMenu id:string
+MenuItem label:string action:string pos:int popupId:string
+MenuSeparator pos:int popupId:string
 Window id:string xPos:int yPos:int visible:bool dragDrop:bool playOnDrop:bool
 Layout id:string width:int height:int minWidth:int maxWidth:int minHeight:int maxHeight:int windowId:string
 Anchor xPos:int yPos:int range:int priority:int points:string layoutId:string
index eb02df37af8e6f96b74635b0d33855152e246057..95832775839872a57e2463cec98c517439e80e67 100644 (file)
@@ -112,6 +112,43 @@ m_id( id ), m_fontFile( fontFile ), m_size( size ) {}
     /// List
     list<Font> m_listFont;
 
+    /// Type definition
+    struct PopupMenu
+    {
+        PopupMenu( const string & id ):
+m_id( id ) {}
+
+        string m_id;
+    };
+    /// List
+    list<PopupMenu> m_listPopupMenu;
+
+    /// Type definition
+    struct MenuItem
+    {
+        MenuItem( const string & label, const string & action, int pos, const string & popupId ):
+m_label( label ), m_action( action ), m_pos( pos ), m_popupId( popupId ) {}
+
+        string m_label;
+        string m_action;
+        int m_pos;
+        string m_popupId;
+    };
+    /// List
+    list<MenuItem> m_listMenuItem;
+
+    /// Type definition
+    struct MenuSeparator
+    {
+        MenuSeparator( int pos, const string & popupId ):
+m_pos( pos ), m_popupId( popupId ) {}
+
+        int m_pos;
+        string m_popupId;
+    };
+    /// List
+    list<MenuSeparator> m_listMenuSeparator;
+
     /// Type definition
     struct Window
     {
index 3b4c6c47646ead028c0162aaeffd7032e62d5d66..26a464713450ba7a04c72145241b0bff04aee1cb 100644 (file)
@@ -216,7 +216,17 @@ CmdGeneric *Interpreter::parseAction( const string &rAction, Theme *pTheme )
         }
         else
         {
-            msg_Err( getIntf(), "Unknown window (%s)", windowId.c_str() );
+            // It was maybe the id of a popup
+            Popup *pPopup = pTheme->getPopupById( windowId );
+            if( pPopup )
+            {
+                pCommand = new CmdShowPopup( getIntf(), *pPopup );
+            }
+            else
+            {
+                msg_Err( getIntf(), "Unknown window or popup (%s)",
+                         windowId.c_str() );
+            }
         }
     }
     else if( rAction.find( ".hide()" ) != string::npos )
index 3adff6a4d1c78045f1520b8425b602b97d9b4640..1e6bdc7bc985ceff09d49b8c7fe5287bc0bae525 100644 (file)
@@ -129,6 +129,36 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
         m_pData->m_listBitmapFont.push_back( font );
     }
 
+    else if( rName == "PopupMenu" )
+    {
+        RequireDefault( "id" );
+
+        m_popupPosList.push_back(0);
+        m_curPopupId = uniqueId( attr["id"] );
+        const BuilderData::PopupMenu popup( m_curPopupId );
+        m_pData->m_listPopupMenu.push_back( popup );
+    }
+
+    else if( rName == "MenuItem" )
+    {
+        RequireDefault( "label" );
+        CheckDefault( "action", "none" );
+
+        const BuilderData::MenuItem item( attr["label"], attr["action"],
+                                          m_popupPosList.back(),
+                                          m_curPopupId );
+        m_pData->m_listMenuItem.push_back( item );
+        m_popupPosList.back()++;
+    }
+
+    else if( rName == "MenuSeparator" )
+    {
+        const BuilderData::MenuSeparator sep( m_popupPosList.back(),
+                                              m_curPopupId );
+        m_pData->m_listMenuSeparator.push_back( sep );
+        m_popupPosList.back()++;
+    }
+
     else if( rName == "Button" )
     {
         RequireDefault( "up" );
@@ -530,6 +560,11 @@ void SkinParser::handleEndElement( const string &rName )
     {
         m_curTreeId = "";
     }
+    else if( rName == "Popup" )
+    {
+        m_curPopupId = "";
+        m_popupPosList.pop_back();
+    }
 }
 
 
index df251b4f72f35bcee31d81a707dabd8bc70a7af2..7bb4c32edea8791275d91c61693075b343686baf 100644 (file)
@@ -51,8 +51,11 @@ class SkinParser: public XMLParser
         string m_curBitmapId;
         string m_curWindowId;
         string m_curLayoutId;
+        string m_curPopupId;
         string m_curListId;
         string m_curTreeId;
+        /// Current position of menu items in the popups
+        list<int> m_popupPosList;
         /// Current offset of the controls
         int m_xOffset, m_yOffset;
         list<int> m_xOffsetList, m_yOffsetList;
index 36593bd474923cf9fa57dda35850eb5946ada64b..dafc383555c015ce63073f8f8687bd244ba29366 100644 (file)
@@ -34,7 +34,7 @@ GenericWindow::GenericWindow( intf_thread_t *pIntf, int left, int top,
     SkinObject( pIntf ), m_left( left ), m_top( top ), m_width( 0 ),
     m_height( 0 ), m_varVisible( pIntf )
 {
-   // Get the OSFactory
+    // Get the OSFactory
     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
 
     // Get the parent OSWindow, if any
index f2110f26c17943d79416d5eaef95722490e11fd0..34f74c1db65ff64f4b79a968eb447072b7d23bf7 100644 (file)
@@ -32,6 +32,7 @@ class OSWindow;
 class EvtGeneric;
 class EvtFocus;
 class EvtLeave;
+class EvtMenu;
 class EvtMotion;
 class EvtMouse;
 class EvtKey;
@@ -53,6 +54,7 @@ class GenericWindow: public SkinObject, public Observer<VarBool, void*>
 
         /// Methods to process OS events.
         virtual void processEvent( EvtFocus &rEvtFocus ) {}
+        virtual void processEvent( EvtMenu &rEvtMenu ) {}
         virtual void processEvent( EvtMotion &rEvtMotion ) {}
         virtual void processEvent( EvtMouse &rEvtMouse ) {}
         virtual void processEvent( EvtLeave &rEvtLeave ) {}
index 49f4e07d8b10fecc9f4a1445035999448f54f1f7..5422917ba64d96534605fe1e407d02bc2e79edf3 100644 (file)
@@ -37,6 +37,7 @@ class OSGraphics;
 class OSLoop;
 class OSWindow;
 class OSTooltip;
+class OSPopup;
 class OSTimer;
 
 
@@ -53,24 +54,28 @@ class OSFactory: public SkinObject
             kResizeNESW
         };
 
-        /// Initialization method overloaded in derived classes.
-        /// It must return false if the init failed.
+        /**
+         * Initialization method overloaded in derived classes.
+         * It must return false if the init failed.
+         */
         virtual bool init() { return true; }
 
-        /// Get the right instance of OSFactory.
-        /// Returns NULL if initialization of the concrete factory failed.
+        /**
+         * Get the right instance of OSFactory.
+         * Returns NULL if initialization of the concrete factory failed.
+         */
         static OSFactory *instance( intf_thread_t *pIntf );
 
-        /// Delete the instance of OSFactory.
+        /// Delete the instance of OSFactory
         static void destroy( intf_thread_t *pIntf );
 
-        /// Instantiate an object OSGraphics.
+        /// Instantiate an object OSGraphics
         virtual OSGraphics *createOSGraphics( int width, int height ) = 0;
 
-        /// Get the instance of the singleton OSLoop.
+        /// Get the instance of the singleton OSLoop
         virtual OSLoop *getOSLoop() = 0;
 
-        /// Destroy the instance of OSLoop.
+        /// Destroy the instance of OSLoop
         virtual void destroyOSLoop() = 0;
 
         ///
@@ -79,14 +84,17 @@ class OSFactory: public SkinObject
         /// Instantiate an OSTimer with the given command
         virtual OSTimer *createOSTimer( CmdGeneric &rCmd ) = 0;
 
-        /// Instantiate an object OSWindow.
+        /// Instantiate an object OSWindow
         virtual OSWindow *createOSWindow( GenericWindow &rWindow,
                                           bool dragDrop, bool playOnDrop,
                                           OSWindow *pParent ) = 0;
 
-        /// Instantiate an object OSTooltip.
+        /// Instantiate an object OSTooltip
         virtual OSTooltip *createOSTooltip() = 0;
 
+        /// Instantiate an object OSPopup
+        virtual OSPopup *createOSPopup() = 0;
+
         /// Get the directory separator
         virtual const string &getDirSeparator() const = 0;
 
@@ -110,7 +118,7 @@ class OSFactory: public SkinObject
         virtual void rmDir( const string &rPath ) = 0;
 
    protected:
-        // Protected because it's a singleton.
+        // Protected because it's a singleton
         OSFactory( intf_thread_t* pIntf ): SkinObject( pIntf ) {}
         virtual ~OSFactory() {}
 };
diff --git a/modules/gui/skins2/src/os_popup.hpp b/modules/gui/skins2/src/os_popup.hpp
new file mode 100644 (file)
index 0000000..fea226f
--- /dev/null
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * os_popup.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <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
+ * 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 OS_POPUP_HPP
+#define OS_POPUP_HPP
+
+#include "skin_common.hpp"
+#include <string>
+
+class OSGraphics;
+
+
+/// Base class for OS specific Popup Windows
+class OSPopup: public SkinObject
+{
+    public:
+        virtual ~OSPopup() {}
+
+        /// Show the popup menu at the given (absolute) corrdinates
+        virtual void show( int xPos, int yPos ) = 0;
+
+        /// Hide the popup menu
+        virtual void hide() = 0;
+
+        /// Append a new menu item with the given label to the popup menu
+        virtual void addItem( const string &rLabel, int pos ) = 0;
+
+        /// Create a dummy menu item to separate sections
+        virtual void addSeparator( int pos ) = 0;
+
+        /// Return the position of the item identified by the given id
+        virtual int getPosFromId( int id ) const = 0;
+
+    protected:
+        OSPopup( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+#endif
index 4b40bec495afa9be3bb0f8a475b0bf7b523139a3..ebb41c5f46b327193c9e6258e9fe04cc4b429474 100644 (file)
@@ -36,10 +36,10 @@ class OSTooltip: public SkinObject
     public:
         virtual ~OSTooltip() {}
 
-        // Show the tooltip
+        /// Show the tooltip
         virtual void show( int left, int top, OSGraphics &rText ) = 0;
 
-        // Hide the tooltip
+        /// Hide the tooltip
         virtual void hide() = 0;
 
     protected:
diff --git a/modules/gui/skins2/src/popup.cpp b/modules/gui/skins2/src/popup.cpp
new file mode 100644 (file)
index 0000000..3bf840d
--- /dev/null
@@ -0,0 +1,86 @@
+/*****************************************************************************
+ * popup.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <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
+ * 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 "popup.hpp"
+#include "os_factory.hpp"
+#include "os_popup.hpp"
+#include "window_manager.hpp"
+#include "../commands/cmd_generic.hpp"
+#include "../events/evt_menu.hpp"
+
+
+Popup::Popup( intf_thread_t *pIntf, WindowManager &rWindowManager )
+    : SkinObject( pIntf ), m_rWindowManager( rWindowManager )
+{
+    // Get the OSFactory
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+
+    // Create an OSPopup to handle OS specific processing
+    m_pOsPopup = pOsFactory->createOSPopup();
+}
+
+
+void Popup::show( int xPos, int yPos )
+{
+    // Notify that we are the active popup menu, so that the window which
+    // receives our menu events knows whom to forward them
+    m_rWindowManager.setActivePopup( *this );
+
+    m_pOsPopup->show( xPos, yPos );
+}
+
+
+void Popup::hide()
+{
+    m_pOsPopup->hide();
+}
+
+
+void Popup::addItem( const string &rLabel, CmdGeneric &rCmd, int pos )
+{
+    m_pOsPopup->addItem( rLabel, pos );
+    m_actions[pos] = &rCmd;
+}
+
+
+void Popup::addSeparator( int pos )
+{
+    m_pOsPopup->addSeparator( pos );
+    m_actions[pos] = NULL;
+}
+
+
+void Popup::handleEvent( const EvtMenu &rEvent )
+{
+    unsigned int n = m_pOsPopup->getPosFromId( rEvent.getItemId() );
+    if( n >= 0 && n < m_actions.size() && m_actions[n] )
+    {
+        m_actions[n]->execute();
+    }
+    else
+    {
+        // Should never happen
+        msg_Warn( getIntf(), "Problem in the popup implementation" );
+    }
+}
+
diff --git a/modules/gui/skins2/src/popup.hpp b/modules/gui/skins2/src/popup.hpp
new file mode 100644 (file)
index 0000000..7fb3df7
--- /dev/null
@@ -0,0 +1,74 @@
+/*****************************************************************************
+ * popup.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <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
+ * 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 POPUP_HPP
+#define POPUP_HPP
+
+#include "skin_common.hpp"
+#include "../utils/pointer.hpp"
+#include <string>
+#include <map>
+
+class OSPopup;
+class TopWindow;
+class CmdGeneric;
+class WindowManager;
+class EvtMenu;
+
+
+/// Class handling a popup menu
+class Popup: public SkinObject
+{
+    public:
+        Popup( intf_thread_t *pIntf, WindowManager &rWindowManager );
+        virtual ~Popup() {}
+
+        void show( int xPos, int yPos );
+        void hide();
+
+        // XXX: it would be nice to use a UString here, if X11 supports it for
+        // its menu items (Windows doesn't, unfortunately)
+        /// Insert a new menu item to the popup menu, at the position pos
+        void addItem( const string &rLabel, CmdGeneric &rCmd, int pos );
+
+        /// Create a dummy menu item to separate sections
+        void addSeparator( int pos );
+
+        /// Execute the action corresponding to the chosen menu item
+        void handleEvent( const EvtMenu &rEvent );
+
+    private:
+        /// OS specific implementation
+        OSPopup *m_pOsPopup;
+
+        /// Window manager
+        WindowManager &m_rWindowManager;
+
+        /// Actions for the menu items, indexed by the position in the menu
+        map<int, CmdGeneric *> m_actions;
+};
+
+typedef CountedPtr<Popup> PopupPtr;
+
+
+#endif
index 1b824906e7d74b58ff3feb6111af4fca1ac99f50..4fd6a516d4418f5b56569c219b30c76aae9fb6f3 100644 (file)
@@ -164,6 +164,11 @@ GenericFont *Theme::getFontById( const string &id )
     FIND_FIRST_OBJECT( GenericFontPtr, m_fonts );
 }
 
+Popup *Theme::getPopupById( const string &id )
+{
+    FIND_OBJECT( PopupPtr, m_popups );
+}
+
 TopWindow *Theme::getWindowById( const string &id )
 {
     FIND_OBJECT( TopWindowPtr, m_windows );
index 494bd4ef2be32a9f381191e0ae2be9b7c011c404..4a3f6d91caa19bde0d9b7a95ef83700fe61cd666 100644 (file)
 #ifndef THEME_HPP
 #define THEME_HPP
 
-#include "../src/generic_bitmap.hpp"
-#include "../src/generic_font.hpp"
-#include "../src/generic_layout.hpp"
+#include "generic_bitmap.hpp"
+#include "generic_font.hpp"
+#include "generic_layout.hpp"
+#include "popup.hpp"
 #include "../src/window_manager.hpp"
 #include "../commands/cmd_generic.hpp"
 #include "../utils/bezier.hpp"
@@ -56,6 +57,7 @@ class Theme: public SkinObject
 
         GenericBitmap *getBitmapById( const string &id );
         GenericFont *getFontById( const string &id );
+        Popup *getPopupById( const string &id );
         TopWindow *getWindowById( const string &id );
         GenericLayout *getLayoutById( const string &id );
         CtrlGeneric *getControlById( const string &id );
@@ -67,6 +69,8 @@ class Theme: public SkinObject
         map<string, GenericBitmapPtr> m_bitmaps;
         /// Store the fonts by ID
         map<string, GenericFontPtr> m_fonts;
+        /// Store the popups by ID
+        map<string, PopupPtr> m_popups;
         /// Store the windows by ID
         map<string, TopWindowPtr> m_windows;
         /// Store the layouts by ID
index d5a559ba1fa22d841f5a4175107ebf4a6f545ed3..e3b3128074b91ce23e2e88085ef73e4bf07682e6 100644 (file)
@@ -36,6 +36,7 @@
 #include "../events/evt_enter.hpp"
 #include "../events/evt_focus.hpp"
 #include "../events/evt_leave.hpp"
+#include "../events/evt_menu.hpp"
 #include "../events/evt_motion.hpp"
 #include "../events/evt_mouse.hpp"
 #include "../events/evt_key.hpp"
@@ -87,7 +88,21 @@ void TopWindow::processEvent( EvtRefresh &rEvtRefresh )
 
 void TopWindow::processEvent( EvtFocus &rEvtFocus )
 {
-//    fprintf(stderr, rEvtFocus.getAsString().c_str()) ;
+//    fprintf(stderr, rEvtFocus.getAsString().c_str());
+}
+
+
+void TopWindow::processEvent( EvtMenu &rEvtMenu )
+{
+    Popup *pPopup = m_rWindowManager.getActivePopup();
+    // We should never receive a menu event when there is no active popup!
+    if( pPopup == NULL )
+    {
+        msg_Warn( getIntf(), "Unexpected menu event, ignoring" );
+        return;
+    }
+
+    pPopup->handleEvent( rEvtMenu );
 }
 
 
index f7596119af3f5661ed68394e30e7a35c28eb3a1e..117dfb7cb9820c3bcd474f21d517207f266fb9ae 100644 (file)
@@ -50,6 +50,7 @@ class TopWindow: public GenericWindow
         /// Methods to process OS events.
         virtual void processEvent( EvtRefresh &rEvtRefresh );
         virtual void processEvent( EvtFocus &rEvtFocus );
+        virtual void processEvent( EvtMenu &rEvtMenu );
         virtual void processEvent( EvtMotion &rEvtMotion );
         virtual void processEvent( EvtMouse &rEvtMouse );
         virtual void processEvent( EvtLeave &rEvtLeave );
index 0ebb82468a6f54c76d0d3433e3cd6b4e6ed2aced..db36429366617d31c7ddabe75273c1828d0c1490 100644 (file)
@@ -33,7 +33,7 @@
 
 
 WindowManager::WindowManager( intf_thread_t *pIntf ):
-    SkinObject( pIntf ), m_magnet( 0 ), m_pTooltip( NULL )
+    SkinObject( pIntf ), m_magnet( 0 ), m_pTooltip( NULL ), m_pPopup( NULL )
 {
     // Create and register a variable for the "on top" status
     VarManager *pVarManager = VarManager::instance( getIntf() );
index 6dd052604213659e1f3c155e2492a98cee84b857..0737b90b46cd52065787a1824719e4df48b56733 100644 (file)
@@ -37,6 +37,7 @@ class GenericFont;
 class GenericLayout;
 class Anchor;
 class Tooltip;
+class Popup;
 
 
 /// Window manager for skin windows
@@ -116,16 +117,25 @@ class WindowManager: public SkinObject
         /// Change the active layout of the given window
         void setActiveLayout( TopWindow &rWindow, GenericLayout &rLayout );
 
+        /// Mark the given popup as active
+        void setActivePopup( Popup &rPopup ) { m_pPopup = &rPopup; }
+
+        /// Return the active popup, or NULL if none is active
+        Popup * getActivePopup() const { return m_pPopup; }
+
     private:
         /// Some useful typedefs for lazy people like me
         typedef set<TopWindow*> WinSet_t;
         typedef list<Anchor*> AncList_t;
 
-        /// This map represents the graph of anchored windows: it associates
-        /// to a given window all the windows that are directly anchored by it.
-        /// This is not transitive, i.e. if a is in m_dep[b] and if b is in
-        /// m_dep[c], it doesn't mean that a is in m_dep[c] (in fact, it
-        /// would be extremely rare...)
+        /// Dependencies map
+        /**
+         * This map represents the graph of anchored windows: it associates
+         * to a given window all the windows that are directly anchored by it.
+         * This is not transitive, i.e. if a is in m_dep[b] and if b is in
+         * m_dep[c], it doesn't mean that a is in m_dep[c] (in fact, it
+         * would be extremely rare...)
+         */
         map<TopWindow*, WinSet_t> m_dependencies;
         /// Store all the windows
         WinSet_t m_allWindows;
@@ -142,12 +152,17 @@ class WindowManager: public SkinObject
         int m_moveAlpha;
         /// Tooltip
         Tooltip *m_pTooltip;
+        /// Active popup, if any
+        Popup *m_pPopup;
 
         /// Recursively build a set of windows anchored to the one given.
         void buildDependSet( WinSet_t &rWinSet, TopWindow *pWindow );
 
-        /// Check anchoring: this function updates xOffset and yOffset,
-        /// to take care of a new anchoring (if any)
+        /// Check anchoring
+        /**
+         * This function updates xOffset and yOffset, to take care of a new
+         * anchoring (if any)
+         */
         void checkAnchors( TopWindow *pWindow,
                            int &xOffset, int &yOffset ) const;
 };
index d3733eb620b0a6837735aad9663c4d9825949aa0..b2e92b9d448be66da0fb854260c60d625d5deb50 100644 (file)
@@ -29,6 +29,7 @@
 #include "win32_timer.hpp"
 #include "win32_window.hpp"
 #include "win32_tooltip.hpp"
+#include "win32_popup.hpp"
 #include "win32_loop.hpp"
 #include "../src/theme.hpp"
 
@@ -257,6 +258,23 @@ OSTooltip *Win32Factory::createOSTooltip()
 }
 
 
+OSPopup *Win32Factory::createOSPopup()
+{
+    // XXX FIXME: this way of getting the handle really sucks!
+    // In fact, the clean way would be to have in Builder::addPopup() a call
+    // to pPopup->associateToWindow() (to be written)... but the problem is
+    // that there is no way to access the OS-dependent window handle from a
+    // GenericWindow (we cannot eevn access the OSWindow).
+    if( m_windowMap.begin() == m_windowMap.end() )
+    {
+        msg_Err( getIntf(), "No window has been created before the popup!" );
+        return NULL;
+    }
+
+    return new Win32Popup( getIntf(), m_windowMap.begin()->first );
+}
+
+
 int Win32Factory::getScreenWidth() const
 {
     return GetSystemMetrics(SM_CXSCREEN);
index 0855acbd5cadfc3b44f45f4db94c0ce98ea6e45c..f49380d3f3b9b83ea78aa55941bbd43017d472b5 100644 (file)
@@ -44,13 +44,13 @@ class Win32Factory: public OSFactory
         /// Initialization method
         virtual bool init();
 
-        /// Instantiate an object OSGraphics.
+        /// Instantiate an object OSGraphics
         virtual OSGraphics *createOSGraphics( int width, int height );
 
-        /// Get the instance of the singleton OSLoop.
+        /// Get the instance of the singleton OSLoop
         virtual OSLoop *getOSLoop();
 
-        /// Destroy the instance of OSLoop.
+        /// Destroy the instance of OSLoop
         virtual void destroyOSLoop();
 
         ///
@@ -64,9 +64,12 @@ class Win32Factory: public OSFactory
                                           bool dragDrop, bool playOnDrop,
                                           OSWindow *pParent );
 
-        /// Instantiate an object OSTooltip.
+        /// Instantiate an object OSTooltip
         virtual OSTooltip *createOSTooltip();
 
+        /// Instantiate an object OSPopup
+        virtual OSPopup *createOSPopup();
+
         /// Get the directory separator
         virtual const string &getDirSeparator() const { return m_dirSep; }
 
index f0414ff033a8ac05f9871ed31a708ab8ca222b68..0461a2a8069c037ef0dd47c8c67a713bbbfa8aa8 100644 (file)
@@ -29,6 +29,7 @@
 #include "../src/generic_window.hpp"
 #include "../events/evt_key.hpp"
 #include "../events/evt_leave.hpp"
+#include "../events/evt_menu.hpp"
 #include "../events/evt_motion.hpp"
 #include "../events/evt_mouse.hpp"
 #include "../events/evt_refresh.hpp"
@@ -132,6 +133,12 @@ void Win32Loop::run()
                 win.processEvent( evt );
                 break;
             }
+            case WM_COMMAND:
+            {
+                EvtMenu evt( getIntf(), LOWORD( msg.wParam ) );
+                win.processEvent( evt );
+                break;
+            }
             case WM_MOUSEMOVE:
             {
                 // Needed to generate WM_MOUSELEAVE events
diff --git a/modules/gui/skins2/win32/win32_popup.cpp b/modules/gui/skins2/win32/win32_popup.cpp
new file mode 100644 (file)
index 0000000..e4ae7f5
--- /dev/null
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ * win32_popup.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <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
+ * 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.
+ *****************************************************************************/
+
+#ifdef WIN32_SKINS
+
+#include "win32_popup.hpp"
+#include "win32_factory.hpp"
+
+#ifndef TPM_NOANIMATION
+const UINT TPM_NOANIMATION = 0x4000L;
+#endif
+
+
+Win32Popup::Win32Popup( intf_thread_t *pIntf, HWND hAssociatedWindow )
+    : OSPopup( pIntf ), m_hWnd( hAssociatedWindow )
+{
+    // Create the popup menu
+    m_hMenu = CreatePopupMenu();
+
+    if( !m_hMenu )
+    {
+        msg_Err( getIntf(), "CreatePopupMenu failed" );
+        return;
+    }
+}
+
+
+Win32Popup::~Win32Popup()
+{
+    if( m_hMenu )
+        DestroyMenu( m_hMenu );
+}
+
+
+void Win32Popup::show( int xPos, int yPos )
+{
+    TrackPopupMenuEx( m_hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON
+                               | TPM_HORIZONTAL | TPM_NOANIMATION,
+                      xPos, yPos, m_hWnd, NULL );
+}
+
+
+void Win32Popup::hide()
+{
+    SendMessage( m_hWnd, WM_CANCELMODE, 0, 0 );
+}
+
+
+void Win32Popup::addItem( const string &rLabel, int pos )
+{
+    MENUITEMINFO menuItem;
+    menuItem.cbSize = sizeof( MENUITEMINFO );
+//     menuItem.fMask = MIIM_FTYPE | MIIM_ID | MIIM_TYPE | MIIM_STRING;
+//     menuItem.fType = MFT_STRING;
+    menuItem.fMask = MIIM_ID | MIIM_STRING;
+    menuItem.wID = pos;
+    menuItem.dwTypeData = (char*)rLabel.c_str();
+    menuItem.cch = rLabel.size();
+
+    InsertMenuItem( m_hMenu, findInsertionPoint( pos ), TRUE, &menuItem );
+}
+
+
+void Win32Popup::addSeparator( int pos )
+{
+    MENUITEMINFO sepItem;
+    sepItem.cbSize = sizeof( MENUITEMINFO );
+    sepItem.fMask = MIIM_FTYPE;
+    sepItem.fType = MFT_SEPARATOR;
+
+    InsertMenuItem( m_hMenu, findInsertionPoint( pos ), TRUE, &sepItem );
+}
+
+
+unsigned int Win32Popup::findInsertionPoint( unsigned int pos ) const
+{
+    // For this simple algorithm, we rely on the fact that in the final state
+    // of the menu, the ID of each item is equal to its position in the menu
+    int i = 0;
+    while( i < GetMenuItemCount( m_hMenu ) &&
+           GetMenuItemID( m_hMenu, i ) < pos )
+    {
+        i++;
+    }
+    return i;
+}
+
+
+#endif
+
diff --git a/modules/gui/skins2/win32/win32_popup.hpp b/modules/gui/skins2/win32/win32_popup.hpp
new file mode 100644 (file)
index 0000000..5395915
--- /dev/null
@@ -0,0 +1,70 @@
+/*****************************************************************************
+ * win32_popup.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <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
+ * 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 WIN32_POPUP_HPP
+#define WIN32_POPUP_HPP
+
+#include "../src/os_popup.hpp"
+#include <windows.h>
+
+
+/// Win32 implementation of OSPopup
+class Win32Popup: public OSPopup
+{
+    public:
+        Win32Popup( intf_thread_t *pIntf, HWND hAssociatedWindow );
+
+        virtual ~Win32Popup();
+
+        /// Show the popup menu at the given (absolute) corrdinates
+        virtual void show( int xPos, int yPos );
+
+        /// Hide the popup menu
+        virtual void hide();
+
+        /// Append a new menu item with the given label to the popup menu
+        virtual void addItem( const string &rLabel, int pos );
+
+        /// Create a dummy menu item to separate sections
+        virtual void addSeparator( int pos );
+
+        /// Return the position of the item identified by the given id
+        virtual int getPosFromId( int id ) const { return id; }
+
+    private:
+        /// Menu handle
+        HMENU m_hMenu;
+        /// Handle of the window which will receive the menu events
+        HWND m_hWnd;
+
+        /**
+         * Find the item before which to insert another item so that the
+         * newly added item is at the position pos _when the whole menu has
+         * been built_ (no assumption is made for the order of insertion of the
+         * items)
+         */
+        unsigned int findInsertionPoint( unsigned int pos ) const;
+};
+
+
+#endif
index 4ef983022755a9d0e22b1eb8f4c86c00aabbaf8d..ab53e42b1b9e2b942ba9cec0f2dbb6fa4e223a54 100644 (file)
@@ -38,10 +38,10 @@ class Win32Tooltip: public OSTooltip
 
         virtual ~Win32Tooltip();
 
-        // Show the tooltip
+        /// Show the tooltip
         virtual void show( int left, int top, OSGraphics &rText );
 
-        // Hide the tooltip
+        /// Hide the tooltip
         virtual void hide();
 
     private:
index 7031d1c160ba8013eb9acb94d7b4d092a1f15a6f..dcc9cedcc2ba8c463c118ecd8e3762e1eb1c9809 100644 (file)
@@ -122,6 +122,12 @@ OSTooltip *X11Factory::createOSTooltip()
 }
 
 
+OSPopup *X11Factory::createOSPopup()
+{
+    return new X11Popup( getIntf(), *m_pDisplay );
+}
+
+
 int X11Factory::getScreenWidth() const
 {
     Display *pDisplay = m_pDisplay->getDisplay();
index 5e5e8401776365d8e692e3e2b490c42b70082f33..38ebfe95e39b51a78f6be1ed18e7dd9e7815d93b 100644 (file)
@@ -50,13 +50,13 @@ class X11Factory: public OSFactory
         /// Initialization method
         virtual bool init();
 
-        /// Instantiate an object OSGraphics.
+        /// Instantiate an object OSGraphics
         virtual OSGraphics *createOSGraphics( int width, int height );
 
-        /// Get the instance of the singleton OSLoop.
+        /// Get the instance of the singleton OSLoop
         virtual OSLoop *getOSLoop();
 
-        /// Destroy the instance of OSLoop.
+        /// Destroy the instance of OSLoop
         virtual void destroyOSLoop();
 
         /// Instantiate an OSTimer with the given command
@@ -70,9 +70,12 @@ class X11Factory: public OSFactory
                                           bool dragDrop, bool playOnDrop,
                                           OSWindow *pParent );
 
-        /// Instantiate an object OSTooltip.
+        /// Instantiate an object OSTooltip
         virtual OSTooltip *createOSTooltip();
 
+        /// Instantiate an object OSPopup
+        virtual OSPopup *createOSPopup();
+
         /// Get the directory separator
         virtual const string &getDirSeparator() const { return m_dirSep; }
 
diff --git a/modules/gui/skins2/x11/x11_popup.cpp b/modules/gui/skins2/x11/x11_popup.cpp
new file mode 100644 (file)
index 0000000..6f2a199
--- /dev/null
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * x11_popup.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <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
+ * 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.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include "x11_popup.hpp"
+
+
+X11Popup::X11Popup( intf_thread_t *pIntf )
+    : OSPopup( pIntf )
+{
+    // TODO
+}
+
+
+X11Popup::~X11Popup()
+{
+    // TODO
+}
+
+
+void X11Popup::show( int xPos, int yPos )
+{
+    // TODO
+}
+
+
+void X11Popup::hide()
+{
+    // TODO
+}
+
+
+void X11Popup::addItem( const string &rLabel, int pos )
+{
+    // TODO
+}
+
+
+void X11Popup::addSeparator( int pos )
+{
+    // TODO
+}
+
+
+int X11Popup::getPosFromId( int id ) const
+{
+    // TODO
+}
+
+
+#endif
+
diff --git a/modules/gui/skins2/x11/x11_popup.hpp b/modules/gui/skins2/x11/x11_popup.hpp
new file mode 100644 (file)
index 0000000..e1df526
--- /dev/null
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * x11_popup.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <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
+ * 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 X11_POPUP_HPP
+#define X11_POPUP_HPP
+
+#include "../src/os_popup.hpp"
+
+
+/// X11 implementation of OSPopup
+class X11Popup: public OSPopup
+{
+    public:
+        X11Popup( intf_thread_t *pIntf );
+
+        virtual ~X11Popup();
+
+        /// Show the popup menu at the given (absolute) corrdinates
+        virtual void show( int xPos, int yPos );
+
+        /// Hide the popup menu
+        virtual void hide();
+
+        /// Append a new menu item with the given label to the popup menu
+        virtual void addItem( const string &rLabel, int pos );
+
+        /// Create a dummy menu item to separate sections
+        virtual void addSeparator( int pos );
+
+        /// Return the position of the item identified by the given id
+        virtual int getPosFromId( int id ) const;
+};
+
+
+#endif
index b05fc3b3db3c6cf9597d18362b384b95dcad90d9..9218efa7a4a397a51d558f814fbf92d24635ff91 100644 (file)
@@ -40,10 +40,10 @@ class X11Tooltip: public OSTooltip
 
         virtual ~X11Tooltip();
 
-        // Show the tooltip
+        /// Show the tooltip
         virtual void show( int left, int top, OSGraphics &rText );
 
-        // Hide the tooltip
+        /// Hide the tooltip
         virtual void hide();
 
     private:
index c40f4153c51e07d5a5e0560ebb4cf00637d30a32..c7c5139e3845a00a1a041679bd2597646c78441c 100644 (file)
@@ -2,7 +2,7 @@
 -->
 
 
-<!ELEMENT Theme (ThemeInfo,(Include|Bitmap|BitmapFont|Font|Window)*)>
+<!ELEMENT Theme (ThemeInfo,(Include|Bitmap|BitmapFont|Font|PopupMenu|Window)*)>
     <!ATTLIST Theme
         version     CDATA   #REQUIRED
         tooltipfont CDATA   "defaultfont"
         file        CDATA   #REQUIRED
         type        CDATA   "digits"
     >
+<!ELEMENT PopupMenu (MenuItem|MenuSeparator)+>
+    <!ATTLIST PopupMenu
+        id          CDATA   #REQUIRED
+    >
+<!ELEMENT MenuItem EMPTY>
+    <!ATTLIST MenuItem
+        label       CDATA   #REQUIRED
+        action      CDATA   "none"
+    >
+<!ELEMENT MenuSeparator EMPTY>
 <!ELEMENT ThemeInfo EMPTY>
     <!ATTLIST ThemeInfo
         name        CDATA   #IMPLIED