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