xref: /trunk/main/sfx2/source/dialog/dockwin.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include <svl/eitem.hxx>
32 #include <vcl/decoview.hxx>
33 
34 #include <vcl/svapp.hxx>
35 #include <vcl/timer.hxx>
36 #include <rtl/instance.hxx>
37 #include <toolkit/helper/vclunohelper.hxx>
38 #include <comphelper/processfactory.hxx>
39 
40 #include <sfx2/dockwin.hxx>
41 #include <sfx2/bindings.hxx>
42 #include <sfx2/viewfrm.hxx>
43 #include <sfx2/dispatch.hxx>
44 #include "workwin.hxx"
45 #include "splitwin.hxx"
46 #include <sfx2/viewsh.hxx>
47 #include "sfx2/sfxhelp.hxx"
48 #include <sfx2/objsh.hxx>
49 #include <sfx2/msgpool.hxx>
50 
51 #include <com/sun/star/frame/XController.hpp>
52 #include <com/sun/star/lang/XUnoTunnel.hpp>
53 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
54 #include <com/sun/star/awt/XWindow.hpp>
55 #include <com/sun/star/uno/XComponentContext.hpp>
56 #include <com/sun/star/frame/XModuleManager.hpp>
57 #include <com/sun/star/container/XNameAccess.hpp>
58 
59 #define MAX_TOGGLEAREA_WIDTH        20
60 #define MAX_TOGGLEAREA_HEIGHT       20
61 
62 using namespace ::com::sun::star;
63 
64 // implemented in 'sfx2/source/appl/childwin.cxx'
65 extern sal_Bool GetPosSizeFromString( const String& rStr, Point& rPos, Size& rSize );
66 extern sal_Bool GetSplitSizeFromString( const String& rStr, Size& rSize );
67 
68 // If you want to change the number you also have to:
69 // - Add new slot ids to sfxsids.hrc
70 // - Add new slots to frmslots.sdi
71 // - Add new slot definitions to sfx.sdi
72 static const int NUM_OF_DOCKINGWINDOWS = 10;
73 
74 class SfxTitleDockingWindow;
75 class SfxTitleDockingWindow : public SfxDockingWindow
76 {
77     Window*             m_pWrappedWindow;
78     sal_uInt16              m_nID;
79 
80 public:
81                         SfxTitleDockingWindow(
82                             SfxBindings* pBindings ,
83                             SfxChildWindow* pChildWin ,
84                             Window* pParent ,
85                             WinBits nBits,
86                             sal_uInt16  nID);
87     virtual             ~SfxTitleDockingWindow();
88 
89     Window*             GetWrappedWindow() const { return m_pWrappedWindow; }
90     void                SetWrappedWindow(Window* const pWindow);
91 
92     virtual void        StateChanged( StateChangedType nType );
93     virtual long        Notify( NotifyEvent& rNEvt );
94     virtual void        Resize();
95     virtual void        Resizing( Size& rSize );
96     virtual sal_Bool        Close();
97 };
98 
99 namespace
100 {
101     struct WindowState
102     {
103         ::rtl::OUString sTitle;
104     };
105 }
106 
107 static uno::WeakReference< container::XNameAccess > m_xWindowStateConfiguration;
108 static uno::WeakReference< frame::XModuleManager >  m_xModuleManager;
109 
110 static bool lcl_getWindowState( const uno::Reference< container::XNameAccess >& xWindowStateMgr, const ::rtl::OUString& rResourceURL, WindowState& rWindowState )
111 {
112     bool bResult = false;
113 
114     try
115     {
116         uno::Any a;
117         uno::Sequence< beans::PropertyValue > aWindowState;
118         a = xWindowStateMgr->getByName( rResourceURL );
119         if ( a >>= aWindowState )
120         {
121             for ( sal_Int32 n = 0; n < aWindowState.getLength(); n++ )
122             {
123                 if ( aWindowState[n].Name.equalsAscii( "UIName" ))
124                 {
125                     aWindowState[n].Value >>= rWindowState.sTitle;
126                 }
127             }
128         }
129 
130         bResult = true;
131     }
132     catch ( container::NoSuchElementException& )
133     {
134         bResult = false;
135     }
136 
137     return bResult;
138 }
139 
140 SfxDockingWrapper::SfxDockingWrapper( Window* pParentWnd ,
141                                       sal_uInt16 nId ,
142                                       SfxBindings* pBindings ,
143                                       SfxChildWinInfo* pInfo )
144                     : SfxChildWindow( pParentWnd , nId )
145 {
146     uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
147     const rtl::OUString aDockWindowResourceURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/dockingwindow/" ));
148 
149     SfxTitleDockingWindow* pTitleDockWindow = new SfxTitleDockingWindow( pBindings, this, pParentWnd,
150         WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE, nId);
151     pWindow = pTitleDockWindow;
152     eChildAlignment = SFX_ALIGN_NOALIGNMENT;
153 
154     // Use factory manager to retrieve XWindow factory. That can be used to instanciate
155     // the real window factory.
156     uno::Reference< lang::XSingleComponentFactory > xFactoryMgr(
157             xServiceManager->createInstance(
158                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
159                     "com.sun.star.ui.WindowContentFactoryManager"))),
160                 uno::UNO_QUERY );
161 
162     if (xFactoryMgr.is())
163     {
164         SfxDispatcher* pDispatcher = pBindings->GetDispatcher();
165         uno::Reference< frame::XFrame > xFrame( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY );
166         uno::Sequence< uno::Any > aArgs(2);
167         beans::PropertyValue      aPropValue;
168         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
169         aPropValue.Value = uno::makeAny( xFrame );
170         aArgs[0] <<= aPropValue;
171         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ));
172 
173         // create a resource URL from the nId provided by the sfx2
174         ::rtl::OUString aResourceURL( aDockWindowResourceURL );
175         aResourceURL += ::rtl::OUString::valueOf(sal_Int32(nId));
176         aPropValue.Value = uno::makeAny( aResourceURL );
177         aArgs[1] <<= aPropValue;
178 
179         uno::Reference< awt::XWindow > xWindow;
180         try
181         {
182             uno::Reference< beans::XPropertySet >    xProps( xServiceManager, uno::UNO_QUERY );
183             uno::Reference< uno::XComponentContext > xContext;
184 
185             if ( xProps.is() )
186                 xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
187             if ( xContext.is() )
188             {
189                 xWindow = uno::Reference< awt::XWindow>(
190                             xFactoryMgr->createInstanceWithArgumentsAndContext( aArgs, xContext ),
191                           uno::UNO_QUERY );
192             }
193 
194             uno::Reference< frame::XModuleManager > xModuleManager( m_xModuleManager );
195             if ( !xModuleManager.is() )
196             {
197                 xModuleManager = uno::Reference< frame::XModuleManager >(
198                                     xServiceManager->createInstance(
199                                         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ))),
200                                     uno::UNO_QUERY );
201                 m_xModuleManager = xModuleManager;
202             }
203 
204             uno::Reference< container::XNameAccess > xWindowStateConfiguration( m_xWindowStateConfiguration );
205             if ( !xWindowStateConfiguration.is() )
206             {
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;
212             }
213 
214             ::rtl::OUString sModuleIdentifier = xModuleManager->identify( xFrame );
215 
216             uno::Reference< container::XNameAccess > xModuleWindowState(
217                                                         xWindowStateConfiguration->getByName( sModuleIdentifier ),
218                                                         uno::UNO_QUERY );
219             if ( xModuleWindowState.is() )
220             {
221                 WindowState aDockWinState;
222                 if ( lcl_getWindowState( xModuleWindowState, aResourceURL, aDockWinState ))
223                     pTitleDockWindow->SetText( aDockWinState.sTitle );
224             }
225         }
226         catch ( beans::UnknownPropertyException& )
227         {
228         }
229         catch ( uno::RuntimeException& )
230         {
231         }
232         catch ( uno::Exception& )
233         {
234         }
235 
236         Window* pContentWindow = VCLUnoHelper::GetWindow(xWindow);
237         if ( pContentWindow )
238             pContentWindow->SetStyle( pContentWindow->GetStyle() | WB_DIALOGCONTROL | WB_CHILDDLGCTRL );
239         pTitleDockWindow->SetWrappedWindow(pContentWindow);
240     }
241 
242     pWindow->SetOutputSizePixel( Size( 270, 240 ) );
243 
244     ( ( SfxDockingWindow* ) pWindow )->Initialize( pInfo );
245     SetHideNotDelete( sal_True );
246 }
247 
248 SfxChildWindow*  SfxDockingWrapper::CreateImpl(
249 Window *pParent, sal_uInt16 nId, SfxBindings *pBindings, SfxChildWinInfo* pInfo )
250 {
251     SfxChildWindow *pWin = new SfxDockingWrapper(pParent, nId, pBindings, pInfo); return pWin;
252 }
253 
254 sal_uInt16 SfxDockingWrapper::GetChildWindowId ()
255 {
256     DBG_ASSERT( false, "This method shouldn't be called!" );
257     return 0;
258 }
259 
260 void SfxDockingWrapper::RegisterChildWindow (sal_Bool bVis, SfxModule *pMod, sal_uInt16 nFlags)
261 {
262     // pre-register a couple of docking windows
263     for (int i=0; i < NUM_OF_DOCKINGWINDOWS; i++ )
264     {
265         sal_uInt16 nID = sal_uInt16(SID_DOCKWIN_START+i);
266         SfxChildWinFactory *pFact = new SfxChildWinFactory( SfxDockingWrapper::CreateImpl, nID, 0xffff );
267         pFact->aInfo.nFlags |= nFlags;
268         pFact->aInfo.bVisible = bVis;
269         SfxChildWindow::RegisterChildWindow(pMod, pFact);
270     }
271 }
272 
273 SfxChildWinInfo  SfxDockingWrapper::GetInfo() const
274 {
275     SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
276     ((SfxDockingWindow*)GetWindow())->FillInfo( aInfo );
277     return aInfo;
278 };
279 
280 SfxTitleDockingWindow::SfxTitleDockingWindow( SfxBindings* pBind ,
281                                               SfxChildWindow* pChildWin ,
282                                               Window* pParent ,
283                                               WinBits nBits,
284                                               sal_uInt16  nID ) :
285                           SfxDockingWindow( pBind ,
286                                             pChildWin ,
287                                             pParent ,
288                                             nBits ),
289                           m_pWrappedWindow(0),
290                           m_nID(nID)
291 {
292 }
293 
294 SfxTitleDockingWindow::~SfxTitleDockingWindow()
295 {
296     delete m_pWrappedWindow;
297 }
298 
299 void SfxTitleDockingWindow::SetWrappedWindow( Window* const pWindow )
300 {
301     m_pWrappedWindow = pWindow;
302     if (m_pWrappedWindow)
303     {
304         m_pWrappedWindow->SetParent(this);
305         m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() );
306         m_pWrappedWindow->Show();
307     }
308 }
309 
310 long SfxTitleDockingWindow::Notify( NotifyEvent& rNEvt )
311 {
312     return SfxDockingWindow::Notify( rNEvt );
313 }
314 
315 void SfxTitleDockingWindow::StateChanged( StateChangedType nType )
316 {
317     if ( nType == STATE_CHANGE_INITSHOW )
318     {
319         Window* pWindow = GetWrappedWindow();
320         if ( pWindow )
321         {
322             pWindow->SetSizePixel( GetOutputSizePixel() );
323             pWindow->Show();
324         }
325     }
326 
327     SfxDockingWindow::StateChanged(nType);
328 }
329 
330 void SfxTitleDockingWindow::Resize()
331 {
332     SfxDockingWindow::Resize();
333     if (m_pWrappedWindow)
334         m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() );
335 }
336 
337 void SfxTitleDockingWindow::Resizing( Size &rSize )
338 {
339     SfxDockingWindow::Resizing( rSize );
340     if (m_pWrappedWindow)
341         m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() );
342 }
343 
344 sal_Bool SfxTitleDockingWindow::Close()
345 {
346     return SfxDockingWindow::Close();
347 }
348 
349 namespace
350 {
351     struct ChildrenRegisteredMap : public rtl::Static< bool, ChildrenRegisteredMap > {};
352 }
353 
354 static bool lcl_checkDockingWindowID( sal_uInt16 nID )
355 {
356     if (nID < SID_DOCKWIN_START || nID >= sal_uInt16(SID_DOCKWIN_START+NUM_OF_DOCKINGWINDOWS))
357         return false;
358     else
359         return true;
360 }
361 
362 static SfxWorkWindow* lcl_getWorkWindowFromXFrame( const uno::Reference< frame::XFrame >& rFrame )
363 {
364     // We need to find the corresponding SfxFrame of our XFrame
365     SfxFrame* pFrame  = SfxFrame::GetFirst();
366     SfxFrame* pXFrame = 0;
367     while ( pFrame )
368     {
369         uno::Reference< frame::XFrame > xViewShellFrame( pFrame->GetFrameInterface() );
370         if ( xViewShellFrame == rFrame )
371         {
372             pXFrame = pFrame;
373             break;
374         }
375         else
376             pFrame = SfxFrame::GetNext( *pFrame );
377     }
378 
379     // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
380     if ( pXFrame )
381         return pXFrame->GetWorkWindow_Impl();
382     else
383         return NULL;
384 }
385 
386 /*
387     Factory function used by the framework layout manager to "create" a docking window with a special name.
388     The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
389     in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
390 */
391 void SAL_CALL SfxDockingWindowFactory( const uno::Reference< frame::XFrame >& rFrame, const rtl::OUString& rDockingWindowName )
392 {
393     ::vos::OGuard aGuard( Application::GetSolarMutex() );
394     sal_uInt16 nID = sal_uInt16(rDockingWindowName.toInt32());
395 
396     // Check the range of the provided ID otherwise nothing will happen
397     if ( lcl_checkDockingWindowID( nID ))
398     {
399         SfxWorkWindow* pWorkWindow = lcl_getWorkWindowFromXFrame( rFrame );
400         if ( pWorkWindow )
401         {
402             SfxChildWindow* pChildWindow = pWorkWindow->GetChildWindow_Impl(nID);
403             if ( !pChildWindow )
404             {
405                 // Register window at the workwindow child window list
406                 pWorkWindow->SetChildWindow_Impl( nID, true, false );
407             }
408         }
409     }
410 }
411 
412 /*
413     Function used by the framework layout manager to determine the visibility state of a docking window with
414     a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
415     range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
416 */
417 bool SAL_CALL IsDockingWindowVisible( const uno::Reference< frame::XFrame >& rFrame, const rtl::OUString& rDockingWindowName )
418 {
419     ::vos::OGuard aGuard( Application::GetSolarMutex() );
420 
421     sal_uInt16 nID = sal_uInt16(rDockingWindowName.toInt32());
422 
423     // Check the range of the provided ID otherwise nothing will happen
424     if ( lcl_checkDockingWindowID( nID ))
425     {
426         SfxWorkWindow* pWorkWindow = lcl_getWorkWindowFromXFrame( rFrame );
427         if ( pWorkWindow )
428         {
429             SfxChildWindow* pChildWindow = pWorkWindow->GetChildWindow_Impl(nID);
430             if ( pChildWindow )
431                 return true;
432         }
433     }
434 
435     return false;
436 }
437 
438 class SfxDockingWindow_Impl
439 {
440 friend class SfxDockingWindow;
441 
442     SfxChildAlignment   eLastAlignment;
443     SfxChildAlignment   eDockAlignment;
444     sal_Bool                bConstructed;
445     Size                aMinSize;
446     SfxSplitWindow*     pSplitWin;
447     sal_Bool                bSplitable;
448 //  sal_Bool                bAutoHide;
449     Timer               aMoveTimer;
450 
451     // Folgende members sind nur in der Zeit von StartDocking bis EndDocking
452     // g"ultig:
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     ByteString          aWinState;
464 
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; }
473 };
474 
475 //-------------------------------------------------------------------------
476 
477 void SfxDockingWindow::Resize()
478 
479 /*  [Beschreibung]
480 
481     Diese virtuelle Methode der Klasse DockingWindow merkt sich ggf. eine
482     ver"anderte FloatingSize.
483     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
484     auch SfxDockingWindow::Resize() gerufen werden.
485 */
486 {
487     DockingWindow::Resize();
488     Invalidate();
489     if ( pImp->bConstructed && pMgr )
490     {
491         if ( IsFloatingMode() )
492         {
493             // start timer for saving window status information
494             pImp->aMoveTimer.Start();
495         }
496         else
497         {
498             Size aSize( GetSizePixel() );
499             switch ( pImp->GetDockAlignment() )
500             {
501                 case SFX_ALIGN_LEFT:
502                 case SFX_ALIGN_FIRSTLEFT:
503                 case SFX_ALIGN_LASTLEFT:
504                 case SFX_ALIGN_RIGHT:
505                 case SFX_ALIGN_FIRSTRIGHT:
506                 case SFX_ALIGN_LASTRIGHT:
507                     pImp->nHorizontalSize = aSize.Width();
508                     pImp->aSplitSize = aSize;
509                     break;
510                 case SFX_ALIGN_TOP:
511                 case SFX_ALIGN_LOWESTTOP:
512                 case SFX_ALIGN_HIGHESTTOP:
513                 case SFX_ALIGN_BOTTOM:
514                 case SFX_ALIGN_HIGHESTBOTTOM:
515                 case SFX_ALIGN_LOWESTBOTTOM:
516                     pImp->nVerticalSize = aSize.Height();
517                     pImp->aSplitSize = aSize;
518                     break;
519                 default:
520                     break;
521             }
522         }
523     }
524 }
525 
526 //-------------------------------------------------------------------------
527 
528 sal_Bool SfxDockingWindow::PrepareToggleFloatingMode()
529 
530 /*  [Beschreibung]
531 
532     Diese virtuelle Methode der Klasse DockingWindow erm"oglicht ein Eingreifen
533     in das Umschalten des floating mode.
534     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
535     danach SfxDockingWindow::PrepareToggleFloatingMode() gerufen werden,
536     wenn nicht FALSE zur"uckgegeben wird.
537 */
538 
539 {
540     if (!pImp->bConstructed)
541         return sal_True;
542 
543     if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr )
544         return sal_False;
545 
546     if ( pImp->bDockingPrevented )
547         return sal_False;
548 
549     if (!IsFloatingMode())
550     {
551         // Testen, ob FloatingMode erlaubt ist
552         if ( CheckAlignment(GetAlignment(),SFX_ALIGN_NOALIGNMENT) != SFX_ALIGN_NOALIGNMENT )
553             return sal_False;
554 
555         if ( pImp->pSplitWin )
556         {
557             // Das DockingWindow sitzt in einem SplitWindow und wird abgerissen
558             pImp->pSplitWin->RemoveWindow(this/*, sal_False*/);
559             pImp->pSplitWin = 0;
560         }
561     }
562     else if ( pMgr )
563     {
564         pImp->aWinState = GetFloatingWindow()->GetWindowState();
565 
566         // Testen, ob es erlaubt ist, anzudocken
567         if (CheckAlignment(GetAlignment(),pImp->GetLastAlignment()) == SFX_ALIGN_NOALIGNMENT)
568             return sal_False;
569 
570         // Testen, ob das Workwindow gerade ein Andocken erlaubt
571         SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
572         if ( !pWorkWin->IsDockingAllowed() || !pWorkWin->IsInternalDockingAllowed() )
573             return sal_False;
574     }
575 
576     return sal_True;
577 }
578 
579 //-------------------------------------------------------------------------
580 
581 void SfxDockingWindow::ToggleFloatingMode()
582 
583 /*  [Beschreibung]
584 
585     Diese virtuelle Methode der Klasse DockingWindow setzt die internen
586     Daten des SfxDockingWindow und sorgt f"ur korrektes Alignment am
587     parent window.
588     Durch PrepareToggleFloatMode und Initialize ist sichergestellt, da\s
589     pImp->GetLastAlignment() immer eine erlaubtes Alignment liefert.
590     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
591     zuerst SfxDockingWindow::ToggleFloatingMode() gerufen werden.
592 */
593 {
594     if ( !pImp->bConstructed || !pMgr )
595         return;                 // Kein Handler-Aufruf
596 
597     // Altes Alignment merken und dann umschalten.
598     // Sv hat jetzt schon umgeschaltet, aber Alignment am SfxDockingWindow
599     // ist noch das alte!
600     // Was war ich bisher ?
601     SfxChildAlignment eLastAlign = GetAlignment();
602 
603     SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
604     SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
605     if ( pImp->bSplitable )
606         eIdent = SFX_CHILDWIN_SPLITWINDOW;
607 
608     if (IsFloatingMode())
609     {
610         SetAlignment(SFX_ALIGN_NOALIGNMENT);
611         if ( pImp->aWinState.Len() )
612             GetFloatingWindow()->SetWindowState( pImp->aWinState );
613         else
614             GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
615 /*
616         if ( pImp->bSplitable && !pImp->bEndDocked )
617             // Wenn das Fenster vorher in einem SplitWindow lag, kommt von
618             // Sv kein Show
619             Show();
620 */
621     }
622     else
623     {
624         if (pImp->GetDockAlignment() == eLastAlign)
625         {
626             // Wenn ToggleFloatingMode aufgerufen wurde, das DockAlignment
627             // aber noch unver"andert ist, mu\s das ein Toggeln durch DClick
628             // gewesen sein, also LastAlignment verwenden
629             SetAlignment (pImp->GetLastAlignment());
630             if ( !pImp->bSplitable )
631                 SetSizePixel( CalcDockingSize(GetAlignment()) );
632         }
633         else
634         {
635             // Toggeln wurde durch Draggen ausgel"ost
636             pImp->nLine = pImp->nDockLine;
637             pImp->nPos = pImp->nDockPos;
638             SetAlignment (pImp->GetDockAlignment());
639         }
640 
641         if ( pImp->bSplitable )
642         {
643             // Das DockingWindow kommt jetzt in ein SplitWindow
644             pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(GetAlignment());
645 
646             // Das LastAlignment ist jetzt immer noch das zuletzt angedockte
647             SfxSplitWindow *pSplit = pWorkWin->GetSplitWindow_Impl(pImp->GetLastAlignment());
648 
649             DBG_ASSERT( pSplit, "LastAlignment kann nicht stimmen!" );
650             if ( pSplit && pSplit != pImp->pSplitWin )
651                 pSplit->ReleaseWindow_Impl(this);
652             if ( pImp->GetDockAlignment() == eLastAlign )
653                 pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize );
654             else
655                 pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize, pImp->nLine, pImp->nPos, pImp->bNewLine );
656             if ( !pImp->pSplitWin->IsFadeIn() )
657                 pImp->pSplitWin->FadeIn();
658         }
659     }
660 
661     // altes Alignment festhalten f"ur n"achstes Togglen; erst jetzt setzen
662     // wg. Abmelden beim SplitWindow!
663     pImp->SetLastAlignment(eLastAlign);
664 
665     // DockAlignment zur"ucksetzen, falls noch EndDocking gerufen wird
666     pImp->SetDockAlignment(GetAlignment());
667 
668     // SfxChildWindow korrekt andocken bzw. entdocken
669     if ( pMgr )
670         pWorkWin->ConfigChild_Impl( eIdent, SFX_TOGGLEFLOATMODE, pMgr->GetType() );
671 }
672 
673 //-------------------------------------------------------------------------
674 
675 void SfxDockingWindow::StartDocking()
676 
677 /*  [Beschreibung]
678 
679     Diese virtuelle Methode der Klasse DockingWindow holt vom parent window
680     das innere und "au\sere docking rectangle.
681     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
682     am Ende SfxDockingWindow::StartDocking() gerufen werden.
683 */
684 {
685     if ( !pImp->bConstructed || !pMgr )
686         return;
687     SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
688     if ( pImp->bSplitable )
689         eIdent = SFX_CHILDWIN_SPLITWINDOW;
690     SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
691     pWorkWin->ConfigChild_Impl( eIdent, SFX_SETDOCKINGRECTS, pMgr->GetType() );
692     pImp->SetDockAlignment(GetAlignment());
693 
694     if ( pImp->pSplitWin )
695     {
696         // Die aktuellen Docking-Daten besorgen
697         pImp->pSplitWin->GetWindowPos(this, pImp->nLine, pImp->nPos);
698         pImp->nDockLine = pImp->nLine;
699         pImp->nDockPos = pImp->nPos;
700         pImp->bNewLine = sal_False;
701     }
702 }
703 
704 //-------------------------------------------------------------------------
705 
706 sal_Bool SfxDockingWindow::Docking( const Point& rPos, Rectangle& rRect )
707 
708 /*  [Beschreibung]
709 
710     Diese virtuelle Methode der Klasse DockingWindow berechnet das aktuelle
711     tracking rectangle. Dazu benutzt sie die Methode CalcAlignment(rPos,rRect),
712     deren Verhalten von abgeleiteten Klassen beeinflu\st werden kann (s.u.).
713     Diese Methode sollte nach M"oglichkeit nicht "uberschrieben werden.
714 */
715 {
716     if ( Application::IsInModalMode() )
717         return sal_True;
718 
719     if ( !pImp->bConstructed || !pMgr )
720     {
721         rRect.SetSize( Size() );
722         return IsFloatingMode();
723     }
724 
725     SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
726     if ( pImp->bDockingPrevented || !pWorkWin->IsInternalDockingAllowed() )
727         return sal_False;
728 
729     sal_Bool bFloatMode = sal_False;
730 
731     if ( GetOuterRect().IsInside( rPos ) && !IsDockingPrevented() )
732     {
733         // Maus innerhalb OuterRect : Alignment und Rectangle berechnen
734         SfxChildAlignment eAlign = CalcAlignment(rPos, rRect);
735         if (eAlign == SFX_ALIGN_NOALIGNMENT)
736             bFloatMode = sal_True;
737         pImp->SetDockAlignment(eAlign);
738     }
739     else
740     {
741         // Maus nicht innerhalb OuterRect : muss FloatingWindow sein
742         // Ist das erlaubt ?
743         if (CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT) != SFX_ALIGN_NOALIGNMENT)
744             return sal_False;
745         bFloatMode = sal_True;
746         if ( SFX_ALIGN_NOALIGNMENT != pImp->GetDockAlignment() )
747         {
748             // wg. SV-Bug darf rRect nur ver"andert werden, wenn sich das
749             // Alignment "andert !
750             pImp->SetDockAlignment(SFX_ALIGN_NOALIGNMENT);
751             rRect.SetSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT));
752         }
753     }
754 
755     if ( !pImp->bSplitable )
756     {
757         // Bei individuell angedocktem Window wird die Position durch das
758         // Alignment und die docking rects festgelegt.
759         Size aSize = rRect.GetSize();
760         Point aPos;
761 
762         switch ( pImp->GetDockAlignment() )
763         {
764             case SFX_ALIGN_LEFT:
765             case SFX_ALIGN_FIRSTLEFT:
766             case SFX_ALIGN_LASTLEFT:
767                 aPos = aInnerRect.TopLeft();
768                 if ( pImp->GetDockAlignment() == GetAlignment() )
769                     aPos.X() -= aSize.Width();
770                 break;
771 
772             case SFX_ALIGN_TOP:
773             case SFX_ALIGN_LOWESTTOP:
774             case SFX_ALIGN_HIGHESTTOP:
775                 aPos = Point(aOuterRect.Left(), aInnerRect.Top());
776                 if ( pImp->GetDockAlignment() == GetAlignment() )
777                     aPos.Y() -= aSize.Height();
778                 break;
779 
780             case SFX_ALIGN_RIGHT:
781             case SFX_ALIGN_FIRSTRIGHT:
782             case SFX_ALIGN_LASTRIGHT:
783                 aPos = Point(aInnerRect.Right() - rRect.GetSize().Width(),
784                             aInnerRect.Top());
785                 if ( pImp->GetDockAlignment() == GetAlignment() )
786                     aPos.X() += aSize.Width();
787                 break;
788 
789             case SFX_ALIGN_BOTTOM:
790             case SFX_ALIGN_HIGHESTBOTTOM:
791             case SFX_ALIGN_LOWESTBOTTOM:
792                 aPos = Point(aOuterRect.Left(),
793                         aInnerRect.Bottom() - rRect.GetSize().Height());
794                 if ( pImp->GetDockAlignment() == GetAlignment() )
795                     aPos.Y() += aSize.Height();
796                 break;
797                      default:
798                          break;
799         }
800 
801         rRect.SetPos(aPos);
802     }
803 
804     return bFloatMode;
805 }
806 
807 //-------------------------------------------------------------------------
808 
809 void SfxDockingWindow::EndDocking( const Rectangle& rRect, sal_Bool bFloatMode )
810 
811 /*  [Beschreibung]
812 
813     Diese virtuelle Methode der Klasse DockingWindow sorgt f"ur das korrekte
814     Alignment am parent window.
815     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
816     zuerst SfxDockingWindow::EndDocking() gerufen werden.
817 */
818 {
819     if ( !pImp->bConstructed || IsDockingCanceled() || !pMgr )
820         return;
821 
822     SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
823     sal_Bool bReArrange = sal_False;
824     SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
825     if ( pImp->bSplitable )
826     {
827         eIdent = SFX_CHILDWIN_SPLITWINDOW;
828 
829         // Wenn sich das Alignment "andert und das Fenster befindet sich
830         // im angedockten Zustand in einem SplitWindow, mu\s umgemeldet werden
831         // Wenn neu angedockt wird, machen PrepareToggleFloatingMode()
832         // und ToggleFloatingMode() das Ummelden.
833         if ( !bFloatMode )
834             bReArrange = sal_True;
835     }
836 
837     if ( bReArrange )
838     {
839         if ( GetAlignment() != pImp->GetDockAlignment() )
840         {
841             // Vor dem Show() mu\s das Ummelden passiert sein, daher kann nicht
842             // die Basisklasse gerufen werden
843             if ( IsFloatingMode() || !pImp->bSplitable )
844                 Show( sal_False, SHOW_NOFOCUSCHANGE );
845 
846             // Die Gr"o\se f"urs Toggeln setzen
847             pImp->aSplitSize = rRect.GetSize();
848             if ( IsFloatingMode() )
849             {
850                 SetFloatingMode( bFloatMode );
851                 if ( IsFloatingMode() || !pImp->bSplitable )
852                     Show( sal_True, SHOW_NOFOCUSCHANGE );
853             }
854             else
855             {
856                 pImp->pSplitWin->RemoveWindow(this,sal_False);
857                 pImp->nLine = pImp->nDockLine;
858                 pImp->nPos = pImp->nDockPos;
859                 pImp->pSplitWin->ReleaseWindow_Impl(this);
860                 pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(pImp->GetDockAlignment());
861                 pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize, pImp->nDockLine, pImp->nDockPos, pImp->bNewLine );
862                 if ( !pImp->pSplitWin->IsFadeIn() )
863                     pImp->pSplitWin->FadeIn();
864             }
865         }
866         else if ( pImp->nLine != pImp->nDockLine || pImp->nPos != pImp->nDockPos || pImp->bNewLine )
867         {
868             // Ich wurde innerhalb meines Splitwindows verschoben.
869             if ( pImp->nLine != pImp->nDockLine )
870                 pImp->aSplitSize = rRect.GetSize();
871             pImp->pSplitWin->MoveWindow( this, pImp->aSplitSize, pImp->nDockLine, pImp->nDockPos, pImp->bNewLine );
872         }
873     }
874     else
875     {
876         pImp->bEndDocked = sal_True;
877         DockingWindow::EndDocking(rRect, bFloatMode);
878         pImp->bEndDocked = sal_False;
879     }
880 
881     SetAlignment( IsFloatingMode() ? SFX_ALIGN_NOALIGNMENT : pImp->GetDockAlignment() );
882 }
883 
884 //-------------------------------------------------------------------------
885 
886 void SfxDockingWindow::Resizing( Size& /*rSize*/ )
887 
888 /*  [Beschreibung]
889 
890     Virtuelle Methode der Klasse DockingWindow.
891     Hier kann das interaktive Umgr"o\sern im FloatingMode beeinflu\t werden,
892     z.B. indem nur diskrete Werte f"ur Breite und/oder H"ohe zugelassen werden.
893     Die Basisimplementation verhindert, da\s die OutputSize kleiner wird als
894     eine mit SetMinOutputSizePixel() gesetzte Gr"o\se.
895 */
896 
897 {
898 /*
899     if(rSize.Width()   < pImp->aMinSize.Width())
900         rSize.Width()  = pImp->aMinSize.Width();
901     if(rSize.Height()  < pImp->aMinSize.Height())
902         rSize.Height() = pImp->aMinSize.Height();
903 */
904 }
905 
906 //-------------------------------------------------------------------------
907 
908 SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW,
909     Window* pParent, WinBits nWinBits) :
910     DockingWindow (pParent, nWinBits),
911     pBindings(pBindinx),
912     pMgr(pCW),
913     pImp(NULL)
914 
915 /*  [Beschreibung]
916 
917     ctor der Klasse SfxDockingWindow. Es wird ein SfxChildWindow ben"otigt,
918     da das Andocken im Sfx "uber SfxChildWindows realisiert wird.
919 */
920 
921 {
922     if ( GetHelpId().getLength() )
923     {
924         SetUniqueId( GetHelpId() );
925         SetHelpId("");
926     }
927     else
928     {
929         SfxViewFrame* pViewFrame = pBindings->GetDispatcher()->GetFrame();
930         SfxSlotPool* pSlotPool = pViewFrame->GetObjectShell()->GetModule()->GetSlotPool();
931         const SfxSlot* pSlot = pSlotPool->GetSlot( pCW->GetType() );
932         if ( pSlot )
933         {
934             rtl::OString aCmd("SFXDOCKINGWINDOW_");
935             aCmd += pSlot->GetUnoName();
936             SetUniqueId( aCmd );
937         }
938     }
939 
940     pImp = new SfxDockingWindow_Impl;
941     pImp->bConstructed = sal_False;
942     pImp->pSplitWin = 0;
943     pImp->bEndDocked = sal_False;
944     pImp->bDockingPrevented = sal_False;
945 
946     pImp->bSplitable = sal_True;
947 //  pImp->bAutoHide = sal_False;
948 
949     // Zun"achst auf Defaults setzen; das Alignment wird in der Subklasse gesetzt
950     pImp->nLine = pImp->nDockLine = 0;
951     pImp->nPos  = pImp->nDockPos = 0;
952     pImp->bNewLine = sal_False;
953     pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT);
954     pImp->aMoveTimer.SetTimeout(50);
955     pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxDockingWindow,TimerHdl));
956 
957 //  DBG_ASSERT(pMgr,"DockingWindow erfordert ein SfxChildWindow!");
958 }
959 
960 //-------------------------------------------------------------------------
961 
962 SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW,
963     Window* pParent, const ResId& rResId) :
964     DockingWindow(pParent, rResId),
965     pBindings(pBindinx),
966     pMgr(pCW),
967     pImp(NULL)
968 
969 /*  [Beschreibung]
970 
971     ctor der Klasse SfxDockingWindow. Es wird ein SfxChildWindow ben"otigt,
972     da das Andocken im Sfx "uber SfxChildWindows realisiert wird.
973 */
974 
975 {
976     if ( GetHelpId().getLength() )
977     {
978         SetUniqueId( GetHelpId() );
979         SetHelpId("");
980     }
981     else
982     {
983         SfxViewFrame* pViewFrame = pBindings->GetDispatcher()->GetFrame();
984         SfxSlotPool* pSlotPool = pViewFrame->GetObjectShell()->GetModule()->GetSlotPool();
985         const SfxSlot* pSlot = pSlotPool->GetSlot( pCW->GetType() );
986         if ( pSlot )
987         {
988             rtl::OString aCmd("SFXDOCKINGWINDOW_");
989             aCmd += pSlot->GetUnoName();
990             SetUniqueId( aCmd );
991         }
992     }
993 
994     pImp = new SfxDockingWindow_Impl;
995     pImp->bConstructed = sal_False;
996     pImp->pSplitWin = 0;
997     pImp->bEndDocked = sal_False;
998     pImp->bDockingPrevented = sal_False;
999 
1000     pImp->bSplitable = sal_True;
1001 //  pImp->bAutoHide = sal_False;
1002 
1003     // Zun"achst auf Defaults setzen; das Alignment wird in der Subklasse gesetzt
1004     pImp->nLine = pImp->nDockLine = 0;
1005     pImp->nPos  = pImp->nDockPos = 0;
1006     pImp->bNewLine = sal_False;
1007     pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT);
1008     pImp->aMoveTimer.SetTimeout(50);
1009     pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxDockingWindow,TimerHdl));
1010 
1011 //  DBG_ASSERT(pMgr,"DockingWindow erfordert ein SfxChildWindow!");
1012 }
1013 
1014 //-------------------------------------------------------------------------
1015 
1016 void SfxDockingWindow::Initialize(SfxChildWinInfo *pInfo)
1017 /*  [Beschreibung]
1018 
1019     Initialisierung der Klasse SfxDockingWindow "uber ein SfxChildWinInfo.
1020     Die Initialisierung erfolgt erst in einem 2.Schritt nach dem ctor und sollte
1021     vom ctor der abgeleiteten Klasse oder vom ctor des SfxChildWindows
1022     aufgerufen werden.
1023 */
1024 {
1025     if ( !pMgr )
1026     {
1027         // Bugfix #39771
1028         pImp->SetDockAlignment( SFX_ALIGN_NOALIGNMENT );
1029         pImp->bConstructed = sal_True;
1030         return;
1031     }
1032 
1033     if ( pInfo->nFlags & SFX_CHILDWIN_FORCEDOCK )
1034         pImp->bDockingPrevented = sal_True;
1035 
1036     pImp->aSplitSize = GetOutputSizePixel();
1037     if ( !GetFloatingSize().Width() )
1038     {
1039         Size aMinSize( GetMinOutputSizePixel() );
1040         SetFloatingSize( pImp->aSplitSize );
1041         if ( pImp->aSplitSize.Width() < aMinSize.Width() )
1042             pImp->aSplitSize.Width() = aMinSize.Width();
1043         if ( pImp->aSplitSize.Height() < aMinSize.Height() )
1044             pImp->aSplitSize.Height() = aMinSize.Height();
1045     }
1046 
1047     sal_Bool bVertHorzRead( sal_False );
1048     if ( pInfo->aExtraString.Len() )
1049     {
1050         // get information about alignment, split size and position in SplitWindow
1051         String aStr;
1052         sal_uInt16 nPos = pInfo->aExtraString.SearchAscii("AL:");
1053         if ( nPos != STRING_NOTFOUND )
1054         {
1055             // alignment information
1056             sal_uInt16 n1 = pInfo->aExtraString.Search('(', nPos);
1057             if ( n1 != STRING_NOTFOUND )
1058             {
1059                 sal_uInt16 n2 = pInfo->aExtraString.Search(')', n1);
1060                 if ( n2 != STRING_NOTFOUND )
1061                 {
1062                     // extract alignment information from extrastring
1063                     aStr = pInfo->aExtraString.Copy(nPos, n2 - nPos + 1);
1064                     pInfo->aExtraString.Erase(nPos, n2 - nPos + 1);
1065                     aStr.Erase(nPos, n1-nPos+1);
1066                 }
1067             }
1068         }
1069 
1070         if ( aStr.Len() )
1071         {
1072             // accept window state only if alignment is also set
1073             pImp->aWinState = pInfo->aWinState;
1074 
1075             // check for valid alignment
1076             SfxChildAlignment eLocalAlignment = (SfxChildAlignment) (sal_uInt16) aStr.ToInt32();
1077             if ( pImp->bDockingPrevented )
1078                 // docking prevented, ignore old configuration and take alignment from default
1079                 aStr.Erase();
1080             else
1081                 SetAlignment( eLocalAlignment );
1082 
1083             SfxChildAlignment eAlign = CheckAlignment(GetAlignment(),GetAlignment());
1084             if ( eAlign != GetAlignment() )
1085             {
1086                 DBG_ERROR("Invalid Alignment!");
1087                 SetAlignment( eAlign );
1088                 aStr.Erase();
1089             }
1090 
1091             // get last alignment (for toggeling)
1092             nPos = aStr.Search(',');
1093             if ( nPos != STRING_NOTFOUND )
1094             {
1095                 aStr.Erase(0, nPos+1);
1096                 pImp->SetLastAlignment( (SfxChildAlignment) (sal_uInt16) aStr.ToInt32() );
1097             }
1098 
1099             nPos = aStr.Search(',');
1100             if ( nPos != STRING_NOTFOUND )
1101             {
1102                 // get split size and position in SplitWindow
1103                 Point aPos;
1104                 aStr.Erase(0, nPos+1);
1105                 if ( GetPosSizeFromString( aStr, aPos, pImp->aSplitSize ) )
1106                 {
1107                     pImp->nLine = pImp->nDockLine = (sal_uInt16) aPos.X();
1108                     pImp->nPos  = pImp->nDockPos  = (sal_uInt16) aPos.Y();
1109                     pImp->nVerticalSize = pImp->aSplitSize.Height();
1110                     pImp->nHorizontalSize = pImp->aSplitSize.Width();
1111                     if ( GetSplitSizeFromString( aStr, pImp->aSplitSize ))
1112                         bVertHorzRead = sal_True;
1113                 }
1114             }
1115         }
1116         else {
1117             DBG_ERROR( "Information is missing!" );
1118         }
1119     }
1120 
1121     if ( !bVertHorzRead )
1122     {
1123         pImp->nVerticalSize = pImp->aSplitSize.Height();
1124         pImp->nHorizontalSize = pImp->aSplitSize.Width();
1125     }
1126 
1127     SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1128     if ( GetAlignment() != SFX_ALIGN_NOALIGNMENT )
1129     {
1130         // check if SfxWorkWindow is able to allow docking at its border
1131         if (
1132             !pWorkWin->IsDockingAllowed() ||
1133             !pWorkWin->IsInternalDockingAllowed() ||
1134             ( (GetFloatStyle() & WB_STANDALONE) && Application::IsInModalMode()) )
1135         {
1136             SetAlignment( SFX_ALIGN_NOALIGNMENT );
1137         }
1138     }
1139 
1140     // detect floating mode
1141     // toggeling mode will not execute code in handlers, because pImp->bConstructed is not set yet
1142     sal_Bool bFloatMode = IsFloatingMode();
1143     if ( bFloatMode != ((GetAlignment() == SFX_ALIGN_NOALIGNMENT)) )
1144     {
1145         bFloatMode = !bFloatMode;
1146         SetFloatingMode( bFloatMode );
1147         if ( bFloatMode )
1148         {
1149             if ( pImp->aWinState.Len() )
1150                 GetFloatingWindow()->SetWindowState( pImp->aWinState );
1151             else
1152                 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
1153         }
1154     }
1155 
1156     if ( IsFloatingMode() )
1157     {
1158         // validate last alignment
1159         SfxChildAlignment eLastAlign = pImp->GetLastAlignment();
1160         if ( eLastAlign == SFX_ALIGN_NOALIGNMENT)
1161             eLastAlign = CheckAlignment(eLastAlign, SFX_ALIGN_LEFT);
1162         if ( eLastAlign == SFX_ALIGN_NOALIGNMENT)
1163             eLastAlign = CheckAlignment(eLastAlign, SFX_ALIGN_RIGHT);
1164         if ( eLastAlign == SFX_ALIGN_NOALIGNMENT)
1165             eLastAlign = CheckAlignment(eLastAlign, SFX_ALIGN_TOP);
1166         if ( eLastAlign == SFX_ALIGN_NOALIGNMENT)
1167             eLastAlign = CheckAlignment(eLastAlign, SFX_ALIGN_BOTTOM);
1168         pImp->SetLastAlignment(eLastAlign);
1169     }
1170     else
1171     {
1172         // docked window must have NOALIGNMENT as last alignment
1173         pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT);
1174 
1175         if ( pImp->bSplitable )
1176         {
1177 //          pImp->bAutoHide = ( pInfo->nFlags & SFX_CHILDWIN_AUTOHIDE) != 0;
1178             pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(GetAlignment());
1179             pImp->pSplitWin->InsertWindow(this, pImp->aSplitSize);
1180         }
1181         else
1182         {
1183             //?????? Currently not supported
1184             // Fenster ist individuell angedockt; Gr"o\se berechnen.
1185             // Dazu mu\s sie mit der FloatingSize initialisiert werden, falls
1186             // irgendwer sich darauf verl"a\st, da\s eine vern"unftige Gr"o\se
1187             // gesetzt ist
1188             SetSizePixel(GetFloatingSize());
1189             SetSizePixel(CalcDockingSize(GetAlignment()));
1190         }
1191     }
1192 
1193     // save alignment
1194     pImp->SetDockAlignment( GetAlignment() );
1195 }
1196 
1197 void SfxDockingWindow::Initialize_Impl()
1198 {
1199     if ( !pMgr )
1200     {
1201         // Bugfix #39771
1202         pImp->bConstructed = sal_True;
1203         return;
1204     }
1205 
1206     FloatingWindow* pFloatWin = GetFloatingWindow();
1207     sal_Bool bSet = sal_False;
1208     if ( pFloatWin )
1209     {
1210         bSet = !pFloatWin->IsDefaultPos();
1211     }
1212     else
1213     {
1214         Point aPos = GetFloatingPos();
1215         if ( aPos != Point() )
1216             bSet = sal_True;
1217     }
1218 
1219     if ( !bSet)
1220     {
1221         SfxViewFrame *pFrame = pBindings->GetDispatcher_Impl()->GetFrame();
1222         Window* pEditWin = pFrame->GetViewShell()->GetWindow();
1223         Point aPos = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
1224         aPos = GetParent()->ScreenToOutputPixel( aPos );
1225         SetFloatingPos( aPos );
1226     }
1227 
1228     if ( pFloatWin )
1229     {
1230         // initialize floating window
1231         if ( !pImp->aWinState.Len() )
1232             // window state never set before, get if from defaults
1233             pImp->aWinState = pFloatWin->GetWindowState();
1234 
1235         // trick: use VCL method SetWindowState to adjust position and size
1236         pFloatWin->SetWindowState( pImp->aWinState );
1237 
1238         // remember floating size for calculating alignment and tracking rectangle
1239         SetFloatingSize( pFloatWin->GetSizePixel() );
1240 
1241         // some versions of VCL didn't call resize in the current situation
1242         //Resize();
1243     }
1244 
1245     // allow calling of docking handlers
1246     pImp->bConstructed = sal_True;
1247 }
1248 
1249 //-------------------------------------------------------------------------
1250 
1251 void SfxDockingWindow::FillInfo(SfxChildWinInfo& rInfo) const
1252 
1253 /*  [Beschreibung]
1254 
1255     F"ullt ein SfxChildWinInfo mit f"ur SfxDockingWindow spezifischen Daten,
1256     damit sie in die INI-Datei geschrieben werden koennen.
1257     Es wird angenommen, da\s rInfo alle anderen evt. relevanten Daten in
1258     der ChildWindow-Klasse erh"alt.
1259     Eingetragen werden hier gemerkten Gr"o\sen, das ZoomIn-Flag und die
1260     f"ur das Docking relevanten Informationen.
1261     Wird diese Methode "uberschrieben, mu\s zuerst die Basisimplementierung
1262     gerufen werden.
1263 */
1264 
1265 {
1266     if ( !pMgr )
1267         return;
1268 
1269     if ( GetFloatingWindow() && pImp->bConstructed )
1270         pImp->aWinState = GetFloatingWindow()->GetWindowState();
1271 
1272     rInfo.aWinState = pImp->aWinState;
1273     rInfo.aExtraString = DEFINE_CONST_UNICODE("AL:(");
1274     rInfo.aExtraString += String::CreateFromInt32((sal_uInt16) GetAlignment());
1275     rInfo.aExtraString += ',';
1276     rInfo.aExtraString += String::CreateFromInt32 ((sal_uInt16) pImp->GetLastAlignment());
1277     if ( pImp->bSplitable )
1278     {
1279         Point aPos(pImp->nLine, pImp->nPos);
1280         rInfo.aExtraString += ',';
1281         rInfo.aExtraString += String::CreateFromInt32( aPos.X() );
1282         rInfo.aExtraString += '/';
1283         rInfo.aExtraString += String::CreateFromInt32( aPos.Y() );
1284         rInfo.aExtraString += '/';
1285         rInfo.aExtraString += String::CreateFromInt32( pImp->nHorizontalSize );
1286         rInfo.aExtraString += '/';
1287         rInfo.aExtraString += String::CreateFromInt32( pImp->nVerticalSize );
1288         rInfo.aExtraString += ',';
1289         rInfo.aExtraString += String::CreateFromInt32( pImp->aSplitSize.Width() );
1290         rInfo.aExtraString += ';';
1291         rInfo.aExtraString += String::CreateFromInt32( pImp->aSplitSize.Height() );
1292     }
1293 
1294     rInfo.aExtraString += ')';
1295 }
1296 
1297 //-------------------------------------------------------------------------
1298 
1299 SfxDockingWindow::~SfxDockingWindow()
1300 {
1301     ReleaseChildWindow_Impl();
1302     delete pImp;
1303 }
1304 
1305 void SfxDockingWindow::ReleaseChildWindow_Impl()
1306 {
1307     if ( pMgr && pMgr->GetFrame() == pBindings->GetActiveFrame() )
1308         pBindings->SetActiveFrame( NULL );
1309 
1310     if ( pMgr && pImp->pSplitWin && pImp->pSplitWin->IsItemValid( GetType() ) )
1311         pImp->pSplitWin->RemoveWindow(this);
1312 
1313     pMgr=NULL;
1314 }
1315 
1316 //-------------------------------------------------------------------------
1317 
1318 SfxChildAlignment SfxDockingWindow::CalcAlignment(const Point& rPos, Rectangle& rRect)
1319 
1320 /*  [Beschreibung]
1321 
1322     Diese Methode berechnet f"ur gegebene Mausposition und tracking rectangle,
1323     welches Alignment sich daraus ergeben w"urde. Beim Wechsel des Alignments
1324     kann sich auch das tracking rectangle "andern, so dass ein ver"andertes
1325     rectangle zur"uckgegeben wird.
1326 
1327     Der Klassenbenutzer kann das Verhalten dieser Methode und damit das Verhalten
1328     seiner DockinWindow-Klasse beim Docken beeinflussen, indem er die hier
1329     aufgerufene virtuelle Methode
1330 
1331         SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign)
1332 
1333     "uberschreibt (s.u.).
1334 */
1335 
1336 {
1337     // calculate hypothetical sizes for different modes
1338     Size aFloatingSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT));
1339     Size aVerticalSize(CalcDockingSize(SFX_ALIGN_LEFT));
1340     Size aHorizontalSize(CalcDockingSize(SFX_ALIGN_TOP));
1341 
1342     // check if docking is permitted
1343     SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1344     if ( !pWorkWin->IsDockingAllowed() )
1345     {
1346         rRect.SetSize( aFloatingSize );
1347         return pImp->GetDockAlignment();
1348     }
1349 
1350     // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1351     long nLRBorder, nTBBorder;
1352     if ( pImp->bSplitable )
1353     {
1354         // take the smaller size of docked and floating mode
1355         Size aSize = pImp->aSplitSize;
1356         if ( GetFloatingSize().Height() < aSize.Height() )
1357             aSize.Height() = GetFloatingSize().Height();
1358         if ( GetFloatingSize().Width() < aSize.Width() )
1359             aSize.Width() = GetFloatingSize().Width();
1360 
1361         nLRBorder = aSize.Width();
1362         nTBBorder = aSize.Height();
1363     }
1364     else
1365     {
1366         nLRBorder = aVerticalSize.Width();
1367         nTBBorder = aHorizontalSize.Height();
1368     }
1369 
1370     // limit border to predefined constant values
1371     if ( nLRBorder > MAX_TOGGLEAREA_WIDTH )
1372         nLRBorder = MAX_TOGGLEAREA_WIDTH;
1373     if ( nTBBorder > MAX_TOGGLEAREA_WIDTH )
1374         nTBBorder = MAX_TOGGLEAREA_WIDTH;
1375 
1376     // shrink area for floating mode if possible
1377     Rectangle aInRect = GetInnerRect();
1378     if ( aInRect.GetWidth() > nLRBorder )
1379         aInRect.Left()   += nLRBorder/2;
1380     if ( aInRect.GetWidth() > nLRBorder )
1381         aInRect.Right()  -= nLRBorder/2;
1382     if ( aInRect.GetHeight() > nTBBorder )
1383         aInRect.Top()    += nTBBorder/2;
1384     if ( aInRect.GetHeight() > nTBBorder )
1385         aInRect.Bottom() -= nTBBorder/2;
1386 
1387     // calculate alignment resulting from docking rectangle
1388     sal_Bool bBecomesFloating = sal_False;
1389     SfxChildAlignment eDockAlign = pImp->GetDockAlignment();
1390     Rectangle aDockingRect( rRect );
1391     if ( !IsFloatingMode() )
1392     {
1393         // don't use tracking rectangle for alignment check, because it will be too large
1394         // to get a floating mode as result - switch to floating size
1395         // so the calculation only depends on the position of the rectangle, not the current
1396         // docking state of the window
1397         aDockingRect.SetSize( GetFloatingSize() );
1398 
1399         // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1400         aDockingRect.SetPos( pWorkWin->GetWindow()->OutputToScreenPixel( pWorkWin->GetWindow()->GetPointerPosPixel() ) );
1401     }
1402 
1403     Point aPos = aDockingRect.TopLeft();
1404     Rectangle aIntersect = GetOuterRect().GetIntersection( aDockingRect );
1405     if ( aIntersect.IsEmpty() )
1406         // docking rectangle completely outside docking area -> floating mode
1407         bBecomesFloating = sal_True;
1408     else
1409     {
1410         // create a small test rect around the mouse position and use this one
1411         // instead of the passed rRect to not dock too easily or by accident
1412         Rectangle aSmallDockingRect;
1413         aSmallDockingRect.SetSize( Size( MAX_TOGGLEAREA_WIDTH, MAX_TOGGLEAREA_HEIGHT ) );
1414         Point aNewPos(rPos);
1415         aNewPos.X() -= aSmallDockingRect.GetWidth()/2;
1416         aNewPos.Y() -= aSmallDockingRect.GetHeight()/2;
1417         aSmallDockingRect.SetPos(rPos);
1418         Rectangle aIntersectRect = aInRect.GetIntersection( aSmallDockingRect );
1419         if ( aIntersectRect == aSmallDockingRect )
1420             // docking rectangle completely inside (shrinked) inner area -> floating mode
1421             bBecomesFloating = sal_True;
1422     }
1423 
1424     if ( bBecomesFloating )
1425     {
1426         eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT);
1427     }
1428     else
1429     {
1430         // docking rectangle is in the "sensible area"
1431         Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() );
1432         Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() );
1433         Size  aInSize = aInRect.GetSize();
1434         sal_Bool  bNoChange = sal_False;
1435 
1436         // check if alignment is still unchanged
1437         switch ( GetAlignment() )
1438         {
1439             case SFX_ALIGN_LEFT:
1440             case SFX_ALIGN_FIRSTLEFT:
1441             case SFX_ALIGN_LASTLEFT:
1442                 if (aInPosTL.X() <= 0)
1443                 {
1444                     eDockAlign = GetAlignment();
1445                     bNoChange = sal_True;
1446                 }
1447                 break;
1448             case SFX_ALIGN_TOP:
1449             case SFX_ALIGN_LOWESTTOP:
1450             case SFX_ALIGN_HIGHESTTOP:
1451                 if ( aInPosTL.Y() <= 0)
1452                 {
1453                     eDockAlign = GetAlignment();
1454                     bNoChange = sal_True;
1455                 }
1456                 break;
1457             case SFX_ALIGN_RIGHT:
1458             case SFX_ALIGN_FIRSTRIGHT:
1459             case SFX_ALIGN_LASTRIGHT:
1460                 if ( aInPosBR.X() >= aInSize.Width())
1461                 {
1462                     eDockAlign = GetAlignment();
1463                     bNoChange = sal_True;
1464                 }
1465                 break;
1466             case SFX_ALIGN_BOTTOM:
1467             case SFX_ALIGN_LOWESTBOTTOM:
1468             case SFX_ALIGN_HIGHESTBOTTOM:
1469                 if ( aInPosBR.Y() >= aInSize.Height())
1470                 {
1471                     eDockAlign = GetAlignment();
1472                     bNoChange = sal_True;
1473                 }
1474                 break;
1475             default:
1476                 break;
1477         }
1478 
1479         if ( !bNoChange )
1480         {
1481             // alignment will change, test alignment according to distance of the docking rectangles edges
1482             sal_Bool bForbidden = sal_True;
1483             if ( aInPosTL.X() <= 0)
1484             {
1485                 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_LEFT);
1486                 bForbidden = ( eDockAlign != SFX_ALIGN_LEFT &&
1487                                eDockAlign != SFX_ALIGN_FIRSTLEFT &&
1488                                eDockAlign != SFX_ALIGN_LASTLEFT );
1489             }
1490 
1491             if ( bForbidden && aInPosTL.Y() <= 0)
1492             {
1493                 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_TOP);
1494                 bForbidden = ( eDockAlign != SFX_ALIGN_TOP &&
1495                                eDockAlign != SFX_ALIGN_HIGHESTTOP &&
1496                                eDockAlign != SFX_ALIGN_LOWESTTOP );
1497             }
1498 
1499             if ( bForbidden && aInPosBR.X() >= aInSize.Width())
1500             {
1501                 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_RIGHT);
1502                 bForbidden = ( eDockAlign != SFX_ALIGN_RIGHT &&
1503                                eDockAlign != SFX_ALIGN_FIRSTRIGHT &&
1504                                eDockAlign != SFX_ALIGN_LASTRIGHT );
1505             }
1506 
1507             if ( bForbidden && aInPosBR.Y() >= aInSize.Height())
1508             {
1509                 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_BOTTOM);
1510                 bForbidden = ( eDockAlign != SFX_ALIGN_BOTTOM &&
1511                                eDockAlign != SFX_ALIGN_HIGHESTBOTTOM &&
1512                                eDockAlign != SFX_ALIGN_LOWESTBOTTOM );
1513             }
1514 
1515             // the calculated alignment was rejected by the window -> take floating mode
1516             if ( bForbidden )
1517                 eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT);
1518         }
1519     }
1520 
1521     if ( eDockAlign == SFX_ALIGN_NOALIGNMENT )
1522     {
1523         //Im FloatingMode erh"alt das tracking rectangle die floating size
1524         // wg. SV-Bug darf rRect nur ver"andert werden, wenn sich das
1525         // Alignment "andert !
1526         if ( eDockAlign != pImp->GetDockAlignment() )
1527             aDockingRect.SetSize( aFloatingSize );
1528     }
1529     else if ( pImp->bSplitable )
1530     {
1531         sal_uInt16 nLine, nPos;
1532         SfxSplitWindow *pSplitWin = pWorkWin->GetSplitWindow_Impl(eDockAlign);
1533         aPos = pSplitWin->ScreenToOutputPixel( aPos );
1534         if ( pSplitWin->GetWindowPos( aPos, nLine, nPos ) )
1535         {
1536             // mouse over splitwindow, get line and position
1537             pImp->nDockLine = nLine;
1538             pImp->nDockPos = nPos;
1539             pImp->bNewLine = sal_False;
1540         }
1541         else
1542         {
1543             if ( 0 )
1544             {
1545                 // mouse touches outer border -> treated as floating mode
1546                 eDockAlign = SFX_ALIGN_NOALIGNMENT;
1547                 aDockingRect.SetSize( aFloatingSize );
1548                 rRect = aDockingRect;
1549                 return eDockAlign;
1550             }
1551 
1552             // mouse touches inner border -> create new line
1553             if ( eDockAlign == GetAlignment() && pImp->pSplitWin &&
1554                 pImp->nLine == pImp->pSplitWin->GetLineCount()-1 && pImp->pSplitWin->GetWindowCount(pImp->nLine) == 1 )
1555             {
1556                 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1557                 pImp->nDockLine = pImp->nLine;
1558                 pImp->nDockPos = pImp->nPos;
1559                 pImp->bNewLine = sal_False;
1560             }
1561             else
1562             {
1563                 // create new line
1564                 pImp->nDockLine = pSplitWin->GetLineCount();
1565                 pImp->nDockPos = 0;
1566                 pImp->bNewLine = sal_True;
1567             }
1568         }
1569 
1570         sal_Bool bChanged = pImp->nLine != pImp->nDockLine || pImp->nPos != pImp->nDockPos || eDockAlign != GetAlignment();
1571         if ( !bChanged && !IsFloatingMode() )
1572         {
1573             // window only sightly moved, no change of any property
1574             rRect.SetSize( pImp->aSplitSize );
1575             rRect.SetPos( aDockingRect.TopLeft() );
1576             return eDockAlign;
1577         }
1578 
1579         // calculate new size and position
1580         Size aSize;
1581         Point aPoint = aDockingRect.TopLeft();
1582         Size aInnerSize = GetInnerRect().GetSize();
1583         if ( eDockAlign == SFX_ALIGN_LEFT || eDockAlign == SFX_ALIGN_RIGHT )
1584         {
1585             if ( pImp->bNewLine )
1586             {
1587                 // set height to height of free area
1588                 aSize.Height() = aInnerSize.Height();
1589                 aSize.Width() = pImp->nHorizontalSize;
1590                 if ( eDockAlign == SFX_ALIGN_LEFT )
1591                 {
1592                     aPoint = aInnerRect.TopLeft();
1593                 }
1594                 else
1595                 {
1596                     aPoint = aInnerRect.TopRight();
1597                     aPoint.X() -= aSize.Width();
1598                 }
1599             }
1600             else
1601             {
1602                 // get width from splitwindow
1603                 aSize.Width() = pSplitWin->GetLineSize(nLine);
1604                 aSize.Height() = pImp->aSplitSize.Height();
1605             }
1606         }
1607         else
1608         {
1609             if ( pImp->bNewLine )
1610             {
1611                 // set width to width of free area
1612                 aSize.Width() = aInnerSize.Width();
1613                 aSize.Height() = pImp->nVerticalSize;
1614                 if ( eDockAlign == SFX_ALIGN_TOP )
1615                 {
1616                     aPoint = aInnerRect.TopLeft();
1617                 }
1618                 else
1619                 {
1620                     aPoint = aInnerRect.BottomLeft();
1621                     aPoint.Y() -= aSize.Height();
1622                 }
1623             }
1624             else
1625             {
1626                 // get height from splitwindow
1627                 aSize.Height() = pSplitWin->GetLineSize(nLine);
1628                 aSize.Width() = pImp->aSplitSize.Width();
1629             }
1630         }
1631 
1632         aDockingRect.SetSize( aSize );
1633         aDockingRect.SetPos( aPoint );
1634     }
1635     else
1636     {
1637         // window can be docked, but outside our splitwindows
1638         // tracking rectangle only needs to be modified if alignment was changed
1639         if ( eDockAlign != pImp->GetDockAlignment() )
1640         {
1641             switch ( eDockAlign )
1642             {
1643                 case SFX_ALIGN_LEFT:
1644                 case SFX_ALIGN_RIGHT:
1645                 case SFX_ALIGN_FIRSTLEFT:
1646                     aDockingRect.SetPos( aInnerRect.TopLeft() );
1647                     aDockingRect.SetSize( aVerticalSize );
1648                     break;
1649                 case SFX_ALIGN_LASTLEFT:
1650                 case SFX_ALIGN_FIRSTRIGHT:
1651                 case SFX_ALIGN_LASTRIGHT:
1652                 {
1653                     Point aPt( aInnerRect.TopRight() );
1654                     aPt.X() -= aDockingRect.GetWidth();
1655                     aDockingRect.SetPos( aPt );
1656                     aDockingRect.SetSize( aVerticalSize );
1657                     break;
1658                 }
1659 
1660                 case SFX_ALIGN_TOP:
1661                 case SFX_ALIGN_BOTTOM:
1662                 case SFX_ALIGN_LOWESTTOP:
1663                     aDockingRect.SetPos( aInnerRect.TopLeft() );
1664                     aDockingRect.SetSize( aHorizontalSize );
1665                     break;
1666                 case SFX_ALIGN_HIGHESTTOP:
1667                 case SFX_ALIGN_LOWESTBOTTOM:
1668                 case SFX_ALIGN_HIGHESTBOTTOM:
1669                 {
1670                     Point aPt( aInnerRect.BottomLeft() );
1671                     aPt.Y() -= aDockingRect.GetHeight();
1672                     aDockingRect.SetPos( aPt );
1673                     aDockingRect.SetSize( aHorizontalSize );
1674                     break;
1675                 }
1676                         default:
1677                             break;
1678             }
1679         }
1680     }
1681 
1682     rRect = aDockingRect;
1683     return eDockAlign;
1684 }
1685 
1686 //-------------------------------------------------------------------------
1687 
1688 Size SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign)
1689 
1690 /*  [Beschreibung]
1691 
1692     Virtuelle Methode der Klasse SfxDockingWindow.
1693     Hier wird festgelegt, wie sich die Gr"o\se des DockingWindows abh"angig vom
1694     Alignment "andert.
1695     Die Basisimplementation setzt im Floating Mode die Gr"o\se auf die gemerkte
1696     Floating Size.
1697     Bei horizontalem Alignment wird die Breite auf die Breite des "au\seren
1698     DockingRects, bei vertikalem Alignment die H"ohe auf die H"ohe des inneren
1699     DockingRects (ergibt sich aus der Reihenfolge, in der im SFX ChildWindows
1700     ausgegeben werden). Die jeweils andere Gr"o\se wird auf die aktuelle
1701     Floating Size gesetzt, hier k"onnte eine abgeleitete Klasse "andernd
1702     eingreifen.
1703     Die DockingSize mu\s f"ur Left/Right und Top/Bottom jeweils gleich sein.
1704 */
1705 
1706 {
1707     // Achtung: falls das Resizing auch im angedockten Zustand geht, mu\s dabei
1708     // auch die Floating Size angepa\st werden !?
1709 
1710     Size aSize = GetFloatingSize();
1711     switch (eAlign)
1712     {
1713         case SFX_ALIGN_TOP:
1714         case SFX_ALIGN_BOTTOM:
1715         case SFX_ALIGN_LOWESTTOP:
1716         case SFX_ALIGN_HIGHESTTOP:
1717         case SFX_ALIGN_LOWESTBOTTOM:
1718         case SFX_ALIGN_HIGHESTBOTTOM:
1719             aSize.Width() = aOuterRect.Right() - aOuterRect.Left();
1720             break;
1721         case SFX_ALIGN_LEFT:
1722         case SFX_ALIGN_RIGHT:
1723         case SFX_ALIGN_FIRSTLEFT:
1724         case SFX_ALIGN_LASTLEFT:
1725         case SFX_ALIGN_FIRSTRIGHT:
1726         case SFX_ALIGN_LASTRIGHT:
1727             aSize.Height() = aInnerRect.Bottom() - aInnerRect.Top();
1728             break;
1729         case SFX_ALIGN_NOALIGNMENT:
1730             break;
1731               default:
1732                   break;
1733     }
1734 
1735     return aSize;
1736 }
1737 
1738 //-------------------------------------------------------------------------
1739 
1740 SfxChildAlignment SfxDockingWindow::CheckAlignment(SfxChildAlignment,
1741     SfxChildAlignment eAlign)
1742 
1743 /*  [Beschreibung]
1744 
1745     Virtuelle Methode der Klasse SfxDockingWindow.
1746     Hier kann eine abgeleitete Klasse bestimmte Alignments verbieten.
1747     Die Basisimplementation verbietet kein Alignment.
1748 */
1749 
1750 {
1751     return eAlign;
1752 }
1753 
1754 //-------------------------------------------------------------------------
1755 
1756 sal_Bool SfxDockingWindow::Close()
1757 
1758 /*  [Beschreibung]
1759 
1760     Das Fenster wird geschlossen, indem das ChildWindow durch Ausf"uhren des
1761     ChildWindow-Slots zerst"ort wird.
1762     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
1763     danach SfxDockingWindow::Close() gerufen werden, wenn nicht das Close()
1764     mit "return FALSE" abgebrochen wird.
1765 
1766 */
1767 {
1768     // Execute mit Parametern, da Toggle von einigen ChildWindows ignoriert
1769     // werden kann
1770     if ( !pMgr )
1771         return sal_True;
1772 
1773     SfxBoolItem aValue( pMgr->GetType(), sal_False);
1774     pBindings->GetDispatcher_Impl()->Execute(
1775         pMgr->GetType(), SFX_CALLMODE_RECORD | SFX_CALLMODE_ASYNCHRON, &aValue, 0L );
1776     return sal_True;
1777 }
1778 
1779 //-------------------------------------------------------------------------
1780 
1781 void SfxDockingWindow::Paint(const Rectangle& /*rRect*/)
1782 
1783 /*  [Beschreibung]
1784 
1785     Es wird im angedockten Zustand eine Begrenzungslinie an der angedockten
1786     Kante und ein Rahmen ausgegeben. Dabei wird SVLOOK ber"ucksichtigt.
1787 */
1788 
1789 {
1790     if ( pImp->bSplitable || IsFloatingMode() )
1791         return;
1792 
1793     Rectangle aRect = Rectangle(Point(0, 0),
1794                                 GetOutputSizePixel());
1795     switch (GetAlignment())
1796     {
1797         case SFX_ALIGN_TOP:
1798         {
1799             DrawLine(aRect.BottomLeft(), aRect.BottomRight());
1800             aRect.Bottom()--;
1801             break;
1802         }
1803 
1804         case SFX_ALIGN_BOTTOM:
1805         {
1806             DrawLine(aRect.TopLeft(), aRect.TopRight());
1807             aRect.Top()++;
1808             break;
1809         }
1810 
1811         case SFX_ALIGN_LEFT:
1812         {
1813             DrawLine(aRect.TopRight(), aRect.BottomRight());
1814             aRect.Right()--;
1815             break;
1816         }
1817 
1818         case SFX_ALIGN_RIGHT:
1819         {
1820             DrawLine(aRect.TopLeft(), aRect.BottomLeft());
1821             aRect.Left()++;
1822             break;
1823         }
1824               default:
1825                   break;
1826     }
1827 
1828     DecorationView aView( this );
1829     aView.DrawFrame( aRect, FRAME_DRAW_OUT );
1830 }
1831 
1832 //-------------------------------------------------------------------------
1833 
1834 void SfxDockingWindow::SetMinOutputSizePixel( const Size& rSize )
1835 
1836 /*  [Beschreibung]
1837 
1838     Mit dieser Methode kann eine minimale OutpuSize gesetzt werden, die
1839     im Resizing()-Handler abgefragt wird.
1840 */
1841 
1842 {
1843     pImp->aMinSize = rSize;
1844     DockingWindow::SetMinOutputSizePixel( rSize );
1845 }
1846 
1847 //-------------------------------------------------------------------------
1848 
1849 Size SfxDockingWindow::GetMinOutputSizePixel() const
1850 
1851 /*  [Beschreibung]
1852 
1853     Die gesetzte minimale Gr"o\se wird zur"uckgegeben.
1854 */
1855 
1856 {
1857     return pImp->aMinSize;
1858 }
1859 
1860 //-------------------------------------------------------------------------
1861 
1862 long SfxDockingWindow::Notify( NotifyEvent& rEvt )
1863 {
1864     if ( rEvt.GetType() == EVENT_GETFOCUS )
1865     {
1866         pBindings->SetActiveFrame( pMgr->GetFrame() );
1867 
1868         if ( pImp->pSplitWin )
1869             pImp->pSplitWin->SetActiveWindow_Impl( this );
1870         else
1871             pMgr->Activate_Impl();
1872 
1873         Window* pWindow = rEvt.GetWindow();
1874         rtl::OString sHelpId;
1875         while ( !sHelpId.getLength() && pWindow )
1876         {
1877             sHelpId = pWindow->GetHelpId();
1878             pWindow = pWindow->GetParent();
1879         }
1880 
1881         if ( sHelpId.getLength() )
1882             SfxHelp::OpenHelpAgent( &pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame(), sHelpId );
1883 
1884         // In VCL geht Notify zun"achst an das Fenster selbst,
1885         // also base class rufen, sonst erf"ahrt der parent nichts
1886         // if ( rEvt.GetWindow() == this )  PB: #i74693# not necessary any longer
1887         DockingWindow::Notify( rEvt );
1888         return sal_True;
1889     }
1890     else if( rEvt.GetType() == EVENT_KEYINPUT )
1891     {
1892         // KeyInput zuerst f"ur Dialogfunktionen zulassen
1893         if ( !DockingWindow::Notify( rEvt ) && SfxViewShell::Current() )
1894             // dann auch global g"ultige Acceleratoren verwenden
1895             return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt.GetKeyEvent() );
1896         return sal_True;
1897     }
1898     else if ( rEvt.GetType() == EVENT_LOSEFOCUS && !HasChildPathFocus() )
1899     {
1900         pBindings->SetActiveFrame( NULL );
1901         pMgr->Deactivate_Impl();
1902     }
1903 
1904     return DockingWindow::Notify( rEvt );
1905 }
1906 
1907 
1908 sal_uInt16 SfxDockingWindow::GetWinBits_Impl() const
1909 {
1910     sal_uInt16 nBits = 0;
1911 //  if ( pImp->bAutoHide )
1912 //      nBits |= SWIB_AUTOHIDE;
1913     return nBits;
1914 }
1915 
1916 //-------------------------------------------------------------------------
1917 
1918 void SfxDockingWindow::SetItemSize_Impl( const Size& rSize )
1919 {
1920     pImp->aSplitSize = rSize;
1921 
1922     SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1923     SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
1924     if ( pImp->bSplitable )
1925         eIdent = SFX_CHILDWIN_SPLITWINDOW;
1926     pWorkWin->ConfigChild_Impl( eIdent, SFX_ALIGNDOCKINGWINDOW, pMgr->GetType() );
1927 }
1928 
1929 void SfxDockingWindow::Disappear_Impl()
1930 {
1931     if ( pImp->pSplitWin && pImp->pSplitWin->IsItemValid( GetType() ) )
1932         pImp->pSplitWin->RemoveWindow(this);
1933 }
1934 
1935 void SfxDockingWindow::Reappear_Impl()
1936 {
1937     if ( pImp->pSplitWin && !pImp->pSplitWin->IsItemValid( GetType() ) )
1938     {
1939         pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize );
1940     }
1941 }
1942 
1943 sal_Bool SfxDockingWindow::IsAutoHide_Impl() const
1944 {
1945     if ( pImp->pSplitWin )
1946         return !pImp->pSplitWin->IsFadeIn();
1947     else
1948         return sal_False;
1949 }
1950 
1951 sal_Bool SfxDockingWindow::IsPinned_Impl() const
1952 {
1953     if ( pImp->pSplitWin )
1954         return pImp->pSplitWin->IsPinned();
1955     else
1956         return sal_True;
1957 }
1958 void SfxDockingWindow::AutoShow( sal_Bool bShow )
1959 {
1960     AutoShow_Impl(bShow);
1961 }
1962 
1963 void SfxDockingWindow::AutoShow_Impl( sal_Bool bShow )
1964 {
1965     if ( pImp->pSplitWin )
1966     {
1967         if ( bShow )
1968             pImp->pSplitWin->FadeIn();
1969         else
1970             pImp->pSplitWin->FadeOut();
1971     }
1972 }
1973 
1974 /*
1975 void SfxDockingWindow::Pin_Impl( sal_Bool bPinned )
1976 {
1977     if ( pImp->pSplitWin )
1978         pImp->pSplitWin->Pin_Impl( bPinned );
1979 }
1980 */
1981 
1982 SfxSplitWindow* SfxDockingWindow::GetSplitWindow_Impl() const
1983 {
1984     return pImp->pSplitWin;
1985 }
1986 
1987 void SfxDockingWindow::FadeIn( sal_Bool /*bFadeIn*/ )
1988 {
1989 }
1990 
1991 void SfxDockingWindow::StateChanged( StateChangedType nStateChange )
1992 {
1993     if ( nStateChange == STATE_CHANGE_INITSHOW )
1994         Initialize_Impl();
1995 
1996     DockingWindow::StateChanged( nStateChange );
1997 }
1998 
1999 void SfxDockingWindow::Move()
2000 {
2001     if ( pImp )
2002         pImp->aMoveTimer.Start();
2003 }
2004 
2005 IMPL_LINK( SfxDockingWindow, TimerHdl, Timer*, EMPTYARG)
2006 {
2007     pImp->aMoveTimer.Stop();
2008     if ( IsReallyVisible() && IsFloatingMode() )
2009     {
2010         if( !GetFloatingWindow()->IsRollUp() )
2011             SetFloatingSize( GetOutputSizePixel() );
2012         pImp->aWinState = GetFloatingWindow()->GetWindowState();
2013         SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW;
2014         if ( pImp->bSplitable )
2015             eIdent = SFX_CHILDWIN_SPLITWINDOW;
2016         SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
2017         pWorkWin->ConfigChild_Impl( eIdent, SFX_ALIGNDOCKINGWINDOW, pMgr->GetType() );
2018     }
2019     return 0;
2020 }
2021 
2022