Bump version to 4.1-6
[LibreOffice.git] / sfx2 / source / dialog / splitwin.cxx
blob06da27c6d411855bd04352e305b8ca73589ad4a3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifdef SOLARIS
21 #include <ctime>
22 #endif
24 #include <string>
26 #include <vcl/wrkwin.hxx>
27 #include <unotools/viewoptions.hxx>
29 #include <vcl/timer.hxx>
31 #include "splitwin.hxx"
32 #include "workwin.hxx"
33 #include <sfx2/dockwin.hxx>
34 #include <sfx2/app.hxx>
35 #include "dialog.hrc"
36 #include "sfx2/sfxresid.hxx"
37 #include <sfx2/mnumgr.hxx>
38 #include "virtmenu.hxx"
39 #include <sfx2/msgpool.hxx>
40 #include <sfx2/viewfrm.hxx>
42 #include <vector>
43 #include <utility>
45 using namespace ::com::sun::star::uno;
46 using namespace ::rtl;
48 #define VERSION 1
49 #define nPixel 30L
50 #define USERITEM_NAME OUString("UserItem")
52 namespace {
53 // helper class to deactivate UpdateMode, if needed, for the life time of an instance
54 class DeactivateUpdateMode
56 public:
57 explicit DeactivateUpdateMode( SfxSplitWindow& rSplitWindow )
58 : mrSplitWindow( rSplitWindow )
59 , mbUpdateMode( rSplitWindow.IsUpdateMode() )
61 if ( mbUpdateMode )
63 mrSplitWindow.SetUpdateMode( sal_False );
67 ~DeactivateUpdateMode( void )
69 if ( mbUpdateMode )
71 mrSplitWindow.SetUpdateMode( sal_True );
75 private:
76 SfxSplitWindow& mrSplitWindow;
77 const sal_Bool mbUpdateMode;
81 struct SfxDock_Impl
83 sal_uInt16 nType;
84 SfxDockingWindow* pWin; // SplitWindow has this window
85 sal_Bool bNewLine;
86 sal_Bool bHide; // SplitWindow had this window
87 long nSize;
90 class SfxDockArr_Impl : public std::vector<SfxDock_Impl*>
92 public:
93 ~SfxDockArr_Impl()
95 for(const_iterator it = begin(); it != end(); ++it)
96 delete *it;
101 class SfxEmptySplitWin_Impl : public SplitWindow
103 /* [Description]
105 The SfxEmptySplitWin_Impldow is an empty SplitWindow, that replaces the
106 SfxSplitWindow AutoHide mode. It only serves as a placeholder to receive
107 mouse moves and if possible blend in the true SplitWindow display.
109 friend class SfxSplitWindow;
111 SfxSplitWindow* pOwner;
112 sal_Bool bFadeIn;
113 sal_Bool bAutoHide;
114 sal_Bool bSplit;
115 sal_Bool bEndAutoHide;
116 Timer aTimer;
117 Point aLastPos;
118 sal_uInt16 nState;
120 SfxEmptySplitWin_Impl( SfxSplitWindow *pParent )
121 : SplitWindow( pParent->GetParent(), WinBits( WB_BORDER | WB_3DLOOK ) )
122 , pOwner( pParent )
123 , bFadeIn( sal_False )
124 , bAutoHide( sal_False )
125 , bSplit( sal_False )
126 , bEndAutoHide( sal_False )
127 , nState( 1 )
129 aTimer.SetTimeoutHdl(
130 LINK(pOwner, SfxSplitWindow, TimerHdl ) );
131 aTimer.SetTimeout( 200 );
132 SetAlign( pOwner->GetAlign() );
133 Actualize();
134 ShowAutoHideButton( pOwner->IsAutoHideButtonVisible() );
135 ShowFadeInHideButton( sal_True );
138 ~SfxEmptySplitWin_Impl()
140 aTimer.Stop();
143 virtual void MouseMove( const MouseEvent& );
144 virtual void AutoHide();
145 virtual void FadeIn();
146 void Actualize();
149 void SfxEmptySplitWin_Impl::Actualize()
151 Size aSize( pOwner->GetSizePixel() );
152 switch ( pOwner->GetAlign() )
154 case WINDOWALIGN_LEFT:
155 case WINDOWALIGN_RIGHT:
156 aSize.Width() = GetFadeInSize();
157 break;
158 case WINDOWALIGN_TOP:
159 case WINDOWALIGN_BOTTOM:
160 aSize.Height() = GetFadeInSize();
161 break;
164 SetSizePixel( aSize );
167 void SfxEmptySplitWin_Impl::AutoHide()
169 pOwner->SetPinned_Impl( !pOwner->bPinned );
170 pOwner->SaveConfig_Impl();
171 bAutoHide = sal_True;
172 FadeIn();
175 void SfxEmptySplitWin_Impl::FadeIn()
177 if (!bAutoHide )
178 bAutoHide = IsFadeNoButtonMode();
179 pOwner->SetFadeIn_Impl( sal_True );
180 pOwner->Show_Impl();
181 if ( bAutoHide )
183 // Set Timer to close; the caller has to ensure themselves that the
184 // Window is not closed instantly (eg by setting the focus or a modal
185 // mode.
186 aLastPos = GetPointerPosPixel();
187 aTimer.Start();
189 else
190 pOwner->SaveConfig_Impl();
193 //-------------------------------------------------------------------------
195 void SfxSplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
197 if ( rMEvt.GetClicks() != 2 )
198 SplitWindow::MouseButtonDown( rMEvt );
201 void SfxEmptySplitWin_Impl::MouseMove( const MouseEvent& rMEvt )
203 SplitWindow::MouseMove( rMEvt );
206 //-------------------------------------------------------------------------
208 SfxSplitWindow::SfxSplitWindow( Window* pParent, SfxChildAlignment eAl,
209 SfxWorkWindow *pW, sal_Bool bWithButtons, WinBits nBits )
211 /* [Description]
213 A SfxSplitWindow brings the recursive structure of the SV-SplitWindows to
214 the outside by simulating a table-like structure with rows and columns
215 (maximum recursion depth 2). Furthermore, it ensures the persistence of
216 the arrangement of the SfxDockingWindows.
219 : SplitWindow ( pParent, nBits | WB_HIDE ),
220 eAlign(eAl),
221 pWorkWin(pW),
222 pDockArr( new SfxDockArr_Impl ),
223 bLocked(sal_False),
224 bPinned(sal_True),
225 pEmptyWin(NULL),
226 pActive(NULL)
228 if ( bWithButtons )
230 ShowAutoHideButton( sal_False ); // no autohide button (pin) anymore
231 ShowFadeOutButton( sal_True );
234 // Set SV-Alignment
235 WindowAlign eTbxAlign;
236 switch ( eAlign )
238 case SFX_ALIGN_LEFT:
239 eTbxAlign = WINDOWALIGN_LEFT;
240 break;
241 case SFX_ALIGN_RIGHT:
242 eTbxAlign = WINDOWALIGN_RIGHT;
243 break;
244 case SFX_ALIGN_TOP:
245 eTbxAlign = WINDOWALIGN_TOP;
246 break;
247 case SFX_ALIGN_BOTTOM:
248 eTbxAlign = WINDOWALIGN_BOTTOM;
249 bPinned = sal_True;
250 break;
251 default:
252 eTbxAlign = WINDOWALIGN_TOP; // some sort of default...
253 break; // -Wall lots not handled..
256 SetAlign (eTbxAlign);
257 pEmptyWin = new SfxEmptySplitWin_Impl( this );
258 if ( bPinned )
260 pEmptyWin->bFadeIn = sal_True;
261 pEmptyWin->nState = 2;
264 if ( bWithButtons )
266 // Read Configuration
267 String aWindowId = OUString("SplitWindow");
268 aWindowId += OUString::number( (sal_Int32) eTbxAlign );
269 SvtViewOptions aWinOpt( E_WINDOW, aWindowId );
270 String aWinData;
271 Any aUserItem = aWinOpt.GetUserItem( USERITEM_NAME );
272 OUString aTemp;
273 if ( aUserItem >>= aTemp )
274 aWinData = String( aTemp );
275 if ( aWinData.Len() && aWinData.GetChar( (sal_uInt16) 0 ) == 'V' )
277 pEmptyWin->nState = (sal_uInt16) aWinData.GetToken( 1, ',' ).ToInt32();
278 if ( pEmptyWin->nState & 2 )
279 pEmptyWin->bFadeIn = sal_True;
280 bPinned = sal_True; // always assume pinned - floating mode not used anymore
282 sal_uInt16 i=2;
283 sal_uInt16 nCount = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32();
284 for ( sal_uInt16 n=0; n<nCount; n++ )
286 SfxDock_Impl *pDock = new SfxDock_Impl;
287 pDock->pWin = 0;
288 pDock->bNewLine = sal_False;
289 pDock->bHide = sal_True;
290 pDock->nType = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32();
291 if ( !pDock->nType )
293 // could mean NewLine
294 pDock->nType = (sal_uInt16) aWinData.GetToken(i++, ',').ToInt32();
295 if ( !pDock->nType )
297 // Read error
298 delete pDock;
299 break;
301 else
302 pDock->bNewLine = sal_True;
305 pDockArr->insert(pDockArr->begin() + n, pDock);
309 else
311 bPinned = sal_True;
312 pEmptyWin->bFadeIn = sal_True;
313 pEmptyWin->nState = 2;
316 SetAutoHideState( !bPinned );
317 pEmptyWin->SetAutoHideState( !bPinned );
320 //-------------------------------------------------------------------------
322 SfxSplitWindow::~SfxSplitWindow()
324 if ( !pWorkWin->GetParent_Impl() )
325 SaveConfig_Impl();
327 if ( pEmptyWin )
329 // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The
330 // window that is just beeing docked is always deleted from the outside.
331 pEmptyWin->pOwner = NULL;
332 delete pEmptyWin;
335 delete pDockArr;
338 void SfxSplitWindow::SaveConfig_Impl()
340 // Save configuration
341 OUStringBuffer aWinData;
342 aWinData.append('V');
343 aWinData.append(static_cast<sal_Int32>(VERSION));
344 aWinData.append(',');
345 aWinData.append(static_cast<sal_Int32>(pEmptyWin->nState));
346 aWinData.append(',');
348 sal_uInt16 nCount = 0;
349 sal_uInt16 n;
350 for ( n=0; n<pDockArr->size(); n++ )
352 SfxDock_Impl *pDock = (*pDockArr)[n];
353 if ( pDock->bHide || pDock->pWin )
354 nCount++;
357 aWinData.append(static_cast<sal_Int32>(nCount));
359 for ( n=0; n<pDockArr->size(); n++ )
361 SfxDock_Impl *pDock = (*pDockArr)[n];
362 if ( !pDock->bHide && !pDock->pWin )
363 continue;
364 if ( pDock->bNewLine )
365 aWinData.append(",0");
366 aWinData.append(',');
367 aWinData.append(static_cast<sal_Int32>(pDock->nType));
370 String aWindowId = OUString("SplitWindow");
371 aWindowId += OUString::number( (sal_Int32) GetAlign() );
372 SvtViewOptions aWinOpt( E_WINDOW, aWindowId );
373 aWinOpt.SetUserItem( USERITEM_NAME, makeAny( aWinData.makeStringAndClear() ) );
376 //-------------------------------------------------------------------------
378 void SfxSplitWindow::StartSplit()
380 long nSize = 0;
381 Size aSize = GetSizePixel();
383 if ( pEmptyWin )
385 pEmptyWin->bFadeIn = sal_True;
386 pEmptyWin->bSplit = sal_True;
389 Rectangle aRect = pWorkWin->GetFreeArea( !bPinned );
390 switch ( GetAlign() )
392 case WINDOWALIGN_LEFT:
393 case WINDOWALIGN_RIGHT:
394 nSize = aSize.Width() + aRect.GetWidth();
395 break;
396 case WINDOWALIGN_TOP:
397 case WINDOWALIGN_BOTTOM:
398 nSize = aSize.Height() + aRect.GetHeight();
399 break;
402 SetMaxSizePixel( nSize );
405 //-------------------------------------------------------------------------
407 void SfxSplitWindow::SplitResize()
409 if ( bPinned )
411 pWorkWin->ArrangeChildren_Impl();
412 pWorkWin->ShowChildren_Impl();
414 else
415 pWorkWin->ArrangeAutoHideWindows( this );
418 //-------------------------------------------------------------------------
420 void SfxSplitWindow::Split()
422 if ( pEmptyWin )
423 pEmptyWin->bSplit = sal_False;
425 SplitWindow::Split();
427 std::vector< std::pair< sal_uInt16, long > > aNewOrgSizes;
429 sal_uInt16 nCount = pDockArr->size();
430 for ( sal_uInt16 n=0; n<nCount; n++ )
432 SfxDock_Impl *pD = (*pDockArr)[n];
433 if ( pD->pWin )
435 const sal_uInt16 nId = pD->nType;
436 const long nSize = GetItemSize( nId, SWIB_FIXED );
437 const long nSetSize = GetItemSize( GetSet( nId ) );
438 Size aSize;
440 if ( IsHorizontal() )
442 aSize.Width() = nSize;
443 aSize.Height() = nSetSize;
445 else
447 aSize.Width() = nSetSize;
448 aSize.Height() = nSize;
451 pD->pWin->SetItemSize_Impl( aSize );
453 aNewOrgSizes.push_back( std::pair< sal_uInt16, long >( nId, nSize ) );
457 // workaround insuffiency of <SplitWindow> regarding dock layouting:
458 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
460 DeactivateUpdateMode aDeactivateUpdateMode( *this );
461 for ( sal_uInt16 i = 0; i < aNewOrgSizes.size(); ++i )
463 SetItemSize( aNewOrgSizes[i].first, aNewOrgSizes[i].second );
467 SaveConfig_Impl();
470 //-------------------------------------------------------------------------
472 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize)
475 To insert SfxDockingWindows just pass no position. The SfxSplitWindow
476 searches the last marked one to the passed SfxDockingWindow or appends a
477 new one at the end.
480 short nLine = -1; // so that the first window cab set nline to 0
481 sal_uInt16 nL;
482 sal_uInt16 nPos = 0;
483 sal_Bool bNewLine = sal_True;
484 sal_Bool bSaveConfig = sal_False;
485 SfxDock_Impl *pFoundDock=0;
486 sal_uInt16 nCount = pDockArr->size();
487 for ( sal_uInt16 n=0; n<nCount; n++ )
489 SfxDock_Impl *pDock = (*pDockArr)[n];
490 if ( pDock->bNewLine )
492 // The window opens a new line
493 if ( pFoundDock )
494 // But after the just inserted window
495 break;
497 // New line
498 nPos = 0;
499 bNewLine = sal_True;
502 if ( pDock->pWin )
504 // Does there exist a window now at this position
505 if ( bNewLine && !pFoundDock )
507 // Not known until now in which real line it is located
508 GetWindowPos( pDock->pWin, nL, nPos );
509 nLine = (short) nL;
512 if ( !pFoundDock )
514 // The window is located before the inserted one
515 nPos++;
518 // Line is opened
519 bNewLine = sal_False;
520 if ( pFoundDock )
521 break;
524 if ( pDock->nType == pDockWin->GetType() )
526 DBG_ASSERT( !pFoundDock && !pDock->pWin, "Window already exists!");
527 pFoundDock = pDock;
528 if ( !bNewLine )
529 break;
530 else
532 // A new line has been created but no window was found there;
533 // continue searching for a window in this line in-order to set
534 // bNewLine correctly. While doing so nline or nPos are not
535 // to be changed!
536 nLine++;
541 if ( !pFoundDock )
543 // Not found, insert at end
544 pFoundDock = new SfxDock_Impl;
545 pFoundDock->bHide = sal_True;
546 pDockArr->push_back( pFoundDock );
547 pFoundDock->nType = pDockWin->GetType();
548 nLine++;
549 nPos = 0;
550 bNewLine = sal_True;
551 pFoundDock->bNewLine = bNewLine;
552 bSaveConfig = sal_True;
555 pFoundDock->pWin = pDockWin;
556 pFoundDock->bHide = sal_False;
557 InsertWindow_Impl( pFoundDock, rSize, nLine, nPos, bNewLine );
558 if ( bSaveConfig )
559 SaveConfig_Impl();
562 //-------------------------------------------------------------------------
564 void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow *pDockWin, sal_Bool bSave)
566 // The docking window is no longer stored in the internal data.
567 SfxDock_Impl *pDock=0;
568 sal_uInt16 nCount = pDockArr->size();
569 sal_Bool bFound = sal_False;
570 for ( sal_uInt16 n=0; n<nCount; n++ )
572 pDock = (*pDockArr)[n];
573 if ( pDock->nType == pDockWin->GetType() )
575 if ( pDock->bNewLine && n<nCount-1 )
576 (*pDockArr)[n+1]->bNewLine = sal_True;
578 // Window has a position, this we forget
579 bFound = sal_True;
580 pDockArr->erase(pDockArr->begin() + n);
581 break;
585 if ( bFound )
586 delete pDock;
588 if ( bSave )
589 SaveConfig_Impl();
592 //-------------------------------------------------------------------------
594 void SfxSplitWindow::MoveWindow( SfxDockingWindow* pDockWin, const Size& rSize,
595 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine)
597 /* [Description]
599 The docking window is moved within the SplitWindows.
603 sal_uInt16 nL, nP;
604 GetWindowPos( pDockWin, nL, nP );
606 if ( nLine > nL && GetItemCount( GetItemId( nL, 0 ) ) == 1 )
608 // If the last window is removed from its line, then everything slips
609 // one line to the front!
610 nLine--;
612 RemoveWindow( pDockWin );
613 InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine );
616 //-------------------------------------------------------------------------
618 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize,
619 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine)
621 /* [Description]
623 The DockingWindow that is pushed on this SplitWindow and shall hold the
624 given position and size.
627 ReleaseWindow_Impl( pDockWin, sal_False );
628 SfxDock_Impl *pDock = new SfxDock_Impl;
629 pDock->bHide = sal_False;
630 pDock->nType = pDockWin->GetType();
631 pDock->bNewLine = bNewLine;
632 pDock->pWin = pDockWin;
634 DBG_ASSERT( nPos==0 || !bNewLine, "Wrong Paramenter!");
635 if ( bNewLine )
636 nPos = 0;
638 // The window must be inserted before the first window so that it has the
639 // same or a greater position than pDockWin.
640 sal_uInt16 nCount = pDockArr->size();
641 sal_uInt16 nLastWindowIdx(0);
643 // If no window is found, a first window is inserted
644 sal_uInt16 nInsertPos = 0;
645 for ( sal_uInt16 n=0; n<nCount; n++ )
647 SfxDock_Impl *pD = (*pDockArr)[n];
649 if (pD->pWin)
651 // A docked window has been found. If no suitable window behind the
652 // the desired insertion point s found, then insertion is done at
653 // the end.
654 nInsertPos = nCount;
655 nLastWindowIdx = n;
656 sal_uInt16 nL=0, nP=0;
657 GetWindowPos( pD->pWin, nL, nP );
659 if ( (nL == nLine && nP == nPos) || nL > nLine )
661 DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Wrong Parameter!" );
662 if ( nL == nLine && nPos == 0 && !bNewLine )
664 DBG_ASSERT(pD->bNewLine, "No new line?");
666 // The posption is pushed to nPos==0
667 pD->bNewLine = sal_False;
668 pDock->bNewLine = sal_True;
671 nInsertPos = n != 0 ? nLastWindowIdx + 1 : 0; // ignore all non-windows after the last window
672 break;
676 if (nCount != 0 && nInsertPos == nCount && nLastWindowIdx != nCount - 1)
678 nInsertPos = nLastWindowIdx + 1; // ignore all non-windows after the last window
681 pDockArr->insert(pDockArr->begin() + nInsertPos, pDock);
682 InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine );
683 SaveConfig_Impl();
686 //-------------------------------------------------------------------------
688 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl* pDock,
689 const Size& rSize,
690 sal_uInt16 nLine, sal_uInt16 nPos, sal_Bool bNewLine)
692 /* [Description]
694 Adds a DockingWindow, and causes the recalculation of the size of
695 the SplitWindows.
699 SfxDockingWindow* pDockWin = pDock->pWin;
701 sal_uInt16 nItemBits = pDockWin->GetWinBits_Impl();
703 long nWinSize, nSetSize;
704 if ( IsHorizontal() )
706 nWinSize = rSize.Width();
707 nSetSize = rSize.Height();
709 else
711 nSetSize = rSize.Width();
712 nWinSize = rSize.Height();
715 pDock->nSize = nWinSize;
717 DeactivateUpdateMode* pDeactivateUpdateMode = new DeactivateUpdateMode( *this );
719 if ( bNewLine || nLine == GetItemCount( 0 ) )
721 // An existing row should not be inserted, instead a new one
722 // will be created
724 sal_uInt16 nId = 1;
725 for ( sal_uInt16 n=0; n<GetItemCount(0); n++ )
727 if ( GetItemId(n) >= nId )
728 nId = GetItemId(n)+1;
731 // Create a new nLine:th line
732 sal_uInt16 nBits = nItemBits;
733 if ( GetAlign() == WINDOWALIGN_TOP || GetAlign() == WINDOWALIGN_BOTTOM )
734 nBits |= SWIB_COLSET;
735 InsertItem( nId, nSetSize, nLine, 0, nBits );
738 // Insert the window at line with the position nline. ItemWindowSize set to
739 // "percentage" share since the SV then does the re-sizing as expected,
740 // "pixel" actually only makes sense if also items with percentage or
741 // relative sizes are present.
742 nItemBits |= SWIB_PERCENTSIZE;
743 bLocked = sal_True;
744 sal_uInt16 nSet = GetItemId( nLine );
745 InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits );
747 // SplitWindows are once created in SFX and when inserting the first
748 // DockingWindows is made visable.
749 if ( GetItemCount( 0 ) == 1 && GetItemCount( 1 ) == 1 )
751 // The Rearranging in WorkWindow and a Show() on the SplitWindow is
752 // caues by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl)
753 if ( !bPinned && !IsFloatingMode() )
755 bPinned = sal_True;
756 sal_Bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
757 pEmptyWin->bFadeIn = sal_False;
758 SetPinned_Impl( sal_False );
759 pEmptyWin->Actualize();
760 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
761 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, sal_True )->nVisible = CHILD_VISIBLE;
762 pWorkWin->ArrangeChildren_Impl();
763 if ( bFadeIn )
764 FadeIn();
766 else
768 sal_Bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
769 pEmptyWin->bFadeIn = sal_False;
770 pEmptyWin->Actualize();
771 #ifdef DBG_UTIL
772 if ( !bPinned || !pEmptyWin->bFadeIn )
774 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
776 else
778 OSL_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
780 #endif
781 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, sal_True )->nVisible = CHILD_VISIBLE;
782 pWorkWin->ArrangeChildren_Impl();
783 if ( bFadeIn )
784 FadeIn();
787 pWorkWin->ShowChildren_Impl();
790 delete pDeactivateUpdateMode;
791 bLocked = sal_False;
793 // workaround insuffiency of <SplitWindow> regarding dock layouting:
794 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
796 std::vector< std::pair< sal_uInt16, long > > aNewOrgSizes;
797 // get FIXED item sizes
798 sal_uInt16 nCount = pDockArr->size();
799 for ( sal_uInt16 n=0; n<nCount; ++n )
801 SfxDock_Impl *pD = (*pDockArr)[n];
802 if ( pD->pWin )
804 const sal_uInt16 nId = pD->nType;
805 const long nSize = GetItemSize( nId, SWIB_FIXED );
806 aNewOrgSizes.push_back( std::pair< sal_uInt16, long >( nId, nSize ) );
809 // apply new item sizes
810 DeactivateUpdateMode aDeactivateUpdateMode( *this );
811 for ( sal_uInt16 i = 0; i < aNewOrgSizes.size(); ++i )
813 SetItemSize( aNewOrgSizes[i].first, aNewOrgSizes[i].second );
818 //-------------------------------------------------------------------------
820 void SfxSplitWindow::RemoveWindow( SfxDockingWindow* pDockWin, sal_Bool bHide )
822 /* [Description]
824 Removes a DockingWindow. If it was the last one, then the SplitWindow is
825 beeing hidden.
828 sal_uInt16 nSet = GetSet( pDockWin->GetType() );
830 // SplitWindows are once created in SFX and is made invisible after
831 // removing the last DockingWindows.
832 if ( GetItemCount( nSet ) == 1 && GetItemCount( 0 ) == 1 )
834 // The Rearranging in WorkWindow is caues by SfxDockingwindow
835 Hide();
836 pEmptyWin->aTimer.Stop();
837 sal_uInt16 nRealState = pEmptyWin->nState;
838 FadeOut_Impl();
839 pEmptyWin->Hide();
840 #ifdef DBG_UTIL
841 if ( !bPinned || !pEmptyWin->bFadeIn )
843 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
845 else
847 OSL_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
849 #endif
850 pWorkWin->ReleaseChild_Impl( *GetSplitWindow() );
851 pEmptyWin->nState = nRealState;
852 pWorkWin->ArrangeAutoHideWindows( this );
855 SfxDock_Impl *pDock=0;
856 sal_uInt16 nCount = pDockArr->size();
857 for ( sal_uInt16 n=0; n<nCount; n++ )
859 pDock = (*pDockArr)[n];
860 if ( pDock->nType == pDockWin->GetType() )
862 pDock->pWin = 0;
863 pDock->bHide = bHide;
864 break;
868 // Remove Windows, and if it was the last of the line, then also remove
869 // the line (line = itemset)
870 DeactivateUpdateMode* pDeactivateUpdateMode = new DeactivateUpdateMode( *this );
871 bLocked = sal_True;
873 RemoveItem( pDockWin->GetType() );
875 if ( nSet && !GetItemCount( nSet ) )
876 RemoveItem( nSet );
878 delete pDeactivateUpdateMode;
879 bLocked = sal_False;
882 //-------------------------------------------------------------------------
884 sal_Bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow* pWindow,
885 sal_uInt16& rLine, sal_uInt16& rPos ) const
886 /* [Description]
888 Returns the ID of the item sets and items for the DockingWindow in
889 the position passed on the old row / column-name.
893 sal_uInt16 nSet = GetSet ( pWindow->GetType() );
894 if ( nSet == SPLITWINDOW_ITEM_NOTFOUND )
895 return sal_False;
897 rPos = GetItemPos( pWindow->GetType(), nSet );
898 rLine = GetItemPos( nSet );
899 return sal_True;
902 //-------------------------------------------------------------------------
904 sal_Bool SfxSplitWindow::GetWindowPos( const Point& rTestPos,
905 sal_uInt16& rLine, sal_uInt16& rPos ) const
906 /* [Description]
908 Returns the ID of the item sets and items for the DockingWindow in
909 the position passed on the old row / column-name.
913 sal_uInt16 nId = GetItemId( rTestPos );
914 if ( nId == 0 )
915 return sal_False;
917 sal_uInt16 nSet = GetSet ( nId );
918 rPos = GetItemPos( nId, nSet );
919 rLine = GetItemPos( nSet );
920 return sal_True;
923 //-------------------------------------------------------------------------
925 sal_uInt16 SfxSplitWindow::GetLineCount() const
927 /* [Description]
929 Returns the number of rows = number of sub-itemsets in the root set.
932 return GetItemCount( 0 );
935 //-------------------------------------------------------------------------
937 long SfxSplitWindow::GetLineSize( sal_uInt16 nLine ) const
939 /* [Description]
941 Returns the Row Height of nline itemset.
944 sal_uInt16 nId = GetItemId( nLine );
945 return GetItemSize( nId );
948 //-------------------------------------------------------------------------
950 sal_uInt16 SfxSplitWindow::GetWindowCount( sal_uInt16 nLine ) const
952 /* [Description]
954 Returns the total number of windows
957 sal_uInt16 nId = GetItemId( nLine );
958 return GetItemCount( nId );
961 //-------------------------------------------------------------------------
963 sal_uInt16 SfxSplitWindow::GetWindowCount() const
965 /* [Description]
967 Returns the total number of windows
970 return GetItemCount( 0 );
973 //-------------------------------------------------------------------------
975 void SfxSplitWindow::Command( const CommandEvent& rCEvt )
977 SplitWindow::Command( rCEvt );
980 //-------------------------------------------------------------------------
982 IMPL_LINK( SfxSplitWindow, TimerHdl, Timer*, pTimer)
984 if ( pTimer )
985 pTimer->Stop();
987 if ( CursorIsOverRect( sal_False ) || !pTimer )
989 // If the cursor is within the window, display the SplitWindow and set
990 // up the timer for close
991 pEmptyWin->bAutoHide = sal_True;
992 if ( !IsVisible() )
993 pEmptyWin->FadeIn();
995 pEmptyWin->aLastPos = GetPointerPosPixel();
996 pEmptyWin->aTimer.Start();
998 else if ( pEmptyWin->bAutoHide )
1000 if ( GetPointerPosPixel() != pEmptyWin->aLastPos )
1002 // The mouse has moved within the running time of the timer, thus
1003 // do nothing
1004 pEmptyWin->aLastPos = GetPointerPosPixel();
1005 pEmptyWin->aTimer.Start();
1006 return 0L;
1009 // Especially for TF_AUTOSHOW_ON_MOUSEMOVE :
1010 // If the window is not visible, there is nothing to do
1011 // (user has simply moved the mouse over pEmptyWin)
1012 if ( IsVisible() )
1014 pEmptyWin->bEndAutoHide = sal_False;
1015 if ( !Application::IsInModalMode() &&
1016 !PopupMenu::IsInExecute() &&
1017 !pEmptyWin->bSplit && !HasChildPathFocus( sal_True ) )
1019 // While a modal dialog or a popup menu is open or while the
1020 // Splitting is done, in any case, do not close. Even as long
1021 // as one of the Children has the focus, the window remains
1022 // open.
1023 pEmptyWin->bEndAutoHide = sal_True;
1026 if ( pEmptyWin->bEndAutoHide )
1028 // As far as I am concered this can be the end of AutoShow
1029 // But maybe some other SfxSplitWindow will remain open,
1030 // then all others remain open too.
1031 if ( !pWorkWin->IsAutoHideMode( this ) )
1033 FadeOut_Impl();
1034 pWorkWin->ArrangeAutoHideWindows( this );
1036 else
1038 pEmptyWin->aLastPos = GetPointerPosPixel();
1039 pEmptyWin->aTimer.Start();
1042 else
1044 pEmptyWin->aLastPos = GetPointerPosPixel();
1045 pEmptyWin->aTimer.Start();
1050 return 0L;
1053 //-------------------------------------------------------------------------
1055 sal_Bool SfxSplitWindow::CursorIsOverRect( sal_Bool bForceAdding ) const
1057 sal_Bool bVisible = IsVisible();
1059 // Also, take the collapsed SplitWindow into account
1060 Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() );
1061 Size aSize = pEmptyWin->GetSizePixel();
1063 if ( bForceAdding )
1065 // Extend with +/- a few pixels, otherwise it is too nervous
1066 aPos.X() -= nPixel;
1067 aPos.Y() -= nPixel;
1068 aSize.Width() += 2 * nPixel;
1069 aSize.Height() += 2 * nPixel;
1072 Rectangle aRect( aPos, aSize );
1074 if ( bVisible )
1076 Point aVisPos = GetPosPixel();
1077 Size aVisSize = GetSizePixel();
1079 // Extend with +/- a few pixels, otherwise it is too nervous
1080 aVisPos.X() -= nPixel;
1081 aVisPos.Y() -= nPixel;
1082 aVisSize.Width() += 2 * nPixel;
1083 aVisSize.Height() += 2 * nPixel;
1085 Rectangle aVisRect( aVisPos, aVisSize );
1086 aRect = aRect.GetUnion( aVisRect );
1089 if ( aRect.IsInside( OutputToScreenPixel( ((Window*)this)->GetPointerPosPixel() ) ) )
1090 return sal_True;
1091 return sal_False;
1094 //-------------------------------------------------------------------------
1096 SplitWindow* SfxSplitWindow::GetSplitWindow()
1098 if ( !bPinned || !pEmptyWin->bFadeIn )
1099 return pEmptyWin;
1100 return this;
1103 //-------------------------------------------------------------------------
1104 sal_Bool SfxSplitWindow::IsFadeIn() const
1106 return pEmptyWin->bFadeIn;
1109 sal_Bool SfxSplitWindow::IsAutoHide( sal_Bool bSelf ) const
1111 return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide;
1114 //-------------------------------------------------------------------------
1116 void SfxSplitWindow::SetPinned_Impl( sal_Bool bOn )
1118 if ( bPinned == bOn )
1119 return;
1121 bPinned = bOn;
1122 if ( GetItemCount( 0 ) == 0 )
1123 return;
1125 if ( !bOn )
1127 pEmptyWin->nState |= 1;
1128 if ( pEmptyWin->bFadeIn )
1130 // Unregister replacement windows
1131 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" );
1132 pWorkWin->ReleaseChild_Impl( *this );
1133 Hide();
1134 pEmptyWin->Actualize();
1135 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" );
1136 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, sal_True )->nVisible = CHILD_VISIBLE;
1139 Point aPos( GetPosPixel() );
1140 aPos = GetParent()->OutputToScreenPixel( aPos );
1141 SetFloatingPos( aPos );
1142 SetFloatingMode( sal_True );
1143 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() );
1145 if ( pEmptyWin->bFadeIn )
1146 Show();
1148 else
1150 pEmptyWin->nState &= ~1;
1151 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() );
1152 SetFloatingMode( sal_False );
1154 if ( pEmptyWin->bFadeIn )
1156 // Unregister replacement windows
1157 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
1158 pWorkWin->ReleaseChild_Impl( *pEmptyWin );
1159 pEmptyWin->Hide();
1160 OSL_TRACE( "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
1161 pWorkWin->RegisterChild_Impl( *this, eAlign, sal_True )->nVisible = CHILD_VISIBLE;
1165 SetAutoHideState( !bPinned );
1166 pEmptyWin->SetAutoHideState( !bPinned );
1169 //-------------------------------------------------------------------------
1171 void SfxSplitWindow::SetFadeIn_Impl( sal_Bool bOn )
1173 if ( bOn == pEmptyWin->bFadeIn )
1174 return;
1176 if ( GetItemCount( 0 ) == 0 )
1177 return;
1179 pEmptyWin->bFadeIn = bOn;
1180 if ( bOn )
1182 pEmptyWin->nState |= 2;
1183 if ( IsFloatingMode() )
1185 // FloatingWindow is not visable, thus display it
1186 pWorkWin->ArrangeAutoHideWindows( this );
1187 Show();
1189 else
1191 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1192 pWorkWin->ReleaseChild_Impl( *pEmptyWin );
1193 pEmptyWin->Hide();
1194 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
1195 pWorkWin->RegisterChild_Impl( *this, eAlign, sal_True )->nVisible = CHILD_VISIBLE;
1196 pWorkWin->ArrangeChildren_Impl();
1197 pWorkWin->ShowChildren_Impl();
1200 else
1202 pEmptyWin->bAutoHide = sal_False;
1203 pEmptyWin->nState &= ~2;
1204 if ( !IsFloatingMode() )
1206 // The window is not "floating", should be hidden
1207 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" );
1208 pWorkWin->ReleaseChild_Impl( *this );
1209 Hide();
1210 pEmptyWin->Actualize();
1211 OSL_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" );
1212 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, sal_True )->nVisible = CHILD_VISIBLE;
1213 pWorkWin->ArrangeChildren_Impl();
1214 pWorkWin->ShowChildren_Impl();
1215 pWorkWin->ArrangeAutoHideWindows( this );
1217 else
1219 Hide();
1220 pWorkWin->ArrangeAutoHideWindows( this );
1225 void SfxSplitWindow::AutoHide()
1227 // If this handler is called in the "real" SplitWindow, it is
1228 // either docked and should be displayed as floating, or vice versa
1229 if ( !bPinned )
1231 // It "floats", thus dock it again
1232 SetPinned_Impl( sal_True );
1233 pWorkWin->ArrangeChildren_Impl();
1235 else
1237 // In "limbo"
1238 SetPinned_Impl( sal_False );
1239 pWorkWin->ArrangeChildren_Impl();
1240 pWorkWin->ArrangeAutoHideWindows( this );
1243 pWorkWin->ShowChildren_Impl();
1244 SaveConfig_Impl();
1247 void SfxSplitWindow::FadeOut_Impl()
1249 if ( pEmptyWin->aTimer.IsActive() )
1251 pEmptyWin->bAutoHide = sal_False;
1252 pEmptyWin->aTimer.Stop();
1255 SetFadeIn_Impl( sal_False );
1256 Show_Impl();
1259 void SfxSplitWindow::FadeOut()
1261 FadeOut_Impl();
1262 SaveConfig_Impl();
1265 void SfxSplitWindow::FadeIn()
1267 SetFadeIn_Impl( sal_True );
1268 Show_Impl();
1271 void SfxSplitWindow::Show_Impl()
1273 sal_uInt16 nCount = pDockArr->size();
1274 for ( sal_uInt16 n=0; n<nCount; n++ )
1276 SfxDock_Impl *pDock = (*pDockArr)[n];
1277 if ( pDock->pWin )
1278 pDock->pWin->FadeIn( pEmptyWin->bFadeIn );
1282 sal_Bool SfxSplitWindow::ActivateNextChild_Impl( sal_Bool bForward )
1284 // If no pActive, go to first and last window (!bForward is first
1285 // decremented in the loop)
1286 sal_uInt16 nCount = pDockArr->size();
1287 sal_uInt16 n = bForward ? 0 : nCount;
1289 // if Focus is within, then move to a window forward or backwards
1290 // if possible
1291 if ( pActive )
1293 // Determine the active window
1294 for ( n=0; n<nCount; n++ )
1296 SfxDock_Impl *pD = (*pDockArr)[n];
1297 if ( pD->pWin && pD->pWin->HasChildPathFocus() )
1298 break;
1301 if ( bForward )
1302 // up window counter (then when n>nCount, the loop below is
1303 // not entered)
1304 n++;
1307 if ( bForward )
1309 // Search for next window
1310 for ( sal_uInt16 nNext=n; nNext<nCount; nNext++ )
1312 SfxDock_Impl *pD = (*pDockArr)[nNext];
1313 if ( pD->pWin )
1315 pD->pWin->GrabFocus();
1316 return sal_True;
1320 else
1322 // Search for previous window
1323 for ( sal_uInt16 nNext=n; nNext--; )
1325 SfxDock_Impl *pD = (*pDockArr)[nNext];
1326 if ( pD->pWin )
1328 pD->pWin->GrabFocus();
1329 return sal_True;
1334 return sal_False;
1337 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow* pWin )
1339 pActive = pWin;
1340 pWorkWin->SetActiveChild_Impl( this );
1344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */