Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / dialog / splitwin.cxx
blobe6f39e660c890c5b8fc38399f1e46d8147e78f26
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #ifdef SOLARIS
31 #include <ctime>
32 #endif
34 #include <string>
36 #include <vcl/wrkwin.hxx>
37 #include <unotools/viewoptions.hxx>
39 #include <vcl/timer.hxx>
41 #include "splitwin.hxx"
42 #include "workwin.hxx"
43 #include <sfx2/dockwin.hxx>
44 #include <sfx2/app.hxx>
45 #include "dialog.hrc"
46 #include "sfx2/sfxresid.hxx"
47 #include <sfx2/mnumgr.hxx>
48 #include "virtmenu.hxx"
49 #include <sfx2/msgpool.hxx>
50 #include <sfx2/viewfrm.hxx>
52 using namespace ::com::sun::star::uno;
53 using namespace ::rtl;
55 #define VERSION 1
56 #define nPixel 30L
57 #define USERITEM_NAME OUString("UserItem")
59 struct SfxDock_Impl
61 sal_uInt16 nType;
62 SfxDockingWindow* pWin; // SplitWindow has this window
63 sal_Bool bNewLine;
64 sal_Bool bHide; // SplitWindow had this window
65 long nSize;
68 typedef SfxDock_Impl* SfxDockPtr;
69 SV_DECL_PTRARR_DEL( SfxDockArr_Impl, SfxDockPtr, 4 )
70 SV_IMPL_PTRARR( SfxDockArr_Impl, SfxDockPtr);
72 class SfxEmptySplitWin_Impl : public SplitWindow
74 /* [Description]
76 The SfxEmptySplitWin_Impldow is an empty SplitWindow, that replaces the
77 SfxSplitWindow AutoHide mode. It only serves as a placeholder to receive
78 mouse moves and if possible blend in the true SplitWindow display.
80 friend class SfxSplitWindow;
82 SfxSplitWindow* pOwner;
83 sal_Bool bFadeIn;
84 sal_Bool bAutoHide;
85 sal_Bool bSplit;
86 sal_Bool bEndAutoHide;
87 Timer aTimer;
88 Point aLastPos;
89 sal_uInt16 nState;
91 SfxEmptySplitWin_Impl( SfxSplitWindow *pParent )
92 : SplitWindow( pParent->GetParent(), WinBits( WB_BORDER | WB_3DLOOK ) )
93 , pOwner( pParent )
94 , bFadeIn( sal_False )
95 , bAutoHide( sal_False )
96 , bSplit( sal_False )
97 , bEndAutoHide( sal_False )
98 , nState( 1 )
100 aTimer.SetTimeoutHdl(
101 LINK(pOwner, SfxSplitWindow, TimerHdl ) );
102 aTimer.SetTimeout( 200 );
103 SetAlign( pOwner->GetAlign() );
104 Actualize();
105 ShowAutoHideButton( pOwner->IsAutoHideButtonVisible() );
106 ShowFadeInHideButton( sal_True );
109 ~SfxEmptySplitWin_Impl()
111 aTimer.Stop();
114 virtual void MouseMove( const MouseEvent& );
115 virtual void AutoHide();
116 virtual void FadeIn();
117 void Actualize();
120 void SfxEmptySplitWin_Impl::Actualize()
122 Size aSize( pOwner->GetSizePixel() );
123 switch ( pOwner->GetAlign() )
125 case WINDOWALIGN_LEFT:
126 case WINDOWALIGN_RIGHT:
127 aSize.Width() = GetFadeInSize();
128 break;
129 case WINDOWALIGN_TOP:
130 case WINDOWALIGN_BOTTOM:
131 aSize.Height() = GetFadeInSize();
132 break;
135 SetSizePixel( aSize );
138 void SfxEmptySplitWin_Impl::AutoHide()
140 pOwner->SetPinned_Impl( !pOwner->bPinned );
141 pOwner->SaveConfig_Impl();
142 bAutoHide = sal_True;
143 FadeIn();
146 void SfxEmptySplitWin_Impl::FadeIn()
148 if (!bAutoHide )
149 bAutoHide = IsFadeNoButtonMode();
150 pOwner->SetFadeIn_Impl( sal_True );
151 pOwner->Show_Impl();
152 if ( bAutoHide )
154 // Set Timer to close; the caller has to ensure themselves that the
155 // Window is not closed instantly (eg by setting the focus or a modal
156 // mode.
157 aLastPos = GetPointerPosPixel();
158 aTimer.Start();
160 else
161 pOwner->SaveConfig_Impl();
164 //-------------------------------------------------------------------------
166 void SfxSplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
168 if ( rMEvt.GetClicks() != 2 )
169 SplitWindow::MouseButtonDown( rMEvt );
172 void SfxEmptySplitWin_Impl::MouseMove( const MouseEvent& rMEvt )
174 SplitWindow::MouseMove( rMEvt );
177 //-------------------------------------------------------------------------
179 SfxSplitWindow::SfxSplitWindow( Window* pParent, SfxChildAlignment eAl,
180 SfxWorkWindow *pW, sal_Bool bWithButtons, WinBits nBits )
182 /* [Description]
184 A SfxSplitWindow brings the recursive structure of the SV-SplitWindows to
185 the outside by simulating a table-like structure with rows and columns
186 (maximum recursion depth 2). Furthermore, it ensures the persistence of
187 the arrangement of the SfxDockingWindows.
190 : SplitWindow ( pParent, nBits | WB_HIDE ),
191 eAlign(eAl),
192 pWorkWin(pW),
193 pDockArr( new SfxDockArr_Impl ),
194 bLocked(sal_False),
195 bPinned(sal_True),
196 pEmptyWin(NULL),
197 pActive(NULL)
199 if ( bWithButtons )
201 ShowAutoHideButton( sal_False ); // no autohide button (pin) anymore
202 ShowFadeOutButton( sal_True );
205 // Set SV-Alignment
206 WindowAlign eTbxAlign;
207 switch ( eAlign )
209 case SFX_ALIGN_LEFT:
210 eTbxAlign = WINDOWALIGN_LEFT;
211 break;
212 case SFX_ALIGN_RIGHT:
213 eTbxAlign = WINDOWALIGN_RIGHT;
214 break;
215 case SFX_ALIGN_TOP:
216 eTbxAlign = WINDOWALIGN_TOP;
217 break;
218 case SFX_ALIGN_BOTTOM:
219 eTbxAlign = WINDOWALIGN_BOTTOM;
220 bPinned = sal_True;
221 break;
222 default:
223 eTbxAlign = WINDOWALIGN_TOP; // some sort of default...
224 break; // -Wall lots not handled..
227 SetAlign (eTbxAlign);
228 pEmptyWin = new SfxEmptySplitWin_Impl( this );
229 if ( bPinned )
231 pEmptyWin->bFadeIn = sal_True;
232 pEmptyWin->nState = 2;
235 if ( bWithButtons )
237 // Read Configuration
238 String aWindowId = String::CreateFromAscii("SplitWindow");
239 aWindowId += String::CreateFromInt32( (sal_Int32) eTbxAlign );
240 SvtViewOptions aWinOpt( E_WINDOW, aWindowId );
241 String aWinData;
242 Any aUserItem = aWinOpt.GetUserItem( USERITEM_NAME );
243 OUString aTemp;
244 if ( aUserItem >>= aTemp )
245 aWinData = String( aTemp );
246 if ( aWinData.Len() && aWinData.GetChar( (sal_uInt16) 0 ) == 'V' )
248 pEmptyWin->nState = (sal_uInt16) aWinData.GetToken( 1, ',' ).ToInt32();
249 if ( pEmptyWin->nState & 2 )
250 pEmptyWin->bFadeIn = sal_True;
251 bPinned = sal_True; // always assume pinned - floating mode not used anymore
253 sal_uInt16 i=2;
254 sal_uInt16 nCount = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32();
255 for ( sal_uInt16 n=0; n<nCount; n++ )
257 SfxDock_Impl *pDock = new SfxDock_Impl;
258 pDock->pWin = 0;
259 pDock->bNewLine = sal_False;
260 pDock->bHide = sal_True;
261 pDock->nType = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32();
262 if ( !pDock->nType )
264 // could mean NewLine
265 pDock->nType = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32();
266 if ( !pDock->nType )
268 // Read error
269 delete pDock;
270 break;
272 else
273 pDock->bNewLine = sal_True;
276 pDockArr->Insert(pDock,n);
280 else
282 bPinned = sal_True;
283 pEmptyWin->bFadeIn = sal_True;
284 pEmptyWin->nState = 2;
287 SetAutoHideState( !bPinned );
288 pEmptyWin->SetAutoHideState( !bPinned );
291 //-------------------------------------------------------------------------
293 SfxSplitWindow::~SfxSplitWindow()
295 if ( !pWorkWin->GetParent_Impl() )
296 SaveConfig_Impl();
298 if ( pEmptyWin )
300 // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The
301 // window that is just beeing docked is always deleted from the outside.
302 pEmptyWin->pOwner = NULL;
303 delete pEmptyWin;
306 delete pDockArr;
309 void SfxSplitWindow::SaveConfig_Impl()
311 // Save configuration
312 String aWinData('V');
313 aWinData += String::CreateFromInt32( VERSION );
314 aWinData += ',';
315 aWinData += String::CreateFromInt32( pEmptyWin->nState );
316 aWinData += ',';
318 sal_uInt16 nCount = 0;
319 sal_uInt16 n;
320 for ( n=0; n<pDockArr->Count(); n++ )
322 SfxDock_Impl *pDock = (*pDockArr)[n];
323 if ( pDock->bHide || pDock->pWin )
324 nCount++;
327 aWinData += String::CreateFromInt32( nCount );
329 for ( n=0; n<pDockArr->Count(); n++ )
331 SfxDock_Impl *pDock = (*pDockArr)[n];
332 if ( !pDock->bHide && !pDock->pWin )
333 continue;
334 if ( pDock->bNewLine )
335 aWinData += DEFINE_CONST_UNICODE(",0");
336 aWinData += ',';
337 aWinData += String::CreateFromInt32( pDock->nType);
340 String aWindowId = String::CreateFromAscii("SplitWindow");
341 aWindowId += String::CreateFromInt32( (sal_Int32) GetAlign() );
342 SvtViewOptions aWinOpt( E_WINDOW, aWindowId );
343 aWinOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aWinData ) ) );
346 //-------------------------------------------------------------------------
348 void SfxSplitWindow::StartSplit()
350 long nSize = 0;
351 Size aSize = GetSizePixel();
353 if ( pEmptyWin )
355 pEmptyWin->bFadeIn = sal_True;
356 pEmptyWin->bSplit = sal_True;
359 Rectangle aRect = pWorkWin->GetFreeArea( !bPinned );
360 switch ( GetAlign() )
362 case WINDOWALIGN_LEFT:
363 case WINDOWALIGN_RIGHT:
364 nSize = aSize.Width() + aRect.GetWidth();
365 break;
366 case WINDOWALIGN_TOP:
367 case WINDOWALIGN_BOTTOM:
368 nSize = aSize.Height() + aRect.GetHeight();
369 break;
372 SetMaxSizePixel( nSize );
375 //-------------------------------------------------------------------------
377 void SfxSplitWindow::SplitResize()
379 if ( bPinned )
381 pWorkWin->ArrangeChildren_Impl();
382 pWorkWin->ShowChildren_Impl();
384 else
385 pWorkWin->ArrangeAutoHideWindows( this );
388 //-------------------------------------------------------------------------
390 void SfxSplitWindow::Split()
392 if ( pEmptyWin )
393 pEmptyWin->bSplit = sal_False;
395 SplitWindow::Split();
397 sal_uInt16 nCount = pDockArr->Count();
398 for ( sal_uInt16 n=0; n<nCount; n++ )
400 SfxDock_Impl *pD = (*pDockArr)[n];
401 if ( pD->pWin )
403 sal_uInt16 nId = pD->nType;
404 long nSize = GetItemSize( nId, SWIB_FIXED );
405 long nSetSize = GetItemSize( GetSet( nId ) );
406 Size aSize;
408 if ( IsHorizontal() )
410 aSize.Width() = nSize;
411 aSize.Height() = nSetSize;
413 else
415 aSize.Width() = nSetSize;
416 aSize.Height() = nSize;
419 pD->pWin->SetItemSize_Impl( aSize );
423 SaveConfig_Impl();
426 //-------------------------------------------------------------------------
428 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize)
430 /* [Description]
432 To insert SfxDockingWindows can no position be passed. The SfxSplitWindow
433 searches the last marked one to the passed SfxDockingWindow or appends a
434 new one at the end.
437 short nLine = -1; // so that the first window cab set nline to 0
438 sal_uInt16 nL;
439 sal_uInt16 nPos = 0;
440 sal_Bool bNewLine = sal_True;
441 sal_Bool bSaveConfig = sal_False;
442 SfxDock_Impl *pFoundDock=0;
443 sal_uInt16 nCount = pDockArr->Count();
444 for ( sal_uInt16 n=0; n<nCount; n++ )
446 SfxDock_Impl *pDock = (*pDockArr)[n];
447 if ( pDock->bNewLine )
449 // The window opens a new line
450 if ( pFoundDock )
451 // But after the just inserted window
452 break;
454 // New line
455 nPos = 0;
456 bNewLine = sal_True;
459 if ( pDock->pWin )
461 // Does there exist a window now at this position
462 if ( bNewLine && !pFoundDock )
464 // Not known until now in which real line it is located
465 GetWindowPos( pDock->pWin, nL, nPos );
466 nLine = (short) nL;
469 if ( !pFoundDock )
471 // The window is located before the inserted one
472 nPos++;
475 // Line is opened
476 bNewLine = sal_False;
477 if ( pFoundDock )
478 break;
481 if ( pDock->nType == pDockWin->GetType() )
483 DBG_ASSERT( !pFoundDock && !pDock->pWin, "Window does already exist!");
484 pFoundDock = pDock;
485 if ( !bNewLine )
486 break;
487 else
489 // A new line has been created but no window was fond there;
490 // continue searching for a window in this line in-order to set
491 // bNewLine correctly. While doing so nline or nPos are not
492 // to be changed!
493 nLine++;
498 if ( !pFoundDock )
500 // Not found, insert at end
501 pFoundDock = new SfxDock_Impl;
502 pFoundDock->bHide = sal_True;
503 pDockArr->Insert( pFoundDock, nCount );
504 pFoundDock->nType = pDockWin->GetType();
505 nLine++;
506 nPos = 0;
507 bNewLine = sal_True;
508 pFoundDock->bNewLine = bNewLine;
509 bSaveConfig = sal_True;
512 pFoundDock->pWin = pDockWin;
513 pFoundDock->bHide = sal_False;
514 InsertWindow_Impl( pFoundDock, rSize, nLine, nPos, bNewLine );
515 if ( bSaveConfig )
516 SaveConfig_Impl();
519 //-------------------------------------------------------------------------
521 void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow *pDockWin, sal_Bool bSave)
523 /* [Description]
525 The docking window is no longer stored in the internal data.
529 SfxDock_Impl *pDock=0;
530 sal_uInt16 nCount = pDockArr->Count();
531 sal_Bool bFound = sal_False;
532 for ( sal_uInt16 n=0; n<nCount; n++ )
534 pDock = (*pDockArr)[n];
535 if ( pDock->nType == pDockWin->GetType() )
537 if ( pDock->bNewLine && n<nCount-1 )
538 (*pDockArr)[n+1]->bNewLine = sal_True;
540 // Window has a position, this we forget
541 bFound = sal_True;
542 pDockArr->Remove(n);
543 break;
547 if ( bFound )
548 delete pDock;
550 if ( bSave )
551 SaveConfig_Impl();
554 //-------------------------------------------------------------------------
556 void SfxSplitWindow::MoveWindow( SfxDockingWindow* pDockWin, const Size& rSize,
557 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine)
559 /* [Description]
561 The docking window is moved within the SplitWindows.
565 sal_uInt16 nL, nP;
566 GetWindowPos( pDockWin, nL, nP );
568 if ( nLine > nL && GetItemCount( GetItemId( nL, 0 ) ) == 1 )
570 // If the last window is removed from its line, then everything slips
571 // one line to the front!
572 nLine--;
574 RemoveWindow( pDockWin );
575 InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine );
578 //-------------------------------------------------------------------------
580 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize,
581 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine)
583 /* [Description]
585 The DockingWindow that is pushed on this SplitWindow and shall hold the
586 given position and size.
589 ReleaseWindow_Impl( pDockWin, sal_False );
590 SfxDock_Impl *pDock = new SfxDock_Impl;
591 pDock->bHide = sal_False;
592 pDock->nType = pDockWin->GetType();
593 pDock->bNewLine = bNewLine;
594 pDock->pWin = pDockWin;
596 DBG_ASSERT( nPos==0 || !bNewLine, "Wrong Paramenter!");
597 if ( bNewLine )
598 nPos = 0;
600 // The window must be inserted before the first window so that it has the
601 // same or a greater position than pDockWin.
602 sal_uInt16 nCount = pDockArr->Count();
603 sal_uInt16 nLastWindowIdx(0);
605 // If no window is found, a first window is inserted
606 sal_uInt16 nInsertPos = 0;
607 for ( sal_uInt16 n=0; n<nCount; n++ )
609 SfxDock_Impl *pD = (*pDockArr)[n];
611 if (pD->pWin)
613 // A docked window has been found. If no suitable window behind the
614 // the desired insertion point s found, then insertion is done at
615 // the end.
616 nInsertPos = nCount;
617 nLastWindowIdx = n;
618 sal_uInt16 nL=0, nP=0;
619 GetWindowPos( pD->pWin, nL, nP );
621 if ( (nL == nLine && nP == nPos) || nL > nLine )
623 DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Wrong Parameter!" );
624 if ( nL == nLine && nPos == 0 && !bNewLine )
626 DBG_ASSERT(pD->bNewLine, "No new line?");
628 // The posption is pushed to nPos==0
629 pD->bNewLine = sal_False;
630 pDock->bNewLine = sal_True;
633 nInsertPos = n != 0 ? nLastWindowIdx + 1 : 0; // ignore all non-windows after the last window
634 break;
638 if (nCount != 0 && nInsertPos == nCount && nLastWindowIdx != nCount - 1)
640 nInsertPos = nLastWindowIdx + 1; // ignore all non-windows after the last window
643 pDockArr->Insert(pDock, nInsertPos);
644 InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine );
645 SaveConfig_Impl();
648 //-------------------------------------------------------------------------
650 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl* pDock,
651 const Size& rSize,
652 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine)
654 /* [Description]
656 Adds a DockingWindow, and causes the recalculation of the size of
657 the SplitWindows.
661 SfxDockingWindow* pDockWin = pDock->pWin;
663 sal_uInt16 nItemBits = pDockWin->GetWinBits_Impl();
665 long nWinSize, nSetSize;
666 if ( IsHorizontal() )
668 nWinSize = rSize.Width();
669 nSetSize = rSize.Height();
671 else
673 nSetSize = rSize.Width();
674 nWinSize = rSize.Height();
677 pDock->nSize = nWinSize;
679 sal_Bool bUpdateMode = IsUpdateMode();
680 if ( bUpdateMode )
681 SetUpdateMode( sal_False );
683 if ( bNewLine || nLine == GetItemCount( 0 ) )
685 // An existing row should not be inserted, instead a new one
686 // will be created
688 sal_uInt16 nId = 1;
689 for ( sal_uInt16 n=0; n<GetItemCount(0); n++ )
691 if ( GetItemId(n) >= nId )
692 nId = GetItemId(n)+1;
695 // Create a new nLine:th line
696 sal_uInt16 nBits = nItemBits;
697 if ( GetAlign() == WINDOWALIGN_TOP || GetAlign() == WINDOWALIGN_BOTTOM )
698 nBits |= SWIB_COLSET;
699 InsertItem( nId, nSetSize, nLine, 0, nBits );
702 // Insert the window at line with the position nline. ItemWindowSize set to
703 // "percentage" share since the SV then does the re-sizing as expected,
704 // "pixel" actually only makes sense if also items with percentage or
705 // relative sizes are present.
706 nItemBits |= SWIB_PERCENTSIZE;
707 bLocked = sal_True;
708 sal_uInt16 nSet = GetItemId( nLine );
709 InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits );
711 // SplitWindows are once created in SFX and when inserting the first
712 // DockingWindows is made visable.
713 if ( GetItemCount( 0 ) == 1 && GetItemCount( 1 ) == 1 )
715 // The Rearranging in WorkWindow and a Show() on the SplitWindow is
716 // caues by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl)
717 if ( !bPinned && !IsFloatingMode() )
719 bPinned = sal_True;
720 sal_Bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
721 pEmptyWin->bFadeIn = sal_False;
722 SetPinned_Impl( sal_False );
723 pEmptyWin->Actualize();
724 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
725 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, sal_True )->nVisible = CHILD_VISIBLE;
726 pWorkWin->ArrangeChildren_Impl();
727 if ( bFadeIn )
728 FadeIn();
730 else
732 sal_Bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
733 pEmptyWin->bFadeIn = sal_False;
734 pEmptyWin->Actualize();
735 #ifdef DBG_UTIL
736 if ( !bPinned || !pEmptyWin->bFadeIn )
738 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
740 else
742 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
744 #endif
745 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, sal_True )->nVisible = CHILD_VISIBLE;
746 pWorkWin->ArrangeChildren_Impl();
747 if ( bFadeIn )
748 FadeIn();
751 pWorkWin->ShowChildren_Impl();
754 if ( bUpdateMode )
755 SetUpdateMode( sal_True );
756 bLocked = sal_False;
759 //-------------------------------------------------------------------------
761 void SfxSplitWindow::RemoveWindow( SfxDockingWindow* pDockWin, sal_Bool bHide )
763 /* [Description]
765 Removes a DockingWindow. If it was the last one, then the SplitWindow is
766 beeing hidden.
769 sal_uInt16 nSet = GetSet( pDockWin->GetType() );
771 // SplitWindows are once created in SFX and is made invisible after
772 // removing the last DockingWindows.
773 if ( GetItemCount( nSet ) == 1 && GetItemCount( 0 ) == 1 )
775 // The Rearranging in WorkWindow is caues by SfxDockingwindow
776 Hide();
777 pEmptyWin->aTimer.Stop();
778 sal_uInt16 nRealState = pEmptyWin->nState;
779 FadeOut_Impl();
780 pEmptyWin->Hide();
781 #ifdef DBG_UTIL
782 if ( !bPinned || !pEmptyWin->bFadeIn )
784 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
786 else
788 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
790 #endif
791 pWorkWin->ReleaseChild_Impl( *GetSplitWindow() );
792 pEmptyWin->nState = nRealState;
793 pWorkWin->ArrangeAutoHideWindows( this );
796 SfxDock_Impl *pDock=0;
797 sal_uInt16 nCount = pDockArr->Count();
798 for ( sal_uInt16 n=0; n<nCount; n++ )
800 pDock = (*pDockArr)[n];
801 if ( pDock->nType == pDockWin->GetType() )
803 pDock->pWin = 0;
804 pDock->bHide = bHide;
805 break;
809 // Remove Windows, and if it was the last of the line, then also remove
810 // the line (line = itemset)
811 sal_Bool bUpdateMode = IsUpdateMode();
812 if ( bUpdateMode )
813 SetUpdateMode( sal_False );
814 bLocked = sal_True;
816 RemoveItem( pDockWin->GetType() );
818 if ( nSet && !GetItemCount( nSet ) )
819 RemoveItem( nSet );
821 if ( bUpdateMode )
822 SetUpdateMode( sal_True );
823 bLocked = sal_False;
826 //-------------------------------------------------------------------------
828 sal_Bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow* pWindow,
829 sal_uInt16& rLine, sal_uInt16& rPos ) const
830 /* [Description]
832 Returns the ID of the item sets and items for the DockingWindow in
833 the position passed on the old row / column-name.
837 sal_uInt16 nSet = GetSet ( pWindow->GetType() );
838 if ( nSet == SPLITWINDOW_ITEM_NOTFOUND )
839 return sal_False;
841 rPos = GetItemPos( pWindow->GetType(), nSet );
842 rLine = GetItemPos( nSet );
843 return sal_True;
846 //-------------------------------------------------------------------------
848 sal_Bool SfxSplitWindow::GetWindowPos( const Point& rTestPos,
849 sal_uInt16& rLine, sal_uInt16& rPos ) const
850 /* [Description]
852 Returns the ID of the item sets and items for the DockingWindow in
853 the position passed on the old row / column-name.
857 sal_uInt16 nId = GetItemId( rTestPos );
858 if ( nId == 0 )
859 return sal_False;
861 sal_uInt16 nSet = GetSet ( nId );
862 rPos = GetItemPos( nId, nSet );
863 rLine = GetItemPos( nSet );
864 return sal_True;
867 //-------------------------------------------------------------------------
869 sal_uInt16 SfxSplitWindow::GetLineCount() const
871 /* [Description]
873 Returns the number of rows = number of sub-itemsets in the root set.
876 return GetItemCount( 0 );
879 //-------------------------------------------------------------------------
881 long SfxSplitWindow::GetLineSize( sal_uInt16 nLine ) const
883 /* [Description]
885 Returns the Row Height of nline itemset.
888 sal_uInt16 nId = GetItemId( nLine );
889 return GetItemSize( nId );
892 //-------------------------------------------------------------------------
894 sal_uInt16 SfxSplitWindow::GetWindowCount( sal_uInt16 nLine ) const
896 /* [Description]
898 Returns the total number of windows
901 sal_uInt16 nId = GetItemId( nLine );
902 return GetItemCount( nId );
905 //-------------------------------------------------------------------------
907 sal_uInt16 SfxSplitWindow::GetWindowCount() const
909 /* [Description]
911 Returns the total number of windows
914 return GetItemCount( 0 );
917 //-------------------------------------------------------------------------
919 void SfxSplitWindow::Command( const CommandEvent& rCEvt )
921 SplitWindow::Command( rCEvt );
924 //-------------------------------------------------------------------------
926 IMPL_LINK( SfxSplitWindow, TimerHdl, Timer*, pTimer)
928 if ( pTimer )
929 pTimer->Stop();
931 if ( CursorIsOverRect( sal_False ) || !pTimer )
933 // If the cursor is within the window, display the SplitWindow and set
934 // up the timer for close
935 pEmptyWin->bAutoHide = sal_True;
936 if ( !IsVisible() )
937 pEmptyWin->FadeIn();
939 pEmptyWin->aLastPos = GetPointerPosPixel();
940 pEmptyWin->aTimer.Start();
942 else if ( pEmptyWin->bAutoHide )
944 if ( GetPointerPosPixel() != pEmptyWin->aLastPos )
946 // The mouse has moved within the running time of the timer, thus
947 // do nothing
948 pEmptyWin->aLastPos = GetPointerPosPixel();
949 pEmptyWin->aTimer.Start();
950 return 0L;
953 // Especially for TF_AUTOSHOW_ON_MOUSEMOVE :
954 // If the window is not visible, there is nothing to do
955 // (user has simply moved the mouse over pEmptyWin)
956 if ( IsVisible() )
958 pEmptyWin->bEndAutoHide = sal_False;
959 if ( !Application::IsInModalMode() &&
960 !PopupMenu::IsInExecute() &&
961 !pEmptyWin->bSplit && !HasChildPathFocus( sal_True ) )
963 // While a modal dialog or a popup menu is open or while the
964 // Splitting is done, in any case, do not close. Even as long
965 // as one of the Children has the focus, the window remains
966 // open.
967 pEmptyWin->bEndAutoHide = sal_True;
970 if ( pEmptyWin->bEndAutoHide )
972 // As far as I am concered this can be the end of AutoShow
973 // But maybe some other SfxSplitWindow will remain open,
974 // then all others remain open too.
975 if ( !pWorkWin->IsAutoHideMode( this ) )
977 FadeOut_Impl();
978 pWorkWin->ArrangeAutoHideWindows( this );
980 else
982 pEmptyWin->aLastPos = GetPointerPosPixel();
983 pEmptyWin->aTimer.Start();
986 else
988 pEmptyWin->aLastPos = GetPointerPosPixel();
989 pEmptyWin->aTimer.Start();
994 return 0L;
997 //-------------------------------------------------------------------------
999 sal_Bool SfxSplitWindow::CursorIsOverRect( sal_Bool bForceAdding ) const
1001 sal_Bool bVisible = IsVisible();
1003 // Also, take the collapsed SplitWindow into account
1004 Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() );
1005 Size aSize = pEmptyWin->GetSizePixel();
1007 if ( bForceAdding )
1009 // Extend with +/- a few pixels, otherwise it is too nervous
1010 aPos.X() -= nPixel;
1011 aPos.Y() -= nPixel;
1012 aSize.Width() += 2 * nPixel;
1013 aSize.Height() += 2 * nPixel;
1016 Rectangle aRect( aPos, aSize );
1018 if ( bVisible )
1020 Point aVisPos = GetPosPixel();
1021 Size aVisSize = GetSizePixel();
1023 // Extend with +/- a few pixels, otherwise it is too nervous
1024 aVisPos.X() -= nPixel;
1025 aVisPos.Y() -= nPixel;
1026 aVisSize.Width() += 2 * nPixel;
1027 aVisSize.Height() += 2 * nPixel;
1029 Rectangle aVisRect( aVisPos, aVisSize );
1030 aRect = aRect.GetUnion( aVisRect );
1033 if ( aRect.IsInside( OutputToScreenPixel( ((Window*)this)->GetPointerPosPixel() ) ) )
1034 return sal_True;
1035 return sal_False;
1038 //-------------------------------------------------------------------------
1040 SplitWindow* SfxSplitWindow::GetSplitWindow()
1042 if ( !bPinned || !pEmptyWin->bFadeIn )
1043 return pEmptyWin;
1044 return this;
1047 //-------------------------------------------------------------------------
1048 sal_Bool SfxSplitWindow::IsFadeIn() const
1050 return pEmptyWin->bFadeIn;
1053 sal_Bool SfxSplitWindow::IsAutoHide( sal_Bool bSelf ) const
1055 return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide;
1058 //-------------------------------------------------------------------------
1060 void SfxSplitWindow::SetPinned_Impl( sal_Bool bOn )
1062 if ( bPinned == bOn )
1063 return;
1065 bPinned = bOn;
1066 if ( GetItemCount( 0 ) == 0 )
1067 return;
1069 if ( !bOn )
1071 pEmptyWin->nState |= 1;
1072 if ( pEmptyWin->bFadeIn )
1074 // Unregister replacement windows
1075 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" );
1076 pWorkWin->ReleaseChild_Impl( *this );
1077 Hide();
1078 pEmptyWin->Actualize();
1079 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" );
1080 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, sal_True )->nVisible = CHILD_VISIBLE;
1083 Point aPos( GetPosPixel() );
1084 aPos = GetParent()->OutputToScreenPixel( aPos );
1085 SetFloatingPos( aPos );
1086 SetFloatingMode( sal_True );
1087 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() );
1089 if ( pEmptyWin->bFadeIn )
1090 Show();
1092 else
1094 pEmptyWin->nState &= ~1;
1095 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() );
1096 SetFloatingMode( sal_False );
1098 if ( pEmptyWin->bFadeIn )
1100 // Unregister replacement windows
1101 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
1102 pWorkWin->ReleaseChild_Impl( *pEmptyWin );
1103 pEmptyWin->Hide();
1104 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
1105 pWorkWin->RegisterChild_Impl( *this, eAlign, sal_True )->nVisible = CHILD_VISIBLE;
1109 SetAutoHideState( !bPinned );
1110 pEmptyWin->SetAutoHideState( !bPinned );
1113 //-------------------------------------------------------------------------
1115 void SfxSplitWindow::SetFadeIn_Impl( sal_Bool bOn )
1117 if ( bOn == pEmptyWin->bFadeIn )
1118 return;
1120 if ( GetItemCount( 0 ) == 0 )
1121 return;
1123 pEmptyWin->bFadeIn = bOn;
1124 if ( bOn )
1126 pEmptyWin->nState |= 2;
1127 if ( IsFloatingMode() )
1129 // FloatingWindow is not visable, thus display it
1130 pWorkWin->ArrangeAutoHideWindows( this );
1131 Show();
1133 else
1135 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1136 pWorkWin->ReleaseChild_Impl( *pEmptyWin );
1137 pEmptyWin->Hide();
1138 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
1139 pWorkWin->RegisterChild_Impl( *this, eAlign, sal_True )->nVisible = CHILD_VISIBLE;
1140 pWorkWin->ArrangeChildren_Impl();
1141 pWorkWin->ShowChildren_Impl();
1144 else
1146 pEmptyWin->bAutoHide = sal_False;
1147 pEmptyWin->nState &= ~2;
1148 if ( !IsFloatingMode() )
1150 // The window is not "floating", should be hidden
1151 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" );
1152 pWorkWin->ReleaseChild_Impl( *this );
1153 Hide();
1154 pEmptyWin->Actualize();
1155 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" );
1156 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, sal_True )->nVisible = CHILD_VISIBLE;
1157 pWorkWin->ArrangeChildren_Impl();
1158 pWorkWin->ShowChildren_Impl();
1159 pWorkWin->ArrangeAutoHideWindows( this );
1161 else
1163 Hide();
1164 pWorkWin->ArrangeAutoHideWindows( this );
1169 void SfxSplitWindow::AutoHide()
1171 // If this handler is called in the "real" SplitWindow, it is
1172 // either docked and should be displayed as floating, or vice versa
1173 if ( !bPinned )
1175 // It "floats", thus dock it again
1176 SetPinned_Impl( sal_True );
1177 pWorkWin->ArrangeChildren_Impl();
1179 else
1181 // In "limbo"
1182 SetPinned_Impl( sal_False );
1183 pWorkWin->ArrangeChildren_Impl();
1184 pWorkWin->ArrangeAutoHideWindows( this );
1187 pWorkWin->ShowChildren_Impl();
1188 SaveConfig_Impl();
1191 void SfxSplitWindow::FadeOut_Impl()
1193 if ( pEmptyWin->aTimer.IsActive() )
1195 pEmptyWin->bAutoHide = sal_False;
1196 pEmptyWin->aTimer.Stop();
1199 SetFadeIn_Impl( sal_False );
1200 Show_Impl();
1203 void SfxSplitWindow::FadeOut()
1205 FadeOut_Impl();
1206 SaveConfig_Impl();
1209 void SfxSplitWindow::FadeIn()
1211 SetFadeIn_Impl( sal_True );
1212 Show_Impl();
1215 void SfxSplitWindow::Show_Impl()
1217 sal_uInt16 nCount = pDockArr->Count();
1218 for ( sal_uInt16 n=0; n<nCount; n++ )
1220 SfxDock_Impl *pDock = (*pDockArr)[n];
1221 if ( pDock->pWin )
1222 pDock->pWin->FadeIn( pEmptyWin->bFadeIn );
1226 sal_Bool SfxSplitWindow::ActivateNextChild_Impl( sal_Bool bForward )
1228 // If no pActive, go to first and last window (!bForward is first
1229 // decremented in the loop)
1230 sal_uInt16 nCount = pDockArr->Count();
1231 sal_uInt16 n = bForward ? 0 : nCount;
1233 // if Focus is within, then move to a window forward or backwards
1234 // if possible
1235 if ( pActive )
1237 // Determine the active window
1238 for ( n=0; n<nCount; n++ )
1240 SfxDock_Impl *pD = (*pDockArr)[n];
1241 if ( pD->pWin && pD->pWin->HasChildPathFocus() )
1242 break;
1245 if ( bForward )
1246 // up window counter (then when n>nCount, the loop below is
1247 // not entered)
1248 n++;
1251 if ( bForward )
1253 // Search for next window
1254 for ( sal_uInt16 nNext=n; nNext<nCount; nNext++ )
1256 SfxDock_Impl *pD = (*pDockArr)[nNext];
1257 if ( pD->pWin )
1259 pD->pWin->GrabFocus();
1260 return sal_True;
1264 else
1266 // Search for previous window
1267 for ( sal_uInt16 nNext=n; nNext--; )
1269 SfxDock_Impl *pD = (*pDockArr)[nNext];
1270 if ( pD->pWin )
1272 pD->pWin->GrabFocus();
1273 return sal_True;
1278 return sal_False;
1281 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow* pWin )
1283 pActive = pWin;
1284 pWorkWin->SetActiveChild_Impl( this );
1288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */