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 <svl/solar.hrc>
22 #include <vcl/event.hxx>
23 #include <vcl/settings.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/timer.hxx>
27 #include <vcl/idle.hxx>
28 #include <o3tl/safeint.hxx>
29 #include <o3tl/string_view.hxx>
30 #include <osl/diagnose.h>
31 #include <toolkit/helper/vclunohelper.hxx>
32 #include <tools/debug.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/propertysequence.hxx>
35 #include <svl/itemset.hxx>
37 #include <sfx2/dockwin.hxx>
38 #include <sfx2/bindings.hxx>
39 #include <sfx2/viewfrm.hxx>
40 #include <sfx2/dispatch.hxx>
41 #include <workwin.hxx>
42 #include <splitwin.hxx>
43 #include <sfx2/viewsh.hxx>
45 #include <com/sun/star/beans/UnknownPropertyException.hpp>
46 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
47 #include <com/sun/star/awt/XWindow.hpp>
48 #include <com/sun/star/uno/XComponentContext.hpp>
49 #include <com/sun/star/frame/ModuleManager.hpp>
50 #include <com/sun/star/container/XNameAccess.hpp>
51 #include <com/sun/star/ui/theWindowStateConfiguration.hpp>
52 #include <com/sun/star/ui/theWindowContentFactoryManager.hpp>
54 #define MAX_TOGGLEAREA_WIDTH 20
55 #define MAX_TOGGLEAREA_HEIGHT 20
57 using namespace ::com::sun::star
;
59 // If you want to change the number you also have to:
60 // - Add new slot ids to sfxsids.hrc
61 // - Add new slots to frmslots.sdi
62 // - Add new slot definitions to sfx.sdi
63 const int NUM_OF_DOCKINGWINDOWS
= 10;
67 class SfxTitleDockingWindow
: public SfxDockingWindow
69 VclPtr
<vcl::Window
> m_pWrappedWindow
;
72 SfxTitleDockingWindow(
73 SfxBindings
* pBindings
,
74 SfxChildWindow
* pChildWin
,
75 vcl::Window
* pParent
,
77 virtual ~SfxTitleDockingWindow() override
;
78 virtual void dispose() override
;
80 vcl::Window
* GetWrappedWindow() const { return m_pWrappedWindow
; }
81 void SetWrappedWindow(vcl::Window
* const pWindow
);
83 virtual void StateChanged( StateChangedType nType
) override
;
84 virtual void Resize() override
;
85 virtual void Resizing( Size
& rSize
) override
;
94 static bool lcl_getWindowState( const uno::Reference
< container::XNameAccess
>& xWindowStateMgr
, const OUString
& rResourceURL
, WindowState
& rWindowState
)
101 uno::Sequence
< beans::PropertyValue
> aWindowState
;
102 a
= xWindowStateMgr
->getByName( rResourceURL
);
103 if ( a
>>= aWindowState
)
105 for ( const auto& rProp
: std::as_const(aWindowState
) )
107 if ( rProp
.Name
== "UIName" )
109 rProp
.Value
>>= rWindowState
.sTitle
;
116 catch ( container::NoSuchElementException
& )
124 SfxDockingWrapper::SfxDockingWrapper( vcl::Window
* pParentWnd
,
126 SfxBindings
* pBindings
,
127 SfxChildWinInfo
* pInfo
)
128 : SfxChildWindow( pParentWnd
, nId
)
130 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
132 VclPtr
<SfxTitleDockingWindow
> pTitleDockWindow
= VclPtr
<SfxTitleDockingWindow
>::Create( pBindings
, this, pParentWnd
,
133 WB_STDDOCKWIN
| WB_CLIPCHILDREN
| WB_SIZEABLE
| WB_3DLOOK
);
134 SetWindow( pTitleDockWindow
);
136 // Use factory manager to retrieve XWindow factory. That can be used to instantiate
137 // the real window factory.
138 uno::Reference
< lang::XSingleComponentFactory
> xFactoryMgr
= ui::theWindowContentFactoryManager::get(xContext
);
140 SfxDispatcher
* pDispatcher
= pBindings
->GetDispatcher();
141 uno::Reference
< frame::XFrame
> xFrame
= pDispatcher
->GetFrame()->GetFrame().GetFrameInterface();
142 // create a resource URL from the nId provided by the sfx2
143 OUString aResourceURL
= "private:resource/dockingwindow/" + OUString::number(nId
);
144 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
146 {"Frame", uno::Any(xFrame
)},
147 {"ResourceURL", uno::Any(aResourceURL
)},
150 uno::Reference
< awt::XWindow
> xWindow
;
154 xFactoryMgr
->createInstanceWithArgumentsAndContext( aArgs
, xContext
),
157 static uno::WeakReference
< frame::XModuleManager2
> s_xModuleManager
;
159 uno::Reference
< frame::XModuleManager2
> xModuleManager( s_xModuleManager
);
160 if ( !xModuleManager
.is() )
162 xModuleManager
= frame::ModuleManager::create(xContext
);
163 s_xModuleManager
= xModuleManager
;
166 static uno::WeakReference
< container::XNameAccess
> s_xWindowStateConfiguration
;
168 uno::Reference
< container::XNameAccess
> xWindowStateConfiguration( s_xWindowStateConfiguration
);
169 if ( !xWindowStateConfiguration
.is() )
171 xWindowStateConfiguration
= ui::theWindowStateConfiguration::get( xContext
);
172 s_xWindowStateConfiguration
= xWindowStateConfiguration
;
175 OUString sModuleIdentifier
= xModuleManager
->identify( xFrame
);
177 uno::Reference
< container::XNameAccess
> xModuleWindowState(
178 xWindowStateConfiguration
->getByName( sModuleIdentifier
),
180 if ( xModuleWindowState
.is() )
182 WindowState aDockWinState
;
183 if ( lcl_getWindowState( xModuleWindowState
, aResourceURL
, aDockWinState
))
184 pTitleDockWindow
->SetText( aDockWinState
.sTitle
);
187 catch ( beans::UnknownPropertyException
& )
190 catch ( uno::RuntimeException
& )
193 catch ( uno::Exception
& )
197 VclPtr
<vcl::Window
> pContentWindow
= VCLUnoHelper::GetWindow(xWindow
);
198 if ( pContentWindow
)
199 pContentWindow
->SetStyle( pContentWindow
->GetStyle() | WB_DIALOGCONTROL
| WB_CHILDDLGCTRL
);
200 pTitleDockWindow
->SetWrappedWindow(pContentWindow
);
202 GetWindow()->SetOutputSizePixel( Size( 270, 240 ) );
204 static_cast<SfxDockingWindow
*>( GetWindow() )->Initialize( pInfo
);
205 SetHideNotDelete( true );
208 std::unique_ptr
<SfxChildWindow
> SfxDockingWrapper::CreateImpl(vcl::Window
*pParent
, sal_uInt16 nId
,
209 SfxBindings
*pBindings
, SfxChildWinInfo
* pInfo
)
211 return std::make_unique
<SfxDockingWrapper
>(pParent
, nId
, pBindings
, pInfo
);
214 void SfxDockingWrapper::RegisterChildWindow (bool bVis
, SfxModule
*pMod
, SfxChildWindowFlags nFlags
)
216 // pre-register a couple of docking windows
217 for (int i
=0; i
< NUM_OF_DOCKINGWINDOWS
; i
++ )
219 sal_uInt16 nID
= sal_uInt16(SID_DOCKWIN_START
+i
);
220 SfxChildWinFactory
aFact( SfxDockingWrapper::CreateImpl
, nID
, 0xffff );
221 aFact
.aInfo
.nFlags
|= nFlags
;
222 aFact
.aInfo
.bVisible
= bVis
;
223 SfxChildWindow::RegisterChildWindow(pMod
, aFact
);
227 SfxChildWinInfo
SfxDockingWrapper::GetInfo() const
229 SfxChildWinInfo aInfo
= SfxChildWindow::GetInfo();
230 static_cast<SfxDockingWindow
*>(GetWindow())->FillInfo( aInfo
);
234 SfxTitleDockingWindow::SfxTitleDockingWindow(SfxBindings
* pBind
, SfxChildWindow
* pChildWin
,
235 vcl::Window
* pParent
, WinBits nBits
)
236 : SfxDockingWindow(pBind
, pChildWin
, pParent
, nBits
)
237 , m_pWrappedWindow(nullptr)
241 SfxTitleDockingWindow::~SfxTitleDockingWindow()
246 void SfxTitleDockingWindow::dispose()
248 m_pWrappedWindow
.disposeAndClear();
249 SfxDockingWindow::dispose();
252 void SfxTitleDockingWindow::SetWrappedWindow( vcl::Window
* const pWindow
)
254 m_pWrappedWindow
= pWindow
;
255 if (m_pWrappedWindow
)
257 m_pWrappedWindow
->SetParent(this);
258 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
259 m_pWrappedWindow
->Show();
263 void SfxTitleDockingWindow::StateChanged( StateChangedType nType
)
265 if ( nType
== StateChangedType::InitShow
)
267 vcl::Window
* pWindow
= GetWrappedWindow();
270 pWindow
->SetSizePixel( GetOutputSizePixel() );
275 SfxDockingWindow::StateChanged(nType
);
278 void SfxTitleDockingWindow::Resize()
280 SfxDockingWindow::Resize();
281 if (m_pWrappedWindow
)
282 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
285 void SfxTitleDockingWindow::Resizing( Size
&rSize
)
287 SfxDockingWindow::Resizing( rSize
);
288 if (m_pWrappedWindow
)
289 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
292 static bool lcl_checkDockingWindowID( sal_uInt16 nID
)
294 return nID
>= SID_DOCKWIN_START
&& nID
< o3tl::make_unsigned(SID_DOCKWIN_START
+NUM_OF_DOCKINGWINDOWS
);
297 static SfxWorkWindow
* lcl_getWorkWindowFromXFrame( const uno::Reference
< frame::XFrame
>& rFrame
)
299 // We need to find the corresponding SfxFrame of our XFrame
300 SfxFrame
* pFrame
= SfxFrame::GetFirst();
301 SfxFrame
* pXFrame
= nullptr;
304 uno::Reference
< frame::XFrame
> xViewShellFrame( pFrame
->GetFrameInterface() );
305 if ( xViewShellFrame
== rFrame
)
311 pFrame
= SfxFrame::GetNext( *pFrame
);
314 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
316 return pXFrame
->GetWorkWindow_Impl();
321 /** Factory function used by the framework layout manager to "create" a docking window with a special name.
322 The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
323 in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
325 void SfxDockingWindowFactory( const uno::Reference
< frame::XFrame
>& rFrame
, std::u16string_view rDockingWindowName
)
327 SolarMutexGuard aGuard
;
328 sal_uInt16 nID
= sal_uInt16(o3tl::toInt32(rDockingWindowName
));
330 // Check the range of the provided ID otherwise nothing will happen
331 if ( !lcl_checkDockingWindowID( nID
))
334 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
337 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
340 // Register window at the workwindow child window list
341 pWorkWindow
->SetChildWindow_Impl( nID
, true, false );
346 /** Function used by the framework layout manager to determine the visibility state of a docking window with
347 a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
348 range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
350 bool IsDockingWindowVisible( const uno::Reference
< frame::XFrame
>& rFrame
, std::u16string_view rDockingWindowName
)
352 SolarMutexGuard aGuard
;
354 sal_uInt16 nID
= sal_uInt16(o3tl::toInt32(rDockingWindowName
));
356 // Check the range of the provided ID otherwise nothing will happen
357 if ( lcl_checkDockingWindowID( nID
))
359 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
362 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
371 class SfxDockingWindow_Impl
373 friend class SfxDockingWindow
;
375 SfxChildAlignment eLastAlignment
;
376 SfxChildAlignment eDockAlignment
;
379 VclPtr
<SfxSplitWindow
> pSplitWin
;
382 // The following members are only valid in the time from startDocking to
385 tools::Long nHorizontalSize
;
386 tools::Long nVerticalSize
;
389 sal_uInt16 nDockLine
;
392 bool bDockingPrevented
;
395 explicit SfxDockingWindow_Impl(SfxDockingWindow
*pBase
);
396 SfxChildAlignment
GetLastAlignment() const
397 { return eLastAlignment
; }
398 void SetLastAlignment(SfxChildAlignment eAlign
)
399 { eLastAlignment
= eAlign
; }
400 SfxChildAlignment
GetDockAlignment() const
401 { return eDockAlignment
; }
402 void SetDockAlignment(SfxChildAlignment eAlign
)
403 { eDockAlignment
= eAlign
; }
406 SfxDockingWindow_Impl::SfxDockingWindow_Impl(SfxDockingWindow
* pBase
)
407 :eLastAlignment(SfxChildAlignment::NOALIGNMENT
)
408 ,eDockAlignment(SfxChildAlignment::NOALIGNMENT
)
411 ,aMoveIdle( "sfx::SfxDockingWindow_Impl aMoveIdle" )
419 ,bDockingPrevented(false)
421 aMoveIdle
.SetPriority(TaskPriority::RESIZE
);
422 aMoveIdle
.SetInvokeHandler(LINK(pBase
,SfxDockingWindow
,TimerHdl
));
427 This virtual method of the class FloatingWindow keeps track of changes in
428 FloatingSize. If this method is overridden by a derived class,
429 then the FloatingWindow: Resize() must also be called.
431 void SfxDockingWindow::Resize()
433 ResizableDockingWindow::Resize();
435 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
438 if ( IsFloatingMode() )
440 // start timer for saving window status information
441 pImpl
->aMoveIdle
.Start();
445 Size
aSize( GetSizePixel() );
446 switch ( pImpl
->GetDockAlignment() )
448 case SfxChildAlignment::LEFT
:
449 case SfxChildAlignment::FIRSTLEFT
:
450 case SfxChildAlignment::LASTLEFT
:
451 case SfxChildAlignment::RIGHT
:
452 case SfxChildAlignment::FIRSTRIGHT
:
453 case SfxChildAlignment::LASTRIGHT
:
454 pImpl
->nHorizontalSize
= aSize
.Width();
455 pImpl
->aSplitSize
= aSize
;
457 case SfxChildAlignment::TOP
:
458 case SfxChildAlignment::LOWESTTOP
:
459 case SfxChildAlignment::HIGHESTTOP
:
460 case SfxChildAlignment::BOTTOM
:
461 case SfxChildAlignment::HIGHESTBOTTOM
:
462 case SfxChildAlignment::LOWESTBOTTOM
:
463 pImpl
->nVerticalSize
= aSize
.Height();
464 pImpl
->aSplitSize
= aSize
;
474 This virtual method of the class DockingWindow makes it possible to
475 intervene in the switching of the floating mode.
476 If this method is overridden by a derived class,
477 then the SfxDockingWindow::PrepareToggleFloatingMode() must be called
478 afterwards, if not FALSE is returned.
480 bool SfxDockingWindow::PrepareToggleFloatingMode()
482 if (!pImpl
|| !pImpl
->bConstructed
)
485 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr
)
488 if ( pImpl
->bDockingPrevented
)
491 if (!IsFloatingMode())
493 // Test, if FloatingMode is permitted.
494 if ( CheckAlignment(GetAlignment(),SfxChildAlignment::NOALIGNMENT
) != SfxChildAlignment::NOALIGNMENT
)
497 if ( pImpl
->pSplitWin
)
499 // The DockingWindow is inside a SplitWindow and will be teared of.
500 pImpl
->pSplitWin
->RemoveWindow(this/*, sal_False*/);
501 pImpl
->pSplitWin
= nullptr;
506 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
508 // Test if it is allowed to dock,
509 if (CheckAlignment(GetAlignment(),pImpl
->GetLastAlignment()) == SfxChildAlignment::NOALIGNMENT
)
512 // Test, if the Workwindow allows for docking at the moment.
513 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
514 if ( !pWorkWin
->IsDockingAllowed() || !pWorkWin
->IsInternalDockingAllowed() )
523 This virtual method of the DockingWindow class sets the internal data of
524 the SfxDockingWindow and ensures the correct alignment on the parent window.
525 Through PrepareToggleFloatMode and Initialize it is ensured that
526 pImpl-> GetLastAlignment() always delivers an allowed alignment. If this
527 method is overridden by a derived class, then first the
528 SfxDockingWindow::ToggleFloatingMode() must be called.
530 void SfxDockingWindow::ToggleFloatingMode()
532 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
533 return; // No Handler call
535 // Remember old alignment and then switch.
536 // SV has already switched, but the alignment SfxDockingWindow is still
537 // the old one. What I was before?
538 SfxChildAlignment eLastAlign
= GetAlignment();
540 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
542 if (IsFloatingMode())
544 SetAlignment(SfxChildAlignment::NOALIGNMENT
);
545 if ( !pImpl
->aWinState
.isEmpty() )
546 GetFloatingWindow()->SetWindowState( pImpl
->aWinState
);
548 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
552 if (pImpl
->GetDockAlignment() == eLastAlign
)
554 // If ToggleFloatingMode was called, but the DockAlignment still
555 // is unchanged, then this means that it must have been a toggling
556 // through DClick, so use last alignment
557 SetAlignment (pImpl
->GetLastAlignment());
562 // Toggling was triggered by dragging
563 pImpl
->nLine
= pImpl
->nDockLine
;
564 pImpl
->nPos
= pImpl
->nDockPos
;
565 SetAlignment (pImpl
->GetDockAlignment());
568 // The DockingWindow is now in a SplitWindow
569 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
571 // The LastAlignment is still the last docked
572 SfxSplitWindow
*pSplit
= pWorkWin
->GetSplitWindow_Impl(pImpl
->GetLastAlignment());
574 DBG_ASSERT( pSplit
, "LastAlignment is not correct!" );
575 if ( pSplit
&& pSplit
!= pImpl
->pSplitWin
)
576 pSplit
->ReleaseWindow_Impl(this);
577 if ( pImpl
->GetDockAlignment() == eLastAlign
)
578 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
);
580 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
, pImpl
->nLine
, pImpl
->nPos
, pImpl
->bNewLine
);
581 if ( !pImpl
->pSplitWin
->IsFadeIn() )
582 pImpl
->pSplitWin
->FadeIn();
585 // Keep the old alignment for the next toggle; set it only now due to the
586 // unregister SplitWindow!
587 pImpl
->SetLastAlignment(eLastAlign
);
589 // Reset DockAlignment, if EndDocking is still called
590 pImpl
->SetDockAlignment(GetAlignment());
592 // Dock or undock SfxChildWindow correctly.
593 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::TOGGLEFLOATMODE
, pMgr
->GetType() );
598 This virtual method of the DockingWindow class takes the inner and outer
599 docking rectangle from the parent window. If this method is overridden by
600 a derived class, then SfxDockingWindow:StartDocking() has to be called at
603 void SfxDockingWindow::StartDocking()
605 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
607 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
608 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::SETDOCKINGRECTS
, pMgr
->GetType() );
609 pImpl
->SetDockAlignment(GetAlignment());
611 if ( pImpl
->pSplitWin
)
613 // Get the current docking data
614 pImpl
->pSplitWin
->GetWindowPos(this, pImpl
->nLine
, pImpl
->nPos
);
615 pImpl
->nDockLine
= pImpl
->nLine
;
616 pImpl
->nDockPos
= pImpl
->nPos
;
617 pImpl
->bNewLine
= false;
623 This virtual method of the DockingWindow class calculates the current
624 tracking rectangle. For this purpose the method CalcAlignment(RPOs, rRect)
625 is used, the behavior can be influenced by the derived classes (see below).
626 This method should if possible not be overwritten.
628 bool SfxDockingWindow::Docking( const Point
& rPos
, tools::Rectangle
& rRect
)
630 if ( Application::IsInModalMode() )
633 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
635 rRect
.SetSize( Size() );
636 return IsFloatingMode();
639 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
640 if ( pImpl
->bDockingPrevented
|| !pWorkWin
->IsInternalDockingAllowed() )
643 bool bFloatMode
= false;
645 if ( GetOuterRect().Contains( rPos
) )
647 // Mouse within OuterRect: calculate Alignment and Rectangle
648 SfxChildAlignment eAlign
= CalcAlignment(rPos
, rRect
);
649 if (eAlign
== SfxChildAlignment::NOALIGNMENT
)
651 pImpl
->SetDockAlignment(eAlign
);
655 // Mouse is not within OuterRect: must be FloatingWindow
657 if (CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
) != SfxChildAlignment::NOALIGNMENT
)
660 if ( SfxChildAlignment::NOALIGNMENT
!= pImpl
->GetDockAlignment() )
662 // Due to a bug the rRect may only be changed when the
663 // alignment is changed!
664 pImpl
->SetDockAlignment(SfxChildAlignment::NOALIGNMENT
);
665 rRect
.SetSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT
));
672 /** Virtual method of the DockingWindow class ensures the correct alignment on
673 the parent window. If this method is overridden by a derived class, then
674 SfxDockingWindow::EndDocking() must be called first.
676 void SfxDockingWindow::EndDocking( const tools::Rectangle
& rRect
, bool bFloatMode
)
678 if ( !pImpl
|| !pImpl
->bConstructed
|| IsDockingCanceled() || !pMgr
)
681 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
683 // If the alignment changes and the window is in a docked state in a
684 // SplitWindow, then it must be re-registered. If it is docked again,
685 // PrepareToggleFloatingMode() and ToggleFloatingMode() perform the
687 bool bReArrange
= !bFloatMode
;
691 if ( GetAlignment() != pImpl
->GetDockAlignment() )
693 // before Show() is called must the reassignment have been made,
694 // therefore the base class can not be called
695 if ( IsFloatingMode() )
696 Show( false, ShowFlags::NoFocusChange
);
698 // Set the size for toggling.
699 pImpl
->aSplitSize
= rRect
.GetSize();
700 if ( IsFloatingMode() )
702 SetFloatingMode( bFloatMode
);
703 if ( IsFloatingMode() )
704 Show( true, ShowFlags::NoFocusChange
);
708 pImpl
->pSplitWin
->RemoveWindow(this,false);
709 pImpl
->nLine
= pImpl
->nDockLine
;
710 pImpl
->nPos
= pImpl
->nDockPos
;
711 pImpl
->pSplitWin
->ReleaseWindow_Impl(this);
712 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(pImpl
->GetDockAlignment());
713 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
, pImpl
->nDockLine
, pImpl
->nDockPos
, pImpl
->bNewLine
);
714 if ( !pImpl
->pSplitWin
->IsFadeIn() )
715 pImpl
->pSplitWin
->FadeIn();
718 else if ( pImpl
->nLine
!= pImpl
->nDockLine
|| pImpl
->nPos
!= pImpl
->nDockPos
|| pImpl
->bNewLine
)
720 // Moved within Splitwindows
721 if ( pImpl
->nLine
!= pImpl
->nDockLine
)
722 pImpl
->aSplitSize
= rRect
.GetSize();
723 pImpl
->pSplitWin
->MoveWindow( this, pImpl
->aSplitSize
, pImpl
->nDockLine
, pImpl
->nDockPos
, pImpl
->bNewLine
);
728 ResizableDockingWindow::EndDocking(rRect
, bFloatMode
);
731 SetAlignment( IsFloatingMode() ? SfxChildAlignment::NOALIGNMENT
: pImpl
->GetDockAlignment() );
736 Virtual method of the DockingWindow class. Here, the interactive resize in
737 FloatingMode can be influenced, for example by only allowing for discrete
738 values for width and / or height. The base implementation prevents that the
739 output size is smaller than one set with SetMinOutputSizePixel().
741 void SfxDockingWindow::Resizing( Size
& /*rSize*/ )
748 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
749 required because the docking is implemented in Sfx through SfxChildWindows.
751 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
752 vcl::Window
* pParent
, WinBits nWinBits
)
753 : ResizableDockingWindow(pParent
, nWinBits
)
754 , pBindings(pBindinx
)
757 pImpl
.reset(new SfxDockingWindow_Impl(this));
760 /** Constructor for the SfxDockingWindow class. A SfxChildWindow will be
761 required because the docking is implemented in Sfx through SfxChildWindows.
763 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
764 vcl::Window
* pParent
, const OUString
& rID
, const OUString
& rUIXMLDescription
)
765 : ResizableDockingWindow(pParent
)
766 , pBindings(pBindinx
)
769 m_xBuilder
= Application::CreateInterimBuilder(m_xBox
, rUIXMLDescription
, true);
770 m_xContainer
= m_xBuilder
->weld_box(rID
);
772 pImpl
.reset(new SfxDockingWindow_Impl(this));
775 /** Initialization of the SfxDockingDialog class via a SfxChildWinInfo.
776 The initialization is done only in a 2nd step after the constructor, this
777 constructor should be called from the derived class or from the
780 void SfxDockingWindow::Initialize(SfxChildWinInfo
*pInfo
)
784 pImpl
->SetDockAlignment( SfxChildAlignment::NOALIGNMENT
);
785 pImpl
->bConstructed
= true;
789 if (pInfo
&& (pInfo
->nFlags
& SfxChildWindowFlags::FORCEDOCK
))
790 pImpl
->bDockingPrevented
= true;
792 pImpl
->aSplitSize
= GetOutputSizePixel();
793 if ( !GetFloatingSize().Width() )
795 Size
aMinSize( GetMinOutputSizePixel() );
796 SetFloatingSize( pImpl
->aSplitSize
);
797 if ( pImpl
->aSplitSize
.Width() < aMinSize
.Width() )
798 pImpl
->aSplitSize
.setWidth( aMinSize
.Width() );
799 if ( pImpl
->aSplitSize
.Height() < aMinSize
.Height() )
800 pImpl
->aSplitSize
.setHeight( aMinSize
.Height() );
803 bool bVertHorzRead( false );
804 if (pInfo
&& !pInfo
->aExtraString
.isEmpty())
806 // get information about alignment, split size and position in SplitWindow
808 sal_Int32 nPos
= pInfo
->aExtraString
.indexOf("AL:");
811 // alignment information
812 sal_Int32 n1
= pInfo
->aExtraString
.indexOf('(', nPos
);
815 sal_Int32 n2
= pInfo
->aExtraString
.indexOf(')', n1
);
818 // extract alignment information from extrastring
819 aStr
= pInfo
->aExtraString
.copy(nPos
, n2
- nPos
+ 1);
820 pInfo
->aExtraString
= pInfo
->aExtraString
.replaceAt(nPos
, n2
- nPos
+ 1, u
"");
821 aStr
= aStr
.replaceAt(nPos
, n1
-nPos
+1, u
"");
826 if ( !aStr
.isEmpty() )
828 // accept window state only if alignment is also set
829 pImpl
->aWinState
= pInfo
->aWinState
;
831 // check for valid alignment
832 SfxChildAlignment eLocalAlignment
= static_cast<SfxChildAlignment
>(static_cast<sal_uInt16
>(aStr
.toInt32()));
833 bool bIgnoreFloatConfig
= (eLocalAlignment
== SfxChildAlignment::NOALIGNMENT
&&
834 !StyleSettings::GetDockingFloatsSupported());
835 if (pImpl
->bDockingPrevented
|| bIgnoreFloatConfig
)
836 // docking prevented, ignore old configuration and take alignment from default
839 SetAlignment( eLocalAlignment
);
841 SfxChildAlignment eAlign
= CheckAlignment(GetAlignment(),GetAlignment());
842 if ( eAlign
!= GetAlignment() )
844 OSL_FAIL("Invalid Alignment!");
845 SetAlignment( eAlign
);
849 // get last alignment (for toggling)
850 nPos
= aStr
.indexOf(',');
853 aStr
= aStr
.copy(nPos
+1);
854 pImpl
->SetLastAlignment( static_cast<SfxChildAlignment
>(static_cast<sal_uInt16
>(aStr
.toInt32())) );
857 nPos
= aStr
.indexOf(',');
860 // get split size and position in SplitWindow
862 aStr
= aStr
.copy(nPos
+1);
863 if ( GetPosSizeFromString( aStr
, aPos
, pImpl
->aSplitSize
) )
865 pImpl
->nLine
= pImpl
->nDockLine
= static_cast<sal_uInt16
>(aPos
.X());
866 pImpl
->nPos
= pImpl
->nDockPos
= static_cast<sal_uInt16
>(aPos
.Y());
867 pImpl
->nVerticalSize
= pImpl
->aSplitSize
.Height();
868 pImpl
->nHorizontalSize
= pImpl
->aSplitSize
.Width();
869 if ( GetSplitSizeFromString( aStr
, pImpl
->aSplitSize
))
870 bVertHorzRead
= true;
875 OSL_FAIL( "Information is missing!" );
879 if ( !bVertHorzRead
)
881 pImpl
->nVerticalSize
= pImpl
->aSplitSize
.Height();
882 pImpl
->nHorizontalSize
= pImpl
->aSplitSize
.Width();
885 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
886 if ( GetAlignment() != SfxChildAlignment::NOALIGNMENT
)
888 // check if SfxWorkWindow is able to allow docking at its border
890 !pWorkWin
->IsDockingAllowed() ||
891 !pWorkWin
->IsInternalDockingAllowed() ||
892 ( (GetFloatStyle() & WB_STANDALONE
) && Application::IsInModalMode()) )
894 SetAlignment( SfxChildAlignment::NOALIGNMENT
);
898 // detect floating mode
899 // toggling mode will not execute code in handlers, because pImpl->bConstructed is not set yet
900 bool bFloatMode
= IsFloatingMode();
901 if ( bFloatMode
!= (GetAlignment() == SfxChildAlignment::NOALIGNMENT
) )
903 bFloatMode
= !bFloatMode
;
904 SetFloatingMode( bFloatMode
);
907 if ( !pImpl
->aWinState
.isEmpty() )
908 GetFloatingWindow()->SetWindowState( pImpl
->aWinState
);
910 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
914 if ( IsFloatingMode() )
916 // validate last alignment
917 SfxChildAlignment eLastAlign
= pImpl
->GetLastAlignment();
918 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
919 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::LEFT
);
920 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
921 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::RIGHT
);
922 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
923 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::TOP
);
924 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
925 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::BOTTOM
);
926 pImpl
->SetLastAlignment(eLastAlign
);
930 // docked window must have NOALIGNMENT as last alignment
931 pImpl
->SetLastAlignment(SfxChildAlignment::NOALIGNMENT
);
933 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
934 pImpl
->pSplitWin
->InsertWindow(this, pImpl
->aSplitSize
);
938 pImpl
->SetDockAlignment( GetAlignment() );
941 void SfxDockingWindow::Initialize_Impl()
945 pImpl
->bConstructed
= true;
949 SystemWindow
* pFloatWin
= GetFloatingWindow();
953 bSet
= !pFloatWin
->IsDefaultPos();
957 Point aPos
= GetFloatingPos();
958 if ( aPos
!= Point() )
964 SfxViewFrame
*pFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
965 vcl::Window
* pEditWin
= pFrame
->GetViewShell()->GetWindow();
966 Point aPos
= pEditWin
->OutputToScreenPixel( pEditWin
->GetPosPixel() );
967 aPos
= GetParent()->ScreenToOutputPixel( aPos
);
968 SetFloatingPos( aPos
);
973 // initialize floating window
974 if ( pImpl
->aWinState
.isEmpty() )
975 // window state never set before, get if from defaults
976 pImpl
->aWinState
= pFloatWin
->GetWindowState();
978 // trick: use VCL method SetWindowState to adjust position and size
979 pFloatWin
->SetWindowState( pImpl
->aWinState
);
980 Size
aSize(pFloatWin
->GetSizePixel());
982 // remember floating size for calculating alignment and tracking rectangle
983 SetFloatingSize(aSize
);
987 // allow calling of docking handlers
988 pImpl
->bConstructed
= true;
991 /** Fills a SfxChildWinInfo with specific data from SfxDockingWindow,
992 so that it can be written in the INI file. It is assumed that rinfo
993 receives all other possible relevant data in the ChildWindow class.
994 Insertions are marked with size and the ZoomIn flag.
995 If this method is overridden, the base implementation must be called first.
997 void SfxDockingWindow::FillInfo(SfxChildWinInfo
& rInfo
) const
1002 if (GetFloatingWindow() && pImpl
->bConstructed
)
1003 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
1005 rInfo
.aWinState
= pImpl
->aWinState
;
1006 rInfo
.aExtraString
= "AL:(";
1007 rInfo
.aExtraString
+= OUString::number(static_cast<sal_uInt16
>(GetAlignment()));
1008 rInfo
.aExtraString
+= ",";
1009 rInfo
.aExtraString
+= OUString::number (static_cast<sal_uInt16
>(pImpl
->GetLastAlignment()));
1011 Point
aPos(pImpl
->nLine
, pImpl
->nPos
);
1012 rInfo
.aExtraString
+= ",";
1013 rInfo
.aExtraString
+= OUString::number( aPos
.X() );
1014 rInfo
.aExtraString
+= "/";
1015 rInfo
.aExtraString
+= OUString::number( aPos
.Y() );
1016 rInfo
.aExtraString
+= "/";
1017 rInfo
.aExtraString
+= OUString::number( pImpl
->nHorizontalSize
);
1018 rInfo
.aExtraString
+= "/";
1019 rInfo
.aExtraString
+= OUString::number( pImpl
->nVerticalSize
);
1020 rInfo
.aExtraString
+= ",";
1021 rInfo
.aExtraString
+= OUString::number( pImpl
->aSplitSize
.Width() );
1022 rInfo
.aExtraString
+= ";";
1023 rInfo
.aExtraString
+= OUString::number( pImpl
->aSplitSize
.Height() );
1025 rInfo
.aExtraString
+= ")";
1028 SfxDockingWindow::~SfxDockingWindow()
1033 void SfxDockingWindow::dispose()
1035 ReleaseChildWindow_Impl();
1037 m_xContainer
.reset();
1039 ResizableDockingWindow::dispose();
1042 void SfxDockingWindow::ReleaseChildWindow_Impl()
1044 if ( pMgr
&& pMgr
->GetFrame() == pBindings
->GetActiveFrame() )
1045 pBindings
->SetActiveFrame( nullptr );
1047 if ( pMgr
&& pImpl
->pSplitWin
&& pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1048 pImpl
->pSplitWin
->RemoveWindow(this);
1053 /** This method calculates a resulting alignment for the given mouse position
1054 and tracking rectangle. When changing the alignment it can also be that
1055 the tracking rectangle is changed, so that an altered rectangle is
1056 returned. The user of this class can influence behaviour of this method,
1057 and thus the behavior of his DockinWindow class when docking where the
1058 called virtual method:
1060 SfxDockingWindow::CalcDockingSize (SfxChildAlignment eAlign)
1062 is overridden (see below).
1064 SfxChildAlignment
SfxDockingWindow::CalcAlignment(const Point
& rPos
, tools::Rectangle
& rRect
)
1066 // calculate hypothetical sizes for different modes
1067 Size
aFloatingSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT
));
1069 // check if docking is permitted
1070 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1071 if ( !pWorkWin
->IsDockingAllowed() )
1073 rRect
.SetSize( aFloatingSize
);
1074 return pImpl
->GetDockAlignment();
1077 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1078 tools::Long nLRBorder
, nTBBorder
;
1080 // take the smaller size of docked and floating mode
1081 Size aBorderTmp
= pImpl
->aSplitSize
;
1082 if ( GetFloatingSize().Height() < aBorderTmp
.Height() )
1083 aBorderTmp
.setHeight( GetFloatingSize().Height() );
1084 if ( GetFloatingSize().Width() < aBorderTmp
.Width() )
1085 aBorderTmp
.setWidth( GetFloatingSize().Width() );
1087 nLRBorder
= aBorderTmp
.Width();
1088 nTBBorder
= aBorderTmp
.Height();
1090 // limit border to predefined constant values
1091 if ( nLRBorder
> MAX_TOGGLEAREA_WIDTH
)
1092 nLRBorder
= MAX_TOGGLEAREA_WIDTH
;
1093 if ( nTBBorder
> MAX_TOGGLEAREA_WIDTH
)
1094 nTBBorder
= MAX_TOGGLEAREA_WIDTH
;
1096 // shrink area for floating mode if possible
1097 tools::Rectangle aInRect
= GetInnerRect();
1098 if ( aInRect
.GetWidth() > nLRBorder
)
1099 aInRect
.AdjustLeft(nLRBorder
/2 );
1100 if ( aInRect
.GetWidth() > nLRBorder
)
1101 aInRect
.AdjustRight( -(nLRBorder
/2) );
1102 if ( aInRect
.GetHeight() > nTBBorder
)
1103 aInRect
.AdjustTop(nTBBorder
/2 );
1104 if ( aInRect
.GetHeight() > nTBBorder
)
1105 aInRect
.AdjustBottom( -(nTBBorder
/2) );
1107 // calculate alignment resulting from docking rectangle
1108 bool bBecomesFloating
= false;
1109 SfxChildAlignment eDockAlign
= pImpl
->GetDockAlignment();
1110 tools::Rectangle
aDockingRect( rRect
);
1111 if ( !IsFloatingMode() )
1113 // don't use tracking rectangle for alignment check, because it will be too large
1114 // to get a floating mode as result - switch to floating size
1115 // so the calculation only depends on the position of the rectangle, not the current
1116 // docking state of the window
1117 aDockingRect
.SetSize( GetFloatingSize() );
1119 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1120 aDockingRect
.SetPos( pWorkWin
->GetWindow()->OutputToScreenPixel( pWorkWin
->GetWindow()->GetPointerPosPixel() ) );
1123 Point aPos
= aDockingRect
.TopLeft();
1124 tools::Rectangle aIntersect
= GetOuterRect().GetIntersection( aDockingRect
);
1125 if ( aIntersect
.IsEmpty() )
1126 // docking rectangle completely outside docking area -> floating mode
1127 bBecomesFloating
= true;
1130 // create a small test rect around the mouse position and use this one
1131 // instead of the passed rRect to not dock too easily or by accident
1132 tools::Rectangle aSmallDockingRect
;
1133 aSmallDockingRect
.SetSize( Size( MAX_TOGGLEAREA_WIDTH
, MAX_TOGGLEAREA_HEIGHT
) );
1134 Point
aNewPos(rPos
);
1135 aNewPos
.AdjustX( -(aSmallDockingRect
.GetWidth()/2) );
1136 aNewPos
.AdjustY( -(aSmallDockingRect
.GetHeight()/2) );
1137 aSmallDockingRect
.SetPos(aNewPos
);
1138 tools::Rectangle aIntersectRect
= aInRect
.GetIntersection( aSmallDockingRect
);
1139 if ( aIntersectRect
== aSmallDockingRect
)
1140 // docking rectangle completely inside (shrunk) inner area -> floating mode
1141 bBecomesFloating
= true;
1144 if ( bBecomesFloating
)
1146 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
);
1150 // docking rectangle is in the "sensible area"
1151 Point
aInPosTL( aPos
.X()-aInRect
.Left(), aPos
.Y()-aInRect
.Top() );
1152 Point
aInPosBR( aPos
.X()-aInRect
.Left() + aDockingRect
.GetWidth(), aPos
.Y()-aInRect
.Top() + aDockingRect
.GetHeight() );
1153 Size aInSize
= aInRect
.GetSize();
1154 bool bNoChange
= false;
1156 // check if alignment is still unchanged
1157 switch ( GetAlignment() )
1159 case SfxChildAlignment::LEFT
:
1160 case SfxChildAlignment::FIRSTLEFT
:
1161 case SfxChildAlignment::LASTLEFT
:
1162 if (aInPosTL
.X() <= 0)
1164 eDockAlign
= GetAlignment();
1168 case SfxChildAlignment::TOP
:
1169 case SfxChildAlignment::LOWESTTOP
:
1170 case SfxChildAlignment::HIGHESTTOP
:
1171 if ( aInPosTL
.Y() <= 0)
1173 eDockAlign
= GetAlignment();
1177 case SfxChildAlignment::RIGHT
:
1178 case SfxChildAlignment::FIRSTRIGHT
:
1179 case SfxChildAlignment::LASTRIGHT
:
1180 if ( aInPosBR
.X() >= aInSize
.Width())
1182 eDockAlign
= GetAlignment();
1186 case SfxChildAlignment::BOTTOM
:
1187 case SfxChildAlignment::LOWESTBOTTOM
:
1188 case SfxChildAlignment::HIGHESTBOTTOM
:
1189 if ( aInPosBR
.Y() >= aInSize
.Height())
1191 eDockAlign
= GetAlignment();
1201 // alignment will change, test alignment according to distance of the docking rectangles edges
1202 bool bForbidden
= true;
1203 if ( aInPosTL
.X() <= 0)
1205 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::LEFT
);
1206 bForbidden
= ( eDockAlign
!= SfxChildAlignment::LEFT
&&
1207 eDockAlign
!= SfxChildAlignment::FIRSTLEFT
&&
1208 eDockAlign
!= SfxChildAlignment::LASTLEFT
);
1211 if ( bForbidden
&& aInPosTL
.Y() <= 0)
1213 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::TOP
);
1214 bForbidden
= ( eDockAlign
!= SfxChildAlignment::TOP
&&
1215 eDockAlign
!= SfxChildAlignment::HIGHESTTOP
&&
1216 eDockAlign
!= SfxChildAlignment::LOWESTTOP
);
1219 if ( bForbidden
&& aInPosBR
.X() >= aInSize
.Width())
1221 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::RIGHT
);
1222 bForbidden
= ( eDockAlign
!= SfxChildAlignment::RIGHT
&&
1223 eDockAlign
!= SfxChildAlignment::FIRSTRIGHT
&&
1224 eDockAlign
!= SfxChildAlignment::LASTRIGHT
);
1227 if ( bForbidden
&& aInPosBR
.Y() >= aInSize
.Height())
1229 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::BOTTOM
);
1230 bForbidden
= ( eDockAlign
!= SfxChildAlignment::BOTTOM
&&
1231 eDockAlign
!= SfxChildAlignment::HIGHESTBOTTOM
&&
1232 eDockAlign
!= SfxChildAlignment::LOWESTBOTTOM
);
1235 // the calculated alignment was rejected by the window -> take floating mode
1237 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
);
1241 if ( eDockAlign
== SfxChildAlignment::NOALIGNMENT
)
1243 // In the FloatingMode the tracking rectangle will get the floating
1244 // size. Due to a bug the rRect may only be changed when the
1245 // alignment is changed!
1246 if ( eDockAlign
!= pImpl
->GetDockAlignment() )
1247 aDockingRect
.SetSize( aFloatingSize
);
1251 sal_uInt16 nLine
, nPos
;
1252 SfxSplitWindow
*pSplitWin
= pWorkWin
->GetSplitWindow_Impl(eDockAlign
);
1253 aPos
= pSplitWin
->ScreenToOutputPixel( aPos
);
1254 if ( pSplitWin
->GetWindowPos( aPos
, nLine
, nPos
) )
1256 // mouse over splitwindow, get line and position
1257 pImpl
->nDockLine
= nLine
;
1258 pImpl
->nDockPos
= nPos
;
1259 pImpl
->bNewLine
= false;
1263 // mouse touches inner border -> create new line
1264 if ( eDockAlign
== GetAlignment() && pImpl
->pSplitWin
&&
1265 pImpl
->nLine
== pImpl
->pSplitWin
->GetLineCount()-1 && pImpl
->pSplitWin
->GetWindowCount(pImpl
->nLine
) == 1 )
1267 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1268 pImpl
->nDockLine
= pImpl
->nLine
;
1269 pImpl
->nDockPos
= pImpl
->nPos
;
1270 pImpl
->bNewLine
= false;
1275 pImpl
->nDockLine
= pSplitWin
->GetLineCount();
1276 pImpl
->nDockPos
= 0;
1277 pImpl
->bNewLine
= true;
1281 bool bChanged
= pImpl
->nLine
!= pImpl
->nDockLine
|| pImpl
->nPos
!= pImpl
->nDockPos
|| eDockAlign
!= GetAlignment();
1282 if ( !bChanged
&& !IsFloatingMode() )
1284 // window only slightly moved, no change of any property
1285 rRect
.SetSize( pImpl
->aSplitSize
);
1286 rRect
.SetPos( aDockingRect
.TopLeft() );
1290 // calculate new size and position
1292 Point aPoint
= aDockingRect
.TopLeft();
1293 Size aInnerSize
= GetInnerRect().GetSize();
1294 if ( eDockAlign
== SfxChildAlignment::LEFT
|| eDockAlign
== SfxChildAlignment::RIGHT
)
1296 if ( pImpl
->bNewLine
)
1298 // set height to height of free area
1299 aSize
.setHeight( aInnerSize
.Height() );
1300 aSize
.setWidth( pImpl
->nHorizontalSize
);
1301 if ( eDockAlign
== SfxChildAlignment::LEFT
)
1303 aPoint
= aInnerRect
.TopLeft();
1307 aPoint
= aInnerRect
.TopRight();
1308 aPoint
.AdjustX( -(aSize
.Width()) );
1313 // get width from splitwindow
1314 aSize
.setWidth( pSplitWin
->GetLineSize(nLine
) );
1315 aSize
.setHeight( pImpl
->aSplitSize
.Height() );
1320 if ( pImpl
->bNewLine
)
1322 // set width to width of free area
1323 aSize
.setWidth( aInnerSize
.Width() );
1324 aSize
.setHeight( pImpl
->nVerticalSize
);
1325 if ( eDockAlign
== SfxChildAlignment::TOP
)
1327 aPoint
= aInnerRect
.TopLeft();
1331 aPoint
= aInnerRect
.BottomLeft();
1332 aPoint
.AdjustY( -(aSize
.Height()) );
1337 // get height from splitwindow
1338 aSize
.setHeight( pSplitWin
->GetLineSize(nLine
) );
1339 aSize
.setWidth( pImpl
->aSplitSize
.Width() );
1343 aDockingRect
.SetSize( aSize
);
1344 aDockingRect
.SetPos( aPoint
);
1347 rRect
= aDockingRect
;
1351 /** Virtual method of the SfxDockingWindow class. This method determines how
1352 the size of the DockingWindows changes depending on the alignment. The base
1353 implementation uses the floating mode, the size of the marked Floating
1354 Size. For horizontal alignment, the width will be the width of the outer
1355 DockingRectangle, with vertical alignment the height will be the height of
1356 the inner DockingRectangle (resulting from the order in which the SFX child
1357 windows are displayed). The other size is set to the current floating-size,
1358 this could changed by a to intervening derived class. The docking size must
1359 be the same for Left/Right and Top/Bottom.
1361 Size
SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign
)
1363 // Note: if the resizing is also possible in the docked state, then the
1364 // Floating-size does also have to be adjusted?
1366 Size aSize
= GetFloatingSize();
1369 case SfxChildAlignment::TOP
:
1370 case SfxChildAlignment::BOTTOM
:
1371 case SfxChildAlignment::LOWESTTOP
:
1372 case SfxChildAlignment::HIGHESTTOP
:
1373 case SfxChildAlignment::LOWESTBOTTOM
:
1374 case SfxChildAlignment::HIGHESTBOTTOM
:
1375 aSize
.setWidth( aOuterRect
.Right() - aOuterRect
.Left() );
1377 case SfxChildAlignment::LEFT
:
1378 case SfxChildAlignment::RIGHT
:
1379 case SfxChildAlignment::FIRSTLEFT
:
1380 case SfxChildAlignment::LASTLEFT
:
1381 case SfxChildAlignment::FIRSTRIGHT
:
1382 case SfxChildAlignment::LASTRIGHT
:
1383 aSize
.setHeight( aInnerRect
.Bottom() - aInnerRect
.Top() );
1385 case SfxChildAlignment::NOALIGNMENT
:
1394 /** Virtual method of the SfxDockingWindow class. Here a derived class can
1395 disallow certain alignments. The base implementation does not
1398 SfxChildAlignment
SfxDockingWindow::CheckAlignment(SfxChildAlignment
,
1399 SfxChildAlignment eAlign
)
1404 /** The window is closed when the ChildWindow is destroyed by running the
1405 ChildWindow-slots. If this is method is overridden by a derived class
1406 method, then the SfxDockingDialogWindow: Close() must be called afterwards
1407 if the Close() was not cancelled with "return sal_False".
1409 bool SfxDockingWindow::Close()
1411 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
1415 SfxBoolItem
aValue( pMgr
->GetType(), false);
1416 pBindings
->GetDispatcher_Impl()->ExecuteList(
1417 pMgr
->GetType(), SfxCallMode::RECORD
| SfxCallMode::ASYNCHRON
,
1422 void SfxDockingWindow::Paint(vcl::RenderContext
&, const tools::Rectangle
& /*rRect*/)
1426 /** With this method, a minimal OutputSize be can set, that is queried in
1427 the Resizing()-Handler.
1429 void SfxDockingWindow::SetMinOutputSizePixel( const Size
& rSize
)
1431 pImpl
->aMinSize
= rSize
;
1432 ResizableDockingWindow::SetMinOutputSizePixel( rSize
);
1435 /** Set the minimum size which is returned.*/
1436 const Size
& SfxDockingWindow::GetMinOutputSizePixel() const
1438 return pImpl
->aMinSize
;
1441 bool SfxDockingWindow::EventNotify( NotifyEvent
& rEvt
)
1444 return ResizableDockingWindow::EventNotify( rEvt
);
1446 if ( rEvt
.GetType() == NotifyEventType::GETFOCUS
)
1448 if (pMgr
!= nullptr)
1449 pBindings
->SetActiveFrame( pMgr
->GetFrame() );
1451 if ( pImpl
->pSplitWin
)
1452 pImpl
->pSplitWin
->SetActiveWindow_Impl( this );
1453 else if (pMgr
!= nullptr)
1454 pMgr
->Activate_Impl();
1456 // In VCL EventNotify goes first to the window itself, also call the
1457 // base class, otherwise the parent learns nothing
1458 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1459 ResizableDockingWindow::EventNotify( rEvt
);
1460 // tdf#151112 move focus into container widget hierarchy if not already there
1461 if (m_xContainer
&& !m_xContainer
->has_child_focus())
1462 m_xContainer
->child_grab_focus();
1465 else if( rEvt
.GetType() == NotifyEventType::KEYINPUT
)
1467 // First, allow KeyInput for Dialog functions
1468 if (!DockingWindow::EventNotify(rEvt
) && SfxViewShell::Current())
1470 // then also for valid global accelerators.
1471 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt
.GetKeyEvent() );
1475 else if ( rEvt
.GetType() == NotifyEventType::LOSEFOCUS
&& !HasChildPathFocus() )
1477 pBindings
->SetActiveFrame( nullptr );
1480 return ResizableDockingWindow::EventNotify( rEvt
);
1483 void SfxDockingWindow::SetItemSize_Impl( const Size
& rSize
)
1485 pImpl
->aSplitSize
= rSize
;
1487 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1488 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1491 void SfxDockingWindow::Disappear_Impl()
1493 if ( pImpl
->pSplitWin
&& pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1494 pImpl
->pSplitWin
->RemoveWindow(this);
1497 void SfxDockingWindow::Reappear_Impl()
1499 if ( pImpl
->pSplitWin
&& !pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1501 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
);
1505 bool SfxDockingWindow::IsAutoHide_Impl() const
1507 if ( pImpl
->pSplitWin
)
1508 return !pImpl
->pSplitWin
->IsFadeIn();
1513 void SfxDockingWindow::AutoShow_Impl()
1515 if ( pImpl
->pSplitWin
)
1517 pImpl
->pSplitWin
->FadeIn();
1521 void SfxDockingWindow::StateChanged( StateChangedType nStateChange
)
1523 if ( nStateChange
== StateChangedType::InitShow
)
1526 ResizableDockingWindow::StateChanged( nStateChange
);
1529 void SfxDockingWindow::Move()
1532 pImpl
->aMoveIdle
.Start();
1535 IMPL_LINK_NOARG(SfxDockingWindow
, TimerHdl
, Timer
*, void)
1537 pImpl
->aMoveIdle
.Stop();
1538 if ( IsReallyVisible() && IsFloatingMode() )
1540 SetFloatingSize( GetOutputSizePixel() );
1541 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
1542 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1543 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */