Commit 24648f43 authored by Olivier Teulière's avatar Olivier Teulière

* modules/gui/skins2/*:

     - 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
parent fef44fa9
...@@ -379,6 +379,12 @@ difficulty to understand how VLC skins work.</para> ...@@ -379,6 +379,12 @@ difficulty to understand how VLC skins work.</para>
<para>...</para> <para>...</para>
<para>Default value: 0</para> <para>Default value: 0</para>
</sect4> </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"> <sect4 id="anchorpriority">
<title>priority</title> <title>priority</title>
<para>Priority of anchor (see the previous description).</para> <para>Priority of anchor (see the previous description).</para>
......
...@@ -24,13 +24,14 @@ ...@@ -24,13 +24,14 @@
#include "cmd_resize.hpp" #include "cmd_resize.hpp"
#include "../src/generic_layout.hpp" #include "../src/generic_layout.hpp"
#include "../src/window_manager.hpp"
#include "../src/vlcproc.hpp" #include "../src/vlcproc.hpp"
CmdResize::CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width, CmdResize::CmdResize( intf_thread_t *pIntf, const WindowManager &rWindowManager,
int height ): GenericLayout &rLayout, int width, int height ):
CmdGeneric( pIntf ), m_rLayout( rLayout ), m_width( width ), CmdGeneric( pIntf ), m_rWindowManager( rWindowManager ),
m_height( height ) m_rLayout( rLayout ), m_width( width ), m_height( height )
{ {
} }
...@@ -38,7 +39,7 @@ CmdResize::CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width, ...@@ -38,7 +39,7 @@ CmdResize::CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width,
void CmdResize::execute() void CmdResize::execute()
{ {
// Resize the layout // Resize the layout
m_rLayout.resize( m_width, m_height ); m_rWindowManager.resize( m_rLayout, m_width, m_height );
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "cmd_generic.hpp" #include "cmd_generic.hpp"
class WindowManager;
class GenericLayout; class GenericLayout;
...@@ -35,8 +36,8 @@ class CmdResize: public CmdGeneric ...@@ -35,8 +36,8 @@ class CmdResize: public CmdGeneric
{ {
public: public:
/// Resize the given layout /// Resize the given layout
CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width, CmdResize( intf_thread_t *pIntf, const WindowManager &rWindowManager,
int height ); GenericLayout &rLayout, int width, int height );
virtual ~CmdResize() {} virtual ~CmdResize() {}
/// This method does the real job of the command /// This method does the real job of the command
...@@ -46,6 +47,7 @@ class CmdResize: public CmdGeneric ...@@ -46,6 +47,7 @@ class CmdResize: public CmdGeneric
virtual string getType() const { return "resize"; } virtual string getType() const { return "resize"; }
private: private:
const WindowManager &m_rWindowManager;
GenericLayout &m_rLayout; GenericLayout &m_rLayout;
int m_width, m_height; int m_width, m_height;
}; };
......
...@@ -33,10 +33,12 @@ ...@@ -33,10 +33,12 @@
#include "../commands/cmd_resize.hpp" #include "../commands/cmd_resize.hpp"
CtrlResize::CtrlResize( intf_thread_t *pIntf, CtrlFlat &rCtrl, CtrlResize::CtrlResize( intf_thread_t *pIntf, WindowManager &rWindowManager,
GenericLayout &rLayout, const UString &rHelp, CtrlFlat &rCtrl, GenericLayout &rLayout,
VarBool *pVisible, Direction_t direction ): const UString &rHelp, VarBool *pVisible,
CtrlFlat( pIntf, rHelp, pVisible ), m_fsm( pIntf ), m_rCtrl( rCtrl ), 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_rLayout( rLayout ), m_direction( direction ), m_cmdOutStill( this ),
m_cmdStillOut( this ), m_cmdStillOut( this ),
m_cmdStillStill( this ), m_cmdStillStill( this ),
...@@ -103,16 +105,16 @@ void CtrlResize::handleEvent( EvtGeneric &rEvent ) ...@@ -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() ); OSFactory *pOsFactory = OSFactory::instance( getIntf() );
if( direction == kResizeSE ) if( direction == WindowManager::kResizeSE )
pOsFactory->changeCursor( OSFactory::kResizeNWSE ); pOsFactory->changeCursor( OSFactory::kResizeNWSE );
else if( direction == kResizeS ) else if( direction == WindowManager::kResizeS )
pOsFactory->changeCursor( OSFactory::kResizeNS ); pOsFactory->changeCursor( OSFactory::kResizeNS );
else if( direction == kResizeE ) else if( direction == WindowManager::kResizeE )
pOsFactory->changeCursor( OSFactory::kResizeWE ); pOsFactory->changeCursor( OSFactory::kResizeWE );
else if( direction == kNone ) else if( direction == WindowManager::kNone )
pOsFactory->changeCursor( OSFactory::kDefaultArrow ); pOsFactory->changeCursor( OSFactory::kDefaultArrow );
} }
...@@ -125,7 +127,7 @@ void CtrlResize::CmdOutStill::execute() ...@@ -125,7 +127,7 @@ void CtrlResize::CmdOutStill::execute()
void CtrlResize::CmdStillOut::execute() void CtrlResize::CmdStillOut::execute()
{ {
m_pParent->changeCursor( kNone ); m_pParent->changeCursor( WindowManager::kNone );
} }
...@@ -149,6 +151,9 @@ void CtrlResize::CmdStillResize::execute() ...@@ -149,6 +151,9 @@ void CtrlResize::CmdStillResize::execute()
m_pParent->m_width = m_pParent->m_rLayout.getWidth(); m_pParent->m_width = m_pParent->m_rLayout.getWidth();
m_pParent->m_height = m_pParent->m_rLayout.getHeight(); 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() ...@@ -158,6 +163,8 @@ void CtrlResize::CmdResizeStill::execute()
m_pParent->changeCursor( m_pParent->m_direction ); m_pParent->changeCursor( m_pParent->m_direction );
m_pParent->releaseMouse(); m_pParent->releaseMouse();
m_pParent->m_rWindowManager.stopResize();
} }
...@@ -169,17 +176,18 @@ void CtrlResize::CmdResizeResize::execute() ...@@ -169,17 +176,18 @@ void CtrlResize::CmdResizeResize::execute()
m_pParent->changeCursor( m_pParent->m_direction ); m_pParent->changeCursor( m_pParent->m_direction );
int newWidth = m_pParent->m_width; int newWidth = m_pParent->m_width;
newWidth += pEvtMotion->getXPos() - m_pParent->m_xPos;
int newHeight = m_pParent->m_height; int newHeight = m_pParent->m_height;
if( m_pParent->m_direction != kResizeS ) newHeight += pEvtMotion->getYPos() - m_pParent->m_yPos;
newWidth += pEvtMotion->getXPos() - m_pParent->m_xPos;
if( m_pParent->m_direction != kResizeE )
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(), CmdGeneric *pCmd = new CmdResize( m_pParent->getIntf(),
m_pParent->m_rWindowManager,
m_pParent->m_rLayout, m_pParent->m_rLayout,
newWidth, newHeight ); newWidth, newHeight );
// Push the command in the asynchronous command queue // Push the command in the asynchronous command queue
AsyncQueue *pQueue = AsyncQueue::instance( m_pParent->getIntf() ); AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) ); pQueue->push( CmdGenericPtr( pCmd ) );
} }
...@@ -27,24 +27,20 @@ ...@@ -27,24 +27,20 @@
#include "ctrl_flat.hpp" #include "ctrl_flat.hpp"
#include "../commands/cmd_generic.hpp" #include "../commands/cmd_generic.hpp"
#include "../src/window_manager.hpp"
#include "../utils/fsm.hpp" #include "../utils/fsm.hpp"
class WindowManager;
/// Control decorator for resizing windows /// Control decorator for resizing windows
class CtrlResize: public CtrlFlat class CtrlResize: public CtrlFlat
{ {
public: public:
enum Direction_t CtrlResize( intf_thread_t *pIntf, WindowManager &rWindowManager,
{ CtrlFlat &rCtrl, GenericLayout &rLayout,
kResizeE, // East const UString &rHelp, VarBool *pVisible,
kResizeSE, // South-East WindowManager::Direction_t direction );
kResizeS, // South
kNone // Reserved for internal use
};
CtrlResize( intf_thread_t *pIntf, CtrlFlat &rCtrl,
GenericLayout &rLayout, const UString &rHelp,
VarBool *pVisible, Direction_t direction );
virtual ~CtrlResize() {} virtual ~CtrlResize() {}
/// Handle an event /// Handle an event
...@@ -68,6 +64,8 @@ class CtrlResize: public CtrlFlat ...@@ -68,6 +64,8 @@ class CtrlResize: public CtrlFlat
private: private:
FSM m_fsm; FSM m_fsm;
/// Window manager
WindowManager &m_rWindowManager;
/// Decorated CtrlFlat /// Decorated CtrlFlat
CtrlFlat &m_rCtrl; CtrlFlat &m_rCtrl;
/// The layout resized by this control /// The layout resized by this control
...@@ -77,10 +75,10 @@ class CtrlResize: public CtrlFlat ...@@ -77,10 +75,10 @@ class CtrlResize: public CtrlFlat
/// Position of the click that started the resizing /// Position of the click that started the resizing
int m_xPos, m_yPos; int m_xPos, m_yPos;
/// Direction of the resizing /// Direction of the resizing
Direction_t m_direction; WindowManager::Direction_t m_direction;
/// Change the cursor, based on the given direction /// Change the cursor, based on the given direction
void changeCursor( Direction_t direction ) const; void changeCursor( WindowManager::Direction_t direction ) const;
/// Callback objects /// Callback objects
DEFINE_CALLBACK( CtrlResize, OutStill ) DEFINE_CALLBACK( CtrlResize, OutStill )
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "../src/vout_window.hpp" #include "../src/vout_window.hpp"
#include "../src/os_graphics.hpp" #include "../src/os_graphics.hpp"
#include "../src/vlcproc.hpp" #include "../src/vlcproc.hpp"
#include "../src/window_manager.hpp"
#include "../commands/async_queue.hpp" #include "../commands/async_queue.hpp"
#include "../commands/cmd_resize.hpp" #include "../commands/cmd_resize.hpp"
...@@ -106,11 +107,18 @@ void CtrlVideo::onUpdate( Subject<VarBox, void *> &rVoutSize, void *arg ) ...@@ -106,11 +107,18 @@ void CtrlVideo::onUpdate( Subject<VarBox, void *> &rVoutSize, void *arg )
int newHeight = ((VarBox&)rVoutSize).getHeight() + m_yShift; int newHeight = ((VarBox&)rVoutSize).getHeight() + m_yShift;
// Create a resize command // Create a resize command
CmdGeneric *pCmd = new CmdResize( getIntf(), m_rLayout, newWidth, // FIXME: this way of getting the window manager kind of sucks
newHeight ); 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 // Push the command in the asynchronous command queue
AsyncQueue *pQueue = AsyncQueue::instance( getIntf() ); AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) ); pQueue->push( CmdGenericPtr( pCmd ) );
// FIXME: this should be a command too
rWindowManager.stopResize();
} }
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "../src/generic_layout.hpp" #include "../src/generic_layout.hpp"
#include "../src/popup.hpp" #include "../src/popup.hpp"
#include "../src/theme.hpp" #include "../src/theme.hpp"
#include "../src/window_manager.hpp"
#include "../commands/cmd_generic.hpp" #include "../commands/cmd_generic.hpp"
#include "../controls/ctrl_button.hpp" #include "../controls/ctrl_button.hpp"
#include "../controls/ctrl_checkbox.hpp" #include "../controls/ctrl_checkbox.hpp"
...@@ -377,8 +378,13 @@ void Builder::addAnchor( const BuilderData::Anchor &rData ) ...@@ -377,8 +378,13 @@ void Builder::addAnchor( const BuilderData::Anchor &rData )
} }
m_pTheme->m_curves.push_back( BezierPtr( pCurve ) ); m_pTheme->m_curves.push_back( BezierPtr( pCurve ) );
Anchor *pAnc = new Anchor( getIntf(), rData.m_xPos, rData.m_yPos, // Compute the position of the anchor
rData.m_range, rData.m_priority, 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 ); *pCurve, *pLayout );
pLayout->addAnchor( pAnc ); pLayout->addAnchor( pAnc );
} }
...@@ -559,23 +565,26 @@ void Builder::addImage( const BuilderData::Image &rData ) ...@@ -559,23 +565,26 @@ void Builder::addImage( const BuilderData::Image &rData )
} }
else if( rData.m_actionId == "resizeS" ) 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, UString( getIntf(), rData.m_help.c_str() ), pVisible,
CtrlResize::kResizeS ); WindowManager::kResizeS );
pLayout->addControl( pResize, pos, rData.m_layer ); pLayout->addControl( pResize, pos, rData.m_layer );
} }
else if( rData.m_actionId == "resizeE" ) 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, UString( getIntf(), rData.m_help.c_str() ), pVisible,
CtrlResize::kResizeE ); WindowManager::kResizeE );
pLayout->addControl( pResize, pos, rData.m_layer ); pLayout->addControl( pResize, pos, rData.m_layer );
} }
else if( rData.m_actionId == "resizeSE" ) 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, UString( getIntf(), rData.m_help.c_str() ), pVisible,
CtrlResize::kResizeSE ); WindowManager::kResizeSE );
pLayout->addControl( pResize, pos, rData.m_layer ); pLayout->addControl( pResize, pos, rData.m_layer );
} }
else else
......
...@@ -8,7 +8,7 @@ MenuItem label:string action:string pos:int popupId:string ...@@ -8,7 +8,7 @@ MenuItem label:string action:string pos:int popupId:string
MenuSeparator pos:int popupId:string MenuSeparator pos:int popupId:string
Window id:string xPos:int yPos:int visible:bool dragDrop:bool playOnDrop:bool 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 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 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 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 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
......
...@@ -186,11 +186,12 @@ m_id( id ), m_width( width ), m_height( height ), m_minWidth( minWidth ), m_maxW ...@@ -186,11 +186,12 @@ m_id( id ), m_width( width ), m_height( height ), m_minWidth( minWidth ), m_maxW
/// Type definition /// Type definition
struct Anchor struct Anchor
{ {
Anchor( int xPos, int yPos, int range, int priority, const string & points, const string & 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_range( range ), m_priority( priority ), m_points( points ), m_layoutId( 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_xPos;
int m_yPos; int m_yPos;
string m_leftTop;
int m_range; int m_range;
int m_priority; int m_priority;
string m_points; string m_points;
......
...@@ -88,12 +88,14 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr ) ...@@ -88,12 +88,14 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
RequireDefault( "priority" ); RequireDefault( "priority" );
CheckDefault( "x", "0" ); CheckDefault( "x", "0" );
CheckDefault( "y", "0" ); CheckDefault( "y", "0" );
CheckDefault( "lefttop", "lefttop" );
CheckDefault( "points", "(0,0)" ); CheckDefault( "points", "(0,0)" );
CheckDefault( "range", "10" ); CheckDefault( "range", "10" );
const BuilderData::Anchor anchor( atoi( attr["x"] ) + m_xOffset, const BuilderData::Anchor anchor( atoi( attr["x"] ) + m_xOffset,
atoi( attr["y"] ) + m_yOffset, atoi( attr["range"] ), atoi( attr["y"] ) + m_yOffset, attr["lefttop"],
atoi( attr["priority"] ), attr["points"], m_curLayoutId ); atoi( attr["range"] ), atoi( attr["priority"] ),
attr["points"], m_curLayoutId );
m_pData->m_listAnchor.push_back( anchor ); m_pData->m_listAnchor.push_back( anchor );
} }
......
...@@ -28,46 +28,60 @@ ...@@ -28,46 +28,60 @@
#include "skin_common.hpp" #include "skin_common.hpp"
#include "generic_layout.hpp" #include "generic_layout.hpp"
#include "../utils/bezier.hpp" #include "../utils/bezier.hpp"
#include "../utils/position.hpp"
/// Class for the windows anchors /// Class for the windows anchors
class Anchor: public SkinObject class Anchor: public SkinObject
{ {
public: 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 ): 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_rCurve( rCurve ), m_range( range ), m_priority( priority ),
m_rLayout( rLayout ) {} m_rLayout( rLayout ) {}
virtual ~Anchor() {} virtual ~Anchor() {}
/// Return true if the given anchor is hanged by this one /**
/// Two conditions are required: * Return true if the given anchor is hanged by this one
/// - the other anchor must be in position of anchoring (as defined * Two conditions are required:
/// by canHang()) * - the other anchor must be in position of anchoring (as defined
/// - the priority of the other anchor must be lower than this one's * by canHang())
* - the priority of the other anchor must be lower than this one's
*/
bool isHanging( const Anchor &rOther ) const; 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 * Return true if the other anchor, moved by the (xOffset, yOffset)
/// action), else return false. * vector, is "hangable" by this one (i.e. if it is in its range of
/// When the function returns true, the xOffset and yOffset parameters * action), else return false.
/// are modified to indicate the position that the other anchor would * When the function returns true, the xOffset and yOffset parameters
/// take if hanged by this one (this position is calculated to minimize * are modified to indicate the position that the other anchor would
/// the difference with the old xOffset and yOffset, so that the window * take if hanged by this one (this position is calculated to minimize
/// doesn't "jump" in a strange way). * 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; bool canHang( const Anchor &rOther, int &xOffset, int &yOffset ) const;
// Indicate whether this anchor is reduced to a single point // Indicate whether this anchor is reduced to a single point
bool isPoint() const { return m_rCurve.getNbCtrlPoints() == 1; } bool isPoint() const { return m_rCurve.getNbCtrlPoints() == 1; }
// Getters // Getters
int getXPosAbs() const { return (m_xPos + m_rLayout.getLeft()); } const Position & getPosition() const { return m_position; }
int getYPosAbs() const { return (m_yPos + m_rLayout.getTop()); }
int getXPosAbs() const
{
return (m_position.getLeft() + m_rLayout.getLeft());
}
int getYPosAbs() const
{
return (m_position.getTop() + m_rLayout.getTop());
}
private: private:
/// Coordinates relative to the window /// Position in the layout
int m_xPos, m_yPos; Position m_position;
/// Curve of the anchor /// Curve of the anchor
const Bezier &m_rCurve; const Bezier &m_rCurve;
...@@ -78,7 +92,7 @@ class Anchor: public SkinObject ...@@ -78,7 +92,7 @@ class Anchor: public SkinObject
/// Priority /// Priority
int m_priority; int m_priority;
/// Parent window /// Parent layout
GenericLayout &m_rLayout; GenericLayout &m_rLayout;
}; };
......
...@@ -158,29 +158,6 @@ void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl, ...@@ -158,29 +158,6 @@ void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
void GenericLayout::resize( int width, int height ) 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 // Update the window size
m_width = width; m_width = width;
m_height = height; m_height = height;
......
...@@ -28,12 +28,13 @@ ...@@ -28,12 +28,13 @@
#include "os_factory.hpp" #include "os_factory.hpp"
#include "anchor.hpp" #include "anchor.hpp"
#include "tooltip.hpp" #include "tooltip.hpp"
#include "var_manager.hpp"
#include "../utils/position.hpp" #include "../utils/position.hpp"
#include "../src/var_manager.hpp"
WindowManager::WindowManager( intf_thread_t *pIntf ): 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 // Create and register a variable for the "on top" status
VarManager *pVarManager = VarManager::instance( getIntf() ); VarManager *pVarManager = VarManager::instance( getIntf() );
...@@ -170,6 +171,152 @@ void WindowManager::move( TopWindow &rWindow, int left, int top ) const ...@@ -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 void WindowManager::synchVisibility() const
{ {
WinSet_t::const_iterator it; WinSet_t::const_iterator it;
...@@ -203,7 +350,7 @@ void WindowManager::showAll( bool firstTime ) const ...@@ -203,7 +350,7 @@ void WindowManager::showAll( bool firstTime ) const
{ {
// When the theme is opened for the first time, // When the theme is opened for the first time,
// only show the window if set as visible in the XML // only show the window if set as visible in the XML
if ((*it)->isVisible() || !firstTime) if( (*it)->isVisible() || !firstTime )
{ {
(*it)->show(); (*it)->show();
} }
...@@ -381,7 +528,7 @@ void WindowManager::createTooltip( const GenericFont &rTipFont ) ...@@ -381,7 +528,7 @@ void WindowManager::createTooltip( const GenericFont &rTipFont )
} }
else else
{ {
msg_Warn( getIntf(), "tooltip already created!"); msg_Warn( getIntf(), "tooltip already created!" );
} }
} }
......
...@@ -44,6 +44,15 @@ class Popup; ...@@ -44,6 +44,15 @@ class Popup;
class WindowManager: public SkinObject class WindowManager: public SkinObject
{ {
public: public:
/// Direction of the resizing
enum Direction_t
{
kResizeE, // East
kResizeSE, // South-East
kResizeS, // South
kNone // Reserved for internal use
};
/// Constructor /// Constructor
WindowManager( intf_thread_t *pIntf); WindowManager( intf_thread_t *pIntf);
...@@ -57,22 +66,38 @@ class WindowManager: public SkinObject ...@@ -57,22 +66,38 @@ class WindowManager: public SkinObject
/// Remove a previously registered window /// Remove a previously registered window
void unregisterWindow( TopWindow &rWindow ); 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 ); void startMove( TopWindow &rWindow );
/// Tell the window manager that the current move ended. /// Tell the window manager that the current move ended
void stopMove(); void stopMove();
/// Move the pWindow window to (left, top), and move all its /**
/// anchored windows. * Move the rWindow window to (left, top), and move all its
/// If a new anchoring is detected, the windows will move accordingly. * anchored windows.
* If a new anchoring is detected, the windows will move accordingly.
*/
void move( TopWindow &rWindow, int left, int top ) const; 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 /// Raise all the registered windows
void raiseAll() const; void raiseAll() const;
/// Show all the registered windows /// Show all the registered windows
void showAll(bool firstTime = false) const; void showAll( bool firstTime = false ) const;
/// Hide all the registered windows /// Hide all the registered windows
void hideAll() const; void hideAll() const;
...@@ -142,6 +167,15 @@ class WindowManager: public SkinObject ...@@ -142,6 +167,15 @@ class WindowManager: public SkinObject
/// Store the moving windows; this set is updated at every start of /// Store the moving windows; this set is updated at every start of
/// move. /// move.
WinSet_t m_movingWindows; 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 /// Indicate whether the windows are currently on top
VariablePtr m_cVarOnTop; VariablePtr m_cVarOnTop;
/// Magnetism of the screen edges (= scope of action) /// Magnetism of the screen edges (= scope of action)
...@@ -150,6 +184,8 @@ class WindowManager: public SkinObject ...@@ -150,6 +184,8 @@ class WindowManager: public SkinObject
int m_alpha; int m_alpha;
/// Alpha value of the moving windows /// Alpha value of the moving windows
int m_moveAlpha; int m_moveAlpha;
/// Direction of the current resizing
Direction_t m_direction;
/// Tooltip /// Tooltip
Tooltip *m_pTooltip; Tooltip *m_pTooltip;
/// Active popup, if any /// Active popup, if any
......
...@@ -95,6 +95,9 @@ class Position ...@@ -95,6 +95,9 @@ class Position
/// Get the size of the rectangle /// Get the size of the rectangle
int getWidth() const; int getWidth() const;
int getHeight() const; int getHeight() const;
/// Get the reference corners
Ref_t getRefLeftTop() const { return m_refLeftTop; }
Ref_t getRefRightBottom() const { return m_refRighBottom; }
private: private:
/// Position and reference edge/corner /// Position and reference edge/corner
......
...@@ -99,6 +99,7 @@ ...@@ -99,6 +99,7 @@
<!ATTLIST Anchor <!ATTLIST Anchor
x CDATA "0" x CDATA "0"
y CDATA "0" y CDATA "0"
lefttop CDATA "lefttop"
priority CDATA #REQUIRED priority CDATA #REQUIRED
points CDATA "(0,0)" points CDATA "(0,0)"
range CDATA "10" range CDATA "10"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment