Anonymous avatar Anonymous committed 4a281ad

dockingwindows2: #i115802# Splitwindows, docked windows with title and other classes/fixes

Comments (0)

Files changed (18)

framework/inc/classes/resource.hrc

 #define MENUITEM_TOOLBAR_CLOSE                  6
 
 #define RID_IMAGE_STATUSBAR_LOGO                (RID_IMAGE_START+0)
+#define RID_IMAGE_CLOSER                        (RID_IMAGE_START+1)
+#define RID_IMAGE_CLOSERHC                      (RID_IMAGE_START+2)
 
 // License Dialog
 #define DLG_LICENSE                         (RID_FWK_DIALOG_START+256)

framework/inc/helper/ilayoutinformation.hxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: layoutmanager.hxx,v $
+ * $Revision: 1.34 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __FRAMEWORK_LAYOUTMANAGER_ILAYOUTINFORMATION_HXX_
+#define __FRAMEWORK_LAYOUTMANAGER_ILAYOUTINFORMATION_HXX_
+
+#include <general.h>
+#include <stdtypes.h>
+
+#include <com/sun/star/awt/Rectangle.hpp>
+
+#include <tools/gen.hxx>
+
+namespace framework
+{
+
+class ILayoutInformation
+{
+    public:
+        virtual css::awt::Rectangle getWorkspaceArea() = 0;
+};
+
+}
+
+#endif // __FRAMEWORK_LAYOUTMANAGER_ILAYOUTINFORMATION_HXX_

framework/inc/helper/ilayoutnotifications.hxx

             HINT_NOT_SPECIFIED,
             HINT_TOOLBARSPACE_HAS_CHANGED,
             HINT_TOOLPANESPACE_HAS_CHANGED,
+            HINT_SPLITPANE_TOP_HAS_CHANGED,
+            HINT_SPLITPANE_BOTTOM_HAS_CHANGED,
+            HINT_SPLITPANE_LEFT_HAS_CHANGED,
+            HINT_SPLITPANE_RIGHT_HAS_CHANGED,
             HINT_COUNT
         };
 

framework/inc/uielement/panelwindow.hxx

 //_________________________________________________________________________________________________________________
 
 #include <vcl/dockwin.hxx>
+#include <vcl/bitmapex.hxx>
 
 //_________________________________________________________________________________________________________________
 //	namespace
         virtual void	StateChanged( StateChangedType nType );
 	    virtual void	DataChanged( const DataChangedEvent& rDCEvt );
 	    virtual void    Resize();
+	    virtual void    Paint( const Rectangle& rRect );
+        virtual BOOL    Close();
 
+        virtual void    MouseMove( const MouseEvent& rMEvt );
+        virtual void    MouseButtonDown( const MouseEvent& rMEvt );
+        virtual void    MouseButtonUp( const MouseEvent& rMEvt );
+        
         virtual BOOL    PrepareToggleFloatingMode();
         virtual void    ToggleFloatingMode();
         virtual void    StartDocking();
         const Link&     GetDataChangedHdl() { return m_aDataChangedHandler; }
 
     private:
+        Rectangle       ImplGetCloserRect() const;
+        Rectangle       ImplGetCloserSensitiveRect() const;
+        int             ImplGetDragWidth() const;
+        void            ImplDrawGrip( const ::Size& rTitleSize );
+        void            ImplDrawCloser( bool bHighlight );
+
+        BitmapEx        m_aCloserImage;
+        BitmapEx        m_aCloserImageHC;
+        
         ::rtl::OUString m_aResourceURL;
         Link	        m_aCommandHandler;
         Link	        m_aStateChangedHandler;
         Link            m_aDataChangedHandler;
+        bool            m_bCloserHighlight;
         Window*         m_pContentWindow;
        ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDockableWindowListener > m_xDockableWindowListener;
 };

framework/source/classes/resource.src

     Text [ en-US ] = "Set Language for all Text" ;   
     Text [ x-comment ] = " "; 
 };
+
+Bitmap RID_IMAGE_CLOSER
+{
+	File = "closer.png";
+};
+
+Bitmap RID_IMAGE_CLOSERHC
+{
+	File = "closerhc.png";
+};

framework/source/layoutmanager/helpers.cxx

 namespace framework
 {
 
+WindowAlign convert2WindowAlign( SplitPanelPosition ePanelPos )
+{
+    if ( ePanelPos == SPLITPANEL_TOP )
+        return WINDOWALIGN_TOP;
+    else if ( ePanelPos == SPLITPANEL_BOTTOM )
+        return WINDOWALIGN_BOTTOM;
+    else if ( ePanelPos == SPLITPANEL_LEFT )
+        return WINDOWALIGN_LEFT;
+    else if ( ePanelPos == SPLITPANEL_RIGHT )
+        return WINDOWALIGN_RIGHT;
+        
+    return WINDOWALIGN_TOP;
+}
+
+ui::DockingArea convertPanel2DockingArea( SplitPanelPosition ePanelPos )
+{
+    if ( ePanelPos == SPLITPANEL_TOP )
+        return ui::DockingArea_DOCKINGAREA_TOP;
+    else if ( ePanelPos == SPLITPANEL_BOTTOM )
+        return ui::DockingArea_DOCKINGAREA_BOTTOM;
+    else if ( ePanelPos == SPLITPANEL_LEFT )
+        return ui::DockingArea_DOCKINGAREA_LEFT;
+    else if ( ePanelPos == SPLITPANEL_RIGHT )
+        return ui::DockingArea_DOCKINGAREA_RIGHT;
+        
+    return ui::DockingArea_DOCKINGAREA_DEFAULT;
+}
+
 awt::Size convertSize( const ::Size& rSize )
 {
     awt::Size aSize;
         return 0;
 }
 
+::Rectangle calcHotZoneRect( const Rectangle& rRect, sal_Int32 nHotZoneOffset )
+{
+    ::Rectangle aRect( rRect );
+    ::Size aSize = rRect.GetSize();
+    
+    aRect.Right() = aRect.Left() + aSize.getWidth() + nHotZoneOffset;
+    aRect.Bottom() = aRect.Top() + aSize.getHeight() + nHotZoneOffset;
+    aRect.Left() -= nHotZoneOffset;
+    aRect.Top() -= nHotZoneOffset;
+    
+    return aRect;
+}
+
 void setZeroRectangle( ::Rectangle& rRect )
 {
     rRect.setX(0);

framework/source/layoutmanager/helpers.hxx

 #include <macros/generic.hxx>
 #include <stdtypes.h>
 #include <properties.h>
+#include <splitpanelmanager.hxx>
 
 // interface includes
 #include <com/sun/star/awt/XWindowPeer.hpp>
 namespace framework
 {
 
+css::ui::DockingArea convertPanel2DockingArea( SplitPanelPosition ePanelPos );
+WindowAlign convert2WindowAlign( SplitPanelPosition ePanelPos );
+
 css::awt::Size convertSize( const ::Size& rSize );
 bool hasEmptySize( const:: Size& aSize );
 bool hasDefaultPosValue( const ::Point& aPos );
 bool isDefaultPos( const css::awt::Point& aPos );
 bool isDefaultPos( const ::Point& aPos );
 
+::Rectangle calcHotZoneRect( const Rectangle& aWinRect, sal_Int32 nDistance );
 bool equalRectangles( const css::awt::Rectangle& rRect1, const css::awt::Rectangle& rRect2 );
 void setZeroRectangle( ::Rectangle& rRect );
 ::Rectangle putAWTToRectangle( const css::awt::Rectangle& rRect );

framework/source/layoutmanager/layoutmanager.cxx

         if ( pToolbarManager )
             aToolbarDockSpace = pToolbarManager->getDockingArea();
         if ( pPanelManager )
-            aPanelDockSpace = pPanelManager->getPreferredSize();
+            aPanelDockSpace = pPanelManager->getDockingArea();
         
         awt::Rectangle aBorderSpace( combineBorders( aToolbarDockSpace, aPanelDockSpace ));
         sal_Bool       bGotRequestedBorderSpace( sal_True );
         if ( pToolbarManager )
             aBorderSpace = pToolbarManager->getDockingArea();
         if ( pPanelManager )
-            aBorderSpace = combineBorders( aBorderSpace, pPanelManager->getPreferredSize() );
+            aBorderSpace = combineBorders( aBorderSpace, pPanelManager->getDockingArea() );
     }
     
     return aBorderSpace;
         m_xFrame.clear();
         delete m_pGlobalSettings;
         m_pGlobalSettings = 0;
-                m_xDockingAreaAcceptor = Reference< ui::XDockingAreaAcceptor >();
+        m_xDockingAreaAcceptor = Reference< ui::XDockingAreaAcceptor >();
 
         bDisposeAndClear = sal_True;
     }
     else if ( rEvent.Source == Reference< XInterface >( m_xContainerWindow, UNO_QUERY ))
     {
         // Our container window gets disposed. Remove all user interface elements.
+        uno::Reference< awt::XWindowPeer > aEmptyWindowPeer;
         uno::Reference< ui::XUIConfigurationListener > xToolbarManager( m_xToolbarManager );
         ToolbarLayoutManager* pToolbarManager = m_pToolbarManager;
         if ( pToolbarManager )
-        {
-            uno::Reference< awt::XWindowPeer > aEmptyWindowPeer;
             pToolbarManager->setParentWindow( aEmptyWindowPeer );
-        }
+        
+        Reference< awt::XWindowListener > xPanelManager( m_xPanelManager, uno::UNO_QUERY );
+        PanelManager* pPanelManager( m_pPanelManager );
+        if ( pPanelManager )
+            pPanelManager->setParentWindow( aEmptyWindowPeer );
+        
         impl_clearUpMenuBar();
         m_xMenuBar.clear();
         if ( m_xInplaceMenuBar.is() )

framework/source/layoutmanager/makefile.mk

                     $(SLO)$/uielement.obj		\
                     $(SLO)$/toolbarlayoutmanager.obj \
                     $(SLO)$/splitpanelcontainerwindow.obj \
-                    $(SLO)$/panelcontainerwindow.obj
+                    $(SLO)$/panelcontainerwindow.obj \
+                    $(SLO)$/splitpanelmanager.obj
 
 # --- Targets ------------------------------------------------------
 

framework/source/layoutmanager/panelmanager.cxx

 #include <vcl/splitwin.hxx>
 #include <vcl/dockingarea.hxx>
 #include <toolkit/unohlp.hxx>
+#include <toolkit/helper/convert.hxx>
 #include <svtools/toolpanel/toolpaneldeck.hxx>
 
 //_________________________________________________________________________________________________________________
     const uno::Reference< ui::XUIElementFactory >& xUIElementFactory,
     ILayoutNotifications* pParentLayouter ) :
     ThreadHelpBase( &Application::GetSolarMutex() ),
+    m_aSplitPanels( SPLITPANEL_COUNT ),
     m_xSMGR( rSMGR ),
     m_xUIElementFactoryManager( xUIElementFactory ),
     m_pParentLayouter( pParentLayouter ),
     aWriteLock.unlock();
 
     if ( rParent.is() )
-    {
         createSplitPanels();
-    }
     else
     {
+        destroyPanels();
         destroySplitPanels();
     }
 }
 		
+void PanelManager::impl_createOrSetSplitPanel( const SplitPanelPosition ePos, uno::Reference< lang::XComponent >& xSplitPanel )
+{
+    ReadGuard aReadLock( m_aLock );
+    uno::Reference< awt::XWindow > xParent( m_xContainerWindow, uno::UNO_QUERY );
+    aReadLock.unlock();
+    
+    SplitPanelManager* pSplitPanelManager;
+    if ( !xSplitPanel.is() )
+    {
+        pSplitPanelManager = new SplitPanelManager( ePos, dynamic_cast< ILayoutNotifications*>( this ));
+        xSplitPanel = uno::Reference< lang::XComponent >( static_cast< cppu::OWeakObject* >( pSplitPanelManager ), uno::UNO_QUERY );
+    }
+    else
+        pSplitPanelManager = dynamic_cast< SplitPanelManager* >( xSplitPanel.get() );
+
+    if ( pSplitPanelManager )
+        pSplitPanelManager->setParentWindow( xParent );
+}
+
 ///---------------------------------------------------------------------------------------------------------
 // Life-time handling and layouting
 //---------------------------------------------------------------------------------------------------------
     WriteGuard aWriteLock( m_aLock );
     uno::Reference< frame::XFrame > xFrame( m_xFrame );
     uno::Reference< awt::XWindowPeer > xParent( m_xContainerWindow, uno::UNO_QUERY );
+    SplitPanelVector aSplitPanels( m_aSplitPanels );
     bool bResult( false );
     aWriteLock.unlock();
 
     if ( xFrame.is() && xParent.is() )
     {
+        Window* pParent(0);
+        {
+            vos::OGuard aGuard( Application::GetSolarMutex() );
+            pParent = VCLUnoHelper::GetWindow( xParent );
+        }
+
+        for ( int i = 0; i < SPLITPANEL_COUNT; i++ )
+            impl_createOrSetSplitPanel( static_cast<SplitPanelPosition>(i), aSplitPanels[i] ); // create or set parent on split panel managers
+        
         aWriteLock.lock();
-        uno::Reference< awt::XWindow > xOldSplitWinTop = m_aSplitPanels[SPLITPANEL_TOP];
-        uno::Reference< awt::XWindow > xOldSplitWinLeft = m_aSplitPanels[SPLITPANEL_LEFT];
-        uno::Reference< awt::XWindow > xOldSplitWinRight = m_aSplitPanels[SPLITPANEL_RIGHT];
-        uno::Reference< awt::XWindow > xOldSplitWinBottom = m_aSplitPanels[SPLITPANEL_BOTTOM];
+        m_aSplitPanels = aSplitPanels;
         aWriteLock.unlock();
-        
-        if ( xOldSplitWinTop.is() && xOldSplitWinLeft.is() && xOldSplitWinRight.is() && xOldSplitWinBottom.is() )
-            implts_reparentSplitWindows();
-        else
-        {
-            uno::Reference< awt::XWindow > xSplitWinTop;
-            uno::Reference< awt::XWindow > xSplitWinBottom;
-            uno::Reference< awt::XWindow > xSplitWinLeft;
-            uno::Reference< awt::XWindow > xSplitWinRight;
-            {
-                vos::OGuard aGuard( Application::GetSolarMutex() );
-                Window* pParent = VCLUnoHelper::GetWindow( xParent );
-                
-                SplitPanelContainerWindow* pSplitPanelContainerWindow = new SplitPanelContainerWindow( pParent, 0 );
-                pSplitPanelContainerWindow->SetAlign( WINDOWALIGN_TOP );
-                xSplitWinTop = VCLUnoHelper::GetInterface( pSplitPanelContainerWindow );
-
-                pSplitPanelContainerWindow = new SplitPanelContainerWindow( pParent, 0 );
-                pSplitPanelContainerWindow->SetAlign( WINDOWALIGN_LEFT );
-                xSplitWinLeft = VCLUnoHelper::GetInterface( pSplitPanelContainerWindow );
-                
-                pSplitPanelContainerWindow = new SplitPanelContainerWindow( pParent, 0 );
-                pSplitPanelContainerWindow->SetAlign( WINDOWALIGN_RIGHT );
-                xSplitWinRight = VCLUnoHelper::GetInterface( pSplitPanelContainerWindow );
-                
-                pSplitPanelContainerWindow = new SplitPanelContainerWindow( pParent, 0 );
-                pSplitPanelContainerWindow->SetAlign( WINDOWALIGN_BOTTOM );
-                xSplitWinBottom = VCLUnoHelper::GetInterface( pSplitPanelContainerWindow );
-            }
-
-            aWriteLock.lock();
-            m_aSplitPanels[SPLITPANEL_TOP] = xSplitWinTop;
-            m_aSplitPanels[SPLITPANEL_BOTTOM] = xSplitWinBottom;
-            m_aSplitPanels[SPLITPANEL_LEFT] = xSplitWinLeft;
-            m_aSplitPanels[SPLITPANEL_RIGHT] = xSplitWinRight;
-            aWriteLock.unlock();
             
-            if ( xOldSplitWinTop.is() || xOldSplitWinLeft.is() || xOldSplitWinRight.is() || xOldSplitWinBottom.is() )
-                implts_reparentSplitWindows();
-            
-            try
-            {
-                if ( xOldSplitWinTop.is() ) xOldSplitWinTop->dispose();
-                if ( xOldSplitWinLeft.is() ) xOldSplitWinLeft->dispose();
-                if ( xOldSplitWinRight.is() ) xOldSplitWinRight->dispose();
-                if ( xOldSplitWinBottom.is() ) xOldSplitWinBottom->dispose();
-            }
-            catch ( uno::RuntimeException& ) { throw; }
-            catch ( uno::Exception& ) {}
-        }
         bResult = true;
     }
     return bResult;
 
 void PanelManager::destroySplitPanels()
 {
-    WriteGuard aWriteLock( m_aLock );
-    uno::Reference< awt::XWindow > xOldSplitWinTop = m_aSplitPanels[SPLITPANEL_TOP];
-    uno::Reference< awt::XWindow > xOldSplitWinLeft = m_aSplitPanels[SPLITPANEL_LEFT];
-    uno::Reference< awt::XWindow > xOldSplitWinRight = m_aSplitPanels[SPLITPANEL_RIGHT];
-    uno::Reference< awt::XWindow > xOldSplitWinBottom = m_aSplitPanels[SPLITPANEL_BOTTOM];
-    
-    for ( sal_Int32 i = 0; i < SPLITPANEL_COUNT; i++ )
+    for ( int i=0; i < SPLITPANEL_COUNT; i++ )
+    {
+        WriteGuard aWriteLock( m_aLock );
+        uno::Reference< lang::XComponent > xComp = m_aSplitPanels[i];
         m_aSplitPanels[i].clear();
-    aWriteLock.unlock();
-    
-    try
-    {
-        if ( xOldSplitWinTop.is() ) xOldSplitWinTop->dispose();
-        if ( xOldSplitWinLeft.is() ) xOldSplitWinLeft->dispose();
-        if ( xOldSplitWinRight.is() ) xOldSplitWinRight->dispose();
-        if ( xOldSplitWinBottom.is() ) xOldSplitWinBottom->dispose();
+        aWriteLock.unlock();
+        
+        try
+        {
+            if ( xComp.is() )
+                xComp->dispose();
+        }
+        catch ( uno::Exception& ) {}
     }
-    catch ( uno::RuntimeException& ) { throw; }
-    catch ( uno::Exception& ) {}
 }
 
 void PanelManager::destroyPanels()
     }
 }
 
+static SplitPanelManager* impl_getSplitPanelManager( const uno::Reference< lang::XComponent >& xPanel )
+{
+    SplitPanelManager* pMgr(0);
+    if ( xPanel.is() )
+        pMgr = dynamic_cast< SplitPanelManager* >( xPanel.get() );
+    
+    return pMgr;
+}
+
 void PanelManager::resetDockingArea()
 {
     ReadGuard aReadLock( m_aLock );
-    uno::Reference< awt::XWindow > xSplitWinTop = m_aSplitPanels[SPLITPANEL_TOP];
-    uno::Reference< awt::XWindow > xSplitWinLeft = m_aSplitPanels[SPLITPANEL_LEFT];
-    uno::Reference< awt::XWindow > xSplitWinRight = m_aSplitPanels[SPLITPANEL_RIGHT];
-    uno::Reference< awt::XWindow > xSplitWinBottom = m_aSplitPanels[SPLITPANEL_BOTTOM];
+    SplitPanelVector aSplitPanels( m_aSplitPanels );
     aReadLock.unlock();
     
-    if ( xSplitWinTop.is() )
-        xSplitWinTop->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
-    if ( xSplitWinLeft.is() )
-        xSplitWinLeft->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
-    if ( xSplitWinRight.is() )
-        xSplitWinRight->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
-    if ( xSplitWinBottom.is() )
-        xSplitWinBottom->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    for ( int i = 0; i < SPLITPANEL_COUNT; i++ )
+    {
+        SplitPanelManager* pMgr = impl_getSplitPanelManager( aSplitPanels[i] );
+        if ( pMgr )
+           pMgr->setSize( 0 );
+    }
 }
 
 void PanelManager::setDockingArea( const awt::Rectangle& rDockingArea )
     implts_setLayoutDirty();
 }
 
-awt::Rectangle PanelManager::getPreferredSize()
+awt::Rectangle PanelManager::getDockingArea()
 {
     if ( isLayoutDirty() )
         calcLayout();
     
     ReadGuard aReadLock( m_aLock );
-    return m_aPreferredDockingArea;
-}
-
-::com::sun::star::awt::Rectangle PanelManager::getMinimalSize()
-{
-    if ( isLayoutDirty() )
-        calcLayout();
-    
-    ReadGuard aReadLock( m_aLock );
-    return m_aMinimalDockingArea;
+    return m_aDockingArea;
 }
 
 void PanelManager::calcLayout()
 {
+    ReadGuard aReadLock( m_aLock );
+    SplitPanelVector aSplitPanels( m_aSplitPanels );
+    aReadLock.unlock();
+    
+    sal_Int32 nSizes[SPLITPANEL_COUNT] = {0};
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    for ( int i = 0; i < SPLITPANEL_COUNT; i++ )
+    {
+        SplitPanelManager* pMgr = impl_getSplitPanelManager( aSplitPanels[i] );
+        if ( pMgr )
+           nSizes[i] = pMgr->getSize();
+    }
+    
     WriteGuard aWriteLock( m_aLock );
-    m_aPreferredDockingArea = m_aDockingArea;
-    m_aMinimalDockingArea   = m_aDockingArea;    
+    m_aDockingArea = awt::Rectangle( nSizes[SPLITPANEL_LEFT], nSizes[SPLITPANEL_TOP],
+                                     nSizes[SPLITPANEL_RIGHT], nSizes[SPLITPANEL_BOTTOM] );
     aWriteLock.unlock();
 }
         
 void PanelManager::doLayout( const awt::Size& rContainerSize )
 {
     WriteGuard aWriteLock( m_aLock );
-    uno::Reference< awt::XWindow > xSplitWinTop = m_aSplitPanels[SPLITPANEL_TOP];
-    uno::Reference< awt::XWindow > xSplitWinLeft = m_aSplitPanels[SPLITPANEL_LEFT];
-    uno::Reference< awt::XWindow > xSplitWinRight = m_aSplitPanels[SPLITPANEL_RIGHT];
-    uno::Reference< awt::XWindow > xSplitWinBottom = m_aSplitPanels[SPLITPANEL_BOTTOM];
+    uno::Reference< lang::XComponent > xSplitTop = m_aSplitPanels[SPLITPANEL_TOP];
+    uno::Reference< lang::XComponent > xSplitLeft = m_aSplitPanels[SPLITPANEL_LEFT];
+    uno::Reference< lang::XComponent > xSplitRight = m_aSplitPanels[SPLITPANEL_RIGHT];
+    uno::Reference< lang::XComponent > xSplitBottom = m_aSplitPanels[SPLITPANEL_BOTTOM];
     awt::Rectangle aOffsets( m_aDockingAreaOffsets );
     awt::Rectangle aDockingArea( m_aDockingArea );
     uno::Reference< awt::XWindow2 > xParent( m_xContainerWindow );
         aPos.Y = aOffsets.Y;
         aSize.Width  = nLeftPanelWidth;
         aSize.Height = nVertPanelHeight;
-        implts_showAndSetPosSizePixel( xSplitWinLeft, aPos, aSize );
+        implts_showAndSetPosSizePixel( xSplitLeft, aPos, aSize );
 
         // Calc right splitwindow pos/size
         sal_Int32 nRightPanelWidth( aDockingArea.Width );
         aPos.X = ::std::max( rContainerSize.Width - aOffsets.Width - aDockingArea.Width, sal_Int32( 0 ));
         aPos.Y = aOffsets.Y;
         aSize.Width = nRightPanelWidth;
-        implts_showAndSetPosSizePixel( xSplitWinRight, aPos, aSize );
+        implts_showAndSetPosSizePixel( xSplitRight, aPos, aSize );
 
         // Calc top splitwindow pos/size
         aPos.X = aOffsets.X + aDockingArea.X;
         aPos.Y = aOffsets.Y;
         aSize.Width  = ::std::max( nHorzPanelWidth - nLeftPanelWidth - nRightPanelWidth, sal_Int32( 0 ));
         aSize.Height = aDockingArea.Y;
-        implts_showAndSetPosSizePixel( xSplitWinTop, aPos, aSize );
+        implts_showAndSetPosSizePixel( xSplitTop, aPos, aSize );
         
         // Calc bottom splitwindow pos/size
         aPos.X = aOffsets.X + aDockingArea.X;
         aPos.Y = ::std::max( rContainerSize.Height - aDockingArea.Height - aOffsets.Height, sal_Int32( 0 ));
         aSize.Height = aDockingArea.Height;
-        implts_showAndSetPosSizePixel( xSplitWinBottom, aPos, aSize );
+        implts_showAndSetPosSizePixel( xSplitBottom, aPos, aSize );
         
         // calculate the remaining size of the client window space
         sal_Int32 nWidth  = ::std::max( sal_Int32( nHorzPanelWidth - nLeftPanelWidth - nRightPanelWidth ), sal_Int32( 0 ));
         sal_Int32 nHeight = ::std::max( sal_Int32( nVertPanelHeight - aDockingArea.Y - aDockingArea.Height ), sal_Int32( 0 ));
         
         aWriteLock.lock();
-        m_aClientSpace = awt::Rectangle( aOffsets.X, aOffsets.Y, nWidth, nHeight );
+        m_aWorkspace = awt::Rectangle( aOffsets.X, aOffsets.Y, nWidth, nHeight );
         aWriteLock.unlock();
     }
 }
             aUIElement = *pIter;
             return true;
         }
+        ++pIter;
     }
     
     return false;
                  return true;
             }
         }
+        ++pIter;
     }
     
     return false;
     return aEmptyElement;
 }
 
-uno::Reference< awt::XWindow > _createToolPanelDeck( Window& pParent )
+class ColorWindow : public Window
 {
+    public:
+        ColorWindow( Window* pParent, const Color& rColor );
+        virtual ~ColorWindow() {}
+        
+        virtual void Paint( const Rectangle& rRect );
+        
+    private:
+        Color m_aColor;
+};
+
+ColorWindow::ColorWindow( Window* pParent, const Color& rColor ) :
+    Window( pParent, WB_NOBORDER ),
+    m_aColor( rColor )
+{
+}
+
+void ColorWindow::Paint( const Rectangle& rRect )
+{
+    SetLineColor( m_aColor );
+    SetFillColor( m_aColor );
+    DrawRect( rRect );
+}
+
+uno::Reference< awt::XWindow > _createContentWindow( Window& pParent )
+{
+    static sal_Int32 nCount(0);
+    static ColorData aColor[10] =
+    {
+        COL_BLUE,
+        COL_GREEN,
+        COL_CYAN,
+        COL_RED,
+        COL_MAGENTA,
+        COL_BROWN,
+        COL_GRAY,
+        COL_YELLOW,
+        COL_LIGHTBLUE,
+        COL_LIGHTRED
+   };
+
     vos::OGuard aGuard( Application::GetSolarMutex() );
-    Window* pWindow = new svt::ToolPanelDeck( pParent, 0 );
+    Color aWinColor( aColor[ nCount % 10 ] );
+    Window* pWindow = new ColorWindow( &pParent, aWinColor );
+    ++nCount;
     
     return VCLUnoHelper::GetInterface( pWindow );
 }
         uno::Reference< lang::XInitialization > xInit( static_cast< cppu::OWeakObject* >( pWrapper ), uno::UNO_QUERY );
         if ( xInit.is() )
         {
+            static sal_Int32 nCount(1);
+            
             beans::PropertyValue aPropValue;
             uno::Sequence< uno::Any > aSeq( 3 );
             aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
             aPropValue.Value <<= uno::makeAny( false );
             aSeq[1] <<= uno::makeAny( aPropValue );
             aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentWindow" ));
-            uno::Reference< awt::XWindow > xWindow( _createToolPanelDeck( *pParent ));
+            uno::Reference< awt::XWindow > xWindow( _createContentWindow( *pParent ));
             aPropValue.Value <<= uno::makeAny( xWindow );
             aSeq[2] <<= uno::makeAny( aPropValue );
             
                {
                    uno::Reference< awt::XDockableWindowListener > xListener( static_cast< cppu::OWeakObject* >( this ), uno::UNO_QUERY );
                    pPanelWindow->setDockableWindowListener( xListener );
+                   
+                   ::rtl::OUString aPanelTitle( RTL_CONSTASCII_USTRINGPARAM( "Panel "));
+                   aPanelTitle += rtl::OUString::valueOf( nCount );
+                   pPanelWindow->SetText( aPanelTitle );
+                   ++nCount;
                }
             }
             
         aUIElement.m_aName      = rResourceName;
         aUIElement.m_xUIElement = xUIElement;
         aUIElement.m_bVisible   = true;
+        aUIElement.m_bFloating  = true;
+        aUIElement.m_aDockedData.m_aSize = ::Size( 200, 400 );
         
         m_aPanels.push_back( aUIElement );
         return true;
 void PanelManager::implts_reparentSplitWindows()
 {
     ReadGuard aReadLock( m_aLock );
+    SplitPanelVector aSplitPanels( m_aSplitPanels );
     uno::Reference< awt::XWindow > xParent( m_xContainerWindow, uno::UNO_QUERY );
-    uno::Reference< awt::XWindow > xSplitWinTop    = m_aSplitPanels[SPLITPANEL_TOP];
-    uno::Reference< awt::XWindow > xSplitWinLeft   = m_aSplitPanels[SPLITPANEL_LEFT];
-    uno::Reference< awt::XWindow > xSplitWinRight  = m_aSplitPanels[SPLITPANEL_RIGHT];
-    uno::Reference< awt::XWindow > xSplitWinBottom = m_aSplitPanels[SPLITPANEL_BOTTOM];
     aReadLock.unlock();
     
     vos::OGuard aGuard( Application::GetSolarMutex() );
-    Window* pParent = VCLUnoHelper::GetWindow( xParent );
-    if ( pParent )
+    for ( int i = 0; i < SPLITPANEL_COUNT; i++ )
     {
-        Window* pWindow = VCLUnoHelper::GetWindow( xSplitWinTop );
-        if ( pWindow )
-            pWindow->SetParent( pParent );
-        pWindow = VCLUnoHelper::GetWindow( xSplitWinLeft );
-        if ( pWindow )
-            pWindow->SetParent( pParent );
-        pWindow = VCLUnoHelper::GetWindow( xSplitWinRight );
-        if ( pWindow )
-            pWindow->SetParent( pParent );
-        pWindow = VCLUnoHelper::GetWindow( xSplitWinBottom );
-        if ( pWindow )
-            pWindow->SetParent( pParent );
+        SplitPanelManager* pMgr = impl_getSplitPanelManager( aSplitPanels[i] );
+        if ( pMgr )
+            pMgr->setParentWindow( xParent );
     }
 }
 
     return xSplitWindow;
 }
 
-void PanelManager::implts_showAndSetPosSizePixel( const uno::Reference< awt::XWindow >& xWindow, const awt::Point& rPos, const awt::Size& rSize )
+void PanelManager::implts_showAndSetPosSizePixel( const uno::Reference< lang::XComponent >& xSplitPanel, const awt::Point& rPos, const awt::Size& rSize )
 {
-    vos::OGuard aGuard( Application::GetSolarMutex() );
-    
-    Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
-    if ( pWindow && pWindow->GetType() == WINDOW_SPLITWINDOW )
+    SplitPanelManager* pSplitPanelManager = dynamic_cast< SplitPanelManager* >( xSplitPanel.get() );
+    if ( pSplitPanelManager )
     {
-        xWindow->setPosSize( rPos.X, rPos.Y, rSize.Width, rSize.Height, awt::PosSize::POSSIZE );
-        pWindow->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
+        pSplitPanelManager->setPosSize( rPos, rSize );
+        pSplitPanelManager->setVisible( true );
     }
 }
 
 //---------------------------------------------------------------------------------------------------------
 // XInterface
 //---------------------------------------------------------------------------------------------------------
