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 <osl/diagnose.h>
30 #include <toolkit/helper/vclunohelper.hxx>
31 #include <tools/debug.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/propertysequence.hxx>
35 #include <sfx2/dockwin.hxx>
36 #include <sfx2/bindings.hxx>
37 #include <sfx2/viewfrm.hxx>
38 #include <sfx2/dispatch.hxx>
39 #include <workwin.hxx>
40 #include <splitwin.hxx>
41 #include <sfx2/viewsh.hxx>
43 #include <com/sun/star/beans/UnknownPropertyException.hpp>
44 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
45 #include <com/sun/star/awt/XWindow.hpp>
46 #include <com/sun/star/uno/XComponentContext.hpp>
47 #include <com/sun/star/frame/ModuleManager.hpp>
48 #include <com/sun/star/container/XNameAccess.hpp>
49 #include <com/sun/star/ui/theWindowStateConfiguration.hpp>
50 #include <com/sun/star/ui/theWindowContentFactoryManager.hpp>
52 #define MAX_TOGGLEAREA_WIDTH 20
53 #define MAX_TOGGLEAREA_HEIGHT 20
55 using namespace ::com::sun::star
;
57 // If you want to change the number you also have to:
58 // - Add new slot ids to sfxsids.hrc
59 // - Add new slots to frmslots.sdi
60 // - Add new slot definitions to sfx.sdi
61 const int NUM_OF_DOCKINGWINDOWS
= 10;
65 class SfxTitleDockingWindow
: public SfxDockingWindow
67 VclPtr
<vcl::Window
> m_pWrappedWindow
;
70 SfxTitleDockingWindow(
71 SfxBindings
* pBindings
,
72 SfxChildWindow
* pChildWin
,
73 vcl::Window
* pParent
,
75 virtual ~SfxTitleDockingWindow() override
;
76 virtual void dispose() override
;
78 vcl::Window
* GetWrappedWindow() const { return m_pWrappedWindow
; }
79 void SetWrappedWindow(vcl::Window
* const pWindow
);
81 virtual void StateChanged( StateChangedType nType
) override
;
82 virtual void Resize() override
;
83 virtual void Resizing( Size
& rSize
) override
;
92 static bool lcl_getWindowState( const uno::Reference
< container::XNameAccess
>& xWindowStateMgr
, const OUString
& rResourceURL
, WindowState
& rWindowState
)
99 uno::Sequence
< beans::PropertyValue
> aWindowState
;
100 a
= xWindowStateMgr
->getByName( rResourceURL
);
101 if ( a
>>= aWindowState
)
103 for ( const auto& rProp
: std::as_const(aWindowState
) )
105 if ( rProp
.Name
== "UIName" )
107 rProp
.Value
>>= rWindowState
.sTitle
;
114 catch ( container::NoSuchElementException
& )
122 SfxDockingWrapper::SfxDockingWrapper( vcl::Window
* pParentWnd
,
124 SfxBindings
* pBindings
,
125 SfxChildWinInfo
* pInfo
)
126 : SfxChildWindow( pParentWnd
, nId
)
128 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
130 VclPtr
<SfxTitleDockingWindow
> pTitleDockWindow
= VclPtr
<SfxTitleDockingWindow
>::Create( pBindings
, this, pParentWnd
,
131 WB_STDDOCKWIN
| WB_CLIPCHILDREN
| WB_SIZEABLE
| WB_3DLOOK
);
132 SetWindow( pTitleDockWindow
);
134 // Use factory manager to retrieve XWindow factory. That can be used to instantiate
135 // the real window factory.
136 uno::Reference
< lang::XSingleComponentFactory
> xFactoryMgr
= ui::theWindowContentFactoryManager::get(xContext
);
138 SfxDispatcher
* pDispatcher
= pBindings
->GetDispatcher();
139 uno::Reference
< frame::XFrame
> xFrame
= pDispatcher
->GetFrame()->GetFrame().GetFrameInterface();
140 // create a resource URL from the nId provided by the sfx2
141 OUString aResourceURL
= "private:resource/dockingwindow/" + OUString::number(nId
);
142 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
144 {"Frame", uno::Any(xFrame
)},
145 {"ResourceURL", uno::Any(aResourceURL
)},
148 uno::Reference
< awt::XWindow
> xWindow
;
152 xFactoryMgr
->createInstanceWithArgumentsAndContext( aArgs
, xContext
),
155 static uno::WeakReference
< frame::XModuleManager2
> s_xModuleManager
;
157 uno::Reference
< frame::XModuleManager2
> xModuleManager( s_xModuleManager
);
158 if ( !xModuleManager
.is() )
160 xModuleManager
= frame::ModuleManager::create(xContext
);
161 s_xModuleManager
= xModuleManager
;
164 static uno::WeakReference
< container::XNameAccess
> s_xWindowStateConfiguration
;
166 uno::Reference
< container::XNameAccess
> xWindowStateConfiguration( s_xWindowStateConfiguration
);
167 if ( !xWindowStateConfiguration
.is() )
169 xWindowStateConfiguration
= ui::theWindowStateConfiguration::get( xContext
);
170 s_xWindowStateConfiguration
= xWindowStateConfiguration
;
173 OUString sModuleIdentifier
= xModuleManager
->identify( xFrame
);
175 uno::Reference
< container::XNameAccess
> xModuleWindowState(
176 xWindowStateConfiguration
->getByName( sModuleIdentifier
),
178 if ( xModuleWindowState
.is() )
180 WindowState aDockWinState
;
181 if ( lcl_getWindowState( xModuleWindowState
, aResourceURL
, aDockWinState
))
182 pTitleDockWindow
->SetText( aDockWinState
.sTitle
);
185 catch ( beans::UnknownPropertyException
& )
188 catch ( uno::RuntimeException
& )
191 catch ( uno::Exception
& )
195 VclPtr
<vcl::Window
> pContentWindow
= VCLUnoHelper::GetWindow(xWindow
);
196 if ( pContentWindow
)
197 pContentWindow
->SetStyle( pContentWindow
->GetStyle() | WB_DIALOGCONTROL
| WB_CHILDDLGCTRL
);
198 pTitleDockWindow
->SetWrappedWindow(pContentWindow
);
200 GetWindow()->SetOutputSizePixel( Size( 270, 240 ) );
202 static_cast<SfxDockingWindow
*>( GetWindow() )->Initialize( pInfo
);
203 SetHideNotDelete( true );
206 std::unique_ptr
<SfxChildWindow
> SfxDockingWrapper::CreateImpl(vcl::Window
*pParent
, sal_uInt16 nId
,
207 SfxBindings
*pBindings
, SfxChildWinInfo
* pInfo
)
209 return std::make_unique
<SfxDockingWrapper
>(pParent
, nId
, pBindings
, pInfo
);
212 void SfxDockingWrapper::RegisterChildWindow (bool bVis
, SfxModule
*pMod
, SfxChildWindowFlags nFlags
)
214 // pre-register a couple of docking windows
215 for (int i
=0; i
< NUM_OF_DOCKINGWINDOWS
; i
++ )
217 sal_uInt16 nID
= sal_uInt16(SID_DOCKWIN_START
+i
);
218 SfxChildWinFactory
aFact( SfxDockingWrapper::CreateImpl
, nID
, 0xffff );
219 aFact
.aInfo
.nFlags
|= nFlags
;
220 aFact
.aInfo
.bVisible
= bVis
;
221 SfxChildWindow::RegisterChildWindow(pMod
, aFact
);
225 SfxChildWinInfo
SfxDockingWrapper::GetInfo() const
227 SfxChildWinInfo aInfo
= SfxChildWindow::GetInfo();
228 static_cast<SfxDockingWindow
*>(GetWindow())->FillInfo( aInfo
);
232 SfxTitleDockingWindow::SfxTitleDockingWindow(SfxBindings
* pBind
, SfxChildWindow
* pChildWin
,
233 vcl::Window
* pParent
, WinBits nBits
)
234 : SfxDockingWindow(pBind
, pChildWin
, pParent
, nBits
)
235 , m_pWrappedWindow(nullptr)
239 SfxTitleDockingWindow::~SfxTitleDockingWindow()
244 void SfxTitleDockingWindow::dispose()
246 m_pWrappedWindow
.disposeAndClear();
247 SfxDockingWindow::dispose();
250 void SfxTitleDockingWindow::SetWrappedWindow( vcl::Window
* const pWindow
)
252 m_pWrappedWindow
= pWindow
;
253 if (m_pWrappedWindow
)
255 m_pWrappedWindow
->SetParent(this);
256 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
257 m_pWrappedWindow
->Show();
261 void SfxTitleDockingWindow::StateChanged( StateChangedType nType
)
263 if ( nType
== StateChangedType::InitShow
)
265 vcl::Window
* pWindow
= GetWrappedWindow();
268 pWindow
->SetSizePixel( GetOutputSizePixel() );
273 SfxDockingWindow::StateChanged(nType
);
276 void SfxTitleDockingWindow::Resize()
278 SfxDockingWindow::Resize();
279 if (m_pWrappedWindow
)
280 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
283 void SfxTitleDockingWindow::Resizing( Size
&rSize
)
285 SfxDockingWindow::Resizing( rSize
);
286 if (m_pWrappedWindow
)
287 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
290 static bool lcl_checkDockingWindowID( sal_uInt16 nID
)
292 return nID
>= SID_DOCKWIN_START
&& nID
< o3tl::make_unsigned(SID_DOCKWIN_START
+NUM_OF_DOCKINGWINDOWS
);
295 static SfxWorkWindow
* lcl_getWorkWindowFromXFrame( const uno::Reference
< frame::XFrame
>& rFrame
)
297 // We need to find the corresponding SfxFrame of our XFrame
298 SfxFrame
* pFrame
= SfxFrame::GetFirst();
299 SfxFrame
* pXFrame
= nullptr;
302 uno::Reference
< frame::XFrame
> xViewShellFrame( pFrame
->GetFrameInterface() );
303 if ( xViewShellFrame
== rFrame
)
309 pFrame
= SfxFrame::GetNext( *pFrame
);
312 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
314 return pXFrame
->GetWorkWindow_Impl();
319 /** Factory function used by the framework layout manager to "create" a docking window with a special name.
320 The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
321 in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
323 void SfxDockingWindowFactory( const uno::Reference
< frame::XFrame
>& rFrame
, const OUString
& rDockingWindowName
)
325 SolarMutexGuard aGuard
;
326 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
328 // Check the range of the provided ID otherwise nothing will happen
329 if ( !lcl_checkDockingWindowID( nID
))
332 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
335 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
338 // Register window at the workwindow child window list
339 pWorkWindow
->SetChildWindow_Impl( nID
, true, false );
344 /** Function used by the framework layout manager to determine the visibility state of a docking window with
345 a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
346 range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
348 bool IsDockingWindowVisible( const uno::Reference
< frame::XFrame
>& rFrame
, const OUString
& rDockingWindowName
)
350 SolarMutexGuard aGuard
;
352 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
354 // Check the range of the provided ID otherwise nothing will happen
355 if ( lcl_checkDockingWindowID( nID
))
357 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
360 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
369 class SfxDockingWindow_Impl
371 friend class SfxDockingWindow
;
373 SfxChildAlignment eLastAlignment
;
374 SfxChildAlignment eDockAlignment
;
377 VclPtr
<SfxSplitWindow
> pSplitWin
;
380 // The following members are only valid in the time from startDocking to
383 tools::Long nHorizontalSize
;
384 tools::Long nVerticalSize
;
387 sal_uInt16 nDockLine
;
390 bool bDockingPrevented
;
393 explicit SfxDockingWindow_Impl(SfxDockingWindow
*pBase
);
394 SfxChildAlignment
GetLastAlignment() const
395 { return eLastAlignment
; }
396 void SetLastAlignment(SfxChildAlignment eAlign
)
397 { eLastAlignment
= eAlign
; }
398 SfxChildAlignment
GetDockAlignment() const
399 { return eDockAlignment
; }
400 void SetDockAlignment(SfxChildAlignment eAlign
)
401 { eDockAlignment
= eAlign
; }
404 SfxDockingWindow_Impl::SfxDockingWindow_Impl(SfxDockingWindow
* pBase
)
405 :eLastAlignment(SfxChildAlignment::NOALIGNMENT
)
406 ,eDockAlignment(SfxChildAlignment::NOALIGNMENT
)
409 ,aMoveIdle( "sfx::SfxDockingWindow_Impl aMoveIdle" )
417 ,bDockingPrevented(false)
419 aMoveIdle
.SetPriority(TaskPriority::RESIZE
);
420 aMoveIdle
.SetInvokeHandler(LINK(pBase
,SfxDockingWindow
,TimerHdl
));
425 This virtual method of the class FloatingWindow keeps track of changes in
426 FloatingSize. If this method is overridden by a derived class,
427 then the FloatingWindow: Resize() must also be called.
429 void SfxDockingWindow::Resize()
431 ResizableDockingWindow::Resize();
433 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
436 if ( IsFloatingMode() )
438 // start timer for saving window status information
439 pImpl
->aMoveIdle
.Start();
443 Size
aSize( GetSizePixel() );
444 switch ( pImpl
->GetDockAlignment() )
446 case SfxChildAlignment::LEFT
:
447 case SfxChildAlignment::FIRSTLEFT
:
448 case SfxChildAlignment::LASTLEFT
:
449 case SfxChildAlignment::RIGHT
:
450 case SfxChildAlignment::FIRSTRIGHT
:
451 case SfxChildAlignment::LASTRIGHT
:
452 pImpl
->nHorizontalSize
= aSize
.Width();
453 pImpl
->aSplitSize
= aSize
;
455 case SfxChildAlignment::TOP
:
456 case SfxChildAlignment::LOWESTTOP
:
457 case SfxChildAlignment::HIGHESTTOP
:
458 case SfxChildAlignment::BOTTOM
:
459 case SfxChildAlignment::HIGHESTBOTTOM
:
460 case SfxChildAlignment::LOWESTBOTTOM
:
461 pImpl
->nVerticalSize
= aSize
.Height();
462 pImpl
->aSplitSize
= aSize
;
472 This virtual method of the class DockingWindow makes it possible to
473 intervene in the switching of the floating mode.
474 If this method is overridden by a derived class,
475 then the SfxDockingWindow::PrepareToggleFloatingMode() must be called
476 afterwards, if not FALSE is returned.
478 bool SfxDockingWindow::PrepareToggleFloatingMode()
480 if (!pImpl
|| !pImpl
->bConstructed
)
483 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr
)
486 if ( pImpl
->bDockingPrevented
)
489 if (!IsFloatingMode())
491 // Test, if FloatingMode is permitted.
492 if ( CheckAlignment(GetAlignment(),SfxChildAlignment::NOALIGNMENT
) != SfxChildAlignment::NOALIGNMENT
)
495 if ( pImpl
->pSplitWin
)
497 // The DockingWindow is inside a SplitWindow and will be teared of.
498 pImpl
->pSplitWin
->RemoveWindow(this/*, sal_False*/);
499 pImpl
->pSplitWin
= nullptr;
504 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
506 // Test if it is allowed to dock,
507 if (CheckAlignment(GetAlignment(),pImpl
->GetLastAlignment()) == SfxChildAlignment::NOALIGNMENT
)
510 // Test, if the Workwindow allows for docking at the moment.
511 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
512 if ( !pWorkWin
->IsDockingAllowed() || !pWorkWin
->IsInternalDockingAllowed() )
521 This virtual method of the DockingWindow class sets the internal data of
522 the SfxDockingWindow and ensures the correct alignment on the parent window.
523 Through PrepareToggleFloatMode and Initialize it is ensured that
524 pImpl-> GetLastAlignment() always delivers an allowed alignment. If this
525 method is overridden by a derived class, then first the
526 SfxDockingWindow::ToggleFloatingMode() must be called.
528 void SfxDockingWindow::ToggleFloatingMode()
530 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
531 return; // No Handler call
533 // Remember old alignment and then switch.
534 // SV has already switched, but the alignment SfxDockingWindow is still
535 // the old one. What I was before?
536 SfxChildAlignment eLastAlign
= GetAlignment();
538 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
540 if (IsFloatingMode())
542 SetAlignment(SfxChildAlignment::NOALIGNMENT
);
543 if ( !pImpl
->aWinState
.isEmpty() )
544 GetFloatingWindow()->SetWindowState( pImpl
->aWinState
);
546 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
550 if (pImpl
->GetDockAlignment() == eLastAlign
)
552 // If ToggleFloatingMode was called, but the DockAlignment still
553 // is unchanged, then this means that it must have been a toggling
554 // through DClick, so use last alignment
555 SetAlignment (pImpl
->GetLastAlignment());
560 // Toggling was triggered by dragging
561 pImpl
->nLine
= pImpl
->nDockLine
;
562 pImpl
->nPos
= pImpl
->nDockPos
;
563 SetAlignment (pImpl
->GetDockAlignment());
566 // The DockingWindow is now in a SplitWindow
567 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
569 // The LastAlignment is still the last docked
570 SfxSplitWindow
*pSplit
= pWorkWin
->GetSplitWindow_Impl(pImpl
->GetLastAlignment());
572 DBG_ASSERT( pSplit
, "LastAlignment is not correct!" );
573 if ( pSplit
&& pSplit
!= pImpl
->pSplitWin
)
574 pSplit
->ReleaseWindow_Impl(this);
575 if ( pImpl
->GetDockAlignment() == eLastAlign
)
576 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
);
578 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
, pImpl
->nLine
, pImpl
->nPos
, pImpl
->bNewLine
);
579 if ( !pImpl
->pSplitWin
->IsFadeIn() )
580 pImpl
->pSplitWin
->FadeIn();
583 // Keep the old alignment for the next toggle; set it only now due to the
584 // unregister SplitWindow!
585 pImpl
->SetLastAlignment(eLastAlign
);
587 // Reset DockAlignment, if EndDocking is still called
588 pImpl
->SetDockAlignment(GetAlignment());
590 // Dock or undock SfxChildWindow correctly.
591 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::TOGGLEFLOATMODE
, pMgr
->GetType() );
596 This virtual method of the DockingWindow class takes the inner and outer
597 docking rectangle from the parent window. If this method is overridden by
598 a derived class, then SfxDockingWindow:StartDocking() has to be called at
601 void SfxDockingWindow::StartDocking()
603 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
605 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
606 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::SETDOCKINGRECTS
, pMgr
->GetType() );
607 pImpl
->SetDockAlignment(GetAlignment());
609 if ( pImpl
->pSplitWin
)
611 // Get the current docking data
612 pImpl
->pSplitWin
->GetWindowPos(this, pImpl
->nLine
, pImpl
->nPos
);
613 pImpl
->nDockLine
= pImpl
->nLine
;
614 pImpl
->nDockPos
= pImpl
->nPos
;
615 pImpl
->bNewLine
= false;
621 This virtual method of the DockingWindow class calculates the current
622 tracking rectangle. For this purpose the method CalcAlignment(RPOs, rRect)
623 is used, the behavior can be influenced by the derived classes (see below).
624 This method should if possible not be overwritten.
626 bool SfxDockingWindow::Docking( const Point
& rPos
, tools::Rectangle
& rRect
)
628 if ( Application::IsInModalMode() )
631 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
633 rRect
.SetSize( Size() );
634 return IsFloatingMode();
637 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
638 if ( pImpl
->bDockingPrevented
|| !pWorkWin
->IsInternalDockingAllowed() )
641 bool bFloatMode
= false;
643 if ( GetOuterRect().Contains( rPos
) )
645 // Mouse within OuterRect: calculate Alignment and Rectangle
646 SfxChildAlignment eAlign
= CalcAlignment(rPos
, rRect
);
647 if (eAlign
== SfxChildAlignment::NOALIGNMENT
)
649 pImpl
->SetDockAlignment(eAlign
);
653 // Mouse is not within OuterRect: must be FloatingWindow
655 if (CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
) != SfxChildAlignment::NOALIGNMENT
)
658 if ( SfxChildAlignment::NOALIGNMENT
!= pImpl
->GetDockAlignment() )
660 // Due to a bug the rRect may only be changed when the
661 // alignment is changed!
662 pImpl
->SetDockAlignment(SfxChildAlignment::NOALIGNMENT
);
663 rRect
.SetSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT
));
670 /** Virtual method of the DockingWindow class ensures the correct alignment on
671 the parent window. If this method is overridden by a derived class, then
672 SfxDockingWindow::EndDocking() must be called first.
674 void SfxDockingWindow::EndDocking( const tools::Rectangle
& rRect
, bool bFloatMode
)
676 if ( !pImpl
|| !pImpl
->bConstructed
|| IsDockingCanceled() || !pMgr
)
679 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
681 // If the alignment changes and the window is in a docked state in a
682 // SplitWindow, then it must be re-registered. If it is docked again,
683 // PrepareToggleFloatingMode() and ToggleFloatingMode() perform the
685 bool bReArrange
= !bFloatMode
;
689 if ( GetAlignment() != pImpl
->GetDockAlignment() )
691 // before Show() is called must the reassignment have been made,
692 // therefore the base class can not be called
693 if ( IsFloatingMode() )
694 Show( false, ShowFlags::NoFocusChange
);
696 // Set the size for toggling.
697 pImpl
->aSplitSize
= rRect
.GetSize();
698 if ( IsFloatingMode() )
700 SetFloatingMode( bFloatMode
);
701 if ( IsFloatingMode() )
702 Show( true, ShowFlags::NoFocusChange
);
706 pImpl
->pSplitWin
->RemoveWindow(this,false);
707 pImpl
->nLine
= pImpl
->nDockLine
;
708 pImpl
->nPos
= pImpl
->nDockPos
;
709 pImpl
->pSplitWin
->ReleaseWindow_Impl(this);
710 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(pImpl
->GetDockAlignment());
711 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
, pImpl
->nDockLine
, pImpl
->nDockPos
, pImpl
->bNewLine
);
712 if ( !pImpl
->pSplitWin
->IsFadeIn() )
713 pImpl
->pSplitWin
->FadeIn();
716 else if ( pImpl
->nLine
!= pImpl
->nDockLine
|| pImpl
->nPos
!= pImpl
->nDockPos
|| pImpl
->bNewLine
)
718 // Moved within Splitwindows
719 if ( pImpl
->nLine
!= pImpl
->nDockLine
)
720 pImpl
->aSplitSize
= rRect
.GetSize();
721 pImpl
->pSplitWin
->MoveWindow( this, pImpl
->aSplitSize
, pImpl
->nDockLine
, pImpl
->nDockPos
, pImpl
->bNewLine
);
726 ResizableDockingWindow::EndDocking(rRect
, bFloatMode
);
729 SetAlignment( IsFloatingMode() ? SfxChildAlignment::NOALIGNMENT
: pImpl
->GetDockAlignment() );
734 Virtual method of the DockingWindow class. Here, the interactive resize in
735 FloatingMode can be influenced, for example by only allowing for discrete
736 values for width and / or height. The base implementation prevents that the
737 output size is smaller than one set with SetMinOutputSizePixel().
739 void SfxDockingWindow::Resizing( Size
& /*rSize*/ )
746 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
747 required because the docking is implemented in Sfx through SfxChildWindows.
749 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
750 vcl::Window
* pParent
, WinBits nWinBits
)
751 : ResizableDockingWindow(pParent
, nWinBits
)
752 , pBindings(pBindinx
)
755 pImpl
.reset(new SfxDockingWindow_Impl(this));
758 /** Constructor for the SfxDockingWindow class. A SfxChildWindow will be
759 required because the docking is implemented in Sfx through SfxChildWindows.
761 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
762 vcl::Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
)
763 : ResizableDockingWindow(pParent
)
764 , pBindings(pBindinx
)
767 m_xBuilder
= Application::CreateInterimBuilder(m_xBox
, rUIXMLDescription
, true);
768 m_xContainer
= m_xBuilder
->weld_box(rID
);
770 pImpl
.reset(new SfxDockingWindow_Impl(this));
773 /** Initialization of the SfxDockingDialog class via a SfxChildWinInfo.
774 The initialization is done only in a 2nd step after the constructor, this
775 constructor should be called from the derived class or from the
778 void SfxDockingWindow::Initialize(SfxChildWinInfo
*pInfo
)
782 pImpl
->SetDockAlignment( SfxChildAlignment::NOALIGNMENT
);
783 pImpl
->bConstructed
= true;
787 if (pInfo
&& (pInfo
->nFlags
& SfxChildWindowFlags::FORCEDOCK
))
788 pImpl
->bDockingPrevented
= true;
790 pImpl
->aSplitSize
= GetOutputSizePixel();
791 if ( !GetFloatingSize().Width() )
793 Size
aMinSize( GetMinOutputSizePixel() );
794 SetFloatingSize( pImpl
->aSplitSize
);
795 if ( pImpl
->aSplitSize
.Width() < aMinSize
.Width() )
796 pImpl
->aSplitSize
.setWidth( aMinSize
.Width() );
797 if ( pImpl
->aSplitSize
.Height() < aMinSize
.Height() )
798 pImpl
->aSplitSize
.setHeight( aMinSize
.Height() );
801 bool bVertHorzRead( false );
802 if (pInfo
&& !pInfo
->aExtraString
.isEmpty())
804 // get information about alignment, split size and position in SplitWindow
806 sal_Int32 nPos
= pInfo
->aExtraString
.indexOf("AL:");
809 // alignment information
810 sal_Int32 n1
= pInfo
->aExtraString
.indexOf('(', nPos
);
813 sal_Int32 n2
= pInfo
->aExtraString
.indexOf(')', n1
);
816 // extract alignment information from extrastring
817 aStr
= pInfo
->aExtraString
.copy(nPos
, n2
- nPos
+ 1);
818 pInfo
->aExtraString
= pInfo
->aExtraString
.replaceAt(nPos
, n2
- nPos
+ 1, u
"");
819 aStr
= aStr
.replaceAt(nPos
, n1
-nPos
+1, u
"");
824 if ( !aStr
.isEmpty() )
826 // accept window state only if alignment is also set
827 pImpl
->aWinState
= pInfo
->aWinState
;
829 // check for valid alignment
830 SfxChildAlignment eLocalAlignment
= static_cast<SfxChildAlignment
>(static_cast<sal_uInt16
>(aStr
.toInt32()));
831 bool bIgnoreFloatConfig
= (eLocalAlignment
== SfxChildAlignment::NOALIGNMENT
&&
832 !StyleSettings::GetDockingFloatsSupported());
833 if (pImpl
->bDockingPrevented
|| bIgnoreFloatConfig
)
834 // docking prevented, ignore old configuration and take alignment from default
837 SetAlignment( eLocalAlignment
);
839 SfxChildAlignment eAlign
= CheckAlignment(GetAlignment(),GetAlignment());
840 if ( eAlign
!= GetAlignment() )
842 OSL_FAIL("Invalid Alignment!");
843 SetAlignment( eAlign
);
847 // get last alignment (for toggling)
848 nPos
= aStr
.indexOf(',');
851 aStr
= aStr
.copy(nPos
+1);
852 pImpl
->SetLastAlignment( static_cast<SfxChildAlignment
>(static_cast<sal_uInt16
>(aStr
.toInt32())) );
855 nPos
= aStr
.indexOf(',');
858 // get split size and position in SplitWindow
860 aStr
= aStr
.copy(nPos
+1);
861 if ( GetPosSizeFromString( aStr
, aPos
, pImpl
->aSplitSize
) )
863 pImpl
->nLine
= pImpl
->nDockLine
= static_cast<sal_uInt16
>(aPos
.X());
864 pImpl
->nPos
= pImpl
->nDockPos
= static_cast<sal_uInt16
>(aPos
.Y());
865 pImpl
->nVerticalSize
= pImpl
->aSplitSize
.Height();
866 pImpl
->nHorizontalSize
= pImpl
->aSplitSize
.Width();
867 if ( GetSplitSizeFromString( aStr
, pImpl
->aSplitSize
))
868 bVertHorzRead
= true;
873 OSL_FAIL( "Information is missing!" );
877 if ( !bVertHorzRead
)
879 pImpl
->nVerticalSize
= pImpl
->aSplitSize
.Height();
880 pImpl
->nHorizontalSize
= pImpl
->aSplitSize
.Width();
883 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
884 if ( GetAlignment() != SfxChildAlignment::NOALIGNMENT
)
886 // check if SfxWorkWindow is able to allow docking at its border
888 !pWorkWin
->IsDockingAllowed() ||
889 !pWorkWin
->IsInternalDockingAllowed() ||
890 ( (GetFloatStyle() & WB_STANDALONE
) && Application::IsInModalMode()) )
892 SetAlignment( SfxChildAlignment::NOALIGNMENT
);
896 // detect floating mode
897 // toggling mode will not execute code in handlers, because pImpl->bConstructed is not set yet
898 bool bFloatMode
= IsFloatingMode();
899 if ( bFloatMode
!= (GetAlignment() == SfxChildAlignment::NOALIGNMENT
) )
901 bFloatMode
= !bFloatMode
;
902 SetFloatingMode( bFloatMode
);
905 if ( !pImpl
->aWinState
.isEmpty() )
906 GetFloatingWindow()->SetWindowState( pImpl
->aWinState
);
908 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
912 if ( IsFloatingMode() )
914 // validate last alignment
915 SfxChildAlignment eLastAlign
= pImpl
->GetLastAlignment();
916 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
917 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::LEFT
);
918 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
919 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::RIGHT
);
920 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
921 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::TOP
);
922 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
923 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::BOTTOM
);
924 pImpl
->SetLastAlignment(eLastAlign
);
928 // docked window must have NOALIGNMENT as last alignment
929 pImpl
->SetLastAlignment(SfxChildAlignment::NOALIGNMENT
);
931 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
932 pImpl
->pSplitWin
->InsertWindow(this, pImpl
->aSplitSize
);
936 pImpl
->SetDockAlignment( GetAlignment() );
939 void SfxDockingWindow::Initialize_Impl()
943 pImpl
->bConstructed
= true;
947 SystemWindow
* pFloatWin
= GetFloatingWindow();
951 bSet
= !pFloatWin
->IsDefaultPos();
955 Point aPos
= GetFloatingPos();
956 if ( aPos
!= Point() )
962 SfxViewFrame
*pFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
963 vcl::Window
* pEditWin
= pFrame
->GetViewShell()->GetWindow();
964 Point aPos
= pEditWin
->OutputToScreenPixel( pEditWin
->GetPosPixel() );
965 aPos
= GetParent()->ScreenToOutputPixel( aPos
);
966 SetFloatingPos( aPos
);
971 // initialize floating window
972 if ( pImpl
->aWinState
.isEmpty() )
973 // window state never set before, get if from defaults
974 pImpl
->aWinState
= pFloatWin
->GetWindowState();
976 // trick: use VCL method SetWindowState to adjust position and size
977 pFloatWin
->SetWindowState( pImpl
->aWinState
);
978 Size
aSize(pFloatWin
->GetSizePixel());
980 // remember floating size for calculating alignment and tracking rectangle
981 SetFloatingSize(aSize
);
985 // allow calling of docking handlers
986 pImpl
->bConstructed
= true;
989 /** Fills a SfxChildWinInfo with specific data from SfxDockingWindow,
990 so that it can be written in the INI file. It is assumed that rinfo
991 receives all other possible relevant data in the ChildWindow class.
992 Insertions are marked with size and the ZoomIn flag.
993 If this method is overridden, the base implementation must be called first.
995 void SfxDockingWindow::FillInfo(SfxChildWinInfo
& rInfo
) const
1000 if (GetFloatingWindow() && pImpl
->bConstructed
)
1001 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
1003 rInfo
.aWinState
= pImpl
->aWinState
;
1004 rInfo
.aExtraString
= "AL:(";
1005 rInfo
.aExtraString
+= OUString::number(static_cast<sal_uInt16
>(GetAlignment()));
1006 rInfo
.aExtraString
+= ",";
1007 rInfo
.aExtraString
+= OUString::number (static_cast<sal_uInt16
>(pImpl
->GetLastAlignment()));
1009 Point
aPos(pImpl
->nLine
, pImpl
->nPos
);
1010 rInfo
.aExtraString
+= ",";
1011 rInfo
.aExtraString
+= OUString::number( aPos
.X() );
1012 rInfo
.aExtraString
+= "/";
1013 rInfo
.aExtraString
+= OUString::number( aPos
.Y() );
1014 rInfo
.aExtraString
+= "/";
1015 rInfo
.aExtraString
+= OUString::number( pImpl
->nHorizontalSize
);
1016 rInfo
.aExtraString
+= "/";
1017 rInfo
.aExtraString
+= OUString::number( pImpl
->nVerticalSize
);
1018 rInfo
.aExtraString
+= ",";
1019 rInfo
.aExtraString
+= OUString::number( pImpl
->aSplitSize
.Width() );
1020 rInfo
.aExtraString
+= ";";
1021 rInfo
.aExtraString
+= OUString::number( pImpl
->aSplitSize
.Height() );
1023 rInfo
.aExtraString
+= ")";
1026 SfxDockingWindow::~SfxDockingWindow()
1031 void SfxDockingWindow::dispose()
1033 ReleaseChildWindow_Impl();
1035 m_xContainer
.reset();
1037 ResizableDockingWindow::dispose();
1040 void SfxDockingWindow::ReleaseChildWindow_Impl()
1042 if ( pMgr
&& pMgr
->GetFrame() == pBindings
->GetActiveFrame() )
1043 pBindings
->SetActiveFrame( nullptr );
1045 if ( pMgr
&& pImpl
->pSplitWin
&& pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1046 pImpl
->pSplitWin
->RemoveWindow(this);
1051 /** This method calculates a resulting alignment for the given mouse position
1052 and tracking rectangle. When changing the alignment it can also be that
1053 the tracking rectangle is changed, so that an altered rectangle is
1054 returned. The user of this class can influence behaviour of this method,
1055 and thus the behavior of his DockinWindow class when docking where the
1056 called virtual method:
1058 SfxDockingWindow::CalcDockingSize (SfxChildAlignment eAlign)
1060 is overridden (see below).
1062 SfxChildAlignment
SfxDockingWindow::CalcAlignment(const Point
& rPos
, tools::Rectangle
& rRect
)
1064 // calculate hypothetical sizes for different modes
1065 Size
aFloatingSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT
));
1067 // check if docking is permitted
1068 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1069 if ( !pWorkWin
->IsDockingAllowed() )
1071 rRect
.SetSize( aFloatingSize
);
1072 return pImpl
->GetDockAlignment();
1075 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1076 tools::Long nLRBorder
, nTBBorder
;
1078 // take the smaller size of docked and floating mode
1079 Size aBorderTmp
= pImpl
->aSplitSize
;
1080 if ( GetFloatingSize().Height() < aBorderTmp
.Height() )
1081 aBorderTmp
.setHeight( GetFloatingSize().Height() );
1082 if ( GetFloatingSize().Width() < aBorderTmp
.Width() )
1083 aBorderTmp
.setWidth( GetFloatingSize().Width() );
1085 nLRBorder
= aBorderTmp
.Width();
1086 nTBBorder
= aBorderTmp
.Height();
1088 // limit border to predefined constant values
1089 if ( nLRBorder
> MAX_TOGGLEAREA_WIDTH
)
1090 nLRBorder
= MAX_TOGGLEAREA_WIDTH
;
1091 if ( nTBBorder
> MAX_TOGGLEAREA_WIDTH
)
1092 nTBBorder
= MAX_TOGGLEAREA_WIDTH
;
1094 // shrink area for floating mode if possible
1095 tools::Rectangle aInRect
= GetInnerRect();
1096 if ( aInRect
.GetWidth() > nLRBorder
)
1097 aInRect
.AdjustLeft(nLRBorder
/2 );
1098 if ( aInRect
.GetWidth() > nLRBorder
)
1099 aInRect
.AdjustRight( -(nLRBorder
/2) );
1100 if ( aInRect
.GetHeight() > nTBBorder
)
1101 aInRect
.AdjustTop(nTBBorder
/2 );
1102 if ( aInRect
.GetHeight() > nTBBorder
)
1103 aInRect
.AdjustBottom( -(nTBBorder
/2) );
1105 // calculate alignment resulting from docking rectangle
1106 bool bBecomesFloating
= false;
1107 SfxChildAlignment eDockAlign
= pImpl
->GetDockAlignment();
1108 tools::Rectangle
aDockingRect( rRect
);
1109 if ( !IsFloatingMode() )
1111 // don't use tracking rectangle for alignment check, because it will be too large
1112 // to get a floating mode as result - switch to floating size
1113 // so the calculation only depends on the position of the rectangle, not the current
1114 // docking state of the window
1115 aDockingRect
.SetSize( GetFloatingSize() );
1117 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1118 aDockingRect
.SetPos( pWorkWin
->GetWindow()->OutputToScreenPixel( pWorkWin
->GetWindow()->GetPointerPosPixel() ) );
1121 Point aPos
= aDockingRect
.TopLeft();
1122 tools::Rectangle aIntersect
= GetOuterRect().GetIntersection( aDockingRect
);
1123 if ( aIntersect
.IsEmpty() )
1124 // docking rectangle completely outside docking area -> floating mode
1125 bBecomesFloating
= true;
1128 // create a small test rect around the mouse position and use this one
1129 // instead of the passed rRect to not dock too easily or by accident
1130 tools::Rectangle aSmallDockingRect
;
1131 aSmallDockingRect
.SetSize( Size( MAX_TOGGLEAREA_WIDTH
, MAX_TOGGLEAREA_HEIGHT
) );
1132 Point
aNewPos(rPos
);
1133 aNewPos
.AdjustX( -(aSmallDockingRect
.GetWidth()/2) );
1134 aNewPos
.AdjustY( -(aSmallDockingRect
.GetHeight()/2) );
1135 aSmallDockingRect
.SetPos(aNewPos
);
1136 tools::Rectangle aIntersectRect
= aInRect
.GetIntersection( aSmallDockingRect
);
1137 if ( aIntersectRect
== aSmallDockingRect
)
1138 // docking rectangle completely inside (shrunk) inner area -> floating mode
1139 bBecomesFloating
= true;
1142 if ( bBecomesFloating
)
1144 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
);
1148 // docking rectangle is in the "sensible area"
1149 Point
aInPosTL( aPos
.X()-aInRect
.Left(), aPos
.Y()-aInRect
.Top() );
1150 Point
aInPosBR( aPos
.X()-aInRect
.Left() + aDockingRect
.GetWidth(), aPos
.Y()-aInRect
.Top() + aDockingRect
.GetHeight() );
1151 Size aInSize
= aInRect
.GetSize();
1152 bool bNoChange
= false;
1154 // check if alignment is still unchanged
1155 switch ( GetAlignment() )
1157 case SfxChildAlignment::LEFT
:
1158 case SfxChildAlignment::FIRSTLEFT
:
1159 case SfxChildAlignment::LASTLEFT
:
1160 if (aInPosTL
.X() <= 0)
1162 eDockAlign
= GetAlignment();
1166 case SfxChildAlignment::TOP
:
1167 case SfxChildAlignment::LOWESTTOP
:
1168 case SfxChildAlignment::HIGHESTTOP
:
1169 if ( aInPosTL
.Y() <= 0)
1171 eDockAlign
= GetAlignment();
1175 case SfxChildAlignment::RIGHT
:
1176 case SfxChildAlignment::FIRSTRIGHT
:
1177 case SfxChildAlignment::LASTRIGHT
:
1178 if ( aInPosBR
.X() >= aInSize
.Width())
1180 eDockAlign
= GetAlignment();
1184 case SfxChildAlignment::BOTTOM
:
1185 case SfxChildAlignment::LOWESTBOTTOM
:
1186 case SfxChildAlignment::HIGHESTBOTTOM
:
1187 if ( aInPosBR
.Y() >= aInSize
.Height())
1189 eDockAlign
= GetAlignment();
1199 // alignment will change, test alignment according to distance of the docking rectangles edges
1200 bool bForbidden
= true;
1201 if ( aInPosTL
.X() <= 0)
1203 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::LEFT
);
1204 bForbidden
= ( eDockAlign
!= SfxChildAlignment::LEFT
&&
1205 eDockAlign
!= SfxChildAlignment::FIRSTLEFT
&&
1206 eDockAlign
!= SfxChildAlignment::LASTLEFT
);
1209 if ( bForbidden
&& aInPosTL
.Y() <= 0)
1211 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::TOP
);
1212 bForbidden
= ( eDockAlign
!= SfxChildAlignment::TOP
&&
1213 eDockAlign
!= SfxChildAlignment::HIGHESTTOP
&&
1214 eDockAlign
!= SfxChildAlignment::LOWESTTOP
);
1217 if ( bForbidden
&& aInPosBR
.X() >= aInSize
.Width())
1219 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::RIGHT
);
1220 bForbidden
= ( eDockAlign
!= SfxChildAlignment::RIGHT
&&
1221 eDockAlign
!= SfxChildAlignment::FIRSTRIGHT
&&
1222 eDockAlign
!= SfxChildAlignment::LASTRIGHT
);
1225 if ( bForbidden
&& aInPosBR
.Y() >= aInSize
.Height())
1227 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::BOTTOM
);
1228 bForbidden
= ( eDockAlign
!= SfxChildAlignment::BOTTOM
&&
1229 eDockAlign
!= SfxChildAlignment::HIGHESTBOTTOM
&&
1230 eDockAlign
!= SfxChildAlignment::LOWESTBOTTOM
);
1233 // the calculated alignment was rejected by the window -> take floating mode
1235 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
);
1239 if ( eDockAlign
== SfxChildAlignment::NOALIGNMENT
)
1241 // In the FloatingMode the tracking rectangle will get the floating
1242 // size. Due to a bug the rRect may only be changed when the
1243 // alignment is changed!
1244 if ( eDockAlign
!= pImpl
->GetDockAlignment() )
1245 aDockingRect
.SetSize( aFloatingSize
);
1249 sal_uInt16 nLine
, nPos
;
1250 SfxSplitWindow
*pSplitWin
= pWorkWin
->GetSplitWindow_Impl(eDockAlign
);
1251 aPos
= pSplitWin
->ScreenToOutputPixel( aPos
);
1252 if ( pSplitWin
->GetWindowPos( aPos
, nLine
, nPos
) )
1254 // mouse over splitwindow, get line and position
1255 pImpl
->nDockLine
= nLine
;
1256 pImpl
->nDockPos
= nPos
;
1257 pImpl
->bNewLine
= false;
1261 // mouse touches inner border -> create new line
1262 if ( eDockAlign
== GetAlignment() && pImpl
->pSplitWin
&&
1263 pImpl
->nLine
== pImpl
->pSplitWin
->GetLineCount()-1 && pImpl
->pSplitWin
->GetWindowCount(pImpl
->nLine
) == 1 )
1265 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1266 pImpl
->nDockLine
= pImpl
->nLine
;
1267 pImpl
->nDockPos
= pImpl
->nPos
;
1268 pImpl
->bNewLine
= false;
1273 pImpl
->nDockLine
= pSplitWin
->GetLineCount();
1274 pImpl
->nDockPos
= 0;
1275 pImpl
->bNewLine
= true;
1279 bool bChanged
= pImpl
->nLine
!= pImpl
->nDockLine
|| pImpl
->nPos
!= pImpl
->nDockPos
|| eDockAlign
!= GetAlignment();
1280 if ( !bChanged
&& !IsFloatingMode() )
1282 // window only slightly moved, no change of any property
1283 rRect
.SetSize( pImpl
->aSplitSize
);
1284 rRect
.SetPos( aDockingRect
.TopLeft() );
1288 // calculate new size and position
1290 Point aPoint
= aDockingRect
.TopLeft();
1291 Size aInnerSize
= GetInnerRect().GetSize();
1292 if ( eDockAlign
== SfxChildAlignment::LEFT
|| eDockAlign
== SfxChildAlignment::RIGHT
)
1294 if ( pImpl
->bNewLine
)
1296 // set height to height of free area
1297 aSize
.setHeight( aInnerSize
.Height() );
1298 aSize
.setWidth( pImpl
->nHorizontalSize
);
1299 if ( eDockAlign
== SfxChildAlignment::LEFT
)
1301 aPoint
= aInnerRect
.TopLeft();
1305 aPoint
= aInnerRect
.TopRight();
1306 aPoint
.AdjustX( -(aSize
.Width()) );
1311 // get width from splitwindow
1312 aSize
.setWidth( pSplitWin
->GetLineSize(nLine
) );
1313 aSize
.setHeight( pImpl
->aSplitSize
.Height() );
1318 if ( pImpl
->bNewLine
)
1320 // set width to width of free area
1321 aSize
.setWidth( aInnerSize
.Width() );
1322 aSize
.setHeight( pImpl
->nVerticalSize
);
1323 if ( eDockAlign
== SfxChildAlignment::TOP
)
1325 aPoint
= aInnerRect
.TopLeft();
1329 aPoint
= aInnerRect
.BottomLeft();
1330 aPoint
.AdjustY( -(aSize
.Height()) );
1335 // get height from splitwindow
1336 aSize
.setHeight( pSplitWin
->GetLineSize(nLine
) );
1337 aSize
.setWidth( pImpl
->aSplitSize
.Width() );
1341 aDockingRect
.SetSize( aSize
);
1342 aDockingRect
.SetPos( aPoint
);
1345 rRect
= aDockingRect
;
1349 /** Virtual method of the SfxDockingWindow class. This method determines how
1350 the size of the DockingWindows changes depending on the alignment. The base
1351 implementation uses the floating mode, the size of the marked Floating
1352 Size. For horizontal alignment, the width will be the width of the outer
1353 DockingRectangle, with vertical alignment the height will be the height of
1354 the inner DockingRectangle (resulting from the order in which the SFX child
1355 windows are displayed). The other size is set to the current floating-size,
1356 this could changed by a to intervening derived class. The docking size must
1357 be the same for Left/Right and Top/Bottom.
1359 Size
SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign
)
1361 // Note: if the resizing is also possible in the docked state, then the
1362 // Floating-size does also have to be adjusted?
1364 Size aSize
= GetFloatingSize();
1367 case SfxChildAlignment::TOP
:
1368 case SfxChildAlignment::BOTTOM
:
1369 case SfxChildAlignment::LOWESTTOP
:
1370 case SfxChildAlignment::HIGHESTTOP
:
1371 case SfxChildAlignment::LOWESTBOTTOM
:
1372 case SfxChildAlignment::HIGHESTBOTTOM
:
1373 aSize
.setWidth( aOuterRect
.Right() - aOuterRect
.Left() );
1375 case SfxChildAlignment::LEFT
:
1376 case SfxChildAlignment::RIGHT
:
1377 case SfxChildAlignment::FIRSTLEFT
:
1378 case SfxChildAlignment::LASTLEFT
:
1379 case SfxChildAlignment::FIRSTRIGHT
:
1380 case SfxChildAlignment::LASTRIGHT
:
1381 aSize
.setHeight( aInnerRect
.Bottom() - aInnerRect
.Top() );
1383 case SfxChildAlignment::NOALIGNMENT
:
1392 /** Virtual method of the SfxDockingWindow class. Here a derived class can
1393 disallow certain alignments. The base implementation does not
1396 SfxChildAlignment
SfxDockingWindow::CheckAlignment(SfxChildAlignment
,
1397 SfxChildAlignment eAlign
)
1402 /** The window is closed when the ChildWindow is destroyed by running the
1403 ChildWindow-slots. If this is method is overridden by a derived class
1404 method, then the SfxDockingDialogWindow: Close() must be called afterwards
1405 if the Close() was not cancelled with "return sal_False".
1407 bool SfxDockingWindow::Close()
1409 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
1413 SfxBoolItem
aValue( pMgr
->GetType(), false);
1414 pBindings
->GetDispatcher_Impl()->ExecuteList(
1415 pMgr
->GetType(), SfxCallMode::RECORD
| SfxCallMode::ASYNCHRON
,
1420 void SfxDockingWindow::Paint(vcl::RenderContext
&, const tools::Rectangle
& /*rRect*/)
1424 /** With this method, a minimal OutputSize be can set, that is queried in
1425 the Resizing()-Handler.
1427 void SfxDockingWindow::SetMinOutputSizePixel( const Size
& rSize
)
1429 pImpl
->aMinSize
= rSize
;
1430 ResizableDockingWindow::SetMinOutputSizePixel( rSize
);
1433 /** Set the minimum size which is returned.*/
1434 const Size
& SfxDockingWindow::GetMinOutputSizePixel() const
1436 return pImpl
->aMinSize
;
1439 bool SfxDockingWindow::EventNotify( NotifyEvent
& rEvt
)
1442 return ResizableDockingWindow::EventNotify( rEvt
);
1444 if ( rEvt
.GetType() == MouseNotifyEvent::GETFOCUS
)
1446 if (pMgr
!= nullptr)
1447 pBindings
->SetActiveFrame( pMgr
->GetFrame() );
1449 if ( pImpl
->pSplitWin
)
1450 pImpl
->pSplitWin
->SetActiveWindow_Impl( this );
1451 else if (pMgr
!= nullptr)
1452 pMgr
->Activate_Impl();
1454 // In VCL EventNotify goes first to the window itself, also call the
1455 // base class, otherwise the parent learns nothing
1456 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1457 ResizableDockingWindow::EventNotify( rEvt
);
1460 else if( rEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
1462 // First, allow KeyInput for Dialog functions
1463 if (!DockingWindow::EventNotify(rEvt
) && SfxViewShell::Current())
1465 // then also for valid global accelerators.
1466 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt
.GetKeyEvent() );
1470 else if ( rEvt
.GetType() == MouseNotifyEvent::LOSEFOCUS
&& !HasChildPathFocus() )
1472 pBindings
->SetActiveFrame( nullptr );
1475 return ResizableDockingWindow::EventNotify( rEvt
);
1478 void SfxDockingWindow::SetItemSize_Impl( const Size
& rSize
)
1480 pImpl
->aSplitSize
= rSize
;
1482 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1483 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1486 void SfxDockingWindow::Disappear_Impl()
1488 if ( pImpl
->pSplitWin
&& pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1489 pImpl
->pSplitWin
->RemoveWindow(this);
1492 void SfxDockingWindow::Reappear_Impl()
1494 if ( pImpl
->pSplitWin
&& !pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1496 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
);
1500 bool SfxDockingWindow::IsAutoHide_Impl() const
1502 if ( pImpl
->pSplitWin
)
1503 return !pImpl
->pSplitWin
->IsFadeIn();
1508 void SfxDockingWindow::AutoShow_Impl()
1510 if ( pImpl
->pSplitWin
)
1512 pImpl
->pSplitWin
->FadeIn();
1516 void SfxDockingWindow::StateChanged( StateChangedType nStateChange
)
1518 if ( nStateChange
== StateChangedType::InitShow
)
1521 ResizableDockingWindow::StateChanged( nStateChange
);
1524 void SfxDockingWindow::Move()
1527 pImpl
->aMoveIdle
.Start();
1530 IMPL_LINK_NOARG(SfxDockingWindow
, TimerHdl
, Timer
*, void)
1532 pImpl
->aMoveIdle
.Stop();
1533 if ( IsReallyVisible() && IsFloatingMode() )
1535 SetFloatingSize( GetOutputSizePixel() );
1536 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
1537 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1538 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1542 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */