]> git.sesse.net Git - vlc/commitdiff
* modules/gui/skins2/*:
authorOlivier Teulière <ipkiss@videolan.org>
Sat, 3 Jun 2006 23:57:40 +0000 (23:57 +0000)
committerOlivier Teulière <ipkiss@videolan.org>
Sat, 3 Jun 2006 23:57:40 +0000 (23:57 +0000)
     - anchors have a new "lefttop" attribute, allowing them to follow the
       border of the window when resizing
     - the resizing is now handled by the WindowManager class (to enforce the
       mediator pattern). This makes it possible to handle tricky cases,
       such as:
           window B is anchored to window A, and A is resized
           ==> B moves accordingly, and can still be anchored by other windows

16 files changed:
doc/skins/skins2-howto.xml
modules/gui/skins2/commands/cmd_resize.cpp
modules/gui/skins2/commands/cmd_resize.hpp
modules/gui/skins2/controls/ctrl_resize.cpp
modules/gui/skins2/controls/ctrl_resize.hpp
modules/gui/skins2/controls/ctrl_video.cpp
modules/gui/skins2/parser/builder.cpp
modules/gui/skins2/parser/builder_data.def
modules/gui/skins2/parser/builder_data.hpp
modules/gui/skins2/parser/skin_parser.cpp
modules/gui/skins2/src/anchor.hpp
modules/gui/skins2/src/generic_layout.cpp
modules/gui/skins2/src/window_manager.cpp
modules/gui/skins2/src/window_manager.hpp
modules/gui/skins2/utils/position.hpp
share/skins2/skin.dtd

index 37ce142d93bdb7f24ea6e400c9d13f38e6d001aa..4715121b9d005126181f4d9d30b2ea3c64ca6ea1 100644 (file)
@@ -379,6 +379,12 @@ difficulty to understand how VLC skins work.</para>
     <para>...</para>
     <para>Default value: 0</para>
   </sect4>
+  <sect4 id="anchorlefttop">
+    <title>lefttop</title>
+    <para>Indicate to which corner of the Layout the top-left-hand corner of this anchor is attached, in case of resizing. Possible values are 'lefttop', 'leftbottom', 'righttop' and 'rightbottom'.</para>
+    <para>Note that there is no "rightbottom" attribute for the anchors (contrarily to normal controls), because an anchor is not resizable (even when the anchor is not ponctual and follows a Bezier curve).</para>
+    <para>Default value: lefttop</para>
+  </sect4>
   <sect4 id="anchorpriority">
     <title>priority</title>
     <para>Priority of anchor (see the previous description).</para>
index cb4fc89fae73460814332e46029a90791af73cad..ea3e4bc66fbd7ebccd914bc4bd85ef959bc52b88 100644 (file)
 
 #include "cmd_resize.hpp"
 #include "../src/generic_layout.hpp"
+#include "../src/window_manager.hpp"
 #include "../src/vlcproc.hpp"
 
 
-CmdResize::CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width,
-                      int height ):
-    CmdGeneric( pIntf ), m_rLayout( rLayout ), m_width( width ),
-    m_height( height )
+CmdResize::CmdResize( intf_thread_t *pIntf, const WindowManager &rWindowManager,
+                      GenericLayout &rLayout, int width, int height ):
+    CmdGeneric( pIntf ), m_rWindowManager( rWindowManager ),
+    m_rLayout( rLayout ), m_width( width ), m_height( height )
 {
 }
 
@@ -38,7 +39,7 @@ CmdResize::CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width,
 void CmdResize::execute()
 {
     // Resize the layout
-    m_rLayout.resize( m_width, m_height );
+    m_rWindowManager.resize( m_rLayout, m_width, m_height );
 }
 
 
index 5dc0ea5e76ac5c12b97b9d081d70b7c6e16f4ecd..c554c1800fe2241775cd1451f0604d6e7cd9be83 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "cmd_generic.hpp"
 
+class WindowManager;
 class GenericLayout;
 
 
@@ -35,8 +36,8 @@ class CmdResize: public CmdGeneric
 {
     public:
         /// Resize the given layout
-        CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width,
-                   int height );
+        CmdResize( intf_thread_t *pIntf, const WindowManager &rWindowManager,
+                   GenericLayout &rLayout, int width, int height );
         virtual ~CmdResize() {}
 
         /// This method does the real job of the command
@@ -46,6 +47,7 @@ class CmdResize: public CmdGeneric
         virtual string getType() const { return "resize"; }
 
     private:
+        const WindowManager &m_rWindowManager;
         GenericLayout &m_rLayout;
         int m_width, m_height;
 };
index 7c8f5be9c9a327e9d919f1ab71c84e7290357c07..b9e4638b74013a8719c0abd9b8111d4d17d495d7 100644 (file)
 #include "../commands/cmd_resize.hpp"
 
 
-CtrlResize::CtrlResize( intf_thread_t *pIntf, CtrlFlat &rCtrl,
-                        GenericLayout &rLayout, const UString &rHelp,
-                        VarBool *pVisible, Direction_t direction ):
-    CtrlFlat( pIntf, rHelp, pVisible ), m_fsm( pIntf ), m_rCtrl( rCtrl ),
+CtrlResize::CtrlResize( intf_thread_t *pIntf, WindowManager &rWindowManager,
+                        CtrlFlat &rCtrl, GenericLayout &rLayout,
+                        const UString &rHelp, VarBool *pVisible,
+                        WindowManager::Direction_t direction ):
+    CtrlFlat( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
+    m_rWindowManager( rWindowManager ), m_rCtrl( rCtrl ),
     m_rLayout( rLayout ), m_direction( direction ),  m_cmdOutStill( this ),
     m_cmdStillOut( this ),
     m_cmdStillStill( this ),
@@ -103,16 +105,16 @@ void CtrlResize::handleEvent( EvtGeneric &rEvent )
 }
 
 
-void CtrlResize::changeCursor( Direction_t direction ) const
+void CtrlResize::changeCursor( WindowManager::Direction_t direction ) const
 {
     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
-    if( direction == kResizeSE )
+    if( direction == WindowManager::kResizeSE )
         pOsFactory->changeCursor( OSFactory::kResizeNWSE );
-    else if( direction == kResizeS )
+    else if( direction == WindowManager::kResizeS )
         pOsFactory->changeCursor( OSFactory::kResizeNS );
-    else if( direction == kResizeE )
+    else if( direction == WindowManager::kResizeE )
         pOsFactory->changeCursor( OSFactory::kResizeWE );
-    else if( direction == kNone )
+    else if( direction == WindowManager::kNone )
         pOsFactory->changeCursor( OSFactory::kDefaultArrow );
 }
 
@@ -125,7 +127,7 @@ void CtrlResize::CmdOutStill::execute()
 
 void CtrlResize::CmdStillOut::execute()
 {
-    m_pParent->changeCursor( kNone );
+    m_pParent->changeCursor( WindowManager::kNone );
 }
 
 
@@ -149,6 +151,9 @@ void CtrlResize::CmdStillResize::execute()
 
     m_pParent->m_width = m_pParent->m_rLayout.getWidth();
     m_pParent->m_height = m_pParent->m_rLayout.getHeight();
+
+    m_pParent->m_rWindowManager.startResize( m_pParent->m_rLayout,
+                                             m_pParent->m_direction);
 }
 
 
@@ -158,6 +163,8 @@ void CtrlResize::CmdResizeStill::execute()
     m_pParent->changeCursor( m_pParent->m_direction );
 
     m_pParent->releaseMouse();
+
+    m_pParent->m_rWindowManager.stopResize();
 }
 
 
@@ -169,17 +176,18 @@ void CtrlResize::CmdResizeResize::execute()
     m_pParent->changeCursor( m_pParent->m_direction );
 
     int newWidth = m_pParent->m_width;
+    newWidth += pEvtMotion->getXPos() - m_pParent->m_xPos;
     int newHeight = m_pParent->m_height;
-    if( m_pParent->m_direction != kResizeS )
-        newWidth += pEvtMotion->getXPos() - m_pParent->m_xPos;
-    if( m_pParent->m_direction != kResizeE )
-        newHeight += pEvtMotion->getYPos() - m_pParent->m_yPos;
+    newHeight += pEvtMotion->getYPos() - m_pParent->m_yPos;
 
-    // Create a resize command
+    // Create a resize command, instead of calling the window manager directly.
+    // Thanks to this trick, the duplicate resizing commands will be trashed
+    // in the asynchronous queue, thus making resizing faster
     CmdGeneric *pCmd = new CmdResize( m_pParent->getIntf(),
+                                      m_pParent->m_rWindowManager,
                                       m_pParent->m_rLayout,
                                       newWidth, newHeight );
     // Push the command in the asynchronous command queue
-    AsyncQueue *pQueue = AsyncQueue::instance( m_pParent->getIntf() );
+    AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
     pQueue->push( CmdGenericPtr( pCmd ) );
 }
index 19759a7c451d39100edf2e23e49a0bbb23ab1b2f..9a708d7d3653c81507db5b33280c6ac8d8572e2e 100644 (file)
 
 #include "ctrl_flat.hpp"
 #include "../commands/cmd_generic.hpp"
+#include "../src/window_manager.hpp"
 #include "../utils/fsm.hpp"
 
+class WindowManager;
+
 
 /// Control decorator for resizing windows
 class CtrlResize: public CtrlFlat
 {
     public:
-        enum Direction_t
-        {
-            kResizeE,   // East
-            kResizeSE,  // South-East
-            kResizeS,   // South
-            kNone       // Reserved for internal use
-        };
-
-        CtrlResize( intf_thread_t *pIntf, CtrlFlat &rCtrl,
-                    GenericLayout &rLayout, const UString &rHelp,
-                    VarBool *pVisible, Direction_t direction );
+        CtrlResize( intf_thread_t *pIntf, WindowManager &rWindowManager,
+                    CtrlFlat &rCtrl, GenericLayout &rLayout,
+                    const UString &rHelp, VarBool *pVisible,
+                    WindowManager::Direction_t direction );
         virtual ~CtrlResize() {}
 
         /// Handle an event
@@ -68,6 +64,8 @@ class CtrlResize: public CtrlFlat
 
     private:
         FSM m_fsm;
+        /// Window manager
+        WindowManager &m_rWindowManager;
         /// Decorated CtrlFlat
         CtrlFlat &m_rCtrl;
         /// The layout resized by this control
@@ -77,10 +75,10 @@ class CtrlResize: public CtrlFlat
         /// Position of the click that started the resizing
         int m_xPos, m_yPos;
         /// Direction of the resizing
-        Direction_t m_direction;
+        WindowManager::Direction_t m_direction;
 
         /// Change the cursor, based on the given direction
-        void changeCursor( Direction_t direction ) const;
+        void changeCursor( WindowManager::Direction_t direction ) const;
 
         /// Callback objects
         DEFINE_CALLBACK( CtrlResize, OutStill )
index 10e5721385a954c3bb1b0784d93194947c1f8547..c3db573928ea320b038555b04b2633cacb05f2e7 100644 (file)
@@ -26,6 +26,7 @@
 #include "../src/vout_window.hpp"
 #include "../src/os_graphics.hpp"
 #include "../src/vlcproc.hpp"
+#include "../src/window_manager.hpp"
 #include "../commands/async_queue.hpp"
 #include "../commands/cmd_resize.hpp"
 
@@ -106,11 +107,18 @@ void CtrlVideo::onUpdate( Subject<VarBox, void *> &rVoutSize, void *arg )
     int newHeight = ((VarBox&)rVoutSize).getHeight() + m_yShift;
 
     // Create a resize command
-    CmdGeneric *pCmd = new CmdResize( getIntf(), m_rLayout, newWidth,
-                                      newHeight );
+    // FIXME: this way of getting the window manager kind of sucks
+    WindowManager &rWindowManager =
+        getIntf()->p_sys->p_theme->getWindowManager();
+    rWindowManager.startResize( m_rLayout, WindowManager::kResizeSE );
+    CmdGeneric *pCmd = new CmdResize( getIntf(), rWindowManager,
+                                      m_rLayout, newWidth, newHeight );
     // Push the command in the asynchronous command queue
     AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
     pQueue->push( CmdGenericPtr( pCmd ) );
+
+    // FIXME: this should be a command too
+    rWindowManager.stopResize();
 }
 
 
index bc0d31927eb6a24a952a2acb42fa592c0cec2bfa..dc970d444e8563d253af8f88de8516e7e9d4709a 100644 (file)
@@ -38,6 +38,7 @@
 #include "../src/generic_layout.hpp"
 #include "../src/popup.hpp"
 #include "../src/theme.hpp"
+#include "../src/window_manager.hpp"
 #include "../commands/cmd_generic.hpp"
 #include "../controls/ctrl_button.hpp"
 #include "../controls/ctrl_checkbox.hpp"
@@ -377,8 +378,13 @@ void Builder::addAnchor( const BuilderData::Anchor &rData )
     }
     m_pTheme->m_curves.push_back( BezierPtr( pCurve ) );
 
-    Anchor *pAnc = new Anchor( getIntf(), rData.m_xPos, rData.m_yPos,
-                               rData.m_range, rData.m_priority,
+    // Compute the position of the anchor
+    const Position pos = makePosition( rData.m_leftTop, rData.m_leftTop,
+                                       rData.m_xPos, rData.m_yPos,
+                                       pCurve->getWidth(),
+                                       pCurve->getHeight(), *pLayout );
+
+    Anchor *pAnc = new Anchor( getIntf(), pos, rData.m_range, rData.m_priority,
                                *pCurve, *pLayout );
     pLayout->addAnchor( pAnc );
 }
@@ -559,23 +565,26 @@ void Builder::addImage( const BuilderData::Image &rData )
     }
     else if( rData.m_actionId == "resizeS" )
     {
-        CtrlResize *pResize = new CtrlResize( getIntf(), *pImage, *pLayout,
+        CtrlResize *pResize = new CtrlResize( getIntf(),
+                m_pTheme->getWindowManager(), *pImage, *pLayout,
                 UString( getIntf(), rData.m_help.c_str() ), pVisible,
-                CtrlResize::kResizeS );
+                WindowManager::kResizeS );
         pLayout->addControl( pResize, pos, rData.m_layer );
     }
     else if( rData.m_actionId == "resizeE" )
     {
-        CtrlResize *pResize = new CtrlResize( getIntf(), *pImage, *pLayout,
+        CtrlResize *pResize = new CtrlResize( getIntf(),
+                m_pTheme->getWindowManager(), *pImage, *pLayout,
                 UString( getIntf(), rData.m_help.c_str() ), pVisible,
-                CtrlResize::kResizeE );
+                WindowManager::kResizeE );
         pLayout->addControl( pResize, pos, rData.m_layer );
     }
     else if( rData.m_actionId == "resizeSE" )
     {
-        CtrlResize *pResize = new CtrlResize( getIntf(), *pImage, *pLayout,
+        CtrlResize *pResize = new CtrlResize( getIntf(),
+                m_pTheme->getWindowManager(), *pImage, *pLayout,
                 UString( getIntf(), rData.m_help.c_str() ), pVisible,
-                CtrlResize::kResizeSE );
+                WindowManager::kResizeSE );
         pLayout->addControl( pResize, pos, rData.m_layer );
     }
     else
index 2e69ec659e4b4c00a5063c3f61df012a09407f71..7c673bd5adfe3bbb89f4410fe84a25a63a023e21 100644 (file)
@@ -8,7 +8,7 @@ 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
+Anchor xPos:int yPos:int leftTop:string range:int priority:int points:string layoutId:string
 Button id:string xPos:int yPos:int leftTop:string rightBottom:string visible:string upId:string downId:string overId:string actionId:string tooltip:string help:string layer:int windowId:string layoutId:string
 Checkbox id:string xPos:int yPos:int leftTop:string rightBottom:string visible:string up1Id:string down1Id:string over1Id:string up2Id:string down2Id:string over2Id:string state:string action1:string action2:string tooltip1:string tooltip2:string help:string layer:int windowId:string layoutId:string
 Image id:string xPos:int yPos:int leftTop:string rightBottom:string visible:string bmpId:string actionId:string action2Id:string resize:string help:string layer:int windowId:string layoutId:string
index b3450b770ca5fa0aa03784881647d5e0235aabe8..61ed07b99bb1441c72d618c4131ac8dc4a9a43bb 100644 (file)
@@ -186,11 +186,12 @@ m_id( id ), m_width( width ), m_height( height ), m_minWidth( minWidth ), m_maxW
     /// Type definition
     struct Anchor
     {
-        Anchor( int xPos, int yPos, int range, int priority, const string & points, const string & layoutId ):
-m_xPos( xPos ), m_yPos( yPos ), m_range( range ), m_priority( priority ), m_points( points ), m_layoutId( layoutId ) {}
+        Anchor( int xPos, int yPos, const string & leftTop, int range, int priority, const string & points, const string & layoutId ):
+m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_range( range ), m_priority( priority ), m_points( points ), m_layoutId( layoutId ) {}
 
         int m_xPos;
         int m_yPos;
+        string m_leftTop;
         int m_range;
         int m_priority;
         string m_points;
index a4553b358a2a465551272d2d6c9ef397ed997814..4c994406934b0471c0f69ec0e58311a7b1870f1c 100644 (file)
@@ -88,12 +88,14 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
         RequireDefault( "priority" );
         CheckDefault( "x", "0" );
         CheckDefault( "y", "0" );
+        CheckDefault( "lefttop", "lefttop" );
         CheckDefault( "points", "(0,0)" );
         CheckDefault( "range", "10" );
 
         const BuilderData::Anchor anchor( atoi( attr["x"] ) + m_xOffset,
-                atoi( attr["y"] ) + m_yOffset, atoi( attr["range"] ),
-                atoi( attr["priority"] ), attr["points"], m_curLayoutId );
+                atoi( attr["y"] ) + m_yOffset, attr["lefttop"],
+                atoi( attr["range"] ), atoi( attr["priority"] ),
+                attr["points"], m_curLayoutId );
         m_pData->m_listAnchor.push_back( anchor );
     }
 
index f958f22eeb085f76e3812393f321bc6c8914adac..9b5dfcdf52c6501769e87542b1a3482062dc23d5 100644 (file)
 #include "skin_common.hpp"
 #include "generic_layout.hpp"
 #include "../utils/bezier.hpp"
+#include "../utils/position.hpp"
 
 
 /// Class for the windows anchors
 class Anchor: public SkinObject
 {
     public:
-        Anchor( intf_thread_t *pIntf, int xPos, int yPos, int range,
+        Anchor( intf_thread_t *pIntf, const Position &rPosition, int range,
                 int priority, const Bezier &rCurve, GenericLayout &rLayout ):
-            SkinObject( pIntf ), m_xPos( xPos ), m_yPos( yPos ),
+            SkinObject( pIntf ), m_position( rPosition ),
             m_rCurve( rCurve ), m_range( range ), m_priority( priority ),
             m_rLayout( rLayout ) {}
         virtual ~Anchor() {}
 
-        /// Return true if the given anchor is hanged by this one
-        /// Two conditions are required:
-        ///  - the other anchor must be in position of anchoring (as defined
-        ///    by canHang())
-        ///  - the priority of the other anchor must be lower than this one's
+        /**
+         * Return true if the given anchor is hanged by this one
+         * Two conditions are required:
+         *  - the other anchor must be in position of anchoring (as defined
+         *    by canHang())
+         *  - the priority of the other anchor must be lower than this one's
+         */
         bool isHanging( const Anchor &rOther ) const;
 
-        /// Return true if the other anchor, moved by the (xOffset, yOffset)
-        /// vector, is "hangable" by this one (i.e. if it is in its range of
-        /// action), else return false.
-        /// When the function returns true, the xOffset and yOffset parameters
-        /// are modified to indicate the position that the other anchor would
-        /// take if hanged by this one (this position is calculated to minimize
-        /// the difference with the old xOffset and yOffset, so that the window
-        /// doesn't "jump" in a strange way).
+        /**
+         * Return true if the other anchor, moved by the (xOffset, yOffset)
+         * vector, is "hangable" by this one (i.e. if it is in its range of
+         * action), else return false.
+         * When the function returns true, the xOffset and yOffset parameters
+         * are modified to indicate the position that the other anchor would
+         * take if hanged by this one (this position is calculated to minimize
+         * the difference with the old xOffset and yOffset, so that the window
+         * doesn't "jump" in a strange way).
+         */
         bool canHang( const Anchor &rOther, int &xOffset, int &yOffset ) const;
 
         // Indicate whether this anchor is reduced to a single point
         bool isPoint() const { return m_rCurve.getNbCtrlPoints() == 1; }
 
         // Getters
-        int getXPosAbs() const { return (m_xPos + m_rLayout.getLeft()); }
-        int getYPosAbs() const { return (m_yPos + m_rLayout.getTop()); }
+        const Position & getPosition() const { return m_position; }
+
+        int getXPosAbs() const
+        {
+            return (m_position.getLeft() + m_rLayout.getLeft());
+        }
+
+        int getYPosAbs() const
+        {
+            return (m_position.getTop() + m_rLayout.getTop());
+        }
 
     private:
-        /// Coordinates relative to the window
-        int m_xPos, m_yPos;
+        /// Position in the layout
+        Position m_position;
 
         /// Curve of the anchor
         const Bezier &m_rCurve;
@@ -78,7 +92,7 @@ class Anchor: public SkinObject
         /// Priority
         int m_priority;
 
-        /// Parent window
+        /// Parent layout
         GenericLayout &m_rLayout;
 };
 
index 9884d06109d0918330a5c4501f6f9898be7d106c..444836b43134f0fb82e8eeb06866bcb17483ae4f 100644 (file)
@@ -158,29 +158,6 @@ void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
 
 void GenericLayout::resize( int width, int height )
 {
-    // Check boundaries
-    if( width < m_minWidth )
-    {
-        width = m_minWidth;
-    }
-    if( width > m_maxWidth )
-    {
-        width = m_maxWidth;
-    }
-    if( height < m_minHeight )
-    {
-        height = m_minHeight;
-    }
-    if( height > m_maxHeight )
-    {
-        height = m_maxHeight;
-    }
-
-    if( width == m_width && height == m_height )
-    {
-        return;
-    }
-
     // Update the window size
     m_width = width;
     m_height = height;
index 7fb32b587805ddf1a69534d71492c4cc36644f55..f93ffea3da7675b62d58cb29e2ce0baf92e1d804 100644 (file)
 #include "os_factory.hpp"
 #include "anchor.hpp"
 #include "tooltip.hpp"
+#include "var_manager.hpp"
 #include "../utils/position.hpp"
-#include "../src/var_manager.hpp"
 
 
 WindowManager::WindowManager( intf_thread_t *pIntf ):
-    SkinObject( pIntf ), m_magnet( 0 ), m_pTooltip( NULL ), m_pPopup( NULL )
+    SkinObject( pIntf ), m_magnet( 0 ), m_direction( kNone ),
+    m_pTooltip( NULL ), m_pPopup( NULL )
 {
     // Create and register a variable for the "on top" status
     VarManager *pVarManager = VarManager::instance( getIntf() );
@@ -170,6 +171,152 @@ void WindowManager::move( TopWindow &rWindow, int left, int top ) const
 }
 
 
+void WindowManager::startResize( GenericLayout &rLayout, Direction_t direction )
+{
+    m_direction = direction;
+
+    // Rebuild the set of moving windows.
+    // From the resized window, we only take into account the anchors which
+    // are mobile with the current type of resizing, and that are hanging a
+    // window. The hanged windows will come will all their dependencies.
+
+    m_resizeMovingE.clear();
+    m_resizeMovingS.clear();
+    m_resizeMovingSE.clear();
+
+    WinSet_t::const_iterator itWin;
+    AncList_t::const_iterator itAnc1, itAnc2;
+    // Get the anchors of the layout
+    const AncList_t &ancList1 = rLayout.getAnchorList();
+
+    // Iterate through all the hanged windows
+    for( itWin = m_dependencies[rLayout.getWindow()].begin();
+         itWin != m_dependencies[rLayout.getWindow()].end(); itWin++ )
+    {
+        // Now, check for anchoring between the 2 windows
+        const AncList_t &ancList2 =
+            (*itWin)->getActiveLayout().getAnchorList();
+        for( itAnc1 = ancList1.begin(); itAnc1 != ancList1.end(); itAnc1++ )
+        {
+            for( itAnc2 = ancList2.begin();
+                 itAnc2 != ancList2.end(); itAnc2++ )
+            {
+                if( (*itAnc1)->isHanging( **itAnc2 ) )
+                {
+                    // Add the dependencies of the hanged window to one of the
+                    // lists of moving windows
+                    Position::Ref_t aRefPos =
+                        (*itAnc1)->getPosition().getRefLeftTop();
+                    if( aRefPos == Position::kRightTop )
+                        buildDependSet( m_resizeMovingE, *itWin );
+                    else if( aRefPos == Position::kLeftBottom )
+                        buildDependSet( m_resizeMovingS, *itWin );
+                    else if( aRefPos == Position::kRightBottom )
+                        buildDependSet( m_resizeMovingSE, *itWin );
+                    break;
+                }
+            }
+        }
+    }
+
+    // The checkAnchors() method will need to have m_movingWindows properly set
+    // so let's insert in it the contents of the other sets
+    m_movingWindows.clear();
+    m_movingWindows.insert( rLayout.getWindow() );
+    m_movingWindows.insert( m_resizeMovingE.begin(), m_resizeMovingE.end() );
+    m_movingWindows.insert( m_resizeMovingS.begin(), m_resizeMovingS.end() );
+    m_movingWindows.insert( m_resizeMovingSE.begin(), m_resizeMovingSE.end() );
+}
+
+
+void WindowManager::stopResize()
+{
+    // Nothing different from stopMove(), luckily
+    stopMove();
+}
+
+
+void WindowManager::resize( GenericLayout &rLayout,
+                            int width, int height ) const
+{
+    // TODO: handle anchored windows
+    // Compute the real resizing offset
+    int xOffset = width - rLayout.getWidth();
+    int yOffset = height - rLayout.getHeight();
+
+    // Check anchoring; this can change the values of xOffset and yOffset
+    checkAnchors( rLayout.getWindow(), xOffset, yOffset );
+    if( m_direction == kResizeS )
+        xOffset = 0;
+    if( m_direction == kResizeE )
+        yOffset = 0;
+
+    int newWidth = rLayout.getWidth() + xOffset;
+    int newHeight = rLayout.getHeight() + yOffset;
+
+    // Check boundaries
+    if( newWidth < rLayout.getMinWidth() )
+    {
+        newWidth = rLayout.getMinWidth();
+    }
+    if( newWidth > rLayout.getMaxWidth() )
+    {
+        newWidth = rLayout.getMaxWidth();
+    }
+    if( newHeight < rLayout.getMinHeight() )
+    {
+        newHeight = rLayout.getMinHeight();
+    }
+    if( newHeight > rLayout.getMaxHeight() )
+    {
+        newHeight = rLayout.getMaxHeight();
+    }
+
+    if( newWidth == rLayout.getWidth() && newHeight == rLayout.getHeight() )
+    {
+        return;
+    }
+
+    // New offset, after the last corrections
+    int xNewOffset = newWidth - rLayout.getWidth();
+    int yNewOffset = newHeight - rLayout.getHeight();
+
+    // Do the actual resizing
+    rLayout.resize( newWidth, newHeight );
+
+    // Move all the anchored windows
+    WinSet_t::const_iterator it;
+    if( m_direction == kResizeE ||
+        m_direction == kResizeSE )
+    {
+        for( it = m_resizeMovingE.begin(); it != m_resizeMovingE.end(); it++ )
+        {
+            (*it)->move( (*it)->getLeft() + xNewOffset,
+                         (*it)->getTop() );
+        }
+    }
+    if( m_direction == kResizeE ||
+        m_direction == kResizeSE )
+    {
+        for( it = m_resizeMovingS.begin(); it != m_resizeMovingS.end(); it++ )
+        {
+            (*it)->move( (*it)->getLeft(),
+                         (*it)->getTop( )+ yNewOffset );
+        }
+    }
+    if( m_direction == kResizeE ||
+        m_direction == kResizeS ||
+        m_direction == kResizeSE )
+    {
+        for( it = m_resizeMovingSE.begin(); it != m_resizeMovingSE.end(); it++ )
+        {
+            (*it)->move( (*it)->getLeft() + xNewOffset,
+                         (*it)->getTop() + yNewOffset );
+        }
+    }
+}
+
+
 void WindowManager::synchVisibility() const
 {
     WinSet_t::const_iterator it;
@@ -203,7 +350,7 @@ void WindowManager::showAll( bool firstTime ) const
     {
         // When the theme is opened for the first time,
         // only show the window if set as visible in the XML
-        if ((*it)->isVisible() || !firstTime)
+        if( (*it)->isVisible() || !firstTime )
         {
             (*it)->show();
         }
@@ -381,7 +528,7 @@ void WindowManager::createTooltip( const GenericFont &rTipFont )
     }
     else
     {
-        msg_Warn( getIntf(), "tooltip already created!");
+        msg_Warn( getIntf(), "tooltip already created!" );
     }
 }
 
index b67fe0d2421596157459dae0fe8b4c3627a91204..ba738f441bec046f12807e646f09a4f5f0d3afe3 100644 (file)
@@ -44,6 +44,15 @@ class Popup;
 class WindowManager: public SkinObject
 {
     public:
+        /// Direction of the resizing
+        enum Direction_t
+        {
+            kResizeE,   // East
+            kResizeSE,  // South-East
+            kResizeS,   // South
+            kNone       // Reserved for internal use
+        };
+
         /// Constructor
         WindowManager( intf_thread_t *pIntf);
 
@@ -57,22 +66,38 @@ class WindowManager: public SkinObject
         /// Remove a previously registered window
         void unregisterWindow( TopWindow &rWindow );
 
-        /// Tell the window manager that a move is initiated for pWindow.
+        /// Tell the window manager that a move is initiated for rWindow
         void startMove( TopWindow &rWindow );
 
-        /// Tell the window manager that the current move ended.
+        /// Tell the window manager that the current move ended
         void stopMove();
 
-        /// Move the pWindow window to (left, top), and move all its
-        /// anchored windows.
-        /// If a new anchoring is detected, the windows will move accordingly.
+        /**
+         * Move the rWindow window to (left, top), and move all its
+         * anchored windows.
+         * If a new anchoring is detected, the windows will move accordingly.
+         */
         void move( TopWindow &rWindow, int left, int top ) const;
 
+        /// Tell the window manager that a resize is initiated for rWindow
+        void startResize( GenericLayout &rLayout, Direction_t direction );
+
+        /// Tell the window manager that the current resizing ended
+        void stopResize();
+
+        /**
+         * Resize the rWindow window to (width, height), and move all its
+         * anchored windows, if some anchors are moved during the resizing.
+         * If a new anchoring is detected, the windows will move (or resize)
+         * accordingly.
+         */
+        void resize( GenericLayout &rLayout, int width, int height ) const;
+
         /// Raise all the registered windows
         void raiseAll() const;
 
         /// Show all the registered windows
-        void showAll(bool firstTime = false) const;
+        void showAll( bool firstTime = false ) const;
 
         /// Hide all the registered windows
         void hideAll() const;
@@ -142,6 +167,15 @@ class WindowManager: public SkinObject
         /// Store the moving windows; this set is updated at every start of
         /// move.
         WinSet_t m_movingWindows;
+        /**
+         * Store the moving windows in the context of resizing
+         * These sets are updated at every start of move
+         */
+        //@{
+        WinSet_t m_resizeMovingE;
+        WinSet_t m_resizeMovingS;
+        WinSet_t m_resizeMovingSE;
+        //@}
         /// Indicate whether the windows are currently on top
         VariablePtr m_cVarOnTop;
         /// Magnetism of the screen edges (= scope of action)
@@ -150,6 +184,8 @@ class WindowManager: public SkinObject
         int m_alpha;
         /// Alpha value of the moving windows
         int m_moveAlpha;
+        /// Direction of the current resizing
+        Direction_t m_direction;
         /// Tooltip
         Tooltip *m_pTooltip;
         /// Active popup, if any
index 5313b728577564eedfa928877eb8fb57df503ef1..08550033bc7b0f52c8288e4c8e9895434ffe3f02 100644 (file)
@@ -95,6 +95,9 @@ class Position
         /// Get the size of the rectangle
         int getWidth() const;
         int getHeight() const;
+        /// Get the reference corners
+        Ref_t getRefLeftTop() const { return m_refLeftTop; }
+        Ref_t getRefRightBottom() const { return m_refRighBottom; }
 
     private:
         /// Position and reference edge/corner
index 703c7f9856db774b27f4e0d3f81b246b0eb03b5a..f39ea28080a35ad02787a49baf7f52d1b8ebd661 100644 (file)
@@ -99,6 +99,7 @@
     <!ATTLIST Anchor
         x           CDATA   "0"
         y           CDATA   "0"
+        lefttop     CDATA   "lefttop"
         priority    CDATA   #REQUIRED
         points      CDATA   "(0,0)"
         range       CDATA   "10"