Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / dialog / dockwin.cxx
blob00da60db9a6117b2d04c154a84c9d1aef013c80a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <svl/eitem.hxx>
31 #include <vcl/decoview.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/timer.hxx>
35 #include <rtl/instance.hxx>
36 #include <toolkit/helper/vclunohelper.hxx>
37 #include <comphelper/processfactory.hxx>
39 #include <sfx2/dockwin.hxx>
40 #include <sfx2/bindings.hxx>
41 #include <sfx2/viewfrm.hxx>
42 #include <sfx2/dispatch.hxx>
43 #include "workwin.hxx"
44 #include "splitwin.hxx"
45 #include <sfx2/viewsh.hxx>
46 #include "sfx2/sfxhelp.hxx"
47 #include <sfx2/objsh.hxx>
48 #include <sfx2/msgpool.hxx>
50 #include <com/sun/star/frame/XController.hpp>
51 #include <com/sun/star/lang/XUnoTunnel.hpp>
52 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
53 #include <com/sun/star/awt/XWindow.hpp>
54 #include <com/sun/star/uno/XComponentContext.hpp>
55 #include <com/sun/star/frame/XModuleManager.hpp>
56 #include <com/sun/star/container/XNameAccess.hpp>
58 #define MAX_TOGGLEAREA_WIDTH 20
59 #define MAX_TOGGLEAREA_HEIGHT 20
61 using namespace ::com::sun::star;
63 // implemented in 'sfx2/source/appl/childwin.cxx'
64 extern sal_Bool GetPosSizeFromString( const String& rStr, Point& rPos, Size& rSize );
65 extern sal_Bool GetSplitSizeFromString( const String& rStr, Size& rSize );
67 // If you want to change the number you also have to:
68 // - Add new slot ids to sfxsids.hrc
69 // - Add new slots to frmslots.sdi
70 // - Add new slot definitions to sfx.sdi
71 static const int NUM_OF_DOCKINGWINDOWS = 10;
73 class SfxTitleDockingWindow;
74 class SfxTitleDockingWindow : public SfxDockingWindow
76 Window* m_pWrappedWindow;
77 sal_uInt16 m_nID;
79 public:
80 SfxTitleDockingWindow(
81 SfxBindings* pBindings ,
82 SfxChildWindow* pChildWin ,
83 Window* pParent ,
84 WinBits nBits,
85 sal_uInt16 nID);
86 virtual ~SfxTitleDockingWindow();
88 Window* GetWrappedWindow() const { return m_pWrappedWindow; }
89 void SetWrappedWindow(Window* const pWindow);
91 virtual void StateChanged( StateChangedType nType );
92 virtual long Notify( NotifyEvent& rNEvt );
93 virtual void Resize();
94 virtual void Resizing( Size& rSize );
95 virtual sal_Bool Close();
98 namespace
100 struct WindowState
102 ::rtl::OUString sTitle;
106 static bool lcl_getWindowState( const uno::Reference< container::XNameAccess >& xWindowStateMgr, const ::rtl::OUString& rResourceURL, WindowState& rWindowState )
108 bool bResult = false;
112 uno::Any a;
113 uno::Sequence< beans::PropertyValue > aWindowState;
114 a = xWindowStateMgr->getByName( rResourceURL );
115 if ( a >>= aWindowState )
117 for ( sal_Int32 n = 0; n < aWindowState.getLength(); n++ )
119 if ( aWindowState[n].Name == "UIName" )
121 aWindowState[n].Value >>= rWindowState.sTitle;
126 bResult = true;
128 catch ( container::NoSuchElementException& )
130 bResult = false;
133 return bResult;
136 SfxDockingWrapper::SfxDockingWrapper( Window* pParentWnd ,
137 sal_uInt16 nId ,
138 SfxBindings* pBindings ,
139 SfxChildWinInfo* pInfo )
140 : SfxChildWindow( pParentWnd , nId )
142 uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
143 const rtl::OUString aDockWindowResourceURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/dockingwindow/" ));
145 SfxTitleDockingWindow* pTitleDockWindow = new SfxTitleDockingWindow( pBindings, this, pParentWnd,
146 WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE, nId);
147 pWindow = pTitleDockWindow;
148 eChildAlignment = SFX_ALIGN_NOALIGNMENT;
150 // Use factory manager to retrieve XWindow factory. That can be used to instanciate
151 // the real window factory.
152 uno::Reference< lang::XSingleComponentFactory > xFactoryMgr(
153 xServiceManager->createInstance(
154 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
155 "com.sun.star.ui.WindowContentFactoryManager"))),
156 uno::UNO_QUERY );
158 if (xFactoryMgr.is())
160 SfxDispatcher* pDispatcher = pBindings->GetDispatcher();
161 uno::Reference< frame::XFrame > xFrame( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY );
162 uno::Sequence< uno::Any > aArgs(2);
163 beans::PropertyValue aPropValue;
164 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
165 aPropValue.Value = uno::makeAny( xFrame );
166 aArgs[0] <<= aPropValue;
167 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ));
169 // create a resource URL from the nId provided by the sfx2
170 ::rtl::OUString aResourceURL( aDockWindowResourceURL );
171 aResourceURL += ::rtl::OUString::valueOf(sal_Int32(nId));
172 aPropValue.Value = uno::makeAny( aResourceURL );
173 aArgs[1] <<= aPropValue;
175 uno::Reference< awt::XWindow > xWindow;
178 uno::Reference< beans::XPropertySet > xProps( xServiceManager, uno::UNO_QUERY );
179 uno::Reference< uno::XComponentContext > xContext;
181 if ( xProps.is() )
182 xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
183 if ( xContext.is() )
185 xWindow = uno::Reference< awt::XWindow>(
186 xFactoryMgr->createInstanceWithArgumentsAndContext( aArgs, xContext ),
187 uno::UNO_QUERY );
190 static uno::WeakReference< frame::XModuleManager > m_xModuleManager;
192 uno::Reference< frame::XModuleManager > xModuleManager( m_xModuleManager );
193 if ( !xModuleManager.is() )
195 xModuleManager = uno::Reference< frame::XModuleManager >(
196 xServiceManager->createInstance(
197 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ))),
198 uno::UNO_QUERY );
199 m_xModuleManager = xModuleManager;
202 static uno::WeakReference< container::XNameAccess > m_xWindowStateConfiguration;
204 uno::Reference< container::XNameAccess > xWindowStateConfiguration( m_xWindowStateConfiguration );
205 if ( !xWindowStateConfiguration.is() )
207 xWindowStateConfiguration = uno::Reference< container::XNameAccess >(
208 xServiceManager->createInstance(
209 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.WindowStateConfiguration" ))),
210 uno::UNO_QUERY );
211 m_xWindowStateConfiguration = xWindowStateConfiguration;
214 ::rtl::OUString sModuleIdentifier = xModuleManager->identify( xFrame );
216 uno::Reference< container::XNameAccess > xModuleWindowState(
217 xWindowStateConfiguration->getByName( sModuleIdentifier ),
218 uno::UNO_QUERY );
219 if ( xModuleWindowState.is() )
221 WindowState aDockWinState;
222 if ( lcl_getWindowState( xModuleWindowState, aResourceURL, aDockWinState ))
223 pTitleDockWindow->SetText( aDockWinState.sTitle );
226 catch ( beans::UnknownPropertyException& )
229 catch ( uno::RuntimeException& )
232 catch ( uno::Exception& )
236 Window* pContentWindow = VCLUnoHelper::GetWindow(xWindow);
237 if ( pContentWindow )
238 pContentWindow->SetStyle( pContentWindow->GetStyle() | WB_DIALOGCONTROL | WB_CHILDDLGCTRL );
239 pTitleDockWindow->SetWrappedWindow(pContentWindow);
242 pWindow->SetOutputSizePixel( Size( 270, 240 ) );
244 ( ( SfxDockingWindow* ) pWindow )->Initialize( pInfo );
245 SetHideNotDelete( sal_True );
248 SfxChildWindow* SfxDockingWrapper::CreateImpl(
249 Window *pParent, sal_uInt16 nId, SfxBindings *pBindings, SfxChildWinInfo* pInfo )
251 SfxChildWindow *pWin = new SfxDockingWrapper(pParent, nId, pBindings, pInfo);
252 return pWin;
255 sal_uInt16 SfxDockingWrapper::GetChildWindowId ()
257 DBG_ASSERT( false, "This method shouldn't be called!" );
258 return 0;
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 sal_uInt16 nID = sal_uInt16(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 );
278 return aInfo;
281 SfxTitleDockingWindow::SfxTitleDockingWindow( SfxBindings* pBind ,
282 SfxChildWindow* pChildWin ,
283 Window* pParent ,
284 WinBits nBits,
285 sal_uInt16 nID ) :
286 SfxDockingWindow( pBind ,
287 pChildWin ,
288 pParent ,
289 nBits ),
290 m_pWrappedWindow(0),
291 m_nID(nID)
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();
321 if ( pWindow )
323 pWindow->SetSizePixel( GetOutputSizePixel() );
324 pWindow->Show();
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 sal_Bool SfxTitleDockingWindow::Close()
347 return SfxDockingWindow::Close();
350 namespace
352 struct ChildrenRegisteredMap : public rtl::Static< bool, ChildrenRegisteredMap > {};
355 static bool lcl_checkDockingWindowID( sal_uInt16 nID )
357 if (nID < SID_DOCKWIN_START || nID >= sal_uInt16(SID_DOCKWIN_START+NUM_OF_DOCKINGWINDOWS))
358 return false;
359 else
360 return true;
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;
368 while ( pFrame )
370 uno::Reference< frame::XFrame > xViewShellFrame( pFrame->GetFrameInterface() );
371 if ( xViewShellFrame == rFrame )
373 pXFrame = pFrame;
374 break;
376 else
377 pFrame = SfxFrame::GetNext( *pFrame );
380 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
381 if ( pXFrame )
382 return pXFrame->GetWorkWindow_Impl();
383 else
384 return NULL;
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 SolarMutexGuard aGuard;
395 sal_uInt16 nID = sal_uInt16(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 );
401 if ( pWorkWindow )
403 SfxChildWindow* pChildWindow = pWorkWindow->GetChildWindow_Impl(nID);
404 if ( !pChildWindow )
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 SolarMutexGuard aGuard;
422 sal_uInt16 nID = sal_uInt16(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 );
428 if ( pWorkWindow )
430 SfxChildWindow* pChildWindow = pWorkWindow->GetChildWindow_Impl(nID);
431 if ( pChildWindow )
432 return true;
436 return false;
439 class SfxDockingWindow_Impl
441 friend class SfxDockingWindow;
443 SfxChildAlignment eLastAlignment;
444 SfxChildAlignment eDockAlignment;
445 sal_Bool bConstructed;
446 Size aMinSize;
447 SfxSplitWindow* pSplitWin;
448 sal_Bool bSplitable;
449 Timer aMoveTimer;
451 // The following members are only valid in the time from startDocking to
452 // EndDocking:
453 sal_Bool bEndDocked;
454 Size aSplitSize;
455 long nHorizontalSize;
456 long nVerticalSize;
457 sal_uInt16 nLine;
458 sal_uInt16 nPos;
459 sal_uInt16 nDockLine;
460 sal_uInt16 nDockPos;
461 sal_Bool bNewLine;
462 sal_Bool bDockingPrevented;
463 rtl::OString aWinState;
465 SfxChildAlignment GetLastAlignment() const
466 { return eLastAlignment; }
467 void SetLastAlignment(SfxChildAlignment eAlign)
468 { eLastAlignment = eAlign; }
469 SfxChildAlignment GetDockAlignment() const
470 { return eDockAlignment; }
471 void SetDockAlignment(SfxChildAlignment eAlign)
472 { eDockAlignment = eAlign; }
475 //-------------------------------------------------------------------------
477 void SfxDockingWindow::Resize()
479 /* [Description]
481 This virtual method of the class FloatingWindow keeps track of changes in
482 FloatingSize. If this method is overridden by a derived class,
483 then the SfxFloatingWindow: Resize() must also be called.
486 DockingWindow::Resize();
487 Invalidate();
488 if ( pImp->bConstructed && pMgr )
490 if ( IsFloatingMode() )
492 // start timer for saving window status information
493 pImp->aMoveTimer.Start();
495 else
497 Size aSize( GetSizePixel() );
498 switch ( pImp->GetDockAlignment() )
500 case SFX_ALIGN_LEFT:
501 case SFX_ALIGN_FIRSTLEFT:
502 case SFX_ALIGN_LASTLEFT:
503 case SFX_ALIGN_RIGHT:
504 case SFX_ALIGN_FIRSTRIGHT:
505 case SFX_ALIGN_LASTRIGHT:
506 pImp->nHorizontalSize = aSize.Width();
507 pImp->aSplitSize = aSize;
508 break;
509 case SFX_ALIGN_TOP:
510 case SFX_ALIGN_LOWESTTOP:
511 case SFX_ALIGN_HIGHESTTOP:
512 case SFX_ALIGN_BOTTOM:
513 case SFX_ALIGN_HIGHESTBOTTOM:
514 case SFX_ALIGN_LOWESTBOTTOM:
515 pImp->nVerticalSize = aSize.Height();
516 pImp->aSplitSize = aSize;
517 break;
518 default:
519 break;
525 //-------------------------------------------------------------------------
527 sal_Bool SfxDockingWindow::PrepareToggleFloatingMode()
529 /* [Description]
531 This virtual method of the class DockingWindow makes it possible to
532 intervene in the switching of the floating mode.
533 If this method is overridden by a derived class,
534 then the SfxDockingWindow::PrepareToggleFloatingMode() must be called
535 afterwards, if not FALSE is returned.
539 if (!pImp->bConstructed)
540 return sal_True;
542 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr )
543 return sal_False;
545 if ( pImp->bDockingPrevented )
546 return sal_False;
548 if (!IsFloatingMode())
550 // Test, if FloatingMode is permitted.
551 if ( CheckAlignment(GetAlignment(),SFX_ALIGN_NOALIGNMENT) != SFX_ALIGN_NOALIGNMENT )
552 return sal_False;
554 if ( pImp->pSplitWin )
556 // The DockingWindow is inside a SplitWindow and will be teared of.
557 pImp->pSplitWin->RemoveWindow(this/*, sal_False*/);
558 pImp->pSplitWin = 0;
561 else if ( pMgr )
563 pImp->aWinState = GetFloatingWindow()->GetWindowState();
565 // Test if it is allowed to dock,
566 if (CheckAlignment(GetAlignment(),pImp->GetLastAlignment()) == SFX_ALIGN_NOALIGNMENT)
567 return sal_False;
569 // Test, if the Workwindow allows for docking at the moment.
570 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
571 if ( !pWorkWin->IsDockingAllowed() || !pWorkWin->IsInternalDockingAllowed() )
572 return sal_False;
575 return sal_True;
578 //-------------------------------------------------------------------------
580 void SfxDockingWindow::ToggleFloatingMode()
582 /* [Description]
584 This virtual method of the DockingWindow class sets the internal data of
585 the SfxDockingWindow and ensures the correct alignment on the parent window.
586 Through PrepareToggleFloatMode and Initialize it is ensured that
587 pImp-> GetLastAlignment() always delivers an allowed alignment. If this
588 method is overloaded from a derived class, then first the
589 SfxDockingWindow:: ToggleFloatingMode() must be called.
592 if ( !pImp->bConstructed || !pMgr )
593 return; // No Handler call
595 // Remember old alignment and then switch.
596 // SV has already switched, but the alignment SfxDockingWindow is still
597 // the old one. What I was before?
598 SfxChildAlignment eLastAlign = GetAlignment();
600 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
601 SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
602 if ( pImp->bSplitable )
603 eIdent = SFX_CHILDWIN_SPLITWINDOW;
605 if (IsFloatingMode())
607 SetAlignment(SFX_ALIGN_NOALIGNMENT);
608 if ( !pImp->aWinState.isEmpty() )
609 GetFloatingWindow()->SetWindowState( pImp->aWinState );
610 else
611 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
613 else
615 if (pImp->GetDockAlignment() == eLastAlign)
617 // If ToggleFloatingMode was called, but the DockAlignment still
618 // is unchanged, then this means that it must have been a toggling
619 // through DClick, so use last alignment
620 SetAlignment (pImp->GetLastAlignment());
621 if ( !pImp->bSplitable )
622 SetSizePixel( CalcDockingSize(GetAlignment()) );
624 else
627 // Toggling was triggered by dragging
628 pImp->nLine = pImp->nDockLine;
629 pImp->nPos = pImp->nDockPos;
630 SetAlignment (pImp->GetDockAlignment());
633 if ( pImp->bSplitable )
635 // The DockingWindow is now in a SplitWindow
636 pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(GetAlignment());
638 // The LastAlignment is still the last docked
639 SfxSplitWindow *pSplit = pWorkWin->GetSplitWindow_Impl(pImp->GetLastAlignment());
641 DBG_ASSERT( pSplit, "LastAlignment is not correct!" );
642 if ( pSplit && pSplit != pImp->pSplitWin )
643 pSplit->ReleaseWindow_Impl(this);
644 if ( pImp->GetDockAlignment() == eLastAlign )
645 pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize );
646 else
647 pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize, pImp->nLine, pImp->nPos, pImp->bNewLine );
648 if ( !pImp->pSplitWin->IsFadeIn() )
649 pImp->pSplitWin->FadeIn();
653 // Keep the old alignment for the next toggle; set it only now due to the
654 // unregister SplitWindow!
655 pImp->SetLastAlignment(eLastAlign);
657 // Reset DockAlignment, if EndDocking is still called
658 pImp->SetDockAlignment(GetAlignment());
660 // Dock or undock SfxChildWindow correctly.
661 if ( pMgr )
662 pWorkWin->ConfigChild_Impl( eIdent, SFX_TOGGLEFLOATMODE, pMgr->GetType() );
665 //-------------------------------------------------------------------------
667 void SfxDockingWindow::StartDocking()
669 /* [Description]
671 This virtual method of the DockingWindow class takes the inner and outer
672 docking rectangle from the parent window. If this method is overloaded by a
673 a derived class, then SfxDockingWindow:StartDocking() has to be called at
674 the end.
677 if ( !pImp->bConstructed || !pMgr )
678 return;
679 SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
680 if ( pImp->bSplitable )
681 eIdent = SFX_CHILDWIN_SPLITWINDOW;
682 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
683 pWorkWin->ConfigChild_Impl( eIdent, SFX_SETDOCKINGRECTS, pMgr->GetType() );
684 pImp->SetDockAlignment(GetAlignment());
686 if ( pImp->pSplitWin )
688 // Get the current docking data
689 pImp->pSplitWin->GetWindowPos(this, pImp->nLine, pImp->nPos);
690 pImp->nDockLine = pImp->nLine;
691 pImp->nDockPos = pImp->nPos;
692 pImp->bNewLine = sal_False;
696 //-------------------------------------------------------------------------
698 sal_Bool SfxDockingWindow::Docking( const Point& rPos, Rectangle& rRect )
700 /* [Description]
702 This virtual method of the DockingWindow class calculates the current
703 tracking rectangle. For this purpose the method CalcAlignment(RPOs, rRect)
704 is used, the behavior can be influenced by the derived classes (see below).
705 This method should if possible not be overwritten.
708 if ( Application::IsInModalMode() )
709 return sal_True;
711 if ( !pImp->bConstructed || !pMgr )
713 rRect.SetSize( Size() );
714 return IsFloatingMode();
717 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
718 if ( pImp->bDockingPrevented || !pWorkWin->IsInternalDockingAllowed() )
719 return sal_False;
721 sal_Bool bFloatMode = sal_False;
723 if ( GetOuterRect().IsInside( rPos ) && !IsDockingPrevented() )
725 // Mouse within OuterRect: calculate Alignment and Rectangle
726 SfxChildAlignment eAlign = CalcAlignment(rPos, rRect);
727 if (eAlign == SFX_ALIGN_NOALIGNMENT)
728 bFloatMode = sal_True;
729 pImp->SetDockAlignment(eAlign);
731 else
733 // Mouse is not within OuterRect: must be FloatingWindow
734 // Is this allowed?
735 if (CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT) != SFX_ALIGN_NOALIGNMENT)
736 return sal_False;
737 bFloatMode = sal_True;
738 if ( SFX_ALIGN_NOALIGNMENT != pImp->GetDockAlignment() )
740 // Due to a bug the rRect may only be changed when the
741 // alignment is changed!
742 pImp->SetDockAlignment(SFX_ALIGN_NOALIGNMENT);
743 rRect.SetSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT));
747 if ( !pImp->bSplitable )
749 // For individually docked window the position is set through the
750 // alignment and the docking rectangle.
751 Size aSize = rRect.GetSize();
752 Point aPos;
754 switch ( pImp->GetDockAlignment() )
756 case SFX_ALIGN_LEFT:
757 case SFX_ALIGN_FIRSTLEFT:
758 case SFX_ALIGN_LASTLEFT:
759 aPos = aInnerRect.TopLeft();
760 if ( pImp->GetDockAlignment() == GetAlignment() )
761 aPos.X() -= aSize.Width();
762 break;
764 case SFX_ALIGN_TOP:
765 case SFX_ALIGN_LOWESTTOP:
766 case SFX_ALIGN_HIGHESTTOP:
767 aPos = Point(aOuterRect.Left(), aInnerRect.Top());
768 if ( pImp->GetDockAlignment() == GetAlignment() )
769 aPos.Y() -= aSize.Height();
770 break;
772 case SFX_ALIGN_RIGHT:
773 case SFX_ALIGN_FIRSTRIGHT:
774 case SFX_ALIGN_LASTRIGHT:
775 aPos = Point(aInnerRect.Right() - rRect.GetSize().Width(),
776 aInnerRect.Top());
777 if ( pImp->GetDockAlignment() == GetAlignment() )
778 aPos.X() += aSize.Width();
779 break;
781 case SFX_ALIGN_BOTTOM:
782 case SFX_ALIGN_HIGHESTBOTTOM:
783 case SFX_ALIGN_LOWESTBOTTOM:
784 aPos = Point(aOuterRect.Left(),
785 aInnerRect.Bottom() - rRect.GetSize().Height());
786 if ( pImp->GetDockAlignment() == GetAlignment() )
787 aPos.Y() += aSize.Height();
788 break;
789 default:
790 break;
793 rRect.SetPos(aPos);
796 return bFloatMode;
799 //-------------------------------------------------------------------------
801 void SfxDockingWindow::EndDocking( const Rectangle& rRect, sal_Bool bFloatMode )
803 /* [Description]
805 Virtual method of the DockingWindow class ensures the correct alignment on
806 the parent window. If this method is overloaded by a derived class, then
807 SfxDockingWindow::EndDocking() must be called first.
810 if ( !pImp->bConstructed || IsDockingCanceled() || !pMgr )
811 return;
813 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
814 sal_Bool bReArrange = sal_False;
815 if ( pImp->bSplitable )
817 // If the alignment changes and the window is in a docked state in a
818 // SplitWindow, then it must be re-registered. If it is docked again,
819 // PrepareToggleFloatingMode() and ToggleFloatingMode() preform the
820 // re-registered
821 if ( !bFloatMode )
822 bReArrange = sal_True;
825 if ( bReArrange )
827 if ( GetAlignment() != pImp->GetDockAlignment() )
829 // before Show() is called must the reassignment have been made,
830 // therefore the base class can not be called
831 if ( IsFloatingMode() || !pImp->bSplitable )
832 Show( sal_False, SHOW_NOFOCUSCHANGE );
834 // Set the size for toggling.
835 pImp->aSplitSize = rRect.GetSize();
836 if ( IsFloatingMode() )
838 SetFloatingMode( bFloatMode );
839 if ( IsFloatingMode() || !pImp->bSplitable )
840 Show( sal_True, SHOW_NOFOCUSCHANGE );
842 else
844 pImp->pSplitWin->RemoveWindow(this,sal_False);
845 pImp->nLine = pImp->nDockLine;
846 pImp->nPos = pImp->nDockPos;
847 pImp->pSplitWin->ReleaseWindow_Impl(this);
848 pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(pImp->GetDockAlignment());
849 pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize, pImp->nDockLine, pImp->nDockPos, pImp->bNewLine );
850 if ( !pImp->pSplitWin->IsFadeIn() )
851 pImp->pSplitWin->FadeIn();
854 else if ( pImp->nLine != pImp->nDockLine || pImp->nPos != pImp->nDockPos || pImp->bNewLine )
856 // Moved within Splitwindows
857 if ( pImp->nLine != pImp->nDockLine )
858 pImp->aSplitSize = rRect.GetSize();
859 pImp->pSplitWin->MoveWindow( this, pImp->aSplitSize, pImp->nDockLine, pImp->nDockPos, pImp->bNewLine );
862 else
864 pImp->bEndDocked = sal_True;
865 DockingWindow::EndDocking(rRect, bFloatMode);
866 pImp->bEndDocked = sal_False;
869 SetAlignment( IsFloatingMode() ? SFX_ALIGN_NOALIGNMENT : pImp->GetDockAlignment() );
872 //-------------------------------------------------------------------------
874 void SfxDockingWindow::Resizing( Size& /*rSize*/ )
876 /* [Description]
878 Virtual method of the DockingWindow class. Here, the interactive resize in
879 FloatingMode can be influenced, for example by only allowing for discrete
880 values for width and / or height. The base implementation prevents that the
881 output size is smaller than one set with SetMinOutputSizePixel().
888 //-------------------------------------------------------------------------
890 SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW,
891 Window* pParent, WinBits nWinBits) :
892 DockingWindow (pParent, nWinBits),
893 pBindings(pBindinx),
894 pMgr(pCW),
895 pImp(NULL)
897 /* [Description]
899 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
900 required because the docking is implemented in Sfx through SfxChildWindows.
904 if ( !GetHelpId().isEmpty() )
906 SetUniqueId( GetHelpId() );
907 SetHelpId("");
909 else
911 SfxViewFrame* pViewFrame = pBindings->GetDispatcher()->GetFrame();
912 SfxSlotPool* pSlotPool = pViewFrame->GetObjectShell()->GetModule()->GetSlotPool();
913 const SfxSlot* pSlot = pSlotPool->GetSlot( pCW->GetType() );
914 if ( pSlot )
916 rtl::OString aCmd("SFXDOCKINGWINDOW_");
917 aCmd += pSlot->GetUnoName();
918 SetUniqueId( aCmd );
922 pImp = new SfxDockingWindow_Impl;
923 pImp->bConstructed = sal_False;
924 pImp->pSplitWin = 0;
925 pImp->bEndDocked = sal_False;
926 pImp->bDockingPrevented = sal_False;
928 pImp->bSplitable = sal_True;
930 // Initially set to default, the alignment is set in the subclass
931 pImp->nLine = pImp->nDockLine = 0;
932 pImp->nPos = pImp->nDockPos = 0;
933 pImp->bNewLine = sal_False;
934 pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT);
935 pImp->aMoveTimer.SetTimeout(50);
936 pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxDockingWindow,TimerHdl));
939 //-------------------------------------------------------------------------
941 SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW,
942 Window* pParent, const ResId& rResId) :
943 DockingWindow(pParent, rResId),
944 pBindings(pBindinx),
945 pMgr(pCW),
946 pImp(NULL)
948 /* [Description]
950 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
951 required because the docking is implemented in Sfx through SfxChildWindows.
955 if ( !GetHelpId().isEmpty() )
957 SetUniqueId( GetHelpId() );
958 SetHelpId("");
960 else
962 SfxViewFrame* pViewFrame = pBindings->GetDispatcher()->GetFrame();
963 SfxSlotPool* pSlotPool = pViewFrame->GetObjectShell()->GetModule()->GetSlotPool();
964 const SfxSlot* pSlot = pSlotPool->GetSlot( pCW->GetType() );
965 if ( pSlot )
967 rtl::OString aCmd("SFXDOCKINGWINDOW_");
968 aCmd += pSlot->GetUnoName();
969 SetUniqueId( aCmd );
973 pImp = new SfxDockingWindow_Impl;
974 pImp->bConstructed = sal_False;
975 pImp->pSplitWin = 0;
976 pImp->bEndDocked = sal_False;
977 pImp->bDockingPrevented = sal_False;
979 pImp->bSplitable = sal_True;
981 // Initially set to default, the alignment is set in the subclass
982 pImp->nLine = pImp->nDockLine = 0;
983 pImp->nPos = pImp->nDockPos = 0;
984 pImp->bNewLine = sal_False;
985 pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT);
986 pImp->aMoveTimer.SetTimeout(50);
987 pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxDockingWindow,TimerHdl));
990 //-------------------------------------------------------------------------
992 void SfxDockingWindow::Initialize(SfxChildWinInfo *pInfo)
993 /* [Description]
995 Initialization of the SfxDockingDialog class via a SfxChildWinInfo.
996 The initialization is done only in a 2nd step after the constructor, this
997 constructor should be called from the derived class or from the
998 SfxChildWindows.
1001 if ( !pMgr )
1003 pImp->SetDockAlignment( SFX_ALIGN_NOALIGNMENT );
1004 pImp->bConstructed = sal_True;
1005 return;
1008 if ( pInfo->nFlags & SFX_CHILDWIN_FORCEDOCK )
1009 pImp->bDockingPrevented = sal_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
1026 String aStr;
1027 sal_uInt16 nPos = pInfo->aExtraString.SearchAscii("AL:");
1028 if ( nPos != STRING_NOTFOUND )
1030 // alignment information
1031 sal_uInt16 n1 = pInfo->aExtraString.Search('(', nPos);
1032 if ( n1 != STRING_NOTFOUND )
1034 sal_uInt16 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);
1045 if ( aStr.Len() )
1047 // accept window state only if alignment is also set
1048 pImp->aWinState = pInfo->aWinState;
1050 // check for valid alignment
1051 SfxChildAlignment eLocalAlignment = (SfxChildAlignment) (sal_uInt16) aStr.ToInt32();
1052 if ( pImp->bDockingPrevented )
1053 // docking prevented, ignore old configuration and take alignment from default
1054 aStr.Erase();
1055 else
1056 SetAlignment( eLocalAlignment );
1058 SfxChildAlignment eAlign = CheckAlignment(GetAlignment(),GetAlignment());
1059 if ( eAlign != GetAlignment() )
1061 OSL_FAIL("Invalid Alignment!");
1062 SetAlignment( eAlign );
1063 aStr.Erase();
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) (sal_uInt16) aStr.ToInt32() );
1074 nPos = aStr.Search(',');
1075 if ( nPos != STRING_NOTFOUND )
1077 // get split size and position in SplitWindow
1078 Point aPos;
1079 aStr.Erase(0, nPos+1);
1080 if ( GetPosSizeFromString( aStr, aPos, pImp->aSplitSize ) )
1082 pImp->nLine = pImp->nDockLine = (sal_uInt16) aPos.X();
1083 pImp->nPos = pImp->nDockPos = (sal_uInt16) aPos.Y();
1084 pImp->nVerticalSize = pImp->aSplitSize.Height();
1085 pImp->nHorizontalSize = pImp->aSplitSize.Width();
1086 if ( GetSplitSizeFromString( aStr, pImp->aSplitSize ))
1087 bVertHorzRead = sal_True;
1091 else {
1092 OSL_FAIL( "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
1106 if (
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 sal_Bool bFloatMode = IsFloatingMode();
1118 if ( bFloatMode != ((GetAlignment() == SFX_ALIGN_NOALIGNMENT)) )
1120 bFloatMode = !bFloatMode;
1121 SetFloatingMode( bFloatMode );
1122 if ( bFloatMode )
1124 if ( !pImp->aWinState.isEmpty() )
1125 GetFloatingWindow()->SetWindowState( pImp->aWinState );
1126 else
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);
1145 else
1147 // docked window must have NOALIGNMENT as last alignment
1148 pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT);
1150 if ( pImp->bSplitable )
1152 pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(GetAlignment());
1153 pImp->pSplitWin->InsertWindow(this, pImp->aSplitSize);
1155 else
1157 //?????? Currently not supported
1158 // Window is docked individually; size is calculated.
1159 // It must therefore be initialized with the DloatingSize if
1160 // someone relies on it that a reasonable size is set
1161 SetSizePixel(GetFloatingSize());
1162 SetSizePixel(CalcDockingSize(GetAlignment()));
1166 // save alignment
1167 pImp->SetDockAlignment( GetAlignment() );
1170 void SfxDockingWindow::Initialize_Impl()
1172 if ( !pMgr )
1174 pImp->bConstructed = sal_True;
1175 return;
1178 FloatingWindow* pFloatWin = GetFloatingWindow();
1179 sal_Bool bSet = sal_False;
1180 if ( pFloatWin )
1182 bSet = !pFloatWin->IsDefaultPos();
1184 else
1186 Point aPos = GetFloatingPos();
1187 if ( aPos != Point() )
1188 bSet = sal_True;
1191 if ( !bSet)
1193 SfxViewFrame *pFrame = pBindings->GetDispatcher_Impl()->GetFrame();
1194 Window* pEditWin = pFrame->GetViewShell()->GetWindow();
1195 Point aPos = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
1196 aPos = GetParent()->ScreenToOutputPixel( aPos );
1197 SetFloatingPos( aPos );
1200 if ( pFloatWin )
1202 // initialize floating window
1203 if ( pImp->aWinState.isEmpty() )
1204 // window state never set before, get if from defaults
1205 pImp->aWinState = pFloatWin->GetWindowState();
1207 // trick: use VCL method SetWindowState to adjust position and size
1208 pFloatWin->SetWindowState( pImp->aWinState );
1210 // remember floating size for calculating alignment and tracking rectangle
1211 SetFloatingSize( pFloatWin->GetSizePixel() );
1215 // allow calling of docking handlers
1216 pImp->bConstructed = sal_True;
1219 //-------------------------------------------------------------------------
1221 void SfxDockingWindow::FillInfo(SfxChildWinInfo& rInfo) const
1223 /* [Description]
1225 Fills a SfxChildWinInfo with specific data from SfxDockingWindow,
1226 so that it can be written in the INI file. It is assumed that rinfo
1227 receives all other possible relevant data in the ChildWindow class.
1228 Insertions are marked with size and the ZoomIn flag.
1229 If this method is overridden, the base implementation must be called first.
1233 if ( !pMgr )
1234 return;
1236 if ( GetFloatingWindow() && pImp->bConstructed )
1237 pImp->aWinState = GetFloatingWindow()->GetWindowState();
1239 rInfo.aWinState = pImp->aWinState;
1240 rInfo.aExtraString = DEFINE_CONST_UNICODE("AL:(");
1241 rInfo.aExtraString += String::CreateFromInt32((sal_uInt16) GetAlignment());
1242 rInfo.aExtraString += ',';
1243 rInfo.aExtraString += String::CreateFromInt32 ((sal_uInt16) pImp->GetLastAlignment());
1244 if ( pImp->bSplitable )
1246 Point aPos(pImp->nLine, pImp->nPos);
1247 rInfo.aExtraString += ',';
1248 rInfo.aExtraString += String::CreateFromInt32( aPos.X() );
1249 rInfo.aExtraString += '/';
1250 rInfo.aExtraString += String::CreateFromInt32( aPos.Y() );
1251 rInfo.aExtraString += '/';
1252 rInfo.aExtraString += String::CreateFromInt32( pImp->nHorizontalSize );
1253 rInfo.aExtraString += '/';
1254 rInfo.aExtraString += String::CreateFromInt32( pImp->nVerticalSize );
1255 rInfo.aExtraString += ',';
1256 rInfo.aExtraString += String::CreateFromInt32( pImp->aSplitSize.Width() );
1257 rInfo.aExtraString += ';';
1258 rInfo.aExtraString += String::CreateFromInt32( pImp->aSplitSize.Height() );
1261 rInfo.aExtraString += ')';
1264 //-------------------------------------------------------------------------
1266 SfxDockingWindow::~SfxDockingWindow()
1268 ReleaseChildWindow_Impl();
1269 delete pImp;
1272 void SfxDockingWindow::ReleaseChildWindow_Impl()
1274 if ( pMgr && pMgr->GetFrame() == pBindings->GetActiveFrame() )
1275 pBindings->SetActiveFrame( NULL );
1277 if ( pMgr && pImp->pSplitWin && pImp->pSplitWin->IsItemValid( GetType() ) )
1278 pImp->pSplitWin->RemoveWindow(this);
1280 pMgr=NULL;
1283 //-------------------------------------------------------------------------
1285 SfxChildAlignment SfxDockingWindow::CalcAlignment(const Point& rPos, Rectangle& rRect)
1287 /* [Description]
1289 This method calculates a resulting alignment for the given mouse position
1290 and tracking rectangle. When changing the alignment it can also be that
1291 the tracking rectangle is changed, so that an altered rectangle is
1292 returned. The user of this class can influence behaviour of this method,
1293 and thus the behavior of his DockinWindow class when docking where the
1294 called virtual method:
1296 SfxDockingWindow :: CalcDockingSize (SfxChildAlignment eAlign)
1298 is overridden (see below).
1302 // calculate hypothetical sizes for different modes
1303 Size aFloatingSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT));
1304 Size aVerticalSize(CalcDockingSize(SFX_ALIGN_LEFT));
1305 Size aHorizontalSize(CalcDockingSize(SFX_ALIGN_TOP));
1307 // check if docking is permitted
1308 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1309 if ( !pWorkWin->IsDockingAllowed() )
1311 rRect.SetSize( aFloatingSize );
1312 return pImp->GetDockAlignment();
1315 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1316 long nLRBorder, nTBBorder;
1317 if ( pImp->bSplitable )
1319 // take the smaller size of docked and floating mode
1320 Size aSize = pImp->aSplitSize;
1321 if ( GetFloatingSize().Height() < aSize.Height() )
1322 aSize.Height() = GetFloatingSize().Height();
1323 if ( GetFloatingSize().Width() < aSize.Width() )
1324 aSize.Width() = GetFloatingSize().Width();
1326 nLRBorder = aSize.Width();
1327 nTBBorder = aSize.Height();
1329 else
1331 nLRBorder = aVerticalSize.Width();
1332 nTBBorder = aHorizontalSize.Height();
1335 // limit border to predefined constant values
1336 if ( nLRBorder > MAX_TOGGLEAREA_WIDTH )
1337 nLRBorder = MAX_TOGGLEAREA_WIDTH;
1338 if ( nTBBorder > MAX_TOGGLEAREA_WIDTH )
1339 nTBBorder = MAX_TOGGLEAREA_WIDTH;
1341 // shrink area for floating mode if possible
1342 Rectangle aInRect = GetInnerRect();
1343 if ( aInRect.GetWidth() > nLRBorder )
1344 aInRect.Left() += nLRBorder/2;
1345 if ( aInRect.GetWidth() > nLRBorder )
1346 aInRect.Right() -= nLRBorder/2;
1347 if ( aInRect.GetHeight() > nTBBorder )
1348 aInRect.Top() += nTBBorder/2;
1349 if ( aInRect.GetHeight() > nTBBorder )
1350 aInRect.Bottom() -= nTBBorder/2;
1352 // calculate alignment resulting from docking rectangle
1353 sal_Bool bBecomesFloating = sal_False;
1354 SfxChildAlignment eDockAlign = pImp->GetDockAlignment();
1355 Rectangle aDockingRect( rRect );
1356 if ( !IsFloatingMode() )
1358 // don't use tracking rectangle for alignment check, because it will be too large
1359 // to get a floating mode as result - switch to floating size
1360 // so the calculation only depends on the position of the rectangle, not the current
1361 // docking state of the window
1362 aDockingRect.SetSize( GetFloatingSize() );
1364 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1365 aDockingRect.SetPos( pWorkWin->GetWindow()->OutputToScreenPixel( pWorkWin->GetWindow()->GetPointerPosPixel() ) );
1368 Point aPos = aDockingRect.TopLeft();
1369 Rectangle aIntersect = GetOuterRect().GetIntersection( aDockingRect );
1370 if ( aIntersect.IsEmpty() )
1371 // docking rectangle completely outside docking area -> floating mode
1372 bBecomesFloating = sal_True;
1373 else
1375 // create a small test rect around the mouse position and use this one
1376 // instead of the passed rRect to not dock too easily or by accident
1377 Rectangle aSmallDockingRect;
1378 aSmallDockingRect.SetSize( Size( MAX_TOGGLEAREA_WIDTH, MAX_TOGGLEAREA_HEIGHT ) );
1379 Point aNewPos(rPos);
1380 aNewPos.X() -= aSmallDockingRect.GetWidth()/2;
1381 aNewPos.Y() -= aSmallDockingRect.GetHeight()/2;
1382 aSmallDockingRect.SetPos(rPos);
1383 Rectangle aIntersectRect = aInRect.GetIntersection( aSmallDockingRect );
1384 if ( aIntersectRect == aSmallDockingRect )
1385 // docking rectangle completely inside (shrinked) inner area -> floating mode
1386 bBecomesFloating = sal_True;
1389 if ( bBecomesFloating )
1391 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT);
1393 else
1395 // docking rectangle is in the "sensible area"
1396 Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() );
1397 Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() );
1398 Size aInSize = aInRect.GetSize();
1399 sal_Bool bNoChange = sal_False;
1401 // check if alignment is still unchanged
1402 switch ( GetAlignment() )
1404 case SFX_ALIGN_LEFT:
1405 case SFX_ALIGN_FIRSTLEFT:
1406 case SFX_ALIGN_LASTLEFT:
1407 if (aInPosTL.X() <= 0)
1409 eDockAlign = GetAlignment();
1410 bNoChange = sal_True;
1412 break;
1413 case SFX_ALIGN_TOP:
1414 case SFX_ALIGN_LOWESTTOP:
1415 case SFX_ALIGN_HIGHESTTOP:
1416 if ( aInPosTL.Y() <= 0)
1418 eDockAlign = GetAlignment();
1419 bNoChange = sal_True;
1421 break;
1422 case SFX_ALIGN_RIGHT:
1423 case SFX_ALIGN_FIRSTRIGHT:
1424 case SFX_ALIGN_LASTRIGHT:
1425 if ( aInPosBR.X() >= aInSize.Width())
1427 eDockAlign = GetAlignment();
1428 bNoChange = sal_True;
1430 break;
1431 case SFX_ALIGN_BOTTOM:
1432 case SFX_ALIGN_LOWESTBOTTOM:
1433 case SFX_ALIGN_HIGHESTBOTTOM:
1434 if ( aInPosBR.Y() >= aInSize.Height())
1436 eDockAlign = GetAlignment();
1437 bNoChange = sal_True;
1439 break;
1440 default:
1441 break;
1444 if ( !bNoChange )
1446 // alignment will change, test alignment according to distance of the docking rectangles edges
1447 sal_Bool bForbidden = sal_True;
1448 if ( aInPosTL.X() <= 0)
1450 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_LEFT);
1451 bForbidden = ( eDockAlign != SFX_ALIGN_LEFT &&
1452 eDockAlign != SFX_ALIGN_FIRSTLEFT &&
1453 eDockAlign != SFX_ALIGN_LASTLEFT );
1456 if ( bForbidden && aInPosTL.Y() <= 0)
1458 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_TOP);
1459 bForbidden = ( eDockAlign != SFX_ALIGN_TOP &&
1460 eDockAlign != SFX_ALIGN_HIGHESTTOP &&
1461 eDockAlign != SFX_ALIGN_LOWESTTOP );
1464 if ( bForbidden && aInPosBR.X() >= aInSize.Width())
1466 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_RIGHT);
1467 bForbidden = ( eDockAlign != SFX_ALIGN_RIGHT &&
1468 eDockAlign != SFX_ALIGN_FIRSTRIGHT &&
1469 eDockAlign != SFX_ALIGN_LASTRIGHT );
1472 if ( bForbidden && aInPosBR.Y() >= aInSize.Height())
1474 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_BOTTOM);
1475 bForbidden = ( eDockAlign != SFX_ALIGN_BOTTOM &&
1476 eDockAlign != SFX_ALIGN_HIGHESTBOTTOM &&
1477 eDockAlign != SFX_ALIGN_LOWESTBOTTOM );
1480 // the calculated alignment was rejected by the window -> take floating mode
1481 if ( bForbidden )
1482 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT);
1486 if ( eDockAlign == SFX_ALIGN_NOALIGNMENT )
1488 // In the FloatingMode the tracking rectangle will get the floating
1489 // size. Due to a bug the rRect may only be changed when the
1490 // alignment is changed!
1491 if ( eDockAlign != pImp->GetDockAlignment() )
1492 aDockingRect.SetSize( aFloatingSize );
1494 else if ( pImp->bSplitable )
1496 sal_uInt16 nLine, nPos;
1497 SfxSplitWindow *pSplitWin = pWorkWin->GetSplitWindow_Impl(eDockAlign);
1498 aPos = pSplitWin->ScreenToOutputPixel( aPos );
1499 if ( pSplitWin->GetWindowPos( aPos, nLine, nPos ) )
1501 // mouse over splitwindow, get line and position
1502 pImp->nDockLine = nLine;
1503 pImp->nDockPos = nPos;
1504 pImp->bNewLine = sal_False;
1506 else
1508 if ( 0 )
1510 // mouse touches outer border -> treated as floating mode
1511 eDockAlign = SFX_ALIGN_NOALIGNMENT;
1512 aDockingRect.SetSize( aFloatingSize );
1513 rRect = aDockingRect;
1514 return eDockAlign;
1517 // mouse touches inner border -> create new line
1518 if ( eDockAlign == GetAlignment() && pImp->pSplitWin &&
1519 pImp->nLine == pImp->pSplitWin->GetLineCount()-1 && pImp->pSplitWin->GetWindowCount(pImp->nLine) == 1 )
1521 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1522 pImp->nDockLine = pImp->nLine;
1523 pImp->nDockPos = pImp->nPos;
1524 pImp->bNewLine = sal_False;
1526 else
1528 // create new line
1529 pImp->nDockLine = pSplitWin->GetLineCount();
1530 pImp->nDockPos = 0;
1531 pImp->bNewLine = sal_True;
1535 sal_Bool bChanged = pImp->nLine != pImp->nDockLine || pImp->nPos != pImp->nDockPos || eDockAlign != GetAlignment();
1536 if ( !bChanged && !IsFloatingMode() )
1538 // window only sightly moved, no change of any property
1539 rRect.SetSize( pImp->aSplitSize );
1540 rRect.SetPos( aDockingRect.TopLeft() );
1541 return eDockAlign;
1544 // calculate new size and position
1545 Size aSize;
1546 Point aPoint = aDockingRect.TopLeft();
1547 Size aInnerSize = GetInnerRect().GetSize();
1548 if ( eDockAlign == SFX_ALIGN_LEFT || eDockAlign == SFX_ALIGN_RIGHT )
1550 if ( pImp->bNewLine )
1552 // set height to height of free area
1553 aSize.Height() = aInnerSize.Height();
1554 aSize.Width() = pImp->nHorizontalSize;
1555 if ( eDockAlign == SFX_ALIGN_LEFT )
1557 aPoint = aInnerRect.TopLeft();
1559 else
1561 aPoint = aInnerRect.TopRight();
1562 aPoint.X() -= aSize.Width();
1565 else
1567 // get width from splitwindow
1568 aSize.Width() = pSplitWin->GetLineSize(nLine);
1569 aSize.Height() = pImp->aSplitSize.Height();
1572 else
1574 if ( pImp->bNewLine )
1576 // set width to width of free area
1577 aSize.Width() = aInnerSize.Width();
1578 aSize.Height() = pImp->nVerticalSize;
1579 if ( eDockAlign == SFX_ALIGN_TOP )
1581 aPoint = aInnerRect.TopLeft();
1583 else
1585 aPoint = aInnerRect.BottomLeft();
1586 aPoint.Y() -= aSize.Height();
1589 else
1591 // get height from splitwindow
1592 aSize.Height() = pSplitWin->GetLineSize(nLine);
1593 aSize.Width() = pImp->aSplitSize.Width();
1597 aDockingRect.SetSize( aSize );
1598 aDockingRect.SetPos( aPoint );
1600 else
1602 // window can be docked, but outside our splitwindows
1603 // tracking rectangle only needs to be modified if alignment was changed
1604 if ( eDockAlign != pImp->GetDockAlignment() )
1606 switch ( eDockAlign )
1608 case SFX_ALIGN_LEFT:
1609 case SFX_ALIGN_RIGHT:
1610 case SFX_ALIGN_FIRSTLEFT:
1611 aDockingRect.SetPos( aInnerRect.TopLeft() );
1612 aDockingRect.SetSize( aVerticalSize );
1613 break;
1614 case SFX_ALIGN_LASTLEFT:
1615 case SFX_ALIGN_FIRSTRIGHT:
1616 case SFX_ALIGN_LASTRIGHT:
1618 Point aPt( aInnerRect.TopRight() );
1619 aPt.X() -= aDockingRect.GetWidth();
1620 aDockingRect.SetPos( aPt );
1621 aDockingRect.SetSize( aVerticalSize );
1622 break;
1625 case SFX_ALIGN_TOP:
1626 case SFX_ALIGN_BOTTOM:
1627 case SFX_ALIGN_LOWESTTOP:
1628 aDockingRect.SetPos( aInnerRect.TopLeft() );
1629 aDockingRect.SetSize( aHorizontalSize );
1630 break;
1631 case SFX_ALIGN_HIGHESTTOP:
1632 case SFX_ALIGN_LOWESTBOTTOM:
1633 case SFX_ALIGN_HIGHESTBOTTOM:
1635 Point aPt( aInnerRect.BottomLeft() );
1636 aPt.Y() -= aDockingRect.GetHeight();
1637 aDockingRect.SetPos( aPt );
1638 aDockingRect.SetSize( aHorizontalSize );
1639 break;
1641 default:
1642 break;
1647 rRect = aDockingRect;
1648 return eDockAlign;
1651 //-------------------------------------------------------------------------
1653 Size SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign)
1655 /* [Description]
1657 Virtual method of the SfxDockingWindow class. This method determines how
1658 the size of the DockingWindows changes depending on the alignment. The base
1659 implementation uses the floating mode, the size of the marked Floating
1660 Size. For horizontal alignment, the width will be the width of the outer
1661 DockingRectangle, with vertical alignment the height will be the height of
1662 the inner DockingRectangle (resulting from the order in which the SFX child
1663 windows are displayed). The other size is set to the current floating-size,
1664 this could changed by a to intervening derived class. The docking size must
1665 be the same for Left/Right and Top/Bottom.
1669 // Note: if the resizing is also possible in the docked state, then the
1670 // Floating-size does also have to be adjusted?
1672 Size aSize = GetFloatingSize();
1673 switch (eAlign)
1675 case SFX_ALIGN_TOP:
1676 case SFX_ALIGN_BOTTOM:
1677 case SFX_ALIGN_LOWESTTOP:
1678 case SFX_ALIGN_HIGHESTTOP:
1679 case SFX_ALIGN_LOWESTBOTTOM:
1680 case SFX_ALIGN_HIGHESTBOTTOM:
1681 aSize.Width() = aOuterRect.Right() - aOuterRect.Left();
1682 break;
1683 case SFX_ALIGN_LEFT:
1684 case SFX_ALIGN_RIGHT:
1685 case SFX_ALIGN_FIRSTLEFT:
1686 case SFX_ALIGN_LASTLEFT:
1687 case SFX_ALIGN_FIRSTRIGHT:
1688 case SFX_ALIGN_LASTRIGHT:
1689 aSize.Height() = aInnerRect.Bottom() - aInnerRect.Top();
1690 break;
1691 case SFX_ALIGN_NOALIGNMENT:
1692 break;
1693 default:
1694 break;
1697 return aSize;
1700 //-------------------------------------------------------------------------
1702 SfxChildAlignment SfxDockingWindow::CheckAlignment(SfxChildAlignment,
1703 SfxChildAlignment eAlign)
1705 /* [Description]
1707 Virtual method of the SfxDockingWindow class. Here a derived class can
1708 disallow certain alignments. The base implementation does not
1709 prohibit alignment.
1713 return eAlign;
1716 //-------------------------------------------------------------------------
1718 sal_Bool SfxDockingWindow::Close()
1720 /* [Description]
1722 The window is closed when the ChildWindow is destroyed by running the
1723 ChildWindow-slots. If this is method is overridden by a derived class
1724 method, then the SfxDockingDialogWindow: Close() must be called afterwards
1725 if the Close() was not cancelled with "return sal_False".
1728 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
1729 if ( !pMgr )
1730 return sal_True;
1732 SfxBoolItem aValue( pMgr->GetType(), sal_False);
1733 pBindings->GetDispatcher_Impl()->Execute(
1734 pMgr->GetType(), SFX_CALLMODE_RECORD | SFX_CALLMODE_ASYNCHRON, &aValue, 0L );
1735 return sal_True;
1738 //-------------------------------------------------------------------------
1740 void SfxDockingWindow::Paint(const Rectangle& /*rRect*/)
1742 /* [Description]
1744 Returns a boundary line to the docked edge and a frame when the Window is in
1745 a docked state. In this way SVLOOK is considered.
1749 if ( pImp->bSplitable || IsFloatingMode() )
1750 return;
1752 Rectangle aRect = Rectangle(Point(0, 0),
1753 GetOutputSizePixel());
1754 switch (GetAlignment())
1756 case SFX_ALIGN_TOP:
1758 DrawLine(aRect.BottomLeft(), aRect.BottomRight());
1759 aRect.Bottom()--;
1760 break;
1763 case SFX_ALIGN_BOTTOM:
1765 DrawLine(aRect.TopLeft(), aRect.TopRight());
1766 aRect.Top()++;
1767 break;
1770 case SFX_ALIGN_LEFT:
1772 DrawLine(aRect.TopRight(), aRect.BottomRight());
1773 aRect.Right()--;
1774 break;
1777 case SFX_ALIGN_RIGHT:
1779 DrawLine(aRect.TopLeft(), aRect.BottomLeft());
1780 aRect.Left()++;
1781 break;
1783 default:
1784 break;
1787 DecorationView aView( this );
1788 aView.DrawFrame( aRect, FRAME_DRAW_OUT );
1791 //-------------------------------------------------------------------------
1793 void SfxDockingWindow::SetMinOutputSizePixel( const Size& rSize )
1795 /* [Description]
1797 With this method, a minimal OutputSize be can set, that is queried in
1798 the Resizing()-Handler.
1802 pImp->aMinSize = rSize;
1803 DockingWindow::SetMinOutputSizePixel( rSize );
1806 //-------------------------------------------------------------------------
1808 Size SfxDockingWindow::GetMinOutputSizePixel() const
1810 /* [Description]
1812 Set the minimum size which is returned.
1816 return pImp->aMinSize;
1819 //-------------------------------------------------------------------------
1821 long SfxDockingWindow::Notify( NotifyEvent& rEvt )
1823 if ( rEvt.GetType() == EVENT_GETFOCUS )
1825 pBindings->SetActiveFrame( pMgr->GetFrame() );
1827 if ( pImp->pSplitWin )
1828 pImp->pSplitWin->SetActiveWindow_Impl( this );
1829 else
1830 pMgr->Activate_Impl();
1832 Window* pWindow = rEvt.GetWindow();
1833 rtl::OString sHelpId;
1834 while ( sHelpId.isEmpty() && pWindow )
1836 sHelpId = pWindow->GetHelpId();
1837 pWindow = pWindow->GetParent();
1840 if ( !sHelpId.isEmpty() )
1841 SfxHelp::OpenHelpAgent( &pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame(), sHelpId );
1843 // In VCL Notify goes first to the window itself, also call the
1844 // base class, otherwise the parent learns nothing
1845 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1846 DockingWindow::Notify( rEvt );
1847 return sal_True;
1849 else if( rEvt.GetType() == EVENT_KEYINPUT )
1851 // First, allow KeyInput for Dialog functions
1852 if ( !DockingWindow::Notify( rEvt ) && SfxViewShell::Current() )
1853 // then also for valid global accelerators.
1854 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt.GetKeyEvent() );
1855 return sal_True;
1857 else if ( rEvt.GetType() == EVENT_LOSEFOCUS && !HasChildPathFocus() )
1859 pBindings->SetActiveFrame( NULL );
1860 pMgr->Deactivate_Impl();
1863 return DockingWindow::Notify( rEvt );
1867 sal_uInt16 SfxDockingWindow::GetWinBits_Impl() const
1869 sal_uInt16 nBits = 0;
1870 return nBits;
1873 //-------------------------------------------------------------------------
1875 void SfxDockingWindow::SetItemSize_Impl( const Size& rSize )
1877 pImp->aSplitSize = rSize;
1879 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1880 SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
1881 if ( pImp->bSplitable )
1882 eIdent = SFX_CHILDWIN_SPLITWINDOW;
1883 pWorkWin->ConfigChild_Impl( eIdent, SFX_ALIGNDOCKINGWINDOW, pMgr->GetType() );
1886 void SfxDockingWindow::Disappear_Impl()
1888 if ( pImp->pSplitWin && pImp->pSplitWin->IsItemValid( GetType() ) )
1889 pImp->pSplitWin->RemoveWindow(this);
1892 void SfxDockingWindow::Reappear_Impl()
1894 if ( pImp->pSplitWin && !pImp->pSplitWin->IsItemValid( GetType() ) )
1896 pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize );
1900 sal_Bool SfxDockingWindow::IsAutoHide_Impl() const
1902 if ( pImp->pSplitWin )
1903 return !pImp->pSplitWin->IsFadeIn();
1904 else
1905 return sal_False;
1908 void SfxDockingWindow::AutoShow( sal_Bool bShow )
1910 AutoShow_Impl(bShow);
1913 void SfxDockingWindow::AutoShow_Impl( sal_Bool bShow )
1915 if ( pImp->pSplitWin )
1917 if ( bShow )
1918 pImp->pSplitWin->FadeIn();
1919 else
1920 pImp->pSplitWin->FadeOut();
1924 void SfxDockingWindow::FadeIn( sal_Bool /*bFadeIn*/ )
1928 void SfxDockingWindow::StateChanged( StateChangedType nStateChange )
1930 if ( nStateChange == STATE_CHANGE_INITSHOW )
1931 Initialize_Impl();
1933 DockingWindow::StateChanged( nStateChange );
1936 void SfxDockingWindow::Move()
1938 if ( pImp )
1939 pImp->aMoveTimer.Start();
1942 IMPL_LINK_NOARG(SfxDockingWindow, TimerHdl)
1944 pImp->aMoveTimer.Stop();
1945 if ( IsReallyVisible() && IsFloatingMode() )
1947 if( !GetFloatingWindow()->IsRollUp() )
1948 SetFloatingSize( GetOutputSizePixel() );
1949 pImp->aWinState = GetFloatingWindow()->GetWindowState();
1950 SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
1951 if ( pImp->bSplitable )
1952 eIdent = SFX_CHILDWIN_SPLITWINDOW;
1953 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1954 pWorkWin->ConfigChild_Impl( eIdent, SFX_ALIGNDOCKINGWINDOW, pMgr->GetType() );
1956 return 0;
1959 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */