xref: /trunk/main/sfx2/source/dialog/dockwin.cxx (revision 86e1cf34)
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 (shrunk) 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