+void PanelManager::requestLayout( Hint )
+{
+    implts_setLayoutDirty();
+    m_pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLPANESPACE_HAS_CHANGED );
+}
+
+awt::Rectangle PanelManager::getWorkspaceArea()
+{
+    ReadGuard aReadLock( m_aLock );
+    return m_aWorkspace;
+}
+
+//---------------------------------------------------------------------------------------------------------
+// XInterface
+//---------------------------------------------------------------------------------------------------------
 void SAL_CALL PanelManager::acquire() throw()
 {
     OWeakObject::acquire();
 //---------------------------------------------------------------------------------------------------------
 // XEventListener
 //---------------------------------------------------------------------------------------------------------
-void SAL_CALL PanelManager::disposing( const css::lang::EventObject& /*aEvent*/ ) 
+void SAL_CALL PanelManager::disposing( const css::lang::EventObject& rEvent ) 
 throw( css::uno::RuntimeException )
 {
+    if ( rEvent.Source == uno::Reference< uno::XInterface >( m_xFrame, uno::UNO_QUERY ))
+    {
+        // Reset all internal references
+        reset();
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------
     return aRect;
 }
 
-awt::Rectangle PanelManager::calcSimpleDockingRect( const sal_Int16 eDockingArea, const awt::Point& rMousePos, const uno::Reference< awt::XWindow >& xWindow, awt::Rectangle& rVirtDockPosSize )
+bool PanelManager::implts_dockWindow( const sal_Int16 eDockingArea, const awt::Rectangle& rVirtDockSize, const uno::Reference< awt::XWindow >& xWindow )
 {
-    awt::Rectangle aDockingRect;
-
-    if (( eDockingArea < 0 && eDockingArea >= ui::DockingArea_DOCKINGAREA_DEFAULT ) || !xWindow.is() )
-        return aDockingRect;
-
+    if ( eDockingArea < 0 || eDockingArea >= SPLITPANEL_COUNT )
+        return false;
+    
     ReadGuard aReadGuard( m_aLock );
-    uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
-    uno::Reference< awt::XWindow > xDockingArea( m_aSplitPanels[eDockingArea] );
-    ::Rectangle aClientRect( convertAWTToRectangle( m_aClientSpace ));
+    SplitPanelVector aSplitPanels( m_aSplitPanels );
     aReadGuard.unlock();
+    
+    SplitPanelManager* pMgr = impl_getSplitPanelManager( aSplitPanels[eDockingArea] );
+    if ( pMgr )
+        return pMgr->addDockWindow( rVirtDockSize, xWindow );
         
-    bool         bEmpty( true );
-    ::Rectangle  aWinRect;
-    
-    vos::OGuard aGuard( Application::GetSolarMutex() );
-    
-    // Retrieve size from split window
-    SplitWindow* pSplitWindow = dynamic_cast< SplitWindow* >( VCLUnoHelper::GetWindow( xDockingArea ));
-    if ( pSplitWindow )
-    {
-        aWinRect = ::Rectangle( pSplitWindow->GetPosPixel(), pSplitWindow->GetSizePixel() );
-        bEmpty   = ( pSplitWindow->GetItemCount() == 0 );
-    }
-    
-    if ( bEmpty )
-    {
-        rVirtDockPosSize.X = 0;
-        rVirtDockPosSize.Y = 0;
-        
-        if ( isHorizontalDockingArea( eDockingArea ))
-        {
-            sal_Int32 nMaxHeight = sal_Int32( aClientRect.GetHeight() * 80 / 100 );
-            sal_Int32 nHeight = std::max( std::min( xWindow->getPosSize().Height, nMaxHeight ), sal_Int32( 1 ));
-            
-            aDockingRect.X      = aWinRect.Left();
-            aDockingRect.Width  = aWinRect.GetWidth();
-            aDockingRect.Height = nHeight;
-            
-            if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
-                aDockingRect.Y = aWinRect.Top();
-            else
-                aDockingRect.Y = std::max( sal_Int32( aWinRect.Top() - nHeight ), sal_Int32( 0 ));
-            
-            rVirtDockPosSize.Width  = aWinRect.GetWidth();
-            rVirtDockPosSize.Height = nHeight;
-        }
-        else
-        {
-            sal_Int32 nMaxWidth = sal_Int32( aClientRect.GetWidth() * 80 / 100 );
-            sal_Int32 nWidth = std::max( std::min( xWindow->getPosSize().Width, nMaxWidth ), sal_Int32( 1 ));
-            
-            aDockingRect.Y      = aWinRect.Top();
-            aDockingRect.Height = aWinRect.GetHeight();
-            aDockingRect.Width  = nWidth;
-            
-            if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )        
-                aDockingRect.X = aWinRect.Left();
-            else
-                aDockingRect.X = std::max( sal_Int32( aWinRect.Left() - nWidth ), sal_Int32( 0 ));
-
-            rVirtDockPosSize.Width  = nWidth;
-            rVirtDockPosSize.Height = aWinRect.GetHeight();
-        }
-    }
-    else
-    {
-        vos::OGuard aGuard( Application::GetSolarMutex() );
-        sal_uInt16 nCount = pSplitWindow->GetItemCount(0);
-        
-        ::Point aPos = pSplitWindow->ScreenToOutputPixel( ::Point( rMousePos.X, rMousePos.Y ));
-        sal_uInt16 nId = pSplitWindow->GetItemId( aPos );
-        if ( nId == SPLITWINDOW_ITEM_NOTFOUND )
-        {
-        }
-        else
-        {
-        }
-    }
-    
-    return aDockingRect;
+    return false;
 }
 
-bool PanelManager::implts_dockWindow( const sal_Int16 eDockingArea, const awt::Rectangle& rVirtDockSize, const uno::Reference< awt::XWindow >& xWindow )
+bool PanelManager::implts_undockWindow( const sal_Int16 eDockingArea, const css::uno::Reference< css::awt::XWindow >& xWindow )
 {
-    if (( eDockingArea < 0 && eDockingArea >= ui::DockingArea_DOCKINGAREA_DEFAULT ) || !xWindow.is() )
+    if ( eDockingArea < 0 || eDockingArea >= SPLITPANEL_COUNT )
         return false;
 
     ReadGuard aReadGuard( m_aLock );
-    uno::Reference< awt::XWindow > xDockingArea( m_aSplitPanels[eDockingArea] );
-    ::Rectangle aClientRect( convertAWTToRectangle( m_aClientSpace ));
+    SplitPanelVector aSplitPanels( m_aSplitPanels );
     aReadGuard.unlock();
+    
+    SplitPanelManager* pMgr = impl_getSplitPanelManager( aSplitPanels[eDockingArea] );
+    if ( pMgr )
+        return pMgr->removeDockWindow( xWindow );
         
-    ::Rectangle aWinRect;
-    
-    SplitWindow* pSplitWindow  = dynamic_cast< SplitWindow *>( VCLUnoHelper::GetWindow( xDockingArea ));
-    DockingWindow* pDockWindow = dynamic_cast< DockingWindow* >( VCLUnoHelper::GetWindow( xWindow ));
-    
-    if ( pSplitWindow && pDockWindow )
+    return false;
+}
+
+::Point PanelManager::implts_findNextCascadeFloatingPos()
+{
+    const sal_Int32 nHotZoneX       = 50;
+    const sal_Int32 nHotZoneY       = 50;
+    const sal_Int32 nCascadeIndentX = 15;
+    const sal_Int32 nCascadeIndentY = 15;
+
+    ReadGuard aReadLock( m_aLock );
+    uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
+    awt::Rectangle aOffsets( m_aDockingAreaOffsets );
+    awt::Rectangle aDockingArea( m_aDockingArea );
+    UIElementVector aPanels = m_aPanels;
+    aReadLock.unlock();
+
+    ::Point aStartPos( nCascadeIndentX, nCascadeIndentY );
+    ::Point aCurrPos( aStartPos );
+    awt::Rectangle aRect;
+
+    Window* pContainerWindow( 0 );
+    if ( xContainerWindow.is() )
     {
         vos::OGuard aGuard( Application::GetSolarMutex() );
-        if ( pDockWindow->IsFloatingMode() )
-            pDockWindow->SetFloatingMode( false );
-        
-        sal_uInt16 nBits( 0 );
+        pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
+        if ( pContainerWindow )
+            aStartPos = pContainerWindow->OutputToScreenPixel( aStartPos );
+    }
 
-        bool bHorzAlign = isHorizontalDockingArea( eDockingArea );
-        if ( bHorzAlign )
-            nBits = SWIB_COLSET;
-            
-        sal_uInt16 nId = 1;
-        if ( !pSplitWindow->IsItemValid( nId ))
-            pSplitWindow->InsertItem( nId, bHorzAlign ? rVirtDockSize.Width : rVirtDockSize.Height, 0, 0, nBits );
-        sal_uInt16 nWinId = nId+1;
-        pSplitWindow->InsertItem( nWinId, pDockWindow, bHorzAlign ? rVirtDockSize.Width : rVirtDockSize.Height, 0, nId, SWIB_PERCENTSIZE );
-        pSplitWindow->FadeIn();
-        pDockWindow->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
-        
-        WriteGuard aWriteGuard( m_aLock );
-        if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
-            m_aDockingArea.Y = rVirtDockSize.Height + 10;
-        else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
-            m_aDockingArea.Height = rVirtDockSize.Height + 10;
-        else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
-            m_aDockingArea.X = rVirtDockSize.Width + 10;
-        else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
-            m_aDockingArea.Width = rVirtDockSize.Width + 10;
-        aWriteGuard.unlock();
+    // Determine size of left and top docking areas
+    aStartPos.X() += aDockingArea.X + aOffsets.X + nCascadeIndentX;
+    aStartPos.Y() += aDockingArea.Y + aOffsets.Y + nCascadeIndentY;
+    aCurrPos = aStartPos;
 
-        return true;
+    // Try to find a cascaded position for the new floating window
+    UIElementVector::const_iterator pIter;
+    for ( pIter = aPanels.begin(); pIter != aPanels.end(); pIter++ )
+    {
+        if ( pIter->m_xUIElement.is() )
+        {
+            vos::OGuard aGuard( Application::GetSolarMutex() );
+            uno::Reference< awt::XWindow > xWindow( pIter->m_xUIElement->getRealInterface(), uno::UNO_QUERY );
+            DockingWindow* pDockWindow = dynamic_cast< DockingWindow* >( VCLUnoHelper::GetWindow( xWindow ));
+
+            if ( pDockWindow && pDockWindow->IsFloatingMode() )
+            {
+                awt::Rectangle aFloatRect = xWindow->getPosSize();
+                if ((( aFloatRect.X - nHotZoneX ) <= aCurrPos.X() ) &&
+                    ( aFloatRect.X >= aCurrPos.X() ) &&
+                    (( aFloatRect.Y - nHotZoneY ) <= aCurrPos.Y() ) &&
+                    ( aFloatRect.Y >= aCurrPos.Y() ))
+                {
+                    aCurrPos.X() = aFloatRect.X + nCascadeIndentX;
+                    aCurrPos.Y() = aFloatRect.Y + nCascadeIndentY;
+                }
+            }
+        }
     }
-    
-    return false;
+
+    return aCurrPos;
 }
 
 //---------------------------------------------------------------------------------------------------------
     UIElement aCurrDockingWindow;
     if ( xWindow.is() && implts_findDockingWindow( e.Source, aCurrDockingWindow ))
     {
-        awt::Rectangle aRect;
-    
         bWinFound = true;
-        uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
-        if ( xDockWindow->isFloating() )
+        
+        DockingWindow* pDockWindow = dynamic_cast< DockingWindow *>( VCLUnoHelper::GetWindow( xWindow ));
+        if ( pDockWindow && pDockWindow->IsFloatingMode() )
         {
             awt::Rectangle aPos  = xWindow->getPosSize();
             awt::Size      aSize = xWindow->getOutputSize();
 awt::DockingData SAL_CALL PanelManager::docking( const awt::DockingEvent& e ) 
 throw (uno::RuntimeException)
 {
-    const sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
-    const sal_Int32 MAGNETIC_DISTANCE_DOCK   = 20;
-
     ReadGuard aReadLock( m_aLock );
-    awt::DockingData                       aDockingData;
-    uno::Reference< awt::XDockableWindow > xDockWindow( e.Source, uno::UNO_QUERY );
-    uno::Reference< awt::XWindow >         xWindow( e.Source, uno::UNO_QUERY );
-    uno::Reference< awt::XWindow >         xSplitWinTop = m_aSplitPanels[SPLITPANEL_TOP];
-    uno::Reference< awt::XWindow >         xSplitWinLeft = m_aSplitPanels[SPLITPANEL_LEFT];
-    uno::Reference< awt::XWindow >         xSplitWinRight = m_aSplitPanels[SPLITPANEL_RIGHT];
-    uno::Reference< awt::XWindow >         xSplitWinBottom = m_aSplitPanels[SPLITPANEL_BOTTOM];
-    uno::Reference< awt::XWindow2 >        xContainerWindow( m_xContainerWindow );
-    UIElement                              aUIDockingElement( m_aCurrDockingWindow );
-    bool                                   bDockingInProgress( m_bDockingInProgress );
+    awt::DockingData                aDockingData;
+    uno::Reference< awt::XWindow >  xDockWindow( e.Source, uno::UNO_QUERY );
+    uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
+    SplitPanelVector                aSplitPanels( m_aSplitPanels );
+    UIElement                       aUIDockingElement( m_aCurrDockingWindow );
+    bool                            bDockingInProgress( m_bDockingInProgress );
     aReadLock.unlock();
 
     if ( bDockingInProgress )
         aDockingData.TrackingRectangle = e.TrackingRectangle;
 
-    if ( bDockingInProgress && xDockWindow.is() && xWindow.is() )
+    if ( bDockingInProgress && xDockWindow.is() )
     {
         try
         {
-            vos::OGuard aGuard( Application::GetSolarMutex() );
+            sal_Int16 eDockingArea( -1 ); // none
+            awt::Rectangle aNewTrackingRect( e.TrackingRectangle.X, e.TrackingRectangle.Y, e.TrackingRectangle.Width, e.TrackingRectangle.Height );
 
-            sal_Int16 eDockingArea( -1 ); // none
-            sal_Int32 nMagneticZone( aUIDockingElement.m_bFloating ? MAGNETIC_DISTANCE_DOCK : MAGNETIC_DISTANCE_UNDOCK );
-            awt::Rectangle aNewTrackingRect;
-            ::Rectangle aTrackingRect( e.TrackingRectangle.X, e.TrackingRectangle.Y,
-                                       ( e.TrackingRectangle.X + e.TrackingRectangle.Width ),
-                                       ( e.TrackingRectangle.Y + e.TrackingRectangle.Height ));
-
-            awt::Rectangle aTmpRect = xSplitWinTop->getPosSize();
-            ::Rectangle aTopDockRect( convertAWTToRectangle( aTmpRect ) );
-            ::Rectangle aHotZoneTopDockRect( lcl_calcHotZoneRect( aTopDockRect, nMagneticZone ));
-
-            aTmpRect = xSplitWinBottom->getPosSize();
-            ::Rectangle aBottomDockRect( convertAWTToRectangle( aTmpRect ) );
-            ::Rectangle aHotZoneBottomDockRect( lcl_calcHotZoneRect( aBottomDockRect, nMagneticZone ));
-
-            aTmpRect = xSplitWinLeft->getPosSize();
-            ::Rectangle aLeftDockRect( convertAWTToRectangle( aTmpRect ) );
-            ::Rectangle aHotZoneLeftDockRect( lcl_calcHotZoneRect( aLeftDockRect, nMagneticZone ));
-
-            aTmpRect = xSplitWinRight->getPosSize();
-            ::Rectangle aRightDockRect( convertAWTToRectangle( aTmpRect ) );
-            ::Rectangle aHotZoneRightDockRect( lcl_calcHotZoneRect( aRightDockRect, nMagneticZone ));
-
-            Window* pContainerWindow( VCLUnoHelper::GetWindow( xContainerWindow ) );
-            Window* pDockingAreaWindow( 0 );
-            ::Point aMousePos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
-
-            if ( aHotZoneTopDockRect.IsInside( aMousePos ))
-                eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
-            else if ( aHotZoneBottomDockRect.IsInside( aMousePos ))
-                eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
-            else if ( aHotZoneLeftDockRect.IsInside( aMousePos ))
-                eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
-            else if ( aHotZoneRightDockRect.IsInside( aMousePos ))
-                eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
-
-            // Higher priority for movements inside the real docking area
-            if ( aTopDockRect.IsInside( aMousePos ))
-                eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
-            else if ( aBottomDockRect.IsInside( aMousePos ))
-                eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
-            else if ( aLeftDockRect.IsInside( aMousePos ))
-                eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
-            else if ( aRightDockRect.IsInside( aMousePos ))
-                eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
-
-            // Determine if we have a docking window and set alignment according to the docking area!
-            DockingWindow* pDockWindow = dynamic_cast< DockingWindow *>( VCLUnoHelper::GetWindow( xWindow ));
-
-            if ( pDockWindow )
+            SplitPanelManager::DockingInfo aInfo;
+            DockingWindow* pDockWindow = dynamic_cast< DockingWindow *>( VCLUnoHelper::GetWindow( xDockWindow ));
+            Window*        pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
+            if ( pDockWindow && pContainerWindow )
             {
-                if ( eDockingArea != -1 )
+                ::Size aStoredDockSize( aUIDockingElement.m_aDockedData.m_aSize );
+                
+                if ( aStoredDockSize.getWidth() > 0 && aStoredDockSize.getHeight() )
                 {
-                    if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
+                    aNewTrackingRect.Width  = aStoredDockSize.getWidth();
+                    aNewTrackingRect.Height = aStoredDockSize.getHeight();
+                }
+                else
+                {
+                    ::Point aPos  = pDockWindow->GetPosPixel();
+                    ::Size  aSize = pDockWindow->GetSizePixel();
+                    aNewTrackingRect.X = aPos.X();
+                    aNewTrackingRect.Y = aPos.Y();
+                    aNewTrackingRect.Width = aSize.getWidth();
+                    aNewTrackingRect.Height = aSize.getHeight();
+                }
+                
+                ::Point aOutPos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
+                for ( int i = 0; i < SPLITPANEL_COUNT; i++ )
+                {
+                    SplitPanelManager* pMgr = impl_getSplitPanelManager( aSplitPanels[i] );
+                    if ( pMgr )
                     {
-                        aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_TOP;
-                        aUIDockingElement.m_bFloating = false;
-                        pDockingAreaWindow = VCLUnoHelper::GetWindow( xSplitWinTop );
+                        awt::Point aMousePos( aOutPos.X(), aOutPos.Y() );
+                        aInfo = pMgr->getDockingInfo( aMousePos, aNewTrackingRect );
+                        if ( aInfo.bCanDock )
+                            break;
                     }
-                    else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
-                    {
-                        aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
-                        aUIDockingElement.m_bFloating = false;
-                        pDockingAreaWindow = VCLUnoHelper::GetWindow( xSplitWinBottom );
-                    }
-                    else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
-                    {
-                        aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_LEFT;
-                        aUIDockingElement.m_bFloating = false;
-                        pDockingAreaWindow = VCLUnoHelper::GetWindow( xSplitWinLeft );
-                    }
-                    else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
-                    {
-                        aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_RIGHT;
-                        aUIDockingElement.m_bFloating = false;
-                        pDockingAreaWindow = VCLUnoHelper::GetWindow( xSplitWinRight );
-                    }
-
-                    ::Point aOutputPos = pContainerWindow->ScreenToOutputPixel( aTrackingRect.TopLeft() );
-                    aTrackingRect.SetPos( aOutputPos );
-
-                    awt::Rectangle aVirtDockingPosSize;
-                    aDockingData.bFloating = false;
-                    aDockingData.TrackingRectangle = calcSimpleDockingRect( eDockingArea, awt::Point( aMousePos.X(), aMousePos.Y()), xWindow, aVirtDockingPosSize );
-                    aUIDockingElement.m_aDockedData.m_aPos  = ::Point( aVirtDockingPosSize.X, aVirtDockingPosSize.Y );
-                    aUIDockingElement.m_aDockedData.m_aSize = ::Size( aVirtDockingPosSize.Width, aVirtDockingPosSize.Height );
+                }
+                
+                if ( aInfo.bCanDock )
+                {
+                    aUIDockingElement.m_bFloating                 = false;
+                    aUIDockingElement.m_aDockedData.m_nDockedArea = static_cast< sal_Int16 >( aInfo.eSplitPanelPos );
+                    aUIDockingElement.m_aDockedData.m_aPos        = ::Point( aInfo.aDockingRect.X, aInfo.aDockingRect.Y );
+                    aUIDockingElement.m_aDockedData.m_aSize       = ::Size( aInfo.aDockingRect.Width, aInfo.aDockingRect.Height );
+                    
+                    aDockingData.bFloating         = false;
+                    aDockingData.TrackingRectangle = aInfo.aDockingRect;
                 }
                 else
                 {
                     ::Size aSize = pDockWindow->GetSizePixel();
-                    aUIDockingElement.m_aFloatingData.m_aPos = pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y ));
+                    aUIDockingElement.m_bFloating             = true;
+                    aUIDockingElement.m_aFloatingData.m_aPos  = pDockWindow->GetPosPixel();
                     aUIDockingElement.m_aFloatingData.m_aSize = aSize;
+                    
                     aDockingData.TrackingRectangle.Height = aSize.Height();
                     aDockingData.TrackingRectangle.Width  = aSize.Width();
                 }
+
+                aDockingData.bFloating = !aInfo.bCanDock;
             }
 
-            aDockingData.bFloating = ( eDockingArea == -1 );
-
             // Write current data to the member docking progress data
             WriteGuard aWriteLock( m_aLock );
             m_aCurrDockingWindow.m_bFloating = aDockingData.bFloating;
 void SAL_CALL PanelManager::endDocking( const awt::EndDockingEvent& ) 
 throw (uno::RuntimeException)
 {
-    bool bDockingInProgress( false );
-    bool bStartDockFloated( false );
-    bool bFloating( false );
-    UIElement aUIDockingElement;
-
     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
     WriteGuard aWriteLock( m_aLock );
-    bDockingInProgress = m_bDockingInProgress;
-    aUIDockingElement  = m_aCurrDockingWindow;
-    bFloating          = aUIDockingElement.m_bFloating;
+    bool bDockingInProgress( m_bDockingInProgress );
+    UIElement aUIDockingElement( m_aCurrDockingWindow );
+    bool bFloating( aUIDockingElement.m_bFloating );
+    bool bLastFloating( false );
+    DockedData aLastDockedData;
 
     uno::Reference< awt::XWindow > xWindow;
     UIElement& rUIElement = impl_findDockingWindow( aUIDockingElement.m_aName );
     if ( rUIElement.m_aName == aUIDockingElement.m_aName )
     {
+        // remember last docking/floating state data
+        aLastDockedData = rUIElement.m_aDockedData;
+        bLastFloating   = rUIElement.m_bFloating;
+        
         xWindow = uno::Reference< awt::XWindow >( aUIDockingElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
         if ( aUIDockingElement.m_bFloating )
         {
             rUIElement.m_aFloatingData.m_aSize = aUIDockingElement.m_aFloatingData.m_aSize;
         }
             
-        bStartDockFloated        = rUIElement.m_bFloating;
         rUIElement.m_bFloating   = m_aCurrDockingWindow.m_bFloating;
         rUIElement.m_bUserActive = true;
         aUIDockingElement = rUIElement;
 
 //    implts_writeWindowStateData( aUIDockingElement );
 
-    if ( bDockingInProgress && !aUIDockingElement.m_bFloating )
+    if ( bDockingInProgress && !aUIDockingElement.m_bFloating && xWindow.is() )
     {
         sal_Int16 eDockArea( aUIDockingElement.m_aDockedData.m_nDockedArea );
         ::Point   aVirtPos( aUIDockingElement.m_aDockedData.m_aPos );
         ::Size    aVirtSize( aUIDockingElement.m_aDockedData.m_aSize );
+        
+        if ( !bLastFloating )
+            implts_undockWindow( aLastDockedData.m_nDockedArea, xWindow );
         implts_dockWindow( eDockArea, awt::Rectangle( aVirtPos.X(), aVirtPos.Y(), aVirtSize.Width(), aVirtSize.Height() ), xWindow );
     }
 
     aWriteLock.lock();
-    m_bDockingInProgress = sal_False;
-    m_bLayoutDirty       = !bStartDockFloated || !bFloating;
+    m_bDockingInProgress = false;
+    m_bLayoutDirty       = !bLastFloating || !bFloating;
     bool bNotify         = m_bLayoutDirty;
     aWriteLock.unlock();
 
         m_pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLPANESPACE_HAS_CHANGED );
 }
 
-sal_Bool SAL_CALL PanelManager::prepareToggleFloatingMode( const lang::EventObject& ) 
+sal_Bool SAL_CALL PanelManager::prepareToggleFloatingMode( const lang::EventObject& e ) 
 throw (uno::RuntimeException)
 {
+    ReadGuard aReadLock( m_aLock );
+    bool bDockingInProgress = m_bDockingInProgress;
+    aReadLock.unlock();
+
+    UIElement aUIDockingElement;
+    if ( implts_findDockingWindow( e.Source, aUIDockingElement ))
+    {
+        uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
+        
+        if ( xWindow.is() && !bDockingInProgress )
+        {
+            {
+                vos::OGuard aGuard( Application::GetSolarMutex() );
+                DockingWindow* pDockWindow = dynamic_cast< DockingWindow *>( VCLUnoHelper::GetWindow( xWindow ));
+                if ( pDockWindow && pDockWindow->IsFloatingMode() )
+                {
+                    aUIDockingElement.m_aFloatingData.m_aPos = pDockWindow->GetPosPixel();
+                    aUIDockingElement.m_aFloatingData.m_aSize = pDockWindow->GetOutputSizePixel();
+                }
+            }
+
+            WriteGuard aWriteLock( m_aLock );
+            UIElement& aUIElement = impl_findDockingWindow( aUIDockingElement.m_aName );
+            if ( aUIElement.m_aName == aUIDockingElement.m_aName )
+            {
+                aUIElement.m_aFloatingData.m_aPos = aUIDockingElement.m_aFloatingData.m_aPos;
+                aUIElement.m_aFloatingData.m_aSize = aUIDockingElement.m_aFloatingData.m_aSize;
+            }
+            aWriteLock.unlock();
+        }
+    }
+    
     return true;
 }
 
-void SAL_CALL PanelManager::toggleFloatingMode( const lang::EventObject& /*e*/ ) 
+void SAL_CALL PanelManager::toggleFloatingMode( const lang::EventObject& e ) 
 throw (uno::RuntimeException)
 {
+    UIElement aUIDockingElement;
+
+    ReadGuard aReadLock( m_aLock );
+    bool bDockingInProgress( m_bDockingInProgress );
+    if ( bDockingInProgress )
+        aUIDockingElement  = m_aCurrDockingWindow;
+    aReadLock.unlock();
+
+    Window* pWindow( 0 );
+    uno::Reference< awt::XWindow > xWindow;
+    uno::Reference< awt::XWindow2 > xWindow2;
+
+    {
+        vos::OGuard aGuard( Application::GetSolarMutex() );
+        xWindow2 = uno::Reference< awt::XWindow2 >( e.Source, uno::UNO_QUERY );
+        xWindow = uno::Reference< awt::XWindow >( xWindow2, uno::UNO_QUERY );
+        pWindow = VCLUnoHelper::GetWindow( xWindow );
+    }
+
+    if ( !bDockingInProgress )
+    {
+        UIElement aUIDockingElement;
+        if ( implts_findDockingWindow( e.Source, aUIDockingElement ))
+        {
+            aUIDockingElement.m_bFloating   = !aUIDockingElement.m_bFloating;
+            aUIDockingElement.m_bUserActive = true;
+
+            sal_Int16 eDockArea( aUIDockingElement.m_aDockedData.m_nDockedArea );
+            ::Point   aVirtPos( aUIDockingElement.m_aDockedData.m_aPos );
+            ::Size    aVirtSize( aUIDockingElement.m_aDockedData.m_aSize );
+            bool      bFloating( aUIDockingElement.m_bFloating );
+            
+            if ( bFloating )
+            {
+                vos::OGuard aGuard( Application::GetSolarMutex() );
+
+                bool bUndefPos = hasDefaultPosValue( aUIDockingElement.m_aFloatingData.m_aPos );
+                bool bSetSize = !hasEmptySize( aUIDockingElement.m_aFloatingData.m_aSize );
+
+                if ( bUndefPos )
+                    aUIDockingElement.m_aFloatingData.m_aPos = implts_findNextCascadeFloatingPos();
+
+                if ( !bSetSize )
+                    aUIDockingElement.m_aFloatingData.m_aSize = pWindow->GetOutputSizePixel();
+
+                implts_undockWindow( eDockArea, xWindow );
+                
+                xWindow2->setPosSize( aUIDockingElement.m_aFloatingData.m_aPos.X(),
+                                      aUIDockingElement.m_aFloatingData.m_aPos.Y(),
+                                      0, 0, awt::PosSize::POS );
+                xWindow2->setOutputSize( AWTSize( aUIDockingElement.m_aFloatingData.m_aSize ) );
+            }
+            else
+            {
+                if ( isDefaultPos( aUIDockingElement.m_aDockedData.m_aPos ))
+                {
+                    // Docking on its default position without a preset position -
+                    // we have to find a good place for it.
+                    ::Point aPixelPos;
+                    ::Point aDockPos;
+                    ::Size  aSize;
+
+                    {
+                        vos::OGuard aGuard( Application::GetSolarMutex() );
+                        aSize = pWindow->GetSizePixel();
+                    }
+
+//                    implts_findNextDockingPos((ui::DockingArea)aUIDockingElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
+//                    aUIDockingElement.m_aDockedData.m_aPos = aDockPos;
+                }
+
+                implts_dockWindow( eDockArea, awt::Rectangle( aVirtPos.X(), aVirtPos.Y(), aVirtSize.Width(), aVirtSize.Height() ), xWindow );
+            }
+
+            implts_setLayoutDirty();
+            
+            aReadLock.lock();
+            ILayoutNotifications* pParentLayouter( m_pParentLayouter );
+            aReadLock.unlock();
+
+            if ( pParentLayouter )
+                pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLPANESPACE_HAS_CHANGED );
+        }
+    }
 }
 
-void SAL_CALL PanelManager::closed( const lang::EventObject& ) 
+void SAL_CALL PanelManager::closed( const lang::EventObject& e ) 
 throw (uno::RuntimeException)
 {
+    UIElement aUIDockingElement;
+    if ( implts_findDockingWindow( e.Source, aUIDockingElement ))
+    {
+    }
 }
 
 void SAL_CALL PanelManager::endPopupMode( const awt::EndPopupModeEvent& ) 

framework/source/layoutmanager/panelmanager.hxx

 #include <stdtypes.h>
 #include <uielement/uielement.hxx>
 #include <helper/ilayoutnotifications.hxx>
+#include <helper/ilayoutinformation.hxx>
+#include <splitpanelmanager.hxx>
 
 //_________________________________________________________________________________________________________________
 //	interface includes
 namespace framework
 {
 		
-enum SplitPanelPosition
-{
-	SPLITPANEL_TOP,
-	SPLITPANEL_BOTTOM,
-	SPLITPANEL_LEFT,
-	SPLITPANEL_RIGHT,
-	SPLITPANEL_COUNT
-};
-
 class PanelManager : public ::cppu::WeakImplHelper2< css::awt::XDockableWindowListener,
                                                      css::awt::XWindowListener >,
+                     public ILayoutNotifications,
+                     public ILayoutInformation,
                      private ThreadHelpBase // Struct for right initalization of mutex member! Must be first of baseclasses.
 {
 	public:
         
         // layouting
         void resetDockingArea();
+        css::awt::Rectangle getDockingArea();
         void setDockingArea( const css::awt::Rectangle& rDockingArea );
         void setDockingAreaOffsets( const css::awt::Rectangle& rOffsets );
-        css::awt::Rectangle getPreferredSize();
-        css::awt::Rectangle getMinimalSize();
         void calcLayout();
-        void doLayout( const css::awt::Size& rSize );
-        
+        void doLayout( const css::awt::Size& rWorkspaceArea );
         bool isLayoutDirty() const;
 
         bool createDockingWindow( const ::rtl::OUString& rResourceName );
         bool destroyDockingWindow( const ::rtl::OUString& rResourceName );
         
         //---------------------------------------------------------------------------------------------------------
+        // ILayoutNotifications
+        //---------------------------------------------------------------------------------------------------------
+        virtual void requestLayout( Hint eHint );
+        
+        //---------------------------------------------------------------------------------------------------------
+        // ILayoutInformation
+        //---------------------------------------------------------------------------------------------------------
+        css::awt::Rectangle getWorkspaceArea();
+        
+        //---------------------------------------------------------------------------------------------------------
         // XInterface
         //---------------------------------------------------------------------------------------------------------
         virtual void SAL_CALL acquire() throw();
         void destroySplitPanels();
         void destroyPanels();
 
-        css::awt::Rectangle calcSimpleDockingRect( const sal_Int16 eDockingArea, const css::awt::Point& rMousePos, const css::uno::Reference< css::awt::XWindow >& xWindow, css::awt::Rectangle& rVirtDockSize );
+        void impl_createOrSetSplitPanel( const SplitPanelPosition ePos, css::uno::Reference< css::lang::XComponent >& xSplitPanel );
         bool implts_dockWindow( const sal_Int16 eDockingArea, const css::awt::Rectangle& rVirtDockSize, const css::uno::Reference< css::awt::XWindow >& xWindow );
+        bool implts_undockWindow( const sal_Int16 eDockingArea, const css::uno::Reference< css::awt::XWindow >& xWindow );
         bool implts_findDockingWindow( const ::rtl::OUString& rResourceName, UIElement& rUIElement );
         bool implts_findDockingWindow( const css::uno::Reference< css::uno::XInterface >& xEventObject, UIElement& aUIElement );
         UIElement& impl_findDockingWindow( const ::rtl::OUString& rResourceName );
+        ::Point implts_findNextCascadeFloatingPos();
         
-        css::awt::Rectangle implts_calcSimpleDockingRect( sal_Int16 eDockingArea, const css::awt::Point& rMousePos, const css::uno::Reference< css::awt::XWindow >& xWindow );
         css::uno::Reference< css::awt::XWindow > implts_createSplitPanel();
         void implts_enableListeners( const css::uno::Reference< css::awt::XWindow >& xPanelWindow );
         void implts_reparentSplitWindows();
-        void implts_showAndSetPosSizePixel( const css::uno::Reference< css::awt::XWindow >& xWindow, 
-                                            const css::awt::Point& rPos, const css::awt::Size& rSize );
+        void implts_showAndSetPosSizePixel( const css::uno::Reference< css::lang::XComponent >& xSplitPanel, const css::awt::Point& rPos, const css::awt::Size& rSize );
         void implts_setLayoutDirty();
         bool implts_addDockingWindow( const ::rtl::OUString& rResourceName, const css::uno::Reference< css::ui::XUIElement >& xUIElement );
+        
+        typedef std::vector< css::uno::Reference< css::lang::XComponent > > SplitPanelVector;
 
-        css::uno::Reference< css::awt::XWindow >               m_aSplitPanels[SPLITPANEL_COUNT];
+        SplitPanelVector                                       m_aSplitPanels;
         css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR;
         css::uno::Reference< css::frame::XFrame >              m_xFrame;
         css::uno::Reference< css::awt::XWindow2 >              m_xContainerWindow;
         css::awt::Rectangle                                    m_aDockingAreaOffsets;
         css::awt::Rectangle                                    m_aMinimalDockingArea;
         css::awt::Rectangle                                    m_aPreferredDockingArea;
-        css::awt::Rectangle                                    m_aClientSpace;
+        css::awt::Rectangle                                    m_aWorkspace;
         bool                                                   m_bLayoutDirty;
         bool                                                   m_bComponentAttached;
         bool                                                   m_bDockingInProgress;

framework/source/layoutmanager/splitpanelcontainerwindow.cxx

 // my own includes
 #include <splitpanelcontainerwindow.hxx>
 
+namespace framework
+{
+
 SplitPanelContainerWindow::SplitPanelContainerWindow( Window* pParent, WinBits nBits ) :
-    SplitWindow( pParent, nBits | WB_3DLOOK | WB_BORDER )
+    SplitWindow( pParent, nBits | WB_3DLOOK | WB_BORDER | WB_CLIPCHILDREN | WB_SIZEABLE )
 {
-    ShowFadeOutButton( true );
 }
 
 SplitPanelContainerWindow::~SplitPanelContainerWindow()
 {
     SplitWindow::GetFocus();
 }
+
+} // namespace framework

framework/source/layoutmanager/splitpanelcontainerwindow.hxx

 // other includes
 #include <vcl/splitwin.hxx>
 
+namespace framework
+{
+
 class SplitPanelContainerWindow : public SplitWindow
 {
     public:
         virtual void GetFocus();
 };
 
+}
+
 #endif // __FRAMEWORK_LAYOUTMANAGER_SPLITPANELCONTAINERWINDOW_HXX_

framework/source/layoutmanager/splitpanelmanager.cxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: layoutmanager.hxx,v $
+ * $Revision: 1.34 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_framework.hxx"
+
+// my own includes
+#include <splitpanelmanager.hxx>
+#include <helper/ilayoutinformation.hxx>
+#include <helpers.hxx>
+
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/splitwin.hxx>
+#include <toolkit/unohlp.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vos/mutex.hxx>
+
+using namespace ::com::sun::star;
+
+namespace framework
+{
+
+static const sal_uInt16 nRowColId = 1;
+static const sal_uInt16 nStartID  = 1000;  
+
+SplitPanelManager::SplitPanelManager( const SplitPanelPosition eSplitAlign, ILayoutNotifications* pParentListener ) :
+    m_bFadeIn( true ),
+    m_bEmpty( true ),
+    m_bDisposed( false ),
+    m_bLayoutDirty( false ),
+    m_bSplitResize( false ),
+    m_nFadeInSize( 0 ),
+    m_eSplitPos( eSplitAlign ),
+    m_pParentListener( pParentListener ),
+    m_pSplitWindow(0)
+{
+}
+
+SplitPanelManager::~SplitPanelManager()
+{
+}
+
+void SplitPanelManager::setParentWindow( uno::Reference< awt::XWindow >& xParent )
+{
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    Window* pParent = VCLUnoHelper::GetWindow( xParent );
+    if ( !m_pSplitWindow )
+    {
+        m_pSplitWindow = new SplitPanelContainerWindow( pParent, 0 );
+        m_pEmptySplitWindow = new SplitWindow( pParent, WinBits( WB_BORDER | WB_3DLOOK ));
+        if ( m_eSplitPos == SPLITPANEL_TOP )
+        {
+            m_pSplitWindow->SetAlign( WINDOWALIGN_TOP );
+            m_pEmptySplitWindow->SetAlign( WINDOWALIGN_TOP );
+        }
+        else if ( m_eSplitPos == SPLITPANEL_BOTTOM )
+        {
+            m_pSplitWindow->SetAlign( WINDOWALIGN_BOTTOM );
+            m_pEmptySplitWindow->SetAlign( WINDOWALIGN_BOTTOM );
+        }
+        else if ( m_eSplitPos == SPLITPANEL_LEFT )
+        {
+            m_pSplitWindow->SetAlign( WINDOWALIGN_LEFT );
+            m_pEmptySplitWindow->SetAlign( WINDOWALIGN_LEFT );
+        }
+        else if ( m_eSplitPos == SPLITPANEL_RIGHT )
+        {
+            m_pSplitWindow->SetAlign( WINDOWALIGN_RIGHT );
+            m_pEmptySplitWindow->SetAlign( WINDOWALIGN_RIGHT );
+        }
+        m_pSplitWindow->SetStartSplitHdl( LINK( this, SplitPanelManager, StartSplit ) );
+        m_pSplitWindow->SetSplitHdl( LINK( this, SplitPanelManager, Split ) );
+        m_pSplitWindow->SetSplitResizeHdl( LINK( this, SplitPanelManager, SplitResize ) );
+        m_pSplitWindow->SetFadeInHdl( LINK( this, SplitPanelManager, FadeIn ) );
+        m_pSplitWindow->SetFadeOutHdl( LINK( this, SplitPanelManager, FadeOut ) );
+        m_pSplitWindow->ShowFadeOutButton( true );
+        
+        // Empty split window for fade out state. Cannot be done with SplitWindow as it's
+        // implementation is not flexible enough.
+        m_pEmptySplitWindow->ShowFadeInHideButton( true );
+        m_pEmptySplitWindow->Hide();
+        m_pEmptySplitWindow->SetFadeInHdl( LINK( this, SplitPanelManager, FadeIn ) );
+    }
+    else
+    {
+        m_pSplitWindow->SetParent( pParent );
+        m_pEmptySplitWindow->SetParent( pParent );
+    }
+}
+
+bool SplitPanelManager::isLayoutDirty() const
+{
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    return m_bLayoutDirty;
+}
+
+bool SplitPanelManager::isEmpty() const
+{
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    return m_bEmpty;
+}
+
+bool SplitPanelManager::isVisible() const
+{
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    if ( m_pSplitWindow )
+        return m_pSplitWindow->IsVisible();
+    else
+        return false;
+}
+
+bool SplitPanelManager::isHorizontal() const
+{
+    return ( m_eSplitPos == SPLITPANEL_TOP || m_eSplitPos == SPLITPANEL_BOTTOM );
+}
+
+void SplitPanelManager::setPosSize( const awt::Point& rPos, const awt::Size& rSize )
+{
+    uno::Reference< lang::XComponent > xThis( this );
+    
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    
+    if ( m_pSplitWindow && m_pEmptySplitWindow )
+    {
+        m_pSplitWindow->SetPosSizePixel( ::Point( rPos.X, rPos.Y ), ::Size( rSize.Width, rSize.Height ));
+        m_pEmptySplitWindow->SetPosSizePixel( ::Point( rPos.X, rPos.Y ), ::Size( rSize.Width, rSize.Height ));
+    }
+}
+
+void SplitPanelManager::setMaxSize( sal_Int32 nMaxSize )
+{
+    uno::Reference< lang::XComponent > xThis( this );
+    
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    if ( m_pSplitWindow )
+        m_pSplitWindow->SetMaxSizePixel( nMaxSize );
+}
+
+void SplitPanelManager::setSize( sal_Int32 nNewSize )
+{
+    uno::Reference< lang::XComponent > xThis( this );
+    
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    if ( m_pSplitWindow && m_pEmptySplitWindow )
+    {
+        Window* pWindow = m_bFadeIn ? m_pSplitWindow : m_pEmptySplitWindow;
+        
+        if ( !m_bFadeIn )
+            nNewSize = m_pEmptySplitWindow->GetFadeInSize();
+            
+        ::Point aPos( m_pSplitWindow->GetPosPixel() );
+        ::Size  aSize( m_pSplitWindow->GetSizePixel() );
+        if ( isHorizontal() )
+        {
+            sal_Int32 nPosY = ( m_eSplitPos == SPLITPANEL_TOP ) ? 
+                aPos.Y() : ::std::max( aPos.Y() - ( nNewSize - aSize.getHeight()), sal_Int32(0));
+            pWindow->SetPosSizePixel( ::Point( aPos.X(), nPosY ), ::Size( aSize.getWidth(), nNewSize ));
+        }
+        else
+        {
+            sal_Int32 nPosX = ( m_eSplitPos == SPLITPANEL_LEFT ) ? 
+                aPos.X() : ::std::max( aPos.X() - ( nNewSize - aSize.getWidth()), sal_Int32(0));
+            pWindow->SetPosSizePixel( ::Point( nPosX, aPos.Y() ), ::Size( nNewSize, aSize.getHeight() ));
+        }
+    }    
+    
+    if ( m_pParentListener )
+        m_pParentListener->requestLayout();
+}
+
+sal_Int32 SplitPanelManager::getSize() const
+{
+    sal_Int32 nSize(0);
+    
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    if ( m_pSplitWindow )
+    {
+        if ( !m_bFadeIn )
+            nSize = m_pEmptySplitWindow->GetFadeInSize();
+        else
+        {
+            ::Size aSize = m_pSplitWindow->GetSizePixel();
+            sal_uInt16 nItems = m_pSplitWindow->GetItemCount(nRowColId);
+            if ( nItems > 0 )
+            {
+                long nFixedSize( 0 );
+                long nSize = m_pSplitWindow->GetItemSize(nRowColId);
+                
+                if ( isHorizontal() )
+                    aSize.setHeight( nSize );
+                else
+                    aSize.setWidth( nSize );
+                aSize = m_pSplitWindow->CalcWindowSizePixel( aSize );
+            }
+            nSize = isHorizontal() ? aSize.getHeight() : aSize.getWidth();
+        }
+    }
+    
+    return nSize;
+}
+
+awt::Rectangle SplitPanelManager::getPosSize() const
+{
+    awt::Rectangle aRect;
+    
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    if ( m_pSplitWindow && m_pEmptySplitWindow )
+    {
+        Window* pWindow = m_bFadeIn ? m_pSplitWindow : m_pEmptySplitWindow;
+        
+        ::Point aPos = pWindow->GetPosPixel();
+        ::Size  aSize = pWindow->GetSizePixel();
+        aRect.X = aPos.X();
+        aRect.Y = aPos.Y();
+        aRect.Width = aSize.getWidth();
+        aRect.Height = aSize.getHeight();
+    }
+    return aRect;
+}
+
+void SplitPanelManager::setVisible( bool bVisible )
+{
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    if ( m_pSplitWindow && m_pEmptySplitWindow )
+    {
+        if ( m_bFadeIn )
+        {
+            if ( bVisible )
+                m_pSplitWindow->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
+            else
+                m_pSplitWindow->Hide();
+        }
+        else
+        {
+            if ( bVisible )
+                m_pEmptySplitWindow->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
+            else
+            {
+                m_pEmptySplitWindow->Hide();
+                m_pSplitWindow->Hide();
+            }
+        }
+    }
+}
+
+SplitPanelManager::DockedWinInfo* SplitPanelManager::impl_getDockedWinInfo( sal_uInt16 nId )
+{
+    DockedWindows::iterator pIter = m_aDockedWindows.begin();
+    while ( pIter != m_aDockedWindows.end() )
+    {
+        if ( pIter->nId == nId )
+            return pIter;
+        ++pIter;
+    }
+    
+    return 0;
+}
+
+::Point SplitPanelManager::impl_calcDockingMousePos( const ::Point& aMousePos )
+{
+    bool      bHorz( isHorizontal() );
+    ::Size    aOutSize( m_pSplitWindow->GetOutputSizePixel() );
+    ::Point   aDockMousePos;
+    sal_Int32 nSplitSize( m_pSplitWindow->GetItemSize( nRowColId ));
+    sal_Int32 nPosX( aMousePos.X() );
+    sal_Int32 nPosY( aMousePos.Y() );
+    
+    sal_Int32 nDecoSize = m_pSplitWindow->GetFadeInSize();
+    if ( bHorz )
+    {
+        aDockMousePos.X() = ::std::min( ::std::max( nPosX, sal_Int32( 2 )), sal_Int32( aOutSize.getWidth() ));
+        aDockMousePos.Y() = ::std::min( ::std::max( nPosY, nDecoSize ), sal_Int32( aOutSize.getHeight() - nDecoSize ));
+    }
+    else
+    {
+        aDockMousePos.X() = ::std::min( ::std::max( nPosX, nDecoSize ), sal_Int32( aOutSize.getWidth() - nDecoSize ));
+        aDockMousePos.Y() = ::std::min( ::std::max( nPosY, sal_Int32( 2 )), sal_Int32( aOutSize.getHeight() ));
+    }
+    
+    return aDockMousePos;
+}
+
+SplitPanelManager::DockingInfo SplitPanelManager::getDockingInfo( const awt::Point& rMousePos, const awt::Rectangle& rDockRect )
+{
+    const sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
+    const sal_Int32 MAGNETIC_DISTANCE_DOCK   = 20;
+
+    DockingInfo aDockingInfo;
+    ::Rectangle aWorkspaceRect;
+
+    vos::OGuard aGuard( Application::GetSolarMutex() );
+    
+    ILayoutInformation* pParentInfo = dynamic_cast< ILayoutInformation* >( m_pParentListener );
+    
+    if ( pParentInfo )
+        aWorkspaceRect = VCLRectangle( pParentInfo->getWorkspaceArea());
+        
+    bool         bEmpty( isEmpty() );
+    bool         bHorz( isHorizontal() );
+    ::Rectangle  aWinRect;
+    
+    if ( m_pSplitWindow )
+    {
+        // Retrieve size from split window
+        ::Rectangle aWinRect( m_pSplitWindow->GetPosPixel(), m_pSplitWindow->GetSizePixel() );
+    
+        ::Rectangle aHotZoneRect( calcHotZoneRect( aWinRect, MAGNETIC_DISTANCE_DOCK ));
+        ::Point     aMousePos( rMousePos.X, rMousePos.Y );
+        
+        if ( aHotZoneRect.IsInside( aMousePos ))
+        {
+            awt::Rectangle aDockingRect;
+            
+            // set docking flag on docking info
+            aDockingInfo.bCanDock = true;
+            aDockingInfo.eSplitPanelPos = m_eSplitPos;
+            
+            sal_uInt16 nCount( m_pSplitWindow->GetItemCount( nRowColId ));
+            ::Size aOutSize( m_pSplitWindow->GetOutputSizePixel() );
+            ::Point aVirtMousePos( impl_calcDockingMousePos( m_pSplitWindow->ScreenToOutputPixel( aMousePos )));
+            sal_uInt16 nId( m_pSplitWindow->GetItemId( aVirtMousePos ));
+            
+            if ( nCount == 0 || nId == SPLITWINDOW_ITEM_NOTFOUND || nId < nStartID )
+            {
+                if ( isHorizontal() )
+                {
+                    sal_Int32 nMaxHeight = sal_Int32( aWorkspaceRect.GetHeight() * 80 / 100 );
+                    sal_Int32 nHeight = std::max( std::min( rDockRect.Height, nMaxHeight ), sal_Int32( 1 ));
+                    
+                    aDockingRect.X      = aWinRect.Left();
+                    aDockingRect.Width  = aOutSize.getWidth();
+                    aDockingRect.Height = nHeight;
+                    
+                    if ( m_eSplitPos == SPLITPANEL_TOP )
+                        aDockingRect.Y = aWinRect.Top();
+                    else
+                        aDockingRect.Y = std::max( sal_Int32( aWinRect.Top() - nHeight ), sal_Int32( 0 ));
+                }
+                else
+                {
+                    sal_Int32 nMaxWidth = sal_Int32( aWorkspaceRect.GetWidth() * 80 / 100 );
+                    sal_Int32 nWidth = std::max( std::min( rDockRect.Width, nMaxWidth ), sal_Int32( 1 ));
+                    
+                    aDockingRect.Y      = aWinRect.Top();
+                    aDockingRect.Height = aOutSize.getHeight();
+                    aDockingRect.Width  = nWidth;
+                    
+                    if ( m_eSplitPos == SPLITPANEL_LEFT )
+                        aDockingRect.X = aWinRect.Left();
+                    else
+                        aDockingRect.X = std::max( sal_Int32( aWinRect.Left() - nWidth ), sal_Int32( 0 ));
+                }
+            }
+            else
+            {
+                sal_uInt16     nCount = m_pSplitWindow->GetItemCount( nRowColId );
+                long           nSize = m_pSplitWindow->GetItemSize( nId, SWIB_FIXED );
+                sal_uInt16     nPos = m_pSplitWindow->GetItemPos( nId, nRowColId );
+                DockedWinInfo* pInfo = impl_getDockedWinInfo( nId );
+                Window*        pWindow = m_pSplitWindow->GetItemWindow( nId );
+                sal_Int32      nItemsSize = implts_getItemsSize();
+                if ( pWindow )
+                {
+                    sal_uInt16 nDockPos(0);
+                    ::Point aPos = pWindow->GetPosPixel();
+                    ::Size  aSize = pWindow->GetSizePixel();