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