1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svl/eitem.hxx>
21 #include <vcl/decoview.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/timer.hxx>
25 #include <vcl/idle.hxx>
26 #include <rtl/instance.hxx>
27 #include <toolkit/helper/vclunohelper.hxx>
28 #include <comphelper/processfactory.hxx>
30 #include <sfx2/dockwin.hxx>
31 #include <sfx2/bindings.hxx>
32 #include <sfx2/viewfrm.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include "workwin.hxx"
35 #include "splitwin.hxx"
36 #include <sfx2/viewsh.hxx>
37 #include <sfx2/sfxhelp.hxx>
38 #include <sfx2/objsh.hxx>
39 #include <sfx2/msgpool.hxx>
41 #include <com/sun/star/frame/XController.hpp>
42 #include <com/sun/star/lang/XUnoTunnel.hpp>
43 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
44 #include <com/sun/star/awt/XWindow.hpp>
45 #include <com/sun/star/uno/XComponentContext.hpp>
46 #include <com/sun/star/frame/ModuleManager.hpp>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/ui/theWindowStateConfiguration.hpp>
49 #include <com/sun/star/ui/theWindowContentFactoryManager.hpp>
51 #define MAX_TOGGLEAREA_WIDTH 20
52 #define MAX_TOGGLEAREA_HEIGHT 20
54 using namespace ::com::sun::star
;
56 // If you want to change the number you also have to:
57 // - Add new slot ids to sfxsids.hrc
58 // - Add new slots to frmslots.sdi
59 // - Add new slot definitions to sfx.sdi
60 static const int NUM_OF_DOCKINGWINDOWS
= 10;
62 class SfxTitleDockingWindow
: public SfxDockingWindow
64 VclPtr
<vcl::Window
> m_pWrappedWindow
;
67 SfxTitleDockingWindow(
68 SfxBindings
* pBindings
,
69 SfxChildWindow
* pChildWin
,
70 vcl::Window
* pParent
,
72 virtual ~SfxTitleDockingWindow();
73 virtual void dispose() SAL_OVERRIDE
;
75 vcl::Window
* GetWrappedWindow() const { return m_pWrappedWindow
; }
76 void SetWrappedWindow(vcl::Window
* const pWindow
);
78 virtual void StateChanged( StateChangedType nType
) SAL_OVERRIDE
;
79 virtual bool Notify( NotifyEvent
& rNEvt
) SAL_OVERRIDE
;
80 virtual void Resize() SAL_OVERRIDE
;
81 virtual void Resizing( Size
& rSize
) SAL_OVERRIDE
;
82 virtual bool Close() SAL_OVERRIDE
;
93 static bool lcl_getWindowState( const uno::Reference
< container::XNameAccess
>& xWindowStateMgr
, const OUString
& rResourceURL
, WindowState
& rWindowState
)
100 uno::Sequence
< beans::PropertyValue
> aWindowState
;
101 a
= xWindowStateMgr
->getByName( rResourceURL
);
102 if ( a
>>= aWindowState
)
104 for ( sal_Int32 n
= 0; n
< aWindowState
.getLength(); n
++ )
106 if ( aWindowState
[n
].Name
== "UIName" )
108 aWindowState
[n
].Value
>>= rWindowState
.sTitle
;
115 catch ( container::NoSuchElementException
& )
123 SfxDockingWrapper::SfxDockingWrapper( vcl::Window
* pParentWnd
,
125 SfxBindings
* pBindings
,
126 SfxChildWinInfo
* pInfo
)
127 : SfxChildWindow( pParentWnd
, nId
)
129 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
130 const OUString
aDockWindowResourceURL( "private:resource/dockingwindow/" );
132 VclPtr
<SfxTitleDockingWindow
> pTitleDockWindow
= VclPtr
<SfxTitleDockingWindow
>::Create( pBindings
, this, pParentWnd
,
133 WB_STDDOCKWIN
| WB_CLIPCHILDREN
| WB_SIZEABLE
| WB_3DLOOK
| WB_ROLLABLE
);
134 pWindow
= pTitleDockWindow
;
135 eChildAlignment
= SfxChildAlignment::NOALIGNMENT
;
137 // Use factory manager to retrieve XWindow factory. That can be used to instantiate
138 // the real window factory.
139 uno::Reference
< lang::XSingleComponentFactory
> xFactoryMgr
= ui::theWindowContentFactoryManager::get(xContext
);
141 SfxDispatcher
* pDispatcher
= pBindings
->GetDispatcher();
142 uno::Reference
< frame::XFrame
> xFrame( pDispatcher
->GetFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY
);
143 uno::Sequence
< uno::Any
> aArgs(2);
144 beans::PropertyValue aPropValue
;
145 aPropValue
.Name
= "Frame";
146 aPropValue
.Value
= uno::makeAny( xFrame
);
147 aArgs
[0] <<= aPropValue
;
148 aPropValue
.Name
= "ResourceURL";
150 // create a resource URL from the nId provided by the sfx2
151 OUString
aResourceURL( aDockWindowResourceURL
);
152 aResourceURL
+= OUString::number(nId
);
153 aPropValue
.Value
= uno::makeAny( aResourceURL
);
154 aArgs
[1] <<= aPropValue
;
156 uno::Reference
< awt::XWindow
> xWindow
;
159 xWindow
= uno::Reference
< awt::XWindow
>(
160 xFactoryMgr
->createInstanceWithArgumentsAndContext( aArgs
, xContext
),
163 static uno::WeakReference
< frame::XModuleManager2
> m_xModuleManager
;
165 uno::Reference
< frame::XModuleManager2
> xModuleManager( m_xModuleManager
);
166 if ( !xModuleManager
.is() )
168 xModuleManager
= frame::ModuleManager::create(xContext
);
169 m_xModuleManager
= xModuleManager
;
172 static uno::WeakReference
< container::XNameAccess
> m_xWindowStateConfiguration
;
174 uno::Reference
< container::XNameAccess
> xWindowStateConfiguration( m_xWindowStateConfiguration
);
175 if ( !xWindowStateConfiguration
.is() )
177 xWindowStateConfiguration
= ui::theWindowStateConfiguration::get( xContext
);
178 m_xWindowStateConfiguration
= xWindowStateConfiguration
;
181 OUString sModuleIdentifier
= xModuleManager
->identify( xFrame
);
183 uno::Reference
< container::XNameAccess
> xModuleWindowState(
184 xWindowStateConfiguration
->getByName( sModuleIdentifier
),
186 if ( xModuleWindowState
.is() )
188 WindowState aDockWinState
;
189 if ( lcl_getWindowState( xModuleWindowState
, aResourceURL
, aDockWinState
))
190 pTitleDockWindow
->SetText( aDockWinState
.sTitle
);
193 catch ( beans::UnknownPropertyException
& )
196 catch ( uno::RuntimeException
& )
199 catch ( uno::Exception
& )
203 vcl::Window
* pContentWindow
= VCLUnoHelper::GetWindow(xWindow
);
204 if ( pContentWindow
)
205 pContentWindow
->SetStyle( pContentWindow
->GetStyle() | WB_DIALOGCONTROL
| WB_CHILDDLGCTRL
);
206 pTitleDockWindow
->SetWrappedWindow(pContentWindow
);
208 pWindow
->SetOutputSizePixel( Size( 270, 240 ) );
210 static_cast<SfxDockingWindow
*>( pWindow
.get() )->Initialize( pInfo
);
211 SetHideNotDelete( true );
214 SfxChildWindow
* SfxDockingWrapper::CreateImpl(vcl::Window
*pParent
, sal_uInt16 nId
,
215 SfxBindings
*pBindings
, SfxChildWinInfo
* pInfo
)
217 SfxChildWindow
*pWin
= new SfxDockingWrapper(pParent
, nId
, pBindings
, pInfo
);
221 void SfxDockingWrapper::RegisterChildWindow (bool bVis
, SfxModule
*pMod
, SfxChildWindowFlags nFlags
)
223 // pre-register a couple of docking windows
224 for (int i
=0; i
< NUM_OF_DOCKINGWINDOWS
; i
++ )
226 sal_uInt16 nID
= sal_uInt16(SID_DOCKWIN_START
+i
);
227 SfxChildWinFactory
*pFact
= new SfxChildWinFactory( SfxDockingWrapper::CreateImpl
, nID
, 0xffff );
228 pFact
->aInfo
.nFlags
|= nFlags
;
229 pFact
->aInfo
.bVisible
= bVis
;
230 SfxChildWindow::RegisterChildWindow(pMod
, pFact
);
234 SfxChildWinInfo
SfxDockingWrapper::GetInfo() const
236 SfxChildWinInfo aInfo
= SfxChildWindow::GetInfo();
237 static_cast<SfxDockingWindow
*>(GetWindow())->FillInfo( aInfo
);
241 SfxTitleDockingWindow::SfxTitleDockingWindow(SfxBindings
* pBind
, SfxChildWindow
* pChildWin
,
242 vcl::Window
* pParent
, WinBits nBits
)
243 : SfxDockingWindow(pBind
, pChildWin
, pParent
, nBits
)
244 , m_pWrappedWindow(nullptr)
248 SfxTitleDockingWindow::~SfxTitleDockingWindow()
253 void SfxTitleDockingWindow::dispose()
255 m_pWrappedWindow
.disposeAndClear();
256 SfxDockingWindow::dispose();
259 void SfxTitleDockingWindow::SetWrappedWindow( vcl::Window
* const pWindow
)
261 m_pWrappedWindow
= pWindow
;
262 if (m_pWrappedWindow
)
264 m_pWrappedWindow
->SetParent(this);
265 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
266 m_pWrappedWindow
->Show();
270 bool SfxTitleDockingWindow::Notify( NotifyEvent
& rNEvt
)
272 return SfxDockingWindow::Notify( rNEvt
);
275 void SfxTitleDockingWindow::StateChanged( StateChangedType nType
)
277 if ( nType
== StateChangedType::InitShow
)
279 vcl::Window
* pWindow
= GetWrappedWindow();
282 pWindow
->SetSizePixel( GetOutputSizePixel() );
287 SfxDockingWindow::StateChanged(nType
);
290 void SfxTitleDockingWindow::Resize()
292 SfxDockingWindow::Resize();
293 if (m_pWrappedWindow
)
294 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
297 void SfxTitleDockingWindow::Resizing( Size
&rSize
)
299 SfxDockingWindow::Resizing( rSize
);
300 if (m_pWrappedWindow
)
301 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
304 bool SfxTitleDockingWindow::Close()
306 return SfxDockingWindow::Close();
311 struct ChildrenRegisteredMap
: public rtl::Static
< bool, ChildrenRegisteredMap
> {};
314 static bool lcl_checkDockingWindowID( sal_uInt16 nID
)
316 if (nID
< SID_DOCKWIN_START
|| nID
>= sal_uInt16(SID_DOCKWIN_START
+NUM_OF_DOCKINGWINDOWS
))
322 static SfxWorkWindow
* lcl_getWorkWindowFromXFrame( const uno::Reference
< frame::XFrame
>& rFrame
)
324 // We need to find the corresponding SfxFrame of our XFrame
325 SfxFrame
* pFrame
= SfxFrame::GetFirst();
326 SfxFrame
* pXFrame
= 0;
329 uno::Reference
< frame::XFrame
> xViewShellFrame( pFrame
->GetFrameInterface() );
330 if ( xViewShellFrame
== rFrame
)
336 pFrame
= SfxFrame::GetNext( *pFrame
);
339 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
341 return pXFrame
->GetWorkWindow_Impl();
346 /** Factory function used by the framework layout manager to "create" a docking window with a special name.
347 The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
348 in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
350 void SAL_CALL
SfxDockingWindowFactory( const uno::Reference
< frame::XFrame
>& rFrame
, const OUString
& rDockingWindowName
)
352 SolarMutexGuard aGuard
;
353 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
355 // Check the range of the provided ID otherwise nothing will happen
356 if ( lcl_checkDockingWindowID( nID
))
358 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
361 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
364 // Register window at the workwindow child window list
365 pWorkWindow
->SetChildWindow_Impl( nID
, true, false );
371 /** Function used by the framework layout manager to determine the visibility state of a docking window with
372 a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
373 range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
375 bool SAL_CALL
IsDockingWindowVisible( const uno::Reference
< frame::XFrame
>& rFrame
, const OUString
& rDockingWindowName
)
377 SolarMutexGuard aGuard
;
379 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
381 // Check the range of the provided ID otherwise nothing will happen
382 if ( lcl_checkDockingWindowID( nID
))
384 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
387 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
396 class SfxDockingWindow_Impl
398 friend class SfxDockingWindow
;
400 SfxChildAlignment eLastAlignment
;
401 SfxChildAlignment eDockAlignment
;
404 VclPtr
<SfxSplitWindow
> pSplitWin
;
408 // The following members are only valid in the time from startDocking to
412 long nHorizontalSize
;
416 sal_uInt16 nDockLine
;
419 bool bDockingPrevented
;
422 SfxChildAlignment
GetLastAlignment() const
423 { return eLastAlignment
; }
424 void SetLastAlignment(SfxChildAlignment eAlign
)
425 { eLastAlignment
= eAlign
; }
426 SfxChildAlignment
GetDockAlignment() const
427 { return eDockAlignment
; }
428 void SetDockAlignment(SfxChildAlignment eAlign
)
429 { eDockAlignment
= eAlign
; }
434 This virtual method of the class FloatingWindow keeps track of changes in
435 FloatingSize. If this method is overridden by a derived class,
436 then the SfxFloatingWindow: Resize() must also be called.
438 void SfxDockingWindow::Resize()
440 DockingWindow::Resize();
442 if ( pImp
&& pImp
->bConstructed
&& pMgr
)
444 if ( IsFloatingMode() )
446 // start timer for saving window status information
447 pImp
->aMoveIdle
.Start();
451 Size
aSize( GetSizePixel() );
452 switch ( pImp
->GetDockAlignment() )
454 case SfxChildAlignment::LEFT
:
455 case SfxChildAlignment::FIRSTLEFT
:
456 case SfxChildAlignment::LASTLEFT
:
457 case SfxChildAlignment::RIGHT
:
458 case SfxChildAlignment::FIRSTRIGHT
:
459 case SfxChildAlignment::LASTRIGHT
:
460 pImp
->nHorizontalSize
= aSize
.Width();
461 pImp
->aSplitSize
= aSize
;
463 case SfxChildAlignment::TOP
:
464 case SfxChildAlignment::LOWESTTOP
:
465 case SfxChildAlignment::HIGHESTTOP
:
466 case SfxChildAlignment::BOTTOM
:
467 case SfxChildAlignment::HIGHESTBOTTOM
:
468 case SfxChildAlignment::LOWESTBOTTOM
:
469 pImp
->nVerticalSize
= aSize
.Height();
470 pImp
->aSplitSize
= aSize
;
481 This virtual method of the class DockingWindow makes it possible to
482 intervene in the switching of the floating mode.
483 If this method is overridden by a derived class,
484 then the SfxDockingWindow::PrepareToggleFloatingMode() must be called
485 afterwards, if not FALSE is returned.
487 bool SfxDockingWindow::PrepareToggleFloatingMode()
489 if (!pImp
|| !pImp
->bConstructed
)
492 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr
)
495 if ( pImp
->bDockingPrevented
)
498 if (!IsFloatingMode())
500 // Test, if FloatingMode is permitted.
501 if ( CheckAlignment(GetAlignment(),SfxChildAlignment::NOALIGNMENT
) != SfxChildAlignment::NOALIGNMENT
)
504 if ( pImp
->pSplitWin
)
506 // The DockingWindow is inside a SplitWindow and will be teared of.
507 pImp
->pSplitWin
->RemoveWindow(this/*, sal_False*/);
513 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
515 // Test if it is allowed to dock,
516 if (CheckAlignment(GetAlignment(),pImp
->GetLastAlignment()) == SfxChildAlignment::NOALIGNMENT
)
519 // Test, if the Workwindow allows for docking at the moment.
520 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
521 if ( !pWorkWin
->IsDockingAllowed() || !pWorkWin
->IsInternalDockingAllowed() )
530 This virtual method of the DockingWindow class sets the internal data of
531 the SfxDockingWindow and ensures the correct alignment on the parent window.
532 Through PrepareToggleFloatMode and Initialize it is ensured that
533 pImp-> GetLastAlignment() always delivers an allowed alignment. If this
534 method is overridden by a derived class, then first the
535 SfxDockingWindow::ToggleFloatingMode() must be called.
537 void SfxDockingWindow::ToggleFloatingMode()
539 if ( !pImp
|| !pImp
->bConstructed
|| !pMgr
)
540 return; // No Handler call
542 // Remember old alignment and then switch.
543 // SV has already switched, but the alignment SfxDockingWindow is still
544 // the old one. What I was before?
545 SfxChildAlignment eLastAlign
= GetAlignment();
547 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
548 SfxChildIdentifier eIdent
= SfxChildIdentifier::DOCKINGWINDOW
;
549 if ( pImp
->bSplitable
)
550 eIdent
= SfxChildIdentifier::SPLITWINDOW
;
552 if (IsFloatingMode())
554 SetAlignment(SfxChildAlignment::NOALIGNMENT
);
555 if ( !pImp
->aWinState
.isEmpty() )
556 GetFloatingWindow()->SetWindowState( pImp
->aWinState
);
558 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
562 if (pImp
->GetDockAlignment() == eLastAlign
)
564 // If ToggleFloatingMode was called, but the DockAlignment still
565 // is unchanged, then this means that it must have been a toggling
566 // through DClick, so use last alignment
567 SetAlignment (pImp
->GetLastAlignment());
568 if ( !pImp
->bSplitable
)
569 SetSizePixel( CalcDockingSize(GetAlignment()) );
574 // Toggling was triggered by dragging
575 pImp
->nLine
= pImp
->nDockLine
;
576 pImp
->nPos
= pImp
->nDockPos
;
577 SetAlignment (pImp
->GetDockAlignment());
580 if ( pImp
->bSplitable
)
582 // The DockingWindow is now in a SplitWindow
583 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
585 // The LastAlignment is still the last docked
586 SfxSplitWindow
*pSplit
= pWorkWin
->GetSplitWindow_Impl(pImp
->GetLastAlignment());
588 DBG_ASSERT( pSplit
, "LastAlignment is not correct!" );
589 if ( pSplit
&& pSplit
!= pImp
->pSplitWin
)
590 pSplit
->ReleaseWindow_Impl(this);
591 if ( pImp
->GetDockAlignment() == eLastAlign
)
592 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
);
594 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
, pImp
->nLine
, pImp
->nPos
, pImp
->bNewLine
);
595 if ( !pImp
->pSplitWin
->IsFadeIn() )
596 pImp
->pSplitWin
->FadeIn();
600 // Keep the old alignment for the next toggle; set it only now due to the
601 // unregister SplitWindow!
602 pImp
->SetLastAlignment(eLastAlign
);
604 // Reset DockAlignment, if EndDocking is still called
605 pImp
->SetDockAlignment(GetAlignment());
607 // Dock or undock SfxChildWindow correctly.
608 pWorkWin
->ConfigChild_Impl( eIdent
, SfxDockingConfig::TOGGLEFLOATMODE
, pMgr
->GetType() );
613 This virtual method of the DockingWindow class takes the inner and outer
614 docking rectangle from the parent window. If this method is overridden by
615 a derived class, then SfxDockingWindow:StartDocking() has to be called at
618 void SfxDockingWindow::StartDocking()
620 if ( !pImp
|| !pImp
->bConstructed
|| !pMgr
)
622 SfxChildIdentifier eIdent
= SfxChildIdentifier::DOCKINGWINDOW
;
623 if ( pImp
->bSplitable
)
624 eIdent
= SfxChildIdentifier::SPLITWINDOW
;
625 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
626 pWorkWin
->ConfigChild_Impl( eIdent
, SfxDockingConfig::SETDOCKINGRECTS
, pMgr
->GetType() );
627 pImp
->SetDockAlignment(GetAlignment());
629 if ( pImp
->pSplitWin
)
631 // Get the current docking data
632 pImp
->pSplitWin
->GetWindowPos(this, pImp
->nLine
, pImp
->nPos
);
633 pImp
->nDockLine
= pImp
->nLine
;
634 pImp
->nDockPos
= pImp
->nPos
;
635 pImp
->bNewLine
= false;
641 This virtual method of the DockingWindow class calculates the current
642 tracking rectangle. For this purpose the method CalcAlignment(RPOs, rRect)
643 is used, the behavior can be influenced by the derived classes (see below).
644 This method should if possible not be overwritten.
646 bool SfxDockingWindow::Docking( const Point
& rPos
, Rectangle
& rRect
)
648 if ( Application::IsInModalMode() )
651 if ( !pImp
|| !pImp
->bConstructed
|| !pMgr
)
653 rRect
.SetSize( Size() );
654 return IsFloatingMode();
657 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
658 if ( pImp
->bDockingPrevented
|| !pWorkWin
->IsInternalDockingAllowed() )
661 bool bFloatMode
= false;
663 if ( GetOuterRect().IsInside( rPos
) && !IsDockingPrevented() )
665 // Mouse within OuterRect: calculate Alignment and Rectangle
666 SfxChildAlignment eAlign
= CalcAlignment(rPos
, rRect
);
667 if (eAlign
== SfxChildAlignment::NOALIGNMENT
)
669 pImp
->SetDockAlignment(eAlign
);
673 // Mouse is not within OuterRect: must be FloatingWindow
675 if (CheckAlignment(pImp
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
) != SfxChildAlignment::NOALIGNMENT
)
678 if ( SfxChildAlignment::NOALIGNMENT
!= pImp
->GetDockAlignment() )
680 // Due to a bug the rRect may only be changed when the
681 // alignment is changed!
682 pImp
->SetDockAlignment(SfxChildAlignment::NOALIGNMENT
);
683 rRect
.SetSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT
));
687 if ( !pImp
->bSplitable
)
689 // For individually docked window the position is set through the
690 // alignment and the docking rectangle.
691 Size aSize
= rRect
.GetSize();
694 switch ( pImp
->GetDockAlignment() )
696 case SfxChildAlignment::LEFT
:
697 case SfxChildAlignment::FIRSTLEFT
:
698 case SfxChildAlignment::LASTLEFT
:
699 aPos
= aInnerRect
.TopLeft();
700 if ( pImp
->GetDockAlignment() == GetAlignment() )
701 aPos
.X() -= aSize
.Width();
704 case SfxChildAlignment::TOP
:
705 case SfxChildAlignment::LOWESTTOP
:
706 case SfxChildAlignment::HIGHESTTOP
:
707 aPos
= Point(aOuterRect
.Left(), aInnerRect
.Top());
708 if ( pImp
->GetDockAlignment() == GetAlignment() )
709 aPos
.Y() -= aSize
.Height();
712 case SfxChildAlignment::RIGHT
:
713 case SfxChildAlignment::FIRSTRIGHT
:
714 case SfxChildAlignment::LASTRIGHT
:
715 aPos
= Point(aInnerRect
.Right() - rRect
.GetSize().Width(),
717 if ( pImp
->GetDockAlignment() == GetAlignment() )
718 aPos
.X() += aSize
.Width();
721 case SfxChildAlignment::BOTTOM
:
722 case SfxChildAlignment::HIGHESTBOTTOM
:
723 case SfxChildAlignment::LOWESTBOTTOM
:
724 aPos
= Point(aOuterRect
.Left(),
725 aInnerRect
.Bottom() - rRect
.GetSize().Height());
726 if ( pImp
->GetDockAlignment() == GetAlignment() )
727 aPos
.Y() += aSize
.Height();
739 /** Virtual method of the DockingWindow class ensures the correct alignment on
740 the parent window. If this method is overridden by a derived class, then
741 SfxDockingWindow::EndDocking() must be called first.
743 void SfxDockingWindow::EndDocking( const Rectangle
& rRect
, bool bFloatMode
)
745 if ( !pImp
|| !pImp
->bConstructed
|| IsDockingCanceled() || !pMgr
)
748 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
749 bool bReArrange
= false;
750 if ( pImp
->bSplitable
)
752 // If the alignment changes and the window is in a docked state in a
753 // SplitWindow, then it must be re-registered. If it is docked again,
754 // PrepareToggleFloatingMode() and ToggleFloatingMode() preform the
762 if ( GetAlignment() != pImp
->GetDockAlignment() )
764 // before Show() is called must the reassignment have been made,
765 // therefore the base class can not be called
766 if ( IsFloatingMode() || !pImp
->bSplitable
)
767 Show( false, SHOW_NOFOCUSCHANGE
);
769 // Set the size for toggling.
770 pImp
->aSplitSize
= rRect
.GetSize();
771 if ( IsFloatingMode() )
773 SetFloatingMode( bFloatMode
);
774 if ( IsFloatingMode() || !pImp
->bSplitable
)
775 Show( true, SHOW_NOFOCUSCHANGE
);
779 pImp
->pSplitWin
->RemoveWindow(this,false);
780 pImp
->nLine
= pImp
->nDockLine
;
781 pImp
->nPos
= pImp
->nDockPos
;
782 pImp
->pSplitWin
->ReleaseWindow_Impl(this);
783 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(pImp
->GetDockAlignment());
784 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
, pImp
->nDockLine
, pImp
->nDockPos
, pImp
->bNewLine
);
785 if ( !pImp
->pSplitWin
->IsFadeIn() )
786 pImp
->pSplitWin
->FadeIn();
789 else if ( pImp
->nLine
!= pImp
->nDockLine
|| pImp
->nPos
!= pImp
->nDockPos
|| pImp
->bNewLine
)
791 // Moved within Splitwindows
792 if ( pImp
->nLine
!= pImp
->nDockLine
)
793 pImp
->aSplitSize
= rRect
.GetSize();
794 pImp
->pSplitWin
->MoveWindow( this, pImp
->aSplitSize
, pImp
->nDockLine
, pImp
->nDockPos
, pImp
->bNewLine
);
799 pImp
->bEndDocked
= true;
800 DockingWindow::EndDocking(rRect
, bFloatMode
);
801 pImp
->bEndDocked
= false;
804 SetAlignment( IsFloatingMode() ? SfxChildAlignment::NOALIGNMENT
: pImp
->GetDockAlignment() );
809 Virtual method of the DockingWindow class. Here, the interactive resize in
810 FloatingMode can be influenced, for example by only allowing for discrete
811 values for width and / or height. The base implementation prevents that the
812 output size is smaller than one set with SetMinOutputSizePixel().
814 void SfxDockingWindow::Resizing( Size
& /*rSize*/ )
821 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
822 required because the docking is implemented in Sfx through SfxChildWindows.
824 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
825 vcl::Window
* pParent
, WinBits nWinBits
) :
826 DockingWindow (pParent
, nWinBits
),
831 if ( !GetHelpId().isEmpty() )
833 SetUniqueId( GetHelpId() );
838 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher()->GetFrame();
839 SfxSlotPool
* pSlotPool
= pViewFrame
->GetObjectShell()->GetModule()->GetSlotPool();
840 const SfxSlot
* pSlot
= pCW
? pSlotPool
->GetSlot( pCW
->GetType() ) : NULL
;
843 OString
aCmd("SFXDOCKINGWINDOW_");
844 aCmd
+= pSlot
->GetUnoName();
849 pImp
= new SfxDockingWindow_Impl
;
850 pImp
->bConstructed
= false;
852 pImp
->bEndDocked
= false;
853 pImp
->bDockingPrevented
= false;
855 pImp
->bSplitable
= true;
857 // Initially set to default, the alignment is set in the subclass
858 pImp
->nLine
= pImp
->nDockLine
= 0;
859 pImp
->nPos
= pImp
->nDockPos
= 0;
860 pImp
->bNewLine
= false;
861 pImp
->SetLastAlignment(SfxChildAlignment::NOALIGNMENT
);
862 pImp
->aMoveIdle
.SetPriority(SchedulerPriority::RESIZE
);
863 pImp
->aMoveIdle
.SetIdleHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
866 /** Constructor for the SfxDockingWindow class. A SfxChildWindow will be
867 required because the docking is implemented in Sfx through SfxChildWindows.
869 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
870 vcl::Window
* pParent
, const ResId
& rResId
) :
871 DockingWindow(pParent
, rResId
),
876 if ( !GetHelpId().isEmpty() )
878 SetUniqueId( GetHelpId() );
883 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher()->GetFrame();
884 SfxSlotPool
* pSlotPool
= pViewFrame
->GetObjectShell()->GetModule()->GetSlotPool();
885 const SfxSlot
* pSlot
= pCW
? pSlotPool
->GetSlot( pCW
->GetType() ) : NULL
;
888 OString
aCmd("SFXDOCKINGWINDOW_");
889 aCmd
+= pSlot
->GetUnoName();
894 pImp
= new SfxDockingWindow_Impl
;
895 pImp
->bConstructed
= false;
897 pImp
->bEndDocked
= false;
898 pImp
->bDockingPrevented
= false;
900 pImp
->bSplitable
= true;
902 // Initially set to default, the alignment is set in the subclass
903 pImp
->nLine
= pImp
->nDockLine
= 0;
904 pImp
->nPos
= pImp
->nDockPos
= 0;
905 pImp
->bNewLine
= false;
906 pImp
->SetLastAlignment(SfxChildAlignment::NOALIGNMENT
);
907 pImp
->aMoveIdle
.SetPriority(SchedulerPriority::RESIZE
);
908 pImp
->aMoveIdle
.SetIdleHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
911 /** Constructor for the SfxDockingWindow class. A SfxChildWindow will be
912 required because the docking is implemented in Sfx through SfxChildWindows.
914 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
915 vcl::Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
)
916 : DockingWindow(pParent
, rID
, rUIXMLDescription
)
917 , pBindings(pBindinx
)
921 if ( !GetHelpId().isEmpty() )
923 SetUniqueId( GetHelpId() );
928 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher()->GetFrame();
929 SfxSlotPool
* pSlotPool
= pViewFrame
->GetObjectShell()->GetModule()->GetSlotPool();
930 const SfxSlot
* pSlot
= pCW
? pSlotPool
->GetSlot( pCW
->GetType() ) : NULL
;
933 OString
aCmd("SFXDOCKINGWINDOW_");
934 aCmd
+= pSlot
->GetUnoName();
939 pImp
= new SfxDockingWindow_Impl
;
940 pImp
->bConstructed
= false;
942 pImp
->bEndDocked
= false;
943 pImp
->bDockingPrevented
= false;
945 pImp
->bSplitable
= true;
947 // Initially set to default, the alignment is set in the subclass
948 pImp
->nLine
= pImp
->nDockLine
= 0;
949 pImp
->nPos
= pImp
->nDockPos
= 0;
950 pImp
->bNewLine
= false;
951 pImp
->SetLastAlignment(SfxChildAlignment::NOALIGNMENT
);
952 pImp
->aMoveIdle
.SetPriority(SchedulerPriority::RESIZE
);
953 pImp
->aMoveIdle
.SetIdleHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
956 /** Initialization of the SfxDockingDialog class via a SfxChildWinInfo.
957 The initialization is done only in a 2nd step after the constructor, this
958 constructor should be called from the derived class or from the
961 void SfxDockingWindow::Initialize(SfxChildWinInfo
*pInfo
)
965 pImp
->SetDockAlignment( SfxChildAlignment::NOALIGNMENT
);
966 pImp
->bConstructed
= true;
970 if (pInfo
&& (pInfo
->nFlags
& SfxChildWindowFlags::FORCEDOCK
))
971 pImp
->bDockingPrevented
= true;
973 pImp
->aSplitSize
= GetOutputSizePixel();
974 if ( !GetFloatingSize().Width() )
976 Size
aMinSize( GetMinOutputSizePixel() );
977 SetFloatingSize( pImp
->aSplitSize
);
978 if ( pImp
->aSplitSize
.Width() < aMinSize
.Width() )
979 pImp
->aSplitSize
.Width() = aMinSize
.Width();
980 if ( pImp
->aSplitSize
.Height() < aMinSize
.Height() )
981 pImp
->aSplitSize
.Height() = aMinSize
.Height();
984 bool bVertHorzRead( false );
985 if (pInfo
&& !pInfo
->aExtraString
.isEmpty())
987 // get information about alignment, split size and position in SplitWindow
989 sal_Int32 nPos
= pInfo
->aExtraString
.indexOf("AL:");
992 // alignment information
993 sal_Int32 n1
= pInfo
->aExtraString
.indexOf('(', nPos
);
996 sal_Int32 n2
= pInfo
->aExtraString
.indexOf(')', n1
);
999 // extract alignment information from extrastring
1000 aStr
= pInfo
->aExtraString
.copy(nPos
, n2
- nPos
+ 1);
1001 pInfo
->aExtraString
= pInfo
->aExtraString
.replaceAt(nPos
, n2
- nPos
+ 1, "");
1002 aStr
= aStr
.replaceAt(nPos
, n1
-nPos
+1, "");
1007 if ( !aStr
.isEmpty() )
1009 // accept window state only if alignment is also set
1010 pImp
->aWinState
= pInfo
->aWinState
;
1012 // check for valid alignment
1013 SfxChildAlignment eLocalAlignment
= (SfxChildAlignment
) (sal_uInt16
) aStr
.toInt32();
1014 if ( pImp
->bDockingPrevented
)
1015 // docking prevented, ignore old configuration and take alignment from default
1018 SetAlignment( eLocalAlignment
);
1020 SfxChildAlignment eAlign
= CheckAlignment(GetAlignment(),GetAlignment());
1021 if ( eAlign
!= GetAlignment() )
1023 OSL_FAIL("Invalid Alignment!");
1024 SetAlignment( eAlign
);
1028 // get last alignment (for toggeling)
1029 nPos
= aStr
.indexOf(',');
1032 aStr
= aStr
.copy(nPos
+1);
1033 pImp
->SetLastAlignment( (SfxChildAlignment
) (sal_uInt16
) aStr
.toInt32() );
1036 nPos
= aStr
.indexOf(',');
1039 // get split size and position in SplitWindow
1041 aStr
= aStr
.copy(nPos
+1);
1042 if ( GetPosSizeFromString( aStr
, aPos
, pImp
->aSplitSize
) )
1044 pImp
->nLine
= pImp
->nDockLine
= (sal_uInt16
) aPos
.X();
1045 pImp
->nPos
= pImp
->nDockPos
= (sal_uInt16
) aPos
.Y();
1046 pImp
->nVerticalSize
= pImp
->aSplitSize
.Height();
1047 pImp
->nHorizontalSize
= pImp
->aSplitSize
.Width();
1048 if ( GetSplitSizeFromString( aStr
, pImp
->aSplitSize
))
1049 bVertHorzRead
= true;
1054 OSL_FAIL( "Information is missing!" );
1058 if ( !bVertHorzRead
)
1060 pImp
->nVerticalSize
= pImp
->aSplitSize
.Height();
1061 pImp
->nHorizontalSize
= pImp
->aSplitSize
.Width();
1064 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1065 if ( GetAlignment() != SfxChildAlignment::NOALIGNMENT
)
1067 // check if SfxWorkWindow is able to allow docking at its border
1069 !pWorkWin
->IsDockingAllowed() ||
1070 !pWorkWin
->IsInternalDockingAllowed() ||
1071 ( (GetFloatStyle() & WB_STANDALONE
) && Application::IsInModalMode()) )
1073 SetAlignment( SfxChildAlignment::NOALIGNMENT
);
1077 // detect floating mode
1078 // toggeling mode will not execute code in handlers, because pImp->bConstructed is not set yet
1079 bool bFloatMode
= IsFloatingMode();
1080 if ( bFloatMode
!= ((GetAlignment() == SfxChildAlignment::NOALIGNMENT
)) )
1082 bFloatMode
= !bFloatMode
;
1083 SetFloatingMode( bFloatMode
);
1086 if ( !pImp
->aWinState
.isEmpty() )
1087 GetFloatingWindow()->SetWindowState( pImp
->aWinState
);
1089 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
1093 if ( IsFloatingMode() )
1095 // validate last alignment
1096 SfxChildAlignment eLastAlign
= pImp
->GetLastAlignment();
1097 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
1098 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::LEFT
);
1099 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
1100 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::RIGHT
);
1101 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
1102 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::TOP
);
1103 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
1104 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::BOTTOM
);
1105 pImp
->SetLastAlignment(eLastAlign
);
1109 // docked window must have NOALIGNMENT as last alignment
1110 pImp
->SetLastAlignment(SfxChildAlignment::NOALIGNMENT
);
1112 if ( pImp
->bSplitable
)
1114 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
1115 pImp
->pSplitWin
->InsertWindow(this, pImp
->aSplitSize
);
1119 //?????? Currently not supported
1120 // Window is docked individually; size is calculated.
1121 // It must therefore be initialized with the DloatingSize if
1122 // someone relies on it that a reasonable size is set
1123 SetSizePixel(GetFloatingSize());
1124 SetSizePixel(CalcDockingSize(GetAlignment()));
1129 pImp
->SetDockAlignment( GetAlignment() );
1132 void SfxDockingWindow::Initialize_Impl()
1136 pImp
->bConstructed
= true;
1140 FloatingWindow
* pFloatWin
= GetFloatingWindow();
1144 bSet
= !pFloatWin
->IsDefaultPos();
1148 Point aPos
= GetFloatingPos();
1149 if ( aPos
!= Point() )
1155 SfxViewFrame
*pFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
1156 vcl::Window
* pEditWin
= pFrame
->GetViewShell()->GetWindow();
1157 Point aPos
= pEditWin
->OutputToScreenPixel( pEditWin
->GetPosPixel() );
1158 aPos
= GetParent()->ScreenToOutputPixel( aPos
);
1159 SetFloatingPos( aPos
);
1164 // initialize floating window
1165 if ( pImp
->aWinState
.isEmpty() )
1166 // window state never set before, get if from defaults
1167 pImp
->aWinState
= pFloatWin
->GetWindowState();
1169 // trick: use VCL method SetWindowState to adjust position and size
1170 pFloatWin
->SetWindowState( pImp
->aWinState
);
1171 Size
aSize(pFloatWin
->GetSizePixel());
1173 // remember floating size for calculating alignment and tracking rectangle
1174 SetFloatingSize(aSize
);
1178 // allow calling of docking handlers
1179 pImp
->bConstructed
= true;
1182 /** Fills a SfxChildWinInfo with specific data from SfxDockingWindow,
1183 so that it can be written in the INI file. It is assumed that rinfo
1184 receives all other possible relevant data in the ChildWindow class.
1185 Insertions are marked with size and the ZoomIn flag.
1186 If this method is overridden, the base implementation must be called first.
1188 void SfxDockingWindow::FillInfo(SfxChildWinInfo
& rInfo
) const
1193 if (GetFloatingWindow() && pImp
->bConstructed
)
1194 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
1196 rInfo
.aWinState
= pImp
->aWinState
;
1197 rInfo
.aExtraString
= "AL:(";
1198 rInfo
.aExtraString
+= OUString::number((sal_uInt16
) GetAlignment());
1199 rInfo
.aExtraString
+= ",";
1200 rInfo
.aExtraString
+= OUString::number ((sal_uInt16
) pImp
->GetLastAlignment());
1201 if ( pImp
->bSplitable
)
1203 Point
aPos(pImp
->nLine
, pImp
->nPos
);
1204 rInfo
.aExtraString
+= ",";
1205 rInfo
.aExtraString
+= OUString::number( aPos
.X() );
1206 rInfo
.aExtraString
+= "/";
1207 rInfo
.aExtraString
+= OUString::number( aPos
.Y() );
1208 rInfo
.aExtraString
+= "/";
1209 rInfo
.aExtraString
+= OUString::number( pImp
->nHorizontalSize
);
1210 rInfo
.aExtraString
+= "/";
1211 rInfo
.aExtraString
+= OUString::number( pImp
->nVerticalSize
);
1212 rInfo
.aExtraString
+= ",";
1213 rInfo
.aExtraString
+= OUString::number( pImp
->aSplitSize
.Width() );
1214 rInfo
.aExtraString
+= ";";
1215 rInfo
.aExtraString
+= OUString::number( pImp
->aSplitSize
.Height() );
1218 rInfo
.aExtraString
+= ")";
1221 SfxDockingWindow::~SfxDockingWindow()
1226 void SfxDockingWindow::dispose()
1228 ReleaseChildWindow_Impl();
1229 delete pImp
; pImp
= NULL
;
1230 DockingWindow::dispose();
1233 void SfxDockingWindow::ReleaseChildWindow_Impl()
1235 if ( pMgr
&& pMgr
->GetFrame() == pBindings
->GetActiveFrame() )
1236 pBindings
->SetActiveFrame( NULL
);
1238 if ( pMgr
&& pImp
->pSplitWin
&& pImp
->pSplitWin
->IsItemValid( GetType() ) )
1239 pImp
->pSplitWin
->RemoveWindow(this);
1244 /** This method calculates a resulting alignment for the given mouse position
1245 and tracking rectangle. When changing the alignment it can also be that
1246 the tracking rectangle is changed, so that an altered rectangle is
1247 returned. The user of this class can influence behaviour of this method,
1248 and thus the behavior of his DockinWindow class when docking where the
1249 called virtual method:
1251 SfxDockingWindow :: CalcDockingSize (SfxChildAlignment eAlign)
1253 is overridden (see below).
1255 SfxChildAlignment
SfxDockingWindow::CalcAlignment(const Point
& rPos
, Rectangle
& rRect
)
1257 // calculate hypothetical sizes for different modes
1258 Size
aFloatingSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT
));
1259 Size
aVerticalSize(CalcDockingSize(SfxChildAlignment::LEFT
));
1260 Size
aHorizontalSize(CalcDockingSize(SfxChildAlignment::TOP
));
1262 // check if docking is permitted
1263 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1264 if ( !pWorkWin
->IsDockingAllowed() )
1266 rRect
.SetSize( aFloatingSize
);
1267 return pImp
->GetDockAlignment();
1270 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1271 long nLRBorder
, nTBBorder
;
1272 if ( pImp
->bSplitable
)
1274 // take the smaller size of docked and floating mode
1275 Size aSize
= pImp
->aSplitSize
;
1276 if ( GetFloatingSize().Height() < aSize
.Height() )
1277 aSize
.Height() = GetFloatingSize().Height();
1278 if ( GetFloatingSize().Width() < aSize
.Width() )
1279 aSize
.Width() = GetFloatingSize().Width();
1281 nLRBorder
= aSize
.Width();
1282 nTBBorder
= aSize
.Height();
1286 nLRBorder
= aVerticalSize
.Width();
1287 nTBBorder
= aHorizontalSize
.Height();
1290 // limit border to predefined constant values
1291 if ( nLRBorder
> MAX_TOGGLEAREA_WIDTH
)
1292 nLRBorder
= MAX_TOGGLEAREA_WIDTH
;
1293 if ( nTBBorder
> MAX_TOGGLEAREA_WIDTH
)
1294 nTBBorder
= MAX_TOGGLEAREA_WIDTH
;
1296 // shrink area for floating mode if possible
1297 Rectangle aInRect
= GetInnerRect();
1298 if ( aInRect
.GetWidth() > nLRBorder
)
1299 aInRect
.Left() += nLRBorder
/2;
1300 if ( aInRect
.GetWidth() > nLRBorder
)
1301 aInRect
.Right() -= nLRBorder
/2;
1302 if ( aInRect
.GetHeight() > nTBBorder
)
1303 aInRect
.Top() += nTBBorder
/2;
1304 if ( aInRect
.GetHeight() > nTBBorder
)
1305 aInRect
.Bottom() -= nTBBorder
/2;
1307 // calculate alignment resulting from docking rectangle
1308 bool bBecomesFloating
= false;
1309 SfxChildAlignment eDockAlign
= pImp
->GetDockAlignment();
1310 Rectangle
aDockingRect( rRect
);
1311 if ( !IsFloatingMode() )
1313 // don't use tracking rectangle for alignment check, because it will be too large
1314 // to get a floating mode as result - switch to floating size
1315 // so the calculation only depends on the position of the rectangle, not the current
1316 // docking state of the window
1317 aDockingRect
.SetSize( GetFloatingSize() );
1319 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1320 aDockingRect
.SetPos( pWorkWin
->GetWindow()->OutputToScreenPixel( pWorkWin
->GetWindow()->GetPointerPosPixel() ) );
1323 Point aPos
= aDockingRect
.TopLeft();
1324 Rectangle aIntersect
= GetOuterRect().GetIntersection( aDockingRect
);
1325 if ( aIntersect
.IsEmpty() )
1326 // docking rectangle completely outside docking area -> floating mode
1327 bBecomesFloating
= true;
1330 // create a small test rect around the mouse position and use this one
1331 // instead of the passed rRect to not dock too easily or by accident
1332 Rectangle aSmallDockingRect
;
1333 aSmallDockingRect
.SetSize( Size( MAX_TOGGLEAREA_WIDTH
, MAX_TOGGLEAREA_HEIGHT
) );
1334 Point
aNewPos(rPos
);
1335 aNewPos
.X() -= aSmallDockingRect
.GetWidth()/2;
1336 aNewPos
.Y() -= aSmallDockingRect
.GetHeight()/2;
1337 aSmallDockingRect
.SetPos(rPos
);
1338 Rectangle aIntersectRect
= aInRect
.GetIntersection( aSmallDockingRect
);
1339 if ( aIntersectRect
== aSmallDockingRect
)
1340 // docking rectangle completely inside (shrunk) inner area -> floating mode
1341 bBecomesFloating
= true;
1344 if ( bBecomesFloating
)
1346 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
);
1350 // docking rectangle is in the "sensible area"
1351 Point
aInPosTL( aPos
.X()-aInRect
.Left(), aPos
.Y()-aInRect
.Top() );
1352 Point
aInPosBR( aPos
.X()-aInRect
.Left() + aDockingRect
.GetWidth(), aPos
.Y()-aInRect
.Top() + aDockingRect
.GetHeight() );
1353 Size aInSize
= aInRect
.GetSize();
1354 bool bNoChange
= false;
1356 // check if alignment is still unchanged
1357 switch ( GetAlignment() )
1359 case SfxChildAlignment::LEFT
:
1360 case SfxChildAlignment::FIRSTLEFT
:
1361 case SfxChildAlignment::LASTLEFT
:
1362 if (aInPosTL
.X() <= 0)
1364 eDockAlign
= GetAlignment();
1368 case SfxChildAlignment::TOP
:
1369 case SfxChildAlignment::LOWESTTOP
:
1370 case SfxChildAlignment::HIGHESTTOP
:
1371 if ( aInPosTL
.Y() <= 0)
1373 eDockAlign
= GetAlignment();
1377 case SfxChildAlignment::RIGHT
:
1378 case SfxChildAlignment::FIRSTRIGHT
:
1379 case SfxChildAlignment::LASTRIGHT
:
1380 if ( aInPosBR
.X() >= aInSize
.Width())
1382 eDockAlign
= GetAlignment();
1386 case SfxChildAlignment::BOTTOM
:
1387 case SfxChildAlignment::LOWESTBOTTOM
:
1388 case SfxChildAlignment::HIGHESTBOTTOM
:
1389 if ( aInPosBR
.Y() >= aInSize
.Height())
1391 eDockAlign
= GetAlignment();
1401 // alignment will change, test alignment according to distance of the docking rectangles edges
1402 bool bForbidden
= true;
1403 if ( aInPosTL
.X() <= 0)
1405 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SfxChildAlignment::LEFT
);
1406 bForbidden
= ( eDockAlign
!= SfxChildAlignment::LEFT
&&
1407 eDockAlign
!= SfxChildAlignment::FIRSTLEFT
&&
1408 eDockAlign
!= SfxChildAlignment::LASTLEFT
);
1411 if ( bForbidden
&& aInPosTL
.Y() <= 0)
1413 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SfxChildAlignment::TOP
);
1414 bForbidden
= ( eDockAlign
!= SfxChildAlignment::TOP
&&
1415 eDockAlign
!= SfxChildAlignment::HIGHESTTOP
&&
1416 eDockAlign
!= SfxChildAlignment::LOWESTTOP
);
1419 if ( bForbidden
&& aInPosBR
.X() >= aInSize
.Width())
1421 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SfxChildAlignment::RIGHT
);
1422 bForbidden
= ( eDockAlign
!= SfxChildAlignment::RIGHT
&&
1423 eDockAlign
!= SfxChildAlignment::FIRSTRIGHT
&&
1424 eDockAlign
!= SfxChildAlignment::LASTRIGHT
);
1427 if ( bForbidden
&& aInPosBR
.Y() >= aInSize
.Height())
1429 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SfxChildAlignment::BOTTOM
);
1430 bForbidden
= ( eDockAlign
!= SfxChildAlignment::BOTTOM
&&
1431 eDockAlign
!= SfxChildAlignment::HIGHESTBOTTOM
&&
1432 eDockAlign
!= SfxChildAlignment::LOWESTBOTTOM
);
1435 // the calculated alignment was rejected by the window -> take floating mode
1437 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
);
1441 if ( eDockAlign
== SfxChildAlignment::NOALIGNMENT
)
1443 // In the FloatingMode the tracking rectangle will get the floating
1444 // size. Due to a bug the rRect may only be changed when the
1445 // alignment is changed!
1446 if ( eDockAlign
!= pImp
->GetDockAlignment() )
1447 aDockingRect
.SetSize( aFloatingSize
);
1449 else if ( pImp
->bSplitable
)
1451 sal_uInt16 nLine
, nPos
;
1452 SfxSplitWindow
*pSplitWin
= pWorkWin
->GetSplitWindow_Impl(eDockAlign
);
1453 aPos
= pSplitWin
->ScreenToOutputPixel( aPos
);
1454 if ( pSplitWin
->GetWindowPos( aPos
, nLine
, nPos
) )
1456 // mouse over splitwindow, get line and position
1457 pImp
->nDockLine
= nLine
;
1458 pImp
->nDockPos
= nPos
;
1459 pImp
->bNewLine
= false;
1463 // mouse touches inner border -> create new line
1464 if ( eDockAlign
== GetAlignment() && pImp
->pSplitWin
&&
1465 pImp
->nLine
== pImp
->pSplitWin
->GetLineCount()-1 && pImp
->pSplitWin
->GetWindowCount(pImp
->nLine
) == 1 )
1467 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1468 pImp
->nDockLine
= pImp
->nLine
;
1469 pImp
->nDockPos
= pImp
->nPos
;
1470 pImp
->bNewLine
= false;
1475 pImp
->nDockLine
= pSplitWin
->GetLineCount();
1477 pImp
->bNewLine
= true;
1481 bool bChanged
= pImp
->nLine
!= pImp
->nDockLine
|| pImp
->nPos
!= pImp
->nDockPos
|| eDockAlign
!= GetAlignment();
1482 if ( !bChanged
&& !IsFloatingMode() )
1484 // window only sightly moved, no change of any property
1485 rRect
.SetSize( pImp
->aSplitSize
);
1486 rRect
.SetPos( aDockingRect
.TopLeft() );
1490 // calculate new size and position
1492 Point aPoint
= aDockingRect
.TopLeft();
1493 Size aInnerSize
= GetInnerRect().GetSize();
1494 if ( eDockAlign
== SfxChildAlignment::LEFT
|| eDockAlign
== SfxChildAlignment::RIGHT
)
1496 if ( pImp
->bNewLine
)
1498 // set height to height of free area
1499 aSize
.Height() = aInnerSize
.Height();
1500 aSize
.Width() = pImp
->nHorizontalSize
;
1501 if ( eDockAlign
== SfxChildAlignment::LEFT
)
1503 aPoint
= aInnerRect
.TopLeft();
1507 aPoint
= aInnerRect
.TopRight();
1508 aPoint
.X() -= aSize
.Width();
1513 // get width from splitwindow
1514 aSize
.Width() = pSplitWin
->GetLineSize(nLine
);
1515 aSize
.Height() = pImp
->aSplitSize
.Height();
1520 if ( pImp
->bNewLine
)
1522 // set width to width of free area
1523 aSize
.Width() = aInnerSize
.Width();
1524 aSize
.Height() = pImp
->nVerticalSize
;
1525 if ( eDockAlign
== SfxChildAlignment::TOP
)
1527 aPoint
= aInnerRect
.TopLeft();
1531 aPoint
= aInnerRect
.BottomLeft();
1532 aPoint
.Y() -= aSize
.Height();
1537 // get height from splitwindow
1538 aSize
.Height() = pSplitWin
->GetLineSize(nLine
);
1539 aSize
.Width() = pImp
->aSplitSize
.Width();
1543 aDockingRect
.SetSize( aSize
);
1544 aDockingRect
.SetPos( aPoint
);
1548 // window can be docked, but outside our splitwindows
1549 // tracking rectangle only needs to be modified if alignment was changed
1550 if ( eDockAlign
!= pImp
->GetDockAlignment() )
1552 switch ( eDockAlign
)
1554 case SfxChildAlignment::LEFT
:
1555 case SfxChildAlignment::RIGHT
:
1556 case SfxChildAlignment::FIRSTLEFT
:
1557 aDockingRect
.SetPos( aInnerRect
.TopLeft() );
1558 aDockingRect
.SetSize( aVerticalSize
);
1560 case SfxChildAlignment::LASTLEFT
:
1561 case SfxChildAlignment::FIRSTRIGHT
:
1562 case SfxChildAlignment::LASTRIGHT
:
1564 Point
aPt( aInnerRect
.TopRight() );
1565 aPt
.X() -= aDockingRect
.GetWidth();
1566 aDockingRect
.SetPos( aPt
);
1567 aDockingRect
.SetSize( aVerticalSize
);
1571 case SfxChildAlignment::TOP
:
1572 case SfxChildAlignment::BOTTOM
:
1573 case SfxChildAlignment::LOWESTTOP
:
1574 aDockingRect
.SetPos( aInnerRect
.TopLeft() );
1575 aDockingRect
.SetSize( aHorizontalSize
);
1577 case SfxChildAlignment::HIGHESTTOP
:
1578 case SfxChildAlignment::LOWESTBOTTOM
:
1579 case SfxChildAlignment::HIGHESTBOTTOM
:
1581 Point
aPt( aInnerRect
.BottomLeft() );
1582 aPt
.Y() -= aDockingRect
.GetHeight();
1583 aDockingRect
.SetPos( aPt
);
1584 aDockingRect
.SetSize( aHorizontalSize
);
1593 rRect
= aDockingRect
;
1597 /** Virtual method of the SfxDockingWindow class. This method determines how
1598 the size of the DockingWindows changes depending on the alignment. The base
1599 implementation uses the floating mode, the size of the marked Floating
1600 Size. For horizontal alignment, the width will be the width of the outer
1601 DockingRectangle, with vertical alignment the height will be the height of
1602 the inner DockingRectangle (resulting from the order in which the SFX child
1603 windows are displayed). The other size is set to the current floating-size,
1604 this could changed by a to intervening derived class. The docking size must
1605 be the same for Left/Right and Top/Bottom.
1607 Size
SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign
)
1609 // Note: if the resizing is also possible in the docked state, then the
1610 // Floating-size does also have to be adjusted?
1612 Size aSize
= GetFloatingSize();
1615 case SfxChildAlignment::TOP
:
1616 case SfxChildAlignment::BOTTOM
:
1617 case SfxChildAlignment::LOWESTTOP
:
1618 case SfxChildAlignment::HIGHESTTOP
:
1619 case SfxChildAlignment::LOWESTBOTTOM
:
1620 case SfxChildAlignment::HIGHESTBOTTOM
:
1621 aSize
.Width() = aOuterRect
.Right() - aOuterRect
.Left();
1623 case SfxChildAlignment::LEFT
:
1624 case SfxChildAlignment::RIGHT
:
1625 case SfxChildAlignment::FIRSTLEFT
:
1626 case SfxChildAlignment::LASTLEFT
:
1627 case SfxChildAlignment::FIRSTRIGHT
:
1628 case SfxChildAlignment::LASTRIGHT
:
1629 aSize
.Height() = aInnerRect
.Bottom() - aInnerRect
.Top();
1631 case SfxChildAlignment::NOALIGNMENT
:
1640 /** Virtual method of the SfxDockingWindow class. Here a derived class can
1641 disallow certain alignments. The base implementation does not
1644 SfxChildAlignment
SfxDockingWindow::CheckAlignment(SfxChildAlignment
,
1645 SfxChildAlignment eAlign
)
1650 /** The window is closed when the ChildWindow is destroyed by running the
1651 ChildWindow-slots. If this is method is overridden by a derived class
1652 method, then the SfxDockingDialogWindow: Close() must be called afterwards
1653 if the Close() was not cancelled with "return sal_False".
1655 bool SfxDockingWindow::Close()
1657 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
1661 SfxBoolItem
aValue( pMgr
->GetType(), false);
1662 pBindings
->GetDispatcher_Impl()->Execute(
1663 pMgr
->GetType(), SfxCallMode::RECORD
| SfxCallMode::ASYNCHRON
, &aValue
, 0L );
1667 /** Returns a boundary line to the docked edge and a frame when the Window is in
1668 a docked state. In this way SVLOOK is considered.
1670 void SfxDockingWindow::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& /*rRect*/)
1672 if (pImp
->bSplitable
|| IsFloatingMode())
1675 Rectangle
aRect(Point(0, 0), GetOutputSizePixel());
1676 switch (GetAlignment())
1678 case SfxChildAlignment::TOP
:
1680 rRenderContext
.DrawLine(aRect
.BottomLeft(), aRect
.BottomRight());
1685 case SfxChildAlignment::BOTTOM
:
1687 rRenderContext
.DrawLine(aRect
.TopLeft(), aRect
.TopRight());
1692 case SfxChildAlignment::LEFT
:
1694 rRenderContext
.DrawLine(aRect
.TopRight(), aRect
.BottomRight());
1699 case SfxChildAlignment::RIGHT
:
1701 rRenderContext
.DrawLine(aRect
.TopLeft(), aRect
.BottomLeft());
1710 DecorationView
aView(&rRenderContext
);
1711 aView
.DrawFrame(aRect
, DrawFrameStyle::Out
);
1714 /** With this method, a minimal OutputSize be can set, that is queried in
1715 the Resizing()-Handler.
1717 void SfxDockingWindow::SetMinOutputSizePixel( const Size
& rSize
)
1719 pImp
->aMinSize
= rSize
;
1720 DockingWindow::SetMinOutputSizePixel( rSize
);
1723 /** Set the minimum size which is returned.*/
1724 Size
SfxDockingWindow::GetMinOutputSizePixel() const
1726 return pImp
->aMinSize
;
1729 bool SfxDockingWindow::Notify( NotifyEvent
& rEvt
)
1732 return DockingWindow::Notify( rEvt
);
1734 if ( rEvt
.GetType() == MouseNotifyEvent::GETFOCUS
)
1737 pBindings
->SetActiveFrame( pMgr
->GetFrame() );
1739 if ( pImp
->pSplitWin
)
1740 pImp
->pSplitWin
->SetActiveWindow_Impl( this );
1741 else if (pMgr
!= NULL
)
1742 pMgr
->Activate_Impl();
1744 // In VCL Notify goes first to the window itself, also call the
1745 // base class, otherwise the parent learns nothing
1746 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1747 DockingWindow::Notify( rEvt
);
1750 else if( rEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
1752 // First, allow KeyInput for Dialog functions
1753 if ( !DockingWindow::Notify( rEvt
) && SfxViewShell::Current() )
1754 // then also for valid global accelerators.
1755 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt
.GetKeyEvent() );
1758 else if ( rEvt
.GetType() == MouseNotifyEvent::LOSEFOCUS
&& !HasChildPathFocus() )
1760 pBindings
->SetActiveFrame( NULL
);
1762 pMgr
->Deactivate_Impl();
1765 return DockingWindow::Notify( rEvt
);
1769 sal_uInt16
SfxDockingWindow::GetWinBits_Impl() const
1771 sal_uInt16 nBits
= 0;
1777 void SfxDockingWindow::SetItemSize_Impl( const Size
& rSize
)
1779 pImp
->aSplitSize
= rSize
;
1781 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1782 SfxChildIdentifier eIdent
= SfxChildIdentifier::DOCKINGWINDOW
;
1783 if ( pImp
->bSplitable
)
1784 eIdent
= SfxChildIdentifier::SPLITWINDOW
;
1785 pWorkWin
->ConfigChild_Impl( eIdent
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1788 void SfxDockingWindow::Disappear_Impl()
1790 if ( pImp
->pSplitWin
&& pImp
->pSplitWin
->IsItemValid( GetType() ) )
1791 pImp
->pSplitWin
->RemoveWindow(this);
1794 void SfxDockingWindow::Reappear_Impl()
1796 if ( pImp
->pSplitWin
&& !pImp
->pSplitWin
->IsItemValid( GetType() ) )
1798 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
);
1802 bool SfxDockingWindow::IsAutoHide_Impl() const
1804 if ( pImp
->pSplitWin
)
1805 return !pImp
->pSplitWin
->IsFadeIn();
1810 void SfxDockingWindow::AutoShow_Impl( bool bShow
)
1812 if ( pImp
->pSplitWin
)
1815 pImp
->pSplitWin
->FadeIn();
1817 pImp
->pSplitWin
->FadeOut();
1821 void SfxDockingWindow::StateChanged( StateChangedType nStateChange
)
1823 if ( nStateChange
== StateChangedType::InitShow
)
1826 DockingWindow::StateChanged( nStateChange
);
1829 void SfxDockingWindow::Move()
1832 pImp
->aMoveIdle
.Start();
1835 IMPL_LINK_NOARG_TYPED(SfxDockingWindow
, TimerHdl
, Idle
*, void)
1837 pImp
->aMoveIdle
.Stop();
1838 if ( IsReallyVisible() && IsFloatingMode() )
1840 if( !GetFloatingWindow()->IsRollUp() )
1841 SetFloatingSize( GetOutputSizePixel() );
1842 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
1843 SfxChildIdentifier eIdent
= SfxChildIdentifier::DOCKINGWINDOW
;
1844 if ( pImp
->bSplitable
)
1845 eIdent
= SfxChildIdentifier::SPLITWINDOW
;
1846 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1847 pWorkWin
->ConfigChild_Impl( eIdent
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1851 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */