1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dockwin.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include <svtools/eitem.hxx>
35 #include <vcl/decoview.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/timer.hxx>
39 #include <rtl/instance.hxx>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <comphelper/processfactory.hxx>
43 #include <sfx2/dockwin.hxx>
44 #include <sfx2/bindings.hxx>
45 #include <sfx2/viewfrm.hxx>
46 #include <sfx2/dispatch.hxx>
47 #include "workwin.hxx"
48 #include "splitwin.hxx"
49 #include <sfx2/viewsh.hxx>
50 #include "sfxhelp.hxx"
51 #include <sfx2/objsh.hxx>
53 #include <com/sun/star/frame/XController.hpp>
54 #include <com/sun/star/lang/XUnoTunnel.hpp>
55 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
56 #include <com/sun/star/awt/XWindow.hpp>
57 #include <com/sun/star/uno/XComponentContext.hpp>
58 #include <com/sun/star/frame/XModuleManager.hpp>
59 #include <com/sun/star/container/XNameAccess.hpp>
61 #define MAX_TOGGLEAREA_WIDTH 20
62 #define MAX_TOGGLEAREA_HEIGHT 20
64 using namespace ::com::sun::star
;
66 // implemented in 'sfx2/source/appl/childwin.cxx'
67 extern sal_Bool
GetPosSizeFromString( const String
& rStr
, Point
& rPos
, Size
& rSize
);
68 extern sal_Bool
GetSplitSizeFromString( const String
& rStr
, Size
& rSize
);
70 // If you want to change the number you also have to:
71 // - Add new slot ids to sfxsids.hrc
72 // - Add new slots to frmslots.sdi
73 // - Add new slot definitions to sfx.sdi
74 static const int NUM_OF_DOCKINGWINDOWS
= 10;
76 class SfxTitleDockingWindow
;
77 class SfxTitleDockingWindow
: public SfxDockingWindow
79 Window
* m_pWrappedWindow
;
83 SfxTitleDockingWindow(
84 SfxBindings
* pBindings
,
85 SfxChildWindow
* pChildWin
,
89 virtual ~SfxTitleDockingWindow();
91 Window
* GetWrappedWindow() const { return m_pWrappedWindow
; }
92 void SetWrappedWindow(Window
* const pWindow
);
94 virtual void StateChanged( StateChangedType nType
);
95 virtual long Notify( NotifyEvent
& rNEvt
);
96 virtual void Resize();
97 virtual void Resizing( Size
& rSize
);
105 ::rtl::OUString sTitle
;
109 static uno::WeakReference
< container::XNameAccess
> m_xWindowStateConfiguration
;
110 static uno::WeakReference
< frame::XModuleManager
> m_xModuleManager
;
112 static bool lcl_getWindowState( const uno::Reference
< container::XNameAccess
>& xWindowStateMgr
, const ::rtl::OUString
& rResourceURL
, WindowState
& rWindowState
)
114 bool bResult
= false;
119 uno::Sequence
< beans::PropertyValue
> aWindowState
;
120 a
= xWindowStateMgr
->getByName( rResourceURL
);
121 if ( a
>>= aWindowState
)
123 for ( sal_Int32 n
= 0; n
< aWindowState
.getLength(); n
++ )
125 if ( aWindowState
[n
].Name
.equalsAscii( "UIName" ))
127 aWindowState
[n
].Value
>>= rWindowState
.sTitle
;
134 catch ( container::NoSuchElementException
& )
142 SfxDockingWrapper::SfxDockingWrapper( Window
* pParentWnd
,
144 SfxBindings
* pBindings
,
145 SfxChildWinInfo
* pInfo
)
146 : SfxChildWindow( pParentWnd
, nId
)
148 uno::Reference
< lang::XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
149 const rtl::OUString
aDockWindowResourceURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/dockingwindow/" ));
151 SfxTitleDockingWindow
* pTitleDockWindow
= new SfxTitleDockingWindow( pBindings
, this, pParentWnd
,
152 WB_STDDOCKWIN
| WB_CLIPCHILDREN
| WB_SIZEABLE
| WB_3DLOOK
| WB_ROLLABLE
, nId
);
153 pWindow
= pTitleDockWindow
;
154 eChildAlignment
= SFX_ALIGN_NOALIGNMENT
;
156 // Use factory manager to retrieve XWindow factory. That can be used to instanciate
157 // the real window factory.
158 uno::Reference
< lang::XSingleComponentFactory
> xFactoryMgr(
159 xServiceManager
->createInstance(
160 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
161 "com.sun.star.ui.WindowContentFactoryManager"))),
164 if (xFactoryMgr
.is())
166 SfxDispatcher
* pDispatcher
= pBindings
->GetDispatcher();
167 uno::Reference
< frame::XFrame
> xFrame( pDispatcher
->GetFrame()->GetFrame()->GetFrameInterface(), uno::UNO_QUERY
);
168 uno::Sequence
< uno::Any
> aArgs(2);
169 beans::PropertyValue aPropValue
;
170 aPropValue
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
171 aPropValue
.Value
= uno::makeAny( xFrame
);
172 aArgs
[0] <<= aPropValue
;
173 aPropValue
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ));
175 // create a resource URL from the nId provided by the sfx2
176 ::rtl::OUString
aResourceURL( aDockWindowResourceURL
);
177 aResourceURL
+= ::rtl::OUString::valueOf(sal_Int32(nId
));
178 aPropValue
.Value
= uno::makeAny( aResourceURL
);
179 aArgs
[1] <<= aPropValue
;
181 uno::Reference
< awt::XWindow
> xWindow
;
184 uno::Reference
< beans::XPropertySet
> xProps( xServiceManager
, uno::UNO_QUERY
);
185 uno::Reference
< uno::XComponentContext
> xContext
;
188 xProps
->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext
;
191 xWindow
= uno::Reference
< awt::XWindow
>(
192 xFactoryMgr
->createInstanceWithArgumentsAndContext( aArgs
, xContext
),
196 uno::Reference
< frame::XModuleManager
> xModuleManager( m_xModuleManager
);
197 if ( !xModuleManager
.is() )
199 xModuleManager
= uno::Reference
< frame::XModuleManager
>(
200 xServiceManager
->createInstance(
201 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ))),
203 m_xModuleManager
= xModuleManager
;
206 uno::Reference
< container::XNameAccess
> xWindowStateConfiguration( m_xWindowStateConfiguration
);
207 if ( !xWindowStateConfiguration
.is() )
209 xWindowStateConfiguration
= uno::Reference
< container::XNameAccess
>(
210 xServiceManager
->createInstance(
211 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.WindowStateConfiguration" ))),
213 m_xWindowStateConfiguration
= xWindowStateConfiguration
;
216 ::rtl::OUString sModuleIdentifier
= xModuleManager
->identify( xFrame
);
218 uno::Reference
< container::XNameAccess
> xModuleWindowState(
219 xWindowStateConfiguration
->getByName( sModuleIdentifier
),
221 if ( xModuleWindowState
.is() )
223 WindowState aDockWinState
;
224 if ( lcl_getWindowState( xModuleWindowState
, aResourceURL
, aDockWinState
))
225 pTitleDockWindow
->SetText( aDockWinState
.sTitle
);
228 catch ( beans::UnknownPropertyException
& )
231 catch ( uno::RuntimeException
& )
234 catch ( uno::Exception
& )
238 Window
* pContentWindow
= VCLUnoHelper::GetWindow(xWindow
);
239 pContentWindow
->SetStyle( pContentWindow
->GetStyle() | WB_DIALOGCONTROL
| WB_CHILDDLGCTRL
);
240 pTitleDockWindow
->SetWrappedWindow(pContentWindow
);
243 pWindow
->SetOutputSizePixel( Size( 270, 240 ) );
245 ( ( SfxDockingWindow
* ) pWindow
)->Initialize( pInfo
);
246 SetHideNotDelete( TRUE
);
249 SfxChildWindow
* SfxDockingWrapper::CreateImpl(
250 Window
*pParent
, sal_uInt16 nId
, SfxBindings
*pBindings
, SfxChildWinInfo
* pInfo
)
252 SfxChildWindow
*pWin
= new SfxDockingWrapper(pParent
, nId
, pBindings
, pInfo
); return pWin
;
255 sal_uInt16
SfxDockingWrapper::GetChildWindowId ()
257 DBG_ASSERT( false, "This method shouldn't be called!" );
261 void SfxDockingWrapper::RegisterChildWindow (sal_Bool bVis
, SfxModule
*pMod
, sal_uInt16 nFlags
)
263 // pre-register a couple of docking windows
264 for (int i
=0; i
< NUM_OF_DOCKINGWINDOWS
; i
++ )
266 USHORT nID
= USHORT(SID_DOCKWIN_START
+i
);
267 SfxChildWinFactory
*pFact
= new SfxChildWinFactory( SfxDockingWrapper::CreateImpl
, nID
, 0xffff );
268 pFact
->aInfo
.nFlags
|= nFlags
;
269 pFact
->aInfo
.bVisible
= bVis
;
270 SfxChildWindow::RegisterChildWindow(pMod
, pFact
);
274 SfxChildWinInfo
SfxDockingWrapper::GetInfo() const
276 SfxChildWinInfo aInfo
= SfxChildWindow::GetInfo();
277 ((SfxDockingWindow
*)GetWindow())->FillInfo( aInfo
);
281 SfxTitleDockingWindow::SfxTitleDockingWindow( SfxBindings
* pBind
,
282 SfxChildWindow
* pChildWin
,
286 SfxDockingWindow( pBind
,
295 SfxTitleDockingWindow::~SfxTitleDockingWindow()
297 delete m_pWrappedWindow
;
300 void SfxTitleDockingWindow::SetWrappedWindow( Window
* const pWindow
)
302 m_pWrappedWindow
= pWindow
;
303 if (m_pWrappedWindow
)
305 m_pWrappedWindow
->SetParent(this);
306 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
307 m_pWrappedWindow
->Show();
311 long SfxTitleDockingWindow::Notify( NotifyEvent
& rNEvt
)
313 return SfxDockingWindow::Notify( rNEvt
);
316 void SfxTitleDockingWindow::StateChanged( StateChangedType nType
)
318 if ( nType
== STATE_CHANGE_INITSHOW
)
320 Window
* pWindow
= GetWrappedWindow();
323 pWindow
->SetSizePixel( GetOutputSizePixel() );
328 SfxDockingWindow::StateChanged(nType
);
331 void SfxTitleDockingWindow::Resize()
333 SfxDockingWindow::Resize();
334 if (m_pWrappedWindow
)
335 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
338 void SfxTitleDockingWindow::Resizing( Size
&rSize
)
340 SfxDockingWindow::Resizing( rSize
);
341 if (m_pWrappedWindow
)
342 m_pWrappedWindow
->SetSizePixel( GetOutputSizePixel() );
345 BOOL
SfxTitleDockingWindow::Close()
347 return SfxDockingWindow::Close();
352 struct ChildrenRegisteredMap
: public rtl::Static
< bool, ChildrenRegisteredMap
> {};
355 static bool lcl_checkDockingWindowID( USHORT nID
)
357 if (nID
< SID_DOCKWIN_START
|| nID
>= USHORT(SID_DOCKWIN_START
+NUM_OF_DOCKINGWINDOWS
))
363 static SfxWorkWindow
* lcl_getWorkWindowFromXFrame( const uno::Reference
< frame::XFrame
>& rFrame
)
365 // We need to find the corresponding SfxFrame of our XFrame
366 SfxFrame
* pFrame
= SfxFrame::GetFirst();
367 SfxFrame
* pXFrame
= 0;
370 uno::Reference
< frame::XFrame
> xViewShellFrame( pFrame
->GetFrameInterface() );
371 if ( xViewShellFrame
== rFrame
)
377 pFrame
= SfxFrame::GetNext( *pFrame
);
380 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
382 return pXFrame
->GetWorkWindow_Impl();
388 Factory function used by the framework layout manager to "create" a docking window with a special name.
389 The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
390 in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
392 void SAL_CALL
SfxDockingWindowFactory( const uno::Reference
< frame::XFrame
>& rFrame
, const rtl::OUString
& rDockingWindowName
)
394 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
395 USHORT nID
= USHORT(rDockingWindowName
.toInt32());
397 // Check the range of the provided ID otherwise nothing will happen
398 if ( lcl_checkDockingWindowID( nID
))
400 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
403 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
406 // Register window at the workwindow child window list
407 pWorkWindow
->SetChildWindow_Impl( nID
, true, false );
414 Function used by the framework layout manager to determine the visibility state of a docking window with
415 a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
416 range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
418 bool SAL_CALL
IsDockingWindowVisible( const uno::Reference
< frame::XFrame
>& rFrame
, const rtl::OUString
& rDockingWindowName
)
420 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
422 USHORT nID
= USHORT(rDockingWindowName
.toInt32());
424 // Check the range of the provided ID otherwise nothing will happen
425 if ( lcl_checkDockingWindowID( nID
))
427 SfxWorkWindow
* pWorkWindow
= lcl_getWorkWindowFromXFrame( rFrame
);
430 SfxChildWindow
* pChildWindow
= pWorkWindow
->GetChildWindow_Impl(nID
);
439 class SfxDockingWindow_Impl
441 friend class SfxDockingWindow
;
443 SfxChildAlignment eLastAlignment
;
444 SfxChildAlignment eDockAlignment
;
447 SfxSplitWindow
* pSplitWin
;
452 // Folgende members sind nur in der Zeit von StartDocking bis EndDocking
456 long nHorizontalSize
;
463 BOOL bDockingPrevented
;
464 ByteString aWinState
;
466 SfxChildAlignment
GetLastAlignment() const
467 { return eLastAlignment
; }
468 void SetLastAlignment(SfxChildAlignment eAlign
)
469 { eLastAlignment
= eAlign
; }
470 SfxChildAlignment
GetDockAlignment() const
471 { return eDockAlignment
; }
472 void SetDockAlignment(SfxChildAlignment eAlign
)
473 { eDockAlignment
= eAlign
; }
476 //-------------------------------------------------------------------------
478 void SfxDockingWindow::Resize()
482 Diese virtuelle Methode der Klasse DockingWindow merkt sich ggf. eine
483 ver"anderte FloatingSize.
484 Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
485 auch SfxDockingWindow::Resize() gerufen werden.
488 DockingWindow::Resize();
490 if ( pImp
->bConstructed
&& pMgr
)
492 if ( IsFloatingMode() )
494 // start timer for saving window status information
495 pImp
->aMoveTimer
.Start();
499 Size
aSize( GetSizePixel() );
500 switch ( pImp
->GetDockAlignment() )
503 case SFX_ALIGN_FIRSTLEFT
:
504 case SFX_ALIGN_LASTLEFT
:
505 case SFX_ALIGN_RIGHT
:
506 case SFX_ALIGN_FIRSTRIGHT
:
507 case SFX_ALIGN_LASTRIGHT
:
508 pImp
->nHorizontalSize
= aSize
.Width();
509 pImp
->aSplitSize
= aSize
;
512 case SFX_ALIGN_LOWESTTOP
:
513 case SFX_ALIGN_HIGHESTTOP
:
514 case SFX_ALIGN_BOTTOM
:
515 case SFX_ALIGN_HIGHESTBOTTOM
:
516 case SFX_ALIGN_LOWESTBOTTOM
:
517 pImp
->nVerticalSize
= aSize
.Height();
518 pImp
->aSplitSize
= aSize
;
527 //-------------------------------------------------------------------------
529 BOOL
SfxDockingWindow::PrepareToggleFloatingMode()
533 Diese virtuelle Methode der Klasse DockingWindow erm"oglicht ein Eingreifen
534 in das Umschalten des floating mode.
535 Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
536 danach SfxDockingWindow::PrepareToggleFloatingMode() gerufen werden,
537 wenn nicht FALSE zur"uckgegeben wird.
541 if (!pImp
->bConstructed
)
544 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr
)
547 if ( pImp
->bDockingPrevented
)
550 if (!IsFloatingMode())
552 // Testen, ob FloatingMode erlaubt ist
553 if ( CheckAlignment(GetAlignment(),SFX_ALIGN_NOALIGNMENT
) != SFX_ALIGN_NOALIGNMENT
)
556 if ( pImp
->pSplitWin
)
558 // Das DockingWindow sitzt in einem SplitWindow und wird abgerissen
559 pImp
->pSplitWin
->RemoveWindow(this/*, FALSE*/);
565 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
567 // Testen, ob es erlaubt ist, anzudocken
568 if (CheckAlignment(GetAlignment(),pImp
->GetLastAlignment()) == SFX_ALIGN_NOALIGNMENT
)
571 // Testen, ob das Workwindow gerade ein Andocken erlaubt
572 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
573 if ( !pWorkWin
->IsDockingAllowed() || !pWorkWin
->IsInternalDockingAllowed() )
580 //-------------------------------------------------------------------------
582 void SfxDockingWindow::ToggleFloatingMode()
586 Diese virtuelle Methode der Klasse DockingWindow setzt die internen
587 Daten des SfxDockingWindow und sorgt f"ur korrektes Alignment am
589 Durch PrepareToggleFloatMode und Initialize ist sichergestellt, da\s
590 pImp->GetLastAlignment() immer eine erlaubtes Alignment liefert.
591 Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
592 zuerst SfxDockingWindow::ToggleFloatingMode() gerufen werden.
595 if ( !pImp
->bConstructed
|| !pMgr
)
596 return; // Kein Handler-Aufruf
598 // Altes Alignment merken und dann umschalten.
599 // Sv hat jetzt schon umgeschaltet, aber Alignment am SfxDockingWindow
600 // ist noch das alte!
601 // Was war ich bisher ?
602 SfxChildAlignment eLastAlign
= GetAlignment();
604 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
605 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
606 if ( pImp
->bSplitable
)
607 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
609 if (IsFloatingMode())
611 SetAlignment(SFX_ALIGN_NOALIGNMENT
);
612 if ( pImp
->aWinState
.Len() )
613 GetFloatingWindow()->SetWindowState( pImp
->aWinState
);
615 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
617 if ( pImp->bSplitable && !pImp->bEndDocked )
618 // Wenn das Fenster vorher in einem SplitWindow lag, kommt von
625 if (pImp
->GetDockAlignment() == eLastAlign
)
627 // Wenn ToggleFloatingMode aufgerufen wurde, das DockAlignment
628 // aber noch unver"andert ist, mu\s das ein Toggeln durch DClick
629 // gewesen sein, also LastAlignment verwenden
630 SetAlignment (pImp
->GetLastAlignment());
631 if ( !pImp
->bSplitable
)
632 SetSizePixel( CalcDockingSize(GetAlignment()) );
636 // Toggeln wurde durch Draggen ausgel"ost
637 pImp
->nLine
= pImp
->nDockLine
;
638 pImp
->nPos
= pImp
->nDockPos
;
639 SetAlignment (pImp
->GetDockAlignment());
642 if ( pImp
->bSplitable
)
644 // Das DockingWindow kommt jetzt in ein SplitWindow
645 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
647 // Das LastAlignment ist jetzt immer noch das zuletzt angedockte
648 SfxSplitWindow
*pSplit
= pWorkWin
->GetSplitWindow_Impl(pImp
->GetLastAlignment());
650 DBG_ASSERT( pSplit
, "LastAlignment kann nicht stimmen!" );
651 if ( pSplit
&& pSplit
!= pImp
->pSplitWin
)
652 pSplit
->ReleaseWindow_Impl(this);
653 if ( pImp
->GetDockAlignment() == eLastAlign
)
654 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
);
656 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
, pImp
->nLine
, pImp
->nPos
, pImp
->bNewLine
);
657 if ( !pImp
->pSplitWin
->IsFadeIn() )
658 pImp
->pSplitWin
->FadeIn();
662 // altes Alignment festhalten f"ur n"achstes Togglen; erst jetzt setzen
663 // wg. Abmelden beim SplitWindow!
664 pImp
->SetLastAlignment(eLastAlign
);
666 // DockAlignment zur"ucksetzen, falls noch EndDocking gerufen wird
667 pImp
->SetDockAlignment(GetAlignment());
669 // SfxChildWindow korrekt andocken bzw. entdocken
671 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_TOGGLEFLOATMODE
, pMgr
->GetType() );
674 //-------------------------------------------------------------------------
676 void SfxDockingWindow::StartDocking()
680 Diese virtuelle Methode der Klasse DockingWindow holt vom parent window
681 das innere und "au\sere docking rectangle.
682 Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
683 am Ende SfxDockingWindow::StartDocking() gerufen werden.
686 if ( !pImp
->bConstructed
|| !pMgr
)
688 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
689 if ( pImp
->bSplitable
)
690 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
691 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
692 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_SETDOCKINGRECTS
, pMgr
->GetType() );
693 pImp
->SetDockAlignment(GetAlignment());
695 if ( pImp
->pSplitWin
)
697 // Die aktuellen Docking-Daten besorgen
698 pImp
->pSplitWin
->GetWindowPos(this, pImp
->nLine
, pImp
->nPos
);
699 pImp
->nDockLine
= pImp
->nLine
;
700 pImp
->nDockPos
= pImp
->nPos
;
701 pImp
->bNewLine
= FALSE
;
705 //-------------------------------------------------------------------------
707 BOOL
SfxDockingWindow::Docking( const Point
& rPos
, Rectangle
& rRect
)
711 Diese virtuelle Methode der Klasse DockingWindow berechnet das aktuelle
712 tracking rectangle. Dazu benutzt sie die Methode CalcAlignment(rPos,rRect),
713 deren Verhalten von abgeleiteten Klassen beeinflu\st werden kann (s.u.).
714 Diese Methode sollte nach M"oglichkeit nicht "uberschrieben werden.
717 if ( Application::IsInModalMode() )
720 if ( !pImp
->bConstructed
|| !pMgr
)
722 rRect
.SetSize( Size() );
723 return IsFloatingMode();
726 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
727 if ( pImp
->bDockingPrevented
|| !pWorkWin
->IsInternalDockingAllowed() )
730 BOOL bFloatMode
= FALSE
;
732 if ( GetOuterRect().IsInside( rPos
) && !IsDockingPrevented() )
734 // Maus innerhalb OuterRect : Alignment und Rectangle berechnen
735 SfxChildAlignment eAlign
= CalcAlignment(rPos
, rRect
);
736 if (eAlign
== SFX_ALIGN_NOALIGNMENT
)
738 pImp
->SetDockAlignment(eAlign
);
742 // Maus nicht innerhalb OuterRect : muss FloatingWindow sein
744 if (CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
) != SFX_ALIGN_NOALIGNMENT
)
747 if ( SFX_ALIGN_NOALIGNMENT
!= pImp
->GetDockAlignment() )
749 // wg. SV-Bug darf rRect nur ver"andert werden, wenn sich das
750 // Alignment "andert !
751 pImp
->SetDockAlignment(SFX_ALIGN_NOALIGNMENT
);
752 rRect
.SetSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT
));
756 if ( !pImp
->bSplitable
)
758 // Bei individuell angedocktem Window wird die Position durch das
759 // Alignment und die docking rects festgelegt.
760 Size aSize
= rRect
.GetSize();
763 switch ( pImp
->GetDockAlignment() )
766 case SFX_ALIGN_FIRSTLEFT
:
767 case SFX_ALIGN_LASTLEFT
:
768 aPos
= aInnerRect
.TopLeft();
769 if ( pImp
->GetDockAlignment() == GetAlignment() )
770 aPos
.X() -= aSize
.Width();
774 case SFX_ALIGN_LOWESTTOP
:
775 case SFX_ALIGN_HIGHESTTOP
:
776 aPos
= Point(aOuterRect
.Left(), aInnerRect
.Top());
777 if ( pImp
->GetDockAlignment() == GetAlignment() )
778 aPos
.Y() -= aSize
.Height();
781 case SFX_ALIGN_RIGHT
:
782 case SFX_ALIGN_FIRSTRIGHT
:
783 case SFX_ALIGN_LASTRIGHT
:
784 aPos
= Point(aInnerRect
.Right() - rRect
.GetSize().Width(),
786 if ( pImp
->GetDockAlignment() == GetAlignment() )
787 aPos
.X() += aSize
.Width();
790 case SFX_ALIGN_BOTTOM
:
791 case SFX_ALIGN_HIGHESTBOTTOM
:
792 case SFX_ALIGN_LOWESTBOTTOM
:
793 aPos
= Point(aOuterRect
.Left(),
794 aInnerRect
.Bottom() - rRect
.GetSize().Height());
795 if ( pImp
->GetDockAlignment() == GetAlignment() )
796 aPos
.Y() += aSize
.Height();
808 //-------------------------------------------------------------------------
810 void SfxDockingWindow::EndDocking( const Rectangle
& rRect
, BOOL bFloatMode
)
814 Diese virtuelle Methode der Klasse DockingWindow sorgt f"ur das korrekte
815 Alignment am parent window.
816 Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
817 zuerst SfxDockingWindow::EndDocking() gerufen werden.
820 if ( !pImp
->bConstructed
|| IsDockingCanceled() || !pMgr
)
823 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
824 BOOL bReArrange
= FALSE
;
825 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
826 if ( pImp
->bSplitable
)
828 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
830 // Wenn sich das Alignment "andert und das Fenster befindet sich
831 // im angedockten Zustand in einem SplitWindow, mu\s umgemeldet werden
832 // Wenn neu angedockt wird, machen PrepareToggleFloatingMode()
833 // und ToggleFloatingMode() das Ummelden.
840 if ( GetAlignment() != pImp
->GetDockAlignment() )
842 // Vor dem Show() mu\s das Ummelden passiert sein, daher kann nicht
843 // die Basisklasse gerufen werden
844 if ( IsFloatingMode() || !pImp
->bSplitable
)
845 Show( FALSE
, SHOW_NOFOCUSCHANGE
);
847 // Die Gr"o\se f"urs Toggeln setzen
848 pImp
->aSplitSize
= rRect
.GetSize();
849 if ( IsFloatingMode() )
851 SetFloatingMode( bFloatMode
);
852 if ( IsFloatingMode() || !pImp
->bSplitable
)
853 Show( TRUE
, SHOW_NOFOCUSCHANGE
);
857 pImp
->pSplitWin
->RemoveWindow(this,FALSE
);
858 pImp
->nLine
= pImp
->nDockLine
;
859 pImp
->nPos
= pImp
->nDockPos
;
860 pImp
->pSplitWin
->ReleaseWindow_Impl(this);
861 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(pImp
->GetDockAlignment());
862 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
, pImp
->nDockLine
, pImp
->nDockPos
, pImp
->bNewLine
);
863 if ( !pImp
->pSplitWin
->IsFadeIn() )
864 pImp
->pSplitWin
->FadeIn();
867 else if ( pImp
->nLine
!= pImp
->nDockLine
|| pImp
->nPos
!= pImp
->nDockPos
|| pImp
->bNewLine
)
869 // Ich wurde innerhalb meines Splitwindows verschoben.
870 if ( pImp
->nLine
!= pImp
->nDockLine
)
871 pImp
->aSplitSize
= rRect
.GetSize();
872 pImp
->pSplitWin
->MoveWindow( this, pImp
->aSplitSize
, pImp
->nDockLine
, pImp
->nDockPos
, pImp
->bNewLine
);
877 pImp
->bEndDocked
= TRUE
;
878 DockingWindow::EndDocking(rRect
, bFloatMode
);
879 pImp
->bEndDocked
= FALSE
;
882 SetAlignment( IsFloatingMode() ? SFX_ALIGN_NOALIGNMENT
: pImp
->GetDockAlignment() );
885 //-------------------------------------------------------------------------
887 void SfxDockingWindow::Resizing( Size
& /*rSize*/ )
891 Virtuelle Methode der Klasse DockingWindow.
892 Hier kann das interaktive Umgr"o\sern im FloatingMode beeinflu\t werden,
893 z.B. indem nur diskrete Werte f"ur Breite und/oder H"ohe zugelassen werden.
894 Die Basisimplementation verhindert, da\s die OutputSize kleiner wird als
895 eine mit SetMinOutputSizePixel() gesetzte Gr"o\se.
900 if(rSize.Width() < pImp->aMinSize.Width())
901 rSize.Width() = pImp->aMinSize.Width();
902 if(rSize.Height() < pImp->aMinSize.Height())
903 rSize.Height() = pImp->aMinSize.Height();
907 //-------------------------------------------------------------------------
909 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
910 Window
* pParent
, WinBits nWinBits
) :
911 DockingWindow (pParent
, nWinBits
),
918 ctor der Klasse SfxDockingWindow. Es wird ein SfxChildWindow ben"otigt,
919 da das Andocken im Sfx "uber SfxChildWindows realisiert wird.
923 ULONG nId
= GetHelpId();
925 nId
= pCW
->GetType();
929 pImp
= new SfxDockingWindow_Impl
;
930 pImp
->bConstructed
= FALSE
;
932 pImp
->bEndDocked
= FALSE
;
933 pImp
->bDockingPrevented
= FALSE
;
935 pImp
->bSplitable
= TRUE
;
936 // pImp->bAutoHide = FALSE;
938 // Zun"achst auf Defaults setzen; das Alignment wird in der Subklasse gesetzt
939 pImp
->nLine
= pImp
->nDockLine
= 0;
940 pImp
->nPos
= pImp
->nDockPos
= 0;
941 pImp
->bNewLine
= FALSE
;
942 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
943 pImp
->aMoveTimer
.SetTimeout(50);
944 pImp
->aMoveTimer
.SetTimeoutHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
946 // DBG_ASSERT(pMgr,"DockingWindow erfordert ein SfxChildWindow!");
949 //-------------------------------------------------------------------------
951 SfxDockingWindow::SfxDockingWindow( SfxBindings
*pBindinx
, SfxChildWindow
*pCW
,
952 Window
* pParent
, const ResId
& rResId
) :
953 DockingWindow(pParent
, rResId
),
960 ctor der Klasse SfxDockingWindow. Es wird ein SfxChildWindow ben"otigt,
961 da das Andocken im Sfx "uber SfxChildWindows realisiert wird.
965 ULONG nId
= GetHelpId();
969 pImp
= new SfxDockingWindow_Impl
;
970 pImp
->bConstructed
= FALSE
;
972 pImp
->bEndDocked
= FALSE
;
973 pImp
->bDockingPrevented
= FALSE
;
975 pImp
->bSplitable
= TRUE
;
976 // pImp->bAutoHide = FALSE;
978 // Zun"achst auf Defaults setzen; das Alignment wird in der Subklasse gesetzt
979 pImp
->nLine
= pImp
->nDockLine
= 0;
980 pImp
->nPos
= pImp
->nDockPos
= 0;
981 pImp
->bNewLine
= FALSE
;
982 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
983 pImp
->aMoveTimer
.SetTimeout(50);
984 pImp
->aMoveTimer
.SetTimeoutHdl(LINK(this,SfxDockingWindow
,TimerHdl
));
986 // DBG_ASSERT(pMgr,"DockingWindow erfordert ein SfxChildWindow!");
989 //-------------------------------------------------------------------------
991 void SfxDockingWindow::Initialize(SfxChildWinInfo
*pInfo
)
994 Initialisierung der Klasse SfxDockingWindow "uber ein SfxChildWinInfo.
995 Die Initialisierung erfolgt erst in einem 2.Schritt nach dem ctor und sollte
996 vom ctor der abgeleiteten Klasse oder vom ctor des SfxChildWindows
1003 pImp
->SetDockAlignment( SFX_ALIGN_NOALIGNMENT
);
1004 pImp
->bConstructed
= TRUE
;
1008 if ( pInfo
->nFlags
& SFX_CHILDWIN_FORCEDOCK
)
1009 pImp
->bDockingPrevented
= TRUE
;
1011 pImp
->aSplitSize
= GetOutputSizePixel();
1012 if ( !GetFloatingSize().Width() )
1014 Size
aMinSize( GetMinOutputSizePixel() );
1015 SetFloatingSize( pImp
->aSplitSize
);
1016 if ( pImp
->aSplitSize
.Width() < aMinSize
.Width() )
1017 pImp
->aSplitSize
.Width() = aMinSize
.Width();
1018 if ( pImp
->aSplitSize
.Height() < aMinSize
.Height() )
1019 pImp
->aSplitSize
.Height() = aMinSize
.Height();
1022 sal_Bool
bVertHorzRead( sal_False
);
1023 if ( pInfo
->aExtraString
.Len() )
1025 // get information about alignment, split size and position in SplitWindow
1027 USHORT nPos
= pInfo
->aExtraString
.SearchAscii("AL:");
1028 if ( nPos
!= STRING_NOTFOUND
)
1030 // alignment information
1031 USHORT n1
= pInfo
->aExtraString
.Search('(', nPos
);
1032 if ( n1
!= STRING_NOTFOUND
)
1034 USHORT n2
= pInfo
->aExtraString
.Search(')', n1
);
1035 if ( n2
!= STRING_NOTFOUND
)
1037 // extract alignment information from extrastring
1038 aStr
= pInfo
->aExtraString
.Copy(nPos
, n2
- nPos
+ 1);
1039 pInfo
->aExtraString
.Erase(nPos
, n2
- nPos
+ 1);
1040 aStr
.Erase(nPos
, n1
-nPos
+1);
1047 // accept window state only if alignment is also set
1048 pImp
->aWinState
= pInfo
->aWinState
;
1050 // check for valid alignment
1051 SfxChildAlignment eLocalAlignment
= (SfxChildAlignment
) (USHORT
) aStr
.ToInt32();
1052 if ( pImp
->bDockingPrevented
)
1053 // docking prevented, ignore old configuration and take alignment from default
1056 SetAlignment( eLocalAlignment
);
1058 SfxChildAlignment eAlign
= CheckAlignment(GetAlignment(),GetAlignment());
1059 if ( eAlign
!= GetAlignment() )
1061 DBG_ERROR("Invalid Alignment!");
1062 SetAlignment( eAlign
);
1066 // get last alignment (for toggeling)
1067 nPos
= aStr
.Search(',');
1068 if ( nPos
!= STRING_NOTFOUND
)
1070 aStr
.Erase(0, nPos
+1);
1071 pImp
->SetLastAlignment( (SfxChildAlignment
) (USHORT
) aStr
.ToInt32() );
1074 nPos
= aStr
.Search(',');
1075 if ( nPos
!= STRING_NOTFOUND
)
1077 // get split size and position in SplitWindow
1079 aStr
.Erase(0, nPos
+1);
1080 if ( GetPosSizeFromString( aStr
, aPos
, pImp
->aSplitSize
) )
1082 pImp
->nLine
= pImp
->nDockLine
= (USHORT
) aPos
.X();
1083 pImp
->nPos
= pImp
->nDockPos
= (USHORT
) aPos
.Y();
1084 pImp
->nVerticalSize
= pImp
->aSplitSize
.Height();
1085 pImp
->nHorizontalSize
= pImp
->aSplitSize
.Width();
1086 if ( GetSplitSizeFromString( aStr
, pImp
->aSplitSize
))
1087 bVertHorzRead
= sal_True
;
1092 DBG_ERROR( "Information is missing!" );
1096 if ( !bVertHorzRead
)
1098 pImp
->nVerticalSize
= pImp
->aSplitSize
.Height();
1099 pImp
->nHorizontalSize
= pImp
->aSplitSize
.Width();
1102 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1103 if ( GetAlignment() != SFX_ALIGN_NOALIGNMENT
)
1105 // check if SfxWorkWindow is able to allow docking at its border
1107 !pWorkWin
->IsDockingAllowed() ||
1108 !pWorkWin
->IsInternalDockingAllowed() ||
1109 ( (GetFloatStyle() & WB_STANDALONE
) && Application::IsInModalMode()) )
1111 SetAlignment( SFX_ALIGN_NOALIGNMENT
);
1115 // detect floating mode
1116 // toggeling mode will not execute code in handlers, because pImp->bConstructed is not set yet
1117 BOOL bFloatMode
= IsFloatingMode();
1118 if ( bFloatMode
!= ((GetAlignment() == SFX_ALIGN_NOALIGNMENT
)) )
1120 bFloatMode
= !bFloatMode
;
1121 SetFloatingMode( bFloatMode
);
1124 if ( pImp
->aWinState
.Len() )
1125 GetFloatingWindow()->SetWindowState( pImp
->aWinState
);
1127 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
1131 if ( IsFloatingMode() )
1133 // validate last alignment
1134 SfxChildAlignment eLastAlign
= pImp
->GetLastAlignment();
1135 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1136 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_LEFT
);
1137 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1138 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_RIGHT
);
1139 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1140 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_TOP
);
1141 if ( eLastAlign
== SFX_ALIGN_NOALIGNMENT
)
1142 eLastAlign
= CheckAlignment(eLastAlign
, SFX_ALIGN_BOTTOM
);
1143 pImp
->SetLastAlignment(eLastAlign
);
1147 // docked window must have NOALIGNMENT as last alignment
1148 pImp
->SetLastAlignment(SFX_ALIGN_NOALIGNMENT
);
1150 if ( pImp
->bSplitable
)
1152 // pImp->bAutoHide = ( pInfo->nFlags & SFX_CHILDWIN_AUTOHIDE) != 0;
1153 pImp
->pSplitWin
= pWorkWin
->GetSplitWindow_Impl(GetAlignment());
1154 pImp
->pSplitWin
->InsertWindow(this, pImp
->aSplitSize
);
1158 //?????? Currently not supported
1159 // Fenster ist individuell angedockt; Gr"o\se berechnen.
1160 // Dazu mu\s sie mit der FloatingSize initialisiert werden, falls
1161 // irgendwer sich darauf verl"a\st, da\s eine vern"unftige Gr"o\se
1163 SetSizePixel(GetFloatingSize());
1164 SetSizePixel(CalcDockingSize(GetAlignment()));
1169 pImp
->SetDockAlignment( GetAlignment() );
1172 void SfxDockingWindow::Initialize_Impl()
1177 pImp
->bConstructed
= TRUE
;
1181 FloatingWindow
* pFloatWin
= GetFloatingWindow();
1185 bSet
= !pFloatWin
->IsDefaultPos();
1189 Point aPos
= GetFloatingPos();
1190 if ( aPos
!= Point() )
1196 SfxViewFrame
*pFrame
= pBindings
->GetDispatcher_Impl()->GetFrame();
1197 Window
* pEditWin
= pFrame
->GetViewShell()->GetWindow();
1198 Point aPos
= pEditWin
->OutputToScreenPixel( pEditWin
->GetPosPixel() );
1199 aPos
= GetParent()->ScreenToOutputPixel( aPos
);
1200 SetFloatingPos( aPos
);
1205 // initialize floating window
1206 if ( !pImp
->aWinState
.Len() )
1207 // window state never set before, get if from defaults
1208 pImp
->aWinState
= pFloatWin
->GetWindowState();
1210 // trick: use VCL method SetWindowState to adjust position and size
1211 pFloatWin
->SetWindowState( pImp
->aWinState
);
1213 // remember floating size for calculating alignment and tracking rectangle
1214 SetFloatingSize( pFloatWin
->GetSizePixel() );
1216 // some versions of VCL didn't call resize in the current situation
1220 // allow calling of docking handlers
1221 pImp
->bConstructed
= TRUE
;
1224 //-------------------------------------------------------------------------
1226 void SfxDockingWindow::FillInfo(SfxChildWinInfo
& rInfo
) const
1230 F"ullt ein SfxChildWinInfo mit f"ur SfxDockingWindow spezifischen Daten,
1231 damit sie in die INI-Datei geschrieben werden koennen.
1232 Es wird angenommen, da\s rInfo alle anderen evt. relevanten Daten in
1233 der ChildWindow-Klasse erh"alt.
1234 Eingetragen werden hier gemerkten Gr"o\sen, das ZoomIn-Flag und die
1235 f"ur das Docking relevanten Informationen.
1236 Wird diese Methode "uberschrieben, mu\s zuerst die Basisimplementierung
1244 if ( GetFloatingWindow() && pImp
->bConstructed
)
1245 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
1247 rInfo
.aWinState
= pImp
->aWinState
;
1248 rInfo
.aExtraString
= DEFINE_CONST_UNICODE("AL:(");
1249 rInfo
.aExtraString
+= String::CreateFromInt32((USHORT
) GetAlignment());
1250 rInfo
.aExtraString
+= ',';
1251 rInfo
.aExtraString
+= String::CreateFromInt32 ((USHORT
) pImp
->GetLastAlignment());
1252 if ( pImp
->bSplitable
)
1254 Point
aPos(pImp
->nLine
, pImp
->nPos
);
1255 rInfo
.aExtraString
+= ',';
1256 rInfo
.aExtraString
+= String::CreateFromInt32( aPos
.X() );
1257 rInfo
.aExtraString
+= '/';
1258 rInfo
.aExtraString
+= String::CreateFromInt32( aPos
.Y() );
1259 rInfo
.aExtraString
+= '/';
1260 rInfo
.aExtraString
+= String::CreateFromInt32( pImp
->nHorizontalSize
);
1261 rInfo
.aExtraString
+= '/';
1262 rInfo
.aExtraString
+= String::CreateFromInt32( pImp
->nVerticalSize
);
1263 rInfo
.aExtraString
+= ',';
1264 rInfo
.aExtraString
+= String::CreateFromInt32( pImp
->aSplitSize
.Width() );
1265 rInfo
.aExtraString
+= ';';
1266 rInfo
.aExtraString
+= String::CreateFromInt32( pImp
->aSplitSize
.Height() );
1269 rInfo
.aExtraString
+= ')';
1272 //-------------------------------------------------------------------------
1274 SfxDockingWindow::~SfxDockingWindow()
1276 ReleaseChildWindow_Impl();
1280 void SfxDockingWindow::ReleaseChildWindow_Impl()
1282 if ( pMgr
&& pMgr
->GetFrame() == pBindings
->GetActiveFrame() )
1283 pBindings
->SetActiveFrame( NULL
);
1285 if ( pMgr
&& pImp
->pSplitWin
&& pImp
->pSplitWin
->IsItemValid( GetType() ) )
1286 pImp
->pSplitWin
->RemoveWindow(this);
1291 //-------------------------------------------------------------------------
1293 SfxChildAlignment
SfxDockingWindow::CalcAlignment(const Point
& rPos
, Rectangle
& rRect
)
1297 Diese Methode berechnet f"ur gegebene Mausposition und tracking rectangle,
1298 welches Alignment sich daraus ergeben w"urde. Beim Wechsel des Alignments
1299 kann sich auch das tracking rectangle "andern, so dass ein ver"andertes
1300 rectangle zur"uckgegeben wird.
1302 Der Klassenbenutzer kann das Verhalten dieser Methode und damit das Verhalten
1303 seiner DockinWindow-Klasse beim Docken beeinflussen, indem er die hier
1304 aufgerufene virtuelle Methode
1306 SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign)
1308 "uberschreibt (s.u.).
1312 // calculate hypothetical sizes for different modes
1313 Size
aFloatingSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT
));
1314 Size
aVerticalSize(CalcDockingSize(SFX_ALIGN_LEFT
));
1315 Size
aHorizontalSize(CalcDockingSize(SFX_ALIGN_TOP
));
1317 // check if docking is permitted
1318 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1319 if ( !pWorkWin
->IsDockingAllowed() )
1321 rRect
.SetSize( aFloatingSize
);
1322 return pImp
->GetDockAlignment();
1325 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1326 long nLRBorder
, nTBBorder
;
1327 if ( pImp
->bSplitable
)
1329 // take the smaller size of docked and floating mode
1330 Size aSize
= pImp
->aSplitSize
;
1331 if ( GetFloatingSize().Height() < aSize
.Height() )
1332 aSize
.Height() = GetFloatingSize().Height();
1333 if ( GetFloatingSize().Width() < aSize
.Width() )
1334 aSize
.Width() = GetFloatingSize().Width();
1336 nLRBorder
= aSize
.Width();
1337 nTBBorder
= aSize
.Height();
1341 nLRBorder
= aVerticalSize
.Width();
1342 nTBBorder
= aHorizontalSize
.Height();
1345 // limit border to predefined constant values
1346 if ( nLRBorder
> MAX_TOGGLEAREA_WIDTH
)
1347 nLRBorder
= MAX_TOGGLEAREA_WIDTH
;
1348 if ( nTBBorder
> MAX_TOGGLEAREA_WIDTH
)
1349 nTBBorder
= MAX_TOGGLEAREA_WIDTH
;
1351 // shrink area for floating mode if possible
1352 Rectangle aInRect
= GetInnerRect();
1353 if ( aInRect
.GetWidth() > nLRBorder
)
1354 aInRect
.Left() += nLRBorder
/2;
1355 if ( aInRect
.GetWidth() > nLRBorder
)
1356 aInRect
.Right() -= nLRBorder
/2;
1357 if ( aInRect
.GetHeight() > nTBBorder
)
1358 aInRect
.Top() += nTBBorder
/2;
1359 if ( aInRect
.GetHeight() > nTBBorder
)
1360 aInRect
.Bottom() -= nTBBorder
/2;
1362 // calculate alignment resulting from docking rectangle
1363 BOOL bBecomesFloating
= FALSE
;
1364 SfxChildAlignment eDockAlign
= pImp
->GetDockAlignment();
1365 Rectangle
aDockingRect( rRect
);
1366 if ( !IsFloatingMode() )
1368 // don't use tracking rectangle for alignment check, because it will be too large
1369 // to get a floating mode as result - switch to floating size
1370 // so the calculation only depends on the position of the rectangle, not the current
1371 // docking state of the window
1372 aDockingRect
.SetSize( GetFloatingSize() );
1374 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1375 aDockingRect
.SetPos( pWorkWin
->GetWindow()->OutputToScreenPixel( pWorkWin
->GetWindow()->GetPointerPosPixel() ) );
1378 Point aPos
= aDockingRect
.TopLeft();
1379 Rectangle aIntersect
= GetOuterRect().GetIntersection( aDockingRect
);
1380 if ( aIntersect
.IsEmpty() )
1381 // docking rectangle completely outside docking area -> floating mode
1382 bBecomesFloating
= TRUE
;
1385 // create a small test rect around the mouse position and use this one
1386 // instead of the passed rRect to not dock too easily or by accident
1387 Rectangle aSmallDockingRect
;
1388 aSmallDockingRect
.SetSize( Size( MAX_TOGGLEAREA_WIDTH
, MAX_TOGGLEAREA_HEIGHT
) );
1389 Point
aNewPos(rPos
);
1390 aNewPos
.X() -= aSmallDockingRect
.GetWidth()/2;
1391 aNewPos
.Y() -= aSmallDockingRect
.GetHeight()/2;
1392 aSmallDockingRect
.SetPos(rPos
);
1393 Rectangle aIntersectRect
= aInRect
.GetIntersection( aSmallDockingRect
);
1394 if ( aIntersectRect
== aSmallDockingRect
)
1395 // docking rectangle completely inside (shrinked) inner area -> floating mode
1396 bBecomesFloating
= TRUE
;
1399 if ( bBecomesFloating
)
1401 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
);
1405 // docking rectangle is in the "sensible area"
1406 Point
aInPosTL( aPos
.X()-aInRect
.Left(), aPos
.Y()-aInRect
.Top() );
1407 Point
aInPosBR( aPos
.X()-aInRect
.Left() + aDockingRect
.GetWidth(), aPos
.Y()-aInRect
.Top() + aDockingRect
.GetHeight() );
1408 Size aInSize
= aInRect
.GetSize();
1409 BOOL bNoChange
= FALSE
;
1411 // check if alignment is still unchanged
1412 switch ( GetAlignment() )
1414 case SFX_ALIGN_LEFT
:
1415 case SFX_ALIGN_FIRSTLEFT
:
1416 case SFX_ALIGN_LASTLEFT
:
1417 if (aInPosTL
.X() <= 0)
1419 eDockAlign
= GetAlignment();
1424 case SFX_ALIGN_LOWESTTOP
:
1425 case SFX_ALIGN_HIGHESTTOP
:
1426 if ( aInPosTL
.Y() <= 0)
1428 eDockAlign
= GetAlignment();
1432 case SFX_ALIGN_RIGHT
:
1433 case SFX_ALIGN_FIRSTRIGHT
:
1434 case SFX_ALIGN_LASTRIGHT
:
1435 if ( aInPosBR
.X() >= aInSize
.Width())
1437 eDockAlign
= GetAlignment();
1441 case SFX_ALIGN_BOTTOM
:
1442 case SFX_ALIGN_LOWESTBOTTOM
:
1443 case SFX_ALIGN_HIGHESTBOTTOM
:
1444 if ( aInPosBR
.Y() >= aInSize
.Height())
1446 eDockAlign
= GetAlignment();
1456 // alignment will change, test alignment according to distance of the docking rectangles edges
1457 BOOL bForbidden
= TRUE
;
1458 if ( aInPosTL
.X() <= 0)
1460 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_LEFT
);
1461 bForbidden
= ( eDockAlign
!= SFX_ALIGN_LEFT
&&
1462 eDockAlign
!= SFX_ALIGN_FIRSTLEFT
&&
1463 eDockAlign
!= SFX_ALIGN_LASTLEFT
);
1466 if ( bForbidden
&& aInPosTL
.Y() <= 0)
1468 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_TOP
);
1469 bForbidden
= ( eDockAlign
!= SFX_ALIGN_TOP
&&
1470 eDockAlign
!= SFX_ALIGN_HIGHESTTOP
&&
1471 eDockAlign
!= SFX_ALIGN_LOWESTTOP
);
1474 if ( bForbidden
&& aInPosBR
.X() >= aInSize
.Width())
1476 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_RIGHT
);
1477 bForbidden
= ( eDockAlign
!= SFX_ALIGN_RIGHT
&&
1478 eDockAlign
!= SFX_ALIGN_FIRSTRIGHT
&&
1479 eDockAlign
!= SFX_ALIGN_LASTRIGHT
);
1482 if ( bForbidden
&& aInPosBR
.Y() >= aInSize
.Height())
1484 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_BOTTOM
);
1485 bForbidden
= ( eDockAlign
!= SFX_ALIGN_BOTTOM
&&
1486 eDockAlign
!= SFX_ALIGN_HIGHESTBOTTOM
&&
1487 eDockAlign
!= SFX_ALIGN_LOWESTBOTTOM
);
1490 // the calculated alignment was rejected by the window -> take floating mode
1492 eDockAlign
= CheckAlignment(pImp
->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT
);
1496 if ( eDockAlign
== SFX_ALIGN_NOALIGNMENT
)
1498 //Im FloatingMode erh"alt das tracking rectangle die floating size
1499 // wg. SV-Bug darf rRect nur ver"andert werden, wenn sich das
1500 // Alignment "andert !
1501 if ( eDockAlign
!= pImp
->GetDockAlignment() )
1502 aDockingRect
.SetSize( aFloatingSize
);
1504 else if ( pImp
->bSplitable
)
1507 SfxSplitWindow
*pSplitWin
= pWorkWin
->GetSplitWindow_Impl(eDockAlign
);
1508 aPos
= pSplitWin
->ScreenToOutputPixel( aPos
);
1509 if ( pSplitWin
->GetWindowPos( aPos
, nLine
, nPos
) )
1511 // mouse over splitwindow, get line and position
1512 pImp
->nDockLine
= nLine
;
1513 pImp
->nDockPos
= nPos
;
1514 pImp
->bNewLine
= FALSE
;
1520 // mouse touches outer border -> treated as floating mode
1521 eDockAlign
= SFX_ALIGN_NOALIGNMENT
;
1522 aDockingRect
.SetSize( aFloatingSize
);
1523 rRect
= aDockingRect
;
1527 // mouse touches inner border -> create new line
1528 if ( eDockAlign
== GetAlignment() && pImp
->pSplitWin
&&
1529 pImp
->nLine
== pImp
->pSplitWin
->GetLineCount()-1 && pImp
->pSplitWin
->GetWindowCount(pImp
->nLine
) == 1 )
1531 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1532 pImp
->nDockLine
= pImp
->nLine
;
1533 pImp
->nDockPos
= pImp
->nPos
;
1534 pImp
->bNewLine
= FALSE
;
1539 pImp
->nDockLine
= pSplitWin
->GetLineCount();
1541 pImp
->bNewLine
= TRUE
;
1545 BOOL bChanged
= pImp
->nLine
!= pImp
->nDockLine
|| pImp
->nPos
!= pImp
->nDockPos
|| eDockAlign
!= GetAlignment();
1546 if ( !bChanged
&& !IsFloatingMode() )
1548 // window only sightly moved, no change of any property
1549 rRect
.SetSize( pImp
->aSplitSize
);
1550 rRect
.SetPos( aDockingRect
.TopLeft() );
1554 // calculate new size and position
1556 Point aPoint
= aDockingRect
.TopLeft();
1557 Size aInnerSize
= GetInnerRect().GetSize();
1558 if ( eDockAlign
== SFX_ALIGN_LEFT
|| eDockAlign
== SFX_ALIGN_RIGHT
)
1560 if ( pImp
->bNewLine
)
1562 // set height to height of free area
1563 aSize
.Height() = aInnerSize
.Height();
1564 aSize
.Width() = pImp
->nHorizontalSize
;
1565 if ( eDockAlign
== SFX_ALIGN_LEFT
)
1567 aPoint
= aInnerRect
.TopLeft();
1571 aPoint
= aInnerRect
.TopRight();
1572 aPoint
.X() -= aSize
.Width();
1577 // get width from splitwindow
1578 aSize
.Width() = pSplitWin
->GetLineSize(nLine
);
1579 aSize
.Height() = pImp
->aSplitSize
.Height();
1584 if ( pImp
->bNewLine
)
1586 // set width to width of free area
1587 aSize
.Width() = aInnerSize
.Width();
1588 aSize
.Height() = pImp
->nVerticalSize
;
1589 if ( eDockAlign
== SFX_ALIGN_TOP
)
1591 aPoint
= aInnerRect
.TopLeft();
1595 aPoint
= aInnerRect
.BottomLeft();
1596 aPoint
.Y() -= aSize
.Height();
1601 // get height from splitwindow
1602 aSize
.Height() = pSplitWin
->GetLineSize(nLine
);
1603 aSize
.Width() = pImp
->aSplitSize
.Width();
1607 aDockingRect
.SetSize( aSize
);
1608 aDockingRect
.SetPos( aPoint
);
1612 // window can be docked, but outside our splitwindows
1613 // tracking rectangle only needs to be modified if alignment was changed
1614 if ( eDockAlign
!= pImp
->GetDockAlignment() )
1616 switch ( eDockAlign
)
1618 case SFX_ALIGN_LEFT
:
1619 case SFX_ALIGN_RIGHT
:
1620 case SFX_ALIGN_FIRSTLEFT
:
1621 aDockingRect
.SetPos( aInnerRect
.TopLeft() );
1622 aDockingRect
.SetSize( aVerticalSize
);
1624 case SFX_ALIGN_LASTLEFT
:
1625 case SFX_ALIGN_FIRSTRIGHT
:
1626 case SFX_ALIGN_LASTRIGHT
:
1628 Point
aPt( aInnerRect
.TopRight() );
1629 aPt
.X() -= aDockingRect
.GetWidth();
1630 aDockingRect
.SetPos( aPt
);
1631 aDockingRect
.SetSize( aVerticalSize
);
1636 case SFX_ALIGN_BOTTOM
:
1637 case SFX_ALIGN_LOWESTTOP
:
1638 aDockingRect
.SetPos( aInnerRect
.TopLeft() );
1639 aDockingRect
.SetSize( aHorizontalSize
);
1641 case SFX_ALIGN_HIGHESTTOP
:
1642 case SFX_ALIGN_LOWESTBOTTOM
:
1643 case SFX_ALIGN_HIGHESTBOTTOM
:
1645 Point
aPt( aInnerRect
.BottomLeft() );
1646 aPt
.Y() -= aDockingRect
.GetHeight();
1647 aDockingRect
.SetPos( aPt
);
1648 aDockingRect
.SetSize( aHorizontalSize
);
1657 rRect
= aDockingRect
;
1661 //-------------------------------------------------------------------------
1663 Size
SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign
)
1667 Virtuelle Methode der Klasse SfxDockingWindow.
1668 Hier wird festgelegt, wie sich die Gr"o\se des DockingWindows abh"angig vom
1670 Die Basisimplementation setzt im Floating Mode die Gr"o\se auf die gemerkte
1672 Bei horizontalem Alignment wird die Breite auf die Breite des "au\seren
1673 DockingRects, bei vertikalem Alignment die H"ohe auf die H"ohe des inneren
1674 DockingRects (ergibt sich aus der Reihenfolge, in der im SFX ChildWindows
1675 ausgegeben werden). Die jeweils andere Gr"o\se wird auf die aktuelle
1676 Floating Size gesetzt, hier k"onnte eine abgeleitete Klasse "andernd
1678 Die DockingSize mu\s f"ur Left/Right und Top/Bottom jeweils gleich sein.
1682 // Achtung: falls das Resizing auch im angedockten Zustand geht, mu\s dabei
1683 // auch die Floating Size angepa\st werden !?
1685 Size aSize
= GetFloatingSize();
1689 case SFX_ALIGN_BOTTOM
:
1690 case SFX_ALIGN_LOWESTTOP
:
1691 case SFX_ALIGN_HIGHESTTOP
:
1692 case SFX_ALIGN_LOWESTBOTTOM
:
1693 case SFX_ALIGN_HIGHESTBOTTOM
:
1694 aSize
.Width() = aOuterRect
.Right() - aOuterRect
.Left();
1696 case SFX_ALIGN_LEFT
:
1697 case SFX_ALIGN_RIGHT
:
1698 case SFX_ALIGN_FIRSTLEFT
:
1699 case SFX_ALIGN_LASTLEFT
:
1700 case SFX_ALIGN_FIRSTRIGHT
:
1701 case SFX_ALIGN_LASTRIGHT
:
1702 aSize
.Height() = aInnerRect
.Bottom() - aInnerRect
.Top();
1704 case SFX_ALIGN_NOALIGNMENT
:
1713 //-------------------------------------------------------------------------
1715 SfxChildAlignment
SfxDockingWindow::CheckAlignment(SfxChildAlignment
,
1716 SfxChildAlignment eAlign
)
1720 Virtuelle Methode der Klasse SfxDockingWindow.
1721 Hier kann eine abgeleitete Klasse bestimmte Alignments verbieten.
1722 Die Basisimplementation verbietet kein Alignment.
1729 //-------------------------------------------------------------------------
1731 BOOL
SfxDockingWindow::Close()
1735 Das Fenster wird geschlossen, indem das ChildWindow durch Ausf"uhren des
1736 ChildWindow-Slots zerst"ort wird.
1737 Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
1738 danach SfxDockingWindow::Close() gerufen werden, wenn nicht das Close()
1739 mit "return FALSE" abgebrochen wird.
1743 // Execute mit Parametern, da Toggle von einigen ChildWindows ignoriert
1748 SfxBoolItem
aValue( pMgr
->GetType(), FALSE
);
1749 pBindings
->GetDispatcher_Impl()->Execute(
1750 pMgr
->GetType(), SFX_CALLMODE_RECORD
| SFX_CALLMODE_ASYNCHRON
, &aValue
, 0L );
1754 //-------------------------------------------------------------------------
1756 void SfxDockingWindow::Paint(const Rectangle
& /*rRect*/)
1760 Es wird im angedockten Zustand eine Begrenzungslinie an der angedockten
1761 Kante und ein Rahmen ausgegeben. Dabei wird SVLOOK ber"ucksichtigt.
1765 if ( pImp
->bSplitable
|| IsFloatingMode() )
1768 Rectangle aRect
= Rectangle(Point(0, 0),
1769 GetOutputSizePixel());
1770 switch (GetAlignment())
1774 DrawLine(aRect
.BottomLeft(), aRect
.BottomRight());
1779 case SFX_ALIGN_BOTTOM
:
1781 DrawLine(aRect
.TopLeft(), aRect
.TopRight());
1786 case SFX_ALIGN_LEFT
:
1788 DrawLine(aRect
.TopRight(), aRect
.BottomRight());
1793 case SFX_ALIGN_RIGHT
:
1795 DrawLine(aRect
.TopLeft(), aRect
.BottomLeft());
1803 DecorationView
aView( this );
1804 aView
.DrawFrame( aRect
, FRAME_DRAW_OUT
);
1807 //-------------------------------------------------------------------------
1809 void SfxDockingWindow::SetMinOutputSizePixel( const Size
& rSize
)
1813 Mit dieser Methode kann eine minimale OutpuSize gesetzt werden, die
1814 im Resizing()-Handler abgefragt wird.
1818 pImp
->aMinSize
= rSize
;
1819 DockingWindow::SetMinOutputSizePixel( rSize
);
1822 //-------------------------------------------------------------------------
1824 Size
SfxDockingWindow::GetMinOutputSizePixel() const
1828 Die gesetzte minimale Gr"o\se wird zur"uckgegeben.
1832 return pImp
->aMinSize
;
1835 //-------------------------------------------------------------------------
1837 long SfxDockingWindow::Notify( NotifyEvent
& rEvt
)
1839 if ( rEvt
.GetType() == EVENT_GETFOCUS
)
1841 pBindings
->SetActiveFrame( pMgr
->GetFrame() );
1843 if ( pImp
->pSplitWin
)
1844 pImp
->pSplitWin
->SetActiveWindow_Impl( this );
1846 pMgr
->Activate_Impl();
1848 Window
* pWindow
= rEvt
.GetWindow();
1850 while ( !nHelpId
&& pWindow
)
1852 nHelpId
= pWindow
->GetHelpId();
1853 pWindow
= pWindow
->GetParent();
1857 SfxHelp::OpenHelpAgent( pBindings
->GetDispatcher_Impl()->GetFrame()->GetFrame(), nHelpId
);
1859 // In VCL geht Notify zun"achst an das Fenster selbst,
1860 // also base class rufen, sonst erf"ahrt der parent nichts
1861 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1862 DockingWindow::Notify( rEvt
);
1865 else if( rEvt
.GetType() == EVENT_KEYINPUT
)
1867 // KeyInput zuerst f"ur Dialogfunktionen zulassen
1868 if ( !DockingWindow::Notify( rEvt
) && SfxViewShell::Current() )
1869 // dann auch global g"ultige Acceleratoren verwenden
1870 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt
.GetKeyEvent() );
1873 else if ( rEvt
.GetType() == EVENT_LOSEFOCUS
&& !HasChildPathFocus() )
1875 pBindings
->SetActiveFrame( NULL
);
1876 pMgr
->Deactivate_Impl();
1879 return DockingWindow::Notify( rEvt
);
1883 USHORT
SfxDockingWindow::GetWinBits_Impl() const
1886 // if ( pImp->bAutoHide )
1887 // nBits |= SWIB_AUTOHIDE;
1891 //-------------------------------------------------------------------------
1893 void SfxDockingWindow::SetItemSize_Impl( const Size
& rSize
)
1895 pImp
->aSplitSize
= rSize
;
1897 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1898 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
1899 if ( pImp
->bSplitable
)
1900 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
1901 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_ALIGNDOCKINGWINDOW
, pMgr
->GetType() );
1904 void SfxDockingWindow::Disappear_Impl()
1906 if ( pImp
->pSplitWin
&& pImp
->pSplitWin
->IsItemValid( GetType() ) )
1907 pImp
->pSplitWin
->RemoveWindow(this);
1910 void SfxDockingWindow::Reappear_Impl()
1912 if ( pImp
->pSplitWin
&& !pImp
->pSplitWin
->IsItemValid( GetType() ) )
1914 pImp
->pSplitWin
->InsertWindow( this, pImp
->aSplitSize
);
1918 BOOL
SfxDockingWindow::IsAutoHide_Impl() const
1920 if ( pImp
->pSplitWin
)
1921 return !pImp
->pSplitWin
->IsFadeIn();
1926 BOOL
SfxDockingWindow::IsPinned_Impl() const
1928 if ( pImp
->pSplitWin
)
1929 return pImp
->pSplitWin
->IsPinned();
1933 void SfxDockingWindow::AutoShow( BOOL bShow
)
1935 AutoShow_Impl(bShow
);
1938 void SfxDockingWindow::AutoShow_Impl( BOOL bShow
)
1940 if ( pImp
->pSplitWin
)
1943 pImp
->pSplitWin
->FadeIn();
1945 pImp
->pSplitWin
->FadeOut();
1950 void SfxDockingWindow::Pin_Impl( BOOL bPinned )
1952 if ( pImp->pSplitWin )
1953 pImp->pSplitWin->Pin_Impl( bPinned );
1957 SfxSplitWindow
* SfxDockingWindow::GetSplitWindow_Impl() const
1959 return pImp
->pSplitWin
;
1962 void SfxDockingWindow::FadeIn( BOOL
/*bFadeIn*/ )
1966 void SfxDockingWindow::StateChanged( StateChangedType nStateChange
)
1968 if ( nStateChange
== STATE_CHANGE_INITSHOW
)
1971 DockingWindow::StateChanged( nStateChange
);
1974 void SfxDockingWindow::Move()
1977 pImp
->aMoveTimer
.Start();
1980 IMPL_LINK( SfxDockingWindow
, TimerHdl
, Timer
*, EMPTYARG
)
1982 pImp
->aMoveTimer
.Stop();
1983 if ( IsReallyVisible() && IsFloatingMode() )
1985 if( !GetFloatingWindow()->IsRollUp() )
1986 SetFloatingSize( GetOutputSizePixel() );
1987 pImp
->aWinState
= GetFloatingWindow()->GetWindowState();
1988 SfxChildIdentifier eIdent
= SFX_CHILDWIN_DOCKINGWINDOW
;
1989 if ( pImp
->bSplitable
)
1990 eIdent
= SFX_CHILDWIN_SPLITWINDOW
;
1991 SfxWorkWindow
*pWorkWin
= pBindings
->GetWorkWindow_Impl();
1992 pWorkWin
->ConfigChild_Impl( eIdent
, SFX_ALIGNDOCKINGWINDOW
, pMgr
->GetType() );