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/layout.hxx>
24 #include <vcl/settings.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/timer.hxx>
28 #include <vcl/idle.hxx>
29 #include <o3tl/safeint.hxx>
30 #include <osl/diagnose.h>
31 #include <rtl/instance.hxx>
32 #include <toolkit/helper/vclunohelper.hxx>
33 #include <tools/debug.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/propertysequence.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
| WB_ROLLABLE
);
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 auto pFact
= std::make_unique
<SfxChildWinFactory
>( SfxDockingWrapper::CreateImpl
, nID
, 0xffff );
221 pFact
->aInfo
.nFlags
|= nFlags
;
222 pFact
->aInfo
.bVisible
= bVis
;
223 SfxChildWindow::RegisterChildWindow(pMod
, std::move(pFact
));
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() );
294 struct ChildrenRegisteredMap
: public rtl::Static
< bool, ChildrenRegisteredMap
> {};
297 static bool lcl_checkDockingWindowID( sal_uInt16 nID
)
299 return nID
>= SID_DOCKWIN_START
&& nID
< o3tl::make_unsigned(SID_DOCKWIN_START
+NUM_OF_DOCKINGWINDOWS
);
302 static SfxWorkWindow
* lcl_getWorkWindowFromXFrame( const uno::Reference
< frame::XFrame
>& rFrame
)
304 // We need to find the corresponding SfxFrame of our XFrame
305 SfxFrame
* pFrame
= SfxFrame::GetFirst();
306 SfxFrame
* pXFrame
= nullptr;
309 uno::Reference
< frame::XFrame
> xViewShellFrame( pFrame
->GetFrameInterface() );
310 if ( xViewShellFrame
== rFrame
)
316 pFrame
= SfxFrame::GetNext( *pFrame
);
319 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
321 return pXFrame
->GetWorkWindow_Impl();
326 /** Factory function used by the framework layout manager to "create" a docking window with a special name.
327 The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
328 in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
330 void SfxDockingWindowFactory( const uno::Reference
< frame::XFrame
>& rFrame
, const OUString
& rDockingWindowName
)
332 SolarMutexGuard aGuard
;
333 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
335 // Check the range of the provided ID otherwise nothing will happen
336 if ( !lcl_checkDockingWindowID( nID
))
339 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
342 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
345 // Register window at the workwindow child window list
346 pWorkWindow
->SetChildWindow_Impl( nID
, true, false );
351 /** Function used by the framework layout manager to determine the visibility state of a docking window with
352 a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
353 range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
355 bool IsDockingWindowVisible( const uno::Reference
< frame::XFrame
>& rFrame
, const OUString
& rDockingWindowName
)
357 SolarMutexGuard aGuard
;
359 sal_uInt16 nID
= sal_uInt16(rDockingWindowName
.toInt32());
361 // Check the range of the provided ID otherwise nothing will happen
362 if ( lcl_checkDockingWindowID( nID
))
364 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
367 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
376 class SfxDockingWindow_Impl
378 friend class SfxDockingWindow
;
380 SfxChildAlignment eLastAlignment
;
381 SfxChildAlignment eDockAlignment
;
384 VclPtr
<SfxSplitWindow
> pSplitWin
;
387 // The following members are only valid in the time from startDocking to
390 tools::Long nHorizontalSize
;
391 tools::Long nVerticalSize
;
394 sal_uInt16 nDockLine
;
397 bool bDockingPrevented
;
400 explicit SfxDockingWindow_Impl(SfxDockingWindow
*pBase
);
401 SfxChildAlignment
GetLastAlignment() const
402 { return eLastAlignment
; }
403 void SetLastAlignment(SfxChildAlignment eAlign
)
404 { eLastAlignment
= eAlign
; }
405 SfxChildAlignment
GetDockAlignment() const
406 { return eDockAlignment
; }
407 void SetDockAlignment(SfxChildAlignment eAlign
)
408 { eDockAlignment
= eAlign
; }
411 SfxDockingWindow_Impl::SfxDockingWindow_Impl(SfxDockingWindow
* pBase
)
412 :eLastAlignment(SfxChildAlignment::NOALIGNMENT
)
413 ,eDockAlignment(SfxChildAlignment::NOALIGNMENT
)
423 ,bDockingPrevented(false)
425 aMoveIdle
.SetPriority(TaskPriority::RESIZE
);
426 aMoveIdle
.SetInvokeHandler(LINK(pBase
,SfxDockingWindow
,TimerHdl
));
427 aMoveIdle
.SetDebugName( "sfx::SfxDockingWindow_Impl aMoveIdle" );
432 This virtual method of the class FloatingWindow keeps track of changes in
433 FloatingSize. If this method is overridden by a derived class,
434 then the FloatingWindow: Resize() must also be called.
436 void SfxDockingWindow::Resize()
438 DockingWindow::Resize();
440 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
443 if ( IsFloatingMode() )
445 // start timer for saving window status information
446 pImpl
->aMoveIdle
.Start();
450 Size
aSize( GetSizePixel() );
451 switch ( pImpl
->GetDockAlignment() )
453 case SfxChildAlignment::LEFT
:
454 case SfxChildAlignment::FIRSTLEFT
:
455 case SfxChildAlignment::LASTLEFT
:
456 case SfxChildAlignment::RIGHT
:
457 case SfxChildAlignment::FIRSTRIGHT
:
458 case SfxChildAlignment::LASTRIGHT
:
459 pImpl
->nHorizontalSize
= aSize
.Width();
460 pImpl
->aSplitSize
= aSize
;
462 case SfxChildAlignment::TOP
:
463 case SfxChildAlignment::LOWESTTOP
:
464 case SfxChildAlignment::HIGHESTTOP
:
465 case SfxChildAlignment::BOTTOM
:
466 case SfxChildAlignment::HIGHESTBOTTOM
:
467 case SfxChildAlignment::LOWESTBOTTOM
:
468 pImpl
->nVerticalSize
= aSize
.Height();
469 pImpl
->aSplitSize
= aSize
;
479 This virtual method of the class DockingWindow makes it possible to
480 intervene in the switching of the floating mode.
481 If this method is overridden by a derived class,
482 then the SfxDockingWindow::PrepareToggleFloatingMode() must be called
483 afterwards, if not FALSE is returned.
485 bool SfxDockingWindow::PrepareToggleFloatingMode()
487 if (!pImpl
|| !pImpl
->bConstructed
)
490 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr
)
493 if ( pImpl
->bDockingPrevented
)
496 if (!IsFloatingMode())
498 // Test, if FloatingMode is permitted.
499 if ( CheckAlignment(GetAlignment(),SfxChildAlignment::NOALIGNMENT
) != SfxChildAlignment::NOALIGNMENT
)
502 if ( pImpl
->pSplitWin
)
504 // The DockingWindow is inside a SplitWindow and will be teared of.
505 pImpl
->pSplitWin
->RemoveWindow(this/*, sal_False*/);
506 pImpl
->pSplitWin
= nullptr;
511 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
513 // Test if it is allowed to dock,
514 if (CheckAlignment(GetAlignment(),pImpl
->GetLastAlignment()) == SfxChildAlignment::NOALIGNMENT
)
517 // Test, if the Workwindow allows for docking at the moment.
518 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
519 if ( !pWorkWin
->IsDockingAllowed() || !pWorkWin
->IsInternalDockingAllowed() )
528 This virtual method of the DockingWindow class sets the internal data of
529 the SfxDockingWindow and ensures the correct alignment on the parent window.
530 Through PrepareToggleFloatMode and Initialize it is ensured that
531 pImpl-> GetLastAlignment() always delivers an allowed alignment. If this
532 method is overridden by a derived class, then first the
533 SfxDockingWindow::ToggleFloatingMode() must be called.
535 void SfxDockingWindow::ToggleFloatingMode()
537 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
538 return; // No Handler call
540 // Remember old alignment and then switch.
541 // SV has already switched, but the alignment SfxDockingWindow is still
542 // the old one. What I was before?
543 SfxChildAlignment eLastAlign
= GetAlignment();
545 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
547 if (IsFloatingMode())
549 SetAlignment(SfxChildAlignment::NOALIGNMENT
);
550 if ( !pImpl
->aWinState
.isEmpty() )
551 GetFloatingWindow()->SetWindowState( pImpl
->aWinState
);
553 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
557 if (pImpl
->GetDockAlignment() == eLastAlign
)
559 // If ToggleFloatingMode was called, but the DockAlignment still
560 // is unchanged, then this means that it must have been a toggling
561 // through DClick, so use last alignment
562 SetAlignment (pImpl
->GetLastAlignment());
567 // Toggling was triggered by dragging
568 pImpl
->nLine
= pImpl
->nDockLine
;
569 pImpl
->nPos
= pImpl
->nDockPos
;
570 SetAlignment (pImpl
->GetDockAlignment());
573 // The DockingWindow is now in a SplitWindow
574 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
576 // The LastAlignment is still the last docked
577 SfxSplitWindow
*pSplit
= pWorkWin
->GetSplitWindow_Impl(pImpl
->GetLastAlignment());
579 DBG_ASSERT( pSplit
, "LastAlignment is not correct!" );
580 if ( pSplit
&& pSplit
!= pImpl
->pSplitWin
)
581 pSplit
->ReleaseWindow_Impl(this);
582 if ( pImpl
->GetDockAlignment() == eLastAlign
)
583 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
);
585 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
, pImpl
->nLine
, pImpl
->nPos
, pImpl
->bNewLine
);
586 if ( !pImpl
->pSplitWin
->IsFadeIn() )
587 pImpl
->pSplitWin
->FadeIn();
590 // Keep the old alignment for the next toggle; set it only now due to the
591 // unregister SplitWindow!
592 pImpl
->SetLastAlignment(eLastAlign
);
594 // Reset DockAlignment, if EndDocking is still called
595 pImpl
->SetDockAlignment(GetAlignment());
597 // Dock or undock SfxChildWindow correctly.
598 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::TOGGLEFLOATMODE
, pMgr
->GetType() );
603 This virtual method of the DockingWindow class takes the inner and outer
604 docking rectangle from the parent window. If this method is overridden by
605 a derived class, then SfxDockingWindow:StartDocking() has to be called at
608 void SfxDockingWindow::StartDocking()
610 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
612 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
613 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::SETDOCKINGRECTS
, pMgr
->GetType() );
614 pImpl
->SetDockAlignment(GetAlignment());
616 if ( pImpl
->pSplitWin
)
618 // Get the current docking data
619 pImpl
->pSplitWin
->GetWindowPos(this, pImpl
->nLine
, pImpl
->nPos
);
620 pImpl
->nDockLine
= pImpl
->nLine
;
621 pImpl
->nDockPos
= pImpl
->nPos
;
622 pImpl
->bNewLine
= false;
628 This virtual method of the DockingWindow class calculates the current
629 tracking rectangle. For this purpose the method CalcAlignment(RPOs, rRect)
630 is used, the behavior can be influenced by the derived classes (see below).
631 This method should if possible not be overwritten.
633 bool SfxDockingWindow::Docking( const Point
& rPos
, tools::Rectangle
& rRect
)
635 if ( Application::IsInModalMode() )
638 if ( !pImpl
|| !pImpl
->bConstructed
|| !pMgr
)
640 rRect
.SetSize( Size() );
641 return IsFloatingMode();
644 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
645 if ( pImpl
->bDockingPrevented
|| !pWorkWin
->IsInternalDockingAllowed() )
648 bool bFloatMode
= false;
650 if ( GetOuterRect().IsInside( rPos
) )
652 // Mouse within OuterRect: calculate Alignment and Rectangle
653 SfxChildAlignment eAlign
= CalcAlignment(rPos
, rRect
);
654 if (eAlign
== SfxChildAlignment::NOALIGNMENT
)
656 pImpl
->SetDockAlignment(eAlign
);
660 // Mouse is not within OuterRect: must be FloatingWindow
662 if (CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
) != SfxChildAlignment::NOALIGNMENT
)
665 if ( SfxChildAlignment::NOALIGNMENT
!= pImpl
->GetDockAlignment() )
667 // Due to a bug the rRect may only be changed when the
668 // alignment is changed!
669 pImpl
->SetDockAlignment(SfxChildAlignment::NOALIGNMENT
);
670 rRect
.SetSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT
));
677 /** Virtual method of the DockingWindow class ensures the correct alignment on
678 the parent window. If this method is overridden by a derived class, then
679 SfxDockingWindow::EndDocking() must be called first.
681 void SfxDockingWindow::EndDocking( const tools::Rectangle
& rRect
, bool bFloatMode
)
683 if ( !pImpl
|| !pImpl
->bConstructed
|| IsDockingCanceled() || !pMgr
)
686 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
688 // If the alignment changes and the window is in a docked state in a
689 // SplitWindow, then it must be re-registered. If it is docked again,
690 // PrepareToggleFloatingMode() and ToggleFloatingMode() perform the
692 bool bReArrange
= !bFloatMode
;
696 if ( GetAlignment() != pImpl
->GetDockAlignment() )
698 // before Show() is called must the reassignment have been made,
699 // therefore the base class can not be called
700 if ( IsFloatingMode() )
701 Show( false, ShowFlags::NoFocusChange
);
703 // Set the size for toggling.
704 pImpl
->aSplitSize
= rRect
.GetSize();
705 if ( IsFloatingMode() )
707 SetFloatingMode( bFloatMode
);
708 if ( IsFloatingMode() )
709 Show( true, ShowFlags::NoFocusChange
);
713 pImpl
->pSplitWin
->RemoveWindow(this,false);
714 pImpl
->nLine
= pImpl
->nDockLine
;
715 pImpl
->nPos
= pImpl
->nDockPos
;
716 pImpl
->pSplitWin
->ReleaseWindow_Impl(this);
717 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(pImpl
->GetDockAlignment());
718 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
, pImpl
->nDockLine
, pImpl
->nDockPos
, pImpl
->bNewLine
);
719 if ( !pImpl
->pSplitWin
->IsFadeIn() )
720 pImpl
->pSplitWin
->FadeIn();
723 else if ( pImpl
->nLine
!= pImpl
->nDockLine
|| pImpl
->nPos
!= pImpl
->nDockPos
|| pImpl
->bNewLine
)
725 // Moved within Splitwindows
726 if ( pImpl
->nLine
!= pImpl
->nDockLine
)
727 pImpl
->aSplitSize
= rRect
.GetSize();
728 pImpl
->pSplitWin
->MoveWindow( this, pImpl
->aSplitSize
, pImpl
->nDockLine
, pImpl
->nDockPos
, pImpl
->bNewLine
);
733 DockingWindow::EndDocking(rRect
, bFloatMode
);
736 SetAlignment( IsFloatingMode() ? SfxChildAlignment::NOALIGNMENT
: pImpl
->GetDockAlignment() );
741 Virtual method of the DockingWindow class. Here, the interactive resize in
742 FloatingMode can be influenced, for example by only allowing for discrete
743 values for width and / or height. The base implementation prevents that the
744 output size is smaller than one set with SetMinOutputSizePixel().
746 void SfxDockingWindow::Resizing( Size
& /*rSize*/ )
753 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
754 required because the docking is implemented in Sfx through SfxChildWindows.
756 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
757 vcl::Window
* pParent
, WinBits nWinBits
) :
758 DockingWindow (pParent
, nWinBits
),
762 pImpl
.reset(new SfxDockingWindow_Impl(this));
765 /** Constructor for the SfxDockingWindow class. A SfxChildWindow will be
766 required because the docking is implemented in Sfx through SfxChildWindows.
768 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
769 vcl::Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
)
770 : DockingWindow(pParent
, "DockingWindow", "sfx/ui/dockingwindow.ui")
771 , pBindings(pBindinx
)
774 m_xVclContentArea
= VclPtr
<VclVBox
>::Create(this);
775 m_xVclContentArea
->Show();
776 m_xBuilder
.reset(Application::CreateInterimBuilder(m_xVclContentArea
, rUIXMLDescription
, true));
777 m_xContainer
= m_xBuilder
->weld_container(rID
);
779 pImpl
.reset(new SfxDockingWindow_Impl(this));
782 /** Initialization of the SfxDockingDialog class via a SfxChildWinInfo.
783 The initialization is done only in a 2nd step after the constructor, this
784 constructor should be called from the derived class or from the
787 void SfxDockingWindow::Initialize(SfxChildWinInfo
*pInfo
)
791 pImpl
->SetDockAlignment( SfxChildAlignment::NOALIGNMENT
);
792 pImpl
->bConstructed
= true;
796 if (pInfo
&& (pInfo
->nFlags
& SfxChildWindowFlags::FORCEDOCK
))
797 pImpl
->bDockingPrevented
= true;
799 pImpl
->aSplitSize
= GetOutputSizePixel();
800 if ( !GetFloatingSize().Width() )
802 Size
aMinSize( GetMinOutputSizePixel() );
803 SetFloatingSize( pImpl
->aSplitSize
);
804 if ( pImpl
->aSplitSize
.Width() < aMinSize
.Width() )
805 pImpl
->aSplitSize
.setWidth( aMinSize
.Width() );
806 if ( pImpl
->aSplitSize
.Height() < aMinSize
.Height() )
807 pImpl
->aSplitSize
.setHeight( aMinSize
.Height() );
810 bool bVertHorzRead( false );
811 if (pInfo
&& !pInfo
->aExtraString
.isEmpty())
813 // get information about alignment, split size and position in SplitWindow
815 sal_Int32 nPos
= pInfo
->aExtraString
.indexOf("AL:");
818 // alignment information
819 sal_Int32 n1
= pInfo
->aExtraString
.indexOf('(', nPos
);
822 sal_Int32 n2
= pInfo
->aExtraString
.indexOf(')', n1
);
825 // extract alignment information from extrastring
826 aStr
= pInfo
->aExtraString
.copy(nPos
, n2
- nPos
+ 1);
827 pInfo
->aExtraString
= pInfo
->aExtraString
.replaceAt(nPos
, n2
- nPos
+ 1, "");
828 aStr
= aStr
.replaceAt(nPos
, n1
-nPos
+1, "");
833 if ( !aStr
.isEmpty() )
835 // accept window state only if alignment is also set
836 pImpl
->aWinState
= pInfo
->aWinState
;
838 // check for valid alignment
839 SfxChildAlignment eLocalAlignment
= static_cast<SfxChildAlignment
>(static_cast<sal_uInt16
>(aStr
.toInt32()));
840 bool bIgnoreFloatConfig
= (eLocalAlignment
== SfxChildAlignment::NOALIGNMENT
&&
841 !StyleSettings::GetDockingFloatsSupported());
842 if (pImpl
->bDockingPrevented
|| bIgnoreFloatConfig
)
843 // docking prevented, ignore old configuration and take alignment from default
846 SetAlignment( eLocalAlignment
);
848 SfxChildAlignment eAlign
= CheckAlignment(GetAlignment(),GetAlignment());
849 if ( eAlign
!= GetAlignment() )
851 OSL_FAIL("Invalid Alignment!");
852 SetAlignment( eAlign
);
856 // get last alignment (for toggling)
857 nPos
= aStr
.indexOf(',');
860 aStr
= aStr
.copy(nPos
+1);
861 pImpl
->SetLastAlignment( static_cast<SfxChildAlignment
>(static_cast<sal_uInt16
>(aStr
.toInt32())) );
864 nPos
= aStr
.indexOf(',');
867 // get split size and position in SplitWindow
869 aStr
= aStr
.copy(nPos
+1);
870 if ( GetPosSizeFromString( aStr
, aPos
, pImpl
->aSplitSize
) )
872 pImpl
->nLine
= pImpl
->nDockLine
= static_cast<sal_uInt16
>(aPos
.X());
873 pImpl
->nPos
= pImpl
->nDockPos
= static_cast<sal_uInt16
>(aPos
.Y());
874 pImpl
->nVerticalSize
= pImpl
->aSplitSize
.Height();
875 pImpl
->nHorizontalSize
= pImpl
->aSplitSize
.Width();
876 if ( GetSplitSizeFromString( aStr
, pImpl
->aSplitSize
))
877 bVertHorzRead
= true;
882 OSL_FAIL( "Information is missing!" );
886 if ( !bVertHorzRead
)
888 pImpl
->nVerticalSize
= pImpl
->aSplitSize
.Height();
889 pImpl
->nHorizontalSize
= pImpl
->aSplitSize
.Width();
892 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
893 if ( GetAlignment() != SfxChildAlignment::NOALIGNMENT
)
895 // check if SfxWorkWindow is able to allow docking at its border
897 !pWorkWin
->IsDockingAllowed() ||
898 !pWorkWin
->IsInternalDockingAllowed() ||
899 ( (GetFloatStyle() & WB_STANDALONE
) && Application::IsInModalMode()) )
901 SetAlignment( SfxChildAlignment::NOALIGNMENT
);
905 // detect floating mode
906 // toggling mode will not execute code in handlers, because pImpl->bConstructed is not set yet
907 bool bFloatMode
= IsFloatingMode();
908 if ( bFloatMode
!= (GetAlignment() == SfxChildAlignment::NOALIGNMENT
) )
910 bFloatMode
= !bFloatMode
;
911 SetFloatingMode( bFloatMode
);
914 if ( !pImpl
->aWinState
.isEmpty() )
915 GetFloatingWindow()->SetWindowState( pImpl
->aWinState
);
917 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
921 if ( IsFloatingMode() )
923 // validate last alignment
924 SfxChildAlignment eLastAlign
= pImpl
->GetLastAlignment();
925 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
926 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::LEFT
);
927 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
928 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::RIGHT
);
929 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
930 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::TOP
);
931 if ( eLastAlign
== SfxChildAlignment::NOALIGNMENT
)
932 eLastAlign
= CheckAlignment(eLastAlign
, SfxChildAlignment::BOTTOM
);
933 pImpl
->SetLastAlignment(eLastAlign
);
937 // docked window must have NOALIGNMENT as last alignment
938 pImpl
->SetLastAlignment(SfxChildAlignment::NOALIGNMENT
);
940 pImpl
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
941 pImpl
->pSplitWin
->InsertWindow(this, pImpl
->aSplitSize
);
945 pImpl
->SetDockAlignment( GetAlignment() );
948 void SfxDockingWindow::Initialize_Impl()
952 pImpl
->bConstructed
= true;
956 FloatingWindow
* pFloatWin
= GetFloatingWindow();
960 bSet
= !pFloatWin
->IsDefaultPos();
964 Point aPos
= GetFloatingPos();
965 if ( aPos
!= Point() )
971 SfxViewFrame
*pFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
972 vcl::Window
* pEditWin
= pFrame
->GetViewShell()->GetWindow();
973 Point aPos
= pEditWin
->OutputToScreenPixel( pEditWin
->GetPosPixel() );
974 aPos
= GetParent()->ScreenToOutputPixel( aPos
);
975 SetFloatingPos( aPos
);
980 // initialize floating window
981 if ( pImpl
->aWinState
.isEmpty() )
982 // window state never set before, get if from defaults
983 pImpl
->aWinState
= pFloatWin
->GetWindowState();
985 // trick: use VCL method SetWindowState to adjust position and size
986 pFloatWin
->SetWindowState( pImpl
->aWinState
);
987 Size
aSize(pFloatWin
->GetSizePixel());
989 // remember floating size for calculating alignment and tracking rectangle
990 SetFloatingSize(aSize
);
994 // allow calling of docking handlers
995 pImpl
->bConstructed
= true;
998 /** Fills a SfxChildWinInfo with specific data from SfxDockingWindow,
999 so that it can be written in the INI file. It is assumed that rinfo
1000 receives all other possible relevant data in the ChildWindow class.
1001 Insertions are marked with size and the ZoomIn flag.
1002 If this method is overridden, the base implementation must be called first.
1004 void SfxDockingWindow::FillInfo(SfxChildWinInfo
& rInfo
) const
1006 if (!pMgr
|| !pImpl
)
1009 if (GetFloatingWindow() && pImpl
->bConstructed
)
1010 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
1012 rInfo
.aWinState
= pImpl
->aWinState
;
1013 rInfo
.aExtraString
= "AL:(";
1014 rInfo
.aExtraString
+= OUString::number(static_cast<sal_uInt16
>(GetAlignment()));
1015 rInfo
.aExtraString
+= ",";
1016 rInfo
.aExtraString
+= OUString::number (static_cast<sal_uInt16
>(pImpl
->GetLastAlignment()));
1018 Point
aPos(pImpl
->nLine
, pImpl
->nPos
);
1019 rInfo
.aExtraString
+= ",";
1020 rInfo
.aExtraString
+= OUString::number( aPos
.X() );
1021 rInfo
.aExtraString
+= "/";
1022 rInfo
.aExtraString
+= OUString::number( aPos
.Y() );
1023 rInfo
.aExtraString
+= "/";
1024 rInfo
.aExtraString
+= OUString::number( pImpl
->nHorizontalSize
);
1025 rInfo
.aExtraString
+= "/";
1026 rInfo
.aExtraString
+= OUString::number( pImpl
->nVerticalSize
);
1027 rInfo
.aExtraString
+= ",";
1028 rInfo
.aExtraString
+= OUString::number( pImpl
->aSplitSize
.Width() );
1029 rInfo
.aExtraString
+= ";";
1030 rInfo
.aExtraString
+= OUString::number( pImpl
->aSplitSize
.Height() );
1032 rInfo
.aExtraString
+= ")";
1035 SfxDockingWindow::~SfxDockingWindow()
1040 void SfxDockingWindow::dispose()
1042 ReleaseChildWindow_Impl();
1044 m_xContainer
.reset();
1046 m_xVclContentArea
.disposeAndClear();
1047 DockingWindow::dispose();
1050 void SfxDockingWindow::ReleaseChildWindow_Impl()
1052 if ( pMgr
&& pMgr
->GetFrame() == pBindings
->GetActiveFrame() )
1053 pBindings
->SetActiveFrame( nullptr );
1055 if ( pMgr
&& pImpl
->pSplitWin
&& pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1056 pImpl
->pSplitWin
->RemoveWindow(this);
1061 /** This method calculates a resulting alignment for the given mouse position
1062 and tracking rectangle. When changing the alignment it can also be that
1063 the tracking rectangle is changed, so that an altered rectangle is
1064 returned. The user of this class can influence behaviour of this method,
1065 and thus the behavior of his DockinWindow class when docking where the
1066 called virtual method:
1068 SfxDockingWindow::CalcDockingSize (SfxChildAlignment eAlign)
1070 is overridden (see below).
1072 SfxChildAlignment
SfxDockingWindow::CalcAlignment(const Point
& rPos
, tools::Rectangle
& rRect
)
1074 // calculate hypothetical sizes for different modes
1075 Size
aFloatingSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT
));
1077 // check if docking is permitted
1078 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1079 if ( !pWorkWin
->IsDockingAllowed() )
1081 rRect
.SetSize( aFloatingSize
);
1082 return pImpl
->GetDockAlignment();
1085 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1086 tools::Long nLRBorder
, nTBBorder
;
1088 // take the smaller size of docked and floating mode
1089 Size aBorderTmp
= pImpl
->aSplitSize
;
1090 if ( GetFloatingSize().Height() < aBorderTmp
.Height() )
1091 aBorderTmp
.setHeight( GetFloatingSize().Height() );
1092 if ( GetFloatingSize().Width() < aBorderTmp
.Width() )
1093 aBorderTmp
.setWidth( GetFloatingSize().Width() );
1095 nLRBorder
= aBorderTmp
.Width();
1096 nTBBorder
= aBorderTmp
.Height();
1098 // limit border to predefined constant values
1099 if ( nLRBorder
> MAX_TOGGLEAREA_WIDTH
)
1100 nLRBorder
= MAX_TOGGLEAREA_WIDTH
;
1101 if ( nTBBorder
> MAX_TOGGLEAREA_WIDTH
)
1102 nTBBorder
= MAX_TOGGLEAREA_WIDTH
;
1104 // shrink area for floating mode if possible
1105 tools::Rectangle aInRect
= GetInnerRect();
1106 if ( aInRect
.GetWidth() > nLRBorder
)
1107 aInRect
.AdjustLeft(nLRBorder
/2 );
1108 if ( aInRect
.GetWidth() > nLRBorder
)
1109 aInRect
.AdjustRight( -(nLRBorder
/2) );
1110 if ( aInRect
.GetHeight() > nTBBorder
)
1111 aInRect
.AdjustTop(nTBBorder
/2 );
1112 if ( aInRect
.GetHeight() > nTBBorder
)
1113 aInRect
.AdjustBottom( -(nTBBorder
/2) );
1115 // calculate alignment resulting from docking rectangle
1116 bool bBecomesFloating
= false;
1117 SfxChildAlignment eDockAlign
= pImpl
->GetDockAlignment();
1118 tools::Rectangle
aDockingRect( rRect
);
1119 if ( !IsFloatingMode() )
1121 // don't use tracking rectangle for alignment check, because it will be too large
1122 // to get a floating mode as result - switch to floating size
1123 // so the calculation only depends on the position of the rectangle, not the current
1124 // docking state of the window
1125 aDockingRect
.SetSize( GetFloatingSize() );
1127 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1128 aDockingRect
.SetPos( pWorkWin
->GetWindow()->OutputToScreenPixel( pWorkWin
->GetWindow()->GetPointerPosPixel() ) );
1131 Point aPos
= aDockingRect
.TopLeft();
1132 tools::Rectangle aIntersect
= GetOuterRect().GetIntersection( aDockingRect
);
1133 if ( aIntersect
.IsEmpty() )
1134 // docking rectangle completely outside docking area -> floating mode
1135 bBecomesFloating
= true;
1138 // create a small test rect around the mouse position and use this one
1139 // instead of the passed rRect to not dock too easily or by accident
1140 tools::Rectangle aSmallDockingRect
;
1141 aSmallDockingRect
.SetSize( Size( MAX_TOGGLEAREA_WIDTH
, MAX_TOGGLEAREA_HEIGHT
) );
1142 Point
aNewPos(rPos
);
1143 aNewPos
.AdjustX( -(aSmallDockingRect
.GetWidth()/2) );
1144 aNewPos
.AdjustY( -(aSmallDockingRect
.GetHeight()/2) );
1145 aSmallDockingRect
.SetPos(aNewPos
);
1146 tools::Rectangle aIntersectRect
= aInRect
.GetIntersection( aSmallDockingRect
);
1147 if ( aIntersectRect
== aSmallDockingRect
)
1148 // docking rectangle completely inside (shrunk) inner area -> floating mode
1149 bBecomesFloating
= true;
1152 if ( bBecomesFloating
)
1154 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
);
1158 // docking rectangle is in the "sensible area"
1159 Point
aInPosTL( aPos
.X()-aInRect
.Left(), aPos
.Y()-aInRect
.Top() );
1160 Point
aInPosBR( aPos
.X()-aInRect
.Left() + aDockingRect
.GetWidth(), aPos
.Y()-aInRect
.Top() + aDockingRect
.GetHeight() );
1161 Size aInSize
= aInRect
.GetSize();
1162 bool bNoChange
= false;
1164 // check if alignment is still unchanged
1165 switch ( GetAlignment() )
1167 case SfxChildAlignment::LEFT
:
1168 case SfxChildAlignment::FIRSTLEFT
:
1169 case SfxChildAlignment::LASTLEFT
:
1170 if (aInPosTL
.X() <= 0)
1172 eDockAlign
= GetAlignment();
1176 case SfxChildAlignment::TOP
:
1177 case SfxChildAlignment::LOWESTTOP
:
1178 case SfxChildAlignment::HIGHESTTOP
:
1179 if ( aInPosTL
.Y() <= 0)
1181 eDockAlign
= GetAlignment();
1185 case SfxChildAlignment::RIGHT
:
1186 case SfxChildAlignment::FIRSTRIGHT
:
1187 case SfxChildAlignment::LASTRIGHT
:
1188 if ( aInPosBR
.X() >= aInSize
.Width())
1190 eDockAlign
= GetAlignment();
1194 case SfxChildAlignment::BOTTOM
:
1195 case SfxChildAlignment::LOWESTBOTTOM
:
1196 case SfxChildAlignment::HIGHESTBOTTOM
:
1197 if ( aInPosBR
.Y() >= aInSize
.Height())
1199 eDockAlign
= GetAlignment();
1209 // alignment will change, test alignment according to distance of the docking rectangles edges
1210 bool bForbidden
= true;
1211 if ( aInPosTL
.X() <= 0)
1213 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::LEFT
);
1214 bForbidden
= ( eDockAlign
!= SfxChildAlignment::LEFT
&&
1215 eDockAlign
!= SfxChildAlignment::FIRSTLEFT
&&
1216 eDockAlign
!= SfxChildAlignment::LASTLEFT
);
1219 if ( bForbidden
&& aInPosTL
.Y() <= 0)
1221 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::TOP
);
1222 bForbidden
= ( eDockAlign
!= SfxChildAlignment::TOP
&&
1223 eDockAlign
!= SfxChildAlignment::HIGHESTTOP
&&
1224 eDockAlign
!= SfxChildAlignment::LOWESTTOP
);
1227 if ( bForbidden
&& aInPosBR
.X() >= aInSize
.Width())
1229 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::RIGHT
);
1230 bForbidden
= ( eDockAlign
!= SfxChildAlignment::RIGHT
&&
1231 eDockAlign
!= SfxChildAlignment::FIRSTRIGHT
&&
1232 eDockAlign
!= SfxChildAlignment::LASTRIGHT
);
1235 if ( bForbidden
&& aInPosBR
.Y() >= aInSize
.Height())
1237 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::BOTTOM
);
1238 bForbidden
= ( eDockAlign
!= SfxChildAlignment::BOTTOM
&&
1239 eDockAlign
!= SfxChildAlignment::HIGHESTBOTTOM
&&
1240 eDockAlign
!= SfxChildAlignment::LOWESTBOTTOM
);
1243 // the calculated alignment was rejected by the window -> take floating mode
1245 eDockAlign
= CheckAlignment(pImpl
->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT
);
1249 if ( eDockAlign
== SfxChildAlignment::NOALIGNMENT
)
1251 // In the FloatingMode the tracking rectangle will get the floating
1252 // size. Due to a bug the rRect may only be changed when the
1253 // alignment is changed!
1254 if ( eDockAlign
!= pImpl
->GetDockAlignment() )
1255 aDockingRect
.SetSize( aFloatingSize
);
1259 sal_uInt16 nLine
, nPos
;
1260 SfxSplitWindow
*pSplitWin
= pWorkWin
->GetSplitWindow_Impl(eDockAlign
);
1261 aPos
= pSplitWin
->ScreenToOutputPixel( aPos
);
1262 if ( pSplitWin
->GetWindowPos( aPos
, nLine
, nPos
) )
1264 // mouse over splitwindow, get line and position
1265 pImpl
->nDockLine
= nLine
;
1266 pImpl
->nDockPos
= nPos
;
1267 pImpl
->bNewLine
= false;
1271 // mouse touches inner border -> create new line
1272 if ( eDockAlign
== GetAlignment() && pImpl
->pSplitWin
&&
1273 pImpl
->nLine
== pImpl
->pSplitWin
->GetLineCount()-1 && pImpl
->pSplitWin
->GetWindowCount(pImpl
->nLine
) == 1 )
1275 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1276 pImpl
->nDockLine
= pImpl
->nLine
;
1277 pImpl
->nDockPos
= pImpl
->nPos
;
1278 pImpl
->bNewLine
= false;
1283 pImpl
->nDockLine
= pSplitWin
->GetLineCount();
1284 pImpl
->nDockPos
= 0;
1285 pImpl
->bNewLine
= true;
1289 bool bChanged
= pImpl
->nLine
!= pImpl
->nDockLine
|| pImpl
->nPos
!= pImpl
->nDockPos
|| eDockAlign
!= GetAlignment();
1290 if ( !bChanged
&& !IsFloatingMode() )
1292 // window only slightly moved, no change of any property
1293 rRect
.SetSize( pImpl
->aSplitSize
);
1294 rRect
.SetPos( aDockingRect
.TopLeft() );
1298 // calculate new size and position
1300 Point aPoint
= aDockingRect
.TopLeft();
1301 Size aInnerSize
= GetInnerRect().GetSize();
1302 if ( eDockAlign
== SfxChildAlignment::LEFT
|| eDockAlign
== SfxChildAlignment::RIGHT
)
1304 if ( pImpl
->bNewLine
)
1306 // set height to height of free area
1307 aSize
.setHeight( aInnerSize
.Height() );
1308 aSize
.setWidth( pImpl
->nHorizontalSize
);
1309 if ( eDockAlign
== SfxChildAlignment::LEFT
)
1311 aPoint
= aInnerRect
.TopLeft();
1315 aPoint
= aInnerRect
.TopRight();
1316 aPoint
.AdjustX( -(aSize
.Width()) );
1321 // get width from splitwindow
1322 aSize
.setWidth( pSplitWin
->GetLineSize(nLine
) );
1323 aSize
.setHeight( pImpl
->aSplitSize
.Height() );
1328 if ( pImpl
->bNewLine
)
1330 // set width to width of free area
1331 aSize
.setWidth( aInnerSize
.Width() );
1332 aSize
.setHeight( pImpl
->nVerticalSize
);
1333 if ( eDockAlign
== SfxChildAlignment::TOP
)
1335 aPoint
= aInnerRect
.TopLeft();
1339 aPoint
= aInnerRect
.BottomLeft();
1340 aPoint
.AdjustY( -(aSize
.Height()) );
1345 // get height from splitwindow
1346 aSize
.setHeight( pSplitWin
->GetLineSize(nLine
) );
1347 aSize
.setWidth( pImpl
->aSplitSize
.Width() );
1351 aDockingRect
.SetSize( aSize
);
1352 aDockingRect
.SetPos( aPoint
);
1355 rRect
= aDockingRect
;
1359 /** Virtual method of the SfxDockingWindow class. This method determines how
1360 the size of the DockingWindows changes depending on the alignment. The base
1361 implementation uses the floating mode, the size of the marked Floating
1362 Size. For horizontal alignment, the width will be the width of the outer
1363 DockingRectangle, with vertical alignment the height will be the height of
1364 the inner DockingRectangle (resulting from the order in which the SFX child
1365 windows are displayed). The other size is set to the current floating-size,
1366 this could changed by a to intervening derived class. The docking size must
1367 be the same for Left/Right and Top/Bottom.
1369 Size
SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign
)
1371 // Note: if the resizing is also possible in the docked state, then the
1372 // Floating-size does also have to be adjusted?
1374 Size aSize
= GetFloatingSize();
1377 case SfxChildAlignment::TOP
:
1378 case SfxChildAlignment::BOTTOM
:
1379 case SfxChildAlignment::LOWESTTOP
:
1380 case SfxChildAlignment::HIGHESTTOP
:
1381 case SfxChildAlignment::LOWESTBOTTOM
:
1382 case SfxChildAlignment::HIGHESTBOTTOM
:
1383 aSize
.setWidth( aOuterRect
.Right() - aOuterRect
.Left() );
1385 case SfxChildAlignment::LEFT
:
1386 case SfxChildAlignment::RIGHT
:
1387 case SfxChildAlignment::FIRSTLEFT
:
1388 case SfxChildAlignment::LASTLEFT
:
1389 case SfxChildAlignment::FIRSTRIGHT
:
1390 case SfxChildAlignment::LASTRIGHT
:
1391 aSize
.setHeight( aInnerRect
.Bottom() - aInnerRect
.Top() );
1393 case SfxChildAlignment::NOALIGNMENT
:
1402 /** Virtual method of the SfxDockingWindow class. Here a derived class can
1403 disallow certain alignments. The base implementation does not
1406 SfxChildAlignment
SfxDockingWindow::CheckAlignment(SfxChildAlignment
,
1407 SfxChildAlignment eAlign
)
1412 /** The window is closed when the ChildWindow is destroyed by running the
1413 ChildWindow-slots. If this is method is overridden by a derived class
1414 method, then the SfxDockingDialogWindow: Close() must be called afterwards
1415 if the Close() was not cancelled with "return sal_False".
1417 bool SfxDockingWindow::Close()
1419 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
1423 SfxBoolItem
aValue( pMgr
->GetType(), false);
1424 pBindings
->GetDispatcher_Impl()->ExecuteList(
1425 pMgr
->GetType(), SfxCallMode::RECORD
| SfxCallMode::ASYNCHRON
,
1430 void SfxDockingWindow::Paint(vcl::RenderContext
&, const tools::Rectangle
& /*rRect*/)
1434 /** With this method, a minimal OutputSize be can set, that is queried in
1435 the Resizing()-Handler.
1437 void SfxDockingWindow::SetMinOutputSizePixel( const Size
& rSize
)
1439 pImpl
->aMinSize
= rSize
;
1440 DockingWindow::SetMinOutputSizePixel( rSize
);
1443 /** Set the minimum size which is returned.*/
1444 const Size
& SfxDockingWindow::GetMinOutputSizePixel() const
1446 return pImpl
->aMinSize
;
1449 bool SfxDockingWindow::EventNotify( NotifyEvent
& rEvt
)
1452 return DockingWindow::EventNotify( rEvt
);
1454 if ( rEvt
.GetType() == MouseNotifyEvent::GETFOCUS
)
1456 if (pMgr
!= nullptr)
1457 pBindings
->SetActiveFrame( pMgr
->GetFrame() );
1459 if ( pImpl
->pSplitWin
)
1460 pImpl
->pSplitWin
->SetActiveWindow_Impl( this );
1461 else if (pMgr
!= nullptr)
1462 pMgr
->Activate_Impl();
1464 // In VCL EventNotify goes first to the window itself, also call the
1465 // base class, otherwise the parent learns nothing
1466 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1467 DockingWindow::EventNotify( rEvt
);
1470 else if( rEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
1472 // First, allow KeyInput for Dialog functions
1473 if (!DockingWindow::EventNotify(rEvt
) && SfxViewShell::Current())
1475 // then also for valid global accelerators.
1476 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt
.GetKeyEvent() );
1480 else if ( rEvt
.GetType() == MouseNotifyEvent::LOSEFOCUS
&& !HasChildPathFocus() )
1482 pBindings
->SetActiveFrame( nullptr );
1485 return DockingWindow::EventNotify( rEvt
);
1489 void SfxDockingWindow::SetItemSize_Impl( const Size
& rSize
)
1491 pImpl
->aSplitSize
= rSize
;
1493 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1494 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1497 void SfxDockingWindow::Disappear_Impl()
1499 if ( pImpl
->pSplitWin
&& pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1500 pImpl
->pSplitWin
->RemoveWindow(this);
1503 void SfxDockingWindow::Reappear_Impl()
1505 if ( pImpl
->pSplitWin
&& !pImpl
->pSplitWin
->IsItemValid( GetType() ) )
1507 pImpl
->pSplitWin
->InsertWindow( this, pImpl
->aSplitSize
);
1511 bool SfxDockingWindow::IsAutoHide_Impl() const
1513 if ( pImpl
->pSplitWin
)
1514 return !pImpl
->pSplitWin
->IsFadeIn();
1519 void SfxDockingWindow::AutoShow_Impl()
1521 if ( pImpl
->pSplitWin
)
1523 pImpl
->pSplitWin
->FadeIn();
1527 void SfxDockingWindow::StateChanged( StateChangedType nStateChange
)
1529 if ( nStateChange
== StateChangedType::InitShow
)
1532 DockingWindow::StateChanged( nStateChange
);
1535 void SfxDockingWindow::Move()
1538 pImpl
->aMoveIdle
.Start();
1541 IMPL_LINK_NOARG(SfxDockingWindow
, TimerHdl
, Timer
*, void)
1543 pImpl
->aMoveIdle
.Stop();
1544 if ( IsReallyVisible() && IsFloatingMode() )
1546 if( !GetFloatingWindow()->IsRollUp() )
1547 SetFloatingSize( GetOutputSizePixel() );
1548 pImpl
->aWinState
= GetFloatingWindow()->GetWindowState();
1549 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1550 pWorkWin
->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1554 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */