summaryrefslogtreecommitdiff
path: root/sfx2/source/dialog/splitwin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/dialog/splitwin.cxx')
-rw-r--r--sfx2/source/dialog/splitwin.cxx1304
1 files changed, 1304 insertions, 0 deletions
diff --git a/sfx2/source/dialog/splitwin.cxx b/sfx2/source/dialog/splitwin.cxx
new file mode 100644
index 000000000000..f6e5f96cf0bd
--- /dev/null
+++ b/sfx2/source/dialog/splitwin.cxx
@@ -0,0 +1,1304 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sfx2.hxx"
+
+#ifdef SOLARIS
+// HACK: prevent conflict between STLPORT and Workshop headers on Solaris 8
+#include <ctime>
+#endif
+
+#include <string> // HACK: prevent conflict between STLPORT and Workshop headers
+
+#ifndef _WRKWIN_HXX //autogen
+#include <vcl/wrkwin.hxx>
+#endif
+#include <unotools/viewoptions.hxx>
+#ifndef GCC
+#endif
+
+#include <vcl/timer.hxx>
+
+#include "splitwin.hxx"
+#include "workwin.hxx"
+#include <sfx2/dockwin.hxx>
+#include <sfx2/app.hxx>
+#include "dialog.hrc"
+#include "sfxresid.hxx"
+#include <sfx2/mnumgr.hxx>
+#include "virtmenu.hxx"
+#include <sfx2/msgpool.hxx>
+#include <sfx2/viewfrm.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::rtl;
+
+#define VERSION 1
+#define nPixel 30L
+#define USERITEM_NAME OUString::createFromAscii( "UserItem" )
+
+struct SfxDock_Impl
+{
+ USHORT nType;
+ SfxDockingWindow* pWin; // SplitWindow hat dieses Fenster
+ BOOL bNewLine;
+ BOOL bHide; // SplitWindow hatte dieses Fenster
+ long nSize;
+};
+
+typedef SfxDock_Impl* SfxDockPtr;
+SV_DECL_PTRARR_DEL( SfxDockArr_Impl, SfxDockPtr, 4, 4)
+SV_IMPL_PTRARR( SfxDockArr_Impl, SfxDockPtr);
+
+class SfxEmptySplitWin_Impl : public SplitWindow
+{
+/* [Beschreibung]
+
+ Das SfxEmptySplitWin_Impldow ist ein leeres SplitWindow, das das SfxSplitWindow
+ im AutoHide-Modus ersetzt. Es dient nur als Platzhalter, um MouseMoves
+ zu empfangen und ggf. das eigentlichte SplitWindow einzublenden
+*/
+friend class SfxSplitWindow;
+
+ SfxSplitWindow* pOwner;
+ BOOL bFadeIn;
+ BOOL bAutoHide;
+ BOOL bSplit;
+ BOOL bEndAutoHide;
+ Timer aTimer;
+ Point aLastPos;
+ USHORT nState;
+
+ SfxEmptySplitWin_Impl( SfxSplitWindow *pParent )
+ : SplitWindow( pParent->GetParent(), WinBits( WB_BORDER | WB_3DLOOK ) )
+ , pOwner( pParent )
+ , bFadeIn( FALSE )
+ , bAutoHide( FALSE )
+ , bSplit( FALSE )
+ , bEndAutoHide( FALSE )
+ , nState( 1 )
+ {
+ aTimer.SetTimeoutHdl(
+ LINK(pOwner, SfxSplitWindow, TimerHdl ) );
+ aTimer.SetTimeout( 200 );
+// EnableDrop( TRUE );
+ SetAlign( pOwner->GetAlign() );
+ Actualize();
+ ShowAutoHideButton( pOwner->IsAutoHideButtonVisible() );
+ ShowFadeInHideButton( TRUE );
+ }
+
+ ~SfxEmptySplitWin_Impl()
+ {
+ aTimer.Stop();
+ }
+
+ virtual void MouseMove( const MouseEvent& );
+ virtual void AutoHide();
+ virtual void FadeIn();
+ void Actualize();
+};
+
+void SfxEmptySplitWin_Impl::Actualize()
+{
+ Size aSize( pOwner->GetSizePixel() );
+ switch ( pOwner->GetAlign() )
+ {
+ case WINDOWALIGN_LEFT:
+ case WINDOWALIGN_RIGHT:
+ aSize.Width() = GetFadeInSize();
+ break;
+ case WINDOWALIGN_TOP:
+ case WINDOWALIGN_BOTTOM:
+ aSize.Height() = GetFadeInSize();
+ break;
+ }
+
+ SetSizePixel( aSize );
+}
+
+void SfxEmptySplitWin_Impl::AutoHide()
+{
+ pOwner->SetPinned_Impl( !pOwner->bPinned );
+ pOwner->SaveConfig_Impl();
+ bAutoHide = TRUE;
+ FadeIn();
+}
+
+void SfxEmptySplitWin_Impl::FadeIn()
+{
+ if (!bAutoHide )
+ bAutoHide = IsFadeNoButtonMode();
+ pOwner->SetFadeIn_Impl( TRUE );
+ pOwner->Show_Impl();
+ if ( bAutoHide )
+ {
+ // Timer zum Schlie\sen aufsetzen; der Aufrufer mu\s selbst sicherstellen,
+ // da\s das Window nicht gleich wieder zu geht ( z.B. durch Setzen des
+ // Focus oder einen modal mode )
+ aLastPos = GetPointerPosPixel();
+ aTimer.Start();
+ }
+ else
+ pOwner->SaveConfig_Impl();
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.GetClicks() != 2 )
+ SplitWindow::MouseButtonDown( rMEvt );
+}
+
+void SfxEmptySplitWin_Impl::MouseMove( const MouseEvent& rMEvt )
+{
+ SplitWindow::MouseMove( rMEvt );
+}
+
+//-------------------------------------------------------------------------
+
+SfxSplitWindow::SfxSplitWindow( Window* pParent, SfxChildAlignment eAl,
+ SfxWorkWindow *pW, BOOL bWithButtons, WinBits nBits )
+
+/* [Beschreibung]
+
+ Ein SfxSplitWindow verbirgt die rekursive Struktur des SV-Splitwindows
+ nach au\sen, indem es einen tabellenartigen Aufbau mit Zeilen und Spalten
+ ( also maximale Rekursionstiefe 2 ) simuliert.
+ Au\erdem sichert es die Persistenz der Anordnung der SfxDockingWindows.
+*/
+
+: SplitWindow ( pParent, nBits | WB_HIDE ),
+ eAlign(eAl),
+ pWorkWin(pW),
+ pDockArr( new SfxDockArr_Impl ),
+ bLocked(FALSE),
+ bPinned(TRUE),
+ pEmptyWin(NULL),
+ pActive(NULL)
+{
+ if ( bWithButtons )
+ {
+ ShowAutoHideButton( FALSE ); // no autohide button (pin) anymore
+ ShowFadeOutButton( TRUE );
+ }
+
+ // SV-Alignment setzen
+ WindowAlign eTbxAlign;
+ switch ( eAlign )
+ {
+ case SFX_ALIGN_LEFT:
+ eTbxAlign = WINDOWALIGN_LEFT;
+ break;
+ case SFX_ALIGN_RIGHT:
+ eTbxAlign = WINDOWALIGN_RIGHT;
+ break;
+ case SFX_ALIGN_TOP:
+ eTbxAlign = WINDOWALIGN_TOP;
+ break;
+ case SFX_ALIGN_BOTTOM:
+ eTbxAlign = WINDOWALIGN_BOTTOM;
+ bPinned = TRUE;
+ break;
+ default:
+ eTbxAlign = WINDOWALIGN_TOP; // some sort of default...
+ break; // -Wall lots not handled..
+ }
+
+ SetAlign (eTbxAlign);
+ pEmptyWin = new SfxEmptySplitWin_Impl( this );
+ if ( bPinned )
+ {
+ pEmptyWin->bFadeIn = TRUE;
+ pEmptyWin->nState = 2;
+ }
+
+ if ( bWithButtons )
+ {
+ // Konfiguration einlesen
+ String aWindowId = String::CreateFromAscii("SplitWindow");
+ aWindowId += String::CreateFromInt32( (sal_Int32) eTbxAlign );
+ SvtViewOptions aWinOpt( E_WINDOW, aWindowId );
+ String aWinData;
+ Any aUserItem = aWinOpt.GetUserItem( USERITEM_NAME );
+ OUString aTemp;
+ if ( aUserItem >>= aTemp )
+ aWinData = String( aTemp );
+ if ( aWinData.Len() && aWinData.GetChar( (USHORT) 0 ) == 'V' )
+ {
+ pEmptyWin->nState = (USHORT) aWinData.GetToken( 1, ',' ).ToInt32();
+ if ( pEmptyWin->nState & 2 )
+ pEmptyWin->bFadeIn = TRUE;
+ //bPinned = !( pEmptyWin->nState & 1 );
+ bPinned = TRUE; // always assume pinned - floating mode not used anymore
+
+ USHORT i=2;
+ USHORT nCount = (USHORT) aWinData.GetToken(i++, ',').ToInt32();
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ SfxDock_Impl *pDock = new SfxDock_Impl;
+ pDock->pWin = 0;
+ pDock->bNewLine = FALSE;
+ pDock->bHide = TRUE;
+ pDock->nType = (USHORT) aWinData.GetToken(i++, ',').ToInt32();
+ if ( !pDock->nType )
+ {
+ // K"onnte NewLine bedeuten
+ pDock->nType = (USHORT) aWinData.GetToken(i++, ',').ToInt32();
+ if ( !pDock->nType )
+ {
+ // Lesefehler
+ delete pDock;
+ break;
+ }
+ else
+ pDock->bNewLine = TRUE;
+ }
+
+ pDockArr->Insert(pDock,n);
+ }
+ }
+ }
+ else
+ {
+ bPinned = TRUE;
+ pEmptyWin->bFadeIn = TRUE;
+ pEmptyWin->nState = 2;
+ }
+
+ SetAutoHideState( !bPinned );
+ pEmptyWin->SetAutoHideState( !bPinned );
+}
+
+//-------------------------------------------------------------------------
+
+SfxSplitWindow::~SfxSplitWindow()
+{
+ if ( !pWorkWin->GetParent_Impl() )
+ SaveConfig_Impl();
+
+ if ( pEmptyWin )
+ {
+ // pOwner auf NULL setzen, sonst versucht pEmptyWin, nochmal zu
+ // l"oschen; es wird n"amlich von au\sen immer das Fenster deleted,
+ // das gerade angedockt ist
+ pEmptyWin->pOwner = NULL;
+ delete pEmptyWin;
+ }
+
+ delete pDockArr;
+}
+
+void SfxSplitWindow::SaveConfig_Impl()
+{
+ // Konfiguration abspeichern
+ String aWinData('V');
+ aWinData += String::CreateFromInt32( VERSION );
+ aWinData += ',';
+ aWinData += String::CreateFromInt32( pEmptyWin->nState );
+ aWinData += ',';
+
+ USHORT nCount = 0;
+ USHORT n;
+ for ( n=0; n<pDockArr->Count(); n++ )
+ {
+ SfxDock_Impl *pDock = (*pDockArr)[n];
+ if ( pDock->bHide || pDock->pWin )
+ nCount++;
+ }
+
+ aWinData += String::CreateFromInt32( nCount );
+
+ for ( n=0; n<pDockArr->Count(); n++ )
+ {
+ SfxDock_Impl *pDock = (*pDockArr)[n];
+ if ( !pDock->bHide && !pDock->pWin )
+ continue;
+ if ( pDock->bNewLine )
+ aWinData += DEFINE_CONST_UNICODE(",0");
+ aWinData += ',';
+ aWinData += String::CreateFromInt32( pDock->nType);
+ }
+
+ String aWindowId = String::CreateFromAscii("SplitWindow");
+ aWindowId += String::CreateFromInt32( (sal_Int32) GetAlign() );
+ SvtViewOptions aWinOpt( E_WINDOW, aWindowId );
+ aWinOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aWinData ) ) );
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::StartSplit()
+{
+ long nSize = 0;
+ Size aSize = GetSizePixel();
+
+ if ( pEmptyWin )
+ {
+ pEmptyWin->bFadeIn = TRUE;
+ pEmptyWin->bSplit = TRUE;
+ }
+
+ Rectangle aRect = pWorkWin->GetFreeArea( !bPinned );
+ switch ( GetAlign() )
+ {
+ case WINDOWALIGN_LEFT:
+ case WINDOWALIGN_RIGHT:
+ nSize = aSize.Width() + aRect.GetWidth();
+ break;
+ case WINDOWALIGN_TOP:
+ case WINDOWALIGN_BOTTOM:
+ nSize = aSize.Height() + aRect.GetHeight();
+ break;
+ }
+
+ SetMaxSizePixel( nSize );
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::SplitResize()
+{
+ if ( bPinned )
+ {
+ pWorkWin->ArrangeChilds_Impl();
+ pWorkWin->ShowChilds_Impl();
+ }
+ else
+ pWorkWin->ArrangeAutoHideWindows( this );
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::Split()
+{
+ if ( pEmptyWin )
+ pEmptyWin->bSplit = FALSE;
+
+ SplitWindow::Split();
+
+ USHORT nCount = pDockArr->Count();
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ SfxDock_Impl *pD = (*pDockArr)[n];
+ if ( pD->pWin )
+ {
+ USHORT nId = pD->nType;
+ long nSize = GetItemSize( nId, SWIB_FIXED );
+ long nSetSize = GetItemSize( GetSet( nId ) );
+ Size aSize;
+
+ if ( IsHorizontal() )
+ {
+ aSize.Width() = nSize;
+ aSize.Height() = nSetSize;
+ }
+ else
+ {
+ aSize.Width() = nSetSize;
+ aSize.Height() = nSize;
+ }
+
+ pD->pWin->SetItemSize_Impl( aSize );
+ }
+ }
+
+ SaveConfig_Impl();
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize)
+
+/* [Beschreibung]
+
+ Zum Einf"ugen von SfxDockingWindows kann auch keine Position "ubergeben
+ werden. Das SfxSplitWindow sucht dann die zuletzt gemerkte zu dem
+ "ubergebenen SfxDockingWindow heraus oder h"angt es als letztes neu an.
+
+*/
+{
+ short nLine = -1; // damit erstes Fenster nLine auf 0 hochsetzen kann
+ USHORT nL;
+ USHORT nPos = 0;
+ BOOL bNewLine = TRUE;
+ BOOL bSaveConfig = FALSE;
+ SfxDock_Impl *pFoundDock=0;
+ USHORT nCount = pDockArr->Count();
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ SfxDock_Impl *pDock = (*pDockArr)[n];
+ if ( pDock->bNewLine )
+ {
+ // Das Fenster er"offnet eine neue Zeile
+ if ( pFoundDock )
+ // Aber hinter dem gerade eingef"ugten Fenster
+ break;
+
+ // Neue Zeile
+ nPos = 0;
+ bNewLine = TRUE;
+ }
+
+ if ( pDock->pWin )
+ {
+ // Es gibt an dieser Stelle gerade ein Fenster
+ if ( bNewLine && !pFoundDock )
+ {
+ // Bisher ist nicht bekannt, in welcher realen Zeile es liegt
+ GetWindowPos( pDock->pWin, nL, nPos );
+ nLine = (short) nL;
+ }
+
+ if ( !pFoundDock )
+ {
+ // Fenster liegt vor dem eingef"ugten
+ nPos++;
+ }
+
+ // Zeile ist schon er"offnet
+ bNewLine = FALSE;
+ if ( pFoundDock )
+ break;
+ }
+
+ if ( pDock->nType == pDockWin->GetType() )
+ {
+ DBG_ASSERT( !pFoundDock && !pDock->pWin, "Fenster ist schon vorhanden!");
+ pFoundDock = pDock;
+ if ( !bNewLine )
+ break;
+ else
+ {
+ // Es wurde zuletzt eine neue Reihe gestartet, aber noch kein
+ // darin liegendes Fenster gefunden; daher weitersuchen, ob noch
+ // ein Fenster in dieser Zeile folgt, um bNewLine korrekt zu setzen.
+ // Dabei darf aber nLine oder nPos nicht mehr ver"andert werden!
+ nLine++;
+ }
+ }
+ }
+
+ if ( !pFoundDock )
+ {
+ // Nicht gefunden, am Ende einf"ugen
+ pFoundDock = new SfxDock_Impl;
+ pFoundDock->bHide = TRUE;
+ pDockArr->Insert( pFoundDock, nCount );
+ pFoundDock->nType = pDockWin->GetType();
+ nLine++;
+ nPos = 0;
+ bNewLine = TRUE;
+ pFoundDock->bNewLine = bNewLine;
+ bSaveConfig = TRUE;
+ }
+
+ pFoundDock->pWin = pDockWin;
+ pFoundDock->bHide = FALSE;
+ InsertWindow_Impl( pFoundDock, rSize, nLine, nPos, bNewLine );
+ if ( bSaveConfig )
+ SaveConfig_Impl();
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow *pDockWin, BOOL bSave)
+
+/* [Beschreibung]
+
+ Das DockingWindow wird nicht mehr in den internen Daten gespeichert.
+*/
+
+{
+ SfxDock_Impl *pDock=0;
+ USHORT nCount = pDockArr->Count();
+ BOOL bFound = FALSE;
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ pDock = (*pDockArr)[n];
+ if ( pDock->nType == pDockWin->GetType() )
+ {
+ if ( pDock->bNewLine && n<nCount-1 )
+ (*pDockArr)[n+1]->bNewLine = TRUE;
+
+ // Fenster hat schon eine Position, die vergessen wir
+ bFound = TRUE;
+ pDockArr->Remove(n);
+ break;
+ }
+ }
+
+ if ( bFound )
+ delete pDock;
+
+ if ( bSave )
+ SaveConfig_Impl();
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::MoveWindow( SfxDockingWindow* pDockWin, const Size& rSize,
+ USHORT nLine, USHORT nPos, BOOL bNewLine)
+
+/* [Beschreibung]
+
+ Das DockingWindow wird innerhalb des Splitwindows verschoben.
+
+*/
+
+{
+ USHORT nL, nP;
+ GetWindowPos( pDockWin, nL, nP );
+
+ if ( nLine > nL && GetItemCount( GetItemId( nL, 0 ) ) == 1 )
+ {
+ // Wenn das letzte Fenster aus seiner Zeile entfernt wird, rutscht
+ // alles eine Zeile nach vorne!
+ nLine--;
+ }
+/*
+ else if ( nLine == nL && nPos > nP )
+ {
+ nPos--;
+ }
+*/
+ RemoveWindow( pDockWin );
+ InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine );
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize,
+ USHORT nLine, USHORT nPos, BOOL bNewLine)
+
+/* [Beschreibung]
+
+ Das DockingWindow wird in dieses Splitwindow geschoben und soll die
+ "ubergebene Position und Gr"o\se haben.
+
+*/
+{
+ ReleaseWindow_Impl( pDockWin, FALSE );
+ SfxDock_Impl *pDock = new SfxDock_Impl;
+ pDock->bHide = FALSE;
+ pDock->nType = pDockWin->GetType();
+ pDock->bNewLine = bNewLine;
+ pDock->pWin = pDockWin;
+
+ DBG_ASSERT( nPos==0 || !bNewLine, "Falsche Paramenter!");
+ if ( bNewLine )
+ nPos = 0;
+
+ // Das Fenster mu\s vor dem ersten Fenster eingef"ugt werden, das die
+ // gleiche oder eine gr"o\sere Position hat als pDockWin.
+ USHORT nCount = pDockArr->Count();
+
+ // Wenn gar kein Fenster gefunden wird, wird als erstes eingef"ugt
+ USHORT nInsertPos = 0;
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ SfxDock_Impl *pD = (*pDockArr)[n];
+
+ if (pD->pWin)
+ {
+ // Ein angedocktes Fenster wurde gefunden
+ // Wenn kein geeignetes Fenster hinter der gew"unschten Einf"ugeposition
+ // gefunden wird, wird am Ende eingef"ugt
+ nInsertPos = nCount;
+ USHORT nL=0, nP=0;
+ GetWindowPos( pD->pWin, nL, nP );
+
+ if ( (nL == nLine && nP == nPos) || nL > nLine )
+ {
+ DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Falsche Parameter!" );
+ if ( nL == nLine && nPos == 0 && !bNewLine )
+ {
+ DBG_ASSERT(pD->bNewLine, "Keine neue Zeile?");
+
+ // Das Fenster wird auf nPos==0 eingeschoben
+ pD->bNewLine = FALSE;
+ pDock->bNewLine = TRUE;
+ }
+
+ nInsertPos = n;
+ break;
+ }
+ }
+ }
+
+ pDockArr->Insert(pDock, nInsertPos);
+ InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine );
+ SaveConfig_Impl();
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl* pDock,
+ const Size& rSize,
+ USHORT nLine, USHORT nPos, BOOL bNewLine)
+
+/* [Beschreibung]
+
+ F"ugt ein DockingWindow ein und veranla\st die Neuberechnung der Gr"o\se
+ des Splitwindows.
+*/
+
+{
+ SfxDockingWindow* pDockWin = pDock->pWin;
+
+ USHORT nItemBits = pDockWin->GetWinBits_Impl();
+
+ long nWinSize, nSetSize;
+ if ( IsHorizontal() )
+ {
+ nWinSize = rSize.Width();
+ nSetSize = rSize.Height();
+ }
+ else
+ {
+ nSetSize = rSize.Width();
+ nWinSize = rSize.Height();
+ }
+
+ pDock->nSize = nWinSize;
+
+ BOOL bUpdateMode = IsUpdateMode();
+ if ( bUpdateMode )
+ SetUpdateMode( FALSE );
+
+ if ( bNewLine || nLine == GetItemCount( 0 ) )
+ {
+ // Es soll nicht in eine vorhandene Zeile eingef"ugt werden, sondern
+ // eine neue erzeugt werden
+
+ USHORT nId = 1;
+ for ( USHORT n=0; n<GetItemCount(0); n++ )
+ {
+ if ( GetItemId(n) >= nId )
+ nId = GetItemId(n)+1;
+ }
+
+ // Eine neue nLine-te Zeile erzeugen
+ USHORT nBits = nItemBits;
+ if ( GetAlign() == WINDOWALIGN_TOP || GetAlign() == WINDOWALIGN_BOTTOM )
+ nBits |= SWIB_COLSET;
+ InsertItem( nId, nSetSize, nLine, 0, nBits );
+ }
+
+ // In Zeile mit Position nLine das Fenster einf"ugen
+ // ItemWindowSize auf "Prozentual" setzen, da SV dann das Umgr"o\sern
+ // so macht, wie man erwartet; "Pixel" macht eigentlich nur Sinn, wenn
+ // auch Items mit prozentualen oder relativen Gr"o\sen dabei sind.
+ nItemBits |= SWIB_PERCENTSIZE;
+ bLocked = TRUE;
+ USHORT nSet = GetItemId( nLine );
+ InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits );
+
+ // Splitwindows werden im SFX einmal angelegt und beim Einf"ugen des ersten
+ // DockingWindows sichtbar gemacht.
+ if ( GetItemCount( 0 ) == 1 && GetItemCount( 1 ) == 1 )
+ {
+ // Das Neuarrangieren am WorkWindow und ein Show() auf das SplitWindow
+ // wird vom SfxDockingwindow veranla\st (->SfxWorkWindow::ConfigChild_Impl)
+ if ( !bPinned && !IsFloatingMode() )
+ {
+ bPinned = TRUE;
+ BOOL bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
+ pEmptyWin->bFadeIn = FALSE;
+ SetPinned_Impl( FALSE );
+ pEmptyWin->Actualize();
+ DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
+ pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, TRUE )->nVisible = CHILD_VISIBLE;
+ pWorkWin->ArrangeChilds_Impl();
+ if ( bFadeIn )
+ FadeIn();
+ }
+ else
+ {
+ BOOL bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
+ pEmptyWin->bFadeIn = FALSE;
+ pEmptyWin->Actualize();
+#ifdef DBG_UTIL
+ if ( !bPinned || !pEmptyWin->bFadeIn )
+ {
+ DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
+ }
+ else
+ {
+ DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
+ }
+#endif
+ pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, TRUE )->nVisible = CHILD_VISIBLE;
+ pWorkWin->ArrangeChilds_Impl();
+ if ( bFadeIn )
+ FadeIn();
+ }
+
+ pWorkWin->ShowChilds_Impl();
+ }
+
+ if ( bUpdateMode )
+ SetUpdateMode( TRUE );
+ bLocked = FALSE;
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::RemoveWindow( SfxDockingWindow* pDockWin, BOOL bHide )
+
+/* [Beschreibung]
+
+ Entfernt ein DockingWindow. Wenn es das letzte war, wird das SplitWindow
+ gehidet.
+*/
+{
+ USHORT nSet = GetSet( pDockWin->GetType() );
+
+ // Splitwindows werden im SFX einmal angelegt und nach dem Entfernen
+ // des letzten DockingWindows unsichtbar gemacht.
+ if ( GetItemCount( nSet ) == 1 && GetItemCount( 0 ) == 1 )
+ {
+ // Das Neuarrangieren am WorkWindow wird vom SfxDockingwindow
+ // veranla\st!
+ Hide();
+ pEmptyWin->aTimer.Stop();
+ USHORT nRealState = pEmptyWin->nState;
+ FadeOut_Impl();
+ pEmptyWin->Hide();
+#ifdef DBG_UTIL
+ if ( !bPinned || !pEmptyWin->bFadeIn )
+ {
+ DBG_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
+ }
+ else
+ {
+ DBG_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
+ }
+#endif
+ pWorkWin->ReleaseChild_Impl( *GetSplitWindow() );
+ pEmptyWin->nState = nRealState;
+ pWorkWin->ArrangeAutoHideWindows( this );
+ }
+
+ SfxDock_Impl *pDock=0;
+ USHORT nCount = pDockArr->Count();
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ pDock = (*pDockArr)[n];
+ if ( pDock->nType == pDockWin->GetType() )
+ {
+ pDock->pWin = 0;
+ pDock->bHide = bHide;
+ break;
+ }
+ }
+
+ // Fenster removen, und wenn es das letzte der Zeile war, auch die Zeile
+ // ( Zeile = ItemSet )
+ BOOL bUpdateMode = IsUpdateMode();
+ if ( bUpdateMode )
+ SetUpdateMode( FALSE );
+ bLocked = TRUE;
+
+ RemoveItem( pDockWin->GetType() );
+
+ if ( nSet && !GetItemCount( nSet ) )
+ RemoveItem( nSet );
+
+ if ( bUpdateMode )
+ SetUpdateMode( TRUE );
+ bLocked = FALSE;
+};
+
+//-------------------------------------------------------------------------
+
+BOOL SfxSplitWindow::GetWindowPos( const SfxDockingWindow* pWindow,
+ USHORT& rLine, USHORT& rPos ) const
+/* [Beschreibung]
+
+ Liefert die Id des Itemsets und die des Items f"ur das "ubergebene
+ DockingWindow in der alten Zeilen/Spalten-Bezeichnung zur"uck.
+*/
+
+{
+ USHORT nSet = GetSet ( pWindow->GetType() );
+ if ( nSet == SPLITWINDOW_ITEM_NOTFOUND )
+ return FALSE;
+
+ rPos = GetItemPos( pWindow->GetType(), nSet );
+ rLine = GetItemPos( nSet );
+ return TRUE;
+}
+
+//-------------------------------------------------------------------------
+
+BOOL SfxSplitWindow::GetWindowPos( const Point& rTestPos,
+ USHORT& rLine, USHORT& rPos ) const
+/* [Beschreibung]
+
+ Liefert die Id des Itemsets und die des Items f"ur das DockingWindow
+ an der "ubergebenen Position in der alten Zeilen/Spalten-Bezeichnung
+ zur"uck.
+*/
+
+{
+ USHORT nId = GetItemId( rTestPos );
+ if ( nId == 0 )
+ return FALSE;
+
+ USHORT nSet = GetSet ( nId );
+ rPos = GetItemPos( nId, nSet );
+ rLine = GetItemPos( nSet );
+ return TRUE;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT SfxSplitWindow::GetLineCount() const
+
+/* [Beschreibung]
+
+ Liefert die Zeilenzahl = Zahl der Sub-Itemsets im Root-Set.
+*/
+{
+ return GetItemCount( 0 );
+}
+
+//-------------------------------------------------------------------------
+
+long SfxSplitWindow::GetLineSize( USHORT nLine ) const
+
+/* [Beschreibung]
+
+ Liefert die "Zeilenh"ohe" des nLine-ten Itemsets.
+*/
+{
+ USHORT nId = GetItemId( nLine );
+ return GetItemSize( nId );
+}
+
+//-------------------------------------------------------------------------
+
+USHORT SfxSplitWindow::GetWindowCount( USHORT nLine ) const
+
+/* [Beschreibung]
+
+ Liefert die
+*/
+{
+ USHORT nId = GetItemId( nLine );
+ return GetItemCount( nId );
+}
+
+//-------------------------------------------------------------------------
+
+USHORT SfxSplitWindow::GetWindowCount() const
+
+/* [Beschreibung]
+
+ Liefert die Gesamtzahl aller Fenstert
+*/
+{
+ return GetItemCount( 0 );
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::Command( const CommandEvent& rCEvt )
+{
+ SplitWindow::Command( rCEvt );
+}
+
+//-------------------------------------------------------------------------
+
+IMPL_LINK( SfxSplitWindow, TimerHdl, Timer*, pTimer)
+{
+ if ( pTimer )
+ pTimer->Stop();
+
+ if ( CursorIsOverRect( FALSE ) || !pTimer )
+ {
+ // Wenn der Mauszeiger innerhalb des Fensters liegt, SplitWindow anzeigen
+ // und Timer zum Schlie\sen aufsetzen
+ pEmptyWin->bAutoHide = TRUE;
+ if ( !IsVisible() )
+ pEmptyWin->FadeIn();
+
+ pEmptyWin->aLastPos = GetPointerPosPixel();
+ pEmptyWin->aTimer.Start();
+ }
+ else if ( pEmptyWin->bAutoHide )
+ {
+ if ( GetPointerPosPixel() != pEmptyWin->aLastPos )
+ {
+ // Die Maus wurd innerhalb der Timerlaugzeit bewegt, also erst einmal
+ // nichts tun
+ pEmptyWin->aLastPos = GetPointerPosPixel();
+ pEmptyWin->aTimer.Start();
+ return 0L;
+ }
+
+ // Speziell f"ur TF_AUTOSHOW_ON_MOUSEMOVE :
+ // Wenn das Fenster nicht sichtbar ist, gibt es nichts zu tun
+ // (Benutzer ist einfach mit der Maus "uber pEmptyWin gefahren)
+ if ( IsVisible() )
+ {
+ pEmptyWin->bEndAutoHide = FALSE;
+ if ( !Application::IsInModalMode() &&
+ !PopupMenu::IsInExecute() &&
+ !pEmptyWin->bSplit && !HasChildPathFocus( TRUE ) )
+ {
+ // W"ahrend ein modaler Dialog oder ein Popupmenu offen sind
+ // oder w"ahrend des Splittens auf keinen Fall zumachen; auch
+ // solange eines der Children den Focus hat, bleibt das
+ // das Fenster offen
+ pEmptyWin->bEndAutoHide = TRUE;
+ }
+
+ if ( pEmptyWin->bEndAutoHide )
+ {
+ // Von mir aus kann Schlu\s sein mit AutoShow
+ // Aber vielleicht will noch ein anderes SfxSplitWindow offen bleiben,
+ // dann bleiben auch alle anderen offen
+ if ( !pWorkWin->IsAutoHideMode( this ) )
+ {
+ FadeOut_Impl();
+ pWorkWin->ArrangeAutoHideWindows( this );
+ }
+ else
+ {
+ pEmptyWin->aLastPos = GetPointerPosPixel();
+ pEmptyWin->aTimer.Start();
+ }
+ }
+ else
+ {
+ pEmptyWin->aLastPos = GetPointerPosPixel();
+ pEmptyWin->aTimer.Start();
+ }
+ }
+ }
+
+ return 0L;
+}
+
+//-------------------------------------------------------------------------
+
+BOOL SfxSplitWindow::CursorIsOverRect( BOOL bForceAdding ) const
+{
+ BOOL bVisible = IsVisible();
+
+ // Auch das kollabierte SplitWindow ber"ucksichtigen
+ Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() );
+ Size aSize = pEmptyWin->GetSizePixel();
+
+ if ( bForceAdding )
+ {
+ // Um +/- ein paar Pixel erweitern, sonst ist es zu nerv"os
+ aPos.X() -= nPixel;
+ aPos.Y() -= nPixel;
+ aSize.Width() += 2 * nPixel;
+ aSize.Height() += 2 * nPixel;
+ }
+
+ Rectangle aRect( aPos, aSize );
+
+ if ( bVisible )
+ {
+ Point aVisPos = GetPosPixel();
+ Size aVisSize = GetSizePixel();
+
+ // Um +/- ein paar Pixel erweitern, sonst ist es zu nerv"os
+ aVisPos.X() -= nPixel;
+ aVisPos.Y() -= nPixel;
+ aVisSize.Width() += 2 * nPixel;
+ aVisSize.Height() += 2 * nPixel;
+
+ Rectangle aVisRect( aVisPos, aVisSize );
+ aRect = aRect.GetUnion( aVisRect );
+ }
+
+ if ( aRect.IsInside( OutputToScreenPixel( ((Window*)this)->GetPointerPosPixel() ) ) )
+ return TRUE;
+ return FALSE;
+}
+
+//-------------------------------------------------------------------------
+
+SplitWindow* SfxSplitWindow::GetSplitWindow()
+{
+ if ( !bPinned || !pEmptyWin->bFadeIn )
+ return pEmptyWin;
+ return this;
+}
+
+//-------------------------------------------------------------------------
+BOOL SfxSplitWindow::IsFadeIn() const
+{
+ return pEmptyWin->bFadeIn;
+}
+
+BOOL SfxSplitWindow::IsAutoHide( BOOL bSelf ) const
+{
+ return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide;
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::SetPinned_Impl( BOOL bOn )
+{
+ if ( bPinned == bOn )
+ return;
+
+ bPinned = bOn;
+ if ( GetItemCount( 0 ) == 0 )
+ return;
+
+ if ( !bOn )
+ {
+ pEmptyWin->nState |= 1;
+ if ( pEmptyWin->bFadeIn )
+ {
+ // Ersatzfenster anmelden
+ DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" );
+ pWorkWin->ReleaseChild_Impl( *this );
+ Hide();
+ pEmptyWin->Actualize();
+ DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" );
+ pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, TRUE )->nVisible = CHILD_VISIBLE;
+ }
+
+ Point aPos( GetPosPixel() );
+ aPos = GetParent()->OutputToScreenPixel( aPos );
+ SetFloatingPos( aPos );
+ SetFloatingMode( TRUE );
+ GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() );
+
+ if ( pEmptyWin->bFadeIn )
+ Show();
+ }
+ else
+ {
+ pEmptyWin->nState &= ~1;
+ SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() );
+ SetFloatingMode( FALSE );
+
+ if ( pEmptyWin->bFadeIn )
+ {
+ // Ersatzfenster abmelden
+ DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
+ pWorkWin->ReleaseChild_Impl( *pEmptyWin );
+ pEmptyWin->Hide();
+ DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
+ pWorkWin->RegisterChild_Impl( *this, eAlign, TRUE )->nVisible = CHILD_VISIBLE;
+ }
+ }
+
+ SetAutoHideState( !bPinned );
+ pEmptyWin->SetAutoHideState( !bPinned );
+}
+
+//-------------------------------------------------------------------------
+
+void SfxSplitWindow::SetFadeIn_Impl( BOOL bOn )
+{
+ if ( bOn == pEmptyWin->bFadeIn )
+ return;
+
+ if ( GetItemCount( 0 ) == 0 )
+ return;
+
+ pEmptyWin->bFadeIn = bOn;
+ if ( bOn )
+ {
+ pEmptyWin->nState |= 2;
+ if ( IsFloatingMode() )
+ {
+ // FloatingWindow ist nicht sichtbar, also anzeigen
+ pWorkWin->ArrangeAutoHideWindows( this );
+ Show();
+ }
+ else
+ {
+ DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
+ pWorkWin->ReleaseChild_Impl( *pEmptyWin );
+ pEmptyWin->Hide();
+ DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
+ pWorkWin->RegisterChild_Impl( *this, eAlign, TRUE )->nVisible = CHILD_VISIBLE;
+ pWorkWin->ArrangeChilds_Impl();
+ pWorkWin->ShowChilds_Impl();
+ }
+ }
+ else
+ {
+ pEmptyWin->bAutoHide = FALSE;
+ pEmptyWin->nState &= ~2;
+ if ( !IsFloatingMode() )
+ {
+ // Das Fenster "schwebt" nicht, soll aber ausgeblendet werden,
+ DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" );
+ pWorkWin->ReleaseChild_Impl( *this );
+ Hide();
+ pEmptyWin->Actualize();
+ DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" );
+ pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, TRUE )->nVisible = CHILD_VISIBLE;
+ pWorkWin->ArrangeChilds_Impl();
+ pWorkWin->ShowChilds_Impl();
+ pWorkWin->ArrangeAutoHideWindows( this );
+ }
+ else
+ {
+ Hide();
+ pWorkWin->ArrangeAutoHideWindows( this );
+ }
+ }
+}
+
+void SfxSplitWindow::AutoHide()
+{
+ // Wenn dieser Handler am "echten" SplitWindow aufgerufen wird, ist es
+ // entweder angedockt und soll "schwebend" angezeigt werden oder umgekehrt
+ if ( !bPinned )
+ {
+ // Es "schwebt", also wieder andocken
+ SetPinned_Impl( TRUE );
+ pWorkWin->ArrangeChilds_Impl();
+ }
+ else
+ {
+ // In den "Schwebezustand" bringen
+ SetPinned_Impl( FALSE );
+ pWorkWin->ArrangeChilds_Impl();
+ pWorkWin->ArrangeAutoHideWindows( this );
+ }
+
+ pWorkWin->ShowChilds_Impl();
+ SaveConfig_Impl();
+}
+
+void SfxSplitWindow::FadeOut_Impl()
+{
+ if ( pEmptyWin->aTimer.IsActive() )
+ {
+ pEmptyWin->bAutoHide = FALSE;
+ pEmptyWin->aTimer.Stop();
+ }
+
+ SetFadeIn_Impl( FALSE );
+ Show_Impl();
+}
+
+void SfxSplitWindow::FadeOut()
+{
+ FadeOut_Impl();
+ SaveConfig_Impl();
+}
+
+void SfxSplitWindow::FadeIn()
+{
+ SetFadeIn_Impl( TRUE );
+ Show_Impl();
+}
+
+void SfxSplitWindow::Show_Impl()
+{
+ USHORT nCount = pDockArr->Count();
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ SfxDock_Impl *pDock = (*pDockArr)[n];
+ if ( pDock->pWin )
+ pDock->pWin->FadeIn( pEmptyWin->bFadeIn );
+ }
+}
+/*
+void SfxSplitWindow::Pin_Impl( BOOL bPin )
+{
+ if ( bPinned != bPin )
+ AutoHide();
+}
+*/
+BOOL SfxSplitWindow::ActivateNextChild_Impl( BOOL bForward )
+{
+ // Wenn kein pActive, auf erstes bzw. letztes Fenster gehen ( bei !bForward wird erst in der loop dekrementiert )
+ USHORT nCount = pDockArr->Count();
+ USHORT n = bForward ? 0 : nCount;
+
+ // Wenn Focus innerhalb, dann ein Fenster vor oder zur"uck, wenn m"oglich
+ if ( pActive )
+ {
+ // Aktives Fenster ermitteln
+ for ( n=0; n<nCount; n++ )
+ {
+ SfxDock_Impl *pD = (*pDockArr)[n];
+ if ( pD->pWin && pD->pWin->HasChildPathFocus() )
+ break;
+ }
+
+ if ( bForward )
+ // ein Fenster weiter ( wenn dann n>nCount, wird die Schleife unten gar nicht durchlaufen )
+ n++;
+ }
+
+ if ( bForward )
+ {
+ // N"achstes Fenster suchen
+ for ( USHORT nNext=n; nNext<nCount; nNext++ )
+ {
+ SfxDock_Impl *pD = (*pDockArr)[nNext];
+ if ( pD->pWin )
+ {
+ pD->pWin->GrabFocus();
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ // Vorheriges Fenster suchen
+ for ( USHORT nNext=n; nNext--; )
+ {
+ SfxDock_Impl *pD = (*pDockArr)[nNext];
+ if ( pD->pWin )
+ {
+ pD->pWin->GrabFocus();
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow* pWin )
+{
+ pActive = pWin;
+ pWorkWin->SetActiveChild_Impl( this );
+}
+
+