summaryrefslogtreecommitdiff
path: root/vcl/source/window
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/window')
-rw-r--r--vcl/source/window/abstdlg.cxx64
-rw-r--r--vcl/source/window/accel.cxx731
-rw-r--r--vcl/source/window/accmgr.cxx290
-rw-r--r--vcl/source/window/arrange.cxx903
-rw-r--r--vcl/source/window/brdwin.cxx2355
-rw-r--r--vcl/source/window/btndlg.cxx551
-rw-r--r--vcl/source/window/cmdevt.cxx101
-rw-r--r--vcl/source/window/cursor.cxx462
-rw-r--r--vcl/source/window/decoview.cxx1388
-rw-r--r--vcl/source/window/dialog.cxx1028
-rw-r--r--vcl/source/window/dlgctrl.cxx1267
-rw-r--r--vcl/source/window/dndevdis.cxx564
-rw-r--r--vcl/source/window/dndlcon.cxx567
-rw-r--r--vcl/source/window/dockingarea.cxx246
-rw-r--r--vcl/source/window/dockmgr.cxx1689
-rw-r--r--vcl/source/window/dockwin.cxx1120
-rw-r--r--vcl/source/window/floatwin.cxx878
-rw-r--r--vcl/source/window/introwin.cxx88
-rw-r--r--vcl/source/window/javachild.cxx207
-rw-r--r--vcl/source/window/keycod.cxx160
-rw-r--r--vcl/source/window/keyevent.cxx116
-rw-r--r--vcl/source/window/makefile.mk104
-rw-r--r--vcl/source/window/menu.cxx6099
-rw-r--r--vcl/source/window/mnemonic.cxx419
-rw-r--r--vcl/source/window/mnemonicengine.cxx130
-rw-r--r--vcl/source/window/mouseevent.cxx92
-rw-r--r--vcl/source/window/msgbox.cxx694
-rw-r--r--vcl/source/window/popupmenuwindow.cxx79
-rw-r--r--vcl/source/window/printdlg.cxx2603
-rw-r--r--vcl/source/window/scrwnd.cxx420
-rw-r--r--vcl/source/window/scrwnd.hxx92
-rw-r--r--vcl/source/window/seleng.cxx502
-rw-r--r--vcl/source/window/split.cxx806
-rw-r--r--vcl/source/window/splitwin.cxx3877
-rw-r--r--vcl/source/window/status.cxx1794
-rw-r--r--vcl/source/window/syschild.cxx192
-rw-r--r--vcl/source/window/syswin.cxx1086
-rw-r--r--vcl/source/window/tabdlg.cxx276
-rw-r--r--vcl/source/window/tabpage.cxx216
-rw-r--r--vcl/source/window/taskpanelist.cxx398
-rw-r--r--vcl/source/window/toolbox.cxx6333
-rw-r--r--vcl/source/window/toolbox2.cxx2437
-rw-r--r--vcl/source/window/window.cxx9972
-rw-r--r--vcl/source/window/window2.cxx2065
-rw-r--r--vcl/source/window/window3.cxx82
-rw-r--r--vcl/source/window/winproc.cxx2618
-rw-r--r--vcl/source/window/wrkwin.cxx323
47 files changed, 58484 insertions, 0 deletions
diff --git a/vcl/source/window/abstdlg.cxx b/vcl/source/window/abstdlg.cxx
new file mode 100644
index 000000000000..7f00b73b0808
--- /dev/null
+++ b/vcl/source/window/abstdlg.cxx
@@ -0,0 +1,64 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <vcl/abstdlg.hxx>
+#include "cuilib.hxx"
+
+#include <osl/module.hxx>
+#include <tools/string.hxx>
+
+typedef VclAbstractDialogFactory* (__LOADONCALLAPI *FuncPtrCreateDialogFactory)();
+
+extern "C" { static void SAL_CALL thisModule() {} }
+
+VclAbstractDialogFactory* VclAbstractDialogFactory::Create()
+{
+ FuncPtrCreateDialogFactory fp = 0;
+ static ::osl::Module aDialogLibrary;
+ if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, String( RTL_CONSTASCII_USTRINGPARAM( DLL_NAME ) ) ) )
+ fp = ( VclAbstractDialogFactory* (__LOADONCALLAPI*)() )
+ aDialogLibrary.getFunctionSymbol( ::rtl::OUString::createFromAscii("CreateDialogFactory") );
+ if ( fp )
+ return fp();
+ return 0;
+}
+
+VclAbstractDialog::~VclAbstractDialog()
+{
+}
+
+// virtual
+VclAbstractDialog2::~VclAbstractDialog2()
+{
+}
+
+VclAbstractDialogFactory::~VclAbstractDialogFactory()
+{
+}
diff --git a/vcl/source/window/accel.cxx b/vcl/source/window/accel.cxx
new file mode 100644
index 000000000000..3018236fff1a
--- /dev/null
+++ b/vcl/source/window/accel.cxx
@@ -0,0 +1,731 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <tools/list.hxx>
+#ifndef _TABLE_HXX
+#include <tools/table.hxx>
+#endif
+#include <tools/debug.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/accel.h>
+#include <vcl/accel.hxx>
+#ifndef _RC_H
+#include <tools/rc.h>
+#endif
+
+
+
+// =======================================================================
+
+DECLARE_TABLE( ImplAccelTable, ImplAccelEntry* )
+DECLARE_LIST( ImplAccelList, ImplAccelEntry* )
+
+#define ACCELENTRY_NOTFOUND ((USHORT)0xFFFF)
+
+// =======================================================================
+
+class ImplAccelData
+{
+public:
+ ImplAccelTable maKeyTable; // Fuer KeyCodes, die mit einem Code erzeugt wurden
+ ImplAccelList maIdList; // Id-List
+};
+
+// =======================================================================
+
+DBG_NAME( Accelerator )
+
+// =======================================================================
+
+USHORT ImplAccelEntryGetIndex( ImplAccelList* pList, USHORT nId,
+ USHORT* pIndex = NULL )
+{
+ ULONG nLow;
+ ULONG nHigh;
+ ULONG nMid;
+ ULONG nCount = pList->Count();
+ USHORT nCompareId;
+
+ // Abpruefen, ob der erste Key groesser als der Vergleichskey ist
+ if ( !nCount || (nId < pList->GetObject( 0 )->mnId) )
+ {
+ if ( pIndex )
+ *pIndex = 0;
+ return ACCELENTRY_NOTFOUND;
+ }
+
+ // Binaeres Suchen
+ nLow = 0;
+ nHigh = nCount-1;
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ nCompareId = pList->GetObject( nMid )->mnId;
+ if ( nId < nCompareId )
+ nHigh = nMid-1;
+ else
+ {
+ if ( nId > nCompareId )
+ nLow = nMid + 1;
+ else
+ return (USHORT)nMid;
+ }
+ }
+ while ( nLow <= nHigh );
+
+ if ( pIndex )
+ {
+ if ( nId > nCompareId )
+ *pIndex = (USHORT)(nMid+1);
+ else
+ *pIndex = (USHORT)nMid;
+ }
+
+ return ACCELENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplAccelEntryInsert( ImplAccelList* pList, ImplAccelEntry* pEntry )
+{
+ USHORT nInsIndex;
+ USHORT nIndex = ImplAccelEntryGetIndex( pList, pEntry->mnId, &nInsIndex );
+
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ do
+ {
+ nIndex++;
+ ImplAccelEntry* pTempEntry = pList->GetObject( nIndex );
+ if ( !pTempEntry || (pTempEntry->mnId != pEntry->mnId) )
+ break;
+ }
+ while ( nIndex < pList->Count() );
+
+ pList->Insert( pEntry, (ULONG)nIndex );
+ }
+ else
+ pList->Insert( pEntry, (ULONG)nInsIndex );
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplAccelEntryGetFirstPos( ImplAccelList* pList, USHORT nId )
+{
+ USHORT nIndex = ImplAccelEntryGetIndex( pList, nId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ while ( nIndex )
+ {
+ nIndex--;
+ if ( pList->GetObject( nIndex )->mnId != nId )
+ break;
+ }
+
+ if ( pList->GetObject( nIndex )->mnId != nId )
+ nIndex++;
+ }
+
+ return nIndex;
+}
+
+// =======================================================================
+
+void Accelerator::ImplInit()
+{
+ mnCurId = 0;
+ mnCurRepeat = 0;
+ mbIsCancel = FALSE;
+ mpDel = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplAccelEntry* Accelerator::ImplGetAccelData( const KeyCode& rKeyCode ) const
+{
+ return mpData->maKeyTable.Get( rKeyCode.GetFullKeyCode() );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::ImplCopyData( ImplAccelData& rAccelData )
+{
+ // Tabellen kopieren
+ ImplAccelEntry* pEntry = rAccelData.maIdList.First();
+ while ( pEntry )
+ {
+ pEntry = new ImplAccelEntry( *pEntry );
+
+ // Folge-Accelerator, dann auch kopieren
+ if ( pEntry->mpAccel )
+ {
+ pEntry->mpAccel = new Accelerator( *(pEntry->mpAccel) );
+ pEntry->mpAutoAccel = pEntry->mpAccel;
+ }
+ else
+ pEntry->mpAutoAccel = NULL;
+
+ mpData->maKeyTable.Insert( (ULONG)pEntry->maKeyCode.GetFullKeyCode(), pEntry );
+ mpData->maIdList.Insert( pEntry, LIST_APPEND );
+
+ pEntry = rAccelData.maIdList.Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::ImplDeleteData()
+{
+ // Accelerator-Eintraege ueber die Id-Tabelle loeschen
+ ImplAccelEntry* pEntry = mpData->maIdList.First();
+ while ( pEntry )
+ {
+ // AutoResAccel zerstoeren
+ if ( pEntry->mpAutoAccel )
+ delete pEntry->mpAutoAccel;
+ delete pEntry;
+
+ pEntry = mpData->maIdList.Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::ImplInsertAccel( USHORT nItemId, const KeyCode& rKeyCode,
+ BOOL bEnable, Accelerator* pAutoAccel )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+ DBG_ASSERT( nItemId, "Accelerator::InsertItem(): ItemId == 0" );
+
+ if ( rKeyCode.IsFunction() )
+ {
+ USHORT nCode1;
+ USHORT nCode2;
+ USHORT nCode3;
+ USHORT nCode4;
+ ImplGetKeyCode( rKeyCode.GetFunction(), nCode1, nCode2, nCode3, nCode4 );
+ if ( nCode1 )
+ ImplInsertAccel( nItemId, KeyCode( nCode1, nCode1 ), bEnable, pAutoAccel );
+ if ( nCode2 )
+ {
+ if ( pAutoAccel )
+ pAutoAccel = new Accelerator( *pAutoAccel );
+ ImplInsertAccel( nItemId, KeyCode( nCode2, nCode2 ), bEnable, pAutoAccel );
+ if ( nCode3 )
+ {
+ if ( pAutoAccel )
+ pAutoAccel = new Accelerator( *pAutoAccel );
+ ImplInsertAccel( nItemId, KeyCode( nCode3, nCode3 ), bEnable, pAutoAccel );
+ }
+ }
+ return;
+ }
+
+ // Neuen Eintrag holen und fuellen
+ ImplAccelEntry* pEntry = new ImplAccelEntry;
+ pEntry->mnId = nItemId;
+ pEntry->maKeyCode = rKeyCode;
+ pEntry->mpAccel = pAutoAccel;
+ pEntry->mpAutoAccel = pAutoAccel;
+ pEntry->mbEnabled = bEnable;
+
+ // Ab in die Tabellen
+ ULONG nCode = rKeyCode.GetFullKeyCode();
+ if ( !nCode )
+ {
+ DBG_ERROR( "Accelerator::InsertItem(): KeyCode with KeyCode 0 not allowed" );
+ delete pEntry;
+ }
+ else if ( !mpData->maKeyTable.Insert( nCode, pEntry ) )
+ {
+ DBG_ERROR1( "Accelerator::InsertItem(): KeyCode (Key: %lx) already exists", nCode );
+ delete pEntry;
+ }
+ else
+ ImplAccelEntryInsert( &(mpData->maIdList), pEntry );
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator::Accelerator()
+{
+ DBG_CTOR( Accelerator, NULL );
+
+ ImplInit();
+ mpData = new ImplAccelData;
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator::Accelerator( const Accelerator& rAccel ) :
+ Resource(),
+ maHelpStr( rAccel.maHelpStr ),
+ maCurKeyCode( rAccel.maCurKeyCode )
+{
+ DBG_CTOR( Accelerator, NULL );
+ DBG_CHKOBJ( &rAccel, Accelerator, NULL );
+
+ ImplInit();
+ mpData = new ImplAccelData;
+ ImplCopyData( *((ImplAccelData*)(rAccel.mpData)) );
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator::Accelerator( const ResId& rResId )
+{
+ DBG_CTOR( Accelerator, NULL );
+
+ ImplInit();
+ mpData = new ImplAccelData;
+ rResId.SetRT( RSC_ACCEL );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::ImplLoadRes( const ResId& rResId )
+{
+ GetRes( rResId );
+
+ maHelpStr = ReadStringRes();
+ ULONG nObjFollows = ReadLongRes();
+
+ for( ULONG i = 0; i < nObjFollows; i++ )
+ {
+ InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator::~Accelerator()
+{
+ DBG_DTOR( Accelerator, NULL );
+
+ // AccelManager benachrichtigen, das Accelrator geloescht wurde
+ if ( mpDel )
+ *mpDel = TRUE;
+
+ ImplDeleteData();
+ delete mpData;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::Activate()
+{
+ maActivateHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::Deactivate()
+{
+ maDeactivateHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::InsertItem( USHORT nItemId, const KeyCode& rKeyCode )
+{
+ ImplInsertAccel( nItemId, rKeyCode, TRUE, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::InsertItem( const ResId& rResId )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ULONG nObjMask;
+ USHORT nAccelKeyId;
+ USHORT bDisable;
+ KeyCode aKeyCode;
+ Accelerator* pAutoAccel = NULL;
+
+ GetRes( rResId.SetRT( RSC_ACCELITEM ) );
+ nObjMask = ReadLongRes();
+ nAccelKeyId = sal::static_int_cast<USHORT>(ReadLongRes());
+ bDisable = ReadShortRes();
+
+ if ( nObjMask & ACCELITEM_KEY )
+ {
+ // es wird ein neuer Kontext aufgespannt
+ RSHEADER_TYPE * pKeyCodeRes = (RSHEADER_TYPE *)GetClassRes();
+ ResId aResId( pKeyCodeRes, *rResId.GetResMgr());
+ aKeyCode = KeyCode( aResId );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+
+ if ( nObjMask & ACCELITEM_ACCEL )
+ {
+ pAutoAccel = new Accelerator( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+
+ ImplInsertAccel( nAccelKeyId, aKeyCode, !bDisable, pAutoAccel );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::RemoveItem( USHORT nItemId )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ // Aus der Id-Liste entfernen
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ USHORT nItemCount = GetItemCount();
+ do
+ {
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nIndex );
+ if ( pEntry && pEntry->mnId == nItemId )
+ {
+ mpData->maKeyTable.Remove( pEntry->maKeyCode.GetFullKeyCode() );
+ mpData->maIdList.Remove( (ULONG)nIndex );
+
+ // AutoResAccel zerstoeren
+ if ( pEntry->mpAutoAccel )
+ delete pEntry->mpAutoAccel;
+
+ delete pEntry;
+ }
+ else
+ break;
+ }
+ while ( nIndex < nItemCount );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::RemoveItem( const KeyCode rKeyCode )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ {
+ // Aus der Id-Liste entfernen
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), pEntry->mnId );
+ USHORT nItemCount = GetItemCount();
+ do
+ {
+ if ( mpData->maIdList.GetObject( (ULONG)nIndex ) == pEntry )
+ break;
+ nIndex++;
+ }
+ while ( nIndex < nItemCount );
+
+ mpData->maKeyTable.Remove( rKeyCode.GetFullKeyCode() );
+ mpData->maIdList.Remove( (ULONG)nIndex );
+
+ // AutoResAccel zerstoeren
+ if ( pEntry->mpAutoAccel )
+ delete pEntry->mpAutoAccel;
+
+ delete pEntry;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::Clear()
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplDeleteData();
+ mpData->maKeyTable.Clear();
+ mpData->maIdList.Clear();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Accelerator::GetItemCount() const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ return (USHORT)mpData->maIdList.Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Accelerator::GetItemId( USHORT nPos ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nPos );
+ if ( pEntry )
+ return pEntry->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+KeyCode Accelerator::GetItemKeyCode( USHORT nPos ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nPos );
+ if ( pEntry )
+ return pEntry->maKeyCode;
+ else
+ return KeyCode();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Accelerator::GetItemId( const KeyCode& rKeyCode ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ return pEntry->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+KeyCode Accelerator::GetKeyCode( USHORT nItemId ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ return mpData->maIdList.GetObject( (ULONG)nIndex )->maKeyCode;
+ else
+ return KeyCode();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::IsIdValid( USHORT nItemId ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
+ return (nIndex != ACCELENTRY_NOTFOUND);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::IsKeyCodeValid( const KeyCode rKeyCode ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ return (pEntry != NULL);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::Call( const KeyCode& rKeyCode, USHORT nRepeat )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ {
+ if ( pEntry->mbEnabled )
+ {
+ BOOL bDel = FALSE;
+ mnCurId = pEntry->mnId;
+ maCurKeyCode = rKeyCode;
+ mnCurRepeat = nRepeat;
+ mpDel = &bDel;
+ Select();
+ if ( !bDel )
+ {
+ mnCurId = 0;
+ maCurKeyCode = KeyCode();
+ mnCurRepeat = 0;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::SetAccel( USHORT nItemId, Accelerator* pAccel )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ USHORT nItemCount = GetItemCount();
+ do
+ {
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nIndex );
+ if ( pEntry->mnId != nItemId )
+ break;
+
+ pEntry->mpAccel = pAccel;
+ nIndex++;
+ }
+ while ( nIndex < nItemCount );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator* Accelerator::GetAccel( USHORT nItemId ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ return mpData->maIdList.GetObject( (ULONG)nIndex )->mpAccel;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::SetAccel( const KeyCode rKeyCode, Accelerator* pAccel )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ pEntry->mpAccel = pAccel;
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator* Accelerator::GetAccel( const KeyCode rKeyCode ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ return pEntry->mpAccel;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::EnableItem( USHORT nItemId, BOOL bEnable )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ USHORT nItemCount = GetItemCount();
+ do
+ {
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nIndex );
+ if ( pEntry->mnId != nItemId )
+ break;
+
+ pEntry->mbEnabled = bEnable;
+ nIndex++;
+ }
+ while ( nIndex < nItemCount );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::IsItemEnabled( USHORT nItemId ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ return mpData->maIdList.GetObject( (ULONG)nIndex )->mbEnabled;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::EnableItem( const KeyCode rKeyCode, BOOL bEnable )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ pEntry->mbEnabled = bEnable;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::IsItemEnabled( const KeyCode rKeyCode ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ return pEntry->mbEnabled;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator& Accelerator::operator=( const Accelerator& rAccel )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+ DBG_CHKOBJ( &rAccel, Accelerator, NULL );
+
+ // Neue Daten zuweisen
+ maHelpStr = rAccel.maHelpStr;
+ maCurKeyCode = KeyCode();
+ mnCurId = 0;
+ mnCurRepeat = 0;
+ mbIsCancel = FALSE;
+
+ // Tabellen loeschen und kopieren
+ ImplDeleteData();
+ mpData->maKeyTable.Clear();
+ mpData->maIdList.Clear();
+ ImplCopyData( *((ImplAccelData*)(rAccel.mpData)) );
+
+ return *this;
+}
diff --git a/vcl/source/window/accmgr.cxx b/vcl/source/window/accmgr.cxx
new file mode 100644
index 000000000000..81699bcaabb0
--- /dev/null
+++ b/vcl/source/window/accmgr.cxx
@@ -0,0 +1,290 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+#include <vcl/accel.h>
+#include <vcl/accel.hxx>
+#include <vcl/accmgr.hxx>
+
+
+
+// =======================================================================
+
+DECLARE_LIST( ImplAccelList, Accelerator* )
+
+// =======================================================================
+
+DBG_NAMEEX( Accelerator )
+
+// =======================================================================
+
+ImplAccelManager::~ImplAccelManager()
+{
+ if ( mpAccelList )
+ delete mpAccelList;
+ if ( mpSequenceList )
+ delete mpSequenceList;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplAccelManager::InsertAccel( Accelerator* pAccel )
+{
+ if ( !mpAccelList )
+ mpAccelList = new ImplAccelList;
+ else
+ {
+ // Gibts den schon ?
+ if ( mpAccelList->GetPos( pAccel ) != LIST_ENTRY_NOTFOUND )
+ return FALSE;
+ }
+
+ // Am Anfang der Liste einfuegen
+ mpAccelList->Insert( pAccel, (ULONG)0 );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplAccelManager::RemoveAccel( Accelerator* pAccel )
+{
+ // Haben wir ueberhaupt eine Liste ?
+ if ( !mpAccelList )
+ return;
+
+ //e.g. #i90599#. Someone starts typing a sequence in a dialog, but doesn't
+ //end it, and then closes the dialog, deleting the accelerators. So if
+ //we're removing an accelerator that a sub-accelerator which is in the
+ //sequence list, throw away the entire sequence
+ if ( mpSequenceList )
+ {
+ for (USHORT i = 0; i < pAccel->GetItemCount(); ++i)
+ {
+ Accelerator* pSubAccel = pAccel->GetAccel(pAccel->GetItemId(i));
+ if ( mpSequenceList->GetPos( pSubAccel ) != LIST_ENTRY_NOTFOUND )
+ {
+ EndSequence( true );
+ break;
+ }
+ }
+ }
+
+ // Raus damit
+ mpAccelList->Remove( pAccel );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplAccelManager::EndSequence( BOOL bCancel )
+{
+ // Sind wir ueberhaupt in einer Sequenz ?
+ if ( !mpSequenceList )
+ return;
+
+ // Alle Deactivate-Handler der Acceleratoren in der Sequenz rufen
+ Accelerator* pTempAccel = mpSequenceList->First();
+ while( pTempAccel )
+ {
+ BOOL bDel = FALSE;
+ pTempAccel->mbIsCancel = bCancel;
+ pTempAccel->mpDel = &bDel;
+ pTempAccel->Deactivate();
+ if ( !bDel )
+ {
+ pTempAccel->mbIsCancel = FALSE;
+ pTempAccel->mpDel = NULL;
+ }
+
+ pTempAccel = mpSequenceList->Next();
+ }
+
+ // Sequenz-Liste loeschen
+ delete mpSequenceList;
+ mpSequenceList = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplAccelManager::IsAccelKey( const KeyCode& rKeyCode, USHORT nRepeat )
+{
+ Accelerator* pAccel;
+
+ // Haben wir ueberhaupt Acceleratoren ??
+ if ( !mpAccelList )
+ return FALSE;
+ if ( !mpAccelList->Count() )
+ return FALSE;
+
+ // Sind wir in einer Sequenz ?
+ if ( mpSequenceList )
+ {
+ pAccel = mpSequenceList->GetObject( 0 );
+ DBG_CHKOBJ( pAccel, Accelerator, NULL );
+
+ // Nicht Gefunden ?
+ if ( !pAccel )
+ {
+ // Sequenz abbrechen
+ FlushAccel();
+ return FALSE;
+ }
+
+ // Ist der Eintrag da drin ?
+ ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ {
+ Accelerator* pNextAccel = pEntry->mpAccel;
+
+ // Ist da ein Accelerator hinter ?
+ if ( pNextAccel )
+ {
+ DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
+
+ mpSequenceList->Insert( pNextAccel, (ULONG)0 );
+
+ // Activate-Handler vom Neuen rufen
+ pNextAccel->Activate();
+ return TRUE;
+ }
+ else
+ {
+ // Hat ihn schon !
+ if ( pEntry->mbEnabled )
+ {
+ // Sequence beenden (Deactivate-Handler vorher rufen)
+ EndSequence();
+
+ // Dem Accelerator das aktuelle Item setzen
+ // und Handler rufen
+ BOOL bDel = FALSE;
+ pAccel->maCurKeyCode = rKeyCode;
+ pAccel->mnCurId = pEntry->mnId;
+ pAccel->mnCurRepeat = nRepeat;
+ pAccel->mpDel = &bDel;
+ pAccel->Select();
+
+ // Hat Accel den Aufruf ueberlebt
+ if ( !bDel )
+ {
+ DBG_CHKOBJ( pAccel, Accelerator, NULL );
+ pAccel->maCurKeyCode = KeyCode();
+ pAccel->mnCurId = 0;
+ pAccel->mnCurRepeat = 0;
+ pAccel->mpDel = NULL;
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ // Sequenz abbrechen, weil Acceleraor disabled
+ // Taste wird weitergeleitet (ans System)
+ FlushAccel();
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ // Sequenz abbrechen wegen falscher Taste
+ FlushAccel();
+ return FALSE;
+ }
+ }
+
+ // Durch die Liste der Acceleratoren wuehlen
+ pAccel = mpAccelList->First();
+ while ( pAccel )
+ {
+ DBG_CHKOBJ( pAccel, Accelerator, NULL );
+
+ // Ist der Eintrag da drin ?
+ ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ {
+ Accelerator* pNextAccel = pEntry->mpAccel;
+
+ // Ist da ein Accelerator hinter ?
+ if ( pNextAccel )
+ {
+ DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
+
+ // Sequenz-Liste erzeugen
+ mpSequenceList = new ImplAccelList;
+ mpSequenceList->Insert( pAccel, (ULONG)0 );
+ mpSequenceList->Insert( pNextAccel, (ULONG)0 );
+
+ // Activate-Handler vom Neuen rufen
+ pNextAccel->Activate();
+
+ return TRUE;
+ }
+ else
+ {
+ // Hat ihn schon !
+ if ( pEntry->mbEnabled )
+ {
+ // Activate/Deactivate-Handler vorher rufen
+ pAccel->Activate();
+ pAccel->Deactivate();
+
+ // Dem Accelerator das aktuelle Item setzen
+ // und Handler rufen
+ BOOL bDel = FALSE;
+ pAccel->maCurKeyCode = rKeyCode;
+ pAccel->mnCurId = pEntry->mnId;
+ pAccel->mnCurRepeat = nRepeat;
+ pAccel->mpDel = &bDel;
+ pAccel->Select();
+
+ // Hat Accel den Aufruf ueberlebt
+ if ( !bDel )
+ {
+ DBG_CHKOBJ( pAccel, Accelerator, NULL );
+ pAccel->maCurKeyCode = KeyCode();
+ pAccel->mnCurId = 0;
+ pAccel->mnCurRepeat = 0;
+ pAccel->mpDel = NULL;
+ }
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ }
+
+ // Nicht gefunden, vielleicht im naechsten Accelerator
+ pAccel = mpAccelList->Next();
+ }
+
+ return FALSE;
+}
diff --git a/vcl/source/window/arrange.cxx b/vcl/source/window/arrange.cxx
new file mode 100644
index 000000000000..dad48235f8fb
--- /dev/null
+++ b/vcl/source/window/arrange.cxx
@@ -0,0 +1,903 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "precompiled_vcl.hxx"
+
+#include "vcl/arrange.hxx"
+#include "vcl/edit.hxx"
+
+#include "osl/diagnose.h"
+
+using namespace vcl;
+
+// ----------------------------------------
+// vcl::WindowArranger
+//-----------------------------------------
+
+WindowArranger::~WindowArranger()
+{}
+
+void WindowArranger::setParent( WindowArranger* i_pParent )
+{
+ OSL_VERIFY( i_pParent->m_pParentWindow == m_pParentWindow || m_pParentWindow == NULL );
+
+ m_pParentArranger = i_pParent;
+ m_pParentWindow = i_pParent->m_pParentWindow;
+ setParentWindow( m_pParentWindow );
+}
+
+void WindowArranger::setParentWindow( Window* i_pNewParent )
+{
+ m_pParentWindow = i_pNewParent;
+
+ size_t nEle = countElements();
+ for( size_t i = 0; i < nEle; i++ )
+ {
+ Element* pEle = getElement( i );
+ if( pEle ) // sanity check
+ {
+ #if OSL_DEBUG_LEVEL > 0
+ if( pEle->m_pElement )
+ {
+ OSL_VERIFY( pEle->m_pElement->GetParent() == i_pNewParent );
+ }
+ #endif
+ if( pEle->m_pChild )
+ pEle->m_pChild->setParentWindow( i_pNewParent );
+ }
+ }
+}
+
+void WindowArranger::show( bool i_bShow, bool i_bImmediateUpdate )
+{
+ size_t nEle = countElements();
+ for( size_t i = 0; i < nEle; i++ )
+ {
+ Element* pEle = getElement( i );
+ if( pEle ) // sanity check
+ {
+ pEle->m_bHidden = ! i_bShow;
+ if( pEle->m_pElement )
+ pEle->m_pElement->Show( i_bShow );
+ if( pEle->m_pChild.get() )
+ pEle->m_pChild->show( i_bShow, false );
+ }
+ }
+ if( m_pParentArranger )
+ {
+ nEle = m_pParentArranger->countElements();
+ for( size_t i = 0; i < nEle; i++ )
+ {
+ Element* pEle = m_pParentArranger->getElement( i );
+ if( pEle && pEle->m_pChild.get() == this )
+ {
+ pEle->m_bHidden = ! i_bShow;
+ break;
+ }
+ }
+ }
+ if( i_bImmediateUpdate )
+ {
+ // find the topmost parent
+ WindowArranger* pResize = this;
+ while( pResize->m_pParentArranger )
+ pResize = pResize->m_pParentArranger;
+ pResize->resize();
+ }
+}
+
+bool WindowArranger::isVisible() const
+{
+ size_t nEle = countElements();
+ for( size_t i = 0; i < nEle; i++ )
+ {
+ const Element* pEle = getConstElement( i );
+ if( pEle->isVisible() )
+ return true;
+ }
+ return false;
+}
+
+bool WindowArranger::Element::isVisible() const
+{
+ bool bVisible = false;
+ if( ! m_bHidden )
+ {
+ if( m_pElement )
+ bVisible = m_pElement->IsVisible();
+ else if( m_pChild )
+ bVisible = m_pChild->isVisible();
+ }
+ return bVisible;
+}
+
+sal_Int32 WindowArranger::Element::getExpandPriority() const
+{
+ sal_Int32 nPrio = m_nExpandPriority;
+ if( m_pChild && m_nExpandPriority >= 0 )
+ {
+ size_t nElements = m_pChild->countElements();
+ for( size_t i = 0; i < nElements; i++ )
+ {
+ sal_Int32 nCPrio = m_pChild->getExpandPriority( i );
+ if( nCPrio > nPrio )
+ nPrio = nCPrio;
+ }
+ }
+ return nPrio;
+}
+
+Size WindowArranger::Element::getOptimalSize( WindowSizeType i_eType ) const
+{
+ Size aResult;
+ if( ! m_bHidden )
+ {
+ if( m_pElement && m_pElement->IsVisible() )
+ aResult = m_pElement->GetOptimalSize( i_eType );
+ else if( m_pChild )
+ aResult = m_pChild->getOptimalSize( i_eType );
+ if( aResult.Width() < m_aMinSize.Width() )
+ aResult.Width() = m_aMinSize.Width();
+ if( aResult.Height() < m_aMinSize.Height() )
+ aResult.Height() = m_aMinSize.Height();
+ aResult.Width() += m_nLeftBorder + m_nRightBorder;
+ aResult.Height() += m_nTopBorder + m_nBottomBorder;
+ }
+
+ return aResult;
+}
+
+void WindowArranger::Element::setPosSize( const Point& i_rPos, const Size& i_rSize )
+{
+ Point aPoint( i_rPos );
+ Size aSize( i_rSize );
+ aPoint.X() += m_nLeftBorder;
+ aPoint.Y() += m_nTopBorder;
+ aSize.Width() -= m_nLeftBorder + m_nRightBorder;
+ aSize.Height() -= m_nTopBorder + m_nBottomBorder;
+ if( m_pElement )
+ m_pElement->SetPosSizePixel( aPoint, aSize );
+ else if( m_pChild )
+ m_pChild->setManagedArea( Rectangle( aPoint, aSize ) );
+}
+
+// ----------------------------------------
+// vcl::RowOrColumn
+//-----------------------------------------
+
+RowOrColumn::~RowOrColumn()
+{
+ for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ it->deleteChild();
+ }
+}
+
+Size RowOrColumn::getOptimalSize( WindowSizeType i_eType ) const
+{
+ Size aRet( 0, 0 );
+ for( std::vector< WindowArranger::Element >::const_iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ if( it->isVisible() )
+ {
+ // get the size of type of the managed element
+ Size aElementSize( it->getOptimalSize( i_eType ) );
+ if( m_bColumn )
+ {
+ // add the distance between elements
+ aRet.Height() += m_nBorderWidth;
+ // check if the width needs adjustment
+ if( aRet.Width() < aElementSize.Width() )
+ aRet.Width() = aElementSize.Width();
+ aRet.Height() += aElementSize.Height();
+ }
+ else
+ {
+ // add the distance between elements
+ aRet.Width() += m_nBorderWidth;
+ // check if the height needs adjustment
+ if( aRet.Height() < aElementSize.Height() )
+ aRet.Height() = aElementSize.Height();
+ aRet.Width() += aElementSize.Width();
+ }
+ }
+ }
+
+ if( aRet.Width() != 0 || aRet.Height() != 0 )
+ {
+ // subtract the border for the first element
+ if( m_bColumn )
+ aRet.Height() -= m_nBorderWidth;
+ else
+ aRet.Width() -= m_nBorderWidth;
+
+ // add the outer border
+ aRet.Width() += 2*m_nOuterBorder;
+ aRet.Height() += 2*m_nOuterBorder;
+ }
+
+ return aRet;
+}
+
+void RowOrColumn::distributeRowWidth( std::vector<Size>& io_rSizes, long /*i_nUsedWidth*/, long i_nExtraWidth )
+{
+ if( ! io_rSizes.empty() && io_rSizes.size() == m_aElements.size() )
+ {
+ // find all elements with the highest expand priority
+ size_t nElements = m_aElements.size();
+ std::vector< size_t > aIndices;
+ sal_Int32 nHighPrio = 0;
+ for( size_t i = 0; i < nElements; i++ )
+ {
+ if( m_aElements[ i ].isVisible() )
+ {
+ sal_Int32 nCurPrio = m_aElements[ i ].getExpandPriority();
+ if( nCurPrio > nHighPrio )
+ {
+ aIndices.clear();
+ nHighPrio = nCurPrio;
+ }
+ if( nCurPrio == nHighPrio )
+ aIndices.push_back( i );
+ }
+ }
+
+ // distribute extra space evenly among collected elements
+ nElements = aIndices.size();
+ if( nElements > 0 )
+ {
+ long nDelta = i_nExtraWidth / nElements;
+ for( size_t i = 0; i < nElements; i++ )
+ {
+ io_rSizes[ aIndices[i] ].Width() += nDelta;
+ i_nExtraWidth -= nDelta;
+ }
+ // add the last pixels to the last row element
+ if( i_nExtraWidth > 0 && nElements > 0 )
+ io_rSizes[aIndices.back()].Width() += i_nExtraWidth;
+ }
+ }
+}
+
+void RowOrColumn::distributeColumnHeight( std::vector<Size>& io_rSizes, long /*i_nUsedHeight*/, long i_nExtraHeight )
+{
+ if( ! io_rSizes.empty() && io_rSizes.size() == m_aElements.size() )
+ {
+ // find all elements with the highest expand priority
+ size_t nElements = m_aElements.size();
+ std::vector< size_t > aIndices;
+ sal_Int32 nHighPrio = 3;
+ for( size_t i = 0; i < nElements; i++ )
+ {
+ if( m_aElements[ i ].isVisible() )
+ {
+ sal_Int32 nCurPrio = m_aElements[ i ].getExpandPriority();
+ if( nCurPrio > nHighPrio )
+ {
+ aIndices.clear();
+ nHighPrio = nCurPrio;
+ }
+ if( nCurPrio == nHighPrio )
+ aIndices.push_back( i );
+ }
+ }
+
+ // distribute extra space evenly among collected elements
+ nElements = aIndices.size();
+ if( nElements > 0 )
+ {
+ long nDelta = i_nExtraHeight / nElements;
+ for( size_t i = 0; i < nElements; i++ )
+ {
+ io_rSizes[ aIndices[i] ].Height() += nDelta;
+ i_nExtraHeight -= nDelta;
+ }
+ // add the last pixels to the last row element
+ if( i_nExtraHeight > 0 && nElements > 0 )
+ io_rSizes[aIndices.back()].Height() += i_nExtraHeight;
+ }
+ }
+}
+
+void RowOrColumn::resize()
+{
+ // check if we can get optimal size, else fallback to minimal size
+ Size aOptSize( getOptimalSize( WINDOWSIZE_PREFERRED ) );
+ WindowSizeType eType = WINDOWSIZE_PREFERRED;
+ if( m_bColumn )
+ {
+ if( aOptSize.Height() > m_aManagedArea.GetHeight() )
+ eType = WINDOWSIZE_MINIMUM;
+ }
+ else
+ {
+ if( aOptSize.Width() > m_aManagedArea.GetWidth() )
+ eType = WINDOWSIZE_MINIMUM;
+ }
+
+ size_t nElements = m_aElements.size();
+ // get all element sizes for sizing
+ std::vector<Size> aElementSizes( nElements );
+ long nUsedWidth = 2*m_nOuterBorder - (nElements ? m_nBorderWidth : 0);
+ for( size_t i = 0; i < nElements; i++ )
+ {
+ if( m_aElements[i].isVisible() )
+ {
+ aElementSizes[i] = m_aElements[i].getOptimalSize( eType );
+ if( m_bColumn )
+ {
+ aElementSizes[i].Width() = m_aManagedArea.GetWidth() - 2* m_nOuterBorder;
+ nUsedWidth += aElementSizes[i].Height() + m_nBorderWidth;
+ }
+ else
+ {
+ aElementSizes[i].Height() = m_aManagedArea.GetHeight() - 2* m_nOuterBorder;
+ nUsedWidth += aElementSizes[i].Width() + m_nBorderWidth;
+ }
+ }
+ }
+
+ long nExtraWidth = (m_bColumn ? m_aManagedArea.GetHeight() : m_aManagedArea.GetWidth()) - nUsedWidth;
+ if( nExtraWidth > 0 )
+ {
+ if( m_bColumn )
+ distributeColumnHeight( aElementSizes, nUsedWidth, nExtraWidth );
+ else
+ distributeRowWidth( aElementSizes, nUsedWidth, nExtraWidth );
+ }
+
+ // get starting position
+ Point aElementPos( m_aManagedArea.TopLeft() );
+ // outer border
+ aElementPos.X() += m_nOuterBorder;
+ aElementPos.Y() += m_nOuterBorder;
+
+ // position managed windows
+ for( size_t i = 0; i < nElements; i++ )
+ {
+ // get the size of type of the managed element
+ if( m_aElements[i].isVisible() )
+ {
+ m_aElements[i].setPosSize( aElementPos, aElementSizes[i] );
+ if( m_bColumn )
+ aElementPos.Y() += m_nBorderWidth + aElementSizes[i].Height();
+ else
+ aElementPos.X() += m_nBorderWidth + aElementSizes[i].Width();
+ }
+ }
+}
+
+size_t RowOrColumn::addWindow( Window* i_pWindow, sal_Int32 i_nExpandPrio, size_t i_nIndex )
+{
+ size_t nIndex = i_nIndex;
+ if( i_nIndex >= m_aElements.size() )
+ {
+ nIndex = m_aElements.size();
+ m_aElements.push_back( WindowArranger::Element( i_pWindow, boost::shared_ptr<WindowArranger>(), i_nExpandPrio ) );
+ }
+ else
+ {
+ std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
+ while( i_nIndex-- )
+ ++it;
+ m_aElements.insert( it, WindowArranger::Element( i_pWindow, boost::shared_ptr<WindowArranger>(), i_nExpandPrio ) );
+ }
+ return nIndex;
+}
+
+size_t RowOrColumn::addChild( boost::shared_ptr<WindowArranger> const & i_pChild, sal_Int32 i_nExpandPrio, size_t i_nIndex )
+{
+ size_t nIndex = i_nIndex;
+ if( i_nIndex >= m_aElements.size() )
+ {
+ nIndex = m_aElements.size();
+ m_aElements.push_back( WindowArranger::Element( NULL, i_pChild, i_nExpandPrio ) );
+ }
+ else
+ {
+ std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
+ while( i_nIndex-- )
+ ++it;
+ m_aElements.insert( it, WindowArranger::Element( NULL, i_pChild, i_nExpandPrio ) );
+ }
+ return nIndex;
+}
+
+void RowOrColumn::remove( Window* i_pWindow )
+{
+ if( i_pWindow )
+ {
+ for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ if( it->m_pElement == i_pWindow )
+ {
+ m_aElements.erase( it );
+ return;
+ }
+ }
+ }
+}
+
+void RowOrColumn::remove( boost::shared_ptr<WindowArranger> const & i_pChild )
+{
+ if( i_pChild )
+ {
+ for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ if( it->m_pChild == i_pChild )
+ {
+ m_aElements.erase( it );
+ return;
+ }
+ }
+ }
+}
+
+// ----------------------------------------
+// vcl::LabeledElement
+//-----------------------------------------
+
+LabeledElement::~LabeledElement()
+{
+ m_aLabel.deleteChild();
+ m_aElement.deleteChild();
+}
+
+Size LabeledElement::getOptimalSize( WindowSizeType i_eType ) const
+{
+ Size aRet( m_aLabel.getOptimalSize( WINDOWSIZE_MINIMUM ) );
+ if( aRet.Width() != 0 )
+ {
+ if( m_nLabelColumnWidth != 0 )
+ aRet.Width() = m_nLabelColumnWidth;
+ else
+ aRet.Width() += m_nDistance;
+ }
+ Size aElementSize( m_aElement.getOptimalSize( i_eType ) );
+ aRet.Width() += aElementSize.Width();
+ if( aElementSize.Height() > aRet.Height() )
+ aRet.Height() = aElementSize.Height();
+ if( aRet.Height() != 0 )
+ aRet.Height() += 2*m_nOuterBorder;
+
+ return aRet;
+}
+
+void LabeledElement::resize()
+{
+ Size aLabelSize( m_aLabel.getOptimalSize( WINDOWSIZE_MINIMUM ) );
+ Size aElementSize( m_aElement.getOptimalSize( WINDOWSIZE_PREFERRED ) );
+ if( m_nDistance + aLabelSize.Width() + aElementSize.Width() > m_aManagedArea.GetWidth() )
+ aElementSize = m_aElement.getOptimalSize( WINDOWSIZE_MINIMUM );
+
+ // align label and element vertically in LabeledElement
+ long nYOff = (m_aManagedArea.GetHeight() - 2*m_nOuterBorder - aLabelSize.Height()) / 2;
+ Point aPos( m_aManagedArea.Left(),
+ m_aManagedArea.Top() + m_nOuterBorder + nYOff );
+ Size aSize( aLabelSize );
+ if( m_nLabelColumnWidth != 0 )
+ aSize.Width() = m_nLabelColumnWidth;
+ m_aLabel.setPosSize( aPos, aSize );
+
+ aPos.X() += aSize.Width() + m_nDistance;
+ nYOff = (m_aManagedArea.GetHeight() - 2*m_nOuterBorder - aElementSize.Height()) / 2;
+ aPos.Y() = m_aManagedArea.Top() + m_nOuterBorder + nYOff;
+ aSize.Width() = aElementSize.Width();
+ aSize.Height() = m_aManagedArea.GetHeight() - 2*m_nOuterBorder;
+
+ // label style
+ // 0: position left and right
+ // 1: keep the element close to label and grow it
+ // 2: keep the element close and don't grow it
+ if( m_nLabelStyle == 0)
+ {
+ if( aPos.X() + aSize.Width() < m_aManagedArea.Right() )
+ aPos.X() = m_aManagedArea.Right() - aSize.Width();
+ }
+ else if( m_nLabelStyle == 1 )
+ {
+ if( aPos.X() + aSize.Width() < m_aManagedArea.Right() )
+ aSize.Width() = m_aManagedArea.Right() - aPos.X();
+ }
+ m_aElement.setPosSize( aPos, aSize );
+}
+
+void LabeledElement::setLabel( Window* i_pLabel )
+{
+ m_aLabel.m_pElement = i_pLabel;
+ m_aLabel.m_pChild.reset();
+}
+
+void LabeledElement::setLabel( boost::shared_ptr<WindowArranger> const & i_pLabel )
+{
+ m_aLabel.m_pElement = NULL;
+ m_aLabel.m_pChild = i_pLabel;
+}
+
+void LabeledElement::setElement( Window* i_pElement )
+{
+ m_aElement.m_pElement = i_pElement;
+ m_aElement.m_pChild.reset();
+}
+
+void LabeledElement::setElement( boost::shared_ptr<WindowArranger> const & i_pElement )
+{
+ m_aElement.m_pElement = NULL;
+ m_aElement.m_pChild = i_pElement;
+}
+
+// ----------------------------------------
+// vcl::LabelColumn
+//-----------------------------------------
+LabelColumn::~LabelColumn()
+{
+}
+
+long LabelColumn::getLabelWidth() const
+{
+ long nWidth = 0;
+
+ size_t nEle = countElements();
+ for( size_t i = 0; i < nEle; i++ )
+ {
+ const Element* pEle = getConstElement( i );
+ if( pEle && pEle->m_pChild.get() )
+ {
+ const LabeledElement* pLabel = dynamic_cast< const LabeledElement* >(pEle->m_pChild.get());
+ if( pLabel )
+ {
+ Window* pLW = pLabel->getWindow( 0 );
+ if( pLW )
+ {
+ Size aLabSize( pLW->GetOptimalSize( WINDOWSIZE_MINIMUM ) );
+ if( aLabSize.Width() > nWidth )
+ nWidth = aLabSize.Width();
+ }
+ }
+ }
+ }
+ return nWidth + getBorderWidth();
+}
+
+Size LabelColumn::getOptimalSize( WindowSizeType i_eType ) const
+{
+ long nWidth = getLabelWidth();
+ Size aColumnSize;
+
+ // every child is a LabeledElement
+ size_t nEle = countElements();
+ for( size_t i = 0; i < nEle; i++ )
+ {
+ Size aElementSize;
+ const Element* pEle = getConstElement( i );
+ if( pEle && pEle->m_pChild.get() )
+ {
+ const LabeledElement* pLabel = dynamic_cast< const LabeledElement* >(pEle->m_pChild.get());
+ if( pLabel ) // we have a label
+ {
+ aElementSize = pLabel->getLabelSize( WINDOWSIZE_MINIMUM );
+ if( aElementSize.Width() )
+ aElementSize.Width() = nWidth;
+ Size aSize( pLabel->getElementSize( i_eType ) );
+ aElementSize.Width() += aSize.Width();
+ if( aSize.Height() > aElementSize.Height() )
+ aElementSize.Height() = aSize.Height();
+ }
+ else // a non label, just treat it as a row
+ {
+ aElementSize = pEle->getOptimalSize( i_eType );
+ }
+ }
+ else if( pEle && pEle->m_pElement ) // a general window, treat is as a row
+ {
+ aElementSize = pEle->getOptimalSize( i_eType );
+ }
+ if( aElementSize.Width() )
+ {
+ aElementSize.Width() += 2*m_nOuterBorder;
+ if( aElementSize.Width() > aColumnSize.Width() )
+ aColumnSize.Width() = aElementSize.Width();
+ }
+ if( aElementSize.Height() )
+ {
+ aColumnSize.Height() += getBorderWidth() + aElementSize.Height();
+ }
+ }
+ if( nEle > 0 && aColumnSize.Height() )
+ {
+ aColumnSize.Height() -= getBorderWidth(); // for the first element
+ aColumnSize.Height() += 2*m_nOuterBorder;
+ }
+ return aColumnSize;
+}
+
+void LabelColumn::resize()
+{
+ long nWidth = getLabelWidth();
+ size_t nEle = countElements();
+ for( size_t i = 0; i < nEle; i++ )
+ {
+ Element* pEle = getElement( i );
+ if( pEle && pEle->m_pChild.get() )
+ {
+ LabeledElement* pLabel = dynamic_cast< LabeledElement* >(pEle->m_pChild.get());
+ if( pLabel )
+ pLabel->setLabelColumnWidth( nWidth );
+ }
+ }
+ RowOrColumn::resize();
+}
+
+size_t LabelColumn::addRow( Window* i_pLabel, boost::shared_ptr<WindowArranger> const& i_rElement, long i_nIndent )
+{
+ boost::shared_ptr< LabeledElement > xLabel( new LabeledElement( this, 1 ) );
+ xLabel->setLabel( i_pLabel );
+ xLabel->setBorders( 0, i_nIndent, 0, 0, 0 );
+ xLabel->setElement( i_rElement );
+ size_t nIndex = addChild( xLabel );
+ resize();
+ return nIndex;
+}
+
+size_t LabelColumn::addRow( Window* i_pLabel, Window* i_pElement, long i_nIndent )
+{
+ boost::shared_ptr< LabeledElement > xLabel( new LabeledElement( this, 1 ) );
+ xLabel->setLabel( i_pLabel );
+ xLabel->setBorders( 0, i_nIndent, 0, 0, 0 );
+ xLabel->setElement( i_pElement );
+ size_t nIndex = addChild( xLabel );
+ resize();
+ return nIndex;
+}
+
+// ----------------------------------------
+// vcl::Indenter
+//-----------------------------------------
+
+Indenter::~Indenter()
+{
+ m_aElement.deleteChild();
+}
+
+Size Indenter::getOptimalSize( WindowSizeType i_eType ) const
+{
+ Size aSize( m_aElement.getOptimalSize( i_eType ) );
+ aSize.Width() += 2*m_nOuterBorder + m_nIndent;
+ aSize.Height() += 2*m_nOuterBorder;
+ return aSize;
+}
+
+void Indenter::resize()
+{
+ Point aPt( m_aManagedArea.TopLeft() );
+ aPt.X() += m_nOuterBorder + m_nIndent;
+ aPt.Y() += m_nOuterBorder;
+ Size aSz( m_aManagedArea.GetSize() );
+ aSz.Width() -= 2*m_nOuterBorder + m_nIndent;
+ aSz.Height() -= 2*m_nOuterBorder;
+ m_aElement.setPosSize( aPt, aSz );
+}
+
+void Indenter::setWindow( Window* i_pWindow, sal_Int32 i_nExpandPrio )
+{
+ OSL_VERIFY( (m_aElement.m_pElement == 0 && m_aElement.m_pChild == 0) || i_pWindow == 0 );
+ OSL_VERIFY( i_pWindow == 0 || i_pWindow->GetParent() == m_pParentWindow );
+ m_aElement.m_pElement = i_pWindow;
+ m_aElement.m_nExpandPriority = i_nExpandPrio;
+}
+
+void Indenter::setChild( boost::shared_ptr<WindowArranger> const & i_pChild, sal_Int32 i_nExpandPrio )
+{
+ OSL_VERIFY( (m_aElement.m_pElement == 0 && m_aElement.m_pChild == 0 ) || i_pChild == 0 );
+ m_aElement.m_pChild = i_pChild;
+ m_aElement.m_nExpandPriority = i_nExpandPrio;
+}
+
+// ----------------------------------------
+// vcl::MatrixArranger
+//-----------------------------------------
+MatrixArranger::~MatrixArranger()
+{
+}
+
+Size MatrixArranger::getOptimalSize( WindowSizeType i_eType, std::vector<long>& o_rColumnWidths, std::vector<long>& o_rRowHeights ) const
+{
+ Size aMatrixSize( 2*m_nOuterBorder, 2*m_nOuterBorder );
+
+ // first find out the current number of rows and columns
+ sal_uInt32 nRows = 0, nColumns = 0;
+ for( std::vector< MatrixElement >::const_iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ if( it->m_nX >= nColumns )
+ nColumns = it->m_nX+1;
+ if( it->m_nY >= nRows )
+ nRows = it->m_nY+1;
+ }
+
+ // now allocate row and column depth vectors
+ o_rColumnWidths = std::vector< long >( nColumns, 0 );
+ o_rRowHeights = std::vector< long >( nRows, 0 );
+
+ // get sizes an allocate them into rows/columns
+ for( std::vector< MatrixElement >::const_iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ Size aSize( it->getOptimalSize( i_eType ) );
+ if( aSize.Width() > o_rColumnWidths[ it->m_nX ] )
+ o_rColumnWidths[ it->m_nX ] = aSize.Width();
+ if( aSize.Height() > o_rRowHeights[ it->m_nY ] )
+ o_rRowHeights[ it->m_nY ] = aSize.Height();
+ }
+
+ // add up sizes
+ for( sal_uInt32 i = 0; i < nColumns; i++ )
+ aMatrixSize.Width() += o_rColumnWidths[i] + m_nBorderX;
+ if( nColumns > 0 )
+ aMatrixSize.Width() -= m_nBorderX;
+
+ for( sal_uInt32 i = 0; i < nRows; i++ )
+ aMatrixSize.Height() += o_rRowHeights[i] + m_nBorderY;
+ if( nRows > 0 )
+ aMatrixSize.Height() -= m_nBorderY;
+
+ return aMatrixSize;
+}
+
+Size MatrixArranger::getOptimalSize( WindowSizeType i_eType ) const
+{
+ std::vector<long> aColumnWidths, aRowHeights;
+ return getOptimalSize( i_eType, aColumnWidths, aRowHeights );
+}
+
+void MatrixArranger::resize()
+{
+ // assure that we have at least one row and column
+ if( m_aElements.empty() )
+ return;
+
+ // check if we can get optimal size, else fallback to minimal size
+ std::vector<long> aColumnWidths, aRowHeights;
+ Size aOptSize( getOptimalSize( WINDOWSIZE_PREFERRED, aColumnWidths, aRowHeights ) );
+ if( aOptSize.Height() > m_aManagedArea.GetHeight() ||
+ aOptSize.Width() > m_aManagedArea.GetWidth() )
+ {
+ std::vector<long> aMinColumnWidths, aMinRowHeights;
+ getOptimalSize( WINDOWSIZE_MINIMUM, aMinColumnWidths, aMinRowHeights );
+ if( aOptSize.Height() > m_aManagedArea.GetHeight() )
+ aRowHeights = aMinRowHeights;
+ if( aOptSize.Width() > m_aManagedArea.GetWidth() )
+ aColumnWidths = aMinColumnWidths;
+ }
+
+ // FIXME: distribute extra space available
+
+ // prepare offsets
+ std::vector<long> aColumnX( aColumnWidths.size() );
+ aColumnX[0] = m_aManagedArea.Left() + m_nOuterBorder;
+ for( size_t i = 1; i < aColumnX.size(); i++ )
+ aColumnX[i] = aColumnX[i-1] + aColumnWidths[i-1] + m_nBorderX;
+
+ std::vector<long> aRowY( aRowHeights.size() );
+ aRowY[0] = m_aManagedArea.Top() + m_nOuterBorder;
+ for( size_t i = 1; i < aRowY.size(); i++ )
+ aRowY[i] = aRowY[i-1] + aRowHeights[i-1] + m_nBorderY;
+
+ // now iterate over the elements and assign their positions
+ for( std::vector< MatrixElement >::iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ Point aCellPos( aColumnX[it->m_nX], aRowY[it->m_nY] );
+ Size aCellSize( aColumnWidths[it->m_nX], aRowHeights[it->m_nY] );
+ it->setPosSize( aCellPos, aCellSize );
+ }
+}
+
+size_t MatrixArranger::addWindow( Window* i_pWindow, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio )
+{
+ sal_uInt64 nMapValue = getMap( i_nX, i_nY );
+ std::map< sal_uInt64, size_t >::const_iterator it = m_aMatrixMap.find( nMapValue );
+ size_t nIndex = 0;
+ if( it == m_aMatrixMap.end() )
+ {
+ m_aMatrixMap[ nMapValue ] = nIndex = m_aElements.size();
+ m_aElements.push_back( MatrixElement( i_pWindow, i_nX, i_nY, boost::shared_ptr<WindowArranger>(), i_nExpandPrio ) );
+ }
+ else
+ {
+ MatrixElement& rEle( m_aElements[ it->second ] );
+ rEle.m_pElement = i_pWindow;
+ rEle.m_pChild.reset();
+ rEle.m_nExpandPriority = i_nExpandPrio;
+ rEle.m_nX = i_nX;
+ rEle.m_nY = i_nY;
+ nIndex = it->second;
+ }
+ return nIndex;
+}
+
+void MatrixArranger::remove( Window* i_pWindow )
+{
+ if( i_pWindow )
+ {
+ for( std::vector< MatrixElement >::iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ if( it->m_pElement == i_pWindow )
+ {
+ m_aMatrixMap.erase( getMap( it->m_nX, it->m_nY ) );
+ m_aElements.erase( it );
+ return;
+ }
+ }
+ }
+}
+
+size_t MatrixArranger::addChild( boost::shared_ptr<WindowArranger> const &i_pChild, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio )
+{
+ sal_uInt64 nMapValue = getMap( i_nX, i_nY );
+ std::map< sal_uInt64, size_t >::const_iterator it = m_aMatrixMap.find( nMapValue );
+ size_t nIndex = 0;
+ if( it == m_aMatrixMap.end() )
+ {
+ m_aMatrixMap[ nMapValue ] = nIndex = m_aElements.size();
+ m_aElements.push_back( MatrixElement( NULL, i_nX, i_nY, i_pChild, i_nExpandPrio ) );
+ }
+ else
+ {
+ MatrixElement& rEle( m_aElements[ it->second ] );
+ rEle.m_pElement = 0;
+ rEle.m_pChild = i_pChild;
+ rEle.m_nExpandPriority = i_nExpandPrio;
+ rEle.m_nX = i_nX;
+ rEle.m_nY = i_nY;
+ nIndex = it->second;
+ }
+ return nIndex;
+}
+
+void MatrixArranger::remove( boost::shared_ptr<WindowArranger> const &i_pChild )
+{
+ if( i_pChild )
+ {
+ for( std::vector< MatrixElement >::iterator it = m_aElements.begin();
+ it != m_aElements.end(); ++it )
+ {
+ if( it->m_pChild == i_pChild )
+ {
+ m_aMatrixMap.erase( getMap( it->m_nX, it->m_nY ) );
+ m_aElements.erase( it );
+ return;
+ }
+ }
+ }
+}
+
diff --git a/vcl/source/window/brdwin.cxx b/vcl/source/window/brdwin.cxx
new file mode 100644
index 000000000000..2ff7d0a687e7
--- /dev/null
+++ b/vcl/source/window/brdwin.cxx
@@ -0,0 +1,2355 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#ifndef _SV_SVIDS_HRC
+#include <vcl/svids.hrc>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/event.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/dockwin.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/image.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/help.hxx>
+#include <vcl/edit.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/window.h>
+#include <vcl/metric.hxx>
+#include <tools/debug.hxx>
+
+using namespace ::com::sun::star::uno;
+
+// useful caption height for title bar buttons
+#define MIN_CAPTION_HEIGHT 18
+
+// =======================================================================
+
+static void ImplGetPinImage( USHORT nStyle, BOOL bPinIn, Image& rImage )
+{
+ // ImageListe laden, wenn noch nicht vorhanden
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maCtrlData.mpPinImgList )
+ {
+ ResMgr* pResMgr = ImplGetResMgr();
+ pSVData->maCtrlData.mpPinImgList = new ImageList();
+ if( pResMgr )
+ {
+ Color aMaskColor( 0x00, 0x00, 0xFF );
+ pSVData->maCtrlData.mpPinImgList->InsertFromHorizontalBitmap
+ ( ResId( SV_RESID_BITMAP_PIN, *pResMgr ), 4,
+ &aMaskColor, NULL, NULL, 0);
+ }
+ }
+
+ // Image ermitteln und zurueckgeben
+ USHORT nId;
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ {
+ if ( bPinIn )
+ nId = 4;
+ else
+ nId = 3;
+ }
+ else
+ {
+ if ( bPinIn )
+ nId = 2;
+ else
+ nId = 1;
+ }
+ rImage = pSVData->maCtrlData.mpPinImgList->GetImage( nId );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcSymbolRect( Rectangle& rRect )
+{
+ // Den Rand den der Button in der nicht Default-Darstellung freilaesst,
+ // dazuaddieren, da wir diesen bei kleinen Buttons mit ausnutzen wollen
+ rRect.Left()--;
+ rRect.Top()--;
+ rRect.Right()++;
+ rRect.Bottom()++;
+
+ // Zwischen dem Symbol und dem Button-Rand lassen wir 5% Platz
+ long nExtraWidth = ((rRect.GetWidth()*50)+500)/1000;
+ long nExtraHeight = ((rRect.GetHeight()*50)+500)/1000;
+ rRect.Left() += nExtraWidth;
+ rRect.Right() -= nExtraWidth;
+ rRect.Top() += nExtraHeight;
+ rRect.Bottom() -= nExtraHeight;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBrdWinSymbol( OutputDevice* pDev,
+ const Rectangle& rRect, SymbolType eSymbol )
+{
+ // Zwischen dem Symbol und dem Button lassen wir 5% Platz
+ DecorationView aDecoView( pDev );
+ Rectangle aTempRect = rRect;
+ Window::ImplCalcSymbolRect( aTempRect );
+ aDecoView.DrawSymbol( aTempRect, eSymbol,
+ pDev->GetSettings().GetStyleSettings().GetButtonTextColor(), 0 );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBrdWinSymbolButton( OutputDevice* pDev,
+ const Rectangle& rRect,
+ SymbolType eSymbol, USHORT nState )
+{
+ BOOL bMouseOver = (nState & BUTTON_DRAW_HIGHLIGHT) != 0;
+ nState &= ~BUTTON_DRAW_HIGHLIGHT;
+
+ Rectangle aTempRect;
+ Window *pWin = dynamic_cast< Window* >(pDev);
+ if( pWin )
+ {
+ if( bMouseOver )
+ {
+ // provide a bright background for selection effect
+ pWin->SetFillColor( pDev->GetSettings().GetStyleSettings().GetWindowColor() );
+ pWin->SetLineColor();
+ pWin->DrawRect( rRect );
+ pWin->DrawSelectionBackground( rRect, 2, (nState & BUTTON_DRAW_PRESSED) ? TRUE : FALSE,
+ TRUE, FALSE );
+ }
+ aTempRect = rRect;
+ aTempRect.nLeft+=3;
+ aTempRect.nRight-=4;
+ aTempRect.nTop+=3;
+ aTempRect.nBottom-=4;
+ }
+ else
+ {
+ DecorationView aDecoView( pDev );
+ aTempRect = aDecoView.DrawButton( rRect, nState|BUTTON_DRAW_FLAT );
+ }
+ ImplDrawBrdWinSymbol( pDev, aTempRect, eSymbol );
+}
+
+
+// =======================================================================
+
+// ------------------------
+// - ImplBorderWindowView -
+// ------------------------
+
+ImplBorderWindowView::~ImplBorderWindowView()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::MouseMove( const MouseEvent& )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::MouseButtonDown( const MouseEvent& )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::Tracking( const TrackingEvent& )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+String ImplBorderWindowView::RequestHelp( const Point&, Rectangle& )
+{
+ return String();
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ImplBorderWindowView::GetMenuRect() const
+{
+ return Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindowView::ImplInitTitle( ImplBorderFrameData* pData )
+{
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+
+ if ( !(pBorderWindow->GetStyle() & WB_MOVEABLE) ||
+ (pData->mnTitleType == BORDERWINDOW_TITLE_NONE) )
+ {
+ pData->mnTitleType = BORDERWINDOW_TITLE_NONE;
+ pData->mnTitleHeight = 0;
+ }
+ else
+ {
+ const StyleSettings& rStyleSettings = pData->mpOutDev->GetSettings().GetStyleSettings();
+ if ( pData->mnTitleType == BORDERWINDOW_TITLE_TEAROFF )
+ pData->mnTitleHeight = rStyleSettings.GetTearOffTitleHeight();
+ else
+ {
+ if ( pData->mnTitleType == BORDERWINDOW_TITLE_SMALL )
+ {
+ pBorderWindow->SetPointFont( rStyleSettings.GetFloatTitleFont() );
+ pData->mnTitleHeight = rStyleSettings.GetFloatTitleHeight();
+ }
+ else // pData->mnTitleType == BORDERWINDOW_TITLE_NORMAL
+ {
+ pBorderWindow->SetPointFont( rStyleSettings.GetTitleFont() );
+ pData->mnTitleHeight = rStyleSettings.GetTitleHeight();
+ }
+ long nTextHeight = pBorderWindow->GetTextHeight();
+ if ( nTextHeight > pData->mnTitleHeight )
+ pData->mnTitleHeight = nTextHeight;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplBorderWindowView::ImplHitTest( ImplBorderFrameData* pData, const Point& rPos )
+{
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+
+ if ( pData->maTitleRect.IsInside( rPos ) )
+ {
+ if ( pData->maCloseRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_CLOSE;
+ else if ( pData->maRollRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_ROLL;
+ else if ( pData->maMenuRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_MENU;
+ else if ( pData->maDockRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_DOCK;
+ else if ( pData->maHideRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_HIDE;
+ else if ( pData->maHelpRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_HELP;
+ else if ( pData->maPinRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_PIN;
+ else
+ return BORDERWINDOW_HITTEST_TITLE;
+ }
+
+ if ( (pBorderWindow->GetStyle() & WB_SIZEABLE) &&
+ !pBorderWindow->mbRollUp )
+ {
+ long nSizeWidth = pData->mnNoTitleTop+pData->mnTitleHeight;
+ if ( nSizeWidth < 16 )
+ nSizeWidth = 16;
+
+ // no corner resize for floating toolbars, which would lead to jumps while formatting
+ // setting nSizeWidth = 0 will only return pure left,top,right,bottom
+ if( pBorderWindow->GetStyle() & WB_OWNERDRAWDECORATION )
+ nSizeWidth = 0;
+
+ if ( rPos.X() < pData->mnLeftBorder )
+ {
+ if ( rPos.Y() < nSizeWidth )
+ return BORDERWINDOW_HITTEST_TOPLEFT;
+ else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
+ return BORDERWINDOW_HITTEST_BOTTOMLEFT;
+ else
+ return BORDERWINDOW_HITTEST_LEFT;
+ }
+ else if ( rPos.X() >= pData->mnWidth-pData->mnRightBorder )
+ {
+ if ( rPos.Y() < nSizeWidth )
+ return BORDERWINDOW_HITTEST_TOPRIGHT;
+ else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
+ return BORDERWINDOW_HITTEST_BOTTOMRIGHT;
+ else
+ return BORDERWINDOW_HITTEST_RIGHT;
+ }
+ else if ( rPos.Y() < pData->mnNoTitleTop )
+ {
+ if ( rPos.X() < nSizeWidth )
+ return BORDERWINDOW_HITTEST_TOPLEFT;
+ else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
+ return BORDERWINDOW_HITTEST_TOPRIGHT;
+ else
+ return BORDERWINDOW_HITTEST_TOP;
+ }
+ else if ( rPos.Y() >= pData->mnHeight-pData->mnBottomBorder )
+ {
+ if ( rPos.X() < nSizeWidth )
+ return BORDERWINDOW_HITTEST_BOTTOMLEFT;
+ else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
+ return BORDERWINDOW_HITTEST_BOTTOMRIGHT;
+ else
+ return BORDERWINDOW_HITTEST_BOTTOM;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::ImplMouseMove( ImplBorderFrameData* pData, const MouseEvent& rMEvt )
+{
+ USHORT oldCloseState = pData->mnCloseState;
+ USHORT oldMenuState = pData->mnMenuState;
+ pData->mnCloseState &= ~BUTTON_DRAW_HIGHLIGHT;
+ pData->mnMenuState &= ~BUTTON_DRAW_HIGHLIGHT;
+
+ Point aMousePos = rMEvt.GetPosPixel();
+ USHORT nHitTest = ImplHitTest( pData, aMousePos );
+ PointerStyle ePtrStyle = POINTER_ARROW;
+ if ( nHitTest & BORDERWINDOW_HITTEST_LEFT )
+ ePtrStyle = POINTER_WINDOW_WSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_RIGHT )
+ ePtrStyle = POINTER_WINDOW_ESIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_TOP )
+ ePtrStyle = POINTER_WINDOW_NSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_BOTTOM )
+ ePtrStyle = POINTER_WINDOW_SSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_TOPLEFT )
+ ePtrStyle = POINTER_WINDOW_NWSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_BOTTOMRIGHT )
+ ePtrStyle = POINTER_WINDOW_SESIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_TOPRIGHT )
+ ePtrStyle = POINTER_WINDOW_NESIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_BOTTOMLEFT )
+ ePtrStyle = POINTER_WINDOW_SWSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ pData->mnCloseState |= BUTTON_DRAW_HIGHLIGHT;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_MENU )
+ pData->mnMenuState |= BUTTON_DRAW_HIGHLIGHT;
+ pData->mpBorderWindow->SetPointer( Pointer( ePtrStyle ) );
+
+ if( pData->mnCloseState != oldCloseState )
+ pData->mpBorderWindow->Invalidate( pData->maCloseRect );
+ if( pData->mnMenuState != oldMenuState )
+ pData->mpBorderWindow->Invalidate( pData->maMenuRect );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::ImplMouseButtonDown( ImplBorderFrameData* pData, const MouseEvent& rMEvt )
+{
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+
+ if ( rMEvt.IsLeft() || rMEvt.IsRight() )
+ {
+ pData->maMouseOff = rMEvt.GetPosPixel();
+ pData->mnHitTest = ImplHitTest( pData, pData->maMouseOff );
+ USHORT nDragFullTest = 0;
+ if ( pData->mnHitTest )
+ {
+ BOOL bTracking = TRUE;
+ BOOL bHitTest = TRUE;
+
+ if ( pData->mnHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ {
+ pData->mnCloseState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_CLOSE );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_ROLL )
+ {
+ pData->mnRollState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_ROLL );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_DOCK )
+ {
+ pData->mnDockState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_DOCK );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_MENU )
+ {
+ pData->mnMenuState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_MENU );
+
+ // call handler already on mouse down
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ pClientWindow->TitleButtonClick( TITLE_BUTTON_MENU );
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_HIDE )
+ {
+ pData->mnHideState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HIDE );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_HELP )
+ {
+ pData->mnHelpState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HELP );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_PIN )
+ {
+ pData->mnPinState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_PIN );
+ }
+ else
+ {
+ if ( rMEvt.GetClicks() == 1 )
+ {
+ if ( bTracking )
+ {
+ Point aPos = pBorderWindow->GetPosPixel();
+ Size aSize = pBorderWindow->GetOutputSizePixel();
+ pData->mnTrackX = aPos.X();
+ pData->mnTrackY = aPos.Y();
+ pData->mnTrackWidth = aSize.Width();
+ pData->mnTrackHeight = aSize.Height();
+
+ if ( pData->mnHitTest & BORDERWINDOW_HITTEST_TITLE )
+ nDragFullTest = DRAGFULL_OPTION_WINDOWMOVE;
+ else
+ nDragFullTest = DRAGFULL_OPTION_WINDOWSIZE;
+ }
+ }
+ else
+ {
+ bTracking = FALSE;
+
+ if ( (pData->mnHitTest & BORDERWINDOW_DRAW_TITLE) &&
+ ((rMEvt.GetClicks() % 2) == 0) )
+ {
+ pData->mnHitTest = 0;
+ bHitTest = FALSE;
+
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ if ( TRUE /*pBorderWindow->mbDockBtn*/ ) // always perform docking on double click, no button required
+ pClientWindow->TitleButtonClick( TITLE_BUTTON_DOCKING );
+ else if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
+ {
+ if ( pClientWindow->IsRollUp() )
+ pClientWindow->RollDown();
+ else
+ pClientWindow->RollUp();
+ pClientWindow->Roll();
+ }
+ }
+ }
+ }
+ }
+
+ if ( bTracking )
+ {
+ pData->mbDragFull = FALSE;
+ if ( nDragFullTest )
+ pData->mbDragFull = TRUE; // always fulldrag for proper docking, ignore system settings
+ pBorderWindow->StartTracking();
+ }
+ else if ( bHitTest )
+ pData->mnHitTest = 0;
+ }
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::ImplTracking( ImplBorderFrameData* pData, const TrackingEvent& rTEvt )
+{
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ USHORT nHitTest = pData->mnHitTest;
+ pData->mnHitTest = 0;
+
+ if ( nHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ {
+ if ( pData->mnCloseState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnCloseState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_CLOSE );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ // dispatch to correct window type (why is Close() not virtual ??? )
+ // TODO: make Close() virtual
+ Window *pWin = pBorderWindow->ImplGetClientWindow()->ImplGetWindow();
+ SystemWindow *pSysWin = dynamic_cast<SystemWindow* >(pWin);
+ DockingWindow *pDockWin = dynamic_cast<DockingWindow*>(pWin);
+ if ( pSysWin )
+ pSysWin->Close();
+ else if ( pDockWin )
+ pDockWin->Close();
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_ROLL )
+ {
+ if ( pData->mnRollState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnRollState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_ROLL );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ if ( pClientWindow->IsRollUp() )
+ pClientWindow->RollDown();
+ else
+ pClientWindow->RollUp();
+ pClientWindow->Roll();
+ }
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_DOCK )
+ {
+ if ( pData->mnDockState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnDockState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_DOCK );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ pClientWindow->TitleButtonClick( TITLE_BUTTON_DOCKING );
+ }
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_MENU )
+ {
+ if ( pData->mnMenuState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnMenuState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_MENU );
+
+ // handler already called on mouse down
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_HIDE )
+ {
+ if ( pData->mnHideState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnHideState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HIDE );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ pClientWindow->TitleButtonClick( TITLE_BUTTON_HIDE );
+ }
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_HELP )
+ {
+ if ( pData->mnHelpState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnHelpState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HELP );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_PIN )
+ {
+ if ( pData->mnPinState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnPinState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_PIN );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ pClientWindow->SetPin( !pClientWindow->IsPined() );
+ pClientWindow->Pin();
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( pData->mbDragFull )
+ {
+ // Bei Abbruch alten Zustand wieder herstellen
+ if ( rTEvt.IsTrackingCanceled() )
+ pBorderWindow->SetPosSizePixel( Point( pData->mnTrackX, pData->mnTrackY ), Size( pData->mnTrackWidth, pData->mnTrackHeight ) );
+ }
+ else
+ {
+ pBorderWindow->HideTracking();
+ if ( !rTEvt.IsTrackingCanceled() )
+ pBorderWindow->SetPosSizePixel( Point( pData->mnTrackX, pData->mnTrackY ), Size( pData->mnTrackWidth, pData->mnTrackHeight ) );
+ }
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->ImplIsFloatingWindow() )
+ {
+ if ( ((FloatingWindow*)pBorderWindow->ImplGetClientWindow())->IsInPopupMode() )
+ ((FloatingWindow*)pBorderWindow->ImplGetClientWindow())->EndPopupMode( FLOATWIN_POPUPMODEEND_TEAROFF );
+ }
+ }
+ }
+ }
+ else if ( !rTEvt.GetMouseEvent().IsSynthetic() )
+ {
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+
+ if ( pData->mnHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ {
+ if ( pData->maCloseRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnCloseState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnCloseState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_CLOSE );
+ }
+ }
+ else
+ {
+ if ( pData->mnCloseState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnCloseState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_CLOSE );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_ROLL )
+ {
+ if ( pData->maRollRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnRollState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnRollState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_ROLL );
+ }
+ }
+ else
+ {
+ if ( pData->mnRollState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnRollState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_ROLL );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_DOCK )
+ {
+ if ( pData->maDockRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnDockState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnDockState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_DOCK );
+ }
+ }
+ else
+ {
+ if ( pData->mnDockState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnDockState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_DOCK );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_MENU )
+ {
+ if ( pData->maMenuRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnMenuState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnMenuState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_MENU );
+
+ }
+ }
+ else
+ {
+ if ( pData->mnMenuState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnMenuState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_MENU );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_HIDE )
+ {
+ if ( pData->maHideRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnHideState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnHideState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HIDE );
+ }
+ }
+ else
+ {
+ if ( pData->mnHideState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnHideState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HIDE );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_HELP )
+ {
+ if ( pData->maHelpRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnHelpState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnHelpState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HELP );
+ }
+ }
+ else
+ {
+ if ( pData->mnHelpState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnHelpState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HELP );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_PIN )
+ {
+ if ( pData->maPinRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnPinState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnPinState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_PIN );
+ }
+ }
+ else
+ {
+ if ( pData->mnPinState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnPinState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_PIN );
+ }
+ }
+ }
+ else
+ {
+ /*
+ // adjusting mousepos not required, we allow the whole screen (no desktop anymore...)
+ Point aFrameMousePos = pBorderWindow->ImplOutputToFrame( aMousePos );
+ Size aFrameSize = pBorderWindow->ImplGetFrameWindow()->GetOutputSizePixel();
+ if ( aFrameMousePos.X() < 0 )
+ aFrameMousePos.X() = 0;
+ if ( aFrameMousePos.Y() < 0 )
+ aFrameMousePos.Y() = 0;
+ if ( aFrameMousePos.X() > aFrameSize.Width()-1 )
+ aFrameMousePos.X() = aFrameSize.Width()-1;
+ if ( aFrameMousePos.Y() > aFrameSize.Height()-1 )
+ aFrameMousePos.Y() = aFrameSize.Height()-1;
+ aMousePos = pBorderWindow->ImplFrameToOutput( aFrameMousePos );
+ */
+
+ aMousePos.X() -= pData->maMouseOff.X();
+ aMousePos.Y() -= pData->maMouseOff.Y();
+
+ if ( pData->mnHitTest & BORDERWINDOW_HITTEST_TITLE )
+ {
+ pData->mpBorderWindow->SetPointer( Pointer( POINTER_MOVE ) );
+
+ Point aPos = pBorderWindow->GetPosPixel();
+ aPos.X() += aMousePos.X();
+ aPos.Y() += aMousePos.Y();
+ if ( pData->mbDragFull )
+ {
+ pBorderWindow->SetPosPixel( aPos );
+ pBorderWindow->ImplUpdateAll();
+ pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
+ }
+ else
+ {
+ pData->mnTrackX = aPos.X();
+ pData->mnTrackY = aPos.Y();
+ pBorderWindow->ShowTracking( Rectangle( pBorderWindow->ScreenToOutputPixel( aPos ), pBorderWindow->GetOutputSizePixel() ), SHOWTRACK_BIG );
+ }
+ }
+ else
+ {
+ Point aOldPos = pBorderWindow->GetPosPixel();
+ Size aSize = pBorderWindow->GetSizePixel();
+ Rectangle aNewRect( aOldPos, aSize );
+ long nOldWidth = aSize.Width();
+ long nOldHeight = aSize.Height();
+ long nBorderWidth = pData->mnLeftBorder+pData->mnRightBorder;
+ long nBorderHeight = pData->mnTopBorder+pData->mnBottomBorder;
+ long nMinWidth = pBorderWindow->mnMinWidth+nBorderWidth;
+ long nMinHeight = pBorderWindow->mnMinHeight+nBorderHeight;
+ long nMinWidth2 = nBorderWidth;
+ long nMaxWidth = pBorderWindow->mnMaxWidth+nBorderWidth;
+ long nMaxHeight = pBorderWindow->mnMaxHeight+nBorderHeight;
+
+ if ( pData->mnTitleHeight )
+ {
+ nMinWidth2 += 4;
+
+ if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
+ nMinWidth2 += pData->maCloseRect.GetWidth();
+ }
+ if ( nMinWidth2 > nMinWidth )
+ nMinWidth = nMinWidth2;
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_LEFT | BORDERWINDOW_HITTEST_TOPLEFT | BORDERWINDOW_HITTEST_BOTTOMLEFT) )
+ {
+ aNewRect.Left() += aMousePos.X();
+ if ( aNewRect.GetWidth() < nMinWidth )
+ aNewRect.Left() = aNewRect.Right()-nMinWidth+1;
+ else if ( aNewRect.GetWidth() > nMaxWidth )
+ aNewRect.Left() = aNewRect.Right()-nMaxWidth+1;
+ }
+ else if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_RIGHT | BORDERWINDOW_HITTEST_TOPRIGHT | BORDERWINDOW_HITTEST_BOTTOMRIGHT) )
+ {
+ aNewRect.Right() += aMousePos.X();
+ if ( aNewRect.GetWidth() < nMinWidth )
+ aNewRect.Right() = aNewRect.Left()+nMinWidth+1;
+ else if ( aNewRect.GetWidth() > nMaxWidth )
+ aNewRect.Right() = aNewRect.Left()+nMaxWidth+1;
+ }
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_TOP | BORDERWINDOW_HITTEST_TOPLEFT | BORDERWINDOW_HITTEST_TOPRIGHT) )
+ {
+ aNewRect.Top() += aMousePos.Y();
+ if ( aNewRect.GetHeight() < nMinHeight )
+ aNewRect.Top() = aNewRect.Bottom()-nMinHeight+1;
+ else if ( aNewRect.GetHeight() > nMaxHeight )
+ aNewRect.Top() = aNewRect.Bottom()-nMaxHeight+1;
+ }
+ else if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_BOTTOM | BORDERWINDOW_HITTEST_BOTTOMLEFT | BORDERWINDOW_HITTEST_BOTTOMRIGHT) )
+ {
+ aNewRect.Bottom() += aMousePos.Y();
+ if ( aNewRect.GetHeight() < nMinHeight )
+ aNewRect.Bottom() = aNewRect.Top()+nMinHeight+1;
+ else if ( aNewRect.GetHeight() > nMaxHeight )
+ aNewRect.Bottom() = aNewRect.Top()+nMaxHeight+1;
+ }
+
+ // call Resizing-Handler for SystemWindows
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ // adjust size for Resizing-call
+ aSize = aNewRect.GetSize();
+ aSize.Width() -= nBorderWidth;
+ aSize.Height() -= nBorderHeight;
+ ((SystemWindow*)pBorderWindow->ImplGetClientWindow())->Resizing( aSize );
+ aSize.Width() += nBorderWidth;
+ aSize.Height() += nBorderHeight;
+ if ( aSize.Width() < nMinWidth )
+ aSize.Width() = nMinWidth;
+ if ( aSize.Height() < nMinHeight )
+ aSize.Height() = nMinHeight;
+ if ( aSize.Width() > nMaxWidth )
+ aSize.Width() = nMaxWidth;
+ if ( aSize.Height() > nMaxHeight )
+ aSize.Height() = nMaxHeight;
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_LEFT | BORDERWINDOW_HITTEST_TOPLEFT | BORDERWINDOW_HITTEST_BOTTOMLEFT) )
+ aNewRect.Left() = aNewRect.Right()-aSize.Width()+1;
+ else
+ aNewRect.Right() = aNewRect.Left()+aSize.Width()-1;
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_TOP | BORDERWINDOW_HITTEST_TOPLEFT | BORDERWINDOW_HITTEST_TOPRIGHT) )
+ aNewRect.Top() = aNewRect.Bottom()-aSize.Height()+1;
+ else
+ aNewRect.Bottom() = aNewRect.Top()+aSize.Height()-1;
+ }
+
+ if ( pData->mbDragFull )
+ {
+ // no move (only resize) if position did not change
+ if( aOldPos != aNewRect.TopLeft() )
+ pBorderWindow->SetPosSizePixel( aNewRect.Left(), aNewRect.Top(),
+ aNewRect.GetWidth(), aNewRect.GetHeight(), WINDOW_POSSIZE_POSSIZE );
+ else
+ pBorderWindow->SetPosSizePixel( aNewRect.Left(), aNewRect.Top(),
+ aNewRect.GetWidth(), aNewRect.GetHeight(), WINDOW_POSSIZE_SIZE );
+
+ pBorderWindow->ImplUpdateAll();
+ pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_RIGHT | BORDERWINDOW_HITTEST_TOPRIGHT | BORDERWINDOW_HITTEST_BOTTOMRIGHT) )
+ pData->maMouseOff.X() += aNewRect.GetWidth()-nOldWidth;
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_BOTTOM | BORDERWINDOW_HITTEST_BOTTOMLEFT | BORDERWINDOW_HITTEST_BOTTOMRIGHT) )
+ pData->maMouseOff.Y() += aNewRect.GetHeight()-nOldHeight;
+ }
+ else
+ {
+ pData->mnTrackX = aNewRect.Left();
+ pData->mnTrackY = aNewRect.Top();
+ pData->mnTrackWidth = aNewRect.GetWidth();
+ pData->mnTrackHeight = aNewRect.GetHeight();
+ pBorderWindow->ShowTracking( Rectangle( pBorderWindow->ScreenToOutputPixel( aNewRect.TopLeft() ), aNewRect.GetSize() ), SHOWTRACK_BIG );
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+String ImplBorderWindowView::ImplRequestHelp( ImplBorderFrameData* pData,
+ const Point& rPos,
+ Rectangle& rHelpRect )
+{
+ USHORT nHelpId = 0;
+ String aHelpStr;
+ USHORT nHitTest = ImplHitTest( pData, rPos );
+ if ( nHitTest )
+ {
+ if ( nHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ {
+ nHelpId = SV_HELPTEXT_CLOSE;
+ rHelpRect = pData->maCloseRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_ROLL )
+ {
+ if ( pData->mpBorderWindow->mbRollUp )
+ nHelpId = SV_HELPTEXT_ROLLDOWN;
+ else
+ nHelpId = SV_HELPTEXT_ROLLUP;
+ rHelpRect = pData->maRollRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_DOCK )
+ {
+ nHelpId = SV_HELPTEXT_MAXIMIZE;
+ rHelpRect = pData->maDockRect;
+ }
+ /* no help string available
+ else if ( nHitTest & BORDERWINDOW_HITTEST_MENU )
+ {
+ nHelpId = SV_HELPTEXT_MENU;
+ rHelpRect = pData->maMenuRect;
+ }*/
+ else if ( nHitTest & BORDERWINDOW_HITTEST_HIDE )
+ {
+ nHelpId = SV_HELPTEXT_MINIMIZE;
+ rHelpRect = pData->maHideRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_HELP )
+ {
+ nHelpId = SV_HELPTEXT_HELP;
+ rHelpRect = pData->maHelpRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_PIN )
+ {
+ nHelpId = SV_HELPTEXT_ALWAYSVISIBLE;
+ rHelpRect = pData->maPinRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_TITLE )
+ {
+ if( !pData->maTitleRect.IsEmpty() )
+ {
+ // tooltip only if title truncated
+ if( pData->mbTitleClipped )
+ {
+ rHelpRect = pData->maTitleRect;
+ // no help id, use window title as help string
+ aHelpStr = pData->mpBorderWindow->GetText();
+ }
+ }
+ }
+ }
+
+ if( nHelpId && ImplGetResMgr() )
+ aHelpStr = String( ResId( nHelpId, *ImplGetResMgr() ) );
+
+ return aHelpStr;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplBorderWindowView::ImplCalcTitleWidth( const ImplBorderFrameData* pData ) const
+{
+ // kein sichtbarer Title, dann auch keine Breite
+ if ( !pData->mnTitleHeight )
+ return 0;
+
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+ long nTitleWidth = pBorderWindow->GetTextWidth( pBorderWindow->GetText() )+6;
+ nTitleWidth += pData->maPinRect.GetWidth();
+ nTitleWidth += pData->maCloseRect.GetWidth();
+ nTitleWidth += pData->maRollRect.GetWidth();
+ nTitleWidth += pData->maDockRect.GetWidth();
+ nTitleWidth += pData->maMenuRect.GetWidth();
+ nTitleWidth += pData->maHideRect.GetWidth();
+ nTitleWidth += pData->maHelpRect.GetWidth();
+ nTitleWidth += pData->mnLeftBorder+pData->mnRightBorder;
+ return nTitleWidth;
+}
+
+// =======================================================================
+
+// --------------------------
+// - ImplNoBorderWindowView -
+// --------------------------
+
+ImplNoBorderWindowView::ImplNoBorderWindowView( ImplBorderWindow* )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImplNoBorderWindowView::Init( OutputDevice*, long, long )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImplNoBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
+ sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
+{
+ rLeftBorder = 0;
+ rTopBorder = 0;
+ rRightBorder = 0;
+ rBottomBorder = 0;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplNoBorderWindowView::CalcTitleWidth() const
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplNoBorderWindowView::DrawWindow( USHORT, OutputDevice*, const Point* )
+{
+}
+
+// =======================================================================
+
+// -----------------------------
+// - ImplSmallBorderWindowView -
+// -----------------------------
+
+// =======================================================================
+
+ImplSmallBorderWindowView::ImplSmallBorderWindowView( ImplBorderWindow* pBorderWindow )
+{
+ mpBorderWindow = pBorderWindow;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSmallBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
+{
+ mpOutDev = pDev;
+ mnWidth = nWidth;
+ mnHeight = nHeight;
+ mbNWFBorder = false;
+
+ USHORT nBorderStyle = mpBorderWindow->GetBorderStyle();
+ if ( nBorderStyle & WINDOW_BORDER_NOBORDER )
+ {
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ }
+ else
+ {
+ // FIXME: this is currently only on aqua, check with other
+ // platforms
+ if( ImplGetSVData()->maNWFData.mbNoFocusRects )
+ {
+ // for native widget drawing we must find out what
+ // control this border belongs to
+ Window *pWin = NULL, *pCtrl = NULL;
+ if( mpOutDev->GetOutDevType() == OUTDEV_WINDOW )
+ pWin = (Window*) mpOutDev;
+
+ ControlType aCtrlType = 0;
+ if( pWin && (pCtrl = mpBorderWindow->GetWindow( WINDOW_CLIENT )) != NULL )
+ {
+ switch( pCtrl->GetType() )
+ {
+ case WINDOW_LISTBOX:
+ if( pCtrl->GetStyle() & WB_DROPDOWN )
+ {
+ aCtrlType = CTRL_LISTBOX;
+ mbNWFBorder = true;
+ }
+ break;
+ case WINDOW_COMBOBOX:
+ if( pCtrl->GetStyle() & WB_DROPDOWN )
+ {
+ aCtrlType = CTRL_COMBOBOX;
+ mbNWFBorder = true;
+ }
+ break;
+ case WINDOW_MULTILINEEDIT:
+ aCtrlType = CTRL_MULTILINE_EDITBOX;
+ mbNWFBorder = true;
+ break;
+ case WINDOW_EDIT:
+ case WINDOW_PATTERNFIELD:
+ case WINDOW_METRICFIELD:
+ case WINDOW_CURRENCYFIELD:
+ case WINDOW_DATEFIELD:
+ case WINDOW_TIMEFIELD:
+ case WINDOW_LONGCURRENCYFIELD:
+ case WINDOW_NUMERICFIELD:
+ case WINDOW_SPINFIELD:
+ mbNWFBorder = true;
+ aCtrlType = (pCtrl->GetStyle() & WB_SPIN) ? CTRL_SPINBOX : CTRL_EDITBOX;
+ break;
+ default:
+ break;
+ }
+ }
+ if( mbNWFBorder )
+ {
+ ImplControlValue aControlValue;
+ Rectangle aCtrlRegion( (const Point&)Point(), Size( mnWidth < 10 ? 10 : mnWidth, mnHeight < 10 ? 10 : mnHeight ) );
+ Rectangle aBounds( aCtrlRegion );
+ Rectangle aContent( aCtrlRegion );
+ if( pWin->GetNativeControlRegion( aCtrlType, PART_ENTIRE_CONTROL, aCtrlRegion,
+ CTRL_STATE_ENABLED, aControlValue, rtl::OUString(),
+ aBounds, aContent ) )
+ {
+ mnLeftBorder = aContent.Left() - aBounds.Left();
+ mnRightBorder = aBounds.Right() - aContent.Right();
+ mnTopBorder = aContent.Top() - aBounds.Top();
+ mnBottomBorder = aBounds.Bottom() - aContent.Bottom();
+ if( mnWidth && mnHeight )
+ {
+
+ mpBorderWindow->SetPaintTransparent( TRUE );
+ mpBorderWindow->SetBackground();
+ pCtrl->SetPaintTransparent( TRUE );
+
+ Window* pCompoundParent = NULL;
+ if( pWin->GetParent() && pWin->GetParent()->IsCompoundControl() )
+ pCompoundParent = pWin->GetParent();
+
+ if( pCompoundParent )
+ pCompoundParent->SetPaintTransparent( TRUE );
+
+ if( mnWidth < aBounds.GetWidth() || mnHeight < aBounds.GetHeight() )
+ {
+ if( ! pCompoundParent ) // compound controls have to fix themselves
+ {
+ Point aPos( mpBorderWindow->GetPosPixel() );
+ if( mnWidth < aBounds.GetWidth() )
+ aPos.X() -= (aBounds.GetWidth() - mnWidth) / 2;
+ if( mnHeight < aBounds.GetHeight() )
+ aPos.Y() -= (aBounds.GetHeight() - mnHeight) / 2;
+ mpBorderWindow->SetPosSizePixel( aPos, aBounds.GetSize() );
+ }
+ }
+ }
+ }
+ else
+ mbNWFBorder = false;
+ }
+ }
+
+ if( ! mbNWFBorder )
+ {
+ USHORT nStyle = FRAME_DRAW_NODRAW;
+ // Wenn Border umgesetzt wurde oder BorderWindow ein Frame-Fenster
+ // ist, dann Border nach aussen
+ if ( (nBorderStyle & WINDOW_BORDER_DOUBLEOUT) || mpBorderWindow->mbSmallOutBorder )
+ nStyle |= FRAME_DRAW_DOUBLEOUT;
+ else
+ nStyle |= FRAME_DRAW_DOUBLEIN;
+ if ( nBorderStyle & WINDOW_BORDER_MONO )
+ nStyle |= FRAME_DRAW_MONO;
+
+ DecorationView aDecoView( mpOutDev );
+ Rectangle aRect( 0, 0, 10, 10 );
+ Rectangle aCalcRect = aDecoView.DrawFrame( aRect, nStyle );
+ mnLeftBorder = aCalcRect.Left();
+ mnTopBorder = aCalcRect.Top();
+ mnRightBorder = aRect.Right()-aCalcRect.Right();
+ mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSmallBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
+ sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
+{
+ rLeftBorder = mnLeftBorder;
+ rTopBorder = mnTopBorder;
+ rRightBorder = mnRightBorder;
+ rBottomBorder = mnBottomBorder;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplSmallBorderWindowView::CalcTitleWidth() const
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSmallBorderWindowView::DrawWindow( USHORT nDrawFlags, OutputDevice*, const Point* )
+{
+ USHORT nBorderStyle = mpBorderWindow->GetBorderStyle();
+ if ( nBorderStyle & WINDOW_BORDER_NOBORDER )
+ return;
+
+ BOOL bNativeOK = FALSE;
+ // for native widget drawing we must find out what
+ // control this border belongs to
+ Window *pWin = NULL, *pCtrl = NULL;
+ if( mpOutDev->GetOutDevType() == OUTDEV_WINDOW )
+ pWin = (Window*) mpOutDev;
+
+ ControlType aCtrlType = 0;
+ ControlPart aCtrlPart = PART_ENTIRE_CONTROL;
+
+ if( pWin && (pCtrl = mpBorderWindow->GetWindow( WINDOW_CLIENT )) != NULL )
+ {
+ switch( pCtrl->GetType() )
+ {
+ case WINDOW_MULTILINEEDIT:
+ aCtrlType = CTRL_MULTILINE_EDITBOX;
+ break;
+ case WINDOW_EDIT:
+ case WINDOW_PATTERNFIELD:
+ case WINDOW_METRICFIELD:
+ case WINDOW_CURRENCYFIELD:
+ case WINDOW_DATEFIELD:
+ case WINDOW_TIMEFIELD:
+ case WINDOW_LONGCURRENCYFIELD:
+ case WINDOW_NUMERICFIELD:
+ case WINDOW_SPINFIELD:
+ if( pCtrl->GetStyle() & WB_SPIN )
+ aCtrlType = CTRL_SPINBOX;
+ else
+ aCtrlType = CTRL_EDITBOX;
+ break;
+
+ case WINDOW_LISTBOX:
+ case WINDOW_MULTILISTBOX:
+ case WINDOW_TREELISTBOX:
+ aCtrlType = CTRL_LISTBOX;
+ if( pCtrl->GetStyle() & WB_DROPDOWN )
+ aCtrlPart = PART_ENTIRE_CONTROL;
+ else
+ aCtrlPart = PART_WINDOW;
+ break;
+
+ case WINDOW_LISTBOXWINDOW:
+ aCtrlType = CTRL_LISTBOX;
+ aCtrlPart = PART_WINDOW;
+ break;
+
+ case WINDOW_COMBOBOX:
+ case WINDOW_PATTERNBOX:
+ case WINDOW_NUMERICBOX:
+ case WINDOW_METRICBOX:
+ case WINDOW_CURRENCYBOX:
+ case WINDOW_DATEBOX:
+ case WINDOW_TIMEBOX:
+ case WINDOW_LONGCURRENCYBOX:
+ if( pCtrl->GetStyle() & WB_DROPDOWN )
+ {
+ aCtrlType = CTRL_COMBOBOX;
+ aCtrlPart = PART_ENTIRE_CONTROL;
+ }
+ else
+ {
+ aCtrlType = CTRL_LISTBOX;
+ aCtrlPart = PART_WINDOW;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ( aCtrlType && pCtrl->IsNativeControlSupported(aCtrlType, aCtrlPart) )
+ {
+ ImplControlValue aControlValue;
+ ControlState nState = CTRL_STATE_ENABLED;
+
+ if ( !pWin->IsEnabled() )
+ nState &= ~CTRL_STATE_ENABLED;
+ if ( pWin->HasFocus() )
+ nState |= CTRL_STATE_FOCUSED;
+ else if( mbNWFBorder )
+ {
+ // FIXME: this is curently only on aqua, see if other platforms can profit
+
+ // FIXME: for aqua focus rings all controls need to support GetNativeControlRegion
+ // for the dropdown style
+ if( pCtrl->HasFocus() || pCtrl->HasChildPathFocus() )
+ nState |= CTRL_STATE_FOCUSED;
+ }
+
+ BOOL bMouseOver = FALSE;
+ Window *pCtrlChild = pCtrl->GetWindow( WINDOW_FIRSTCHILD );
+ while( pCtrlChild && (bMouseOver = pCtrlChild->IsMouseOver()) == FALSE )
+ pCtrlChild = pCtrlChild->GetWindow( WINDOW_NEXT );
+
+ if( bMouseOver )
+ nState |= CTRL_STATE_ROLLOVER;
+
+ Point aPoint;
+ Rectangle aCtrlRegion( aPoint, Size( mnWidth, mnHeight ) );
+
+ Rectangle aBoundingRgn( aPoint, Size( mnWidth, mnHeight ) );
+ Rectangle aContentRgn( aCtrlRegion );
+ if( ! ImplGetSVData()->maNWFData.mbCanDrawWidgetAnySize &&
+ pWin->GetNativeControlRegion( aCtrlType, aCtrlPart, aCtrlRegion,
+ nState, aControlValue, rtl::OUString(),
+ aBoundingRgn, aContentRgn ))
+ {
+ aCtrlRegion=aContentRgn;
+ }
+
+ bNativeOK = pWin->DrawNativeControl( aCtrlType, aCtrlPart, aCtrlRegion, nState,
+ aControlValue, rtl::OUString() );
+
+ // if the native theme draws the spinbuttons in one call, make sure the proper settings
+ // are passed, this might force a redraw though.... (TODO: improve)
+ if ( (aCtrlType == CTRL_SPINBOX) && !pCtrl->IsNativeControlSupported( CTRL_SPINBOX, PART_BUTTON_UP ) )
+ {
+ Edit *pEdit = ((Edit*) pCtrl)->GetSubEdit();
+ if ( pEdit )
+ pCtrl->Paint( Rectangle() ); // make sure the buttons are also drawn as they might overwrite the border
+ }
+ }
+
+ if( bNativeOK )
+ return;
+
+ if ( nDrawFlags & BORDERWINDOW_DRAW_FRAME )
+ {
+ if ( nBorderStyle & WINDOW_BORDER_ACTIVE )
+ {
+ Color aColor = mpOutDev->GetSettings().GetStyleSettings().GetHighlightColor();
+ mpOutDev->SetLineColor();
+ mpOutDev->SetFillColor( aColor );
+ mpOutDev->DrawRect( Rectangle( 0, 0, mnWidth-1, mnTopBorder ) );
+ mpOutDev->DrawRect( Rectangle( 0, mnHeight-mnBottomBorder, mnWidth-1, mnHeight-1 ) );
+ mpOutDev->DrawRect( Rectangle( 0, 0, mnLeftBorder, mnHeight-1 ) );
+ mpOutDev->DrawRect( Rectangle( mnWidth-mnRightBorder, 0, mnWidth-1, mnHeight-1 ) );
+ }
+ else
+ {
+ USHORT nStyle = 0;
+ // Wenn Border umgesetzt wurde oder BorderWindow ein Frame-Fenster
+ // ist, dann Border nach aussen
+ if ( (nBorderStyle & WINDOW_BORDER_DOUBLEOUT) || mpBorderWindow->mbSmallOutBorder )
+ nStyle |= FRAME_DRAW_DOUBLEOUT;
+ else
+ nStyle |= FRAME_DRAW_DOUBLEIN;
+ if ( nBorderStyle & WINDOW_BORDER_MONO )
+ nStyle |= FRAME_DRAW_MONO;
+ if ( nBorderStyle & WINDOW_BORDER_MENU )
+ nStyle |= FRAME_DRAW_MENU;
+ // tell DrawFrame that we're drawing a window border of a frame window to avoid round corners
+ if( pWin && pWin == pWin->ImplGetFrameWindow() )
+ nStyle |= FRAME_DRAW_WINDOWBORDER;
+
+ DecorationView aDecoView( mpOutDev );
+ Point aTmpPoint;
+ Rectangle aInRect( aTmpPoint, Size( mnWidth, mnHeight ) );
+ aDecoView.DrawFrame( aInRect, nStyle );
+ }
+ }
+}
+
+// =======================================================================
+
+// ---------------------------
+// - ImplStdBorderWindowView -
+// ---------------------------
+
+ImplStdBorderWindowView::ImplStdBorderWindowView( ImplBorderWindow* pBorderWindow )
+{
+ maFrameData.mpBorderWindow = pBorderWindow;
+ maFrameData.mbDragFull = FALSE;
+ maFrameData.mnHitTest = 0;
+ maFrameData.mnPinState = 0;
+ maFrameData.mnCloseState = 0;
+ maFrameData.mnRollState = 0;
+ maFrameData.mnDockState = 0;
+ maFrameData.mnMenuState = 0;
+ maFrameData.mnHideState = 0;
+ maFrameData.mnHelpState = 0;
+ maFrameData.mbTitleClipped = 0;
+
+ mpATitleVirDev = NULL;
+ mpDTitleVirDev = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplStdBorderWindowView::~ImplStdBorderWindowView()
+{
+ if ( mpATitleVirDev )
+ delete mpATitleVirDev;
+ if ( mpDTitleVirDev )
+ delete mpDTitleVirDev;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplStdBorderWindowView::MouseMove( const MouseEvent& rMEvt )
+{
+ return ImplMouseMove( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplStdBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ return ImplMouseButtonDown( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplStdBorderWindowView::Tracking( const TrackingEvent& rTEvt )
+{
+ return ImplTracking( &maFrameData, rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+String ImplStdBorderWindowView::RequestHelp( const Point& rPos, Rectangle& rHelpRect )
+{
+ return ImplRequestHelp( &maFrameData, rPos, rHelpRect );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ImplStdBorderWindowView::GetMenuRect() const
+{
+ return maFrameData.maMenuRect;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStdBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ DecorationView aDecoView( pDev );
+ Rectangle aRect( 0, 0, 10, 10 );
+ Rectangle aCalcRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEOUT | FRAME_DRAW_NODRAW );
+
+ pData->mpOutDev = pDev;
+ pData->mnWidth = nWidth;
+ pData->mnHeight = nHeight;
+
+ pData->mnTitleType = pBorderWindow->mnTitleType;
+ pData->mbFloatWindow = pBorderWindow->mbFloatWindow;
+
+ if ( !(pBorderWindow->GetStyle() & WB_MOVEABLE) || (pData->mnTitleType == BORDERWINDOW_TITLE_NONE) )
+ pData->mnBorderSize = 0;
+ else if ( pData->mnTitleType == BORDERWINDOW_TITLE_TEAROFF )
+ pData->mnBorderSize = 0;
+ else
+ pData->mnBorderSize = rStyleSettings.GetBorderSize();
+ pData->mnLeftBorder = aCalcRect.Left();
+ pData->mnTopBorder = aCalcRect.Top();
+ pData->mnRightBorder = aRect.Right()-aCalcRect.Right();
+ pData->mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
+ pData->mnLeftBorder += pData->mnBorderSize;
+ pData->mnTopBorder += pData->mnBorderSize;
+ pData->mnRightBorder += pData->mnBorderSize;
+ pData->mnBottomBorder += pData->mnBorderSize;
+ pData->mnNoTitleTop = pData->mnTopBorder;
+
+ ImplInitTitle( &maFrameData );
+ if ( pData->mnTitleHeight )
+ {
+ // to improve symbol display force a minum title height
+ if( pData->mnTitleHeight < MIN_CAPTION_HEIGHT )
+ pData->mnTitleHeight = MIN_CAPTION_HEIGHT;
+
+ // set a proper background for drawing
+ // highlighted buttons in the title
+ pBorderWindow->SetBackground( rStyleSettings.GetWindowColor() );
+
+ pData->maTitleRect.Left() = pData->mnLeftBorder;
+ pData->maTitleRect.Right() = nWidth-pData->mnRightBorder-1;
+ pData->maTitleRect.Top() = pData->mnTopBorder;
+ pData->maTitleRect.Bottom() = pData->maTitleRect.Top()+pData->mnTitleHeight-1;
+
+ if ( pData->mnTitleType & (BORDERWINDOW_TITLE_NORMAL | BORDERWINDOW_TITLE_SMALL) )
+ {
+ long nLeft = pData->maTitleRect.Left();
+ long nRight = pData->maTitleRect.Right();
+ long nItemTop = pData->maTitleRect.Top();
+ long nItemBottom = pData->maTitleRect.Bottom();
+ nLeft += 1;
+ nRight -= 3;
+ nItemTop += 2;
+ nItemBottom -= 2;
+
+ if ( pBorderWindow->GetStyle() & WB_PINABLE )
+ {
+ Image aImage;
+ ImplGetPinImage( 0, 0, aImage );
+ pData->maPinRect.Top() = nItemTop;
+ pData->maPinRect.Bottom() = nItemBottom;
+ pData->maPinRect.Left() = nLeft;
+ pData->maPinRect.Right() = pData->maPinRect.Left()+aImage.GetSizePixel().Width();
+ nLeft += pData->maPinRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
+ {
+ pData->maCloseRect.Top() = nItemTop;
+ pData->maCloseRect.Bottom() = nItemBottom;
+ pData->maCloseRect.Right() = nRight;
+ pData->maCloseRect.Left() = pData->maCloseRect.Right()-pData->maCloseRect.GetHeight()+1;
+ nRight -= pData->maCloseRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->mbMenuBtn )
+ {
+ pData->maMenuRect.Top() = nItemTop;
+ pData->maMenuRect.Bottom() = nItemBottom;
+ pData->maMenuRect.Right() = nRight;
+ pData->maMenuRect.Left() = pData->maMenuRect.Right()-pData->maMenuRect.GetHeight()+1;
+ nRight -= pData->maMenuRect.GetWidth();
+ }
+
+ if ( pBorderWindow->mbDockBtn )
+ {
+ pData->maDockRect.Top() = nItemTop;
+ pData->maDockRect.Bottom() = nItemBottom;
+ pData->maDockRect.Right() = nRight;
+ pData->maDockRect.Left() = pData->maDockRect.Right()-pData->maDockRect.GetHeight()+1;
+ nRight -= pData->maDockRect.GetWidth();
+ if ( !pBorderWindow->mbHideBtn &&
+ !(pBorderWindow->GetStyle() & WB_ROLLABLE) )
+ nRight -= 3;
+ }
+
+ if ( pBorderWindow->mbHideBtn )
+ {
+ pData->maHideRect.Top() = nItemTop;
+ pData->maHideRect.Bottom() = nItemBottom;
+ pData->maHideRect.Right() = nRight;
+ pData->maHideRect.Left() = pData->maHideRect.Right()-pData->maHideRect.GetHeight()+1;
+ nRight -= pData->maHideRect.GetWidth();
+ if ( !(pBorderWindow->GetStyle() & WB_ROLLABLE) )
+ nRight -= 3;
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
+ {
+ pData->maRollRect.Top() = nItemTop;
+ pData->maRollRect.Bottom() = nItemBottom;
+ pData->maRollRect.Right() = nRight;
+ pData->maRollRect.Left() = pData->maRollRect.Right()-pData->maRollRect.GetHeight()+1;
+ nRight -= pData->maRollRect.GetWidth();
+ }
+
+ if ( pBorderWindow->mbHelpBtn )
+ {
+ pData->maHelpRect.Top() = nItemTop;
+ pData->maHelpRect.Bottom() = nItemBottom;
+ pData->maHelpRect.Right() = nRight;
+ pData->maHelpRect.Left() = pData->maHelpRect.Right()-pData->maHelpRect.GetHeight()+1;
+ nRight -= pData->maHelpRect.GetWidth()+3;
+ }
+ }
+ else
+ {
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maMenuRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+
+ pData->mnTopBorder += pData->mnTitleHeight;
+ }
+ else
+ {
+ pData->maTitleRect.SetEmpty();
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maMenuRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStdBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
+ sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
+{
+ rLeftBorder = maFrameData.mnLeftBorder;
+ rTopBorder = maFrameData.mnTopBorder;
+ rRightBorder = maFrameData.mnRightBorder;
+ rBottomBorder = maFrameData.mnBottomBorder;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplStdBorderWindowView::CalcTitleWidth() const
+{
+ return ImplCalcTitleWidth( &maFrameData );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStdBorderWindowView::DrawWindow( USHORT nDrawFlags, OutputDevice* pOutDev, const Point* pOffset )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ OutputDevice* pDev = pOutDev ? pOutDev : pData->mpOutDev;
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+ Point aTmpPoint = pOffset ? Point(*pOffset) : Point();
+ Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) );
+ const StyleSettings& rStyleSettings = pData->mpOutDev->GetSettings().GetStyleSettings();
+ DecorationView aDecoView( pDev );
+ Color aFrameColor( rStyleSettings.GetFaceColor() );
+
+ aFrameColor.DecreaseContrast( (UINT8) (0.50 * 255));
+
+ // Draw Frame
+ if ( nDrawFlags & BORDERWINDOW_DRAW_FRAME )
+ {
+ // single line frame
+ pDev->SetLineColor( aFrameColor );
+ pDev->SetFillColor();
+ pDev->DrawRect( aInRect );
+ aInRect.nLeft++; aInRect.nRight--;
+ aInRect.nTop++; aInRect.nBottom--;
+ }
+ else
+ aInRect = aDecoView.DrawFrame( aInRect, FRAME_DRAW_DOUBLEOUT | FRAME_DRAW_NODRAW);
+
+ // Draw Border
+ pDev->SetLineColor();
+ long nBorderSize = pData->mnBorderSize;
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_BORDER) && nBorderSize )
+ {
+ pDev->SetFillColor( rStyleSettings.GetFaceColor() );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top() ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top()+nBorderSize ),
+ Size( nBorderSize, aInRect.GetHeight()-nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Bottom()-nBorderSize+1 ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Right()-nBorderSize+1, aInRect.Top()+nBorderSize ),
+ Size( nBorderSize, aInRect.GetHeight()-nBorderSize ) ) );
+ }
+
+ // Draw Title
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_TITLE) && !pData->maTitleRect.IsEmpty() )
+ {
+ aInRect = pData->maTitleRect;
+
+ // use no gradient anymore, just a static titlecolor
+ pDev->SetFillColor( aFrameColor );
+ pDev->SetTextColor( rStyleSettings.GetButtonTextColor() );
+ Rectangle aTitleRect( pData->maTitleRect );
+ if( pOffset )
+ aTitleRect.Move( pOffset->X(), pOffset->Y() );
+ pDev->DrawRect( aTitleRect );
+
+
+ if ( pData->mnTitleType != BORDERWINDOW_TITLE_TEAROFF )
+ {
+ aInRect.Left() += 2;
+ aInRect.Right() -= 2;
+
+ if ( !pData->maPinRect.IsEmpty() )
+ aInRect.Left() = pData->maPinRect.Right()+2;
+
+ if ( !pData->maHelpRect.IsEmpty() )
+ aInRect.Right() = pData->maHelpRect.Left()-2;
+ else if ( !pData->maRollRect.IsEmpty() )
+ aInRect.Right() = pData->maRollRect.Left()-2;
+ else if ( !pData->maHideRect.IsEmpty() )
+ aInRect.Right() = pData->maHideRect.Left()-2;
+ else if ( !pData->maDockRect.IsEmpty() )
+ aInRect.Right() = pData->maDockRect.Left()-2;
+ else if ( !pData->maMenuRect.IsEmpty() )
+ aInRect.Right() = pData->maMenuRect.Left()-2;
+ else if ( !pData->maCloseRect.IsEmpty() )
+ aInRect.Right() = pData->maCloseRect.Left()-2;
+
+ if ( pOffset )
+ aInRect.Move( pOffset->X(), pOffset->Y() );
+
+ USHORT nTextStyle = TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER | TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_CLIP;
+
+ // must show tooltip ?
+ TextRectInfo aInfo;
+ pDev->GetTextRect( aInRect, pBorderWindow->GetText(), nTextStyle, &aInfo );
+ pData->mbTitleClipped = aInfo.IsEllipses();
+
+ pDev->DrawText( aInRect, pBorderWindow->GetText(), nTextStyle );
+ }
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_CLOSE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maCloseRect.IsEmpty() )
+ {
+ Rectangle aSymbolRect( pData->maCloseRect );
+ if ( pOffset )
+ aSymbolRect.Move( pOffset->X(), pOffset->Y() );
+ ImplDrawBrdWinSymbolButton( pDev, aSymbolRect, SYMBOL_CLOSE, pData->mnCloseState );
+ }
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_DOCK) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maDockRect.IsEmpty() )
+ {
+ Rectangle aSymbolRect( pData->maDockRect );
+ if ( pOffset )
+ aSymbolRect.Move( pOffset->X(), pOffset->Y() );
+ ImplDrawBrdWinSymbolButton( pDev, aSymbolRect, SYMBOL_DOCK, pData->mnDockState );
+ }
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_MENU) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maMenuRect.IsEmpty() )
+ {
+ Rectangle aSymbolRect( pData->maMenuRect );
+ if ( pOffset )
+ aSymbolRect.Move( pOffset->X(), pOffset->Y() );
+ ImplDrawBrdWinSymbolButton( pDev, aSymbolRect, SYMBOL_MENU, pData->mnMenuState );
+ }
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HIDE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHideRect.IsEmpty() )
+ {
+ Rectangle aSymbolRect( pData->maHideRect );
+ if ( pOffset )
+ aSymbolRect.Move( pOffset->X(), pOffset->Y() );
+ ImplDrawBrdWinSymbolButton( pDev, aSymbolRect, SYMBOL_HIDE, pData->mnHideState );
+ }
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_ROLL) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maRollRect.IsEmpty() )
+ {
+ SymbolType eType;
+ if ( pBorderWindow->mbRollUp )
+ eType = SYMBOL_ROLLDOWN;
+ else
+ eType = SYMBOL_ROLLUP;
+ Rectangle aSymbolRect( pData->maRollRect );
+ if ( pOffset )
+ aSymbolRect.Move( pOffset->X(), pOffset->Y() );
+ ImplDrawBrdWinSymbolButton( pDev, aSymbolRect, eType, pData->mnRollState );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HELP) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHelpRect.IsEmpty() )
+ {
+ Rectangle aSymbolRect( pData->maHelpRect );
+ if ( pOffset )
+ aSymbolRect.Move( pOffset->X(), pOffset->Y() );
+ ImplDrawBrdWinSymbolButton( pDev, aSymbolRect, SYMBOL_HELP, pData->mnHelpState );
+ }
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_PIN) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maPinRect.IsEmpty() )
+ {
+ Image aImage;
+ ImplGetPinImage( pData->mnPinState, pBorderWindow->mbPined, aImage );
+ Size aImageSize = aImage.GetSizePixel();
+ long nRectHeight = pData->maPinRect.GetHeight();
+ Point aPos( pData->maPinRect.TopLeft() );
+ if ( pOffset )
+ aPos.Move( pOffset->X(), pOffset->Y() );
+ if ( nRectHeight < aImageSize.Height() )
+ {
+ pDev->DrawImage( aPos, Size( aImageSize.Width(), nRectHeight ), aImage );
+ }
+ else
+ {
+ aPos.Y() += (nRectHeight-aImageSize.Height())/2;
+ pDev->DrawImage( aPos, aImage );
+ }
+ }
+}
+
+
+// =======================================================================
+void ImplBorderWindow::ImplInit( Window* pParent,
+ WinBits nStyle, USHORT nTypeStyle,
+ const ::com::sun::star::uno::Any& )
+{
+ ImplInit( pParent, nStyle, nTypeStyle, NULL );
+}
+
+void ImplBorderWindow::ImplInit( Window* pParent,
+ WinBits nStyle, USHORT nTypeStyle,
+ SystemParentData* pSystemParentData
+ )
+{
+ // Alle WindowBits entfernen, die wir nicht haben wollen
+ WinBits nOrgStyle = nStyle;
+ WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_PINABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW | WB_NEEDSFOCUS);
+ if ( nTypeStyle & BORDERWINDOW_STYLE_APP )
+ nTestStyle |= WB_APP;
+ nStyle &= nTestStyle;
+
+ mpWindowImpl->mbBorderWin = TRUE;
+ mbSmallOutBorder = FALSE;
+ if ( nTypeStyle & BORDERWINDOW_STYLE_FRAME )
+ {
+ if( (nStyle & WB_SYSTEMCHILDWINDOW) )
+ {
+ mpWindowImpl->mbOverlapWin = TRUE;
+ mpWindowImpl->mbFrame = TRUE;
+ mbFrameBorder = FALSE;
+ }
+ else if( (nStyle & WB_OWNERDRAWDECORATION) )
+ {
+ mpWindowImpl->mbOverlapWin = TRUE;
+ mpWindowImpl->mbFrame = TRUE;
+ mbFrameBorder = (nOrgStyle & WB_NOBORDER) ? FALSE : TRUE;
+ }
+ else
+ {
+ mpWindowImpl->mbOverlapWin = TRUE;
+ mpWindowImpl->mbFrame = TRUE;
+ mbFrameBorder = FALSE;
+ // closeable windows may have a border as well, eg. system floating windows without caption
+ if ( (nOrgStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE/* | WB_CLOSEABLE*/)) == WB_BORDER )
+ mbSmallOutBorder = TRUE;
+ }
+ }
+ else if ( nTypeStyle & BORDERWINDOW_STYLE_OVERLAP )
+ {
+ mpWindowImpl->mbOverlapWin = TRUE;
+ mbFrameBorder = TRUE;
+ }
+ else
+ mbFrameBorder = FALSE;
+
+ if ( nTypeStyle & BORDERWINDOW_STYLE_FLOAT )
+ mbFloatWindow = TRUE;
+ else
+ mbFloatWindow = FALSE;
+
+ Window::ImplInit( pParent, nStyle, pSystemParentData );
+ SetBackground();
+ SetTextFillColor();
+
+ mpMenuBarWindow = NULL;
+ mnMinWidth = 0;
+ mnMinHeight = 0;
+ mnMaxWidth = SHRT_MAX;
+ mnMaxHeight = SHRT_MAX;
+ mnRollHeight = 0;
+ mnOrgMenuHeight = 0;
+ mbPined = FALSE;
+ mbRollUp = FALSE;
+ mbMenuHide = FALSE;
+ mbDockBtn = FALSE;
+ mbMenuBtn = FALSE;
+ mbHideBtn = FALSE;
+ mbHelpBtn = FALSE;
+ mbDisplayActive = IsActive();
+
+ if ( nTypeStyle & BORDERWINDOW_STYLE_FLOAT )
+ mnTitleType = BORDERWINDOW_TITLE_SMALL;
+ else
+ mnTitleType = BORDERWINDOW_TITLE_NORMAL;
+ mnBorderStyle = WINDOW_BORDER_NORMAL;
+ InitView();
+}
+
+// =======================================================================
+
+ImplBorderWindow::ImplBorderWindow( Window* pParent,
+ SystemParentData* pSystemParentData,
+ WinBits nStyle, USHORT nTypeStyle
+ ) : Window( WINDOW_BORDERWINDOW )
+{
+ ImplInit( pParent, nStyle, nTypeStyle, pSystemParentData );
+}
+
+// -----------------------------------------------------------------------
+
+ImplBorderWindow::ImplBorderWindow( Window* pParent, WinBits nStyle ,
+ USHORT nTypeStyle ) :
+ Window( WINDOW_BORDERWINDOW )
+{
+ ImplInit( pParent, nStyle, nTypeStyle, ::com::sun::star::uno::Any() );
+}
+
+ImplBorderWindow::ImplBorderWindow( Window* pParent,
+ WinBits nStyle, USHORT nTypeStyle,
+ const ::com::sun::star::uno::Any& aSystemToken ) :
+ Window( WINDOW_BORDERWINDOW )
+{
+ ImplInit( pParent, nStyle, nTypeStyle, aSystemToken );
+}
+
+// -----------------------------------------------------------------------
+
+ImplBorderWindow::~ImplBorderWindow()
+{
+ delete mpBorderView;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ mpBorderView->MouseMove( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ mpBorderView->MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Tracking( const TrackingEvent& rTEvt )
+{
+ mpBorderView->Tracking( rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Paint( const Rectangle& )
+{
+ mpBorderView->DrawWindow( BORDERWINDOW_DRAW_ALL );
+}
+
+void ImplBorderWindow::Draw( const Rectangle&, OutputDevice* pOutDev, const Point& rPos )
+{
+ mpBorderView->DrawWindow( BORDERWINDOW_DRAW_ALL, pOutDev, &rPos );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Activate()
+{
+ SetDisplayActive( TRUE );
+ Window::Activate();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Deactivate()
+{
+ // Fenster die immer Active sind, nehmen wir von dieser Regel aus,
+ // genauso, wenn ein Menu aktiv wird, ignorieren wir das Deactivate
+ if ( GetActivateMode() && !ImplGetSVData()->maWinData.mbNoDeactivate )
+ SetDisplayActive( FALSE );
+ Window::Deactivate();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ // no keyboard help for border win
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) && !rHEvt.KeyboardActivated() )
+ {
+ Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
+ Rectangle aHelpRect;
+ String aHelpStr( mpBorderView->RequestHelp( aMousePosPixel, aHelpRect ) );
+
+ // Rechteck ermitteln
+ if ( aHelpStr.Len() )
+ {
+ aHelpRect.SetPos( OutputToScreenPixel( aHelpRect.TopLeft() ) );
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aHelpStr );
+ else
+ Help::ShowQuickHelp( this, aHelpRect, aHelpStr );
+ return;
+ }
+ }
+
+ Window::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Resize()
+{
+ Size aSize = GetOutputSizePixel();
+
+ if ( !mbRollUp )
+ {
+ Window* pClientWindow = ImplGetClientWindow();
+
+ if ( mpMenuBarWindow )
+ {
+ sal_Int32 nLeftBorder;
+ sal_Int32 nTopBorder;
+ sal_Int32 nRightBorder;
+ sal_Int32 nBottomBorder;
+ long nMenuHeight = mpMenuBarWindow->GetSizePixel().Height();
+ if ( mbMenuHide )
+ {
+ if ( nMenuHeight )
+ mnOrgMenuHeight = nMenuHeight;
+ nMenuHeight = 0;
+ }
+ else
+ {
+ if ( !nMenuHeight )
+ nMenuHeight = mnOrgMenuHeight;
+ }
+ mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ mpMenuBarWindow->SetPosSizePixel( nLeftBorder,
+ nTopBorder,
+ aSize.Width()-nLeftBorder-nRightBorder,
+ nMenuHeight,
+ WINDOW_POSSIZE_POS |
+ WINDOW_POSSIZE_WIDTH | WINDOW_POSSIZE_HEIGHT );
+ }
+
+ GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder,
+ pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder );
+ pClientWindow->ImplPosSizeWindow( pClientWindow->mpWindowImpl->mnLeftBorder,
+ pClientWindow->mpWindowImpl->mnTopBorder,
+ aSize.Width()-pClientWindow->mpWindowImpl->mnLeftBorder-pClientWindow->mpWindowImpl->mnRightBorder,
+ aSize.Height()-pClientWindow->mpWindowImpl->mnTopBorder-pClientWindow->mpWindowImpl->mnBottomBorder,
+ WINDOW_POSSIZE_X | WINDOW_POSSIZE_Y |
+ WINDOW_POSSIZE_WIDTH | WINDOW_POSSIZE_HEIGHT );
+ }
+
+ // UpdateView
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+
+ Window::Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::StateChanged( StateChangedType nType )
+{
+ if ( (nType == STATE_CHANGE_TEXT) ||
+ (nType == STATE_CHANGE_IMAGE) ||
+ (nType == STATE_CHANGE_DATA) )
+ {
+ if ( IsReallyVisible() && mbFrameBorder )
+ {
+ if ( HasPaintEvent() )
+ InvalidateBorder();
+ else
+ mpBorderView->DrawWindow( BORDERWINDOW_DRAW_TITLE );
+ }
+ }
+
+ Window::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ if ( !mpWindowImpl->mbFrame || (GetStyle() & WB_OWNERDRAWDECORATION) )
+ UpdateView( TRUE, ImplGetWindow()->GetOutputSizePixel() );
+ }
+
+ Window::DataChanged( rDCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::InitView()
+{
+ if ( mbSmallOutBorder )
+ mpBorderView = new ImplSmallBorderWindowView( this );
+ else if ( mpWindowImpl->mbFrame )
+ {
+ if( mbFrameBorder )
+ mpBorderView = new ImplStdBorderWindowView( this );
+ else
+ mpBorderView = new ImplNoBorderWindowView( this );
+ }
+ else if ( !mbFrameBorder )
+ mpBorderView = new ImplSmallBorderWindowView( this );
+ else
+ mpBorderView = new ImplStdBorderWindowView( this );
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::UpdateView( BOOL bNewView, const Size& rNewOutSize )
+{
+ sal_Int32 nLeftBorder;
+ sal_Int32 nTopBorder;
+ sal_Int32 nRightBorder;
+ sal_Int32 nBottomBorder;
+ Size aOldSize = GetSizePixel();
+ Size aOutputSize = rNewOutSize;
+
+ if ( bNewView )
+ {
+ delete mpBorderView;
+ InitView();
+ }
+ else
+ {
+ Size aSize = aOutputSize;
+ mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ aSize.Width() += nLeftBorder+nRightBorder;
+ aSize.Height() += nTopBorder+nBottomBorder;
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ }
+
+ Window* pClientWindow = ImplGetClientWindow();
+ if ( pClientWindow )
+ {
+ GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder,
+ pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder );
+ }
+ GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ if ( aOldSize.Width() || aOldSize.Height() )
+ {
+ aOutputSize.Width() += nLeftBorder+nRightBorder;
+ aOutputSize.Height() += nTopBorder+nBottomBorder;
+ if ( aOutputSize == GetSizePixel() )
+ InvalidateBorder();
+ else
+ SetSizePixel( aOutputSize );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::InvalidateBorder()
+{
+ if ( IsReallyVisible() )
+ {
+ // Nur wenn wir einen Border haben, muessen wir auch invalidieren
+ sal_Int32 nLeftBorder;
+ sal_Int32 nTopBorder;
+ sal_Int32 nRightBorder;
+ sal_Int32 nBottomBorder;
+ mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ if ( nLeftBorder || nTopBorder || nRightBorder || nBottomBorder )
+ {
+ Rectangle aWinRect( Point( 0, 0 ), GetOutputSizePixel() );
+ Region aRegion( aWinRect );
+ aWinRect.Left() += nLeftBorder;
+ aWinRect.Top() += nTopBorder;
+ aWinRect.Right() -= nRightBorder;
+ aWinRect.Bottom() -= nBottomBorder;
+ // kein Output-Bereich mehr, dann alles invalidieren
+ if ( (aWinRect.Right() < aWinRect.Left()) ||
+ (aWinRect.Bottom() < aWinRect.Top()) )
+ Invalidate( INVALIDATE_NOCHILDREN );
+ else
+ {
+ aRegion.Exclude( aWinRect );
+ Invalidate( aRegion, INVALIDATE_NOCHILDREN );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetDisplayActive( BOOL bActive )
+{
+ if ( mbDisplayActive != bActive )
+ {
+ mbDisplayActive = bActive;
+ if ( mbFrameBorder )
+ InvalidateBorder();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetTitleType( USHORT nTitleType, const Size& rSize )
+{
+ mnTitleType = nTitleType;
+ UpdateView( FALSE, rSize );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetBorderStyle( USHORT nStyle )
+{
+ if ( !mbFrameBorder && (mnBorderStyle != nStyle) )
+ {
+ mnBorderStyle = nStyle;
+ UpdateView( FALSE, ImplGetWindow()->GetOutputSizePixel() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetPin( BOOL bPin )
+{
+ mbPined = bPin;
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetRollUp( BOOL bRollUp, const Size& rSize )
+{
+ mbRollUp = bRollUp;
+ mnRollHeight = rSize.Height();
+ UpdateView( FALSE, rSize );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetCloser()
+{
+ SetStyle( GetStyle() | WB_CLOSEABLE );
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetDockButton( BOOL bDockButton )
+{
+ mbDockBtn = bDockButton;
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetHideButton( BOOL bHideButton )
+{
+ mbHideBtn = bHideButton;
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetHelpButton( BOOL bHelpButton )
+{
+ mbHelpBtn = bHelpButton;
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetMenuButton( BOOL bMenuButton )
+{
+ mbMenuBtn = bMenuButton;
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::UpdateMenuHeight()
+{
+ Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetMenuBarWindow( Window* pWindow )
+{
+ mpMenuBarWindow = pWindow;
+ UpdateMenuHeight();
+ if ( pWindow )
+ pWindow->Show();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetMenuBarMode( BOOL bHide )
+{
+ mbMenuHide = bHide;
+ UpdateMenuHeight();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
+ sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
+{
+ mpBorderView->GetBorder( rLeftBorder, rTopBorder, rRightBorder, rBottomBorder );
+ if ( mpMenuBarWindow && !mbMenuHide )
+ rTopBorder += mpMenuBarWindow->GetSizePixel().Height();
+}
+
+// -----------------------------------------------------------------------
+
+long ImplBorderWindow::CalcTitleWidth() const
+{
+ return mpBorderView->CalcTitleWidth();
+}
+
+Rectangle ImplBorderWindow::GetMenuRect() const
+{
+ return mpBorderView->GetMenuRect();
+}
diff --git a/vcl/source/window/btndlg.cxx b/vcl/source/window/btndlg.cxx
new file mode 100644
index 000000000000..e835fe749ed1
--- /dev/null
+++ b/vcl/source/window/btndlg.cxx
@@ -0,0 +1,551 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <tools/ref.hxx>
+#include <tools/debug.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/button.hxx>
+#include <vcl/btndlg.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+
+
+
+// =======================================================================
+
+struct ImplBtnDlgItem
+{
+ USHORT mnId;
+ BOOL mbOwnButton;
+ BOOL mbDummyAlign;
+ long mnSepSize;
+ PushButton* mpPushButton;
+};
+
+DECLARE_LIST( ImplBtnDlgItemList, ImplBtnDlgItem* )
+
+// =======================================================================
+
+void ButtonDialog::ImplInitButtonDialogData()
+{
+ mpItemList = new ImplBtnDlgItemList( 8, 8 );
+ mnButtonSize = 0;
+ mnCurButtonId = 0;
+ mnFocusButtonId = BUTTONDIALOG_BUTTON_NOTFOUND;
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+ButtonDialog::ButtonDialog( WindowType nType ) :
+ Dialog( nType )
+{
+ ImplInitButtonDialogData();
+}
+
+// -----------------------------------------------------------------------
+
+ButtonDialog::ButtonDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_BUTTONDIALOG )
+{
+ ImplInitButtonDialogData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ButtonDialog::ButtonDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_BUTTONDIALOG )
+{
+ ImplInitButtonDialogData();
+ rResId.SetRT( RSC_DIALOG ); // !!!!!!!!!! RSC_BUTTONDIALOG !!!!!!!!
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+ButtonDialog::~ButtonDialog()
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mpPushButton && pItem->mbOwnButton )
+ delete pItem->mpPushButton;
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ delete mpItemList;
+}
+
+// -----------------------------------------------------------------------
+
+PushButton* ButtonDialog::ImplCreatePushButton( USHORT nBtnFlags )
+{
+ PushButton* pBtn;
+ WinBits nStyle = 0;
+
+ if ( nBtnFlags & BUTTONDIALOG_DEFBUTTON )
+ nStyle |= WB_DEFBUTTON;
+ if ( nBtnFlags & BUTTONDIALOG_CANCELBUTTON )
+ pBtn = new CancelButton( this, nStyle );
+ else if ( nBtnFlags & BUTTONDIALOG_OKBUTTON )
+ pBtn = new OKButton( this, nStyle );
+ else if ( nBtnFlags & BUTTONDIALOG_HELPBUTTON )
+ pBtn = new HelpButton( this, nStyle );
+ else
+ pBtn = new PushButton( this, nStyle );
+
+ if ( !(nBtnFlags & BUTTONDIALOG_HELPBUTTON) )
+ pBtn->SetClickHdl( LINK( this, ButtonDialog, ImplClickHdl ) );
+
+ return pBtn;
+}
+
+// -----------------------------------------------------------------------
+
+ImplBtnDlgItem* ButtonDialog::ImplGetItem( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nId )
+ return pItem;
+
+ pItem = mpItemList->Next();
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+long ButtonDialog::ImplGetButtonSize()
+{
+ if ( !mbFormat )
+ return mnButtonSize;
+
+ // Calculate ButtonSize
+ long nLastSepSize = 0;
+ long nSepSize = 0;
+ long nButtonCount = 0;
+ maCtrlSize = Size( IMPL_MINSIZE_BUTTON_WIDTH, IMPL_MINSIZE_BUTTON_HEIGHT );
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ nSepSize += nLastSepSize;
+
+ long nTxtWidth = pItem->mpPushButton->GetCtrlTextWidth( pItem->mpPushButton->GetText() );
+ nTxtWidth += IMPL_EXTRA_BUTTON_WIDTH;
+ if ( nTxtWidth > maCtrlSize.Width() )
+ maCtrlSize.Width() = nTxtWidth;
+ long nTxtHeight = pItem->mpPushButton->GetTextHeight();
+ nTxtHeight += IMPL_EXTRA_BUTTON_HEIGHT;
+ if ( nTxtHeight > maCtrlSize.Height() )
+ maCtrlSize.Height() = nTxtHeight;
+
+ nSepSize += pItem->mnSepSize;
+
+ if ( GetStyle() & WB_HORZ )
+ nLastSepSize = IMPL_SEP_BUTTON_X;
+ else
+ nLastSepSize = IMPL_SEP_BUTTON_Y;
+
+ nButtonCount++;
+
+ pItem = mpItemList->Next();
+ }
+
+ if ( GetStyle() & WB_HORZ )
+ mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Width());
+ else
+ mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Height());
+
+ return mnButtonSize;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::ImplPosControls()
+{
+ if ( !mbFormat )
+ return;
+
+ // Create PushButtons and determine Sizes
+ ImplGetButtonSize();
+
+ // determine dialog size
+ ImplBtnDlgItem* pItem;
+ Size aDlgSize = maPageSize;
+ long nX;
+ long nY;
+ if ( GetStyle() & WB_HORZ )
+ {
+ if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Width() )
+ aDlgSize.Width() = mnButtonSize+(IMPL_DIALOG_OFFSET*2);
+ if ( GetStyle() & WB_LEFT )
+ nX = IMPL_DIALOG_OFFSET;
+ else if ( GetStyle() & WB_RIGHT )
+ nX = aDlgSize.Width()-mnButtonSize-IMPL_DIALOG_OFFSET;
+ else
+ nX = (aDlgSize.Width()-mnButtonSize)/2;
+
+ aDlgSize.Height() += IMPL_DIALOG_OFFSET+maCtrlSize.Height();
+ nY = aDlgSize.Height()-maCtrlSize.Height()-IMPL_DIALOG_OFFSET;
+ }
+ else
+ {
+ if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Height() )
+ aDlgSize.Height() = mnButtonSize+(IMPL_DIALOG_OFFSET*2);
+ if ( GetStyle() & WB_BOTTOM )
+ nY = aDlgSize.Height()-mnButtonSize-IMPL_DIALOG_OFFSET;
+ else if ( GetStyle() & WB_VCENTER )
+ nY = (aDlgSize.Height()-mnButtonSize)/2;
+ else
+ nY = IMPL_DIALOG_OFFSET;
+
+ aDlgSize.Width() += IMPL_DIALOG_OFFSET+maCtrlSize.Width();
+ nX = aDlgSize.Width()-maCtrlSize.Width()-IMPL_DIALOG_OFFSET;
+ }
+
+ // Arrange PushButtons
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( GetStyle() & WB_HORZ )
+ nX += pItem->mnSepSize;
+ else
+ nY += pItem->mnSepSize;
+ pItem->mpPushButton->SetPosSizePixel( Point( nX, nY ), maCtrlSize );
+ pItem->mpPushButton->Show();
+ if ( GetStyle() & WB_HORZ )
+ nX += maCtrlSize.Width()+IMPL_SEP_BUTTON_X;
+ else
+ nY += maCtrlSize.Height()+IMPL_SEP_BUTTON_Y;
+
+ pItem = mpItemList->Next();
+ }
+
+ SetOutputSizePixel( aDlgSize );
+
+ mbFormat = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ButtonDialog, ImplClickHdl, PushButton*, pBtn )
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mpPushButton == pBtn )
+ {
+ mnCurButtonId = pItem->mnId;
+ Click();
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::Resize()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ ImplPosControls();
+
+ // Focus evt. auf den entsprechenden Button setzen
+ if ( mnFocusButtonId != BUTTONDIALOG_BUTTON_NOTFOUND )
+ {
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == mnFocusButtonId )
+ {
+ if ( pItem->mpPushButton->IsVisible() )
+ pItem->mpPushButton->GrabFocus();
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+ }
+
+ Dialog::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::Click()
+{
+ if ( !maClickHdl )
+ {
+ if ( IsInExecute() )
+ EndDialog( GetCurButtonId() );
+ }
+ else
+ maClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::AddButton( const XubString& rText, USHORT nId,
+ USHORT nBtnFlags, long nSepPixel )
+{
+ // PageItem anlegen
+ ImplBtnDlgItem* pItem = new ImplBtnDlgItem;
+ pItem->mnId = nId;
+ pItem->mbOwnButton = TRUE;
+ pItem->mnSepSize = nSepPixel;
+ pItem->mpPushButton = ImplCreatePushButton( nBtnFlags );
+ if ( rText.Len() )
+ pItem->mpPushButton->SetText( rText );
+
+ // In die Liste eintragen
+ mpItemList->Insert( pItem, LIST_APPEND );
+
+ if ( nBtnFlags & BUTTONDIALOG_FOCUSBUTTON )
+ mnFocusButtonId = nId;
+
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::AddButton( StandardButtonType eType, USHORT nId,
+ USHORT nBtnFlags, long nSepPixel )
+{
+ // PageItem anlegen
+ ImplBtnDlgItem* pItem = new ImplBtnDlgItem;
+ pItem->mnId = nId;
+ pItem->mbOwnButton = TRUE;
+ pItem->mnSepSize = nSepPixel;
+
+ if ( eType == BUTTON_OK )
+ nBtnFlags |= BUTTONDIALOG_OKBUTTON;
+ else if ( eType == BUTTON_HELP )
+ nBtnFlags |= BUTTONDIALOG_HELPBUTTON;
+ else if ( (eType == BUTTON_CANCEL) || (eType == BUTTON_CLOSE) )
+ nBtnFlags |= BUTTONDIALOG_CANCELBUTTON;
+ pItem->mpPushButton = ImplCreatePushButton( nBtnFlags );
+
+ // Standard-Buttons have the right text already
+ if ( !((eType == BUTTON_OK) && (pItem->mpPushButton->GetType() == WINDOW_OKBUTTON)) ||
+ !((eType == BUTTON_CANCEL) && (pItem->mpPushButton->GetType() == WINDOW_CANCELBUTTON)) ||
+ !((eType == BUTTON_HELP) && (pItem->mpPushButton->GetType() == WINDOW_HELPBUTTON)) )
+ {
+ pItem->mpPushButton->SetText( Button::GetStandardText( eType ) );
+ pItem->mpPushButton->SetHelpText( Button::GetStandardHelpText( eType ) );
+ }
+
+ if ( nBtnFlags & BUTTONDIALOG_FOCUSBUTTON )
+ mnFocusButtonId = nId;
+
+ // In die Liste eintragen
+ mpItemList->Insert( pItem, LIST_APPEND );
+
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::AddButton( PushButton* pBtn, USHORT nId,
+ USHORT nBtnFlags, long nSepPixel )
+{
+ // PageItem anlegen
+ ImplBtnDlgItem* pItem = new ImplBtnDlgItem;
+ pItem->mnId = nId;
+ pItem->mbOwnButton = FALSE;
+ pItem->mnSepSize = nSepPixel;
+ pItem->mpPushButton = pBtn;
+
+ if ( nBtnFlags & BUTTONDIALOG_FOCUSBUTTON )
+ mnFocusButtonId = nId;
+
+ // In die View-Liste eintragen
+ mpItemList->Insert( pItem, LIST_APPEND );
+
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::RemoveButton( USHORT nId )
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nId )
+ {
+ pItem->mpPushButton->Hide();
+ if ( pItem->mbOwnButton )
+ delete pItem->mpPushButton;
+ delete pItem;
+ mpItemList->Remove();
+ mbFormat = TRUE;
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ DBG_ERRORFILE( "ButtonDialog::RemoveButton(): ButtonId invalid" );
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::Clear()
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ pItem->mpPushButton->Hide();
+ if ( pItem->mbOwnButton )
+ delete pItem->mpPushButton;
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ mpItemList->Clear();
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ButtonDialog::GetButtonCount() const
+{
+ return (USHORT)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ButtonDialog::GetButtonId( USHORT nButton ) const
+{
+ if ( nButton < mpItemList->Count() )
+ return (USHORT)mpItemList->GetObject( nButton )->mnId;
+ else
+ return BUTTONDIALOG_BUTTON_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+PushButton* ButtonDialog::GetPushButton( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ return pItem->mpPushButton;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::SetButtonText( USHORT nId, const XubString& rText )
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ {
+ pItem->mpPushButton->SetText( rText );
+ mbFormat = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString ButtonDialog::GetButtonText( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ return pItem->mpPushButton->GetText();
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::SetButtonHelpText( USHORT nId, const XubString& rText )
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ pItem->mpPushButton->SetHelpText( rText );
+}
+
+// -----------------------------------------------------------------------
+
+XubString ButtonDialog::GetButtonHelpText( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ return pItem->mpPushButton->GetHelpText();
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::SetButtonHelpId( USHORT nId, ULONG nHelpId )
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ pItem->mpPushButton->SetHelpId( nHelpId );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG ButtonDialog::GetButtonHelpId( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ return pItem->mpPushButton->GetHelpId();
+ else
+ return 0;
+}
diff --git a/vcl/source/window/cmdevt.cxx b/vcl/source/window/cmdevt.cxx
new file mode 100644
index 000000000000..03e01c96742b
--- /dev/null
+++ b/vcl/source/window/cmdevt.cxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _STRING_H
+#include <string.h>
+#endif
+
+#ifndef _SV_CMDEVT_HXX
+#include <vcl/cmdevt.hxx>
+#endif
+
+// =======================================================================
+
+CommandExtTextInputData::CommandExtTextInputData()
+{
+ mpTextAttr = NULL;
+ mnCursorPos = 0;
+ mnDeltaStart = 0;
+ mnOldTextLen = 0;
+ mnCursorFlags = 0;
+ mbOnlyCursor = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+CommandExtTextInputData::CommandExtTextInputData( const XubString& rText,
+ const USHORT* pTextAttr,
+ xub_StrLen nCursorPos,
+ USHORT nCursorFlags,
+ xub_StrLen nDeltaStart,
+ xub_StrLen nOldTextLen,
+ BOOL bOnlyCursor ) :
+ maText( rText )
+{
+ if ( pTextAttr && maText.Len() )
+ {
+ mpTextAttr = new USHORT[maText.Len()];
+ memcpy( mpTextAttr, pTextAttr, maText.Len()*sizeof(USHORT) );
+ }
+ else
+ mpTextAttr = NULL;
+ mnCursorPos = nCursorPos;
+ mnDeltaStart = nDeltaStart;
+ mnOldTextLen = nOldTextLen;
+ mnCursorFlags = nCursorFlags;
+ mbOnlyCursor = bOnlyCursor;
+}
+
+// -----------------------------------------------------------------------
+
+CommandExtTextInputData::CommandExtTextInputData( const CommandExtTextInputData& rData ) :
+ maText( rData.maText )
+{
+ if ( rData.mpTextAttr && maText.Len() )
+ {
+ mpTextAttr = new USHORT[maText.Len()];
+ memcpy( mpTextAttr, rData.mpTextAttr, maText.Len()*sizeof(USHORT) );
+ }
+ else
+ mpTextAttr = NULL;
+ mnCursorPos = rData.mnCursorPos;
+ mnDeltaStart = rData.mnDeltaStart;
+ mnOldTextLen = rData.mnOldTextLen;
+ mnCursorFlags = rData.mnCursorFlags;
+ mbOnlyCursor = rData.mbOnlyCursor;
+}
+
+// -----------------------------------------------------------------------
+
+CommandExtTextInputData::~CommandExtTextInputData()
+{
+ if ( mpTextAttr )
+ delete [] mpTextAttr;
+}
diff --git a/vcl/source/window/cursor.cxx b/vcl/source/window/cursor.cxx
new file mode 100644
index 000000000000..5725189e10c3
--- /dev/null
+++ b/vcl/source/window/cursor.cxx
@@ -0,0 +1,462 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/window.hxx>
+#include <vcl/window.h>
+#include <tools/poly.hxx>
+#include <vcl/cursor.hxx>
+
+
+// =======================================================================
+
+struct ImplCursorData
+{
+ AutoTimer maTimer; // Timer
+ Point maPixPos; // Pixel-Position
+ Point maPixRotOff; // Pixel-Offset-Position
+ Size maPixSize; // Pixel-Size
+ long mnPixSlant; // Pixel-Slant
+ short mnOrientation; // Pixel-Orientation
+ unsigned char mnDirection; // indicates writing direction
+ USHORT mnStyle; // Cursor-Style
+ BOOL mbCurVisible; // Ist Cursor aktuell sichtbar
+ Window* mpWindow; // Zugeordnetes Windows
+};
+
+// =======================================================================
+
+static void ImplCursorInvert( ImplCursorData* pData )
+{
+ Window* pWindow = pData->mpWindow;
+ BOOL bMapMode = pWindow->IsMapModeEnabled();
+ pWindow->EnableMapMode( FALSE );
+ USHORT nInvertStyle;
+ if ( pData->mnStyle & CURSOR_SHADOW )
+ nInvertStyle = INVERT_50;
+ else
+ nInvertStyle = 0;
+
+ Rectangle aRect( pData->maPixPos, pData->maPixSize );
+ if ( pData->mnDirection || pData->mnOrientation || pData->mnPixSlant )
+ {
+ Polygon aPoly( aRect );
+ if( aPoly.GetSize() == 5 )
+ {
+ aPoly[1].X() += 1; // include the right border
+ aPoly[2].X() += 1;
+ if ( pData->mnPixSlant )
+ {
+ Point aPoint = aPoly.GetPoint( 0 );
+ aPoint.X() += pData->mnPixSlant;
+ aPoly.SetPoint( aPoint, 0 );
+ aPoly.SetPoint( aPoint, 4 );
+ aPoint = aPoly.GetPoint( 1 );
+ aPoint.X() += pData->mnPixSlant;
+ aPoly.SetPoint( aPoint, 1 );
+ }
+
+ // apply direction flag after slant to use the correct shape
+ if ( pData->mnDirection )
+ {
+ Point pAry[7];
+ int delta = 3*aRect.getWidth()+1;
+ if( pData->mnDirection == CURSOR_DIRECTION_LTR )
+ {
+ // left-to-right
+ pAry[0] = aPoly.GetPoint( 0 );
+ pAry[1] = aPoly.GetPoint( 1 );
+ pAry[2] = pAry[1];
+ pAry[2].X() += delta;
+ pAry[3] = pAry[1];
+ pAry[3].Y() += delta;
+ pAry[4] = aPoly.GetPoint( 2 );
+ pAry[5] = aPoly.GetPoint( 3 );
+ pAry[6] = aPoly.GetPoint( 4 );
+ }
+ else if( pData->mnDirection == CURSOR_DIRECTION_RTL )
+ {
+ // right-to-left
+ pAry[0] = aPoly.GetPoint( 0 );
+ pAry[1] = aPoly.GetPoint( 1 );
+ pAry[2] = aPoly.GetPoint( 2 );
+ pAry[3] = aPoly.GetPoint( 3 );
+ pAry[4] = pAry[0];
+ pAry[4].Y() += delta;
+ pAry[5] = pAry[0];
+ pAry[5].X() -= delta;
+ pAry[6] = aPoly.GetPoint( 4 );
+ }
+ aPoly = Polygon( 7, pAry);
+ }
+
+ if ( pData->mnOrientation )
+ aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
+ pWindow->Invert( aPoly, nInvertStyle );
+ }
+ }
+ else
+ pWindow->Invert( aRect, nInvertStyle );
+ pWindow->EnableMapMode( bMapMode );
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplDraw()
+{
+ if ( mpData && mpData->mpWindow && !mpData->mbCurVisible )
+ {
+ Window* pWindow = mpData->mpWindow;
+ mpData->maPixPos = pWindow->LogicToPixel( maPos );
+ mpData->maPixSize = pWindow->LogicToPixel( maSize );
+ mpData->mnPixSlant = pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width();
+ mpData->mnOrientation = mnOrientation;
+ mpData->mnDirection = mnDirection;
+ long nOffsetY = pWindow->LogicToPixel( Size( 0, mnOffsetY ) ).Height();
+
+ // Position um den Offset korrigieren
+ mpData->maPixPos.Y() -= nOffsetY;
+ mpData->maPixRotOff = mpData->maPixPos;
+ mpData->maPixRotOff.Y() += nOffsetY;
+
+ // Wenn groesse 0 ist, nehmen wir die breite, die in den
+ // Settings eingestellt ist
+ if ( !mpData->maPixSize.Width() )
+ mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize();
+
+ // Ausgabeflaeche berechnen und ausgeben
+ ImplCursorInvert( mpData );
+ mpData->mbCurVisible = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplRestore()
+{
+ if ( mpData && mpData->mbCurVisible )
+ {
+ ImplCursorInvert( mpData );
+ mpData->mbCurVisible = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplShow( BOOL bDrawDirect )
+{
+ if ( mbVisible )
+ {
+ Window* pWindow;
+ if ( mpWindow )
+ pWindow = mpWindow;
+ else
+ {
+ // Gibt es ein aktives Fenster und ist der Cursor in dieses Fenster
+ // selektiert, dann zeige den Cursor an
+ pWindow = Application::GetFocusWindow();
+ if ( !pWindow || (pWindow->mpWindowImpl->mpCursor != this) || pWindow->mpWindowImpl->mbInPaint
+ || !pWindow->mpWindowImpl->mpFrameData->mbHasFocus )
+ pWindow = NULL;
+ }
+
+ if ( pWindow )
+ {
+ if ( !mpData )
+ {
+ mpData = new ImplCursorData;
+ mpData->mbCurVisible = FALSE;
+ mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) );
+ }
+
+ mpData->mpWindow = pWindow;
+ mpData->mnStyle = mnStyle;
+ if ( bDrawDirect )
+ ImplDraw();
+
+ if ( !mpWindow )
+ {
+ mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() );
+ if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
+ mpData->maTimer.Start();
+ else if ( !mpData->mbCurVisible )
+ ImplDraw();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplHide()
+{
+ if ( mpData && mpData->mpWindow )
+ {
+ if ( mpData->mbCurVisible )
+ ImplRestore();
+
+ mpData->maTimer.Stop();
+ mpData->mpWindow = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplNew()
+{
+ if ( mbVisible && mpData && mpData->mpWindow )
+ {
+ if ( mpData->mbCurVisible )
+ ImplRestore();
+
+ ImplDraw();
+ if ( !mpWindow )
+ {
+ if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
+ mpData->maTimer.Start();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Cursor, ImplTimerHdl, AutoTimer*, EMPTYARG )
+{
+ if ( mpData->mbCurVisible )
+ ImplRestore();
+ else
+ ImplDraw();
+ return 0;
+}
+
+// =======================================================================
+
+Cursor::Cursor()
+{
+ mpData = NULL;
+ mpWindow = NULL;
+ mnSlant = 0;
+ mnOffsetY = 0;
+ mnOrientation = 0;
+ mnDirection = 0;
+ mnStyle = 0;
+ mbVisible = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Cursor::Cursor( const Cursor& rCursor ) :
+ maSize( rCursor.maSize ),
+ maPos( rCursor.maPos )
+{
+ mpData = NULL;
+ mpWindow = NULL;
+ mnSlant = rCursor.mnSlant;
+ mnOrientation = rCursor.mnOrientation;
+ mnDirection = rCursor.mnDirection;
+ mnStyle = 0;
+ mbVisible = rCursor.mbVisible;
+}
+
+// -----------------------------------------------------------------------
+
+Cursor::~Cursor()
+{
+ if ( mpData )
+ {
+ if ( mpData->mbCurVisible )
+ ImplRestore();
+
+ delete mpData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetStyle( USHORT nStyle )
+{
+ if ( mnStyle != nStyle )
+ {
+ mnStyle = nStyle;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::Show()
+{
+ if ( !mbVisible )
+ {
+ mbVisible = TRUE;
+ ImplShow();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::Hide()
+{
+ if ( mbVisible )
+ {
+ mbVisible = FALSE;
+ ImplHide();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetWindow( Window* pWindow )
+{
+ if ( mpWindow != pWindow )
+ {
+ mpWindow = pWindow;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetPos( const Point& rPoint )
+{
+ if ( maPos != rPoint )
+ {
+ maPos = rPoint;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetOffsetY( long nNewOffsetY )
+{
+ if ( mnOffsetY != nNewOffsetY )
+ {
+ mnOffsetY = nNewOffsetY;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetSize( const Size& rSize )
+{
+ if ( maSize != rSize )
+ {
+ maSize = rSize;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetWidth( long nNewWidth )
+{
+ if ( maSize.Width() != nNewWidth )
+ {
+ maSize.Width() = nNewWidth;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetHeight( long nNewHeight )
+{
+ if ( maSize.Height() != nNewHeight )
+ {
+ maSize.Height() = nNewHeight;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetSlant( long nNewSlant )
+{
+ if ( mnSlant != nNewSlant )
+ {
+ mnSlant = nNewSlant;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetOrientation( short nNewOrientation )
+{
+ if ( mnOrientation != nNewOrientation )
+ {
+ mnOrientation = nNewOrientation;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetDirection( unsigned char nNewDirection )
+{
+ if ( mnDirection != nNewDirection )
+ {
+ mnDirection = nNewDirection;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Cursor& Cursor::operator=( const Cursor& rCursor )
+{
+ maPos = rCursor.maPos;
+ maSize = rCursor.maSize;
+ mnSlant = rCursor.mnSlant;
+ mnOrientation = rCursor.mnOrientation;
+ mnDirection = rCursor.mnDirection;
+ mbVisible = rCursor.mbVisible;
+ ImplNew();
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Cursor::operator==( const Cursor& rCursor ) const
+{
+ if ( (maPos == rCursor.maPos) &&
+ (maSize == rCursor.maSize) &&
+ (mnSlant == rCursor.mnSlant) &&
+ (mnOrientation == rCursor.mnOrientation) &&
+ (mnDirection == rCursor.mnDirection) &&
+ (mbVisible == rCursor.mbVisible) )
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/vcl/source/window/decoview.cxx b/vcl/source/window/decoview.cxx
new file mode 100644
index 000000000000..e5c3dc525cec
--- /dev/null
+++ b/vcl/source/window/decoview.cxx
@@ -0,0 +1,1388 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <vcl/settings.hxx>
+#include <tools/poly.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/window.hxx>
+#include <vcl/ctrl.hxx>
+
+// =======================================================================
+
+#define BUTTON_DRAW_FLATTEST (BUTTON_DRAW_FLAT | \
+ BUTTON_DRAW_PRESSED | \
+ BUTTON_DRAW_CHECKED | \
+ BUTTON_DRAW_HIGHLIGHT)
+
+// =======================================================================
+
+void ImplDrawOS2Symbol( OutputDevice* pDev, const Rectangle& rRect,
+ USHORT nStyle, BOOL bClose )
+{
+ DecorationView aView( pDev );
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ Rectangle aRect = rRect;
+ Color aColor1;
+ Color aColor2;
+
+ pDev->SetFillColor();
+
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ aColor1 = rStyleSettings.GetShadowColor();
+ aColor2 = rStyleSettings.GetLightColor();
+ }
+ else
+ {
+ aColor1 = rStyleSettings.GetLightColor();
+ aColor2 = rStyleSettings.GetShadowColor();
+ }
+ aView.DrawFrame( aRect, aColor1, aColor2 );
+
+ aRect.Left() += 2;
+ aRect.Top() += 2;
+ aRect.Right() -= 2;
+ aRect.Bottom() -= 2;
+
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ if ( bClose )
+ {
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom()-2 ) );
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right()-2, aRect.Top() ) );
+ pDev->DrawLine( Point( aRect.Left()+2, aRect.Bottom()-1 ),
+ Point( aRect.Right()-1, aRect.Top()+2 ) );
+ }
+ else
+ {
+ pDev->DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right()-1, aRect.Top() ) );
+ }
+
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ if ( bClose )
+ {
+ pDev->DrawLine( Point( aRect.Right(), aRect.Top()+2 ), aRect.BottomRight() );
+ pDev->DrawLine( Point( aRect.Left()+2, aRect.Bottom() ), aRect.BottomRight() );
+ pDev->DrawLine( Point( aRect.Right()-2, aRect.Top()+1 ),
+ Point( aRect.Left()+1, aRect.Bottom()-2 ) );
+ }
+ else
+ {
+ pDev->DrawLine( aRect.TopRight(), aRect.BottomRight() );
+ pDev->DrawLine( Point( aRect.Left()+1, aRect.Bottom() ), aRect.BottomRight() );
+ }
+}
+
+// =======================================================================
+
+static void ImplDrawSymbol( OutputDevice* pDev, const Rectangle& rRect,
+ SymbolType eType )
+{
+ // Groessen vorberechnen
+ long nMin = Min( rRect.GetWidth(), rRect.GetHeight() );
+ long nSize = nMin;
+
+ if ( nMin & 0x01 )
+ nMin--;
+ Point aCenter = rRect.Center();
+ long nCenterX = aCenter.X();
+ long nCenterY = aCenter.Y();
+ long n2 = nMin / 2;
+ long n4 = nMin / 4;
+ long nLeft;
+ long nTop;
+ long nRight;
+ long nBottom;
+ long nTemp;
+ long i;
+
+ switch ( eType )
+ {
+ case SYMBOL_ARROW_UP:
+ {
+ if ( !(nMin & 0x01) )
+ {
+ n2--;
+ n4--;
+ }
+ nTop = nCenterY-n2;
+ nBottom = nCenterY;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nTop++;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ pDev->DrawRect( Rectangle( nCenterX-n4, nBottom,
+ nCenterX+n4, nBottom+n2 ) );
+ }
+ break;
+
+ case SYMBOL_ARROW_DOWN:
+ {
+ if ( !(nMin & 0x01) )
+ {
+ n2--;
+ n4--;
+ }
+ nTop = nCenterY;
+ nBottom = nCenterY+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nBottom--;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ pDev->DrawRect( Rectangle( nCenterX-n4, nTop-n2,
+ nCenterX+n4, nTop ) );
+ }
+ break;
+
+ case SYMBOL_ARROW_LEFT:
+ {
+ if ( !(nMin & 0x01) )
+ {
+ n2--;
+ n4--;
+ }
+ nLeft = nCenterX-n2;
+ nRight = nCenterX;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nLeft++;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ i++;
+ }
+ pDev->DrawRect( Rectangle( nRight, nCenterY-n4,
+ nRight+n2, nCenterY+n4 ) );
+ }
+ break;
+
+ case SYMBOL_ARROW_RIGHT:
+ {
+ if ( !(nMin & 0x01) )
+ {
+ n2--;
+ n4--;
+ }
+ nLeft = nCenterX;
+ nRight = nCenterX+n2;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nRight--;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ i++;
+ }
+ pDev->DrawRect( Rectangle( nLeft-n2, nCenterY-n4,
+ nLeft, nCenterY+n4 ) );
+ }
+ break;
+
+
+ case SYMBOL_SPIN_UP:
+ {
+ if ( !(nMin & 0x01) )
+ n2--;
+ nTop = nCenterY-n4;
+ nBottom = nTop+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nTop++;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_SPIN_DOWN:
+ {
+ if ( !(nMin & 0x01) )
+ n2--;
+ nTop = nCenterY-n4;
+ nBottom = nTop+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nBottom--;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_SPIN_LEFT:
+ case SYMBOL_FIRST:
+ case SYMBOL_PREV:
+ case SYMBOL_REVERSEPLAY:
+ {
+ if ( !(nMin & 0x01) )
+ n2--;
+ nLeft = nCenterX-n4;
+ if ( eType == SYMBOL_FIRST )
+ nLeft++;
+ nRight = nLeft+n2;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nLeft++;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ i++;
+ }
+ if ( eType == SYMBOL_FIRST )
+ {
+ pDev->DrawRect( Rectangle( nCenterX-n4-1, nCenterY-n2,
+ nCenterX-n4-1, nCenterY+n2 ) );
+ }
+ }
+ break;
+
+ case SYMBOL_SPIN_RIGHT:
+ case SYMBOL_LAST:
+ case SYMBOL_NEXT:
+ case SYMBOL_PLAY:
+ {
+ if ( !(nMin & 0x01) )
+ n2--;
+ nLeft = nCenterX-n4;
+ if ( eType == SYMBOL_LAST )
+ nLeft--;
+ nRight = nLeft+n2;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nRight--;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ i++;
+ }
+ if ( eType == SYMBOL_LAST )
+ {
+ pDev->DrawRect( Rectangle( nCenterX+n4+1, nCenterY-n2,
+ nCenterX+n4+1, nCenterY+n2 ) );
+ }
+ }
+ break;
+
+ case SYMBOL_PAGEUP:
+ case SYMBOL_PAGEDOWN:
+ {
+ if ( !( nSize & 0x01 ))
+ {
+ // An even rectangle size means we have to use a smaller size for
+ // our arrows as we want to use one pixel for the spearhead! Otherwise
+ // it will be clipped!
+ nCenterX++;
+ n2 = ( nMin-1 ) / 2;
+ n4 = ( nMin-1 ) / 4;
+ }
+
+ nTop = nCenterY-n2;
+ nBottom = nCenterY-1;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ pDev->DrawRect( Rectangle( nCenterX, nTop+n2+1, nCenterX, nBottom+n2+1 ) );
+ i = 1;
+ while ( i < n2 )
+ {
+ ( eType == SYMBOL_PAGEUP ) ? nTop++ : nBottom--;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ pDev->DrawRect( Rectangle( nTemp, nTop+n2+1, nTemp, nBottom+n2+1 ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ pDev->DrawRect( Rectangle( nTemp, nTop+n2+1, nTemp, nBottom+n2+1 ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_RADIOCHECKMARK:
+ case SYMBOL_RECORD:
+ {
+ const long nExt = ( n2 << 1 ) + 1;
+ Bitmap aBmp( Size( nExt, nExt ), 1 );
+ BitmapWriteAccess* pWAcc = aBmp.AcquireWriteAccess();
+
+ if( pWAcc )
+ {
+ const Color aWhite( COL_WHITE );
+ const Color aBlack( COL_BLACK );
+
+ pWAcc->Erase( aWhite );
+ pWAcc->SetLineColor( aBlack );
+ pWAcc->SetFillColor( aBlack );
+ pWAcc->DrawPolygon( Polygon( Point( n2, n2 ), n2, n2 ) );
+ aBmp.ReleaseAccess( pWAcc );
+ pDev->DrawMask( Point( nCenterX - n2, nCenterY - n2 ), aBmp, pDev->GetFillColor() );
+ }
+ else
+ pDev->DrawPolygon( Polygon( Point( nCenterX, nCenterY ), n2, n2 ) );
+ }
+ break;
+
+ case SYMBOL_STOP:
+ {
+ nLeft = nCenterX-n2;
+ nRight = nCenterX+n2;
+ nTop = nCenterY-n2;
+ nBottom = nCenterY+n2;
+ pDev->DrawRect( Rectangle( nLeft, nTop, nRight, nBottom ) );
+ }
+ break;
+
+ case SYMBOL_PAUSE:
+ {
+ nLeft = nCenterX-n2;
+ nRight = nCenterX+n2-1;
+ nTop = nCenterY-n2;
+ nBottom = nCenterY+n2;
+ pDev->DrawRect( Rectangle( nLeft, nTop, nCenterX-2, nBottom ) );
+ pDev->DrawRect( Rectangle( nCenterX+1, nTop, nRight, nBottom ) );
+ }
+ break;
+
+ case SYMBOL_WINDSTART:
+ case SYMBOL_WINDBACKWARD:
+ {
+ nLeft = nCenterX-n2+1;
+ nRight = nCenterX;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nCenterY, nRight+n2, nCenterY ) );
+ i = 1;
+ while ( i < n2 )
+ {
+ nLeft++;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nTemp, nRight+n2, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nTemp, nRight+n2, nTemp ) );
+ i++;
+ }
+ if ( eType == SYMBOL_WINDSTART )
+ {
+ pDev->DrawRect( Rectangle( nCenterX-n2, nCenterY-n2,
+ nCenterX-n2, nCenterY+n2 ) );
+ }
+ }
+ break;
+
+ case SYMBOL_WINDEND:
+ case SYMBOL_WINDFORWARD:
+ {
+ nLeft = nCenterX-n2;
+ nRight = nCenterX-1;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nCenterY, nRight+n2, nCenterY ) );
+ i = 1;
+ while ( i < n2 )
+ {
+ nRight--;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nTemp, nRight+n2, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nTemp, nRight+n2, nTemp ) );
+ i++;
+ }
+ if ( eType == SYMBOL_WINDEND )
+ {
+ pDev->DrawRect( Rectangle( nCenterX+n2, nCenterY-n2,
+ nCenterX+n2, nCenterY+n2 ) );
+ }
+ }
+ break;
+
+ case SYMBOL_CLOSE:
+ {
+ Size aRectSize( 2, 1 );
+ if ( nMin < 8 )
+ aRectSize.Width() = 1;
+ else if ( nMin > 20 )
+ aRectSize.Width() = nMin/10;
+ nLeft = nCenterX-n2+1;
+ nTop = nCenterY-n2+1;
+ nBottom = nCenterY-n2+nMin-aRectSize.Width()+1;
+ i = 0;
+ while ( i < nMin-aRectSize.Width()+1 )
+ {
+ pDev->DrawRect( Rectangle( Point( nLeft+i, nTop+i ), aRectSize ) );
+ pDev->DrawRect( Rectangle( Point( nLeft+i, nBottom-i ), aRectSize ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_ROLLUP:
+ case SYMBOL_ROLLDOWN:
+ {
+ Rectangle aRect( nCenterX-n2, nCenterY-n2,
+ nCenterX+n2, nCenterY-n2+1 );
+ pDev->DrawRect( aRect );
+ if ( eType == SYMBOL_ROLLDOWN )
+ {
+ Rectangle aTempRect = aRect;
+ aTempRect.Bottom() = nCenterY+n2;
+ aTempRect.Right() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Left() = aRect.Right();
+ aTempRect.Right() = aRect.Right();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Top() = aTempRect.Bottom();
+ aTempRect.Left() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ }
+ }
+ break;
+ case SYMBOL_CHECKMARK:
+ {
+ // #106953# never mirror checkmarks
+ BOOL bRTL = pDev->ImplHasMirroredGraphics() && pDev->IsRTLEnabled();
+ Point aPos1( bRTL ? rRect.Right() : rRect.Left(),
+ rRect.Bottom() - rRect.GetHeight() / 3 );
+ Point aPos2( bRTL ? rRect.Right() - rRect.GetWidth()/3 : rRect.Left() + rRect.GetWidth()/3,
+ rRect.Bottom() );
+ Point aPos3( bRTL ? rRect.TopLeft() : rRect.TopRight() );
+ Size aRectSize( 1, 2 );
+ long nStepsY = aPos2.Y()-aPos1.Y();
+ long nX = aPos1.X();
+ long nY = aPos1.Y();
+ long n;
+ for ( n = 0; n <= nStepsY; n++ )
+ {
+ if( bRTL )
+ nX--;
+ pDev->DrawRect( Rectangle( Point( nX, nY++ ), aRectSize ) );
+ if( !bRTL )
+ nX++;
+ }
+ nStepsY = aPos2.Y()-aPos3.Y();
+ nX = aPos2.X();
+ nY = aPos2.Y();
+ for ( n = 0; n <= nStepsY; n++ )
+ {
+ if( bRTL )
+ if ( --nX < rRect.Left() )
+ break;
+ pDev->DrawRect( Rectangle( Point( nX, nY-- ), aRectSize ) );
+ if( !bRTL )
+ if ( ++nX > rRect.Right() )
+ break;
+ }
+ }
+ break;
+
+ case SYMBOL_SPIN_UPDOWN:
+ {
+ nTop = nCenterY-n2-1;
+ nBottom = nTop+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nTop++;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ nTop = nCenterY+1;
+ nBottom = nTop+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nBottom--;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ }
+ break;
+
+
+ case SYMBOL_FLOAT:
+ {
+ Rectangle aRect( nCenterX-n2, nCenterY-n2+3,
+ nCenterX+n2-2, nCenterY-n2+4 );
+ pDev->DrawRect( aRect );
+ Rectangle aTempRect = aRect;
+ aTempRect.Bottom() = nCenterY+n2;
+ aTempRect.Right() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Left() = aRect.Right();
+ aTempRect.Right() = aRect.Right();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Top() = aTempRect.Bottom();
+ aTempRect.Left() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aRect = Rectangle( nCenterX-n2+2, nCenterY-n2,
+ nCenterX+n2, nCenterY-n2+1 );
+ pDev->DrawRect( aRect );
+ aTempRect = aRect;
+ aTempRect.Bottom() = nCenterY+n2-3;
+ aTempRect.Right() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Left() = aRect.Right();
+ aTempRect.Right() = aRect.Right();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Top() = aTempRect.Bottom();
+ aTempRect.Left() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ }
+ break;
+ case SYMBOL_DOCK:
+ {
+ Rectangle aRect( nCenterX-n2, nCenterY-n2,
+ nCenterX+n2, nCenterY-n2 );
+ pDev->DrawRect( aRect );
+ Rectangle aTempRect = aRect;
+ aTempRect.Bottom() = nCenterY+n2;
+ aTempRect.Right() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Left() = aRect.Right();
+ aTempRect.Right() = aRect.Right();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Top() = aTempRect.Bottom();
+ aTempRect.Left() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ }
+ break;
+ case SYMBOL_HIDE:
+ {
+ long nExtra = nMin / 8;
+ Rectangle aRect( nCenterX-n2+nExtra, nCenterY+n2-1,
+ nCenterX+n2-nExtra, nCenterY+n2 );
+ pDev->DrawRect( aRect );
+ }
+ break;
+
+ case SYMBOL_OS2CLOSE:
+ {
+ Rectangle aRect( nCenterX-n2, nCenterY-n2,
+ nCenterX+n2, nCenterY+n2 );
+ ImplDrawOS2Symbol( pDev, aRect, 0, TRUE );
+ }
+ break;
+
+ case SYMBOL_OS2FLOAT:
+ {
+ Rectangle aRect( nCenterX-n2+4, nCenterY-n2+4,
+ nCenterX+n2-4, nCenterY+n2-3 );
+ ImplDrawOS2Symbol( pDev, aRect, 0, FALSE );
+ DecorationView aDecoView( pDev );
+ Rectangle aRect2( nCenterX-n2, nCenterY-n2,
+ nCenterX-n2+2, nCenterY+n2 );
+ aDecoView.DrawFrame( aRect2,
+ pDev->GetSettings().GetStyleSettings().GetLightColor(),
+ pDev->GetSettings().GetStyleSettings().GetShadowColor() );
+ Rectangle aRect3( nCenterX+n2-2, nCenterY-n2,
+ nCenterX+n2, nCenterY+n2 );
+ aDecoView.DrawFrame( aRect3,
+ pDev->GetSettings().GetStyleSettings().GetLightColor(),
+ pDev->GetSettings().GetStyleSettings().GetShadowColor() );
+ }
+ break;
+
+ case SYMBOL_OS2HIDE:
+ {
+ Rectangle aRect( nCenterX-n2+3, nCenterY-n2+3,
+ nCenterX+n2-3, nCenterY+n2-3 );
+ ImplDrawOS2Symbol( pDev, aRect, 0, FALSE );
+ }
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DecorationView::DrawSymbol( const Rectangle& rRect, SymbolType eType,
+ const Color& rColor, USHORT nStyle )
+{
+ const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
+ Rectangle aRect = mpOutDev->LogicToPixel( rRect );
+ Color aOldLineColor = mpOutDev->GetLineColor();
+ Color aOldFillColor = mpOutDev->GetFillColor();
+ BOOL bOldMapMode = mpOutDev->IsMapModeEnabled();
+ mpOutDev->SetLineColor();
+ mpOutDev->SetFillColor( rColor );
+ mpOutDev->EnableMapMode( FALSE );
+
+ if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ||
+ (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
+ nStyle |= BUTTON_DRAW_MONO;
+
+ if ( nStyle & SYMBOL_DRAW_MONO )
+ {
+ if ( nStyle & SYMBOL_DRAW_DISABLE )
+ mpOutDev->SetFillColor( Color( COL_GRAY ) );
+ else
+ mpOutDev->SetFillColor( Color( COL_BLACK ) );
+ }
+ else
+ {
+ if ( nStyle & SYMBOL_DRAW_DISABLE )
+ {
+ // Als Embosed ausgeben
+ mpOutDev->SetFillColor( rStyleSettings.GetLightColor() );
+ Rectangle aTempRect = aRect;
+ aTempRect.Move( 1, 1 );
+ ImplDrawSymbol( mpOutDev, aTempRect, eType );
+ mpOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
+ }
+ else
+ mpOutDev->SetFillColor( rColor );
+ }
+
+ ImplDrawSymbol( mpOutDev, aRect, eType );
+
+ mpOutDev->SetLineColor( aOldLineColor );
+ mpOutDev->SetFillColor( aOldFillColor );
+ mpOutDev->EnableMapMode( bOldMapMode );
+}
+
+// =======================================================================
+
+void DecorationView::DrawFrame( const Rectangle& rRect,
+ const Color& rLeftTopColor,
+ const Color& rRightBottomColor )
+{
+ Rectangle aRect = mpOutDev->LogicToPixel( rRect );
+ Color aOldLineColor = mpOutDev->GetLineColor();
+ Color aOldFillColor = mpOutDev->GetFillColor();
+ BOOL bOldMapMode = mpOutDev->IsMapModeEnabled();
+ mpOutDev->EnableMapMode( FALSE );
+ mpOutDev->SetLineColor();
+ mpOutDev->ImplDraw2ColorFrame( aRect, rLeftTopColor, rRightBottomColor );
+ mpOutDev->SetLineColor( aOldLineColor );
+ mpOutDev->SetFillColor( aOldFillColor );
+ mpOutDev->EnableMapMode( bOldMapMode );
+}
+
+// =======================================================================
+
+void DecorationView::DrawHighlightFrame( const Rectangle& rRect,
+ USHORT nStyle )
+{
+ const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
+ Color aLightColor = rStyleSettings.GetLightColor();
+ Color aShadowColor = rStyleSettings.GetShadowColor();
+
+ if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ||
+ (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
+ {
+ aLightColor = Color( COL_BLACK );
+ aShadowColor = Color( COL_BLACK );
+ }
+ else if ( nStyle & FRAME_HIGHLIGHT_TESTBACKGROUND )
+ {
+ Wallpaper aBackground = mpOutDev->GetBackground();
+ if ( aBackground.IsBitmap() || aBackground.IsGradient() )
+ {
+ aLightColor = rStyleSettings.GetFaceColor();
+ aShadowColor = Color( COL_BLACK );
+ }
+ else
+ {
+ Color aBackColor = aBackground.GetColor();
+ if ( (aLightColor.GetColorError( aBackColor ) < 32) ||
+ (aShadowColor.GetColorError( aBackColor ) < 32) )
+ {
+ aLightColor = Color( COL_WHITE );
+ aShadowColor = Color( COL_BLACK );
+
+ if ( aLightColor.GetColorError( aBackColor ) < 32 )
+ aLightColor.DecreaseLuminance( 64 );
+ if ( aShadowColor.GetColorError( aBackColor ) < 32 )
+ aShadowColor.IncreaseLuminance( 64 );
+ }
+ }
+ }
+
+ if ( (nStyle & FRAME_HIGHLIGHT_STYLE) == FRAME_HIGHLIGHT_IN )
+ {
+ Color aTempColor = aLightColor;
+ aLightColor = aShadowColor;
+ aShadowColor = aTempColor;
+ }
+
+ DrawFrame( rRect, aLightColor, aShadowColor );
+}
+
+// =======================================================================
+
+static void ImplDrawDPILineRect( OutputDevice* pDev, Rectangle& rRect,
+ const Color* pColor, BOOL bRound = FALSE )
+{
+ long nLineWidth = pDev->ImplGetDPIX()/300;
+ long nLineHeight = pDev->ImplGetDPIY()/300;
+ if ( !nLineWidth )
+ nLineWidth = 1;
+ if ( !nLineHeight )
+ nLineHeight = 1;
+
+ if ( pColor )
+ {
+ if ( (nLineWidth == 1) && (nLineHeight == 1) )
+ {
+ pDev->SetLineColor( *pColor );
+ pDev->SetFillColor();
+ if( bRound )
+ {
+ pDev->DrawLine( Point( rRect.Left()+1, rRect.Top()), Point( rRect.Right()-1, rRect.Top()) );
+ pDev->DrawLine( Point( rRect.Left()+1, rRect.Bottom()), Point( rRect.Right()-1, rRect.Bottom()) );
+ pDev->DrawLine( Point( rRect.Left(), rRect.Top()+1), Point( rRect.Left(), rRect.Bottom()-1) );
+ pDev->DrawLine( Point( rRect.Right(), rRect.Top()+1), Point( rRect.Right(), rRect.Bottom()-1) );
+ }
+ else
+ pDev->DrawRect( rRect );
+ }
+ else
+ {
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+ pDev->SetLineColor();
+ pDev->SetFillColor( *pColor );
+ pDev->DrawRect( Rectangle( rRect.TopLeft(), Size( nWidth, nLineHeight ) ) );
+ pDev->DrawRect( Rectangle( rRect.TopLeft(), Size( nLineWidth, nHeight ) ) );
+ pDev->DrawRect( Rectangle( Point( rRect.Left(), rRect.Bottom()-nLineHeight ),
+ Size( nWidth, nLineHeight ) ) );
+ pDev->DrawRect( Rectangle( Point( rRect.Right()-nLineWidth, rRect.Top() ),
+ Size( nLineWidth, nHeight ) ) );
+ }
+ }
+
+ rRect.Left() += nLineWidth;
+ rRect.Top() += nLineHeight;
+ rRect.Right() -= nLineWidth;
+ rRect.Bottom() -= nLineHeight;
+}
+
+// =======================================================================
+
+static void ImplDrawFrame( OutputDevice* pDev, Rectangle& rRect,
+ const StyleSettings& rStyleSettings, USHORT nStyle )
+{
+ // mask menu style
+ BOOL bMenuStyle = (nStyle & FRAME_DRAW_MENU) ? TRUE : FALSE;
+ nStyle &= ~FRAME_DRAW_MENU;
+
+ Window *pWin = NULL;
+ if( pDev->GetOutDevType() == OUTDEV_WINDOW )
+ pWin = (Window*) pDev;
+
+ // UseFlatBorders disables 3D style for all frames except menus
+ // menus may use different border colors (eg on XP)
+ // normal frames will be drawn using the shadow color
+ // whereas window frame borders will use black
+ BOOL bFlatBorders = ( !bMenuStyle && rStyleSettings.GetUseFlatBorders() );
+
+ // no flat borders for standard VCL controls (ie formcontrols that keep their classic look)
+ // will not affect frame windows (like dropdowns)
+ if( bFlatBorders && pWin && pWin->GetType() == WINDOW_BORDERWINDOW && (pWin != pWin->ImplGetFrameWindow()) )
+ {
+ // check for formcontrol, i.e., a control without NWF enabled
+ Control *pControl = dynamic_cast< Control* >( pWin->GetWindow( WINDOW_CLIENT ) );
+ if( pControl && pControl->IsNativeWidgetEnabled() )
+ bFlatBorders = TRUE;
+ else
+ bFlatBorders = FALSE;
+ }
+
+ // no round corners for window frame borders
+ BOOL bRound = (bFlatBorders && !(nStyle & FRAME_DRAW_WINDOWBORDER));
+
+ if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ||
+ (pDev->GetOutDevType() == OUTDEV_PRINTER) ||
+ bFlatBorders )
+ nStyle |= FRAME_DRAW_MONO;
+
+ if ( nStyle & FRAME_DRAW_NODRAW )
+ {
+ USHORT nValueStyle = bMenuStyle ? nStyle | FRAME_DRAW_MENU : nStyle;
+ if( pWin->GetType() == WINDOW_BORDERWINDOW )
+ nValueStyle |= FRAME_DRAW_BORDERWINDOWBORDER;
+ ImplControlValue aControlValue( nValueStyle );
+ Rectangle aBound, aContent;
+ Rectangle aNatRgn( rRect );
+ if(pWin && pWin->GetNativeControlRegion(CTRL_FRAME, PART_BORDER,
+ aNatRgn, 0, aControlValue, rtl::OUString(), aBound, aContent) )
+ {
+ rRect = aContent;
+ }
+ else if ( nStyle & FRAME_DRAW_MONO )
+ ImplDrawDPILineRect( pDev, rRect, NULL, bRound );
+ else
+ {
+ USHORT nFrameStyle = nStyle & FRAME_DRAW_STYLE;
+
+ if ( nFrameStyle == FRAME_DRAW_GROUP )
+ {
+ rRect.Left() += 2;
+ rRect.Top() += 2;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+ }
+ else if ( (nFrameStyle == FRAME_DRAW_IN) ||
+ (nFrameStyle == FRAME_DRAW_OUT) )
+ {
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+ }
+ else // FRAME_DRAW_DOUBLEIN || FRAME_DRAW_DOUBLEOUT
+ {
+ rRect.Left() += 2;
+ rRect.Top() += 2;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+ }
+ }
+ }
+ else
+ {
+ if( pWin && pWin->IsNativeControlSupported(CTRL_FRAME, PART_BORDER) )
+ {
+ USHORT nValueStyle = bMenuStyle ? nStyle | FRAME_DRAW_MENU : nStyle;
+ if( pWin->GetType() == WINDOW_BORDERWINDOW )
+ nValueStyle |= FRAME_DRAW_BORDERWINDOWBORDER;
+ ImplControlValue aControlValue( nValueStyle );
+ Rectangle aBound, aContent;
+ Rectangle aNatRgn( rRect );
+ if( pWin->GetNativeControlRegion(CTRL_FRAME, PART_BORDER,
+ aNatRgn, 0, aControlValue, rtl::OUString(), aBound, aContent) )
+ {
+ if( pWin->DrawNativeControl( CTRL_FRAME, PART_BORDER, aContent, CTRL_STATE_ENABLED,
+ aControlValue, rtl::OUString()) )
+ {
+ rRect = aContent;
+ return;
+ }
+ }
+ }
+
+ if ( nStyle & FRAME_DRAW_MONO )
+ {
+ Color aColor = bRound ? rStyleSettings.GetShadowColor()
+ : pDev->GetSettings().GetStyleSettings().GetMonoColor();
+ // when the MonoColor wasn't set, check face color
+ if (
+ (bRound && aColor.IsDark()) ||
+ (
+ (aColor == Color(COL_BLACK)) &&
+ (pDev->GetSettings().GetStyleSettings().GetFaceColor().IsDark())
+ )
+ )
+ {
+ aColor = Color( COL_WHITE );
+ }
+ ImplDrawDPILineRect( pDev, rRect, &aColor, bRound );
+ }
+ else
+ {
+ USHORT nFrameStyle = nStyle & FRAME_DRAW_STYLE;
+ if ( nFrameStyle == FRAME_DRAW_GROUP )
+ {
+ pDev->SetFillColor();
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ rRect.Top()++;
+ rRect.Left()++;
+ pDev->DrawRect( rRect );
+ rRect.Top()--;
+ rRect.Left()--;
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ rRect.Right()--;
+ rRect.Bottom()--;
+ pDev->DrawRect( rRect );
+ rRect.Right()++;
+ rRect.Bottom()++;
+ }
+ else
+ {
+ pDev->SetLineColor();
+
+ if ( (nFrameStyle == FRAME_DRAW_IN) ||
+ (nFrameStyle == FRAME_DRAW_OUT) )
+ {
+ if ( nFrameStyle == FRAME_DRAW_IN )
+ {
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetShadowColor(),
+ rStyleSettings.GetLightColor() );
+ }
+ else
+ {
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetLightColor(),
+ rStyleSettings.GetShadowColor() );
+ }
+
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+ }
+ else // FRAME_DRAW_DOUBLEIN || FRAME_DRAW_DOUBLEOUT
+ {
+ if ( nFrameStyle == FRAME_DRAW_DOUBLEIN )
+ {
+ if( bFlatBorders ) // no 3d effect
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetShadowColor(),
+ rStyleSettings.GetShadowColor() );
+ else
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetShadowColor(),
+ rStyleSettings.GetLightColor() );
+ }
+ else
+ {
+ if( bMenuStyle )
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetMenuBorderColor(),
+ rStyleSettings.GetDarkShadowColor() );
+ else
+ pDev->ImplDraw2ColorFrame( rRect,
+ bFlatBorders ? // no 3d effect
+ rStyleSettings.GetDarkShadowColor() :
+ rStyleSettings.GetLightBorderColor(),
+ rStyleSettings.GetDarkShadowColor() );
+
+ }
+
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+
+ BOOL bDrawn = TRUE;
+ if ( nFrameStyle == FRAME_DRAW_DOUBLEIN )
+ {
+ if( bFlatBorders ) // no 3d effect
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetFaceColor(),
+ rStyleSettings.GetFaceColor() );
+ else
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetDarkShadowColor(),
+ rStyleSettings.GetLightBorderColor() );
+ }
+ else
+ {
+ // flat menues have no shadow border
+ if( !bMenuStyle || !rStyleSettings.GetUseFlatMenues() )
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetLightColor(),
+ rStyleSettings.GetShadowColor() );
+ else
+ bDrawn = FALSE;
+ }
+ if( bDrawn )
+ {
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+ }
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle DecorationView::DrawFrame( const Rectangle& rRect, USHORT nStyle )
+{
+ Rectangle aRect = rRect;
+ BOOL bOldMap = mpOutDev->IsMapModeEnabled();
+ if ( bOldMap )
+ {
+ aRect = mpOutDev->LogicToPixel( aRect );
+ mpOutDev->EnableMapMode( FALSE );
+ }
+
+ if ( !rRect.IsEmpty() )
+ {
+ if ( nStyle & FRAME_DRAW_NODRAW )
+ ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle );
+ else
+ {
+ Color maOldLineColor = mpOutDev->GetLineColor();
+ Color maOldFillColor = mpOutDev->GetFillColor();
+ ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle );
+ mpOutDev->SetLineColor( maOldLineColor );
+ mpOutDev->SetFillColor( maOldFillColor );
+ }
+ }
+
+ if ( bOldMap )
+ {
+ mpOutDev->EnableMapMode( bOldMap );
+ aRect = mpOutDev->PixelToLogic( aRect );
+ }
+
+ return aRect;
+}
+
+// =======================================================================
+
+static void ImplDrawButton( OutputDevice* pDev, Rectangle& rRect,
+ const StyleSettings& rStyleSettings, USHORT nStyle )
+{
+ Rectangle aFillRect = rRect;
+
+ if ( nStyle & BUTTON_DRAW_MONO )
+ {
+ if ( !(nStyle & BUTTON_DRAW_NODRAW) )
+ {
+ Color aBlackColor( COL_BLACK );
+
+ if ( nStyle & BUTTON_DRAW_DEFAULT )
+ ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor );
+
+ ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor );
+
+ Size aBrdSize( 1, 1 );
+ if ( pDev->GetOutDevType() == OUTDEV_PRINTER )
+ {
+ MapMode aResMapMode( MAP_100TH_MM );
+ aBrdSize = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode );
+ if ( !aBrdSize.Width() )
+ aBrdSize.Width() = 1;
+ if ( !aBrdSize.Height() )
+ aBrdSize.Height() = 1;
+ }
+ pDev->SetLineColor();
+ pDev->SetFillColor( aBlackColor );
+ Rectangle aRect1;
+ Rectangle aRect2;
+ aRect1.Left() = aFillRect.Left();
+ aRect1.Right() = aFillRect.Right(),
+ aRect2.Top() = aFillRect.Top();
+ aRect2.Bottom() = aFillRect.Bottom();
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ aRect1.Top() = aFillRect.Top();
+ aRect1.Bottom() = aBrdSize.Height()-1;
+ aRect2.Left() = aFillRect.Left();
+ aRect2.Right() = aFillRect.Left()+aBrdSize.Width()-1;
+ aFillRect.Left() += aBrdSize.Width();
+ aFillRect.Top() += aBrdSize.Height();
+ }
+ else
+ {
+ aRect1.Top() = aFillRect.Bottom()-aBrdSize.Height()+1;
+ aRect1.Bottom() = aFillRect.Bottom();
+ aRect2.Left() = aFillRect.Right()-aBrdSize.Width()+1;
+ aRect2.Right() = aFillRect.Right(),
+ aFillRect.Right() -= aBrdSize.Width();
+ aFillRect.Bottom() -= aBrdSize.Height();
+ }
+ pDev->DrawRect( aRect1 );
+ pDev->DrawRect( aRect2 );
+ }
+ }
+ else
+ {
+ if ( !(nStyle & BUTTON_DRAW_NODRAW) )
+ {
+ if ( nStyle & BUTTON_DRAW_DEFAULT )
+ {
+ Color aDefBtnColor = rStyleSettings.GetDarkShadowColor();
+ ImplDrawDPILineRect( pDev, aFillRect, &aDefBtnColor );
+ }
+ }
+
+ if ( !(nStyle & BUTTON_DRAW_NODRAW) )
+ {
+ pDev->SetLineColor();
+ if ( nStyle & BUTTON_DRAW_NOLEFTLIGHTBORDER )
+ {
+ pDev->SetFillColor( rStyleSettings.GetLightBorderColor() );
+ pDev->DrawRect( Rectangle( aFillRect.Left(), aFillRect.Top(),
+ aFillRect.Left(), aFillRect.Bottom() ) );
+ aFillRect.Left()++;
+ }
+ if ( (nStyle & BUTTON_DRAW_NOTOPLIGHTBORDER) &&
+ !(nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED)) )
+ {
+ pDev->SetFillColor( rStyleSettings.GetLightBorderColor() );
+ pDev->DrawRect( Rectangle( aFillRect.Left(), aFillRect.Top(),
+ aFillRect.Right(), aFillRect.Top() ) );
+ aFillRect.Top()++;
+ }
+ if ( (( (nStyle & BUTTON_DRAW_NOBOTTOMSHADOWBORDER) | BUTTON_DRAW_FLAT) == (BUTTON_DRAW_NOBOTTOMSHADOWBORDER | BUTTON_DRAW_FLAT)) &&
+ !(nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED | BUTTON_DRAW_HIGHLIGHT)) )
+ {
+ pDev->SetFillColor( rStyleSettings.GetDarkShadowColor() );
+ pDev->DrawRect( Rectangle( aFillRect.Left(), aFillRect.Bottom(),
+ aFillRect.Right(), aFillRect.Bottom() ) );
+ aFillRect.Bottom()--;
+ }
+
+ Color aColor1;
+ Color aColor2;
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ aColor1 = rStyleSettings.GetDarkShadowColor();
+ aColor2 = rStyleSettings.GetLightColor();
+ }
+ else
+ {
+ if ( nStyle & BUTTON_DRAW_NOLIGHTBORDER )
+ aColor1 = rStyleSettings.GetLightBorderColor();
+ else
+ aColor1 = rStyleSettings.GetLightColor();
+ if ( (nStyle & BUTTON_DRAW_FLATTEST) == BUTTON_DRAW_FLAT )
+ aColor2 = rStyleSettings.GetShadowColor();
+ else
+ aColor2 = rStyleSettings.GetDarkShadowColor();
+ }
+ pDev->ImplDraw2ColorFrame( aFillRect, aColor1, aColor2 );
+ aFillRect.Left()++;
+ aFillRect.Top()++;
+ aFillRect.Right()--;
+ aFillRect.Bottom()--;
+
+ if ( !((nStyle & BUTTON_DRAW_FLATTEST) == BUTTON_DRAW_FLAT) )
+ {
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ aColor1 = rStyleSettings.GetShadowColor();
+ aColor2 = rStyleSettings.GetLightBorderColor();
+ }
+ else
+ {
+ if ( nStyle & BUTTON_DRAW_NOLIGHTBORDER )
+ aColor1 = rStyleSettings.GetLightColor();
+ else
+ aColor1 = rStyleSettings.GetLightBorderColor();
+ aColor2 = rStyleSettings.GetShadowColor();
+ }
+ pDev->ImplDraw2ColorFrame( aFillRect, aColor1, aColor2 );
+ aFillRect.Left()++;
+ aFillRect.Top()++;
+ aFillRect.Right()--;
+ aFillRect.Bottom()--;
+ }
+ }
+ }
+
+ if ( !(nStyle & (BUTTON_DRAW_NOFILL | BUTTON_DRAW_NODRAW)) )
+ {
+ pDev->SetLineColor();
+ if ( nStyle & BUTTON_DRAW_MONO )
+ {
+ // Hack: Auf Druckern wollen wir im MonoChrom-Modus trotzdem
+ // erstmal graue Buttons haben
+ if ( pDev->GetOutDevType() == OUTDEV_PRINTER )
+ pDev->SetFillColor( Color( COL_LIGHTGRAY ) );
+ else
+ pDev->SetFillColor( Color( COL_WHITE ) );
+ }
+ else
+ {
+ if ( nStyle & (BUTTON_DRAW_CHECKED | BUTTON_DRAW_DONTKNOW) )
+ pDev->SetFillColor( rStyleSettings.GetCheckedColor() );
+ else
+ pDev->SetFillColor( rStyleSettings.GetFaceColor() );
+ }
+ pDev->DrawRect( aFillRect );
+ }
+
+ // Ein Border freilassen, der jedoch bei Default-Darstellung
+ // mitbenutzt wird
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+
+ if ( nStyle & BUTTON_DRAW_NOLIGHTBORDER )
+ {
+ rRect.Left()++;
+ rRect.Top()++;
+ }
+ else if ( nStyle & BUTTON_DRAW_NOLEFTLIGHTBORDER )
+ rRect.Left()++;
+
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ {
+ if ( (rRect.GetHeight() > 10) && (rRect.GetWidth() > 10) )
+ {
+ rRect.Left() += 4;
+ rRect.Top() += 4;
+ rRect.Right() -= 1;
+ rRect.Bottom() -= 1;
+ }
+ else
+ {
+ rRect.Left() += 3;
+ rRect.Top() += 3;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+ }
+ }
+ else if ( nStyle & BUTTON_DRAW_CHECKED )
+ {
+ rRect.Left() += 3;
+ rRect.Top() += 3;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+ }
+ else
+ {
+ rRect.Left() += 2;
+ rRect.Top() += 2;
+ rRect.Right() -= 3;
+ rRect.Bottom() -= 3;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle DecorationView::DrawButton( const Rectangle& rRect, USHORT nStyle )
+{
+ Rectangle aRect = rRect;
+ BOOL bOldMap = mpOutDev->IsMapModeEnabled();
+ if ( bOldMap )
+ {
+ aRect = mpOutDev->LogicToPixel( aRect );
+ mpOutDev->EnableMapMode( FALSE );
+ }
+
+ if ( !rRect.IsEmpty() )
+ {
+ const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
+
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
+ nStyle |= BUTTON_DRAW_MONO;
+
+ if ( nStyle & BUTTON_DRAW_NODRAW )
+ ImplDrawButton( mpOutDev, aRect, rStyleSettings, nStyle );
+ else
+ {
+ Color maOldLineColor = mpOutDev->GetLineColor();
+ Color maOldFillColor = mpOutDev->GetFillColor();
+ ImplDrawButton( mpOutDev, aRect, rStyleSettings, nStyle );
+ mpOutDev->SetLineColor( maOldLineColor );
+ mpOutDev->SetFillColor( maOldFillColor );
+ }
+ }
+
+ if ( bOldMap )
+ {
+ mpOutDev->EnableMapMode( bOldMap );
+ aRect = mpOutDev->PixelToLogic( aRect );
+ }
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void DecorationView::DrawSeparator( const Point& rStart, const Point& rStop, bool bVertical )
+{
+ Point aStart( rStart ), aStop( rStop );
+ const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
+
+ mpOutDev->Push( PUSH_LINECOLOR );
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
+ mpOutDev->SetLineColor( Color( COL_BLACK ) );
+ else
+ mpOutDev->SetLineColor( rStyleSettings.GetShadowColor() );
+
+ mpOutDev->DrawLine( aStart, aStop );
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ mpOutDev->SetLineColor( rStyleSettings.GetLightColor() );
+ if( bVertical )
+ {
+ aStart.X()++;
+ aStop.X()++;
+ }
+ else
+ {
+ aStart.Y()++;
+ aStop.Y()++;
+ }
+ mpOutDev->DrawLine( aStart, aStop );
+ }
+ mpOutDev->Pop();
+}
+
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
new file mode 100644
index 000000000000..3b5585d3bc63
--- /dev/null
+++ b/vcl/source/window/dialog.cxx
@@ -0,0 +1,1028 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <tools/debug.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.h>
+#include <vcl/event.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/button.hxx>
+#include <vcl/mnemonic.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/decoview.hxx>
+
+#ifdef DBG_UTIL
+#include <vcl/msgbox.hxx>
+#endif
+
+#include <vcl/unowrap.hxx>
+
+
+
+// =======================================================================
+
+#ifdef DBG_UTIL
+
+static ByteString ImplGetDialogText( Dialog* pDialog )
+{
+ ByteString aErrorStr( pDialog->GetText(), RTL_TEXTENCODING_UTF8 );
+ if ( (pDialog->GetType() == WINDOW_MESSBOX) ||
+ (pDialog->GetType() == WINDOW_INFOBOX) ||
+ (pDialog->GetType() == WINDOW_WARNINGBOX) ||
+ (pDialog->GetType() == WINDOW_ERRORBOX) ||
+ (pDialog->GetType() == WINDOW_QUERYBOX) )
+ {
+ aErrorStr += ", ";
+ aErrorStr += ByteString( ((MessBox*)pDialog)->GetMessText(), RTL_TEXTENCODING_UTF8 );
+ }
+ return aErrorStr;
+}
+
+#endif
+
+// =======================================================================
+
+static BOOL ImplIsMnemonicCtrl( Window* pWindow )
+{
+ if( ! pWindow->GetSettings().GetStyleSettings().GetAutoMnemonic() )
+ return FALSE;
+
+ if ( (pWindow->GetType() == WINDOW_RADIOBUTTON) ||
+ (pWindow->GetType() == WINDOW_CHECKBOX) ||
+ (pWindow->GetType() == WINDOW_TRISTATEBOX) ||
+ (pWindow->GetType() == WINDOW_PUSHBUTTON) )
+ return TRUE;
+
+ if ( pWindow->GetType() == WINDOW_FIXEDTEXT )
+ {
+ if ( pWindow->GetStyle() & (WB_INFO | WB_NOLABEL) )
+ return FALSE;
+ Window* pNextWindow = pWindow->GetWindow( WINDOW_NEXT );
+ if ( !pNextWindow )
+ return FALSE;
+ pNextWindow = pNextWindow->GetWindow( WINDOW_CLIENT );
+ if ( !(pNextWindow->GetStyle() & WB_TABSTOP) ||
+ (pNextWindow->GetType() == WINDOW_FIXEDTEXT) ||
+ (pNextWindow->GetType() == WINDOW_GROUPBOX) ||
+ (pNextWindow->GetType() == WINDOW_RADIOBUTTON) ||
+ (pNextWindow->GetType() == WINDOW_CHECKBOX) ||
+ (pNextWindow->GetType() == WINDOW_TRISTATEBOX) ||
+ (pNextWindow->GetType() == WINDOW_PUSHBUTTON) )
+ return FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWindowAutoMnemonic( Window* pWindow )
+{
+ MnemonicGenerator aMnemonicGenerator;
+ Window* pGetChild;
+ Window* pChild;
+
+ // Die schon vergebenen Mnemonics registieren
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+
+ // Bei TabPages auch noch die Controls vom Dialog beruecksichtigen
+ if ( pWindow->GetType() == WINDOW_TABPAGE )
+ {
+ Window* pParent = pWindow->GetParent();
+ if ( pParent->GetType() == WINDOW_TABCONTROL )
+ pParent = pParent->GetParent();
+
+ if ( (pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
+ {
+ pGetChild = pParent->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+ }
+ }
+
+ // Die Mnemonics an die Controls vergeben, die noch keinen haben
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ if ( ImplIsMnemonicCtrl( pChild ) )
+ {
+ XubString aText = pChild->GetText();
+ if ( aMnemonicGenerator.CreateMnemonic( aText ) )
+ pChild->SetText( aText );
+ }
+
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+}
+
+// =======================================================================
+
+static PushButton* ImplGetDefaultButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->ImplIsPushButton() )
+ {
+ PushButton* pPushButton = (PushButton*)pChild;
+ if ( pPushButton->ImplIsDefButton() )
+ return pPushButton;
+ }
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static PushButton* ImplGetOKButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->GetType() == WINDOW_OKBUTTON )
+ return (PushButton*)pChild;
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static PushButton* ImplGetCancelButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->GetType() == WINDOW_CANCELBUTTON )
+ return (PushButton*)pChild;
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplMouseAutoPos( Dialog* pDialog )
+{
+ ULONG nMouseOptions = pDialog->GetSettings().GetMouseSettings().GetOptions();
+ if ( nMouseOptions & MOUSE_OPTION_AUTOCENTERPOS )
+ {
+ Size aSize = pDialog->GetOutputSizePixel();
+ pDialog->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
+ }
+ else if ( nMouseOptions & MOUSE_OPTION_AUTODEFBTNPOS )
+ {
+ Window* pWindow = ImplGetDefaultButton( pDialog );
+ if ( !pWindow )
+ pWindow = ImplGetOKButton( pDialog );
+ if ( !pWindow )
+ pWindow = ImplGetCancelButton( pDialog );
+ if ( !pWindow )
+ pWindow = pDialog;
+ Size aSize = pWindow->GetOutputSizePixel();
+ pWindow->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
+ }
+}
+
+// =======================================================================
+
+struct DialogImpl
+{
+ long mnResult;
+ bool mbStartedModal;
+ Link maEndDialogHdl;
+
+ DialogImpl() : mnResult( -1 ), mbStartedModal( false ) {}
+};
+
+// =======================================================================
+
+void Dialog::ImplInitDialogData()
+{
+ mpWindowImpl->mbDialog = TRUE;
+ mpDialogParent = NULL;
+ mpPrevExecuteDlg = NULL;
+ mbInExecute = FALSE;
+ mbOldSaveBack = FALSE;
+ mbInClose = FALSE;
+ mbModalMode = FALSE;
+ mnMousePositioned = 0;
+ mpDialogImpl = new DialogImpl;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplInit( Window* pParent, WinBits nStyle )
+{
+ USHORT nSysWinMode = Application::GetSystemWindowMode();
+
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+ nStyle |= WB_ROLLABLE;
+
+ // Now, all Dialogs are per default system windows !!!
+ nStyle |= WB_SYSTEMWINDOW;
+
+
+ // parent is NULL: get the default Dialog parent
+ if ( !pParent )
+ {
+ pParent = Application::GetDefDialogParent();
+ if ( !pParent && !(nStyle & WB_SYSTEMWINDOW) )
+ pParent = ImplGetSVData()->maWinData.mpAppWin;
+
+ // If Parent is disabled, then we search for a modal dialog
+ // in this frame
+ if ( pParent && (!pParent->IsInputEnabled() || pParent->IsInModalMode()) )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
+ while ( pExeDlg )
+ {
+ // Nur wenn er sichtbar und enabled ist
+ if ( pParent->ImplGetFirstOverlapWindow()->IsWindowOrChild( pExeDlg, TRUE ) &&
+ pExeDlg->IsReallyVisible() &&
+ pExeDlg->IsEnabled() && pExeDlg->IsInputEnabled() && !pExeDlg->IsInModalMode() )
+ {
+ pParent = pExeDlg;
+ break;
+ }
+
+ pExeDlg = pExeDlg->mpPrevExecuteDlg;
+ }
+ }
+ }
+ // DIALOG_NO_PARENT: explicitly don't have a parent for this Dialog
+ else if( pParent == DIALOG_NO_PARENT )
+ pParent = NULL;
+
+/*
+ // Now, all Dialogs are per default system windows !!!
+ if ( pParent && !(nSysWinMode & SYSTEMWINDOW_MODE_NOAUTOMODE) )
+ {
+ if ( !pParent->mpWindowImpl->mpFrameWindow->IsVisible() )
+ pParent = NULL;
+ else
+ {
+ if ( pParent->mpWindowImpl->mpFrameWindow->IsDialog() )
+ {
+ Size aOutSize = pParent->mpWindowImpl->mpFrameWindow->GetOutputSizePixel();
+ if ( (aOutSize.Width() < 210) ||(aOutSize.Height() < 160) )
+ nStyle |= WB_SYSTEMWINDOW;
+ }
+ }
+ }
+*/
+
+ if ( !pParent || (nStyle & WB_SYSTEMWINDOW) ||
+ (pParent->mpWindowImpl->mpFrameData->mbNeedSysWindow && !(nSysWinMode & SYSTEMWINDOW_MODE_NOAUTOMODE)) ||
+ (nSysWinMode & SYSTEMWINDOW_MODE_DIALOG) )
+ {
+ // create window with a small border ?
+ if ( (nStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE)) == WB_BORDER )
+ {
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_FRAME );
+ SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
+ pBorderWin->mpWindowImpl->mpClientWindow = this;
+ pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ mpWindowImpl->mpBorderWindow = pBorderWin;
+ mpWindowImpl->mpRealParent = pParent;
+ }
+ else
+ {
+ mpWindowImpl->mbFrame = TRUE;
+ mpWindowImpl->mbOverlapWin = TRUE;
+ SystemWindow::ImplInit( pParent, (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)) | WB_CLOSEABLE, NULL );
+ // Now set all style bits
+ mpWindowImpl->mnStyle = nStyle;
+ }
+ }
+ else
+ {
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_OVERLAP | BORDERWINDOW_STYLE_BORDER );
+ SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
+ pBorderWin->mpWindowImpl->mpClientWindow = this;
+ pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ mpWindowImpl->mpBorderWindow = pBorderWin;
+ mpWindowImpl->mpRealParent = pParent;
+ }
+
+ SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplInitSettings()
+{
+ // user override
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ // NWF background
+ else if( IsNativeControlSupported( CTRL_WINDOW_BACKGROUND, PART_BACKGROUND_DIALOG ) )
+ {
+ mpWindowImpl->mnNativeBackground = PART_BACKGROUND_DIALOG;
+ EnableChildTransparentMode( TRUE );
+ }
+ // fallback to settings color
+ else
+ SetBackground( GetSettings().GetStyleSettings().GetDialogColor() );
+
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplCenterDialog()
+{
+ Rectangle aDeskRect = ImplGetFrameWindow()->GetDesktopRectPixel();
+ Point aDeskPos = aDeskRect.TopLeft();
+ Size aDeskSize = aDeskRect.GetSize();
+ Size aWinSize = GetSizePixel();
+ Window *pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+ Point aWinPos( ((aDeskSize.Width() - aWinSize.Width()) / 2) + aDeskPos.X(),
+ ((aDeskSize.Height() - aWinSize.Height()) / 2) + aDeskPos.Y() );
+
+ // Pruefen, ob Dialogbox ausserhalb des Desks liegt
+ if ( (aWinPos.X() + aWinSize.Width()) > (aDeskPos.X()+aDeskSize.Width()) )
+ aWinPos.X() = aDeskPos.X()+aDeskSize.Width() - aWinSize.Width();
+ if ( (aWinPos.Y()+aWinSize.Height()) > (aDeskPos.Y()+aDeskSize.Height()) )
+ aWinPos.Y() = aDeskPos.Y()+aDeskSize.Height() - aWinSize.Height();
+ // Linke Ecke bevorzugen, da Titelbar oben ist
+ if ( aWinPos.X() < aDeskPos.X() )
+ aWinPos.X() = aDeskPos.X();
+ if ( aWinPos.Y() < aDeskPos.Y() )
+ aWinPos.Y() = aDeskPos.Y();
+
+ //SetPosPixel( aWinPos );
+ SetPosPixel( pWindow->ScreenToOutputPixel( aWinPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( WindowType nType ) :
+ SystemWindow( nType )
+{
+ ImplInitDialogData();
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( Window* pParent, WinBits nStyle ) :
+ SystemWindow( WINDOW_DIALOG )
+{
+ ImplInitDialogData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( Window* pParent, const ResId& rResId ) :
+ SystemWindow( WINDOW_DIALOG )
+{
+ ImplInitDialogData();
+ rResId.SetRT( RSC_DIALOG );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::~Dialog()
+{
+ delete mpDialogImpl;
+ mpDialogImpl = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Dialog, ImplAsyncCloseHdl, void*, EMPTYARG )
+{
+ Close();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long Dialog::Notify( NotifyEvent& rNEvt )
+{
+ // Zuerst Basisklasse rufen wegen TabSteuerung
+ long nRet = SystemWindow::Notify( rNEvt );
+ if ( !nRet )
+ {
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+ KeyCode aKeyCode = pKEvt->GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+
+ if ( (nKeyCode == KEY_ESCAPE) &&
+ ((GetStyle() & WB_CLOSEABLE) || ImplGetCancelButton( this ) || ImplGetOKButton( this )) )
+ {
+ // #i89505# for the benefit of slightly mentally challenged implementations
+ // like e.g. SfxModelessDialog which destroy themselves inside Close()
+ // post this Close asynchronous so we can leave our key handler before
+ // we get destroyed
+ PostUserEvent( LINK( this, Dialog, ImplAsyncCloseHdl ), this );
+ return TRUE;
+ }
+ }
+ else if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ {
+ // make sure the dialog is still modal
+ // changing focus between application frames may
+ // have re-enabled input for our parent
+ if( mbInExecute && mbModalMode )
+ {
+ // do not change modal counter (pSVData->maAppData.mnModalDialog)
+ SetModalInputMode( FALSE );
+ SetModalInputMode( TRUE );
+
+ // #93022# def-button might have changed after show
+ if( !mnMousePositioned )
+ {
+ mnMousePositioned = 1;
+ ImplMouseAutoPos( this );
+ }
+
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::StateChanged( StateChangedType nType )
+{
+ SystemWindow::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( GetSettings().GetStyleSettings().GetAutoMnemonic() )
+ ImplWindowAutoMnemonic( this );
+
+ //if ( IsDefaultPos() && !mpWindowImpl->mbFrame )
+ // ImplCenterDialog();
+ if ( !HasChildPathFocus() || HasFocus() )
+ GrabFocusToFirstControl();
+ if ( !(GetStyle() & WB_CLOSEABLE) )
+ {
+ if ( ImplGetCancelButton( this ) || ImplGetOKButton( this ) )
+ {
+ if ( ImplGetBorderWindow() )
+ ((ImplBorderWindow*)ImplGetBorderWindow())->SetCloser();
+ }
+ }
+
+ ImplMouseAutoPos( this );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SystemWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Dialog::Close()
+{
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ ImplCallEventListeners( VCLEVENT_WINDOW_CLOSE );
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ ImplRemoveDel( &aDelData );
+
+ if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() && !IsInExecute() )
+ return FALSE;
+
+ mbInClose = TRUE;
+
+ if ( !(GetStyle() & WB_CLOSEABLE) )
+ {
+ BOOL bRet = TRUE;
+ ImplAddDel( &aDelData );
+ PushButton* pButton = ImplGetCancelButton( this );
+ if ( pButton )
+ pButton->Click();
+ else
+ {
+ pButton = ImplGetOKButton( this );
+ if ( pButton )
+ pButton->Click();
+ else
+ bRet = FALSE;
+ }
+ if ( aDelData.IsDelete() )
+ return TRUE;
+ ImplRemoveDel( &aDelData );
+ return bRet;
+ }
+
+ if ( IsInExecute() )
+ {
+ EndDialog( FALSE );
+ mbInClose = FALSE;
+ return TRUE;
+ }
+ else
+ {
+ mbInClose = FALSE;
+ return SystemWindow::Close();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Dialog::ImplStartExecuteModal()
+{
+ if ( mbInExecute )
+ {
+#ifdef DBG_UTIL
+ ByteString aErrorStr( "Dialog::StartExecuteModal() is called in Dialog::StartExecuteModal(): " );
+ aErrorStr += ImplGetDialogText( this );
+ DBG_ERROR( aErrorStr.GetBuffer() );
+#endif
+ return FALSE;
+ }
+
+ if ( Application::IsDialogCancelEnabled() )
+ {
+#ifdef DBG_UTIL
+ ByteString aErrorStr( "Dialog::StartExecuteModal() is called in a none UI application: " );
+ aErrorStr += ImplGetDialogText( this );
+ DBG_ERROR( aErrorStr.GetBuffer() );
+#endif
+ return FALSE;
+ }
+
+#ifdef DBG_UTIL
+ Window* pParent = GetParent();
+ if ( pParent )
+ {
+ pParent = pParent->ImplGetFirstOverlapWindow();
+ DBG_ASSERT( pParent->IsReallyVisible(),
+ "Dialog::StartExecuteModal() - Parent not visible" );
+ DBG_ASSERT( pParent->IsInputEnabled(),
+ "Dialog::StartExecuteModal() - Parent input disabled, use another parent to ensure modality!" );
+ DBG_ASSERT( ! pParent->IsInModalMode(),
+ "Dialog::StartExecuteModal() - Parent already modally disabled, use another parent to ensure modality!" );
+
+ }
+#endif
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Dialoge, die sich in Execute befinden, miteinander verketten
+ mpPrevExecuteDlg = pSVData->maWinData.mpLastExecuteDlg;
+ pSVData->maWinData.mpLastExecuteDlg = this;
+
+ // Capture beenden, damit der Dialog bedient werden kann
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ if ( pSVData->maWinData.mpCaptureWin )
+ pSVData->maWinData.mpCaptureWin->ReleaseMouse();
+ EnableInput( TRUE, TRUE );
+
+ if ( GetParent() )
+ {
+ NotifyEvent aNEvt( EVENT_EXECUTEDIALOG, this );
+ GetParent()->Notify( aNEvt );
+ }
+ mbInExecute = TRUE;
+ SetModalInputMode( TRUE );
+ mbOldSaveBack = IsSaveBackgroundEnabled();
+ EnableSaveBackground();
+
+ // FIXME: no layouting, workaround some clipping issues
+ ImplAdjustNWFSizes();
+
+ Show();
+
+ pSVData->maAppData.mnModalMode++;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplEndExecuteModal()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maAppData.mnModalMode--;
+}
+
+// -----------------------------------------------------------------------
+
+short Dialog::Execute()
+{
+ if ( !ImplStartExecuteModal() )
+ return 0;
+
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+
+#ifdef DBG_UTIL
+ ImplDelData aParentDelData;
+ Window* pDialogParent = mpDialogParent;
+ if( pDialogParent )
+ pDialogParent->ImplAddDel( &aParentDelData );
+#endif
+
+ // Yield util EndDialog is called or dialog gets destroyed
+ // (the latter should not happen, but better safe than sorry
+ while ( !aDelData.IsDelete() && mbInExecute )
+ Application::Yield();
+
+ ImplEndExecuteModal();
+
+#ifdef DBG_UTIL
+ if( pDialogParent )
+ {
+ if( ! aParentDelData.IsDelete() )
+ pDialogParent->ImplRemoveDel( &aParentDelData );
+ else
+ DBG_ERROR( "Dialog::Execute() - Parent of dialog destroyed in Execute()" );
+ }
+#endif
+ if ( !aDelData.IsDelete() )
+ ImplRemoveDel( &aDelData );
+#ifdef DBG_UTIL
+ else
+ {
+ DBG_ERROR( "Dialog::Execute() - Dialog destroyed in Execute()" );
+ }
+#endif
+
+ long nRet = mpDialogImpl->mnResult;
+ mpDialogImpl->mnResult = -1;
+ return (short)nRet;
+}
+
+// -----------------------------------------------------------------------
+
+// virtual
+void Dialog::StartExecuteModal( const Link& rEndDialogHdl )
+{
+ if ( !ImplStartExecuteModal() )
+ return;
+
+ mpDialogImpl->maEndDialogHdl = rEndDialogHdl;
+ mpDialogImpl->mbStartedModal = true;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Dialog::IsStartedModal() const
+{
+ return mpDialogImpl->mbStartedModal;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::EndDialog( long nResult )
+{
+ if ( mbInExecute )
+ {
+ SetModalInputMode( FALSE );
+
+ // Dialog aus der Kette der Dialoge die in Execute stehen entfernen
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
+ while ( pExeDlg )
+ {
+ if ( pExeDlg == this )
+ {
+ pSVData->maWinData.mpLastExecuteDlg = mpPrevExecuteDlg;
+ break;
+ }
+ pExeDlg = pExeDlg->mpPrevExecuteDlg;
+ }
+ // set focus to previous modal dialogue if it is modal for
+ // the same frame parent (or NULL)
+ if( mpPrevExecuteDlg )
+ {
+ Window* pFrameParent = ImplGetFrameWindow()->ImplGetParent();
+ Window* pPrevFrameParent = mpPrevExecuteDlg->ImplGetFrameWindow()->ImplGetParent();
+ if( ( !pFrameParent && !pPrevFrameParent ) ||
+ ( pFrameParent && pPrevFrameParent && pFrameParent->ImplGetFrame() == pPrevFrameParent->ImplGetFrame() )
+ )
+ {
+ mpPrevExecuteDlg->GrabFocus();
+ }
+ }
+ mpPrevExecuteDlg = NULL;
+
+ Hide();
+ EnableSaveBackground( mbOldSaveBack );
+ if ( GetParent() )
+ {
+ NotifyEvent aNEvt( EVENT_ENDEXECUTEDIALOG, this );
+ GetParent()->Notify( aNEvt );
+ }
+
+ mpDialogImpl->mnResult = nResult;
+
+ if ( mpDialogImpl->mbStartedModal )
+ {
+ ImplEndExecuteModal();
+ mpDialogImpl->maEndDialogHdl.Call( this );
+
+ mpDialogImpl->maEndDialogHdl = Link();
+ mpDialogImpl->mbStartedModal = false;
+ mpDialogImpl->mnResult = -1;
+ }
+ mbInExecute = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long Dialog::GetResult() const
+{
+ return mpDialogImpl->mnResult;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::EndAllDialogs( Window* pParent )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pTempModDialog;
+ Dialog* pModDialog = pSVData->maWinData.mpLastExecuteDlg;
+ while ( pModDialog )
+ {
+ pTempModDialog = pModDialog->mpPrevExecuteDlg;
+ if( !pParent || ( pParent && pParent->IsWindowOrChild( pModDialog, TRUE ) ) )
+ {
+ pModDialog->EndDialog( FALSE );
+ pModDialog->PostUserEvent( Link() );
+ }
+ pModDialog = pTempModDialog;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::SetModalInputMode( BOOL bModal )
+{
+ if ( bModal == mbModalMode )
+ return;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ mbModalMode = bModal;
+ if ( bModal )
+ {
+ pSVData->maAppData.mnModalDialog++;
+
+ // Diable the prev Modal Dialog, because our dialog must close at first,
+ // before the other dialog can be closed (because the other dialog
+ // is on stack since our dialog returns)
+ if ( mpPrevExecuteDlg && !mpPrevExecuteDlg->IsWindowOrChild( this, TRUE ) )
+ mpPrevExecuteDlg->EnableInput( FALSE, TRUE, TRUE, this );
+
+ // determine next overlap dialog parent
+ Window* pParent = GetParent();
+ if ( pParent )
+ {
+ // #103716# dialogs should always be modal to the whole frame window
+ // #115933# disable the whole frame hierarchie, useful if our parent
+ // is a modeless dialog
+ mpDialogParent = pParent->mpWindowImpl->mpFrameWindow;
+ mpDialogParent->ImplIncModalCount();
+ }
+
+ }
+ else
+ {
+ pSVData->maAppData.mnModalDialog--;
+
+ if ( mpDialogParent )
+ {
+ // #115933# re-enable the whole frame hierarchie again (see above)
+ // note that code in getfocus assures that we do not accidentally enable
+ // windows that were disabled before
+ mpDialogParent->ImplDecModalCount();
+ }
+
+ // Enable the prev Modal Dialog
+ if ( mpPrevExecuteDlg && !mpPrevExecuteDlg->IsWindowOrChild( this, TRUE ) )
+ {
+ mpPrevExecuteDlg->EnableInput( TRUE, TRUE, TRUE, this );
+ // ensure continued modality of prev dialog
+ // do not change modality counter
+ mpPrevExecuteDlg->SetModalInputMode( FALSE );
+ mpPrevExecuteDlg->SetModalInputMode( TRUE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::SetModalInputMode( BOOL bModal, BOOL bSubModalDialogs )
+{
+ if ( bSubModalDialogs )
+ {
+ Window* pOverlap = ImplGetFirstOverlapWindow();
+ pOverlap = pOverlap->mpWindowImpl->mpFirstOverlap;
+ while ( pOverlap )
+ {
+ if ( pOverlap->IsDialog() )
+ ((Dialog*)pOverlap)->SetModalInputMode( bModal, TRUE );
+ pOverlap = pOverlap->mpWindowImpl->mpNext;
+ }
+ }
+
+ SetModalInputMode( bModal );
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::GrabFocusToFirstControl()
+{
+ Window* pFocusControl;
+
+ // Wenn Dialog den Focus hat, versuchen wr trotzdem
+ // ein Focus-Control zu finden
+ if ( HasFocus() )
+ pFocusControl = NULL;
+ else
+ {
+ // Wenn schon ein Child-Fenster mal den Focus hatte,
+ // dann dieses bevorzugen
+ pFocusControl = ImplGetFirstOverlapWindow()->mpWindowImpl->mpLastFocusWindow;
+ // Control aus der Dialog-Steuerung suchen
+ if ( pFocusControl )
+ pFocusControl = ImplFindDlgCtrlWindow( pFocusControl );
+ }
+ // Kein Control hatte vorher den Focus, oder das Control
+ // befindet sich nicht in der Tab-Steuerung, dann das erste
+ // Control in der TabSteuerung den Focus geben
+ if ( !pFocusControl ||
+ !(pFocusControl->GetStyle() & WB_TABSTOP) ||
+ !pFocusControl->IsVisible() ||
+ !pFocusControl->IsEnabled() || !pFocusControl->IsInputEnabled() )
+ {
+ USHORT n = 0;
+ pFocusControl = ImplGetDlgWindow( n, DLGWINDOW_FIRST );
+ }
+ if ( pFocusControl )
+ pFocusControl->ImplControlFocus( GETFOCUS_INIT );
+}
+
+void Dialog::GetDrawWindowBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
+{
+ ImplBorderWindow aImplWin( (Window*)this, WB_BORDER|WB_STDWORK, BORDERWINDOW_STYLE_OVERLAP );
+// aImplWin.SetText( GetText() );
+// aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() );
+// aImplWin.SetDisplayActive( TRUE );
+// aImplWin.InitView();
+ aImplWin.GetBorder( rLeftBorder, rTopBorder, rRightBorder, rBottomBorder );
+}
+
+
+void Dialog::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+
+ Wallpaper aWallpaper = GetBackground();
+ if ( !aWallpaper.IsBitmap() )
+ ImplInitSettings();
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetLineColor();
+
+ if ( aWallpaper.IsBitmap() )
+ pDev->DrawBitmapEx( aPos, aSize, aWallpaper.GetBitmap() );
+ else
+ {
+ pDev->SetFillColor( aWallpaper.GetColor() );
+ pDev->DrawRect( Rectangle( aPos, aSize ) );
+ }
+
+ if (!( GetStyle() & WB_NOBORDER ))
+ {
+ ImplBorderWindow aImplWin( this, WB_BORDER|WB_STDWORK, BORDERWINDOW_STYLE_OVERLAP );
+ aImplWin.SetText( GetText() );
+ aImplWin.SetPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() );
+ aImplWin.SetDisplayActive( TRUE );
+ aImplWin.InitView();
+
+ aImplWin.Draw( Rectangle( aPos, aSize ), pDev, aPos );
+ }
+
+ pDev->Pop();
+}
+
+
+// =======================================================================
+
+ModelessDialog::ModelessDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_MODELESSDIALOG )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ModelessDialog::ModelessDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_MODELESSDIALOG )
+{
+ rResId.SetRT( RSC_MODELESSDIALOG );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// =======================================================================
+
+ModalDialog::ModalDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_MODALDIALOG )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ModalDialog::ModalDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_MODALDIALOG )
+{
+ rResId.SetRT( RSC_MODALDIALOG );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
diff --git a/vcl/source/window/dlgctrl.cxx b/vcl/source/window/dlgctrl.cxx
new file mode 100644
index 000000000000..055b7e9fe80b
--- /dev/null
+++ b/vcl/source/window/dlgctrl.cxx
@@ -0,0 +1,1267 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <tools/debug.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabdlg.hxx>
+#include <vcl/button.hxx>
+#include <vcl/window.h>
+
+#include <vcl/unohelp.hxx>
+#include <com/sun/star/i18n/XCharacterClassification.hpp>
+
+using namespace ::com::sun::star;
+
+// =======================================================================
+
+static BOOL ImplHasIndirectTabParent( Window* pWindow )
+{
+ // The window has inderect tab parent if it is included in tab hierarchy
+ // of the indirect parent window
+
+ return ( pWindow && pWindow->GetParent()
+ && ( pWindow->GetParent()->ImplGetWindow()->GetStyle() & WB_CHILDDLGCTRL ) );
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetTopParentOfTabHierarchy( Window* pParent )
+{
+ // The method allows to find the most close parent containing all the
+ // window from the current tab-hierarchy
+ // The direct parent should be provided as a parameter here
+
+ Window* pResult = pParent;
+
+ if ( pResult )
+ {
+ while ( pResult->GetParent() && ( pResult->ImplGetWindow()->GetStyle() & WB_CHILDDLGCTRL ) )
+ pResult = pResult->GetParent();
+ }
+
+ return pResult;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetSubChildWindow( Window* pParent, USHORT n, USHORT& nIndex )
+{
+ Window* pTabPage = NULL;
+ Window* pFoundWindow = NULL;
+
+ Window* pWindow = pParent->GetWindow( WINDOW_FIRSTCHILD );
+ Window* pNextWindow = pWindow;
+ while ( pWindow )
+ {
+ pWindow = pWindow->ImplGetWindow();
+
+ // Unsichtbare und disablte Fenster werden uebersprungen
+ if ( pTabPage || pWindow->IsVisible() )
+ {
+ // Wenn das letzte Control ein TabControl war, wird von
+ // diesem die TabPage genommen
+ if ( pTabPage )
+ {
+ pFoundWindow = ImplGetSubChildWindow( pTabPage, n, nIndex );
+ pTabPage = NULL;
+ }
+ else
+ {
+ pFoundWindow = pWindow;
+
+ // Bei einem TabControl sich die aktuelle TabPage merken,
+ // damit diese dann genommen wird
+ if ( pWindow->GetType() == WINDOW_TABCONTROL )
+ {
+ TabControl* pTabControl = ((TabControl*)pWindow);
+ // Feststellen, ob TabPage Child vom TabControl ist
+ // und auch noch existiert (deshalb durch Vergleich,
+ // indem alle ChildFenster getestet werden). Denn es
+ // kann sein, das TabPages schon in einem Dialog-Dtor
+ // zerstoert wurden, obwohl das TabControl noch
+ // existiert.
+ TabPage* pTempTabPage = pTabControl->GetTabPage( pTabControl->GetCurPageId() );
+ if ( pTempTabPage )
+ {
+ Window* pTempWindow = pTabControl->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->ImplGetWindow() == pTempTabPage )
+ {
+ pTabPage = pTempTabPage;
+ break;
+ }
+ pTempWindow = pTempWindow->GetWindow( WINDOW_NEXT );
+ }
+ }
+ }
+ else if ( ( pWindow->GetStyle() & WB_DIALOGCONTROL )
+ || ( pWindow->GetStyle() & WB_CHILDDLGCTRL ) )
+ pFoundWindow = ImplGetSubChildWindow( pWindow, n, nIndex );
+ }
+
+ if ( n == nIndex )
+ return pFoundWindow;
+ nIndex++;
+ }
+
+ if ( pTabPage )
+ pWindow = pTabPage;
+ else
+ {
+ pWindow = pNextWindow->GetWindow( WINDOW_NEXT );
+ pNextWindow = pWindow;
+ }
+ }
+
+ nIndex--;
+ return pFoundWindow;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetChildWindow( Window* pParent, USHORT n, USHORT& nIndex, BOOL bTestEnable )
+{
+ pParent = ImplGetTopParentOfTabHierarchy( pParent );
+
+ nIndex = 0;
+ Window* pWindow = ImplGetSubChildWindow( pParent, n, nIndex );
+ if ( bTestEnable )
+ {
+ USHORT n2 = nIndex;
+ while ( pWindow && (!pWindow->IsEnabled() || !pWindow->IsInputEnabled()) )
+ {
+ n2 = nIndex+1;
+ nIndex = 0;
+ pWindow = ImplGetSubChildWindow( pParent, n2, nIndex );
+ if ( nIndex < n2 )
+ break;
+ }
+
+ if ( (nIndex < n2) && n )
+ {
+ do
+ {
+ n--;
+ nIndex = 0;
+ pWindow = ImplGetSubChildWindow( pParent, n, nIndex );
+ }
+ while ( pWindow && n && (!pWindow->IsEnabled() || !pWindow->IsInputEnabled()) );
+ }
+ }
+ return pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetNextWindow( Window* pParent, USHORT n, USHORT& nIndex, BOOL bTestEnable )
+{
+ Window* pWindow = ImplGetChildWindow( pParent, n+1, nIndex, bTestEnable );
+ if ( n == nIndex )
+ {
+ n = 0;
+ pWindow = ImplGetChildWindow( pParent, n, nIndex, bTestEnable );
+ }
+ return pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::ImplGetDlgWindow( USHORT nIndex, USHORT nType,
+ USHORT nFormStart, USHORT nFormEnd,
+ USHORT* pIndex )
+{
+ DBG_ASSERT( (nIndex >= nFormStart) && (nIndex <= nFormEnd),
+ "Window::ImplGetDlgWindow() - nIndex not in Form" );
+
+ Window* pWindow = NULL;
+ USHORT i;
+ USHORT nTemp;
+ USHORT nStartIndex;
+
+ if ( nType == DLGWINDOW_PREV )
+ {
+ i = nIndex;
+ do
+ {
+ if ( i > nFormStart )
+ i--;
+ else
+ i = nFormEnd;
+ pWindow = ImplGetChildWindow( this, i, nTemp, TRUE );
+ if ( !pWindow )
+ break;
+ if ( (i == nTemp) && (pWindow->GetStyle() & WB_TABSTOP) )
+ break;
+ }
+ while ( i != nIndex );
+ }
+ else
+ {
+ i = nIndex;
+ pWindow = ImplGetChildWindow( this, i, i, (nType == DLGWINDOW_FIRST) );
+ if ( pWindow )
+ {
+ nStartIndex = i;
+
+ if ( nType == DLGWINDOW_NEXT )
+ {
+ if ( i < nFormEnd )
+ {
+ pWindow = ImplGetNextWindow( this, i, i, TRUE );
+ if ( (i > nFormEnd) || (i < nFormStart) )
+ pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
+ }
+ else
+ pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
+ }
+
+ if ( i <= nFormEnd )
+ {
+ // 2ten Index mitfuehren, falls alle Controls disablte
+ USHORT nStartIndex2 = i;
+ USHORT nOldIndex = i+1;
+
+ do
+ {
+ if ( pWindow->GetStyle() & WB_TABSTOP )
+ break;
+ if( i == nOldIndex ) // only disabled controls ?
+ {
+ i = nStartIndex2;
+ break;
+ }
+ nOldIndex = i;
+ if ( (i > nFormEnd) || (i < nFormStart) )
+ pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
+ else
+ pWindow = ImplGetNextWindow( this, i, i, TRUE );
+ }
+ while ( (i != nStartIndex) && (i != nStartIndex2) );
+
+ if ( (i == nStartIndex2) &&
+ (!(pWindow->GetStyle() & WB_TABSTOP) || !pWindow->IsEnabled()) )
+ i = nStartIndex;
+ }
+ }
+
+ if ( nType == DLGWINDOW_FIRST )
+ {
+ if ( pWindow )
+ {
+ if ( pWindow->GetType() == WINDOW_TABCONTROL )
+ {
+ Window* pNextWindow = ImplGetDlgWindow( i, DLGWINDOW_NEXT );
+ if ( pNextWindow )
+ {
+ if ( pWindow->IsChild( pNextWindow ) )
+ pWindow = pNextWindow;
+ }
+ }
+
+ if ( !(pWindow->GetStyle() & WB_TABSTOP) )
+ pWindow = NULL;
+ }
+ }
+ }
+
+ if ( pIndex )
+ *pIndex = i;
+
+ return pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplFindDlgCtrlWindow( Window* pParent, Window* pWindow, USHORT& rIndex,
+ USHORT& rFormStart, USHORT& rFormEnd )
+{
+ Window* pSWindow;
+ Window* pSecondWindow = NULL;
+ Window* pTempWindow = NULL;
+ USHORT i;
+ USHORT nSecond_i = 0;
+ USHORT nFormStart = 0;
+ USHORT nSecondFormStart = 0;
+ USHORT nFormEnd;
+
+ // Focus-Fenster in der Child-Liste suchen
+ Window* pFirstChildWindow = pSWindow = ImplGetChildWindow( pParent, 0, i, FALSE );
+
+ if( pWindow == NULL )
+ pWindow = pSWindow;
+
+ while ( pSWindow )
+ {
+ // the DialogControlStart mark is only accepted for the direct children
+ if ( !ImplHasIndirectTabParent( pSWindow )
+ && pSWindow->ImplGetWindow()->IsDialogControlStart() )
+ nFormStart = i;
+
+ // SecondWindow wegen zusammengesetzten Controls wie
+ // ComboBoxen und Feldern
+ if ( pSWindow->ImplIsWindowOrChild( pWindow ) )
+ {
+ pSecondWindow = pSWindow;
+ nSecond_i = i;
+ nSecondFormStart = nFormStart;
+ if ( pSWindow == pWindow )
+ break;
+ }
+
+ pSWindow = ImplGetNextWindow( pParent, i, i, FALSE );
+ if ( !i )
+ pSWindow = NULL;
+ }
+
+ if ( !pSWindow )
+ {
+ // Fenster nicht gefunden, dann koennen wir auch keine
+ // Steuerung uebernehmen
+ if ( !pSecondWindow )
+ return NULL;
+ else
+ {
+ pSWindow = pSecondWindow;
+ i = nSecond_i;
+ nFormStart = nSecondFormStart;
+ }
+ }
+
+ // Start-Daten setzen
+ rIndex = i;
+ rFormStart = nFormStart;
+
+ // Formularende suchen
+ nFormEnd = nFormStart;
+ pTempWindow = pSWindow;
+ sal_Int32 nIteration = 0;
+ do
+ {
+ nFormEnd = i;
+ pTempWindow = ImplGetNextWindow( pParent, i, i, FALSE );
+
+ // the DialogControlStart mark is only accepted for the direct children
+ if ( !i
+ || ( pTempWindow && !ImplHasIndirectTabParent( pTempWindow )
+ && pTempWindow->ImplGetWindow()->IsDialogControlStart() ) )
+ break;
+
+ if ( pTempWindow && pTempWindow == pFirstChildWindow )
+ {
+ // It is possible to go through the begin of hierarchy once
+ // while looking for DialogControlStart mark.
+ // If it happens second time, it looks like an endless loop,
+ // that should be impossible, but just for the case...
+ nIteration++;
+ if ( nIteration >= 2 )
+ {
+ // this is an unexpected scenario
+ DBG_ASSERT( FALSE, "It seems to be an endless loop!" );
+ rFormStart = 0;
+ break;
+ }
+ }
+ }
+ while ( pTempWindow );
+ rFormEnd = nFormEnd;
+
+ return pSWindow;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplFindAccelWindow( Window* pParent, USHORT& rIndex, xub_Unicode cCharCode,
+ USHORT nFormStart, USHORT nFormEnd, BOOL bCheckEnable = TRUE )
+{
+ DBG_ASSERT( (rIndex >= nFormStart) && (rIndex <= nFormEnd),
+ "Window::ImplFindAccelWindow() - rIndex not in Form" );
+
+ xub_Unicode cCompareChar;
+ USHORT nStart = rIndex;
+ USHORT i = rIndex;
+ int bSearch = TRUE;
+ Window* pWindow;
+
+ // MT: Where can we keep the CharClass?!
+ static uno::Reference< i18n::XCharacterClassification > xCharClass;
+ if ( !xCharClass.is() )
+ xCharClass = vcl::unohelper::CreateCharacterClassification();
+
+ const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetUILocale();
+ cCharCode = xCharClass->toUpper( String(cCharCode), 0, 1, rLocale )[0];
+
+ if ( i < nFormEnd )
+ pWindow = ImplGetNextWindow( pParent, i, i, TRUE );
+ else
+ pWindow = ImplGetChildWindow( pParent, nFormStart, i, TRUE );
+ while( bSearch && pWindow )
+ {
+ const XubString aStr = pWindow->GetText();
+ USHORT nPos = aStr.Search( '~' );
+ while ( nPos != STRING_NOTFOUND )
+ {
+ cCompareChar = aStr.GetChar( nPos+1 );
+ cCompareChar = xCharClass->toUpper( String(cCompareChar), 0, 1, rLocale )[0];
+ if ( cCompareChar == cCharCode )
+ {
+ // Bei Static-Controls auf das naechste Controlm weiterschalten
+ if ( (pWindow->GetType() == WINDOW_FIXEDTEXT) ||
+ (pWindow->GetType() == WINDOW_FIXEDLINE) ||
+ (pWindow->GetType() == WINDOW_GROUPBOX) )
+ pWindow = pParent->ImplGetDlgWindow( i, DLGWINDOW_NEXT );
+ rIndex = i;
+ return pWindow;
+ }
+ nPos = aStr.Search( '~', nPos+1 );
+ }
+
+ // #i93011# it would have made sense to have this really recursive
+ // right from the start. However this would cause unpredictable side effects now
+ // so instead we have a style bit for some child windows, that want their
+ // children checked for accelerators
+ if( (pWindow->GetStyle() & WB_CHILDDLGCTRL) != 0 )
+ {
+ USHORT nChildIndex;
+ USHORT nChildFormStart;
+ USHORT nChildFormEnd;
+
+ // get form start and end
+ ::ImplFindDlgCtrlWindow( pWindow, NULL,
+ nChildIndex, nChildFormStart, nChildFormEnd );
+ Window* pAccelWin = ImplFindAccelWindow( pWindow, nChildIndex, cCharCode,
+ nChildFormStart, nChildFormEnd,
+ bCheckEnable );
+ if( pAccelWin )
+ return pAccelWin;
+ }
+
+ if ( i == nStart )
+ break;
+
+ if ( i < nFormEnd )
+ {
+ pWindow = ImplGetNextWindow( pParent, i, i, bCheckEnable );
+ if( ! pWindow )
+ pWindow = ImplGetChildWindow( pParent, nFormStart, i, bCheckEnable );
+ }
+ else
+ pWindow = ImplGetChildWindow( pParent, nFormStart, i, bCheckEnable );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplControlFocus( USHORT nFlags )
+{
+ if ( nFlags & GETFOCUS_MNEMONIC )
+ {
+ if ( GetType() == WINDOW_RADIOBUTTON )
+ {
+ if ( !((RadioButton*)this)->IsChecked() )
+ ((RadioButton*)this)->ImplCallClick( TRUE, nFlags );
+ else
+ ImplGrabFocus( nFlags );
+ }
+ else
+ {
+ ImplGrabFocus( nFlags );
+ if ( nFlags & GETFOCUS_UNIQUEMNEMONIC )
+ {
+ if ( GetType() == WINDOW_CHECKBOX )
+ ((CheckBox*)this)->ImplCheck();
+ else if ( mpWindowImpl->mbPushButton )
+ {
+ ((PushButton*)this)->SetPressed( TRUE );
+ ((PushButton*)this)->SetPressed( FALSE );
+ ((PushButton*)this)->Click();
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( GetType() == WINDOW_RADIOBUTTON )
+ {
+ if ( !((RadioButton*)this)->IsChecked() )
+ ((RadioButton*)this)->ImplCallClick( TRUE, nFlags );
+ else
+ ImplGrabFocus( nFlags );
+ }
+ else
+ ImplGrabFocus( nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplDlgCtrl( const KeyEvent& rKEvt, BOOL bKeyInput )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+ Window* pSWindow;
+ Window* pTempWindow;
+ Window* pButtonWindow;
+ USHORT i;
+ USHORT iButton;
+ USHORT iButtonStart;
+ USHORT iTemp;
+ USHORT nIndex;
+ USHORT nFormStart;
+ USHORT nFormEnd;
+ USHORT nDlgCtrlFlags;
+
+ // Ohne Focus-Window koennen wir auch keine Steuerung uebernehmen
+ Window* pFocusWindow = Application::GetFocusWindow();
+ if ( !pFocusWindow || !ImplIsWindowOrChild( pFocusWindow ) )
+ return FALSE;
+
+ // Focus-Fenster in der Child-Liste suchen
+ pSWindow = ::ImplFindDlgCtrlWindow( this, pFocusWindow,
+ nIndex, nFormStart, nFormEnd );
+ if ( !pSWindow )
+ return FALSE;
+ i = nIndex;
+
+ nDlgCtrlFlags = 0;
+ pTempWindow = pSWindow;
+ do
+ {
+ nDlgCtrlFlags |= pTempWindow->GetDialogControlFlags();
+ if ( pTempWindow == this )
+ break;
+ pTempWindow = pTempWindow->ImplGetParent();
+ }
+ while ( pTempWindow );
+
+ pButtonWindow = NULL;
+
+ if ( nKeyCode == KEY_RETURN )
+ {
+ // Wir suchen zuerst nach einem DefPushButton/CancelButton
+ pButtonWindow = ImplGetChildWindow( this, nFormStart, iButton, TRUE );
+ iButtonStart = iButton;
+ while ( pButtonWindow )
+ {
+ if ( (pButtonWindow->GetStyle() & WB_DEFBUTTON) &&
+ pButtonWindow->mpWindowImpl->mbPushButton )
+ break;
+
+ pButtonWindow = ImplGetNextWindow( this, iButton, iButton, TRUE );
+ if ( (iButton <= iButtonStart) || (iButton > nFormEnd) )
+ pButtonWindow = NULL;
+ }
+
+ if ( bKeyInput && !pButtonWindow && (nDlgCtrlFlags & WINDOW_DLGCTRL_RETURN) )
+ {
+ USHORT nType;
+ USHORT nGetFocusFlags = GETFOCUS_TAB;
+ USHORT nNewIndex;
+ USHORT iStart;
+ if ( aKeyCode.IsShift() )
+ {
+ nType = DLGWINDOW_PREV;
+ nGetFocusFlags |= GETFOCUS_BACKWARD;
+ }
+ else
+ {
+ nType = DLGWINDOW_NEXT;
+ nGetFocusFlags |= GETFOCUS_FORWARD;
+ }
+ iStart = i;
+ pTempWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
+ while ( pTempWindow && (pTempWindow != pSWindow) )
+ {
+ if ( !pTempWindow->mpWindowImpl->mbPushButton )
+ {
+ // Around-Flag ermitteln
+ if ( nType == DLGWINDOW_PREV )
+ {
+ if ( nNewIndex > iStart )
+ nGetFocusFlags |= GETFOCUS_AROUND;
+ }
+ else
+ {
+ if ( nNewIndex < iStart )
+ nGetFocusFlags |= GETFOCUS_AROUND;
+ }
+ pTempWindow->ImplControlFocus( nGetFocusFlags );
+ return TRUE;
+ }
+ else
+ {
+ i = nNewIndex;
+ pTempWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
+ }
+ if ( (i <= iStart) || (i > nFormEnd) )
+ pTempWindow = NULL;
+ }
+ // Wenn es das gleiche Fenster ist, ein Get/LoseFocus
+ // simulieren, falls AROUND ausgewertet wird
+ if ( pTempWindow && (pTempWindow == pSWindow) )
+ {
+ NotifyEvent aNEvt1( EVENT_LOSEFOCUS, pSWindow );
+ if ( !ImplCallPreNotify( aNEvt1 ) )
+ pSWindow->LoseFocus();
+ pSWindow->mpWindowImpl->mnGetFocusFlags = nGetFocusFlags | GETFOCUS_AROUND;
+ NotifyEvent aNEvt2( EVENT_GETFOCUS, pSWindow );
+ if ( !ImplCallPreNotify( aNEvt2 ) )
+ pSWindow->GetFocus();
+ pSWindow->mpWindowImpl->mnGetFocusFlags = 0;
+ return TRUE;
+ }
+ }
+ }
+ else if ( nKeyCode == KEY_ESCAPE )
+ {
+ // Wir suchen zuerst nach einem DefPushButton/CancelButton
+ pButtonWindow = ImplGetChildWindow( this, nFormStart, iButton, TRUE );
+ iButtonStart = iButton;
+ while ( pButtonWindow )
+ {
+ if ( pButtonWindow->GetType() == WINDOW_CANCELBUTTON )
+ break;
+
+ pButtonWindow = ImplGetNextWindow( this, iButton, iButton, TRUE );
+ if ( (iButton <= iButtonStart) || (iButton > nFormEnd) )
+ pButtonWindow = NULL;
+ }
+
+ if ( bKeyInput && mpWindowImpl->mpDlgCtrlDownWindow )
+ {
+ if ( mpWindowImpl->mpDlgCtrlDownWindow != pButtonWindow )
+ {
+ ((PushButton*)mpWindowImpl->mpDlgCtrlDownWindow)->SetPressed( FALSE );
+ mpWindowImpl->mpDlgCtrlDownWindow = NULL;
+ return TRUE;
+ }
+ }
+ }
+ else if ( bKeyInput )
+ {
+ if ( nKeyCode == KEY_TAB )
+ {
+ // keine Alt-Taste abfangen, wegen Windows
+ if ( !aKeyCode.IsMod2() )
+ {
+ USHORT nType;
+ USHORT nGetFocusFlags = GETFOCUS_TAB;
+ USHORT nNewIndex;
+ BOOL bFormular = FALSE;
+
+ // Bei Ctrl-Tab erstmal testen, ob zwischen Formularen
+ // gesprungen werden soll
+ if ( aKeyCode.IsMod1() )
+ {
+ // Gruppe suchen
+ Window* pFormularFirstWindow = NULL;
+ Window* pLastFormularFirstWindow = NULL;
+ pTempWindow = ImplGetChildWindow( this, 0, iTemp, FALSE );
+ Window* pPrevFirstFormularFirstWindow = NULL;
+ Window* pFirstFormularFirstWindow = pTempWindow;
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->ImplGetWindow()->IsDialogControlStart() )
+ {
+ if ( iTemp != 0 )
+ bFormular = TRUE;
+ if ( aKeyCode.IsShift() )
+ {
+ if ( iTemp <= nIndex )
+ pFormularFirstWindow = pPrevFirstFormularFirstWindow;
+ pPrevFirstFormularFirstWindow = pTempWindow;
+ }
+ else
+ {
+ if ( (iTemp > nIndex) && !pFormularFirstWindow )
+ pFormularFirstWindow = pTempWindow;
+ }
+ pLastFormularFirstWindow = pTempWindow;
+ }
+
+ pTempWindow = ImplGetNextWindow( this, iTemp, iTemp, FALSE );
+ if ( !iTemp )
+ pTempWindow = NULL;
+ }
+
+ if ( bFormular )
+ {
+ if ( !pFormularFirstWindow )
+ {
+ if ( aKeyCode.IsShift() )
+ pFormularFirstWindow = pLastFormularFirstWindow;
+ else
+ pFormularFirstWindow = pFirstFormularFirstWindow;
+ }
+
+ USHORT nFoundFormStart = 0;
+ USHORT nFoundFormEnd = 0;
+ USHORT nTempIndex = 0;
+ if ( ::ImplFindDlgCtrlWindow( this, pFormularFirstWindow, nTempIndex,
+ nFoundFormStart, nFoundFormEnd ) )
+ {
+ nTempIndex = nFoundFormStart;
+ pFormularFirstWindow = ImplGetDlgWindow( nTempIndex, DLGWINDOW_FIRST, nFoundFormStart, nFoundFormEnd );
+ if ( pFormularFirstWindow )
+ {
+ pFormularFirstWindow->ImplControlFocus();
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ if ( !bFormular )
+ {
+ // Only use Ctrl-TAB if it was allowed for the whole
+ // dialog or for the current control (#103667#)
+ if ( !aKeyCode.IsMod1() || (nDlgCtrlFlags & WINDOW_DLGCTRL_MOD1TAB) ||
+ ( pSWindow->GetStyle() & WINDOW_DLGCTRL_MOD1TAB) )
+ {
+ if ( aKeyCode.IsShift() )
+ {
+ nType = DLGWINDOW_PREV;
+ nGetFocusFlags |= GETFOCUS_BACKWARD;
+ }
+ else
+ {
+ nType = DLGWINDOW_NEXT;
+ nGetFocusFlags |= GETFOCUS_FORWARD;
+ }
+ Window* pWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
+ // Wenn es das gleiche Fenster ist, ein Get/LoseFocus
+ // simulieren, falls AROUND ausgewertet wird
+ if ( pWindow == pSWindow )
+ {
+ NotifyEvent aNEvt1( EVENT_LOSEFOCUS, pSWindow );
+ if ( !ImplCallPreNotify( aNEvt1 ) )
+ pSWindow->LoseFocus();
+ pSWindow->mpWindowImpl->mnGetFocusFlags = nGetFocusFlags | GETFOCUS_AROUND;
+ NotifyEvent aNEvt2( EVENT_GETFOCUS, pSWindow );
+ if ( !ImplCallPreNotify( aNEvt2 ) )
+ pSWindow->GetFocus();
+ pSWindow->mpWindowImpl->mnGetFocusFlags = 0;
+ return TRUE;
+ }
+ else if ( pWindow )
+ {
+ // Around-Flag ermitteln
+ if ( nType == DLGWINDOW_PREV )
+ {
+ if ( nNewIndex > i )
+ nGetFocusFlags |= GETFOCUS_AROUND;
+ }
+ else
+ {
+ if ( nNewIndex < i )
+ nGetFocusFlags |= GETFOCUS_AROUND;
+ }
+ pWindow->ImplControlFocus( nGetFocusFlags );
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ else if ( (nKeyCode == KEY_LEFT) || (nKeyCode == KEY_UP) )
+ {
+ Window* pWindow = pSWindow;
+ WinBits nStyle = pSWindow->GetStyle();
+ if ( !(nStyle & WB_GROUP) )
+ {
+ pWindow = pWindow->GetWindow( WINDOW_PREV );
+ while ( pWindow )
+ {
+ pWindow = pWindow->ImplGetWindow();
+
+ nStyle = pWindow->GetStyle();
+
+ if ( pWindow->IsVisible() && pWindow->IsEnabled() && pWindow->IsInputEnabled() )
+ {
+ if ( pWindow != pSWindow )
+ pWindow->ImplControlFocus( GETFOCUS_CURSOR | GETFOCUS_BACKWARD );
+ return TRUE;
+ }
+
+ if ( nStyle & WB_GROUP )
+ break;
+
+ pWindow = pWindow->GetWindow( WINDOW_PREV );
+ }
+ }
+ }
+ else if ( (nKeyCode == KEY_RIGHT) || (nKeyCode == KEY_DOWN) )
+ {
+ Window* pWindow;
+ WinBits nStyle;
+ pWindow = pSWindow->GetWindow( WINDOW_NEXT );
+ while ( pWindow )
+ {
+ pWindow = pWindow->ImplGetWindow();
+
+ nStyle = pWindow->GetStyle();
+
+ if ( nStyle & WB_GROUP )
+ break;
+
+ if ( pWindow->IsVisible() && pWindow->IsEnabled() && pWindow->IsInputEnabled() )
+ {
+ pWindow->ImplControlFocus( GETFOCUS_CURSOR | GETFOCUS_BACKWARD );
+ return TRUE;
+ }
+
+ pWindow = pWindow->GetWindow( WINDOW_NEXT );
+ }
+ }
+ else
+ {
+ xub_Unicode c = rKEvt.GetCharCode();
+ if ( c )
+ {
+ pSWindow = ::ImplFindAccelWindow( this, i, c, nFormStart, nFormEnd );
+ if ( pSWindow )
+ {
+ USHORT nGetFocusFlags = GETFOCUS_MNEMONIC;
+ if ( pSWindow == ::ImplFindAccelWindow( this, i, c, nFormStart, nFormEnd ) )
+ nGetFocusFlags |= GETFOCUS_UNIQUEMNEMONIC;
+ pSWindow->ImplControlFocus( nGetFocusFlags );
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ if ( pButtonWindow && pButtonWindow->IsVisible() && pButtonWindow->IsEnabled() && pButtonWindow->IsInputEnabled() )
+ {
+ if ( bKeyInput )
+ {
+ if ( mpWindowImpl->mpDlgCtrlDownWindow && (mpWindowImpl->mpDlgCtrlDownWindow != pButtonWindow) )
+ {
+ ((PushButton*)mpWindowImpl->mpDlgCtrlDownWindow)->SetPressed( FALSE );
+ mpWindowImpl->mpDlgCtrlDownWindow = NULL;
+ }
+
+ ((PushButton*)pButtonWindow)->SetPressed( TRUE );
+ mpWindowImpl->mpDlgCtrlDownWindow = pButtonWindow;
+ }
+ else if ( mpWindowImpl->mpDlgCtrlDownWindow == pButtonWindow )
+ {
+ mpWindowImpl->mpDlgCtrlDownWindow = NULL;
+ ((PushButton*)pButtonWindow)->SetPressed( FALSE );
+ ((PushButton*)pButtonWindow)->Click();
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+// checks if this window has dialog control
+BOOL Window::ImplHasDlgCtrl()
+{
+ Window* pDlgCtrlParent;
+ Window* pDlgCtrl;
+
+ // lookup window for dialog control
+ pDlgCtrl = this;
+ pDlgCtrlParent = ImplGetParent();
+ while ( pDlgCtrlParent &&
+ !pDlgCtrlParent->ImplIsOverlapWindow() &&
+ ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
+ pDlgCtrlParent = pDlgCtrlParent->ImplGetParent();
+
+ if ( !pDlgCtrlParent || ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void Window::ImplDlgCtrlNextWindow()
+{
+ Window* pDlgCtrlParent;
+ Window* pDlgCtrl;
+ Window* pSWindow;
+ USHORT nIndex;
+ USHORT nFormStart;
+ USHORT nFormEnd;
+
+ // lookup window for dialog control
+ pDlgCtrl = this;
+ pDlgCtrlParent = ImplGetParent();
+ while ( pDlgCtrlParent &&
+ !pDlgCtrlParent->ImplIsOverlapWindow() &&
+ ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
+ pDlgCtrlParent = pDlgCtrlParent->ImplGetParent();
+
+if ( !pDlgCtrlParent || (GetStyle() & WB_NODIALOGCONTROL) || ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
+ return;
+
+ // lookup window in child list
+ pSWindow = ::ImplFindDlgCtrlWindow( pDlgCtrlParent, pDlgCtrl,
+ nIndex, nFormStart, nFormEnd );
+ if ( !pSWindow )
+ return;
+
+ Window* pWindow = pDlgCtrlParent->ImplGetDlgWindow( nIndex, DLGWINDOW_NEXT, nFormStart, nFormEnd );
+ if ( pWindow && (pWindow != pSWindow) )
+ pWindow->ImplControlFocus();
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDlgCtrlUpdateDefButton( Window* pParent, Window* pFocusWindow,
+ BOOL bGetFocus )
+{
+ PushButton* pOldDefButton = NULL;
+ PushButton* pNewDefButton = NULL;
+ Window* pSWindow;
+ USHORT i;
+ USHORT nFormStart;
+ USHORT nFormEnd;
+
+ // Formular suchen
+ pSWindow = ::ImplFindDlgCtrlWindow( pParent, pFocusWindow, i, nFormStart, nFormEnd );
+ if ( !pSWindow )
+ {
+ nFormStart = 0;
+ nFormEnd = 0xFFFF;
+ }
+
+ pSWindow = ImplGetChildWindow( pParent, nFormStart, i, FALSE );
+ while ( pSWindow )
+ {
+ if ( pSWindow->ImplIsPushButton() )
+ {
+ PushButton* pPushButton = (PushButton*)pSWindow;
+ if ( pPushButton->ImplIsDefButton() )
+ pOldDefButton = pPushButton;
+ if ( pPushButton->HasChildPathFocus() )
+ pNewDefButton = pPushButton;
+ else if ( !pNewDefButton && (pPushButton->GetStyle() & WB_DEFBUTTON) )
+ pNewDefButton = pPushButton;
+ }
+
+ pSWindow = ImplGetNextWindow( pParent, i, i, FALSE );
+ if ( !i || (i > nFormEnd) )
+ pSWindow = NULL;
+ }
+
+ if ( !bGetFocus )
+ {
+ USHORT nDummy;
+ Window* pNewFocusWindow = Application::GetFocusWindow();
+ if ( !pNewFocusWindow || !pParent->ImplIsWindowOrChild( pNewFocusWindow ) )
+ pNewDefButton = NULL;
+ else if ( !::ImplFindDlgCtrlWindow( pParent, pNewFocusWindow, i, nDummy, nDummy ) ||
+ (i < nFormStart) || (i > nFormEnd) )
+ pNewDefButton = NULL;
+ }
+
+ if ( pOldDefButton != pNewDefButton )
+ {
+ if ( pOldDefButton )
+ pOldDefButton->ImplSetDefButton( FALSE );
+ if ( pNewDefButton )
+ pNewDefButton->ImplSetDefButton( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplDlgCtrlFocusChanged( Window* pWindow, BOOL bGetFocus )
+{
+ if ( mpWindowImpl->mpDlgCtrlDownWindow && !bGetFocus )
+ {
+ ((PushButton*)mpWindowImpl->mpDlgCtrlDownWindow)->SetPressed( FALSE );
+ mpWindowImpl->mpDlgCtrlDownWindow = NULL;
+ }
+
+ ImplDlgCtrlUpdateDefButton( this, pWindow, bGetFocus );
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::ImplFindDlgCtrlWindow( Window* pWindow )
+{
+ USHORT nIndex;
+ USHORT nFormStart;
+ USHORT nFormEnd;
+
+ // Focus-Fenster in der Child-Liste suchen und zurueckgeben
+ return ::ImplFindDlgCtrlWindow( this, pWindow, nIndex, nFormStart, nFormEnd );
+}
+
+
+// -----------------------------------------------------------------------
+
+Window* Window::GetParentLabelFor( const Window* ) const
+{
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::GetParentLabeledBy( const Window* ) const
+{
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Unicode getAccel( const String& rStr )
+{
+ sal_Unicode nChar = 0;
+ USHORT nPos = 0;
+ do
+ {
+ nPos = rStr.Search( '~', nPos );
+ if( nPos != STRING_NOTFOUND && nPos < rStr.Len() )
+ nChar = rStr.GetChar( ++nPos );
+ else
+ nChar = 0;
+ } while( nChar == '~' );
+ return nChar;
+}
+
+static Window* ImplGetLabelFor( Window* pFrameWindow, WindowType nMyType, Window* pLabel, sal_Unicode nAccel )
+{
+ Window* pWindow = NULL;
+
+ if( nMyType == WINDOW_FIXEDTEXT ||
+ nMyType == WINDOW_FIXEDLINE ||
+ nMyType == WINDOW_GROUPBOX )
+ {
+ // #i100833# MT 2010/02: Group box and fixed lines can also lable a fixed text.
+ // See tools/options/print for example.
+ BOOL bThisIsAGroupControl = (nMyType == WINDOW_GROUPBOX) || (nMyType == WINDOW_FIXEDLINE);
+ Window* pSWindow = NULL;
+ // get index, form start and form end
+ USHORT nIndex=0, nFormStart=0, nFormEnd=0;
+ pSWindow = ::ImplFindDlgCtrlWindow( pFrameWindow,
+ pLabel,
+ nIndex,
+ nFormStart,
+ nFormEnd );
+ if( nAccel )
+ {
+ // find the accelerated window
+ pWindow = ::ImplFindAccelWindow( pFrameWindow,
+ nIndex,
+ nAccel,
+ nFormStart,
+ nFormEnd,
+ FALSE );
+ }
+ else
+ {
+ // find the next control; if that is a fixed text
+ // fixed line or group box, then return NULL
+ while( nIndex < nFormEnd )
+ {
+ nIndex++;
+ pSWindow = ::ImplGetChildWindow( pFrameWindow,
+ nIndex,
+ nIndex,
+ FALSE );
+ if( pSWindow && pSWindow->IsVisible() && ! (pSWindow->GetStyle() & WB_NOLABEL) )
+ {
+ WindowType nType = pSWindow->GetType();
+ if( nType != WINDOW_FIXEDTEXT &&
+ nType != WINDOW_FIXEDLINE &&
+ nType != WINDOW_GROUPBOX )
+ {
+ pWindow = pSWindow;
+ }
+ else if( bThisIsAGroupControl && ( nType == WINDOW_FIXEDTEXT ) )
+ {
+ pWindow = pSWindow;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return pWindow;
+}
+
+Window* Window::GetLabelFor() const
+{
+ if ( mpWindowImpl->mbDisableAccessibleLabelForRelation )
+ return NULL;
+
+ Window* pWindow = NULL;
+ Window* pFrameWindow = ImplGetFrameWindow();
+
+ WinBits nFrameStyle = pFrameWindow->GetStyle();
+ if( ! ( nFrameStyle & WB_DIALOGCONTROL )
+ || ( nFrameStyle & WB_NODIALOGCONTROL )
+ )
+ return NULL;
+
+ if ( mpWindowImpl->mpRealParent )
+ pWindow = mpWindowImpl->mpRealParent->GetParentLabelFor( this );
+
+ if( pWindow )
+ return pWindow;
+
+ sal_Unicode nAccel = getAccel( GetText() );
+
+ pWindow = ImplGetLabelFor( pFrameWindow, GetType(), const_cast<Window*>(this), nAccel );
+ if( ! pWindow && mpWindowImpl->mpRealParent )
+ pWindow = ImplGetLabelFor( mpWindowImpl->mpRealParent, GetType(), const_cast<Window*>(this), nAccel );
+ return pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetLabeledBy( Window* pFrameWindow, WindowType nMyType, Window* pLabeled )
+{
+ Window* pWindow = NULL;
+ if ( (nMyType != WINDOW_GROUPBOX) && (nMyType != WINDOW_FIXEDLINE) )
+ {
+ // search for a control that labels this window
+ // a label is considered the last fixed text, fixed line or group box
+ // that comes before this control; with the exception of push buttons
+ // which are labeled only if the fixed text, fixed line or group box
+ // is directly before the control
+
+ // get form start and form end and index of this control
+ USHORT nIndex, nFormStart, nFormEnd;
+ Window* pSWindow = ::ImplFindDlgCtrlWindow( pFrameWindow,
+ pLabeled,
+ nIndex,
+ nFormStart,
+ nFormEnd );
+ if( pSWindow && nIndex != nFormStart )
+ {
+ if( nMyType == WINDOW_PUSHBUTTON ||
+ nMyType == WINDOW_HELPBUTTON ||
+ nMyType == WINDOW_OKBUTTON ||
+ nMyType == WINDOW_CANCELBUTTON )
+ {
+ nFormStart = nIndex-1;
+ }
+ for( USHORT nSearchIndex = nIndex-1; nSearchIndex >= nFormStart; nSearchIndex-- )
+ {
+ USHORT nFoundIndex = 0;
+ pSWindow = ::ImplGetChildWindow( pFrameWindow,
+ nSearchIndex,
+ nFoundIndex,
+ FALSE );
+ if( pSWindow && pSWindow->IsVisible() && !(pSWindow->GetStyle() & WB_NOLABEL) )
+ {
+ WindowType nType = pSWindow->GetType();
+ if ( ( nType == WINDOW_FIXEDTEXT ||
+ nType == WINDOW_FIXEDLINE ||
+ nType == WINDOW_GROUPBOX ) )
+ {
+ // a fixed text can't be labeld by a fixed text.
+ if ( ( nMyType != WINDOW_FIXEDTEXT ) || ( nType != WINDOW_FIXEDTEXT ) )
+ pWindow = pSWindow;
+ break;
+ }
+ }
+ if( nFoundIndex > nSearchIndex || nSearchIndex == 0 )
+ break;
+ }
+ }
+ }
+ return pWindow;
+}
+
+Window* Window::GetLabeledBy() const
+{
+ if ( mpWindowImpl->mbDisableAccessibleLabeledByRelation )
+ return NULL;
+
+ Window* pWindow = NULL;
+ Window* pFrameWindow = ImplGetFrameWindow();
+
+ if ( mpWindowImpl->mpRealParent )
+ {
+ pWindow = mpWindowImpl->mpRealParent->GetParentLabeledBy( this );
+
+ if( pWindow )
+ return pWindow;
+ }
+
+ // #i62723#, #104191# checkboxes and radiobuttons are not supposed to have labels
+ if( GetType() == WINDOW_CHECKBOX || GetType() == WINDOW_RADIOBUTTON )
+ return NULL;
+
+// if( ! ( GetType() == WINDOW_FIXEDTEXT ||
+// GetType() == WINDOW_FIXEDLINE ||
+// GetType() == WINDOW_GROUPBOX ) )
+ // #i100833# MT 2010/02: Group box and fixed lines can also lable a fixed text.
+ // See tools/options/print for example.
+
+ pWindow = ImplGetLabeledBy( pFrameWindow, GetType(), const_cast<Window*>(this) );
+ if( ! pWindow && mpWindowImpl->mpRealParent )
+ pWindow = ImplGetLabeledBy( mpWindowImpl->mpRealParent, GetType(), const_cast<Window*>(this) );
+
+ return pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+KeyEvent Window::GetActivationKey() const
+{
+ KeyEvent aKeyEvent;
+
+ sal_Unicode nAccel = getAccel( GetText() );
+ if( ! nAccel )
+ {
+ Window* pWindow = GetLabeledBy();
+ if( pWindow )
+ nAccel = getAccel( pWindow->GetText() );
+ }
+ if( nAccel )
+ {
+ USHORT nCode = 0;
+ if( nAccel >= 'a' && nAccel <= 'z' )
+ nCode = KEY_A + (nAccel-'a');
+ else if( nAccel >= 'A' && nAccel <= 'Z' )
+ nCode = KEY_A + (nAccel-'A');
+ else if( nAccel >= '0' && nAccel <= '9' )
+ nCode = KEY_0 + (nAccel-'0');
+ KeyCode aKeyCode( nCode, FALSE, FALSE, TRUE, FALSE );
+ aKeyEvent = KeyEvent( nAccel, aKeyCode );
+ }
+ return aKeyEvent;
+}
diff --git a/vcl/source/window/dndevdis.cxx b/vcl/source/window/dndevdis.cxx
new file mode 100644
index 000000000000..e4d5a8c4c0eb
--- /dev/null
+++ b/vcl/source/window/dndevdis.cxx
@@ -0,0 +1,564 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <vcl/dndevdis.hxx>
+#include <vcl/dndlcon.hxx>
+#include <vcl/window.h>
+
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/svdata.hxx>
+using namespace ::osl;
+using namespace ::vos;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::datatransfer::dnd;
+
+//==================================================================================================
+// DNDEventDispatcher::DNDEventDispatcher
+//==================================================================================================
+
+DNDEventDispatcher::DNDEventDispatcher( Window * pTopWindow ):
+ m_pTopWindow( pTopWindow ),
+ m_pCurrentWindow( NULL )
+{
+}
+
+//==================================================================================================
+// DNDEventDispatcher::~DNDEventDispatcher
+//==================================================================================================
+
+DNDEventDispatcher::~DNDEventDispatcher()
+{
+}
+
+//==================================================================================================
+// DNDEventDispatcher::drop
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::drop( const DropTargetDropEvent& dtde )
+ throw(RuntimeException)
+{
+ MutexGuard aImplGuard( m_aMutex );
+
+ Point location( dtde.LocationX, dtde.LocationY );
+
+ // find the window that is toplevel for this coordinates
+ OClearableGuard aSolarGuard( Application::GetSolarMutex() );
+
+ // because those coordinates come from outside, they must be mirrored if RTL layout is active
+ if( Application::GetSettings().GetLayoutRTL() )
+ m_pTopWindow->ImplMirrorFramePos( location );
+ Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
+
+ if( NULL == pChildWindow )
+ pChildWindow = m_pTopWindow;
+
+ while( pChildWindow->ImplGetClientWindow() )
+ pChildWindow = pChildWindow->ImplGetClientWindow();
+
+ if( pChildWindow->ImplIsAntiparallel() )
+ pChildWindow->ImplReMirror( location );
+
+ aSolarGuard.clear();
+
+ // handle the case that drop is in an other vcl window than the last dragOver
+ if( pChildWindow != m_pCurrentWindow )
+ {
+ // fire dragExit on listeners of previous window
+ fireDragExitEvent( m_pCurrentWindow );
+
+ fireDragEnterEvent( pChildWindow, static_cast < XDropTargetDragContext * > (this),
+ dtde.DropAction, location, dtde.SourceActions, m_aDataFlavorList );
+ }
+
+ sal_Int32 nListeners = 0;
+
+ // send drop event to the child window
+ nListeners = fireDropEvent( pChildWindow, dtde.Context, dtde.DropAction,
+ location, dtde.SourceActions, dtde.Transferable );
+
+ // reject drop if no listeners found
+ if( nListeners == 0 ) {
+ OSL_TRACE( "rejecting drop due to missing listeners." );
+ dtde.Context->rejectDrop();
+ }
+
+ // this is a drop -> no further drag overs
+ m_pCurrentWindow = NULL;
+ m_aDataFlavorList.realloc( 0 );
+}
+
+//==================================================================================================
+// DNDEventDispatcher::dragEnter
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::dragEnter( const DropTargetDragEnterEvent& dtdee )
+ throw(RuntimeException)
+{
+ MutexGuard aImplGuard( m_aMutex );
+ Point location( dtdee.LocationX, dtdee.LocationY );
+
+ // find the window that is toplevel for this coordinates
+ OClearableGuard aSolarGuard( Application::GetSolarMutex() );
+
+ // because those coordinates come from outside, they must be mirrored if RTL layout is active
+ if( Application::GetSettings().GetLayoutRTL() )
+ m_pTopWindow->ImplMirrorFramePos( location );
+ Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
+
+ if( NULL == pChildWindow )
+ pChildWindow = m_pTopWindow;
+
+ while( pChildWindow->ImplGetClientWindow() )
+ pChildWindow = pChildWindow->ImplGetClientWindow();
+
+ if( pChildWindow->ImplIsAntiparallel() )
+ pChildWindow->ImplReMirror( location );
+
+ aSolarGuard.clear();
+
+ // assume pointer write operation to be atomic
+ m_pCurrentWindow = pChildWindow;
+ m_aDataFlavorList = dtdee.SupportedDataFlavors;
+
+ // fire dragEnter on listeners of current window
+ sal_Int32 nListeners = fireDragEnterEvent( pChildWindow, dtdee.Context, dtdee.DropAction, location,
+ dtdee.SourceActions, dtdee.SupportedDataFlavors );
+
+ // reject drag if no listener found
+ if( nListeners == 0 ) {
+ OSL_TRACE( "rejecting drag enter due to missing listeners." );
+ dtdee.Context->rejectDrag();
+ }
+
+}
+
+//==================================================================================================
+// DNDEventDispatcher::dragExit
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::dragExit( const DropTargetEvent& /*dte*/ )
+ throw(RuntimeException)
+{
+ MutexGuard aImplGuard( m_aMutex );
+
+ fireDragExitEvent( m_pCurrentWindow );
+
+ // reset member values
+ m_pCurrentWindow = NULL;
+ m_aDataFlavorList.realloc( 0 );
+}
+
+//==================================================================================================
+// DNDEventDispatcher::dragOver
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::dragOver( const DropTargetDragEvent& dtde )
+ throw(RuntimeException)
+{
+ MutexGuard aImplGuard( m_aMutex );
+
+ Point location( dtde.LocationX, dtde.LocationY );
+ sal_Int32 nListeners;
+
+ // find the window that is toplevel for this coordinates
+ OClearableGuard aSolarGuard( Application::GetSolarMutex() );
+
+ // because those coordinates come from outside, they must be mirrored if RTL layout is active
+ if( Application::GetSettings().GetLayoutRTL() )
+ m_pTopWindow->ImplMirrorFramePos( location );
+ Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
+
+ if( NULL == pChildWindow )
+ pChildWindow = m_pTopWindow;
+
+ while( pChildWindow->ImplGetClientWindow() )
+ pChildWindow = pChildWindow->ImplGetClientWindow();
+
+ if( pChildWindow->ImplIsAntiparallel() )
+ pChildWindow->ImplReMirror( location );
+
+ aSolarGuard.clear();
+
+ if( pChildWindow != m_pCurrentWindow )
+ {
+ // fire dragExit on listeners of previous window
+ fireDragExitEvent( m_pCurrentWindow );
+
+ // remember new window
+ m_pCurrentWindow = pChildWindow;
+
+ // fire dragEnter on listeners of current window
+ nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
+ dtde.SourceActions, m_aDataFlavorList );
+ }
+ else
+ {
+ // fire dragOver on listeners of current window
+ nListeners = fireDragOverEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
+ dtde.SourceActions );
+ }
+
+ // reject drag if no listener found
+ if( nListeners == 0 )
+ {
+ OSL_TRACE( "rejecting drag over due to missing listeners." );
+ dtde.Context->rejectDrag();
+ }
+}
+
+//==================================================================================================
+// DNDEventDispatcher::dropActionChanged
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::dropActionChanged( const DropTargetDragEvent& dtde )
+ throw(RuntimeException)
+{
+ MutexGuard aImplGuard( m_aMutex );
+
+ Point location( dtde.LocationX, dtde.LocationY );
+ sal_Int32 nListeners;
+
+ // find the window that is toplevel for this coordinates
+ OClearableGuard aSolarGuard( Application::GetSolarMutex() );
+
+ // because those coordinates come from outside, they must be mirrored if RTL layout is active
+ if( Application::GetSettings().GetLayoutRTL() )
+ m_pTopWindow->ImplMirrorFramePos( location );
+ Window * pChildWindow = m_pTopWindow->ImplFindWindow( location );
+
+ if( NULL == pChildWindow )
+ pChildWindow = m_pTopWindow;
+
+ while( pChildWindow->ImplGetClientWindow() )
+ pChildWindow = pChildWindow->ImplGetClientWindow();
+
+ if( pChildWindow->ImplIsAntiparallel() )
+ pChildWindow->ImplReMirror( location );
+
+ aSolarGuard.clear();
+
+ if( pChildWindow != m_pCurrentWindow )
+ {
+ // fire dragExit on listeners of previous window
+ fireDragExitEvent( m_pCurrentWindow );
+
+ // remember new window
+ m_pCurrentWindow = pChildWindow;
+
+ // fire dragEnter on listeners of current window
+ nListeners = fireDragEnterEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
+ dtde.SourceActions, m_aDataFlavorList );
+ }
+ else
+ {
+ // fire dropActionChanged on listeners of current window
+ nListeners = fireDropActionChangedEvent( pChildWindow, dtde.Context, dtde.DropAction, location,
+ dtde.SourceActions );
+ }
+
+ // reject drag if no listener found
+ if( nListeners == 0 )
+ {
+ OSL_TRACE( "rejecting dropActionChanged due to missing listeners." );
+ dtde.Context->rejectDrag();
+ }
+}
+
+
+//==================================================================================================
+// DNDEventDispatcher::dragGestureRecognized
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::dragGestureRecognized( const DragGestureEvent& dge )
+ throw(RuntimeException)
+{ MutexGuard aImplGuard( m_aMutex );
+
+ Point origin( dge.DragOriginX, dge.DragOriginY );
+
+ // find the window that is toplevel for this coordinates
+ OClearableGuard aSolarGuard( Application::GetSolarMutex() );
+
+ // because those coordinates come from outside, they must be mirrored if RTL layout is active
+ if( Application::GetSettings().GetLayoutRTL() )
+ m_pTopWindow->ImplMirrorFramePos( origin );
+ Window * pChildWindow = m_pTopWindow->ImplFindWindow( origin );
+
+ if( NULL == pChildWindow )
+ pChildWindow = m_pTopWindow;
+
+ while( pChildWindow->ImplGetClientWindow() )
+ pChildWindow = pChildWindow->ImplGetClientWindow();
+
+ if( pChildWindow->ImplIsAntiparallel() )
+ pChildWindow->ImplReMirror( origin );
+
+ aSolarGuard.clear();
+
+ fireDragGestureEvent( pChildWindow, dge.DragSource, dge.Event, origin, dge.DragAction );
+}
+
+//==================================================================================================
+// DNDEventDispatcher::disposing
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::disposing( const EventObject& )
+ throw(RuntimeException)
+{
+}
+
+//==================================================================================================
+// DNDEventDispatcher::acceptDrag
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::acceptDrag( sal_Int8 /*dropAction*/ ) throw(RuntimeException)
+{
+}
+
+//==================================================================================================
+// DNDEventDispatcher::rejectDrag
+//==================================================================================================
+
+void SAL_CALL DNDEventDispatcher::rejectDrag() throw(RuntimeException)
+{
+}
+
+//==================================================================================================
+// DNDEventDispatcher::fireDragEnterEvent
+//==================================================================================================
+
+sal_Int32 DNDEventDispatcher::fireDragEnterEvent( Window *pWindow,
+ const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
+ const Point& rLocation, const sal_Int8 nSourceActions, const Sequence< DataFlavor >& aFlavorList
+)
+ throw(RuntimeException)
+{
+ sal_Int32 n = 0;
+
+ if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
+ {
+ OClearableGuard aGuard( Application::GetSolarMutex() );
+
+ // set an UI lock
+ pWindow->IncrementLockCount();
+
+ // query DropTarget from window
+ Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
+
+ if( xDropTarget.is() )
+ {
+ // retrieve relative mouse position
+ Point relLoc = pWindow->ImplFrameToOutput( rLocation );
+ aGuard.clear();
+
+ n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragEnterEvent(
+ xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, aFlavorList );
+ }
+ }
+
+ return n;
+}
+
+//==================================================================================================
+// DNDEventDispatcher::fireDragOverEvent
+//==================================================================================================
+
+sal_Int32 DNDEventDispatcher::fireDragOverEvent( Window *pWindow,
+ const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
+ const Point& rLocation, const sal_Int8 nSourceActions
+)
+ throw(RuntimeException)
+{
+ sal_Int32 n = 0;
+
+ if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
+ {
+ OClearableGuard aGuard( Application::GetSolarMutex() );
+
+ // query DropTarget from window
+ Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
+
+ if( xDropTarget.is() )
+ {
+ // retrieve relative mouse position
+ Point relLoc = pWindow->ImplFrameToOutput( rLocation );
+ aGuard.clear();
+
+ n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragOverEvent(
+ xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
+ }
+ }
+
+ return n;
+}
+
+//==================================================================================================
+// DNDEventDispatcher::fireDragExitEvent
+//==================================================================================================
+
+sal_Int32 DNDEventDispatcher::fireDragExitEvent( Window *pWindow ) throw(RuntimeException)
+{
+ sal_Int32 n = 0;
+
+ if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
+ {
+ OClearableGuard aGuard( Application::GetSolarMutex() );
+
+ // query DropTarget from window
+ Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
+
+ aGuard.clear();
+
+ if( xDropTarget.is() )
+ n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDragExitEvent();
+
+ // release UI lock
+ pWindow->DecrementLockCount();
+ }
+
+ return n;
+}
+
+//==================================================================================================
+// DNDEventDispatcher::fireDropActionChangedEvent
+//==================================================================================================
+
+sal_Int32 DNDEventDispatcher::fireDropActionChangedEvent( Window *pWindow,
+ const Reference< XDropTargetDragContext >& xContext, const sal_Int8 nDropAction,
+ const Point& rLocation, const sal_Int8 nSourceActions
+)
+ throw(RuntimeException)
+{
+ sal_Int32 n = 0;
+
+ if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
+ {
+ OClearableGuard aGuard( Application::GetSolarMutex() );
+
+ // query DropTarget from window
+ Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
+
+ if( xDropTarget.is() )
+ {
+ // retrieve relative mouse position
+ Point relLoc = pWindow->ImplFrameToOutput( rLocation );
+ aGuard.clear();
+
+ n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropActionChangedEvent(
+ xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions );
+ }
+ }
+
+ return n;
+}
+
+//==================================================================================================
+// DNDEventDispatcher::fireDropEvent
+//==================================================================================================
+
+sal_Int32 DNDEventDispatcher::fireDropEvent( Window *pWindow,
+ const Reference< XDropTargetDropContext >& xContext, const sal_Int8 nDropAction, const Point& rLocation,
+ const sal_Int8 nSourceActions, const Reference< XTransferable >& xTransferable
+)
+ throw(RuntimeException)
+{
+ sal_Int32 n = 0;
+
+ if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
+ {
+ OClearableGuard aGuard( Application::GetSolarMutex() );
+
+ // query DropTarget from window
+ Reference< XDropTarget > xDropTarget = pWindow->GetDropTarget();
+
+ // window may be destroyed in drop event handler
+ ImplDelData aDelData;
+ pWindow->ImplAddDel( &aDelData );
+
+ if( xDropTarget.is() )
+ {
+ // retrieve relative mouse position
+ Point relLoc = pWindow->ImplFrameToOutput( rLocation );
+ aGuard.clear();
+
+ n = static_cast < DNDListenerContainer * > ( xDropTarget.get() )->fireDropEvent(
+ xContext, nDropAction, relLoc.X(), relLoc.Y(), nSourceActions, xTransferable );
+ }
+
+ if ( !aDelData.IsDelete() )
+ {
+ pWindow->ImplRemoveDel( &aDelData );
+ // release UI lock
+ pWindow->DecrementLockCount();
+ }
+
+ }
+
+ return n;
+}
+
+//==================================================================================================
+// DNDEventDispatcher::fireDragGestureRecognized
+//==================================================================================================
+
+sal_Int32 DNDEventDispatcher::fireDragGestureEvent( Window *pWindow,
+ const Reference< XDragSource >& xSource, const Any event,
+ const Point& rOrigin, const sal_Int8 nDragAction
+)
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ sal_Int32 n = 0;
+
+ if( pWindow && pWindow->IsInputEnabled() && ! pWindow->IsInModalMode() )
+ {
+ OClearableGuard aGuard( Application::GetSolarMutex() );
+
+ // query DropTarget from window
+ Reference< XDragGestureRecognizer > xDragGestureRecognizer = pWindow->GetDragGestureRecognizer();
+
+ if( xDragGestureRecognizer.is() )
+ {
+ // retrieve relative mouse position
+ Point relLoc = pWindow->ImplFrameToOutput( rOrigin );
+ aGuard.clear();
+
+ n = static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent(
+ nDragAction, relLoc.X(), relLoc.Y(), xSource, event );
+ }
+
+ // release UI lock
+ pWindow->DecrementLockCount();
+ }
+
+ return n;
+}
diff --git a/vcl/source/window/dndlcon.cxx b/vcl/source/window/dndlcon.cxx
new file mode 100644
index 000000000000..07819e76f957
--- /dev/null
+++ b/vcl/source/window/dndlcon.cxx
@@ -0,0 +1,567 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <vcl/dndlcon.hxx>
+
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::datatransfer::dnd;
+
+//==================================================================================================
+//
+//==================================================================================================
+
+DNDListenerContainer::DNDListenerContainer( sal_Int8 nDefaultActions )
+ : WeakComponentImplHelper4< XDragGestureRecognizer, XDropTargetDragContext, XDropTargetDropContext, XDropTarget >(GetMutex())
+{
+ m_bActive = sal_True;
+ m_nDefaultActions = nDefaultActions;
+}
+
+//==================================================================================================
+//
+//==================================================================================================
+
+DNDListenerContainer::~DNDListenerContainer()
+{
+}
+
+//==================================================================================================
+// DNDListenerContainer::addDragGestureListener
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::addDragGestureListener( const Reference< XDragGestureListener >& dgl )
+ throw(RuntimeException)
+{
+ rBHelper.addListener( getCppuType( ( const Reference< XDragGestureListener > * ) 0 ), dgl );
+}
+
+//==================================================================================================
+// DNDListenerContainer::removeDragGestureListener
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::removeDragGestureListener( const Reference< XDragGestureListener >& dgl )
+ throw(RuntimeException)
+{
+ rBHelper.removeListener( getCppuType( ( const Reference< XDragGestureListener > * ) 0 ), dgl );
+}
+
+//==================================================================================================
+// DNDListenerContainer::resetRecognizer
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::resetRecognizer( )
+ throw(RuntimeException)
+{
+}
+
+//==================================================================================================
+// DNDListenerContainer::addDropTargetListener
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::addDropTargetListener( const Reference< XDropTargetListener >& dtl )
+ throw(RuntimeException)
+{
+ rBHelper.addListener( getCppuType( ( const Reference< XDropTargetListener > * ) 0 ), dtl );
+}
+
+//==================================================================================================
+// DNDListenerContainer::removeDropTargetListener
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::removeDropTargetListener( const Reference< XDropTargetListener >& dtl )
+ throw(RuntimeException)
+{
+ rBHelper.removeListener( getCppuType( ( const Reference< XDropTargetListener > * ) 0 ), dtl );
+}
+
+//==================================================================================================
+// DNDListenerContainer::isActive
+//==================================================================================================
+
+sal_Bool SAL_CALL DNDListenerContainer::isActive( )
+ throw(RuntimeException)
+{
+ return m_bActive;
+}
+
+//==================================================================================================
+// DNDListenerContainer::setActive
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::setActive( sal_Bool active )
+ throw(RuntimeException)
+{
+ m_bActive = active;
+}
+
+//==================================================================================================
+// DNDListenerContainer::getDefaultActions
+//==================================================================================================
+
+sal_Int8 SAL_CALL DNDListenerContainer::getDefaultActions( )
+ throw(RuntimeException)
+{
+ return m_nDefaultActions;
+}
+
+//==================================================================================================
+// DNDListenerContainer::setDefaultActions
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::setDefaultActions( sal_Int8 actions )
+ throw(RuntimeException)
+{
+ m_nDefaultActions = actions;
+}
+
+//==================================================================================================
+// DNDListenerContainer::fireDropEvent
+//==================================================================================================
+
+sal_uInt32 DNDListenerContainer::fireDropEvent( const Reference< XDropTargetDropContext >& context,
+ sal_Int8 dropAction, sal_Int32 locationX, sal_Int32 locationY, sal_Int8 sourceActions,
+ const Reference< XTransferable >& transferable )
+{
+ sal_uInt32 nRet = 0;
+
+ // fire DropTargetDropEvent on all XDropTargetListeners
+ OInterfaceContainerHelper *pContainer = rBHelper.getContainer( getCppuType( ( Reference < XDropTargetListener > * ) 0) );
+
+ if( pContainer && m_bActive )
+ {
+ OInterfaceIteratorHelper aIterator( *pContainer );
+
+ // remember context to use in own context methods
+ m_xDropTargetDropContext = context;
+
+ // do not construct the event before you are sure at least one listener is registered
+ DropTargetDropEvent aEvent( static_cast < XDropTarget * > (this), 0,
+ static_cast < XDropTargetDropContext * > (this), dropAction,
+ locationX, locationY, sourceActions, transferable );
+
+ while (aIterator.hasMoreElements())
+ {
+ // FIXME: this can be simplified as soon as the Iterator has a remove method
+ Reference< XInterface > xElement( aIterator.next() );
+
+ try
+ {
+ // this may result in a runtime exception
+ Reference < XDropTargetListener > xListener( xElement, UNO_QUERY );
+
+ if( xListener.is() )
+ {
+ // fire drop until the first one has accepted
+ if( m_xDropTargetDropContext.is() )
+ xListener->drop( aEvent );
+ else
+ {
+ DropTargetEvent aDTEvent( static_cast < XDropTarget * > (this), 0 );
+ xListener->dragExit( aDTEvent );
+ }
+
+ nRet++;
+ }
+ }
+
+ catch( RuntimeException exc )
+ {
+ pContainer->removeInterface( xElement );
+ }
+ }
+
+ // if context still valid, then reject drop
+ if( m_xDropTargetDropContext.is() )
+ {
+ m_xDropTargetDropContext.clear();
+
+ try
+ {
+ context->rejectDrop();
+ }
+
+ catch( RuntimeException exc )
+ {
+ }
+ }
+ }
+
+ return nRet;
+}
+
+//==================================================================================================
+// DNDListenerContainer::fireDragExitEvent
+//==================================================================================================
+
+sal_uInt32 DNDListenerContainer::fireDragExitEvent()
+{
+ sal_uInt32 nRet = 0;
+
+ // fire DropTargetDropEvent on all XDropTargetListeners
+ OInterfaceContainerHelper *pContainer = rBHelper.getContainer( getCppuType( ( Reference < XDropTargetListener > * ) 0) );
+
+ if( pContainer && m_bActive )
+ {
+ OInterfaceIteratorHelper aIterator( *pContainer );
+
+ // do not construct the event before you are sure at least one listener is registered
+ DropTargetEvent aEvent( static_cast < XDropTarget * > (this), 0 );
+
+ while (aIterator.hasMoreElements())
+ {
+ // FIXME: this can be simplified as soon as the Iterator has a remove method
+ Reference< XInterface > xElement( aIterator.next() );
+
+ try
+ {
+ // this may result in a runtime exception
+ Reference < XDropTargetListener > xListener( xElement, UNO_QUERY );
+
+ if( xListener.is() )
+ {
+ xListener->dragExit( aEvent );
+ nRet++;
+ }
+ }
+
+ catch( RuntimeException exc )
+ {
+ pContainer->removeInterface( xElement );
+ }
+ }
+ }
+
+ return nRet;
+}
+
+//==================================================================================================
+// DNDListenerContainer::fireDragOverEvent
+//==================================================================================================
+
+sal_uInt32 DNDListenerContainer::fireDragOverEvent( const Reference< XDropTargetDragContext >& context,
+ sal_Int8 dropAction, sal_Int32 locationX, sal_Int32 locationY, sal_Int8 sourceActions )
+{
+ sal_uInt32 nRet = 0;
+
+ // fire DropTargetDropEvent on all XDropTargetListeners
+ OInterfaceContainerHelper *pContainer = rBHelper.getContainer( getCppuType( ( Reference < XDropTargetListener > * ) 0) );
+
+ if( pContainer && m_bActive )
+ {
+ OInterfaceIteratorHelper aIterator( *pContainer );
+
+ // remember context to use in own context methods
+ m_xDropTargetDragContext = context;
+
+ // do not construct the event before you are sure at least one listener is registered
+ DropTargetDragEvent aEvent( static_cast < XDropTarget * > (this), 0,
+ static_cast < XDropTargetDragContext * > (this),
+ dropAction, locationX, locationY, sourceActions );
+
+ while (aIterator.hasMoreElements())
+ {
+ // FIXME: this can be simplified as soon as the Iterator has a remove method
+ Reference< XInterface > xElement( aIterator.next() );
+
+ try
+ {
+ // this may result in a runtime exception
+ Reference < XDropTargetListener > xListener( xElement, UNO_QUERY );
+
+ if( xListener.is() )
+ {
+ if( m_xDropTargetDragContext.is() )
+ xListener->dragOver( aEvent );
+ nRet++;
+ }
+ }
+
+ catch( RuntimeException exc )
+ {
+ pContainer->removeInterface( xElement );
+ }
+ }
+
+ // if context still valid, then reject drag
+ if( m_xDropTargetDragContext.is() )
+ {
+ m_xDropTargetDragContext.clear();
+
+ try
+ {
+ context->rejectDrag();
+ }
+
+ catch( RuntimeException exc )
+ {
+ }
+ }
+ }
+
+ return nRet;
+}
+
+//==================================================================================================
+// DNDListenerContainer::fireDragEnterEvent
+//==================================================================================================
+
+sal_uInt32 DNDListenerContainer::fireDragEnterEvent( const Reference< XDropTargetDragContext >& context,
+ sal_Int8 dropAction, sal_Int32 locationX, sal_Int32 locationY, sal_Int8 sourceActions,
+ const Sequence< DataFlavor >& dataFlavors )
+{
+ sal_uInt32 nRet = 0;
+
+ // fire DropTargetDropEvent on all XDropTargetListeners
+ OInterfaceContainerHelper *pContainer = rBHelper.getContainer( getCppuType( ( Reference < XDropTargetListener > * ) 0) );
+
+ if( pContainer && m_bActive )
+ {
+ OInterfaceIteratorHelper aIterator( *pContainer );
+
+ // remember context to use in own context methods
+ m_xDropTargetDragContext = context;
+
+ // do not construct the event before you are sure at least one listener is registered
+ DropTargetDragEnterEvent aEvent( static_cast < XDropTarget * > (this), 0,
+ static_cast < XDropTargetDragContext * > (this),
+ dropAction, locationX, locationY, sourceActions, dataFlavors );
+
+ while (aIterator.hasMoreElements())
+ {
+ // FIXME: this can be simplified as soon as the Iterator has a remove method
+ Reference< XInterface > xElement( aIterator.next() );
+
+ try
+ {
+ // this may result in a runtime exception
+ Reference < XDropTargetListener > xListener( xElement, UNO_QUERY );
+
+ if( xListener.is() )
+ {
+ if( m_xDropTargetDragContext.is() )
+ xListener->dragEnter( aEvent );
+ nRet++;
+ }
+ }
+
+ catch( RuntimeException exc )
+ {
+ pContainer->removeInterface( xElement );
+ }
+ }
+
+ // if context still valid, then reject drag
+ if( m_xDropTargetDragContext.is() )
+ {
+ m_xDropTargetDragContext.clear();
+
+ try
+ {
+ context->rejectDrag();
+ }
+
+ catch( RuntimeException exc )
+ {
+ }
+ }
+ }
+
+ return nRet;
+}
+
+//==================================================================================================
+// DNDListenerContainer::fireDropActionChangedEvent
+//==================================================================================================
+
+sal_uInt32 DNDListenerContainer::fireDropActionChangedEvent( const Reference< XDropTargetDragContext >& context,
+ sal_Int8 dropAction, sal_Int32 locationX, sal_Int32 locationY, sal_Int8 sourceActions )
+{
+ sal_uInt32 nRet = 0;
+
+ // fire DropTargetDropEvent on all XDropTargetListeners
+ OInterfaceContainerHelper *pContainer = rBHelper.getContainer( getCppuType( ( Reference < XDropTargetListener > * ) 0) );
+
+ if( pContainer && m_bActive )
+ {
+ OInterfaceIteratorHelper aIterator( *pContainer );
+
+ // remember context to use in own context methods
+ m_xDropTargetDragContext = context;
+
+ // do not construct the event before you are sure at least one listener is registered
+ DropTargetDragEvent aEvent( static_cast < XDropTarget * > (this), 0,
+ static_cast < XDropTargetDragContext * > (this),
+ dropAction, locationX, locationY, sourceActions );
+
+ while (aIterator.hasMoreElements())
+ {
+ // FIXME: this can be simplified as soon as the Iterator has a remove method
+ Reference< XInterface > xElement( aIterator.next() );
+
+ try
+ {
+ // this may result in a runtime exception
+ Reference < XDropTargetListener > xListener( xElement, UNO_QUERY );
+
+ if( xListener.is() )
+ {
+ if( m_xDropTargetDragContext.is() )
+ xListener->dropActionChanged( aEvent );
+ nRet++;
+ }
+ }
+
+ catch( RuntimeException exc )
+ {
+ pContainer->removeInterface( xElement );
+ }
+ }
+
+ // if context still valid, then reject drag
+ if( m_xDropTargetDragContext.is() )
+ {
+ m_xDropTargetDragContext.clear();
+
+ try
+ {
+ context->rejectDrag();
+ }
+
+ catch( RuntimeException exc )
+ {
+ }
+ }
+ }
+
+ return nRet;
+}
+
+//==================================================================================================
+// DNDListenerContainer::fireDragGestureEvent
+//==================================================================================================
+
+sal_uInt32 DNDListenerContainer::fireDragGestureEvent( sal_Int8 dragAction, sal_Int32 dragOriginX,
+ sal_Int32 dragOriginY, const Reference< XDragSource >& dragSource, const Any& triggerEvent )
+{
+ sal_uInt32 nRet = 0;
+
+ // fire DropTargetDropEvent on all XDropTargetListeners
+ OInterfaceContainerHelper *pContainer = rBHelper.getContainer( getCppuType( ( Reference < XDragGestureListener > * ) 0) );
+
+ if( pContainer )
+ {
+ OInterfaceIteratorHelper aIterator( *pContainer );
+
+ // do not construct the event before you are sure at least one listener is registered
+ DragGestureEvent aEvent( static_cast < XDragGestureRecognizer * > (this), dragAction,
+ dragOriginX, dragOriginY, dragSource, triggerEvent );
+
+ while( aIterator.hasMoreElements() )
+ {
+ // FIXME: this can be simplified as soon as the Iterator has a remove method
+ Reference< XInterface > xElement( aIterator.next() );
+
+ try
+ {
+ // this may result in a runtime exception
+ Reference < XDragGestureListener > xListener( xElement, UNO_QUERY );
+
+ if( xListener.is() )
+ {
+ xListener->dragGestureRecognized( aEvent );
+ nRet++;
+ }
+ }
+
+ catch( RuntimeException exc )
+ {
+ pContainer->removeInterface( xElement );
+ }
+ }
+ }
+
+ return nRet;
+}
+
+//==================================================================================================
+// DNDListenerContainer::acceptDrag
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::acceptDrag( sal_Int8 dragOperation ) throw (RuntimeException)
+{
+ if( m_xDropTargetDragContext.is() )
+ {
+ m_xDropTargetDragContext->acceptDrag( dragOperation );
+ m_xDropTargetDragContext.clear();
+ }
+}
+
+//==================================================================================================
+// DNDListenerContainer::rejectDrag
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::rejectDrag( ) throw (RuntimeException)
+{
+ // nothing to do here
+}
+
+//==================================================================================================
+// DNDListenerContainer::acceptDrop
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::acceptDrop( sal_Int8 dropOperation ) throw (RuntimeException)
+{
+ if( m_xDropTargetDropContext.is() )
+ m_xDropTargetDropContext->acceptDrop( dropOperation );
+}
+
+//==================================================================================================
+// DNDListenerContainer::rejectDrop
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::rejectDrop( ) throw (RuntimeException)
+{
+ // nothing to do here
+}
+
+//==================================================================================================
+// DNDListenerContainer::dropComplete
+//==================================================================================================
+
+void SAL_CALL DNDListenerContainer::dropComplete( sal_Bool success ) throw (RuntimeException)
+{
+ if( m_xDropTargetDropContext.is() )
+ {
+ m_xDropTargetDropContext->dropComplete( success );
+ m_xDropTargetDropContext.clear();
+ }
+}
diff --git a/vcl/source/window/dockingarea.cxx b/vcl/source/window/dockingarea.cxx
new file mode 100644
index 000000000000..9ea407e52ee3
--- /dev/null
+++ b/vcl/source/window/dockingarea.cxx
@@ -0,0 +1,246 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <tools/debug.hxx>
+#include <vcl/dockingarea.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/svdata.hxx>
+
+#include <map>
+
+// =======================================================================
+
+class DockingAreaWindow::ImplData
+{
+public:
+ ImplData();
+ ~ImplData();
+
+ WindowAlign meAlign;
+};
+
+DockingAreaWindow::ImplData::ImplData()
+{
+ meAlign = WINDOWALIGN_TOP;
+}
+
+DockingAreaWindow::ImplData::~ImplData()
+{
+}
+
+// =======================================================================
+
+static void ImplInitBackground( DockingAreaWindow* pThis )
+{
+ if( !pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
+ {
+ Wallpaper aWallpaper;
+ aWallpaper.SetStyle( WALLPAPER_APPLICATIONGRADIENT );
+ pThis->SetBackground( aWallpaper );
+ }
+ else
+ pThis->SetBackground( Wallpaper( pThis->GetSettings().GetStyleSettings().GetFaceColor() ) );
+}
+
+DockingAreaWindow::DockingAreaWindow( Window* pParent ) :
+ Window( WINDOW_DOCKINGAREA )
+{
+ ImplInit( pParent, WB_CLIPCHILDREN|WB_3DLOOK, NULL );
+
+ mpImplData = new ImplData;
+ ImplInitBackground( this );
+}
+
+DockingAreaWindow::~DockingAreaWindow()
+{
+ delete mpImplData;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingAreaWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitBackground( this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplInvalidateMenubar( DockingAreaWindow* pThis )
+{
+ // due to a possible comon gradient covering menubar and top dockingarea
+ // the menubar must be repainted if the top dockingarea changes size or visibility
+ if( ImplGetSVData()->maNWFData.mbMenuBarDockingAreaCommonBG &&
+ (pThis->GetAlign() == WINDOWALIGN_TOP)
+ && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL )
+ && pThis->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
+ {
+ SystemWindow *pSysWin = pThis->GetSystemWindow();
+ if( pSysWin && pSysWin->GetMenuBar() )
+ {
+ Window *pMenubarWin = pSysWin->GetMenuBar()->GetWindow();
+ if( pMenubarWin )
+ pMenubarWin->Invalidate();
+ }
+ }
+}
+
+void DockingAreaWindow::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_VISIBLE )
+ ImplInvalidateMenubar( this );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingAreaWindow::IsHorizontal() const
+{
+ return ( mpImplData->meAlign == WINDOWALIGN_TOP || mpImplData->meAlign == WINDOWALIGN_BOTTOM );
+}
+
+void DockingAreaWindow::SetAlign( WindowAlign eNewAlign )
+{
+ if( eNewAlign != mpImplData->meAlign )
+ {
+ mpImplData->meAlign = eNewAlign;
+ Invalidate();
+ }
+}
+
+WindowAlign DockingAreaWindow::GetAlign() const
+{
+ return mpImplData->meAlign;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingAreaWindow::Paint( const Rectangle& )
+{
+ EnableNativeWidget( TRUE ); // only required because the toolkit curently switches this flag off
+ if( IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
+ {
+ ToolbarValue aControlValue;
+
+ if( GetAlign() == WINDOWALIGN_TOP && ImplGetSVData()->maNWFData.mbMenuBarDockingAreaCommonBG )
+ {
+ // give NWF a hint that this dockingarea is adjacent to the menubar
+ // useful for special gradient effects that should cover both windows
+ aControlValue.mbIsTopDockingArea = TRUE;
+ }
+ ControlState nState = CTRL_STATE_ENABLED;
+
+ if( !ImplGetSVData()->maNWFData.mbDockingAreaSeparateTB )
+ {
+ // draw a single toolbar background covering the whole docking area
+ Point tmp;
+ Rectangle aCtrlRegion( tmp, GetOutputSizePixel() );
+
+ DrawNativeControl( CTRL_TOOLBAR, IsHorizontal() ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT,
+ aCtrlRegion, nState, aControlValue, rtl::OUString() );
+
+ // each toolbar gets a thin border to better recognize its borders on the homogeneous docking area
+ USHORT nChildren = GetChildCount();
+ for( USHORT n = 0; n < nChildren; n++ )
+ {
+ Window* pChild = GetChild( n );
+ if ( pChild->IsVisible() )
+ {
+ Point aPos = pChild->GetPosPixel();
+ Size aSize = pChild->GetSizePixel();
+ Rectangle aRect( aPos, aSize );
+
+ SetLineColor( GetSettings().GetStyleSettings().GetLightColor() );
+ DrawLine( aRect.TopLeft(), aRect.TopRight() );
+ DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
+
+ SetLineColor( GetSettings().GetStyleSettings().GetSeparatorColor() );
+ DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
+ DrawLine( aRect.TopRight(), aRect.BottomRight() );
+ }
+ }
+ }
+ else
+ {
+ // create map to find toolbar lines
+ Size aOutSz = GetOutputSizePixel();
+ std::map< int, int > ranges;
+ USHORT nChildren = GetChildCount();
+ for( USHORT n = 0; n < nChildren; n++ )
+ {
+ Window* pChild = GetChild( n );
+ Point aPos = pChild->GetPosPixel();
+ Size aSize = pChild->GetSizePixel();
+ if( IsHorizontal() )
+ ranges[ aPos.Y() ] = aSize.Height();
+ else
+ ranges[ aPos.X() ] = aSize.Width();
+ }
+
+
+ // draw multiple toolbar backgrounds, i.e., one for each toolbar line
+ for( std::map<int,int>::const_iterator it = ranges.begin(); it != ranges.end(); ++it )
+ {
+ Rectangle aTBRect;
+ if( IsHorizontal() )
+ {
+ aTBRect.Left() = 0;
+ aTBRect.Right() = aOutSz.Width() - 1;
+ aTBRect.Top() = it->first;
+ aTBRect.Bottom() = it->first + it->second - 1;
+ }
+ else
+ {
+ aTBRect.Left() = it->first;
+ aTBRect.Right() = it->first + it->second - 1;
+ aTBRect.Top() = 0;
+ aTBRect.Bottom() = aOutSz.Height() - 1;
+ }
+ DrawNativeControl( CTRL_TOOLBAR, IsHorizontal() ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT,
+ aTBRect, nState, aControlValue, rtl::OUString() );
+ }
+ }
+ }
+}
+
+void DockingAreaWindow::Resize()
+{
+ ImplInvalidateMenubar( this );
+ if( IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
diff --git a/vcl/source/window/dockmgr.cxx b/vcl/source/window/dockmgr.cxx
new file mode 100644
index 000000000000..e67c2d9ecfd5
--- /dev/null
+++ b/vcl/source/window/dockmgr.cxx
@@ -0,0 +1,1689 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <tools/time.hxx>
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/event.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/dockwin.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/lineinfo.hxx>
+#include <vcl/window.h>
+#include <vcl/unowrap.hxx>
+#include <vcl/salframe.hxx>
+
+
+// =======================================================================
+
+#define DOCKWIN_FLOATSTYLES (WB_SIZEABLE | WB_MOVEABLE | WB_CLOSEABLE | WB_STANDALONE | WB_PINABLE | WB_ROLLABLE )
+
+// =======================================================================
+
+
+// =======================================================================
+
+class ImplDockFloatWin2 : public FloatingWindow
+{
+private:
+ ImplDockingWindowWrapper* mpDockWin;
+ ULONG mnLastTicks;
+ Timer maDockTimer;
+ Timer maEndDockTimer;
+ Point maDockPos;
+ Rectangle maDockRect;
+ BOOL mbInMove;
+ ULONG mnLastUserEvent;
+
+ DECL_LINK( DockingHdl, ImplDockFloatWin2* );
+ DECL_LINK( DockTimerHdl, ImplDockFloatWin2* );
+ DECL_LINK( EndDockTimerHdl, ImplDockFloatWin2* );
+public:
+ ImplDockFloatWin2( Window* pParent, WinBits nWinBits,
+ ImplDockingWindowWrapper* pDockingWin );
+ ~ImplDockFloatWin2();
+
+ virtual void Move();
+ virtual void Resize();
+ virtual void TitleButtonClick( USHORT nButton );
+ virtual void Pin();
+ virtual void Roll();
+ virtual void PopupModeEnd();
+ virtual void Resizing( Size& rSize );
+ virtual BOOL Close();
+ using Window::SetPosSizePixel;
+ virtual void SetPosSizePixel( long nX, long nY,
+ long nWidth, long nHeight,
+ USHORT nFlags = WINDOW_POSSIZE_ALL );
+
+ ULONG GetLastTicks() const { return mnLastTicks; }
+};
+
+// =======================================================================
+
+ImplDockFloatWin2::ImplDockFloatWin2( Window* pParent, WinBits nWinBits,
+ ImplDockingWindowWrapper* pDockingWin ) :
+ FloatingWindow( pParent, nWinBits ),
+ mpDockWin( pDockingWin ),
+ mnLastTicks( Time::GetSystemTicks() ),
+ mbInMove( FALSE ),
+ mnLastUserEvent( 0 )
+{
+ // Daten vom DockingWindow uebernehmen
+ if ( pDockingWin )
+ {
+ SetSettings( pDockingWin->GetWindow()->GetSettings() );
+ Enable( pDockingWin->GetWindow()->IsEnabled(), FALSE );
+ EnableInput( pDockingWin->GetWindow()->IsInputEnabled(), FALSE );
+ AlwaysEnableInput( pDockingWin->GetWindow()->IsAlwaysEnableInput(), FALSE );
+ EnableAlwaysOnTop( pDockingWin->GetWindow()->IsAlwaysOnTopEnabled() );
+ SetActivateMode( pDockingWin->GetWindow()->GetActivateMode() );
+ }
+
+ SetBackground( GetSettings().GetStyleSettings().GetFaceColor() );
+
+ maDockTimer.SetTimeoutHdl( LINK( this, ImplDockFloatWin2, DockTimerHdl ) );
+ maDockTimer.SetTimeout( 50 );
+ maEndDockTimer.SetTimeoutHdl( LINK( this, ImplDockFloatWin2, EndDockTimerHdl ) );
+ maEndDockTimer.SetTimeout( 50 );
+}
+
+// -----------------------------------------------------------------------
+
+ImplDockFloatWin2::~ImplDockFloatWin2()
+{
+ if( mnLastUserEvent )
+ Application::RemoveUserEvent( mnLastUserEvent );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplDockFloatWin2, DockTimerHdl, ImplDockFloatWin2*, EMPTYARG )
+{
+ DBG_ASSERT( mpDockWin->IsFloatingMode(), "docktimer called but not floating" );
+
+ maDockTimer.Stop();
+ PointerState aState = GetPointerState();
+
+ if( aState.mnState & KEY_MOD1 )
+ {
+ // i43499 CTRL disables docking now
+ mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
+ if( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) )
+ maDockTimer.Start();
+ }
+ else if( ! ( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) ) )
+ {
+ mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
+ mpDockWin->EndDocking( maDockRect, FALSE );
+ }
+ else
+ {
+ mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect, SHOWTRACK_BIG | SHOWTRACK_WINDOW );
+ maDockTimer.Start();
+ }
+
+ return 0;
+}
+
+IMPL_LINK( ImplDockFloatWin2, EndDockTimerHdl, ImplDockFloatWin2*, EMPTYARG )
+{
+ DBG_ASSERT( mpDockWin->IsFloatingMode(), "enddocktimer called but not floating" );
+
+ maEndDockTimer.Stop();
+ PointerState aState = GetPointerState();
+ if( ! ( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) ) )
+ {
+ mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
+ mpDockWin->EndDocking( maDockRect, TRUE );
+ }
+ else
+ {
+ maEndDockTimer.Start();
+ }
+
+ return 0;
+}
+
+
+IMPL_LINK( ImplDockFloatWin2, DockingHdl, ImplDockFloatWin2*, EMPTYARG )
+{
+ // called during move of a floating window
+ mnLastUserEvent = 0;
+
+ Window *pDockingArea = mpDockWin->GetWindow()->GetParent();
+ PointerState aState = pDockingArea->GetPointerState();
+
+ BOOL bRealMove = TRUE;
+ if( GetStyle() & WB_OWNERDRAWDECORATION )
+ {
+ // for windows with ownerdraw decoration
+ // we allow docking only when the window was moved
+ // by dragging its caption
+ // and ignore move request due to resizing
+ Window *pBorder = GetWindow( WINDOW_BORDER );
+ if( pBorder != this )
+ {
+ Point aPt;
+ Rectangle aBorderRect( aPt, pBorder->GetSizePixel() );
+ sal_Int32 nLeft, nTop, nRight, nBottom;
+ GetBorder( nLeft, nTop, nRight, nBottom );
+ // limit borderrect to the caption part only and without the resizing borders
+ aBorderRect.nBottom = aBorderRect.nTop + nTop;
+ aBorderRect.nLeft += nLeft;
+ aBorderRect.nRight -= nRight;
+
+ PointerState aBorderState = pBorder->GetPointerState();
+ if( aBorderRect.IsInside( aBorderState.maPos ) )
+ bRealMove = TRUE;
+ else
+ bRealMove = FALSE;
+ }
+ }
+
+ if( mpDockWin->IsDockable() &&
+ mpDockWin->GetWindow()->IsVisible() &&
+ (Time::GetSystemTicks() - mnLastTicks > 500) &&
+ ( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) ) &&
+ !(aState.mnState & KEY_MOD1) && // i43499 CTRL disables docking now
+ bRealMove )
+ {
+ maDockPos = Point( pDockingArea->OutputToScreenPixel( pDockingArea->AbsoluteScreenToOutputPixel( OutputToAbsoluteScreenPixel( Point() ) ) ) );
+ maDockRect = Rectangle( maDockPos, mpDockWin->GetSizePixel() );
+
+ // mouse pos in screen pixels
+ Point aMousePos = pDockingArea->OutputToScreenPixel( aState.maPos );
+
+ if( ! mpDockWin->IsDocking() )
+ mpDockWin->StartDocking( aMousePos, maDockRect );
+
+ BOOL bFloatMode = mpDockWin->Docking( aMousePos, maDockRect );
+
+ if( ! bFloatMode )
+ {
+ // indicates that the window could be docked at maDockRect
+ maDockRect.SetPos( mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->ScreenToOutputPixel(
+ maDockRect.TopLeft() ) );
+ mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect, SHOWTRACK_BIG | SHOWTRACK_WINDOW );
+ maEndDockTimer.Stop();
+ DockTimerHdl( this );
+ }
+ else
+ {
+ mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
+ maDockTimer.Stop();
+ EndDockTimerHdl( this );
+ }
+ }
+ mbInMove = FALSE;
+ return 0;
+}
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin2::Move()
+{
+ if( mbInMove )
+ return;
+
+ mbInMove = TRUE;
+ FloatingWindow::Move();
+ mpDockWin->GetWindow()->Move();
+
+ /*
+ * note: the window should only dock if KEY_MOD1 is pressed
+ * and the user releases all mouse buttons. The real problem here
+ * is that we don't get mouse events (at least not on X)
+ * if the mouse is on the decoration. So we have to start an
+ * awkward timer based process that polls the modifier/buttons
+ * to see whether they are in the right condition shortly after the
+ * last Move message.
+ */
+ if( ! mnLastUserEvent )
+ mnLastUserEvent = Application::PostUserEvent( LINK( this, ImplDockFloatWin2, DockingHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin2::Resize()
+{
+ // forwarding of resize only required if we have no borderwindow ( GetWindow() then returns 'this' )
+ if( GetWindow( WINDOW_BORDER ) == this )
+ {
+ FloatingWindow::Resize();
+ Size aSize( GetSizePixel() );
+ mpDockWin->GetWindow()->ImplPosSizeWindow( 0, 0, aSize.Width(), aSize.Height(), WINDOW_POSSIZE_POSSIZE ); // is this needed ???
+ }
+}
+
+void ImplDockFloatWin2::SetPosSizePixel( long nX, long nY,
+ long nWidth, long nHeight,
+ USHORT nFlags )
+{
+ FloatingWindow::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+
+void ImplDockFloatWin2::TitleButtonClick( USHORT nButton )
+{
+ FloatingWindow::TitleButtonClick( nButton );
+ mpDockWin->TitleButtonClick( nButton );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin2::Pin()
+{
+ FloatingWindow::Pin();
+ mpDockWin->Pin();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin2::Roll()
+{
+ FloatingWindow::Roll();
+ mpDockWin->Roll();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin2::PopupModeEnd()
+{
+ FloatingWindow::PopupModeEnd();
+ mpDockWin->PopupModeEnd();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin2::Resizing( Size& rSize )
+{
+ FloatingWindow::Resizing( rSize );
+ mpDockWin->Resizing( rSize );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplDockFloatWin2::Close()
+{
+ return mpDockWin->Close();
+}
+
+// =======================================================================
+
+DockingManager::DockingManager()
+{
+}
+
+DockingManager::~DockingManager()
+{
+ ::std::vector< ImplDockingWindowWrapper* >::iterator p;
+ p = mDockingWindows.begin();
+ for(; p != mDockingWindows.end(); ++p )
+ {
+ delete (*p);
+ }
+ mDockingWindows.clear();
+}
+
+ImplDockingWindowWrapper* DockingManager::GetDockingWindowWrapper( const Window *pWindow )
+{
+ ::std::vector< ImplDockingWindowWrapper* >::iterator p;
+ p = mDockingWindows.begin();
+ while( p != mDockingWindows.end() )
+ {
+ if( (*p)->mpDockingWindow == pWindow )
+ return (*p);
+ else
+ p++;
+ }
+ return NULL;
+}
+
+BOOL DockingManager::IsDockable( const Window *pWindow )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+
+ /*
+ if( pWindow->HasDockingHandler() )
+ return TRUE;
+ */
+ return (pWrapper != NULL);
+}
+
+BOOL DockingManager::IsFloating( const Window *pWindow )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper )
+ return pWrapper->IsFloatingMode();
+ else
+ return FALSE;
+}
+
+BOOL DockingManager::IsLocked( const Window *pWindow )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper && pWrapper->IsLocked() )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void DockingManager::Lock( const Window *pWindow )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper )
+ pWrapper->Lock();
+}
+
+void DockingManager::Unlock( const Window *pWindow )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper )
+ pWrapper->Unlock();
+}
+
+void DockingManager::SetFloatingMode( const Window *pWindow, BOOL bFloating )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper )
+ pWrapper->SetFloatingMode( bFloating );
+}
+
+void DockingManager::StartPopupMode( ToolBox *pParentToolBox, const Window *pWindow, ULONG nFlags )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper )
+ pWrapper->StartPopupMode( pParentToolBox, nFlags );
+}
+
+void DockingManager::StartPopupMode( ToolBox *pParentToolBox, const Window *pWindow )
+{
+ StartPopupMode( pParentToolBox, pWindow, FLOATWIN_POPUPMODE_ALLOWTEAROFF |
+ FLOATWIN_POPUPMODE_NOFOCUSCLOSE |
+ FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
+ FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE );
+}
+
+BOOL DockingManager::IsInPopupMode( const Window *pWindow )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper && pWrapper->IsInPopupMode() )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingManager::EndPopupMode( const Window *pWin )
+{
+ ImplDockingWindowWrapper *pWrapper = GetDockingWindowWrapper( pWin );
+ if( pWrapper && pWrapper->GetFloatingWindow() && pWrapper->GetFloatingWindow()->IsInPopupMode() )
+ pWrapper->GetFloatingWindow()->EndPopupMode();
+}
+
+// -----------------------------------------------------------------------
+
+void DockingManager::AddWindow( const Window *pWindow )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper )
+ return;
+ else
+ pWrapper = new ImplDockingWindowWrapper( pWindow );
+
+ mDockingWindows.push_back( pWrapper );
+}
+
+void DockingManager::RemoveWindow( const Window *pWindow )
+{
+ ::std::vector< ImplDockingWindowWrapper* >::iterator p;
+ p = mDockingWindows.begin();
+ while( p != mDockingWindows.end() )
+ {
+ if( (*p)->mpDockingWindow == pWindow )
+ {
+ delete (*p);
+ mDockingWindows.erase( p );
+ break;
+ }
+ else
+ p++;
+ }
+}
+
+void DockingManager::SetPosSizePixel( Window *pWindow, long nX, long nY,
+ long nWidth, long nHeight,
+ USHORT nFlags )
+{
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper )
+ pWrapper->SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+}
+
+Rectangle DockingManager::GetPosSizePixel( const Window *pWindow )
+{
+ Rectangle aRect;
+ ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
+ if( pWrapper )
+ aRect = Rectangle( pWrapper->GetPosPixel(), pWrapper->GetSizePixel() );
+
+ return aRect;
+}
+
+// =======================================================================
+// special floating window for popup mode
+// main purpose: provides tear-off area for undocking
+// =======================================================================
+
+// if TEAROFF_DASHED defined a single dashed line is used
+// otherwise multiple smaller lines will be painted
+//#define TEAROFF_DASHED
+
+// size of the drag area
+#ifdef TEAROFF_DASHED
+#define POPUP_DRAGBORDER 2
+#define POPUP_DRAGGRIP 5
+#else
+#define POPUP_DRAGBORDER 3
+#define POPUP_DRAGGRIP 5
+#endif
+#define POPUP_DRAGHEIGHT (POPUP_DRAGGRIP+POPUP_DRAGBORDER+POPUP_DRAGBORDER)
+#define POPUP_DRAGWIDTH 20
+
+class ImplPopupFloatWin : public FloatingWindow
+{
+private:
+ ImplDockingWindowWrapper* mpDockingWin;
+ BOOL mbHighlight;
+ BOOL mbMoving;
+ bool mbTrackingEnabled;
+ Point maDelta;
+ Point maTearOffPosition;
+ bool mbGripAtBottom;
+ bool mbHasGrip;
+ void ImplSetBorder();
+
+public:
+ ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* pDockingWin, bool bHasGrip );
+ ~ImplPopupFloatWin();
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
+ virtual void Paint( const Rectangle& rRect );
+ virtual void MouseMove( const MouseEvent& rMEvt );
+ virtual void MouseButtonDown( const MouseEvent& rMEvt );
+ virtual void MouseButtonUp( const MouseEvent& rMEvt );
+ virtual void Tracking( const TrackingEvent& rTEvt );
+ virtual void Resize();
+ virtual Window* GetPreferredKeyInputWindow();
+
+ Rectangle GetDragRect() const;
+ Point GetToolboxPosition() const;
+ Point GetTearOffPosition() const;
+ void DrawGrip();
+ void DrawBorder();
+
+ bool hasGrip() const { return mbHasGrip; }
+};
+
+ImplPopupFloatWin::ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* pDockingWin, bool bHasGrip ) :
+ FloatingWindow( pParent, WB_NOBORDER | WB_SYSTEMWINDOW | WB_NOSHADOW)
+{
+ mpWindowImpl->mbToolbarFloatingWindow = TRUE; // indicate window type, required for accessibility
+ // which should not see this window as a toplevel window
+ mpDockingWin = pDockingWin;
+ mbHighlight = FALSE;
+ mbMoving = FALSE;
+ mbTrackingEnabled = FALSE;
+ mbGripAtBottom = TRUE;
+ mbHasGrip = bHasGrip;
+
+ ImplSetBorder();
+}
+
+ImplPopupFloatWin::~ImplPopupFloatWin()
+{
+ mpDockingWin = NULL;
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ImplPopupFloatWin::CreateAccessible()
+{
+ // switch off direct accessibilty support for this window
+
+ // this is to avoid appearance of this window as standalone window in the accessibility hierarchy
+ // as this window is only used as a helper for subtoolbars that are not teared-off, the parent toolbar
+ // has to provide accessibility support (as implemented in the toolkit)
+ // so the contained toolbar should appear as child of the correponsing toolbar item of the parent toolbar
+ return ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >();
+}
+
+Window* ImplPopupFloatWin::GetPreferredKeyInputWindow()
+{
+ if( mpWindowImpl->mpClientWindow )
+ return mpWindowImpl->mpClientWindow;
+ else
+ return FloatingWindow::GetPreferredKeyInputWindow();
+}
+
+
+void ImplPopupFloatWin::ImplSetBorder()
+{
+ // although we have no border in the sense of a borderwindow
+ // we're using a special border for the grip
+ // by setting those members the method SetOutputSizePixel() can
+ // be used to set the proper window size
+ mpWindowImpl->mnTopBorder = 1;
+ if( hasGrip() )
+ mpWindowImpl->mnTopBorder += POPUP_DRAGHEIGHT+2;
+ mpWindowImpl->mnBottomBorder = 1;
+ mpWindowImpl->mnLeftBorder = 1;
+ mpWindowImpl->mnRightBorder = 1;
+}
+
+void ImplPopupFloatWin::Resize()
+{
+ // the borderview overwrites the border during resize so restore it
+ ImplSetBorder();
+}
+
+Rectangle ImplPopupFloatWin::GetDragRect() const
+{
+ Rectangle aRect;
+ if( hasGrip() )
+ {
+ aRect = Rectangle( 1,1, GetOutputSizePixel().Width()-1, 2+POPUP_DRAGHEIGHT );
+ if( mbGripAtBottom )
+ {
+ int height = GetOutputSizePixel().Height();
+ aRect.Top() = height - 3 - POPUP_DRAGHEIGHT;
+ aRect.Bottom() = aRect.Top() + 1 + POPUP_DRAGHEIGHT;
+ }
+ }
+ return aRect;
+}
+
+Point ImplPopupFloatWin::GetToolboxPosition() const
+{
+ // return inner position where a toolbox could be placed
+ Point aPt( 1, 1 + ((mbGripAtBottom || !hasGrip()) ? 0 : GetDragRect().getHeight()) ); // grip + border
+
+ return aPt;
+}
+
+Point ImplPopupFloatWin::GetTearOffPosition() const
+{
+ Point aPt( maTearOffPosition );
+ //aPt += GetToolboxPosition(); // remove 'decoration'
+ return aPt;
+}
+
+void ImplPopupFloatWin::DrawBorder()
+{
+ SetFillColor();
+ Point aPt;
+ Rectangle aRect( aPt, GetOutputSizePixel() );
+
+ Region oldClipRgn( GetClipRegion( ) );
+ Region aClipRgn( aRect );
+ Rectangle aItemClipRect( ImplGetItemEdgeClipRect() );
+ if( !aItemClipRect.IsEmpty() )
+ {
+ aItemClipRect.SetPos( AbsoluteScreenToOutputPixel( aItemClipRect.TopLeft() ) );
+
+ // draw the excluded border part with the background color of a toolbox
+ SetClipRegion( Region( aItemClipRect ) );
+ SetLineColor( GetSettings().GetStyleSettings().GetFaceColor() );
+ DrawRect( aRect );
+
+ aClipRgn.Exclude( aItemClipRect );
+ SetClipRegion( aClipRgn );
+ }
+ SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ DrawRect( aRect );
+ SetClipRegion( oldClipRgn );
+}
+
+void ImplPopupFloatWin::DrawGrip()
+{
+ BOOL bLinecolor = IsLineColor();
+ Color aLinecolor = GetLineColor();
+ BOOL bFillcolor = IsFillColor();
+ Color aFillcolor = GetFillColor();
+
+ // draw background
+ Rectangle aRect( GetDragRect() );
+ aRect.nTop += POPUP_DRAGBORDER;
+ aRect.nBottom -= POPUP_DRAGBORDER;
+ aRect.nLeft+=3;
+ aRect.nRight-=3;
+
+ if( mbHighlight )
+ {
+ Erase( aRect );
+ DrawSelectionBackground( aRect, 2, FALSE, TRUE, FALSE );
+ }
+ else
+ {
+ SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
+ SetLineColor();
+ DrawRect( aRect );
+ }
+
+ if( !ToolBox::AlwaysLocked() ) // no grip if toolboxes are locked
+ {
+#ifdef TEAROFF_DASHED
+ // draw single dashed line
+ LineInfo aLineInfo( LINE_DASH );
+ aLineInfo.SetDistance( 4 );
+ aLineInfo.SetDashLen( 12 );
+ aLineInfo.SetDashCount( 1 );
+
+ aRect.nLeft+=2; aRect.nRight-=2;
+
+ aRect.nTop+=2;
+ aRect.nBottom = aRect.nTop;
+ SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
+ DrawLine( aRect.TopLeft(), aRect.TopRight(), aLineInfo );
+
+ if( !mbHighlight )
+ {
+ aRect.nTop++; aRect.nBottom++;
+ SetLineColor( GetSettings().GetStyleSettings().GetLightColor() );
+ DrawLine( aRect.TopLeft(), aRect.TopRight(), aLineInfo );
+ }
+
+#else
+ // draw several grip lines
+ SetFillColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ aRect.nTop++;
+ aRect.nBottom = aRect.nTop;
+
+ int width = POPUP_DRAGWIDTH;
+ while( width >= aRect.getWidth() )
+ width -= 4;
+ if( width <= 0 )
+ width = aRect.getWidth();
+ //aRect.nLeft = aRect.nLeft + (aRect.getWidth() - width) / 2;
+ aRect.nLeft = (aRect.nLeft + aRect.nRight - width) / 2;
+ aRect.nRight = aRect.nLeft + width;
+
+ int i=0;
+ while( i< POPUP_DRAGGRIP )
+ {
+ DrawRect( aRect );
+ aRect.nTop+=2;
+ aRect.nBottom+=2;
+ i+=2;
+ }
+#endif
+ }
+
+ if( bLinecolor )
+ SetLineColor( aLinecolor );
+ else
+ SetLineColor();
+ if( bFillcolor )
+ SetFillColor( aFillcolor );
+ else
+ SetFillColor();
+}
+
+void ImplPopupFloatWin::Paint( const Rectangle& )
+{
+ Point aPt;
+ Rectangle aRect( aPt, GetOutputSizePixel() );
+ DrawWallpaper( aRect, Wallpaper( GetSettings().GetStyleSettings().GetFaceGradientColor() ) );
+ DrawBorder();
+ if( hasGrip() )
+ DrawGrip();
+}
+
+void ImplPopupFloatWin::MouseMove( const MouseEvent& rMEvt )
+{
+ Point aMousePos = rMEvt.GetPosPixel();
+
+ if( !ToolBox::AlwaysLocked() ) // no tear off if locking is enabled
+ {
+ if( mbTrackingEnabled && rMEvt.IsLeft() && GetDragRect().IsInside( aMousePos ) )
+ {
+ // start window move
+ mbMoving = TRUE;
+ StartTracking( STARTTRACK_NOKEYCANCEL );
+ return;
+ }
+ if( !mbHighlight && GetDragRect().IsInside( aMousePos ) )
+ {
+ mbHighlight = TRUE;
+ DrawGrip();
+ }
+ if( mbHighlight && ( rMEvt.IsLeaveWindow() || !GetDragRect().IsInside( aMousePos ) ) )
+ {
+ mbHighlight = FALSE;
+ DrawGrip();
+ }
+ }
+}
+
+void ImplPopupFloatWin::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ mbTrackingEnabled = false;
+ FloatingWindow::MouseButtonUp( rMEvt );
+}
+
+void ImplPopupFloatWin::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ Point aMousePos = rMEvt.GetPosPixel();
+ if( GetDragRect().IsInside( aMousePos ) )
+ {
+ // get mouse pos at a static window to have a fixed reference point
+ PointerState aState = GetParent()->GetPointerState();
+ if (ImplHasMirroredGraphics() && IsRTLEnabled())
+ ImplMirrorFramePos(aState.maPos);
+ maTearOffPosition = GetWindow( WINDOW_BORDER )->GetPosPixel();
+ maDelta = aState.maPos - maTearOffPosition;
+ mbTrackingEnabled = true;
+ }
+ else
+ {
+ mbTrackingEnabled = false;
+ }
+}
+
+void ImplPopupFloatWin::Tracking( const TrackingEvent& rTEvt )
+{
+ if( mbMoving )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbMoving = FALSE;
+ EndPopupMode( FLOATWIN_POPUPMODEEND_TEAROFF );
+ }
+ else if ( !rTEvt.GetMouseEvent().IsSynthetic() )
+ {
+ // move the window according to mouse pos
+ PointerState aState = GetParent()->GetPointerState();
+ if (ImplHasMirroredGraphics() && IsRTLEnabled())
+ ImplMirrorFramePos(aState.maPos);
+ maTearOffPosition = aState.maPos - maDelta;
+ GetWindow( WINDOW_BORDER )->SetPosPixel( maTearOffPosition );
+ }
+ }
+}
+
+
+// =======================================================================
+
+ImplDockingWindowWrapper::ImplDockingWindowWrapper( const Window *pWindow )
+{
+ ImplInitData();
+
+ mpDockingWindow = (Window*) pWindow;
+ mpParent = pWindow->GetParent();
+ mbDockable = TRUE;
+ mbLocked = FALSE;
+ mnFloatBits = WB_BORDER | WB_CLOSEABLE | WB_SIZEABLE | (pWindow->GetStyle() & DOCKWIN_FLOATSTYLES);
+ DockingWindow *pDockWin = dynamic_cast< DockingWindow* > ( mpDockingWindow );
+ if( pDockWin )
+ mnFloatBits = pDockWin->GetFloatStyle();
+
+ // must be enabled in Window::Notify to prevent permanent docking during mouse move
+ mbStartDockingEnabled = FALSE;
+}
+
+ImplDockingWindowWrapper::~ImplDockingWindowWrapper()
+{
+ if ( IsFloatingMode() )
+ {
+ GetWindow()->Show( FALSE, SHOW_NOFOCUSCHANGE );
+ SetFloatingMode( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplDockingWindowWrapper::ImplStartDocking( const Point& rPos )
+{
+ if ( !mbDockable )
+ return FALSE;
+
+ if( !mbStartDockingEnabled )
+ return FALSE;
+
+ maMouseOff = rPos;
+ maMouseStart = maMouseOff;
+ mbDocking = TRUE;
+ mbLastFloatMode = IsFloatingMode();
+ mbStartFloat = mbLastFloatMode;
+
+ // FloatingBorder berechnen
+ FloatingWindow* pWin;
+ if ( mpFloatWin )
+ pWin = mpFloatWin;
+ else
+ pWin = new ImplDockFloatWin2( mpParent, mnFloatBits, NULL );
+ pWin->GetBorder( mnDockLeft, mnDockTop, mnDockRight, mnDockBottom );
+ if ( !mpFloatWin )
+ delete pWin;
+
+ Point aPos = GetWindow()->ImplOutputToFrame( Point() );
+ Size aSize = GetWindow()->GetOutputSizePixel();
+ mnTrackX = aPos.X();
+ mnTrackY = aPos.Y();
+ mnTrackWidth = aSize.Width();
+ mnTrackHeight = aSize.Height();
+
+ if ( mbLastFloatMode )
+ {
+ maMouseOff.X() += mnDockLeft;
+ maMouseOff.Y() += mnDockTop;
+ mnTrackX -= mnDockLeft;
+ mnTrackY -= mnDockTop;
+ mnTrackWidth += mnDockLeft+mnDockRight;
+ mnTrackHeight += mnDockTop+mnDockBottom;
+ }
+
+ Window *pDockingArea = GetWindow()->GetParent();
+ Window::PointerState aState = pDockingArea->GetPointerState();
+
+ // mouse pos in screen pixels
+ Point aMousePos = pDockingArea->OutputToScreenPixel( aState.maPos );
+ Point aDockPos = Point( pDockingArea->AbsoluteScreenToOutputPixel( GetWindow()->OutputToAbsoluteScreenPixel( GetWindow()->GetPosPixel() ) ) );
+ Rectangle aDockRect( aDockPos, GetWindow()->GetSizePixel() );
+ StartDocking( aMousePos, aDockRect );
+
+ GetWindow()->ImplUpdateAll();
+ GetWindow()->ImplGetFrameWindow()->ImplUpdateAll();
+
+ GetWindow()->StartTracking( STARTTRACK_KEYMOD );
+ return TRUE;
+}
+
+// =======================================================================
+
+void ImplDockingWindowWrapper::ImplInitData()
+{
+ mpDockingWindow = NULL;
+
+ //GetWindow()->mpWindowImpl->mbDockWin = TRUE; // TODO: must be eliminated
+ mpFloatWin = NULL;
+ mbDockCanceled = FALSE;
+ mbFloatPrevented = FALSE;
+ mbDocking = FALSE;
+ mbPined = FALSE;
+ mbRollUp = FALSE;
+ mbDockBtn = FALSE;
+ mbHideBtn = FALSE;
+ maMaxOutSize = Size( SHRT_MAX, SHRT_MAX );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::Tracking( const TrackingEvent& rTEvt )
+{
+ // used during docking of a currently docked window
+ if ( mbDocking )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbDocking = FALSE;
+ GetWindow()->HideTracking();
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ mbDockCanceled = TRUE;
+ EndDocking( Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
+ mbDockCanceled = FALSE;
+ }
+ else
+ EndDocking( Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
+ }
+ // Docking only upon non-synthetic MouseEvents
+ else if ( !rTEvt.GetMouseEvent().IsSynthetic() || rTEvt.GetMouseEvent().IsModifierChanged() )
+ {
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+ Point aFrameMousePos = GetWindow()->ImplOutputToFrame( aMousePos );
+ Size aFrameSize = GetWindow()->ImplGetFrameWindow()->GetOutputSizePixel();
+ if ( aFrameMousePos.X() < 0 )
+ aFrameMousePos.X() = 0;
+ if ( aFrameMousePos.Y() < 0 )
+ aFrameMousePos.Y() = 0;
+ if ( aFrameMousePos.X() > aFrameSize.Width()-1 )
+ aFrameMousePos.X() = aFrameSize.Width()-1;
+ if ( aFrameMousePos.Y() > aFrameSize.Height()-1 )
+ aFrameMousePos.Y() = aFrameSize.Height()-1;
+ aMousePos = GetWindow()->ImplFrameToOutput( aFrameMousePos );
+ aMousePos.X() -= maMouseOff.X();
+ aMousePos.Y() -= maMouseOff.Y();
+ Point aPos = GetWindow()->ImplOutputToFrame( aMousePos );
+ Rectangle aTrackRect( aPos, Size( mnTrackWidth, mnTrackHeight ) );
+ Rectangle aCompRect = aTrackRect;
+ aPos.X() += maMouseOff.X();
+ aPos.Y() += maMouseOff.Y();
+
+ BOOL bFloatMode = Docking( aPos, aTrackRect );
+
+ mbFloatPrevented = FALSE;
+ if ( mbLastFloatMode != bFloatMode )
+ {
+ if ( bFloatMode )
+ {
+ aTrackRect.Left() -= mnDockLeft;
+ aTrackRect.Top() -= mnDockTop;
+ aTrackRect.Right() += mnDockRight;
+ aTrackRect.Bottom() += mnDockBottom;
+ }
+ else
+ {
+ if ( aCompRect == aTrackRect )
+ {
+ aTrackRect.Left() += mnDockLeft;
+ aTrackRect.Top() += mnDockTop;
+ aTrackRect.Right() -= mnDockRight;
+ aTrackRect.Bottom() -= mnDockBottom;
+ }
+ }
+ mbLastFloatMode = bFloatMode;
+ }
+
+ USHORT nTrackStyle;
+ if ( bFloatMode )
+ nTrackStyle = SHOWTRACK_OBJECT;
+ else
+ nTrackStyle = SHOWTRACK_BIG;
+ Rectangle aShowTrackRect = aTrackRect;
+ aShowTrackRect.SetPos( GetWindow()->ImplFrameToOutput( aShowTrackRect.TopLeft() ) );
+ //if( bFloatMode )
+ GetWindow()->ShowTracking( aShowTrackRect, nTrackStyle );
+ /*else
+ {
+ GetWindow()->HideTracking();
+ Point aPt( GetWindow()->GetParent()->ScreenToOutputPixel( aTrackRect.TopLeft() ) );
+ GetWindow()->SetPosPixel( aPt );
+ }*/
+
+ // Maus-Offset neu berechnen, da Rechteck veraendert werden
+ // konnte
+ maMouseOff.X() = aPos.X() - aTrackRect.Left();
+ maMouseOff.Y() = aPos.Y() - aTrackRect.Top();
+
+ mnTrackX = aTrackRect.Left();
+ mnTrackY = aTrackRect.Top();
+ mnTrackWidth = aTrackRect.GetWidth();
+ mnTrackHeight = aTrackRect.GetHeight();
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::StartDocking( const Point& rPoint, Rectangle& rRect )
+{
+ DockingData data( rPoint, rRect, IsFloatingMode() );
+
+ GetWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_STARTDOCKING, &data );
+ mbDocking = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplDockingWindowWrapper::Docking( const Point& rPoint, Rectangle& rRect )
+{
+ DockingData data( rPoint, rRect, IsFloatingMode() );
+
+ GetWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_DOCKING, &data );
+ rRect = data.maTrackRect;
+ return data.mbFloating;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::EndDocking( const Rectangle& rRect, BOOL bFloatMode )
+{
+ Rectangle aRect( rRect );
+
+ if ( !IsDockingCanceled() )
+ {
+ BOOL bShow = FALSE;
+ if ( bFloatMode != IsFloatingMode() )
+ {
+ GetWindow()->Show( FALSE, SHOW_NOFOCUSCHANGE );
+ SetFloatingMode( bFloatMode );
+ bShow = TRUE;
+ if ( bFloatMode )
+ {
+ // #i44800# always use outputsize - as in all other places
+ mpFloatWin->SetOutputSizePixel( aRect.GetSize() );
+ mpFloatWin->SetPosPixel( aRect.TopLeft() );
+ }
+ }
+ if ( !bFloatMode )
+ {
+ Point aPos = aRect.TopLeft();
+ aPos = GetWindow()->GetParent()->ScreenToOutputPixel( aPos );
+ GetWindow()->SetPosSizePixel( aPos, aRect.GetSize() );
+ }
+
+ if ( bShow )
+ GetWindow()->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
+ }
+
+ EndDockingData data( aRect, IsFloatingMode(), IsDockingCanceled() );
+ GetWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_ENDDOCKING, &data );
+
+ mbDocking = FALSE;
+
+ // must be enabled in Window::Notify to prevent permanent docking during mouse move
+ mbStartDockingEnabled = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplDockingWindowWrapper::PrepareToggleFloatingMode()
+{
+ BOOL bFloating = TRUE;
+ GetWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_PREPARETOGGLEFLOATING, &bFloating );
+ return bFloating;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplDockingWindowWrapper::Close()
+{
+ // TODO: send event
+/*
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ GetWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_CLOSE );
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ ImplRemoveDel( &aDelData );
+
+ if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() )
+ return FALSE;
+
+ GetWindow()->Show( FALSE, SHOW_NOFOCUSCHANGE );
+ */
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::ToggleFloatingMode()
+{
+ // notify dockingwindow/toolbox
+ // note: this must be done *before* notifying the
+ // listeners to have the toolbox in the proper state
+ if( GetWindow()->ImplIsDockingWindow() )
+ ((DockingWindow*) GetWindow())->ToggleFloatingMode();
+
+ // now notify listeners
+ GetWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_TOGGLEFLOATING );
+
+ // must be enabled in Window::Notify to prevent permanent docking during mouse move
+ mbStartDockingEnabled = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::TitleButtonClick( USHORT nType )
+{
+ if( nType == TITLE_BUTTON_MENU )
+ {
+ ToolBox *pToolBox = dynamic_cast< ToolBox* >( GetWindow() );
+ if( pToolBox )
+ {
+ pToolBox->ExecuteCustomMenu();
+ }
+ }
+ if( nType == TITLE_BUTTON_DOCKING )
+ {
+ SetFloatingMode( !IsFloatingMode() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::Pin()
+{
+ // TODO: send event
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::Roll()
+{
+ // TODO: send event
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::PopupModeEnd()
+{
+ // TODO: send event
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::Resizing( Size& rSize )
+{
+ // TODO: add virtual Resizing() to class Window, so we can get rid of class DockingWindow
+ DockingWindow *pDockingWindow = dynamic_cast< DockingWindow* >( GetWindow() );
+ if( pDockingWindow )
+ pDockingWindow->Resizing( rSize );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::ShowTitleButton( USHORT nButton, BOOL bVisible )
+{
+ if ( mpFloatWin )
+ mpFloatWin->ShowTitleButton( nButton, bVisible );
+ else
+ {
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ mbDockBtn = bVisible;
+ else // if ( nButton == TITLE_BUTTON_HIDE )
+ mbHideBtn = bVisible;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplDockingWindowWrapper::IsTitleButtonVisible( USHORT nButton ) const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->IsTitleButtonVisible( nButton );
+ else
+ {
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ return mbDockBtn;
+ else // if ( nButton == TITLE_BUTTON_HIDE )
+ return mbHideBtn;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::StartPopupMode( ToolBox *pParentToolBox, ULONG nFlags )
+{
+ // do nothing if window is floating
+ if( IsFloatingMode() )
+ return;
+
+ GetWindow()->Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // prepare reparenting
+ Window* pRealParent = GetWindow()->GetWindow( WINDOW_PARENT );
+ mpOldBorderWin = GetWindow()->GetWindow( WINDOW_BORDER );
+ if( mpOldBorderWin == GetWindow() )
+ mpOldBorderWin = NULL; // no border window found
+
+ // the new parent for popup mode
+ ImplPopupFloatWin* pWin = new ImplPopupFloatWin( mpParent, this, (nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) != 0 );
+
+ pWin->SetPopupModeEndHdl( LINK( this, ImplDockingWindowWrapper, PopupModeEnd ) );
+ pWin->SetText( GetWindow()->GetText() );
+
+ pWin->SetOutputSizePixel( GetWindow()->GetSizePixel() );
+
+ GetWindow()->mpWindowImpl->mpBorderWindow = NULL;
+ GetWindow()->mpWindowImpl->mnLeftBorder = 0;
+ GetWindow()->mpWindowImpl->mnTopBorder = 0;
+ GetWindow()->mpWindowImpl->mnRightBorder = 0;
+ GetWindow()->mpWindowImpl->mnBottomBorder = 0;
+
+ // position toolbox below dragrect
+ GetWindow()->SetPosPixel( pWin->GetToolboxPosition() );
+
+ // reparent borderwindow and window
+ if ( mpOldBorderWin )
+ mpOldBorderWin->SetParent( pWin );
+ GetWindow()->SetParent( pWin );
+
+ // correct border window pointers
+ GetWindow()->mpWindowImpl->mpBorderWindow = pWin;
+ pWin->mpWindowImpl->mpClientWindow = GetWindow();
+ GetWindow()->mpWindowImpl->mpRealParent = pRealParent;
+
+ // set mpFloatWin not until all window positioning is done !!!
+ // (SetPosPixel etc. check for valid mpFloatWin pointer)
+ mpFloatWin = pWin;
+
+ // if the subtoolbar was opened via keyboard make sure that key events
+ // will go into subtoolbar
+ if( pParentToolBox->IsKeyEvent() )
+ nFlags |= FLOATWIN_POPUPMODE_GRABFOCUS;
+
+ mpFloatWin->StartPopupMode( pParentToolBox, nFlags );
+ GetWindow()->Show();
+
+ if( pParentToolBox->IsKeyEvent() )
+ {
+ // send HOME key to subtoolbar in order to select first item
+ KeyEvent aEvent( 0, KeyCode( KEY_HOME ) );
+ mpFloatWin->GetPreferredKeyInputWindow()->KeyInput( aEvent );
+ }
+}
+
+IMPL_LINK( ImplDockingWindowWrapper, PopupModeEnd, void*, EMPTYARG )
+{
+ GetWindow()->Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // set parameter for handler before destroying floating window
+ ImplPopupFloatWin *pPopupFloatWin = (ImplPopupFloatWin*) mpFloatWin;
+ EndPopupModeData aData( pPopupFloatWin->GetTearOffPosition(), mpFloatWin->IsPopupModeTearOff() );
+
+ // before deleting change parent back, so we can delete the floating window alone
+ Window* pRealParent = GetWindow()->GetWindow( WINDOW_PARENT );
+ GetWindow()->mpWindowImpl->mpBorderWindow = NULL;
+ if ( mpOldBorderWin )
+ {
+ GetWindow()->SetParent( mpOldBorderWin );
+ ((ImplBorderWindow*)mpOldBorderWin)->GetBorder(
+ GetWindow()->mpWindowImpl->mnLeftBorder, GetWindow()->mpWindowImpl->mnTopBorder,
+ GetWindow()->mpWindowImpl->mnRightBorder, GetWindow()->mpWindowImpl->mnBottomBorder );
+ mpOldBorderWin->Resize();
+ }
+ GetWindow()->mpWindowImpl->mpBorderWindow = mpOldBorderWin;
+ GetWindow()->SetParent( pRealParent );
+ GetWindow()->mpWindowImpl->mpRealParent = pRealParent;
+
+ delete mpFloatWin;
+ mpFloatWin = NULL;
+
+ // call handler - which will destroy the window and thus the wrapper as well !
+ GetWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_ENDPOPUPMODE, &aData );
+
+ return 0;
+}
+
+
+BOOL ImplDockingWindowWrapper::IsInPopupMode() const
+{
+ if( GetFloatingWindow() )
+ return GetFloatingWindow()->IsInPopupMode();
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::SetFloatingMode( BOOL bFloatMode )
+{
+ // do nothing if window is docked and locked
+ if( !IsFloatingMode() && IsLocked() )
+ return;
+
+ if ( IsFloatingMode() != bFloatMode )
+ {
+ if ( PrepareToggleFloatingMode() )
+ {
+ BOOL bVisible = GetWindow()->IsVisible();
+
+ if ( bFloatMode )
+ {
+ GetWindow()->Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ maDockPos = GetWindow()->GetPosPixel();
+
+ Window* pRealParent = GetWindow()->GetWindow( WINDOW_PARENT );
+ mpOldBorderWin = GetWindow()->GetWindow( WINDOW_BORDER );
+ if( mpOldBorderWin == mpDockingWindow )
+ mpOldBorderWin = NULL; // no border window found
+
+ ImplDockFloatWin2* pWin =
+ new ImplDockFloatWin2(
+ mpParent,
+ mnFloatBits & ( WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE ) ?
+ mnFloatBits | WB_SYSTEMWINDOW
+//#ifdef __USE_OWNERDRAWDECORATION__
+ | WB_OWNERDRAWDECORATION
+//#endif
+ : mnFloatBits,
+ this );
+
+ // reduce the border width for seamless NWF painting
+ // (especially for the toolbar gradient on Windows XP)
+ /*AllSettings aSettings( pWin->GetSettings() );
+ StyleSettings aStyleSettings( aSettings.GetStyleSettings() );
+ aStyleSettings.SetBorderSize( 0 );
+ aSettings.SetStyleSettings( aStyleSettings );
+ pWin->SetSettings( aSettings );*/
+
+// mpFloatWin = pWin;
+
+
+ GetWindow()->mpWindowImpl->mpBorderWindow = NULL;
+ GetWindow()->mpWindowImpl->mnLeftBorder = 0;
+ GetWindow()->mpWindowImpl->mnTopBorder = 0;
+ GetWindow()->mpWindowImpl->mnRightBorder = 0;
+ GetWindow()->mpWindowImpl->mnBottomBorder = 0;
+
+ // Falls Parent zerstoert wird, muessen wir auch vom
+ // BorderWindow den Parent umsetzen
+ if ( mpOldBorderWin )
+ mpOldBorderWin->SetParent( pWin );
+ GetWindow()->SetParent( pWin );
+ pWin->SetPosPixel( Point() );
+
+ GetWindow()->mpWindowImpl->mpBorderWindow = pWin;
+ pWin->mpWindowImpl->mpClientWindow = mpDockingWindow;
+ GetWindow()->mpWindowImpl->mpRealParent = pRealParent;
+
+ pWin->SetText( GetWindow()->GetText() );
+ pWin->SetOutputSizePixel( GetWindow()->GetSizePixel() );
+ pWin->SetPosPixel( maFloatPos );
+ // DockingDaten ans FloatingWindow weiterreichen
+ pWin->ShowTitleButton( TITLE_BUTTON_DOCKING, mbDockBtn );
+ pWin->ShowTitleButton( TITLE_BUTTON_HIDE, mbHideBtn );
+ pWin->SetPin( mbPined );
+ if ( mbRollUp )
+ pWin->RollUp();
+ else
+ pWin->RollDown();
+ pWin->SetRollUpOutputSizePixel( maRollUpOutSize );
+ pWin->SetMinOutputSizePixel( maMinOutSize );
+ pWin->SetMaxOutputSizePixel( maMaxOutSize );
+
+ mpFloatWin = pWin;
+
+ if ( bVisible )
+ GetWindow()->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
+
+ ToggleFloatingMode();
+ }
+ else
+ {
+ GetWindow()->Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // FloatingDaten wird im FloatingWindow speichern
+ maFloatPos = mpFloatWin->GetPosPixel();
+ mbDockBtn = mpFloatWin->IsTitleButtonVisible( TITLE_BUTTON_DOCKING );
+ mbHideBtn = mpFloatWin->IsTitleButtonVisible( TITLE_BUTTON_HIDE );
+ mbPined = mpFloatWin->IsPined();
+ mbRollUp = mpFloatWin->IsRollUp();
+ maRollUpOutSize = mpFloatWin->GetRollUpOutputSizePixel();
+ maMinOutSize = mpFloatWin->GetMinOutputSizePixel();
+ maMaxOutSize = mpFloatWin->GetMaxOutputSizePixel();
+
+ Window* pRealParent = GetWindow()->GetWindow( WINDOW_PARENT ); //mpWindowImpl->mpRealParent;
+ GetWindow()->mpWindowImpl->mpBorderWindow = NULL;
+ if ( mpOldBorderWin )
+ {
+ GetWindow()->SetParent( mpOldBorderWin );
+ ((ImplBorderWindow*)mpOldBorderWin)->GetBorder(
+ GetWindow()->mpWindowImpl->mnLeftBorder, GetWindow()->mpWindowImpl->mnTopBorder,
+ GetWindow()->mpWindowImpl->mnRightBorder, GetWindow()->mpWindowImpl->mnBottomBorder );
+ mpOldBorderWin->Resize();
+ }
+ GetWindow()->mpWindowImpl->mpBorderWindow = mpOldBorderWin;
+ GetWindow()->SetParent( pRealParent );
+ GetWindow()->mpWindowImpl->mpRealParent = pRealParent;
+
+ delete static_cast<ImplDockFloatWin2*>(mpFloatWin);
+ mpFloatWin = NULL;
+ GetWindow()->SetPosPixel( maDockPos );
+
+ if ( bVisible )
+ GetWindow()->Show();
+
+ ToggleFloatingMode();
+
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::SetFloatStyle( WinBits nStyle )
+{
+ mnFloatBits = nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+WinBits ImplDockingWindowWrapper::GetFloatStyle() const
+{
+ return mnFloatBits;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::SetTabStop()
+{
+ GetWindow()->SetStyle( GetWindow()->GetStyle() | (WB_GROUP | WB_TABSTOP) );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::SetPosSizePixel( long nX, long nY,
+ long nWidth, long nHeight,
+ USHORT nFlags )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+ else
+ GetWindow()->SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+Point ImplDockingWindowWrapper::GetPosPixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetPosPixel();
+ else
+ return mpDockingWindow->GetPosPixel();
+}
+
+// -----------------------------------------------------------------------
+
+Size ImplDockingWindowWrapper::GetSizePixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetSizePixel();
+ else
+ return mpDockingWindow->GetSizePixel();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::SetOutputSizePixel( const Size& rNewSize )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetOutputSizePixel( rNewSize );
+ else
+ GetWindow()->SetOutputSizePixel( rNewSize );
+}
+
+// -----------------------------------------------------------------------
+
+Size ImplDockingWindowWrapper::GetOutputSizePixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetOutputSizePixel();
+ else
+ return mpDockingWindow->GetOutputSizePixel();
+}
+
+Point ImplDockingWindowWrapper::GetFloatingPos() const
+{
+ if ( mpFloatWin )
+ {
+ //Rectangle aRect = mpFloatWin->GetWindow( WINDOW_CLIENT)->GetWindowExtentsRelative( mpFloatWin->GetParent() );
+ WindowStateData aData;
+ aData.SetMask( WINDOWSTATE_MASK_POS );
+ mpFloatWin->GetWindowStateData( aData );
+ Point aPos( aData.GetX(), aData.GetY() );
+ aPos = mpFloatWin->GetParent()->ImplGetFrameWindow()->AbsoluteScreenToOutputPixel( aPos );
+ return aPos;
+ }
+ else
+ return maFloatPos;
+}
+
+// -----------------------------------------------------------------------
+// old inlines from DockingWindow
+// -----------------------------------------------------------------------
+
+void ImplDockingWindowWrapper::SetPin( BOOL bPin )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetPin( bPin );
+ mbPined = bPin;
+}
+
+BOOL ImplDockingWindowWrapper::IsPined() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->IsPined();
+ return mbPined;
+}
+
+void ImplDockingWindowWrapper::RollUp()
+{
+ if ( mpFloatWin )
+ mpFloatWin->RollUp();
+ mbRollUp = TRUE;
+}
+
+void ImplDockingWindowWrapper::RollDown()
+{
+ if ( mpFloatWin )
+ mpFloatWin->RollDown();
+ mbRollUp = FALSE;
+}
+
+BOOL ImplDockingWindowWrapper::IsRollUp() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->IsRollUp();
+ return mbRollUp;
+}
+
+void ImplDockingWindowWrapper::SetRollUpOutputSizePixel( const Size& rSize )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetRollUpOutputSizePixel( rSize );
+ maRollUpOutSize = rSize;
+}
+
+Size ImplDockingWindowWrapper::GetRollUpOutputSizePixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetRollUpOutputSizePixel();
+ return maRollUpOutSize;
+}
+
+void ImplDockingWindowWrapper::SetMinOutputSizePixel( const Size& rSize )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetMinOutputSizePixel( rSize );
+ maMinOutSize = rSize;
+}
+
+void ImplDockingWindowWrapper::SetMaxOutputSizePixel( const Size& rSize )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetMaxOutputSizePixel( rSize );
+ maMaxOutSize = rSize;
+}
+
+const Size& ImplDockingWindowWrapper::GetMinOutputSizePixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetMinOutputSizePixel();
+ return maMinOutSize;
+}
+
+const Size& ImplDockingWindowWrapper::GetMaxOutputSizePixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetMaxOutputSizePixel();
+ return maMaxOutSize;
+}
+
+void ImplDockingWindowWrapper::SetFloatingPos( const Point& rNewPos )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetPosPixel( rNewPos );
+ else
+ maFloatPos = rNewPos;
+}
+
+BOOL ImplDockingWindowWrapper::IsFloatingMode() const
+{
+ return (mpFloatWin != NULL);
+}
+
+
+void ImplDockingWindowWrapper::SetDragArea( const Rectangle& rRect )
+{
+ maDragArea = rRect;
+}
+
+Rectangle ImplDockingWindowWrapper::GetDragArea() const
+{
+ return maDragArea;
+}
+
+void ImplDockingWindowWrapper::Lock()
+{
+ mbLocked = TRUE;
+ // only toolbars support locking
+ ToolBox *pToolBox = dynamic_cast< ToolBox * >( GetWindow() );
+ if( pToolBox )
+ pToolBox->Lock( mbLocked );
+}
+
+void ImplDockingWindowWrapper::Unlock()
+{
+ mbLocked = FALSE;
+ // only toolbars support locking
+ ToolBox *pToolBox = dynamic_cast< ToolBox * >( GetWindow() );
+ if( pToolBox )
+ pToolBox->Lock( mbLocked );
+}
+
+BOOL ImplDockingWindowWrapper::IsLocked() const
+{
+ return mbLocked;
+}
diff --git a/vcl/source/window/dockwin.cxx b/vcl/source/window/dockwin.cxx
new file mode 100644
index 000000000000..c8e382bad982
--- /dev/null
+++ b/vcl/source/window/dockwin.cxx
@@ -0,0 +1,1120 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <tools/time.hxx>
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/event.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/dockwin.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/window.h>
+#include <vcl/unowrap.hxx>
+#include <vcl/salframe.hxx>
+
+
+
+// =======================================================================
+
+#define DOCKWIN_FLOATSTYLES (WB_SIZEABLE | WB_MOVEABLE | WB_CLOSEABLE | WB_STANDALONE | WB_PINABLE | WB_ROLLABLE )
+
+// =======================================================================
+
+// -----------------------------------------------------------------------
+
+class DockingWindow::ImplData
+{
+public:
+ ImplData();
+ ~ImplData();
+
+ Window* mpParent;
+ Size maMaxOutSize;
+};
+
+DockingWindow::ImplData::ImplData()
+{
+ mpParent = NULL;
+ maMaxOutSize = Size( SHRT_MAX, SHRT_MAX );
+}
+
+DockingWindow::ImplData::~ImplData()
+{
+}
+
+// -----------------------------------------------------------------------
+
+class ImplDockFloatWin : public FloatingWindow
+{
+private:
+ DockingWindow* mpDockWin;
+ ULONG mnLastTicks;
+ Timer maDockTimer;
+ Point maDockPos;
+ Rectangle maDockRect;
+ BOOL mbInMove;
+ ULONG mnLastUserEvent;
+
+ DECL_LINK( DockingHdl, ImplDockFloatWin* );
+ DECL_LINK( DockTimerHdl, ImplDockFloatWin* );
+public:
+ ImplDockFloatWin( Window* pParent, WinBits nWinBits,
+ DockingWindow* pDockingWin );
+ ~ImplDockFloatWin();
+
+ virtual void Move();
+ virtual void Resize();
+ virtual void TitleButtonClick( USHORT nButton );
+ virtual void Pin();
+ virtual void Roll();
+ virtual void PopupModeEnd();
+ virtual void Resizing( Size& rSize );
+ virtual BOOL Close();
+
+ ULONG GetLastTicks() const { return mnLastTicks; }
+};
+
+
+ImplDockFloatWin::ImplDockFloatWin( Window* pParent, WinBits nWinBits,
+ DockingWindow* pDockingWin ) :
+ FloatingWindow( pParent, nWinBits ),
+ mpDockWin( pDockingWin ),
+ mnLastTicks( Time::GetSystemTicks() ),
+ mbInMove( FALSE ),
+ mnLastUserEvent( 0 )
+{
+ // Daten vom DockingWindow uebernehmen
+ if ( pDockingWin )
+ {
+ SetSettings( pDockingWin->GetSettings() );
+ Enable( pDockingWin->IsEnabled(), FALSE );
+ EnableInput( pDockingWin->IsInputEnabled(), FALSE );
+ AlwaysEnableInput( pDockingWin->IsAlwaysEnableInput(), FALSE );
+ EnableAlwaysOnTop( pDockingWin->IsAlwaysOnTopEnabled() );
+ SetActivateMode( pDockingWin->GetActivateMode() );
+ }
+
+ SetBackground();
+
+ maDockTimer.SetTimeoutHdl( LINK( this, ImplDockFloatWin, DockTimerHdl ) );
+ maDockTimer.SetTimeout( 50 );
+}
+
+// -----------------------------------------------------------------------
+
+ImplDockFloatWin::~ImplDockFloatWin()
+{
+ if( mnLastUserEvent )
+ Application::RemoveUserEvent( mnLastUserEvent );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplDockFloatWin, DockTimerHdl, ImplDockFloatWin*, EMPTYARG )
+{
+ DBG_ASSERT( mpDockWin->IsFloatingMode(), "docktimer called but not floating" );
+
+ maDockTimer.Stop();
+ PointerState aState = GetPointerState();
+
+ if( aState.mnState & KEY_MOD1 )
+ {
+ // i43499 CTRL disables docking now
+ mpDockWin->GetParent()->ImplGetFrameWindow()->HideTracking();
+ mpDockWin->EndDocking( maDockRect, TRUE );
+ if( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) )
+ maDockTimer.Start();
+ }
+ else if( ! ( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) ) )
+ {
+ mpDockWin->GetParent()->ImplGetFrameWindow()->HideTracking();
+ mpDockWin->EndDocking( maDockRect, FALSE );
+ }
+ else
+ {
+ mpDockWin->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect, SHOWTRACK_BIG | SHOWTRACK_WINDOW );
+ maDockTimer.Start();
+ }
+
+ return 0;
+}
+
+IMPL_LINK( ImplDockFloatWin, DockingHdl, ImplDockFloatWin*, EMPTYARG )
+{
+ PointerState aState = mpDockWin->GetParent()->GetPointerState();
+
+ mnLastUserEvent = 0;
+ if( mpDockWin->IsDockable() &&
+ (Time::GetSystemTicks() - mnLastTicks > 500) &&
+ ( aState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT ) ) &&
+ !(aState.mnState & KEY_MOD1) ) // i43499 CTRL disables docking now
+ {
+ maDockPos = Point( mpDockWin->GetParent()->AbsoluteScreenToOutputPixel( OutputToAbsoluteScreenPixel( Point() ) ) );
+ maDockPos = mpDockWin->GetParent()->OutputToScreenPixel( maDockPos ); // sfx expects screen coordinates
+
+ if( ! mpDockWin->IsDocking() )
+ mpDockWin->StartDocking();
+ maDockRect = Rectangle( maDockPos, mpDockWin->GetSizePixel() );
+
+ // mouse pos also in screen pixels
+ Point aMousePos = mpDockWin->GetParent()->OutputToScreenPixel( aState.maPos );
+
+ BOOL bFloatMode = mpDockWin->Docking( aMousePos, maDockRect );
+ if( ! bFloatMode )
+ {
+ mpDockWin->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect, SHOWTRACK_OBJECT | SHOWTRACK_WINDOW );
+ DockTimerHdl( this );
+ }
+ else
+ {
+ mpDockWin->GetParent()->ImplGetFrameWindow()->HideTracking();
+ maDockTimer.Stop();
+ mpDockWin->EndDocking( maDockRect, TRUE );
+ }
+ }
+ mbInMove = FALSE;
+ return 0;
+}
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Move()
+{
+ if( mbInMove )
+ return;
+
+ mbInMove = TRUE;
+ FloatingWindow::Move();
+ mpDockWin->Move();
+
+ /*
+ * note: the window should only dock if
+ * the user releases all mouse buttons. The real problem here
+ * is that we don't get mouse events (at least not on X)
+ * if the mouse is on the decoration. So we have to start an
+ * awkward timer based process that polls the modifier/buttons
+ * to see whether they are in the right condition shortly after the
+ * last Move message.
+ */
+ if( ! mnLastUserEvent )
+ mnLastUserEvent = Application::PostUserEvent( LINK( this, ImplDockFloatWin, DockingHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Resize()
+{
+ FloatingWindow::Resize();
+ Size aSize( GetSizePixel() );
+ mpDockWin->ImplPosSizeWindow( 0, 0, aSize.Width(), aSize.Height(), WINDOW_POSSIZE_POSSIZE );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::TitleButtonClick( USHORT nButton )
+{
+ FloatingWindow::TitleButtonClick( nButton );
+ mpDockWin->TitleButtonClick( nButton );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Pin()
+{
+ FloatingWindow::Pin();
+ mpDockWin->Pin();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Roll()
+{
+ FloatingWindow::Roll();
+ mpDockWin->Roll();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::PopupModeEnd()
+{
+ FloatingWindow::PopupModeEnd();
+ mpDockWin->PopupModeEnd();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Resizing( Size& rSize )
+{
+ FloatingWindow::Resizing( rSize );
+ mpDockWin->Resizing( rSize );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplDockFloatWin::Close()
+{
+ return mpDockWin->Close();
+}
+
+// =======================================================================
+
+BOOL DockingWindow::ImplStartDocking( const Point& rPos )
+{
+ if ( !mbDockable )
+ return FALSE;
+
+ maMouseOff = rPos;
+ maMouseStart = maMouseOff;
+ mbDocking = TRUE;
+ mbLastFloatMode = IsFloatingMode();
+ mbStartFloat = mbLastFloatMode;
+
+ // FloatingBorder berechnen
+ FloatingWindow* pWin;
+ if ( mpFloatWin )
+ pWin = mpFloatWin;
+ else
+ pWin = new ImplDockFloatWin( mpImplData->mpParent, mnFloatBits, NULL );
+ pWin->GetBorder( mnDockLeft, mnDockTop, mnDockRight, mnDockBottom );
+ if ( !mpFloatWin )
+ delete pWin;
+
+ Point aPos = ImplOutputToFrame( Point() );
+ Size aSize = Window::GetOutputSizePixel();
+ mnTrackX = aPos.X();
+ mnTrackY = aPos.Y();
+ mnTrackWidth = aSize.Width();
+ mnTrackHeight = aSize.Height();
+
+ if ( mbLastFloatMode )
+ {
+ maMouseOff.X() += mnDockLeft;
+ maMouseOff.Y() += mnDockTop;
+ mnTrackX -= mnDockLeft;
+ mnTrackY -= mnDockTop;
+ mnTrackWidth += mnDockLeft+mnDockRight;
+ mnTrackHeight += mnDockTop+mnDockBottom;
+ }
+
+ if ( GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_DOCKING &&
+ !( mnFloatBits & ( WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE ) ) ) // no full drag when migrating to system window
+ mbDragFull = TRUE;
+ else
+ {
+ StartDocking();
+ mbDragFull = FALSE;
+ ImplUpdateAll();
+ ImplGetFrameWindow()->ImplUpdateAll();
+ }
+
+ StartTracking( STARTTRACK_KEYMOD );
+ return TRUE;
+}
+
+// =======================================================================
+
+void DockingWindow::ImplInitDockingWindowData()
+{
+ mpImplData = new ImplData;
+ mpWindowImpl->mbDockWin = TRUE;
+
+ mpFloatWin = NULL;
+ mbDockCanceled = FALSE;
+ mbDockPrevented = FALSE;
+ mbFloatPrevented = FALSE;
+ mbDocking = FALSE;
+ mbPined = FALSE;
+ mbRollUp = FALSE;
+ mbDockBtn = FALSE;
+ mbHideBtn = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ImplInit( Window* pParent, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+
+ mpImplData->mpParent = pParent;
+ mbDockable = (nStyle & WB_DOCKABLE) != 0;
+ mnFloatBits = WB_BORDER | (nStyle & DOCKWIN_FLOATSTYLES);
+ nStyle &= ~(DOCKWIN_FLOATSTYLES | WB_BORDER);
+ if ( nStyle & WB_DOCKBORDER )
+ nStyle |= WB_BORDER;
+
+ Window::ImplInit( pParent, nStyle, NULL );
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ImplInitSettings()
+{
+ // Hack, damit man auch DockingWindows ohne Hintergrund bauen kann
+ // und noch nicht alles umgestellt ist
+ if ( IsBackground() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ImplLoadRes( const ResId& rResId )
+{
+ Window::ImplLoadRes( rResId );
+
+ ULONG nMask = ReadLongRes();
+
+ if ( (RSC_DOCKINGWINDOW_XYMAPMODE | RSC_DOCKINGWINDOW_X |
+ RSC_DOCKINGWINDOW_Y) & nMask )
+ {
+ // Groessenangabe aus der Resource verwenden
+ Point aPos;
+ MapUnit ePosMap = MAP_PIXEL;
+
+ if ( RSC_DOCKINGWINDOW_XYMAPMODE & nMask )
+ ePosMap = (MapUnit)ReadLongRes();
+
+ if ( RSC_DOCKINGWINDOW_X & nMask )
+ {
+ aPos.X() = ReadShortRes();
+ aPos.X() = ImplLogicUnitToPixelX( aPos.X(), ePosMap );
+ }
+
+ if ( RSC_DOCKINGWINDOW_Y & nMask )
+ {
+ aPos.Y() = ReadShortRes();
+ aPos.Y() = ImplLogicUnitToPixelY( aPos.Y(), ePosMap );
+ }
+
+ SetFloatingPos( aPos );
+ }
+
+ if ( nMask & RSC_DOCKINGWINDOW_FLOATING )
+ {
+ if ( (BOOL)ReadShortRes() )
+ SetFloatingMode( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+DockingWindow::DockingWindow( WindowType nType ) :
+ Window( nType )
+{
+ ImplInitDockingWindowData();
+}
+
+// -----------------------------------------------------------------------
+
+DockingWindow::DockingWindow( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_DOCKINGWINDOW )
+{
+ ImplInitDockingWindowData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+DockingWindow::DockingWindow( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_DOCKINGWINDOW )
+{
+ ImplInitDockingWindowData();
+ rResId.SetRT( RSC_DOCKINGWINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+DockingWindow::~DockingWindow()
+{
+ if ( IsFloatingMode() )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+ SetFloatingMode( FALSE );
+ }
+ delete mpImplData;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::Tracking( const TrackingEvent& rTEvt )
+{
+ if( GetDockingManager()->IsDockable( this ) ) // new docking interface
+ return Window::Tracking( rTEvt );
+
+ if ( mbDocking )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbDocking = FALSE;
+ if ( mbDragFull )
+ {
+ // Bei Abbruch alten Zustand wieder herstellen
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ StartDocking();
+ Rectangle aRect( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) );
+ EndDocking( aRect, mbStartFloat );
+ }
+ }
+ else
+ {
+ HideTracking();
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ mbDockCanceled = TRUE;
+ EndDocking( Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
+ mbDockCanceled = FALSE;
+ }
+ else
+ EndDocking( Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
+ }
+ }
+ // Docking nur bei nicht synthetischen MouseEvents
+ else if ( !rTEvt.GetMouseEvent().IsSynthetic() || rTEvt.GetMouseEvent().IsModifierChanged() )
+ {
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+ Point aFrameMousePos = ImplOutputToFrame( aMousePos );
+ Size aFrameSize = mpWindowImpl->mpFrameWindow->GetOutputSizePixel();
+ if ( aFrameMousePos.X() < 0 )
+ aFrameMousePos.X() = 0;
+ if ( aFrameMousePos.Y() < 0 )
+ aFrameMousePos.Y() = 0;
+ if ( aFrameMousePos.X() > aFrameSize.Width()-1 )
+ aFrameMousePos.X() = aFrameSize.Width()-1;
+ if ( aFrameMousePos.Y() > aFrameSize.Height()-1 )
+ aFrameMousePos.Y() = aFrameSize.Height()-1;
+ aMousePos = ImplFrameToOutput( aFrameMousePos );
+ aMousePos.X() -= maMouseOff.X();
+ aMousePos.Y() -= maMouseOff.Y();
+ Point aFramePos = ImplOutputToFrame( aMousePos );
+ Rectangle aTrackRect( aFramePos, Size( mnTrackWidth, mnTrackHeight ) );
+ Rectangle aCompRect = aTrackRect;
+ aFramePos.X() += maMouseOff.X();
+ aFramePos.Y() += maMouseOff.Y();
+ if ( mbDragFull )
+ StartDocking();
+ BOOL bFloatMode = Docking( aFramePos, aTrackRect );
+ mbDockPrevented = FALSE;
+ mbFloatPrevented = FALSE;
+ if ( mbLastFloatMode != bFloatMode )
+ {
+ if ( bFloatMode )
+ {
+ aTrackRect.Left() -= mnDockLeft;
+ aTrackRect.Top() -= mnDockTop;
+ aTrackRect.Right() += mnDockRight;
+ aTrackRect.Bottom() += mnDockBottom;
+ }
+ else
+ {
+ if ( aCompRect == aTrackRect )
+ {
+ aTrackRect.Left() += mnDockLeft;
+ aTrackRect.Top() += mnDockTop;
+ aTrackRect.Right() -= mnDockRight;
+ aTrackRect.Bottom() -= mnDockBottom;
+ }
+ }
+ mbLastFloatMode = bFloatMode;
+ }
+ if ( mbDragFull )
+ {
+ Point aPos;
+ Point aOldPos = OutputToScreenPixel( aPos );
+ EndDocking( aTrackRect, mbLastFloatMode );
+ // Wenn der Status bzw. die Position sich
+ // geaendert hat, dann neu ausgeben
+ if ( aOldPos != OutputToScreenPixel( aPos ) )
+ {
+ ImplUpdateAll();
+ ImplGetFrameWindow()->ImplUpdateAll();
+ }
+// EndDocking( aTrackRect, mbLastFloatMode );
+ }
+ else
+ {
+ USHORT nTrackStyle;
+ if ( bFloatMode )
+ nTrackStyle = SHOWTRACK_BIG;
+ else
+ nTrackStyle = SHOWTRACK_OBJECT;
+ Rectangle aShowTrackRect = aTrackRect;
+ aShowTrackRect.SetPos( ImplFrameToOutput( aShowTrackRect.TopLeft() ) );
+ ShowTracking( aShowTrackRect, nTrackStyle );
+
+ // Maus-Offset neu berechnen, da Rechteck veraendert werden
+ // konnte
+ maMouseOff.X() = aFramePos.X() - aTrackRect.Left();
+ maMouseOff.Y() = aFramePos.Y() - aTrackRect.Top();
+ }
+
+ mnTrackX = aTrackRect.Left();
+ mnTrackY = aTrackRect.Top();
+ mnTrackWidth = aTrackRect.GetWidth();
+ mnTrackHeight = aTrackRect.GetHeight();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long DockingWindow::Notify( NotifyEvent& rNEvt )
+{
+ if( GetDockingManager()->IsDockable( this ) ) // new docking interface
+ return Window::Notify( rNEvt );
+
+ if ( mbDockable )
+ {
+ if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
+ {
+ const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
+ if ( pMEvt->IsLeft() )
+ {
+ if ( pMEvt->IsMod1() && (pMEvt->GetClicks() == 2) )
+ {
+ SetFloatingMode( !IsFloatingMode() );
+ return TRUE;
+ }
+ else if ( pMEvt->GetClicks() == 1 )
+ {
+ // check if window is floating standalone (IsFloating())
+ // or only partially floating and still docked with one border
+ // ( !mpWindowImpl->mbFrame)
+ if( ! IsFloatingMode() || ! mpFloatWin->mpWindowImpl->mbFrame )
+ {
+ Point aPos = pMEvt->GetPosPixel();
+ Window* pWindow = rNEvt.GetWindow();
+ if ( pWindow != this )
+ {
+ aPos = pWindow->OutputToScreenPixel( aPos );
+ aPos = ScreenToOutputPixel( aPos );
+ }
+ ImplStartDocking( aPos );
+ }
+ return TRUE;
+ }
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyCode& rKey = rNEvt.GetKeyEvent()->GetKeyCode();
+ if( rKey.GetCode() == KEY_F10 && rKey.GetModifier() &&
+ rKey.IsShift() && rKey.IsMod1() )
+ {
+ SetFloatingMode( !IsFloatingMode() );
+ return TRUE;
+ }
+ }
+ }
+
+ return Window::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::StartDocking()
+{
+ mbDocking = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingWindow::Docking( const Point&, Rectangle& )
+{
+ return IsFloatingMode();
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::EndDocking( const Rectangle& rRect, BOOL bFloatMode )
+{
+ if ( !IsDockingCanceled() )
+ {
+ BOOL bShow = FALSE;
+ if ( bFloatMode != IsFloatingMode() )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+ SetFloatingMode( bFloatMode );
+ bShow = TRUE;
+ if ( bFloatMode && mpFloatWin )
+ mpFloatWin->SetPosSizePixel( rRect.TopLeft(), rRect.GetSize() );
+ }
+ if ( !bFloatMode )
+ {
+ Point aPos = rRect.TopLeft();
+ aPos = GetParent()->ScreenToOutputPixel( aPos );
+ Window::SetPosSizePixel( aPos, rRect.GetSize() );
+ }
+
+ if ( bShow )
+ Show();
+ }
+ mbDocking = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingWindow::PrepareToggleFloatingMode()
+{
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingWindow::Close()
+{
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ ImplCallEventListeners( VCLEVENT_WINDOW_CLOSE );
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ ImplRemoveDel( &aDelData );
+
+ if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() )
+ return FALSE;
+
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ToggleFloatingMode()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::TitleButtonClick( USHORT )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::Pin()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::Roll()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::PopupModeEnd()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::Resizing( Size& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+
+ Window::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+ else
+ Window::DataChanged( rDCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ShowTitleButton( USHORT nButton, BOOL bVisible )
+{
+ if ( mpFloatWin )
+ mpFloatWin->ShowTitleButton( nButton, bVisible );
+ else
+ {
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ mbDockBtn = bVisible;
+ else /* if ( nButton == TITLE_BUTTON_HIDE ) */
+ mbHideBtn = bVisible;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingWindow::IsTitleButtonVisible( USHORT nButton ) const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->IsTitleButtonVisible( nButton );
+ else
+ {
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ return mbDockBtn;
+ else /* if ( nButton == TITLE_BUTTON_HIDE ) */
+ return mbHideBtn;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetFloatingMode( BOOL bFloatMode )
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ pWrapper->SetFloatingMode( bFloatMode );
+ return;
+ }
+ if ( IsFloatingMode() != bFloatMode )
+ {
+ if ( PrepareToggleFloatingMode() ) // changes to floating mode can be vetoed
+ {
+ BOOL bVisible = IsVisible();
+
+ if ( bFloatMode )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ maDockPos = Window::GetPosPixel();
+
+ Window* pRealParent = mpWindowImpl->mpRealParent;
+ mpOldBorderWin = mpWindowImpl->mpBorderWindow;
+
+ ImplDockFloatWin* pWin =
+ new ImplDockFloatWin(
+ mpImplData->mpParent,
+ mnFloatBits & ( WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE ) ? mnFloatBits | WB_SYSTEMWINDOW : mnFloatBits,
+ this );
+ mpFloatWin = pWin;
+ mpWindowImpl->mpBorderWindow = NULL;
+ mpWindowImpl->mnLeftBorder = 0;
+ mpWindowImpl->mnTopBorder = 0;
+ mpWindowImpl->mnRightBorder = 0;
+ mpWindowImpl->mnBottomBorder = 0;
+ // Falls Parent zerstoert wird, muessen wir auch vom
+ // BorderWindow den Parent umsetzen
+ if ( mpOldBorderWin )
+ mpOldBorderWin->SetParent( pWin );
+ SetParent( pWin );
+ SetPosPixel( Point() );
+ mpWindowImpl->mpBorderWindow = pWin;
+ pWin->mpWindowImpl->mpClientWindow = this;
+ mpWindowImpl->mpRealParent = pRealParent;
+ pWin->SetText( Window::GetText() );
+ pWin->SetOutputSizePixel( Window::GetSizePixel() );
+ pWin->SetPosPixel( maFloatPos );
+ // DockingDaten ans FloatingWindow weiterreichen
+ pWin->ShowTitleButton( TITLE_BUTTON_DOCKING, mbDockBtn );
+ pWin->ShowTitleButton( TITLE_BUTTON_HIDE, mbHideBtn );
+ pWin->SetPin( mbPined );
+ if ( mbRollUp )
+ pWin->RollUp();
+ else
+ pWin->RollDown();
+ pWin->SetRollUpOutputSizePixel( maRollUpOutSize );
+ pWin->SetMinOutputSizePixel( maMinOutSize );
+ pWin->SetMaxOutputSizePixel( mpImplData->maMaxOutSize );
+
+ ToggleFloatingMode();
+
+ if ( bVisible )
+ Show();
+ }
+ else
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // FloatingDaten wird im FloatingWindow speichern
+ maFloatPos = mpFloatWin->GetPosPixel();
+ mbDockBtn = mpFloatWin->IsTitleButtonVisible( TITLE_BUTTON_DOCKING );
+ mbHideBtn = mpFloatWin->IsTitleButtonVisible( TITLE_BUTTON_HIDE );
+ mbPined = mpFloatWin->IsPined();
+ mbRollUp = mpFloatWin->IsRollUp();
+ maRollUpOutSize = mpFloatWin->GetRollUpOutputSizePixel();
+ maMinOutSize = mpFloatWin->GetMinOutputSizePixel();
+ mpImplData->maMaxOutSize = mpFloatWin->GetMaxOutputSizePixel();
+
+ Window* pRealParent = mpWindowImpl->mpRealParent;
+ mpWindowImpl->mpBorderWindow = NULL;
+ if ( mpOldBorderWin )
+ {
+ SetParent( mpOldBorderWin );
+ ((ImplBorderWindow*)mpOldBorderWin)->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ mpOldBorderWin->Resize();
+ }
+ mpWindowImpl->mpBorderWindow = mpOldBorderWin;
+ SetParent( pRealParent );
+ mpWindowImpl->mpRealParent = pRealParent;
+ delete static_cast<ImplDockFloatWin*>(mpFloatWin);
+ mpFloatWin = NULL;
+ SetPosPixel( maDockPos );
+
+ ToggleFloatingMode();
+
+ if ( bVisible )
+ Show();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetFloatStyle( WinBits nStyle )
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ pWrapper->SetFloatStyle( nStyle );
+ return;
+ }
+
+ mnFloatBits = nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+WinBits DockingWindow::GetFloatStyle() const
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ return pWrapper->GetFloatStyle();
+ }
+
+ return mnFloatBits;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetTabStop()
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ pWrapper->SetTabStop();
+ return;
+ }
+
+ mpWindowImpl->mnStyle |= WB_GROUP | WB_TABSTOP;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetPosSizePixel( long nX, long nY,
+ long nWidth, long nHeight,
+ USHORT nFlags )
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ if ( pWrapper->mpFloatWin )
+ pWrapper->mpFloatWin->SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+ else
+ Window::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+ return;
+ }
+
+ if ( mpFloatWin )
+ mpFloatWin->SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+ else
+ Window::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+Point DockingWindow::GetPosPixel() const
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ if ( pWrapper->mpFloatWin )
+ return pWrapper->mpFloatWin->GetPosPixel();
+ else
+ return Window::GetPosPixel();
+ }
+
+ if ( mpFloatWin )
+ return mpFloatWin->GetPosPixel();
+ else
+ return Window::GetPosPixel();
+}
+
+// -----------------------------------------------------------------------
+
+Size DockingWindow::GetSizePixel() const
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ if ( pWrapper->mpFloatWin )
+ return pWrapper->mpFloatWin->GetSizePixel();
+ else
+ return Window::GetSizePixel();
+ }
+
+ if ( mpFloatWin )
+ return mpFloatWin->GetSizePixel();
+ else
+ return Window::GetSizePixel();
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetOutputSizePixel( const Size& rNewSize )
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ if ( pWrapper->mpFloatWin )
+ pWrapper->mpFloatWin->SetOutputSizePixel( rNewSize );
+ else
+ Window::SetOutputSizePixel( rNewSize );
+ return;
+ }
+
+ if ( mpFloatWin )
+ mpFloatWin->SetOutputSizePixel( rNewSize );
+ else
+ Window::SetOutputSizePixel( rNewSize );
+}
+
+// -----------------------------------------------------------------------
+
+Size DockingWindow::GetOutputSizePixel() const
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ if ( pWrapper->mpFloatWin )
+ return pWrapper->mpFloatWin->GetOutputSizePixel();
+ else
+ return Window::GetOutputSizePixel();
+ }
+
+ if ( mpFloatWin )
+ return mpFloatWin->GetOutputSizePixel();
+ else
+ return Window::GetOutputSizePixel();
+}
+
+Point DockingWindow::GetFloatingPos() const
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ {
+ if ( pWrapper->mpFloatWin )
+ {
+ WindowStateData aData;
+ aData.SetMask( WINDOWSTATE_MASK_POS );
+ pWrapper->mpFloatWin->GetWindowStateData( aData );
+ Point aPos( aData.GetX(), aData.GetY() );
+ aPos = pWrapper->mpFloatWin->GetParent()->ImplGetFrameWindow()->AbsoluteScreenToOutputPixel( aPos );
+ return aPos;
+ }
+ else
+ return maFloatPos;
+ }
+
+ if ( mpFloatWin )
+ {
+ WindowStateData aData;
+ aData.SetMask( WINDOWSTATE_MASK_POS );
+ mpFloatWin->GetWindowStateData( aData );
+ Point aPos( aData.GetX(), aData.GetY() );
+ aPos = mpFloatWin->GetParent()->ImplGetFrameWindow()->AbsoluteScreenToOutputPixel( aPos );
+ return aPos;
+ }
+ else
+ return maFloatPos;
+}
+
+BOOL DockingWindow::IsFloatingMode() const
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ return pWrapper->IsFloatingMode();
+ else
+ return (mpFloatWin != NULL);
+}
+
+void DockingWindow::SetMaxOutputSizePixel( const Size& rSize )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetMaxOutputSizePixel( rSize );
+ mpImplData->maMaxOutSize = rSize;
+}
+
+const Size& DockingWindow::GetMaxOutputSizePixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetMaxOutputSizePixel();
+ return mpImplData->maMaxOutSize;
+}
diff --git a/vcl/source/window/floatwin.cxx b/vcl/source/window/floatwin.cxx
new file mode 100644
index 000000000000..323bbe3b0d74
--- /dev/null
+++ b/vcl/source/window/floatwin.cxx
@@ -0,0 +1,878 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/event.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/window.h>
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/salframe.hxx>
+#include <tools/debug.hxx>
+
+
+// =======================================================================
+
+class FloatingWindow::ImplData
+{
+public:
+ ImplData();
+ ~ImplData();
+
+ ToolBox* mpBox;
+ Rectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
+};
+
+FloatingWindow::ImplData::ImplData()
+{
+ mpBox = NULL;
+}
+
+FloatingWindow::ImplData::~ImplData()
+{
+}
+
+Rectangle& FloatingWindow::ImplGetItemEdgeClipRect()
+{
+ return mpImplData->maItemEdgeClipRect;
+}
+
+// =======================================================================
+
+void FloatingWindow::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mpImplData = new ImplData;
+
+ mpWindowImpl->mbFloatWin = TRUE;
+ mbInCleanUp = FALSE;
+ mbGrabFocus = FALSE;
+
+ DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL!" );
+
+ if ( !pParent )
+ pParent = ImplGetSVData()->maWinData.mpAppWin;
+
+ DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists" );
+
+ // no Border, then we dont need a border window
+ if ( !nStyle )
+ {
+ mpWindowImpl->mbOverlapWin = TRUE;
+ nStyle |= WB_DIALOGCONTROL;
+ SystemWindow::ImplInit( pParent, nStyle, NULL );
+ }
+ else
+ {
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+
+ if( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)
+ && !(nStyle & WB_OWNERDRAWDECORATION) )
+ {
+ WinBits nFloatWinStyle = nStyle;
+ // #99154# floaters are not closeable by default anymore, eg fullscreen floater
+ // nFloatWinStyle |= WB_CLOSEABLE;
+ mpWindowImpl->mbFrame = TRUE;
+ mpWindowImpl->mbOverlapWin = TRUE;
+ SystemWindow::ImplInit( pParent, nFloatWinStyle & ~WB_BORDER, NULL );
+ }
+ else
+ {
+ ImplBorderWindow* pBorderWin;
+ USHORT nBorderStyle = BORDERWINDOW_STYLE_BORDER | BORDERWINDOW_STYLE_FLOAT;
+
+ if( nStyle & WB_OWNERDRAWDECORATION ) nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
+ else nBorderStyle |= BORDERWINDOW_STYLE_OVERLAP;
+
+ if ( (nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
+ {
+ nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
+ nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
+ }
+ pBorderWin = new ImplBorderWindow( pParent, nStyle, nBorderStyle );
+ SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
+ pBorderWin->mpWindowImpl->mpClientWindow = this;
+ pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ pBorderWin->SetDisplayActive( TRUE );
+ mpWindowImpl->mpBorderWindow = pBorderWin;
+ mpWindowImpl->mpRealParent = pParent;
+ }
+ }
+ SetActivateMode( 0 );
+
+ mpNextFloat = NULL;
+ mpFirstPopupModeWin = NULL;
+ mnPostId = 0;
+ mnTitle = (nStyle & WB_MOVEABLE) ? FLOATWIN_TITLE_NORMAL : FLOATWIN_TITLE_NONE;
+ mnOldTitle = mnTitle;
+ mnPopupModeFlags = 0;
+ mbInPopupMode = FALSE;
+ mbPopupMode = FALSE;
+ mbPopupModeCanceled = FALSE;
+ mbPopupModeTearOff = FALSE;
+ mbMouseDown = FALSE;
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::ImplInitSettings()
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+}
+
+// =======================================================================
+
+FloatingWindow::FloatingWindow( Window* pParent, WinBits nStyle ) :
+ SystemWindow( WINDOW_FLOATINGWINDOW )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+FloatingWindow::FloatingWindow( Window* pParent, const ResId& rResId ) :
+ SystemWindow( WINDOW_FLOATINGWINDOW )
+{
+ rResId.SetRT( RSC_FLOATINGWINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::ImplLoadRes( const ResId& rResId )
+{
+ SystemWindow::ImplLoadRes( rResId );
+
+ ULONG nObjMask = ReadLongRes();
+
+ if ( (RSC_FLOATINGWINDOW_WHMAPMODE | RSC_FLOATINGWINDOW_WIDTH |
+ RSC_FLOATINGWINDOW_HEIGHT) & nObjMask )
+ {
+ // Groessenangabe aus der Resource verwenden
+ Size aSize;
+ MapUnit eSizeMap = MAP_PIXEL;
+
+ if ( RSC_FLOATINGWINDOW_WHMAPMODE & nObjMask )
+ eSizeMap = (MapUnit) ReadShortRes();
+ if ( RSC_FLOATINGWINDOW_WIDTH & nObjMask )
+ aSize.Width() = ReadShortRes();
+ if ( RSC_FLOATINGWINDOW_HEIGHT & nObjMask )
+ aSize.Height() = ReadShortRes();
+
+ SetRollUpOutputSizePixel( LogicToPixel( aSize, eSizeMap ) );
+ }
+
+ if (nObjMask & RSC_FLOATINGWINDOW_ZOOMIN )
+ {
+ if ( ReadShortRes() )
+ RollUp();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+FloatingWindow::~FloatingWindow()
+{
+ if( mbPopupModeCanceled )
+ // indicates that ESC key was pressed
+ // will be handled in Window::ImplGrabFocus()
+ SetDialogControlFlags( GetDialogControlFlags() | WINDOW_DLGCTRL_FLOATWIN_POPUPMODEEND_CANCEL );
+
+ if ( IsInPopupMode() )
+ EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL | FLOATWIN_POPUPMODEEND_DONTCALLHDL );
+
+ if ( mnPostId )
+ Application::RemoveUserEvent( mnPostId );
+
+ delete mpImplData;
+}
+
+// -----------------------------------------------------------------------
+
+Point FloatingWindow::CalcFloatingPosition( Window* pWindow, const Rectangle& rRect, ULONG nFlags, USHORT& rArrangeIndex )
+{
+ return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
+}
+
+// -----------------------------------------------------------------------
+
+Point FloatingWindow::ImplCalcPos( Window* pWindow,
+ const Rectangle& rRect, ULONG nFlags,
+ USHORT& rArrangeIndex )
+{
+ // Fenster-Position ermitteln
+ Point aPos;
+ Size aSize = pWindow->GetSizePixel();
+ Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
+ FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
+
+ // convert....
+ Window* pW = pWindow;
+ if ( pW->mpWindowImpl->mpRealParent )
+ pW = pW->mpWindowImpl->mpRealParent;
+
+ Rectangle normRect( rRect ); // rRect is already relative to top-level window
+ normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
+
+ BOOL bRTL = Application::GetSettings().GetLayoutRTL();
+
+ Rectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
+ pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
+
+ Rectangle devRectRTL( devRect );
+ if( bRTL )
+ // create a rect that can be compared to desktop coordinates
+ devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
+ if( Application::GetScreenCount() > 1 && ! Application::IsMultiDisplay() )
+ aScreenRect = Application::GetScreenPosSizePixel(
+ Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
+
+
+ USHORT nArrangeAry[5];
+ USHORT nArrangeIndex;
+ BOOL bBreak;
+ Point e1,e2; // the common edge between the item rect and the floating window
+
+ if ( nFlags & FLOATWIN_POPUPMODE_LEFT )
+ {
+ nArrangeAry[0] = FLOATWIN_POPUPMODE_LEFT;
+ nArrangeAry[1] = FLOATWIN_POPUPMODE_RIGHT;
+ nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
+ nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
+ nArrangeAry[4] = FLOATWIN_POPUPMODE_LEFT;
+ }
+ else if ( nFlags & FLOATWIN_POPUPMODE_RIGHT )
+ {
+ nArrangeAry[0] = FLOATWIN_POPUPMODE_RIGHT;
+ nArrangeAry[1] = FLOATWIN_POPUPMODE_LEFT;
+ nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
+ nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
+ nArrangeAry[4] = FLOATWIN_POPUPMODE_RIGHT;
+ }
+ else if ( nFlags & FLOATWIN_POPUPMODE_UP )
+ {
+ nArrangeAry[0] = FLOATWIN_POPUPMODE_UP;
+ nArrangeAry[1] = FLOATWIN_POPUPMODE_DOWN;
+ nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
+ nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
+ nArrangeAry[4] = FLOATWIN_POPUPMODE_UP;
+ }
+ else
+ {
+ nArrangeAry[0] = FLOATWIN_POPUPMODE_DOWN;
+ nArrangeAry[1] = FLOATWIN_POPUPMODE_UP;
+ nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
+ nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
+ nArrangeAry[4] = FLOATWIN_POPUPMODE_DOWN;
+ }
+ if ( nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE )
+ nArrangeIndex = 4;
+ else
+ nArrangeIndex = 0;
+
+ for ( ; nArrangeIndex < 5; nArrangeIndex++ )
+ {
+ bBreak = TRUE;
+ switch ( nArrangeAry[nArrangeIndex] )
+ {
+
+ case FLOATWIN_POPUPMODE_LEFT:
+ aPos.X() = devRect.Left()-aSize.Width()+1;
+ aPos.Y() = devRect.Top();
+ aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
+ if( bRTL ) // --- RTL --- we're comparing screen coordinates here
+ {
+ if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
+ bBreak = FALSE;
+ }
+ else
+ {
+ if ( aPos.X() < aScreenRect.Left() )
+ bBreak = FALSE;
+ }
+ if( bBreak )
+ {
+ e1 = devRect.TopLeft();
+ e2 = devRect.BottomLeft();
+ // set non-zero width
+ e2.X()++;
+ // don't clip corners
+ e1.Y()++;
+ e2.Y()--;
+ }
+ break;
+ case FLOATWIN_POPUPMODE_RIGHT:
+ aPos = devRect.TopRight();
+ aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
+ if( bRTL ) // --- RTL --- we're comparing screen coordinates here
+ {
+ if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
+ bBreak = FALSE;
+ }
+ else
+ {
+ if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
+ bBreak = FALSE;
+ }
+ if( bBreak )
+ {
+ e1 = devRect.TopRight();
+ e2 = devRect.BottomRight();
+ // set non-zero width
+ e2.X()++;
+ // don't clip corners
+ e1.Y()++;
+ e2.Y()--;
+ }
+ break;
+ case FLOATWIN_POPUPMODE_UP:
+ aPos.X() = devRect.Left();
+ aPos.Y() = devRect.Top()-aSize.Height()+1;
+ if ( aPos.Y() < aScreenRect.Top() )
+ bBreak = FALSE;
+ if( bBreak )
+ {
+ e1 = devRect.TopLeft();
+ e2 = devRect.TopRight();
+ // set non-zero height
+ e2.Y()++;
+ // don't clip corners
+ e1.X()++;
+ e2.X()--;
+ }
+ break;
+ case FLOATWIN_POPUPMODE_DOWN:
+ aPos = devRect.BottomLeft();
+ if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
+ bBreak = FALSE;
+ if( bBreak )
+ {
+ e1 = devRect.BottomLeft();
+ e2 = devRect.BottomRight();
+ // set non-zero height
+ e2.Y()++;
+ // don't clip corners
+ e1.X()++;
+ e2.X()--;
+ }
+ break;
+ }
+
+ // Evt. noch anpassen
+ if ( bBreak && !(nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE) )
+ {
+ if ( (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_LEFT) ||
+ (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_RIGHT) )
+ {
+ if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
+ {
+ aPos.Y() = devRect.Bottom()-aSize.Height()+1;
+ if ( aPos.Y() < aScreenRect.Top() )
+ aPos.Y() = aScreenRect.Top();
+ }
+ }
+ else
+ {
+ if( bRTL ) // --- RTL --- we're comparing screen coordinates here
+ {
+ if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
+ aPos.X() -= aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1;
+ else if( aPos.X() + aSize.Width() > aScreenRect.Right() )
+ {
+ aPos.X() -= aSize.Width()-2; // popup to left instead
+ aPos.Y() -= 2;
+ }
+ }
+ else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
+ {
+ aPos.X() = devRect.Right()-aSize.Width()+1;
+ if ( aPos.X() < aScreenRect.Left() )
+ aPos.X() = aScreenRect.Left();
+ }
+ }
+ }
+
+ if ( bBreak )
+ break;
+ }
+ if ( nArrangeIndex > 4 )
+ nArrangeIndex = 4;
+
+ rArrangeIndex = nArrangeIndex;
+
+ aPos = pW->AbsoluteScreenToOutputPixel( aPos );
+
+ // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
+ if( pFloatingWindow )
+ {
+ pFloatingWindow->mpImplData->maItemEdgeClipRect =
+ Rectangle( e1, e2 );
+ }
+
+ // caller expects cordinates relative to top-level win
+ return pW->OutputToScreenPixel( aPos );
+}
+
+// -----------------------------------------------------------------------
+
+FloatingWindow* FloatingWindow::ImplFloatHitTest( Window* pReference, const Point& rPos, USHORT& rHitTest )
+{
+ FloatingWindow* pWin = this;
+
+ Point aAbsolute( rPos );
+
+ // compare coordinates in absolute screen coordinates
+ if( pReference->ImplHasMirroredGraphics() )
+ {
+ if(!pReference->IsRTLEnabled() )
+ // --- RTL --- re-mirror back to get device coordiantes
+ pReference->ImplReMirror( aAbsolute );
+
+ Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
+ aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
+ aAbsolute = aRect.TopLeft();
+ }
+ else
+ aAbsolute = Point( pReference->OutputToAbsoluteScreenPixel(
+ pReference->ScreenToOutputPixel(rPos) ) );
+
+ do
+ {
+ // compute the floating window's size in absolute screen coordinates
+
+ // use the border window to have the exact position
+ Window *pBorderWin = pWin->GetWindow( WINDOW_BORDER );
+
+ Point aPt; // the top-left corner in output coordinates ie (0,0)
+ Rectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( Rectangle( aPt, pBorderWin->GetSizePixel()) ) ) ;
+ if ( devRect.IsInside( aAbsolute ) )
+ {
+ rHitTest = IMPL_FLOATWIN_HITTEST_WINDOW;
+ return pWin;
+ }
+
+ // test, if mouse is in rectangle, (this is typically the rect of the active
+ // toolbox item or similar)
+ // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
+ // is already in absolute device coordinates
+ if ( pWin->maFloatRect.IsInside( aAbsolute ) )
+ {
+ rHitTest = IMPL_FLOATWIN_HITTEST_RECT;
+ return pWin;
+ }
+
+ pWin = pWin->mpNextFloat;
+ }
+ while ( pWin );
+
+ rHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
+{
+ FloatingWindow* pWin = this;
+ FloatingWindow* pLastFoundWin = pWin;
+
+ do
+ {
+ if ( pWin->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NEWLEVEL )
+ pLastFoundWin = pWin;
+
+ pWin = pWin->mpNextFloat;
+ }
+ while ( pWin );
+
+ return pLastFoundWin;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL FloatingWindow::ImplIsFloatPopupModeWindow( const Window* pWindow )
+{
+ FloatingWindow* pWin = this;
+
+ do
+ {
+ if ( pWin->mpFirstPopupModeWin == pWindow )
+ return TRUE;
+
+ pWin = pWin->mpNextFloat;
+ }
+ while ( pWin );
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( FloatingWindow, ImplEndPopupModeHdl, void*, EMPTYARG )
+{
+ mnPostId = 0;
+ mnPopupModeFlags = 0;
+ mbPopupMode = FALSE;
+ PopupModeEnd();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long FloatingWindow::Notify( NotifyEvent& rNEvt )
+{
+ // Zuerst Basisklasse rufen wegen TabSteuerung
+ long nRet = SystemWindow::Notify( rNEvt );
+ if ( !nRet )
+ {
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+ KeyCode aKeyCode = pKEvt->GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+
+ if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
+ {
+ Close();
+ return TRUE;
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::StateChanged( StateChangedType nType )
+{
+ SystemWindow::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SystemWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::ImplCallPopupModeEnd()
+{
+ // PopupMode wurde beendet
+ mbInPopupMode = FALSE;
+
+ // Handler asyncron rufen
+ if ( !mnPostId )
+ Application::PostUserEvent( mnPostId, LINK( this, FloatingWindow, ImplEndPopupModeHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::PopupModeEnd()
+{
+ maPopupModeEndHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::SetTitleType( USHORT nTitle )
+{
+ if ( (mnTitle != nTitle) && mpWindowImpl->mpBorderWindow )
+ {
+ mnTitle = nTitle;
+ Size aOutSize = GetOutputSizePixel();
+ USHORT nTitleStyle;
+ if ( nTitle == FLOATWIN_TITLE_NORMAL )
+ nTitleStyle = BORDERWINDOW_TITLE_SMALL;
+ else if ( nTitle == FLOATWIN_TITLE_TEAROFF )
+ nTitleStyle = BORDERWINDOW_TITLE_TEAROFF;
+ else // nTitle == FLOATWIN_TITLE_NONE
+ nTitleStyle = BORDERWINDOW_TITLE_NONE;
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetTitleType( nTitleStyle, aOutSize );
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::StartPopupMode( const Rectangle& rRect, ULONG nFlags )
+{
+ // avoid flickering
+ if ( IsVisible() )
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ if ( IsRollUp() )
+ RollDown();
+
+ // remove title
+ mnOldTitle = mnTitle;
+ if ( nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF )
+ SetTitleType( FLOATWIN_TITLE_TEAROFF );
+ else
+ SetTitleType( FLOATWIN_TITLE_NONE );
+
+ // avoid close on focus change for decorated floating windows only
+ if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
+ nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
+
+ // #102010# For debugging Accessibility
+ static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
+ if( pEnv && *pEnv )
+ nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
+
+ // compute window position according to flags and arrangement
+ USHORT nArrangeIndex;
+ SetPosPixel( ImplCalcPos( this, rRect, nFlags, nArrangeIndex ) );
+
+ // set data and display window
+ // convert maFloatRect to absolute device coordinates
+ // so they can be compared across different frames
+ // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
+ maFloatRect = rRect;
+ if( GetParent()->ImplHasMirroredGraphics() )
+ {
+ maFloatRect.SetPos( GetParent()->ScreenToOutputPixel( rRect.TopLeft() ) );
+ maFloatRect = GetParent()->ImplOutputToUnmirroredAbsoluteScreenPixel( maFloatRect );
+ }
+ else
+ maFloatRect.SetPos( GetParent()->OutputToAbsoluteScreenPixel( GetParent()->ScreenToOutputPixel( rRect.TopLeft() ) ) );
+
+ maFloatRect.Left() -= 2;
+ maFloatRect.Top() -= 2;
+ maFloatRect.Right() += 2;
+ maFloatRect.Bottom() += 2;
+ mnPopupModeFlags = nFlags;
+ mbInPopupMode = TRUE;
+ mbPopupMode = TRUE;
+ mbPopupModeCanceled = FALSE;
+ mbPopupModeTearOff = FALSE;
+ mbMouseDown = FALSE;
+
+ mbOldSaveBackMode = IsSaveBackgroundEnabled();
+ EnableSaveBackground();
+
+ // add FloatingWindow to list of windows that are in popup mode
+ ImplSVData* pSVData = ImplGetSVData();
+ mpNextFloat = pSVData->maWinData.mpFirstFloat;
+ pSVData->maWinData.mpFirstFloat = this;
+ if( nFlags & FLOATWIN_POPUPMODE_GRABFOCUS )
+ {
+ // force key input even without focus (useful for menues)
+ mbGrabFocus = TRUE;
+ }
+ Show( TRUE, SHOW_NOACTIVATE );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::StartPopupMode( ToolBox* pBox, ULONG nFlags )
+{
+ // get selected button
+ USHORT nItemId = pBox->GetDownItemId();
+ if ( !nItemId )
+ return;
+
+ mpImplData->mpBox = pBox;
+ pBox->ImplFloatControl( TRUE, this );
+
+ // retrieve some data from the ToolBox
+ Rectangle aRect = pBox->GetItemRect( nItemId );
+ Point aPos;
+ // convert to parent's screen coordinates
+ aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
+ aRect.SetPos( aPos );
+
+ nFlags |=
+ FLOATWIN_POPUPMODE_NOFOCUSCLOSE |
+// FLOATWIN_POPUPMODE_NOMOUSECLOSE |
+ FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
+// FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE | // #105968# floating toolboxes should close when clicked in (parent's) float rect
+ FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;
+// | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
+
+/*
+ * FLOATWIN_POPUPMODE_NOKEYCLOSE |
+ * don't set since it disables closing floaters with escape
+ */
+
+ // Flags fuer Positionierung bestimmen
+ if ( !(nFlags & (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_UP |
+ FLOATWIN_POPUPMODE_LEFT | FLOATWIN_POPUPMODE_RIGHT |
+ FLOATWIN_POPUPMODE_NOAUTOARRANGE)) )
+ {
+ if ( pBox->IsHorizontal() )
+ nFlags |= FLOATWIN_POPUPMODE_DOWN;
+ else
+ nFlags |= FLOATWIN_POPUPMODE_RIGHT;
+ }
+
+ // FloatingModus starten
+ StartPopupMode( aRect, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::ImplEndPopupMode( USHORT nFlags, ULONG nFocusId )
+{
+ if ( !mbInPopupMode )
+ return;
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ mbInCleanUp = TRUE; // prevent killing this window due to focus change while working with it
+
+ // Bei allen nachfolgenden PopupMode-Fenster den Modus auch beenden
+ while ( pSVData->maWinData.mpFirstFloat && pSVData->maWinData.mpFirstFloat != this )
+ pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
+
+
+ // Fenster aus der Liste austragen
+ pSVData->maWinData.mpFirstFloat = mpNextFloat;
+ mpNextFloat = NULL;
+
+ ULONG nPopupModeFlags = mnPopupModeFlags;
+
+ // Wenn nicht abgerissen wurde, dann Fenster wieder Hiden
+ if ( !(nFlags & FLOATWIN_POPUPMODEEND_TEAROFF) ||
+ !(nPopupModeFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // Focus evt. auf ein entsprechendes FloatingWindow weiterschalten
+ if ( nFocusId )
+ Window::EndSaveFocus( nFocusId );
+ else if ( pSVData->maWinData.mpFocusWin && pSVData->maWinData.mpFirstFloat &&
+ ImplIsWindowOrChild( pSVData->maWinData.mpFocusWin ) )
+ pSVData->maWinData.mpFirstFloat->GrabFocus();
+ mbPopupModeTearOff = FALSE;
+ }
+ else
+ {
+ mbPopupModeTearOff = TRUE;
+ if ( nFocusId )
+ Window::EndSaveFocus( nFocusId, FALSE );
+ }
+ EnableSaveBackground( mbOldSaveBackMode );
+
+ mbPopupModeCanceled = (nFlags & FLOATWIN_POPUPMODEEND_CANCEL) != 0;
+
+ // Gegebenenfalls den Title wieder herstellen
+ SetTitleType( mnOldTitle );
+
+ // ToolBox wieder auf normal schalten
+ if ( mpImplData->mpBox )
+ {
+ mpImplData->mpBox->ImplFloatControl( FALSE, this );
+ mpImplData->mpBox = NULL;
+ }
+
+ // Je nach Parameter den PopupModeEnd-Handler rufen
+ if ( !(nFlags & FLOATWIN_POPUPMODEEND_DONTCALLHDL) )
+ ImplCallPopupModeEnd();
+
+ // Je nach Parameter die restlichen Fenster auch noch schliessen
+ if ( nFlags & FLOATWIN_POPUPMODEEND_CLOSEALL )
+ {
+ if ( !(nPopupModeFlags & FLOATWIN_POPUPMODE_NEWLEVEL) )
+ {
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+ }
+ }
+
+ mbInCleanUp = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::EndPopupMode( USHORT nFlags )
+{
+ ImplEndPopupMode( nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::AddPopupModeWindow( Window* pWindow )
+{
+ // !!! bisher erst 1 Fenster und noch keine Liste
+ mpFirstPopupModeWin = pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::RemovePopupModeWindow( Window* pWindow )
+{
+ // !!! bisher erst 1 Fenster und noch keine Liste
+ if ( mpFirstPopupModeWin == pWindow )
+ mpFirstPopupModeWin = NULL;
+}
+
diff --git a/vcl/source/window/introwin.cxx b/vcl/source/window/introwin.cxx
new file mode 100644
index 000000000000..03f88adc3566
--- /dev/null
+++ b/vcl/source/window/introwin.cxx
@@ -0,0 +1,88 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/salframe.hxx>
+#include <tools/debug.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/wrkwin.hxx>
+
+#include <vcl/bitmap.hxx>
+#include <vcl/impbmp.hxx>
+#include <vcl/introwin.hxx>
+
+
+
+
+// =======================================================================
+
+void IntroWindow::ImplInitIntroWindowData()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpIntroWindow = this;
+}
+
+// -----------------------------------------------------------------------
+
+IntroWindow::IntroWindow( ) :
+ WorkWindow( WINDOW_INTROWINDOW )
+{
+ ImplInitIntroWindowData();
+ WorkWindow::ImplInit( 0, WB_INTROWIN, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+IntroWindow::~IntroWindow()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->mpIntroWindow == this )
+ pSVData->mpIntroWindow = NULL;
+}
+
+void IntroWindow::SetBackgroundBitmap( const Bitmap& rBitmap )
+{
+ if( ! rBitmap.IsEmpty() )
+ {
+ SalBitmap* pBmp = rBitmap.ImplGetImpBitmap()->ImplGetSalBitmap();
+ ImplGetFrame()->SetBackgroundBitmap( pBmp );
+ }
+}
+
+void IntroWindow::SetBackgroundBitmap( const BitmapEx& rBitmapEx )
+{
+ if( ! rBitmapEx.IsEmpty() )
+ {
+ SalBitmap* pBmp = rBitmapEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap();
+ ImplGetFrame()->SetBackgroundBitmap( pBmp );
+ }
+}
diff --git a/vcl/source/window/javachild.cxx b/vcl/source/window/javachild.cxx
new file mode 100644
index 000000000000..2cd18b897ff5
--- /dev/null
+++ b/vcl/source/window/javachild.cxx
@@ -0,0 +1,207 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+
+#ifdef SOLAR_JAVA
+#include <jni.h>
+#endif
+#include <comphelper/processfactory.hxx>
+
+#include <vcl/unohelp.hxx>
+#include <rtl/process.h>
+#include <rtl/ref.hxx>
+#include <jvmaccess/virtualmachine.hxx>
+#include <com/sun/star/java/XJavaVM.hpp>
+#include <com/sun/star/java/XJavaThreadRegister_11.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/salinst.hxx>
+#include <vcl/salframe.hxx>
+#include <vcl/window.hxx>
+#include <vcl/salobj.hxx>
+#include <vcl/javachild.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/sysdata.hxx>
+
+using namespace ::com::sun::star;
+
+// -------------------
+// - JavaChildWindow -
+// -------------------
+
+JavaChildWindow::JavaChildWindow( Window* pParent, WinBits nStyle ) :
+ SystemChildWindow( pParent, nStyle )
+{
+}
+
+// -----------------------------------------------------------------------
+
+JavaChildWindow::JavaChildWindow( Window* pParent, const ResId& rResId ) :
+ SystemChildWindow( pParent, rResId )
+{
+}
+
+// -----------------------------------------------------------------------
+
+JavaChildWindow::~JavaChildWindow()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void JavaChildWindow::implTestJavaException( void* pEnv )
+{
+#ifdef SOLAR_JAVA
+ JNIEnv* pJavaEnv = reinterpret_cast< JNIEnv* >( pEnv );
+ jthrowable jtThrowable = pJavaEnv->ExceptionOccurred();
+
+ if( jtThrowable )
+ { // is it a java exception ?
+#if OSL_DEBUG_LEVEL > 1
+ pJavaEnv->ExceptionDescribe();
+#endif // OSL_DEBUG_LEVEL > 1
+ pJavaEnv->ExceptionClear();
+
+ jclass jcThrowable = pJavaEnv->FindClass("java/lang/Throwable");
+ jmethodID jmThrowable_getMessage = pJavaEnv->GetMethodID(jcThrowable, "getMessage", "()Ljava/lang/String;");
+ jstring jsMessage = (jstring) pJavaEnv->CallObjectMethod(jtThrowable, jmThrowable_getMessage);
+ ::rtl::OUString ouMessage;
+
+ if(jsMessage)
+ {
+ const jchar * jcMessage = pJavaEnv->GetStringChars(jsMessage, NULL);
+ ouMessage = ::rtl::OUString(jcMessage);
+ pJavaEnv->ReleaseStringChars(jsMessage, jcMessage);
+ }
+
+ throw uno::RuntimeException(ouMessage, uno::Reference<uno::XInterface>());
+ }
+#endif // SOLAR_JAVA
+}
+
+// -----------------------------------------------------------------------
+
+sal_IntPtr JavaChildWindow::getParentWindowHandleForJava()
+{
+ sal_IntPtr nRet = 0;
+
+#if defined WNT
+ nRet = reinterpret_cast< sal_IntPtr >( GetSystemData()->hWnd );
+#elif defined QUARTZ
+ // FIXME: this is wrong
+ nRet = reinterpret_cast< sal_IntPtr >( GetSystemData()->pView );
+#elif defined UNX
+#ifdef SOLAR_JAVA
+ uno::Reference< lang::XMultiServiceFactory > xFactory( vcl::unohelper::GetMultiServiceFactory() );
+
+ if( xFactory.is() && ( GetSystemData()->aWindow > 0 ) )
+ {
+ try
+ {
+ ::rtl::Reference< ::jvmaccess::VirtualMachine > xVM;
+ uno::Reference< java::XJavaVM > xJavaVM( xFactory->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.java.JavaVirtualMachine") ) ), uno::UNO_QUERY );
+ uno::Sequence< sal_Int8 > aProcessID( 17 );
+
+ rtl_getGlobalProcessId( (sal_uInt8*) aProcessID.getArray() );
+ aProcessID[ 16 ] = 0;
+ OSL_ENSURE(sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *), "Pointer cannot be represented as sal_Int64");
+ sal_Int64 nPointer = reinterpret_cast< sal_Int64 >( static_cast< jvmaccess::VirtualMachine * >(0));
+ xJavaVM->getJavaVM(aProcessID) >>= nPointer;
+ xVM = reinterpret_cast< jvmaccess::VirtualMachine * >(nPointer);
+
+ if( xVM.is() )
+ {
+ try
+ {
+ ::jvmaccess::VirtualMachine::AttachGuard aVMAttachGuard( xVM );
+ JNIEnv* pEnv = aVMAttachGuard.getEnvironment();
+
+ jclass jcToolkit = pEnv->FindClass("java/awt/Toolkit");
+ implTestJavaException(pEnv);
+
+ jmethodID jmToolkit_getDefaultToolkit = pEnv->GetStaticMethodID( jcToolkit, "getDefaultToolkit", "()Ljava/awt/Toolkit;" );
+ implTestJavaException(pEnv);
+
+ pEnv->CallStaticObjectMethod(jcToolkit, jmToolkit_getDefaultToolkit);
+ implTestJavaException(pEnv);
+
+ jclass jcMotifAppletViewer = pEnv->FindClass("sun/plugin/navig/motif/MotifAppletViewer");
+ if( pEnv->ExceptionOccurred() )
+ {
+ pEnv->ExceptionClear();
+
+ jcMotifAppletViewer = pEnv->FindClass( "sun/plugin/viewer/MNetscapePluginContext");
+ implTestJavaException(pEnv);
+ }
+
+ jclass jcClassLoader = pEnv->FindClass("java/lang/ClassLoader");
+ implTestJavaException(pEnv);
+
+ jmethodID jmClassLoader_loadLibrary = pEnv->GetStaticMethodID( jcClassLoader, "loadLibrary", "(Ljava/lang/Class;Ljava/lang/String;Z)V");
+ implTestJavaException(pEnv);
+
+ jstring jsplugin = pEnv->NewStringUTF("javaplugin_jni");
+ implTestJavaException(pEnv);
+
+ pEnv->CallStaticVoidMethod(jcClassLoader, jmClassLoader_loadLibrary, jcMotifAppletViewer, jsplugin, JNI_FALSE);
+ implTestJavaException(pEnv);
+
+ jmethodID jmMotifAppletViewer_getWidget = pEnv->GetStaticMethodID( jcMotifAppletViewer, "getWidget", "(IIIII)I" );
+ implTestJavaException(pEnv);
+
+ const Size aSize( GetOutputSizePixel() );
+ jint ji_widget = pEnv->CallStaticIntMethod( jcMotifAppletViewer, jmMotifAppletViewer_getWidget,
+ GetSystemData()->aWindow, 0, 0, aSize.Width(), aSize.Height() );
+ implTestJavaException(pEnv);
+
+ nRet = static_cast< sal_IntPtr >( ji_widget );
+ }
+ catch( uno::RuntimeException& )
+ {
+ }
+
+ if( !nRet )
+ nRet = static_cast< sal_IntPtr >( GetSystemData()->aWindow );
+ }
+ }
+ catch( ... )
+ {
+ }
+ }
+#endif // SOLAR_JAVA
+#else // WNT || QUARTZ || UNX
+ // TBD
+#endif
+
+ return nRet;
+}
diff --git a/vcl/source/window/keycod.cxx b/vcl/source/window/keycod.cxx
new file mode 100644
index 000000000000..bcc5536fd028
--- /dev/null
+++ b/vcl/source/window/keycod.cxx
@@ -0,0 +1,160 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/salinst.hxx>
+#include <vcl/salframe.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/window.hxx>
+#ifndef _SV_KEYCOD_HXX
+#include <vcl/keycod.hxx>
+#endif
+
+#ifndef _RC_H
+#include <tools/rc.h>
+#endif
+
+
+
+// =======================================================================
+static USHORT aImplKeyFuncTab[(KEYFUNC_FRONT+1)*4] =
+{
+ 0, 0, 0, 0, // KEYFUNC_DONTKNOW
+ KEY_N | KEY_MOD1, 0, 0, 0, // KEYFUNC_NEW
+ KEY_O | KEY_MOD1, KEY_OPEN, 0, 0, // KEYFUNC_OPEN
+ KEY_S | KEY_MOD1, 0, 0, 0, // KEYFUNC_SAVE
+ 0, 0, 0, 0, // KEYFUNC_SAVEAS
+ KEY_P | KEY_MOD1, 0, 0, 0, // KEYFUNC_PRINT
+ KEY_W | KEY_MOD1, KEY_F4 | KEY_MOD1, 0, 0, // KEYFUNC_CLOSE
+ KEY_Q | KEY_MOD1, KEY_F4 | KEY_MOD2, 0, 0, // KEYFUNC_QUIT
+ KEY_X | KEY_MOD1, KEY_DELETE | KEY_SHIFT, KEY_CUT, 0, // KEYFUNC_CUT
+ KEY_C | KEY_MOD1, KEY_INSERT | KEY_MOD1, KEY_COPY, 0, // KEYFUNC_COPY
+ KEY_V | KEY_MOD1, KEY_INSERT | KEY_SHIFT, KEY_PASTE, 0, // KEYFUNC_PASTE
+ KEY_Z | KEY_MOD1, KEY_BACKSPACE | KEY_MOD2, KEY_UNDO, 0, // KEYFUNC_UNDO
+ 0, 0, 0, 0, // KEYFUNC_REDO
+ KEY_DELETE, 0, 0, 0, // KEYFUNC_DELETE
+ KEY_REPEAT, 0, 0, 0, // KEYFUNC_REPEAT
+ KEY_F | KEY_MOD1, KEY_FIND, 0, 0, // KEYFUNC_FIND
+ KEY_F | KEY_SHIFT | KEY_MOD1, KEY_SHIFT | KEY_FIND, 0, 0, // KEYFUNC_FINDBACKWARD
+ KEY_RETURN | KEY_MOD2, 0, 0, 0, // KEYFUNC_PROPERTIES
+ 0, 0, 0, 0 // KEYFUNC_FRONT
+};
+
+// -----------------------------------------------------------------------
+
+void ImplGetKeyCode( KeyFuncType eFunc, USHORT& rCode1, USHORT& rCode2, USHORT& rCode3, USHORT& rCode4 )
+{
+ USHORT nIndex = (USHORT)eFunc;
+ nIndex *= 4;
+ rCode1 = aImplKeyFuncTab[nIndex];
+ rCode2 = aImplKeyFuncTab[nIndex+1];
+ rCode3 = aImplKeyFuncTab[nIndex+2];
+ rCode4 = aImplKeyFuncTab[nIndex+3];
+}
+
+// =======================================================================
+
+KeyCode::KeyCode( KeyFuncType eFunction )
+{
+ USHORT nDummy;
+ ImplGetKeyCode( eFunction, nCode, nDummy, nDummy, nDummy );
+ eFunc = eFunction;
+}
+
+// -----------------------------------------------------------------------
+
+KeyCode::KeyCode( const ResId& rResId )
+{
+ rResId.SetRT( RSC_KEYCODE );
+
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if ( pResMgr && pResMgr->GetResource( rResId ) )
+ {
+ pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
+
+ ULONG nKeyCode = pResMgr->ReadLong();
+ ULONG nModifier = pResMgr->ReadLong();
+ ULONG nKeyFunc = pResMgr->ReadLong();
+
+ eFunc = (KeyFuncType)nKeyFunc;
+ if ( eFunc != KEYFUNC_DONTKNOW )
+ {
+ USHORT nDummy;
+ ImplGetKeyCode( eFunc, nCode, nDummy, nDummy, nDummy );
+ }
+ else
+ nCode = sal::static_int_cast<USHORT>(nKeyCode | nModifier);
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString KeyCode::GetName( Window* pWindow ) const
+{
+ if ( !pWindow )
+ pWindow = ImplGetDefaultWindow();
+ return pWindow ? pWindow->ImplGetFrame()->GetKeyName( GetFullCode() ) : XubString();
+}
+
+// -----------------------------------------------------------------------
+
+XubString KeyCode::GetSymbolName( const XubString& rFontName, Window* pWindow ) const
+{
+ if ( !pWindow )
+ pWindow = ImplGetDefaultWindow();
+ return pWindow ? pWindow->ImplGetFrame()->GetSymbolKeyName( rFontName, GetFullCode() ) : XubString();
+}
+
+// -----------------------------------------------------------------------
+
+KeyFuncType KeyCode::GetFunction() const
+{
+ if ( eFunc != KEYFUNC_DONTKNOW )
+ return eFunc;
+
+ USHORT nCompCode = GetModifier() | GetCode();
+ if ( nCompCode )
+ {
+ for ( USHORT i = (USHORT)KEYFUNC_NEW; i < (USHORT)KEYFUNC_FRONT; i++ )
+ {
+ USHORT nKeyCode1;
+ USHORT nKeyCode2;
+ USHORT nKeyCode3;
+ USHORT nKeyCode4;
+ ImplGetKeyCode( (KeyFuncType)i, nKeyCode1, nKeyCode2, nKeyCode3, nKeyCode4 );
+ if ( (nCompCode == nKeyCode1) || (nCompCode == nKeyCode2) || (nCompCode == nKeyCode3) || (nCompCode == nKeyCode4) )
+ return (KeyFuncType)i;
+ }
+ }
+
+ return KEYFUNC_DONTKNOW;
+}
diff --git a/vcl/source/window/keyevent.cxx b/vcl/source/window/keyevent.cxx
new file mode 100644
index 000000000000..f4011b9be16e
--- /dev/null
+++ b/vcl/source/window/keyevent.cxx
@@ -0,0 +1,116 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <com/sun/star/awt/KeyEvent.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <tools/debug.hxx>
+#include <vcl/event.hxx>
+
+KeyEvent::KeyEvent (const KeyEvent& rKeyEvent) :
+ maKeyCode (rKeyEvent.maKeyCode),
+ mnRepeat (rKeyEvent.mnRepeat),
+ mnCharCode(rKeyEvent.mnCharCode)
+{}
+
+/** inits this vcl KeyEvent with all settings from the given awt event **/
+KeyEvent::KeyEvent( const ::com::sun::star::awt::KeyEvent& rEvent )
+{
+ maKeyCode = KeyCode(
+ rEvent.KeyCode,
+ (rEvent.Modifiers & ::com::sun::star::awt::KeyModifier::SHIFT) != 0,
+ (rEvent.Modifiers & ::com::sun::star::awt::KeyModifier::MOD1) != 0,
+ (rEvent.Modifiers & ::com::sun::star::awt::KeyModifier::MOD2) != 0,
+ (rEvent.Modifiers & ::com::sun::star::awt::KeyModifier::MOD3) != 0);
+ mnRepeat = 0;
+ mnCharCode = rEvent.KeyChar;
+}
+
+/** fills out the given awt KeyEvent with all settings from this vcl event **/
+void KeyEvent::InitKeyEvent( ::com::sun::star::awt::KeyEvent& rEvent ) const
+{
+ rEvent.Modifiers = 0;
+ if( GetKeyCode().IsShift() )
+ rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
+ if( GetKeyCode().IsMod1() )
+ rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
+ if( GetKeyCode().IsMod2() )
+ rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
+ if( GetKeyCode().IsMod3() )
+ rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
+
+ rEvent.KeyCode = GetKeyCode().GetCode();
+ rEvent.KeyChar = GetCharCode();
+ rEvent.KeyFunc = sal::static_int_cast< sal_Int16 >(GetKeyCode().GetFunction());
+}
+
+KeyEvent KeyEvent::LogicalTextDirectionality (TextDirectionality eMode) const
+{
+ KeyEvent aClone(*this);
+
+ USHORT nCode = maKeyCode.GetCode();
+ USHORT nMod = maKeyCode.GetAllModifier();
+
+ switch (eMode)
+ {
+ case TextDirectionality_RightToLeft_TopToBottom:
+ switch (nCode)
+ {
+ case KEY_LEFT: aClone.maKeyCode = KeyCode(KEY_RIGHT, nMod); break;
+ case KEY_RIGHT: aClone.maKeyCode = KeyCode(KEY_LEFT, nMod); break;
+ }
+ break;
+
+ case TextDirectionality_TopToBottom_RightToLeft:
+ switch (nCode)
+ {
+ case KEY_DOWN: aClone.maKeyCode = KeyCode(KEY_RIGHT, nMod); break;
+ case KEY_UP: aClone.maKeyCode = KeyCode(KEY_LEFT, nMod); break;
+ case KEY_LEFT: aClone.maKeyCode = KeyCode(KEY_DOWN, nMod); break;
+ case KEY_RIGHT: aClone.maKeyCode = KeyCode(KEY_UP, nMod); break;
+ }
+ break;
+
+ case TextDirectionality_LeftToRight_TopToBottom:
+ /* do nothing */
+ break;
+ }
+
+ return aClone;
+}
+
+
+// -------------------------------------------------------
+
+const Point& HelpEvent::GetMousePosPixel() const
+{
+ //DBG_ASSERT( !mbKeyboardActivated, "Keyboard help has no mouse position !");
+ return maPos;
+}
+
diff --git a/vcl/source/window/makefile.mk b/vcl/source/window/makefile.mk
new file mode 100644
index 000000000000..82ce26f8e78e
--- /dev/null
+++ b/vcl/source/window/makefile.mk
@@ -0,0 +1,104 @@
+#*************************************************************************
+#
+# 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.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=vcl
+TARGET=win
+ENABLE_EXCEPTIONS=TRUE
+
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile2.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= \
+ $(SLO)$/arrange.obj \
+ $(SLO)$/abstdlg.obj \
+ $(SLO)$/accel.obj \
+ $(SLO)$/accmgr.obj \
+ $(SLO)$/brdwin.obj \
+ $(SLO)$/btndlg.obj \
+ $(SLO)$/cmdevt.obj \
+ $(SLO)$/cursor.obj \
+ $(SLO)$/decoview.obj \
+ $(SLO)$/dialog.obj \
+ $(SLO)$/dlgctrl.obj \
+ $(SLO)$/dndevdis.obj \
+ $(SLO)$/dndlcon.obj \
+ $(SLO)$/dockingarea.obj \
+ $(SLO)$/dockmgr.obj \
+ $(SLO)$/dockwin.obj \
+ $(SLO)$/floatwin.obj \
+ $(SLO)$/introwin.obj \
+ $(SLO)$/keycod.obj \
+ $(SLO)$/keyevent.obj \
+ $(SLO)$/mouseevent.obj \
+ $(SLO)$/menu.obj \
+ $(SLO)$/mnemonic.obj \
+ $(SLO)$/mnemonicengine.obj \
+ $(SLO)$/msgbox.obj \
+ $(SLO)$/popupmenuwindow.obj \
+ $(SLO)$/scrwnd.obj \
+ $(SLO)$/printdlg.obj \
+ $(SLO)$/seleng.obj \
+ $(SLO)$/split.obj \
+ $(SLO)$/splitwin.obj \
+ $(SLO)$/status.obj \
+ $(SLO)$/syschild.obj \
+ $(SLO)$/javachild.obj \
+ $(SLO)$/syswin.obj \
+ $(SLO)$/tabdlg.obj \
+ $(SLO)$/tabpage.obj \
+ $(SLO)$/taskpanelist.obj \
+ $(SLO)$/toolbox.obj \
+ $(SLO)$/toolbox2.obj \
+ $(SLO)$/window.obj \
+ $(SLO)$/winproc.obj \
+ $(SLO)$/window2.obj \
+ $(SLO)$/window3.obj \
+ $(SLO)$/wrkwin.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
+
+$(INCCOM)$/cuilib.hxx: makefile.mk
+.IF "$(GUI)"=="UNX"
+ @$(RM) $@
+ @echo \#define DLL_NAME \"libcui$(DLLPOSTFIX)$(DLLPOST)\" >$@
+.ELSE
+ @echo $(EMQ)#define DLL_NAME $(EMQ)"cui$(DLLPOSTFIX)$(DLLPOST)$(EMQ)" >$@
+.ENDIF
+
+$(SLO)$/abstdlg.obj : $(INCCOM)$/cuilib.hxx
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
new file mode 100644
index 000000000000..81676eba3be4
--- /dev/null
+++ b/vcl/source/window/menu.cxx
@@ -0,0 +1,6099 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include "svsys.h"
+#include "vcl/salinst.hxx"
+#include "tools/list.hxx"
+#include "tools/debug.hxx"
+#include "tools/diagnose_ex.h"
+#include "vcl/svdata.hxx"
+#include "vcl/svapp.hxx"
+#include "vcl/mnemonic.hxx"
+#include "vcl/image.hxx"
+#include "vcl/event.hxx"
+#include "vcl/help.hxx"
+#include "vcl/svids.hrc"
+#include "vcl/floatwin.hxx"
+#include "vcl/wrkwin.hxx"
+#include "vcl/timer.hxx"
+#include "vcl/sound.hxx"
+#include "vcl/decoview.hxx"
+#include "vcl/bitmap.hxx"
+#include "tools/rc.h"
+#include "vcl/menu.hxx"
+#include "vcl/button.hxx"
+#include "vcl/gradient.hxx"
+#include "vcl/i18nhelp.hxx"
+#include "vcl/taskpanelist.hxx"
+#include "vcl/window.h"
+#include "vcl/controllayout.hxx"
+#include "vcl/toolbox.hxx"
+#include "tools/stream.hxx"
+#include "vcl/salmenu.hxx"
+#include "vcl/salframe.hxx"
+#include "vcl/dockingarea.hxx"
+
+
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/i18n/XCharacterClassification.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <vcl/unowrap.hxx>
+
+#include <vcl/unohelp.hxx>
+#include <vcl/configsettings.hxx>
+
+#include "vcl/lazydelete.hxx"
+
+#include <map>
+
+namespace vcl
+{
+
+struct MenuLayoutData : public ControlLayoutData
+{
+ std::vector< USHORT > m_aLineItemIds;
+ std::vector< USHORT > m_aLineItemPositions;
+ std::map< USHORT, Rectangle > m_aVisibleItemBoundRects;
+};
+
+}
+
+using namespace ::com::sun::star;
+using namespace vcl;
+
+DBG_NAME( Menu )
+
+#define ITEMPOS_INVALID 0xFFFF
+
+#define EXTRASPACEY 2
+#define EXTRAITEMHEIGHT 4
+
+// document closer
+#define IID_DOCUMENTCLOSE 1
+
+#ifdef OS2
+
+#include <xwphook.h>
+
+// return TRUE if hilite should be executed: left mouse button down
+// or xwp mouse hook enabled
+static BOOL ImplHilite( const MouseEvent& rMEvt )
+{
+ static BOOL init = FALSE;
+ static HOOKCONFIG hc;
+
+ // read XWP settings at program startup
+ if (init == FALSE) {
+ BOOL rc;
+ ULONG cb = sizeof(HOOKCONFIG);
+ memset(&hc, 0, sizeof(HOOKCONFIG));
+ rc = PrfQueryProfileData( HINI_USER, INIAPP_XWPHOOK, INIKEY_HOOK_CONFIG,
+ &hc, &cb);
+ init = TRUE;
+ }
+ // check mouse left button
+ if (rMEvt.GetButtons() == MOUSE_LEFT)
+ return TRUE;
+ // return xwp flag
+ return hc.fSlidingMenus;
+}
+
+#endif
+
+static BOOL ImplAccelDisabled()
+{
+ // display of accelerator strings may be suppressed via configuration
+ static int nAccelDisabled = -1;
+
+ if( nAccelDisabled == -1 )
+ {
+ rtl::OUString aStr =
+ vcl::SettingsConfigItem::get()->
+ getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Menu" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SuppressAccelerators" ) ) );
+ nAccelDisabled = aStr.equalsIgnoreAsciiCaseAscii( "true" ) ? 1 : 0;
+ }
+ return (nAccelDisabled == 1) ? TRUE : FALSE;
+}
+
+struct MenuItemData
+{
+ USHORT nId; // SV Id
+ MenuItemType eType; // MenuItem-Type
+ MenuItemBits nBits; // MenuItem-Bits
+ Menu* pSubMenu; // Pointer auf das SubMenu
+ Menu* pAutoSubMenu; // Pointer auf SubMenu aus Resource
+ XubString aText; // Menu-Text
+ XubString aHelpText; // Help-String
+ XubString aTipHelpText; // TipHelp-String (eg, expanded filenames)
+ XubString aCommandStr; // CommandString
+ XubString aHelpCommandStr; // Help command string (to reference external help)
+ ULONG nHelpId; // Help-Id
+ ULONG nUserValue; // User value
+ Image aImage; // Image
+ KeyCode aAccelKey; // Accelerator-Key
+ BOOL bChecked; // Checked
+ BOOL bEnabled; // Enabled
+ BOOL bVisible; // Visible (note: this flag will not override MENU_FLAG_HIDEDISABLEDENTRIES when true)
+ BOOL bIsTemporary; // Temporary inserted ('No selection possible')
+ BOOL bMirrorMode;
+ long nItemImageAngle;
+ Size aSz; // nur temporaer gueltig
+ XubString aAccessibleName; // accessible name
+ XubString aAccessibleDescription; // accessible description
+
+ SalMenuItem* pSalMenuItem; // access to native menu
+
+ MenuItemData() :
+ pSalMenuItem ( NULL )
+ {}
+ MenuItemData( const XubString& rStr, const Image& rImage ) :
+ aText( rStr ),
+ aImage( rImage ),
+ pSalMenuItem ( NULL )
+ {}
+ ~MenuItemData();
+ bool HasCheck()
+ {
+ return bChecked || ( nBits & ( MIB_RADIOCHECK | MIB_CHECKABLE | MIB_AUTOCHECK ) );
+ }
+};
+
+MenuItemData::~MenuItemData()
+{
+ if( pAutoSubMenu )
+ {
+ ((PopupMenu*)pAutoSubMenu)->pRefAutoSubMenu = NULL;
+ delete pAutoSubMenu;
+ pAutoSubMenu = NULL;
+ }
+ if( pSalMenuItem )
+ ImplGetSVData()->mpDefInst->DestroyMenuItem( pSalMenuItem );
+}
+
+class MenuItemList : public List
+{
+private:
+ uno::Reference< i18n::XCharacterClassification > xCharClass;
+
+
+public:
+ MenuItemList() : List( 16, 4 ) {}
+ ~MenuItemList();
+
+ MenuItemData* Insert( USHORT nId, MenuItemType eType, MenuItemBits nBits,
+ const XubString& rStr, const Image& rImage,
+ Menu* pMenu, USHORT nPos );
+ void InsertSeparator( USHORT nPos );
+ void Remove( USHORT nPos );
+
+
+ MenuItemData* GetData( USHORT nSVId, USHORT& rPos ) const;
+ MenuItemData* GetData( USHORT nSVId ) const
+ { USHORT nTemp; return GetData( nSVId, nTemp ); }
+ MenuItemData* GetDataFromPos( ULONG nPos ) const
+ { return (MenuItemData*)List::GetObject( nPos ); }
+
+ MenuItemData* SearchItem( xub_Unicode cSelectChar, KeyCode aKeyCode, USHORT& rPos, USHORT& nDuplicates, USHORT nCurrentPos ) const;
+ USHORT GetItemCount( xub_Unicode cSelectChar ) const;
+ USHORT GetItemCount( KeyCode aKeyCode ) const;
+
+ uno::Reference< i18n::XCharacterClassification > GetCharClass() const;
+};
+
+
+
+MenuItemList::~MenuItemList()
+{
+ for ( ULONG n = Count(); n; )
+ {
+ MenuItemData* pData = GetDataFromPos( --n );
+ delete pData;
+ }
+}
+
+MenuItemData* MenuItemList::Insert( USHORT nId, MenuItemType eType,
+ MenuItemBits nBits,
+ const XubString& rStr, const Image& rImage,
+ Menu* pMenu, USHORT nPos )
+{
+ MenuItemData* pData = new MenuItemData( rStr, rImage );
+ pData->nId = nId;
+ pData->eType = eType;
+ pData->nBits = nBits;
+ pData->pSubMenu = NULL;
+ pData->pAutoSubMenu = NULL;
+ pData->nHelpId = 0;
+ pData->nUserValue = 0;
+ pData->bChecked = FALSE;
+ pData->bEnabled = TRUE;
+ pData->bVisible = TRUE;
+ pData->bIsTemporary = FALSE;
+ pData->bMirrorMode = FALSE;
+ pData->nItemImageAngle = 0;
+
+ SalItemParams aSalMIData;
+ aSalMIData.nId = nId;
+ aSalMIData.eType = eType;
+ aSalMIData.nBits = nBits;
+ aSalMIData.pMenu = pMenu;
+ aSalMIData.aText = rStr;
+ aSalMIData.aImage = rImage;
+
+ // Native-support: returns NULL if not supported
+ pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
+
+ List::Insert( (void*)pData, nPos );
+ return pData;
+}
+
+void MenuItemList::InsertSeparator( USHORT nPos )
+{
+ MenuItemData* pData = new MenuItemData;
+ pData->nId = 0;
+ pData->eType = MENUITEM_SEPARATOR;
+ pData->nBits = 0;
+ pData->pSubMenu = NULL;
+ pData->pAutoSubMenu = NULL;
+ pData->nHelpId = 0;
+ pData->nUserValue = 0;
+ pData->bChecked = FALSE;
+ pData->bEnabled = TRUE;
+ pData->bVisible = TRUE;
+ pData->bIsTemporary = FALSE;
+ pData->bMirrorMode = FALSE;
+ pData->nItemImageAngle = 0;
+
+ SalItemParams aSalMIData;
+ aSalMIData.nId = 0;
+ aSalMIData.eType = MENUITEM_SEPARATOR;
+ aSalMIData.nBits = 0;
+ aSalMIData.pMenu = NULL;
+ aSalMIData.aText = XubString();
+ aSalMIData.aImage = Image();
+
+ // Native-support: returns NULL if not supported
+ pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
+
+ List::Insert( (void*)pData, nPos );
+}
+
+void MenuItemList::Remove( USHORT nPos )
+{
+ MenuItemData* pData = (MenuItemData*)List::Remove( (ULONG)nPos );
+ if ( pData )
+ delete pData;
+}
+
+MenuItemData* MenuItemList::GetData( USHORT nSVId, USHORT& rPos ) const
+{
+ rPos = 0;
+ MenuItemData* pData = (MenuItemData*)GetObject( rPos );
+ while ( pData )
+ {
+ if ( pData->nId == nSVId )
+ return pData;
+
+ rPos++;
+ pData = (MenuItemData*)GetObject( rPos );
+ }
+
+ return NULL;
+}
+
+MenuItemData* MenuItemList::SearchItem( xub_Unicode cSelectChar, KeyCode aKeyCode, USHORT& rPos, USHORT& nDuplicates, USHORT nCurrentPos ) const
+{
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+
+ USHORT nListCount = (USHORT)Count();
+
+ // try character code first
+ nDuplicates = GetItemCount( cSelectChar ); // return number of duplicates
+ if( nDuplicates )
+ {
+ for ( rPos = 0; rPos < nListCount; rPos++)
+ {
+ MenuItemData* pData = GetDataFromPos( rPos );
+ if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
+ {
+ if( nDuplicates > 1 && rPos == nCurrentPos )
+ continue; // select next entry with the same mnemonic
+ else
+ return pData;
+ }
+ }
+ }
+
+ // nothing found, try keycode instead
+ nDuplicates = GetItemCount( aKeyCode ); // return number of duplicates
+
+ if( nDuplicates )
+ {
+ char ascii = 0;
+ if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
+ ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
+
+ for ( rPos = 0; rPos < nListCount; rPos++)
+ {
+ MenuItemData* pData = GetDataFromPos( rPos );
+ if ( pData->bEnabled )
+ {
+ USHORT n = pData->aText.Search( '~' );
+ if ( n != STRING_NOTFOUND )
+ {
+ KeyCode mnKeyCode;
+ xub_Unicode mnUnicode = pData->aText.GetChar(n+1);
+ Window* pDefWindow = ImplGetDefaultWindow();
+ if( (pDefWindow && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( mnUnicode, Application::GetSettings().GetUILanguage(), mnKeyCode )
+ && aKeyCode.GetCode() == mnKeyCode.GetCode())
+ || (ascii && rI18nHelper.MatchMnemonic( pData->aText, ascii ) ) )
+
+ {
+ if( nDuplicates > 1 && rPos == nCurrentPos )
+ continue; // select next entry with the same mnemonic
+ else
+ return pData;
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+USHORT MenuItemList::GetItemCount( xub_Unicode cSelectChar ) const
+{
+ // returns number of entries with same mnemonic
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+
+ USHORT nItems = 0, nPos;
+ for ( nPos = (USHORT)Count(); nPos; )
+ {
+ MenuItemData* pData = GetDataFromPos( --nPos );
+ if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
+ nItems++;
+ }
+
+ return nItems;
+}
+
+USHORT MenuItemList::GetItemCount( KeyCode aKeyCode ) const
+{
+ // returns number of entries with same mnemonic
+ // uses key codes instead of character codes
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+ char ascii = 0;
+ if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
+ ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
+
+ USHORT nItems = 0, nPos;
+ for ( nPos = (USHORT)Count(); nPos; )
+ {
+ MenuItemData* pData = GetDataFromPos( --nPos );
+ if ( pData->bEnabled )
+ {
+ USHORT n = pData->aText.Search( '~' );
+ if ( n != STRING_NOTFOUND )
+ {
+ KeyCode mnKeyCode;
+ // if MapUnicodeToKeyCode fails or is unsupported we try the pure ascii mapping of the keycodes
+ // so we have working shortcuts when ascii mnemonics are used
+ Window* pDefWindow = ImplGetDefaultWindow();
+ if( (pDefWindow && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( pData->aText.GetChar(n+1), Application::GetSettings().GetUILanguage(), mnKeyCode )
+ && aKeyCode.GetCode() == mnKeyCode.GetCode())
+ || ( ascii && rI18nHelper.MatchMnemonic( pData->aText, ascii ) ) )
+ nItems++;
+ }
+ }
+ }
+
+ return nItems;
+}
+
+uno::Reference< i18n::XCharacterClassification > MenuItemList::GetCharClass() const
+{
+ if ( !xCharClass.is() )
+ ((MenuItemList*)this)->xCharClass = vcl::unohelper::CreateCharacterClassification();
+ return xCharClass;
+}
+
+
+
+// ----------------------
+// - MenuFloatingWindow -
+// ----------------------
+
+class MenuFloatingWindow : public FloatingWindow
+{
+ friend void Menu::ImplFillLayoutData() const;
+ friend Menu::~Menu();
+
+private:
+ Menu* pMenu;
+ PopupMenu* pActivePopup;
+ Timer aHighlightChangedTimer;
+ Timer aSubmenuCloseTimer;
+ Timer aScrollTimer;
+ ULONG nSaveFocusId;
+// long nStartY;
+ USHORT nHighlightedItem; // gehighlightetes/selektiertes Item
+ USHORT nMBDownPos;
+ USHORT nScrollerHeight;
+ USHORT nFirstEntry;
+ USHORT nBorder;
+ USHORT nPosInParent;
+ BOOL bInExecute;
+
+ BOOL bScrollMenu;
+ BOOL bScrollUp;
+ BOOL bScrollDown;
+ BOOL bIgnoreFirstMove;
+ BOOL bKeyInput;
+
+ DECL_LINK( PopupEnd, FloatingWindow* );
+ DECL_LINK( HighlightChanged, Timer* );
+ DECL_LINK( SubmenuClose, Timer* );
+ DECL_LINK( AutoScroll, Timer* );
+ DECL_LINK( ShowHideListener, VclWindowEvent* );
+
+ void StateChanged( StateChangedType nType );
+ void DataChanged( const DataChangedEvent& rDCEvt );
+protected:
+ Region ImplCalcClipRegion( BOOL bIncludeLogo = TRUE ) const;
+ void ImplInitClipRegion();
+ void ImplDrawScroller( BOOL bUp );
+ using Window::ImplScroll;
+ void ImplScroll( const Point& rMousePos );
+ void ImplScroll( BOOL bUp );
+ void ImplCursorUpDown( BOOL bUp, BOOL bHomeEnd = FALSE );
+ void ImplHighlightItem( const MouseEvent& rMEvt, BOOL bMBDown );
+ long ImplGetStartY() const;
+ Rectangle ImplGetItemRect( USHORT nPos );
+
+public:
+ MenuFloatingWindow( Menu* pMenu, Window* pParent, WinBits nStyle );
+ ~MenuFloatingWindow();
+
+ void doShutdown();
+
+ virtual void MouseMove( const MouseEvent& rMEvt );
+ virtual void MouseButtonDown( const MouseEvent& rMEvt );
+ virtual void MouseButtonUp( const MouseEvent& rMEvt );
+ virtual void KeyInput( const KeyEvent& rKEvent );
+ virtual void Command( const CommandEvent& rCEvt );
+ virtual void Paint( const Rectangle& rRect );
+ virtual void RequestHelp( const HelpEvent& rHEvt );
+ virtual void Resize();
+
+ void SetFocusId( ULONG nId ) { nSaveFocusId = nId; }
+ ULONG GetFocusId() const { return nSaveFocusId; }
+
+ void EnableScrollMenu( BOOL b );
+ BOOL IsScrollMenu() const { return bScrollMenu; }
+ USHORT GetScrollerHeight() const { return nScrollerHeight; }
+
+ void Execute();
+ void StopExecute( ULONG nFocusId = 0 );
+ void EndExecute();
+ void EndExecute( USHORT nSelectId );
+
+ PopupMenu* GetActivePopup() const { return pActivePopup; }
+ void KillActivePopup( PopupMenu* pThisOnly = NULL );
+
+ void HighlightItem( USHORT nPos, BOOL bHighlight );
+ void ChangeHighlightItem( USHORT n, BOOL bStartPopupTimer );
+ USHORT GetHighlightedItem() const { return nHighlightedItem; }
+
+ void SetPosInParent( USHORT nPos ) { nPosInParent = nPos; }
+ USHORT GetPosInParent() const { return nPosInParent; }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
+};
+
+// To get the transparent mouse-over look, the closer is actually a toolbox
+// overload DataChange to handle style changes correctly
+class DecoToolBox : public ToolBox
+{
+ long lastSize;
+ Size maMinSize;
+
+ using Window::ImplInit;
+public:
+ DecoToolBox( Window* pParent, WinBits nStyle = 0 );
+ DecoToolBox( Window* pParent, const ResId& rResId );
+ void ImplInit();
+
+ void DataChanged( const DataChangedEvent& rDCEvt );
+
+ void SetImages( long nMaxHeight = 0, bool bForce = false );
+
+ void calcMinSize();
+ Size getMinSize();
+
+ Image maImage;
+ Image maImageHC;
+};
+
+DecoToolBox::DecoToolBox( Window* pParent, WinBits nStyle ) :
+ ToolBox( pParent, nStyle )
+{
+ ImplInit();
+}
+DecoToolBox::DecoToolBox( Window* pParent, const ResId& rResId ) :
+ ToolBox( pParent, rResId )
+{
+ ImplInit();
+}
+
+void DecoToolBox::ImplInit()
+{
+ lastSize = -1;
+ calcMinSize();
+}
+
+void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( rDCEvt.GetFlags() & SETTINGS_STYLE )
+ {
+ calcMinSize();
+ SetBackground();
+ SetImages( 0, true);
+ }
+}
+
+void DecoToolBox::calcMinSize()
+{
+ ToolBox aTbx( GetParent() );
+ if( GetItemCount() == 0 )
+ {
+ ResMgr* pResMgr = ImplGetResMgr();
+
+ Bitmap aBitmap;
+ if( pResMgr )
+ aBitmap = Bitmap( ResId( SV_RESID_BITMAP_CLOSEDOC, *pResMgr ) );
+ aTbx.InsertItem( IID_DOCUMENTCLOSE, Image( aBitmap ) );
+ }
+ else
+ {
+ USHORT nItems = GetItemCount();
+ for( USHORT i = 0; i < nItems; i++ )
+ {
+ USHORT nId = GetItemId( i );
+ aTbx.InsertItem( nId, GetItemImage( nId ) );
+ }
+ }
+ aTbx.SetOutStyle( TOOLBOX_STYLE_FLAT );
+ maMinSize = aTbx.CalcWindowSizePixel();
+}
+
+Size DecoToolBox::getMinSize()
+{
+ return maMinSize;
+}
+
+void DecoToolBox::SetImages( long nMaxHeight, bool bForce )
+{
+ long border = getMinSize().Height() - maImage.GetSizePixel().Height();
+
+ if( !nMaxHeight && lastSize != -1 )
+ nMaxHeight = lastSize + border; // don't change anything if called with 0
+
+ if( nMaxHeight < getMinSize().Height() )
+ nMaxHeight = getMinSize().Height();
+
+ if( (lastSize != nMaxHeight - border) || bForce )
+ {
+ lastSize = nMaxHeight - border;
+
+ Color aEraseColor( 255, 255, 255, 255 );
+ BitmapEx aBmpExDst( maImage.GetBitmapEx() );
+ BitmapEx aBmpExSrc( GetSettings().GetStyleSettings().GetHighContrastMode() ?
+ maImageHC.GetBitmapEx() : aBmpExDst );
+
+ aEraseColor.SetTransparency( 255 );
+ aBmpExDst.Erase( aEraseColor );
+ aBmpExDst.SetSizePixel( Size( lastSize, lastSize ) );
+
+ Rectangle aSrcRect( Point(0,0), maImage.GetSizePixel() );
+ Rectangle aDestRect( Point((lastSize - maImage.GetSizePixel().Width())/2,
+ (lastSize - maImage.GetSizePixel().Height())/2 ),
+ maImage.GetSizePixel() );
+
+
+ aBmpExDst.CopyPixel( aDestRect, aSrcRect, &aBmpExSrc );
+ SetItemImage( IID_DOCUMENTCLOSE, Image( aBmpExDst ) );
+ }
+}
+
+
+// Eine Basicklasse fuer beide (wegen pActivePopup, Timer, ...) waere nett,
+// aber dann musste eine 'Container'-Klasse gemacht werden, da von
+// unterschiedlichen Windows abgeleitet...
+// In den meisten Funktionen muessen dann sowieso Sonderbehandlungen fuer
+// MenuBar, PopupMenu gemacht werden, also doch zwei verschiedene Klassen.
+
+class MenuBarWindow : public Window
+{
+ friend class MenuBar;
+ friend class Menu;
+
+private:
+ struct AddButtonEntry
+ {
+ USHORT m_nId;
+ Link m_aSelectLink;
+ Link m_aHighlightLink;
+
+ AddButtonEntry() : m_nId( 0 ) {}
+ };
+
+ Menu* pMenu;
+ PopupMenu* pActivePopup;
+ USHORT nHighlightedItem;
+ ULONG nSaveFocusId;
+ BOOL mbAutoPopup;
+ BOOL bIgnoreFirstMove;
+ BOOL bStayActive;
+
+ DecoToolBox aCloser;
+ PushButton aFloatBtn;
+ PushButton aHideBtn;
+
+ std::map< USHORT, AddButtonEntry > m_aAddButtons;
+
+ void HighlightItem( USHORT nPos, BOOL bHighlight );
+ void ChangeHighlightItem( USHORT n, BOOL bSelectPopupEntry, BOOL bAllowRestoreFocus = TRUE, BOOL bDefaultToDocument = TRUE );
+
+ USHORT ImplFindEntry( const Point& rMousePos ) const;
+ void ImplCreatePopup( BOOL bPreSelectFirst );
+ BOOL ImplHandleKeyEvent( const KeyEvent& rKEvent, BOOL bFromMenu = TRUE );
+ Rectangle ImplGetItemRect( USHORT nPos );
+
+ void ImplInitStyleSettings();
+
+ DECL_LINK( CloserHdl, PushButton* );
+ DECL_LINK( FloatHdl, PushButton* );
+ DECL_LINK( HideHdl, PushButton* );
+ DECL_LINK( ToolboxEventHdl, VclWindowEvent* );
+ DECL_LINK( ShowHideListener, VclWindowEvent* );
+
+ void StateChanged( StateChangedType nType );
+ void DataChanged( const DataChangedEvent& rDCEvt );
+ void LoseFocus();
+ void GetFocus();
+
+public:
+ MenuBarWindow( Window* pParent );
+ ~MenuBarWindow();
+
+ void ShowButtons( BOOL bClose, BOOL bFloat, BOOL bHide );
+
+ virtual void MouseMove( const MouseEvent& rMEvt );
+ virtual void MouseButtonDown( const MouseEvent& rMEvt );
+ virtual void MouseButtonUp( const MouseEvent& rMEvt );
+ virtual void KeyInput( const KeyEvent& rKEvent );
+ virtual void Paint( const Rectangle& rRect );
+ virtual void Resize();
+ virtual void RequestHelp( const HelpEvent& rHEvt );
+
+ void SetFocusId( ULONG nId ) { nSaveFocusId = nId; }
+ ULONG GetFocusId() const { return nSaveFocusId; }
+
+ void SetMenu( MenuBar* pMenu );
+ void KillActivePopup();
+ PopupMenu* GetActivePopup() const { return pActivePopup; }
+ void PopupClosed( Menu* pMenu );
+ USHORT GetHighlightedItem() const { return nHighlightedItem; }
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
+
+ void SetAutoPopup( BOOL bAuto ) { mbAutoPopup = bAuto; }
+ void ImplLayoutChanged();
+ Size MinCloseButtonSize();
+
+ // add an arbitrary button to the menubar (will appear next to closer)
+ USHORT AddMenuBarButton( const Image&, const Link&, const String&, USHORT nPos );
+ void SetMenuBarButtonHighlightHdl( USHORT nId, const Link& );
+ Rectangle GetMenuBarButtonRectPixel( USHORT nId );
+ void RemoveMenuBarButton( USHORT nId );
+ bool HandleMenuButtonEvent( USHORT i_nButtonId );
+};
+
+static void ImplAddNWFSeparator( Window *pThis, const MenubarValue& rMenubarValue )
+{
+ // add a separator if
+ // - we have an adjacent docking area
+ // - and if toolbars would draw them as well (mbDockingAreaSeparateTB must not be set, see dockingarea.cxx)
+ if( rMenubarValue.maTopDockingAreaHeight && !ImplGetSVData()->maNWFData.mbDockingAreaSeparateTB )
+ {
+ // note: the menubar only provides the upper (dark) half of it, the rest (bright part) is drawn by the docking area
+
+ pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetSeparatorColor() );
+ Point aPt;
+ Rectangle aRect( aPt, pThis->GetOutputSizePixel() );
+ pThis->DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
+ }
+}
+
+static void ImplSetMenuItemData( MenuItemData* pData )
+{
+ // Daten umsetzen
+ if ( !pData->aImage )
+ pData->eType = MENUITEM_STRING;
+ else if ( !pData->aText.Len() )
+ pData->eType = MENUITEM_IMAGE;
+ else
+ pData->eType = MENUITEM_STRINGIMAGE;
+}
+
+static ULONG ImplChangeTipTimeout( ULONG nTimeout, Window *pWindow )
+{
+ AllSettings aAllSettings( pWindow->GetSettings() );
+ HelpSettings aHelpSettings( aAllSettings.GetHelpSettings() );
+ ULONG nRet = aHelpSettings.GetTipTimeout();
+ aHelpSettings.SetTipTimeout( nTimeout );
+ aAllSettings.SetHelpSettings( aHelpSettings );
+ pWindow->SetSettings( aAllSettings );
+ return nRet;
+}
+
+static BOOL ImplHandleHelpEvent( Window* pMenuWindow, Menu* pMenu, USHORT nHighlightedItem, const HelpEvent& rHEvt, const Rectangle &rHighlightRect )
+{
+ if( ! pMenu )
+ return FALSE;
+
+ BOOL bDone = FALSE;
+ USHORT nId = 0;
+
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ {
+ MenuItemData* pItemData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
+ if ( pItemData )
+ nId = pItemData->nId;
+ }
+
+ if ( ( rHEvt.GetMode() & HELPMODE_BALLOON ) && pMenuWindow )
+ {
+ Point aPos;
+ if( rHEvt.KeyboardActivated() )
+ aPos = rHighlightRect.Center();
+ else
+ aPos = rHEvt.GetMousePosPixel();
+
+ Rectangle aRect( aPos, Size() );
+ if( pMenu->GetHelpText( nId ).Len() )
+ Help::ShowBalloon( pMenuWindow, aPos, pMenu->GetHelpText( nId ) );
+ else
+ {
+ // give user a chance to read the full filename
+ ULONG oldTimeout=ImplChangeTipTimeout( 60000, pMenuWindow );
+ // call always, even when strlen==0 to correctly remove tip
+ Help::ShowQuickHelp( pMenuWindow, aRect, pMenu->GetTipHelpText( nId ) );
+ ImplChangeTipTimeout( oldTimeout, pMenuWindow );
+ }
+ bDone = TRUE;
+ }
+ else if ( ( rHEvt.GetMode() & HELPMODE_QUICK ) && pMenuWindow )
+ {
+ Point aPos = rHEvt.GetMousePosPixel();
+ Rectangle aRect( aPos, Size() );
+ // give user a chance to read the full filename
+ ULONG oldTimeout=ImplChangeTipTimeout( 60000, pMenuWindow );
+ // call always, even when strlen==0 to correctly remove tip
+ Help::ShowQuickHelp( pMenuWindow, aRect, pMenu->GetTipHelpText( nId ) );
+ ImplChangeTipTimeout( oldTimeout, pMenuWindow );
+ bDone = TRUE;
+ }
+ else if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
+ {
+ // Ist eine Hilfe in die Applikation selektiert
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ // Ist eine ID vorhanden, dann Hilfe mit der ID aufrufen, sonst
+ // den Hilfe-Index
+ String aCommand = pMenu->GetItemCommand( nId );
+ ULONG nHelpId = pMenu->GetHelpId( nId );
+
+ if ( aCommand.Len() )
+ pHelp->Start( aCommand, NULL );
+ else if ( nHelpId )
+ pHelp->Start( nHelpId, NULL );
+ else
+ pHelp->Start( OOO_HELP_INDEX, NULL );
+ }
+ bDone = TRUE;
+ }
+ return bDone;
+}
+
+static int ImplGetTopDockingAreaHeight( Window *pWindow )
+{
+ // find docking area that is top aligned and return its height
+ // note: dockingareas are direct children of the SystemWindow
+ int height=0;
+ BOOL bDone = FALSE;
+ if( pWindow->ImplGetFrameWindow() )
+ {
+ Window *pWin = pWindow->ImplGetFrameWindow()->GetWindow( WINDOW_FIRSTCHILD); //mpWindowImpl->mpFirstChild;
+ while( pWin && !bDone )
+ {
+ if( pWin->IsSystemWindow() )
+ {
+ pWin = pWin->GetWindow( WINDOW_FIRSTCHILD); //mpWindowImpl->mpFirstChild;
+ while( pWin && !bDone )
+ {
+ DockingAreaWindow *pDockingArea = dynamic_cast< DockingAreaWindow* >( pWin );
+ if( pDockingArea && pDockingArea->GetAlign() == WINDOWALIGN_TOP )
+ {
+ bDone = TRUE;
+ if( pDockingArea->IsVisible() )
+ height = pDockingArea->GetOutputSizePixel().Height();
+ }
+ else
+ pWin = pWin->GetWindow( WINDOW_NEXT ); //mpWindowImpl->mpNext;
+ }
+
+ }
+ else
+ pWin = pWin->GetWindow( WINDOW_NEXT ); //mpWindowImpl->mpNext;
+ }
+ }
+ return height;
+}
+
+Menu::Menu()
+{
+ DBG_CTOR( Menu, NULL );
+ bIsMenuBar = FALSE;
+ ImplInit();
+}
+
+// this constructor makes sure we're creating the native menu
+// with the correct type (ie, MenuBar vs. PopupMenu)
+Menu::Menu( BOOL bMenubar )
+{
+ DBG_CTOR( Menu, NULL );
+ bIsMenuBar = bMenubar;
+ ImplInit();
+}
+
+Menu::~Menu()
+{
+ DBG_DTOR( Menu, NULL );
+
+ vcl::LazyDeletor<Menu>::Undelete( this );
+
+ ImplCallEventListeners( VCLEVENT_OBJECT_DYING, ITEMPOS_INVALID );
+
+ // at the window free the reference to the accessible component
+ // and make sure the MenuFloatingWindow knows about our destruction
+ if ( pWindow )
+ {
+ MenuFloatingWindow* pFloat = (MenuFloatingWindow*)pWindow;
+ if( pFloat->pMenu == this )
+ pFloat->pMenu = NULL;
+ pWindow->SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
+ }
+
+ // dispose accessible components
+ if ( mxAccessible.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xComponent( mxAccessible, ::com::sun::star::uno::UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+
+ if ( nEventId )
+ Application::RemoveUserEvent( nEventId );
+
+ // Notify deletion of this menu
+ ImplMenuDelData* pDelData = mpFirstDel;
+ while ( pDelData )
+ {
+ pDelData->mpMenu = NULL;
+ pDelData = pDelData->mpNext;
+ }
+
+ bKilled = TRUE;
+
+ delete pItemList;
+ delete pLogo;
+ delete mpLayoutData;
+
+ // Native-support: destroy SalMenu
+ ImplSetSalMenu( NULL );
+}
+
+void Menu::doLazyDelete()
+{
+ vcl::LazyDeletor<Menu>::Delete( this );
+}
+
+void Menu::ImplInit()
+{
+ mnHighlightedItemPos = ITEMPOS_INVALID;
+ mpSalMenu = NULL;
+ nMenuFlags = MENU_FLAG_SHOWCHECKIMAGES;
+ nDefaultItem = 0;
+ //bIsMenuBar = FALSE; // this is now set in the ctor, must not be changed here!!!
+ nSelectedId = 0;
+ pItemList = new MenuItemList;
+ pLogo = NULL;
+ pStartedFrom = NULL;
+ pWindow = NULL;
+ nEventId = 0;
+ bCanceled = FALSE;
+ bInCallback = FALSE;
+ bKilled = FALSE;
+ mpLayoutData = NULL;
+ mpFirstDel = NULL; // Dtor notification list
+ // Native-support: returns NULL if not supported
+ mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu( bIsMenuBar );
+}
+
+Menu* Menu::ImplGetStartedFrom() const
+{
+ return pStartedFrom;
+}
+
+void Menu::ImplLoadRes( const ResId& rResId )
+{
+ ResMgr* pMgr = rResId.GetResMgr();
+ if( ! pMgr )
+ return;
+
+ rResId.SetRT( RSC_MENU );
+ GetRes( rResId );
+
+ ULONG nObjMask = ReadLongRes();
+
+ if( nObjMask & RSC_MENU_ITEMS )
+ {
+ ULONG nObjFollows = ReadLongRes();
+ // MenuItems einfuegen
+ for( ULONG i = 0; i < nObjFollows; i++ )
+ {
+ InsertItem( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+ }
+
+ if( nObjMask & RSC_MENU_TEXT )
+ {
+ if( bIsMenuBar ) // Kein Titel im Menubar
+ ReadStringRes();
+ else
+ aTitleText = ReadStringRes();
+ }
+ if( nObjMask & RSC_MENU_DEFAULTITEMID )
+ SetDefaultItem( sal::static_int_cast<USHORT>(ReadLongRes()) );
+}
+
+void Menu::CreateAutoMnemonics()
+{
+ MnemonicGenerator aMnemonicGenerator;
+ ULONG n;
+ for ( n = 0; n < pItemList->Count(); n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos(n);
+ if ( ! (pData->nBits & MIB_NOSELECT ) )
+ aMnemonicGenerator.RegisterMnemonic( pData->aText );
+ }
+ for ( n = 0; n < pItemList->Count(); n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos(n);
+ if ( ! (pData->nBits & MIB_NOSELECT ) )
+ aMnemonicGenerator.CreateMnemonic( pData->aText );
+ }
+}
+
+void Menu::Activate()
+{
+ bInCallback = TRUE;
+
+ ImplMenuDelData aDelData( this );
+
+ ImplCallEventListeners( VCLEVENT_MENU_ACTIVATE, ITEMPOS_INVALID );
+
+ if( !aDelData.isDeleted() )
+ {
+ if ( !aActivateHdl.Call( this ) )
+ {
+ if( !aDelData.isDeleted() )
+ {
+ Menu* pStartMenu = ImplGetStartMenu();
+ if ( pStartMenu && ( pStartMenu != this ) )
+ {
+ pStartMenu->bInCallback = TRUE;
+ // MT 11/01: Call EventListener here? I don't know...
+ pStartMenu->aActivateHdl.Call( this );
+ pStartMenu->bInCallback = FALSE;
+ }
+ }
+ }
+ bInCallback = FALSE;
+ }
+}
+
+void Menu::Deactivate()
+{
+ for ( USHORT n = (USHORT)pItemList->Count(); n; )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( --n );
+ if ( pData->bIsTemporary )
+ pItemList->Remove( n );
+ }
+
+ bInCallback = TRUE;
+
+ ImplMenuDelData aDelData( this );
+
+ Menu* pStartMenu = ImplGetStartMenu();
+ ImplCallEventListeners( VCLEVENT_MENU_DEACTIVATE, ITEMPOS_INVALID );
+
+ if( !aDelData.isDeleted() )
+ {
+ if ( !aDeactivateHdl.Call( this ) )
+ {
+ if( !aDelData.isDeleted() )
+ {
+ if ( pStartMenu && ( pStartMenu != this ) )
+ {
+ pStartMenu->bInCallback = TRUE;
+ pStartMenu->aDeactivateHdl.Call( this );
+ pStartMenu->bInCallback = FALSE;
+ }
+ }
+ }
+ }
+
+ if( !aDelData.isDeleted() )
+ {
+ bInCallback = FALSE;
+
+ if ( this == pStartMenu )
+ GetpApp()->HideHelpStatusText();
+ }
+}
+
+void Menu::Highlight()
+{
+ ImplMenuDelData aDelData( this );
+
+ Menu* pStartMenu = ImplGetStartMenu();
+ if ( !aHighlightHdl.Call( this ) && !aDelData.isDeleted() )
+ {
+ if ( pStartMenu && ( pStartMenu != this ) )
+ pStartMenu->aHighlightHdl.Call( this );
+ }
+
+ if ( !aDelData.isDeleted() && GetCurItemId() )
+ GetpApp()->ShowHelpStatusText( GetHelpText( GetCurItemId() ) );
+}
+
+void Menu::ImplSelect()
+{
+ MenuItemData* pData = GetItemList()->GetData( nSelectedId );
+ if ( pData && (pData->nBits & MIB_AUTOCHECK) )
+ {
+ BOOL bChecked = IsItemChecked( nSelectedId );
+ if ( pData->nBits & MIB_RADIOCHECK )
+ {
+ if ( !bChecked )
+ CheckItem( nSelectedId, TRUE );
+ }
+ else
+ CheckItem( nSelectedId, !bChecked );
+ }
+
+ // Select rufen
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maAppData.mpActivePopupMenu = NULL; // Falls neues Execute im Select()
+ Application::PostUserEvent( nEventId, LINK( this, Menu, ImplCallSelect ) );
+}
+
+void Menu::Select()
+{
+ ImplMenuDelData aDelData( this );
+
+ ImplCallEventListeners( VCLEVENT_MENU_SELECT, GetItemPos( GetCurItemId() ) );
+ if ( !aDelData.isDeleted() && !aSelectHdl.Call( this ) )
+ {
+ if( !aDelData.isDeleted() )
+ {
+ Menu* pStartMenu = ImplGetStartMenu();
+ if ( pStartMenu && ( pStartMenu != this ) )
+ {
+ pStartMenu->nSelectedId = nSelectedId;
+ pStartMenu->aSelectHdl.Call( this );
+ }
+ }
+ }
+}
+
+void Menu::ImplSelectWithStart( Menu* pSMenu )
+{
+ Menu* pOldStartedFrom = pStartedFrom;
+ pStartedFrom = pSMenu;
+ Menu* pOldStartedStarted = pOldStartedFrom ? pOldStartedFrom->pStartedFrom : NULL;
+ Select();
+ if( pOldStartedFrom )
+ pOldStartedFrom->pStartedFrom = pOldStartedStarted;
+ pStartedFrom = pOldStartedFrom;
+}
+
+void Menu::RequestHelp( const HelpEvent& )
+{
+}
+
+void Menu::ImplCallEventListeners( ULONG nEvent, USHORT nPos )
+{
+ ImplMenuDelData aDelData( this );
+
+ VclMenuEvent aEvent( this, nEvent, nPos );
+
+ // This is needed by atk accessibility bridge
+ if ( nEvent == VCLEVENT_MENU_HIGHLIGHT )
+ {
+ ImplGetSVData()->mpApp->ImplCallEventListeners( &aEvent );
+ }
+
+ if ( !aDelData.isDeleted() && !maEventListeners.empty() )
+ maEventListeners.Call( &aEvent );
+
+ if( !aDelData.isDeleted() )
+ {
+ Menu* pMenu = this;
+ while ( pMenu )
+ {
+ if ( !maChildEventListeners.empty() )
+ maChildEventListeners.Call( &aEvent );
+
+ if( aDelData.isDeleted() )
+ break;
+
+ pMenu = ( pMenu->pStartedFrom != pMenu ) ? pMenu->pStartedFrom : NULL;
+ }
+ }
+}
+
+void Menu::AddEventListener( const Link& rEventListener )
+{
+ maEventListeners.push_back( rEventListener );
+}
+
+void Menu::RemoveEventListener( const Link& rEventListener )
+{
+ maEventListeners.remove( rEventListener );
+}
+
+// -----------------------------------------------------------------------
+
+//void Menu::AddChildEventListener( const Link& rEventListener )
+//{
+// mpDummy4_WindowChildEventListeners->push_back( rEventListener );
+//}
+
+// -----------------------------------------------------------------------
+
+//void Menu::RemoveChildEventListener( const Link& rEventListener )
+//{
+// mpDummy4_WindowChildEventListeners->remove( rEventListener );
+//}
+
+void Menu::InsertItem( USHORT nItemId, const XubString& rStr, MenuItemBits nItemBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "Menu::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == MENU_ITEM_NOTFOUND,
+ "Menu::InsertItem(): ItemId already exists" );
+
+ // if Position > ItemCount, append
+ if ( nPos >= (USHORT)pItemList->Count() )
+ nPos = MENU_APPEND;
+
+ // put Item in MenuItemList
+ MenuItemData* pData = pItemList->Insert( nItemId, MENUITEM_STRING,
+ nItemBits, rStr, Image(), this, nPos );
+
+ // update native menu
+ if( ImplGetSalMenu() && pData->pSalMenuItem )
+ ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
+
+ Window* pWin = ImplGetWindow();
+ delete mpLayoutData, mpLayoutData = NULL;
+ if ( pWin )
+ {
+ ImplCalcSize( pWin );
+ if ( pWin->IsVisible() )
+ pWin->Invalidate();
+ }
+ ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
+}
+
+void Menu::InsertItem( USHORT nItemId, const Image& rImage,
+ MenuItemBits nItemBits, USHORT nPos )
+{
+ InsertItem( nItemId, ImplGetSVEmptyStr(), nItemBits, nPos );
+ SetItemImage( nItemId, rImage );
+}
+
+void Menu::InsertItem( USHORT nItemId,
+ const XubString& rStr, const Image& rImage,
+ MenuItemBits nItemBits, USHORT nPos )
+{
+ InsertItem( nItemId, rStr, nItemBits, nPos );
+ SetItemImage( nItemId, rImage );
+}
+
+void Menu::InsertItem( const ResId& rResId, USHORT nPos )
+{
+ ResMgr* pMgr = rResId.GetResMgr();
+ if( ! pMgr )
+ return;
+
+ ULONG nObjMask;
+
+ GetRes( rResId.SetRT( RSC_MENUITEM ) );
+ nObjMask = ReadLongRes();
+
+ BOOL bSep = FALSE;
+ if ( nObjMask & RSC_MENUITEM_SEPARATOR )
+ bSep = (BOOL)ReadShortRes();
+
+ USHORT nItemId = 1;
+ if ( nObjMask & RSC_MENUITEM_ID )
+ nItemId = sal::static_int_cast<USHORT>(ReadLongRes());
+
+ MenuItemBits nStatus = 0;
+ if ( nObjMask & RSC_MENUITEM_STATUS )
+ nStatus = sal::static_int_cast<MenuItemBits>(ReadLongRes());
+
+ String aText;
+ if ( nObjMask & RSC_MENUITEM_TEXT )
+ aText = ReadStringRes();
+
+ // Item erzeugen
+ if ( nObjMask & RSC_MENUITEM_BITMAP )
+ {
+ if ( !bSep )
+ {
+ Bitmap aBmp( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
+ if ( aText.Len() )
+ InsertItem( nItemId, aText, aBmp, nStatus, nPos );
+ else
+ InsertItem( nItemId, aBmp, nStatus, nPos );
+ }
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+ else if ( !bSep )
+ InsertItem( nItemId, aText, nStatus, nPos );
+ if ( bSep )
+ InsertSeparator( nPos );
+
+ String aHelpText;
+ if ( nObjMask & RSC_MENUITEM_HELPTEXT )
+ {
+ aHelpText = ReadStringRes();
+ if( !bSep )
+ SetHelpText( nItemId, aHelpText );
+ }
+
+ ULONG nHelpId = 0;
+ if ( nObjMask & RSC_MENUITEM_HELPID )
+ {
+ nHelpId = ReadLongRes();
+ if ( !bSep )
+ SetHelpId( nItemId, nHelpId );
+ }
+
+ if( !bSep /* && SvHelpSettings::HelpText( aHelpText, nHelpId ) */ )
+ SetHelpText( nItemId, aHelpText );
+
+ if ( nObjMask & RSC_MENUITEM_KEYCODE )
+ {
+ if ( !bSep )
+ SetAccelKey( nItemId, KeyCode( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+ if( nObjMask & RSC_MENUITEM_CHECKED )
+ {
+ if ( !bSep )
+ CheckItem( nItemId, (BOOL)ReadShortRes() );
+ }
+ if ( nObjMask & RSC_MENUITEM_DISABLE )
+ {
+ if ( !bSep )
+ EnableItem( nItemId, !(BOOL)ReadShortRes() );
+ }
+ if ( nObjMask & RSC_MENUITEM_COMMAND )
+ {
+ String aCommandStr = ReadStringRes();
+ if ( !bSep )
+ SetItemCommand( nItemId, aCommandStr );
+ }
+ if ( nObjMask & RSC_MENUITEM_MENU )
+ {
+ if ( !bSep )
+ {
+ MenuItemData* pData = GetItemList()->GetData( nItemId );
+ if ( pData )
+ {
+ PopupMenu* pSubMenu = new PopupMenu( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
+ pData->pAutoSubMenu = pSubMenu;
+ // #111060# keep track of this pointer, may be it will be deleted from outside
+ pSubMenu->pRefAutoSubMenu = &pData->pAutoSubMenu;
+ SetPopupMenu( nItemId, pSubMenu );
+ }
+ }
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+ delete mpLayoutData, mpLayoutData = NULL;
+}
+
+void Menu::InsertSeparator( USHORT nPos )
+{
+ // do nothing if its a menu bar
+ if ( bIsMenuBar )
+ return;
+
+ // if position > ItemCount, append
+ if ( nPos >= (USHORT)pItemList->Count() )
+ nPos = MENU_APPEND;
+
+ // put separator in item list
+ pItemList->InsertSeparator( nPos );
+
+ // update native menu
+ USHORT itemPos = nPos != MENU_APPEND ? nPos : (USHORT)pItemList->Count() - 1;
+ MenuItemData *pData = pItemList->GetDataFromPos( itemPos );
+ if( ImplGetSalMenu() && pData && pData->pSalMenuItem )
+ ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
+
+ delete mpLayoutData, mpLayoutData = NULL;
+
+ ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
+}
+
+void Menu::RemoveItem( USHORT nPos )
+{
+ BOOL bRemove = FALSE;
+
+ if ( nPos < GetItemCount() )
+ {
+ // update native menu
+ if( ImplGetSalMenu() )
+ ImplGetSalMenu()->RemoveItem( nPos );
+
+ pItemList->Remove( nPos );
+ bRemove = TRUE;
+ }
+
+ Window* pWin = ImplGetWindow();
+ if ( pWin )
+ {
+ ImplCalcSize( pWin );
+ if ( pWin->IsVisible() )
+ pWin->Invalidate();
+ }
+ delete mpLayoutData, mpLayoutData = NULL;
+
+ if ( bRemove )
+ ImplCallEventListeners( VCLEVENT_MENU_REMOVEITEM, nPos );
+}
+
+void ImplCopyItem( Menu* pThis, const Menu& rMenu, USHORT nPos, USHORT nNewPos,
+ USHORT nMode = 0 )
+{
+ MenuItemType eType = rMenu.GetItemType( nPos );
+
+ if ( eType == MENUITEM_DONTKNOW )
+ return;
+
+ if ( eType == MENUITEM_SEPARATOR )
+ pThis->InsertSeparator( nNewPos );
+ else
+ {
+ USHORT nId = rMenu.GetItemId( nPos );
+
+ DBG_ASSERT( pThis->GetItemPos( nId ) == MENU_ITEM_NOTFOUND,
+ "Menu::CopyItem(): ItemId already exists" );
+
+ MenuItemData* pData = rMenu.GetItemList()->GetData( nId );
+
+ if ( eType == MENUITEM_STRINGIMAGE )
+ pThis->InsertItem( nId, pData->aText, pData->aImage, pData->nBits, nNewPos );
+ else if ( eType == MENUITEM_STRING )
+ pThis->InsertItem( nId, pData->aText, pData->nBits, nNewPos );
+ else
+ pThis->InsertItem( nId, pData->aImage, pData->nBits, nNewPos );
+
+ if ( rMenu.IsItemChecked( nId ) )
+ pThis->CheckItem( nId, TRUE );
+ if ( !rMenu.IsItemEnabled( nId ) )
+ pThis->EnableItem( nId, FALSE );
+ pThis->SetHelpId( nId, pData->nHelpId );
+ pThis->SetHelpText( nId, pData->aHelpText );
+ pThis->SetAccelKey( nId, pData->aAccelKey );
+ pThis->SetItemCommand( nId, pData->aCommandStr );
+ pThis->SetHelpCommand( nId, pData->aHelpCommandStr );
+
+ PopupMenu* pSubMenu = rMenu.GetPopupMenu( nId );
+ if ( pSubMenu )
+ {
+ // AutoKopie anlegen
+ if ( nMode == 1 )
+ {
+ PopupMenu* pNewMenu = new PopupMenu( *pSubMenu );
+ pThis->SetPopupMenu( nId, pNewMenu );
+// SetAutoMenu( pThis, nId, pNewMenu );
+ }
+ else
+ pThis->SetPopupMenu( nId, pSubMenu );
+ }
+ }
+}
+
+void Menu::CopyItem( const Menu& rMenu, USHORT nPos, USHORT nNewPos )
+{
+ ImplCopyItem( this, rMenu, nPos, nNewPos );
+}
+
+void Menu::Clear()
+{
+ for ( USHORT i = GetItemCount(); i; i-- )
+ RemoveItem( 0 );
+}
+
+USHORT Menu::GetItemCount() const
+{
+ return (USHORT)pItemList->Count();
+}
+
+USHORT Menu::ImplGetVisibleItemCount() const
+{
+ USHORT nItems = 0;
+ for ( USHORT n = (USHORT)pItemList->Count(); n; )
+ {
+ if ( ImplIsVisible( --n ) )
+ nItems++;
+ }
+ return nItems;
+}
+
+USHORT Menu::ImplGetFirstVisible() const
+{
+ for ( USHORT n = 0; n < pItemList->Count(); n++ )
+ {
+ if ( ImplIsVisible( n ) )
+ return n;
+ }
+ return ITEMPOS_INVALID;
+}
+
+USHORT Menu::ImplGetPrevVisible( USHORT nPos ) const
+{
+ for ( USHORT n = nPos; n; )
+ {
+ if ( n && ImplIsVisible( --n ) )
+ return n;
+ }
+ return ITEMPOS_INVALID;
+}
+
+USHORT Menu::ImplGetNextVisible( USHORT nPos ) const
+{
+ for ( USHORT n = nPos+1; n < pItemList->Count(); n++ )
+ {
+ if ( ImplIsVisible( n ) )
+ return n;
+ }
+ return ITEMPOS_INVALID;
+}
+
+USHORT Menu::GetItemId( USHORT nPos ) const
+{
+ MenuItemData* pData = pItemList->GetDataFromPos( nPos );
+
+ if ( pData )
+ return pData->nId;
+ else
+ return 0;
+}
+
+USHORT Menu::GetItemPos( USHORT nItemId ) const
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData )
+ return nPos;
+ else
+ return MENU_ITEM_NOTFOUND;
+}
+
+MenuItemType Menu::GetItemType( USHORT nPos ) const
+{
+ MenuItemData* pData = pItemList->GetDataFromPos( nPos );
+
+ if ( pData )
+ return pData->eType;
+ else
+ return MENUITEM_DONTKNOW;
+}
+
+USHORT Menu::GetCurItemId() const
+{
+ return nSelectedId;
+}
+
+void Menu::SetItemBits( USHORT nItemId, MenuItemBits nBits )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+ if ( pData )
+ pData->nBits = nBits;
+}
+
+MenuItemBits Menu::GetItemBits( USHORT nItemId ) const
+{
+ MenuItemBits nBits = 0;
+ MenuItemData* pData = pItemList->GetData( nItemId );
+ if ( pData )
+ nBits = pData->nBits;
+ return nBits;
+}
+
+void Menu::SetUserValue( USHORT nItemId, ULONG nValue )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+ if ( pData )
+ pData->nUserValue = nValue;
+}
+
+ULONG Menu::GetUserValue( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+ return pData ? pData->nUserValue : 0;
+}
+
+void Menu::SetPopupMenu( USHORT nItemId, PopupMenu* pMenu )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ // Item does not exist -> return NULL
+ if ( !pData )
+ return;
+
+ // same menu, nothing to do
+ if ( (PopupMenu*)pData->pSubMenu == pMenu )
+ return;
+
+ // data exchange
+ pData->pSubMenu = pMenu;
+
+ // #112023# Make sure pStartedFrom does not point to invalid (old) data
+ if ( pData->pSubMenu )
+ pData->pSubMenu->pStartedFrom = 0;
+
+ // set native submenu
+ if( ImplGetSalMenu() && pData->pSalMenuItem )
+ {
+ if( pMenu )
+ ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, pMenu->ImplGetSalMenu(), nPos );
+ else
+ ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, NULL, nPos );
+ }
+
+ ImplCallEventListeners( VCLEVENT_MENU_SUBMENUCHANGED, nPos );
+}
+
+PopupMenu* Menu::GetPopupMenu( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return (PopupMenu*)(pData->pSubMenu);
+ else
+ return NULL;
+}
+
+void Menu::SetAccelKey( USHORT nItemId, const KeyCode& rKeyCode )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return;
+
+ if ( pData->aAccelKey == rKeyCode )
+ return;
+
+ pData->aAccelKey = rKeyCode;
+
+ // update native menu
+ if( ImplGetSalMenu() && pData->pSalMenuItem )
+ ImplGetSalMenu()->SetAccelerator( nPos, pData->pSalMenuItem, rKeyCode, rKeyCode.GetName() );
+}
+
+KeyCode Menu::GetAccelKey( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aAccelKey;
+ else
+ return KeyCode();
+}
+
+KeyEvent Menu::GetActivationKey( USHORT nItemId ) const
+{
+ KeyEvent aRet;
+ MenuItemData* pData = pItemList->GetData( nItemId );
+ if( pData )
+ {
+ USHORT nPos = pData->aText.Search( '~' );
+ if( nPos != STRING_NOTFOUND && nPos < pData->aText.Len()-1 )
+ {
+ USHORT nCode = 0;
+ sal_Unicode cAccel = pData->aText.GetChar( nPos+1 );
+ if( cAccel >= 'a' && cAccel <= 'z' )
+ nCode = KEY_A + (cAccel-'a');
+ else if( cAccel >= 'A' && cAccel <= 'Z' )
+ nCode = KEY_A + (cAccel-'A');
+ else if( cAccel >= '0' && cAccel <= '9' )
+ nCode = KEY_0 + (cAccel-'0');
+ if(nCode )
+ aRet = KeyEvent( cAccel, KeyCode( nCode, KEY_MOD2 ) );
+ }
+
+ }
+ return aRet;
+}
+
+void Menu::CheckItem( USHORT nItemId, BOOL bCheck )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData || pData->bChecked == bCheck )
+ return;
+
+ // Wenn RadioCheck, dann vorherigen unchecken
+ if ( bCheck && (pData->nBits & MIB_AUTOCHECK) &&
+ (pData->nBits & MIB_RADIOCHECK) )
+ {
+ MenuItemData* pGroupData;
+ USHORT nGroupPos;
+ USHORT nItemCount = GetItemCount();
+ BOOL bFound = FALSE;
+
+ nGroupPos = nPos;
+ while ( nGroupPos )
+ {
+ pGroupData = pItemList->GetDataFromPos( nGroupPos-1 );
+ if ( pGroupData->nBits & MIB_RADIOCHECK )
+ {
+ if ( IsItemChecked( pGroupData->nId ) )
+ {
+ CheckItem( pGroupData->nId, FALSE );
+ bFound = TRUE;
+ break;
+ }
+ }
+ else
+ break;
+ nGroupPos--;
+ }
+
+ if ( !bFound )
+ {
+ nGroupPos = nPos+1;
+ while ( nGroupPos < nItemCount )
+ {
+ pGroupData = pItemList->GetDataFromPos( nGroupPos );
+ if ( pGroupData->nBits & MIB_RADIOCHECK )
+ {
+ if ( IsItemChecked( pGroupData->nId ) )
+ {
+ CheckItem( pGroupData->nId, FALSE );
+ break;
+ }
+ }
+ else
+ break;
+ nGroupPos++;
+ }
+ }
+ }
+
+ pData->bChecked = bCheck;
+
+ // update native menu
+ if( ImplGetSalMenu() )
+ ImplGetSalMenu()->CheckItem( nPos, bCheck );
+
+ ImplCallEventListeners( bCheck ? VCLEVENT_MENU_ITEMCHECKED : VCLEVENT_MENU_ITEMUNCHECKED, nPos );
+}
+
+BOOL Menu::IsItemChecked( USHORT nItemId ) const
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return FALSE;
+
+ return pData->bChecked;
+}
+
+void Menu::EnableItem( USHORT nItemId, BOOL bEnable )
+{
+ USHORT nPos;
+ MenuItemData* pItemData = pItemList->GetData( nItemId, nPos );
+
+ if ( pItemData && ( pItemData->bEnabled != bEnable ) )
+ {
+ pItemData->bEnabled = bEnable;
+
+ Window* pWin = ImplGetWindow();
+ if ( pWin && pWin->IsVisible() )
+ {
+ DBG_ASSERT( bIsMenuBar, "Menu::EnableItem - Popup visible!" );
+ long nX = 0;
+ ULONG nCount = pItemList->Count();
+ for ( ULONG n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ if ( n == nPos )
+ {
+ pWin->Invalidate( Rectangle( Point( nX, 0 ), Size( pData->aSz.Width(), pData->aSz.Height() ) ) );
+ break;
+ }
+ nX += pData->aSz.Width();
+ }
+ }
+ // update native menu
+ if( ImplGetSalMenu() )
+ ImplGetSalMenu()->EnableItem( nPos, bEnable );
+
+ ImplCallEventListeners( bEnable ? VCLEVENT_MENU_ENABLE : VCLEVENT_MENU_DISABLE, nPos );
+ }
+}
+
+BOOL Menu::IsItemEnabled( USHORT nItemId ) const
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return FALSE;
+
+ return pData->bEnabled;
+}
+
+void Menu::ShowItem( USHORT nItemId, BOOL bVisible )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ DBG_ASSERT( !bIsMenuBar, "Menu::ShowItem - ignored for menu bar entries!" );
+ if ( !bIsMenuBar && pData && ( pData->bVisible != bVisible ) )
+ {
+ Window* pWin = ImplGetWindow();
+ if ( pWin && pWin->IsVisible() )
+ {
+ DBG_ASSERT( 0, "Menu::ShowItem - ignored for visible popups!" );
+ return;
+ }
+ pData->bVisible = bVisible;
+
+ // update native menu
+ // as long as there is no support to hide native menu entries, we just disable them
+ // TODO: add support to show/hide native menu entries
+ if( ImplGetSalMenu() )
+ ImplGetSalMenu()->EnableItem( nPos, bVisible );
+ }
+}
+
+void Menu::SetItemText( USHORT nItemId, const XubString& rStr )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return;
+
+ if ( !rStr.Equals( pData->aText ) )
+ {
+ pData->aText = rStr;
+ ImplSetMenuItemData( pData );
+ // update native menu
+ if( ImplGetSalMenu() && pData->pSalMenuItem )
+ ImplGetSalMenu()->SetItemText( nPos, pData->pSalMenuItem, rStr );
+
+ Window* pWin = ImplGetWindow();
+ delete mpLayoutData, mpLayoutData = NULL;
+ if ( pWin && IsMenuBar() )
+ {
+ ImplCalcSize( pWin );
+ if ( pWin->IsVisible() )
+ pWin->Invalidate();
+ }
+
+ ImplCallEventListeners( VCLEVENT_MENU_ITEMTEXTCHANGED, nPos );
+ }
+}
+
+XubString Menu::GetItemText( USHORT nItemId ) const
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData )
+ return pData->aText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::SetItemImage( USHORT nItemId, const Image& rImage )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return;
+
+ pData->aImage = rImage;
+ ImplSetMenuItemData( pData );
+
+ // update native menu
+ if( ImplGetSalMenu() && pData->pSalMenuItem )
+ ImplGetSalMenu()->SetItemImage( nPos, pData->pSalMenuItem, rImage );
+}
+
+static inline Image ImplRotImage( const Image& rImage, long nAngle10 )
+{
+ Image aRet;
+ BitmapEx aBmpEx( rImage.GetBitmapEx() );
+
+ aBmpEx.Rotate( nAngle10, COL_WHITE );
+
+ return Image( aBmpEx );
+}
+
+void Menu::SetItemImageAngle( USHORT nItemId, long nAngle10 )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData )
+ {
+ long nDeltaAngle = (nAngle10 - pData->nItemImageAngle) % 3600;
+ while( nDeltaAngle < 0 )
+ nDeltaAngle += 3600;
+
+ pData->nItemImageAngle = nAngle10;
+ if( nDeltaAngle && !!pData->aImage )
+ pData->aImage = ImplRotImage( pData->aImage, nDeltaAngle );
+ }
+}
+
+static inline Image ImplMirrorImage( const Image& rImage )
+{
+ Image aRet;
+ BitmapEx aBmpEx( rImage.GetBitmapEx() );
+
+ aBmpEx.Mirror( BMP_MIRROR_HORZ );
+
+ return Image( aBmpEx );
+}
+
+void Menu::SetItemImageMirrorMode( USHORT nItemId, BOOL bMirror )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData )
+ {
+ if( ( pData->bMirrorMode && ! bMirror ) ||
+ ( ! pData->bMirrorMode && bMirror )
+ )
+ {
+ pData->bMirrorMode = bMirror ? true : false;
+ if( !!pData->aImage )
+ pData->aImage = ImplMirrorImage( pData->aImage );
+ }
+ }
+}
+
+Image Menu::GetItemImage( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aImage;
+ else
+ return Image();
+}
+
+long Menu::GetItemImageAngle( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->nItemImageAngle;
+ else
+ return 0;
+}
+
+BOOL Menu::GetItemImageMirrorMode( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->bMirrorMode;
+ else
+ return FALSE;
+}
+
+void Menu::SetItemCommand( USHORT nItemId, const String& rCommand )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->aCommandStr = rCommand;
+}
+
+const XubString& Menu::GetItemCommand( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aCommandStr;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::SetHelpCommand( USHORT nItemId, const XubString& rStr )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->aHelpCommandStr = rStr;
+}
+
+const XubString& Menu::GetHelpCommand( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aHelpCommandStr;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::SetHelpText( USHORT nItemId, const XubString& rStr )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->aHelpText = rStr;
+}
+
+const XubString& Menu::ImplGetHelpText( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ {
+ if ( !pData->aHelpText.Len() &&
+ (( pData->nHelpId ) || ( pData->aCommandStr.Len() )))
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ if ( pData->aCommandStr.Len() )
+ pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, NULL );
+
+ if( !pData->aHelpText.Len() && pData->nHelpId )
+ pData->aHelpText = pHelp->GetHelpText( pData->nHelpId, NULL );
+ }
+ }
+
+ return pData->aHelpText;
+ }
+ else
+ return ImplGetSVEmptyStr();
+}
+
+const XubString& Menu::GetHelpText( USHORT nItemId ) const
+{
+ return ImplGetHelpText( nItemId );
+}
+
+void Menu::SetTipHelpText( USHORT nItemId, const XubString& rStr )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->aTipHelpText = rStr;
+}
+
+const XubString& Menu::GetTipHelpText( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aTipHelpText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::SetHelpId( USHORT nItemId, ULONG nHelpId )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->nHelpId = nHelpId;
+}
+
+ULONG Menu::GetHelpId( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->nHelpId;
+ else
+ return 0;
+}
+
+Menu& Menu::operator=( const Menu& rMenu )
+{
+ // Aufraeumen
+ Clear();
+
+ // Items kopieren
+ USHORT nCount = rMenu.GetItemCount();
+ for ( USHORT i = 0; i < nCount; i++ )
+ ImplCopyItem( this, rMenu, i, MENU_APPEND, 1 );
+
+ nDefaultItem = rMenu.nDefaultItem;
+ aActivateHdl = rMenu.aActivateHdl;
+ aDeactivateHdl = rMenu.aDeactivateHdl;
+ aHighlightHdl = rMenu.aHighlightHdl;
+ aSelectHdl = rMenu.aSelectHdl;
+ aTitleText = rMenu.aTitleText;
+ bIsMenuBar = rMenu.bIsMenuBar;
+
+ return *this;
+}
+
+BOOL Menu::ImplIsVisible( USHORT nPos ) const
+{
+ BOOL bVisible = TRUE;
+
+ MenuItemData* pData = pItemList->GetDataFromPos( nPos );
+ // check general visibility first
+ if( pData && !pData->bVisible )
+ bVisible = FALSE;
+
+ if ( bVisible && pData && pData->eType == MENUITEM_SEPARATOR )
+ {
+ if( nPos == 0 ) // no separator should be shown at the very beginning
+ bVisible = FALSE;
+ else
+ {
+ // always avoid adjacent separators
+ USHORT nCount = (USHORT) pItemList->Count();
+ USHORT n;
+ MenuItemData* pNextData = NULL;
+ // search next visible item
+ for( n = nPos + 1; n < nCount; n++ )
+ {
+ pNextData = pItemList->GetDataFromPos( n );
+ if( pNextData && pNextData->bVisible )
+ {
+ if( pNextData->eType == MENUITEM_SEPARATOR || ImplIsVisible(n) )
+ break;
+ }
+ }
+ if( n == nCount ) // no next visible item
+ bVisible = FALSE;
+ // check for separator
+ if( pNextData && pNextData->bVisible && pNextData->eType == MENUITEM_SEPARATOR )
+ bVisible = FALSE;
+
+ if( bVisible )
+ {
+ for( n = nPos; n > 0; n-- )
+ {
+ pNextData = pItemList->GetDataFromPos( n-1 );
+ if( pNextData && pNextData->bVisible )
+ {
+ if( pNextData->eType != MENUITEM_SEPARATOR && ImplIsVisible(n-1) )
+ break;
+ }
+ }
+ if( n == 0 ) // no previous visible item
+ bVisible = FALSE;
+ }
+ }
+ }
+
+ // Fuer den Menubar nicht erlaubt, weil ich nicht mitbekomme
+ // ob dadurch ein Eintrag verschwindet oder wieder da ist.
+ if ( bVisible && !bIsMenuBar && ( nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES ) &&
+ !( nMenuFlags & MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ) )
+ {
+ if( !pData ) // e.g. nPos == ITEMPOS_INVALID
+ bVisible = FALSE;
+ else if ( pData->eType != MENUITEM_SEPARATOR ) // separators handled above
+ {
+ // bVisible = pData->bEnabled && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( TRUE ) );
+ bVisible = pData->bEnabled; // SubMenus nicht pruefen, weil sie ggf. erst im Activate() gefuellt werden.
+ }
+ }
+
+ return bVisible;
+}
+
+BOOL Menu::IsItemVisible( USHORT nItemId ) const
+{
+ return IsMenuVisible() && ImplIsVisible( GetItemPos( nItemId ) );
+}
+
+BOOL Menu::IsItemPosVisible( USHORT nItemPos ) const
+{
+ return IsMenuVisible() && ImplIsVisible( nItemPos );
+}
+
+BOOL Menu::IsMenuVisible() const
+{
+ return pWindow && pWindow->IsReallyVisible();
+}
+
+BOOL Menu::ImplIsSelectable( USHORT nPos ) const
+{
+ BOOL bSelectable = TRUE;
+
+ MenuItemData* pData = pItemList->GetDataFromPos( nPos );
+ // check general visibility first
+ if ( pData && ( pData->nBits & MIB_NOSELECT ) )
+ bSelectable = FALSE;
+
+ return bSelectable;
+}
+
+void Menu::SelectItem( USHORT nItemId )
+{
+ if( bIsMenuBar )
+ static_cast<MenuBar*>(this)->SelectEntry( nItemId );
+ else
+ static_cast<PopupMenu*>(this)->SelectEntry( nItemId );
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Menu::GetAccessible()
+{
+ // Since PopupMenu are sometimes shared by different instances of MenuBar, the mxAccessible member gets
+ // overwritten and may contain a disposed object when the initial menubar gets set again. So use the
+ // mxAccessible member only for sub menus.
+ if ( pStartedFrom )
+ {
+ for ( sal_uInt16 i = 0, nCount = pStartedFrom->GetItemCount(); i < nCount; ++i )
+ {
+ sal_uInt16 nItemId = pStartedFrom->GetItemId( i );
+ if ( static_cast< Menu* >( pStartedFrom->GetPopupMenu( nItemId ) ) == this )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xParent = pStartedFrom->GetAccessible();
+ if ( xParent.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+ if ( xParentContext.is() )
+ return xParentContext->getAccessibleChild( i );
+ }
+ }
+ }
+ }
+ else if ( !mxAccessible.is() )
+ {
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ if ( pWrapper )
+ mxAccessible = pWrapper->CreateAccessible( this, bIsMenuBar );
+ }
+
+ return mxAccessible;
+}
+
+void Menu::SetAccessible( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible )
+{
+ mxAccessible = rxAccessible;
+}
+
+long Menu::ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth ) const
+{
+ rMaxWidth = rCheckHeight = rRadioHeight = 0;
+
+ if( ! bIsMenuBar )
+ {
+ ImplControlValue aVal;
+ Rectangle aNativeBounds;
+ Rectangle aNativeContent;
+ Point tmp( 0, 0 );
+ Rectangle aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) );
+ if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) )
+ {
+ if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
+ ControlPart(PART_MENU_ITEM_CHECK_MARK),
+ aCtrlRegion,
+ ControlState(CTRL_STATE_ENABLED),
+ aVal,
+ OUString(),
+ aNativeBounds,
+ aNativeContent )
+ )
+ {
+ rCheckHeight = aNativeBounds.GetHeight();
+ rMaxWidth = aNativeContent.GetWidth();
+ }
+ }
+ if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) )
+ {
+ if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
+ ControlPart(PART_MENU_ITEM_RADIO_MARK),
+ aCtrlRegion,
+ ControlState(CTRL_STATE_ENABLED),
+ aVal,
+ OUString(),
+ aNativeBounds,
+ aNativeContent )
+ )
+ {
+ rRadioHeight = aNativeBounds.GetHeight();
+ rMaxWidth = Max (rMaxWidth, aNativeContent.GetWidth());
+ }
+ }
+ }
+ return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight;
+}
+
+// -----------------------------------------------------------------------
+
+void Menu::ImplAddDel( ImplMenuDelData& rDel )
+{
+ DBG_ASSERT( !rDel.mpMenu, "Menu::ImplAddDel(): cannot add ImplMenuDelData twice !" );
+ if( !rDel.mpMenu )
+ {
+ rDel.mpMenu = this;
+ rDel.mpNext = mpFirstDel;
+ mpFirstDel = &rDel;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Menu::ImplRemoveDel( ImplMenuDelData& rDel )
+{
+ rDel.mpMenu = NULL;
+ if ( mpFirstDel == &rDel )
+ {
+ mpFirstDel = rDel.mpNext;
+ }
+ else
+ {
+ ImplMenuDelData* pData = mpFirstDel;
+ while ( pData && (pData->mpNext != &rDel) )
+ pData = pData->mpNext;
+
+ DBG_ASSERT( pData, "Menu::ImplRemoveDel(): ImplMenuDelData not registered !" );
+ if( pData )
+ pData->mpNext = rDel.mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Menu::ImplCalcSize( Window* pWin )
+{
+ // | Checked| Image| Text| Accel/Popup|
+
+ // Fuer Symbole: nFontHeight x nFontHeight
+ long nFontHeight = pWin->GetTextHeight();
+ long nExtra = nFontHeight/4;
+
+
+ Size aSz;
+ Size aMaxImgSz;
+ long nMaxWidth = 0;
+ long nMinMenuItemHeight = nFontHeight;
+ long nCheckHeight = 0, nRadioHeight = 0;
+ long nCheckWidth = 0, nMaxCheckWidth = 0;
+ long nMax = ImplGetNativeCheckAndRadioSize( pWin, nCheckHeight, nRadioHeight, nMaxCheckWidth );
+ if( nMax > nMinMenuItemHeight )
+ nMinMenuItemHeight = nMax;
+
+ const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
+ if ( rSettings.GetUseImagesInMenus() )
+ {
+ nMinMenuItemHeight = 16;
+ for ( USHORT i = (USHORT)pItemList->Count(); i; )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( --i );
+ if ( ImplIsVisible( i ) && (( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE )))
+ {
+ Size aImgSz = pData->aImage.GetSizePixel();
+ if ( aImgSz.Height() > aMaxImgSz.Height() )
+ aMaxImgSz.Height() = aImgSz.Height();
+ if ( aImgSz.Height() > nMinMenuItemHeight )
+ nMinMenuItemHeight = aImgSz.Height();
+ break;
+ }
+ }
+ }
+
+ for ( USHORT n = (USHORT)pItemList->Count(); n; )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( --n );
+
+ pData->aSz.Height() = 0;
+ pData->aSz.Width() = 0;
+
+ if ( ImplIsVisible( n ) )
+ {
+ long nWidth = 0;
+
+ // Separator
+ if ( !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
+ {
+ DBG_ASSERT( !bIsMenuBar, "Separator in MenuBar ?! " );
+ pData->aSz.Height() = 4;
+ }
+
+ // Image:
+ if ( !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
+ {
+ Size aImgSz = pData->aImage.GetSizePixel();
+ aImgSz.Height() += 4; // add a border for native marks
+ aImgSz.Width() += 4; // add a border for native marks
+ if ( aImgSz.Width() > aMaxImgSz.Width() )
+ aMaxImgSz.Width() = aImgSz.Width();
+ if ( aImgSz.Height() > aMaxImgSz.Height() )
+ aMaxImgSz.Height() = aImgSz.Height();
+ if ( aImgSz.Height() > pData->aSz.Height() )
+ pData->aSz.Height() = aImgSz.Height();
+ }
+
+ // Check Buttons:
+ if ( !bIsMenuBar && pData->HasCheck() )
+ {
+ nCheckWidth = nMaxCheckWidth;
+ if (nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES)
+ {
+ // checks / images take the same place
+ if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
+ nWidth += nCheckWidth + nExtra * 2;
+ }
+ }
+
+ // Text:
+ if ( (pData->eType == MENUITEM_STRING) || (pData->eType == MENUITEM_STRINGIMAGE) )
+ {
+ long nTextWidth = pWin->GetCtrlTextWidth( pData->aText );
+ long nTextHeight = pWin->GetTextHeight();
+
+// if ( nTextHeight > pData->aSz.Height() )
+// pData->aSz.Height() = nTextHeight;
+
+ if ( bIsMenuBar )
+ {
+ if ( nTextHeight > pData->aSz.Height() )
+ pData->aSz.Height() = nTextHeight;
+
+ pData->aSz.Width() = nTextWidth + 4*nExtra;
+ aSz.Width() += pData->aSz.Width();
+ }
+ else
+ pData->aSz.Height() = Max( Max( nTextHeight, pData->aSz.Height() ), nMinMenuItemHeight );
+
+ nWidth += nTextWidth;
+ }
+
+ // Accel
+ if ( !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
+ {
+ String aName = pData->aAccelKey.GetName();
+ long nAccWidth = pWin->GetTextWidth( aName );
+ nAccWidth += nExtra;
+ nWidth += nAccWidth;
+ }
+
+ // SubMenu?
+ if ( !bIsMenuBar && pData->pSubMenu )
+ {
+ if ( nFontHeight > nWidth )
+ nWidth += nFontHeight;
+
+ pData->aSz.Height() = Max( Max( nFontHeight, pData->aSz.Height() ), nMinMenuItemHeight );
+ }
+
+ pData->aSz.Height() += EXTRAITEMHEIGHT; // Etwas mehr Abstand:
+
+ if ( !bIsMenuBar )
+ aSz.Height() += (long)pData->aSz.Height();
+
+ if ( nWidth > nMaxWidth )
+ nMaxWidth = nWidth;
+
+ }
+ }
+
+ if ( !bIsMenuBar )
+ {
+ USHORT gfxExtra = (USHORT) Max( nExtra, 7L ); // #107710# increase space between checkmarks/images/text
+ nCheckPos = (USHORT)nExtra;
+ if (nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES)
+ {
+ long nImgOrChkWidth = 0;
+ nImagePos = nCheckPos;
+ if( nMax > 0 ) // NWF case
+ nImgOrChkWidth = nMax + nExtra;
+ else // non NWF case
+ nImgOrChkWidth = nFontHeight/2 + gfxExtra;
+ nImgOrChkWidth = Max( nImgOrChkWidth, aMaxImgSz.Width() + gfxExtra );
+ nTextPos = (USHORT)(nImagePos + nImgOrChkWidth);
+ }
+ else
+ {
+ nImagePos = nCheckPos;
+ nTextPos = (USHORT)(nImagePos + Max( aMaxImgSz.Width(), nCheckWidth ));
+ }
+ nTextPos = nTextPos + gfxExtra;
+
+ aSz.Width() = nTextPos + nMaxWidth + nExtra;
+ aSz.Width() += 4*nExtra; // a _little_ more ...
+
+ int nOuterSpace = ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder;
+ aSz.Width() += 2*nOuterSpace;
+ aSz.Height() += 2*nOuterSpace;
+ }
+ else
+ {
+ nTextPos = (USHORT)(2*nExtra);
+ aSz.Height() = nFontHeight+6;
+
+ // get menubar height from native methods if supported
+ if( pWindow->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
+ {
+ ImplControlValue aVal;
+ Rectangle aNativeBounds;
+ Rectangle aNativeContent;
+ Point tmp( 0, 0 );
+ Rectangle aCtrlRegion( tmp, Size( 100, 15 ) );
+ if( pWindow->GetNativeControlRegion( ControlType(CTRL_MENUBAR),
+ ControlPart(PART_ENTIRE_CONTROL),
+ aCtrlRegion,
+ ControlState(CTRL_STATE_ENABLED),
+ aVal,
+ OUString(),
+ aNativeBounds,
+ aNativeContent )
+ )
+ {
+ int nNativeHeight = aNativeBounds.GetHeight();
+ if( nNativeHeight > aSz.Height() )
+ aSz.Height() = nNativeHeight;
+ }
+ }
+
+ // account for the size of the close button, which actually is a toolbox
+ // due to NWF this is variable
+ long nCloserHeight = ((MenuBarWindow*) pWindow)->MinCloseButtonSize().Height();
+ if( aSz.Height() < nCloserHeight )
+ aSz.Height() = nCloserHeight;
+ }
+
+ if ( pLogo )
+ aSz.Width() += pLogo->aBitmap.GetSizePixel().Width();
+
+ return aSz;
+}
+
+static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight )
+{
+ BOOL bNativeOk = FALSE;
+ if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
+ {
+ ImplControlValue aControlValue;
+ Rectangle aCtrlRegion( i_rRect );
+ ControlState nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED;
+
+ aControlValue.setTristateVal( BUTTONVALUE_ON );
+
+ bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
+ aCtrlRegion, nState, aControlValue,
+ rtl::OUString() );
+ }
+
+ if( ! bNativeOk )
+ {
+ const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings();
+ Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() );
+ i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, TRUE, FALSE, 2, NULL, &aColor );
+ }
+}
+
+void Menu::ImplPaint( Window* pWin, USHORT nBorder, long nStartY, MenuItemData* pThisItemOnly, BOOL bHighlighted, bool bLayout ) const
+{
+ // Fuer Symbole: nFontHeight x nFontHeight
+ long nFontHeight = pWin->GetTextHeight();
+ long nExtra = nFontHeight/4;
+
+ long nCheckHeight = 0, nRadioHeight = 0, nMaxCheckWidth = 0;
+ ImplGetNativeCheckAndRadioSize( pWin, nCheckHeight, nRadioHeight, nMaxCheckWidth );
+
+ DecorationView aDecoView( pWin );
+ const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
+
+ Point aTopLeft, aTmpPos;
+
+ if ( pLogo )
+ aTopLeft.X() = pLogo->aBitmap.GetSizePixel().Width();
+
+ int nOuterSpace = 0;
+ if( !bIsMenuBar )
+ {
+ nOuterSpace = ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder;
+ aTopLeft.X() += nOuterSpace;
+ aTopLeft.Y() += nOuterSpace;
+ }
+
+ Size aOutSz = pWin->GetOutputSizePixel();
+ USHORT nCount = (USHORT)pItemList->Count();
+ if( bLayout )
+ mpLayoutData->m_aVisibleItemBoundRects.clear();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ if ( ImplIsVisible( n ) && ( !pThisItemOnly || ( pData == pThisItemOnly ) ) )
+ {
+ if ( pThisItemOnly && bHighlighted )
+ pWin->SetTextColor( rSettings.GetMenuHighlightTextColor() );
+
+ Point aPos( aTopLeft );
+ aPos.Y() += nBorder;
+ aPos.Y() += nStartY;
+
+ if ( aPos.Y() >= 0 )
+ {
+ long nTextOffsetY = ((pData->aSz.Height()-nFontHeight)/2);
+ if( bIsMenuBar )
+ nTextOffsetY += (aOutSz.Height()-pData->aSz.Height()) / 2;
+ USHORT nTextStyle = 0;
+ USHORT nSymbolStyle = 0;
+ USHORT nImageStyle = 0;
+ // SubMenus ohne Items werden nicht mehr disablte dargestellt,
+ // wenn keine Items enthalten sind, da die Anwendung selber
+ // darauf achten muss. Ansonsten gibt es Faelle, wo beim
+ // asyncronen laden die Eintraege disablte dargestellt werden.
+ if ( !pData->bEnabled )
+ {
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ nSymbolStyle |= SYMBOL_DRAW_DISABLE;
+ nImageStyle |= IMAGE_DRAW_DISABLE;
+ }
+
+ // Separator
+ if ( !bLayout && !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
+ {
+ aTmpPos.Y() = aPos.Y() + ((pData->aSz.Height()-2)/2);
+ aTmpPos.X() = aPos.X() + 2 + nOuterSpace;
+ pWin->SetLineColor( rSettings.GetShadowColor() );
+ pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) );
+ aTmpPos.Y()++;
+ pWin->SetLineColor( rSettings.GetLightColor() );
+ pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) );
+ pWin->SetLineColor();
+ }
+
+ Rectangle aOuterCheckRect( Point( aPos.X()+nCheckPos, aPos.Y() ), Size( pData->aSz.Height(), pData->aSz.Height() ) );
+ aOuterCheckRect.Left() += 1;
+ aOuterCheckRect.Right() -= 1;
+ aOuterCheckRect.Top() += 1;
+ aOuterCheckRect.Bottom() -= 1;
+
+ // CheckMark
+ if ( !bLayout && !bIsMenuBar && pData->HasCheck() )
+ {
+ // draw selection transparent marker if checked
+ // onto that either a checkmark or the item image
+ // will be painted
+ // however do not do this if native checks will be painted since
+ // the selection color too often does not fit the theme's check and/or radio
+
+ if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
+ {
+ if ( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
+ (pData->nBits & MIB_RADIOCHECK)
+ ? PART_MENU_ITEM_CHECK_MARK
+ : PART_MENU_ITEM_RADIO_MARK ) )
+ {
+ ControlPart nPart = ((pData->nBits & MIB_RADIOCHECK)
+ ? PART_MENU_ITEM_RADIO_MARK
+ : PART_MENU_ITEM_CHECK_MARK);
+
+ ControlState nState = 0;
+
+ if ( pData->bChecked )
+ nState |= CTRL_STATE_PRESSED;
+
+ if ( pData->bEnabled )
+ nState |= CTRL_STATE_ENABLED;
+
+ if ( bHighlighted )
+ nState |= CTRL_STATE_SELECTED;
+
+ long nCtrlHeight = (pData->nBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight;
+ aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2;
+ aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2;
+
+ Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) );
+ pWin->DrawNativeControl( CTRL_MENU_POPUP, nPart,
+ aCheckRect,
+ nState,
+ ImplControlValue(),
+ OUString() );
+ }
+ else if ( pData->bChecked ) // by default do nothing for unchecked items
+ {
+ ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted );
+
+ SymbolType eSymbol;
+ Size aSymbolSize;
+ if ( pData->nBits & MIB_RADIOCHECK )
+ {
+ eSymbol = SYMBOL_RADIOCHECKMARK;
+ aSymbolSize = Size( nFontHeight/2, nFontHeight/2 );
+ }
+ else
+ {
+ eSymbol = SYMBOL_CHECKMARK;
+ aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 );
+ }
+ aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2;
+ aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2;
+ Rectangle aRect( aTmpPos, aSymbolSize );
+ aDecoView.DrawSymbol( aRect, eSymbol, pWin->GetTextColor(), nSymbolStyle );
+ }
+ }
+ }
+
+ // Image:
+ if ( !bLayout && !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
+ {
+ // Don't render an image for a check thing
+ if ((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pData->HasCheck() )
+ {
+ if( pData->bChecked )
+ ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted );
+ aTmpPos = aOuterCheckRect.TopLeft();
+ aTmpPos.X() += (aOuterCheckRect.GetWidth()-pData->aImage.GetSizePixel().Width())/2;
+ aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pData->aImage.GetSizePixel().Height())/2;
+ pWin->DrawImage( aTmpPos, pData->aImage, nImageStyle );
+ }
+ }
+
+ // Text:
+ if ( ( pData->eType == MENUITEM_STRING ) || ( pData->eType == MENUITEM_STRINGIMAGE ) )
+ {
+ aTmpPos.X() = aPos.X() + nTextPos;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nTextOffsetY;
+ USHORT nStyle = nTextStyle|TEXT_DRAW_MNEMONIC;
+ if ( pData->bIsTemporary )
+ nStyle |= TEXT_DRAW_DISABLE;
+ MetricVector* pVector = bLayout ? &mpLayoutData->m_aUnicodeBoundRects : NULL;
+ String* pDisplayText = bLayout ? &mpLayoutData->m_aDisplayText : NULL;
+ if( bLayout )
+ {
+ mpLayoutData->m_aLineIndices.push_back( mpLayoutData->m_aDisplayText.Len() );
+ mpLayoutData->m_aLineItemIds.push_back( pData->nId );
+ mpLayoutData->m_aLineItemPositions.push_back( n );
+ }
+ // #i47946# with NWF painted menus the background is transparent
+ // since DrawCtrlText can depend on the background (e.g. for
+ // TEXT_DRAW_DISABLE), temporarily set a background which
+ // hopefully matches the NWF background since it is read
+ // from the system style settings
+ bool bSetTmpBackground = !pWin->IsBackground() && pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL );
+ if( bSetTmpBackground )
+ {
+ Color aBg = bIsMenuBar ?
+ pWin->GetSettings().GetStyleSettings().GetMenuBarColor() :
+ pWin->GetSettings().GetStyleSettings().GetMenuColor();
+ pWin->SetBackground( Wallpaper( aBg ) );
+ }
+ pWin->DrawCtrlText( aTmpPos, pData->aText, 0, pData->aText.Len(), nStyle, pVector, pDisplayText );
+ if( bSetTmpBackground )
+ pWin->SetBackground();
+ }
+
+ // Accel
+ if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
+ {
+ XubString aAccText = pData->aAccelKey.GetName();
+ aTmpPos.X() = aOutSz.Width() - pWin->GetTextWidth( aAccText );
+ aTmpPos.X() -= 4*nExtra;
+
+ aTmpPos.X() -= nOuterSpace;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nTextOffsetY;
+ pWin->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle );
+ }
+
+ // SubMenu?
+ if ( !bLayout && !bIsMenuBar && pData->pSubMenu )
+ {
+ aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nExtra/2;
+ aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 );
+ if ( pData->nBits & MIB_POPUPSELECT )
+ {
+ pWin->SetTextColor( rSettings.GetMenuTextColor() );
+ Point aTmpPos2( aPos );
+ aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
+ aDecoView.DrawFrame(
+ Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pData->aSz.Height() ) ), FRAME_DRAW_GROUP );
+ }
+ aDecoView.DrawSymbol(
+ Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
+ SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle );
+// if ( pData->nBits & MIB_POPUPSELECT )
+// {
+// aTmpPos.Y() += nFontHeight/2 ;
+// pWin->SetLineColor( rSettings.GetShadowColor() );
+// pWin->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
+// pWin->SetLineColor( rSettings.GetLightColor() );
+// aTmpPos.Y()++;
+// pWin->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
+// pWin->SetLineColor();
+// }
+ }
+
+ if ( pThisItemOnly && bHighlighted )
+ {
+ // This restores the normal menu or menu bar text
+ // color for when it is no longer highlighted.
+ if ( bIsMenuBar )
+ pWin->SetTextColor( rSettings.GetMenuBarTextColor() );
+ else
+ pWin->SetTextColor( rSettings.GetMenuTextColor() );
+ }
+ }
+ if( bLayout )
+ {
+ if ( !bIsMenuBar )
+ mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle( aTopLeft, Size( aOutSz.Width(), pData->aSz.Height() ) );
+ else
+ mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle( aTopLeft, pData->aSz );
+ }
+ }
+
+ if ( !bIsMenuBar )
+ {
+ aTopLeft.Y() += pData->aSz.Height();
+ }
+ else
+ {
+ aTopLeft.X() += pData->aSz.Width();
+ }
+ }
+
+ if ( !bLayout && !pThisItemOnly && pLogo )
+ {
+ Size aLogoSz = pLogo->aBitmap.GetSizePixel();
+
+ Rectangle aRect( Point( 0, 0 ), Point( aLogoSz.Width()-1, aOutSz.Height() ) );
+ if ( pWin->GetColorCount() >= 256 )
+ {
+ Gradient aGrad( GRADIENT_LINEAR, pLogo->aStartColor, pLogo->aEndColor );
+ aGrad.SetAngle( 1800 );
+ aGrad.SetBorder( 15 );
+ pWin->DrawGradient( aRect, aGrad );
+ }
+ else
+ {
+ pWin->SetFillColor( pLogo->aStartColor );
+ pWin->DrawRect( aRect );
+ }
+
+ Point aLogoPos( 0, aOutSz.Height() - aLogoSz.Height() );
+ pLogo->aBitmap.Draw( pWin, aLogoPos );
+ }
+}
+
+Menu* Menu::ImplGetStartMenu()
+{
+ Menu* pStart = this;
+ while ( pStart && pStart->pStartedFrom && ( pStart->pStartedFrom != pStart ) )
+ pStart = pStart->pStartedFrom;
+ return pStart;
+}
+
+void Menu::ImplCallHighlight( USHORT nHighlightedItem )
+{
+ ImplMenuDelData aDelData( this );
+
+ nSelectedId = 0;
+ MenuItemData* pData = pItemList->GetDataFromPos( nHighlightedItem );
+ if ( pData )
+ nSelectedId = pData->nId;
+ ImplCallEventListeners( VCLEVENT_MENU_HIGHLIGHT, GetItemPos( GetCurItemId() ) );
+
+ if( !aDelData.isDeleted() )
+ {
+ Highlight();
+ nSelectedId = 0;
+ }
+}
+
+IMPL_LINK( Menu, ImplCallSelect, Menu*, EMPTYARG )
+{
+ nEventId = 0;
+ Select();
+ return 0;
+}
+
+Menu* Menu::ImplFindSelectMenu()
+{
+ Menu* pSelMenu = nEventId ? this : NULL;
+
+ for ( ULONG n = GetItemList()->Count(); n && !pSelMenu; )
+ {
+ MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
+
+ if ( pData->pSubMenu )
+ pSelMenu = pData->pSubMenu->ImplFindSelectMenu();
+ }
+
+ return pSelMenu;
+}
+
+Menu* Menu::ImplFindMenu( USHORT nItemId )
+{
+ Menu* pSelMenu = NULL;
+
+ for ( ULONG n = GetItemList()->Count(); n && !pSelMenu; )
+ {
+ MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
+
+ if( pData->nId == nItemId )
+ pSelMenu = this;
+ else if ( pData->pSubMenu )
+ pSelMenu = pData->pSubMenu->ImplFindMenu( nItemId );
+ }
+
+ return pSelMenu;
+}
+
+void Menu::RemoveDisabledEntries( BOOL bCheckPopups, BOOL bRemoveEmptyPopups )
+{
+ for ( USHORT n = 0; n < GetItemCount(); n++ )
+ {
+ BOOL bRemove = FALSE;
+ MenuItemData* pItem = pItemList->GetDataFromPos( n );
+ if ( pItem->eType == MENUITEM_SEPARATOR )
+ {
+ if ( !n || ( GetItemType( n-1 ) == MENUITEM_SEPARATOR ) )
+ bRemove = TRUE;
+ }
+ else
+ bRemove = !pItem->bEnabled;
+
+ if ( bCheckPopups && pItem->pSubMenu )
+ {
+ pItem->pSubMenu->RemoveDisabledEntries( TRUE );
+ if ( bRemoveEmptyPopups && !pItem->pSubMenu->GetItemCount() )
+ bRemove = TRUE;
+ }
+
+ if ( bRemove )
+ RemoveItem( n-- );
+ }
+
+ if ( GetItemCount() )
+ {
+ USHORT nLast = GetItemCount() - 1;
+ MenuItemData* pItem = pItemList->GetDataFromPos( nLast );
+ if ( pItem->eType == MENUITEM_SEPARATOR )
+ RemoveItem( nLast );
+ }
+ delete mpLayoutData, mpLayoutData = NULL;
+}
+
+BOOL Menu::HasValidEntries( BOOL bCheckPopups )
+{
+ BOOL bValidEntries = FALSE;
+ USHORT nCount = GetItemCount();
+ for ( USHORT n = 0; !bValidEntries && ( n < nCount ); n++ )
+ {
+ MenuItemData* pItem = pItemList->GetDataFromPos( n );
+ if ( pItem->bEnabled && ( pItem->eType != MENUITEM_SEPARATOR ) )
+ {
+ if ( bCheckPopups && pItem->pSubMenu )
+ bValidEntries = pItem->pSubMenu->HasValidEntries( TRUE );
+ else
+ bValidEntries = TRUE;
+ }
+ }
+ return bValidEntries;
+}
+
+void Menu::SetLogo( const MenuLogo& rLogo )
+{
+ delete pLogo;
+ pLogo = new MenuLogo( rLogo );
+}
+
+void Menu::SetLogo()
+{
+ delete pLogo;
+ pLogo = NULL;
+}
+
+MenuLogo Menu::GetLogo() const
+{
+ MenuLogo aLogo;
+ if ( pLogo )
+ aLogo = *pLogo;
+ return aLogo;
+}
+
+void Menu::ImplKillLayoutData() const
+{
+ delete mpLayoutData, mpLayoutData = NULL;
+}
+
+void Menu::ImplFillLayoutData() const
+{
+ if( pWindow && pWindow->IsReallyVisible() )
+ {
+ mpLayoutData = new MenuLayoutData();
+ if( bIsMenuBar )
+ {
+ ImplPaint( pWindow, 0, 0, 0, FALSE, true );
+ }
+ else
+ {
+ MenuFloatingWindow* pFloat = (MenuFloatingWindow*)pWindow;
+ ImplPaint( pWindow, pFloat->nScrollerHeight, pFloat->ImplGetStartY(), 0, FALSE, true );
+ }
+ }
+}
+
+String Menu::GetDisplayText() const
+{
+ if( ! mpLayoutData )
+ ImplFillLayoutData();
+ return mpLayoutData ? mpLayoutData->m_aDisplayText : String();
+}
+
+Rectangle Menu::GetCharacterBounds( USHORT nItemID, long nIndex ) const
+{
+ long nItemIndex = -1;
+ if( ! mpLayoutData )
+ ImplFillLayoutData();
+ if( mpLayoutData )
+ {
+ for( size_t i = 0; i < mpLayoutData->m_aLineItemIds.size(); i++ )
+ {
+ if( mpLayoutData->m_aLineItemIds[i] == nItemID )
+ {
+ nItemIndex = mpLayoutData->m_aLineIndices[i];
+ break;
+ }
+ }
+ }
+ return (mpLayoutData && nItemIndex != -1) ? mpLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : Rectangle();
+}
+
+
+long Menu::GetIndexForPoint( const Point& rPoint, USHORT& rItemID ) const
+{
+ long nIndex = -1;
+ rItemID = 0;
+ if( ! mpLayoutData )
+ ImplFillLayoutData();
+ if( mpLayoutData )
+ {
+ nIndex = mpLayoutData->GetIndexForPoint( rPoint );
+ for( size_t i = 0; i < mpLayoutData->m_aLineIndices.size(); i++ )
+ {
+ if( mpLayoutData->m_aLineIndices[i] <= nIndex &&
+ (i == mpLayoutData->m_aLineIndices.size()-1 || mpLayoutData->m_aLineIndices[i+1] > nIndex) )
+ {
+ // make index relative to item
+ nIndex -= mpLayoutData->m_aLineIndices[i];
+ rItemID = mpLayoutData->m_aLineItemIds[i];
+ break;
+ }
+ }
+ }
+ return nIndex;
+}
+
+long Menu::GetLineCount() const
+{
+ if( ! mpLayoutData )
+ ImplFillLayoutData();
+ return mpLayoutData ? mpLayoutData->GetLineCount() : 0;
+}
+
+Pair Menu::GetLineStartEnd( long nLine ) const
+{
+ if( ! mpLayoutData )
+ ImplFillLayoutData();
+ return mpLayoutData ? mpLayoutData->GetLineStartEnd( nLine ) : Pair( -1, -1 );
+}
+
+Pair Menu::GetItemStartEnd( USHORT nItem ) const
+{
+ if( ! mpLayoutData )
+ ImplFillLayoutData();
+
+ for( size_t i = 0; i < mpLayoutData->m_aLineItemIds.size(); i++ )
+ if( mpLayoutData->m_aLineItemIds[i] == nItem )
+ return GetLineStartEnd( i );
+
+ return Pair( -1, -1 );
+}
+
+USHORT Menu::GetDisplayItemId( long nLine ) const
+{
+ USHORT nItemId = 0;
+ if( ! mpLayoutData )
+ ImplFillLayoutData();
+ if( mpLayoutData && ( nLine >= 0 ) && ( nLine < (long)mpLayoutData->m_aLineItemIds.size() ) )
+ nItemId = mpLayoutData->m_aLineItemIds[nLine];
+ return nItemId;
+}
+
+BOOL Menu::ConvertPoint( Point& rPoint, Window* pReferenceWindow ) const
+{
+ BOOL bRet = FALSE;
+ if( pWindow && pReferenceWindow )
+ {
+ rPoint = pReferenceWindow->OutputToAbsoluteScreenPixel( rPoint );
+ rPoint = pWindow->AbsoluteScreenToOutputPixel( rPoint );
+ bRet = TRUE;
+ }
+ return bRet;
+}
+
+Rectangle Menu::GetBoundingRectangle( USHORT nPos ) const
+{
+ Rectangle aRet;
+
+ if( ! mpLayoutData )
+ ImplFillLayoutData();
+ if( mpLayoutData )
+ {
+ std::map< USHORT, Rectangle >::const_iterator it = mpLayoutData->m_aVisibleItemBoundRects.find( nPos );
+ if( it != mpLayoutData->m_aVisibleItemBoundRects.end() )
+ aRet = it->second;
+ }
+ return aRet;
+}
+
+void Menu::SetAccessibleName( USHORT nItemId, const XubString& rStr )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData && !rStr.Equals( pData->aAccessibleName ) )
+ {
+ pData->aAccessibleName = rStr;
+ ImplCallEventListeners( VCLEVENT_MENU_ACCESSIBLENAMECHANGED, nPos );
+ }
+}
+
+XubString Menu::GetAccessibleName( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aAccessibleName;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::SetAccessibleDescription( USHORT nItemId, const XubString& rStr )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->aAccessibleDescription = rStr;
+}
+
+XubString Menu::GetAccessibleDescription( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aAccessibleDescription;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::ImplSetSalMenu( SalMenu *pSalMenu )
+{
+ if( mpSalMenu )
+ ImplGetSVData()->mpDefInst->DestroyMenu( mpSalMenu );
+ mpSalMenu = pSalMenu;
+}
+
+BOOL Menu::GetSystemMenuData( SystemMenuData* pData ) const
+{
+ Menu* pMenu = (Menu*)this;
+ if( pData && pMenu->ImplGetSalMenu() )
+ {
+ pMenu->ImplGetSalMenu()->GetSystemMenuData( pData );
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+bool Menu::IsHighlighted( USHORT nItemPos ) const
+{
+ bool bRet = false;
+
+ if( pWindow )
+ {
+ if( bIsMenuBar )
+ bRet = ( nItemPos == static_cast< MenuBarWindow * > (pWindow)->GetHighlightedItem() );
+ else
+ bRet = ( nItemPos == static_cast< MenuFloatingWindow * > (pWindow)->GetHighlightedItem() );
+ }
+
+ return bRet;
+}
+
+void Menu::HighlightItem( USHORT nItemPos )
+{
+ if ( pWindow )
+ {
+ if ( bIsMenuBar )
+ {
+ MenuBarWindow* pMenuWin = static_cast< MenuBarWindow* >( pWindow );
+ pMenuWin->SetAutoPopup( FALSE );
+ pMenuWin->ChangeHighlightItem( nItemPos, FALSE );
+ }
+ else
+ {
+ static_cast< MenuFloatingWindow* >( pWindow )->ChangeHighlightItem( nItemPos, FALSE );
+ }
+ }
+}
+
+// -----------
+// - MenuBar -
+// -----------
+
+MenuBar::MenuBar() : Menu( TRUE )
+{
+ mbDisplayable = TRUE;
+ mbCloserVisible = FALSE;
+ mbFloatBtnVisible = FALSE;
+ mbHideBtnVisible = FALSE;
+}
+
+MenuBar::MenuBar( const MenuBar& rMenu ) : Menu( TRUE )
+{
+ mbDisplayable = TRUE;
+ mbCloserVisible = FALSE;
+ mbFloatBtnVisible = FALSE;
+ mbHideBtnVisible = FALSE;
+ *this = rMenu;
+ bIsMenuBar = TRUE;
+}
+
+MenuBar::MenuBar( const ResId& rResId ) : Menu ( TRUE )
+{
+ mbDisplayable = TRUE;
+ mbCloserVisible = FALSE;
+ mbFloatBtnVisible = FALSE;
+ mbHideBtnVisible = FALSE;
+ ImplLoadRes( rResId );
+}
+
+MenuBar::~MenuBar()
+{
+ ImplDestroy( this, TRUE );
+}
+
+void MenuBar::ShowCloser( BOOL bShow )
+{
+ ShowButtons( bShow, mbFloatBtnVisible, mbHideBtnVisible );
+}
+
+void MenuBar::ShowFloatButton( BOOL bShow )
+{
+ ShowButtons( mbCloserVisible, bShow, mbHideBtnVisible );
+}
+
+void MenuBar::ShowHideButton( BOOL bShow )
+{
+ ShowButtons( mbCloserVisible, mbFloatBtnVisible, bShow );
+}
+
+void MenuBar::ShowButtons( BOOL bClose, BOOL bFloat, BOOL bHide )
+{
+ if ( (bClose != mbCloserVisible) ||
+ (bFloat != mbFloatBtnVisible) ||
+ (bHide != mbHideBtnVisible) )
+ {
+ mbCloserVisible = bClose;
+ mbFloatBtnVisible = bFloat;
+ mbHideBtnVisible = bHide;
+ if ( ImplGetWindow() )
+ ((MenuBarWindow*)ImplGetWindow())->ShowButtons( bClose, bFloat, bHide );
+ }
+}
+
+void MenuBar::SetDisplayable( BOOL bDisplayable )
+{
+ if( bDisplayable != mbDisplayable )
+ {
+ mbDisplayable = bDisplayable;
+ MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
+ if( pMenuWin )
+ pMenuWin->ImplLayoutChanged();
+ }
+}
+
+Window* MenuBar::ImplCreate( Window* pParent, Window* pWindow, MenuBar* pMenu )
+{
+ if ( !pWindow )
+ pWindow = new MenuBarWindow( pParent );
+
+ pMenu->pStartedFrom = 0;
+ pMenu->pWindow = pWindow;
+ ((MenuBarWindow*)pWindow)->SetMenu( pMenu );
+ long nHeight = pMenu->ImplCalcSize( pWindow ).Height();
+
+ // depending on the native implementation or the displayable flag
+ // the menubar windows is supressed (ie, height=0)
+ if( !((MenuBar*) pMenu)->IsDisplayable() ||
+ ( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() ) )
+ nHeight = 0;
+
+ pWindow->SetPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
+ return pWindow;
+}
+
+void MenuBar::ImplDestroy( MenuBar* pMenu, BOOL bDelete )
+{
+ MenuBarWindow* pWindow = (MenuBarWindow*) pMenu->ImplGetWindow();
+ if ( pWindow && bDelete )
+ {
+ pWindow->KillActivePopup();
+ delete pWindow;
+ }
+ pMenu->pWindow = NULL;
+}
+
+BOOL MenuBar::ImplHandleKeyEvent( const KeyEvent& rKEvent, BOOL bFromMenu )
+{
+ BOOL bDone = FALSE;
+
+ // No keyboard processing when system handles the menu or our menubar is invisible
+ if( !IsDisplayable() ||
+ ( ImplGetSalMenu() && ImplGetSalMenu()->VisibleMenuBar() ) )
+ return bDone;
+
+ // Enabled-Abfragen, falls diese Methode von einem anderen Fenster gerufen wurde...
+ Window* pWin = ImplGetWindow();
+ if ( pWin && pWin->IsEnabled() && pWin->IsInputEnabled() && ! pWin->IsInModalMode() )
+ bDone = ((MenuBarWindow*)pWin)->ImplHandleKeyEvent( rKEvent, bFromMenu );
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+void MenuBar::SelectEntry( USHORT nId )
+{
+ MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
+
+ if( pMenuWin )
+ {
+ pMenuWin->GrabFocus();
+ nId = GetItemPos( nId );
+
+ // #99705# popup the selected menu
+ pMenuWin->SetAutoPopup( TRUE );
+ if( ITEMPOS_INVALID != pMenuWin->nHighlightedItem )
+ {
+ pMenuWin->KillActivePopup();
+ pMenuWin->ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ }
+ if( nId != ITEMPOS_INVALID )
+ pMenuWin->ChangeHighlightItem( nId, FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+// handler for native menu selection and command events
+
+BOOL MenuBar::HandleMenuActivateEvent( Menu *pMenu ) const
+{
+ if( pMenu )
+ {
+ ImplMenuDelData aDelData( this );
+
+ pMenu->pStartedFrom = (Menu*)this;
+ pMenu->bInCallback = TRUE;
+ pMenu->Activate();
+
+ if( !aDelData.isDeleted() )
+ pMenu->bInCallback = FALSE;
+ }
+ return TRUE;
+}
+
+BOOL MenuBar::HandleMenuDeActivateEvent( Menu *pMenu ) const
+{
+ if( pMenu )
+ {
+ ImplMenuDelData aDelData( this );
+
+ pMenu->pStartedFrom = (Menu*)this;
+ pMenu->bInCallback = TRUE;
+ pMenu->Deactivate();
+ if( !aDelData.isDeleted() )
+ pMenu->bInCallback = FALSE;
+ }
+ return TRUE;
+}
+
+BOOL MenuBar::HandleMenuHighlightEvent( Menu *pMenu, USHORT nHighlightEventId ) const
+{
+ if( !pMenu )
+ pMenu = ((Menu*) this)->ImplFindMenu( nHighlightEventId );
+ if( pMenu )
+ {
+ ImplMenuDelData aDelData( pMenu );
+
+ if( mnHighlightedItemPos != ITEMPOS_INVALID )
+ pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, mnHighlightedItemPos );
+
+ if( !aDelData.isDeleted() )
+ {
+ pMenu->mnHighlightedItemPos = pMenu->GetItemPos( nHighlightEventId );
+ pMenu->nSelectedId = nHighlightEventId;
+ pMenu->pStartedFrom = (Menu*)this;
+ pMenu->ImplCallHighlight( pMenu->mnHighlightedItemPos );
+ }
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+BOOL MenuBar::HandleMenuCommandEvent( Menu *pMenu, USHORT nCommandEventId ) const
+{
+ if( !pMenu )
+ pMenu = ((Menu*) this)->ImplFindMenu( nCommandEventId );
+ if( pMenu )
+ {
+ pMenu->nSelectedId = nCommandEventId;
+ pMenu->pStartedFrom = (Menu*)this;
+ pMenu->ImplSelect();
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+USHORT MenuBar::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, USHORT i_nPos )
+{
+ return AddMenuBarButton( i_rImage, i_rLink, String(), i_nPos );
+}
+
+USHORT MenuBar::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, const String& i_rToolTip, USHORT i_nPos )
+{
+ return pWindow ? static_cast<MenuBarWindow*>(pWindow)->AddMenuBarButton( i_rImage, i_rLink, i_rToolTip, i_nPos ) : 0;
+}
+
+void MenuBar::SetMenuBarButtonHighlightHdl( USHORT nId, const Link& rLink )
+{
+ if( pWindow )
+ static_cast<MenuBarWindow*>(pWindow)->SetMenuBarButtonHighlightHdl( nId, rLink );
+}
+
+Rectangle MenuBar::GetMenuBarButtonRectPixel( USHORT nId )
+{
+ return pWindow ? static_cast<MenuBarWindow*>(pWindow)->GetMenuBarButtonRectPixel( nId ) : Rectangle();
+}
+
+void MenuBar::RemoveMenuBarButton( USHORT nId )
+{
+ if( pWindow )
+ static_cast<MenuBarWindow*>(pWindow)->RemoveMenuBarButton( nId );
+}
+
+BOOL MenuBar::HandleMenuButtonEvent( Menu *, USHORT i_nButtonId ) const
+{
+ return static_cast<MenuBarWindow*>(pWindow)->HandleMenuButtonEvent( i_nButtonId );
+}
+
+// -----------------------------------------------------------------------
+
+// BOOL PopupMenu::bAnyPopupInExecute = FALSE;
+
+PopupMenu::PopupMenu()
+{
+ pRefAutoSubMenu = NULL;
+}
+
+PopupMenu::PopupMenu( const ResId& rResId )
+{
+ pRefAutoSubMenu = NULL;
+ ImplLoadRes( rResId );
+}
+
+PopupMenu::PopupMenu( const PopupMenu& rMenu ) : Menu()
+{
+ pRefAutoSubMenu = NULL;
+ *this = rMenu;
+}
+
+PopupMenu::~PopupMenu()
+{
+ if( pRefAutoSubMenu && *pRefAutoSubMenu == this )
+ *pRefAutoSubMenu = NULL; // #111060# avoid second delete in ~MenuItemData
+}
+
+BOOL PopupMenu::IsInExecute()
+{
+ return GetActivePopupMenu() ? TRUE : FALSE;
+}
+
+PopupMenu* PopupMenu::GetActivePopupMenu()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ return pSVData->maAppData.mpActivePopupMenu;
+}
+
+void PopupMenu::EndExecute( USHORT nSelectId )
+{
+ if ( ImplGetWindow() )
+ ImplGetFloatingWindow()->EndExecute( nSelectId );
+}
+
+void PopupMenu::SelectEntry( USHORT nId )
+{
+ if ( ImplGetWindow() )
+ {
+ if( nId != ITEMPOS_INVALID )
+ {
+ USHORT nPos;
+ MenuItemData* pData = GetItemList()->GetData( nId, nPos );
+ if ( pData->pSubMenu )
+ ImplGetFloatingWindow()->ChangeHighlightItem( nPos, TRUE );
+ else
+ ImplGetFloatingWindow()->EndExecute( nId );
+ }
+ else
+ {
+ MenuFloatingWindow* pFloat = ImplGetFloatingWindow();
+ pFloat->GrabFocus();
+ USHORT nPos;
+ for( nPos = 0; nPos < GetItemList()->Count(); nPos++ )
+ {
+ MenuItemData* pData = (MenuItemData*)GetItemList()->GetObject( nPos );
+ if( pData->pSubMenu )
+ {
+ pFloat->KillActivePopup();
+ }
+ }
+ pFloat->ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ }
+ }
+}
+
+void PopupMenu::SetSelectedEntry( USHORT nId )
+{
+ nSelectedId = nId;
+}
+
+USHORT PopupMenu::Execute( Window* pExecWindow, const Point& rPopupPos )
+{
+ return Execute( pExecWindow, Rectangle( rPopupPos, rPopupPos ), POPUPMENU_EXECUTE_DOWN );
+}
+
+USHORT PopupMenu::Execute( Window* pExecWindow, const Rectangle& rRect, USHORT nFlags )
+{
+ ENSURE_OR_RETURN( pExecWindow, "PopupMenu::Execute: need a non-NULL window!", 0 );
+
+
+ ULONG nPopupModeFlags = 0;
+ if ( nFlags & POPUPMENU_EXECUTE_DOWN )
+ nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
+ else if ( nFlags & POPUPMENU_EXECUTE_UP )
+ nPopupModeFlags = FLOATWIN_POPUPMODE_UP;
+ else if ( nFlags & POPUPMENU_EXECUTE_LEFT )
+ nPopupModeFlags = FLOATWIN_POPUPMODE_LEFT;
+ else if ( nFlags & POPUPMENU_EXECUTE_RIGHT )
+ nPopupModeFlags = FLOATWIN_POPUPMODE_RIGHT;
+ else
+ nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
+
+ if (nFlags & POPUPMENU_NOMOUSEUPCLOSE ) // allow popup menus to stay open on mouse button up
+ nPopupModeFlags |= FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE; // useful if the menu was opened on mousebutton down (eg toolbox configuration)
+
+ return ImplExecute( pExecWindow, rRect, nPopupModeFlags, 0, FALSE );
+}
+
+USHORT PopupMenu::ImplExecute( Window* pW, const Rectangle& rRect, ULONG nPopupModeFlags, Menu* pSFrom, BOOL bPreSelectFirst )
+{
+ if ( !pSFrom && ( PopupMenu::IsInExecute() || !GetItemCount() ) )
+ return 0;
+
+ delete mpLayoutData, mpLayoutData = NULL;
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ pStartedFrom = pSFrom;
+ nSelectedId = 0;
+ bCanceled = FALSE;
+
+ ULONG nFocusId = 0;
+ BOOL bRealExecute = FALSE;
+ if ( !pStartedFrom )
+ {
+ pSVData->maWinData.mbNoDeactivate = TRUE;
+ nFocusId = Window::SaveFocus();
+ bRealExecute = TRUE;
+ }
+ else
+ {
+ // assure that only one menu is open at a time
+ if( pStartedFrom->bIsMenuBar && pSVData->maWinData.mpFirstFloat )
+ pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+
+ DBG_ASSERT( !ImplGetWindow(), "Win?!" );
+ Rectangle aRect( rRect );
+ aRect.SetPos( pW->OutputToScreenPixel( aRect.TopLeft() ) );
+
+ WinBits nStyle = WB_BORDER;
+ if ( bRealExecute )
+ nPopupModeFlags |= FLOATWIN_POPUPMODE_NEWLEVEL;
+ if ( !pStartedFrom || !pStartedFrom->bIsMenuBar )
+ nPopupModeFlags |= FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK | FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE;
+
+ nPopupModeFlags |= FLOATWIN_POPUPMODE_NOKEYCLOSE;
+
+ // Kann beim Debuggen hilfreich sein.
+ // nPopupModeFlags |= FLOATWIN_POPUPMODE_NOFOCUSCLOSE;
+
+ ImplDelData aDelData;
+ pW->ImplAddDel( &aDelData );
+
+ bInCallback = TRUE; // hier schon setzen, falls Activate ueberladen
+ Activate();
+ bInCallback = FALSE;
+
+ if ( aDelData.IsDelete() )
+ return 0; // Error
+
+ pW->ImplRemoveDel( &aDelData );
+
+ if ( bCanceled || bKilled )
+ return 0;
+
+ if ( !GetItemCount() )
+ return 0;
+
+ // Das Flag MENU_FLAG_HIDEDISABLEDENTRIES wird vererbt.
+ if ( pSFrom )
+ {
+ if ( pSFrom->nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES )
+ nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
+ else
+ nMenuFlags &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
+ }
+ else
+ // #102790# context menues shall never show disabled entries
+ nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
+
+
+ USHORT nVisibleEntries = ImplGetVisibleItemCount();
+ if ( !nVisibleEntries )
+ {
+ ResMgr* pResMgr = ImplGetResMgr();
+ if( pResMgr )
+ {
+ String aTmpEntryText( ResId( SV_RESID_STRING_NOSELECTIONPOSSIBLE, *pResMgr ) );
+ MenuItemData* pData = pItemList->Insert(
+ 0xFFFF, MENUITEM_STRING, 0, aTmpEntryText, Image(), NULL, 0xFFFF );
+ pData->bIsTemporary = TRUE;
+ }
+ }
+ else if ( Application::GetSettings().GetStyleSettings().GetAutoMnemonic() && !( nMenuFlags & MENU_FLAG_NOAUTOMNEMONICS ) )
+ {
+ CreateAutoMnemonics();
+ }
+
+ MenuFloatingWindow* pWin = new MenuFloatingWindow( this, pW, nStyle | WB_SYSTEMWINDOW );
+ if( pSVData->maNWFData.mbFlatMenu )
+ pWin->SetBorderStyle( WINDOW_BORDER_NOBORDER );
+ else
+ pWin->SetBorderStyle( pWin->GetBorderStyle() | WINDOW_BORDER_MENU );
+ pWindow = pWin;
+
+ Size aSz = ImplCalcSize( pWin );
+
+ long nMaxHeight = pWin->GetDesktopRectPixel().GetHeight();
+ if( Application::GetScreenCount() > 1 && ! Application::IsMultiDisplay() )
+ {
+ Window* pDeskW = pWindow->GetWindow( WINDOW_REALPARENT );
+ if( ! pDeskW )
+ pDeskW = pWindow;
+ Point aDesktopTL( pDeskW->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) );
+ nMaxHeight = Application::GetWorkAreaPosSizePixel(
+ Application::GetBestScreen( Rectangle( aDesktopTL, aRect.GetSize() ) )
+ ).GetHeight();
+ }
+ if ( pStartedFrom && pStartedFrom->bIsMenuBar )
+ nMaxHeight -= pW->GetSizePixel().Height();
+ sal_Int32 nLeft, nTop, nRight, nBottom;
+ pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
+ nMaxHeight -= nTop+nBottom;
+ if ( aSz.Height() > nMaxHeight )
+ {
+ pWin->EnableScrollMenu( TRUE );
+ USHORT nStart = ImplGetFirstVisible();
+ USHORT nEntries = ImplCalcVisEntries( nMaxHeight, nStart );
+ aSz.Height() = ImplCalcHeight( nEntries );
+ }
+
+ pWin->SetFocusId( nFocusId );
+ pWin->SetOutputSizePixel( aSz );
+ // #102158# menus must never grab the focus, otherwise
+ // they will be closed immediately
+ // from now on focus grabbing is only prohibited automatically if
+ // FLOATWIN_POPUPMODE_GRABFOCUS was set (which is done below), because some
+ // floaters (like floating toolboxes) may grab the focus
+ // pWin->GrabFocus();
+ if ( GetItemCount() )
+ {
+ SalMenu* pMenu = ImplGetSalMenu();
+ if( pMenu && pMenu->ShowNativePopupMenu( pWin, aRect, nPopupModeFlags | FLOATWIN_POPUPMODE_GRABFOCUS ) )
+ {
+ pWin->StopExecute(0);
+ pWin->doShutdown();
+ pWindow->doLazyDelete();
+ pWindow = NULL;
+ return nSelectedId;
+ }
+ else
+ {
+ pWin->StartPopupMode( aRect, nPopupModeFlags | FLOATWIN_POPUPMODE_GRABFOCUS );
+ }
+ if( pSFrom )
+ {
+ USHORT aPos;
+ if( pSFrom->bIsMenuBar )
+ aPos = ((MenuBarWindow *) pSFrom->pWindow)->GetHighlightedItem();
+ else
+ aPos = ((MenuFloatingWindow *) pSFrom->pWindow)->GetHighlightedItem();
+
+ pWin->SetPosInParent( aPos ); // store position to be sent in SUBMENUDEACTIVATE
+ pSFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUACTIVATE, aPos );
+ }
+ }
+ if ( bPreSelectFirst )
+ {
+ USHORT nCount = (USHORT)pItemList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ if ( ( pData->bEnabled || !Application::GetSettings().GetStyleSettings().GetSkipDisabledInMenus() )
+ && ( pData->eType != MENUITEM_SEPARATOR ) && ImplIsVisible( n ) && ImplIsSelectable( n ) )
+ {
+ pWin->ChangeHighlightItem( n, FALSE );
+ break;
+ }
+ }
+ }
+ if ( bRealExecute )
+ {
+ pWin->ImplAddDel( &aDelData );
+
+ ImplDelData aModalWinDel;
+ pW->ImplAddDel( &aModalWinDel );
+ pW->ImplIncModalCount();
+
+ pWin->Execute();
+
+ DBG_ASSERT( ! aModalWinDel.IsDead(), "window for popup died, modal count incorrect !" );
+ if( ! aModalWinDel.IsDead() )
+ pW->ImplDecModalCount();
+
+ if ( !aDelData.IsDelete() )
+ pWin->ImplRemoveDel( &aDelData );
+ else
+ return 0;
+
+ // Focus wieder herstellen (kann schon im Select wieder
+ // hergestellt wurden sein
+ nFocusId = pWin->GetFocusId();
+ if ( nFocusId )
+ {
+ pWin->SetFocusId( 0 );
+ pSVData->maWinData.mbNoDeactivate = FALSE;
+ }
+ pWin->ImplEndPopupMode( 0, nFocusId );
+
+ if ( nSelectedId ) // Dann abraeumen... ( sonst macht TH das )
+ {
+ PopupMenu* pSub = pWin->GetActivePopup();
+ while ( pSub )
+ {
+ pSub->ImplGetFloatingWindow()->EndPopupMode();
+ pSub = pSub->ImplGetFloatingWindow()->GetActivePopup();
+ }
+ }
+ pWin->doShutdown();
+ pWindow->doLazyDelete();
+ pWindow = NULL;
+
+ // Steht noch ein Select aus?
+ Menu* pSelect = ImplFindSelectMenu();
+ if ( pSelect )
+ {
+ // Beim Popup-Menu muss das Select vor dem Verlassen von Execute gerufen werden!
+ Application::RemoveUserEvent( pSelect->nEventId );
+ pSelect->nEventId = 0;
+ pSelect->Select();
+ }
+ }
+
+ return bRealExecute ? nSelectedId : 0;
+}
+
+USHORT PopupMenu::ImplCalcVisEntries( long nMaxHeight, USHORT nStartEntry, USHORT* pLastVisible ) const
+{
+ nMaxHeight -= 2 * ImplGetFloatingWindow()->GetScrollerHeight();
+
+ long nHeight = 0;
+ USHORT nEntries = (USHORT) pItemList->Count();
+ USHORT nVisEntries = 0;
+
+ if ( pLastVisible )
+ *pLastVisible = 0;
+
+ for ( USHORT n = nStartEntry; n < nEntries; n++ )
+ {
+ if ( ImplIsVisible( n ) )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ nHeight += pData->aSz.Height();
+ if ( nHeight > nMaxHeight )
+ break;
+
+ if ( pLastVisible )
+ *pLastVisible = n;
+ nVisEntries++;
+ }
+ }
+ return nVisEntries;
+}
+
+long PopupMenu::ImplCalcHeight( USHORT nEntries ) const
+{
+ long nHeight = 0;
+
+ USHORT nFound = 0;
+ for ( USHORT n = 0; ( nFound < nEntries ) && ( n < pItemList->Count() ); n++ )
+ {
+ if ( ImplIsVisible( (USHORT) n ) )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ nHeight += pData->aSz.Height();
+ nFound++;
+ }
+ }
+
+ nHeight += 2*ImplGetFloatingWindow()->GetScrollerHeight();
+
+ return nHeight;
+}
+
+
+static void ImplInitMenuWindow( Window* pWin, BOOL bFont, BOOL bMenuBar )
+{
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ pWin->SetPointFont( rStyleSettings.GetMenuFont() );
+ if( bMenuBar )
+ {
+ if( pWin->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
+ {
+ pWin->SetBackground(); // background will be drawn by NWF
+ }
+ else
+ {
+ Wallpaper aWallpaper;
+ aWallpaper.SetStyle( WALLPAPER_APPLICATIONGRADIENT );
+ pWin->SetBackground( aWallpaper );
+ pWin->SetPaintTransparent( FALSE );
+ pWin->SetParentClipMode( 0 );
+ }
+ }
+ else
+ {
+ if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
+ {
+ pWin->SetBackground(); // background will be drawn by NWF
+ }
+ else
+ pWin->SetBackground( Wallpaper( rStyleSettings.GetMenuColor() ) );
+ }
+
+ if ( bMenuBar )
+ pWin->SetTextColor( rStyleSettings.GetMenuBarTextColor() );
+ else
+ pWin->SetTextColor( rStyleSettings.GetMenuTextColor() );
+ pWin->SetTextFillColor();
+ pWin->SetLineColor();
+}
+
+MenuFloatingWindow::MenuFloatingWindow( Menu* pMen, Window* pParent, WinBits nStyle ) :
+ FloatingWindow( pParent, nStyle )
+{
+ mpWindowImpl->mbMenuFloatingWindow= TRUE;
+ pMenu = pMen;
+ pActivePopup = 0;
+ nSaveFocusId = 0;
+ bInExecute = FALSE;
+ bScrollMenu = FALSE;
+ nHighlightedItem = ITEMPOS_INVALID;
+ nMBDownPos = ITEMPOS_INVALID;
+ nPosInParent = ITEMPOS_INVALID;
+ nScrollerHeight = 0;
+// nStartY = 0;
+ nBorder = EXTRASPACEY;
+ nFirstEntry = 0;
+ bScrollUp = FALSE;
+ bScrollDown = FALSE;
+ bIgnoreFirstMove = TRUE;
+ bKeyInput = FALSE;
+
+ EnableSaveBackground();
+ ImplInitMenuWindow( this, TRUE, FALSE );
+
+ SetPopupModeEndHdl( LINK( this, MenuFloatingWindow, PopupEnd ) );
+
+ aHighlightChangedTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, HighlightChanged ) );
+ aHighlightChangedTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
+ aSubmenuCloseTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
+ aSubmenuCloseTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, SubmenuClose ) );
+ aScrollTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, AutoScroll ) );
+
+ AddEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
+}
+
+void MenuFloatingWindow::doShutdown()
+{
+ if( pMenu )
+ {
+ // #105373# notify toolkit that highlight was removed
+ // otherwise the entry will not be read when the menu is opened again
+ if( nHighlightedItem != ITEMPOS_INVALID )
+ pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
+
+ if( !bKeyInput && pMenu && pMenu->pStartedFrom && !pMenu->pStartedFrom->bIsMenuBar )
+ {
+ // #102461# remove highlight in parent
+ MenuItemData* pData;
+ USHORT i, nCount = (USHORT)pMenu->pStartedFrom->pItemList->Count();
+ for(i = 0; i < nCount; i++)
+ {
+ pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
+ if( pData && ( pData->pSubMenu == pMenu ) )
+ break;
+ }
+ if( i < nCount )
+ {
+ MenuFloatingWindow* pPWin = (MenuFloatingWindow*)pMenu->pStartedFrom->ImplGetWindow();
+ if( pPWin )
+ pPWin->HighlightItem( i, FALSE );
+ }
+ }
+
+ // free the reference to the accessible component
+ SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
+
+ aHighlightChangedTimer.Stop();
+
+ // #95056# invalidate screen area covered by system window
+ // so this can be taken into account if the commandhandler performs a scroll operation
+ if( GetParent() )
+ {
+ Rectangle aInvRect( GetWindowExtentsRelative( GetParent() ) );
+ GetParent()->Invalidate( aInvRect );
+ }
+ pMenu = NULL;
+ RemoveEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
+ }
+}
+
+MenuFloatingWindow::~MenuFloatingWindow()
+{
+ doShutdown();
+}
+
+void MenuFloatingWindow::Resize()
+{
+ ImplInitClipRegion();
+}
+
+long MenuFloatingWindow::ImplGetStartY() const
+{
+ long nY = 0;
+ if( pMenu )
+ {
+ for ( USHORT n = 0; n < nFirstEntry; n++ )
+ nY += pMenu->GetItemList()->GetDataFromPos( n )->aSz.Height();
+ }
+ return -nY;
+}
+
+Region MenuFloatingWindow::ImplCalcClipRegion( BOOL bIncludeLogo ) const
+{
+ Size aOutSz = GetOutputSizePixel();
+ Point aPos;
+ Rectangle aRect( aPos, aOutSz );
+ aRect.Top() += nScrollerHeight;
+ aRect.Bottom() -= nScrollerHeight;
+
+ if ( pMenu && pMenu->pLogo && !bIncludeLogo )
+ aRect.Left() += pMenu->pLogo->aBitmap.GetSizePixel().Width();
+
+ Region aRegion = aRect;
+ if ( pMenu && pMenu->pLogo && bIncludeLogo && nScrollerHeight )
+ aRegion.Union( Rectangle( Point(), Size( pMenu->pLogo->aBitmap.GetSizePixel().Width(), aOutSz.Height() ) ) );
+
+ return aRegion;
+}
+
+void MenuFloatingWindow::ImplInitClipRegion()
+{
+ if ( IsScrollMenu() )
+ {
+ SetClipRegion( ImplCalcClipRegion() );
+ }
+ else
+ {
+ SetClipRegion();
+ }
+}
+
+void MenuFloatingWindow::ImplHighlightItem( const MouseEvent& rMEvt, BOOL bMBDown )
+{
+ if( ! pMenu )
+ return;
+
+ long nY = nScrollerHeight;
+ long nMouseY = rMEvt.GetPosPixel().Y();
+ Size aOutSz = GetOutputSizePixel();
+ if ( ( nMouseY >= nY ) && ( nMouseY < ( aOutSz.Height() - nY ) ) )
+ {
+ BOOL bHighlighted = FALSE;
+ USHORT nCount = (USHORT)pMenu->pItemList->Count();
+ nY += ImplGetStartY(); // ggf. gescrollt.
+ for ( USHORT n = 0; !bHighlighted && ( n < nCount ); n++ )
+ {
+ if ( pMenu->ImplIsVisible( n ) )
+ {
+ MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( n );
+ long nOldY = nY;
+ nY += pItemData->aSz.Height();
+ if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) && pMenu->ImplIsSelectable( n ) )
+ {
+ BOOL bPopupArea = TRUE;
+ if ( pItemData->nBits & MIB_POPUPSELECT )
+ {
+ // Nur wenn ueber dem Pfeil geklickt wurde...
+ Size aSz = GetOutputSizePixel();
+ long nFontHeight = GetTextHeight();
+ bPopupArea = ( rMEvt.GetPosPixel().X() >= ( aSz.Width() - nFontHeight - nFontHeight/4 ) );
+ }
+
+ if ( bMBDown )
+ {
+ if ( n != nHighlightedItem )
+ {
+ ChangeHighlightItem( (USHORT)n, FALSE );
+ }
+
+ BOOL bAllowNewPopup = TRUE;
+ if ( pActivePopup )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ bAllowNewPopup = pData && ( pData->pSubMenu != pActivePopup );
+ if ( bAllowNewPopup )
+ KillActivePopup();
+ }
+
+ if ( bPopupArea && bAllowNewPopup )
+ {
+ HighlightChanged( NULL );
+ }
+ }
+ else
+ {
+ if ( n != nHighlightedItem )
+ {
+ ChangeHighlightItem( (USHORT)n, TRUE );
+ }
+ else if ( pItemData->nBits & MIB_POPUPSELECT )
+ {
+ if ( bPopupArea && ( pActivePopup != pItemData->pSubMenu ) )
+ HighlightChanged( NULL );
+ }
+ }
+ bHighlighted = TRUE;
+ }
+ }
+ }
+ if ( !bHighlighted )
+ ChangeHighlightItem( ITEMPOS_INVALID, TRUE );
+ }
+ else
+ {
+ ImplScroll( rMEvt.GetPosPixel() );
+ ChangeHighlightItem( ITEMPOS_INVALID, TRUE );
+ }
+}
+
+IMPL_LINK( MenuFloatingWindow, PopupEnd, FloatingWindow*, EMPTYARG )
+{
+ // "this" will be deleted before the end of this method!
+ Menu* pM = pMenu;
+ if ( bInExecute )
+ {
+ if ( pActivePopup )
+ {
+ //DBG_ASSERT( !pActivePopup->ImplGetWindow(), "PopupEnd, obwohl pActivePopup MIT Window!" );
+ KillActivePopup(); // should be ok to just remove it
+ //pActivePopup->bCanceled = TRUE;
+ }
+ bInExecute = FALSE;
+ pMenu->bInCallback = TRUE;
+ pMenu->Deactivate();
+ pMenu->bInCallback = FALSE;
+ }
+ else
+ {
+ if( pMenu )
+ {
+ // Wenn dies Fenster von TH geschlossen wurde, hat noch ein anderes
+ // Menu dieses Fenster als pActivePopup.
+ if ( pMenu->pStartedFrom )
+ {
+ // Das pWin am 'Parent' kann aber schon 0 sein, falls die Kette von
+ // vorne abgeraeumt wurde und jetzt die EndPopup-Events eintrudeln
+ if ( pMenu->pStartedFrom->bIsMenuBar )
+ {
+ MenuBarWindow* p = (MenuBarWindow*) pMenu->pStartedFrom->ImplGetWindow();
+ if ( p )
+ p->PopupClosed( pMenu );
+ }
+ else
+ {
+ MenuFloatingWindow* p = (MenuFloatingWindow*) pMenu->pStartedFrom->ImplGetWindow();
+ if ( p )
+ p->KillActivePopup( (PopupMenu*)pMenu );
+ }
+ }
+ }
+ }
+
+ if ( pM )
+ pM->pStartedFrom = 0;
+
+ return 0;
+}
+
+IMPL_LINK( MenuFloatingWindow, AutoScroll, Timer*, EMPTYARG )
+{
+ ImplScroll( GetPointerPosPixel() );
+ return 1;
+}
+
+IMPL_LINK( MenuFloatingWindow, HighlightChanged, Timer*, pTimer )
+{
+ if( ! pMenu )
+ return 0;
+
+ MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
+ if ( pItemData )
+ {
+ if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
+ {
+ ULONG nOldFlags = GetPopupModeFlags();
+ SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE );
+ KillActivePopup();
+ SetPopupModeFlags( nOldFlags );
+ }
+ if ( pItemData->bEnabled && pItemData->pSubMenu && pItemData->pSubMenu->GetItemCount() && ( pItemData->pSubMenu != pActivePopup ) )
+ {
+ pActivePopup = (PopupMenu*)pItemData->pSubMenu;
+ long nY = nScrollerHeight+ImplGetStartY();
+ MenuItemData* pData = 0;
+ for ( ULONG n = 0; n < nHighlightedItem; n++ )
+ {
+ pData = pMenu->pItemList->GetDataFromPos( n );
+ nY += pData->aSz.Height();
+ }
+ pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
+ Size MySize = GetOutputSizePixel();
+// Point MyPos = GetPosPixel();
+// Point aItemTopLeft( MyPos.X(), MyPos.Y()+nY );
+ Point aItemTopLeft( 0, nY );
+ Point aItemBottomRight( aItemTopLeft );
+ aItemBottomRight.X() += MySize.Width();
+ aItemBottomRight.Y() += pData->aSz.Height();
+
+ // Popups leicht versetzen:
+ aItemTopLeft.X() += 2;
+ aItemBottomRight.X() -= 2;
+ if ( nHighlightedItem )
+ aItemTopLeft.Y() -= 2;
+ else
+ {
+ sal_Int32 nL, nT, nR, nB;
+ GetBorder( nL, nT, nR, nB );
+ aItemTopLeft.Y() -= nT;
+ }
+
+ // pTest: Wegen Abstuerzen durch Reschedule() im Aufruf von Activate()
+ // Ausserdem wird damit auch verhindert, dass SubMenus angezeigt werden,
+ // die lange im Activate Rescheduled haben und jetzt schon nicht mehr
+ // angezeigt werden sollen.
+ Menu* pTest = pActivePopup;
+ ULONG nOldFlags = GetPopupModeFlags();
+ SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE );
+ USHORT nRet = pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_RIGHT, pMenu, pTimer ? FALSE : TRUE );
+ SetPopupModeFlags( nOldFlags );
+
+ // nRet != 0, wenn es waerend Activate() abgeschossen wurde...
+ if ( !nRet && ( pActivePopup == pTest ) && pActivePopup->ImplGetWindow() )
+ pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
+ }
+ }
+
+ return 0;
+}
+
+IMPL_LINK( MenuFloatingWindow, SubmenuClose, Timer*, EMPTYARG )
+{
+ if( pMenu && pMenu->pStartedFrom )
+ {
+ MenuFloatingWindow* pWin = (MenuFloatingWindow*) pMenu->pStartedFrom->GetWindow();
+ if( pWin )
+ pWin->KillActivePopup();
+ }
+ return 0;
+}
+
+IMPL_LINK( MenuFloatingWindow, ShowHideListener, VclWindowEvent*, pEvent )
+{
+ if( ! pMenu )
+ return 0;
+
+ if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
+ pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
+ else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
+ pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
+ return 0;
+}
+
+void MenuFloatingWindow::EnableScrollMenu( BOOL b )
+{
+ bScrollMenu = b;
+ nScrollerHeight = b ? (USHORT) GetSettings().GetStyleSettings().GetScrollBarSize() /2 : 0;
+ bScrollDown = TRUE;
+ ImplInitClipRegion();
+}
+
+void MenuFloatingWindow::Execute()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ pSVData->maAppData.mpActivePopupMenu = (PopupMenu*)pMenu;
+
+ bInExecute = TRUE;
+// bCallingSelect = FALSE;
+
+ while ( bInExecute )
+ Application::Yield();
+
+ pSVData->maAppData.mpActivePopupMenu = NULL;
+
+// while ( bCallingSelect )
+// Application::Yield();
+}
+
+void MenuFloatingWindow::StopExecute( ULONG nFocusId )
+{
+ // Focus wieder herstellen
+ // (kann schon im Select wieder hergestellt wurden sein)
+ if ( nSaveFocusId )
+ {
+ Window::EndSaveFocus( nFocusId, FALSE );
+ nFocusId = nSaveFocusId;
+ if ( nFocusId )
+ {
+ nSaveFocusId = 0;
+ ImplGetSVData()->maWinData.mbNoDeactivate = FALSE;
+ }
+ }
+ ImplEndPopupMode( 0, nFocusId );
+
+ aHighlightChangedTimer.Stop();
+ bInExecute = FALSE;
+ if ( pActivePopup )
+ {
+ KillActivePopup();
+ }
+ // notify parent, needed for accessibility
+ if( pMenu && pMenu->pStartedFrom )
+ pMenu->pStartedFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUDEACTIVATE, nPosInParent );
+}
+
+void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly )
+{
+ if ( pActivePopup && ( !pThisOnly || ( pThisOnly == pActivePopup ) ) )
+ {
+ if( pActivePopup->pWindow != NULL )
+ if( ((FloatingWindow *) pActivePopup->pWindow)->IsInCleanUp() )
+ return; // kill it later
+ if ( pActivePopup->bInCallback )
+ pActivePopup->bCanceled = TRUE;
+
+ // Vor allen Aktionen schon pActivePopup = 0, falls z.B.
+ // PopupModeEndHdl des zu zerstoerenden Popups mal synchron gerufen wird.
+ PopupMenu* pPopup = pActivePopup;
+ pActivePopup = NULL;
+ pPopup->bInCallback = TRUE;
+ pPopup->Deactivate();
+ pPopup->bInCallback = FALSE;
+ if ( pPopup->ImplGetWindow() )
+ {
+ pPopup->ImplGetFloatingWindow()->StopExecute();
+ pPopup->ImplGetFloatingWindow()->doShutdown();
+ pPopup->pWindow->doLazyDelete();
+ pPopup->pWindow = NULL;
+
+ Update();
+ }
+ }
+}
+
+void MenuFloatingWindow::EndExecute()
+{
+ Menu* pStart = pMenu ? pMenu->ImplGetStartMenu() : NULL;
+ ULONG nFocusId = 0;
+ if ( pStart && pStart->bIsMenuBar )
+ {
+ nFocusId = ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->GetFocusId();
+ if ( nFocusId )
+ {
+ ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->SetFocusId( 0 );
+ ImplGetSVData()->maWinData.mbNoDeactivate = FALSE;
+ }
+ }
+
+ // Wenn von woanders gestartet, dann ab dort aufraumen:
+ MenuFloatingWindow* pCleanUpFrom = this;
+ MenuFloatingWindow* pWin = this;
+ while ( pWin && !pWin->bInExecute &&
+ pWin->pMenu->pStartedFrom && !pWin->pMenu->pStartedFrom->bIsMenuBar )
+ {
+ pWin = ((PopupMenu*)pWin->pMenu->pStartedFrom)->ImplGetFloatingWindow();
+ }
+ if ( pWin )
+ pCleanUpFrom = pWin;
+
+ // Dies Fenster wird gleich zerstoert => Daten lokal merken...
+ Menu* pM = pMenu;
+ USHORT nItem = nHighlightedItem;
+
+ pCleanUpFrom->StopExecute( nFocusId );
+
+ if ( nItem != ITEMPOS_INVALID && pM )
+ {
+ MenuItemData* pItemData = pM->GetItemList()->GetDataFromPos( nItem );
+ if ( pItemData && !pItemData->bIsTemporary )
+ {
+ pM->nSelectedId = pItemData->nId;
+ if ( pStart )
+ pStart->nSelectedId = pItemData->nId;
+
+ pM->ImplSelect();
+ }
+ }
+}
+
+void MenuFloatingWindow::EndExecute( USHORT nId )
+{
+ USHORT nPos;
+ if ( pMenu && pMenu->GetItemList()->GetData( nId, nPos ) )
+ nHighlightedItem = nPos;
+ else
+ nHighlightedItem = ITEMPOS_INVALID;
+
+ EndExecute();
+}
+
+void MenuFloatingWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // TH macht ein ToTop auf dieses Fenster, aber das aktive Popup
+ // soll oben bleiben...
+ // due to focus chage this would close all menues -> don't do it (#94123)
+ //if ( pActivePopup && pActivePopup->ImplGetWindow() && !pActivePopup->ImplGetFloatingWindow()->pActivePopup )
+ // pActivePopup->ImplGetFloatingWindow()->ToTop( TOTOP_NOGRABFOCUS );
+
+ ImplHighlightItem( rMEvt, TRUE );
+
+ nMBDownPos = nHighlightedItem;
+}
+
+void MenuFloatingWindow::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ MenuItemData* pData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
+ // nMBDownPos in lokaler Variable merken und gleich zuruecksetzen,
+ // weil nach EndExecute zu spaet
+ USHORT _nMBDownPos = nMBDownPos;
+ nMBDownPos = ITEMPOS_INVALID;
+ if ( pData && pData->bEnabled && ( pData->eType != MENUITEM_SEPARATOR ) )
+ {
+ if ( !pData->pSubMenu )
+ {
+ EndExecute();
+ }
+ else if ( ( pData->nBits & MIB_POPUPSELECT ) && ( nHighlightedItem == _nMBDownPos ) && ( rMEvt.GetClicks() == 2 ) )
+ {
+ // Nicht wenn ueber dem Pfeil geklickt wurde...
+ Size aSz = GetOutputSizePixel();
+ long nFontHeight = GetTextHeight();
+ if ( rMEvt.GetPosPixel().X() < ( aSz.Width() - nFontHeight - nFontHeight/4 ) )
+ EndExecute();
+ }
+ }
+
+}
+
+void MenuFloatingWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( !IsVisible() || rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
+ return;
+
+ if ( rMEvt.IsLeaveWindow() )
+ {
+#ifdef OS2
+ if ( ImplHilite(rMEvt) )
+ {
+#endif
+ // #102461# do not remove highlight if a popup menu is open at this position
+ MenuItemData* pData = pMenu ? pMenu->pItemList->GetDataFromPos( nHighlightedItem ) : NULL;
+ // close popup with some delayed if we leave somewhere else
+ if( pActivePopup && pData && pData->pSubMenu != pActivePopup )
+ pActivePopup->ImplGetFloatingWindow()->aSubmenuCloseTimer.Start();
+
+ if( !pActivePopup || (pData && pData->pSubMenu != pActivePopup ) )
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+#ifdef OS2
+ }
+#endif
+
+ if ( IsScrollMenu() )
+ ImplScroll( rMEvt.GetPosPixel() );
+ }
+ else
+#ifdef OS2
+ if ( ImplHilite(rMEvt) )
+#endif
+ {
+ aSubmenuCloseTimer.Stop();
+ if( bIgnoreFirstMove )
+ bIgnoreFirstMove = FALSE;
+ else
+ ImplHighlightItem( rMEvt, FALSE );
+ }
+}
+
+void MenuFloatingWindow::ImplScroll( BOOL bUp )
+{
+ KillActivePopup();
+ Update();
+
+ if( ! pMenu )
+ return;
+
+ HighlightItem( nHighlightedItem, FALSE );
+
+ pMenu->ImplKillLayoutData();
+
+ if ( bScrollUp && bUp )
+ {
+ nFirstEntry = pMenu->ImplGetPrevVisible( nFirstEntry );
+ DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
+
+ long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
+
+// nStartY += nEntryHeight;
+
+ if ( !bScrollDown )
+ {
+ bScrollDown = TRUE;
+ ImplDrawScroller( FALSE );
+ }
+
+ if ( pMenu->ImplGetPrevVisible( nFirstEntry ) == ITEMPOS_INVALID )
+ {
+ bScrollUp = FALSE;
+ ImplDrawScroller( TRUE );
+ }
+
+ Scroll( 0, nScrollEntryHeight, ImplCalcClipRegion( FALSE ).GetBoundRect(), SCROLL_CLIP );
+ }
+ else if ( bScrollDown && !bUp )
+ {
+ long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
+
+ nFirstEntry = pMenu->ImplGetNextVisible( nFirstEntry );
+ DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
+
+
+ if ( !bScrollUp )
+ {
+ bScrollUp = TRUE;
+ ImplDrawScroller( TRUE );
+ }
+
+ long nHeight = GetOutputSizePixel().Height();
+ USHORT nLastVisible;
+ ((PopupMenu*)pMenu)->ImplCalcVisEntries( nHeight, nFirstEntry, &nLastVisible );
+ if ( pMenu->ImplGetNextVisible( nLastVisible ) == ITEMPOS_INVALID )
+ {
+ bScrollDown = FALSE;
+ ImplDrawScroller( FALSE );
+ }
+
+// nStartY -= nEntryHeight;
+ Scroll( 0, -nScrollEntryHeight, ImplCalcClipRegion( FALSE ).GetBoundRect(), SCROLL_CLIP );
+ }
+
+ HighlightItem( nHighlightedItem, TRUE );
+}
+
+void MenuFloatingWindow::ImplScroll( const Point& rMousePos )
+{
+ Size aOutSz = GetOutputSizePixel();
+
+ long nY = nScrollerHeight;
+ long nMouseY = rMousePos.Y();
+ long nDelta = 0;
+
+ if ( bScrollUp && ( nMouseY < nY ) )
+ {
+ ImplScroll( TRUE );
+ nDelta = nY - nMouseY;
+ }
+ else if ( bScrollDown && ( nMouseY > ( aOutSz.Height() - nY ) ) )
+ {
+ ImplScroll( FALSE );
+ nDelta = nMouseY - ( aOutSz.Height() - nY );
+ }
+
+ if ( nDelta )
+ {
+ aScrollTimer.Stop(); // Falls durch MouseMove gescrollt.
+ long nTimeout;
+ if ( nDelta < 3 )
+ nTimeout = 200;
+ else if ( nDelta < 5 )
+ nTimeout = 100;
+ else if ( nDelta < 8 )
+ nTimeout = 70;
+ else if ( nDelta < 12 )
+ nTimeout = 40;
+ else
+ nTimeout = 20;
+ aScrollTimer.SetTimeout( nTimeout );
+ aScrollTimer.Start();
+ }
+}
+void MenuFloatingWindow::ChangeHighlightItem( USHORT n, BOOL bStartPopupTimer )
+{
+ // #57934# ggf. das aktive Popup sofort schliessen, damit TH's Hintergrundsicherung funktioniert.
+ // #65750# Dann verzichten wir lieber auf den schmalen Streifen Hintergrundsicherung.
+ // Sonst lassen sich die Menus schlecht bedienen.
+// MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
+// if ( pActivePopup && pNextData && ( pActivePopup != pNextData->pSubMenu ) )
+// KillActivePopup();
+
+ aSubmenuCloseTimer.Stop();
+ if( ! pMenu )
+ return;
+
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ {
+ HighlightItem( nHighlightedItem, FALSE );
+ pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
+ }
+
+ nHighlightedItem = (USHORT)n;
+ DBG_ASSERT( pMenu->ImplIsVisible( nHighlightedItem ) || nHighlightedItem == ITEMPOS_INVALID, "ChangeHighlightItem: Not visible!" );
+ if( nHighlightedItem != ITEMPOS_INVALID )
+ {
+ if( pMenu->pStartedFrom && !pMenu->pStartedFrom->bIsMenuBar )
+ {
+ // #102461# make sure parent entry is highlighted as well
+ MenuItemData* pData;
+ USHORT i, nCount = (USHORT)pMenu->pStartedFrom->pItemList->Count();
+ for(i = 0; i < nCount; i++)
+ {
+ pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
+ if( pData && ( pData->pSubMenu == pMenu ) )
+ break;
+ }
+ if( i < nCount )
+ {
+ MenuFloatingWindow* pPWin = (MenuFloatingWindow*)pMenu->pStartedFrom->ImplGetWindow();
+ if( pPWin && pPWin->nHighlightedItem != i )
+ {
+ pPWin->HighlightItem( i, TRUE );
+ pPWin->nHighlightedItem = i;
+ }
+ }
+ }
+ HighlightItem( nHighlightedItem, TRUE );
+ pMenu->ImplCallHighlight( nHighlightedItem );
+ }
+ else
+ pMenu->nSelectedId = 0;
+
+ if ( bStartPopupTimer )
+ {
+ // #102438# Menu items are not selectable
+ // If a menu item is selected by an AT-tool via the XAccessibleAction, XAccessibleValue
+ // or XAccessibleSelection interface, and the parent popup menus are not executed yet,
+ // the parent popup menus must be executed SYNCHRONOUSLY, before the menu item is selected.
+ if ( GetSettings().GetMouseSettings().GetMenuDelay() )
+ aHighlightChangedTimer.Start();
+ else
+ HighlightChanged( &aHighlightChangedTimer );
+ }
+}
+
+void MenuFloatingWindow::HighlightItem( USHORT nPos, BOOL bHighlight )
+{
+ if( ! pMenu )
+ return;
+
+ Size aSz = GetOutputSizePixel();
+ long nStartY = ImplGetStartY();
+ long nY = nScrollerHeight+nStartY;
+ long nX = 0;
+
+ if ( pMenu->pLogo )
+ nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
+
+ int nOuterSpace = ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder;
+ nY += nOuterSpace;
+
+ USHORT nCount = (USHORT)pMenu->pItemList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ if ( n == nPos )
+ {
+ DBG_ASSERT( pMenu->ImplIsVisible( n ), "Highlight: Item not visible!" );
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ {
+ BOOL bRestoreLineColor = FALSE;
+ Color oldLineColor;
+ bool bDrawItemRect = true;
+
+ Rectangle aItemRect( Point( nX+nOuterSpace, nY ), Size( aSz.Width()-2*nOuterSpace, pData->aSz.Height() ) );
+ if ( pData->nBits & MIB_POPUPSELECT )
+ {
+ long nFontHeight = GetTextHeight();
+ aItemRect.Right() -= nFontHeight + nFontHeight/4;
+ }
+
+ if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
+ {
+ Size aPxSize( GetOutputSizePixel() );
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) ) );
+ Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) );
+ DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
+ aCtrlRect,
+ CTRL_STATE_ENABLED,
+ ImplControlValue(),
+ OUString() );
+ if( bHighlight &&
+ IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) )
+ {
+ bDrawItemRect = false;
+ if( FALSE == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM,
+ aItemRect,
+ CTRL_STATE_SELECTED | ( pData->bEnabled? CTRL_STATE_ENABLED: 0 ),
+ ImplControlValue(),
+ OUString() ) )
+ {
+ bDrawItemRect = bHighlight;
+ }
+ }
+ else
+ bDrawItemRect = bHighlight;
+ Pop();
+ }
+ if( bDrawItemRect )
+ {
+ if ( bHighlight )
+ {
+ if( pData->bEnabled )
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
+ else
+ {
+ SetFillColor();
+ oldLineColor = GetLineColor();
+ SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
+ bRestoreLineColor = TRUE;
+ }
+ }
+ else
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
+
+ DrawRect( aItemRect );
+ }
+ pMenu->ImplPaint( this, nScrollerHeight, nStartY, pData, bHighlight );
+ if( bRestoreLineColor )
+ SetLineColor( oldLineColor );
+ }
+ return;
+ }
+
+ nY += pData->aSz.Height();
+ }
+}
+
+Rectangle MenuFloatingWindow::ImplGetItemRect( USHORT nPos )
+{
+ if( ! pMenu )
+ return Rectangle();
+
+ Rectangle aRect;
+ Size aSz = GetOutputSizePixel();
+ long nStartY = ImplGetStartY();
+ long nY = nScrollerHeight+nStartY;
+ long nX = 0;
+
+ if ( pMenu->pLogo )
+ nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
+
+ USHORT nCount = (USHORT)pMenu->pItemList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ if ( n == nPos )
+ {
+ DBG_ASSERT( pMenu->ImplIsVisible( n ), "ImplGetItemRect: Item not visible!" );
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ {
+ aRect = Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) );
+ if ( pData->nBits & MIB_POPUPSELECT )
+ {
+ long nFontHeight = GetTextHeight();
+ aRect.Right() -= nFontHeight + nFontHeight/4;
+ }
+ }
+ break;
+ }
+ nY += pData->aSz.Height();
+ }
+ return aRect;
+}
+
+
+void MenuFloatingWindow::ImplCursorUpDown( BOOL bUp, BOOL bHomeEnd )
+{
+ if( ! pMenu )
+ return;
+
+ const StyleSettings& rSettings = GetSettings().GetStyleSettings();
+
+ USHORT n = nHighlightedItem;
+ if ( n == ITEMPOS_INVALID )
+ {
+ if ( bUp )
+ n = 0;
+ else
+ n = pMenu->GetItemCount()-1;
+ }
+
+ USHORT nLoop = n;
+
+ if( bHomeEnd )
+ {
+ // absolute positioning
+ if( bUp )
+ {
+ n = pMenu->GetItemCount();
+ nLoop = n-1;
+ }
+ else
+ {
+ n = (USHORT)-1;
+ nLoop = n+1;
+ }
+ }
+
+ do
+ {
+ if ( bUp )
+ {
+ if ( n )
+ n--;
+ else
+ if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
+ n = pMenu->GetItemCount()-1;
+ else
+ break;
+ }
+ else
+ {
+ n++;
+ if ( n >= pMenu->GetItemCount() )
+ {
+ if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
+ n = 0;
+ else
+ break;
+ }
+ }
+
+ MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
+ if ( ( pData->bEnabled || !rSettings.GetSkipDisabledInMenus() )
+ && ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) && pMenu->ImplIsSelectable( n ) )
+ {
+ // Selektion noch im sichtbaren Bereich?
+ if ( IsScrollMenu() )
+ {
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+
+ while ( n < nFirstEntry )
+ ImplScroll( TRUE );
+
+ Size aOutSz = GetOutputSizePixel();
+ USHORT nLastVisible;
+ ((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
+ while ( n > nLastVisible )
+ {
+ ImplScroll( FALSE );
+ ((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
+ }
+ }
+ ChangeHighlightItem( n, FALSE );
+ break;
+ }
+ } while ( n != nLoop );
+}
+
+void MenuFloatingWindow::KeyInput( const KeyEvent& rKEvent )
+{
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+
+ USHORT nCode = rKEvent.GetKeyCode().GetCode();
+ bKeyInput = TRUE;
+ switch ( nCode )
+ {
+ case KEY_UP:
+ case KEY_DOWN:
+ {
+ ImplCursorUpDown( nCode == KEY_UP );
+ }
+ break;
+ case KEY_END:
+ case KEY_HOME:
+ {
+ ImplCursorUpDown( nCode == KEY_END, TRUE );
+ }
+ break;
+ case KEY_F6:
+ case KEY_ESCAPE:
+ {
+ // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
+ if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() )
+ break;
+ if( pMenu )
+ {
+ if ( !pMenu->pStartedFrom )
+ {
+ StopExecute();
+ KillActivePopup();
+ }
+ else if ( pMenu->pStartedFrom->bIsMenuBar )
+ {
+ // Forward...
+ ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
+ }
+ else
+ {
+ StopExecute();
+ PopupMenu* pPopupMenu = (PopupMenu*)pMenu->pStartedFrom;
+ MenuFloatingWindow* pFloat = pPopupMenu->ImplGetFloatingWindow();
+ pFloat->GrabFocus();
+ pFloat->KillActivePopup();
+ pPopupMenu->ImplCallHighlight(pFloat->nHighlightedItem);
+ }
+ }
+ }
+ break;
+ case KEY_LEFT:
+ {
+ if ( pMenu && pMenu->pStartedFrom )
+ {
+ StopExecute();
+ if ( pMenu->pStartedFrom->bIsMenuBar )
+ {
+ // Forward...
+ ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
+ }
+ else
+ {
+ MenuFloatingWindow* pFloat = ((PopupMenu*)pMenu->pStartedFrom)->ImplGetFloatingWindow();
+ pFloat->GrabFocus();
+ pFloat->KillActivePopup();
+ }
+ }
+ }
+ break;
+ case KEY_RIGHT:
+ {
+ if( pMenu )
+ {
+ BOOL bDone = FALSE;
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ {
+ MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
+ if ( pData && pData->pSubMenu )
+ {
+ HighlightChanged( 0 );
+ bDone = TRUE;
+ }
+ }
+ if ( !bDone )
+ {
+ Menu* pStart = pMenu->ImplGetStartMenu();
+ if ( pStart && pStart->bIsMenuBar )
+ {
+ // Forward...
+ pStart->ImplGetWindow()->KeyInput( rKEvent );
+ }
+ }
+ }
+ }
+ break;
+ case KEY_RETURN:
+ {
+ if( pMenu )
+ {
+ MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
+ if ( pData && pData->bEnabled )
+ {
+ if ( pData->pSubMenu )
+ HighlightChanged( 0 );
+ else
+ EndExecute();
+ }
+ else
+ StopExecute();
+ }
+ }
+ break;
+ case KEY_MENU:
+ {
+ if( pMenu )
+ {
+ Menu* pStart = pMenu->ImplGetStartMenu();
+ if ( pStart && pStart->bIsMenuBar )
+ {
+ // Forward...
+ pStart->ImplGetWindow()->KeyInput( rKEvent );
+ }
+ }
+ }
+ break;
+ default:
+ {
+ xub_Unicode nCharCode = rKEvent.GetCharCode();
+ USHORT nPos = 0;
+ USHORT nDuplicates = 0;
+ MenuItemData* pData = (nCharCode && pMenu) ? pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nPos, nDuplicates, nHighlightedItem ) : NULL;
+ if ( pData )
+ {
+ if ( pData->pSubMenu || nDuplicates > 1 )
+ {
+ ChangeHighlightItem( nPos, FALSE );
+ HighlightChanged( 0 );
+ }
+ else
+ {
+ nHighlightedItem = nPos;
+ EndExecute();
+ }
+ }
+ else
+ {
+ // Bei ungueltigen Tasten Beepen, aber nicht bei HELP und F-Tasten
+ if ( !rKEvent.GetKeyCode().IsMod2() && ( nCode != KEY_HELP ) && ( rKEvent.GetKeyCode().GetGroup() != KEYGROUP_FKEYS ) )
+ Sound::Beep();
+ FloatingWindow::KeyInput( rKEvent );
+ }
+ }
+ }
+ // #105474# check if menu window was not destroyed
+ if ( !aDelData.IsDelete() )
+ {
+ ImplRemoveDel( &aDelData );
+ bKeyInput = FALSE;
+ }
+}
+
+void MenuFloatingWindow::Paint( const Rectangle& )
+{
+ if( ! pMenu )
+ return;
+
+ if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
+ {
+ SetClipRegion();
+ long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
+ Size aPxSize( GetOutputSizePixel() );
+ aPxSize.Width() -= nX;
+ DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
+ Rectangle( Point( nX, 0 ), aPxSize ),
+ CTRL_STATE_ENABLED,
+ ImplControlValue(),
+ OUString() );
+ ImplInitClipRegion();
+ }
+ if ( IsScrollMenu() )
+ {
+ ImplDrawScroller( TRUE );
+ ImplDrawScroller( FALSE );
+ }
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
+ pMenu->ImplPaint( this, nScrollerHeight, ImplGetStartY() );
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ HighlightItem( nHighlightedItem, TRUE );
+}
+
+void MenuFloatingWindow::ImplDrawScroller( BOOL bUp )
+{
+ if( ! pMenu )
+ return;
+
+ SetClipRegion();
+
+ Size aOutSz = GetOutputSizePixel();
+ long nY = bUp ? 0 : ( aOutSz.Height() - nScrollerHeight );
+ long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
+ Rectangle aRect( Point( nX, nY ), Size( aOutSz.Width()-nX, nScrollerHeight ) );
+
+ DecorationView aDecoView( this );
+ SymbolType eSymbol = bUp ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN;
+
+ USHORT nStyle = 0;
+ if ( ( bUp && !bScrollUp ) || ( !bUp && !bScrollDown ) )
+ nStyle |= SYMBOL_DRAW_DISABLE;
+
+ aDecoView.DrawSymbol( aRect, eSymbol, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle );
+
+ ImplInitClipRegion();
+}
+
+void MenuFloatingWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT nId = nHighlightedItem;
+ Menu* pM = pMenu;
+ Window* pW = this;
+
+ // #102618# Get item rect before destroying the window in EndExecute() call
+ Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
+
+ if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
+ {
+ nHighlightedItem = ITEMPOS_INVALID;
+ EndExecute();
+ pW = NULL;
+ }
+
+ if( !ImplHandleHelpEvent( pW, pM, nId, rHEvt, aHighlightRect ) )
+ Window::RequestHelp( rHEvt );
+}
+
+void MenuFloatingWindow::StateChanged( StateChangedType nType )
+{
+ FloatingWindow::StateChanged( nType );
+
+ if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
+ {
+ ImplInitMenuWindow( this, FALSE, FALSE );
+ Invalidate();
+ }
+}
+
+void MenuFloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ FloatingWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitMenuWindow( this, FALSE, FALSE );
+ Invalidate();
+ }
+}
+
+void MenuFloatingWindow::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
+ {
+// ImplCursorUpDown( pData->GetDelta() > 0L );
+ ImplScroll( pData->GetDelta() > 0L );
+ MouseMove( MouseEvent( GetPointerPosPixel(), 0 ) );
+ }
+ }
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > MenuFloatingWindow::CreateAccessible()
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
+
+ if ( pMenu && !pMenu->pStartedFrom )
+ xAcc = pMenu->GetAccessible();
+
+ return xAcc;
+}
+
+MenuBarWindow::MenuBarWindow( Window* pParent ) :
+ Window( pParent, 0 ),
+ aCloser( this ),
+ aFloatBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE ),
+ aHideBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE )
+{
+ SetType( WINDOW_MENUBARWINDOW );
+ pMenu = NULL;
+ pActivePopup = NULL;
+ nSaveFocusId = 0;
+ nHighlightedItem = ITEMPOS_INVALID;
+ mbAutoPopup = TRUE;
+ nSaveFocusId = 0;
+ bIgnoreFirstMove = TRUE;
+ bStayActive = FALSE;
+
+ ResMgr* pResMgr = ImplGetResMgr();
+
+ if( pResMgr )
+ {
+ BitmapEx aBitmap( ResId( SV_RESID_BITMAP_CLOSEDOC, *pResMgr ) );
+ BitmapEx aBitmapHC( ResId( SV_RESID_BITMAP_CLOSEDOCHC, *pResMgr ) );
+
+ aCloser.maImage = Image( aBitmap );
+ aCloser.maImageHC = Image( aBitmapHC );
+
+ aCloser.SetOutStyle( TOOLBOX_STYLE_FLAT );
+ aCloser.SetBackground();
+ aCloser.SetPaintTransparent( TRUE );
+ aCloser.SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+
+ aCloser.InsertItem( IID_DOCUMENTCLOSE,
+ GetSettings().GetStyleSettings().GetHighContrastMode() ? aCloser.maImageHC : aCloser.maImage, 0 );
+ aCloser.SetSelectHdl( LINK( this, MenuBarWindow, CloserHdl ) );
+ aCloser.AddEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
+ aCloser.SetQuickHelpText( IID_DOCUMENTCLOSE, XubString( ResId( SV_HELPTEXT_CLOSEDOCUMENT, *pResMgr ) ) );
+
+ aFloatBtn.SetClickHdl( LINK( this, MenuBarWindow, FloatHdl ) );
+ aFloatBtn.SetSymbol( SYMBOL_FLOAT );
+ aFloatBtn.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_RESTORE, *pResMgr ) ) );
+
+ aHideBtn.SetClickHdl( LINK( this, MenuBarWindow, HideHdl ) );
+ aHideBtn.SetSymbol( SYMBOL_HIDE );
+ aHideBtn.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_MINIMIZE, *pResMgr ) ) );
+ }
+
+ ImplInitStyleSettings();
+
+ AddEventListener( LINK( this, MenuBarWindow, ShowHideListener ) );
+}
+
+MenuBarWindow::~MenuBarWindow()
+{
+ aCloser.RemoveEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
+ RemoveEventListener( LINK( this, MenuBarWindow, ShowHideListener ) );
+}
+
+void MenuBarWindow::SetMenu( MenuBar* pMen )
+{
+ pMenu = pMen;
+ KillActivePopup();
+ nHighlightedItem = ITEMPOS_INVALID;
+ ImplInitMenuWindow( this, TRUE, TRUE );
+ if ( pMen )
+ {
+ aCloser.ShowItem( IID_DOCUMENTCLOSE, pMen->HasCloser() );
+ aCloser.Show( pMen->HasCloser() || !m_aAddButtons.empty() );
+ aFloatBtn.Show( pMen->HasFloatButton() );
+ aHideBtn.Show( pMen->HasHideButton() );
+ }
+ Invalidate();
+
+ // show and connect native menubar
+ if( pMenu && pMenu->ImplGetSalMenu() )
+ {
+ if( pMenu->ImplGetSalMenu()->VisibleMenuBar() )
+ ImplGetFrame()->SetMenu( pMenu->ImplGetSalMenu() );
+
+ pMenu->ImplGetSalMenu()->SetFrame( ImplGetFrame() );
+ }
+}
+
+void MenuBarWindow::ShowButtons( BOOL bClose, BOOL bFloat, BOOL bHide )
+{
+ aCloser.ShowItem( IID_DOCUMENTCLOSE, bClose );
+ aCloser.Show( bClose || ! m_aAddButtons.empty() );
+ aFloatBtn.Show( bFloat );
+ aHideBtn.Show( bHide );
+ Resize();
+}
+
+Size MenuBarWindow::MinCloseButtonSize()
+{
+ return aCloser.getMinSize();
+}
+
+IMPL_LINK( MenuBarWindow, CloserHdl, PushButton*, EMPTYARG )
+{
+ if( ! pMenu )
+ return 0;
+
+ if( aCloser.GetCurItemId() == IID_DOCUMENTCLOSE )
+ {
+ // #i106052# call close hdl asynchronously to ease handler implementation
+ // this avoids still being in the handler while the DecoToolBox already
+ // gets destroyed
+ Application::PostUserEvent( ((MenuBar*)pMenu)->GetCloserHdl(), pMenu );
+ }
+ else
+ {
+ std::map<USHORT,AddButtonEntry>::iterator it = m_aAddButtons.find( aCloser.GetCurItemId() );
+ if( it != m_aAddButtons.end() )
+ {
+ MenuBar::MenuBarButtonCallbackArg aArg;
+ aArg.nId = it->first;
+ aArg.bHighlight = (aCloser.GetHighlightItemId() == it->first);
+ aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
+ return it->second.m_aSelectLink.Call( &aArg );
+ }
+ }
+ return 0;
+}
+
+IMPL_LINK( MenuBarWindow, ToolboxEventHdl, VclWindowEvent*, pEvent )
+{
+ if( ! pMenu )
+ return 0;
+
+ MenuBar::MenuBarButtonCallbackArg aArg;
+ aArg.nId = 0xffff;
+ aArg.bHighlight = (pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT);
+ aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
+ if( pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT )
+ aArg.nId = aCloser.GetHighlightItemId();
+ else if( pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHTOFF )
+ {
+ USHORT nPos = static_cast< USHORT >(reinterpret_cast<sal_IntPtr>(pEvent->GetData()));
+ aArg.nId = aCloser.GetItemId( nPos );
+ }
+ std::map< USHORT, AddButtonEntry >::iterator it = m_aAddButtons.find( aArg.nId );
+ if( it != m_aAddButtons.end() )
+ {
+ it->second.m_aHighlightLink.Call( &aArg );
+ }
+ return 0;
+}
+
+IMPL_LINK( MenuBarWindow, ShowHideListener, VclWindowEvent*, pEvent )
+{
+ if( ! pMenu )
+ return 0;
+
+ if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
+ pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
+ else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
+ pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
+ return 0;
+}
+
+IMPL_LINK( MenuBarWindow, FloatHdl, PushButton*, EMPTYARG )
+{
+ return pMenu ? ((MenuBar*)pMenu)->GetFloatButtonClickHdl().Call( pMenu ) : 0;
+}
+
+IMPL_LINK( MenuBarWindow, HideHdl, PushButton*, EMPTYARG )
+{
+ return pMenu ? ((MenuBar*)pMenu)->GetHideButtonClickHdl().Call( pMenu ) : 0;
+}
+
+void MenuBarWindow::ImplCreatePopup( BOOL bPreSelectFirst )
+{
+ MenuItemData* pItemData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
+ if ( pItemData )
+ {
+ bIgnoreFirstMove = TRUE;
+ if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
+ {
+ KillActivePopup();
+ }
+ if ( pItemData->bEnabled && pItemData->pSubMenu && ( nHighlightedItem != ITEMPOS_INVALID ) && ( pItemData->pSubMenu != pActivePopup ) )
+ {
+ pActivePopup = (PopupMenu*)pItemData->pSubMenu;
+ long nX = 0;
+ MenuItemData* pData = 0;
+ for ( ULONG n = 0; n < nHighlightedItem; n++ )
+ {
+ pData = pMenu->GetItemList()->GetDataFromPos( n );
+ nX += pData->aSz.Width();
+ }
+ pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
+// Point MyPos = GetPosPixel();
+// Point aItemTopLeft( MyPos.X()+nX, MyPos.Y() );
+ Point aItemTopLeft( nX, 0 );
+ Point aItemBottomRight( aItemTopLeft );
+ aItemBottomRight.X() += pData->aSz.Width();
+
+ // Im Vollbild-Modus hat die MenuBar ggf. die Hoehe 0:
+ // Nicht immer einfach die Window-Hoehe nehmen, weil ItemHeight < WindowHeight.
+ if ( GetSizePixel().Height() )
+ {
+ // #107747# give menuitems the height of the menubar
+ aItemBottomRight.Y() += GetOutputSizePixel().Height()-1;
+ }
+
+ // ImplExecute ist doch nicht modal...
+ // #99071# do not grab the focus, otherwise it will be restored to the menubar
+ // when the frame is reactivated later
+ //GrabFocus();
+ pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_DOWN, pMenu, bPreSelectFirst );
+ if ( pActivePopup )
+ {
+ // Hat kein Window, wenn vorher abgebrochen oder keine Eintraege
+ if ( pActivePopup->ImplGetFloatingWindow() )
+ pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
+ else
+ pActivePopup = NULL;
+ }
+ }
+ }
+}
+
+
+void MenuBarWindow::KillActivePopup()
+{
+ if ( pActivePopup )
+ {
+ if( pActivePopup->pWindow != NULL )
+ if( ((FloatingWindow *) pActivePopup->pWindow)->IsInCleanUp() )
+ return; // kill it later
+
+ if ( pActivePopup->bInCallback )
+ pActivePopup->bCanceled = TRUE;
+
+ pActivePopup->bInCallback = TRUE;
+ pActivePopup->Deactivate();
+ pActivePopup->bInCallback = FALSE;
+ // Abfrage auf pActivePopup, falls im Deactivate abgeschossen...
+ if ( pActivePopup && pActivePopup->ImplGetWindow() )
+ {
+ pActivePopup->ImplGetFloatingWindow()->StopExecute();
+ pActivePopup->ImplGetFloatingWindow()->doShutdown();
+ pActivePopup->pWindow->doLazyDelete();
+ pActivePopup->pWindow = NULL;
+ }
+ pActivePopup = 0;
+ }
+}
+
+void MenuBarWindow::PopupClosed( Menu* pPopup )
+{
+ if ( pPopup == pActivePopup )
+ {
+ KillActivePopup();
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE, ImplGetFrameWindow()->ImplGetFrameData()->mbHasFocus, FALSE );
+ }
+}
+
+void MenuBarWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ mbAutoPopup = TRUE;
+ USHORT nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
+ if ( ( nEntry != ITEMPOS_INVALID ) && ( nEntry != nHighlightedItem ) )
+ {
+ ChangeHighlightItem( nEntry, FALSE );
+ }
+ else
+ {
+ KillActivePopup();
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ }
+}
+
+void MenuBarWindow::MouseButtonUp( const MouseEvent& )
+{
+}
+
+void MenuBarWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ // Im Move nur Highlighten, wenn schon eins gehighlightet.
+ if ( rMEvt.IsSynthetic() || rMEvt.IsLeaveWindow() || rMEvt.IsEnterWindow() || ( nHighlightedItem == ITEMPOS_INVALID ) )
+ return;
+
+ if( bIgnoreFirstMove )
+ {
+ bIgnoreFirstMove = FALSE;
+ return;
+ }
+
+ USHORT nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
+ if ( ( nEntry != ITEMPOS_INVALID )
+#ifdef OS2
+ && ( ImplHilite(rMEvt) )
+#endif
+ && ( nEntry != nHighlightedItem ) )
+ ChangeHighlightItem( nEntry, FALSE );
+}
+
+void MenuBarWindow::ChangeHighlightItem( USHORT n, BOOL bSelectEntry, BOOL bAllowRestoreFocus, BOOL bDefaultToDocument)
+{
+ if( ! pMenu )
+ return;
+
+ // #57934# ggf. das aktive Popup sofort schliessen, damit TH's Hintergrundsicherung funktioniert.
+ MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
+ if ( pActivePopup && pActivePopup->ImplGetWindow() && ( !pNextData || ( pActivePopup != pNextData->pSubMenu ) ) )
+ KillActivePopup(); // pActivePopup ggf. ohne pWin, wenn in Activate() Rescheduled wurde
+
+ // Activate am MenuBar immer nur einmal pro Vorgang...
+ BOOL bJustActivated = FALSE;
+ if ( ( nHighlightedItem == ITEMPOS_INVALID ) && ( n != ITEMPOS_INVALID ) )
+ {
+ ImplGetSVData()->maWinData.mbNoDeactivate = TRUE;
+ if( !bStayActive )
+ {
+ // #105406# avoid saving the focus when we already have the focus
+ BOOL bNoSaveFocus = (this == ImplGetSVData()->maWinData.mpFocusWin );
+
+ if( nSaveFocusId )
+ {
+ if( !ImplGetSVData()->maWinData.mbNoSaveFocus )
+ {
+ // we didn't clean up last time
+ Window::EndSaveFocus( nSaveFocusId, FALSE ); // clean up
+ nSaveFocusId = 0;
+ if( !bNoSaveFocus )
+ nSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
+ }
+ else {
+ ; // do nothing: we 're activated again from taskpanelist, focus was already saved
+ }
+ }
+ else
+ {
+ if( !bNoSaveFocus )
+ nSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
+ }
+ }
+ else
+ bStayActive = FALSE;
+ pMenu->bInCallback = TRUE; // hier schon setzen, falls Activate ueberladen
+ pMenu->Activate();
+ pMenu->bInCallback = FALSE;
+ bJustActivated = TRUE;
+ }
+ else if ( ( nHighlightedItem != ITEMPOS_INVALID ) && ( n == ITEMPOS_INVALID ) )
+ {
+ pMenu->bInCallback = TRUE;
+ pMenu->Deactivate();
+ pMenu->bInCallback = FALSE;
+ ImplGetSVData()->maWinData.mbNoDeactivate = FALSE;
+ if( !ImplGetSVData()->maWinData.mbNoSaveFocus )
+ {
+ ULONG nTempFocusId = nSaveFocusId;
+ nSaveFocusId = 0;
+ Window::EndSaveFocus( nTempFocusId, bAllowRestoreFocus );
+ // #105406# restore focus to document if we could not save focus before
+ if( bDefaultToDocument && !nTempFocusId && bAllowRestoreFocus )
+ GrabFocusToDocument();
+ }
+ }
+
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ {
+ HighlightItem( nHighlightedItem, FALSE );
+ pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
+ }
+
+ nHighlightedItem = (USHORT)n;
+ DBG_ASSERT( ( nHighlightedItem == ITEMPOS_INVALID ) || pMenu->ImplIsVisible( nHighlightedItem ), "ChangeHighlightItem: Not visible!" );
+ HighlightItem( nHighlightedItem, TRUE );
+ pMenu->ImplCallHighlight( nHighlightedItem );
+
+ if( mbAutoPopup )
+ ImplCreatePopup( bSelectEntry );
+
+ // #58935# #73659# Focus, wenn kein Popup drunter haengt...
+ if ( bJustActivated && !pActivePopup )
+ GrabFocus();
+}
+
+void MenuBarWindow::HighlightItem( USHORT nPos, BOOL bHighlight )
+{
+ if( ! pMenu )
+ return;
+
+ long nX = 0;
+ ULONG nCount = pMenu->pItemList->Count();
+ for ( ULONG n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ if ( n == nPos )
+ {
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ {
+ // #107747# give menuitems the height of the menubar
+ Rectangle aRect = Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( aRect );
+ if ( bHighlight )
+ {
+ if( IsNativeControlSupported( CTRL_MENUBAR, PART_MENU_ITEM ) &&
+ IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
+ {
+ // draw background (transparency)
+ MenubarValue aControlValue;
+ aControlValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
+
+ Point tmp(0,0);
+ Rectangle aBgRegion( tmp, GetOutputSizePixel() );
+ DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL,
+ aBgRegion,
+ CTRL_STATE_ENABLED,
+ aControlValue,
+ OUString() );
+ ImplAddNWFSeparator( this, aControlValue );
+
+ // draw selected item
+ DrawNativeControl( CTRL_MENUBAR, PART_MENU_ITEM,
+ aRect,
+ CTRL_STATE_ENABLED | CTRL_STATE_SELECTED,
+ aControlValue,
+ OUString() );
+ }
+ else
+ {
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
+ SetLineColor();
+ DrawRect( aRect );
+ }
+ }
+ else
+ {
+ if( IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) )
+ {
+ MenubarValue aMenubarValue;
+ aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
+
+ // use full window size to get proper gradient
+ // but clip accordingly
+ Point aPt;
+ Rectangle aCtrlRect( aPt, GetOutputSizePixel() );
+
+ DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED, aMenubarValue, rtl::OUString() );
+ ImplAddNWFSeparator( this, aMenubarValue );
+ }
+ else
+ Erase( aRect );
+ }
+ Pop();
+ pMenu->ImplPaint( this, 0, 0, pData, bHighlight );
+ }
+ return;
+ }
+
+ nX += pData->aSz.Width();
+ }
+}
+
+Rectangle MenuBarWindow::ImplGetItemRect( USHORT nPos )
+{
+ Rectangle aRect;
+ if( pMenu )
+ {
+ long nX = 0;
+ ULONG nCount = pMenu->pItemList->Count();
+ for ( ULONG n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ if ( n == nPos )
+ {
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ // #107747# give menuitems the height of the menubar
+ aRect = Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
+ break;
+ }
+
+ nX += pData->aSz.Width();
+ }
+ }
+ return aRect;
+}
+
+void MenuBarWindow::KeyInput( const KeyEvent& rKEvent )
+{
+ if ( !ImplHandleKeyEvent( rKEvent ) )
+ Window::KeyInput( rKEvent );
+}
+
+BOOL MenuBarWindow::ImplHandleKeyEvent( const KeyEvent& rKEvent, BOOL bFromMenu )
+{
+ if( ! pMenu )
+ return FALSE;
+
+ if ( pMenu->bInCallback )
+ return TRUE; // schlucken
+
+ BOOL bDone = FALSE;
+ USHORT nCode = rKEvent.GetKeyCode().GetCode();
+
+ if( GetParent() )
+ {
+ if( GetParent()->GetWindow( WINDOW_CLIENT )->IsSystemWindow() )
+ {
+ SystemWindow *pSysWin = (SystemWindow*)GetParent()->GetWindow( WINDOW_CLIENT );
+ if( pSysWin->GetTaskPaneList() )
+ if( pSysWin->GetTaskPaneList()->HandleKeyEvent( rKEvent ) )
+ return TRUE;
+ }
+ }
+
+ if ( nCode == KEY_MENU && !rKEvent.GetKeyCode().IsShift() ) // only F10, not Shift-F10
+ {
+ mbAutoPopup = ImplGetSVData()->maNWFData.mbOpenMenuOnF10;
+ if ( nHighlightedItem == ITEMPOS_INVALID )
+ {
+ ChangeHighlightItem( 0, FALSE );
+ GrabFocus();
+ }
+ else
+ {
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ nSaveFocusId = 0;
+ }
+ bDone = TRUE;
+ }
+ else if ( bFromMenu )
+ {
+ if ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ||
+ ( nCode == KEY_HOME ) || ( nCode == KEY_END ) )
+ {
+ USHORT n = nHighlightedItem;
+ if ( n == ITEMPOS_INVALID )
+ {
+ if ( nCode == KEY_LEFT)
+ n = 0;
+ else
+ n = pMenu->GetItemCount()-1;
+ }
+
+ // handling gtk like (aka mbOpenMenuOnF10)
+ // do not highlight an item when opening a sub menu
+ // unless there already was a higlighted sub menu item
+ bool bWasHighlight = false;
+ if( pActivePopup )
+ {
+ MenuFloatingWindow* pSubWindow = dynamic_cast<MenuFloatingWindow*>(pActivePopup->ImplGetWindow());
+ if( pSubWindow )
+ bWasHighlight = (pSubWindow->GetHighlightedItem() != ITEMPOS_INVALID);
+ }
+
+ USHORT nLoop = n;
+
+ if( nCode == KEY_HOME )
+ { n = (USHORT)-1; nLoop = n+1; }
+ if( nCode == KEY_END )
+ { n = pMenu->GetItemCount(); nLoop = n-1; }
+
+ do
+ {
+ if ( nCode == KEY_LEFT || nCode == KEY_END )
+ {
+ if ( n )
+ n--;
+ else
+ n = pMenu->GetItemCount()-1;
+ }
+ if ( nCode == KEY_RIGHT || nCode == KEY_HOME )
+ {
+ n++;
+ if ( n >= pMenu->GetItemCount() )
+ n = 0;
+ }
+
+ MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
+ if ( ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) )
+ {
+ BOOL bDoSelect = TRUE;
+ if( ImplGetSVData()->maNWFData.mbOpenMenuOnF10 )
+ bDoSelect = bWasHighlight;
+ ChangeHighlightItem( n, bDoSelect );
+ break;
+ }
+ } while ( n != nLoop );
+ bDone = TRUE;
+ }
+ else if ( nCode == KEY_RETURN )
+ {
+ if( pActivePopup ) KillActivePopup();
+ else
+ if ( !mbAutoPopup )
+ {
+ ImplCreatePopup( TRUE );
+ mbAutoPopup = TRUE;
+ }
+ bDone = TRUE;
+ }
+ else if ( ( nCode == KEY_UP ) || ( nCode == KEY_DOWN ) )
+ {
+ if ( !mbAutoPopup )
+ {
+ ImplCreatePopup( TRUE );
+ mbAutoPopup = TRUE;
+ }
+ bDone = TRUE;
+ }
+ else if ( nCode == KEY_ESCAPE || ( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() ) )
+ {
+ if( pActivePopup )
+ {
+ // bring focus to menu bar without any open popup
+ mbAutoPopup = FALSE;
+ USHORT n = nHighlightedItem;
+ nHighlightedItem = ITEMPOS_INVALID;
+ bStayActive = TRUE;
+ ChangeHighlightItem( n, FALSE );
+ bStayActive = FALSE;
+ KillActivePopup();
+ GrabFocus();
+ }
+ else
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+
+ if( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() )
+ {
+ // put focus into document
+ GrabFocusToDocument();
+ }
+
+ bDone = TRUE;
+ }
+ }
+
+ if ( !bDone && ( bFromMenu || rKEvent.GetKeyCode().IsMod2() ) )
+ {
+ xub_Unicode nCharCode = rKEvent.GetCharCode();
+ if ( nCharCode )
+ {
+ USHORT nEntry, nDuplicates;
+ MenuItemData* pData = pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nEntry, nDuplicates, nHighlightedItem );
+ if ( pData && (nEntry != ITEMPOS_INVALID) )
+ {
+ mbAutoPopup = TRUE;
+ ChangeHighlightItem( nEntry, TRUE );
+ bDone = TRUE;
+ }
+ else
+ {
+ // Wegen Systemmenu und anderen System-HotKeys, nur
+ // eigenstaendige Character-Kombinationen auswerten
+ USHORT nKeyCode = rKEvent.GetKeyCode().GetCode();
+ if ( ((nKeyCode >= KEY_A) && (nKeyCode <= KEY_Z)) )
+ Sound::Beep();
+ }
+ }
+ }
+ return bDone;
+}
+
+void MenuBarWindow::Paint( const Rectangle& )
+{
+ if( ! pMenu )
+ return;
+
+ // no VCL paint if native menus
+ if( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() )
+ {
+ ImplGetFrame()->DrawMenuBar();
+ return;
+ }
+
+ if( IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) )
+ {
+ Point aPt;
+ Rectangle aCtrlRegion( aPt, GetOutputSizePixel() );
+
+ MenubarValue aMenubarValue;
+ aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
+
+ DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL, aCtrlRegion, CTRL_STATE_ENABLED, aMenubarValue, rtl::OUString() );
+ ImplAddNWFSeparator( this, aMenubarValue );
+ }
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
+ pMenu->ImplPaint( this, 0 );
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ HighlightItem( nHighlightedItem, TRUE );
+
+ // in high contrast mode draw a separating line on the lower edge
+ if( ! IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) &&
+ GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ Push( PUSH_LINECOLOR | PUSH_MAPMODE );
+ SetLineColor( Color( COL_WHITE ) );
+ SetMapMode( MapMode( MAP_PIXEL ) );
+ Size aSize = GetSizePixel();
+ DrawLine( Point( 0, aSize.Height()-1 ), Point( aSize.Width()-1, aSize.Height()-1 ) );
+ Pop();
+ }
+
+}
+
+void MenuBarWindow::Resize()
+{
+ Size aOutSz = GetOutputSizePixel();
+ long n = aOutSz.Height()-4;
+ long nX = aOutSz.Width()-3;
+ long nY = 2;
+
+ if ( aCloser.IsVisible() )
+ {
+ aCloser.Hide();
+ aCloser.SetImages( n );
+ Size aTbxSize( aCloser.CalcWindowSizePixel() );
+ nX -= aTbxSize.Width();
+ long nTbxY = (aOutSz.Height() - aTbxSize.Height())/2;
+ aCloser.SetPosSizePixel( nX, nTbxY, aTbxSize.Width(), aTbxSize.Height() );
+ nX -= 3;
+ aCloser.Show();
+ }
+ if ( aFloatBtn.IsVisible() )
+ {
+ nX -= n;
+ aFloatBtn.SetPosSizePixel( nX, nY, n, n );
+ }
+ if ( aHideBtn.IsVisible() )
+ {
+ nX -= n;
+ aHideBtn.SetPosSizePixel( nX, nY, n, n );
+ }
+
+ aFloatBtn.SetSymbol( SYMBOL_FLOAT );
+ aHideBtn.SetSymbol( SYMBOL_HIDE );
+ //aCloser.SetSymbol( SYMBOL_CLOSE ); //is a toolbox now
+
+ Invalidate();
+}
+
+USHORT MenuBarWindow::ImplFindEntry( const Point& rMousePos ) const
+{
+ if( pMenu )
+ {
+ long nX = 0;
+ USHORT nCount = (USHORT)pMenu->pItemList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ if ( pMenu->ImplIsVisible( n ) )
+ {
+ nX += pData->aSz.Width();
+ if ( nX > rMousePos.X() )
+ return (USHORT)n;
+ }
+ }
+ }
+ return ITEMPOS_INVALID;
+}
+
+void MenuBarWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT nId = nHighlightedItem;
+ if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
+ ChangeHighlightItem( ITEMPOS_INVALID, TRUE );
+
+ Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
+ if( !ImplHandleHelpEvent( this, pMenu, nId, rHEvt, aHighlightRect ) )
+ Window::RequestHelp( rHEvt );
+}
+
+void MenuBarWindow::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) ||
+ ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
+ {
+ ImplInitMenuWindow( this, FALSE, TRUE );
+ Invalidate();
+ }
+ else if( pMenu )
+ pMenu->ImplKillLayoutData();
+
+}
+
+void MenuBarWindow::ImplLayoutChanged()
+{
+ if( pMenu )
+ {
+ ImplInitMenuWindow( this, TRUE, TRUE );
+ // Falls sich der Font geaendert hat.
+ long nHeight = pMenu->ImplCalcSize( this ).Height();
+
+ // depending on the native implementation or the displayable flag
+ // the menubar windows is supressed (ie, height=0)
+ if( !((MenuBar*) pMenu)->IsDisplayable() ||
+ ( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() ) )
+ nHeight = 0;
+
+ SetPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
+ GetParent()->Resize();
+ Invalidate();
+ Resize();
+ if( pMenu )
+ pMenu->ImplKillLayoutData();
+ }
+}
+
+void MenuBarWindow::ImplInitStyleSettings()
+{
+ if( IsNativeControlSupported( CTRL_MENUBAR, PART_MENU_ITEM ) &&
+ IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
+ {
+ Color aHighlightTextColor = ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor;
+ if( aHighlightTextColor != Color( COL_TRANSPARENT ) )
+ {
+ AllSettings aSettings( GetSettings() );
+ StyleSettings aStyle( aSettings.GetStyleSettings() );
+ aStyle.SetMenuHighlightTextColor( aHighlightTextColor );
+ aSettings.SetStyleSettings( aStyle );
+ OutputDevice::SetSettings( aSettings );
+ }
+ }
+}
+
+void MenuBarWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplLayoutChanged();
+ ImplInitStyleSettings();
+ }
+}
+
+void MenuBarWindow::LoseFocus()
+{
+ if ( !HasChildPathFocus( TRUE ) )
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE, FALSE );
+}
+
+void MenuBarWindow::GetFocus()
+{
+ if ( nHighlightedItem == ITEMPOS_INVALID )
+ {
+ mbAutoPopup = FALSE; // do not open menu when activated by focus handling like taskpane cycling
+ ChangeHighlightItem( 0, FALSE );
+ }
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > MenuBarWindow::CreateAccessible()
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
+
+ if ( pMenu )
+ xAcc = pMenu->GetAccessible();
+
+ return xAcc;
+}
+
+USHORT MenuBarWindow::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, const String& i_rToolTip, USHORT i_nPos )
+{
+ // find first free button id
+ USHORT nId = IID_DOCUMENTCLOSE;
+ std::map< USHORT, AddButtonEntry >::const_iterator it;
+ if( i_nPos > m_aAddButtons.size() )
+ i_nPos = static_cast<USHORT>(m_aAddButtons.size());
+ do
+ {
+ nId++;
+ it = m_aAddButtons.find( nId );
+ } while( it != m_aAddButtons.end() && nId < 128 );
+ DBG_ASSERT( nId < 128, "too many addbuttons in menubar" );
+ AddButtonEntry& rNewEntry = m_aAddButtons[nId];
+ rNewEntry.m_nId = nId;
+ rNewEntry.m_aSelectLink = i_rLink;
+ aCloser.InsertItem( nId, i_rImage, 0, 0 );
+ aCloser.calcMinSize();
+ ShowButtons( aCloser.IsItemVisible( IID_DOCUMENTCLOSE ),
+ aFloatBtn.IsVisible(),
+ aHideBtn.IsVisible() );
+ ImplLayoutChanged();
+
+ if( pMenu->mpSalMenu )
+ pMenu->mpSalMenu->AddMenuBarButton( SalMenuButtonItem( nId, i_rImage, i_rToolTip ) );
+
+ return nId;
+}
+
+void MenuBarWindow::SetMenuBarButtonHighlightHdl( USHORT nId, const Link& rLink )
+{
+ std::map< USHORT, AddButtonEntry >::iterator it = m_aAddButtons.find( nId );
+ if( it != m_aAddButtons.end() )
+ it->second.m_aHighlightLink = rLink;
+}
+
+Rectangle MenuBarWindow::GetMenuBarButtonRectPixel( USHORT nId )
+{
+ Rectangle aRect;
+ if( m_aAddButtons.find( nId ) != m_aAddButtons.end() )
+ {
+ if( pMenu->mpSalMenu )
+ {
+ aRect = pMenu->mpSalMenu->GetMenuBarButtonRectPixel( nId, ImplGetWindowImpl()->mpFrame );
+ if( aRect == Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) )
+ {
+ // system menu button is somehwere but location cannot be determined
+ return Rectangle();
+ }
+ }
+
+ if( aRect.IsEmpty() )
+ {
+ aRect = aCloser.GetItemRect( nId );
+ Point aOffset = aCloser.OutputToScreenPixel( Point() );
+ aRect.Move( aOffset.X(), aOffset.Y() );
+ }
+ }
+ return aRect;
+}
+
+void MenuBarWindow::RemoveMenuBarButton( USHORT nId )
+{
+ USHORT nPos = aCloser.GetItemPos( nId );
+ aCloser.RemoveItem( nPos );
+ m_aAddButtons.erase( nId );
+ aCloser.calcMinSize();
+ ImplLayoutChanged();
+
+ if( pMenu->mpSalMenu )
+ pMenu->mpSalMenu->RemoveMenuBarButton( nId );
+}
+
+bool MenuBarWindow::HandleMenuButtonEvent( USHORT i_nButtonId )
+{
+ std::map< USHORT, AddButtonEntry >::iterator it = m_aAddButtons.find( i_nButtonId );
+ if( it != m_aAddButtons.end() )
+ {
+ MenuBar::MenuBarButtonCallbackArg aArg;
+ aArg.nId = it->first;
+ aArg.bHighlight = true;
+ aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
+ return it->second.m_aSelectLink.Call( &aArg );
+ }
+ return FALSE;
+}
+
+ImplMenuDelData::ImplMenuDelData( const Menu* pMenu )
+: mpNext( 0 )
+, mpMenu( 0 )
+{
+ if( pMenu )
+ const_cast< Menu* >( pMenu )->ImplAddDel( *this );
+}
+
+ImplMenuDelData::~ImplMenuDelData()
+{
+ if( mpMenu )
+ const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this );
+}
diff --git a/vcl/source/window/mnemonic.cxx b/vcl/source/window/mnemonic.cxx
new file mode 100644
index 000000000000..c2c6c18135f2
--- /dev/null
+++ b/vcl/source/window/mnemonic.cxx
@@ -0,0 +1,419 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <string.h>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/mnemonic.hxx>
+
+#include <vcl/unohelp.hxx>
+#include <com/sun/star/i18n/XCharacterClassification.hpp>
+
+using namespace ::com::sun::star;
+
+
+// =======================================================================
+
+MnemonicGenerator::MnemonicGenerator()
+{
+ memset( maMnemonics, 1, sizeof( maMnemonics ) );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT MnemonicGenerator::ImplGetMnemonicIndex( sal_Unicode c )
+{
+ static USHORT const aImplMnemonicRangeTab[MNEMONIC_RANGES*2] =
+ {
+ MNEMONIC_RANGE_1_START, MNEMONIC_RANGE_1_END,
+ MNEMONIC_RANGE_2_START, MNEMONIC_RANGE_2_END,
+ MNEMONIC_RANGE_3_START, MNEMONIC_RANGE_3_END,
+ MNEMONIC_RANGE_4_START, MNEMONIC_RANGE_4_END
+ };
+
+ USHORT nMnemonicIndex = 0;
+ for ( USHORT i = 0; i < MNEMONIC_RANGES; i++ )
+ {
+ if ( (c >= aImplMnemonicRangeTab[i*2]) &&
+ (c <= aImplMnemonicRangeTab[i*2+1]) )
+ return nMnemonicIndex+c-aImplMnemonicRangeTab[i*2];
+
+ nMnemonicIndex += aImplMnemonicRangeTab[i*2+1]-aImplMnemonicRangeTab[i*2];
+ }
+
+ return MNEMONIC_INDEX_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Unicode MnemonicGenerator::ImplFindMnemonic( const XubString& rKey )
+{
+ xub_StrLen nIndex = 0;
+ while ( (nIndex = rKey.Search( MNEMONIC_CHAR, nIndex )) != STRING_NOTFOUND )
+ {
+ sal_Unicode cMnemonic = rKey.GetChar( nIndex+1 );
+ if ( cMnemonic != MNEMONIC_CHAR )
+ return cMnemonic;
+ nIndex += 2;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void MnemonicGenerator::RegisterMnemonic( const XubString& rKey )
+{
+ const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetUILocale();
+ uno::Reference < i18n::XCharacterClassification > xCharClass = GetCharClass();
+
+ // Don't crash even when we don't have access to i18n service
+ if ( !xCharClass.is() )
+ return;
+
+ XubString aKey = xCharClass->toUpper( rKey, 0, rKey.Len(), rLocale );
+
+ // If we find a Mnemonic, set the flag. In other case count the
+ // characters, because we need this to set most as possible
+ // Mnemonics
+ sal_Unicode cMnemonic = ImplFindMnemonic( aKey );
+ if ( cMnemonic )
+ {
+ USHORT nMnemonicIndex = ImplGetMnemonicIndex( cMnemonic );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ maMnemonics[nMnemonicIndex] = 0;
+ }
+ else
+ {
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = aKey.Len();
+ while ( nIndex < nLen )
+ {
+ sal_Unicode c = aKey.GetChar( nIndex );
+
+ USHORT nMnemonicIndex = ImplGetMnemonicIndex( c );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ {
+ if ( maMnemonics[nMnemonicIndex] && (maMnemonics[nMnemonicIndex] < 0xFF) )
+ maMnemonics[nMnemonicIndex]++;
+ }
+
+ nIndex++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MnemonicGenerator::CreateMnemonic( XubString& rKey )
+{
+ if ( !rKey.Len() || ImplFindMnemonic( rKey ) )
+ return FALSE;
+
+ const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetUILocale();
+ uno::Reference < i18n::XCharacterClassification > xCharClass = GetCharClass();
+
+ // Don't crash even when we don't have access to i18n service
+ if ( !xCharClass.is() )
+ return FALSE;
+
+ XubString aKey = xCharClass->toUpper( rKey, 0, rKey.Len(), rLocale );
+
+ BOOL bChanged = FALSE;
+ xub_StrLen nLen = aKey.Len();
+
+ BOOL bCJK = FALSE;
+ switch( Application::GetSettings().GetUILanguage() )
+ {
+ case LANGUAGE_JAPANESE:
+ case LANGUAGE_CHINESE_TRADITIONAL:
+ case LANGUAGE_CHINESE_SIMPLIFIED:
+ case LANGUAGE_CHINESE_HONGKONG:
+ case LANGUAGE_CHINESE_SINGAPORE:
+ case LANGUAGE_CHINESE_MACAU:
+ case LANGUAGE_KOREAN:
+ case LANGUAGE_KOREAN_JOHAB:
+ bCJK = TRUE;
+ break;
+ default:
+ break;
+ }
+ // #107889# in CJK versions ALL strings (even those that contain latin characters)
+ // will get mnemonics in the form: xyz (M)
+ // thus steps 1) and 2) are skipped for CJK locales
+
+ // #110720#, avoid CJK-style mnemonics for latin-only strings that do not contain useful mnemonic chars
+ if( bCJK )
+ {
+ BOOL bLatinOnly = TRUE;
+ BOOL bMnemonicIndexFound = FALSE;
+ sal_Unicode c;
+ xub_StrLen nIndex;
+
+ for( nIndex=0; nIndex < nLen; nIndex++ )
+ {
+ c = aKey.GetChar( nIndex );
+ if ( ((c >= 0x3000) && (c <= 0xD7FF)) || // cjk
+ ((c >= 0xFF61) && (c <= 0xFFDC)) ) // halfwidth forms
+ {
+ bLatinOnly = FALSE;
+ break;
+ }
+ if( ImplGetMnemonicIndex( c ) != MNEMONIC_INDEX_NOTFOUND )
+ bMnemonicIndexFound = TRUE;
+ }
+ if( bLatinOnly && !bMnemonicIndexFound )
+ return FALSE;
+ }
+
+
+ int nCJK = 0;
+ USHORT nMnemonicIndex;
+ sal_Unicode c;
+ xub_StrLen nIndex = 0;
+ if( !bCJK )
+ {
+ // 1) first try the first character of a word
+ do
+ {
+ c = aKey.GetChar( nIndex );
+
+ if ( nCJK != 2 )
+ {
+ if ( ((c >= 0x3000) && (c <= 0xD7FF)) || // cjk
+ ((c >= 0xFF61) && (c <= 0xFFDC)) ) // halfwidth forms
+ nCJK = 1;
+ else if ( ((c >= 0x0030) && (c <= 0x0039)) || // digits
+ ((c >= 0x0041) && (c <= 0x005A)) || // latin capitals
+ ((c >= 0x0061) && (c <= 0x007A)) || // latin small
+ ((c >= 0x0370) && (c <= 0x037F)) || // greek numeral signs
+ ((c >= 0x0400) && (c <= 0x04FF)) ) // cyrillic
+ nCJK = 2;
+ }
+
+ nMnemonicIndex = ImplGetMnemonicIndex( c );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ {
+ if ( maMnemonics[nMnemonicIndex] )
+ {
+ maMnemonics[nMnemonicIndex] = 0;
+ rKey.Insert( MNEMONIC_CHAR, nIndex );
+ bChanged = TRUE;
+ break;
+ }
+ }
+
+ // Search for next word
+ do
+ {
+ nIndex++;
+ c = aKey.GetChar( nIndex );
+ if ( c == ' ' )
+ break;
+ }
+ while ( nIndex < nLen );
+ nIndex++;
+ }
+ while ( nIndex < nLen );
+
+ // 2) search for a unique/uncommon character
+ if ( !bChanged )
+ {
+ USHORT nBestCount = 0xFFFF;
+ USHORT nBestMnemonicIndex = 0;
+ xub_StrLen nBestIndex = 0;
+ nIndex = 0;
+ do
+ {
+ c = aKey.GetChar( nIndex );
+ nMnemonicIndex = ImplGetMnemonicIndex( c );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ {
+ if ( maMnemonics[nMnemonicIndex] )
+ {
+ if ( maMnemonics[nMnemonicIndex] < nBestCount )
+ {
+ nBestCount = maMnemonics[nMnemonicIndex];
+ nBestIndex = nIndex;
+ nBestMnemonicIndex = nMnemonicIndex;
+ if ( nBestCount == 2 )
+ break;
+ }
+ }
+ }
+
+ nIndex++;
+ }
+ while ( nIndex < nLen );
+
+ if ( nBestCount != 0xFFFF )
+ {
+ maMnemonics[nBestMnemonicIndex] = 0;
+ rKey.Insert( MNEMONIC_CHAR, nBestIndex );
+ bChanged = TRUE;
+ }
+ }
+ }
+ else
+ nCJK = 1;
+
+ // 3) Add English Mnemonic for CJK Text
+ if ( !bChanged && (nCJK == 1) && rKey.Len() )
+ {
+ // Append Ascii Mnemonic
+ for ( c = MNEMONIC_RANGE_2_START; c <= MNEMONIC_RANGE_2_END; c++ )
+ {
+ nMnemonicIndex = ImplGetMnemonicIndex( c );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ {
+ if ( maMnemonics[nMnemonicIndex] )
+ {
+ maMnemonics[nMnemonicIndex] = 0;
+ UniString aStr( '(' );
+ aStr += MNEMONIC_CHAR;
+ aStr += c;
+ aStr += ')';
+ nIndex = rKey.Len();
+ if( nIndex >= 2 )
+ {
+ static sal_Unicode cGreaterGreater[] = { 0xFF1E, 0xFF1E };
+ if ( rKey.EqualsAscii( ">>", nIndex-2, 2 ) ||
+ rKey.Equals( cGreaterGreater, nIndex-2, 2 ) )
+ nIndex -= 2;
+ }
+ if( nIndex >= 3 )
+ {
+ static sal_Unicode cDotDotDot[] = { 0xFF0E, 0xFF0E, 0xFF0E };
+ if ( rKey.EqualsAscii( "...", nIndex-3, 3 ) ||
+ rKey.Equals( cDotDotDot, nIndex-3, 3 ) )
+ nIndex -= 3;
+ }
+ if( nIndex >= 1)
+ {
+ sal_Unicode cLastChar = rKey.GetChar( nIndex-1 );
+ if ( (cLastChar == ':') || (cLastChar == 0xFF1A) ||
+ (cLastChar == '.') || (cLastChar == 0xFF0E) ||
+ (cLastChar == '?') || (cLastChar == 0xFF1F) ||
+ (cLastChar == ' ') )
+ nIndex--;
+ }
+ rKey.Insert( aStr, nIndex );
+ bChanged = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+// #i87415# Duplicates mnemonics are bad for consistent keyboard accessibility
+// It's probably better to not have mnemonics for some widgets, than to have ambiguous ones.
+// if( ! bChanged )
+// {
+// /*
+// * #97809# if all else fails use the first character of a word
+// * anyway and live with duplicate mnemonics
+// */
+// nIndex = 0;
+// do
+// {
+// c = aKey.GetChar( nIndex );
+//
+// nMnemonicIndex = ImplGetMnemonicIndex( c );
+// if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+// {
+// maMnemonics[nMnemonicIndex] = 0;
+// rKey.Insert( MNEMONIC_CHAR, nIndex );
+// bChanged = TRUE;
+// break;
+// }
+//
+// // Search for next word
+// do
+// {
+// nIndex++;
+// c = aKey.GetChar( nIndex );
+// if ( c == ' ' )
+// break;
+// }
+// while ( nIndex < nLen );
+// nIndex++;
+// }
+// while ( nIndex < nLen );
+// }
+
+ return bChanged;
+}
+
+// -----------------------------------------------------------------------
+
+uno::Reference< i18n::XCharacterClassification > MnemonicGenerator::GetCharClass()
+{
+ if ( !mxCharClass.is() )
+ mxCharClass = vcl::unohelper::CreateCharacterClassification();
+ return mxCharClass;
+}
+
+// -----------------------------------------------------------------------
+
+String MnemonicGenerator::EraseAllMnemonicChars( const String& rStr )
+{
+ String aStr = rStr;
+ xub_StrLen nLen = aStr.Len();
+ xub_StrLen i = 0;
+
+ while ( i < nLen )
+ {
+ if ( aStr.GetChar( i ) == '~' )
+ {
+ // check for CJK-style mnemonic
+ if( i > 0 && (i+2) < nLen )
+ {
+ sal_Unicode c = aStr.GetChar(i+1);
+ if( aStr.GetChar( i-1 ) == '(' &&
+ aStr.GetChar( i+2 ) == ')' &&
+ c >= MNEMONIC_RANGE_2_START && c <= MNEMONIC_RANGE_2_END )
+ {
+ aStr.Erase( i-1, 4 );
+ nLen -= 4;
+ i--;
+ continue;
+ }
+ }
+
+ // remove standard mnemonics
+ aStr.Erase( i, 1 );
+ nLen--;
+ }
+ else
+ i++;
+ }
+
+ return aStr;
+}
diff --git a/vcl/source/window/mnemonicengine.cxx b/vcl/source/window/mnemonicengine.cxx
new file mode 100644
index 000000000000..241aea1cf336
--- /dev/null
+++ b/vcl/source/window/mnemonicengine.cxx
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <vcl/mnemonicengine.hxx>
+
+#include <vcl/i18nhelp.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/event.hxx>
+
+//........................................................................
+namespace vcl
+{
+//........................................................................
+
+ //====================================================================
+ //= MnemonicEngine_Data
+ //====================================================================
+ struct MnemonicEngine_Data
+ {
+ IMnemonicEntryList& rEntryList;
+
+ MnemonicEngine_Data( IMnemonicEntryList& _rEntryList )
+ :rEntryList( _rEntryList )
+ {
+ }
+ };
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ const void* lcl_getEntryForMnemonic( IMnemonicEntryList& _rEntryList, sal_Unicode _cMnemonic, bool& _rbAmbiguous )
+ {
+ _rbAmbiguous = false;
+
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+
+ String sEntryText;
+ const void* pSearchEntry = _rEntryList.FirstSearchEntry( sEntryText );
+
+ const void* pFirstFoundEntry = NULL;
+ bool bCheckingAmbiguity = false;
+ const void* pStartedWith = pSearchEntry;
+ while ( pSearchEntry )
+ {
+ if ( rI18nHelper.MatchMnemonic( sEntryText, _cMnemonic ) )
+ {
+ if ( bCheckingAmbiguity )
+ {
+ // that's the second (at least) entry with this mnemonic
+ _rbAmbiguous = true;
+ return pFirstFoundEntry;
+ }
+
+ pFirstFoundEntry = pSearchEntry;
+ bCheckingAmbiguity = true;
+ }
+
+ pSearchEntry = _rEntryList.NextSearchEntry( pSearchEntry, sEntryText );
+ if ( pSearchEntry == pStartedWith )
+ break;
+ }
+
+ return pFirstFoundEntry;
+ }
+ }
+
+ //====================================================================
+ //= MnemonicEngine
+ //====================================================================
+ //--------------------------------------------------------------------
+ MnemonicEngine::MnemonicEngine( IMnemonicEntryList& _rEntryList )
+ :m_pData( new MnemonicEngine_Data( _rEntryList ) )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ bool MnemonicEngine::HandleKeyEvent( const KeyEvent& _rKEvt )
+ {
+ BOOL bAccelKey = _rKEvt.GetKeyCode().IsMod2();
+ if ( !bAccelKey )
+ return false;
+
+ sal_Unicode cChar = _rKEvt.GetCharCode();
+ bool bAmbiguous = false;
+ const void* pEntry = lcl_getEntryForMnemonic( m_pData->rEntryList, cChar, bAmbiguous );
+ if ( !pEntry )
+ return false;
+
+ m_pData->rEntryList.SelectSearchEntry( pEntry );
+ if ( !bAmbiguous )
+ m_pData->rEntryList.ExecuteSearchEntry( pEntry );
+
+ // handled
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ MnemonicEngine::~MnemonicEngine()
+ {
+ }
+
+//........................................................................
+} // namespace vcl
+//........................................................................
diff --git a/vcl/source/window/mouseevent.cxx b/vcl/source/window/mouseevent.cxx
new file mode 100644
index 000000000000..4bfe08b3f3d8
--- /dev/null
+++ b/vcl/source/window/mouseevent.cxx
@@ -0,0 +1,92 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <com/sun/star/awt/MouseEvent.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <tools/debug.hxx>
+#include <vcl/event.hxx>
+
+/** inits this vcl KeyEvent with all settings from the given awt event **/
+MouseEvent::MouseEvent( const ::com::sun::star::awt::MouseEvent& rEvent )
+: maPos( rEvent.X, rEvent.Y )
+, mnMode( 0 )
+, mnClicks( static_cast< USHORT >( rEvent.ClickCount ) )
+, mnCode( 0 )
+{
+ if( rEvent.Modifiers )
+ {
+ if( (rEvent.Modifiers & ::com::sun::star::awt::KeyModifier::SHIFT) != 0 )
+ mnCode |= KEY_SHIFT;
+ if( (rEvent.Modifiers & ::com::sun::star::awt::KeyModifier::MOD1) != 0 )
+ mnCode |= KEY_MOD1;
+ if( (rEvent.Modifiers & ::com::sun::star::awt::KeyModifier::MOD2) != 0 )
+ mnCode |= KEY_MOD2;
+ if( (rEvent.Modifiers & ::com::sun::star::awt::KeyModifier::MOD3) != 0 )
+ mnCode |= KEY_MOD3;
+ }
+
+ if( rEvent.Buttons )
+ {
+ if( (rEvent.Buttons & ::com::sun::star::awt::MouseButton::LEFT) != 0 )
+ mnCode |= MOUSE_LEFT;
+ if( (rEvent.Buttons & ::com::sun::star::awt::MouseButton::RIGHT) != 0 )
+ mnCode |= MOUSE_RIGHT;
+ if( (rEvent.Buttons & ::com::sun::star::awt::MouseButton::MIDDLE) != 0 )
+ mnCode |= MOUSE_MIDDLE;
+ }
+}
+
+/** fills out the given awt KeyEvent with all settings from this vcl event **/
+void MouseEvent::InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent ) const
+{
+ rEvent.Modifiers = 0;
+ if ( IsShift() )
+ rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
+ if ( IsMod1() )
+ rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
+ if ( IsMod2() )
+ rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
+ if ( IsMod3() )
+ rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
+
+ rEvent.Buttons = 0;
+ if ( IsLeft() )
+ rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
+ if ( IsRight() )
+ rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
+ if ( IsMiddle() )
+ rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
+
+ rEvent.X = GetPosPixel().X();
+ rEvent.Y = GetPosPixel().Y();
+ rEvent.ClickCount = GetClicks();
+ rEvent.PopupTrigger = sal_False;
+}
diff --git a/vcl/source/window/msgbox.cxx b/vcl/source/window/msgbox.cxx
new file mode 100644
index 000000000000..7f7a65cd7fb9
--- /dev/null
+++ b/vcl/source/window/msgbox.cxx
@@ -0,0 +1,694 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVIDS_HRC
+#include <vcl/svids.hrc>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/fixed.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/button.hxx>
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/mnemonic.hxx>
+#include <vcl/window.h>
+
+
+
+// =======================================================================
+
+static void ImplInitMsgBoxImageList()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maWinData.mpMsgBoxImgList )
+ {
+ ResMgr* pResMgr = ImplGetResMgr();
+ pSVData->maWinData.mpMsgBoxImgList = new ImageList(4);
+ pSVData->maWinData.mpMsgBoxHCImgList = new ImageList(4);
+ if( pResMgr )
+ {
+ Color aNonAlphaMask( 0xC0, 0xC0, 0xC0 );
+ pSVData->maWinData.mpMsgBoxImgList->InsertFromHorizontalBitmap
+ ( ResId( SV_RESID_BITMAP_MSGBOX, *pResMgr ), 4, &aNonAlphaMask );
+ pSVData->maWinData.mpMsgBoxHCImgList->InsertFromHorizontalBitmap
+ ( ResId( SV_RESID_BITMAP_MSGBOX_HC, *pResMgr ), 4, &aNonAlphaMask );
+ }
+ }
+}
+
+// =======================================================================
+
+void MessBox::ImplInitMessBoxData()
+{
+ mpFixedText = NULL;
+ mpFixedImage = NULL;
+ mnSoundType = 0;
+ mbHelpBtn = FALSE;
+ mbSound = TRUE;
+ mpCheckBox = NULL;
+ mbCheck = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::ImplInitButtons()
+{
+ WinBits nStyle = GetStyle();
+ USHORT nOKFlags = BUTTONDIALOG_OKBUTTON;
+ USHORT nCancelFlags = BUTTONDIALOG_CANCELBUTTON;
+ USHORT nRetryFlags = 0;
+ USHORT nYesFlags = 0;
+ USHORT nNoFlags = 0;
+
+ if ( nStyle & WB_OK_CANCEL )
+ {
+ if ( nStyle & WB_DEF_CANCEL )
+ nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else // WB_DEF_OK
+ nOKFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_OK, BUTTONID_OK, nOKFlags );
+ AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
+ }
+ else if ( nStyle & WB_YES_NO )
+ {
+ if ( nStyle & WB_DEF_YES )
+ nYesFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else // WB_DEF_NO
+ nNoFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ nNoFlags |= BUTTONDIALOG_CANCELBUTTON;
+
+ AddButton( BUTTON_YES, BUTTONID_YES, nYesFlags );
+ AddButton( BUTTON_NO, BUTTONID_NO, nNoFlags );
+ }
+ else if ( nStyle & WB_YES_NO_CANCEL )
+ {
+ if ( nStyle & WB_DEF_YES )
+ nYesFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else if ( nStyle & WB_DEF_NO )
+ nNoFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else
+ nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_YES, BUTTONID_YES, nYesFlags );
+ AddButton( BUTTON_NO, BUTTONID_NO, nNoFlags );
+ AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
+ }
+ else if ( nStyle & WB_RETRY_CANCEL )
+ {
+ if ( nStyle & WB_DEF_CANCEL )
+ nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else // WB_DEF_RETRY
+ nRetryFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_RETRY, BUTTONID_RETRY, nRetryFlags );
+ AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
+ }
+ else if ( nStyle & WB_ABORT_RETRY_IGNORE )
+ {
+ USHORT nAbortFlags = 0;
+ USHORT nIgnoreFlags = 0;
+
+ if ( nStyle & WB_DEF_CANCEL )
+ nAbortFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else if ( nStyle & WB_DEF_RETRY )
+ nRetryFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else if ( nStyle & WB_DEF_IGNORE )
+ nIgnoreFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_ABORT, BUTTONID_CANCEL, nAbortFlags );
+ AddButton( BUTTON_RETRY, BUTTONID_RETRY, nRetryFlags );
+ AddButton( BUTTON_IGNORE, BUTTONID_IGNORE, nIgnoreFlags );
+ }
+ else if ( nStyle & WB_OK )
+ {
+ nOKFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_OK, BUTTONID_OK, nOKFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MessBox::MessBox( WindowType ) :
+ ButtonDialog( WINDOW_MESSBOX )
+{
+ ImplInitMessBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+MessBox::MessBox( Window* pParent, WinBits nStyle,
+ const XubString& rTitle, const XubString& rMessage ) :
+ ButtonDialog( WINDOW_MESSBOX ),
+ maMessText( rMessage )
+{
+ ImplInitMessBoxData();
+ ImplInit( pParent, nStyle | WB_MOVEABLE | WB_HORZ | WB_CENTER );
+ ImplInitButtons();
+
+ if ( rTitle.Len() )
+ SetText( rTitle );
+}
+
+// -----------------------------------------------------------------------
+
+MessBox::MessBox( Window* pParent, const ResId& rResId ) :
+ ButtonDialog( WINDOW_MESSBOX )
+{
+ ImplInitMessBoxData();
+
+ GetRes( rResId.SetRT( RSC_MESSBOX ) );
+ USHORT nHiButtons = ReadShortRes();
+ USHORT nLoButtons = ReadShortRes();
+ USHORT nHiDefButton = ReadShortRes();
+ USHORT nLoDefButton = ReadShortRes();
+ USHORT nHiHelpId = ReadShortRes();
+ USHORT nLoHelpId = ReadShortRes();
+ /* USHORT bSysModal = */ ReadShortRes();
+ SetHelpId( ((ULONG)nHiHelpId << 16) + nLoHelpId );
+ WinBits nBits = (((ULONG)nHiButtons << 16) + nLoButtons) |
+ (((ULONG)nHiDefButton << 16) + nLoDefButton);
+ ImplInit( pParent, nBits | WB_MOVEABLE | WB_HORZ | WB_CENTER );
+
+ ImplLoadRes( rResId );
+ ImplInitButtons();
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::ImplLoadRes( const ResId& )
+{
+ SetText( ReadStringRes() );
+ SetMessText( ReadStringRes() );
+ SetHelpText( ReadStringRes() );
+}
+
+// -----------------------------------------------------------------------
+
+MessBox::~MessBox()
+{
+ if ( mpFixedText )
+ delete mpFixedText;
+ if ( mpFixedImage )
+ delete mpFixedImage;
+ if ( mpCheckBox )
+ delete mpCheckBox;
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::ImplPosControls()
+{
+ if ( GetHelpId() )
+ {
+ if ( !mbHelpBtn )
+ {
+ AddButton( BUTTON_HELP, BUTTONID_HELP, BUTTONDIALOG_HELPBUTTON, 3 );
+ mbHelpBtn = TRUE;
+ }
+ }
+ else
+ {
+ if ( mbHelpBtn )
+ {
+ RemoveButton( BUTTONID_HELP );
+ mbHelpBtn = FALSE;
+ }
+ }
+
+ XubString aMessText( maMessText );
+ TextRectInfo aTextInfo;
+ Rectangle aRect( 0, 0, 30000, 30000 );
+ Rectangle aFormatRect;
+ Point aTextPos( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+IMPL_MSGBOX_OFFSET_EXTRA_Y );
+ Size aImageSize;
+ Size aPageSize;
+ Size aFixedSize;
+ long nTitleWidth;
+ long nButtonSize = ImplGetButtonSize();
+ long nMaxWidth = GetDesktopRectPixel().GetWidth()-8;
+ long nMaxLineWidth;
+ long nWidth;
+ WinBits nWinStyle = WB_LEFT | WB_WORDBREAK | WB_NOLABEL | WB_INFO;
+ USHORT nTextStyle = TEXT_DRAW_MULTILINE | TEXT_DRAW_TOP | TEXT_DRAW_LEFT;
+
+ if ( mpFixedText )
+ delete mpFixedText;
+ if ( mpFixedImage )
+ {
+ delete mpFixedImage;
+ mpFixedImage = NULL;
+ }
+ if ( mpCheckBox )
+ {
+ mbCheck = mpCheckBox->IsChecked();
+ delete mpCheckBox;
+ mpCheckBox = NULL;
+ }
+
+
+ // Message-Text um Tabs bereinigen
+ XubString aTabStr( RTL_CONSTASCII_USTRINGPARAM( " " ) );
+ USHORT nIndex = 0;
+ while ( nIndex != STRING_NOTFOUND )
+ nIndex = aMessText.SearchAndReplace( '\t', aTabStr, nIndex );
+
+ // Wenn Fenster zu schmall, machen wir Dialog auch breiter
+ if ( mpWindowImpl->mbFrame )
+ nMaxWidth = 630;
+ else if ( nMaxWidth < 120 )
+ nMaxWidth = 120;
+
+ nMaxWidth -= mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder+4;
+
+ // MessageBox sollte min. so breit sein, das auch Title sichtbar ist
+ // Extra-Width for Closer, because Closer is set after this call
+ nTitleWidth = CalcTitleWidth();
+ nTitleWidth += mpWindowImpl->mnTopBorder;
+
+ nMaxWidth -= (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
+
+ // Wenn wir ein Image haben, dann deren Groesse ermitteln und das
+ // entsprechende Control anlegen und positionieren
+ aImageSize = maImage.GetSizePixel();
+ if ( aImageSize.Width() )
+ {
+ aImageSize.Width() += 4;
+ aImageSize.Height() += 4;
+ aTextPos.X() += aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
+ mpFixedImage = new FixedImage( this );
+ mpFixedImage->SetPosSizePixel( Point( IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_X,
+ IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_Y ),
+ aImageSize );
+ mpFixedImage->SetImage( maImage );
+ // forward the HC image
+ if( !!maImageHC )
+ mpFixedImage->SetModeImage( maImageHC, BMP_COLOR_HIGHCONTRAST );
+ mpFixedImage->Show();
+ nMaxWidth -= aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
+ }
+ else
+ aTextPos.X() += IMPL_MSGBOX_OFFSET_EXTRA_X;
+
+ // Maximale Zeilenlaenge ohne Wordbreak ermitteln
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ nMaxLineWidth = aFormatRect.GetWidth();
+ nTextStyle |= TEXT_DRAW_WORDBREAK;
+
+ // Breite fuer Textformatierung ermitteln
+ if ( nMaxLineWidth > 450 )
+ nWidth = 450;
+ else if ( nMaxLineWidth > 300 )
+ nWidth = nMaxLineWidth+5;
+ else
+ nWidth = 300;
+ if ( nButtonSize > nWidth )
+ nWidth = nButtonSize-(aTextPos.X()-IMPL_DIALOG_OFFSET);
+ if ( nWidth > nMaxWidth )
+ nWidth = nMaxWidth;
+
+ aRect.Right() = nWidth;
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ if ( aTextInfo.GetMaxLineWidth() > nWidth )
+ {
+ nWidth = aTextInfo.GetMaxLineWidth()+8;
+ aRect.Right() = nWidth;
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ }
+
+ // Style fuer FixedText ermitteln
+ aPageSize.Width() = aImageSize.Width();
+ aFixedSize.Width() = aTextInfo.GetMaxLineWidth()+1;
+ aFixedSize.Height() = aFormatRect.GetHeight();
+ if ( aFixedSize.Height() < aImageSize.Height() )
+ {
+ nWinStyle |= WB_VCENTER;
+ aPageSize.Height() = aImageSize.Height();
+ aFixedSize.Height() = aImageSize.Height();
+ }
+ else
+ {
+ nWinStyle |= WB_TOP;
+ aPageSize.Height() = aFixedSize.Height();
+ }
+ if ( aImageSize.Width() )
+ aPageSize.Width() += IMPL_SEP_MSGBOX_IMAGE;
+ aPageSize.Width() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
+ aPageSize.Width() += aFixedSize.Width()+1;
+ aPageSize.Height() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
+
+ if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH )
+ aPageSize.Width() = IMPL_MINSIZE_MSGBOX_WIDTH;
+ if ( aPageSize.Width() < nTitleWidth )
+ aPageSize.Width() = nTitleWidth;
+
+ if ( maCheckBoxText.Len() )
+ {
+ Size aMinCheckboxSize ( aFixedSize );
+ if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH+80 )
+ {
+ aPageSize.Width() = IMPL_MINSIZE_MSGBOX_WIDTH+80;
+ aMinCheckboxSize.Width() += 80;
+ }
+
+ // #104492# auto mnemonics for CJK strings may increase the length, so measure the
+ // checkbox length including a temporary mnemonic, the correct auto mnemonic will be
+ // generated later in the dialog (see init_show)
+
+ String aMnemonicString( maCheckBoxText );
+ if( GetSettings().GetStyleSettings().GetAutoMnemonic() )
+ {
+ if( aMnemonicString == GetNonMnemonicString( maCheckBoxText ) )
+ {
+ // no mnemonic found -> create one
+ MnemonicGenerator aMnemonicGenerator;
+ aMnemonicGenerator.CreateMnemonic( aMnemonicString );
+ }
+ }
+
+ mpCheckBox = new CheckBox( this );
+ mpCheckBox->Check( mbCheck );
+ mpCheckBox->SetText( aMnemonicString );
+ mpCheckBox->SetStyle( mpCheckBox->GetStyle() | WB_WORDBREAK );
+ mpCheckBox->SetHelpId( GetHelpId() ); // DR: Check box and dialog have same HID
+
+ // align checkbox with message text
+ Size aSize = mpCheckBox->CalcMinimumSize( aMinCheckboxSize.Width() );
+
+ // now set the original non-mnemonic string
+ mpCheckBox->SetText( maCheckBoxText );
+
+ Point aPos( aTextPos );
+ aPos.Y() += aFixedSize.Height() + (IMPL_DIALOG_OFFSET)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
+
+ // increase messagebox
+ aPageSize.Height() += aSize.Height() + (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
+
+ mpCheckBox->SetPosSizePixel( aPos, aSize );
+ mpCheckBox->Show();
+ }
+
+ mpFixedText = new FixedText( this, nWinStyle );
+ mpFixedText->SetPosSizePixel( aTextPos, aFixedSize );
+ mpFixedText->SetText( aMessText );
+ mpFixedText->Show();
+ SetPageSizePixel( aPageSize );
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ ImplPosControls();
+ if ( mbSound && mnSoundType )
+ Sound::Beep( (SoundType)(mnSoundType-1), this );
+ }
+ ButtonDialog::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MessBox::GetCheckBoxState() const
+{
+ return mpCheckBox ? mpCheckBox->IsChecked() : mbCheck;
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::SetCheckBoxState( BOOL bCheck )
+{
+ if( mpCheckBox ) mpCheckBox->Check( bCheck );
+ mbCheck = bCheck;
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::SetDefaultCheckBoxText()
+{
+ ResMgr* pResMgr = ImplGetResMgr();
+ if( pResMgr )
+ maCheckBoxText = XubString( ResId( SV_STDTEXT_DONTHINTAGAIN, *pResMgr ) );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MessBox::SetModeImage( const Image& rImage, BmpColorMode eMode )
+{
+ if( eMode == BMP_COLOR_NORMAL )
+ SetImage( rImage );
+ else if( eMode == BMP_COLOR_HIGHCONTRAST )
+ maImageHC = rImage;
+ else
+ return FALSE;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+const Image& MessBox::GetModeImage( BmpColorMode eMode ) const
+{
+ if( eMode == BMP_COLOR_HIGHCONTRAST )
+ return maImageHC;
+ else
+ return maImage;
+}
+
+// -----------------------------------------------------------------------
+
+void InfoBox::ImplInitInfoBoxData()
+{
+ // Default Text is the display title from the application
+ if ( !GetText().Len() )
+ SetText( Application::GetDisplayName() );
+
+ SetImage( GetSettings().GetStyleSettings().GetHighContrastMode() ?
+ InfoBox::GetStandardImageHC() : InfoBox::GetStandardImage() );
+ mnSoundType = ((USHORT)SOUND_INFO)+1;
+}
+
+// -----------------------------------------------------------------------
+
+InfoBox::InfoBox( Window* pParent, const XubString& rMessage ) :
+ MessBox( pParent, WB_OK | WB_DEF_OK, ImplGetSVEmptyStr(), rMessage )
+{
+ ImplInitInfoBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+InfoBox::InfoBox( Window* pParent, const ResId & rResId ) :
+ MessBox( pParent, rResId.SetRT( RSC_INFOBOX ) )
+{
+ ImplInitInfoBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+Image InfoBox::GetStandardImage()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 4 );
+}
+
+// -----------------------------------------------------------------------
+
+Image InfoBox::GetStandardImageHC()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxHCImgList->GetImage( 4 );
+}
+
+// -----------------------------------------------------------------------
+
+void WarningBox::ImplInitWarningBoxData()
+{
+ // Default Text is the display title from the application
+ if ( !GetText().Len() )
+ SetText( Application::GetDisplayName() );
+
+ SetImage( WarningBox::GetStandardImage() );
+ mnSoundType = ((USHORT)SOUND_WARNING)+1;
+}
+
+// -----------------------------------------------------------------------
+
+WarningBox::WarningBox( Window* pParent, WinBits nStyle,
+ const XubString& rMessage ) :
+ MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
+{
+ ImplInitWarningBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+WarningBox::WarningBox( Window* pParent, const ResId& rResId ) :
+ MessBox( pParent, rResId.SetRT( RSC_WARNINGBOX ) )
+{
+ ImplInitWarningBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+void WarningBox::SetDefaultCheckBoxText()
+{
+ ResMgr* pResMgr = ImplGetResMgr();
+ if( pResMgr )
+ maCheckBoxText = XubString( ResId( SV_STDTEXT_DONTWARNAGAIN, *pResMgr ) );
+}
+
+// -----------------------------------------------------------------------
+
+Image WarningBox::GetStandardImage()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 3 );
+}
+
+// -----------------------------------------------------------------------
+
+void ErrorBox::ImplInitErrorBoxData()
+{
+ // Default Text is the display title from the application
+ if ( !GetText().Len() )
+ SetText( Application::GetDisplayName() );
+
+ SetImage( GetSettings().GetStyleSettings().GetHighContrastMode() ?
+ ErrorBox::GetStandardImageHC() : ErrorBox::GetStandardImage() );
+ mnSoundType = ((USHORT)SOUND_ERROR)+1;
+}
+
+// -----------------------------------------------------------------------
+
+ErrorBox::ErrorBox( Window* pParent, WinBits nStyle,
+ const XubString& rMessage ) :
+ MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
+{
+ ImplInitErrorBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+ErrorBox::ErrorBox( Window* pParent, const ResId& rResId ) :
+ MessBox( pParent, rResId.SetRT( RSC_ERRORBOX ) )
+{
+ ImplInitErrorBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+Image ErrorBox::GetStandardImage()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 1 );
+}
+
+// -----------------------------------------------------------------------
+
+Image ErrorBox::GetStandardImageHC()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxHCImgList->GetImage( 1 );
+}
+
+// -----------------------------------------------------------------------
+
+void QueryBox::ImplInitQueryBoxData()
+{
+ // Default Text is the display title from the application
+ if ( !GetText().Len() )
+ SetText( Application::GetDisplayName() );
+
+ SetImage( GetSettings().GetStyleSettings().GetHighContrastMode() ?
+ QueryBox::GetStandardImageHC() : QueryBox::GetStandardImage() );
+ mnSoundType = ((USHORT)SOUND_QUERY)+1;
+}
+
+// -----------------------------------------------------------------------
+
+QueryBox::QueryBox( Window* pParent, WinBits nStyle, const XubString& rMessage ) :
+ MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
+{
+ ImplInitQueryBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+QueryBox::QueryBox( Window* pParent, const ResId& rResId ) :
+ MessBox( pParent, rResId.SetRT( RSC_QUERYBOX ) )
+{
+ ImplInitQueryBoxData();
+}
+
+// -----------------------------------------------------------------------
+
+void QueryBox::SetDefaultCheckBoxText()
+{
+ ResMgr* pResMgr = ImplGetResMgr();
+ if( pResMgr )
+ maCheckBoxText = XubString( ResId( SV_STDTEXT_DONTASKAGAIN, *pResMgr ) );
+}
+
+// -----------------------------------------------------------------------
+
+Image QueryBox::GetStandardImage()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 2 );
+}
+
+// -----------------------------------------------------------------------
+
+Image QueryBox::GetStandardImageHC()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxHCImgList->GetImage( 2 );
+}
+
+// -----------------------------------------------------------------------
+
+Size MessBox::GetOptimalSize(WindowSizeType eType) const
+{
+ switch( eType ) {
+ case WINDOWSIZE_MINIMUM:
+ // FIXME: base me on the font size ?
+ return Size( 250, 100 );
+ default:
+ return Window::GetOptimalSize( eType );
+ }
+}
diff --git a/vcl/source/window/popupmenuwindow.cxx b/vcl/source/window/popupmenuwindow.cxx
new file mode 100644
index 000000000000..78ef0bcf1068
--- /dev/null
+++ b/vcl/source/window/popupmenuwindow.cxx
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include "vcl/popupmenuwindow.hxx"
+
+#include <limits>
+
+struct PopupMenuFloatingWindow::ImplData
+{
+ sal_uInt16 mnMenuStackLevel; // Store the stack level of a popup menu. 0 = top-level menu.
+
+ ImplData();
+ ~ImplData();
+};
+
+PopupMenuFloatingWindow::ImplData::ImplData() :
+ mnMenuStackLevel( ::std::numeric_limits<sal_uInt16>::max() )
+{
+}
+
+PopupMenuFloatingWindow::ImplData::~ImplData()
+{
+}
+
+// ============================================================================
+
+PopupMenuFloatingWindow::PopupMenuFloatingWindow( Window* pParent, WinBits nStyle ) :
+ FloatingWindow(pParent, nStyle),
+ mpImplData(new ImplData)
+{
+}
+
+PopupMenuFloatingWindow::~PopupMenuFloatingWindow()
+{
+ delete mpImplData;
+}
+
+sal_uInt16 PopupMenuFloatingWindow::GetMenuStackLevel() const
+{
+ return mpImplData->mnMenuStackLevel;
+}
+
+void PopupMenuFloatingWindow::SetMenuStackLevel( sal_uInt16 nLevel )
+{
+ mpImplData->mnMenuStackLevel = nLevel;
+}
+
+bool PopupMenuFloatingWindow::IsPopupMenu() const
+{
+ return mpImplData->mnMenuStackLevel != ::std::numeric_limits<sal_uInt16>::max();
+}
+
diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx
new file mode 100644
index 000000000000..d0fae33acf3b
--- /dev/null
+++ b/vcl/source/window/printdlg.cxx
@@ -0,0 +1,2603 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "precompiled_vcl.hxx"
+
+#include "vcl/print.hxx"
+#include "vcl/prndlg.hxx"
+#include "vcl/dialog.hxx"
+#include "vcl/button.hxx"
+#include "vcl/svdata.hxx"
+#include "vcl/svids.hrc"
+#include "vcl/wall.hxx"
+#include "vcl/jobset.h"
+#include "vcl/status.hxx"
+#include "vcl/decoview.hxx"
+#include "vcl/arrange.hxx"
+#include "vcl/configsettings.hxx"
+#include "vcl/help.hxx"
+#include "vcl/decoview.hxx"
+#include "vcl/svapp.hxx"
+#include "vcl/unohelp.hxx"
+
+#include "unotools/localedatawrapper.hxx"
+
+#include "rtl/ustrbuf.hxx"
+
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/container/XNameAccess.hpp"
+#include "com/sun/star/beans/PropertyValue.hpp"
+#include "com/sun/star/awt/Size.hpp"
+
+using namespace vcl;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::container;
+using namespace com::sun::star::beans;
+
+#define HELPID_PREFIX ".HelpId:vcl:PrintDialog"
+#define SMHID2( a, b ) SetSmartHelpId( SmartId( String( RTL_CONSTASCII_USTRINGPARAM( HELPID_PREFIX ":" a ":" b ) ), HID_PRINTDLG ) )
+#define SMHID1( a ) SetSmartHelpId( SmartId( String( RTL_CONSTASCII_USTRINGPARAM( HELPID_PREFIX ":" a ) ), HID_PRINTDLG ) )
+
+PrintDialog::PrintPreviewWindow::PrintPreviewWindow( Window* i_pParent, const ResId& i_rId )
+ : Window( i_pParent, i_rId )
+ , maOrigSize( 10, 10 )
+ , maPageVDev( *this )
+ , maToolTipString( String( VclResId( SV_PRINT_PRINTPREVIEW_TXT ) ) )
+{
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ if( useHCColorReplacement() )
+ maPageVDev.SetBackground( GetSettings().GetStyleSettings().GetWindowColor() );
+ else
+ maPageVDev.SetBackground( Color( COL_WHITE ) );
+}
+
+PrintDialog::PrintPreviewWindow::~PrintPreviewWindow()
+{
+}
+
+bool PrintDialog::PrintPreviewWindow::useHCColorReplacement() const
+{
+ bool bRet = false;
+ if( GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ try
+ {
+ // get service provider
+ Reference< XMultiServiceFactory > xSMgr( unohelper::GetMultiServiceFactory() );
+ // create configuration hierachical access name
+ if( xSMgr.is() )
+ {
+ try
+ {
+ Reference< XMultiServiceFactory > xConfigProvider(
+ Reference< XMultiServiceFactory >(
+ xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider" ))),
+ UNO_QUERY )
+ );
+ if( xConfigProvider.is() )
+ {
+ Sequence< Any > aArgs(1);
+ PropertyValue aVal;
+ aVal.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
+ aVal.Value <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Accessibility" ) );
+ aArgs.getArray()[0] <<= aVal;
+ Reference< XNameAccess > xConfigAccess(
+ Reference< XNameAccess >(
+ xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationAccess" )),
+ aArgs ),
+ UNO_QUERY )
+ );
+ if( xConfigAccess.is() )
+ {
+ try
+ {
+ sal_Bool bValue = sal_False;
+ Any aAny = xConfigAccess->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsForPagePreviews" ) ) );
+ if( aAny >>= bValue )
+ bRet = bool(bValue);
+ }
+ catch( NoSuchElementException& )
+ {
+ }
+ catch( WrappedTargetException& )
+ {
+ }
+ }
+ }
+ }
+ catch( Exception& )
+ {
+ }
+ }
+ }
+ catch( WrappedTargetException& )
+ {
+ }
+ }
+ return bRet;
+}
+
+void PrintDialog::PrintPreviewWindow::DataChanged( const DataChangedEvent& i_rDCEvt )
+{
+ // react on settings changed
+ if( i_rDCEvt.GetType() == DATACHANGED_SETTINGS )
+ {
+ if( useHCColorReplacement() )
+ maPageVDev.SetBackground( GetSettings().GetStyleSettings().GetWindowColor() );
+ else
+ maPageVDev.SetBackground( Color( COL_WHITE ) );
+ }
+ Window::DataChanged( i_rDCEvt );
+}
+
+void PrintDialog::PrintPreviewWindow::Resize()
+{
+ Size aNewSize( GetSizePixel() );
+ // leave small space for decoration
+ aNewSize.Width() -= 2;
+ aNewSize.Height() -= 2;
+ Size aScaledSize;
+ double fScale = 1.0;
+
+ // #i106435# catch corner case of Size(0,0)
+ Size aOrigSize( maOrigSize );
+ if( aOrigSize.Width() < 1 )
+ aOrigSize.Width() = aNewSize.Width();
+ if( aOrigSize.Height() < 1 )
+ aOrigSize.Height() = aNewSize.Height();
+ if( aOrigSize.Width() > aOrigSize.Height() )
+ {
+ aScaledSize = Size( aNewSize.Width(), aNewSize.Width() * aOrigSize.Height() / aOrigSize.Width() );
+ if( aScaledSize.Height() > aNewSize.Height() )
+ fScale = double(aNewSize.Height())/double(aScaledSize.Height());
+ }
+ else
+ {
+ aScaledSize = Size( aNewSize.Height() * aOrigSize.Width() / aOrigSize.Height(), aNewSize.Height() );
+ if( aScaledSize.Width() > aNewSize.Width() )
+ fScale = double(aNewSize.Width())/double(aScaledSize.Width());
+ }
+ aScaledSize.Width() = long(aScaledSize.Width()*fScale);
+ aScaledSize.Height() = long(aScaledSize.Height()*fScale);
+
+ maPreviewSize = aScaledSize;
+
+ // #i104784# if we render the page too small then rounding issues result in
+ // layout artifacts looking really bad. So scale the page unto a device that is not
+ // full page size but not too small either. This also results in much better visual
+ // quality of the preview, e.g. when its height approaches the number of text lines
+ // find a good scaling factor
+ Size aPreviewMMSize( maPageVDev.PixelToLogic( aScaledSize, MapMode( MAP_100TH_MM ) ) );
+ double fZoom = double(maOrigSize.Height())/double(aPreviewMMSize.Height());
+ while( fZoom > 10 )
+ {
+ aScaledSize.Width() *= 2;
+ aScaledSize.Height() *= 2;
+ fZoom /= 2.0;
+ }
+
+ maPageVDev.SetOutputSizePixel( aScaledSize, FALSE );
+}
+
+void PrintDialog::PrintPreviewWindow::Paint( const Rectangle& )
+{
+ Size aSize( GetSizePixel() );
+ if( maReplacementString.getLength() != 0 )
+ {
+ // replacement is active
+ Push();
+ Rectangle aTextRect( Point( 0, 0 ), aSize );
+ DecorationView aVw( this );
+ aVw.DrawFrame( aTextRect, FRAME_DRAW_GROUP );
+ aTextRect.Left() += 2;
+ aTextRect.Top() += 2;
+ aTextRect.Right() -= 2;
+ aTextRect.Bottom() -= 2;
+ Font aFont( GetSettings().GetStyleSettings().GetLabelFont() );
+ SetZoomedPointFont( aFont );
+ DrawText( aTextRect, maReplacementString,
+ TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE
+ );
+ Pop();
+ }
+ else
+ {
+ GDIMetaFile aMtf( maMtf );
+
+ Point aOffset( (aSize.Width() - maPreviewSize.Width()) / 2,
+ (aSize.Height() - maPreviewSize.Height()) / 2 );
+
+ Size aVDevSize( maPageVDev.GetOutputSizePixel() );
+ const Size aLogicSize( maPageVDev.PixelToLogic( aVDevSize, MapMode( MAP_100TH_MM ) ) );
+ Size aOrigSize( maOrigSize );
+ if( aOrigSize.Width() < 1 )
+ aOrigSize.Width() = aLogicSize.Width();
+ if( aOrigSize.Height() < 1 )
+ aOrigSize.Height() = aLogicSize.Height();
+ double fScale = double(aLogicSize.Width())/double(aOrigSize.Width());
+
+
+ maPageVDev.Erase();
+ maPageVDev.Push();
+ maPageVDev.SetMapMode( MAP_100TH_MM );
+ aMtf.WindStart();
+ aMtf.Scale( fScale, fScale );
+ aMtf.WindStart();
+ aMtf.Play( &maPageVDev, Point( 0, 0 ), aLogicSize );
+ maPageVDev.Pop();
+
+ SetMapMode( MAP_PIXEL );
+ maPageVDev.SetMapMode( MAP_PIXEL );
+ DrawOutDev( aOffset, maPreviewSize, Point( 0, 0 ), aVDevSize, maPageVDev );
+
+ DecorationView aVw( this );
+ Rectangle aFrame( aOffset + Point( -1, -1 ), Size( maPreviewSize.Width() + 2, maPreviewSize.Height() + 2 ) );
+ aVw.DrawFrame( aFrame, FRAME_DRAW_GROUP );
+ }
+}
+
+void PrintDialog::PrintPreviewWindow::Command( const CommandEvent& rEvt )
+{
+ if( rEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pWheelData = rEvt.GetWheelData();
+ PrintDialog* pDlg = dynamic_cast<PrintDialog*>(GetParent());
+ if( pDlg )
+ {
+ if( pWheelData->GetDelta() > 0 )
+ pDlg->previewForward();
+ else if( pWheelData->GetDelta() < 0 )
+ pDlg->previewBackward();
+ /*
+ else
+ huh ?
+ */
+ }
+ }
+}
+
+void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile& i_rNewPreview,
+ const Size& i_rOrigSize,
+ const rtl::OUString& i_rReplacement,
+ sal_Int32 i_nDPIX,
+ sal_Int32 i_nDPIY
+ )
+{
+ rtl::OUStringBuffer aBuf( 256 );
+ aBuf.append( maToolTipString );
+ #if OSL_DEBUG_LEVEL > 0
+ aBuf.appendAscii( "\n---\nPageSize: " );
+ aBuf.append( sal_Int32( i_rOrigSize.Width()/100) );
+ aBuf.appendAscii( "mm x " );
+ aBuf.append( sal_Int32( i_rOrigSize.Height()/100) );
+ aBuf.appendAscii( "mm" );
+ #endif
+ SetQuickHelpText( aBuf.makeStringAndClear() );
+ maMtf = i_rNewPreview;
+ if( useHCColorReplacement() )
+ {
+ maMtf.ReplaceColors( Color( COL_BLACK ), Color( COL_WHITE ), 30 );
+ }
+
+ maOrigSize = i_rOrigSize;
+ maReplacementString = i_rReplacement;
+ maPageVDev.SetReferenceDevice( i_nDPIX, i_nDPIY );
+ maPageVDev.EnableOutput( TRUE );
+ Resize();
+ Invalidate();
+}
+
+PrintDialog::ShowNupOrderWindow::ShowNupOrderWindow( Window* i_pParent )
+ : Window( i_pParent, WB_NOBORDER )
+ , mnOrderMode( 0 )
+ , mnRows( 1 )
+ , mnColumns( 1 )
+{
+ ImplInitSettings();
+}
+
+PrintDialog::ShowNupOrderWindow::~ShowNupOrderWindow()
+{
+}
+
+void PrintDialog::ShowNupOrderWindow::ImplInitSettings()
+{
+ SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
+}
+
+void PrintDialog::ShowNupOrderWindow::Paint( const Rectangle& i_rRect )
+{
+ Window::Paint( i_rRect );
+ SetMapMode( MAP_PIXEL );
+ SetTextColor( GetSettings().GetStyleSettings().GetFieldTextColor() );
+
+ int nPages = mnRows * mnColumns;
+ Font aFont( GetSettings().GetStyleSettings().GetFieldFont() );
+ aFont.SetSize( Size( 0, 24 ) );
+ SetFont( aFont );
+ Size aSampleTextSize( GetTextWidth( rtl::OUString::valueOf( sal_Int32(nPages+1) ) ), GetTextHeight() );
+
+ Size aOutSize( GetOutputSizePixel() );
+ Size aSubSize( aOutSize.Width() / mnColumns, aOutSize.Height() / mnRows );
+ // calculate font size: shrink the sample text so it fits
+ double fX = double(aSubSize.Width())/double(aSampleTextSize.Width());
+ double fY = double(aSubSize.Height())/double(aSampleTextSize.Height());
+ double fScale = (fX < fY) ? fX : fY;
+ long nFontHeight = long(24.0*fScale) - 3;
+ if( nFontHeight < 5 )
+ nFontHeight = 5;
+ aFont.SetSize( Size( 0, nFontHeight ) );
+ SetFont( aFont );
+ long nTextHeight = GetTextHeight();
+ for( int i = 0; i < nPages; i++ )
+ {
+ rtl::OUString aPageText( rtl::OUString::valueOf( sal_Int32(i+1) ) );
+ int nX = 0, nY = 0;
+ switch( mnOrderMode )
+ {
+ case SV_PRINT_PRT_NUP_ORDER_LRTD:
+ nX = (i % mnColumns); nY = (i / mnColumns);
+ break;
+ case SV_PRINT_PRT_NUP_ORDER_TDLR:
+ nX = (i / mnRows); nY = (i % mnRows);
+ break;
+ }
+ Size aTextSize( GetTextWidth( aPageText ), nTextHeight );
+ int nDeltaX = (aSubSize.Width() - aTextSize.Width()) / 2;
+ int nDeltaY = (aSubSize.Height() - aTextSize.Height()) / 2;
+ DrawText( Point( nX * aSubSize.Width() + nDeltaX,
+ nY * aSubSize.Height() + nDeltaY ),
+ aPageText );
+ }
+ DecorationView aVw( this );
+ aVw.DrawFrame( Rectangle( Point( 0, 0), aOutSize ), FRAME_DRAW_GROUP );
+}
+
+PrintDialog::NUpTabPage::NUpTabPage( Window* i_pParent, const ResId& rResId )
+ : TabPage( i_pParent, rResId )
+ , maNupLine( this, VclResId( SV_PRINT_PRT_NUP_LAYOUT_FL ) )
+ , maPagesBtn( this, VclResId( SV_PRINT_PRT_NUP_PAGES_BTN ) )
+ , maBrochureBtn( this, VclResId( SV_PRINT_PRT_NUP_BROCHURE_BTN ) )
+ , maPagesBoxTitleTxt( this, 0 )
+ , maNupPagesBox( this, VclResId( SV_PRINT_PRT_NUP_PAGES_BOX ) )
+ , maNupNumPagesTxt( this, VclResId( SV_PRINT_PRT_NUP_NUM_PAGES_TXT ) )
+ , maNupColEdt( this, VclResId( SV_PRINT_PRT_NUP_COLS_EDT ) )
+ , maNupTimesTxt( this, VclResId( SV_PRINT_PRT_NUP_TIMES_TXT ) )
+ , maNupRowsEdt( this, VclResId( SV_PRINT_PRT_NUP_ROWS_EDT ) )
+ , maPageMarginTxt1( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_PAGES_1_TXT ) )
+ , maPageMarginEdt( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_PAGES_EDT ) )
+ , maPageMarginTxt2( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_PAGES_2_TXT ) )
+ , maSheetMarginTxt1( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_SHEET_1_TXT ) )
+ , maSheetMarginEdt( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_SHEET_EDT ) )
+ , maSheetMarginTxt2( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_SHEET_2_TXT ) )
+ , maNupOrientationTxt( this, VclResId( SV_PRINT_PRT_NUP_ORIENTATION_TXT ) )
+ , maNupOrientationBox( this, VclResId( SV_PRINT_PRT_NUP_ORIENTATION_BOX ) )
+ , maNupOrderTxt( this, VclResId( SV_PRINT_PRT_NUP_ORDER_TXT ) )
+ , maNupOrderBox( this, VclResId( SV_PRINT_PRT_NUP_ORDER_BOX ) )
+ , maNupOrderWin( this )
+ , maBorderCB( this, VclResId( SV_PRINT_PRT_NUP_BORDER_CB ) )
+{
+ FreeResource();
+
+ maNupOrderWin.Show();
+ maPagesBtn.Check( TRUE );
+ maBrochureBtn.Show( FALSE );
+
+ // setup field units for metric fields
+ const LocaleDataWrapper& rLocWrap( maPageMarginEdt.GetLocaleDataWrapper() );
+ FieldUnit eUnit = FUNIT_MM;
+ USHORT nDigits = 0;
+ if( rLocWrap.getMeasurementSystemEnum() == MEASURE_US )
+ {
+ eUnit = FUNIT_INCH;
+ nDigits = 2;
+ }
+ // set units
+ maPageMarginEdt.SetUnit( eUnit );
+ maSheetMarginEdt.SetUnit( eUnit );
+
+ // set precision
+ maPageMarginEdt.SetDecimalDigits( nDigits );
+ maSheetMarginEdt.SetDecimalDigits( nDigits );
+
+ SMHID1( "NUpPage" );
+ maNupLine.SMHID2("NUpPage", "Layout");
+ maBrochureBtn.SMHID2("NUpPage", "Brochure" );
+ maPagesBtn.SMHID2( "NUpPage", "PagesPerSheet" );
+ maPagesBoxTitleTxt.SMHID2( "NUpPage", "PagesPerSheetLabel" );
+ maNupPagesBox.SMHID2( "NUpPage", "PagesPerSheetBox" );
+ maNupNumPagesTxt.SMHID2( "NUpPage", "Columns" );
+ maNupColEdt.SMHID2( "NUpPage", "ColumnsBox" );
+ maNupTimesTxt.SMHID2( "NUpPage", "Rows" );
+ maNupRowsEdt.SMHID2( "NUpPage", "RowsBox" );
+ maPageMarginTxt1.SMHID2( "NUpPage", "PageMargin" );
+ maPageMarginEdt.SMHID2( "NUpPage", "PageMarginBox" );
+ maPageMarginTxt2.SMHID2( "NUpPage", "PageMarginCont" );
+ maSheetMarginTxt1.SMHID2( "NUpPage", "SheetMargin" );
+ maSheetMarginEdt.SMHID2( "NUpPage", "SheetMarginBox" );
+ maSheetMarginTxt2.SMHID2( "NUpPage", "SheetMarginCont" );
+ maNupOrientationTxt.SMHID2( "NUpPage", "Orientation" );
+ maNupOrientationBox.SMHID2( "NUpPage", "OrientationBox" );
+ maNupOrderTxt.SMHID2( "NUpPage", "Order" );
+ maNupOrderBox.SMHID2( "NUpPage", "OrderBox" );
+ maBorderCB.SMHID2( "NUpPage", "BorderBox" );
+
+ setupLayout();
+}
+
+PrintDialog::NUpTabPage::~NUpTabPage()
+{
+}
+
+void PrintDialog::NUpTabPage::enableNupControls( bool bEnable )
+{
+ maNupPagesBox.Enable( TRUE );
+ maNupNumPagesTxt.Enable( bEnable );
+ maNupColEdt.Enable( bEnable );
+ maNupTimesTxt.Enable( bEnable );
+ maNupRowsEdt.Enable( bEnable );
+ maPageMarginTxt1.Enable( bEnable );
+ maPageMarginEdt.Enable( bEnable );
+ maPageMarginTxt2.Enable( bEnable );
+ maSheetMarginTxt1.Enable( bEnable );
+ maSheetMarginEdt.Enable( bEnable );
+ maSheetMarginTxt2.Enable( bEnable );
+ maNupOrientationTxt.Enable( bEnable );
+ maNupOrientationBox.Enable( bEnable );
+ maNupOrderTxt.Enable( bEnable );
+ maNupOrderBox.Enable( bEnable );
+ maNupOrderWin.Enable( bEnable );
+ maBorderCB.Enable( bEnable );
+}
+
+void PrintDialog::NUpTabPage::showAdvancedControls( bool i_bShow )
+{
+ maNupNumPagesTxt.Show( i_bShow );
+ maNupColEdt.Show( i_bShow );
+ maNupTimesTxt.Show( i_bShow );
+ maNupRowsEdt.Show( i_bShow );
+ maPageMarginTxt1.Show( i_bShow );
+ maPageMarginEdt.Show( i_bShow );
+ maPageMarginTxt2.Show( i_bShow );
+ maSheetMarginTxt1.Show( i_bShow );
+ maSheetMarginEdt.Show( i_bShow );
+ maSheetMarginTxt2.Show( i_bShow );
+ maNupOrientationTxt.Show( i_bShow );
+ maNupOrientationBox.Show( i_bShow );
+ maLayout.resize();
+}
+
+void PrintDialog::NUpTabPage::setupLayout()
+{
+ Size aBorder( LogicToPixel( Size( 6, 6 ), MapMode( MAP_APPFONT ) ) );
+ /* According to OOo style guide, the horizontal indentation of child
+ elements to their parent element should always be 6 map units. */
+ long nIndent = aBorder.Width();
+
+ maLayout.setParentWindow( this );
+ maLayout.setOuterBorder( aBorder.Width() );
+
+ maLayout.addWindow( &maNupLine );
+ boost::shared_ptr< vcl::RowOrColumn > xRow( new vcl::RowOrColumn( &maLayout, false ) );
+ maLayout.addChild( xRow );
+ boost::shared_ptr< vcl::Indenter > xIndent( new vcl::Indenter( xRow.get() ) );
+ xRow->addChild( xIndent );
+
+ boost::shared_ptr< vcl::RowOrColumn > xShowNupCol( new vcl::RowOrColumn( xRow.get() ) );
+ xRow->addChild( xShowNupCol, -1 );
+ xShowNupCol->setMinimumSize( xShowNupCol->addWindow( &maNupOrderWin ), Size( 70, 70 ) );
+ boost::shared_ptr< vcl::Spacer > xSpacer( new vcl::Spacer( xShowNupCol.get() ) );
+ xShowNupCol->addChild( xSpacer );
+
+ boost::shared_ptr< vcl::LabelColumn > xMainCol( new vcl::LabelColumn( xIndent.get() ) );
+ xIndent->setChild( xMainCol );
+
+ size_t nPagesIndex = xMainCol->addRow( &maPagesBtn, &maNupPagesBox );
+ mxPagesBtnLabel = boost::dynamic_pointer_cast<vcl::LabeledElement>( xMainCol->getChild( nPagesIndex ) );
+
+ xRow.reset( new vcl::RowOrColumn( xMainCol.get(), false ) );
+ xMainCol->addRow( &maNupNumPagesTxt, xRow, nIndent );
+ xRow->addWindow( &maNupColEdt );
+ xRow->addWindow( &maNupTimesTxt );
+ xRow->addWindow( &maNupRowsEdt );
+
+ boost::shared_ptr< vcl::LabeledElement > xLab( new vcl::LabeledElement( xMainCol.get(), 2 ) );
+ xLab->setLabel( &maPageMarginEdt );
+ xLab->setElement( &maPageMarginTxt2 );
+ xMainCol->addRow( &maPageMarginTxt1, xLab, nIndent );
+
+ xLab.reset( new vcl::LabeledElement( xMainCol.get(), 2 ) );
+ xLab->setLabel( &maSheetMarginEdt );
+ xLab->setElement( &maSheetMarginTxt2 );
+ xMainCol->addRow( &maSheetMarginTxt1, xLab, nIndent );
+
+ xMainCol->addRow( &maNupOrientationTxt, &maNupOrientationBox, nIndent );
+ xMainCol->addRow( &maNupOrderTxt, &maNupOrderBox, nIndent );
+ xMainCol->setBorders( xMainCol->addWindow( &maBorderCB ), nIndent, 0, 0, 0 );
+
+ xSpacer.reset( new vcl::Spacer( xMainCol.get(), 0, Size( 10, aBorder.Width() ) ) );
+ xMainCol->addChild( xSpacer );
+
+ xRow.reset( new vcl::RowOrColumn( xMainCol.get(), false ) );
+ xMainCol->addRow( &maBrochureBtn, xRow );
+ // remember brochure row for dependencies
+ mxBrochureDep = xRow;
+
+ // initially advanced controls are not shown, rows=columns=1
+ showAdvancedControls( false );
+}
+
+void PrintDialog::NUpTabPage::Resize()
+{
+ maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetOutputSizePixel() ) );
+}
+
+void PrintDialog::NUpTabPage::initFromMultiPageSetup( const vcl::PrinterController::MultiPageSetup& i_rMPS )
+{
+ maSheetMarginEdt.SetValue( maSheetMarginEdt.Normalize( i_rMPS.nLeftMargin ), FUNIT_100TH_MM );
+ maPageMarginEdt.SetValue( maPageMarginEdt.Normalize( i_rMPS.nHorizontalSpacing ), FUNIT_100TH_MM );
+ maBorderCB.Check( i_rMPS.bDrawBorder );
+ maNupRowsEdt.SetValue( i_rMPS.nRows );
+ maNupColEdt.SetValue( i_rMPS.nColumns );
+}
+
+void PrintDialog::NUpTabPage::readFromSettings()
+{
+}
+
+void PrintDialog::NUpTabPage::storeToSettings()
+{
+}
+
+PrintDialog::JobTabPage::JobTabPage( Window* i_pParent, const ResId& rResId )
+ : TabPage( i_pParent, rResId )
+ , maPrinterFL( this, VclResId( SV_PRINT_PRINTERS_FL ) )
+ , maPrinters( this, VclResId( SV_PRINT_PRINTERS ) )
+ , maDetailsBtn( this, VclResId( SV_PRINT_DETAILS_BTN ) )
+ , maStatusLabel( this, VclResId( SV_PRINT_STATUS_TXT ) )
+ , maStatusTxt( this, 0 )
+ , maLocationLabel( this, VclResId( SV_PRINT_LOCATION_TXT ) )
+ , maLocationTxt( this, 0 )
+ , maCommentLabel( this, VclResId( SV_PRINT_COMMENT_TXT ) )
+ , maCommentTxt( this, 0 )
+ , maSetupButton( this, VclResId( SV_PRINT_PRT_SETUP ) )
+ , maCopies( this, VclResId( SV_PRINT_COPIES ) )
+ , maCopySpacer( this, WB_VERT )
+ , maCopyCount( this, VclResId( SV_PRINT_COPYCOUNT ) )
+ , maCopyCountField( this, VclResId( SV_PRINT_COPYCOUNT_FIELD ) )
+ , maCollateBox( this, VclResId( SV_PRINT_COLLATE ) )
+ , maCollateImage( this, VclResId( SV_PRINT_COLLATE_IMAGE ) )
+ , maCollateImg( VclResId( SV_PRINT_COLLATE_IMG ) )
+ , maCollateHCImg( VclResId( SV_PRINT_COLLATE_HC_IMG ) )
+ , maNoCollateImg( VclResId( SV_PRINT_NOCOLLATE_IMG ) )
+ , maNoCollateHCImg( VclResId( SV_PRINT_NOCOLLATE_HC_IMG ) )
+ , mnCollateUIMode( 0 )
+ , maLayout( NULL, true )
+{
+ FreeResource();
+
+ SMHID1( "JobPage" );
+ maPrinterFL.SMHID2( "JobPage", "Printer" );
+ maPrinters.SMHID2( "JobPage", "PrinterList" );
+ maDetailsBtn.SMHID2( "JobPage", "DetailsBtn" );
+ maStatusLabel.SMHID2( "JobPage", "StatusLabel" );
+ maStatusTxt.SMHID2( "JobPage", "StatusText" );
+ maLocationLabel.SMHID2( "JobPage", "LocationLabel" );
+ maLocationTxt.SMHID2( "JobPage", "LocationText" );
+ maCommentLabel.SMHID2( "JobPage", "CommentLabel" );
+ maCommentTxt.SMHID2( "JobPage", "CommentText" );
+ maSetupButton.SMHID2( "JobPage", "Properties" );
+ maCopies.SMHID2( "JobPage", "CopiesLine" );
+ maCopySpacer.SMHID2( "JobPage", "CopySpacer" );
+ maCopyCount.SMHID2( "JobPage", "CopiesText" );
+ maCopyCountField.SMHID2( "JobPage", "Copies" );
+ maCollateBox.SMHID2( "JobPage", "Collate" );
+ maCollateImage.SMHID2( "JobPage", "CollateImage" );
+
+ maCopySpacer.Show();
+ maStatusTxt.Show();
+ maCommentTxt.Show();
+ maLocationTxt.Show();
+
+ setupLayout();
+}
+
+PrintDialog::JobTabPage::~JobTabPage()
+{
+}
+
+void PrintDialog::JobTabPage::setupLayout()
+{
+ // HACK: this is not a dropdown box, but the dropdown line count
+ // sets the results of GetOptimalSize in a normal ListBox
+ maPrinters.SetDropDownLineCount( 4 );
+
+ Size aBorder( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) );
+
+ maLayout.setParentWindow( this );
+ maLayout.setOuterBorder( aBorder.Width() );
+
+ // add printer fixed line
+ maLayout.addWindow( &maPrinterFL );
+ // add print LB
+ maLayout.addWindow( &maPrinters, 3 );
+
+ // create a row for details button/text and properties button
+ boost::shared_ptr< vcl::RowOrColumn > xDetRow( new vcl::RowOrColumn( &maLayout, false ) );
+ maLayout.addChild( xDetRow );
+ xDetRow->addWindow( &maDetailsBtn );
+ xDetRow->addChild( new vcl::Spacer( xDetRow.get(), 2 ) );
+ xDetRow->addWindow( &maSetupButton );
+
+ // create an indent for details
+ boost::shared_ptr< vcl::Indenter > xIndent( new vcl::Indenter( &maLayout ) );
+ maLayout.addChild( xIndent );
+ // remember details controls
+ mxDetails = xIndent;
+ // create a column for the details
+ boost::shared_ptr< vcl::LabelColumn > xLabelCol( new vcl::LabelColumn( xIndent.get(), aBorder.Height() ) );
+ xIndent->setChild( xLabelCol );
+ xLabelCol->addRow( &maStatusLabel, &maStatusTxt );
+ xLabelCol->addRow( &maLocationLabel, &maLocationTxt );
+ xLabelCol->addRow( &maCommentLabel, &maCommentTxt );
+
+ // add print range and copies columns
+ maLayout.addWindow( &maCopies );
+ boost::shared_ptr< vcl::RowOrColumn > xRangeRow( new vcl::RowOrColumn( &maLayout, false, aBorder.Width() ) );
+ maLayout.addChild( xRangeRow );
+
+ // create print range and add to range row
+ mxPrintRange.reset( new vcl::RowOrColumn( xRangeRow.get() ) );
+ xRangeRow->addChild( mxPrintRange );
+ xRangeRow->addWindow( &maCopySpacer );
+
+ boost::shared_ptr< vcl::RowOrColumn > xCopyCollateCol( new vcl::RowOrColumn( xRangeRow.get() ) );
+ xRangeRow->addChild( xCopyCollateCol );
+
+ // add copies row to copy/collate column
+ boost::shared_ptr< vcl::LabeledElement > xCopiesRow( new vcl::LabeledElement( xCopyCollateCol.get(), 2 ) );
+ xCopyCollateCol->addChild( xCopiesRow );
+ xCopiesRow->setLabel( &maCopyCount );
+ xCopiesRow->setElement( &maCopyCountField );
+ boost::shared_ptr< vcl::LabeledElement > xCollateRow( new vcl::LabeledElement( xCopyCollateCol.get(), 2 ) );
+ xCopyCollateCol->addChild( xCollateRow );
+ xCollateRow->setLabel( &maCollateBox );
+ xCollateRow->setElement( &maCollateImage );
+
+ // maDetailsBtn.SetStyle( maDetailsBtn.GetStyle() | (WB_SMALLSTYLE | WB_BEVELBUTTON) );
+ mxDetails->show( false, false );
+}
+
+void PrintDialog::JobTabPage::readFromSettings()
+{
+ SettingsConfigItem* pItem = SettingsConfigItem::get();
+ rtl::OUString aValue;
+
+ #if 0
+ // do not actually make copy count persistent
+ // the assumption is that this would lead to a lot of unwanted copies
+ aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ) );
+ sal_Int32 nVal = aValue.toInt32();
+ maCopyCountField.SetValue( sal_Int64(nVal > 1 ? nVal : 1) );
+ #endif
+
+ aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CollateBox" ) ) );
+ if( aValue.equalsIgnoreAsciiCaseAscii( "alwaysoff" ) )
+ {
+ mnCollateUIMode = 1;
+ maCollateBox.Check( FALSE );
+ maCollateBox.Enable( FALSE );
+ }
+ else
+ {
+ mnCollateUIMode = 0;
+ aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ) );
+ maCollateBox.Check( aValue.equalsIgnoreAsciiCaseAscii( "true" ) );
+ }
+ Resize();
+}
+
+void PrintDialog::JobTabPage::storeToSettings()
+{
+ SettingsConfigItem* pItem = SettingsConfigItem::get();
+ pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ),
+ maCopyCountField.GetText() );
+ pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
+ rtl::OUString::createFromAscii( maCollateBox.IsChecked() ? "true" : "false" ) );
+}
+
+void PrintDialog::JobTabPage::Resize()
+{
+ maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
+}
+
+PrintDialog::OutputOptPage::OutputOptPage( Window* i_pParent, const ResId& i_rResId )
+ : TabPage( i_pParent, i_rResId )
+ , maOptionsLine( this, VclResId( SV_PRINT_OPT_PRINT_FL ) )
+ , maToFileBox( this, VclResId( SV_PRINT_OPT_TOFILE ) )
+ , maCollateSingleJobsBox( this, VclResId( SV_PRINT_OPT_SINGLEJOBS ) )
+ , maReverseOrderBox( this, VclResId( SV_PRINT_OPT_REVERSE ) )
+{
+ FreeResource();
+ SMHID1( "OptPage" );
+ maOptionsLine.SMHID2( "OptPage", "Options" );
+ maToFileBox.SMHID2( "OptPage", "ToFile" );
+ maCollateSingleJobsBox.SMHID2( "OptPage", "SingleJobs" );
+ maReverseOrderBox.SMHID2( "OptPage", "Reverse" );
+
+ setupLayout();
+}
+
+PrintDialog::OutputOptPage::~OutputOptPage()
+{
+}
+
+void PrintDialog::OutputOptPage::setupLayout()
+{
+ Size aBorder( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) );
+
+ maLayout.setParentWindow( this );
+ maLayout.setOuterBorder( aBorder.Width() );
+
+ maLayout.addWindow( &maOptionsLine );
+ boost::shared_ptr<vcl::Indenter> xIndent( new vcl::Indenter( &maLayout, aBorder.Width() ) );
+ maLayout.addChild( xIndent );
+ boost::shared_ptr<vcl::RowOrColumn> xCol( new vcl::RowOrColumn( xIndent.get(), aBorder.Height() ) );
+ xIndent->setChild( xCol );
+ mxOptGroup = xCol;
+ xCol->addWindow( &maToFileBox );
+ xCol->addWindow( &maCollateSingleJobsBox );
+ xCol->addWindow( &maReverseOrderBox );
+}
+
+void PrintDialog::OutputOptPage::readFromSettings()
+{
+ #if 0
+ SettingsConfigItem* pItem = SettingsConfigItem::get();
+ rtl::OUString aValue;
+
+ aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ToFile" ) ) );
+ maToFileBox.Check( aValue.equalsIgnoreAsciiCaseAscii( "true" ) );
+ #endif
+}
+
+void PrintDialog::OutputOptPage::storeToSettings()
+{
+ SettingsConfigItem* pItem = SettingsConfigItem::get();
+ pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ToFile" ) ),
+ rtl::OUString::createFromAscii( maToFileBox.IsChecked() ? "true" : "false" ) );
+}
+
+void PrintDialog::OutputOptPage::Resize()
+{
+ maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
+}
+
+
+PrintDialog::PrintDialog( Window* i_pParent, const boost::shared_ptr<PrinterController>& i_rController )
+ : ModalDialog( i_pParent, VclResId( SV_DLG_PRINT ) )
+ , maOKButton( this, VclResId( SV_PRINT_OK ) )
+ , maCancelButton( this, VclResId( SV_PRINT_CANCEL ) )
+ , maHelpButton( this, VclResId( SV_PRINT_HELP ) )
+ , maPreviewWindow( this, VclResId( SV_PRINT_PAGE_PREVIEW ) )
+ , maPageEdit( this, VclResId( SV_PRINT_PAGE_EDIT ) )
+ , maNumPagesText( this, VclResId( SV_PRINT_PAGE_TXT ) )
+ , maBackwardBtn( this, VclResId( SV_PRINT_PAGE_BACKWARD ) )
+ , maForwardBtn( this, VclResId( SV_PRINT_PAGE_FORWARD ) )
+ , maTabCtrl( this, VclResId( SV_PRINT_TABCTRL ) )
+ , maNUpPage( &maTabCtrl, VclResId( SV_PRINT_TAB_NUP ) )
+ , maJobPage( &maTabCtrl, VclResId( SV_PRINT_TAB_JOB ) )
+ , maOptionsPage( &maTabCtrl, VclResId( SV_PRINT_TAB_OPT ) )
+ , maButtonLine( this, VclResId( SV_PRINT_BUTTONLINE ) )
+ , maPController( i_rController )
+ , maNoPageStr( String( VclResId( SV_PRINT_NOPAGES ) ) )
+ , mnCurPage( 0 )
+ , mnCachedPages( 0 )
+ , maPrintToFileText( String( VclResId( SV_PRINT_TOFILE_TXT ) ) )
+ , maDefPrtText( String( VclResId( SV_PRINT_DEFPRT_TXT ) ) )
+ , mbShowLayoutPage( sal_True )
+{
+ FreeResource();
+
+ // save printbutton text, gets exchanged occasionally with print to file
+ maPrintText = maOKButton.GetText();
+
+ // setup preview controls
+ maForwardBtn.SetStyle( maForwardBtn.GetStyle() | WB_BEVELBUTTON );
+ maBackwardBtn.SetStyle( maBackwardBtn.GetStyle() | WB_BEVELBUTTON );
+
+ // insert the job (general) tab page first
+ maTabCtrl.InsertPage( SV_PRINT_TAB_JOB, maJobPage.GetText() );
+ maTabCtrl.SetTabPage( SV_PRINT_TAB_JOB, &maJobPage );
+
+ // set symbols on forward and backward button
+ maBackwardBtn.SetSymbol( SYMBOL_PREV );
+ maForwardBtn.SetSymbol( SYMBOL_NEXT );
+ maBackwardBtn.ImplSetSmallSymbol( TRUE );
+ maForwardBtn.ImplSetSmallSymbol( TRUE );
+
+ maPageStr = maNumPagesText.GetText();
+
+ // init reverse print
+ maOptionsPage.maReverseOrderBox.Check( maPController->getReversePrint() );
+
+ // get the first page
+ preparePreview( true, true );
+
+ // fill printer listbox
+ const std::vector< rtl::OUString >& rQueues( Printer::GetPrinterQueues() );
+ for( std::vector< rtl::OUString >::const_iterator it = rQueues.begin();
+ it != rQueues.end(); ++it )
+ {
+ maJobPage.maPrinters.InsertEntry( *it );
+ }
+ // select current printer
+ if( maJobPage.maPrinters.GetEntryPos( maPController->getPrinter()->GetName() ) != LISTBOX_ENTRY_NOTFOUND )
+ {
+ maJobPage.maPrinters.SelectEntry( maPController->getPrinter()->GetName() );
+ }
+ else
+ {
+ // fall back to last printer
+ SettingsConfigItem* pItem = SettingsConfigItem::get();
+ String aValue( pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinter" ) ) ) );
+ if( maJobPage.maPrinters.GetEntryPos( aValue ) != LISTBOX_ENTRY_NOTFOUND )
+ {
+ maJobPage.maPrinters.SelectEntry( aValue );
+ maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( aValue ) ) );
+ }
+ else
+ {
+ // fall back to default printer
+ maJobPage.maPrinters.SelectEntry( Printer::GetDefaultPrinterName() );
+ maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( Printer::GetDefaultPrinterName() ) ) );
+ }
+ }
+ // update the text fields for the printer
+ updatePrinterText();
+
+ // set a select handler
+ maJobPage.maPrinters.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
+
+ // setup sizes for N-Up
+ Size aNupSize( maPController->getPrinter()->PixelToLogic(
+ maPController->getPrinter()->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ) );
+ if( maPController->getPrinter()->GetOrientation() == ORIENTATION_LANDSCAPE )
+ {
+ maNupLandscapeSize = aNupSize;
+ maNupPortraitSize = Size( aNupSize.Height(), aNupSize.Width() );
+ }
+ else
+ {
+ maNupPortraitSize = aNupSize;
+ maNupLandscapeSize = Size( aNupSize.Height(), aNupSize.Width() );
+ }
+ maNUpPage.initFromMultiPageSetup( maPController->getMultipage() );
+
+
+ // setup click handler on the various buttons
+ maOKButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
+ #if OSL_DEBUG_LEVEL > 1
+ maCancelButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
+ #endif
+ maHelpButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maForwardBtn.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maBackwardBtn.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maJobPage.maCollateBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maJobPage.maSetupButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maJobPage.maDetailsBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maNUpPage.maBorderCB.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maOptionsPage.maToFileBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maOptionsPage.maReverseOrderBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maOptionsPage.maCollateSingleJobsBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
+ maNUpPage.maPagesBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
+
+ // setup modify hdl
+ maPageEdit.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
+ maJobPage.maCopyCountField.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
+ maNUpPage.maNupRowsEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
+ maNUpPage.maNupColEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
+ maNUpPage.maPageMarginEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
+ maNUpPage.maSheetMarginEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
+
+ // setup select hdl
+ maNUpPage.maNupPagesBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
+ maNUpPage.maNupOrientationBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
+ maNUpPage.maNupOrderBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
+
+ // setup the layout
+ setupLayout();
+
+ // setup optional UI options set by application
+ setupOptionalUI();
+
+ // set change handler for UI options
+ maPController->setOptionChangeHdl( LINK( this, PrintDialog, UIOptionsChanged ) );
+
+ // set min size pixel to current size
+ Size aOutSize( GetOutputSizePixel() );
+ SetMinOutputSizePixel( aOutSize );
+
+ // if there is space enough, enlarge the preview so it gets roughly as
+ // high as the tab control
+ if( aOutSize.Width() < 768 )
+ {
+ Size aJobPageSize( getJobPageSize() );
+ Size aTabSize( maTabCtrl.GetSizePixel() );
+ if( aJobPageSize.Width() < 1 )
+ aJobPageSize.Width() = aTabSize.Width();
+ if( aJobPageSize.Height() < 1 )
+ aJobPageSize.Height() = aTabSize.Height();
+ long nOptPreviewWidth = aTabSize.Height() * aJobPageSize.Width() / aJobPageSize.Height();
+ // add space for borders
+ nOptPreviewWidth += 15;
+ if( aOutSize.Width() - aTabSize.Width() < nOptPreviewWidth )
+ {
+ aOutSize.Width() = aTabSize.Width() + nOptPreviewWidth;
+ if( aOutSize.Width() > 768 ) // don't enlarge the dialog too much
+ aOutSize.Width() = 768;
+ SetOutputSizePixel( aOutSize );
+ }
+ }
+
+ // set HelpIDs
+ SMHID1( "Dialog" );
+ maOKButton.SMHID1( "OK" );
+ maCancelButton.SMHID1( "Cancel" );
+ maHelpButton.SMHID1( "Help" );
+ maPreviewWindow.SMHID1( "Preview" );
+ maNumPagesText.SMHID1( "NumPagesText" );
+ maPageEdit.SMHID1( "PageEdit" );
+ maForwardBtn.SMHID1( "ForwardBtn" );
+ maBackwardBtn.SMHID1( "BackwardBtn" );
+ maTabCtrl.SMHID1( "TabPages" );
+
+ // append further tab pages
+ if( mbShowLayoutPage )
+ {
+ maTabCtrl.InsertPage( SV_PRINT_TAB_NUP, maNUpPage.GetText() );
+ maTabCtrl.SetTabPage( SV_PRINT_TAB_NUP, &maNUpPage );
+ }
+ maTabCtrl.InsertPage( SV_PRINT_TAB_OPT, maOptionsPage.GetText() );
+ maTabCtrl.SetTabPage( SV_PRINT_TAB_OPT, &maOptionsPage );
+
+ // restore settings from last run
+ readFromSettings();
+
+ // setup dependencies
+ checkControlDependencies();
+
+}
+
+PrintDialog::~PrintDialog()
+{
+ while( ! maControls.empty() )
+ {
+ delete maControls.front();
+ maControls.pop_front();
+ }
+}
+
+void PrintDialog::setupLayout()
+{
+ Size aBorder( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) );
+
+ maLayout.setParentWindow( this );
+
+ boost::shared_ptr< vcl::RowOrColumn > xPreviewAndTab( new vcl::RowOrColumn( &maLayout, false ) );
+ size_t nIndex = maLayout.addChild( xPreviewAndTab, 5 );
+ maLayout.setBorders( nIndex, aBorder.Width(), aBorder.Width(), aBorder.Width(), 0 );
+
+ // setup column for preview and sub controls
+ boost::shared_ptr< vcl::RowOrColumn > xPreview( new vcl::RowOrColumn( xPreviewAndTab.get() ) );
+ xPreviewAndTab->addChild( xPreview, 5 );
+ xPreview->addWindow( &maPreviewWindow, 5 );
+ // get a row for the preview controls
+ mxPreviewCtrls.reset( new vcl::RowOrColumn( xPreview.get(), false ) );
+ nIndex = xPreview->addChild( mxPreviewCtrls );
+ boost::shared_ptr< vcl::Spacer > xSpacer( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
+ mxPreviewCtrls->addChild( xSpacer );
+ mxPreviewCtrls->addWindow( &maPageEdit );
+ mxPreviewCtrls->addWindow( &maNumPagesText );
+ xSpacer.reset( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
+ mxPreviewCtrls->addChild( xSpacer );
+ mxPreviewCtrls->addWindow( &maBackwardBtn );
+ mxPreviewCtrls->addWindow( &maForwardBtn );
+ xSpacer.reset( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
+ mxPreviewCtrls->addChild( xSpacer );
+
+ // continue with the tab ctrl
+ xPreviewAndTab->addWindow( &maTabCtrl );
+
+ // add the button line
+ maLayout.addWindow( &maButtonLine );
+
+ // add the row for the buttons
+ boost::shared_ptr< vcl::RowOrColumn > xButtons( new vcl::RowOrColumn( &maLayout, false ) );
+ nIndex = maLayout.addChild( xButtons );
+ maLayout.setBorders( nIndex, aBorder.Width(), 0, aBorder.Width(), aBorder.Width() );
+
+ Size aMinSize( maCancelButton.GetSizePixel() );
+ // insert help button
+ xButtons->setMinimumSize( xButtons->addWindow( &maHelpButton ), aMinSize );
+ // insert a spacer, cancel and OK buttons are right aligned
+ xSpacer.reset( new vcl::Spacer( xButtons.get(), 2 ) );
+ xButtons->addChild( xSpacer );
+ xButtons->setMinimumSize( xButtons->addWindow( &maOKButton ), aMinSize );
+ xButtons->setMinimumSize( xButtons->addWindow( &maCancelButton ), aMinSize );
+}
+
+void PrintDialog::readFromSettings()
+{
+ maJobPage.readFromSettings();
+ maNUpPage.readFromSettings();
+ maOptionsPage.readFromSettings();
+
+ // read last selected tab page; if it exists, actiavte it
+ SettingsConfigItem* pItem = SettingsConfigItem::get();
+ rtl::OUString aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPage" ) ) );
+ USHORT nCount = maTabCtrl.GetPageCount();
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ USHORT nPageId = maTabCtrl.GetPageId( i );
+ if( aValue.equals( maTabCtrl.GetPageText( nPageId ) ) )
+ {
+ maTabCtrl.SelectTabPage( nPageId );
+ break;
+ }
+ }
+ maOKButton.SetText( maOptionsPage.maToFileBox.IsChecked() ? maPrintToFileText : maPrintText );
+}
+
+void PrintDialog::storeToSettings()
+{
+ maJobPage.storeToSettings();
+ maNUpPage.storeToSettings();
+ maOptionsPage.storeToSettings();
+
+ // store last selected printer
+ SettingsConfigItem* pItem = SettingsConfigItem::get();
+ pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinter" ) ),
+ maJobPage.maPrinters.GetSelectEntry() );
+
+ pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPage" ) ),
+ maTabCtrl.GetPageText( maTabCtrl.GetCurPageId() ) );
+ pItem->Commit();
+}
+
+bool PrintDialog::isPrintToFile()
+{
+ return maOptionsPage.maToFileBox.IsChecked();
+}
+
+int PrintDialog::getCopyCount()
+{
+ return static_cast<int>(maJobPage.maCopyCountField.GetValue());
+}
+
+bool PrintDialog::isCollate()
+{
+ return maJobPage.maCopyCountField.GetValue() > 1 ? maJobPage.maCollateBox.IsChecked() : FALSE;
+}
+
+bool PrintDialog::isSingleJobs()
+{
+ return maOptionsPage.maCollateSingleJobsBox.IsChecked();
+}
+
+static void setSmartId( Window* i_pWindow, const char* i_pType, sal_Int32 i_nId = -1, const rtl::OUString& i_rPropName = rtl::OUString() )
+{
+ rtl::OUStringBuffer aBuf( 256 );
+ aBuf.appendAscii( HELPID_PREFIX );
+ if( i_rPropName.getLength() )
+ {
+ aBuf.append( sal_Unicode( ':' ) );
+ aBuf.append( i_rPropName );
+ }
+ if( i_pType )
+ {
+ aBuf.append( sal_Unicode( ':' ) );
+ aBuf.appendAscii( i_pType );
+ }
+ if( i_nId >= 0 )
+ {
+ aBuf.append( sal_Unicode( ':' ) );
+ aBuf.append( i_nId );
+ }
+ i_pWindow->SetSmartHelpId( SmartId( aBuf.makeStringAndClear(), HID_PRINTDLG ) );
+}
+
+static void setHelpText( Window* /*i_pWindow*/, const Sequence< rtl::OUString >& /*i_rHelpTexts*/, sal_Int32 /*i_nIndex*/ )
+{
+ // without a help text set and the correct smartID,
+ // help texts will be retrieved from the online help system
+
+ // passed help texts for optional UI is used only for native dialogs which currently
+ // cannot access the same (rather implicit) mechanism
+ #if 0
+ if( i_nIndex >= 0 && i_nIndex < i_rHelpTexts.getLength() )
+ i_pWindow->SetHelpText( i_rHelpTexts.getConstArray()[i_nIndex] );
+ #endif
+}
+
+void updateMaxSize( const Size& i_rCheckSize, Size& o_rMaxSize )
+{
+ if( i_rCheckSize.Width() > o_rMaxSize.Width() )
+ o_rMaxSize.Width() = i_rCheckSize.Width();
+ if( i_rCheckSize.Height() > o_rMaxSize.Height() )
+ o_rMaxSize.Height() = i_rCheckSize.Height();
+}
+
+void PrintDialog::setupOptionalUI()
+{
+ Size aBorder( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) );
+
+ std::vector<vcl::RowOrColumn*> aDynamicColumns;
+ vcl::RowOrColumn* pCurColumn = 0;
+
+ Window* pCurParent = 0, *pDynamicPageParent = 0;
+ USHORT nOptPageId = 9, nCurSubGroup = 0;
+ bool bOnStaticPage = false;
+ bool bSubgroupOnStaticPage = false;
+
+ std::multimap< rtl::OUString, vcl::RowOrColumn* > aPropertyToDependencyRowMap;
+
+ const Sequence< PropertyValue >& rOptions( maPController->getUIOptions() );
+ for( int i = 0; i < rOptions.getLength(); i++ )
+ {
+ Sequence< beans::PropertyValue > aOptProp;
+ rOptions[i].Value >>= aOptProp;
+
+ // extract ui element
+ bool bEnabled = true;
+ rtl::OUString aCtrlType;
+ rtl::OUString aText;
+ rtl::OUString aPropertyName;
+ Sequence< rtl::OUString > aChoices;
+ Sequence< rtl::OUString > aHelpTexts;
+ sal_Int64 nMinValue = 0, nMaxValue = 0;
+ sal_Int32 nCurHelpText = 0;
+ rtl::OUString aGroupingHint;
+ rtl::OUString aDependsOnName;
+ sal_Int32 nDependsOnValue = 0;
+ sal_Bool bUseDependencyRow = sal_False;
+
+ for( int n = 0; n < aOptProp.getLength(); n++ )
+ {
+ const beans::PropertyValue& rEntry( aOptProp[ n ] );
+ if( rEntry.Name.equalsAscii( "Text" ) )
+ {
+ rEntry.Value >>= aText;
+ }
+ else if( rEntry.Name.equalsAscii( "ControlType" ) )
+ {
+ rEntry.Value >>= aCtrlType;
+ }
+ else if( rEntry.Name.equalsAscii( "Choices" ) )
+ {
+ rEntry.Value >>= aChoices;
+ }
+ else if( rEntry.Name.equalsAscii( "Property" ) )
+ {
+ PropertyValue aVal;
+ rEntry.Value >>= aVal;
+ aPropertyName = aVal.Name;
+ }
+ else if( rEntry.Name.equalsAscii( "Enabled" ) )
+ {
+ sal_Bool bValue = sal_True;
+ rEntry.Value >>= bValue;
+ bEnabled = bValue;
+ }
+ else if( rEntry.Name.equalsAscii( "GroupingHint" ) )
+ {
+ rEntry.Value >>= aGroupingHint;
+ }
+ else if( rEntry.Name.equalsAscii( "DependsOnName" ) )
+ {
+ rEntry.Value >>= aDependsOnName;
+ }
+ else if( rEntry.Name.equalsAscii( "DependsOnEntry" ) )
+ {
+ rEntry.Value >>= nDependsOnValue;
+ }
+ else if( rEntry.Name.equalsAscii( "AttachToDependency" ) )
+ {
+ rEntry.Value >>= bUseDependencyRow;
+ }
+ else if( rEntry.Name.equalsAscii( "MinValue" ) )
+ {
+ rEntry.Value >>= nMinValue;
+ }
+ else if( rEntry.Name.equalsAscii( "MaxValue" ) )
+ {
+ rEntry.Value >>= nMaxValue;
+ }
+ else if( rEntry.Name.equalsAscii( "HelpText" ) )
+ {
+ if( ! (rEntry.Value >>= aHelpTexts) )
+ {
+ rtl::OUString aHelpText;
+ if( (rEntry.Value >>= aHelpText) )
+ {
+ aHelpTexts.realloc( 1 );
+ *aHelpTexts.getArray() = aHelpText;
+ }
+ }
+ }
+ else if( rEntry.Name.equalsAscii( "HintNoLayoutPage" ) )
+ {
+ sal_Bool bNoLayoutPage = sal_False;
+ rEntry.Value >>= bNoLayoutPage;
+ mbShowLayoutPage = ! bNoLayoutPage;
+ }
+ }
+
+ // bUseDependencyRow should only be true if a dependency exists
+ bUseDependencyRow = bUseDependencyRow && (aDependsOnName.getLength() != 0);
+
+ // is it necessary to switch between static and dynamic pages ?
+ bool bSwitchPage = false;
+ if( aGroupingHint.getLength() )
+ bSwitchPage = true;
+ else if( aCtrlType.equalsAscii( "Subgroup" ) || (bOnStaticPage && ! bSubgroupOnStaticPage ) )
+ bSwitchPage = true;
+ if( bSwitchPage )
+ {
+ // restore to dynamic
+ pCurParent = pDynamicPageParent;
+ pCurColumn = aDynamicColumns.empty() ? NULL : aDynamicColumns.back();
+ bOnStaticPage = false;
+ bSubgroupOnStaticPage = false;
+
+ if( aGroupingHint.equalsAscii( "PrintRange" ) )
+ {
+ pCurColumn = maJobPage.mxPrintRange.get();
+ pCurParent = &maJobPage; // set job page as current parent
+ bOnStaticPage = true;
+ }
+ else if( aGroupingHint.equalsAscii( "OptionsPage" ) )
+ {
+ pCurColumn = &maOptionsPage.maLayout;
+ pCurParent = &maOptionsPage; // set options page as current parent
+ bOnStaticPage = true;
+ }
+ else if( aGroupingHint.equalsAscii( "OptionsPageOptGroup" ) )
+ {
+ pCurColumn = maOptionsPage.mxOptGroup.get();
+ pCurParent = &maOptionsPage; // set options page as current parent
+ bOnStaticPage = true;
+ }
+ else if( aGroupingHint.equalsAscii( "LayoutPage" ) )
+ {
+ pCurColumn = &maNUpPage.maLayout;
+ pCurParent = &maNUpPage; // set layout page as current parent
+ bOnStaticPage = true;
+ }
+ else if( aGroupingHint.getLength() )
+ {
+ pCurColumn = &maJobPage.maLayout;
+ pCurParent = &maJobPage; // set job page as current parent
+ bOnStaticPage = true;
+ }
+ }
+
+ if( aCtrlType.equalsAscii( "Group" ) ||
+ ( ! pCurParent && ! (bOnStaticPage || aGroupingHint.getLength() ) ) )
+ {
+ // add new tab page
+ TabPage* pNewGroup = new TabPage( &maTabCtrl );
+ maControls.push_front( pNewGroup );
+ pDynamicPageParent = pCurParent = pNewGroup;
+ pNewGroup->SetText( aText );
+ maTabCtrl.InsertPage( ++nOptPageId, aText );
+ maTabCtrl.SetTabPage( nOptPageId, pNewGroup );
+
+ // set help id
+ setSmartId( pNewGroup, "TabPage", nOptPageId );
+ // set help text
+ setHelpText( pNewGroup, aHelpTexts, 0 );
+
+ // reset subgroup counter
+ nCurSubGroup = 0;
+
+ aDynamicColumns.push_back( new vcl::RowOrColumn( NULL, true, aBorder.Width() ) );
+ pCurColumn = aDynamicColumns.back();
+ pCurColumn->setParentWindow( pNewGroup );
+ pCurColumn->setOuterBorder( aBorder.Width() );
+ bSubgroupOnStaticPage = false;
+ bOnStaticPage = false;
+ }
+ else if( aCtrlType.equalsAscii( "Subgroup" ) && (pCurParent || aGroupingHint.getLength() ) )
+ {
+ bSubgroupOnStaticPage = (aGroupingHint.getLength() != 0);
+ // create group FixedLine
+ if( ! aGroupingHint.equalsAscii( "PrintRange" ) ||
+ ! pCurColumn->countElements() == 0
+ )
+ {
+ Window* pNewSub = NULL;
+ if( aGroupingHint.equalsAscii( "PrintRange" ) )
+ pNewSub = new FixedText( pCurParent, WB_VCENTER );
+ else
+ pNewSub = new FixedLine( pCurParent );
+ maControls.push_front( pNewSub );
+ pNewSub->SetText( aText );
+ pNewSub->Show();
+
+ // set help id
+ setSmartId( pNewSub, "FixedLine", sal_Int32( nCurSubGroup++ ) );
+ // set help text
+ setHelpText( pNewSub, aHelpTexts, 0 );
+ // add group to current column
+ pCurColumn->addWindow( pNewSub );
+ }
+
+ // add an indent to the current column
+ vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn, aBorder.Width() );
+ pCurColumn->addChild( pIndent );
+ // and create a column inside the indent
+ pCurColumn = new vcl::RowOrColumn( pIndent );
+ pIndent->setChild( pCurColumn );
+ }
+ // EVIL
+ else if( aCtrlType.equalsAscii( "Bool" ) &&
+ aGroupingHint.equalsAscii( "LayoutPage" ) &&
+ aPropertyName.equalsAscii( "PrintProspect" )
+ )
+ {
+ maNUpPage.maBrochureBtn.SetText( aText );
+ maNUpPage.maBrochureBtn.Show();
+ setHelpText( &maNUpPage.maBrochureBtn, aHelpTexts, 0 );
+
+ sal_Bool bVal = sal_False;
+ PropertyValue* pVal = maPController->getValue( aPropertyName );
+ if( pVal )
+ pVal->Value >>= bVal;
+ maNUpPage.maBrochureBtn.Check( bVal );
+ maNUpPage.maBrochureBtn.Enable( maPController->isUIOptionEnabled( aPropertyName ) && pVal != NULL );
+ maNUpPage.maBrochureBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
+
+ maPropertyToWindowMap[ aPropertyName ].push_back( &maNUpPage.maBrochureBtn );
+ maControlToPropertyMap[&maNUpPage.maBrochureBtn] = aPropertyName;
+
+ aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, vcl::RowOrColumn* >( aPropertyName, maNUpPage.mxBrochureDep.get() ) );
+ }
+ else
+ {
+ vcl::RowOrColumn* pSaveCurColumn = pCurColumn;
+
+ if( bUseDependencyRow )
+ {
+ // find the correct dependency row (if any)
+ std::pair< std::multimap< rtl::OUString, vcl::RowOrColumn* >::iterator,
+ std::multimap< rtl::OUString, vcl::RowOrColumn* >::iterator > aDepRange;
+ aDepRange = aPropertyToDependencyRowMap.equal_range( aDependsOnName );
+ if( aDepRange.first != aDepRange.second )
+ {
+ while( nDependsOnValue && aDepRange.first != aDepRange.second )
+ {
+ nDependsOnValue--;
+ ++aDepRange.first;
+ }
+ if( aDepRange.first != aPropertyToDependencyRowMap.end() )
+ {
+ pCurColumn = aDepRange.first->second;
+ maReverseDependencySet.insert( aPropertyName );
+ }
+ }
+ }
+ if( aCtrlType.equalsAscii( "Bool" ) && pCurParent )
+ {
+ // add a check box
+ CheckBox* pNewBox = new CheckBox( pCurParent );
+ maControls.push_front( pNewBox );
+ pNewBox->SetText( aText );
+ pNewBox->Show();
+
+ sal_Bool bVal = sal_False;
+ PropertyValue* pVal = maPController->getValue( aPropertyName );
+ if( pVal )
+ pVal->Value >>= bVal;
+ pNewBox->Check( bVal );
+ pNewBox->SetToggleHdl( LINK( this, PrintDialog, UIOption_CheckHdl ) );
+
+ maPropertyToWindowMap[ aPropertyName ].push_back( pNewBox );
+ maControlToPropertyMap[pNewBox] = aPropertyName;
+
+ // set help id
+ setSmartId( pNewBox, "CheckBox", -1, aPropertyName );
+ // set help text
+ setHelpText( pNewBox, aHelpTexts, 0 );
+
+ vcl::RowOrColumn* pDependencyRow = new vcl::RowOrColumn( pCurColumn, false );
+ pCurColumn->addChild( pDependencyRow );
+ aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, vcl::RowOrColumn* >( aPropertyName, pDependencyRow ) );
+
+ // add checkbox to current column
+ pDependencyRow->addWindow( pNewBox );
+ }
+ else if( aCtrlType.equalsAscii( "Radio" ) && pCurParent )
+ {
+ vcl::RowOrColumn* pRadioColumn = pCurColumn;
+ if( aText.getLength() )
+ {
+ // add a FixedText:
+ FixedText* pHeading = new FixedText( pCurParent );
+ maControls.push_front( pHeading );
+ pHeading->SetText( aText );
+ pHeading->Show();
+
+ // set help id
+ setSmartId( pHeading, "FixedText", -1, aPropertyName );
+ // set help text
+ setHelpText( pHeading, aHelpTexts, nCurHelpText++ );
+ // add fixed text to current column
+ pCurColumn->addWindow( pHeading );
+ // add an indent to the current column
+ vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn, 15 );
+ pCurColumn->addChild( pIndent );
+ // and create a column inside the indent
+ pRadioColumn = new vcl::RowOrColumn( pIndent );
+ pIndent->setChild( pRadioColumn );
+ }
+ // iterate options
+ sal_Int32 nSelectVal = 0;
+ PropertyValue* pVal = maPController->getValue( aPropertyName );
+ if( pVal && pVal->Value.hasValue() )
+ pVal->Value >>= nSelectVal;
+ for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
+ {
+ boost::shared_ptr<vcl::LabeledElement> pLabel( new vcl::LabeledElement( pRadioColumn, 1 ) );
+ pRadioColumn->addChild( pLabel );
+ boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pLabel.get(), false ) );
+ pLabel->setElement( pDependencyRow );
+ aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, vcl::RowOrColumn* >( aPropertyName, pDependencyRow.get() ) );
+
+ RadioButton* pBtn = new RadioButton( pCurParent, m == 0 ? WB_GROUP : 0 );
+ maControls.push_front( pBtn );
+ pBtn->SetText( aChoices[m] );
+ pBtn->Check( m == nSelectVal );
+ pBtn->SetToggleHdl( LINK( this, PrintDialog, UIOption_RadioHdl ) );
+ pBtn->Show();
+ maPropertyToWindowMap[ aPropertyName ].push_back( pBtn );
+ maControlToPropertyMap[pBtn] = aPropertyName;
+ maControlToNumValMap[pBtn] = m;
+
+ // set help id
+ setSmartId( pBtn, "RadioButton", m, aPropertyName );
+ // set help text
+ setHelpText( pBtn, aHelpTexts, nCurHelpText++ );
+ // add the radio button to the column
+ pLabel->setLabel( pBtn );
+ }
+ }
+ else if( ( aCtrlType.equalsAscii( "List" ) ||
+ aCtrlType.equalsAscii( "Range" ) ||
+ aCtrlType.equalsAscii( "Edit" )
+ ) && pCurParent )
+ {
+ // create a row in the current column
+ vcl::RowOrColumn* pFieldColumn = new vcl::RowOrColumn( pCurColumn, false );
+ pCurColumn->addChild( pFieldColumn );
+ aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, vcl::RowOrColumn* >( aPropertyName, pFieldColumn ) );
+
+ vcl::LabeledElement* pLabel = NULL;
+ if( aText.getLength() )
+ {
+ // add a FixedText:
+ FixedText* pHeading = new FixedText( pCurParent, WB_VCENTER );
+ maControls.push_front( pHeading );
+ pHeading->SetText( aText );
+ pHeading->Show();
+
+ // set help id
+ setSmartId( pHeading, "FixedText", -1, aPropertyName );
+
+ // add to row
+ pLabel = new vcl::LabeledElement( pFieldColumn, 2 );
+ pFieldColumn->addChild( pLabel );
+ pLabel->setLabel( pHeading );
+ }
+
+ if( aCtrlType.equalsAscii( "List" ) )
+ {
+ ListBox* pList = new ListBox( pCurParent, WB_DROPDOWN | WB_BORDER );
+ maControls.push_front( pList );
+
+ // iterate options
+ for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
+ {
+ pList->InsertEntry( aChoices[m] );
+ }
+ sal_Int32 nSelectVal = 0;
+ PropertyValue* pVal = maPController->getValue( aPropertyName );
+ if( pVal && pVal->Value.hasValue() )
+ pVal->Value >>= nSelectVal;
+ pList->SelectEntryPos( static_cast<USHORT>(nSelectVal) );
+ pList->SetSelectHdl( LINK( this, PrintDialog, UIOption_SelectHdl ) );
+ pList->SetDropDownLineCount( static_cast<USHORT>(aChoices.getLength()) );
+ pList->Show();
+
+ // set help id
+ setSmartId( pList, "ListBox", -1, aPropertyName );
+ // set help text
+ setHelpText( pList, aHelpTexts, 0 );
+
+ maPropertyToWindowMap[ aPropertyName ].push_back( pList );
+ maControlToPropertyMap[pList] = aPropertyName;
+
+ // finish the pair
+ if( pLabel )
+ pLabel->setElement( pList );
+ else
+ pFieldColumn->addWindow( pList );
+ }
+ else if( aCtrlType.equalsAscii( "Range" ) )
+ {
+ NumericField* pField = new NumericField( pCurParent, WB_BORDER | WB_SPIN );
+ maControls.push_front( pField );
+
+ // set min/max and current value
+ if( nMinValue != nMaxValue )
+ {
+ pField->SetMin( nMinValue );
+ pField->SetMax( nMaxValue );
+ }
+ sal_Int64 nCurVal = 0;
+ PropertyValue* pVal = maPController->getValue( aPropertyName );
+ if( pVal && pVal->Value.hasValue() )
+ pVal->Value >>= nCurVal;
+ pField->SetValue( nCurVal );
+ pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) );
+ pField->Show();
+
+ // set help id
+ setSmartId( pField, "NumericField", -1, aPropertyName );
+ // set help text
+ setHelpText( pField, aHelpTexts, 0 );
+
+ maPropertyToWindowMap[ aPropertyName ].push_back( pField );
+ maControlToPropertyMap[pField] = aPropertyName;
+
+ // add to row
+ if( pLabel )
+ pLabel->setElement( pField );
+ else
+ pFieldColumn->addWindow( pField );
+ }
+ else if( aCtrlType.equalsAscii( "Edit" ) )
+ {
+ Edit* pField = new Edit( pCurParent, WB_BORDER );
+ maControls.push_front( pField );
+
+ rtl::OUString aCurVal;
+ PropertyValue* pVal = maPController->getValue( aPropertyName );
+ if( pVal && pVal->Value.hasValue() )
+ pVal->Value >>= aCurVal;
+ pField->SetText( aCurVal );
+ pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) );
+ pField->Show();
+
+ // set help id
+ setSmartId( pField, "Edit", -1, aPropertyName );
+ // set help text
+ setHelpText( pField, aHelpTexts, 0 );
+
+ maPropertyToWindowMap[ aPropertyName ].push_back( pField );
+ maControlToPropertyMap[pField] = aPropertyName;
+
+ // add to row
+ if( pLabel )
+ pLabel->setElement( pField );
+ else
+ pFieldColumn->addWindow( pField, 2 );
+ }
+ }
+ else
+ {
+ DBG_ERROR( "Unsupported UI option" );
+ }
+
+ pCurColumn = pSaveCurColumn;
+ }
+ }
+
+ // #i106506# if no brochure button, then the singular Pages radio button
+ // makes no sense, so replace it by a FixedText label
+ if( ! maNUpPage.maBrochureBtn.IsVisible() )
+ {
+ if( maNUpPage.mxPagesBtnLabel.get() )
+ {
+ maNUpPage.maPagesBoxTitleTxt.SetText( maNUpPage.maPagesBtn.GetText() );
+ maNUpPage.maPagesBoxTitleTxt.Show( TRUE );
+ maNUpPage.mxPagesBtnLabel->setLabel( &maNUpPage.maPagesBoxTitleTxt );
+ maNUpPage.maPagesBtn.Show( FALSE );
+ }
+ }
+
+ // update enable states
+ checkOptionalControlDependencies();
+
+ // print range empty (currently math only) -> hide print range and spacer line
+ if( maJobPage.mxPrintRange->countElements() == 0 )
+ {
+ maJobPage.mxPrintRange->show( false, false );
+ maJobPage.maCopySpacer.Show( FALSE );
+ }
+
+#ifdef WNT
+ // FIXME: the GetNativeControlRegion call on Windows has some issues
+ // (which skew the results of GetOptimalSize())
+ // however fixing this thoroughly needs to take interaction with paint into
+ // acoount, making the right fix less simple. Fix this the right way
+ // at some point. For now simply add some space at the lowest element
+ size_t nIndex = maJobPage.maLayout.countElements();
+ if( nIndex > 0 ) // sanity check
+ maJobPage.maLayout.setBorders( nIndex-1, 0, 0, 0, aBorder.Width() );
+#endif
+
+ // create auto mnemomnics now so they can be calculated in layout
+ ImplWindowAutoMnemonic( &maJobPage );
+ ImplWindowAutoMnemonic( &maNUpPage );
+ ImplWindowAutoMnemonic( &maOptionsPage );
+ ImplWindowAutoMnemonic( this );
+
+ // calculate job page
+ Size aMaxSize = maJobPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED );
+ // and layout page
+ updateMaxSize( maNUpPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
+ // and options page
+ updateMaxSize( maOptionsPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
+
+ for( std::vector< vcl::RowOrColumn* >::iterator it = aDynamicColumns.begin();
+ it != aDynamicColumns.end(); ++it )
+ {
+ Size aPageSize( (*it)->getOptimalSize( WINDOWSIZE_PREFERRED ) );
+ updateMaxSize( aPageSize, aMaxSize );
+ }
+
+ // resize dialog if necessary
+ Size aTabSize = maTabCtrl.GetTabPageSizePixel();
+ maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
+ if( aMaxSize.Height() > aTabSize.Height() || aMaxSize.Width() > aTabSize.Width() )
+ {
+ Size aCurSize( GetOutputSizePixel() );
+ if( aMaxSize.Height() > aTabSize.Height() )
+ {
+ aCurSize.Height() += aMaxSize.Height() - aTabSize.Height();
+ aTabSize.Height() = aMaxSize.Height();
+ }
+ if( aMaxSize.Width() > aTabSize.Width() )
+ {
+ aCurSize.Width() += aMaxSize.Width() - aTabSize.Width();
+ // and the tab ctrl needs more space, too
+ aTabSize.Width() = aMaxSize.Width();
+ }
+ maTabCtrl.SetTabPageSizePixel( aTabSize );
+ maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
+ }
+
+ // and finally arrange controls
+ for( std::vector< vcl::RowOrColumn* >::iterator it = aDynamicColumns.begin();
+ it != aDynamicColumns.end(); ++it )
+ {
+ (*it)->setManagedArea( Rectangle( Point(), aTabSize ) );
+ delete *it;
+ *it = NULL;
+ }
+ maJobPage.Resize();
+ maNUpPage.Resize();
+ maOptionsPage.Resize();
+
+ Size aSz = maLayout.getOptimalSize( WINDOWSIZE_PREFERRED );
+ SetOutputSizePixel( aSz );
+}
+
+void PrintDialog::DataChanged( const DataChangedEvent& i_rDCEvt )
+{
+ // react on settings changed
+ if( i_rDCEvt.GetType() == DATACHANGED_SETTINGS )
+ checkControlDependencies();
+ ModalDialog::DataChanged( i_rDCEvt );
+}
+
+void PrintDialog::checkControlDependencies()
+{
+ if( maJobPage.maCopyCountField.GetValue() > 1 )
+ maJobPage.maCollateBox.Enable( maJobPage.mnCollateUIMode == 0 );
+ else
+ maJobPage.maCollateBox.Enable( FALSE );
+
+ Image aImg( maJobPage.maCollateBox.IsChecked() ? maJobPage.maCollateImg : maJobPage.maNoCollateImg );
+ Image aHCImg( maJobPage.maCollateBox.IsChecked() ? maJobPage.maCollateHCImg : maJobPage.maNoCollateHCImg );
+ bool bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
+
+ Size aImgSize( aImg.GetSizePixel() );
+ Size aHCImgSize( aHCImg.GetSizePixel() );
+
+ if( aHCImgSize.Width() > aImgSize.Width() )
+ aImgSize.Width() = aHCImgSize.Width();
+ if( aHCImgSize.Height() > aImgSize.Height() )
+ aImgSize.Height() = aHCImgSize.Height();
+
+ // adjust size of image
+ maJobPage.maCollateImage.SetSizePixel( aImgSize );
+ maJobPage.maCollateImage.SetImage( bHC ? aHCImg : aImg );
+ maJobPage.maCollateImage.SetModeImage( aHCImg, BMP_COLOR_HIGHCONTRAST );
+ maJobPage.maLayout.resize();
+
+ // enable setup button only for printers that can be setup
+ bool bHaveSetup = maPController->getPrinter()->HasSupport( SUPPORT_SETUPDIALOG );
+ maJobPage.maSetupButton.Enable( bHaveSetup );
+ if( bHaveSetup )
+ {
+ if( ! maJobPage.maSetupButton.IsVisible() )
+ {
+ Point aPrinterPos( maJobPage.maPrinters.GetPosPixel() );
+ Point aSetupPos( maJobPage.maSetupButton.GetPosPixel() );
+ Size aPrinterSize( maJobPage.maPrinters.GetSizePixel() );
+ aPrinterSize.Width() = aSetupPos.X() - aPrinterPos.X() - LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ).Width();
+ maJobPage.maPrinters.SetSizePixel( aPrinterSize );
+ maJobPage.maSetupButton.Show();
+ maLayout.resize();
+ }
+ }
+ else
+ {
+ if( maJobPage.maSetupButton.IsVisible() )
+ {
+ Point aPrinterPos( maJobPage.maPrinters.GetPosPixel() );
+ Point aSetupPos( maJobPage.maSetupButton.GetPosPixel() );
+ Size aPrinterSize( maJobPage.maPrinters.GetSizePixel() );
+ Size aSetupSize( maJobPage.maSetupButton.GetSizePixel() );
+ aPrinterSize.Width() = aSetupPos.X() + aSetupSize.Width() - aPrinterPos.X();
+ maJobPage.maPrinters.SetSizePixel( aPrinterSize );
+ maJobPage.maSetupButton.Hide();
+ maLayout.resize();
+ }
+ }
+}
+
+void PrintDialog::checkOptionalControlDependencies()
+{
+ for( std::map< Window*, rtl::OUString >::iterator it = maControlToPropertyMap.begin();
+ it != maControlToPropertyMap.end(); ++it )
+ {
+ bool bShouldbeEnabled = maPController->isUIOptionEnabled( it->second );
+ if( ! bShouldbeEnabled )
+ {
+ // enable controls that are directly attached to a dependency anyway
+ // if the normally disabled controls get modified, change the dependency
+ // so the control would be enabled
+ // example: in print range "Print All" is selected, "Page Range" is then of course
+ // not selected and the Edit for the Page Range would be disabled
+ // as a convenience we should enable the Edit anyway and automatically select
+ // "Page Range" instead of "Print All" if the Edit gets modified
+ if( maReverseDependencySet.find( it->second ) != maReverseDependencySet.end() )
+ {
+ rtl::OUString aDep( maPController->getDependency( it->second ) );
+ // if the dependency is at least enabled, then enable this control anyway
+ if( aDep.getLength() && maPController->isUIOptionEnabled( aDep ) )
+ bShouldbeEnabled = true;
+ }
+ }
+
+ bool bIsEnabled = it->first->IsEnabled();
+ // Enable does not do a change check first, so can be less cheap than expected
+ if( bShouldbeEnabled != bIsEnabled )
+ it->first->Enable( bShouldbeEnabled );
+ }
+}
+
+static rtl::OUString searchAndReplace( const rtl::OUString& i_rOrig, const char* i_pRepl, sal_Int32 i_nReplLen, const rtl::OUString& i_rRepl )
+{
+ sal_Int32 nPos = i_rOrig.indexOfAsciiL( i_pRepl, i_nReplLen );
+ if( nPos != -1 )
+ {
+ rtl::OUStringBuffer aBuf( i_rOrig.getLength() );
+ aBuf.append( i_rOrig.getStr(), nPos );
+ aBuf.append( i_rRepl );
+ if( nPos + i_nReplLen < i_rOrig.getLength() )
+ aBuf.append( i_rOrig.getStr() + nPos + i_nReplLen );
+ return aBuf.makeStringAndClear();
+ }
+ return i_rOrig;
+}
+
+void PrintDialog::updatePrinterText()
+{
+ String aDefPrt( Printer::GetDefaultPrinterName() );
+ const QueueInfo* pInfo = Printer::GetQueueInfo( maJobPage.maPrinters.GetSelectEntry(), true );
+ if( pInfo )
+ {
+ maJobPage.maLocationTxt.SetText( pInfo->GetLocation() );
+ maJobPage.maCommentTxt.SetText( pInfo->GetComment() );
+ // FIXME: status text
+ rtl::OUString aStatus;
+ if( aDefPrt == pInfo->GetPrinterName() )
+ aStatus = maDefPrtText;
+ maJobPage.maStatusTxt.SetText( aStatus );
+ }
+ else
+ {
+ maJobPage.maLocationTxt.SetText( String() );
+ maJobPage.maCommentTxt.SetText( String() );
+ maJobPage.maStatusTxt.SetText( String() );
+ }
+}
+
+void PrintDialog::setPreviewText( sal_Int32 )
+{
+ rtl::OUString aNewText( searchAndReplace( maPageStr, "%n", 2, rtl::OUString::valueOf( mnCachedPages ) ) );
+ maNumPagesText.SetText( aNewText );
+
+ // if layout is already established the refresh layout of
+ // preview controls since text length may have changes
+ if( mxPreviewCtrls.get() )
+ mxPreviewCtrls->setManagedArea( mxPreviewCtrls->getManagedArea() );
+}
+
+void PrintDialog::preparePreview( bool i_bNewPage, bool i_bMayUseCache )
+{
+ // page range may have changed depending on options
+ sal_Int32 nPages = maPController->getFilteredPageCount();
+ mnCachedPages = nPages;
+
+ if( mnCurPage >= nPages )
+ mnCurPage = nPages-1;
+ if( mnCurPage < 0 )
+ mnCurPage = 0;
+
+ setPreviewText( mnCurPage );
+
+ maPageEdit.SetMin( 1 );
+ maPageEdit.SetMax( nPages );
+
+ if( i_bNewPage )
+ {
+ const MapMode aMapMode( MAP_100TH_MM );
+ GDIMetaFile aMtf;
+ boost::shared_ptr<Printer> aPrt( maPController->getPrinter() );
+ if( nPages > 0 )
+ {
+ PrinterController::PageSize aPageSize =
+ maPController->getFilteredPageFile( mnCurPage, aMtf, i_bMayUseCache );
+ if( ! aPageSize.bFullPaper )
+ {
+ Point aOff( aPrt->PixelToLogic( aPrt->GetPageOffsetPixel(), aMapMode ) );
+ aMtf.Move( aOff.X(), aOff.Y() );
+ }
+ }
+
+ Size aCurPageSize = aPrt->PixelToLogic( aPrt->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) );
+ maPreviewWindow.setPreview( aMtf, aCurPageSize, nPages > 0 ? rtl::OUString() : maNoPageStr,
+ aPrt->ImplGetDPIX(), aPrt->ImplGetDPIY()
+ );
+
+ maForwardBtn.Enable( mnCurPage < nPages-1 );
+ maBackwardBtn.Enable( mnCurPage != 0 );
+ maPageEdit.Enable( nPages > 1 );
+ }
+}
+
+Size PrintDialog::getJobPageSize()
+{
+ if( maFirstPageSize.Width() == 0 && maFirstPageSize.Height() == 0)
+ {
+ maFirstPageSize = maNupPortraitSize;
+ GDIMetaFile aMtf;
+ if( maPController->getPageCountProtected() > 0 )
+ {
+ PrinterController::PageSize aPageSize = maPController->getPageFile( 0, aMtf, true );
+ maFirstPageSize = aPageSize.aSize;
+ }
+ }
+ return maFirstPageSize;
+}
+
+void PrintDialog::updateNupFromPages()
+{
+ long nPages = long(maNUpPage.maNupPagesBox.GetEntryData(maNUpPage.maNupPagesBox.GetSelectEntryPos()));
+ int nRows = int(maNUpPage.maNupRowsEdt.GetValue());
+ int nCols = int(maNUpPage.maNupColEdt.GetValue());
+ long nPageMargin = long(maNUpPage.maPageMarginEdt.Denormalize(maNUpPage.maPageMarginEdt.GetValue( FUNIT_100TH_MM )));
+ long nSheetMargin = long(maNUpPage.maSheetMarginEdt.Denormalize(maNUpPage.maSheetMarginEdt.GetValue( FUNIT_100TH_MM )));
+ bool bCustom = false;
+
+ if( nPages == 1 )
+ {
+ nRows = nCols = 1;
+ nSheetMargin = 0;
+ nPageMargin = 0;
+ }
+ else if( nPages == 2 || nPages == 4 || nPages == 6 || nPages == 9 || nPages == 16 )
+ {
+ Size aJobPageSize( getJobPageSize() );
+ bool bPortrait = aJobPageSize.Width() < aJobPageSize.Height();
+ if( nPages == 2 )
+ {
+ if( bPortrait )
+ nRows = 1, nCols = 2;
+ else
+ nRows = 2, nCols = 1;
+ }
+ else if( nPages == 4 )
+ nRows = nCols = 2;
+ else if( nPages == 6 )
+ {
+ if( bPortrait )
+ nRows = 2, nCols = 3;
+ else
+ nRows = 3, nCols = 2;
+ }
+ else if( nPages == 9 )
+ nRows = nCols = 3;
+ else if( nPages == 16 )
+ nRows = nCols = 4;
+ nPageMargin = 0;
+ nSheetMargin = 0;
+ }
+ else
+ bCustom = true;
+
+ if( nPages > 1 )
+ {
+ // set upper limits for margins based on job page size and rows/columns
+ Size aSize( getJobPageSize() );
+
+ // maximum sheet distance: 1/2 sheet
+ long nHorzMax = aSize.Width()/2;
+ long nVertMax = aSize.Height()/2;
+ if( nSheetMargin > nHorzMax )
+ nSheetMargin = nHorzMax;
+ if( nSheetMargin > nVertMax )
+ nSheetMargin = nVertMax;
+
+ maNUpPage.maSheetMarginEdt.SetMax(
+ maNUpPage.maSheetMarginEdt.Normalize(
+ nHorzMax > nVertMax ? nVertMax : nHorzMax ), FUNIT_100TH_MM );
+
+ // maximum page distance
+ nHorzMax = (aSize.Width() - 2*nSheetMargin);
+ if( nCols > 1 )
+ nHorzMax /= (nCols-1);
+ nVertMax = (aSize.Height() - 2*nSheetMargin);
+ if( nRows > 1 )
+ nHorzMax /= (nRows-1);
+
+ if( nPageMargin > nHorzMax )
+ nPageMargin = nHorzMax;
+ if( nPageMargin > nVertMax )
+ nPageMargin = nVertMax;
+
+ maNUpPage.maPageMarginEdt.SetMax(
+ maNUpPage.maSheetMarginEdt.Normalize(
+ nHorzMax > nVertMax ? nVertMax : nHorzMax ), FUNIT_100TH_MM );
+ }
+
+ maNUpPage.maNupRowsEdt.SetValue( nRows );
+ maNUpPage.maNupColEdt.SetValue( nCols );
+ maNUpPage.maPageMarginEdt.SetValue( maNUpPage.maPageMarginEdt.Normalize( nPageMargin ), FUNIT_100TH_MM );
+ maNUpPage.maSheetMarginEdt.SetValue( maNUpPage.maSheetMarginEdt.Normalize( nSheetMargin ), FUNIT_100TH_MM );
+
+ maNUpPage.showAdvancedControls( bCustom );
+ if( bCustom )
+ {
+ // see if we have to enlarge the dialog to make the tab page fit
+ Size aCurSize( maNUpPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED ) );
+ Size aTabSize( maTabCtrl.GetTabPageSizePixel() );
+ if( aTabSize.Height() < aCurSize.Height() )
+ {
+ Size aDlgSize( GetSizePixel() );
+ aDlgSize.Height() += aCurSize.Height() - aTabSize.Height();
+ SetSizePixel( aDlgSize );
+ }
+ }
+
+ updateNup();
+}
+
+void PrintDialog::updateNup()
+{
+ int nRows = int(maNUpPage.maNupRowsEdt.GetValue());
+ int nCols = int(maNUpPage.maNupColEdt.GetValue());
+ long nPageMargin = long(maNUpPage.maPageMarginEdt.Denormalize(maNUpPage.maPageMarginEdt.GetValue( FUNIT_100TH_MM )));
+ long nSheetMargin = long(maNUpPage.maSheetMarginEdt.Denormalize(maNUpPage.maSheetMarginEdt.GetValue( FUNIT_100TH_MM )));
+
+ PrinterController::MultiPageSetup aMPS;
+ aMPS.nRows = nRows;
+ aMPS.nColumns = nCols;
+ aMPS.nRepeat = 1;
+ aMPS.nLeftMargin =
+ aMPS.nTopMargin =
+ aMPS.nRightMargin =
+ aMPS.nBottomMargin = nSheetMargin;
+
+ aMPS.nHorizontalSpacing =
+ aMPS.nVerticalSpacing = nPageMargin;
+
+ aMPS.bDrawBorder = maNUpPage.maBorderCB.IsChecked();
+
+ int nOrderMode = int(sal_IntPtr(maNUpPage.maNupOrderBox.GetEntryData(
+ maNUpPage.maNupOrderBox.GetSelectEntryPos() )));
+ if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_LRTD )
+ aMPS.nOrder = PrinterController::LRTB;
+ else if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_TDLR )
+ aMPS.nOrder = PrinterController::TBLR;
+
+ int nOrientationMode = int(sal_IntPtr(maNUpPage.maNupOrientationBox.GetEntryData(
+ maNUpPage.maNupOrientationBox.GetSelectEntryPos() )));
+ if( nOrientationMode == SV_PRINT_PRT_NUP_ORIENTATION_LANDSCAPE )
+ aMPS.aPaperSize = maNupLandscapeSize;
+ else if( nOrientationMode == SV_PRINT_PRT_NUP_ORIENTATION_PORTRAIT )
+ aMPS.aPaperSize = maNupPortraitSize;
+ else // automatic mode
+ {
+ // get size of first real page to see if it is portrait or landscape
+ // we assume same page sizes for all the pages for this
+ Size aPageSize = getJobPageSize();
+
+ Size aMultiSize( aPageSize.Width() * nCols, aPageSize.Height() * nRows );
+ if( aMultiSize.Width() > aMultiSize.Height() ) // fits better on landscape
+ aMPS.aPaperSize = maNupLandscapeSize;
+ else
+ aMPS.aPaperSize = maNupPortraitSize;
+ }
+
+ maPController->setMultipage( aMPS );
+
+ maNUpPage.maNupOrderWin.setValues( nOrderMode, nCols, nRows );
+
+ preparePreview( true, true );
+}
+
+IMPL_LINK( PrintDialog, SelectHdl, ListBox*, pBox )
+{
+ if( pBox == &maJobPage.maPrinters )
+ {
+ String aNewPrinter( pBox->GetSelectEntry() );
+ // set new printer
+ maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( aNewPrinter ) ) );
+ // update text fields
+ updatePrinterText();
+ }
+ else if( pBox == &maNUpPage.maNupOrientationBox || pBox == &maNUpPage.maNupOrderBox )
+ {
+ updateNup();
+ }
+ else if( pBox == &maNUpPage.maNupPagesBox )
+ {
+ if( !maNUpPage.maPagesBtn.IsChecked() )
+ maNUpPage.maPagesBtn.Check();
+ updateNupFromPages();
+ }
+
+ return 0;
+}
+
+IMPL_LINK( PrintDialog, ClickHdl, Button*, pButton )
+{
+ if( pButton == &maOKButton || pButton == &maCancelButton )
+ {
+ storeToSettings();
+ EndDialog( pButton == &maOKButton );
+ }
+ else if( pButton == &maHelpButton )
+ {
+ // start help system
+ Help* pHelp = Application::GetHelp();
+ if( pHelp )
+ {
+ // FIXME: find out proper help URL and use here
+ pHelp->Start( HID_PRINTDLG, GetParent() );
+ }
+ }
+ else if( pButton == &maForwardBtn )
+ {
+ previewForward();
+ }
+ else if( pButton == &maBackwardBtn )
+ {
+ previewBackward();
+ }
+ else if( pButton == &maOptionsPage.maToFileBox )
+ {
+ maOKButton.SetText( maOptionsPage.maToFileBox.IsChecked() ? maPrintToFileText : maPrintText );
+ maLayout.resize();
+ }
+ else if( pButton == &maNUpPage.maBrochureBtn )
+ {
+ PropertyValue* pVal = getValueForWindow( pButton );
+ if( pVal )
+ {
+ sal_Bool bVal = maNUpPage.maBrochureBtn.IsChecked();
+ pVal->Value <<= bVal;
+
+ checkOptionalControlDependencies();
+
+ // update preview and page settings
+ preparePreview();
+ }
+ if( maNUpPage.maBrochureBtn.IsChecked() )
+ {
+ maNUpPage.maNupPagesBox.SelectEntryPos( 0 );
+ updateNupFromPages();
+ maNUpPage.showAdvancedControls( false );
+ maNUpPage.enableNupControls( false );
+ }
+ }
+ else if( pButton == &maNUpPage.maPagesBtn )
+ {
+ maNUpPage.enableNupControls( true );
+ updateNupFromPages();
+ }
+ else if( pButton == &maJobPage.maDetailsBtn )
+ {
+ bool bShow = maJobPage.maDetailsBtn.IsChecked();
+ maJobPage.mxDetails->show( bShow );
+ if( bShow )
+ {
+ maDetailsCollapsedSize = GetOutputSizePixel();
+ // enlarge dialog if necessary
+ Size aMinSize( maJobPage.maLayout.getOptimalSize( WINDOWSIZE_MINIMUM ) );
+ Size aCurSize( maJobPage.GetSizePixel() );
+ if( aCurSize.Height() < aMinSize.Height() )
+ {
+ Size aDlgSize( GetOutputSizePixel() );
+ aDlgSize.Height() += aMinSize.Height() - aCurSize.Height();
+ SetOutputSizePixel( aDlgSize );
+ }
+ maDetailsExpandedSize = GetOutputSizePixel();
+ }
+ else if( maDetailsCollapsedSize.Width() > 0 &&
+ maDetailsCollapsedSize.Height() > 0 )
+ {
+ // if the user did not resize the dialog
+ // make it smaller again on collapsing the details
+ Size aDlgSize( GetOutputSizePixel() );
+ if( aDlgSize == maDetailsExpandedSize &&
+ aDlgSize.Height() > maDetailsCollapsedSize.Height() )
+ {
+ SetOutputSizePixel( maDetailsCollapsedSize );
+ }
+ }
+ }
+ else if( pButton == &maJobPage.maCollateBox )
+ {
+ maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
+ makeAny( sal_Bool(isCollate()) ) );
+ checkControlDependencies();
+ }
+ else if( pButton == &maOptionsPage.maReverseOrderBox )
+ {
+ sal_Bool bChecked = maOptionsPage.maReverseOrderBox.IsChecked();
+ maPController->setReversePrint( bChecked );
+ maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintReverse" ) ),
+ makeAny( bChecked ) );
+ preparePreview( true, true );
+ }
+ else if( pButton == &maNUpPage.maBorderCB )
+ {
+ updateNup();
+ }
+ else
+ {
+ if( pButton == &maJobPage.maSetupButton )
+ {
+ maPController->setupPrinter( this );
+ preparePreview( true, true );
+ }
+ checkControlDependencies();
+ }
+ return 0;
+}
+
+IMPL_LINK( PrintDialog, ModifyHdl, Edit*, pEdit )
+{
+ checkControlDependencies();
+ if( pEdit == &maNUpPage.maNupRowsEdt || pEdit == &maNUpPage.maNupColEdt ||
+ pEdit == &maNUpPage.maSheetMarginEdt || pEdit == &maNUpPage.maPageMarginEdt
+ )
+ {
+ updateNupFromPages();
+ }
+ else if( pEdit == &maPageEdit )
+ {
+ mnCurPage = sal_Int32( maPageEdit.GetValue() - 1 );
+ preparePreview( true, true );
+ }
+ else if( pEdit == &maJobPage.maCopyCountField )
+ {
+ maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ),
+ makeAny( sal_Int32(maJobPage.maCopyCountField.GetValue()) ) );
+ maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
+ makeAny( sal_Bool(isCollate()) ) );
+ }
+ return 0;
+}
+
+IMPL_LINK( PrintDialog, UIOptionsChanged, void*, EMPTYARG )
+{
+ checkOptionalControlDependencies();
+ return 0;
+}
+
+PropertyValue* PrintDialog::getValueForWindow( Window* i_pWindow ) const
+{
+ PropertyValue* pVal = NULL;
+ std::map< Window*, rtl::OUString >::const_iterator it = maControlToPropertyMap.find( i_pWindow );
+ if( it != maControlToPropertyMap.end() )
+ {
+ pVal = maPController->getValue( it->second );
+ DBG_ASSERT( pVal, "property value not found" );
+ }
+ else
+ {
+ DBG_ERROR( "changed control not in property map" );
+ }
+ return pVal;
+}
+
+void PrintDialog::updateWindowFromProperty( const rtl::OUString& i_rProperty )
+{
+ beans::PropertyValue* pValue = maPController->getValue( i_rProperty );
+ std::map< rtl::OUString, std::vector< Window* > >::const_iterator it = maPropertyToWindowMap.find( i_rProperty );
+ if( pValue && it != maPropertyToWindowMap.end() )
+ {
+ const std::vector< Window* >& rWindows( it->second );
+ if( ! rWindows.empty() )
+ {
+ sal_Bool bVal = sal_False;
+ sal_Int32 nVal = -1;
+ if( pValue->Value >>= bVal )
+ {
+ // we should have a CheckBox for this one
+ CheckBox* pBox = dynamic_cast< CheckBox* >( rWindows.front() );
+ if( pBox )
+ {
+ pBox->Check( bVal );
+ }
+ else if( i_rProperty.equalsAscii( "PrintProspect" ) )
+ {
+ // EVIL special case
+ if( bVal )
+ maNUpPage.maBrochureBtn.Check();
+ else
+ maNUpPage.maPagesBtn.Check();
+ }
+ else
+ {
+ DBG_ASSERT( 0, "missing a checkbox" );
+ }
+ }
+ else if( pValue->Value >>= nVal )
+ {
+ // this could be a ListBox or a RadioButtonGroup
+ ListBox* pList = dynamic_cast< ListBox* >( rWindows.front() );
+ if( pList )
+ {
+ pList->SelectEntryPos( static_cast< USHORT >(nVal) );
+ }
+ else if( nVal >= 0 && nVal < sal_Int32(rWindows.size() ) )
+ {
+ RadioButton* pBtn = dynamic_cast< RadioButton* >( rWindows[nVal] );
+ DBG_ASSERT( pBtn, "unexpected control for property" );
+ if( pBtn )
+ pBtn->Check();
+ }
+ }
+ }
+ }
+}
+
+void PrintDialog::makeEnabled( Window* i_pWindow )
+{
+ std::map< Window*, rtl::OUString >::const_iterator it = maControlToPropertyMap.find( i_pWindow );
+ if( it != maControlToPropertyMap.end() )
+ {
+ rtl::OUString aDependency( maPController->makeEnabled( it->second ) );
+ if( aDependency.getLength() )
+ updateWindowFromProperty( aDependency );
+ }
+}
+
+IMPL_LINK( PrintDialog, UIOption_CheckHdl, CheckBox*, i_pBox )
+{
+ PropertyValue* pVal = getValueForWindow( i_pBox );
+ if( pVal )
+ {
+ makeEnabled( i_pBox );
+
+ sal_Bool bVal = i_pBox->IsChecked();
+ pVal->Value <<= bVal;
+
+ checkOptionalControlDependencies();
+
+ // update preview and page settings
+ preparePreview();
+ }
+ return 0;
+}
+
+IMPL_LINK( PrintDialog, UIOption_RadioHdl, RadioButton*, i_pBtn )
+{
+ // this handler gets called for all radiobuttons that get unchecked, too
+ // however we only want one notificaction for the new value (that is for
+ // the button that gets checked)
+ if( i_pBtn->IsChecked() )
+ {
+ PropertyValue* pVal = getValueForWindow( i_pBtn );
+ std::map< Window*, sal_Int32 >::const_iterator it = maControlToNumValMap.find( i_pBtn );
+ if( pVal && it != maControlToNumValMap.end() )
+ {
+ makeEnabled( i_pBtn );
+
+ sal_Int32 nVal = it->second;
+ pVal->Value <<= nVal;
+
+ checkOptionalControlDependencies();
+
+ // update preview and page settings
+ preparePreview();
+ }
+ }
+ return 0;
+}
+
+IMPL_LINK( PrintDialog, UIOption_SelectHdl, ListBox*, i_pBox )
+{
+ PropertyValue* pVal = getValueForWindow( i_pBox );
+ if( pVal )
+ {
+ makeEnabled( i_pBox );
+
+ sal_Int32 nVal( i_pBox->GetSelectEntryPos() );
+ pVal->Value <<= nVal;
+
+ checkOptionalControlDependencies();
+
+ // update preview and page settings
+ preparePreview();
+ }
+ return 0;
+}
+
+IMPL_LINK( PrintDialog, UIOption_ModifyHdl, Edit*, i_pBox )
+{
+ PropertyValue* pVal = getValueForWindow( i_pBox );
+ if( pVal )
+ {
+ makeEnabled( i_pBox );
+
+ NumericField* pNum = dynamic_cast<NumericField*>(i_pBox);
+ MetricField* pMetric = dynamic_cast<MetricField*>(i_pBox);
+ if( pNum )
+ {
+ sal_Int64 nVal = pNum->GetValue();
+ pVal->Value <<= nVal;
+ }
+ else if( pMetric )
+ {
+ sal_Int64 nVal = pMetric->GetValue();
+ pVal->Value <<= nVal;
+ }
+ else
+ {
+ rtl::OUString aVal( i_pBox->GetText() );
+ pVal->Value <<= aVal;
+ }
+
+ checkOptionalControlDependencies();
+
+ // update preview and page settings
+ preparePreview();
+ }
+ return 0;
+}
+
+void PrintDialog::Command( const CommandEvent& rEvt )
+{
+ if( rEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pWheelData = rEvt.GetWheelData();
+ if( pWheelData->GetDelta() > 0 )
+ previewForward();
+ else if( pWheelData->GetDelta() < 0 )
+ previewBackward();
+ /*
+ else
+ huh ?
+ */
+ }
+}
+
+void PrintDialog::Resize()
+{
+ maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
+ // and do the preview; however the metafile does not need to be gotten anew
+ preparePreview( false );
+
+ // do an invalidate for the benefit of the grouping elements
+ Invalidate();
+}
+
+void PrintDialog::previewForward()
+{
+ maPageEdit.Up();
+}
+
+void PrintDialog::previewBackward()
+{
+ maPageEdit.Down();
+}
+
+// -----------------------------------------------------------------------------
+//
+// PrintProgressDialog
+//
+// -----------------------------------------------------------------------------
+
+PrintProgressDialog::PrintProgressDialog( Window* i_pParent, int i_nMax ) :
+ ModelessDialog( i_pParent, VclResId( SV_DLG_PRINT_PROGRESS ) ),
+ maText( this, VclResId( SV_PRINT_PROGRESS_TEXT ) ),
+ maButton( this, VclResId( SV_PRINT_PROGRESS_CANCEL ) ),
+ mbCanceled( false ),
+ mnCur( 0 ),
+ mnMax( i_nMax ),
+ mnProgressHeight( 15 ),
+ mbNativeProgress( false )
+{
+ FreeResource();
+
+ if( mnMax < 1 )
+ mnMax = 1;
+
+ maStr = maText.GetText();
+
+ maButton.SetClickHdl( LINK( this, PrintProgressDialog, ClickHdl ) );
+
+}
+
+PrintProgressDialog::~PrintProgressDialog()
+{
+}
+
+IMPL_LINK( PrintProgressDialog, ClickHdl, Button*, pButton )
+{
+ if( pButton == &maButton )
+ mbCanceled = true;
+
+ return 0;
+}
+
+void PrintProgressDialog::implCalcProgressRect()
+{
+ if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
+ {
+ ImplControlValue aValue;
+ Rectangle aControlRegion( Point(), Size( 100, mnProgressHeight ) );
+ Rectangle aNativeControlRegion, aNativeContentRegion;
+ if( GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
+ CTRL_STATE_ENABLED, aValue, rtl::OUString(),
+ aNativeControlRegion, aNativeContentRegion ) )
+ {
+ mnProgressHeight = aNativeControlRegion.GetHeight();
+ }
+ mbNativeProgress = true;
+ }
+ maProgressRect = Rectangle( Point( 10, maText.GetPosPixel().Y() + maText.GetSizePixel().Height() + 8 ),
+ Size( GetSizePixel().Width() - 20, mnProgressHeight ) );
+}
+
+void PrintProgressDialog::setProgress( int i_nCurrent, int i_nMax )
+{
+ if( maProgressRect.IsEmpty() )
+ implCalcProgressRect();
+
+ mnCur = i_nCurrent;
+ if( i_nMax != -1 )
+ mnMax = i_nMax;
+
+ if( mnMax < 1 )
+ mnMax = 1;
+
+ rtl::OUString aNewText( searchAndReplace( maStr, "%p", 2, rtl::OUString::valueOf( mnCur ) ) );
+ aNewText = searchAndReplace( aNewText, "%n", 2, rtl::OUString::valueOf( mnMax ) );
+ maText.SetText( aNewText );
+
+ // update progress
+ Invalidate( maProgressRect, INVALIDATE_UPDATE );
+}
+
+void PrintProgressDialog::tick()
+{
+ if( mnCur < mnMax )
+ setProgress( ++mnCur );
+}
+
+void PrintProgressDialog::reset()
+{
+ setProgress( 0 );
+}
+
+void PrintProgressDialog::Paint( const Rectangle& )
+{
+ if( maProgressRect.IsEmpty() )
+ implCalcProgressRect();
+
+ Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Color aPrgsColor = rStyleSettings.GetHighlightColor();
+ if ( aPrgsColor == rStyleSettings.GetFaceColor() )
+ aPrgsColor = rStyleSettings.GetDarkShadowColor();
+ SetLineColor();
+ SetFillColor( aPrgsColor );
+
+ const long nOffset = 3;
+ const long nWidth = 3*mnProgressHeight/2;
+ const long nFullWidth = nWidth + nOffset;
+ const long nMaxCount = maProgressRect.GetWidth() / nFullWidth;
+ DrawProgress( this, maProgressRect.TopLeft(),
+ nOffset,
+ nWidth,
+ mnProgressHeight,
+ static_cast<USHORT>(0),
+ static_cast<USHORT>(10000*mnCur/mnMax),
+ static_cast<USHORT>(10000/nMaxCount),
+ maProgressRect
+ );
+ Pop();
+
+ if( ! mbNativeProgress )
+ {
+ DecorationView aDecoView( this );
+ Rectangle aFrameRect( maProgressRect );
+ aFrameRect.Left() -= nOffset;
+ aFrameRect.Right() += nOffset;
+ aFrameRect.Top() -= nOffset;
+ aFrameRect.Bottom() += nOffset;
+ aDecoView.DrawFrame( aFrameRect );
+ }
+}
+
diff --git a/vcl/source/window/scrwnd.cxx b/vcl/source/window/scrwnd.cxx
new file mode 100644
index 000000000000..735add842518
--- /dev/null
+++ b/vcl/source/window/scrwnd.cxx
@@ -0,0 +1,420 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+// #include <math.h>
+#include <limits.h>
+#include <tools/time.hxx>
+#include <tools/debug.hxx>
+
+#ifndef _SV_SVIDS_HRC
+#include <vcl/svids.hrc>
+#endif
+#include <vcl/svdata.hxx>
+#ifndef _VCL_TIMER_HXX
+#include <vcl/timer.hxx>
+#endif
+#ifndef _VCL_EVENT_HXX
+#include <vcl/event.hxx>
+#endif
+#ifndef _VCL_SCRWND_HXX
+#include <scrwnd.hxx>
+#endif
+
+#include <math.h>
+#include <limits.h>
+
+// -----------
+// - Defines -
+// -----------
+
+#define WHEEL_WIDTH 25
+#define WHEEL_RADIUS ((WHEEL_WIDTH) >> 1 )
+#define MAX_TIME 300
+#define MIN_TIME 20
+#define DEF_TIMEOUT 50
+
+// -------------------
+// - ImplWheelWindow -
+// -------------------
+
+ImplWheelWindow::ImplWheelWindow( Window* pParent ) :
+ FloatingWindow ( pParent, 0 ),
+ mnRepaintTime ( 1UL ),
+ mnTimeout ( DEF_TIMEOUT ),
+ mnWheelMode ( WHEELMODE_NONE ),
+ mnActDist ( 0UL ),
+ mnActDeltaX ( 0L ),
+ mnActDeltaY ( 0L )
+{
+ // we need a parent
+ DBG_ASSERT( pParent, "ImplWheelWindow::ImplWheelWindow(): Parent not set!" );
+
+ const Size aSize( pParent->GetOutputSizePixel() );
+ const USHORT nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
+ const BOOL bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
+ const BOOL bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
+
+ // calculate maximum speed distance
+ mnMaxWidth = (ULONG) ( 0.4 * hypot( (double) aSize.Width(), aSize.Height() ) );
+
+ // create wheel window
+ SetTitleType( FLOATWIN_TITLE_NONE );
+ ImplCreateImageList();
+ ResMgr* pResMgr = ImplGetResMgr();
+ Bitmap aBmp;
+ if( pResMgr )
+ aBmp = Bitmap( ResId( SV_RESID_BITMAP_SCROLLMSK, *pResMgr ) );
+ ImplSetRegion( aBmp );
+
+ // set wheel mode
+ if( bHorz && bVert )
+ ImplSetWheelMode( WHEELMODE_VH );
+ else if( bHorz )
+ ImplSetWheelMode( WHEELMODE_H );
+ else
+ ImplSetWheelMode( WHEELMODE_V );
+
+ // init timer
+ mpTimer = new Timer;
+ mpTimer->SetTimeoutHdl( LINK( this, ImplWheelWindow, ImplScrollHdl ) );
+ mpTimer->SetTimeout( mnTimeout );
+ mpTimer->Start();
+
+ CaptureMouse();
+}
+
+// ------------------------------------------------------------------------
+
+ImplWheelWindow::~ImplWheelWindow()
+{
+ ImplStop();
+ delete mpTimer;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplStop()
+{
+ ReleaseMouse();
+ mpTimer->Stop();
+ Show(FALSE);
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplSetRegion( const Bitmap& rRegionBmp )
+{
+ Point aPos( GetPointerPosPixel() );
+ const Size aSize( rRegionBmp.GetSizePixel() );
+ Point aPoint;
+ const Rectangle aRect( aPoint, aSize );
+
+ maCenter = maLastMousePos = aPos;
+ aPos.X() -= aSize.Width() >> 1;
+ aPos.Y() -= aSize.Height() >> 1;
+
+ SetPosSizePixel( aPos, aSize );
+ SetWindowRegionPixel( rRegionBmp.CreateRegion( COL_BLACK, aRect ) );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplCreateImageList()
+{
+ ResMgr* pResMgr = ImplGetResMgr();
+ if( pResMgr )
+ maImgList.InsertFromHorizontalBitmap
+ ( ResId( SV_RESID_BITMAP_SCROLLBMP, *pResMgr ), 6, NULL );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplSetWheelMode( ULONG nWheelMode )
+{
+ if( nWheelMode != mnWheelMode )
+ {
+ mnWheelMode = nWheelMode;
+
+ if( WHEELMODE_NONE == mnWheelMode )
+ {
+ if( IsVisible() )
+ Hide();
+ }
+ else
+ {
+ if( !IsVisible() )
+ Show();
+
+ ImplDrawWheel();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplDrawWheel()
+{
+ USHORT nId;
+
+ switch( mnWheelMode )
+ {
+ case( WHEELMODE_VH ): nId = 1; break;
+ case( WHEELMODE_V ): nId = 2; break;
+ case( WHEELMODE_H ): nId = 3; break;
+ case( WHEELMODE_SCROLL_VH ):nId = 4; break;
+ case( WHEELMODE_SCROLL_V ): nId = 5; break;
+ case( WHEELMODE_SCROLL_H ): nId = 6; break;
+ default: nId = 0; break;
+ }
+
+ if( nId )
+ DrawImage( Point(), maImgList.GetImage( nId ) );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplRecalcScrollValues()
+{
+ if( mnActDist < WHEEL_RADIUS )
+ {
+ mnActDeltaX = mnActDeltaY = 0L;
+ mnTimeout = DEF_TIMEOUT;
+ }
+ else
+ {
+ ULONG nCurTime;
+
+ // calc current time
+ if( mnMaxWidth )
+ {
+ const double fExp = ( (double) mnActDist / mnMaxWidth ) * log10( (double) MAX_TIME / MIN_TIME );
+ nCurTime = (ULONG) ( MAX_TIME / pow( 10., fExp ) );
+ }
+ else
+ nCurTime = MAX_TIME;
+
+ if( !nCurTime )
+ nCurTime = 1UL;
+
+ if( mnRepaintTime <= nCurTime )
+ mnTimeout = nCurTime - mnRepaintTime;
+ else
+ {
+ long nMult = mnRepaintTime / nCurTime;
+
+ if( !( mnRepaintTime % nCurTime ) )
+ mnTimeout = 0UL;
+ else
+ mnTimeout = ++nMult * nCurTime - mnRepaintTime;
+
+ double fValX = (double) mnActDeltaX * nMult;
+ double fValY = (double) mnActDeltaY * nMult;
+
+ if( fValX > LONG_MAX )
+ mnActDeltaX = LONG_MAX;
+ else if( fValX < LONG_MIN )
+ mnActDeltaX = LONG_MIN;
+ else
+ mnActDeltaX = (long) fValX;
+
+ if( fValY > LONG_MAX )
+ mnActDeltaY = LONG_MAX;
+ else if( fValY < LONG_MIN )
+ mnActDeltaY = LONG_MIN;
+ else
+ mnActDeltaY = (long) fValY;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+PointerStyle ImplWheelWindow::ImplGetMousePointer( long nDistX, long nDistY )
+{
+ PointerStyle eStyle;
+ const USHORT nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
+ const BOOL bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
+ const BOOL bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
+
+ if( bHorz || bVert )
+ {
+ if( mnActDist < WHEEL_RADIUS )
+ {
+ if( bHorz && bVert )
+ eStyle = POINTER_AUTOSCROLL_NSWE;
+ else if( bHorz )
+ eStyle = POINTER_AUTOSCROLL_WE;
+ else
+ eStyle = POINTER_AUTOSCROLL_NS;
+ }
+ else
+ {
+ double fAngle = atan2( (double) -nDistY, nDistX ) / F_PI180;
+
+ if( fAngle < 0.0 )
+ fAngle += 360.;
+
+ if( bHorz && bVert )
+ {
+ if( fAngle >= 22.5 && fAngle <= 67.5 )
+ eStyle = POINTER_AUTOSCROLL_NE;
+ else if( fAngle >= 67.5 && fAngle <= 112.5 )
+ eStyle = POINTER_AUTOSCROLL_N;
+ else if( fAngle >= 112.5 && fAngle <= 157.5 )
+ eStyle = POINTER_AUTOSCROLL_NW;
+ else if( fAngle >= 157.5 && fAngle <= 202.5 )
+ eStyle = POINTER_AUTOSCROLL_W;
+ else if( fAngle >= 202.5 && fAngle <= 247.5 )
+ eStyle = POINTER_AUTOSCROLL_SW;
+ else if( fAngle >= 247.5 && fAngle <= 292.5 )
+ eStyle = POINTER_AUTOSCROLL_S;
+ else if( fAngle >= 292.5 && fAngle <= 337.5 )
+ eStyle = POINTER_AUTOSCROLL_SE;
+ else
+ eStyle = POINTER_AUTOSCROLL_E;
+ }
+ else if( bHorz )
+ {
+ if( fAngle >= 270. || fAngle <= 90. )
+ eStyle = POINTER_AUTOSCROLL_E;
+ else
+ eStyle = POINTER_AUTOSCROLL_W;
+ }
+ else
+ {
+ if( fAngle >= 0. && fAngle <= 180. )
+ eStyle = POINTER_AUTOSCROLL_N;
+ else
+ eStyle = POINTER_AUTOSCROLL_S;
+ }
+ }
+ }
+ else
+ eStyle = POINTER_ARROW;
+
+ return eStyle;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::Paint( const Rectangle& )
+{
+ ImplDrawWheel();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ FloatingWindow::MouseMove( rMEvt );
+
+ const Point aMousePos( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
+ const long nDistX = aMousePos.X() - maCenter.X();
+ const long nDistY = aMousePos.Y() - maCenter.Y();
+
+ mnActDist = (ULONG) hypot( (double) nDistX, nDistY );
+
+ const PointerStyle eActStyle = ImplGetMousePointer( nDistX, nDistY );
+ const USHORT nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
+ const BOOL bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
+ const BOOL bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
+ const BOOL bOuter = mnActDist > WHEEL_RADIUS;
+
+ if( bOuter && ( maLastMousePos != aMousePos ) )
+ {
+ switch( eActStyle )
+ {
+ case( POINTER_AUTOSCROLL_N ): mnActDeltaX = +0L, mnActDeltaY = +1L; break;
+ case( POINTER_AUTOSCROLL_S ): mnActDeltaX = +0L, mnActDeltaY = -1L; break;
+ case( POINTER_AUTOSCROLL_W ): mnActDeltaX = +1L, mnActDeltaY = +0L; break;
+ case( POINTER_AUTOSCROLL_E ): mnActDeltaX = -1L, mnActDeltaY = +0L; break;
+ case( POINTER_AUTOSCROLL_NW ): mnActDeltaX = +1L, mnActDeltaY = +1L; break;
+ case( POINTER_AUTOSCROLL_NE ): mnActDeltaX = -1L, mnActDeltaY = +1L; break;
+ case( POINTER_AUTOSCROLL_SW ): mnActDeltaX = +1L, mnActDeltaY = -1L; break;
+ case( POINTER_AUTOSCROLL_SE ): mnActDeltaX = -1L, mnActDeltaY = -1L; break;
+
+ default:
+ break;
+ }
+ }
+
+ ImplRecalcScrollValues();
+ maLastMousePos = aMousePos;
+ SetPointer( eActStyle );
+
+ if( bHorz && bVert )
+ ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_VH : WHEELMODE_VH );
+ else if( bHorz )
+ ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_H : WHEELMODE_H );
+ else
+ ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_V : WHEELMODE_V );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if( mnActDist > WHEEL_RADIUS )
+ GetParent()->EndAutoScroll();
+ else
+ FloatingWindow::MouseButtonUp( rMEvt );
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK( ImplWheelWindow, ImplScrollHdl, Timer*, EMPTYARG )
+{
+ if ( mnActDeltaX || mnActDeltaY )
+ {
+ Window* pWindow = GetParent();
+ const Point aMousePos( pWindow->OutputToScreenPixel( pWindow->GetPointerPosPixel() ) );
+ Point aCmdMousePos( pWindow->ImplFrameToOutput( aMousePos ) );
+ CommandScrollData aScrollData( mnActDeltaX, mnActDeltaY );
+ CommandEvent aCEvt( aCmdMousePos, COMMAND_AUTOSCROLL, TRUE, &aScrollData );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
+
+ if ( !ImplCallPreNotify( aNCmdEvt ) )
+ {
+ const ULONG nTime = Time::GetSystemTicks();
+ ImplDelData aDel( this );
+ pWindow->Command( aCEvt );
+ if( aDel.IsDead() )
+ return 0;
+ mnRepaintTime = Max( Time::GetSystemTicks() - nTime, 1UL );
+ ImplRecalcScrollValues();
+ }
+ }
+
+ if ( mnTimeout != mpTimer->GetTimeout() )
+ mpTimer->SetTimeout( mnTimeout );
+ mpTimer->Start();
+
+ return 0L;
+}
diff --git a/vcl/source/window/scrwnd.hxx b/vcl/source/window/scrwnd.hxx
new file mode 100644
index 000000000000..d808fa73e321
--- /dev/null
+++ b/vcl/source/window/scrwnd.hxx
@@ -0,0 +1,92 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include <vcl/floatwin.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/image.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define WHEELMODE_NONE 0x00000000UL
+#define WHEELMODE_VH 0x00000001UL
+#define WHEELMODE_V 0x00000002UL
+#define WHEELMODE_H 0x00000004UL
+#define WHEELMODE_SCROLL_VH 0x00000008UL
+#define WHEELMODE_SCROLL_V 0x00000010UL
+#define WHEELMODE_SCROLL_H 0x00000020UL
+
+// -------------------
+// - ImplWheelWindow -
+// -------------------
+
+class Timer;
+
+class ImplWheelWindow : public FloatingWindow
+{
+private:
+
+ ImageList maImgList;
+ Bitmap maWheelBmp;
+ CommandScrollData maCommandScrollData;
+ Point maLastMousePos;
+ Point maCenter;
+ Timer* mpTimer;
+ ULONG mnRepaintTime;
+ ULONG mnTimeout;
+ ULONG mnWheelMode;
+ ULONG mnMaxWidth;
+ ULONG mnActWidth;
+ ULONG mnActDist;
+ long mnActDeltaX;
+ long mnActDeltaY;
+
+ void ImplCreateImageList();
+ void ImplSetRegion( const Bitmap& rRegionBmp );
+ using Window::ImplGetMousePointer;
+ PointerStyle ImplGetMousePointer( long nDistX, long nDistY );
+ void ImplDrawWheel();
+ void ImplRecalcScrollValues();
+
+ DECL_LINK( ImplScrollHdl, Timer* pTimer );
+
+protected:
+
+ virtual void Paint( const Rectangle& rRect );
+ virtual void MouseMove( const MouseEvent& rMEvt );
+ virtual void MouseButtonUp( const MouseEvent& rMEvt );
+
+public:
+
+ ImplWheelWindow( Window* pParent );
+ ~ImplWheelWindow();
+
+ void ImplStop();
+ void ImplSetWheelMode( ULONG nWheelMode );
+ ULONG ImplGetWheelMode() const { return mnWheelMode; }
+};
diff --git a/vcl/source/window/seleng.cxx b/vcl/source/window/seleng.cxx
new file mode 100644
index 000000000000..322b2937b5c9
--- /dev/null
+++ b/vcl/source/window/seleng.cxx
@@ -0,0 +1,502 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <tools/ref.hxx>
+#include <vcl/window.hxx>
+#include <vcl/seleng.hxx>
+#include <tools/debug.hxx>
+
+
+
+
+inline BOOL SelectionEngine::ShouldDeselect( BOOL bModifierKey1 ) const
+{
+// return !( eSelMode == MULTIPLE_SELECTION && bModifierKey1 );
+ return eSelMode != MULTIPLE_SELECTION || !bModifierKey1;
+}
+
+
+// TODO: FunctionSet::SelectAtPoint raus
+
+/*************************************************************************
+|*
+|* SelectionEngine::SelectionEngine()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+SelectionEngine::SelectionEngine( Window* pWindow, FunctionSet* pFuncSet ) :
+ pWin( pWindow )
+{
+ eSelMode = SINGLE_SELECTION;
+ pFunctionSet = pFuncSet;
+ nFlags = SELENG_EXPANDONMOVE;
+ nLockedMods = 0;
+
+ aWTimer.SetTimeoutHdl( LINK( this, SelectionEngine, ImpWatchDog ) );
+ aWTimer.SetTimeout( SELENG_AUTOREPEAT_INTERVAL );
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::~SelectionEngine()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+SelectionEngine::~SelectionEngine()
+{
+ aWTimer.Stop();
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::ImpWatchDog()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+IMPL_LINK( SelectionEngine, ImpWatchDog, Timer*, EMPTYARG )
+{
+ if ( !aArea.IsInside( aLastMove.GetPosPixel() ) )
+ SelMouseMove( aLastMove );
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SetSelectionMode()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+void SelectionEngine::SetSelectionMode( SelectionMode eMode )
+{
+ eSelMode = eMode;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::ActivateDragMode()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+void SelectionEngine::ActivateDragMode()
+{
+ DBG_ERRORFILE( "SelectionEngine::ActivateDragMode not implemented" );
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::CursorPosChanging()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung GT 2002-04-04
+|*
+*************************************************************************/
+
+void SelectionEngine::CursorPosChanging( BOOL bShift, BOOL bMod1 )
+{
+ if ( !pFunctionSet )
+ return;
+
+ if ( bShift && eSelMode != SINGLE_SELECTION )
+ {
+ if ( IsAddMode() )
+ {
+ if ( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ pFunctionSet->CreateAnchor();
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ }
+ else
+ {
+ if ( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ if( ShouldDeselect( bMod1 ) )
+ pFunctionSet->DeselectAll();
+ pFunctionSet->CreateAnchor();
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ }
+ }
+ else
+ {
+ if ( IsAddMode() )
+ {
+ if ( nFlags & SELENG_HAS_ANCH )
+ {
+ // pFunctionSet->CreateCursor();
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH);
+ }
+ }
+ else
+ {
+ if( ShouldDeselect( bMod1 ) )
+ pFunctionSet->DeselectAll();
+ else
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH);
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SelMouseButtonDown()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 07.06.95
+|*
+*************************************************************************/
+
+BOOL SelectionEngine::SelMouseButtonDown( const MouseEvent& rMEvt )
+{
+ nFlags &= (~SELENG_CMDEVT);
+ if ( !pFunctionSet || !pWin )
+ return FALSE;
+ const bool bRightClickCursorPositioning =
+ rMEvt.IsRight() && rMEvt.GetClicks() == 1 && !IsInSelection();
+ if ( (rMEvt.GetClicks() > 1 || rMEvt.IsRight()) && !bRightClickCursorPositioning )
+ return FALSE;
+
+ USHORT nModifier = rMEvt.GetModifier() | nLockedMods;
+ if ( nModifier & KEY_MOD2 )
+ return FALSE;
+ // in SingleSelection: Control-Taste filtern (damit auch
+ // mit Ctrl-Click ein D&D gestartet werden kann)
+ if ( nModifier == KEY_MOD1 && eSelMode == SINGLE_SELECTION )
+ nModifier = 0;
+
+ Point aPos = rMEvt.GetPosPixel();
+ aLastMove = rMEvt;
+
+ if( !rMEvt.IsRight() )
+ {
+ pWin->CaptureMouse();
+ nFlags |= SELENG_IN_SEL;
+ }
+ else
+ {
+ nModifier = 0;
+ }
+
+ switch ( nModifier )
+ {
+ case 0: // KEY_NO_KEY
+ {
+ BOOL bSelAtPoint = pFunctionSet->IsSelectionAtPoint( aPos );
+ nFlags &= (~SELENG_IN_ADD);
+ if ( (nFlags & SELENG_DRG_ENAB) && bSelAtPoint )
+ {
+ nFlags |= SELENG_WAIT_UPEVT;
+ nFlags &= ~(SELENG_IN_SEL);
+ pWin->ReleaseMouse();
+ return TRUE; //auf STARTDRAG-Command-Event warten
+ }
+ if ( eSelMode != SINGLE_SELECTION )
+ {
+ if( !IsAddMode() )
+ pFunctionSet->DeselectAll();
+ else
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH); // bHasAnchor = FALSE;
+ }
+ pFunctionSet->SetCursorAtPoint( aPos );
+ // Sonderbehandlung Single-Selection, damit Select+Drag
+ // in einem Zug moeglich ist
+ if (eSelMode == SINGLE_SELECTION && (nFlags & SELENG_DRG_ENAB))
+ nFlags |= SELENG_WAIT_UPEVT;
+ return TRUE;
+ }
+
+ case KEY_SHIFT:
+ if ( eSelMode == SINGLE_SELECTION )
+ {
+ pWin->ReleaseMouse();
+ nFlags &= (~SELENG_IN_SEL);
+ return FALSE;
+ }
+ if ( nFlags & SELENG_ADD_ALW )
+ nFlags |= SELENG_IN_ADD;
+ else
+ nFlags &= (~SELENG_IN_ADD);
+
+ if( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ if ( !(nFlags & SELENG_IN_ADD) )
+ pFunctionSet->DeselectAll();
+ pFunctionSet->CreateAnchor();
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ pFunctionSet->SetCursorAtPoint( aPos );
+ return TRUE;
+
+ case KEY_MOD1:
+ // Control nur bei Mehrfachselektion erlaubt
+ if ( eSelMode != MULTIPLE_SELECTION )
+ {
+ nFlags &= (~SELENG_IN_SEL);
+ pWin->ReleaseMouse();
+ return TRUE; // Mausclick verschlucken
+ }
+ if ( nFlags & SELENG_HAS_ANCH )
+ {
+ // pFunctionSet->CreateCursor();
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH);
+ }
+ if ( pFunctionSet->IsSelectionAtPoint( aPos ) )
+ {
+ pFunctionSet->DeselectAtPoint( aPos );
+ pFunctionSet->SetCursorAtPoint( aPos, TRUE );
+ }
+ else
+ {
+ pFunctionSet->SetCursorAtPoint( aPos );
+ }
+ return TRUE;
+
+ case KEY_SHIFT + KEY_MOD1:
+ if ( eSelMode != MULTIPLE_SELECTION )
+ {
+ pWin->ReleaseMouse();
+ nFlags &= (~SELENG_IN_SEL);
+ return FALSE;
+ }
+ nFlags |= SELENG_IN_ADD; //bIsInAddMode = TRUE;
+ if ( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ pFunctionSet->CreateAnchor();
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ pFunctionSet->SetCursorAtPoint( aPos );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SelMouseButtonUp()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+BOOL SelectionEngine::SelMouseButtonUp( const MouseEvent& rMEvt )
+{
+ aWTimer.Stop();
+ //DbgOut("Up");
+ if( !pFunctionSet || !pWin )
+ {
+ nFlags &= ~(SELENG_CMDEVT | SELENG_WAIT_UPEVT | SELENG_IN_SEL);
+ return FALSE;
+ }
+
+ if( !rMEvt.IsRight() )
+ {
+ pWin->ReleaseMouse();
+ }
+
+ if( (nFlags & SELENG_WAIT_UPEVT) && !(nFlags & SELENG_CMDEVT) &&
+ eSelMode != SINGLE_SELECTION)
+ {
+ // MouseButtonDown in Sel aber kein CommandEvent eingetrudelt
+ // ==> deselektieren
+ USHORT nModifier = aLastMove.GetModifier() | nLockedMods;
+ if( nModifier == KEY_MOD1 || IsAlwaysAdding() )
+ {
+ if( !(nModifier & KEY_SHIFT) )
+ {
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH); // nix Anker
+ }
+ pFunctionSet->DeselectAtPoint( aLastMove.GetPosPixel() );
+ nFlags &= (~SELENG_HAS_ANCH); // nix Anker
+ pFunctionSet->SetCursorAtPoint( aLastMove.GetPosPixel(), TRUE );
+ }
+ else
+ {
+ pFunctionSet->DeselectAll();
+ nFlags &= (~SELENG_HAS_ANCH); // nix Anker
+ pFunctionSet->SetCursorAtPoint( aLastMove.GetPosPixel() );
+ }
+ }
+
+ nFlags &= ~(SELENG_CMDEVT | SELENG_WAIT_UPEVT | SELENG_IN_SEL);
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SelMouseMove()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+BOOL SelectionEngine::SelMouseMove( const MouseEvent& rMEvt )
+{
+
+ if ( !pFunctionSet || !(nFlags & SELENG_IN_SEL) ||
+ (nFlags & (SELENG_CMDEVT | SELENG_WAIT_UPEVT)) )
+ return FALSE;
+
+ if( !(nFlags & SELENG_EXPANDONMOVE) )
+ return FALSE; // auf DragEvent warten!
+
+ aLastMove = rMEvt;
+ // wenn die Maus ausserhalb der Area steht, dann wird die
+ // Frequenz des SetCursorAtPoint() nur durch den Timer bestimmt
+ if( aWTimer.IsActive() && !aArea.IsInside( rMEvt.GetPosPixel() ))
+ return TRUE;
+
+
+ aWTimer.Start();
+ if ( eSelMode != SINGLE_SELECTION )
+ {
+ if ( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ pFunctionSet->CreateAnchor();
+ //DbgOut("Move:Creating anchor");
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ }
+
+ //DbgOut("Move:SetCursor");
+ pFunctionSet->SetCursorAtPoint( rMEvt.GetPosPixel() );
+
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SetWindow()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+void SelectionEngine::SetWindow( Window* pNewWin )
+{
+ if( pNewWin != pWin )
+ {
+ if ( pWin && (nFlags & SELENG_IN_SEL) )
+ pWin->ReleaseMouse();
+ pWin = pNewWin;
+ if ( pWin && ( nFlags & SELENG_IN_SEL ) )
+ pWin->CaptureMouse();
+ }
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::Reset()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 07.07.95
+|* Letzte Aenderung OV 07.07.95
+|*
+*************************************************************************/
+
+void SelectionEngine::Reset()
+{
+ aWTimer.Stop();
+ if ( nFlags & SELENG_IN_SEL )
+ pWin->ReleaseMouse();
+ nFlags &= ~(SELENG_HAS_ANCH | SELENG_IN_SEL);
+ nLockedMods = 0;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::Command()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 07.07.95
+|* Letzte Aenderung OV 07.07.95
+|*
+*************************************************************************/
+
+void SelectionEngine::Command( const CommandEvent& rCEvt )
+{
+ // Timer aWTimer ist beim Aufspannen einer Selektion aktiv
+ if ( !pFunctionSet || !pWin || aWTimer.IsActive() )
+ return;
+ aWTimer.Stop();
+ nFlags |= SELENG_CMDEVT;
+ if ( rCEvt.GetCommand() == COMMAND_STARTDRAG )
+ {
+ if ( nFlags & SELENG_DRG_ENAB )
+ {
+ DBG_ASSERT( rCEvt.IsMouseEvent(), "STARTDRAG: Not a MouseEvent" );
+ if ( pFunctionSet->IsSelectionAtPoint( rCEvt.GetMousePosPixel() ) )
+ {
+ aLastMove = MouseEvent( rCEvt.GetMousePosPixel(),
+ aLastMove.GetClicks(), aLastMove.GetMode(),
+ aLastMove.GetButtons(), aLastMove.GetModifier() );
+ pFunctionSet->BeginDrag();
+ nFlags &= ~(SELENG_CMDEVT|SELENG_WAIT_UPEVT|SELENG_IN_SEL);
+ }
+ else
+ nFlags &= ~SELENG_CMDEVT;
+ }
+ else
+ nFlags &= ~SELENG_CMDEVT;
+ }
+}
diff --git a/vcl/source/window/split.cxx b/vcl/source/window/split.cxx
new file mode 100644
index 000000000000..b4553a4cf8a7
--- /dev/null
+++ b/vcl/source/window/split.cxx
@@ -0,0 +1,806 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/event.hxx>
+#include <vcl/split.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/taskpanelist.hxx>
+#include <vcl/gradient.hxx>
+#include <tools/poly.hxx>
+#include <vcl/lineinfo.hxx>
+#include <rtl/instance.hxx>
+#include <vcl/window.h>
+
+namespace
+{
+ struct ImplBlackWall
+ : public rtl::StaticWithInit<Wallpaper, ImplBlackWall> {
+ Wallpaper operator () () {
+ return Wallpaper(COL_BLACK);
+ }
+ };
+ struct ImplWhiteWall
+ : public rtl::StaticWithInit<Wallpaper, ImplWhiteWall> {
+ Wallpaper operator () () {
+ return Wallpaper(COL_LIGHTGRAY);
+ }
+ };
+}
+
+// =======================================================================
+
+void Splitter::ImplInitSplitterData()
+{
+ ImplGetWindowImpl()->mbSplitter = TRUE;
+ mpRefWin = NULL;
+ mnSplitPos = 0;
+ mnLastSplitPos = 0;
+ mnStartSplitPos = 0;
+ mbDragFull = FALSE;
+ mbKbdSplitting = FALSE;
+ mbInKeyEvent = 0;
+ mnKeyboardStepSize = SPLITTER_DEFAULTSTEPSIZE;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplInit( Window* pParent, WinBits nWinStyle )
+{
+ Window::ImplInit( pParent, nWinStyle, NULL );
+
+ mpRefWin = pParent;
+
+ const StyleSettings& rSettings = GetSettings().GetStyleSettings();
+ long nA = rSettings.GetScrollBarSize();
+ long nB = rSettings.GetSplitSize();
+
+ PointerStyle ePointerStyle;
+
+ if ( nWinStyle & WB_HSCROLL )
+ {
+ ePointerStyle = POINTER_HSPLIT;
+ mbHorzSplit = TRUE;
+ SetSizePixel( Size( nB, nA ) );
+ }
+ else
+ {
+ ePointerStyle = POINTER_VSPLIT;
+ mbHorzSplit = FALSE;
+ SetSizePixel( Size( nA, nB ) );
+ }
+
+ SetPointer( Pointer( ePointerStyle ) );
+
+ if( GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
+ SetBackground( ImplWhiteWall::get() );
+ else
+ SetBackground( ImplBlackWall::get() );
+
+ TaskPaneList *pTList = GetSystemWindow()->GetTaskPaneList();
+ pTList->AddWindow( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplSplitMousePos( Point& rPos )
+{
+ if ( mbHorzSplit )
+ {
+ if ( rPos.X() > maDragRect.Right()-1 )
+ rPos.X() = maDragRect.Right()-1;
+ if ( rPos.X() < maDragRect.Left()+1 )
+ rPos.X() = maDragRect.Left()+1;
+ }
+ else
+ {
+ if ( rPos.Y() > maDragRect.Bottom()-1 )
+ rPos.Y() = maDragRect.Bottom()-1;
+ if ( rPos.Y() < maDragRect.Top()+1 )
+ rPos.Y() = maDragRect.Top()+1;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplDrawSplitter()
+{
+ Rectangle aInvRect( maDragRect );
+
+ if ( mbHorzSplit )
+ {
+ aInvRect.Left() = maDragPos.X() - 1;
+ aInvRect.Right() = maDragPos.X() + 1;
+ }
+ else
+ {
+ aInvRect.Top() = maDragPos.Y() - 1;
+ aInvRect.Bottom() = maDragPos.Y() + 1;
+ }
+
+ mpRefWin->InvertTracking( mpRefWin->PixelToLogic(aInvRect), SHOWTRACK_SPLIT );
+}
+
+// -----------------------------------------------------------------------
+
+Splitter::Splitter( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_SPLITTER )
+{
+ ImplInitSplitterData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Splitter::Splitter( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_SPLITTER )
+{
+ ImplInitSplitterData();
+ rResId.SetRT( RSC_SPLITTER );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+Splitter::~Splitter()
+{
+ TaskPaneList *pTList = GetSystemWindow()->GetTaskPaneList();
+ pTList->RemoveWindow( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::SetKeyboardStepSize( long nStepSize )
+{
+ mnKeyboardStepSize = nStepSize;
+}
+
+// -----------------------------------------------------------------------
+
+long Splitter::GetKeyboardStepSize() const
+{
+ return mnKeyboardStepSize;
+}
+
+// -----------------------------------------------------------------------
+
+Splitter* Splitter::ImplFindSibling()
+{
+ // look for another splitter with the same parent but different orientation
+ Window *pWin = GetParent()->GetWindow( WINDOW_FIRSTCHILD );
+ Splitter *pSplitter = NULL;
+ while( pWin )
+ {
+ if( pWin->ImplIsSplitter() )
+ {
+ pSplitter = (Splitter*) pWin;
+ if( pSplitter != this && IsHorizontal() != pSplitter->IsHorizontal() )
+ return pSplitter;
+ }
+ pWin = pWin->GetWindow( WINDOW_NEXT );
+ }
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Splitter::ImplSplitterActive()
+{
+ // is splitter in document or at scrollbar handle ?
+
+ BOOL bActive = TRUE;
+ const StyleSettings& rSettings = GetSettings().GetStyleSettings();
+ long nA = rSettings.GetScrollBarSize();
+ long nB = rSettings.GetSplitSize();
+
+ Size aSize = GetOutputSize();
+ if ( mbHorzSplit )
+ {
+ if( aSize.Width() == nB && aSize.Height() == nA )
+ bActive = FALSE;
+ }
+ else
+ {
+ if( aSize.Width() == nA && aSize.Height() == nB )
+ bActive = FALSE;
+ }
+ return bActive;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.GetClicks() == 2 )
+ {
+ if ( mnLastSplitPos != mnSplitPos )
+ {
+ StartSplit();
+ Point aPos = rMEvt.GetPosPixel();
+ if ( mbHorzSplit )
+ aPos.X() = mnLastSplitPos;
+ else
+ aPos.Y() = mnLastSplitPos;
+ ImplSplitMousePos( aPos );
+ Splitting( aPos );
+ ImplSplitMousePos( aPos );
+ long nTemp = mnSplitPos;
+ if ( mbHorzSplit )
+ SetSplitPosPixel( aPos.X() );
+ else
+ SetSplitPosPixel( aPos.Y() );
+ mnLastSplitPos = nTemp;
+ Split();
+ EndSplit();
+ }
+ }
+ else
+ StartDrag();
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( !mbDragFull )
+ ImplDrawSplitter();
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ long nNewPos;
+ if ( mbHorzSplit )
+ nNewPos = maDragPos.X();
+ else
+ nNewPos = maDragPos.Y();
+ if ( nNewPos != mnStartSplitPos )
+ {
+ SetSplitPosPixel( nNewPos );
+ mnLastSplitPos = 0;
+ Split();
+ }
+ EndSplit();
+ }
+ else if ( mbDragFull )
+ {
+ SetSplitPosPixel( mnStartSplitPos );
+ Split();
+ }
+ mnStartSplitPos = 0;
+ }
+ else
+ {
+ //Point aNewPos = mpRefWin->ScreenToOutputPixel( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
+ Point aNewPos = mpRefWin->NormalizedScreenToOutputPixel( OutputToNormalizedScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
+ ImplSplitMousePos( aNewPos );
+ Splitting( aNewPos );
+ ImplSplitMousePos( aNewPos );
+
+ if ( mbHorzSplit )
+ {
+ if ( aNewPos.X() == maDragPos.X() )
+ return;
+ }
+ else
+ {
+ if ( aNewPos.Y() == maDragPos.Y() )
+ return;
+ }
+
+ if ( mbDragFull )
+ {
+ maDragPos = aNewPos;
+ long nNewPos;
+ if ( mbHorzSplit )
+ nNewPos = maDragPos.X();
+ else
+ nNewPos = maDragPos.Y();
+ if ( nNewPos != mnSplitPos )
+ {
+ SetSplitPosPixel( nNewPos );
+ mnLastSplitPos = 0;
+ Split();
+ }
+
+ GetParent()->Update();
+ }
+ else
+ {
+ ImplDrawSplitter();
+ maDragPos = aNewPos;
+ ImplDrawSplitter();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplKbdTracking( KeyCode aKeyCode )
+{
+ USHORT nCode = aKeyCode.GetCode();
+ if ( nCode == KEY_ESCAPE || nCode == KEY_RETURN )
+ {
+ if( !mbKbdSplitting )
+ return;
+ else
+ mbKbdSplitting = FALSE;
+
+ if ( nCode != KEY_ESCAPE )
+ {
+ long nNewPos;
+ if ( mbHorzSplit )
+ nNewPos = maDragPos.X();
+ else
+ nNewPos = maDragPos.Y();
+ if ( nNewPos != mnStartSplitPos )
+ {
+ SetSplitPosPixel( nNewPos );
+ mnLastSplitPos = 0;
+ Split();
+ }
+ }
+ else
+ {
+ SetSplitPosPixel( mnStartSplitPos );
+ Split();
+ EndSplit();
+ }
+ mnStartSplitPos = 0;
+ }
+ else
+ {
+ Point aNewPos;
+ Size aSize = mpRefWin->GetOutputSize();
+ Point aPos = GetPosPixel();
+ // depending on the position calc allows continous moves or snaps to row/columns
+ // continous mode is active when position is at the origin or end of the splitter
+ // otherwise snap mode is active
+ // default here is snap, holding shift sets continous mode
+ if( mbHorzSplit )
+ aNewPos = Point( ImplSplitterActive() ? aPos.X() : mnSplitPos, aKeyCode.IsShift() ? 0 : aSize.Height()/2);
+ else
+ aNewPos = Point( aKeyCode.IsShift() ? 0 : aSize.Width()/2, ImplSplitterActive() ? aPos.Y() : mnSplitPos );
+
+ Point aOldWindowPos = GetPosPixel();
+
+ int maxiter = 500; // avoid endless loop
+ int delta=0;
+ int delta_step = mbHorzSplit ? aSize.Width()/10 : aSize.Height()/10;
+
+ // use the specified step size if it was set
+ if( mnKeyboardStepSize != SPLITTER_DEFAULTSTEPSIZE )
+ delta_step = mnKeyboardStepSize;
+
+ while( maxiter-- && aOldWindowPos == GetPosPixel() )
+ {
+ // inc/dec position until application performs changes
+ // thus a single key press really moves the splitter
+ if( aKeyCode.IsShift() )
+ delta++;
+ else
+ delta += delta_step;
+
+ switch( nCode )
+ {
+ case KEY_LEFT:
+ aNewPos.X()-=delta;
+ break;
+ case KEY_RIGHT:
+ aNewPos.X()+=delta;
+ break;
+ case KEY_UP:
+ aNewPos.Y()-=delta;
+ break;
+ case KEY_DOWN:
+ aNewPos.Y()+=delta;
+ break;
+ default:
+ maxiter = 0; // leave loop
+ break;
+ }
+ ImplSplitMousePos( aNewPos );
+ Splitting( aNewPos );
+ ImplSplitMousePos( aNewPos );
+
+ if ( mbHorzSplit )
+ {
+ if ( aNewPos.X() == maDragPos.X() )
+ continue;
+ }
+ else
+ {
+ if ( aNewPos.Y() == maDragPos.Y() )
+ continue;
+ }
+
+ maDragPos = aNewPos;
+ long nNewPos;
+ if ( mbHorzSplit )
+ nNewPos = maDragPos.X();
+ else
+ nNewPos = maDragPos.Y();
+ if ( nNewPos != mnSplitPos )
+ {
+ SetSplitPosPixel( nNewPos );
+ mnLastSplitPos = 0;
+ Split();
+ }
+ GetParent()->Update();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::StartSplit()
+{
+ maStartSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::Split()
+{
+ maSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::EndSplit()
+{
+ if ( maEndSplitHdl.IsSet() )
+ maEndSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::Splitting( Point& /* rSplitPos */ )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::SetDragRectPixel( const Rectangle& rDragRect, Window* _pRefWin )
+{
+ maDragRect = rDragRect;
+ if ( !_pRefWin )
+ mpRefWin = GetParent();
+ else
+ mpRefWin = _pRefWin;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::SetSplitPosPixel( long nNewPos )
+{
+ mnSplitPos = nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::SetLastSplitPosPixel( long nNewPos )
+{
+ mnLastSplitPos = nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::StartDrag()
+{
+ if ( IsTracking() )
+ return;
+
+ StartSplit();
+
+ // Tracking starten
+ StartTracking();
+
+ // Start-Positon ermitteln
+ maDragPos = mpRefWin->GetPointerPosPixel();
+ ImplSplitMousePos( maDragPos );
+ Splitting( maDragPos );
+ ImplSplitMousePos( maDragPos );
+ if ( mbHorzSplit )
+ mnStartSplitPos = maDragPos.X();
+ else
+ mnStartSplitPos = maDragPos.Y();
+
+ mbDragFull = (Application::GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SPLIT) != 0;
+ if ( !mbDragFull )
+ ImplDrawSplitter();
+}
+
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplStartKbdSplitting()
+{
+ if( mbKbdSplitting )
+ return;
+
+ mbKbdSplitting = TRUE;
+
+ StartSplit();
+
+ // determine start position
+ // because we have no mouse position we take either the position
+ // of the splitter window or the last split position
+ // the other coordinate is just the center of the reference window
+ Size aSize = mpRefWin->GetOutputSize();
+ Point aPos = GetPosPixel();
+ if( mbHorzSplit )
+ maDragPos = Point( ImplSplitterActive() ? aPos.X() : mnSplitPos, aSize.Height()/2 );
+ else
+ maDragPos = Point( aSize.Width()/2, ImplSplitterActive() ? aPos.Y() : mnSplitPos );
+ ImplSplitMousePos( maDragPos );
+ Splitting( maDragPos );
+ ImplSplitMousePos( maDragPos );
+ if ( mbHorzSplit )
+ mnStartSplitPos = maDragPos.X();
+ else
+ mnStartSplitPos = maDragPos.Y();
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplRestoreSplitter()
+{
+ // set splitter in the center of the ref window
+ StartSplit();
+ Size aSize = mpRefWin->GetOutputSize();
+ Point aPos = Point( aSize.Width()/2 , aSize.Height()/2);
+ if ( mnLastSplitPos != mnSplitPos && mnLastSplitPos > 5 )
+ {
+ // restore last pos if it was a useful position (>5)
+ if ( mbHorzSplit )
+ aPos.X() = mnLastSplitPos;
+ else
+ aPos.Y() = mnLastSplitPos;
+ }
+
+ ImplSplitMousePos( aPos );
+ Splitting( aPos );
+ ImplSplitMousePos( aPos );
+ long nTemp = mnSplitPos;
+ if ( mbHorzSplit )
+ SetSplitPosPixel( aPos.X() );
+ else
+ SetSplitPosPixel( aPos.Y() );
+ mnLastSplitPos = nTemp;
+ Split();
+ EndSplit();
+}
+
+
+// -----------------------------------------------------------------------
+
+void Splitter::GetFocus()
+{
+ if( !ImplSplitterActive() )
+ ImplRestoreSplitter();
+
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::LoseFocus()
+{
+ if( mbKbdSplitting )
+ {
+ KeyCode aReturnKey( KEY_RETURN );
+ ImplKbdTracking( aReturnKey );
+ mbKbdSplitting = FALSE;
+ }
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::KeyInput( const KeyEvent& rKEvt )
+{
+ if( mbInKeyEvent )
+ return;
+
+ mbInKeyEvent = 1;
+
+ Splitter *pSibling = ImplFindSibling();
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+ USHORT nCode = aKeyCode.GetCode();
+ switch ( nCode )
+ {
+ case KEY_UP:
+ case KEY_DOWN:
+ if( !mbHorzSplit )
+ {
+ ImplStartKbdSplitting();
+ ImplKbdTracking( aKeyCode );
+ }
+ else
+ {
+ if( pSibling )
+ {
+ pSibling->GrabFocus();
+ pSibling->KeyInput( rKEvt );
+ }
+ }
+ break;
+ case KEY_RIGHT:
+ case KEY_LEFT:
+ if( mbHorzSplit )
+ {
+ ImplStartKbdSplitting();
+ ImplKbdTracking( aKeyCode );
+ }
+ else
+ {
+ if( pSibling )
+ {
+ pSibling->GrabFocus();
+ pSibling->KeyInput( rKEvt );
+ }
+ }
+ break;
+
+ case KEY_DELETE:
+ if( ImplSplitterActive() )
+ {
+ if( mbKbdSplitting )
+ {
+ KeyCode aKey( KEY_ESCAPE );
+ ImplKbdTracking( aKey );
+ }
+
+ StartSplit();
+ Point aPos;
+ if ( mbHorzSplit )
+ aPos.X() = 0;
+ else
+ aPos.Y() = 0;
+ ImplSplitMousePos( aPos );
+ Splitting( aPos );
+ ImplSplitMousePos( aPos );
+ long nTemp = mnSplitPos;
+ if ( mbHorzSplit )
+ SetSplitPosPixel( aPos.X() );
+ else
+ SetSplitPosPixel( aPos.Y() );
+ mnLastSplitPos = nTemp;
+ Split();
+ EndSplit();
+
+ // Shift-Del deletes both splitters
+ if( aKeyCode.IsShift() && pSibling )
+ pSibling->KeyInput( rKEvt );
+
+ GrabFocusToDocument();
+ }
+ break;
+
+ case KEY_ESCAPE:
+ if( mbKbdSplitting )
+ ImplKbdTracking( aKeyCode );
+ else
+ GrabFocusToDocument();
+ break;
+
+ case KEY_RETURN:
+ ImplKbdTracking( aKeyCode );
+ GrabFocusToDocument();
+ break;
+ default: // let any key input fix the splitter
+ Window::KeyInput( rKEvt );
+ GrabFocusToDocument();
+ break;
+ }
+ mbInKeyEvent = 0;
+}
+
+// -----------------------------------------------------------------------
+
+long Splitter::Notify( NotifyEvent& rNEvt )
+{
+ return Window::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+ if( rDCEvt.GetType() == DATACHANGED_SETTINGS )
+ {
+ Color oldFaceColor = ((AllSettings *) rDCEvt.GetData())->GetStyleSettings().GetFaceColor();
+ Color newFaceColor = Application::GetSettings().GetStyleSettings().GetFaceColor();
+ if( oldFaceColor.IsDark() != newFaceColor.IsDark() )
+ {
+ if( newFaceColor.IsDark() )
+ SetBackground( ImplWhiteWall::get() );
+ else
+ SetBackground( ImplBlackWall::get() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::Paint( const Rectangle& rPaintRect )
+{
+ if( HasFocus() || mbKbdSplitting )
+ {
+ Color oldFillCol = GetFillColor();
+ Color oldLineCol = GetLineColor();
+
+ SetLineColor();
+ SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
+ DrawRect( rPaintRect );
+
+ Color aSelectionBorderCol( GetSettings().GetStyleSettings().GetActiveColor() );
+ SetFillColor( aSelectionBorderCol );
+ SetLineColor();
+
+ Polygon aPoly( rPaintRect );
+ PolyPolygon aPolyPoly( aPoly );
+ DrawTransparent( aPolyPoly, 85 );
+
+ SetLineColor( aSelectionBorderCol );
+ SetFillColor();
+
+ if( mbKbdSplitting )
+ {
+ LineInfo aInfo( LINE_DASH );
+ //aInfo.SetDashLen( 2 );
+ //aInfo.SetDashCount( 1 );
+ aInfo.SetDistance( 1 );
+ aInfo.SetDotLen( 2 );
+ aInfo.SetDotCount( 1 );
+
+ DrawPolyLine( aPoly, aInfo );
+ }
+ else
+ DrawRect( rPaintRect );
+
+ SetFillColor( oldFillCol);
+ SetLineColor( oldLineCol);
+ }
+ else
+ {
+ Window::Paint( rPaintRect );
+ }
+}
diff --git a/vcl/source/window/splitwin.cxx b/vcl/source/window/splitwin.cxx
new file mode 100644
index 000000000000..689c56cbe619
--- /dev/null
+++ b/vcl/source/window/splitwin.cxx
@@ -0,0 +1,3877 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <string.h>
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+#include <tools/rcid.h>
+#include <vcl/event.hxx>
+#include <vcl/wall.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/symbol.hxx>
+#ifndef _SV_SVIDS_HRC
+#include <vcl/svids.hrc>
+#endif
+#include <vcl/image.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/help.hxx>
+#include <vcl/splitwin.hxx>
+
+
+
+// =======================================================================
+
+// Achtung: Darf keine Objekte enthalten, da mit memmove/memcpy gearbeitet wird
+struct ImplSplitItem
+{
+ long mnSize;
+ long mnPixSize;
+ long mnLeft;
+ long mnTop;
+ long mnWidth;
+ long mnHeight;
+ long mnSplitPos;
+ long mnSplitSize;
+ long mnOldSplitPos;
+ long mnOldSplitSize;
+ long mnOldWidth;
+ long mnOldHeight;
+ ImplSplitSet* mpSet;
+ Window* mpWindow;
+ Window* mpOrgParent;
+ USHORT mnId;
+ SplitWindowItemBits mnBits;
+ BOOL mbFixed;
+ BOOL mbSubSize;
+};
+
+struct ImplSplitSet
+{
+ ImplSplitItem* mpItems;
+ Wallpaper* mpWallpaper;
+ Bitmap* mpBitmap;
+ long mnLastSize;
+ long mnSplitSize;
+ USHORT mnItems;
+ USHORT mnId;
+ BOOL mbCalcPix;
+};
+
+#define SPLITWIN_SPLITSIZE 3
+#define SPLITWIN_SPLITSIZEEX 4
+#define SPLITWIN_SPLITSIZEEXLN 6
+#define SPLITWIN_SPLITSIZEAUTOHIDE 36
+#define SPLITWIN_SPLITSIZEFADE 36
+
+#define SPLIT_HORZ ((USHORT)0x0001)
+#define SPLIT_VERT ((USHORT)0x0002)
+#define SPLIT_WINDOW ((USHORT)0x0004)
+#define SPLIT_NOSPLIT ((USHORT)0x8000)
+
+// -----------------------------------------------------------------------
+
+DECLARE_LIST( ImplSplitList, SplitWindow* )
+
+// =======================================================================
+
+static void ImplCalcBorder( WindowAlign eAlign, BOOL bNoAlign,
+ long& rLeft, long& rTop,
+ long& rRight, long& rBottom )
+{
+ if ( bNoAlign )
+ {
+ rLeft = 2;
+ rTop = 2;
+ rRight = 2;
+ rBottom = 2;
+ }
+ else
+ {
+ if ( eAlign == WINDOWALIGN_TOP )
+ {
+ rLeft = 2;
+ rTop = 2;
+ rRight = 2;
+ rBottom = 0;
+ }
+ else if ( eAlign == WINDOWALIGN_LEFT )
+ {
+ rLeft = 2;
+ rTop = 2;
+ rRight = 0;
+ rBottom = 2;
+ }
+ else if ( eAlign == WINDOWALIGN_BOTTOM )
+ {
+ rLeft = 2;
+ rTop = 0;
+ rRight = 2;
+ rBottom = 2;
+ }
+ else
+ {
+ rLeft = 0;
+ rTop = 2;
+ rRight = 2;
+ rBottom = 2;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawBorder( SplitWindow* pWin )
+{
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+ long nDX = pWin->mnDX;
+ long nDY = pWin->mnDY;
+
+ if ( pWin->mbNoAlign )
+ {
+ DecorationView aDecoView( pWin );
+ Point aTmpPoint;
+ Rectangle aRect( aTmpPoint, Size( nDX, nDY ) );
+ aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
+ }
+ else
+ {/*
+ if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) );
+ if ( (pWin->meAlign == WINDOWALIGN_LEFT) || (pWin->meAlign == WINDOWALIGN_RIGHT) )
+ {
+ if ( pWin->meAlign == WINDOWALIGN_LEFT )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ }
+ }*/
+ if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
+ pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
+
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
+ pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
+ }
+ else if ( pWin->meAlign == WINDOWALIGN_TOP )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
+ pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
+ pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-1 ) );
+
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 1, 1 ), Point( nDX-3, 1 ) );
+ pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-1 ) );
+ pWin->DrawLine( Point( nDX-1, 1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else if ( pWin->meAlign == WINDOWALIGN_LEFT )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
+ pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 1, 1 ), Point( nDX-1, 1 ) );
+ pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
+ pWin->DrawLine( Point( 1, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( nDX-2, 0 ) );
+ pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
+
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, 1 ), Point( nDX-3, 1 ) );
+ pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawBorderLine( SplitWindow* pWin )
+{
+ if ( pWin->mbFadeOut || pWin->mbAutoHide )
+ {
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+ long nDX = pWin->mnDX;
+ long nDY = pWin->mnDY;
+
+ if ( pWin->meAlign == WINDOWALIGN_LEFT )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( nDX-SPLITWIN_SPLITSIZEEXLN-1, 0 ), Point( nDX-SPLITWIN_SPLITSIZEEXLN-1, nDY-3 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( nDX-SPLITWIN_SPLITSIZEEXLN, 1 ), Point( nDX-SPLITWIN_SPLITSIZEEXLN, nDY-4 ) );
+ }
+ else if ( pWin->meAlign == WINDOWALIGN_RIGHT )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( SPLITWIN_SPLITSIZEEXLN-1, 0 ), Point( SPLITWIN_SPLITSIZEEXLN-1, nDY-3 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( SPLITWIN_SPLITSIZEEXLN, 1 ), Point( SPLITWIN_SPLITSIZEEXLN, nDY-4 ) );
+ }
+ else if ( pWin->meAlign == WINDOWALIGN_TOP )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, nDY-SPLITWIN_SPLITSIZEEXLN-1 ), Point( nDX-3, nDY-SPLITWIN_SPLITSIZEEXLN-1 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 1, nDY-SPLITWIN_SPLITSIZEEXLN ), Point( nDX-4, nDY-SPLITWIN_SPLITSIZEEXLN ) );
+ }
+ else if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, SPLITWIN_SPLITSIZEEXLN-1 ), Point( nDX-3, SPLITWIN_SPLITSIZEEXLN-1 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 1, SPLITWIN_SPLITSIZEEXLN ), Point( nDX-4, SPLITWIN_SPLITSIZEEXLN ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static ImplSplitSet* ImplFindSet( ImplSplitSet* pSet, USHORT nId )
+{
+ if ( pSet->mnId == nId )
+ return pSet;
+
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnId == nId )
+ return pItems[i].mpSet;
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ {
+ ImplSplitSet* pFindSet = ImplFindSet( pItems[i].mpSet, nId );
+ if ( pFindSet )
+ return pFindSet;
+ }
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static ImplSplitSet* ImplFindItem( ImplSplitSet* pSet, USHORT nId, USHORT& rPos )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnId == nId )
+ {
+ rPos = i;
+ return pSet;
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ {
+ ImplSplitSet* pFindSet = ImplFindItem( pItems[i].mpSet, nId, rPos );
+ if ( pFindSet )
+ return pFindSet;
+ }
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplFindItem( ImplSplitSet* pSet, Window* pWindow )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpWindow == pWindow )
+ return pItems[i].mnId;
+ else
+ {
+ if ( pItems[i].mpSet )
+ {
+ USHORT nId = ImplFindItem( pItems[i].mpSet, pWindow );
+ if ( nId )
+ return nId;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplFindItem( ImplSplitSet* pSet, const Point& rPos,
+ BOOL bRows, BOOL bDown = TRUE )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnWidth && pItems[i].mnHeight )
+ {
+ // Wegen ICC auftrennen
+ Point aPoint( pItems[i].mnLeft, pItems[i].mnTop );
+ Size aSize( pItems[i].mnWidth, pItems[i].mnHeight );
+ Rectangle aRect( aPoint, aSize );
+ if ( bRows )
+ {
+ if ( bDown )
+ aRect.Bottom() += pSet->mnSplitSize;
+ else
+ aRect.Top() -= pSet->mnSplitSize;
+ }
+ else
+ {
+ if ( bDown )
+ aRect.Right() += pSet->mnSplitSize;
+ else
+ aRect.Left() -= pSet->mnSplitSize;
+ }
+
+ if ( aRect.IsInside( rPos ) )
+ {
+ if ( pItems[i].mpSet && pItems[i].mpSet->mpItems )
+ {
+ return ImplFindItem( pItems[i].mpSet, rPos,
+ ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ }
+ else
+ return pItems[i].mnId;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDeleteSet( ImplSplitSet* pSet )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ ImplDeleteSet( pItems[i].mpSet );
+ }
+
+ if ( pSet->mpWallpaper )
+ delete pSet->mpWallpaper;
+
+ if ( pSet->mpBitmap )
+ delete pSet->mpBitmap;
+
+ delete [] pItems;
+ delete pSet;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSetSplitSize( ImplSplitSet* pSet, long nNewSize )
+{
+ pSet->mnSplitSize = nNewSize;
+ for ( USHORT i = 0; i < pSet->mnItems; i++ )
+ {
+ if ( pSet->mpItems[i].mpSet )
+ ImplSetSplitSize( pSet->mpItems[i].mpSet, nNewSize );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcSet( ImplSplitSet* pSet,
+ long nSetLeft, long nSetTop,
+ long nSetWidth, long nSetHeight,
+ BOOL bRows, BOOL bDown = TRUE )
+{
+ if ( !pSet->mpItems )
+ return;
+
+ USHORT i;
+ USHORT j;
+ USHORT nMins;
+ USHORT nCalcItems;
+ USHORT nItems = pSet->mnItems;
+ USHORT nVisItems;
+ USHORT nAbsItems;
+ long nCalcSize;
+ long nSizeDelta;
+ long nCurSize;
+ long nSizeWinSize;
+ long nNewSizeWinSize;
+ long nTemp;
+ long nTempErr;
+ long nErrorSum;
+ long nCurSizeDelta;
+ long nPos;
+ long nMaxPos;
+ long* pSize;
+ ImplSplitItem* pItems = pSet->mpItems;
+ BOOL bEmpty;
+
+ // Anzahl sichtbarer Items ermitteln
+ nVisItems = 0;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ nVisItems++;
+ }
+
+ // Groessen berechnen
+ if ( bRows )
+ nCalcSize = nSetHeight;
+ else
+ nCalcSize = nSetWidth;
+ nCalcSize -= (nVisItems-1)*pSet->mnSplitSize;
+ nCurSize = 0;
+ if ( pSet->mbCalcPix || (pSet->mnLastSize != nCalcSize) )
+ {
+ long nPercentFactor = 10;
+ long nRelCount = 0;
+ long nPercent = 0;
+ long nRelPercent = 0;
+ long nAbsSize = 0;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( pItems[i].mnBits & SWIB_RELATIVESIZE )
+ nRelCount += pItems[i].mnSize;
+ else if ( pItems[i].mnBits & SWIB_PERCENTSIZE )
+ nPercent += pItems[i].mnSize;
+ else
+ nAbsSize += pItems[i].mnSize;
+ }
+ }
+ // Relative-Werte auf prozentual mappen (Percent bei uns 10tel Prozent)
+ nPercent *= nPercentFactor;
+ if ( nRelCount )
+ {
+ long nRelPercentBase = 1000;
+ while ( (nRelCount > nRelPercentBase) && (nPercentFactor < 100000) )
+ {
+ nRelPercentBase *= 10;
+ nPercentFactor *= 10;
+ }
+ if ( nPercent < nRelPercentBase )
+ {
+ nRelPercent = (nRelPercentBase-nPercent)/nRelCount;
+ nPercent += nRelPercent*nRelCount;
+ }
+ else
+ nRelPercent = 0;
+ }
+ if ( !nPercent )
+ nPercent = 1;
+ nSizeDelta = nCalcSize-nAbsSize;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnBits & SWIB_INVISIBLE )
+ pItems[i].mnPixSize = 0;
+ else if ( pItems[i].mnBits & SWIB_RELATIVESIZE )
+ {
+ if ( nSizeDelta <= 0 )
+ pItems[i].mnPixSize = 0;
+ else
+ pItems[i].mnPixSize = (nSizeDelta*pItems[i].mnSize*nRelPercent)/nPercent;
+ }
+ else if ( pItems[i].mnBits & SWIB_PERCENTSIZE )
+ {
+ if ( nSizeDelta <= 0 )
+ pItems[i].mnPixSize = 0;
+ else
+ pItems[i].mnPixSize = (nSizeDelta*pItems[i].mnSize*nPercentFactor)/nPercent;
+ }
+ else
+ pItems[i].mnPixSize = pItems[i].mnSize;
+ nCurSize += pItems[i].mnPixSize;
+ }
+
+ pSet->mbCalcPix = FALSE;
+ pSet->mnLastSize = nCalcSize;
+
+ // Fenster einpassen
+ nSizeDelta = nCalcSize-nCurSize;
+ if ( nSizeDelta )
+ {
+ nAbsItems = 0;
+ nSizeWinSize = 0;
+ nNewSizeWinSize = 0;
+
+ // Zuerst die absoluten Items relativ resizen
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( !(pItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE)) )
+ {
+ nAbsItems++;
+ nSizeWinSize += pItems[i].mnPixSize;
+ }
+ }
+ }
+ // Rundungsfehler werden hier nicht ausgelichen
+ if ( (nAbsItems < (USHORT)(Abs( nSizeDelta ))) && nSizeWinSize )
+ {
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( !(pItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE)) )
+ {
+ pItems[i].mnPixSize += (nSizeDelta*pItems[i].mnPixSize)/nSizeWinSize;
+ nNewSizeWinSize += pItems[i].mnPixSize;
+ }
+ }
+ }
+ nSizeDelta -= nNewSizeWinSize-nSizeWinSize;
+ }
+
+ // Jetzt die Rundunsfehler ausgleichen
+ j = 0;
+ nMins = 0;
+ while ( nSizeDelta && (nItems != nMins) )
+ {
+ // Feststellen, welche Items berechnet werden duerfen
+ nCalcItems = 0;
+ while ( !nCalcItems )
+ {
+ for ( i = 0; i < nItems; i++ )
+ {
+ pItems[i].mbSubSize = FALSE;
+
+ if ( j >= 2 )
+ pItems[i].mbSubSize = TRUE;
+ else
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( (nSizeDelta > 0) || pItems[i].mnPixSize )
+ {
+ if ( j >= 1 )
+ pItems[i].mbSubSize = TRUE;
+ else
+ {
+ if ( (j == 0) && (pItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE)) )
+ pItems[i].mbSubSize = TRUE;
+ }
+ }
+ }
+ }
+
+ if ( pItems[i].mbSubSize )
+ nCalcItems++;
+ }
+
+ j++;
+ }
+
+ // Groessen von den einzelnen Items abziehen
+ nErrorSum = nSizeDelta % nCalcItems;
+ nCurSizeDelta = nSizeDelta / nCalcItems;
+ nMins = 0;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnBits & SWIB_INVISIBLE )
+ nMins++;
+ else if ( pItems[i].mbSubSize )
+ {
+ pSize = &(pItems[i].mnPixSize);
+
+ if ( nErrorSum )
+ {
+ if ( nErrorSum < 0 )
+ nTempErr = -1;
+ else
+ nTempErr = 1;
+ }
+ else
+ nTempErr = 0;
+
+ if ( (*pSize+nCurSizeDelta+nTempErr) <= 0 )
+ {
+ nTemp = *pSize;
+ if ( nTemp )
+ {
+ *pSize -= nTemp;
+ nSizeDelta += nTemp;
+ }
+ nMins++;
+ }
+ else
+ {
+ *pSize += nCurSizeDelta;
+ nSizeDelta -= nCurSizeDelta;
+ if ( nTempErr && (*pSize || (nTempErr > 0)) )
+ {
+ *pSize += nTempErr;
+ nSizeDelta -= nTempErr;
+ nErrorSum -= nTempErr;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ nCurSize += pItems[i].mnPixSize;
+ }
+ }
+
+ // Maximale Groesse berechnen
+ if ( bRows )
+ {
+ nPos = nSetTop;
+ if ( !bDown )
+ nMaxPos = nSetTop-nSetHeight;
+ else
+ nMaxPos = nSetTop+nSetHeight;
+ }
+ else
+ {
+ nPos = nSetLeft;
+ if ( !bDown )
+ nMaxPos = nSetLeft-nSetWidth;
+ else
+ nMaxPos = nSetLeft+nSetWidth;
+ }
+
+ // Fenster anordnen und Werte anpassen
+ for ( i = 0; i < nItems; i++ )
+ {
+ pItems[i].mnOldSplitPos = pItems[i].mnSplitPos;
+ pItems[i].mnOldSplitSize = pItems[i].mnSplitSize;
+ pItems[i].mnOldWidth = pItems[i].mnWidth;
+ pItems[i].mnOldHeight = pItems[i].mnHeight;
+
+ if ( pItems[i].mnBits & SWIB_INVISIBLE )
+ bEmpty = TRUE;
+ else
+ {
+ bEmpty = FALSE;
+ if ( bDown )
+ {
+ if ( nPos+pItems[i].mnPixSize > nMaxPos )
+ bEmpty = TRUE;
+ }
+ else
+ {
+ nPos -= pItems[i].mnPixSize;
+ if ( nPos < nMaxPos )
+ bEmpty = TRUE;
+ }
+ }
+
+ if ( bEmpty )
+ {
+ pItems[i].mnWidth = 0;
+ pItems[i].mnHeight = 0;
+ pItems[i].mnSplitSize = 0;
+ }
+ else
+ {
+ if ( bRows )
+ {
+ pItems[i].mnLeft = nSetLeft;
+ pItems[i].mnTop = nPos;
+ pItems[i].mnWidth = nSetWidth;
+ pItems[i].mnHeight = pItems[i].mnPixSize;
+ }
+ else
+ {
+ pItems[i].mnLeft = nPos;
+ pItems[i].mnTop = nSetTop;
+ pItems[i].mnWidth = pItems[i].mnPixSize;
+ pItems[i].mnHeight = nSetHeight;
+ }
+
+ if ( i > nItems-1 )
+ pItems[i].mnSplitSize = 0;
+ else
+ {
+ pItems[i].mnSplitSize = pSet->mnSplitSize;
+ if ( bDown )
+ {
+ pItems[i].mnSplitPos = nPos+pItems[i].mnPixSize;
+ if ( pItems[i].mnSplitPos+pItems[i].mnSplitSize > nMaxPos )
+ pItems[i].mnSplitSize = nMaxPos-pItems[i].mnSplitPos;
+ }
+ else
+ {
+ pItems[i].mnSplitPos = nPos-pSet->mnSplitSize;
+ if ( pItems[i].mnSplitPos < nMaxPos )
+ pItems[i].mnSplitSize = pItems[i].mnSplitPos+pSet->mnSplitSize-nMaxPos;
+ }
+ }
+ }
+
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( !bDown )
+ nPos -= pSet->mnSplitSize;
+ else
+ nPos += pItems[i].mnPixSize+pSet->mnSplitSize;
+ }
+ }
+
+ // Sub-Set's berechnen
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet && pItems[i].mnWidth && pItems[i].mnHeight )
+ {
+ ImplCalcSet( pItems[i].mpSet,
+ pItems[i].mnLeft, pItems[i].mnTop,
+ pItems[i].mnWidth, pItems[i].mnHeight,
+ ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ }
+ }
+
+ // Fixed setzen
+ for ( i = 0; i < nItems; i++ )
+ {
+ pItems[i].mbFixed = FALSE;
+ if ( pItems[i].mnBits & SWIB_FIXED )
+ pItems[i].mbFixed = TRUE;
+ else
+ {
+ // Wenn Child-Set vorhanden, ist dieses Item auch Fixed, wenn
+ // ein Child fixed ist
+ if ( pItems[i].mpSet )
+ {
+ for ( j = 0; j < pItems[i].mpSet->mnItems; j++ )
+ {
+ if ( pItems[i].mpSet->mpItems[j].mbFixed )
+ {
+ pItems[i].mbFixed = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplCalcSet2( SplitWindow* pWindow, ImplSplitSet* pSet, BOOL bHide,
+ BOOL bRows, BOOL /*bDown*/ )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ if ( pWindow->IsReallyVisible() && pWindow->IsUpdateMode() && pWindow->mbInvalidate )
+ {
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnSplitSize )
+ {
+ // Evt. alles invalidieren oder nur einen kleinen Teil
+ if ( (pItems[i].mnOldSplitPos != pItems[i].mnSplitPos) ||
+ (pItems[i].mnOldSplitSize != pItems[i].mnSplitSize) ||
+ (pItems[i].mnOldWidth != pItems[i].mnWidth) ||
+ (pItems[i].mnOldHeight != pItems[i].mnHeight) )
+ {
+ Rectangle aRect;
+
+ // Old Rect invalidieren
+ if ( bRows )
+ {
+ aRect.Left() = pItems[i].mnLeft;
+ aRect.Right() = pItems[i].mnLeft+pItems[i].mnOldWidth-1;
+ aRect.Top() = pItems[i].mnOldSplitPos;
+ aRect.Bottom() = aRect.Top() + pItems[i].mnOldSplitSize;
+ }
+ else
+ {
+ aRect.Top() = pItems[i].mnTop;
+ aRect.Bottom() = pItems[i].mnTop+pItems[i].mnOldHeight-1;
+ aRect.Left() = pItems[i].mnOldSplitPos;
+ aRect.Right() = aRect.Left() + pItems[i].mnOldSplitSize;
+ }
+ pWindow->Invalidate( aRect );
+ // New Rect invalidieren
+ if ( bRows )
+ {
+ aRect.Left() = pItems[i].mnLeft;
+ aRect.Right() = pItems[i].mnLeft+pItems[i].mnWidth-1;
+ aRect.Top() = pItems[i].mnSplitPos;
+ aRect.Bottom() = aRect.Top() + pItems[i].mnSplitSize;
+ }
+ else
+ {
+ aRect.Top() = pItems[i].mnTop;
+ aRect.Bottom() = pItems[i].mnTop+pItems[i].mnHeight-1;
+ aRect.Left() = pItems[i].mnSplitPos;
+ aRect.Right() = aRect.Left() + pItems[i].mnSplitSize;
+ }
+ pWindow->Invalidate( aRect );
+
+ // Leere Sets komplett invalidieren, da diese Flaechen
+ // nicht von Fenstern ueberladen werden
+ if ( pItems[i].mpSet && !pItems[i].mpSet->mpItems )
+ {
+ aRect.Left() = pItems[i].mnLeft;
+ aRect.Top() = pItems[i].mnTop;
+ aRect.Right() = pItems[i].mnLeft+pItems[i].mnWidth-1;
+ aRect.Bottom() = pItems[i].mnTop+pItems[i].mnHeight-1;
+ pWindow->Invalidate( aRect );
+ }
+ }
+ }
+ }
+ }
+
+ // Fenster positionieren
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ {
+ BOOL bTempHide = bHide;
+ if ( !pItems[i].mnWidth || !pItems[i].mnHeight )
+ bTempHide = TRUE;
+ ImplCalcSet2( pWindow, pItems[i].mpSet, bTempHide,
+ ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ }
+ else
+ {
+ if ( pItems[i].mnWidth && pItems[i].mnHeight && !bHide )
+ {
+ Point aPos( pItems[i].mnLeft, pItems[i].mnTop );
+ Size aSize( pItems[i].mnWidth, pItems[i].mnHeight );
+ pItems[i].mpWindow->SetPosSizePixel( aPos, aSize );
+ }
+ else
+ pItems[i].mpWindow->Hide();
+ }
+ }
+
+ // Fenster anzeigen und Flag zuruecksetzen
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpWindow && pItems[i].mnWidth && pItems[i].mnHeight && !bHide )
+ pItems[i].mpWindow->Show();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcLogSize( ImplSplitItem* pItems, USHORT nItems )
+{
+ // Original-Groessen updaten
+ USHORT i;
+ long nRelSize = 0;
+ long nPerSize = 0;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnBits & SWIB_RELATIVESIZE )
+ nRelSize += pItems[i].mnPixSize;
+ else if ( pItems[i].mnBits & SWIB_PERCENTSIZE )
+ nPerSize += pItems[i].mnPixSize;
+ }
+ nPerSize += nRelSize;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnBits & SWIB_RELATIVESIZE )
+ {
+ if ( nRelSize )
+ pItems[i].mnSize = (pItems[i].mnPixSize+(nRelSize/2))/nRelSize;
+ else
+ pItems[i].mnSize = 1;
+ }
+ else if ( pItems[i].mnBits & SWIB_PERCENTSIZE )
+ {
+ if ( nPerSize )
+ pItems[i].mnSize = (pItems[i].mnPixSize*100)/nPerSize;
+ else
+ pItems[i].mnSize = 1;
+ }
+ else
+ pItems[i].mnSize = pItems[i].mnPixSize;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawBack( SplitWindow* pWindow, const Rectangle& rRect,
+ const Wallpaper* pWall, const Bitmap* pBitmap )
+{
+ if ( pBitmap )
+ {
+ Point aPos = rRect.TopLeft();
+ Size aBmpSize = pBitmap->GetSizePixel();
+ pWindow->Push( PUSH_CLIPREGION );
+ pWindow->IntersectClipRegion( rRect );
+ do
+ {
+ aPos.X() = rRect.Left();
+ do
+ {
+ pWindow->DrawBitmap( aPos, *pBitmap );
+ aPos.X() += aBmpSize.Width();
+ }
+ while ( aPos.X() < rRect.Right() );
+ aPos.Y() += aBmpSize.Height();
+ }
+ while ( aPos.Y() < rRect.Bottom() );
+ pWindow->Pop();
+ }
+ else
+ pWindow->DrawWallpaper( rRect, *pWall );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawBack( SplitWindow* pWindow, ImplSplitSet* pSet )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ // Beim Mainset auch den Hintergrund zeichnen
+ if ( pSet->mnId == 0 )
+ {
+ if ( pSet->mpBitmap )
+ {
+ Rectangle aRect( pWindow->mnLeftBorder,
+ pWindow->mnTopBorder,
+ pWindow->mnDX-pWindow->mnRightBorder-1,
+ pWindow->mnDY-pWindow->mnBottomBorder-1 );
+ ImplDrawBack( pWindow, aRect, pSet->mpWallpaper, pSet->mpBitmap );
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ pSet = pItems[i].mpSet;
+ if ( pSet )
+ {
+ if ( pSet->mpBitmap || pSet->mpWallpaper )
+ {
+ // Wegen ICC auftrennen
+ Point aPoint( pItems[i].mnLeft, pItems[i].mnTop );
+ Size aSize( pItems[i].mnWidth, pItems[i].mnHeight );
+ Rectangle aRect( aPoint, aSize );
+ ImplDrawBack( pWindow, aRect, pSet->mpWallpaper, pSet->mpBitmap );
+ }
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ ImplDrawBack( pWindow, pItems[i].mpSet );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawSplit( SplitWindow* pWindow, ImplSplitSet* pSet,
+ BOOL bRows, BOOL bDown = TRUE )
+{
+ if ( !pSet->mpItems )
+ return;
+
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ long nPos;
+ long nTop;
+ long nBottom;
+ ImplSplitItem* pItems = pSet->mpItems;
+ const StyleSettings& rStyleSettings = pWindow->GetSettings().GetStyleSettings();
+
+ BOOL bFlat = (pWindow->GetStyle() & WB_FLATSPLITDRAW) == WB_FLATSPLITDRAW;
+
+ for ( i = 0; i < nItems-1; i++ )
+ {
+ if ( pItems[i].mnSplitSize )
+ {
+ nPos = pItems[i].mnSplitPos;
+
+ long nItemSplitSize = pItems[i].mnSplitSize;
+ long nSplitSize = pSet->mnSplitSize;
+ if ( bRows )
+ {
+ nTop = pItems[i].mnLeft;
+ nBottom = pItems[i].mnLeft+pItems[i].mnWidth-1;
+
+ if ( bFlat ) nPos--;
+
+ if ( bDown || (nItemSplitSize >= nSplitSize) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetLightColor() );
+ pWindow->DrawLine( Point( nTop, nPos+1 ), Point( nBottom, nPos+1 ) );
+ }
+ nPos += nSplitSize-2;
+ if ( bFlat ) nPos+=2;
+ if ( (!bDown && (nItemSplitSize >= 2)) ||
+ (bDown && (nItemSplitSize >= nSplitSize-1)) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWindow->DrawLine( Point( nTop, nPos ), Point( nBottom, nPos ) );
+ }
+ if ( !bFlat )
+ {
+ nPos++;
+ if ( !bDown || (nItemSplitSize >= nSplitSize) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ pWindow->DrawLine( Point( nTop, nPos ), Point( nBottom, nPos ) );
+ }
+ }
+ }
+ else
+ {
+ nTop = pItems[i].mnTop;
+ nBottom = pItems[i].mnTop+pSet->mpItems[i].mnHeight-1;
+
+ if ( bFlat ) nPos--;
+ if ( bDown || (nItemSplitSize >= nSplitSize) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetLightColor() );
+ pWindow->DrawLine( Point( nPos+1, nTop ), Point( nPos+1, nBottom ) );
+ }
+ nPos += pSet->mnSplitSize-2;
+ if ( bFlat ) nPos+=2;
+ if ( (!bDown && (nItemSplitSize >= 2)) ||
+ (bDown && (nItemSplitSize >= nSplitSize-1)) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWindow->DrawLine( Point( nPos, nTop ), Point( nPos, nBottom ) );
+ }
+ if( !bFlat )
+ {
+ nPos++;
+ if ( !bDown || (nItemSplitSize >= nSplitSize) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ pWindow->DrawLine( Point( nPos, nTop ), Point( nPos, nBottom ) );
+ }
+ }
+ }
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet && pItems[i].mnWidth && pItems[i].mnHeight )
+ ImplDrawSplit( pWindow, pItems[i].mpSet, ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::ImplTestSplit( ImplSplitSet* pSet, const Point& rPos,
+ long& rMouseOff, ImplSplitSet** ppFoundSet, USHORT& rFoundPos,
+ BOOL bRows, BOOL /*bDown*/ )
+{
+ if ( !pSet->mpItems )
+ return 0;
+
+ USHORT i;
+ USHORT nSplitTest;
+ USHORT nItems = pSet->mnItems;
+ long nMPos1;
+ long nMPos2;
+ long nPos;
+ long nTop;
+ long nBottom;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ if ( bRows )
+ {
+ nMPos1 = rPos.X();
+ nMPos2 = rPos.Y();
+ }
+ else
+ {
+ nMPos1 = rPos.Y();
+ nMPos2 = rPos.X();
+ }
+
+ for ( i = 0; i < nItems-1; i++ )
+ {
+ if ( pItems[i].mnSplitSize )
+ {
+ if ( bRows )
+ {
+ nTop = pItems[i].mnLeft;
+ nBottom = pItems[i].mnLeft+pItems[i].mnWidth-1;
+ }
+ else
+ {
+ nTop = pItems[i].mnTop;
+ nBottom = pItems[i].mnTop+pItems[i].mnHeight-1;
+ }
+ nPos = pItems[i].mnSplitPos;
+
+ if ( (nMPos1 >= nTop) && (nMPos1 <= nBottom) &&
+ (nMPos2 >= nPos) && (nMPos2 <= nPos+pItems[i].mnSplitSize) )
+ {
+ if ( !pItems[i].mbFixed && !pItems[i+1].mbFixed )
+ {
+ rMouseOff = nMPos2-nPos;
+ *ppFoundSet = pSet;
+ rFoundPos = i;
+ if ( bRows )
+ return SPLIT_VERT;
+ else
+ return SPLIT_HORZ;
+ }
+ else
+ return SPLIT_NOSPLIT;
+ }
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ {
+ nSplitTest = ImplTestSplit( pItems[i].mpSet, rPos,
+ rMouseOff, ppFoundSet, rFoundPos,
+ ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ if ( nSplitTest )
+ return nSplitTest;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::ImplTestSplit( SplitWindow* pWindow, const Point& rPos,
+ long& rMouseOff, ImplSplitSet** ppFoundSet, USHORT& rFoundPos )
+{
+ // Resizeable SplitWindow muss anders behandelt werden
+ if ( pWindow->mnWinStyle & WB_SIZEABLE )
+ {
+ long nTPos;
+ long nPos;
+ long nBorder;
+
+ if ( pWindow->mbHorz )
+ {
+ if ( pWindow->mbBottomRight )
+ {
+ nBorder = pWindow->mnBottomBorder;
+ nPos = 0;
+ }
+ else
+ {
+ nBorder = pWindow->mnTopBorder;
+ nPos = pWindow->mnDY-nBorder;
+ }
+ nTPos = rPos.Y();
+ }
+ else
+ {
+ if ( pWindow->mbBottomRight )
+ {
+ nBorder = pWindow->mnRightBorder;
+ nPos = 0;
+ }
+ else
+ {
+ nBorder = pWindow->mnLeftBorder;
+ nPos = pWindow->mnDX-nBorder;
+ }
+ nTPos = rPos.X();
+ }
+ long nSplitSize = pWindow->mpMainSet->mnSplitSize-2;
+ if ( pWindow->mbAutoHide || pWindow->mbFadeOut )
+ nSplitSize += SPLITWIN_SPLITSIZEEXLN;
+ if ( !pWindow->mbBottomRight )
+ nPos -= nSplitSize;
+ if ( (nTPos >= nPos) && (nTPos <= nPos+nSplitSize+nBorder) )
+ {
+ rMouseOff = nTPos-nPos;
+ *ppFoundSet = pWindow->mpMainSet;
+ if ( pWindow->mpMainSet->mpItems )
+ rFoundPos = pWindow->mpMainSet->mnItems-1;
+ else
+ rFoundPos = 0;
+ if ( pWindow->mbHorz )
+ return SPLIT_VERT | SPLIT_WINDOW;
+ else
+ return SPLIT_HORZ | SPLIT_WINDOW;
+ }
+ }
+
+ return ImplTestSplit( pWindow->mpMainSet, rPos, rMouseOff, ppFoundSet, rFoundPos,
+ pWindow->mbHorz, !pWindow->mbBottomRight );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawSplitTracking( SplitWindow* pThis, const Point& rPos )
+{
+ Rectangle aRect;
+
+ if ( pThis->mnSplitTest & SPLIT_HORZ )
+ {
+ aRect.Top() = pThis->maDragRect.Top();
+ aRect.Bottom() = pThis->maDragRect.Bottom();
+ aRect.Left() = rPos.X();
+ aRect.Right() = aRect.Left()+pThis->mpSplitSet->mnSplitSize-1;
+ if ( !(pThis->mnWinStyle & WB_NOSPLITDRAW) )
+ aRect.Right()--;
+ if ( (pThis->mnSplitTest & SPLIT_WINDOW) &&
+ (pThis->mbAutoHide || pThis->mbFadeOut) )
+ {
+ aRect.Left() += SPLITWIN_SPLITSIZEEXLN;
+ aRect.Right() += SPLITWIN_SPLITSIZEEXLN;
+ }
+ }
+ else
+ {
+ aRect.Left() = pThis->maDragRect.Left();
+ aRect.Right() = pThis->maDragRect.Right();
+ aRect.Top() = rPos.Y();
+ aRect.Bottom() = aRect.Top()+pThis->mpSplitSet->mnSplitSize-1;
+ if ( !(pThis->mnWinStyle & WB_NOSPLITDRAW) )
+ aRect.Bottom()--;
+ if ( (pThis->mnSplitTest & SPLIT_WINDOW) &&
+ (pThis->mbAutoHide || pThis->mbFadeOut) )
+ {
+ aRect.Top() += SPLITWIN_SPLITSIZEEXLN;
+ aRect.Bottom() += SPLITWIN_SPLITSIZEEXLN;
+ }
+ }
+ pThis->ShowTracking( aRect, SHOWTRACK_SPLIT );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplInit( Window* pParent, WinBits nStyle )
+{
+ ImplSplitSet* pNewSet = new ImplSplitSet;
+ pNewSet->mpItems = NULL;
+ pNewSet->mpWallpaper = NULL;
+ pNewSet->mpBitmap = NULL;
+ pNewSet->mnLastSize = 0;
+ pNewSet->mnItems = 0;
+ pNewSet->mnId = 0;
+ pNewSet->mnSplitSize = SPLITWIN_SPLITSIZE;
+ pNewSet->mbCalcPix = TRUE;
+
+ mpMainSet = pNewSet;
+ mpBaseSet = pNewSet;
+ mpSplitSet = NULL;
+ mpLastSizes = NULL;
+ mnDX = 0;
+ mnDY = 0;
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ mnMaxSize = 0;
+ mnMouseOff = 0;
+ meAlign = WINDOWALIGN_TOP;
+ mnWinStyle = nStyle;
+ mnSplitTest = 0;
+ mnSplitPos = 0;
+ mnMouseModifier = 0;
+ mnMStartPos = 0;
+ mnMSplitPos = 0;
+ mbDragFull = FALSE;
+ mbHorz = TRUE;
+ mbBottomRight = FALSE;
+ mbCalc = FALSE;
+ mbRecalc = TRUE;
+ mbInvalidate = TRUE;
+ mbAutoHide = FALSE;
+ mbFadeIn = FALSE;
+ mbFadeOut = FALSE;
+ mbAutoHideIn = FALSE;
+ mbAutoHideDown = FALSE;
+ mbFadeInDown = FALSE;
+ mbFadeOutDown = FALSE;
+ mbAutoHidePressed = FALSE;
+ mbFadeInPressed = FALSE;
+ mbFadeOutPressed = FALSE;
+ mbFadeNoButtonMode = FALSE;
+ mbNoAlign = FALSE;
+
+ if ( nStyle & WB_NOSPLITDRAW )
+ {
+ pNewSet->mnSplitSize -= 2;
+ mbInvalidate = FALSE;
+ }
+
+ if ( nStyle & WB_BORDER )
+ {
+ ImplCalcBorder( meAlign, mbNoAlign, mnLeftBorder, mnTopBorder,
+ mnRightBorder, mnBottomBorder );
+ }
+ else
+ {
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ }
+
+ DockingWindow::ImplInit( pParent, (nStyle | WB_CLIPCHILDREN) & ~(WB_BORDER | WB_SIZEABLE) );
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplInitSettings()
+{
+ // Wenn fuer das MainSet eine Bitmap gesetzt wird, dann
+ // brauchen wir nicht mehr den Hintergrund loeschen
+ // Wenn MainSet Wallpaper hat, dann ist das der Hintergrund, ansonsten
+ // sind es die Standard-Farben
+ if ( mpMainSet->mpBitmap )
+ SetBackground();
+ else if ( mpMainSet->mpWallpaper )
+ SetBackground( *mpMainSet->mpWallpaper );
+ else
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+ }
+}
+
+// =======================================================================
+
+SplitWindow::SplitWindow( Window* pParent, WinBits nStyle ) :
+ DockingWindow( WINDOW_SPLITWINDOW )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+SplitWindow::SplitWindow( Window* pParent, const ResId& rResId ) :
+ DockingWindow( WINDOW_SPLITWINDOW )
+{
+ rResId.SetRT( RSC_SPLITWINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+SplitWindow::~SplitWindow()
+{
+ // Sets loeschen
+ ImplDeleteSet( mpMainSet );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplSetWindowSize( long nDelta )
+{
+ if ( !nDelta )
+ return;
+
+ Size aSize = GetSizePixel();
+ if ( meAlign == WINDOWALIGN_TOP )
+ {
+ aSize.Height() += nDelta;
+ SetSizePixel( aSize );
+ }
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ {
+ maDragRect.Top() += nDelta;
+ Point aPos = GetPosPixel();
+ aPos.Y() -= nDelta;
+ aSize.Height() += nDelta;
+ SetPosSizePixel( aPos, aSize );
+ }
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ aSize.Width() += nDelta;
+ SetSizePixel( aSize );
+ }
+ else // meAlign == WINDOWALIGN_RIGHT
+ {
+ maDragRect.Left() += nDelta;
+ Point aPos = GetPosPixel();
+ aPos.X() -= nDelta;
+ aSize.Width() += nDelta;
+ SetPosSizePixel( aPos, aSize );
+ }
+
+ SplitResize();
+}
+
+// -----------------------------------------------------------------------
+
+Size SplitWindow::CalcLayoutSizePixel( const Size& aNewSize )
+{
+ Size aSize( aNewSize );
+ long nSplitSize = mpMainSet->mnSplitSize-2;
+
+ if ( mbAutoHide || mbFadeOut )
+ nSplitSize += SPLITWIN_SPLITSIZEEXLN;
+
+ // Wenn Fenster sizeable ist, wird die groesse automatisch nach
+ // dem MainSet festgelegt, wenn kein relatives Fenster enthalten
+ // ist
+ if ( mnWinStyle & WB_SIZEABLE )
+ {
+ long nCurSize;
+ long nCalcSize = 0;
+ USHORT i;
+
+ for ( i = 0; i < mpMainSet->mnItems; i++ )
+ {
+ if ( mpMainSet->mpItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE) )
+ break;
+ else
+ nCalcSize += mpMainSet->mpItems[i].mnSize;
+ }
+
+ if ( i == mpMainSet->mnItems )
+ {
+ long nDelta = 0;
+ Point aPos = GetPosPixel();
+
+ if ( mbHorz )
+ nCurSize = aNewSize.Height()-mnTopBorder-mnBottomBorder;
+ else
+ nCurSize = aNewSize.Width()-mnLeftBorder-mnRightBorder;
+ nCurSize -= nSplitSize;
+ nCurSize -= (mpMainSet->mnItems-1)*mpMainSet->mnSplitSize;
+
+ nDelta = nCalcSize-nCurSize;
+ if ( !nDelta )
+ return aSize;
+
+ if ( meAlign == WINDOWALIGN_TOP )
+ {
+ aSize.Height() += nDelta;
+ }
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ {
+ aPos.Y() -= nDelta;
+ aSize.Height() += nDelta;
+ }
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ aSize.Width() += nDelta;
+ }
+ else // meAlign == WINDOWALIGN_RIGHT
+ {
+ aPos.X() -= nDelta;
+ aSize.Width() += nDelta;
+ }
+ }
+ }
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplCalcLayout()
+{
+ if ( !mbCalc || !mbRecalc || !mpMainSet->mpItems )
+ return;
+
+ long nSplitSize = mpMainSet->mnSplitSize-2;
+ if ( mbAutoHide || mbFadeOut )
+ nSplitSize += SPLITWIN_SPLITSIZEEXLN;
+
+ // Wenn Fenster sizeable ist, wird die groesse automatisch nach
+ // dem MainSet festgelegt, wenn kein relatives Fenster enthalten
+ // ist
+ if ( mnWinStyle & WB_SIZEABLE )
+ {
+ long nCurSize;
+ long nCalcSize = 0;
+ USHORT i;
+
+ for ( i = 0; i < mpMainSet->mnItems; i++ )
+ {
+ if ( mpMainSet->mpItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE) )
+ break;
+ else
+ nCalcSize += mpMainSet->mpItems[i].mnSize;
+ }
+
+ if ( i == mpMainSet->mnItems )
+ {
+ if ( mbHorz )
+ nCurSize = mnDY-mnTopBorder-mnBottomBorder;
+ else
+ nCurSize = mnDX-mnLeftBorder-mnRightBorder;
+ nCurSize -= nSplitSize;
+ nCurSize -= (mpMainSet->mnItems-1)*mpMainSet->mnSplitSize;
+
+ mbRecalc = FALSE;
+ ImplSetWindowSize( nCalcSize-nCurSize );
+ mbRecalc = TRUE;
+ }
+ }
+
+ if ( (mnDX <= 0) || (mnDY <= 0) )
+ return;
+
+ // Groessen/Position vorberechnen
+ long nL;
+ long nT;
+ long nW;
+ long nH;
+
+ if ( mbHorz )
+ {
+ if ( mbBottomRight )
+ nT = mnDY-mnBottomBorder;
+ else
+ nT = mnTopBorder;
+ nL = mnLeftBorder;
+ }
+ else
+ {
+ if ( mbBottomRight )
+ nL = mnDX-mnRightBorder;
+ else
+ nL = mnLeftBorder;
+ nT = mnTopBorder;
+ }
+ nW = mnDX-mnLeftBorder-mnRightBorder;
+ nH = mnDY-mnTopBorder-mnBottomBorder;
+ if ( mnWinStyle & WB_SIZEABLE )
+ {
+ if ( mbHorz )
+ nH -= nSplitSize;
+ else
+ nW -= nSplitSize;
+ }
+
+ // Sets rekursiv berechnen
+ ImplCalcSet( mpMainSet, nL, nT, nW, nH, mbHorz, !mbBottomRight );
+ ImplCalcSet2( this, mpMainSet, FALSE, mbHorz, !mbBottomRight );
+ mbCalc = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplUpdate()
+{
+ mbCalc = TRUE;
+
+ if ( IsReallyShown() && IsUpdateMode() && mbRecalc )
+ {
+ if ( mpMainSet->mpItems )
+ ImplCalcLayout();
+ else
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplUpdateSet( ImplSplitSet* pSet )
+{
+ if ( IsReallyShown() && IsUpdateMode() && mbRecalc )
+ {
+ // Wenn wir noch berechnen muessen, dann alles invalidieren.
+ if ( mbCalc )
+ {
+ // Wenn nicht NOSPLITDRAW gesetzt ist, koennen wir uns das
+ // invalidieren sparen, da bei ImplCalcSet2() die freien flaechen
+ // sowieso invalidiert werden
+ if ( !mpMainSet->mpItems || (mnWinStyle & WB_NOSPLITDRAW) )
+ pSet = mpMainSet;
+ else
+ return;
+ }
+
+ Rectangle aRect;
+ if ( pSet == mpMainSet )
+ {
+ aRect.Left() = mnLeftBorder;
+ aRect.Top() = mnTopBorder;
+ aRect.Right() = mnDX-mnRightBorder-1;
+ aRect.Bottom() = mnDY-mnBottomBorder-1;
+ }
+ else
+ {
+ ImplSplitItem* pItem;
+ USHORT nPos;
+
+ pSet = ImplFindItem( mpMainSet, pSet->mnId, nPos );
+ pItem = &(pSet->mpItems[nPos]);
+ aRect.Left() = pItem->mnLeft;
+ aRect.Top() = pItem->mnTop;
+ aRect.Right() = aRect.Left()+pItem->mnWidth;
+ aRect.Bottom() = aRect.Top()+pItem->mnHeight;
+ }
+ Invalidate( aRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplSplitMousePos( Point& rMousePos )
+{
+ if ( mnSplitTest & SPLIT_HORZ )
+ {
+ rMousePos.X() -= mnMouseOff;
+ if ( rMousePos.X() < maDragRect.Left() )
+ rMousePos.X() = maDragRect.Left();
+ else if ( rMousePos.X()+mpSplitSet->mnSplitSize+1 > maDragRect.Right() )
+ rMousePos.X() = maDragRect.Right()-mpSplitSet->mnSplitSize+1;
+ // Wegen FullDrag in Screen-Koordinaaten merken
+ mnMSplitPos = OutputToScreenPixel( rMousePos ).X();
+ }
+ else
+ {
+ rMousePos.Y() -= mnMouseOff;
+ if ( rMousePos.Y() < maDragRect.Top() )
+ rMousePos.Y() = maDragRect.Top();
+ else if ( rMousePos.Y()+mpSplitSet->mnSplitSize+1 > maDragRect.Bottom() )
+ rMousePos.Y() = maDragRect.Bottom()-mpSplitSet->mnSplitSize+1;
+ mnMSplitPos = OutputToScreenPixel( rMousePos ).Y();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplGetButtonRect( Rectangle& rRect, long nEx, BOOL bTest ) const
+{
+ long nSplitSize = mpMainSet->mnSplitSize-2;
+ if ( mbAutoHide || mbFadeOut || mbFadeIn )
+ nSplitSize += SPLITWIN_SPLITSIZEEX;
+
+ long nButtonSize = 0;
+ if ( mbFadeIn )
+ nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
+ if ( mbFadeOut )
+ nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
+ if ( mbAutoHide )
+ nButtonSize += SPLITWIN_SPLITSIZEAUTOHIDE+1;
+ long nCenterEx = 0;
+ if ( mbHorz )
+ nCenterEx += ((mnDX-mnLeftBorder-mnRightBorder)-nButtonSize)/2;
+ else
+ nCenterEx += ((mnDY-mnTopBorder-mnBottomBorder)-nButtonSize)/2;
+ if ( nCenterEx > 0 )
+ nEx += nCenterEx;
+
+ if ( meAlign == WINDOWALIGN_TOP )
+ {
+ rRect.Left() = mnLeftBorder+nEx;
+ rRect.Top() = mnDY-mnBottomBorder-nSplitSize;
+ rRect.Right() = rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE;
+ rRect.Bottom() = mnDY-mnBottomBorder-1;
+ if ( bTest )
+ {
+ rRect.Top() -= mnTopBorder;
+ rRect.Bottom() += mnBottomBorder;
+ }
+ }
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ {
+ rRect.Left() = mnLeftBorder+nEx;
+ rRect.Top() = mnTopBorder;
+ rRect.Right() = rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE;
+ rRect.Bottom() = mnTopBorder+nSplitSize-1;
+ if ( bTest )
+ {
+ rRect.Top() -= mnTopBorder;
+ rRect.Bottom() += mnBottomBorder;
+ }
+ }
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ rRect.Left() = mnDX-mnRightBorder-nSplitSize;
+ rRect.Top() = mnTopBorder+nEx;
+ rRect.Right() = mnDX-mnRightBorder-1;
+ rRect.Bottom() = rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE;
+ if ( bTest )
+ {
+ rRect.Left() -= mnLeftBorder;
+ rRect.Right() += mnRightBorder;
+ }
+ }
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ {
+ rRect.Left() = mnLeftBorder;
+ rRect.Top() = mnTopBorder+nEx;
+ rRect.Right() = mnLeftBorder+nSplitSize-1;
+ rRect.Bottom() = rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE;
+ if ( bTest )
+ {
+ rRect.Left() -= mnLeftBorder;
+ rRect.Right() += mnRightBorder;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplGetAutoHideRect( Rectangle& rRect, BOOL bTest ) const
+{
+ Rectangle aRect;
+
+ if ( mbAutoHide )
+ {
+ long nEx = 0;
+ if ( mbFadeIn || mbFadeOut )
+ nEx = SPLITWIN_SPLITSIZEFADE+1;
+ ImplGetButtonRect( aRect, nEx, bTest && mbFadeIn );
+ }
+
+ rRect = aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplGetFadeInRect( Rectangle& rRect, BOOL bTest ) const
+{
+ Rectangle aRect;
+
+ if ( mbFadeIn )
+ ImplGetButtonRect( aRect, 0, bTest );
+
+ rRect = aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplGetFadeOutRect( Rectangle& rRect, BOOL ) const
+{
+ Rectangle aRect;
+
+ if ( mbFadeOut )
+ ImplGetButtonRect( aRect, 0, FALSE );
+
+ rRect = aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawButtonRect( const Rectangle& rRect, long nSize )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( mbHorz )
+ {
+ long nLeft = rRect.Left();
+ long nRight = rRect.Right();
+ long nCenter = rRect.Center().Y();
+ long nEx1 = nLeft+((rRect.GetWidth()-nSize)/2)-2;
+ long nEx2 = nEx1+nSize+3;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Left(), rRect.Bottom() ) );
+ DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Right(), rRect.Top() ) );
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( rRect.Right(), rRect.Top() ), Point( rRect.Right(), rRect.Bottom() ) );
+ DrawLine( Point( rRect.Left(), rRect.Bottom() ), Point( rRect.Right(), rRect.Bottom() ) );
+ long i = nLeft+2;
+ while ( i < nRight-3 )
+ {
+ if ( (i < nEx1) || (i > nEx2 ) )
+ {
+ DrawPixel( Point( i, nCenter-2 ), rStyleSettings.GetLightColor() );
+ DrawPixel( Point( i+1, nCenter-2+1 ), rStyleSettings.GetShadowColor() );
+ }
+ i++;
+ if ( (i < nEx1) || ((i > nEx2 ) && (i < nRight-3)) )
+ {
+ DrawPixel( Point( i, nCenter+2 ), rStyleSettings.GetLightColor() );
+ DrawPixel( Point( i+1, nCenter+2+1 ), rStyleSettings.GetShadowColor() );
+ }
+ i += 2;
+ }
+ }
+ else
+ {
+ long nTop = rRect.Top();
+ long nBottom = rRect.Bottom();
+ long nCenter = rRect.Center().X();
+ long nEx1 = nTop+((rRect.GetHeight()-nSize)/2)-2;
+ long nEx2 = nEx1+nSize+3;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Right(), rRect.Top() ) );
+ DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Left(), rRect.Bottom() ) );
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( rRect.Right(), rRect.Top() ), Point( rRect.Right(), rRect.Bottom() ) );
+ DrawLine( Point( rRect.Left(), rRect.Bottom() ), Point( rRect.Right(), rRect.Bottom() ) );
+ long i = nTop+2;
+ while ( i < nBottom-3 )
+ {
+ if ( (i < nEx1) || (i > nEx2 ) )
+ {
+ DrawPixel( Point( nCenter-2, i ), rStyleSettings.GetLightColor() );
+ DrawPixel( Point( nCenter-2+1, i+1 ), rStyleSettings.GetShadowColor() );
+ }
+ i++;
+ if ( (i < nEx1) || ((i > nEx2 ) && (i < nBottom-3)) )
+ {
+ DrawPixel( Point( nCenter+2, i ), rStyleSettings.GetLightColor() );
+ DrawPixel( Point( nCenter+2+1, i+1 ), rStyleSettings.GetShadowColor() );
+ }
+ i += 2;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawAutoHide( BOOL bInPaint )
+{
+ if ( mbAutoHide )
+ {
+ Rectangle aTempRect;
+ ImplGetAutoHideRect( aTempRect );
+
+ if ( !bInPaint )
+ Erase( aTempRect );
+
+ // ImageListe laden, wenn noch nicht vorhanden
+ ImplSVData* pSVData = ImplGetSVData();
+ ImageList* pImageList;
+ if ( mbHorz )
+ {
+ if ( !pSVData->maCtrlData.mpSplitHPinImgList )
+ {
+ ResMgr* pResMgr = ImplGetResMgr();
+ if( pResMgr )
+ {
+ Color aNonAlphaMask( 0x00, 0x00, 0xFF );
+ pSVData->maCtrlData.mpSplitHPinImgList = new ImageList(4);
+ pSVData->maCtrlData.mpSplitHPinImgList->InsertFromHorizontalBitmap
+ ( ResId( SV_RESID_BITMAP_SPLITHPIN, *pResMgr ), 4, &aNonAlphaMask );
+ }
+ }
+ pImageList = pSVData->maCtrlData.mpSplitHPinImgList;
+ }
+ else
+ {
+ if ( !pSVData->maCtrlData.mpSplitVPinImgList )
+ {
+ ResMgr* pResMgr = ImplGetResMgr();
+ pSVData->maCtrlData.mpSplitVPinImgList = new ImageList(4);
+ if( pResMgr )
+ {
+ Color aNonAlphaMask( 0x00, 0x00, 0xFF );
+ pSVData->maCtrlData.mpSplitVPinImgList->InsertFromHorizontalBitmap
+ ( ResId( SV_RESID_BITMAP_SPLITVPIN, *pResMgr ), 4, &aNonAlphaMask );
+ }
+ }
+ pImageList = pSVData->maCtrlData.mpSplitVPinImgList;
+ }
+
+ // Image ermitteln und zurueckgeben
+ USHORT nId;
+ if ( mbAutoHidePressed )
+ {
+ if ( mbAutoHideIn )
+ nId = 3;
+ else
+ nId = 4;
+ }
+ else
+ {
+ if ( mbAutoHideIn )
+ nId = 1;
+ else
+ nId = 2;
+ }
+
+ Image aImage = pImageList->GetImage( nId );
+ Size aImageSize = aImage.GetSizePixel();
+ Point aPos( aTempRect.Left()+((aTempRect.GetWidth()-aImageSize.Width())/2),
+ aTempRect.Top()+((aTempRect.GetHeight()-aImageSize.Height())/2) );
+ long nSize;
+ if ( mbHorz )
+ nSize = aImageSize.Width();
+ else
+ nSize = aImageSize.Height();
+ ImplDrawButtonRect( aTempRect, nSize );
+ DrawImage( aPos, aImage );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawFadeArrow( const Point& rPt, BOOL bHorz, BOOL bLeft )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ int x( rPt.X() );
+ int y( rPt.Y() );
+
+ Color aCol;
+ if( !bHorz )
+ {
+ int dx = 1;
+ if( bLeft )
+ {
+ x ++;
+ dx = -1;
+ }
+
+ x++; y++;
+ aCol = Color( COL_WHITE );
+ DrawPixel( Point(x, y), aCol );
+ DrawPixel( Point(x, y+1), aCol );
+ DrawPixel( Point(x, y+2), aCol );
+ DrawPixel( Point(x+dx, y+1), aCol );
+
+ x--; y--;
+ aCol = rStyleSettings.GetDarkShadowColor();
+ DrawPixel( Point(x, y), rStyleSettings.GetDarkShadowColor() );
+ DrawPixel( Point(x, y+1), rStyleSettings.GetDarkShadowColor() );
+ DrawPixel( Point(x, y+2), rStyleSettings.GetDarkShadowColor() );
+ DrawPixel( Point(x+dx, y+1), rStyleSettings.GetDarkShadowColor() );
+ }
+ else
+ {
+ int dy = 1;
+ if( bLeft )
+ {
+ y ++;
+ dy = -1;
+ }
+
+ x++; y++;
+ aCol = Color( COL_WHITE );
+ DrawPixel( Point(x, y), aCol );
+ DrawPixel( Point(x+1, y), aCol );
+ DrawPixel( Point(x+2, y), aCol );
+ DrawPixel( Point(x+1, y+dy), aCol );
+
+ x--; y--;
+ aCol = rStyleSettings.GetDarkShadowColor();
+ DrawPixel( Point(x, y), aCol );
+ DrawPixel( Point(x+1, y), aCol );
+ DrawPixel( Point(x+2, y), aCol );
+ DrawPixel( Point(x+1, y+dy), aCol );
+ }
+}
+
+void SplitWindow::ImplDrawGrip( const Rectangle& rRect, BOOL bHorz, BOOL bLeft )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if( rRect.IsInside( GetPointerPosPixel() ) )
+ {
+ DrawWallpaper( rRect, Wallpaper( Color( COL_WHITE ) ) );
+ DrawSelectionBackground( rRect, 2, FALSE, FALSE, FALSE );
+ }
+
+ if( bHorz )
+ {
+ int width = (int) (0.5 * rRect.getWidth() + 0.5);
+ int i = rRect.nLeft + (rRect.getWidth() - width) / 2;
+ width += i;
+ const int y = rRect.nTop + 1;
+ ImplDrawFadeArrow( Point( i-8, y), bHorz, bLeft );
+ while( i <= width )
+ {
+
+ DrawPixel( Point(i, y), rStyleSettings.GetDarkShadowColor() );
+ DrawPixel( Point(i+1, y), rStyleSettings.GetShadowColor() );
+
+ DrawPixel( Point(i, y+1), rStyleSettings.GetShadowColor() );
+ DrawPixel( Point(i+1, y+1), rStyleSettings.GetFaceColor() );
+ DrawPixel( Point(i+2, y+1), Color(COL_WHITE) );
+
+ DrawPixel( Point(i+1, y+2), Color(COL_WHITE) );
+ DrawPixel( Point(i+2, y+2), Color(COL_WHITE) );
+ i+=4;
+ }
+ ImplDrawFadeArrow( Point( i+3, y), bHorz, bLeft );
+ }
+ else
+ {
+ int height = (int) (0.5 * rRect.getHeight() + 0.5);
+ int i = rRect.nTop + (rRect.getHeight() - height) / 2;
+ height += i;
+ const int x = rRect.nLeft + 1;
+ ImplDrawFadeArrow( Point( x, i-8), bHorz, bLeft );
+ while( i <= height )
+ {
+
+ DrawPixel( Point(x, i), rStyleSettings.GetDarkShadowColor() );
+ DrawPixel( Point(x+1, i), rStyleSettings.GetShadowColor() );
+
+ DrawPixel( Point(x, i+1), rStyleSettings.GetShadowColor() );
+ DrawPixel( Point(x+1, i+1), rStyleSettings.GetFaceColor() );
+ DrawPixel( Point(x+2, i+1), Color(COL_WHITE) );
+
+ DrawPixel( Point(x+1, i+2), Color(COL_WHITE) );
+ DrawPixel( Point(x+2, i+2), Color(COL_WHITE) );
+ i+=4;
+ }
+ ImplDrawFadeArrow( Point( x, i+3), bHorz, bLeft );
+ }
+}
+
+void SplitWindow::ImplDrawFadeIn( BOOL bInPaint )
+{
+ if ( mbFadeIn )
+ {
+ Rectangle aTempRect;
+ Image aImage;
+ ImplGetFadeInRect( aTempRect );
+
+ BOOL bLeft;
+ if ( meAlign == WINDOWALIGN_TOP )
+ bLeft = FALSE;
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ bLeft = TRUE;
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ bLeft = FALSE;
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ bLeft = TRUE;
+ else
+ bLeft = TRUE;
+
+ if ( !bInPaint )
+ Erase( aTempRect );
+
+ ImplDrawGrip( aTempRect, (meAlign == WINDOWALIGN_TOP) || (meAlign == WINDOWALIGN_BOTTOM), bLeft );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawFadeOut( BOOL bInPaint )
+{
+ if ( mbFadeOut )
+ {
+ Rectangle aTempRect;
+ Image aImage;
+ ImplGetFadeOutRect( aTempRect );
+
+ BOOL bLeft;
+ if ( meAlign == WINDOWALIGN_TOP )
+ bLeft = TRUE;
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ bLeft = FALSE;
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ bLeft = TRUE;
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ bLeft = FALSE;
+ else
+ bLeft = TRUE;
+
+ if ( !bInPaint )
+ Erase( aTempRect );
+
+ ImplDrawGrip( aTempRect, (meAlign == WINDOWALIGN_TOP) || (meAlign == WINDOWALIGN_BOTTOM), bLeft );
+ }
+}
+
+// -----------------------------------------------------------------------
+void SplitWindow::ImplStartSplit( const MouseEvent& rMEvt )
+{
+ Point aMousePosPixel = rMEvt.GetPosPixel();
+ mnSplitTest = ImplTestSplit( this, aMousePosPixel, mnMouseOff, &mpSplitSet, mnSplitPos );
+
+ if ( mnSplitTest && !(mnSplitTest & SPLIT_NOSPLIT) )
+ {
+ ImplSplitItem* pSplitItem;
+ long nCurMaxSize;
+ USHORT nTemp;
+ BOOL bDown;
+ BOOL bPropSmaller;
+
+ mnMouseModifier = rMEvt.GetModifier();
+ if ( !(mnMouseModifier & KEY_SHIFT) || (mnSplitPos+1 >= mpSplitSet->mnItems) )
+ bPropSmaller = FALSE;
+ else
+ bPropSmaller = TRUE;
+
+ // Hier kann noch die maximale Groesse gesetzt werden
+ StartSplit();
+
+ if ( mnMaxSize )
+ nCurMaxSize = mnMaxSize;
+ else
+ {
+ Size aSize = GetParent()->GetOutputSizePixel();
+ if ( mbHorz )
+ nCurMaxSize = aSize.Height();
+ else
+ nCurMaxSize = aSize.Width();
+ }
+
+ if ( mpSplitSet->mpItems )
+ {
+ bDown = TRUE;
+ if ( (mpSplitSet == mpMainSet) && mbBottomRight )
+ bDown = FALSE;
+
+ pSplitItem = &(mpSplitSet->mpItems[mnSplitPos]);
+ maDragRect.Left() = pSplitItem->mnLeft;
+ maDragRect.Top() = pSplitItem->mnTop;
+ maDragRect.Right() = pSplitItem->mnLeft+pSplitItem->mnWidth-1;
+ maDragRect.Bottom() = pSplitItem->mnTop+pSplitItem->mnHeight-1;
+
+ if ( mnSplitTest & SPLIT_HORZ )
+ {
+ if ( bDown )
+ maDragRect.Right() += mpSplitSet->mnSplitSize;
+ else
+ maDragRect.Left() -= mpSplitSet->mnSplitSize;
+ }
+ else
+ {
+ if ( bDown )
+ maDragRect.Bottom() += mpSplitSet->mnSplitSize;
+ else
+ maDragRect.Top() -= mpSplitSet->mnSplitSize;
+ }
+
+ if ( mnSplitPos )
+ {
+ nTemp = mnSplitPos;
+ while ( nTemp )
+ {
+ pSplitItem = &(mpSplitSet->mpItems[nTemp-1]);
+ if ( pSplitItem->mbFixed )
+ break;
+ else
+ {
+ if ( mnSplitTest & SPLIT_HORZ )
+ {
+ if ( bDown )
+ maDragRect.Left() -= pSplitItem->mnPixSize;
+ else
+ maDragRect.Right() += pSplitItem->mnPixSize;
+ }
+ else
+ {
+ if ( bDown )
+ maDragRect.Top() -= pSplitItem->mnPixSize;
+ else
+ maDragRect.Bottom() += pSplitItem->mnPixSize;
+ }
+ }
+ nTemp--;
+ }
+ }
+
+ if ( (mpSplitSet == mpMainSet) && (mnWinStyle & WB_SIZEABLE) && !bPropSmaller )
+ {
+ if ( bDown )
+ {
+ if ( mbHorz )
+ maDragRect.Bottom() += nCurMaxSize-mnDY-mnTopBorder;
+ else
+ maDragRect.Right() += nCurMaxSize-mnDX-mnLeftBorder;
+ }
+ else
+ {
+ if ( mbHorz )
+ maDragRect.Top() -= nCurMaxSize-mnDY-mnBottomBorder;
+ else
+ maDragRect.Left() -= nCurMaxSize-mnDX-mnRightBorder;
+ }
+ }
+ else
+ {
+ nTemp = mnSplitPos+1;
+ while ( nTemp < mpSplitSet->mnItems )
+ {
+ pSplitItem = &(mpSplitSet->mpItems[nTemp]);
+ if ( pSplitItem->mbFixed )
+ break;
+ else
+ {
+ if ( mnSplitTest & SPLIT_HORZ )
+ {
+ if ( bDown )
+ maDragRect.Right() += pSplitItem->mnPixSize;
+ else
+ maDragRect.Left() -= pSplitItem->mnPixSize;
+ }
+ else
+ {
+ if ( bDown )
+ maDragRect.Bottom() += pSplitItem->mnPixSize;
+ else
+ maDragRect.Top() -= pSplitItem->mnPixSize;
+ }
+ }
+ nTemp++;
+ }
+ }
+ }
+ else
+ {
+ maDragRect.Left() = mnLeftBorder;
+ maDragRect.Top() = mnTopBorder;
+ maDragRect.Right() = mnDX-mnRightBorder-1;
+ maDragRect.Bottom() = mnDY-mnBottomBorder-1;
+ if ( mbHorz )
+ {
+ if ( mbBottomRight )
+ maDragRect.Top() -= nCurMaxSize-mnDY-mnBottomBorder;
+ else
+ maDragRect.Bottom() += nCurMaxSize-mnDY-mnTopBorder;
+ }
+ else
+ {
+ if ( mbBottomRight )
+ maDragRect.Left() -= nCurMaxSize-mnDX-mnRightBorder;
+ else
+ maDragRect.Right() += nCurMaxSize-mnDX-mnLeftBorder;
+ }
+ }
+
+ StartTracking();
+
+ mbDragFull = (GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SPLIT) != 0;
+
+ ImplSplitMousePos( aMousePosPixel );
+
+ if ( !mbDragFull )
+ ImplDrawSplitTracking( this, aMousePosPixel );
+ else
+ {
+ ImplSplitItem* pItems = mpSplitSet->mpItems;
+ USHORT nItems = mpSplitSet->mnItems;
+ mpLastSizes = new long[nItems*2];
+ for ( USHORT i = 0; i < nItems; i++ )
+ {
+ mpLastSizes[i*2] = pItems[i].mnSize;
+ mpLastSizes[i*2+1] = pItems[i].mnPixSize;
+ }
+ }
+ mnMStartPos = mnMSplitPos;
+
+ PointerStyle eStyle = POINTER_ARROW;
+ if ( mnSplitTest & SPLIT_HORZ )
+ eStyle = POINTER_HSPLIT;
+ else if ( mnSplitTest & SPLIT_VERT )
+ eStyle = POINTER_VSPLIT;
+
+ Pointer aPtr( eStyle );
+ SetPointer( aPtr );
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::StartSplit()
+{
+ maStartSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Split()
+{
+ maSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SplitResize()
+{
+ maSplitResizeHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::AutoHide()
+{
+ maAutoHideHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::FadeIn()
+{
+ maFadeInHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::FadeOut()
+{
+ maFadeOutHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( !rMEvt.IsLeft() || rMEvt.IsMod2() )
+ {
+ DockingWindow::MouseButtonDown( rMEvt );
+ return;
+ }
+
+ Point aMousePosPixel = rMEvt.GetPosPixel();
+ Rectangle aTestRect;
+
+ mbFadeNoButtonMode = FALSE;
+ ImplGetAutoHideRect( aTestRect, TRUE );
+ if ( aTestRect.IsInside( aMousePosPixel ) )
+ {
+ mbAutoHideDown = TRUE;
+ mbAutoHidePressed = TRUE;
+ ImplDrawAutoHide( FALSE );
+ }
+ else
+ {
+ ImplGetFadeOutRect( aTestRect, TRUE );
+ if ( aTestRect.IsInside( aMousePosPixel ) )
+ {
+ mbFadeOutDown = TRUE;
+ mbFadeOutPressed = TRUE;
+ ImplDrawFadeOut( FALSE );
+ }
+ else
+ {
+ ImplGetFadeInRect( aTestRect, TRUE );
+ if ( aTestRect.IsInside( aMousePosPixel ) )
+ {
+ mbFadeInDown = TRUE;
+ mbFadeInPressed = TRUE;
+ ImplDrawFadeIn( FALSE );
+ }
+ else if ( !aTestRect.IsEmpty() && !(mnWinStyle & WB_SIZEABLE) )
+ {
+ mbFadeNoButtonMode = TRUE;
+ FadeIn();
+ return;
+ }
+ }
+ }
+
+ if ( mbAutoHideDown || mbFadeInDown || mbFadeOutDown )
+ StartTracking();
+ else
+ ImplStartSplit( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( !IsTracking() )
+ {
+ Point aPos = rMEvt.GetPosPixel();
+ long nTemp;
+ ImplSplitSet* pTempSplitSet;
+ USHORT nTempSplitPos;
+ USHORT nSplitTest = ImplTestSplit( this, aPos, nTemp, &pTempSplitSet, nTempSplitPos );
+ PointerStyle eStyle = POINTER_ARROW;
+ Rectangle aAutoHideRect;
+ Rectangle aFadeInRect;
+ Rectangle aFadeOutRect;
+
+ ImplGetAutoHideRect( aAutoHideRect );
+ ImplGetFadeInRect( aFadeInRect );
+ ImplGetFadeOutRect( aFadeOutRect );
+ if ( !aAutoHideRect.IsInside( aPos ) &&
+ !aFadeInRect.IsInside( aPos ) &&
+ !aFadeOutRect.IsInside( aPos ) )
+ {
+ if ( nSplitTest && !(nSplitTest & SPLIT_NOSPLIT) )
+ {
+ if ( nSplitTest & SPLIT_HORZ )
+ eStyle = POINTER_HSPLIT;
+ else if ( nSplitTest & SPLIT_VERT )
+ eStyle = POINTER_VSPLIT;
+ }
+ }
+
+ Pointer aPtr( eStyle );
+ SetPointer( aPtr );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Tracking( const TrackingEvent& rTEvt )
+{
+ Point aMousePosPixel = rTEvt.GetMouseEvent().GetPosPixel();
+
+ if ( mbAutoHideDown )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbAutoHideDown = FALSE;
+ if ( mbAutoHidePressed )
+ {
+ mbAutoHidePressed = FALSE;
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ mbAutoHideIn = !mbAutoHideIn;
+ ImplDrawAutoHide( FALSE );
+ AutoHide();
+ }
+ else
+ ImplDrawAutoHide( FALSE );
+ }
+ }
+ else
+ {
+ Rectangle aTestRect;
+ ImplGetAutoHideRect( aTestRect, TRUE );
+ BOOL bNewPressed = aTestRect.IsInside( aMousePosPixel );
+ if ( bNewPressed != mbAutoHidePressed )
+ {
+ mbAutoHidePressed = bNewPressed;
+ ImplDrawAutoHide( FALSE );
+ }
+ }
+ }
+ else if ( mbFadeInDown )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbFadeInDown = FALSE;
+ if ( mbFadeInPressed )
+ {
+ mbFadeInPressed = FALSE;
+ ImplDrawFadeIn( FALSE );
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ FadeIn();
+ }
+ }
+ else
+ {
+ Rectangle aTestRect;
+ ImplGetFadeInRect( aTestRect, TRUE );
+ BOOL bNewPressed = aTestRect.IsInside( aMousePosPixel );
+ if ( bNewPressed != mbFadeInPressed )
+ {
+ mbFadeInPressed = bNewPressed;
+ ImplDrawFadeIn( FALSE );
+ }
+ }
+ }
+ else if ( mbFadeOutDown )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbFadeOutDown = FALSE;
+ if ( mbFadeOutPressed )
+ {
+ mbFadeOutPressed = FALSE;
+ ImplDrawFadeOut( FALSE );
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ FadeOut();
+ }
+ }
+ else
+ {
+ Rectangle aTestRect;
+ ImplGetFadeOutRect( aTestRect, TRUE );
+ BOOL bNewPressed = aTestRect.IsInside( aMousePosPixel );
+ if ( bNewPressed == FALSE )
+ {
+ mbFadeOutPressed = bNewPressed;
+ ImplDrawFadeOut( FALSE );
+
+ // We need a mouseevent with a position inside the button for the
+ // ImplStartSplit function!
+ MouseEvent aOrgMEvt = rTEvt.GetMouseEvent();
+ MouseEvent aNewMEvt = MouseEvent( aTestRect.Center(), aOrgMEvt.GetClicks(),
+ aOrgMEvt.GetMode(), aOrgMEvt.GetButtons(),
+ aOrgMEvt.GetModifier() );
+
+ ImplStartSplit( aNewMEvt );
+ mbFadeOutDown = FALSE;
+ }
+ }
+ }
+ else
+ {
+ ImplSplitMousePos( aMousePosPixel );
+ BOOL bSplit = TRUE;
+ if ( mbDragFull )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ ImplSplitItem* pItems = mpSplitSet->mpItems;
+ USHORT nItems = mpSplitSet->mnItems;
+ for ( USHORT i = 0; i < nItems; i++ )
+ {
+ pItems[i].mnSize = mpLastSizes[i*2];
+ pItems[i].mnPixSize = mpLastSizes[i*2+1];
+ }
+ ImplUpdate();
+ Split();
+ }
+ bSplit = FALSE;
+ }
+ }
+ else
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ HideTracking();
+ bSplit = !rTEvt.IsTrackingCanceled();
+ }
+ else
+ {
+ ImplDrawSplitTracking( this, aMousePosPixel );
+ bSplit = FALSE;
+ }
+ }
+
+ if ( bSplit )
+ {
+ BOOL bPropSmaller = (mnMouseModifier & KEY_SHIFT) ? TRUE : FALSE;
+ BOOL bPropGreater = (mnMouseModifier & KEY_MOD1) ? TRUE : FALSE;
+ long nDelta = mnMSplitPos-mnMStartPos;
+
+ if ( (mnSplitTest & SPLIT_WINDOW) && !mpMainSet->mpItems )
+ {
+ if ( (mpSplitSet == mpMainSet) && mbBottomRight )
+ nDelta *= -1;
+ ImplSetWindowSize( nDelta );
+ }
+ else
+ {
+ long nNewSize = mpSplitSet->mpItems[mnSplitPos].mnPixSize;
+ if ( (mpSplitSet == mpMainSet) && mbBottomRight )
+ nNewSize -= nDelta;
+ else
+ nNewSize += nDelta;
+ SplitItem( mpSplitSet->mpItems[mnSplitPos].mnId, nNewSize,
+ bPropSmaller, bPropGreater );
+ }
+
+ Split();
+
+ if ( mbDragFull )
+ {
+ Update();
+ mnMStartPos = mnMSplitPos;
+ }
+ }
+
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( mpLastSizes )
+ delete mpLastSizes;
+ mpLastSizes = NULL;
+ mpSplitSet = NULL;
+ mnMouseOff = 0;
+ mnMStartPos = 0;
+ mnMSplitPos = 0;
+ mnMouseModifier = 0;
+ mnSplitTest = 0;
+ mnSplitPos = 0;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::PreNotify( NotifyEvent& rNEvt )
+{
+ const MouseEvent* pMouseEvt = NULL;
+
+ if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
+ {
+ if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
+ {
+ // trigger redraw if mouse over state has changed
+ Rectangle aFadeInRect;
+ Rectangle aFadeOutRect;
+ ImplGetFadeInRect( aFadeInRect );
+ ImplGetFadeOutRect( aFadeOutRect );
+
+ if ( aFadeInRect.IsInside( GetPointerPosPixel() ) != aFadeInRect.IsInside( GetLastPointerPosPixel() ) )
+ Invalidate( aFadeInRect );
+ if ( aFadeOutRect.IsInside( GetPointerPosPixel() ) != aFadeOutRect.IsInside( GetLastPointerPosPixel() ) )
+ Invalidate( aFadeOutRect );
+
+ if( pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
+ {
+ Invalidate( aFadeInRect );
+ Invalidate( aFadeOutRect );
+ }
+ }
+ }
+ return Window::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Paint( const Rectangle& )
+{
+ if ( mnWinStyle & WB_BORDER )
+ ImplDrawBorder( this );
+
+ ImplDrawBorderLine( this );
+ ImplDrawFadeOut( TRUE );
+ ImplDrawFadeIn( TRUE );
+ ImplDrawAutoHide( TRUE );
+
+ // FrameSet-Hintergruende zeichnen
+ ImplDrawBack( this, mpMainSet );
+
+ // Splitter zeichnen
+ if ( !(mnWinStyle & WB_NOSPLITDRAW) )
+ ImplDrawSplit( this, mpMainSet, mbHorz, !mbBottomRight );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Move()
+{
+ DockingWindow::Move();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Resize()
+{
+ Size aSize = GetOutputSizePixel();
+ mnDX = aSize.Width();
+ mnDY = aSize.Height();
+
+ ImplUpdate();
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ // no keyboard help for splitwin
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) && !rHEvt.KeyboardActivated() )
+ {
+ Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
+ Rectangle aHelpRect;
+ USHORT nHelpResId = 0;
+
+ ImplGetAutoHideRect( aHelpRect, TRUE );
+ if ( aHelpRect.IsInside( aMousePosPixel ) )
+ {
+ if ( mbAutoHideIn )
+ nHelpResId = SV_HELPTEXT_SPLITFIXED;
+ else
+ nHelpResId = SV_HELPTEXT_SPLITFLOATING;
+ }
+ else
+ {
+ ImplGetFadeInRect( aHelpRect, TRUE );
+ if ( aHelpRect.IsInside( aMousePosPixel ) )
+ nHelpResId = SV_HELPTEXT_FADEIN;
+ else
+ {
+ ImplGetFadeOutRect( aHelpRect, TRUE );
+ if ( aHelpRect.IsInside( aMousePosPixel ) )
+ nHelpResId = SV_HELPTEXT_FADEOUT;
+ }
+ }
+
+ // Rechteck ermitteln
+ if ( nHelpResId )
+ {
+ Point aPt = OutputToScreenPixel( aHelpRect.TopLeft() );
+ aHelpRect.Left() = aPt.X();
+ aHelpRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aHelpRect.BottomRight() );
+ aHelpRect.Right() = aPt.X();
+ aHelpRect.Bottom() = aPt.Y();
+
+ // Text ermitteln und anzeigen
+ XubString aStr;
+ ResMgr* pResMgr = ImplGetResMgr();
+ if( pResMgr )
+ aStr = XubString( ResId( nHelpResId, *pResMgr ) );
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aStr );
+ else
+ Help::ShowQuickHelp( this, aHelpRect, aStr );
+ return;
+ }
+ }
+
+ DockingWindow::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( IsUpdateMode() )
+ ImplCalcLayout();
+ }
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsUpdateMode() && IsReallyShown() )
+ ImplCalcLayout();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+
+ DockingWindow::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+ else
+ DockingWindow::DataChanged( rDCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::InsertItem( USHORT nId, Window* pWindow, long nSize,
+ USHORT nPos, USHORT nSetId,
+ SplitWindowItemBits nBits )
+{
+#ifdef DBG_UTIL
+ USHORT nDbgDummy;
+ DBG_ASSERT( ImplFindSet( mpMainSet, nSetId ), "SplitWindow::InsertItem() - Set not exists" );
+ DBG_ASSERT( !ImplFindItem( mpMainSet, nId, nDbgDummy ), "SplitWindow::InsertItem() - Id already exists" );
+#endif
+
+ // Size muss min. 1 sein
+ if ( nSize < 1 )
+ nSize = 1;
+
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+ ImplSplitSet* pNewSet;
+ ImplSplitItem* pItem;
+
+ // Platz fuer neues Item schaffen
+ if ( nPos > pSet->mnItems )
+ nPos = pSet->mnItems;
+ ImplSplitItem* pNewItems = new ImplSplitItem[pSet->mnItems+1];
+ if ( nPos )
+ memcpy( pNewItems, pSet->mpItems, sizeof( ImplSplitItem )*nPos );
+ if ( nPos < pSet->mnItems )
+ memcpy( pNewItems+nPos+1, pSet->mpItems+nPos, sizeof( ImplSplitItem )*(pSet->mnItems-nPos) );
+ delete[] pSet->mpItems;
+ pSet->mpItems = pNewItems;
+ pSet->mnItems++;
+ pSet->mbCalcPix = TRUE;
+
+ // Item anlegen und erweitern
+ pItem = &(pSet->mpItems[nPos]);
+ memset( pItem, 0, sizeof( ImplSplitItem ) );
+ pItem->mnSize = nSize;
+ pItem->mnId = nId;
+ pItem->mnBits = nBits;
+
+ if ( pWindow )
+ {
+ pItem->mpWindow = pWindow;
+ pItem->mpOrgParent = pWindow->GetParent();
+
+ // Window mit SplitWindow verbinden
+ pWindow->Hide();
+ pWindow->SetParent( this );
+ }
+ else
+ {
+ pNewSet = new ImplSplitSet;
+ pNewSet->mpItems = NULL;
+ pNewSet->mpWallpaper = NULL;
+ pNewSet->mpBitmap = NULL;
+ pNewSet->mnLastSize = 0;
+ pNewSet->mnItems = 0;
+ pNewSet->mnId = nId;
+ pNewSet->mnSplitSize = pSet->mnSplitSize;
+ pNewSet->mbCalcPix = TRUE;
+
+ pItem->mpSet = pNewSet;
+ }
+
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::InsertItem( USHORT nId, long nSize,
+ USHORT nPos, USHORT nSetId,
+ SplitWindowItemBits nBits )
+{
+ InsertItem( nId, NULL, nSize, nPos, nSetId, nBits );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::MoveItem( USHORT nId, USHORT nNewPos, USHORT nNewSetId )
+{
+#ifdef DBG_UTIL
+ USHORT nDbgDummy;
+ DBG_ASSERT( ImplFindItem( mpMainSet, nId, nDbgDummy ), "SplitWindow::MoveItem() - Id not found" );
+ DBG_ASSERT( ImplFindSet( mpMainSet, nNewSetId ), "SplitWindow::MoveItem() - Set not exists" );
+#endif
+
+ USHORT nPos;
+ ImplSplitSet* pNewSet = ImplFindSet( mpMainSet, nNewSetId );
+ ImplSplitSet* pSet = ImplFindItem( mpMainSet, nId, nPos );
+ ImplSplitItem aTempItem;
+
+ if ( pNewSet == pSet )
+ {
+ if ( nNewPos >= pNewSet->mnItems )
+ nNewPos = pNewSet->mnItems-1;
+ if ( nPos != nNewPos )
+ {
+ memcpy( &aTempItem, &(pSet->mpItems[nPos]), sizeof( aTempItem ) );
+ if ( nPos < nNewPos )
+ {
+ memmove( pSet->mpItems+nPos, pSet->mpItems+nPos+1,
+ (nNewPos-nPos)*sizeof( ImplSplitItem ) );
+ }
+ else
+ {
+ memmove( pSet->mpItems+nNewPos+1, pSet->mpItems+nNewPos,
+ (nPos-nNewPos)*sizeof( ImplSplitItem ) );
+ }
+ memcpy( &(pSet->mpItems[nNewPos]), &aTempItem, sizeof( aTempItem ) );
+
+ ImplUpdate();
+ }
+ }
+ else
+ {
+ if ( nNewPos >= pNewSet->mnItems )
+ nNewPos = pNewSet->mnItems;
+ memcpy( &aTempItem, &(pSet->mpItems[nPos]), sizeof( aTempItem ) );
+ pSet->mnItems--;
+ pSet->mbCalcPix = TRUE;
+ if ( pSet->mnItems )
+ {
+ memmove( pSet->mpItems+nPos, pSet->mpItems+nPos+1,
+ (pSet->mnItems-nPos)*sizeof( ImplSplitItem ) );
+ }
+ else
+ {
+ delete[] pSet->mpItems;
+ pSet->mpItems = NULL;
+ }
+ ImplSplitItem* pNewItems = new ImplSplitItem[pNewSet->mnItems+1];
+ if ( nNewPos )
+ memcpy( pNewItems, pNewSet->mpItems, sizeof( ImplSplitItem )*nNewPos );
+ if ( nNewPos < pNewSet->mnItems )
+ {
+ memcpy( pNewItems+nNewPos+1, pNewSet->mpItems+nNewPos,
+ sizeof( ImplSplitItem )*(pNewSet->mnItems-nNewPos) );
+ }
+ delete[] pNewSet->mpItems;
+ pNewSet->mpItems = pNewItems;
+ pNewSet->mnItems++;
+ pNewSet->mbCalcPix = TRUE;
+ memcpy( &(pNewSet->mpItems[nNewPos]), &aTempItem, sizeof( aTempItem ) );
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::RemoveItem( USHORT nId, BOOL bHide )
+{
+#ifdef DBG_UTIL
+ USHORT nDbgDummy;
+ DBG_ASSERT( ImplFindItem( mpMainSet, nId, nDbgDummy ), "SplitWindow::RemoveItem() - Id not found" );
+#endif
+
+ // Set suchen
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpMainSet, nId, nPos );
+ ImplSplitItem* pItem = &(pSet->mpItems[nPos]);
+ Window* pWindow = pItem->mpWindow;
+ Window* pOrgParent = pItem->mpOrgParent;
+
+ // Evt. Set loeschen
+ if ( !pWindow )
+ ImplDeleteSet( pItem->mpSet );
+
+ // Item entfernen
+ pSet->mnItems--;
+ pSet->mbCalcPix = TRUE;
+ if ( pSet->mnItems )
+ {
+ memmove( pSet->mpItems+nPos, pSet->mpItems+nPos+1,
+ (pSet->mnItems-nPos)*sizeof( ImplSplitItem ) );
+ }
+ else
+ {
+ delete[] pSet->mpItems;
+ pSet->mpItems = NULL;
+ }
+
+ ImplUpdate();
+
+ // Window erst hier loeschen, um weniger Paints zu haben
+ if ( pWindow )
+ {
+ // Fenster wieder herstellen
+ if ( bHide || (pOrgParent != this) )
+ {
+ pWindow->Hide();
+ pWindow->SetParent( pOrgParent );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Clear()
+{
+ // Alle Sets loeschen
+ ImplDeleteSet( mpMainSet );
+
+ // Main-Set wieder anlegen
+ mpMainSet = new ImplSplitSet;
+ mpMainSet->mpItems = NULL;
+ mpMainSet->mpWallpaper = NULL;
+ mpMainSet->mpBitmap = NULL;
+ mpMainSet->mnLastSize = 0;
+ mpMainSet->mnItems = 0;
+ mpMainSet->mnId = 0;
+ mpMainSet->mnSplitSize = SPLITWIN_SPLITSIZE;
+ mpMainSet->mbCalcPix = TRUE;
+ if ( mnWinStyle & WB_NOSPLITDRAW )
+ mpMainSet->mnSplitSize -= 2;
+ mpBaseSet = mpMainSet;
+
+ // Und neu invalidieren
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetBaseSet( USHORT nSetId )
+{
+ mpBaseSet = ImplFindSet( mpMainSet, nSetId );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetBaseSet() const
+{
+ return mpBaseSet->mnId;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetSplitSize( USHORT nSetId, long nSplitSize,
+ BOOL bWithChilds )
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+ if ( pSet )
+ {
+ if ( bWithChilds )
+ ImplSetSplitSize( pSet, nSplitSize );
+ else
+ pSet->mnSplitSize = nSplitSize;
+ }
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::GetSplitSize( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+ if ( pSet )
+ return pSet->mnSplitSize;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemBackground( USHORT nSetId )
+{
+ Wallpaper aWall;
+ SetItemBackground( nSetId, aWall );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemBackground( USHORT nSetId, const Wallpaper& rWallpaper )
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet )
+ {
+ BOOL bUpdate = TRUE;
+
+ if ( rWallpaper.GetStyle() == WALLPAPER_NULL )
+ {
+ if ( pSet->mpWallpaper )
+ {
+ delete pSet->mpWallpaper;
+ pSet->mpWallpaper = NULL;
+ }
+ else
+ bUpdate = FALSE;
+ }
+ else
+ {
+ // Ab jetzt muss immer invalidiert werden
+ mbInvalidate = TRUE;
+
+ if ( !pSet->mpWallpaper )
+ pSet->mpWallpaper = new Wallpaper( rWallpaper );
+ else
+ *(pSet->mpWallpaper) = rWallpaper;
+ }
+
+ // Beim MainSet koennen wir den Background umsetzen
+ if ( pSet == mpMainSet )
+ ImplInitSettings();
+
+ if ( bUpdate )
+ ImplUpdateSet( pSet );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper SplitWindow::GetItemBackground( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet && pSet->mpWallpaper )
+ return *(pSet->mpWallpaper);
+ else
+ {
+ Wallpaper aWall;
+ return aWall;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SplitWindow::IsItemBackground( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet && pSet->mpWallpaper )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemBitmap( USHORT nSetId, const Bitmap& rBitmap )
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet )
+ {
+ BOOL bUpdate = TRUE;
+
+ if ( !rBitmap )
+ {
+ if ( pSet->mpBitmap )
+ {
+ delete pSet->mpBitmap;
+ pSet->mpBitmap = NULL;
+ }
+ else
+ bUpdate = FALSE;
+ }
+ else
+ {
+ // Ab jetzt muss immer invalidiert werden
+ mbInvalidate = TRUE;
+
+ if ( !pSet->mpBitmap )
+ pSet->mpBitmap = new Bitmap( rBitmap );
+ else
+ *(pSet->mpBitmap) = rBitmap;
+ }
+
+ // Beim MainSet koennen wir den Background umsetzen
+ if ( pSet == mpMainSet )
+ ImplInitSettings();
+
+ if ( bUpdate )
+ ImplUpdateSet( pSet );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap SplitWindow::GetItemBitmap( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet && pSet->mpBitmap )
+ return *(pSet->mpBitmap);
+ else
+ {
+ Bitmap aBitmap;
+ return aBitmap;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SplitItem( USHORT nId, long nNewSize,
+ BOOL bPropSmall, BOOL bPropGreat )
+{
+ USHORT nItems;
+ USHORT nPos;
+ USHORT nMin;
+ USHORT nMax;
+ USHORT i;
+ USHORT n;
+ long nDelta;
+ long nTempDelta;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+ ImplSplitItem* pItems;
+
+ if ( !pSet )
+ return;
+
+ nItems = pSet->mnItems;
+ pItems = pSet->mpItems;
+
+ if ( mbCalc )
+ {
+ pItems[nPos].mnSize = nNewSize;
+ return;
+ }
+
+ nDelta = nNewSize-pItems[nPos].mnPixSize;
+ if ( !nDelta )
+ return;
+
+ // Bereich berechnen, der beim Splitten betroffen sein kann
+ nMin = 0;
+ nMax = nItems;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mbFixed )
+ {
+ if ( i < nPos )
+ nMin = i+1;
+ else
+ nMax = i;
+ }
+ }
+
+ // Wenn das Fenster sizeable ist, wird das TopSet anders behandelt
+ BOOL bSmall = TRUE;
+ BOOL bGreat = TRUE;
+ if ( (pSet == mpMainSet) && (mnWinStyle & WB_SIZEABLE) )
+ {
+ if ( nPos < pSet->mnItems-1 )
+ {
+ if ( !((bPropSmall && bPropGreat) ||
+ ((nDelta > 0) && bPropSmall) ||
+ ((nDelta < 0) && bPropGreat)) )
+ {
+ if ( nDelta < 0 )
+ bGreat = FALSE;
+ else
+ bSmall = FALSE;
+ }
+ }
+ else
+ {
+ if ( nDelta < 0 )
+ bGreat = FALSE;
+ else
+ bSmall = FALSE;
+ }
+ }
+ else if ( nPos >= nMax )
+ {
+ bSmall = FALSE;
+ bGreat = FALSE;
+ }
+ else if ( nPos && (nPos >= pSet->mnItems-1) )
+ {
+ nPos--;
+ nDelta *= -1;
+ BOOL bTemp = bPropSmall;
+ bPropSmall = bPropGreat;
+ bPropGreat = bTemp;
+ }
+
+ // Jetzt die Fenster splitten
+ if ( nDelta < 0 )
+ {
+ if ( bGreat )
+ {
+ if ( bPropGreat )
+ {
+ nTempDelta = nDelta;
+ do
+ {
+ n = nPos+1;
+ do
+ {
+ if ( nTempDelta )
+ {
+ pItems[n].mnPixSize++;
+ nTempDelta++;
+ }
+ n++;
+ }
+ while ( n < nMax );
+ }
+ while ( nTempDelta );
+ }
+ else
+ pItems[nPos+1].mnPixSize -= nDelta;
+ }
+
+ if ( bSmall )
+ {
+ if ( bPropSmall )
+ {
+ do
+ {
+ n = nPos+1;
+ do
+ {
+ if ( nDelta && pItems[n-1].mnPixSize )
+ {
+ pItems[n-1].mnPixSize--;
+ nDelta++;
+ }
+
+ n--;
+ }
+ while ( n > nMin );
+ }
+ while ( nDelta );
+ }
+ else
+ {
+ n = nPos+1;
+ do
+ {
+ if ( pItems[n-1].mnPixSize+nDelta < 0 )
+ {
+ nDelta += pItems[n-1].mnPixSize;
+ pItems[n-1].mnPixSize = 0;
+ }
+ else
+ {
+ pItems[n-1].mnPixSize += nDelta;
+ break;
+ }
+ n--;
+ }
+ while ( n > nMin );
+ }
+ }
+ }
+ else
+ {
+ if ( bGreat )
+ {
+ if ( bPropGreat )
+ {
+ nTempDelta = nDelta;
+ do
+ {
+ n = nPos+1;
+ do
+ {
+ if ( nTempDelta )
+ {
+ pItems[n-1].mnPixSize++;
+ nTempDelta--;
+ }
+ n--;
+ }
+ while ( n > nMin );
+ }
+ while ( nTempDelta );
+ }
+ else
+ pItems[nPos].mnPixSize += nDelta;
+ }
+
+ if ( bSmall )
+ {
+ if ( bPropSmall )
+ {
+ do
+ {
+ n = nPos+1;
+ do
+ {
+ if ( nDelta && pItems[n].mnPixSize )
+ {
+ pItems[n].mnPixSize--;
+ nDelta--;
+ }
+
+ n++;
+ }
+ while ( n < nMax );
+ }
+ while ( nDelta );
+ }
+ else
+ {
+ n = nPos+1;
+ do
+ {
+ if ( pItems[n].mnPixSize-nDelta < 0 )
+ {
+ nDelta -= pItems[n].mnPixSize;
+ pItems[n].mnPixSize = 0;
+ }
+ else
+ {
+ pItems[n].mnPixSize -= nDelta;
+ break;
+ }
+ n++;
+ }
+ while ( n < nMax );
+ }
+ }
+ }
+
+ // Original-Groessen updaten
+ ImplCalcLogSize( pItems, nItems );
+
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemSize( USHORT nId, long nNewSize )
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+ ImplSplitItem* pItem;
+
+ if ( !pSet )
+ return;
+
+ // Testen, ob sich Groesse aendert
+ pItem = &(pSet->mpItems[nPos]);
+ if ( pItem->mnSize != nNewSize )
+ {
+ // Neue Groesse setzen und neu durchrechnen
+ pItem->mnSize = nNewSize;
+ pSet->mbCalcPix = TRUE;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::GetItemSize( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return pSet->mpItems[nPos].mnSize;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::GetItemSize( USHORT nId, SplitWindowItemBits nBits ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ {
+ if ( nBits == pSet->mpItems[nPos].mnBits )
+ return pSet->mpItems[nPos].mnSize;
+ else
+ {
+ ((SplitWindow*)this)->ImplCalcLayout();
+
+ long nRelSize = 0;
+ long nPerSize = 0;
+ ImplSplitItem* pItems;
+ USHORT nItems;
+ SplitWindowItemBits nTempBits;
+ USHORT i;
+ nItems = pSet->mnItems;
+ pItems = pSet->mpItems;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( i == nPos )
+ nTempBits = nBits;
+ else
+ nTempBits = pItems[i].mnBits;
+ if ( nTempBits & SWIB_RELATIVESIZE )
+ nRelSize += pItems[i].mnPixSize;
+ else if ( nTempBits & SWIB_PERCENTSIZE )
+ nPerSize += pItems[i].mnPixSize;
+ }
+ nPerSize += nRelSize;
+ if ( nBits & SWIB_RELATIVESIZE )
+ {
+ if ( nRelSize )
+ return (pItems[nPos].mnPixSize+(nRelSize/2))/nRelSize;
+ else
+ return 1;
+ }
+ else if ( nBits & SWIB_PERCENTSIZE )
+ {
+ if ( nPerSize )
+ return (pItems[nPos].mnPixSize*100)/nPerSize;
+ else
+ return 1;
+ }
+ else
+ return pItems[nPos].mnPixSize;
+ }
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemBits( USHORT nId, SplitWindowItemBits nNewBits )
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+ ImplSplitItem* pItem;
+
+ if ( !pSet )
+ return;
+
+ pItem = &(pSet->mpItems[nPos]);
+ if ( pItem->mpWindow )
+ nNewBits &= ~SWIB_COLSET;
+
+ if ( pItem->mnBits != nNewBits )
+ {
+ // Neue Bits setzen und neu durchrechnen
+ pItem->mnBits = nNewBits;
+ pSet->mbCalcPix = TRUE;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+SplitWindowItemBits SplitWindow::GetItemBits( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return pSet->mpItems[nPos].mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Window* SplitWindow::GetItemWindow( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return pSet->mpItems[nPos].mpWindow;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetSet( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return pSet->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SplitWindow::GetSet( USHORT nId, USHORT& rSetId, USHORT& rPos ) const
+{
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, rPos );
+ if ( pSet )
+ {
+ rSetId = pSet->mnId;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SplitWindow::IsItemValid( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemId( Window* pWindow ) const
+{
+ return ImplFindItem( mpBaseSet, pWindow );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemId( const Point& rPos ) const
+{
+ return ImplFindItem( mpBaseSet, rPos, mbHorz, !mbBottomRight );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemPos( USHORT nId, USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
+ USHORT nPos = SPLITWINDOW_ITEM_NOTFOUND;
+
+ if ( pSet )
+ {
+ for ( USHORT i = 0; i < pSet->mnItems; i++ )
+ {
+ if ( pSet->mpItems[i].mnId == nId )
+ {
+ nPos = i;
+ break;
+ }
+ }
+ }
+
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemId( USHORT nPos, USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
+ if ( pSet && (nPos < pSet->mnItems) )
+ return pSet->mpItems[nPos].mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemCount( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
+ if ( pSet )
+ return pSet->mnItems;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplNewAlign()
+{
+ if ( mbNoAlign )
+ {
+ mbHorz = FALSE;
+ mbBottomRight = FALSE;
+ }
+ else if ( meAlign == WINDOWALIGN_TOP )
+ {
+ mbHorz = TRUE;
+ mbBottomRight = FALSE;
+ }
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ {
+ mbHorz = TRUE;
+ mbBottomRight = TRUE;
+ }
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ mbHorz = FALSE;
+ mbBottomRight = FALSE;
+ }
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ {
+ mbHorz = FALSE;
+ mbBottomRight = TRUE;
+ }
+
+ if ( mnWinStyle & WB_BORDER )
+ {
+ ImplCalcBorder( meAlign, mbNoAlign, mnLeftBorder, mnTopBorder,
+ mnRightBorder, mnBottomBorder );
+ }
+
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetNoAlign( BOOL bNoAlign )
+{
+ bNoAlign = bNoAlign != 0;
+ if ( mbNoAlign != bNoAlign )
+ {
+ mbNoAlign = bNoAlign;
+ ImplNewAlign();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetAlign( WindowAlign eNewAlign )
+{
+ if ( meAlign != eNewAlign )
+ {
+ meAlign = eNewAlign;
+ ImplNewAlign();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size SplitWindow::CalcWindowSizePixel( const Size& rSize, WindowAlign eAlign,
+ WinBits nWinStyle, BOOL bExtra )
+{
+ long nLeft;
+ long nTop;
+ long nRight;
+ long nBottom;
+ Size aSize = rSize;
+
+ ImplCalcBorder( eAlign, FALSE, nLeft, nTop, nRight, nBottom );
+ aSize.Width() += nLeft+nRight;
+ aSize.Height() += nTop+nBottom;
+
+ if ( nWinStyle & WB_SIZEABLE )
+ {
+ if ( (eAlign == WINDOWALIGN_TOP) || (eAlign == WINDOWALIGN_BOTTOM) )
+ {
+ aSize.Height() += SPLITWIN_SPLITSIZE-2;
+ if ( bExtra )
+ aSize.Height() += SPLITWIN_SPLITSIZEEXLN;
+ }
+ else
+ {
+ aSize.Width() += SPLITWIN_SPLITSIZE-2;
+ if ( bExtra )
+ aSize.Width() += SPLITWIN_SPLITSIZEEXLN;
+ }
+ }
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ShowAutoHideButton( BOOL bShow )
+{
+ mbAutoHide = bShow;
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ShowFadeInHideButton( BOOL bShow )
+{
+ mbFadeIn = bShow;
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ShowFadeOutButton( BOOL bShow )
+{
+ mbFadeOut = bShow;
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetAutoHideState( BOOL bAutoHide )
+{
+ mbAutoHideIn = bAutoHide;
+ if ( IsReallyVisible() )
+ {
+ Rectangle aRect;
+ ImplGetAutoHideRect( aRect );
+ Invalidate( aRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::GetFadeInSize() const
+{
+ long n = 0;
+
+ if ( mbHorz )
+ n = mnTopBorder+mnBottomBorder;
+ else
+ n = mnLeftBorder+mnRightBorder;
+
+ return n+SPLITWIN_SPLITSIZE+SPLITWIN_SPLITSIZEEX-2;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle SplitWindow::GetAutoHideRect() const
+{
+ Rectangle aRect;
+ ImplGetAutoHideRect( aRect, TRUE );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle SplitWindow::GetFadeInRect() const
+{
+ Rectangle aRect;
+ ImplGetFadeInRect( aRect, TRUE );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle SplitWindow::GetFadeOutRect() const
+{
+ Rectangle aRect;
+ ImplGetFadeOutRect( aRect, TRUE );
+ return aRect;
+}
diff --git a/vcl/source/window/status.cxx b/vcl/source/window/status.cxx
new file mode 100644
index 000000000000..385dd241c770
--- /dev/null
+++ b/vcl/source/window/status.cxx
@@ -0,0 +1,1794 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/event.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/help.hxx>
+#include <vcl/status.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/window.h>
+
+// =======================================================================
+
+#define STATUSBAR_OFFSET_X STATUSBAR_OFFSET
+#define STATUSBAR_OFFSET_Y 2
+#define STATUSBAR_OFFSET_TEXTY 3
+
+#define STATUSBAR_PRGS_OFFSET 3
+#define STATUSBAR_PRGS_COUNT 100
+#define STATUSBAR_PRGS_MIN 5
+
+// -----------------------------------------------------------------------
+
+class StatusBar::ImplData
+{
+public:
+ ImplData();
+ ~ImplData();
+
+ VirtualDevice* mpVirDev;
+ long mnItemBorderWidth;
+ bool mbTopBorder:1;
+ bool mbDrawItemFrames:1;
+};
+
+StatusBar::ImplData::ImplData()
+{
+ mpVirDev = NULL;
+ mbTopBorder = false;
+ mbDrawItemFrames = false;
+ mnItemBorderWidth = 0;
+}
+
+StatusBar::ImplData::~ImplData()
+{
+}
+
+struct ImplStatusItem
+{
+ USHORT mnId;
+ StatusBarItemBits mnBits;
+ long mnWidth;
+ long mnOffset;
+ long mnExtraWidth;
+ long mnX;
+ XubString maText;
+ XubString maHelpText;
+ XubString maQuickHelpText;
+ ULONG mnHelpId;
+ void* mpUserData;
+ BOOL mbVisible;
+ XubString maAccessibleName;
+ XubString maCommand;
+};
+
+DECLARE_LIST( ImplStatusItemList, ImplStatusItem* )
+
+// =======================================================================
+
+inline long ImplCalcProgessWidth( USHORT nMax, long nSize )
+{
+ return ((nMax*(nSize+(nSize/2)))-(nSize/2)+(STATUSBAR_PRGS_OFFSET*2));
+}
+
+// -----------------------------------------------------------------------
+
+static Point ImplGetItemTextPos( const Size& rRectSize, const Size& rTextSize,
+ USHORT nStyle )
+{
+ long nX;
+ long nY;
+ long delta = (rTextSize.Height()/4) + 1;
+ if( delta + rTextSize.Width() > rRectSize.Width() )
+ delta = 0;
+
+ if ( nStyle & SIB_LEFT )
+ nX = delta;
+ else if ( nStyle & SIB_RIGHT )
+ nX = rRectSize.Width()-rTextSize.Width()-delta;
+ else // SIB_CENTER
+ nX = (rRectSize.Width()-rTextSize.Width())/2;
+ nY = (rRectSize.Height()-rTextSize.Height())/2 + 1;
+ return Point( nX, nY );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL StatusBar::ImplIsItemUpdate()
+{
+ if ( !mbProgressMode && mbVisibleItems && IsReallyVisible() && IsUpdateMode() )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mpImplData = new ImplData;
+
+ // Default ist RightAlign
+ if ( !(nStyle & (WB_LEFT | WB_RIGHT)) )
+ nStyle |= WB_RIGHT;
+
+ Window::ImplInit( pParent, nStyle & ~WB_BORDER, NULL );
+
+ // WinBits merken
+ mpItemList = new ImplStatusItemList;
+ mpImplData->mpVirDev = new VirtualDevice( *this );
+ mnCurItemId = 0;
+ mbFormat = TRUE;
+ mbVisibleItems = TRUE;
+ mbProgressMode = FALSE;
+ mbInUserDraw = FALSE;
+ mbBottomBorder = FALSE;
+ mnItemsWidth = STATUSBAR_OFFSET_X;
+ mnDX = 0;
+ mnDY = 0;
+ mnCalcHeight = 0;
+ mnItemY = STATUSBAR_OFFSET_Y;
+ mnTextY = STATUSBAR_OFFSET_TEXTY;
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ SetLineColor();
+
+ SetOutputSizePixel( CalcWindowSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+StatusBar::StatusBar( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_STATUSBAR )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+StatusBar::StatusBar( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_STATUSBAR )
+{
+ rResId.SetRT( RSC_STATUSBAR );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+StatusBar::~StatusBar()
+{
+ // Alle Items loeschen
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ delete mpItemList;
+
+ // VirtualDevice loeschen
+ delete mpImplData->mpVirDev;
+
+ delete mpImplData;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetToolFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else if ( GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetButtonTextColor();
+ else
+ aColor = rStyleSettings.GetWindowTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+
+ mpImplData->mpVirDev->SetFont( GetFont() );
+ mpImplData->mpVirDev->SetTextColor( GetTextColor() );
+ mpImplData->mpVirDev->SetTextAlign( GetTextAlign() );
+ mpImplData->mpVirDev->SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+ mpImplData->mpVirDev->SetBackground( GetBackground() );
+
+ // NWF background
+ if( ! IsControlBackground() &&
+ IsNativeControlSupported( CTRL_WINDOW_BACKGROUND, PART_BACKGROUND_WINDOW ) )
+ {
+ ImplGetWindowImpl()->mnNativeBackground = PART_BACKGROUND_WINDOW;
+ EnableChildTransparentMode( TRUE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplFormat()
+{
+ ImplStatusItem* pItem;
+ long nExtraWidth;
+ long nExtraWidth2;
+ long nX;
+ USHORT nAutoSizeItems = 0;
+
+ // Breiten zusammenrechnen
+ mnItemsWidth = STATUSBAR_OFFSET_X;
+ long nOffset = 0;
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbVisible )
+ {
+ if ( pItem->mnBits & SIB_AUTOSIZE )
+ nAutoSizeItems++;
+
+ mnItemsWidth += pItem->mnWidth + nOffset;
+ nOffset = pItem->mnOffset;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ if ( GetStyle() & WB_RIGHT )
+ {
+ // Bei rechtsbuendiger Ausrichtung wird kein AutoSize ausgewertet,
+ // da wir links den Text anzeigen, der mit SetText gesetzt wird
+ nX = mnDX - mnItemsWidth;
+ nExtraWidth = 0;
+ nExtraWidth2 = 0;
+ }
+ else
+ {
+ mnItemsWidth += STATUSBAR_OFFSET_X;
+
+ // Bei linksbuendiger Ausrichtung muessen wir gegebenenfalls noch
+ // AutoSize auswerten
+ if ( nAutoSizeItems && (mnDX > (mnItemsWidth - STATUSBAR_OFFSET)) )
+ {
+ nExtraWidth = (mnDX - mnItemsWidth - 1) / nAutoSizeItems;
+ nExtraWidth2 = (mnDX - mnItemsWidth - 1) % nAutoSizeItems;
+ }
+ else
+ {
+ nExtraWidth = 0;
+ nExtraWidth2 = 0;
+ }
+ nX = STATUSBAR_OFFSET_X;
+ }
+
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbVisible )
+ {
+ if ( pItem->mnBits & SIB_AUTOSIZE )
+ {
+ pItem->mnExtraWidth = nExtraWidth;
+ if ( nExtraWidth2 )
+ {
+ pItem->mnExtraWidth++;
+ nExtraWidth2--;
+ }
+ }
+ else
+ pItem->mnExtraWidth = 0;
+
+ pItem->mnX = nX;
+ nX += pItem->mnWidth + pItem->mnExtraWidth + pItem->mnOffset;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ mbFormat = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle StatusBar::ImplGetItemRectPos( USHORT nPos ) const
+{
+ Rectangle aRect;
+ ImplStatusItem* pItem;
+ pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ {
+ if ( pItem->mbVisible )
+ {
+ aRect.Left() = pItem->mnX;
+ aRect.Right() = aRect.Left() + pItem->mnWidth + pItem->mnExtraWidth;
+ aRect.Top() = mnItemY;
+ aRect.Bottom() = mnCalcHeight - STATUSBAR_OFFSET_Y;
+ if( IsTopBorder() )
+ aRect.Bottom()+=2;
+ }
+ }
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::ImplGetFirstVisiblePos() const
+{
+ ImplStatusItem* pItem;
+
+ for( USHORT nPos = 0; nPos < mpItemList->Count(); nPos++ )
+ {
+ pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ {
+ if ( pItem->mbVisible )
+ return nPos;
+ }
+ }
+
+ return ~0;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplDrawText( BOOL bOffScreen, long nOldTextWidth )
+{
+ // Das ueberschreiben der Item-Box verhindern
+ Rectangle aTextRect;
+ aTextRect.Left() = STATUSBAR_OFFSET_X+1;
+ aTextRect.Top() = mnTextY;
+ if ( mbVisibleItems && (GetStyle() & WB_RIGHT) )
+ aTextRect.Right() = mnDX - mnItemsWidth - 1;
+ else
+ aTextRect.Right() = mnDX - 1;
+ if ( aTextRect.Right() > aTextRect.Left() )
+ {
+ // Position ermitteln
+ XubString aStr = GetText();
+ USHORT nPos = aStr.Search( _LF );
+ if ( nPos != STRING_NOTFOUND )
+ aStr.Erase( nPos );
+
+ aTextRect.Bottom() = aTextRect.Top()+GetTextHeight()+1;
+
+ if ( bOffScreen )
+ {
+ long nMaxWidth = Max( nOldTextWidth, GetTextWidth( aStr ) );
+ Size aVirDevSize( nMaxWidth, aTextRect.GetHeight() );
+ mpImplData->mpVirDev->SetOutputSizePixel( aVirDevSize );
+ Rectangle aTempRect = aTextRect;
+ aTempRect.SetPos( Point( 0, 0 ) );
+ mpImplData->mpVirDev->DrawText( aTempRect, aStr, TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
+ DrawOutDev( aTextRect.TopLeft(), aVirDevSize, Point(), aVirDevSize, *mpImplData->mpVirDev );
+ }
+ else
+ DrawText( aTextRect, aStr, TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplDrawItem( BOOL bOffScreen, USHORT nPos, BOOL bDrawText, BOOL bDrawFrame )
+{
+ Rectangle aRect = ImplGetItemRectPos( nPos );
+
+ if ( aRect.IsEmpty() )
+ return;
+
+ // Ausgabebereich berechnen
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ long nW = mpImplData->mnItemBorderWidth + 1;
+ Rectangle aTextRect( aRect.Left()+nW, aRect.Top()+nW,
+ aRect.Right()-nW, aRect.Bottom()-nW );
+ Size aTextRectSize( aTextRect.GetSize() );
+
+ if ( bOffScreen )
+ mpImplData->mpVirDev->SetOutputSizePixel( aTextRectSize );
+ else
+ {
+ Region aRegion( aTextRect );
+ SetClipRegion( aRegion );
+ }
+
+ // Text ausgeben
+ if ( bDrawText )
+ {
+ Size aTextSize( GetTextWidth( pItem->maText ), GetTextHeight() );
+ Point aTextPos = ImplGetItemTextPos( aTextRectSize, aTextSize, pItem->mnBits );
+ if ( bOffScreen )
+ mpImplData->mpVirDev->DrawText( aTextPos, pItem->maText );
+ else
+ {
+ aTextPos.X() += aTextRect.Left();
+ aTextPos.Y() += aTextRect.Top();
+ DrawText( aTextPos, pItem->maText );
+ }
+ }
+
+ // Gegebenenfalls auch DrawItem aufrufen
+ if ( pItem->mnBits & SIB_USERDRAW )
+ {
+ if ( bOffScreen )
+ {
+ mbInUserDraw = TRUE;
+ mpImplData->mpVirDev->EnableRTL( IsRTLEnabled() );
+ UserDrawEvent aODEvt( mpImplData->mpVirDev, Rectangle( Point(), aTextRectSize ), pItem->mnId );
+ UserDraw( aODEvt );
+ mpImplData->mpVirDev->EnableRTL( FALSE );
+ mbInUserDraw = FALSE;
+ }
+ else
+ {
+ UserDrawEvent aODEvt( this, aTextRect, pItem->mnId );
+ UserDraw( aODEvt );
+ }
+ }
+
+ if ( bOffScreen )
+ DrawOutDev( aTextRect.TopLeft(), aTextRectSize, Point(), aTextRectSize, *mpImplData->mpVirDev );
+ else
+ SetClipRegion();
+
+ // Frame ausgeben
+ if ( bDrawFrame )
+ {
+ if( mpImplData->mbDrawItemFrames )
+ {
+ if( !(pItem->mnBits & SIB_FLAT) )
+ {
+ USHORT nStyle;
+
+ if ( pItem->mnBits & SIB_IN )
+ nStyle = FRAME_DRAW_IN;
+ else
+ nStyle = FRAME_DRAW_OUT;
+
+ DecorationView aDecoView( this );
+ aDecoView.DrawFrame( aRect, nStyle );
+ }
+ }
+ else if( nPos != ImplGetFirstVisiblePos() )
+ {
+ // draw separator
+ Point aFrom( aRect.TopLeft() );
+ aFrom.X()--;
+ aFrom.Y()++;
+ Point aTo( aRect.BottomLeft() );
+ aTo.X()--;
+ aTo.Y()--;
+
+ DecorationView aDecoView( this );
+ aDecoView.DrawSeparator( aFrom, aTo );
+ }
+ }
+
+ if ( !ImplIsRecordLayout() )
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_DRAWITEM, (void*) sal_IntPtr(pItem->mnId) );
+}
+
+// -----------------------------------------------------------------------
+
+void DrawProgress( Window* pWindow, const Point& rPos,
+ long nOffset, long nPrgsWidth, long nPrgsHeight,
+ USHORT nPercent1, USHORT nPercent2, USHORT nPercentCount,
+ const Rectangle& rFramePosSize
+ )
+{
+ if( pWindow->IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
+ {
+ bool bNeedErase = ImplGetSVData()->maNWFData.mbProgressNeedsErase;
+
+ long nFullWidth = (nPrgsWidth + nOffset) * (10000 / nPercentCount);
+ long nPerc = (nPercent2 > 10000) ? 10000 : nPercent2;
+ ImplControlValue aValue( nFullWidth * (long)nPerc / 10000 );
+ Rectangle aDrawRect( rPos, Size( nFullWidth, nPrgsHeight ) );
+ Rectangle aControlRegion( aDrawRect );
+ if( bNeedErase )
+ {
+ Window* pEraseWindow = pWindow;
+ while( pEraseWindow->IsPaintTransparent() &&
+ ! pEraseWindow->ImplGetWindowImpl()->mbFrame )
+ {
+ pEraseWindow = pEraseWindow->ImplGetWindowImpl()->mpParent;
+ }
+ if( pEraseWindow == pWindow )
+ // restore background of pWindow
+ pEraseWindow->Erase( rFramePosSize );
+ else
+ {
+ // restore transparent background
+ Point aTL( pWindow->OutputToAbsoluteScreenPixel( rFramePosSize.TopLeft() ) );
+ aTL = pEraseWindow->AbsoluteScreenToOutputPixel( aTL );
+ Rectangle aRect( aTL, rFramePosSize.GetSize() );
+ pEraseWindow->Invalidate( aRect, INVALIDATE_NOCHILDREN |
+ INVALIDATE_NOCLIPCHILDREN |
+ INVALIDATE_TRANSPARENT );
+ pEraseWindow->Update();
+ }
+ pWindow->Push( PUSH_CLIPREGION );
+ pWindow->IntersectClipRegion( rFramePosSize );
+ }
+ BOOL bNativeOK = pWindow->DrawNativeControl( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
+ CTRL_STATE_ENABLED, aValue, rtl::OUString() );
+ if( bNeedErase )
+ pWindow->Pop();
+ if( bNativeOK )
+ {
+ pWindow->Flush();
+ return;
+ }
+ }
+
+ // Werte vorberechnen
+ USHORT nPerc1 = nPercent1 / nPercentCount;
+ USHORT nPerc2 = nPercent2 / nPercentCount;
+
+ if ( nPerc1 > nPerc2 )
+ {
+ // Support progress that can also decrease
+
+ // Rechteck berechnen
+ long nDX = nPrgsWidth + nOffset;
+ long nLeft = rPos.X()+((nPerc1-1)*nDX);
+ Rectangle aRect( nLeft, rPos.Y(), nLeft+nPrgsWidth, rPos.Y()+nPrgsHeight );
+
+ do
+ {
+ pWindow->Erase( aRect );
+ aRect.Left() -= nDX;
+ aRect.Right() -= nDX;
+ nPerc1--;
+ }
+ while ( nPerc1 > nPerc2 );
+
+ pWindow->Flush();
+ }
+ else if ( nPerc1 < nPerc2 )
+ {
+ // Percent-Rechtecke malen
+ // Wenn Percent2 ueber 100%, Werte anpassen
+ if ( nPercent2 > 10000 )
+ {
+ nPerc2 = 10000 / nPercentCount;
+ if ( nPerc1 >= nPerc2 )
+ nPerc1 = nPerc2-1;
+ }
+
+ // Rechteck berechnen
+ long nDX = nPrgsWidth + nOffset;
+ long nLeft = rPos.X()+(nPerc1*nDX);
+ Rectangle aRect( nLeft, rPos.Y(), nLeft+nPrgsWidth, rPos.Y()+nPrgsHeight );
+
+ do
+ {
+ pWindow->DrawRect( aRect );
+ aRect.Left() += nDX;
+ aRect.Right() += nDX;
+ nPerc1++;
+ }
+ while ( nPerc1 < nPerc2 );
+
+ // Bei mehr als 100%, lassen wir das Rechteck blinken
+ if ( nPercent2 > 10000 )
+ {
+ // an/aus-Status festlegen
+ if ( ((nPercent2 / nPercentCount) & 0x01) == (nPercentCount & 0x01) )
+ {
+ aRect.Left() -= nDX;
+ aRect.Right() -= nDX;
+ pWindow->Erase( aRect );
+ }
+ }
+
+ pWindow->Flush();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplDrawProgress( BOOL bPaint,
+ USHORT nPercent1, USHORT nPercent2 )
+{
+ bool bNative = IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL );
+ // bPaint: draw text also, else only update progress
+ if ( bPaint )
+ {
+ DrawText( maPrgsTxtPos, maPrgsTxt );
+ if( ! bNative )
+ {
+ DecorationView aDecoView( this );
+ aDecoView.DrawFrame( maPrgsFrameRect, FRAME_DRAW_IN );
+ }
+ }
+
+ Point aPos( maPrgsFrameRect.Left()+STATUSBAR_PRGS_OFFSET,
+ maPrgsFrameRect.Top()+STATUSBAR_PRGS_OFFSET );
+ long nPrgsHeight = mnPrgsSize;
+ if( bNative )
+ {
+ aPos = maPrgsFrameRect.TopLeft();
+ nPrgsHeight = maPrgsFrameRect.GetHeight();
+ }
+ DrawProgress( this, aPos, mnPrgsSize/2, mnPrgsSize, nPrgsHeight,
+ nPercent1*100, nPercent2*100, mnPercentCount, maPrgsFrameRect );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplCalcProgressRect()
+{
+ // calculate text size
+ Size aPrgsTxtSize( GetTextWidth( maPrgsTxt ), GetTextHeight() );
+ maPrgsTxtPos.X() = STATUSBAR_OFFSET_X+1;
+
+ // calculate progress frame
+ maPrgsFrameRect.Left() = maPrgsTxtPos.X()+aPrgsTxtSize.Width()+STATUSBAR_OFFSET;
+ maPrgsFrameRect.Top() = mnItemY;
+ maPrgsFrameRect.Bottom() = mnCalcHeight - STATUSBAR_OFFSET_Y;
+ if( IsTopBorder() )
+ maPrgsFrameRect.Bottom()+=2;
+
+ // calculate size of progress rects
+ mnPrgsSize = maPrgsFrameRect.Bottom()-maPrgsFrameRect.Top()-(STATUSBAR_PRGS_OFFSET*2);
+ USHORT nMaxPercent = STATUSBAR_PRGS_COUNT;
+
+ long nMaxWidth = mnDX-STATUSBAR_OFFSET-1;
+
+ // make smaller if there are too many rects
+ while ( maPrgsFrameRect.Left()+ImplCalcProgessWidth( nMaxPercent, mnPrgsSize ) > nMaxWidth )
+ {
+ nMaxPercent--;
+ if ( nMaxPercent <= STATUSBAR_PRGS_MIN )
+ break;
+ }
+ maPrgsFrameRect.Right() = maPrgsFrameRect.Left() + ImplCalcProgessWidth( nMaxPercent, mnPrgsSize );
+
+ // save the divisor for later
+ mnPercentCount = 10000 / nMaxPercent;
+ BOOL bNativeOK = FALSE;
+ if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
+ {
+ ImplControlValue aValue;
+ Rectangle aControlRegion( Rectangle( (const Point&)Point(), maPrgsFrameRect.GetSize() ) );
+ Rectangle aNativeControlRegion, aNativeContentRegion;
+ if( (bNativeOK = GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
+ CTRL_STATE_ENABLED, aValue, rtl::OUString(),
+ aNativeControlRegion, aNativeContentRegion ) ) != FALSE )
+ {
+ long nProgressHeight = aNativeControlRegion.GetHeight();
+ if( nProgressHeight > maPrgsFrameRect.GetHeight() )
+ {
+ long nDelta = nProgressHeight - maPrgsFrameRect.GetHeight();
+ maPrgsFrameRect.Top() -= (nDelta - nDelta/2);
+ maPrgsFrameRect.Bottom() += nDelta/2;
+ }
+ maPrgsTxtPos.Y() = maPrgsFrameRect.Top() + (nProgressHeight - GetTextHeight())/2;
+ }
+ }
+ if( ! bNativeOK )
+ maPrgsTxtPos.Y() = mnTextY;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // Nur bei linker Maustaste ToolBox ausloesen
+ if ( rMEvt.IsLeft() )
+ {
+ if ( mbVisibleItems )
+ {
+ Point aMousePos = rMEvt.GetPosPixel();
+ USHORT i = 0;
+
+ // Item suchen, das geklickt wurde
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Ist es dieses Item
+ if ( ImplGetItemRectPos( i ).IsInside( aMousePos ) )
+ {
+ mnCurItemId = pItem->mnId;
+ if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+ else
+ Click();
+ mnCurItemId = 0;
+
+ // Item wurde gefunden
+ return;
+ }
+
+ i++;
+ pItem = mpItemList->Next();
+ }
+ }
+
+ // Kein Item, dann nur Click oder DoubleClick
+ if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+ else
+ Click();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Paint( const Rectangle& )
+{
+ if ( mbFormat )
+ ImplFormat();
+
+ USHORT nItemCount = (USHORT)mpItemList->Count();
+
+ if ( mbProgressMode )
+ ImplDrawProgress( TRUE, 0, mnPercent );
+ else
+ {
+ // Text zeichen
+ if ( !mbVisibleItems || (GetStyle() & WB_RIGHT) )
+ ImplDrawText( FALSE, 0 );
+
+ // Items zeichnen
+ if ( mbVisibleItems )
+ {
+ // Items zeichnen
+ for ( USHORT i = 0; i < nItemCount; i++ )
+ ImplDrawItem( FALSE, i, TRUE, TRUE );
+ }
+ }
+
+ // draw borders
+ if( IsTopBorder() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( 0, 0 ), Point( mnDX-1, 0 ) );
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( 0, 1 ), Point( mnDX-1, 1 ) );
+ }
+
+ if ( IsBottomBorder() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( 0, mnDY-2 ), Point( mnDX-1, mnDY-2 ) );
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( 0, mnDY-1 ), Point( mnDX-1, mnDY-1 ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Move()
+{
+ Window::Move();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Resize()
+{
+ // Breite und Hoehe abfragen und merken
+ Size aSize = GetOutputSizePixel();
+ mnDX = aSize.Width();
+ mnDY = aSize.Height();
+ mnCalcHeight = mnDY;
+ // subtract border
+ if( IsTopBorder() )
+ mnCalcHeight -= 2;
+ if ( IsBottomBorder() )
+ mnCalcHeight -= 2;
+
+ mnItemY = STATUSBAR_OFFSET_Y;
+ if( IsTopBorder() )
+ mnItemY += 2;
+ mnTextY = (mnCalcHeight-GetTextHeight())/2;
+ if( IsTopBorder() )
+ mnTextY += 2;
+
+ // Formatierung neu ausloesen
+ mbFormat = TRUE;
+
+ if ( mbProgressMode )
+ ImplCalcProgressRect();
+
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::RequestHelp( const HelpEvent& rHEvt )
+{
+ // no keyboard help in status bar
+ if( rHEvt.KeyboardActivated() )
+ return;
+
+ USHORT nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+
+ if ( nItemId )
+ {
+ Rectangle aItemRect = GetItemRect( nItemId );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ XubString aStr = GetHelpText( nItemId );
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
+ return;
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_QUICK )
+ {
+ XubString aStr = GetQuickHelpText( nItemId );
+ // Show quickhelp if available
+ if( aStr.Len() )
+ {
+ Help::ShowQuickHelp( this, aItemRect, aStr );
+ return;
+ }
+ aStr = GetItemText( nItemId );
+ // show a quick help if item text doesn't fit
+ if ( GetTextWidth( aStr ) > aItemRect.GetWidth() )
+ {
+ Help::ShowQuickHelp( this, aItemRect, aStr );
+ return;
+ }
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
+ {
+ String aCommand = GetItemCommand( nItemId );
+ ULONG nHelpId = GetHelpId( nItemId );
+
+ if ( aCommand.Len() || nHelpId )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ if ( aCommand.Len() )
+ pHelp->Start( aCommand, this );
+ else if ( nHelpId )
+ pHelp->Start( nHelpId, this );
+ }
+ return;
+ }
+ }
+ }
+
+ Window::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplFormat();
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ Invalidate();
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ mbFormat = TRUE;
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ mbFormat = TRUE;
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ ImplStatusItem* pItem = mpItemList->First();
+ long nFudge = GetTextHeight() / 4;
+ while ( pItem )
+ {
+ long nWidth = GetTextWidth( pItem->maText ) + nFudge;
+ if( nWidth > pItem->mnWidth + STATUSBAR_OFFSET )
+ pItem->mnWidth = nWidth + STATUSBAR_OFFSET;
+ pItem = mpItemList->Next();
+ }
+ Size aSize = GetSizePixel();
+ // do not disturb current width, since
+ // CalcWindowSizePixel calculates a minimum width
+ aSize.Height() = CalcWindowSizePixel().Height();
+ SetSizePixel( aSize );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Click()
+{
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_CLICK );
+ maClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::DoubleClick()
+{
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_DOUBLECLICK );
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::InsertItem( USHORT nItemId, ULONG nWidth,
+ StatusBarItemBits nBits,
+ long nOffset, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "StatusBar::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == STATUSBAR_ITEM_NOTFOUND,
+ "StatusBar::InsertItem(): ItemId already exists" );
+
+ // IN und CENTER sind Default
+ if ( !(nBits & (SIB_IN | SIB_OUT | SIB_FLAT)) )
+ nBits |= SIB_IN;
+ if ( !(nBits & (SIB_LEFT | SIB_RIGHT | SIB_CENTER)) )
+ nBits |= SIB_CENTER;
+
+ // Item anlegen
+ long nFudge = GetTextHeight()/4;
+ ImplStatusItem* pItem = new ImplStatusItem;
+ pItem->mnId = nItemId;
+ pItem->mnBits = nBits;
+ pItem->mnWidth = (long)nWidth+nFudge+STATUSBAR_OFFSET;
+ pItem->mnOffset = nOffset;
+ pItem->mnHelpId = 0;
+ pItem->mpUserData = 0;
+ pItem->mbVisible = TRUE;
+
+ // Item in die Liste einfuegen
+ mpItemList->Insert( pItem, nPos );
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_ITEMADDED, (void*) sal_IntPtr(nItemId) );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::RemoveItem( USHORT nItemId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->Remove( nPos );
+ delete pItem;
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_ITEMREMOVED, (void*) sal_IntPtr(nItemId) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ShowItem( USHORT nItemId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ if ( !pItem->mbVisible )
+ {
+ pItem->mbVisible = TRUE;
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_SHOWITEM, (void*) sal_IntPtr(nItemId) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::HideItem( USHORT nItemId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem->mbVisible )
+ {
+ pItem->mbVisible = FALSE;
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_HIDEITEM, (void*) sal_IntPtr(nItemId) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL StatusBar::IsItemVisible( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mbVisible;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ShowItems()
+{
+ if ( !mbVisibleItems )
+ {
+ mbVisibleItems = TRUE;
+ if ( !mbProgressMode )
+ Invalidate();
+
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_SHOWALLITEMS );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::HideItems()
+{
+ if ( mbVisibleItems )
+ {
+ mbVisibleItems = FALSE;
+ if ( !mbProgressMode )
+ Invalidate();
+
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_HIDEALLITEMS );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::CopyItems( const StatusBar& rStatusBar )
+{
+ // Alle Items entfernen
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Items aus der Liste loeschen
+ mpItemList->Clear();
+
+ // Items kopieren
+ ULONG i = 0;
+ pItem = rStatusBar.mpItemList->GetObject( i );
+ while ( pItem )
+ {
+ mpItemList->Insert( new ImplStatusItem( *pItem ), LIST_APPEND );
+ i++;
+ pItem = rStatusBar.mpItemList->GetObject( i );
+ }
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Clear()
+{
+ // Alle Item loeschen
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Items aus der Liste loeschen
+ mpItemList->Clear();
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_ALLITEMSREMOVED );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::GetItemCount() const
+{
+ return (USHORT)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::GetItemId( USHORT nPos ) const
+{
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::GetItemPos( USHORT nItemId ) const
+{
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return (USHORT)mpItemList->GetCurPos();
+
+ pItem = mpItemList->Next();
+ }
+
+ return STATUSBAR_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::GetItemId( const Point& rPos ) const
+{
+ if ( AreItemsVisible() && !mbFormat )
+ {
+ USHORT nItemCount = GetItemCount();
+ USHORT nPos;
+ for ( nPos = 0; nPos < nItemCount; nPos++ )
+ {
+ // Rechteck holen
+ Rectangle aRect = ImplGetItemRectPos( nPos );
+ if ( aRect.IsInside( rPos ) )
+ return mpItemList->GetObject( nPos )->mnId;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle StatusBar::GetItemRect( USHORT nItemId ) const
+{
+ Rectangle aRect;
+
+ if ( AreItemsVisible() && !mbFormat )
+ {
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ // Rechteck holen und Rahmen abziehen
+ aRect = ImplGetItemRectPos( nPos );
+ long nW = mpImplData->mnItemBorderWidth+1;
+ aRect.Top() += nW-1;
+ aRect.Bottom() -= nW-1;
+ aRect.Left() += nW;
+ aRect.Right() -= nW;
+ return aRect;
+ }
+ }
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+Point StatusBar::GetItemTextPos( USHORT nItemId ) const
+{
+ if ( !mbFormat )
+ {
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ // Rechteck holen
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ Rectangle aRect = ImplGetItemRectPos( nPos );
+ long nW = mpImplData->mnItemBorderWidth + 1;
+ Rectangle aTextRect( aRect.Left()+nW, aRect.Top()+nW,
+ aRect.Right()-nW, aRect.Bottom()-nW );
+ Point aPos = ImplGetItemTextPos( aTextRect.GetSize(),
+ Size( GetTextWidth( pItem->maText ), GetTextHeight() ),
+ pItem->mnBits );
+ if ( !mbInUserDraw )
+ {
+ aPos.X() += aTextRect.Left();
+ aPos.Y() += aTextRect.Top();
+ }
+ return aPos;
+ }
+ }
+
+ return Point();
+}
+
+// -----------------------------------------------------------------------
+
+ULONG StatusBar::GetItemWidth( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnWidth;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+StatusBarItemBits StatusBar::GetItemBits( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long StatusBar::GetItemOffset( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnOffset;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetItemText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->maText != rText )
+ {
+ pItem->maText = rText;
+
+ // adjust item width - see also DataChanged()
+ long nFudge = GetTextHeight()/4;
+ long nWidth = GetTextWidth( pItem->maText ) + nFudge;
+ if( (nWidth > pItem->mnWidth + STATUSBAR_OFFSET) ||
+ ((nWidth < pItem->mnWidth) && (mnDX - STATUSBAR_OFFSET) < mnItemsWidth ))
+ {
+ pItem->mnWidth = nWidth + STATUSBAR_OFFSET;
+ ImplFormat();
+ Invalidate();
+ }
+
+ // Item neu Zeichen, wenn StatusBar sichtbar und
+ // UpdateMode gesetzt ist
+ if ( pItem->mbVisible && !mbFormat && ImplIsItemUpdate() )
+ {
+ Update();
+ ImplDrawItem( TRUE, nPos, TRUE, FALSE );
+ Flush();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& StatusBar::GetItemText( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetItemCommand( USHORT nItemId, const XubString& rCommand )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->maCommand != rCommand )
+ pItem->maCommand = rCommand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& StatusBar::GetItemCommand( USHORT nItemId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maCommand;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetItemData( USHORT nItemId, void* pNewData )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ pItem->mpUserData = pNewData;
+
+ // Wenn es ein User-Item ist, DrawItem-Aufrufen
+ if ( (pItem->mnBits & SIB_USERDRAW) && pItem->mbVisible &&
+ !mbFormat && ImplIsItemUpdate() )
+ {
+ Update();
+ ImplDrawItem( TRUE, nPos, FALSE, FALSE );
+ Flush();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* StatusBar::GetItemData( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mpUserData;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetHelpText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& StatusBar::GetHelpText( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ if ( !pItem->maHelpText.Len() && ( pItem->mnHelpId || pItem->maCommand.Len() ))
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ if ( pItem->maCommand.Len() )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->maCommand, this );
+ if ( !pItem->maHelpText.Len() && pItem->mnHelpId )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId, this );
+ }
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetQuickHelpText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->maQuickHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& StatusBar::GetQuickHelpText( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ return pItem->maQuickHelpText;
+ }
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetHelpId( USHORT nItemId, ULONG nHelpId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->mnHelpId = nHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG StatusBar::GetHelpId( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnHelpId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplCalcBorder( )
+{
+ mnCalcHeight = mnDY;
+ // subtract border
+ if( IsTopBorder() )
+ {
+ mnCalcHeight -= 2;
+ mnTextY += 2;
+ mnItemY += 2;
+ }
+ if ( IsBottomBorder() )
+ mnCalcHeight -= 2;
+ mbFormat = TRUE;
+ Invalidate();
+}
+
+void StatusBar::SetBottomBorder( BOOL bBottomBorder )
+{
+ if ( mbBottomBorder != bBottomBorder )
+ {
+ mbBottomBorder = bBottomBorder;
+ ImplCalcBorder();
+ }
+}
+
+void StatusBar::SetTopBorder( BOOL bTopBorder )
+{
+ if ( mpImplData->mbTopBorder != static_cast<bool>(bTopBorder) )
+ {
+ mpImplData->mbTopBorder = static_cast<bool>(bTopBorder);
+ ImplCalcBorder();
+ }
+}
+
+BOOL StatusBar::IsTopBorder() const
+{
+ return mpImplData->mbTopBorder;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::StartProgressMode( const XubString& rText )
+{
+ DBG_ASSERT( !mbProgressMode, "StatusBar::StartProgressMode(): progress mode is active" );
+
+ mbProgressMode = TRUE;
+ mnPercent = 0;
+ maPrgsTxt = rText;
+
+ // Groessen berechnen
+ ImplCalcProgressRect();
+
+ // Paint ausloesen (dort wird der Text und der Frame gemalt)
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Color aPrgsColor = rStyleSettings.GetHighlightColor();
+ if ( aPrgsColor == rStyleSettings.GetFaceColor() )
+ aPrgsColor = rStyleSettings.GetDarkShadowColor();
+ SetLineColor();
+ SetFillColor( aPrgsColor );
+ if ( IsReallyVisible() )
+ {
+ Invalidate();
+ Update();
+ Flush();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetProgressValue( USHORT nNewPercent )
+{
+ DBG_ASSERT( mbProgressMode, "StatusBar::SetProgressValue(): no progrss mode" );
+ DBG_ASSERTWARNING( nNewPercent <= 100, "StatusBar::SetProgressValue(): nPercent > 100" );
+
+ if ( mbProgressMode
+ && IsReallyVisible()
+ && (!mnPercent || (mnPercent != nNewPercent)) )
+ {
+ Update();
+ SetLineColor();
+ ImplDrawProgress( FALSE, mnPercent, nNewPercent );
+ Flush();
+ }
+ mnPercent = nNewPercent;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::EndProgressMode()
+{
+ DBG_ASSERT( mbProgressMode, "StatusBar::EndProgressMode(): no progress mode" );
+
+ mbProgressMode = FALSE;
+ maPrgsTxt.Erase();
+
+ // Paint neu ausloesen um StatusBar wieder herzustellen
+ SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
+ if ( IsReallyVisible() )
+ {
+ Invalidate();
+ Update();
+ Flush();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ResetProgressMode()
+{
+ if ( mbProgressMode )
+ {
+ mnPercent = 0;
+ maPrgsTxt.Erase();
+ if ( IsReallyVisible() )
+ {
+ Invalidate();
+ Update();
+ Flush();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetText( const XubString& rText )
+{
+ if ( (!mbVisibleItems || (GetStyle() & WB_RIGHT)) && !mbProgressMode &&
+ IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( mbFormat )
+ {
+ Invalidate();
+ Window::SetText( rText );
+ }
+ else
+ {
+ Update();
+ long nOldTextWidth = GetTextWidth( GetText() );
+ Window::SetText( rText );
+ ImplDrawText( TRUE, nOldTextWidth );
+ Flush();
+ }
+ }
+ else if ( mbProgressMode )
+ {
+ maPrgsTxt = rText;
+ if ( IsReallyVisible() )
+ {
+ Invalidate();
+ Update();
+ Flush();
+ }
+ }
+ else
+ Window::SetText( rText );
+}
+
+// -----------------------------------------------------------------------
+
+Size StatusBar::CalcWindowSizePixel() const
+{
+ ULONG i = 0;
+ ULONG nCount = mpItemList->Count();
+ long nOffset = 0;
+ long nCalcWidth = (STATUSBAR_OFFSET_X*2);
+ long nCalcHeight;
+
+ while ( i < nCount )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( i );
+ nCalcWidth += pItem->mnWidth + nOffset;
+ nOffset = pItem->mnOffset;
+ i++;
+ }
+
+ long nMinHeight = GetTextHeight();
+ const long nBarTextOffset = STATUSBAR_OFFSET_TEXTY*2;
+ long nProgressHeight = nMinHeight + nBarTextOffset;
+ // FIXME: IsNativeControlSupported and GetNativeControlRegion should be const ?
+ StatusBar* pThis = const_cast<StatusBar*>( this );
+ if( pThis->IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
+ {
+ ImplControlValue aValue;
+ Rectangle aControlRegion( (const Point&)Point(), Size( nCalcWidth, nMinHeight ) );
+ Rectangle aNativeControlRegion, aNativeContentRegion;
+ if( pThis->GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
+ CTRL_STATE_ENABLED, aValue, rtl::OUString(),
+ aNativeControlRegion, aNativeContentRegion ) )
+ {
+ nProgressHeight = aNativeControlRegion.GetHeight();
+ }
+ }
+
+ if( mpImplData->mbDrawItemFrames &&
+ pThis->IsNativeControlSupported( CTRL_FRAME, PART_BORDER ) )
+ {
+ ImplControlValue aControlValue( FRAME_DRAW_NODRAW );
+ Rectangle aBound, aContent;
+ Rectangle aNatRgn( Point( 0, 0 ), Size( 150, 50 ) );
+ if( pThis->GetNativeControlRegion(CTRL_FRAME, PART_BORDER,
+ aNatRgn, 0, aControlValue, rtl::OUString(), aBound, aContent) )
+ {
+ mpImplData->mnItemBorderWidth =
+ ( aBound.GetHeight() - aContent.GetHeight() ) / 2;
+ }
+ }
+
+ nCalcHeight = nMinHeight+nBarTextOffset + 2*mpImplData->mnItemBorderWidth;
+ if( nCalcHeight < nProgressHeight+2 )
+ nCalcHeight = nProgressHeight+2;
+
+ // add border
+ if( IsTopBorder() )
+ nCalcHeight += 2;
+ if ( IsBottomBorder() )
+ nCalcHeight += 2;
+
+ return Size( nCalcWidth, nCalcHeight );
+}
+
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetAccessibleName( USHORT nItemId, const XubString& rName )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->maAccessibleName != rName )
+ {
+ pItem->maAccessibleName = rName;
+ ImplCallEventListeners( VCLEVENT_STATUSBAR_NAMECHANGED, (void*) sal_IntPtr(pItem->mnId) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& StatusBar::GetAccessibleName( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maAccessibleName;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
diff --git a/vcl/source/window/syschild.cxx b/vcl/source/window/syschild.cxx
new file mode 100644
index 000000000000..ef71f83df1ee
--- /dev/null
+++ b/vcl/source/window/syschild.cxx
@@ -0,0 +1,192 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/salinst.hxx>
+#include <vcl/salframe.hxx>
+#include <vcl/window.hxx>
+#include <vcl/salobj.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/svdata.hxx>
+#ifndef _SV_WIDNOW_H
+#include <vcl/window.h>
+#endif
+#include <vcl/svapp.hxx>
+#include <vcl/syschild.hxx>
+
+
+
+// =======================================================================
+
+long ImplSysChildProc( void* pInst, SalObject* /* pObject */,
+ USHORT nEvent, const void* /* pEvent */ )
+{
+ SystemChildWindow* pWindow = (SystemChildWindow*)pInst;
+ long nRet = 0;
+
+ ImplDelData aDogTag( pWindow );
+ switch ( nEvent )
+ {
+ case SALOBJ_EVENT_GETFOCUS:
+ // Focus holen und zwar so, das alle Handler gerufen
+ // werden, als ob dieses Fenster den Focus bekommt,
+ // ohne das der Frame den Focus wieder klaut
+ pWindow->ImplGetFrameData()->mbSysObjFocus = TRUE;
+ pWindow->ImplGetFrameData()->mbInSysObjToTopHdl = TRUE;
+ pWindow->ToTop( TOTOP_NOGRABFOCUS );
+ if( aDogTag.IsDead() )
+ break;
+ pWindow->ImplGetFrameData()->mbInSysObjToTopHdl = FALSE;
+ pWindow->ImplGetFrameData()->mbInSysObjFocusHdl = TRUE;
+ pWindow->GrabFocus();
+ if( aDogTag.IsDead() )
+ break;
+ pWindow->ImplGetFrameData()->mbInSysObjFocusHdl = FALSE;
+ break;
+
+ case SALOBJ_EVENT_LOSEFOCUS:
+ // Hintenrum einen LoseFocus ausloesen, das der Status
+ // der Fenster dem entsprechenden Activate-Status
+ // entspricht
+ pWindow->ImplGetFrameData()->mbSysObjFocus = FALSE;
+ if ( !pWindow->ImplGetFrameData()->mnFocusId )
+ {
+ pWindow->ImplGetFrameData()->mbStartFocusState = TRUE;
+ Application::PostUserEvent( pWindow->ImplGetFrameData()->mnFocusId, LINK( pWindow->ImplGetFrameWindow(), Window, ImplAsyncFocusHdl ) );
+ }
+ break;
+
+ case SALOBJ_EVENT_TOTOP:
+ pWindow->ImplGetFrameData()->mbInSysObjToTopHdl = TRUE;
+ if ( !Application::GetFocusWindow() || pWindow->HasChildPathFocus() )
+ pWindow->ToTop( TOTOP_NOGRABFOCUS );
+ else
+ pWindow->ToTop();
+ if( aDogTag.IsDead() )
+ break;
+ pWindow->GrabFocus();
+ if( aDogTag.IsDead() )
+ break;
+ pWindow->ImplGetFrameData()->mbInSysObjToTopHdl = FALSE;
+ break;
+ }
+
+ return nRet;
+}
+
+// =======================================================================
+
+void SystemChildWindow::ImplInitSysChild( Window* pParent, WinBits nStyle, SystemWindowData *pData, BOOL bShow )
+{
+ mpWindowImpl->mpSysObj = ImplGetSVData()->mpDefInst->CreateObject( pParent->ImplGetFrame(), pData, bShow );
+
+ Window::ImplInit( pParent, nStyle, NULL );
+
+ // Wenn es ein richtiges SysChild ist, dann painten wir auch nicht
+ if ( GetSystemData() )
+ {
+ mpWindowImpl->mpSysObj->SetCallback( this, ImplSysChildProc );
+ SetParentClipMode( PARENTCLIPMODE_CLIP );
+ SetBackground();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+SystemChildWindow::SystemChildWindow( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_SYSTEMCHILDWINDOW )
+{
+ ImplInitSysChild( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+SystemChildWindow::SystemChildWindow( Window* pParent, WinBits nStyle, SystemWindowData *pData, BOOL bShow ) :
+ Window( WINDOW_SYSTEMCHILDWINDOW )
+{
+ ImplInitSysChild( pParent, nStyle, pData, bShow );
+}
+
+// -----------------------------------------------------------------------
+
+SystemChildWindow::SystemChildWindow( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_SYSTEMCHILDWINDOW )
+{
+ rResId.SetRT( RSC_WINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInitSysChild( pParent, nStyle, NULL );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+SystemChildWindow::~SystemChildWindow()
+{
+ Hide();
+ if ( mpWindowImpl->mpSysObj )
+ {
+ ImplGetSVData()->mpDefInst->DestroyObject( mpWindowImpl->mpSysObj );
+ mpWindowImpl->mpSysObj = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const SystemEnvData* SystemChildWindow::GetSystemData() const
+{
+ if ( mpWindowImpl->mpSysObj )
+ return mpWindowImpl->mpSysObj->GetSystemData();
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemChildWindow::EnableEraseBackground( BOOL bEnable )
+{
+ if ( mpWindowImpl->mpSysObj )
+ mpWindowImpl->mpSysObj->EnableEraseBackground( bEnable );
+}
+
+BOOL SystemChildWindow::IsEraseBackgroundEnabled()
+{
+ if ( mpWindowImpl->mpSysObj )
+ return mpWindowImpl->mpSysObj->IsEraseBackgroundEnabled();
+ else
+ return FALSE;
+}
diff --git a/vcl/source/window/syswin.cxx b/vcl/source/window/syswin.cxx
new file mode 100644
index 000000000000..f6a37658b79f
--- /dev/null
+++ b/vcl/source/window/syswin.cxx
@@ -0,0 +1,1086 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <tools/debug.hxx>
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/salframe.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/window.h>
+#include <vcl/brdwin.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/event.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/taskpanelist.hxx>
+#include <vcl/unowrap.hxx>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+// =======================================================================
+class SystemWindow::ImplData
+{
+public:
+ ImplData();
+ ~ImplData();
+
+ TaskPaneList* mpTaskPaneList;
+ Size maMaxOutSize;
+ rtl::OUString maRepresentedURL;
+};
+
+SystemWindow::ImplData::ImplData()
+{
+ mpTaskPaneList = NULL;
+ maMaxOutSize = Size( SHRT_MAX, SHRT_MAX );
+}
+
+SystemWindow::ImplData::~ImplData()
+{
+ if( mpTaskPaneList )
+ delete mpTaskPaneList;
+}
+
+// =======================================================================
+
+SystemWindow::SystemWindow( WindowType nType ) :
+ Window( nType )
+{
+ mpImplData = new ImplData;
+ mpWindowImpl->mbSysWin = TRUE;
+ mpWindowImpl->mnActivateMode = ACTIVATE_MODE_GRABFOCUS;
+
+ mpMenuBar = NULL;
+ mbPined = FALSE;
+ mbRollUp = FALSE;
+ mbRollFunc = FALSE;
+ mbDockBtn = FALSE;
+ mbHideBtn = FALSE;
+ mbSysChild = FALSE;
+ mnMenuBarMode = MENUBAR_MODE_NORMAL;
+ mnIcon = 0;
+}
+
+SystemWindow::~SystemWindow()
+{
+ delete mpImplData;
+ mpImplData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+long SystemWindow::Notify( NotifyEvent& rNEvt )
+{
+ // capture KeyEvents for menu handling
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ MenuBar* pMBar = mpMenuBar;
+ if ( !pMBar && ( GetType() == WINDOW_FLOATINGWINDOW ) )
+ {
+ Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
+ if( pWin && pWin->IsSystemWindow() )
+ pMBar = ((SystemWindow*)pWin)->GetMenuBar();
+ }
+ if ( pMBar && pMBar->ImplHandleKeyEvent( *rNEvt.GetKeyEvent(), FALSE ) )
+ return TRUE;
+ }
+
+ return Window::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long SystemWindow::PreNotify( NotifyEvent& rNEvt )
+{
+ // capture KeyEvents for taskpane cycling
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ if( rNEvt.GetKeyEvent()->GetKeyCode().GetCode() == KEY_F6 &&
+ rNEvt.GetKeyEvent()->GetKeyCode().IsMod1() &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsShift() )
+ {
+ // Ctrl-F6 goes directly to the document
+ GrabFocusToDocument();
+ return TRUE;
+ }
+ else
+ {
+ TaskPaneList *pTList = mpImplData->mpTaskPaneList;
+ if( !pTList && ( GetType() == WINDOW_FLOATINGWINDOW ) )
+ {
+ Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
+ if( pWin && pWin->IsSystemWindow() )
+ pTList = ((SystemWindow*)pWin)->mpImplData->mpTaskPaneList;
+ }
+ if( !pTList )
+ {
+ // search topmost system window which is the one to handle dialog/toolbar cycling
+ SystemWindow *pSysWin = this;
+ Window *pWin = this;
+ while( pWin )
+ {
+ pWin = pWin->GetParent();
+ if( pWin && pWin->IsSystemWindow() )
+ pSysWin = (SystemWindow*) pWin;
+ }
+ pTList = pSysWin->mpImplData->mpTaskPaneList;
+ }
+ if( pTList && pTList->HandleKeyEvent( *rNEvt.GetKeyEvent() ) )
+ return TRUE;
+ }
+ }
+ return Window::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+TaskPaneList* SystemWindow::GetTaskPaneList()
+{
+ if( mpImplData->mpTaskPaneList )
+ return mpImplData->mpTaskPaneList ;
+ else
+ {
+ mpImplData->mpTaskPaneList = new TaskPaneList();
+ MenuBar* pMBar = mpMenuBar;
+ if ( !pMBar && ( GetType() == WINDOW_FLOATINGWINDOW ) )
+ {
+ Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
+ if ( pWin && pWin->IsSystemWindow() )
+ pMBar = ((SystemWindow*)pWin)->GetMenuBar();
+ }
+ if( pMBar )
+ mpImplData->mpTaskPaneList->AddWindow( pMBar->ImplGetWindow() );
+ return mpImplData->mpTaskPaneList;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SystemWindow::Close()
+{
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ ImplCallEventListeners( VCLEVENT_WINDOW_CLOSE );
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ ImplRemoveDel( &aDelData );
+
+ if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() )
+ return FALSE;
+
+ // Is Window not closeable, ignore close
+ Window* pBorderWin = ImplGetBorderWindow();
+ WinBits nStyle;
+ if ( pBorderWin )
+ nStyle = pBorderWin->GetStyle();
+ else
+ nStyle = GetStyle();
+ if ( !(nStyle & WB_CLOSEABLE) )
+ {
+ Sound::Beep( SOUND_DISABLE, this );
+ return FALSE;
+ }
+
+ Hide();
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::TitleButtonClick( USHORT )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::Pin()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::Roll()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::Resizing( Size& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetZLevel( BYTE nLevel )
+{
+ Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+ if ( pWindow->mpWindowImpl->mbOverlapWin && !pWindow->mpWindowImpl->mbFrame )
+ {
+ BYTE nOldLevel = pWindow->mpWindowImpl->mpOverlapData->mnTopLevel;
+ pWindow->mpWindowImpl->mpOverlapData->mnTopLevel = nLevel;
+ // Wenn der neue Level groesser als der alte ist, schieben
+ // wir das Fenster nach hinten
+ if ( !IsReallyVisible() && (nLevel > nOldLevel) && pWindow->mpWindowImpl->mpNext )
+ {
+ // Fenster aus der Liste entfernen
+ if ( pWindow->mpWindowImpl->mpPrev )
+ pWindow->mpWindowImpl->mpPrev->mpWindowImpl->mpNext = pWindow->mpWindowImpl->mpNext;
+ else
+ pWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = pWindow->mpWindowImpl->mpNext;
+ pWindow->mpWindowImpl->mpNext->mpWindowImpl->mpPrev = pWindow->mpWindowImpl->mpPrev;
+ pWindow->mpWindowImpl->mpNext = NULL;
+ // und Fenster wieder in die Liste am Ende eintragen
+ pWindow->mpWindowImpl->mpPrev = pWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap;
+ pWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = pWindow;
+ pWindow->mpWindowImpl->mpPrev->mpWindowImpl->mpNext = pWindow;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetRepresentedURL( const rtl::OUString& i_rURL )
+{
+ bool bChanged = (i_rURL != mpImplData->maRepresentedURL);
+ mpImplData->maRepresentedURL = i_rURL;
+ if ( !mbSysChild && bChanged )
+ {
+ const Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+
+ if ( pWindow->mpWindowImpl->mbFrame )
+ pWindow->mpWindowImpl->mpFrame->SetRepresentedURL( i_rURL );
+ }
+}
+// -----------------------------------------------------------------------
+
+const rtl::OUString& SystemWindow::GetRepresentedURL() const
+{
+ return mpImplData->maRepresentedURL;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetIcon( USHORT nIcon )
+{
+ if ( mnIcon == nIcon )
+ return;
+
+ mnIcon = nIcon;
+
+ if ( !mbSysChild )
+ {
+ const Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+
+ if ( pWindow->mpWindowImpl->mbFrame )
+ pWindow->mpWindowImpl->mpFrame->SetIcon( nIcon );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BYTE SystemWindow::GetZLevel() const
+{
+ const Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+ if ( pWindow->mpWindowImpl->mpOverlapData )
+ return pWindow->mpWindowImpl->mpOverlapData->mnTopLevel;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::EnableSaveBackground( BOOL bSave )
+{
+ if( ImplGetSVData()->maWinData.mbNoSaveBackground )
+ bSave = false;
+
+ Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+ if ( pWindow->mpWindowImpl->mbOverlapWin && !pWindow->mpWindowImpl->mbFrame )
+ {
+ pWindow->mpWindowImpl->mpOverlapData->mbSaveBack = bSave;
+ if ( !bSave )
+ pWindow->ImplDeleteOverlapBackground();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SystemWindow::IsSaveBackgroundEnabled() const
+{
+ const Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+ if ( pWindow->mpWindowImpl->mpOverlapData )
+ return pWindow->mpWindowImpl->mpOverlapData->mbSaveBack;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::ShowTitleButton( USHORT nButton, BOOL bVisible )
+{
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ {
+ if ( mbDockBtn != bVisible )
+ {
+ mbDockBtn = bVisible;
+ if ( mpWindowImpl->mpBorderWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetDockButton( bVisible );
+ }
+ }
+ else if ( nButton == TITLE_BUTTON_HIDE )
+ {
+ if ( mbHideBtn != bVisible )
+ {
+ mbHideBtn = bVisible;
+ if ( mpWindowImpl->mpBorderWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetHideButton( bVisible );
+ }
+ }
+ else if ( nButton == TITLE_BUTTON_MENU )
+ {
+ if ( mpWindowImpl->mpBorderWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuButton( bVisible );
+ }
+ else
+ return;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SystemWindow::IsTitleButtonVisible( USHORT nButton ) const
+{
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ return mbDockBtn;
+ else /* if ( nButton == TITLE_BUTTON_HIDE ) */
+ return mbHideBtn;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetPin( BOOL bPin )
+{
+ if ( bPin != mbPined )
+ {
+ mbPined = bPin;
+ if ( mpWindowImpl->mpBorderWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetPin( bPin );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::RollUp()
+{
+ if ( !mbRollUp )
+ {
+ maOrgSize = GetOutputSizePixel();
+ mbRollFunc = TRUE;
+ Size aSize = maRollUpOutSize;
+ if ( !aSize.Width() )
+ aSize.Width() = GetOutputSizePixel().Width();
+ mbRollUp = TRUE;
+ if ( mpWindowImpl->mpBorderWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetRollUp( TRUE, aSize );
+ else
+ SetOutputSizePixel( aSize );
+ mbRollFunc = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::RollDown()
+{
+ if ( mbRollUp )
+ {
+ mbRollUp = FALSE;
+ if ( mpWindowImpl->mpBorderWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetRollUp( FALSE, maOrgSize );
+ else
+ SetOutputSizePixel( maOrgSize );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetMinOutputSizePixel( const Size& rSize )
+{
+ maMinOutSize = rSize;
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMinOutputSize( rSize.Width(), rSize.Height() );
+ if ( mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame )
+ mpWindowImpl->mpBorderWindow->mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
+ }
+ else if ( mpWindowImpl->mbFrame )
+ mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetMaxOutputSizePixel( const Size& rSize )
+{
+ Size aSize( rSize );
+ if( aSize.Width() > SHRT_MAX || aSize.Width() <= 0 )
+ aSize.Width() = SHRT_MAX;
+ if( aSize.Height() > SHRT_MAX || aSize.Height() <= 0 )
+ aSize.Height() = SHRT_MAX;
+
+ mpImplData->maMaxOutSize = aSize;
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMaxOutputSize( aSize.Width(), aSize.Height() );
+ if ( mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame )
+ mpWindowImpl->mpBorderWindow->mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
+ }
+ else if ( mpWindowImpl->mbFrame )
+ mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
+}
+
+const Size& SystemWindow::GetMaxOutputSizePixel() const
+{
+ return mpImplData->maMaxOutSize;
+}
+// -----------------------------------------------------------------------
+
+Size SystemWindow::GetResizeOutputSizePixel() const
+{
+ Size aSize = GetOutputSizePixel();
+ if ( aSize.Width() < maMinOutSize.Width() )
+ aSize.Width() = maMinOutSize.Width();
+ if ( aSize.Height() < maMinOutSize.Height() )
+ aSize.Height() = maMinOutSize.Height();
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplWindowStateFromStr( WindowStateData& rData, const ByteString& rStr )
+{
+ ULONG nValidMask = 0;
+ xub_StrLen nIndex = 0;
+ ByteString aTokenStr;
+
+ aTokenStr = rStr.GetToken( 0, ',', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ rData.SetX( aTokenStr.ToInt32() );
+ if( rData.GetX() > -16384 && rData.GetX() < 16384 )
+ nValidMask |= WINDOWSTATE_MASK_X;
+ else
+ rData.SetX( 0 );
+ }
+ else
+ rData.SetX( 0 );
+ aTokenStr = rStr.GetToken( 0, ',', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ rData.SetY( aTokenStr.ToInt32() );
+ if( rData.GetY() > -16384 && rData.GetY() < 16384 )
+ nValidMask |= WINDOWSTATE_MASK_Y;
+ else
+ rData.SetY( 0 );
+ }
+ else
+ rData.SetY( 0 );
+ aTokenStr = rStr.GetToken( 0, ',', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ rData.SetWidth( aTokenStr.ToInt32() );
+ if( rData.GetWidth() > 0 && rData.GetWidth() < 16384 )
+ nValidMask |= WINDOWSTATE_MASK_WIDTH;
+ else
+ rData.SetWidth( 0 );
+ }
+ else
+ rData.SetWidth( 0 );
+ aTokenStr = rStr.GetToken( 0, ';', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ rData.SetHeight( aTokenStr.ToInt32() );
+ if( rData.GetHeight() > 0 && rData.GetHeight() < 16384 )
+ nValidMask |= WINDOWSTATE_MASK_HEIGHT;
+ else
+ rData.SetHeight( 0 );
+ }
+ else
+ rData.SetHeight( 0 );
+ aTokenStr = rStr.GetToken( 0, ';', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ // #94144# allow Minimize again, should be masked out when read from configuration
+ // 91625 - ignore Minimize
+ ULONG nState = (ULONG)aTokenStr.ToInt32();
+ //nState &= ~(WINDOWSTATE_STATE_MINIMIZED);
+ rData.SetState( nState );
+ nValidMask |= WINDOWSTATE_MASK_STATE;
+ }
+ else
+ rData.SetState( 0 );
+
+ // read maximized pos/size
+ aTokenStr = rStr.GetToken( 0, ',', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ rData.SetMaximizedX( aTokenStr.ToInt32() );
+ if( rData.GetMaximizedX() > -16384 && rData.GetMaximizedX() < 16384 )
+ nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_X;
+ else
+ rData.SetMaximizedX( 0 );
+ }
+ else
+ rData.SetMaximizedX( 0 );
+ aTokenStr = rStr.GetToken( 0, ',', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ rData.SetMaximizedY( aTokenStr.ToInt32() );
+ if( rData.GetMaximizedY() > -16384 && rData.GetMaximizedY() < 16384 )
+ nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_Y;
+ else
+ rData.SetMaximizedY( 0 );
+ }
+ else
+ rData.SetMaximizedY( 0 );
+ aTokenStr = rStr.GetToken( 0, ',', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ rData.SetMaximizedWidth( aTokenStr.ToInt32() );
+ if( rData.GetMaximizedWidth() > 0 && rData.GetMaximizedWidth() < 16384 )
+ nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_WIDTH;
+ else
+ rData.SetMaximizedWidth( 0 );
+ }
+ else
+ rData.SetMaximizedWidth( 0 );
+ aTokenStr = rStr.GetToken( 0, ';', nIndex );
+ if ( aTokenStr.Len() )
+ {
+ rData.SetMaximizedHeight( aTokenStr.ToInt32() );
+ if( rData.GetMaximizedHeight() > 0 && rData.GetMaximizedHeight() < 16384 )
+ nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_HEIGHT;
+ else
+ rData.SetMaximizedHeight( 0 );
+ }
+ else
+ rData.SetMaximizedHeight( 0 );
+
+ // mark valid fields
+ rData.SetMask( nValidMask );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplWindowStateToStr( const WindowStateData& rData, ByteString& rStr )
+{
+ ULONG nValidMask = rData.GetMask();
+ if ( !nValidMask )
+ return;
+
+ if ( nValidMask & WINDOWSTATE_MASK_X )
+ rStr.Append( ByteString::CreateFromInt32( rData.GetX() ) );
+ rStr.Append( ',' );
+ if ( nValidMask & WINDOWSTATE_MASK_Y )
+ rStr.Append( ByteString::CreateFromInt32( rData.GetY() ) );
+ rStr.Append( ',' );
+ if ( nValidMask & WINDOWSTATE_MASK_WIDTH )
+ rStr.Append( ByteString::CreateFromInt32( rData.GetWidth() ) );
+ rStr.Append( ',' );
+ if ( nValidMask & WINDOWSTATE_MASK_HEIGHT )
+ rStr.Append( ByteString::CreateFromInt32( rData.GetHeight() ) );
+ rStr.Append( ';' );
+ if ( nValidMask & WINDOWSTATE_MASK_STATE )
+ {
+ // #94144# allow Minimize again, should be masked out when read from configuration
+ // 91625 - ignore Minimize
+ ULONG nState = rData.GetState();
+ //nState &= ~(WINDOWSTATE_STATE_MINIMIZED);
+ rStr.Append( ByteString::CreateFromInt32( (long)nState ) );
+ }
+ rStr.Append( ';' );
+ if ( nValidMask & WINDOWSTATE_MASK_MAXIMIZED_X )
+ rStr.Append( ByteString::CreateFromInt32( rData.GetMaximizedX() ) );
+ rStr.Append( ',' );
+ if ( nValidMask & WINDOWSTATE_MASK_MAXIMIZED_Y )
+ rStr.Append( ByteString::CreateFromInt32( rData.GetMaximizedY() ) );
+ rStr.Append( ',' );
+ if ( nValidMask & WINDOWSTATE_MASK_MAXIMIZED_WIDTH )
+ rStr.Append( ByteString::CreateFromInt32( rData.GetMaximizedWidth() ) );
+ rStr.Append( ',' );
+ if ( nValidMask & WINDOWSTATE_MASK_MAXIMIZED_HEIGHT )
+ rStr.Append( ByteString::CreateFromInt32( rData.GetMaximizedHeight() ) );
+ rStr.Append( ';' );
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::ImplMoveToScreen( long& io_rX, long& io_rY, long i_nWidth, long i_nHeight, Window* i_pConfigureWin )
+{
+ Rectangle aScreenRect;
+ if( Application::IsMultiDisplay() )
+ {
+ aScreenRect = Application::GetScreenPosSizePixel( GetScreenNumber() );
+ }
+ else
+ {
+ aScreenRect = Application::GetScreenPosSizePixel( 0 );
+ for( unsigned int i = 1; i < Application::GetScreenCount(); i++ )
+ aScreenRect.Union( Application::GetScreenPosSizePixel( i ) );
+ }
+ // unfortunately most of the time width and height are not really known
+ if( i_nWidth < 1 )
+ i_nWidth = 50;
+ if( i_nHeight < 1 )
+ i_nHeight = 50;
+
+ // check left border
+ bool bMove = false;
+ if( io_rX + i_nWidth < aScreenRect.Left() )
+ {
+ bMove = true;
+ io_rX = aScreenRect.Left();
+ }
+ // check right border
+ if( io_rX > aScreenRect.Right() - i_nWidth )
+ {
+ bMove = true;
+ io_rX = aScreenRect.Right() - i_nWidth;
+ }
+ // check top border
+ if( io_rY + i_nHeight < aScreenRect.Top() )
+ {
+ bMove = true;
+ io_rY = aScreenRect.Top();
+ }
+ // check bottom border
+ if( io_rY > aScreenRect.Bottom() - i_nHeight )
+ {
+ bMove = true;
+ io_rY = aScreenRect.Bottom() - i_nHeight;
+ }
+ Window* pParent = i_pConfigureWin->GetParent();
+ if( bMove && pParent )
+ {
+ // calculate absolute screen pos here, since that is what is contained in WindowState
+ Point aParentAbsPos( pParent->OutputToAbsoluteScreenPixel( Point(0,0) ) );
+ Size aParentSizePixel( pParent->GetOutputSizePixel() );
+ Point aPos( (aParentSizePixel.Width() - i_nWidth) / 2,
+ (aParentSizePixel.Height() - i_nHeight) / 2 );
+ io_rX = aParentAbsPos.X() + aPos.X();
+ io_rY = aParentAbsPos.Y() + aPos.Y();
+ }
+}
+
+void SystemWindow::SetWindowStateData( const WindowStateData& rData )
+{
+ ULONG nValidMask = rData.GetMask();
+ if ( !nValidMask )
+ return;
+
+ if ( mbSysChild )
+ return;
+
+ Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+
+ if ( pWindow->mpWindowImpl->mbFrame )
+ {
+ ULONG nState = rData.GetState();
+ SalFrameState aState;
+ aState.mnMask = rData.GetMask();
+ aState.mnX = rData.GetX();
+ aState.mnY = rData.GetY();
+ aState.mnWidth = rData.GetWidth();
+ aState.mnHeight = rData.GetHeight();
+
+ if( rData.GetMask() & (WINDOWSTATE_MASK_WIDTH|WINDOWSTATE_MASK_HEIGHT) )
+ {
+ // #i43799# adjust window state sizes if a minimial output size was set
+ // otherwise the frame and the client might get different sizes
+ if( maMinOutSize.Width() > aState.mnWidth )
+ aState.mnWidth = maMinOutSize.Width();
+ if( maMinOutSize.Height() > aState.mnHeight )
+ aState.mnHeight = maMinOutSize.Height();
+ }
+
+ aState.mnMaximizedX = rData.GetMaximizedX();
+ aState.mnMaximizedY = rData.GetMaximizedY();
+ aState.mnMaximizedWidth = rData.GetMaximizedWidth();
+ aState.mnMaximizedHeight = rData.GetMaximizedHeight();
+ // #94144# allow Minimize again, should be masked out when read from configuration
+ // 91625 - ignore Minimize
+ //nState &= ~(WINDOWSTATE_STATE_MINIMIZED);
+ aState.mnState = nState & SAL_FRAMESTATE_SYSTEMMASK;
+
+ // normalize window positions onto screen
+ ImplMoveToScreen( aState.mnX, aState.mnY, aState.mnWidth, aState.mnHeight, pWindow );
+ ImplMoveToScreen( aState.mnMaximizedX, aState.mnMaximizedY, aState.mnMaximizedWidth, aState.mnMaximizedHeight, pWindow );
+
+ // #96568# avoid having multiple frames at the same screen location
+ // do the check only if not maximized
+ if( !((rData.GetMask() & WINDOWSTATE_MASK_STATE) && (nState & WINDOWSTATE_STATE_MAXIMIZED)) )
+ if( rData.GetMask() & (WINDOWSTATE_MASK_POS|WINDOWSTATE_MASK_WIDTH|WINDOWSTATE_MASK_HEIGHT) )
+ {
+ Rectangle aDesktop = GetDesktopRectPixel();
+ ImplSVData *pSVData = ImplGetSVData();
+ Window *pWin = pSVData->maWinData.mpFirstFrame;
+ BOOL bWrapped = FALSE;
+ while( pWin )
+ {
+ if( !pWin->ImplIsRealParentPath( this ) && ( pWin != this ) &&
+ pWin->ImplGetWindow()->IsTopWindow() && pWin->mpWindowImpl->mbReallyVisible )
+ {
+ SalFrameGeometry g = pWin->mpWindowImpl->mpFrame->GetGeometry();
+ if( abs(g.nX-aState.mnX) < 2 && abs(g.nY-aState.mnY) < 5 )
+ {
+ long displacement = g.nTopDecoration ? g.nTopDecoration : 20;
+ if( (unsigned long) (aState.mnX + displacement + aState.mnWidth + g.nRightDecoration) > (unsigned long) aDesktop.nRight ||
+ (unsigned long) (aState.mnY + displacement + aState.mnHeight + g.nBottomDecoration) > (unsigned long) aDesktop.nBottom )
+ {
+ // displacing would leave screen
+ aState.mnX = g.nLeftDecoration ? g.nLeftDecoration : 10; // should result in (0,0)
+ aState.mnY = displacement;
+ if( bWrapped ||
+ (unsigned long) (aState.mnX + displacement + aState.mnWidth + g.nRightDecoration) > (unsigned long) aDesktop.nRight ||
+ (unsigned long) (aState.mnY + displacement + aState.mnHeight + g.nBottomDecoration) > (unsigned long) aDesktop.nBottom )
+ break; // further displacement not possible -> break
+ // avoid endless testing
+ bWrapped = TRUE;
+ }
+ else
+ {
+ // displace
+ aState.mnX += displacement;
+ aState.mnY += displacement;
+ }
+ pWin = pSVData->maWinData.mpFirstFrame; // check new pos again
+ }
+ }
+ pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+ }
+
+ mpWindowImpl->mpFrame->SetWindowState( &aState );
+
+ // do a synchronous resize for layout reasons
+ // but use rData only when the window is not to be maximized (#i38089#)
+ // otherwise we have no useful size information
+ if( (rData.GetMask() & WINDOWSTATE_MASK_STATE) && (nState & WINDOWSTATE_STATE_MAXIMIZED) )
+ {
+ // query maximized size from frame
+ SalFrameGeometry aGeometry = mpWindowImpl->mpFrame->GetGeometry();
+
+ // but use it only if it is different from the restore size (rData)
+ // as currently only on windows the exact size of a maximized window
+ // can be computed without actually showing the window
+ if( aGeometry.nWidth != rData.GetWidth() || aGeometry.nHeight != rData.GetHeight() )
+ ImplHandleResize( pWindow, aGeometry.nWidth, aGeometry.nHeight );
+ }
+ else
+ if( rData.GetMask() & (WINDOWSTATE_MASK_WIDTH|WINDOWSTATE_MASK_HEIGHT) )
+ ImplHandleResize( pWindow, aState.mnWidth, aState.mnHeight ); // #i43799# use aState and not rData, see above
+ }
+ else
+ {
+ USHORT nPosSize = 0;
+ if ( nValidMask & WINDOWSTATE_MASK_X )
+ nPosSize |= WINDOW_POSSIZE_X;
+ if ( nValidMask & WINDOWSTATE_MASK_Y )
+ nPosSize |= WINDOW_POSSIZE_Y;
+ if ( nValidMask & WINDOWSTATE_MASK_WIDTH )
+ nPosSize |= WINDOW_POSSIZE_WIDTH;
+ if ( nValidMask & WINDOWSTATE_MASK_HEIGHT )
+ nPosSize |= WINDOW_POSSIZE_HEIGHT;
+
+ if( IsRollUp() )
+ RollDown();
+
+ long nX = rData.GetX();
+ long nY = rData.GetY();
+ long nWidth = rData.GetWidth();
+ long nHeight = rData.GetHeight();
+ const SalFrameGeometry& rGeom = pWindow->mpWindowImpl->mpFrame->GetGeometry();
+ if( nX < 0 )
+ nX = 0;
+ if( nX + nWidth > (long) rGeom.nWidth )
+ nX = rGeom.nWidth - nWidth;
+ if( nY < 0 )
+ nY = 0;
+ if( nY + nHeight > (long) rGeom.nHeight )
+ nY = rGeom.nHeight - nHeight;
+ SetPosSizePixel( nX, nY, nWidth, nHeight, nPosSize );
+ maOrgSize = Size( nWidth, nHeight );
+
+ // 91625 - ignore Minimize
+ if ( nValidMask & WINDOWSTATE_MASK_STATE )
+ {
+ ULONG nState = rData.GetState();
+ if ( nState & WINDOWSTATE_STATE_ROLLUP )
+ RollUp();
+ else
+ RollDown();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::GetWindowStateData( WindowStateData& rData ) const
+{
+ ULONG nValidMask = rData.GetMask();
+ if ( !nValidMask )
+ return;
+
+ if ( mbSysChild )
+ return;
+
+ const Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+
+ if ( pWindow->mpWindowImpl->mbFrame )
+ {
+ SalFrameState aState;
+ aState.mnMask = 0xFFFFFFFF;
+ if ( mpWindowImpl->mpFrame->GetWindowState( &aState ) )
+ {
+ if ( nValidMask & WINDOWSTATE_MASK_X )
+ rData.SetX( aState.mnX );
+ if ( nValidMask & WINDOWSTATE_MASK_Y )
+ rData.SetY( aState.mnY );
+ if ( nValidMask & WINDOWSTATE_MASK_WIDTH )
+ rData.SetWidth( aState.mnWidth );
+ if ( nValidMask & WINDOWSTATE_MASK_HEIGHT )
+ rData.SetHeight( aState.mnHeight );
+ if ( aState.mnMask & SAL_FRAMESTATE_MASK_MAXIMIZED_X )
+ {
+ rData.SetMaximizedX( aState.mnMaximizedX );
+ nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_X;
+ }
+ if ( aState.mnMask & SAL_FRAMESTATE_MASK_MAXIMIZED_Y )
+ {
+ rData.SetMaximizedY( aState.mnMaximizedY );
+ nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_Y;
+ }
+ if ( aState.mnMask & SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH )
+ {
+ rData.SetMaximizedWidth( aState.mnMaximizedWidth );
+ nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_WIDTH;
+ }
+ if ( aState.mnMask & SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT )
+ {
+ rData.SetMaximizedHeight( aState.mnMaximizedHeight );
+ nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_HEIGHT;
+ }
+ if ( nValidMask & WINDOWSTATE_MASK_STATE )
+ {
+ // #94144# allow Minimize again, should be masked out when read from configuration
+ // 91625 - ignore Minimize
+ if ( !(nValidMask&WINDOWSTATE_MASK_MINIMIZED) )
+ aState.mnState &= ~(WINDOWSTATE_STATE_MINIMIZED);
+ rData.SetState( aState.mnState );
+ }
+ rData.SetMask( nValidMask );
+ }
+ else
+ rData.SetMask( 0 );
+ }
+ else
+ {
+ Point aPos = GetPosPixel();
+ Size aSize = GetSizePixel();
+ ULONG nState = 0;
+
+ if ( IsRollUp() )
+ {
+ aSize.Height() += maOrgSize.Height();
+ nState |= WINDOWSTATE_STATE_ROLLUP;
+ }
+
+ if ( nValidMask & WINDOWSTATE_MASK_X )
+ rData.SetX( aPos.X() );
+ if ( nValidMask & WINDOWSTATE_MASK_Y )
+ rData.SetY( aPos.Y() );
+ if ( nValidMask & WINDOWSTATE_MASK_WIDTH )
+ rData.SetWidth( aSize.Width() );
+ if ( nValidMask & WINDOWSTATE_MASK_HEIGHT )
+ rData.SetHeight( aSize.Height() );
+ if ( nValidMask & WINDOWSTATE_MASK_STATE )
+ rData.SetState( nState );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetWindowState( const ByteString& rStr )
+{
+ if ( !rStr.Len() )
+ return;
+
+ WindowStateData aData;
+ ImplWindowStateFromStr( aData, rStr );
+ SetWindowStateData( aData );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString SystemWindow::GetWindowState( ULONG nMask ) const
+{
+ WindowStateData aData;
+ aData.SetMask( nMask );
+ GetWindowStateData( aData );
+
+ ByteString aStr;
+ ImplWindowStateToStr( aData, aStr );
+ return aStr;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetMenuBar( MenuBar* pMenuBar )
+{
+ if ( mpMenuBar != pMenuBar )
+ {
+ MenuBar* pOldMenuBar = mpMenuBar;
+ Window* pOldWindow = NULL;
+ Window* pNewWindow=NULL;
+ mpMenuBar = pMenuBar;
+
+ if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) )
+ {
+ if ( pOldMenuBar )
+ pOldWindow = pOldMenuBar->ImplGetWindow();
+ else
+ pOldWindow = NULL;
+ if ( pOldWindow )
+ {
+ ImplCallEventListeners( VCLEVENT_WINDOW_MENUBARREMOVED, (void*) pOldMenuBar );
+ pOldWindow->SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
+ }
+ if ( pMenuBar )
+ {
+ DBG_ASSERT( !pMenuBar->pWindow, "SystemWindow::SetMenuBar() - MenuBars can only set in one SystemWindow at time" );
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarWindow( pNewWindow = MenuBar::ImplCreate( mpWindowImpl->mpBorderWindow, pOldWindow, pMenuBar ) );
+ ImplCallEventListeners( VCLEVENT_WINDOW_MENUBARADDED, (void*) pMenuBar );
+ }
+ else
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarWindow( NULL );
+ ImplToBottomChild();
+ if ( pOldMenuBar )
+ {
+ BOOL bDelete = (pMenuBar == 0) ? TRUE : FALSE;
+ if( bDelete && pOldWindow )
+ {
+ if( mpImplData->mpTaskPaneList )
+ mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
+ }
+ MenuBar::ImplDestroy( pOldMenuBar, bDelete );
+ if( bDelete )
+ pOldWindow = NULL; // will be deleted in MenuBar::ImplDestroy,
+ }
+
+ }
+ else
+ {
+ if( pMenuBar )
+ pNewWindow = pMenuBar->ImplGetWindow();
+ if( pOldMenuBar )
+ pOldWindow = pOldMenuBar->ImplGetWindow();
+ }
+
+ // update taskpane list to make menubar accessible
+ if( mpImplData->mpTaskPaneList )
+ {
+ if( pOldWindow )
+ mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
+ if( pNewWindow )
+ mpImplData->mpTaskPaneList->AddWindow( pNewWindow );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetMenuBarMode( USHORT nMode )
+{
+ if ( mnMenuBarMode != nMode )
+ {
+ mnMenuBarMode = nMode;
+ if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) )
+ {
+ if ( nMode == MENUBAR_MODE_HIDE )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarMode( TRUE );
+ else
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarMode( FALSE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SystemWindow::ImplIsInTaskPaneList( Window* pWin )
+{
+ if( mpImplData && mpImplData->mpTaskPaneList )
+ return mpImplData->mpTaskPaneList->IsInList( pWin );
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+unsigned int SystemWindow::GetScreenNumber() const
+{
+ return mpWindowImpl->mpFrame->maGeometry.nScreenNumber;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetScreenNumber( unsigned int nScreen)
+{
+ mpWindowImpl->mpFrame->SetScreenNumber( nScreen );
+}
diff --git a/vcl/source/window/tabdlg.cxx b/vcl/source/window/tabdlg.cxx
new file mode 100644
index 000000000000..874881c0c5ef
--- /dev/null
+++ b/vcl/source/window/tabdlg.cxx
@@ -0,0 +1,276 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <vcl/fixed.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabdlg.hxx>
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+
+
+
+// =======================================================================
+
+void TabDialog::ImplInitTabDialogData()
+{
+ mpFixedLine = NULL;
+ mpViewWindow = NULL;
+ meViewAlign = WINDOWALIGN_LEFT;
+ mbPosControls = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void TabDialog::ImplPosControls()
+{
+ Size aCtrlSize( IMPL_MINSIZE_BUTTON_WIDTH, IMPL_MINSIZE_BUTTON_HEIGHT );
+ long nDownCtrl = 0;
+ long nOffY = 0;
+ TabControl* pTabControl = NULL;
+
+ Window* pChild = GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->IsVisible() && (pChild != mpViewWindow) )
+ {
+ if ( pChild->GetType() == WINDOW_TABCONTROL )
+ pTabControl = (TabControl*)pChild;
+ else if ( pTabControl )
+ {
+ long nTxtWidth = pChild->GetCtrlTextWidth( pChild->GetText() );
+ nTxtWidth += IMPL_EXTRA_BUTTON_WIDTH;
+ if ( nTxtWidth > aCtrlSize.Width() )
+ aCtrlSize.Width() = nTxtWidth;
+ long nTxtHeight = pChild->GetTextHeight();
+ nTxtHeight += IMPL_EXTRA_BUTTON_HEIGHT;
+ if ( nTxtHeight > aCtrlSize.Height() )
+ aCtrlSize.Height() = nTxtHeight;
+ nDownCtrl++;
+ }
+ else
+ {
+ long nHeight = pChild->GetSizePixel().Height();
+ if ( nHeight > nOffY )
+ nOffY = nHeight;
+ }
+ }
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ // Haben wir ueberhaupt ein TabControl
+ if ( pTabControl )
+ {
+ // Offset bei weiteren Controls um einen weiteren Abstand anpassen
+ if ( nOffY )
+ nOffY += IMPL_DIALOG_BAR_OFFSET*2 + 2;
+
+ Point aTabOffset( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+nOffY );
+ Size aTabSize = pTabControl->GetSizePixel();
+ Size aDlgSize( aTabSize.Width() + IMPL_DIALOG_OFFSET*2,
+ aTabSize.Height() + IMPL_DIALOG_OFFSET*2 + nOffY );
+ long nBtnEx = 0;
+
+ // Preview-Fenster beruecksichtigen und die Groessen/Offsets anpassen
+ if ( mpViewWindow && mpViewWindow->IsVisible() )
+ {
+ long nViewOffX = 0;
+ long nViewOffY = 0;
+ long nViewWidth = 0;
+ long nViewHeight = 0;
+ USHORT nViewPosFlags = WINDOW_POSSIZE_POS;
+ Size aViewSize = mpViewWindow->GetSizePixel();
+ if ( meViewAlign == WINDOWALIGN_TOP )
+ {
+ nViewOffX = aTabOffset.X();
+ nViewOffY = nOffY+IMPL_DIALOG_OFFSET;
+ nViewWidth = aTabSize.Width();
+ nViewPosFlags |= WINDOW_POSSIZE_WIDTH;
+ aTabOffset.Y() += aViewSize.Height()+IMPL_DIALOG_OFFSET;
+ aDlgSize.Height() += aViewSize.Height()+IMPL_DIALOG_OFFSET;
+ }
+ else if ( meViewAlign == WINDOWALIGN_BOTTOM )
+ {
+ nViewOffX = aTabOffset.X();
+ nViewOffY = aTabOffset.Y()+aTabSize.Height()+IMPL_DIALOG_OFFSET;
+ nViewWidth = aTabSize.Width();
+ nViewPosFlags |= WINDOW_POSSIZE_WIDTH;
+ aDlgSize.Height() += aViewSize.Height()+IMPL_DIALOG_OFFSET;
+ }
+ else if ( meViewAlign == WINDOWALIGN_RIGHT )
+ {
+ nViewOffX = aTabOffset.X()+aTabSize.Width()+IMPL_DIALOG_OFFSET;
+ nViewOffY = aTabOffset.Y();
+ nViewHeight = aTabSize.Height();
+ nViewPosFlags |= WINDOW_POSSIZE_HEIGHT;
+ aDlgSize.Width() += aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ nBtnEx = aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ }
+ else // meViewAlign == WINDOWALIGN_LEFT
+ {
+ nViewOffX = IMPL_DIALOG_OFFSET;
+ nViewOffY = aTabOffset.Y();
+ nViewHeight = aTabSize.Height();
+ nViewPosFlags |= WINDOW_POSSIZE_HEIGHT;
+ aTabOffset.X() += aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ aDlgSize.Width() += aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ nBtnEx = aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ }
+
+ mpViewWindow->SetPosSizePixel( nViewOffX, nViewOffY,
+ nViewWidth, nViewHeight,
+ nViewPosFlags );
+ }
+
+ // Positionierung vornehmen
+ pTabControl->SetPosPixel( aTabOffset );
+
+ // Alle anderen Childs positionieren
+ BOOL bTabCtrl = FALSE;
+ int nLines = 0;
+ long nX;
+ long nY = aDlgSize.Height();
+ long nTopX = IMPL_DIALOG_OFFSET;
+
+ // Unter Windows 95 werden die Buttons rechtsbuendig angeordnet
+ nX = IMPL_DIALOG_OFFSET;
+ long nCtrlBarWidth = ((aCtrlSize.Width()+IMPL_DIALOG_OFFSET)*nDownCtrl)-IMPL_DIALOG_OFFSET;
+ if ( nCtrlBarWidth <= (aTabSize.Width()+nBtnEx) )
+ nX = (aTabSize.Width()+nBtnEx) - nCtrlBarWidth + IMPL_DIALOG_OFFSET;
+
+ Window* pChild2 = GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild2 )
+ {
+ if ( pChild2->IsVisible() && (pChild2 != mpViewWindow) )
+ {
+ if ( pChild2 == pTabControl )
+ bTabCtrl = TRUE;
+ else if ( bTabCtrl )
+ {
+ if ( !nLines )
+ nLines = 1;
+
+ if ( nX+aCtrlSize.Width()-IMPL_DIALOG_OFFSET > (aTabSize.Width()+nBtnEx) )
+ {
+ nY += aCtrlSize.Height()+IMPL_DIALOG_OFFSET;
+ nX = IMPL_DIALOG_OFFSET;
+ nLines++;
+ }
+
+ pChild2->SetPosSizePixel( Point( nX, nY ), aCtrlSize );
+ nX += aCtrlSize.Width()+IMPL_DIALOG_OFFSET;
+ }
+ else
+ {
+ Size aChildSize = pChild2->GetSizePixel();
+ pChild2->SetPosPixel( Point( nTopX, (nOffY-aChildSize.Height())/2 ) );
+ nTopX += aChildSize.Width()+2;
+ }
+ }
+
+ pChild2 = pChild2->GetWindow( WINDOW_NEXT );
+ }
+
+ aDlgSize.Height() += nLines * (aCtrlSize.Height()+IMPL_DIALOG_OFFSET);
+ SetOutputSizePixel( aDlgSize );
+ }
+
+ // Offset merken
+ if ( nOffY )
+ {
+ Size aDlgSize = GetOutputSizePixel();
+ if ( !mpFixedLine )
+ mpFixedLine = new FixedLine( this );
+ mpFixedLine->SetPosSizePixel( Point( 0, nOffY ),
+ Size( aDlgSize.Width(), 2 ) );
+ mpFixedLine->Show();
+ }
+
+ mbPosControls = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+TabDialog::TabDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_TABDIALOG )
+{
+ ImplInitTabDialogData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+TabDialog::TabDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_TABDIALOG )
+{
+ ImplInitTabDialogData();
+ rResId.SetRT( RSC_TABDIALOG );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+TabDialog::~TabDialog()
+{
+ if ( mpFixedLine )
+ delete mpFixedLine;
+}
+
+// -----------------------------------------------------------------------
+
+void TabDialog::Resize()
+{
+// !!! In the future the controls should be automaticly rearrange
+// !!! if the window is resized
+// !!! if ( !IsRollUp() )
+// !!! ImplPosControls();
+}
+
+// -----------------------------------------------------------------------
+
+void TabDialog::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ // Calculate the Layout only for the initialized state
+ if ( mbPosControls )
+ ImplPosControls();
+ }
+ Dialog::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void TabDialog::AdjustLayout()
+{
+ ImplPosControls();
+}
+
diff --git a/vcl/source/window/tabpage.cxx b/vcl/source/window/tabpage.cxx
new file mode 100644
index 000000000000..0589d57009f4
--- /dev/null
+++ b/vcl/source/window/tabpage.cxx
@@ -0,0 +1,216 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <tools/ref.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/event.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/bitmapex.hxx>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+
+
+
+
+// =======================================================================
+
+void TabPage::ImplInit( Window* pParent, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+
+ Window::ImplInit( pParent, nStyle, NULL );
+
+ ImplInitSettings();
+
+ // if the tabpage is drawn (ie filled) by a native widget, make sure all contols will have transparent background
+ // otherwise they will paint with a wrong background
+ if( IsNativeControlSupported(CTRL_TAB_BODY, PART_ENTIRE_CONTROL) && GetParent() && (GetParent()->GetType() == WINDOW_TABCONTROL) )
+ EnableChildTransparentMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::ImplInitSettings()
+{
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TabPage::TabPage( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_TABPAGE )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+TabPage::TabPage( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_TABPAGE )
+{
+ rResId.SetRT( RSC_TABPAGE );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( GetSettings().GetStyleSettings().GetAutoMnemonic() )
+ ImplWindowAutoMnemonic( this );
+ // FIXME: no layouting, workaround some clipping issues
+ ImplAdjustNWFSizes();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::Paint( const Rectangle& )
+{
+ // draw native tabpage only inside tabcontrols, standalone tabpages look ugly (due to bad dialog design)
+ if( IsNativeControlSupported(CTRL_TAB_BODY, PART_ENTIRE_CONTROL) && GetParent() && (GetParent()->GetType() == WINDOW_TABCONTROL) )
+ {
+ const ImplControlValue aControlValue;
+
+ ControlState nState = CTRL_STATE_ENABLED;
+ int part = PART_ENTIRE_CONTROL;
+ if ( !IsEnabled() )
+ nState &= ~CTRL_STATE_ENABLED;
+ if ( HasFocus() )
+ nState |= CTRL_STATE_FOCUSED;
+ Point aPoint;
+ // pass the whole window region to NWF as the tab body might be a gradient or bitmap
+ // that has to be scaled properly, clipping makes sure that we do not paint too much
+ Rectangle aCtrlRegion( aPoint, GetOutputSizePixel() );
+ DrawNativeControl( CTRL_TAB_BODY, part, aCtrlRegion, nState,
+ aControlValue, rtl::OUString() );
+ }
+}
+
+// -----------------------------------------------------------------------
+void TabPage::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+
+ Wallpaper aWallpaper = GetBackground();
+ if ( !aWallpaper.IsBitmap() )
+ ImplInitSettings();
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetLineColor();
+
+ if ( aWallpaper.IsBitmap() )
+ pDev->DrawBitmapEx( aPos, aSize, aWallpaper.GetBitmap() );
+ else
+ {
+ if( aWallpaper.GetColor() == COL_AUTO )
+ pDev->SetFillColor( GetSettings().GetStyleSettings().GetDialogColor() );
+ else
+ pDev->SetFillColor( aWallpaper.GetColor() );
+ pDev->DrawRect( Rectangle( aPos, aSize ) );
+ }
+
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::ActivatePage()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::DeactivatePage()
+{
+}
+
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > TabPage::CreateAccessible()
+{
+ // TODO: remove this method (incompatible)
+
+ return Window::CreateAccessible();
+}
diff --git a/vcl/source/window/taskpanelist.cxx b/vcl/source/window/taskpanelist.cxx
new file mode 100644
index 000000000000..c09dc464b809
--- /dev/null
+++ b/vcl/source/window/taskpanelist.cxx
@@ -0,0 +1,398 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <vcl/svdata.hxx>
+#include <tools/rcid.h>
+#include <vcl/dockwin.hxx>
+
+#include <vcl/taskpanelist.hxx>
+#include <functional>
+#include <algorithm>
+
+// can't have static linkage because SUNPRO 5.2 complains
+Point ImplTaskPaneListGetPos( const Window *w )
+{
+ Point pos;
+ if( w->ImplIsDockingWindow() )
+ {
+ pos = ((DockingWindow*)w)->GetPosPixel();
+ Window *pF = ((DockingWindow*)w)->GetFloatingWindow();
+ if( pF )
+ pos = pF->OutputToAbsoluteScreenPixel( pF->ScreenToOutputPixel( pos ) );
+ else
+ pos = w->OutputToAbsoluteScreenPixel( pos );
+ }
+ else
+ pos = w->OutputToAbsoluteScreenPixel( w->GetPosPixel() );
+
+ return pos;
+}
+
+// compares window pos left-to-right
+struct LTRSort : public ::std::binary_function< const Window*, const Window*, bool >
+{
+ bool operator()( const Window* w1, const Window* w2 ) const
+ {
+ Point pos1(ImplTaskPaneListGetPos( w1 ));
+ Point pos2(ImplTaskPaneListGetPos( w2 ));
+
+ if( pos1.X() == pos2.X() )
+ return ( pos1.Y() < pos2.Y() );
+ else
+ return ( pos1.X() < pos2.X() );
+ }
+};
+struct LTRSortBackward : public ::std::binary_function< const Window*, const Window*, bool >
+{
+ bool operator()( const Window* w2, const Window* w1 ) const
+ {
+ Point pos1(ImplTaskPaneListGetPos( w1 ));
+ Point pos2(ImplTaskPaneListGetPos( w2 ));
+
+ if( pos1.X() == pos2.X() )
+ return ( pos1.Y() < pos2.Y() );
+ else
+ return ( pos1.X() < pos2.X() );
+ }
+};
+
+// --------------------------------------------------
+
+static void ImplTaskPaneListGrabFocus( Window *pWindow )
+{
+ // put focus in child of floating windows which is typically a toolbar
+ // that can deal with the focus
+ if( pWindow->ImplIsFloatingWindow() && pWindow->GetWindow( WINDOW_FIRSTCHILD ) )
+ pWindow = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ pWindow->GrabFocus();
+}
+
+// --------------------------------------------------
+
+TaskPaneList::TaskPaneList()
+{
+}
+
+TaskPaneList::~TaskPaneList()
+{
+}
+
+// --------------------------------------------------
+
+void TaskPaneList::AddWindow( Window *pWindow )
+{
+#if OSL_DEBUG_LEVEL > 0
+ bool bDockingWindow=false;
+ bool bToolbox=false;
+ bool bDialog=false;
+ bool bUnknown=false;
+#endif
+
+ if( pWindow )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ if( pWindow->GetType() == RSC_DOCKINGWINDOW )
+ bDockingWindow = true;
+ else if( pWindow->GetType() == RSC_TOOLBOX )
+ bToolbox = true;
+ else if( pWindow->IsDialog() )
+ bDialog = true;
+ else
+ bUnknown = true;
+#endif
+
+ ::std::vector< Window* >::iterator insertionPos = mTaskPanes.end();
+ for ( ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ p != mTaskPanes.end();
+ ++p
+ )
+ {
+ if ( *p == pWindow )
+ // avoid duplicates
+ return;
+
+ // If the new window is the child of an existing pane window, or vice versa,
+ // ensure that in our pane list, *first* the child window appears, *then*
+ // the ancestor window.
+ // This is necessary for HandleKeyEvent: There, the list is traveled from the
+ // beginning, until the first window is found which has the ChildPathFocus. Now
+ // if this would be the ancestor window of another pane window, this would fudge
+ // the result
+ // 2004-09-27 - fs@openoffice.org, while fixing #i33573#, which included replacing
+ // the original fix for #98916# with this one here.
+ if ( pWindow->IsWindowOrChild( *p ) )
+ {
+ insertionPos = p + 1;
+ break;
+ }
+ if ( (*p)->IsWindowOrChild( pWindow ) )
+ {
+ insertionPos = p;
+ break;
+ }
+ }
+
+ mTaskPanes.insert( insertionPos, pWindow );
+ pWindow->ImplIsInTaskPaneList( TRUE );
+ }
+}
+
+// --------------------------------------------------
+
+void TaskPaneList::RemoveWindow( Window *pWindow )
+{
+ ::std::vector< Window* >::iterator p;
+ p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), pWindow );
+ if( p != mTaskPanes.end() )
+ {
+ mTaskPanes.erase( p );
+ pWindow->ImplIsInTaskPaneList( FALSE );
+ }
+}
+
+// --------------------------------------------------
+
+BOOL TaskPaneList::IsInList( Window *pWindow )
+{
+ ::std::vector< Window* >::iterator p;
+ p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), pWindow );
+ if( p != mTaskPanes.end() )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// --------------------------------------------------
+
+BOOL TaskPaneList::HandleKeyEvent( KeyEvent aKeyEvent )
+{
+
+ // F6 cycles through everything and works always
+
+ // MAV, #i104204#
+ // The old design was the following one:
+ // < Ctrl-TAB cycles through Menubar, Toolbars and Floatingwindows only and is
+ // < only active if one of those items has the focus
+ //
+ // Since the design of Ctrl-Tab looks to be inconsistent ( non-modal dialogs are not reachable
+ // and the shortcut conflicts with tab-control shortcut ), it is no more supported
+ BOOL bSplitterOnly = FALSE;
+ BOOL bFocusInList = FALSE;
+ KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ BOOL bForward = !aKeyCode.IsShift();
+ if( aKeyCode.GetCode() == KEY_F6 ) // F6
+ {
+ bSplitterOnly = aKeyCode.IsMod1() && aKeyCode.IsShift();
+
+ // is the focus in the list ?
+ ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ while( p != mTaskPanes.end() )
+ {
+ Window *pWin = *p;
+ if( pWin->HasChildPathFocus( TRUE ) )
+ {
+ bFocusInList = TRUE;
+
+ // Ctrl-F6 goes directly to the document
+ if( !pWin->IsDialog() && aKeyCode.IsMod1() && !aKeyCode.IsShift() )
+ {
+ pWin->GrabFocusToDocument();
+ return TRUE;
+ }
+
+ // activate next task pane
+ Window *pNextWin = NULL;
+
+ if( bSplitterOnly )
+ pNextWin = FindNextSplitter( *p, TRUE );
+ else
+ pNextWin = FindNextFloat( *p, bForward );
+
+ if( pNextWin != pWin )
+ {
+ ImplGetSVData()->maWinData.mbNoSaveFocus = TRUE;
+ ImplTaskPaneListGrabFocus( pNextWin );
+ ImplGetSVData()->maWinData.mbNoSaveFocus = FALSE;
+ }
+ else
+ {
+ // forward key if no splitter found
+ if( bSplitterOnly )
+ return FALSE;
+
+ // we did not find another taskpane, so
+ // put focus back into document
+ pWin->GrabFocusToDocument();
+ }
+
+ return TRUE;
+ }
+ else
+ p++;
+ }
+
+ // the focus is not in the list: activate first float if F6 was pressed
+ if( !bFocusInList )
+ {
+ Window *pWin;
+ if( bSplitterOnly )
+ pWin = FindNextSplitter( NULL, TRUE );
+ else
+ pWin = FindNextFloat( NULL, bForward );
+ if( pWin )
+ {
+ ImplTaskPaneListGrabFocus( pWin );
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+// --------------------------------------------------
+
+// returns next valid pane
+Window* TaskPaneList::FindNextPane( Window *pWindow, BOOL bForward )
+{
+ if( bForward )
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
+ else
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
+
+ ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ while( p != mTaskPanes.end() )
+ {
+ if( *p == pWindow )
+ {
+ unsigned n = mTaskPanes.size();
+ while( --n )
+ {
+ if( ++p == mTaskPanes.end() )
+ p = mTaskPanes.begin();
+ if( (*p)->IsReallyVisible() && !(*p)->IsDialog() && !(*p)->ImplIsSplitter() )
+ {
+ pWindow = *p;
+ break;
+ }
+ }
+ break;
+ }
+ else
+ ++p;
+ }
+
+ return pWindow;
+}
+
+// --------------------------------------------------
+
+// returns next splitter
+Window* TaskPaneList::FindNextSplitter( Window *pWindow, BOOL bForward )
+{
+ if( bForward )
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
+ else
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
+
+ ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ while( p != mTaskPanes.end() )
+ {
+ if( !pWindow || *p == pWindow )
+ {
+ unsigned n = mTaskPanes.size();
+ while( --n )
+ {
+ if( pWindow ) // increment before test
+ ++p;
+ if( p == mTaskPanes.end() )
+ p = mTaskPanes.begin();
+ if( (*p)->ImplIsSplitter() && (*p)->IsReallyVisible() && !(*p)->IsDialog() && (*p)->GetParent()->HasChildPathFocus() )
+ {
+ pWindow = *p;
+ break;
+ }
+ if( !pWindow ) // increment after test, otherwise first element is skipped
+ ++p;
+ }
+ break;
+ }
+ else
+ ++p;
+ }
+
+ return pWindow;
+}
+
+// --------------------------------------------------
+
+// returns first valid item (regardless of type) if pWindow==0, otherwise returns next valid float
+Window* TaskPaneList::FindNextFloat( Window *pWindow, BOOL bForward )
+{
+ if( bForward )
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
+ else
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
+
+ ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ while( p != mTaskPanes.end() )
+ {
+ if( !pWindow || *p == pWindow )
+ {
+ while( p != mTaskPanes.end() )
+ {
+ if( pWindow ) // increment before test
+ ++p;
+ if( p == mTaskPanes.end() )
+ break; // do not wrap, send focus back to document at end of list
+ /* #i83908# do not use the menubar if it is native and invisible
+ this relies on MenuBar::ImplCreate setting the height of the menubar
+ to 0 in this case
+ */
+ if( (*p)->IsReallyVisible() && !(*p)->ImplIsSplitter() &&
+ ( (*p)->GetType() != WINDOW_MENUBARWINDOW || (*p)->GetSizePixel().Height() > 0 )
+ )
+ {
+ pWindow = *p;
+ break;
+ }
+ if( !pWindow ) // increment after test, otherwise first element is skipped
+ ++p;
+ }
+ break;
+ }
+ else
+ ++p;
+ }
+
+ return pWindow;
+}
+
+// --------------------------------------------------
+
diff --git a/vcl/source/window/toolbox.cxx b/vcl/source/window/toolbox.cxx
new file mode 100644
index 000000000000..cde91a8dcd97
--- /dev/null
+++ b/vcl/source/window/toolbox.cxx
@@ -0,0 +1,6333 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <rtl/logfile.hxx>
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/event.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/accel.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/help.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/spin.h>
+#include <vcl/toolbox.hxx>
+#include <vcl/toolbox.h>
+#include <vcl/bitmap.hxx>
+#include <tools/poly.hxx>
+#include <vcl/salframe.hxx>
+#include <vcl/mnemonic.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/window.h>
+
+#include <string.h>
+#include <vector>
+#include <math.h>
+
+// =======================================================================
+
+DBG_NAMEEX( Window )
+
+// =======================================================================
+
+#define SMALLBUTTON_HSIZE 7
+#define SMALLBUTTON_VSIZE 7
+
+#define SMALLBUTTON_OFF_NORMAL_X 3
+#define SMALLBUTTON_OFF_NORMAL_Y 3
+#define SMALLBUTTON_OFF_CHECKED_X 4
+#define SMALLBUTTON_OFF_CHECKED_Y 4
+#define SMALLBUTTON_OFF_PRESSED_X 5
+#define SMALLBUTTON_OFF_PRESSED_Y 5
+
+#define OUTBUTTON_SIZE 6
+#define OUTBUTTON_BORDER 4
+#define OUTBUTTON_OFF_NORMAL_X 1
+#define OUTBUTTON_OFF_NORMAL_Y 1
+
+// -----------------------------------------------------------------------
+
+#define DEF_MIN_WIDTH 8
+#define DEF_MIN_HEIGHT 8
+#define DEF_TEXT_WIDTH 40
+
+#define TB_TEXTOFFSET 2
+#define TB_IMAGETEXTOFFSET 3
+#define TB_LINESPACING 3
+#define TB_SPIN_SIZE 14
+#define TB_SPIN_OFFSET 2
+#define TB_NEXT_SIZE 22
+#define TB_NEXT_OFFSET 2
+#define TB_BORDER_OFFSET1 4
+#define TB_BORDER_OFFSET2 2
+#define TB_CUSTOMIZE_OFFSET 2
+#define TB_RESIZE_OFFSET 3
+#define TB_MAXLINES 5
+#define TB_MAXNOSCROLL 32765
+
+#define TB_MIN_WIN_WIDTH 20
+
+#define TB_CALCMODE_HORZ 1
+#define TB_CALCMODE_VERT 2
+#define TB_CALCMODE_FLOAT 3
+
+#define TB_WBLINESIZING (WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL)
+
+#define TB_MAX_GROUPS 100
+
+#define DOCK_LINEHSIZE ((USHORT)0x0001)
+#define DOCK_LINEVSIZE ((USHORT)0x0002)
+#define DOCK_LINERIGHT ((USHORT)0x1000)
+#define DOCK_LINEBOTTOM ((USHORT)0x2000)
+#define DOCK_LINELEFT ((USHORT)0x4000)
+#define DOCK_LINETOP ((USHORT)0x8000)
+#define DOCK_LINEOFFSET 3
+
+
+// -----------------------------------------------------------------------
+static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, USHORT highlight, BOOL bChecked, BOOL bEnabled, BOOL bIsWindow );
+// -----------------------------------------------------------------------
+
+struct ImplToolSize
+{
+ long mnWidth;
+ long mnHeight;
+ USHORT mnLines;
+};
+
+struct ImplToolSizeArray
+{
+ long mnLength;
+ long mnLastEntry;
+ ImplToolSize* mpSize;
+
+ ImplToolSizeArray() { mpSize = NULL; mnLength = 0; mnLastEntry = 0; }
+ ~ImplToolSizeArray() { if( mpSize ) delete [] mpSize; mnLength = 0; }
+};
+
+// -----------------------------------------------------------------------
+
+DECLARE_LIST( ImplTBList, ToolBox* )
+
+class ImplTBDragMgr
+{
+private:
+ ImplTBList* mpBoxList;
+ ToolBox* mpDragBox;
+ Point maMouseOff;
+ Rectangle maRect;
+ Rectangle maStartRect;
+ Accelerator maAccel;
+ long mnMinWidth;
+ long mnMaxWidth;
+ USHORT mnLineMode;
+ USHORT mnStartLines;
+ void* mpCustomizeData;
+ BOOL mbCustomizeMode;
+ BOOL mbResizeMode;
+ BOOL mbShowDragRect;
+
+public:
+ ImplTBDragMgr();
+ ~ImplTBDragMgr();
+
+ void Insert( ToolBox* pBox )
+ { mpBoxList->Insert( pBox ); }
+ void Remove( ToolBox* pBox )
+ { mpBoxList->Remove( pBox ); }
+ ULONG Count() const
+ { return mpBoxList->Count(); }
+
+ ToolBox* FindToolBox( const Rectangle& rRect );
+
+ void StartDragging( ToolBox* pDragBox,
+ const Point& rPos, const Rectangle& rRect,
+ USHORT nLineMode, BOOL bResizeItem,
+ void* pData = NULL );
+ void Dragging( const Point& rPos );
+ void EndDragging( BOOL bOK = TRUE );
+ void HideDragRect() { if ( mbShowDragRect ) mpDragBox->HideTracking(); }
+ void UpdateDragRect();
+ DECL_LINK( SelectHdl, Accelerator* );
+
+ void StartCustomizeMode();
+ void EndCustomizeMode();
+ BOOL IsCustomizeMode() { return mbCustomizeMode; }
+ BOOL IsResizeMode() { return mbResizeMode; }
+};
+
+// -----------------------------------------------------------------------
+
+static ImplTBDragMgr* ImplGetTBDragMgr()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maCtrlData.mpTBDragMgr )
+ pSVData->maCtrlData.mpTBDragMgr = new ImplTBDragMgr;
+ return pSVData->maCtrlData.mpTBDragMgr;
+}
+
+// -----------------------------------------------------------------------
+
+int ToolBox::ImplGetDragWidth( ToolBox* pThis )
+{
+ #define TB_DRAGWIDTH 8 // the default width of the grip
+
+ int width = TB_DRAGWIDTH;
+ if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
+ {
+
+ ImplControlValue aControlValue;
+ Point aPoint;
+ Rectangle aContent, aBound;
+ Rectangle aArea( aPoint, pThis->GetOutputSizePixel() );
+
+ if ( pThis->GetNativeControlRegion(CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
+ aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
+ {
+ width = pThis->mbHorz ? aContent.GetWidth() : aContent.GetHeight();
+ }
+ }
+ return width;
+}
+
+ButtonType determineButtonType( ImplToolItem* pItem, ButtonType defaultType )
+{
+ ButtonType tmpButtonType = defaultType;
+ ToolBoxItemBits nBits( pItem->mnBits & 0x300 );
+ if ( nBits & TIB_TEXTICON ) // item has custom setting
+ {
+ tmpButtonType = BUTTON_SYMBOLTEXT;
+ if ( nBits == TIB_TEXT_ONLY )
+ tmpButtonType = BUTTON_TEXT;
+ else if ( nBits == TIB_ICON_ONLY )
+ tmpButtonType = BUTTON_SYMBOL;
+ }
+ return tmpButtonType;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplUpdateDragArea( ToolBox *pThis )
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
+ if( pWrapper )
+ {
+ if ( pThis->ImplIsFloatingMode() || pWrapper->IsLocked() )
+ pWrapper->SetDragArea( Rectangle() );
+ else
+ {
+ if( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
+ pWrapper->SetDragArea( Rectangle( 0, 0, ImplGetDragWidth( pThis ), pThis->GetOutputSizePixel().Height() ) );
+ else
+ pWrapper->SetDragArea( Rectangle( 0, 0, pThis->GetOutputSizePixel().Width(), ImplGetDragWidth( pThis ) ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplCalcBorder( WindowAlign eAlign, long& rLeft, long& rTop,
+ long& rRight, long& rBottom, const ToolBox *pThis )
+{
+ if( pThis->ImplIsFloatingMode() || !(pThis->mnWinStyle & WB_BORDER) )
+ {
+ // no border in floating mode
+ rLeft = rTop = rRight = rBottom = 0;
+ return;
+ }
+
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
+
+ // reserve dragarea only for dockable toolbars
+ int dragwidth = ( pWrapper && !pWrapper->IsLocked() ) ? ImplGetDragWidth( (ToolBox*)pThis ) : 0;
+
+ // no shadow border for dockable toolbars
+ int borderwidth = pWrapper ? 0: 2;
+
+ if ( eAlign == WINDOWALIGN_TOP )
+ {
+ rLeft = borderwidth+dragwidth;
+ rTop = borderwidth;
+ rRight = borderwidth;
+ rBottom = 0;
+ }
+ else if ( eAlign == WINDOWALIGN_LEFT )
+ {
+ rLeft = borderwidth;
+ rTop = borderwidth+dragwidth;
+ rRight = 0;
+ rBottom = borderwidth;
+ }
+ else if ( eAlign == WINDOWALIGN_BOTTOM )
+ {
+ rLeft = borderwidth+dragwidth;
+ rTop = 0;
+ rRight = borderwidth;
+ rBottom = borderwidth;
+ }
+ else
+ {
+ rLeft = 0;
+ rTop = borderwidth+dragwidth;
+ rRight = borderwidth;
+ rBottom = borderwidth;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCheckUpdate( ToolBox *pThis )
+{
+ // remove any pending invalidates to avoid
+ // have them triggered when paint is locked (see mpData->mbIsPaintLocked)
+ // which would result in erasing the background only and not painting any items
+ // this must not be done when we're already in Paint()
+
+ // this is only required for transparent toolbars (see ImplDrawTransparentBackground() )
+ if( !pThis->IsBackground() && pThis->HasPaintEvent() && !pThis->IsInPaint() )
+ pThis->Update();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDrawGrip( ToolBox* pThis )
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
+ if( pWrapper && !pWrapper->GetDragArea().IsEmpty() )
+ {
+ // execute pending paint requests
+ ImplCheckUpdate( pThis );
+
+ BOOL bNativeOk = FALSE;
+ if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_HORZ : PART_THUMB_VERT ) )
+ {
+ ToolbarValue aToolbarValue;
+ aToolbarValue.maGripRect = pWrapper->GetDragArea();
+ Point aPt;
+ Rectangle aCtrlRegion( aPt, pThis->GetOutputSizePixel() );
+ ControlState nState = CTRL_STATE_ENABLED;
+
+ bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
+ aCtrlRegion, nState, aToolbarValue, rtl::OUString() );
+ }
+
+ if( bNativeOk )
+ return;
+
+ const StyleSettings& rStyleSettings = pThis->GetSettings().GetStyleSettings();
+ pThis->SetLineColor( rStyleSettings.GetShadowColor() );
+
+ Size aSz ( pThis->GetOutputSizePixel() );
+
+ if ( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
+ {
+ int height = (int) (0.6 * aSz.Height() + 0.5);
+ int i = (aSz.Height() - height) / 2;
+ height += i;
+ while( i <= height )
+ {
+ int x = ImplGetDragWidth( pThis ) / 2;
+
+ pThis->DrawPixel( Point(x, i), rStyleSettings.GetDarkShadowColor() );
+ pThis->DrawPixel( Point(x+1, i), rStyleSettings.GetShadowColor() );
+
+ pThis->DrawPixel( Point(x, i+1), rStyleSettings.GetShadowColor() );
+ pThis->DrawPixel( Point(x+1, i+1), rStyleSettings.GetFaceColor() );
+ pThis->DrawPixel( Point(x+2, i+1), Color(COL_WHITE) );
+
+ pThis->DrawPixel( Point(x+1, i+2), Color(COL_WHITE) );
+ pThis->DrawPixel( Point(x+2, i+2), Color(COL_WHITE) );
+ i+=4;
+ }
+ }
+ else
+ {
+ int width = (int) (0.6 * aSz.Width() + 0.5);
+ int i = (aSz.Width() - width) / 2;
+ width += i;
+ while( i <= width )
+ {
+ int y = ImplGetDragWidth(pThis) / 2;
+
+ pThis->DrawPixel( Point(i, y), rStyleSettings.GetDarkShadowColor() );
+ pThis->DrawPixel( Point(i+1, y), rStyleSettings.GetShadowColor() );
+
+ pThis->DrawPixel( Point(i, y+1), rStyleSettings.GetShadowColor() );
+ pThis->DrawPixel( Point(i+1, y+1), rStyleSettings.GetFaceColor() );
+ pThis->DrawPixel( Point(i+2, y+1), Color(COL_WHITE) );
+
+ pThis->DrawPixel( Point(i+1, y+2), Color(COL_WHITE) );
+ pThis->DrawPixel( Point(i+2, y+2), Color(COL_WHITE) );
+ i+=4;
+ }
+ }
+ }
+}
+
+void ToolBox::ImplDrawGradientBackground( ToolBox* pThis, ImplDockingWindowWrapper * )
+{
+ // draw a nice gradient
+
+ Color startCol, endCol;
+ startCol = pThis->GetSettings().GetStyleSettings().GetFaceGradientColor();
+ endCol = pThis->GetSettings().GetStyleSettings().GetFaceColor();
+ if( pThis->GetSettings().GetStyleSettings().GetHighContrastMode() )
+ // no 'extreme' gradient when high contrast
+ startCol = endCol;
+
+ Gradient g;
+ g.SetAngle( pThis->mbHorz ? 0 : 900 );
+ g.SetStyle( GRADIENT_LINEAR );
+
+ g.SetStartColor( startCol );
+ g.SetEndColor( endCol );
+
+ BOOL bLineColor = pThis->IsLineColor();
+ Color aOldCol = pThis->GetLineColor();
+ pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetShadowColor() );
+
+ Size aFullSz( pThis->GetOutputSizePixel() );
+ Size aLineSz( aFullSz );
+
+ // use the linesize only when floating
+ // full window height is used when docked (single line)
+ if( pThis->ImplIsFloatingMode() )
+ {
+ long nLineSize;
+ if( pThis->mbHorz )
+ {
+ nLineSize = pThis->mnMaxItemHeight;
+ if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
+ nLineSize = pThis->mnWinHeight;
+
+ aLineSz.Height() = nLineSize;
+ }
+ else
+ {
+ nLineSize = pThis->mnMaxItemWidth;
+ aLineSz.Width() = nLineSize;
+ }
+ }
+
+ long nLeft, nTop, nRight, nBottom;
+ ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
+
+ Size aTopLineSz( aLineSz );
+ Size aBottomLineSz( aLineSz );
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ {
+ if( pThis->mbHorz )
+ {
+ aTopLineSz.Height() += TB_BORDER_OFFSET2 + nTop;
+ aBottomLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
+
+ if( pThis->mnCurLines == 1 )
+ aTopLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
+ }
+ else
+ {
+ aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
+ aBottomLineSz.Width() += TB_BORDER_OFFSET1 + nRight;
+
+ if( pThis->mnCurLines == 1 )
+ aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
+ }
+ }
+
+ if( pThis->mbHorz )
+ {
+ aTopLineSz.Height() += pThis->mnBorderY;
+ if( pThis->mnCurLines == 1 )
+ aTopLineSz.Height() += pThis->mnBorderY;
+
+ aBottomLineSz.Height() += pThis->mnBorderY;
+ }
+ else
+ {
+ aTopLineSz.Width() += pThis->mnBorderX;
+ if( pThis->mnCurLines == 1 )
+ aTopLineSz.Width() += pThis->mnBorderX;
+
+ aBottomLineSz.Width() += pThis->mnBorderX;
+ }
+
+
+ if ( pThis->mnWinStyle & WB_LINESPACING )
+ {
+ if( pThis->mbHorz )
+ {
+ aLineSz.Height() += TB_LINESPACING;
+ if( pThis->mnCurLines > 1 )
+ aTopLineSz.Height() += TB_LINESPACING;
+ }
+ else
+ {
+ aLineSz.Width() += TB_LINESPACING;
+ if( pThis->mnCurLines > 1 )
+ aTopLineSz.Width() += TB_LINESPACING;
+ }
+ }
+
+ if( pThis->mbHorz )
+ {
+ long y = 0;
+ BOOL bDrawSep = FALSE; // pThis->ImplIsFloatingMode() && ( pThis->mnWinStyle & WB_LINESPACING );
+
+ pThis->DrawGradient( Rectangle( 0, y, aTopLineSz.Width(), y+aTopLineSz.Height()), g );
+ y += aTopLineSz.Height();
+
+ if ( bDrawSep )
+ pThis->DrawLine( Point(0, y-2), Point(aTopLineSz.Width(), y-2) );
+
+ while( y < (pThis->mnDY - aBottomLineSz.Height()) )
+ {
+ pThis->DrawGradient( Rectangle( 0, y, aLineSz.Width(), y+aLineSz.Height()), g);
+ y += aLineSz.Height();
+
+ if ( bDrawSep )
+ pThis->DrawLine( Point(0, y-2), Point(aLineSz.Width(), y-2) );
+ }
+
+ pThis->DrawGradient( Rectangle( 0, y, aBottomLineSz.Width(), y+aBottomLineSz.Height()), g );
+ if ( bDrawSep )
+ pThis->DrawLine( Point(0, y-2), Point(aBottomLineSz.Width(), y-2) );
+ }
+ else
+ {
+ long x = 0;
+
+ pThis->DrawGradient( Rectangle( x, 0, x+aTopLineSz.Width(), aTopLineSz.Height()), g );
+ x += aTopLineSz.Width();
+
+ while( x < (pThis->mnDX - aBottomLineSz.Width()) )
+ {
+ pThis->DrawGradient( Rectangle( x, 0, x+aLineSz.Width(), aLineSz.Height()), g);
+ x += aLineSz.Width();
+ }
+
+ pThis->DrawGradient( Rectangle( x, 0, x+aBottomLineSz.Width(), aBottomLineSz.Height()), g );
+ }
+
+ if( bLineColor )
+ pThis->SetLineColor( aOldCol );
+
+}
+
+BOOL ToolBox::ImplDrawNativeBackground( ToolBox* pThis, const Region & )
+{
+ // use NWF
+ Point aPt;
+ Rectangle aCtrlRegion( aPt, pThis->GetOutputSizePixel() );
+ ControlState nState = CTRL_STATE_ENABLED;
+
+ return pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT,
+ aCtrlRegion, nState, ImplControlValue(), rtl::OUString() );
+}
+
+void ToolBox::ImplDrawTransparentBackground( ToolBox* pThis, const Region &rRegion )
+{
+ // just invalidate to trigger paint of the parent
+
+ const bool bOldPaintLock = pThis->mpData->mbIsPaintLocked;
+ pThis->mpData->mbIsPaintLocked = true;
+
+ // send an invalidate to the first opaque parent and invalidate the whole hierarchy from there (noclipchildren)
+ pThis->Invalidate( rRegion, INVALIDATE_UPDATE|INVALIDATE_NOCLIPCHILDREN );
+
+ pThis->mpData->mbIsPaintLocked = bOldPaintLock;
+}
+
+void ToolBox::ImplDrawConstantBackground( ToolBox* pThis, const Region &rRegion, BOOL bIsInPopupMode )
+{
+ // draw a constant color
+ if( !bIsInPopupMode )
+ // default background
+ pThis->Erase( rRegion.GetBoundRect() );
+ else
+ {
+ // use different color in popupmode
+ pThis->DrawWallpaper( rRegion.GetBoundRect(),
+ Wallpaper( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() ) );
+ }
+}
+
+
+void ToolBox::ImplDrawBackground( ToolBox* pThis, const Rectangle &rRect )
+{
+ // execute pending paint requests
+ ImplCheckUpdate( pThis );
+
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
+ BOOL bIsInPopupMode = pThis->ImplIsInPopupMode();
+
+ Region aPaintRegion( rRect );
+
+ // make sure we do not invalidate/erase too much
+ if( pThis->IsInPaint() )
+ aPaintRegion.Intersect( pThis->GetActiveClipRegion() );
+
+ pThis->Push( PUSH_CLIPREGION );
+ pThis->IntersectClipRegion( aPaintRegion );
+
+
+ if( !pWrapper /*|| bIsInPopupMode*/ )
+ {
+ // no gradient for ordinary toolbars (not dockable)
+ if( !pThis->IsBackground() && !pThis->IsInPaint() )
+ ImplDrawTransparentBackground( pThis, aPaintRegion );
+ else
+ ImplDrawConstantBackground( pThis, aPaintRegion, bIsInPopupMode );
+ }
+ else
+ {
+ // toolbars known to the dockingmanager will be drawn using NWF or a gradient
+ // docked toolbars are transparent and NWF is already used in the docking area which is their common background
+ // so NWF is used here for floating toolbars only
+ BOOL bNativeOk = FALSE;
+ if( pThis->ImplIsFloatingMode() && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL) )
+ bNativeOk = ImplDrawNativeBackground( pThis, aPaintRegion );
+
+ if( !bNativeOk )
+ {
+ if( !pThis->IsBackground() )
+ {
+ if( !pThis->IsInPaint() )
+ ImplDrawTransparentBackground( pThis, aPaintRegion );
+ }
+ else
+ ImplDrawGradientBackground( pThis, pWrapper );
+ }
+ }
+
+ // restore clip region
+ pThis->Pop();
+}
+
+void ToolBox::ImplErase( ToolBox* pThis, const Rectangle &rRect, BOOL bHighlight, BOOL bHasOpenPopup )
+{
+ // the background of non NWF buttons is painted in a constant color
+ // to have the same highlight color (transparency in DrawSelectionBackground())
+ // items with open popups will also painted using a constant color
+ if( !pThis->mpData->mbNativeButtons &&
+ (bHighlight || ! (((Window*) pThis)->GetStyle() & WB_3DLOOK ) ) )
+ {
+ if( (((Window*) pThis)->GetStyle() & WB_3DLOOK ) )
+ {
+ pThis->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ pThis->SetLineColor();
+ if( bHasOpenPopup )
+ // choose the same color as the popup will use
+ pThis->SetFillColor( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() );
+ else
+ pThis->SetFillColor( Color( COL_WHITE ) );
+
+ pThis->DrawRect( rRect );
+ pThis->Pop();
+ }
+ else
+ ImplDrawBackground( pThis, rRect );
+ }
+ else
+ ImplDrawBackground( pThis, rRect );
+}
+
+void ToolBox::ImplDrawBorder( ToolBox* pWin )
+{
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+ long nDX = pWin->mnDX;
+ long nDY = pWin->mnDY;
+
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pWin );
+
+ // draw borders for ordinary toolbars only (not dockable)
+ if( pWrapper )
+ return;
+
+ if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
+ {
+ // draw bottom border
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ // draw top border
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) );
+
+ if ( (pWin->meAlign == WINDOWALIGN_LEFT) || (pWin->meAlign == WINDOWALIGN_RIGHT) )
+ {
+ if ( pWin->meAlign == WINDOWALIGN_LEFT )
+ {
+ // draw left-bottom border
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ // draw right-bottom border
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ }
+ }
+
+
+ if ( pWin->meAlign == WINDOWALIGN_BOTTOM || pWin->meAlign == WINDOWALIGN_TOP )
+ {
+ // draw right border
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-1 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static bool ImplIsFixedControl( const ImplToolItem *pItem )
+{
+ return ( pItem->mpWindow &&
+ (pItem->mpWindow->GetType() == WINDOW_FIXEDTEXT ||
+ pItem->mpWindow->GetType() == WINDOW_FIXEDLINE ||
+ pItem->mpWindow->GetType() == WINDOW_GROUPBOX) );
+}
+
+// -----------------------------------------------------------------------
+
+const ImplToolItem *ToolBox::ImplGetFirstClippedItem( const ToolBox* pThis )
+{
+ std::vector< ImplToolItem >::const_iterator it;
+ it = pThis->mpData->m_aItems.begin();
+ while ( it != pThis->mpData->m_aItems.end() )
+ {
+ if( it->IsClipped() )
+ return &(*it);
+ ++it;
+ }
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Size ToolBox::ImplCalcSize( const ToolBox* pThis, USHORT nCalcLines, USHORT nCalcMode )
+{
+ long nMax;
+ long nLeft = 0;
+ long nTop = 0;
+ long nRight = 0;
+ long nBottom = 0;
+ Size aSize;
+ WindowAlign eOldAlign = pThis->meAlign;
+ BOOL bOldHorz = pThis->mbHorz;
+ BOOL bOldAssumeDocked = pThis->mpData->mbAssumeDocked;
+ BOOL bOldAssumeFloating = pThis->mpData->mbAssumeFloating;
+
+ if ( nCalcMode )
+ {
+ BOOL bOldFloatingMode = pThis->ImplIsFloatingMode();
+
+ pThis->mpData->mbAssumeDocked = FALSE;
+ pThis->mpData->mbAssumeFloating = FALSE;
+
+ if ( nCalcMode == TB_CALCMODE_HORZ )
+ {
+ pThis->mpData->mbAssumeDocked = TRUE; // force non-floating mode during calculation
+ ImplCalcBorder( WINDOWALIGN_TOP, nLeft, nTop, nRight, nBottom, pThis );
+ ((ToolBox*)pThis)->mbHorz = TRUE;
+ if ( pThis->mbHorz != bOldHorz )
+ ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
+ }
+ else if ( nCalcMode == TB_CALCMODE_VERT )
+ {
+ pThis->mpData->mbAssumeDocked = TRUE; // force non-floating mode during calculation
+ ImplCalcBorder( WINDOWALIGN_LEFT, nLeft, nTop, nRight, nBottom, pThis );
+ ((ToolBox*)pThis)->mbHorz = FALSE;
+ if ( pThis->mbHorz != bOldHorz )
+ ((ToolBox*)pThis)->meAlign = WINDOWALIGN_LEFT;
+ }
+ else if ( nCalcMode == TB_CALCMODE_FLOAT )
+ {
+ pThis->mpData->mbAssumeFloating = TRUE; // force non-floating mode during calculation
+ nLeft = nTop = nRight = nBottom = 0;
+ ((ToolBox*)pThis)->mbHorz = TRUE;
+ if ( pThis->mbHorz != bOldHorz )
+ ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
+ }
+
+ if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) ||
+ (pThis->ImplIsFloatingMode() != bOldFloatingMode ) )
+ ((ToolBox*)pThis)->mbCalc = TRUE;
+ }
+ else
+ ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
+
+ ((ToolBox*)pThis)->ImplCalcItem();
+
+ if( !nCalcMode && pThis->ImplIsFloatingMode() )
+ {
+ aSize = ImplCalcFloatSize( ((ToolBox*)pThis), nCalcLines );
+ }
+ else
+ {
+ if ( pThis->mbHorz )
+ {
+ if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
+ aSize.Height() = nCalcLines * pThis->mnWinHeight;
+ else
+ aSize.Height() = nCalcLines * pThis->mnMaxItemHeight;
+
+ if ( pThis->mnWinStyle & WB_LINESPACING )
+ aSize.Height() += (nCalcLines-1)*TB_LINESPACING;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ aSize.Height() += (TB_BORDER_OFFSET2*2) + nTop + nBottom;
+
+ nMax = 0;
+ ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
+ if ( nMax )
+ aSize.Width() += nMax;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ aSize.Width() += (TB_BORDER_OFFSET1*2) + nLeft + nRight;
+ }
+ else
+ {
+ aSize.Width() = nCalcLines * pThis->mnMaxItemWidth;
+
+ if ( pThis->mnWinStyle & WB_LINESPACING )
+ aSize.Width() += (nCalcLines-1)*TB_LINESPACING;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ aSize.Width() += (TB_BORDER_OFFSET2*2) + nLeft + nRight;
+
+ nMax = 0;
+ ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
+ if ( nMax )
+ aSize.Height() += nMax;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ aSize.Height() += (TB_BORDER_OFFSET1*2) + nTop + nBottom;
+ }
+ }
+ // restore previous values
+ if ( nCalcMode )
+ {
+ pThis->mpData->mbAssumeDocked = bOldAssumeDocked;
+ pThis->mpData->mbAssumeFloating = bOldAssumeFloating;
+ if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) )
+ {
+ ((ToolBox*)pThis)->meAlign = eOldAlign;
+ ((ToolBox*)pThis)->mbHorz = bOldHorz;
+ ((ToolBox*)pThis)->mbCalc = TRUE;
+ }
+ }
+
+ if ( aSize.Width() )
+ aSize.Width() += pThis->mnBorderX*2;
+ if ( aSize.Height() )
+ aSize.Height() += pThis->mnBorderY*2;
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplCalcFloatSizes( ToolBox* pThis )
+{
+ if ( pThis->mpFloatSizeAry )
+ return;
+
+ // calculate the minimal size, i.e. where the biggest item just fits
+ long nCalcSize = 0;
+
+ std::vector< ImplToolItem >::const_iterator it;
+ it = pThis->mpData->m_aItems.begin();
+ while ( it != pThis->mpData->m_aItems.end() )
+ {
+ if ( it->mbVisible )
+ {
+ if ( it->mpWindow )
+ {
+ long nTempSize = it->mpWindow->GetSizePixel().Width();
+ if ( nTempSize > nCalcSize )
+ nCalcSize = nTempSize;
+ }
+ else
+ {
+ if( it->maItemSize.Width() > nCalcSize )
+ nCalcSize = it->maItemSize.Width();
+ }
+ }
+ ++it;
+ }
+
+ // calc an upper bound for ImplCalcBreaks below
+ long upperBoundWidth = nCalcSize * pThis->mpData->m_aItems.size();
+
+ USHORT i;
+ USHORT nLines;
+ USHORT nCalcLines;
+ USHORT nTempLines;
+ long nHeight;
+ long nMaxLineWidth;
+ nCalcLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, TRUE );
+
+ pThis->mpFloatSizeAry = new ImplToolSizeArray;
+ pThis->mpFloatSizeAry->mpSize = new ImplToolSize[nCalcLines];
+ pThis->mpFloatSizeAry->mnLength = nCalcLines;
+
+ memset( pThis->mpFloatSizeAry->mpSize, 0, sizeof( ImplToolSize )*nCalcLines );
+ i = 0;
+ nTempLines = nLines = nCalcLines;
+ while ( nLines )
+ {
+ nHeight = ImplCalcSize( pThis, nTempLines, TB_CALCMODE_FLOAT ).Height();
+ pThis->mpFloatSizeAry->mnLastEntry = i;
+ pThis->mpFloatSizeAry->mpSize[i].mnHeight = nHeight;
+ pThis->mpFloatSizeAry->mpSize[i].mnLines = nTempLines;
+ pThis->mpFloatSizeAry->mpSize[i].mnWidth = nMaxLineWidth+(TB_BORDER_OFFSET1*2);
+ nLines--;
+ if ( nLines )
+ {
+ do
+ {
+ nCalcSize += pThis->mnMaxItemWidth;
+ nTempLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, TRUE );
+ }
+ while ( (nCalcSize < upperBoundWidth) && (nLines < nTempLines) && (nTempLines != 1) );
+ if ( nTempLines < nLines )
+ nLines = nTempLines;
+ }
+ i++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size ToolBox::ImplCalcFloatSize( ToolBox* pThis, USHORT& rLines )
+{
+ ImplCalcFloatSizes( pThis );
+
+ if ( !rLines )
+ {
+ rLines = pThis->mnFloatLines;
+ if ( !rLines )
+ rLines = pThis->mnLines;
+ }
+
+ USHORT i = 0;
+ while ( i < pThis->mpFloatSizeAry->mnLastEntry &&
+ rLines < pThis->mpFloatSizeAry->mpSize[i].mnLines )
+ i++;
+
+ Size aSize( pThis->mpFloatSizeAry->mpSize[i].mnWidth,
+ pThis->mpFloatSizeAry->mpSize[i].mnHeight );
+ rLines = pThis->mpFloatSizeAry->mpSize[i].mnLines;
+ if ( pThis->maNextToolBoxStr.Len() && pThis->mbScroll )
+ aSize.Width() += TB_NEXT_SIZE-TB_NEXT_OFFSET;
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplCalcMinMaxFloatSize( ToolBox* pThis, Size& rMinSize, Size& rMaxSize )
+{
+ ImplCalcFloatSizes( pThis );
+
+ USHORT i = 0;
+ rMinSize = Size( pThis->mpFloatSizeAry->mpSize[i].mnWidth, pThis->mpFloatSizeAry->mpSize[i].mnHeight );
+ rMaxSize = Size( pThis->mpFloatSizeAry->mpSize[i].mnWidth, pThis->mpFloatSizeAry->mpSize[i].mnHeight );
+ while ( ++i <= pThis->mpFloatSizeAry->mnLastEntry )
+ {
+ if( pThis->mpFloatSizeAry->mpSize[i].mnWidth < rMinSize.Width() )
+ rMinSize.Width() = pThis->mpFloatSizeAry->mpSize[i].mnWidth;
+ if( pThis->mpFloatSizeAry->mpSize[i].mnHeight < rMinSize.Height() )
+ rMinSize.Height() = pThis->mpFloatSizeAry->mpSize[i].mnHeight;
+
+ if( pThis->mpFloatSizeAry->mpSize[i].mnWidth > rMaxSize.Width() )
+ rMaxSize.Width() = pThis->mpFloatSizeAry->mpSize[i].mnWidth;
+ if( pThis->mpFloatSizeAry->mpSize[i].mnHeight > rMaxSize.Height() )
+ rMaxSize.Height() = pThis->mpFloatSizeAry->mpSize[i].mnHeight;
+ }
+}
+
+void ToolBox::ImplSetMinMaxFloatSize( ToolBox *pThis )
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
+ Size aMinSize, aMaxSize;
+ ImplCalcMinMaxFloatSize( pThis, aMinSize, aMaxSize );
+ if( pWrapper )
+ {
+ pWrapper->SetMinOutputSizePixel( aMinSize );
+ pWrapper->SetMaxOutputSizePixel( aMaxSize );
+ pWrapper->ShowTitleButton( TITLE_BUTTON_MENU, ( pThis->GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE) ? TRUE : FALSE );
+ }
+ else
+ {
+ // TODO: change SetMinOutputSizePixel to be not inline
+ pThis->SetMinOutputSizePixel( aMinSize );
+ pThis->SetMaxOutputSizePixel( aMaxSize );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+
+USHORT ToolBox::ImplCalcLines( ToolBox* pThis, long nToolSize )
+{
+ long nLineHeight;
+
+ if ( pThis->mbHorz )
+ {
+ if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
+ nLineHeight = pThis->mnWinHeight;
+ else
+ nLineHeight = pThis->mnMaxItemHeight;
+ }
+ else
+ nLineHeight = pThis->mnMaxItemWidth;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ nToolSize -= TB_BORDER_OFFSET2*2;
+
+ if ( pThis->mnWinStyle & WB_LINESPACING )
+ {
+ nLineHeight += TB_LINESPACING;
+ nToolSize += TB_LINESPACING;
+ }
+
+ // #i91917# always report at least one line
+ long nLines = nToolSize/nLineHeight;
+ if( nLines < 1 )
+ nLines = 1;
+
+ return static_cast<USHORT>(nLines);
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::ImplTestLineSize( ToolBox* pThis, const Point& rPos )
+{
+ if ( !pThis->ImplIsFloatingMode() &&
+ (!pThis->mbScroll || (pThis->mnLines > 1) || (pThis->mnCurLines > pThis->mnVisLines)) )
+ {
+ WindowAlign eAlign = pThis->GetAlign();
+
+ if ( eAlign == WINDOWALIGN_LEFT )
+ {
+ if ( rPos.X() > pThis->mnDX-DOCK_LINEOFFSET )
+ return DOCK_LINEHSIZE | DOCK_LINERIGHT;
+ }
+ else if ( eAlign == WINDOWALIGN_TOP )
+ {
+ if ( rPos.Y() > pThis->mnDY-DOCK_LINEOFFSET )
+ return DOCK_LINEVSIZE | DOCK_LINEBOTTOM;
+ }
+ else if ( eAlign == WINDOWALIGN_RIGHT )
+ {
+ if ( rPos.X() < DOCK_LINEOFFSET )
+ return DOCK_LINEHSIZE | DOCK_LINELEFT;
+ }
+ else if ( eAlign == WINDOWALIGN_BOTTOM )
+ {
+ if ( rPos.Y() < DOCK_LINEOFFSET )
+ return DOCK_LINEVSIZE | DOCK_LINETOP;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplLineSizing( ToolBox* pThis, const Point& rPos, Rectangle& rRect,
+ USHORT nLineMode )
+{
+ BOOL mbHorz;
+ long nOneLineSize;
+ long nCurSize;
+ long nMaxSize;
+ long nSize;
+ Size aSize;
+
+ if ( nLineMode & DOCK_LINERIGHT )
+ {
+ nCurSize = rPos.X() - rRect.Left();
+ mbHorz = FALSE;
+ }
+ else if ( nLineMode & DOCK_LINEBOTTOM )
+ {
+ nCurSize = rPos.Y() - rRect.Top();
+ mbHorz = TRUE;
+ }
+ else if ( nLineMode & DOCK_LINELEFT )
+ {
+ nCurSize = rRect.Right() - rPos.X();
+ mbHorz = FALSE;
+ }
+ else if ( nLineMode & DOCK_LINETOP )
+ {
+ nCurSize = rRect.Bottom() - rPos.Y();
+ mbHorz = TRUE;
+ }
+ else {
+ DBG_ERROR( "ImplLineSizing: Trailing else" );
+ nCurSize = 0;
+ mbHorz = FALSE;
+ }
+
+ Size aWinSize = pThis->GetSizePixel();
+ USHORT nMaxLines = (pThis->mnLines > pThis->mnCurLines) ? pThis->mnLines : pThis->mnCurLines;
+ if ( nMaxLines > TB_MAXLINES )
+ nMaxLines = TB_MAXLINES;
+ if ( mbHorz )
+ {
+ nOneLineSize = ImplCalcSize( pThis, 1 ).Height();
+ nMaxSize = pThis->maOutDockRect.GetHeight() - 20;
+ if ( nMaxSize < aWinSize.Height() )
+ nMaxSize = aWinSize.Height();
+ }
+ else
+ {
+ nOneLineSize = ImplCalcSize( pThis, 1 ).Width();
+ nMaxSize = pThis->maOutDockRect.GetWidth() - 20;
+ if ( nMaxSize < aWinSize.Width() )
+ nMaxSize = aWinSize.Width();
+ }
+
+ USHORT i = 1;
+ if ( nCurSize <= nOneLineSize )
+ nSize = nOneLineSize;
+ else
+ {
+ nSize = 0;
+ while ( (nSize < nCurSize) && (i < nMaxLines) )
+ {
+ i++;
+ aSize = ImplCalcSize( pThis, i );
+ if ( mbHorz )
+ nSize = aSize.Height();
+ else
+ nSize = aSize.Width();
+ if ( nSize > nMaxSize )
+ {
+ i--;
+ aSize = ImplCalcSize( pThis, i );
+ if ( mbHorz )
+ nSize = aSize.Height();
+ else
+ nSize = aSize.Width();
+ break;
+ }
+ }
+ }
+
+ if ( nLineMode & DOCK_LINERIGHT )
+ rRect.Right() = rRect.Left()+nSize-1;
+ else if ( nLineMode & DOCK_LINEBOTTOM )
+ rRect.Bottom() = rRect.Top()+nSize-1;
+ else if ( nLineMode & DOCK_LINELEFT )
+ rRect.Left() = rRect.Right()-nSize;
+ else //if ( nLineMode & DOCK_LINETOP )
+ rRect.Top() = rRect.Bottom()-nSize;
+
+ pThis->mnDockLines = i;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::ImplFindItemPos( ToolBox* pBox, const Point& rPos )
+{
+ USHORT nPos = 0;
+ long nLast = 0;
+ Point aPos = rPos;
+ Size aSize( pBox->mnDX, pBox->mnDY );
+
+ if ( aPos.X() > aSize.Width()-TB_BORDER_OFFSET1 )
+ aPos.X() = aSize.Width()-TB_BORDER_OFFSET1;
+ if ( aPos.Y() > aSize.Height()-TB_BORDER_OFFSET1 )
+ aPos.Y() = aSize.Height()-TB_BORDER_OFFSET1;
+
+ // Item suchen, das geklickt wurde
+ std::vector< ImplToolItem >::const_iterator it = pBox->mpData->m_aItems.begin();
+ while ( it != pBox->mpData->m_aItems.end() )
+ {
+ if ( it->mbVisible )
+ {
+ if ( nLast || !it->maRect.IsEmpty() )
+ {
+ if ( pBox->mbHorz )
+ {
+ if ( nLast &&
+ ((nLast < it->maRect.Top()) || it->maRect.IsEmpty()) )
+ return nPos;
+
+ if ( aPos.Y() <= it->maRect.Bottom() )
+ {
+ if ( aPos.X() < it->maRect.Left() )
+ return nPos;
+ else if ( aPos.X() < it->maRect.Right() )
+ return nPos+1;
+ else if ( !nLast )
+ nLast = it->maRect.Bottom();
+ }
+ }
+ else
+ {
+ if ( nLast &&
+ ((nLast < it->maRect.Left()) || it->maRect.IsEmpty()) )
+ return nPos;
+
+ if ( aPos.X() <= it->maRect.Right() )
+ {
+ if ( aPos.Y() < it->maRect.Top() )
+ return nPos;
+ else if ( aPos.Y() < it->maRect.Bottom() )
+ return nPos+1;
+ else if ( !nLast )
+ nLast = it->maRect.Right();
+ }
+ }
+ }
+ }
+
+ nPos++;
+ ++it;
+ }
+
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+ImplTBDragMgr::ImplTBDragMgr()
+{
+ mpBoxList = new ImplTBList( 4, 4 );
+ mnLineMode = 0;
+ mnStartLines = 0;
+ mbCustomizeMode = FALSE;
+ mbResizeMode = FALSE;
+ mbShowDragRect = FALSE;
+ mpDragBox = NULL;
+
+ maAccel.InsertItem( KEY_RETURN, KeyCode( KEY_RETURN ) );
+ maAccel.InsertItem( KEY_ESCAPE, KeyCode( KEY_ESCAPE ) );
+ maAccel.SetSelectHdl( LINK( this, ImplTBDragMgr, SelectHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+ImplTBDragMgr::~ImplTBDragMgr()
+{
+ delete mpBoxList;
+}
+
+// -----------------------------------------------------------------------
+
+ToolBox* ImplTBDragMgr::FindToolBox( const Rectangle& rRect )
+{
+ ToolBox* pBox = mpBoxList->First();
+ while ( pBox )
+ {
+ /*
+ * FIXME: since we can have multiple frames now we cannot
+ * find the drag target by its position alone.
+ * As long as the toolbar config dialogue is not a system window
+ * this works in one frame only anyway. If the dialogue
+ * changes to a system window, we need a new implementation here
+ */
+ if ( pBox->IsReallyVisible() && pBox->ImplGetWindowImpl()->mpFrame == mpDragBox->ImplGetWindowImpl()->mpFrame )
+ {
+ if ( !pBox->ImplIsFloatingMode() )
+ {
+ Point aPos = pBox->GetPosPixel();
+ aPos = pBox->GetParent()->OutputToScreenPixel( aPos );
+ Rectangle aTempRect( aPos, pBox->GetSizePixel() );
+ if ( aTempRect.IsOver( rRect ) )
+ return pBox;
+ }
+ }
+
+ pBox = mpBoxList->Next();
+ }
+
+ return pBox;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::StartDragging( ToolBox* pToolBox,
+ const Point& rPos, const Rectangle& rRect,
+ USHORT nDragLineMode, BOOL bResizeItem,
+ void* pData )
+{
+ mpDragBox = pToolBox;
+ pToolBox->CaptureMouse();
+ pToolBox->mbDragging = TRUE;
+ Application::InsertAccel( &maAccel );
+
+ if ( nDragLineMode )
+ {
+ mnLineMode = nDragLineMode;
+ mnStartLines = pToolBox->mnDockLines;
+ }
+ else
+ {
+ mpCustomizeData = pData;
+ mbResizeMode = bResizeItem;
+ pToolBox->Activate();
+ pToolBox->mnCurItemId = pToolBox->mnConfigItem;
+ pToolBox->Highlight();
+ pToolBox->mnCurItemId = 0;
+ if ( mbResizeMode )
+ {
+ if ( rRect.GetWidth() < TB_MIN_WIN_WIDTH )
+ mnMinWidth = rRect.GetWidth();
+ else
+ mnMinWidth = TB_MIN_WIN_WIDTH;
+ mnMaxWidth = pToolBox->GetSizePixel().Width()-rRect.Left()-
+ TB_SPIN_SIZE-TB_BORDER_OFFSET1-(TB_SPIN_OFFSET*2);
+ }
+ }
+
+ // MouseOffset berechnen
+ maMouseOff.X() = rRect.Left() - rPos.X();
+ maMouseOff.Y() = rRect.Top() - rPos.Y();
+ maRect = rRect;
+ maStartRect = rRect;
+ mbShowDragRect = TRUE;
+ pToolBox->ShowTracking( maRect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::Dragging( const Point& rPos )
+{
+ if ( mnLineMode )
+ {
+ ToolBox::ImplLineSizing( mpDragBox, rPos, maRect, mnLineMode );
+ Point aOff = mpDragBox->OutputToScreenPixel( Point() );
+ maRect.Move( aOff.X(), aOff.Y() );
+ mpDragBox->Docking( rPos, maRect );
+ maRect.Move( -aOff.X(), -aOff.Y() );
+ mpDragBox->ShowTracking( maRect );
+ }
+ else
+ {
+ if ( mbResizeMode )
+ {
+ long nXOff = rPos.X()-maStartRect.Left();
+ nXOff += maMouseOff.X()+(maStartRect.Right()-maStartRect.Left());
+ if ( nXOff < mnMinWidth )
+ nXOff = mnMinWidth;
+ if ( nXOff > mnMaxWidth )
+ nXOff = mnMaxWidth;
+ maRect.Right() = maStartRect.Left()+nXOff;
+ }
+ else
+ {
+ maRect.SetPos( rPos );
+ maRect.Move( maMouseOff.X(), maMouseOff.Y() );
+ }
+ mpDragBox->ShowTracking( maRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::EndDragging( BOOL bOK )
+{
+ mpDragBox->HideTracking();
+ mpDragBox->ReleaseMouse();
+ mpDragBox->mbDragging = FALSE;
+ mbShowDragRect = FALSE;
+ Application::RemoveAccel( &maAccel );
+
+ if ( mnLineMode )
+ {
+ if ( !bOK )
+ {
+ mpDragBox->mnDockLines = mnStartLines;
+ mpDragBox->EndDocking( maStartRect, FALSE );
+ }
+ else
+ mpDragBox->EndDocking( maRect, FALSE );
+ mnLineMode = 0;
+ mnStartLines = 0;
+ }
+ else
+ {
+ USHORT nTempItem = mpDragBox->mnConfigItem;
+ if ( nTempItem )
+ {
+ mpDragBox->mnConfigItem = 0;
+ if ( !mbResizeMode )
+ mpDragBox->Invalidate( mpDragBox->GetItemRect( nTempItem ) );
+ }
+
+ if ( bOK && (maRect != maStartRect) )
+ {
+ if ( mbResizeMode )
+ {
+ ImplToolItem* pItem = mpDragBox->ImplGetItem( nTempItem );
+ Size aSize = pItem->mpWindow->GetSizePixel();
+ aSize.Width() = maRect.GetWidth();
+ pItem->mpWindow->SetSizePixel( aSize );
+
+ // ToolBox neu brechnen und neu ausgeben
+ mpDragBox->ImplInvalidate( TRUE );
+ mpDragBox->Customize( ToolBoxCustomizeEvent( mpDragBox, nTempItem,
+ TOOLBOX_CUSTOMIZE_RESIZE,
+ mpCustomizeData ) );
+ }
+ else
+ {
+ Point aOff = mpDragBox->OutputToScreenPixel( Point() );
+ Rectangle aScreenRect( maRect );
+ aScreenRect.Move( aOff.X(), aOff.Y() );
+ ToolBox* pDropBox = FindToolBox( aScreenRect );
+ if ( pDropBox )
+ {
+ // Such-Position bestimmen
+ Point aPos;
+ if ( pDropBox->mbHorz )
+ {
+ aPos.X() = aScreenRect.Left()-TB_CUSTOMIZE_OFFSET;
+ aPos.Y() = aScreenRect.Center().Y();
+ }
+ else
+ {
+ aPos.X() = aScreenRect.Center().X();
+ aPos.Y() = aScreenRect.Top()-TB_CUSTOMIZE_OFFSET;
+ }
+
+ aPos = pDropBox->ScreenToOutputPixel( aPos );
+ USHORT nPos = ToolBox::ImplFindItemPos( pDropBox, aPos );
+ mpDragBox->Customize( ToolBoxCustomizeEvent( pDropBox, nTempItem,
+ nPos, mpCustomizeData ) );
+ }
+ else
+ {
+ mpDragBox->Customize( ToolBoxCustomizeEvent( NULL, nTempItem,
+ 0, mpCustomizeData ) );
+ }
+ }
+ }
+ mpCustomizeData = NULL;
+ mbResizeMode = FALSE;
+ mpDragBox->Deactivate();
+ }
+
+ mpDragBox = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::UpdateDragRect()
+{
+ // Nur Updaten, wenn wir schon im Dragging sind
+ if ( !mbShowDragRect )
+ return;
+
+ mpDragBox->ShowTracking( maRect );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplTBDragMgr, SelectHdl, Accelerator*, pAccel )
+{
+ if ( pAccel->GetCurItemId() == KEY_ESCAPE )
+ EndDragging( FALSE );
+ else
+ EndDragging( TRUE );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::StartCustomizeMode()
+{
+ mbCustomizeMode = TRUE;
+
+ ToolBox* pBox = mpBoxList->First();
+ while ( pBox )
+ {
+ pBox->ImplStartCustomizeMode();
+ pBox = mpBoxList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::EndCustomizeMode()
+{
+ mbCustomizeMode = FALSE;
+
+ ToolBox* pBox = mpBoxList->First();
+ while ( pBox )
+ {
+ pBox->ImplEndCustomizeMode();
+ pBox = mpBoxList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+
+static void ImplDrawOutButton( OutputDevice* pOutDev, const Rectangle& rRect,
+ USHORT nStyle )
+{
+ const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
+ Color aShadowColor = rStyleSettings.GetShadowColor();
+ Point aPos( rRect.TopLeft() );
+ Size aSize( rRect.GetSize() );
+ long nOffset = 0;
+
+ if ( pOutDev->GetBackground().GetColor() == aShadowColor )
+ aShadowColor = rStyleSettings.GetDarkShadowColor();
+
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ {
+ aPos.X()++;
+ aPos.Y()++;
+ nOffset++;
+ }
+
+ // Hintergrund loeschen
+ pOutDev->Erase( rRect );
+
+ // Button zeichnen
+ pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pOutDev->DrawLine( aPos,
+ Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ) );
+ pOutDev->DrawLine( aPos,
+ Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
+ pOutDev->SetLineColor( aShadowColor );
+ pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ),
+ Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
+ pOutDev->DrawLine( Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ),
+ Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
+ for ( long i = 0; i < OUTBUTTON_BORDER-1-nOffset; i++ )
+ {
+ pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+OUTBUTTON_BORDER ),
+ Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+aSize.Height()-1 ) );
+ pOutDev->DrawLine( Point( aPos.X()+OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ),
+ Point( aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ) );
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+
+ // Variablen initialisieren
+ ImplGetWindowImpl()->mbToolBox = TRUE;
+ mpBtnDev = NULL;
+ mpFloatSizeAry = NULL;
+ mpData = new ImplToolBoxPrivateData;
+ mpFloatWin = NULL;
+ mnDX = 0;
+ mnDY = 0;
+ mnMaxItemWidth = 0;
+ mnMaxItemHeight = 0;
+ mnWinHeight = 0;
+ mnBorderX = 0;
+ mnBorderY = 0;
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ mnLastResizeDY = 0;
+ mnOutStyle = TOOLBOX_STYLE_FLAT; // force flat buttons since NWF
+ mnHighItemId = 0;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnFocusPos = TOOLBOX_ITEM_NOTFOUND; // current position during keyboard access
+ mnLines = 1;
+ mnCurLine = 1;
+ mnCurLines = 1;
+ mnVisLines = 1;
+ mnFloatLines = 0;
+ mnConfigItem = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ mbCommandDrag = FALSE;
+ mbUpper = FALSE;
+ mbLower = FALSE;
+ mbNextTool = FALSE;
+ mbIn = FALSE;
+ mbCalc = TRUE;
+ mbFormat = FALSE;
+ mbFullPaint = FALSE;
+ mbHorz = TRUE;
+ mbScroll = (nStyle & WB_SCROLL) != 0;
+ mbCustomize = FALSE;
+ mbCustomizeMode = FALSE;
+ mbDragging = FALSE;
+ mbHideStatusText = FALSE;
+ mbMenuStrings = FALSE;
+ mbIsShift = FALSE;
+ mbIsKeyEvent = FALSE;
+ mbChangingHighlight = FALSE;
+ meButtonType = BUTTON_SYMBOL;
+ meAlign = WINDOWALIGN_TOP;
+ meLastStyle = POINTER_ARROW;
+ mnWinStyle = nStyle;
+ mnLastFocusItemId = 0;
+ mnKeyModifier = 0;
+ mnActivateCount = 0;
+
+ maTimer.SetTimeout( 50 );
+ maTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplUpdateHdl ) );
+
+ // set timeout and handler for dropdown items
+ mpData->maDropdownTimer.SetTimeout( 250 );
+ mpData->maDropdownTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplDropdownLongClickHdl ) );
+
+ DockingWindow::ImplInit( pParent, nStyle & ~(WB_BORDER) );
+
+
+ // always set WB_TABSTOP for ToolBars !!! if( mnWinStyle & WB_TABSTOP )
+ {
+ // dockingwindow's ImplInit removes some bits, so restore them here
+ // to allow keyboard handling for toolbars
+ ImplGetWindowImpl()->mnStyle |= WB_TABSTOP|WB_NODIALOGCONTROL;
+ ImplGetWindowImpl()->mnStyle &= ~WB_DIALOGCONTROL;
+ }
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ mpData->mbNativeButtons = IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON );
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetToolFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetButtonTextColor();
+ else
+ aColor = rStyleSettings.GetWindowTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ {
+ aColor = GetControlBackground();
+ SetBackground( aColor );
+ SetPaintTransparent( FALSE );
+ SetParentClipMode( 0 );
+ }
+ else
+ {
+ if( IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
+ {
+ SetBackground();
+ SetPaintTransparent( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ mpData->maDisplayBackground = Wallpaper( rStyleSettings.GetFaceColor() );
+ }
+ else
+ {
+ if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+
+ SetBackground( aColor );
+ SetPaintTransparent( FALSE );
+ SetParentClipMode( 0 );
+
+ ImplUpdateImageList();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplLoadRes( const ResId& rResId )
+{
+ ResMgr* pMgr = rResId.GetResMgr();
+ if( ! pMgr )
+ return;
+
+ DockingWindow::ImplLoadRes( rResId );
+
+ ULONG nObjMask;
+
+ nObjMask = ReadLongRes();
+
+ if ( nObjMask & RSC_TOOLBOX_BUTTONTYPE )
+ SetButtonType( (ButtonType)ReadLongRes() );
+
+ if ( nObjMask & RSC_TOOLBOX_ALIGN )
+ SetAlign( (WindowAlign)ReadLongRes() );
+
+ if ( nObjMask & RSC_TOOLBOX_LINECOUNT )
+ SetLineCount( sal::static_int_cast<USHORT>(ReadLongRes()) );
+
+ if ( nObjMask & RSC_TOOLBOX_CUSTOMIZE )
+ {
+ BOOL bCust = (BOOL)ReadShortRes();
+ EnableCustomize( bCust );
+ }
+
+ if ( nObjMask & RSC_TOOLBOX_MENUSTRINGS )
+ {
+ BOOL bCust = (BOOL)ReadShortRes();
+ EnableMenuStrings( bCust );
+ }
+
+ if ( nObjMask & RSC_TOOLBOX_FLOATLINES )
+ SetFloatingLines( ReadShortRes() );
+
+ if ( nObjMask & RSC_TOOLBOX_ITEMIMAGELIST )
+ {
+ maImageList = ImageList( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+
+ if ( nObjMask & RSC_TOOLBOX_ITEMLIST )
+ {
+ ULONG nEle = ReadLongRes();
+
+ // Item hinzufuegen
+ for ( ULONG i = 0; i < nEle; i++ )
+ {
+ InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ToolBox::ToolBox( Window* pParent, WinBits nStyle ) :
+ DockingWindow( WINDOW_TOOLBOX )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ToolBox::ToolBox( Window* pParent, const ResId& rResId ) :
+ DockingWindow( WINDOW_TOOLBOX )
+{
+ RTL_LOGFILE_CONTEXT( aLog, "vcl: ToolBox::ToolBox( Window* pParent, const ResId& rResId )" );
+
+ rResId.SetRT( RSC_TOOLBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ // Groesse des FloatingWindows berechnen und umschalten, wenn die
+ // ToolBox initial im FloatingModus ist
+ if ( ImplIsFloatingMode() )
+ mbHorz = TRUE;
+ else
+ Resize();
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+ToolBox::~ToolBox()
+{
+ // custom menu event still running?
+ if( mpData->mnEventId )
+ Application::RemoveUserEvent( mpData->mnEventId );
+
+ // #103005# make sure our activate/deactivate balance is right
+ while( mnActivateCount > 0 )
+ Deactivate();
+
+ // Falls noch ein Floating-Window connected ist, dann den
+ // PopupModus beenden
+ if ( mpFloatWin )
+ mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
+
+ // delete private data
+ delete mpData;
+
+ // FloatSizeAry gegebenenfalls loeschen
+ if ( mpFloatSizeAry )
+ delete mpFloatSizeAry;
+
+ // Wenn keine ToolBox-Referenzen mehr auf die Listen bestehen, dann
+ // Listen mit wegloeschen
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maCtrlData.mpTBDragMgr )
+ {
+ // Wenn im TBDrag-Manager, dann wieder rausnehmen
+ if ( mbCustomize )
+ pSVData->maCtrlData.mpTBDragMgr->Remove( this );
+
+ if ( !pSVData->maCtrlData.mpTBDragMgr->Count() )
+ {
+ delete pSVData->maCtrlData.mpTBDragMgr;
+ pSVData->maCtrlData.mpTBDragMgr = NULL;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem* ToolBox::ImplGetItem( USHORT nItemId ) const
+{
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ if ( it->mnId == nItemId )
+ return &(*it);
+ ++it;
+ }
+
+ return NULL;
+}
+// -----------------------------------------------------------------------
+
+static void ImplAddButtonBorder( long &rWidth, long& rHeight, USHORT aOutStyle, BOOL bNativeButtons )
+{
+ if ( aOutStyle & TOOLBOX_STYLE_OUTBUTTON )
+ {
+ rWidth += OUTBUTTON_SIZE;
+ rHeight += OUTBUTTON_SIZE;
+ }
+ else
+ {
+ rWidth += SMALLBUTTON_HSIZE;
+ rHeight += SMALLBUTTON_VSIZE;
+ }
+
+ if( bNativeButtons )
+ {
+ // give more border space for rounded buttons
+ rWidth += 2;
+ rHeight += 4;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::ImplCalcItem()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ // recalc required ?
+ if ( !mbCalc )
+ return FALSE;
+
+ ImplDisableFlatButtons();
+
+ long nDefWidth;
+ long nDefHeight;
+ long nMaxWidth = 0;
+ long nMaxHeight = 0;
+ long nHeight;
+ long nMinWidth = 6;
+ long nMinHeight = 6;
+ long nDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
+
+ // set defaults if image or text is needed but empty
+ nDefWidth = GetDefaultImageSize().Width();
+ nDefHeight = GetDefaultImageSize().Height();
+
+ mnWinHeight = 0;
+ // determine minimum size necessary in NWF
+ {
+ Rectangle aRect( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
+ Rectangle aReg( aRect );
+ ImplControlValue aVal;
+ Rectangle aNativeBounds, aNativeContent;
+ if( IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
+ {
+ if( GetNativeControlRegion( CTRL_TOOLBAR, PART_BUTTON,
+ aReg,
+ CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
+ aVal, OUString(),
+ aNativeBounds, aNativeContent ) )
+ {
+ aRect = aNativeBounds;
+ if( aRect.GetWidth() > nMinWidth )
+ nMinWidth = aRect.GetWidth();
+ if( aRect.GetHeight() > nMinHeight )
+ nMinHeight = aRect.GetHeight();
+ if( nDropDownArrowWidth < nMinWidth )
+ nDropDownArrowWidth = nMinWidth;
+ if( nMinWidth > mpData->mnMenuButtonWidth )
+ mpData->mnMenuButtonWidth = nMinWidth;
+ else if( nMinWidth < TB_MENUBUTTON_SIZE )
+ mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
+ }
+ }
+
+ // also calculate the area for comboboxes, drop down list boxes and spinfields
+ // as these are often inserted into toolboxes; set mnWinHeight to the
+ // greater of those values to prevent toolbar flickering (#i103385#)
+ aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
+ aReg = aRect;
+ if( GetNativeControlRegion( CTRL_COMBOBOX, PART_ENTIRE_CONTROL,
+ aReg,
+ CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
+ aVal, OUString(),
+ aNativeBounds, aNativeContent ) )
+ {
+ aRect = aNativeBounds;
+ if( aRect.GetHeight() > mnWinHeight )
+ mnWinHeight = aRect.GetHeight();
+ }
+ aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
+ aReg = aRect;
+ if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL,
+ aReg,
+ CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
+ aVal, OUString(),
+ aNativeBounds, aNativeContent ) )
+ {
+ aRect = aNativeBounds;
+ if( aRect.GetHeight() > mnWinHeight )
+ mnWinHeight = aRect.GetHeight();
+ }
+ aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
+ aReg = aRect;
+ if( GetNativeControlRegion( CTRL_SPINBOX, PART_ENTIRE_CONTROL,
+ aReg,
+ CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
+ aVal, OUString(),
+ aNativeBounds, aNativeContent ) )
+ {
+ aRect = aNativeBounds;
+ if( aRect.GetHeight() > mnWinHeight )
+ mnWinHeight = aRect.GetHeight();
+ }
+ }
+
+ if ( ! mpData->m_aItems.empty() )
+ {
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ BOOL bImage;
+ BOOL bText;
+
+ it->mbVisibleText = FALSE; // indicates if text will definitely be drawn, influences dropdown pos
+
+ if ( it->meType == TOOLBOXITEM_BUTTON )
+ {
+ // check if image and/or text exists
+ if ( !(it->maImage) )
+ bImage = FALSE;
+ else
+ bImage = TRUE;
+ if ( !it->maText.Len() )
+ bText = FALSE;
+ else
+ bText = TRUE;
+ ButtonType tmpButtonType = determineButtonType( &(*it), meButtonType ); // default to toolbox setting
+ if ( bImage || bText )
+ {
+
+ it->mbEmptyBtn = FALSE;
+
+ if ( tmpButtonType == BUTTON_SYMBOL )
+ {
+ // we're drawing images only
+ if ( bImage || !bText )
+ {
+ it->maItemSize = it->maImage.GetSizePixel();
+ }
+ else
+ {
+ it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
+ GetTextHeight() );
+ it->mbVisibleText = TRUE;
+ }
+ }
+ else if ( tmpButtonType == BUTTON_TEXT )
+ {
+ // we're drawing text only
+ if ( bText || !bImage )
+ {
+ it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
+ GetTextHeight() );
+ it->mbVisibleText = TRUE;
+ }
+ else
+ {
+ it->maItemSize = it->maImage.GetSizePixel();
+ }
+ }
+ else
+ {
+ // we're drawing images and text
+ it->maItemSize.Width() = bText ? GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET : 0;
+ it->maItemSize.Height() = bText ? GetTextHeight() : 0;
+
+ // leave space between image and text
+ if( bText )
+ it->maItemSize.Width() += TB_IMAGETEXTOFFSET;
+
+ // image and text side by side
+ it->maItemSize.Width() += it->maImage.GetSizePixel().Width();
+ if ( it->maImage.GetSizePixel().Height() > it->maItemSize.Height() )
+ it->maItemSize.Height() = it->maImage.GetSizePixel().Height();
+
+ it->mbVisibleText = bText;
+ }
+ }
+ else
+ { // no image and no text
+ it->maItemSize = Size( nDefWidth, nDefHeight );
+ it->mbEmptyBtn = TRUE;
+ }
+
+ // Gegebenenfalls die Fensterhoehe mit beruecksichtigen
+ if ( it->mpWindow )
+ {
+ nHeight = it->mpWindow->GetSizePixel().Height();
+ if ( nHeight > mnWinHeight )
+ mnWinHeight = nHeight;
+ }
+
+ // add in drop down arrow
+ if( it->mnBits & TIB_DROPDOWN )
+ {
+ it->maItemSize.Width() += nDropDownArrowWidth;
+ it->mnDropDownArrowWidth = nDropDownArrowWidth;
+ }
+
+ // text items will be rotated in vertical mode
+ // -> swap width and height
+ if( it->mbVisibleText && !mbHorz )
+ {
+ long tmp = it->maItemSize.Width();
+ it->maItemSize.Width() = it->maItemSize.Height();
+ it->maItemSize.Height() = tmp;
+ }
+ }
+ else if ( it->meType == TOOLBOXITEM_SPACE )
+ {
+ it->maItemSize = Size( nDefWidth, nDefHeight );
+ }
+
+ if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
+ {
+ // add borders
+ ImplAddButtonBorder( it->maItemSize.Width(), it->maItemSize.Height(), mnOutStyle, mpData->mbNativeButtons );
+
+ if( it->meType == TOOLBOXITEM_BUTTON )
+ {
+ if( it->maItemSize.Width() < nMinWidth )
+ it->maItemSize.Width() = nMinWidth;
+ if( it->maItemSize.Height() < nMinHeight )
+ it->maItemSize.Height() = nMinHeight;
+ }
+
+ // keep track of max item size
+ if ( it->maItemSize.Width() > nMaxWidth )
+ nMaxWidth = it->maItemSize.Width();
+ if ( it->maItemSize.Height() > nMaxHeight )
+ nMaxHeight = it->maItemSize.Height();
+ }
+
+ ++it;
+ }
+ }
+ else
+ {
+ nMaxWidth = nDefWidth;
+ nMaxHeight = nDefHeight;
+
+ ImplAddButtonBorder( nMaxWidth, nMaxHeight, mnOutStyle, mpData->mbNativeButtons );
+ }
+
+ if( !ImplIsFloatingMode() && GetToolboxButtonSize() != TOOLBOX_BUTTONSIZE_DONTCARE )
+ {
+ // make sure all vertical toolbars have the same width and horizontal have the same height
+ // this depends on the used button sizes
+ // as this is used for alignement of multiple toolbars
+ // it is only required for docked toolbars
+
+ long nFixedWidth = nDefWidth+nDropDownArrowWidth;
+ long nFixedHeight = nDefHeight;
+ ImplAddButtonBorder( nFixedWidth, nFixedHeight, mnOutStyle, mpData->mbNativeButtons );
+
+ if( mbHorz )
+ nMaxHeight = nFixedHeight;
+ else
+ nMaxWidth = nFixedWidth;
+ }
+
+ mbCalc = FALSE;
+ mbFormat = TRUE;
+
+ // do we have to recalc the sizes ?
+ if ( (nMaxWidth != mnMaxItemWidth) || (nMaxHeight != mnMaxItemHeight) )
+ {
+ mnMaxItemWidth = nMaxWidth;
+ mnMaxItemHeight = nMaxHeight;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::ImplCalcBreaks( long nWidth, long* pMaxLineWidth, BOOL bCalcHorz )
+{
+ ULONG nLineStart = 0;
+ ULONG nGroupStart = 0;
+ long nLineWidth = 0;
+ long nCurWidth;
+ long nLastGroupLineWidth = 0;
+ long nMaxLineWidth = 0;
+ USHORT nLines = 1;
+ BOOL bWindow;
+ BOOL bBreak = FALSE;
+ long nWidthTotal = nWidth;
+
+ // when docked the menubutton will be in the first line
+ // ->initialize first linewidth with button
+ if( IsMenuEnabled() && !ImplIsFloatingMode() )
+ nLineWidth = mpData->maMenubuttonItem.maItemSize.Width();
+
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ it->mbBreak = bBreak;
+ bBreak = FALSE;
+
+ if ( it->mbVisible )
+ {
+ bWindow = FALSE;
+ bBreak = FALSE;
+ nCurWidth = 0;
+
+ if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
+ {
+ if ( bCalcHorz )
+ nCurWidth = it->maItemSize.Width();
+ else
+ nCurWidth = it->maItemSize.Height();
+
+ if ( it->mpWindow && bCalcHorz )
+ {
+ long nWinItemWidth = it->mpWindow->GetSizePixel().Width();
+ if ( !mbScroll || (nWinItemWidth <= nWidthTotal) )
+ {
+ nCurWidth = nWinItemWidth;
+ bWindow = TRUE;
+ }
+ else
+ {
+ if ( it->mbEmptyBtn )
+ {
+ nCurWidth = 0;
+ }
+ }
+ }
+
+ // check for line break
+ if ( (nLineWidth+nCurWidth > nWidthTotal) && mbScroll )
+ bBreak = TRUE;
+ }
+ else if ( it->meType == TOOLBOXITEM_SEPARATOR )
+ nCurWidth = it->mnSepSize;
+ // treat breaks as separators, except when using old style toolbars (ie. no menu button)
+ else if ( (it->meType == TOOLBOXITEM_BREAK) && !IsMenuEnabled() )
+ bBreak = TRUE;
+
+ if ( bBreak )
+ {
+ nLines++;
+
+ // Gruppe auseinanderbrechen oder ganze Gruppe umbrechen?
+ if ( (it->meType == TOOLBOXITEM_BREAK) ||
+ (nLineStart == nGroupStart) )
+ {
+ if ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+
+ nLineWidth = 0;
+ nLineStart = it - mpData->m_aItems.begin();
+ nGroupStart = nLineStart;
+ it->mbBreak = TRUE;
+ bBreak = FALSE;
+ }
+ else
+ {
+ if ( nLastGroupLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLastGroupLineWidth;
+
+ // Wenn ganze Gruppe umgebrochen wird, diese auf
+ // Zeilenanfang setzen und wieder neu berechnen
+ nLineWidth = 0;
+ nLineStart = nGroupStart;
+ it = mpData->m_aItems.begin() + nGroupStart;
+ continue;
+ }
+ }
+ else
+ {
+ if( ImplIsFloatingMode() || !IsMenuEnabled() ) // no group breaking when being docked single-line
+ {
+ if ( (it->meType != TOOLBOXITEM_BUTTON) || bWindow )
+ {
+ // found separator or break
+ nLastGroupLineWidth = nLineWidth;
+ nGroupStart = it - mpData->m_aItems.begin();
+ if ( !bWindow )
+ nGroupStart++;
+ }
+ }
+ }
+
+ nLineWidth += nCurWidth;
+ }
+
+ ++it;
+ }
+
+
+ if ( pMaxLineWidth )
+ {
+ if ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+
+ if( ImplIsFloatingMode() && !ImplIsInPopupMode() )
+ {
+ // leave enough space to display buttons in the decoration
+ long aMinWidth = 2 * GetSettings().GetStyleSettings().GetFloatTitleHeight();
+ if( nMaxLineWidth < aMinWidth )
+ nMaxLineWidth = aMinWidth;
+ }
+
+ // Wegen Separatoren kann MaxLineWidth > Width werden, hat aber
+ // auf die Umbrueche keine Auswirkung
+ //if ( nMaxLineWidth > nWidth )
+ // nMaxLineWidth = nWidth;
+
+ *pMaxLineWidth = nMaxLineWidth;
+ }
+
+ return nLines;
+}
+
+// -----------------------------------------------------------------------
+namespace
+{
+ BOOL ImplFollowedByVisibleButton( std::vector< ImplToolItem >::iterator _aSeparator, std::vector< ImplToolItem >::iterator _aEnd )
+ {
+ std::vector< ImplToolItem >::iterator aLookup = _aSeparator;
+ while ( ++aLookup != _aEnd )
+ {
+ if ( aLookup->meType == TOOLBOXITEM_SEPARATOR )
+ return ImplFollowedByVisibleButton( aLookup, _aEnd );
+
+ if ( ( aLookup->meType == TOOLBOXITEM_BUTTON ) && aLookup->mbVisible )
+ return TRUE;
+ }
+ return FALSE;
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+Size ToolBox::ImplGetOptimalFloatingSize( FloatingSizeMode eMode )
+{
+ if( !ImplIsFloatingMode() )
+ return Size();
+
+ Size aCurrentSize( mnDX, mnDY );
+ Size aSize1( aCurrentSize );
+ Size aSize2( aCurrentSize );
+
+ // try to preserve current height
+ if( eMode == FSMODE_AUTO || eMode == FSMODE_FAVOURHEIGHT )
+ {
+ // calc number of floating lines for current window height
+ USHORT nFloatLinesHeight = ImplCalcLines( this, mnDY );
+ // calc window size according to this number
+ aSize1 = ImplCalcFloatSize( this, nFloatLinesHeight );
+
+ if( eMode == FSMODE_FAVOURHEIGHT || aCurrentSize == aSize1 )
+ return aSize1;
+ }
+
+ if( eMode == FSMODE_AUTO || eMode == FSMODE_FAVOURWIDTH )
+ {
+ // try to preserve current width
+ long nLineHeight = ( mnWinHeight > mnMaxItemHeight ) ? mnWinHeight : mnMaxItemHeight;
+ int nBorderX = 2*TB_BORDER_OFFSET1 + mnLeftBorder + mnRightBorder + 2*mnBorderX;
+ int nBorderY = 2*TB_BORDER_OFFSET2 + mnTopBorder + mnBottomBorder + 2*mnBorderY;
+ Size aSz( aCurrentSize );
+ long maxX;
+ USHORT nLines = ImplCalcBreaks( aSz.Width()-nBorderX, &maxX, mbHorz );
+
+ USHORT manyLines = 1000;
+ Size aMinimalFloatSize = ImplCalcFloatSize( this, manyLines );
+
+ aSz.Height() = nBorderY + nLineHeight * nLines;
+ // line space when more than one line
+ if ( mnWinStyle & WB_LINESPACING )
+ aSz.Height() += (nLines-1)*TB_LINESPACING;
+
+ aSz.Width() = nBorderX + maxX;
+
+ // avoid clipping of any items
+ if( aSz.Width() < aMinimalFloatSize.Width() )
+ aSize2 = ImplCalcFloatSize( this, nLines );
+ else
+ aSize2 = aSz;
+
+ if( eMode == FSMODE_FAVOURWIDTH || aCurrentSize == aSize2 )
+ return aSize2;
+ else
+ {
+ // set the size with the smallest delta as the current size
+ long dx1 = abs( mnDX - aSize1.Width() );
+ long dy1 = abs( mnDY - aSize1.Height() );
+
+ long dx2 = abs( mnDX - aSize2.Width() );
+ long dy2 = abs( mnDY - aSize2.Height() );
+
+ if( dx1*dy1 < dx2*dy2 )
+ aCurrentSize = aSize1;
+ else
+ aCurrentSize = aSize2;
+ }
+ }
+ return aCurrentSize;
+}
+
+
+void ToolBox::ImplFormat( BOOL bResize )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ // Muss ueberhaupt neu formatiert werden
+ if ( !mbFormat )
+ return;
+
+ mpData->ImplClearLayoutData();
+
+ // Positionen/Groessen berechnen
+ Rectangle aEmptyRect;
+ long nLineSize;
+ long nLeft;
+ long nRight;
+ long nTop;
+ long nBottom;
+ long nMax; // width of layoutarea in pixels
+ long nX;
+ long nY;
+ USHORT nFormatLine;
+ BOOL bMustFullPaint;
+ BOOL bLastSep;
+
+ std::vector< ImplToolItem >::iterator it;
+ std::vector< ImplToolItem >::iterator temp_it;
+
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ BOOL bIsInPopupMode = ImplIsInPopupMode();
+
+ // FloatSizeAry gegebenenfalls loeschen
+ if ( mpFloatSizeAry )
+ {
+ delete mpFloatSizeAry;
+ mpFloatSizeAry = NULL;
+ }
+
+ // compute border sizes
+ ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder, this );
+
+ // update drag area (where the 'grip' will be placed)
+ Rectangle aOldDragRect;
+ if( pWrapper )
+ aOldDragRect = pWrapper->GetDragArea();
+ ImplUpdateDragArea( this );
+
+ if ( ImplCalcItem() )
+ bMustFullPaint = TRUE;
+ else
+ bMustFullPaint = FALSE;
+
+
+ // calculate new size during interactive resize or
+ // set computed size when formatting only
+ if ( ImplIsFloatingMode() )
+ {
+ if ( bResize )
+ mnFloatLines = ImplCalcLines( this, mnDY );
+ else
+ SetOutputSizePixel( ImplGetOptimalFloatingSize( FSMODE_AUTO ) );
+ }
+
+ // Horizontal
+ if ( mbHorz )
+ {
+ // nLineSize: height of a single line, will fit highest item
+ nLineSize = mnMaxItemHeight;
+
+ if ( mnWinHeight > mnMaxItemHeight )
+ nLineSize = mnWinHeight;
+
+ if ( mbScroll )
+ {
+ nMax = mnDX;
+ mnVisLines = ImplCalcLines( this, mnDY );
+ }
+ else
+ {
+ // layout over all lines
+ mnVisLines = mnLines;
+ nMax = TB_MAXNOSCROLL;
+ }
+
+ // add in all border offsets
+ // inner border as well as custom border (mnBorderX, mnBorderY)
+ if ( mnWinStyle & WB_BORDER )
+ {
+ nLeft = TB_BORDER_OFFSET1 + mnLeftBorder;
+ nTop = TB_BORDER_OFFSET2 + mnTopBorder;
+ nBottom = TB_BORDER_OFFSET1 + mnBottomBorder;
+ nMax -= nLeft + TB_BORDER_OFFSET1 + mnRightBorder;
+ }
+ else
+ {
+ nLeft = 0;
+ nTop = 0;
+ nBottom = 0;
+ }
+
+ nLeft += mnBorderX;
+ nTop += mnBorderY;
+ nBottom += mnBorderY;
+ nMax -= mnBorderX*2;
+
+ // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
+ // we have to center all items in the window height
+ if( IsMenuEnabled() && !ImplIsFloatingMode() )
+ {
+ long nWinHeight = mnDY - nTop - nBottom;
+ if( nWinHeight > nLineSize )
+ nLineSize = nWinHeight;
+ }
+ }
+ else
+ {
+ nLineSize = mnMaxItemWidth;
+
+ if ( mbScroll )
+ {
+ mnVisLines = ImplCalcLines( this, mnDX );
+ nMax = mnDY;
+ }
+ else
+ {
+ mnVisLines = mnLines;
+ nMax = TB_MAXNOSCROLL;
+ }
+
+ if ( mnWinStyle & WB_BORDER )
+ {
+ nTop = TB_BORDER_OFFSET1 + mnTopBorder;
+ nLeft = TB_BORDER_OFFSET2 + mnLeftBorder;
+ nRight = TB_BORDER_OFFSET2 + mnRightBorder;
+ nMax -= nTop + TB_BORDER_OFFSET1 + mnBottomBorder;
+ }
+ else
+ {
+ nLeft = 0;
+ nTop = 0;
+ nRight = 0;
+ }
+
+ nLeft += mnBorderX;
+ nRight+= mnBorderX;
+ nTop += mnBorderY;
+ nMax -= mnBorderY*2;
+
+ // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
+ // we have to center all items in the window height
+ if( !ImplIsFloatingMode() && IsMenuEnabled() )
+ {
+ long nWinWidth = mnDX - nLeft - nRight;
+ if( nWinWidth > nLineSize )
+ nLineSize = nWinWidth;
+ }
+ }
+
+ // no calculation if the window has no size (nMax=0)
+ // non scrolling toolboxes must be computed though
+ if ( (nMax <= 0) && mbScroll )
+ {
+ mnVisLines = 1;
+ mnCurLine = 1;
+ mnCurLines = 1;
+
+ it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ it->maRect = aEmptyRect;
+
+ // For items not visible, release resources only needed during
+ // painting the items (on Win98, for example, these are system-wide
+ // resources that are easily exhausted, so be nice):
+
+ /* !!!
+ it->maImage.ClearCaches();
+ it->maHighImage.ClearCaches();
+ */
+
+ ++it;
+ }
+
+ maLowerRect = aEmptyRect;
+ maUpperRect = aEmptyRect;
+ maNextToolRect = aEmptyRect;
+ }
+ else
+ {
+ // init start values
+ nX = nLeft; // top-left offset
+ nY = nTop;
+ nFormatLine = 1;
+ bLastSep = TRUE;
+
+ // save old scroll rectangles and reset them
+ Rectangle aOldLowerRect = maLowerRect;
+ Rectangle aOldUpperRect = maUpperRect;
+ Rectangle aOldNextToolRect = maNextToolRect;
+ Rectangle aOldMenubuttonRect = mpData->maMenubuttonItem.maRect;
+ maUpperRect = aEmptyRect;
+ maLowerRect = aEmptyRect;
+ maNextToolRect = aEmptyRect;
+ mpData->maMenubuttonItem.maRect = aEmptyRect;
+
+ // additional toolboxes require a toggle button (maNextToolRect)
+ if ( maNextToolBoxStr.Len() && mbScroll )
+ {
+ nMax -= TB_NEXT_SIZE-TB_NEXT_OFFSET;
+ if ( mbHorz )
+ {
+ maNextToolRect.Left() = nLeft+nMax;
+ maNextToolRect.Right() = maNextToolRect.Left()+TB_NEXT_SIZE-1;
+ maNextToolRect.Top() = nTop;
+ maNextToolRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
+ }
+ else
+ {
+ maNextToolRect.Top() = nTop+nMax;
+ maNextToolRect.Bottom() = maNextToolRect.Top()+TB_NEXT_SIZE-1;
+ maNextToolRect.Left() = nLeft;
+ maNextToolRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
+ }
+ }
+
+ // do we have any toolbox items at all ?
+ if ( !mpData->m_aItems.empty() || IsMenuEnabled() )
+ {
+ // compute line breaks and visible lines give the current window width (nMax)
+ // the break indicators will be stored within each item (it->mbBreak)
+ mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
+
+ // check for scrollbar buttons or dropdown menu
+ // (if a menu is enabled, this will be used to store clipped
+ // items and no scroll buttons will appear)
+ if ( (!ImplIsFloatingMode() && (mnCurLines > mnVisLines) && mbScroll ) ||
+ IsMenuEnabled() )
+ {
+ // compute linebreaks again, incorporating scrollbar buttons
+ if( !IsMenuEnabled() )
+ {
+ nMax -= TB_SPIN_SIZE+TB_SPIN_OFFSET;
+ mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
+ }
+
+ // compute scroll rectangles or menu button
+ if ( mbHorz )
+ {
+ if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
+ {
+ if( !ImplIsFloatingMode() )
+ {
+ mpData->maMenubuttonItem.maRect.Right() = mnDX - 2;
+ mpData->maMenubuttonItem.maRect.Top() = nTop;
+ mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
+ }
+ else
+ {
+ mpData->maMenubuttonItem.maRect.Right() = mnDX - mnRightBorder-mnBorderX-TB_BORDER_OFFSET1-1;
+ mpData->maMenubuttonItem.maRect.Top() = nTop;
+ mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
+ }
+ mpData->maMenubuttonItem.maRect.Left() = mpData->maMenubuttonItem.maRect.Right() - mpData->mnMenuButtonWidth;
+ }
+ else
+ {
+ maUpperRect.Left() = nLeft+nMax+TB_SPIN_OFFSET;
+ maUpperRect.Right() = maUpperRect.Left()+TB_SPIN_SIZE-1;
+ maUpperRect.Top() = nTop;
+ maLowerRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
+ maLowerRect.Left() = maUpperRect.Left();
+ maLowerRect.Right() = maUpperRect.Right();
+ maUpperRect.Bottom() = maUpperRect.Top() +
+ (maLowerRect.Bottom()-maUpperRect.Top())/2;
+ maLowerRect.Top() = maUpperRect.Bottom();
+ }
+ }
+ else
+ {
+ if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
+ {
+ if( !ImplIsFloatingMode() )
+ {
+ mpData->maMenubuttonItem.maRect.Bottom() = mnDY - 2;
+ mpData->maMenubuttonItem.maRect.Left() = nLeft;
+ mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
+ }
+ else
+ {
+ mpData->maMenubuttonItem.maRect.Bottom() = mnDY - mnBottomBorder-mnBorderY-TB_BORDER_OFFSET1-1;
+ mpData->maMenubuttonItem.maRect.Left() = nLeft;
+ mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
+ }
+ mpData->maMenubuttonItem.maRect.Top() = mpData->maMenubuttonItem.maRect.Bottom() - mpData->mnMenuButtonWidth;
+ }
+ else
+ {
+ maUpperRect.Top() = nTop+nMax+TB_SPIN_OFFSET;;
+ maUpperRect.Bottom() = maUpperRect.Top()+TB_SPIN_SIZE-1;
+ maUpperRect.Left() = nLeft;
+ maLowerRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
+ maLowerRect.Top() = maUpperRect.Top();
+ maLowerRect.Bottom() = maUpperRect.Bottom();
+ maUpperRect.Right() = maUpperRect.Left() +
+ (maLowerRect.Right()-maUpperRect.Left())/2;
+ maLowerRect.Left() = maUpperRect.Right();
+ }
+ }
+ }
+
+ // no scrolling when there is a "more"-menu
+ // anything will "fit" in a single line then
+ if( IsMenuEnabled() )
+ mnCurLines = 1;
+
+ // determine the currently visible line
+ if ( mnVisLines >= mnCurLines )
+ mnCurLine = 1;
+ else if ( mnCurLine+mnVisLines-1 > mnCurLines )
+ mnCurLine = mnCurLines - (mnVisLines-1);
+
+ it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ // hide double separators
+ if ( it->meType == TOOLBOXITEM_SEPARATOR )
+ {
+ it->mbVisible = FALSE;
+ if ( !bLastSep )
+ {
+ // check if any visible items have to appear behind it
+ temp_it = it+1;
+ while ( temp_it != mpData->m_aItems.end() )
+ {
+ if ( (temp_it->meType == TOOLBOXITEM_SEPARATOR) ||
+ ((temp_it->meType == TOOLBOXITEM_BUTTON) &&
+ temp_it->mbVisible) )
+ {
+ it->mbVisible = TRUE;
+ break;
+ }
+ ++temp_it;
+ }
+ }
+ bLastSep = TRUE;
+ }
+ else if ( it->mbVisible )
+ bLastSep = FALSE;
+
+ it->mbShowWindow = FALSE;
+
+ // check for line break and advance nX/nY accordingly
+ if ( it->mbBreak )
+ {
+ nFormatLine++;
+
+ // increment starting with the second line
+ if ( nFormatLine > mnCurLine )
+ {
+ if ( mbHorz )
+ {
+ nX = nLeft;
+ if ( mnWinStyle & WB_LINESPACING )
+ nY += nLineSize+TB_LINESPACING;
+ else
+ nY += nLineSize;
+ }
+ else
+ {
+ nY = nTop;
+ if ( mnWinStyle & WB_LINESPACING )
+ nX += nLineSize+TB_LINESPACING;
+ else
+ nX += nLineSize;
+ }
+ }
+ }
+
+ if ( !it->mbVisible || (nFormatLine < mnCurLine) ||
+ (nFormatLine > mnCurLine+mnVisLines-1) )
+ // item is not visible
+ it->maCalcRect = aEmptyRect;
+ else
+ {
+ // 1. determine current item width/height
+ // take window size and orientation into account, because this affects the size of item windows
+
+ Size aCurrentItemSize( it->GetSize( mbHorz, mbScroll, nMax, Size(mnMaxItemWidth, mnMaxItemHeight) ) );
+
+ // 2. position item rect and use size from step 1
+ // items will be centered horizontally (if mbHorz) or vertically
+ // advance nX and nY accordingly
+ if ( mbHorz )
+ {
+ it->maCalcRect.Left() = nX;
+ it->maCalcRect.Top() = nY+(nLineSize-aCurrentItemSize.Height())/2;
+ it->maCalcRect.Right() = nX+aCurrentItemSize.Width()-1;
+ it->maCalcRect.Bottom() = it->maCalcRect.Top()+aCurrentItemSize.Height()-1;
+ nX += aCurrentItemSize.Width();
+ }
+ else
+ {
+ it->maCalcRect.Left() = nX+(nLineSize-aCurrentItemSize.Width())/2;
+ it->maCalcRect.Top() = nY;
+ it->maCalcRect.Right() = it->maCalcRect.Left()+aCurrentItemSize.Width()-1;
+ it->maCalcRect.Bottom() = nY+aCurrentItemSize.Height()-1;
+ nY += aCurrentItemSize.Height();
+ }
+ }
+
+ // position window items into calculated item rect
+ if ( it->mpWindow )
+ {
+ if ( it->mbShowWindow )
+ {
+ Point aPos( it->maCalcRect.Left(), it->maCalcRect.Top() );
+ it->mpWindow->SetPosPixel( aPos );
+ if ( !mbCustomizeMode )
+ it->mpWindow->Show();
+ }
+ else
+ it->mpWindow->Hide();
+ }
+
+ ++it;
+ } // end of loop over all items
+ }
+ else
+ // we have no toolbox items
+ mnCurLines = 1;
+
+
+ if( IsMenuEnabled() && ImplIsFloatingMode() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
+ {
+ // custom menu will be the last button in floating mode
+ ImplToolItem &rIt = mpData->maMenubuttonItem;
+
+ if ( mbHorz )
+ {
+ rIt.maRect.Left() = nX+TB_MENUBUTTON_OFFSET;
+ rIt.maRect.Top() = nY;
+ rIt.maRect.Right() = rIt.maRect.Left() + mpData->mnMenuButtonWidth;
+ rIt.maRect.Bottom() = nY+nLineSize-1;
+ nX += rIt.maItemSize.Width();
+ }
+ else
+ {
+ rIt.maRect.Left() = nX;
+ rIt.maRect.Top() = nY+TB_MENUBUTTON_OFFSET;
+ rIt.maRect.Right() = nX+nLineSize-1;
+ rIt.maRect.Bottom() = rIt.maRect.Top() + mpData->mnMenuButtonWidth;
+ nY += rIt.maItemSize.Height();
+ }
+ }
+
+
+ // if toolbox visible trigger paint for changed regions
+ if ( IsVisible() && !mbFullPaint )
+ {
+ if ( bMustFullPaint )
+ {
+ maPaintRect = Rectangle( mnLeftBorder, mnTopBorder,
+ mnDX-mnRightBorder, mnDY-mnBottomBorder );
+ }
+ else
+ {
+ if ( aOldLowerRect != maLowerRect )
+ {
+ maPaintRect.Union( maLowerRect );
+ maPaintRect.Union( aOldLowerRect );
+ }
+ if ( aOldUpperRect != maUpperRect )
+ {
+ maPaintRect.Union( maUpperRect );
+ maPaintRect.Union( aOldUpperRect );
+ }
+ if ( aOldNextToolRect != maNextToolRect )
+ {
+ maPaintRect.Union( maNextToolRect );
+ maPaintRect.Union( aOldNextToolRect );
+ }
+ if ( aOldMenubuttonRect != mpData->maMenubuttonItem.maRect )
+ {
+ maPaintRect.Union( mpData->maMenubuttonItem.maRect );
+ maPaintRect.Union( aOldMenubuttonRect );
+ }
+ if ( pWrapper && aOldDragRect != pWrapper->GetDragArea() )
+ {
+ maPaintRect.Union( pWrapper->GetDragArea() );
+ maPaintRect.Union( aOldDragRect );
+ }
+
+ it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ if ( it->maRect != it->maCalcRect )
+ {
+ maPaintRect.Union( it->maRect );
+ maPaintRect.Union( it->maCalcRect );
+ }
+ ++it;
+ }
+ }
+
+ Invalidate( maPaintRect );
+ }
+
+ // store the new calculated item rects
+ maPaintRect = aEmptyRect;
+ Rectangle aVisibleRect(Point(0, 0), GetOutputSizePixel());
+ it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ it->maRect = it->maCalcRect;
+ if (!it->maRect.IsOver(aVisibleRect))
+ {
+ // For items not visible, release resources only needed during
+ // painting the items (on Win98, for example, these are system-
+ // wide resources that are easily exhausted, so be nice):
+
+ /* !!!
+ it->maImage.ClearCaches();
+ it->maHighImage.ClearCaches();
+ */
+ }
+ ++it;
+ }
+ }
+
+ // indicate formatting is done
+ mbFormat = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ToolBox, ImplDropdownLongClickHdl, ToolBox*, EMPTYARG )
+{
+ if( mnCurPos != TOOLBOX_ITEM_NOTFOUND &&
+ (mpData->m_aItems[ mnCurPos ].mnBits & TIB_DROPDOWN)
+ )
+ {
+ mpData->mbDropDownByKeyboard = FALSE;
+ GetDropdownClickHdl().Call( this );
+
+ // do not reset data if the dropdown handler opened a floating window
+ // see ImplFloatControl()
+ if( mpFloatWin == NULL )
+ {
+ // no floater was opened
+ Deactivate();
+ ImplDrawItem( mnCurPos, FALSE );
+
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+ mnHighItemId = 0;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ToolBox, ImplUpdateHdl, void*, EMPTYARG )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( mbFormat )
+ ImplFormat();
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawMoreIndicator( ToolBox *pBox, const Rectangle& rRect, BOOL bSetColor, BOOL bRotate )
+{
+ Color aOldFillColor = pBox->GetFillColor();
+ Color aOldLineColor = pBox->GetLineColor();
+ pBox->SetLineColor();
+
+ if ( bSetColor )
+ {
+ if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
+ pBox->SetFillColor( Color( COL_WHITE ) );
+ else
+ pBox->SetFillColor( Color( COL_BLACK ) );
+ }
+
+ if( !bRotate )
+ {
+ long width = 8;
+ long height = 5;
+ long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
+ long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
+ while( height >= 1)
+ {
+ pBox->DrawRect( Rectangle( x, y, x+1, y ) );
+ x+=4;
+ pBox->DrawRect( Rectangle( x, y, x+1, y ) );
+ x-=4;
+ y++;
+ if( height <= 3) x--;
+ else x++;
+ height--;
+ }
+ }
+ else
+ {
+ long width = 5;
+ long height = 8;
+ long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
+ long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
+ while( width >= 1)
+ {
+ pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
+ y+=4;
+ pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
+ y-=4;
+ x++;
+ if( width <= 3) y--;
+ else y++;
+ width--;
+ }
+ }
+
+ pBox->SetFillColor( aOldFillColor );
+ pBox->SetLineColor( aOldLineColor );
+}
+
+static void ImplDrawDropdownArrow( ToolBox *pBox, const Rectangle& rDropDownRect, BOOL bSetColor, BOOL bRotate )
+{
+ BOOL bLineColor = pBox->IsLineColor();
+ BOOL bFillColor = pBox->IsFillColor();
+ Color aOldFillColor = pBox->GetFillColor();
+ Color aOldLineColor = pBox->GetLineColor();
+ pBox->SetLineColor();
+
+ if ( bSetColor )
+ {
+ if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
+ pBox->SetFillColor( Color( COL_WHITE ) );
+ else
+ pBox->SetFillColor( Color( COL_BLACK ) );
+ }
+
+ if( !bRotate )
+ {
+ long width = 5;
+ long height = 3;
+ long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
+ long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
+ while( width >= 1)
+ {
+ pBox->DrawRect( Rectangle( x, y, x+width-1, y ) );
+ y++; x++;
+ width -= 2;
+ }
+ }
+ else
+ {
+ long width = 3;
+ long height = 5;
+ long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
+ long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
+ while( height >= 1)
+ {
+ pBox->DrawRect( Rectangle( x, y, x, y+height-1 ) );
+ y++; x++;
+ height -= 2;
+ }
+ }
+
+ if( bFillColor )
+ pBox->SetFillColor( aOldFillColor );
+ else
+ pBox->SetFillColor();
+ if( bLineColor )
+ pBox->SetLineColor( aOldLineColor );
+ else
+ pBox->SetLineColor( );
+}
+
+void ToolBox::ImplDrawToolArrow( ToolBox* pBox, long nX, long nY, BOOL bBlack, BOOL bColTransform,
+ BOOL bLeft, BOOL bTop, long nSize )
+{
+ Color aOldFillColor = pBox->GetFillColor();
+ WindowAlign eAlign = pBox->meAlign;
+ long n = 0;
+ long nHalfSize;
+ if ( bLeft )
+ eAlign = WINDOWALIGN_RIGHT;
+ else if ( bTop )
+ eAlign = WINDOWALIGN_BOTTOM;
+
+ nHalfSize = nSize/2;
+
+ switch ( eAlign )
+ {
+ case WINDOWALIGN_LEFT:
+ if ( bBlack )
+ pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
+ while ( n <= nHalfSize )
+ {
+ pBox->DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) );
+ n++;
+ }
+ if ( bBlack )
+ {
+ pBox->SetFillColor( aOldFillColor );
+ n = 1;
+ while ( n < nHalfSize )
+ {
+ pBox->DrawRect( Rectangle( nX+n, nY+1+n, nX+n, nY+nSize-1-n ) );
+ n++;
+ }
+ }
+ break;
+ case WINDOWALIGN_TOP:
+ if ( bBlack )
+ pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
+ while ( n <= nHalfSize )
+ {
+ pBox->DrawRect( Rectangle( nX+n, nY+n, nX+nSize-n, nY+n ) );
+ n++;
+ }
+ if ( bBlack )
+ {
+ pBox->SetFillColor( aOldFillColor );
+ n = 1;
+ while ( n < nHalfSize )
+ {
+ pBox->DrawRect( Rectangle( nX+1+n, nY+n, nX+nSize-1-n, nY+n ) );
+ n++;
+ }
+ }
+ break;
+ case WINDOWALIGN_RIGHT:
+ if ( bBlack )
+ pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
+ while ( n <= nHalfSize )
+ {
+ pBox->DrawRect( Rectangle( nX+nHalfSize-n, nY+n, nX+nHalfSize-n, nY+nSize-n ) );
+ n++;
+ }
+ if ( bBlack )
+ {
+ pBox->SetFillColor( aOldFillColor );
+ n = 1;
+ while ( n < nHalfSize )
+ {
+ pBox->DrawRect( Rectangle( nX+nHalfSize-n, nY+1+n, nX+nHalfSize-n, nY+nSize-1-n ) );
+ n++;
+ }
+ }
+ break;
+ case WINDOWALIGN_BOTTOM:
+ if ( bBlack )
+ pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
+ while ( n <= nHalfSize )
+ {
+ pBox->DrawRect( Rectangle( nX+n, nY+nHalfSize-n, nX+nSize-n, nY+nHalfSize-n ) );
+ n++;
+ }
+ if ( bBlack )
+ {
+ pBox->SetFillColor( aOldFillColor );
+ n = 1;
+ while ( n < nHalfSize )
+ {
+ pBox->DrawRect( Rectangle( nX+1+n, nY+nHalfSize-n, nX+nSize-1-n, nY+nHalfSize-n ) );
+ n++;
+ }
+ }
+ break;
+ }
+}
+
+void ToolBox::SetToolArrowClipregion( ToolBox* pBox, long nX, long nY,
+ BOOL bLeft, BOOL bTop, long nSize )
+{
+ WindowAlign eAlign = pBox->meAlign;
+ long nHalfSize;
+ if ( bLeft )
+ eAlign = WINDOWALIGN_RIGHT;
+ else if ( bTop )
+ eAlign = WINDOWALIGN_BOTTOM;
+
+ nHalfSize = nSize/2;
+
+ Point p[6];
+
+ switch ( eAlign )
+ {
+ case WINDOWALIGN_LEFT:
+ p[0].X() = nX-1; p[0].Y() = nY-1;
+ p[1].X() = nX-1; p[1].Y() = nY+nSize+1;
+ p[2].X() = nX+1; p[2].Y() = nY+nSize+1;
+ p[3].X() = nX+nHalfSize+1; p[3].Y() = nY+nHalfSize+1;
+ p[4].X() = nX+nHalfSize+1; p[4].Y() = nY+nHalfSize-1;
+ p[5].X() = nX+1; p[5].Y() = nY-1;
+ break;
+ case WINDOWALIGN_TOP:
+ p[0].X() = nX-1; p[0].Y() = nY-1;
+ p[1].X() = nX-1; p[1].Y() = nY+1;
+ p[2].X() = nX+nHalfSize-1; p[2].Y() = nY+nHalfSize+1;
+ p[3].X() = nX+nHalfSize+1; p[3].Y() = nY+nHalfSize+1;
+ p[4].X() = nX+nSize+1; p[4].Y() = nY+1;
+ p[5].X() = nX+nSize+1; p[5].Y() = nY-1;
+ break;
+ case WINDOWALIGN_RIGHT:
+ p[0].X() = nX+nHalfSize-1; p[0].Y() = nY-1;
+ p[1].X() = nX-1; p[1].Y() = nY+nHalfSize-1;
+ p[2].X() = nX-1; p[2].Y() = nY+nHalfSize+1;
+ p[3].X() = nX+nHalfSize-1; p[3].Y() = nY+nSize+1;
+ p[4].X() = nX+nHalfSize+1; p[4].Y() = nY+nSize+1;
+ p[5].X() = nX+nHalfSize+1; p[5].Y() = nY-1;
+ break;
+ case WINDOWALIGN_BOTTOM:
+ p[0].X() = nX-1; p[0].Y() = nY+nHalfSize-1;
+ p[1].X() = nX-1; p[1].Y() = nY+nHalfSize+1;
+ p[2].X() = nX+nSize+1; p[2].Y() = nY+nHalfSize+1;
+ p[3].X() = nX+nSize+1; p[3].Y() = nY+nHalfSize-1;
+ p[4].X() = nX+nHalfSize+1; p[4].Y() = nY-1;
+ p[5].X() = nX+nHalfSize-1; p[5].Y() = nY-1;
+ break;
+ }
+ Polygon aPoly(6,p);
+ Region aRgn( aPoly );
+ pBox->SetClipRegion( aRgn );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDrawMenubutton( ToolBox *pThis, BOOL bHighlight )
+{
+ if( !pThis->mpData->maMenubuttonItem.maRect.IsEmpty() )
+ {
+ // #i53937# paint menu button only if necessary
+ if( !(pThis->GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE) && !pThis->ImplHasClippedItems() )
+ return;
+
+ // execute pending paint requests
+ ImplCheckUpdate( pThis );
+
+ BOOL bFillColor = pThis->IsFillColor();
+ BOOL bLineColor = pThis->IsLineColor();
+ Color aOldFillCol = pThis->GetFillColor();
+ Color aOldLineCol = pThis->GetLineColor();
+ BOOL bNativeButtons = pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON );
+
+ Rectangle aInnerRect( pThis->mpData->maMenubuttonItem.maRect );
+ if( pThis->mpData->mnMenuButtonWidth > TB_MENUBUTTON_SIZE )
+ {
+ long nDiff = pThis->mpData->mnMenuButtonWidth - TB_MENUBUTTON_SIZE;
+ long nDiff1 = nDiff/2;
+ long nDiff2 = nDiff - nDiff1;
+ if( pThis->IsHorizontal() )
+ {
+ aInnerRect.Left() += nDiff1;
+ aInnerRect.Right() -= nDiff2;
+ }
+ else
+ {
+ aInnerRect.Top() += nDiff1;
+ aInnerRect.Bottom() -= nDiff2;
+ }
+ }
+
+ if( pThis->IsHorizontal() )
+ {
+ aInnerRect.nLeft+=2;
+ aInnerRect.nRight-=1;
+ aInnerRect.nTop+=1;
+ aInnerRect.nBottom-=1;
+ }
+ else
+ {
+ aInnerRect.nLeft+=1;
+ aInnerRect.nRight-=1;
+ aInnerRect.nTop+=2;
+ aInnerRect.nBottom-=1;
+ }
+
+ ImplErase( pThis, bNativeButtons ? pThis->mpData->maMenubuttonItem.maRect : aInnerRect, bHighlight );
+
+ if( bHighlight )
+ {
+ if( bNativeButtons )
+ ImplDrawButton( pThis, pThis->mpData->maMenubuttonItem.maRect, 2, FALSE, TRUE, FALSE );
+ else
+ pThis->DrawSelectionBackground( aInnerRect, 2, FALSE, FALSE, FALSE );
+ }
+ else
+ {
+ // improve visibility by using a dark gradient
+ Gradient g;
+ g.SetAngle( pThis->mbHorz ? 0 : 900 );
+ g.SetStyle( GRADIENT_LINEAR );
+
+ g.SetStartColor( pThis->GetSettings().GetStyleSettings().GetFaceColor() );
+ g.SetEndColor( pThis->GetSettings().GetStyleSettings().GetShadowColor() );
+
+ pThis->DrawGradient( aInnerRect, g );
+ }
+
+ Rectangle aRect( aInnerRect );
+ if( pThis->mbHorz )
+ aRect.Top() = aRect.Bottom() - aRect.getHeight()/3;
+ else
+ aRect.Left() = aRect.Right() - aRect.getWidth()/3;
+
+ if( pThis->mpData->maMenuType & TOOLBOX_MENUTYPE_CUSTOMIZE )
+ ImplDrawDropdownArrow( pThis, aRect, TRUE, !pThis->mbHorz );
+
+ if( pThis->ImplHasClippedItems() )
+ {
+ aRect = aInnerRect;
+ if( pThis->mbHorz )
+ aRect.Bottom() = aRect.Top() + aRect.getHeight()/3;
+ else
+ aRect.Right() = aRect.Left() + aRect.getWidth()/3;
+
+ ImplDrawMoreIndicator( pThis, aRect, TRUE, !pThis->mbHorz );
+ }
+
+ // store highlight state
+ pThis->mpData->mbMenubuttonSelected = bHighlight;
+
+ // restore colors
+ if( bFillColor )
+ pThis->SetFillColor( aOldFillCol );
+ else
+ pThis->SetFillColor();
+ if( bLineColor )
+ pThis->SetLineColor( aOldLineCol );
+ else
+ pThis->SetLineColor();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDrawSpin( BOOL bUpperIn, BOOL bLowerIn )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ BOOL bTmpUpper;
+ BOOL bTmpLower;
+
+ if ( maUpperRect.IsEmpty() || maLowerRect.IsEmpty() )
+ return;
+
+ if ( mnCurLine > 1 )
+ bTmpUpper = TRUE;
+ else
+ bTmpUpper = FALSE;
+
+ if ( mnCurLine+mnVisLines-1 < mnCurLines )
+ bTmpLower = TRUE;
+ else
+ bTmpLower = FALSE;
+
+ if ( !IsEnabled() )
+ {
+ bTmpUpper = FALSE;
+ bTmpLower = FALSE;
+ }
+
+ ImplDrawSpinButton( this, maUpperRect, maLowerRect,
+ bUpperIn, bLowerIn, bTmpUpper, bTmpLower, !mbHorz );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDrawNext( BOOL bIn )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( maNextToolRect.IsEmpty() )
+ return;
+
+ DecorationView aDecoView( this );
+
+ // Button malen
+ long nX = SMALLBUTTON_OFF_NORMAL_X;
+ long nY = SMALLBUTTON_OFF_NORMAL_Y;
+ USHORT nStyle = 0;
+ if ( bIn == 1 )
+ {
+ nStyle |= BUTTON_DRAW_PRESSED;
+ nX = SMALLBUTTON_OFF_PRESSED_X;
+ nY = SMALLBUTTON_OFF_PRESSED_Y;
+ }
+ aDecoView.DrawButton( maNextToolRect, nStyle );
+
+ // Inhalt ausgeben
+ BOOL bLeft = FALSE;
+ BOOL bTop = FALSE;
+ if ( mbHorz )
+ {
+ bLeft = TRUE;
+ nX += (maNextToolRect.GetWidth()-6)/2-4;
+ nY += (maNextToolRect.GetHeight()-6)/2-6;
+ }
+ else
+ {
+ bTop = TRUE;
+ nY += (maNextToolRect.GetHeight()-6)/2-4;
+ nX += (maNextToolRect.GetWidth()-6)/2-6;
+ }
+
+ nX += maNextToolRect.Left();
+ nY += maNextToolRect.Top();
+ SetLineColor();
+ SetFillColor( COL_LIGHTBLUE );
+ ImplDrawToolArrow( this, nX, nY, TRUE, FALSE, bLeft, bTop, 10 );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, USHORT highlight, BOOL bChecked, BOOL bEnabled, BOOL bIsWindow )
+{
+ // draws toolbar button background either native or using a coloured selection
+ // if bIsWindow is TRUE, the corresponding item is a control and only a selection border will be drawn
+
+ BOOL bNativeOk = FALSE;
+ if( !bIsWindow && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
+ {
+ ImplControlValue aControlValue;
+ ControlState nState = 0;
+
+ if ( highlight == 1 ) nState |= CTRL_STATE_PRESSED;
+ if ( highlight == 2 ) nState |= CTRL_STATE_ROLLOVER;
+ if ( bEnabled ) nState |= CTRL_STATE_ENABLED;
+
+ aControlValue.setTristateVal( bChecked ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
+
+
+ bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
+ rRect, nState, aControlValue, rtl::OUString() );
+ }
+
+ if( !bNativeOk )
+ pThis->DrawSelectionBackground( rRect, bIsWindow ? 3 : highlight, bChecked, TRUE, bIsWindow, 2, NULL, NULL );
+}
+
+void ToolBox::ImplDrawItem( USHORT nPos, BOOL bHighlight, BOOL bPaint, BOOL bLayout )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( nPos >= mpData->m_aItems.size() )
+ return;
+
+ // execute pending paint requests
+ ImplCheckUpdate( this );
+
+ ImplDisableFlatButtons();
+
+ SetFillColor();
+
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+ MetricVector* pVector = bLayout ? &mpData->m_pLayoutData->m_aUnicodeBoundRects : NULL;
+ String* pDisplayText = bLayout ? &mpData->m_pLayoutData->m_aDisplayText : NULL;
+
+ // Falls Rechteck ausserhalb des sichbaren Bereichs liegt
+ if ( pItem->maRect.IsEmpty() )
+ return;
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ // no gradient background for items that have a popup open
+ BOOL bHasOpenPopup = (mpFloatWin != NULL) && (mnDownItemId==pItem->mnId);
+
+ BOOL bHighContrastWhite = FALSE;
+ // check the face color as highcontrast indicator
+ // because the toolbox itself might have a gradient
+ if( rStyleSettings.GetFaceColor() == Color( COL_WHITE ) )
+ bHighContrastWhite = TRUE;
+
+ // draw separators in flat style only
+ if ( !bLayout &&
+ (mnOutStyle & TOOLBOX_STYLE_FLAT) &&
+ (pItem->meType == TOOLBOXITEM_SEPARATOR) &&
+ nPos > 0
+ )
+ {
+ // no separator before or after windows or at breaks
+ ImplToolItem* pTempItem = &mpData->m_aItems[nPos-1];
+ if ( pTempItem && !pTempItem->mbShowWindow && nPos < mpData->m_aItems.size()-1 )
+ {
+ pTempItem = &mpData->m_aItems[nPos+1];
+ if ( !pTempItem->mbShowWindow && !pTempItem->mbBreak )
+ {
+ long nCenterPos, nSlim;
+ SetLineColor( rStyleSettings.GetSeparatorColor() );
+ if ( IsHorizontal() )
+ {
+ nSlim = (pItem->maRect.Bottom() - pItem->maRect.Top ()) / 4;
+ nCenterPos = pItem->maRect.Center().X();
+ DrawLine( Point( nCenterPos, pItem->maRect.Top() + nSlim ),
+ Point( nCenterPos, pItem->maRect.Bottom() - nSlim ) );
+ }
+ else
+ {
+ nSlim = (pItem->maRect.Right() - pItem->maRect.Left ()) / 4;
+ nCenterPos = pItem->maRect.Center().Y();
+ DrawLine( Point( pItem->maRect.Left() + nSlim, nCenterPos ),
+ Point( pItem->maRect.Right() - nSlim, nCenterPos ) );
+ }
+ }
+ }
+ }
+
+ // do nothing if item is no button or will be displayed as window
+ if ( (pItem->meType != TOOLBOXITEM_BUTTON) ||
+ (pItem->mbShowWindow && !mbCustomizeMode) )
+ return;
+
+ // we need a TBDragMananger to draw the configuration item
+ ImplTBDragMgr* pMgr;
+ if ( pItem->mnId == mnConfigItem )
+ {
+ pMgr = ImplGetTBDragMgr();
+ pMgr->HideDragRect();
+ }
+ else
+ pMgr = NULL;
+
+ // during configuration mode visible windows will be drawn in a special way
+ if ( mbCustomizeMode && pItem->mbShowWindow )
+ {
+ Font aOldFont = GetFont();
+ Color aOldTextColor = GetTextColor();
+
+ SetZoomedPointFont( rStyleSettings.GetAppFont() );
+ SetLineColor( Color( COL_BLACK ) );
+ SetFillColor( rStyleSettings.GetFieldColor() );
+ SetTextColor( rStyleSettings.GetFieldTextColor() );
+ if( !bLayout )
+ DrawRect( pItem->maRect );
+
+ Size aSize( GetCtrlTextWidth( pItem->maText ), GetTextHeight() );
+ Point aPos( pItem->maRect.Left()+2, pItem->maRect.Top() );
+ aPos.Y() += (pItem->maRect.GetHeight()-aSize.Height())/2;
+ BOOL bClip;
+ if ( (aSize.Width() > pItem->maRect.GetWidth()-2) ||
+ (aSize.Height() > pItem->maRect.GetHeight()-2) )
+ {
+ bClip = TRUE;
+ Rectangle aTempRect( pItem->maRect.Left()+1, pItem->maRect.Top()+1,
+ pItem->maRect.Right()-1, pItem->maRect.Bottom()-1 );
+ Region aTempRegion( aTempRect );
+ SetClipRegion( aTempRegion );
+ }
+ else
+ bClip = FALSE;
+ if( bLayout )
+ {
+ mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.Len() );
+ mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
+ mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
+ }
+ DrawCtrlText( aPos, pItem->maText, 0, STRING_LEN, TEXT_DRAW_MNEMONIC, pVector, pDisplayText );
+ if ( bClip )
+ SetClipRegion();
+ SetFont( aOldFont );
+ SetTextColor( aOldTextColor );
+
+ // Gegebenenfalls noch Config-Frame zeichnen
+ if ( pMgr && !bLayout)
+ pMgr->UpdateDragRect();
+ return;
+ }
+
+ // draw button
+ Size aBtnSize = pItem->maRect.GetSize();
+ if( ImplGetSVData()->maNWFData.mbToolboxDropDownSeparate )
+ {
+ // separate button not for dropdown only where the whole button is painted
+ if ( pItem->mnBits & TIB_DROPDOWN &&
+ ((pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY) )
+ {
+ Rectangle aArrowRect = pItem->GetDropDownRect( mbHorz );
+ if( aArrowRect.Top() == pItem->maRect.Top() ) // dropdown arrow on right side
+ aBtnSize.Width() -= aArrowRect.GetWidth();
+ else // dropdown arrow on bottom side
+ aBtnSize.Height() -= aArrowRect.GetHeight();
+ }
+ }
+ Rectangle aButtonRect( pItem->maRect.TopLeft(), aBtnSize );
+ long nOffX = SMALLBUTTON_OFF_NORMAL_X;
+ long nOffY = SMALLBUTTON_OFF_NORMAL_Y;
+ long nImageOffX=0;
+ long nImageOffY=0;
+ long nTextOffX=0;
+ long nTextOffY=0;
+ USHORT nStyle = 0;
+
+ if ( pItem->meState == STATE_CHECK )
+ {
+ nStyle |= BUTTON_DRAW_CHECKED;
+ }
+ else if ( pItem->meState == STATE_DONTKNOW )
+ {
+ nStyle |= BUTTON_DRAW_DONTKNOW;
+ }
+ if ( bHighlight == 1 )
+ {
+ nStyle |= BUTTON_DRAW_PRESSED;
+ }
+
+ if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
+ {
+ nOffX = OUTBUTTON_OFF_NORMAL_X;
+ nOffY = OUTBUTTON_OFF_NORMAL_Y;
+ if ( bHighlight )
+ {
+ nOffX++;
+ nOffY++;
+ }
+ }
+
+ if( ! bLayout )
+ {
+ if ( mnOutStyle & TOOLBOX_STYLE_FLAT )
+ {
+ if ( (pItem->meState != STATE_NOCHECK) || !bPaint )
+ {
+ ImplErase( this, pItem->maRect, bHighlight, bHasOpenPopup );
+ }
+ }
+ else
+ {
+ if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
+ ImplDrawOutButton( this, aButtonRect, nStyle );
+ else
+ {
+ DecorationView aDecoView( this );
+ aDecoView.DrawButton( aButtonRect, nStyle );
+ }
+ }
+ }
+
+ nOffX += pItem->maRect.Left();
+ nOffY += pItem->maRect.Top();
+
+ // determine what has to be drawn on the button: image, text or both
+ BOOL bImage;
+ BOOL bText;
+ ButtonType tmpButtonType = determineButtonType( pItem, meButtonType ); // default to toolbox setting
+ pItem->DetermineButtonDrawStyle( tmpButtonType, bImage, bText );
+
+ // compute output values
+ long nBtnWidth = aBtnSize.Width()-SMALLBUTTON_HSIZE;
+ long nBtnHeight = aBtnSize.Height()-SMALLBUTTON_VSIZE;
+ Size aImageSize;
+ Size aTxtSize;
+
+ if ( bText )
+ {
+ aTxtSize.Width() = GetCtrlTextWidth( pItem->maText );
+ aTxtSize.Height() = GetTextHeight();
+ }
+
+ if ( bImage && ! bLayout )
+ {
+ const Image* pImage;
+ if ( bHighlight && (!(pItem->maHighImage)) == FALSE )
+ pImage = &(pItem->maHighImage);
+ else
+ pImage = &(pItem->maImage);
+
+ aImageSize = pImage->GetSizePixel();
+
+ // determine drawing flags
+ USHORT nImageStyle = 0;
+
+ if ( !pItem->mbEnabled || !IsEnabled() )
+ nImageStyle |= IMAGE_DRAW_DISABLE;
+
+ // #i35563# the dontknow state indicates different states at the same time
+ // which should not be rendered disabled but normal
+ //if ( pItem->meState == STATE_DONTKNOW )
+ // nImageStyle |= IMAGE_DRAW_DISABLE;
+
+ // draw the image
+ nImageOffX = nOffX;
+ nImageOffY = nOffY;
+ if ( (pItem->mnBits & (TIB_LEFT|TIB_DROPDOWN)) || bText )
+ {
+ // left align also to leave space for drop down arrow
+ // and when drawing text+image
+ // just center in y, except for vertical (ie rotated text)
+ if( mbHorz || !bText )
+ nImageOffY += (nBtnHeight-aImageSize.Height())/2;
+ }
+ else
+ {
+ nImageOffX += (nBtnWidth-aImageSize.Width())/2;
+ nImageOffY += (nBtnHeight-aImageSize.Height())/2;
+ }
+ if ( bHighlight || (pItem->meState == STATE_CHECK) )
+ {
+ if( bHasOpenPopup )
+ ImplDrawFloatwinBorder( pItem );
+ else
+ ImplDrawButton( this, aButtonRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? TRUE : FALSE );
+
+ if( bHighlight )
+ {
+ if( bHighContrastWhite )
+ nImageStyle |= IMAGE_DRAW_COLORTRANSFORM;
+ }
+ }
+ DrawImage( Point( nImageOffX, nImageOffY ), *pImage, nImageStyle );
+ }
+
+ // draw the text
+ BOOL bRotate = FALSE;
+ if ( bText )
+ {
+ nTextOffX = nOffX;
+ nTextOffY = nOffY;
+
+ // rotate text when vertically docked
+ Font aOldFont = GetFont();
+ if( pItem->mbVisibleText && !ImplIsFloatingMode() &&
+ ((meAlign == WINDOWALIGN_LEFT) || (meAlign == WINDOWALIGN_RIGHT)) )
+ {
+ bRotate = TRUE;
+
+ Font aRotateFont = aOldFont;
+ /*
+ if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ aRotateFont.SetOrientation( 900 );
+ nTextOffX += (nBtnWidth-aTxtSize.Height())/2;
+ nTextOffY += aTxtSize.Width();
+ nTextOffY += (nBtnHeight-aTxtSize.Width())/2;
+ }
+ else*/
+ {
+ aRotateFont.SetOrientation( 2700 );
+
+ // center horizontally
+ nTextOffX += aTxtSize.Height();
+ nTextOffX += (nBtnWidth-aTxtSize.Height())/2;
+
+ // add in image offset
+ if( bImage )
+ nTextOffY = nImageOffY + aImageSize.Height() + TB_IMAGETEXTOFFSET;
+ }
+
+ SetFont( aRotateFont );
+ }
+ else
+ {
+ // center vertically
+ nTextOffY += (nBtnHeight-aTxtSize.Height())/2;
+
+ // add in image offset
+ if( bImage )
+ nTextOffX = nImageOffX + aImageSize.Width() + TB_IMAGETEXTOFFSET;
+ //nTextOffX += TB_TEXTOFFSET/2;
+ }
+
+ // draw selection only if not already drawn during image output (see above)
+ if ( !bLayout && !bImage && (bHighlight || (pItem->meState == STATE_CHECK) ) )
+ {
+ if( bHasOpenPopup )
+ ImplDrawFloatwinBorder( pItem );
+ else
+ ImplDrawButton( this, pItem->maRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? TRUE : FALSE );
+ }
+
+ USHORT nTextStyle = 0;
+ if ( !pItem->mbEnabled )
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ if( bLayout )
+ {
+ mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.Len() );
+ mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
+ mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
+ }
+ DrawCtrlText( Point( nTextOffX, nTextOffY ), pItem->maText,
+ 0, STRING_LEN, nTextStyle, pVector, pDisplayText );
+ if ( bRotate )
+ SetFont( aOldFont );
+ }
+
+ if( bLayout )
+ return;
+
+ // paint optional drop down arrow
+ if ( pItem->mnBits & TIB_DROPDOWN )
+ {
+ Rectangle aDropDownRect( pItem->GetDropDownRect( mbHorz ) );
+ BOOL bSetColor = TRUE;
+ if ( !pItem->mbEnabled || !IsEnabled() )
+ {
+ bSetColor = FALSE;
+ SetFillColor( rStyleSettings.GetShadowColor() );
+ }
+
+ // dropdown only will be painted without inner border
+ if( (pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY )
+ {
+ ImplErase( this, aDropDownRect, bHighlight, bHasOpenPopup );
+
+ if( bHighlight || (pItem->meState == STATE_CHECK) )
+ {
+ if( bHasOpenPopup )
+ ImplDrawFloatwinBorder( pItem );
+ else
+ ImplDrawButton( this, aDropDownRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), FALSE );
+ }
+ }
+ ImplDrawDropdownArrow( this, aDropDownRect, bSetColor, bRotate );
+ }
+
+ // Gegebenenfalls noch Config-Frame zeichnen
+ if ( pMgr )
+ pMgr->UpdateDragRect();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplStartCustomizeMode()
+{
+ mbCustomizeMode = TRUE;
+
+ mpData->ImplClearLayoutData();
+
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ if ( it->mbShowWindow )
+ {
+ it->mpWindow->Hide();
+
+ if ( !(it->maRect.IsEmpty()) )
+ Invalidate( it->maRect );
+ }
+
+ ++it;
+ }
+}
+
+void ToolBox::SetCustomizeMode( BOOL bSet )
+{
+ if ( bSet )
+ ImplStartCustomizeMode();
+ else
+ ImplEndCustomizeMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplEndCustomizeMode()
+{
+ mbCustomizeMode = FALSE;
+
+ mpData->ImplClearLayoutData();
+
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ if ( it->mbShowWindow )
+ {
+ if ( !(it->maRect.IsEmpty()) )
+ Invalidate( it->maRect );
+
+ it->mpWindow->Show();
+ }
+
+ ++it;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDrawFloatwinBorder( ImplToolItem* pItem )
+{
+ if ( !pItem->maRect.IsEmpty() )
+ {
+ Rectangle aRect( mpFloatWin->ImplGetItemEdgeClipRect() );
+ aRect.SetPos( AbsoluteScreenToOutputPixel( aRect.TopLeft() ) );
+ SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ Point p1, p2;
+
+ p1 = pItem->maRect.TopLeft();
+ p1.X()++;
+ p2 = pItem->maRect.TopRight();
+ p2.X()--;
+ DrawLine( p1, p2);
+ p1 = pItem->maRect.BottomLeft();
+ p1.X()++;
+ p2 = pItem->maRect.BottomRight();
+ p2.X()--;
+ DrawLine( p1, p2);
+
+ p1 = pItem->maRect.TopLeft();
+ p1.Y()++;
+ p2 = pItem->maRect.BottomLeft();
+ p2.Y()--;
+ DrawLine( p1, p2);
+ p1 = pItem->maRect.TopRight();
+ p1.Y()++;
+ p2 = pItem->maRect.BottomRight();
+ p2.Y()--;
+ DrawLine( p1, p2);
+
+ //DrawRect( pItem->maRect );
+ }
+}
+
+void ToolBox::ImplFloatControl( BOOL bStart, FloatingWindow* pFloatWindow )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( bStart )
+ {
+ mpFloatWin = pFloatWindow;
+
+ // redraw item, to trigger drawing of a special border
+ ImplDrawItem( mnCurPos, TRUE );
+
+ mbDrag = FALSE;
+ EndTracking();
+ ReleaseMouse();
+ }
+ else
+ {
+ mpFloatWin = NULL;
+
+ // if focus is still in this toolbox, then the floater was opened by keyboard
+ // draw current item with highlight and keep old state
+ BOOL bWasKeyboardActivate = mpData->mbDropDownByKeyboard;
+
+
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ ImplDrawItem( mnCurPos, bWasKeyboardActivate ? 2 : 0 );
+ Deactivate();
+
+ if( !bWasKeyboardActivate )
+ {
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ mnHighItemId = 0;
+ }
+ mnDownItemId = 0;
+
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ShowLine( BOOL bNext )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mbFormat = TRUE;
+
+ if ( mpData->mbPageScroll )
+ {
+ USHORT delta = mnVisLines;
+ if ( bNext )
+ {
+ mnCurLine = mnCurLine + delta;
+ if ( mnCurLine+mnVisLines-1 > mnCurLines )
+ mnCurLine = mnCurLines - mnVisLines+1;
+ }
+ else
+ {
+ if( mnCurLine >= delta+1 )
+ mnCurLine = mnCurLine - delta;
+ else
+ mnCurLine = 1;
+ }
+ }
+ else
+ {
+ if ( bNext )
+ mnCurLine++;
+ else
+ mnCurLine--;
+ }
+
+ ImplFormat();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::ImplHandleMouseMove( const MouseEvent& rMEvt, BOOL bRepeat )
+{
+ Point aMousePos = rMEvt.GetPosPixel();
+
+ // Ist ToolBox aktiv
+ if ( mbDrag && mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ // Befindet sich Maus ueber dem Item
+ ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
+ if ( pItem->maRect.IsInside( aMousePos ) )
+ {
+ if ( !mnCurItemId )
+ {
+ ImplDrawItem( mnCurPos, TRUE );
+ mnCurItemId = pItem->mnId;
+ Highlight();
+ }
+
+ if ( (pItem->mnBits & TIB_REPEAT) && bRepeat )
+ Select();
+ }
+ else
+ {
+ if ( mnCurItemId )
+ {
+ ImplDrawItem( mnCurPos );
+ mnCurItemId = 0;
+ ImplDrawItem( mnCurPos );
+ Highlight();
+ }
+ }
+
+ return TRUE;
+ }
+
+ if ( mbUpper )
+ {
+ BOOL bNewIn = maUpperRect.IsInside( aMousePos );
+ if ( bNewIn != mbIn )
+ {
+ mbIn = bNewIn;
+ ImplDrawSpin( mbIn, FALSE );
+ }
+ return TRUE;
+ }
+
+ if ( mbLower )
+ {
+ BOOL bNewIn = maLowerRect.IsInside( aMousePos );
+ if ( bNewIn != mbIn )
+ {
+ mbIn = bNewIn;
+ ImplDrawSpin( FALSE, mbIn );
+ }
+ return TRUE;
+ }
+
+ if ( mbNextTool )
+ {
+ BOOL bNewIn = maNextToolRect.IsInside( aMousePos );
+ if ( bNewIn != mbIn )
+ {
+ mbIn = bNewIn;
+ ImplDrawNext( mbIn );
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::ImplHandleMouseButtonUp( const MouseEvent& rMEvt, BOOL bCancel )
+{
+ ImplDisableFlatButtons();
+
+ // stop eventual running dropdown timer
+ if( mnCurPos < mpData->m_aItems.size() &&
+ (mpData->m_aItems[mnCurPos].mnBits & TIB_DROPDOWN ) )
+ {
+ mpData->maDropdownTimer.Stop();
+ }
+
+ if ( mbDrag || mbSelection )
+ {
+ // Hier die MouseDaten setzen, wenn Selection-Modus, da dann kein
+ // MouseButtonDown-Handler gerufen wird
+ if ( mbSelection )
+ {
+ mnMouseClicks = rMEvt.GetClicks();
+ mnMouseModifier = rMEvt.GetModifier();
+ }
+
+ Deactivate();
+
+ if ( mbDrag )
+ mbDrag = FALSE;
+ else
+ {
+ mbSelection = FALSE;
+ if ( mnCurPos == TOOLBOX_ITEM_NOTFOUND )
+ return TRUE;
+ }
+
+ // Wurde Maus ueber dem Item losgelassen
+ if( mnCurPos < mpData->m_aItems.size() )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
+ if ( pItem->maRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ mnCurItemId = pItem->mnId;
+ if ( !bCancel )
+ {
+ // Gegebenenfalls ein AutoCheck durchfuehren
+ if ( pItem->mnBits & TIB_AUTOCHECK )
+ {
+ if ( pItem->mnBits & TIB_RADIOCHECK )
+ {
+ if ( pItem->meState != STATE_CHECK )
+ SetItemState( pItem->mnId, STATE_CHECK );
+ }
+ else
+ {
+ if ( pItem->meState != STATE_CHECK )
+ pItem->meState = STATE_CHECK;
+ else
+ pItem->meState = STATE_NOCHECK;
+ }
+ }
+
+ // Select nicht bei Repeat ausloesen, da dies schon im
+ // MouseButtonDown ausgeloest wurde
+ if ( !(pItem->mnBits & TIB_REPEAT) )
+ {
+ // Gegen zerstoeren im Select-Handler sichern
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ Select();
+ if ( aDelData.IsDelete() )
+ return TRUE;
+ ImplRemoveDel( &aDelData );
+ }
+ }
+
+ {
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ // Items nicht geloescht, im Select-Handler
+ if ( mnCurItemId )
+ {
+ BOOL bHighlight;
+ if ( (mnCurItemId == mnHighItemId) && (mnOutStyle & TOOLBOX_STYLE_FLAT) )
+ bHighlight = 2;
+ else
+ bHighlight = FALSE;
+ // Get current pos for the case that items are inserted/removed
+ // in the toolBox
+ mnCurPos = GetItemPos( mnCurItemId );
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplDrawItem( mnCurPos, bHighlight );
+ Flush();
+ }
+ }
+ }
+ }
+
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+ return TRUE;
+ }
+ else if ( mbUpper || mbLower )
+ {
+ if ( mbIn )
+ ShowLine( !mbUpper );
+ mbUpper = FALSE;
+ mbLower = FALSE;
+ mbIn = FALSE;
+ ImplDrawSpin( FALSE, FALSE );
+ return TRUE;
+ }
+ else if ( mbNextTool )
+ {
+ mbNextTool = FALSE;
+ mbIn = FALSE;
+ ImplDrawNext( FALSE );
+ NextToolBox();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::MouseMove( const MouseEvent& rMEvt )
+{
+ // pressing a modifier generates synthetic mouse moves
+ // ignore it if keyboard selection is acive
+ if( HasFocus() && ( rMEvt.GetMode() & MOUSE_MODIFIERCHANGED ) )
+ return;
+
+ if ( ImplHandleMouseMove( rMEvt ) )
+ return;
+
+ ImplDisableFlatButtons();
+
+ Point aMousePos = rMEvt.GetPosPixel();
+
+ // only highlight when the focus is not inside a child window of a toolbox
+ // eg, in a edit control
+ // and do not hilight when focus is in a different toolbox
+ BOOL bDrawHotSpot = TRUE;
+ Window *pWin = Application::GetFocusWindow();
+ if( pWin && pWin->ImplGetWindowImpl()->mbToolBox && pWin != this )
+ bDrawHotSpot = FALSE;
+ /*
+ else
+ if( pWin && !pWin->ImplGetWindowImpl()->mbToolBox )
+ while( pWin )
+ {
+ pWin = pWin->GetParent();
+ if( pWin && pWin->ImplGetWindowImpl()->mbToolBox )
+ {
+ bDrawHotSpot = FALSE;
+ break;
+ }
+ }
+ */
+
+ if ( mbSelection && bDrawHotSpot )
+ {
+ USHORT i = 0;
+ USHORT nNewPos = TOOLBOX_ITEM_NOTFOUND;
+
+ // Item suchen, das geklickt wurde
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ // Wenn Mausposition in diesem Item vorhanden, kann die
+ // Suche abgebrochen werden
+ if ( it->maRect.IsInside( aMousePos ) )
+ {
+ // Wenn es ein Button ist, dann wird er selektiert
+ if ( it->meType == TOOLBOXITEM_BUTTON )
+ {
+ // Wenn er disablet ist, findet keine Aenderung
+ // statt
+ if ( !it->mbEnabled || it->mbShowWindow )
+ nNewPos = mnCurPos;
+ else
+ nNewPos = i;
+ }
+
+ break;
+ }
+
+ i++;
+ ++it;
+ }
+
+ // was a new entery selected ?
+ // don't change selection if keyboard selection is active and
+ // mouse leaves the toolbox
+ if ( nNewPos != mnCurPos && !( HasFocus() && nNewPos == TOOLBOX_ITEM_NOTFOUND ) )
+ {
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplDrawItem( mnCurPos );
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( mnCurPos ) );
+ }
+
+ mnCurPos = nNewPos;
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ mnCurItemId = mnHighItemId = it->mnId;
+ ImplDrawItem( mnCurPos, 2 /*TRUE*/ ); // always use shadow effect (2)
+ }
+ else
+ mnCurItemId = mnHighItemId = 0;
+
+ Highlight();
+ }
+ return;
+ }
+
+ if ( mbDragging )
+ {
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ pMgr->Dragging( aMousePos );
+ return;
+ }
+
+ PointerStyle eStyle = POINTER_ARROW;
+
+ // change mouse cursor over drag area
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper && pWrapper->GetDragArea().IsInside( rMEvt.GetPosPixel() ) )
+ eStyle = POINTER_MOVE;
+
+ if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
+ {
+ if ( rMEvt.GetMode() & MOUSE_SIMPLEMOVE )
+ {
+ USHORT nLinePtr = ImplTestLineSize( this, rMEvt.GetPosPixel() );
+ if ( nLinePtr & DOCK_LINEHSIZE )
+ {
+ if ( meAlign == WINDOWALIGN_LEFT )
+ eStyle = POINTER_WINDOW_ESIZE;
+ else
+ eStyle = POINTER_WINDOW_WSIZE;
+ }
+ else if ( nLinePtr & DOCK_LINEVSIZE )
+ {
+ if ( meAlign == WINDOWALIGN_TOP )
+ eStyle = POINTER_WINDOW_SSIZE;
+ else
+ eStyle = POINTER_WINDOW_NSIZE;
+ }
+ }
+ }
+
+ if ( (eStyle == POINTER_ARROW) && mbCustomizeMode )
+ {
+ // Item suchen, das geklickt wurde
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ // Wenn es ein Customize-Window ist, gegebenenfalls den
+ // Resize-Pointer anzeigen
+ if ( it->mbShowWindow )
+ {
+ if ( it->maRect.IsInside( aMousePos ) )
+ {
+ if ( it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X() )
+ eStyle = POINTER_HSIZEBAR;
+ break;
+ }
+ }
+
+ ++it;
+ }
+ }
+
+ if ( bDrawHotSpot && ( ((eStyle == POINTER_ARROW) && (mnOutStyle & TOOLBOX_STYLE_HANDPOINTER)) ||
+ (mnOutStyle & TOOLBOX_STYLE_FLAT) || !mnOutStyle ) )
+ {
+ BOOL bClearHigh = TRUE;
+ if ( !rMEvt.IsLeaveWindow() && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
+ {
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ if ( it->maRect.IsInside( aMousePos ) )
+ {
+ if ( (it->meType == TOOLBOXITEM_BUTTON) && it->mbEnabled )
+ {
+ if ( !mnOutStyle || (mnOutStyle & TOOLBOX_STYLE_FLAT) )
+ {
+ bClearHigh = FALSE;
+ if ( mnHighItemId != it->mnId )
+ {
+ USHORT nTempPos = sal::static_int_cast<USHORT>(it - mpData->m_aItems.begin());
+ if ( mnHighItemId )
+ {
+ ImplHideFocus();
+ USHORT nPos = GetItemPos( mnHighItemId );
+ ImplDrawItem( nPos );
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
+ }
+ if ( mpData->mbMenubuttonSelected )
+ {
+ // remove highlight from menubutton
+ ImplDrawMenubutton( this, FALSE );
+ }
+ mnHighItemId = it->mnId;
+ ImplDrawItem( nTempPos, 2 );
+ ImplShowFocus();
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
+ }
+ }
+ if ( mnOutStyle & TOOLBOX_STYLE_HANDPOINTER )
+ eStyle = POINTER_REFHAND;
+ }
+ break;
+ }
+
+ ++it;
+ }
+ }
+
+ // only clear highlight when focus is not in toolbar
+ BOOL bMenuButtonHit = mpData->maMenubuttonItem.maRect.IsInside( aMousePos );
+ if ( bClearHigh || bMenuButtonHit )
+ {
+ if ( !bMenuButtonHit && mpData->mbMenubuttonSelected )
+ {
+ // remove highlight from menubutton
+ ImplDrawMenubutton( this, FALSE );
+ }
+
+ if( mnHighItemId )
+ {
+ USHORT nClearPos = GetItemPos( mnHighItemId );
+ if ( nClearPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplDrawItem( nClearPos, (nClearPos == mnCurPos) ? TRUE : FALSE );
+ if( nClearPos != mnCurPos )
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nClearPos ) );
+ }
+ ImplHideFocus();
+ mnHighItemId = 0;
+ }
+
+ if( bMenuButtonHit )
+ {
+ ImplDrawMenubutton( this, TRUE );
+ }
+ }
+ }
+
+ if ( meLastStyle != eStyle )
+ {
+ meLastStyle = eStyle;
+ Pointer aPtr( eStyle );
+ SetPointer( aPtr );
+ }
+
+ DockingWindow::MouseMove( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // Nur bei linker Maustaste ToolBox ausloesen und wenn wir uns nicht
+ // noch in der normalen Bearbeitung befinden
+ if ( rMEvt.IsLeft() && !mbDrag && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
+ {
+ // Activate schon hier rufen, da gegebenenfalls noch Items
+ // ausgetauscht werden
+ Activate();
+
+ // ToolBox hier updaten, damit der Anwender weiss, was Sache ist
+ if ( mbFormat )
+ {
+ ImplFormat();
+ Update();
+ }
+
+ Point aMousePos = rMEvt.GetPosPixel();
+ USHORT i = 0;
+ USHORT nNewPos = TOOLBOX_ITEM_NOTFOUND;
+
+ // Item suchen, das geklickt wurde
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ // Ist es dieses Item
+ if ( it->maRect.IsInside( aMousePos ) )
+ {
+ // Ist es ein Separator oder ist das Item disabled,
+ // dann mache nichts
+ if ( (it->meType == TOOLBOXITEM_BUTTON) &&
+ (!it->mbShowWindow || mbCustomizeMode) )
+ nNewPos = i;
+
+ break;
+ }
+
+ i++;
+ ++it;
+ }
+
+ // Item gefunden
+ if ( nNewPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ if ( mbCustomize )
+ {
+ if ( rMEvt.IsMod2() || mbCustomizeMode )
+ {
+ Deactivate();
+
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ Rectangle aItemRect = GetItemRect( it->mnId );
+ mnConfigItem = it->mnId;
+
+ BOOL bResizeItem;
+ if ( mbCustomizeMode && it->mbShowWindow &&
+ (it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X()) )
+ bResizeItem = TRUE;
+ else
+ bResizeItem = FALSE;
+ pMgr->StartDragging( this, aMousePos, aItemRect, 0, bResizeItem );
+ return;
+ }
+ }
+
+ if ( !it->mbEnabled )
+ {
+ Deactivate();
+ return;
+ }
+
+
+ // Aktuelle Daten setzen
+ USHORT nTrackFlags = 0;
+ mnCurPos = i;
+ mnCurItemId = it->mnId;
+ mnDownItemId = mnCurItemId;
+ mnMouseClicks = rMEvt.GetClicks();
+ mnMouseModifier = rMEvt.GetModifier();
+ if ( it->mnBits & TIB_REPEAT )
+ nTrackFlags |= STARTTRACK_BUTTONREPEAT;
+
+
+ if ( mbSelection )
+ {
+ ImplDrawItem( mnCurPos, TRUE );
+ Highlight();
+ }
+ else
+ {
+ // Hier schon bDrag setzen, da in EndSelection ausgewertet wird
+ mbDrag = TRUE;
+
+ // Bei Doppelklick nur den Handler rufen, aber bevor der
+ // Button gehiltet wird, da evt. in diesem Handler der
+ // Drag-Vorgang abgebrochen wird
+ if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+
+
+ if ( mbDrag )
+ {
+ ImplDrawItem( mnCurPos, TRUE );
+ Highlight();
+ }
+
+ // was dropdown arrow pressed
+ if( (it->mnBits & TIB_DROPDOWN) )
+ {
+ if( ( (it->mnBits & TIB_DROPDOWNONLY) == TIB_DROPDOWNONLY) || it->GetDropDownRect( mbHorz ).IsInside( aMousePos ))
+ {
+ // dropdownonly always triggers the dropdown handler, over the whole button area
+
+ // the drop down arrow should not trigger the item action
+ mpData->mbDropDownByKeyboard = FALSE;
+ GetDropdownClickHdl().Call( this );
+
+ // do not reset data if the dropdown handler opened a floating window
+ // see ImplFloatControl()
+ if( mpFloatWin == NULL )
+ {
+ // no floater was opened
+ Deactivate();
+ ImplDrawItem( mnCurPos, FALSE );
+
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+ mnHighItemId = 0;
+ }
+ return;
+ }
+ else // activate long click timer
+ mpData->maDropdownTimer.Start();
+ }
+
+
+ // Click-Handler aufrufen
+ if ( rMEvt.GetClicks() != 2 )
+ Click();
+
+ // Bei Repeat auch den Select-Handler rufen
+ if ( nTrackFlags & STARTTRACK_BUTTONREPEAT )
+ Select();
+
+ // Wenn die Aktion nicht im Click-Handler abgebrochen wurde
+ if ( mbDrag )
+ StartTracking( nTrackFlags );
+ }
+
+ // Wenn Maus ueber einem Item gedrueckt wurde, koennen wir
+ // die Bearbeitung abbrechen
+ return;
+ }
+
+ Deactivate();
+
+ // menu button hit ?
+ if( mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) )
+ {
+ ExecuteCustomMenu();
+ return;
+ }
+
+
+ // Gegebenenfalls noch Scroll- und Next-Buttons ueberpruefen
+ if ( maUpperRect.IsInside( aMousePos ) )
+ {
+ if ( mnCurLine > 1 )
+ {
+ StartTracking();
+ mbUpper = TRUE;
+ mbIn = TRUE;
+ ImplDrawSpin( TRUE, FALSE );
+ }
+ return;
+ }
+ if ( maLowerRect.IsInside( aMousePos ) )
+ {
+ if ( mnCurLine+mnVisLines-1 < mnCurLines )
+ {
+ StartTracking();
+ mbLower = TRUE;
+ mbIn = TRUE;
+ ImplDrawSpin( FALSE, TRUE );
+ }
+ return;
+ }
+ if ( maNextToolRect.IsInside( aMousePos ) )
+ {
+ StartTracking();
+ mbNextTool = TRUE;
+ mbIn = TRUE;
+ ImplDrawNext( TRUE );
+ return;
+ }
+
+ // Linesizing testen
+ if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
+ {
+ USHORT nLineMode = ImplTestLineSize( this, aMousePos );
+ if ( nLineMode )
+ {
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+
+ // Handler rufen, damit die Dock-Rectangles gesetzt werden
+ // koenen
+ StartDocking();
+
+ Point aPos = GetParent()->OutputToScreenPixel( GetPosPixel() );
+ Size aSize = GetSizePixel();
+ aPos = ScreenToOutputPixel( aPos );
+
+ // Dragging starten
+ pMgr->StartDragging( this, aMousePos, Rectangle( aPos, aSize ),
+ nLineMode, FALSE );
+ return;
+ }
+ }
+
+ // Kein Item, dann nur Click oder DoubleClick
+ if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+ else
+ Click();
+ }
+
+ if ( !mbDrag && !mbSelection && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
+ DockingWindow::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if ( ImplHandleMouseButtonUp( rMEvt ) )
+ return;
+
+ if ( mbDragging && (rMEvt.IsLeft() || mbCommandDrag) )
+ {
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ pMgr->EndDragging();
+ return;
+ }
+ mbCommandDrag = FALSE;
+
+ DockingWindow::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Tracking( const TrackingEvent& rTEvt )
+{
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+
+ if ( rTEvt.IsTrackingEnded() )
+ ImplHandleMouseButtonUp( rTEvt.GetMouseEvent(), rTEvt.IsTrackingCanceled() );
+ else
+ ImplHandleMouseMove( rTEvt.GetMouseEvent(), rTEvt.IsTrackingRepeat() );
+
+ if ( aDelData.IsDelete() )
+ // toolbox was deleted
+ return;
+ ImplRemoveDel( &aDelData );
+ DockingWindow::Tracking( rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Paint( const Rectangle& rPaintRect )
+{
+ if( mpData->mbIsPaintLocked )
+ return;
+ if ( rPaintRect == Rectangle( 0, 0, mnDX-1, mnDY-1 ) )
+ mbFullPaint = TRUE;
+ ImplFormat();
+ mbFullPaint = FALSE;
+
+
+ ImplDrawBackground( this, rPaintRect );
+
+ if ( (mnWinStyle & WB_BORDER) && !ImplIsFloatingMode() )
+ ImplDrawBorder( this );
+
+ if( !ImplIsFloatingMode() )
+ ImplDrawGrip( this );
+
+ ImplDrawMenubutton( this, mpData->mbMenubuttonSelected );
+
+ // SpinButtons zeichnen
+ if ( mnWinStyle & WB_SCROLL )
+ {
+ if ( mnCurLines > mnLines )
+ ImplDrawSpin( FALSE, FALSE );
+ }
+
+ // NextButton zeichnen
+ ImplDrawNext( FALSE );
+
+ // Buttons zeichnen
+ USHORT nHighPos;
+ if ( mnHighItemId )
+ nHighPos = GetItemPos( mnHighItemId );
+ else
+ nHighPos = TOOLBOX_ITEM_NOTFOUND;
+
+ USHORT nCount = (USHORT)mpData->m_aItems.size();
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[i];
+
+ // Nur malen, wenn Rechteck im PaintRectangle liegt
+ if ( !pItem->maRect.IsEmpty() && rPaintRect.IsOver( pItem->maRect ) )
+ {
+ BOOL bHighlight = FALSE;
+ if ( i == mnCurPos )
+ bHighlight = 1;
+ else if ( i == nHighPos )
+ bHighlight = 2;
+ ImplDrawItem( i, bHighlight );
+ }
+ }
+ ImplShowFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Move()
+{
+ DockingWindow::Move();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Resize()
+{
+ Size aSize = GetOutputSizePixel();
+ // #i31422# some WindowManagers send (0,0) sizes when
+ // switching virtual desktops - ignore this and avoid reformatting
+ if( !aSize.Width() && !aSize.Height() )
+ return;
+
+ long nOldDX = mnDX;
+ long nOldDY = mnDY;
+ mnDX = aSize.Width();
+ mnDY = aSize.Height();
+
+ mnLastResizeDY = 0;
+
+ // invalidate everything to have gradient backgrounds properly drawn
+ Invalidate();
+
+ // Evt. neu formatieren oder neu painten
+ if ( mbScroll )
+ {
+ if ( !mbFormat )
+ {
+ mbFormat = TRUE;
+ if( IsReallyVisible() )
+ ImplFormat( TRUE );
+ }
+ }
+
+ // Border muss neu ausgegeben werden
+ if ( mnWinStyle & WB_BORDER )
+ {
+ // Da wir sonst beim Paint denken, das alles neu gepaintet wird
+ if ( mbFormat && IsReallyVisible() )
+ Invalidate();
+ else
+ {
+ if ( mnRightBorder )
+ {
+ if ( nOldDX > mnDX )
+ Invalidate( Rectangle( mnDX-mnRightBorder-1, 0, mnDX, mnDY ) );
+ else
+ Invalidate( Rectangle( nOldDX-mnRightBorder-1, 0, nOldDX, nOldDY ) );
+ }
+
+ if ( mnBottomBorder )
+ {
+ if ( nOldDY > mnDY )
+ Invalidate( Rectangle( 0, mnDY-mnBottomBorder-1, mnDX, mnDY ) );
+ else
+ Invalidate( Rectangle( 0, nOldDY-mnBottomBorder-1, nOldDX, nOldDY ) );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+const XubString& ToolBox::ImplGetHelpText( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ {
+ if ( !pItem->maHelpText.Len() && ( pItem->mnHelpId || pItem->maCommandStr.Len() ))
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ if ( pItem->maCommandStr.Len() )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->maCommandStr, this );
+ if ( !pItem->maHelpText.Len() && pItem->mnHelpId )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId, this );
+ }
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT nItemId;
+ Point aHelpPos;
+
+ if( !rHEvt.KeyboardActivated() )
+ {
+ nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+ aHelpPos = rHEvt.GetMousePosPixel();
+ }
+ else
+ {
+ if( !mnHighItemId )
+ return;
+ else
+ nItemId = mnHighItemId;
+ Rectangle aRect( GetItemRect( nItemId ) );
+ if( aRect.IsEmpty() )
+ return;
+ else
+ aHelpPos = OutputToScreenPixel( aRect.Center() );
+ }
+
+ if ( nItemId )
+ {
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
+ {
+ // Rechteck ermitteln
+ Rectangle aTempRect = GetItemRect( nItemId );
+ Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
+ aTempRect.Left() = aPt.X();
+ aTempRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aTempRect.BottomRight() );
+ aTempRect.Right() = aPt.X();
+ aTempRect.Bottom() = aPt.Y();
+
+ // Text ermitteln und anzeigen
+ XubString aStr = GetQuickHelpText( nItemId );
+ const XubString& rHelpStr = GetHelpText( nItemId );
+ if ( !aStr.Len() )
+ aStr = MnemonicGenerator::EraseAllMnemonicChars( GetItemText( nItemId ) );
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ if ( rHelpStr.Len() )
+ aStr = rHelpStr;
+ Help::ShowBalloon( this, aHelpPos, aTempRect, aStr );
+ }
+ else
+ Help::ShowQuickHelp( this, aTempRect, aStr, rHelpStr, QUICKHELP_CTRLTEXT );
+ return;
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
+ {
+ String aCommand = GetItemCommand( nItemId );
+ ULONG nHelpId = GetHelpId( nItemId );
+
+ if ( aCommand.Len() || nHelpId )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ if ( aCommand.Len() )
+ pHelp->Start( aCommand, this );
+ else if ( nHelpId )
+ pHelp->Start( nHelpId, this );
+ }
+ return;
+ }
+ }
+ }
+ else if ( maNextToolRect.IsInside( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ) )
+ {
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
+ {
+ // Rechteck ermitteln
+ Rectangle aTempRect = maNextToolRect;
+ Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
+ aTempRect.Left() = aPt.X();
+ aTempRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aTempRect.BottomRight() );
+ aTempRect.Right() = aPt.X();
+ aTempRect.Bottom() = aPt.Y();
+
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aTempRect.Center(), aTempRect, maNextToolBoxStr );
+ else
+ Help::ShowQuickHelp( this, aTempRect, maNextToolBoxStr );
+ return;
+ }
+ }
+
+ DockingWindow::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long ToolBox::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ KeyEvent aKEvt = *rNEvt.GetKeyEvent();
+ KeyCode aKeyCode = aKEvt.GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+ switch( nKeyCode )
+ {
+ case KEY_TAB:
+ {
+ // internal TAB cycling only if parent is not a dialog or if we are the ony child
+ // otherwise the dialog control will take over
+ BOOL bNoTabCycling = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL &&
+ ImplGetParent()->GetChildCount() != 1 );
+
+ if( bNoTabCycling && ! (GetStyle() & WB_FORCETABCYCLE) )
+ return DockingWindow::Notify( rNEvt );
+ else if( ImplChangeHighlightUpDn( aKeyCode.IsShift() ? TRUE : FALSE , bNoTabCycling ) )
+ return FALSE;
+ else
+ return DockingWindow::Notify( rNEvt );
+ }
+ default:
+ break;
+ };
+ }
+ else if( rNEvt.GetType() == EVENT_GETFOCUS )
+ {
+ if( rNEvt.GetWindow() == this )
+ {
+ // the toolbar itself got the focus
+ if( mnLastFocusItemId != 0 )
+ {
+ // restore last item
+ ImplChangeHighlight( ImplGetItem( mnLastFocusItemId ) );
+ mnLastFocusItemId = 0;
+ }
+ else if( (GetGetFocusFlags() & (GETFOCUS_BACKWARD|GETFOCUS_TAB) ) == (GETFOCUS_BACKWARD|GETFOCUS_TAB))
+ // Shift-TAB was pressed in the parent
+ ImplChangeHighlightUpDn( FALSE );
+ else
+ ImplChangeHighlightUpDn( TRUE );
+
+ mnLastFocusItemId = 0;
+
+ return true;
+ }
+ else
+ {
+ // a child window got the focus so update current item to
+ // allow for proper lose focus handling in keyboard navigation
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while( it != mpData->m_aItems.end() )
+ {
+ if ( it->mbVisible )
+ {
+ if ( it->mpWindow && it->mpWindow->ImplIsWindowOrChild( rNEvt.GetWindow() ) )
+ {
+ mnHighItemId = it->mnId;
+ break;
+ }
+ }
+
+ ++it;
+ }
+ return DockingWindow::Notify( rNEvt );
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ // deselect
+ ImplHideFocus();
+ mnHighItemId = 0;
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ }
+
+ return DockingWindow::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Command( const CommandEvent& rCEvt )
+{
+ // StartDrag auf MouseButton/Left/Alt abbilden
+ if ( (rCEvt.GetCommand() == COMMAND_STARTDRAG) && rCEvt.IsMouseEvent() &&
+ mbCustomize && !mbDragging && !mbDrag && !mbSelection &&
+ (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
+ {
+ // Wir erlauben nur das Draggen von Items. Deshalb muessen wir
+ // testen, ob auch ein Item angeklickt wurde, ansonsten wuerden
+ // wir evt. das Fenster verschieben, was nicht gewollt waere.
+ // Wir machen dieses jedoch nur im Customize-Mode, da ansonsten
+ // Items zuhaeufig ausversehen verschoben werden.
+ if ( mbCustomizeMode )
+ {
+ Point aMousePos = rCEvt.GetMousePosPixel();
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ // Ist es dieses Item
+ if ( it->maRect.IsInside( aMousePos ) )
+ {
+ // Ist es ein Separator oder ist das Item disabled,
+ // dann mache nichts
+ if ( (it->meType == TOOLBOXITEM_BUTTON) &&
+ !it->mbShowWindow )
+ mbCommandDrag = TRUE;
+ break;
+ }
+
+ ++it;
+ }
+
+ if ( mbCommandDrag )
+ {
+ MouseEvent aMEvt( aMousePos, 1, MOUSE_SIMPLECLICK,
+ MOUSE_LEFT, KEY_MOD2 );
+ ToolBox::MouseButtonDown( aMEvt );
+ return;
+ }
+ }
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ if ( (mnCurLine > 1) || (mnCurLine+mnVisLines-1 < mnCurLines) )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
+ {
+ if ( (mnCurLine > 1) && (pData->GetDelta() > 0) )
+ ShowLine( FALSE );
+ else if ( (mnCurLine+mnVisLines-1 < mnCurLines) && (pData->GetDelta() < 0) )
+ ShowLine( TRUE );
+ ImplDrawSpin( FALSE, FALSE );
+ return;
+ }
+ }
+ }
+
+ DockingWindow::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StateChanged( StateChangedType nType )
+{
+ DockingWindow::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplFormat();
+ else if ( nType == STATE_CHANGE_ENABLE )
+ ImplUpdateItem();
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ mbCalc = TRUE;
+ mbFormat = TRUE;
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE ); // font, foreground, background
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ DockingWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ mbCalc = TRUE;
+ mbFormat = TRUE;
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::PrepareToggleFloatingMode()
+{
+ return DockingWindow::PrepareToggleFloatingMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ToggleFloatingMode()
+{
+ DockingWindow::ToggleFloatingMode();
+
+ BOOL mbOldHorz = mbHorz;
+
+ if ( ImplIsFloatingMode() )
+ {
+ mbHorz = TRUE;
+ meAlign = WINDOWALIGN_TOP;
+ mbScroll = TRUE;
+
+ if( mbOldHorz != mbHorz )
+ mbCalc = TRUE; // orientation was changed !
+
+ ImplSetMinMaxFloatSize( this );
+ SetOutputSizePixel( ImplCalcFloatSize( this, mnFloatLines ) );
+ }
+ else
+ {
+ mbScroll = (mnWinStyle & WB_SCROLL) ? TRUE : FALSE;
+ if ( (meAlign == WINDOWALIGN_TOP) || (meAlign == WINDOWALIGN_BOTTOM) )
+ mbHorz = TRUE;
+ else
+ mbHorz = FALSE;
+
+ // set focus back to document
+ ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
+ }
+
+ if( mbOldHorz != mbHorz )
+ {
+ // if orientation changes, the toolbox has to be initialized again
+ // to update the direction of the gradient
+ mbCalc = TRUE;
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ }
+
+ mbFormat = TRUE;
+ ImplFormat();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StartDocking()
+{
+ meDockAlign = meAlign;
+ mnDockLines = mnLines;
+ mbLastFloatMode = ImplIsFloatingMode();
+ DockingWindow::StartDocking();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::Docking( const Point& rPos, Rectangle& rRect )
+{
+ // Wenn Dragging, dann nicht machen, da vorher schon berechnet
+ if ( mbDragging )
+ return FALSE;
+
+ BOOL bFloatMode = FALSE;
+
+ DockingWindow::Docking( rPos, rRect );
+
+ // Befindet sich die Maus ausserhalb des Bereichs befindet, kann es nur ein
+ // FloatWindow werden
+ Rectangle aDockingRect( rRect );
+ if ( !ImplIsFloatingMode() )
+ {
+ // don't use tracking rectangle for alignment check, because it will be too large
+ // to get a floating mode as result - switch to floating size
+ // so the calculation only depends on the position of the rectangle, not the current
+ // docking state of the window
+ USHORT nTemp = 0;
+ aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
+
+ // in this mode docking is never done by keyboard, so it's OK to use the mouse position
+ aDockingRect.SetPos( ImplGetFrameWindow()->GetPointerPosPixel() );
+ }
+
+ Rectangle aIntersection = maOutDockRect.GetIntersection( aDockingRect );
+ if ( !aIntersection.IsEmpty() && !IsDockingPrevented() )
+ {
+ Rectangle aInRect = maInDockRect;
+ Size aDockSize;
+ aDockSize.Width() = ImplCalcSize( this, mnLines, TB_CALCMODE_VERT ).Width();
+ aDockSize.Height() = ImplCalcSize( this, mnLines, TB_CALCMODE_HORZ ).Height();
+ aInRect.Left() += aDockSize.Width()/2;
+ aInRect.Top() += aDockSize.Height()/2;
+ aInRect.Right() -= aDockSize.Width()/2;
+ aInRect.Bottom() -= aDockSize.Height()/2;
+
+ // Wenn Fenster zu klein, wird das gesammte InDock-Rect genommen
+ if ( aInRect.Left() >= aInRect.Right() )
+ {
+ aInRect.Left() = maInDockRect.Left();
+ aInRect.Right() = maInDockRect.Right();
+ }
+ if ( aInRect.Top() >= aInRect.Bottom() )
+ {
+ aInRect.Top() = maInDockRect.Top();
+ aInRect.Bottom() = maInDockRect.Bottom();
+ }
+
+ // Wenn Maus nicht im Dock-Bereich, dann kann es nur zum
+ // FloatWindow werden
+ Rectangle aIntersect = aInRect.GetIntersection( aDockingRect );
+ if ( aIntersect == aDockingRect )
+ bFloatMode = TRUE;
+ else
+ {
+ // docking rectangle is in the "sensible area"
+ Point aPos = aDockingRect.TopLeft();
+ Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() );
+ Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() );
+ Size aInSize = aInRect.GetSize();
+
+ if ( aInPosTL.X() <= 0 )
+ meDockAlign = WINDOWALIGN_LEFT;
+ else if ( aInPosTL.Y() <= 0)
+ meDockAlign = WINDOWALIGN_TOP;
+ else if ( aInPosBR.X() >= aInSize.Width() )
+ meDockAlign = WINDOWALIGN_RIGHT;
+ else if ( aInPosBR.Y() >= aInSize.Height() )
+ meDockAlign = WINDOWALIGN_BOTTOM;
+
+ // Wenn sich Dock-Align geaendert hat, muessen wir die
+ // neue Dock-Groesse setzen
+ if ( (meDockAlign == WINDOWALIGN_TOP) || (meDockAlign == WINDOWALIGN_BOTTOM) )
+ aDockSize.Width() = maInDockRect.GetWidth();
+ else
+ aDockSize.Height() = maInDockRect.GetHeight();
+
+ aDockingRect.SetSize( aDockSize );
+
+ Point aPosTL( maInDockRect.TopLeft() );
+ switch ( meDockAlign )
+ {
+ case WINDOWALIGN_TOP :
+ aDockingRect.SetPos( aPosTL );
+ break;
+ case WINDOWALIGN_LEFT :
+ aDockingRect.SetPos( aPosTL );
+ break;
+ case WINDOWALIGN_BOTTOM :
+ {
+ Point aPosBL( maInDockRect.BottomLeft() );
+ aPosBL.Y() -= aDockingRect.GetHeight();
+ aDockingRect.SetPos( aPosBL );
+ break;
+ }
+ case WINDOWALIGN_RIGHT :
+ {
+ Point aPosTR( maInDockRect.TopRight() );
+ aPosTR.X() -= aDockingRect.GetWidth();
+ aDockingRect.SetPos( aPosTR );
+ break;
+ }
+ }
+ }
+ }
+ else
+ bFloatMode = TRUE;
+
+ if ( bFloatMode )
+ {
+ meDockAlign = meAlign;
+ if ( !mbLastFloatMode )
+ {
+ USHORT nTemp = 0;
+ aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
+ }
+ }
+
+ rRect = aDockingRect;
+ mbLastFloatMode = bFloatMode;
+
+ return bFloatMode;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EndDocking( const Rectangle& rRect, BOOL bFloatMode )
+{
+ if ( !IsDockingCanceled() )
+ {
+ if ( mnLines != mnDockLines )
+ SetLineCount( mnDockLines );
+ if ( meAlign != meDockAlign )
+ SetAlign( meDockAlign );
+ }
+ if ( bFloatMode || (bFloatMode != ImplIsFloatingMode()) )
+ DockingWindow::EndDocking( rRect, bFloatMode );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Resizing( Size& rSize )
+{
+ USHORT nCalcLines;
+ USHORT nTemp;
+
+ // Alle Floatinggroessen berechnen
+ ImplCalcFloatSizes( this );
+
+ if ( !mnLastResizeDY )
+ mnLastResizeDY = mnDY;
+
+ // Ist vertikales Resizing angesagt
+ if ( (mnLastResizeDY != rSize.Height()) && (mnDY != rSize.Height()) )
+ {
+ nCalcLines = ImplCalcLines( this, rSize.Height() );
+ if ( nCalcLines < 1 )
+ nCalcLines = 1;
+ rSize = ImplCalcFloatSize( this, nCalcLines );
+ }
+ else
+ {
+ nCalcLines = 1;
+ nTemp = nCalcLines;
+ Size aTempSize = ImplCalcFloatSize( this, nTemp );
+ while ( (aTempSize.Width() > rSize.Width()) &&
+ (nCalcLines <= mpFloatSizeAry->mpSize[0].mnLines) )
+ {
+ nCalcLines++;
+ nTemp = nCalcLines;
+ aTempSize = ImplCalcFloatSize( this, nTemp );
+ }
+ rSize = aTempSize;
+ }
+
+ mnLastResizeDY = rSize.Height();
+}
+
+// -----------------------------------------------------------------------
+
+Size ToolBox::CalcWindowSizePixel( USHORT nCalcLines ) const
+{
+ return ImplCalcSize( this, nCalcLines );
+}
+
+Size ToolBox::CalcWindowSizePixel( USHORT nCalcLines, WindowAlign eAlign ) const
+{
+ return ImplCalcSize( this, nCalcLines,
+ (eAlign == WINDOWALIGN_TOP || eAlign == WINDOWALIGN_BOTTOM) ? TB_CALCMODE_HORZ : TB_CALCMODE_VERT );
+}
+
+USHORT ToolBox::ImplCountLineBreaks( const ToolBox *pThis )
+{
+ USHORT nLines = 0;
+
+ std::vector< ImplToolItem >::const_iterator it = ((ToolBox*)pThis)->mpData->m_aItems.begin();
+ while ( it != ((ToolBox*)pThis)->mpData->m_aItems.end() )
+ {
+ if( it->meType == TOOLBOXITEM_BREAK )
+ nLines++;
+ it++;
+ }
+ return nLines;
+}
+
+Size ToolBox::CalcPopupWindowSizePixel() const
+{
+ // count number of breaks and calc corresponding floating window size
+ USHORT nLines = ImplCountLineBreaks( this );
+
+ if( nLines )
+ nLines++; // add the first line
+ else
+ {
+ // no breaks found: use quadratic layout
+ nLines = (USHORT) ceil( sqrt( (double) GetItemCount() ) );
+ }
+
+ BOOL bPopup = mpData->mbAssumePopupMode;
+ ToolBox *pThis = (ToolBox*) this;
+ pThis->mpData->mbAssumePopupMode = TRUE;
+
+ Size aSize = CalcFloatingWindowSizePixel( nLines );
+
+ pThis->mpData->mbAssumePopupMode = bPopup;
+ return aSize;
+}
+
+Size ToolBox::CalcFloatingWindowSizePixel() const
+{
+ USHORT nLines = ImplCountLineBreaks( this );
+ nLines++; // add the first line
+ return CalcFloatingWindowSizePixel( nLines );
+}
+
+Size ToolBox::CalcFloatingWindowSizePixel( USHORT nCalcLines ) const
+{
+ BOOL bFloat = mpData->mbAssumeFloating;
+ BOOL bDocking = mpData->mbAssumeDocked;
+
+ // simulate floating mode and force reformat before calculating
+ ToolBox *pThis = (ToolBox*) this;
+ pThis->mpData->mbAssumeFloating = TRUE;
+ pThis->mpData->mbAssumeDocked = FALSE;
+
+ Size aSize = ImplCalcFloatSize( (ToolBox*) this, nCalcLines );
+
+ pThis->mbFormat = TRUE;
+ pThis->mpData->mbAssumeFloating = bFloat;
+ pThis->mpData->mbAssumeDocked = bDocking;
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+Size ToolBox::CalcMinimumWindowSizePixel() const
+{
+ if( ImplIsFloatingMode() )
+ return ImplCalcSize( this, mnFloatLines );
+ else
+ {
+ // create dummy toolbox for measurements
+ ToolBox *pToolBox = new ToolBox( GetParent(), GetStyle() );
+
+ // copy until first useful item
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ while( it != mpData->m_aItems.end() )
+ {
+ pToolBox->CopyItem( *this, it->mnId );
+ if( (it->meType != TOOLBOXITEM_BUTTON) ||
+ !it->mbVisible || ImplIsFixedControl( &(*it) ) )
+ it++;
+ else
+ break;
+ }
+
+ // add to docking manager if required to obtain a drag area
+ // (which is accounted for in calcwindowsizepixel)
+ if( ImplGetDockingManager()->GetDockingWindowWrapper( this ) )
+ ImplGetDockingManager()->AddWindow( pToolBox );
+
+ // account for menu
+ if( IsMenuEnabled() )
+ pToolBox->SetMenuType( GetMenuType() );
+
+ pToolBox->SetAlign( GetAlign() );
+ Size aSize = pToolBox->CalcWindowSizePixel( 1 );
+
+ ImplGetDockingManager()->RemoveWindow( pToolBox );
+ pToolBox->Clear();
+ delete pToolBox;
+
+ return aSize;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EnableCustomize( BOOL bEnable )
+{
+ if ( bEnable != mbCustomize )
+ {
+ mbCustomize = bEnable;
+
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ if ( bEnable )
+ pMgr->Insert( this );
+ else
+ pMgr->Remove( this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StartCustomize( const Rectangle& rRect, void* pData )
+{
+ DBG_ASSERT( mbCustomize,
+ "ToolBox::StartCustomize(): ToolBox must be customized" );
+
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ Point aMousePos = GetPointerPosPixel();
+ Point aPos = ScreenToOutputPixel( rRect.TopLeft() );
+ Rectangle aRect( aPos.X(), aPos.Y(),
+ aPos.X()+rRect.GetWidth()+SMALLBUTTON_HSIZE,
+ aPos.Y()+rRect.GetHeight()+SMALLBUTTON_VSIZE );
+ aMousePos = ScreenToOutputPixel( aPos );
+ Pointer aPtr;
+ SetPointer( aPtr );
+ pMgr->StartDragging( this, aMousePos, aRect, 0, FALSE, pData );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StartCustomizeMode()
+{
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ pMgr->StartCustomizeMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EndCustomizeMode()
+{
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ pMgr->EndCustomizeMode();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsCustomizeMode()
+{
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ return pMgr->IsCustomizeMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::GetFocus()
+{
+ DockingWindow::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::LoseFocus()
+{
+ ImplChangeHighlight( NULL, TRUE );
+
+ DockingWindow::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+// performs the action associated with an item, ie simulates clicking the item
+void ToolBox::TriggerItem( USHORT nItemId, BOOL bShift, BOOL bCtrl )
+{
+ mnHighItemId = nItemId;
+ USHORT nModifier = 0;
+ if( bShift )
+ nModifier |= KEY_SHIFT;
+ if( bCtrl )
+ nModifier |= KEY_MOD1;
+ KeyCode aKeyCode( 0, nModifier );
+ ImplActivateItem( aKeyCode );
+}
+
+// -----------------------------------------------------------------------
+
+// calls the button's action handler
+// returns TRUE if action was called
+BOOL ToolBox::ImplActivateItem( KeyCode aKeyCode )
+{
+ BOOL bRet = TRUE;
+ if( mnHighItemId )
+ {
+ ImplToolItem *pToolItem = ImplGetItem( mnHighItemId );
+
+ // #107712#, activate can also be called for disabled entries
+ if( pToolItem && !pToolItem->mbEnabled )
+ return TRUE;
+
+ if( pToolItem && pToolItem->mpWindow && HasFocus() )
+ {
+ ImplHideFocus();
+ mbChangingHighlight = TRUE; // avoid focus change due to loose focus
+ pToolItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
+ mbChangingHighlight = FALSE;
+ }
+ else
+ {
+ mnDownItemId = mnCurItemId = mnHighItemId;
+ ImplToolItem* pItem = ImplGetItem( mnHighItemId );
+ if ( pItem->mnBits & TIB_AUTOCHECK )
+ {
+ if ( pItem->mnBits & TIB_RADIOCHECK )
+ {
+ if ( pItem->meState != STATE_CHECK )
+ SetItemState( pItem->mnId, STATE_CHECK );
+ }
+ else
+ {
+ if ( pItem->meState != STATE_CHECK )
+ pItem->meState = STATE_CHECK;
+ else
+ pItem->meState = STATE_NOCHECK;
+ }
+ }
+ mnMouseModifier = aKeyCode.GetModifier();
+ mbIsKeyEvent = TRUE;
+ Activate();
+ Click();
+
+ // #107776# we might be destroyed in the selecthandler
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ Select();
+ if ( aDelData.IsDelete() )
+ return bRet;
+ ImplRemoveDel( &aDelData );
+
+ Deactivate();
+ mbIsKeyEvent = FALSE;
+ mnMouseModifier = 0;
+ }
+ }
+ else
+ bRet = FALSE;
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplCloseLastPopup( Window *pParent )
+{
+ // close last popup toolbox (see also:
+ // ImplHandleMouseFloatMode(...) in winproc.cxx )
+
+ if( ImplGetSVData()->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat = ImplGetSVData()->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ // only close the floater if it is not our direct parent, which would kill ourself
+ if( pLastLevelFloat && pLastLevelFloat != pParent )
+ {
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+// opens a drop down toolbox item
+// returns TRUE if item was opened
+BOOL ToolBox::ImplOpenItem( KeyCode aKeyCode )
+{
+ USHORT nCode = aKeyCode.GetCode();
+ BOOL bRet = TRUE;
+
+ // arrow keys should work only in the opposite direction of alignment (to not break cursor travelling)
+ if ( ((nCode == KEY_LEFT || nCode == KEY_RIGHT) && IsHorizontal())
+ || ((nCode == KEY_UP || nCode == KEY_DOWN) && !IsHorizontal()) )
+ return FALSE;
+
+ if( IsMenuEnabled() && mpData->mbMenubuttonSelected )
+ {
+ if( ImplCloseLastPopup( GetParent() ) )
+ return bRet;
+
+ ImplUpdateCustomMenu();
+ Application::PostUserEvent( mpData->mnEventId, LINK( this, ToolBox, ImplCallExecuteCustomMenu ) );
+ }
+ else if( mnHighItemId && ImplGetItem( mnHighItemId ) &&
+ (ImplGetItem( mnHighItemId )->mnBits & TIB_DROPDOWN) )
+ {
+ if( ImplCloseLastPopup( GetParent() ) )
+ return bRet;
+
+ mnDownItemId = mnCurItemId = mnHighItemId;
+ mnCurPos = GetItemPos( mnCurItemId );
+ mnLastFocusItemId = mnCurItemId; // save item id for possible later focus restore
+ mnMouseModifier = aKeyCode.GetModifier();
+ mbIsShift = TRUE;
+ mbIsKeyEvent = TRUE;
+ Activate();
+
+ mpData->mbDropDownByKeyboard = TRUE;
+ GetDropdownClickHdl().Call( this );
+
+ mbIsKeyEvent = FALSE;
+ mbIsShift = FALSE;
+ mnMouseModifier = 0;
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::KeyInput( const KeyEvent& rKEvt )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+ mnKeyModifier = aKeyCode.GetModifier();
+ USHORT nCode = aKeyCode.GetCode();
+ BOOL bParentIsDialog = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL );
+ BOOL bForwardKey = FALSE;
+ BOOL bGrabFocusToDocument = FALSE;
+
+ // #107776# we might be destroyed in the keyhandler
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+
+ switch ( nCode )
+ {
+ case KEY_UP:
+ {
+ // Ctrl-Cursor activates next toolbox, indicated by a blue arrow pointing to the left/up
+ if( aKeyCode.GetModifier() ) // allow only pure cursor keys
+ break;
+ if( !IsHorizontal() )
+ ImplChangeHighlightUpDn( TRUE );
+ else
+ ImplOpenItem( aKeyCode );
+ }
+ break;
+ case KEY_LEFT:
+ {
+ if( aKeyCode.GetModifier() ) // allow only pure cursor keys
+ break;
+ if( IsHorizontal() )
+ ImplChangeHighlightUpDn( TRUE );
+ else
+ ImplOpenItem( aKeyCode );
+ }
+ break;
+ case KEY_DOWN:
+ {
+ if( aKeyCode.GetModifier() ) // allow only pure cursor keys
+ break;
+ if( !IsHorizontal() )
+ ImplChangeHighlightUpDn( FALSE );
+ else
+ ImplOpenItem( aKeyCode );
+ }
+ break;
+ case KEY_RIGHT:
+ {
+ if( aKeyCode.GetModifier() ) // allow only pure cursor keys
+ break;
+ if( IsHorizontal() )
+ ImplChangeHighlightUpDn( FALSE );
+ else
+ ImplOpenItem( aKeyCode );
+ }
+ break;
+ case KEY_PAGEUP:
+ if ( mnCurLine > 1 )
+ {
+ if( mnCurLine > mnVisLines )
+ mnCurLine = mnCurLine - mnVisLines;
+ else
+ mnCurLine = 1;
+ mbFormat = TRUE;
+ ImplFormat();
+ ImplDrawSpin( FALSE, FALSE );
+ ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
+ }
+ break;
+ case KEY_PAGEDOWN:
+ if ( mnCurLine+mnVisLines-1 < mnCurLines )
+ {
+ if( mnCurLine + 2*mnVisLines-1 < mnCurLines )
+ mnCurLine = mnCurLine + mnVisLines;
+ else
+ mnCurLine = mnCurLines;
+ mbFormat = TRUE;
+ ImplFormat();
+ ImplDrawSpin( FALSE, FALSE );
+ ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
+ }
+ break;
+ case KEY_END:
+ {
+ ImplChangeHighlight( NULL );
+ ImplChangeHighlightUpDn( FALSE );
+ }
+ break;
+ case KEY_HOME:
+ {
+ ImplChangeHighlight( NULL );
+ ImplChangeHighlightUpDn( TRUE );
+ }
+ break;
+ case KEY_ESCAPE:
+ {
+ if( !ImplIsFloatingMode() && bParentIsDialog )
+ DockingWindow::KeyInput( rKEvt );
+ else
+ {
+ // send focus to document pane
+ Window *pWin = this;
+ while( pWin )
+ {
+ if( !pWin->GetParent() )
+ {
+ pWin->ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
+ break;
+ }
+ pWin = pWin->GetParent();
+ }
+ }
+ }
+ break;
+ case KEY_RETURN:
+ {
+ // #107712#, disabled entries are selectable now
+ // leave toolbox and move focus to document
+ if( mnHighItemId )
+ {
+ ImplToolItem *pItem = ImplGetItem( mnHighItemId );
+ if( !pItem->mbEnabled )
+ {
+ Sound::Beep( SOUND_DISABLE, this );
+ bGrabFocusToDocument = TRUE;
+ }
+ }
+ if( !bGrabFocusToDocument )
+ bForwardKey = !ImplActivateItem( aKeyCode );
+ }
+ break;
+ default:
+ {
+ USHORT aKeyGroup = aKeyCode.GetGroup();
+ ImplToolItem *pItem = NULL;
+ if( mnHighItemId )
+ pItem = ImplGetItem( mnHighItemId );
+ // #i13931# forward alphanum keyinput into embedded control
+ if( (aKeyGroup == KEYGROUP_NUM || aKeyGroup == KEYGROUP_ALPHA ) && pItem && pItem->mpWindow && pItem->mbEnabled )
+ {
+ Window *pFocusWindow = Application::GetFocusWindow();
+ ImplHideFocus();
+ mbChangingHighlight = TRUE; // avoid focus change due to loose focus
+ pItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
+ mbChangingHighlight = FALSE;
+ if( pFocusWindow != Application::GetFocusWindow() )
+ Application::GetFocusWindow()->KeyInput( rKEvt );
+ }
+ else
+ {
+ // do nothing to avoid key presses going into the document
+ // while the toolbox has the focus
+ // just forward function and special keys and combinations with Alt-key
+ if( aKeyGroup == KEYGROUP_FKEYS || aKeyGroup == KEYGROUP_MISC || aKeyCode.IsMod2() )
+ bForwardKey = TRUE;
+ }
+ }
+ }
+
+ if ( aDelData.IsDelete() )
+ return;
+ ImplRemoveDel( &aDelData );
+
+ // #107251# move focus away if this toolbox was disabled during keyinput
+ if( HasFocus() && mpData->mbKeyInputDisabled && (ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL)
+ {
+ USHORT n = 0;
+ Window *pFocusControl = ImplGetParent()->ImplGetDlgWindow( n, DLGWINDOW_FIRST );
+ if ( pFocusControl && pFocusControl != this )
+ pFocusControl->ImplControlFocus( GETFOCUS_INIT );
+ }
+
+ mnKeyModifier = 0;
+
+ // #107712#, leave toolbox
+ if( bGrabFocusToDocument )
+ {
+ GrabFocusToDocument();
+ return;
+ }
+
+ if( bForwardKey )
+ DockingWindow::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+// returns the current toolbox line of the item
+USHORT ToolBox::ImplGetItemLine( ImplToolItem* pCurrentItem )
+{
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ USHORT nLine = 1;
+ while( it != mpData->m_aItems.end() )
+ {
+ if ( it->mbBreak )
+ nLine++;
+ if( &(*it) == pCurrentItem)
+ break;
+ ++it;
+ }
+ return nLine;
+}
+
+// returns the first displayable item in the given line
+ImplToolItem* ToolBox::ImplGetFirstValidItem( USHORT nLine )
+{
+ if( !nLine || nLine > mnCurLines )
+ return NULL;
+
+ nLine--;
+
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ while( it != mpData->m_aItems.end() )
+ {
+ // find correct line
+ if ( it->mbBreak )
+ nLine--;
+ if( !nLine )
+ {
+ // find first useful item
+ while( it != mpData->m_aItems.end() && ((it->meType != TOOLBOXITEM_BUTTON) ||
+ /*!it->mbEnabled ||*/ !it->mbVisible || ImplIsFixedControl( &(*it) )) )
+ {
+ ++it;
+ if( it == mpData->m_aItems.end() || it->mbBreak )
+ return NULL; // no valid items in this line
+ }
+ return &(*it);
+ }
+ ++it;
+ }
+
+ return (it == mpData->m_aItems.end()) ? NULL : &(*it);
+}
+
+// returns the last displayable item in the given line
+ImplToolItem* ToolBox::ImplGetLastValidItem( USHORT nLine )
+{
+ if( !nLine || nLine > mnCurLines )
+ return NULL;
+
+ nLine--;
+ ImplToolItem *pFound = NULL;
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ while( it != mpData->m_aItems.end() )
+ {
+ // find correct line
+ if ( it->mbBreak )
+ nLine--;
+ if( !nLine )
+ {
+ // find last useful item
+ while( it != mpData->m_aItems.end() && ((it->meType == TOOLBOXITEM_BUTTON) &&
+ /*it->mbEnabled &&*/ it->mbVisible && !ImplIsFixedControl( &(*it) )) )
+ {
+ pFound = &(*it);
+ ++it;
+ if( it == mpData->m_aItems.end() || it->mbBreak )
+ return pFound; // end of line: return last useful item
+ }
+ return pFound;
+ }
+ ++it;
+ }
+
+ return pFound;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::ImplFindItemPos( const ImplToolItem* pItem, const std::vector< ImplToolItem >& rList )
+{
+ if( pItem )
+ {
+ USHORT nPos;
+ for( nPos = 0; nPos < rList.size(); nPos++ )
+ if( &rList[ nPos ] == pItem )
+ return nPos;
+ }
+ return TOOLBOX_ITEM_NOTFOUND;
+}
+
+void ToolBox::ChangeHighlight( USHORT nPos )
+{
+ if ( nPos < GetItemCount() ) {
+ ImplGrabFocus( 0 );
+ ImplChangeHighlight ( ImplGetItem ( GetItemId ( (USHORT) nPos ) ), FALSE );
+ }
+}
+
+void ToolBox::ImplChangeHighlight( ImplToolItem* pItem, BOOL bNoGrabFocus )
+{
+ // avoid recursion due to focus change
+ if( mbChangingHighlight )
+ return;
+
+ mbChangingHighlight = TRUE;
+
+ ImplToolItem* pOldItem = NULL;
+
+ if ( mnHighItemId )
+ {
+ ImplHideFocus();
+ USHORT nPos = GetItemPos( mnHighItemId );
+ pOldItem = ImplGetItem( mnHighItemId );
+ // #i89962# ImplDrawItem can cause Invalidate/Update
+ // which will in turn ImplShowFocus again
+ // set mnHighItemId to 0 already to prevent this hen/egg problem
+ mnHighItemId = 0;
+ ImplDrawItem( nPos, FALSE );
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
+ }
+
+ if( !bNoGrabFocus && pItem != pOldItem && pOldItem && pOldItem->mpWindow )
+ {
+ // move focus into toolbox
+ GrabFocus();
+ }
+
+ if( pItem )
+ {
+ USHORT aPos = ToolBox::ImplFindItemPos( pItem, mpData->m_aItems );
+ if( aPos != TOOLBOX_ITEM_NOTFOUND)
+ {
+ // check for line breaks
+ USHORT nLine = ImplGetItemLine( pItem );
+
+ if( nLine >= mnCurLine + mnVisLines )
+ {
+ mnCurLine = nLine - mnVisLines + 1;
+ mbFormat = TRUE;
+ }
+ else if ( nLine < mnCurLine )
+ {
+ mnCurLine = nLine;
+ mbFormat = TRUE;
+ }
+
+ if( mbFormat )
+ {
+ ImplFormat();
+ }
+
+ mnHighItemId = pItem->mnId;
+ ImplDrawItem( aPos, 2 ); // always use shadow effect (2)
+
+ if( mbSelection )
+ mnCurPos = aPos;
+ ImplShowFocus();
+
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
+ }
+ }
+ else
+ {
+ ImplHideFocus();
+ mnHighItemId = 0;
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ }
+
+ mbChangingHighlight = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+// check for keyboard accessible items
+static BOOL ImplIsValidItem( const ImplToolItem* pItem, BOOL bNotClipped )
+{
+ BOOL bValid = (pItem && pItem->meType == TOOLBOXITEM_BUTTON && pItem->mbVisible && !ImplIsFixedControl( pItem ));
+ if( bValid && bNotClipped && pItem->IsClipped() )
+ bValid = FALSE;
+ return bValid;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::ImplChangeHighlightUpDn( BOOL bUp, BOOL bNoCycle )
+{
+ ImplToolItem* pToolItem = ImplGetItem( mnHighItemId );
+
+ if( !pToolItem || !mnHighItemId )
+ {
+ // menubutton highlighted ?
+ if( mpData->mbMenubuttonSelected )
+ {
+ if( bUp )
+ {
+ // select last valid non-clipped item
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
+ ImplToolItem* pItem = NULL;
+ while( it != mpData->m_aItems.begin() )
+ {
+ --it;
+ if ( ImplIsValidItem( &(*it), TRUE ) )
+ {
+ pItem = &(*it);
+ break;
+ }
+ }
+ ImplDrawMenubutton( this, FALSE );
+ ImplChangeHighlight( pItem );
+ }
+ else
+ {
+ // select first valid non-clipped item
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ while( it != mpData->m_aItems.end() )
+ {
+ if ( ImplIsValidItem( &(*it), TRUE ) )
+ break;
+ ++it;
+ }
+ if( it != mpData->m_aItems.end() )
+ {
+ ImplDrawMenubutton( this, FALSE );
+ ImplChangeHighlight( &(*it) );
+ }
+ }
+ return TRUE;
+ }
+
+ if( bUp )
+ {
+ // Select first valid item
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ while( it != mpData->m_aItems.end() )
+ {
+ if ( ImplIsValidItem( &(*it), FALSE ) )
+ break;
+ ++it;
+ }
+
+ // select the menu button if a clipped item would be selected
+ if( (it != mpData->m_aItems.end() && &(*it) == ImplGetFirstClippedItem( this )) && IsMenuEnabled() )
+ {
+ ImplChangeHighlight( NULL );
+ ImplDrawMenubutton( this, TRUE );
+ }
+ else
+ ImplChangeHighlight( (it != mpData->m_aItems.end()) ? &(*it) : NULL );
+ return TRUE;
+ }
+ else
+ {
+ // Select last valid item
+
+ // docked toolbars have the menubutton as last item - if this button is enabled
+ if( IsMenuEnabled() && !ImplIsFloatingMode() )
+ {
+ ImplChangeHighlight( NULL );
+ ImplDrawMenubutton( this, TRUE );
+ }
+ else
+ {
+ std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
+ ImplToolItem* pItem = NULL;
+ while( it != mpData->m_aItems.begin() )
+ {
+ --it;
+ if ( ImplIsValidItem( &(*it), FALSE ) )
+ {
+ pItem = &(*it);
+ break;
+ }
+ }
+ ImplChangeHighlight( pItem );
+ }
+ return TRUE;
+ }
+ }
+
+ if( pToolItem )
+ {
+ ULONG pos = ToolBox::ImplFindItemPos( pToolItem, mpData->m_aItems );
+ ULONG nCount = mpData->m_aItems.size();
+
+ ULONG i=0;
+ do
+ {
+ if( bUp )
+ {
+ if( !pos-- )
+ {
+ if( bNoCycle )
+ return FALSE;
+
+ // highlight the menu button if it is the last item
+ if( IsMenuEnabled() && !ImplIsFloatingMode() )
+ {
+ ImplChangeHighlight( NULL );
+ ImplDrawMenubutton( this, TRUE );
+ return TRUE;
+ }
+ else
+ pos = nCount-1;
+ }
+ }
+ else
+ {
+ if( ++pos >= nCount )
+ {
+ if( bNoCycle )
+ return FALSE;
+
+ // highlight the menu button if it is the last item
+ if( IsMenuEnabled() && !ImplIsFloatingMode() )
+ {
+ ImplChangeHighlight( NULL );
+ ImplDrawMenubutton( this, TRUE );
+ return TRUE;
+ }
+ else
+ pos = 0;
+ }
+ }
+
+ pToolItem = &mpData->m_aItems[pos];
+
+ if ( ImplIsValidItem( pToolItem, FALSE ) )
+ break;
+
+ } while( ++i < nCount);
+
+ if( pToolItem->IsClipped() && IsMenuEnabled() )
+ {
+ // select the menu button if a clipped item would be selected
+ ImplChangeHighlight( NULL );
+ ImplDrawMenubutton( this, TRUE );
+ }
+ else if( i != nCount )
+ ImplChangeHighlight( pToolItem );
+ else
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplShowFocus()
+{
+ if( mnHighItemId && HasFocus() )
+ {
+ ImplToolItem* pItem = ImplGetItem( mnHighItemId );
+ if( pItem->mpWindow )
+ {
+ Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
+ pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = TRUE;
+ pWin->Invalidate( 0 );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplHideFocus()
+{
+ if( mnHighItemId )
+ {
+ ImplToolItem* pItem = ImplGetItem( mnHighItemId );
+ if( pItem->mpWindow )
+ {
+ Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
+ pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = FALSE;
+ pWin->Invalidate( 0 );
+ }
+ }
+
+ if ( mpData->mbMenubuttonSelected )
+ {
+ // remove highlight from menubutton
+ ImplDrawMenubutton( this, FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDisableFlatButtons()
+{
+#ifdef WNT // Check in the Windows registry if an AT tool wants no flat toolboxes
+ static bool bInit = false, bValue = false;
+ if( ! bInit )
+ {
+ bInit = true;
+ HKEY hkey;
+
+ if( ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER,
+ "Software\\OpenOffice.org\\Accessibility\\AtToolSupport",
+ &hkey) )
+ {
+ DWORD dwType = 0;
+ WIN_BYTE Data[6]; // possible values: "true", "false", "1", "0", DWORD
+ DWORD cbData = sizeof(Data);
+
+ if( ERROR_SUCCESS == RegQueryValueEx(hkey, "DisableFlatToolboxButtons",
+ NULL, &dwType, Data, &cbData) )
+ {
+ switch (dwType)
+ {
+ case REG_SZ:
+ bValue = ((0 == stricmp((const char *) Data, "1")) || (0 == stricmp((const char *) Data, "true")));
+ break;
+ case REG_DWORD:
+ bValue = (bool)(((DWORD *) Data)[0]);
+ break;
+ }
+ }
+ RegCloseKey(hkey);
+ }
+ }
+ if( bValue )
+ mnOutStyle &= ~TOOLBOX_STYLE_FLAT;
+#endif
+}
diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx
new file mode 100644
index 000000000000..334cdd2d0a64
--- /dev/null
+++ b/vcl/source/window/toolbox2.cxx
@@ -0,0 +1,2437 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/help.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/toolbox.h>
+#include <vcl/mnemonic.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/brdwin.hxx>
+
+#include <vcl/unohelp.hxx>
+#include <unotools/confignode.hxx>
+
+#include <vcl/ImageListProvider.hxx>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+using namespace vcl;
+using namespace rtl;
+
+// =======================================================================
+
+#define TB_SEP_SIZE 8
+
+// -----------------------------------------------------------------------
+
+ImplToolBoxPrivateData::ImplToolBoxPrivateData() :
+ m_pLayoutData( NULL ),
+ mpImageListProvider( NULL ),
+ meImageListType( vcl::IMAGELISTTYPE_UNKNOWN )
+{
+ meButtonSize = TOOLBOX_BUTTONSIZE_DONTCARE;
+ mpMenu = new PopupMenu();
+ mnEventId = 0;
+
+ maMenuType = TOOLBOX_MENUTYPE_NONE;
+ maMenubuttonItem.maItemSize = Size( TB_MENUBUTTON_SIZE+TB_MENUBUTTON_OFFSET, TB_MENUBUTTON_SIZE+TB_MENUBUTTON_OFFSET );
+ maMenubuttonItem.meState = STATE_NOCHECK;
+ mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
+
+
+ mbIsLocked = FALSE;
+ mbNativeButtons = FALSE;
+ mbIsPaintLocked = FALSE;
+ mbAssumeDocked = FALSE;
+ mbAssumePopupMode = FALSE;
+ mbAssumeFloating = FALSE;
+ mbKeyInputDisabled = FALSE;
+ mbMenubuttonSelected = FALSE;
+ mbPageScroll = FALSE;
+ mbWillUsePopupMode = FALSE;
+ mbDropDownByKeyboard = FALSE;
+}
+
+ImplToolBoxPrivateData::~ImplToolBoxPrivateData()
+{
+ if( m_pLayoutData )
+ delete m_pLayoutData;
+ delete mpMenu;
+}
+
+// -----------------------------------------------------------------------
+ImplToolItem::ImplToolItem()
+{
+ mnId = 0;
+ mpWindow = NULL;
+ mpUserData = NULL;
+ mnHelpId = 0;
+ meType = TOOLBOXITEM_BUTTON;
+ mnBits = 0;
+ meState = STATE_NOCHECK;
+ mbEnabled = TRUE;
+ mbVisible = TRUE;
+ mbEmptyBtn = TRUE;
+ mbShowWindow = FALSE;
+ mbBreak = FALSE;
+ mnSepSize = TB_SEP_SIZE;
+ mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
+ mnImageAngle = 0;
+ mbMirrorMode = FALSE;
+ mbVisibleText = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::ImplToolItem( USHORT nItemId, const Image& rImage,
+ ToolBoxItemBits nItemBits ) :
+ maImage( rImage )
+{
+ mnId = nItemId;
+ mpWindow = NULL;
+ mpUserData = NULL;
+ mnHelpId = 0;
+ meType = TOOLBOXITEM_BUTTON;
+ mnBits = nItemBits;
+ meState = STATE_NOCHECK;
+ mbEnabled = TRUE;
+ mbVisible = TRUE;
+ mbEmptyBtn = FALSE;
+ mbShowWindow = FALSE;
+ mbBreak = FALSE;
+ mnSepSize = TB_SEP_SIZE;
+ mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
+ mnImageAngle = 0;
+ mbMirrorMode = false;
+ mbVisibleText = false;
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::ImplToolItem( USHORT nItemId, const XubString& rText,
+ ToolBoxItemBits nItemBits ) :
+ maText( rText )
+{
+ mnId = nItemId;
+ mpWindow = NULL;
+ mpUserData = NULL;
+ mnHelpId = 0;
+ meType = TOOLBOXITEM_BUTTON;
+ mnBits = nItemBits;
+ meState = STATE_NOCHECK;
+ mbEnabled = TRUE;
+ mbVisible = TRUE;
+ mbEmptyBtn = FALSE;
+ mbShowWindow = FALSE;
+ mbBreak = FALSE;
+ mnSepSize = TB_SEP_SIZE;
+ mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
+ mnImageAngle = 0;
+ mbMirrorMode = false;
+ mbVisibleText = false;
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::ImplToolItem( USHORT nItemId, const Image& rImage,
+ const XubString& rText, ToolBoxItemBits nItemBits ) :
+ maImage( rImage ),
+ maText( rText )
+{
+ mnId = nItemId;
+ mpWindow = NULL;
+ mpUserData = NULL;
+ mnHelpId = 0;
+ meType = TOOLBOXITEM_BUTTON;
+ mnBits = nItemBits;
+ meState = STATE_NOCHECK;
+ mbEnabled = TRUE;
+ mbVisible = TRUE;
+ mbEmptyBtn = FALSE;
+ mbShowWindow = FALSE;
+ mbBreak = FALSE;
+ mnSepSize = TB_SEP_SIZE;
+ mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
+ mnImageAngle = 0;
+ mbMirrorMode = false;
+ mbVisibleText = false;
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::ImplToolItem( const ImplToolItem& rItem ) :
+ mpWindow ( rItem.mpWindow ),
+ mpUserData ( rItem.mpUserData ),
+ maImage ( rItem.maImage ),
+ maHighImage ( rItem.maHighImage ),
+ mnImageAngle ( rItem.mnImageAngle ),
+ mbMirrorMode ( rItem.mbMirrorMode ),
+ maText ( rItem.maText ),
+ maQuickHelpText ( rItem.maQuickHelpText ),
+ maHelpText ( rItem.maHelpText ),
+ maCommandStr ( rItem.maCommandStr ),
+ mnHelpId ( rItem.mnHelpId ),
+ maRect ( rItem.maRect ),
+ maCalcRect ( rItem.maCalcRect ),
+ maItemSize ( rItem.maItemSize ),
+ mnSepSize ( rItem.mnSepSize ),
+ mnDropDownArrowWidth ( rItem.mnDropDownArrowWidth ),
+ meType ( rItem.meType ),
+ mnBits ( rItem.mnBits ),
+ meState ( rItem.meState ),
+ mnId ( rItem.mnId ),
+ mbEnabled ( rItem.mbEnabled ),
+ mbVisible ( rItem.mbVisible ),
+ mbEmptyBtn ( rItem.mbEmptyBtn ),
+ mbShowWindow ( rItem.mbShowWindow ),
+ mbBreak ( rItem.mbBreak ),
+ mbVisibleText ( rItem.mbVisibleText )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::~ImplToolItem()
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem& ImplToolItem::operator=( const ImplToolItem& rItem )
+{
+ mpWindow = rItem.mpWindow;
+ mpUserData = rItem.mpUserData;
+ maImage = rItem.maImage;
+ maHighImage = rItem.maHighImage;
+ mnImageAngle = rItem.mnImageAngle;
+ mbMirrorMode = rItem.mbMirrorMode;
+ maText = rItem.maText;
+ maQuickHelpText = rItem.maQuickHelpText;
+ maHelpText = rItem.maHelpText;
+ maCommandStr = rItem.maCommandStr;
+ mnHelpId = rItem.mnHelpId;
+ maRect = rItem.maRect;
+ maCalcRect = rItem.maCalcRect;
+ mnSepSize = rItem.mnSepSize;
+ mnDropDownArrowWidth = rItem.mnDropDownArrowWidth;
+ maItemSize = rItem.maItemSize;
+ mbVisibleText = rItem.mbVisibleText;
+ meType = rItem.meType;
+ mnBits = rItem.mnBits;
+ meState = rItem.meState;
+ mnId = rItem.mnId;
+ mbEnabled = rItem.mbEnabled;
+ mbVisible = rItem.mbVisible;
+ mbEmptyBtn = rItem.mbEmptyBtn;
+ mbShowWindow = rItem.mbShowWindow;
+ mbBreak = rItem.mbBreak;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+Size ImplToolItem::GetSize( BOOL bHorz, BOOL bCheckMaxWidth, long maxWidth, const Size& rDefaultSize )
+{
+ Size aSize( rDefaultSize ); // the size of 'standard' toolbox items
+ // non-standard items are eg windows or buttons with text
+
+ if ( (meType == TOOLBOXITEM_BUTTON) || (meType == TOOLBOXITEM_SPACE) )
+ {
+ aSize = maItemSize;
+
+ if ( mpWindow && bHorz )
+ {
+ // get size of item window and check if it fits
+ // no windows in vertical toolbars (the default is mbShowWindow=FALSE)
+ Size aWinSize = mpWindow->GetSizePixel();
+ if ( !bCheckMaxWidth || (aWinSize.Width() <= maxWidth) )
+ {
+ aSize.Width() = aWinSize.Width();
+ aSize.Height() = aWinSize.Height();
+ mbShowWindow = TRUE;
+ }
+ else
+ {
+ if ( mbEmptyBtn )
+ {
+ aSize.Width() = 0;
+ aSize.Height() = 0;
+ }
+ }
+ }
+ }
+ else if ( meType == TOOLBOXITEM_SEPARATOR )
+ {
+ if ( bHorz )
+ {
+ aSize.Width() = mnSepSize;
+ aSize.Height() = rDefaultSize.Height();
+ }
+ else
+ {
+ aSize.Width() = rDefaultSize.Width();
+ aSize.Height() = mnSepSize;
+ }
+ }
+ else if ( meType == TOOLBOXITEM_BREAK )
+ {
+ aSize.Width() = 0;
+ aSize.Height() = 0;
+ }
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplToolItem::DetermineButtonDrawStyle( ButtonType eButtonType, BOOL& rbImage, BOOL& rbText ) const
+{
+ if ( meType != TOOLBOXITEM_BUTTON )
+ {
+ // no button -> draw nothing
+ rbImage = rbText = FALSE;
+ return;
+ }
+
+ BOOL bHasImage;
+ BOOL bHasText;
+
+ // check for image and/or text
+ if ( !(maImage) )
+ bHasImage = FALSE;
+ else
+ bHasImage = TRUE;
+ if ( !maText.Len() )
+ bHasText = FALSE;
+ else
+ bHasText = TRUE;
+
+ // prefer images if symbolonly buttons are drawn
+ // prefer texts if textonly buttons are dreawn
+
+ if ( eButtonType == BUTTON_SYMBOL ) // drawing icons only
+ {
+ if( bHasImage || !bHasText )
+ {
+ rbImage = TRUE;
+ rbText = FALSE;
+ }
+ else
+ {
+ rbImage = FALSE;
+ rbText = TRUE;
+ }
+ }
+ else if ( eButtonType == BUTTON_TEXT ) // drawing text only
+ {
+ if( bHasText || !bHasImage )
+ {
+ rbImage = FALSE;
+ rbText = TRUE;
+ }
+ else
+ {
+ rbImage = TRUE;
+ rbText = FALSE;
+ }
+ }
+ else // drawing icons and text both
+ {
+ rbImage = TRUE;
+ rbText = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ImplToolItem::GetDropDownRect( BOOL bHorz ) const
+{
+ Rectangle aRect;
+ if( (mnBits & TIB_DROPDOWN) && !maRect.IsEmpty() )
+ {
+ aRect = maRect;
+ if( mbVisibleText && !bHorz )
+ // item will be rotated -> place dropdown to the bottom
+ aRect.Top() = aRect.Bottom() - mnDropDownArrowWidth;
+ else
+ // place dropdown to the right
+ aRect.Left() = aRect.Right() - mnDropDownArrowWidth;
+ }
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplToolItem::IsClipped() const
+{
+ return ( meType == TOOLBOXITEM_BUTTON && mbVisible && maRect.IsEmpty() );
+}
+
+// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::ImplConvertMenuString( const XubString& rStr )
+{
+ maCvtStr = rStr;
+ if ( mbMenuStrings )
+ maCvtStr.EraseTrailingChars( '.' );
+ maCvtStr = MnemonicGenerator::EraseAllMnemonicChars( maCvtStr );
+ return maCvtStr;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplInvalidate( BOOL bNewCalc, BOOL bFullPaint )
+{
+ ImplUpdateInputEnable();
+
+ if ( bNewCalc )
+ mbCalc = TRUE;
+
+ if ( bFullPaint )
+ {
+ mbFormat = TRUE;
+
+ // Muss ueberhaupt eine neue Ausgabe erfolgen
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ Invalidate( Rectangle( mnLeftBorder, mnTopBorder,
+ mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
+ maTimer.Stop();
+ }
+ }
+ else
+ {
+ if ( !mbFormat )
+ {
+ mbFormat = TRUE;
+
+ // Muss ueberhaupt eine neue Ausgabe erfolgen
+ if ( IsReallyVisible() && IsUpdateMode() )
+ maTimer.Start();
+ }
+ }
+
+ // request new layout by layoutmanager
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_FORMATCHANGED );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplUpdateItem( USHORT nIndex )
+{
+ // Muss ueberhaupt eine neue Ausgabe erfolgen
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( nIndex == 0xFFFF )
+ {
+ // #i52217# no immediate draw as this might lead to paint problems
+ Invalidate( Rectangle( mnLeftBorder, mnTopBorder,
+ mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
+ }
+ else
+ {
+ if ( !mbFormat )
+ {
+ // #i52217# no immediate draw as this might lead to paint problems
+ Invalidate( mpData->m_aItems[nIndex].maRect );
+ }
+ else
+ maPaintRect.Union( mpData->m_aItems[nIndex].maRect );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Click()
+{
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_CLICK );
+ maClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::DoubleClick()
+{
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_DOUBLECLICK );
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Activate()
+{
+ mnActivateCount++;
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ACTIVATE );
+ maActivateHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Deactivate()
+{
+ mnActivateCount--;
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_DEACTIVATE );
+ maDeactivateHdl.Call( this );
+
+ if ( mbHideStatusText )
+ {
+ GetpApp()->HideHelpStatusText();
+ mbHideStatusText = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Highlight()
+{
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
+ maHighlightHdl.Call( this );
+
+ XubString aStr = GetHelpText( mnCurItemId );
+ if ( aStr.Len() || mbHideStatusText )
+ {
+ GetpApp()->ShowHelpStatusText( aStr );
+ mbHideStatusText = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Select()
+{
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_SELECT );
+ maSelectHdl.Call( this );
+
+ if ( aDelData.IsDelete() )
+ return;
+ ImplRemoveDel( &aDelData );
+
+ // TODO: GetFloatingWindow in DockingWindow is currently inline, change it to check dockingwrapper
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper && pWrapper->GetFloatingWindow() && pWrapper->GetFloatingWindow()->IsInPopupMode() )
+ pWrapper->GetFloatingWindow()->EndPopupMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::NextToolBox()
+{
+ maNextToolBoxHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Customize( const ToolBoxCustomizeEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertItem( const ResId& rResId, USHORT nPos )
+{
+ ULONG nObjMask;
+ BOOL bImage = FALSE; // Wurde Image gesetzt
+
+ // Item anlegen
+ ImplToolItem aItem;
+
+ GetRes( rResId.SetRT( RSC_TOOLBOXITEM ) );
+ nObjMask = ReadLongRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_ID )
+ aItem.mnId = sal::static_int_cast<USHORT>(ReadLongRes());
+ else
+ aItem.mnId = 1;
+
+ if ( nObjMask & RSC_TOOLBOXITEM_TYPE )
+ aItem.meType = (ToolBoxItemType)ReadLongRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_STATUS )
+ aItem.mnBits = (ToolBoxItemBits)ReadLongRes();
+
+ if( nObjMask & RSC_TOOLBOXITEM_HELPID )
+ aItem.mnHelpId = ReadLongRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_TEXT )
+ {
+ aItem.maText = ReadStringRes();
+ aItem.maText = ImplConvertMenuString( aItem.maText );
+ }
+ if ( nObjMask & RSC_TOOLBOXITEM_HELPTEXT )
+ aItem.maHelpText = ReadStringRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_BITMAP )
+ {
+ Bitmap aBmp = Bitmap( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ aItem.maImage = Image( aBmp, IMAGE_STDBTN_COLOR );
+ bImage = TRUE;
+ }
+ if ( nObjMask & RSC_TOOLBOXITEM_IMAGE )
+ {
+ aItem.maImage = Image( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ bImage = TRUE;
+ }
+ if ( nObjMask & RSC_TOOLBOXITEM_DISABLE )
+ aItem.mbEnabled = !(BOOL)ReadShortRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_STATE )
+ aItem.meState = (TriState)ReadLongRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_HIDE )
+ aItem.mbVisible = !((BOOL)ReadShortRes());
+
+ if ( nObjMask & RSC_TOOLBOXITEM_COMMAND )
+ aItem.maCommandStr = ReadStringRes();
+
+ // Wenn kein Image geladen wurde, versuchen wir das Image aus der
+ // Image-Liste zu holen
+ if ( !bImage && aItem.mnId )
+ aItem.maImage = maImageList.GetImage( aItem.mnId );
+
+ // Wenn es sich um ein ButtonItem handelt, die ID ueberpruefen
+ BOOL bNewCalc;
+ if ( aItem.meType != TOOLBOXITEM_BUTTON )
+ {
+ bNewCalc = FALSE;
+ aItem.mnId = 0;
+ }
+ else
+ {
+ bNewCalc = TRUE;
+
+ DBG_ASSERT( aItem.mnId, "ToolBox::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( aItem.mnId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertItem(): ItemId already exists" );
+ }
+
+ // Item anlegen und in die Liste einfuegen
+ mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
+ mpData->ImplClearLayoutData();
+
+ // ToolBox neu brechnen und neu ausgeben
+ ImplInvalidate( bNewCalc );
+
+ // Notify
+ USHORT nNewPos = sal::static_int_cast<USHORT>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertItem( USHORT nItemId, const Image& rImage,
+ ToolBoxItemBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, rImage, nBits ) );
+ mpData->ImplClearLayoutData();
+
+ ImplInvalidate( TRUE );
+
+ // Notify
+ USHORT nNewPos = sal::static_int_cast<USHORT>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >(nNewPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertItem( USHORT nItemId, const Image& rImage,
+ const XubString& rText,
+ ToolBoxItemBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, rImage, ImplConvertMenuString( rText ), nBits ) );
+ mpData->ImplClearLayoutData();
+
+ ImplInvalidate( TRUE );
+
+ // Notify
+ USHORT nNewPos = sal::static_int_cast<USHORT>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertItem( USHORT nItemId, const XubString& rText,
+ ToolBoxItemBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, ImplConvertMenuString( rText ), nBits ) );
+ mpData->ImplClearLayoutData();
+
+ ImplInvalidate( TRUE );
+
+ // Notify
+ USHORT nNewPos = sal::static_int_cast<USHORT>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertWindow( USHORT nItemId, Window* pWindow,
+ ToolBoxItemBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "ToolBox::InsertWindow(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertWindow(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ ImplToolItem aItem;
+ aItem.mnId = nItemId;
+ aItem.meType = TOOLBOXITEM_BUTTON;
+ aItem.mnBits = nBits;
+ aItem.mpWindow = pWindow;
+ mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
+ mpData->ImplClearLayoutData();
+
+ if ( pWindow )
+ pWindow->Hide();
+
+ ImplInvalidate( TRUE );
+
+ // Notify
+ USHORT nNewPos = sal::static_int_cast<USHORT>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertSpace( USHORT nPos )
+{
+ // Item anlegen und in die Liste einfuegen
+ ImplToolItem aItem;
+ aItem.meType = TOOLBOXITEM_SPACE;
+ aItem.mbEnabled = FALSE;
+ mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
+ mpData->ImplClearLayoutData();
+
+ ImplInvalidate( FALSE );
+
+ // Notify
+ USHORT nNewPos = sal::static_int_cast<USHORT>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertSeparator( USHORT nPos, USHORT nPixSize )
+{
+ // Item anlegen und in die Liste einfuegen
+ ImplToolItem aItem;
+ aItem.meType = TOOLBOXITEM_SEPARATOR;
+ aItem.mbEnabled = FALSE;
+ if ( nPixSize )
+ aItem.mnSepSize = nPixSize;
+ mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
+ mpData->ImplClearLayoutData();
+
+ ImplInvalidate( FALSE );
+
+ // Notify
+ USHORT nNewPos = sal::static_int_cast<USHORT>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertBreak( USHORT nPos )
+{
+ // Item anlegen und in die Liste einfuegen
+ ImplToolItem aItem;
+ aItem.meType = TOOLBOXITEM_BREAK;
+ aItem.mbEnabled = FALSE;
+ mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
+ mpData->ImplClearLayoutData();
+
+ ImplInvalidate( FALSE );
+
+ // Notify
+ USHORT nNewPos = sal::static_int_cast<USHORT>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::RemoveItem( USHORT nPos )
+{
+ if( nPos < mpData->m_aItems.size() )
+ {
+ BOOL bMustCalc;
+ if ( mpData->m_aItems[nPos].meType == TOOLBOXITEM_BUTTON )
+ bMustCalc = TRUE;
+ else
+ bMustCalc = FALSE;
+
+ if ( mpData->m_aItems[nPos].mpWindow )
+ mpData->m_aItems[nPos].mpWindow->Hide();
+
+ // PaintRect um das removete Item erweitern
+ maPaintRect.Union( mpData->m_aItems[nPos].maRect );
+
+ // Absichern gegen das Loeschen im Select-Handler
+ if ( mpData->m_aItems[nPos].mnId == mnCurItemId )
+ mnCurItemId = 0;
+ if ( mpData->m_aItems[nPos].mnId == mnHighItemId )
+ mnHighItemId = 0;
+
+ ImplInvalidate( bMustCalc );
+
+ mpData->m_aItems.erase( mpData->m_aItems.begin()+nPos );
+ mpData->ImplClearLayoutData();
+
+ // Notify
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMREMOVED, reinterpret_cast< void* >( nPos ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::MoveItem( USHORT nItemId, USHORT nNewPos )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos == nNewPos )
+ return;
+
+ if ( nPos < nNewPos )
+ nNewPos--;
+
+ // Existiert Item
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ // ToolBox-Item in der Liste verschieben
+ ImplToolItem aItem = mpData->m_aItems[nPos];
+ mpData->m_aItems.erase( mpData->m_aItems.begin()+nPos );
+ mpData->m_aItems.insert( (nNewPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nNewPos : mpData->m_aItems.end(), aItem );
+ mpData->ImplClearLayoutData();
+
+ // ToolBox neu ausgeben
+ ImplInvalidate( FALSE );
+
+ // Notify
+ if( nPos < nNewPos ) // only send one event, all indices above this item are invalid anyway
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMREMOVED, reinterpret_cast< void* >( nPos ) );
+ else
+ {
+ USHORT nNewPos2 = sal::static_int_cast<USHORT>(( nNewPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nNewPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos2 ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::CopyItem( const ToolBox& rToolBox, USHORT nItemId,
+ USHORT nNewPos )
+{
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::CopyItem(): ItemId already exists" );
+
+ USHORT nPos = rToolBox.GetItemPos( nItemId );
+
+ // Existiert Item
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ // ToolBox-Item in der Liste verschieben
+ ImplToolItem aNewItem = rToolBox.mpData->m_aItems[nPos];
+ // Bestimme Daten zuruecksetzen
+ aNewItem.mpWindow = NULL;
+ aNewItem.mbShowWindow = FALSE;
+
+ mpData->m_aItems.insert( (nNewPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nNewPos : mpData->m_aItems.end(), aNewItem );
+ mpData->ImplClearLayoutData();
+ // ToolBox neu ausgeben
+ ImplInvalidate( FALSE );
+
+ // Notify
+ USHORT nNewPos2 = sal::static_int_cast<USHORT>(( nNewPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nNewPos);
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos2 ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::CopyItems( const ToolBox& rToolBox )
+{
+ mpData->ImplClearLayoutData();
+ mpData->m_aItems = rToolBox.mpData->m_aItems;
+ // Absichern gegen das Loeschen im Select-Handler
+ mnCurItemId = 0;
+ mnHighItemId = 0;
+
+ for( std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
+ it != mpData->m_aItems.end(); ++it )
+ {
+ it->mpWindow = NULL;
+ it->mbShowWindow = FALSE;
+ }
+
+ ImplInvalidate( TRUE, TRUE );
+
+ // Notify
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ALLITEMSCHANGED );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Clear()
+{
+ mpData->m_aItems.clear();
+ mpData->ImplClearLayoutData();
+
+ // Absichern gegen das Loeschen im Select-Handler
+ mnCurItemId = 0;
+ mnHighItemId = 0;
+
+ ImplInvalidate( TRUE, TRUE );
+
+ // Notify
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ALLITEMSCHANGED );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetButtonType( ButtonType eNewType )
+{
+ if ( meButtonType != eNewType )
+ {
+ meButtonType = eNewType;
+
+ // Hier besser alles neu ausgeben, da es ansonsten zu Problemen
+ // mit den per CopyBits kopierten Bereichen geben kann
+ ImplInvalidate( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetToolboxButtonSize( ToolBoxButtonSize eSize )
+{
+ if( mpData->meButtonSize != eSize )
+ {
+ mpData->meButtonSize = eSize;
+ mbCalc = TRUE;
+ mbFormat = TRUE;
+ }
+}
+
+ToolBoxButtonSize ToolBox::GetToolboxButtonSize() const
+{
+ return mpData->meButtonSize;
+}
+
+// -----------------------------------------------------------------------
+
+const Size& ToolBox::GetDefaultImageSize() const
+{
+ static Size aSmallButtonSize( TB_SMALLIMAGESIZE, TB_SMALLIMAGESIZE );
+
+ static ULONG s_nSymbolsStyle = STYLE_SYMBOLS_DEFAULT;
+ static Size aLargeButtonSize( TB_LARGEIMAGESIZE, TB_LARGEIMAGESIZE );
+
+ ULONG nSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyle();
+ if ( s_nSymbolsStyle != nSymbolsStyle )
+ {
+ s_nSymbolsStyle = nSymbolsStyle;
+ switch ( nSymbolsStyle )
+ {
+ case STYLE_SYMBOLS_INDUSTRIAL:
+ aLargeButtonSize = Size( TB_LARGEIMAGESIZE_INDUSTRIAL, TB_LARGEIMAGESIZE_INDUSTRIAL );
+ break;
+ case STYLE_SYMBOLS_CRYSTAL:
+ aLargeButtonSize = Size( TB_LARGEIMAGESIZE_CRYSTAL, TB_LARGEIMAGESIZE_CRYSTAL );
+ break;
+ case STYLE_SYMBOLS_OXYGEN:
+ aLargeButtonSize = Size( TB_LARGEIMAGESIZE_OXYGEN, TB_LARGEIMAGESIZE_OXYGEN );
+ break;
+ default:
+ aLargeButtonSize = Size( TB_LARGEIMAGESIZE, TB_LARGEIMAGESIZE );
+ }
+ }
+
+ return GetToolboxButtonSize() == TOOLBOX_BUTTONSIZE_LARGE ? aLargeButtonSize : aSmallButtonSize;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetAlign( WindowAlign eNewAlign )
+{
+ if ( meAlign != eNewAlign )
+ {
+ meAlign = eNewAlign;
+
+ if ( !ImplIsFloatingMode() )
+ {
+ // Setzen, ob Items horizontal oder vertikal angeordnet werden sollen
+ if ( (eNewAlign == WINDOWALIGN_LEFT) || (eNewAlign == WINDOWALIGN_RIGHT) )
+ mbHorz = FALSE;
+ else
+ mbHorz = TRUE;
+
+ // Hier alles neu ausgeben, da sich Border auch aendert
+ mbCalc = TRUE;
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetLineCount( USHORT nNewLines )
+{
+ if ( !nNewLines )
+ nNewLines = 1;
+
+ if ( mnLines != nNewLines )
+ {
+ mnLines = nNewLines;
+
+ // Hier besser alles neu ausgeben, da es ansonsten zu Problemen
+ // mit den per CopyBits kopierten Bereichen geben kann
+ ImplInvalidate( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetPageScroll( BOOL b )
+{
+ mpData->mbPageScroll = b;
+}
+
+BOOL ToolBox::GetPageScroll()
+{
+ return mpData->mbPageScroll;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetNextToolBox( const XubString& rStr )
+{
+ BOOL bCalcNew = (!maNextToolBoxStr.Len() != !rStr.Len());
+ maNextToolBoxStr = rStr;
+ if ( bCalcNew )
+ ImplInvalidate( TRUE, FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemCount() const
+{
+ return (USHORT)mpData->m_aItems.size();
+}
+
+// -----------------------------------------------------------------------
+
+ToolBoxItemType ToolBox::GetItemType( USHORT nPos ) const
+{
+ return (nPos < mpData->m_aItems.size()) ? mpData->m_aItems[nPos].meType : TOOLBOXITEM_DONTKNOW;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemPos( USHORT nItemId ) const
+{
+ int nCount = mpData->m_aItems.size();
+ for( int nPos = 0; nPos < nCount; nPos++ )
+ if( mpData->m_aItems[nPos].mnId == nItemId )
+ return (USHORT)nPos;
+
+ return TOOLBOX_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemPos( const Point& rPos ) const
+{
+ // search the item position on the given point
+ USHORT nRet = TOOLBOX_ITEM_NOTFOUND;
+ USHORT nPos = 0;
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while( it != mpData->m_aItems.end() )
+ {
+ if ( it->maRect.IsInside( rPos ) )
+ {
+ // item found -> save position and break
+ nRet = nPos;
+ break;
+ }
+
+ ++it;
+ ++nPos;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemId( USHORT nPos ) const
+{
+ return (nPos < mpData->m_aItems.size()) ? mpData->m_aItems[nPos].mnId : 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemId( const Point& rPos ) const
+{
+ // Item suchen, das geklickt wurde
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while( it != mpData->m_aItems.end() )
+ {
+ // Ist es dieses Item
+ if ( it->maRect.IsInside( rPos ) )
+ {
+ if ( it->meType == TOOLBOXITEM_BUTTON )
+ return it->mnId;
+ else
+ return 0;
+ }
+
+ ++it;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Point ToolBox::ImplGetPopupPosition( const Rectangle& rRect, const Size& rSize ) const
+{
+ Point aPos;
+ if( !rRect.IsEmpty() )
+ {
+ Rectangle aScreen = GetDesktopRectPixel();
+
+ // the popup should be positioned so that it will not cover
+ // the item rect and that it fits the desktop
+ // the preferred direction is always towards the center of
+ // the application window
+
+ Point devPos; // the position in device coordinates for screen comparison
+ switch( meAlign )
+ {
+ case WINDOWALIGN_TOP:
+ aPos = rRect.BottomLeft();
+ aPos.Y()++;
+ devPos = OutputToAbsoluteScreenPixel( aPos );
+ if( devPos.Y() + rSize.Height() >= aScreen.Bottom() )
+ aPos.Y() = rRect.Top() - rSize.Height();
+ break;
+ case WINDOWALIGN_BOTTOM:
+ aPos = rRect.TopLeft();
+ aPos.Y()--;
+ devPos = OutputToAbsoluteScreenPixel( aPos );
+ if( devPos.Y() - rSize.Height() > aScreen.Top() )
+ aPos.Y() -= rSize.Height();
+ else
+ aPos.Y() = rRect.Bottom();
+ break;
+ case WINDOWALIGN_LEFT:
+ aPos = rRect.TopRight();
+ aPos.X()++;
+ devPos = OutputToAbsoluteScreenPixel( aPos );
+ if( devPos.X() + rSize.Width() >= aScreen.Right() )
+ aPos.X() = rRect.Left() - rSize.Width();
+ break;
+ case WINDOWALIGN_RIGHT:
+ aPos = rRect.TopLeft();
+ aPos.X()--;
+ devPos = OutputToAbsoluteScreenPixel( aPos );
+ if( devPos.X() - rSize.Width() > aScreen.Left() )
+ aPos.X() -= rSize.Width();
+ else
+ aPos.X() = rRect.Right();
+ break;
+ default:
+ break;
+ };
+ }
+ return aPos;
+}
+
+
+Point ToolBox::GetItemPopupPosition( USHORT nItemId, const Size& rSize ) const
+{
+ return ImplGetPopupPosition( GetItemRect( nItemId ), rSize );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ToolBox::GetItemRect( USHORT nItemId ) const
+{
+ if ( mbCalc || mbFormat )
+ ((ToolBox*)this)->ImplFormat();
+
+ USHORT nPos = GetItemPos( nItemId );
+ return GetItemPosRect( nPos );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ToolBox::GetItemPosRect( USHORT nPos ) const
+{
+ if ( mbCalc || mbFormat )
+ ((ToolBox*)this)->ImplFormat();
+
+ if ( nPos < mpData->m_aItems.size() )
+ return mpData->m_aItems[nPos].maRect;
+ else
+ return Rectangle();
+}
+
+// -----------------------------------------------------------------------
+Rectangle ToolBox::GetItemDropDownRect( USHORT nItemId ) const
+{
+ if ( mbCalc || mbFormat )
+ ((ToolBox*)this)->ImplFormat();
+
+ USHORT nPos = GetItemPos( nItemId );
+ return GetItemPosDropDownRect( nPos );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ToolBox::GetItemPosDropDownRect( USHORT nPos ) const
+{
+ if ( mbCalc || mbFormat )
+ ((ToolBox*)this)->ImplFormat();
+
+ if ( nPos < mpData->m_aItems.size() )
+ return mpData->m_aItems[nPos].GetDropDownRect( mbHorz );
+ else
+ return Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ToolBox::GetMenubuttonRect() const
+{
+ return mpData->maMenubuttonItem.maRect;
+}
+
+BOOL ToolBox::ImplHasExternalMenubutton()
+{
+ // check if the borderwindow (i.e. the decoration) provides the menu button
+ BOOL bRet = FALSE;
+ if( ImplIsFloatingMode() )
+ {
+ // custom menu is placed in the decoration
+ ImplBorderWindow *pBorderWin = dynamic_cast<ImplBorderWindow*>( GetWindow( WINDOW_BORDER ) );
+ if( pBorderWin && !pBorderWin->GetMenuRect().IsEmpty() )
+ bRet = TRUE;
+ }
+ return bRet;
+}
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemBits( USHORT nItemId, ToolBoxItemBits nBits )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos < mpData->m_aItems.size() )
+ {
+ ToolBoxItemBits nOldBits = mpData->m_aItems[nPos].mnBits;
+ mpData->m_aItems[nPos].mnBits = nBits;
+ nBits &= TIB_LEFT | TIB_AUTOSIZE | TIB_DROPDOWN;
+ nOldBits &= TIB_LEFT | TIB_AUTOSIZE | TIB_DROPDOWN;
+ // trigger reformat when the item width has changed (dropdown arrow)
+ BOOL bFormat = (nBits & TIB_DROPDOWN) != (nOldBits & TIB_DROPDOWN);
+ if ( nBits != nOldBits )
+ ImplInvalidate( TRUE, bFormat );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ToolBoxItemBits ToolBox::GetItemBits( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemData( USHORT nItemId, void* pNewData )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos < mpData->m_aItems.size() )
+ {
+ mpData->m_aItems[nPos].mpUserData = pNewData;
+ ImplUpdateItem( nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* ToolBox::GetItemData( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mpUserData;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemImage( USHORT nItemId, const Image& rImage )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+ // Nur wenn alles berechnet ist, mehr Aufwand treiben
+ if ( !mbCalc )
+ {
+ Size aOldSize = pItem->maImage.GetSizePixel();
+ pItem->maImage = rImage;
+ if ( aOldSize != pItem->maImage.GetSizePixel() )
+ ImplInvalidate( TRUE );
+ else
+ ImplUpdateItem( nPos );
+ }
+ else
+ pItem->maImage = rImage;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetImageList( const ImageList& rImageList )
+{
+ maImageList = rImageList;
+
+ USHORT nCount = (USHORT)mpData->m_aItems.size();
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ Image aImage;
+ if ( mpData->m_aItems[i].mnId )
+ aImage = maImageList.GetImage( mpData->m_aItems[i].mnId );
+ if( !!aImage )
+ SetItemImage( mpData->m_aItems[i].mnId, aImage );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static Image ImplRotImage( const Image& rImage, long nAngle10 )
+{
+ Image aRet;
+ BitmapEx aRotBitmapEx( rImage.GetBitmapEx() );
+
+ aRotBitmapEx.Rotate( nAngle10, Color( COL_WHITE ) );
+
+ return Image( aRotBitmapEx );
+}
+
+void ToolBox::SetItemImageAngle( USHORT nItemId, long nAngle10 )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+ Size aOldSize = pItem->maImage.GetSizePixel();
+
+ long nDeltaAngle = (nAngle10 - pItem->mnImageAngle) % 3600;
+ while( nDeltaAngle < 0 )
+ nDeltaAngle += 3600;
+
+ pItem->mnImageAngle = nAngle10;
+ if( nDeltaAngle && !!pItem->maImage )
+ {
+ pItem->maImage = ImplRotImage( pItem->maImage, nDeltaAngle );
+ if( !!pItem->maHighImage )
+ pItem->maHighImage = ImplRotImage( pItem->maHighImage, nDeltaAngle );
+ }
+
+ if ( !mbCalc )
+ {
+ if ( aOldSize != pItem->maImage.GetSizePixel() )
+ ImplInvalidate( TRUE );
+ else
+ ImplUpdateItem( nPos );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static Image ImplMirrorImage( const Image& rImage )
+{
+ Image aRet;
+ BitmapEx aMirrBitmapEx( rImage.GetBitmapEx() );
+
+ aMirrBitmapEx.Mirror( BMP_MIRROR_HORZ );
+
+ return Image( aMirrBitmapEx );
+}
+
+void ToolBox::SetItemImageMirrorMode( USHORT nItemId, BOOL bMirror )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+
+ if( ( pItem->mbMirrorMode && ! bMirror ) ||
+ ( ! pItem->mbMirrorMode && bMirror )
+ )
+ {
+ pItem->mbMirrorMode = bMirror ? true : false;
+ if( !!pItem->maImage )
+ {
+ pItem->maImage = ImplMirrorImage( pItem->maImage );
+ if( !!pItem->maHighImage )
+ pItem->maHighImage = ImplMirrorImage( pItem->maHighImage );
+ }
+
+ if ( !mbCalc )
+ ImplUpdateItem( nPos );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image ToolBox::GetItemImage( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maImage;
+ else
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+long ToolBox::GetItemImageAngle( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mnImageAngle;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::GetItemImageMirrorMode( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mbMirrorMode;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemHighImage( USHORT nItemId, const Image& rImage )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+ if ( pItem )
+ {
+ DBG_ASSERT( (pItem->maImage.GetSizePixel() == rImage.GetSizePixel()) ||
+ ((!rImage) == TRUE), "ToolBox::SetItemHighImage() - ImageSize != HighImageSize" );
+ pItem->maHighImage = rImage;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image ToolBox::GetItemHighImage( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maHighImage;
+ else
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+ // Nur wenn alles berechnet ist, mehr Aufwand treiben
+ if ( !mbCalc &&
+ ((meButtonType != BUTTON_SYMBOL) || !pItem->maImage) )
+ {
+ long nOldWidth = GetCtrlTextWidth( pItem->maText );
+ pItem->maText = ImplConvertMenuString( rText );
+ mpData->ImplClearLayoutData();
+ if ( nOldWidth != GetCtrlTextWidth( pItem->maText ) )
+ ImplInvalidate( TRUE );
+ else
+ ImplUpdateItem( nPos );
+ }
+ else
+ pItem->maText = ImplConvertMenuString( rText );
+
+ // Notify button changed event to prepare accessibility bridge
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
+
+ // Notify
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMTEXTCHANGED, reinterpret_cast< void* >( nPos ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::GetItemText( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemWindow( USHORT nItemId, Window* pNewWindow )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+ pItem->mpWindow = pNewWindow;
+ if ( pNewWindow )
+ pNewWindow->Hide();
+ ImplInvalidate( TRUE );
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED, reinterpret_cast< void* >( nPos ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Window* ToolBox::GetItemWindow( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mpWindow;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StartSelection()
+{
+ if ( mbDrag )
+ EndSelection();
+
+ if ( !mbSelection )
+ {
+ mbSelection = TRUE;
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ Activate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EndSelection()
+{
+ mbCommandDrag = FALSE;
+
+ if ( mbDrag || mbSelection )
+ {
+ // Daten zuruecksetzen
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ ImplDrawItem( mnCurPos );
+ EndTracking();
+ ReleaseMouse();
+ Deactivate();
+ }
+
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemDown( USHORT nItemId, BOOL bDown, BOOL bRelease )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ if ( bDown )
+ {
+ if ( nPos != mnCurPos )
+ {
+ mnCurPos = nPos;
+ ImplDrawItem( mnCurPos, TRUE );
+ Flush();
+ }
+ }
+ else
+ {
+ if ( nPos == mnCurPos )
+ {
+ ImplDrawItem( mnCurPos, FALSE );
+ Flush();
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ }
+ }
+
+ if ( bRelease )
+ {
+ if ( mbDrag || mbSelection )
+ {
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ EndTracking();
+ ReleaseMouse();
+ Deactivate();
+ }
+
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsItemDown( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ return (nPos == mnCurPos);
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemState( USHORT nItemId, TriState eState )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+
+ // Hat sich der Status geaendert
+ if ( pItem->meState != eState )
+ {
+ // Wenn RadioCheck, dann vorherigen unchecken
+ if ( (eState == STATE_CHECK) && (pItem->mnBits & TIB_AUTOCHECK) &&
+ (pItem->mnBits & TIB_RADIOCHECK) )
+ {
+ ImplToolItem* pGroupItem;
+ USHORT nGroupPos;
+ USHORT nItemCount = GetItemCount();
+
+ nGroupPos = nPos;
+ while ( nGroupPos )
+ {
+ pGroupItem = &mpData->m_aItems[nGroupPos-1];
+ if ( pGroupItem->mnBits & TIB_RADIOCHECK )
+ {
+ if ( pGroupItem->meState != STATE_NOCHECK )
+ SetItemState( pGroupItem->mnId, STATE_NOCHECK );
+ }
+ else
+ break;
+ nGroupPos--;
+ }
+
+ nGroupPos = nPos+1;
+ while ( nGroupPos < nItemCount )
+ {
+ pGroupItem = &mpData->m_aItems[nGroupPos];
+ if ( pGroupItem->mnBits & TIB_RADIOCHECK )
+ {
+ if ( pGroupItem->meState != STATE_NOCHECK )
+ SetItemState( pGroupItem->mnId, STATE_NOCHECK );
+ }
+ else
+ break;
+ nGroupPos++;
+ }
+ }
+
+ pItem->meState = eState;
+ ImplUpdateItem( nPos );
+
+ // Notify button changed event to prepare accessibility bridge
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
+
+ // Notify
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_CLICK, reinterpret_cast< void* >( nPos ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TriState ToolBox::GetItemState( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->meState;
+ else
+ return STATE_NOCHECK;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EnableItem( USHORT nItemId, BOOL bEnable )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+ if ( bEnable )
+ bEnable = TRUE;
+ if ( pItem->mbEnabled != bEnable )
+ {
+ pItem->mbEnabled = bEnable;
+
+ // Gegebenenfalls das Fenster mit updaten
+ if ( pItem->mpWindow )
+ pItem->mpWindow->Enable( pItem->mbEnabled );
+
+ // Item updaten
+ ImplUpdateItem( nPos );
+
+ ImplUpdateInputEnable();
+
+ // Notify button changed event to prepare accessibility bridge
+ ImplCallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
+
+ ImplCallEventListeners( bEnable ? VCLEVENT_TOOLBOX_ITEMENABLED : VCLEVENT_TOOLBOX_ITEMDISABLED, reinterpret_cast< void* >( nPos ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsItemEnabled( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mbEnabled;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ShowItem( USHORT nItemId, BOOL bVisible )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ mpData->ImplClearLayoutData();
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[nPos];
+ if ( pItem->mbVisible != bVisible )
+ {
+ pItem->mbVisible = bVisible;
+ ImplInvalidate( FALSE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsItemVisible( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mbVisible;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsItemReallyVisible( USHORT nItemId ) const
+{
+ // is the item on the visible area of the toolbox?
+ BOOL bRet = FALSE;
+ Rectangle aRect( mnLeftBorder, mnTopBorder, mnDX-mnRightBorder, mnDY-mnBottomBorder );
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem && pItem->mbVisible &&
+ !pItem->maRect.IsEmpty() && aRect.IsOver( pItem->maRect ) )
+ {
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemCommand( USHORT nItemId, const XubString& rCommand )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ pItem->maCommandStr = rCommand;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::GetItemCommand( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maCommandStr;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetQuickHelpText( USHORT nItemId, const XubString& rText )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ pItem->maQuickHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::GetQuickHelpText( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maQuickHelpText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetHelpText( USHORT nItemId, const XubString& rText )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ pItem->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::GetHelpText( USHORT nItemId ) const
+{
+ return ImplGetHelpText( nItemId );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetHelpId( USHORT nItemId, ULONG nHelpId )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ pItem->mnHelpId = nHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG ToolBox::GetHelpId( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mnHelpId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetBorder( long nX, long nY )
+{
+ mnBorderX = nX;
+ mnBorderY = nY;
+
+ ImplInvalidate( TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetOutStyle( USHORT nNewStyle )
+{
+ // always force flat looking toolbars since NWF
+ nNewStyle |= TOOLBOX_STYLE_FLAT;
+
+ if ( mnOutStyle != nNewStyle )
+ {
+ mnOutStyle = nNewStyle;
+ ImplDisableFlatButtons();
+
+ // Damit das ButtonDevice neu angelegt wird
+ if ( !(mnOutStyle & TOOLBOX_STYLE_FLAT) )
+ {
+ mnMaxItemWidth = 1;
+ mnMaxItemHeight = 1;
+ }
+
+ ImplInvalidate( TRUE, TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::RecalcItems()
+{
+ ImplInvalidate( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+// disable key input if all items are disabled
+
+void ToolBox::ImplUpdateInputEnable()
+{
+ for( std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ it != mpData->m_aItems.end(); ++it )
+ {
+ if( it->mbEnabled )
+ {
+ // at least one useful entry
+ mpData->mbKeyInputDisabled = FALSE;
+ return;
+ }
+ }
+ mpData->mbKeyInputDisabled = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplFillLayoutData() const
+{
+ mpData->m_pLayoutData = new ToolBoxLayoutData();
+
+ USHORT nCount = (USHORT)mpData->m_aItems.size();
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ ImplToolItem* pItem = &mpData->m_aItems[i];
+
+ // Nur malen, wenn Rechteck im PaintRectangle liegt
+ if ( !pItem->maRect.IsEmpty() )
+ const_cast<ToolBox*>(this)->ImplDrawItem( i, FALSE, FALSE, TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+String ToolBox::GetDisplayText() const
+{
+ if( ! mpData->m_pLayoutData )
+ ImplFillLayoutData();
+ return mpData->m_pLayoutData ? mpData->m_pLayoutData->m_aDisplayText : String();
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ToolBox::GetCharacterBounds( USHORT nItemID, long nIndex ) const
+{
+ long nItemIndex = -1;
+ if( ! mpData->m_pLayoutData )
+ ImplFillLayoutData();
+ if( mpData->m_pLayoutData )
+ {
+ for( ULONG i = 0; i < mpData->m_pLayoutData->m_aLineItemIds.size(); i++ )
+ {
+ if( mpData->m_pLayoutData->m_aLineItemIds[i] == nItemID )
+ {
+ nItemIndex = mpData->m_pLayoutData->m_aLineIndices[i];
+ break;
+ }
+ }
+ }
+ return (mpData->m_pLayoutData && nItemIndex != -1) ? mpData->m_pLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+long ToolBox::GetIndexForPoint( const Point& rPoint, USHORT& rItemID ) const
+{
+ long nIndex = -1;
+ rItemID = 0;
+ if( ! mpData->m_pLayoutData )
+ ImplFillLayoutData();
+ if( mpData->m_pLayoutData )
+ {
+ nIndex = mpData->m_pLayoutData->GetIndexForPoint( rPoint );
+ for( ULONG i = 0; i < mpData->m_pLayoutData->m_aLineIndices.size(); i++ )
+ {
+ if( mpData->m_pLayoutData->m_aLineIndices[i] <= nIndex &&
+ (i == mpData->m_pLayoutData->m_aLineIndices.size()-1 || mpData->m_pLayoutData->m_aLineIndices[i+1] > nIndex) )
+ {
+ rItemID = mpData->m_pLayoutData->m_aLineItemIds[i];
+ break;
+ }
+ }
+ }
+ return nIndex;
+}
+
+// -----------------------------------------------------------------------
+
+long ToolBox::GetTextCount() const
+{
+ if( ! mpData->m_pLayoutData )
+ ImplFillLayoutData();
+ return mpData->m_pLayoutData ? mpData->m_pLayoutData->GetLineCount() : 0;
+}
+
+// -----------------------------------------------------------------------
+
+Pair ToolBox::GetTextStartEnd( long nText ) const
+{
+ if( ! mpData->m_pLayoutData )
+ ImplFillLayoutData();
+ return mpData->m_pLayoutData ? mpData->m_pLayoutData->GetLineStartEnd( nText ) : Pair( -1, -1 );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetDisplayItemId( long nText ) const
+{
+ USHORT nItemId = 0;
+ if( ! mpData->m_pLayoutData )
+ ImplFillLayoutData();
+ if( mpData->m_pLayoutData && nText >= 0 && (ULONG)nText < mpData->m_pLayoutData->m_aLineItemIds.size() )
+ nItemId = mpData->m_pLayoutData->m_aLineItemIds[nText];
+ return nItemId;
+}
+
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetDropdownClickHdl( const Link& rLink )
+{
+ mpData->maDropdownClickHdl = rLink;
+}
+
+const Link& ToolBox::GetDropdownClickHdl() const
+{
+ return mpData->maDropdownClickHdl;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetMenuType( USHORT aType )
+{
+ if( aType != mpData->maMenuType )
+ {
+ mpData->maMenuType = aType;
+ if( IsFloatingMode() )
+ {
+ // the menu button may have to be moved into the decoration which changes the layout
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ pWrapper->ShowTitleButton( TITLE_BUTTON_MENU, ( aType & TOOLBOX_MENUTYPE_CUSTOMIZE) ? TRUE : FALSE );
+
+ mbFormat = TRUE;
+ ImplFormat();
+ ImplSetMinMaxFloatSize( this );
+ }
+ else
+ {
+ // trigger redraw of menu button
+ if( !mpData->maMenubuttonItem.maRect.IsEmpty() )
+ Invalidate(mpData->maMenubuttonItem.maRect);
+ }
+ }
+}
+
+USHORT ToolBox::GetMenuType() const
+{
+ return mpData->maMenuType;
+}
+
+BOOL ToolBox::IsMenuEnabled() const
+{
+ return mpData->maMenuType != TOOLBOX_MENUTYPE_NONE;
+}
+
+PopupMenu* ToolBox::GetMenu() const
+{
+ return mpData->mpMenu;
+}
+
+void ToolBox::SetMenuButtonHdl( const Link& rLink )
+{
+ mpData->maMenuButtonHdl = rLink;
+}
+
+const Link& ToolBox::GetMenuButtonHdl() const
+{
+ return mpData->maMenuButtonHdl;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::ImplHasClippedItems()
+{
+ // are any items currently clipped ?
+ ImplFormat();
+ std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
+ while ( it != mpData->m_aItems.end() )
+ {
+ if( it->IsClipped() )
+ return TRUE;
+ it++;
+ }
+ return FALSE;
+}
+
+void ToolBox::ImplUpdateCustomMenu()
+{
+ // fill clipped items into menu
+ if( !IsMenuEnabled() )
+ return;
+
+ PopupMenu *pMenu = GetMenu();
+
+ USHORT i = 0;
+ // remove old entries
+ while( i < pMenu->GetItemCount() )
+ {
+ if( pMenu->GetItemId( i ) >= TOOLBOX_MENUITEM_START )
+ {
+ pMenu->RemoveItem( i );
+ i = 0;
+ }
+ else
+ i++;
+ }
+
+ // add menu items, starting from the end and inserting at pos 0
+ if ( !mpData->m_aItems.empty() )
+ {
+ for ( std::vector< ImplToolItem >::reverse_iterator it(mpData->m_aItems.rbegin());
+ it != mpData->m_aItems.rend(); ++it)
+ {
+ if( it->IsClipped() )
+ {
+ USHORT id = it->mnId + TOOLBOX_MENUITEM_START;
+ pMenu->InsertItem( id, it->maText, it->maImage, 0, 0 );
+ pMenu->EnableItem( id, it->mbEnabled );
+ pMenu->CheckItem( id, it->meState == STATE_CHECK );
+ }
+ }
+ }
+}
+
+IMPL_LINK( ToolBox, ImplCustomMenuListener, VclMenuEvent*, pEvent )
+{
+ if( pEvent->GetMenu() == GetMenu() && pEvent->GetId() == VCLEVENT_MENU_SELECT )
+ {
+ USHORT id = GetMenu()->GetItemId( pEvent->GetItemPos() );
+ if( id >= TOOLBOX_MENUITEM_START )
+ TriggerItem( id - TOOLBOX_MENUITEM_START, FALSE, FALSE );
+ }
+ return 0;
+}
+
+IMPL_LINK( ToolBox, ImplCallExecuteCustomMenu, void*, EMPTYARG )
+{
+ mpData->mnEventId = 0;
+ ImplExecuteCustomMenu();
+ return 0;
+}
+
+void ToolBox::ImplExecuteCustomMenu()
+{
+ if( IsMenuEnabled() )
+ {
+ if( GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE )
+ // call button handler to allow for menu customization
+ mpData->maMenuButtonHdl.Call( this );
+
+ // register handler
+ GetMenu()->AddEventListener( LINK( this, ToolBox, ImplCustomMenuListener ) );
+
+ // make sure all disabled entries will be shown
+ GetMenu()->SetMenuFlags(
+ GetMenu()->GetMenuFlags() | MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES );
+
+ // toolbox might be destroyed during execute
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ ImplDelData aBorderDel;
+ bool bBorderDel = false;
+
+ Window *pWin = this;
+ Rectangle aMenuRect = mpData->maMenubuttonItem.maRect;
+ if( IsFloatingMode() )
+ {
+ // custom menu is placed in the decoration
+ ImplBorderWindow *pBorderWin = dynamic_cast<ImplBorderWindow*>( GetWindow( WINDOW_BORDER ) );
+ if( pBorderWin && !pBorderWin->GetMenuRect().IsEmpty() )
+ {
+ pWin = pBorderWin;
+ aMenuRect = pBorderWin->GetMenuRect();
+ pWin->ImplAddDel( &aBorderDel );
+ bBorderDel = true;
+ }
+ }
+
+ USHORT uId = GetMenu()->Execute( pWin, Rectangle( ImplGetPopupPosition( aMenuRect, Size() ), Size() ),
+ POPUPMENU_EXECUTE_DOWN | POPUPMENU_NOMOUSEUPCLOSE );
+
+ if ( aDelData.IsDelete() )
+ return;
+ ImplRemoveDel( &aDelData );
+
+ if( GetMenu() )
+ GetMenu()->RemoveEventListener( LINK( this, ToolBox, ImplCustomMenuListener ) );
+ if( bBorderDel )
+ {
+ if( aBorderDel.IsDelete() )
+ return;
+ pWin->ImplRemoveDel( &aBorderDel );
+ }
+
+ pWin->Invalidate( aMenuRect );
+
+ if( uId )
+ GrabFocusToDocument();
+ }
+}
+
+void ToolBox::ExecuteCustomMenu()
+{
+ if( IsMenuEnabled() )
+ {
+ // handle custom menu asynchronously
+ // to avoid problems if the toolbox is closed during menu execute
+ ImplUpdateCustomMenu();
+ Application::PostUserEvent( mpData->mnEventId, LINK( this, ToolBox, ImplCallExecuteCustomMenu ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+// checks override first, useful during calculation of sizes
+BOOL ToolBox::ImplIsFloatingMode() const
+{
+ DBG_ASSERT( !(mpData->mbAssumeDocked && mpData->mbAssumeFloating),
+ "ToolBox::ImplIsFloatingMode(): cannot assume docked and floating" );
+
+ if( mpData->mbAssumeDocked )
+ return FALSE;
+ else if( mpData->mbAssumeFloating )
+ return TRUE;
+ else
+ return IsFloatingMode();
+}
+
+// checks override first, useful during calculation of sizes
+BOOL ToolBox::ImplIsInPopupMode() const
+{
+ if( mpData->mbAssumePopupMode )
+ return TRUE;
+ else
+ {
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ return ( pWrapper && pWrapper->GetFloatingWindow() && pWrapper->GetFloatingWindow()->IsInPopupMode() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Lock( BOOL bLock )
+{
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( !pWrapper )
+ return;
+ if( mpData->mbIsLocked != bLock )
+ {
+ mpData->mbIsLocked = bLock;
+ if( !ImplIsFloatingMode() )
+ {
+ mbCalc = TRUE;
+ mbFormat = TRUE;
+ SetSizePixel( CalcWindowSizePixel(1) );
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::AlwaysLocked()
+{
+ // read config item to determine toolbox behaviour, used for subtoolbars
+
+ static int nAlwaysLocked = -1;
+
+ if( nAlwaysLocked == -1 )
+ {
+ nAlwaysLocked = 0; // ask configuration only once
+
+ utl::OConfigurationNode aNode = utl::OConfigurationTreeRoot::tryCreateWithServiceFactory(
+ vcl::unohelper::GetMultiServiceFactory(),
+ OUString::createFromAscii( "/org.openoffice.Office.UI.GlobalSettings/Toolbars" ) ); // note: case sensisitive !
+ if ( aNode.isValid() )
+ {
+ // feature enabled ?
+ BOOL bStatesEnabled = BOOL();
+ ::com::sun::star::uno::Any aValue = aNode.getNodeValue( OUString::createFromAscii( "StatesEnabled" ) );
+ if( aValue >>= bStatesEnabled )
+ {
+ if( bStatesEnabled == TRUE )
+ {
+ // now read the locking state
+ utl::OConfigurationNode aNode2 = utl::OConfigurationTreeRoot::tryCreateWithServiceFactory(
+ vcl::unohelper::GetMultiServiceFactory(),
+ OUString::createFromAscii( "/org.openoffice.Office.UI.GlobalSettings/Toolbars/States" ) ); // note: case sensisitive !
+
+ BOOL bLocked = BOOL();
+ ::com::sun::star::uno::Any aValue2 = aNode2.getNodeValue( OUString::createFromAscii( "Locked" ) );
+ if( aValue2 >>= bLocked )
+ nAlwaysLocked = (bLocked == TRUE) ? 1 : 0;
+ }
+ }
+ }
+ }
+
+ return nAlwaysLocked == 1 ? TRUE : FALSE;
+}
+
+BOOL ToolBox::WillUsePopupMode() const
+{
+ return mpData->mbWillUsePopupMode;
+}
+
+void ToolBox::WillUsePopupMode( BOOL b )
+{
+ mpData->mbWillUsePopupMode = b;
+}
+
+void ToolBox::ImplUpdateImageList()
+{
+ if (mpData->mpImageListProvider != NULL)
+ {
+ BOOL bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
+ try
+ {
+ ImageListType eType = bHC ? vcl::HIGHCONTRAST_YES : vcl::HIGHCONTRAST_NO;
+
+ if (eType != mpData->meImageListType)
+ {
+ vcl::IImageListProvider* pImageListProvider = mpData->mpImageListProvider;
+ SetImageList( pImageListProvider->getImageList(eType) );
+ mpData->meImageListType = eType;
+ }
+ }
+ catch (com::sun::star::lang::IllegalArgumentException &) {}
+ }
+}
+
+void ToolBox::SetImageListProvider(vcl::IImageListProvider* _pProvider)
+{
+ mpData->mpImageListProvider = _pProvider;
+ ImplUpdateImageList();
+}
+// -----------------------------------------------------------------------
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
new file mode 100644
index 000000000000..adedbde4c0f2
--- /dev/null
+++ b/vcl/source/window/window.cxx
@@ -0,0 +1,9972 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+#ifndef _SV_SVSYS_HXX
+#include "svsys.h"
+#endif
+#include "vcl/salframe.hxx"
+#include "vcl/salobj.hxx"
+#include "vcl/salinst.hxx"
+#include "vcl/salgtype.hxx"
+#include "vcl/salgdi.hxx"
+#include "vcl/salctrlhandle.hxx"
+
+#include "vcl/unohelp.hxx"
+#include "tools/time.hxx"
+#include "tools/debug.hxx"
+#ifndef _SV_RC_H
+#include "tools/rc.h"
+#endif
+#include "vcl/svdata.hxx"
+#include "vcl/windata.hxx"
+#include "vcl/dbggui.hxx"
+#include "vcl/outfont.hxx"
+#include "vcl/outdev.h"
+#include "vcl/region.h"
+#include "vcl/event.hxx"
+#include "vcl/help.hxx"
+#include "vcl/cursor.hxx"
+#include "vcl/svapp.hxx"
+#include "vcl/window.h"
+#include "vcl/window.hxx"
+#include "vcl/syswin.hxx"
+#include "vcl/syschild.hxx"
+#include "vcl/brdwin.hxx"
+#include "vcl/helpwin.hxx"
+#include "vcl/dockwin.hxx"
+#include "vcl/menu.hxx"
+#include "vcl/wrkwin.hxx"
+#include "vcl/wall.hxx"
+#include "vcl/gradient.hxx"
+#include "vcl/toolbox.h"
+#include "unotools/fontcfg.hxx"
+#include "vcl/sysdata.hxx"
+#include "vcl/sallayout.hxx"
+#include "vcl/button.hxx" // Button::GetStandardText
+#include "vcl/taskpanelist.hxx"
+#include "com/sun/star/awt/XWindowPeer.hpp"
+#include "com/sun/star/rendering/XCanvas.hpp"
+#include "com/sun/star/rendering/XSpriteCanvas.hpp"
+#include "com/sun/star/awt/XWindow.hpp"
+#include "comphelper/processfactory.hxx"
+#include "com/sun/star/datatransfer/dnd/XDragSource.hpp"
+#include "com/sun/star/datatransfer/dnd/XDropTarget.hpp"
+#include "com/sun/star/datatransfer/clipboard/XClipboard.hpp"
+#include "com/sun/star/awt/XTopWindow.hpp"
+#include "com/sun/star/awt/XDisplayConnection.hpp"
+#include "com/sun/star/lang/XInitialization.hpp"
+#include "com/sun/star/lang/XComponent.hpp"
+#include "com/sun/star/lang/XServiceName.hpp"
+#include "com/sun/star/accessibility/XAccessible.hpp"
+#include "com/sun/star/accessibility/AccessibleRole.hpp"
+
+#include "vcl/dialog.hxx"
+#include "vcl/unowrap.hxx"
+#include "vcl/dndlcon.hxx"
+#include "vcl/dndevdis.hxx"
+#include "vcl/impbmpconv.hxx"
+#include "unotools/confignode.hxx"
+#include "vcl/gdimtf.hxx"
+
+#include "vcl/pdfextoutdevdata.hxx"
+#include "vcl/lazydelete.hxx"
+
+#include <set>
+#include <typeinfo>
+
+using namespace rtl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::datatransfer::clipboard;
+using namespace ::com::sun::star::datatransfer::dnd;
+using namespace ::com::sun::star;
+using namespace com::sun;
+
+using ::com::sun::star::awt::XTopWindow;
+
+// =======================================================================
+
+DBG_NAME( Window )
+
+// =======================================================================
+
+#define IMPL_PAINT_PAINT ((USHORT)0x0001)
+#define IMPL_PAINT_PAINTALL ((USHORT)0x0002)
+#define IMPL_PAINT_PAINTALLCHILDS ((USHORT)0x0004)
+#define IMPL_PAINT_PAINTCHILDS ((USHORT)0x0008)
+#define IMPL_PAINT_ERASE ((USHORT)0x0010)
+#define IMPL_PAINT_CHECKRTL ((USHORT)0x0020)
+
+// -----------------------------------------------------------------------
+
+typedef Window* PWINDOW;
+
+// -----------------------------------------------------------------------
+
+struct ImplCalcToTopData
+{
+ ImplCalcToTopData* mpNext;
+ Window* mpWindow;
+ Region* mpInvalidateRegion;
+};
+
+struct ImplAccessibleInfos
+{
+ USHORT nAccessibleRole;
+ String* pAccessibleName;
+ String* pAccessibleDescription;
+
+ ImplAccessibleInfos()
+ {
+ nAccessibleRole = 0xFFFF;
+ pAccessibleName = NULL;
+ pAccessibleDescription = NULL;
+ }
+
+ ~ImplAccessibleInfos()
+ {
+ delete pAccessibleName;
+ delete pAccessibleDescription;
+ }
+};
+
+// -----------------------------------------------------------------------
+
+WindowImpl::WindowImpl()
+{
+}
+
+WindowImpl::~WindowImpl()
+{
+}
+
+
+// -----------------------------------------------------------------------
+
+// helper method to allow inline constructor even for pWindow!=NULL case
+void ImplDelData::AttachToWindow( const Window* pWindow )
+{
+ if( pWindow )
+ const_cast<Window*>(pWindow)->ImplAddDel( this );
+}
+
+// -----------------------------------------------------------------------
+
+// define dtor for ImplDelData
+ImplDelData::~ImplDelData()
+{
+ // #112873# auto remove of ImplDelData
+ // due to this code actively calling ImplRemoveDel() is not mandatory anymore
+ if( !mbDel && mpWindow )
+ {
+ // the window still exists but we were not removed
+ const_cast<Window*>(mpWindow)->ImplRemoveDel( this );
+ mpWindow = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+const char* ImplDbgCheckWindow( const void* pObj )
+{
+ DBG_TESTSOLARMUTEX();
+
+ const Window* pWindow = (Window*)pObj;
+
+ if ( (pWindow->GetType() < WINDOW_FIRST) || (pWindow->GetType() > WINDOW_LAST) )
+ return "Window data overwrite";
+
+ // Fenster-Verkettung ueberpruefen
+ Window* pChild = pWindow->mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ if ( pChild->mpWindowImpl->mpParent != pWindow )
+ return "Child-Window-Parent wrong";
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+
+ return NULL;
+}
+#endif
+
+// =======================================================================
+
+void Window::ImplInitAppFontData( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ long nTextHeight = pWindow->GetTextHeight();
+ long nTextWidth = pWindow->GetTextWidth( XubString( RTL_CONSTASCII_USTRINGPARAM( "aemnnxEM" ) ) );
+ long nSymHeight = nTextHeight*4;
+ // Falls Font zu schmal ist, machen wir die Basis breiter,
+ // damit die Dialoge symetrisch aussehen und nicht zu schmal
+ // werden. Wenn der Dialog die gleiche breite hat, geben wir
+ // noch etwas Spielraum dazu, da etwas mehr Platz besser ist.
+ if ( nSymHeight > nTextWidth )
+ nTextWidth = nSymHeight;
+ else if ( nSymHeight+5 > nTextWidth )
+ nTextWidth = nSymHeight+5;
+ pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8;
+ pSVData->maGDIData.mnAppFontY = nTextHeight * 10;
+
+ // FIXME: this is currently only on aqua, check with other
+ // platforms
+ if( pSVData->maNWFData.mbNoFocusRects )
+ {
+ // try to find out wether there is a large correction
+ // of control sizes, if yes, make app font scalings larger
+ // so dialog positioning is not completely off
+ ImplControlValue aControlValue;
+ Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) );
+ Rectangle aBoundingRgn( aCtrlRegion );
+ Rectangle aContentRgn( aCtrlRegion );
+ if( pWindow->GetNativeControlRegion( CTRL_EDITBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
+ CTRL_STATE_ENABLED, aControlValue, rtl::OUString(),
+ aBoundingRgn, aContentRgn ) )
+ {
+ // comment: the magical +6 is for the extra border in bordered
+ // (which is the standard) edit fields
+ if( aContentRgn.GetHeight() - nTextHeight > (nTextHeight+4)/4 )
+ pSVData->maGDIData.mnAppFontY = (aContentRgn.GetHeight()-4) * 10;
+ }
+ }
+
+
+ pSVData->maGDIData.mnRealAppFontX = pSVData->maGDIData.mnAppFontX;
+ if ( pSVData->maAppData.mnDialogScaleX )
+ pSVData->maGDIData.mnAppFontX += (pSVData->maGDIData.mnAppFontX*pSVData->maAppData.mnDialogScaleX)/100;
+}
+
+// -----------------------------------------------------------------------
+
+bool Window::ImplCheckUIFont( const Font& rFont )
+{
+ if( ImplGetSVData()->maGDIData.mbNativeFontConfig )
+ return true;
+
+ String aTestText;
+ aTestText.Append( Button::GetStandardText( BUTTON_OK ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_CANCEL ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_YES ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_NO ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_RETRY ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_HELP ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_CLOSE ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_MORE ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_LESS ) );
+ aTestText.Append( Button::GetStandardText( BUTTON_ABORT ) );
+
+ return HasGlyphs( rFont, aTestText ) >= aTestText.Len();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateGlobalSettings( AllSettings& rSettings, BOOL bCallHdl )
+{
+ // reset high contrast to false, so the system can either update it
+ // or AutoDetectSystemHC can kick in (see below)
+ StyleSettings aTmpSt( rSettings.GetStyleSettings() );
+ aTmpSt.SetHighContrastMode( FALSE );
+ rSettings.SetStyleSettings( aTmpSt );
+ ImplGetFrame()->UpdateSettings( rSettings );
+
+ // Verify availability of the configured UI font, otherwise choose "Andale Sans UI"
+ String aUserInterfaceFont;
+ bool bUseSystemFont = rSettings.GetStyleSettings().GetUseSystemUIFonts();
+
+ // check whether system UI font can display a typical UI text
+ if( bUseSystemFont )
+ bUseSystemFont = ImplCheckUIFont( rSettings.GetStyleSettings().GetAppFont() );
+
+ if ( !bUseSystemFont )
+ {
+ ImplInitFontList();
+ String aConfigFont = utl::DefaultFontConfiguration::get()->getUserInterfaceFont( rSettings.GetUILocale() );
+ xub_StrLen nIndex = 0;
+ while( nIndex != STRING_NOTFOUND )
+ {
+ String aName( aConfigFont.GetToken( 0, ';', nIndex ) );
+ if ( aName.Len() && mpWindowImpl->mpFrameData->mpFontList->FindFontFamily( aName ) )
+ {
+ aUserInterfaceFont = aConfigFont;
+ break;
+ }
+ }
+
+ if ( ! aUserInterfaceFont.Len() )
+ {
+ String aFallbackFont (RTL_CONSTASCII_USTRINGPARAM( "Andale Sans UI" ));
+ if ( mpWindowImpl->mpFrameData->mpFontList->FindFontFamily( aFallbackFont ) )
+ aUserInterfaceFont = aFallbackFont;
+ }
+ }
+
+ if ( !bUseSystemFont && aUserInterfaceFont.Len() )
+ {
+ StyleSettings aStyleSettings = rSettings.GetStyleSettings();
+ Font aFont = aStyleSettings.GetAppFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetAppFont( aFont );
+ aFont = aStyleSettings.GetHelpFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetHelpFont( aFont );
+ aFont = aStyleSettings.GetTitleFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetTitleFont( aFont );
+ aFont = aStyleSettings.GetFloatTitleFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetFloatTitleFont( aFont );
+ aFont = aStyleSettings.GetMenuFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetMenuFont( aFont );
+ aFont = aStyleSettings.GetToolFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetToolFont( aFont );
+ aFont = aStyleSettings.GetLabelFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetLabelFont( aFont );
+ aFont = aStyleSettings.GetInfoFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetInfoFont( aFont );
+ aFont = aStyleSettings.GetRadioCheckFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetRadioCheckFont( aFont );
+ aFont = aStyleSettings.GetPushButtonFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetPushButtonFont( aFont );
+ aFont = aStyleSettings.GetFieldFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetFieldFont( aFont );
+ aFont = aStyleSettings.GetIconFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetIconFont( aFont );
+ aFont = aStyleSettings.GetGroupFont();
+ aFont.SetName( aUserInterfaceFont );
+ aStyleSettings.SetGroupFont( aFont );
+ rSettings.SetStyleSettings( aStyleSettings );
+ }
+
+ StyleSettings aStyleSettings = rSettings.GetStyleSettings();
+ // #97047: Force all fonts except Menu and Help to a fixed height
+ // to avoid UI scaling due to large fonts
+ // - but allow bigger fonts on bigger screens (i16682, i21238)
+ // dialogs were designed to fit 800x600 with an 8pt font, so scale accordingly
+ int maxFontheight = 9; // #107886#: 9 is default for some asian systems, so always allow if requested
+ if( GetDesktopRectPixel().getHeight() > 600 )
+ maxFontheight = (int) ((( 8.0 * (double) GetDesktopRectPixel().getHeight()) / 600.0) + 1.5);
+
+ Font aFont = aStyleSettings.GetMenuFont();
+ int defFontheight = aFont.GetHeight();
+ if( defFontheight > maxFontheight )
+ defFontheight = maxFontheight;
+
+ // if the UI is korean, chinese or another locale
+ // where the system font size is kown to be often too small to
+ // generate readable fonts enforce a minimum font size of 9 points
+ bool bBrokenLangFontHeight = false;
+ static const LanguageType eBrokenSystemFontSizeLanguages[] =
+ { LANGUAGE_KOREAN, LANGUAGE_KOREAN_JOHAB,
+ LANGUAGE_CHINESE_HONGKONG, LANGUAGE_CHINESE_MACAU, LANGUAGE_CHINESE_SIMPLIFIED, LANGUAGE_CHINESE_SINGAPORE, LANGUAGE_CHINESE_TRADITIONAL
+ };
+ static std::set< LanguageType > aBrokenSystemFontSizeLanguagesSet(
+ eBrokenSystemFontSizeLanguages,
+ eBrokenSystemFontSizeLanguages +
+ (sizeof(eBrokenSystemFontSizeLanguages)/sizeof(eBrokenSystemFontSizeLanguages[0]))
+ );
+ LanguageType aLang = Application::GetSettings().GetUILanguage();
+ if( aBrokenSystemFontSizeLanguagesSet.find( aLang ) != aBrokenSystemFontSizeLanguagesSet.end() )
+ {
+ defFontheight = Max(9, defFontheight);
+ bBrokenLangFontHeight = true;
+ }
+
+ // i22098, toolfont will be scaled differently to avoid bloated rulers and status bars for big fonts
+ int toolfontheight = defFontheight;
+ if( toolfontheight > 9 )
+ toolfontheight = (defFontheight+8) / 2;
+
+ aFont = aStyleSettings.GetAppFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetAppFont( aFont );
+ aFont = aStyleSettings.GetTitleFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetTitleFont( aFont );
+ aFont = aStyleSettings.GetFloatTitleFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetFloatTitleFont( aFont );
+ // keep menu and help font size from system unless in broken locale size
+ if( bBrokenLangFontHeight )
+ {
+ aFont = aStyleSettings.GetMenuFont();
+ if( aFont.GetHeight() < defFontheight )
+ {
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetMenuFont( aFont );
+ }
+ aFont = aStyleSettings.GetHelpFont();
+ if( aFont.GetHeight() < defFontheight )
+ {
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetHelpFont( aFont );
+ }
+ }
+
+ // use different height for toolfont
+ aFont = aStyleSettings.GetToolFont();
+ aFont.SetHeight( toolfontheight );
+ aStyleSettings.SetToolFont( aFont );
+
+ aFont = aStyleSettings.GetLabelFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetLabelFont( aFont );
+ aFont = aStyleSettings.GetInfoFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetInfoFont( aFont );
+ aFont = aStyleSettings.GetRadioCheckFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetRadioCheckFont( aFont );
+ aFont = aStyleSettings.GetPushButtonFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetPushButtonFont( aFont );
+ aFont = aStyleSettings.GetFieldFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetFieldFont( aFont );
+ aFont = aStyleSettings.GetIconFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetIconFont( aFont );
+ aFont = aStyleSettings.GetGroupFont();
+ aFont.SetHeight( defFontheight );
+ aStyleSettings.SetGroupFont( aFont );
+
+ // set workspace gradient to black in dark themes
+ if( aStyleSettings.GetWindowColor().IsDark() )
+ aStyleSettings.SetWorkspaceGradient( Wallpaper( Color( COL_BLACK ) ) );
+ else
+ {
+ Gradient aGrad( GRADIENT_LINEAR, DEFAULT_WORKSPACE_GRADIENT_START_COLOR, DEFAULT_WORKSPACE_GRADIENT_END_COLOR );
+ aStyleSettings.SetWorkspaceGradient( Wallpaper( aGrad ) );
+ }
+
+ rSettings.SetStyleSettings( aStyleSettings );
+
+
+ // auto detect HC mode; if the system already set it to "yes"
+ // (see above) then accept that
+ if( !rSettings.GetStyleSettings().GetHighContrastMode() )
+ {
+ sal_Bool bTmp = sal_False, bAutoHCMode = sal_True;
+ utl::OConfigurationNode aNode = utl::OConfigurationTreeRoot::tryCreateWithServiceFactory(
+ vcl::unohelper::GetMultiServiceFactory(),
+ OUString::createFromAscii( "org.openoffice.Office.Common/Accessibility" ) ); // note: case sensisitive !
+ if ( aNode.isValid() )
+ {
+ ::com::sun::star::uno::Any aValue = aNode.getNodeValue( OUString::createFromAscii( "AutoDetectSystemHC" ) );
+ if( aValue >>= bTmp )
+ bAutoHCMode = bTmp;
+ }
+ if( bAutoHCMode )
+ {
+ if( rSettings.GetStyleSettings().GetFaceColor().IsDark()
+ || rSettings.GetStyleSettings().GetWindowColor().IsDark() )
+ {
+ aStyleSettings = rSettings.GetStyleSettings();
+ aStyleSettings.SetHighContrastMode( TRUE );
+ rSettings.SetStyleSettings( aStyleSettings );
+ }
+ }
+ }
+
+ static const char* pEnvHC = getenv( "SAL_FORCE_HC" );
+ if( pEnvHC && *pEnvHC )
+ {
+ aStyleSettings.SetHighContrastMode( TRUE );
+ rSettings.SetStyleSettings( aStyleSettings );
+ }
+
+#ifdef DBG_UTIL
+ // Evt. AppFont auf Fett schalten, damit man feststellen kann,
+ // ob fuer die Texte auf anderen Systemen genuegend Platz
+ // vorhanden ist
+ if ( DbgIsBoldAppFont() )
+ {
+ aStyleSettings = rSettings.GetStyleSettings();
+ aFont = aStyleSettings.GetAppFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetAppFont( aFont );
+ aFont = aStyleSettings.GetGroupFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetGroupFont( aFont );
+ aFont = aStyleSettings.GetLabelFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetLabelFont( aFont );
+ aFont = aStyleSettings.GetRadioCheckFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetRadioCheckFont( aFont );
+ aFont = aStyleSettings.GetPushButtonFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetPushButtonFont( aFont );
+ aFont = aStyleSettings.GetFieldFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetFieldFont( aFont );
+ aFont = aStyleSettings.GetIconFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetIconFont( aFont );
+ rSettings.SetStyleSettings( aStyleSettings );
+ }
+#endif
+
+ if ( bCallHdl )
+ GetpApp()->SystemSettingsChanging( rSettings, this );
+}
+
+// -----------------------------------------------------------------------
+
+MouseEvent ImplTranslateMouseEvent( const MouseEvent& rE, Window* pSource, Window* pDest )
+{
+ Point aPos = pSource->OutputToScreenPixel( rE.GetPosPixel() );
+ aPos = pDest->ScreenToOutputPixel( aPos );
+ return MouseEvent( aPos, rE.GetClicks(), rE.GetMode(), rE.GetButtons(), rE.GetModifier() );
+}
+
+// -----------------------------------------------------------------------
+
+CommandEvent ImplTranslateCommandEvent( const CommandEvent& rCEvt, Window* pSource, Window* pDest )
+{
+ if ( !rCEvt.IsMouseEvent() )
+ return rCEvt;
+
+ Point aPos = pSource->OutputToScreenPixel( rCEvt.GetMousePosPixel() );
+ aPos = pDest->ScreenToOutputPixel( aPos );
+ return CommandEvent( aPos, rCEvt.GetCommand(), rCEvt.IsMouseEvent(), rCEvt.GetData() );
+}
+
+// =======================================================================
+
+void Window::ImplInitWindowData( WindowType nType )
+{
+ mpWindowImpl = new WindowImpl;
+
+ meOutDevType = OUTDEV_WINDOW;
+
+ mpWindowImpl->maZoom = Fraction( 1, 1 );
+ mpWindowImpl->maWinRegion = Region( REGION_NULL );
+ mpWindowImpl->maWinClipRegion = Region( REGION_NULL );
+ mpWindowImpl->mpWinData = NULL; // Extra Window Data, that we dont need for all windows
+ mpWindowImpl->mpOverlapData = NULL; // Overlap Data
+ mpWindowImpl->mpFrameData = NULL; // Frame Data
+ mpWindowImpl->mpFrame = NULL; // Pointer to frame window
+ mpWindowImpl->mpSysObj = NULL;
+ mpWindowImpl->mpFrameWindow = NULL; // window to top level parent (same as frame window)
+ mpWindowImpl->mpOverlapWindow = NULL; // first overlap parent
+ mpWindowImpl->mpBorderWindow = NULL; // Border-Window
+ mpWindowImpl->mpClientWindow = NULL; // Client-Window of a FrameWindow
+ mpWindowImpl->mpParent = NULL; // parent (inkl. BorderWindow)
+ mpWindowImpl->mpRealParent = NULL; // real parent (exkl. BorderWindow)
+ mpWindowImpl->mpFirstChild = NULL; // first child window
+ mpWindowImpl->mpLastChild = NULL; // last child window
+ mpWindowImpl->mpFirstOverlap = NULL; // first overlap window (only set in overlap windows)
+ mpWindowImpl->mpLastOverlap = NULL; // last overlap window (only set in overlap windows)
+ mpWindowImpl->mpPrev = NULL; // prev window
+ mpWindowImpl->mpNext = NULL; // next window
+ mpWindowImpl->mpNextOverlap = NULL; // next overlap window of frame
+ mpWindowImpl->mpLastFocusWindow = NULL; // window for focus restore
+ mpWindowImpl->mpDlgCtrlDownWindow = NULL; // window for dialog control
+ mpWindowImpl->mpFirstDel = NULL; // Dtor notification list
+ mpWindowImpl->mpUserData = NULL; // user data
+ mpWindowImpl->mpCursor = NULL; // cursor
+ mpWindowImpl->mpControlFont = NULL; // font propertie
+ mpWindowImpl->mpVCLXWindow = NULL;
+ mpWindowImpl->mpAccessibleInfos = NULL;
+ mpWindowImpl->maControlForeground = Color( COL_TRANSPARENT ); // kein Foreground gesetzt
+ mpWindowImpl->maControlBackground = Color( COL_TRANSPARENT ); // kein Background gesetzt
+ mpWindowImpl->mnLeftBorder = 0; // left border
+ mpWindowImpl->mnTopBorder = 0; // top border
+ mpWindowImpl->mnRightBorder = 0; // right border
+ mpWindowImpl->mnBottomBorder = 0; // bottom border
+ mpWindowImpl->mnX = 0; // X-Position to Parent
+ mpWindowImpl->mnY = 0; // Y-Position to Parent
+ mpWindowImpl->mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning
+ mpWindowImpl->mnHelpId = 0; // help id
+ mpWindowImpl->mnUniqId = 0; // unique id
+ mpWindowImpl->mpChildClipRegion = NULL; // Child-Clip-Region when ClipChildren
+ mpWindowImpl->mpPaintRegion = NULL; // Paint-ClipRegion
+ mpWindowImpl->mnStyle = 0; // style (init in ImplInitWindow)
+ mpWindowImpl->mnPrevStyle = 0; // prevstyle (set in SetStyle)
+ mpWindowImpl->mnExtendedStyle = 0; // extended style (init in ImplInitWindow)
+ mpWindowImpl->mnPrevExtendedStyle = 0; // prevstyle (set in SetExtendedStyle)
+ mpWindowImpl->mnType = nType; // type
+ mpWindowImpl->mnGetFocusFlags = 0; // Flags fuer GetFocus()-Aufruf
+ mpWindowImpl->mnWaitCount = 0; // Wait-Count (>1 == Warte-MousePointer)
+ mpWindowImpl->mnPaintFlags = 0; // Flags for ImplCallPaint
+ mpWindowImpl->mnParentClipMode = 0; // Flags for Parent-ClipChildren-Mode
+ mpWindowImpl->mnActivateMode = 0; // Wird bei System/Overlap-Windows umgesetzt
+ mpWindowImpl->mnDlgCtrlFlags = 0; // DialogControl-Flags
+ mpWindowImpl->mnLockCount = 0; // LockCount
+ mpWindowImpl->meAlwaysInputMode = AlwaysInputNone; // neither AlwaysEnableInput nor AlwaysDisableInput called
+ mpWindowImpl->mbFrame = FALSE; // TRUE: Window is a frame window
+ mpWindowImpl->mbBorderWin = FALSE; // TRUE: Window is a border window
+ mpWindowImpl->mbOverlapWin = FALSE; // TRUE: Window is a overlap window
+ mpWindowImpl->mbSysWin = FALSE; // TRUE: SystemWindow is the base class
+ mpWindowImpl->mbDialog = FALSE; // TRUE: Dialog is the base class
+ mpWindowImpl->mbDockWin = FALSE; // TRUE: DockingWindow is the base class
+ mpWindowImpl->mbFloatWin = FALSE; // TRUE: FloatingWindow is the base class
+ mpWindowImpl->mbPushButton = FALSE; // TRUE: PushButton is the base class
+ mpWindowImpl->mbToolBox = FALSE; // TRUE: ToolBox is the base class
+ mpWindowImpl->mbMenuFloatingWindow= FALSE; // TRUE: MenuFloatingWindow is the base class
+ mpWindowImpl->mbToolbarFloatingWindow= FALSE; // TRUE: ImplPopupFloatWin is the base class, used for subtoolbars
+ mpWindowImpl->mbSplitter = FALSE; // TRUE: Splitter is the base class
+ mpWindowImpl->mbVisible = FALSE; // TRUE: Show( TRUE ) called
+ mpWindowImpl->mbOverlapVisible = FALSE; // TRUE: Hide called for visible window from ImplHideAllOverlapWindow()
+ mpWindowImpl->mbDisabled = FALSE; // TRUE: Enable( FALSE ) called
+ mpWindowImpl->mbInputDisabled = FALSE; // TRUE: EnableInput( FALSE ) called
+ mpWindowImpl->mbDropDisabled = FALSE; // TRUE: Drop is enabled
+ mpWindowImpl->mbNoUpdate = FALSE; // TRUE: SetUpdateMode( FALSE ) called
+ mpWindowImpl->mbNoParentUpdate = FALSE; // TRUE: SetParentUpdateMode( FALSE ) called
+ mpWindowImpl->mbActive = FALSE; // TRUE: Window Active
+ mpWindowImpl->mbParentActive = FALSE; // TRUE: OverlapActive from Parent
+ mpWindowImpl->mbReallyVisible = FALSE; // TRUE: this and all parents to an overlaped window are visible
+ mpWindowImpl->mbReallyShown = FALSE; // TRUE: this and all parents to an overlaped window are shown
+ mpWindowImpl->mbInInitShow = FALSE; // TRUE: we are in InitShow
+ mpWindowImpl->mbChildNotify = FALSE; // TRUE: ChildNotify
+ mpWindowImpl->mbChildPtrOverwrite = FALSE; // TRUE: PointerStyle overwrites Child-Pointer
+ mpWindowImpl->mbNoPtrVisible = FALSE; // TRUE: ShowPointer( FALSE ) called
+ mpWindowImpl->mbMouseMove = FALSE; // TRUE: BaseMouseMove called
+ mpWindowImpl->mbPaintFrame = FALSE; // TRUE: Paint is visible, but not painted
+ mpWindowImpl->mbInPaint = FALSE; // TRUE: Inside PaintHdl
+ mpWindowImpl->mbMouseButtonDown = FALSE; // TRUE: BaseMouseButtonDown called
+ mpWindowImpl->mbMouseButtonUp = FALSE; // TRUE: BaseMouseButtonUp called
+ mpWindowImpl->mbKeyInput = FALSE; // TRUE: BaseKeyInput called
+ mpWindowImpl->mbKeyUp = FALSE; // TRUE: BaseKeyUp called
+ mpWindowImpl->mbCommand = FALSE; // TRUE: BaseCommand called
+ mpWindowImpl->mbDefPos = TRUE; // TRUE: Position is not Set
+ mpWindowImpl->mbDefSize = TRUE; // TRUE: Size is not Set
+ mpWindowImpl->mbCallMove = TRUE; // TRUE: Move must be called by Show
+ mpWindowImpl->mbCallResize = TRUE; // TRUE: Resize must be called by Show
+ mpWindowImpl->mbWaitSystemResize = TRUE; // TRUE: Wait for System-Resize
+ mpWindowImpl->mbInitWinClipRegion = TRUE; // TRUE: Calc Window Clip Region
+ mpWindowImpl->mbInitChildRegion = FALSE; // TRUE: InitChildClipRegion
+ mpWindowImpl->mbWinRegion = FALSE; // TRUE: Window Region
+ mpWindowImpl->mbClipChildren = FALSE; // TRUE: Child-Fenster muessen evt. geclippt werden
+ mpWindowImpl->mbClipSiblings = FALSE; // TRUE: Nebeneinanderliegende Child-Fenster muessen evt. geclippt werden
+ mpWindowImpl->mbChildTransparent = FALSE; // TRUE: Child-Fenster duerfen transparent einschalten (inkl. Parent-CLIPCHILDREN)
+ mpWindowImpl->mbPaintTransparent = FALSE; // TRUE: Paints muessen auf Parent ausgeloest werden
+ mpWindowImpl->mbMouseTransparent = FALSE; // TRUE: Window is transparent for Mouse
+ mpWindowImpl->mbDlgCtrlStart = FALSE; // TRUE: Ab hier eigenes Dialog-Control
+ mpWindowImpl->mbFocusVisible = FALSE; // TRUE: Focus Visible
+ mpWindowImpl->mbUseNativeFocus = FALSE;
+ mpWindowImpl->mbNativeFocusVisible= FALSE; // TRUE: native Focus Visible
+ mpWindowImpl->mbInShowFocus = FALSE; // prevent recursion
+ mpWindowImpl->mbInHideFocus = FALSE; // prevent recursion
+ mpWindowImpl->mbTrackVisible = FALSE; // TRUE: Tracking Visible
+ mpWindowImpl->mbControlForeground = FALSE; // TRUE: Foreground-Property set
+ mpWindowImpl->mbControlBackground = FALSE; // TRUE: Background-Property set
+ mpWindowImpl->mbAlwaysOnTop = FALSE; // TRUE: immer vor allen anderen normalen Fenstern sichtbar
+ mpWindowImpl->mbCompoundControl = FALSE; // TRUE: Zusammengesetztes Control => Listener...
+ mpWindowImpl->mbCompoundControlHasFocus = FALSE; // TRUE: Zusammengesetztes Control hat irgendwo den Focus
+ mpWindowImpl->mbPaintDisabled = FALSE; // TRUE: Paint soll nicht ausgefuehrt werden
+ mpWindowImpl->mbAllResize = FALSE; // TRUE: Auch ResizeEvents mit 0,0 schicken
+ mpWindowImpl->mbInDtor = FALSE; // TRUE: Wir befinden uns im Window-Dtor
+ mpWindowImpl->mbExtTextInput = FALSE; // TRUE: ExtTextInput-Mode is active
+ mpWindowImpl->mbInFocusHdl = FALSE; // TRUE: Innerhalb vom GetFocus-Handler
+ mpWindowImpl->mbCreatedWithToolkit = FALSE;
+ mpWindowImpl->mbSuppressAccessibilityEvents = FALSE; // TRUE: do not send any accessibility events
+ mpWindowImpl->mbDrawSelectionBackground = FALSE; // TRUE: draws transparent window background to indicate (toolbox) selection
+ mpWindowImpl->mbIsInTaskPaneList = FALSE; // TRUE: window was added to the taskpanelist in the topmost system window
+ mpWindowImpl->mnNativeBackground = 0; // initialize later, depends on type
+ mpWindowImpl->mbCallHandlersDuringInputDisabled = FALSE; // TRUE: call event handlers even if input is disabled
+ mpWindowImpl->mbDisableAccessibleLabelForRelation = FALSE; // TRUE: do not set LabelFor relation on accessible objects
+ mpWindowImpl->mbDisableAccessibleLabeledByRelation = FALSE; // TRUE: do not set LabeledBy relation on accessible objects
+ mpWindowImpl->mbHelpTextDynamic = FALSE; // TRUE: append help id in HELP_DEBUG case
+ mpWindowImpl->mbFakeFocusSet = FALSE; // TRUE: pretend as if the window has focus.
+
+ mbEnableRTL = Application::GetSettings().GetLayoutRTL(); // TRUE: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInit( Window* pParent, WinBits nStyle, const ::com::sun::star::uno::Any& /*aSystemWorkWindowToken*/ )
+{
+ ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
+{
+ DBG_ASSERT( mpWindowImpl->mbFrame || pParent, "Window::Window(): pParent == NULL" );
+
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pRealParent = pParent;
+
+ // 3D-Look vererben
+ if ( !mpWindowImpl->mbOverlapWin && pParent && (pParent->GetStyle() & WB_3DLOOK) )
+ nStyle |= WB_3DLOOK;
+
+ // create border window if necessary
+ if ( !mpWindowImpl->mbFrame && !mpWindowImpl->mbBorderWin && !mpWindowImpl->mpBorderWindow
+ && (nStyle & (WB_BORDER | WB_SYSTEMCHILDWINDOW) ) )
+ {
+ USHORT nBorderTypeStyle = 0;
+ if( (nStyle & WB_SYSTEMCHILDWINDOW) )
+ {
+ // handle WB_SYSTEMCHILDWINDOW
+ // these should be analogous to a top level frame; meaning they
+ // should have a border window with style BORDERWINDOW_STYLE_FRAME
+ // which controls their size
+ nBorderTypeStyle |= BORDERWINDOW_STYLE_FRAME;
+ nStyle |= WB_BORDER;
+ }
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_NEEDSFOCUS), nBorderTypeStyle );
+ ((Window*)pBorderWin)->mpWindowImpl->mpClientWindow = this;
+ pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ mpWindowImpl->mpBorderWindow = pBorderWin;
+ pParent = mpWindowImpl->mpBorderWindow;
+ }
+ else if( !mpWindowImpl->mbFrame && ! pParent )
+ {
+ mpWindowImpl->mbOverlapWin = TRUE;
+ mpWindowImpl->mbFrame = TRUE;
+ }
+
+ // insert window in list
+ ImplInsertWindow( pParent );
+ mpWindowImpl->mnStyle = nStyle;
+
+ // Overlap-Window-Daten
+ if ( mpWindowImpl->mbOverlapWin )
+ {
+ mpWindowImpl->mpOverlapData = new ImplOverlapData;
+ mpWindowImpl->mpOverlapData->mpSaveBackDev = NULL;
+ mpWindowImpl->mpOverlapData->mpSaveBackRgn = NULL;
+ mpWindowImpl->mpOverlapData->mpNextBackWin = NULL;
+ mpWindowImpl->mpOverlapData->mnSaveBackSize = 0;
+ mpWindowImpl->mpOverlapData->mbSaveBack = FALSE;
+ mpWindowImpl->mpOverlapData->mnTopLevel = 1;
+ }
+
+ if( pParent && ! mpWindowImpl->mbFrame )
+ mbEnableRTL = pParent->mbEnableRTL;
+
+ // test for frame creation
+ if ( mpWindowImpl->mbFrame )
+ {
+ // create frame
+ ULONG nFrameStyle = 0;
+
+ if ( nStyle & WB_MOVEABLE )
+ nFrameStyle |= SAL_FRAME_STYLE_MOVEABLE;
+ if ( nStyle & WB_SIZEABLE )
+ nFrameStyle |= SAL_FRAME_STYLE_SIZEABLE;
+ if ( nStyle & WB_CLOSEABLE )
+ nFrameStyle |= SAL_FRAME_STYLE_CLOSEABLE;
+ if ( nStyle & WB_APP )
+ nFrameStyle |= SAL_FRAME_STYLE_DEFAULT;
+ // check for undecorated floating window
+ if( // 1. floating windows that are not moveable/sizeable (only closeable allowed)
+ ( !(nFrameStyle & ~SAL_FRAME_STYLE_CLOSEABLE) &&
+ ( mpWindowImpl->mbFloatWin || ((GetType() == WINDOW_BORDERWINDOW) && ((ImplBorderWindow*)this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) ||
+ // 2. borderwindows of floaters with ownerdraw decoration
+ ( ((GetType() == WINDOW_BORDERWINDOW) && ((ImplBorderWindow*)this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) ) )
+ {
+ nFrameStyle = SAL_FRAME_STYLE_FLOAT;
+ if( nStyle & WB_OWNERDRAWDECORATION )
+ nFrameStyle |= (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_NOSHADOW);
+ if( nStyle & WB_NEEDSFOCUS )
+ nFrameStyle |= SAL_FRAME_STYLE_FLOAT_FOCUSABLE;
+ }
+ else if( mpWindowImpl->mbFloatWin )
+ nFrameStyle |= SAL_FRAME_STYLE_TOOLWINDOW;
+
+ if( nStyle & WB_INTROWIN )
+ nFrameStyle |= SAL_FRAME_STYLE_INTRO;
+ if( nStyle & WB_TOOLTIPWIN )
+ nFrameStyle |= SAL_FRAME_STYLE_TOOLTIP;
+
+ if( nStyle & WB_NOSHADOW )
+ nFrameStyle |= SAL_FRAME_STYLE_NOSHADOW;
+
+ if( nStyle & WB_SYSTEMCHILDWINDOW )
+ nFrameStyle |= SAL_FRAME_STYLE_SYSTEMCHILD;
+
+ switch (mpWindowImpl->mnType)
+ {
+ case WINDOW_DIALOG:
+ case WINDOW_TABDIALOG:
+ case WINDOW_MODALDIALOG:
+ case WINDOW_MODELESSDIALOG:
+ case WINDOW_MESSBOX:
+ case WINDOW_INFOBOX:
+ case WINDOW_WARNINGBOX:
+ case WINDOW_ERRORBOX:
+ case WINDOW_QUERYBOX:
+ nFrameStyle |= SAL_FRAME_STYLE_DIALOG;
+ default:
+ break;
+ }
+
+ SalFrame* pParentFrame = NULL;
+ if ( pParent )
+ pParentFrame = pParent->mpWindowImpl->mpFrame;
+ SalFrame* pFrame;
+ if ( pSystemParentData )
+ pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SAL_FRAME_STYLE_PLUG );
+ else
+ pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle );
+ if ( !pFrame )
+ {
+ // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
+ throw ::com::sun::star::uno::RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not create system window!" ) ),
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
+ //GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
+ }
+
+ pFrame->SetCallback( this, ImplWindowFrameProc );
+
+ // set window frame data
+ mpWindowImpl->mpFrameData = new ImplFrameData;
+ mpWindowImpl->mpFrame = pFrame;
+ mpWindowImpl->mpFrameWindow = this;
+ mpWindowImpl->mpOverlapWindow = this;
+
+ // set frame data
+ mpWindowImpl->mpFrameData->mpNextFrame = pSVData->maWinData.mpFirstFrame;
+ pSVData->maWinData.mpFirstFrame = this;
+ mpWindowImpl->mpFrameData->mpFirstOverlap = NULL;
+ mpWindowImpl->mpFrameData->mpFocusWin = NULL;
+ mpWindowImpl->mpFrameData->mpMouseMoveWin = NULL;
+ mpWindowImpl->mpFrameData->mpMouseDownWin = NULL;
+ mpWindowImpl->mpFrameData->mpFirstBackWin = NULL;
+ mpWindowImpl->mpFrameData->mpFontList = pSVData->maGDIData.mpScreenFontList;
+ mpWindowImpl->mpFrameData->mpFontCache = pSVData->maGDIData.mpScreenFontCache;
+ mpWindowImpl->mpFrameData->mnAllSaveBackSize = 0;
+ mpWindowImpl->mpFrameData->mnFocusId = 0;
+ mpWindowImpl->mpFrameData->mnMouseMoveId = 0;
+ mpWindowImpl->mpFrameData->mnLastMouseX = -1;
+ mpWindowImpl->mpFrameData->mnLastMouseY = -1;
+ mpWindowImpl->mpFrameData->mnBeforeLastMouseX = -1;
+ mpWindowImpl->mpFrameData->mnBeforeLastMouseY = -1;
+ mpWindowImpl->mpFrameData->mnFirstMouseX = -1;
+ mpWindowImpl->mpFrameData->mnFirstMouseY = -1;
+ mpWindowImpl->mpFrameData->mnLastMouseWinX = -1;
+ mpWindowImpl->mpFrameData->mnLastMouseWinY = -1;
+ mpWindowImpl->mpFrameData->mnModalMode = 0;
+ mpWindowImpl->mpFrameData->mnMouseDownTime = 0;
+ mpWindowImpl->mpFrameData->mnClickCount = 0;
+ mpWindowImpl->mpFrameData->mnFirstMouseCode = 0;
+ mpWindowImpl->mpFrameData->mnMouseCode = 0;
+ mpWindowImpl->mpFrameData->mnMouseMode = 0;
+ mpWindowImpl->mpFrameData->meMapUnit = MAP_PIXEL;
+ mpWindowImpl->mpFrameData->mbHasFocus = FALSE;
+ mpWindowImpl->mpFrameData->mbInMouseMove = FALSE;
+ mpWindowImpl->mpFrameData->mbMouseIn = FALSE;
+ mpWindowImpl->mpFrameData->mbStartDragCalled = FALSE;
+ mpWindowImpl->mpFrameData->mbNeedSysWindow = FALSE;
+ mpWindowImpl->mpFrameData->mbMinimized = FALSE;
+ mpWindowImpl->mpFrameData->mbStartFocusState = FALSE;
+ mpWindowImpl->mpFrameData->mbInSysObjFocusHdl = FALSE;
+ mpWindowImpl->mpFrameData->mbInSysObjToTopHdl = FALSE;
+ mpWindowImpl->mpFrameData->mbSysObjFocus = FALSE;
+ mpWindowImpl->mpFrameData->maPaintTimer.SetTimeout( 30 );
+ mpWindowImpl->mpFrameData->maPaintTimer.SetTimeoutHdl( LINK( this, Window, ImplHandlePaintHdl ) );
+ mpWindowImpl->mpFrameData->maResizeTimer.SetTimeout( 50 );
+ mpWindowImpl->mpFrameData->maResizeTimer.SetTimeoutHdl( LINK( this, Window, ImplHandleResizeTimerHdl ) );
+ mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = FALSE;
+
+ if ( pRealParent && IsTopWindow() )
+ {
+ ImplWinData* pParentWinData = pRealParent->ImplGetWinData();
+ pParentWinData->maTopWindowChildren.push_back( this );
+ }
+ }
+
+ // init data
+ mpWindowImpl->mpRealParent = pRealParent;
+
+ // #99318: make sure fontcache and list is available before call to SetSettings
+ mpFontList = mpWindowImpl->mpFrameData->mpFontList;
+ mpFontCache = mpWindowImpl->mpFrameData->mpFontCache;
+
+ if ( mpWindowImpl->mbFrame )
+ {
+ if ( pParent )
+ {
+ mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
+ mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
+ }
+ else
+ {
+ if ( ImplGetGraphics() )
+ {
+ mpGraphics->GetResolution( mpWindowImpl->mpFrameData->mnDPIX, mpWindowImpl->mpFrameData->mnDPIY );
+ }
+ }
+
+ // add ownerdraw decorated frame windows to list in the top-most frame window
+ // so they can be hidden on lose focus
+ if( nStyle & WB_OWNERDRAWDECORATION )
+ ImplGetOwnerDrawList().push_back( this );
+
+ // delay settings initialization until first "real" frame
+ // this relies on the IntroWindow not needing any system settings
+ if ( !pSVData->maAppData.mbSettingsInit &&
+ ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN))
+ )
+ {
+ // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
+ ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
+ OutputDevice::SetSettings( *pSVData->maAppData.mpSettings );
+ pSVData->maAppData.mbSettingsInit = TRUE;
+ }
+
+ // If we create a Window with default size, query this
+ // size directly, because we want resize all Controls to
+ // the correct size before we display the window
+ if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) )
+ mpWindowImpl->mpFrame->GetClientSize( mnOutWidth, mnOutHeight );
+ }
+ else
+ {
+ if ( pParent )
+ {
+ if ( !ImplIsOverlapWindow() )
+ {
+ mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled;
+ mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled;
+ mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode;
+ }
+
+ OutputDevice::SetSettings( pParent->GetSettings() );
+ }
+
+ }
+
+ const StyleSettings& rStyleSettings = maSettings.GetStyleSettings();
+ USHORT nScreenZoom = rStyleSettings.GetScreenZoom();
+ mnDPIX = (mpWindowImpl->mpFrameData->mnDPIX*nScreenZoom)/100;
+ mnDPIY = (mpWindowImpl->mpFrameData->mnDPIY*nScreenZoom)/100;
+ maFont = rStyleSettings.GetAppFont();
+ ImplPointToLogic( maFont );
+
+ if ( nStyle & WB_3DLOOK )
+ {
+ SetTextColor( rStyleSettings.GetButtonTextColor() );
+ SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
+ }
+ else
+ {
+ SetTextColor( rStyleSettings.GetWindowTextColor() );
+ SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
+ }
+
+ ImplUpdatePos();
+
+ // calculate app font res (except for the Intro Window or the default window)
+ if ( mpWindowImpl->mbFrame && !pSVData->maGDIData.mnAppFontX && ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) )
+ ImplInitAppFontData( this );
+
+ if ( GetAccessibleParentWindow() && GetParent() != Application::GetDefDialogParent() )
+ GetAccessibleParentWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_CHILDCREATED, this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplSetFrameParent( const Window* pParent )
+{
+ Window* pFrameWindow = ImplGetSVData()->maWinData.mpFirstFrame;
+ while( pFrameWindow )
+ {
+ // search all frames that are children of this window
+ // and reparent them
+ if( ImplIsRealParentPath( pFrameWindow ) )
+ {
+ DBG_ASSERT( mpWindowImpl->mpFrame != pFrameWindow->mpWindowImpl->mpFrame, "SetFrameParent to own" );
+ DBG_ASSERT( mpWindowImpl->mpFrame, "no frame" );
+ SalFrame* pParentFrame = pParent ? pParent->mpWindowImpl->mpFrame : NULL;
+ pFrameWindow->mpWindowImpl->mpFrame->SetParent( pParentFrame );
+ }
+ pFrameWindow = pFrameWindow->mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInsertWindow( Window* pParent )
+{
+ mpWindowImpl->mpParent = pParent;
+ mpWindowImpl->mpRealParent = pParent;
+
+ if ( pParent && !mpWindowImpl->mbFrame )
+ {
+ // search frame window and set window frame data
+ Window* pFrameParent = pParent->mpWindowImpl->mpFrameWindow;
+ mpWindowImpl->mpFrameData = pFrameParent->mpWindowImpl->mpFrameData;
+ mpWindowImpl->mpFrame = pFrameParent->mpWindowImpl->mpFrame;
+ mpWindowImpl->mpFrameWindow = pFrameParent;
+ mpWindowImpl->mbFrame = FALSE;
+
+ // search overlap window and insert window in list
+ if ( ImplIsOverlapWindow() )
+ {
+ Window* pFirstOverlapParent = pParent;
+ while ( !pFirstOverlapParent->ImplIsOverlapWindow() )
+ pFirstOverlapParent = pFirstOverlapParent->ImplGetParent();
+ mpWindowImpl->mpOverlapWindow = pFirstOverlapParent;
+
+ mpWindowImpl->mpNextOverlap = mpWindowImpl->mpFrameData->mpFirstOverlap;
+ mpWindowImpl->mpFrameData->mpFirstOverlap = this;
+
+ // Overlap-Windows sind per default die obersten
+ mpWindowImpl->mpNext = pFirstOverlapParent->mpWindowImpl->mpFirstOverlap;
+ pFirstOverlapParent->mpWindowImpl->mpFirstOverlap = this;
+ if ( !pFirstOverlapParent->mpWindowImpl->mpLastOverlap )
+ pFirstOverlapParent->mpWindowImpl->mpLastOverlap = this;
+ else
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
+ }
+ else
+ {
+ if ( pParent->ImplIsOverlapWindow() )
+ mpWindowImpl->mpOverlapWindow = pParent;
+ else
+ mpWindowImpl->mpOverlapWindow = pParent->mpWindowImpl->mpOverlapWindow;
+ mpWindowImpl->mpPrev = pParent->mpWindowImpl->mpLastChild;
+ pParent->mpWindowImpl->mpLastChild = this;
+ if ( !pParent->mpWindowImpl->mpFirstChild )
+ pParent->mpWindowImpl->mpFirstChild = this;
+ else
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplRemoveWindow( BOOL bRemoveFrameData )
+{
+ // Fenster aus den Listen austragen
+ if ( !mpWindowImpl->mbFrame )
+ {
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( mpWindowImpl->mpFrameData->mpFirstOverlap == this )
+ mpWindowImpl->mpFrameData->mpFirstOverlap = mpWindowImpl->mpNextOverlap;
+ else
+ {
+ Window* pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
+ while ( pTempWin->mpWindowImpl->mpNextOverlap != this )
+ pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
+ pTempWin->mpWindowImpl->mpNextOverlap = mpWindowImpl->mpNextOverlap;
+ }
+
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
+ else
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
+ if ( mpWindowImpl->mpNext )
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
+ else
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
+ }
+ else
+ {
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
+ else
+ mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
+ if ( mpWindowImpl->mpNext )
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
+ else
+ mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
+ }
+
+ mpWindowImpl->mpPrev = NULL;
+ mpWindowImpl->mpNext = NULL;
+ }
+
+ if ( bRemoveFrameData )
+ {
+ // Graphic freigeben
+ ImplReleaseGraphics();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallResize()
+{
+ mpWindowImpl->mbCallResize = FALSE;
+
+ if( GetBackground().IsGradient() )
+ Invalidate();
+
+ Resize();
+
+ // #88419# Most classes don't call the base class in Resize() and Move(),
+ // => Call ImpleResize/Move instead of Resize/Move directly...
+ ImplCallEventListeners( VCLEVENT_WINDOW_RESIZE );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallMove()
+{
+ mpWindowImpl->mbCallMove = FALSE;
+
+ if( mpWindowImpl->mbFrame )
+ {
+ // update frame position
+ SalFrame *pParentFrame = NULL;
+ Window *pParent = ImplGetParent();
+ while( pParent )
+ {
+ if( pParent->mpWindowImpl->mpFrame != mpWindowImpl->mpFrame )
+ {
+ pParentFrame = pParent->mpWindowImpl->mpFrame;
+ break;
+ }
+ pParent = pParent->GetParent();
+ }
+
+ SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
+ mpWindowImpl->maPos = Point( g.nX, g.nY );
+ if( pParentFrame )
+ {
+ g = pParentFrame->GetGeometry();
+ mpWindowImpl->maPos -= Point( g.nX, g.nY );
+ }
+ // the client window and and all its subclients have the same position as the borderframe
+ // this is important for floating toolbars where the borderwindow is a floating window
+ // which has another borderwindow (ie the system floating window)
+ Window *pClientWin = mpWindowImpl->mpClientWindow;
+ while( pClientWin )
+ {
+ pClientWin->mpWindowImpl->maPos = mpWindowImpl->maPos;
+ pClientWin = pClientWin->mpWindowImpl->mpClientWindow;
+ }
+ }
+
+ Move();
+
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOVE );
+}
+
+// -----------------------------------------------------------------------
+
+static ULONG ImplAutoHelpID( ResMgr* pResMgr )
+{
+ if ( !Application::IsAutoHelpIdEnabled() )
+ return 0;
+
+ ULONG nHID = 0;
+
+ DBG_ASSERT( pResMgr, "No res mgr for auto help id" );
+ if( ! pResMgr )
+ return 0;
+
+ nHID = pResMgr->GetAutoHelpId();
+
+ return nHID;
+}
+
+// -----------------------------------------------------------------------
+
+WinBits Window::ImplInitRes( const ResId& rResId )
+{
+ GetRes( rResId );
+
+ char* pRes = (char*)GetClassRes();
+ pRes += 8;
+ sal_uInt32 nStyle = (sal_uInt32)GetLongRes( (void*)pRes );
+ rResId.SetWinBits( nStyle );
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplLoadRes( const ResId& rResId )
+{
+ // newer move this line after IncrementRes
+ char* pRes = (char*)GetClassRes();
+ pRes += 12;
+ sal_uInt32 nHelpId = (sal_uInt32)GetLongRes( (void*)pRes );
+ if ( !nHelpId )
+ nHelpId = ImplAutoHelpID( rResId.GetResMgr() );
+ SetHelpId( nHelpId );
+
+ ULONG nObjMask = ReadLongRes();
+
+ // ResourceStyle
+ ULONG nRSStyle = ReadLongRes();
+ // WinBits
+ ReadLongRes();
+ // HelpId
+ ReadLongRes();
+
+ BOOL bPos = FALSE;
+ BOOL bSize = FALSE;
+ Point aPos;
+ Size aSize;
+
+ if ( nObjMask & (WINDOW_XYMAPMODE | WINDOW_X | WINDOW_Y) )
+ {
+ // Groessenangabe aus der Resource verwenden
+ MapUnit ePosMap = MAP_PIXEL;
+
+ bPos = TRUE;
+
+ if ( nObjMask & WINDOW_XYMAPMODE )
+ ePosMap = (MapUnit)ReadLongRes();
+ if ( nObjMask & WINDOW_X )
+ aPos.X() = ImplLogicUnitToPixelX( ReadLongRes(), ePosMap );
+ if ( nObjMask & WINDOW_Y )
+ aPos.Y() = ImplLogicUnitToPixelY( ReadLongRes(), ePosMap );
+ }
+
+ if ( nObjMask & (WINDOW_WHMAPMODE | WINDOW_WIDTH | WINDOW_HEIGHT) )
+ {
+ // Groessenangabe aus der Resource verwenden
+ MapUnit eSizeMap = MAP_PIXEL;
+
+ bSize = TRUE;
+
+ if ( nObjMask & WINDOW_WHMAPMODE )
+ eSizeMap = (MapUnit)ReadLongRes();
+ if ( nObjMask & WINDOW_WIDTH )
+ aSize.Width() = ImplLogicUnitToPixelX( ReadLongRes(), eSizeMap );
+ if ( nObjMask & WINDOW_HEIGHT )
+ aSize.Height() = ImplLogicUnitToPixelY( ReadLongRes(), eSizeMap );
+ }
+
+ // Wegen Optimierung so schlimm aussehend
+ if ( nRSStyle & RSWND_CLIENTSIZE )
+ {
+ if ( bPos )
+ SetPosPixel( aPos );
+ if ( bSize )
+ SetOutputSizePixel( aSize );
+ }
+ else if ( bPos && bSize )
+ SetPosSizePixel( aPos, aSize );
+ else if ( bPos )
+ SetPosPixel( aPos );
+ else if ( bSize )
+ SetSizePixel( aSize );
+
+ if ( nRSStyle & RSWND_DISABLED )
+ Enable( FALSE );
+
+ if ( nObjMask & WINDOW_TEXT )
+ SetText( ReadStringRes() );
+ if ( nObjMask & WINDOW_HELPTEXT )
+ {
+ SetHelpText( ReadStringRes() );
+ mpWindowImpl->mbHelpTextDynamic = TRUE;
+ }
+ if ( nObjMask & WINDOW_QUICKTEXT )
+ SetQuickHelpText( ReadStringRes() );
+ if ( nObjMask & WINDOW_EXTRALONG )
+ SetData( (void*)ReadLongRes() );
+ if ( nObjMask & WINDOW_UNIQUEID )
+ SetUniqueId( (ULONG)ReadLongRes() );
+
+ if ( nObjMask & WINDOW_BORDER_STYLE )
+ {
+ USHORT nBorderStyle = (USHORT)ReadLongRes();
+ SetBorderStyle( nBorderStyle );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplWinData* Window::ImplGetWinData() const
+{
+ if ( !mpWindowImpl->mpWinData )
+ {
+ static const char* pNoNWF = getenv( "SAL_NO_NWF" );
+
+ ((Window*)this)->mpWindowImpl->mpWinData = new ImplWinData;
+ mpWindowImpl->mpWinData->mpExtOldText = NULL;
+ mpWindowImpl->mpWinData->mpExtOldAttrAry = NULL;
+ mpWindowImpl->mpWinData->mpCursorRect = 0;
+ mpWindowImpl->mpWinData->mnCursorExtWidth = 0;
+ mpWindowImpl->mpWinData->mpFocusRect = NULL;
+ mpWindowImpl->mpWinData->mpTrackRect = NULL;
+ mpWindowImpl->mpWinData->mnTrackFlags = 0;
+ mpWindowImpl->mpWinData->mnIsTopWindow = (USHORT) ~0; // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
+ mpWindowImpl->mpWinData->mbMouseOver = FALSE;
+ mpWindowImpl->mpWinData->mbEnableNativeWidget = (pNoNWF && *pNoNWF) ? FALSE : TRUE; // TRUE: try to draw this control with native theme API
+ mpWindowImpl->mpWinData->mpSmartHelpId = NULL;
+ mpWindowImpl->mpWinData->mpSmartUniqueId = NULL;
+ }
+
+ return mpWindowImpl->mpWinData;
+}
+
+// -----------------------------------------------------------------------
+
+SalGraphics* Window::ImplGetFrameGraphics() const
+{
+ if ( mpWindowImpl->mpFrameWindow->mpGraphics )
+ mpWindowImpl->mpFrameWindow->mbInitClipRegion = TRUE;
+ else
+ mpWindowImpl->mpFrameWindow->ImplGetGraphics();
+ mpWindowImpl->mpFrameWindow->mpGraphics->ResetClipRegion();
+ return mpWindowImpl->mpFrameWindow->mpGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::ImplFindWindow( const Point& rFramePos )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Window* pTempWindow;
+ Window* pFindWindow;
+
+ // Zuerst alle ueberlappenden Fenster ueberpruefen
+ pTempWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pTempWindow )
+ {
+ pFindWindow = pTempWindow->ImplFindWindow( rFramePos );
+ if ( pFindWindow )
+ return pFindWindow;
+ pTempWindow = pTempWindow->mpWindowImpl->mpNext;
+ }
+
+ // dann testen wir unser Fenster
+ if ( !mpWindowImpl->mbVisible )
+ return NULL;
+
+ USHORT nHitTest = ImplHitTest( rFramePos );
+ if ( nHitTest & WINDOW_HITTEST_INSIDE )
+ {
+ // und danach gehen wir noch alle Child-Fenster durch
+ pTempWindow = mpWindowImpl->mpFirstChild;
+ while ( pTempWindow )
+ {
+ pFindWindow = pTempWindow->ImplFindWindow( rFramePos );
+ if ( pFindWindow )
+ return pFindWindow;
+ pTempWindow = pTempWindow->mpWindowImpl->mpNext;
+ }
+
+ if ( nHitTest & WINDOW_HITTEST_TRANSPARENT )
+ return NULL;
+ else
+ return this;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::ImplHitTest( const Point& rFramePos )
+{
+ Point aFramePos( rFramePos );
+ if( ImplIsAntiparallel() )
+ {
+ // - RTL - re-mirror frame pos at this window
+ ImplReMirror( aFramePos );
+ }
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ if ( !aRect.IsInside( aFramePos ) )
+ return 0;
+ if ( mpWindowImpl->mbWinRegion )
+ {
+ Point aTempPos = aFramePos;
+ aTempPos.X() -= mnOutOffX;
+ aTempPos.Y() -= mnOutOffY;
+ if ( !mpWindowImpl->maWinRegion.IsInside( aTempPos ) )
+ return 0;
+ }
+
+ USHORT nHitTest = WINDOW_HITTEST_INSIDE;
+ if ( mpWindowImpl->mbMouseTransparent )
+ nHitTest |= WINDOW_HITTEST_TRANSPARENT;
+ return nHitTest;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplIsRealParentPath( const Window* pWindow ) const
+{
+ pWindow = pWindow->GetParent();
+ while ( pWindow )
+ {
+ if ( pWindow == this )
+ return TRUE;
+ pWindow = pWindow->GetParent();
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplIsChild( const Window* pWindow, BOOL bSystemWindow ) const
+{
+ do
+ {
+ if ( !bSystemWindow && pWindow->ImplIsOverlapWindow() )
+ break;
+
+ pWindow = pWindow->ImplGetParent();
+
+ if ( pWindow == this )
+ return TRUE;
+ }
+ while ( pWindow );
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplIsWindowOrChild( const Window* pWindow, BOOL bSystemWindow ) const
+{
+ if ( this == pWindow )
+ return TRUE;
+ return ImplIsChild( pWindow, bSystemWindow );
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::ImplGetSameParent( const Window* pWindow ) const
+{
+ if ( mpWindowImpl->mpFrameWindow != pWindow->mpWindowImpl->mpFrameWindow )
+ return NULL;
+ else
+ {
+ if ( pWindow->ImplIsChild( this ) )
+ return (Window*)pWindow;
+ else
+ {
+ Window* pTestWindow = (Window*)this;
+ while ( (pTestWindow == pWindow) || pTestWindow->ImplIsChild( pWindow ) )
+ pTestWindow = pTestWindow->ImplGetParent();
+ return pTestWindow;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+int Window::ImplTestMousePointerSet()
+{
+ // Wenn Mouse gecaptured ist, dann soll MousePointer umgeschaltet werden
+ if ( IsMouseCaptured() )
+ return TRUE;
+
+ // Wenn sich Mouse ueber dem Fenster befindet, dann soll MousePointer
+ // umgeschaltet werden
+ Rectangle aClientRect( Point( 0, 0 ), GetOutputSizePixel() );
+ if ( aClientRect.IsInside( GetPointerPosPixel() ) )
+ return TRUE;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+PointerStyle Window::ImplGetMousePointer() const
+{
+ PointerStyle ePointerStyle;
+ BOOL bWait = FALSE;
+
+ if ( IsEnabled() && IsInputEnabled() && ! IsInModalMode() )
+ ePointerStyle = GetPointer().GetStyle();
+ else
+ ePointerStyle = POINTER_ARROW;
+
+ const Window* pWindow = this;
+ do
+ {
+ // Wenn Pointer nicht sichtbar, dann wird suche abgebrochen, da
+ // dieser Status nicht ueberschrieben werden darf
+ if ( pWindow->mpWindowImpl->mbNoPtrVisible )
+ return POINTER_NULL;
+
+ if ( !bWait )
+ {
+ if ( pWindow->mpWindowImpl->mnWaitCount )
+ {
+ ePointerStyle = POINTER_WAIT;
+ bWait = TRUE;
+ }
+ else
+ {
+ if ( pWindow->mpWindowImpl->mbChildPtrOverwrite )
+ ePointerStyle = pWindow->GetPointer().GetStyle();
+ }
+ }
+
+ if ( pWindow->ImplIsOverlapWindow() )
+ break;
+
+ pWindow = pWindow->ImplGetParent();
+ }
+ while ( pWindow );
+
+ return ePointerStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplResetReallyVisible()
+{
+ BOOL bBecameReallyInvisible = mpWindowImpl->mbReallyVisible;
+
+ mbDevOutput = FALSE;
+ mpWindowImpl->mbReallyVisible = FALSE;
+ mpWindowImpl->mbReallyShown = FALSE;
+
+ // the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge.
+ // For this, the data member of the event must not be NULL.
+ // Previously, we did this in Window::Show, but there some events got lost in certain situations.
+ // #104887# - 2004-08-10 - fs@openoffice.org
+ if( bBecameReallyInvisible && ImplIsAccessibleCandidate() )
+ ImplCallEventListeners( VCLEVENT_WINDOW_HIDE, this );
+ // TODO. It's kind of a hack that we're re-using the VCLEVENT_WINDOW_HIDE. Normally, we should
+ // introduce another event which explicitly triggers the Accessibility implementations.
+
+ Window* pWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbReallyVisible )
+ pWindow->ImplResetReallyVisible();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+
+ pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbReallyVisible )
+ pWindow->ImplResetReallyVisible();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplSetReallyVisible()
+{
+ // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between
+ // ImplCallInitShow() and ImplSetReallyVisible() when called from Show()
+ // mbReallyShown is a useful indicator
+ if( !mpWindowImpl->mbReallyShown )
+ ImplCallInitShow();
+
+ BOOL bBecameReallyVisible = !mpWindowImpl->mbReallyVisible;
+
+ mbDevOutput = TRUE;
+ mpWindowImpl->mbReallyVisible = TRUE;
+ mpWindowImpl->mbReallyShown = TRUE;
+
+ // the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge.
+ // For this, the data member of the event must not be NULL.
+ // Previously, we did this in Window::Show, but there some events got lost in certain situations. Now
+ // we're doing it when the visibility really changes
+ // #104887# - 2004-08-10 - fs@openoffice.org
+ if( bBecameReallyVisible && ImplIsAccessibleCandidate() )
+ ImplCallEventListeners( VCLEVENT_WINDOW_SHOW, this );
+ // TODO. It's kind of a hack that we're re-using the VCLEVENT_WINDOW_SHOW. Normally, we should
+ // introduce another event which explicitly triggers the Accessibility implementations.
+
+ Window* pWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbVisible )
+ pWindow->ImplSetReallyVisible();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+
+ pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbVisible )
+ pWindow->ImplSetReallyVisible();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallInitShow()
+{
+ mpWindowImpl->mbReallyShown = TRUE;
+ mpWindowImpl->mbInInitShow = TRUE;
+ StateChanged( STATE_CHANGE_INITSHOW );
+ mpWindowImpl->mbInInitShow = FALSE;
+
+ Window* pWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbVisible )
+ pWindow->ImplCallInitShow();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+
+ pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbVisible )
+ pWindow->ImplCallInitShow();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplAddDel( ImplDelData* pDel ) // TODO: make "const" when incompatiblity ok
+{
+ DBG_ASSERT( !pDel->mpWindow, "Window::ImplAddDel(): cannot add ImplDelData twice !" );
+ if( !pDel->mpWindow )
+ {
+ pDel->mpWindow = this; // #112873# store ref to this window, so pDel can remove itself
+ pDel->mpNext = mpWindowImpl->mpFirstDel;
+ mpWindowImpl->mpFirstDel = pDel;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplRemoveDel( ImplDelData* pDel ) // TODO: make "const" when incompatiblity ok
+{
+ pDel->mpWindow = NULL; // #112873# pDel is not associated with a Window anymore
+ if ( mpWindowImpl->mpFirstDel == pDel )
+ mpWindowImpl->mpFirstDel = pDel->mpNext;
+ else
+ {
+ ImplDelData* pData = mpWindowImpl->mpFirstDel;
+ while ( pData->mpNext != pDel )
+ pData = pData->mpNext;
+ pData->mpNext = pDel->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInitResolutionSettings()
+{
+ // AppFont-Aufloesung und DPI-Aufloesung neu berechnen
+ if ( mpWindowImpl->mbFrame )
+ {
+ const StyleSettings& rStyleSettings = maSettings.GetStyleSettings();
+ USHORT nScreenZoom = rStyleSettings.GetScreenZoom();
+ mnDPIX = (mpWindowImpl->mpFrameData->mnDPIX*nScreenZoom)/100;
+ mnDPIY = (mpWindowImpl->mpFrameData->mnDPIY*nScreenZoom)/100;
+ SetPointFont( rStyleSettings.GetAppFont() );
+ }
+ else if ( mpWindowImpl->mpParent )
+ {
+ mnDPIX = mpWindowImpl->mpParent->mnDPIX;
+ mnDPIY = mpWindowImpl->mpParent->mnDPIY;
+ }
+
+ // Vorberechnete Werte fuer logische Einheiten updaten und auch
+ // die entsprechenden Tools dazu
+ if ( IsMapMode() )
+ {
+ MapMode aMapMode = GetMapMode();
+ SetMapMode();
+ SetMapMode( aMapMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplPointToLogic( Font& rFont ) const
+{
+ Size aSize = rFont.GetSize();
+ USHORT nScreenFontZoom = maSettings.GetStyleSettings().GetScreenFontZoom();
+
+ if ( aSize.Width() )
+ {
+ aSize.Width() *= mpWindowImpl->mpFrameData->mnDPIX;
+ aSize.Width() += 72/2;
+ aSize.Width() /= 72;
+ aSize.Width() *= nScreenFontZoom;
+ aSize.Width() /= 100;
+ }
+ aSize.Height() *= mpWindowImpl->mpFrameData->mnDPIY;
+ aSize.Height() += 72/2;
+ aSize.Height() /= 72;
+ aSize.Height() *= nScreenFontZoom;
+ aSize.Height() /= 100;
+
+ if ( IsMapModeEnabled() )
+ aSize = PixelToLogic( aSize );
+
+ rFont.SetSize( aSize );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplLogicToPoint( Font& rFont ) const
+{
+ Size aSize = rFont.GetSize();
+ USHORT nScreenFontZoom = maSettings.GetStyleSettings().GetScreenFontZoom();
+
+ if ( IsMapModeEnabled() )
+ aSize = LogicToPixel( aSize );
+
+ if ( aSize.Width() )
+ {
+ aSize.Width() *= 100;
+ aSize.Width() /= nScreenFontZoom;
+ aSize.Width() *= 72;
+ aSize.Width() += mpWindowImpl->mpFrameData->mnDPIX/2;
+ aSize.Width() /= mpWindowImpl->mpFrameData->mnDPIX;
+ }
+ aSize.Height() *= 100;
+ aSize.Height() /= nScreenFontZoom;
+ aSize.Height() *= 72;
+ aSize.Height() += mpWindowImpl->mpFrameData->mnDPIY/2;
+ aSize.Height() /= mpWindowImpl->mpFrameData->mnDPIY;
+
+ rFont.SetSize( aSize );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplSysObjClip( const Region* pOldRegion )
+{
+ BOOL bUpdate = TRUE;
+
+ if ( mpWindowImpl->mpSysObj )
+ {
+ BOOL bVisibleState = mpWindowImpl->mbReallyVisible;
+
+ if ( bVisibleState )
+ {
+ Region* pWinChildClipRegion = ImplGetWinChildClipRegion();
+
+ if ( !pWinChildClipRegion->IsEmpty() )
+ {
+ if ( pOldRegion )
+ {
+ Region aNewRegion = *pWinChildClipRegion;
+ pWinChildClipRegion->Intersect( *pOldRegion );
+ bUpdate = aNewRegion == *pWinChildClipRegion;
+ }
+
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ Region aRegion = *pWinChildClipRegion;
+ Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aWinRectRegion( aWinRect );
+ USHORT nClipFlags = mpWindowImpl->mpSysObj->GetClipRegionType();
+
+ if ( aRegion == aWinRectRegion )
+ mpWindowImpl->mpSysObj->ResetClipRegion();
+ else
+ {
+ if ( nClipFlags & SAL_OBJECT_CLIP_EXCLUDERECTS )
+ {
+ aWinRectRegion.Exclude( aRegion );
+ aRegion = aWinRectRegion;
+ }
+ if ( !(nClipFlags & SAL_OBJECT_CLIP_ABSOLUTE) )
+ aRegion.Move( -mnOutOffX, -mnOutOffY );
+
+ // ClipRegion setzen/updaten
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ULONG nRectCount;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ nRectCount = aRegion.GetRectCount();
+ mpWindowImpl->mpSysObj->BeginSetClipRegion( nRectCount );
+ bRegionRect = aRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ mpWindowImpl->mpSysObj->UnionClipRegion( nX, nY, nWidth, nHeight );
+ bRegionRect = aRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ mpWindowImpl->mpSysObj->EndSetClipRegion();
+ }
+ }
+ else
+ bVisibleState = FALSE;
+ }
+
+ // Visible-Status updaten
+ mpWindowImpl->mpSysObj->Show( bVisibleState );
+ }
+
+ return bUpdate;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateSysObjChildsClip()
+{
+ if ( mpWindowImpl->mpSysObj && mpWindowImpl->mbInitWinClipRegion )
+ ImplSysObjClip( NULL );
+
+ Window* pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ pWindow->ImplUpdateSysObjChildsClip();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateSysObjOverlapsClip()
+{
+ ImplUpdateSysObjChildsClip();
+
+ Window* pWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pWindow )
+ {
+ pWindow->ImplUpdateSysObjOverlapsClip();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateSysObjClip()
+{
+ if ( !ImplIsOverlapWindow() )
+ {
+ ImplUpdateSysObjChildsClip();
+
+ // Schwestern muessen ihre ClipRegion auch neu berechnen
+ if ( mpWindowImpl->mbClipSiblings )
+ {
+ Window* pWindow = mpWindowImpl->mpNext;
+ while ( pWindow )
+ {
+ pWindow->ImplUpdateSysObjChildsClip();
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ }
+ }
+ else
+ mpWindowImpl->mpFrameWindow->ImplUpdateSysObjOverlapsClip();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplSetClipFlagChilds( BOOL bSysObjOnlySmaller )
+{
+ BOOL bUpdate = TRUE;
+ if ( mpWindowImpl->mpSysObj )
+ {
+ Region* pOldRegion = NULL;
+ if ( bSysObjOnlySmaller && !mpWindowImpl->mbInitWinClipRegion )
+ pOldRegion = new Region( mpWindowImpl->maWinClipRegion );
+
+ mbInitClipRegion = TRUE;
+ mpWindowImpl->mbInitWinClipRegion = TRUE;
+
+ Window* pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( !pWindow->ImplSetClipFlagChilds( bSysObjOnlySmaller ) )
+ bUpdate = FALSE;
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+
+ if ( !ImplSysObjClip( pOldRegion ) )
+ {
+ mbInitClipRegion = TRUE;
+ mpWindowImpl->mbInitWinClipRegion = TRUE;
+ bUpdate = FALSE;
+ }
+
+ if ( pOldRegion )
+ delete pOldRegion;
+ }
+ else
+ {
+ mbInitClipRegion = TRUE;
+ mpWindowImpl->mbInitWinClipRegion = TRUE;
+
+ Window* pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( !pWindow->ImplSetClipFlagChilds( bSysObjOnlySmaller ) )
+ bUpdate = FALSE;
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ }
+ return bUpdate;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplSetClipFlagOverlapWindows( BOOL bSysObjOnlySmaller )
+{
+ BOOL bUpdate = ImplSetClipFlagChilds( bSysObjOnlySmaller );
+
+ Window* pWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( !pWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller ) )
+ bUpdate = FALSE;
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+
+ return bUpdate;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplSetClipFlag( BOOL bSysObjOnlySmaller )
+{
+ if ( !ImplIsOverlapWindow() )
+ {
+ BOOL bUpdate = ImplSetClipFlagChilds( bSysObjOnlySmaller );
+
+ Window* pParent = ImplGetParent();
+ if ( pParent &&
+ ((pParent->GetStyle() & WB_CLIPCHILDREN) || (mpWindowImpl->mnParentClipMode & PARENTCLIPMODE_CLIP)) )
+ {
+ pParent->mbInitClipRegion = TRUE;
+ pParent->mpWindowImpl->mbInitChildRegion = TRUE;
+ }
+
+ // Schwestern muessen ihre ClipRegion auch neu berechnen
+ if ( mpWindowImpl->mbClipSiblings )
+ {
+ Window* pWindow = mpWindowImpl->mpNext;
+ while ( pWindow )
+ {
+ if ( !pWindow->ImplSetClipFlagChilds( bSysObjOnlySmaller ) )
+ bUpdate = FALSE;
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ }
+
+ return bUpdate;
+ }
+ else
+ return mpWindowImpl->mpFrameWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplIntersectWindowClipRegion( Region& rRegion )
+{
+ if ( mpWindowImpl->mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+
+ rRegion.Intersect( mpWindowImpl->maWinClipRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplIntersectWindowRegion( Region& rRegion )
+{
+ rRegion.Intersect( Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) ) );
+ if ( mpWindowImpl->mbWinRegion )
+ rRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplExcludeWindowRegion( Region& rRegion )
+{
+ if ( mpWindowImpl->mbWinRegion )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
+ rRegion.Exclude( aRegion );
+ }
+ else
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ rRegion.Exclude( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplExcludeOverlapWindows( Region& rRegion )
+{
+ Window* pWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbReallyVisible )
+ {
+ pWindow->ImplExcludeWindowRegion( rRegion );
+ pWindow->ImplExcludeOverlapWindows( rRegion );
+ }
+
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplExcludeOverlapWindows2( Region& rRegion )
+{
+ if ( mpWindowImpl->mbReallyVisible )
+ ImplExcludeWindowRegion( rRegion );
+
+ ImplExcludeOverlapWindows( rRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplClipBoundaries( Region& rRegion, BOOL bThis, BOOL bOverlaps )
+{
+ if ( bThis )
+ ImplIntersectWindowClipRegion( rRegion );
+ else if ( ImplIsOverlapWindow() )
+ {
+ // Evt. noch am Frame clippen
+ if ( !mpWindowImpl->mbFrame )
+ rRegion.Intersect( Rectangle( Point( 0, 0 ), Size( mpWindowImpl->mpFrameWindow->mnOutWidth, mpWindowImpl->mpFrameWindow->mnOutHeight ) ) );
+
+ if ( bOverlaps && !rRegion.IsEmpty() )
+ {
+ // Clip Overlap Siblings
+ Window* pStartOverlapWindow = this;
+ while ( !pStartOverlapWindow->mpWindowImpl->mbFrame )
+ {
+ Window* pOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
+ while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
+ {
+ pOverlapWindow->ImplExcludeOverlapWindows2( rRegion );
+ pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
+ }
+ pStartOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow;
+ }
+
+ // Clip Child Overlap Windows
+ ImplExcludeOverlapWindows( rRegion );
+ }
+ }
+ else
+ ImplGetParent()->ImplIntersectWindowClipRegion( rRegion );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplClipChilds( Region& rRegion )
+{
+ BOOL bOtherClip = FALSE;
+ Window* pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbReallyVisible )
+ {
+ // ParentClipMode-Flags auswerten
+ USHORT nClipMode = pWindow->GetParentClipMode();
+ if ( !(nClipMode & PARENTCLIPMODE_NOCLIP) &&
+ ((nClipMode & PARENTCLIPMODE_CLIP) || (GetStyle() & WB_CLIPCHILDREN)) )
+ pWindow->ImplExcludeWindowRegion( rRegion );
+ else
+ bOtherClip = TRUE;
+ }
+
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+
+ return bOtherClip;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplClipAllChilds( Region& rRegion )
+{
+ Window* pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbReallyVisible )
+ pWindow->ImplExcludeWindowRegion( rRegion );
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplClipSiblings( Region& rRegion )
+{
+ Window* pWindow = ImplGetParent()->mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow == this )
+ break;
+
+ if ( pWindow->mpWindowImpl->mbReallyVisible )
+ pWindow->ImplExcludeWindowRegion( rRegion );
+
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInitWinClipRegion()
+{
+ // Build Window Region
+ mpWindowImpl->maWinClipRegion = Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ if ( mpWindowImpl->mbWinRegion )
+ mpWindowImpl->maWinClipRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
+
+ // ClipSiblings
+ if ( mpWindowImpl->mbClipSiblings && !ImplIsOverlapWindow() )
+ ImplClipSiblings( mpWindowImpl->maWinClipRegion );
+
+ // Clip Parent Boundaries
+ ImplClipBoundaries( mpWindowImpl->maWinClipRegion, FALSE, TRUE );
+
+ // Clip Children
+ if ( (GetStyle() & WB_CLIPCHILDREN) || mpWindowImpl->mbClipChildren )
+ mpWindowImpl->mbInitChildRegion = TRUE;
+
+ mpWindowImpl->mbInitWinClipRegion = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInitWinChildClipRegion()
+{
+ if ( !mpWindowImpl->mpFirstChild )
+ {
+ if ( mpWindowImpl->mpChildClipRegion )
+ {
+ delete mpWindowImpl->mpChildClipRegion;
+ mpWindowImpl->mpChildClipRegion = NULL;
+ }
+ }
+ else
+ {
+ if ( !mpWindowImpl->mpChildClipRegion )
+ mpWindowImpl->mpChildClipRegion = new Region( mpWindowImpl->maWinClipRegion );
+ else
+ *mpWindowImpl->mpChildClipRegion = mpWindowImpl->maWinClipRegion;
+
+ ImplClipChilds( *mpWindowImpl->mpChildClipRegion );
+ }
+
+ mpWindowImpl->mbInitChildRegion = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Region* Window::ImplGetWinChildClipRegion()
+{
+ if ( mpWindowImpl->mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+ if ( mpWindowImpl->mbInitChildRegion )
+ ImplInitWinChildClipRegion();
+ if ( mpWindowImpl->mpChildClipRegion )
+ return mpWindowImpl->mpChildClipRegion;
+ else
+ return &mpWindowImpl->maWinClipRegion;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplIntersectAndUnionOverlapWindows( const Region& rInterRegion, Region& rRegion )
+{
+ Window* pWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbReallyVisible )
+ {
+ Region aTempRegion( rInterRegion );
+ pWindow->ImplIntersectWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ pWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
+ }
+
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplIntersectAndUnionOverlapWindows2( const Region& rInterRegion, Region& rRegion )
+{
+ if ( mpWindowImpl->mbReallyVisible )
+ {
+ Region aTempRegion( rInterRegion );
+ ImplIntersectWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ }
+
+ ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcOverlapRegionOverlaps( const Region& rInterRegion, Region& rRegion )
+{
+ // Clip Overlap Siblings
+ Window* pStartOverlapWindow;
+ if ( !ImplIsOverlapWindow() )
+ pStartOverlapWindow = mpWindowImpl->mpOverlapWindow;
+ else
+ pStartOverlapWindow = this;
+ while ( !pStartOverlapWindow->mpWindowImpl->mbFrame )
+ {
+ Window* pOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
+ while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
+ {
+ pOverlapWindow->ImplIntersectAndUnionOverlapWindows2( rInterRegion, rRegion );
+ pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
+ }
+ pStartOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow;
+ }
+
+ // Clip Child Overlap Windows
+ if ( !ImplIsOverlapWindow() )
+ mpWindowImpl->mpOverlapWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
+ else
+ ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcOverlapRegion( const Rectangle& rSourceRect, Region& rRegion,
+ BOOL bChilds, BOOL bParent, BOOL bSiblings )
+{
+ Region aRegion( rSourceRect );
+ if ( mpWindowImpl->mbWinRegion )
+ rRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
+ Region aTempRegion;
+ Window* pWindow;
+
+ ImplCalcOverlapRegionOverlaps( aRegion, rRegion );
+
+ // Parent-Boundaries
+ if ( bParent )
+ {
+ pWindow = this;
+ if ( !ImplIsOverlapWindow() )
+ {
+ pWindow = ImplGetParent();
+ do
+ {
+ aTempRegion = aRegion;
+ pWindow->ImplExcludeWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ if ( pWindow->ImplIsOverlapWindow() )
+ break;
+ pWindow = pWindow->ImplGetParent();
+ }
+ while ( pWindow );
+ }
+ if ( !pWindow->mpWindowImpl->mbFrame )
+ {
+ aTempRegion = aRegion;
+ aTempRegion.Exclude( Rectangle( Point( 0, 0 ), Size( mpWindowImpl->mpFrameWindow->mnOutWidth, mpWindowImpl->mpFrameWindow->mnOutHeight ) ) );
+ rRegion.Union( aTempRegion );
+ }
+ }
+
+ // Siblings
+ if ( bSiblings && !ImplIsOverlapWindow() )
+ {
+ pWindow = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
+ do
+ {
+ if ( pWindow->mpWindowImpl->mbReallyVisible && (pWindow != this) )
+ {
+ aTempRegion = aRegion;
+ pWindow->ImplIntersectWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ }
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ while ( pWindow );
+ }
+
+ // Childs
+ if ( bChilds )
+ {
+ pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mpWindowImpl->mbReallyVisible )
+ {
+ aTempRegion = aRegion;
+ pWindow->ImplIntersectWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ }
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallPaint( const Region* pRegion, USHORT nPaintFlags )
+{
+ // call PrePaint. PrePaint may add to the invalidate region as well as
+ // other parameters used below.
+ PrePaint();
+
+ mpWindowImpl->mbPaintFrame = FALSE;
+
+ if ( nPaintFlags & IMPL_PAINT_PAINTALLCHILDS )
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALLCHILDS | (nPaintFlags & IMPL_PAINT_PAINTALL);
+ if ( nPaintFlags & IMPL_PAINT_PAINTCHILDS )
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTCHILDS;
+ if ( nPaintFlags & IMPL_PAINT_ERASE )
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_ERASE;
+ if ( nPaintFlags & IMPL_PAINT_CHECKRTL )
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_CHECKRTL;
+ if ( !mpWindowImpl->mpFirstChild )
+ mpWindowImpl->mnPaintFlags &= ~IMPL_PAINT_PAINTALLCHILDS;
+
+ if ( mpWindowImpl->mbPaintDisabled )
+ {
+ if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
+ Invalidate( INVALIDATE_NOCHILDREN | INVALIDATE_NOERASE | INVALIDATE_NOTRANSPARENT | INVALIDATE_NOCLIPCHILDREN );
+ else if ( pRegion )
+ Invalidate( *pRegion, INVALIDATE_NOCHILDREN | INVALIDATE_NOERASE | INVALIDATE_NOTRANSPARENT | INVALIDATE_NOCLIPCHILDREN );
+ return;
+ }
+
+ nPaintFlags = mpWindowImpl->mnPaintFlags & ~(IMPL_PAINT_PAINT);
+
+ Region* pChildRegion = NULL;
+ Rectangle aSelectionRect;
+ if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINT )
+ {
+ Region* pWinChildClipRegion = ImplGetWinChildClipRegion();
+ if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
+ mpWindowImpl->maInvalidateRegion = *pWinChildClipRegion;
+ else
+ {
+ if ( pRegion )
+ mpWindowImpl->maInvalidateRegion.Union( *pRegion );
+
+ if( mpWindowImpl->mpWinData && mpWindowImpl->mbTrackVisible )
+ /* #98602# need to repaint all children within the
+ * tracking rectangle, so the following invert
+ * operation takes places without traces of the previous
+ * one.
+ */
+ mpWindowImpl->maInvalidateRegion.Union( *mpWindowImpl->mpWinData->mpTrackRect );
+
+ if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDS )
+ pChildRegion = new Region( mpWindowImpl->maInvalidateRegion );
+ mpWindowImpl->maInvalidateRegion.Intersect( *pWinChildClipRegion );
+ }
+ mpWindowImpl->mnPaintFlags = 0;
+ if ( !mpWindowImpl->maInvalidateRegion.IsEmpty() )
+ {
+ if ( mpWindowImpl->mpCursor )
+ mpWindowImpl->mpCursor->ImplHide();
+
+ mbInitClipRegion = TRUE;
+ mpWindowImpl->mbInPaint = TRUE;
+
+ // Paint-Region zuruecksetzen
+ Region aPaintRegion( mpWindowImpl->maInvalidateRegion );
+ Rectangle aPaintRect = aPaintRegion.GetBoundRect();
+
+ // - RTL - re-mirror paint rect and region at this window
+ if( ImplIsAntiparallel() )
+ {
+ ImplReMirror( aPaintRect );
+ ImplReMirror( aPaintRegion );
+ }
+ aPaintRect = ImplDevicePixelToLogic( aPaintRect);
+ mpWindowImpl->mpPaintRegion = &aPaintRegion;
+ mpWindowImpl->maInvalidateRegion.SetEmpty();
+
+ if ( (nPaintFlags & IMPL_PAINT_ERASE) && IsBackground() )
+ {
+ if ( IsClipRegion() )
+ {
+ Region aOldRegion = GetClipRegion();
+ SetClipRegion();
+ Erase();
+ SetClipRegion( aOldRegion );
+ }
+ else
+ Erase();
+ }
+
+ // #98943# trigger drawing of toolbox selection after all childern are painted
+ if( mpWindowImpl->mbDrawSelectionBackground )
+ aSelectionRect = aPaintRect;
+
+ Paint( aPaintRect );
+
+ if ( mpWindowImpl->mpWinData )
+ {
+ if ( mpWindowImpl->mbFocusVisible )
+ ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) );
+ }
+ mpWindowImpl->mbInPaint = FALSE;
+ mbInitClipRegion = TRUE;
+ mpWindowImpl->mpPaintRegion = NULL;
+ if ( mpWindowImpl->mpCursor )
+ mpWindowImpl->mpCursor->ImplShow( FALSE );
+ }
+ }
+ else
+ mpWindowImpl->mnPaintFlags = 0;
+
+ if ( nPaintFlags & (IMPL_PAINT_PAINTALLCHILDS | IMPL_PAINT_PAINTCHILDS) )
+ {
+ // die Childfenster ausgeben
+ Window* pTempWindow = mpWindowImpl->mpFirstChild;
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->mpWindowImpl->mbVisible )
+ pTempWindow->ImplCallPaint( pChildRegion, nPaintFlags );
+ pTempWindow = pTempWindow->mpWindowImpl->mpNext;
+ }
+ }
+
+ if ( mpWindowImpl->mpWinData && mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ /* #98602# need to invert the tracking rect AFTER
+ * the children have painted
+ */
+ InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags );
+
+ // #98943# draw toolbox selection
+ if( !aSelectionRect.IsEmpty() )
+ DrawSelectionBackground( aSelectionRect, 3, FALSE, TRUE, FALSE );
+
+ if ( pChildRegion )
+ delete pChildRegion;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallOverlapPaint()
+{
+ // Zuerst geben wir die ueberlappenden Fenster aus
+ Window* pTempWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->mpWindowImpl->mbReallyVisible )
+ pTempWindow->ImplCallOverlapPaint();
+ pTempWindow = pTempWindow->mpWindowImpl->mpNext;
+ }
+
+ // und dann erst uns selber
+ if ( mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDS) )
+ {
+ // - RTL - notify ImplCallPaint to check for re-mirroring (CHECKRTL)
+ // because we were called from the Sal layer
+ ImplCallPaint( NULL, mpWindowImpl->mnPaintFlags /*| IMPL_PAINT_CHECKRTL */);
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplPostPaint()
+{
+ if ( !mpWindowImpl->mpFrameData->maPaintTimer.IsActive() )
+ mpWindowImpl->mpFrameData->maPaintTimer.Start();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplHandlePaintHdl, void*, EMPTYARG )
+{
+ // save paint events until resizing is done
+ if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData->maResizeTimer.IsActive() )
+ mpWindowImpl->mpFrameData->maPaintTimer.Start();
+ else if ( mpWindowImpl->mbReallyVisible )
+ ImplCallOverlapPaint();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplHandleResizeTimerHdl, void*, EMPTYARG )
+{
+ if( mpWindowImpl->mbReallyVisible )
+ {
+ ImplCallResize();
+ if( mpWindowImpl->mpFrameData->maPaintTimer.IsActive() )
+ {
+ mpWindowImpl->mpFrameData->maPaintTimer.Stop();
+ mpWindowImpl->mpFrameData->maPaintTimer.GetTimeoutHdl().Call( NULL );
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateFrameRegion( const Region* pRegion, USHORT nFlags )
+{
+ // PAINTCHILDS bei allen Parent-Fenster bis zum ersten OverlapWindow
+ // setzen
+ if ( !ImplIsOverlapWindow() )
+ {
+ Window* pTempWindow = this;
+ USHORT nTranspPaint = IsPaintTransparent() ? IMPL_PAINT_PAINT : 0;
+ do
+ {
+ pTempWindow = pTempWindow->ImplGetParent();
+ if ( pTempWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTCHILDS )
+ break;
+ pTempWindow->mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTCHILDS | nTranspPaint;
+ if( ! pTempWindow->IsPaintTransparent() )
+ nTranspPaint = 0;
+ }
+ while ( !pTempWindow->ImplIsOverlapWindow() );
+ }
+
+ // Paint-Flags setzen
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINT;
+ if ( nFlags & INVALIDATE_CHILDREN )
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTALLCHILDS;
+ if ( !(nFlags & INVALIDATE_NOERASE) )
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_ERASE;
+ if ( !pRegion )
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTALL;
+
+ // Wenn nicht alles neu ausgegeben werden muss, dann die Region
+ // dazupacken
+ if ( !(mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL) )
+ mpWindowImpl->maInvalidateRegion.Union( *pRegion );
+
+ // Handle transparent windows correctly: invalidate must be done on the first opaque parent
+ if( ((IsPaintTransparent() && !(nFlags & INVALIDATE_NOTRANSPARENT)) || (nFlags & INVALIDATE_TRANSPARENT) )
+ && ImplGetParent() )
+ {
+ Window *pParent = ImplGetParent();
+ while( pParent && pParent->IsPaintTransparent() )
+ pParent = pParent->ImplGetParent();
+ if( pParent )
+ {
+ Region *pChildRegion;
+ if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
+ // invalidate the whole child window region in the parent
+ pChildRegion = ImplGetWinChildClipRegion();
+ else
+ // invalidate the same region in the parent that has to be repainted in the child
+ pChildRegion = &mpWindowImpl->maInvalidateRegion;
+
+ nFlags |= INVALIDATE_CHILDREN; // paint should also be done on all children
+ nFlags &= ~INVALIDATE_NOERASE; // parent should paint and erase to create proper background
+ pParent->ImplInvalidateFrameRegion( pChildRegion, nFlags );
+ }
+ }
+ ImplPostPaint();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateOverlapFrameRegion( const Region& rRegion )
+{
+ Region aRegion = rRegion;
+
+ ImplClipBoundaries( aRegion, TRUE, TRUE );
+ if ( !aRegion.IsEmpty() )
+ ImplInvalidateFrameRegion( &aRegion, INVALIDATE_CHILDREN );
+
+ // Dann invalidieren wir die ueberlappenden Fenster
+ Window* pTempWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->IsVisible() )
+ pTempWindow->ImplInvalidateOverlapFrameRegion( rRegion );
+
+ pTempWindow = pTempWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateParentFrameRegion( Region& rRegion )
+{
+ if ( mpWindowImpl->mbOverlapWin )
+ mpWindowImpl->mpFrameWindow->ImplInvalidateOverlapFrameRegion( rRegion );
+ else
+ {
+ if( ImplGetParent() )
+ ImplGetParent()->ImplInvalidateFrameRegion( &rRegion, INVALIDATE_CHILDREN );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidate( const Region* pRegion, USHORT nFlags )
+{
+
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ // Feststellen, was neu ausgegeben werden muss
+ BOOL bInvalidateAll = !pRegion;
+
+ // Transparent-Invalidate beruecksichtigen
+ Window* pOpaqueWindow = this;
+ if ( (mpWindowImpl->mbPaintTransparent && !(nFlags & INVALIDATE_NOTRANSPARENT)) || (nFlags & INVALIDATE_TRANSPARENT) )
+ {
+ Window* pTempWindow = pOpaqueWindow->ImplGetParent();
+ while ( pTempWindow )
+ {
+ if ( !pTempWindow->IsPaintTransparent() )
+ {
+ pOpaqueWindow = pTempWindow;
+ nFlags |= INVALIDATE_CHILDREN;
+ bInvalidateAll = FALSE;
+ break;
+ }
+
+ if ( pTempWindow->ImplIsOverlapWindow() )
+ break;
+
+ pTempWindow = pTempWindow->ImplGetParent();
+ }
+ }
+
+ // Region zusammenbauen
+ USHORT nOrgFlags = nFlags;
+ if ( !(nFlags & (INVALIDATE_CHILDREN | INVALIDATE_NOCHILDREN)) )
+ {
+ if ( GetStyle() & WB_CLIPCHILDREN )
+ nFlags |= INVALIDATE_NOCHILDREN;
+ else
+ nFlags |= INVALIDATE_CHILDREN;
+ }
+ if ( (nFlags & INVALIDATE_NOCHILDREN) && mpWindowImpl->mpFirstChild )
+ bInvalidateAll = FALSE;
+ if ( bInvalidateAll )
+ ImplInvalidateFrameRegion( NULL, nFlags );
+ else
+ {
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aRegion( aRect );
+ if ( pRegion )
+ {
+ // --- RTL --- remirror region before intersecting it
+ if ( ImplIsAntiparallel() )
+ {
+ Region aRgn( *pRegion );
+ ImplReMirror( aRgn );
+ aRegion.Intersect( aRgn );
+ }
+ else
+ aRegion.Intersect( *pRegion );
+ }
+ ImplClipBoundaries( aRegion, TRUE, TRUE );
+ if ( nFlags & INVALIDATE_NOCHILDREN )
+ {
+ nFlags &= ~INVALIDATE_CHILDREN;
+ if ( !(nFlags & INVALIDATE_NOCLIPCHILDREN) )
+ {
+ if ( nOrgFlags & INVALIDATE_NOCHILDREN )
+ ImplClipAllChilds( aRegion );
+ else
+ {
+ if ( ImplClipChilds( aRegion ) )
+ nFlags |= INVALIDATE_CHILDREN;
+ }
+ }
+ }
+ if ( !aRegion.IsEmpty() )
+ ImplInvalidateFrameRegion( &aRegion, nFlags ); // transparency is handled here, pOpaqueWindow not required
+ }
+
+ if ( nFlags & INVALIDATE_UPDATE )
+ pOpaqueWindow->Update(); // start painting at the opaque parent
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplMoveInvalidateRegion( const Rectangle& rRect,
+ long nHorzScroll, long nVertScroll,
+ BOOL bChilds )
+{
+ if ( (mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALL)) == IMPL_PAINT_PAINT )
+ {
+ Region aTempRegion = mpWindowImpl->maInvalidateRegion;
+ aTempRegion.Intersect( rRect );
+ aTempRegion.Move( nHorzScroll, nVertScroll );
+ mpWindowImpl->maInvalidateRegion.Union( aTempRegion );
+ }
+
+ if ( bChilds && (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTCHILDS) )
+ {
+ Window* pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ pWindow->ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, TRUE );
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplMoveAllInvalidateRegions( const Rectangle& rRect,
+ long nHorzScroll, long nVertScroll,
+ BOOL bChilds )
+{
+ // Paint-Region auch verschieben, wenn noch Paints anstehen
+ ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, bChilds );
+ // Paint-Region muss bei uns verschoben gesetzt werden, die durch
+ // die Parents gezeichnet werden
+ if ( !ImplIsOverlapWindow() )
+ {
+ Region aPaintAllRegion;
+ Window* pPaintAllWindow = this;
+ do
+ {
+ pPaintAllWindow = pPaintAllWindow->ImplGetParent();
+ if ( pPaintAllWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDS )
+ {
+ if ( pPaintAllWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
+ {
+ aPaintAllRegion.SetEmpty();
+ break;
+ }
+ else
+ aPaintAllRegion.Union( pPaintAllWindow->mpWindowImpl->maInvalidateRegion );
+ }
+ }
+ while ( !pPaintAllWindow->ImplIsOverlapWindow() );
+ if ( !aPaintAllRegion.IsEmpty() )
+ {
+ aPaintAllRegion.Move( nHorzScroll, nVertScroll );
+ USHORT nPaintFlags = 0;
+ if ( bChilds )
+ mpWindowImpl->mnPaintFlags |= INVALIDATE_CHILDREN;
+ ImplInvalidateFrameRegion( &aPaintAllRegion, nPaintFlags );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplValidateFrameRegion( const Region* pRegion, USHORT nFlags )
+{
+ if ( !pRegion )
+ mpWindowImpl->maInvalidateRegion.SetEmpty();
+ else
+ {
+ // Wenn alle Childfenster neu ausgegeben werden muessen,
+ // dann invalidieren wir diese vorher
+ if ( (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDS) && mpWindowImpl->mpFirstChild )
+ {
+ Region aChildRegion = mpWindowImpl->maInvalidateRegion;
+ if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
+ {
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ aChildRegion = aRect;
+ }
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->Invalidate( aChildRegion, INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+ if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
+ {
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ mpWindowImpl->maInvalidateRegion = aRect;
+ }
+ mpWindowImpl->maInvalidateRegion.Exclude( *pRegion );
+ }
+ mpWindowImpl->mnPaintFlags &= ~IMPL_PAINT_PAINTALL;
+
+ if ( nFlags & VALIDATE_CHILDREN )
+ {
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplValidateFrameRegion( pRegion, nFlags );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplValidate( const Region* pRegion, USHORT nFlags )
+{
+ // Region zusammenbauen
+ BOOL bValidateAll = !pRegion;
+ USHORT nOrgFlags = nFlags;
+ if ( !(nFlags & (VALIDATE_CHILDREN | VALIDATE_NOCHILDREN)) )
+ {
+ if ( GetStyle() & WB_CLIPCHILDREN )
+ nFlags |= VALIDATE_NOCHILDREN;
+ else
+ nFlags |= VALIDATE_CHILDREN;
+ }
+ if ( (nFlags & VALIDATE_NOCHILDREN) && mpWindowImpl->mpFirstChild )
+ bValidateAll = FALSE;
+ if ( bValidateAll )
+ ImplValidateFrameRegion( NULL, nFlags );
+ else
+ {
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aRegion( aRect );
+ if ( pRegion )
+ aRegion.Intersect( *pRegion );
+ ImplClipBoundaries( aRegion, TRUE, TRUE );
+ if ( nFlags & VALIDATE_NOCHILDREN )
+ {
+ nFlags &= ~VALIDATE_CHILDREN;
+ if ( nOrgFlags & VALIDATE_NOCHILDREN )
+ ImplClipAllChilds( aRegion );
+ else
+ {
+ if ( ImplClipChilds( aRegion ) )
+ nFlags |= VALIDATE_CHILDREN;
+ }
+ }
+ if ( !aRegion.IsEmpty() )
+ ImplValidateFrameRegion( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplScroll( const Rectangle& rRect,
+ long nHorzScroll, long nVertScroll, USHORT nFlags )
+{
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ nHorzScroll = ImplLogicWidthToDevicePixel( nHorzScroll );
+ nVertScroll = ImplLogicHeightToDevicePixel( nVertScroll );
+
+ if ( !nHorzScroll && !nVertScroll )
+ return;
+
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ if ( mpWindowImpl->mpCursor )
+ mpWindowImpl->mpCursor->ImplHide();
+
+ USHORT nOrgFlags = nFlags;
+ if ( !(nFlags & (SCROLL_CHILDREN | SCROLL_NOCHILDREN)) )
+ {
+ if ( GetStyle() & WB_CLIPCHILDREN )
+ nFlags |= SCROLL_NOCHILDREN;
+ else
+ nFlags |= SCROLL_CHILDREN;
+ }
+
+ Region aInvalidateRegion;
+ BOOL bScrollChilds = (nFlags & SCROLL_CHILDREN) != 0;
+ BOOL bErase = (nFlags & SCROLL_NOERASE) == 0;
+
+ if ( !mpWindowImpl->mpFirstChild )
+ bScrollChilds = FALSE;
+
+ // --- RTL --- check if this window requires special action
+ BOOL bReMirror = ( ImplIsAntiparallel() );
+
+ Rectangle aRectMirror( rRect );
+ if( bReMirror )
+ {
+ // --- RTL --- make sure the invalidate region of this window is
+ // computed in the same coordinate space as the one from the overlap windows
+ ImplReMirror( aRectMirror );
+ }
+
+ // Paint-Bereiche anpassen
+ ImplMoveAllInvalidateRegions( aRectMirror, nHorzScroll, nVertScroll, bScrollChilds );
+
+ if ( !(nFlags & SCROLL_NOINVALIDATE) )
+ {
+ ImplCalcOverlapRegion( aRectMirror, aInvalidateRegion, !bScrollChilds, TRUE, FALSE );
+
+ // --- RTL ---
+ // if the scrolling on the device is performed in the opposite direction
+ // then move the overlaps in that direction to compute the invalidate region
+ // on the correct side, i.e., revert nHorzScroll
+
+ if ( !aInvalidateRegion.IsEmpty() )
+ {
+ aInvalidateRegion.Move( bReMirror ? -nHorzScroll : nHorzScroll, nVertScroll );
+ bErase = TRUE;
+ }
+ if ( !(nFlags & SCROLL_NOWINDOWINVALIDATE) )
+ {
+ Rectangle aDestRect( aRectMirror );
+ aDestRect.Move( bReMirror ? -nHorzScroll : nHorzScroll, nVertScroll );
+ Region aWinInvalidateRegion( aRectMirror );
+ aWinInvalidateRegion.Exclude( aDestRect );
+
+ aInvalidateRegion.Union( aWinInvalidateRegion );
+ }
+ }
+
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
+ if ( nFlags & SCROLL_CLIP )
+ aRegion.Intersect( rRect );
+ if ( mpWindowImpl->mbWinRegion )
+ aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
+
+ aRegion.Exclude( aInvalidateRegion );
+
+ ImplClipBoundaries( aRegion, FALSE, TRUE );
+ if ( !bScrollChilds )
+ {
+ if ( nOrgFlags & SCROLL_NOCHILDREN )
+ ImplClipAllChilds( aRegion );
+ else
+ ImplClipChilds( aRegion );
+ }
+ if ( mbClipRegion && (nFlags & SCROLL_USECLIPREGION) )
+ aRegion.Intersect( maRegion );
+ if ( !aRegion.IsEmpty() )
+ {
+ if ( mpWindowImpl->mpWinData )
+ {
+ if ( mpWindowImpl->mbFocusVisible )
+ ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) );
+ if ( mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags );
+ }
+
+ SalGraphics* pGraphics = ImplGetFrameGraphics();
+ if ( pGraphics )
+ {
+ if( bReMirror )
+ {
+ // --- RTL --- frame coordinates require re-mirroring
+ ImplReMirror( aRegion );
+ }
+
+ ImplSelectClipRegion( aRegion, pGraphics );
+ pGraphics->CopyArea( rRect.Left()+nHorzScroll, rRect.Top()+nVertScroll,
+ rRect.Left(), rRect.Top(),
+ rRect.GetWidth(), rRect.GetHeight(),
+ SAL_COPYAREA_WINDOWINVALIDATE, this );
+ }
+
+ if ( mpWindowImpl->mpWinData )
+ {
+ if ( mpWindowImpl->mbFocusVisible )
+ ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) );
+ if ( mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags );
+ }
+ }
+
+ if ( !aInvalidateRegion.IsEmpty() )
+ {
+ // --- RTL --- the invalidate region for this windows is already computed in frame coordinates
+ // so it has to be re-mirrored before calling the Paint-handler
+ mpWindowImpl->mnPaintFlags |= IMPL_PAINT_CHECKRTL;
+
+ USHORT nPaintFlags = INVALIDATE_CHILDREN;
+ if ( !bErase )
+ nPaintFlags |= INVALIDATE_NOERASE;
+ if ( !bScrollChilds )
+ {
+ if ( nOrgFlags & SCROLL_NOCHILDREN )
+ ImplClipAllChilds( aInvalidateRegion );
+ else
+ ImplClipChilds( aInvalidateRegion );
+ }
+ ImplInvalidateFrameRegion( &aInvalidateRegion, nPaintFlags );
+ }
+
+ if ( bScrollChilds )
+ {
+ Window* pWindow = mpWindowImpl->mpFirstChild;
+ while ( pWindow )
+ {
+ Point aPos = pWindow->GetPosPixel();
+ aPos += Point( nHorzScroll, nVertScroll );
+ pWindow->SetPosPixel( aPos );
+
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ }
+
+ if ( nFlags & SCROLL_UPDATE )
+ Update();
+
+ if ( mpWindowImpl->mpCursor )
+ mpWindowImpl->mpCursor->ImplShow( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateAll( BOOL bOverlapWindows )
+{
+ if ( !mpWindowImpl->mbReallyVisible )
+ return;
+
+ BOOL bFlush = FALSE;
+ if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
+ {
+ Point aPoint( 0, 0 );
+ Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
+ ImplInvalidateOverlapFrameRegion( aRegion );
+ if ( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) )
+ bFlush = TRUE;
+ }
+
+ // Ein Update wirkt immer auf das OverlapWindow, damit bei spaeteren
+ // Paints nicht zuviel gemalt wird, wenn dort ALLCHILDREN usw. gesetzt
+ // ist
+ Window* pWindow = ImplGetFirstOverlapWindow();
+ if ( bOverlapWindows )
+ pWindow->ImplCallOverlapPaint();
+ else
+ {
+ if ( pWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDS) )
+ pWindow->ImplCallPaint( NULL, pWindow->mpWindowImpl->mnPaintFlags );
+ }
+
+ if ( bFlush )
+ Flush();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateWindowPtr( Window* pWindow )
+{
+ if ( mpWindowImpl->mpFrameWindow != pWindow->mpWindowImpl->mpFrameWindow )
+ {
+ // Graphic freigeben
+ ImplReleaseGraphics();
+ }
+
+ mpWindowImpl->mpFrameData = pWindow->mpWindowImpl->mpFrameData;
+ mpWindowImpl->mpFrame = pWindow->mpWindowImpl->mpFrame;
+ mpWindowImpl->mpFrameWindow = pWindow->mpWindowImpl->mpFrameWindow;
+ if ( pWindow->ImplIsOverlapWindow() )
+ mpWindowImpl->mpOverlapWindow = pWindow;
+ else
+ mpWindowImpl->mpOverlapWindow = pWindow->mpWindowImpl->mpOverlapWindow;
+
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplUpdateWindowPtr( pWindow );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateWindowPtr()
+{
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplUpdateWindowPtr( this );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateOverlapWindowPtr( BOOL bNewFrame )
+{
+ BOOL bVisible = IsVisible();
+ Show( FALSE );
+ ImplRemoveWindow( bNewFrame );
+ Window* pRealParent = mpWindowImpl->mpRealParent;
+ ImplInsertWindow( ImplGetParent() );
+ mpWindowImpl->mpRealParent = pRealParent;
+ ImplUpdateWindowPtr();
+ if ( ImplUpdatePos() )
+ ImplUpdateSysObjPos();
+
+ if ( bNewFrame )
+ {
+ Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
+ pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
+ pOverlapWindow = pNextOverlapWindow;
+ }
+ }
+
+ if ( bVisible )
+ Show( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplUpdatePos()
+{
+ BOOL bSysChild = FALSE;
+
+ if ( ImplIsOverlapWindow() )
+ {
+ mnOutOffX = mpWindowImpl->mnX;
+ mnOutOffY = mpWindowImpl->mnY;
+ }
+ else
+ {
+ Window* pParent = ImplGetParent();
+
+ mnOutOffX = mpWindowImpl->mnX + pParent->mnOutOffX;
+ mnOutOffY = mpWindowImpl->mnY + pParent->mnOutOffY;
+ }
+
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ if ( pChild->ImplUpdatePos() )
+ bSysChild = TRUE;
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+
+ if ( mpWindowImpl->mpSysObj )
+ bSysChild = TRUE;
+
+ return bSysChild;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateSysObjPos()
+{
+ if ( mpWindowImpl->mpSysObj )
+ mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
+
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplUpdateSysObjPos();
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+}
+// -----------------------------------------------------------------------
+
+void Window::ImplPosSizeWindow( long nX, long nY,
+ long nWidth, long nHeight, USHORT nFlags )
+{
+ BOOL bNewPos = FALSE;
+ BOOL bNewSize = FALSE;
+ BOOL bNewWidth = FALSE;
+ BOOL bCopyBits = FALSE;
+ long nOldOutOffX = mnOutOffX;
+ long nOldOutOffY = mnOutOffY;
+ long nOldOutWidth = mnOutWidth;
+ long nOldOutHeight = mnOutHeight;
+ Region* pOverlapRegion = NULL;
+ Region* pOldRegion = NULL;
+
+ if ( IsReallyVisible() )
+ {
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
+ Size( nOldOutWidth, nOldOutHeight ) );
+ pOldRegion = new Region( aOldWinRect );
+ if ( mpWindowImpl->mbWinRegion )
+ pOldRegion->Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
+
+ if ( mnOutWidth && mnOutHeight && !mpWindowImpl->mbPaintTransparent &&
+ !mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() &&
+ !HasPaintEvent() )
+ bCopyBits = TRUE;
+ }
+
+ BOOL bnXRecycled = FALSE; // avoid duplicate mirroring in RTL case
+ if ( nFlags & WINDOW_POSSIZE_WIDTH )
+ {
+ if(!( nFlags & WINDOW_POSSIZE_X ))
+ {
+ nX = mpWindowImpl->mnX;
+ nFlags |= WINDOW_POSSIZE_X;
+ bnXRecycled = TRUE; // we're using a mnX which was already mirrored in RTL case
+ }
+
+ if ( nWidth < 0 )
+ nWidth = 0;
+ if ( nWidth != mnOutWidth )
+ {
+ mnOutWidth = nWidth;
+ bNewSize = TRUE;
+ bCopyBits = FALSE;
+ bNewWidth = TRUE;
+ }
+ }
+ if ( nFlags & WINDOW_POSSIZE_HEIGHT )
+ {
+ if ( nHeight < 0 )
+ nHeight = 0;
+ if ( nHeight != mnOutHeight )
+ {
+ mnOutHeight = nHeight;
+ bNewSize = TRUE;
+ bCopyBits = FALSE;
+ }
+ }
+
+ if ( nFlags & WINDOW_POSSIZE_X )
+ {
+ long nOrgX = nX;
+ // --- RTL --- (compare the screen coordinates)
+ Point aPtDev( Point( nX+mnOutOffX, 0 ) );
+ if( ImplHasMirroredGraphics() )
+ {
+ mpGraphics->mirror( aPtDev.X(), this );
+
+ // #106948# always mirror our pos if our parent is not mirroring, even
+ // if we are also not mirroring
+ // --- RTL --- check if parent is in different coordinates
+ if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
+ {
+ // --- RTL --- (re-mirror at parent window)
+ nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX;
+ }
+ /* #i99166# An LTR window in RTL UI that gets sized only would be
+ expected to not moved its upper left point
+ */
+ if( bnXRecycled )
+ {
+ if( ImplIsAntiparallel() )
+ {
+ aPtDev.X() = mpWindowImpl->mnAbsScreenX;
+ nOrgX = mpWindowImpl->maPos.X();
+ }
+ }
+ }
+ else if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
+ {
+ // mirrored window in LTR UI
+ {
+ // --- RTL --- (re-mirror at parent window)
+ nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX;
+ }
+ }
+
+ // check maPos as well, as it could have been changed for client windows (ImplCallMove())
+ if ( mpWindowImpl->mnAbsScreenX != aPtDev.X() || nX != mpWindowImpl->mnX || nOrgX != mpWindowImpl->maPos.X() )
+ {
+ if ( bCopyBits && !pOverlapRegion )
+ {
+ pOverlapRegion = new Region();
+ ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) ),
+ *pOverlapRegion, FALSE, TRUE, TRUE );
+ }
+ mpWindowImpl->mnX = nX;
+ mpWindowImpl->maPos.X() = nOrgX;
+ mpWindowImpl->mnAbsScreenX = aPtDev.X(); // --- RTL --- (store real screen pos)
+ bNewPos = TRUE;
+ }
+ }
+ if ( nFlags & WINDOW_POSSIZE_Y )
+ {
+ // check maPos as well, as it could have been changed for client windows (ImplCallMove())
+ if ( nY != mpWindowImpl->mnY || nY != mpWindowImpl->maPos.Y() )
+ {
+ if ( bCopyBits && !pOverlapRegion )
+ {
+ pOverlapRegion = new Region();
+ ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) ),
+ *pOverlapRegion, FALSE, TRUE, TRUE );
+ }
+ mpWindowImpl->mnY = nY;
+ mpWindowImpl->maPos.Y() = nY;
+ bNewPos = TRUE;
+ }
+ }
+
+/* if ( nFlags & (WINDOW_POSSIZE_X|WINDOW_POSSIZE_Y) )
+ {
+ POINT aPt;
+ aPt.x = mpWindowImpl->maPos.X();
+ aPt.y = mpWindowImpl->maPos.Y();
+ ClientToScreen( mpWindowImpl->mpFrame->maFrameData.mhWnd , &aPt );
+ mpWindowImpl->maPos.X() = aPt.x;
+ mpWindowImpl->maPos.Y() = aPt.y;
+ }
+*/
+ if ( bNewPos || bNewSize )
+ {
+ BOOL bUpdateSysObjPos = FALSE;
+ if ( bNewPos )
+ bUpdateSysObjPos = ImplUpdatePos();
+
+ // the borderwindow always specifies the position for its client window
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos;
+
+ if ( mpWindowImpl->mpClientWindow )
+ {
+ mpWindowImpl->mpClientWindow->ImplPosSizeWindow( mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder,
+ mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder,
+ mnOutWidth-mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder,
+ mnOutHeight-mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnBottomBorder,
+ WINDOW_POSSIZE_X | WINDOW_POSSIZE_Y |
+ WINDOW_POSSIZE_WIDTH | WINDOW_POSSIZE_HEIGHT );
+ // Wenn wir ein ClientWindow haben, dann hat dieses fuer die
+ // Applikation auch die Position des FloatingWindows
+ mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos;
+ if ( bNewPos )
+ {
+ if ( mpWindowImpl->mpClientWindow->IsVisible() )
+ {
+ mpWindowImpl->mpClientWindow->ImplCallMove();
+ }
+ else
+ {
+ mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = TRUE;
+ }
+ }
+ }
+// else
+// {
+// if ( mpWindowImpl->mpBorderWindow )
+// mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos;
+// }
+
+ // Move()/Resize() werden erst bei Show() gerufen, damit min. eins vor
+ // einem Show() kommt
+ if ( IsVisible() )
+ {
+ if ( bNewPos )
+ {
+ ImplCallMove();
+ }
+ if ( bNewSize )
+ {
+ ImplCallResize();
+ }
+ }
+ else
+ {
+ if ( bNewPos )
+ mpWindowImpl->mbCallMove = TRUE;
+ if ( bNewSize )
+ mpWindowImpl->mbCallResize = TRUE;
+ }
+
+ BOOL bUpdateSysObjClip = FALSE;
+ if ( IsReallyVisible() )
+ {
+ if ( bNewPos || bNewSize )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev )
+ ImplDeleteOverlapBackground();
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+ // Clip-Flag neu setzen
+ bUpdateSysObjClip = !ImplSetClipFlag( TRUE );
+ }
+
+ // Fensterinhalt invalidieren ?
+ if ( bNewPos || (mnOutWidth > nOldOutWidth) || (mnOutHeight > nOldOutHeight) )
+ {
+ if ( bNewPos )
+ {
+ BOOL bInvalidate = FALSE;
+ BOOL bParentPaint = TRUE;
+ if ( !ImplIsOverlapWindow() )
+ bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled();
+ if ( bCopyBits && bParentPaint && !HasPaintEvent() )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ if ( mpWindowImpl->mbWinRegion )
+ aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
+ ImplClipBoundaries( aRegion, FALSE, TRUE );
+ if ( !pOverlapRegion->IsEmpty() )
+ {
+ pOverlapRegion->Move( mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY );
+ aRegion.Exclude( *pOverlapRegion );
+ }
+ if ( !aRegion.IsEmpty() )
+ {
+ // Paint-Bereiche anpassen
+ ImplMoveAllInvalidateRegions( Rectangle( Point( nOldOutOffX, nOldOutOffY ),
+ Size( nOldOutWidth, nOldOutHeight ) ),
+ mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY,
+ TRUE );
+ SalGraphics* pGraphics = ImplGetFrameGraphics();
+ if ( pGraphics )
+ {
+ const bool bSelectClipRegion = ImplSelectClipRegion( aRegion, pGraphics );
+ if ( bSelectClipRegion )
+ {
+ pGraphics->CopyArea( mnOutOffX, mnOutOffY,
+ nOldOutOffX, nOldOutOffY,
+ nOldOutWidth, nOldOutHeight,
+ SAL_COPYAREA_WINDOWINVALIDATE, this );
+ }
+ else
+ bInvalidate = TRUE;
+ }
+ else
+ bInvalidate = TRUE;
+ if ( !bInvalidate )
+ {
+ if ( !pOverlapRegion->IsEmpty() )
+ ImplInvalidateFrameRegion( pOverlapRegion, INVALIDATE_CHILDREN );
+ }
+ }
+ else
+ bInvalidate = TRUE;
+ }
+ else
+ bInvalidate = TRUE;
+ if ( bInvalidate )
+ ImplInvalidateFrameRegion( NULL, INVALIDATE_CHILDREN );
+ }
+ else
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ aRegion.Exclude( *pOldRegion );
+ if ( mpWindowImpl->mbWinRegion )
+ aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
+ ImplClipBoundaries( aRegion, FALSE, TRUE );
+ if ( !aRegion.IsEmpty() )
+ ImplInvalidateFrameRegion( &aRegion, INVALIDATE_CHILDREN );
+ }
+ }
+
+ // Parent oder Overlaps invalidieren
+ if ( bNewPos ||
+ (mnOutWidth < nOldOutWidth) || (mnOutHeight < nOldOutHeight) )
+ {
+ Region aRegion( *pOldRegion );
+ if ( !mpWindowImpl->mbPaintTransparent )
+ ImplExcludeWindowRegion( aRegion );
+ ImplClipBoundaries( aRegion, FALSE, TRUE );
+ if ( !aRegion.IsEmpty() && !mpWindowImpl->mpBorderWindow )
+ ImplInvalidateParentFrameRegion( aRegion );
+ }
+ }
+
+ // System-Objekte anpassen
+ if ( bUpdateSysObjClip )
+ ImplUpdateSysObjClip();
+ if ( bUpdateSysObjPos )
+ ImplUpdateSysObjPos();
+ if ( bNewSize && mpWindowImpl->mpSysObj )
+ mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
+ }
+
+ if ( pOverlapRegion )
+ delete pOverlapRegion;
+ if ( pOldRegion )
+ delete pOldRegion;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplToBottomChild()
+{
+ if ( !ImplIsOverlapWindow() && !mpWindowImpl->mbReallyVisible && (mpWindowImpl->mpParent->mpWindowImpl->mpLastChild != this) )
+ {
+ // Fenster an das Ende der Liste setzen
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
+ else
+ mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
+ mpWindowImpl->mpPrev = mpWindowImpl->mpParent->mpWindowImpl->mpLastChild;
+ mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = this;
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
+ mpWindowImpl->mpNext = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcToTop( ImplCalcToTopData* pPrevData )
+{
+ DBG_ASSERT( ImplIsOverlapWindow(), "Window::ImplCalcToTop(): Is not a OverlapWindow" );
+
+ if ( !mpWindowImpl->mbFrame )
+ {
+ if ( IsReallyVisible() )
+ {
+ // Region berechnen, wo das Fenster mit anderen Fenstern ueberlappt
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ Region aInvalidateRegion;
+ ImplCalcOverlapRegionOverlaps( aRegion, aInvalidateRegion );
+
+ if ( !aInvalidateRegion.IsEmpty() )
+ {
+ ImplCalcToTopData* pData = new ImplCalcToTopData;
+ pPrevData->mpNext = pData;
+ pData->mpNext = NULL;
+ pData->mpWindow = this;
+ pData->mpInvalidateRegion = new Region( aInvalidateRegion );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcChildOverlapToTop( ImplCalcToTopData* pPrevData )
+{
+ DBG_ASSERT( ImplIsOverlapWindow(), "Window::ImplCalcChildOverlapToTop(): Is not a OverlapWindow" );
+
+ ImplCalcToTop( pPrevData );
+ if ( pPrevData->mpNext )
+ pPrevData = pPrevData->mpNext;
+
+ Window* pOverlap = mpWindowImpl->mpFirstOverlap;
+ while ( pOverlap )
+ {
+ pOverlap->ImplCalcToTop( pPrevData );
+ if ( pPrevData->mpNext )
+ pPrevData = pPrevData->mpNext;
+ pOverlap = pOverlap->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplToTop( USHORT nFlags )
+{
+ DBG_ASSERT( ImplIsOverlapWindow(), "Window::ImplToTop(): Is not a OverlapWindow" );
+
+ if ( mpWindowImpl->mbFrame )
+ {
+ // Wenn in das externe Fenster geklickt wird, ist dieses
+ // dafuer zustaendig dafuer zu sorgen, das unser Frame
+ // nach vorne kommt
+ if ( !mpWindowImpl->mpFrameData->mbHasFocus &&
+ !mpWindowImpl->mpFrameData->mbSysObjFocus &&
+ !mpWindowImpl->mpFrameData->mbInSysObjFocusHdl &&
+ !mpWindowImpl->mpFrameData->mbInSysObjToTopHdl )
+ {
+ // do not bring floating windows on the client to top
+ if( !ImplGetClientWindow() || !(ImplGetClientWindow()->GetStyle() & WB_SYSTEMFLOATWIN) )
+ {
+ USHORT nSysFlags = 0;
+ if ( nFlags & TOTOP_RESTOREWHENMIN )
+ nSysFlags |= SAL_FRAME_TOTOP_RESTOREWHENMIN;
+ if ( nFlags & TOTOP_FOREGROUNDTASK )
+ nSysFlags |= SAL_FRAME_TOTOP_FOREGROUNDTASK;
+ if ( nFlags & TOTOP_GRABFOCUSONLY )
+ nSysFlags |= SAL_FRAME_TOTOP_GRABFOCUS_ONLY;
+ mpWindowImpl->mpFrame->ToTop( nSysFlags );
+ }
+ }
+ }
+ else
+ {
+ if ( mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap != this )
+ {
+ // Fenster aus der Liste entfernen
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
+ if ( mpWindowImpl->mpNext )
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
+ else
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
+
+ // AlwaysOnTop beruecksichtigen
+ BOOL bOnTop = IsAlwaysOnTopEnabled();
+ Window* pNextWin = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
+ if ( !bOnTop )
+ {
+ while ( pNextWin )
+ {
+ if ( !pNextWin->IsAlwaysOnTopEnabled() )
+ break;
+ pNextWin = pNextWin->mpWindowImpl->mpNext;
+ }
+ }
+
+ // TopLevel abpruefen
+ BYTE nTopLevel = mpWindowImpl->mpOverlapData->mnTopLevel;
+ while ( pNextWin )
+ {
+ if ( (bOnTop != pNextWin->IsAlwaysOnTopEnabled()) ||
+ (nTopLevel <= pNextWin->mpWindowImpl->mpOverlapData->mnTopLevel) )
+ break;
+ pNextWin = pNextWin->mpWindowImpl->mpNext;
+ }
+
+ // Fenster in die Liste wieder eintragen
+ mpWindowImpl->mpNext = pNextWin;
+ if ( pNextWin )
+ {
+ mpWindowImpl->mpPrev = pNextWin->mpWindowImpl->mpPrev;
+ pNextWin->mpWindowImpl->mpPrev = this;
+ }
+ else
+ {
+ mpWindowImpl->mpPrev = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap;
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = this;
+ }
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
+ else
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = this;
+
+ // ClipRegion muss von diesem Fenster und allen weiteren
+ // ueberlappenden Fenstern neu berechnet werden.
+ if ( IsReallyVisible() )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+ mpWindowImpl->mpOverlapWindow->ImplSetClipFlagOverlapWindows();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplStartToTop( USHORT nFlags )
+{
+ ImplCalcToTopData aStartData;
+ ImplCalcToTopData* pCurData;
+ ImplCalcToTopData* pNextData;
+ Window* pOverlapWindow;
+ if ( ImplIsOverlapWindow() )
+ pOverlapWindow = this;
+ else
+ pOverlapWindow = mpWindowImpl->mpOverlapWindow;
+
+ // Zuerst die Paint-Bereiche berechnen
+ Window* pTempOverlapWindow = pOverlapWindow;
+ aStartData.mpNext = NULL;
+ pCurData = &aStartData;
+ do
+ {
+ pTempOverlapWindow->ImplCalcToTop( pCurData );
+ if ( pCurData->mpNext )
+ pCurData = pCurData->mpNext;
+ pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ while ( !pTempOverlapWindow->mpWindowImpl->mbFrame );
+ // Dann die Paint-Bereiche der ChildOverlap-Windows berechnen
+ pTempOverlapWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pTempOverlapWindow )
+ {
+ pTempOverlapWindow->ImplCalcToTop( pCurData );
+ if ( pCurData->mpNext )
+ pCurData = pCurData->mpNext;
+ pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpNext;
+ }
+
+ // Dann die Fenster-Verkettung aendern
+ pTempOverlapWindow = pOverlapWindow;
+ do
+ {
+ pTempOverlapWindow->ImplToTop( nFlags );
+ pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ while ( !pTempOverlapWindow->mpWindowImpl->mbFrame );
+ // Und zum Schluss invalidieren wir die ungueltigen Bereiche
+ pCurData = aStartData.mpNext;
+ while ( pCurData )
+ {
+ pCurData->mpWindow->ImplInvalidateFrameRegion( pCurData->mpInvalidateRegion, INVALIDATE_CHILDREN );
+ pNextData = pCurData->mpNext;
+ delete pCurData->mpInvalidateRegion;
+ delete pCurData;
+ pCurData = pNextData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplFocusToTop( USHORT nFlags, BOOL bReallyVisible )
+{
+ // Soll Focus auch geholt werden?
+ if ( !(nFlags & TOTOP_NOGRABFOCUS) )
+ {
+ // Erstes Fenster mit GrabFocus-Activate bekommt den Focus
+ Window* pFocusWindow = this;
+ while ( !pFocusWindow->ImplIsOverlapWindow() )
+ {
+ // Nur wenn Fenster kein Border-Fenster hat, da wir
+ // immer das dazugehoerende BorderFenster finden wollen
+ if ( !pFocusWindow->mpWindowImpl->mpBorderWindow )
+ {
+ if ( pFocusWindow->mpWindowImpl->mnActivateMode & ACTIVATE_MODE_GRABFOCUS )
+ break;
+ }
+ pFocusWindow = pFocusWindow->ImplGetParent();
+ }
+ if ( (pFocusWindow->mpWindowImpl->mnActivateMode & ACTIVATE_MODE_GRABFOCUS) &&
+ !pFocusWindow->HasChildPathFocus( TRUE ) )
+ pFocusWindow->GrabFocus();
+ }
+
+ if ( bReallyVisible )
+ ImplGenerateMouseMove();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplShowAllOverlaps()
+{
+ Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ if ( pOverlapWindow->mpWindowImpl->mbOverlapVisible )
+ {
+ pOverlapWindow->Show( TRUE, SHOW_NOACTIVATE );
+ pOverlapWindow->mpWindowImpl->mbOverlapVisible = FALSE;
+ }
+
+ pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplHideAllOverlaps()
+{
+ Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ if ( pOverlapWindow->IsVisible() )
+ {
+ pOverlapWindow->mpWindowImpl->mbOverlapVisible = TRUE;
+ pOverlapWindow->Show( FALSE );
+ }
+
+ pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallMouseMove( USHORT nMouseCode, BOOL bModChanged )
+{
+ if ( mpWindowImpl->mpFrameData->mbMouseIn && mpWindowImpl->mpFrameWindow->mpWindowImpl->mbReallyVisible )
+ {
+ ULONG nTime = Time::GetSystemTicks();
+ long nX = mpWindowImpl->mpFrameData->mnLastMouseX;
+ long nY = mpWindowImpl->mpFrameData->mnLastMouseY;
+ USHORT nCode = nMouseCode;
+ USHORT nMode = mpWindowImpl->mpFrameData->mnMouseMode;
+ BOOL bLeave;
+ // Auf MouseLeave testen
+ if ( ((nX < 0) || (nY < 0) ||
+ (nX >= mpWindowImpl->mpFrameWindow->mnOutWidth) ||
+ (nY >= mpWindowImpl->mpFrameWindow->mnOutHeight)) &&
+ !ImplGetSVData()->maWinData.mpCaptureWin )
+ bLeave = TRUE;
+ else
+ bLeave = FALSE;
+ nMode |= MOUSE_SYNTHETIC;
+ if ( bModChanged )
+ nMode |= MOUSE_MODIFIERCHANGED;
+ ImplHandleMouseEvent( mpWindowImpl->mpFrameWindow, EVENT_MOUSEMOVE, bLeave, nX, nY, nTime, nCode, nMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplGenerateMouseMove()
+{
+ if ( !mpWindowImpl->mpFrameData->mnMouseMoveId )
+ Application::PostUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId, LINK( mpWindowImpl->mpFrameWindow, Window, ImplGenerateMouseMoveHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplGenerateMouseMoveHdl, void*, EMPTYARG )
+{
+ mpWindowImpl->mpFrameData->mnMouseMoveId = 0;
+ Window* pCaptureWin = ImplGetSVData()->maWinData.mpCaptureWin;
+ if( ! pCaptureWin ||
+ (pCaptureWin->mpWindowImpl && pCaptureWin->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame)
+ )
+ {
+ ImplCallMouseMove( mpWindowImpl->mpFrameData->mnMouseCode );
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvertFocus( const Rectangle& rRect )
+{
+ InvertTracking( rRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallFocusChangeActivate( Window* pNewOverlapWindow,
+ Window* pOldOverlapWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pNewRealWindow;
+ Window* pOldRealWindow;
+ Window* pLastRealWindow;
+ BOOL bCallActivate = TRUE;
+ BOOL bCallDeactivate = TRUE;
+
+ pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
+ pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
+ if ( (pOldRealWindow->GetType() != WINDOW_FLOATINGWINDOW) ||
+ pOldRealWindow->GetActivateMode() )
+ {
+ if ( (pNewRealWindow->GetType() == WINDOW_FLOATINGWINDOW) &&
+ !pNewRealWindow->GetActivateMode() )
+ {
+ pSVData->maWinData.mpLastDeacWin = pOldOverlapWindow;
+ bCallDeactivate = FALSE;
+ }
+ }
+ else if ( (pNewRealWindow->GetType() != WINDOW_FLOATINGWINDOW) ||
+ pNewRealWindow->GetActivateMode() )
+ {
+ if ( pSVData->maWinData.mpLastDeacWin )
+ {
+ if ( pSVData->maWinData.mpLastDeacWin == pNewOverlapWindow )
+ bCallActivate = FALSE;
+ else
+ {
+ pLastRealWindow = pSVData->maWinData.mpLastDeacWin->ImplGetWindow();
+ pSVData->maWinData.mpLastDeacWin->mpWindowImpl->mbActive = FALSE;
+ pSVData->maWinData.mpLastDeacWin->Deactivate();
+ if ( pLastRealWindow != pSVData->maWinData.mpLastDeacWin )
+ {
+ pLastRealWindow->mpWindowImpl->mbActive = TRUE;
+ pLastRealWindow->Activate();
+ }
+ }
+ pSVData->maWinData.mpLastDeacWin = NULL;
+ }
+ }
+
+ if ( bCallDeactivate )
+ {
+ if( pOldOverlapWindow->mpWindowImpl->mbActive )
+ {
+ pOldOverlapWindow->mpWindowImpl->mbActive = FALSE;
+ pOldOverlapWindow->Deactivate();
+ }
+ if ( pOldRealWindow != pOldOverlapWindow )
+ {
+ if( pOldRealWindow->mpWindowImpl->mbActive )
+ {
+ pOldRealWindow->mpWindowImpl->mbActive = FALSE;
+ pOldRealWindow->Deactivate();
+ }
+ }
+ }
+ if ( bCallActivate && ! pNewOverlapWindow->mpWindowImpl->mbActive )
+ {
+ if( ! pNewOverlapWindow->mpWindowImpl->mbActive )
+ {
+ pNewOverlapWindow->mpWindowImpl->mbActive = TRUE;
+ pNewOverlapWindow->Activate();
+ }
+ if ( pNewRealWindow != pNewOverlapWindow )
+ {
+ if( ! pNewRealWindow->mpWindowImpl->mbActive )
+ {
+ pNewRealWindow->mpWindowImpl->mbActive = TRUE;
+ pNewRealWindow->Activate();
+ }
+ }
+ }
+}
+
+static bool IsWindowFocused(const WindowImpl& rWinImpl)
+{
+ if (rWinImpl.mpSysObj)
+ return true;
+
+ if (rWinImpl.mpFrameData->mbHasFocus)
+ return true;
+
+ if (rWinImpl.mbFakeFocusSet)
+ return true;
+
+ return false;
+}
+
+// -----------------------------------------------------------------------
+void Window::ImplGrabFocus( USHORT nFlags )
+{
+ // #143570# no focus for destructing windows
+ if( mpWindowImpl->mbInDtor )
+ return;
+
+ // some event listeners do really bad stuff
+ // => prepare for the worst
+ ImplDelData aDogTag( this );
+
+ // Currently the client window should always get the focus
+ // Should the border window at some point be focusable
+ // we need to change all GrabFocus() instances in VCL,
+ // e.g. in ToTop()
+
+ if ( mpWindowImpl->mpClientWindow )
+ {
+ // For a lack of design we need a little hack here to
+ // ensure that dialogs on close pass the focus back to
+ // the correct window
+ if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow != this) &&
+ !(mpWindowImpl->mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) &&
+ mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
+ mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
+ ! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
+ )
+ mpWindowImpl->mpLastFocusWindow->GrabFocus();
+ else
+ mpWindowImpl->mpClientWindow->GrabFocus();
+ return;
+ }
+ else if ( mpWindowImpl->mbFrame )
+ {
+ // For a lack of design we need a little hack here to
+ // ensure that dialogs on close pass the focus back to
+ // the correct window
+ if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow != this) &&
+ !(mpWindowImpl->mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) &&
+ mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
+ mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
+ ! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
+ )
+ {
+ mpWindowImpl->mpLastFocusWindow->GrabFocus();
+ return;
+ }
+ }
+
+ // If the Window is disabled, then we don't change the focus
+ if ( !IsEnabled() || !IsInputEnabled() || IsInModalMode() )
+ return;
+
+ // we only need to set the focus if it is not already set
+ // note: if some other frame is waiting for an asynchrounous focus event
+ // we also have to post an asynchronous focus event for this frame
+ // which is done using ToTop
+ ImplSVData* pSVData = ImplGetSVData();
+
+ BOOL bAsyncFocusWaiting = FALSE;
+ Window *pFrame = pSVData->maWinData.mpFirstFrame;
+ while( pFrame )
+ {
+ if( pFrame != mpWindowImpl->mpFrameWindow && pFrame->mpWindowImpl->mpFrameData->mnFocusId )
+ {
+ bAsyncFocusWaiting = TRUE;
+ break;
+ }
+ pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+
+ bool bHasFocus = IsWindowFocused(*mpWindowImpl);
+
+ BOOL bMustNotGrabFocus = FALSE;
+ // #100242#, check parent hierarchy if some floater prohibits grab focus
+
+ Window *pParent = this;
+ while( pParent )
+ {
+ // #102158#, ignore grabfocus only if the floating parent grabs keyboard focus by itself (GrabsFocus())
+ // otherwise we cannot set the focus in a floating toolbox
+ if( ( (pParent->mpWindowImpl->mbFloatWin && ((FloatingWindow*)pParent)->GrabsFocus()) || ( pParent->GetStyle() & WB_SYSTEMFLOATWIN ) ) && !( pParent->GetStyle() & WB_MOVEABLE ) )
+ {
+ bMustNotGrabFocus = TRUE;
+ break;
+ }
+ pParent = pParent->mpWindowImpl->mpParent;
+ }
+
+
+ if ( ( pSVData->maWinData.mpFocusWin != this && ! mpWindowImpl->mbInDtor ) || ( bAsyncFocusWaiting && !bHasFocus && !bMustNotGrabFocus ) )
+ {
+ // EndExtTextInput if it is not the same window
+ if ( pSVData->maWinData.mpExtTextInputWin &&
+ (pSVData->maWinData.mpExtTextInputWin != this) )
+ pSVData->maWinData.mpExtTextInputWin->EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
+
+ // Dieses Fenster als letztes FocusWindow merken
+ Window* pOverlapWindow = ImplGetFirstOverlapWindow();
+ pOverlapWindow->mpWindowImpl->mpLastFocusWindow = this;
+ mpWindowImpl->mpFrameData->mpFocusWin = this;
+
+ if( !bHasFocus )
+ {
+ // menue windows never get the system focus
+ // the application will keep the focus
+ if( bMustNotGrabFocus )
+ return;
+ else
+ {
+ // Hier setzen wir schon den Focus um, da ToTop() den Focus
+ // nicht auf ein anderes Fenster setzen darf
+ //DBG_WARNING( "Window::GrabFocus() - Frame doesn't have the focus" );
+ mpWindowImpl->mpFrame->ToTop( SAL_FRAME_TOTOP_GRABFOCUS | SAL_FRAME_TOTOP_GRABFOCUS_ONLY );
+ return;
+ }
+ }
+
+ Window* pOldFocusWindow = pSVData->maWinData.mpFocusWin;
+ ImplDelData aOldFocusDel( pOldFocusWindow );
+
+ pSVData->maWinData.mpFocusWin = this;
+
+ if ( pOldFocusWindow )
+ {
+ // Cursor hiden
+ if ( pOldFocusWindow->mpWindowImpl->mpCursor )
+ pOldFocusWindow->mpWindowImpl->mpCursor->ImplHide();
+ }
+
+ // !!!!! Wegen altem SV-Office Activate/Deavtivate Handling
+ // !!!!! erstmal so wie frueher
+ if ( pOldFocusWindow )
+ {
+ // Focus merken
+ Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
+ Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
+ if ( pOldOverlapWindow != pNewOverlapWindow )
+ ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
+ }
+ else
+ {
+ Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
+ Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
+ pNewOverlapWindow->mpWindowImpl->mbActive = TRUE;
+ pNewOverlapWindow->Activate();
+ if ( pNewRealWindow != pNewOverlapWindow )
+ {
+ pNewRealWindow->mpWindowImpl->mbActive = TRUE;
+ pNewRealWindow->Activate();
+ }
+ }
+/*
+ // call Deactivate and Activate
+ Window* pDeactivateParent;
+ Window* pActivateParent;
+ Window* pParent;
+ Window* pLastParent;
+ pDeactivateParent = pOldFocusWindow;
+ while ( pDeactivateParent )
+ {
+ pParent = pDeactivateParent;
+ if ( pParent->ImplIsChild( this ) )
+ break;
+
+ if ( pDeactivateParent->ImplIsOverlapWindow() )
+ {
+ if ( !pDeactivateParent->mpWindowImpl->mbParentActive )
+ break;
+ }
+
+ pDeactivateParent = pDeactivateParent->ImplGetParent();
+ }
+ if ( pOldFocusWindow )
+ {
+ pActivateParent = this;
+ while ( pActivateParent )
+ {
+ pParent = pActivateParent;
+ if ( pParent->ImplIsChild( pOldFocusWindow ) )
+ break;
+
+ if ( pActivateParent->ImplIsOverlapWindow() )
+ {
+ if ( !pActivateParent->mpWindowImpl->mbParentActive )
+ break;
+ }
+
+ pActivateParent = pActivateParent->ImplGetParent();
+ }
+ }
+ else
+ {
+ if ( ImplIsOverlapWindow() )
+ pActivateParent = this;
+ else
+ pActivateParent = mpWindowImpl->mpOverlapWindow;
+ while ( pActivateParent )
+ {
+ if ( pActivateParent->ImplIsOverlapWindow() )
+ {
+ if ( !pActivateParent->mpWindowImpl->mbParentActive )
+ break;
+ }
+
+ pActivateParent = pActivateParent->ImplGetParent();
+ }
+ }
+ if ( pDeactivateParent )
+ {
+ do
+ {
+ pLastParent = pOldFocusWindow;
+ if ( pLastParent != pDeactivateParent )
+ {
+ pParent = pLastParent->ImplGetParent();
+ while ( pParent )
+ {
+ if ( pParent == pDeactivateParent )
+ break;
+ pLastParent = pParent;
+ pParent = pParent->ImplGetParent();
+ }
+ }
+ else
+ pParent = pLastParent;
+
+ pParent->mpWindowImpl->mbActive = FALSE;
+ pParent->Deactivate();
+ pDeactivateParent = pLastParent;
+ }
+ while ( pDeactivateParent != pOldFocusWindow );
+ }
+ do
+ {
+ pLastParent = this;
+ if ( pLastParent != pActivateParent )
+ {
+ pParent = pLastParent->ImplGetParent();
+ while ( pParent )
+ {
+ if ( pParent == pActivateParent )
+ break;
+ pLastParent = pParent;
+ pParent = pParent->ImplGetParent();
+ }
+ }
+ else
+ pParent = pLastParent;
+
+ pParent->mpWindowImpl->mbActive = TRUE;
+ pParent->Activate();
+ pActivateParent = pLastParent;
+ }
+ while ( pActivateParent != this );
+*/
+ // call Get- and LoseFocus
+ if ( pOldFocusWindow && ! aOldFocusDel.IsDelete() )
+ {
+ if ( pOldFocusWindow->IsTracking() &&
+ (pSVData->maWinData.mnTrackFlags & STARTTRACK_FOCUSCANCEL) )
+ pOldFocusWindow->EndTracking( ENDTRACK_CANCEL | ENDTRACK_FOCUS );
+ NotifyEvent aNEvt( EVENT_LOSEFOCUS, pOldFocusWindow );
+ if ( !ImplCallPreNotify( aNEvt ) )
+ pOldFocusWindow->LoseFocus();
+ pOldFocusWindow->ImplCallDeactivateListeners( this );
+ }
+
+ if ( pSVData->maWinData.mpFocusWin == this )
+ {
+ if ( mpWindowImpl->mpSysObj )
+ {
+ mpWindowImpl->mpFrameData->mpFocusWin = this;
+ if ( !mpWindowImpl->mpFrameData->mbInSysObjFocusHdl )
+ mpWindowImpl->mpSysObj->GrabFocus();
+ }
+
+ if ( pSVData->maWinData.mpFocusWin == this )
+ {
+ if ( mpWindowImpl->mpCursor )
+ mpWindowImpl->mpCursor->ImplShow();
+ mpWindowImpl->mbInFocusHdl = TRUE;
+ mpWindowImpl->mnGetFocusFlags = nFlags;
+ // if we're changing focus due to closing a popup floating window
+ // notify the new focus window so it can restore the inner focus
+ // eg, toolboxes can select their recent active item
+ if( pOldFocusWindow &&
+ ! aOldFocusDel.IsDelete() &&
+ ( pOldFocusWindow->GetDialogControlFlags() & WINDOW_DLGCTRL_FLOATWIN_POPUPMODEEND_CANCEL ) )
+ mpWindowImpl->mnGetFocusFlags |= GETFOCUS_FLOATWIN_POPUPMODEEND_CANCEL;
+ NotifyEvent aNEvt( EVENT_GETFOCUS, this );
+ if ( !ImplCallPreNotify( aNEvt ) && !aDogTag.IsDelete() )
+ GetFocus();
+ if( !aDogTag.IsDelete() )
+ ImplCallActivateListeners( (pOldFocusWindow && ! aOldFocusDel.IsDelete()) ? pOldFocusWindow : NULL );
+ if( !aDogTag.IsDelete() )
+ {
+ mpWindowImpl->mnGetFocusFlags = 0;
+ mpWindowImpl->mbInFocusHdl = FALSE;
+ }
+ }
+ }
+
+ GetpApp()->FocusChanged();
+ ImplNewInputContext();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplNewInputContext()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pFocusWin = pSVData->maWinData.mpFocusWin;
+ if ( !pFocusWin )
+ return;
+
+ // Is InputContext changed?
+ const InputContext& rInputContext = pFocusWin->GetInputContext();
+ if ( rInputContext == pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext )
+ return;
+
+ pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext = rInputContext;
+
+ SalInputContext aNewContext;
+ const Font& rFont = rInputContext.GetFont();
+ const XubString& rFontName = rFont.GetName();
+ ImplFontEntry* pFontEntry = NULL;
+ aNewContext.mpFont = NULL;
+ if ( rFontName.Len() )
+ {
+ Size aSize = pFocusWin->ImplLogicToDevicePixel( rFont.GetSize() );
+ if ( !aSize.Height() )
+ {
+ // Nur dann Defaultgroesse setzen, wenn Fonthoehe auch in logischen
+ // Koordinaaten 0 ist
+ if ( rFont.GetSize().Height() )
+ aSize.Height() = 1;
+ else
+ aSize.Height() = (12*pFocusWin->mnDPIY)/72;
+ }
+ // TODO: No display device uses ImplDirectFontSubstitution thingy, right? => remove it
+ ImplDirectFontSubstitution* pFontSubst = NULL;
+ //if( pFocusWin->mpOutDevData )
+ // pFontSubst = &pFocusWin->mpOutDevData->maDevFontSubst;
+ pFontEntry = pFocusWin->mpFontCache->GetFontEntry( pFocusWin->mpFontList,
+ rFont, aSize, static_cast<float>(aSize.Height()), pFontSubst );
+ if ( pFontEntry )
+ aNewContext.mpFont = &pFontEntry->maFontSelData;
+ }
+ aNewContext.meLanguage = rFont.GetLanguage();
+ aNewContext.mnOptions = rInputContext.GetOptions();
+ pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
+
+ if ( pFontEntry )
+ pFocusWin->mpFontCache->Release( pFontEntry );
+}
+
+// -----------------------------------------------------------------------
+
+Window::Window( WindowType nType )
+{
+ DBG_CTOR( Window, ImplDbgCheckWindow );
+
+ ImplInitWindowData( nType );
+}
+
+// -----------------------------------------------------------------------
+
+Window::Window( Window* pParent, WinBits nStyle )
+{
+ DBG_CTOR( Window, ImplDbgCheckWindow );
+
+ ImplInitWindowData( WINDOW_WINDOW );
+ ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Window::Window( Window* pParent, const ResId& rResId )
+{
+ DBG_CTOR( Window, ImplDbgCheckWindow );
+
+ ImplInitWindowData( WINDOW_WINDOW );
+ rResId.SetRT( RSC_WINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle, NULL );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+#if OSL_DEBUG_LEVEL > 0
+namespace
+{
+ void lcl_appendWindowInfo( ByteString& io_rErrorString, const Window& i_rWindow )
+ {
+ // skip border windows, they don't carry information which helps diagnosing the problem
+ const Window* pWindow( &i_rWindow );
+ while ( pWindow && ( pWindow->GetType() == WINDOW_BORDERWINDOW ) )
+ pWindow = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ if ( !pWindow )
+ pWindow = &i_rWindow;
+
+ io_rErrorString += char(13);
+ io_rErrorString += typeid( *pWindow ).name();
+ io_rErrorString += " (window text: '";
+ io_rErrorString += ByteString( pWindow->GetText(), RTL_TEXTENCODING_UTF8 );
+ io_rErrorString += "')";
+ }
+}
+#endif
+// -----------------------------------------------------------------------
+
+Window::~Window()
+{
+ vcl::LazyDeletor<Window>::Undelete( this );
+
+ DBG_DTOR( Window, ImplDbgCheckWindow );
+ DBG_ASSERT( !mpWindowImpl->mbInDtor, "~Window - already in DTOR!" );
+
+
+ // remove Key and Mouse events issued by Application::PostKey/MouseEvent
+ Application::RemoveMouseAndKeyEvents( this );
+
+ // Dispose of the canvas implementation (which, currently, has an
+ // own wrapper window as a child to this one.
+ Reference< rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
+ if( xCanvas.is() )
+ {
+ uno::Reference < lang::XComponent > xCanvasComponent( xCanvas,
+ uno::UNO_QUERY );
+ if( xCanvasComponent.is() )
+ xCanvasComponent->dispose();
+ }
+
+ mpWindowImpl->mbInDtor = TRUE;
+
+ ImplCallEventListeners( VCLEVENT_OBJECT_DYING );
+
+ // do not send child events for frames that were registered as native frames
+ if( !ImplIsAccessibleNativeFrame() && mpWindowImpl->mbReallyVisible )
+ if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
+ GetAccessibleParentWindow()->ImplCallEventListeners( VCLEVENT_WINDOW_CHILDDESTROYED, this );
+
+ // remove associated data structures from dockingmanager
+ ImplGetDockingManager()->RemoveWindow( this );
+
+
+ // remove ownerdraw decorated windows from list in the top-most frame window
+ if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
+ {
+ ::std::vector< Window* >& rList = ImplGetOwnerDrawList();
+ ::std::vector< Window* >::iterator p;
+ p = ::std::find( rList.begin(), rList.end(), this );
+ if( p != rList.end() )
+ rList.erase( p );
+ }
+
+ // shutdown drag and drop
+ ::com::sun::star::uno::Reference < ::com::sun::star::lang::XComponent > xDnDComponent( mpWindowImpl->mxDNDListenerContainer, ::com::sun::star::uno::UNO_QUERY );
+
+ if( xDnDComponent.is() )
+ xDnDComponent->dispose();
+
+ if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
+ {
+ try
+ {
+ // deregister drop target listener
+ if( mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
+ {
+ Reference< XDragGestureRecognizer > xDragGestureRecognizer =
+ Reference< XDragGestureRecognizer > (mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
+ if( xDragGestureRecognizer.is() )
+ {
+ xDragGestureRecognizer->removeDragGestureListener(
+ Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
+ }
+
+ mpWindowImpl->mpFrameData->mxDropTarget->removeDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
+ mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
+ }
+
+ // shutdown drag and drop for this frame window
+ Reference< XComponent > xComponent( mpWindowImpl->mpFrameData->mxDropTarget, UNO_QUERY );
+
+ // DNDEventDispatcher does not hold a reference of the DropTarget,
+ // so it's ok if it does not support XComponent
+ if( xComponent.is() )
+ xComponent->dispose();
+ }
+
+ catch ( Exception exc )
+ {
+ // can be safely ignored here.
+ }
+ }
+
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper( FALSE );
+ if ( pWrapper )
+ pWrapper->WindowDestroyed( this );
+
+ // MT: Must be called after WindowDestroyed!
+ // Otherwise, if the accessible is a VCLXWindow, it will try to destroy this window again!
+ // But accessibility implementations from applications need this dispose.
+ if ( mpWindowImpl->mxAccessible.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xC( mpWindowImpl->mxAccessible, ::com::sun::star::uno::UNO_QUERY );
+ if ( xC.is() )
+ xC->dispose();
+ }
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maHelpData.mpHelpWin && (pSVData->maHelpData.mpHelpWin->GetParent() == this) )
+ ImplDestroyHelpWindow( true );
+
+ DBG_ASSERT( pSVData->maWinData.mpTrackWin != this,
+ "Window::~Window(): Window is in TrackingMode" );
+ DBG_ASSERT( pSVData->maWinData.mpCaptureWin != this,
+ "Window::~Window(): Window has the mouse captured" );
+ // #103442# DefModalDialogParent is now determined on-the-fly, so this pointer is unimportant now
+ //DBG_ASSERT( pSVData->maWinData.mpDefDialogParent != this,
+ // "Window::~Window(): Window is DefModalDialogParent" );
+
+ // Wegen alter kompatibilitaet
+ if ( pSVData->maWinData.mpTrackWin == this )
+ EndTracking();
+ if ( pSVData->maWinData.mpCaptureWin == this )
+ ReleaseMouse();
+ if ( pSVData->maWinData.mpDefDialogParent == this )
+ pSVData->maWinData.mpDefDialogParent = NULL;
+
+#ifdef DBG_UTIL
+ if ( TRUE ) // always perform these tests in non-pro versions
+ {
+ ByteString aErrorStr;
+ BOOL bError = FALSE;
+ Window* pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
+ while ( pTempWin )
+ {
+ if ( ImplIsRealParentPath( pTempWin ) )
+ {
+ bError = TRUE;
+ lcl_appendWindowInfo( aErrorStr, *pTempWin );
+ }
+ pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
+ }
+ if ( bError )
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") with living SystemWindow(s) destroyed: ";
+ aTempStr += aErrorStr;
+ DBG_ERROR( aTempStr.GetBuffer() );
+ GetpApp()->Abort( String( aTempStr, RTL_TEXTENCODING_UTF8 ) ); // abort in non-pro version, this must be fixed!
+ }
+
+ bError = FALSE;
+ pTempWin = pSVData->maWinData.mpFirstFrame;
+ while ( pTempWin )
+ {
+ if ( ImplIsRealParentPath( pTempWin ) )
+ {
+ bError = TRUE;
+ lcl_appendWindowInfo( aErrorStr, *pTempWin );
+ }
+ pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+ if ( bError )
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") with living SystemWindow(s) destroyed: ";
+ aTempStr += aErrorStr;
+ DBG_ERROR( aTempStr.GetBuffer() );
+ GetpApp()->Abort( String( aTempStr, RTL_TEXTENCODING_UTF8 ) ); // abort in non-pro version, this must be fixed!
+ }
+
+ if ( mpWindowImpl->mpFirstChild )
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") with living Child(s) destroyed: ";
+ pTempWin = mpWindowImpl->mpFirstChild;
+ while ( pTempWin )
+ {
+ lcl_appendWindowInfo( aTempStr, *pTempWin );
+ pTempWin = pTempWin->mpWindowImpl->mpNext;
+ }
+ DBG_ERROR( aTempStr.GetBuffer() );
+ GetpApp()->Abort( String( aTempStr, RTL_TEXTENCODING_UTF8 ) ); // abort in non-pro version, this must be fixed!
+ }
+
+ if ( mpWindowImpl->mpFirstOverlap )
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") with living SystemWindow(s) destroyed: ";
+ pTempWin = mpWindowImpl->mpFirstOverlap;
+ while ( pTempWin )
+ {
+ lcl_appendWindowInfo( aTempStr, *pTempWin );
+ pTempWin = pTempWin->mpWindowImpl->mpNext;
+ }
+ DBG_ERROR( aTempStr.GetBuffer() );
+ GetpApp()->Abort( String( aTempStr, RTL_TEXTENCODING_UTF8 ) ); // abort in non-pro version, this must be fixed!
+ }
+
+ Window* pMyParent = this;
+ SystemWindow* pMySysWin = NULL;
+
+ while ( pMyParent )
+ {
+ if ( pMyParent->IsSystemWindow() )
+ pMySysWin = (SystemWindow*)pMyParent;
+ pMyParent = pMyParent->GetParent();
+ }
+ if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") still in TaskPanelList!";
+ DBG_ERROR( aTempStr.GetBuffer() );
+ GetpApp()->Abort( String( aTempStr, RTL_TEXTENCODING_UTF8 ) ); // abort in non-pro version, this must be fixed!
+ }
+ }
+#endif
+
+ if( mpWindowImpl->mbIsInTaskPaneList )
+ {
+ Window* pMyParent = this;
+ SystemWindow* pMySysWin = NULL;
+
+ while ( pMyParent )
+ {
+ if ( pMyParent->IsSystemWindow() )
+ pMySysWin = (SystemWindow*)pMyParent;
+ pMyParent = pMyParent->GetParent();
+ }
+ if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
+ {
+ pMySysWin->GetTaskPaneList()->RemoveWindow( this );
+ }
+ else
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") not found in TaskPanelList!";
+ DBG_ERROR( aTempStr.GetBuffer() );
+ }
+ }
+
+ // Fenster hiden, um das entsprechende Paint-Handling auszuloesen
+ Hide();
+
+ // Mitteilen, das Fenster zerstoert wird
+ {
+ NotifyEvent aNEvt( EVENT_DESTROY, this );
+ Notify( aNEvt );
+ }
+
+ // EndExtTextInputMode
+ if ( pSVData->maWinData.mpExtTextInputWin == this )
+ {
+ EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
+ if ( pSVData->maWinData.mpExtTextInputWin == this )
+ pSVData->maWinData.mpExtTextInputWin = NULL;
+ }
+
+ // check if the focus window is our child
+ BOOL bHasFocussedChild = FALSE;
+ if( pSVData->maWinData.mpFocusWin && ImplIsRealParentPath( pSVData->maWinData.mpFocusWin ) )
+ {
+ // #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below
+ bHasFocussedChild = TRUE;
+#ifdef DBG_UTIL
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") with focussed child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !";
+ DBG_ERROR( aTempStr.GetBuffer() );
+ GetpApp()->Abort( String( aTempStr, RTL_TEXTENCODING_UTF8 ) ); // abort in non-pro version, this must be fixed!
+#endif
+ }
+
+ // Wenn wir den Focus haben, dann den Focus auf ein anderes Fenster setzen
+ Window* pOverlapWindow = ImplGetFirstOverlapWindow();
+ if ( pSVData->maWinData.mpFocusWin == this
+ || bHasFocussedChild ) // #122232#, see above, try some cleanup
+ {
+ if ( mpWindowImpl->mbFrame )
+ {
+ pSVData->maWinData.mpFocusWin = NULL;
+ pOverlapWindow->mpWindowImpl->mpLastFocusWindow = NULL;
+ GetpApp()->FocusChanged();
+ }
+ else
+ {
+ Window* pParent = GetParent();
+ Window* pBorderWindow = mpWindowImpl->mpBorderWindow;
+ // Bei ueberlappenden Fenstern wird der Focus auf den
+ // Parent vom naechsten FrameWindow gesetzt
+ if ( pBorderWindow )
+ {
+ if ( pBorderWindow->ImplIsOverlapWindow() )
+ pParent = pBorderWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ else if ( ImplIsOverlapWindow() )
+ pParent = mpWindowImpl->mpOverlapWindow;
+
+ if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() && ! pParent->IsInModalMode() )
+ pParent->GrabFocus();
+ else
+ mpWindowImpl->mpFrameWindow->GrabFocus();
+
+ // If the focus was set back to 'this' set it to nothing
+ if ( pSVData->maWinData.mpFocusWin == this )
+ {
+ pSVData->maWinData.mpFocusWin = NULL;
+ pOverlapWindow->mpWindowImpl->mpLastFocusWindow = NULL;
+ GetpApp()->FocusChanged();
+ }
+ }
+ }
+
+
+ if ( pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
+ pOverlapWindow->mpWindowImpl->mpLastFocusWindow = NULL;
+
+ // reset hint for DefModalDialogParent
+ if( pSVData->maWinData.mpActiveApplicationFrame == this )
+ pSVData->maWinData.mpActiveApplicationFrame = NULL;
+
+ // gemerkte Fenster zuruecksetzen
+ if ( mpWindowImpl->mpFrameData->mpFocusWin == this )
+ mpWindowImpl->mpFrameData->mpFocusWin = NULL;
+ if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this )
+ mpWindowImpl->mpFrameData->mpMouseMoveWin = NULL;
+ if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this )
+ mpWindowImpl->mpFrameData->mpMouseDownWin = NULL;
+
+ // Deactivate-Window zuruecksetzen
+ if ( pSVData->maWinData.mpLastDeacWin == this )
+ pSVData->maWinData.mpLastDeacWin = NULL;
+
+ if ( mpWindowImpl->mbFrame )
+ {
+ if ( mpWindowImpl->mpFrameData->mnFocusId )
+ Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId );
+ if ( mpWindowImpl->mpFrameData->mnMouseMoveId )
+ Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId );
+ }
+
+ // Graphic freigeben
+ ImplReleaseGraphics();
+
+ // Evt. anderen Funktion mitteilen, das das Fenster geloescht
+ // wurde
+ ImplDelData* pDelData = mpWindowImpl->mpFirstDel;
+ while ( pDelData )
+ {
+ pDelData->mbDel = TRUE;
+ pDelData->mpWindow = NULL; // #112873# pDel is not associated with a Window anymore
+ pDelData = pDelData->mpNext;
+ }
+
+ // Fenster aus den Listen austragen
+ ImplRemoveWindow( TRUE );
+
+ // de-register as "top window child" at our parent, if necessary
+ if ( mpWindowImpl->mbFrame )
+ {
+ BOOL bIsTopWindow = mpWindowImpl->mpWinData && ( mpWindowImpl->mpWinData->mnIsTopWindow == 1 );
+ if ( mpWindowImpl->mpRealParent && bIsTopWindow )
+ {
+ ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData();
+
+ ::std::list< Window* >::iterator myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(),
+ pParentWinData->maTopWindowChildren.end(), this );
+ DBG_ASSERT( myPos != pParentWinData->maTopWindowChildren.end(), "Window::~Window: inconsistency in top window chain!" );
+ if ( myPos != pParentWinData->maTopWindowChildren.end() )
+ pParentWinData->maTopWindowChildren.erase( myPos );
+ }
+ }
+
+ // Extra Window Daten loeschen
+ if ( mpWindowImpl->mpWinData )
+ {
+ if ( mpWindowImpl->mpWinData->mpExtOldText )
+ delete mpWindowImpl->mpWinData->mpExtOldText;
+ if ( mpWindowImpl->mpWinData->mpExtOldAttrAry )
+ delete mpWindowImpl->mpWinData->mpExtOldAttrAry;
+ if ( mpWindowImpl->mpWinData->mpCursorRect )
+ delete mpWindowImpl->mpWinData->mpCursorRect;
+ if ( mpWindowImpl->mpWinData->mpFocusRect )
+ delete mpWindowImpl->mpWinData->mpFocusRect;
+ if ( mpWindowImpl->mpWinData->mpTrackRect )
+ delete mpWindowImpl->mpWinData->mpTrackRect;
+ if ( mpWindowImpl->mpWinData->mpSmartHelpId )
+ delete mpWindowImpl->mpWinData->mpSmartHelpId;
+ if ( mpWindowImpl->mpWinData->mpSmartUniqueId )
+ delete mpWindowImpl->mpWinData->mpSmartUniqueId;
+
+ delete mpWindowImpl->mpWinData;
+ }
+
+
+ // Overlap-Window-Daten loeschen
+ if ( mpWindowImpl->mpOverlapData )
+ {
+ delete mpWindowImpl->mpOverlapData;
+ }
+
+ // Evt. noch BorderWindow oder Frame zerstoeren
+ if ( mpWindowImpl->mpBorderWindow )
+ delete mpWindowImpl->mpBorderWindow;
+ else if ( mpWindowImpl->mbFrame )
+ {
+ if ( pSVData->maWinData.mpFirstFrame == this )
+ pSVData->maWinData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame;
+ else
+ {
+ Window* pSysWin = pSVData->maWinData.mpFirstFrame;
+ while ( pSysWin->mpWindowImpl->mpFrameData->mpNextFrame != this )
+ pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
+ pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+ mpWindowImpl->mpFrame->SetCallback( NULL, NULL );
+ pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
+ delete mpWindowImpl->mpFrameData;
+ }
+
+ if ( mpWindowImpl->mpChildClipRegion )
+ delete mpWindowImpl->mpChildClipRegion;
+
+ delete mpWindowImpl->mpAccessibleInfos;
+ delete mpWindowImpl->mpControlFont;
+
+ // should be the last statements
+ delete mpWindowImpl; mpWindowImpl = NULL;
+}
+
+// -----------------------------------------------------------------------
+void Window::doLazyDelete()
+{
+ SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(this);
+ DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(this);
+ if( pSysWin || ( pDockWin && pDockWin->IsFloatingMode() ) )
+ {
+ Show( FALSE );
+ SetParent( ImplGetDefaultWindow() );
+ }
+ vcl::LazyDeletor<Window>::Delete( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::MouseMove( const MouseEvent& rMEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_MOUSEMOVE, this, &rMEvt );
+ if ( !Notify( aNEvt ) )
+ mpWindowImpl->mbMouseMove = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_MOUSEBUTTONDOWN, this, &rMEvt );
+ if ( !Notify( aNEvt ) )
+ mpWindowImpl->mbMouseButtonDown = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_MOUSEBUTTONUP, this, &rMEvt );
+ if ( !Notify( aNEvt ) )
+ mpWindowImpl->mbMouseButtonUp = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::KeyInput( const KeyEvent& rKEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_KEYINPUT, this, &rKEvt );
+ if ( !Notify( aNEvt ) )
+ mpWindowImpl->mbKeyInput = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::KeyUp( const KeyEvent& rKEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_KEYUP, this, &rKEvt );
+ if ( !Notify( aNEvt ) )
+ mpWindowImpl->mbKeyUp = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::PrePaint()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Paint( const Rectangle& rRect )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ ImplCallEventListeners( VCLEVENT_WINDOW_PAINT, (void*)&rRect );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Draw( OutputDevice*, const Point&, const Size&, ULONG )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Move()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Resize()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Activate()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Deactivate()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GetFocus()
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) )
+ {
+ ImplDelData aDogtag( this );
+ mpWindowImpl->mpLastFocusWindow->GrabFocus();
+ if( aDogtag.IsDelete() )
+ return;
+ }
+
+ NotifyEvent aNEvt( EVENT_GETFOCUS, this );
+ Notify( aNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::LoseFocus()
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_LOSEFOCUS, this );
+ Notify( aNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::RequestHelp( const HelpEvent& rHEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ // Wenn Balloon-Help angefordert wird, dann den Balloon mit dem
+ // gesetzten Hilfetext anzeigen
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ const XubString* pStr = &(GetHelpText());
+ if ( !pStr->Len() )
+ pStr = &(GetQuickHelpText());
+ if ( !pStr->Len() && ImplGetParent() && !ImplIsOverlapWindow() )
+ ImplGetParent()->RequestHelp( rHEvt );
+ else
+ Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), *pStr );
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_QUICK )
+ {
+ const XubString* pStr = &(GetQuickHelpText());
+ if ( !pStr->Len() && ImplGetParent() && !ImplIsOverlapWindow() )
+ ImplGetParent()->RequestHelp( rHEvt );
+ else
+ {
+ Point aPos = GetPosPixel();
+ if ( ImplGetParent() && !ImplIsOverlapWindow() )
+ aPos = ImplGetParent()->OutputToScreenPixel( aPos );
+ Rectangle aRect( aPos, GetSizePixel() );
+ String aHelpText;
+ if ( pStr->Len() )
+ aHelpText = GetHelpText();
+ Help::ShowQuickHelp( this, aRect, *pStr, aHelpText, QUICKHELP_CTRLTEXT );
+ }
+ }
+ else
+ {
+ SmartId aSmartId = GetSmartHelpId();
+
+ ULONG nNumHelpId = 0;
+ String aStrHelpId;
+ if( aSmartId.HasString() )
+ aStrHelpId = aSmartId.GetStr();
+ if( aSmartId.HasNumeric() )
+ nNumHelpId = aSmartId.GetNum();
+
+ if ( !nNumHelpId && aStrHelpId.Len() == 0 && ImplGetParent() )
+ ImplGetParent()->RequestHelp( rHEvt );
+ else
+ {
+ if ( !nNumHelpId && aStrHelpId.Len() == 0 )
+ nNumHelpId = OOO_HELP_INDEX;
+
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ if( aStrHelpId.Len() > 0 )
+ pHelp->Start( aStrHelpId, this );
+ else
+ pHelp->Start( nNumHelpId, this );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Command( const CommandEvent& rCEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ ImplCallEventListeners( VCLEVENT_WINDOW_COMMAND, (void*)&rCEvt );
+
+ NotifyEvent aNEvt( EVENT_COMMAND, this, &rCEvt );
+ if ( !Notify( aNEvt ) )
+ mpWindowImpl->mbCommand = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Tracking( const TrackingEvent& rTEvt )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper )
+ pWrapper->Tracking( rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::UserEvent( ULONG, void* )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::StateChanged( StateChangedType )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::DataChanged( const DataChangedEvent& )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplNotifyKeyMouseCommandEventListeners( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetType() == EVENT_COMMAND )
+ {
+ const CommandEvent* pCEvt = rNEvt.GetCommandEvent();
+ if ( pCEvt->GetCommand() != COMMAND_CONTEXTMENU )
+ // non context menu events are not to be notified up the chain
+ // so we return immediately
+ return;
+
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ // not interested in: The event listeners are already called in ::Command,
+ // and calling them here a second time doesn't make sense
+ ;
+ else
+ {
+ CommandEvent aCommandEvent = ImplTranslateCommandEvent( *pCEvt, rNEvt.GetWindow(), this );
+ ImplCallEventListeners( VCLEVENT_WINDOW_COMMAND, &aCommandEvent );
+ }
+ }
+ }
+
+ // #82968# notify event listeners for mouse and key events seperately and
+ // not in PreNotify ( as for focus listeners )
+ // this allows for procesing those events internally first and pass it to
+ // the toolkit later
+
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+
+ if( rNEvt.GetType() == EVENT_MOUSEMOVE )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEMOVE, (void*)rNEvt.GetMouseEvent() );
+ else
+ {
+ MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEMOVE, &aMouseEvent );
+ }
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_MOUSEBUTTONUP )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, (void*)rNEvt.GetMouseEvent() );
+ else
+ {
+ MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, &aMouseEvent );
+ }
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, (void*)rNEvt.GetMouseEvent() );
+ else
+ {
+ MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, &aMouseEvent );
+ }
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ ImplCallEventListeners( VCLEVENT_WINDOW_KEYINPUT, (void*)rNEvt.GetKeyEvent() );
+ }
+ else if( rNEvt.GetType() == EVENT_KEYUP )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ ImplCallEventListeners( VCLEVENT_WINDOW_KEYUP, (void*)rNEvt.GetKeyEvent() );
+ }
+
+ if ( aDelData.IsDelete() )
+ return;
+ ImplRemoveDel( &aDelData );
+
+ // #106721# check if we're part of a compound control and notify
+ Window *pParent = ImplGetParent();
+ while( pParent )
+ {
+ if( pParent->IsCompoundControl() )
+ {
+ pParent->ImplNotifyKeyMouseCommandEventListeners( rNEvt );
+ break;
+ }
+ pParent = pParent->ImplGetParent();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long Window::PreNotify( NotifyEvent& rNEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ long bDone = FALSE;
+ if ( mpWindowImpl->mpParent && !ImplIsOverlapWindow() )
+ bDone = mpWindowImpl->mpParent->PreNotify( rNEvt );
+
+ if ( !bDone )
+ {
+ if( rNEvt.GetType() == EVENT_GETFOCUS )
+ {
+ BOOL bCompoundFocusChanged = FALSE;
+ if ( mpWindowImpl->mbCompoundControl && !mpWindowImpl->mbCompoundControlHasFocus && HasChildPathFocus() )
+ {
+ mpWindowImpl->mbCompoundControlHasFocus = TRUE;
+ bCompoundFocusChanged = TRUE;
+ }
+
+ if ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) )
+ ImplCallEventListeners( VCLEVENT_WINDOW_GETFOCUS );
+ }
+ else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ BOOL bCompoundFocusChanged = FALSE;
+ if ( mpWindowImpl->mbCompoundControl && mpWindowImpl->mbCompoundControlHasFocus && !HasChildPathFocus() )
+ {
+ mpWindowImpl->mbCompoundControlHasFocus = FALSE ;
+ bCompoundFocusChanged = TRUE;
+ }
+
+ if ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) )
+ ImplCallEventListeners( VCLEVENT_WINDOW_LOSEFOCUS );
+ }
+
+ // #82968# mouse and key events will be notified after processing ( in ImplNotifyKeyMouseCommandEventListeners() )!
+ // see also ImplHandleMouseEvent(), ImplHandleKey()
+
+ /*
+ else if( rNEvt.GetType() == EVENT_MOUSEMOVE )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEMOVE, (void*)rNEvt.GetMouseEvent() );
+ else
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEMOVE, &ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this ) );
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_MOUSEBUTTONUP )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, (void*)rNEvt.GetMouseEvent() );
+ else
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, &ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this ) );
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, (void*)rNEvt.GetMouseEvent() );
+ else
+ ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, &ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this ) );
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ ImplCallEventListeners( VCLEVENT_WINDOW_KEYINPUT, (void*)rNEvt.GetKeyEvent() );
+ }
+ else if( rNEvt.GetType() == EVENT_KEYUP )
+ {
+ if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
+ ImplCallEventListeners( VCLEVENT_WINDOW_KEYUP, (void*)rNEvt.GetKeyEvent() );
+ }
+ */
+ }
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::Notify( NotifyEvent& rNEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ long nRet = FALSE;
+
+ // check for docking window
+ // but do nothing if window is docked and locked
+ ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
+ if( pWrapper && !( !pWrapper->IsFloatingMode() && pWrapper->IsLocked() ) )
+ {
+ if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
+ {
+ const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
+ BOOL bHit = pWrapper->GetDragArea().IsInside( pMEvt->GetPosPixel() );
+ if ( pMEvt->IsLeft() )
+ {
+ if ( pMEvt->IsMod1() && (pMEvt->GetClicks() == 2) )
+ {
+ // ctrl double click toggles floating mode
+ pWrapper->SetFloatingMode( !pWrapper->IsFloatingMode() );
+ return TRUE;
+ }
+ else if ( pMEvt->GetClicks() == 1 && bHit)
+ {
+ // allow start docking during mouse move
+ pWrapper->ImplEnableStartDocking();
+ return TRUE;
+ }
+ }
+ }
+ else if ( rNEvt.GetType() == EVENT_MOUSEMOVE )
+ {
+ const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
+ BOOL bHit = pWrapper->GetDragArea().IsInside( pMEvt->GetPosPixel() );
+ if ( pMEvt->IsLeft() )
+ {
+ // check if a single click initiated this sequence ( ImplStartDockingEnabled() )
+ // check if window is docked and
+ if( pWrapper->ImplStartDockingEnabled() && !pWrapper->IsFloatingMode() &&
+ !pWrapper->IsDocking() && bHit )
+ {
+ Point aPos = pMEvt->GetPosPixel();
+ Window* pWindow = rNEvt.GetWindow();
+ if ( pWindow != this )
+ {
+ aPos = pWindow->OutputToScreenPixel( aPos );
+ aPos = ScreenToOutputPixel( aPos );
+ }
+ pWrapper->ImplStartDocking( aPos );
+ }
+ return TRUE;
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyCode& rKey = rNEvt.GetKeyEvent()->GetKeyCode();
+ if( rKey.GetCode() == KEY_F10 && rKey.GetModifier() &&
+ rKey.IsShift() && rKey.IsMod1() )
+ {
+ pWrapper->SetFloatingMode( !pWrapper->IsFloatingMode() );
+ /* At this point the floating toolbar frame does not have the
+ * input focus since these frames don't get the focus per default
+ * To enable keyboard handling of this toolbar set the input focus
+ * to the frame. This needs to be done with ToTop since GrabFocus
+ * would not notice any change since "this" already has the focus.
+ */
+ if( pWrapper->IsFloatingMode() )
+ ToTop( TOTOP_GRABFOCUSONLY );
+ return TRUE;
+ }
+ }
+ }
+
+ // Dialog-Steuerung
+ if ( (GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
+ {
+ // Wenn Parent auch DialogSteuerung aktiviert hat, uebernimmt dieser die Steuerung
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) || (rNEvt.GetType() == EVENT_KEYUP) )
+ {
+ if ( ImplIsOverlapWindow() ||
+ ((ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
+ {
+ nRet = ImplDlgCtrl( *rNEvt.GetKeyEvent(), rNEvt.GetType() == EVENT_KEYINPUT );
+ }
+ }
+ else if ( (rNEvt.GetType() == EVENT_GETFOCUS) || (rNEvt.GetType() == EVENT_LOSEFOCUS) )
+ {
+ ImplDlgCtrlFocusChanged( rNEvt.GetWindow(), rNEvt.GetType() == EVENT_GETFOCUS );
+ if ( (rNEvt.GetWindow() == this) && (rNEvt.GetType() == EVENT_GETFOCUS) &&
+ !(GetStyle() & WB_TABSTOP) && !(mpWindowImpl->mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) )
+ {
+ USHORT n = 0;
+ Window* pFirstChild = ImplGetDlgWindow( n, DLGWINDOW_FIRST );
+ if ( pFirstChild )
+ pFirstChild->ImplControlFocus();
+ }
+ }
+ }
+
+ if ( !nRet )
+ {
+ if ( mpWindowImpl->mpParent && !ImplIsOverlapWindow() )
+ nRet = mpWindowImpl->mpParent->Notify( rNEvt );
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallEventListeners( ULONG nEvent, void* pData )
+{
+ // The implementation was moved to CallEventListeners(),
+ // because derived classes in svtools must be able to
+ // call the event listeners and ImplCallEventListeners()
+ // is not exported.
+ // TODO: replace ImplCallEventListeners() by CallEventListeners() in vcl
+
+ CallEventListeners( nEvent, pData );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::CallEventListeners( ULONG nEvent, void* pData )
+{
+ VclWindowEvent aEvent( this, nEvent, pData );
+
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+
+ ImplGetSVData()->mpApp->ImplCallEventListeners( &aEvent );
+
+ if ( aDelData.IsDelete() )
+ return;
+
+ if ( !mpWindowImpl->maEventListeners.empty() )
+ mpWindowImpl->maEventListeners.Call( &aEvent );
+
+ if ( aDelData.IsDelete() )
+ return;
+
+ ImplRemoveDel( &aDelData );
+
+ Window* pWindow = this;
+ while ( pWindow )
+ {
+ pWindow->ImplAddDel( &aDelData );
+
+ if ( !pWindow->mpWindowImpl->maChildEventListeners.empty() )
+ pWindow->mpWindowImpl->maChildEventListeners.Call( &aEvent );
+
+ if ( aDelData.IsDelete() )
+ return;
+
+ pWindow->ImplRemoveDel( &aDelData );
+
+ pWindow = pWindow->GetParent();
+ }
+}
+
+void Window::FireVclEvent( VclSimpleEvent* pEvent )
+{
+ ImplGetSVData()->mpApp->ImplCallEventListeners(pEvent);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::AddEventListener( const Link& rEventListener )
+{
+ mpWindowImpl->maEventListeners.push_back( rEventListener );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::RemoveEventListener( const Link& rEventListener )
+{
+ mpWindowImpl->maEventListeners.remove( rEventListener );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::AddChildEventListener( const Link& rEventListener )
+{
+ mpWindowImpl->maChildEventListeners.push_back( rEventListener );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::RemoveChildEventListener( const Link& rEventListener )
+{
+ mpWindowImpl->maChildEventListeners.remove( rEventListener );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Window::PostUserEvent( ULONG nEvent, void* pEventData )
+{
+ ULONG nEventId;
+ PostUserEvent( nEventId, nEvent, pEventData );
+ return nEventId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Window::PostUserEvent( const Link& rLink, void* pCaller )
+{
+ ULONG nEventId;
+ PostUserEvent( nEventId, rLink, pCaller );
+ return nEventId;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::PostUserEvent( ULONG& rEventId, ULONG nEvent, void* pEventData )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVEvent* pSVEvent = new ImplSVEvent;
+ pSVEvent->mnEvent = nEvent;
+ pSVEvent->mpData = pEventData;
+ pSVEvent->mpLink = NULL;
+ pSVEvent->mpWindow = this;
+ pSVEvent->mbCall = TRUE;
+ ImplAddDel( &(pSVEvent->maDelData) );
+ rEventId = (ULONG)pSVEvent;
+ if ( mpWindowImpl->mpFrame->PostEvent( pSVEvent ) )
+ return TRUE;
+ else
+ {
+ rEventId = 0;
+ ImplRemoveDel( &(pSVEvent->maDelData) );
+ delete pSVEvent;
+ return FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::PostUserEvent( ULONG& rEventId, const Link& rLink, void* pCaller )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVEvent* pSVEvent = new ImplSVEvent;
+ pSVEvent->mnEvent = 0;
+ pSVEvent->mpData = pCaller;
+ pSVEvent->mpLink = new Link( rLink );
+ pSVEvent->mpWindow = this;
+ pSVEvent->mbCall = TRUE;
+ ImplAddDel( &(pSVEvent->maDelData) );
+ rEventId = (ULONG)pSVEvent;
+ if ( mpWindowImpl->mpFrame->PostEvent( pSVEvent ) )
+ return TRUE;
+ else
+ {
+ rEventId = 0;
+ ImplRemoveDel( &(pSVEvent->maDelData) );
+ delete pSVEvent;
+ return FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::RemoveUserEvent( ULONG nUserEvent )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVEvent* pSVEvent = (ImplSVEvent*)nUserEvent;
+
+ DBG_ASSERT( pSVEvent->mpWindow == this,
+ "Window::RemoveUserEvent(): Event doesn't send to this window or is already removed" );
+ DBG_ASSERT( pSVEvent->mbCall,
+ "Window::RemoveUserEvent(): Event is already removed" );
+
+ if ( pSVEvent->mpWindow )
+ {
+ pSVEvent->mpWindow->ImplRemoveDel( &(pSVEvent->maDelData) );
+ pSVEvent->mpWindow = NULL;
+ }
+
+ pSVEvent->mbCall = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplAsyncStateChangedHdl, void*, pState )
+{
+ StateChanged( (StateChangedType)(ULONG)pState );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::PostStateChanged( StateChangedType nState )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ PostUserEvent( LINK( this, Window, ImplAsyncStateChangedHdl ), (void*)(ULONG)nState );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsLocked( BOOL bChilds ) const
+{
+ if ( mpWindowImpl->mnLockCount != 0 )
+ return TRUE;
+
+ if ( bChilds || mpWindowImpl->mbChildNotify )
+ {
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ if ( pChild->IsLocked( TRUE ) )
+ return TRUE;
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetStyle( WinBits nStyle )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mnStyle != nStyle )
+ {
+ mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle;
+ mpWindowImpl->mnStyle = nStyle;
+ StateChanged( STATE_CHANGE_STYLE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetExtendedStyle( WinBits nExtendedStyle )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mnExtendedStyle != nExtendedStyle )
+ {
+ Window* pWindow = ImplGetBorderWindow();
+ if( ! pWindow )
+ pWindow = this;
+ if( pWindow->mpWindowImpl->mbFrame )
+ {
+ SalExtStyle nExt = 0;
+ if( (nExtendedStyle & WB_EXT_DOCUMENT) )
+ nExt |= SAL_FRAME_EXT_STYLE_DOCUMENT;
+ if( (nExtendedStyle & WB_EXT_DOCMODIFIED) )
+ nExt |= SAL_FRAME_EXT_STYLE_DOCMODIFIED;
+
+ pWindow->ImplGetFrame()->SetExtendedFrameStyle( nExt );
+ }
+ mpWindowImpl->mnPrevExtendedStyle = mpWindowImpl->mnExtendedStyle;
+ mpWindowImpl->mnExtendedStyle = nExtendedStyle;
+ StateChanged( STATE_CHANGE_EXTENDEDSTYLE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+SystemWindow* Window::GetSystemWindow() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Window* pWin = this;
+ while ( pWin && !pWin->IsSystemWindow() )
+ pWin = pWin->GetParent();
+ return (SystemWindow*)pWin;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetBorderStyle( USHORT nBorderStyle )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ if( nBorderStyle == WINDOW_BORDER_REMOVEBORDER &&
+ ! mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
+ mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent
+ )
+ {
+ // this is a little awkward: some controls (e.g. svtools ProgressBar)
+ // cannot avoid getting constructed with WB_BORDER but want to disable
+ // borders in case of NWF drawing. So they need a method to remove their border window
+ Window* pBorderWin = mpWindowImpl->mpBorderWindow;
+ // remove us as border window's client
+ pBorderWin->mpWindowImpl->mpClientWindow = NULL;
+ mpWindowImpl->mpBorderWindow = NULL;
+ mpWindowImpl->mpRealParent = pBorderWin->mpWindowImpl->mpParent;
+ // reparent us above the border window
+ SetParent( pBorderWin->mpWindowImpl->mpParent );
+ // set us to the position and size of our previous border
+ Point aBorderPos( pBorderWin->GetPosPixel() );
+ Size aBorderSize( pBorderWin->GetSizePixel() );
+ SetPosSizePixel( aBorderPos.X(), aBorderPos.Y(), aBorderSize.Width(), aBorderSize.Height() );
+ // release border window
+ delete pBorderWin;
+
+ // set new style bits
+ SetStyle( GetStyle() & (~WB_BORDER) );
+ }
+ else
+ {
+ if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetBorderStyle( nBorderStyle );
+ else
+ mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::GetBorderStyle() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
+ return ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->GetBorderStyle();
+ else
+ return mpWindowImpl->mpBorderWindow->GetBorderStyle();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::CalcTitleWidth() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
+ return ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->CalcTitleWidth();
+ else
+ return mpWindowImpl->mpBorderWindow->CalcTitleWidth();
+ }
+ else if ( mpWindowImpl->mbFrame && (mpWindowImpl->mnStyle & WB_MOVEABLE) )
+ {
+ // Fuer Frame-Fenster raten wir die Breite, da wir den Border fuer
+ // externe Dialoge nicht kennen
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Font aFont = GetFont();
+ ((Window*)this)->SetPointFont( rStyleSettings.GetTitleFont() );
+ long nTitleWidth = GetTextWidth( GetText() );
+ ((Window*)this)->SetFont( aFont );
+ nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
+ nTitleWidth += rStyleSettings.GetBorderSize() * 2;
+ nTitleWidth += 10;
+ return nTitleWidth;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableClipSiblings( BOOL bClipSiblings )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->EnableClipSiblings( bClipSiblings );
+
+ mpWindowImpl->mbClipSiblings = bClipSiblings;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetMouseTransparent( BOOL bTransparent )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->SetMouseTransparent( bTransparent );
+
+ if( mpWindowImpl->mpSysObj )
+ mpWindowImpl->mpSysObj->SetMouseTransparent( bTransparent );
+
+ mpWindowImpl->mbMouseTransparent = bTransparent;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPaintTransparent( BOOL bTransparent )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ // transparency is not useful for frames as the background would have to be provided by a different frame
+ if( bTransparent && mpWindowImpl->mbFrame )
+ return;
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->SetPaintTransparent( bTransparent );
+
+ mpWindowImpl->mbPaintTransparent = bTransparent;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetInputContext( const InputContext& rInputContext )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mpWindowImpl->maInputContext = rInputContext;
+ if ( !mpWindowImpl->mbInFocusHdl && HasFocus() )
+ ImplNewInputContext();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EndExtTextInput( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mbExtTextInput )
+ ImplGetFrame()->EndExtTextInput( nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetCursorRect( const Rectangle* pRect, long nExtTextInputWidth )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+ if ( pWinData->mpCursorRect )
+ {
+ if ( pRect )
+ *pWinData->mpCursorRect = *pRect;
+ else
+ {
+ delete pWinData->mpCursorRect;
+ pWinData->mpCursorRect = NULL;
+ }
+ }
+ else
+ {
+ if ( pRect )
+ pWinData->mpCursorRect = new Rectangle( *pRect );
+ }
+
+ pWinData->mnCursorExtWidth = nExtTextInputWidth;
+
+}
+
+// -----------------------------------------------------------------------
+
+const Rectangle* Window::GetCursorRect() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+ return pWinData->mpCursorRect;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::GetCursorExtTextInputWidth() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+ return pWinData->mnCursorExtWidth;
+}
+
+// -----------------------------------------------------------------------
+void Window::SetSettings( const AllSettings& rSettings )
+{
+ SetSettings( rSettings, FALSE );
+}
+
+void Window::SetSettings( const AllSettings& rSettings, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ mpWindowImpl->mpBorderWindow->SetSettings( rSettings, FALSE );
+ if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow->SetSettings( rSettings, TRUE );
+ }
+
+ AllSettings aOldSettings = maSettings;
+ OutputDevice::SetSettings( rSettings );
+ ULONG nChangeFlags = aOldSettings.GetChangeFlags( rSettings );
+
+ // AppFont-Aufloesung und DPI-Aufloesung neu berechnen
+ ImplInitResolutionSettings();
+
+ if ( nChangeFlags )
+ {
+ DataChangedEvent aDCEvt( DATACHANGED_SETTINGS, &aOldSettings, nChangeFlags );
+ DataChanged( aDCEvt );
+ }
+
+ if ( bChild || mpWindowImpl->mbChildNotify )
+ {
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->SetSettings( rSettings, bChild );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::UpdateSettings( const AllSettings& rSettings, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ mpWindowImpl->mpBorderWindow->UpdateSettings( rSettings, FALSE );
+ if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow->UpdateSettings( rSettings, TRUE );
+ }
+
+ AllSettings aOldSettings = maSettings;
+ ULONG nChangeFlags = maSettings.Update( maSettings.GetWindowUpdate(), rSettings );
+ nChangeFlags |= SETTINGS_IN_UPDATE_SETTINGS; // Set this flag so the receiver of the data changed
+ // event can distinguish between the changing of global
+ // setting and a local change ( with SetSettings )
+
+ // AppFont-Aufloesung und DPI-Aufloesung neu berechnen
+ ImplInitResolutionSettings();
+
+ /* #i73785#
+ * do not overwrite a WheelBehavior with false
+ * this looks kind of a hack, but WheelBehavior
+ * is always a local change, not a system property,
+ * so we can spare all our users the hassle of reacting on
+ * this in their respective DataChanged.
+ */
+ MouseSettings aSet( maSettings.GetMouseSettings() );
+ aSet.SetWheelBehavior( aOldSettings.GetMouseSettings().GetWheelBehavior() );
+ maSettings.SetMouseSettings( aSet );
+
+ if( (nChangeFlags & SETTINGS_STYLE) && IsBackground() )
+ {
+ Wallpaper aWallpaper = GetBackground();
+ if( !aWallpaper.IsBitmap() && !aWallpaper.IsGradient() )
+ {
+ if ( mpWindowImpl->mnStyle & WB_3DLOOK )
+ SetBackground( Wallpaper( rSettings.GetStyleSettings().GetFaceColor() ) );
+ else
+ SetBackground( Wallpaper( rSettings.GetStyleSettings().GetWindowColor() ) );
+ }
+ }
+
+ if ( nChangeFlags )
+ {
+ DataChangedEvent aDCEvt( DATACHANGED_SETTINGS, &aOldSettings, nChangeFlags );
+ DataChanged( aDCEvt );
+ // notify data change handler
+ ImplCallEventListeners( VCLEVENT_WINDOW_DATACHANGED, &aDCEvt);
+ }
+
+ if ( bChild || mpWindowImpl->mbChildNotify )
+ {
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->UpdateSettings( rSettings, bChild );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::NotifyAllChilds( DataChangedEvent& rDCEvt )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ DataChanged( rDCEvt );
+
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->NotifyAllChilds( rDCEvt );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPointFont( const Font& rFont )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Font aFont = rFont;
+ ImplPointToLogic( aFont );
+ SetFont( aFont );
+}
+
+// -----------------------------------------------------------------------
+
+Font Window::GetPointFont() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Font aFont = GetFont();
+ ImplLogicToPoint( aFont );
+ return aFont;
+}
+
+// -----------------------------------------------------------------------
+
+// TODO: remove in next incompatible build
+void Window::GetFontResolution( sal_Int32& nDPIX, sal_Int32& nDPIY ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ nDPIX = mpWindowImpl->mpFrameData->mnDPIX;
+ nDPIY = mpWindowImpl->mpFrameData->mnDPIY;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetParentClipMode( USHORT nMode )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->SetParentClipMode( nMode );
+ else
+ {
+ if ( !ImplIsOverlapWindow() )
+ {
+ mpWindowImpl->mnParentClipMode = nMode;
+ if ( nMode & PARENTCLIPMODE_CLIP )
+ mpWindowImpl->mpParent->mpWindowImpl->mbClipChildren = TRUE;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::GetParentClipMode() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ return mpWindowImpl->mpBorderWindow->GetParentClipMode();
+ else
+ return mpWindowImpl->mnParentClipMode;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetWindowRegionPixel()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->SetWindowRegionPixel();
+ else if( mpWindowImpl->mbFrame )
+ {
+ mpWindowImpl->maWinRegion = Region( REGION_NULL);
+ mpWindowImpl->mbWinRegion = FALSE;
+ mpWindowImpl->mpFrame->ResetClipRegion();
+ }
+ else
+ {
+ if ( mpWindowImpl->mbWinRegion )
+ {
+ mpWindowImpl->maWinRegion = Region( REGION_NULL );
+ mpWindowImpl->mbWinRegion = FALSE;
+ ImplSetClipFlag();
+
+ if ( IsReallyVisible() )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev )
+ ImplDeleteOverlapBackground();
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aRegion( aRect );
+ ImplInvalidateParentFrameRegion( aRegion );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetWindowRegionPixel( const Region& rRegion )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->SetWindowRegionPixel( rRegion );
+ else if( mpWindowImpl->mbFrame )
+ {
+ if( rRegion.GetType() != REGION_NULL )
+ {
+ mpWindowImpl->maWinRegion = rRegion;
+ mpWindowImpl->mbWinRegion = ! rRegion.IsEmpty();
+ if( mpWindowImpl->mbWinRegion )
+ {
+ // ClipRegion setzen/updaten
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ULONG nRectCount;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ nRectCount = mpWindowImpl->maWinRegion.GetRectCount();
+ mpWindowImpl->mpFrame->BeginSetClipRegion( nRectCount );
+ bRegionRect = mpWindowImpl->maWinRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ mpWindowImpl->mpFrame->UnionClipRegion( nX, nY, nWidth, nHeight );
+ bRegionRect = mpWindowImpl->maWinRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ mpWindowImpl->mpFrame->EndSetClipRegion();
+ }
+ else
+ SetWindowRegionPixel();
+ }
+ else
+ SetWindowRegionPixel();
+ }
+ else
+ {
+ BOOL bInvalidate = FALSE;
+
+ if ( rRegion.GetType() == REGION_NULL )
+ {
+ if ( mpWindowImpl->mbWinRegion )
+ {
+ mpWindowImpl->maWinRegion = Region( REGION_NULL );
+ mpWindowImpl->mbWinRegion = FALSE;
+ ImplSetClipFlag();
+ bInvalidate = TRUE;
+ }
+ }
+ else
+ {
+ mpWindowImpl->maWinRegion = rRegion;
+ mpWindowImpl->mbWinRegion = TRUE;
+ ImplSetClipFlag();
+ bInvalidate = TRUE;
+ }
+
+ if ( IsReallyVisible() )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev )
+ ImplDeleteOverlapBackground();
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aRegion( aRect );
+ ImplInvalidateParentFrameRegion( aRegion );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const Region& Window::GetWindowRegionPixel() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ return mpWindowImpl->mpBorderWindow->GetWindowRegionPixel();
+ else
+ return mpWindowImpl->maWinRegion;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsWindowRegionPixel() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ return mpWindowImpl->mpBorderWindow->IsWindowRegionPixel();
+ else
+ return mpWindowImpl->mbWinRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Region Window::GetWindowClipRegionPixel( USHORT nFlags ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Region aWinClipRegion;
+
+ if ( nFlags & WINDOW_GETCLIPREGION_NOCHILDREN )
+ {
+ if ( mpWindowImpl->mbInitWinClipRegion )
+ ((Window*)this)->ImplInitWinClipRegion();
+ aWinClipRegion = mpWindowImpl->maWinClipRegion;
+ }
+ else
+ {
+ Region* pWinChildClipRegion = ((Window*)this)->ImplGetWinChildClipRegion();
+ aWinClipRegion = *pWinChildClipRegion;
+ // --- RTL --- remirror clip region before passing it to somebody
+ if( ImplIsAntiparallel() )
+ ImplReMirror( aWinClipRegion );
+ }
+
+ if ( nFlags & WINDOW_GETCLIPREGION_NULL )
+ {
+ Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aWinRegion( aWinRect );
+
+ if ( aWinRegion == aWinClipRegion )
+ aWinClipRegion.SetNull();
+ }
+
+ aWinClipRegion.Move( -mnOutOffX, -mnOutOffY );
+
+ return aWinClipRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Region Window::GetPaintRegion() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpPaintRegion )
+ {
+ Region aRegion = *mpWindowImpl->mpPaintRegion;
+ aRegion.Move( -mnOutOffX, -mnOutOffY );
+ return PixelToLogic( aRegion );
+ }
+ else
+ {
+ Region aPaintRegion( REGION_NULL );
+ return aPaintRegion;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ExpandPaintClipRegion( const Region& rRegion )
+{
+ if( mpWindowImpl->mpPaintRegion )
+ {
+ Region aPixRegion = LogicToPixel( rRegion );
+ Region aDevPixRegion = ImplPixelToDevicePixel( aPixRegion );
+
+ Region aWinChildRegion = *ImplGetWinChildClipRegion();
+ // --- RTL -- only this region is in frame coordinates, so re-mirror it
+ if( ImplIsAntiparallel() )
+ ImplReMirror( aWinChildRegion );
+ aDevPixRegion.Intersect( aWinChildRegion );
+ if( ! aDevPixRegion.IsEmpty() )
+ {
+ mpWindowImpl->mpPaintRegion->Union( aDevPixRegion );
+ mbInitClipRegion = TRUE;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static SystemWindow *ImplGetLastSystemWindow( Window *pWin )
+{
+ // get the most top-level system window, the one that contains the taskpanelist
+ SystemWindow *pSysWin = NULL;
+ if( !pWin )
+ return pSysWin;
+ Window *pMyParent = pWin;
+ while ( pMyParent )
+ {
+ if ( pMyParent->IsSystemWindow() )
+ pSysWin = (SystemWindow*)pMyParent;
+ pMyParent = pMyParent->GetParent();
+ }
+ return pSysWin;
+}
+
+void Window::SetParent( Window* pNewParent )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_ASSERT( pNewParent, "Window::SetParent(): pParent == NULL" );
+ DBG_ASSERT( pNewParent != this, "someone tried to reparent a window to itself" );
+
+ if( pNewParent == this )
+ return;
+
+ // check if the taskpanelist would change and move the window pointer accordingly
+ SystemWindow *pSysWin = ImplGetLastSystemWindow(this);
+ SystemWindow *pNewSysWin = NULL;
+ BOOL bChangeTaskPaneList = FALSE;
+ if( pSysWin && pSysWin->ImplIsInTaskPaneList( this ) )
+ {
+ pNewSysWin = ImplGetLastSystemWindow( pNewParent );
+ if( pNewSysWin && pNewSysWin != pSysWin )
+ {
+ bChangeTaskPaneList = TRUE;
+ pSysWin->GetTaskPaneList()->RemoveWindow( this );
+ }
+ }
+ // remove ownerdraw decorated windows from list in the top-most frame window
+ if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
+ {
+ ::std::vector< Window* >& rList = ImplGetOwnerDrawList();
+ ::std::vector< Window* >::iterator p;
+ p = ::std::find( rList.begin(), rList.end(), this );
+ if( p != rList.end() )
+ rList.erase( p );
+ }
+
+ ImplSetFrameParent( pNewParent );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ mpWindowImpl->mpRealParent = pNewParent;
+ mpWindowImpl->mpBorderWindow->SetParent( pNewParent );
+ return;
+ }
+
+ if ( mpWindowImpl->mpParent == pNewParent )
+ return;
+
+ if ( mpWindowImpl->mbFrame )
+ mpWindowImpl->mpFrame->SetParent( pNewParent->mpWindowImpl->mpFrame );
+
+ BOOL bVisible = IsVisible();
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // Testen, ob sich das Overlap-Window aendert
+ Window* pOldOverlapWindow;
+ Window* pNewOverlapWindow = NULL;
+ if ( ImplIsOverlapWindow() )
+ pOldOverlapWindow = NULL;
+ else
+ {
+ pNewOverlapWindow = pNewParent->ImplGetFirstOverlapWindow();
+ if ( mpWindowImpl->mpOverlapWindow != pNewOverlapWindow )
+ pOldOverlapWindow = mpWindowImpl->mpOverlapWindow;
+ else
+ pOldOverlapWindow = NULL;
+ }
+
+ // Fenster in der Hirachie umsetzen
+ BOOL bFocusOverlapWin = HasChildPathFocus( TRUE );
+ BOOL bFocusWin = HasChildPathFocus();
+ BOOL bNewFrame = pNewParent->mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow;
+ if ( bNewFrame )
+ {
+ if ( mpWindowImpl->mpFrameData->mpFocusWin )
+ {
+ if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpFocusWin ) )
+ mpWindowImpl->mpFrameData->mpFocusWin = NULL;
+ }
+ if ( mpWindowImpl->mpFrameData->mpMouseMoveWin )
+ {
+ if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpMouseMoveWin ) )
+ mpWindowImpl->mpFrameData->mpMouseMoveWin = NULL;
+ }
+ if ( mpWindowImpl->mpFrameData->mpMouseDownWin )
+ {
+ if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpMouseDownWin ) )
+ mpWindowImpl->mpFrameData->mpMouseDownWin = NULL;
+ }
+ }
+ ImplRemoveWindow( bNewFrame );
+ ImplInsertWindow( pNewParent );
+ if ( mpWindowImpl->mnParentClipMode & PARENTCLIPMODE_CLIP )
+ pNewParent->mpWindowImpl->mbClipChildren = TRUE;
+ ImplUpdateWindowPtr();
+ if ( ImplUpdatePos() )
+ ImplUpdateSysObjPos();
+
+ // Wenn sich das Overlap-Window geaendert hat, dann muss getestet werden,
+ // ob auch OverlapWindow die das Child-Fenster als Parent gehabt haben
+ // in der Window-Hirachie umgesetzt werden muessen
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( bNewFrame )
+ {
+ Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
+ pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
+ pOverlapWindow = pNextOverlapWindow;
+ }
+ }
+ }
+ else if ( pOldOverlapWindow )
+ {
+ // Focus-Save zuruecksetzen
+ if ( bFocusWin ||
+ (pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow &&
+ IsWindowOrChild( pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow )) )
+ pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow = NULL;
+
+ Window* pOverlapWindow = pOldOverlapWindow->mpWindowImpl->mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
+ if ( ImplIsRealParentPath( pOverlapWindow->ImplGetWindow() ) )
+ pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
+ pOverlapWindow = pNextOverlapWindow;
+ }
+
+ // Activate-Status beim naechsten Overlap-Window updaten
+ if ( HasChildPathFocus( TRUE ) )
+ ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
+ }
+
+ // Activate-Status mit umsetzen
+ if ( bNewFrame )
+ {
+ if ( (GetType() == WINDOW_BORDERWINDOW) &&
+ (ImplGetWindow()->GetType() == WINDOW_FLOATINGWINDOW) )
+ ((ImplBorderWindow*)this)->SetDisplayActive( mpWindowImpl->mpFrameData->mbHasFocus );
+ }
+
+ // Focus evtl. auf den neuen Frame umsetzen, wenn FocusWindow mit
+ // SetParent() umgesetzt wird
+ if ( bFocusOverlapWin )
+ {
+ mpWindowImpl->mpFrameData->mpFocusWin = Application::GetFocusWindow();
+ if ( !mpWindowImpl->mpFrameData->mbHasFocus )
+ {
+ mpWindowImpl->mpFrame->ToTop( 0 );
+ }
+ }
+
+ // Assure DragSource and DropTarget members are created
+ if ( bNewFrame )
+ {
+ GetDropTarget();
+ }
+
+ if( bChangeTaskPaneList )
+ pNewSysWin->GetTaskPaneList()->AddWindow( this );
+
+ if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
+ ImplGetOwnerDrawList().push_back( this );
+
+ if ( bVisible )
+ Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Show( BOOL bVisible, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mbVisible == bVisible )
+ return;
+
+ ImplDelData aDogTag( this );
+
+ BOOL bRealVisibilityChanged = FALSE;
+ mpWindowImpl->mbVisible = (bVisible != 0);
+
+ if ( !bVisible )
+ {
+ ImplHideAllOverlaps();
+ if( aDogTag.IsDelete() )
+ return;
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ BOOL bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate;
+ if ( mpWindowImpl->mbNoParentUpdate )
+ mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = TRUE;
+ mpWindowImpl->mpBorderWindow->Show( FALSE, nFlags );
+ mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate;
+ }
+ else if ( mpWindowImpl->mbFrame )
+ {
+ mpWindowImpl->mbSuppressAccessibilityEvents = TRUE;
+ mpWindowImpl->mpFrame->Show( FALSE, FALSE );
+ }
+
+ StateChanged( STATE_CHANGE_VISIBLE );
+
+ if ( mpWindowImpl->mbReallyVisible )
+ {
+ Region aInvRegion( REGION_EMPTY );
+ BOOL bSaveBack = FALSE;
+
+ if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
+ {
+ if ( ImplRestoreOverlapBackground( aInvRegion ) )
+ bSaveBack = TRUE;
+ }
+
+ if ( !bSaveBack )
+ {
+ if ( mpWindowImpl->mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+ aInvRegion = mpWindowImpl->maWinClipRegion;
+ }
+
+ if( aDogTag.IsDelete() )
+ return;
+
+ bRealVisibilityChanged = mpWindowImpl->mbReallyVisible;
+ ImplResetReallyVisible();
+ ImplSetClipFlag();
+
+ if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
+ {
+ // Focus umsetzen
+ if ( !(nFlags & SHOW_NOFOCUSCHANGE) && HasChildPathFocus() )
+ {
+ if ( mpWindowImpl->mpOverlapWindow->IsEnabled() &&
+ mpWindowImpl->mpOverlapWindow->IsInputEnabled() &&
+ ! mpWindowImpl->mpOverlapWindow->IsInModalMode()
+ )
+ mpWindowImpl->mpOverlapWindow->GrabFocus();
+ }
+ }
+
+ if ( !mpWindowImpl->mbFrame )
+ {
+ if( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mbEnableNativeWidget )
+ {
+ /*
+ * #i48371# native theming: some themes draw outside the control
+ * area we tell them to (bad thing, but we cannot do much about it ).
+ * On hiding these controls they get invalidated with their window rectangle
+ * which leads to the parts outside the control area being left and not
+ * invalidated. Workaround: invalidate an area on the parent, too
+ */
+ const int workaround_border = 5;
+ Rectangle aBounds( aInvRegion.GetBoundRect() );
+ aBounds.Left() -= workaround_border;
+ aBounds.Top() -= workaround_border;
+ aBounds.Right() += workaround_border;
+ aBounds.Bottom() += workaround_border;
+ aInvRegion = aBounds;
+ }
+ if ( !mpWindowImpl->mbNoParentUpdate && !(nFlags & SHOW_NOPARENTUPDATE) )
+ {
+ if ( !aInvRegion.IsEmpty() )
+ ImplInvalidateParentFrameRegion( aInvRegion );
+ }
+ ImplGenerateMouseMove();
+ }
+ }
+ }
+ else
+ {
+ // inherit native widget flag for form controls
+ // required here, because frames never show up in the child hierarchy - which should be fixed....
+ // eg, the drop down of a combobox which is a system floating window
+ if( mpWindowImpl->mbFrame && GetParent() && GetParent()->IsCompoundControl() &&
+ GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() )
+ EnableNativeWidget( GetParent()->IsNativeWidgetEnabled() );
+
+ if ( mpWindowImpl->mbCallMove )
+ {
+ ImplCallMove();
+ }
+ if ( mpWindowImpl->mbCallResize )
+ {
+ ImplCallResize();
+ }
+
+ StateChanged( STATE_CHANGE_VISIBLE );
+
+ Window* pTestParent;
+ if ( ImplIsOverlapWindow() )
+ pTestParent = mpWindowImpl->mpOverlapWindow;
+ else
+ pTestParent = ImplGetParent();
+ if ( mpWindowImpl->mbFrame || pTestParent->mpWindowImpl->mbReallyVisible )
+ {
+ // Wenn ein Window gerade sichtbar wird, schicken wir allen
+ // Child-Fenstern ein StateChanged, damit diese sich
+ // initialisieren koennen
+ ImplCallInitShow();
+
+ // Wenn es ein SystemWindow ist, dann kommt es auch automatisch
+ // nach vorne, wenn es gewuenscht ist
+ if ( ImplIsOverlapWindow() && !(nFlags & SHOW_NOACTIVATE) )
+ {
+ ImplStartToTop(( nFlags & SHOW_FOREGROUNDTASK ) ? TOTOP_FOREGROUNDTASK : 0 );
+ ImplFocusToTop( 0, FALSE );
+ }
+
+ // Hintergrund sichern
+ if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mbSaveBack )
+ ImplSaveOverlapBackground();
+ // adjust mpWindowImpl->mbReallyVisible
+ bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
+ ImplSetReallyVisible();
+
+ // Dafuer sorgen, das Clip-Rechtecke neu berechnet werden
+ ImplSetClipFlag();
+
+ if ( !mpWindowImpl->mbFrame )
+ {
+ USHORT nInvalidateFlags = INVALIDATE_CHILDREN;
+ if( ! IsPaintTransparent() )
+ nInvalidateFlags |= INVALIDATE_NOTRANSPARENT;
+ ImplInvalidate( NULL, nInvalidateFlags );
+ ImplGenerateMouseMove();
+ }
+ }
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->Show( TRUE, nFlags );
+ else if ( mpWindowImpl->mbFrame )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ // #106431#, hide SplashScreen
+ if( pSVData->mpIntroWindow && !ImplIsWindowOrChild( pSVData->mpIntroWindow ) )
+ pSVData->mpIntroWindow->Hide();
+
+ //DBG_ASSERT( !mpWindowImpl->mbSuppressAccessibilityEvents, "Window::Show() - Frame reactivated");
+ mpWindowImpl->mbSuppressAccessibilityEvents = FALSE;
+
+ mpWindowImpl->mbPaintFrame = TRUE;
+ BOOL bNoActivate = (nFlags & (SHOW_NOACTIVATE|SHOW_NOFOCUSCHANGE)) ? TRUE : FALSE;
+ mpWindowImpl->mpFrame->Show( TRUE, bNoActivate );
+ if( aDogTag.IsDelete() )
+ return;
+
+ // Query the correct size of the window, if we are waiting for
+ // a system resize
+ if ( mpWindowImpl->mbWaitSystemResize )
+ {
+ long nOutWidth;
+ long nOutHeight;
+ mpWindowImpl->mpFrame->GetClientSize( nOutWidth, nOutHeight );
+ ImplHandleResize( this, nOutWidth, nOutHeight );
+ }
+ }
+
+ if( aDogTag.IsDelete() )
+ return;
+
+#ifdef DBG_UTIL
+ if ( IsDialog() || (GetType() == WINDOW_TABPAGE) || (GetType() == WINDOW_DOCKINGWINDOW) )
+ {
+ DBG_DIALOGTEST( this );
+ }
+#endif
+
+ ImplShowAllOverlaps();
+ }
+
+ if( aDogTag.IsDelete() )
+ return;
+ // invalidate all saved backgrounds
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ // the SHOW/HIDE events also serve as indicators to send child creation/destroy events to the access bridge
+ // However, the access bridge only uses this event if the data member is not NULL (it's kind of a hack that
+ // we re-use the SHOW/HIDE events this way, with this particular semantics).
+ // Since #104887#, the notifications for the access bridge are done in Impl(Set|Reset)ReallyVisible. Here, we
+ // now only notify with a NULL data pointer, for all other clients except the access bridge.
+ if ( !bRealVisibilityChanged )
+ ImplCallEventListeners( mpWindowImpl->mbVisible ? VCLEVENT_WINDOW_SHOW : VCLEVENT_WINDOW_HIDE, NULL );
+ if( aDogTag.IsDelete() )
+ return;
+
+ // #107575#, if a floating windows is shown that grabs the focus, we have to notify the toolkit about it
+ // ImplGrabFocus() is not called in this case
+ // Because this might lead to problems the task will be shifted to 6.y
+ // Note: top-level context menues are registered at the access bridge after being shown,
+ // so this will probably not help here....
+ /*
+ if( mpWindowImpl->mbFloatWin && ((FloatingWindow*) this )->GrabsFocus() )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ if( !mpWindowImpl->mbVisible )
+ {
+ ImplCallEventListeners( VCLEVENT_WINDOW_LOSEFOCUS );
+ if( pSVData->maWinData.mpFocusWin )
+ pSVData->maWinData.mpFocusWin->ImplCallEventListeners( VCLEVENT_WINDOW_GETFOCUS );
+ }
+ else
+ {
+ if( pSVData->maWinData.mpFocusWin )
+ pSVData->maWinData.mpFocusWin->ImplCallEventListeners( VCLEVENT_WINDOW_LOSEFOCUS );
+ ImplCallEventListeners( VCLEVENT_WINDOW_GETFOCUS );
+ }
+ }
+ */
+}
+
+// -----------------------------------------------------------------------
+
+Size Window::GetSizePixel() const
+{
+ // #i43257# trigger pending resize handler to assure correct window sizes
+ if( mpWindowImpl->mpFrameData->maResizeTimer.IsActive() )
+ {
+ ImplDelData aDogtag( this );
+ mpWindowImpl->mpFrameData->maResizeTimer.Stop();
+ mpWindowImpl->mpFrameData->maResizeTimer.GetTimeoutHdl().Call( NULL );
+ if( aDogtag.IsDelete() )
+ return Size(0,0);
+ }
+
+ return Size( mnOutWidth+mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
+ mnOutHeight+mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder );
+}
+
+void Window::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
+ sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
+{
+ rLeftBorder = mpWindowImpl->mnLeftBorder;
+ rTopBorder = mpWindowImpl->mnTopBorder;
+ rRightBorder = mpWindowImpl->mnRightBorder;
+ rBottomBorder = mpWindowImpl->mnBottomBorder;
+}
+
+
+// -----------------------------------------------------------------------
+
+void Window::Enable( bool bEnable, bool bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !bEnable )
+ {
+ // Wenn ein Fenster disablte wird, wird automatisch der Tracking-Modus
+ // beendet oder der Capture geklaut
+ if ( IsTracking() )
+ EndTracking( ENDTRACK_CANCEL );
+ if ( IsMouseCaptured() )
+ ReleaseMouse();
+ // Wenn Fenster den Focus hat und in der Dialog-Steuerung enthalten,
+ // wird versucht, den Focus auf das naechste Control weiterzuschalten
+ // mpWindowImpl->mbDisabled darf erst nach Aufruf von ImplDlgCtrlNextWindow() gesetzt
+ // werden. Ansonsten muss ImplDlgCtrlNextWindow() umgestellt werden
+ if ( HasFocus() )
+ ImplDlgCtrlNextWindow();
+ }
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ mpWindowImpl->mpBorderWindow->Enable( bEnable, FALSE );
+ if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow->Enable( bEnable, TRUE );
+ }
+
+ // #i56102# restore app focus win in case the
+ // window was disabled when the frame focus changed
+ ImplSVData* pSVData = ImplGetSVData();
+ if( bEnable &&
+ pSVData->maWinData.mpFocusWin == NULL &&
+ mpWindowImpl->mpFrameData->mbHasFocus &&
+ mpWindowImpl->mpFrameData->mpFocusWin == this )
+ pSVData->maWinData.mpFocusWin = this;
+
+ if ( mpWindowImpl->mbDisabled != !bEnable )
+ {
+ mpWindowImpl->mbDisabled = !bEnable;
+ if ( mpWindowImpl->mpSysObj )
+ mpWindowImpl->mpSysObj->Enable( bEnable && !mpWindowImpl->mbInputDisabled );
+// if ( mpWindowImpl->mbFrame )
+// mpWindowImpl->mpFrame->Enable( bEnable && !mpWindowImpl->mbInputDisabled );
+ StateChanged( STATE_CHANGE_ENABLE );
+
+ ImplCallEventListeners( bEnable ? VCLEVENT_WINDOW_ENABLED : VCLEVENT_WINDOW_DISABLED );
+ }
+
+ if ( bChild || mpWindowImpl->mbChildNotify )
+ {
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->Enable( bEnable, bChild );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+
+ if ( IsReallyVisible() )
+ ImplGenerateMouseMove();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetCallHandlersOnInputDisabled( bool bCall )
+{
+ mpWindowImpl->mbCallHandlersDuringInputDisabled = bCall ? TRUE : FALSE;
+
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->SetCallHandlersOnInputDisabled( bCall );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool Window::IsCallHandlersOnInputDisabled() const
+{
+ return mpWindowImpl->mbCallHandlersDuringInputDisabled ? true : false;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableInput( BOOL bEnable, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ BOOL bNotify = (bEnable != mpWindowImpl->mbInputDisabled);
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ mpWindowImpl->mpBorderWindow->EnableInput( bEnable, FALSE );
+ if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow )
+ ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow->EnableInput( bEnable, TRUE );
+ }
+
+ if ( (! bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) ||
+ ( bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled) )
+ {
+ // Wenn ein Fenster disablte wird, wird automatisch der
+ // Tracking-Modus beendet oder der Capture geklaut
+ if ( !bEnable )
+ {
+ if ( IsTracking() )
+ EndTracking( ENDTRACK_CANCEL );
+ if ( IsMouseCaptured() )
+ ReleaseMouse();
+ }
+
+ if ( mpWindowImpl->mbInputDisabled != !bEnable )
+ {
+ mpWindowImpl->mbInputDisabled = !bEnable;
+ if ( mpWindowImpl->mpSysObj )
+ mpWindowImpl->mpSysObj->Enable( !mpWindowImpl->mbDisabled && bEnable );
+// if ( mpWindowImpl->mbFrame )
+// mpWindowImpl->mpFrame->Enable( !mpWindowImpl->mbDisabled && bEnable );
+ }
+ }
+
+ // #i56102# restore app focus win in case the
+ // window was disabled when the frame focus changed
+ ImplSVData* pSVData = ImplGetSVData();
+ if( bEnable &&
+ pSVData->maWinData.mpFocusWin == NULL &&
+ mpWindowImpl->mpFrameData->mbHasFocus &&
+ mpWindowImpl->mpFrameData->mpFocusWin == this )
+ pSVData->maWinData.mpFocusWin = this;
+
+ if ( bChild || mpWindowImpl->mbChildNotify )
+ {
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->EnableInput( bEnable, bChild );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+
+ if ( IsReallyVisible() )
+ ImplGenerateMouseMove();
+
+ // #104827# notify parent
+ if ( bNotify )
+ {
+ NotifyEvent aNEvt( bEnable ? EVENT_INPUTENABLE : EVENT_INPUTDISABLE, this );
+ Notify( aNEvt );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableInput( BOOL bEnable, BOOL bChild, BOOL bSysWin,
+ const Window* pExcludeWindow )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ EnableInput( bEnable, bChild );
+ if ( bSysWin )
+ {
+ // pExculeWindow is the first Overlap-Frame --> if this
+ // shouldn't be the case, than this must be changed in dialog.cxx
+ if( pExcludeWindow )
+ pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow();
+ Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap;
+ while ( pSysWin )
+ {
+ // Is Window in the path from this window
+ if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, TRUE ) )
+ {
+ // Is Window not in the exclude window path or not the
+ // exclude window, than change the status
+ if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, TRUE ) )
+ pSysWin->EnableInput( bEnable, bChild );
+ }
+ pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
+ }
+
+ // enable/disable floating system windows as well
+ Window* pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
+ while ( pFrameWin )
+ {
+ if( pFrameWin->ImplIsFloatingWindow() )
+ {
+ // Is Window in the path from this window
+ if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, TRUE ) )
+ {
+ // Is Window not in the exclude window path or not the
+ // exclude window, than change the status
+ if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, TRUE ) )
+ pFrameWin->EnableInput( bEnable, bChild );
+ }
+ }
+ pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+
+ // the same for ownerdraw floating windows
+ if( mpWindowImpl->mbFrame )
+ {
+ ::std::vector< Window* >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList;
+ ::std::vector< Window* >::iterator p = rList.begin();
+ while( p != rList.end() )
+ {
+ // Is Window in the path from this window
+ if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( (*p), TRUE ) )
+ {
+ // Is Window not in the exclude window path or not the
+ // exclude window, than change the status
+ if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( (*p), TRUE ) )
+ (*p)->EnableInput( bEnable, bChild );
+ }
+ p++;
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::AlwaysEnableInput( BOOL bAlways, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, FALSE );
+
+ if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled )
+ {
+ mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled;
+
+ if ( bAlways )
+ EnableInput( TRUE, FALSE );
+ }
+ else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled )
+ {
+ mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
+ }
+
+ if ( bChild || mpWindowImpl->mbChildNotify )
+ {
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->AlwaysEnableInput( bAlways, bChild );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::AlwaysDisableInput( BOOL bAlways, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->AlwaysDisableInput( bAlways, FALSE );
+
+ if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled )
+ {
+ mpWindowImpl->meAlwaysInputMode = AlwaysInputDisabled;
+
+ if ( bAlways )
+ EnableInput( FALSE, FALSE );
+ }
+ else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputDisabled )
+ {
+ mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
+ }
+
+ if ( bChild || mpWindowImpl->mbChildNotify )
+ {
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->AlwaysDisableInput( bAlways, bChild );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetActivateMode( USHORT nMode )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->SetActivateMode( nMode );
+
+ if ( mpWindowImpl->mnActivateMode != nMode )
+ {
+ mpWindowImpl->mnActivateMode = nMode;
+
+ // Evtl. ein Decativate/Activate ausloesen
+ if ( mpWindowImpl->mnActivateMode )
+ {
+ if ( (mpWindowImpl->mbActive || (GetType() == WINDOW_BORDERWINDOW)) &&
+ !HasChildPathFocus( TRUE ) )
+ {
+ mpWindowImpl->mbActive = FALSE;
+ Deactivate();
+ }
+ }
+ else
+ {
+ if ( !mpWindowImpl->mbActive || (GetType() == WINDOW_BORDERWINDOW) )
+ {
+ mpWindowImpl->mbActive = TRUE;
+ Activate();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ToTop( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplStartToTop( nFlags );
+ ImplFocusToTop( nFlags, IsReallyVisible() );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetZOrder( Window* pRefWindow, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ mpWindowImpl->mpBorderWindow->SetZOrder( pRefWindow, nFlags );
+ return;
+ }
+
+ if ( nFlags & WINDOW_ZORDER_FIRST )
+ {
+ if ( ImplIsOverlapWindow() )
+ pRefWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
+ else
+ pRefWindow = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
+ nFlags |= WINDOW_ZORDER_BEFOR;
+ }
+ else if ( nFlags & WINDOW_ZORDER_LAST )
+ {
+ if ( ImplIsOverlapWindow() )
+ pRefWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap;
+ else
+ pRefWindow = mpWindowImpl->mpParent->mpWindowImpl->mpLastChild;
+ nFlags |= WINDOW_ZORDER_BEHIND;
+ }
+
+ while ( pRefWindow->mpWindowImpl->mpBorderWindow )
+ pRefWindow = pRefWindow->mpWindowImpl->mpBorderWindow;
+ if ( (pRefWindow == this) || mpWindowImpl->mbFrame )
+ return;
+
+ DBG_ASSERT( pRefWindow->mpWindowImpl->mpParent == mpWindowImpl->mpParent, "Window::SetZOrder() - pRefWindow has other parent" );
+ if ( nFlags & WINDOW_ZORDER_BEFOR )
+ {
+ if ( pRefWindow->mpWindowImpl->mpPrev == this )
+ return;
+
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
+ else
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
+ if ( mpWindowImpl->mpNext )
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
+ else
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
+ if ( !pRefWindow->mpWindowImpl->mpPrev )
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = this;
+ }
+ else
+ {
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
+ else
+ mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
+ if ( mpWindowImpl->mpNext )
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
+ else
+ mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
+ if ( !pRefWindow->mpWindowImpl->mpPrev )
+ mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = this;
+ }
+
+ mpWindowImpl->mpPrev = pRefWindow->mpWindowImpl->mpPrev;
+ mpWindowImpl->mpNext = pRefWindow;
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
+ }
+ else if ( nFlags & WINDOW_ZORDER_BEHIND )
+ {
+ if ( pRefWindow->mpWindowImpl->mpNext == this )
+ return;
+
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
+ else
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
+ if ( mpWindowImpl->mpNext )
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
+ else
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
+ if ( !pRefWindow->mpWindowImpl->mpNext )
+ mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = this;
+ }
+ else
+ {
+ if ( mpWindowImpl->mpPrev )
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
+ else
+ mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
+ if ( mpWindowImpl->mpNext )
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
+ else
+ mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
+ if ( !pRefWindow->mpWindowImpl->mpNext )
+ mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = this;
+ }
+
+ mpWindowImpl->mpPrev = pRefWindow;
+ mpWindowImpl->mpNext = pRefWindow->mpWindowImpl->mpNext;
+ if ( mpWindowImpl->mpNext )
+ mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
+ mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
+ }
+
+ if ( IsReallyVisible() )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ if ( mpWindowImpl->mbInitWinClipRegion || !mpWindowImpl->maWinClipRegion.IsEmpty() )
+ {
+ BOOL bInitWinClipRegion = mpWindowImpl->mbInitWinClipRegion;
+ ImplSetClipFlag();
+
+ // Wenn ClipRegion noch nicht initalisiert wurde, dann
+ // gehen wir davon aus, das das Fenster noch nicht
+ // ausgegeben wurde und loesen somit auch keine
+ // Invalidates aus. Dies ist eine Optimierung fuer
+ // HTML-Dokumenten mit vielen Controls. Wenn es mal
+ // Probleme mit dieser Abfrage gibt, sollte man ein
+ // Flag einfuehren, ob das Fenster nach Show schon
+ // einmal ausgegeben wurde.
+ if ( !bInitWinClipRegion )
+ {
+ // Alle nebeneinanderliegen Fenster invalidieren
+ // Noch nicht komplett implementiert !!!
+ Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Window* pWindow = NULL;
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( mpWindowImpl->mpOverlapWindow )
+ pWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
+ }
+ else
+ pWindow = ImplGetParent()->mpWindowImpl->mpFirstChild;
+ // Alle Fenster, die vor uns liegen und von uns verdeckt wurden,
+ // invalidieren
+ while ( pWindow )
+ {
+ if ( pWindow == this )
+ break;
+ Rectangle aCompRect( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
+ Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
+ if ( aWinRect.IsOver( aCompRect ) )
+ pWindow->Invalidate( INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ // Wenn uns ein Fenster welches im Hinterund liegt verdeckt hat,
+ // dann muessen wir uns neu ausgeben
+ while ( pWindow )
+ {
+ if ( pWindow != this )
+ {
+ Rectangle aCompRect( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
+ Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
+ if ( aWinRect.IsOver( aCompRect ) )
+ {
+ Invalidate( INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
+ break;
+ }
+ }
+ pWindow = pWindow->mpWindowImpl->mpNext;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableAlwaysOnTop( BOOL bEnable )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mpWindowImpl->mbAlwaysOnTop = bEnable;
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->EnableAlwaysOnTop( bEnable );
+ else if ( bEnable && IsReallyVisible() )
+ ToTop();
+
+ if ( mpWindowImpl->mbFrame )
+ mpWindowImpl->mpFrame->SetAlwaysOnTop( bEnable );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPosSizePixel( long nX, long nY,
+ long nWidth, long nHeight, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ BOOL bHasValidSize = !mpWindowImpl->mbDefSize;
+
+ if ( nFlags & WINDOW_POSSIZE_POS )
+ mpWindowImpl->mbDefPos = FALSE;
+ if ( nFlags & WINDOW_POSSIZE_SIZE )
+ mpWindowImpl->mbDefSize = FALSE;
+
+ // Oberstes BorderWindow ist das Window, welches positioniert werden soll
+ Window* pWindow = this;
+ while ( pWindow->mpWindowImpl->mpBorderWindow )
+ pWindow = pWindow->mpWindowImpl->mpBorderWindow;
+
+ if ( pWindow->mpWindowImpl->mbFrame )
+ {
+ // Note: if we're positioning a frame, the coordinates are interpreted
+ // as being the top-left corner of the window's client area and NOT
+ // as the position of the border ! (due to limitations of several UNIX window managers)
+ long nOldWidth = pWindow->mnOutWidth;
+
+ if ( !(nFlags & WINDOW_POSSIZE_WIDTH) )
+ nWidth = pWindow->mnOutWidth;
+ if ( !(nFlags & WINDOW_POSSIZE_HEIGHT) )
+ nHeight = pWindow->mnOutHeight;
+
+
+ USHORT nSysFlags=0;
+ if( nFlags & WINDOW_POSSIZE_WIDTH )
+ nSysFlags |= SAL_FRAME_POSSIZE_WIDTH;
+ if( nFlags & WINDOW_POSSIZE_HEIGHT )
+ nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT;
+ if( nFlags & WINDOW_POSSIZE_X )
+ {
+ nSysFlags |= SAL_FRAME_POSSIZE_X;
+ if( pWindow->GetParent() && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
+ {
+ Window* pParent = pWindow->GetParent();
+ nX += pParent->mnOutOffX;
+ }
+ if( GetParent() && GetParent()->ImplIsAntiparallel() )
+ {
+ // --- RTL --- (re-mirror at parent window)
+ Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) );
+ GetParent()->ImplReMirror( aRect );
+ nX = aRect.nLeft;
+ }
+ }
+ if( !(nFlags & WINDOW_POSSIZE_X) && bHasValidSize && pWindow->mpWindowImpl->mpFrame->maGeometry.nWidth )
+ {
+ // --- RTL --- make sure the old right aligned position is not changed
+ // system windows will always grow to the right
+ if( pWindow->GetParent() && pWindow->GetParent()->ImplHasMirroredGraphics() )
+ {
+ long myWidth = nOldWidth;
+ if( !myWidth )
+ myWidth = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nWidth;
+ if( !myWidth )
+ myWidth = nWidth;
+ nFlags |= WINDOW_POSSIZE_X;
+ nSysFlags |= SAL_FRAME_POSSIZE_X;
+ nX = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX - pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX -
+ mpWindowImpl->mpFrame->GetUnmirroredGeometry().nLeftDecoration;
+ nX = pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX - mpWindowImpl->mpFrame->GetUnmirroredGeometry().nLeftDecoration +
+ pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nWidth - myWidth - 1 - mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX;
+ if(!(nFlags & WINDOW_POSSIZE_Y))
+ {
+ nFlags |= WINDOW_POSSIZE_Y;
+ nSysFlags |= SAL_FRAME_POSSIZE_Y;
+ nY = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nY - pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nY -
+ mpWindowImpl->mpFrame->GetUnmirroredGeometry().nTopDecoration;
+ }
+ }
+ }
+ if( nFlags & WINDOW_POSSIZE_Y )
+ {
+ nSysFlags |= SAL_FRAME_POSSIZE_Y;
+ if( pWindow->GetParent() && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
+ {
+ Window* pParent = pWindow->GetParent();
+ nY += pParent->mnOutOffY;
+ }
+ }
+
+ if( nSysFlags & (SAL_FRAME_POSSIZE_WIDTH|SAL_FRAME_POSSIZE_HEIGHT) )
+ {
+ // check for min/max client size and adjust size accordingly
+ // otherwise it may happen that the resize event is ignored, i.e. the old size remains
+ // unchanged but ImplHandleResize() is called with the wrong size
+ SystemWindow *pSystemWindow = dynamic_cast< SystemWindow* >( pWindow );
+ if( pSystemWindow )
+ {
+ Size aMinSize = pSystemWindow->GetMinOutputSizePixel();
+ Size aMaxSize = pSystemWindow->GetMaxOutputSizePixel();
+ if( nWidth < aMinSize.Width() )
+ nWidth = aMinSize.Width();
+ if( nHeight < aMinSize.Height() )
+ nHeight = aMinSize.Height();
+
+ if( nWidth > aMaxSize.Width() )
+ nWidth = aMaxSize.Width();
+ if( nHeight > aMaxSize.Height() )
+ nHeight = aMaxSize.Height();
+ }
+ }
+
+ pWindow->mpWindowImpl->mpFrame->SetPosSize( nX, nY, nWidth, nHeight, nSysFlags );
+
+ // Resize should be called directly. If we havn't
+ // set the correct size, we get a second resize from
+ // the system with the correct size. This can be happend
+ // if the size is to small or to large.
+ ImplHandleResize( pWindow, nWidth, nHeight );
+ }
+ else
+ {
+ pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags );
+ if ( IsReallyVisible() )
+ ImplGenerateMouseMove();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::GetPosPixel() const
+{
+ return mpWindowImpl->maPos;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Window::GetDesktopRectPixel() const
+{
+ Rectangle rRect;
+ mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrame->GetWorkArea( rRect );
+ return rRect;
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::OutputToScreenPixel( const Point& rPos ) const
+{
+ // relative to top level parent
+ return Point( rPos.X()+mnOutOffX, rPos.Y()+mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::ScreenToOutputPixel( const Point& rPos ) const
+{
+ // relative to top level parent
+ return Point( rPos.X()-mnOutOffX, rPos.Y()-mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+long Window::ImplGetUnmirroredOutOffX()
+{
+ // revert mnOutOffX changes that were potentially made in ImplPosSizeWindow
+ long offx = mnOutOffX;
+ if( ImplHasMirroredGraphics() )
+ {
+ if( mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
+ {
+ if ( !ImplIsOverlapWindow() )
+ offx -= mpWindowImpl->mpParent->mnOutOffX;
+
+ offx = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - offx;
+
+ if ( !ImplIsOverlapWindow() )
+ offx += mpWindowImpl->mpParent->mnOutOffX;
+
+ }
+ }
+ return offx;
+}
+
+// normalized screen pixel are independent of mirroring
+Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const
+{
+ // relative to top level parent
+ long offx = ((Window*) this)->ImplGetUnmirroredOutOffX();
+ return Point( rPos.X()+offx, rPos.Y()+mnOutOffY );
+}
+
+Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const
+{
+ // relative to top level parent
+ long offx = ((Window*) this)->ImplGetUnmirroredOutOffX();
+ return Point( rPos.X()-offx, rPos.Y()-mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const
+{
+ // relative to the screen
+ Point p = OutputToScreenPixel( rPos );
+ SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
+ p.X() += g.nX;
+ p.Y() += g.nY;
+ return p;
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::AbsoluteScreenToOutputPixel( const Point& rPos ) const
+{
+ // relative to the screen
+ Point p = ScreenToOutputPixel( rPos );
+ SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
+ p.X() -= g.nX;
+ p.Y() -= g.nY;
+ return p;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const Rectangle &rRect ) const
+{
+ // this method creates unmirrored screen coordinates to be compared with the desktop
+ // and is used for positioning of RTL popup windows correctly on the screen
+ SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
+
+ Point p1 = OutputToScreenPixel( rRect.TopRight() );
+ p1.X() = g.nX+g.nWidth-p1.X();
+ p1.Y() += g.nY;
+
+ Point p2 = OutputToScreenPixel( rRect.BottomLeft() );
+ p2.X() = g.nX+g.nWidth-p2.X();
+ p2.Y() += g.nY;
+
+ return Rectangle( p1, p2 );
+}
+
+
+// -----------------------------------------------------------------------
+
+Rectangle Window::GetWindowExtentsRelative( Window *pRelativeWindow ) const
+{
+ // with decoration
+ return ImplGetWindowExtentsRelative( pRelativeWindow, FALSE );
+}
+
+Rectangle Window::GetClientWindowExtentsRelative( Window *pRelativeWindow ) const
+{
+ // without decoration
+ return ImplGetWindowExtentsRelative( pRelativeWindow, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Window::ImplGetWindowExtentsRelative( Window *pRelativeWindow, BOOL bClientOnly ) const
+{
+ SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
+ // make sure we use the extent of our border window,
+ // otherwise we miss a few pixels
+ const Window *pWin = (!bClientOnly && mpWindowImpl->mpBorderWindow) ? mpWindowImpl->mpBorderWindow : this;
+
+ Point aPos( pWin->OutputToScreenPixel( Point(0,0) ) );
+ aPos.X() += g.nX;
+ aPos.Y() += g.nY;
+ Size aSize ( pWin->GetSizePixel() );
+ // #104088# do not add decoration to the workwindow to be compatible to java accessibility api
+ if( !bClientOnly && (mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WINDOW_WORKWINDOW)) )
+ {
+ aPos.X() -= g.nLeftDecoration;
+ aPos.Y() -= g.nTopDecoration;
+ aSize.Width() += g.nLeftDecoration + g.nRightDecoration;
+ aSize.Height() += g.nTopDecoration + g.nBottomDecoration;
+ }
+ if( pRelativeWindow )
+ {
+ // #106399# express coordinates relative to borderwindow
+ Window *pRelWin = (!bClientOnly && pRelativeWindow->mpWindowImpl->mpBorderWindow) ? pRelativeWindow->mpWindowImpl->mpBorderWindow : pRelativeWindow;
+ aPos = pRelWin->AbsoluteScreenToOutputPixel( aPos );
+ }
+ return Rectangle( aPos, aSize );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Scroll( long nHorzScroll, long nVertScroll, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplScroll( Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) ),
+ nHorzScroll, nVertScroll, nFlags & ~SCROLL_CLIP );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Scroll( long nHorzScroll, long nVertScroll,
+ const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Rectangle aRect = ImplLogicToDevicePixel( rRect );
+ aRect.Intersection( Rectangle( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ) );
+ if ( !aRect.IsEmpty() )
+ ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invalidate( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ ImplInvalidate( NULL, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invalidate( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ Rectangle aRect = ImplLogicToDevicePixel( rRect );
+ if ( !aRect.IsEmpty() )
+ {
+ Region aRegion( aRect );
+ ImplInvalidate( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invalidate( const Region& rRegion, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ if ( rRegion.IsNull() )
+ ImplInvalidate( NULL, nFlags );
+ else
+ {
+ Region aRegion = ImplPixelToDevicePixel( LogicToPixel( rRegion ) );
+ if ( !aRegion.IsEmpty() )
+ ImplInvalidate( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Validate( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ ImplValidate( NULL, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Validate( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ Rectangle aRect = ImplLogicToDevicePixel( rRect );
+ if ( !aRect.IsEmpty() )
+ {
+ Region aRegion( aRect );
+ ImplValidate( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Validate( const Region& rRegion, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ if ( rRegion.IsNull() )
+ ImplValidate( NULL, nFlags );
+ else
+ {
+ Region aRegion = ImplPixelToDevicePixel( LogicToPixel( rRegion ) );
+ if ( !aRegion.IsEmpty() )
+ ImplValidate( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HasPaintEvent() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !mpWindowImpl->mbReallyVisible )
+ return FALSE;
+
+ if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
+ return TRUE;
+
+ if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINT )
+ return TRUE;
+
+ if ( !ImplIsOverlapWindow() )
+ {
+ const Window* pTempWindow = this;
+ do
+ {
+ pTempWindow = pTempWindow->ImplGetParent();
+ if ( pTempWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINTCHILDS | IMPL_PAINT_PAINTALLCHILDS) )
+ return TRUE;
+ }
+ while ( !pTempWindow->ImplIsOverlapWindow() );
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Update()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpBorderWindow )
+ {
+ mpWindowImpl->mpBorderWindow->Update();
+ return;
+ }
+
+ if ( !mpWindowImpl->mbReallyVisible )
+ return;
+
+ BOOL bFlush = FALSE;
+ if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
+ {
+ Point aPoint( 0, 0 );
+ Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
+ ImplInvalidateOverlapFrameRegion( aRegion );
+ if ( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) )
+ bFlush = TRUE;
+ }
+
+ // Zuerst muessen wir alle Fenster ueberspringen, die Paint-Transparent
+ // sind
+ Window* pUpdateWindow = this;
+ Window* pWindow = pUpdateWindow;
+ while ( !pWindow->ImplIsOverlapWindow() )
+ {
+ if ( !pWindow->mpWindowImpl->mbPaintTransparent )
+ {
+ pUpdateWindow = pWindow;
+ break;
+ }
+ pWindow = pWindow->ImplGetParent();
+ }
+ // Ein Update wirkt immer auf das Window, wo PAINTALLCHILDS gesetzt
+ // ist, damit nicht zuviel gemalt wird
+ pWindow = pUpdateWindow;
+ do
+ {
+ if ( pWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDS )
+ pUpdateWindow = pWindow;
+ if ( pWindow->ImplIsOverlapWindow() )
+ break;
+ pWindow = pWindow->ImplGetParent();
+ }
+ while ( pWindow );
+
+ // Wenn es etwas zu malen gibt, dann ein Paint ausloesen
+ if ( pUpdateWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDS) )
+ {
+ // und fuer alle ueber uns stehende System-Fenster auch ein Update
+ // ausloesen, damit nicht die ganze Zeit luecken stehen bleiben
+ Window* pUpdateOverlapWindow = ImplGetFirstOverlapWindow()->mpWindowImpl->mpFirstOverlap;
+ while ( pUpdateOverlapWindow )
+ {
+ pUpdateOverlapWindow->Update();
+ pUpdateOverlapWindow = pUpdateOverlapWindow->mpWindowImpl->mpNext;
+ }
+
+ pUpdateWindow->ImplCallPaint( NULL, pUpdateWindow->mpWindowImpl->mnPaintFlags );
+ }
+
+ if ( bFlush )
+ Flush();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Flush()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ mpWindowImpl->mpFrame->Flush( aWinRect );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Sync()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mpWindowImpl->mpFrame->Sync();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetUpdateMode( BOOL bUpdate )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mpWindowImpl->mbNoUpdate = !bUpdate;
+ StateChanged( STATE_CHANGE_UPDATEMODE );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GrabFocus()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplGrabFocus( 0 );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HasFocus() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ // #107575# the first floating window always has the keyboard focus, see also winproc.cxx: ImplGetKeyInputWindow()
+ // task was shifted to 6.y, so its commented out
+ /*
+ Window* pFocusWin = ImplGetSVData()->maWinData.mpFirstFloat;
+ if( pFocusWin && pFocusWin->mpWindowImpl->mbFloatWin && ((FloatingWindow *)pFocusWin)->GrabsFocus() )
+ pFocusWin = pFocusWin->GetPreferredKeyInputWindow();
+ else
+ pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
+
+ return (this == pFocusWin);
+ */
+
+ return (this == ImplGetSVData()->maWinData.mpFocusWin);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GrabFocusToDocument()
+{
+ Window *pWin = this;
+ while( pWin )
+ {
+ if( !pWin->GetParent() )
+ {
+ pWin->ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
+ return;
+ }
+ pWin = pWin->GetParent();
+ }
+}
+
+void Window::SetFakeFocus( bool bFocus )
+{
+ ImplGetWindowImpl()->mbFakeFocusSet = bFocus;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HasChildPathFocus( BOOL bSystemWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ // #107575#, the first floating window always has the keyboard focus, see also winproc.cxx: ImplGetKeyInputWindow()
+ // task was shifted to 6.y, so its commented out
+ /*
+ Window* pFocusWin = ImplGetSVData()->maWinData.mpFirstFloat;
+ if( pFocusWin && pFocusWin->mpWindowImpl->mbFloatWin && ((FloatingWindow *)pFocusWin)->GrabsFocus() )
+ pFocusWin = pFocusWin->GetPreferredKeyInputWindow();
+ else
+ pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
+ */
+ Window* pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
+ if ( pFocusWin )
+ return ImplIsWindowOrChild( pFocusWin, bSystemWindow );
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::CaptureMouse()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Tracking evt. beenden
+ if ( pSVData->maWinData.mpTrackWin != this )
+ {
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ }
+
+ if ( pSVData->maWinData.mpCaptureWin != this )
+ {
+ pSVData->maWinData.mpCaptureWin = this;
+ mpWindowImpl->mpFrame->CaptureMouse( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ReleaseMouse()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ DBG_ASSERTWARNING( pSVData->maWinData.mpCaptureWin == this,
+ "Window::ReleaseMouse(): window doesn't have the mouse capture" );
+
+ if ( pSVData->maWinData.mpCaptureWin == this )
+ {
+ pSVData->maWinData.mpCaptureWin = NULL;
+ mpWindowImpl->mpFrame->CaptureMouse( FALSE );
+ ImplGenerateMouseMove();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsMouseCaptured() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (this == ImplGetSVData()->maWinData.mpCaptureWin);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPointer( const Pointer& rPointer )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->maPointer == rPointer )
+ return;
+
+ mpWindowImpl->maPointer = rPointer;
+
+ // Pointer evt. direkt umsetzen
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableChildPointerOverwrite( BOOL bOverwrite )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mbChildPtrOverwrite == bOverwrite )
+ return;
+
+ mpWindowImpl->mbChildPtrOverwrite = bOverwrite;
+
+ // Pointer evt. direkt umsetzen
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPointerPosPixel( const Point& rPos )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Point aPos = ImplOutputToFrame( rPos );
+ if( ImplHasMirroredGraphics() )
+ {
+ if( !IsRTLEnabled() )
+ {
+ // --- RTL --- (re-mirror mouse pos at this window)
+ ImplReMirror( aPos );
+ }
+ // mirroring is required here, SetPointerPos bypasses SalGraphics
+ mpGraphics->mirror( aPos.X(), this );
+ }
+ else if( ImplIsAntiparallel() )
+ {
+ ImplReMirror( aPos );
+ }
+ mpWindowImpl->mpFrame->SetPointerPos( aPos.X(), aPos.Y() );
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::GetPointerPosPixel()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Point aPos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
+ if( ImplIsAntiparallel() )
+ {
+ // --- RTL --- (re-mirror mouse pos at this window)
+ ImplReMirror( aPos );
+ }
+ return ImplFrameToOutput( aPos );
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::GetLastPointerPosPixel()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Point aPos( mpWindowImpl->mpFrameData->mnBeforeLastMouseX, mpWindowImpl->mpFrameData->mnBeforeLastMouseY );
+ if( ImplIsAntiparallel() )
+ {
+ // --- RTL --- (re-mirror mouse pos at this window)
+ ImplReMirror( aPos );
+ }
+ return ImplFrameToOutput( aPos );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ShowPointer( BOOL bVisible )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mbNoPtrVisible != !bVisible )
+ {
+ mpWindowImpl->mbNoPtrVisible = !bVisible;
+
+ // Pointer evt. direkt umsetzen
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Window::PointerState Window::GetPointerState()
+{
+ PointerState aState;
+ aState.mnState = 0;
+
+ if (mpWindowImpl->mpFrame)
+ {
+ SalFrame::SalPointerState aSalPointerState;
+
+ aSalPointerState = mpWindowImpl->mpFrame->GetPointerState();
+ if( ImplIsAntiparallel() )
+ {
+ // --- RTL --- (re-mirror mouse pos at this window)
+ ImplReMirror( aSalPointerState.maPos );
+ }
+ aState.maPos = ImplFrameToOutput( aSalPointerState.maPos );
+ aState.mnState = aSalPointerState.mnState;
+ }
+ return aState;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsMouseOver()
+{
+ return ImplGetWinData()->mbMouseOver;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnterWait()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mpWindowImpl->mnWaitCount++;
+
+ if ( mpWindowImpl->mnWaitCount == 1 )
+ {
+ // Pointer evt. direkt umsetzen
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::LeaveWait()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mnWaitCount )
+ {
+ mpWindowImpl->mnWaitCount--;
+
+ if ( !mpWindowImpl->mnWaitCount )
+ {
+ // Pointer evt. direkt umsetzen
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetCursor( Cursor* pCursor )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpCursor != pCursor )
+ {
+ if ( mpWindowImpl->mpCursor )
+ mpWindowImpl->mpCursor->ImplHide();
+ mpWindowImpl->mpCursor = pCursor;
+ if ( pCursor )
+ pCursor->ImplShow();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetText( const XubString& rStr )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ String oldTitle( mpWindowImpl->maText );
+ mpWindowImpl->maText = rStr;
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->SetText( rStr );
+ else if ( mpWindowImpl->mbFrame )
+ mpWindowImpl->mpFrame->SetTitle( rStr );
+
+ ImplCallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldTitle );
+
+ // #107247# needed for accessibility
+ // The VCLEVENT_WINDOW_FRAMETITLECHANGED is (mis)used to notify accessible name changes.
+ // Therefore a window, which is labeled by this window, must also notify an accessible
+ // name change.
+ if ( IsReallyVisible() )
+ {
+ Window* pWindow = GetLabelFor();
+ if ( pWindow && pWindow != this )
+ pWindow->ImplCallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldTitle );
+ }
+
+ StateChanged( STATE_CHANGE_TEXT );
+}
+
+// -----------------------------------------------------------------------
+
+String Window::GetText() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return mpWindowImpl->maText;
+}
+
+// -----------------------------------------------------------------------
+
+String Window::GetDisplayText() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return GetText();
+}
+
+// -----------------------------------------------------------------------
+
+const Wallpaper& Window::GetDisplayBackground() const
+{
+ // FIXME: fix issue 52349, need to fix this really in
+ // all NWF enabled controls
+ const ToolBox* pTB = dynamic_cast<const ToolBox*>(this);
+ if( pTB )
+ {
+ if( IsNativeWidgetEnabled() )
+ return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground;
+ }
+
+ if( !IsBackground() )
+ {
+ if( mpWindowImpl->mpParent )
+ return mpWindowImpl->mpParent->GetDisplayBackground();
+ }
+
+ const Wallpaper& rBack = GetBackground();
+ if( ! rBack.IsBitmap() &&
+ ! rBack.IsGradient() &&
+ rBack.GetColor().GetColor() == COL_TRANSPARENT &&
+ mpWindowImpl->mpParent )
+ return mpWindowImpl->mpParent->GetDisplayBackground();
+ return rBack;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& Window::GetHelpText() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ SmartId aSmartId = GetSmartHelpId();
+
+ ULONG nNumHelpId = 0;
+ String aStrHelpId;
+ if( aSmartId.HasString() )
+ aStrHelpId = aSmartId.GetStr();
+ if( aSmartId.HasNumeric() )
+ nNumHelpId = aSmartId.GetNum();
+ bool bStrHelpId = (aStrHelpId.Len() > 0);
+
+ if ( !mpWindowImpl->maHelpText.Len() && (nNumHelpId || bStrHelpId) )
+ {
+ if ( !IsDialog() && (mpWindowImpl->mnType != WINDOW_TABPAGE) && (mpWindowImpl->mnType != WINDOW_FLOATINGWINDOW) )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ if( bStrHelpId )
+ ((Window*)this)->mpWindowImpl->maHelpText = pHelp->GetHelpText( aStrHelpId, this );
+ else
+ ((Window*)this)->mpWindowImpl->maHelpText = pHelp->GetHelpText( nNumHelpId, this );
+ mpWindowImpl->mbHelpTextDynamic = FALSE;
+ }
+ }
+ }
+ else if( mpWindowImpl->mbHelpTextDynamic && (nNumHelpId || bStrHelpId) )
+ {
+ static const char* pEnv = getenv( "HELP_DEBUG" );
+ if( pEnv && *pEnv )
+ {
+ rtl::OUStringBuffer aTxt( 64+mpWindowImpl->maHelpText.Len() );
+ aTxt.append( mpWindowImpl->maHelpText );
+ aTxt.appendAscii( "\n------------------\n" );
+ if( bStrHelpId )
+ aTxt.append( rtl::OUString( aStrHelpId ) );
+ else
+ aTxt.append( sal_Int32( nNumHelpId ) );
+ mpWindowImpl->maHelpText = aTxt.makeStringAndClear();
+ }
+ mpWindowImpl->mbHelpTextDynamic = FALSE;
+ }
+
+ return mpWindowImpl->maHelpText;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::FindWindow( const Point& rPos ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Point aPos = OutputToScreenPixel( rPos );
+ return ((Window*)this)->ImplFindWindow( aPos );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::GetChildCount() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ USHORT nChildCount = 0;
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ nChildCount++;
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+
+ return nChildCount;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::GetChild( USHORT nChild ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ USHORT nChildCount = 0;
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ if ( nChild == nChildCount )
+ return pChild;
+ pChild = pChild->mpWindowImpl->mpNext;
+ nChildCount++;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::GetWindow( USHORT nType ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ switch ( nType )
+ {
+ case WINDOW_PARENT:
+ return mpWindowImpl->mpRealParent;
+
+ case WINDOW_FIRSTCHILD:
+ return mpWindowImpl->mpFirstChild;
+
+ case WINDOW_LASTCHILD:
+ return mpWindowImpl->mpLastChild;
+
+ case WINDOW_PREV:
+ return mpWindowImpl->mpPrev;
+
+ case WINDOW_NEXT:
+ return mpWindowImpl->mpNext;
+
+ case WINDOW_FIRSTOVERLAP:
+ return mpWindowImpl->mpFirstOverlap;
+
+ case WINDOW_LASTOVERLAP:
+ return mpWindowImpl->mpLastOverlap;
+
+ case WINDOW_OVERLAP:
+ if ( ImplIsOverlapWindow() )
+ return (Window*)this;
+ else
+ return mpWindowImpl->mpOverlapWindow;
+
+ case WINDOW_PARENTOVERLAP:
+ if ( ImplIsOverlapWindow() )
+ return mpWindowImpl->mpOverlapWindow;
+ else
+ return mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpOverlapWindow;
+
+ case WINDOW_CLIENT:
+ return ((Window*)this)->ImplGetWindow();
+
+ case WINDOW_REALPARENT:
+ return ImplGetParent();
+
+ case WINDOW_FRAME:
+ return mpWindowImpl->mpFrameWindow;
+
+ case WINDOW_BORDER:
+ if ( mpWindowImpl->mpBorderWindow )
+ return mpWindowImpl->mpBorderWindow->GetWindow( WINDOW_BORDER );
+ return (Window*)this;
+
+ case WINDOW_FIRSTTOPWINDOWCHILD:
+ return ImplGetWinData()->maTopWindowChildren.empty() ? NULL : *ImplGetWinData()->maTopWindowChildren.begin();
+
+ case WINDOW_LASTTOPWINDOWCHILD:
+ return ImplGetWinData()->maTopWindowChildren.empty() ? NULL : *ImplGetWinData()->maTopWindowChildren.rbegin();
+
+ case WINDOW_PREVTOPWINDOWSIBLING:
+ {
+ if ( !mpWindowImpl->mpRealParent )
+ return NULL;
+ const ::std::list< Window* >& rTopWindows( mpWindowImpl->mpRealParent->ImplGetWinData()->maTopWindowChildren );
+ ::std::list< Window* >::const_iterator myPos =
+ ::std::find( rTopWindows.begin(), rTopWindows.end(), this );
+ if ( myPos == rTopWindows.end() )
+ return NULL;
+ if ( myPos == rTopWindows.begin() )
+ return NULL;
+ return *--myPos;
+ }
+
+ case WINDOW_NEXTTOPWINDOWSIBLING:
+ {
+ if ( !mpWindowImpl->mpRealParent )
+ return NULL;
+ const ::std::list< Window* >& rTopWindows( mpWindowImpl->mpRealParent->ImplGetWinData()->maTopWindowChildren );
+ ::std::list< Window* >::const_iterator myPos =
+ ::std::find( rTopWindows.begin(), rTopWindows.end(), this );
+ if ( ( myPos == rTopWindows.end() ) || ( ++myPos == rTopWindows.end() ) )
+ return NULL;
+ return *myPos;
+ }
+
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsChild( const Window* pWindow, BOOL bSystemWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_CHKOBJ( pWindow, Window, ImplDbgCheckWindow );
+
+ do
+ {
+ if ( !bSystemWindow && pWindow->ImplIsOverlapWindow() )
+ break;
+
+ pWindow = pWindow->ImplGetParent();
+
+ if ( pWindow == this )
+ return TRUE;
+ }
+ while ( pWindow );
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsWindowOrChild( const Window* pWindow, BOOL bSystemWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_CHKOBJ( pWindow, Window, ImplDbgCheckWindow );
+
+ if ( this == pWindow )
+ return TRUE;
+ return ImplIsChild( pWindow, bSystemWindow );
+}
+
+// -----------------------------------------------------------------------
+
+const SystemEnvData* Window::GetSystemData() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return mpWindowImpl->mpFrame ? mpWindowImpl->mpFrame->GetSystemData() : NULL;
+}
+
+::com::sun::star::uno::Any Window::GetSystemDataAny() const
+{
+ ::com::sun::star::uno::Any aRet;
+ const SystemEnvData* pSysData = GetSystemData();
+ if( pSysData )
+ {
+ ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( (sal_Int8*)pSysData, pSysData->nSize );
+ aRet <<= aSeq;
+ }
+ return aRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetWindowPeer( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xPeer, VCLXWindow* pVCLXWindow )
+{
+ // be safe against re-entrance: first clear the old ref, then assign the new one
+ // #133706# / 2006-03-30 / frank.schoenheit@sun.com
+ mpWindowImpl->mxWindowPeer.clear();
+ mpWindowImpl->mxWindowPeer = xPeer;
+
+ mpWindowImpl->mpVCLXWindow = pVCLXWindow;
+}
+
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > Window::GetComponentInterface( BOOL bCreate )
+{
+ if ( !mpWindowImpl->mxWindowPeer.is() && bCreate )
+ {
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ if ( pWrapper )
+ mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this, sal_True );
+ }
+ return mpWindowImpl->mxWindowPeer;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetComponentInterface( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xIFace )
+{
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ DBG_ASSERT( pWrapper, "SetComponentInterface: No Wrapper!" );
+ if ( pWrapper )
+ pWrapper->SetWindowInterface( this, xIFace );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallDeactivateListeners( Window *pNew )
+{
+ // no deactivation if the the newly activated window is my child
+ if ( !pNew || !ImplIsChild( pNew ) )
+ {
+ ImplDelData aDogtag( this );
+ ImplCallEventListeners( VCLEVENT_WINDOW_DEACTIVATE );
+ if( aDogtag.IsDelete() )
+ return;
+
+ // #100759#, avoid walking the wrong frame's hierarchy
+ // eg, undocked docking windows (ImplDockFloatWin)
+ if ( ImplGetParent() && mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow )
+ ImplGetParent()->ImplCallDeactivateListeners( pNew );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallActivateListeners( Window *pOld )
+{
+ // no activation if the the old active window is my child
+ if ( !pOld || !ImplIsChild( pOld ) )
+ {
+ ImplDelData aDogtag( this );
+ ImplCallEventListeners( VCLEVENT_WINDOW_ACTIVATE, pOld );
+ if( aDogtag.IsDelete() )
+ return;
+
+ // #106298# revoke the change for 105369, because this change
+ // disabled the activate event for the parent,
+ // if the parent is a compound control
+ //if( !GetParent() || !GetParent()->IsCompoundControl() )
+ //{
+ // #100759#, avoid walking the wrong frame's hierarchy
+ // eg, undocked docking windows (ImplDockFloatWin)
+ // #104714#, revert the changes for 100759 because it has a side effect when pOld is a dialog
+ // additionally the gallery is not dockable anymore, so 100759 canot occur
+ if ( ImplGetParent() ) /* && mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow ) */
+ ImplGetParent()->ImplCallActivateListeners( pOld );
+ else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 )
+ {
+ // top level frame reached: store hint for DefModalDialogParent
+ ImplGetSVData()->maWinData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow;
+ }
+ //}
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool Window::ImplStopDnd()
+{
+ bool bRet = false;
+ if( mpWindowImpl->mpFrameData && mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
+ {
+ bRet = true;
+ mpWindowImpl->mpFrameData->mxDropTarget.clear();
+ mpWindowImpl->mpFrameData->mxDragSource.clear();
+ mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplStartDnd()
+{
+ GetDropTarget();
+}
+
+// -----------------------------------------------------------------------
+
+Reference< XDropTarget > Window::GetDropTarget()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( ! mpWindowImpl->mxDNDListenerContainer.is() )
+ {
+ sal_Int8 nDefaultActions = 0;
+
+ if( mpWindowImpl->mpFrameData )
+ {
+ if( ! mpWindowImpl->mpFrameData->mxDropTarget.is() )
+ {
+ // initialization is done in GetDragSource
+ Reference< XDragSource > xDragSource = GetDragSource();
+ }
+
+ if( mpWindowImpl->mpFrameData->mxDropTarget.is() )
+ {
+ nDefaultActions = mpWindowImpl->mpFrameData->mxDropTarget->getDefaultActions();
+
+ if( ! mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
+ {
+ mpWindowImpl->mpFrameData->mxDropTargetListener = new DNDEventDispatcher( mpWindowImpl->mpFrameWindow );
+
+ try
+ {
+ mpWindowImpl->mpFrameData->mxDropTarget->addDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
+
+ // register also as drag gesture listener if directly supported by drag source
+ Reference< XDragGestureRecognizer > xDragGestureRecognizer =
+ Reference< XDragGestureRecognizer > (mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
+
+ if( xDragGestureRecognizer.is() )
+ {
+ xDragGestureRecognizer->addDragGestureListener(
+ Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
+ }
+ else
+ mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = TRUE;
+
+ }
+
+ catch( RuntimeException exc )
+ {
+ // release all instances
+ mpWindowImpl->mpFrameData->mxDropTarget.clear();
+ mpWindowImpl->mpFrameData->mxDragSource.clear();
+ }
+ }
+ }
+
+ }
+
+ mpWindowImpl->mxDNDListenerContainer = static_cast < XDropTarget * > ( new DNDListenerContainer( nDefaultActions ) );
+ }
+
+ // this object is located in the same process, so there will be no runtime exception
+ return Reference< XDropTarget > ( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
+}
+
+// -----------------------------------------------------------------------
+
+Reference< XDragSource > Window::GetDragSource()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( mpWindowImpl->mpFrameData )
+ {
+ if( ! mpWindowImpl->mpFrameData->mxDragSource.is() )
+ {
+ try
+ {
+ Reference< XMultiServiceFactory > xFactory = vcl::unohelper::GetMultiServiceFactory();
+ if ( xFactory.is() )
+ {
+ const SystemEnvData * pEnvData = GetSystemData();
+
+ if( pEnvData )
+ {
+ Sequence< Any > aDragSourceAL( 2 ), aDropTargetAL( 2 );
+ OUString aDragSourceSN, aDropTargetSN;
+#if defined WNT
+ aDragSourceSN = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.OleDragSource" );
+ aDropTargetSN = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.OleDropTarget" );
+ aDragSourceAL[ 1 ] = makeAny( (sal_uInt32) pEnvData->hWnd );
+ aDropTargetAL[ 0 ] = makeAny( (sal_uInt32) pEnvData->hWnd );
+#elif defined QUARTZ
+ /* FIXME: Mac OS X specific dnd interface does not exist! *
+ * Using Windows based dnd as a temporary solution */
+ aDragSourceSN = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.OleDragSource" );
+ aDropTargetSN = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.OleDropTarget" );
+ aDragSourceAL[ 1 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->pView) ) );
+ aDropTargetAL[ 0 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->pView) ) );
+#elif defined UNX
+ aDropTargetAL.realloc( 3 );
+ aDragSourceAL.realloc( 3 );
+ aDragSourceSN = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.X11DragSource" );
+ aDropTargetSN = OUString::createFromAscii( "com.sun.star.datatransfer.dnd.X11DropTarget" );
+
+ aDragSourceAL[ 0 ] = makeAny( Application::GetDisplayConnection() );
+ aDragSourceAL[ 2 ] = makeAny( vcl::createBmpConverter() );
+ aDropTargetAL[ 0 ] = makeAny( Application::GetDisplayConnection() );
+ aDropTargetAL[ 1 ] = makeAny( (sal_Size)(pEnvData->aShellWindow) );
+ aDropTargetAL[ 2 ] = makeAny( vcl::createBmpConverter() );
+#endif
+ if( aDragSourceSN.getLength() )
+ mpWindowImpl->mpFrameData->mxDragSource = Reference< XDragSource > ( xFactory->createInstanceWithArguments( aDragSourceSN, aDragSourceAL ), UNO_QUERY );
+
+ if( aDropTargetSN.getLength() )
+ mpWindowImpl->mpFrameData->mxDropTarget = Reference< XDropTarget > ( xFactory->createInstanceWithArguments( aDropTargetSN, aDropTargetAL ), UNO_QUERY );
+ }
+ }
+ }
+
+ // createInstance can throw any exception
+ catch( Exception exc )
+ {
+ // release all instances
+ mpWindowImpl->mpFrameData->mxDropTarget.clear();
+ mpWindowImpl->mpFrameData->mxDragSource.clear();
+ }
+ }
+
+ return mpWindowImpl->mpFrameData->mxDragSource;
+ }
+
+ return Reference< XDragSource > ();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GetDragSourceDropTarget(Reference< XDragSource >& xDragSource, Reference< XDropTarget > &xDropTarget )
+// only for RVP transmission
+{
+ if( mpWindowImpl->mpFrameData )
+ {
+ // initialization is done in GetDragSource
+ xDragSource = GetDragSource();
+ xDropTarget = mpWindowImpl->mpFrameData->mxDropTarget;
+ }
+ else
+ {
+ xDragSource.clear();
+ xDropTarget.clear();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Reference< XDragGestureRecognizer > Window::GetDragGestureRecognizer()
+{
+ return Reference< XDragGestureRecognizer > ( GetDropTarget(), UNO_QUERY );
+}
+
+// -----------------------------------------------------------------------
+
+Reference< XClipboard > Window::GetClipboard()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( mpWindowImpl->mpFrameData )
+ {
+ if( ! mpWindowImpl->mpFrameData->mxClipboard.is() )
+ {
+ try
+ {
+ Reference< XMultiServiceFactory > xFactory( vcl::unohelper::GetMultiServiceFactory() );
+
+ if( xFactory.is() )
+ {
+ mpWindowImpl->mpFrameData->mxClipboard = Reference< XClipboard >( xFactory->createInstance( OUString::createFromAscii( "com.sun.star.datatransfer.clipboard.SystemClipboardExt" ) ), UNO_QUERY );
+
+ if( !mpWindowImpl->mpFrameData->mxClipboard.is() )
+ mpWindowImpl->mpFrameData->mxClipboard = Reference< XClipboard >( xFactory->createInstance( OUString::createFromAscii( "com.sun.star.datatransfer.clipboard.SystemClipboard" ) ), UNO_QUERY );
+
+#if defined(UNX) && !defined(QUARTZ) // unix clipboard needs to be initialized
+ if( mpWindowImpl->mpFrameData->mxClipboard.is() )
+ {
+ Reference< XInitialization > xInit = Reference< XInitialization >( mpWindowImpl->mpFrameData->mxClipboard, UNO_QUERY );
+
+ if( xInit.is() )
+ {
+ Sequence< Any > aArgumentList( 3 );
+ aArgumentList[ 0 ] = makeAny( Application::GetDisplayConnection() );
+ aArgumentList[ 1 ] = makeAny( OUString::createFromAscii( "CLIPBOARD" ) );
+ aArgumentList[ 2 ] = makeAny( vcl::createBmpConverter() );
+
+ xInit->initialize( aArgumentList );
+ }
+ }
+#endif
+ }
+ }
+
+ // createInstance can throw any exception
+ catch( Exception exc )
+ {
+ // release all instances
+ mpWindowImpl->mpFrameData->mxClipboard.clear();
+ }
+ }
+
+ return mpWindowImpl->mpFrameData->mxClipboard;
+ }
+
+ return static_cast < XClipboard * > (0);
+}
+
+// -----------------------------------------------------------------------
+
+Reference< XClipboard > Window::GetPrimarySelection()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( mpWindowImpl->mpFrameData )
+ {
+ if( ! mpWindowImpl->mpFrameData->mxSelection.is() )
+ {
+ try
+ {
+ Reference< XMultiServiceFactory > xFactory( vcl::unohelper::GetMultiServiceFactory() );
+
+ if( xFactory.is() )
+ {
+#if defined(UNX) && !defined(QUARTZ)
+ Sequence< Any > aArgumentList( 3 );
+ aArgumentList[ 0 ] = makeAny( Application::GetDisplayConnection() );
+ aArgumentList[ 1 ] = makeAny( OUString::createFromAscii( "PRIMARY" ) );
+ aArgumentList[ 2 ] = makeAny( vcl::createBmpConverter() );
+
+ mpWindowImpl->mpFrameData->mxSelection = Reference< XClipboard >( xFactory->createInstanceWithArguments(
+ OUString::createFromAscii( "com.sun.star.datatransfer.clipboard.SystemClipboard" ), aArgumentList ), UNO_QUERY );
+# else
+ static Reference< XClipboard > s_xSelection;
+
+ if ( !s_xSelection.is() )
+ s_xSelection = Reference< XClipboard >( xFactory->createInstance( OUString::createFromAscii( "com.sun.star.datatransfer.clipboard.GenericClipboardExt" ) ), UNO_QUERY );
+
+ if ( !s_xSelection.is() )
+ s_xSelection = Reference< XClipboard >( xFactory->createInstance( OUString::createFromAscii( "com.sun.star.datatransfer.clipboard.GenericClipboard" ) ), UNO_QUERY );
+
+ mpWindowImpl->mpFrameData->mxSelection = s_xSelection;
+# endif
+ }
+ }
+
+ // createInstance can throw any exception
+ catch( Exception exc )
+ {
+ // release all instances
+ mpWindowImpl->mpFrameData->mxSelection.clear();
+ }
+ }
+
+ return mpWindowImpl->mpFrameData->mxSelection;
+ }
+
+ return static_cast < XClipboard * > (0);
+}
+
+// -----------------------------------------------------------------------
+// Accessibility
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Window::GetAccessible( BOOL bCreate )
+{
+ // do not optimize hierarchy for the top level border win (ie, when there is no parent)
+ /* // do not optimize accessible hierarchy at all to better reflect real VCL hierarchy
+ if ( GetParent() && ( GetType() == WINDOW_BORDERWINDOW ) && ( GetChildCount() == 1 ) )
+ //if( !ImplIsAccessibleCandidate() )
+ {
+ Window* pChild = GetAccessibleChildWindow( 0 );
+ if ( pChild )
+ return pChild->GetAccessible();
+ }
+ */
+ if ( !mpWindowImpl->mxAccessible.is() && bCreate )
+ mpWindowImpl->mxAccessible = CreateAccessible();
+
+ return mpWindowImpl->mxAccessible;
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Window::CreateAccessible()
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc( GetComponentInterface( TRUE ), ::com::sun::star::uno::UNO_QUERY );
+ return xAcc;
+}
+
+void Window::SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > x )
+{
+ mpWindowImpl->mxAccessible = x;
+}
+
+// skip all border windows that are no top level frames
+BOOL Window::ImplIsAccessibleCandidate() const
+{
+ if( !mpWindowImpl->mbBorderWin )
+ return TRUE;
+ else
+ // #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menues!) are closeable
+ if( mpWindowImpl->mbFrame && mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+BOOL Window::ImplIsAccessibleNativeFrame() const
+{
+ if( mpWindowImpl->mbFrame )
+ // #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menues!) are closeable
+ if( (mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
+ return TRUE;
+ else
+ return FALSE;
+ else
+ return FALSE;
+}
+
+USHORT Window::ImplGetAccessibleCandidateChildWindowCount( USHORT nFirstWindowType ) const
+{
+ USHORT nChildren = 0;
+ Window* pChild = GetWindow( nFirstWindowType );
+ while ( pChild )
+ {
+ if( pChild->ImplIsAccessibleCandidate() )
+ nChildren++;
+ else
+ nChildren = sal::static_int_cast<USHORT>(nChildren + pChild->ImplGetAccessibleCandidateChildWindowCount( WINDOW_FIRSTCHILD ));
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ return nChildren;
+}
+
+Window* Window::ImplGetAccessibleCandidateChild( USHORT nChild, USHORT& rChildCount, USHORT nFirstWindowType, BOOL bTopLevel ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( bTopLevel )
+ rChildCount = 0;
+
+ Window* pChild = GetWindow( nFirstWindowType );
+ while ( pChild )
+ {
+ Window *pTmpChild = pChild;
+
+ if( !pChild->ImplIsAccessibleCandidate() )
+ pTmpChild = pChild->ImplGetAccessibleCandidateChild( nChild, rChildCount, WINDOW_FIRSTCHILD, FALSE );
+
+ if ( nChild == rChildCount )
+ return pTmpChild;
+ pChild = pChild->mpWindowImpl->mpNext;
+ rChildCount++;
+ }
+
+ return NULL;
+}
+
+/*
+Window* Window::GetAccessibleParentWindow() const
+{
+ Window* pParent = GetParent();
+ while ( pParent )
+ if( pParent->ImplIsAccessibleCandidate() )
+ break;
+ else
+ pParent = pParent->GetParent();
+ return pParent;
+}
+*/
+
+Window* Window::GetAccessibleParentWindow() const
+{
+ if ( ImplIsAccessibleNativeFrame() )
+ return NULL;
+
+ Window* pParent = mpWindowImpl->mpParent;
+ if( GetType() == WINDOW_MENUBARWINDOW )
+ {
+ // report the menubar as a child of THE workwindow
+ Window *pWorkWin = GetParent()->mpWindowImpl->mpFirstChild;
+ while( pWorkWin && (pWorkWin == this) )
+ pWorkWin = pWorkWin->mpWindowImpl->mpNext;
+ pParent = pWorkWin;
+ }
+ // If this a floating window which has a native boarder window, this one should be reported as
+ // accessible parent
+ else if( GetType() == WINDOW_FLOATINGWINDOW &&
+ mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame)
+ {
+ pParent = mpWindowImpl->mpBorderWindow;
+ }
+ else if( pParent && !pParent->ImplIsAccessibleCandidate() )
+ {
+ pParent = pParent->mpWindowImpl->mpParent;
+ }
+ return pParent;
+}
+
+/*
+USHORT Window::GetAccessibleChildWindowCount()
+{
+ USHORT nChildren = ImplGetAccessibleCandidateChildWindowCount( WINDOW_FIRSTCHILD );
+
+ // Search also for SystemWindows.
+ Window* pOverlap = GetWindow( WINDOW_OVERLAP );
+ nChildren += pOverlap->ImplGetAccessibleCandidateChildWindowCount( WINDOW_FIRSTOVERLAP );
+
+ return nChildren;
+}
+*/
+
+USHORT Window::GetAccessibleChildWindowCount()
+{
+ USHORT nChildren = 0;
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while( pChild )
+ {
+ if( pChild->IsVisible() )
+ nChildren++;
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+
+ // #107176# ignore overlapwindows
+ // this only affects non-system floating windows
+ // which are either not accessible (like the HelpAgent) or should be changed to system windows anyway
+ /*
+ if( ImplIsOverlapWindow() )
+ {
+ Window* pOverlap = GetWindow( WINDOW_FIRSTOVERLAP );
+ while ( pOverlap )
+ {
+ if( pOverlap->IsVisible() )
+ nChildren++;
+ pOverlap = pOverlap->GetWindow( WINDOW_NEXT );
+ }
+ }
+ */
+
+ // report the menubarwindow as a child of THE workwindow
+ if( GetType() == WINDOW_BORDERWINDOW )
+ {
+ if( ((ImplBorderWindow *) this)->mpMenuBarWindow &&
+ ((ImplBorderWindow *) this)->mpMenuBarWindow->IsVisible()
+ )
+ --nChildren;
+ }
+ else if( GetType() == WINDOW_WORKWINDOW )
+ {
+ if( ((WorkWindow *) this)->GetMenuBar() &&
+ ((WorkWindow *) this)->GetMenuBar()->GetWindow() &&
+ ((WorkWindow *) this)->GetMenuBar()->GetWindow()->IsVisible()
+ )
+ ++nChildren;
+ }
+
+ return nChildren;
+}
+
+/*
+Window* Window::GetAccessibleChildWindow( USHORT n )
+{
+ USHORT nChildCount; // will be set in ImplGetAccessibleCandidateChild(...)
+ Window* pChild = ImplGetAccessibleCandidateChild( n, nChildCount, WINDOW_FIRSTCHILD, TRUE );
+ if ( !pChild && ( n >= nChildCount ) )
+ {
+ Window* pOverlap = GetWindow( WINDOW_OVERLAP );
+ pChild = pOverlap->ImplGetAccessibleCandidateChild( n, nChildCount, WINDOW_FIRSTOVERLAP, FALSE );
+ }
+
+ return pChild;
+}
+*/
+
+Window* Window::GetAccessibleChildWindow( USHORT n )
+{
+ // report the menubarwindow as a the first child of THE workwindow
+ if( GetType() == WINDOW_WORKWINDOW && ((WorkWindow *) this)->GetMenuBar() )
+ {
+ if( n == 0 )
+ {
+ MenuBar *pMenuBar = ((WorkWindow *) this)->GetMenuBar();
+ if( pMenuBar->GetWindow() && pMenuBar->GetWindow()->IsVisible() )
+ return pMenuBar->GetWindow();
+ }
+ else
+ --n;
+ }
+
+ // transform n to child number including invisible children
+ USHORT nChildren = n;
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while( pChild )
+ {
+ if( pChild->IsVisible() )
+ {
+ if( ! nChildren )
+ break;
+ nChildren--;
+ }
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+
+ if( GetType() == WINDOW_BORDERWINDOW && pChild && pChild->GetType() == WINDOW_MENUBARWINDOW )
+ {
+ do pChild = pChild->mpWindowImpl->mpNext; while( pChild && ! pChild->IsVisible() );
+ DBG_ASSERT( pChild, "GetAccessibleChildWindow(): wrong index in border window");
+ }
+ if ( !pChild )
+ {
+ // #107176# ignore overlapwindows
+ /*
+ if( ImplIsOverlapWindow() )
+ {
+ Window* pOverlap = GetWindow( WINDOW_FIRSTOVERLAP );
+ while ( !pChild && pOverlap )
+ {
+ if ( !nChildren && pOverlap->IsVisible() )
+ {
+ pChild = pOverlap;
+ break;
+ }
+ pOverlap = pOverlap->GetWindow( WINDOW_NEXT );
+ if( pOverlap && pOverlap->IsVisible() )
+ nChildren--;
+ }
+ }
+ */
+
+ }
+ if ( pChild && ( pChild->GetType() == WINDOW_BORDERWINDOW ) && ( pChild->GetChildCount() == 1 ) )
+ {
+ pChild = pChild->GetChild( 0 );
+ }
+ return pChild;
+}
+
+
+void Window::SetAccessibleRole( USHORT nRole )
+{
+ if ( !mpWindowImpl->mpAccessibleInfos )
+ mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
+
+ DBG_ASSERT( mpWindowImpl->mpAccessibleInfos->nAccessibleRole == 0xFFFF, "AccessibleRole already set!" );
+ mpWindowImpl->mpAccessibleInfos->nAccessibleRole = nRole;
+}
+
+USHORT Window::GetAccessibleRole() const
+{
+ using namespace ::com::sun::star;
+
+ USHORT nRole = mpWindowImpl->mpAccessibleInfos ? mpWindowImpl->mpAccessibleInfos->nAccessibleRole : 0xFFFF;
+ if ( nRole == 0xFFFF )
+ {
+ switch ( GetType() )
+ {
+ case WINDOW_MESSBOX: // MT: Would be nice to have special roles!
+ case WINDOW_INFOBOX:
+ case WINDOW_WARNINGBOX:
+ case WINDOW_ERRORBOX:
+ case WINDOW_QUERYBOX: nRole = accessibility::AccessibleRole::ALERT; break;
+
+ case WINDOW_MODELESSDIALOG:
+ case WINDOW_MODALDIALOG:
+ case WINDOW_SYSTEMDIALOG:
+ case WINDOW_PRINTERSETUPDIALOG:
+ case WINDOW_PRINTDIALOG:
+ case WINDOW_TABDIALOG:
+ case WINDOW_BUTTONDIALOG:
+ case WINDOW_DIALOG: nRole = accessibility::AccessibleRole::DIALOG; break;
+
+ case WINDOW_PUSHBUTTON:
+ case WINDOW_OKBUTTON:
+ case WINDOW_CANCELBUTTON:
+ case WINDOW_HELPBUTTON:
+ case WINDOW_IMAGEBUTTON:
+ case WINDOW_MENUBUTTON:
+ case WINDOW_MOREBUTTON:
+ case WINDOW_SPINBUTTON:
+ case WINDOW_BUTTON: nRole = accessibility::AccessibleRole::PUSH_BUTTON; break;
+
+ case WINDOW_PATHDIALOG: nRole = accessibility::AccessibleRole::DIRECTORY_PANE; break;
+ case WINDOW_FILEDIALOG: nRole = accessibility::AccessibleRole::FILE_CHOOSER; break;
+ case WINDOW_COLORDIALOG: nRole = accessibility::AccessibleRole::COLOR_CHOOSER; break;
+ case WINDOW_FONTDIALOG: nRole = accessibility::AccessibleRole::FONT_CHOOSER; break;
+
+ case WINDOW_IMAGERADIOBUTTON:
+ case WINDOW_RADIOBUTTON: nRole = accessibility::AccessibleRole::RADIO_BUTTON; break;
+ case WINDOW_TRISTATEBOX:
+ case WINDOW_CHECKBOX: nRole = accessibility::AccessibleRole::CHECK_BOX; break;
+
+ case WINDOW_MULTILINEEDIT: nRole = accessibility::AccessibleRole::SCROLL_PANE; break;
+
+ case WINDOW_PATTERNFIELD:
+ case WINDOW_NUMERICFIELD:
+ case WINDOW_METRICFIELD:
+ case WINDOW_CURRENCYFIELD:
+ case WINDOW_LONGCURRENCYFIELD:
+ case WINDOW_EDIT: nRole = ( GetStyle() & WB_PASSWORD ) ? (accessibility::AccessibleRole::PASSWORD_TEXT) : (accessibility::AccessibleRole::TEXT); break;
+
+ case WINDOW_PATTERNBOX:
+ case WINDOW_NUMERICBOX:
+ case WINDOW_METRICBOX:
+ case WINDOW_CURRENCYBOX:
+ case WINDOW_LONGCURRENCYBOX:
+ case WINDOW_COMBOBOX: nRole = accessibility::AccessibleRole::COMBO_BOX; break;
+
+ case WINDOW_LISTBOX:
+ case WINDOW_MULTILISTBOX: nRole = accessibility::AccessibleRole::LIST; break;
+
+ case WINDOW_TREELISTBOX: nRole = accessibility::AccessibleRole::TREE; break;
+
+ case WINDOW_FIXEDTEXT: nRole = accessibility::AccessibleRole::LABEL; break;
+ case WINDOW_FIXEDBORDER:
+ case WINDOW_FIXEDLINE: nRole = accessibility::AccessibleRole::SEPARATOR; break;
+ case WINDOW_FIXEDBITMAP:
+ case WINDOW_FIXEDIMAGE: nRole = accessibility::AccessibleRole::ICON; break;
+ case WINDOW_GROUPBOX: nRole = accessibility::AccessibleRole::GROUP_BOX; break;
+ case WINDOW_SCROLLBAR: nRole = accessibility::AccessibleRole::SCROLL_BAR; break;
+
+ case WINDOW_SLIDER:
+ case WINDOW_SPLITTER:
+ case WINDOW_SPLITWINDOW: nRole = accessibility::AccessibleRole::SPLIT_PANE; break;
+
+ case WINDOW_DATEBOX:
+ case WINDOW_TIMEBOX:
+ case WINDOW_DATEFIELD:
+ case WINDOW_TIMEFIELD: nRole = accessibility::AccessibleRole::DATE_EDITOR; break;
+
+ case WINDOW_SPINFIELD: nRole = accessibility::AccessibleRole::SPIN_BOX; break;
+
+ case WINDOW_TOOLBOX: nRole = accessibility::AccessibleRole::TOOL_BAR; break;
+ case WINDOW_STATUSBAR: nRole = accessibility::AccessibleRole::STATUS_BAR; break;
+
+ case WINDOW_TABPAGE: nRole = accessibility::AccessibleRole::PANEL; break;
+ case WINDOW_TABCONTROL: nRole = accessibility::AccessibleRole::PAGE_TAB_LIST; break;
+
+ case WINDOW_DOCKINGWINDOW:
+ case WINDOW_SYSWINDOW: nRole = (mpWindowImpl->mbFrame) ? accessibility::AccessibleRole::FRAME :
+ accessibility::AccessibleRole::PANEL; break;
+
+ case WINDOW_FLOATINGWINDOW: nRole = ( mpWindowImpl->mbFrame ||
+ (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) ||
+ (GetStyle() & WB_OWNERDRAWDECORATION) ) ? accessibility::AccessibleRole::FRAME :
+ accessibility::AccessibleRole::WINDOW; break;
+
+ case WINDOW_WORKWINDOW: nRole = accessibility::AccessibleRole::ROOT_PANE; break;
+
+
+ case WINDOW_SCROLLBARBOX: nRole = accessibility::AccessibleRole::FILLER; break;
+
+ case WINDOW_HELPTEXTWINDOW: nRole = accessibility::AccessibleRole::TOOL_TIP; break;
+
+ case WINDOW_WINDOW:
+ case WINDOW_CONTROL:
+ case WINDOW_BORDERWINDOW:
+ case WINDOW_SYSTEMCHILDWINDOW:
+ default:
+ if (ImplIsAccessibleNativeFrame() )
+ nRole = accessibility::AccessibleRole::FRAME;
+ else if( IsScrollable() )
+ nRole = accessibility::AccessibleRole::SCROLL_PANE;
+ else if( ((Window*)this)->ImplGetWindow()->IsMenuFloatingWindow() )
+ nRole = accessibility::AccessibleRole::WINDOW; // #106002#, contextmenues are windows (i.e. toplevel)
+ else
+ // #104051# WINDOW seems to be a bad default role, use LAYEREDPANE instead
+ // a WINDOW is interpreted as a top-level window, which is typically not the case
+ //nRole = accessibility::AccessibleRole::WINDOW;
+ nRole = accessibility::AccessibleRole::PANEL;
+ }
+ }
+ return nRole;
+}
+
+void Window::SetAccessibleName( const String& rName )
+{
+ if ( !mpWindowImpl->mpAccessibleInfos )
+ mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
+
+ DBG_ASSERT( !mpWindowImpl->mpAccessibleInfos->pAccessibleName, "AccessibleName already set!" );
+ delete mpWindowImpl->mpAccessibleInfos->pAccessibleName;
+ mpWindowImpl->mpAccessibleInfos->pAccessibleName = new String( rName );
+}
+
+String Window::GetAccessibleName() const
+{
+ String aAccessibleName;
+ if ( mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleName )
+ {
+ aAccessibleName = *mpWindowImpl->mpAccessibleInfos->pAccessibleName;
+ }
+ else
+ {
+ switch ( GetType() )
+ {
+// case WINDOW_IMAGERADIOBUTTON:
+// case WINDOW_RADIOBUTTON:
+// case WINDOW_TRISTATEBOX:
+// case WINDOW_CHECKBOX:
+
+ case WINDOW_MULTILINEEDIT:
+ case WINDOW_PATTERNFIELD:
+ case WINDOW_NUMERICFIELD:
+ case WINDOW_METRICFIELD:
+ case WINDOW_CURRENCYFIELD:
+ case WINDOW_LONGCURRENCYFIELD:
+ case WINDOW_EDIT:
+
+ case WINDOW_DATEBOX:
+ case WINDOW_TIMEBOX:
+ case WINDOW_CURRENCYBOX:
+ case WINDOW_LONGCURRENCYBOX:
+ case WINDOW_DATEFIELD:
+ case WINDOW_TIMEFIELD:
+ case WINDOW_SPINFIELD:
+
+ case WINDOW_COMBOBOX:
+ case WINDOW_LISTBOX:
+ case WINDOW_MULTILISTBOX:
+ case WINDOW_TREELISTBOX:
+
+ {
+ Window *pLabel = GetLabeledBy();
+ if ( pLabel && pLabel != this )
+ aAccessibleName = pLabel->GetText();
+ }
+ break;
+
+ case WINDOW_IMAGEBUTTON:
+ case WINDOW_PUSHBUTTON:
+ aAccessibleName = GetText();
+ if ( !aAccessibleName.Len() )
+ {
+ aAccessibleName = GetQuickHelpText();
+ if ( !aAccessibleName.Len() )
+ aAccessibleName = GetHelpText();
+ }
+ break;
+
+ default:
+ aAccessibleName = GetText();
+ break;
+ }
+
+ aAccessibleName = GetNonMnemonicString( aAccessibleName );
+ }
+
+ return aAccessibleName;
+}
+
+void Window::SetAccessibleDescription( const String& rDescription )
+{
+ if ( ! mpWindowImpl->mpAccessibleInfos )
+ mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
+
+ DBG_ASSERT( !mpWindowImpl->mpAccessibleInfos->pAccessibleDescription, "AccessibleDescription already set!" );
+ delete mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
+ mpWindowImpl->mpAccessibleInfos->pAccessibleDescription = new String( rDescription );
+}
+
+String Window::GetAccessibleDescription() const
+{
+ String aAccessibleDescription;
+ if ( mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription )
+ {
+ aAccessibleDescription = *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
+ }
+ else
+ {
+ // Special code for help text windows. ZT asks the border window for the
+ // description so we have to forward this request to our inner window.
+ const Window* pWin = ((Window *)this)->ImplGetWindow();
+ if ( pWin->GetType() == WINDOW_HELPTEXTWINDOW )
+ aAccessibleDescription = pWin->GetHelpText();
+ else
+ aAccessibleDescription = GetHelpText();
+ }
+
+ return aAccessibleDescription;
+}
+
+BOOL Window::IsAccessibilityEventsSuppressed( BOOL bTraverseParentPath )
+{
+ if( !bTraverseParentPath )
+ return mpWindowImpl->mbSuppressAccessibilityEvents;
+ else
+ {
+ Window *pParent = this;
+ while ( pParent && pParent->mpWindowImpl)
+ {
+ if( pParent->mpWindowImpl->mbSuppressAccessibilityEvents )
+ return TRUE;
+ else
+ pParent = pParent->mpWindowImpl->mpParent; // do not use GetParent() to find borderwindows that are frames
+ }
+ return FALSE;
+ }
+}
+
+void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const Rectangle& rRect )
+{
+ if( ! mpOutDevData )
+ ImplInitOutDevData();
+ mpOutDevData->mpRecordLayout = pLayout;
+ mpOutDevData->maRecordRect = rRect;
+ Paint( rRect );
+ mpOutDevData->mpRecordLayout = NULL;
+}
+
+// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
+
+
+// returns background color used in this control
+// false: could not determine color
+BOOL Window::ImplGetCurrentBackgroundColor( Color& rCol )
+{
+ BOOL bRet = TRUE;
+
+ switch ( GetType() )
+ {
+ // peform special handling here
+ case WINDOW_PUSHBUTTON:
+ case WINDOW_OKBUTTON:
+ case WINDOW_CANCELBUTTON:
+ // etc.
+ default:
+ if( IsControlBackground() )
+ rCol = GetControlBackground();
+ else if( IsBackground() )
+ {
+ Wallpaper aWall = GetBackground();
+ if( !aWall.IsGradient() && !aWall.IsBitmap() )
+ rCol = aWall.GetColor();
+ else
+ bRet = FALSE;
+ }
+ else
+ rCol = GetSettings().GetStyleSettings().GetFaceColor();
+ break;
+ }
+ return bRet;
+}
+
+void Window::DrawSelectionBackground( const Rectangle& rRect, USHORT highlight, BOOL bChecked, BOOL bDrawBorder, BOOL bDrawExtBorderOnly )
+{
+ DrawSelectionBackground( rRect, highlight, bChecked, bDrawBorder, bDrawExtBorderOnly, 0, NULL, NULL );
+}
+
+void Window::DrawSelectionBackground( const Rectangle& rRect, USHORT highlight, BOOL bChecked, BOOL bDrawBorder, BOOL bDrawExtBorderOnly, Color* pSelectionTextColor )
+{
+ DrawSelectionBackground( rRect, highlight, bChecked, bDrawBorder, bDrawExtBorderOnly, 0, pSelectionTextColor, NULL );
+}
+
+void Window::DrawSelectionBackground( const Rectangle& rRect,
+ USHORT highlight,
+ BOOL bChecked,
+ BOOL bDrawBorder,
+ BOOL bDrawExtBorderOnly,
+ long nCornerRadius,
+ Color* pSelectionTextColor,
+ Color* pPaintColor
+ )
+{
+ if( rRect.IsEmpty() )
+ return;
+
+ bool bRoundEdges = nCornerRadius > 0;
+
+ const StyleSettings& rStyles = GetSettings().GetStyleSettings();
+
+
+ // colors used for item highlighting
+ Color aSelectionBorderCol( pPaintColor ? *pPaintColor : rStyles.GetHighlightColor() );
+ Color aSelectionFillCol( aSelectionBorderCol );
+
+ BOOL bDark = rStyles.GetFaceColor().IsDark();
+ BOOL bBright = ( rStyles.GetFaceColor() == Color( COL_WHITE ) );
+
+ int c1 = aSelectionBorderCol.GetLuminance();
+ int c2 = GetDisplayBackground().GetColor().GetLuminance();
+
+ if( !bDark && !bBright && abs( c2-c1 ) < (pPaintColor ? 40 : 75) )
+ {
+ // constrast too low
+ USHORT h,s,b;
+ aSelectionFillCol.RGBtoHSB( h, s, b );
+ if( b > 50 ) b -= 40;
+ else b += 40;
+ aSelectionFillCol.SetColor( Color::HSBtoRGB( h, s, b ) );
+ aSelectionBorderCol = aSelectionFillCol;
+ }
+
+ if( bRoundEdges )
+ {
+ if( aSelectionBorderCol.IsDark() )
+ aSelectionBorderCol.IncreaseLuminance( 128 );
+ else
+ aSelectionBorderCol.DecreaseLuminance( 128 );
+ }
+
+ Rectangle aRect( rRect );
+ if( bDrawExtBorderOnly )
+ {
+ aRect.nLeft -= 1;
+ aRect.nTop -= 1;
+ aRect.nRight += 1;
+ aRect.nBottom += 1;
+ }
+ Color oldFillCol = GetFillColor();
+ Color oldLineCol = GetLineColor();
+
+ if( bDrawBorder )
+ SetLineColor( bDark ? Color(COL_WHITE) : ( bBright ? Color(COL_BLACK) : aSelectionBorderCol ) );
+ else
+ SetLineColor();
+
+ USHORT nPercent = 0;
+ if( !highlight )
+ {
+ if( bDark )
+ aSelectionFillCol = COL_BLACK;
+ else
+ nPercent = bRoundEdges ? 90 : 80; // just checked (light)
+ }
+ else
+ {
+ if( bChecked && highlight == 2 )
+ {
+ if( bDark )
+ aSelectionFillCol = COL_LIGHTGRAY;
+ else if ( bBright )
+ {
+ aSelectionFillCol = COL_BLACK;
+ SetLineColor( COL_BLACK );
+ nPercent = 0;
+ }
+ else
+ nPercent = bRoundEdges ? 50 : 20; // selected, pressed or checked ( very dark )
+ }
+ else if( bChecked || highlight == 1 )
+ {
+ if( bDark )
+ aSelectionFillCol = COL_GRAY;
+ else if ( bBright )
+ {
+ aSelectionFillCol = COL_BLACK;
+ SetLineColor( COL_BLACK );
+ nPercent = 0;
+ }
+ else
+ nPercent = bRoundEdges ? 70 : 35; // selected, pressed or checked ( very dark )
+ }
+ else
+ {
+ if( bDark )
+ aSelectionFillCol = COL_LIGHTGRAY;
+ else if ( bBright )
+ {
+ aSelectionFillCol = COL_BLACK;
+ SetLineColor( COL_BLACK );
+ if( highlight == 3 )
+ nPercent = 80;
+ else
+ nPercent = 0;
+ }
+ else
+ nPercent = bRoundEdges ? 80 : 70; // selected ( dark )
+ }
+ }
+
+ if( bDark && bDrawExtBorderOnly )
+ {
+ SetFillColor();
+ if( pSelectionTextColor )
+ *pSelectionTextColor = rStyles.GetHighlightTextColor();
+ }
+ else
+ {
+ SetFillColor( aSelectionFillCol );
+ if( pSelectionTextColor )
+ {
+ Color aTextColor = IsControlBackground() ? GetControlForeground() : rStyles.GetButtonTextColor();
+ Color aHLTextColor = rStyles.GetHighlightTextColor();
+ int nTextDiff = abs(aSelectionFillCol.GetLuminance() - aTextColor.GetLuminance());
+ int nHLDiff = abs(aSelectionFillCol.GetLuminance() - aHLTextColor.GetLuminance());
+ *pSelectionTextColor = (nHLDiff >= nTextDiff) ? aHLTextColor : aTextColor;
+ }
+ }
+
+
+ if( bDark )
+ {
+ DrawRect( aRect );
+ }
+ else
+ {
+ if( bRoundEdges )
+ {
+ Polygon aPoly( aRect, nCornerRadius, nCornerRadius );
+ PolyPolygon aPolyPoly( aPoly );
+ DrawTransparent( aPolyPoly, nPercent );
+ }
+ else
+ {
+ Polygon aPoly( aRect );
+ PolyPolygon aPolyPoly( aPoly );
+ DrawTransparent( aPolyPoly, nPercent );
+ }
+ }
+
+ SetFillColor( oldFillCol );
+ SetLineColor( oldLineCol );
+}
+
+/*
+void Window::DbgAssertNoEventListeners()
+{
+ VclWindowEvent aEvent( this, 0, NULL );
+ DBG_ASSERT( mpWindowImpl->maEventListeners.empty(), "Eventlistener: Who is still listening???" )
+ if ( !mpWindowImpl->maEventListeners.empty() )
+ mpWindowImpl->maEventListeners.Call( &aEvent );
+
+ DBG_ASSERT( mpWindowImpl->maChildEventListeners.empty(), "ChildEventlistener: Who is still listening???" )
+ if ( !mpWindowImpl->maChildEventListeners.empty() )
+ mpWindowImpl->maChildEventListeners.Call( &aEvent );
+}
+*/
+
+// controls should return the window that gets the
+// focus by default, so keyevents can be sent to that window directly
+Window* Window::GetPreferredKeyInputWindow()
+{
+ return this;
+}
+
+
+BOOL Window::IsScrollable() const
+{
+ // check for scrollbars
+ Window *pChild = mpWindowImpl->mpFirstChild;
+ while( pChild )
+ {
+ if( pChild->GetType() == WINDOW_SCROLLBAR )
+ return true;
+ else
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ return false;
+}
+
+BOOL Window::IsTopWindow() const
+{
+ if ( mpWindowImpl->mbInDtor )
+ return FALSE;
+
+ // topwindows must be frames or they must have a borderwindow which is a frame
+ if( !mpWindowImpl->mbFrame && (!mpWindowImpl->mpBorderWindow || (mpWindowImpl->mpBorderWindow && !mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) ) )
+ return FALSE;
+
+ ImplGetWinData();
+ if( mpWindowImpl->mpWinData->mnIsTopWindow == (USHORT)~0) // still uninitialized
+ {
+ // #113722#, cache result of expensive queryInterface call
+ Window *pThisWin = (Window*)this;
+ Reference< XTopWindow > xTopWindow( pThisWin->GetComponentInterface(), UNO_QUERY );
+ pThisWin->mpWindowImpl->mpWinData->mnIsTopWindow = xTopWindow.is() ? 1 : 0;
+ }
+ return mpWindowImpl->mpWinData->mnIsTopWindow == 1 ? TRUE : FALSE;
+}
+
+void Window::ImplMirrorFramePos( Point &pt ) const
+{
+ pt.X() = mpWindowImpl->mpFrame->maGeometry.nWidth-1-pt.X();
+}
+
+// frame based modal counter (dialogs are not modal to the whole application anymore)
+BOOL Window::IsInModalMode() const
+{
+ return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
+}
+void Window::ImplIncModalCount()
+{
+ Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
+ Window* pParent = pFrameWindow;
+ while( pFrameWindow )
+ {
+ pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++;
+ while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
+ {
+ pParent = pParent->GetParent();
+ }
+ pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow : NULL;
+ }
+}
+void Window::ImplDecModalCount()
+{
+ Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
+ Window* pParent = pFrameWindow;
+ while( pFrameWindow )
+ {
+ pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--;
+ while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
+ {
+ pParent = pParent->GetParent();
+ }
+ pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow : NULL;
+ }
+}
+BOOL Window::ImplIsInTaskPaneList()
+{
+ return mpWindowImpl->mbIsInTaskPaneList;
+}
+void Window::ImplIsInTaskPaneList( BOOL mbIsInTaskList )
+{
+ mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList;
+}
+
+void Window::ImplNotifyIconifiedState( BOOL bIconified )
+{
+ mpWindowImpl->mpFrameWindow->ImplCallEventListeners( bIconified ? VCLEVENT_WINDOW_MINIMIZE : VCLEVENT_WINDOW_NORMALIZE );
+ // #109206# notify client window as well to have toolkit topwindow listeners notified
+ if( mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow && mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow )
+ mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow->ImplCallEventListeners( bIconified ? VCLEVENT_WINDOW_MINIMIZE : VCLEVENT_WINDOW_NORMALIZE );
+}
+
+BOOL Window::HasActiveChildFrame()
+{
+ BOOL bRet = FALSE;
+ Window *pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
+ while( pFrameWin )
+ {
+ if( pFrameWin != mpWindowImpl->mpFrameWindow )
+ {
+ BOOL bDecorated = FALSE;
+ Window *pChildFrame = pFrameWin->ImplGetWindow();
+ // #i15285# unfortunately WB_MOVEABLE is the same as WB_TABSTOP which can
+ // be removed for ToolBoxes to influence the keyboard accessibility
+ // thus WB_MOVEABLE is no indicator for decoration anymore
+ // but FloatingWindows carry this information in their TitleType...
+ // TODO: avoid duplicate WinBits !!!
+ if( pChildFrame && pChildFrame->ImplIsFloatingWindow() )
+ bDecorated = ((FloatingWindow*) pChildFrame)->GetTitleType() != FLOATWIN_TITLE_NONE;
+ if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) )
+ if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() )
+ {
+ if( ImplIsChild( pChildFrame, TRUE ) )
+ {
+ bRet = TRUE;
+ break;
+ }
+ }
+ }
+ pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+ return bRet;
+}
+
+LanguageType Window::GetInputLanguage() const
+{
+ return mpWindowImpl->mpFrame->GetInputLanguage();
+}
+
+void Window::EnableNativeWidget( BOOL bEnable )
+{
+ static const char* pNoNWF = getenv( "SAL_NO_NWF" );
+ if( pNoNWF && *pNoNWF )
+ bEnable = FALSE;
+
+ if( bEnable != ImplGetWinData()->mbEnableNativeWidget )
+ {
+ ImplGetWinData()->mbEnableNativeWidget = bEnable;
+
+ // send datachanged event to allow for internal changes required for NWF
+ // like clipmode, transparency, etc.
+ DataChangedEvent aDCEvt( DATACHANGED_SETTINGS, &maSettings, SETTINGS_STYLE );
+ DataChanged( aDCEvt );
+
+ // sometimes the borderwindow is queried, so keep it in sync
+ if( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable;
+ }
+
+ // push down, useful for compound controls
+ Window *pChild = mpWindowImpl->mpFirstChild;
+ while( pChild )
+ {
+ pChild->EnableNativeWidget( bEnable );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+}
+
+BOOL Window::IsNativeWidgetEnabled() const
+{
+ return ImplGetWinData()->mbEnableNativeWidget;
+}
+
+#ifdef WNT // see #140456#
+#include <salframe.h>
+#endif
+
+Reference< rendering::XCanvas > Window::ImplGetCanvas( const Size& rFullscreenSize,
+ bool bFullscreen,
+ bool bSpriteCanvas ) const
+{
+ // try to retrieve hard reference from weak member
+ Reference< rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
+
+ // canvas still valid? Then we're done.
+ if( xCanvas.is() )
+ return xCanvas;
+
+ Sequence< Any > aArg(6);
+
+ // Feed any with operating system's window handle
+ // ==============================================
+
+ // common: first any is VCL pointer to window (for VCL canvas)
+ aArg[ 0 ] = makeAny( reinterpret_cast<sal_Int64>(this) );
+
+ // TODO(Q1): Make GetSystemData method virtual
+
+ // check whether we're a SysChild: have to fetch system data
+ // directly from SystemChildWindow, because the GetSystemData
+ // method is unfortunately not virtual
+ const SystemChildWindow* pSysChild = dynamic_cast< const SystemChildWindow* >( this );
+ if( pSysChild )
+ {
+ aArg[ 1 ] = pSysChild->GetSystemDataAny();
+ aArg[ 5 ] = pSysChild->GetSystemGfxDataAny();
+ }
+ else
+ {
+ aArg[ 1 ] = GetSystemDataAny();
+ aArg[ 5 ] = GetSystemGfxDataAny();
+ }
+
+ if( bFullscreen )
+ aArg[ 2 ] = makeAny( ::com::sun::star::awt::Rectangle( 0, 0,
+ rFullscreenSize.Width(),
+ rFullscreenSize.Height() ) );
+ else
+ aArg[ 2 ] = makeAny( ::com::sun::star::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ) );
+
+ aArg[ 3 ] = makeAny( mpWindowImpl->mbAlwaysOnTop ? sal_True : sal_False );
+ aArg[ 4 ] = makeAny( Reference< awt::XWindow >(
+ const_cast<Window*>(this)->GetComponentInterface(),
+ uno::UNO_QUERY ));
+
+ Reference< XMultiServiceFactory > xFactory = vcl::unohelper::GetMultiServiceFactory();
+
+ // Create canvas instance with window handle
+ // =========================================
+ if ( xFactory.is() )
+ {
+ static Reference<lang::XMultiServiceFactory> xCanvasFactory(
+ xFactory->createInstance(
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star."
+ "rendering.CanvasFactory") ) ), UNO_QUERY );
+ if(xCanvasFactory.is())
+ {
+#ifdef WNT
+ // see #140456# - if we're running on a multiscreen setup,
+ // request special, multi-screen safe sprite canvas
+ // implementation (not DX5 canvas, as it cannot cope with
+ // surfaces spanning multiple displays). Note: canvas
+ // (without sprite) stays the same)
+ const sal_uInt32 nDisplay = static_cast< WinSalFrame* >( mpWindowImpl->mpFrame )->mnDisplay;
+ if( (nDisplay >= Application::GetScreenCount()) )
+ {
+ xCanvas.set( xCanvasFactory->createInstanceWithArguments(
+ bSpriteCanvas ?
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.rendering.SpriteCanvas.MultiScreen" )) :
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.rendering.Canvas" )),
+ aArg ),
+ UNO_QUERY );
+
+ }
+ else
+ {
+#endif
+ xCanvas.set( xCanvasFactory->createInstanceWithArguments(
+ bSpriteCanvas ?
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.rendering.SpriteCanvas" )) :
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.rendering.Canvas" )),
+ aArg ),
+ UNO_QUERY );
+
+#ifdef WNT
+ }
+#endif
+
+ mpWindowImpl->mxCanvas = xCanvas;
+ }
+ }
+
+ // no factory??? Empty reference, then.
+ return xCanvas;
+}
+
+Reference< rendering::XCanvas > Window::GetCanvas() const
+{
+ return ImplGetCanvas( Size(), false, false );
+}
+
+Reference< rendering::XSpriteCanvas > Window::GetSpriteCanvas() const
+{
+ Reference< rendering::XSpriteCanvas > xSpriteCanvas(
+ ImplGetCanvas( Size(), false, true ), uno::UNO_QUERY );
+ return xSpriteCanvas;
+}
+
+Reference< ::com::sun::star::rendering::XSpriteCanvas > Window::GetFullscreenSpriteCanvas( const Size& rFullscreenSize ) const
+{
+ Reference< rendering::XSpriteCanvas > xSpriteCanvas(
+ ImplGetCanvas( rFullscreenSize, true, true ), uno::UNO_QUERY );
+ return xSpriteCanvas;
+}
+
+void Window::ImplPaintToDevice( OutputDevice* i_pTargetOutDev, const Point& i_rPos )
+{
+ BOOL bRVisible = mpWindowImpl->mbReallyVisible;
+ mpWindowImpl->mbReallyVisible = mpWindowImpl->mbVisible;
+ BOOL bDevOutput = mbDevOutput;
+ mbDevOutput = TRUE;
+
+ long nOldDPIX = ImplGetDPIX();
+ long nOldDPIY = ImplGetDPIY();
+ mnDPIX = i_pTargetOutDev->ImplGetDPIX();
+ mnDPIY = i_pTargetOutDev->ImplGetDPIY();
+ BOOL bOutput = IsOutputEnabled();
+ EnableOutput();
+
+ DBG_ASSERT( GetMapMode().GetMapUnit() == MAP_PIXEL, "MapMode must be PIXEL based" );
+ if ( GetMapMode().GetMapUnit() != MAP_PIXEL )
+ return;
+
+ // preserve graphicsstate
+ Push();
+ Region aClipRegion( GetClipRegion() );
+ SetClipRegion();
+
+ GDIMetaFile* pOldMtf = GetConnectMetaFile();
+ GDIMetaFile aMtf;
+ SetConnectMetaFile( &aMtf );
+
+ // put a push action to metafile
+ Push();
+ // copy graphics state to metafile
+ Font aCopyFont = GetFont();
+ if( nOldDPIX != mnDPIX || nOldDPIY != mnDPIY )
+ {
+ aCopyFont.SetHeight( aCopyFont.GetHeight() * mnDPIY / nOldDPIY );
+ aCopyFont.SetWidth( aCopyFont.GetWidth() * mnDPIX / nOldDPIX );
+ }
+ SetFont( aCopyFont );
+ SetTextColor( GetTextColor() );
+ if( IsLineColor() )
+ SetLineColor( GetLineColor() );
+ else
+ SetLineColor();
+ if( IsFillColor() )
+ SetFillColor( GetFillColor() );
+ else
+ SetFillColor();
+ if( IsTextLineColor() )
+ SetTextLineColor( GetTextLineColor() );
+ else
+ SetTextLineColor();
+ if( IsOverlineColor() )
+ SetOverlineColor( GetOverlineColor() );
+ else
+ SetOverlineColor();
+ if( IsTextFillColor() )
+ SetTextFillColor( GetTextFillColor() );
+ else
+ SetTextFillColor();
+ SetTextAlign( GetTextAlign() );
+ SetRasterOp( GetRasterOp() );
+ if( IsRefPoint() )
+ SetRefPoint( GetRefPoint() );
+ else
+ SetRefPoint();
+ SetLayoutMode( GetLayoutMode() );
+ SetDigitLanguage( GetDigitLanguage() );
+ Rectangle aPaintRect( Point( 0, 0 ), GetOutputSizePixel() );
+ aClipRegion.Intersect( aPaintRect );
+ SetClipRegion( aClipRegion );
+
+ // do the actual paint
+
+ // background
+ if( ! IsPaintTransparent() && IsBackground() && ! (GetParentClipMode() & PARENTCLIPMODE_NOCLIP ) )
+ Erase();
+ // foreground
+ Paint( aPaintRect );
+ // put a pop action to metafile
+ Pop();
+
+ SetConnectMetaFile( pOldMtf );
+ EnableOutput( bOutput );
+ mpWindowImpl->mbReallyVisible = bRVisible;
+
+ // paint metafile to VDev
+ VirtualDevice* pMaskedDevice = new VirtualDevice( *i_pTargetOutDev, 0, 0 );
+ pMaskedDevice->SetOutputSizePixel( GetOutputSizePixel() );
+ pMaskedDevice->EnableRTL( IsRTLEnabled() );
+ aMtf.WindStart();
+ aMtf.Play( pMaskedDevice );
+ BitmapEx aBmpEx( pMaskedDevice->GetBitmapEx( Point( 0, 0 ), pMaskedDevice->GetOutputSizePixel() ) );
+ i_pTargetOutDev->DrawBitmapEx( i_rPos, aBmpEx );
+ // get rid of virtual device now so they don't pile up during recursive calls
+ delete pMaskedDevice, pMaskedDevice = NULL;
+
+
+ for( Window* pChild = mpWindowImpl->mpFirstChild; pChild; pChild = pChild->mpWindowImpl->mpNext )
+ {
+ if( pChild->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame && pChild->IsVisible() )
+ {
+ long nDeltaX = pChild->mnOutOffX - mnOutOffX;
+ if( ImplHasMirroredGraphics() )
+ nDeltaX = mnOutWidth - nDeltaX - pChild->mnOutWidth;
+ long nDeltaY = pChild->GetOutOffYPixel() - GetOutOffYPixel();
+ Point aPos( i_rPos );
+ Point aDelta( nDeltaX, nDeltaY );
+ aPos += aDelta;
+ pChild->ImplPaintToDevice( i_pTargetOutDev, aPos );
+ }
+ }
+
+ // restore graphics state
+ Pop();
+
+ EnableOutput( bOutput );
+ mpWindowImpl->mbReallyVisible = bRVisible;
+ mbDevOutput = bDevOutput;
+ mnDPIX = nOldDPIX;
+ mnDPIY = nOldDPIY;
+}
+
+void Window::PaintToDevice( OutputDevice* pDev, const Point& rPos, const Size& /*rSize*/ )
+{
+ // FIXME: scaling: currently this is for pixel copying only
+
+ DBG_ASSERT( ! pDev->ImplHasMirroredGraphics(), "PaintToDevice to mirroring graphics" );
+ DBG_ASSERT( ! pDev->IsRTLEnabled(), "PaintToDevice to mirroring device" );
+
+
+ Point aPos = pDev->LogicToPixel( rPos );
+
+ Window* pRealParent = NULL;
+ if( ! mpWindowImpl->mbVisible )
+ {
+ Window* pTempParent = ImplGetDefaultWindow();
+ if( pTempParent )
+ pTempParent->EnableChildTransparentMode();
+ pRealParent = GetParent();
+ SetParent( pTempParent );
+ // trigger correct visibility flags for children
+ Show();
+ Hide();
+ }
+
+ BOOL bVisible = mpWindowImpl->mbVisible;
+ mpWindowImpl->mbVisible = TRUE;
+
+ if( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->ImplPaintToDevice( pDev, rPos );
+ else
+ ImplPaintToDevice( pDev, rPos );
+
+ mpWindowImpl->mbVisible = bVisible;
+
+ if( pRealParent )
+ SetParent( pRealParent );
+}
+
+XubString Window::GetSurroundingText() const
+{
+ return XubString::EmptyString();
+}
+
+Selection Window::GetSurroundingTextSelection() const
+{
+ return Selection( 0, 0 );
+}
+
diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
new file mode 100644
index 000000000000..02b2713b01cc
--- /dev/null
+++ b/vcl/source/window/window2.cxx
@@ -0,0 +1,2065 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include <limits.h>
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/salbmp.hxx>
+#include <vcl/salgdi.hxx>
+#include <vcl/salframe.hxx>
+#include <tools/debug.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/impbmp.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/event.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/outfont.hxx>
+#include <vcl/outdev.h>
+#include <tools/poly.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/window.h>
+#include <vcl/window.hxx>
+#include <vcl/scrbar.hxx>
+#ifndef _SV_SCRWND_HXX
+#include <scrwnd.hxx>
+#endif
+#include <vcl/dockwin.hxx>
+
+
+
+// =======================================================================
+
+DBG_NAMEEX( Window )
+
+// =======================================================================
+
+#define IMPL_MAXSAVEBACKSIZE (640*480)
+#define IMPL_MAXALLSAVEBACKSIZE (800*600*2)
+
+// =======================================================================
+
+struct ImplFocusDelData : public ImplDelData
+{
+ Window* mpFocusWin;
+};
+
+// =======================================================================
+
+BOOL Window::ImplIsWindowInFront( const Window* pTestWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_CHKOBJ( pTestWindow, Window, ImplDbgCheckWindow );
+
+ // Testen, ob es Fenster untereinander liegen
+ pTestWindow = pTestWindow->ImplGetFirstOverlapWindow();
+ const Window* pTempWindow = pTestWindow;
+ const Window* pThisWindow = ImplGetFirstOverlapWindow();
+ if ( pTempWindow == pThisWindow )
+ return FALSE;
+ do
+ {
+ if ( pTempWindow == pThisWindow )
+ return TRUE;
+ if ( pTempWindow->mpWindowImpl->mbFrame )
+ break;
+ pTempWindow = pTempWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ while ( pTempWindow );
+ pTempWindow = pThisWindow;
+ do
+ {
+ if ( pTempWindow == pTestWindow )
+ return FALSE;
+ if ( pTempWindow->mpWindowImpl->mbFrame )
+ break;
+ pTempWindow = pTempWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ while ( pTempWindow );
+
+ // Fenster auf gleiche Ebene bringen
+ if ( pThisWindow->mpWindowImpl->mpOverlapWindow != pTestWindow->mpWindowImpl->mpOverlapWindow )
+ {
+ USHORT nThisLevel = 0;
+ USHORT nTestLevel = 0;
+ pTempWindow = pThisWindow;
+ do
+ {
+ nThisLevel++;
+ pTempWindow = pTempWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ while ( !pTempWindow->mpWindowImpl->mbFrame );
+ pTempWindow = pTestWindow;
+ do
+ {
+ nTestLevel++;
+ pTempWindow = pTempWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ while ( !pTempWindow->mpWindowImpl->mbFrame );
+
+ if ( nThisLevel < nTestLevel )
+ {
+ do
+ {
+ if ( pTestWindow->mpWindowImpl->mpOverlapWindow == pThisWindow->mpWindowImpl->mpOverlapWindow )
+ break;
+ if ( pTestWindow->mpWindowImpl->mbFrame )
+ break;
+ pTestWindow = pTestWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ while ( pTestWindow );
+ }
+ else
+ {
+ do
+ {
+ if ( pThisWindow->mpWindowImpl->mpOverlapWindow == pTempWindow->mpWindowImpl->mpOverlapWindow )
+ break;
+ if ( pThisWindow->mpWindowImpl->mbFrame )
+ break;
+ pThisWindow = pThisWindow->mpWindowImpl->mpOverlapWindow;
+ }
+ while ( pThisWindow );
+ }
+ }
+
+ // Wenn TestWindow vor ThisWindow kommt, liegt es vorne
+ pTempWindow = pTestWindow;
+ do
+ {
+ if ( pTempWindow == pThisWindow )
+ return TRUE;
+ pTempWindow = pTempWindow->mpWindowImpl->mpNext;
+ }
+ while ( pTempWindow );
+
+ return FALSE;
+}
+
+// =======================================================================
+
+void Window::ImplSaveOverlapBackground()
+{
+ DBG_ASSERT( !mpWindowImpl->mpOverlapData->mpSaveBackDev, "Window::ImplSaveOverlapBackground() - Background already saved" );
+
+ if ( !mpWindowImpl->mbFrame )
+ {
+ ULONG nSaveBackSize = mnOutWidth*mnOutHeight;
+ if ( nSaveBackSize <= IMPL_MAXSAVEBACKSIZE )
+ {
+ if ( nSaveBackSize+mpWindowImpl->mpFrameData->mnAllSaveBackSize <= IMPL_MAXALLSAVEBACKSIZE )
+ {
+ Size aOutSize( mnOutWidth, mnOutHeight );
+ mpWindowImpl->mpOverlapData->mpSaveBackDev = new VirtualDevice( *mpWindowImpl->mpFrameWindow );
+ if ( mpWindowImpl->mpOverlapData->mpSaveBackDev->SetOutputSizePixel( aOutSize ) )
+ {
+ mpWindowImpl->mpFrameWindow->ImplUpdateAll();
+
+ if ( mpWindowImpl->mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+
+ mpWindowImpl->mpOverlapData->mnSaveBackSize = nSaveBackSize;
+ mpWindowImpl->mpFrameData->mnAllSaveBackSize += nSaveBackSize;
+ Point aDevPt;
+ mpWindowImpl->mpFrameWindow->ImplGetFrameDev( Point( mnOutOffX, mnOutOffY ),
+ aDevPt, aOutSize,
+ *(mpWindowImpl->mpOverlapData->mpSaveBackDev) );
+ mpWindowImpl->mpOverlapData->mpNextBackWin = mpWindowImpl->mpFrameData->mpFirstBackWin;
+ mpWindowImpl->mpFrameData->mpFirstBackWin = this;
+ }
+ else
+ {
+ delete mpWindowImpl->mpOverlapData->mpSaveBackDev;
+ mpWindowImpl->mpOverlapData->mpSaveBackDev = NULL;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplRestoreOverlapBackground( Region& rInvRegion )
+{
+ if ( mpWindowImpl->mpOverlapData->mpSaveBackDev )
+ {
+ if ( mpWindowImpl->mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+
+ if ( mpWindowImpl->mpOverlapData->mpSaveBackDev )
+ {
+ Point aDevPt;
+ Point aDestPt( mnOutOffX, mnOutOffY );
+ Size aDevSize = mpWindowImpl->mpOverlapData->mpSaveBackDev->GetOutputSizePixel();
+ if ( mpWindowImpl->mpOverlapData->mpSaveBackRgn )
+ {
+ mpWindowImpl->mpOverlapData->mpSaveBackRgn->Intersect( mpWindowImpl->maWinClipRegion );
+ rInvRegion = mpWindowImpl->maWinClipRegion;
+ rInvRegion.Exclude( *mpWindowImpl->mpOverlapData->mpSaveBackRgn );
+ mpWindowImpl->mpFrameWindow->ImplDrawFrameDev( aDestPt, aDevPt, aDevSize,
+ *(mpWindowImpl->mpOverlapData->mpSaveBackDev),
+ *mpWindowImpl->mpOverlapData->mpSaveBackRgn );
+ }
+ else
+ {
+ mpWindowImpl->mpFrameWindow->ImplDrawFrameDev( aDestPt, aDevPt, aDevSize,
+ *(mpWindowImpl->mpOverlapData->mpSaveBackDev),
+ mpWindowImpl->maWinClipRegion );
+ }
+ ImplDeleteOverlapBackground();
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplDeleteOverlapBackground()
+{
+ if ( mpWindowImpl->mpOverlapData->mpSaveBackDev )
+ {
+ mpWindowImpl->mpFrameData->mnAllSaveBackSize -= mpWindowImpl->mpOverlapData->mnSaveBackSize;
+ delete mpWindowImpl->mpOverlapData->mpSaveBackDev;
+ mpWindowImpl->mpOverlapData->mpSaveBackDev = NULL;
+ if ( mpWindowImpl->mpOverlapData->mpSaveBackRgn )
+ {
+ delete mpWindowImpl->mpOverlapData->mpSaveBackRgn;
+ mpWindowImpl->mpOverlapData->mpSaveBackRgn = NULL;
+ }
+
+ // Fenster aus der Liste entfernen
+ if ( mpWindowImpl->mpFrameData->mpFirstBackWin == this )
+ mpWindowImpl->mpFrameData->mpFirstBackWin = mpWindowImpl->mpOverlapData->mpNextBackWin;
+ else
+ {
+ Window* pTemp = mpWindowImpl->mpFrameData->mpFirstBackWin;
+ while ( pTemp->mpWindowImpl->mpOverlapData->mpNextBackWin != this )
+ pTemp = pTemp->mpWindowImpl->mpOverlapData->mpNextBackWin;
+ pTemp->mpWindowImpl->mpOverlapData->mpNextBackWin = mpWindowImpl->mpOverlapData->mpNextBackWin;
+ }
+ mpWindowImpl->mpOverlapData->mpNextBackWin = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateAllOverlapBackgrounds()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Window* pWindow = mpWindowImpl->mpFrameData->mpFirstBackWin;
+ while ( pWindow )
+ {
+ // Naechstes Fenster schon hier merken, da dieses Fenster in
+ // der if-Abfrage aus der Liste entfernt werden kann
+ Window* pNext = pWindow->mpWindowImpl->mpOverlapData->mpNextBackWin;
+
+ if ( ImplIsWindowInFront( pWindow ) )
+ {
+ Rectangle aRect1( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ Rectangle aRect2( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
+ Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
+ aRect1.Intersection( aRect2 );
+ if ( !aRect1.IsEmpty() )
+ {
+ if ( !pWindow->mpWindowImpl->mpOverlapData->mpSaveBackRgn )
+ pWindow->mpWindowImpl->mpOverlapData->mpSaveBackRgn = new Region( aRect2 );
+ pWindow->mpWindowImpl->mpOverlapData->mpSaveBackRgn->Exclude( aRect1 );
+ if ( pWindow->mpWindowImpl->mpOverlapData->mpSaveBackRgn->IsEmpty() )
+ pWindow->ImplDeleteOverlapBackground();
+ }
+
+ }
+
+ pWindow = pNext;
+ }
+}
+
+// =======================================================================
+
+Bitmap Window::SnapShot( BOOL bBorder ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Bitmap aBmp;
+
+ if ( IsReallyVisible() )
+ {
+ if ( bBorder && mpWindowImpl->mpBorderWindow )
+ aBmp = mpWindowImpl->mpBorderWindow->SnapShot();
+ else
+ {
+ ((Window*)this)->Update();
+
+ if ( bBorder && mpWindowImpl->mbFrame )
+ {
+ SalBitmap* pSalBmp = mpWindowImpl->mpFrame->SnapShot();
+
+ if ( pSalBmp )
+ {
+ ImpBitmap* pImpBmp = new ImpBitmap;
+ pImpBmp->ImplSetSalBitmap( pSalBmp );
+ aBmp.ImplSetImpBitmap( pImpBmp );
+ return aBmp;
+ }
+ }
+
+ mpWindowImpl->mpFrameWindow->ImplGetFrameBitmap( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ), aBmp );
+ }
+ }
+
+ return aBmp;
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap Window::SnapShot() const
+{
+ // Should be merged in the next top level build !!!
+ return SnapShot( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ShowFocus( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( mpWindowImpl->mbInShowFocus )
+ return;
+ mpWindowImpl->mbInShowFocus = TRUE;
+
+ ImplWinData* pWinData = ImplGetWinData();
+
+ // native themeing suggest not to use focus rects
+ if( ! ( mpWindowImpl->mbUseNativeFocus &&
+ IsNativeWidgetEnabled() ) )
+ {
+ if ( !mpWindowImpl->mbInPaint )
+ {
+ if ( mpWindowImpl->mbFocusVisible )
+ {
+ if ( *(pWinData->mpFocusRect) == rRect )
+ {
+ mpWindowImpl->mbInShowFocus = FALSE;
+ return;
+ }
+
+ ImplInvertFocus( *(pWinData->mpFocusRect) );
+ }
+
+ ImplInvertFocus( rRect );
+ }
+ if ( !pWinData->mpFocusRect )
+ pWinData->mpFocusRect = new Rectangle( rRect );
+ else
+ *(pWinData->mpFocusRect) = rRect;
+ mpWindowImpl->mbFocusVisible = TRUE;
+ }
+ else
+ {
+ if( ! mpWindowImpl->mbNativeFocusVisible )
+ {
+ mpWindowImpl->mbNativeFocusVisible = TRUE;
+ if ( !mpWindowImpl->mbInPaint )
+ Invalidate();
+ }
+ }
+ mpWindowImpl->mbInShowFocus = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::HideFocus()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if( mpWindowImpl->mbInHideFocus )
+ return;
+ mpWindowImpl->mbInHideFocus = TRUE;
+
+ // native themeing can suggest not to use focus rects
+ if( ! ( mpWindowImpl->mbUseNativeFocus &&
+ IsNativeWidgetEnabled() ) )
+ {
+ if ( !mpWindowImpl->mbFocusVisible )
+ {
+ mpWindowImpl->mbInHideFocus = FALSE;
+ return;
+ }
+
+ if ( !mpWindowImpl->mbInPaint )
+ ImplInvertFocus( *(ImplGetWinData()->mpFocusRect) );
+ mpWindowImpl->mbFocusVisible = FALSE;
+ }
+ else
+ {
+ if( mpWindowImpl->mbNativeFocusVisible )
+ {
+ mpWindowImpl->mbNativeFocusVisible = FALSE;
+ if ( !mpWindowImpl->mbInPaint )
+ Invalidate();
+ }
+ }
+ mpWindowImpl->mbInHideFocus = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invert( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+ aRect.Justify();
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ SalInvert nSalFlags = 0;
+ if ( nFlags & INVERT_HIGHLIGHT )
+ nSalFlags |= SAL_INVERT_HIGHLIGHT;
+ if ( nFlags & INVERT_50 )
+ nSalFlags |= SAL_INVERT_50;
+ mpGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), nSalFlags, this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invert( const Polygon& rPoly, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( nPoints < 2 )
+ return;
+
+ Polygon aPoly( ImplLogicToDevicePixel( rPoly ) );
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ SalInvert nSalFlags = 0;
+ if ( nFlags & INVERT_HIGHLIGHT )
+ nSalFlags |= SAL_INVERT_HIGHLIGHT;
+ if ( nFlags & INVERT_50 )
+ nSalFlags |= SAL_INVERT_50;
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry();
+ mpGraphics->Invert( nPoints, pPtAry, nSalFlags, this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ShowTracking( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+
+ if ( !mpWindowImpl->mbInPaint || !(nFlags & SHOWTRACK_WINDOW) )
+ {
+ if ( mpWindowImpl->mbTrackVisible )
+ {
+ if ( (*(pWinData->mpTrackRect) == rRect) &&
+ (pWinData->mnTrackFlags == nFlags) )
+ return;
+
+ InvertTracking( *(pWinData->mpTrackRect), pWinData->mnTrackFlags );
+ }
+
+ InvertTracking( rRect, nFlags );
+ }
+
+ if ( !pWinData->mpTrackRect )
+ pWinData->mpTrackRect = new Rectangle( rRect );
+ else
+ *(pWinData->mpTrackRect) = rRect;
+ pWinData->mnTrackFlags = nFlags;
+ mpWindowImpl->mbTrackVisible = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::HideTracking()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mbTrackVisible )
+ {
+ ImplWinData* pWinData = ImplGetWinData();
+ if ( !mpWindowImpl->mbInPaint || !(pWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ InvertTracking( *(pWinData->mpTrackRect), pWinData->mnTrackFlags );
+ mpWindowImpl->mbTrackVisible = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::InvertTracking( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+ aRect.Justify();
+
+ SalGraphics* pGraphics;
+
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ pGraphics = mpGraphics;
+ }
+ else
+ {
+ pGraphics = ImplGetFrameGraphics();
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ ImplSelectClipRegion( aRegion, pGraphics );
+ }
+ }
+
+ USHORT nStyle = nFlags & SHOWTRACK_STYLE;
+ if ( nStyle == SHOWTRACK_OBJECT )
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), SAL_INVERT_TRACKFRAME, this );
+ else if ( nStyle == SHOWTRACK_SPLIT )
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), SAL_INVERT_50, this );
+ else
+ {
+ long nBorder = 1;
+ if ( nStyle == SHOWTRACK_BIG )
+ nBorder = 5;
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), nBorder, SAL_INVERT_50, this );
+ pGraphics->Invert( aRect.Left(), aRect.Bottom()-nBorder+1, aRect.GetWidth(), nBorder, SAL_INVERT_50, this );
+ pGraphics->Invert( aRect.Left(), aRect.Top()+nBorder, nBorder, aRect.GetHeight()-(nBorder*2), SAL_INVERT_50, this );
+ pGraphics->Invert( aRect.Right()-nBorder+1, aRect.Top()+nBorder, nBorder, aRect.GetHeight()-(nBorder*2), SAL_INVERT_50, this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::InvertTracking( const Polygon& rPoly, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( nPoints < 2 )
+ return;
+
+ Polygon aPoly( ImplLogicToDevicePixel( rPoly ) );
+
+ SalGraphics* pGraphics;
+
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ pGraphics = mpGraphics;
+ }
+ else
+ {
+ pGraphics = ImplGetFrameGraphics();
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ ImplSelectClipRegion( aRegion, pGraphics );
+ }
+ }
+
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry();
+ pGraphics->Invert( nPoints, pPtAry, SAL_INVERT_TRACKFRAME, this );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplTrackTimerHdl, Timer*, pTimer )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Bei Button-Repeat muessen wir den Timeout umsetzen
+ if ( pSVData->maWinData.mnTrackFlags & STARTTRACK_BUTTONREPEAT )
+ pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
+
+ // Tracking-Event erzeugen
+ Point aMousePos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
+ if( ImplIsAntiparallel() )
+ {
+ // - RTL - re-mirror frame pos at pChild
+ ImplReMirror( aMousePos );
+ }
+ MouseEvent aMEvt( ImplFrameToOutput( aMousePos ),
+ mpWindowImpl->mpFrameData->mnClickCount, 0,
+ mpWindowImpl->mpFrameData->mnMouseCode, mpWindowImpl->mpFrameData->mnMouseCode );
+ TrackingEvent aTEvt( aMEvt, TRACKING_REPEAT );
+ Tracking( aTEvt );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::StartTracking( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpTrackWin != this )
+ {
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ }
+
+ if ( nFlags & (STARTTRACK_SCROLLREPEAT | STARTTRACK_BUTTONREPEAT) )
+ {
+ pSVData->maWinData.mpTrackTimer = new AutoTimer;
+
+ if ( nFlags & STARTTRACK_SCROLLREPEAT )
+ pSVData->maWinData.mpTrackTimer->SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
+ else
+ pSVData->maWinData.mpTrackTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
+ pSVData->maWinData.mpTrackTimer->SetTimeoutHdl( LINK( this, Window, ImplTrackTimerHdl ) );
+ pSVData->maWinData.mpTrackTimer->Start();
+ }
+
+ pSVData->maWinData.mpTrackWin = this;
+ pSVData->maWinData.mnTrackFlags = nFlags;
+ CaptureMouse();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EndTracking( USHORT nFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpTrackWin == this )
+ {
+ // Hier wegen DbgChkThis geklammert, da Window im Handler zerstoert
+ // werden kann
+ {
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( pSVData->maWinData.mpTrackTimer )
+ {
+ delete pSVData->maWinData.mpTrackTimer;
+ pSVData->maWinData.mpTrackTimer = NULL;
+ }
+
+ pSVData->maWinData.mpTrackWin = NULL;
+ pSVData->maWinData.mnTrackFlags = 0;
+ ReleaseMouse();
+ }
+
+ // EndTracking rufen, wenn es gerufen werden soll
+ if ( !(nFlags & ENDTRACK_DONTCALLHDL) )
+ {
+ Point aMousePos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
+ if( ImplIsAntiparallel() )
+ {
+ // - RTL - re-mirror frame pos at pChild
+ ImplReMirror( aMousePos );
+ }
+
+ MouseEvent aMEvt( ImplFrameToOutput( aMousePos ),
+ mpWindowImpl->mpFrameData->mnClickCount, 0,
+ mpWindowImpl->mpFrameData->mnMouseCode, mpWindowImpl->mpFrameData->mnMouseCode );
+ TrackingEvent aTEvt( aMEvt, nFlags | ENDTRACK_END );
+ Tracking( aTEvt );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsTracking() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (ImplGetSVData()->maWinData.mpTrackWin == this);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::StartAutoScroll( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpAutoScrollWin != this )
+ {
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ }
+
+ pSVData->maWinData.mpAutoScrollWin = this;
+ pSVData->maWinData.mnAutoScrollFlags = nFlags;
+ pSVData->maAppData.mpWheelWindow = new ImplWheelWindow( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EndAutoScroll()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpAutoScrollWin == this )
+ {
+ pSVData->maWinData.mpAutoScrollWin = NULL;
+ pSVData->maWinData.mnAutoScrollFlags = 0;
+ pSVData->maAppData.mpWheelWindow->ImplStop();
+ pSVData->maAppData.mpWheelWindow->doLazyDelete();
+ pSVData->maAppData.mpWheelWindow = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsAutoScroll() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (ImplGetSVData()->maWinData.mpAutoScrollWin == this);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SaveBackground( const Point& rPos, const Size& rSize,
+ const Point& rDestOff, VirtualDevice& rSaveDevice )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpPaintRegion )
+ {
+ Region aClip( *mpWindowImpl->mpPaintRegion );
+ const Point aPixPos( LogicToPixel( rPos ) );
+
+ aClip.Move( -mnOutOffX, -mnOutOffY );
+ aClip.Intersect( Rectangle( aPixPos, LogicToPixel( rSize ) ) );
+
+ if ( !aClip.IsEmpty() )
+ {
+ const Region aOldClip( rSaveDevice.GetClipRegion() );
+ const Point aPixOffset( rSaveDevice.LogicToPixel( rDestOff ) );
+ const BOOL bMap = rSaveDevice.IsMapModeEnabled();
+
+ // move clip region to have the same distance to DestOffset
+ aClip.Move( aPixOffset.X() - aPixPos.X(), aPixOffset.Y() - aPixPos.Y() );
+
+ // set pixel clip region
+ rSaveDevice.EnableMapMode( FALSE );
+ rSaveDevice.SetClipRegion( aClip );
+ rSaveDevice.EnableMapMode( bMap );
+ rSaveDevice.DrawOutDev( rDestOff, rSize, rPos, rSize, *this );
+ rSaveDevice.SetClipRegion( aOldClip );
+ }
+ }
+ else
+ rSaveDevice.DrawOutDev( rDestOff, rSize, rPos, rSize, *this );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uIntPtr Window::SaveFocus()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpFocusWin )
+ {
+ ImplFocusDelData* pDelData = new ImplFocusDelData;
+ pSVData->maWinData.mpFocusWin->ImplAddDel( pDelData );
+ pDelData->mpFocusWin = pSVData->maWinData.mpFocusWin;
+ return (sal_uIntPtr)(void*)pDelData;
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::EndSaveFocus( sal_uIntPtr nSaveId, BOOL bRestore )
+{
+ if ( !nSaveId )
+ return FALSE;
+ else
+ {
+ BOOL bOK = TRUE;
+ ImplFocusDelData* pDelData = (ImplFocusDelData*)(void*)nSaveId;
+ if ( !pDelData->IsDelete() )
+ {
+ pDelData->mpFocusWin->ImplRemoveDel( pDelData );
+ if ( bRestore )
+ pDelData->mpFocusWin->GrabFocus();
+ }
+ else
+ bOK = !bRestore;
+ delete pDelData;
+ return bOK;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetZoom( const Fraction& rZoom )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->maZoom != rZoom )
+ {
+ mpWindowImpl->maZoom = rZoom;
+ StateChanged( STATE_CHANGE_ZOOM );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline long WinFloatRound( double fVal )
+{
+ return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetZoomedPointFont( const Font& rFont )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Fraction& rZoom = GetZoom();
+ if ( rZoom.GetNumerator() != rZoom.GetDenominator() )
+ {
+ Font aFont( rFont );
+ Size aSize = aFont.GetSize();
+ double n = (double)aSize.Width();
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ aSize.Width() = WinFloatRound( n );
+ n = (double)aSize.Height();
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ aSize.Height() = WinFloatRound( n );
+ aFont.SetSize( aSize );
+ SetPointFont( aFont );
+
+ // Wenn Darstellung skaliert wird, nehmen wir gegebenenfalls
+ // einen anderen Font, wenn der aktuelle nicht skalierbar ist
+ FontMetric aMetric = GetFontMetric();
+ long nFontDiff = Abs( GetFont().GetSize().Height()-aMetric.GetSize().Height() );
+ if ( (aMetric.GetType() == TYPE_RASTER) && (nFontDiff >= 2) )
+ {
+ USHORT nType;
+ if ( aMetric.GetPitch() == PITCH_FIXED )
+ nType = DEFAULTFONT_FIXED;
+ else
+ nType = DEFAULTFONT_UI_SANS;
+ Font aTempFont = GetDefaultFont( nType, GetSettings().GetLanguage(), 0 );
+ aFont.SetName( aTempFont.GetName() );
+ SetPointFont( aFont );
+ }
+ }
+ else
+ SetPointFont( rFont );
+}
+
+// -----------------------------------------------------------------------
+
+long Window::CalcZoom( long nCalc ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Fraction& rZoom = GetZoom();
+ if ( rZoom.GetNumerator() != rZoom.GetDenominator() )
+ {
+ double n = (double)nCalc;
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ nCalc = WinFloatRound( n );
+ }
+ return nCalc;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlFont()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpControlFont )
+ {
+ delete mpWindowImpl->mpControlFont;
+ mpWindowImpl->mpControlFont = NULL;
+ StateChanged( STATE_CHANGE_CONTROLFONT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlFont( const Font& rFont )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rFont == Font() )
+ {
+ SetControlFont();
+ return;
+ }
+
+ if ( mpWindowImpl->mpControlFont )
+ {
+ if ( *mpWindowImpl->mpControlFont == rFont )
+ return;
+ *mpWindowImpl->mpControlFont = rFont;
+ }
+ else
+ mpWindowImpl->mpControlFont = new Font( rFont );
+
+ StateChanged( STATE_CHANGE_CONTROLFONT );
+}
+
+// -----------------------------------------------------------------------
+
+Font Window::GetControlFont() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mpControlFont )
+ return *mpWindowImpl->mpControlFont;
+ else
+ {
+ Font aFont;
+ return aFont;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlForeground()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mbControlForeground )
+ {
+ mpWindowImpl->maControlForeground = Color( COL_TRANSPARENT );
+ mpWindowImpl->mbControlForeground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlForeground( const Color& rColor )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rColor.GetTransparency() )
+ {
+ if ( mpWindowImpl->mbControlForeground )
+ {
+ mpWindowImpl->maControlForeground = Color( COL_TRANSPARENT );
+ mpWindowImpl->mbControlForeground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+ }
+ else
+ {
+ if ( mpWindowImpl->maControlForeground != rColor )
+ {
+ mpWindowImpl->maControlForeground = rColor;
+ mpWindowImpl->mbControlForeground = TRUE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlBackground()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpWindowImpl->mbControlBackground )
+ {
+ mpWindowImpl->maControlBackground = Color( COL_TRANSPARENT );
+ mpWindowImpl->mbControlBackground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlBackground( const Color& rColor )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rColor.GetTransparency() )
+ {
+ if ( mpWindowImpl->mbControlBackground )
+ {
+ mpWindowImpl->maControlBackground = Color( COL_TRANSPARENT );
+ mpWindowImpl->mbControlBackground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+ }
+ else
+ {
+ if ( mpWindowImpl->maControlBackground != rColor )
+ {
+ mpWindowImpl->maControlBackground = rColor;
+ mpWindowImpl->mbControlBackground = TRUE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Window::CalcWindowSize( const Size& rOutSz ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Size aSz = rOutSz;
+ aSz.Width() += mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder;
+ aSz.Height() += mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder;
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size Window::CalcOutputSize( const Size& rWinSz ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Size aSz = rWinSz;
+ aSz.Width() -= mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder;
+ aSz.Height() -= mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder;
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Font Window::GetDrawPixelFont( OutputDevice* pDev ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Font aFont = GetPointFont();
+ Size aFontSize = aFont.GetSize();
+ MapMode aPtMapMode( MAP_POINT );
+ aFontSize = pDev->LogicToPixel( aFontSize, aPtMapMode );
+ aFont.SetSize( aFontSize );
+ return aFont;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::GetDrawPixel( OutputDevice* pDev, long nPixels ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ long nP = nPixels;
+ if ( pDev->GetOutDevType() != OUTDEV_WINDOW )
+ {
+ MapMode aMap( MAP_100TH_MM );
+ Size aSz( nP, 0 );
+ aSz = PixelToLogic( aSz, aMap );
+ aSz = pDev->LogicToPixel( aSz, aMap );
+ nP = aSz.Width();
+ }
+ return nP;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HandleScrollCommand( const CommandEvent& rCmd,
+ ScrollBar* pHScrl, ScrollBar* pVScrl )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ BOOL bRet = FALSE;
+
+ if ( pHScrl || pVScrl )
+ {
+ switch( rCmd.GetCommand() )
+ {
+ case COMMAND_STARTAUTOSCROLL:
+ {
+ USHORT nFlags = 0;
+ if ( pHScrl )
+ {
+ if ( (pHScrl->GetVisibleSize() < pHScrl->GetRangeMax()) &&
+ pHScrl->IsEnabled() && pHScrl->IsInputEnabled() && ! pHScrl->IsInModalMode() )
+ nFlags |= AUTOSCROLL_HORZ;
+ }
+ if ( pVScrl )
+ {
+ if ( (pVScrl->GetVisibleSize() < pVScrl->GetRangeMax()) &&
+ pVScrl->IsEnabled() && pVScrl->IsInputEnabled() && ! pVScrl->IsInModalMode() )
+ nFlags |= AUTOSCROLL_VERT;
+ }
+
+ if ( nFlags )
+ {
+ StartAutoScroll( nFlags );
+ bRet = TRUE;
+ }
+ }
+ break;
+
+ case COMMAND_WHEEL:
+ {
+ const CommandWheelData* pData = rCmd.GetWheelData();
+
+ if ( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) )
+ {
+ ULONG nScrollLines = pData->GetScrollLines();
+ long nLines;
+ if ( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
+ {
+ if ( pData->GetDelta() < 0 )
+ nLines = -LONG_MAX;
+ else
+ nLines = LONG_MAX;
+ }
+ else
+ nLines = pData->GetNotchDelta() * (long)nScrollLines;
+ if ( nLines )
+ {
+ ImplHandleScroll( NULL,
+ 0L,
+ pData->IsHorz() ? pHScrl : pVScrl,
+ nLines );
+ bRet = TRUE;
+ }
+ }
+ }
+ break;
+
+ case COMMAND_AUTOSCROLL:
+ {
+ const CommandScrollData* pData = rCmd.GetAutoScrollData();
+ if ( pData && (pData->GetDeltaX() || pData->GetDeltaY()) )
+ {
+ ImplHandleScroll( pHScrl, pData->GetDeltaX(),
+ pVScrl, pData->GetDeltaY() );
+ bRet = TRUE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplHandleScroll( ScrollBar* pHScrl, long nX,
+ ScrollBar* pVScrl, long nY )
+{
+ if ( pHScrl && nX && pHScrl->IsEnabled() && pHScrl->IsInputEnabled() && ! pHScrl->IsInModalMode() )
+ {
+ long nNewPos = pHScrl->GetThumbPos();
+
+ if ( nX == -LONG_MAX )
+ nNewPos += pHScrl->GetPageSize();
+ else if ( nX == LONG_MAX )
+ nNewPos -= pHScrl->GetPageSize();
+ else
+ {
+ const double fVal = (double)nNewPos - ((double)nX * pHScrl->GetLineSize());
+
+ if ( fVal < LONG_MIN )
+ nNewPos = LONG_MIN;
+ else if ( fVal > LONG_MAX )
+ nNewPos = LONG_MAX;
+ else
+ nNewPos = (long)fVal;
+ }
+
+ pHScrl->DoScroll( nNewPos );
+ }
+
+ if ( pVScrl && nY && pVScrl->IsEnabled() && pVScrl->IsInputEnabled() && ! pVScrl->IsInModalMode() )
+ {
+ long nNewPos = pVScrl->GetThumbPos();
+
+ if ( nY == -LONG_MAX )
+ nNewPos += pVScrl->GetPageSize();
+ else if ( nY == LONG_MAX )
+ nNewPos -= pVScrl->GetPageSize();
+ else
+ {
+ const double fVal = (double)nNewPos - ((double)nY * pVScrl->GetLineSize());
+
+ if ( fVal < LONG_MIN )
+ nNewPos = LONG_MIN;
+ else if ( fVal > LONG_MAX )
+ nNewPos = LONG_MAX;
+ else
+ nNewPos = (long)fVal;
+ }
+
+ pVScrl->DoScroll( nNewPos );
+ }
+}
+
+// support for docking
+// this is currently handled in ImplDockingWindowWrapper
+/*
+void Window::ImplSetFloatingMode( BOOL bFloatMode )
+{
+ // if the window is docked, put it into a flaoting window
+ // if it is floating put it back in the old frame
+
+ ImplDockingWindowWrapper *pWrapper = pDockingMgr->GetDockingWindowWrapper( this );
+ if( !pDockingData )
+ return;
+
+ if ( pWrapper->IsFloatingMode() != bFloatMode )
+ {
+ if ( pWrapper->PrepareToggleFloatingMode() )
+ {
+ BOOL bVisible = IsVisible();
+
+ if ( bFloatMode )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ pWrapper->maDockPos = GetPosPixel();
+
+ Window* pRealParent = mpWindowImpl->mpRealParent;
+ pWrapper->mpOldBorderWin = mpWindowImpl->mpBorderWindow;
+
+ ImplDockFloatWin* pWin =
+ new ImplDockFloatWin2(
+ mpWindowImpl->mpParent,
+ mnFloatBits & ( WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE ) ? mnFloatBits | WB_SYSTEMWINDOW : mnFloatBits,
+ pWrapper );
+ pWrapper->mpFloatWin = pWin;
+ mpWindowImpl->mpBorderWindow = NULL;
+ mpWindowImpl->mnLeftBorder = 0;
+ mpWindowImpl->mnTopBorder = 0;
+ mpWindowImpl->mnRightBorder = 0;
+ mpWindowImpl->mnBottomBorder = 0;
+ // Falls Parent zerstoert wird, muessen wir auch vom
+ // BorderWindow den Parent umsetzen
+ if ( pWrapper->mpOldBorderWin )
+ pWrapper->mpOldBorderWin->SetParent( pWin );
+ SetParent( pWin );
+ pWin->SetPosPixel( Point() );
+ mpWindowImpl->mpBorderWindow = pWin;
+ pWin->mpWindowImpl->mpClientWindow = this;
+ mpWindowImpl->mpRealParent = pRealParent;
+ pWin->SetText( GetText() );
+ pWin->SetOutputSizePixel( GetSizePixel() );
+ pWin->SetPosPixel( pWrapper->maFloatPos );
+ // DockingDaten ans FloatingWindow weiterreichen
+ pWin->ShowTitleButton( TITLE_BUTTON_DOCKING, pWrapper->mbDockBtn );
+ pWin->ShowTitleButton( TITLE_BUTTON_HIDE, pWrapper->mbHideBtn );
+ pWin->SetPin( pWrapper->mbPined );
+ if ( pWrapper->mbRollUp )
+ pWin->RollUp();
+ else
+ pWin->RollDown();
+ pWin->SetRollUpOutputSizePixel( pWrapper->maRollUpOutSize );
+ pWin->SetMinOutputSizePixel( pWrapper->maMinOutSize );
+
+ pWrapper->ToggleFloatingMode();
+
+ if ( bVisible )
+ Show();
+ }
+ else
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // FloatingDaten wird im FloatingWindow speichern
+ pWrapper->maFloatPos = mpFloatWin->GetPosPixel();
+ pWrapper->mbDockBtn = mpFloatWin->IsTitleButtonVisible( TITLE_BUTTON_DOCKING );
+ pWrapper->mbHideBtn = mpFloatWin->IsTitleButtonVisible( TITLE_BUTTON_HIDE );
+ pWrapper->mbPined = mpFloatWin->IsPined();
+ pWrapper->mbRollUp = mpFloatWin->IsRollUp();
+ pWrapper->maRollUpOutSize = mpFloatWin->GetRollUpOutputSizePixel();
+ pWrapper->maMinOutSize = mpFloatWin->GetMinOutputSizePixel();
+
+ Window* pRealParent = mpWindowImpl->mpRealParent;
+ mpWindowImpl->mpBorderWindow = NULL;
+ if ( pWrapper->mpOldBorderWin )
+ {
+ SetParent( pWrapper->mpOldBorderWin );
+ ((ImplBorderWindow*)pWrapper->mpOldBorderWin)->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ pWrapper->mpOldBorderWin->Resize();
+ }
+ mpWindowImpl->mpBorderWindow = pWrapper->mpOldBorderWin;
+ SetParent( pRealParent );
+ mpWindowImpl->mpRealParent = pRealParent;
+ delete static_cast<ImplDockFloatWin*>(mpFloatWin);
+ pWrapper->mpFloatWin = NULL;
+ SetPosPixel( maDockPos );
+
+ pWrapper->ToggleFloatingMode();
+
+ if ( bVisible )
+ Show();
+ }
+ }
+ }
+}
+*/
+
+DockingManager* Window::GetDockingManager()
+{
+ return ImplGetDockingManager();
+}
+
+void Window::EnableDocking( BOOL bEnable )
+{
+ // update list of dockable windows
+ if( bEnable )
+ ImplGetDockingManager()->AddWindow( this );
+ else
+ ImplGetDockingManager()->RemoveWindow( this );
+}
+
+
+// retrieves the list of owner draw decorated windows for this window hiearchy
+::std::vector<Window *>& Window::ImplGetOwnerDrawList()
+{
+ return ImplGetTopmostFrameWindow()->mpWindowImpl->mpFrameData->maOwnerDrawList;
+}
+
+Window* Window::ImplGetTopmostFrameWindow()
+{
+ Window *pTopmostParent = this;
+ while( pTopmostParent->ImplGetParent() )
+ pTopmostParent = pTopmostParent->ImplGetParent();
+ return pTopmostParent->mpWindowImpl->mpFrameWindow;
+}
+
+// making these Methods out of line to be able to change them lateron without complete rebuild
+// TODO: Set the SmartId in here and remove mpWindowImpl->mnHelpId
+void Window::SetHelpId( ULONG nHelpId )
+{
+ SetSmartHelpId(SmartId(nHelpId));
+}
+
+ULONG Window::GetHelpId() const
+{
+ return mpWindowImpl->mnHelpId;
+}
+
+void Window::SetSmartHelpId( const SmartId& aId, SmartIdUpdateMode aMode )
+{
+ // create SmartId if required
+ if ( (aMode == SMART_SET_STR) || (aMode == SMART_SET_ALL) || ( (aMode == SMART_SET_SMART) && aId.HasString() ) )
+ {
+ if ( !ImplGetWinData()->mpSmartHelpId )
+ ImplGetWinData()->mpSmartHelpId = new SmartId();
+ }
+
+ // if we have a SmartId (eather from earlier call or just created) fill with new values
+ if ( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mpSmartHelpId )
+ ImplGetWinData()->mpSmartHelpId->UpdateId( aId, aMode );
+
+ if ( (aMode == SMART_SET_NUM) || (aMode == SMART_SET_ALL) || ( (aMode == SMART_SET_SMART) && aId.HasNumeric() ) )
+ {
+ mpWindowImpl->mnHelpId = aId.GetNum();
+ }
+}
+
+SmartId Window::GetSmartHelpId() const
+{
+ if ( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mpSmartHelpId )
+ {
+ if ( mpWindowImpl->mnHelpId || mpWindowImpl->mpWinData->mpSmartHelpId->HasNumeric() )
+ mpWindowImpl->mpWinData->mpSmartHelpId->UpdateId( SmartId( mpWindowImpl->mnHelpId ), SMART_SET_NUM );
+ return *mpWindowImpl->mpWinData->mpSmartHelpId;
+ }
+ else
+ {
+ if ( mpWindowImpl->mnHelpId )
+ return SmartId( mpWindowImpl->mnHelpId );
+ else
+ return SmartId();
+ }
+}
+
+
+// making these Methods out of line to be able to change them lateron without complete rebuild
+// TODO: Set the SmartId in here and remove mpWindowImpl->mnUniqId
+void Window::SetUniqueId( ULONG nUniqueId ) { mpWindowImpl->mnUniqId = nUniqueId; }
+ULONG Window::GetUniqueId() const { return mpWindowImpl->mnUniqId; }
+
+
+void Window::SetSmartUniqueId( const SmartId& aId, SmartIdUpdateMode aMode )
+{
+ // create SmartId if required
+ if ( (aMode == SMART_SET_STR) || (aMode == SMART_SET_ALL) || ( (aMode == SMART_SET_SMART) && aId.HasString() ) )
+ {
+ if ( !ImplGetWinData()->mpSmartUniqueId )
+ ImplGetWinData()->mpSmartUniqueId = new SmartId();
+ }
+
+ // if we have a SmartId (eather from earlier call or just created) fill with new values
+ if ( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mpSmartUniqueId )
+ ImplGetWinData()->mpSmartUniqueId->UpdateId( aId, aMode );
+
+ if ( (aMode == SMART_SET_NUM) || (aMode == SMART_SET_ALL) || ( (aMode == SMART_SET_SMART) && aId.HasNumeric() ) )
+ mpWindowImpl->mnUniqId = aId.GetNum();
+}
+
+SmartId Window::GetSmartUniqueId() const
+{
+ if ( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mpSmartUniqueId )
+ {
+ if ( mpWindowImpl->mnUniqId || mpWindowImpl->mpWinData->mpSmartUniqueId->HasNumeric() )
+ mpWindowImpl->mpWinData->mpSmartUniqueId->UpdateId( SmartId( mpWindowImpl->mnUniqId ), SMART_SET_NUM );
+ return *mpWindowImpl->mpWinData->mpSmartUniqueId;
+ }
+ else
+ {
+ if ( mpWindowImpl->mnUniqId )
+ return SmartId( mpWindowImpl->mnUniqId );
+ else
+ return SmartId();
+ }
+}
+
+SmartId Window::GetSmartUniqueOrHelpId() const
+{
+ if ( ( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mpSmartHelpId ) || mpWindowImpl->mnHelpId )
+ {
+ if ( ( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mpSmartUniqueId ) || mpWindowImpl->mnUniqId )
+ {
+ SmartId aTemp = GetSmartHelpId();
+ aTemp.UpdateId( GetSmartUniqueId() );
+ return aTemp;
+ }
+ else
+ return GetSmartHelpId();
+ }
+ else
+ return GetSmartUniqueId();
+}
+
+
+
+
+// --------- old inline methods ---------------
+
+Window* Window::ImplGetWindow()
+{
+ if ( mpWindowImpl->mpClientWindow )
+ return mpWindowImpl->mpClientWindow;
+ else
+ return this;
+}
+
+ImplFrameData* Window::ImplGetFrameData()
+{
+ return mpWindowImpl->mpFrameData;
+}
+
+SalFrame* Window::ImplGetFrame() const
+{
+ return mpWindowImpl->mpFrame;
+}
+
+Window* Window::ImplGetParent() const
+{
+ return mpWindowImpl->mpParent;
+}
+
+Window* Window::ImplGetClientWindow() const
+{
+ return mpWindowImpl->mpClientWindow;
+}
+
+Window* Window::ImplGetBorderWindow() const
+{
+ return mpWindowImpl->mpBorderWindow;
+}
+
+Window* Window::ImplGetFirstOverlapWindow()
+{
+ if ( mpWindowImpl->mbOverlapWin )
+ return this;
+ else
+ return mpWindowImpl->mpOverlapWindow;
+}
+
+const Window* Window::ImplGetFirstOverlapWindow() const
+{
+ if ( mpWindowImpl->mbOverlapWin )
+ return this;
+ else
+ return mpWindowImpl->mpOverlapWindow;
+}
+
+Window* Window::ImplGetFrameWindow() const
+{
+ return mpWindowImpl->mpFrameWindow;
+}
+
+BOOL Window::ImplIsDockingWindow() const
+{
+ return mpWindowImpl->mbDockWin;
+}
+
+BOOL Window::ImplIsFloatingWindow() const
+{
+ return mpWindowImpl->mbFloatWin;
+}
+
+BOOL Window::ImplIsToolbox() const
+{
+ return mpWindowImpl->mbToolBox;
+}
+
+BOOL Window::ImplIsSplitter() const
+{
+ return mpWindowImpl->mbSplitter;
+}
+
+BOOL Window::ImplIsPushButton() const
+{
+ return mpWindowImpl->mbPushButton;
+}
+
+BOOL Window::ImplIsOverlapWindow() const
+{
+ return mpWindowImpl->mbOverlapWin;
+}
+
+void Window::ImplSetActive( BOOL bActive )
+{
+ mpWindowImpl->mbActive = bActive;
+}
+
+BOOL Window::ImplIsMouseTransparent() const
+{
+ return mpWindowImpl->mbMouseTransparent;
+}
+
+void Window::ImplSetMouseTransparent( BOOL bTransparent )
+{
+ mpWindowImpl->mbMouseTransparent = bTransparent;
+}
+
+Point Window::ImplOutputToFrame( const Point& rPos )
+{
+ return Point( rPos.X()+mnOutOffX, rPos.Y()+mnOutOffY );
+}
+
+Point Window::ImplFrameToOutput( const Point& rPos )
+{
+ return Point( rPos.X()-mnOutOffX, rPos.Y()-mnOutOffY );
+}
+
+void Window::ImplOutputToFrame( Rectangle& rRect )
+{
+ rRect.Left()+=mnOutOffX;
+ rRect.Top()+=mnOutOffY;
+ rRect.Right()+=mnOutOffX;
+ rRect.Bottom()+=mnOutOffY;
+}
+
+void Window::ImplFrameToOutput( Rectangle& rRect )
+{
+ rRect.Left()-=mnOutOffX;
+ rRect.Top()-=mnOutOffY;
+ rRect.Right()-=mnOutOffX;
+ rRect.Bottom()-=mnOutOffY;
+}
+
+void Window::SetCompoundControl( BOOL bCompound )
+{
+ mpWindowImpl->mbCompoundControl = bCompound;
+}
+
+void Window::IncrementLockCount()
+{
+ mpWindowImpl->mnLockCount++;
+}
+
+void Window::DecrementLockCount()
+{
+ mpWindowImpl->mnLockCount--;
+}
+
+WinBits Window::GetStyle() const
+{
+ return mpWindowImpl->mnStyle;
+}
+
+WinBits Window::GetPrevStyle() const
+{
+ return mpWindowImpl->mnPrevStyle;
+}
+
+WinBits Window::GetExtendedStyle() const
+{
+ return mpWindowImpl->mnExtendedStyle;
+}
+
+WinBits Window::GetPrevExtendedStyle() const
+{
+ return mpWindowImpl->mnExtendedStyle;
+}
+
+void Window::SetType( WindowType nType )
+{
+ mpWindowImpl->mnType = nType;
+}
+
+WindowType Window::GetType() const
+{
+ return mpWindowImpl->mnType;
+}
+BOOL Window::IsSystemWindow() const
+{
+ return mpWindowImpl->mbSysWin;
+}
+
+BOOL Window::IsDialog() const
+{
+ return mpWindowImpl->mbDialog;
+}
+
+BOOL Window::IsMenuFloatingWindow() const
+{
+ return mpWindowImpl->mbMenuFloatingWindow;
+}
+
+BOOL Window::IsToolbarFloatingWindow() const
+{
+ return mpWindowImpl->mbToolbarFloatingWindow;
+}
+
+void Window::EnableAllResize( BOOL bEnable )
+{
+ mpWindowImpl->mbAllResize = bEnable;
+}
+
+BOOL Window::IsAllResizeEnabled() const
+{
+ return mpWindowImpl->mbAllResize;
+}
+
+BOOL Window::IsClipSiblingsEnabled() const
+{
+ return mpWindowImpl->mbClipSiblings;
+}
+
+void Window::EnableChildTransparentMode( BOOL bEnable )
+{
+ mpWindowImpl->mbChildTransparent = bEnable;
+}
+
+BOOL Window::IsChildTransparentModeEnabled() const
+{
+ return mpWindowImpl->mbChildTransparent;
+}
+
+BOOL Window::IsMouseTransparent() const
+{
+ return mpWindowImpl->mbMouseTransparent;
+}
+
+BOOL Window::IsPaintTransparent() const
+{
+ return mpWindowImpl->mbPaintTransparent;
+}
+
+void Window::SetDialogControlStart( BOOL bStart )
+{
+ mpWindowImpl->mbDlgCtrlStart = bStart;
+}
+
+BOOL Window::IsDialogControlStart() const
+{
+ return mpWindowImpl->mbDlgCtrlStart;
+}
+
+void Window::SetDialogControlFlags( USHORT nFlags )
+{
+ mpWindowImpl->mnDlgCtrlFlags = nFlags;
+}
+
+USHORT Window::GetDialogControlFlags() const
+{
+ return mpWindowImpl->mnDlgCtrlFlags;
+}
+
+const InputContext& Window::GetInputContext() const
+{
+ return mpWindowImpl->maInputContext;
+}
+
+BOOL Window::IsExtTextInput() const
+{
+ return mpWindowImpl->mbExtTextInput;
+}
+
+void Window::EnableChildNotify( BOOL bEnable )
+{
+ mpWindowImpl->mbChildNotify = bEnable;
+}
+
+BOOL Window::IsChildNotify() const
+{
+ return mpWindowImpl->mbChildNotify;
+}
+
+BOOL Window::IsControlFont() const
+{
+ return (mpWindowImpl->mpControlFont != 0);
+}
+
+Color Window::GetControlForeground() const
+{
+ return mpWindowImpl->maControlForeground;
+}
+
+BOOL Window::IsControlForeground() const
+{
+ return mpWindowImpl->mbControlForeground;
+}
+
+Color Window::GetControlBackground() const
+{
+ return mpWindowImpl->maControlBackground;
+}
+
+BOOL Window::IsControlBackground() const
+{
+ return mpWindowImpl->mbControlBackground;
+}
+
+BOOL Window::IsInPaint() const
+{
+ return mpWindowImpl->mbInPaint;
+}
+
+Window* Window::GetParent() const
+{
+ return mpWindowImpl->mpRealParent;
+}
+
+BOOL Window::IsVisible() const
+{
+ return mpWindowImpl->mbVisible;
+}
+
+BOOL Window::IsReallyVisible() const
+{
+ return mpWindowImpl->mbReallyVisible;
+}
+
+BOOL Window::IsParentPathVisible() const
+{
+ return mpWindowImpl->mbReallyVisible;
+}
+
+BOOL Window::IsReallyShown() const
+{
+ return mpWindowImpl->mbReallyShown;
+}
+
+BOOL Window::IsInInitShow() const
+{
+ return mpWindowImpl->mbInInitShow;
+}
+
+BOOL Window::IsEnabled() const
+{
+ return !mpWindowImpl->mbDisabled;
+}
+
+BOOL Window::IsInputEnabled() const
+{
+ return !mpWindowImpl->mbInputDisabled;
+}
+
+BOOL Window::IsAlwaysEnableInput() const
+{
+ return mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled;
+}
+
+BOOL Window::IsAlwaysDisableInput() const
+{
+ return mpWindowImpl->meAlwaysInputMode == AlwaysInputDisabled;
+}
+
+USHORT Window::GetActivateMode() const
+{
+ return mpWindowImpl->mnActivateMode;
+
+}
+
+BOOL Window::IsAlwaysOnTopEnabled() const
+{
+ return mpWindowImpl->mbAlwaysOnTop;
+}
+
+BOOL Window::IsDefaultPos() const
+{
+ return mpWindowImpl->mbDefPos;
+}
+
+BOOL Window::IsDefaultSize() const
+{
+ return mpWindowImpl->mbDefSize;
+}
+
+void Window::EnablePaint( BOOL bEnable )
+{
+ mpWindowImpl->mbPaintDisabled = !bEnable;
+}
+
+BOOL Window::IsPaintEnabled() const
+{
+ return !mpWindowImpl->mbPaintDisabled;
+}
+
+BOOL Window::IsUpdateMode() const
+{
+ return !mpWindowImpl->mbNoUpdate;
+}
+
+void Window::SetParentUpdateMode( BOOL bUpdate )
+{
+ mpWindowImpl->mbNoParentUpdate = !bUpdate;
+}
+
+BOOL Window::IsParentUpdateMode() const
+{
+ return !mpWindowImpl->mbNoParentUpdate;
+}
+
+BOOL Window::IsActive() const
+{
+ return mpWindowImpl->mbActive;
+}
+
+USHORT Window::GetGetFocusFlags() const
+{
+ return mpWindowImpl->mnGetFocusFlags;
+}
+
+BOOL Window::IsCompoundControl() const
+{
+ return mpWindowImpl->mbCompoundControl;
+}
+
+BOOL Window::HasCompoundControlFocus() const
+{
+ return mpWindowImpl->mbCompoundControlHasFocus;
+}
+
+BOOL Window::IsChildPointerOverwrite() const
+{
+ return mpWindowImpl->mbChildPtrOverwrite;
+}
+
+BOOL Window::IsPointerVisible() const
+{
+ return !mpWindowImpl->mbNoPtrVisible;
+}
+
+BOOL Window::IsWait() const
+{
+ return (mpWindowImpl->mnWaitCount != 0);
+}
+
+Cursor* Window::GetCursor() const
+{
+ return mpWindowImpl->mpCursor;
+}
+
+const Fraction& Window::GetZoom() const
+{
+ return mpWindowImpl->maZoom;
+}
+
+BOOL Window::IsZoom() const
+{
+ return mpWindowImpl->maZoom.GetNumerator() != mpWindowImpl->maZoom.GetDenominator();
+}
+
+void Window::SetHelpText( const XubString& rHelpText )
+{
+ mpWindowImpl->maHelpText = rHelpText;
+ mpWindowImpl->mbHelpTextDynamic = TRUE;
+}
+
+void Window::SetQuickHelpText( const XubString& rHelpText )
+{
+ mpWindowImpl->maQuickHelpText = rHelpText;
+}
+
+const XubString& Window::GetQuickHelpText() const
+{
+ return mpWindowImpl->maQuickHelpText;
+}
+
+void Window::SetData( void* pNewData )
+{
+ mpWindowImpl->mpUserData = pNewData;
+}
+
+void* Window::GetData() const
+{
+ return mpWindowImpl->mpUserData;
+}
+
+BOOL Window::IsCreatedWithToolkit() const
+{
+ return mpWindowImpl->mbCreatedWithToolkit;
+}
+
+void Window::SetCreatedWithToolkit( BOOL b )
+{
+ mpWindowImpl->mbCreatedWithToolkit = b;
+
+}
+const Pointer& Window::GetPointer() const
+{
+ return mpWindowImpl->maPointer;
+}
+
+VCLXWindow* Window::GetWindowPeer() const
+{
+ return mpWindowImpl->mpVCLXWindow;
+}
+
+void Window::SetPosPixel( const Point& rNewPos )
+{
+ SetPosSizePixel( rNewPos.X(), rNewPos.Y(), 0, 0, WINDOW_POSSIZE_POS );
+}
+
+void Window::SetSizePixel( const Size& rNewSize )
+{
+ SetPosSizePixel( 0, 0, rNewSize.Width(), rNewSize.Height(),
+ WINDOW_POSSIZE_SIZE );
+}
+
+void Window::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
+{
+ SetPosSizePixel( rNewPos.X(), rNewPos.Y(),
+ rNewSize.Width(), rNewSize.Height(),
+ WINDOW_POSSIZE_POSSIZE );
+}
+
+void Window::SetOutputSizePixel( const Size& rNewSize )
+{
+ SetSizePixel( Size( rNewSize.Width()+mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
+ rNewSize.Height()+mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder ) );
+}
+
diff --git a/vcl/source/window/window3.cxx b/vcl/source/window/window3.cxx
new file mode 100644
index 000000000000..65019ba2a4af
--- /dev/null
+++ b/vcl/source/window/window3.cxx
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#include "vcl/window.hxx"
+#include "vcl/waitobj.hxx"
+#include "vcl/button.hxx"
+
+// -----------------------------------------------------------------------
+
+WaitObject::~WaitObject()
+{
+ if ( mpWindow )
+ mpWindow->LeaveWait();
+}
+
+// -----------------------------------------------------------------------
+
+Size Window::GetOptimalSize(WindowSizeType eType) const
+{
+ switch (eType) {
+ case WINDOWSIZE_MINIMUM:
+ return Size();
+ case WINDOWSIZE_PREFERRED:
+ return GetOptimalSize( WINDOWSIZE_MINIMUM );
+ case WINDOWSIZE_MAXIMUM:
+ default:
+ return Size( LONG_MAX, LONG_MAX );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplAdjustNWFSizes()
+{
+ switch( GetType() )
+ {
+ case WINDOW_CHECKBOX:
+ ((CheckBox*)this)->ImplSetMinimumNWFSize();
+ break;
+ case WINDOW_RADIOBUTTON:
+ ((RadioButton*)this)->ImplSetMinimumNWFSize();
+ break;
+ default:
+ {
+ // iterate over children
+ Window* pWin = GetWindow( WINDOW_FIRSTCHILD );
+ while( pWin )
+ {
+ pWin->ImplAdjustNWFSizes();
+ pWin = pWin->GetWindow( WINDOW_NEXT );
+ }
+ }
+ break;
+ }
+}
diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx
new file mode 100644
index 000000000000..c964ad0d739b
--- /dev/null
+++ b/vcl/source/window/winproc.cxx
@@ -0,0 +1,2618 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/salwtype.hxx>
+#include <vcl/salframe.hxx>
+#include <tools/debug.hxx>
+#ifndef _INTN_HXX
+//#include <tools/intn.hxx>
+#endif
+#include <vcl/i18nhelp.hxx>
+#include <vcl/unohelp.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <vcl/svdata.hxx>
+#include <vcl/dbggui.hxx>
+#include <vcl/windata.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/event.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/cursor.hxx>
+#include <vcl/accmgr.hxx>
+#include <vcl/print.h>
+#include <vcl/window.h>
+#include <vcl/wrkwin.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/help.hxx>
+#include <vcl/helpwin.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/dockwin.hxx>
+#include <vcl/salgdi.hxx>
+#include <vcl/menu.hxx>
+
+#include <vcl/dndlcon.hxx>
+#include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
+#include <com/sun/star/awt/MouseEvent.hpp>
+
+#if OSL_DEBUG_LEVEL > 1
+char dbgbuffer[1024];
+#ifndef WNT
+#include <stdio.h>
+#define MyOutputDebugString(s) (fprintf(stderr, s ))
+#else
+extern void MyOutputDebugString( char *s);
+#endif
+#endif
+
+
+// =======================================================================
+
+#define IMPL_MIN_NEEDSYSWIN 49
+
+// =======================================================================
+
+long ImplCallPreNotify( NotifyEvent& rEvt )
+{
+ long nRet = Application::CallEventHooks( rEvt );
+ if ( !nRet )
+ nRet = rEvt.GetWindow()->PreNotify( rEvt );
+ return nRet;
+}
+
+// =======================================================================
+
+long ImplCallEvent( NotifyEvent& rEvt )
+{
+ long nRet = ImplCallPreNotify( rEvt );
+ if ( !nRet )
+ {
+ Window* pWindow = rEvt.GetWindow();
+ switch ( rEvt.GetType() )
+ {
+ case EVENT_MOUSEBUTTONDOWN:
+ pWindow->MouseButtonDown( *rEvt.GetMouseEvent() );
+ break;
+ case EVENT_MOUSEBUTTONUP:
+ pWindow->MouseButtonUp( *rEvt.GetMouseEvent() );
+ break;
+ case EVENT_MOUSEMOVE:
+ pWindow->MouseMove( *rEvt.GetMouseEvent() );
+ break;
+ case EVENT_KEYINPUT:
+ pWindow->KeyInput( *rEvt.GetKeyEvent() );
+ break;
+ case EVENT_KEYUP:
+ pWindow->KeyUp( *rEvt.GetKeyEvent() );
+ break;
+ case EVENT_GETFOCUS:
+ pWindow->GetFocus();
+ break;
+ case EVENT_LOSEFOCUS:
+ pWindow->LoseFocus();
+ break;
+ case EVENT_COMMAND:
+ pWindow->Command( *rEvt.GetCommandEvent() );
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+// =======================================================================
+
+static BOOL ImplHandleMouseFloatMode( Window* pChild, const Point& rMousePos,
+ USHORT nCode, USHORT nSVEvent,
+ BOOL bMouseLeave )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpFirstFloat && !pSVData->maWinData.mpCaptureWin &&
+ !pSVData->maWinData.mpFirstFloat->ImplIsFloatPopupModeWindow( pChild ) )
+ {
+ /*
+ * #93895# since floats are system windows, coordinates have
+ * to be converted to float relative for the hittest
+ */
+ USHORT nHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
+ FloatingWindow* pFloat = pSVData->maWinData.mpFirstFloat->ImplFloatHitTest( pChild, rMousePos, nHitTest );
+ FloatingWindow* pLastLevelFloat;
+ ULONG nPopupFlags;
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ if ( bMouseLeave )
+ return TRUE;
+
+ if ( !pFloat || (nHitTest & IMPL_FLOATWIN_HITTEST_RECT) )
+ {
+ if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp )
+ ImplDestroyHelpWindow( true );
+ pChild->ImplGetFrame()->SetPointer( POINTER_ARROW );
+ return TRUE;
+ }
+ }
+ else
+ {
+ if ( nCode & MOUSE_LEFT )
+ {
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( !pFloat )
+ {
+ pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+// Erstmal ausgebaut als Hack fuer Bug 53378
+// if ( nPopupFlags & FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK )
+// return FALSE;
+// else
+ return TRUE;
+ }
+ else if ( nHitTest & IMPL_FLOATWIN_HITTEST_RECT )
+ {
+ if ( !(pFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE) )
+ pFloat->ImplSetMouseDown();
+ return TRUE;
+ }
+ }
+ else
+ {
+ if ( pFloat )
+ {
+ if ( nHitTest & IMPL_FLOATWIN_HITTEST_RECT )
+ {
+ if ( pFloat->ImplIsMouseDown() )
+ pFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
+ return TRUE;
+ }
+ }
+ else
+ {
+ pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
+ if ( !(nPopupFlags & FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE) )
+ {
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ return TRUE;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( !pFloat )
+ {
+ pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
+ if ( nPopupFlags & FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE )
+ {
+ if ( (nPopupFlags & FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE) &&
+ (nSVEvent == EVENT_MOUSEBUTTONUP) )
+ return TRUE;
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ if ( nPopupFlags & FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK )
+ return FALSE;
+ else
+ return TRUE;
+ }
+ else
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleMouseHelpRequest( Window* pChild, const Point& rMousePos )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maHelpData.mpHelpWin ||
+ !( pSVData->maHelpData.mpHelpWin->IsWindowOrChild( pChild ) ||
+ pChild->IsWindowOrChild( pSVData->maHelpData.mpHelpWin ) ) )
+ {
+ USHORT nHelpMode = 0;
+ if ( pSVData->maHelpData.mbQuickHelp )
+ nHelpMode = HELPMODE_QUICK;
+ if ( pSVData->maHelpData.mbBalloonHelp )
+ nHelpMode |= HELPMODE_BALLOON;
+ if ( nHelpMode )
+ {
+ if ( pChild->IsInputEnabled() && ! pChild->IsInModalMode() )
+ {
+ HelpEvent aHelpEvent( rMousePos, nHelpMode );
+ pSVData->maHelpData.mbRequestingHelp = TRUE;
+ pChild->RequestHelp( aHelpEvent );
+ pSVData->maHelpData.mbRequestingHelp = FALSE;
+ }
+ // #104172# do not kill keyboard activated tooltips
+ else if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp)
+ {
+ ImplDestroyHelpWindow( true );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSetMousePointer( Window* pChild )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maHelpData.mbExtHelpMode )
+ pChild->ImplGetFrame()->SetPointer( POINTER_HELP );
+ else
+ pChild->ImplGetFrame()->SetPointer( pChild->ImplGetMousePointer() );
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplCallCommand( Window* pChild, USHORT nEvt, void* pData = NULL,
+ BOOL bMouse = FALSE, Point* pPos = NULL )
+{
+ Point aPos;
+ if ( pPos )
+ aPos = *pPos;
+ else
+ {
+ if( bMouse )
+ aPos = pChild->GetPointerPosPixel();
+ else
+ {
+ // simulate mouseposition at center of window
+ Size aSize( pChild->GetOutputSizePixel() );
+ aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
+ }
+ }
+
+ CommandEvent aCEvt( aPos, nEvt, bMouse, pData );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pChild, &aCEvt );
+ ImplDelData aDelData( pChild );
+ BOOL bPreNotify = (ImplCallPreNotify( aNCmdEvt ) != 0);
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ if ( !bPreNotify )
+ {
+ pChild->ImplGetWindowImpl()->mbCommand = FALSE;
+ pChild->Command( aCEvt );
+
+ if( aDelData.IsDelete() )
+ return FALSE;
+ pChild->ImplNotifyKeyMouseCommandEventListeners( aNCmdEvt );
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ if ( pChild->ImplGetWindowImpl()->mbCommand )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+/* #i34277# delayed context menu activation;
+* necessary if there already was a popup menu running.
+*/
+
+struct ContextMenuEvent
+{
+ Window* pWindow;
+ ImplDelData aDelData;
+ Point aChildPos;
+};
+
+static long ContextMenuEventLink( void* pCEvent, void* )
+{
+ ContextMenuEvent* pEv = (ContextMenuEvent*)pCEvent;
+
+ if( ! pEv->aDelData.IsDelete() )
+ {
+ pEv->pWindow->ImplRemoveDel( &pEv->aDelData );
+ ImplCallCommand( pEv->pWindow, COMMAND_CONTEXTMENU, NULL, TRUE, &pEv->aChildPos );
+ }
+ delete pEv;
+
+ return 0;
+}
+
+long ImplHandleMouseEvent( Window* pWindow, USHORT nSVEvent, BOOL bMouseLeave,
+ long nX, long nY, ULONG nMsgTime,
+ USHORT nCode, USHORT nMode )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Point aMousePos( nX, nY );
+ Window* pChild;
+ long nRet;
+ USHORT nClicks;
+ ImplFrameData* pWinFrameData = pWindow->ImplGetFrameData();
+ USHORT nOldCode = pWinFrameData->mnMouseCode;
+
+ // we need a mousemove event, befor we get a mousebuttondown or a
+ // mousebuttonup event
+ if ( (nSVEvent == EVENT_MOUSEBUTTONDOWN) ||
+ (nSVEvent == EVENT_MOUSEBUTTONUP) )
+ {
+ if ( (nSVEvent == EVENT_MOUSEBUTTONUP) && pSVData->maHelpData.mbExtHelpMode )
+ Help::EndExtHelp();
+ if ( pSVData->maHelpData.mpHelpWin )
+ {
+ if( pWindow->ImplGetWindow() == pSVData->maHelpData.mpHelpWin )
+ {
+ ImplDestroyHelpWindow( false );
+ return 1; // pWindow is dead now - avoid crash!
+ }
+ else
+ ImplDestroyHelpWindow( true );
+ }
+
+ if ( (pWinFrameData->mnLastMouseX != nX) ||
+ (pWinFrameData->mnLastMouseY != nY) )
+ {
+ ImplHandleMouseEvent( pWindow, EVENT_MOUSEMOVE, FALSE, nX, nY, nMsgTime, nCode, nMode );
+ }
+ }
+
+ // update frame data
+ pWinFrameData->mnBeforeLastMouseX = pWinFrameData->mnLastMouseX;
+ pWinFrameData->mnBeforeLastMouseY = pWinFrameData->mnLastMouseY;
+ pWinFrameData->mnLastMouseX = nX;
+ pWinFrameData->mnLastMouseY = nY;
+ pWinFrameData->mnMouseCode = nCode;
+ pWinFrameData->mnMouseMode = nMode & ~(MOUSE_SYNTHETIC | MOUSE_MODIFIERCHANGED);
+ if ( bMouseLeave )
+ {
+ pWinFrameData->mbMouseIn = FALSE;
+ if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp )
+ {
+ ImplDelData aDelData( pWindow );
+
+ ImplDestroyHelpWindow( true );
+
+ if ( aDelData.IsDelete() )
+ return 1; // pWindow is dead now - avoid crash! (#122045#)
+ }
+ }
+ else
+ pWinFrameData->mbMouseIn = TRUE;
+
+ DBG_ASSERT( !pSVData->maWinData.mpTrackWin ||
+ (pSVData->maWinData.mpTrackWin == pSVData->maWinData.mpCaptureWin),
+ "ImplHandleMouseEvent: TrackWin != CaptureWin" );
+
+ // AutoScrollMode
+ if ( pSVData->maWinData.mpAutoScrollWin && (nSVEvent == EVENT_MOUSEBUTTONDOWN) )
+ {
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ return 1;
+ }
+
+ // find mouse window
+ if ( pSVData->maWinData.mpCaptureWin )
+ {
+ pChild = pSVData->maWinData.mpCaptureWin;
+
+ DBG_ASSERT( pWindow == pChild->ImplGetFrameWindow(),
+ "ImplHandleMouseEvent: mouse event is not sent to capture window" );
+
+ // java client cannot capture mouse correctly
+ if ( pWindow != pChild->ImplGetFrameWindow() )
+ return 0;
+
+ if ( bMouseLeave )
+ return 0;
+ }
+ else
+ {
+ if ( bMouseLeave )
+ pChild = NULL;
+ else
+ pChild = pWindow->ImplFindWindow( aMousePos );
+ }
+
+ // test this because mouse events are buffered in the remote version
+ // and size may not be in sync
+ if ( !pChild && !bMouseLeave )
+ return 0;
+
+ // Ein paar Test ausfuehren und Message abfangen oder Status umsetzen
+ if ( pChild )
+ {
+ if( pChild->ImplIsAntiparallel() )
+ {
+ // - RTL - re-mirror frame pos at pChild
+ pChild->ImplReMirror( aMousePos );
+ }
+ // no mouse messages to system object windows ?
+ // !!!KA: Is it OK to comment this out? !!!
+// if ( pChild->ImplGetWindowImpl()->mpSysObj )
+// return 0;
+
+ // no mouse messages to disabled windows
+ // #106845# if the window was disabed during capturing we have to pass the mouse events to release capturing
+ if ( pSVData->maWinData.mpCaptureWin != pChild && (!pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode() ) )
+ {
+ ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave );
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ ImplHandleMouseHelpRequest( pChild, aMousePos );
+ if( pWinFrameData->mpMouseMoveWin != pChild )
+ nMode |= MOUSE_ENTERWINDOW;
+ }
+
+ // Call the hook also, if Window is disabled
+ Point aChildPos = pChild->ImplFrameToOutput( aMousePos );
+ MouseEvent aMEvt( aChildPos, pWinFrameData->mnClickCount, nMode, nCode, nCode );
+ NotifyEvent aNEvt( nSVEvent, pChild, &aMEvt );
+ Application::CallEventHooks( aNEvt );
+
+ if( pChild->IsCallHandlersOnInputDisabled() )
+ {
+ pWinFrameData->mpMouseMoveWin = pChild;
+ pChild->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
+ }
+
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ Sound::Beep( SOUND_DISABLE, pChild );
+ return 1;
+ }
+ else
+ {
+ // Set normal MousePointer for disabled windows
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ ImplSetMousePointer( pChild );
+
+ return 0;
+ }
+ }
+
+ // End ExtTextInput-Mode, if the user click in the same TopLevel Window
+ if ( pSVData->maWinData.mpExtTextInputWin &&
+ ((nSVEvent == EVENT_MOUSEBUTTONDOWN) ||
+ (nSVEvent == EVENT_MOUSEBUTTONUP)) )
+ pSVData->maWinData.mpExtTextInputWin->EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
+ }
+
+ // determine mouse event data
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ // Testen, ob MouseMove an das gleiche Fenster geht und sich der
+ // Status nicht geaendert hat
+ if ( pChild )
+ {
+ Point aChildMousePos = pChild->ImplFrameToOutput( aMousePos );
+ if ( !bMouseLeave &&
+ (pChild == pWinFrameData->mpMouseMoveWin) &&
+ (aChildMousePos.X() == pWinFrameData->mnLastMouseWinX) &&
+ (aChildMousePos.Y() == pWinFrameData->mnLastMouseWinY) &&
+ (nOldCode == pWinFrameData->mnMouseCode) )
+ {
+ // Mouse-Pointer neu setzen, da er sich geaendet haben
+ // koennte, da ein Modus umgesetzt wurde
+ ImplSetMousePointer( pChild );
+ return 0;
+ }
+
+ pWinFrameData->mnLastMouseWinX = aChildMousePos.X();
+ pWinFrameData->mnLastMouseWinY = aChildMousePos.Y();
+ }
+
+ // mouse click
+ nClicks = pWinFrameData->mnClickCount;
+
+ // Gegebenenfalls den Start-Drag-Handler rufen.
+ // Achtung: Muss vor Move gerufen werden, da sonst bei schnellen
+ // Mausbewegungen die Applikationen in den Selektionszustand gehen.
+ Window* pMouseDownWin = pWinFrameData->mpMouseDownWin;
+ if ( pMouseDownWin )
+ {
+ // Testen, ob StartDrag-Modus uebereinstimmt. Wir vergleichen nur
+ // den Status der Maustasten, damit man mit Mod1 z.B. sofort
+ // in den Kopiermodus gehen kann.
+ const MouseSettings& rMSettings = pMouseDownWin->GetSettings().GetMouseSettings();
+ if ( (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
+ (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) )
+ {
+ if ( !pMouseDownWin->ImplGetFrameData()->mbStartDragCalled )
+ {
+ long nDragW = rMSettings.GetStartDragWidth();
+ long nDragH = rMSettings.GetStartDragWidth();
+ //long nMouseX = nX;
+ //long nMouseY = nY;
+ long nMouseX = aMousePos.X(); // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
+ long nMouseY = aMousePos.Y();
+ if ( !(((nMouseX-nDragW) <= pMouseDownWin->ImplGetFrameData()->mnFirstMouseX) &&
+ ((nMouseX+nDragW) >= pMouseDownWin->ImplGetFrameData()->mnFirstMouseX)) ||
+ !(((nMouseY-nDragH) <= pMouseDownWin->ImplGetFrameData()->mnFirstMouseY) &&
+ ((nMouseY+nDragH) >= pMouseDownWin->ImplGetFrameData()->mnFirstMouseY)) )
+ {
+ pMouseDownWin->ImplGetFrameData()->mbStartDragCalled = TRUE;
+
+ // Check if drag source provides it's own recognizer
+ if( pMouseDownWin->ImplGetFrameData()->mbInternalDragGestureRecognizer )
+ {
+ // query DropTarget from child window
+ ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer =
+ ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragGestureRecognizer > ( pMouseDownWin->ImplGetWindowImpl()->mxDNDListenerContainer,
+ ::com::sun::star::uno::UNO_QUERY );
+
+ if( xDragGestureRecognizer.is() )
+ {
+ // retrieve mouse position relative to mouse down window
+ Point relLoc = pMouseDownWin->ImplFrameToOutput( Point(
+ pMouseDownWin->ImplGetFrameData()->mnFirstMouseX,
+ pMouseDownWin->ImplGetFrameData()->mnFirstMouseY ) );
+
+ // create a uno mouse event out of the available data
+ ::com::sun::star::awt::MouseEvent aMouseEvent(
+ static_cast < ::com::sun::star::uno::XInterface * > ( 0 ),
+#ifdef MACOSX
+ nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3),
+#else
+ nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2),
+#endif
+ nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE),
+ nMouseX,
+ nMouseY,
+ nClicks,
+ sal_False );
+
+ ULONG nCount = Application::ReleaseSolarMutex();
+
+ // FIXME: where do I get Action from ?
+ ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragSource > xDragSource = pMouseDownWin->GetDragSource();
+
+ if( xDragSource.is() )
+ {
+ static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent( 0,
+ relLoc.X(), relLoc.Y(), xDragSource, ::com::sun::star::uno::makeAny( aMouseEvent ) );
+ }
+
+ Application::AcquireSolarMutex( nCount );
+ }
+ }
+ }
+ }
+ }
+ else
+ pMouseDownWin->ImplGetFrameData()->mbStartDragCalled = TRUE;
+ }
+
+ // test for mouseleave and mouseenter
+ Window* pMouseMoveWin = pWinFrameData->mpMouseMoveWin;
+ if ( pChild != pMouseMoveWin )
+ {
+ if ( pMouseMoveWin )
+ {
+ Point aLeaveMousePos = pMouseMoveWin->ImplFrameToOutput( aMousePos );
+ MouseEvent aMLeaveEvt( aLeaveMousePos, nClicks, nMode | MOUSE_LEAVEWINDOW, nCode, nCode );
+ NotifyEvent aNLeaveEvt( EVENT_MOUSEMOVE, pMouseMoveWin, &aMLeaveEvt );
+ ImplDelData aDelData;
+ ImplDelData aDelData2;
+ pWinFrameData->mbInMouseMove = TRUE;
+ pMouseMoveWin->ImplGetWinData()->mbMouseOver = FALSE;
+ pMouseMoveWin->ImplAddDel( &aDelData );
+ // Durch MouseLeave kann auch dieses Fenster zerstoert
+ // werden
+ if ( pChild )
+ pChild->ImplAddDel( &aDelData2 );
+ if ( !ImplCallPreNotify( aNLeaveEvt ) )
+ {
+ pMouseMoveWin->MouseMove( aMLeaveEvt );
+ // #82968#
+ if( !aDelData.IsDelete() )
+ aNLeaveEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNLeaveEvt );
+ }
+
+ pWinFrameData->mpMouseMoveWin = NULL;
+ pWinFrameData->mbInMouseMove = FALSE;
+
+ if ( pChild )
+ {
+ if ( aDelData2.IsDelete() )
+ pChild = NULL;
+ else
+ pChild->ImplRemoveDel( &aDelData2 );
+ }
+ if ( aDelData.IsDelete() )
+ return 1;
+ pMouseMoveWin->ImplRemoveDel( &aDelData );
+ }
+
+ nMode |= MOUSE_ENTERWINDOW;
+ }
+ pWinFrameData->mpMouseMoveWin = pChild;
+ if( pChild )
+ pChild->ImplGetWinData()->mbMouseOver = TRUE;
+
+ // MouseLeave
+ if ( !pChild )
+ return 0;
+ }
+ else
+ {
+ // mouse click
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ const MouseSettings& rMSettings = pChild->GetSettings().GetMouseSettings();
+ ULONG nDblClkTime = rMSettings.GetDoubleClickTime();
+ long nDblClkW = rMSettings.GetDoubleClickWidth();
+ long nDblClkH = rMSettings.GetDoubleClickHeight();
+ //long nMouseX = nX;
+ //long nMouseY = nY;
+ long nMouseX = aMousePos.X(); // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
+ long nMouseY = aMousePos.Y();
+
+ if ( (pChild == pChild->ImplGetFrameData()->mpMouseDownWin) &&
+ (nCode == pChild->ImplGetFrameData()->mnFirstMouseCode) &&
+ ((nMsgTime-pChild->ImplGetFrameData()->mnMouseDownTime) < nDblClkTime) &&
+ ((nMouseX-nDblClkW) <= pChild->ImplGetFrameData()->mnFirstMouseX) &&
+ ((nMouseX+nDblClkW) >= pChild->ImplGetFrameData()->mnFirstMouseX) &&
+ ((nMouseY-nDblClkH) <= pChild->ImplGetFrameData()->mnFirstMouseY) &&
+ ((nMouseY+nDblClkH) >= pChild->ImplGetFrameData()->mnFirstMouseY) )
+ {
+ pChild->ImplGetFrameData()->mnClickCount++;
+ pChild->ImplGetFrameData()->mbStartDragCalled = TRUE;
+ }
+ else
+ {
+ pChild->ImplGetFrameData()->mpMouseDownWin = pChild;
+ pChild->ImplGetFrameData()->mnClickCount = 1;
+ pChild->ImplGetFrameData()->mnFirstMouseX = nMouseX;
+ pChild->ImplGetFrameData()->mnFirstMouseY = nMouseY;
+ pChild->ImplGetFrameData()->mnFirstMouseCode = nCode;
+ pChild->ImplGetFrameData()->mbStartDragCalled = !((nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
+ (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)));
+ }
+ pChild->ImplGetFrameData()->mnMouseDownTime = nMsgTime;
+ }
+ nClicks = pChild->ImplGetFrameData()->mnClickCount;
+
+ pSVData->maAppData.mnLastInputTime = Time::GetSystemTicks();
+ }
+
+ DBG_ASSERT( pChild, "ImplHandleMouseEvent: pChild == NULL" );
+
+ // create mouse event
+ Point aChildPos = pChild->ImplFrameToOutput( aMousePos );
+ MouseEvent aMEvt( aChildPos, nClicks, nMode, nCode, nCode );
+
+ // tracking window gets the mouse events
+ if ( pSVData->maWinData.mpTrackWin )
+ pChild = pSVData->maWinData.mpTrackWin;
+
+ // handle FloatingMode
+ if ( !pSVData->maWinData.mpTrackWin && pSVData->maWinData.mpFirstFloat )
+ {
+ ImplDelData aDelData;
+ pChild->ImplAddDel( &aDelData );
+ if ( ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave ) )
+ {
+ if ( !aDelData.IsDelete() )
+ {
+ pChild->ImplRemoveDel( &aDelData );
+ pChild->ImplGetFrameData()->mbStartDragCalled = TRUE;
+ }
+ return 1;
+ }
+ else
+ pChild->ImplRemoveDel( &aDelData );
+ }
+
+ // call handler
+ BOOL bDrag = FALSE;
+ BOOL bCallHelpRequest = TRUE;
+ DBG_ASSERT( pChild, "ImplHandleMouseEvent: pChild is NULL" );
+
+ ImplDelData aDelData;
+ NotifyEvent aNEvt( nSVEvent, pChild, &aMEvt );
+ pChild->ImplAddDel( &aDelData );
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ pChild->ImplGetFrameData()->mbInMouseMove = TRUE;
+
+ // bring window into foreground on mouseclick
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ if( !pSVData->maWinData.mpFirstFloat && // totop for floating windows in popup would change the focus and would close them immediately
+ !(pChild->ImplGetFrameWindow()->GetStyle() & WB_OWNERDRAWDECORATION) ) // ownerdrawdecorated windows must never grab focus
+ pChild->ToTop();
+ if ( aDelData.IsDelete() )
+ return 1;
+ }
+
+ if ( ImplCallPreNotify( aNEvt ) || aDelData.IsDelete() )
+ nRet = 1;
+ else
+ {
+ nRet = 0;
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ if ( pSVData->maWinData.mpTrackWin )
+ {
+ TrackingEvent aTEvt( aMEvt );
+ pChild->Tracking( aTEvt );
+ if ( !aDelData.IsDelete() )
+ {
+ // When ScrollRepeat, we restart the timer
+ if ( pSVData->maWinData.mpTrackTimer &&
+ (pSVData->maWinData.mnTrackFlags & STARTTRACK_SCROLLREPEAT) )
+ pSVData->maWinData.mpTrackTimer->Start();
+ }
+ bCallHelpRequest = FALSE;
+ nRet = 1;
+ }
+ else
+ {
+ // Auto-ToTop
+ if ( !pSVData->maWinData.mpCaptureWin &&
+ (pChild->GetSettings().GetMouseSettings().GetOptions() & MOUSE_OPTION_AUTOFOCUS) )
+ pChild->ToTop( TOTOP_NOGRABFOCUS );
+
+ if( aDelData.IsDelete() )
+ bCallHelpRequest = FALSE;
+ else
+ {
+ // if the MouseMove handler changes the help window's visibility
+ // the HelpRequest handler should not be called anymore
+ Window* pOldHelpTextWin = pSVData->maHelpData.mpHelpWin;
+ pChild->ImplGetWindowImpl()->mbMouseMove = FALSE;
+ pChild->MouseMove( aMEvt );
+ if ( pOldHelpTextWin != pSVData->maHelpData.mpHelpWin )
+ bCallHelpRequest = FALSE;
+ }
+ }
+ }
+ else if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( pSVData->maWinData.mpTrackWin &&
+ !(pSVData->maWinData.mnTrackFlags & STARTTRACK_MOUSEBUTTONDOWN) )
+ nRet = 1;
+ else
+ {
+ pChild->ImplGetWindowImpl()->mbMouseButtonDown = FALSE;
+ pChild->MouseButtonDown( aMEvt );
+ }
+ }
+ else
+ {
+ if ( pSVData->maWinData.mpTrackWin )
+ {
+ pChild->EndTracking();
+ nRet = 1;
+ }
+ else
+ {
+ pChild->ImplGetWindowImpl()->mbMouseButtonUp = FALSE;
+ pChild->MouseButtonUp( aMEvt );
+ }
+ }
+
+ // #82968#
+ if ( !aDelData.IsDelete() )
+ aNEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
+ }
+
+ if ( aDelData.IsDelete() )
+ return 1;
+
+
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ pChild->ImplGetWindowImpl()->mpFrameData->mbInMouseMove = FALSE;
+
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ if ( bCallHelpRequest && !pSVData->maHelpData.mbKeyboardHelp )
+ ImplHandleMouseHelpRequest( pChild, pChild->OutputToScreenPixel( aMEvt.GetPosPixel() ) );
+ nRet = 1;
+ }
+ else if ( !nRet )
+ {
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( !pChild->ImplGetWindowImpl()->mbMouseButtonDown )
+ nRet = 1;
+ }
+ else
+ {
+ if ( !pChild->ImplGetWindowImpl()->mbMouseButtonUp )
+ nRet = 1;
+ }
+ }
+
+ pChild->ImplRemoveDel( &aDelData );
+
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ // set new mouse pointer
+ if ( !bMouseLeave )
+ ImplSetMousePointer( pChild );
+ }
+ else if ( (nSVEvent == EVENT_MOUSEBUTTONDOWN) || (nSVEvent == EVENT_MOUSEBUTTONUP) )
+ {
+ if ( !bDrag )
+ {
+ // Command-Events
+ if ( /*(nRet == 0) &&*/ (nClicks == 1) && (nSVEvent == EVENT_MOUSEBUTTONDOWN) &&
+ (nCode == MOUSE_MIDDLE) )
+ {
+ USHORT nMiddleAction = pChild->GetSettings().GetMouseSettings().GetMiddleButtonAction();
+ if ( nMiddleAction == MOUSE_MIDDLE_AUTOSCROLL )
+ nRet = !ImplCallCommand( pChild, COMMAND_STARTAUTOSCROLL, NULL, TRUE, &aChildPos );
+ else if ( nMiddleAction == MOUSE_MIDDLE_PASTESELECTION )
+ nRet = !ImplCallCommand( pChild, COMMAND_PASTESELECTION, NULL, TRUE, &aChildPos );
+ }
+ else
+ {
+ // ContextMenu
+ const MouseSettings& rMSettings = pChild->GetSettings().GetMouseSettings();
+ if ( (nCode == rMSettings.GetContextMenuCode()) &&
+ (nClicks == rMSettings.GetContextMenuClicks()) )
+ {
+ BOOL bContextMenu;
+ if ( rMSettings.GetContextMenuDown() )
+ bContextMenu = (nSVEvent == EVENT_MOUSEBUTTONDOWN);
+ else
+ bContextMenu = (nSVEvent == EVENT_MOUSEBUTTONUP);
+ if ( bContextMenu )
+ {
+ if( pSVData->maAppData.mpActivePopupMenu )
+ {
+ /* #i34277# there already is a context menu open
+ * that was probably just closed with EndPopupMode.
+ * We need to give the eventual corresponding
+ * PopupMenu::Execute a chance to end properly.
+ * Therefore delay context menu command and
+ * issue only after popping one frame of the
+ * Yield stack.
+ */
+ ContextMenuEvent* pEv = new ContextMenuEvent;
+ pEv->pWindow = pChild;
+ pEv->aChildPos = aChildPos;
+ pChild->ImplAddDel( &pEv->aDelData );
+ Application::PostUserEvent( Link( pEv, ContextMenuEventLink ) );
+ }
+ else
+ nRet = ! ImplCallCommand( pChild, COMMAND_CONTEXTMENU, NULL, TRUE, &aChildPos );
+ }
+ }
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetKeyInputWindow( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // determine last input time
+ pSVData->maAppData.mnLastInputTime = Time::GetSystemTicks();
+
+ // #127104# workaround for destroyed windows
+ if( pWindow->ImplGetWindowImpl() == NULL )
+ return 0;
+
+ // find window - is every time the window which has currently the
+ // focus or the last time the focus.
+ // the first floating window always has the focus
+ Window* pChild = pSVData->maWinData.mpFirstFloat;
+ if( !pChild || ( pChild->ImplGetWindowImpl()->mbFloatWin && !((FloatingWindow *)pChild)->GrabsFocus() ) )
+ pChild = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
+ else
+ {
+ // allow floaters to forward keyinput to some member
+ pChild = pChild->GetPreferredKeyInputWindow();
+ }
+
+ // no child - than no input
+ if ( !pChild )
+ return 0;
+
+ // We call also KeyInput if we haven't the focus, because on Unix
+ // system this is often the case when a Lookup Choise Window has
+ // the focus - because this windows send the KeyInput directly to
+ // the window without resetting the focus
+ DBG_ASSERTWARNING( pChild == pSVData->maWinData.mpFocusWin,
+ "ImplHandleKey: Keyboard-Input is sent to a frame without focus" );
+
+ // no keyinput to disabled windows
+ if ( !pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode() )
+ return 0;
+
+ return pChild;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleKey( Window* pWindow, USHORT nSVEvent,
+ USHORT nKeyCode, USHORT nCharCode, USHORT nRepeat, BOOL bForward )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ KeyCode aKeyCode( nKeyCode, nKeyCode );
+ USHORT nEvCode = aKeyCode.GetCode();
+
+ // allow application key listeners to remove the key event
+ // but make sure we're not forwarding external KeyEvents, (ie where bForward is FALSE)
+ // becasue those are coming back from the listener itself and MUST be processed
+ KeyEvent aKeyEvent( (xub_Unicode)nCharCode, aKeyCode, nRepeat );
+ if( bForward )
+ {
+ USHORT nVCLEvent;
+ switch( nSVEvent )
+ {
+ case EVENT_KEYINPUT:
+ nVCLEvent = VCLEVENT_WINDOW_KEYINPUT;
+ break;
+ case EVENT_KEYUP:
+ nVCLEvent = VCLEVENT_WINDOW_KEYUP;
+ break;
+ default:
+ nVCLEvent = 0;
+ break;
+ }
+ if( nVCLEvent && pSVData->mpApp->HandleKey( nVCLEvent, pWindow, &aKeyEvent ) )
+ return 1;
+ }
+
+ // #i1820# use locale specific decimal separator
+ if( nEvCode == KEY_DECIMAL )
+ {
+ if( Application::GetSettings().GetMiscSettings().GetEnableLocalizedDecimalSep() )
+ {
+ String aSep( pWindow->GetSettings().GetLocaleDataWrapper().getNumDecimalSep() );
+ nCharCode = (USHORT) aSep.GetChar(0);
+ }
+ }
+
+ BOOL bCtrlF6 = (aKeyCode.GetCode() == KEY_F6) && aKeyCode.IsMod1();
+
+ // determine last input time
+ pSVData->maAppData.mnLastInputTime = Time::GetSystemTicks();
+
+ // handle tracking window
+ if ( nSVEvent == EVENT_KEYINPUT )
+ {
+#ifdef DBG_UTIL
+ // #105224# use Ctrl-Alt-Shift-D, Ctrl-Shift-D must be useable by app
+ if ( aKeyCode.IsShift() && aKeyCode.IsMod1() && (aKeyCode.IsMod2() || aKeyCode.IsMod3()) && (aKeyCode.GetCode() == KEY_D) )
+ {
+ DBGGUI_START();
+ return 1;
+ }
+#endif
+
+ if ( pSVData->maHelpData.mbExtHelpMode )
+ {
+ Help::EndExtHelp();
+ if ( nEvCode == KEY_ESCAPE )
+ return 1;
+ }
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow( false );
+
+ // AutoScrollMode
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ {
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ if ( nEvCode == KEY_ESCAPE )
+ return 1;
+ }
+
+ if ( pSVData->maWinData.mpTrackWin )
+ {
+ USHORT nOrigCode = aKeyCode.GetCode();
+
+ if ( (nOrigCode == KEY_ESCAPE) && !(pSVData->maWinData.mnTrackFlags & STARTTRACK_NOKEYCANCEL) )
+ {
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL | ENDTRACK_KEY );
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ if ( !(pLastLevelFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOKEYCLOSE) )
+ {
+ USHORT nEscCode = aKeyCode.GetCode();
+
+ if ( nEscCode == KEY_ESCAPE )
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+ }
+ return 1;
+ }
+ else if ( nOrigCode == KEY_RETURN )
+ {
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_KEY );
+ return 1;
+ }
+ else if ( !(pSVData->maWinData.mnTrackFlags & STARTTRACK_KEYINPUT) )
+ return 1;
+ }
+
+ // handle FloatingMode
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ if ( !(pLastLevelFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOKEYCLOSE) )
+ {
+ USHORT nCode = aKeyCode.GetCode();
+
+ if ( (nCode == KEY_ESCAPE) || bCtrlF6)
+ {
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ if( !bCtrlF6 )
+ return 1;
+ }
+ }
+ }
+
+ // test for accel
+ if ( pSVData->maAppData.mpAccelMgr )
+ {
+ if ( pSVData->maAppData.mpAccelMgr->IsAccelKey( aKeyCode, nRepeat ) )
+ return 1;
+ }
+ }
+
+ // find window
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ if ( !pChild )
+ return 0;
+
+ // --- RTL --- mirror cursor keys
+ if( (aKeyCode.GetCode() == KEY_LEFT || aKeyCode.GetCode() == KEY_RIGHT) &&
+ pChild->ImplHasMirroredGraphics() && pChild->IsRTLEnabled() )
+ aKeyCode = KeyCode( aKeyCode.GetCode() == KEY_LEFT ? KEY_RIGHT : KEY_LEFT, aKeyCode.GetModifier() );
+
+ // call handler
+ ImplDelData aDelData;
+ pChild->ImplAddDel( &aDelData );
+
+ KeyEvent aKeyEvt( (xub_Unicode)nCharCode, aKeyCode, nRepeat );
+ NotifyEvent aNotifyEvt( nSVEvent, pChild, &aKeyEvt );
+ BOOL bKeyPreNotify = (ImplCallPreNotify( aNotifyEvt ) != 0);
+ long nRet = 1;
+
+ if ( !bKeyPreNotify && !aDelData.IsDelete() )
+ {
+ if ( nSVEvent == EVENT_KEYINPUT )
+ {
+ pChild->ImplGetWindowImpl()->mbKeyInput = FALSE;
+ pChild->KeyInput( aKeyEvt );
+ }
+ else
+ {
+ pChild->ImplGetWindowImpl()->mbKeyUp = FALSE;
+ pChild->KeyUp( aKeyEvt );
+ }
+ // #82968#
+ if( !aDelData.IsDelete() )
+ aNotifyEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNotifyEvt );
+ }
+
+ if ( aDelData.IsDelete() )
+ return 1;
+
+ pChild->ImplRemoveDel( &aDelData );
+
+ if ( nSVEvent == EVENT_KEYINPUT )
+ {
+ if ( !bKeyPreNotify && pChild->ImplGetWindowImpl()->mbKeyInput )
+ {
+ USHORT nCode = aKeyCode.GetCode();
+
+ // #101999# is focus in or below toolbox
+ BOOL bToolboxFocus=FALSE;
+ if( (nCode == KEY_F1) && aKeyCode.IsShift() )
+ {
+ Window *pWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
+ while( pWin )
+ {
+ if( pWin->ImplGetWindowImpl()->mbToolBox )
+ {
+ bToolboxFocus = TRUE;
+ break;
+ }
+ else
+ pWin = pWin->GetParent();
+ }
+ }
+
+ // ContextMenu
+ if ( (nCode == KEY_CONTEXTMENU) || ((nCode == KEY_F10) && aKeyCode.IsShift() && !aKeyCode.IsMod1() && !aKeyCode.IsMod2() ) )
+ nRet = !ImplCallCommand( pChild, COMMAND_CONTEXTMENU, NULL, FALSE );
+ else if ( ( (nCode == KEY_F2) && aKeyCode.IsShift() ) || ( (nCode == KEY_F1) && aKeyCode.IsMod1() ) ||
+ // #101999# no active help when focus in toolbox, simulate BallonHelp instead
+ ( (nCode == KEY_F1) && aKeyCode.IsShift() && bToolboxFocus ) )
+ {
+ // TipHelp via Keyboard (Shift-F2 or Ctrl-F1)
+ // simulate mouseposition at center of window
+
+ Size aSize = pChild->GetOutputSize();
+ Point aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
+ aPos = pChild->OutputToScreenPixel( aPos );
+
+ HelpEvent aHelpEvent( aPos, HELPMODE_BALLOON );
+ aHelpEvent.SetKeyboardActivated( TRUE );
+ pSVData->maHelpData.mbSetKeyboardHelp = TRUE;
+ pChild->RequestHelp( aHelpEvent );
+ pSVData->maHelpData.mbSetKeyboardHelp = FALSE;
+ }
+ else if ( (nCode == KEY_F1) || (nCode == KEY_HELP) )
+ {
+ if ( !aKeyCode.GetModifier() )
+ {
+ if ( pSVData->maHelpData.mbContextHelp )
+ {
+ Point aMousePos = pChild->OutputToScreenPixel( pChild->GetPointerPosPixel() );
+ HelpEvent aHelpEvent( aMousePos, HELPMODE_CONTEXT );
+ pChild->RequestHelp( aHelpEvent );
+ }
+ else
+ nRet = 0;
+ }
+ else if ( aKeyCode.IsShift() )
+ {
+ if ( pSVData->maHelpData.mbExtHelp )
+ Help::StartExtHelp();
+ else
+ nRet = 0;
+ }
+ }
+ else
+ {
+ if ( ImplCallHotKey( aKeyCode ) )
+ nRet = 1;
+ else
+ nRet = 0;
+ }
+ }
+ }
+ else
+ {
+ if ( !bKeyPreNotify && pChild->ImplGetWindowImpl()->mbKeyUp )
+ nRet = 0;
+ }
+
+ // #105591# send keyinput to parent if we are a floating window and the key was not pocessed yet
+ if( !nRet && pWindow->ImplGetWindowImpl()->mbFloatWin && pWindow->GetParent() && (pWindow->ImplGetWindowImpl()->mpFrame != pWindow->GetParent()->ImplGetWindowImpl()->mpFrame) )
+ {
+ pChild = pWindow->GetParent();
+
+ // call handler
+ ImplDelData aChildDelData( pChild );
+ KeyEvent aKEvt( (xub_Unicode)nCharCode, aKeyCode, nRepeat );
+ NotifyEvent aNEvt( nSVEvent, pChild, &aKEvt );
+ BOOL bPreNotify = (ImplCallPreNotify( aNEvt ) != 0);
+ if ( aChildDelData.IsDelete() )
+ return 1;
+
+ if ( !bPreNotify )
+ {
+ if ( nSVEvent == EVENT_KEYINPUT )
+ {
+ pChild->ImplGetWindowImpl()->mbKeyInput = FALSE;
+ pChild->KeyInput( aKEvt );
+ }
+ else
+ {
+ pChild->ImplGetWindowImpl()->mbKeyUp = FALSE;
+ pChild->KeyUp( aKEvt );
+ }
+ // #82968#
+ if( !aChildDelData.IsDelete() )
+ aNEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
+ if ( aChildDelData.IsDelete() )
+ return 1;
+ }
+
+ if( bPreNotify || !pChild->ImplGetWindowImpl()->mbKeyInput )
+ nRet = 1;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleExtTextInput( Window* pWindow,
+ const XubString& rText,
+ const USHORT* pTextAttr,
+ ULONG nCursorPos, USHORT nCursorFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pChild = NULL;
+
+ int nTries = 200;
+ while( nTries-- )
+ {
+ pChild = pSVData->maWinData.mpExtTextInputWin;
+ if ( !pChild )
+ {
+ pChild = ImplGetKeyInputWindow( pWindow );
+ if ( !pChild )
+ return 0;
+ }
+ if( !pChild->ImplGetWindowImpl()->mpFrameData->mnFocusId )
+ break;
+ Application::Yield();
+ }
+
+ // If it is the first ExtTextInput call, we inform the information
+ // and allocate the data, which we must store in this mode
+ ImplWinData* pWinData = pChild->ImplGetWinData();
+ if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
+ {
+ pChild->ImplGetWindowImpl()->mbExtTextInput = TRUE;
+ if ( !pWinData->mpExtOldText )
+ pWinData->mpExtOldText = new UniString;
+ else
+ pWinData->mpExtOldText->Erase();
+ if ( pWinData->mpExtOldAttrAry )
+ {
+ delete [] pWinData->mpExtOldAttrAry;
+ pWinData->mpExtOldAttrAry = NULL;
+ }
+ pSVData->maWinData.mpExtTextInputWin = pChild;
+ ImplCallCommand( pChild, COMMAND_STARTEXTTEXTINPUT );
+ }
+
+ // be aware of being recursively called in StartExtTextInput
+ if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
+ return 0;
+
+ // Test for changes
+ BOOL bOnlyCursor = FALSE;
+ xub_StrLen nMinLen = Min( pWinData->mpExtOldText->Len(), rText.Len() );
+ xub_StrLen nDeltaStart = 0;
+ while ( nDeltaStart < nMinLen )
+ {
+ if ( pWinData->mpExtOldText->GetChar( nDeltaStart ) != rText.GetChar( nDeltaStart ) )
+ break;
+ nDeltaStart++;
+ }
+ if ( pWinData->mpExtOldAttrAry || pTextAttr )
+ {
+ if ( !pWinData->mpExtOldAttrAry || !pTextAttr )
+ nDeltaStart = 0;
+ else
+ {
+ xub_StrLen i = 0;
+ while ( i < nDeltaStart )
+ {
+ if ( pWinData->mpExtOldAttrAry[i] != pTextAttr[i] )
+ {
+ nDeltaStart = i;
+ break;
+ }
+ i++;
+ }
+ }
+ }
+ if ( (nDeltaStart >= nMinLen) &&
+ (pWinData->mpExtOldText->Len() == rText.Len()) )
+ bOnlyCursor = TRUE;
+
+ // Call Event and store the information
+ CommandExtTextInputData aData( rText, pTextAttr,
+ (xub_StrLen)nCursorPos, nCursorFlags,
+ nDeltaStart, pWinData->mpExtOldText->Len(),
+ bOnlyCursor );
+ *pWinData->mpExtOldText = rText;
+ if ( pWinData->mpExtOldAttrAry )
+ {
+ delete [] pWinData->mpExtOldAttrAry;
+ pWinData->mpExtOldAttrAry = NULL;
+ }
+ if ( pTextAttr )
+ {
+ pWinData->mpExtOldAttrAry = new USHORT[rText.Len()];
+ memcpy( pWinData->mpExtOldAttrAry, pTextAttr, rText.Len()*sizeof( USHORT ) );
+ }
+ return !ImplCallCommand( pChild, COMMAND_EXTTEXTINPUT, &aData );
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleEndExtTextInput( Window* /* pWindow */ )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pChild = pSVData->maWinData.mpExtTextInputWin;
+ long nRet = 0;
+
+ if ( pChild )
+ {
+ pChild->ImplGetWindowImpl()->mbExtTextInput = FALSE;
+ pSVData->maWinData.mpExtTextInputWin = NULL;
+ ImplWinData* pWinData = pChild->ImplGetWinData();
+ if ( pWinData->mpExtOldText )
+ {
+ delete pWinData->mpExtOldText;
+ pWinData->mpExtOldText = NULL;
+ }
+ if ( pWinData->mpExtOldAttrAry )
+ {
+ delete [] pWinData->mpExtOldAttrAry;
+ pWinData->mpExtOldAttrAry = NULL;
+ }
+ nRet = !ImplCallCommand( pChild, COMMAND_ENDEXTTEXTINPUT );
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleExtTextInputPos( Window* pWindow,
+ Rectangle& rRect, long& rInputWidth,
+ bool * pVertical )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pChild = pSVData->maWinData.mpExtTextInputWin;
+
+ if ( !pChild )
+ pChild = ImplGetKeyInputWindow( pWindow );
+ else
+ {
+ // Test, if the Window is related to the frame
+ if ( !pWindow->ImplIsWindowOrChild( pChild ) )
+ pChild = ImplGetKeyInputWindow( pWindow );
+ }
+
+ if ( pChild )
+ {
+ ImplCallCommand( pChild, COMMAND_CURSORPOS );
+ const Rectangle* pRect = pChild->GetCursorRect();
+ if ( pRect )
+ rRect = pChild->ImplLogicToDevicePixel( *pRect );
+ else
+ {
+ Cursor* pCursor = pChild->GetCursor();
+ if ( pCursor )
+ {
+ Point aPos = pChild->ImplLogicToDevicePixel( pCursor->GetPos() );
+ Size aSize = pChild->LogicToPixel( pCursor->GetSize() );
+ if ( !aSize.Width() )
+ aSize.Width() = pChild->GetSettings().GetStyleSettings().GetCursorSize();
+ rRect = Rectangle( aPos, aSize );
+ }
+ else
+ rRect = Rectangle( Point( pChild->GetOutOffXPixel(), pChild->GetOutOffYPixel() ), Size() );
+ }
+ rInputWidth = pChild->ImplLogicWidthToDevicePixel( pChild->GetCursorExtTextInputWidth() );
+ if ( !rInputWidth )
+ rInputWidth = rRect.GetWidth();
+ }
+ if (pVertical != 0)
+ *pVertical
+ = pChild != 0 && pChild->GetInputContext().GetFont().IsVertical();
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleInputContextChange( Window* pWindow, LanguageType eNewLang )
+{
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ CommandInputContextData aData( eNewLang );
+ return !ImplCallCommand( pChild, COMMAND_INPUTCONTEXTCHANGE, &aData );
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplCallWheelCommand( Window* pWindow, const Point& rPos,
+ const CommandWheelData* pWheelData )
+{
+ Point aCmdMousePos = pWindow->ImplFrameToOutput( rPos );
+ CommandEvent aCEvt( aCmdMousePos, COMMAND_WHEEL, TRUE, pWheelData );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
+ ImplDelData aDelData( pWindow );
+ BOOL bPreNotify = (ImplCallPreNotify( aNCmdEvt ) != 0);
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ if ( !bPreNotify )
+ {
+ pWindow->ImplGetWindowImpl()->mbCommand = FALSE;
+ pWindow->Command( aCEvt );
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ if ( pWindow->ImplGetWindowImpl()->mbCommand )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleWheelEvent( Window* pWindow, const SalWheelMouseEvent& rEvt )
+{
+ ImplDelData aDogTag( pWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow( true );
+ if( aDogTag.IsDelete() )
+ return 0;
+
+ USHORT nMode;
+ USHORT nCode = rEvt.mnCode;
+ bool bHorz = rEvt.mbHorz;
+ bool bPixel = rEvt.mbDeltaIsPixel;
+ if ( nCode & KEY_MOD1 )
+ nMode = COMMAND_WHEEL_ZOOM;
+ else if ( nCode & KEY_MOD2 )
+ nMode = COMMAND_WHEEL_DATAZOOM;
+ else
+ {
+ nMode = COMMAND_WHEEL_SCROLL;
+ // #i85450# interpret shift-wheel as horizontal wheel action
+ if( (nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)) == KEY_SHIFT )
+ bHorz = true;
+ }
+
+ CommandWheelData aWheelData( rEvt.mnDelta, rEvt.mnNotchDelta, rEvt.mnScrollLines, nMode, nCode, bHorz, bPixel );
+ Point aMousePos( rEvt.mnX, rEvt.mnY );
+ BOOL bRet = TRUE;
+
+ // first check any floating window ( eg. drop down listboxes)
+ bool bIsFloat = false;
+ Window *pMouseWindow = NULL;
+ if ( pSVData->maWinData.mpFirstFloat && !pSVData->maWinData.mpCaptureWin &&
+ !pSVData->maWinData.mpFirstFloat->ImplIsFloatPopupModeWindow( pWindow ) )
+ {
+ USHORT nHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
+ pMouseWindow = pSVData->maWinData.mpFirstFloat->ImplFloatHitTest( pWindow, aMousePos, nHitTest );
+ }
+ // then try the window directly beneath the mouse
+ if( !pMouseWindow )
+ pMouseWindow = pWindow->ImplFindWindow( aMousePos );
+ else
+ {
+ // transform coordinates to float window frame coordinates
+ pMouseWindow = pMouseWindow->ImplFindWindow(
+ pMouseWindow->OutputToScreenPixel(
+ pMouseWindow->AbsoluteScreenToOutputPixel(
+ pWindow->OutputToAbsoluteScreenPixel(
+ pWindow->ScreenToOutputPixel( aMousePos ) ) ) ) );
+ bIsFloat = true;
+ }
+
+ if ( pMouseWindow &&
+ pMouseWindow->IsEnabled() && pMouseWindow->IsInputEnabled() && ! pMouseWindow->IsInModalMode() )
+ {
+ // transform coordinates to float window frame coordinates
+ Point aRelMousePos( pMouseWindow->OutputToScreenPixel(
+ pMouseWindow->AbsoluteScreenToOutputPixel(
+ pWindow->OutputToAbsoluteScreenPixel(
+ pWindow->ScreenToOutputPixel( aMousePos ) ) ) ) );
+ bRet = ImplCallWheelCommand( pMouseWindow, aRelMousePos, &aWheelData );
+ }
+
+ // if the commad was not handled try the focus window
+ if ( bRet )
+ {
+ Window* pFocusWindow = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
+ if ( pFocusWindow && (pFocusWindow != pMouseWindow) &&
+ (pFocusWindow == pSVData->maWinData.mpFocusWin) )
+ {
+ // no wheel-messages to disabled windows
+ if ( pFocusWindow->IsEnabled() && pFocusWindow->IsInputEnabled() && ! pFocusWindow->IsInModalMode() )
+ {
+ // transform coordinates to focus window frame coordinates
+ Point aRelMousePos( pFocusWindow->OutputToScreenPixel(
+ pFocusWindow->AbsoluteScreenToOutputPixel(
+ pWindow->OutputToAbsoluteScreenPixel(
+ pWindow->ScreenToOutputPixel( aMousePos ) ) ) ) );
+ bRet = ImplCallWheelCommand( pFocusWindow, aRelMousePos, &aWheelData );
+ }
+ }
+ }
+
+ // close floaters
+ if( ! bIsFloat && pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ if( pLastLevelFloat )
+ {
+ ULONG nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
+ if ( nPopupFlags & FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE )
+ {
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+ }
+ }
+
+ return !bRet;
+}
+
+// -----------------------------------------------------------------------
+#define IMPL_PAINT_CHECKRTL ((USHORT)0x0020)
+
+static void ImplHandlePaint( Window* pWindow, const Rectangle& rBoundRect, bool bImmediateUpdate )
+{
+ // give up background save when sytem paints arrive
+ Window* pSaveBackWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFirstBackWin;
+ while ( pSaveBackWin )
+ {
+ Window* pNext = pSaveBackWin->ImplGetWindowImpl()->mpOverlapData->mpNextBackWin;
+ Rectangle aRect( Point( pSaveBackWin->GetOutOffXPixel(), pSaveBackWin->GetOutOffYPixel() ),
+ Size( pSaveBackWin->GetOutputWidthPixel(), pSaveBackWin->GetOutputHeightPixel() ) );
+ if ( aRect.IsOver( rBoundRect ) )
+ pSaveBackWin->ImplDeleteOverlapBackground();
+ pSaveBackWin = pNext;
+ }
+
+ // system paint events must be checked for re-mirroring
+ pWindow->ImplGetWindowImpl()->mnPaintFlags |= IMPL_PAINT_CHECKRTL;
+
+ // trigger paint for all windows that live in the new paint region
+ Region aRegion( rBoundRect );
+ pWindow->ImplInvalidateOverlapFrameRegion( aRegion );
+ if( bImmediateUpdate )
+ {
+ // #i87663# trigger possible pending resize notifications
+ // (GetSizePixel does that for us)
+ pWindow->GetSizePixel();
+ // force drawing inmmediately
+ pWindow->Update();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void KillOwnPopups( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window *pParent = pWindow->ImplGetWindowImpl()->mpFrameWindow;
+ Window *pChild = pSVData->maWinData.mpFirstFloat;
+ if ( pChild && pParent->ImplIsWindowOrChild( pChild, TRUE ) )
+ {
+ if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) )
+ pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplHandleResize( Window* pWindow, long nNewWidth, long nNewHeight )
+{
+ if( pWindow->GetStyle() & (WB_MOVEABLE|WB_SIZEABLE) )
+ {
+ KillOwnPopups( pWindow );
+ if( pWindow->ImplGetWindow() != ImplGetSVData()->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow( true );
+ }
+
+ if (
+ (nNewWidth > 0 && nNewHeight > 0) ||
+ pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize
+ )
+ {
+ if ( (nNewWidth != pWindow->GetOutputWidthPixel()) || (nNewHeight != pWindow->GetOutputHeightPixel()) )
+ {
+ pWindow->mnOutWidth = nNewWidth;
+ pWindow->mnOutHeight = nNewHeight;
+ pWindow->ImplGetWindowImpl()->mbWaitSystemResize = FALSE;
+ if ( pWindow->IsReallyVisible() )
+ pWindow->ImplSetClipFlag();
+ if ( pWindow->IsVisible() || pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize ||
+ ( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplGetWindowImpl()->mpClientWindow ) ) // propagate resize for system border windows
+ {
+ bool bStartTimer = true;
+ // use resize buffering for user resizes
+ // ownerdraw decorated windows and floating windows can be resized immediately (i.e. synchronously)
+ if( pWindow->ImplGetWindowImpl()->mbFrame && (pWindow->GetStyle() & WB_SIZEABLE)
+ && !(pWindow->GetStyle() & WB_OWNERDRAWDECORATION) // synchronous resize for ownerdraw decorated windows (toolbars)
+ && !pWindow->ImplGetWindowImpl()->mbFloatWin ) // synchronous resize for floating windows, #i43799#
+ {
+ if( pWindow->ImplGetWindowImpl()->mpClientWindow )
+ {
+ // #i42750# presentation wants to be informed about resize
+ // as early as possible
+ WorkWindow* pWorkWindow = dynamic_cast<WorkWindow*>(pWindow->ImplGetWindowImpl()->mpClientWindow);
+ if( pWorkWindow && pWorkWindow->IsPresentationMode() )
+ bStartTimer = false;
+ }
+ }
+ else
+ bStartTimer = false;
+
+ if( bStartTimer )
+ pWindow->ImplGetWindowImpl()->mpFrameData->maResizeTimer.Start();
+ else
+ pWindow->ImplCallResize(); // otherwise menues cannot be positioned
+ }
+ else
+ pWindow->ImplGetWindowImpl()->mbCallResize = TRUE;
+ }
+ }
+
+ pWindow->ImplGetWindowImpl()->mpFrameData->mbNeedSysWindow = (nNewWidth < IMPL_MIN_NEEDSYSWIN) ||
+ (nNewHeight < IMPL_MIN_NEEDSYSWIN);
+ BOOL bMinimized = (nNewWidth <= 0) || (nNewHeight <= 0);
+ if( bMinimized != pWindow->ImplGetWindowImpl()->mpFrameData->mbMinimized )
+ pWindow->ImplGetWindowImpl()->mpFrameWindow->ImplNotifyIconifiedState( bMinimized );
+ pWindow->ImplGetWindowImpl()->mpFrameData->mbMinimized = bMinimized;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleMove( Window* pWindow )
+{
+ if( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplIsFloatingWindow() && pWindow->IsReallyVisible() )
+ {
+ static_cast<FloatingWindow*>(pWindow)->EndPopupMode( FLOATWIN_POPUPMODEEND_TEAROFF );
+ pWindow->ImplCallMove();
+ }
+
+ if( pWindow->GetStyle() & (WB_MOVEABLE|WB_SIZEABLE) )
+ {
+ KillOwnPopups( pWindow );
+ if( pWindow->ImplGetWindow() != ImplGetSVData()->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow( true );
+ }
+
+ if ( pWindow->IsVisible() )
+ pWindow->ImplCallMove();
+ else
+ pWindow->ImplGetWindowImpl()->mbCallMove = TRUE; // make sure the framepos will be updated on the next Show()
+
+ if ( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplGetWindowImpl()->mpClientWindow )
+ pWindow->ImplGetWindowImpl()->mpClientWindow->ImplCallMove(); // notify client to update geometry
+
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleMoveResize( Window* pWindow, long nNewWidth, long nNewHeight )
+{
+ ImplHandleMove( pWindow );
+ ImplHandleResize( pWindow, nNewWidth, nNewHeight );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplActivateFloatingWindows( Window* pWindow, BOOL bActive )
+{
+ // Zuerst alle ueberlappenden Fenster ueberpruefen
+ Window* pTempWindow = pWindow->ImplGetWindowImpl()->mpFirstOverlap;
+ while ( pTempWindow )
+ {
+ if ( !pTempWindow->GetActivateMode() )
+ {
+ if ( (pTempWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ (pTempWindow->ImplGetWindow()->GetType() == WINDOW_FLOATINGWINDOW) )
+ ((ImplBorderWindow*)pTempWindow)->SetDisplayActive( bActive );
+ }
+
+ ImplActivateFloatingWindows( pTempWindow, bActive );
+ pTempWindow = pTempWindow->ImplGetWindowImpl()->mpNext;
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplAsyncFocusHdl, void*, EMPTYARG )
+{
+ ImplGetWindowImpl()->mpFrameData->mnFocusId = 0;
+
+ // Wenn Status erhalten geblieben ist, weil wir den Focus in der
+ // zwischenzeit schon wiederbekommen haben, brauchen wir auch
+ // nichts machen
+ BOOL bHasFocus = ImplGetWindowImpl()->mpFrameData->mbHasFocus || ImplGetWindowImpl()->mpFrameData->mbSysObjFocus;
+
+ // Dann die zeitverzoegerten Funktionen ausfuehren
+ if ( bHasFocus )
+ {
+ // Alle FloatingFenster deaktiv zeichnen
+ if ( ImplGetWindowImpl()->mpFrameData->mbStartFocusState != bHasFocus )
+ ImplActivateFloatingWindows( this, bHasFocus );
+
+ if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin )
+ {
+ BOOL bHandled = FALSE;
+ if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsInputEnabled() &&
+ ! ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsInModalMode() )
+ {
+ if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsEnabled() )
+ {
+ ImplGetWindowImpl()->mpFrameData->mpFocusWin->GrabFocus();
+ bHandled = TRUE;
+ }
+ else if( ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplHasDlgCtrl() )
+ {
+ // #109094# if the focus is restored to a disabled dialog control (was disabled meanwhile)
+ // try to move it to the next control
+ ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplDlgCtrlNextWindow();
+ bHandled = TRUE;
+ }
+ }
+ if ( !bHandled )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pTopLevelWindow = ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplGetFirstOverlapWindow();
+ if ( ( ! pTopLevelWindow->IsInputEnabled() || pTopLevelWindow->IsInModalMode() )
+ && pSVData->maWinData.mpLastExecuteDlg )
+ pSVData->maWinData.mpLastExecuteDlg->ToTop( TOTOP_RESTOREWHENMIN | TOTOP_GRABFOCUSONLY);
+ else
+ pTopLevelWindow->GrabFocus();
+ }
+ }
+ else
+ GrabFocus();
+ }
+ else
+ {
+ Window* pFocusWin = ImplGetWindowImpl()->mpFrameData->mpFocusWin;
+ if ( pFocusWin )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpFocusWin == pFocusWin )
+ {
+ // FocusWindow umsetzen
+ Window* pOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow();
+ pOverlapWindow->ImplGetWindowImpl()->mpLastFocusWindow = pFocusWin;
+ pSVData->maWinData.mpFocusWin = NULL;
+
+ if ( pFocusWin->ImplGetWindowImpl()->mpCursor )
+ pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide();
+
+ // Deaktivate rufen
+ Window* pOldFocusWindow = pFocusWin;
+ if ( pOldFocusWindow )
+ {
+ Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
+ Window* pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
+
+ pOldOverlapWindow->ImplGetWindowImpl()->mbActive = FALSE;
+ pOldOverlapWindow->Deactivate();
+ if ( pOldRealWindow != pOldOverlapWindow )
+ {
+ pOldRealWindow->ImplGetWindowImpl()->mbActive = FALSE;
+ pOldRealWindow->Deactivate();
+ }
+ }
+
+ // TrackingMode is ended in ImplHandleLoseFocus
+// To avoid problems with the Unix IME
+// pFocusWin->EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
+
+ // XXX #102010# hack for accessibility: do not close the menu,
+ // even after focus lost
+ static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE");
+ if( !(pEnv && *pEnv) )
+ {
+ NotifyEvent aNEvt( EVENT_LOSEFOCUS, pFocusWin );
+ if ( !ImplCallPreNotify( aNEvt ) )
+ pFocusWin->LoseFocus();
+ pFocusWin->ImplCallDeactivateListeners( NULL );
+ GetpApp()->FocusChanged();
+ }
+ // XXX
+ }
+ }
+
+ // Alle FloatingFenster deaktiv zeichnen
+ if ( ImplGetWindowImpl()->mpFrameData->mbStartFocusState != bHasFocus )
+ ImplActivateFloatingWindows( this, bHasFocus );
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleGetFocus( Window* pWindow )
+{
+ pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus = TRUE;
+
+ // Focus-Events zeitverzoegert ausfuehren, damit bei SystemChildFenstern
+ // nicht alles flackert, wenn diese den Focus bekommen
+ if ( !pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId )
+ {
+ bool bCallDirect = ImplGetSVData()->mbIsTestTool;
+ pWindow->ImplGetWindowImpl()->mpFrameData->mbStartFocusState = !pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus;
+ if( ! bCallDirect )
+ Application::PostUserEvent( pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId, LINK( pWindow, Window, ImplAsyncFocusHdl ) );
+ Window* pFocusWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
+ if ( pFocusWin && pFocusWin->ImplGetWindowImpl()->mpCursor )
+ pFocusWin->ImplGetWindowImpl()->mpCursor->ImplShow();
+ if( bCallDirect )
+ pWindow->ImplAsyncFocusHdl( NULL );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleLoseFocus( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Wenn Frame den Focus verliert, brechen wir auch ein AutoScroll ab
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+
+ // Wenn Frame den Focus verliert, brechen wir auch ein Tracking ab
+ if ( pSVData->maWinData.mpTrackWin )
+ {
+ if ( pSVData->maWinData.mpTrackWin->ImplGetWindowImpl()->mpFrameWindow == pWindow )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ }
+
+ // handle FloatingMode
+ // hier beenden wir immer den PopupModus, auch dann, wenn NOFOCUSCLOSE
+ // gesetzt ist, damit wir nicht beim Wechsel noch Fenster stehen lassen
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) )
+ pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+
+ pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus = FALSE;
+
+ // Focus-Events zeitverzoegert ausfuehren, damit bei SystemChildFenstern
+ // nicht alles flackert, wenn diese den Focus bekommen
+ bool bCallDirect = ImplGetSVData()->mbIsTestTool;
+ if ( !pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId )
+ {
+ pWindow->ImplGetWindowImpl()->mpFrameData->mbStartFocusState = !pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus;
+ if( ! bCallDirect )
+ Application::PostUserEvent( pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId, LINK( pWindow, Window, ImplAsyncFocusHdl ) );
+ }
+
+ Window* pFocusWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
+ if ( pFocusWin && pFocusWin->ImplGetWindowImpl()->mpCursor )
+ pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide();
+ if( bCallDirect )
+ pWindow->ImplAsyncFocusHdl( NULL );
+}
+
+// -----------------------------------------------------------------------
+struct DelayedCloseEvent
+{
+ Window* pWindow;
+ ImplDelData aDelData;
+};
+
+static long DelayedCloseEventLink( void* pCEvent, void* )
+{
+ DelayedCloseEvent* pEv = (DelayedCloseEvent*)pCEvent;
+
+ if( ! pEv->aDelData.IsDelete() )
+ {
+ pEv->pWindow->ImplRemoveDel( &pEv->aDelData );
+ // dispatch to correct window type
+ if( pEv->pWindow->IsSystemWindow() )
+ ((SystemWindow*)pEv->pWindow)->Close();
+ else if( pEv->pWindow->ImplIsDockingWindow() )
+ ((DockingWindow*)pEv->pWindow)->Close();
+ }
+ delete pEv;
+
+ return 0;
+}
+
+void ImplHandleClose( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ bool bWasPopup = false;
+ if( pWindow->ImplIsFloatingWindow() &&
+ static_cast<FloatingWindow*>(pWindow)->ImplIsInPrivatePopupMode() )
+ {
+ bWasPopup = true;
+ }
+
+ // on Close stop all floating modes and end popups
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat;
+ pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+ if ( pSVData->maHelpData.mbExtHelpMode )
+ Help::EndExtHelp();
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow( false );
+ // AutoScrollMode
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL | ENDTRACK_KEY );
+
+ if( ! bWasPopup )
+ {
+ Window *pWin = pWindow->ImplGetWindow();
+ // check whether close is allowed
+ if ( !pWin->IsEnabled() || !pWin->IsInputEnabled() || pWin->IsInModalMode() )
+ Sound::Beep( SOUND_DISABLE, pWin );
+ else
+ {
+ DelayedCloseEvent* pEv = new DelayedCloseEvent;
+ pEv->pWindow = pWin;
+ pWin->ImplAddDel( &pEv->aDelData );
+ Application::PostUserEvent( Link( pEv, DelayedCloseEventLink ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleUserEvent( ImplSVEvent* pSVEvent )
+{
+ if ( pSVEvent )
+ {
+ if ( pSVEvent->mbCall && !pSVEvent->maDelData.IsDelete() )
+ {
+ if ( pSVEvent->mpWindow )
+ {
+ pSVEvent->mpWindow->ImplRemoveDel( &(pSVEvent->maDelData) );
+ if ( pSVEvent->mpLink )
+ pSVEvent->mpLink->Call( pSVEvent->mpData );
+ else
+ pSVEvent->mpWindow->UserEvent( pSVEvent->mnEvent, pSVEvent->mpData );
+ }
+ else
+ {
+ if ( pSVEvent->mpLink )
+ pSVEvent->mpLink->Call( pSVEvent->mpData );
+ else
+ GetpApp()->UserEvent( pSVEvent->mnEvent, pSVEvent->mpData );
+ }
+ }
+
+ delete pSVEvent->mpLink;
+ delete pSVEvent;
+ }
+}
+
+// =======================================================================
+
+static USHORT ImplGetMouseMoveMode( SalMouseEvent* pEvent )
+{
+ USHORT nMode = 0;
+ if ( !pEvent->mnCode )
+ nMode |= MOUSE_SIMPLEMOVE;
+ if ( (pEvent->mnCode & MOUSE_LEFT) && !(pEvent->mnCode & KEY_MOD1) )
+ nMode |= MOUSE_DRAGMOVE;
+ if ( (pEvent->mnCode & MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) )
+ nMode |= MOUSE_DRAGCOPY;
+ return nMode;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplGetMouseButtonMode( SalMouseEvent* pEvent )
+{
+ USHORT nMode = 0;
+ if ( pEvent->mnButton == MOUSE_LEFT )
+ nMode |= MOUSE_SIMPLECLICK;
+ if ( (pEvent->mnButton == MOUSE_LEFT) && !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT)) )
+ nMode |= MOUSE_SELECT;
+ if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) &&
+ !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_SHIFT)) )
+ nMode |= MOUSE_MULTISELECT;
+ if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_SHIFT) &&
+ !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_MOD1)) )
+ nMode |= MOUSE_RANGESELECT;
+ return nMode;
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleSalMouseLeave( Window* pWindow, SalMouseEvent* pEvent )
+{
+ return ImplHandleMouseEvent( pWindow, EVENT_MOUSEMOVE, TRUE,
+ pEvent->mnX, pEvent->mnY,
+ pEvent->mnTime, pEvent->mnCode,
+ ImplGetMouseMoveMode( pEvent ) );
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleSalMouseMove( Window* pWindow, SalMouseEvent* pEvent )
+{
+ return ImplHandleMouseEvent( pWindow, EVENT_MOUSEMOVE, FALSE,
+ pEvent->mnX, pEvent->mnY,
+ pEvent->mnTime, pEvent->mnCode,
+ ImplGetMouseMoveMode( pEvent ) );
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleSalMouseButtonDown( Window* pWindow, SalMouseEvent* pEvent )
+{
+ return ImplHandleMouseEvent( pWindow, EVENT_MOUSEBUTTONDOWN, FALSE,
+ pEvent->mnX, pEvent->mnY,
+ pEvent->mnTime,
+#ifdef MACOSX
+ pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
+#else
+ pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
+#endif
+ ImplGetMouseButtonMode( pEvent ) );
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleSalMouseButtonUp( Window* pWindow, SalMouseEvent* pEvent )
+{
+ return ImplHandleMouseEvent( pWindow, EVENT_MOUSEBUTTONUP, FALSE,
+ pEvent->mnX, pEvent->mnY,
+ pEvent->mnTime,
+#ifdef MACOSX
+ pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
+#else
+ pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
+#endif
+ ImplGetMouseButtonMode( pEvent ) );
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleSalMouseActivate( Window* /*pWindow*/, SalMouseActivateEvent* /*pEvent*/ )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleMenuEvent( Window* pWindow, SalMenuEvent* pEvent, USHORT nEvent )
+{
+ // Find SystemWindow and its Menubar and let it dispatch the command
+ long nRet = 0;
+ Window *pWin = pWindow->ImplGetWindowImpl()->mpFirstChild;
+ while ( pWin )
+ {
+ if ( pWin->ImplGetWindowImpl()->mbSysWin )
+ break;
+ pWin = pWin->ImplGetWindowImpl()->mpNext;
+ }
+ if( pWin )
+ {
+ MenuBar *pMenuBar = ((SystemWindow*) pWin)->GetMenuBar();
+ if( pMenuBar )
+ {
+ switch( nEvent )
+ {
+ case SALEVENT_MENUACTIVATE:
+ nRet = pMenuBar->HandleMenuActivateEvent( (Menu*) pEvent->mpMenu ) ? 1 : 0;
+ break;
+ case SALEVENT_MENUDEACTIVATE:
+ nRet = pMenuBar->HandleMenuDeActivateEvent( (Menu*) pEvent->mpMenu ) ? 1 : 0;
+ break;
+ case SALEVENT_MENUHIGHLIGHT:
+ nRet = pMenuBar->HandleMenuHighlightEvent( (Menu*) pEvent->mpMenu, pEvent->mnId ) ? 1 : 0;
+ break;
+ case SALEVENT_MENUBUTTONCOMMAND:
+ nRet = pMenuBar->HandleMenuButtonEvent( (Menu*) pEvent->mpMenu, pEvent->mnId ) ? 1 : 0;
+ break;
+ case SALEVENT_MENUCOMMAND:
+ nRet = pMenuBar->HandleMenuCommandEvent( (Menu*) pEvent->mpMenu, pEvent->mnId ) ? 1 : 0;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSalKeyMod( Window* pWindow, SalKeyModEvent* pEvent )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pTrackWin = pSVData->maWinData.mpTrackWin;
+ if ( pTrackWin )
+ pWindow = pTrackWin;
+#ifdef MACOSX
+ USHORT nOldCode = pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3);
+#else
+ USHORT nOldCode = pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
+#endif
+ USHORT nNewCode = pEvent->mnCode;
+ if ( nOldCode != nNewCode )
+ {
+#ifdef MACOSX
+ nNewCode |= pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3);
+#else
+ nNewCode |= pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
+#endif
+ pWindow->ImplGetWindowImpl()->mpFrameWindow->ImplCallMouseMove( nNewCode, TRUE );
+ }
+
+ // #105224# send commandevent to allow special treatment of Ctrl-LeftShift/Ctrl-RightShift etc.
+
+ // find window
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ if ( !pChild )
+ return;
+
+ // send modkey events only if useful data is available
+ if( pEvent->mnModKeyCode != 0 )
+ {
+ CommandModKeyData data( pEvent->mnModKeyCode );
+ ImplCallCommand( pChild, COMMAND_MODKEYCHANGE, &data );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleInputLanguageChange( Window* pWindow )
+{
+ // find window
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ if ( !pChild )
+ return;
+
+ ImplCallCommand( pChild, COMMAND_INPUTLANGUAGECHANGE );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSalSettings( Window* pWindow, USHORT nEvent )
+{
+ // Application Notification werden nur fuer das erste Window ausgeloest
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pWindow != pSVData->maWinData.mpFirstFrame )
+ return;
+
+ Application* pApp = GetpApp();
+ if ( !pApp )
+ return;
+
+ if ( nEvent == SALEVENT_SETTINGSCHANGED )
+ {
+ AllSettings aSettings = pApp->GetSettings();
+ pApp->MergeSystemSettings( aSettings );
+ pApp->SystemSettingsChanging( aSettings, pWindow );
+ pApp->SetSettings( aSettings );
+ }
+ else
+ {
+ USHORT nType;
+ switch ( nEvent )
+ {
+ case SALEVENT_VOLUMECHANGED:
+ nType = 0;
+ break;
+ case SALEVENT_PRINTERCHANGED:
+ ImplDeletePrnQueueList();
+ nType = DATACHANGED_PRINTER;
+ break;
+ case SALEVENT_DISPLAYCHANGED:
+ nType = DATACHANGED_DISPLAY;
+ break;
+ case SALEVENT_FONTCHANGED:
+ OutputDevice::ImplUpdateAllFontData( TRUE );
+ nType = DATACHANGED_FONTS;
+ break;
+ case SALEVENT_DATETIMECHANGED:
+ nType = DATACHANGED_DATETIME;
+ break;
+ case SALEVENT_KEYBOARDCHANGED:
+ nType = 0;
+ break;
+ default:
+ nType = 0;
+ break;
+ }
+
+ if ( nType )
+ {
+ DataChangedEvent aDCEvt( nType );
+ pApp->DataChanged( aDCEvt );
+ pApp->NotifyAllWindows( aDCEvt );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSalExtTextInputPos( Window* pWindow, SalExtTextInputPosEvent* pEvt )
+{
+ Rectangle aCursorRect;
+ ImplHandleExtTextInputPos( pWindow, aCursorRect, pEvt->mnExtWidth, &pEvt->mbVertical );
+ if ( aCursorRect.IsEmpty() )
+ {
+ pEvt->mnX = -1;
+ pEvt->mnY = -1;
+ pEvt->mnWidth = -1;
+ pEvt->mnHeight = -1;
+ }
+ else
+ {
+ pEvt->mnX = aCursorRect.Left();
+ pEvt->mnY = aCursorRect.Top();
+ pEvt->mnWidth = aCursorRect.GetWidth();
+ pEvt->mnHeight = aCursorRect.GetHeight();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleShowDialog( Window* pWindow, int nDialogId )
+{
+ if( ! pWindow )
+ return FALSE;
+
+ if( pWindow->GetType() == WINDOW_BORDERWINDOW )
+ {
+ Window* pWrkWin = pWindow->GetWindow( WINDOW_CLIENT );
+ if( pWrkWin )
+ pWindow = pWrkWin;
+ }
+ CommandDialogData aCmdData( nDialogId );
+ return ImplCallCommand( pWindow, COMMAND_SHOWDIALOG, &aCmdData );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSurroundingTextRequest( Window *pWindow,
+ XubString& rText,
+ Selection &rSelRange )
+{
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+
+ if ( !pChild )
+ {
+ rText = XubString::EmptyString();
+ rSelRange.setMin( 0 );
+ rSelRange.setMax( 0 );
+ }
+ else
+ {
+
+ rText = pChild->GetSurroundingText();
+ Selection aSel = pChild->GetSurroundingTextSelection();
+ rSelRange.setMin( aSel.Min() );
+ rSelRange.setMax( aSel.Max() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSalSurroundingTextRequest( Window *pWindow,
+ SalSurroundingTextRequestEvent *pEvt )
+{
+ Selection aSelRange;
+ ImplHandleSurroundingTextRequest( pWindow, pEvt->maText, aSelRange );
+
+ aSelRange.Justify();
+
+ if( aSelRange.Min() < 0 )
+ pEvt->mnStart = 0;
+ else if( aSelRange.Min() > pEvt->maText.Len() )
+ pEvt->mnStart = pEvt->maText.Len();
+ else
+ pEvt->mnStart = aSelRange.Min();
+
+ if( aSelRange.Max() < 0 )
+ pEvt->mnStart = 0;
+ else if( aSelRange.Max() > pEvt->maText.Len() )
+ pEvt->mnEnd = pEvt->maText.Len();
+ else
+ pEvt->mnEnd = aSelRange.Max();
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSurroundingTextSelectionChange( Window *pWindow,
+ ULONG nStart,
+ ULONG nEnd )
+{
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ if( pChild )
+ {
+ CommandSelectionChangeData data( nStart, nEnd );
+ ImplCallCommand( pChild, COMMAND_SELECTIONCHANGE, &data );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleStartReconversion( Window *pWindow )
+{
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ if( pChild )
+ ImplCallCommand( pChild, COMMAND_PREPARERECONVERSION );
+}
+
+// -----------------------------------------------------------------------
+
+long ImplWindowFrameProc( Window* pWindow, SalFrame* /*pFrame*/,
+ USHORT nEvent, const void* pEvent )
+{
+ DBG_TESTSOLARMUTEX();
+
+ long nRet = 0;
+
+ // #119709# for some unknown reason it is possible to receive events (in this case key events)
+ // although the corresponding VCL window must have been destroyed already
+ // at least ImplGetWindowImpl() was NULL in these cases, so check this here
+ if( pWindow->ImplGetWindowImpl() == NULL )
+ return 0;
+
+ switch ( nEvent )
+ {
+ case SALEVENT_MOUSEMOVE:
+ nRet = ImplHandleSalMouseMove( pWindow, (SalMouseEvent*)pEvent );
+ break;
+ case SALEVENT_EXTERNALMOUSEMOVE:
+ {
+ MouseEvent* pMouseEvt = (MouseEvent*) pEvent;
+ SalMouseEvent aSalMouseEvent;
+
+ aSalMouseEvent.mnTime = Time::GetSystemTicks();
+ aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
+ aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
+ aSalMouseEvent.mnButton = 0;
+ aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
+
+ nRet = ImplHandleSalMouseMove( pWindow, &aSalMouseEvent );
+ }
+ break;
+ case SALEVENT_MOUSELEAVE:
+ nRet = ImplHandleSalMouseLeave( pWindow, (SalMouseEvent*)pEvent );
+ break;
+ case SALEVENT_MOUSEBUTTONDOWN:
+ nRet = ImplHandleSalMouseButtonDown( pWindow, (SalMouseEvent*)pEvent );
+ break;
+ case SALEVENT_EXTERNALMOUSEBUTTONDOWN:
+ {
+ MouseEvent* pMouseEvt = (MouseEvent*) pEvent;
+ SalMouseEvent aSalMouseEvent;
+
+ aSalMouseEvent.mnTime = Time::GetSystemTicks();
+ aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
+ aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
+ aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
+ aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
+
+ nRet = ImplHandleSalMouseButtonDown( pWindow, &aSalMouseEvent );
+ }
+ break;
+ case SALEVENT_MOUSEBUTTONUP:
+ nRet = ImplHandleSalMouseButtonUp( pWindow, (SalMouseEvent*)pEvent );
+ break;
+ case SALEVENT_EXTERNALMOUSEBUTTONUP:
+ {
+ MouseEvent* pMouseEvt = (MouseEvent*) pEvent;
+ SalMouseEvent aSalMouseEvent;
+
+ aSalMouseEvent.mnTime = Time::GetSystemTicks();
+ aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
+ aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
+ aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
+ aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
+
+ nRet = ImplHandleSalMouseButtonUp( pWindow, &aSalMouseEvent );
+ }
+ break;
+ case SALEVENT_MOUSEACTIVATE:
+ nRet = ImplHandleSalMouseActivate( pWindow, (SalMouseActivateEvent*)pEvent );
+ break;
+ case SALEVENT_KEYINPUT:
+ {
+ SalKeyEvent* pKeyEvt = (SalKeyEvent*)pEvent;
+ nRet = ImplHandleKey( pWindow, EVENT_KEYINPUT,
+ pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, TRUE );
+ }
+ break;
+ case SALEVENT_EXTERNALKEYINPUT:
+ {
+ KeyEvent* pKeyEvt = (KeyEvent*) pEvent;
+ nRet = ImplHandleKey( pWindow, EVENT_KEYINPUT,
+ pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), FALSE );
+ }
+ break;
+ case SALEVENT_KEYUP:
+ {
+ SalKeyEvent* pKeyEvt = (SalKeyEvent*)pEvent;
+ nRet = ImplHandleKey( pWindow, EVENT_KEYUP,
+ pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, TRUE );
+ }
+ break;
+ case SALEVENT_EXTERNALKEYUP:
+ {
+ KeyEvent* pKeyEvt = (KeyEvent*) pEvent;
+ nRet = ImplHandleKey( pWindow, EVENT_KEYUP,
+ pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), FALSE );
+ }
+ break;
+ case SALEVENT_KEYMODCHANGE:
+ ImplHandleSalKeyMod( pWindow, (SalKeyModEvent*)pEvent );
+ break;
+
+ case SALEVENT_INPUTLANGUAGECHANGE:
+ ImplHandleInputLanguageChange( pWindow );
+ break;
+
+ case SALEVENT_MENUACTIVATE:
+ case SALEVENT_MENUDEACTIVATE:
+ case SALEVENT_MENUHIGHLIGHT:
+ case SALEVENT_MENUCOMMAND:
+ case SALEVENT_MENUBUTTONCOMMAND:
+ nRet = ImplHandleMenuEvent( pWindow, (SalMenuEvent*)pEvent, nEvent );
+ break;
+
+ case SALEVENT_WHEELMOUSE:
+ nRet = ImplHandleWheelEvent( pWindow, *(const SalWheelMouseEvent*)pEvent);
+ break;
+
+ case SALEVENT_PAINT:
+ {
+ SalPaintEvent* pPaintEvt = (SalPaintEvent*)pEvent;
+
+ if( Application::GetSettings().GetLayoutRTL() )
+ {
+ // --- RTL --- (mirror paint rect)
+ SalFrame* pSalFrame = pWindow->ImplGetWindowImpl()->mpFrame;
+ pPaintEvt->mnBoundX = pSalFrame->maGeometry.nWidth-pPaintEvt->mnBoundWidth-pPaintEvt->mnBoundX;
+ }
+
+ Rectangle aBoundRect( Point( pPaintEvt->mnBoundX, pPaintEvt->mnBoundY ),
+ Size( pPaintEvt->mnBoundWidth, pPaintEvt->mnBoundHeight ) );
+ ImplHandlePaint( pWindow, aBoundRect, pPaintEvt->mbImmediateUpdate );
+ }
+ break;
+
+ case SALEVENT_MOVE:
+ ImplHandleMove( pWindow );
+ break;
+
+ case SALEVENT_RESIZE:
+ {
+ long nNewWidth;
+ long nNewHeight;
+ pWindow->ImplGetWindowImpl()->mpFrame->GetClientSize( nNewWidth, nNewHeight );
+ ImplHandleResize( pWindow, nNewWidth, nNewHeight );
+ }
+ break;
+
+ case SALEVENT_MOVERESIZE:
+ {
+ SalFrameGeometry g = pWindow->ImplGetWindowImpl()->mpFrame->GetGeometry();
+ ImplHandleMoveResize( pWindow, g.nWidth, g.nHeight );
+ }
+ break;
+
+ case SALEVENT_CLOSEPOPUPS:
+ {
+ KillOwnPopups( pWindow );
+ }
+ break;
+
+ case SALEVENT_GETFOCUS:
+ ImplHandleGetFocus( pWindow );
+ break;
+ case SALEVENT_LOSEFOCUS:
+ ImplHandleLoseFocus( pWindow );
+ break;
+
+ case SALEVENT_CLOSE:
+ ImplHandleClose( pWindow );
+ break;
+
+ case SALEVENT_SHUTDOWN:
+ {
+ static bool bInQueryExit = false;
+ if( !bInQueryExit )
+ {
+ bInQueryExit = true;
+ if ( GetpApp()->QueryExit() )
+ {
+ // Message-Schleife beenden
+ Application::Quit();
+ return FALSE;
+ }
+ else
+ {
+ bInQueryExit = false;
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+
+ case SALEVENT_SETTINGSCHANGED:
+ case SALEVENT_VOLUMECHANGED:
+ case SALEVENT_PRINTERCHANGED:
+ case SALEVENT_DISPLAYCHANGED:
+ case SALEVENT_FONTCHANGED:
+ case SALEVENT_DATETIMECHANGED:
+ case SALEVENT_KEYBOARDCHANGED:
+ ImplHandleSalSettings( pWindow, nEvent );
+ break;
+
+ case SALEVENT_USEREVENT:
+ ImplHandleUserEvent( (ImplSVEvent*)pEvent );
+ break;
+
+ case SALEVENT_EXTTEXTINPUT:
+ {
+ SalExtTextInputEvent* pEvt = (SalExtTextInputEvent*)pEvent;
+ nRet = ImplHandleExtTextInput( pWindow,
+ pEvt->maText, pEvt->mpTextAttr,
+ pEvt->mnCursorPos, pEvt->mnCursorFlags );
+ }
+ break;
+ case SALEVENT_ENDEXTTEXTINPUT:
+ nRet = ImplHandleEndExtTextInput( pWindow );
+ break;
+ case SALEVENT_EXTTEXTINPUTPOS:
+ ImplHandleSalExtTextInputPos( pWindow, (SalExtTextInputPosEvent*)pEvent );
+ break;
+ case SALEVENT_INPUTCONTEXTCHANGE:
+ nRet = ImplHandleInputContextChange( pWindow, ((SalInputContextChangeEvent*)pEvent)->meLanguage );
+ break;
+ case SALEVENT_SHOWDIALOG:
+ {
+ int nDialogID = static_cast<int>(reinterpret_cast<sal_IntPtr>(pEvent));
+ nRet = ImplHandleShowDialog( pWindow, nDialogID );
+ }
+ break;
+ case SALEVENT_SURROUNDINGTEXTREQUEST:
+ ImplHandleSalSurroundingTextRequest( pWindow, (SalSurroundingTextRequestEvent*)pEvent );
+ break;
+ case SALEVENT_SURROUNDINGTEXTSELECTIONCHANGE:
+ {
+ SalSurroundingTextSelectionChangeEvent* pEvt
+ = (SalSurroundingTextSelectionChangeEvent*)pEvent;
+ ImplHandleSurroundingTextSelectionChange( pWindow,
+ pEvt->mnStart,
+ pEvt->mnEnd );
+ }
+ case SALEVENT_STARTRECONVERSION:
+ ImplHandleStartReconversion( pWindow );
+ break;
+#ifdef DBG_UTIL
+ default:
+ DBG_ERROR1( "ImplWindowFrameProc(): unknown event (%lu)", (ULONG)nEvent );
+ break;
+#endif
+ }
+
+ return nRet;
+}
diff --git a/vcl/source/window/wrkwin.cxx b/vcl/source/window/wrkwin.cxx
new file mode 100644
index 000000000000..8fb2f2f8346a
--- /dev/null
+++ b/vcl/source/window/wrkwin.cxx
@@ -0,0 +1,323 @@
+/*************************************************************************
+ *
+ * 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_vcl.hxx"
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#include <vcl/salframe.hxx>
+#include <tools/debug.hxx>
+
+#ifndef _SV_RC_H
+#include <tools/rc.h>
+#endif
+#include <vcl/svdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/brdwin.hxx>
+#include <vcl/window.h>
+#include <vcl/wrkwin.hxx>
+#include <vcl/sysdata.hxx>
+
+// =======================================================================
+
+#define WORKWIN_WINDOWSTATE_FULLSCREEN ((ULONG)0x00010000)
+#define WORKWIN_WINDOWSTATE_ALL ((ULONG)0x00FF0000)
+
+// =======================================================================
+
+void WorkWindow::ImplInitWorkWindowData()
+{
+ mnIcon = 0; // Should be removed in the next top level update - now in SystemWindow
+
+ mnPresentationFlags = 0;
+ mbPresentationMode = FALSE;
+ mbPresentationVisible = FALSE;
+ mbPresentationFull = FALSE;
+ mbFullScreenMode = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
+{
+ USHORT nFrameStyle = BORDERWINDOW_STYLE_FRAME;
+ if ( nStyle & WB_APP )
+ nFrameStyle |= BORDERWINDOW_STYLE_APP;
+
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, pSystemParentData, nStyle, nFrameStyle );
+ Window::ImplInit( pBorderWin, nStyle & (WB_3DLOOK | WB_CLIPCHILDREN | WB_DIALOGCONTROL | WB_SYSTEMFLOATWIN), NULL );
+ pBorderWin->mpWindowImpl->mpClientWindow = this;
+ pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
+ mpWindowImpl->mpBorderWindow = pBorderWin;
+// mpWindowImpl->mpRealParent = pParent; // !!! Muesste eigentlich gesetzt werden, aber wegen Fehlern mit dem MenuBar erstmal nicht gesetzt !!!
+
+ if ( nStyle & WB_APP )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ DBG_ASSERT( !pSVData->maWinData.mpAppWin, "WorkWindow::WorkWindow(): More than one window with style WB_APP" );
+ pSVData->maWinData.mpAppWin = this;
+ }
+
+ SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::ImplInit( Window* pParent, WinBits nStyle, const ::com::sun::star::uno::Any& aSystemWorkWindowToken )
+{
+ if( aSystemWorkWindowToken.hasValue() )
+ {
+ ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
+ aSystemWorkWindowToken >>= aSeq;
+ SystemParentData* pData = (SystemParentData*)aSeq.getArray();
+ DBG_ASSERT( aSeq.getLength() == sizeof( SystemParentData ) && pData->nSize == sizeof( SystemParentData ), "WorkWindow::WorkWindow( Window*, const Any&, WinBits ) called with invalid Any" );
+ // init with style 0 as does WorkWindow::WorkWindow( SystemParentData* );
+ ImplInit( pParent, 0, pData );
+ }
+ else
+ ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( WindowType nType ) :
+ SystemWindow( nType )
+{
+ ImplInitWorkWindowData();
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( Window* pParent, WinBits nStyle ) :
+ SystemWindow( WINDOW_WORKWINDOW )
+{
+ ImplInitWorkWindowData();
+ ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( Window* pParent, const ResId& rResId ) :
+ SystemWindow( WINDOW_WORKWINDOW )
+{
+ ImplInitWorkWindowData();
+ rResId.SetRT( RSC_WORKWIN );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( Window* pParent, const ::com::sun::star::uno::Any& aSystemWorkWindowToken, WinBits nStyle ) :
+ SystemWindow( WINDOW_WORKWINDOW )
+{
+ ImplInitWorkWindowData();
+ mbSysChild = TRUE;
+ ImplInit( pParent, nStyle, aSystemWorkWindowToken );
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( SystemParentData* pParent ) :
+ SystemWindow( WINDOW_WORKWINDOW )
+{
+ ImplInitWorkWindowData();
+ mbSysChild = TRUE;
+ ImplInit( NULL, 0, pParent );
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::ImplLoadRes( const ResId& rResId )
+{
+ SystemWindow::ImplLoadRes( rResId );
+
+ ReadLongRes();
+ if ( !(rResId.GetWinBits() & WB_HIDE) && (RSC_WORKWIN == rResId.GetRT()) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::~WorkWindow()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpAppWin == this )
+ {
+ pSVData->maWinData.mpAppWin = NULL;
+ Application::Quit();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::ShowFullScreenMode( BOOL bFullScreenMode, sal_Int32 nDisplay )
+{
+ if ( !mbFullScreenMode == !bFullScreenMode )
+ return;
+
+ if( (nDisplay < 0)
+ || (nDisplay >= static_cast<sal_Int32>(Application::GetScreenCount()) ) )
+ {
+ nDisplay = GetScreenNumber();
+ }
+
+ mbFullScreenMode = bFullScreenMode != 0;
+ if ( !mbSysChild )
+ {
+ mpWindowImpl->mpFrameWindow->mpWindowImpl->mbWaitSystemResize = TRUE;
+ ImplGetFrame()->ShowFullScreen( bFullScreenMode, nDisplay );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::StartPresentationMode( BOOL bPresentation, USHORT nFlags, sal_Int32 nDisplay )
+{
+ if ( !bPresentation == !mbPresentationMode )
+ return;
+
+ if ( bPresentation )
+ {
+ mbPresentationMode = TRUE;
+ mbPresentationVisible = IsVisible();
+ mbPresentationFull = mbFullScreenMode;
+ mnPresentationFlags = nFlags;
+
+ if ( !(mnPresentationFlags & PRESENTATION_NOFULLSCREEN) )
+ ShowFullScreenMode( TRUE, nDisplay );
+ if ( !mbSysChild )
+ {
+ if ( mnPresentationFlags & PRESENTATION_HIDEALLAPPS )
+ mpWindowImpl->mpFrame->SetAlwaysOnTop( TRUE );
+ if ( !(mnPresentationFlags & PRESENTATION_NOAUTOSHOW) )
+ ToTop();
+ mpWindowImpl->mpFrame->StartPresentation( TRUE );
+ }
+
+ if ( !(mnPresentationFlags & PRESENTATION_NOAUTOSHOW) )
+ Show();
+ }
+ else
+ {
+ Show( mbPresentationVisible );
+ if ( !mbSysChild )
+ {
+ mpWindowImpl->mpFrame->StartPresentation( FALSE );
+ if ( mnPresentationFlags & PRESENTATION_HIDEALLAPPS )
+ mpWindowImpl->mpFrame->SetAlwaysOnTop( FALSE );
+ }
+ ShowFullScreenMode( mbPresentationFull, nDisplay );
+
+ mbPresentationMode = FALSE;
+ mbPresentationVisible = FALSE;
+ mbPresentationFull = FALSE;
+ mnPresentationFlags = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WorkWindow::IsMinimized() const
+{
+ //return mpWindowImpl->mpFrameData->mbMinimized;
+ SalFrameState aState;
+ mpWindowImpl->mpFrame->GetWindowState(&aState);
+ return (( aState.mnState & SAL_FRAMESTATE_MINIMIZED ) != 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WorkWindow::SetPluginParent( SystemParentData* pParent )
+{
+ DBG_ASSERT( ! mbPresentationMode && ! mbFullScreenMode, "SetPluginParent in fullscreen or presentation mode !" );
+
+ bool bWasDnd = Window::ImplStopDnd();
+
+ BOOL bShown = IsVisible();
+ Show( FALSE );
+ BOOL bRet = mpWindowImpl->mpFrame->SetPluginParent( pParent );
+ Show( bShown );
+
+ if( bWasDnd )
+ Window::ImplStartDnd();
+
+ return bRet;
+}
+
+void WorkWindow::ImplSetFrameState( ULONG aFrameState )
+{
+ SalFrameState aState;
+ aState.mnMask = SAL_FRAMESTATE_MASK_STATE;
+ aState.mnState = aFrameState;
+ mpWindowImpl->mpFrame->SetWindowState( &aState );
+}
+
+
+void WorkWindow::Minimize()
+{
+ ImplSetFrameState( SAL_FRAMESTATE_MINIMIZED );
+}
+
+void WorkWindow::Restore()
+{
+ ImplSetFrameState( SAL_FRAMESTATE_NORMAL );
+}
+
+BOOL WorkWindow::Close()
+{
+ BOOL bCanClose = SystemWindow::Close();
+
+ // Ist es das Applikationsfenster, dann beende die Applikation
+ if ( bCanClose && ( ImplGetSVData()->maWinData.mpAppWin == this ) )
+ GetpApp()->Quit();
+
+ return bCanClose;
+}
+
+void WorkWindow::Maximize( BOOL bMaximize )
+{
+ ImplSetFrameState( bMaximize ? SAL_FRAMESTATE_MAXIMIZED : SAL_FRAMESTATE_NORMAL );
+}
+
+BOOL WorkWindow::IsMaximized() const
+{
+ BOOL bRet = FALSE;
+
+ SalFrameState aState;
+ if( mpWindowImpl->mpFrame->GetWindowState( &aState ) )
+ {
+ if( aState.mnState & (SAL_FRAMESTATE_MAXIMIZED |
+ SAL_FRAMESTATE_MAXIMIZED_HORZ |
+ SAL_FRAMESTATE_MAXIMIZED_VERT ) )
+ bRet = TRUE;
+ }
+ return bRet;
+}