1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <svl/eitem.hxx>
31 #include <vcl/decoview.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/timer.hxx>
35 #include <rtl/instance.hxx>
36 #include <toolkit/helper/vclunohelper.hxx>
37 #include <comphelper/processfactory.hxx>
39 #include <sfx2/dockwin.hxx>
40 #include <sfx2/bindings.hxx>
41 #include <sfx2/viewfrm.hxx>
42 #include <sfx2/dispatch.hxx>
43 #include "workwin.hxx"
44 #include "splitwin.hxx"
45 #include <sfx2/viewsh.hxx>
46 #include "sfx2/sfxhelp.hxx"
47 #include <sfx2/objsh.hxx>
48 #include <sfx2/msgpool.hxx>
50 #include <com/sun/star/frame/XController.hpp>
51 #include <com/sun/star/lang/XUnoTunnel.hpp>
52 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
53 #include <com/sun/star/awt/XWindow.hpp>
54 #include <com/sun/star/uno/XComponentContext.hpp>
55 #include <com/sun/star/frame/XModuleManager.hpp>
56 #include <com/sun/star/container/XNameAccess.hpp>
58 #define MAX_TOGGLEAREA_WIDTH 20
59 #define MAX_TOGGLEAREA_HEIGHT 20
61 using namespace ::com::sun::star
;
63 // implemented in 'sfx2/source/appl/childwin.cxx'
64 extern sal_Bool
GetPosSizeFromString( const String
& rStr
, Point
& rPos
, Size
& rSize
);
65 extern sal_Bool
GetSplitSizeFromString( const String
& rStr
, Size
& rSize
);
67 // If you want to change the number you also have to:
68 // - Add new slot ids to sfxsids.hrc
69 // - Add new slots to frmslots.sdi
70 // - Add new slot definitions to sfx.sdi
71 static const int NUM_OF_DOCKINGWINDOWS
= 10;
73 class SfxTitleDockingWindow
;
74 class SfxTitleDockingWindow
: public SfxDockingWindow
76 Window
* m_pWrappedWindow
;
80 SfxTitleDockingWindow(
81 SfxBindings
* pBindings
,
82 SfxChildWindow
* pChildWin
,
86 virtual ~SfxTitleDockingWindow();
88 Window
* GetWrappedWindow() const { return m_pWrappedWindow
; }
89 void SetWrappedWindow(Window
* const pWindow
);
91 virtual void StateChanged( StateChangedType nType
);
92 virtual long Notify( NotifyEvent
& rNEvt
);
93 virtual void Resize();
94 virtual void Resizing( Size
& rSize
);
95 virtual sal_Bool
Close();
102 ::rtl::OUString sTitle
;
106 static bool lcl_getWindowState( const uno::Reference
< container::XNameAccess
>& xWindowStateMgr
, const ::rtl::OUString
& rResourceURL
, WindowState
& rWindowState
)
108 bool bResult
= false;
113 uno::Sequence
< beans::PropertyValue
> aWindowState
;
114 a
= xWindowStateMgr
->getByName( rResourceURL
);
115 if ( a
>>= aWindowState
)
117 for ( sal_Int32 n
= 0; n
< aWindowState
.getLength(); n
++ )
119 if ( aWindowState
[n
].Name
== "UIName" )
121 aWindowState
[n
].Value
>>= rWindowState
.sTitle
;
128 catch ( container::NoSuchElementException
& )
136 SfxDockingWrapper::SfxDockingWrapper( Window
* pParentWnd
,
138 SfxBindings
* pBindings
,
139 SfxChildWinInfo
* pInfo
)
140 : SfxChildWindow( pParentWnd
, nId
)
142 uno::Reference
< lang::XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
143 const rtl::OUString
aDockWindowResourceURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/dockingwindow/" ));
145 SfxTitleDockingWindow
* pTitleDockWindow
= new SfxTitleDockingWindow( pBindings
, this, pParentWnd
,
146 WB_STDDOCKWIN
| WB_CLIPCHILDREN
| WB_SIZEABLE
| WB_3DLOOK
| WB_ROLLABLE
, nId
);
147 pWindow
= pTitleDockWindow
;
148 eChildAlignment
= SFX_ALIGN_NOALIGNMENT
;
150 // Use factory manager to retrieve XWindow factory. That can be used to instanciate
151 // the real window factory.
152 uno::Reference
< lang::XSingleComponentFactory
> xFactoryMgr(
153 xServiceManager
->createInstance(
154 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
155 "com.sun.star.ui.WindowContentFactoryManager"))),
158 if (xFactoryMgr
.is())
160 SfxDispatcher
* pDispatcher
= pBindings
->GetDispatcher();
161 uno::Reference
< frame::XFrame
> xFrame( pDispatcher
->GetFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY
);
162 uno::Sequence
< uno::Any
> aArgs(2);
163 beans::PropertyValue aPropValue
;
164 aPropValue
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
165 aPropValue
.Value
= uno::makeAny( xFrame
);
166 aArgs
[0] <<= aPropValue
;
167 aPropValue
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ));
169 // create a resource URL from the nId provided by the sfx2
170 ::rtl::OUString
aResourceURL( aDockWindowResourceURL
);
171 aResourceURL
+= ::rtl::OUString::valueOf(sal_Int32(nId
));
172 aPropValue
.Value
= uno::makeAny( aResourceURL
);
173 aArgs
[1] <<= aPropValue
;
175 uno::Reference
< awt::XWindow
> xWindow
;
178 uno::Reference
< beans::XPropertySet
> xProps( xServiceManager
, uno::UNO_QUERY
);
179 uno::Reference
< uno::XComponentContext
> xContext
;
182 xProps
->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext
;
185 xWindow
= uno::Reference
< awt::XWindow
>(
186 xFactoryMgr
->createInstanceWithArgumentsAndContext( aArgs
, xContext
),
190 static uno::WeakReference
< frame::XModuleManager
> m_xModuleManager
;
192 uno::Reference
< frame::XModuleManager
> xModuleManager( m_xModuleManager
);
193 if ( !xModuleManager
.is() )
195 xModuleManager
= uno::Reference
< frame::XModuleManager
>(
196 xServiceManager
->createInstance(
197 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ))),
199 m_xModuleManager
= xModuleManager
;
202 static uno::WeakReference
< container::XNameAccess
> m_xWindowStateConfiguration
;
204 uno::Reference
< container::XNameAccess
> xWindowStateConfiguration( m_xWindowStateConfiguration
);
205 if ( !xWindowStateConfiguration
.is() )
207 xWindowStateConfiguration
= uno::Reference
< container::XNameAccess
>(
208 xServiceManager
->createInstance(
209 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.WindowStateConfiguration" ))),
211 m_xWindowStateConfiguration
= xWindowStateConfiguration
;
214 ::rtl::OUString sModuleIdentifier
= xModuleManager
->identify( xFrame
);
216 uno::Reference
< container::XNameAccess
> xModuleWindowState(
217 xWindowStateConfiguration
->getByName( sModuleIdentifier
),
219 if ( xModuleWindowState
.is() )
221 WindowState aDockWinState
;
222 if ( lcl_getWindowState( xModuleWindowState
, aResourceURL
, aDockWinState
))
223 pTitleDockWindow
->SetText( aDockWinState
.sTitle
);
226 catch ( beans::UnknownPropertyException
& )
229 catch ( uno::RuntimeException
& )
232 catch ( uno::Exception
& )
236 Window
* pContentWindow
= VCLUnoHelper::GetWindow(xWindow
);
237 if ( pContentWindow
)
238 pContentWindow
->SetStyle( pContentWindow
->GetStyle() | WB_DIALOGCONTROL
| WB_CHILDDLGCTRL
);
239 pTitleDockWindow
->SetWrappedWindow(pContentWindow
);
242 pWindow
->SetOutputSizePixel( Size( 270, 240 ) );
244 ( ( SfxDockingWindow
* ) pWindow
)->Initialize( pInfo
);
245 SetHideNotDelete( sal_True
);
248 SfxChildWindow
* SfxDockingWrapper::CreateImpl(
249 Window
*pParent
, sal_uInt16 nId
, SfxBindings
*pBindings
, SfxChildWinInfo
* pInfo
)
251 SfxChildWindow
*pWin
= new SfxDockingWrapper(pParent
, nId
, pBindings
, pInfo
);
255 sal_uInt16
SfxDockingWrapper::GetChildWindowId ()
257 DBG_ASSERT( false, "This method shouldn't be called!" );
261 void SfxDockingWrapper::RegisterChildWindow (sal_Bool bVis
, SfxModule
*pMod
, sal_uInt16 nFlags
)
263 // pre-register a couple of docking windows
264 for (int i
=0; i
< NUM_OF_DOCKINGWINDOWS
; i
++ )
266 sal_uInt16 nID
= sal_uInt16(SID_DOCKWIN_START
+i
);
267 SfxChildWinFactory
*pFact
= new SfxChildWinFactory( SfxDockingWrapper::CreateImpl
, nID
, 0xffff );
268 pFact
->aInfo
.nFlags
|= nFlags
;
269 pFact
->aInfo
.bVisible
= bVis
;
270 SfxChildWindow::RegisterChildWindow(pMod
, pFact
);
274 SfxChildWinInfo
SfxDockingWrapper::GetInfo() const
276 SfxChildWinInfo aInfo
= SfxChildWindow::GetInfo();
277 ((SfxDockingWindow
*)GetWindow())->FillInfo( aInfo
);
281 SfxTitleDockingWindow::SfxTitleDockingWindow( SfxBindings
* pBind
,
282 SfxChildWindow
* pChildWin
,
286 SfxDockingWindow( pBind
,
295 SfxTitleDockingWindow::~SfxTitleDockingWindow()
297 delete m_pWrappedWindow
;
300 void SfxTitleDockingWindow::SetWrappedWindow( Window
* const pWindow
)
302 m_pWrappedWindow
= pWindow
;
303 if (m_pWrappedWindow
)
305 m_pWrappedWindow
->SetParent(this);
306 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
307 m_pWrappedWindow
->Show();
311 long SfxTitleDockingWindow::Notify( NotifyEvent
& rNEvt
)
313 return SfxDockingWindow::Notify( rNEvt
);
316 void SfxTitleDockingWindow::StateChanged( StateChangedType nType
)
318 if ( nType
== STATE_CHANGE_INITSHOW
)
320 Window
* pWindow
= GetWrappedWindow();
323 pWindow
->SetSizePixel( GetOutputSizePixel() );
328 SfxDockingWindow::StateChanged(nType
);
331 void SfxTitleDockingWindow::Resize()
333 SfxDockingWindow::Resize();
334 if (m_pWrappedWindow
)
335 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
338 void SfxTitleDockingWindow::Resizing( Size
&rSize
)
340 SfxDockingWindow::Resizing( rSize
);
341 if (m_pWrappedWindow
)
342 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
345 sal_Bool
SfxTitleDockingWindow::Close()
347 return SfxDockingWindow::Close();
352 struct ChildrenRegisteredMap
: public rtl::Static
< bool, ChildrenRegisteredMap
> {};
355 static bool lcl_checkDockingWindowID( sal_uInt16 nID
)
357 if (nID
< SID_DOCKWIN_START
|| nID
>= sal_uInt16(SID_DOCKWIN_START
+NUM_OF_DOCKINGWINDOWS
))
363 static SfxWorkWindow
* lcl_getWorkWindowFromXFrame( const uno::Reference
< frame::XFrame
>& rFrame
)
365 // We need to find the corresponding SfxFrame of our XFrame
366 SfxFrame
* pFrame
= SfxFrame::GetFirst();
367 SfxFrame
* pXFrame
= 0;
370 uno::Reference
< frame::XFrame
> xViewShellFrame( pFrame
->GetFrameInterface() );
371 if ( xViewShellFrame
== rFrame
)
377 pFrame
= SfxFrame::GetNext( *pFrame
);
380 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
382 return pXFrame
->GetWorkWindow_Impl();
388 Factory function used by the framework layout manager to "create" a docking window with a special name.
389 The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
390 in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
392 void SAL_CALL
SfxDockingWindowFactory( const uno::Reference
< frame::XFrame
>& rFrame
, const rtl::OUString
& rDockingWindowName
)
394 SolarMutexGuard aGuard
;
395 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
397 // Check the range of the provided ID otherwise nothing will happen
398 if ( lcl_checkDockingWindowID( nID
))
400 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
403 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
406 // Register window at the workwindow child window list
407 pWorkWindow
->SetChildWindow_Impl( nID
, true, false );
414 Function used by the framework layout manager to determine the visibility state of a docking window with
415 a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
416 range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
418 bool SAL_CALL
IsDockingWindowVisible( const uno::Reference
< frame::XFrame
>& rFrame
, const rtl::OUString
& rDockingWindowName
)
420 SolarMutexGuard aGuard
;
422 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
424 // Check the range of the provided ID otherwise nothing will happen
425 if ( lcl_checkDockingWindowID( nID
))
427 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
430 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
439 class SfxDockingWindow_Impl
441 friend class SfxDockingWindow
;
443 SfxChildAlignment eLastAlignment
;
444 SfxChildAlignment eDockAlignment
;
445 sal_Bool bConstructed
;
447 SfxSplitWindow
* pSplitWin
;
451 // The following members are only valid in the time from startDocking to
455 long nHorizontalSize
;
459 sal_uInt16 nDockLine
;
462 sal_Bool bDockingPrevented
;
463 rtl::OString aWinState
;
465 SfxChildAlignment
GetLastAlignment() const
466 { return eLastAlignment
; }
467 void SetLastAlignment(SfxChildAlignment eAlign
)
468 { eLastAlignment
= eAlign
; }
469 SfxChildAlignment
GetDockAlignment() const
470 { return eDockAlignment
; }
471 void SetDockAlignment(SfxChildAlignment eAlign
)
472 { eDockAlignment
= eAlign
; }
475 //-------------------------------------------------------------------------
477 void SfxDockingWindow::Resize()
481 This virtual method of the class FloatingWindow keeps track of changes in
482 FloatingSize. If this method is overridden by a derived class,
483 then the SfxFloatingWindow: Resize() must also be called.
486 DockingWindow::Resize();
488 if ( pImp
->bConstructed
&& pMgr
)
490 if ( IsFloatingMode() )
492 // start timer for saving window status information
493 pImp
->aMoveTimer
.Start();
497 Size
aSize( GetSizePixel() );
498 switch ( pImp
->GetDockAlignment() )
501 case SFX_ALIGN_FIRSTLEFT
:
502 case SFX_ALIGN_LASTLEFT
:
503 case SFX_ALIGN_RIGHT
:
504 case SFX_ALIGN_FIRSTRIGHT
:
505 case SFX_ALIGN_LASTRIGHT
:
506 pImp
->nHorizontalSize
= aSize
.Width();
507 pImp
->aSplitSize
= aSize
;
510 case SFX_ALIGN_LOWESTTOP
:
511 case SFX_ALIGN_HIGHESTTOP
:
512 case SFX_ALIGN_BOTTOM
:
513 case SFX_ALIGN_HIGHESTBOTTOM
:
514 case SFX_ALIGN_LOWESTBOTTOM
:
515 pImp
->nVerticalSize
= aSize
.Height();
516 pImp
->aSplitSize
= aSize
;
525 //-------------------------------------------------------------------------
527 sal_Bool
SfxDockingWindow::PrepareToggleFloatingMode()
531 This virtual method of the class DockingWindow makes it possible to
532 intervene in the switching of the floating mode.
533 If this method is overridden by a derived class,
534 then the SfxDockingWindow::PrepareToggleFloatingMode() must be called
535 afterwards, if not FALSE is returned.
539 if (!pImp
->bConstructed
)
542 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr
)
545 if ( pImp
->bDockingPrevented
)
548 if (!IsFloatingMode())
550 // Test, if FloatingMode is permitted.
551 if ( CheckAlignment(GetAlignment(),SFX_ALIGN_NOALIGNMENT
) != SFX_ALIGN_NOALIGNMENT
)
554 if ( pImp
->pSplitWin
)
556 // The DockingWindow is inside a SplitWindow and will be teared of.
557 pImp
->pSplitWin
->RemoveWindow(this/*, sal_False*/);
563 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
565 // Test if it is allowed to dock,
566 if (CheckAlignment(GetAlignment(),pImp
->GetLastAlignment()) == SFX_ALIGN_NOALIGNMENT
)
569 // Test, if the Workwindow allows for docking at the moment.
570 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
571 if ( !pWorkWin
->IsDockingAllowed() || !pWorkWin
->IsInternalDockingAllowed() )
578 //-------------------------------------------------------------------------
580 void SfxDockingWindow::ToggleFloatingMode()
584 This virtual method of the DockingWindow class sets the internal data of
585 the SfxDockingWindow and ensures the correct alignment on the parent window.
586 Through PrepareToggleFloatMode and Initialize it is ensured that
587 pImp-> GetLastAlignment() always delivers an allowed alignment. If this
588 method is overloaded from a derived class, then first the
589 SfxDockingWindow:: ToggleFloatingMode() must be called.
592 if ( !pImp
->bConstructed
|| !pMgr
)
593 return; // No Handler call
595 // Remember old alignment and then switch.
596 // SV has already switched, but the alignment SfxDockingWindow is still
597 // the old one. What I was before?
598 SfxChildAlignment eLastAlign
= GetAlignment();
600 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
601 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
602 if ( pImp
->bSplitable
)
603 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
605 if (IsFloatingMode())
607 SetAlignment(SFX_ALIGN_NOALIGNMENT
);
608 if ( !pImp
->aWinState
.isEmpty() )
609 GetFloatingWindow()->SetWindowState( pImp
->aWinState
);
611 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
615 if (pImp
->GetDockAlignment() == eLastAlign
)
617 // If ToggleFloatingMode was called, but the DockAlignment still
618 // is unchanged, then this means that it must have been a toggling
619 // through DClick, so use last alignment
620 SetAlignment (pImp
->GetLastAlignment());
621 if ( !pImp
->bSplitable
)
622 SetSizePixel( CalcDockingSize(GetAlignment()) );
627 // Toggling was triggered by dragging
628 pImp
->nLine
= pImp
->nDockLine
;
629 pImp
->nPos
= pImp
->nDockPos
;
630 SetAlignment (pImp
->GetDockAlignment());
633 if ( pImp
->bSplitable
)
635 // The DockingWindow is now in a SplitWindow
636 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
638 // The LastAlignment is still the last docked
639 SfxSplitWindow
*pSplit
= pWorkWin
->GetSplitWindow_Impl(pImp
->GetLastAlignment());
641 DBG_ASSERT( pSplit
, "LastAlignment is not correct!" );
642 if ( pSplit
&& pSplit
!= pImp
->pSplitWin
)
643 pSplit
->ReleaseWindow_Impl(this);
644 if ( pImp
->GetDockAlignment() == eLastAlign
)
645 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
);
647 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
, pImp
->nLine
, pImp
->nPos
, pImp
->bNewLine
);
648 if ( !pImp
->pSplitWin
->IsFadeIn() )
649 pImp
->pSplitWin
->FadeIn();
653 // Keep the old alignment for the next toggle; set it only now due to the
654 // unregister SplitWindow!
655 pImp
->SetLastAlignment(eLastAlign
);
657 // Reset DockAlignment, if EndDocking is still called
658 pImp
->SetDockAlignment(GetAlignment());
660 // Dock or undock SfxChildWindow correctly.
662 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_TOGGLEFLOATMODE
, pMgr
->GetType() );
665 //-------------------------------------------------------------------------
667 void SfxDockingWindow::StartDocking()
671 This virtual method of the DockingWindow class takes the inner and outer
672 docking rectangle from the parent window. If this method is overloaded by a
673 a derived class, then SfxDockingWindow:StartDocking() has to be called at
677 if ( !pImp
->bConstructed
|| !pMgr
)
679 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
680 if ( pImp
->bSplitable
)
681 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
682 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
683 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_SETDOCKINGRECTS
, pMgr
->GetType() );
684 pImp
->SetDockAlignment(GetAlignment());
686 if ( pImp
->pSplitWin
)
688 // Get the current docking data
689 pImp
->pSplitWin
->GetWindowPos(this, pImp
->nLine
, pImp
->nPos
);
690 pImp
->nDockLine
= pImp
->nLine
;
691 pImp
->nDockPos
= pImp
->nPos
;
692 pImp
->bNewLine
= sal_False
;
696 //-------------------------------------------------------------------------
698 sal_Bool
SfxDockingWindow::Docking( const Point
& rPos
, Rectangle
& rRect
)
702 This virtual method of the DockingWindow class calculates the current
703 tracking rectangle. For this purpose the method CalcAlignment(RPOs, rRect)
704 is used, the behavior can be influenced by the derived classes (see below).
705 This method should if possible not be overwritten.
708 if ( Application::IsInModalMode() )
711 if ( !pImp
->bConstructed
|| !pMgr
)
713 rRect
.SetSize( Size() );
714 return IsFloatingMode();
717 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
718 if ( pImp
->bDockingPrevented
|| !pWorkWin
->IsInternalDockingAllowed() )
721 sal_Bool bFloatMode
= sal_False
;
723 if ( GetOuterRect().IsInside( rPos
) && !IsDockingPrevented() )
725 // Mouse within OuterRect: calculate Alignment and Rectangle
726 SfxChildAlignment eAlign
= CalcAlignment(rPos
, rRect
);
727 if (eAlign
== SFX_ALIGN_NOALIGNMENT
)
728 bFloatMode
= sal_True
;
729 pImp
->SetDockAlignment(eAlign
);
733 // Mouse is not within OuterRect: must be FloatingWindow
735 if (CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
) != SFX_ALIGN_NOALIGNMENT
)
737 bFloatMode
= sal_True
;
738 if ( SFX_ALIGN_NOALIGNMENT
!= pImp
->GetDockAlignment() )
740 // Due to a bug the rRect may only be changed when the
741 // alignment is changed!
742 pImp
->SetDockAlignment(SFX_ALIGN_NOALIGNMENT
);
743 rRect
.SetSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT
));
747 if ( !pImp
->bSplitable
)
749 // For individually docked window the position is set through the
750 // alignment and the docking rectangle.
751 Size aSize
= rRect
.GetSize();
754 switch ( pImp
->GetDockAlignment() )
757 case SFX_ALIGN_FIRSTLEFT
:
758 case SFX_ALIGN_LASTLEFT
:
759 aPos
= aInnerRect
.TopLeft();
760 if ( pImp
->GetDockAlignment() == GetAlignment() )
761 aPos
.X() -= aSize
.Width();
765 case SFX_ALIGN_LOWESTTOP
:
766 case SFX_ALIGN_HIGHESTTOP
:
767 aPos
= Point(aOuterRect
.Left(), aInnerRect
.Top());
768 if ( pImp
->GetDockAlignment() == GetAlignment() )
769 aPos
.Y() -= aSize
.Height();
772 case SFX_ALIGN_RIGHT
:
773 case SFX_ALIGN_FIRSTRIGHT
:
774 case SFX_ALIGN_LASTRIGHT
:
775 aPos
= Point(aInnerRect
.Right() - rRect
.GetSize().Width(),
777 if ( pImp
->GetDockAlignment() == GetAlignment() )
778 aPos
.X() += aSize
.Width();
781 case SFX_ALIGN_BOTTOM
:
782 case SFX_ALIGN_HIGHESTBOTTOM
:
783 case SFX_ALIGN_LOWESTBOTTOM
:
784 aPos
= Point(aOuterRect
.Left(),
785 aInnerRect
.Bottom() - rRect
.GetSize().Height());
786 if ( pImp
->GetDockAlignment() == GetAlignment() )
787 aPos
.Y() += aSize
.Height();
799 //-------------------------------------------------------------------------
801 void SfxDockingWindow::EndDocking( const Rectangle
& rRect
, sal_Bool bFloatMode
)
805 Virtual method of the DockingWindow class ensures the correct alignment on
806 the parent window. If this method is overloaded by a derived class, then
807 SfxDockingWindow::EndDocking() must be called first.
810 if ( !pImp
->bConstructed
|| IsDockingCanceled() || !pMgr
)
813 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
814 sal_Bool bReArrange
= sal_False
;
815 if ( pImp
->bSplitable
)
817 // If the alignment changes and the window is in a docked state in a
818 // SplitWindow, then it must be re-registered. If it is docked again,
819 // PrepareToggleFloatingMode() and ToggleFloatingMode() preform the
822 bReArrange
= sal_True
;
827 if ( GetAlignment() != pImp
->GetDockAlignment() )
829 // before Show() is called must the reassignment have been made,
830 // therefore the base class can not be called
831 if ( IsFloatingMode() || !pImp
->bSplitable
)
832 Show( sal_False
, SHOW_NOFOCUSCHANGE
);
834 // Set the size for toggling.
835 pImp
->aSplitSize
= rRect
.GetSize();
836 if ( IsFloatingMode() )
838 SetFloatingMode( bFloatMode
);
839 if ( IsFloatingMode() || !pImp
->bSplitable
)
840 Show( sal_True
, SHOW_NOFOCUSCHANGE
);
844 pImp
->pSplitWin
->RemoveWindow(this,sal_False
);
845 pImp
->nLine
= pImp
->nDockLine
;
846 pImp
->nPos
= pImp
->nDockPos
;
847 pImp
->pSplitWin
->ReleaseWindow_Impl(this);
848 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(pImp
->GetDockAlignment());
849 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
, pImp
->nDockLine
, pImp
->nDockPos
, pImp
->bNewLine
);
850 if ( !pImp
->pSplitWin
->IsFadeIn() )
851 pImp
->pSplitWin
->FadeIn();
854 else if ( pImp
->nLine
!= pImp
->nDockLine
|| pImp
->nPos
!= pImp
->nDockPos
|| pImp
->bNewLine
)
856 // Moved within Splitwindows
857 if ( pImp
->nLine
!= pImp
->nDockLine
)
858 pImp
->aSplitSize
= rRect
.GetSize();
859 pImp
->pSplitWin
->MoveWindow( this, pImp
->aSplitSize
, pImp
->nDockLine
, pImp
->nDockPos
, pImp
->bNewLine
);
864 pImp
->bEndDocked
= sal_True
;
865 DockingWindow::EndDocking(rRect
, bFloatMode
);
866 pImp
->bEndDocked
= sal_False
;
869 SetAlignment( IsFloatingMode() ? SFX_ALIGN_NOALIGNMENT
: pImp
->GetDockAlignment() );
872 //-------------------------------------------------------------------------
874 void SfxDockingWindow::Resizing( Size
& /*rSize*/ )
878 Virtual method of the DockingWindow class. Here, the interactive resize in
879 FloatingMode can be influenced, for example by only allowing for discrete
880 values for width and / or height. The base implementation prevents that the
881 output size is smaller than one set with SetMinOutputSizePixel().
888 //-------------------------------------------------------------------------
890 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
891 Window
* pParent
, WinBits nWinBits
) :
892 DockingWindow (pParent
, nWinBits
),
899 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
900 required because the docking is implemented in Sfx through SfxChildWindows.
904 if ( !GetHelpId().isEmpty() )
906 SetUniqueId( GetHelpId() );
911 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher()->GetFrame();
912 SfxSlotPool
* pSlotPool
= pViewFrame
->GetObjectShell()->GetModule()->GetSlotPool();
913 const SfxSlot
* pSlot
= pSlotPool
->GetSlot( pCW
->GetType() );
916 rtl::OString
aCmd("SFXDOCKINGWINDOW_");
917 aCmd
+= pSlot
->GetUnoName();
922 pImp
= new SfxDockingWindow_Impl
;
923 pImp
->bConstructed
= sal_False
;
925 pImp
->bEndDocked
= sal_False
;
926 pImp
->bDockingPrevented
= sal_False
;
928 pImp
->bSplitable
= sal_True
;
930 // Initially set to default, the alignment is set in the subclass
931 pImp
->nLine
= pImp
->nDockLine
= 0;
932 pImp
->nPos
= pImp
->nDockPos
= 0;
933 pImp
->bNewLine
= sal_False
;
934 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
935 pImp
->aMoveTimer
.SetTimeout(50);
936 pImp
->aMoveTimer
.SetTimeoutHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
939 //-------------------------------------------------------------------------
941 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
942 Window
* pParent
, const ResId
& rResId
) :
943 DockingWindow(pParent
, rResId
),
950 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
951 required because the docking is implemented in Sfx through SfxChildWindows.
955 if ( !GetHelpId().isEmpty() )
957 SetUniqueId( GetHelpId() );
962 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher()->GetFrame();
963 SfxSlotPool
* pSlotPool
= pViewFrame
->GetObjectShell()->GetModule()->GetSlotPool();
964 const SfxSlot
* pSlot
= pSlotPool
->GetSlot( pCW
->GetType() );
967 rtl::OString
aCmd("SFXDOCKINGWINDOW_");
968 aCmd
+= pSlot
->GetUnoName();
973 pImp
= new SfxDockingWindow_Impl
;
974 pImp
->bConstructed
= sal_False
;
976 pImp
->bEndDocked
= sal_False
;
977 pImp
->bDockingPrevented
= sal_False
;
979 pImp
->bSplitable
= sal_True
;
981 // Initially set to default, the alignment is set in the subclass
982 pImp
->nLine
= pImp
->nDockLine
= 0;
983 pImp
->nPos
= pImp
->nDockPos
= 0;
984 pImp
->bNewLine
= sal_False
;
985 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
986 pImp
->aMoveTimer
.SetTimeout(50);
987 pImp
->aMoveTimer
.SetTimeoutHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
990 //-------------------------------------------------------------------------
992 void SfxDockingWindow::Initialize(SfxChildWinInfo
*pInfo
)
995 Initialization of the SfxDockingDialog class via a SfxChildWinInfo.
996 The initialization is done only in a 2nd step after the constructor, this
997 constructor should be called from the derived class or from the
1003 pImp
->SetDockAlignment( SFX_ALIGN_NOALIGNMENT
);
1004 pImp
->bConstructed
= sal_True
;
1008 if ( pInfo
->nFlags
& SFX_CHILDWIN_FORCEDOCK
)
1009 pImp
->bDockingPrevented
= sal_True
;
1011 pImp
->aSplitSize
= GetOutputSizePixel();
1012 if ( !GetFloatingSize().Width() )
1014 Size
aMinSize( GetMinOutputSizePixel() );
1015 SetFloatingSize( pImp
->aSplitSize
);
1016 if ( pImp
->aSplitSize
.Width() < aMinSize
.Width() )
1017 pImp
->aSplitSize
.Width() = aMinSize
.Width();
1018 if ( pImp
->aSplitSize
.Height() < aMinSize
.Height() )
1019 pImp
->aSplitSize
.Height() = aMinSize
.Height();
1022 sal_Bool
bVertHorzRead( sal_False
);
1023 if ( pInfo
->aExtraString
.Len() )
1025 // get information about alignment, split size and position in SplitWindow
1027 sal_uInt16 nPos
= pInfo
->aExtraString
.SearchAscii("AL:");
1028 if ( nPos
!= STRING_NOTFOUND
)
1030 // alignment information
1031 sal_uInt16 n1
= pInfo
->aExtraString
.Search('(', nPos
);
1032 if ( n1
!= STRING_NOTFOUND
)
1034 sal_uInt16 n2
= pInfo
->aExtraString
.Search(')', n1
);
1035 if ( n2
!= STRING_NOTFOUND
)
1037 // extract alignment information from extrastring
1038 aStr
= pInfo
->aExtraString
.Copy(nPos
, n2
- nPos
+ 1);
1039 pInfo
->aExtraString
.Erase(nPos
, n2
- nPos
+ 1);
1040 aStr
.Erase(nPos
, n1
-nPos
+1);
1047 // accept window state only if alignment is also set
1048 pImp
->aWinState
= pInfo
->aWinState
;
1050 // check for valid alignment
1051 SfxChildAlignment eLocalAlignment
= (SfxChildAlignment
) (sal_uInt16
) aStr
.ToInt32();
1052 if ( pImp
->bDockingPrevented
)
1053 // docking prevented, ignore old configuration and take alignment from default
1056 SetAlignment( eLocalAlignment
);
1058 SfxChildAlignment eAlign
= CheckAlignment(GetAlignment(),GetAlignment());
1059 if ( eAlign
!= GetAlignment() )
1061 OSL_FAIL("Invalid Alignment!");
1062 SetAlignment( eAlign
);
1066 // get last alignment (for toggeling)
1067 nPos
= aStr
.Search(',');
1068 if ( nPos
!= STRING_NOTFOUND
)
1070 aStr
.Erase(0, nPos
+1);
1071 pImp
->SetLastAlignment( (SfxChildAlignment
) (sal_uInt16
) aStr
.ToInt32() );
1074 nPos
= aStr
.Search(',');
1075 if ( nPos
!= STRING_NOTFOUND
)
1077 // get split size and position in SplitWindow
1079 aStr
.Erase(0, nPos
+1);
1080 if ( GetPosSizeFromString( aStr
, aPos
, pImp
->aSplitSize
) )
1082 pImp
->nLine
= pImp
->nDockLine
= (sal_uInt16
) aPos
.X();
1083 pImp
->nPos
= pImp
->nDockPos
= (sal_uInt16
) aPos
.Y();
1084 pImp
->nVerticalSize
= pImp
->aSplitSize
.Height();
1085 pImp
->nHorizontalSize
= pImp
->aSplitSize
.Width();
1086 if ( GetSplitSizeFromString( aStr
, pImp
->aSplitSize
))
1087 bVertHorzRead
= sal_True
;
1092 OSL_FAIL( "Information is missing!" );
1096 if ( !bVertHorzRead
)
1098 pImp
->nVerticalSize
= pImp
->aSplitSize
.Height();
1099 pImp
->nHorizontalSize
= pImp
->aSplitSize
.Width();
1102 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1103 if ( GetAlignment() != SFX_ALIGN_NOALIGNMENT
)
1105 // check if SfxWorkWindow is able to allow docking at its border
1107 !pWorkWin
->IsDockingAllowed() ||
1108 !pWorkWin
->IsInternalDockingAllowed() ||
1109 ( (GetFloatStyle() & WB_STANDALONE
) && Application::IsInModalMode()) )
1111 SetAlignment( SFX_ALIGN_NOALIGNMENT
);
1115 // detect floating mode
1116 // toggeling mode will not execute code in handlers, because pImp->bConstructed is not set yet
1117 sal_Bool bFloatMode
= IsFloatingMode();
1118 if ( bFloatMode
!= ((GetAlignment() == SFX_ALIGN_NOALIGNMENT
)) )
1120 bFloatMode
= !bFloatMode
;
1121 SetFloatingMode( bFloatMode
);
1124 if ( !pImp
->aWinState
.isEmpty() )
1125 GetFloatingWindow()->SetWindowState( pImp
->aWinState
);
1127 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
1131 if ( IsFloatingMode() )
1133 // validate last alignment
1134 SfxChildAlignment eLastAlign
= pImp
->GetLastAlignment();
1135 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1136 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_LEFT
);
1137 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1138 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_RIGHT
);
1139 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1140 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_TOP
);
1141 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1142 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_BOTTOM
);
1143 pImp
->SetLastAlignment(eLastAlign
);
1147 // docked window must have NOALIGNMENT as last alignment
1148 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
1150 if ( pImp
->bSplitable
)
1152 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
1153 pImp
->pSplitWin
->InsertWindow(this, pImp
->aSplitSize
);
1157 //?????? Currently not supported
1158 // Window is docked individually; size is calculated.
1159 // It must therefore be initialized with the DloatingSize if
1160 // someone relies on it that a reasonable size is set
1161 SetSizePixel(GetFloatingSize());
1162 SetSizePixel(CalcDockingSize(GetAlignment()));
1167 pImp
->SetDockAlignment( GetAlignment() );
1170 void SfxDockingWindow::Initialize_Impl()
1174 pImp
->bConstructed
= sal_True
;
1178 FloatingWindow
* pFloatWin
= GetFloatingWindow();
1179 sal_Bool bSet
= sal_False
;
1182 bSet
= !pFloatWin
->IsDefaultPos();
1186 Point aPos
= GetFloatingPos();
1187 if ( aPos
!= Point() )
1193 SfxViewFrame
*pFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
1194 Window
* pEditWin
= pFrame
->GetViewShell()->GetWindow();
1195 Point aPos
= pEditWin
->OutputToScreenPixel( pEditWin
->GetPosPixel() );
1196 aPos
= GetParent()->ScreenToOutputPixel( aPos
);
1197 SetFloatingPos( aPos
);
1202 // initialize floating window
1203 if ( pImp
->aWinState
.isEmpty() )
1204 // window state never set before, get if from defaults
1205 pImp
->aWinState
= pFloatWin
->GetWindowState();
1207 // trick: use VCL method SetWindowState to adjust position and size
1208 pFloatWin
->SetWindowState( pImp
->aWinState
);
1210 // remember floating size for calculating alignment and tracking rectangle
1211 SetFloatingSize( pFloatWin
->GetSizePixel() );
1215 // allow calling of docking handlers
1216 pImp
->bConstructed
= sal_True
;
1219 //-------------------------------------------------------------------------
1221 void SfxDockingWindow::FillInfo(SfxChildWinInfo
& rInfo
) const
1225 Fills a SfxChildWinInfo with specific data from SfxDockingWindow,
1226 so that it can be written in the INI file. It is assumed that rinfo
1227 receives all other possible relevant data in the ChildWindow class.
1228 Insertions are marked with size and the ZoomIn flag.
1229 If this method is overridden, the base implementation must be called first.
1236 if ( GetFloatingWindow() && pImp
->bConstructed
)
1237 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
1239 rInfo
.aWinState
= pImp
->aWinState
;
1240 rInfo
.aExtraString
= DEFINE_CONST_UNICODE("AL:(");
1241 rInfo
.aExtraString
+= String::CreateFromInt32((sal_uInt16
) GetAlignment());
1242 rInfo
.aExtraString
+= ',';
1243 rInfo
.aExtraString
+= String::CreateFromInt32 ((sal_uInt16
) pImp
->GetLastAlignment());
1244 if ( pImp
->bSplitable
)
1246 Point
aPos(pImp
->nLine
, pImp
->nPos
);
1247 rInfo
.aExtraString
+= ',';
1248 rInfo
.aExtraString
+= String::CreateFromInt32( aPos
.X() );
1249 rInfo
.aExtraString
+= '/';
1250 rInfo
.aExtraString
+= String::CreateFromInt32( aPos
.Y() );
1251 rInfo
.aExtraString
+= '/';
1252 rInfo
.aExtraString
+= String::CreateFromInt32( pImp
->nHorizontalSize
);
1253 rInfo
.aExtraString
+= '/';
1254 rInfo
.aExtraString
+= String::CreateFromInt32( pImp
->nVerticalSize
);
1255 rInfo
.aExtraString
+= ',';
1256 rInfo
.aExtraString
+= String::CreateFromInt32( pImp
->aSplitSize
.Width() );
1257 rInfo
.aExtraString
+= ';';
1258 rInfo
.aExtraString
+= String::CreateFromInt32( pImp
->aSplitSize
.Height() );
1261 rInfo
.aExtraString
+= ')';
1264 //-------------------------------------------------------------------------
1266 SfxDockingWindow::~SfxDockingWindow()
1268 ReleaseChildWindow_Impl();
1272 void SfxDockingWindow::ReleaseChildWindow_Impl()
1274 if ( pMgr
&& pMgr
->GetFrame() == pBindings
->GetActiveFrame() )
1275 pBindings
->SetActiveFrame( NULL
);
1277 if ( pMgr
&& pImp
->pSplitWin
&& pImp
->pSplitWin
->IsItemValid( GetType() ) )
1278 pImp
->pSplitWin
->RemoveWindow(this);
1283 //-------------------------------------------------------------------------
1285 SfxChildAlignment
SfxDockingWindow::CalcAlignment(const Point
& rPos
, Rectangle
& rRect
)
1289 This method calculates a resulting alignment for the given mouse position
1290 and tracking rectangle. When changing the alignment it can also be that
1291 the tracking rectangle is changed, so that an altered rectangle is
1292 returned. The user of this class can influence behaviour of this method,
1293 and thus the behavior of his DockinWindow class when docking where the
1294 called virtual method:
1296 SfxDockingWindow :: CalcDockingSize (SfxChildAlignment eAlign)
1298 is overridden (see below).
1302 // calculate hypothetical sizes for different modes
1303 Size
aFloatingSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT
));
1304 Size
aVerticalSize(CalcDockingSize(SFX_ALIGN_LEFT
));
1305 Size
aHorizontalSize(CalcDockingSize(SFX_ALIGN_TOP
));
1307 // check if docking is permitted
1308 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1309 if ( !pWorkWin
->IsDockingAllowed() )
1311 rRect
.SetSize( aFloatingSize
);
1312 return pImp
->GetDockAlignment();
1315 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1316 long nLRBorder
, nTBBorder
;
1317 if ( pImp
->bSplitable
)
1319 // take the smaller size of docked and floating mode
1320 Size aSize
= pImp
->aSplitSize
;
1321 if ( GetFloatingSize().Height() < aSize
.Height() )
1322 aSize
.Height() = GetFloatingSize().Height();
1323 if ( GetFloatingSize().Width() < aSize
.Width() )
1324 aSize
.Width() = GetFloatingSize().Width();
1326 nLRBorder
= aSize
.Width();
1327 nTBBorder
= aSize
.Height();
1331 nLRBorder
= aVerticalSize
.Width();
1332 nTBBorder
= aHorizontalSize
.Height();
1335 // limit border to predefined constant values
1336 if ( nLRBorder
> MAX_TOGGLEAREA_WIDTH
)
1337 nLRBorder
= MAX_TOGGLEAREA_WIDTH
;
1338 if ( nTBBorder
> MAX_TOGGLEAREA_WIDTH
)
1339 nTBBorder
= MAX_TOGGLEAREA_WIDTH
;
1341 // shrink area for floating mode if possible
1342 Rectangle aInRect
= GetInnerRect();
1343 if ( aInRect
.GetWidth() > nLRBorder
)
1344 aInRect
.Left() += nLRBorder
/2;
1345 if ( aInRect
.GetWidth() > nLRBorder
)
1346 aInRect
.Right() -= nLRBorder
/2;
1347 if ( aInRect
.GetHeight() > nTBBorder
)
1348 aInRect
.Top() += nTBBorder
/2;
1349 if ( aInRect
.GetHeight() > nTBBorder
)
1350 aInRect
.Bottom() -= nTBBorder
/2;
1352 // calculate alignment resulting from docking rectangle
1353 sal_Bool bBecomesFloating
= sal_False
;
1354 SfxChildAlignment eDockAlign
= pImp
->GetDockAlignment();
1355 Rectangle
aDockingRect( rRect
);
1356 if ( !IsFloatingMode() )
1358 // don't use tracking rectangle for alignment check, because it will be too large
1359 // to get a floating mode as result - switch to floating size
1360 // so the calculation only depends on the position of the rectangle, not the current
1361 // docking state of the window
1362 aDockingRect
.SetSize( GetFloatingSize() );
1364 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1365 aDockingRect
.SetPos( pWorkWin
->GetWindow()->OutputToScreenPixel( pWorkWin
->GetWindow()->GetPointerPosPixel() ) );
1368 Point aPos
= aDockingRect
.TopLeft();
1369 Rectangle aIntersect
= GetOuterRect().GetIntersection( aDockingRect
);
1370 if ( aIntersect
.IsEmpty() )
1371 // docking rectangle completely outside docking area -> floating mode
1372 bBecomesFloating
= sal_True
;
1375 // create a small test rect around the mouse position and use this one
1376 // instead of the passed rRect to not dock too easily or by accident
1377 Rectangle aSmallDockingRect
;
1378 aSmallDockingRect
.SetSize( Size( MAX_TOGGLEAREA_WIDTH
, MAX_TOGGLEAREA_HEIGHT
) );
1379 Point
aNewPos(rPos
);
1380 aNewPos
.X() -= aSmallDockingRect
.GetWidth()/2;
1381 aNewPos
.Y() -= aSmallDockingRect
.GetHeight()/2;
1382 aSmallDockingRect
.SetPos(rPos
);
1383 Rectangle aIntersectRect
= aInRect
.GetIntersection( aSmallDockingRect
);
1384 if ( aIntersectRect
== aSmallDockingRect
)
1385 // docking rectangle completely inside (shrinked) inner area -> floating mode
1386 bBecomesFloating
= sal_True
;
1389 if ( bBecomesFloating
)
1391 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
);
1395 // docking rectangle is in the "sensible area"
1396 Point
aInPosTL( aPos
.X()-aInRect
.Left(), aPos
.Y()-aInRect
.Top() );
1397 Point
aInPosBR( aPos
.X()-aInRect
.Left() + aDockingRect
.GetWidth(), aPos
.Y()-aInRect
.Top() + aDockingRect
.GetHeight() );
1398 Size aInSize
= aInRect
.GetSize();
1399 sal_Bool bNoChange
= sal_False
;
1401 // check if alignment is still unchanged
1402 switch ( GetAlignment() )
1404 case SFX_ALIGN_LEFT
:
1405 case SFX_ALIGN_FIRSTLEFT
:
1406 case SFX_ALIGN_LASTLEFT
:
1407 if (aInPosTL
.X() <= 0)
1409 eDockAlign
= GetAlignment();
1410 bNoChange
= sal_True
;
1414 case SFX_ALIGN_LOWESTTOP
:
1415 case SFX_ALIGN_HIGHESTTOP
:
1416 if ( aInPosTL
.Y() <= 0)
1418 eDockAlign
= GetAlignment();
1419 bNoChange
= sal_True
;
1422 case SFX_ALIGN_RIGHT
:
1423 case SFX_ALIGN_FIRSTRIGHT
:
1424 case SFX_ALIGN_LASTRIGHT
:
1425 if ( aInPosBR
.X() >= aInSize
.Width())
1427 eDockAlign
= GetAlignment();
1428 bNoChange
= sal_True
;
1431 case SFX_ALIGN_BOTTOM
:
1432 case SFX_ALIGN_LOWESTBOTTOM
:
1433 case SFX_ALIGN_HIGHESTBOTTOM
:
1434 if ( aInPosBR
.Y() >= aInSize
.Height())
1436 eDockAlign
= GetAlignment();
1437 bNoChange
= sal_True
;
1446 // alignment will change, test alignment according to distance of the docking rectangles edges
1447 sal_Bool bForbidden
= sal_True
;
1448 if ( aInPosTL
.X() <= 0)
1450 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_LEFT
);
1451 bForbidden
= ( eDockAlign
!= SFX_ALIGN_LEFT
&&
1452 eDockAlign
!= SFX_ALIGN_FIRSTLEFT
&&
1453 eDockAlign
!= SFX_ALIGN_LASTLEFT
);
1456 if ( bForbidden
&& aInPosTL
.Y() <= 0)
1458 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_TOP
);
1459 bForbidden
= ( eDockAlign
!= SFX_ALIGN_TOP
&&
1460 eDockAlign
!= SFX_ALIGN_HIGHESTTOP
&&
1461 eDockAlign
!= SFX_ALIGN_LOWESTTOP
);
1464 if ( bForbidden
&& aInPosBR
.X() >= aInSize
.Width())
1466 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_RIGHT
);
1467 bForbidden
= ( eDockAlign
!= SFX_ALIGN_RIGHT
&&
1468 eDockAlign
!= SFX_ALIGN_FIRSTRIGHT
&&
1469 eDockAlign
!= SFX_ALIGN_LASTRIGHT
);
1472 if ( bForbidden
&& aInPosBR
.Y() >= aInSize
.Height())
1474 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_BOTTOM
);
1475 bForbidden
= ( eDockAlign
!= SFX_ALIGN_BOTTOM
&&
1476 eDockAlign
!= SFX_ALIGN_HIGHESTBOTTOM
&&
1477 eDockAlign
!= SFX_ALIGN_LOWESTBOTTOM
);
1480 // the calculated alignment was rejected by the window -> take floating mode
1482 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
);
1486 if ( eDockAlign
== SFX_ALIGN_NOALIGNMENT
)
1488 // In the FloatingMode the tracking rectangle will get the floating
1489 // size. Due to a bug the rRect may only be changed when the
1490 // alignment is changed!
1491 if ( eDockAlign
!= pImp
->GetDockAlignment() )
1492 aDockingRect
.SetSize( aFloatingSize
);
1494 else if ( pImp
->bSplitable
)
1496 sal_uInt16 nLine
, nPos
;
1497 SfxSplitWindow
*pSplitWin
= pWorkWin
->GetSplitWindow_Impl(eDockAlign
);
1498 aPos
= pSplitWin
->ScreenToOutputPixel( aPos
);
1499 if ( pSplitWin
->GetWindowPos( aPos
, nLine
, nPos
) )
1501 // mouse over splitwindow, get line and position
1502 pImp
->nDockLine
= nLine
;
1503 pImp
->nDockPos
= nPos
;
1504 pImp
->bNewLine
= sal_False
;
1510 // mouse touches outer border -> treated as floating mode
1511 eDockAlign
= SFX_ALIGN_NOALIGNMENT
;
1512 aDockingRect
.SetSize( aFloatingSize
);
1513 rRect
= aDockingRect
;
1517 // mouse touches inner border -> create new line
1518 if ( eDockAlign
== GetAlignment() && pImp
->pSplitWin
&&
1519 pImp
->nLine
== pImp
->pSplitWin
->GetLineCount()-1 && pImp
->pSplitWin
->GetWindowCount(pImp
->nLine
) == 1 )
1521 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1522 pImp
->nDockLine
= pImp
->nLine
;
1523 pImp
->nDockPos
= pImp
->nPos
;
1524 pImp
->bNewLine
= sal_False
;
1529 pImp
->nDockLine
= pSplitWin
->GetLineCount();
1531 pImp
->bNewLine
= sal_True
;
1535 sal_Bool bChanged
= pImp
->nLine
!= pImp
->nDockLine
|| pImp
->nPos
!= pImp
->nDockPos
|| eDockAlign
!= GetAlignment();
1536 if ( !bChanged
&& !IsFloatingMode() )
1538 // window only sightly moved, no change of any property
1539 rRect
.SetSize( pImp
->aSplitSize
);
1540 rRect
.SetPos( aDockingRect
.TopLeft() );
1544 // calculate new size and position
1546 Point aPoint
= aDockingRect
.TopLeft();
1547 Size aInnerSize
= GetInnerRect().GetSize();
1548 if ( eDockAlign
== SFX_ALIGN_LEFT
|| eDockAlign
== SFX_ALIGN_RIGHT
)
1550 if ( pImp
->bNewLine
)
1552 // set height to height of free area
1553 aSize
.Height() = aInnerSize
.Height();
1554 aSize
.Width() = pImp
->nHorizontalSize
;
1555 if ( eDockAlign
== SFX_ALIGN_LEFT
)
1557 aPoint
= aInnerRect
.TopLeft();
1561 aPoint
= aInnerRect
.TopRight();
1562 aPoint
.X() -= aSize
.Width();
1567 // get width from splitwindow
1568 aSize
.Width() = pSplitWin
->GetLineSize(nLine
);
1569 aSize
.Height() = pImp
->aSplitSize
.Height();
1574 if ( pImp
->bNewLine
)
1576 // set width to width of free area
1577 aSize
.Width() = aInnerSize
.Width();
1578 aSize
.Height() = pImp
->nVerticalSize
;
1579 if ( eDockAlign
== SFX_ALIGN_TOP
)
1581 aPoint
= aInnerRect
.TopLeft();
1585 aPoint
= aInnerRect
.BottomLeft();
1586 aPoint
.Y() -= aSize
.Height();
1591 // get height from splitwindow
1592 aSize
.Height() = pSplitWin
->GetLineSize(nLine
);
1593 aSize
.Width() = pImp
->aSplitSize
.Width();
1597 aDockingRect
.SetSize( aSize
);
1598 aDockingRect
.SetPos( aPoint
);
1602 // window can be docked, but outside our splitwindows
1603 // tracking rectangle only needs to be modified if alignment was changed
1604 if ( eDockAlign
!= pImp
->GetDockAlignment() )
1606 switch ( eDockAlign
)
1608 case SFX_ALIGN_LEFT
:
1609 case SFX_ALIGN_RIGHT
:
1610 case SFX_ALIGN_FIRSTLEFT
:
1611 aDockingRect
.SetPos( aInnerRect
.TopLeft() );
1612 aDockingRect
.SetSize( aVerticalSize
);
1614 case SFX_ALIGN_LASTLEFT
:
1615 case SFX_ALIGN_FIRSTRIGHT
:
1616 case SFX_ALIGN_LASTRIGHT
:
1618 Point
aPt( aInnerRect
.TopRight() );
1619 aPt
.X() -= aDockingRect
.GetWidth();
1620 aDockingRect
.SetPos( aPt
);
1621 aDockingRect
.SetSize( aVerticalSize
);
1626 case SFX_ALIGN_BOTTOM
:
1627 case SFX_ALIGN_LOWESTTOP
:
1628 aDockingRect
.SetPos( aInnerRect
.TopLeft() );
1629 aDockingRect
.SetSize( aHorizontalSize
);
1631 case SFX_ALIGN_HIGHESTTOP
:
1632 case SFX_ALIGN_LOWESTBOTTOM
:
1633 case SFX_ALIGN_HIGHESTBOTTOM
:
1635 Point
aPt( aInnerRect
.BottomLeft() );
1636 aPt
.Y() -= aDockingRect
.GetHeight();
1637 aDockingRect
.SetPos( aPt
);
1638 aDockingRect
.SetSize( aHorizontalSize
);
1647 rRect
= aDockingRect
;
1651 //-------------------------------------------------------------------------
1653 Size
SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign
)
1657 Virtual method of the SfxDockingWindow class. This method determines how
1658 the size of the DockingWindows changes depending on the alignment. The base
1659 implementation uses the floating mode, the size of the marked Floating
1660 Size. For horizontal alignment, the width will be the width of the outer
1661 DockingRectangle, with vertical alignment the height will be the height of
1662 the inner DockingRectangle (resulting from the order in which the SFX child
1663 windows are displayed). The other size is set to the current floating-size,
1664 this could changed by a to intervening derived class. The docking size must
1665 be the same for Left/Right and Top/Bottom.
1669 // Note: if the resizing is also possible in the docked state, then the
1670 // Floating-size does also have to be adjusted?
1672 Size aSize
= GetFloatingSize();
1676 case SFX_ALIGN_BOTTOM
:
1677 case SFX_ALIGN_LOWESTTOP
:
1678 case SFX_ALIGN_HIGHESTTOP
:
1679 case SFX_ALIGN_LOWESTBOTTOM
:
1680 case SFX_ALIGN_HIGHESTBOTTOM
:
1681 aSize
.Width() = aOuterRect
.Right() - aOuterRect
.Left();
1683 case SFX_ALIGN_LEFT
:
1684 case SFX_ALIGN_RIGHT
:
1685 case SFX_ALIGN_FIRSTLEFT
:
1686 case SFX_ALIGN_LASTLEFT
:
1687 case SFX_ALIGN_FIRSTRIGHT
:
1688 case SFX_ALIGN_LASTRIGHT
:
1689 aSize
.Height() = aInnerRect
.Bottom() - aInnerRect
.Top();
1691 case SFX_ALIGN_NOALIGNMENT
:
1700 //-------------------------------------------------------------------------
1702 SfxChildAlignment
SfxDockingWindow::CheckAlignment(SfxChildAlignment
,
1703 SfxChildAlignment eAlign
)
1707 Virtual method of the SfxDockingWindow class. Here a derived class can
1708 disallow certain alignments. The base implementation does not
1716 //-------------------------------------------------------------------------
1718 sal_Bool
SfxDockingWindow::Close()
1722 The window is closed when the ChildWindow is destroyed by running the
1723 ChildWindow-slots. If this is method is overridden by a derived class
1724 method, then the SfxDockingDialogWindow: Close() must be called afterwards
1725 if the Close() was not cancelled with "return sal_False".
1728 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
1732 SfxBoolItem
aValue( pMgr
->GetType(), sal_False
);
1733 pBindings
->GetDispatcher_Impl()->Execute(
1734 pMgr
->GetType(), SFX_CALLMODE_RECORD
| SFX_CALLMODE_ASYNCHRON
, &aValue
, 0L );
1738 //-------------------------------------------------------------------------
1740 void SfxDockingWindow::Paint(const Rectangle
& /*rRect*/)
1744 Returns a boundary line to the docked edge and a frame when the Window is in
1745 a docked state. In this way SVLOOK is considered.
1749 if ( pImp
->bSplitable
|| IsFloatingMode() )
1752 Rectangle aRect
= Rectangle(Point(0, 0),
1753 GetOutputSizePixel());
1754 switch (GetAlignment())
1758 DrawLine(aRect
.BottomLeft(), aRect
.BottomRight());
1763 case SFX_ALIGN_BOTTOM
:
1765 DrawLine(aRect
.TopLeft(), aRect
.TopRight());
1770 case SFX_ALIGN_LEFT
:
1772 DrawLine(aRect
.TopRight(), aRect
.BottomRight());
1777 case SFX_ALIGN_RIGHT
:
1779 DrawLine(aRect
.TopLeft(), aRect
.BottomLeft());
1787 DecorationView
aView( this );
1788 aView
.DrawFrame( aRect
, FRAME_DRAW_OUT
);
1791 //-------------------------------------------------------------------------
1793 void SfxDockingWindow::SetMinOutputSizePixel( const Size
& rSize
)
1797 With this method, a minimal OutputSize be can set, that is queried in
1798 the Resizing()-Handler.
1802 pImp
->aMinSize
= rSize
;
1803 DockingWindow::SetMinOutputSizePixel( rSize
);
1806 //-------------------------------------------------------------------------
1808 Size
SfxDockingWindow::GetMinOutputSizePixel() const
1812 Set the minimum size which is returned.
1816 return pImp
->aMinSize
;
1819 //-------------------------------------------------------------------------
1821 long SfxDockingWindow::Notify( NotifyEvent
& rEvt
)
1823 if ( rEvt
.GetType() == EVENT_GETFOCUS
)
1825 pBindings
->SetActiveFrame( pMgr
->GetFrame() );
1827 if ( pImp
->pSplitWin
)
1828 pImp
->pSplitWin
->SetActiveWindow_Impl( this );
1830 pMgr
->Activate_Impl();
1832 Window
* pWindow
= rEvt
.GetWindow();
1833 rtl::OString sHelpId
;
1834 while ( sHelpId
.isEmpty() && pWindow
)
1836 sHelpId
= pWindow
->GetHelpId();
1837 pWindow
= pWindow
->GetParent();
1840 if ( !sHelpId
.isEmpty() )
1841 SfxHelp::OpenHelpAgent( &pBindings
->GetDispatcher_Impl()->GetFrame()->GetFrame(), sHelpId
);
1843 // In VCL Notify goes first to the window itself, also call the
1844 // base class, otherwise the parent learns nothing
1845 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1846 DockingWindow::Notify( rEvt
);
1849 else if( rEvt
.GetType() == EVENT_KEYINPUT
)
1851 // First, allow KeyInput for Dialog functions
1852 if ( !DockingWindow::Notify( rEvt
) && SfxViewShell::Current() )
1853 // then also for valid global accelerators.
1854 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt
.GetKeyEvent() );
1857 else if ( rEvt
.GetType() == EVENT_LOSEFOCUS
&& !HasChildPathFocus() )
1859 pBindings
->SetActiveFrame( NULL
);
1860 pMgr
->Deactivate_Impl();
1863 return DockingWindow::Notify( rEvt
);
1867 sal_uInt16
SfxDockingWindow::GetWinBits_Impl() const
1869 sal_uInt16 nBits
= 0;
1873 //-------------------------------------------------------------------------
1875 void SfxDockingWindow::SetItemSize_Impl( const Size
& rSize
)
1877 pImp
->aSplitSize
= rSize
;
1879 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1880 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
1881 if ( pImp
->bSplitable
)
1882 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
1883 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1886 void SfxDockingWindow::Disappear_Impl()
1888 if ( pImp
->pSplitWin
&& pImp
->pSplitWin
->IsItemValid( GetType() ) )
1889 pImp
->pSplitWin
->RemoveWindow(this);
1892 void SfxDockingWindow::Reappear_Impl()
1894 if ( pImp
->pSplitWin
&& !pImp
->pSplitWin
->IsItemValid( GetType() ) )
1896 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
);
1900 sal_Bool
SfxDockingWindow::IsAutoHide_Impl() const
1902 if ( pImp
->pSplitWin
)
1903 return !pImp
->pSplitWin
->IsFadeIn();
1908 void SfxDockingWindow::AutoShow( sal_Bool bShow
)
1910 AutoShow_Impl(bShow
);
1913 void SfxDockingWindow::AutoShow_Impl( sal_Bool bShow
)
1915 if ( pImp
->pSplitWin
)
1918 pImp
->pSplitWin
->FadeIn();
1920 pImp
->pSplitWin
->FadeOut();
1924 void SfxDockingWindow::FadeIn( sal_Bool
/*bFadeIn*/ )
1928 void SfxDockingWindow::StateChanged( StateChangedType nStateChange
)
1930 if ( nStateChange
== STATE_CHANGE_INITSHOW
)
1933 DockingWindow::StateChanged( nStateChange
);
1936 void SfxDockingWindow::Move()
1939 pImp
->aMoveTimer
.Start();
1942 IMPL_LINK_NOARG(SfxDockingWindow
, TimerHdl
)
1944 pImp
->aMoveTimer
.Stop();
1945 if ( IsReallyVisible() && IsFloatingMode() )
1947 if( !GetFloatingWindow()->IsRollUp() )
1948 SetFloatingSize( GetOutputSizePixel() );
1949 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
1950 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
1951 if ( pImp
->bSplitable
)
1952 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
1953 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1954 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1959 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */