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 .
21 #include <svl/eitem.hxx>
22 #include <vcl/decoview.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/timer.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/WindowStateConfiguration.hpp>
49 #include <com/sun/star/ui/WindowContentFactoryManager.hpp>
51 #define MAX_TOGGLEAREA_WIDTH 20
52 #define MAX_TOGGLEAREA_HEIGHT 20
54 using namespace ::com::sun::star
;
56 // implemented in 'sfx2/source/appl/childwin.cxx'
57 extern sal_Bool
GetPosSizeFromString( const String
& rStr
, Point
& rPos
, Size
& rSize
);
58 extern sal_Bool
GetSplitSizeFromString( const String
& rStr
, Size
& rSize
);
60 // If you want to change the number you also have to:
61 // - Add new slot ids to sfxsids.hrc
62 // - Add new slots to frmslots.sdi
63 // - Add new slot definitions to sfx.sdi
64 static const int NUM_OF_DOCKINGWINDOWS
= 10;
66 class SfxTitleDockingWindow
: public SfxDockingWindow
68 Window
* m_pWrappedWindow
;
71 SfxTitleDockingWindow(
72 SfxBindings
* pBindings
,
73 SfxChildWindow
* pChildWin
,
76 virtual ~SfxTitleDockingWindow();
78 Window
* GetWrappedWindow() const { return m_pWrappedWindow
; }
79 void SetWrappedWindow(Window
* const pWindow
);
81 virtual void StateChanged( StateChangedType nType
);
82 virtual long Notify( NotifyEvent
& rNEvt
);
83 virtual void Resize();
84 virtual void Resizing( Size
& rSize
);
85 virtual sal_Bool
Close();
96 static bool lcl_getWindowState( const uno::Reference
< container::XNameAccess
>& xWindowStateMgr
, const OUString
& rResourceURL
, WindowState
& rWindowState
)
103 uno::Sequence
< beans::PropertyValue
> aWindowState
;
104 a
= xWindowStateMgr
->getByName( rResourceURL
);
105 if ( a
>>= aWindowState
)
107 for ( sal_Int32 n
= 0; n
< aWindowState
.getLength(); n
++ )
109 if ( aWindowState
[n
].Name
== "UIName" )
111 aWindowState
[n
].Value
>>= rWindowState
.sTitle
;
118 catch ( container::NoSuchElementException
& )
126 SfxDockingWrapper::SfxDockingWrapper( Window
* pParentWnd
,
128 SfxBindings
* pBindings
,
129 SfxChildWinInfo
* pInfo
)
130 : SfxChildWindow( pParentWnd
, nId
)
132 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
133 const OUString
aDockWindowResourceURL( "private:resource/dockingwindow/" );
135 SfxTitleDockingWindow
* pTitleDockWindow
= new SfxTitleDockingWindow( pBindings
, this, pParentWnd
,
136 WB_STDDOCKWIN
| WB_CLIPCHILDREN
| WB_SIZEABLE
| WB_3DLOOK
| WB_ROLLABLE
);
137 pWindow
= pTitleDockWindow
;
138 eChildAlignment
= SFX_ALIGN_NOALIGNMENT
;
140 // Use factory manager to retrieve XWindow factory. That can be used to instantiate
141 // the real window factory.
142 uno::Reference
< lang::XSingleComponentFactory
> xFactoryMgr
= ui::WindowContentFactoryManager::create(xContext
);
144 SfxDispatcher
* pDispatcher
= pBindings
->GetDispatcher();
145 uno::Reference
< frame::XFrame
> xFrame( pDispatcher
->GetFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY
);
146 uno::Sequence
< uno::Any
> aArgs(2);
147 beans::PropertyValue aPropValue
;
148 aPropValue
.Name
= OUString( "Frame" );
149 aPropValue
.Value
= uno::makeAny( xFrame
);
150 aArgs
[0] <<= aPropValue
;
151 aPropValue
.Name
= OUString( "ResourceURL" );
153 // create a resource URL from the nId provided by the sfx2
154 OUString
aResourceURL( aDockWindowResourceURL
);
155 aResourceURL
+= OUString::valueOf(sal_Int32(nId
));
156 aPropValue
.Value
= uno::makeAny( aResourceURL
);
157 aArgs
[1] <<= aPropValue
;
159 uno::Reference
< awt::XWindow
> xWindow
;
162 xWindow
= uno::Reference
< awt::XWindow
>(
163 xFactoryMgr
->createInstanceWithArgumentsAndContext( aArgs
, xContext
),
166 static uno::WeakReference
< frame::XModuleManager2
> m_xModuleManager
;
168 uno::Reference
< frame::XModuleManager2
> xModuleManager( m_xModuleManager
);
169 if ( !xModuleManager
.is() )
171 xModuleManager
= frame::ModuleManager::create(xContext
);
172 m_xModuleManager
= xModuleManager
;
175 static uno::WeakReference
< container::XNameAccess
> m_xWindowStateConfiguration
;
177 uno::Reference
< container::XNameAccess
> xWindowStateConfiguration( m_xWindowStateConfiguration
);
178 if ( !xWindowStateConfiguration
.is() )
180 xWindowStateConfiguration
= ui::WindowStateConfiguration::create( xContext
);
181 m_xWindowStateConfiguration
= xWindowStateConfiguration
;
184 OUString sModuleIdentifier
= xModuleManager
->identify( xFrame
);
186 uno::Reference
< container::XNameAccess
> xModuleWindowState(
187 xWindowStateConfiguration
->getByName( sModuleIdentifier
),
189 if ( xModuleWindowState
.is() )
191 WindowState aDockWinState
;
192 if ( lcl_getWindowState( xModuleWindowState
, aResourceURL
, aDockWinState
))
193 pTitleDockWindow
->SetText( aDockWinState
.sTitle
);
196 catch ( beans::UnknownPropertyException
& )
199 catch ( uno::RuntimeException
& )
202 catch ( uno::Exception
& )
206 Window
* pContentWindow
= VCLUnoHelper::GetWindow(xWindow
);
207 if ( pContentWindow
)
208 pContentWindow
->SetStyle( pContentWindow
->GetStyle() | WB_DIALOGCONTROL
| WB_CHILDDLGCTRL
);
209 pTitleDockWindow
->SetWrappedWindow(pContentWindow
);
211 pWindow
->SetOutputSizePixel( Size( 270, 240 ) );
213 ( ( SfxDockingWindow
* ) pWindow
)->Initialize( pInfo
);
214 SetHideNotDelete( sal_True
);
217 SfxChildWindow
* SfxDockingWrapper::CreateImpl(
218 Window
*pParent
, sal_uInt16 nId
, SfxBindings
*pBindings
, SfxChildWinInfo
* pInfo
)
220 SfxChildWindow
*pWin
= new SfxDockingWrapper(pParent
, nId
, pBindings
, pInfo
);
224 void SfxDockingWrapper::RegisterChildWindow (sal_Bool bVis
, SfxModule
*pMod
, sal_uInt16 nFlags
)
226 // pre-register a couple of docking windows
227 for (int i
=0; i
< NUM_OF_DOCKINGWINDOWS
; i
++ )
229 sal_uInt16 nID
= sal_uInt16(SID_DOCKWIN_START
+i
);
230 SfxChildWinFactory
*pFact
= new SfxChildWinFactory( SfxDockingWrapper::CreateImpl
, nID
, 0xffff );
231 pFact
->aInfo
.nFlags
|= nFlags
;
232 pFact
->aInfo
.bVisible
= bVis
;
233 SfxChildWindow::RegisterChildWindow(pMod
, pFact
);
237 SfxChildWinInfo
SfxDockingWrapper::GetInfo() const
239 SfxChildWinInfo aInfo
= SfxChildWindow::GetInfo();
240 ((SfxDockingWindow
*)GetWindow())->FillInfo( aInfo
);
244 SfxTitleDockingWindow::SfxTitleDockingWindow( SfxBindings
* pBind
,
245 SfxChildWindow
* pChildWin
,
248 SfxDockingWindow( pBind
,
256 SfxTitleDockingWindow::~SfxTitleDockingWindow()
258 delete m_pWrappedWindow
;
261 void SfxTitleDockingWindow::SetWrappedWindow( Window
* const pWindow
)
263 m_pWrappedWindow
= pWindow
;
264 if (m_pWrappedWindow
)
266 m_pWrappedWindow
->SetParent(this);
267 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
268 m_pWrappedWindow
->Show();
272 long SfxTitleDockingWindow::Notify( NotifyEvent
& rNEvt
)
274 return SfxDockingWindow::Notify( rNEvt
);
277 void SfxTitleDockingWindow::StateChanged( StateChangedType nType
)
279 if ( nType
== STATE_CHANGE_INITSHOW
)
281 Window
* pWindow
= GetWrappedWindow();
284 pWindow
->SetSizePixel( GetOutputSizePixel() );
289 SfxDockingWindow::StateChanged(nType
);
292 void SfxTitleDockingWindow::Resize()
294 SfxDockingWindow::Resize();
295 if (m_pWrappedWindow
)
296 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
299 void SfxTitleDockingWindow::Resizing( Size
&rSize
)
301 SfxDockingWindow::Resizing( rSize
);
302 if (m_pWrappedWindow
)
303 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
306 sal_Bool
SfxTitleDockingWindow::Close()
308 return SfxDockingWindow::Close();
313 struct ChildrenRegisteredMap
: public rtl::Static
< bool, ChildrenRegisteredMap
> {};
316 static bool lcl_checkDockingWindowID( sal_uInt16 nID
)
318 if (nID
< SID_DOCKWIN_START
|| nID
>= sal_uInt16(SID_DOCKWIN_START
+NUM_OF_DOCKINGWINDOWS
))
324 static SfxWorkWindow
* lcl_getWorkWindowFromXFrame( const uno::Reference
< frame::XFrame
>& rFrame
)
326 // We need to find the corresponding SfxFrame of our XFrame
327 SfxFrame
* pFrame
= SfxFrame::GetFirst();
328 SfxFrame
* pXFrame
= 0;
331 uno::Reference
< frame::XFrame
> xViewShellFrame( pFrame
->GetFrameInterface() );
332 if ( xViewShellFrame
== rFrame
)
338 pFrame
= SfxFrame::GetNext( *pFrame
);
341 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
343 return pXFrame
->GetWorkWindow_Impl();
349 Factory function used by the framework layout manager to "create" a docking window with a special name.
350 The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
351 in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
353 void SAL_CALL
SfxDockingWindowFactory( const uno::Reference
< frame::XFrame
>& rFrame
, const OUString
& rDockingWindowName
)
355 SolarMutexGuard aGuard
;
356 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
358 // Check the range of the provided ID otherwise nothing will happen
359 if ( lcl_checkDockingWindowID( nID
))
361 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
364 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
367 // Register window at the workwindow child window list
368 pWorkWindow
->SetChildWindow_Impl( nID
, true, false );
375 Function used by the framework layout manager to determine the visibility state of a docking window with
376 a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
377 range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
379 bool SAL_CALL
IsDockingWindowVisible( const uno::Reference
< frame::XFrame
>& rFrame
, const OUString
& rDockingWindowName
)
381 SolarMutexGuard aGuard
;
383 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
385 // Check the range of the provided ID otherwise nothing will happen
386 if ( lcl_checkDockingWindowID( nID
))
388 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
391 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
400 class SfxDockingWindow_Impl
402 friend class SfxDockingWindow
;
404 SfxChildAlignment eLastAlignment
;
405 SfxChildAlignment eDockAlignment
;
406 sal_Bool bConstructed
;
408 SfxSplitWindow
* pSplitWin
;
412 // The following members are only valid in the time from startDocking to
416 long nHorizontalSize
;
420 sal_uInt16 nDockLine
;
423 sal_Bool bDockingPrevented
;
426 SfxChildAlignment
GetLastAlignment() const
427 { return eLastAlignment
; }
428 void SetLastAlignment(SfxChildAlignment eAlign
)
429 { eLastAlignment
= eAlign
; }
430 SfxChildAlignment
GetDockAlignment() const
431 { return eDockAlignment
; }
432 void SetDockAlignment(SfxChildAlignment eAlign
)
433 { eDockAlignment
= eAlign
; }
436 //-------------------------------------------------------------------------
438 void SfxDockingWindow::Resize()
442 This virtual method of the class FloatingWindow keeps track of changes in
443 FloatingSize. If this method is overridden by a derived class,
444 then the SfxFloatingWindow: Resize() must also be called.
447 DockingWindow::Resize();
449 if ( pImp
->bConstructed
&& pMgr
)
451 if ( IsFloatingMode() )
453 // start timer for saving window status information
454 pImp
->aMoveTimer
.Start();
458 Size
aSize( GetSizePixel() );
459 switch ( pImp
->GetDockAlignment() )
462 case SFX_ALIGN_FIRSTLEFT
:
463 case SFX_ALIGN_LASTLEFT
:
464 case SFX_ALIGN_RIGHT
:
465 case SFX_ALIGN_FIRSTRIGHT
:
466 case SFX_ALIGN_LASTRIGHT
:
467 pImp
->nHorizontalSize
= aSize
.Width();
468 pImp
->aSplitSize
= aSize
;
471 case SFX_ALIGN_LOWESTTOP
:
472 case SFX_ALIGN_HIGHESTTOP
:
473 case SFX_ALIGN_BOTTOM
:
474 case SFX_ALIGN_HIGHESTBOTTOM
:
475 case SFX_ALIGN_LOWESTBOTTOM
:
476 pImp
->nVerticalSize
= aSize
.Height();
477 pImp
->aSplitSize
= aSize
;
486 //-------------------------------------------------------------------------
488 sal_Bool
SfxDockingWindow::PrepareToggleFloatingMode()
492 This virtual method of the class DockingWindow makes it possible to
493 intervene in the switching of the floating mode.
494 If this method is overridden by a derived class,
495 then the SfxDockingWindow::PrepareToggleFloatingMode() must be called
496 afterwards, if not FALSE is returned.
500 if (!pImp
->bConstructed
)
503 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr
)
506 if ( pImp
->bDockingPrevented
)
509 if (!IsFloatingMode())
511 // Test, if FloatingMode is permitted.
512 if ( CheckAlignment(GetAlignment(),SFX_ALIGN_NOALIGNMENT
) != SFX_ALIGN_NOALIGNMENT
)
515 if ( pImp
->pSplitWin
)
517 // The DockingWindow is inside a SplitWindow and will be teared of.
518 pImp
->pSplitWin
->RemoveWindow(this/*, sal_False*/);
524 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
526 // Test if it is allowed to dock,
527 if (CheckAlignment(GetAlignment(),pImp
->GetLastAlignment()) == SFX_ALIGN_NOALIGNMENT
)
530 // Test, if the Workwindow allows for docking at the moment.
531 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
532 if ( !pWorkWin
->IsDockingAllowed() || !pWorkWin
->IsInternalDockingAllowed() )
539 //-------------------------------------------------------------------------
541 void SfxDockingWindow::ToggleFloatingMode()
545 This virtual method of the DockingWindow class sets the internal data of
546 the SfxDockingWindow and ensures the correct alignment on the parent window.
547 Through PrepareToggleFloatMode and Initialize it is ensured that
548 pImp-> GetLastAlignment() always delivers an allowed alignment. If this
549 method is overloaded from a derived class, then first the
550 SfxDockingWindow:: ToggleFloatingMode() must be called.
553 if ( !pImp
->bConstructed
|| !pMgr
)
554 return; // No Handler call
556 // Remember old alignment and then switch.
557 // SV has already switched, but the alignment SfxDockingWindow is still
558 // the old one. What I was before?
559 SfxChildAlignment eLastAlign
= GetAlignment();
561 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
562 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
563 if ( pImp
->bSplitable
)
564 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
566 if (IsFloatingMode())
568 SetAlignment(SFX_ALIGN_NOALIGNMENT
);
569 if ( !pImp
->aWinState
.isEmpty() )
570 GetFloatingWindow()->SetWindowState( pImp
->aWinState
);
572 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
576 if (pImp
->GetDockAlignment() == eLastAlign
)
578 // If ToggleFloatingMode was called, but the DockAlignment still
579 // is unchanged, then this means that it must have been a toggling
580 // through DClick, so use last alignment
581 SetAlignment (pImp
->GetLastAlignment());
582 if ( !pImp
->bSplitable
)
583 SetSizePixel( CalcDockingSize(GetAlignment()) );
588 // Toggling was triggered by dragging
589 pImp
->nLine
= pImp
->nDockLine
;
590 pImp
->nPos
= pImp
->nDockPos
;
591 SetAlignment (pImp
->GetDockAlignment());
594 if ( pImp
->bSplitable
)
596 // The DockingWindow is now in a SplitWindow
597 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
599 // The LastAlignment is still the last docked
600 SfxSplitWindow
*pSplit
= pWorkWin
->GetSplitWindow_Impl(pImp
->GetLastAlignment());
602 DBG_ASSERT( pSplit
, "LastAlignment is not correct!" );
603 if ( pSplit
&& pSplit
!= pImp
->pSplitWin
)
604 pSplit
->ReleaseWindow_Impl(this);
605 if ( pImp
->GetDockAlignment() == eLastAlign
)
606 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
);
608 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
, pImp
->nLine
, pImp
->nPos
, pImp
->bNewLine
);
609 if ( !pImp
->pSplitWin
->IsFadeIn() )
610 pImp
->pSplitWin
->FadeIn();
614 // Keep the old alignment for the next toggle; set it only now due to the
615 // unregister SplitWindow!
616 pImp
->SetLastAlignment(eLastAlign
);
618 // Reset DockAlignment, if EndDocking is still called
619 pImp
->SetDockAlignment(GetAlignment());
621 // Dock or undock SfxChildWindow correctly.
623 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_TOGGLEFLOATMODE
, pMgr
->GetType() );
626 //-------------------------------------------------------------------------
628 void SfxDockingWindow::StartDocking()
632 This virtual method of the DockingWindow class takes the inner and outer
633 docking rectangle from the parent window. If this method is overloaded by a
634 a derived class, then SfxDockingWindow:StartDocking() has to be called at
638 if ( !pImp
->bConstructed
|| !pMgr
)
640 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
641 if ( pImp
->bSplitable
)
642 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
643 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
644 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_SETDOCKINGRECTS
, pMgr
->GetType() );
645 pImp
->SetDockAlignment(GetAlignment());
647 if ( pImp
->pSplitWin
)
649 // Get the current docking data
650 pImp
->pSplitWin
->GetWindowPos(this, pImp
->nLine
, pImp
->nPos
);
651 pImp
->nDockLine
= pImp
->nLine
;
652 pImp
->nDockPos
= pImp
->nPos
;
653 pImp
->bNewLine
= sal_False
;
657 //-------------------------------------------------------------------------
659 sal_Bool
SfxDockingWindow::Docking( const Point
& rPos
, Rectangle
& rRect
)
663 This virtual method of the DockingWindow class calculates the current
664 tracking rectangle. For this purpose the method CalcAlignment(RPOs, rRect)
665 is used, the behavior can be influenced by the derived classes (see below).
666 This method should if possible not be overwritten.
669 if ( Application::IsInModalMode() )
672 if ( !pImp
->bConstructed
|| !pMgr
)
674 rRect
.SetSize( Size() );
675 return IsFloatingMode();
678 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
679 if ( pImp
->bDockingPrevented
|| !pWorkWin
->IsInternalDockingAllowed() )
682 sal_Bool bFloatMode
= sal_False
;
684 if ( GetOuterRect().IsInside( rPos
) && !IsDockingPrevented() )
686 // Mouse within OuterRect: calculate Alignment and Rectangle
687 SfxChildAlignment eAlign
= CalcAlignment(rPos
, rRect
);
688 if (eAlign
== SFX_ALIGN_NOALIGNMENT
)
689 bFloatMode
= sal_True
;
690 pImp
->SetDockAlignment(eAlign
);
694 // Mouse is not within OuterRect: must be FloatingWindow
696 if (CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
) != SFX_ALIGN_NOALIGNMENT
)
698 bFloatMode
= sal_True
;
699 if ( SFX_ALIGN_NOALIGNMENT
!= pImp
->GetDockAlignment() )
701 // Due to a bug the rRect may only be changed when the
702 // alignment is changed!
703 pImp
->SetDockAlignment(SFX_ALIGN_NOALIGNMENT
);
704 rRect
.SetSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT
));
708 if ( !pImp
->bSplitable
)
710 // For individually docked window the position is set through the
711 // alignment and the docking rectangle.
712 Size aSize
= rRect
.GetSize();
715 switch ( pImp
->GetDockAlignment() )
718 case SFX_ALIGN_FIRSTLEFT
:
719 case SFX_ALIGN_LASTLEFT
:
720 aPos
= aInnerRect
.TopLeft();
721 if ( pImp
->GetDockAlignment() == GetAlignment() )
722 aPos
.X() -= aSize
.Width();
726 case SFX_ALIGN_LOWESTTOP
:
727 case SFX_ALIGN_HIGHESTTOP
:
728 aPos
= Point(aOuterRect
.Left(), aInnerRect
.Top());
729 if ( pImp
->GetDockAlignment() == GetAlignment() )
730 aPos
.Y() -= aSize
.Height();
733 case SFX_ALIGN_RIGHT
:
734 case SFX_ALIGN_FIRSTRIGHT
:
735 case SFX_ALIGN_LASTRIGHT
:
736 aPos
= Point(aInnerRect
.Right() - rRect
.GetSize().Width(),
738 if ( pImp
->GetDockAlignment() == GetAlignment() )
739 aPos
.X() += aSize
.Width();
742 case SFX_ALIGN_BOTTOM
:
743 case SFX_ALIGN_HIGHESTBOTTOM
:
744 case SFX_ALIGN_LOWESTBOTTOM
:
745 aPos
= Point(aOuterRect
.Left(),
746 aInnerRect
.Bottom() - rRect
.GetSize().Height());
747 if ( pImp
->GetDockAlignment() == GetAlignment() )
748 aPos
.Y() += aSize
.Height();
760 //-------------------------------------------------------------------------
762 void SfxDockingWindow::EndDocking( const Rectangle
& rRect
, sal_Bool bFloatMode
)
766 Virtual method of the DockingWindow class ensures the correct alignment on
767 the parent window. If this method is overloaded by a derived class, then
768 SfxDockingWindow::EndDocking() must be called first.
771 if ( !pImp
->bConstructed
|| IsDockingCanceled() || !pMgr
)
774 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
775 sal_Bool bReArrange
= sal_False
;
776 if ( pImp
->bSplitable
)
778 // If the alignment changes and the window is in a docked state in a
779 // SplitWindow, then it must be re-registered. If it is docked again,
780 // PrepareToggleFloatingMode() and ToggleFloatingMode() preform the
783 bReArrange
= sal_True
;
788 if ( GetAlignment() != pImp
->GetDockAlignment() )
790 // before Show() is called must the reassignment have been made,
791 // therefore the base class can not be called
792 if ( IsFloatingMode() || !pImp
->bSplitable
)
793 Show( sal_False
, SHOW_NOFOCUSCHANGE
);
795 // Set the size for toggling.
796 pImp
->aSplitSize
= rRect
.GetSize();
797 if ( IsFloatingMode() )
799 SetFloatingMode( bFloatMode
);
800 if ( IsFloatingMode() || !pImp
->bSplitable
)
801 Show( sal_True
, SHOW_NOFOCUSCHANGE
);
805 pImp
->pSplitWin
->RemoveWindow(this,sal_False
);
806 pImp
->nLine
= pImp
->nDockLine
;
807 pImp
->nPos
= pImp
->nDockPos
;
808 pImp
->pSplitWin
->ReleaseWindow_Impl(this);
809 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(pImp
->GetDockAlignment());
810 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
, pImp
->nDockLine
, pImp
->nDockPos
, pImp
->bNewLine
);
811 if ( !pImp
->pSplitWin
->IsFadeIn() )
812 pImp
->pSplitWin
->FadeIn();
815 else if ( pImp
->nLine
!= pImp
->nDockLine
|| pImp
->nPos
!= pImp
->nDockPos
|| pImp
->bNewLine
)
817 // Moved within Splitwindows
818 if ( pImp
->nLine
!= pImp
->nDockLine
)
819 pImp
->aSplitSize
= rRect
.GetSize();
820 pImp
->pSplitWin
->MoveWindow( this, pImp
->aSplitSize
, pImp
->nDockLine
, pImp
->nDockPos
, pImp
->bNewLine
);
825 pImp
->bEndDocked
= sal_True
;
826 DockingWindow::EndDocking(rRect
, bFloatMode
);
827 pImp
->bEndDocked
= sal_False
;
830 SetAlignment( IsFloatingMode() ? SFX_ALIGN_NOALIGNMENT
: pImp
->GetDockAlignment() );
833 //-------------------------------------------------------------------------
835 void SfxDockingWindow::Resizing( Size
& /*rSize*/ )
839 Virtual method of the DockingWindow class. Here, the interactive resize in
840 FloatingMode can be influenced, for example by only allowing for discrete
841 values for width and / or height. The base implementation prevents that the
842 output size is smaller than one set with SetMinOutputSizePixel().
849 //-------------------------------------------------------------------------
851 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
852 Window
* pParent
, WinBits nWinBits
) :
853 DockingWindow (pParent
, nWinBits
),
860 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
861 required because the docking is implemented in Sfx through SfxChildWindows.
865 if ( !GetHelpId().isEmpty() )
867 SetUniqueId( GetHelpId() );
872 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher()->GetFrame();
873 SfxSlotPool
* pSlotPool
= pViewFrame
->GetObjectShell()->GetModule()->GetSlotPool();
874 const SfxSlot
* pSlot
= pSlotPool
->GetSlot( pCW
->GetType() );
877 OString
aCmd("SFXDOCKINGWINDOW_");
878 aCmd
+= pSlot
->GetUnoName();
883 pImp
= new SfxDockingWindow_Impl
;
884 pImp
->bConstructed
= sal_False
;
886 pImp
->bEndDocked
= sal_False
;
887 pImp
->bDockingPrevented
= sal_False
;
889 pImp
->bSplitable
= sal_True
;
891 // Initially set to default, the alignment is set in the subclass
892 pImp
->nLine
= pImp
->nDockLine
= 0;
893 pImp
->nPos
= pImp
->nDockPos
= 0;
894 pImp
->bNewLine
= sal_False
;
895 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
896 pImp
->aMoveTimer
.SetTimeout(50);
897 pImp
->aMoveTimer
.SetTimeoutHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
900 //-------------------------------------------------------------------------
902 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
903 Window
* pParent
, const ResId
& rResId
) :
904 DockingWindow(pParent
, rResId
),
911 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
912 required because the docking is implemented in Sfx through SfxChildWindows.
916 if ( !GetHelpId().isEmpty() )
918 SetUniqueId( GetHelpId() );
923 SfxViewFrame
* pViewFrame
= pBindings
->GetDispatcher()->GetFrame();
924 SfxSlotPool
* pSlotPool
= pViewFrame
->GetObjectShell()->GetModule()->GetSlotPool();
925 const SfxSlot
* pSlot
= pSlotPool
->GetSlot( pCW
->GetType() );
928 OString
aCmd("SFXDOCKINGWINDOW_");
929 aCmd
+= pSlot
->GetUnoName();
934 pImp
= new SfxDockingWindow_Impl
;
935 pImp
->bConstructed
= sal_False
;
937 pImp
->bEndDocked
= sal_False
;
938 pImp
->bDockingPrevented
= sal_False
;
940 pImp
->bSplitable
= sal_True
;
942 // Initially set to default, the alignment is set in the subclass
943 pImp
->nLine
= pImp
->nDockLine
= 0;
944 pImp
->nPos
= pImp
->nDockPos
= 0;
945 pImp
->bNewLine
= sal_False
;
946 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
947 pImp
->aMoveTimer
.SetTimeout(50);
948 pImp
->aMoveTimer
.SetTimeoutHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
951 //-------------------------------------------------------------------------
953 void SfxDockingWindow::Initialize(SfxChildWinInfo
*pInfo
)
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
964 pImp
->SetDockAlignment( SFX_ALIGN_NOALIGNMENT
);
965 pImp
->bConstructed
= sal_True
;
969 if ( pInfo
->nFlags
& SFX_CHILDWIN_FORCEDOCK
)
970 pImp
->bDockingPrevented
= sal_True
;
972 pImp
->aSplitSize
= GetOutputSizePixel();
973 if ( !GetFloatingSize().Width() )
975 Size
aMinSize( GetMinOutputSizePixel() );
976 SetFloatingSize( pImp
->aSplitSize
);
977 if ( pImp
->aSplitSize
.Width() < aMinSize
.Width() )
978 pImp
->aSplitSize
.Width() = aMinSize
.Width();
979 if ( pImp
->aSplitSize
.Height() < aMinSize
.Height() )
980 pImp
->aSplitSize
.Height() = aMinSize
.Height();
983 sal_Bool
bVertHorzRead( sal_False
);
984 if ( pInfo
->aExtraString
.Len() )
986 // get information about alignment, split size and position in SplitWindow
988 sal_uInt16 nPos
= pInfo
->aExtraString
.SearchAscii("AL:");
989 if ( nPos
!= STRING_NOTFOUND
)
991 // alignment information
992 sal_uInt16 n1
= pInfo
->aExtraString
.Search('(', nPos
);
993 if ( n1
!= STRING_NOTFOUND
)
995 sal_uInt16 n2
= pInfo
->aExtraString
.Search(')', n1
);
996 if ( n2
!= STRING_NOTFOUND
)
998 // extract alignment information from extrastring
999 aStr
= pInfo
->aExtraString
.Copy(nPos
, n2
- nPos
+ 1);
1000 pInfo
->aExtraString
.Erase(nPos
, n2
- nPos
+ 1);
1001 aStr
.Erase(nPos
, n1
-nPos
+1);
1008 // accept window state only if alignment is also set
1009 pImp
->aWinState
= pInfo
->aWinState
;
1011 // check for valid alignment
1012 SfxChildAlignment eLocalAlignment
= (SfxChildAlignment
) (sal_uInt16
) aStr
.ToInt32();
1013 if ( pImp
->bDockingPrevented
)
1014 // docking prevented, ignore old configuration and take alignment from default
1017 SetAlignment( eLocalAlignment
);
1019 SfxChildAlignment eAlign
= CheckAlignment(GetAlignment(),GetAlignment());
1020 if ( eAlign
!= GetAlignment() )
1022 OSL_FAIL("Invalid Alignment!");
1023 SetAlignment( eAlign
);
1027 // get last alignment (for toggeling)
1028 nPos
= aStr
.Search(',');
1029 if ( nPos
!= STRING_NOTFOUND
)
1031 aStr
.Erase(0, nPos
+1);
1032 pImp
->SetLastAlignment( (SfxChildAlignment
) (sal_uInt16
) aStr
.ToInt32() );
1035 nPos
= aStr
.Search(',');
1036 if ( nPos
!= STRING_NOTFOUND
)
1038 // get split size and position in SplitWindow
1040 aStr
.Erase(0, nPos
+1);
1041 if ( GetPosSizeFromString( aStr
, aPos
, pImp
->aSplitSize
) )
1043 pImp
->nLine
= pImp
->nDockLine
= (sal_uInt16
) aPos
.X();
1044 pImp
->nPos
= pImp
->nDockPos
= (sal_uInt16
) aPos
.Y();
1045 pImp
->nVerticalSize
= pImp
->aSplitSize
.Height();
1046 pImp
->nHorizontalSize
= pImp
->aSplitSize
.Width();
1047 if ( GetSplitSizeFromString( aStr
, pImp
->aSplitSize
))
1048 bVertHorzRead
= sal_True
;
1053 OSL_FAIL( "Information is missing!" );
1057 if ( !bVertHorzRead
)
1059 pImp
->nVerticalSize
= pImp
->aSplitSize
.Height();
1060 pImp
->nHorizontalSize
= pImp
->aSplitSize
.Width();
1063 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1064 if ( GetAlignment() != SFX_ALIGN_NOALIGNMENT
)
1066 // check if SfxWorkWindow is able to allow docking at its border
1068 !pWorkWin
->IsDockingAllowed() ||
1069 !pWorkWin
->IsInternalDockingAllowed() ||
1070 ( (GetFloatStyle() & WB_STANDALONE
) && Application::IsInModalMode()) )
1072 SetAlignment( SFX_ALIGN_NOALIGNMENT
);
1076 // detect floating mode
1077 // toggeling mode will not execute code in handlers, because pImp->bConstructed is not set yet
1078 sal_Bool bFloatMode
= IsFloatingMode();
1079 if ( bFloatMode
!= ((GetAlignment() == SFX_ALIGN_NOALIGNMENT
)) )
1081 bFloatMode
= !bFloatMode
;
1082 SetFloatingMode( bFloatMode
);
1085 if ( !pImp
->aWinState
.isEmpty() )
1086 GetFloatingWindow()->SetWindowState( pImp
->aWinState
);
1088 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
1092 if ( IsFloatingMode() )
1094 // validate last alignment
1095 SfxChildAlignment eLastAlign
= pImp
->GetLastAlignment();
1096 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1097 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_LEFT
);
1098 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1099 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_RIGHT
);
1100 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1101 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_TOP
);
1102 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1103 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_BOTTOM
);
1104 pImp
->SetLastAlignment(eLastAlign
);
1108 // docked window must have NOALIGNMENT as last alignment
1109 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
1111 if ( pImp
->bSplitable
)
1113 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
1114 pImp
->pSplitWin
->InsertWindow(this, pImp
->aSplitSize
);
1118 //?????? Currently not supported
1119 // Window is docked individually; size is calculated.
1120 // It must therefore be initialized with the DloatingSize if
1121 // someone relies on it that a reasonable size is set
1122 SetSizePixel(GetFloatingSize());
1123 SetSizePixel(CalcDockingSize(GetAlignment()));
1128 pImp
->SetDockAlignment( GetAlignment() );
1131 void SfxDockingWindow::Initialize_Impl()
1135 pImp
->bConstructed
= sal_True
;
1139 FloatingWindow
* pFloatWin
= GetFloatingWindow();
1140 sal_Bool bSet
= sal_False
;
1143 bSet
= !pFloatWin
->IsDefaultPos();
1147 Point aPos
= GetFloatingPos();
1148 if ( aPos
!= Point() )
1154 SfxViewFrame
*pFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
1155 Window
* pEditWin
= pFrame
->GetViewShell()->GetWindow();
1156 Point aPos
= pEditWin
->OutputToScreenPixel( pEditWin
->GetPosPixel() );
1157 aPos
= GetParent()->ScreenToOutputPixel( aPos
);
1158 SetFloatingPos( aPos
);
1163 // initialize floating window
1164 if ( pImp
->aWinState
.isEmpty() )
1165 // window state never set before, get if from defaults
1166 pImp
->aWinState
= pFloatWin
->GetWindowState();
1168 // trick: use VCL method SetWindowState to adjust position and size
1169 pFloatWin
->SetWindowState( pImp
->aWinState
);
1171 // remember floating size for calculating alignment and tracking rectangle
1172 SetFloatingSize( pFloatWin
->GetSizePixel() );
1176 // allow calling of docking handlers
1177 pImp
->bConstructed
= sal_True
;
1180 //-------------------------------------------------------------------------
1182 void SfxDockingWindow::FillInfo(SfxChildWinInfo
& rInfo
) const
1186 Fills a SfxChildWinInfo with specific data from SfxDockingWindow,
1187 so that it can be written in the INI file. It is assumed that rinfo
1188 receives all other possible relevant data in the ChildWindow class.
1189 Insertions are marked with size and the ZoomIn flag.
1190 If this method is overridden, the base implementation must be called first.
1197 if ( GetFloatingWindow() && pImp
->bConstructed
)
1198 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
1200 rInfo
.aWinState
= pImp
->aWinState
;
1201 rInfo
.aExtraString
= "AL:(";
1202 rInfo
.aExtraString
+= OUString::number((sal_uInt16
) GetAlignment());
1203 rInfo
.aExtraString
+= ',';
1204 rInfo
.aExtraString
+= OUString::number ((sal_uInt16
) pImp
->GetLastAlignment());
1205 if ( pImp
->bSplitable
)
1207 Point
aPos(pImp
->nLine
, pImp
->nPos
);
1208 rInfo
.aExtraString
+= ',';
1209 rInfo
.aExtraString
+= OUString::number( aPos
.X() );
1210 rInfo
.aExtraString
+= '/';
1211 rInfo
.aExtraString
+= OUString::number( aPos
.Y() );
1212 rInfo
.aExtraString
+= '/';
1213 rInfo
.aExtraString
+= OUString::number( pImp
->nHorizontalSize
);
1214 rInfo
.aExtraString
+= '/';
1215 rInfo
.aExtraString
+= OUString::number( pImp
->nVerticalSize
);
1216 rInfo
.aExtraString
+= ',';
1217 rInfo
.aExtraString
+= OUString::number( pImp
->aSplitSize
.Width() );
1218 rInfo
.aExtraString
+= ';';
1219 rInfo
.aExtraString
+= OUString::number( pImp
->aSplitSize
.Height() );
1222 rInfo
.aExtraString
+= ')';
1225 //-------------------------------------------------------------------------
1227 SfxDockingWindow::~SfxDockingWindow()
1229 ReleaseChildWindow_Impl();
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 //-------------------------------------------------------------------------
1246 SfxChildAlignment
SfxDockingWindow::CalcAlignment(const Point
& rPos
, Rectangle
& rRect
)
1250 This method calculates a resulting alignment for the given mouse position
1251 and tracking rectangle. When changing the alignment it can also be that
1252 the tracking rectangle is changed, so that an altered rectangle is
1253 returned. The user of this class can influence behaviour of this method,
1254 and thus the behavior of his DockinWindow class when docking where the
1255 called virtual method:
1257 SfxDockingWindow :: CalcDockingSize (SfxChildAlignment eAlign)
1259 is overridden (see below).
1263 // calculate hypothetical sizes for different modes
1264 Size
aFloatingSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT
));
1265 Size
aVerticalSize(CalcDockingSize(SFX_ALIGN_LEFT
));
1266 Size
aHorizontalSize(CalcDockingSize(SFX_ALIGN_TOP
));
1268 // check if docking is permitted
1269 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1270 if ( !pWorkWin
->IsDockingAllowed() )
1272 rRect
.SetSize( aFloatingSize
);
1273 return pImp
->GetDockAlignment();
1276 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1277 long nLRBorder
, nTBBorder
;
1278 if ( pImp
->bSplitable
)
1280 // take the smaller size of docked and floating mode
1281 Size aSize
= pImp
->aSplitSize
;
1282 if ( GetFloatingSize().Height() < aSize
.Height() )
1283 aSize
.Height() = GetFloatingSize().Height();
1284 if ( GetFloatingSize().Width() < aSize
.Width() )
1285 aSize
.Width() = GetFloatingSize().Width();
1287 nLRBorder
= aSize
.Width();
1288 nTBBorder
= aSize
.Height();
1292 nLRBorder
= aVerticalSize
.Width();
1293 nTBBorder
= aHorizontalSize
.Height();
1296 // limit border to predefined constant values
1297 if ( nLRBorder
> MAX_TOGGLEAREA_WIDTH
)
1298 nLRBorder
= MAX_TOGGLEAREA_WIDTH
;
1299 if ( nTBBorder
> MAX_TOGGLEAREA_WIDTH
)
1300 nTBBorder
= MAX_TOGGLEAREA_WIDTH
;
1302 // shrink area for floating mode if possible
1303 Rectangle aInRect
= GetInnerRect();
1304 if ( aInRect
.GetWidth() > nLRBorder
)
1305 aInRect
.Left() += nLRBorder
/2;
1306 if ( aInRect
.GetWidth() > nLRBorder
)
1307 aInRect
.Right() -= nLRBorder
/2;
1308 if ( aInRect
.GetHeight() > nTBBorder
)
1309 aInRect
.Top() += nTBBorder
/2;
1310 if ( aInRect
.GetHeight() > nTBBorder
)
1311 aInRect
.Bottom() -= nTBBorder
/2;
1313 // calculate alignment resulting from docking rectangle
1314 sal_Bool bBecomesFloating
= sal_False
;
1315 SfxChildAlignment eDockAlign
= pImp
->GetDockAlignment();
1316 Rectangle
aDockingRect( rRect
);
1317 if ( !IsFloatingMode() )
1319 // don't use tracking rectangle for alignment check, because it will be too large
1320 // to get a floating mode as result - switch to floating size
1321 // so the calculation only depends on the position of the rectangle, not the current
1322 // docking state of the window
1323 aDockingRect
.SetSize( GetFloatingSize() );
1325 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1326 aDockingRect
.SetPos( pWorkWin
->GetWindow()->OutputToScreenPixel( pWorkWin
->GetWindow()->GetPointerPosPixel() ) );
1329 Point aPos
= aDockingRect
.TopLeft();
1330 Rectangle aIntersect
= GetOuterRect().GetIntersection( aDockingRect
);
1331 if ( aIntersect
.IsEmpty() )
1332 // docking rectangle completely outside docking area -> floating mode
1333 bBecomesFloating
= sal_True
;
1336 // create a small test rect around the mouse position and use this one
1337 // instead of the passed rRect to not dock too easily or by accident
1338 Rectangle aSmallDockingRect
;
1339 aSmallDockingRect
.SetSize( Size( MAX_TOGGLEAREA_WIDTH
, MAX_TOGGLEAREA_HEIGHT
) );
1340 Point
aNewPos(rPos
);
1341 aNewPos
.X() -= aSmallDockingRect
.GetWidth()/2;
1342 aNewPos
.Y() -= aSmallDockingRect
.GetHeight()/2;
1343 aSmallDockingRect
.SetPos(rPos
);
1344 Rectangle aIntersectRect
= aInRect
.GetIntersection( aSmallDockingRect
);
1345 if ( aIntersectRect
== aSmallDockingRect
)
1346 // docking rectangle completely inside (shrinked) inner area -> floating mode
1347 bBecomesFloating
= sal_True
;
1350 if ( bBecomesFloating
)
1352 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
);
1356 // docking rectangle is in the "sensible area"
1357 Point
aInPosTL( aPos
.X()-aInRect
.Left(), aPos
.Y()-aInRect
.Top() );
1358 Point
aInPosBR( aPos
.X()-aInRect
.Left() + aDockingRect
.GetWidth(), aPos
.Y()-aInRect
.Top() + aDockingRect
.GetHeight() );
1359 Size aInSize
= aInRect
.GetSize();
1360 sal_Bool bNoChange
= sal_False
;
1362 // check if alignment is still unchanged
1363 switch ( GetAlignment() )
1365 case SFX_ALIGN_LEFT
:
1366 case SFX_ALIGN_FIRSTLEFT
:
1367 case SFX_ALIGN_LASTLEFT
:
1368 if (aInPosTL
.X() <= 0)
1370 eDockAlign
= GetAlignment();
1371 bNoChange
= sal_True
;
1375 case SFX_ALIGN_LOWESTTOP
:
1376 case SFX_ALIGN_HIGHESTTOP
:
1377 if ( aInPosTL
.Y() <= 0)
1379 eDockAlign
= GetAlignment();
1380 bNoChange
= sal_True
;
1383 case SFX_ALIGN_RIGHT
:
1384 case SFX_ALIGN_FIRSTRIGHT
:
1385 case SFX_ALIGN_LASTRIGHT
:
1386 if ( aInPosBR
.X() >= aInSize
.Width())
1388 eDockAlign
= GetAlignment();
1389 bNoChange
= sal_True
;
1392 case SFX_ALIGN_BOTTOM
:
1393 case SFX_ALIGN_LOWESTBOTTOM
:
1394 case SFX_ALIGN_HIGHESTBOTTOM
:
1395 if ( aInPosBR
.Y() >= aInSize
.Height())
1397 eDockAlign
= GetAlignment();
1398 bNoChange
= sal_True
;
1407 // alignment will change, test alignment according to distance of the docking rectangles edges
1408 sal_Bool bForbidden
= sal_True
;
1409 if ( aInPosTL
.X() <= 0)
1411 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_LEFT
);
1412 bForbidden
= ( eDockAlign
!= SFX_ALIGN_LEFT
&&
1413 eDockAlign
!= SFX_ALIGN_FIRSTLEFT
&&
1414 eDockAlign
!= SFX_ALIGN_LASTLEFT
);
1417 if ( bForbidden
&& aInPosTL
.Y() <= 0)
1419 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_TOP
);
1420 bForbidden
= ( eDockAlign
!= SFX_ALIGN_TOP
&&
1421 eDockAlign
!= SFX_ALIGN_HIGHESTTOP
&&
1422 eDockAlign
!= SFX_ALIGN_LOWESTTOP
);
1425 if ( bForbidden
&& aInPosBR
.X() >= aInSize
.Width())
1427 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_RIGHT
);
1428 bForbidden
= ( eDockAlign
!= SFX_ALIGN_RIGHT
&&
1429 eDockAlign
!= SFX_ALIGN_FIRSTRIGHT
&&
1430 eDockAlign
!= SFX_ALIGN_LASTRIGHT
);
1433 if ( bForbidden
&& aInPosBR
.Y() >= aInSize
.Height())
1435 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_BOTTOM
);
1436 bForbidden
= ( eDockAlign
!= SFX_ALIGN_BOTTOM
&&
1437 eDockAlign
!= SFX_ALIGN_HIGHESTBOTTOM
&&
1438 eDockAlign
!= SFX_ALIGN_LOWESTBOTTOM
);
1441 // the calculated alignment was rejected by the window -> take floating mode
1443 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
);
1447 if ( eDockAlign
== SFX_ALIGN_NOALIGNMENT
)
1449 // In the FloatingMode the tracking rectangle will get the floating
1450 // size. Due to a bug the rRect may only be changed when the
1451 // alignment is changed!
1452 if ( eDockAlign
!= pImp
->GetDockAlignment() )
1453 aDockingRect
.SetSize( aFloatingSize
);
1455 else if ( pImp
->bSplitable
)
1457 sal_uInt16 nLine
, nPos
;
1458 SfxSplitWindow
*pSplitWin
= pWorkWin
->GetSplitWindow_Impl(eDockAlign
);
1459 aPos
= pSplitWin
->ScreenToOutputPixel( aPos
);
1460 if ( pSplitWin
->GetWindowPos( aPos
, nLine
, nPos
) )
1462 // mouse over splitwindow, get line and position
1463 pImp
->nDockLine
= nLine
;
1464 pImp
->nDockPos
= nPos
;
1465 pImp
->bNewLine
= sal_False
;
1469 // mouse touches inner border -> create new line
1470 if ( eDockAlign
== GetAlignment() && pImp
->pSplitWin
&&
1471 pImp
->nLine
== pImp
->pSplitWin
->GetLineCount()-1 && pImp
->pSplitWin
->GetWindowCount(pImp
->nLine
) == 1 )
1473 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1474 pImp
->nDockLine
= pImp
->nLine
;
1475 pImp
->nDockPos
= pImp
->nPos
;
1476 pImp
->bNewLine
= sal_False
;
1481 pImp
->nDockLine
= pSplitWin
->GetLineCount();
1483 pImp
->bNewLine
= sal_True
;
1487 sal_Bool bChanged
= pImp
->nLine
!= pImp
->nDockLine
|| pImp
->nPos
!= pImp
->nDockPos
|| eDockAlign
!= GetAlignment();
1488 if ( !bChanged
&& !IsFloatingMode() )
1490 // window only sightly moved, no change of any property
1491 rRect
.SetSize( pImp
->aSplitSize
);
1492 rRect
.SetPos( aDockingRect
.TopLeft() );
1496 // calculate new size and position
1498 Point aPoint
= aDockingRect
.TopLeft();
1499 Size aInnerSize
= GetInnerRect().GetSize();
1500 if ( eDockAlign
== SFX_ALIGN_LEFT
|| eDockAlign
== SFX_ALIGN_RIGHT
)
1502 if ( pImp
->bNewLine
)
1504 // set height to height of free area
1505 aSize
.Height() = aInnerSize
.Height();
1506 aSize
.Width() = pImp
->nHorizontalSize
;
1507 if ( eDockAlign
== SFX_ALIGN_LEFT
)
1509 aPoint
= aInnerRect
.TopLeft();
1513 aPoint
= aInnerRect
.TopRight();
1514 aPoint
.X() -= aSize
.Width();
1519 // get width from splitwindow
1520 aSize
.Width() = pSplitWin
->GetLineSize(nLine
);
1521 aSize
.Height() = pImp
->aSplitSize
.Height();
1526 if ( pImp
->bNewLine
)
1528 // set width to width of free area
1529 aSize
.Width() = aInnerSize
.Width();
1530 aSize
.Height() = pImp
->nVerticalSize
;
1531 if ( eDockAlign
== SFX_ALIGN_TOP
)
1533 aPoint
= aInnerRect
.TopLeft();
1537 aPoint
= aInnerRect
.BottomLeft();
1538 aPoint
.Y() -= aSize
.Height();
1543 // get height from splitwindow
1544 aSize
.Height() = pSplitWin
->GetLineSize(nLine
);
1545 aSize
.Width() = pImp
->aSplitSize
.Width();
1549 aDockingRect
.SetSize( aSize
);
1550 aDockingRect
.SetPos( aPoint
);
1554 // window can be docked, but outside our splitwindows
1555 // tracking rectangle only needs to be modified if alignment was changed
1556 if ( eDockAlign
!= pImp
->GetDockAlignment() )
1558 switch ( eDockAlign
)
1560 case SFX_ALIGN_LEFT
:
1561 case SFX_ALIGN_RIGHT
:
1562 case SFX_ALIGN_FIRSTLEFT
:
1563 aDockingRect
.SetPos( aInnerRect
.TopLeft() );
1564 aDockingRect
.SetSize( aVerticalSize
);
1566 case SFX_ALIGN_LASTLEFT
:
1567 case SFX_ALIGN_FIRSTRIGHT
:
1568 case SFX_ALIGN_LASTRIGHT
:
1570 Point
aPt( aInnerRect
.TopRight() );
1571 aPt
.X() -= aDockingRect
.GetWidth();
1572 aDockingRect
.SetPos( aPt
);
1573 aDockingRect
.SetSize( aVerticalSize
);
1578 case SFX_ALIGN_BOTTOM
:
1579 case SFX_ALIGN_LOWESTTOP
:
1580 aDockingRect
.SetPos( aInnerRect
.TopLeft() );
1581 aDockingRect
.SetSize( aHorizontalSize
);
1583 case SFX_ALIGN_HIGHESTTOP
:
1584 case SFX_ALIGN_LOWESTBOTTOM
:
1585 case SFX_ALIGN_HIGHESTBOTTOM
:
1587 Point
aPt( aInnerRect
.BottomLeft() );
1588 aPt
.Y() -= aDockingRect
.GetHeight();
1589 aDockingRect
.SetPos( aPt
);
1590 aDockingRect
.SetSize( aHorizontalSize
);
1599 rRect
= aDockingRect
;
1603 //-------------------------------------------------------------------------
1605 Size
SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign
)
1609 Virtual method of the SfxDockingWindow class. This method determines how
1610 the size of the DockingWindows changes depending on the alignment. The base
1611 implementation uses the floating mode, the size of the marked Floating
1612 Size. For horizontal alignment, the width will be the width of the outer
1613 DockingRectangle, with vertical alignment the height will be the height of
1614 the inner DockingRectangle (resulting from the order in which the SFX child
1615 windows are displayed). The other size is set to the current floating-size,
1616 this could changed by a to intervening derived class. The docking size must
1617 be the same for Left/Right and Top/Bottom.
1621 // Note: if the resizing is also possible in the docked state, then the
1622 // Floating-size does also have to be adjusted?
1624 Size aSize
= GetFloatingSize();
1628 case SFX_ALIGN_BOTTOM
:
1629 case SFX_ALIGN_LOWESTTOP
:
1630 case SFX_ALIGN_HIGHESTTOP
:
1631 case SFX_ALIGN_LOWESTBOTTOM
:
1632 case SFX_ALIGN_HIGHESTBOTTOM
:
1633 aSize
.Width() = aOuterRect
.Right() - aOuterRect
.Left();
1635 case SFX_ALIGN_LEFT
:
1636 case SFX_ALIGN_RIGHT
:
1637 case SFX_ALIGN_FIRSTLEFT
:
1638 case SFX_ALIGN_LASTLEFT
:
1639 case SFX_ALIGN_FIRSTRIGHT
:
1640 case SFX_ALIGN_LASTRIGHT
:
1641 aSize
.Height() = aInnerRect
.Bottom() - aInnerRect
.Top();
1643 case SFX_ALIGN_NOALIGNMENT
:
1652 //-------------------------------------------------------------------------
1654 SfxChildAlignment
SfxDockingWindow::CheckAlignment(SfxChildAlignment
,
1655 SfxChildAlignment eAlign
)
1659 Virtual method of the SfxDockingWindow class. Here a derived class can
1660 disallow certain alignments. The base implementation does not
1668 //-------------------------------------------------------------------------
1670 sal_Bool
SfxDockingWindow::Close()
1674 The window is closed when the ChildWindow is destroyed by running the
1675 ChildWindow-slots. If this is method is overridden by a derived class
1676 method, then the SfxDockingDialogWindow: Close() must be called afterwards
1677 if the Close() was not cancelled with "return sal_False".
1680 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
1684 SfxBoolItem
aValue( pMgr
->GetType(), sal_False
);
1685 pBindings
->GetDispatcher_Impl()->Execute(
1686 pMgr
->GetType(), SFX_CALLMODE_RECORD
| SFX_CALLMODE_ASYNCHRON
, &aValue
, 0L );
1690 //-------------------------------------------------------------------------
1692 void SfxDockingWindow::Paint(const Rectangle
& /*rRect*/)
1696 Returns a boundary line to the docked edge and a frame when the Window is in
1697 a docked state. In this way SVLOOK is considered.
1701 if ( pImp
->bSplitable
|| IsFloatingMode() )
1704 Rectangle aRect
= Rectangle(Point(0, 0),
1705 GetOutputSizePixel());
1706 switch (GetAlignment())
1710 DrawLine(aRect
.BottomLeft(), aRect
.BottomRight());
1715 case SFX_ALIGN_BOTTOM
:
1717 DrawLine(aRect
.TopLeft(), aRect
.TopRight());
1722 case SFX_ALIGN_LEFT
:
1724 DrawLine(aRect
.TopRight(), aRect
.BottomRight());
1729 case SFX_ALIGN_RIGHT
:
1731 DrawLine(aRect
.TopLeft(), aRect
.BottomLeft());
1739 DecorationView
aView( this );
1740 aView
.DrawFrame( aRect
, FRAME_DRAW_OUT
);
1743 //-------------------------------------------------------------------------
1745 void SfxDockingWindow::SetMinOutputSizePixel( const Size
& rSize
)
1749 With this method, a minimal OutputSize be can set, that is queried in
1750 the Resizing()-Handler.
1754 pImp
->aMinSize
= rSize
;
1755 DockingWindow::SetMinOutputSizePixel( rSize
);
1758 //-------------------------------------------------------------------------
1760 Size
SfxDockingWindow::GetMinOutputSizePixel() const
1764 Set the minimum size which is returned.
1768 return pImp
->aMinSize
;
1771 //-------------------------------------------------------------------------
1773 long SfxDockingWindow::Notify( NotifyEvent
& rEvt
)
1775 if ( rEvt
.GetType() == EVENT_GETFOCUS
)
1778 pBindings
->SetActiveFrame( pMgr
->GetFrame() );
1780 if ( pImp
->pSplitWin
)
1781 pImp
->pSplitWin
->SetActiveWindow_Impl( this );
1782 else if (pMgr
!= NULL
)
1783 pMgr
->Activate_Impl();
1785 // In VCL Notify goes first to the window itself, also call the
1786 // base class, otherwise the parent learns nothing
1787 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1788 DockingWindow::Notify( rEvt
);
1791 else if( rEvt
.GetType() == EVENT_KEYINPUT
)
1793 // First, allow KeyInput for Dialog functions
1794 if ( !DockingWindow::Notify( rEvt
) && SfxViewShell::Current() )
1795 // then also for valid global accelerators.
1796 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt
.GetKeyEvent() );
1799 else if ( rEvt
.GetType() == EVENT_LOSEFOCUS
&& !HasChildPathFocus() )
1801 pBindings
->SetActiveFrame( NULL
);
1803 pMgr
->Deactivate_Impl();
1806 return DockingWindow::Notify( rEvt
);
1810 sal_uInt16
SfxDockingWindow::GetWinBits_Impl() const
1812 sal_uInt16 nBits
= 0;
1816 //-------------------------------------------------------------------------
1818 void SfxDockingWindow::SetItemSize_Impl( const Size
& rSize
)
1820 pImp
->aSplitSize
= rSize
;
1822 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1823 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
1824 if ( pImp
->bSplitable
)
1825 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
1826 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1829 void SfxDockingWindow::Disappear_Impl()
1831 if ( pImp
->pSplitWin
&& pImp
->pSplitWin
->IsItemValid( GetType() ) )
1832 pImp
->pSplitWin
->RemoveWindow(this);
1835 void SfxDockingWindow::Reappear_Impl()
1837 if ( pImp
->pSplitWin
&& !pImp
->pSplitWin
->IsItemValid( GetType() ) )
1839 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
);
1843 sal_Bool
SfxDockingWindow::IsAutoHide_Impl() const
1845 if ( pImp
->pSplitWin
)
1846 return !pImp
->pSplitWin
->IsFadeIn();
1851 void SfxDockingWindow::AutoShow( sal_Bool bShow
)
1853 AutoShow_Impl(bShow
);
1856 void SfxDockingWindow::AutoShow_Impl( sal_Bool bShow
)
1858 if ( pImp
->pSplitWin
)
1861 pImp
->pSplitWin
->FadeIn();
1863 pImp
->pSplitWin
->FadeOut();
1867 void SfxDockingWindow::FadeIn( sal_Bool
/*bFadeIn*/ )
1871 void SfxDockingWindow::StateChanged( StateChangedType nStateChange
)
1873 if ( nStateChange
== STATE_CHANGE_INITSHOW
)
1876 DockingWindow::StateChanged( nStateChange
);
1879 void SfxDockingWindow::Move()
1882 pImp
->aMoveTimer
.Start();
1885 IMPL_LINK_NOARG(SfxDockingWindow
, TimerHdl
)
1887 pImp
->aMoveTimer
.Stop();
1888 if ( IsReallyVisible() && IsFloatingMode() )
1890 if( !GetFloatingWindow()->IsRollUp() )
1891 SetFloatingSize( GetOutputSizePixel() );
1892 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
1893 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
1894 if ( pImp
->bSplitable
)
1895 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
1896 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1897 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1902 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */