summaryrefslogtreecommitdiff
path: root/svtools/source/contnr
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/contnr')
-rw-r--r--svtools/source/contnr/cont_pch.cxx41
-rw-r--r--svtools/source/contnr/contentenumeration.cxx464
-rw-r--r--svtools/source/contnr/contentenumeration.hxx287
-rw-r--r--svtools/source/contnr/ctrdll.cxx79
-rw-r--r--svtools/source/contnr/fileview.cxx2809
-rw-r--r--svtools/source/contnr/fileview.hrc40
-rw-r--r--svtools/source/contnr/fileview.src196
-rw-r--r--svtools/source/contnr/imivctl.hxx637
-rw-r--r--svtools/source/contnr/imivctl1.cxx4681
-rw-r--r--svtools/source/contnr/imivctl2.cxx848
-rw-r--r--svtools/source/contnr/ivctrl.cxx642
-rw-r--r--svtools/source/contnr/makefile.mk82
-rw-r--r--svtools/source/contnr/svcontnr.src103
-rw-r--r--svtools/source/contnr/svicnvw.cxx833
-rw-r--r--svtools/source/contnr/svimpbox.cxx3650
-rw-r--r--svtools/source/contnr/svimpicn.cxx4167
-rw-r--r--svtools/source/contnr/svlbitm.cxx651
-rw-r--r--svtools/source/contnr/svlbox.cxx1923
-rw-r--r--svtools/source/contnr/svtabbx.cxx1304
-rw-r--r--svtools/source/contnr/svtreebx.cxx2670
-rw-r--r--svtools/source/contnr/templwin.cxx2025
-rw-r--r--svtools/source/contnr/templwin.hrc59
-rw-r--r--svtools/source/contnr/templwin.hxx309
-rw-r--r--svtools/source/contnr/templwin.src376
-rw-r--r--svtools/source/contnr/tooltiplbox.cxx120
-rw-r--r--svtools/source/contnr/treelist.cxx2126
26 files changed, 31122 insertions, 0 deletions
diff --git a/svtools/source/contnr/cont_pch.cxx b/svtools/source/contnr/cont_pch.cxx
new file mode 100644
index 000000000000..4661a08162a2
--- /dev/null
+++ b/svtools/source/contnr/cont_pch.cxx
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+#include <sv.hxx>
+#include <svtools/treelist.hxx>
+#include <svtools/svtabbx.hxx>
+#include <svtools/svtreebx.hxx>
+#include <svtools/svicnvw.hxx>
+#include "svimpbox.hxx"
+#include "svimpicn.hxx"
+#include <svtools/svlbox.hxx>
+#include <svtools/svlbitm.hxx>
+
+
diff --git a/svtools/source/contnr/contentenumeration.cxx b/svtools/source/contnr/contentenumeration.cxx
new file mode 100644
index 000000000000..93f328ae2028
--- /dev/null
+++ b/svtools/source/contnr/contentenumeration.cxx
@@ -0,0 +1,464 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+#include "contentenumeration.hxx"
+#include <svl/urlfilter.hxx>
+#include <svtools/inettbc.hxx>
+#include "imagemgr.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/ucb/XDynamicResultSet.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+/** === end UNO includes === **/
+#include <comphelper/processfactory.hxx>
+#include <tools/debug.hxx>
+#include <vcl/svapp.hxx>
+#include <vos/mutex.hxx>
+
+#include <memory>
+
+//........................................................................
+namespace svt
+{
+//........................................................................
+
+#define ROW_TITLE 1
+#define ROW_SIZE 2
+#define ROW_DATE_MOD 3
+#define ROW_DATE_CREATE 4
+#define ROW_IS_FOLDER 5
+#define ROW_TARGET_URL 6
+#define ROW_IS_HIDDEN 7
+#define ROW_IS_VOLUME 8
+#define ROW_IS_REMOTE 9
+#define ROW_IS_REMOVEABLE 10
+#define ROW_IS_FLOPPY 11
+#define ROW_IS_COMPACTDISC 12
+
+#define CONVERT_DATETIME( aUnoDT, aToolsDT ) \
+ aToolsDT = ::DateTime( Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year ), \
+ Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds ) );
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::util::DateTime;
+ using ::com::sun::star::sdbc::XResultSet;
+ using ::com::sun::star::sdbc::XRow;
+ using ::com::sun::star::ucb::XDynamicResultSet;
+ using ::com::sun::star::ucb::CommandAbortedException;
+ using ::com::sun::star::ucb::XContentAccess;
+ using ::com::sun::star::ucb::XCommandEnvironment;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::rtl::OUString;
+ using ::ucbhelper::ResultSetInclude;
+ using ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS;
+
+ //====================================================================
+ //= FileViewContentEnumerator
+ //====================================================================
+ //--------------------------------------------------------------------
+ FileViewContentEnumerator::FileViewContentEnumerator(
+ const Reference< XCommandEnvironment >& _rxCommandEnv,
+ ContentData& _rContentToFill, ::osl::Mutex& _rContentMutex,
+ const IContentTitleTranslation* _pTranslator )
+ :m_rContent ( _rContentToFill )
+ ,m_rContentMutex ( _rContentMutex )
+ ,m_refCount ( 0 )
+ ,m_xCommandEnv ( _rxCommandEnv )
+ ,m_pFilter ( NULL )
+ ,m_pTranslator ( _pTranslator )
+ ,m_bCancelled ( false )
+ ,m_rBlackList ( ::com::sun::star::uno::Sequence< ::rtl::OUString >() )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ FileViewContentEnumerator::~FileViewContentEnumerator()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void FileViewContentEnumerator::cancel()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_bCancelled = true;
+ m_pResultHandler = NULL;
+ m_pTranslator = NULL;
+ m_pFilter = NULL;
+ m_aFolder.aContent = ::ucbhelper::Content();
+ m_aFolder.sURL = String();
+ }
+
+ //--------------------------------------------------------------------
+ EnumerationResult FileViewContentEnumerator::enumerateFolderContentSync(
+ const FolderDescriptor& _rFolder,
+ const IUrlFilter* _pFilter,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
+ {
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_aFolder = _rFolder;
+ m_pFilter = _pFilter;
+ m_pResultHandler = NULL;
+ m_rBlackList = rBlackList;
+ }
+ return enumerateFolderContent();
+ }
+
+ //--------------------------------------------------------------------
+ void FileViewContentEnumerator::enumerateFolderContent(
+ const FolderDescriptor& _rFolder, const IUrlFilter* _pFilter, IEnumerationResultHandler* _pResultHandler )
+ {
+ // ensure that we don't get deleted while herein
+ acquire();
+ // the matching "release" will be called in onTerminated
+ // Note that onTerminated is only called if run was left normally.
+ // If somebody terminates the thread from the outside, then onTerminated
+ // will never be called. However, our terminate method is not accessible
+ // to our clients, so the only class which could misbehave is this class
+ // here itself ...
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_aFolder = _rFolder;
+ m_pFilter = _pFilter;
+ m_pResultHandler = _pResultHandler;
+
+ OSL_ENSURE( m_aFolder.aContent.get().is() || m_aFolder.sURL.Len(),
+ "FileViewContentEnumerator::enumerateFolderContent: invalid folder descriptor!" );
+
+ // start the thread
+ create();
+ }
+
+ //--------------------------------------------------------------------
+ oslInterlockedCount SAL_CALL FileViewContentEnumerator::acquire()
+ {
+ return osl_incrementInterlockedCount( &m_refCount );
+ }
+
+ //--------------------------------------------------------------------
+ oslInterlockedCount SAL_CALL FileViewContentEnumerator::release()
+ {
+ if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
+ {
+ delete this;
+ return 0;
+ }
+ return m_refCount;
+ }
+
+ //--------------------------------------------------------------------
+ EnumerationResult FileViewContentEnumerator::enumerateFolderContent()
+ {
+ EnumerationResult eResult = ERROR;
+ try
+ {
+
+ Reference< XResultSet > xResultSet;
+ Sequence< OUString > aProps(12);
+
+ aProps[0] = OUString::createFromAscii( "Title" );
+ aProps[1] = OUString::createFromAscii( "Size" );
+ aProps[2] = OUString::createFromAscii( "DateModified" );
+ aProps[3] = OUString::createFromAscii( "DateCreated" );
+ aProps[4] = OUString::createFromAscii( "IsFolder" );
+ aProps[5] = OUString::createFromAscii( "TargetURL" );
+ aProps[6] = OUString::createFromAscii( "IsHidden" );
+ aProps[7] = OUString::createFromAscii( "IsVolume" );
+ aProps[8] = OUString::createFromAscii( "IsRemote" );
+ aProps[9] = OUString::createFromAscii( "IsRemoveable" );
+ aProps[10] = OUString::createFromAscii( "IsFloppy" );
+ aProps[11] = OUString::createFromAscii( "IsCompactDisc" );
+
+ Reference< XCommandEnvironment > xEnvironment;
+ try
+ {
+ FolderDescriptor aFolder;
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ aFolder = m_aFolder;
+ xEnvironment = m_xCommandEnv;
+ }
+ if ( !aFolder.aContent.get().is() )
+ {
+ aFolder.aContent = ::ucbhelper::Content( aFolder.sURL, xEnvironment );
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_aFolder.aContent = aFolder.aContent;
+ }
+ }
+
+ Reference< XDynamicResultSet > xDynResultSet;
+ ResultSetInclude eInclude = INCLUDE_FOLDERS_AND_DOCUMENTS;
+ xDynResultSet = aFolder.aContent.createDynamicCursor( aProps, eInclude );
+
+ if ( xDynResultSet.is() )
+ xResultSet = xDynResultSet->getStaticResultSet();
+ }
+ catch( CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "createCursor: CommandAbortedException" );
+ }
+ catch( Exception& )
+ {
+ }
+
+ bool bCancelled = false;
+ if ( xResultSet.is() )
+ {
+ Reference< XRow > xRow( xResultSet, UNO_QUERY );
+ Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
+
+ try
+ {
+ SortingData_Impl* pData;
+ DateTime aDT;
+
+ while ( !bCancelled && xResultSet->next() )
+ {
+ sal_Bool bIsHidden = xRow->getBoolean( ROW_IS_HIDDEN );
+ // don't show hidden files
+ if ( !bIsHidden || xRow->wasNull() )
+ {
+ pData = NULL;
+
+ aDT = xRow->getTimestamp( ROW_DATE_MOD );
+ sal_Bool bContainsDate = !xRow->wasNull();
+ if ( !bContainsDate )
+ {
+ aDT = xRow->getTimestamp( ROW_DATE_CREATE );
+ bContainsDate = !xRow->wasNull();
+ }
+
+ OUString aContentURL = xContentAccess->queryContentIdentifierString();
+ OUString aTargetURL = xRow->getString( ROW_TARGET_URL );
+ sal_Bool bHasTargetURL = !xRow->wasNull() && aTargetURL.getLength() > 0;
+
+ OUString sRealURL = bHasTargetURL ? aTargetURL : aContentURL;
+
+ // check for restrictions
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( m_pFilter && !m_pFilter->isUrlAllowed( sRealURL ) )
+ continue;
+
+ if ( /* m_rBlackList.hasElements() && */ URLOnBlackList ( sRealURL ) )
+ continue;
+ }
+
+ pData = new SortingData_Impl;
+ pData->maTargetURL = sRealURL;
+
+ pData->mbIsFolder = xRow->getBoolean( ROW_IS_FOLDER ) && !xRow->wasNull();
+ pData->mbIsVolume = xRow->getBoolean( ROW_IS_VOLUME ) && !xRow->wasNull();
+ pData->mbIsRemote = xRow->getBoolean( ROW_IS_REMOTE ) && !xRow->wasNull();
+ pData->mbIsRemoveable = xRow->getBoolean( ROW_IS_REMOVEABLE ) && !xRow->wasNull();
+ pData->mbIsFloppy = xRow->getBoolean( ROW_IS_FLOPPY ) && !xRow->wasNull();
+ pData->mbIsCompactDisc = xRow->getBoolean( ROW_IS_COMPACTDISC ) && !xRow->wasNull();
+ pData->SetNewTitle( xRow->getString( ROW_TITLE ) );
+ pData->maSize = xRow->getLong( ROW_SIZE );
+
+ if ( bHasTargetURL &&
+ INetURLObject( aContentURL ).GetProtocol() == INET_PROT_VND_SUN_STAR_HIER )
+ {
+ ::ucbhelper::Content aCnt( aTargetURL, xEnvironment );
+ try
+ {
+ aCnt.getPropertyValue( OUString::createFromAscii( "Size" ) ) >>= pData->maSize;
+ aCnt.getPropertyValue( OUString::createFromAscii( "DateModified" ) ) >>= aDT;
+ }
+ catch (...) {}
+ }
+
+ if ( bContainsDate )
+ {
+ CONVERT_DATETIME( aDT, pData->maModDate );
+ }
+
+ if ( pData->mbIsFolder )
+ {
+ ::vos::OGuard aGuard( Application::GetSolarMutex() );
+ ::svtools::VolumeInfo aVolInfo( pData->mbIsVolume, pData->mbIsRemote,
+ pData->mbIsRemoveable, pData->mbIsFloppy,
+ pData->mbIsCompactDisc );
+ pData->maType = SvFileInformationManager::GetFolderDescription( aVolInfo );
+ }
+ else
+ pData->maType = SvFileInformationManager::GetFileDescription(
+ INetURLObject( pData->maTargetURL ) );
+
+ // replace names on demand
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if( m_pTranslator )
+ {
+ OUString sNewTitle;
+ sal_Bool bTranslated = sal_False;
+
+ if ( pData->mbIsFolder )
+ bTranslated = m_pTranslator->GetTranslation( pData->GetTitle(), sNewTitle );
+ else
+ bTranslated = implGetDocTitle( pData->maTargetURL, sNewTitle );
+
+ if ( bTranslated )
+ pData->ChangeTitle( sNewTitle );
+ }
+ }
+
+ {
+ ::osl::MutexGuard aGuard( m_rContentMutex );
+ m_rContent.push_back( pData );
+ }
+ }
+
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ bCancelled = m_bCancelled;
+ }
+ }
+ eResult = SUCCESS;
+ }
+ catch( CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "FileViewContentEnumerator::enumerateFolderContent: caught an CommandAbortedException while enumerating!" );
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "FileViewContentEnumerator::enumerateFolderContent: caught an exception other than CommandAbortedException while enumerating!" );
+ }
+ }
+ }
+ catch( CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "FileViewContentEnumerator::enumerateFolderContent: caught an CommandAbortedException!" );
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "FileViewContentEnumerator::enumerateFolderContent: caught an exception other than CommandAbortedException!" );
+ }
+
+ IEnumerationResultHandler* pHandler = NULL;
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ pHandler = m_pResultHandler;
+ if ( m_bCancelled )
+ return ERROR;
+ }
+
+ {
+ ::osl::MutexGuard aGuard( m_rContentMutex );
+ if ( eResult != SUCCESS )
+ // clear any "intermediate" and unfinished result
+ m_rContent.clear();
+ }
+
+ if ( pHandler )
+ pHandler->enumerationDone( eResult );
+ return eResult;
+ }
+
+ //--------------------------------------------------------------------
+
+ sal_Bool FileViewContentEnumerator::URLOnBlackList ( const ::rtl::OUString& sRealURL )
+ {
+ ::rtl::OUString entryName = sRealURL.copy( sRealURL.lastIndexOf( rtl::OUString::createFromAscii("/")) +1 );
+
+ for (int i = 0; i < m_rBlackList.getLength() ; i++)
+ {
+ if ( entryName.equals( m_rBlackList[i] ) )
+ return true;
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool FileViewContentEnumerator::implGetDocTitle( const OUString& _rTargetURL, OUString& _rRet ) const
+ {
+ sal_Bool bRet = sal_False;
+
+ try
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if( !m_xDocInfo.is() )
+ {
+ m_xDocInfo = m_xDocInfo.query(
+ ::comphelper::getProcessServiceFactory()->createInstance(
+ String( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.StandaloneDocumentInfo") )
+ )
+ );
+ }
+
+ DBG_ASSERT( m_xDocInfo.is(), "FileViewContentEnumerator::implGetDocTitle: no DocumentProperties service!" );
+ if ( !m_xDocInfo.is() )
+ return sal_False;
+
+ m_xDocInfo->loadFromURL( _rTargetURL );
+ Reference< XPropertySet > xPropSet( m_xDocInfo, UNO_QUERY );
+
+ Any aAny = xPropSet->getPropertyValue( OUString::createFromAscii( "Title" ) );
+
+ OUString sTitle;
+ if ( ( aAny >>= sTitle ) && sTitle.getLength() > 0 )
+ {
+ _rRet = sTitle;
+ bRet = sal_True;
+ }
+ }
+ catch ( const Exception& )
+ {
+ }
+
+ return bRet;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FileViewContentEnumerator::run()
+ {
+ enumerateFolderContent();
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FileViewContentEnumerator::onTerminated()
+ {
+ release();
+ }
+
+//........................................................................
+} // namespace svt
+//........................................................................
+
diff --git a/svtools/source/contnr/contentenumeration.hxx b/svtools/source/contnr/contentenumeration.hxx
new file mode 100644
index 000000000000..16db279ad547
--- /dev/null
+++ b/svtools/source/contnr/contentenumeration.hxx
@@ -0,0 +1,287 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef SVTOOLS_SOURCE_CONTNR_CONTENTENUMERATION_HXX
+#define SVTOOLS_SOURCE_CONTNR_CONTENTENUMERATION_HXX
+
+/** === begin UNO includes === **/
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/document/XStandaloneDocumentInfo.hpp>
+/** === end UNO includes === **/
+#include <osl/thread.hxx>
+#include <rtl/ref.hxx>
+#include <ucbhelper/content.hxx>
+#include <rtl/ustring.hxx>
+#include <tools/datetime.hxx>
+#include <vcl/image.hxx>
+
+class IUrlFilter;
+//........................................................................
+namespace svt
+{
+//........................................................................
+
+ //====================================================================
+ //= SortingData_Impl
+ //====================================================================
+ struct SortingData_Impl
+ {
+ private:
+ ::rtl::OUString maFilename; // only filename in upper case - for compare purposes
+ ::rtl::OUString maTitle; // -> be carefull when changing maTitle to update maFilename only when new
+ ::rtl::OUString maLowerTitle;
+
+
+ public:
+ ::rtl::OUString maType;
+ ::rtl::OUString maTargetURL;
+ ::rtl::OUString maImageURL;
+ ::rtl::OUString maDisplayText;
+ DateTime maModDate;
+ Image maImage;
+ sal_Int64 maSize;
+ sal_Bool mbIsFolder;
+ sal_Bool mbIsVolume;
+ sal_Bool mbIsRemote;
+ sal_Bool mbIsRemoveable;
+ sal_Bool mbIsFloppy;
+ sal_Bool mbIsCompactDisc;
+
+ inline SortingData_Impl();
+ inline const ::rtl::OUString& GetTitle() const;
+ inline const ::rtl::OUString& GetLowerTitle() const;
+ inline const ::rtl::OUString& GetFileName() const;
+ inline void SetNewTitle( const ::rtl::OUString& rNewTitle ); // new maTitle is set -> maFilename is set to same!
+ inline void ChangeTitle( const ::rtl::OUString& rChangedTitle ); // maTitle is changed, maFilename is unchanged!
+
+ private:
+ inline void SetTitles( const ::rtl::OUString& rNewTitle );
+ };
+
+ inline SortingData_Impl::SortingData_Impl() :
+ maSize ( 0 ),
+ mbIsFolder ( sal_False ),
+ mbIsVolume ( sal_False ),
+ mbIsRemote ( sal_False ),
+ mbIsRemoveable ( sal_False ),
+ mbIsFloppy ( sal_False ),
+ mbIsCompactDisc ( sal_False )
+ {
+ }
+
+ inline const ::rtl::OUString& SortingData_Impl::GetTitle() const
+ {
+ return maTitle;
+ }
+
+ inline const ::rtl::OUString& SortingData_Impl::GetLowerTitle() const
+ {
+ return maLowerTitle;
+ }
+
+ inline const ::rtl::OUString& SortingData_Impl::GetFileName() const
+ {
+ return maFilename;
+ }
+
+ inline void SortingData_Impl::SetNewTitle( const ::rtl::OUString& rNewTitle )
+ {
+ SetTitles( rNewTitle );
+ maFilename = rNewTitle.toAsciiUpperCase();
+ }
+
+ inline void SortingData_Impl::ChangeTitle( const ::rtl::OUString& rChangedTitle )
+ {
+ SetTitles( rChangedTitle );
+ }
+
+ inline void SortingData_Impl::SetTitles( const ::rtl::OUString& rNewTitle )
+ {
+ maTitle = rNewTitle;
+ maLowerTitle = rNewTitle.toAsciiLowerCase();
+ }
+
+ //====================================================================
+ //= IContentTitleTranslation
+ //====================================================================
+ class IContentTitleTranslation
+ {
+ public:
+ virtual sal_Bool GetTranslation( const ::rtl::OUString& _rOriginalName, ::rtl::OUString& _rTranslatedName ) const = 0;
+ };
+
+ //====================================================================
+ //= EnumerationResult
+ //====================================================================
+ enum EnumerationResult
+ {
+ SUCCESS, /// the enumration was successfull
+ ERROR, /// the enumration was unsuccessfull
+ RUNNING /// the enumeration is still running, and the maximum wait time has passed
+ };
+
+ //====================================================================
+ //= FolderDescriptor
+ //====================================================================
+ struct FolderDescriptor
+ {
+ /** a content object describing the folder. Can be <NULL/>, in this case <member>sURL</member>
+ is relevant.
+ */
+ ::ucbhelper::Content aContent;
+ /** the URL of a folder. Will be ignored if <member>aContent</member> is not <NULL/>.
+ */
+ String sURL;
+
+ FolderDescriptor() { }
+
+ FolderDescriptor( const ::ucbhelper::Content& _rContent )
+ :aContent( _rContent )
+ {
+ }
+
+ FolderDescriptor( const String& _rURL )
+ :sURL( _rURL )
+ {
+ }
+ };
+
+ //====================================================================
+ //= IEnumerationResultHandler
+ //====================================================================
+ class IEnumerationResultHandler
+ {
+ public:
+ virtual void enumerationDone( EnumerationResult _eResult ) = 0;
+ };
+
+ //====================================================================
+ //= FileViewContentEnumerator
+ //====================================================================
+ class FileViewContentEnumerator
+ :public ::rtl::IReference
+ ,private ::osl::Thread
+ {
+ public:
+ typedef ::std::vector< SortingData_Impl* > ContentData;
+
+ private:
+ ContentData& m_rContent;
+ ::osl::Mutex& m_rContentMutex;
+
+ oslInterlockedCount m_refCount;
+ mutable ::osl::Mutex m_aMutex;
+
+ FolderDescriptor m_aFolder;
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >
+ m_xCommandEnv;
+ const IUrlFilter* m_pFilter;
+ const IContentTitleTranslation* m_pTranslator;
+ IEnumerationResultHandler* m_pResultHandler;
+ bool m_bCancelled;
+
+ mutable ::com::sun::star::uno::Reference< ::com::sun::star::document::XStandaloneDocumentInfo >
+ m_xDocInfo;
+
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > m_rBlackList;
+
+ sal_Bool URLOnBlackList ( const ::rtl::OUString& sRealURL );
+
+ public:
+ /** constructs an enumerator instance
+
+ @param _rContentToFill
+ the structure which is to be filled with the found content
+ @param _rContentMutex
+ the mutex which protects the access to <arg>_rContentToFill</arg>
+ @param _pTranslator
+ an instance which should be used to translate content titles. May be <NULL/>
+ */
+ FileViewContentEnumerator(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& _rxCommandEnv,
+ ContentData& _rContentToFill,
+ ::osl::Mutex& _rContentMutex,
+ const IContentTitleTranslation* _pTranslator
+ );
+
+ /** enumerates the content of a given folder
+
+ @param _rFolder
+ the folder whose content is to be enumerated
+ @param _pFilter
+ a filter to apply to the found contents
+ @param _pResultHandler
+ an instance which should handle the results of the enumeration
+ */
+ void enumerateFolderContent(
+ const FolderDescriptor& _rFolder,
+ const IUrlFilter* _pFilter,
+ IEnumerationResultHandler* _pResultHandler
+ );
+
+ /** enumerates the content of a given folder synchronously
+ */
+ EnumerationResult enumerateFolderContentSync(
+ const FolderDescriptor& _rFolder,
+ const IUrlFilter* _pFilter,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >()
+ );
+
+ /** cancels the running operation.
+
+ Note that "cancel" may mean that the operation is running, but its result
+ is simply disregarded later on.
+ */
+ void cancel();
+
+ // IReference overridables
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+ using Thread::operator new;
+ using Thread::operator delete;
+
+ protected:
+ ~FileViewContentEnumerator();
+
+ private:
+ EnumerationResult enumerateFolderContent();
+
+ // Thread overridables
+ virtual void SAL_CALL run();
+ virtual void SAL_CALL onTerminated();
+
+ private:
+ sal_Bool implGetDocTitle( const ::rtl::OUString& _rTargetURL, ::rtl::OUString& _rRet ) const;
+ };
+
+//........................................................................
+} // namespace svt
+//........................................................................
+
+#endif // SVTOOLS_SOURCE_CONTNR_CONTENTENUMERATION_HXX
+
diff --git a/svtools/source/contnr/ctrdll.cxx b/svtools/source/contnr/ctrdll.cxx
new file mode 100644
index 000000000000..463c6ccc8b35
--- /dev/null
+++ b/svtools/source/contnr/ctrdll.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_svtools.hxx"
+
+#ifdef WIN
+#include <svwin.h>
+
+#ifndef _SYSDEP_HXX
+#include <sysdep.hxx>
+#endif
+
+// Statische DLL-Verwaltungs-Variablen
+static HINSTANCE hDLLInst = 0; // HANDLE der DLL
+
+
+/***************************************************************************
+|*
+|* LibMain()
+|*
+|* Beschreibung Initialisierungsfunktion der DLL
+|* Ersterstellung TH 05.05.93
+|* Letzte Aenderung TH 05.05.93
+|*
+***************************************************************************/
+
+extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
+{
+#ifndef WNT
+ if ( nHeap )
+ UnlockData( 0 );
+#endif
+
+ hDLLInst = hDLL;
+
+ return TRUE;
+}
+
+/***************************************************************************
+|*
+|* WEP()
+|*
+|* Beschreibung DLL-Deinitialisierung
+|* Ersterstellung TH 05.05.93
+|* Letzte Aenderung TH 05.05.93
+|*
+***************************************************************************/
+
+extern "C" int CALLBACK WEP( int )
+{
+ return 1;
+}
+
+#endif
diff --git a/svtools/source/contnr/fileview.cxx b/svtools/source/contnr/fileview.cxx
new file mode 100644
index 000000000000..af19379d8b8f
--- /dev/null
+++ b/svtools/source/contnr/fileview.cxx
@@ -0,0 +1,2809 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+#include "fileview.hxx"
+#include <svtools/svtdata.hxx>
+#include "imagemgr.hxx"
+#include <svtools/headbar.hxx>
+#include <svtools/svtabbx.hxx>
+
+#include <svtools/svtools.hrc>
+#include "fileview.hrc"
+#include "contentenumeration.hxx"
+#include <svtools/AccessibleBrowseBoxObjType.hxx>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/ucb/XAnyCompareFactory.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/ucb/XDynamicResultSet.hpp>
+#include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/ucb/CommandAbortedException.hpp>
+#include <com/sun/star/ucb/ContentCreationException.hpp>
+#include <vcl/waitobj.hxx>
+#include <com/sun/star/io/XPersist.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <algorithm>
+#include <memory>
+#include <tools/urlobj.hxx>
+#include <tools/datetime.hxx>
+#include <comphelper/processfactory.hxx>
+#include <unotools/localfilehelper.hxx>
+#include <ucbhelper/content.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+#include <vcl/msgbox.hxx>
+#ifndef INCLUDED_RTL_MATH_H
+#include <rtl/math.hxx>
+#endif
+#include <tools/config.hxx>
+#include <osl/mutex.hxx>
+#include <osl/conditn.hxx>
+#include <vos/timer.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/sound.hxx>
+#include <unotools/ucbhelper.hxx>
+#include <unotools/intlwrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <svl/urlfilter.hxx>
+
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::beans;
+using namespace ::comphelper;
+using ::svt::SortingData_Impl;
+using ::svt::FolderDescriptor;
+using ::vos::TTimeValue;
+using ::rtl::OUString;
+
+#define ALL_FILES_FILTER "*.*"
+
+#define COLUMN_TITLE 1
+#define COLUMN_TYPE 2
+#define COLUMN_SIZE 3
+#define COLUMN_DATE 4
+
+DECLARE_LIST( StringList_Impl, OUString* )
+
+#define ROW_HEIGHT 17 // the height of a row has to be a little higher than the bitmap
+#define QUICK_SEARCH_TIMEOUT 1500 // time in mSec before the quicksearch string will be reseted
+
+namespace
+{
+ //====================================================================
+ //= ReleaseSolarMutex
+ //====================================================================
+ struct ReleaseSolarMutex
+ {
+ private:
+ ULONG m_nCount;
+
+ public:
+ inline ReleaseSolarMutex()
+ {
+ m_nCount = Application::ReleaseSolarMutex();
+ }
+ inline ~ReleaseSolarMutex()
+ {
+ Application::AcquireSolarMutex( m_nCount );
+ }
+ };
+
+ //====================================================================
+ //= ITimeoutHandler
+ //====================================================================
+ class CallbackTimer;
+ class ITimeoutHandler
+ {
+ public:
+ virtual void onTimeout( CallbackTimer* _pInstigator ) = 0;
+ };
+
+ //====================================================================
+ //= CallbackTimer
+ //====================================================================
+ class CallbackTimer : public ::vos::OTimer
+ {
+ protected:
+ ITimeoutHandler* m_pTimeoutHandler;
+
+ public:
+ CallbackTimer( ITimeoutHandler* _pHandler ) : m_pTimeoutHandler( _pHandler ) { }
+
+ protected:
+ virtual void SAL_CALL onShot();
+ };
+
+ //--------------------------------------------------------------------
+ void SAL_CALL CallbackTimer::onShot()
+ {
+ OSL_ENSURE( m_pTimeoutHandler, "CallbackTimer::onShot: nobody interested in?" );
+ ITimeoutHandler* pHandler( m_pTimeoutHandler );
+ if ( pHandler )
+ pHandler->onTimeout( this );
+ }
+
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Bool isHighContrast( const Window* _pView )
+{
+ return _pView->GetSettings().GetStyleSettings().GetHighContrastMode();
+}
+
+// -----------------------------------------------------------------------
+
+void FilterMatch::createWildCardFilterList(const String& _rFilterList,::std::vector< WildCard >& _rFilters)
+{
+ if( _rFilterList.Len() )
+ {// filter is given
+ xub_StrLen nCount = _rFilterList.GetTokenCount();
+ _rFilters.reserve( nCount );
+ xub_StrLen nIndex = 0;
+ OUString sToken;
+ do
+ {
+ sToken = _rFilterList.GetToken( 0, ';', nIndex );
+ if ( sToken.getLength() )
+ {
+ _rFilters.push_back( WildCard( sToken.toAsciiUpperCase() ) );
+ }
+ }
+ while ( nIndex != STRING_NOTFOUND );
+ }
+ else
+ // no filter is given -> match all
+ _rFilters.push_back( WildCard( String::CreateFromAscii( "*" ) ) );
+}
+// class ViewTabListBox_Impl ---------------------------------------------
+
+class ViewTabListBox_Impl : public SvHeaderTabListBox
+{
+private:
+ Reference< XCommandEnvironment > mxCmdEnv;
+
+ ::osl::Mutex maMutex;
+ HeaderBar* mpHeaderBar;
+ SvtFileView_Impl* mpParent;
+ Timer maResetQuickSearch;
+ OUString maQuickSearchText;
+ String msAccessibleDescText;
+ String msFolder;
+ String msFile;
+ sal_uInt32 mnSearchIndex;
+ sal_Bool mbResizeDisabled : 1;
+ sal_Bool mbAutoResize : 1;
+ sal_Bool mbEnableDelete : 1;
+ sal_Bool mbEnableRename : 1;
+
+ void DeleteEntries();
+ void DoQuickSearch( const xub_Unicode& rChar );
+ sal_Bool Kill( const OUString& rURL );
+
+protected:
+ virtual BOOL DoubleClickHdl();
+ virtual ::rtl::OUString GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const;
+
+public:
+ ViewTabListBox_Impl( Window* pParentWin, SvtFileView_Impl* pParent, sal_Int16 nFlags );
+ ~ViewTabListBox_Impl();
+
+ virtual void Resize();
+ virtual void KeyInput( const KeyEvent& rKEvt );
+ virtual BOOL EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText );
+
+ void ClearAll();
+ HeaderBar* GetHeaderBar() const { return mpHeaderBar; }
+
+ void EnableAutoResize() { mbAutoResize = sal_True; }
+ void EnableDelete( sal_Bool bEnable ) { mbEnableDelete = bEnable; }
+ void EnableRename( sal_Bool bEnable ) { mbEnableRename = bEnable; }
+ sal_Bool IsDeleteOrContextMenuEnabled() { return mbEnableDelete || IsContextMenuHandlingEnabled(); }
+
+ Reference< XCommandEnvironment > GetCommandEnvironment() const { return mxCmdEnv; }
+
+ DECL_LINK( ResetQuickSearch_Impl, Timer * );
+
+ virtual PopupMenu* CreateContextMenu( void );
+ virtual void ExcecuteContextMenuAction( USHORT nSelectedPopentry );
+};
+
+// class HashedEntry --------------------------------------------------
+
+class HashedEntry
+{ // just a special String which can be compared on equality much faster
+protected:
+ OUString maName;
+ sal_Int32 mnHashCode;
+public:
+ inline HashedEntry( const OUString& rName );
+ inline HashedEntry( const INetURLObject& rURL );
+ inline HashedEntry( const HashedEntry& rCopy );
+ virtual ~HashedEntry();
+
+ inline sal_Bool operator ==( const HashedEntry& rRef ) const;
+ inline sal_Bool operator !=( const HashedEntry& rRef ) const;
+
+ inline const OUString& GetName() const;
+};
+
+inline HashedEntry::HashedEntry( const OUString& rName ): maName( rName ), mnHashCode( rName.hashCode() )
+{
+}
+
+inline HashedEntry::HashedEntry( const INetURLObject& rURL ):
+ maName( rURL.GetMainURL( INetURLObject::NO_DECODE ) ),
+ mnHashCode( maName.hashCode() )
+{
+}
+
+inline HashedEntry::HashedEntry( const HashedEntry& r ): maName( r.maName ), mnHashCode( r.mnHashCode )
+{
+}
+
+HashedEntry::~HashedEntry()
+{
+}
+
+inline sal_Bool HashedEntry::operator ==( const HashedEntry& rRef ) const
+{
+ return mnHashCode == rRef.mnHashCode && maName.reverseCompareTo( rRef.maName ) == 0;
+}
+
+inline sal_Bool HashedEntry::operator !=( const HashedEntry& rRef ) const
+{
+ return mnHashCode != rRef.mnHashCode || maName.reverseCompareTo( rRef.maName ) != 0;
+}
+
+inline const OUString& HashedEntry::GetName() const
+{
+ return maName;
+}
+
+// class HashedEntryList ----------------------------------------------
+
+class HashedEntryList : protected List
+{// provides a list of _unique_ Entries
+protected:
+ inline HashedEntry* First();
+ inline HashedEntry* Next();
+ inline void Append( HashedEntry* pNewEntry );
+public:
+ virtual ~HashedEntryList();
+
+ const HashedEntry* Find( const OUString& rNameToSearchFor );
+ const HashedEntry* Find( const HashedEntry& rToSearchFor );
+ // not const, because First()/Next() is used
+ using List::Insert;
+ const HashedEntry& Insert( HashedEntry* pInsertOrDelete );
+ // don't care about pInsertOrDelete after this any more and handle it as invalid!
+ // returns the Entry, which is effectively inserted
+
+ void Clear();
+};
+
+inline HashedEntry* HashedEntryList::First()
+{
+ return ( HashedEntry* ) List::First();
+}
+
+inline HashedEntry* HashedEntryList::Next()
+{
+ return ( HashedEntry* ) List::Next();
+}
+
+inline void HashedEntryList::Append( HashedEntry* pNew )
+{
+ List::Insert( pNew, LIST_APPEND );
+}
+
+HashedEntryList::~HashedEntryList()
+{
+ Clear();
+}
+
+const HashedEntry* HashedEntryList::Find( const OUString& rRefName )
+{ // simple linear search, which should be fast enough for this purpose
+ HashedEntry aRef( rRefName );
+ HashedEntry* pIter = First();
+ while( pIter && *pIter != aRef )
+ pIter = Next();
+
+ return pIter;
+}
+
+const HashedEntry* HashedEntryList::Find( const HashedEntry& rRef )
+{ // simple linear search, which should be fast enough for this purpose
+ HashedEntry* pIter = First();
+ while( pIter && *pIter != rRef )
+ pIter = Next();
+
+ return pIter;
+}
+
+const HashedEntry& HashedEntryList::Insert( HashedEntry* pNew )
+{ // inserts (appends) only, if entry doesn't already exists
+ // if it already exists, pNew is deleted, because the caller must not worry about pNew any more
+
+ DBG_ASSERT( pNew, "HashedEntryList::Insert(): NULL-pointer can't be inserted" );
+
+ const HashedEntry* pSearch = Find( *pNew );
+ if( pSearch )
+ {
+ delete pNew;
+ return *pSearch;
+ }
+
+ Append( pNew );
+
+ return *pNew;
+}
+
+void HashedEntryList::Clear()
+{
+ HashedEntry* p = First();
+ while( p )
+ {
+ delete p;
+ p = Next();
+ }
+}
+
+// class NameTranslationEntry -----------------------------------------
+
+class NameTranslationEntry : public HashedEntry
+{// a fast compareble String and another String, which is used to get a substitution for a given String
+protected:
+ OUString maTranslatedName;
+public:
+ inline NameTranslationEntry( const OUString& rOriginalName, const OUString& rTranslatedName );
+ inline NameTranslationEntry( const ByteString& rOriginalName, const ByteString& rTranslatedName );
+
+ inline const OUString& GetTranslation() const;
+};
+
+inline NameTranslationEntry::NameTranslationEntry( const OUString& rOrg, const OUString& rTrans ):
+ HashedEntry( rOrg ),
+ maTranslatedName( rTrans )
+{
+}
+
+inline NameTranslationEntry::NameTranslationEntry( const ByteString& rOrg, const ByteString& rTrans ):
+ HashedEntry( OUString( rOrg.GetBuffer(), rOrg.Len(), RTL_TEXTENCODING_ASCII_US ) ),
+ maTranslatedName( OUString( rTrans.GetBuffer(), rTrans.Len(), RTL_TEXTENCODING_UTF8 ) )
+{
+}
+
+inline const OUString& NameTranslationEntry::GetTranslation() const
+{
+ return maTranslatedName;
+}
+
+// class NameTranslationList -----------------------------------------
+
+class NameTranslationList : protected HashedEntryList
+{ // contains a list of substitutes of strings for a given folder (as URL)
+ // explanation of the circumstances see in remarks for Init();
+protected:
+ INetURLObject maTransFile; // URL of file with translation entries
+ HashedEntry maHashedURL; // for future purposes when dealing with a set of cached
+ // NameTranslationLists
+private:
+ const String maTransFileName;
+ void Init(); // reads the translation file and fills the (internal) list
+
+public:
+ NameTranslationList( const INetURLObject& rBaseURL );
+ // rBaseURL: path to folder for which the translation of the entries
+ // should be done
+
+ using List::operator==;
+ inline sal_Bool operator ==( const HashedEntry& rRef ) const;
+ using List::operator!=;
+ inline sal_Bool operator !=( const HashedEntry& rRef ) const;
+
+ const OUString* Translate( const OUString& rName ) const;
+ // returns NULL, if rName can't be found
+
+ inline void Update(); // clears list and init
+
+ inline const String& GetTransTableFileName() const;
+ // returns the name for the file, which contains the translation strings
+};
+
+inline const String& NameTranslationList::GetTransTableFileName() const
+{
+ return maTransFileName;
+}
+
+void NameTranslationList::Init()
+{
+// Tries to read the file ".nametranslation.table" in the base folder. Complete path/name is in maTransFile.
+// Further on, the found entries in the section "TRANSLATIONNAMES" are used to replace names in the
+// base folder by translated ones. The translation must be given in UTF8
+// See examples of such a files in the samples-folder of an Office installation
+
+ try
+ {
+ ::ucbhelper::Content aTestContent( maTransFile.GetMainURL( INetURLObject::NO_DECODE ), Reference< XCommandEnvironment >() );
+
+ if( aTestContent.isDocument() )
+ {// ... also tests the existence of maTransFile by throwing an Exception
+ const sal_Char* pSection = "TRANSLATIONNAMES";
+ String aFsysName( maTransFile.getFSysPath( INetURLObject::FSYS_DETECT ) );
+ Config aConfig( aFsysName );
+
+ aConfig.SetGroup( ByteString( pSection ) );
+
+ USHORT nKeyCnt = aConfig.GetKeyCount();
+
+ for( USHORT nCnt = 0 ; nCnt < nKeyCnt ; ++nCnt )
+ Insert( new NameTranslationEntry( aConfig.GetKeyName( nCnt ), aConfig.ReadKey( nCnt ) ) );
+ }
+ }
+ catch( Exception const & ) {}
+}
+
+NameTranslationList::NameTranslationList( const INetURLObject& rBaseURL ):
+ maTransFile( rBaseURL ),
+ maHashedURL( rBaseURL ),
+ maTransFileName( String::CreateFromAscii( ".nametranslation.table" ) )
+{
+ maTransFile.insertName( maTransFileName );
+ Init();
+}
+
+inline sal_Bool NameTranslationList::operator ==( const HashedEntry& rRef ) const
+{
+ return maHashedURL == rRef;
+}
+
+inline sal_Bool NameTranslationList::operator !=( const HashedEntry& rRef ) const
+{
+ return maHashedURL != rRef;
+}
+
+const OUString* NameTranslationList::Translate( const OUString& rName ) const
+{
+ const NameTranslationEntry* pSearch = static_cast< const NameTranslationEntry* >(
+ ( const_cast< NameTranslationList* >( this ) )->Find( rName ) );
+
+ return pSearch? &pSearch->GetTranslation() : NULL;
+}
+
+inline void NameTranslationList::Update()
+{
+ Clear();
+ Init();
+}
+
+// class NameTranslator_Impl ------------------------------------------
+
+// enables the user to get string substitutions (translations for the content) for a given folder
+// see more explanations above in the description for NameTranslationList
+class NameTranslator_Impl : public ::svt::IContentTitleTranslation
+{
+private:
+ NameTranslationList* mpActFolder;
+public:
+ NameTranslator_Impl( void );
+ NameTranslator_Impl( const INetURLObject& rActualFolder );
+ virtual ~NameTranslator_Impl();
+
+ // IContentTitleTranslation
+ virtual sal_Bool GetTranslation( const OUString& rOriginalName, OUString& rTranslatedName ) const;
+
+ void UpdateTranslationTable(); // reads the translation file again
+
+ void SetActualFolder( const INetURLObject& rActualFolder );
+ const String* GetTransTableFileName() const;
+ // returns the name for the file, which contains the translation strings
+};
+
+//====================================================================
+//= SvtFileView_Impl
+//====================================================================
+
+class SvtFileView_Impl :public ::svt::IEnumerationResultHandler
+ ,public ITimeoutHandler
+{
+protected:
+ SvtFileView* mpAntiImpl;
+ Link m_aSelectHandler;
+
+ ::rtl::Reference< ::svt::FileViewContentEnumerator >
+ m_pContentEnumerator;
+ Link m_aCurrentAsyncActionHandler;
+ ::osl::Condition m_aAsyncActionFinished;
+ ::rtl::Reference< ::vos::OTimer > m_pCancelAsyncTimer;
+ ::svt::EnumerationResult m_eAsyncActionResult;
+ bool m_bRunningAsyncAction;
+ bool m_bAsyncActionCancelled;
+
+
+public:
+
+ ::std::vector< SortingData_Impl* > maContent;
+ ::osl::Mutex maMutex;
+
+ ViewTabListBox_Impl* mpView;
+ NameTranslator_Impl* mpNameTrans;
+ const IUrlFilter* mpUrlFilter;
+ sal_uInt16 mnSortColumn;
+ sal_Bool mbAscending : 1;
+ sal_Bool mbOnlyFolder : 1;
+ sal_Bool mbReplaceNames : 1; // translate folder names or display doc-title instead of file name
+ sal_Int16 mnSuspendSelectCallback : 1;
+ sal_Bool mbIsFirstResort : 1;
+
+ IntlWrapper aIntlWrapper;
+
+ String maViewURL;
+ String maAllFilter;
+ String maCurrentFilter;
+ Image maFolderImage;
+ Link maOpenDoneLink;
+ Reference< XCommandEnvironment > mxCmdEnv;
+
+ SvtFileView_Impl( SvtFileView* pAntiImpl, Reference < XCommandEnvironment > xEnv,
+ sal_Int16 nFlags,
+ sal_Bool bOnlyFolder );
+ virtual ~SvtFileView_Impl();
+
+ void Clear();
+
+ FileViewResult GetFolderContent_Impl(
+ const String& rFolder,
+ const FileViewAsyncAction* pAsyncDescriptor,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >() );
+
+ FileViewResult GetFolderContent_Impl(
+ const FolderDescriptor& _rFolder,
+ const FileViewAsyncAction* pAsyncDescriptor,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >());
+ void FilterFolderContent_Impl( const OUString &rFilter );
+ void CancelRunningAsyncAction();
+
+ void OpenFolder_Impl();
+ // #83004# -------
+ void ReplaceTabWithString( OUString& aValue );
+ void CreateDisplayText_Impl();
+ void CreateVector_Impl( const Sequence < OUString > &rList );
+ void SortFolderContent_Impl();
+
+ void EntryRemoved( const OUString& rURL );
+ void EntryRenamed( OUString& rURL,
+ const OUString& rName );
+ String FolderInserted( const OUString& rURL,
+ const OUString& rTitle );
+
+ ULONG GetEntryPos( const OUString& rURL );
+
+ inline void EnableContextMenu( sal_Bool bEnable );
+ inline void EnableDelete( sal_Bool bEnable );
+
+ void Resort_Impl( sal_Int16 nColumn, sal_Bool bAscending );
+ sal_Bool SearchNextEntry( sal_uInt32 &nIndex,
+ const OUString& rTitle,
+ sal_Bool bWrapAround );
+
+ inline sal_Bool EnableNameReplacing( sal_Bool bEnable = sal_True ); // returns false, if action wasn't possible
+ void SetActualFolder( const INetURLObject& rActualFolder );
+
+ sal_Bool GetDocTitle( const OUString& rTargetURL, OUString& rDocTitle ) const;
+
+ void SetSelectHandler( const Link& _rHdl );
+
+ void InitSelection();
+ void ResetCursor();
+
+ inline void EndEditing( bool _bCancel );
+
+protected:
+ DECL_LINK( SelectionMultiplexer, void* );
+
+protected:
+ // IEnumerationResultHandler overridables
+ virtual void enumerationDone( ::svt::EnumerationResult _eResult );
+ void implEnumerationSuccess();
+
+ // ITimeoutHandler
+ virtual void onTimeout( CallbackTimer* _pInstigator );
+};
+
+inline void SvtFileView_Impl::EnableContextMenu( sal_Bool bEnable )
+{
+ mpView->EnableContextMenuHandling( bEnable );
+ if( bEnable )
+ mbReplaceNames = sal_False;
+}
+
+inline void SvtFileView_Impl::EnableDelete( sal_Bool bEnable )
+{
+ mpView->EnableDelete( bEnable );
+ if( bEnable )
+ mbReplaceNames = sal_False;
+}
+
+inline sal_Bool SvtFileView_Impl::EnableNameReplacing( sal_Bool bEnable )
+{
+ mpView->EnableRename( bEnable );
+
+ sal_Bool bRet;
+ if( mpView->IsDeleteOrContextMenuEnabled() )
+ {
+ DBG_ASSERT( !mbReplaceNames, "SvtFileView_Impl::EnableNameReplacing(): state should be not possible!" );
+ bRet = !bEnable; // only for enabling this is an unsuccessful result
+ }
+ else
+ {
+ mbReplaceNames = bEnable;
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+inline void SvtFileView_Impl::EndEditing( bool _bCancel )
+{
+ if ( mpView->IsEditingActive() )
+ mpView->EndEditing( _bCancel != false );
+}
+
+// functions -------------------------------------------------------------
+
+OUString CreateExactSizeText_Impl( sal_Int64 nSize )
+{
+ double fSize( ( double ) nSize );
+ int nDec;
+
+ long nMega = 1024 * 1024;
+ long nGiga = nMega * 1024;
+
+ String aUnitStr = ' ';
+
+ if ( nSize < 10000 )
+ {
+ aUnitStr += String( SvtResId( STR_SVT_BYTES ) );
+ nDec = 0;
+ }
+ else if ( nSize < nMega )
+ {
+ fSize /= 1024;
+ aUnitStr += String( SvtResId( STR_SVT_KB ) );
+ nDec = 1;
+ }
+ else if ( nSize < nGiga )
+ {
+ fSize /= nMega;
+ aUnitStr += String( SvtResId( STR_SVT_MB ) );
+ nDec = 2;
+ }
+ else
+ {
+ fSize /= nGiga;
+ aUnitStr += String( SvtResId( STR_SVT_GB ) );
+ nDec = 3;
+ }
+
+ OUString aSizeStr( ::rtl::math::doubleToUString( fSize,
+ rtl_math_StringFormat_F, nDec,
+ SvtSysLocale().GetLocaleData().getNumDecimalSep().GetChar(0)));
+ aSizeStr += aUnitStr;
+
+ return aSizeStr;
+}
+
+// -----------------------------------------------------------------------
+// class ViewTabListBox_Impl ---------------------------------------------
+// -----------------------------------------------------------------------
+
+ViewTabListBox_Impl::ViewTabListBox_Impl( Window* pParentWin,
+ SvtFileView_Impl* pParent,
+ sal_Int16 nFlags ) :
+
+ SvHeaderTabListBox( pParentWin, WB_TABSTOP ),
+
+ mpHeaderBar ( NULL ),
+ mpParent ( pParent ),
+ msAccessibleDescText( SvtResId( STR_SVT_ACC_DESC_FILEVIEW ) ),
+ msFolder ( SvtResId( STR_SVT_ACC_DESC_FOLDER ) ),
+ msFile ( SvtResId( STR_SVT_ACC_DESC_FILE ) ),
+ mnSearchIndex ( 0 ),
+ mbResizeDisabled ( sal_False ),
+ mbAutoResize ( sal_False ),
+ mbEnableDelete ( sal_True ),
+ mbEnableRename ( sal_True )
+
+{
+ Size aBoxSize = pParentWin->GetSizePixel();
+ mpHeaderBar = new HeaderBar( pParentWin, WB_BUTTONSTYLE | WB_BOTTOMBORDER );
+ mpHeaderBar->SetPosSizePixel( Point( 0, 0 ), mpHeaderBar->CalcWindowSizePixel() );
+
+ HeaderBarItemBits nBits = ( HIB_LEFT | HIB_VCENTER | HIB_CLICKABLE );
+ if ( ( nFlags & FILEVIEW_SHOW_ALL ) == FILEVIEW_SHOW_ALL )
+ {
+ mpHeaderBar->InsertItem( COLUMN_TITLE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TITLE ) ), 180, nBits | HIB_UPARROW );
+ mpHeaderBar->InsertItem( COLUMN_TYPE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TYPE ) ), 140, nBits );
+ mpHeaderBar->InsertItem( COLUMN_SIZE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_SIZE ) ), 80, nBits );
+ mpHeaderBar->InsertItem( COLUMN_DATE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_DATE ) ), 500, nBits );
+ }
+ else
+ mpHeaderBar->InsertItem( COLUMN_TITLE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TITLE ) ), 600, nBits );
+
+ Size aHeadSize = mpHeaderBar->GetSizePixel();
+ SetPosSizePixel( Point( 0, aHeadSize.Height() ),
+ Size( aBoxSize.Width(), aBoxSize.Height() - aHeadSize.Height() ) );
+ InitHeaderBar( mpHeaderBar );
+ SetHighlightRange();
+ SetEntryHeight( ROW_HEIGHT );
+
+ Show();
+ mpHeaderBar->Show();
+
+ maResetQuickSearch.SetTimeout( QUICK_SEARCH_TIMEOUT );
+ maResetQuickSearch.SetTimeoutHdl( LINK( this, ViewTabListBox_Impl, ResetQuickSearch_Impl ) );
+
+ Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
+ Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
+ xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
+
+ mxCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
+
+ EnableContextMenuHandling();
+}
+
+// -----------------------------------------------------------------------
+
+ViewTabListBox_Impl::~ViewTabListBox_Impl()
+{
+ maResetQuickSearch.Stop();
+
+ delete mpHeaderBar;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ViewTabListBox_Impl, ResetQuickSearch_Impl, Timer*, EMPTYARG )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ maQuickSearchText = OUString();
+ mnSearchIndex = 0;
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ViewTabListBox_Impl::Resize()
+{
+ SvTabListBox::Resize();
+ Size aBoxSize = Control::GetParent()->GetOutputSizePixel();
+
+ if ( mbResizeDisabled || !aBoxSize.Width() )
+ return;
+
+ Size aBarSize = mpHeaderBar->GetSizePixel();
+ aBarSize.Width() = mbAutoResize ? aBoxSize.Width() : GetSizePixel().Width();
+ mpHeaderBar->SetSizePixel( aBarSize );
+
+ if ( mbAutoResize )
+ {
+ mbResizeDisabled = sal_True;
+ Point aPos = GetPosPixel();
+ SetPosSizePixel( Point( 0, aBarSize.Height() ),
+ Size( aBoxSize.Width(), aBoxSize.Height() - aBarSize.Height() ) );
+ mbResizeDisabled = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ViewTabListBox_Impl::KeyInput( const KeyEvent& rKEvt )
+{
+ bool bHandled = false;
+
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ if ( 0 == rKeyCode.GetModifier() )
+ {
+ if ( rKeyCode.GetCode() == KEY_RETURN )
+ {
+ ResetQuickSearch_Impl( NULL );
+ GetDoubleClickHdl().Call( this );
+ bHandled = true;
+ }
+ else if ( ( rKeyCode.GetCode() == KEY_DELETE ) &&
+ mbEnableDelete )
+ {
+ ResetQuickSearch_Impl( NULL );
+ DeleteEntries();
+ bHandled = true;
+ }
+ else if ( ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_NUM ) ||
+ ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_ALPHA ) )
+ {
+ DoQuickSearch( rKEvt.GetCharCode() );
+ bHandled = true;
+ }
+ }
+
+ if ( !bHandled )
+ {
+ ResetQuickSearch_Impl( NULL );
+ SvHeaderTabListBox::KeyInput( rKEvt );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+PopupMenu* ViewTabListBox_Impl::CreateContextMenu( void )
+{
+ bool bEnableDelete = mbEnableDelete;
+ bool bEnableRename = mbEnableRename;
+
+ if ( bEnableDelete || bEnableRename )
+ {
+ sal_Int32 nSelectedEntries = GetSelectionCount();
+ bEnableDelete &= nSelectedEntries > 0;
+ bEnableRename &= nSelectedEntries == 1;
+ }
+
+ if ( bEnableDelete || bEnableRename )
+ {
+ SvLBoxEntry* pEntry = FirstSelected();
+ while ( pEntry )
+ {
+ ::ucbhelper::Content aCnt;
+ try
+ {
+ OUString aURL( static_cast< SvtContentEntry * >(
+ pEntry->GetUserData() )->maURL );
+ aCnt = ::ucbhelper::Content( aURL, mxCmdEnv );
+ }
+ catch( Exception const & )
+ {
+ bEnableDelete = bEnableRename = false;
+ }
+
+ if ( bEnableDelete )
+ {
+ try
+ {
+ Reference< XCommandInfo > aCommands = aCnt.getCommands();
+ if ( aCommands.is() )
+ bEnableDelete
+ = aCommands->hasCommandByName(
+ OUString::createFromAscii( "delete" ) );
+ else
+ bEnableDelete = false;
+ }
+ catch( Exception const & )
+ {
+ bEnableDelete = false;
+ }
+ }
+
+ if ( bEnableRename )
+ {
+ try
+ {
+ Reference< XPropertySetInfo > aProps = aCnt.getProperties();
+ if ( aProps.is() )
+ {
+ Property aProp
+ = aProps->getPropertyByName(
+ OUString::createFromAscii( "Title" ) );
+ bEnableRename
+ = !( aProp.Attributes & PropertyAttribute::READONLY );
+ }
+ else
+ bEnableRename = false;
+ }
+ catch( Exception const & )
+ {
+ bEnableRename = false;
+ }
+ }
+
+ pEntry = ( bEnableDelete || bEnableRename )
+ ? NextSelected( pEntry )
+ : 0;
+ }
+ }
+
+ if ( bEnableDelete || bEnableRename )
+ {
+ PopupMenu * pRet
+ = new PopupMenu( SvtResId( RID_FILEVIEW_CONTEXTMENU ) );
+ pRet->EnableItem( MID_FILEVIEW_DELETE, bEnableDelete );
+ pRet->EnableItem( MID_FILEVIEW_RENAME, bEnableRename );
+ pRet->RemoveDisabledEntries( sal_True, sal_True );
+ return pRet;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ViewTabListBox_Impl::ExcecuteContextMenuAction( USHORT nSelectedPopupEntry )
+{
+ switch ( nSelectedPopupEntry )
+ {
+ case MID_FILEVIEW_DELETE :
+ DeleteEntries();
+ break;
+
+ case MID_FILEVIEW_RENAME :
+ EditEntry( FirstSelected() );
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ViewTabListBox_Impl::ClearAll()
+{
+ for ( USHORT i = 0; i < GetEntryCount(); ++i )
+ delete (SvtContentEntry*)GetEntry(i)->GetUserData();
+ Clear();
+}
+
+// -----------------------------------------------------------------------
+void ViewTabListBox_Impl::DeleteEntries()
+{
+ svtools::QueryDeleteResult_Impl eResult = svtools::QUERYDELETE_YES;
+ SvLBoxEntry* pEntry = FirstSelected();
+ String aURL;
+
+ ByteString sDialogPosition;
+ while ( pEntry && ( eResult != svtools::QUERYDELETE_CANCEL ) )
+ {
+ SvLBoxEntry *pCurEntry = pEntry;
+ pEntry = NextSelected( pEntry );
+
+ if ( pCurEntry->GetUserData() )
+ aURL = ( (SvtContentEntry*)pCurEntry->GetUserData() )->maURL;
+
+ if ( !aURL.Len() )
+ continue;
+
+ bool canDelete = true;
+ try
+ {
+ ::ucbhelper::Content aCnt( aURL, mxCmdEnv );
+ Reference< XCommandInfo > aCommands = aCnt.getCommands();
+ if ( aCommands.is() )
+ canDelete
+ = aCommands->hasCommandByName(
+ OUString::createFromAscii( "delete" ) );
+ else
+ canDelete = false;
+ }
+ catch( Exception const & )
+ {
+ canDelete = false;
+ }
+
+ if (!canDelete)
+ continue; // process next entry
+
+ if ( eResult != svtools::QUERYDELETE_ALL )
+ {
+ INetURLObject aObj( aURL );
+ svtools::QueryDeleteDlg_Impl aDlg( NULL, aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ) );
+ if ( sDialogPosition.Len() )
+ aDlg.SetWindowState( sDialogPosition );
+
+ if ( GetSelectionCount() > 1 )
+ aDlg.EnableAllButton();
+
+ if ( aDlg.Execute() == RET_OK )
+ eResult = aDlg.GetResult();
+ else
+ eResult = svtools::QUERYDELETE_CANCEL;
+
+ sDialogPosition = aDlg.GetWindowState( );
+ }
+
+ if ( ( eResult == svtools::QUERYDELETE_ALL ) ||
+ ( eResult == svtools::QUERYDELETE_YES ) )
+ {
+ if ( Kill( aURL ) )
+ {
+ delete (SvtContentEntry*)pCurEntry->GetUserData();
+ GetModel()->Remove( pCurEntry );
+ mpParent->EntryRemoved( aURL );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+BOOL ViewTabListBox_Impl::EditedEntry( SvLBoxEntry* pEntry,
+ const XubString& rNewText )
+{
+ BOOL bRet = FALSE;
+
+ OUString aURL;
+ SvtContentEntry* pData = (SvtContentEntry*)pEntry->GetUserData();
+
+ if ( pData )
+ aURL = OUString( pData->maURL );
+
+ if ( ! aURL.getLength() )
+ return bRet;
+
+ try
+ {
+ OUString aPropName = OUString::createFromAscii( "Title" );
+ bool canRename = true;
+ ::ucbhelper::Content aContent( aURL, mxCmdEnv );
+
+ try
+ {
+ Reference< XPropertySetInfo > aProps = aContent.getProperties();
+ if ( aProps.is() )
+ {
+ Property aProp = aProps->getPropertyByName( aPropName );
+ canRename = !( aProp.Attributes & PropertyAttribute::READONLY );
+ }
+ else
+ {
+ canRename = false;
+ }
+ }
+ catch ( Exception const & )
+ {
+ canRename = false;
+ }
+
+ if ( canRename )
+ {
+ Any aValue;
+ aValue <<= OUString( rNewText );
+ aContent.setPropertyValue( aPropName, aValue );
+ mpParent->EntryRenamed( aURL, rNewText );
+
+ pData->maURL = aURL;
+ pEntry->SetUserData( pData );
+
+ bRet = TRUE;
+ }
+ }
+ catch( Exception const & )
+ {
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+void ViewTabListBox_Impl::DoQuickSearch( const xub_Unicode& rChar )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ maResetQuickSearch.Stop();
+
+ OUString aLastText = maQuickSearchText;
+ sal_uInt32 aLastPos = mnSearchIndex;
+ sal_Bool bFound = sal_False;
+
+ maQuickSearchText += OUString( String( rChar ) ).toAsciiLowerCase();
+
+ bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, sal_False );
+
+ if ( !bFound && ( aLastText.getLength() == 1 ) &&
+ ( aLastText == OUString( String( rChar ) ) ) )
+ {
+ mnSearchIndex = aLastPos + 1;
+ maQuickSearchText = aLastText;
+ bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, sal_True );
+ }
+
+ if ( bFound )
+ {
+ SvLBoxEntry* pEntry = GetEntry( mnSearchIndex );
+ if ( pEntry )
+ {
+ SelectAll( FALSE );
+ Select( pEntry );
+ SetCurEntry( pEntry );
+ MakeVisible( pEntry );
+ }
+ else
+ bFound = sal_False;
+ }
+
+ if ( !bFound )
+ Sound::Beep();
+
+ maResetQuickSearch.Start();
+}
+
+// -----------------------------------------------------------------------
+BOOL ViewTabListBox_Impl::DoubleClickHdl()
+{
+ SvHeaderTabListBox::DoubleClickHdl();
+ return FALSE;
+ // this means "do no additional handling". Especially this means that the SvImpLBox does not
+ // recognize that the entry at the double click position change after the handler call (which is
+ // the case if in the handler, our content was replaced)
+ // If it _would_ recognize this change, it would take this as a reason to select the entry, again
+ // - which is not what in the case of content replace
+ // (I really doubt that this behaviour of the SvImpLBox does make any sense at all, but
+ // who knows ...)
+ // 07.12.2001 - 95727 - fs@openoffice.org
+}
+
+::rtl::OUString ViewTabListBox_Impl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
+{
+ ::rtl::OUString sRet = SvHeaderTabListBox::GetAccessibleObjectDescription( _eType, _nPos );
+ if ( ::svt::BBTYPE_TABLECELL == _eType )
+ {
+ sal_Int32 nRow = -1;
+ const sal_uInt16 nColumnCount = GetColumnCount();
+ if (nColumnCount > 0)
+ nRow = _nPos / nColumnCount;
+ SvLBoxEntry* pEntry = GetEntry( nRow );
+ if ( pEntry )
+ {
+ SvtContentEntry* pData = (SvtContentEntry*)pEntry->GetUserData();
+ if ( pData )
+ {
+ static const String sVar1( RTL_CONSTASCII_USTRINGPARAM( "%1" ) );
+ static const String sVar2( RTL_CONSTASCII_USTRINGPARAM( "%2" ) );
+ String aText( msAccessibleDescText );
+ aText.SearchAndReplace( sVar1, pData->mbIsFolder ? msFolder : msFile );
+ aText.SearchAndReplace( sVar2, pData->maURL );
+ sRet += ::rtl::OUString( aText );
+ }
+ }
+ }
+
+ return sRet;
+}
+
+// -----------------------------------------------------------------------
+sal_Bool ViewTabListBox_Impl::Kill( const OUString& rContent )
+{
+ sal_Bool bRet = sal_True;
+
+ try
+ {
+ ::ucbhelper::Content aCnt( rContent, mxCmdEnv );
+ aCnt.executeCommand( OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException const & )
+ {
+ DBG_WARNING( "CommandAbortedException" );
+ bRet = sal_False;
+ }
+ catch( Exception const & )
+ {
+ DBG_WARNING( "Any other exception" );
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+
+
+
+// -----------------------------------------------------------------------
+// class SvtFileView -----------------------------------------------------
+// -----------------------------------------------------------------------
+
+SvtFileView::SvtFileView( Window* pParent, const ResId& rResId,
+ sal_Bool bOnlyFolder, sal_Bool bMultiSelection ) :
+
+ Control( pParent, rResId )
+{
+ sal_Int8 nFlags = FILEVIEW_SHOW_ALL;
+ if ( bOnlyFolder )
+ nFlags |= FILEVIEW_ONLYFOLDER;
+ if ( bMultiSelection )
+ nFlags |= FILEVIEW_MULTISELECTION;
+
+ Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
+ ::comphelper::getProcessServiceFactory()->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
+ Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
+
+ mpImp = new SvtFileView_Impl( this, xCmdEnv, nFlags, bOnlyFolder );
+ mpImp->mpView->ForbidEmptyText();
+
+ long pTabs[] = { 5, 20, 180, 320, 400, 600 };
+ mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
+ mpImp->mpView->SetTabJustify( 2, AdjustRight ); // column "Size"
+
+ if ( bMultiSelection )
+ mpImp->mpView->SetSelectionMode( MULTIPLE_SELECTION );
+
+ HeaderBar* pHeaderBar = mpImp->mpView->GetHeaderBar();
+ pHeaderBar->SetSelectHdl( LINK( this, SvtFileView, HeaderSelect_Impl ) );
+ pHeaderBar->SetEndDragHdl( LINK( this, SvtFileView, HeaderEndDrag_Impl ) );
+}
+
+SvtFileView::SvtFileView( Window* pParent, const ResId& rResId, sal_Int8 nFlags ) :
+
+ Control( pParent, rResId )
+{
+ Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
+ ::comphelper::getProcessServiceFactory()->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
+ Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
+ mpImp = new SvtFileView_Impl( this, xCmdEnv, nFlags,
+ ( nFlags & FILEVIEW_ONLYFOLDER ) == FILEVIEW_ONLYFOLDER );
+
+ if ( ( nFlags & FILEVIEW_SHOW_ALL ) == FILEVIEW_SHOW_ALL )
+ {
+ long pTabs[] = { 5, 20, 180, 320, 400, 600 };
+ mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
+ mpImp->mpView->SetTabJustify( 2, AdjustRight ); // column "Size"
+ }
+ else
+ {
+ // show only title
+ long pTabs[] = { 2, 20, 600 };
+ mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
+ }
+
+ if ( ( nFlags & FILEVIEW_MULTISELECTION ) == FILEVIEW_MULTISELECTION )
+ mpImp->mpView->SetSelectionMode( MULTIPLE_SELECTION );
+
+ HeaderBar *pHeaderBar = mpImp->mpView->GetHeaderBar();
+ pHeaderBar->SetSelectHdl( LINK( this, SvtFileView, HeaderSelect_Impl ) );
+ pHeaderBar->SetEndDragHdl( LINK( this, SvtFileView, HeaderEndDrag_Impl ) );
+}
+
+// -----------------------------------------------------------------------
+
+SvtFileView::~SvtFileView()
+{
+ // use temp pointer to prevent access of deleted member (GetFocus())
+ SvtFileView_Impl* pTemp = mpImp;
+ mpImp = NULL;
+ delete pTemp;
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::OpenFolder( const Sequence< OUString >& aContents )
+{
+ mpImp->mpView->ClearAll();
+ const OUString* pFileProperties = aContents.getConstArray();
+ UINT32 i, nCount = aContents.getLength();
+ for ( i = 0; i < nCount; ++i )
+ {
+ String aRow( pFileProperties[i] );
+ // extract columns
+ // the columns are: title, type, size, date, target url, is folder, image url
+ String aTitle, aType, aSize, aDate, aURL, aImageURL;
+ xub_StrLen nIdx = 0;
+ aTitle = aRow.GetToken( 0, '\t', nIdx );
+ aType = aRow.GetToken( 0, '\t', nIdx );
+ aSize = aRow.GetToken( 0, '\t', nIdx );
+ aDate = aRow.GetToken( 0, '\t', nIdx );
+ aURL = aRow.GetToken( 0, '\t', nIdx );
+ sal_Unicode cFolder = aRow.GetToken( 0, '\t', nIdx ).GetChar(0);
+ sal_Bool bIsFolder = ( '1' == cFolder );
+ if ( nIdx != STRING_NOTFOUND )
+ aImageURL = aRow.GetToken( 0, '\t', nIdx );
+
+ if ( mpImp->mbOnlyFolder && !bIsFolder )
+ continue;
+
+ // build new row
+ String aNewRow = aTitle;
+ aNewRow += '\t';
+ aNewRow += aType;
+ aNewRow += '\t';
+ aNewRow += aSize;
+ aNewRow += '\t';
+ aNewRow += aDate;
+ // detect image
+ sal_Bool bDoInsert = sal_True;
+ INetURLObject aObj( aImageURL.Len() > 0 ? aImageURL : aURL );
+ Image aImage = SvFileInformationManager::GetImage( aObj, FALSE, isHighContrast( this ) );
+
+ if ( bDoInsert )
+ {
+ // insert entry and set user data
+ SvLBoxEntry* pEntry = mpImp->mpView->InsertEntry( aNewRow, aImage, aImage, NULL );
+ SvtContentEntry* pUserData = new SvtContentEntry( aURL, bIsFolder );
+ pEntry->SetUserData( pUserData );
+ }
+ }
+
+ mpImp->InitSelection();
+ mpImp->ResetCursor();
+}
+
+// -----------------------------------------------------------------------
+
+String SvtFileView::GetURL( SvLBoxEntry* pEntry ) const
+{
+ String aURL;
+ if ( pEntry && pEntry->GetUserData() )
+ aURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
+ return aURL;
+}
+
+// -----------------------------------------------------------------------
+
+String SvtFileView::GetCurrentURL() const
+{
+ String aURL;
+ SvLBoxEntry* pEntry = mpImp->mpView->FirstSelected();
+ if ( pEntry && pEntry->GetUserData() )
+ aURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
+ return aURL;
+}
+// -----------------------------------------------------------------------------
+
+sal_Bool SvtFileView::CreateNewFolder( const String& rNewFolder )
+{
+ sal_Bool bRet = sal_False;
+ INetURLObject aObj( mpImp->maViewURL );
+ aObj.insertName( rNewFolder, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL );
+ String sURL = aObj.GetMainURL( INetURLObject::NO_DECODE );
+ if ( ::utl::UCBContentHelper::MakeFolder( sURL, sal_True ) )
+ {
+ String sTitle = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
+ String sEntry = mpImp->FolderInserted( sURL, sTitle );
+ SvLBoxEntry* pEntry = mpImp->mpView->InsertEntry( sEntry, mpImp->maFolderImage, mpImp->maFolderImage );
+ SvtContentEntry* pUserData = new SvtContentEntry( sURL, TRUE );
+ pEntry->SetUserData( pUserData );
+ mpImp->mpView->MakeVisible( pEntry );
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+FileViewResult SvtFileView::PreviousLevel( const FileViewAsyncAction* pAsyncDescriptor )
+{
+ FileViewResult eResult = eFailure;
+
+ String sParentURL;
+ if ( GetParentURL( sParentURL ) )
+ eResult = Initialize( sParentURL, mpImp->maCurrentFilter, pAsyncDescriptor, mpBlackList );
+
+ return eResult;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SvtFileView::GetParentURL( String& rParentURL ) const
+{
+ sal_Bool bRet = sal_False;
+ try
+ {
+ ::ucbhelper::Content aCnt( mpImp->maViewURL, mpImp->mxCmdEnv );
+ Reference< XContent > xContent( aCnt.get() );
+ Reference< com::sun::star::container::XChild > xChild( xContent, UNO_QUERY );
+ if ( xChild.is() )
+ {
+ Reference< XContent > xParent( xChild->getParent(), UNO_QUERY );
+ if ( xParent.is() )
+ {
+ rParentURL = String( xParent->getIdentifier()->getContentIdentifier() );
+ bRet = ( rParentURL.Len() > 0 && rParentURL != mpImp->maViewURL );
+ }
+ }
+ }
+ catch( Exception const & )
+ {
+ // perhaps an unkown url protocol (e.g. "private:newdoc")
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt32 SvtFileView::GetHelpId( ) const
+{
+ return mpImp->mpView->GetHelpId( );
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::SetHelpId( sal_uInt32 nHelpId )
+{
+ mpImp->mpView->SetHelpId( nHelpId );
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::SetSizePixel( const Size& rNewSize )
+{
+ Control::SetSizePixel( rNewSize );
+ mpImp->mpView->SetSizePixel( rNewSize );
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
+{
+ SetPosPixel( rNewPos );
+ SetSizePixel( rNewSize );
+}
+
+// -----------------------------------------------------------------------------
+sal_Bool SvtFileView::Initialize( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent>& _xContent, const String& rFilter )
+{
+ WaitObject aWaitCursor( this );
+
+ mpImp->Clear();
+ ::ucbhelper::Content aContent(_xContent, mpImp->mxCmdEnv );
+ FileViewResult eResult = mpImp->GetFolderContent_Impl( FolderDescriptor( aContent ), NULL );
+ OSL_ENSURE( eResult != eStillRunning, "SvtFileView::Initialize: this was expected to be synchronous!" );
+ if ( eResult != eSuccess )
+ return sal_False;
+
+ mpImp->FilterFolderContent_Impl( rFilter );
+
+ mpImp->SortFolderContent_Impl(); // possibly not necessary!!!!!!!!!!
+ mpImp->CreateDisplayText_Impl();
+ mpImp->OpenFolder_Impl();
+
+ mpImp->maOpenDoneLink.Call( this );
+ return sal_True;
+}
+
+// -----------------------------------------------------------------------
+FileViewResult SvtFileView::Initialize(
+ const String& rURL,
+ const String& rFilter,
+ const FileViewAsyncAction* pAsyncDescriptor,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
+{
+ WaitObject aWaitCursor( this );
+ mpBlackList = rBlackList;
+
+ String sPushURL( mpImp->maViewURL );
+
+ mpImp->maViewURL = rURL;
+ FileViewResult eResult = ExecuteFilter( rFilter, pAsyncDescriptor );
+ switch ( eResult )
+ {
+ case eFailure:
+ case eTimeout:
+ mpImp->maViewURL = sPushURL;
+ return eResult;
+
+ case eStillRunning:
+ OSL_ENSURE( pAsyncDescriptor, "SvtFileView::Initialize: we told it to read synchronously!" );
+ case eSuccess:
+ return eResult;
+ }
+
+ OSL_ENSURE( sal_False, "SvtFileView::Initialize: unreachable!" );
+ return eFailure;
+}
+
+// -----------------------------------------------------------------------
+FileViewResult SvtFileView::Initialize(
+ const String& rURL,
+ const String& rFilter,
+ const FileViewAsyncAction* pAsyncDescriptor )
+{
+ return Initialize( rURL, rFilter, pAsyncDescriptor, ::com::sun::star::uno::Sequence< ::rtl::OUString >());
+}
+
+// -----------------------------------------------------------------------
+
+// -----------------------------------------------------------------------
+sal_Bool SvtFileView::Initialize( const Sequence< OUString >& aContents )
+{
+ WaitObject aWaitCursor( this );
+
+ mpImp->maViewURL = String();
+ mpImp->maCurrentFilter = mpImp->maAllFilter;
+
+ mpImp->Clear();
+ mpImp->CreateVector_Impl( aContents );
+ mpImp->SortFolderContent_Impl();
+
+ mpImp->OpenFolder_Impl();
+
+ mpImp->maOpenDoneLink.Call( this );
+
+ return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+FileViewResult SvtFileView::ExecuteFilter( const String& rFilter, const FileViewAsyncAction* pAsyncDescriptor )
+{
+ mpImp->maCurrentFilter = rFilter;
+ mpImp->maCurrentFilter.ToLowerAscii();
+
+ mpImp->Clear();
+ FileViewResult eResult = mpImp->GetFolderContent_Impl( mpImp->maViewURL, pAsyncDescriptor, mpBlackList );
+ OSL_ENSURE( ( eResult != eStillRunning ) || pAsyncDescriptor, "SvtFileView::ExecuteFilter: we told it to read synchronously!" );
+ return eResult;
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::CancelRunningAsyncAction()
+{
+ mpImp->CancelRunningAsyncAction();
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::SetNoSelection()
+{
+ mpImp->mpView->SelectAll( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::GetFocus()
+{
+ Control::GetFocus();
+ if ( mpImp && mpImp->mpView )
+ mpImp->mpView->GrabFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::ResetCursor()
+{
+ mpImp->ResetCursor();
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::SetSelectHdl( const Link& rHdl )
+{
+ mpImp->SetSelectHandler( rHdl );
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::SetDoubleClickHdl( const Link& rHdl )
+{
+ mpImp->mpView->SetDoubleClickHdl( rHdl );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG SvtFileView::GetSelectionCount() const
+{
+ return mpImp->mpView->GetSelectionCount();
+}
+
+// -----------------------------------------------------------------------
+
+SvLBoxEntry* SvtFileView::FirstSelected() const
+{
+ return mpImp->mpView->FirstSelected();
+}
+
+// -----------------------------------------------------------------------
+
+SvLBoxEntry* SvtFileView::NextSelected( SvLBoxEntry* pEntry ) const
+{
+ return mpImp->mpView->NextSelected( pEntry );
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::EnableAutoResize()
+{
+ mpImp->mpView->EnableAutoResize();
+}
+
+// -----------------------------------------------------------------------
+
+void SvtFileView::SetFocus()
+{
+ mpImp->mpView->GrabFocus();
+}
+
+// -----------------------------------------------------------------------
+const String& SvtFileView::GetViewURL() const
+{
+ return mpImp->maViewURL;
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView::SetOpenDoneHdl( const Link& rHdl )
+{
+ mpImp->maOpenDoneLink = rHdl;
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView::EnableContextMenu( sal_Bool bEnable )
+{
+ mpImp->EnableContextMenu( bEnable );
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView::EnableDelete( sal_Bool bEnable )
+{
+ mpImp->EnableDelete( bEnable );
+}
+
+void SvtFileView::EnableNameReplacing( sal_Bool bEnable )
+{
+ mpImp->EnableNameReplacing( bEnable );
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView::EndInplaceEditing( bool _bCancel )
+{
+ return mpImp->EndEditing( _bCancel );
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( SvtFileView, HeaderSelect_Impl, HeaderBar*, pBar )
+{
+ DBG_ASSERT( pBar, "no headerbar" );
+ USHORT nItemID = pBar->GetCurItemId();
+
+ HeaderBarItemBits nBits;
+
+ // clear the arrow of the recently used column
+ if ( nItemID != mpImp->mnSortColumn )
+ {
+ if ( !nItemID )
+ {
+ // first call -> remove arrow from title column,
+ // because another column is the sort column
+ nItemID = mpImp->mnSortColumn;
+ mpImp->mnSortColumn = COLUMN_TITLE;
+ }
+ nBits = pBar->GetItemBits( mpImp->mnSortColumn );
+ nBits &= ~( HIB_UPARROW | HIB_DOWNARROW );
+ pBar->SetItemBits( mpImp->mnSortColumn, nBits );
+ }
+
+ nBits = pBar->GetItemBits( nItemID );
+
+ BOOL bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW );
+
+ if ( bUp )
+ {
+ nBits &= ~HIB_UPARROW;
+ nBits |= HIB_DOWNARROW;
+ }
+ else
+ {
+ nBits &= ~HIB_DOWNARROW;
+ nBits |= HIB_UPARROW;
+ }
+
+ pBar->SetItemBits( nItemID, nBits );
+ mpImp->Resort_Impl( nItemID, !bUp );
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( SvtFileView, HeaderEndDrag_Impl, HeaderBar*, pBar )
+{
+ if ( !pBar->IsItemMode() )
+ {
+ Size aSize;
+ USHORT nTabs = pBar->GetItemCount();
+ long nTmpSize = 0;
+
+ for ( USHORT i = 1; i <= nTabs; ++i )
+ {
+ long nWidth = pBar->GetItemSize(i);
+ aSize.Width() = nWidth + nTmpSize;
+ nTmpSize += nWidth;
+ mpImp->mpView->SetTab( i, aSize.Width(), MAP_PIXEL );
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+String SvtFileView::GetConfigString() const
+{
+ String sRet;
+ HeaderBar* pBar = mpImp->mpView->GetHeaderBar();
+ DBG_ASSERT( pBar, "invalid headerbar" );
+
+ // sort order
+ sRet += String::CreateFromInt32( mpImp->mnSortColumn );
+ sRet += ';';
+ HeaderBarItemBits nBits = pBar->GetItemBits( mpImp->mnSortColumn );
+ BOOL bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW );
+ sRet += bUp ? '1' : '0';
+ sRet += ';';
+
+ USHORT nCount = pBar->GetItemCount();
+ for ( USHORT i = 0; i < nCount; ++i )
+ {
+ USHORT nId = pBar->GetItemId(i);
+ sRet += String::CreateFromInt32( nId );
+ sRet += ';';
+ sRet += String::CreateFromInt32( pBar->GetItemSize( nId ) );
+ sRet += ';';
+ }
+
+ sRet.EraseTrailingChars( ';' );
+ return sRet;
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView::SetConfigString( const String& rCfgStr )
+{
+ HeaderBar* pBar = mpImp->mpView->GetHeaderBar();
+ DBG_ASSERT( pBar, "invalid headerbar" );
+
+ USHORT nIdx = 0;
+ mpImp->mnSortColumn = (USHORT)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
+ BOOL bUp = (BOOL)(USHORT)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
+ HeaderBarItemBits nBits = pBar->GetItemBits( mpImp->mnSortColumn );
+
+ if ( bUp )
+ {
+ nBits &= ~HIB_UPARROW;
+ nBits |= HIB_DOWNARROW;
+ }
+ else
+ {
+ nBits &= ~HIB_DOWNARROW;
+ nBits |= HIB_UPARROW;
+ }
+ pBar->SetItemBits( mpImp->mnSortColumn, nBits );
+
+ while ( nIdx != STRING_NOTFOUND )
+ {
+ USHORT nItemId = (USHORT)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
+ pBar->SetItemSize( nItemId, rCfgStr.GetToken( 0, ';', nIdx ).ToInt32() );
+ }
+
+ HeaderSelect_Impl( pBar );
+ HeaderEndDrag_Impl( pBar );
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView::SetUrlFilter( const IUrlFilter* _pFilter )
+{
+ mpImp->mpUrlFilter = _pFilter;
+}
+
+// -----------------------------------------------------------------------
+const IUrlFilter* SvtFileView::GetUrlFilter( ) const
+{
+ return mpImp->mpUrlFilter;
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView::StateChanged( StateChangedType nStateChange )
+{
+ if ( nStateChange == STATE_CHANGE_ENABLE )
+ Invalidate();
+ Control::StateChanged( nStateChange );
+}
+
+// -----------------------------------------------------------------------
+// class NameTranslator_Impl
+// -----------------------------------------------------------------------
+
+NameTranslator_Impl::NameTranslator_Impl( void ) :
+ mpActFolder( NULL )
+{
+}
+
+NameTranslator_Impl::NameTranslator_Impl( const INetURLObject& rActualFolder )
+{
+ mpActFolder = new NameTranslationList( rActualFolder );
+}
+
+NameTranslator_Impl::~NameTranslator_Impl()
+{
+ if( mpActFolder )
+ delete mpActFolder;
+}
+
+void NameTranslator_Impl::UpdateTranslationTable()
+{
+ if( mpActFolder )
+ mpActFolder->Update();
+}
+
+void NameTranslator_Impl::SetActualFolder( const INetURLObject& rActualFolder )
+{
+ HashedEntry aActFolder( rActualFolder );
+
+ if( mpActFolder )
+ {
+ if( *mpActFolder != aActFolder )
+ {
+ delete mpActFolder;
+ mpActFolder = new NameTranslationList( rActualFolder );
+ }
+ }
+ else
+ mpActFolder = new NameTranslationList( rActualFolder );
+}
+
+sal_Bool NameTranslator_Impl::GetTranslation( const OUString& rOrg, OUString& rTrans ) const
+{
+ sal_Bool bRet = sal_False;
+
+ if( mpActFolder )
+ {
+ const OUString* pTrans = mpActFolder->Translate( rOrg );
+ if( pTrans )
+ {
+ rTrans = *pTrans;
+ bRet = sal_True;
+ }
+ }
+
+ return bRet;
+}
+
+const String* NameTranslator_Impl::GetTransTableFileName() const
+{
+ return mpActFolder? &mpActFolder->GetTransTableFileName() : NULL;
+}
+
+// -----------------------------------------------------------------------
+// class SvtFileView_Impl
+// -----------------------------------------------------------------------
+
+SvtFileView_Impl::SvtFileView_Impl( SvtFileView* pAntiImpl, Reference < XCommandEnvironment > xEnv, sal_Int16 nFlags, sal_Bool bOnlyFolder )
+
+ :mpAntiImpl ( pAntiImpl )
+ ,m_eAsyncActionResult ( ::svt::ERROR )
+ ,m_bRunningAsyncAction ( false )
+ ,m_bAsyncActionCancelled ( false )
+ ,mpNameTrans ( NULL )
+ ,mpUrlFilter ( NULL )
+ ,mnSortColumn ( COLUMN_TITLE )
+ ,mbAscending ( sal_True )
+ ,mbOnlyFolder ( bOnlyFolder )
+ ,mbReplaceNames ( sal_False )
+ ,mnSuspendSelectCallback ( 0 )
+ ,mbIsFirstResort ( sal_True )
+ ,aIntlWrapper ( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() )
+ ,maFolderImage ( SvtResId( IMG_SVT_FOLDER ) )
+ ,mxCmdEnv ( xEnv )
+
+{
+ maAllFilter = String::CreateFromAscii( "*.*" );
+ mpView = new ViewTabListBox_Impl( mpAntiImpl, this, nFlags );
+ mpView->EnableCellFocus();
+}
+
+// -----------------------------------------------------------------------
+SvtFileView_Impl::~SvtFileView_Impl()
+{
+ Clear();
+
+ // use temp pointer to prevent access of deleted member (GetFocus())
+ ViewTabListBox_Impl* pTemp = mpView;
+ mpView = NULL;
+ delete pTemp;
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::Clear()
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ std::vector< SortingData_Impl* >::iterator aIt;
+
+ for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
+ delete (*aIt);
+
+ maContent.clear();
+
+ if( mpNameTrans )
+ DELETEZ( mpNameTrans );
+}
+
+// -----------------------------------------------------------------------
+FileViewResult SvtFileView_Impl::GetFolderContent_Impl(
+ const String& rFolder,
+ const FileViewAsyncAction* pAsyncDescriptor,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
+{
+ ::osl::ClearableMutexGuard aGuard( maMutex );
+ INetURLObject aFolderObj( rFolder );
+ DBG_ASSERT( aFolderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
+
+ // prepare name translation
+ SetActualFolder( aFolderObj );
+
+ FolderDescriptor aFolder( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ) );
+
+ aGuard.clear();
+ return GetFolderContent_Impl( aFolder, pAsyncDescriptor, rBlackList );
+}
+
+// -----------------------------------------------------------------------
+FileViewResult SvtFileView_Impl::GetFolderContent_Impl(
+ const FolderDescriptor& _rFolder,
+ const FileViewAsyncAction* pAsyncDescriptor,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
+{
+ DBG_TESTSOLARMUTEX();
+ ::osl::ClearableMutexGuard aGuard( maMutex );
+
+ OSL_ENSURE( !m_pContentEnumerator.is(), "SvtFileView_Impl::GetFolderContent_Impl: still running another enumeration!" );
+ m_pContentEnumerator = new ::svt::FileViewContentEnumerator(
+ mpView->GetCommandEnvironment(), maContent, maMutex, mbReplaceNames ? mpNameTrans : NULL );
+ // TODO: should we cache and re-use this thread?
+
+ if ( !pAsyncDescriptor )
+ {
+ ::svt::EnumerationResult eResult = m_pContentEnumerator->enumerateFolderContentSync( _rFolder, mpUrlFilter, rBlackList );
+ if ( ::svt::SUCCESS == eResult )
+ {
+ implEnumerationSuccess();
+ m_pContentEnumerator = NULL;
+ return eSuccess;
+ }
+ m_pContentEnumerator = NULL;
+ return eFailure;
+ }
+
+ m_bRunningAsyncAction = true;
+ m_bAsyncActionCancelled = false;
+ m_eAsyncActionResult = ::svt::ERROR;
+ m_aAsyncActionFinished.reset();
+
+ // don't (yet) set m_aCurrentAsyncActionHandler to pTimeout->aFinishHandler.
+ // By definition, this handler *only* get's called when the result cannot be obtained
+ // during the minimum wait time, so it is only set below, when needed.
+ m_aCurrentAsyncActionHandler = Link();
+
+ // minimum time to wait
+ ::std::auto_ptr< TimeValue > pTimeout( new TimeValue );
+ sal_Int32 nMinTimeout = pAsyncDescriptor->nMinTimeout;
+ OSL_ENSURE( nMinTimeout > 0, "SvtFileView_Impl::GetFolderContent_Impl: invalid minimum timeout!" );
+ if ( nMinTimeout <= 0 )
+ nMinTimeout = sal_Int32( 1000L );
+ pTimeout->Seconds = nMinTimeout / 1000L;
+ pTimeout->Nanosec = ( nMinTimeout % 1000L ) * 1000000L;
+
+ m_pContentEnumerator->enumerateFolderContent( _rFolder, mpUrlFilter, this );
+
+ // wait until the enumeration is finished
+ // for this, release our own mutex (which is used by the enumerator thread)
+ aGuard.clear();
+
+ ::osl::Condition::Result eResult = ::osl::Condition::result_ok;
+ {
+ // also release the SolarMutex. Not all code which is needed during the enumeration
+ // is Solar-Thread-Safe, in particular there is some code which needs to access
+ // string resources (and our resource system relies on the SolarMutex :()
+ ReleaseSolarMutex aSolarRelease;
+
+ // now wait. Note that if we didn't get an pAsyncDescriptor, then this is an infinite wait.
+ eResult = m_aAsyncActionFinished.wait( pTimeout.get() );
+ }
+
+ ::osl::MutexGuard aGuard2( maMutex );
+ if ( ::osl::Condition::result_timeout == eResult )
+ {
+ // maximum time to wait
+ OSL_ENSURE( !m_pCancelAsyncTimer.get(), "SvtFileView_Impl::GetFolderContent_Impl: there's still a previous timer!" );
+ m_pCancelAsyncTimer = new CallbackTimer( this );
+ sal_Int32 nMaxTimeout = pAsyncDescriptor->nMaxTimeout;
+ OSL_ENSURE( nMaxTimeout > nMinTimeout,
+ "SvtFileView_Impl::GetFolderContent_Impl: invalid maximum timeout!" );
+ if ( nMaxTimeout <= nMinTimeout )
+ nMaxTimeout = nMinTimeout + 5000;
+ m_pCancelAsyncTimer->setRemainingTime( TTimeValue( nMaxTimeout - nMinTimeout ) );
+ // we already waited for nMinTimeout milliseconds, so take this into account
+ m_pCancelAsyncTimer->start();
+
+ m_aCurrentAsyncActionHandler = pAsyncDescriptor->aFinishHandler;
+ DBG_ASSERT( m_aCurrentAsyncActionHandler.IsSet(), "SvtFileView_Impl::GetFolderContent_Impl: nobody interested when it's finished?" );
+ mpView->ClearAll();
+ return eStillRunning;
+ }
+
+ m_bRunningAsyncAction = false;
+ switch ( m_eAsyncActionResult )
+ {
+ case ::svt::SUCCESS:
+ return eSuccess;
+
+ case ::svt::ERROR:
+ return eFailure;
+
+ case ::svt::RUNNING:
+ return eStillRunning;
+ }
+
+ DBG_ERRORFILE( "SvtFileView_Impl::GetFolderContent_Impl: unreachable!" );
+ return eFailure;
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::FilterFolderContent_Impl( const OUString &rFilter )
+{
+ sal_Bool bHideTransFile = mbReplaceNames && mpNameTrans;
+
+ String sHideEntry;
+ if( bHideTransFile )
+ {
+ const String* pTransTableFileName = mpNameTrans->GetTransTableFileName();
+ if( pTransTableFileName )
+ {
+ sHideEntry = *pTransTableFileName;
+ sHideEntry.ToUpperAscii();
+ }
+ else
+ bHideTransFile = sal_False;
+ }
+
+ if ( !bHideTransFile &&
+ ( !rFilter.getLength() || ( rFilter.compareToAscii( ALL_FILES_FILTER ) == COMPARE_EQUAL ) ) )
+ // when replacing names, there is always something to filter (no view of ".nametranslation.table")
+ return;
+
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if ( maContent.empty() )
+ return;
+
+ // count (estimate) the number of filter tokens
+ sal_Int32 nTokens=0;
+ const sal_Unicode* pStart = rFilter.getStr();
+ const sal_Unicode* pEnd = pStart + rFilter.getLength();
+ while ( pStart != pEnd )
+ if ( *pStart++ == ';' )
+ ++nTokens;
+
+ // collect the filter tokens
+ ::std::vector< WildCard > aFilters;
+ FilterMatch::createWildCardFilterList(rFilter,aFilters);
+
+
+ // do the filtering
+ ::std::vector< SortingData_Impl* >::iterator aContentLoop = maContent.begin();
+ String sCompareString;
+ do
+ {
+ if ( (*aContentLoop)->mbIsFolder )
+ ++aContentLoop;
+ else
+ {
+ // normalize the content title (we always match case-insensitive)
+ // 91872 - 11.09.2001 - frank.schoenheit@sun.com
+ sCompareString = (*aContentLoop)->GetFileName(); // filter works on file name, not on title!
+ sal_Bool bDelete;
+
+ if( bHideTransFile && sCompareString == sHideEntry )
+ bDelete = sal_True;
+ else
+ {
+ // search for the first filter which matches
+ ::std::vector< WildCard >::const_iterator pMatchingFilter =
+ ::std::find_if(
+ aFilters.begin(),
+ aFilters.end(),
+ FilterMatch( sCompareString )
+ );
+
+ bDelete = aFilters.end() == pMatchingFilter;
+ }
+
+ if( bDelete )
+ {
+ // none of the filters did match
+ delete (*aContentLoop);
+
+ if ( maContent.begin() == aContentLoop )
+ {
+ maContent.erase( aContentLoop );
+ aContentLoop = maContent.begin();
+ }
+ else
+ {
+ std::vector< SortingData_Impl* >::iterator aDelete = aContentLoop;
+ --aContentLoop; // move the iterator to a position which is not invalidated by the erase
+ maContent.erase( aDelete );
+ ++aContentLoop; // this is now the next one ....
+ }
+ }
+ else
+ ++aContentLoop;
+ }
+ }
+ while ( aContentLoop != maContent.end() );
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( SvtFileView_Impl, SelectionMultiplexer, void*, _pSource )
+{
+ return mnSuspendSelectCallback ? 0L : m_aSelectHandler.Call( _pSource );
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::SetSelectHandler( const Link& _rHdl )
+{
+ m_aSelectHandler = _rHdl;
+
+ Link aMasterHandler;
+ if ( m_aSelectHandler.IsSet() )
+ aMasterHandler = LINK( this, SvtFileView_Impl, SelectionMultiplexer );
+
+ mpView->SetSelectHdl( aMasterHandler );
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::InitSelection()
+{
+ mpView->SelectAll( sal_False );
+ SvLBoxEntry* pFirst = mpView->First();
+ if ( pFirst )
+ mpView->SetCursor( pFirst, sal_True );
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::OpenFolder_Impl()
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ mpView->SetUpdateMode( FALSE );
+ mpView->ClearAll();
+
+ std::vector< SortingData_Impl* >::iterator aIt;
+
+ for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
+ {
+ if ( mbOnlyFolder && ! (*aIt)->mbIsFolder )
+ continue;
+
+ // insert entry and set user data
+ SvLBoxEntry* pEntry = mpView->InsertEntry( (*aIt)->maDisplayText,
+ (*aIt)->maImage,
+ (*aIt)->maImage );
+
+ SvtContentEntry* pUserData = new SvtContentEntry( (*aIt)->maTargetURL,
+ (*aIt)->mbIsFolder );
+ pEntry->SetUserData( pUserData );
+ }
+
+ InitSelection();
+
+ ++mnSuspendSelectCallback;
+ mpView->SetUpdateMode( TRUE );
+ --mnSuspendSelectCallback;
+
+ ResetCursor();
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::ResetCursor()
+{
+ // deselect
+ SvLBoxEntry* pEntry = mpView->FirstSelected();
+ if ( pEntry )
+ mpView->Select( pEntry, FALSE );
+ // set cursor to the first entry
+ mpView->SetCursor( mpView->First(), TRUE );
+ mpView->Update();
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::CancelRunningAsyncAction()
+{
+ DBG_TESTSOLARMUTEX();
+ ::osl::MutexGuard aGuard( maMutex );
+ if ( !m_pContentEnumerator.is() )
+ return;
+
+ m_bAsyncActionCancelled = true;
+ m_pContentEnumerator->cancel();
+ m_bRunningAsyncAction = false;
+
+ m_pContentEnumerator = NULL;
+ if ( m_pCancelAsyncTimer.is() && m_pCancelAsyncTimer->isTicking() )
+ m_pCancelAsyncTimer->stop();
+ m_pCancelAsyncTimer = NULL;
+}
+
+//-----------------------------------------------------------------------
+void SvtFileView_Impl::onTimeout( CallbackTimer* )
+{
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ::osl::MutexGuard aGuard( maMutex );
+ if ( !m_bRunningAsyncAction )
+ // there might have been a race condition while we waited for the mutex
+ return;
+
+ CancelRunningAsyncAction();
+
+ if ( m_aCurrentAsyncActionHandler.IsSet() )
+ {
+ Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( eTimeout ) );
+ m_aCurrentAsyncActionHandler = Link();
+ }
+}
+
+//-----------------------------------------------------------------------
+void SvtFileView_Impl::enumerationDone( ::svt::EnumerationResult _eResult )
+{
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ::osl::MutexGuard aGuard( maMutex );
+
+ m_pContentEnumerator = NULL;
+ if ( m_pCancelAsyncTimer.is() && m_pCancelAsyncTimer->isTicking() )
+ m_pCancelAsyncTimer->stop();
+ m_pCancelAsyncTimer = NULL;
+
+ if ( m_bAsyncActionCancelled )
+ // this is to prevent race conditions
+ return;
+
+ m_eAsyncActionResult = _eResult;
+ m_bRunningAsyncAction = false;
+
+ m_aAsyncActionFinished.set();
+
+ if ( svt::SUCCESS == _eResult )
+ implEnumerationSuccess();
+
+ if ( m_aCurrentAsyncActionHandler.IsSet() )
+ {
+ Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( m_eAsyncActionResult ) );
+ m_aCurrentAsyncActionHandler = Link();
+ }
+}
+
+//-----------------------------------------------------------------------
+void SvtFileView_Impl::implEnumerationSuccess()
+{
+ FilterFolderContent_Impl( maCurrentFilter );
+ SortFolderContent_Impl();
+ CreateDisplayText_Impl();
+ OpenFolder_Impl();
+ maOpenDoneLink.Call( mpAntiImpl );
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::ReplaceTabWithString( OUString& aValue )
+{
+ OUString aTab = OUString::createFromAscii( "\t" );
+ OUString aTabString = OUString::createFromAscii( "%09" );
+ sal_Int32 iPos;
+
+ while ( ( iPos = aValue.indexOf( aTab ) ) >= 0 )
+ aValue = aValue.replaceAt( iPos, 1, aTabString );
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::CreateDisplayText_Impl()
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ OUString aValue;
+ OUString aTab = OUString::createFromAscii( "\t" );
+ OUString aDateSep = OUString::createFromAscii( ", " );
+
+ std::vector< SortingData_Impl* >::iterator aIt;
+
+ for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
+ {
+ // title, type, size, date
+ aValue = (*aIt)->GetTitle();
+ // #83004# --------------------
+ ReplaceTabWithString( aValue );
+ aValue += aTab;
+ aValue += (*aIt)->maType;
+ aValue += aTab;
+ // folders don't have a size
+ if ( ! (*aIt)->mbIsFolder )
+ aValue += CreateExactSizeText_Impl( (*aIt)->maSize );
+ aValue += aTab;
+ // set the date, but volumes have no date
+ if ( ! (*aIt)->mbIsFolder || ! (*aIt)->mbIsVolume )
+ {
+ SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
+ aValue += rLocaleData.getDate( (*aIt)->maModDate );
+ aValue += aDateSep;
+ aValue += rLocaleData.getTime( (*aIt)->maModDate );
+ }
+ (*aIt)->maDisplayText = aValue;
+
+ // detect image
+ if ( (*aIt)->mbIsFolder )
+ {
+ ::svtools::VolumeInfo aVolInfo( (*aIt)->mbIsVolume, (*aIt)->mbIsRemote,
+ (*aIt)->mbIsRemoveable, (*aIt)->mbIsFloppy,
+ (*aIt)->mbIsCompactDisc );
+ (*aIt)->maImage = SvFileInformationManager::GetFolderImage( aVolInfo, FALSE, isHighContrast( mpView ) );
+ }
+ else
+ (*aIt)->maImage = SvFileInformationManager::GetFileImage( INetURLObject( (*aIt)->maTargetURL ), FALSE, isHighContrast( mpView ));
+ }
+}
+
+// -----------------------------------------------------------------------
+// this function converts the sequence of strings into a vector of SortingData
+// the string should have the form :
+// title \t type \t size \t date \t target url \t is folder \t image url
+
+void SvtFileView_Impl::CreateVector_Impl( const Sequence < OUString > &rList )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ OUString aTab = OUString::createFromAscii( "\t" );
+
+ sal_uInt32 nCount = (sal_uInt32) rList.getLength();
+
+ for( sal_uInt32 i = 0; i < nCount; i++ )
+ {
+ SortingData_Impl* pEntry = new SortingData_Impl;
+ OUString aValue = rList[i];
+ OUString aDisplayText;
+ sal_Int32 nIndex = 0;
+
+ // get the title
+ pEntry->SetNewTitle( aValue.getToken( 0, '\t', nIndex ) );
+ aDisplayText = pEntry->GetTitle();
+ // #83004# --------------------
+ ReplaceTabWithString( aDisplayText );
+ aDisplayText += aTab;
+
+ // get the type
+ if ( nIndex >= 0 )
+ {
+ pEntry->maType = aValue.getToken( 0, '\t', nIndex );
+ aDisplayText += pEntry->maType;
+ }
+ aDisplayText += aTab;
+
+ // get the size
+ if ( nIndex >= 0 )
+ {
+ OUString aSize = aValue.getToken( 0, '\t', nIndex );
+ aDisplayText += aSize;
+
+ if ( aSize.getLength() )
+ pEntry->maSize = aSize.toInt64();
+ }
+ aDisplayText += aTab;
+
+ // get the date
+ if ( nIndex >= 0 )
+ {
+ OUString aDate = aValue.getToken( 0, '\t', nIndex );
+ aDisplayText += aDate;
+
+ if ( aDate.getLength() )
+ {
+ DBG_ERRORFILE( "Don't know, how to convert date" );
+ ;// convert date string to date
+ }
+ }
+ // get the target url
+ if ( nIndex >= 0 )
+ {
+ pEntry->maTargetURL = aValue.getToken( 0, '\t', nIndex );
+ }
+ // get the size
+ if ( nIndex >= 0 )
+ {
+ OUString aBool = aValue.getToken( 0, '\t', nIndex );
+ if ( aBool.getLength() )
+ pEntry->mbIsFolder = aBool.toBoolean();
+ }
+ // get the image url
+ if ( nIndex >= 0 )
+ {
+ pEntry->maImageURL = aValue.getToken( 0, '\t', nIndex );
+ }
+
+ // set the display text
+ pEntry->maDisplayText = aDisplayText;
+
+ // detect the image
+ INetURLObject aObj( pEntry->maImageURL.getLength() ? pEntry->maImageURL : pEntry->maTargetURL );
+ pEntry->maImage = SvFileInformationManager::GetImage( aObj, FALSE, isHighContrast( mpView ) );
+
+ maContent.push_back( pEntry );
+ }
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::Resort_Impl( sal_Int16 nColumn, sal_Bool bAscending )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if ( ( nColumn == mnSortColumn ) &&
+ ( bAscending == mbAscending ) )
+ return;
+
+ // reset the quick search index
+ mpView->ResetQuickSearch_Impl( NULL );
+
+ String aEntryURL;
+ SvLBoxEntry* pEntry = mpView->GetCurEntry();
+ if ( pEntry && pEntry->GetUserData() )
+ aEntryURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
+
+ mnSortColumn = nColumn;
+ mbAscending = bAscending;
+
+ SortFolderContent_Impl();
+ OpenFolder_Impl();
+
+ if ( !mbIsFirstResort )
+ {
+ ULONG nPos = GetEntryPos( aEntryURL );
+ if ( nPos < mpView->GetEntryCount() )
+ {
+ pEntry = mpView->GetEntry( nPos );
+
+ ++mnSuspendSelectCallback; // #i15668# - 2004-04-25 - fs@openoffice.org
+ mpView->SetCurEntry( pEntry );
+ --mnSuspendSelectCallback;
+ }
+ }
+ else
+ mbIsFirstResort = sal_False;
+}
+
+// -----------------------------------------------------------------------
+static sal_Bool gbAscending = sal_True;
+static sal_Int16 gnColumn = COLUMN_TITLE;
+static const CollatorWrapper* pCollatorWrapper = NULL;
+
+/* this functions returns true, if aOne is less then aTwo
+*/
+sal_Bool CompareSortingData_Impl( SortingData_Impl* const aOne, SortingData_Impl* const aTwo )
+{
+ DBG_ASSERT( pCollatorWrapper, "*CompareSortingData_Impl(): Can't work this way!" );
+
+ sal_Int32 nComp;
+ sal_Bool bRet = sal_False;
+ sal_Bool bEqual = sal_False;
+
+ if ( aOne->mbIsFolder != aTwo->mbIsFolder )
+ {
+ if ( aOne->mbIsFolder )
+ bRet = sal_True;
+ else
+ bRet = sal_False;
+
+ // !!! pb: #100376# folder always on top
+ if ( !gbAscending )
+ bRet = !bRet;
+ }
+ else
+ {
+ switch ( gnColumn )
+ {
+ case COLUMN_TITLE:
+ // compare case insensitiv first
+ nComp = pCollatorWrapper->compareString( aOne->GetLowerTitle(), aTwo->GetLowerTitle() );
+
+ if ( nComp == 0 )
+ nComp = pCollatorWrapper->compareString( aOne->GetTitle(), aTwo->GetTitle() );
+
+ if ( nComp < 0 )
+ bRet = sal_True;
+ else if ( nComp > 0 )
+ bRet = sal_False;
+ else
+ bEqual = sal_True;
+ break;
+ case COLUMN_TYPE:
+ nComp = pCollatorWrapper->compareString( aOne->maType, aTwo->maType );
+ if ( nComp < 0 )
+ bRet = sal_True;
+ else if ( nComp > 0 )
+ bRet = sal_False;
+ else
+ bEqual = sal_True;
+ break;
+ case COLUMN_SIZE:
+ if ( aOne->maSize < aTwo->maSize )
+ bRet = sal_True;
+ else if ( aOne->maSize > aTwo->maSize )
+ bRet = sal_False;
+ else
+ bEqual = sal_True;
+ break;
+ case COLUMN_DATE:
+ if ( aOne->maModDate < aTwo->maModDate )
+ bRet = sal_True;
+ else if ( aOne->maModDate > aTwo->maModDate )
+ bRet = sal_False;
+ else
+ bEqual = sal_True;
+ break;
+ default:
+ DBG_WARNING( "CompareSortingData_Impl: Compare unknown type!" );
+ bRet = sal_False;
+ }
+ }
+
+ // when the two elements are equal, we must not return TRUE (which would
+ // happen if we just return ! ( a < b ) when not sorting ascending )
+ if ( bEqual )
+ return sal_False;
+
+ return gbAscending ? bRet : !bRet;
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::SortFolderContent_Impl()
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ sal_uInt32 nSize = maContent.size();
+
+ if ( nSize > 1 )
+ {
+ gbAscending = mbAscending;
+ gnColumn = mnSortColumn;
+ pCollatorWrapper = aIntlWrapper.getCaseCollator();
+
+ std::stable_sort( maContent.begin(), maContent.end(), CompareSortingData_Impl );
+
+ pCollatorWrapper = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::EntryRemoved( const OUString& rURL )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ std::vector< SortingData_Impl* >::iterator aIt;
+
+ for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
+ {
+ if ( (*aIt)->maTargetURL == rURL )
+ {
+ maContent.erase( aIt );
+ break;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::EntryRenamed( OUString& rURL,
+ const OUString& rTitle )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ std::vector< SortingData_Impl* >::iterator aIt;
+
+ for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
+ {
+ if ( (*aIt)->maTargetURL == rURL )
+ {
+ (*aIt)->SetNewTitle( rTitle );
+ OUString aDisplayText = (*aIt)->maDisplayText;
+ sal_Int32 nIndex = aDisplayText.indexOf( '\t' );
+
+ if ( nIndex > 0 )
+ (*aIt)->maDisplayText = aDisplayText.replaceAt( 0, nIndex, rTitle );
+
+ INetURLObject aURLObj( rURL );
+ aURLObj.SetName( rTitle, INetURLObject::ENCODE_ALL );
+
+ rURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
+
+ (*aIt)->maTargetURL = rURL;
+ break;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+String SvtFileView_Impl::FolderInserted( const OUString& rURL, const OUString& rTitle )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ SortingData_Impl* pData = new SortingData_Impl;
+
+ pData->SetNewTitle( rTitle );
+ pData->maSize = 0;
+ pData->mbIsFolder = sal_True;
+ pData->maTargetURL = rURL;
+
+ INetURLObject aURLObj( rURL );
+
+ ::svtools::VolumeInfo aVolInfo;
+ pData->maType = SvFileInformationManager::GetFolderDescription( aVolInfo );
+ pData->maImage = SvFileInformationManager::GetFolderImage( aVolInfo, FALSE, isHighContrast( mpView ) );
+
+ OUString aValue;
+ OUString aTab = OUString::createFromAscii( "\t" );
+ OUString aDateSep = OUString::createFromAscii( ", " );
+
+ // title, type, size, date
+ aValue = pData->GetTitle();
+ // #83004# --------------------
+ ReplaceTabWithString( aValue );
+ aValue += aTab;
+ aValue += pData->maType;
+ aValue += aTab;
+ // folders don't have a size
+ aValue += aTab;
+ // set the date
+ SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
+ aValue += rLocaleData.getDate( pData->maModDate );
+ aValue += aDateSep;
+ aValue += rLocaleData.getTime( pData->maModDate );
+
+ pData->maDisplayText = aValue;
+ maContent.push_back( pData );
+
+ return String( aValue );
+}
+
+// -----------------------------------------------------------------------
+ULONG SvtFileView_Impl::GetEntryPos( const OUString& rURL )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ std::vector< SortingData_Impl* >::iterator aIt;
+ ULONG nPos = 0;
+
+ for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
+ {
+ if ( (*aIt)->maTargetURL == rURL )
+ return nPos;
+ nPos += 1;
+ }
+
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+sal_Bool SvtFileView_Impl::SearchNextEntry( sal_uInt32& nIndex, const OUString& rTitle, sal_Bool bWrapAround )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ sal_uInt32 nEnd = maContent.size();
+ sal_uInt32 nStart = nIndex;
+ while ( nIndex < nEnd )
+ {
+ SortingData_Impl* pData = maContent[ nIndex ];
+ if ( rTitle.compareTo( pData->GetLowerTitle(), rTitle.getLength() ) == 0 )
+ return sal_True;
+ nIndex += 1;
+ }
+
+ if ( bWrapAround )
+ {
+ nIndex = 0;
+ while ( nIndex < nEnd && nIndex <= nStart )
+ {
+ SortingData_Impl* pData = maContent[ nIndex ];
+ if ( rTitle.compareTo( pData->GetLowerTitle(), rTitle.getLength() ) == 0 )
+ return sal_True;
+ nIndex += 1;
+ }
+ }
+
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+void SvtFileView_Impl::SetActualFolder( const INetURLObject& rActualFolder )
+{
+ if( mbReplaceNames )
+ {
+ if( mpNameTrans )
+ mpNameTrans->SetActualFolder( rActualFolder );
+ else
+ mpNameTrans = new NameTranslator_Impl( rActualFolder );
+ }
+}
+
+namespace svtools {
+
+// -----------------------------------------------------------------------
+// QueryDeleteDlg_Impl
+// -----------------------------------------------------------------------
+
+QueryDeleteDlg_Impl::QueryDeleteDlg_Impl
+(
+ Window* pParent,
+ const String& rName // Eintragsname
+) :
+
+ ModalDialog( pParent, SvtResId( DLG_SVT_QUERYDELETE ) ),
+
+ _aEntryLabel ( this, SvtResId( TXT_ENTRY ) ),
+ _aEntry ( this, SvtResId( TXT_ENTRYNAME ) ),
+ _aQueryMsg ( this, SvtResId( TXT_QUERYMSG ) ),
+ _aYesButton ( this, SvtResId( BTN_YES ) ),
+ _aAllButton ( this, SvtResId( BTN_ALL ) ),
+ _aNoButton ( this, SvtResId( BTN_NO ) ),
+ _aCancelButton( this, SvtResId( BTN_CANCEL ) )
+
+{
+ FreeResource();
+
+ // Handler
+ Link aLink( STATIC_LINK( this, QueryDeleteDlg_Impl, ClickLink ) );
+ _aYesButton.SetClickHdl( aLink );
+ _aAllButton.SetClickHdl( aLink );
+ _aNoButton.SetClickHdl( aLink );
+
+ // Anzeige der spezifizierten Texte
+
+ WinBits nTmpStyle = _aEntry.GetStyle();
+ nTmpStyle |= WB_PATHELLIPSIS;
+ _aEntry.SetStyle( nTmpStyle );
+ _aEntry.SetText( rName );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_STATIC_LINK( QueryDeleteDlg_Impl, ClickLink, PushButton*, pBtn )
+{
+ if ( pBtn == &pThis->_aYesButton )
+ pThis->_eResult = QUERYDELETE_YES;
+ else if ( pBtn == &pThis->_aNoButton )
+ pThis->_eResult = QUERYDELETE_NO;
+ else if ( pBtn == &pThis->_aAllButton )
+ pThis->_eResult = QUERYDELETE_ALL;
+ else if ( pBtn == &pThis->_aCancelButton )
+ pThis->_eResult = QUERYDELETE_CANCEL;
+
+ pThis->EndDialog( RET_OK );
+
+ return 0;
+}
+
+}
+
diff --git a/svtools/source/contnr/fileview.hrc b/svtools/source/contnr/fileview.hrc
new file mode 100644
index 000000000000..bbf340148fc9
--- /dev/null
+++ b/svtools/source/contnr/fileview.hrc
@@ -0,0 +1,40 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#define MID_FILEVIEW_DELETE 1
+#define MID_FILEVIEW_RENAME 2
+
+// DLG_SFX_QUERYDELETE ********************************************************
+
+#define TXT_ENTRY 1
+#define TXT_ENTRYNAME 2
+#define TXT_QUERYMSG 3
+#define BTN_YES 4
+#define BTN_NO 5
+#define BTN_ALL 6
+#define BTN_CANCEL 7
+
diff --git a/svtools/source/contnr/fileview.src b/svtools/source/contnr/fileview.src
new file mode 100644
index 000000000000..f40530c10347
--- /dev/null
+++ b/svtools/source/contnr/fileview.src
@@ -0,0 +1,196 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+ // includes ------------------------------------------------------------------
+
+#include <svtools/svtools.hrc>
+#include "fileview.hrc"
+#include <svtools/helpid.hrc>
+
+// strings --------------------------------------------------------------------
+
+String STR_SVT_FILEVIEW_COLUMN_TITLE
+{
+ Text [ en-US ] = "Title";
+};
+
+String STR_SVT_FILEVIEW_COLUMN_SIZE
+{
+ Text [ en-US ] = "Size";
+};
+
+String STR_SVT_FILEVIEW_COLUMN_DATE
+{
+ Text [ en-US ] = "Date modified";
+};
+
+String STR_SVT_FILEVIEW_COLUMN_TYPE
+{
+ Text [ en-US ] = "Type";
+};
+
+String STR_SVT_FILEVIEW_ERR_MAKEFOLDER
+{
+ Text [ en-US ] = "Could not create the folder %1.";
+};
+
+String STR_SVT_BYTES
+{
+ Text [ en-US ] = "Bytes" ;
+};
+
+String STR_SVT_KB
+{
+ Text [ en-US ] = "KB" ;
+};
+
+String STR_SVT_MB
+{
+ Text [ en-US ] = "MB" ;
+};
+
+
+String STR_SVT_GB
+{
+ Text [ en-US ] = "GB" ;
+};
+
+// Images ---------------------------------------------------------------------
+
+Image IMG_SVT_FOLDER
+{
+ ImageBitmap = Bitmap { File = "folder.bmp" ; };
+ MaskColor = Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; };
+};
+
+// Menus -----------------------------------------------------------------
+
+Menu RID_FILEVIEW_CONTEXTMENU
+{
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = MID_FILEVIEW_DELETE ;
+ HelpId = HID_FILEVIEW_MENU_DELETE ;
+ Text [ en-US ] = "~Delete";
+ };
+ MenuItem
+ {
+ Identifier = MID_FILEVIEW_RENAME ;
+ HelpId = HID_FILEVIEW_MENU_RENAME ;
+ Text [ en-US ] = "~Rename";
+ };
+ };
+};
+
+ModalDialog DLG_SVT_QUERYDELETE
+{
+ SVLook = TRUE ;
+ OutputSize = TRUE ;
+ Moveable = TRUE ;
+ Size = MAP_APPFONT ( 221 , 67 ) ;
+ Text [ en-US ] = "Confirm Delete" ;
+
+ FixedText TXT_ENTRY
+ {
+ NoLabel = TRUE;
+ Pos = MAP_APPFONT ( 6 , 6 ) ;
+ Size = MAP_APPFONT ( 40 , 10 ) ;
+ Text [ en-US ] = "Entry:" ;
+ };
+
+ FixedText TXT_ENTRYNAME
+ {
+ Pos = MAP_APPFONT ( 52 , 6 ) ;
+ Size = MAP_APPFONT ( 163 , 10 ) ;
+ NoLabel = TRUE ;
+ };
+
+ FixedText TXT_QUERYMSG
+ {
+ NoLabel = TRUE;
+ WordBreak = TRUE;
+ Pos = MAP_APPFONT ( 6 , 19 ) ;
+ Size = MAP_APPFONT ( 209 , 22 ) ;
+ Text [ en-US ] = "Are you sure you want to delete the selected data?" ;
+ };
+
+ PushButton BTN_YES
+ {
+ Pos = MAP_APPFONT ( 6 , 47 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ Text [ en-US ] = "~Delete" ;
+ };
+
+ PushButton BTN_ALL
+ {
+ Pos = MAP_APPFONT ( 59 , 47 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Disable = TRUE ;
+ Text [ en-US ] = "Delete ~All" ;
+ };
+
+ PushButton BTN_NO
+ {
+ Pos = MAP_APPFONT ( 112 , 47 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "Do ~Not Delete" ;
+ };
+
+ CancelButton BTN_CANCEL
+ {
+ Pos = MAP_APPFONT ( 165 , 47 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svtools/source/contnr/imivctl.hxx b/svtools/source/contnr/imivctl.hxx
new file mode 100644
index 000000000000..cc7aa4e05ee1
--- /dev/null
+++ b/svtools/source/contnr/imivctl.hxx
@@ -0,0 +1,637 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _IMPICNVW_HXX
+#define _IMPICNVW_HXX
+
+#ifndef _VIRDEV_HXX
+#include <vcl/virdev.hxx>
+#endif
+#ifndef _SCRBAR_HXX
+#include <vcl/scrbar.hxx>
+#endif
+#include <vcl/timer.hxx>
+#include <vcl/seleng.hxx>
+#include <tools/debug.hxx>
+#include "svtaccessiblefactory.hxx"
+
+#include <limits.h>
+
+#include "ivctrl.hxx"
+#include <svl/svarray.hxx>
+
+class IcnCursor_Impl;
+class SvtIconChoiceCtrl;
+class SvxIconChoiceCtrlEntry;
+class IcnViewEdit_Impl;
+class IcnGridMap_Impl;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// some defines
+//
+#define PAINTFLAG_HOR_CENTERED 0x0001
+#define PAINTFLAG_VER_CENTERED 0x0002
+
+#define F_VER_SBARSIZE_WITH_HBAR 0x0001
+#define F_HOR_SBARSIZE_WITH_VBAR 0x0002
+#define F_PAINTED 0x0004 // TRUE nach erstem Paint
+#define F_ADD_MODE 0x0008
+#define F_SELECTING_RECT 0x0020
+#define F_DOWN_CTRL 0x0080
+#define F_DOWN_DESELECT 0x0100
+#define F_START_EDITTIMER_IN_MOUSEUP 0x0400
+#define F_MOVED_ENTRIES 0x0800
+#define F_ENTRYLISTPOS_VALID 0x1000
+#define F_CLEARING_SELECTION 0x2000
+#define F_ARRANGING 0x4000
+
+// alle Angaben in Pixel
+// Abstaende von Fensterraendern
+#define LROFFS_WINBORDER 4
+#define TBOFFS_WINBORDER 4
+// fuer das Bounding-Rectangle
+#define LROFFS_BOUND 2
+#define TBOFFS_BOUND 2
+// Abstand Fokusrechteck - Icon
+#define LROFFS_ICON 2
+#define TBOFFS_ICON 2
+// Abstaende Icon - Text
+#define HOR_DIST_BMP_STRING 3
+#define VER_DIST_BMP_STRING 3
+// Breitenoffset Highlight-Rect bei Text
+#define LROFFS_TEXT 2
+
+#define DEFAULT_MAX_VIRT_WIDTH 200
+#define DEFAULT_MAX_VIRT_HEIGHT 200
+
+#define VIEWMODE_MASK (WB_ICON | WB_SMALLICON | WB_DETAILS)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//
+//
+enum IcnViewFieldType
+{
+ IcnViewFieldTypeDontknow = 0,
+ IcnViewFieldTypeImage = 1,
+ IcnViewFieldTypeText = 2
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Data about the focus of entries
+//
+struct LocalFocus
+{
+ BOOL bOn;
+ Rectangle aRect;
+ Color aPenColor;
+
+ LocalFocus() { bOn = FALSE; }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Entry-List
+//
+class EntryList_Impl : public List
+{
+private:
+
+ using List::Replace;
+
+ SvxIconChoiceCtrl_Impl* _pOwner;
+
+ void Removed_Impl( SvxIconChoiceCtrlEntry* pEntry );
+
+public:
+ EntryList_Impl(
+ SvxIconChoiceCtrl_Impl*,
+ USHORT _nInitSize = 1024,
+ USHORT _nReSize = 1024 );
+ EntryList_Impl(
+ SvxIconChoiceCtrl_Impl*,
+ USHORT _nBlockSize,
+ USHORT _nInitSize,
+ USHORT _nReSize );
+ ~EntryList_Impl();
+
+ void Clear();
+ void Insert( SvxIconChoiceCtrlEntry* pEntry, ULONG nPos );
+ SvxIconChoiceCtrlEntry* Remove( ULONG nPos );
+ void Remove( SvxIconChoiceCtrlEntry* pEntry );
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Implementation-class of IconChoiceCtrl
+//
+class SvxIconChoiceCtrl_Impl
+{
+ friend class IcnCursor_Impl;
+ friend class EntryList_Impl;
+ friend class IcnGridMap_Impl;
+
+ BOOL bChooseWithCursor;
+ EntryList_Impl aEntries;
+ ScrollBar aVerSBar;
+ ScrollBar aHorSBar;
+ ScrollBarBox aScrBarBox;
+ Rectangle aCurSelectionRect;
+ SvPtrarr aSelectedRectList;
+ Timer aEditTimer; // fuer Inplace-Editieren
+ Timer aAutoArrangeTimer;
+ Timer aDocRectChangedTimer;
+ Timer aVisRectChangedTimer;
+ Timer aCallSelectHdlTimer;
+ Size aVirtOutputSize;
+ Size aImageSize;
+ Size aDefaultTextSize;
+ Size aOutputSize; // Pixel
+ Point aDDLastEntryPos;
+ Point aDDLastRectPos;
+ Point aDDPaintOffs;
+ Point aDDStartPos;
+ SvtIconChoiceCtrl* pView;
+ IcnCursor_Impl* pImpCursor;
+ IcnGridMap_Impl* pGridMap;
+ long nMaxVirtWidth; // max. Breite aVirtOutputSize bei ALIGN_TOP
+ long nMaxVirtHeight; // max. Hoehe aVirtOutputSize bei ALIGN_LEFT
+ List* pZOrderList;
+ SvPtrarr* pColumns;
+ IcnViewEdit_Impl* pEdit;
+ WinBits nWinBits;
+ long nMaxBoundHeight; // Hoehe des hoechsten BoundRects
+ USHORT nFlags;
+ USHORT nCurTextDrawFlags;
+ ULONG nUserEventAdjustScrBars;
+ ULONG nUserEventShowCursor;
+ SvxIconChoiceCtrlEntry* pCurHighlightFrame;
+ BOOL bHighlightFramePressed;
+ SvxIconChoiceCtrlEntry* pHead; // Eintrag oben links
+ SvxIconChoiceCtrlEntry* pCursor;
+ SvxIconChoiceCtrlEntry* pPrevDropTarget;
+ SvxIconChoiceCtrlEntry* pHdlEntry;
+ SvxIconChoiceCtrlEntry* pDDRefEntry;
+ VirtualDevice* pDDDev;
+ VirtualDevice* pDDBufDev;
+ VirtualDevice* pDDTempDev;
+ VirtualDevice* pEntryPaintDev;
+ SvxIconChoiceCtrlEntry* pAnchor; // fuer Selektion
+ LocalFocus aFocus; // Data for focusrect
+ ::svt::AccessibleFactoryAccess aAccFactory;
+
+ List* pDraggedSelection;
+ SvxIconChoiceCtrlEntry* pCurEditedEntry;
+ SvxIconChoiceCtrlTextMode eTextMode;
+ SelectionMode eSelectionMode;
+ ULONG nSelectionCount;
+ SvxIconChoiceCtrlPositionMode ePositionMode;
+ BOOL bBoundRectsDirty;
+ BOOL bUpdateMode;
+ BOOL bEntryEditingEnabled;
+ BOOL bInDragDrop;
+
+ void ShowCursor( BOOL bShow );
+
+ void ImpArrange( BOOL bKeepPredecessors = FALSE );
+ void AdjustVirtSize( const Rectangle& );
+ void ResetVirtSize();
+ void CheckScrollBars();
+
+ DECL_LINK( ScrollUpDownHdl, ScrollBar * );
+ DECL_LINK( ScrollLeftRightHdl, ScrollBar * );
+ DECL_LINK( EditTimeoutHdl, Timer* );
+ DECL_LINK( UserEventHdl, void* );
+ DECL_LINK( EndScrollHdl, void* );
+ DECL_LINK( AutoArrangeHdl, void* );
+ DECL_LINK( DocRectChangedHdl, void* );
+ DECL_LINK( VisRectChangedHdl, void* );
+ DECL_LINK( CallSelectHdlHdl, void* );
+
+ void AdjustScrollBars( BOOL bVirtSizeGrowedOnly = FALSE);
+ void PositionScrollBars( long nRealWidth, long nRealHeight );
+ long GetScrollBarPageSize( long nVisibleRange ) const { return ((nVisibleRange*75)/100); }
+ long GetScrollBarLineSize() const { return nMaxBoundHeight / 2; }
+ BOOL HandleScrollCommand( const CommandEvent& rCmd );
+ void ToDocPos( Point& rPosPixel ) { rPosPixel -= pView->GetMapMode().GetOrigin(); }
+ void InitScrollBarBox();
+ SvxIconChoiceCtrlEntry* FindNewCursor();
+ void ToggleSelection( SvxIconChoiceCtrlEntry* );
+ void DeselectAllBut( SvxIconChoiceCtrlEntry*, BOOL bPaintSync=FALSE );
+ void Center( SvxIconChoiceCtrlEntry* pEntry ) const;
+ void StopEditTimer() { aEditTimer.Stop(); }
+ void StartEditTimer() { aEditTimer.Start(); }
+ void ImpHideDDIcon();
+ void CallSelectHandler( SvxIconChoiceCtrlEntry* );
+ void SelectRect(
+ SvxIconChoiceCtrlEntry* pEntry1,
+ SvxIconChoiceCtrlEntry* pEntry2,
+ BOOL bAdd = TRUE,
+ SvPtrarr* pOtherRects = 0 );
+
+ void SelectRange(
+ SvxIconChoiceCtrlEntry* pStart,
+ SvxIconChoiceCtrlEntry* pEnd,
+ BOOL bAdd = TRUE );
+
+ void AddSelectedRect( const Rectangle& );
+ void AddSelectedRect(
+ SvxIconChoiceCtrlEntry* pEntry1,
+ SvxIconChoiceCtrlEntry* pEntry2 );
+
+ void ClearSelectedRectList();
+ void ClearColumnList();
+ Rectangle CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const;
+
+ void ClipAtVirtOutRect( Rectangle& rRect ) const;
+ void AdjustAtGrid( const SvPtrarr& rRow, SvxIconChoiceCtrlEntry* pStart=0 );
+ Point AdjustAtGrid(
+ const Rectangle& rCenterRect, // "Schwerpunkt" des Objekts (typ. Bmp-Rect)
+ const Rectangle& rBoundRect ) const;
+ ULONG GetPredecessorGrid( const Point& rDocPos) const;
+
+ void InitPredecessors();
+ void ClearPredecessors();
+
+ BOOL CheckVerScrollBar();
+ BOOL CheckHorScrollBar();
+ void CancelUserEvents();
+ void EntrySelected( SvxIconChoiceCtrlEntry* pEntry, BOOL bSelect,
+ BOOL bSyncPaint );
+ void SaveSelection( List** );
+ void RepaintEntries( USHORT nEntryFlagsMask );
+ void SetListPositions();
+ void SetDefaultTextSize();
+ BOOL IsAutoArrange() const {
+ return (BOOL)(ePositionMode == IcnViewPositionModeAutoArrange); }
+ BOOL IsAutoAdjust() const {
+ return (BOOL)(ePositionMode == IcnViewPositionModeAutoAdjust); }
+ void DocRectChanged() { aDocRectChangedTimer.Start(); }
+ void VisRectChanged() { aVisRectChangedTimer.Start(); }
+ void SetOrigin( const Point&, BOOL bDoNotUpdateWallpaper = FALSE );
+
+ DECL_LINK( TextEditEndedHdl, IcnViewEdit_Impl* );
+
+ void ShowFocus ( Rectangle& rRect );
+ void HideFocus ();
+ void DrawFocusRect ( OutputDevice* pOut );
+
+ BOOL IsMnemonicChar( sal_Unicode cChar, ULONG& rPos ) const;
+
+public:
+
+ long nGridDX,
+ nGridDY;
+ long nHorSBarHeight,
+ nVerSBarWidth;
+
+ SvxIconChoiceCtrl_Impl( SvtIconChoiceCtrl* pView, WinBits nWinStyle );
+ ~SvxIconChoiceCtrl_Impl();
+
+ BOOL SetChoiceWithCursor ( BOOL bDo = TRUE ) { BOOL bOld=bChooseWithCursor; bChooseWithCursor = bDo; return bOld; }
+ void Clear( BOOL bInCtor = FALSE );
+ void SetStyle( WinBits nWinStyle );
+ WinBits GetStyle() const { return nWinBits; }
+ void InsertEntry( SvxIconChoiceCtrlEntry*, ULONG nPos, const Point* pPos=0 );
+ void CreateAutoMnemonics( MnemonicGenerator* _pGenerator = NULL );
+ void RemoveEntry( SvxIconChoiceCtrlEntry* pEntry );
+ void FontModified();
+ void SelectAll( BOOL bSelect = TRUE, BOOL bPaint = TRUE );
+ void SelectEntry(
+ SvxIconChoiceCtrlEntry*,
+ BOOL bSelect,
+ BOOL bCallHdl = TRUE,
+ BOOL bAddToSelection = FALSE,
+ BOOL bSyncPaint = FALSE );
+ void Paint( const Rectangle& rRect );
+ BOOL MouseButtonDown( const MouseEvent& );
+ BOOL MouseButtonUp( const MouseEvent& );
+ BOOL MouseMove( const MouseEvent&);
+ BOOL RequestHelp( const HelpEvent& rHEvt );
+ void SetCursor_Impl(
+ SvxIconChoiceCtrlEntry* pOldCursor,
+ SvxIconChoiceCtrlEntry* pNewCursor,
+ BOOL bMod1,
+ BOOL bShift,
+ BOOL bPaintSync = FALSE);
+ BOOL KeyInput( const KeyEvent& );
+ void Resize();
+ void GetFocus();
+ void LoseFocus();
+ void SetUpdateMode( BOOL bUpdate );
+ BOOL GetUpdateMode() const { return bUpdateMode; }
+ void PaintEntry( SvxIconChoiceCtrlEntry* pEntry, BOOL bIsBackgroundPainted=FALSE );
+ void PaintEntry(
+ SvxIconChoiceCtrlEntry*,
+ const Point&,
+ OutputDevice* pOut = 0,
+ BOOL bIsBackgroundPainted = FALSE);
+ void PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* );
+
+ void SetEntryPos(
+ SvxIconChoiceCtrlEntry* pEntry,
+ const Point& rPos,
+ BOOL bAdjustRow = FALSE,
+ BOOL bCheckScrollBars = FALSE,
+ BOOL bKeepGridMap = FALSE );
+
+ void InvalidateEntry( SvxIconChoiceCtrlEntry* );
+ IcnViewFieldType GetItem( SvxIconChoiceCtrlEntry*, const Point& rAbsPos );
+
+ void SetNoSelection();
+
+ SvxIconChoiceCtrlEntry* GetCurEntry() const { return pCursor; }
+ void SetCursor(
+ SvxIconChoiceCtrlEntry*,
+ // TRUE == bei Single-Selection die Sel. mitfuehren
+ BOOL bSyncSingleSelection = TRUE,
+ BOOL bShowFocusAsync = FALSE );
+
+ SvxIconChoiceCtrlEntry* GetEntry( const Point& rDocPos, BOOL bHit = FALSE );
+ SvxIconChoiceCtrlEntry* GetNextEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry );
+ SvxIconChoiceCtrlEntry* GetPrevEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry );
+
+ Point GetEntryPos( SvxIconChoiceCtrlEntry* );
+ void MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, BOOL bBound = TRUE );
+
+ void Arrange(BOOL bKeepPredecessors = FALSE, long nSetMaxVirtWidth =0, long nSetMaxVirtHeight =0 );
+
+ Rectangle CalcFocusRect( SvxIconChoiceCtrlEntry* );
+ Rectangle CalcBmpRect( SvxIconChoiceCtrlEntry*, const Point* pPos = 0 );
+ Rectangle CalcTextRect(
+ SvxIconChoiceCtrlEntry*,
+ const Point* pPos = 0,
+ BOOL bForInplaceEdit = FALSE,
+ const String* pStr = 0 );
+
+ long CalcBoundingWidth( SvxIconChoiceCtrlEntry* ) const;
+ long CalcBoundingHeight( SvxIconChoiceCtrlEntry* ) const;
+ Size CalcBoundingSize( SvxIconChoiceCtrlEntry* ) const;
+ void FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry );
+ void SetBoundingRect_Impl(
+ SvxIconChoiceCtrlEntry* pEntry,
+ const Point& rPos,
+ const Size& rBoundingSize );
+ // berechnet alle BoundRects neu
+ void RecalcAllBoundingRects();
+ // berechnet alle ungueltigen BoundRects neu
+ void RecalcAllBoundingRectsSmart();
+ const Rectangle& GetEntryBoundRect( SvxIconChoiceCtrlEntry* );
+ void InvalidateBoundingRect( SvxIconChoiceCtrlEntry* );
+ void InvalidateBoundingRect( Rectangle& rRect ) { rRect.Right() = LONG_MAX; bBoundRectsDirty = TRUE; }
+ BOOL IsBoundingRectValid( const Rectangle& rRect ) const { return (BOOL)( rRect.Right() != LONG_MAX ); }
+
+ void PaintEmphasis(
+ const Rectangle& rRect1,
+ const Rectangle& rRect2,
+ BOOL bSelected,
+ BOOL bDropTarget,
+ BOOL bCursored,
+ OutputDevice* pOut,
+ BOOL bIsBackgroundPainted = FALSE);
+
+ void PaintItem(
+ const Rectangle& rRect,
+ IcnViewFieldType eItem,
+ SvxIconChoiceCtrlEntry* pEntry,
+ USHORT nPaintFlags,
+ OutputDevice* pOut,
+ const String* pStr = 0,
+ ::vcl::ControlLayoutData* _pLayoutData = NULL );
+
+ // berechnet alle BoundingRects neu, wenn bMustRecalcBoundingRects == TRUE
+ void CheckBoundingRects() { if (bBoundRectsDirty) RecalcAllBoundingRectsSmart(); }
+ // berechnet alle invalidierten BoundingRects neu
+ void UpdateBoundingRects();
+ void ShowTargetEmphasis( SvxIconChoiceCtrlEntry* pEntry, BOOL bShow );
+ void PrepareCommandEvent( const CommandEvent& );
+ void Command( const CommandEvent& rCEvt );
+ void ToTop( SvxIconChoiceCtrlEntry* );
+
+ ULONG GetSelectionCount() const;
+ void SetGrid( const Size& );
+ Size GetMinGrid() const;
+ ULONG GetGridCount(
+ const Size& rSize,
+ BOOL bCheckScrBars,
+ BOOL bSmartScrBar ) const;
+ void Scroll( long nDeltaX, long nDeltaY, BOOL bScrollBar = FALSE );
+ const Size& GetItemSize( SvxIconChoiceCtrlEntry*, IcnViewFieldType ) const;
+
+ void HideDDIcon();
+ void ShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPos );
+ void HideShowDDIcon(
+ SvxIconChoiceCtrlEntry* pRefEntry,
+ const Point& rPos );
+
+ BOOL IsOver(
+ SvPtrarr* pSelectedRectList,
+ const Rectangle& rEntryBoundRect ) const;
+
+ void SelectRect(
+ const Rectangle&,
+ BOOL bAdd = TRUE,
+ SvPtrarr* pOtherRects = 0 );
+
+ void CalcScrollOffsets(
+ const Point& rRefPosPixel,
+ long& rX,
+ long& rY,
+ BOOL bDragDrop = FALSE,
+ USHORT nBorderWidth = 10 );
+
+ BOOL IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos );
+ void MakeVisible(
+ const Rectangle& rDocPos,
+ BOOL bInScrollBarEvent=FALSE,
+ BOOL bCallRectChangedHdl = TRUE );
+
+ void AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart = 0 );
+ void SetEntryTextMode( SvxIconChoiceCtrlTextMode, SvxIconChoiceCtrlEntry* pEntry = 0 );
+ SvxIconChoiceCtrlTextMode GetTextMode( const SvxIconChoiceCtrlEntry* pEntry = 0 ) const;
+ void ShowEntryFocusRect( const SvxIconChoiceCtrlEntry* pEntry );
+ void EnableEntryEditing( BOOL bEnable ) { bEntryEditingEnabled = bEnable; }
+ BOOL IsEntryEditingEnabled() const { return bEntryEditingEnabled; }
+ BOOL IsEntryEditing() const { return (BOOL)(pCurEditedEntry!=0); }
+ void EditEntry( SvxIconChoiceCtrlEntry* pEntry );
+ void StopEntryEditing( BOOL bCancel );
+ void LockEntryPos( SvxIconChoiceCtrlEntry* pEntry, BOOL bLock );
+ ULONG GetEntryCount() const { return aEntries.Count(); }
+ SvxIconChoiceCtrlEntry* GetEntry( ULONG nPos ) const { return (SvxIconChoiceCtrlEntry*)aEntries.GetObject(nPos); }
+ SvxIconChoiceCtrlEntry* GetFirstSelectedEntry( ULONG& ) const;
+ SvxIconChoiceCtrlEntry* GetNextSelectedEntry( ULONG& ) const;
+ SvxIconChoiceCtrlEntry* GetHdlEntry() const { return pHdlEntry; }
+ void SetHdlEntry( SvxIconChoiceCtrlEntry* pEntry ) { pHdlEntry = pEntry; }
+
+ SvxIconChoiceCtrlTextMode GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const;
+ void SetSelectionMode( SelectionMode eMode ) { eSelectionMode=eMode; }
+ SelectionMode GetSelectionMode() const { return eSelectionMode; }
+ BOOL AreEntriesMoved() const { return (BOOL)((nFlags & F_MOVED_ENTRIES)!=0); }
+ void SetEntriesMoved( BOOL bMoved )
+ {
+ if( bMoved ) nFlags |= F_MOVED_ENTRIES;
+ else nFlags &= ~(F_MOVED_ENTRIES);
+ }
+ ULONG GetEntryListPos( SvxIconChoiceCtrlEntry* ) const;
+ void SetEntryListPos( SvxIconChoiceCtrlEntry* pEntry, ULONG nNewPos );
+ void SetEntryImageSize( const Size& rSize ) { aImageSize = rSize; }
+ void SetEntryFlags( SvxIconChoiceCtrlEntry* pEntry, USHORT nFlags );
+ SvxIconChoiceCtrlEntry* GoLeftRight( SvxIconChoiceCtrlEntry*, BOOL bRight );
+ SvxIconChoiceCtrlEntry* GoUpDown( SvxIconChoiceCtrlEntry*, BOOL bDown );
+ void InitSettings();
+ Rectangle GetOutputRect() const;
+
+ BOOL ArePredecessorsSet() const { return (BOOL)(pHead != 0); }
+ SvxIconChoiceCtrlEntry* GetPredecessorHead() const { return pHead; }
+ void SetEntryPredecessor(SvxIconChoiceCtrlEntry* pEntry,SvxIconChoiceCtrlEntry* pPredecessor);
+ BOOL GetEntryPredecessor(SvxIconChoiceCtrlEntry* pEntry,SvxIconChoiceCtrlEntry** ppPredecessor);
+ // liefert gueltige Ergebnisse nur im AutoArrange-Modus!
+ SvxIconChoiceCtrlEntry* FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry, const Point& );
+
+ void SetPositionMode( SvxIconChoiceCtrlPositionMode );
+ SvxIconChoiceCtrlPositionMode GetPositionMode() const { return ePositionMode;}
+
+ void Flush();
+ void SetColumn( USHORT nIndex, const SvxIconChoiceCtrlColumnInfo& );
+ const SvxIconChoiceCtrlColumnInfo* GetColumn( USHORT nIndex ) const;
+ const SvxIconChoiceCtrlColumnInfo* GetItemColumn( USHORT nSubItem, long& rLeft ) const;
+
+ Rectangle GetDocumentRect() const { return Rectangle( Point(), aVirtOutputSize ); }
+ Rectangle GetVisibleRect() const { return GetOutputRect(); }
+
+ void SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,BOOL bKeepHighlightFlags=FALSE );
+ void HideEntryHighlightFrame();
+ void DrawHighlightFrame( OutputDevice* pOut,
+ const Rectangle& rBmpRect, BOOL bHide );
+ void StopSelectTimer() { aCallSelectHdlTimer.Stop(); }
+ void Tracking( const TrackingEvent& rTEvt );
+ Point GetPopupMenuPosPixel() const;
+
+ BOOL HandleShortCutKey( const KeyEvent& rKeyEvent );
+
+ void CallEventListeners( ULONG nEvent, void* pData = NULL );
+
+ inline ::svt::IAccessibleFactory&
+ GetAccessibleFactory() { return aAccFactory.getFactory(); }
+};
+
+// ----------------------------------------------------------------------------------------------
+
+class IcnCursor_Impl
+{
+ SvxIconChoiceCtrl_Impl* pView;
+ SvPtrarr* pColumns;
+ SvPtrarr* pRows;
+ long nCols;
+ long nRows;
+ short nDeltaWidth;
+ short nDeltaHeight;
+ SvxIconChoiceCtrlEntry* pCurEntry;
+ void SetDeltas();
+ void ImplCreate();
+ void Create() { if( !pColumns ) ImplCreate(); }
+
+ USHORT GetSortListPos( SvPtrarr* pList, long nValue, int bVertical);
+ SvxIconChoiceCtrlEntry* SearchCol(USHORT nCol,USHORT nTop,USHORT nBottom,USHORT nPref,
+ BOOL bDown, BOOL bSimple );
+
+ SvxIconChoiceCtrlEntry* SearchRow(USHORT nRow,USHORT nRight,USHORT nLeft,USHORT nPref,
+ BOOL bRight, BOOL bSimple );
+
+public:
+ IcnCursor_Impl( SvxIconChoiceCtrl_Impl* pOwner );
+ ~IcnCursor_Impl();
+ void Clear();
+
+ // fuer Cursortravelling usw.
+ SvxIconChoiceCtrlEntry* GoLeftRight( SvxIconChoiceCtrlEntry*, BOOL bRight );
+ SvxIconChoiceCtrlEntry* GoUpDown( SvxIconChoiceCtrlEntry*, BOOL bDown );
+ SvxIconChoiceCtrlEntry* GoPageUpDown( SvxIconChoiceCtrlEntry*, BOOL bDown );
+
+ // Erzeugt fuer jede Zeile (Hoehe=nGridDY) eine nach BoundRect.Left()
+ // sortierte Liste der Eintraege, die in ihr stehen. Eine Liste kann
+ // leer sein. Die Listen gehen in das Eigentum des Rufenden ueber und
+ // muessen mit DestroyGridAdjustData geloescht werden
+ void CreateGridAjustData( SvPtrarr& pLists, SvxIconChoiceCtrlEntry* pRow=0);
+ static void DestroyGridAdjustData( SvPtrarr& rLists );
+};
+
+// ----------------------------------------------------------------------------------------------
+
+typedef ULONG GridId;
+
+#define GRID_NOT_FOUND ((GridId)ULONG_MAX)
+
+class IcnGridMap_Impl
+{
+ Rectangle _aLastOccupiedGrid;
+ SvxIconChoiceCtrl_Impl* _pView;
+ BOOL* _pGridMap;
+ USHORT _nGridCols, _nGridRows;
+
+ void Expand();
+ void Create_Impl();
+ void Create() { if(!_pGridMap) Create_Impl(); }
+
+ void GetMinMapSize( USHORT& rDX, USHORT& rDY ) const;
+
+public:
+ IcnGridMap_Impl(SvxIconChoiceCtrl_Impl* pView);
+ ~IcnGridMap_Impl();
+
+ void Clear();
+
+ GridId GetGrid( const Point& rDocPos, BOOL* pbClipped = 0 );
+ GridId GetGrid( USHORT nGridX, USHORT nGridY );
+ GridId GetUnoccupiedGrid( BOOL bOccupyFound=TRUE );
+
+ void OccupyGrids( const Rectangle&, BOOL bOccupy = TRUE );
+ void OccupyGrids( const SvxIconChoiceCtrlEntry*, BOOL bOccupy = TRUE );
+ void OccupyGrid( GridId nId, BOOL bOccupy = TRUE )
+ {
+ DBG_ASSERT(!_pGridMap || nId<(ULONG)(_nGridCols*_nGridRows),"OccupyGrid: Bad GridId");
+ if(_pGridMap && nId < (ULONG)(_nGridCols *_nGridRows) )
+ _pGridMap[ nId ] = bOccupy;
+ }
+
+ Rectangle GetGridRect( GridId );
+ void GetGridCoord( GridId, USHORT& rGridX, USHORT& rGridY );
+ static ULONG GetGridCount( const Size& rSizePixel, USHORT nGridWidth, USHORT nGridHeight );
+
+ void OutputSizeChanged();
+};
+
+
+
+
+
+#endif
+
+
diff --git a/svtools/source/contnr/imivctl1.cxx b/svtools/source/contnr/imivctl1.cxx
new file mode 100644
index 000000000000..dd2ed992536e
--- /dev/null
+++ b/svtools/source/contnr/imivctl1.cxx
@@ -0,0 +1,4681 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+#include <limits.h>
+#include <tools/debug.hxx>
+#include <vcl/wall.hxx>
+#include <vcl/help.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/poly.hxx>
+#include <vcl/lineinfo.hxx>
+#include <vcl/i18nhelp.hxx>
+#include <vcl/mnemonic.hxx>
+#include <vcl/controllayout.hxx>
+
+#include "ivctrl.hxx"
+#include "imivctl.hxx"
+#include <svtools/svmedit.hxx>
+
+#include <algorithm>
+#include <memory>
+
+#define DD_SCROLL_PIXEL 24
+#define IMPICNVIEW_ACC_RETURN 1
+#define IMPICNVIEW_ACC_ESCAPE 2
+
+#define DRAWTEXT_FLAGS_ICON \
+ ( TEXT_DRAW_CENTER | TEXT_DRAW_TOP | TEXT_DRAW_ENDELLIPSIS | \
+ TEXT_DRAW_CLIP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MNEMONIC )
+
+#define DRAWTEXT_FLAGS_SMALLICON (TEXT_DRAW_LEFT|TEXT_DRAW_ENDELLIPSIS|TEXT_DRAW_CLIP)
+
+#define EVENTID_SHOW_CURSOR ((void*)1)
+#define EVENTID_ADJUST_SCROLLBARS ((void*)2)
+
+struct SvxIconChoiceCtrlEntry_Impl
+{
+ SvxIconChoiceCtrlEntry* _pEntry;
+ Point _aPos;
+ SvxIconChoiceCtrlEntry_Impl( SvxIconChoiceCtrlEntry* pEntry, const Rectangle& rBoundRect )
+ : _pEntry( pEntry), _aPos( rBoundRect.TopLeft()) {}
+};
+
+static BOOL bEndScrollInvalidate = TRUE;
+
+// ----------------------------------------------------------------------------------------------
+
+class IcnViewEdit_Impl : public MultiLineEdit
+{
+ Link aCallBackHdl;
+ Accelerator aAccReturn;
+ Accelerator aAccEscape;
+ Timer aTimer;
+ BOOL bCanceled;
+ BOOL bAlreadyInCallback;
+ BOOL bGrabFocus;
+
+ void CallCallBackHdl_Impl();
+ DECL_LINK( Timeout_Impl, Timer * );
+ DECL_LINK( ReturnHdl_Impl, Accelerator * );
+ DECL_LINK( EscapeHdl_Impl, Accelerator * );
+
+public:
+
+ IcnViewEdit_Impl(
+ SvtIconChoiceCtrl* pParent,
+ const Point& rPos,
+ const Size& rSize,
+ const XubString& rData,
+ const Link& rNotifyEditEnd );
+
+ ~IcnViewEdit_Impl();
+ virtual void KeyInput( const KeyEvent& rKEvt );
+ virtual long PreNotify( NotifyEvent& rNEvt );
+ BOOL EditingCanceled() const { return bCanceled; }
+ void StopEditing( BOOL bCancel = FALSE );
+ BOOL IsGrabFocus() const { return bGrabFocus; }
+};
+
+// ----------------------------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------------------------
+
+SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl( SvtIconChoiceCtrl* pCurView,
+ WinBits nWinStyle ) :
+ aEntries( this ),
+ aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ),
+ aHorSBar( pCurView, WB_DRAG | WB_HSCROLL ),
+ aScrBarBox( pCurView ),
+ aImageSize( 32, 32 ),
+ pColumns( 0 )
+{
+ bChooseWithCursor=FALSE;
+ pEntryPaintDev = 0;
+ pCurEditedEntry = 0;
+ pCurHighlightFrame = 0;
+ pEdit = 0;
+ pAnchor = 0;
+ pDraggedSelection = 0;
+ pPrevDropTarget = 0;
+ pHdlEntry = 0;
+ pHead = NULL;
+ pCursor = NULL;
+ bUpdateMode = TRUE;
+ bEntryEditingEnabled = FALSE;
+ bInDragDrop = FALSE;
+ bHighlightFramePressed = FALSE;
+ eSelectionMode = MULTIPLE_SELECTION;
+ pView = pCurView;
+ pZOrderList = new List; //SvPtrarr;
+ ePositionMode = IcnViewPositionModeFree;
+ SetStyle( nWinStyle );
+ nFlags = 0;
+ nUserEventAdjustScrBars = 0;
+ nUserEventShowCursor = 0;
+ nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
+ nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
+ pDDRefEntry = 0;
+ pDDDev = 0;
+ pDDBufDev = 0;
+ pDDTempDev = 0;
+ eTextMode = IcnShowTextShort;
+ pImpCursor = new IcnCursor_Impl( this );
+ pGridMap = new IcnGridMap_Impl( this );
+
+ aVerSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl ) );
+ aHorSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl ) );
+ Link aEndScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, EndScrollHdl ) );
+ aVerSBar.SetEndScrollHdl( aEndScrollHdl );
+ aHorSBar.SetEndScrollHdl( aEndScrollHdl );
+
+ nHorSBarHeight = aHorSBar.GetSizePixel().Height();
+ nVerSBarWidth = aVerSBar.GetSizePixel().Width();
+
+ aEditTimer.SetTimeout( 800 );
+ aEditTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl));
+ aAutoArrangeTimer.SetTimeout( 100 );
+ aAutoArrangeTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl));
+ aCallSelectHdlTimer.SetTimeout( 500 );
+ aCallSelectHdlTimer.SetTimeoutHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl));
+
+ aDocRectChangedTimer.SetTimeout( 50 );
+ aDocRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl));
+ aVisRectChangedTimer.SetTimeout( 50 );
+ aVisRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl));
+
+ Clear( TRUE );
+
+ SetGrid( Size(100, 70) );
+}
+
+SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
+{
+ pCurEditedEntry = 0;
+ DELETEZ(pEdit);
+ Clear();
+ StopEditTimer();
+ CancelUserEvents();
+ delete pZOrderList;
+ delete pImpCursor;
+ delete pGridMap;
+ delete pDDDev;
+ delete pDDBufDev;
+ delete pDDTempDev;
+ delete pDraggedSelection;
+ delete pEntryPaintDev;
+ ClearSelectedRectList();
+ ClearColumnList();
+}
+
+void SvxIconChoiceCtrl_Impl::Clear( BOOL bInCtor )
+{
+ StopEntryEditing( TRUE );
+ nSelectionCount = 0;
+ DELETEZ(pDraggedSelection);
+ bInDragDrop = FALSE;
+ pCurHighlightFrame = 0;
+ StopEditTimer();
+ CancelUserEvents();
+ ShowCursor( FALSE );
+ bBoundRectsDirty = FALSE;
+ nMaxBoundHeight = 0;
+
+ nFlags &= ~(F_PAINTED | F_MOVED_ENTRIES);
+ pCursor = 0;
+ if( !bInCtor )
+ {
+ pImpCursor->Clear();
+ pGridMap->Clear();
+ aVirtOutputSize.Width() = 0;
+ aVirtOutputSize.Height() = 0;
+ Size aSize( pView->GetOutputSizePixel() );
+ nMaxVirtWidth = aSize.Width() - nVerSBarWidth;
+ if( nMaxVirtWidth <= 0 )
+ nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
+ nMaxVirtHeight = aSize.Height() - nHorSBarHeight;
+ if( nMaxVirtHeight <= 0 )
+ nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
+ pZOrderList->Clear(); //Remove(0,pZOrderList->Count());
+ SetOrigin( Point() );
+ if( bUpdateMode )
+ pView->Invalidate(INVALIDATE_NOCHILDREN);
+ }
+ AdjustScrollBars();
+ ULONG nCount = aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ delete pCur;
+ }
+ aEntries.Clear();
+ DocRectChanged();
+ VisRectChanged();
+}
+
+void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle )
+{
+ nWinBits = nWinStyle;
+ nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON;
+ if( nWinBits & (WB_SMALLICON | WB_DETAILS) )
+ nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON;
+ if( nWinBits & WB_NOSELECTION )
+ eSelectionMode = NO_SELECTION;
+ if( !(nWinStyle & (WB_ALIGN_TOP | WB_ALIGN_LEFT)))
+ nWinBits |= WB_ALIGN_LEFT;
+ if( (nWinStyle & WB_DETAILS))
+ {
+ if( !pColumns )
+ SetColumn( 0, SvxIconChoiceCtrlColumnInfo( 0, 100, IcnViewAlignLeft ));
+ }
+}
+
+IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar )
+{
+ StopEntryEditing( TRUE );
+ // Pfeil hoch: delta=-1; Pfeil runter: delta=+1
+ Scroll( 0, pScrollBar->GetDelta(), TRUE );
+ bEndScrollInvalidate = TRUE;
+ return 0;
+}
+
+IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar )
+{
+ StopEntryEditing( TRUE );
+ // Pfeil links: delta=-1; Pfeil rechts: delta=+1
+ Scroll( pScrollBar->GetDelta(), 0, TRUE );
+ bEndScrollInvalidate = TRUE;
+ return 0;
+}
+
+IMPL_LINK( SvxIconChoiceCtrl_Impl, EndScrollHdl, void*, EMPTYARG )
+{
+ if( pView->HasBackground() && !pView->GetBackground().IsScrollable() &&
+ bEndScrollInvalidate )
+ {
+ pView->Invalidate(INVALIDATE_NOCHILDREN);
+ }
+ return 0;
+}
+
+void SvxIconChoiceCtrl_Impl::FontModified()
+{
+ StopEditTimer();
+ DELETEZ(pDDDev);
+ DELETEZ(pDDBufDev);
+ DELETEZ(pDDTempDev);
+ DELETEZ(pEntryPaintDev);
+ SetDefaultTextSize();
+ ShowCursor( FALSE );
+ ShowCursor( TRUE );
+}
+
+void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry* pEntry, ULONG nPos,
+ const Point* pPos )
+{
+ StopEditTimer();
+ aEntries.Insert( pEntry, nPos );
+ if( (nFlags & F_ENTRYLISTPOS_VALID) && nPos >= aEntries.Count() - 1 )
+ pEntry->nPos = aEntries.Count() - 1;
+ else
+ nFlags &= ~F_ENTRYLISTPOS_VALID;
+
+ pZOrderList->Insert( (void*)pEntry, LIST_APPEND ); //pZOrderList->Count() );
+ pImpCursor->Clear();
+// pGridMap->Clear();
+ if( pPos )
+ {
+ Size aSize( CalcBoundingSize( pEntry ) );
+ SetBoundingRect_Impl( pEntry, *pPos, aSize );
+ SetEntryPos( pEntry, *pPos, FALSE, TRUE, TRUE /*keep grid map*/ );
+ pEntry->nFlags |= ICNVIEW_FLAG_POS_MOVED;
+ SetEntriesMoved( TRUE );
+ }
+ else
+ {
+ // wenn der UpdateMode TRUE ist, wollen wir nicht pauschal alle
+ // BoundRects auf 'zu ueberpruefen' setzen, sondern nur das des
+ // neuen Eintrags. Deshalb kein InvalidateBoundingRect aufrufen!
+ pEntry->aRect.Right() = LONG_MAX;
+ if( bUpdateMode )
+ {
+ FindBoundingRect( pEntry );
+ Rectangle aOutputArea( GetOutputRect() );
+ pGridMap->OccupyGrids( pEntry );
+ if( !aOutputArea.IsOver( pEntry->aRect ) )
+ return; // ist nicht sichtbar
+ pView->Invalidate( pEntry->aRect );
+ }
+ else
+ InvalidateBoundingRect( pEntry->aRect );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator* _pGenerator )
+{
+ ::std::auto_ptr< MnemonicGenerator > pAutoDeleteOwnGenerator;
+ if ( !_pGenerator )
+ {
+ _pGenerator = new MnemonicGenerator;
+ pAutoDeleteOwnGenerator.reset( _pGenerator );
+ }
+
+ ULONG nEntryCount = GetEntryCount();
+ ULONG i;
+
+ // insert texts in generator
+ for( i = 0; i < nEntryCount; ++i )
+ {
+ DBG_ASSERT( GetEntry( i ), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" );
+
+ _pGenerator->RegisterMnemonic( GetEntry( i )->GetText() );
+ }
+
+ // exchange texts with generated mnemonics
+ for( i = 0; i < nEntryCount; ++i )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = GetEntry( i );
+ String aTxt = pEntry->GetText();
+
+ if( _pGenerator->CreateMnemonic( aTxt ) )
+ pEntry->SetText( aTxt );
+ }
+}
+
+Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const
+{
+ Point aOrigin( pView->GetMapMode().GetOrigin() );
+ aOrigin *= -1;
+ return Rectangle( aOrigin, aOutputSize );
+}
+
+void SvxIconChoiceCtrl_Impl::SetListPositions()
+{
+ if( nFlags & F_ENTRYLISTPOS_VALID )
+ return;
+
+ ULONG nCount = aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ pEntry->nPos = nCur;
+ }
+ nFlags |= F_ENTRYLISTPOS_VALID;
+}
+
+void SvxIconChoiceCtrl_Impl::RemoveEntry( SvxIconChoiceCtrlEntry* pEntry )
+{
+ BOOL bSyncSingleSelection;
+ // bei Single-Selection wird die Selektion beim Umsetzen des Cursors
+ // mitgefuehrt. Das soll aber nur erfolgen, wenn ueberhaupt ein
+ // Eintrag selektiert ist.
+ if( GetSelectionCount() )
+ bSyncSingleSelection = TRUE;
+ else
+ bSyncSingleSelection = FALSE;
+
+ if( pEntry == pCurHighlightFrame )
+ pCurHighlightFrame = 0;
+
+ if( bInDragDrop )
+ {
+ DELETEZ(pDraggedSelection);
+ bInDragDrop = FALSE;
+ }
+
+ if( pEntry->IsSelected() )
+ CallSelectHandler( 0 );
+
+ if( aEntries.Count() == 1 && aEntries.GetObject(0) == pEntry )
+ {
+ Clear();
+ return;
+ }
+
+ StopEditTimer();
+ if( pEntry == pAnchor )
+ pAnchor = 0;
+ if( pEntry->IsSelected() )
+ nSelectionCount--;
+ BOOL bEntryBoundValid = IsBoundingRectValid( pEntry->aRect );
+ if( bEntryBoundValid )
+ pView->Invalidate( pEntry->aRect );
+
+ BOOL bSetNewCursor = FALSE;
+ SvxIconChoiceCtrlEntry* pNewCursor = NULL;
+
+ if( pEntry == pCursor )
+ {
+ bSetNewCursor = TRUE;
+ pNewCursor = FindNewCursor();
+ ShowCursor( FALSE );
+ pCursor = 0;
+ }
+
+ BOOL bCurEntryPosValid = (nFlags & F_ENTRYLISTPOS_VALID) ? TRUE : FALSE;
+ if( bCurEntryPosValid && aEntries.GetObject(aEntries.Count()-1) != pEntry )
+ nFlags &= ~F_ENTRYLISTPOS_VALID;
+ ULONG nPos = pZOrderList->GetPos( (void*)pEntry );
+ pZOrderList->Remove( nPos );
+ if( bCurEntryPosValid )
+ {
+ DBG_ASSERT(aEntries.GetObject(pEntry->nPos)==pEntry,"RemoveEntry: Wrong nPos in entry");
+ aEntries.Remove( pEntry->nPos );
+ }
+ else
+ aEntries.Remove( pEntry );
+ pImpCursor->Clear();
+ pGridMap->Clear();
+ delete pEntry;
+ if( IsAutoArrange() && aEntries.Count() )
+ aAutoArrangeTimer.Start();
+ if( bSetNewCursor )
+ {
+ // Fokusrechteck asynchron einblenden, um das Loeschen einer
+ // Multiselektion zu beschleunigen.
+ SetCursor( pNewCursor, bSyncSingleSelection, TRUE );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, BOOL bSelect,
+ BOOL bCallHdl, BOOL bAdd, BOOL bSyncPaint )
+{
+ if( eSelectionMode == NO_SELECTION )
+ return;
+
+ if( !bAdd )
+ {
+ if ( 0 == ( nFlags & F_CLEARING_SELECTION ) )
+ {
+ nFlags |= F_CLEARING_SELECTION;
+ DeselectAllBut( pEntry, sal_True );
+ nFlags &= ~F_CLEARING_SELECTION;
+ }
+ }
+ if( pEntry->IsSelected() != bSelect )
+ {
+ pHdlEntry = pEntry;
+ USHORT nEntryFlags = pEntry->GetFlags();
+ if( bSelect )
+ {
+ nEntryFlags |= ICNVIEW_FLAG_SELECTED;
+ pEntry->AssignFlags( nEntryFlags );
+ nSelectionCount++;
+ if( bCallHdl )
+ CallSelectHandler( pEntry );
+ }
+ else
+ {
+ nEntryFlags &= ~( ICNVIEW_FLAG_SELECTED);
+ pEntry->AssignFlags( nEntryFlags );
+ nSelectionCount--;
+ if( bCallHdl )
+ CallSelectHandler( 0 );
+ }
+ EntrySelected( pEntry, bSelect, bSyncPaint );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry* pEntry, BOOL bSelect,
+ BOOL bSyncPaint )
+{
+ // bei SingleSelection dafuer sorgen, dass der Cursor immer
+ // auf dem (einzigen) selektierten Eintrag steht. Aber nur,
+ // wenn es bereits einen Cursor gibt
+ if( bSelect && pCursor &&
+ eSelectionMode == SINGLE_SELECTION &&
+ pEntry != pCursor )
+ {
+ SetCursor( pEntry );
+ //DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?")
+ }
+
+ // beim Aufziehen nicht, da sonst die Schleife in SelectRect
+ // nicht richtig funktioniert!
+ if( !(nFlags & F_SELECTING_RECT) )
+ ToTop( pEntry );
+ if( bUpdateMode )
+ {
+ if( pEntry == pCursor )
+ ShowCursor( FALSE );
+ if( pView->IsTracking() && (bSelect || !pView->HasBackground()) ) // beim Tracken immer synchron
+ PaintEntry( pEntry );
+ else if( bSyncPaint ) // synchron & mit virtuellem OutDev!
+ PaintEntryVirtOutDev( pEntry );
+ else
+ {
+ pView->Invalidate( CalcFocusRect( pEntry ) );
+ }
+ if( pEntry == pCursor )
+ ShowCursor( TRUE );
+ } // if( bUpdateMode )
+
+ // --> OD 2009-05-27 #i101012#
+ // emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
+ if ( bSelect )
+ {
+ CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
+ }
+ // <--
+}
+
+void SvxIconChoiceCtrl_Impl::ResetVirtSize()
+{
+ StopEditTimer();
+ aVirtOutputSize.Width() = 0;
+ aVirtOutputSize.Height() = 0;
+ BOOL bLockedEntryFound = FALSE;
+ const ULONG nCount = aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ pCur->ClearFlags( ICNVIEW_FLAG_POS_MOVED );
+ if( pCur->IsPosLocked() )
+ {
+ // VirtSize u.a. anpassen
+ if( !IsBoundingRectValid( pCur->aRect ) )
+ FindBoundingRect( pCur );
+ else
+ AdjustVirtSize( pCur->aRect );
+ bLockedEntryFound = TRUE;
+ }
+ else
+ InvalidateBoundingRect( pCur->aRect );
+ }
+
+ if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) )
+ {
+ Size aRealOutputSize( pView->GetOutputSizePixel() );
+ if( aVirtOutputSize.Width() < aRealOutputSize.Width() ||
+ aVirtOutputSize.Height() < aRealOutputSize.Height() )
+ {
+ ULONG nGridCount = IcnGridMap_Impl::GetGridCount(
+ aRealOutputSize, (USHORT)nGridDX, (USHORT)nGridDY );
+ if( nGridCount < nCount )
+ {
+ if( nWinBits & WB_ALIGN_TOP )
+ nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth;
+ else // WB_ALIGN_LEFT
+ nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight;
+ }
+ }
+ }
+
+ pImpCursor->Clear();
+ pGridMap->Clear();
+ VisRectChanged();
+}
+
+void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle& rRect )
+{
+ long nHeightOffs = 0;
+ long nWidthOffs = 0;
+
+ if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
+ nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
+
+ if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
+ nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
+
+ if( nWidthOffs || nHeightOffs )
+ {
+ Range aRange;
+ aVirtOutputSize.Width() += nWidthOffs;
+ aRange.Max() = aVirtOutputSize.Width();
+ aHorSBar.SetRange( aRange );
+
+ aVirtOutputSize.Height() += nHeightOffs;
+ aRange.Max() = aVirtOutputSize.Height();
+ aVerSBar.SetRange( aRange );
+
+ pImpCursor->Clear();
+ pGridMap->OutputSizeChanged();
+ AdjustScrollBars();
+ DocRectChanged();
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::InitPredecessors()
+{
+ DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
+ ULONG nCount = aEntries.Count();
+ if( nCount )
+ {
+ SvxIconChoiceCtrlEntry* pPrev = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
+ for( ULONG nCur = 1; nCur <= nCount; nCur++ )
+ {
+ pPrev->ClearFlags( ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED |
+ ICNVIEW_FLAG_PRED_SET);
+
+ SvxIconChoiceCtrlEntry* pNext;
+ if( nCur == nCount )
+ pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
+ else
+ pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ pPrev->pflink = pNext;
+ pNext->pblink = pPrev;
+ pPrev = pNext;
+ }
+ pHead = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
+ }
+ else
+ pHead = 0;
+ nFlags &= ~F_MOVED_ENTRIES;
+}
+
+void SvxIconChoiceCtrl_Impl::ClearPredecessors()
+{
+ if( pHead )
+ {
+ ULONG nCount = aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ pCur->pflink = 0;
+ pCur->pblink = 0;
+ pCur->ClearFlags( ICNVIEW_FLAG_PRED_SET );
+ }
+ pHead = 0;
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::Arrange( BOOL bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight )
+{
+ if ( nSetMaxVirtWidth != 0 )
+ nMaxVirtWidth = nSetMaxVirtWidth;
+ else
+ nMaxVirtWidth = aOutputSize.Width();
+
+ if ( nSetMaxVirtHeight != 0 )
+ nMaxVirtHeight = nSetMaxVirtHeight;
+ else
+ nMaxVirtHeight = aOutputSize.Height();
+
+ ImpArrange( bKeepPredecessors );
+}
+
+void SvxIconChoiceCtrl_Impl::ImpArrange( BOOL bKeepPredecessors )
+{
+ static Point aEmptyPoint;
+
+ BOOL bOldUpdate = bUpdateMode;
+ Rectangle aCurOutputArea( GetOutputRect() );
+ if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
+ bUpdateMode = FALSE;
+ aAutoArrangeTimer.Stop();
+ nFlags &= ~F_MOVED_ENTRIES;
+ nFlags |= F_ARRANGING;
+ StopEditTimer();
+ ShowCursor( FALSE );
+ ResetVirtSize();
+ if( !bKeepPredecessors )
+ ClearPredecessors();
+ bBoundRectsDirty = FALSE;
+ SetOrigin( Point() );
+ VisRectChanged();
+ RecalcAllBoundingRectsSmart();
+ // in der Detailsview muss das Invalidieren intelligenter erfolgen
+ //if( !(nWinBits & WB_DETAILS ))
+ pView->Invalidate( INVALIDATE_NOCHILDREN );
+ nFlags &= ~F_ARRANGING;
+ if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
+ {
+ MakeVisible( aCurOutputArea );
+ SetUpdateMode( bOldUpdate );
+ }
+ ShowCursor( TRUE );
+}
+
+void SvxIconChoiceCtrl_Impl::Paint( const Rectangle& rRect )
+{
+ bEndScrollInvalidate = FALSE;
+
+#if defined(OV_DRAWGRID)
+ Color aOldColor ( pView->GetLineColor() );
+ Color aColor( COL_BLACK );
+ pView->SetLineColor( aColor );
+ Point aOffs( pView->GetMapMode().GetOrigin());
+ Size aXSize( pView->GetOutputSizePixel() );
+
+ {
+ Point aStart( LROFFS_WINBORDER, 0 );
+ Point aEnd( LROFFS_WINBORDER, aXSize.Height());
+ aStart -= aOffs;
+ aEnd -= aOffs;
+ pView->DrawLine( aStart, aEnd );
+ }
+ {
+ Point aStart( 0, TBOFFS_WINBORDER );
+ Point aEnd( aXSize.Width(), TBOFFS_WINBORDER );
+ aStart -= aOffs;
+ aEnd -= aOffs;
+ pView->DrawLine( aStart, aEnd );
+ }
+
+ for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
+ {
+ Point aStart( nDX+LROFFS_WINBORDER, 0 );
+ Point aEnd( nDX+LROFFS_WINBORDER, aXSize.Height());
+ aStart -= aOffs;
+ aEnd -= aOffs;
+ pView->DrawLine( aStart, aEnd );
+ }
+ for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
+ {
+ Point aStart( 0, nDY+TBOFFS_WINBORDER );
+ Point aEnd( aXSize.Width(), nDY+TBOFFS_WINBORDER );
+ aStart -= aOffs;
+ aEnd -= aOffs;
+ pView->DrawLine( aStart, aEnd );
+ }
+ pView->SetLineColor( aOldColor );
+#endif
+ nFlags |= F_PAINTED;
+
+ if( !aEntries.Count() )
+ return;
+ if( !pCursor )
+ {
+ // set cursor to item with focus-flag
+ BOOL bfound = FALSE;
+ for ( ULONG i = 0; i < pView->GetEntryCount() && !bfound; i++)
+ {
+ SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry ( i );
+ if( pEntry->IsFocused() )
+ {
+ pCursor = pEntry;
+ bfound=TRUE;
+ }
+ }
+
+ if( !bfound )
+ pCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
+ }
+
+ // Show Focus at Init-Time
+ if ( pView->HasFocus() )
+ GetFocus();
+
+ ULONG nCount = pZOrderList->Count();
+ if( !nCount )
+ return;
+
+ BOOL bResetClipRegion = FALSE;
+ if( !pView->IsClipRegion() )
+ {
+ Rectangle aOutputArea( GetOutputRect() );
+ bResetClipRegion = TRUE;
+ pView->SetClipRegion( aOutputArea );
+ }
+
+ const USHORT nListInitSize = aEntries.Count() > USHRT_MAX ?
+ USHRT_MAX : (USHORT)aEntries.Count();
+ List* pNewZOrderList = new List( nListInitSize );
+ List* pPaintedEntries = new List( nListInitSize );
+
+ ULONG nPos = 0;
+ while( nCount )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
+ const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
+ if( rRect.IsOver( rBoundRect ) )
+ {
+ PaintEntry( pEntry, rBoundRect.TopLeft(), pView, TRUE );
+ // Eintraege, die neu gezeichnet werden, auf Top setzen
+ pPaintedEntries->Insert( pEntry, LIST_APPEND );
+ }
+ else
+ pNewZOrderList->Insert( pEntry, LIST_APPEND );
+
+ nCount--;
+ nPos++;
+ }
+ delete pZOrderList;
+ pZOrderList = pNewZOrderList;
+ nCount = pPaintedEntries->Count();
+ if( nCount )
+ {
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ pZOrderList->Insert( pPaintedEntries->GetObject(nCur), LIST_APPEND);
+ }
+ delete pPaintedEntries;
+
+ if( bResetClipRegion )
+ pView->SetClipRegion();
+}
+
+void SvxIconChoiceCtrl_Impl::RepaintEntries( USHORT nEntryFlagsMask )
+{
+ const ULONG nCount = pZOrderList->Count();
+ if( !nCount )
+ return;
+
+ BOOL bResetClipRegion = FALSE;
+ Rectangle aOutRect( GetOutputRect() );
+ if( !pView->IsClipRegion() )
+ {
+ bResetClipRegion = TRUE;
+ pView->SetClipRegion( aOutRect );
+ }
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
+ if( pEntry->GetFlags() & nEntryFlagsMask )
+ {
+ const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
+ if( aOutRect.IsOver( rBoundRect ) )
+ PaintEntry( pEntry, rBoundRect.TopLeft() );
+ }
+ }
+ if( bResetClipRegion )
+ pView->SetClipRegion();
+}
+
+
+void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
+{
+ aScrBarBox.SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) );
+ Size aSize( pView->GetOutputSizePixel() );
+ aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1));
+}
+
+IcnViewFieldType SvxIconChoiceCtrl_Impl::GetItem( SvxIconChoiceCtrlEntry* pEntry,
+ const Point& rAbsPos )
+{
+ Rectangle aRect( CalcTextRect( pEntry ) );
+ if( aRect.IsInside( rAbsPos ) )
+ return IcnViewFieldTypeText;
+
+ aRect = CalcBmpRect( pEntry );
+ if( aRect.IsInside( rAbsPos ) )
+ return IcnViewFieldTypeImage;
+
+ return IcnViewFieldTypeDontknow;
+}
+
+BOOL SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt)
+{
+ BOOL bHandled = TRUE;
+ bHighlightFramePressed = FALSE;
+ StopEditTimer();
+ BOOL bGotFocus = (BOOL)(!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS));
+ if( !(nWinBits & WB_NOPOINTERFOCUS) )
+ pView->GrabFocus();
+
+ Point aDocPos( rMEvt.GetPosPixel() );
+ if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
+ return FALSE;
+ ToDocPos( aDocPos );
+ SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, TRUE );
+ if( pEntry )
+ MakeEntryVisible( pEntry, FALSE );
+
+ if( rMEvt.IsShift() && eSelectionMode != SINGLE_SELECTION )
+ {
+ if( pEntry )
+ SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift(), TRUE);
+ return TRUE;
+ }
+
+ if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // Tastaturselektion?
+ {
+ DBG_ASSERT(eSelectionMode != SINGLE_SELECTION,"Invalid selection mode");
+ if( rMEvt.IsMod1() )
+ nFlags |= F_ADD_MODE;
+
+ if( rMEvt.IsShift() )
+ {
+ Rectangle aRect( GetEntryBoundRect( pAnchor ));
+ if( pEntry )
+ aRect.Union( GetEntryBoundRect( pEntry ) );
+ else
+ {
+ Rectangle aTempRect( aDocPos, Size(1,1));
+ aRect.Union( aTempRect );
+ }
+ aCurSelectionRect = aRect;
+ SelectRect( aRect, (nFlags & F_ADD_MODE)!=0, &aSelectedRectList );
+ }
+ else if( rMEvt.IsMod1() )
+ {
+ AddSelectedRect( aCurSelectionRect );
+ pAnchor = 0;
+ aCurSelectionRect.SetPos( aDocPos );
+ }
+
+ if( !pEntry && !(nWinBits & WB_NODRAGSELECTION))
+ pView->StartTracking( STARTTRACK_SCROLLREPEAT );
+ return TRUE;
+ }
+ else
+ {
+ if( !pEntry )
+ {
+ if( eSelectionMode == MULTIPLE_SELECTION )
+ {
+ if( !rMEvt.IsMod1() ) // Ctrl
+ {
+ if( !bGotFocus )
+ {
+ SetNoSelection();
+ ClearSelectedRectList();
+ }
+ }
+ else
+ nFlags |= F_ADD_MODE;
+ aCurSelectionRect.SetPos( aDocPos );
+ pView->StartTracking( STARTTRACK_SCROLLREPEAT );
+ }
+ else
+ bHandled = FALSE;
+ return bHandled;
+ }
+ }
+ BOOL bSelected = pEntry->IsSelected();
+ BOOL bEditingEnabled = IsEntryEditingEnabled();
+
+ if( rMEvt.GetClicks() == 2 )
+ {
+ DeselectAllBut( pEntry );
+ SelectEntry( pEntry, TRUE, TRUE, FALSE, TRUE );
+ pHdlEntry = pEntry;
+ pView->ClickIcon();
+ }
+ else
+ {
+ // Inplace-Editing ?
+ if( rMEvt.IsMod2() ) // Alt?
+ {
+ if( bEntryEditingEnabled && pEntry &&
+ pEntry->IsSelected())
+ {
+ if( pView->EditingEntry( pEntry ))
+ EditEntry( pEntry );
+ }
+ }
+ else if( eSelectionMode == SINGLE_SELECTION )
+ {
+ DeselectAllBut( pEntry );
+ SetCursor( pEntry );
+ if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
+ rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
+ {
+ nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
+ }
+ }
+ else if( eSelectionMode == NO_SELECTION )
+ {
+ if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAME) )
+ {
+ pCurHighlightFrame = 0; // Neues painten des Frames erzwingen
+ bHighlightFramePressed = TRUE;
+ SetEntryHighlightFrame( pEntry, TRUE );
+ }
+ }
+ else
+ {
+ if( !rMEvt.GetModifier() && rMEvt.IsLeft() )
+ {
+ if( !bSelected )
+ {
+ DeselectAllBut( pEntry, TRUE /* Synchron painten */ );
+ SetCursor( pEntry );
+ SelectEntry( pEntry, TRUE, TRUE, FALSE, TRUE );
+ }
+ else
+ {
+ // erst im Up deselektieren, falls Move per D&D!
+ nFlags |= F_DOWN_DESELECT;
+ if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
+ rMEvt.IsLeft())
+ {
+ nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
+ }
+ }
+ }
+ else if( rMEvt.IsMod1() )
+ nFlags |= F_DOWN_CTRL;
+ }
+ }
+ return bHandled;
+}
+
+BOOL SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ BOOL bHandled = FALSE;
+ if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
+ {
+ nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
+ bHandled = TRUE;
+ }
+
+ Point aDocPos( rMEvt.GetPosPixel() );
+ ToDocPos( aDocPos );
+ SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos );
+ if( pDocEntry )
+ {
+ if( nFlags & F_DOWN_CTRL )
+ {
+ // Ctrl & MultiSelection
+ ToggleSelection( pDocEntry );
+ SetCursor( pDocEntry );
+ bHandled = TRUE;
+ }
+ else if( nFlags & F_DOWN_DESELECT )
+ {
+ DeselectAllBut( pDocEntry );
+ SetCursor( pDocEntry );
+ SelectEntry( pDocEntry, TRUE, TRUE, FALSE, TRUE );
+ bHandled = TRUE;
+ }
+ }
+
+ nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
+ if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
+ {
+ bHandled = TRUE;
+ StartEditTimer();
+ nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
+ }
+
+ if((nWinBits & WB_HIGHLIGHTFRAME) && bHighlightFramePressed && pCurHighlightFrame)
+ {
+ bHandled = TRUE;
+ SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
+ pCurHighlightFrame = 0; // Neues painten des Frames erzwingen
+ bHighlightFramePressed = FALSE;
+ SetEntryHighlightFrame( pEntry, TRUE );
+#if 0
+ CallSelectHandler( pCurHighlightFrame );
+#else
+ pHdlEntry = pCurHighlightFrame;
+ pView->ClickIcon();
+
+ // set focus on Icon
+ SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
+ SetCursor_Impl( pOldCursor, pHdlEntry, FALSE, FALSE, TRUE );
+#endif
+ pHdlEntry = 0;
+ }
+ return bHandled;
+}
+
+BOOL SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt )
+{
+ const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) );
+
+ if( pView->IsTracking() )
+ return FALSE;
+ else if( nWinBits & WB_HIGHLIGHTFRAME )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, TRUE );
+ SetEntryHighlightFrame( pEntry );
+ }
+ else
+ return FALSE;
+ return TRUE;
+}
+
+void SvxIconChoiceCtrl_Impl::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ // Das Rechteck darf nicht "justified" sein, da seine
+ // TopLeft-Position u.U. zur Berechnung eines Ankers
+ // benutzt wird.
+ AddSelectedRect( aCurSelectionRect );
+ pView->HideTracking();
+ nFlags &= ~(F_ADD_MODE);
+ if( rTEvt.IsTrackingCanceled() )
+ SetNoSelection();
+ }
+ else
+ {
+ Point aPosPixel = rTEvt.GetMouseEvent().GetPosPixel();
+ Point aDocPos( aPosPixel );
+ ToDocPos( aDocPos );
+
+ long nScrollDX, nScrollDY;
+
+ CalcScrollOffsets( aPosPixel, nScrollDX, nScrollDY, FALSE );
+ if( nScrollDX || nScrollDY )
+ {
+ pView->HideTracking();
+ pView->Scroll( nScrollDX, nScrollDY );
+ }
+ Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos );
+ if( aRect != aCurSelectionRect )
+ {
+ pView->HideTracking();
+ BOOL bAdd = (nFlags & F_ADD_MODE) ? TRUE : FALSE;
+ SelectRect( aRect, bAdd, &aSelectedRectList );
+ }
+ pView->ShowTracking( aRect, SHOWTRACK_SMALL | SHOWTRACK_CLIP );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor,
+ SvxIconChoiceCtrlEntry* pNewCursor, BOOL bMod1, BOOL bShift, BOOL bPaintSync )
+{
+ if( pNewCursor )
+ {
+ SvxIconChoiceCtrlEntry* pFilterEntry = 0;
+ BOOL bDeselectAll = FALSE;
+ if( eSelectionMode != SINGLE_SELECTION )
+ {
+ if( !bMod1 && !bShift )
+ bDeselectAll = TRUE;
+ else if( bShift && !bMod1 && !pAnchor )
+ {
+ bDeselectAll = TRUE;
+ pFilterEntry = pOldCursor;
+ }
+ }
+ if( bDeselectAll )
+ DeselectAllBut( pFilterEntry, bPaintSync );
+ ShowCursor( FALSE );
+ MakeEntryVisible( pNewCursor );
+ SetCursor( pNewCursor );
+ if( bMod1 && !bShift )
+ {
+ if( pAnchor )
+ {
+ AddSelectedRect( pAnchor, pOldCursor );
+ pAnchor = 0;
+ }
+ }
+ else if( bShift )
+ {
+ if( !pAnchor )
+ pAnchor = pOldCursor;
+ if ( nWinBits & WB_ALIGN_LEFT )
+ SelectRange( pAnchor, pNewCursor, (nFlags & F_ADD_MODE)!=0 );
+ else
+ SelectRect(pAnchor,pNewCursor,(nFlags & F_ADD_MODE)!=0,&aSelectedRectList);
+ }
+ else
+ {
+ SelectEntry( pCursor, TRUE, TRUE, FALSE, bPaintSync );
+ aCurSelectionRect = GetEntryBoundRect( pCursor );
+ }
+ }
+}
+
+BOOL SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
+{
+ StopEditTimer();
+
+ BOOL bMod2 = rKEvt.GetKeyCode().IsMod2();
+ sal_Unicode cChar = rKEvt.GetCharCode();
+ ULONG nPos = (ULONG)-1;
+ if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) )
+ {
+ // shortcut is clicked
+ SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
+ SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
+ if ( pNewCursor != pOldCursor )
+ SetCursor_Impl( pOldCursor, pNewCursor, FALSE, FALSE, FALSE );
+ return TRUE;
+ }
+
+ if ( bMod2 )
+ // no actions with <ALT>
+ return FALSE;
+
+ BOOL bKeyUsed = TRUE;
+ BOOL bMod1 = rKEvt.GetKeyCode().IsMod1();
+ BOOL bShift = rKEvt.GetKeyCode().IsShift();
+
+ if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION)
+ {
+ bShift = FALSE;
+ bMod1 = FALSE;
+ }
+
+ if( bMod1 )
+ nFlags |= F_ADD_MODE;
+ BOOL bDeselectAll = FALSE;
+ if( eSelectionMode != SINGLE_SELECTION )
+ {
+ if( !bMod1 && !bShift )
+ bDeselectAll = TRUE;
+ if( bShift && !bMod1 && !pAnchor )
+ bDeselectAll = TRUE;
+ }
+
+ SvxIconChoiceCtrlEntry* pNewCursor;
+ SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
+
+ USHORT nCode = rKEvt.GetKeyCode().GetCode();
+ switch( nCode )
+ {
+ case KEY_UP:
+ case KEY_PAGEUP:
+ if( pCursor )
+ {
+ MakeEntryVisible( pCursor );
+ if( nCode == KEY_UP )
+ pNewCursor = pImpCursor->GoUpDown(pCursor,FALSE);
+ else
+ pNewCursor = pImpCursor->GoPageUpDown(pCursor,FALSE);
+ SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
+ if( !pNewCursor )
+ {
+ Rectangle aRect( GetEntryBoundRect( pCursor ) );
+ if( aRect.Top())
+ {
+ aRect.Bottom() -= aRect.Top();
+ aRect.Top() = 0;
+ MakeVisible( aRect );
+ }
+ }
+
+ if ( bChooseWithCursor && pNewCursor != NULL )
+ {
+ pHdlEntry = pNewCursor;//GetCurEntry();
+ pCurHighlightFrame = pHdlEntry;
+ pView->ClickIcon();
+ pCurHighlightFrame = NULL;
+ }
+ }
+ break;
+
+ case KEY_DOWN:
+ case KEY_PAGEDOWN:
+ if( pCursor )
+ {
+ if( nCode == KEY_DOWN )
+ pNewCursor=pImpCursor->GoUpDown( pCursor,TRUE );
+ else
+ pNewCursor=pImpCursor->GoPageUpDown( pCursor,TRUE );
+ SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
+
+ if ( bChooseWithCursor && pNewCursor != NULL)
+ {
+ pHdlEntry = pNewCursor;//GetCurEntry();
+ pCurHighlightFrame = pHdlEntry;
+ pView->ClickIcon();
+ pCurHighlightFrame = NULL;
+ }
+ }
+ break;
+
+ case KEY_RIGHT:
+ if( pCursor )
+ {
+ pNewCursor=pImpCursor->GoLeftRight(pCursor,TRUE );
+ SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
+ }
+ break;
+
+ case KEY_LEFT:
+ if( pCursor )
+ {
+ MakeEntryVisible( pCursor );
+ pNewCursor = pImpCursor->GoLeftRight(pCursor,FALSE );
+ SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
+ if( !pNewCursor )
+ {
+ Rectangle aRect( GetEntryBoundRect(pCursor));
+ if( aRect.Left() )
+ {
+ aRect.Right() -= aRect.Left();
+ aRect.Left() = 0;
+ MakeVisible( aRect );
+ }
+ }
+ }
+ break;
+
+// wird vom VCL-Tracking gesteuert
+#if 0
+ case KEY_ESCAPE:
+ if( pView->IsTracking() )
+ {
+ HideSelectionRect();
+ //SelectAll( FALSE );
+ SetNoSelection();
+ ClearSelectedRectList();
+ nFlags &= ~F_TRACKING;
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+#endif
+
+
+ case KEY_F2:
+ if( !bMod1 && !bShift )
+ EditTimeoutHdl( 0 );
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_F8:
+ if( rKEvt.GetKeyCode().IsShift() )
+ {
+ if( nFlags & F_ADD_MODE )
+ nFlags &= (~F_ADD_MODE);
+ else
+ nFlags |= F_ADD_MODE;
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_SPACE:
+ if( pCursor && eSelectionMode != SINGLE_SELECTION )
+ {
+ if( !bMod1 )
+ {
+ //SelectAll( FALSE );
+ SetNoSelection();
+ ClearSelectedRectList();
+
+ // click Icon with spacebar
+ SetEntryHighlightFrame( GetCurEntry(), TRUE );
+ pView->ClickIcon();
+ pHdlEntry = pCurHighlightFrame;
+ pCurHighlightFrame=0;
+ }
+ else
+ ToggleSelection( pCursor );
+ }
+ break;
+
+#ifdef DBG_UTIL
+ case KEY_F10:
+ if( rKEvt.GetKeyCode().IsShift() )
+ {
+ if( pCursor )
+ pView->SetEntryTextMode( IcnShowTextFull, pCursor );
+ }
+ if( rKEvt.GetKeyCode().IsMod1() )
+ {
+ if( pCursor )
+ pView->SetEntryTextMode( IcnShowTextShort, pCursor );
+ }
+ break;
+#endif
+
+ case KEY_ADD:
+ case KEY_DIVIDE :
+ case KEY_A:
+ if( bMod1 && (eSelectionMode != SINGLE_SELECTION))
+ SelectAll( TRUE );
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_SUBTRACT:
+ case KEY_COMMA :
+ if( bMod1 )
+ SetNoSelection();
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_RETURN:
+ if( bMod1 )
+ {
+ if( pCursor && bEntryEditingEnabled )
+ /*pView->*/EditEntry( pCursor );
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_END:
+ if( pCursor )
+ {
+ pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( aEntries.Count() - 1 );
+ SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
+ }
+ break;
+
+ case KEY_HOME:
+ if( pCursor )
+ {
+ pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
+ SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
+ }
+ break;
+
+ default:
+ bKeyUsed = FALSE;
+
+ }
+ return bKeyUsed;
+}
+
+// Berechnet TopLeft der Scrollbars (nicht ihre Groessen!)
+void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
+{
+ // hor scrollbar
+ Point aPos( 0, nRealHeight );
+ aPos.Y() -= nHorSBarHeight;
+
+ if( aHorSBar.GetPosPixel() != aPos )
+ aHorSBar.SetPosPixel( aPos );
+
+ // ver scrollbar
+ aPos.X() = nRealWidth; aPos.Y() = 0;
+ aPos.X() -= nVerSBarWidth;
+ aPos.X()++;
+ aPos.Y()--;
+
+ if( aVerSBar.GetPosPixel() != aPos )
+ aVerSBar.SetPosPixel( aPos );
+}
+
+void SvxIconChoiceCtrl_Impl::AdjustScrollBars( BOOL )
+{
+ Rectangle aOldOutRect( GetOutputRect() );
+ long nVirtHeight = aVirtOutputSize.Height();
+ long nVirtWidth = aVirtOutputSize.Width();
+
+ Size aOSize( pView->Control::GetOutputSizePixel() );
+ long nRealHeight = aOSize.Height();
+ long nRealWidth = aOSize.Width();
+
+ PositionScrollBars( nRealWidth, nRealHeight );
+
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin() );
+
+ long nVisibleWidth;
+ if( nRealWidth > nVirtWidth )
+ nVisibleWidth = nVirtWidth + aOrigin.X();
+ else
+ nVisibleWidth = nRealWidth;
+
+ long nVisibleHeight;
+ if( nRealHeight > nVirtHeight )
+ nVisibleHeight = nVirtHeight + aOrigin.Y();
+ else
+ nVisibleHeight = nRealHeight;
+
+ sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
+ sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
+ sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0;
+ sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0;
+
+ USHORT nResult = 0;
+ if( nVirtHeight )
+ {
+ // activate ver scrollbar ?
+ if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
+ {
+ nResult = 0x0001;
+ nRealWidth -= nVerSBarWidth;
+
+ if( nRealWidth > nVirtWidth )
+ nVisibleWidth = nVirtWidth + aOrigin.X();
+ else
+ nVisibleWidth = nRealWidth;
+
+ nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
+ }
+ // activate hor scrollbar ?
+ if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
+ {
+ nResult |= 0x0002;
+ nRealHeight -= nHorSBarHeight;
+
+ if( nRealHeight > nVirtHeight )
+ nVisibleHeight = nVirtHeight + aOrigin.Y();
+ else
+ nVisibleHeight = nRealHeight;
+
+ // brauchen wir jetzt doch eine senkrechte Scrollbar ?
+ if( !(nResult & 0x0001) && // nur wenn nicht schon da
+ ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
+ {
+ nResult = 3; // beide sind an
+ nRealWidth -= nVerSBarWidth;
+
+ if( nRealWidth > nVirtWidth )
+ nVisibleWidth = nVirtWidth + aOrigin.X();
+ else
+ nVisibleWidth = nRealWidth;
+
+ nFlags |= F_VER_SBARSIZE_WITH_HBAR;
+ }
+ }
+ }
+
+ // size ver scrollbar
+ long nThumb = aVerSBar.GetThumbPos();
+ Size aSize( nVerSBarWidth, nRealHeight );
+ aSize.Height() += 2;
+ if( aSize != aVerSBar.GetSizePixel() )
+ aVerSBar.SetSizePixel( aSize );
+ aVerSBar.SetVisibleSize( nVisibleHeight );
+ aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight ));
+
+ if( nResult & 0x0001 )
+ {
+ aVerSBar.SetThumbPos( nThumb );
+ aVerSBar.Show();
+ }
+ else
+ {
+ aVerSBar.SetThumbPos( 0 );
+ aVerSBar.Hide();
+ }
+
+ // size hor scrollbar
+ nThumb = aHorSBar.GetThumbPos();
+ aSize.Width() = nRealWidth;
+ aSize.Height() = nHorSBarHeight;
+ aSize.Width()++;
+ if( nResult & 0x0001 ) // vertikale Scrollbar ?
+ {
+ aSize.Width()++;
+ nRealWidth++;
+ }
+ if( aSize != aHorSBar.GetSizePixel() )
+ aHorSBar.SetSizePixel( aSize );
+ aHorSBar.SetVisibleSize( nVisibleWidth );
+ aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
+ if( nResult & 0x0002 )
+ {
+ aHorSBar.SetThumbPos( nThumb );
+ aHorSBar.Show();
+ }
+ else
+ {
+ aHorSBar.SetThumbPos( 0 );
+ aHorSBar.Hide();
+ }
+
+ aOutputSize.Width() = nRealWidth;
+ if( nResult & 0x0002 ) // hor scrollbar ?
+ nRealHeight++; // weil unterer Rand geclippt wird
+ aOutputSize.Height() = nRealHeight;
+
+ Rectangle aNewOutRect( GetOutputRect() );
+ if( aNewOutRect != aOldOutRect && pView->HasBackground() )
+ {
+ Wallpaper aPaper( pView->GetBackground() );
+ aPaper.SetRect( aNewOutRect );
+ pView->SetBackground( aPaper );
+ }
+
+ if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
+ aScrBarBox.Show();
+ else
+ aScrBarBox.Hide();
+}
+
+void SvxIconChoiceCtrl_Impl::Resize()
+{
+ StopEditTimer();
+ InitScrollBarBox();
+ aOutputSize = pView->GetOutputSizePixel();
+ pImpCursor->Clear();
+ pGridMap->OutputSizeChanged();
+
+ const Size& rSize = pView->Control::GetOutputSizePixel();
+ PositionScrollBars( rSize.Width(), rSize.Height() );
+ // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete
+ // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass
+ // die ScrollBars aufblitzen
+ // Wenn schon ein Event unterwegs ist, dann braucht kein neues verschickt werden,
+ // zumindest, solange es nur einen EventTypen gibt
+ if ( ! nUserEventAdjustScrBars )
+ nUserEventAdjustScrBars =
+ Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
+ EVENTID_ADJUST_SCROLLBARS);
+
+ if( pView->HasBackground() && !pView->GetBackground().IsScrollable() )
+ {
+ Rectangle aRect( GetOutputRect());
+ Wallpaper aPaper( pView->GetBackground() );
+ aPaper.SetRect( aRect );
+ pView->SetBackground( aPaper );
+ }
+ VisRectChanged();
+}
+
+BOOL SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
+{
+ if( !pZOrderList || !aHorSBar.IsVisible() )
+ return FALSE;
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin() );
+ if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
+ {
+ long nWidth = aOutputSize.Width();
+ const ULONG nCount = pZOrderList->Count();
+ long nMostRight = 0;
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
+ long nRight = GetEntryBoundRect(pEntry).Right();
+ if( nRight > nWidth )
+ return FALSE;
+ if( nRight > nMostRight )
+ nMostRight = nRight;
+ }
+ aHorSBar.Hide();
+ aOutputSize.Height() += nHorSBarHeight;
+ aVirtOutputSize.Width() = nMostRight;
+ aHorSBar.SetThumbPos( 0 );
+ Range aRange;
+ aRange.Max() = nMostRight - 1;
+ aHorSBar.SetRange( aRange );
+ if( aVerSBar.IsVisible() )
+ {
+ Size aSize( aVerSBar.GetSizePixel());
+ aSize.Height() += nHorSBarHeight;
+ aVerSBar.SetSizePixel( aSize );
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
+{
+ if( !pZOrderList || !aVerSBar.IsVisible() )
+ return FALSE;
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin() );
+ if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
+ {
+ long nDeepest = 0;
+ long nHeight = aOutputSize.Height();
+ const ULONG nCount = pZOrderList->Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
+ long nBottom = GetEntryBoundRect(pEntry).Bottom();
+ if( nBottom > nHeight )
+ return FALSE;
+ if( nBottom > nDeepest )
+ nDeepest = nBottom;
+ }
+ aVerSBar.Hide();
+ aOutputSize.Width() += nVerSBarWidth;
+ aVirtOutputSize.Height() = nDeepest;
+ aVerSBar.SetThumbPos( 0 );
+ Range aRange;
+ aRange.Max() = nDeepest - 1;
+ aVerSBar.SetRange( aRange );
+ if( aHorSBar.IsVisible() )
+ {
+ Size aSize( aHorSBar.GetSizePixel());
+ aSize.Width() += nVerSBarWidth;
+ aHorSBar.SetSizePixel( aSize );
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+// blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden
+void SvxIconChoiceCtrl_Impl::CheckScrollBars()
+{
+ CheckVerScrollBar();
+ if( CheckHorScrollBar() )
+ CheckVerScrollBar();
+ if( aVerSBar.IsVisible() && aHorSBar.IsVisible() )
+ aScrBarBox.Show();
+ else
+ aScrBarBox.Hide();
+}
+
+
+void SvxIconChoiceCtrl_Impl::GetFocus()
+{
+ RepaintEntries( ICNVIEW_FLAG_SELECTED );
+ if( pCursor )
+ {
+ pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
+ ShowCursor( TRUE );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::LoseFocus()
+{
+ StopEditTimer();
+ if( pCursor )
+ pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
+ ShowCursor( FALSE );
+
+// HideFocus ();
+// pView->Invalidate ( aFocus.aRect );
+
+ RepaintEntries( ICNVIEW_FLAG_SELECTED );
+}
+
+void SvxIconChoiceCtrl_Impl::SetUpdateMode( BOOL bUpdate )
+{
+ if( bUpdate != bUpdateMode )
+ {
+ bUpdateMode = bUpdate;
+ if( bUpdate )
+ {
+ AdjustScrollBars();
+ pImpCursor->Clear();
+ pGridMap->Clear();
+ pView->Invalidate(INVALIDATE_NOCHILDREN);
+ }
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, BOOL bIsBackgroundPainted )
+{
+ Point aPos( GetEntryPos( pEntry ) );
+ PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted );
+}
+
+// Prios der Emphasis: bDropTarget => bCursored => bSelected
+void SvxIconChoiceCtrl_Impl::PaintEmphasis(
+ const Rectangle& rTextRect, const Rectangle& rImageRect,
+ BOOL bSelected, BOOL bDropTarget, BOOL bCursored, OutputDevice* pOut,
+ BOOL bIsBackgroundPainted )
+{
+ static Color aTransparent( COL_TRANSPARENT );
+
+ if( !pOut )
+ pOut = pView;
+
+#ifdef OV_CHECK_EMPH_RECTS
+ {
+ Color aXOld( pOut->GetFillColor() );
+ pOut->SetFillColor( Color( COL_GREEN ));
+ pOut->DrawRect( rTextRect );
+ pOut->DrawRect( rImageRect );
+ pOut->SetFillColor( aXOld );
+ }
+#endif
+
+ const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
+ Color aOldFillColor( pOut->GetFillColor() );
+
+ BOOL bSolidTextRect = FALSE;
+ BOOL bSolidImageRect = FALSE;
+
+ if( bDropTarget && ( eSelectionMode != NO_SELECTION ) )
+ {
+ pOut->SetFillColor( rSettings.GetHighlightColor() );
+ bSolidTextRect = TRUE;
+ bSolidImageRect = TRUE;
+ }
+ else
+ {
+ if ( !bSelected || bCursored )
+ {
+ if( !pView->HasFontFillColor() )
+ pOut->SetFillColor( pOut->GetBackground().GetColor() );
+ else
+ {
+ const Color& rFillColor = pView->GetFont().GetFillColor();
+ pOut->SetFillColor( rFillColor );
+ if( rFillColor != aTransparent )
+ bSolidTextRect = TRUE;
+ }
+ }
+ }
+
+ // Textrechteck zeichnen
+ if( !bSolidTextRect )
+ {
+ if( !bIsBackgroundPainted )
+ pOut->Erase( rTextRect );
+ }
+ else
+ {
+ Color aOldLineColor;
+ if( bCursored )
+ {
+ aOldLineColor = pOut->GetLineColor();
+ pOut->SetLineColor( Color( COL_GRAY ) );
+ }
+ pOut->DrawRect( rTextRect );
+ if( bCursored )
+ pOut->SetLineColor( aOldLineColor );
+ }
+
+ // Bildrechteck zeichnen
+ if( !bSolidImageRect )
+ {
+ if( !bIsBackgroundPainted )
+ pOut->Erase( rImageRect );
+ }
+// die Emphasis des Images muss von der abgeleiteten Klasse gezeichnet werden
+// (in der virtuellen Funktion DrawEntryImage)
+// else
+// pOut->DrawRect( rImageRect );
+
+ pOut->SetFillColor( aOldFillColor );
+}
+
+
+void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect,
+ IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, USHORT nPaintFlags,
+ OutputDevice* pOut, const String* pStr, ::vcl::ControlLayoutData* _pLayoutData )
+{
+ if( eItem == IcnViewFieldTypeText )
+ {
+ String aText;
+ if( !pStr )
+ aText = pView->GetEntryText( pEntry, FALSE );
+ else
+ aText = *pStr;
+
+ if ( _pLayoutData )
+ {
+ pOut->DrawText( rRect, aText, nCurTextDrawFlags,
+ &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText );
+ }
+ else
+ {
+ Color aOldFontColor = pOut->GetTextColor();
+ if ( pView->AutoFontColor() )
+ {
+ Color aBkgColor( pOut->GetBackground().GetColor() );
+ Color aFontColor;
+ USHORT nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
+ if ( nColor > 127 )
+ aFontColor.SetColor ( COL_BLACK );
+ else
+ aFontColor.SetColor( COL_WHITE );
+ pOut->SetTextColor( aFontColor );
+ }
+
+ pOut->DrawText( rRect, aText, nCurTextDrawFlags );
+
+ if ( pView->AutoFontColor() )
+ pOut->SetTextColor( aOldFontColor );
+
+ if( pEntry->IsFocused() )
+ {
+ Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
+ /*pView->*/ShowFocus( aRect );
+ DrawFocusRect( pOut );
+ }
+ }
+ }
+ else
+ {
+ Point aPos( rRect.TopLeft() );
+ if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
+ aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2;
+ if( nPaintFlags & PAINTFLAG_VER_CENTERED )
+ aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2;
+ pView->DrawEntryImage( pEntry, aPos, *pOut );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry )
+{
+#ifdef OV_NO_VIRT_OUTDEV
+ PaintEntry( pEntry );
+#else
+ if( !pEntryPaintDev )
+ {
+ pEntryPaintDev = new VirtualDevice( *pView );
+ pEntryPaintDev->SetFont( pView->GetFont() );
+ pEntryPaintDev->SetLineColor();
+ //pEntryPaintDev->SetBackground( pView->GetBackground() );
+ }
+ const Rectangle& rRect = GetEntryBoundRect( pEntry );
+ Rectangle aOutRect( GetOutputRect() );
+ if( !rRect.IsOver( aOutRect ) )
+ return;
+ Wallpaper aPaper( pView->GetBackground() );
+ Rectangle aRect( aPaper.GetRect() );
+
+ // Rechteck verschieben, so dass das Boundrect des Entries im
+ // VirtOut-Dev bei 0,0 liegt.
+ aRect.Move( -rRect.Left(), -rRect.Top() );
+ aPaper.SetRect( aRect );
+ pEntryPaintDev->SetBackground( aPaper );
+ pEntryPaintDev->SetFont( pView->GetFont() );
+ Rectangle aPix ( pEntryPaintDev->LogicToPixel(aRect) );
+
+
+ Size aSize( rRect.GetSize() );
+ pEntryPaintDev->SetOutputSizePixel( aSize );
+ pEntryPaintDev->DrawOutDev(
+ Point(), aSize, rRect.TopLeft(), aSize, *pView );
+
+ PaintEntry( pEntry, Point(), pEntryPaintDev );
+
+ pView->DrawOutDev(
+ rRect.TopLeft(),
+ aSize,
+ Point(),
+ aSize,
+ *pEntryPaintDev );
+#endif
+}
+
+
+void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
+ OutputDevice* pOut, BOOL bIsBackgroundPainted )
+{
+ if( !pOut )
+ pOut = pView;
+
+ BOOL bSelected = FALSE;
+
+ if( eSelectionMode != NO_SELECTION )
+ bSelected = pEntry->IsSelected();
+
+ BOOL bCursored = pEntry->IsCursored();
+ BOOL bDropTarget = pEntry->IsDropTarget();
+ BOOL bNoEmphasis = pEntry->IsBlockingEmphasis();
+
+ Font aTempFont( pOut->GetFont() );
+
+ // AutoFontColor
+ /*
+ if ( pView->AutoFontColor() )
+ {
+ aTempFont.SetColor ( aFontColor );
+ }
+ */
+
+ String aEntryText( pView->GetEntryText( pEntry, FALSE ) );
+ Rectangle aTextRect( CalcTextRect(pEntry,&rPos,FALSE,&aEntryText));
+ Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) );
+
+ sal_Bool bShowSelection =
+ ( ( ( bSelected && !bCursored )
+ || bDropTarget
+ )
+ && !bNoEmphasis
+ && ( eSelectionMode != NO_SELECTION )
+ );
+ sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus();
+
+ if ( bShowSelection )
+ {
+ const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
+ Font aNewFont( aTempFont );
+
+ // bei hart attributierter Font-Fuellcolor muessen wir diese
+ // hart auf die Highlight-Color setzen
+ if( pView->HasFontFillColor() )
+ {
+ if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() )
+ aNewFont.SetFillColor( rSettings.GetHighlightColor() );
+ else
+ aNewFont.SetFillColor( rSettings.GetDeactiveColor() );
+ }
+
+ Color aWinCol = rSettings.GetWindowTextColor();
+ if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() )
+ aNewFont.SetColor( rSettings.GetWindowTextColor() );
+ else
+ aNewFont.SetColor( rSettings.GetHighlightTextColor() );
+
+ pOut->SetFont( aNewFont );
+
+ pOut->SetFillColor( pOut->GetBackground().GetColor() );
+ pOut->DrawRect( CalcFocusRect( pEntry ) );
+ pOut->SetFillColor( );
+ }
+
+ BOOL bResetClipRegion = FALSE;
+ if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) )
+ {
+ Rectangle aOutputArea( GetOutputRect() );
+ if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) )
+ {
+ pView->SetClipRegion( aOutputArea );
+ bResetClipRegion = TRUE;
+ }
+ }
+
+#ifdef OV_DRAWBOUNDRECT
+ {
+ Color aXOldColor = pOut->GetLineColor();
+ pOut->SetLineColor( Color( COL_LIGHTRED ) );
+ Rectangle aXRect( pEntry->aRect );
+ aXRect.SetPos( rPos );
+ pOut->DrawRect( aXRect );
+ pOut->SetLineColor( aXOldColor );
+ }
+#endif
+
+ sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) );
+ USHORT nBmpPaintFlags = PAINTFLAG_VER_CENTERED;
+ if ( bLargeIconMode )
+ nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED;
+ USHORT nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
+
+ if( !bNoEmphasis )
+ PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted);
+
+ if ( bShowSelection )
+ pView->DrawSelectionBackground( CalcFocusRect( pEntry ),
+ bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ );
+
+ PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut );
+
+ PaintItem( aTextRect, IcnViewFieldTypeText, pEntry,
+ nTextPaintFlags, pOut );
+
+ // Highlight-Frame zeichnen
+ if( pEntry == pCurHighlightFrame && !bNoEmphasis )
+ DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), FALSE );
+
+ pOut->SetFont( aTempFont );
+ if( bResetClipRegion )
+ pView->SetClipRegion();
+}
+
+void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
+ BOOL bAdjustAtGrid, BOOL bCheckScrollBars, BOOL bKeepGridMap )
+{
+ ShowCursor( FALSE );
+ Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
+ pView->Invalidate( aBoundRect );
+ ToTop( pEntry );
+ if( !IsAutoArrange() )
+ {
+ BOOL bAdjustVirtSize = FALSE;
+ if( rPos != aBoundRect.TopLeft() )
+ {
+ Point aGridOffs(
+ pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
+ pImpCursor->Clear();
+ if( !bKeepGridMap )
+ pGridMap->Clear();
+ aBoundRect.SetPos( rPos );
+ pEntry->aRect = aBoundRect;
+ pEntry->aGridRect.SetPos( rPos + aGridOffs );
+ bAdjustVirtSize = TRUE;
+ }
+ if( bAdjustAtGrid )
+ {
+ if( bAdjustVirtSize )
+ {
+ // Durch das Ausrichten des (ggf. gerade neu positionierten) Eintrags,
+ // kann er wieder komplett
+ // in den sichtbaren Bereich rutschen, so dass u.U. doch keine Scrollbar
+ // eingeblendet werden muss. Um deshalb ein 'Aufblitzen' der
+ // Scrollbar(s) zu vermeiden, wird zum Aufplustern der virtuellen
+ // Ausgabegroesse bereits das ausgerichtete Boundrect des
+ // Eintrags genommen. Die virtuelle Groesse muss angepasst werden,
+ // da AdjustEntryAtGrid von ihr abhaengt.
+ const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
+ Rectangle aCenterRect( CalcBmpRect( pEntry, 0 ));
+ Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
+ Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize());
+ AdjustVirtSize( aNewBoundRect );
+ bAdjustVirtSize = FALSE;
+ }
+ AdjustEntryAtGrid( pEntry );
+ ToTop( pEntry );
+ }
+ if( bAdjustVirtSize )
+ AdjustVirtSize( pEntry->aRect );
+
+ if( bCheckScrollBars && bUpdateMode )
+ CheckScrollBars();
+
+ pView->Invalidate( pEntry->aRect );
+ pGridMap->OccupyGrids( pEntry );
+ }
+ else
+ {
+ SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos );
+ SetEntryPredecessor( pEntry, pPrev );
+ aAutoArrangeTimer.Start();
+ }
+ ShowCursor( TRUE );
+}
+
+void SvxIconChoiceCtrl_Impl::SetNoSelection()
+{
+ // rekursive Aufrufe ueber SelectEntry abblocken
+ if( !(nFlags & F_CLEARING_SELECTION ))
+ {
+ nFlags |= F_CLEARING_SELECTION;
+ DeselectAllBut( 0, TRUE );
+ nFlags &= ~F_CLEARING_SELECTION;
+ }
+}
+
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, BOOL bHit )
+{
+ CheckBoundingRects();
+ // Z-Order-Liste vom Ende her absuchen
+ ULONG nCount = pZOrderList->Count();
+ while( nCount )
+ {
+ nCount--;
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCount));
+ if( pEntry->aRect.IsInside( rDocPos ) )
+ {
+ if( bHit )
+ {
+ Rectangle aRect = CalcBmpRect( pEntry );
+ aRect.Top() -= 3;
+ aRect.Bottom() += 3;
+ aRect.Left() -= 3;
+ aRect.Right() += 3;
+ if( aRect.IsInside( rDocPos ) )
+ return pEntry;
+ aRect = CalcTextRect( pEntry );
+ if( aRect.IsInside( rDocPos ) )
+ return pEntry;
+ }
+ else
+ return pEntry;
+ }
+ }
+ return 0;
+}
+
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
+{
+ CheckBoundingRects();
+ SvxIconChoiceCtrlEntry* pTarget = 0;
+ const ULONG nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
+ if( nStartPos != LIST_ENTRY_NOTFOUND )
+ {
+ const ULONG nCount = pZOrderList->Count();
+ for( ULONG nCur = nStartPos+1; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
+ if( pEntry->aRect.IsInside( rDocPos ) )
+ {
+ pTarget = pEntry;
+ break;
+ }
+ }
+ }
+ return pTarget;
+}
+
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetPrevEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
+{
+ CheckBoundingRects();
+ SvxIconChoiceCtrlEntry* pTarget = 0;
+ ULONG nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
+ if( nStartPos != LIST_ENTRY_NOTFOUND && nStartPos != 0 )
+ {
+ nStartPos--;
+ do
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nStartPos));
+ if( pEntry->aRect.IsInside( rDocPos ) )
+ {
+ pTarget = pEntry;
+ break;
+ }
+ } while( nStartPos > 0 );
+ }
+ return pTarget;
+}
+
+Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry )
+{
+ return pEntry->aRect.TopLeft();
+}
+
+void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, BOOL bBound )
+{
+ if ( bBound )
+ {
+ const Rectangle& rRect = GetEntryBoundRect( pEntry );
+ MakeVisible( rRect );
+ }
+ else
+ {
+ Rectangle aRect = CalcBmpRect( pEntry );
+ aRect.Union( CalcTextRect( pEntry ) );
+ aRect.Top() += TBOFFS_BOUND;
+ aRect.Bottom() += TBOFFS_BOUND;
+ aRect.Left() += LROFFS_BOUND;
+ aRect.Right() += LROFFS_BOUND;
+ MakeVisible( aRect );
+ }
+}
+
+const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
+{
+ if( !IsBoundingRectValid( pEntry->aRect ))
+ FindBoundingRect( pEntry );
+ return pEntry->aRect;
+}
+
+Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
+{
+ Rectangle aBound = GetEntryBoundRect( pEntry );
+ if( pPos )
+ aBound.SetPos( *pPos );
+ Point aPos( aBound.TopLeft() );
+
+ switch( nWinBits & (VIEWMODE_MASK) )
+ {
+ case WB_ICON:
+ {
+ aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2;
+ return Rectangle( aPos, aImageSize );
+ }
+
+ case WB_SMALLICON:
+ case WB_DETAILS:
+ aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2;
+ //todo: hor. Abstand zum BoundRect?
+ return Rectangle( aPos, aImageSize );
+
+ default:
+ DBG_ERROR("IconView: Viewmode not set");
+ return aBound;
+ }
+}
+
+Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
+ const Point* pEntryPos, BOOL bEdit, const String* pStr )
+{
+ String aEntryText;
+ if( !pStr )
+ aEntryText = pView->GetEntryText( pEntry, bEdit );
+ else
+ aEntryText = *pStr;
+
+ const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
+ Rectangle aBound( GetEntryBoundRect( pEntry ) );
+ if( pEntryPos )
+ aBound.SetPos( *pEntryPos );
+
+ Rectangle aTextRect( aMaxTextRect );
+ if( !bEdit )
+ aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags );
+
+ Size aTextSize( aTextRect.GetSize() );
+
+ Point aPos( aBound.TopLeft() );
+ long nBoundWidth = aBound.GetWidth();
+ long nBoundHeight = aBound.GetHeight();
+
+ switch( nWinBits & (VIEWMODE_MASK) )
+ {
+ case WB_ICON:
+ aPos.Y() += aImageSize.Height();
+ aPos.Y() += VER_DIST_BMP_STRING;
+ // beim Editieren etwas mehr Platz
+ if( bEdit )
+ {
+ // 20% rauf
+ long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) +
+ aImageSize.Width();
+ if( nMinWidth > nBoundWidth )
+ nMinWidth = nBoundWidth;
+
+ if( aTextSize.Width() < nMinWidth )
+ aTextSize.Width() = nMinWidth;
+
+ // beim Editieren ist Ueberlappung nach unten erlaubt
+ Size aOptSize = aMaxTextRect.GetSize();
+ if( aOptSize.Height() > aTextSize.Height() )
+ aTextSize.Height() = aOptSize.Height();
+ }
+ aPos.X() += (nBoundWidth - aTextSize.Width()) / 2;
+ break;
+
+ case WB_SMALLICON:
+ case WB_DETAILS:
+ aPos.X() += aImageSize.Width();
+ aPos.X() += HOR_DIST_BMP_STRING;
+ aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2;
+ break;
+ }
+ return Rectangle( aPos, aTextSize );
+}
+
+
+long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width();
+// nStringWidth += 2*LROFFS_TEXT;
+ long nWidth = 0;
+
+ switch( nWinBits & (VIEWMODE_MASK) )
+ {
+ case WB_ICON:
+ nWidth = Max( nStringWidth, aImageSize.Width() );
+ break;
+
+ case WB_SMALLICON:
+ case WB_DETAILS:
+ nWidth = aImageSize.Width();
+ nWidth += HOR_DIST_BMP_STRING;
+ nWidth += nStringWidth;
+ break;
+ }
+ return nWidth;
+}
+
+long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height();
+ long nHeight = 0;
+
+ switch( nWinBits & (VIEWMODE_MASK) )
+ {
+ case WB_ICON:
+ nHeight = aImageSize.Height();
+ nHeight += VER_DIST_BMP_STRING;
+ nHeight += nStringHeight;
+ break;
+
+ case WB_SMALLICON:
+ case WB_DETAILS:
+ nHeight = Max( aImageSize.Height(), nStringHeight );
+ break;
+ }
+ if( nHeight > nMaxBoundHeight )
+ {
+ ((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight;
+ ((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() );
+ ((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() );
+ }
+ return nHeight;
+}
+
+Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ return Size( CalcBoundingWidth( pEntry ),
+ CalcBoundingHeight( pEntry ) );
+}
+
+void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRects()
+{
+ nMaxBoundHeight = 0;
+ pZOrderList->Clear();
+ ULONG nCount = aEntries.Count();
+ ULONG nCur;
+ SvxIconChoiceCtrlEntry* pEntry;
+
+ if( !IsAutoArrange() || !pHead )
+ {
+ for( nCur = 0; nCur < nCount; nCur++ )
+ {
+ pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ FindBoundingRect( pEntry );
+ pZOrderList->Insert( pEntry, LIST_APPEND );
+ }
+ }
+ else
+ {
+ nCur = 0;
+ pEntry = pHead;
+ while( nCur != nCount )
+ {
+ DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
+ FindBoundingRect( pEntry );
+ pZOrderList->Insert( pEntry, pZOrderList->Count() );
+ pEntry = pEntry->pflink;
+ nCur++;
+ }
+ }
+ bBoundRectsDirty = FALSE;
+ AdjustScrollBars();
+}
+
+void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
+{
+ nMaxBoundHeight = 0;
+ pZOrderList->Clear();
+ ULONG nCur;
+ SvxIconChoiceCtrlEntry* pEntry;
+ const ULONG nCount = aEntries.Count();
+
+ if( !IsAutoArrange() || !pHead )
+ {
+ for( nCur = 0; nCur < nCount; nCur++ )
+ {
+ pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ if( IsBoundingRectValid( pEntry->aRect ))
+ {
+ Size aBoundSize( pEntry->aRect.GetSize() );
+ if( aBoundSize.Height() > nMaxBoundHeight )
+ nMaxBoundHeight = aBoundSize.Height();
+ }
+ else
+ FindBoundingRect( pEntry );
+ pZOrderList->Insert( pEntry, LIST_APPEND );
+ }
+ }
+ else
+ {
+ nCur = 0;
+ pEntry = pHead;
+ while( nCur != nCount )
+ {
+ DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
+ if( IsBoundingRectValid( pEntry->aRect ))
+ {
+ Size aBoundSize( pEntry->aRect.GetSize() );
+ if( aBoundSize.Height() > nMaxBoundHeight )
+ nMaxBoundHeight = aBoundSize.Height();
+ }
+ else
+ FindBoundingRect( pEntry );
+ pZOrderList->Insert( pEntry, LIST_APPEND );
+ pEntry = pEntry->pflink;
+ nCur++;
+ }
+ }
+ AdjustScrollBars();
+}
+
+void SvxIconChoiceCtrl_Impl::UpdateBoundingRects()
+{
+ const ULONG nCount = aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ GetEntryBoundRect( pEntry );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
+{
+ DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect");
+ if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
+ {
+ AdjustVirtSize( pEntry->aRect );
+ return;
+ }
+ Size aSize( CalcBoundingSize( pEntry ) );
+ Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(TRUE)).TopLeft());
+ SetBoundingRect_Impl( pEntry, aPos, aSize );
+}
+
+void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
+ const Size& /*rBoundingSize*/ )
+{
+ Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
+ pEntry->aGridRect = aGridRect;
+ Center( pEntry );
+ AdjustVirtSize( pEntry->aRect );
+ pGridMap->OccupyGrids( pEntry );
+}
+
+
+void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, BOOL bSyncSingleSelection,
+ BOOL bShowFocusAsync )
+{
+ if( pEntry == pCursor )
+ {
+ if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection &&
+ !pCursor->IsSelected() )
+ SelectEntry( pCursor, TRUE, TRUE );
+ return;
+ }
+ ShowCursor( FALSE );
+ SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
+ pCursor = pEntry;
+ if( pOldCursor )
+ {
+ pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
+ if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
+ SelectEntry( pOldCursor, FALSE, TRUE ); // alten Cursor deselektieren
+ }
+ if( pCursor )
+ {
+ ToTop( pCursor );
+ pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
+ if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
+ SelectEntry( pCursor, TRUE, TRUE );
+ if( !bShowFocusAsync )
+ ShowCursor( TRUE );
+ else
+ {
+ if( !nUserEventShowCursor )
+ nUserEventShowCursor =
+ Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
+ EVENTID_SHOW_CURSOR );
+ }
+ }
+}
+
+
+void SvxIconChoiceCtrl_Impl::ShowCursor( BOOL bShow )
+{
+ if( !pCursor || !bShow || !pView->HasFocus() )
+ {
+ pView->HideFocus();
+ return;
+ }
+ Rectangle aRect ( CalcFocusRect( pCursor ) );
+ /*pView->*/ShowFocus( aRect );
+}
+
+
+void SvxIconChoiceCtrl_Impl::HideDDIcon()
+{
+ pView->Update();
+ ImpHideDDIcon();
+ pDDBufDev = pDDDev;
+ pDDDev = 0;
+}
+
+void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
+{
+ if( pDDDev )
+ {
+ Size aSize( pDDDev->GetOutputSizePixel() );
+ // pView restaurieren
+ pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
+ }
+}
+
+
+void SvxIconChoiceCtrl_Impl::ShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
+{
+ pView->Update();
+ if( pRefEntry != pDDRefEntry )
+ {
+ DELETEZ(pDDDev);
+ DELETEZ(pDDBufDev);
+ }
+ BOOL bSelected = pRefEntry->IsSelected();
+ pRefEntry->ClearFlags( ICNVIEW_FLAG_SELECTED );
+ if( !pDDDev )
+ {
+ if( pDDBufDev )
+ {
+ // nicht bei jedem Move ein Device anlegen, da dies besonders
+ // auf Remote-Clients zu langsam ist
+ pDDDev = pDDBufDev;
+ pDDBufDev = 0;
+ }
+ else
+ {
+ pDDDev = new VirtualDevice( *pView );
+ pDDDev->SetFont( pView->GetFont() );
+ }
+ }
+ else
+ {
+ ImpHideDDIcon();
+ }
+ const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
+ pDDDev->SetOutputSizePixel( rRect.GetSize() );
+
+ Point aPos( rPosPix );
+ ToDocPos( aPos );
+
+ Size aSize( pDDDev->GetOutputSizePixel() );
+ pDDRefEntry = pRefEntry;
+ aDDLastEntryPos = aPos;
+ aDDLastRectPos = aPos;
+
+ // Hintergrund sichern
+ pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView );
+ // Icon in pView malen
+ pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
+ PaintEntry( pRefEntry, aPos );
+ pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
+ if( bSelected )
+ pRefEntry->SetFlags( ICNVIEW_FLAG_SELECTED );
+}
+
+void SvxIconChoiceCtrl_Impl::HideShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
+{
+/* In Notfaellen folgenden flackernden Code aktivieren:
+
+ HideDDIcon();
+ ShowDDIcon( pRefEntry, rPosPix );
+ return;
+*/
+ if( !pDDDev )
+ {
+ ShowDDIcon( pRefEntry, rPosPix );
+ return;
+ }
+
+ if( pRefEntry != pDDRefEntry )
+ {
+ HideDDIcon();
+ ShowDDIcon( pRefEntry, rPosPix );
+ return;
+ }
+
+ Point aEmptyPoint;
+
+ Point aCurEntryPos( rPosPix );
+ ToDocPos( aCurEntryPos );
+
+ const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
+ Size aEntrySize( rRect.GetSize() );
+ Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize );
+ Rectangle aCurEntryRect( aCurEntryPos, aEntrySize );
+
+ if( !aPrevEntryRect.IsOver( aCurEntryRect ) )
+ {
+ HideDDIcon();
+ ShowDDIcon( pRefEntry, rPosPix );
+ return;
+ }
+
+ // Ueberlappung des neuen und alten D&D-Pointers!
+
+ Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) );
+ if( !pDDTempDev )
+ {
+ pDDTempDev = new VirtualDevice( *pView );
+ pDDTempDev->SetFont( pView->GetFont() );
+ }
+
+ Size aFullSize( aFullRect.GetSize() );
+ Point aFullPos( aFullRect.TopLeft() );
+
+ pDDTempDev->SetOutputSizePixel( aFullSize );
+
+ // Hintergrund (mit dem alten D&D-Pointer!) sichern
+ pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView );
+ // den alten Buffer in den neuen Buffer pasten
+ aDDLastRectPos = aDDLastRectPos - aFullPos;
+
+ pDDTempDev->DrawOutDev(
+ aDDLastRectPos,
+ pDDDev->GetOutputSizePixel(),
+ aEmptyPoint,
+ pDDDev->GetOutputSizePixel(),
+ *pDDDev );
+
+ // Swap
+ VirtualDevice* pTemp = pDDDev;
+ pDDDev = pDDTempDev;
+ pDDTempDev = pTemp;
+
+ // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen
+ pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() );
+ pDDTempDev->DrawOutDev(
+ aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev );
+ Point aRelPos = aCurEntryPos - aFullPos;
+ pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
+ PaintEntry( pRefEntry, aRelPos, pDDTempDev );
+ pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
+
+ aDDLastRectPos = aFullPos;
+ aDDLastEntryPos = aCurEntryPos;
+
+ pView->DrawOutDev(
+ aDDLastRectPos,
+ pDDDev->GetOutputSizePixel(),
+ aEmptyPoint,
+ pDDDev->GetOutputSizePixel(),
+ *pDDTempDev );
+}
+
+void SvxIconChoiceCtrl_Impl::InvalidateBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
+{
+ InvalidateBoundingRect( pEntry->aRect );
+}
+
+
+BOOL SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
+{
+ Rectangle aDocRect( GetDocumentRect() );
+ Rectangle aVisRect( GetVisibleRect() );
+ if( aVisRect.IsInside( aDocRect ))
+ return FALSE;
+ Size aDocSize( aDocRect.GetSize() );
+ Size aVisSize( aVisRect.GetSize() );
+ BOOL bHor = aDocSize.Width() > aVisSize.Width();
+ BOOL bVer = aDocSize.Height() > aVisSize.Height();
+
+ long nScrollDX = 0, nScrollDY = 0;
+
+ switch( rCmd.GetCommand() )
+ {
+ case COMMAND_STARTAUTOSCROLL:
+ {
+ pView->EndTracking();
+ USHORT nScrollFlags = 0;
+ if( bHor )
+ nScrollFlags |= AUTOSCROLL_HORZ;
+ if( bVer )
+ nScrollFlags |= AUTOSCROLL_VERT;
+ if( nScrollFlags )
+ {
+ pView->StartAutoScroll( nScrollFlags );
+ return TRUE;
+ }
+ }
+ break;
+
+ case COMMAND_WHEEL:
+ {
+ const CommandWheelData* pData = rCmd.GetWheelData();
+ if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
+ {
+ ULONG nScrollLines = pData->GetScrollLines();
+ if( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
+ {
+ nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
+ if( pData->GetDelta() < 0 )
+ nScrollDY *= -1;
+ }
+ else
+ {
+ nScrollDY = pData->GetNotchDelta() * (long)nScrollLines;
+ nScrollDY *= GetScrollBarLineSize();
+ }
+ }
+ }
+ break;
+
+ case COMMAND_AUTOSCROLL:
+ {
+ const CommandScrollData* pData = rCmd.GetAutoScrollData();
+ if( pData )
+ {
+ nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
+ nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
+ }
+ }
+ break;
+ }
+
+ if( nScrollDX || nScrollDY )
+ {
+ aVisRect.Top() -= nScrollDY;
+ aVisRect.Bottom() -= nScrollDY;
+ aVisRect.Left() -= nScrollDX;
+ aVisRect.Right() -= nScrollDX;
+ MakeVisible( aVisRect );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
+{
+ // Rollmaus-Event?
+ if( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
+ (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
+ (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
+ {
+#if 1
+ if( HandleScrollCommand( rCEvt ) )
+ return;
+#else
+ ScrollBar* pHor = aHorSBar.IsVisible() ? &aHorSBar : 0;
+ ScrollBar* pVer = aVerSBar.IsVisible() ? &aVerSBar : 0;
+ if( pView->HandleScrollCommand( rCEvt, pHor, pVer ) )
+ return;
+#endif
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
+{
+ if( pZOrderList->GetObject( pZOrderList->Count() - 1 ) != pEntry )
+ {
+ ULONG nPos = pZOrderList->GetPos( (void*)pEntry );
+ pZOrderList->Remove( nPos );
+ pZOrderList->Insert( pEntry, LIST_APPEND );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const
+{
+ if( rRect.Bottom() >= aVirtOutputSize.Height() )
+ rRect.Bottom() = aVirtOutputSize.Height() - 1;
+ if( rRect.Right() >= aVirtOutputSize.Width() )
+ rRect.Right() = aVirtOutputSize.Width() - 1;
+ if( rRect.Top() < 0 )
+ rRect.Top() = 0;
+ if( rRect.Left() < 0 )
+ rRect.Left() = 0;
+}
+
+// rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der
+// sichtbar gemacht werden soll.
+// bScrBar == TRUE: Das Rect wurde aufgrund eines ScrollBar-Events berechnet
+
+void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, BOOL bScrBar,
+ BOOL bCallRectChangedHdl )
+{
+ Rectangle aVirtRect( rRect );
+ ClipAtVirtOutRect( aVirtRect );
+ Point aOrigin( pView->GetMapMode().GetOrigin() );
+ // in Dokumentkoordinate umwandeln
+ aOrigin *= -1;
+ Rectangle aOutputArea( GetOutputRect() );
+ if( aOutputArea.IsInside( aVirtRect ) )
+ return; // ist schon sichtbar
+
+ long nDy;
+ if( aVirtRect.Top() < aOutputArea.Top() )
+ {
+ // nach oben scrollen (nDy < 0)
+ nDy = aVirtRect.Top() - aOutputArea.Top();
+ }
+ else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
+ {
+ // nach unten scrollen (nDy > 0)
+ nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
+ }
+ else
+ nDy = 0;
+
+ long nDx;
+ if( aVirtRect.Left() < aOutputArea.Left() )
+ {
+ // nach links scrollen (nDx < 0)
+ nDx = aVirtRect.Left() - aOutputArea.Left();
+ }
+ else if( aVirtRect.Right() > aOutputArea.Right() )
+ {
+ // nach rechts scrollen (nDx > 0)
+ nDx = aVirtRect.Right() - aOutputArea.Right();
+ }
+ else
+ nDx = 0;
+
+ aOrigin.X() += nDx;
+ aOrigin.Y() += nDy;
+ aOutputArea.SetPos( aOrigin );
+ if( GetUpdateMode() )
+ {
+ HideDDIcon();
+ pView->Update();
+ ShowCursor( FALSE );
+ }
+
+ // Origin fuer SV invertieren (damit wir in
+ // Dokumentkoordinaten scrollen/painten koennen)
+ aOrigin *= -1;
+ SetOrigin( aOrigin );
+
+ BOOL bScrollable = pView->GetBackground().IsScrollable();
+ if( pView->HasBackground() && !bScrollable )
+ {
+ Rectangle aRect( GetOutputRect());
+ Wallpaper aPaper( pView->GetBackground() );
+ aPaper.SetRect( aRect );
+ pView->SetBackground( aPaper );
+ }
+
+ if( bScrollable && GetUpdateMode() )
+ {
+ // in umgekehrte Richtung scrollen!
+ pView->Control::Scroll( -nDx, -nDy, aOutputArea,
+ SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP );
+ }
+ else
+ pView->Invalidate(INVALIDATE_NOCHILDREN);
+
+ if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
+ {
+ if( !bScrBar )
+ {
+ aOrigin *= -1;
+ // Thumbs korrigieren
+ if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
+ aHorSBar.SetThumbPos( aOrigin.X() );
+ if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
+ aVerSBar.SetThumbPos( aOrigin.Y() );
+ }
+ }
+
+ if( GetUpdateMode() )
+ ShowCursor( TRUE );
+
+ // pruefen, ob ScrollBars noch benoetigt werden
+ CheckScrollBars();
+ if( bScrollable && GetUpdateMode() )
+ pView->Update();
+
+ // kann der angeforderte Bereich nicht komplett sichtbar gemacht werden,
+ // wird auf jeden Fall der Vis-Rect-Changed-Handler gerufen. Eintreten kann der
+ // Fall z.B. wenn nur wenige Pixel des unteren Randes nicht sichtbar sind,
+ // eine ScrollBar aber eine groessere Line-Size eingestellt hat.
+ if( bCallRectChangedHdl || GetOutputRect() != rRect )
+ VisRectChanged();
+}
+
+
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindNewCursor()
+{
+ SvxIconChoiceCtrlEntry* pNewCursor;
+ if( pCursor )
+ {
+ pNewCursor = pImpCursor->GoLeftRight( pCursor, FALSE );
+ if( !pNewCursor )
+ {
+ pNewCursor = pImpCursor->GoLeftRight( pCursor, TRUE );
+ if( !pNewCursor )
+ {
+ pNewCursor = pImpCursor->GoUpDown( pCursor, FALSE );
+ if( !pNewCursor )
+ pNewCursor = pImpCursor->GoUpDown( pCursor, TRUE );
+ }
+ }
+ }
+ else
+ pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
+ DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"FindNewCursor failed");
+ return pNewCursor;
+}
+
+ULONG SvxIconChoiceCtrl_Impl::GetSelectionCount() const
+{
+ if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame )
+ return 1;
+ return nSelectionCount;
+}
+
+void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
+{
+ BOOL bSel;
+ if( pEntry->IsSelected() )
+ bSel = FALSE;
+ else
+ bSel = TRUE;
+ SelectEntry( pEntry, bSel, TRUE, TRUE );
+}
+
+void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot,
+ BOOL bPaintSync )
+{
+ ClearSelectedRectList();
+ //
+ // !!!!!!! Todo: Evtl. Z-Orderlist abarbeiten !!!!!!!
+ //
+ ULONG nCount = aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ if( pEntry != pThisEntryNot && pEntry->IsSelected() )
+ SelectEntry( pEntry, FALSE, TRUE, TRUE, bPaintSync );
+ }
+ pAnchor = 0;
+ nFlags &= (~F_ADD_MODE);
+}
+
+Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
+{
+ Size aMinSize( aImageSize );
+ aMinSize.Width() += 2 * LROFFS_BOUND;
+ aMinSize.Height() += TBOFFS_BOUND; // PB: einmal Offset reicht (FileDlg)
+ String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) );
+ Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() );
+ if( nWinBits & WB_ICON )
+ {
+ aMinSize.Height() += VER_DIST_BMP_STRING;
+ aMinSize.Height() += aTextSize.Height();
+ }
+ else
+ {
+ aMinSize.Width() += HOR_DIST_BMP_STRING;
+ aMinSize.Width() += aTextSize.Width();
+ }
+ return aMinSize;
+}
+
+void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
+{
+ Size aSize( rSize );
+ Size aMinSize( GetMinGrid() );
+ if( aSize.Width() < aMinSize.Width() )
+ aSize.Width() = aMinSize.Width();
+ if( aSize.Height() < aMinSize.Height() )
+ aSize.Height() = aMinSize.Height();
+
+ nGridDX = aSize.Width();
+ // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
+ // dieses Workaround bringts mit einer Spalte zum Fliegen
+ if( nWinBits & WB_DETAILS )
+ {
+ const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
+ if( pCol )
+ ((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX );
+ }
+ nGridDY = aSize.Height();
+ SetDefaultTextSize();
+}
+
+// berechnet die maximale Groesse, die das Textrechteck innerhalb des
+// umschliessenden Rechtecks einnehmen kann. Im Modus WB_ICON und
+// IcnShowTextFull wird Bottom auf LONG_MAX gesetzt
+
+Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ Rectangle aBoundRect;
+ // keine Endlosrekursion! deshalb das Bound-Rect hier nicht berechnen
+ if( IsBoundingRectValid( pEntry->aRect ) )
+ aBoundRect = pEntry->aRect;
+ else
+ aBoundRect = pEntry->aGridRect;
+
+ Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect(
+ (SvxIconChoiceCtrlEntry*)pEntry ) );
+ if( nWinBits & WB_ICON )
+ {
+ aBoundRect.Top() = aBmpRect.Bottom();
+ aBoundRect.Top() += VER_DIST_BMP_STRING;
+ if( aBoundRect.Top() > aBoundRect.Bottom())
+ aBoundRect.Top() = aBoundRect.Bottom();
+ aBoundRect.Left() += LROFFS_BOUND;
+ aBoundRect.Left()++;
+ aBoundRect.Right() -= LROFFS_BOUND;
+ aBoundRect.Right()--;
+ if( aBoundRect.Left() > aBoundRect.Right())
+ aBoundRect.Left() = aBoundRect.Right();
+ if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull )
+ aBoundRect.Bottom() = LONG_MAX;
+ }
+ else
+ {
+ aBoundRect.Left() = aBmpRect.Right();
+ aBoundRect.Left() += HOR_DIST_BMP_STRING;
+ aBoundRect.Right() -= LROFFS_BOUND;
+ if( aBoundRect.Left() > aBoundRect.Right() )
+ aBoundRect.Left() = aBoundRect.Right();
+ long nHeight = aBoundRect.GetSize().Height();
+ nHeight = nHeight - aDefaultTextSize.Height();
+ nHeight /= 2;
+ aBoundRect.Top() += nHeight;
+ aBoundRect.Bottom() -= nHeight;
+ }
+ return aBoundRect;
+}
+
+void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
+{
+ long nDY = nGridDY;
+ nDY -= aImageSize.Height();
+ nDY -= VER_DIST_BMP_STRING;
+ nDY -= 2*TBOFFS_BOUND;
+ if( nDY <= 0 )
+ nDY = 2;
+
+ long nDX = nGridDX;
+ nDX -= 2*LROFFS_BOUND;
+ nDX -= 2;
+ if( nDX <= 0 )
+ nDX = 2;
+
+ String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "X" ) );
+ long nHeight = pView->GetTextHeight();
+ if( nDY < nHeight )
+ nDY = nHeight;
+ aDefaultTextSize = Size( nDX, nDY );
+}
+
+
+void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ pEntry->aRect = pEntry->aGridRect;
+ Size aSize( CalcBoundingSize( pEntry ) );
+ if( nWinBits & WB_ICON )
+ {
+ // horizontal zentrieren
+ long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
+ pEntry->aRect.Left() += nBorder / 2;
+ pEntry->aRect.Right() -= nBorder / 2;
+ }
+ // vertikal zentrieren
+ pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height();
+}
+
+
+// Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird
+// links, hoch: Offsets < 0
+// rechts, runter: Offsets > 0
+void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, BOOL bScrollBar )
+{
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin() );
+ // in Dokumentkoordinate umwandeln
+ aOrigin *= -1;
+ aOrigin.Y() += nDeltaY;
+ aOrigin.X() += nDeltaX;
+ Rectangle aRect( aOrigin, aOutputSize );
+ MakeVisible( aRect, bScrollBar );
+}
+
+
+const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*,
+ IcnViewFieldType eItem ) const
+{
+ if( eItem == IcnViewFieldTypeText )
+ return aDefaultTextSize;
+ return aImageSize;
+}
+
+Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
+{
+ Rectangle aBmpRect( CalcBmpRect( pEntry ) );
+ Rectangle aTextRect( CalcTextRect( pEntry ) );
+ Rectangle aBoundRect( GetEntryBoundRect( pEntry ) );
+ Rectangle aFocusRect( aBoundRect.Left(), aBmpRect.Top() - 1,
+ aBoundRect.Right() - 4, aTextRect.Bottom() + 1 );
+ // Das Fokusrechteck soll nicht den Text beruehren
+ if( aFocusRect.Left() - 1 >= pEntry->aRect.Left() )
+ aFocusRect.Left()--;
+ if( aFocusRect.Right() + 1 <= pEntry->aRect.Right() )
+ aFocusRect.Right()++;
+
+ return aFocusRect;
+}
+
+// Der 'Hot Spot' sind die inneren 50% der Rechteckflaeche
+static Rectangle GetHotSpot( const Rectangle& rRect )
+{
+ Rectangle aResult( rRect );
+ aResult.Justify();
+ Size aSize( rRect.GetSize() );
+ long nDelta = aSize.Width() / 4;
+ aResult.Left() += nDelta;
+ aResult.Right() -= nDelta;
+ nDelta = aSize.Height() / 4;
+ aResult.Top() += nDelta;
+ aResult.Bottom() -= nDelta;
+ return aResult;
+}
+
+void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
+ BOOL bAdd, SvPtrarr* pOtherRects )
+{
+ DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
+ Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
+ aRect.Union( GetEntryBoundRect( pEntry2 ) );
+ SelectRect( aRect, bAdd, pOtherRects );
+}
+
+void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, BOOL bAdd,
+ SvPtrarr* pOtherRects )
+{
+ aCurSelectionRect = rRect;
+ if( !pZOrderList || !pZOrderList->Count() )
+ return;
+
+ // Flag setzen, damit im Select kein ToTop gerufen wird
+ BOOL bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? TRUE : FALSE;
+ nFlags |= F_SELECTING_RECT;
+
+ CheckBoundingRects();
+ pView->Update();
+ const ULONG nCount = pZOrderList->Count();
+
+ Rectangle aRect( rRect );
+ aRect.Justify();
+ BOOL bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? TRUE : FALSE;
+
+ BOOL bResetClipRegion = FALSE;
+ if( !pView->IsClipRegion() )
+ {
+ bResetClipRegion = TRUE;
+ pView->SetClipRegion( GetOutputRect() );
+ }
+
+ for( ULONG nPos = 0; nPos < nCount; nPos++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
+
+ if( !IsBoundingRectValid( pEntry->aRect ))
+ FindBoundingRect( pEntry );
+ Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
+ BOOL bSelected = pEntry->IsSelected();
+
+ BOOL bOverlaps;
+ if( bCalcOverlap )
+ bOverlaps = IsOver( pOtherRects, aBoundRect );
+ else
+ bOverlaps = FALSE;
+ BOOL bOver = aRect.IsOver( aBoundRect );
+
+ if( bOver && !bOverlaps )
+ {
+ // Ist im neuen Selektionsrechteck und in keinem alten
+ // => selektieren
+ if( !bSelected )
+ SelectEntry( pEntry, TRUE, TRUE, TRUE );
+ }
+ else if( !bAdd )
+ {
+ // ist ausserhalb des Selektionsrechtecks
+ // => Selektion entfernen
+ if( bSelected )
+ SelectEntry( pEntry, FALSE, TRUE, TRUE );
+ }
+ else if( bAdd && bOverlaps )
+ {
+ // Der Eintrag befindet sich in einem alten (=>Aufspannen
+ // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck
+
+ // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags
+ // in einem vorherigen Rechteck, muss restauriert werden, wenn
+ // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber
+ // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber
+ // pauschal davon aus, dass die Eintraege in den alten Rechtecken
+ // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge
+ // nur zu deselektieren.
+ // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf-
+ // spannen des Rechtecks merken
+ if( aBoundRect.IsOver( rRect))
+ {
+ // Schnittmenge zwischen alten Rects & aktuellem Rect desel.
+ if( bSelected )
+ SelectEntry( pEntry, FALSE, TRUE, TRUE );
+ }
+ else
+ {
+ // Eintrag eines alten Rects selektieren
+ if( !bSelected )
+ SelectEntry( pEntry, TRUE, TRUE, TRUE );
+ }
+ }
+ else if( !bOver && bSelected )
+ {
+ // Der Eintrag liegt voellig ausserhalb und wird deshalb desel.
+ SelectEntry( pEntry, FALSE, TRUE, TRUE );
+ }
+ }
+
+ if( !bAlreadySelectingRect )
+ nFlags &= ~F_SELECTING_RECT;
+
+ pView->Update();
+ if( bResetClipRegion )
+ pView->SetClipRegion();
+}
+
+void SvxIconChoiceCtrl_Impl::SelectRange(
+ SvxIconChoiceCtrlEntry* pStart,
+ SvxIconChoiceCtrlEntry* pEnd,
+ BOOL bAdd )
+{
+ ULONG nFront = GetEntryListPos( pStart );
+ ULONG nBack = GetEntryListPos( pEnd );
+ ULONG nFirst = std::min( nFront, nBack );
+ ULONG nLast = std::max( nFront, nBack );
+ ULONG i;
+ SvxIconChoiceCtrlEntry* pEntry;
+
+ if ( ! bAdd )
+ {
+ // deselect everything before the first entry if not in
+ // adding mode
+ for ( i=0; i<nFirst; i++ )
+ {
+ pEntry = GetEntry( i );
+ if( pEntry->IsSelected() )
+ SelectEntry( pEntry, FALSE, TRUE, TRUE, TRUE );
+ }
+ }
+
+ // select everything between nFirst and nLast
+ for ( i=nFirst; i<=nLast; i++ )
+ {
+ pEntry = GetEntry( i );
+ if( ! pEntry->IsSelected() )
+ SelectEntry( pEntry, TRUE, TRUE, TRUE, TRUE );
+ }
+
+ if ( ! bAdd )
+ {
+ // deselect everything behind the last entry if not in
+ // adding mode
+ ULONG nEnd = GetEntryCount();
+ for ( ; i<nEnd; i++ )
+ {
+ pEntry = GetEntry( i );
+ if( pEntry->IsSelected() )
+ SelectEntry( pEntry, FALSE, TRUE, TRUE, TRUE );
+ }
+ }
+}
+
+BOOL SvxIconChoiceCtrl_Impl::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const
+{
+ const USHORT nCount = pRectList->Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur );
+ if( rBoundRect.IsOver( *pRect ))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
+ SvxIconChoiceCtrlEntry* pEntry2 )
+{
+ DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
+ Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
+ aRect.Union( GetEntryBoundRect( pEntry2 ) );
+ AddSelectedRect( aRect );
+}
+
+void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect )
+{
+ Rectangle* pRect = new Rectangle( rRect );
+ pRect->Justify();
+ aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() );
+}
+
+void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
+{
+ const USHORT nCount = aSelectedRectList.Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur );
+ delete pRect;
+ }
+ aSelectedRectList.Remove( 0, aSelectedRectList.Count() );
+}
+
+void SvxIconChoiceCtrl_Impl::CalcScrollOffsets( const Point& rPosPixel,
+ long& rX, long& rY, BOOL isInDragDrop, USHORT nBorderWidth)
+{
+ // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des
+ // Fensters befindet
+ long nPixelToScrollX = 0;
+ long nPixelToScrollY = 0;
+ Size aWndSize = aOutputSize;
+
+ nBorderWidth = (USHORT)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth ));
+ nBorderWidth = (USHORT)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth ));
+
+ if ( rPosPixel.X() < nBorderWidth )
+ {
+ if( isInDragDrop )
+ nPixelToScrollX = -DD_SCROLL_PIXEL;
+ else
+ nPixelToScrollX = rPosPixel.X()- nBorderWidth;
+ }
+ else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth )
+ {
+ if( isInDragDrop )
+ nPixelToScrollX = DD_SCROLL_PIXEL;
+ else
+ nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth);
+ }
+ if ( rPosPixel.Y() < nBorderWidth )
+ {
+ if( isInDragDrop )
+ nPixelToScrollY = -DD_SCROLL_PIXEL;
+ else
+ nPixelToScrollY = rPosPixel.Y() - nBorderWidth;
+ }
+ else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth )
+ {
+ if( isInDragDrop )
+ nPixelToScrollY = DD_SCROLL_PIXEL;
+ else
+ nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth);
+ }
+
+ rX = nPixelToScrollX;
+ rY = nPixelToScrollY;
+}
+
+IMPL_LINK(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, void*, EMPTYARG )
+{
+ aAutoArrangeTimer.Stop();
+ Arrange( IsAutoArrange() );
+ return 0;
+}
+
+IMPL_LINK(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, void*, EMPTYARG )
+{
+ aVisRectChangedTimer.Stop();
+ pView->VisibleRectChanged();
+ return 0;
+}
+
+IMPL_LINK(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, void*, EMPTYARG )
+{
+ aDocRectChangedTimer.Stop();
+ pView->DocumentRectChanged();
+ return 0;
+}
+
+void SvxIconChoiceCtrl_Impl::PrepareCommandEvent( const CommandEvent& rCEvt )
+{
+ StopEditTimer();
+ SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry( rCEvt.GetMousePosPixel() );
+ if( (nFlags & F_DOWN_CTRL) && pEntry && !pEntry->IsSelected() )
+ SelectEntry( pEntry, TRUE, TRUE );
+ nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
+}
+
+BOOL SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos )
+{
+ Rectangle aRect( CalcTextRect( pEntry ));
+ if( aRect.IsInside( rDocPos ) )
+ return TRUE;
+ return FALSE;
+}
+
+IMPL_LINK(SvxIconChoiceCtrl_Impl, EditTimeoutHdl, Timer*, EMPTYARG )
+{
+ SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
+ if( bEntryEditingEnabled && pEntry &&
+ pEntry->IsSelected())
+ {
+ if( pView->EditingEntry( pEntry ))
+ EditEntry( pEntry );
+ }
+ return 0;
+}
+
+
+//
+// Funktionen zum Ausrichten der Eintraege am Grid
+//
+
+// pStart == 0: Alle Eintraege werden ausgerichtet
+// sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet
+void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart )
+{
+ SvPtrarr aLists;
+ pImpCursor->CreateGridAjustData( aLists, pStart );
+ const USHORT nCount = aLists.Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart );
+ IcnCursor_Impl::DestroyGridAdjustData( aLists );
+ CheckScrollBars();
+}
+
+// Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
+void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvPtrarr& rRow, SvxIconChoiceCtrlEntry* pStart )
+{
+ if( !rRow.Count() )
+ return;
+
+ BOOL bGo;
+ if( !pStart )
+ bGo = TRUE;
+ else
+ bGo = FALSE;
+
+ long nCurRight = 0;
+ for( USHORT nCur = 0; nCur < rRow.Count(); nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)rRow[ nCur ];
+ if( !bGo && pCur == pStart )
+ bGo = TRUE;
+
+ //SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
+ // Massgebend (fuer unser Auge) ist die Bitmap, da sonst
+ // durch lange Texte der Eintrag stark springen kann
+ const Rectangle& rBoundRect = GetEntryBoundRect( pCur );
+ Rectangle aCenterRect( CalcBmpRect( pCur, 0 ));
+ if( bGo && !pCur->IsPosLocked() )
+ {
+ long nWidth = aCenterRect.GetSize().Width();
+ Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
+ while( aNewPos.X() < nCurRight )
+ aNewPos.X() += nGridDX;
+ if( aNewPos != rBoundRect.TopLeft() )
+ {
+ SetEntryPos( pCur, aNewPos );
+ pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED );
+ nFlags |= F_MOVED_ENTRIES;
+ }
+ nCurRight = aNewPos.X() + nWidth;
+ }
+ else
+ {
+ nCurRight = rBoundRect.Right();
+ }
+ }
+}
+
+// Richtet Rect am Grid aus, garantiert jedoch nicht, dass die
+// neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden.
+// Das CenterRect beschreibt den Teil des BoundRects, der fuer
+// die Berechnung des Ziel-Rechtecks verwendet wird.
+Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect,
+ const Rectangle& rBoundRect ) const
+{
+ Point aPos( rCenterRect.TopLeft() );
+ Size aSize( rCenterRect.GetSize() );
+
+ aPos.X() -= LROFFS_WINBORDER;
+ aPos.Y() -= TBOFFS_WINBORDER;
+
+ // align (ref ist mitte des rects)
+ short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
+ short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
+ aPos.X() = nGridX * nGridDX;
+ aPos.Y() = nGridY * nGridDY;
+ // hor. center
+ aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
+
+ aPos.X() += LROFFS_WINBORDER;
+ aPos.Y() += TBOFFS_WINBORDER;
+
+ return aPos;
+}
+
+void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
+{
+ if( !pEntry )
+ {
+ if( eTextMode != eMode )
+ {
+ if( eTextMode == IcnShowTextDontKnow )
+ eTextMode = IcnShowTextShort;
+ eTextMode = eMode;
+ Arrange( TRUE );
+ }
+ }
+ else
+ {
+ if( pEntry->eTextMode != eMode )
+ {
+ pEntry->eTextMode = eMode;
+ InvalidateEntry( pEntry );
+ pView->Invalidate( GetEntryBoundRect( pEntry ) );
+ AdjustVirtSize( pEntry->aRect );
+ }
+ }
+}
+
+SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetTextMode( const SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ if( !pEntry )
+ return eTextMode;
+ return pEntry->GetTextMode();
+}
+
+SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
+ SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode();
+ if( eMode == IcnShowTextDontKnow )
+ return eTextMode;
+ return eMode;
+}
+
+void SvxIconChoiceCtrl_Impl::ShowEntryFocusRect( const SvxIconChoiceCtrlEntry* pEntry )
+{
+ if( !pEntry )
+ {
+ pView->HideFocus();
+ }
+ else
+ {
+ Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
+ /*pView->*/ShowFocus( aRect );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
+// of the background. But what will we see, if the the backgroundcolor is gray ? - We will see
+// a gray focusrect on a gray background !!!
+//
+void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect )
+{
+ Color aBkgColor ( pView->GetBackground().GetColor() );
+ Color aPenColor;
+ USHORT nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
+ if ( nColor > 128 )
+ aPenColor.SetColor ( COL_BLACK );
+ else
+ aPenColor.SetColor( COL_WHITE );
+
+ aFocus.bOn = TRUE;
+ aFocus.aPenColor = aPenColor;
+ aFocus.aRect = rRect;
+}
+
+void SvxIconChoiceCtrl_Impl::HideFocus ()
+{
+ aFocus.bOn = FALSE;
+}
+
+void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut )
+{
+ pOut->SetLineColor( aFocus.aPenColor );
+ pOut->SetFillColor();
+ Polygon aPolygon ( aFocus.aRect );
+
+ LineInfo aLineInfo ( LINE_DASH );
+
+ aLineInfo.SetDashLen ( 1 );
+
+ aLineInfo.SetDotLen ( 1L );
+ aLineInfo.SetDistance ( 1L );
+ aLineInfo.SetDotCount ( 1 );
+
+ pOut->DrawPolyLine ( aPolygon, aLineInfo );
+}
+
+sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, ULONG& rPos ) const
+{
+ sal_Bool bRet = sal_False;
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+ ULONG nEntryCount = GetEntryCount();
+ for ( ULONG i = 0; i < nEntryCount; ++i )
+ {
+ if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
+ {
+ bRet = sal_True;
+ rPos = i;
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+//
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId )
+{
+ if( nId == EVENTID_ADJUST_SCROLLBARS )
+ {
+ nUserEventAdjustScrBars = 0;
+ AdjustScrollBars();
+ }
+ else if( nId == EVENTID_SHOW_CURSOR )
+ {
+ nUserEventShowCursor = 0;
+ ShowCursor( TRUE );
+ }
+ return 0;
+}
+
+void SvxIconChoiceCtrl_Impl::CancelUserEvents()
+{
+ if( nUserEventAdjustScrBars )
+ {
+ Application::RemoveUserEvent( nUserEventAdjustScrBars );
+ nUserEventAdjustScrBars = 0;
+ }
+ if( nUserEventShowCursor )
+ {
+ Application::RemoveUserEvent( nUserEventShowCursor );
+ nUserEventShowCursor = 0;
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
+{
+ if( pEntry == pCursor )
+ ShowCursor( FALSE );
+ pView->Invalidate( pEntry->aRect );
+ Center( pEntry );
+ pView->Invalidate( pEntry->aRect );
+ if( pEntry == pCursor )
+ ShowCursor( TRUE );
+}
+
+void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry )
+{
+ DBG_ASSERT(pEntry,"EditEntry: Entry not set");
+ if( !pEntry )
+ return;
+
+ StopEntryEditing( TRUE );
+ DELETEZ(pEdit);
+ SetNoSelection();
+
+ pCurEditedEntry = pEntry;
+ String aEntryText( pView->GetEntryText( pEntry, TRUE ) );
+ Rectangle aRect( CalcTextRect( pEntry, 0, TRUE, &aEntryText ) );
+ MakeVisible( aRect );
+ Point aPos( aRect.TopLeft() );
+ aPos = pView->GetPixelPos( aPos );
+ aRect.SetPos( aPos );
+ pView->HideFocus();
+ pEdit = new IcnViewEdit_Impl(
+ pView,
+ aRect.TopLeft(),
+ aRect.GetSize(),
+ aEntryText,
+ LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) );
+}
+
+IMPL_LINK( SvxIconChoiceCtrl_Impl, TextEditEndedHdl, IcnViewEdit_Impl*, EMPTYARG )
+{
+ DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set");
+ if( !pEdit )
+ {
+ pCurEditedEntry = 0;
+ return 0;
+ }
+ DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set");
+
+ if( !pCurEditedEntry )
+ {
+ pEdit->Hide();
+ if( pEdit->IsGrabFocus() )
+ pView->GrabFocus();
+ return 0;
+ }
+
+ String aText;
+ if ( !pEdit->EditingCanceled() )
+ aText = pEdit->GetText();
+ else
+ aText = pEdit->GetSavedValue();
+
+ if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) )
+ InvalidateEntry( pCurEditedEntry );
+ if( !GetSelectionCount() )
+ SelectEntry( pCurEditedEntry, TRUE );
+
+ pEdit->Hide();
+ if( pEdit->IsGrabFocus() )
+ pView->GrabFocus();
+ // Das Edit kann nicht hier geloescht werden, weil es noch in einem
+ // Handler steht. Es wird im Dtor oder im naechsten EditEntry geloescht.
+ pCurEditedEntry = 0;
+ return 0;
+}
+
+void SvxIconChoiceCtrl_Impl::StopEntryEditing( BOOL bCancel )
+{
+ if( pEdit )
+ pEdit->StopEditing( bCancel );
+}
+
+void SvxIconChoiceCtrl_Impl::LockEntryPos( SvxIconChoiceCtrlEntry* pEntry, BOOL bLock )
+{
+ if( bLock )
+ pEntry->SetFlags( ICNVIEW_FLAG_POS_LOCKED );
+ else
+ pEntry->ClearFlags( ICNVIEW_FLAG_POS_LOCKED );
+}
+
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( ULONG& rPos ) const
+{
+ if( !GetSelectionCount() )
+ return 0;
+
+ if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) )
+ {
+ rPos = pView->GetEntryListPos( pCurHighlightFrame );
+ return pCurHighlightFrame;
+ }
+
+ ULONG nCount = aEntries.Count();
+ if( !pHead )
+ {
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ if( pEntry->IsSelected() )
+ {
+ rPos = nCur;
+ return pEntry;
+ }
+ }
+ }
+ else
+ {
+ SvxIconChoiceCtrlEntry* pEntry = pHead;
+ while( nCount-- )
+ {
+ if( pEntry->IsSelected() )
+ {
+ rPos = GetEntryListPos( pEntry );
+ return pEntry;
+ }
+ pEntry = pEntry->pflink;
+ if( nCount && pEntry == pHead )
+ {
+ DBG_ERROR("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > Endlosschleife!");
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+// kein Round Robin!
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextSelectedEntry( ULONG& rStartPos ) const
+{
+ ULONG nCount = aEntries.Count();
+ if( rStartPos > nCount || !GetSelectionCount() )
+ return 0;
+ if( !pHead )
+ {
+ for( ULONG nCur = rStartPos+1; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ if( pEntry->IsSelected() )
+ {
+ rStartPos = nCur;
+ return pEntry;
+ }
+ }
+ }
+ else
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( rStartPos );
+ pEntry = pEntry->pflink;
+ while( pEntry != pHead )
+ {
+ if( pEntry->IsSelected() )
+ {
+ rStartPos = GetEntryListPos( pEntry );
+ return pEntry;
+ }
+ pEntry = pEntry->pflink;
+ }
+ }
+
+ rStartPos = 0xffffffff;
+ return 0;
+}
+
+void SvxIconChoiceCtrl_Impl::SelectAll( BOOL bSelect, BOOL bPaint )
+{
+ bPaint = TRUE;
+
+ ULONG nCount = aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ SelectEntry( pEntry, bSelect, TRUE, TRUE, bPaint );
+ }
+ nFlags &= (~F_ADD_MODE);
+ pAnchor = 0;
+}
+
+void SvxIconChoiceCtrl_Impl::SaveSelection( List** ppList )
+{
+ if( !*ppList )
+ *ppList = new List;
+ ULONG nPos;
+ SvxIconChoiceCtrlEntry* pEntry = GetFirstSelectedEntry( nPos );
+ while( pEntry && GetSelectionCount() != (*ppList)->Count() )
+ {
+ (*ppList)->Insert( pEntry, LIST_APPEND );
+ pEntry = GetNextSelectedEntry( nPos );
+ }
+}
+
+IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos,
+ const Size& rSize, const XubString& rData, const Link& rNotifyEditEnd ) :
+ MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT),
+ aCallBackHdl( rNotifyEditEnd ),
+ bCanceled( FALSE ),
+ bAlreadyInCallback( FALSE ),
+ bGrabFocus( FALSE )
+{
+ Font aFont( pParent->GetPointFont() );
+ aFont.SetTransparent( FALSE );
+ SetControlFont( aFont );
+ if( !pParent->HasFontFillColor() )
+ {
+ Color aColor( pParent->GetBackground().GetColor() );
+ SetControlBackground( aColor );
+ }
+ else
+ SetControlBackground( aFont.GetFillColor() );
+ SetControlForeground( aFont.GetColor() );
+ SetPosPixel( rPos );
+ SetSizePixel( CalcAdjustedSize(rSize) );
+ SetText( rData );
+ SaveValue();
+
+ aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) );
+ aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
+
+ aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) );
+ aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) );
+ GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS );
+ GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS );
+ Show();
+ GrabFocus();
+}
+
+IcnViewEdit_Impl::~IcnViewEdit_Impl()
+{
+ if( !bAlreadyInCallback )
+ {
+ GetpApp()->RemoveAccel( &aAccReturn );
+ GetpApp()->RemoveAccel( &aAccEscape );
+ }
+}
+
+void IcnViewEdit_Impl::CallCallBackHdl_Impl()
+{
+ aTimer.Stop();
+ if ( !bAlreadyInCallback )
+ {
+ bAlreadyInCallback = TRUE;
+ GetpApp()->RemoveAccel( &aAccReturn );
+ GetpApp()->RemoveAccel( &aAccEscape );
+ Hide();
+ aCallBackHdl.Call( this );
+ }
+}
+
+IMPL_LINK( IcnViewEdit_Impl, Timeout_Impl, Timer*, EMPTYARG )
+{
+ CallCallBackHdl_Impl();
+ return 0;
+}
+
+IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG )
+{
+ bCanceled = FALSE;
+ bGrabFocus = TRUE;
+ CallCallBackHdl_Impl();
+ return 1;
+}
+
+IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG )
+{
+ bCanceled = TRUE;
+ bGrabFocus = TRUE;
+ CallCallBackHdl_Impl();
+ return 1;
+}
+
+void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt )
+{
+ KeyCode aCode = rKEvt.GetKeyCode();
+ USHORT nCode = aCode.GetCode();
+
+ switch ( nCode )
+ {
+ case KEY_ESCAPE:
+ bCanceled = TRUE;
+ bGrabFocus = TRUE;
+ CallCallBackHdl_Impl();
+ break;
+
+ case KEY_RETURN:
+ bCanceled = FALSE;
+ bGrabFocus = TRUE;
+ CallCallBackHdl_Impl();
+ break;
+
+ default:
+ MultiLineEdit::KeyInput( rKEvt );
+ }
+}
+
+long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( !bAlreadyInCallback &&
+ ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
+ {
+ bCanceled = FALSE;
+ aTimer.SetTimeout(10);
+ aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
+ aTimer.Start();
+ }
+ }
+ return 0;
+}
+
+void IcnViewEdit_Impl::StopEditing( BOOL bCancel )
+{
+ if ( !bAlreadyInCallback )
+ {
+ bCanceled = bCancel;
+ CallCallBackHdl_Impl();
+ }
+}
+
+ULONG SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ if( !(nFlags & F_ENTRYLISTPOS_VALID ))
+ ((SvxIconChoiceCtrl_Impl*)this)->SetListPositions();
+ return pEntry->nPos;
+}
+
+void SvxIconChoiceCtrl_Impl::SetEntryListPos( SvxIconChoiceCtrlEntry* pListEntry, ULONG nNewPos )
+{
+ ULONG nCurPos = GetEntryListPos( pListEntry );
+ if( nCurPos == nNewPos )
+ return;
+ aEntries.List::Remove( nCurPos );
+ aEntries.List::Insert( (void*)pListEntry, nNewPos );
+ // Eintragspositionen anpassen
+ ULONG nStart, nEnd;
+ if( nNewPos < nCurPos )
+ {
+ nStart = nNewPos;
+ nEnd = nCurPos;
+ }
+ else
+ {
+ nStart = nCurPos;
+ nEnd = nNewPos;
+ }
+ for( ; nStart <= nEnd; nStart++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nStart );
+ pEntry->nPos = nStart;
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::SetEntryFlags( SvxIconChoiceCtrlEntry* pEntry, USHORT nEntryFlags )
+{
+ pEntry->nFlags = nEntryFlags;
+ if( nEntryFlags & ICNVIEW_FLAG_POS_MOVED )
+ nFlags |= F_MOVED_ENTRIES;
+}
+
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pStart, BOOL bRight )
+{
+ return pImpCursor->GoLeftRight( pStart, bRight );
+}
+
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pStart, BOOL bDown )
+{
+ return pImpCursor->GoUpDown( pStart, bDown );
+}
+
+void SvxIconChoiceCtrl_Impl::InitSettings()
+{
+ const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
+
+ if( !pView->HasFont() )
+ {
+ // Unit aus den Settings ist Point
+ Font aFont( rStyleSettings.GetFieldFont() );
+ //const Font& rFont = pView->GetFont();
+ //if( pView->HasFontTextColor() )
+ aFont.SetColor( rStyleSettings.GetWindowTextColor() );
+ //if( pView->HasFontFillColor() )
+ //aFont.SetFillColor( rFont.GetFillColor() );
+ pView->SetPointFont( aFont );
+ SetDefaultTextSize();
+ }
+
+ //if( !pView->HasFontTextColor() )
+ pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
+ //if( !pView->HasFontFillColor() )
+ pView->SetTextFillColor();
+
+ //if( !pView->HasBackground() )
+ pView->SetBackground( rStyleSettings.GetFieldColor());
+
+ long nScrBarSize = rStyleSettings.GetScrollBarSize();
+ if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth )
+ {
+ nHorSBarHeight = nScrBarSize;
+ Size aSize( aHorSBar.GetSizePixel() );
+ aSize.Height() = nScrBarSize;
+ aHorSBar.Hide();
+ aHorSBar.SetSizePixel( aSize );
+
+ nVerSBarWidth = nScrBarSize;
+ aSize = aVerSBar.GetSizePixel();
+ aSize.Width() = nScrBarSize;
+ aVerSBar.Hide();
+ aVerSBar.SetSizePixel( aSize );
+
+ Size aOSize( pView->Control::GetOutputSizePixel() );
+ PositionScrollBars( aOSize.Width(), aOSize.Height() );
+ AdjustScrollBars();
+ }
+}
+
+EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, USHORT _nInitSize , USHORT _nReSize ) :
+ List( _nInitSize, _nReSize ),
+ _pOwner( pOwner )
+{
+ _pOwner->pHead = 0;
+}
+
+EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, USHORT _nBlockSize, USHORT _nInitSize, USHORT _nReSize ) :
+ List( _nBlockSize, _nInitSize, _nReSize ),
+ _pOwner( pOwner )
+{
+ _pOwner->pHead = 0;
+}
+
+EntryList_Impl::~EntryList_Impl()
+{
+ _pOwner->pHead = 0;
+}
+
+void EntryList_Impl::Clear()
+{
+ _pOwner->pHead = 0;
+ List::Clear();
+}
+
+void EntryList_Impl::Insert( SvxIconChoiceCtrlEntry* pEntry, ULONG nPos )
+{
+ List::Insert( pEntry, nPos );
+ if( _pOwner->pHead )
+ pEntry->SetBacklink( _pOwner->pHead->pblink );
+}
+
+SvxIconChoiceCtrlEntry* EntryList_Impl::Remove( ULONG nPos )
+{
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)List::Remove( nPos );
+ DBG_ASSERT(pEntry,"EntryList_Impl::Remove > Entry not found");
+ Removed_Impl( pEntry );
+ return pEntry;
+}
+
+void EntryList_Impl::Remove( SvxIconChoiceCtrlEntry* pEntry )
+{
+ List::Remove( (void*)pEntry );
+ Removed_Impl( pEntry );
+}
+
+void EntryList_Impl::Removed_Impl( SvxIconChoiceCtrlEntry* pEntry )
+{
+ if( _pOwner->pHead )
+ {
+ if( _pOwner->pHead == pEntry )
+ {
+ if( _pOwner->pHead != pEntry->pflink )
+ _pOwner->pHead = pEntry->pflink;
+ else
+ {
+ DBG_ASSERT(!Count(),"EntryList_Impl::Remove > Invalid predecessor" );
+ _pOwner->pHead = 0;
+ }
+ }
+ pEntry->Unlink();
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
+{
+ ULONG nCur;
+
+ if( eMode == ePositionMode )
+ return;
+
+ SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
+ ePositionMode = eMode;
+ ULONG nCount = aEntries.Count();
+
+ if( eOldMode == IcnViewPositionModeAutoArrange )
+ {
+ // positionieren wir verschobene Eintraege 'hart' gibts noch Probleme
+ // mit ungewollten Ueberlappungen, da diese Eintrage im Arrange
+ // nicht beruecksichtigt werden.
+#if 1
+ if( aEntries.Count() )
+ aAutoArrangeTimer.Start();
+#else
+ if( pHead )
+ {
+ // verschobene Eintraege 'hart' auf ihre Position setzen
+ nCur = nCount;
+ SvxIconChoiceCtrlEntry* pEntry = pHead;
+ while( nCur )
+ {
+ SvxIconChoiceCtrlEntry* pPred;
+ if( GetEntryPredecessor( pEntry, &pPred ))
+ SetEntryFlags( pEntry, ICNVIEW_FLAG_POS_MOVED );
+ pEntry = pEntry->pflink;
+ nCur--;
+ }
+ ClearPredecessors();
+ }
+#endif
+ return;
+ }
+
+ if( ePositionMode == IcnViewPositionModeAutoArrange )
+ {
+ List aMovedEntries;
+ for( nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
+ if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED))
+ {
+ SvxIconChoiceCtrlEntry_Impl* pE = new SvxIconChoiceCtrlEntry_Impl(
+ pEntry, GetEntryBoundRect( pEntry ));
+ aMovedEntries.Insert( pE, LIST_APPEND );
+ }
+ }
+ nCount = aMovedEntries.Count();
+ for( nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry_Impl* pE = (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject(nCur);
+ SetEntryPos( pE->_pEntry, pE->_aPos );
+ }
+ for( nCur = 0; nCur < nCount; nCur++ )
+ delete (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject( nCur );
+ if( aEntries.Count() )
+ aAutoArrangeTimer.Start();
+ }
+ else if( ePositionMode == IcnViewPositionModeAutoAdjust )
+ {
+ AdjustEntryAtGrid( 0 );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
+ SvxIconChoiceCtrlEntry* pPredecessor )
+{
+ if( !IsAutoArrange() )
+ return;
+
+ if( pEntry == pPredecessor )
+ return;
+
+ ULONG nPos1 = GetEntryListPos( pEntry );
+ if( !pHead )
+ {
+ if( pPredecessor )
+ {
+ ULONG nPos2 = GetEntryListPos( pPredecessor );
+ if( nPos1 == (nPos2 + 1) )
+ return; // ist schon Vorgaenger
+ }
+ else if( !nPos1 )
+ return;
+ }
+
+ if( !pHead )
+ InitPredecessors();
+
+ if( !pPredecessor && pHead == pEntry )
+ return; // ist schon der Erste
+
+ BOOL bSetHead = FALSE;
+ if( !pPredecessor )
+ {
+ bSetHead = TRUE;
+ pPredecessor = pHead->pblink;
+ }
+ if( pEntry == pHead )
+ {
+ pHead = pHead->pflink;
+ bSetHead = FALSE;
+ }
+ if( pEntry != pPredecessor )
+ {
+ pEntry->Unlink();
+ pEntry->SetBacklink( pPredecessor );
+ }
+ if( bSetHead )
+ pHead = pEntry;
+ pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET );
+ aAutoArrangeTimer.Start();
+}
+
+BOOL SvxIconChoiceCtrl_Impl::GetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
+ SvxIconChoiceCtrlEntry** ppPredecessor )
+{
+ *ppPredecessor = 0;
+ if( !pHead )
+ return FALSE;
+ DBG_ASSERT(pEntry->pblink,"GetEntryPredecessor: Backward link not set");
+ DBG_ASSERT(pEntry->pflink,"GetEntryPredecessor: Forward link not set");
+
+ if( pEntry == pHead )
+ {
+ SvxIconChoiceCtrlEntry* pFirst = (SvxIconChoiceCtrlEntry*)aEntries.GetObject(0);
+ if( pFirst != pEntry )
+ return TRUE;
+ return FALSE;
+ }
+ *ppPredecessor = pEntry->pblink;
+ if( !(pEntry->nFlags & ICNVIEW_FLAG_PRED_SET) &&
+ (GetEntryListPos( *ppPredecessor ) + 1) == GetEntryListPos( pEntry ))
+ return FALSE;
+ return TRUE;
+}
+
+SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
+ const Point& rPosTopLeft )
+{
+ Point aPos( rPosTopLeft ); //TopLeft
+ Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
+ Point aNewPos( aCenterRect.Center() );
+ ULONG nGrid = GetPredecessorGrid( aNewPos );
+ ULONG nCount = aEntries.Count();
+ if( nGrid == ULONG_MAX )
+ return 0;
+ if( nGrid >= nCount )
+ nGrid = nCount - 1;
+ if( !pHead )
+ return (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nGrid );
+
+ SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
+ // todo: Liste von hinten aufrollen wenn nGrid > nCount/2
+ for( ULONG nCur = 0; nCur < nGrid; nCur++ )
+ pCur = pCur->pflink;
+
+ return pCur;
+}
+
+ULONG SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
+{
+ Point aPos( rPos );
+ aPos.X() -= LROFFS_WINBORDER;
+ aPos.Y() -= TBOFFS_WINBORDER;
+ USHORT nMaxCol = (USHORT)(aVirtOutputSize.Width() / nGridDX);
+ if( nMaxCol )
+ nMaxCol--;
+ USHORT nGridX = (USHORT)(aPos.X() / nGridDX);
+ if( nGridX > nMaxCol )
+ nGridX = nMaxCol;
+ USHORT nGridY = (USHORT)(aPos.Y() / nGridDY);
+ USHORT nGridsX = (USHORT)(aOutputSize.Width() / nGridDX);
+ ULONG nGrid = (nGridY * nGridsX) + nGridX;
+ long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
+ if( rPos.X() < nMiddle )
+ {
+ if( !nGrid )
+ nGrid = ULONG_MAX;
+ else
+ nGrid--;
+ }
+ return nGrid;
+}
+
+void SvxIconChoiceCtrl_Impl::Flush()
+{
+ if( aAutoArrangeTimer.IsActive() )
+ {
+ AutoArrangeHdl( 0 );
+ }
+}
+
+BOOL SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) )
+ return FALSE;
+
+ Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
+ aPos -= pView->GetMapMode().GetOrigin();
+ SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, TRUE );
+
+ if ( !pEntry )
+ return FALSE;
+
+ String sQuickHelpText = pEntry->GetQuickHelpText();
+ String aEntryText( pView->GetEntryText( pEntry, FALSE ) );
+ Rectangle aTextRect( CalcTextRect( pEntry, 0, FALSE, &aEntryText ) );
+ if ( ( !aTextRect.IsInside( aPos ) || !aEntryText.Len() ) && !sQuickHelpText.Len() )
+ return FALSE;
+
+ Rectangle aOptTextRect( aTextRect );
+ aOptTextRect.Bottom() = LONG_MAX;
+ USHORT nNewFlags = nCurTextDrawFlags;
+ nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
+ aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
+ if ( aOptTextRect != aTextRect || sQuickHelpText.Len() > 0 )
+ {
+ //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
+ Point aPt( aOptTextRect.TopLeft() );
+ aPt += pView->GetMapMode().GetOrigin();
+ aPt = pView->OutputToScreenPixel( aPt );
+ // Border der Tiphilfe abziehen
+ aPt.Y() -= 1;
+ aPt.X() -= 3;
+ aOptTextRect.SetPos( aPt );
+ String sHelpText;
+ if ( sQuickHelpText.Len() > 0 )
+ sHelpText = sQuickHelpText;
+ else
+ sHelpText = aEntryText;
+ Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER );
+ }
+
+ return TRUE;
+}
+
+void SvxIconChoiceCtrl_Impl::ClearColumnList()
+{
+ if( !pColumns )
+ return;
+
+ const USHORT nCount = pColumns->Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlColumnInfo* pInfo = (SvxIconChoiceCtrlColumnInfo*)
+ pColumns->GetObject( nCur );
+ delete pInfo;
+ }
+ DELETEZ(pColumns);
+}
+
+void SvxIconChoiceCtrl_Impl::SetColumn( USHORT nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
+{
+ if( !pColumns )
+ pColumns = new SvPtrarr;
+ while( pColumns->Count() < nIndex + 1 )
+ pColumns->Insert( (void*)0, pColumns->Count() );
+
+ SvxIconChoiceCtrlColumnInfo* pInfo =
+ (SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject(nIndex);
+ if( !pInfo )
+ {
+ pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
+ pColumns->Insert( (void*)pInfo, nIndex );
+ }
+ else
+ {
+ delete pInfo;
+ pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
+ pColumns->Replace( pInfo, nIndex );
+ }
+
+ // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
+ // dieses Workaround bringts mit einer Spalte zum Fliegen
+ if( !nIndex && (nWinBits & WB_DETAILS) )
+ nGridDX = pInfo->GetWidth();
+
+ if( GetUpdateMode() )
+ Arrange( IsAutoArrange() );
+}
+
+const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( USHORT nIndex ) const
+{
+ if( !pColumns || nIndex >= pColumns->Count() )
+ return 0;
+ return (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nIndex );
+}
+
+const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetItemColumn( USHORT nSubItem,
+ long& rLeft ) const
+{
+ rLeft = 0;
+ if( !pColumns )
+ return 0;
+ const USHORT nCount = pColumns->Count();
+ const SvxIconChoiceCtrlColumnInfo* pCol = 0;
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ pCol = (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nCur );
+ if( !pCol || pCol->GetSubItem() == nSubItem )
+ return pCol;
+ rLeft += pCol->GetWidth();
+ }
+ return pCol;
+}
+
+void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
+ OutputDevice* pOut, const Rectangle& rBmpRect, BOOL bHide )
+{
+ Rectangle aBmpRect( rBmpRect );
+ long nBorder = 2;
+ if( aImageSize.Width() < 32 )
+ nBorder = 1;
+ aBmpRect.Right() += nBorder;
+ aBmpRect.Left() -= nBorder;
+ aBmpRect.Bottom() += nBorder;
+ aBmpRect.Top() -= nBorder;
+
+ if ( bHide )
+ pView->Invalidate( aBmpRect );
+ else
+ {
+ DecorationView aDecoView( pOut );
+ USHORT nDecoFlags;
+ if ( bHighlightFramePressed )
+ nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN;
+ else
+ nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT;
+ aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
+ BOOL bKeepHighlightFlags )
+{
+ if( pEntry == pCurHighlightFrame )
+ return;
+
+ if( !bKeepHighlightFlags )
+ bHighlightFramePressed = FALSE;
+
+ HideEntryHighlightFrame();
+ pCurHighlightFrame = pEntry;
+ if( pEntry )
+ {
+ Rectangle aBmpRect( CalcFocusRect(pEntry) );
+ DrawHighlightFrame( pView, aBmpRect, FALSE );
+ }
+}
+
+void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
+{
+ if( !pCurHighlightFrame )
+ return;
+
+ SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
+ pCurHighlightFrame = 0;
+ Rectangle aBmpRect( CalcFocusRect(pEntry) );
+ DrawHighlightFrame( pView, aBmpRect, TRUE );
+}
+
+void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* )
+{
+ // Bei aktiviertem Single-Click-Modus sollte der Selektionshandler
+ // synchron gerufen werden, weil die Selektion automatisch
+ // weggenommen wird, wenn der Mauszeiger nicht mehr das Objekt
+ // beruehrt. Es kann sonst zu fehlenden Select-Aufrufen kommen,
+ // wenn das Objekt aus einer Mausbewegung heraus selektiert wird,
+ // weil beim Ausloesen des Timers der Mauszeiger das Objekt u.U.
+ // schon verlassen hat.
+ // Fuer spezielle Faelle (=>SfxFileDialog!) koennen synchrone
+ // Aufrufe auch per WB_NOASYNCSELECTHDL erzwungen werden.
+ if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) )
+ {
+ pHdlEntry = 0;
+ pView->ClickIcon();
+ //pView->Select();
+ }
+ else
+ aCallSelectHdlTimer.Start();
+}
+
+IMPL_LINK( SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, void*, EMPTYARG )
+{
+ pHdlEntry = 0;
+ pView->ClickIcon();
+ //pView->Select();
+ return 0;
+}
+
+Point SvxIconChoiceCtrl_Impl::GetPopupMenuPosPixel() const
+{
+ Point aResult;
+ if( !GetSelectionCount() )
+ return aResult;
+
+ SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
+ if( !pEntry || !pEntry->IsSelected() )
+ {
+ ULONG nNext;
+ pEntry = GetFirstSelectedEntry( nNext );
+ }
+ if( pEntry )
+ {
+ Rectangle aRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( pEntry ) );
+ aResult = aRect.Center();
+ aResult = pView->GetPixelPos( aResult );
+ }
+ return aResult;
+}
+
+void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, BOOL bDoNotUpdateWallpaper )
+{
+ MapMode aMapMode( pView->GetMapMode() );
+ aMapMode.SetOrigin( rPos );
+ pView->SetMapMode( aMapMode );
+ if( !bDoNotUpdateWallpaper )
+ {
+ BOOL bScrollable = pView->GetBackground().IsScrollable();
+ if( pView->HasBackground() && !bScrollable )
+ {
+ Rectangle aRect( GetOutputRect());
+ Wallpaper aPaper( pView->GetBackground() );
+ aPaper.SetRect( aRect );
+ pView->SetBackground( aPaper );
+ }
+ }
+}
+
+ULONG SvxIconChoiceCtrl_Impl::GetGridCount( const Size& rSize, BOOL bCheckScrBars,
+ BOOL bSmartScrBar ) const
+{
+ Size aSize( rSize );
+ if( bCheckScrBars && aHorSBar.IsVisible() )
+ aSize.Height() -= nHorSBarHeight;
+ else if( bSmartScrBar && (nWinBits & WB_ALIGN_LEFT) )
+ aSize.Height() -= nHorSBarHeight;
+
+ if( bCheckScrBars && aVerSBar.IsVisible() )
+ aSize.Width() -= nVerSBarWidth;
+ else if( bSmartScrBar && (nWinBits & WB_ALIGN_TOP) )
+ aSize.Width() -= nVerSBarWidth;
+
+ if( aSize.Width() < 0 )
+ aSize.Width() = 0;
+ if( aSize.Height() < 0 )
+ aSize.Height() = 0;
+
+ return IcnGridMap_Impl::GetGridCount( aSize, (USHORT)nGridDX, (USHORT)nGridDY );
+}
+
+BOOL SvxIconChoiceCtrl_Impl::HandleShortCutKey( const KeyEvent& rKEvt )
+{
+ StopEditTimer();
+
+ BOOL bRet = FALSE;
+
+ DBG_ASSERT( rKEvt.GetKeyCode().IsMod2(), "*SvxIconChoiceCtrl_Impl::HandleShortCutKey(): no <ALT> pressed!?" );
+
+ sal_Unicode cChar = rKEvt.GetCharCode();
+ ULONG nPos = (ULONG)-1;
+
+ if( cChar && IsMnemonicChar( cChar, nPos ) )
+ {
+ // shortcut is clicked
+ SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
+ SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
+ if( pNewCursor != pOldCursor )
+ {
+ SetCursor_Impl( pOldCursor, pNewCursor, FALSE, FALSE, FALSE );
+
+ if( pNewCursor != NULL )
+ {
+ pHdlEntry = pNewCursor;
+ pCurHighlightFrame = pHdlEntry;
+ pView->ClickIcon();
+ pCurHighlightFrame = NULL;
+ }
+ }
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void SvxIconChoiceCtrl_Impl::CallEventListeners( ULONG nEvent, void* pData )
+{
+ pView->CallImplEventListeners( nEvent, pData );
+}
+
+
diff --git a/svtools/source/contnr/imivctl2.cxx b/svtools/source/contnr/imivctl2.cxx
new file mode 100644
index 000000000000..7cb92e8cef07
--- /dev/null
+++ b/svtools/source/contnr/imivctl2.cxx
@@ -0,0 +1,848 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+#include "imivctl.hxx"
+
+IcnCursor_Impl::IcnCursor_Impl( SvxIconChoiceCtrl_Impl* pOwner )
+{
+ pView = pOwner;
+ pColumns = 0;
+ pRows = 0;
+ pCurEntry = 0;
+ nDeltaWidth = 0;
+ nDeltaHeight= 0;
+ nCols = 0;
+ nRows = 0;
+}
+
+IcnCursor_Impl::~IcnCursor_Impl()
+{
+ delete[] pColumns;
+ delete[] pRows;
+}
+
+USHORT IcnCursor_Impl::GetSortListPos( SvPtrarr* pList, long nValue,
+ int bVertical )
+{
+ USHORT nCount = (USHORT)pList->Count();
+ if( !nCount )
+ return 0;
+
+ USHORT nCurPos = 0;
+ long nPrevValue = LONG_MIN;
+ while( nCount )
+ {
+ const Rectangle& rRect=
+ pView->GetEntryBoundRect((SvxIconChoiceCtrlEntry*)(pList->GetObject(nCurPos)));
+ long nCurValue;
+ if( bVertical )
+ nCurValue = rRect.Top();
+ else
+ nCurValue = rRect.Left();
+ if( nValue >= nPrevValue && nValue <= nCurValue )
+ return (USHORT)nCurPos;
+ nPrevValue = nCurValue;
+ nCount--;
+ nCurPos++;
+ }
+ return pList->Count();
+}
+
+void IcnCursor_Impl::ImplCreate()
+{
+ pView->CheckBoundingRects();
+ DBG_ASSERT(pColumns==0&&pRows==0,"ImplCreate: Not cleared");
+
+ SetDeltas();
+
+ pColumns = new SvPtrarr[ nCols ];
+ pRows = new SvPtrarr[ nRows ];
+
+ ULONG nCount = pView->aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur );
+ // const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ Rectangle rRect( pView->CalcBmpRect( pEntry,0 ) );
+ short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight );
+ short nX = (short)( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth );
+
+ // Rundungsfehler abfangen
+ if( nY >= nRows )
+ nY = sal::static_int_cast< short >(nRows - 1);
+ if( nX >= nCols )
+ nX = sal::static_int_cast< short >(nCols - 1);
+
+ USHORT nIns = GetSortListPos( &pColumns[nX], rRect.Top(), TRUE );
+ pColumns[ nX ].Insert( pEntry, nIns );
+
+ nIns = GetSortListPos( &pRows[nY], rRect.Left(), FALSE );
+ pRows[ nY ].Insert( pEntry, nIns );
+
+ pEntry->nX = nX;
+ pEntry->nY = nY;
+ }
+}
+
+
+
+
+void IcnCursor_Impl::Clear()
+{
+ if( pColumns )
+ {
+ delete[] pColumns;
+ delete[] pRows;
+ pColumns = 0;
+ pRows = 0;
+ pCurEntry = 0;
+ nDeltaWidth = 0;
+ nDeltaHeight = 0;
+ }
+}
+
+SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchCol(USHORT nCol,USHORT nTop,USHORT nBottom,
+ USHORT, BOOL bDown, BOOL bSimple )
+{
+ DBG_ASSERT(pCurEntry,"SearchCol: No reference entry");
+ SvPtrarr* pList = &(pColumns[ nCol ]);
+ const USHORT nCount = pList->Count();
+ if( !nCount )
+ return 0;
+
+ const Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry);
+
+ if( bSimple )
+ {
+ USHORT nListPos = pList->GetPos( pCurEntry );
+ DBG_ASSERT(nListPos!=0xffff,"Entry not in Col-List");
+ if( bDown )
+ {
+ while( nListPos < nCount-1 )
+ {
+ nListPos++;
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos );
+ const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ if( rRect.Top() > rRefRect.Top() )
+ return pEntry;
+ }
+ return 0;
+ }
+ else
+ {
+ while( nListPos )
+ {
+ nListPos--;
+ if( nListPos < nCount )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos );
+ const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ if( rRect.Top() < rRefRect.Top() )
+ return pEntry;
+ }
+ }
+ return 0;
+ }
+ }
+
+ if( nTop > nBottom )
+ {
+ USHORT nTemp = nTop;
+ nTop = nBottom;
+ nBottom = nTemp;
+ }
+ long nMinDistance = LONG_MAX;
+ SvxIconChoiceCtrlEntry* pResult = 0;
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pList->GetObject( nCur ));
+ if( pEntry != pCurEntry )
+ {
+ USHORT nY = pEntry->nY;
+ if( nY >= nTop && nY <= nBottom )
+ {
+ const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ long nDistance = rRect.Top() - rRefRect.Top();
+ if( nDistance < 0 )
+ nDistance *= -1;
+ if( nDistance && nDistance < nMinDistance )
+ {
+ nMinDistance = nDistance;
+ pResult = pEntry;
+ }
+ }
+ }
+ }
+ return pResult;
+}
+
+SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchRow(USHORT nRow,USHORT nLeft,USHORT nRight,
+ USHORT, BOOL bRight, BOOL bSimple )
+{
+ DBG_ASSERT(pCurEntry,"SearchRow: No reference entry");
+ SvPtrarr* pList = &(pRows[ nRow ]);
+ const USHORT nCount = pList->Count();
+ if( !nCount )
+ return 0;
+
+ const Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry);
+
+ if( bSimple )
+ {
+ USHORT nListPos = pList->GetPos( pCurEntry );
+ DBG_ASSERT(nListPos!=0xffff,"Entry not in Row-List");
+ if( bRight )
+ {
+ while( nListPos < nCount-1 )
+ {
+ nListPos++;
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos );
+ const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ if( rRect.Left() > rRefRect.Left() )
+ return pEntry;
+ }
+ return 0;
+ }
+ else
+ {
+ while( nListPos )
+ {
+ nListPos--;
+ if( nListPos < nCount )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos );
+ const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ if( rRect.Left() < rRefRect.Left() )
+ return pEntry;
+ }
+ }
+ return 0;
+ }
+
+ }
+ if( nRight < nLeft )
+ {
+ USHORT nTemp = nRight;
+ nRight = nLeft;
+ nLeft = nTemp;
+ }
+ long nMinDistance = LONG_MAX;
+ SvxIconChoiceCtrlEntry* pResult = 0;
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pList->GetObject( nCur ));
+ if( pEntry != pCurEntry )
+ {
+ USHORT nX = pEntry->nX;
+ if( nX >= nLeft && nX <= nRight )
+ {
+ const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ long nDistance = rRect.Left() - rRefRect.Left();
+ if( nDistance < 0 )
+ nDistance *= -1;
+ if( nDistance && nDistance < nMinDistance )
+ {
+ nMinDistance = nDistance;
+ pResult = pEntry;
+ }
+ }
+ }
+ }
+ return pResult;
+}
+
+
+
+/*
+ Sucht ab dem uebergebenen Eintrag den naechsten rechts- bzw.
+ linksstehenden. Suchverfahren am Beispiel bRight = TRUE:
+
+ c
+ b c
+ a b c
+ S 1 1 1 ====> Suchrichtung
+ a b c
+ b c
+ c
+
+ S : Startposition
+ 1 : erstes Suchrechteck
+ a,b,c : 2., 3., 4. Suchrechteck
+*/
+
+SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pCtrlEntry, BOOL bRight )
+{
+ SvxIconChoiceCtrlEntry* pResult;
+ pCurEntry = pCtrlEntry;
+ Create();
+ USHORT nY = pCtrlEntry->nY;
+ USHORT nX = pCtrlEntry->nX;
+ DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column");
+ DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row");
+ // Nachbar auf gleicher Zeile ?
+ if( bRight )
+ pResult = SearchRow(
+ nY, nX, sal::static_int_cast< USHORT >(nCols-1), nX, TRUE, TRUE );
+ else
+ pResult = SearchRow( nY, nX ,0, nX, FALSE, TRUE );
+ if( pResult )
+ return pResult;
+
+ long nCurCol = nX;
+
+ long nColOffs, nLastCol;
+ if( bRight )
+ {
+ nColOffs = 1;
+ nLastCol = nCols;
+ }
+ else
+ {
+ nColOffs = -1;
+ nLastCol = -1; // 0-1
+ }
+
+ USHORT nRowMin = nY;
+ USHORT nRowMax = nY;
+ do
+ {
+ SvxIconChoiceCtrlEntry* pEntry = SearchCol((USHORT)nCurCol,nRowMin,nRowMax,nY,TRUE, FALSE);
+ if( pEntry )
+ return pEntry;
+ if( nRowMin )
+ nRowMin--;
+ if( nRowMax < (nRows-1))
+ nRowMax++;
+ nCurCol += nColOffs;
+ } while( nCurCol != nLastCol );
+ return 0;
+}
+
+SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoPageUpDown( SvxIconChoiceCtrlEntry* pStart, BOOL bDown)
+{
+ if( pView->IsAutoArrange() && !(pView->nWinBits & WB_ALIGN_TOP) )
+ {
+ const long nPos = (long)pView->GetEntryListPos( pStart );
+ long nEntriesInView = (pView->aOutputSize.Height() / pView->nGridDY);
+ nEntriesInView *=
+ ((pView->aOutputSize.Width()+(pView->nGridDX/2)) / pView->nGridDX );
+ long nNewPos = nPos;
+ if( bDown )
+ {
+ nNewPos += nEntriesInView;
+ if( nNewPos >= (long)pView->aEntries.Count() )
+ nNewPos = pView->aEntries.Count() - 1;
+ }
+ else
+ {
+ nNewPos -= nEntriesInView;
+ if( nNewPos < 0 )
+ nNewPos = 0;
+ }
+ if( nPos != nNewPos )
+ return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( (ULONG)nNewPos );
+ return 0;
+ }
+ long nOpt = pView->GetEntryBoundRect( pStart ).Top();
+ if( bDown )
+ {
+ nOpt += pView->aOutputSize.Height();
+ nOpt -= pView->nGridDY;
+ }
+ else
+ {
+ nOpt -= pView->aOutputSize.Height();
+ nOpt += pView->nGridDY;
+ }
+ if( nOpt < 0 )
+ nOpt = 0;
+
+ long nPrevErr = LONG_MAX;
+
+ SvxIconChoiceCtrlEntry* pPrev = pStart;
+ SvxIconChoiceCtrlEntry* pNext = GoUpDown( pStart, bDown );
+ while( pNext )
+ {
+ long nCur = pView->GetEntryBoundRect( pNext ).Top();
+ long nErr = nOpt - nCur;
+ if( nErr < 0 )
+ nErr *= -1;
+ if( nErr > nPrevErr )
+ return pPrev;
+ nPrevErr = nErr;
+ pPrev = pNext;
+ pNext = GoUpDown( pNext, bDown );
+ }
+ if( pPrev != pStart )
+ return pPrev;
+ return 0;
+}
+
+SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pCtrlEntry, BOOL bDown)
+{
+ if( pView->IsAutoArrange() && !(pView->nWinBits & WB_ALIGN_TOP) )
+ {
+ ULONG nPos = pView->GetEntryListPos( pCtrlEntry );
+ if( bDown && nPos < (pView->aEntries.Count() - 1) )
+ return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nPos + 1 );
+ else if( !bDown && nPos > 0 )
+ return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nPos - 1 );
+ return 0;
+ }
+
+ SvxIconChoiceCtrlEntry* pResult;
+ pCurEntry = pCtrlEntry;
+ Create();
+ USHORT nY = pCtrlEntry->nY;
+ USHORT nX = pCtrlEntry->nX;
+ DBG_ASSERT(nY<nRows,"GoUpDown:Bad column");
+ DBG_ASSERT(nX<nCols,"GoUpDown:Bad row");
+
+ // Nachbar in gleicher Spalte ?
+ if( bDown )
+ pResult = SearchCol(
+ nX, nY, sal::static_int_cast< USHORT >(nRows-1), nY, TRUE, TRUE );
+ else
+ pResult = SearchCol( nX, nY ,0, nY, FALSE, TRUE );
+ if( pResult )
+ return pResult;
+
+ long nCurRow = nY;
+
+ long nRowOffs, nLastRow;
+ if( bDown )
+ {
+ nRowOffs = 1;
+ nLastRow = nRows;
+ }
+ else
+ {
+ nRowOffs = -1;
+ nLastRow = -1; // 0-1
+ }
+
+ USHORT nColMin = nX;
+ USHORT nColMax = nX;
+ do
+ {
+ SvxIconChoiceCtrlEntry* pEntry = SearchRow((USHORT)nCurRow,nColMin,nColMax,nX,TRUE, FALSE);
+ if( pEntry )
+ return pEntry;
+ if( nColMin )
+ nColMin--;
+ if( nColMax < (nCols-1))
+ nColMax++;
+ nCurRow += nRowOffs;
+ } while( nCurRow != nLastRow );
+ return 0;
+}
+
+void IcnCursor_Impl::SetDeltas()
+{
+ const Size& rSize = pView->aVirtOutputSize;
+ nCols = rSize.Width() / pView->nGridDX;
+ if( !nCols )
+ nCols = 1;
+ nRows = rSize.Height() / pView->nGridDY;
+ if( (nRows * pView->nGridDY) < rSize.Height() )
+ nRows++;
+ if( !nRows )
+ nRows = 1;
+
+ nDeltaWidth = (short)(rSize.Width() / nCols);
+ nDeltaHeight = (short)(rSize.Height() / nRows);
+ if( !nDeltaHeight )
+ {
+ nDeltaHeight = 1;
+ DBG_WARNING("SetDeltas:Bad height");
+ }
+ if( !nDeltaWidth )
+ {
+ nDeltaWidth = 1;
+ DBG_WARNING("SetDeltas:Bad width");
+ }
+}
+
+void IcnCursor_Impl::CreateGridAjustData( SvPtrarr& rLists, SvxIconChoiceCtrlEntry* pRefEntry)
+{
+ if( !pRefEntry )
+ {
+ USHORT nGridRows = (USHORT)(pView->aVirtOutputSize.Height() / pView->nGridDY);
+ nGridRows++; // wg. Abrundung!
+
+ if( !nGridRows )
+ return;
+ for( USHORT nCurList = 0; nCurList < nGridRows; nCurList++ )
+ {
+ SvPtrarr* pRow = new SvPtrarr;
+ rLists.Insert( (void*)pRow, nCurList );
+ }
+ const ULONG nCount = pView->aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur );
+ const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
+ USHORT nIns = GetSortListPos((SvPtrarr*)rLists[nY],rRect.Left(),FALSE);
+ ((SvPtrarr*)rLists[ nY ])->Insert( pEntry, nIns );
+ }
+ }
+ else
+ {
+ // Aufbau eines hor. "Schlauchs" auf der RefEntry-Zeile
+ // UEBERLEGEN: BoundingRect nehmen wg. Ueberlappungen???
+ Rectangle rRefRect( pView->CalcBmpRect( pRefEntry ) );
+ //const Rectangle& rRefRect = pView->GetEntryBoundRect( pRefEntry );
+ short nRefRow = (short)( ((rRefRect.Top()+rRefRect.Bottom())/2) / pView->nGridDY );
+ SvPtrarr* pRow = new SvPtrarr;
+ rLists.Insert( (void*)pRow, 0 );
+ ULONG nCount = pView->aEntries.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur );
+ Rectangle rRect( pView->CalcBmpRect(pEntry) );
+ //const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
+ short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
+ if( nY == nRefRow )
+ {
+ USHORT nIns = GetSortListPos( pRow, rRect.Left(), FALSE );
+ pRow->Insert( pEntry, nIns );
+ }
+ }
+ }
+}
+
+//static
+void IcnCursor_Impl::DestroyGridAdjustData( SvPtrarr& rLists )
+{
+ const USHORT nCount = rLists.Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvPtrarr* pArr = (SvPtrarr*)rLists[ nCur ];
+ delete pArr;
+ }
+ rLists.Remove( 0, rLists.Count() );
+}
+
+IcnGridMap_Impl::IcnGridMap_Impl(SvxIconChoiceCtrl_Impl* pView)
+{
+ _pView = pView;
+ _pGridMap = 0;
+ _nGridCols = 0;
+ _nGridRows = 0;
+}
+
+IcnGridMap_Impl::~IcnGridMap_Impl()
+{
+ delete[] _pGridMap, _pGridMap=0;
+}
+
+void IcnGridMap_Impl::Expand()
+{
+ if( !_pGridMap )
+ Create_Impl();
+ else
+ {
+ USHORT nNewGridRows = _nGridRows;
+ USHORT nNewGridCols = _nGridCols;
+ if( _pView->nWinBits & WB_ALIGN_TOP )
+ nNewGridRows += 50;
+ else
+ nNewGridCols += 50;
+
+ BOOL* pNewGridMap = new BOOL[nNewGridRows*nNewGridCols];
+ memset( pNewGridMap, 0, nNewGridRows * nNewGridCols * sizeof(BOOL) );
+ memcpy( pNewGridMap, _pGridMap, _nGridRows * _nGridCols * sizeof(BOOL) );
+ delete[] _pGridMap;
+ _pGridMap = pNewGridMap;
+ _nGridRows = nNewGridRows;
+ _nGridCols = nNewGridCols;
+ }
+}
+
+void IcnGridMap_Impl::Create_Impl()
+{
+ DBG_ASSERT(!_pGridMap,"Unnecessary call to IcnGridMap_Impl::Create_Impl()");
+ if( _pGridMap )
+ return;
+ GetMinMapSize( _nGridCols, _nGridRows );
+ if( _pView->nWinBits & WB_ALIGN_TOP )
+ _nGridRows += 50; // avoid resize of gridmap too often
+ else
+ _nGridCols += 50;
+
+ _pGridMap = new BOOL[ _nGridRows * _nGridCols];
+ memset( (void*)_pGridMap, 0, _nGridRows * _nGridCols );
+
+ const ULONG nCount = _pView->aEntries.Count();
+ for( ULONG nCur=0; nCur < nCount; nCur++ )
+ OccupyGrids( (SvxIconChoiceCtrlEntry*)_pView->aEntries.GetObject( nCur ));
+}
+
+void IcnGridMap_Impl::GetMinMapSize( USHORT& rDX, USHORT& rDY ) const
+{
+ long nX, nY;
+ if( _pView->nWinBits & WB_ALIGN_TOP )
+ {
+ // The view grows in vertical direction. Its max. width is _pView->nMaxVirtWidth
+ nX = _pView->nMaxVirtWidth;
+ if( !nX )
+ nX = _pView->pView->GetOutputSizePixel().Width();
+ if( !(_pView->nFlags & F_ARRANGING) )
+ nX -= _pView->nVerSBarWidth;
+
+ nY = _pView->aVirtOutputSize.Height();
+ }
+ else
+ {
+ // The view grows in horizontal direction. Its max. height is _pView->nMaxVirtHeight
+ nY = _pView->nMaxVirtHeight;
+ if( !nY )
+ nY = _pView->pView->GetOutputSizePixel().Height();
+ if( !(_pView->nFlags & F_ARRANGING) )
+ nY -= _pView->nHorSBarHeight;
+ nX = _pView->aVirtOutputSize.Width();
+ }
+
+ if( !nX )
+ nX = DEFAULT_MAX_VIRT_WIDTH;
+ if( !nY )
+ nY = DEFAULT_MAX_VIRT_HEIGHT;
+
+ long nDX = nX / _pView->nGridDX;
+ long nDY = nY / _pView->nGridDY;
+
+ if( !nDX )
+ nDX++;
+ if( !nDY )
+ nDY++;
+
+ rDX = (USHORT)nDX;
+ rDY = (USHORT)nDY;
+}
+
+GridId IcnGridMap_Impl::GetGrid( USHORT nGridX, USHORT nGridY )
+{
+ Create();
+ if( _pView->nWinBits & WB_ALIGN_TOP )
+ return nGridX + ( nGridY * _nGridCols );
+ else
+ return nGridY + ( nGridX * _nGridRows );
+}
+
+GridId IcnGridMap_Impl::GetGrid( const Point& rDocPos, BOOL* pbClipped )
+{
+ Create();
+
+ long nX = rDocPos.X();
+ long nY = rDocPos.Y();
+ nX -= LROFFS_WINBORDER;
+ nY -= TBOFFS_WINBORDER;
+ nX /= _pView->nGridDX;
+ nY /= _pView->nGridDY;
+ BOOL bClipped = FALSE;
+ if( nX >= _nGridCols )
+ {
+ nX = _nGridCols - 1;
+ bClipped = TRUE;
+ }
+ if( nY >= _nGridRows )
+ {
+ nY = _nGridRows - 1;
+ bClipped = TRUE;
+ }
+ GridId nId = GetGrid( (USHORT)nX, (USHORT)nY );
+ if( pbClipped )
+ *pbClipped = bClipped;
+ DBG_ASSERT(nId <(ULONG)(_nGridCols*_nGridRows),"GetGrid failed");
+ return nId;
+}
+
+Rectangle IcnGridMap_Impl::GetGridRect( GridId nId )
+{
+ Create();
+ USHORT nGridX, nGridY;
+ GetGridCoord( nId, nGridX, nGridY );
+ const long nLeft = nGridX * _pView->nGridDX+ LROFFS_WINBORDER;
+ const long nTop = nGridY * _pView->nGridDY + TBOFFS_WINBORDER;
+ return Rectangle(
+ nLeft, nTop,
+ nLeft + _pView->nGridDX,
+ nTop + _pView->nGridDY );
+}
+
+GridId IcnGridMap_Impl::GetUnoccupiedGrid( BOOL bOccupyFound )
+{
+ Create();
+ ULONG nStart = 0;
+ BOOL bExpanded = FALSE;
+
+ while( 1 )
+ {
+ const ULONG nCount = (USHORT)(_nGridCols * _nGridRows);
+ for( ULONG nCur = nStart; nCur < nCount; nCur++ )
+ {
+ if( !_pGridMap[ nCur ] )
+ {
+ if( bOccupyFound )
+ _pGridMap[ nCur ] = TRUE;
+ return (GridId)nCur;
+ }
+ }
+ DBG_ASSERT(!bExpanded,"ExpandGrid failed");
+ if( bExpanded )
+ return 0; // prevent never ending loop
+ bExpanded = TRUE;
+ Expand();
+ nStart = nCount;
+ }
+}
+
+// ein Eintrag belegt nur das unter seinem Zentrum liegende GridRect
+// diese Variante ist bedeutend schneller als die Belegung ueber das
+// Bounding-Rect, kann aber zu kleinen Ueberlappungen fuehren
+#define OCCUPY_CENTER
+
+void IcnGridMap_Impl::OccupyGrids( const SvxIconChoiceCtrlEntry* pEntry, BOOL bOccupy )
+{
+ if( !_pGridMap || !_pView->IsBoundingRectValid( pEntry->aRect ))
+ return;
+#ifndef OCCUPY_CENTER
+ OccupyGrids( pEntry->aRect, bOccupy );
+#else
+ OccupyGrid( GetGrid( pEntry->aRect.Center()), bOccupy );
+#endif
+
+}
+
+void IcnGridMap_Impl::OccupyGrids( const Rectangle& rRect, BOOL bUsed )
+{
+ if( !_pGridMap )
+ return;
+
+ if( bUsed )
+ {
+ if( _aLastOccupiedGrid == rRect )
+ return;
+ _aLastOccupiedGrid = rRect;
+ }
+ else
+ _aLastOccupiedGrid.SetEmpty();
+
+ BOOL bTopLeftClipped, bBottomRightClipped;
+ GridId nIdTL = GetGrid( rRect.TopLeft(), &bTopLeftClipped );
+ GridId nIdBR = GetGrid( rRect.BottomRight(), &bBottomRightClipped );
+
+ if( bTopLeftClipped && bBottomRightClipped )
+ return;
+
+ USHORT nX1,nX2,nY1,nY2;
+ GetGridCoord( nIdTL, nX1, nY1 );
+ GetGridCoord( nIdBR, nX2, nY2 );
+ USHORT nTemp;
+ if( nX1 > nX2 )
+ {
+ nTemp = nX1;
+ nX1 = nX2;
+ nX2 = nTemp;
+ }
+ if( nY1 > nY2 )
+ {
+ nTemp = nY1;
+ nY1 = nY2;
+ nY2 = nTemp;
+ }
+ for( ; nX1 <= nX2; nX1++ )
+ for( ; nY1 <= nY2; nY1++ )
+ OccupyGrid( GetGrid( nX1, nY1 ) );
+}
+
+void IcnGridMap_Impl::Clear()
+{
+ if( _pGridMap )
+ {
+ delete[] _pGridMap, _pGridMap=0;
+ _nGridRows = 0;
+ _nGridCols = 0;
+ _aLastOccupiedGrid.SetEmpty();
+ }
+}
+
+ULONG IcnGridMap_Impl::GetGridCount( const Size& rSizePixel, USHORT nDX, USHORT nDY)
+{
+ long ndx = (rSizePixel.Width() - LROFFS_WINBORDER) / nDX;
+ if( ndx < 0 ) ndx *= -1;
+ long ndy = (rSizePixel.Height() - TBOFFS_WINBORDER) / nDY;
+ if( ndy < 0 ) ndy *= -1;
+ return (ULONG)(ndx * ndy);
+}
+
+void IcnGridMap_Impl::OutputSizeChanged()
+{
+ if( _pGridMap )
+ {
+ USHORT nCols, nRows;
+ GetMinMapSize( nCols, nRows );
+ if( _pView->nWinBits & WB_ALIGN_TOP )
+ {
+ if( nCols != _nGridCols )
+ Clear();
+ else if( nRows >= _nGridRows )
+ Expand();
+ }
+ else
+ {
+ if( nRows != _nGridRows )
+ Clear();
+ else if( nCols >= _nGridCols )
+ Expand();
+ }
+ }
+}
+
+// Independendly of the views alignment (TOP or LEFT) the gridmap
+// should contain the data in a continues region, to make it possible
+// to copy the whole block if the gridmap needs to be expanded.
+void IcnGridMap_Impl::GetGridCoord( GridId nId, USHORT& rGridX, USHORT& rGridY )
+{
+ Create();
+ if( _pView->nWinBits & WB_ALIGN_TOP )
+ {
+ rGridX = (USHORT)(nId % _nGridCols);
+ rGridY = (USHORT)(nId / _nGridCols);
+ }
+ else
+ {
+ rGridX = (USHORT)(nId / _nGridRows);
+ rGridY = (USHORT)(nId % _nGridRows);
+ }
+}
+
+
+
diff --git a/svtools/source/contnr/ivctrl.cxx b/svtools/source/contnr/ivctrl.cxx
new file mode 100644
index 000000000000..dae3abbac966
--- /dev/null
+++ b/svtools/source/contnr/ivctrl.cxx
@@ -0,0 +1,642 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+#ifndef GCC
+#endif
+
+#include "ivctrl.hxx"
+#include "imivctl.hxx"
+#include <vcl/bitmapex.hxx>
+#include <vcl/controllayout.hxx>
+#include <vcl/mnemonic.hxx>
+using namespace ::com::sun::star::accessibility;
+
+/*****************************************************************************
+|
+| class : SvxIconChoiceCtrlEntry
+|
+\*****************************************************************************/
+
+SvxIconChoiceCtrlEntry::SvxIconChoiceCtrlEntry( const String& rText, const Image& rImage, USHORT _nFlags )
+{
+ aText = rText;
+ aImage = rImage;
+ aImageHC = rImage;
+ pUserData = NULL;
+
+ nFlags = _nFlags;
+ eTextMode = IcnShowTextShort;
+ pblink = 0;
+ pflink = 0;
+}
+
+SvxIconChoiceCtrlEntry::SvxIconChoiceCtrlEntry( const String& rText, const Image& rImage, const Image& rImageHC, USHORT _nFlags )
+{
+ aText = rText;
+ aImage = rImage;
+ aImageHC = rImageHC;
+ pUserData = NULL;
+
+ nFlags = _nFlags;
+ eTextMode = IcnShowTextShort;
+ pblink = 0;
+ pflink = 0;
+}
+
+SvxIconChoiceCtrlEntry::SvxIconChoiceCtrlEntry( USHORT _nFlags )
+{
+ pUserData = NULL;
+
+ nFlags = _nFlags;
+ eTextMode = IcnShowTextShort;
+ pblink = 0;
+ pflink = 0;
+}
+
+void SvxIconChoiceCtrlEntry::SetMoved( BOOL bMoved )
+{
+ if( bMoved )
+ nFlags |= ICNVIEW_FLAG_POS_MOVED;
+ else
+ nFlags &= ~ICNVIEW_FLAG_POS_MOVED;
+}
+
+void SvxIconChoiceCtrlEntry::LockPos( BOOL bLock )
+{
+ if( bLock )
+ nFlags |= ICNVIEW_FLAG_POS_LOCKED;
+ else
+ nFlags &= ~ICNVIEW_FLAG_POS_LOCKED;
+}
+
+/*sal_Unicode SvxIconChoiceCtrlEntry::GetMnemonicChar() const
+{
+ sal_Unicode cChar = 0;
+ xub_StrLen nPos = aText.Search( '~' );
+ if ( nPos != STRING_NOTFOUND && nPos < ( aText.Len() ) - 1 )
+ cChar = aText.GetChar( nPos + 1 );
+ return cChar;
+}*/
+
+String SvxIconChoiceCtrlEntry::GetDisplayText() const
+{
+ return MnemonicGenerator::EraseAllMnemonicChars( aText );
+}
+
+// ----------------------------------------------------------------------------
+
+SvxIconChoiceCtrlColumnInfo::SvxIconChoiceCtrlColumnInfo( const SvxIconChoiceCtrlColumnInfo& rInfo )
+ : aColText( rInfo.aColText ), aColImage( rInfo.aColImage )
+{
+ nWidth = rInfo.nWidth;
+ eAlignment = rInfo.eAlignment;
+ nSubItem = rInfo.nSubItem;
+}
+
+/*****************************************************************************
+|
+| class : SvtIconChoiceCtrl
+|
+\*****************************************************************************/
+
+SvtIconChoiceCtrl::SvtIconChoiceCtrl( Window* pParent, WinBits nWinStyle ) :
+
+ // WB_CLIPCHILDREN an, da ScrollBars auf dem Fenster liegen!
+ Control( pParent, nWinStyle | WB_CLIPCHILDREN ),
+
+ _pCurKeyEvent ( NULL ),
+ _pImp ( new SvxIconChoiceCtrl_Impl( this, nWinStyle ) ),
+ _bAutoFontColor ( FALSE )
+
+{
+ SetLineColor();
+ _pImp->SetGrid( Size( 100, 70 ) );
+ _pImp->InitSettings();
+ _pImp->SetPositionMode( IcnViewPositionModeAutoArrange );
+}
+
+SvtIconChoiceCtrl::SvtIconChoiceCtrl( Window* pParent, const ResId& rResId ) :
+
+ Control( pParent, rResId ),
+
+ _pCurKeyEvent ( NULL ),
+ _pImp ( new SvxIconChoiceCtrl_Impl( this, WB_BORDER ) ),
+ _bAutoFontColor ( FALSE )
+
+{
+ SetLineColor();
+ _pImp->SetGrid( Size( 100, 70 ) );
+ _pImp->InitSettings();
+ _pImp->SetPositionMode( IcnViewPositionModeAutoArrange );
+}
+
+SvtIconChoiceCtrl::~SvtIconChoiceCtrl()
+{
+ _pImp->CallEventListeners( VCLEVENT_OBJECT_DYING );
+ delete _pImp;
+}
+
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::InsertEntry( ULONG nPos, const Point* pPos, USHORT nFlags )
+{
+ SvxIconChoiceCtrlEntry* pEntry = new SvxIconChoiceCtrlEntry( nFlags );
+ _pImp->InsertEntry( pEntry, nPos, pPos );
+ return pEntry;
+}
+
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::InsertEntry( const String& rText, const Image& rImage, ULONG nPos, const Point* pPos, USHORT nFlags )
+{
+ SvxIconChoiceCtrlEntry* pEntry = new SvxIconChoiceCtrlEntry( rText, rImage, nFlags);
+
+ _pImp->InsertEntry( pEntry, nPos, pPos );
+
+ return pEntry;
+}
+
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::InsertEntry( const String& rText, const Image& rImage, const Image& rImageHC, ULONG nPos, const Point* pPos, USHORT nFlags )
+{
+ SvxIconChoiceCtrlEntry* pEntry = new SvxIconChoiceCtrlEntry( rText, rImage, rImageHC, nFlags);
+
+ _pImp->InsertEntry( pEntry, nPos, pPos );
+
+ return pEntry;
+}
+
+BOOL SvtIconChoiceCtrl::EditedEntry( SvxIconChoiceCtrlEntry*, const XubString&, BOOL )
+{
+ return TRUE;
+}
+BOOL SvtIconChoiceCtrl::EditingEntry( SvxIconChoiceCtrlEntry* )
+{
+ return TRUE;
+}
+void SvtIconChoiceCtrl::DrawEntryImage( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, OutputDevice& rDev )
+{
+ rDev.DrawImage( rPos, GetSettings().GetStyleSettings().GetHighContrastMode() ? pEntry->GetImageHC() : pEntry->GetImage() );
+}
+String SvtIconChoiceCtrl::GetEntryText( SvxIconChoiceCtrlEntry* pEntry, BOOL )
+{
+ return pEntry->GetText();
+}
+BOOL SvtIconChoiceCtrl::HasBackground() const
+{
+ return FALSE;
+}
+BOOL SvtIconChoiceCtrl::HasFont() const
+{
+ return FALSE;
+}
+BOOL SvtIconChoiceCtrl::HasFontTextColor() const
+{
+ return TRUE;
+}
+BOOL SvtIconChoiceCtrl::HasFontFillColor() const
+{
+ return TRUE;
+}
+
+void SvtIconChoiceCtrl::Paint( const Rectangle& rRect )
+{
+ _pImp->Paint( rRect );
+}
+
+void SvtIconChoiceCtrl::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if( !_pImp->MouseButtonDown( rMEvt ) )
+ Control::MouseButtonDown( rMEvt );
+}
+
+void SvtIconChoiceCtrl::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if( !_pImp->MouseButtonUp( rMEvt ) )
+ Control::MouseButtonUp( rMEvt );
+}
+
+void SvtIconChoiceCtrl::MouseMove( const MouseEvent& rMEvt )
+{
+ if( !_pImp->MouseMove( rMEvt ) )
+ Control::MouseMove( rMEvt );
+}
+void SvtIconChoiceCtrl::ArrangeIcons()
+{
+ if ( GetStyle() & WB_ALIGN_TOP )
+ {
+ Size aFullSize;
+ Rectangle aEntryRect;
+
+ for ( ULONG i = 0; i < GetEntryCount(); i++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = GetEntry ( i );
+ aEntryRect = _pImp->GetEntryBoundRect ( pEntry );
+
+ aFullSize.setWidth ( aFullSize.getWidth()+aEntryRect.GetWidth() );
+ }
+
+ _pImp->Arrange ( FALSE, aFullSize.getWidth() );
+ }
+ else if ( GetStyle() & WB_ALIGN_LEFT )
+ {
+ Size aFullSize;
+ Rectangle aEntryRect;
+
+ for ( ULONG i = 0; i < GetEntryCount(); i++ )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = GetEntry ( i );
+ aEntryRect = _pImp->GetEntryBoundRect ( pEntry );
+
+ aFullSize.setHeight ( aFullSize.getHeight()+aEntryRect.GetHeight() );
+ }
+
+ _pImp->Arrange ( FALSE, 0, aFullSize.getHeight() );
+ }
+ else
+ {
+ _pImp->Arrange();
+ }
+ _pImp->Arrange( FALSE, 0, 1000 );
+}
+void SvtIconChoiceCtrl::Resize()
+{
+ _pImp->Resize();
+ Control::Resize();
+}
+
+Point SvtIconChoiceCtrl::GetLogicPos( const Point& rPosPixel ) const
+{
+ Point aPos( rPosPixel );
+ aPos -= GetMapMode().GetOrigin();
+ return aPos;
+}
+
+Point SvtIconChoiceCtrl::GetPixelPos( const Point& rPosLogic ) const
+{
+ Point aPos( rPosLogic );
+ aPos += GetMapMode().GetOrigin();
+ return aPos;
+}
+
+void SvtIconChoiceCtrl::DocumentRectChanged()
+{
+ _aDocRectChangedHdl.Call( this );
+}
+
+void SvtIconChoiceCtrl::VisibleRectChanged()
+{
+ _aVisRectChangedHdl.Call( this );
+}
+
+void SvtIconChoiceCtrl::GetFocus()
+{
+ _pImp->GetFocus();
+ Control::GetFocus();
+ ULONG nPos;
+ SvxIconChoiceCtrlEntry* pSelectedEntry = GetSelectedEntry ( nPos );
+ if ( pSelectedEntry )
+ _pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pSelectedEntry );
+}
+
+void SvtIconChoiceCtrl::LoseFocus()
+{
+ _pImp->LoseFocus();
+ Control::LoseFocus();
+}
+
+void SvtIconChoiceCtrl::SetUpdateMode( BOOL bUpdate )
+{
+ Control::SetUpdateMode( bUpdate );
+ _pImp->SetUpdateMode( bUpdate );
+}
+void SvtIconChoiceCtrl::SetFont( const Font& rFont )
+{
+ if( rFont != GetFont() )
+ {
+ Control::SetFont( rFont );
+ _pImp->FontModified();
+ }
+}
+
+void SvtIconChoiceCtrl::SetPointFont( const Font& rFont )
+{
+ if( rFont != GetPointFont() )
+ {
+ Control::SetPointFont( rFont );
+ _pImp->FontModified();
+ }
+}
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::GetEntry( const Point& rPixPos, BOOL bHit ) const
+{
+ Point aPos( rPixPos );
+ aPos -= GetMapMode().GetOrigin();
+ return ((SvtIconChoiceCtrl*)this)->_pImp->GetEntry( aPos, bHit );
+}
+
+void SvtIconChoiceCtrl::SetStyle( WinBits nWinStyle )
+{
+ _pImp->SetStyle( nWinStyle );
+}
+
+WinBits SvtIconChoiceCtrl::GetStyle() const
+{
+ return _pImp->GetStyle();
+}
+void SvtIconChoiceCtrl::Command( const CommandEvent& rCEvt )
+{
+ _pImp->Command( rCEvt );
+}
+
+void SvtIconChoiceCtrl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
+{
+ _pImp->SetEntryTextMode( eMode, pEntry );
+}
+
+SvxIconChoiceCtrlTextMode SvtIconChoiceCtrl::GetEntryTextMode( const SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ return _pImp->GetEntryTextModeSmart( pEntry );
+}
+
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::GetNextEntry( const Point& rPixPos, SvxIconChoiceCtrlEntry* pCurEntry, BOOL ) const
+{
+ Point aPos( rPixPos );
+ aPos -= GetMapMode().GetOrigin();
+ return ((SvtIconChoiceCtrl*)this)->_pImp->GetNextEntry( aPos, pCurEntry );
+}
+
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::GetPrevEntry( const Point& rPixPos, SvxIconChoiceCtrlEntry* pCurEntry, BOOL ) const
+{
+ Point aPos( rPixPos );
+ aPos -= GetMapMode().GetOrigin();
+ return ((SvtIconChoiceCtrl*)this)->_pImp->GetPrevEntry( aPos, pCurEntry );
+}
+ULONG SvtIconChoiceCtrl::GetEntryCount() const
+{
+ return _pImp->GetEntryCount();
+}
+
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::GetEntry( ULONG nPos ) const
+{
+ return _pImp->GetEntry( nPos );
+}
+
+void SvtIconChoiceCtrl::CreateAutoMnemonics( MnemonicGenerator& _rUsedMnemonics )
+{
+ _pImp->CreateAutoMnemonics( &_rUsedMnemonics );
+}
+
+void SvtIconChoiceCtrl::CreateAutoMnemonics( void )
+{
+ _pImp->CreateAutoMnemonics();
+}
+
+void SvtIconChoiceCtrl::RemoveEntry( SvxIconChoiceCtrlEntry* pEntry )
+{
+ _pImp->RemoveEntry( pEntry );
+}
+
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::GetSelectedEntry( ULONG& rPos ) const
+{
+ return _pImp->GetFirstSelectedEntry( rPos );
+}
+
+void SvtIconChoiceCtrl::ClickIcon()
+{
+ ULONG nPos;
+ GetSelectedEntry ( nPos );
+ _aClickIconHdl.Call( this );
+}
+BOOL SvtIconChoiceCtrl::IsEntryEditing() const
+{
+ return _pImp->IsEntryEditing();
+}
+
+BOOL SvtIconChoiceCtrl::SetChoiceWithCursor ( BOOL bDo )
+{
+ return _pImp->SetChoiceWithCursor (bDo);
+}
+
+void SvtIconChoiceCtrl::KeyInput( const KeyEvent& rKEvt )
+{
+ BOOL bKeyUsed = DoKeyInput( rKEvt );
+ if ( !bKeyUsed )
+ {
+ _pCurKeyEvent = (KeyEvent*)&rKEvt;
+ Control::KeyInput( rKEvt );
+ _pCurKeyEvent = NULL;
+ }
+}
+BOOL SvtIconChoiceCtrl::DoKeyInput( const KeyEvent& rKEvt )
+{
+ // unter OS/2 bekommen wir auch beim Editieren Key-Up/Down
+ if( IsEntryEditing() )
+ return TRUE;
+ _pCurKeyEvent = (KeyEvent*)&rKEvt;
+ BOOL bHandled = _pImp->KeyInput( rKEvt );
+ _pCurKeyEvent = NULL;
+ return bHandled;
+}
+ULONG SvtIconChoiceCtrl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ return _pImp->GetEntryListPos( pEntry );
+}
+SvxIconChoiceCtrlEntry* SvtIconChoiceCtrl::GetCursor( ) const
+{
+ return _pImp->GetCurEntry( );
+}
+void SvtIconChoiceCtrl::SetCursor( SvxIconChoiceCtrlEntry* pEntry )
+{
+ _pImp->SetCursor( pEntry );
+}
+void SvtIconChoiceCtrl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
+{
+ _pImp->InvalidateEntry( pEntry );
+}
+void SvtIconChoiceCtrl::Clear()
+{
+ _pImp->Clear();
+}
+void SvtIconChoiceCtrl::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+}
+
+
+void SvtIconChoiceCtrl::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( ((rDCEvt.GetType() == DATACHANGED_SETTINGS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTS) ) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ _pImp->InitSettings();
+ Invalidate(INVALIDATE_NOCHILDREN);
+ }
+ else
+ Control::DataChanged( rDCEvt );
+}
+
+void SvtIconChoiceCtrl::SetBackground( const Wallpaper& rPaper )
+{
+ if( rPaper != GetBackground() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Wallpaper aEmpty;
+ if( rPaper == aEmpty )
+ Control::SetBackground( rStyleSettings.GetFieldColor() );
+ else
+ {
+ Wallpaper aBackground( rPaper );
+ // HACK, da Hintergrund sonst transparent sein koennte
+ if( !aBackground.IsBitmap() )
+ aBackground.SetStyle( WALLPAPER_TILE );
+
+ WallpaperStyle eStyle = aBackground.GetStyle();
+ Color aBack( aBackground.GetColor());
+ Color aTrans( COL_TRANSPARENT );
+ if( aBack == aTrans && (
+ (!aBackground.IsBitmap() ||
+ aBackground.GetBitmap().IsTransparent() ||
+ (eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE))))
+ {
+ aBackground.SetColor( rStyleSettings.GetFieldColor() );
+ }
+ if( aBackground.IsScrollable() )
+ {
+ Rectangle aRect;
+ aRect.SetSize( Size(32765, 32765) );
+ aBackground.SetRect( aRect );
+ }
+ else
+ {
+ Rectangle aRect( _pImp->GetOutputRect() );
+ aBackground.SetRect( aRect );
+ }
+ Control::SetBackground( aBackground );
+ }
+
+ // bei hart attributierter Textfarbe keine 'Automatik', die eine
+ // lesbare Textfarbe einstellt.
+ Font aFont( GetFont() );
+ aFont.SetColor( rStyleSettings.GetFieldTextColor() );
+ SetFont( aFont );
+
+ Invalidate(INVALIDATE_NOCHILDREN);
+ }
+}
+
+void SvtIconChoiceCtrl::Flush()
+{
+ _pImp->Flush();
+}
+
+void SvtIconChoiceCtrl::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( !_pImp->RequestHelp( rHEvt ) )
+ Control::RequestHelp( rHEvt );
+}
+
+void SvtIconChoiceCtrl::SetSelectionMode( SelectionMode eMode )
+{
+ _pImp->SetSelectionMode( eMode );
+}
+
+BOOL SvtIconChoiceCtrl::HandleShortCutKey( const KeyEvent& r )
+{
+ return _pImp->HandleShortCutKey( r );
+}
+
+Rectangle SvtIconChoiceCtrl::GetBoundingBox( SvxIconChoiceCtrlEntry* pEntry ) const
+{
+ return _pImp->GetEntryBoundRect( pEntry );
+}
+
+void SvtIconChoiceCtrl::FillLayoutData() const
+{
+ CreateLayoutData();
+
+ SvtIconChoiceCtrl* pNonConstMe = const_cast< SvtIconChoiceCtrl* >( this );
+
+ // loop through all entries
+ sal_uInt16 nCount = (sal_uInt16)GetEntryCount();
+ sal_uInt16 nPos = 0;
+ while ( nPos < nCount )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = GetEntry( nPos );
+
+ Point aPos = _pImp->GetEntryBoundRect( pEntry ).TopLeft();
+ String sEntryText = pEntry->GetDisplayText( );
+ Rectangle aTextRect = _pImp->CalcTextRect( pEntry, &aPos, sal_False, &sEntryText );
+
+ sal_Bool bLargeIconMode = WB_ICON == ( _pImp->GetStyle() & ( VIEWMODE_MASK ) );
+ sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
+
+ _pImp->PaintItem( aTextRect, IcnViewFieldTypeText, pEntry, nTextPaintFlags, pNonConstMe, &sEntryText, GetLayoutData() );
+
+ ++nPos;
+ }
+}
+
+Rectangle SvtIconChoiceCtrl::GetEntryCharacterBounds( const sal_Int32 _nEntryPos, const sal_Int32 _nCharacterIndex ) const
+{
+ Rectangle aRect;
+
+ Pair aEntryCharacterRange = GetLineStartEnd( _nEntryPos );
+ if ( aEntryCharacterRange.A() + _nCharacterIndex < aEntryCharacterRange.B() )
+ {
+ aRect = GetCharacterBounds( aEntryCharacterRange.A() + _nCharacterIndex );
+ }
+
+ return aRect;
+}
+
+void SvtIconChoiceCtrl::SetNoSelection()
+{
+ _pImp->SetNoSelection();
+}
+
+void SvtIconChoiceCtrl::CallImplEventListeners(ULONG nEvent, void* pData)
+{
+ CallEventListeners(nEvent, pData);
+}
+::com::sun::star::uno::Reference< XAccessible > SvtIconChoiceCtrl::CreateAccessible()
+{
+ Window* pParent = GetAccessibleParentWindow();
+ DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" );
+
+ ::com::sun::star::uno::Reference< XAccessible > xAccessible;
+ if ( pParent )
+ {
+ ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
+ if ( xAccParent.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface());
+ xAccessible = _pImp->GetAccessibleFactory().createAccessibleIconChoiceCtrl( *this, xAccParent );
+ }
+ }
+ return xAccessible;
+}
+
diff --git a/svtools/source/contnr/makefile.mk b/svtools/source/contnr/makefile.mk
new file mode 100644
index 000000000000..232665c88c9c
--- /dev/null
+++ b/svtools/source/contnr/makefile.mk
@@ -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.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=svtools
+TARGET=svcontnr
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=cont_pch
+PROJECTPCHSOURCE=cont_pch
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/svt.pmk
+
+# --- Files --------------------------------------------------------
+
+EXCEPTIONSFILES=\
+ $(SLO)$/contentenumeration.obj \
+ $(SLO)$/fileview.obj \
+ $(SLO)$/svlbox.obj \
+ $(SLO)$/svtabbx.obj \
+ $(SLO)$/svimpbox.obj \
+ $(SLO)$/templwin.obj
+
+SLOFILES= $(EXCEPTIONSFILES) \
+ $(SLO)$/svicnvw.obj \
+ $(SLO)$/svimpicn.obj \
+ $(SLO)$/treelist.obj \
+ $(SLO)$/svlbitm.obj \
+ $(SLO)$/svtreebx.obj \
+ $(SLO)$/imivctl1.obj \
+ $(SLO)$/imivctl2.obj \
+ $(SLO)$/ivctrl.obj \
+ $(SLO)$/tooltiplbox.obj
+
+SRS1NAME=$(TARGET)
+SRC1FILES =\
+ fileview.src \
+ templwin.src \
+ svcontnr.src
+
+HXX1TARGET= svcontnr
+HXX1EXT= hxx
+HXX1FILES= $(PRJ)$/inc$/svlbox.hxx \
+ $(PRJ)$/inc$/svlbitm.hxx \
+ $(PRJ)$/inc$/svtreebx.hxx \
+ $(PRJ)$/inc$/svicnvw.hxx \
+ $(PRJ)$/inc$/svtabbx.hxx \
+ $(PRJ)$/inc$/treelist.hxx
+HXX1EXCL= -E:*include*
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/svtools/source/contnr/svcontnr.src b/svtools/source/contnr/svcontnr.src
new file mode 100644
index 000000000000..bcd1e060664f
--- /dev/null
+++ b/svtools/source/contnr/svcontnr.src
@@ -0,0 +1,103 @@
+/*************************************************************************
+ *
+ * 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 <svtools/svtools.hrc>
+
+Image RID_IMG_TREENODE_COLLAPSED
+{
+ ImageBitmap = Bitmap { File = "plus.bmp"; } ;
+ MaskColor = Color { Red = 0xFF00; Green = 0x0000; Blue = 0xFF00; };
+};
+
+Image RID_IMG_TREENODE_EXPANDED
+{
+ ImageBitmap = Bitmap { File = "minus.bmp"; } ;
+ MaskColor = Color { Red = 0xFF00; Green = 0x0000; Blue = 0xFF00; };
+};
+
+Image RID_IMG_TREENODE_COLLAPSED_HC
+{
+ ImageBitmap = Bitmap { File = "plus_sch.bmp"; } ;
+ MaskColor = Color { Red = 0xFF00; Green = 0x0000; Blue = 0xFF00; };
+};
+
+Image RID_IMG_TREENODE_EXPANDED_HC
+{
+ ImageBitmap = Bitmap { File = "minus_sch.bmp"; } ;
+ MaskColor = Color { Red = 0xFF00; Green = 0x0000; Blue = 0xFF00; };
+};
+
+// descriptions of accessible objects
+
+String STR_SVT_ACC_DESC_TABLISTBOX
+{
+ Text [ en-US ] = "Row: %1, Column: %2";
+};
+String STR_SVT_ACC_DESC_FILEVIEW
+{
+ Text [ en-US ] = ", Type: %1, URL: %2";
+};
+String STR_SVT_ACC_DESC_FOLDER
+{
+ Text [ en-US ] = "Folder";
+};
+String STR_SVT_ACC_DESC_FILE
+{
+ Text [ en-US ] = "File";
+};
+String STR_SVT_ACC_EMPTY_FIELD
+{
+ Text [ en-US ] = "Empty Field";
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svtools/source/contnr/svicnvw.cxx b/svtools/source/contnr/svicnvw.cxx
new file mode 100644
index 000000000000..20bcfe0fe33a
--- /dev/null
+++ b/svtools/source/contnr/svicnvw.cxx
@@ -0,0 +1,833 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+#include <svtools/svlbox.hxx>
+#include <svtools/svicnvw.hxx>
+#include <svimpicn.hxx>
+#include <svtools/svlbitm.hxx>
+
+#ifndef GCC
+#endif
+
+#define ICNVW_BLOCK_ENTRYINS 0x0001
+
+SvIcnVwDataEntry::SvIcnVwDataEntry()
+ : nIcnVwFlags(0),eTextMode(ShowTextDontKnow)
+{
+}
+
+SvIcnVwDataEntry::~SvIcnVwDataEntry()
+{
+}
+
+SvIconView::SvIconView( Window* pParent, WinBits nWinStyle ) :
+ SvLBox( pParent, nWinStyle | WB_BORDER )
+{
+ nWinBits = nWinStyle;
+ nIcnVwFlags = 0;
+ pImp = new SvImpIconView( this, GetModel(), nWinStyle | WB_ICON );
+ pImp->mpViewData = 0;
+ SetSelectionMode( SINGLE_SELECTION );
+ SetLineColor();
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
+ SetDefaultFont();
+}
+
+SvIconView::SvIconView( Window* pParent , const ResId& rResId ) :
+ SvLBox( pParent, rResId )
+{
+ pImp = new SvImpIconView( this, GetModel(), WB_BORDER | WB_ICON );
+ nIcnVwFlags = 0;
+ pImp->mpViewData = 0;
+ SetLineColor();
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
+ SetDefaultFont();
+ pImp->SetSelectionMode( GetSelectionMode() );
+ pImp->SetWindowBits( nWindowStyle );
+ nWinBits = nWindowStyle;
+}
+
+SvIconView::~SvIconView()
+{
+ delete pImp;
+}
+
+void SvIconView::SetDefaultFont()
+{
+ SetFont( GetFont() );
+}
+
+SvLBoxEntry* SvIconView::CreateEntry( const XubString& rStr,
+ const Image& rCollEntryBmp, const Image& rExpEntryBmp )
+{
+ SvLBoxEntry* pEntry = new SvLBoxEntry;
+
+ SvLBoxContextBmp* pContextBmp =
+ new SvLBoxContextBmp( pEntry,0, rCollEntryBmp,rExpEntryBmp, 0xffff );
+ pEntry->AddItem( pContextBmp );
+
+ SvLBoxString* pString = new SvLBoxString( pEntry, 0, rStr );
+ pEntry->AddItem( pString );
+
+ return pEntry;
+}
+
+void SvIconView::DisconnectFromModel()
+{
+ SvLBox::DisconnectFromModel();
+ pImp->SetModel( GetModel(), 0 );
+}
+
+
+SvLBoxEntry* SvIconView::InsertEntry( const XubString& rText,
+ SvLBoxEntry* pParent, BOOL bChildsOnDemand, ULONG nPos )
+{
+ SvLBoxEntry* pEntry = CreateEntry(
+ rText, aCollapsedEntryBmp, aExpandedEntryBmp );
+ pEntry->EnableChildsOnDemand( bChildsOnDemand );
+
+ if ( !pParent )
+ SvLBox::Insert( pEntry, nPos );
+ else
+ SvLBox::Insert( pEntry, pParent, nPos );
+ return pEntry;
+}
+
+SvLBoxEntry* SvIconView::InsertEntry( const XubString& rText,
+ const Image& rExpEntryBmp,
+ const Image& rCollEntryBmp,
+ SvLBoxEntry* pParent, BOOL bChildsOnDemand, ULONG nPos)
+{
+ SvLBoxEntry* pEntry = CreateEntry(
+ rText, rCollEntryBmp, rExpEntryBmp );
+
+ pEntry->EnableChildsOnDemand( bChildsOnDemand );
+ if ( !pParent )
+ SvLBox::Insert( pEntry, nPos );
+ else
+ SvLBox::Insert( pEntry, pParent, nPos );
+ return pEntry;
+}
+
+
+void SvIconView::SetEntryText(SvLBoxEntry* pEntry, const XubString& rStr)
+{
+ SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ if ( pItem )
+ {
+ pItem->SetText( pEntry, rStr );
+ GetModel()->InvalidateEntry( pEntry );
+ }
+}
+
+void SvIconView::SetExpandedEntryBmp(SvLBoxEntry* pEntry, const Image& rBmp)
+{
+ SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ if ( pItem )
+ {
+ pItem->SetBitmap2( rBmp );
+ GetModel()->InvalidateEntry( pEntry );
+ }
+}
+
+void SvIconView::SetCollapsedEntryBmp(SvLBoxEntry* pEntry,
+ const Image& rBmp )
+{
+ SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ if ( pItem )
+ {
+ pItem->SetBitmap1( rBmp );
+ GetModel()->InvalidateEntry( pEntry );
+ }
+}
+
+XubString SvIconView::GetEntryText(SvLBoxEntry* pEntry ) const
+{
+ XubString aStr;
+ SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ if ( pItem )
+ aStr = pItem->GetText();
+ return aStr;
+}
+
+Image SvIconView::GetExpandedEntryBmp(SvLBoxEntry* pEntry) const
+{
+ Image aBmp;
+ SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ if ( pItem )
+ aBmp = pItem->GetBitmap2();
+ return aBmp;
+}
+
+Image SvIconView::GetCollapsedEntryBmp(SvLBoxEntry* pEntry) const
+{
+ Image aBmp;
+ SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ if ( pItem )
+ aBmp = pItem->GetBitmap1();
+ return aBmp;
+}
+
+
+SvLBoxEntry* SvIconView::CloneEntry( SvLBoxEntry* pSource )
+{
+ XubString aStr;
+ Image aCollEntryBmp;
+ Image aExpEntryBmp;
+
+ SvLBoxString* pStringItem = (SvLBoxString*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ if ( pStringItem )
+ aStr = pStringItem->GetText();
+ SvLBoxContextBmp* pBmpItem =(SvLBoxContextBmp*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ if ( pBmpItem )
+ {
+ aCollEntryBmp = pBmpItem->GetBitmap1();
+ aExpEntryBmp = pBmpItem->GetBitmap2();
+ }
+ SvLBoxEntry* pEntry = CreateEntry( aStr, aCollEntryBmp, aExpEntryBmp );
+ pEntry->SvListEntry::Clone( pSource );
+ pEntry->EnableChildsOnDemand( pSource->HasChildsOnDemand() );
+ pEntry->SetUserData( pSource->GetUserData() );
+ return pEntry;
+}
+
+
+USHORT SvIconView::IsA()
+{
+ return SV_LISTBOX_ID_ICONVIEW;
+}
+
+void SvIconView::RequestingChilds( SvLBoxEntry* pParent )
+{
+ if ( !pParent->HasChilds() )
+ InsertEntry( String::CreateFromAscii("<dummy>"), pParent, FALSE, LIST_APPEND );
+}
+
+void __EXPORT SvIconView::Paint( const Rectangle& rRect )
+{
+ pImp->Paint( rRect );
+}
+
+void __EXPORT SvIconView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ pImp->MouseButtonDown( rMEvt );
+}
+
+void __EXPORT SvIconView::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ pImp->MouseButtonUp( rMEvt );
+}
+
+void __EXPORT SvIconView::MouseMove( const MouseEvent& rMEvt )
+{
+ pImp->MouseMove( rMEvt );
+}
+
+void __EXPORT SvIconView::KeyInput( const KeyEvent& rKEvt )
+{
+ // unter OS/2 bekommen wir auch beim Editieren Key-Up/Down
+ if( IsEditingActive() )
+ return;
+
+ nImpFlags |= SVLBOX_IS_TRAVELSELECT;
+ BOOL bKeyUsed = pImp->KeyInput( rKEvt );
+ if ( !bKeyUsed )
+ SvLBox::KeyInput( rKEvt );
+ nImpFlags &= ~SVLBOX_IS_TRAVELSELECT;
+}
+
+void __EXPORT SvIconView::Resize()
+{
+ pImp->Resize();
+ SvLBox::Resize();
+}
+
+void __EXPORT SvIconView::GetFocus()
+{
+ pImp->GetFocus();
+ SvLBox::GetFocus();
+}
+
+void __EXPORT SvIconView::LoseFocus()
+{
+ pImp->LoseFocus();
+ SvLBox::LoseFocus();
+}
+
+void SvIconView::SetUpdateMode( BOOL bUpdate )
+{
+ Control::SetUpdateMode( bUpdate );
+ if ( bUpdate )
+ pImp->UpdateAll();
+}
+
+void SvIconView::SetModel( SvLBoxTreeList* )
+{
+}
+
+void SvIconView::SetModel( SvLBoxTreeList* pNewModel, SvLBoxEntry* pParent )
+{
+ nIcnVwFlags |= ICNVW_BLOCK_ENTRYINS;
+ SvLBox::SetModel( pNewModel );
+ nIcnVwFlags &= (~ICNVW_BLOCK_ENTRYINS);
+ if ( pParent && pParent->HasChildsOnDemand() )
+ RequestingChilds( pParent );
+ pImp->SetModel( pNewModel, pParent );
+}
+
+void __EXPORT SvIconView::ModelHasCleared()
+{
+ SvLBox::ModelHasCleared();
+ pImp->Clear();
+}
+
+void __EXPORT SvIconView::ModelHasInserted( SvListEntry* pEntry )
+{
+ if( !(nIcnVwFlags & ICNVW_BLOCK_ENTRYINS ) )
+ pImp->EntryInserted( (SvLBoxEntry*)pEntry );
+}
+
+void __EXPORT SvIconView::ModelHasInsertedTree( SvListEntry* pEntry )
+{
+ pImp->TreeInserted( (SvLBoxEntry*)pEntry );
+}
+
+void __EXPORT SvIconView::ModelIsMoving(SvListEntry* pSource,
+ SvListEntry* /* pTargetParent */ , ULONG /* nChildPos */ )
+{
+ pImp->MovingEntry( (SvLBoxEntry*)pSource );
+}
+
+void __EXPORT SvIconView::ModelHasMoved(SvListEntry* pSource )
+{
+ pImp->EntryMoved( (SvLBoxEntry*)pSource );
+}
+
+void __EXPORT SvIconView::ModelIsRemoving( SvListEntry* pEntry )
+{
+ pImp->RemovingEntry( (SvLBoxEntry*)pEntry );
+ NotifyRemoving( (SvLBoxEntry*)pEntry );
+}
+
+void __EXPORT SvIconView::ModelHasRemoved( SvListEntry* /* pEntry */ )
+{
+ pImp->EntryRemoved();
+}
+
+void __EXPORT SvIconView::ModelHasEntryInvalidated( SvListEntry* pEntry )
+{
+ // die einzelnen Items des Entries reinitialisieren
+ SvLBox::ModelHasEntryInvalidated( pEntry );
+ // painten
+ pImp->ModelHasEntryInvalidated( pEntry );
+}
+
+void SvIconView::ShowTargetEmphasis( SvLBoxEntry* pEntry, BOOL bShow )
+{
+ pImp->ShowTargetEmphasis( pEntry, bShow );
+}
+
+Point SvIconView::GetEntryPosition( SvLBoxEntry* pEntry ) const
+{
+ return ((SvIconView*)this)->pImp->GetEntryPosition( pEntry );
+}
+
+void SvIconView::SetEntryPosition( SvLBoxEntry* pEntry, const Point& rPos)
+{
+ pImp->SetEntryPosition( pEntry, rPos, FALSE, TRUE );
+}
+
+void SvIconView::SetEntryPosition( SvLBoxEntry* pEntry, const Point& rPos, BOOL bAdjustAtGrid )
+{
+ pImp->SetEntryPosition( pEntry, rPos, bAdjustAtGrid );
+}
+
+void SvIconView::SetFont( const Font& rFont )
+{
+ Font aTempFont( rFont );
+ aTempFont.SetTransparent( TRUE );
+ SvLBox::SetFont( aTempFont );
+ RecalcViewData();
+ pImp->ChangedFont();
+}
+
+void SvIconView::ViewDataInitialized( SvLBoxEntry* pEntry )
+{
+ pImp->ViewDataInitialized( pEntry );
+}
+
+SvLBoxEntry* SvIconView::GetDropTarget( const Point& rPos )
+{
+ return pImp->GetDropTarget( rPos );
+}
+
+SvLBoxEntry* SvIconView::GetEntry( const Point& rPixPos, BOOL ) const
+{
+ Point aPos( rPixPos );
+ aPos -= GetMapMode().GetOrigin();
+ return ((SvIconView*)this)->pImp->GetEntry( aPos );
+}
+
+SvLBoxEntry* SvIconView::GetEntryFromLogicPos( const Point& rDocPos ) const
+{
+ return ((SvIconView*)this)->pImp->GetEntry( rDocPos );
+}
+
+
+void SvIconView::SetWindowBits( WinBits nWinStyle )
+{
+ nWinBits = nWinStyle;
+ pImp->SetWindowBits( nWinStyle );
+}
+
+void SvIconView::PaintEntry( SvLBoxEntry* pEntry )
+{
+ pImp->PaintEntry( pEntry );
+}
+
+
+void SvIconView::PaintEntry( SvLBoxEntry* pEntry, const Point& rPos )
+{
+ pImp->PaintEntry( pEntry, rPos );
+}
+
+Rectangle SvIconView::GetFocusRect( SvLBoxEntry* pEntry )
+{
+ return pImp->CalcFocusRect( pEntry );
+}
+
+void SvIconView::InvalidateEntry( SvLBoxEntry* pEntry )
+{
+ pImp->InvalidateEntry( pEntry );
+}
+
+void SvIconView::SetDragDropMode( DragDropMode nDDMode )
+{
+ SvLBox::SetDragDropMode( nDDMode );
+ pImp->SetDragDropMode( nDDMode );
+}
+
+void SvIconView::SetSelectionMode( SelectionMode eSelectMode )
+{
+ SvLBox::SetSelectionMode( eSelectMode );
+ pImp->SetSelectionMode( eSelectMode );
+}
+
+BOOL SvIconView::Select( SvLBoxEntry* pEntry, BOOL bSelect )
+{
+ EndEditing();
+ BOOL bRetVal = SvListView::Select( pEntry, bSelect );
+ if( bRetVal )
+ {
+ pImp->EntrySelected( pEntry, bSelect );
+ pHdlEntry = pEntry;
+ SelectHdl();
+ }
+ return bRetVal;
+}
+
+void SvIconView::SelectAll( BOOL bSelect, BOOL )
+{
+ SvLBoxEntry* pEntry = pImp->GetCurParent();
+ pEntry = FirstChild( pEntry );
+ while( pEntry )
+ {
+ Select( pEntry, bSelect );
+ pEntry = NextSibling( pEntry );
+ }
+}
+
+void SvIconView::SetCurEntry( SvLBoxEntry* _pEntry )
+{
+ pImp->SetCursor( _pEntry );
+}
+
+SvLBoxEntry* SvIconView::GetCurEntry() const
+{
+ return pImp->GetCurEntry();
+}
+
+void SvIconView::Arrange()
+{
+#ifdef DBG_UTIL
+ USHORT n=1;
+ if( n == 1 && n-1 == 0 )
+ {
+ pImp->Arrange();
+ }
+ else
+ {
+ pImp->AdjustAtGrid();
+ }
+#else
+ pImp->Arrange();
+#endif
+}
+
+
+void SvIconView::SetSpaceBetweenEntries( long nX, long nY )
+{
+ pImp->SetSpaceBetweenEntries( nX, nY );
+}
+
+BOOL SvIconView::NotifyMoving( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
+ SvLBoxEntry*& rpNewParent, ULONG& rNewChildPos )
+{
+ return pImp->NotifyMoving(pTarget,pEntry,rpNewParent,rNewChildPos);
+}
+
+BOOL SvIconView::NotifyCopying( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
+ SvLBoxEntry*& rpNewParent, ULONG& rNewChildPos )
+{
+ return pImp->NotifyCopying(pTarget,pEntry,rpNewParent,rNewChildPos);
+}
+
+
+void SvIconView::EnableInplaceEditing( BOOL bEnable )
+{
+ SvLBox::EnableInplaceEditing( bEnable );
+}
+
+void SvIconView::EditingRequest( SvLBoxEntry* pEntry, SvLBoxItem* pItem,
+ const Point& )
+{
+ if ( pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
+ {
+ Selection aSel( SELECTION_MIN, SELECTION_MAX );
+ if ( EditingEntry( pEntry, aSel ) )
+ {
+ SelectAll( FALSE );
+ EditItemText( pEntry, (SvLBoxString*)pItem, aSel );
+ }
+ }
+}
+
+
+void SvIconView::EditItemText( SvLBoxEntry* pEntry, SvLBoxItem* pItem,
+ const Selection& rSel )
+{
+ DBG_ASSERT(pEntry&&pItem,"EditItemText:Params?");
+ pCurEdEntry = pEntry;
+ pCurEdItem = pItem;
+ Rectangle aRect( pImp->CalcTextRect( pEntry, (SvLBoxString*)pItem,0,TRUE ));
+
+ aRect.Bottom() += 4;
+ pImp->MakeVisible( aRect ); // vor der Umrechnung in Pixel-Koord. rufen!
+ aRect.Bottom() -= 4;
+
+ Point aPos( aRect.TopLeft() );
+ aPos += GetMapMode().GetOrigin(); // Dok-Koord. -> Window-Koord.
+ aRect.SetPos( aPos );
+
+ aRect.Bottom() += 2; // sieht huebscher aus
+
+#ifdef WIN
+ aRect.Bottom() += 4;
+#endif
+#ifdef OS2
+
+#if OS2_SINGLE_LINE_EDIT
+ aRect.Left() -= 3;
+ aRect.Right() += 3;
+ aRect.Top() -= 3;
+ aRect.Bottom() += 3;
+#else
+ aRect.Left() -= 10;
+ aRect.Right() += 10;
+ aRect.Top() -= 5;
+ aRect.Bottom() += 5;
+#endif
+
+#endif // OS2
+ EditText( ((SvLBoxString*)pItem)->GetText(), aRect, rSel, TRUE );
+}
+
+void SvIconView::EditEntry( SvLBoxEntry* pEntry )
+{
+ if( !pEntry )
+ pEntry = pImp->GetCurEntry();
+ if( pEntry )
+ {
+ SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ if( pItem )
+ {
+ Selection aSel( SELECTION_MIN, SELECTION_MAX );
+ if( EditingEntry( pEntry, aSel ) )
+ {
+ SelectAll( FALSE );
+ EditItemText( pEntry, pItem, aSel );
+ }
+ }
+ }
+}
+
+void SvIconView::EditedText( const XubString& rStr )
+{
+ XubString aRefStr( ((SvLBoxString*)pCurEdItem)->GetText() );
+ if ( EditedEntry( pCurEdEntry, rStr ) )
+ {
+ ((SvLBoxString*)pCurEdItem)->SetText( pCurEdEntry, rStr );
+ pModel->InvalidateEntry( pCurEdEntry );
+ }
+ if( GetSelectionMode()==SINGLE_SELECTION && !GetSelectionCount())
+ Select( pCurEdEntry );
+}
+
+
+BOOL SvIconView::EditingEntry( SvLBoxEntry*, Selection& )
+{
+ return TRUE;
+}
+
+BOOL SvIconView::EditedEntry( SvLBoxEntry*, const XubString& )
+{
+ return TRUE;
+}
+
+
+void SvIconView::WriteDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo)
+{
+ pImp->WriteDragServerInfo( rPos, pInfo );
+}
+
+void SvIconView::ReadDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo )
+{
+ pImp->ReadDragServerInfo( rPos, pInfo );
+}
+
+void SvIconView::Command( const CommandEvent& rCEvt )
+{
+ pImp->PrepareCommandEvent( rCEvt.GetMousePosPixel() );
+}
+
+void SvIconView::SetCurParent( SvLBoxEntry* pNewParent )
+{
+ if ( pNewParent && pNewParent->HasChildsOnDemand() )
+ RequestingChilds( pNewParent );
+ pImp->SetCurParent( pNewParent );
+}
+
+SvLBoxEntry* SvIconView::GetCurParent() const
+{
+ return pImp->GetCurParent();
+}
+
+SvViewData* SvIconView::CreateViewData( SvListEntry* )
+{
+ SvIcnVwDataEntry* pEntryData = new SvIcnVwDataEntry;
+ return (SvViewData*)pEntryData;
+}
+
+void SvIconView::InitViewData( SvViewData* pData, SvListEntry* pEntry )
+{
+ SvLBox::InitViewData( pData, pEntry );
+ pImp->InvalidateBoundingRect( ((SvIcnVwDataEntry*)pData)->aRect );
+}
+
+Region SvIconView::GetDragRegion() const
+{
+ Rectangle aRect;
+ SvLBoxEntry* pEntry = GetCurEntry();
+ if( pEntry )
+ aRect = pImp->GetBoundingRect( pEntry );
+ Region aRegion( aRect );
+ return aRegion;
+}
+
+ULONG SvIconView::GetSelectionCount() const
+{
+ return (ULONG)(pImp->GetSelectionCount());
+}
+
+void SvIconView::SetGrid( long nDX, long nDY )
+{
+ pImp->SetGrid( nDX, nDY );
+}
+
+void SvIconView::ModelNotification( USHORT nActionId, SvListEntry* pEntry1,
+ SvListEntry* pEntry2, ULONG nPos )
+{
+ SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos );
+ switch( nActionId )
+ {
+ case LISTACTION_RESORTING:
+ SetUpdateMode( FALSE );
+ break;
+
+ case LISTACTION_RESORTED:
+ SetUpdateMode( TRUE );
+ Arrange();
+ break;
+
+ case LISTACTION_CLEARED:
+ if( IsUpdateMode() )
+ Update();
+ break;
+ }
+}
+
+
+void SvIconView::Scroll( long nDeltaX, long nDeltaY, USHORT )
+{
+ pImp->Scroll( nDeltaX, nDeltaY, FALSE );
+}
+
+void SvIconView::PrepareCommandEvent( const CommandEvent& rCEvt )
+{
+ pImp->PrepareCommandEvent( rCEvt.GetMousePosPixel() );
+}
+
+void SvIconView::StartDrag( sal_Int8 nAction, const Point& rPos )
+{
+ pImp->SttDrag( rPos );
+ SvLBoxEntry* pEntry = GetEntry( rPos, TRUE );
+ pImp->mpViewData = pEntry;
+ SvLBox::StartDrag( nAction, rPos );
+}
+
+void SvIconView::DragFinished( sal_Int8 )
+{
+ pImp->EndDrag();
+}
+
+sal_Int8 SvIconView::AcceptDrop( const AcceptDropEvent& rEvt )
+{
+ if( pImp->mpViewData )
+ pImp->HideDDIcon();
+ sal_Int8 nRet = SvLBox::AcceptDrop( rEvt );
+ if( DND_ACTION_NONE != nRet )
+ pImp->ShowDDIcon( pImp->mpViewData, rEvt.maPosPixel );
+
+ return nRet;
+}
+
+sal_Int8 SvIconView::ExecuteDrop( const ExecuteDropEvent& rEvt )
+{
+ if( pImp->mpViewData )
+ {
+ pImp->HideDDIcon();
+ pImp->mpViewData = 0;
+ }
+ return SvLBox::ExecuteDrop( rEvt );
+}
+
+void SvIconView::ShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPos )
+{
+ pImp->ShowDDIcon( pRefEntry, rPos );
+}
+
+void SvIconView::HideDDIcon()
+{
+ pImp->HideDDIcon();
+}
+
+void SvIconView::HideShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPos )
+{
+ pImp->HideShowDDIcon( pRefEntry, rPos );
+}
+
+void SvIconView::SelectRect( const Rectangle& rRect, BOOL bAdd,
+ SvPtrarr* pRects, short nOffs )
+{
+ pImp->SelectRect( rRect, bAdd, pRects, nOffs );
+}
+
+void SvIconView::CalcScrollOffsets( const Point& rRefPosPixel, long& rX, long& rY,
+ BOOL b, USHORT nBorderWidth )
+{
+ pImp->CalcScrollOffsets( rRefPosPixel, rX, rY, b, nBorderWidth );
+}
+
+void SvIconView::EndTracking()
+{
+ pImp->EndTracking();
+}
+
+void SvIconView::MakeVisible( SvLBoxEntry* pEntry )
+{
+ pImp->MakeVisible( pEntry );
+}
+
+void SvIconView::PreparePaint( SvLBoxEntry* )
+{
+}
+
+void SvIconView::AdjustAtGrid( SvLBoxEntry* pEntry )
+{
+ pImp->AdjustAtGrid( pEntry );
+}
+
+void SvIconView::LockEntryPos( SvLBoxEntry* pEntry, BOOL bLock )
+{
+ SvIcnVwDataEntry* pViewData = (SvIcnVwDataEntry*)GetViewData( pEntry );
+ if( bLock )
+ pViewData->SetVwFlags( ICNVW_FLAG_POS_LOCKED );
+ else
+ pViewData->ClearVwFlags( ICNVW_FLAG_POS_LOCKED );
+}
+
+BOOL SvIconView::IsEntryPosLocked( const SvLBoxEntry* pEntry ) const
+{
+ const SvIcnVwDataEntry* pViewData = (const SvIcnVwDataEntry*)GetViewData( (SvListEntry*)pEntry );
+ return pViewData->IsEntryPosLocked();
+}
+
+void SvIconView::SetTextMode( SvIconViewTextMode eMode, SvLBoxEntry* pEntry )
+{
+ pImp->SetTextMode( eMode, pEntry );
+}
+
+SvIconViewTextMode SvIconView::GetTextMode( const SvLBoxEntry* pEntry ) const
+{
+ return pImp->GetTextMode( pEntry );
+}
+
+SvLBoxEntry* SvIconView::GetNextEntry( const Point& rPixPos, SvLBoxEntry* pCurEntry, BOOL ) const
+{
+ Point aPos( rPixPos );
+ aPos -= GetMapMode().GetOrigin();
+ return ((SvIconView*)this)->pImp->GetNextEntry( aPos, pCurEntry );
+}
+
+SvLBoxEntry* SvIconView::GetPrevEntry( const Point& rPixPos, SvLBoxEntry* pCurEntry, BOOL ) const
+{
+ Point aPos( rPixPos );
+ aPos -= GetMapMode().GetOrigin();
+ return ((SvIconView*)this)->pImp->GetPrevEntry( aPos, pCurEntry );
+}
+
+void SvIconView::ShowFocusRect( const SvLBoxEntry* pEntry )
+{
+ pImp->ShowFocusRect( pEntry );
+}
+
+
diff --git a/svtools/source/contnr/svimpbox.cxx b/svtools/source/contnr/svimpbox.cxx
new file mode 100644
index 000000000000..484584828b9f
--- /dev/null
+++ b/svtools/source/contnr/svimpbox.cxx
@@ -0,0 +1,3650 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/salnativewidgets.hxx>
+
+#ifndef _HELP_HXX
+#include <vcl/help.hxx>
+#endif
+#include <tabbar.hxx>
+
+#ifndef _STACK_
+#include <stack>
+#endif
+
+#define _SVTREEBX_CXX
+#include <svtools/svtreebx.hxx>
+#include <svtools/svlbox.hxx>
+#include <svimpbox.hxx>
+#include <rtl/instance.hxx>
+#include <svtools/svtdata.hxx>
+
+#ifndef _SVTOOLS_HRC
+#include <svtools/svtools.hrc>
+#endif
+
+// #102891# --------------------
+#ifndef _UNOTOOLS_PROCESSFACTORY_HXX
+#include <comphelper/processfactory.hxx>
+#endif
+
+#define NODE_BMP_TABDIST_NOTVALID -2000000
+#define FIRST_ENTRY_TAB 1
+
+// #i27063# (pl), #i32300# (pb) never access VCL after DeInitVCL - also no destructors
+Image* SvImpLBox::s_pDefCollapsed = NULL;
+Image* SvImpLBox::s_pDefExpanded = NULL;
+Image* SvImpLBox::s_pDefCollapsedHC = NULL;
+Image* SvImpLBox::s_pDefExpandedHC = NULL;
+sal_Int32 SvImpLBox::s_nImageRefCount = 0;
+
+SvImpLBox::SvImpLBox( SvTreeListBox* pLBView, SvLBoxTreeList* pLBTree, WinBits nWinStyle) :
+
+ pTabBar( NULL ),
+ aVerSBar( pLBView, WB_DRAG | WB_VSCROLL ),
+ aHorSBar( pLBView, WB_DRAG | WB_HSCROLL ),
+ aScrBarBox( pLBView ),
+ aOutputSize( 0, 0 ),
+ aSelEng( pLBView, (FunctionSet*)0 ),
+ aFctSet( this, &aSelEng, pLBView ),
+ nExtendedWinBits( 0 ),
+ bAreChildrenTransient( sal_True ),
+ pIntlWrapper( NULL ) // #102891# -----------------------
+{
+ osl_incrementInterlockedCount(&s_nImageRefCount);
+ pView = pLBView;
+ pTree = pLBTree;
+ aSelEng.SetFunctionSet( (FunctionSet*)&aFctSet );
+ aSelEng.ExpandSelectionOnMouseMove( FALSE );
+ SetWindowBits( nWinStyle );
+ SetSelectionMode( SINGLE_SELECTION );
+ SetDragDropMode( 0 );
+
+ aVerSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollUpDownHdl ) );
+ aHorSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollLeftRightHdl ) );
+ aHorSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
+ aVerSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
+ aVerSBar.SetRange( Range(0,0) );
+ aVerSBar.Hide();
+ aHorSBar.SetRange( Range(0,0) );
+ aHorSBar.SetPageSize( 24 ); // Pixel
+ aHorSBar.SetLineSize( 8 ); // Pixel
+
+ nHorSBarHeight = (short)aHorSBar.GetSizePixel().Height();
+ nVerSBarWidth = (short)aVerSBar.GetSizePixel().Width();
+
+ pStartEntry = 0;
+ pCursor = 0;
+ pAnchor = 0;
+ nVisibleCount = 0; // Anzahl Daten-Zeilen im Control
+ nNodeBmpTabDistance = NODE_BMP_TABDIST_NOTVALID;
+ nYoffsNodeBmp = 0;
+ nNodeBmpWidth = 0;
+
+ bAsyncBeginDrag = FALSE;
+ aAsyncBeginDragTimer.SetTimeout( 0 );
+ aAsyncBeginDragTimer.SetTimeoutHdl( LINK(this,SvImpLBox,BeginDragHdl));
+ // Button-Animation in Listbox
+ pActiveButton = 0;
+ pActiveEntry = 0;
+ pActiveTab = 0;
+
+ nFlags = 0;
+ nCurTabPos = FIRST_ENTRY_TAB;
+
+ aEditTimer.SetTimeout( 800 );
+ aEditTimer.SetTimeoutHdl( LINK(this,SvImpLBox,EditTimerCall) );
+
+ nMostRight = -1;
+ pMostRightEntry = 0;
+ nCurUserEvent = 0xffffffff;
+
+ bUpdateMode = TRUE;
+ bInVScrollHdl = FALSE;
+ nFlags |= F_FILLING;
+
+ bSubLstOpRet = bSubLstOpLR = bContextMenuHandling = bIsCellFocusEnabled = FALSE;
+}
+
+SvImpLBox::~SvImpLBox()
+{
+ aEditTimer.Stop();
+ StopUserEvent();
+
+ // #102891# ---------------------
+ if( pIntlWrapper )
+ delete pIntlWrapper;
+ if ( osl_decrementInterlockedCount(&s_nImageRefCount) == 0 )
+ {
+ DELETEZ(s_pDefCollapsed);
+ DELETEZ(s_pDefExpanded);
+ DELETEZ(s_pDefCollapsedHC);
+ DELETEZ(s_pDefExpandedHC);
+ }
+}
+
+// #102891# --------------------
+void SvImpLBox::UpdateIntlWrapper()
+{
+ const ::com::sun::star::lang::Locale & aNewLocale = Application::GetSettings().GetLocale();
+ if( !pIntlWrapper )
+ pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), aNewLocale );
+ else
+ {
+ const ::com::sun::star::lang::Locale &aLocale = pIntlWrapper->getLocale();
+ if( aLocale.Language != aNewLocale.Language || // different Locale from the older one
+ aLocale.Country != aNewLocale.Country ||
+ aLocale.Variant != aNewLocale.Variant )
+ {
+ delete pIntlWrapper;
+ pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), aNewLocale );
+ }
+ }
+}
+
+// #97680# ----------------------
+short SvImpLBox::UpdateContextBmpWidthVector( SvLBoxEntry* pEntry, short nWidth )
+{
+ DBG_ASSERT( pView->pModel, "View and Model aren't valid!" );
+
+ USHORT nDepth = pView->pModel->GetDepth( pEntry );
+ // initialize vector if necessary
+ std::vector< short >::size_type nSize = aContextBmpWidthVector.size();
+ while ( nDepth > nSize )
+ {
+ aContextBmpWidthVector.resize( nSize + 1 );
+ aContextBmpWidthVector.at( nSize ) = nWidth;
+ ++nSize;
+ }
+ if( aContextBmpWidthVector.size() == nDepth )
+ {
+ aContextBmpWidthVector.resize( nDepth + 1 );
+ aContextBmpWidthVector.at( nDepth ) = 0;
+ }
+ short nContextBmpWidth = aContextBmpWidthVector[ nDepth ];
+ if( nContextBmpWidth < nWidth )
+ {
+ aContextBmpWidthVector.at( nDepth ) = nWidth;
+ return nWidth;
+ }
+ else
+ return nContextBmpWidth;
+}
+
+void SvImpLBox::UpdateContextBmpWidthVectorFromMovedEntry( SvLBoxEntry* pEntry )
+{
+ DBG_ASSERT( pEntry, "Moved Entry is invalid!" );
+
+ SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
+ short nExpWidth = (short)pBmpItem->GetBitmap1().GetSizePixel().Width();
+ short nColWidth = (short)pBmpItem->GetBitmap2().GetSizePixel().Width();
+ short nMax = Max(nExpWidth, nColWidth);
+ UpdateContextBmpWidthVector( pEntry, nMax );
+
+ if( pEntry->HasChilds() ) // recursive call, whether expanded or not
+ {
+ SvLBoxEntry* pChild = pView->FirstChild( pEntry );
+ DBG_ASSERT( pChild, "The first child is invalid!" );
+ do
+ {
+ UpdateContextBmpWidthVectorFromMovedEntry( pChild );
+ pChild = pView->Next( pChild );
+ } while ( pChild );
+ }
+}
+
+void SvImpLBox::UpdateContextBmpWidthMax( SvLBoxEntry* pEntry )
+{
+ USHORT nDepth = pView->pModel->GetDepth( pEntry );
+ if( aContextBmpWidthVector.size() < 1 )
+ return;
+ short nWidth = aContextBmpWidthVector[ nDepth ];
+ if( nWidth != pView->nContextBmpWidthMax ) {
+ pView->nContextBmpWidthMax = nWidth;
+ nFlags |= F_IGNORE_CHANGED_TABS;
+ pView->SetTabs();
+ nFlags &= ~F_IGNORE_CHANGED_TABS;
+ }
+}
+
+void SvImpLBox::CalcCellFocusRect( SvLBoxEntry* pEntry, Rectangle& rRect )
+{
+ if ( pEntry && bIsCellFocusEnabled )
+ {
+ if ( nCurTabPos > FIRST_ENTRY_TAB )
+ {
+ SvLBoxItem* pItem = pCursor->GetItem( nCurTabPos );
+ rRect.Left() = pView->GetTab( pCursor, pItem )->GetPos();
+ }
+ if ( pCursor->ItemCount() > ( nCurTabPos + 1 ) )
+ {
+ SvLBoxItem* pNextItem = pCursor->GetItem( nCurTabPos + 1 );
+ long nRight = pView->GetTab( pCursor, pNextItem )->GetPos() - 1;
+ if ( nRight < rRect.Right() )
+ rRect.Right() = nRight;
+ }
+ }
+}
+
+void SvImpLBox::SetWindowBits( WinBits nWinStyle )
+{
+ nWinBits = nWinStyle;
+ if((nWinStyle & WB_SIMPLEMODE) && aSelEng.GetSelectionMode()==MULTIPLE_SELECTION)
+ aSelEng.AddAlways( TRUE );
+}
+
+void SvImpLBox::SetExtendedWindowBits( ExtendedWinBits _nBits )
+{
+ nExtendedWinBits = _nBits;
+}
+
+// Das Model darf hier nicht mehr angefasst werden
+void SvImpLBox::Clear()
+{
+ StopUserEvent();
+ pStartEntry = 0;
+ pAnchor = 0;
+
+ pActiveButton = 0;
+ pActiveEntry = 0;
+ pActiveTab = 0;
+
+ nMostRight = -1;
+ pMostRightEntry = 0;
+
+ // Der Cursor darf hier nicht mehr angefasst werden!
+ if( pCursor )
+ {
+ if( pView->HasFocus() )
+ pView->HideFocus();
+ pCursor = 0;
+ }
+ aVerSBar.Hide();
+ aVerSBar.SetThumbPos( 0 );
+ Range aRange( 0, 0 );
+ aVerSBar.SetRange( aRange );
+ aOutputSize = pView->Control::GetOutputSizePixel();
+ nFlags &= ~(F_VER_SBARSIZE_WITH_HBAR | F_HOR_SBARSIZE_WITH_VBAR );
+ if( pTabBar )
+ {
+ aOutputSize.Height() -= nHorSBarHeight;
+ nFlags |= F_VER_SBARSIZE_WITH_HBAR;
+ }
+ if( !pTabBar )
+ aHorSBar.Hide();
+ aHorSBar.SetThumbPos( 0 );
+ MapMode aMapMode( pView->GetMapMode());
+ aMapMode.SetOrigin( Point(0,0) );
+ pView->Control::SetMapMode( aMapMode );
+ aHorSBar.SetRange( aRange );
+ aHorSBar.SetSizePixel(Size(aOutputSize.Width(),nHorSBarHeight));
+ pView->SetClipRegion();
+ if( GetUpdateMode() )
+ pView->Invalidate( GetVisibleArea() );
+ nFlags |= F_FILLING;
+ if( !aHorSBar.IsVisible() && !aVerSBar.IsVisible() )
+ aScrBarBox.Hide();
+
+ // #97680# ---------
+ aContextBmpWidthVector.clear();
+}
+
+// *********************************************************************
+// Painten, Navigieren, Scrollen
+// *********************************************************************
+
+IMPL_LINK_INLINE_START( SvImpLBox, EndScrollHdl, ScrollBar *, EMPTYARG )
+{
+ if( nFlags & F_ENDSCROLL_SET_VIS_SIZE )
+ {
+ aVerSBar.SetVisibleSize( nNextVerVisSize );
+ nFlags &= ~F_ENDSCROLL_SET_VIS_SIZE;
+ }
+ EndScroll();
+ return 0;
+}
+IMPL_LINK_INLINE_END( SvImpLBox, EndScrollHdl, ScrollBar *, pScrollBar )
+
+
+// Handler vertikale ScrollBar
+
+IMPL_LINK( SvImpLBox, ScrollUpDownHdl, ScrollBar *, pScrollBar )
+{
+ DBG_ASSERT(!bInVScrollHdl,"Scroll-Handler ueberholt sich!");
+ long nDelta = pScrollBar->GetDelta();
+ if( !nDelta )
+ return 0;
+
+ nFlags &= (~F_FILLING);
+
+ bInVScrollHdl = TRUE;
+
+ if( pView->IsEditingActive() )
+ {
+ pView->EndEditing( TRUE ); // Cancel
+ pView->Update();
+ }
+ BeginScroll();
+
+ if( nDelta > 0 )
+ {
+ if( nDelta == 1 )
+ CursorDown();
+ else
+ PageDown( (USHORT) nDelta );
+ }
+ else
+ {
+ nDelta *= (-1);
+ if( nDelta == 1 )
+ CursorUp();
+ else
+ PageUp( (USHORT) nDelta );
+ }
+ bInVScrollHdl = FALSE;
+ return 0;
+}
+
+
+void SvImpLBox::CursorDown()
+{
+ SvLBoxEntry* pNextFirstToDraw = (SvLBoxEntry*)(pView->NextVisible( pStartEntry));
+ if( pNextFirstToDraw )
+ {
+ nFlags &= (~F_FILLING);
+ pView->NotifyScrolling( -1 );
+ ShowCursor( FALSE );
+ pView->Update();
+ pStartEntry = pNextFirstToDraw;
+ Rectangle aArea( GetVisibleArea() );
+ pView->Scroll( 0, -(pView->GetEntryHeight()), aArea, SCROLL_NOCHILDREN );
+ pView->Update();
+ ShowCursor( TRUE );
+ pView->NotifyScrolled();
+ }
+}
+
+void SvImpLBox::CursorUp()
+{
+ SvLBoxEntry* pPrevFirstToDraw = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry));
+ if( pPrevFirstToDraw )
+ {
+ nFlags &= (~F_FILLING);
+ long nEntryHeight = pView->GetEntryHeight();
+ pView->NotifyScrolling( 1 );
+ ShowCursor( FALSE );
+ pView->Update();
+ pStartEntry = pPrevFirstToDraw;
+ Rectangle aArea( GetVisibleArea() );
+ aArea.Bottom() -= nEntryHeight;
+ pView->Scroll( 0, nEntryHeight, aArea, SCROLL_NOCHILDREN );
+ pView->Update();
+ ShowCursor( TRUE );
+ pView->NotifyScrolled();
+ }
+}
+
+void SvImpLBox::PageDown( USHORT nDelta )
+{
+ USHORT nRealDelta = nDelta;
+
+ if( !nDelta )
+ return;
+
+ SvLBoxEntry* pNext;
+ pNext = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nRealDelta ));
+ if( (ULONG)pNext == (ULONG)pStartEntry )
+ return;
+
+ ShowCursor( FALSE );
+
+ nFlags &= (~F_FILLING);
+ pView->Update();
+ pStartEntry = pNext;
+
+ if( nRealDelta >= nVisibleCount )
+ {
+ pView->Invalidate( GetVisibleArea() );
+ pView->Update();
+ }
+ else
+ {
+ long nScroll = nRealDelta * (-1);
+ pView->NotifyScrolling( nScroll );
+ Rectangle aArea( GetVisibleArea() );
+ nScroll = pView->GetEntryHeight()*nRealDelta;
+ nScroll = -nScroll;
+ pView->Update();
+ pView->Scroll( 0, nScroll, aArea, SCROLL_NOCHILDREN );
+ pView->Update();
+ pView->NotifyScrolled();
+ }
+
+ ShowCursor( TRUE );
+}
+
+void SvImpLBox::PageUp( USHORT nDelta )
+{
+ USHORT nRealDelta = nDelta;
+ if( !nDelta )
+ return;
+
+ SvLBoxEntry* pPrev = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry, nRealDelta ));
+ if( (ULONG)pPrev == (ULONG)pStartEntry )
+ return;
+
+ nFlags &= (~F_FILLING);
+ ShowCursor( FALSE );
+
+ pView->Update();
+ pStartEntry = pPrev;
+ if( nRealDelta >= nVisibleCount )
+ {
+ pView->Invalidate( GetVisibleArea() );
+ pView->Update();
+ }
+ else
+ {
+ long nEntryHeight = pView->GetEntryHeight();
+ pView->NotifyScrolling( (long)nRealDelta );
+ Rectangle aArea( GetVisibleArea() );
+ pView->Update();
+ pView->Scroll( 0, nEntryHeight*nRealDelta, aArea, SCROLL_NOCHILDREN );
+ pView->Update();
+ pView->NotifyScrolled();
+ }
+
+ ShowCursor( TRUE );
+}
+
+void SvImpLBox::KeyUp( BOOL bPageUp, BOOL bNotifyScroll )
+{
+ if( !aVerSBar.IsVisible() )
+ return;
+
+ long nDelta;
+ if( bPageUp )
+ nDelta = aVerSBar.GetPageSize();
+ else
+ nDelta = 1;
+
+ long nThumbPos = aVerSBar.GetThumbPos();
+
+ if( nThumbPos < nDelta )
+ nDelta = nThumbPos;
+
+ if( nDelta <= 0 )
+ return;
+
+ nFlags &= (~F_FILLING);
+ if( bNotifyScroll )
+ BeginScroll();
+
+ aVerSBar.SetThumbPos( nThumbPos - nDelta );
+ if( bPageUp )
+ PageUp( (short)nDelta );
+ else
+ CursorUp();
+
+ if( bNotifyScroll )
+ EndScroll();
+}
+
+
+void SvImpLBox::KeyDown( BOOL bPageDown, BOOL bNotifyScroll )
+{
+ if( !aVerSBar.IsVisible() )
+ return;
+
+ long nDelta;
+ if( bPageDown )
+ nDelta = aVerSBar.GetPageSize();
+ else
+ nDelta = 1;
+
+ long nThumbPos = aVerSBar.GetThumbPos();
+ long nVisibleSize = aVerSBar.GetVisibleSize();
+ long nRange = aVerSBar.GetRange().Len();
+
+ long nTmp = nThumbPos+nVisibleSize;
+ while( (nDelta > 0) && (nTmp+nDelta) >= nRange )
+ nDelta--;
+
+ if( nDelta <= 0 )
+ return;
+
+ nFlags &= (~F_FILLING);
+ if( bNotifyScroll )
+ BeginScroll();
+
+ aVerSBar.SetThumbPos( nThumbPos+nDelta );
+ if( bPageDown )
+ PageDown( (short)nDelta );
+ else
+ CursorDown();
+
+ if( bNotifyScroll )
+ EndScroll();
+}
+
+
+
+void SvImpLBox::InvalidateEntriesFrom( long nY ) const
+{
+ if( !(nFlags & F_IN_PAINT ))
+ {
+ Rectangle aRect( GetVisibleArea() );
+ aRect.Top() = nY;
+ pView->Invalidate( aRect );
+ }
+}
+
+void SvImpLBox::InvalidateEntry( long nY ) const
+{
+ if( !(nFlags & F_IN_PAINT ))
+ {
+ Rectangle aRect( GetVisibleArea() );
+ long nMaxBottom = aRect.Bottom();
+ aRect.Top() = nY;
+ aRect.Bottom() = nY; aRect.Bottom() += pView->GetEntryHeight();
+ if( aRect.Top() > nMaxBottom )
+ return;
+ if( aRect.Bottom() > nMaxBottom )
+ aRect.Bottom() = nMaxBottom;
+ pView->Invalidate( aRect );
+ }
+}
+
+void SvImpLBox::InvalidateEntry( SvLBoxEntry* pEntry )
+{
+ if( GetUpdateMode() )
+ {
+ long nPrev = nMostRight;
+ SetMostRight( pEntry );
+ if( nPrev < nMostRight )
+ ShowVerSBar();
+ }
+ if( !(nFlags & F_IN_PAINT ))
+ {
+ BOOL bHasFocusRect = FALSE;
+ if( pEntry==pCursor && pView->HasFocus() )
+ {
+ bHasFocusRect = TRUE;
+ ShowCursor( FALSE );
+ }
+ InvalidateEntry( GetEntryLine( pEntry ) );
+ if( bHasFocusRect )
+ ShowCursor( TRUE );
+ }
+}
+
+
+void SvImpLBox::RecalcFocusRect()
+{
+ if( pView->HasFocus() && pCursor )
+ {
+ pView->HideFocus();
+ long nY = GetEntryLine( pCursor );
+ Rectangle aRect = pView->GetFocusRect( pCursor, nY );
+ CalcCellFocusRect( pCursor, aRect );
+ Region aOldClip( pView->GetClipRegion());
+ Region aClipRegion( GetClipRegionRect() );
+ pView->SetClipRegion( aClipRegion );
+ pView->ShowFocus( aRect );
+ pView->SetClipRegion( aOldClip );
+ }
+}
+
+//
+// Setzt Cursor. Passt bei SingleSelection die Selektion an
+//
+
+void SvImpLBox::SetCursor( SvLBoxEntry* pEntry, BOOL bForceNoSelect )
+{
+ SvViewDataEntry* pViewDataNewCur = 0;
+ if( pEntry )
+ pViewDataNewCur= pView->GetViewDataEntry(pEntry);
+ if( pEntry &&
+ pEntry == pCursor &&
+ pViewDataNewCur->HasFocus() &&
+ pViewDataNewCur->IsSelected())
+ {
+ return;
+ }
+
+ // if this cursor is not selectable, find first visible that is and use it
+ while( pEntry && pViewDataNewCur && !pViewDataNewCur->IsSelectable() )
+ {
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ pViewDataNewCur = pEntry ? pView->GetViewDataEntry(pEntry) : 0;
+ }
+
+ SvLBoxEntry* pOldCursor = pCursor;
+ if( pCursor && pEntry != pCursor )
+ {
+ pView->SetEntryFocus( pCursor, FALSE );
+ if( bSimpleTravel )
+ pView->Select( pCursor, FALSE );
+ pView->HideFocus();
+ }
+ pCursor = pEntry;
+ if( pCursor )
+ {
+ pViewDataNewCur->SetFocus( TRUE );
+ if(!bForceNoSelect && bSimpleTravel && !(nFlags & F_DESEL_ALL) && GetUpdateMode())
+ {
+ pView->Select( pCursor, TRUE );
+ }
+ // Mehrfachselektion: Im Cursor-Move selektieren, wenn
+ // nicht im Add-Mode (Ctrl-F8)
+ else if( GetUpdateMode() &&
+ pView->GetSelectionMode() == MULTIPLE_SELECTION &&
+ !(nFlags & F_DESEL_ALL) && !aSelEng.IsAddMode() &&
+ !bForceNoSelect )
+ {
+ pView->Select( pCursor, TRUE );
+ }
+ else
+ {
+ ShowCursor( TRUE );
+ }
+
+ if( pAnchor )
+ {
+ DBG_ASSERT(aSelEng.GetSelectionMode() != SINGLE_SELECTION,"Mode?");
+ SetAnchorSelection( pOldCursor, pCursor );
+ }
+ }
+ nFlags &= (~F_DESEL_ALL);
+}
+
+void SvImpLBox::ShowCursor( BOOL bShow )
+{
+ if( !bShow || !pCursor || !pView->HasFocus() )
+ {
+ Region aOldClip( pView->GetClipRegion());
+ Region aClipRegion( GetClipRegionRect() );
+ pView->SetClipRegion( aClipRegion );
+ pView->HideFocus();
+ pView->SetClipRegion( aOldClip );
+ }
+ else
+ {
+ long nY = GetEntryLine( pCursor );
+ Rectangle aRect = pView->GetFocusRect( pCursor, nY );
+ CalcCellFocusRect( pCursor, aRect );
+ Region aOldClip( pView->GetClipRegion());
+ Region aClipRegion( GetClipRegionRect() );
+ pView->SetClipRegion( aClipRegion );
+ pView->ShowFocus( aRect );
+ pView->SetClipRegion( aOldClip );
+ }
+}
+
+
+
+void SvImpLBox::UpdateAll( BOOL bInvalidateCompleteView,
+ BOOL bUpdateVerScrollBar )
+{
+ if( bUpdateVerScrollBar )
+ FindMostRight(0);
+ aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
+ SyncVerThumb();
+ FillView();
+ ShowVerSBar();
+ if( bSimpleTravel && pCursor && pView->HasFocus() )
+ pView->Select( pCursor, TRUE );
+ ShowCursor( TRUE );
+ if( bInvalidateCompleteView )
+ pView->Invalidate();
+ else
+ pView->Invalidate( GetVisibleArea() );
+}
+
+IMPL_LINK_INLINE_START( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
+{
+ long nDelta = pScrollBar->GetDelta();
+ if( nDelta )
+ {
+ if( pView->IsEditingActive() )
+ {
+ pView->EndEditing( TRUE ); // Cancel
+ pView->Update();
+ }
+ pView->nFocusWidth = -1;
+ KeyLeftRight( nDelta );
+ }
+ return 0;
+}
+IMPL_LINK_INLINE_END( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
+
+void SvImpLBox::KeyLeftRight( long nDelta )
+{
+ if( !(nFlags & F_IN_RESIZE) )
+ pView->Update();
+ BeginScroll();
+ nFlags &= (~F_FILLING);
+ pView->NotifyScrolling( 0 ); // 0 == horizontales Scrolling
+ ShowCursor( FALSE );
+
+ // neuen Origin berechnen
+ long nPos = aHorSBar.GetThumbPos();
+ Point aOrigin( -nPos, 0 );
+
+ MapMode aMapMode( pView->GetMapMode() );
+ aMapMode.SetOrigin( aOrigin );
+ pView->SetMapMode( aMapMode );
+
+ if( !(nFlags & F_IN_RESIZE) )
+ {
+ Rectangle aRect( GetVisibleArea() );
+ pView->Scroll( -nDelta, 0, aRect, SCROLL_NOCHILDREN );
+ }
+ else
+ pView->Invalidate();
+ RecalcFocusRect();
+ ShowCursor( TRUE );
+ pView->NotifyScrolled();
+}
+
+
+// gibt letzten Eintrag zurueck, wenn Position unter
+// dem letzten Eintrag ist
+SvLBoxEntry* SvImpLBox::GetClickedEntry( const Point& rPoint ) const
+{
+ DBG_ASSERT( pView->GetModel(), "SvImpLBox::GetClickedEntry: how can this ever happen? Please tell me (frank.schoenheit@sun.com) how to reproduce!" );
+ if ( !pView->GetModel() )
+ // this is quite impossible. Nevertheless, stack traces from the crash reporter
+ // suggest it isn't. Okay, make it safe, and wait for somebody to reproduce it
+ // reliably :-\ ....
+ // #122359# / 2005-05-23 / frank.schoenheit@sun.com
+ return NULL;
+ if( pView->GetEntryCount() == 0 || !pStartEntry || !pView->GetEntryHeight())
+ return 0;
+
+ USHORT nClickedEntry = (USHORT)(rPoint.Y() / pView->GetEntryHeight() );
+ USHORT nTemp = nClickedEntry;
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nTemp ));
+ return pEntry;
+}
+
+//
+// prueft, ob der Eintrag "richtig" getroffen wurde
+// (Focusrect+ ContextBitmap bei TreeListBox)
+//
+BOOL SvImpLBox::EntryReallyHit(SvLBoxEntry* pEntry,const Point& rPosPixel,long nLine)
+{
+ BOOL bRet;
+ // bei "besonderen" Entries (mit CheckButtons usw.) sind wir
+ // nicht so pingelig
+ if( pEntry->ItemCount() >= 3 )
+ return TRUE;
+
+ Rectangle aRect( pView->GetFocusRect( pEntry, nLine ));
+ aRect.Right() = GetOutputSize().Width() - pView->GetMapMode().GetOrigin().X();
+ if( pView->IsA() == SV_LISTBOX_ID_TREEBOX )
+ {
+ SvLBoxContextBmp* pBmp = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ aRect.Left() -= pBmp->GetSize(pView,pEntry).Width();
+ aRect.Left() -= 4; // etwas Speilraum lassen
+ }
+ Point aPos( rPosPixel );
+ aPos -= pView->GetMapMode().GetOrigin();
+ if( aRect.IsInside( aPos ) )
+ bRet = TRUE;
+ else
+ bRet = FALSE;
+ return bRet;
+}
+
+
+// gibt 0 zurueck, wenn Position unter dem letzten Eintrag ist
+SvLBoxEntry* SvImpLBox::GetEntry( const Point& rPoint ) const
+{
+ if( (pView->GetEntryCount() == 0) || !pStartEntry ||
+ (rPoint.Y() > aOutputSize.Height())
+ || !pView->GetEntryHeight())
+ return 0;
+
+ USHORT nClickedEntry = (USHORT)(rPoint.Y() / pView->GetEntryHeight() );
+ USHORT nTemp = nClickedEntry;
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nTemp ));
+ if( nTemp != nClickedEntry )
+ pEntry = 0;
+ return pEntry;
+}
+
+
+SvLBoxEntry* SvImpLBox::MakePointVisible(const Point& rPoint,BOOL bNotifyScroll)
+{
+ if( !pCursor )
+ return 0;
+ long nY = rPoint.Y();
+ SvLBoxEntry* pEntry = 0;
+ long nMax = aOutputSize.Height();
+ if( nY < 0 || nY >= nMax ) // aOutputSize.Height() )
+ {
+ if( nY < 0 )
+ pEntry = (SvLBoxEntry*)(pView->PrevVisible( pCursor ));
+ else
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pCursor ));
+
+ if( pEntry && pEntry != pCursor )
+ pView->SetEntryFocus( pCursor, FALSE );
+
+ if( nY < 0 )
+ KeyUp( FALSE, bNotifyScroll );
+ else
+ KeyDown( FALSE, bNotifyScroll );
+ }
+ else
+ {
+ pEntry = GetClickedEntry( rPoint );
+ if( !pEntry )
+ {
+ USHORT nSteps = 0xFFFF;
+ // LastVisible ist noch nicht implementiert!
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nSteps ));
+ }
+ if( pEntry )
+ {
+ if( pEntry != pCursor &&
+ aSelEng.GetSelectionMode() == SINGLE_SELECTION
+ )
+ pView->Select( pCursor, FALSE );
+ }
+ }
+ return pEntry;
+}
+
+Rectangle SvImpLBox::GetClipRegionRect() const
+{
+ Point aOrigin( pView->GetMapMode().GetOrigin() );
+ aOrigin.X() *= -1; // Umrechnung Dokumentkoord.
+ Rectangle aClipRect( aOrigin, aOutputSize );
+ aClipRect.Bottom()++;
+ return aClipRect;
+}
+
+
+void SvImpLBox::Paint( const Rectangle& rRect )
+{
+ if( !pView->GetVisibleCount() )
+ return;
+
+ nFlags |= F_IN_PAINT;
+
+ if( nFlags & F_FILLING )
+ {
+ SvLBoxEntry* pFirst = pView->First();
+ if( pFirst != pStartEntry )
+ {
+ ShowCursor( FALSE );
+ pStartEntry = pView->First();
+ aVerSBar.SetThumbPos( 0 );
+ StopUserEvent();
+ ShowCursor( TRUE );
+ nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)1);
+ return;
+ }
+ }
+
+ if( !pStartEntry )
+ {
+ pStartEntry = pView->First();
+ }
+
+#ifdef XX_OV
+ ULONG nXAbsPos = (USHORT)pTree->GetAbsPos( pStartEntry );
+ ULONG nXVisPos = pView->GetVisiblePos( pStartEntry );
+ SvLBoxString* pXStr = (SvLBoxString*)pStartEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING);
+#endif
+
+
+
+ if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
+ SetNodeBmpTabDistance();
+
+ long nRectHeight = rRect.GetHeight();
+ long nEntryHeight = pView->GetEntryHeight();
+
+ // Bereich der zu zeichnenden Entries berechnen
+ USHORT nStartLine = (USHORT)( rRect.Top() / nEntryHeight );
+ USHORT nCount = (USHORT)( nRectHeight / nEntryHeight );
+ nCount += 2; // keine Zeile vergessen
+
+ long nY = nStartLine * nEntryHeight;
+ SvLBoxEntry* pEntry = pStartEntry;
+ while( nStartLine && pEntry )
+ {
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ nStartLine--;
+ }
+
+ Region aClipRegion( GetClipRegionRect() );
+
+ // erst die Linien Zeichnen, dann clippen!
+ pView->SetClipRegion();
+ if( nWinBits & ( WB_HASLINES | WB_HASLINESATROOT ) )
+ DrawNet();
+
+ pView->SetClipRegion( aClipRegion );
+
+ for( USHORT n=0; n< nCount && pEntry; n++ )
+ {
+ /*long nMaxRight=*/
+ pView->PaintEntry1( pEntry, nY, 0xffff, TRUE );
+ nY += nEntryHeight;
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+
+ if ( !pCursor && ( ( nExtendedWinBits & EWB_NO_AUTO_CURENTRY ) == 0 ) )
+ {
+ // do not select if multiselection or explicit set
+ BOOL bNotSelect = ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION )
+ || ( ( nWinBits & WB_NOINITIALSELECTION ) == WB_NOINITIALSELECTION );
+ SetCursor( pStartEntry, bNotSelect );
+ }
+
+ nFlags &= (~F_DESEL_ALL);
+ pView->SetClipRegion();
+ Rectangle aRect;
+ if( !(nFlags & F_PAINTED) )
+ {
+ nFlags |= F_PAINTED;
+ RepaintScrollBars();
+ }
+ nFlags &= (~F_IN_PAINT);
+}
+
+void SvImpLBox::MakeVisible( SvLBoxEntry* pEntry, BOOL bMoveToTop )
+{
+ if( !pEntry )
+ return;
+
+ BOOL bInView = IsEntryInView( pEntry );
+
+ if( bInView && (!bMoveToTop || pStartEntry == pEntry) )
+ return; // ist schon sichtbar
+
+ if( pStartEntry || (nWinBits & WB_FORCE_MAKEVISIBLE) )
+ nFlags &= (~F_FILLING);
+ if( !bInView )
+ {
+ if( !pView->IsEntryVisible(pEntry) ) // Parent(s) zugeklappt ?
+ {
+ SvLBoxEntry* pParent = pView->GetParent( pEntry );
+ while( pParent )
+ {
+ if( !pView->IsExpanded( pParent ) )
+ {
+ #ifdef DBG_UTIL
+ BOOL bRet =
+ #endif
+ pView->Expand( pParent );
+ DBG_ASSERT(bRet,"Not expanded!");
+ }
+ pParent = pView->GetParent( pParent );
+ }
+ // Passen Childs der Parents in View oder muessen wir scrollen ?
+ if( IsEntryInView( pEntry ) && !bMoveToTop )
+ return; // Scrollen nicht noetig -> tschuess
+ }
+ }
+
+ pStartEntry = pEntry;
+ ShowCursor( FALSE );
+ FillView();
+ aVerSBar.SetThumbPos( (long)(pView->GetVisiblePos( pStartEntry )) );
+ ShowCursor( TRUE );
+ pView->Invalidate();
+}
+
+
+void SvImpLBox::RepaintSelectionItems()
+{
+ if( !pView->GetVisibleCount() )
+ return;
+
+ if( !pStartEntry )
+ pStartEntry = pView->First();
+
+ if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
+ SetNodeBmpTabDistance();
+
+ ShowCursor( FALSE );
+
+ long nEntryHeight = pView->GetEntryHeight();
+
+ ULONG nCount = nVisibleCount;
+ long nY = 0;
+ SvLBoxEntry* pEntry = pStartEntry;
+ for( ULONG n=0; n< nCount && pEntry; n++ )
+ {
+ pView->PaintEntry1( pEntry, nY, 0xffff ); //wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
+ nY += nEntryHeight;
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+
+ ShowCursor( TRUE );
+}
+
+
+void SvImpLBox::DrawNet()
+{
+ if( pView->GetVisibleCount() < 2 && !pStartEntry->HasChildsOnDemand() &&
+ !pStartEntry->HasChilds() )
+ return;
+
+ //for platforms who don't have nets, DrawNativeControl does nothing and return true
+ //so that SvImpLBox::DrawNet() doesn't draw anything too
+ if(pView->IsNativeControlSupported( CTRL_LISTNET, PART_ENTIRE_CONTROL)) {
+ ImplControlValue aControlValue;
+ Point aTemp(0,0); // temporary needed for g++ 3.3.5
+ Rectangle aCtrlRegion( aTemp, Size( 0, 0 ) );
+ ControlState nState = CTRL_STATE_ENABLED;
+ if( pView->DrawNativeControl( CTRL_LISTNET, PART_ENTIRE_CONTROL,
+ aCtrlRegion, nState, aControlValue, rtl::OUString() ) )
+ {
+ return;
+ }
+
+ }
+
+ long nEntryHeight = pView->GetEntryHeight();
+ long nEntryHeightDIV2 = nEntryHeight / 2;
+ if( nEntryHeightDIV2 && !(nEntryHeight & 0x0001))
+ nEntryHeightDIV2--;
+
+ SvLBoxEntry* pChild;
+ SvLBoxEntry* pEntry = pStartEntry;
+
+ SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
+ while( pTree->GetDepth( pEntry ) > 0 )
+ pEntry = pView->GetParent( pEntry );
+ USHORT nOffs = (USHORT)(pView->GetVisiblePos( pStartEntry ) -
+ pView->GetVisiblePos( pEntry ));
+ long nY = 0;
+ nY -= ( nOffs * nEntryHeight );
+
+ DBG_ASSERT(pFirstDynamicTab,"No Tree!");
+
+ Color aOldLineColor = pView->GetLineColor();
+ const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
+ Color aCol= rStyleSettings.GetFaceColor();
+
+ if( aCol.IsRGBEqual( pView->GetBackground().GetColor()) )
+ aCol = rStyleSettings.GetShadowColor();
+ pView->SetLineColor( aCol );
+ Point aPos1, aPos2;
+ USHORT nDistance;
+ ULONG nMax = nVisibleCount + nOffs + 1;
+
+ const Image& rExpandedNodeBitmap = GetExpandedNodeBmp();
+
+ for( ULONG n=0; n< nMax && pEntry; n++ )
+ {
+ if( pView->IsExpanded(pEntry) )
+ {
+ aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
+ // wenn keine ContextBitmap, dann etwas nach rechts
+ // unter den ersten Text (Node.Bmp ebenfalls
+ if( !pView->nContextBmpWidthMax )
+ aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
+
+ aPos1.Y() = nY;
+ aPos1.Y() += nEntryHeightDIV2;
+
+ pChild = pView->FirstChild( pEntry );
+ DBG_ASSERT(pChild,"Child?");
+ pChild = pTree->LastSibling( pChild );
+ nDistance = (USHORT)(pView->GetVisiblePos(pChild) -
+ pView->GetVisiblePos(pEntry));
+ aPos2 = aPos1;
+ aPos2.Y() += nDistance * nEntryHeight;
+ pView->DrawLine( aPos1, aPos2 );
+ }
+ // Sichtbar im Control ?
+ if( n>= nOffs && ((nWinBits & WB_HASLINESATROOT) || !pTree->IsAtRootDepth(pEntry)))
+ {
+ // kann aPos1 recyclet werden ?
+ if( !pView->IsExpanded(pEntry) )
+ {
+ // njet
+ aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
+ // wenn keine ContextBitmap, dann etwas nach rechts
+ // unter den ersten Text (Node.Bmp ebenfalls
+ if( !pView->nContextBmpWidthMax )
+ aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
+ aPos1.Y() = nY;
+ aPos1.Y() += nEntryHeightDIV2;
+ aPos2.X() = aPos1.X();
+ }
+ aPos2.Y() = aPos1.Y();
+ aPos2.X() -= pView->GetIndent();
+ pView->DrawLine( aPos1, aPos2 );
+ }
+ nY += nEntryHeight;
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ if( nWinBits & WB_HASLINESATROOT )
+ {
+ pEntry = pView->First();
+ aPos1.X() = pView->GetTabPos( pEntry, pFirstDynamicTab);
+ // wenn keine ContextBitmap, dann etwas nach rechts
+ // unter den ersten Text (Node.Bmp ebenfalls
+ if( !pView->nContextBmpWidthMax )
+ aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
+ aPos1.X() -= pView->GetIndent();
+ aPos1.Y() = GetEntryLine( pEntry );
+ aPos1.Y() += nEntryHeightDIV2;
+ pChild = pTree->LastSibling( pEntry );
+ aPos2.X() = aPos1.X();
+ aPos2.Y() = GetEntryLine( pChild );
+ aPos2.Y() += nEntryHeightDIV2;
+ pView->DrawLine( aPos1, aPos2 );
+ }
+ pView->SetLineColor( aOldLineColor );
+}
+
+
+static long GetOptSize( TabBar* pTabBar )
+{
+ return pTabBar->CalcWindowSizePixel().Width();
+}
+
+void SvImpLBox::PositionScrollBars( Size& rSize, USHORT nMask )
+{
+ long nOverlap = 0;
+
+ Size aVerSize( nVerSBarWidth, rSize.Height() );
+ Size aHorSize( rSize.Width(), nHorSBarHeight );
+ long nTabBarWidth = 0;
+ if( pTabBar )
+ {
+ nTabBarWidth = GetOptSize( pTabBar );
+ long nMaxWidth = (rSize.Width() * 700) / 1000;
+ if( nTabBarWidth > nMaxWidth )
+ {
+ nTabBarWidth = nMaxWidth;
+ pTabBar->SetStyle( pTabBar->GetStyle() | WB_MINSCROLL );
+ }
+ else
+ {
+ WinBits nStyle = pTabBar->GetStyle();
+ nStyle &= ~(WB_MINSCROLL);
+ pTabBar->SetStyle( nStyle );
+ }
+ aHorSize.Width() -= nTabBarWidth;
+ Size aTabSize( pTabBar->GetSizePixel() );
+ aTabSize.Width() = nTabBarWidth;
+ pTabBar->SetSizePixel( aTabSize );
+ }
+ if( nMask & 0x0001 )
+ aHorSize.Width() -= nVerSBarWidth;
+ if( nMask & 0x0002 )
+ aVerSize.Height() -= nHorSBarHeight;
+
+ aVerSize.Height() += 2 * nOverlap;
+ Point aVerPos( rSize.Width() - aVerSize.Width() + nOverlap, -nOverlap );
+ aVerSBar.SetPosSizePixel( aVerPos, aVerSize );
+
+ aHorSize.Width() += 2 * nOverlap;
+ Point aHorPos( -nOverlap, rSize.Height() - aHorSize.Height() + nOverlap );
+ if( pTabBar )
+ pTabBar->SetPosPixel( aHorPos );
+ aHorPos.X() += nTabBarWidth;
+ aHorSBar.SetPosSizePixel( aHorPos, aHorSize );
+
+ if( nMask & 0x0001 )
+ rSize.Width() = aVerPos.X();
+ if( nMask & 0x0002 )
+ rSize.Height() = aHorPos.Y();
+ if( pTabBar )
+ pTabBar->Show();
+
+ if( (nMask & (0x0001|0x0002)) == (0x0001|0x0002) )
+ aScrBarBox.Show();
+ else
+ aScrBarBox.Hide();
+
+}
+
+// nResult: Bit0 == VerSBar Bit1 == HorSBar
+USHORT SvImpLBox::AdjustScrollBars( Size& rSize )
+{
+ long nEntryHeight = pView->GetEntryHeight();
+ if( !nEntryHeight )
+ return 0;
+
+ USHORT nResult = 0;
+
+ Size aOSize( pView->Control::GetOutputSizePixel() );
+
+ BOOL bVerSBar = ( pView->nWindowStyle & WB_VSCROLL ) != 0;
+ BOOL bHorBar = FALSE;
+ long nMaxRight = aOSize.Width(); //GetOutputSize().Width();
+ Point aOrigin( pView->GetMapMode().GetOrigin() );
+ aOrigin.X() *= -1;
+ nMaxRight += aOrigin.X() - 1;
+ long nVis = nMostRight - aOrigin.X();
+ if( pTabBar || (
+ (pView->nWindowStyle & WB_HSCROLL) &&
+ (nVis < nMostRight || nMaxRight < nMostRight) ))
+ bHorBar = TRUE;
+
+ // Anzahl aller nicht eingeklappten Eintraege
+ ULONG nTotalCount = pView->GetVisibleCount();
+
+ // Anzahl in der View sichtbarer Eintraege
+ nVisibleCount = aOSize.Height() / nEntryHeight;
+
+ // muessen wir eine vertikale Scrollbar einblenden?
+ if( bVerSBar || nTotalCount > nVisibleCount )
+ {
+ nResult = 1;
+ nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
+ nMaxRight -= nVerSBarWidth;
+ if( !bHorBar )
+ {
+ if( (pView->nWindowStyle & WB_HSCROLL) &&
+ (nVis < nMostRight || nMaxRight < nMostRight) )
+ bHorBar = TRUE;
+ }
+ }
+
+ // muessen wir eine horizontale Scrollbar einblenden?
+ if( bHorBar )
+ {
+ nResult |= 0x0002;
+ // die Anzahl der in der View sichtbaren Eintraege
+ // muss neu berechnet werden, da die horizontale
+ // ScrollBar eingeblendet wird
+ nVisibleCount = (aOSize.Height() - nHorSBarHeight) / nEntryHeight;
+ // eventuell brauchen wir jetzt doch eine vertikale ScrollBar
+ if( !(nResult & 0x0001) &&
+ ((nTotalCount > nVisibleCount) || bVerSBar) )
+ {
+ nResult = 3;
+ nFlags |= F_VER_SBARSIZE_WITH_HBAR;
+ }
+ }
+
+ PositionScrollBars( aOSize, nResult );
+
+ // Range, VisibleRange usw. anpassen
+
+ // Output-Size aktualisieren, falls wir scrollen muessen
+ Rectangle aRect;
+ aRect.SetSize( aOSize );
+ aSelEng.SetVisibleArea( aRect );
+
+ // Vertikale ScrollBar
+ long nTemp = (long)nVisibleCount;
+ nTemp--;
+ if( nTemp != aVerSBar.GetVisibleSize() )
+ {
+ if( !bInVScrollHdl )
+ {
+ aVerSBar.SetPageSize( nTemp - 1 );
+ aVerSBar.SetVisibleSize( nTemp );
+ }
+ else
+ {
+ nFlags |= F_ENDSCROLL_SET_VIS_SIZE;
+ nNextVerVisSize = nTemp;
+ }
+ }
+
+ // Horizontale ScrollBar
+ nTemp = aHorSBar.GetThumbPos();
+ aHorSBar.SetVisibleSize( aOSize.Width() );
+ long nNewThumbPos = aHorSBar.GetThumbPos();
+ Range aRange( aHorSBar.GetRange() );
+ if( aRange.Max() < nMostRight+25 )
+ {
+ aRange.Max() = nMostRight+25;
+ aHorSBar.SetRange( aRange );
+ }
+
+ if( nTemp != nNewThumbPos )
+ {
+ nTemp = nNewThumbPos - nTemp;
+ if( pView->IsEditingActive() )
+ {
+ pView->EndEditing( TRUE ); // Cancel
+ pView->Update();
+ }
+ pView->nFocusWidth = -1;
+ KeyLeftRight( nTemp );
+ }
+
+ if( nResult & 0x0001 )
+ aVerSBar.Show();
+ else
+ aVerSBar.Hide();
+
+ if( nResult & 0x0002 )
+ aHorSBar.Show();
+ else
+ {
+ if( !pTabBar )
+ aHorSBar.Hide();
+ }
+ rSize = aOSize;
+ return nResult;
+}
+
+void SvImpLBox::InitScrollBarBox()
+{
+ aScrBarBox.SetSizePixel( Size(nVerSBarWidth, nHorSBarHeight) );
+ Size aSize( pView->Control::GetOutputSizePixel() );
+ aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth, aSize.Height()-nHorSBarHeight));
+}
+
+void SvImpLBox::Resize()
+{
+ Size aSize( pView->Control::GetOutputSizePixel());
+ if( aSize.Width() <= 0 || aSize.Height() <= 0 )
+ return;
+ nFlags |= F_IN_RESIZE;
+ InitScrollBarBox();
+
+ if( pView->GetEntryHeight())
+ {
+ AdjustScrollBars( aOutputSize );
+ FillView();
+ }
+ // !!!HACK, da in Floating- & Docking-Windows nach Resizes
+ // die Scrollbars nicht richtig, bzw. ueberhaupt nicht gezeichnet werden
+ if( aHorSBar.IsVisible())
+ aHorSBar.Invalidate();
+ if( aVerSBar.IsVisible())
+ aVerSBar.Invalidate();
+ nFlags &= (~(F_IN_RESIZE | F_PAINTED));
+}
+
+void SvImpLBox::FillView()
+{
+ if( !pStartEntry )
+ {
+ USHORT nVisibleViewCount = (USHORT)(pView->GetVisibleCount());
+ USHORT nTempThumb = (USHORT)aVerSBar.GetThumbPos();
+ if( nTempThumb >= nVisibleViewCount )
+ nTempThumb = nVisibleViewCount - 1;
+ pStartEntry = (SvLBoxEntry*)(pView->GetEntryAtVisPos(nTempThumb));
+ }
+ if( pStartEntry )
+ {
+ USHORT nLast = (USHORT)(pView->GetVisiblePos( (SvLBoxEntry*)(pView->LastVisible())));
+ USHORT nThumb = (USHORT)(pView->GetVisiblePos( pStartEntry ));
+ USHORT nCurDispEntries = nLast-nThumb+1;
+ if( nCurDispEntries < nVisibleCount )
+ {
+ ShowCursor( FALSE );
+ // Fenster fuellen, indem der Thumb schrittweise
+ // nach oben bewegt wird
+ BOOL bFound = FALSE;
+ SvLBoxEntry* pTemp = pStartEntry;
+ while( nCurDispEntries < nVisibleCount && pTemp )
+ {
+ pTemp = (SvLBoxEntry*)(pView->PrevVisible(pStartEntry));
+ if( pTemp )
+ {
+ nThumb--;
+ pStartEntry = pTemp;
+ nCurDispEntries++;
+ bFound = TRUE;
+ }
+ }
+ if( bFound )
+ {
+ aVerSBar.SetThumbPos( nThumb );
+ ShowCursor( TRUE ); // Focusrect neu berechnen
+ pView->Invalidate();
+ }
+ }
+ }
+}
+
+
+
+
+void SvImpLBox::ShowVerSBar()
+{
+ BOOL bVerBar = ( pView->nWindowStyle & WB_VSCROLL ) != 0;
+ ULONG nVis = 0;
+ if( !bVerBar )
+ nVis = pView->GetVisibleCount();
+ if( bVerBar || (nVisibleCount && nVis > (ULONG)(nVisibleCount-1)) )
+ {
+ if( !aVerSBar.IsVisible() )
+ {
+ pView->nFocusWidth = -1;
+ AdjustScrollBars( aOutputSize );
+ if( GetUpdateMode() )
+ aVerSBar.Update();
+ }
+ }
+ else
+ {
+ if( aVerSBar.IsVisible() )
+ {
+ pView->nFocusWidth = -1;
+ AdjustScrollBars( aOutputSize );
+ }
+ }
+
+ long nMaxRight = GetOutputSize().Width();
+ Point aPos( pView->GetMapMode().GetOrigin() );
+ aPos.X() *= -1; // Umrechnung Dokumentkoord.
+ nMaxRight = nMaxRight + aPos.X() - 1;
+ if( nMaxRight < nMostRight )
+ {
+ if( !aHorSBar.IsVisible() )
+ {
+ pView->nFocusWidth = -1;
+ AdjustScrollBars( aOutputSize );
+ if( GetUpdateMode() )
+ aHorSBar.Update();
+ }
+ else
+ {
+ Range aRange( aHorSBar.GetRange() );
+ if( aRange.Max() < nMostRight+25 )
+ {
+ aRange.Max() = nMostRight+25;
+ aHorSBar.SetRange( aRange );
+ }
+ else
+ {
+ pView->nFocusWidth = -1;
+ AdjustScrollBars( aOutputSize );
+ }
+ }
+ }
+ else
+ {
+ if( aHorSBar.IsVisible() )
+ {
+ pView->nFocusWidth = -1;
+ AdjustScrollBars( aOutputSize );
+ }
+ }
+}
+
+
+void SvImpLBox::SyncVerThumb()
+{
+ if( pStartEntry )
+ {
+ long nEntryPos = pView->GetVisiblePos( pStartEntry );
+ aVerSBar.SetThumbPos( nEntryPos );
+ }
+ else
+ aVerSBar.SetThumbPos( 0 );
+}
+
+BOOL SvImpLBox::IsEntryInView( SvLBoxEntry* pEntry ) const
+{
+ // Parent eingeklappt
+ if( !pView->IsEntryVisible(pEntry) )
+ return FALSE;
+ long nY = GetEntryLine( pEntry );
+ if( nY < 0 )
+ return FALSE;
+ long nMax = nVisibleCount * pView->GetEntryHeight();
+ if( nY >= nMax )
+ return FALSE;
+ return TRUE;
+}
+
+
+long SvImpLBox::GetEntryLine( SvLBoxEntry* pEntry ) const
+{
+ if(!pStartEntry )
+ return -1; // unsichtbare Position
+
+ long nFirstVisPos = pView->GetVisiblePos( pStartEntry );
+ long nEntryVisPos = pView->GetVisiblePos( pEntry );
+ nFirstVisPos = nEntryVisPos - nFirstVisPos;
+ nFirstVisPos *= pView->GetEntryHeight();
+ return nFirstVisPos;
+}
+
+void SvImpLBox::SetEntryHeight( short /* nHeight */ )
+{
+ SetNodeBmpYOffset( GetExpandedNodeBmp() );
+ SetNodeBmpYOffset( GetCollapsedNodeBmp() );
+ if(!pView->HasViewData()) // stehen wir im Clear?
+ {
+ Size aSize = pView->Control::GetOutputSizePixel();
+ AdjustScrollBars( aSize );
+ }
+ else
+ {
+ Resize();
+ if( GetUpdateMode() )
+ pView->Invalidate();
+ }
+}
+
+
+
+// ***********************************************************************
+// Callback-Functions
+// ***********************************************************************
+
+void SvImpLBox::IndentChanged( short /* nIndentPixel */ ) {}
+
+void SvImpLBox::EntryExpanded( SvLBoxEntry* pEntry )
+{
+ // SelAllDestrAnch( FALSE, TRUE ); //DeselectAll();
+ if( GetUpdateMode() )
+ {
+ ShowCursor( FALSE );
+ long nY = GetEntryLine( pEntry );
+ if( IsLineVisible(nY) )
+ {
+ InvalidateEntriesFrom( nY );
+ FindMostRight( pEntry, 0 );
+ }
+ aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
+ // falls vor dem Thumb expandiert wurde, muss
+ // die Thumb-Position korrigiert werden.
+ SyncVerThumb();
+ ShowVerSBar();
+ ShowCursor( TRUE );
+ }
+}
+
+void SvImpLBox::EntryCollapsed( SvLBoxEntry* pEntry )
+{
+ if( !pView->IsEntryVisible( pEntry ) )
+ return;
+
+ ShowCursor( FALSE );
+
+ if( !pMostRightEntry || pTree->IsChild( pEntry,pMostRightEntry ) )
+ {
+ FindMostRight(0);
+ }
+
+ if( pStartEntry )
+ {
+ long nOldThumbPos = aVerSBar.GetThumbPos();
+ ULONG nVisList = pView->GetVisibleCount();
+ aVerSBar.SetRange( Range(0, nVisList-1) );
+ long nNewThumbPos = aVerSBar.GetThumbPos();
+ if( nNewThumbPos != nOldThumbPos )
+ {
+ pStartEntry = pView->First();
+ USHORT nDistance = (USHORT)nNewThumbPos;
+ if( nDistance )
+ pStartEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry,
+ nDistance));
+ if( GetUpdateMode() )
+ pView->Invalidate();
+ }
+ else
+ SyncVerThumb();
+ ShowVerSBar();
+ }
+ // wurde Cursor eingeklappt ?
+ if( pTree->IsChild( pEntry, pCursor ) )
+ SetCursor( pEntry );
+ if( GetUpdateMode() )
+ ShowVerSBar();
+ ShowCursor( TRUE );
+ if( GetUpdateMode() && pCursor )
+ pView->Select( pCursor, TRUE );
+}
+
+void SvImpLBox::CollapsingEntry( SvLBoxEntry* pEntry )
+{
+ if( !pView->IsEntryVisible( pEntry ) || !pStartEntry )
+ return;
+
+ SelAllDestrAnch( FALSE, TRUE ); // deselectall
+
+ // ist der eingeklappte Parent sichtbar ?
+ long nY = GetEntryLine( pEntry );
+ if( IsLineVisible(nY) )
+ {
+ if( GetUpdateMode() )
+ InvalidateEntriesFrom( nY );
+ }
+ else
+ {
+ if( pTree->IsChild(pEntry, pStartEntry) )
+ {
+ pStartEntry = pEntry;
+ if( GetUpdateMode() )
+ pView->Invalidate();
+ }
+ }
+}
+
+
+void SvImpLBox::SetNodeBmpYOffset( const Image& rBmp )
+{
+ Size aSize;
+ nYoffsNodeBmp = pView->GetHeightOffset( rBmp, aSize );
+ nNodeBmpWidth = aSize.Width();
+}
+
+void SvImpLBox::SetNodeBmpTabDistance()
+{
+ nNodeBmpTabDistance = -pView->GetIndent();
+ if( pView->nContextBmpWidthMax )
+ {
+ // nur, wenn der erste dynamische Tab zentriert ist
+ // (setze ich momentan voraus)
+ Size aSize = GetExpandedNodeBmp().GetSizePixel();
+ nNodeBmpTabDistance -= aSize.Width() / 2;
+ }
+}
+
+//
+// korrigiert bei SingleSelection den Cursor
+//
+void SvImpLBox::EntrySelected( SvLBoxEntry* pEntry, BOOL bSelect )
+{
+ if( nFlags & F_IGNORE_SELECT )
+ return;
+
+ /*
+ if( (nWinBits & WB_HIDESELECTION) && pEntry && !pView->HasFocus() )
+ {
+ SvViewData* pViewData = pView->GetViewData( pEntry );
+ pViewData->SetCursored( bSelect );
+ }
+ */
+
+ nFlags &= (~F_DESEL_ALL);
+ if( bSelect &&
+ aSelEng.GetSelectionMode() == SINGLE_SELECTION &&
+ pEntry != pCursor )
+ {
+ SetCursor( pEntry );
+ DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
+ }
+
+ if( GetUpdateMode() && pView->IsEntryVisible(pEntry) )
+ {
+ long nY = GetEntryLine( pEntry );
+ if( IsLineVisible( nY ) )
+ {
+ ShowCursor( FALSE );
+ pView->PaintEntry1( pEntry, nY, 0xffff ); // wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
+ ShowCursor( TRUE );
+ }
+ }
+}
+
+
+void SvImpLBox::RemovingEntry( SvLBoxEntry* pEntry )
+{
+ DestroyAnchor();
+
+ if( !pView->IsEntryVisible( pEntry ) )
+ {
+ // wenn Parent eingeklappt, dann tschuess
+ nFlags |= F_REMOVED_ENTRY_INVISIBLE;
+ return;
+ }
+
+ if( pEntry == pMostRightEntry || (
+ pEntry->HasChilds() && pView->IsExpanded(pEntry) &&
+ pTree->IsChild(pEntry, pMostRightEntry)))
+ {
+ nFlags |= F_REMOVED_RECALC_MOST_RIGHT;
+ }
+
+ SvLBoxEntry* pOldStartEntry = pStartEntry;
+
+ SvLBoxEntry* pParent = (SvLBoxEntry*)(pView->GetModel()->GetParent(pEntry));
+
+ if( pParent && pView->GetModel()->GetChildList(pParent)->Count() == 1 )
+ {
+ DBG_ASSERT( pView->IsExpanded( pParent ), "Parent not expanded");
+ pParent->SetFlags( pParent->GetFlags() | SV_ENTRYFLAG_NO_NODEBMP);
+ InvalidateEntry( pParent );
+ }
+
+ if( pCursor && pTree->IsChild( pEntry, pCursor) )
+ pCursor = pEntry;
+ if( pStartEntry && pTree->IsChild(pEntry,pStartEntry) )
+ pStartEntry = pEntry;
+
+ SvLBoxEntry* pTemp;
+ if( pCursor && pCursor == pEntry )
+ {
+ if( bSimpleTravel )
+ pView->Select( pCursor, FALSE );
+ ShowCursor( FALSE ); // Focus-Rect weg
+ // NextSibling, weil auch Childs des Cursors geloescht werden
+ pTemp = pView->NextSibling( pCursor );
+ if( !pTemp )
+ pTemp = (SvLBoxEntry*)(pView->PrevVisible( pCursor ));
+
+ SetCursor( pTemp, TRUE );
+ }
+ if( pStartEntry && pStartEntry == pEntry )
+ {
+ pTemp = pView->NextSibling( pStartEntry );
+ if( !pTemp )
+ pTemp = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry ));
+ pStartEntry = pTemp;
+ }
+ if( GetUpdateMode())
+ {
+ // wenns der letzte ist, muss invalidiert werden, damit die Linien
+ // richtig gezeichnet (in diesem Fall geloescht) werden.
+ if( pStartEntry && (pStartEntry != pOldStartEntry || pEntry == (SvLBoxEntry*)pView->GetModel()->Last()) )
+ {
+ aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry ));
+ pView->Invalidate( GetVisibleArea() );
+ }
+ else
+ InvalidateEntriesFrom( GetEntryLine( pEntry ) );
+ }
+}
+
+void SvImpLBox::EntryRemoved()
+{
+ if( nFlags & F_REMOVED_ENTRY_INVISIBLE )
+ {
+ nFlags &= (~F_REMOVED_ENTRY_INVISIBLE);
+ return;
+ }
+ if( !pStartEntry )
+ pStartEntry = pTree->First();
+ if( !pCursor )
+ SetCursor( pStartEntry, TRUE );
+
+ if( pCursor && (bSimpleTravel || !pView->GetSelectionCount() ))
+ pView->Select( pCursor, TRUE );
+
+ if( GetUpdateMode())
+ {
+ if( nFlags & F_REMOVED_RECALC_MOST_RIGHT )
+ FindMostRight(0);
+ aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
+ FillView();
+ if( pStartEntry )
+ // falls ueber dem Thumb geloescht wurde
+ aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry) );
+
+ ShowVerSBar();
+ if( pCursor && pView->HasFocus() && !pView->IsSelected(pCursor) )
+ {
+ if( pView->GetSelectionCount() )
+ {
+ // ist ein benachbarter Eintrag selektiert?
+ SvLBoxEntry* pNextCursor = (SvLBoxEntry*)pView->PrevVisible( pCursor );
+ if( !pNextCursor || !pView->IsSelected( pNextCursor ))
+ pNextCursor = (SvLBoxEntry*)pView->NextVisible( pCursor );
+ if( !pNextCursor || !pView->IsSelected( pNextCursor ))
+ // kein Nachbar selektiert: Ersten selektierten nehmen
+ pNextCursor = pView->FirstSelected();
+ SetCursor( pNextCursor );
+ MakeVisible( pCursor );
+ }
+ else
+ pView->Select( pCursor, TRUE );
+ }
+ ShowCursor( TRUE );
+ }
+ nFlags &= (~F_REMOVED_RECALC_MOST_RIGHT);
+}
+
+
+void SvImpLBox::MovingEntry( SvLBoxEntry* pEntry )
+{
+ int bDeselAll = nFlags & F_DESEL_ALL;
+ SelAllDestrAnch( FALSE, TRUE ); // DeselectAll();
+ if( !bDeselAll )
+ nFlags &= (~F_DESEL_ALL);
+
+ if( pEntry == pCursor )
+ ShowCursor( FALSE );
+ if( IsEntryInView( pEntry ) )
+ pView->Invalidate();
+ if( pEntry == pStartEntry )
+ {
+ SvLBoxEntry* pNew = 0;
+ if( !pEntry->HasChilds() )
+ {
+ pNew = (SvLBoxEntry*)(pView->NextVisible( pStartEntry ));
+ if( !pNew )
+ pNew = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry ));
+ }
+ else
+ {
+ pNew = pTree->NextSibling( pEntry );
+ if( !pNew )
+ pNew = pTree->PrevSibling( pEntry );
+ }
+ pStartEntry = pNew;
+ }
+}
+
+void SvImpLBox::EntryMoved( SvLBoxEntry* pEntry )
+{
+ // #97680# --------------
+ UpdateContextBmpWidthVectorFromMovedEntry( pEntry );
+
+ if ( !pStartEntry )
+ // this might happen if the only entry in the view is moved to its very same position
+ // #i97346#
+ pStartEntry = pView->First();
+
+ aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
+ USHORT nFirstPos = (USHORT)pTree->GetAbsPos( pStartEntry );
+ USHORT nNewPos = (USHORT)pTree->GetAbsPos( pEntry );
+ FindMostRight(0);
+ if( nNewPos < nFirstPos ) //!!!Notloesung
+ pStartEntry = pEntry;
+ // #97702# ---------------
+ SyncVerThumb();
+ if( pEntry == pCursor )
+ {
+ if( pView->IsEntryVisible( pCursor ) )
+ ShowCursor( TRUE );
+ else
+ {
+ SvLBoxEntry* pParent = pEntry;
+ do {
+ pParent = pTree->GetParent( pParent );
+ }
+ while( !pView->IsEntryVisible( pParent ) );
+ SetCursor( pParent );
+ }
+ }
+ if( IsEntryInView( pEntry ) )
+ pView->Invalidate();
+}
+
+
+
+void SvImpLBox::EntryInserted( SvLBoxEntry* pEntry )
+{
+ if( GetUpdateMode() )
+ {
+ SvLBoxEntry* pParent = (SvLBoxEntry*)pTree->GetParent(pEntry);
+ if( pParent && pTree->GetChildList(pParent)->Count() == 1 )
+ // Pluszeichen zeichnen
+ pTree->InvalidateEntry( pParent );
+
+ if( !pView->IsEntryVisible( pEntry ) )
+ return;
+ int bDeselAll = nFlags & F_DESEL_ALL;
+ if( bDeselAll )
+ SelAllDestrAnch( FALSE, TRUE );
+ else
+ DestroyAnchor();
+ // nFlags &= (~F_DESEL_ALL);
+// ShowCursor( FALSE ); // falls sich Cursor nach unten verschiebt
+ long nY = GetEntryLine( pEntry );
+ BOOL bEntryVisible = IsLineVisible( nY );
+ if( bEntryVisible )
+ {
+ ShowCursor( FALSE ); // falls sich Cursor nach unten verschiebt
+ nY -= pView->GetEntryHeight(); // wg. Linien
+ InvalidateEntriesFrom( nY );
+ }
+ else if( pStartEntry && nY < GetEntryLine(pStartEntry) )
+ {
+ // pruefen, ob die View komplett gefuellt ist. Wenn
+ // nicht, dann pStartEntry und den Cursor anpassen
+ // (automatisches scrollen)
+ USHORT nLast = (USHORT)(pView->GetVisiblePos( (SvLBoxEntry*)(pView->LastVisible())));
+ USHORT nThumb = (USHORT)(pView->GetVisiblePos( pStartEntry ));
+ USHORT nCurDispEntries = nLast-nThumb+1;
+ if( nCurDispEntries < nVisibleCount )
+ {
+ // beim naechsten Paint-Event setzen
+ pStartEntry = 0;
+ SetCursor( 0 );
+ pView->Invalidate();
+ }
+ }
+ else if( !pStartEntry )
+ pView->Invalidate();
+
+ // die Linien invalidieren
+ /*
+ if( (bEntryVisible || bPrevEntryVisible) &&
+ (nWinBits & ( WB_HASLINES | WB_HASLINESATROOT )) )
+ {
+ SvLBoxTab* pTab = pView->GetFirstDynamicTab();
+ if( pTab )
+ {
+ long nDX = pView->GetTabPos( pEntry, pTab );
+ Point aTmpPoint;
+ Size aSize( nDX, nY );
+ Rectangle aRect( aTmpPoint, aSize );
+ pView->Invalidate( aRect );
+ }
+ }
+ */
+
+ SetMostRight( pEntry );
+ aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
+ SyncVerThumb(); // falls vor Thumb eingefuegt wurde
+ ShowVerSBar();
+ ShowCursor( TRUE );
+ if( pStartEntry != pView->First() && (nFlags & F_FILLING) )
+ pView->Update();
+ }
+}
+
+
+
+// ********************************************************************
+// Eventhandler
+// ********************************************************************
+
+
+// ****** Steuerung der Controlanimation
+
+BOOL SvImpLBox::ButtonDownCheckCtrl(const MouseEvent& rMEvt, SvLBoxEntry* pEntry,
+ long nY )
+{
+ SvLBoxItem* pItem = pView->GetItem(pEntry,rMEvt.GetPosPixel().X(),&pActiveTab);
+ if( pItem && (pItem->IsA()==SV_ITEM_ID_LBOXBUTTON))
+ {
+ pActiveButton = (SvLBoxButton*)pItem;
+ pActiveEntry = pEntry;
+ if( pCursor == pActiveEntry )
+ pView->HideFocus();
+ pView->CaptureMouse();
+ pActiveButton->SetStateHilighted( TRUE );
+ pView->PaintEntry1( pActiveEntry, nY,
+ SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
+ SV_LBOXTAB_ADJUST_RIGHT );
+ return TRUE;
+ }
+ else
+ pActiveButton = 0;
+ return FALSE;
+}
+
+BOOL SvImpLBox::MouseMoveCheckCtrl( const MouseEvent& rMEvt, SvLBoxEntry* pEntry)
+{
+ if( pActiveButton )
+ {
+ long nY;
+ long nMouseX = rMEvt.GetPosPixel().X();
+ if( pEntry == pActiveEntry &&
+ pView->GetItem(pActiveEntry, nMouseX) == pActiveButton )
+ {
+ if( !pActiveButton->IsStateHilighted() )
+ {
+ pActiveButton->SetStateHilighted(TRUE );
+ nY = GetEntryLine( pActiveEntry );
+ pView->PaintEntry1( pActiveEntry, nY,
+ SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
+ SV_LBOXTAB_ADJUST_RIGHT );
+ }
+ }
+ else
+ {
+ if( pActiveButton->IsStateHilighted() )
+ {
+ pActiveButton->SetStateHilighted(FALSE );
+ nY = GetEntryLine( pActiveEntry );
+ pView->PaintEntry1( pActiveEntry, nY, SV_LBOXTAB_PUSHABLE );
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL SvImpLBox::ButtonUpCheckCtrl( const MouseEvent& rMEvt )
+{
+ if( pActiveButton )
+ {
+ pView->ReleaseMouse();
+ SvLBoxEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
+ long nY = GetEntryLine( pActiveEntry );
+ pActiveButton->SetStateHilighted( FALSE );
+ long nMouseX = rMEvt.GetPosPixel().X();
+ if( pEntry == pActiveEntry &&
+ pView->GetItem( pActiveEntry, nMouseX ) == pActiveButton )
+ pActiveButton->ClickHdl( pView, pActiveEntry );
+ pView->PaintEntry1( pActiveEntry, nY,
+ SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
+ SV_LBOXTAB_ADJUST_RIGHT );
+ if( pCursor == pActiveEntry )
+ ShowCursor( TRUE );
+ pActiveButton = 0;
+ pActiveEntry = 0;
+ pActiveTab = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// ******* Steuerung Plus/Minus-Button zum Expandieren/Kollabieren
+
+// FALSE == kein Expand/Collapse-Button getroffen
+BOOL SvImpLBox::IsNodeButton( const Point& rPosPixel, SvLBoxEntry* pEntry ) const
+{
+ if( !pEntry->HasChilds() && !pEntry->HasChildsOnDemand() )
+ return FALSE;
+
+ SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
+ if( !pFirstDynamicTab )
+ return FALSE;
+
+ long nMouseX = rPosPixel.X();
+ // in Doc-Koords umrechnen
+ Point aOrigin( pView->GetMapMode().GetOrigin() );
+ nMouseX -= aOrigin.X();
+
+ long nX = pView->GetTabPos( pEntry, pFirstDynamicTab);
+ nX += nNodeBmpTabDistance;
+ if( nMouseX < nX )
+ return FALSE;
+ nX += nNodeBmpWidth;
+ if( nMouseX > nX )
+ return FALSE;
+ return TRUE;
+}
+
+// FALSE == hit no node button
+BOOL SvImpLBox::ButtonDownCheckExpand( const MouseEvent& rMEvt, SvLBoxEntry* pEntry, long /* nY */ )
+{
+ BOOL bRet = FALSE;
+
+ if ( pView->IsEditingActive() && pEntry == pView->pEdEntry )
+ // inplace editing -> nothing to do
+ bRet = TRUE;
+ else if ( IsNodeButton( rMEvt.GetPosPixel(), pEntry ) )
+ {
+ if ( pView->IsExpanded( pEntry ) )
+ {
+ pView->EndEditing( TRUE );
+ pView->Collapse( pEntry );
+ }
+ else
+ {
+ // you can expand an entry, which is in editing
+ pView->Expand( pEntry );
+ }
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+void SvImpLBox::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( !rMEvt.IsLeft() && !rMEvt.IsRight())
+ return;
+
+#ifdef OS2
+ // unter OS/2 kommt zwischen MouseButtonDown und
+ // MouseButtonUp ein MouseMove
+ nFlags |= F_IGNORE_NEXT_MOUSEMOVE;
+#endif
+ aEditTimer.Stop();
+ Point aPos( rMEvt.GetPosPixel());
+
+ if( aPos.X() > aOutputSize.Width() || aPos.Y() > aOutputSize.Height() )
+ return;
+
+ SvLBoxEntry* pEntry = GetEntry( aPos );
+ if ( pEntry != pCursor )
+ // new entry selected -> reset current tab position to first tab
+ nCurTabPos = FIRST_ENTRY_TAB;
+ nFlags &= (~F_FILLING);
+ pView->GrabFocus();
+ // #120417# the entry can still be invalid!
+ if( !pEntry || !pView->GetViewData( pEntry ))
+ return;
+
+ long nY = GetEntryLine( pEntry );
+ // Node-Button?
+ if( ButtonDownCheckExpand( rMEvt, pEntry, nY ) )
+ return;
+
+ if( !EntryReallyHit(pEntry,aPos,nY))
+ return;
+
+ SvLBoxItem* pXItem = pView->GetItem( pEntry, aPos.X() );
+ if( pXItem )
+ {
+ SvLBoxTab* pXTab = pView->GetTab( pEntry, pXItem );
+ if ( !rMEvt.IsMod1() && !rMEvt.IsMod2() && rMEvt.IsLeft() && pXTab->IsEditable()
+ && pEntry == pView->FirstSelected() && NULL == pView->NextSelected( pEntry ) )
+ // #i8234# FirstSelected() and NextSelected() ensures, that inplace editing is only triggered, when only one entry is selected
+ nFlags |= F_START_EDITTIMER;
+ if ( !pView->IsSelected( pEntry ) )
+ nFlags &= ~F_START_EDITTIMER;
+ }
+
+
+ if( (rMEvt.GetClicks() % 2) == 0 )
+ {
+ nFlags &= (~F_START_EDITTIMER);
+ pView->pHdlEntry = pEntry;
+ if( pView->DoubleClickHdl() )
+ {
+ // falls im Handler der Eintrag geloescht wurde
+ pEntry = GetClickedEntry( aPos );
+ if( !pEntry )
+ return;
+ if( pEntry != pView->pHdlEntry )
+ {
+ // neu selektieren & tschuess
+ if( !bSimpleTravel && !aSelEng.IsAlwaysAdding())
+ SelAllDestrAnch( FALSE, TRUE ); // DeselectAll();
+ SetCursor( pEntry );
+
+ DBG_ERROR( "Please report what you did to get this assertion to FS!" );
+ // The entry which has been double-clicked changed - and we select it, again.
+ // I have situations where this behaviour does not make any sense at all - even more, it
+ // leads to hacks to revert it's results.
+ // So I'm not sure if this behaviour here is nonsense (which I believe at the moment),
+ // or if there are really scenarious where it dones make sense ....
+ // 07.12.2001 - 95727 - fs@openoffice.org
+
+ return;
+ }
+ if( pEntry->HasChilds() || pEntry->HasChildsOnDemand() )
+ {
+ if( pView->IsExpanded(pEntry) )
+ pView->Collapse( pEntry );
+ else
+ pView->Expand( pEntry );
+ if( pEntry == pCursor ) // nur wenn Entryitem angeklickt wurde
+ // (Nodebutton ist kein Entryitem!)
+ pView->Select( pCursor, TRUE );
+ return;
+ }
+ }
+ }
+ else
+ {
+ // CheckButton? (TreeListBox: Check + Info)
+ if( ButtonDownCheckCtrl(rMEvt, pEntry, nY) == TRUE)
+ return;
+ // Inplace-Editing?
+#if 0
+ if( rMEvt.IsMod2() && pView->IsInplaceEditingEnabled() )
+ {
+ SvLBoxItem* pItem = pView->GetItem( pEntry, aPos.X() );
+ if( pItem )
+ pView->EditingRequest( pEntry, pItem, aPos );
+ return;
+ }
+#endif
+ }
+ if ( aSelEng.GetSelectionMode() != NO_SELECTION )
+ aSelEng.SelMouseButtonDown( rMEvt );
+}
+
+void SvImpLBox::MouseButtonUp( const MouseEvent& rMEvt)
+{
+#ifdef OS2
+ nFlags &= (~F_IGNORE_NEXT_MOUSEMOVE);
+#endif
+ if ( !ButtonUpCheckCtrl( rMEvt ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
+ aSelEng.SelMouseButtonUp( rMEvt );
+ EndScroll();
+ if( nFlags & F_START_EDITTIMER )
+ {
+ nFlags &= (~F_START_EDITTIMER);
+ aEditClickPos = rMEvt.GetPosPixel();
+ aEditTimer.Start();
+ }
+
+ return;
+}
+
+void SvImpLBox::MouseMove( const MouseEvent& rMEvt)
+{
+#ifdef OS2
+ if( nFlags & F_IGNORE_NEXT_MOUSEMOVE )
+ {
+ nFlags &= (~F_IGNORE_NEXT_MOUSEMOVE);
+ return;
+ }
+#endif
+ SvLBoxEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
+ if ( !MouseMoveCheckCtrl( rMEvt, pEntry ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
+ aSelEng.SelMouseMove( rMEvt );
+ return;
+}
+
+BOOL SvImpLBox::KeyInput( const KeyEvent& rKEvt)
+{
+ aEditTimer.Stop();
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+
+ if( rKeyCode.IsMod2() )
+ return FALSE; // Alt-Taste nicht auswerten
+
+ nFlags &= (~F_FILLING);
+
+ if( !pCursor )
+ pCursor = pStartEntry;
+ if( !pCursor )
+ return FALSE;
+
+ BOOL bKeyUsed = TRUE;
+
+ USHORT nDelta = (USHORT)aVerSBar.GetPageSize();
+ USHORT aCode = rKeyCode.GetCode();
+
+ BOOL bShift = rKeyCode.IsShift();
+ BOOL bMod1 = rKeyCode.IsMod1();
+
+ SvLBoxEntry* pNewCursor;
+
+ switch( aCode )
+ {
+ case KEY_UP:
+ if( !IsEntryInView( pCursor ) )
+ MakeVisible( pCursor );
+
+ pNewCursor = pCursor;
+ do
+ {
+ pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
+ } while( pNewCursor && !IsSelectable(pNewCursor) );
+
+ if ( pNewCursor )
+ // new entry selected -> reset current tab position to first tab
+ nCurTabPos = FIRST_ENTRY_TAB;
+ // if there is no next entry, take the current one
+ // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
+ // the cursor key
+ // 06.09.20001 - 83416 - fs@openoffice.org
+ if ( !pNewCursor && pCursor )
+ pNewCursor = pCursor;
+
+ if( pNewCursor )
+ {
+ aSelEng.CursorPosChanging( bShift, bMod1 );
+ SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
+ if( !IsEntryInView( pNewCursor ) )
+ KeyUp( FALSE );
+ }
+ break;
+
+ case KEY_DOWN:
+ if( !IsEntryInView( pCursor ) )
+ MakeVisible( pCursor );
+
+ pNewCursor = pCursor;
+ do
+ {
+ pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
+ } while( pNewCursor && !IsSelectable(pNewCursor) );
+
+ if ( pNewCursor )
+ // new entry selected -> reset current tab position to first tab
+ nCurTabPos = FIRST_ENTRY_TAB;
+
+ // if there is no next entry, take the current one
+ // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
+ // the cursor key
+ // 06.09.20001 - 83416 - frank.schoenheit@sun.com
+ if ( !pNewCursor && pCursor )
+ pNewCursor = pCursor;
+
+ if( pNewCursor )
+ {
+ aSelEng.CursorPosChanging( bShift, bMod1 );
+ if( IsEntryInView( pNewCursor ) )
+ SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
+ else
+ {
+ if( pCursor )
+ pView->Select( pCursor, FALSE );
+ KeyDown( FALSE );
+ SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
+ }
+ }
+ else
+ KeyDown( FALSE ); // weil ScrollBar-Range evtl. noch
+ // scrollen erlaubt
+ break;
+
+ case KEY_RIGHT:
+ {
+ if( bSubLstOpLR && IsNowExpandable() )
+ pView->Expand( pCursor );
+ else if ( bIsCellFocusEnabled && pCursor )
+ {
+ if ( nCurTabPos < ( pView->TabCount() - 1 /*!2*/ ) )
+ {
+ ++nCurTabPos;
+ ShowCursor( TRUE );
+ CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
+ }
+ }
+ else if( pView->nWindowStyle & WB_HSCROLL )
+ {
+ long nThumb = aHorSBar.GetThumbPos();
+ nThumb += aHorSBar.GetLineSize();
+ long nOldThumb = aHorSBar.GetThumbPos();
+ aHorSBar.SetThumbPos( nThumb );
+ nThumb = nOldThumb;
+ nThumb -= aHorSBar.GetThumbPos();
+ nThumb *= -1;
+ if( nThumb )
+ {
+ KeyLeftRight( nThumb );
+ EndScroll();
+ }
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+ }
+
+ case KEY_LEFT:
+ {
+ if ( bIsCellFocusEnabled )
+ {
+ if ( nCurTabPos > FIRST_ENTRY_TAB )
+ {
+ --nCurTabPos;
+ ShowCursor( TRUE );
+ CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
+ }
+ }
+ else if ( pView->nWindowStyle & WB_HSCROLL )
+ {
+ long nThumb = aHorSBar.GetThumbPos();
+ nThumb -= aHorSBar.GetLineSize();
+ long nOldThumb = aHorSBar.GetThumbPos();
+ aHorSBar.SetThumbPos( nThumb );
+ nThumb = nOldThumb;
+ nThumb -= aHorSBar.GetThumbPos();
+ if( nThumb )
+ {
+ KeyLeftRight( -nThumb );
+ EndScroll();
+ }
+ else if( bSubLstOpLR )
+ {
+ if( IsExpandable() && pView->IsExpanded( pCursor ) )
+ pView->Collapse( pCursor );
+ else
+ {
+ pNewCursor = pView->GetParent( pCursor );
+ if( pNewCursor )
+ SetCursor( pNewCursor );
+ }
+ }
+ }
+ else if( bSubLstOpLR && IsExpandable() )
+ pView->Collapse( pCursor );
+ else
+ bKeyUsed = FALSE;
+ break;
+ }
+
+ case KEY_PAGEUP:
+ if( !bMod1 )
+ {
+ pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pCursor, nDelta ));
+
+ while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
+ {
+ pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
+ nDelta--;
+ }
+
+ if( nDelta )
+ {
+ DBG_ASSERT(pNewCursor&&(ULONG)pNewCursor!=(ULONG)pCursor,"Cursor?");
+ aSelEng.CursorPosChanging( bShift, bMod1 );
+ if( IsEntryInView( pNewCursor ) )
+ SetCursor( pNewCursor );
+ else
+ {
+ SetCursor( pNewCursor );
+ KeyUp( TRUE );
+ }
+ }
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_PAGEDOWN:
+ if( !bMod1 )
+ {
+ pNewCursor= (SvLBoxEntry*)(pView->NextVisible( pCursor, nDelta ));
+
+ while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
+ {
+ pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
+ nDelta--;
+ }
+
+ if( nDelta )
+ {
+ DBG_ASSERT(pNewCursor&&(ULONG)pNewCursor!=(ULONG)pCursor,"Cursor?");
+ aSelEng.CursorPosChanging( bShift, bMod1 );
+ if( IsEntryInView( pNewCursor ) )
+ SetCursor( pNewCursor );
+ else
+ {
+ SetCursor( pNewCursor );
+ KeyDown( TRUE );
+ }
+ }
+ else
+ KeyDown( FALSE ); // siehe KEY_DOWN
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_SPACE:
+ if ( pView->GetSelectionMode() != NO_SELECTION )
+ {
+ if ( bMod1 )
+ {
+ if ( pView->GetSelectionMode() == MULTIPLE_SELECTION && !bShift )
+ // toggle selection
+ pView->Select( pCursor, !pView->IsSelected( pCursor ) );
+ }
+ else if ( !bShift /*&& !bMod1*/ )
+ {
+ if ( aSelEng.IsAddMode() )
+ // toggle selection
+ pView->Select( pCursor, !pView->IsSelected( pCursor ) );
+ else
+ {
+ SelAllDestrAnch( FALSE );
+ pView->Select( pCursor, TRUE );
+ }
+ }
+ else
+ bKeyUsed = FALSE;
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_RETURN:
+ if( bSubLstOpRet && IsExpandable() )
+ {
+ if( pView->IsExpanded( pCursor ) )
+ pView->Collapse( pCursor );
+ else
+ pView->Expand( pCursor );
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_F2:
+ if( !bShift && !bMod1 )
+ {
+ aEditClickPos = Point( -1, -1 );
+ EditTimerCall( 0 );
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_F8:
+ if( bShift && pView->GetSelectionMode()==MULTIPLE_SELECTION &&
+ !(nWinBits & WB_SIMPLEMODE))
+ {
+ if( aSelEng.IsAlwaysAdding() )
+ aSelEng.AddAlways( FALSE );
+ else
+ aSelEng.AddAlways( TRUE );
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+
+#ifdef OV_DEBUG
+ case KEY_F9:
+ MakeVisible( pCursor );
+ break;
+ case KEY_F10:
+ pView->RemoveSelection();
+ break;
+ case KEY_DELETE:
+ pView->RemoveEntry( pCursor );
+ break;
+#endif
+
+ case KEY_ADD:
+ if( pCursor )
+ {
+ if( !pView->IsExpanded(pCursor))
+ pView->Expand( pCursor );
+ if( bMod1 )
+ {
+ USHORT nRefDepth = pTree->GetDepth( pCursor );
+ SvLBoxEntry* pCur = pTree->Next( pCursor );
+ while( pCur && pTree->GetDepth(pCur) > nRefDepth )
+ {
+ if( pCur->HasChilds() && !pView->IsExpanded(pCur))
+ pView->Expand( pCur );
+ pCur = pTree->Next( pCur );
+ }
+ }
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_A:
+ if( bMod1 )
+ SelAllDestrAnch( TRUE );
+// else
+// bKeyUsed = FALSE; #105907# assume user wants to use quicksearch with key "a", so key is handled!
+ break;
+
+ case KEY_SUBTRACT:
+ if( pCursor )
+ {
+ if( pView->IsExpanded(pCursor))
+ pView->Collapse( pCursor );
+ if( bMod1 )
+ {
+ // bis zur Root alle Parents einklappen
+ SvLBoxEntry* pParentToCollapse = (SvLBoxEntry*)pTree->GetRootLevelParent(pCursor);
+ if( pParentToCollapse )
+ {
+ USHORT nRefDepth;
+ // Sonderbehandlung Explorer: Befindet sich auf der
+ // Root nur ein Eintrag,dann den Root-Entry nicht
+ // einklappen
+ if( pTree->GetChildList(0)->Count() < 2 )
+ {
+ nRefDepth = 1;
+ pParentToCollapse = pCursor;
+ while( pTree->GetParent(pParentToCollapse) &&
+ pTree->GetDepth( pTree->GetParent(pParentToCollapse)) > 0)
+ {
+ pParentToCollapse = pTree->GetParent(pParentToCollapse);
+ }
+ }
+ else
+ nRefDepth = 0;
+
+ if( pView->IsExpanded(pParentToCollapse) )
+ pView->Collapse( pParentToCollapse );
+ SvLBoxEntry* pCur = pTree->Next( pParentToCollapse );
+ while( pCur && pTree->GetDepth(pCur) > nRefDepth )
+ {
+ if( pCur->HasChilds() && pView->IsExpanded(pCur) )
+ pView->Collapse( pCur );
+ pCur = pTree->Next( pCur );
+ }
+ }
+ }
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_DIVIDE :
+ if( bMod1 )
+ SelAllDestrAnch( TRUE );
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_COMMA :
+ if( bMod1 )
+ SelAllDestrAnch( FALSE );
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_HOME :
+ pNewCursor = pView->GetModel()->First();
+
+ while( pNewCursor && !IsSelectable(pNewCursor) )
+ {
+ pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
+ }
+
+ if( pNewCursor && pNewCursor != pCursor )
+ {
+// SelAllDestrAnch( FALSE );
+ aSelEng.CursorPosChanging( bShift, bMod1 );
+ SetCursor( pNewCursor );
+ if( !IsEntryInView( pNewCursor ) )
+ MakeVisible( pNewCursor );
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_END :
+ pNewCursor = pView->GetModel()->Last();
+
+ while( pNewCursor && !IsSelectable(pNewCursor) )
+ {
+ pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
+ }
+
+ if( pNewCursor && pNewCursor != pCursor)
+ {
+// SelAllDestrAnch( FALSE );
+ aSelEng.CursorPosChanging( bShift, bMod1 );
+ SetCursor( pNewCursor );
+ if( !IsEntryInView( pNewCursor ) )
+ MakeVisible( pNewCursor );
+ }
+ else
+ bKeyUsed = FALSE;
+ break;
+
+ case KEY_ESCAPE:
+ case KEY_TAB:
+ case KEY_DELETE:
+ case KEY_BACKSPACE:
+ // #105907# must not be handled because this quits dialogs and does other magic things...
+ // if there are other single keys which should not be handled, they can be added here
+ bKeyUsed = FALSE;
+ break;
+
+ default:
+ if( bMod1 || rKeyCode.GetGroup() == KEYGROUP_FKEYS )
+ // #105907# CTRL or Function key is pressed, assume user don't want to use quicksearch...
+ // if there are groups of keys which should not be handled, they can be added here
+ bKeyUsed = FALSE;
+ }
+ return bKeyUsed;
+}
+
+void __EXPORT SvImpLBox::GetFocus()
+{
+ if( pCursor )
+ {
+ pView->SetEntryFocus( pCursor, TRUE );
+ ShowCursor( TRUE );
+// auskommentiert wg. deselectall
+// if( bSimpleTravel && !pView->IsSelected(pCursor) )
+// pView->Select( pCursor, TRUE );
+ }
+ if( nWinBits & WB_HIDESELECTION )
+ {
+ SvLBoxEntry* pEntry = pView->FirstSelected();
+ while( pEntry )
+ {
+ InvalidateEntry( pEntry );
+ pEntry = pView->NextSelected( pEntry );
+ }
+ /*
+ SvLBoxEntry* pEntry = pView->GetModel()->First();
+ while( pEntry )
+ {
+ SvViewData* pViewData = pView->GetViewData( pEntry );
+ if( pViewData->IsCursored() )
+ {
+ pViewData->SetCursored( FALSE );
+ InvalidateEntry( pEntry );
+ }
+ pEntry = pView->GetModel()->Next( pEntry );
+ }
+ */
+
+
+ }
+}
+
+void __EXPORT SvImpLBox::LoseFocus()
+{
+ aEditTimer.Stop();
+ if( pCursor )
+ pView->SetEntryFocus( pCursor,FALSE );
+ ShowCursor( FALSE );
+
+ if( nWinBits & WB_HIDESELECTION )
+ {
+ SvLBoxEntry* pEntry = pView->FirstSelected();
+ while( pEntry )
+ {
+ //SvViewData* pViewData = pView->GetViewData( pEntry );
+ //pViewData->SetCursored( TRUE );
+ InvalidateEntry( pEntry );
+ pEntry = pView->NextSelected( pEntry );
+ }
+ }
+}
+
+
+// ********************************************************************
+// SelectionEngine
+// ********************************************************************
+
+inline void SvImpLBox::SelectEntry( SvLBoxEntry* pEntry, BOOL bSelect )
+{
+ pView->Select( pEntry, bSelect );
+}
+
+__EXPORT ImpLBSelEng::ImpLBSelEng( SvImpLBox* pImpl, SelectionEngine* pSEng,
+ SvTreeListBox* pV )
+{
+ pImp = pImpl;
+ pSelEng = pSEng;
+ pView = pV;
+}
+
+__EXPORT ImpLBSelEng::~ImpLBSelEng()
+{
+}
+
+void __EXPORT ImpLBSelEng::BeginDrag()
+{
+ pImp->BeginDrag();
+}
+
+/*
+void __EXPORT ImpLBSelEng::EndDrag( const Point& )
+{
+}
+*/
+
+void __EXPORT ImpLBSelEng::CreateAnchor()
+{
+ pImp->pAnchor = pImp->pCursor;
+}
+
+void __EXPORT ImpLBSelEng::DestroyAnchor()
+{
+ pImp->pAnchor = 0;
+}
+
+/*
+void __EXPORT ImpLBSelEng::CreateCursor()
+{
+ pImp->pAnchor = 0;
+}
+*/
+
+
+BOOL __EXPORT ImpLBSelEng::SetCursorAtPoint(const Point& rPoint, BOOL bDontSelectAtCursor)
+{
+ SvLBoxEntry* pNewCursor = pImp->MakePointVisible( rPoint );
+ if( pNewCursor != pImp->pCursor )
+ pImp->BeginScroll();
+
+ if( pNewCursor )
+ {
+ // bei SimpleTravel wird in SetCursor selektiert und
+ // der Select-Handler gerufen
+ //if( !bDontSelectAtCursor && !pImp->bSimpleTravel )
+ // pImp->SelectEntry( pNewCursor, TRUE );
+ pImp->SetCursor( pNewCursor, bDontSelectAtCursor );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL __EXPORT ImpLBSelEng::IsSelectionAtPoint( const Point& rPoint )
+{
+ SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
+ if( pEntry )
+ return pView->IsSelected(pEntry);
+ return FALSE;
+}
+
+void __EXPORT ImpLBSelEng::DeselectAtPoint( const Point& rPoint )
+{
+ SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
+ if( !pEntry )
+ return;
+ pImp->SelectEntry( pEntry, FALSE );
+}
+
+/*
+void __EXPORT ImpLBSelEng::SelectAtPoint( const Point& rPoint )
+{
+ SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
+ if( !pEntry )
+ return;
+ pImp->SelectEntry( pEntry, TRUE );
+}
+*/
+
+void __EXPORT ImpLBSelEng::DeselectAll()
+{
+ pImp->SelAllDestrAnch( FALSE, FALSE ); // SelectionEngine nicht resetten!
+ pImp->nFlags &= (~F_DESEL_ALL);
+}
+
+// ***********************************************************************
+// Selektion
+// ***********************************************************************
+
+void SvImpLBox::SetAnchorSelection(SvLBoxEntry* pOldCursor,SvLBoxEntry* pNewCursor)
+{
+ SvLBoxEntry* pEntry;
+ ULONG nAnchorVisPos = pView->GetVisiblePos( pAnchor );
+ ULONG nOldVisPos = pView->GetVisiblePos( pOldCursor );
+ ULONG nNewVisPos = pView->GetVisiblePos( pNewCursor );
+
+ if( nOldVisPos > nAnchorVisPos ||
+ ( nAnchorVisPos==nOldVisPos && nNewVisPos > nAnchorVisPos) )
+ {
+ if( nNewVisPos > nOldVisPos )
+ {
+ pEntry = pOldCursor;
+ while( pEntry && pEntry != pNewCursor )
+ {
+ pView->Select( pEntry, TRUE );
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ if( pEntry )
+ pView->Select( pEntry, TRUE );
+ return;
+ }
+
+ if( nNewVisPos < nAnchorVisPos )
+ {
+ pEntry = pAnchor;
+ while( pEntry && pEntry != pOldCursor )
+ {
+ pView->Select( pEntry, FALSE );
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ if( pEntry )
+ pView->Select( pEntry, FALSE );
+
+ pEntry = pNewCursor;
+ while( pEntry && pEntry != pAnchor )
+ {
+ pView->Select( pEntry, TRUE );
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ if( pEntry )
+ pView->Select( pEntry, TRUE );
+ return;
+ }
+
+ if( nNewVisPos < nOldVisPos )
+ {
+ pEntry = pNewCursor;
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ while( pEntry && pEntry != pOldCursor )
+ {
+ pView->Select( pEntry, FALSE );
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ if( pEntry )
+ pView->Select( pEntry, FALSE );
+ return;
+ }
+ }
+ else
+ {
+ if( nNewVisPos < nOldVisPos ) // Vergroessern der Selektion
+ {
+ pEntry = pNewCursor;
+ while( pEntry && pEntry != pOldCursor )
+ {
+ pView->Select( pEntry, TRUE );
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ if( pEntry )
+ pView->Select( pEntry, TRUE );
+ return;
+ }
+
+ if( nNewVisPos > nAnchorVisPos )
+ {
+ pEntry = pOldCursor;
+ while( pEntry && pEntry != pAnchor )
+ {
+ pView->Select( pEntry, FALSE );
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ if( pEntry )
+ pView->Select( pEntry, FALSE );
+ pEntry = pAnchor;
+ while( pEntry && pEntry != pNewCursor )
+ {
+ pView->Select( pEntry, TRUE );
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ if( pEntry )
+ pView->Select( pEntry, TRUE );
+ return;
+ }
+
+ if( nNewVisPos > nOldVisPos )
+ {
+ pEntry = pOldCursor;
+ while( pEntry && pEntry != pNewCursor )
+ {
+ pView->Select( pEntry, FALSE );
+ pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
+ }
+ return;
+ }
+ }
+}
+
+void SvImpLBox::SelAllDestrAnch( BOOL bSelect, BOOL bDestroyAnchor,
+ BOOL bSingleSelToo )
+{
+ SvLBoxEntry* pEntry;
+ nFlags &= (~F_DESEL_ALL);
+ if( bSelect && bSimpleTravel )
+ {
+ if( pCursor && !pView->IsSelected( pCursor ))
+ {
+ pView->Select( pCursor, TRUE );
+ }
+ return;
+ }
+ if( !bSelect && pView->GetSelectionCount() == 0 )
+ {
+ if( bSimpleTravel && ( !GetUpdateMode() || !pCursor) )
+ nFlags |= F_DESEL_ALL;
+ return;
+ }
+ if( bSelect && pView->GetSelectionCount() == pView->GetEntryCount())
+ return;
+ if( !bSingleSelToo && bSimpleTravel )
+ return;
+
+ if( !bSelect && pView->GetSelectionCount()==1 && pCursor &&
+ pView->IsSelected( pCursor ))
+ {
+ pView->Select( pCursor, FALSE );
+ if( bDestroyAnchor )
+ DestroyAnchor(); // Anker loeschen & SelectionEngine zuruecksetzen
+ else
+ pAnchor = 0; // internen Anker immer loeschen
+ return;
+ }
+
+ if( bSimpleTravel && !pCursor && !GetUpdateMode() )
+ nFlags |= F_DESEL_ALL;
+
+ ShowCursor( FALSE );
+ BOOL bUpdate = GetUpdateMode();
+
+ nFlags |= F_IGNORE_SELECT; // EntryInserted soll nix tun
+ pEntry = pTree->First();
+ while( pEntry )
+ {
+ if( pView->Select( pEntry, bSelect ) )
+ {
+ if( bUpdate && pView->IsEntryVisible(pEntry) )
+ {
+ long nY = GetEntryLine( pEntry );
+ if( IsLineVisible( nY ) )
+ pView->PaintEntry1( pEntry, nY, 0xffff ); // wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
+ }
+ }
+ pEntry = pTree->Next( pEntry );
+ }
+ nFlags &= ~F_IGNORE_SELECT;
+
+ if( bDestroyAnchor )
+ DestroyAnchor(); // Anker loeschen & SelectionEngine zuruecksetzen
+ else
+ pAnchor = 0; // internen Anker immer loeschen
+ ShowCursor( TRUE );
+}
+
+void SvImpLBox::SetSelectionMode( SelectionMode eSelMode )
+{
+ aSelEng.SetSelectionMode( eSelMode);
+ if( eSelMode == SINGLE_SELECTION )
+ bSimpleTravel = TRUE;
+ else
+ bSimpleTravel = FALSE;
+ if( (nWinBits & WB_SIMPLEMODE) && (eSelMode == MULTIPLE_SELECTION) )
+ aSelEng.AddAlways( TRUE );
+}
+
+// ***********************************************************************
+// Drag & Drop
+// ***********************************************************************
+
+void SvImpLBox::SetDragDropMode( DragDropMode eDDMode )
+{
+ if( eDDMode && eDDMode != SV_DRAGDROP_APP_DROP )
+ {
+ aSelEng.ExpandSelectionOnMouseMove( FALSE );
+ aSelEng.EnableDrag( TRUE );
+ }
+ else
+ {
+ aSelEng.ExpandSelectionOnMouseMove( TRUE );
+ aSelEng.EnableDrag( FALSE );
+ }
+}
+
+void SvImpLBox::BeginDrag()
+{
+ nFlags &= (~F_FILLING);
+ if( !bAsyncBeginDrag )
+ {
+ BeginScroll();
+ pView->StartDrag( 0, aSelEng.GetMousePosPixel() );
+ EndScroll();
+ }
+ else
+ {
+ aAsyncBeginDragPos = aSelEng.GetMousePosPixel();
+ aAsyncBeginDragTimer.Start();
+ }
+}
+
+IMPL_LINK( SvImpLBox, BeginDragHdl, void*, EMPTYARG )
+{
+ pView->StartDrag( 0, aAsyncBeginDragPos );
+ return 0;
+}
+
+void SvImpLBox::PaintDDCursor( SvLBoxEntry* pInsertionPos )
+{
+ long nY;
+ if( pInsertionPos )
+ {
+ nY = GetEntryLine( pInsertionPos );
+ nY += pView->GetEntryHeight();
+ }
+ else
+ nY = 1;
+ RasterOp eOldOp = pView->GetRasterOp();
+ pView->SetRasterOp( ROP_INVERT );
+ Color aOldLineColor = pView->GetLineColor();
+ pView->SetLineColor( Color( COL_BLACK ) );
+ pView->DrawLine( Point( 0, nY ), Point( aOutputSize.Width(), nY ) );
+ pView->SetLineColor( aOldLineColor );
+ pView->SetRasterOp( eOldOp );
+}
+/* -----------------26.08.2003 12:52-----------------
+ Delete all sub menues of a PopupMenu, recursively
+ --------------------------------------------------*/
+void lcl_DeleteSubPopups(PopupMenu* pPopup)
+{
+ for(USHORT i = 0; i < pPopup->GetItemCount(); i++)
+ {
+ PopupMenu* pSubPopup = pPopup->GetPopupMenu( pPopup->GetItemId( i ));
+ if(pSubPopup)
+ {
+ lcl_DeleteSubPopups(pSubPopup);
+ delete pSubPopup;
+ }
+ }
+}
+
+bool SvImpLBox::Command( const CommandEvent& rCEvt )
+{
+ USHORT nCommand = rCEvt.GetCommand();
+
+ if( nCommand == COMMAND_CONTEXTMENU )
+ aEditTimer.Stop();
+
+ // Rollmaus-Event?
+ if ( ( ( nCommand == COMMAND_WHEEL )
+ || ( nCommand == COMMAND_STARTAUTOSCROLL )
+ || ( nCommand == COMMAND_AUTOSCROLL )
+ )
+ && pView->HandleScrollCommand( rCEvt, &aHorSBar, &aVerSBar )
+ )
+ {
+ return true;
+ }
+
+ if ( ( nCommand == COMMAND_CONTEXTMENU )
+ && !bContextMenuHandling
+ )
+ {
+ return false;
+ }
+
+ if( bContextMenuHandling && nCommand == COMMAND_CONTEXTMENU )
+ {
+ Point aPopupPos;
+ BOOL bClickedIsFreePlace = FALSE;
+ std::stack<SvLBoxEntry*> aSelRestore;
+
+ if( rCEvt.IsMouseEvent() )
+ { // change selection, if mouse pos doesn't fit to selection
+
+ aPopupPos = rCEvt.GetMousePosPixel();
+
+ SvLBoxEntry* pClickedEntry = GetEntry( aPopupPos );
+ if( pClickedEntry )
+ { // mouse in non empty area
+ BOOL bClickedIsSelected = FALSE;
+
+ // collect the currently selected entries
+ SvLBoxEntry* pSelected = pView->FirstSelected();
+ while( pSelected )
+ {
+ bClickedIsSelected |= ( pClickedEntry == pSelected );
+ pSelected = pView->NextSelected( pSelected );
+ }
+
+ // if the entry which the user clicked at is not selected
+ if( !bClickedIsSelected )
+ { // deselect all other and select the clicked one
+ pView->SelectAll( FALSE );
+ pView->SetCursor( pClickedEntry );
+ }
+ }
+ else if( aSelEng.GetSelectionMode() == SINGLE_SELECTION )
+ {//modified by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
+ bClickedIsFreePlace = TRUE;
+ INT32 nSelectedEntries = pView->GetSelectionCount();
+ SvLBoxEntry* pSelected = pView->FirstSelected();
+ for(USHORT nSel = 0; nSel < nSelectedEntries; nSel++ )
+ {
+ aSelRestore.push(pSelected);
+ pSelected = pView->NextSelected( pSelected );
+ }
+ pView->SelectAll( FALSE );
+ }
+ else
+ { // deselect all
+ pView->SelectAll( FALSE );
+ }
+ }
+ else
+ { // key event (or at least no mouse event)
+ INT32 nSelectionCount = pView->GetSelectionCount();
+
+ if( nSelectionCount )
+ { // now allways take first visible as base for positioning the menu
+ SvLBoxEntry* pSelected = pView->FirstSelected();
+ while( pSelected )
+ {
+ if( IsEntryInView( pSelected ) )
+ break;
+
+ pSelected = pView->NextSelected( pSelected );
+ }
+
+ if( !pSelected )
+ {
+ // no one was visible
+ pSelected = pView->FirstSelected();
+ pView->MakeVisible( pSelected );
+ }
+
+ aPopupPos = pView->GetFocusRect( pSelected, pView->GetEntryPosition( pSelected ).Y() ).Center();
+ }
+ else
+ aPopupPos = Point( 0, 0 );
+ }
+
+ PopupMenu* pPopup = pView->CreateContextMenu();
+
+ if( pPopup )
+ {
+ // do action for selected entry in popup menu
+ USHORT nMenuAction = pPopup->Execute( pView, aPopupPos );
+ if ( nMenuAction )
+ pView->ExcecuteContextMenuAction( nMenuAction );
+ lcl_DeleteSubPopups(pPopup);
+ delete pPopup;
+ }
+ //added by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
+ if( bClickedIsFreePlace )
+ {
+ while(!aSelRestore.empty())
+ {
+ SvLBoxEntry* pEntry = aSelRestore.top();
+ //#i19717# the entry is maybe already deleted
+ bool bFound = false;
+ for(ULONG nEntry = 0; nEntry < pView->GetEntryCount(); nEntry++)
+ if(pEntry == pView->GetEntry(nEntry))
+ {
+ bFound = true;
+ break;
+ }
+ if(bFound)
+ SetCurEntry( pEntry );
+ aSelRestore.pop();
+ }
+ }
+ return true;
+ }
+
+ const Point& rPos = rCEvt.GetMousePosPixel();
+ if( rPos.X() < aOutputSize.Width() && rPos.Y() < aOutputSize.Height() )
+ aSelEng.Command( rCEvt );
+
+ // strictly, this is not correct. However, it leads to a behavior compatible to the one at the time
+ // when this method did have a void return value ...
+ // A proper solution would be to give the EditEngine::Command also a boolean return value, and forward
+ // this (or false) to our caller
+ return true;
+}
+
+void SvImpLBox::BeginScroll()
+{
+ if( !(nFlags & F_IN_SCROLLING))
+ {
+ pView->NotifyBeginScroll();
+ nFlags |= F_IN_SCROLLING;
+ }
+}
+
+void SvImpLBox::EndScroll()
+{
+ if( nFlags & F_IN_SCROLLING)
+ {
+ pView->NotifyEndScroll();
+ nFlags &= (~F_IN_SCROLLING);
+ }
+}
+
+
+Rectangle SvImpLBox::GetVisibleArea() const
+{
+ Point aPos( pView->GetMapMode().GetOrigin() );
+ aPos.X() *= -1;
+ Rectangle aRect( aPos, aOutputSize );
+ return aRect;
+}
+
+void SvImpLBox::Invalidate()
+{
+ pView->SetClipRegion();
+}
+
+void SvImpLBox::SetCurEntry( SvLBoxEntry* pEntry )
+{
+ if ( ( aSelEng.GetSelectionMode() != SINGLE_SELECTION )
+ && ( aSelEng.GetSelectionMode() != NO_SELECTION )
+ )
+ SelAllDestrAnch( FALSE, TRUE, FALSE );
+ if ( pEntry )
+ MakeVisible( pEntry );
+ SetCursor( pEntry );
+ if ( pEntry && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
+ pView->Select( pEntry, TRUE );
+}
+
+IMPL_LINK( SvImpLBox, EditTimerCall, Timer *, EMPTYARG )
+{
+ if( pView->IsInplaceEditingEnabled() )
+ {
+ sal_Bool bIsMouseTriggered = aEditClickPos.X() >= 0;
+ if ( bIsMouseTriggered )
+ {
+ Point aCurrentMousePos = pView->GetPointerPosPixel();
+ if ( ( abs( aCurrentMousePos.X() - aEditClickPos.X() ) > 5 )
+ || ( abs( aCurrentMousePos.Y() - aEditClickPos.Y() ) > 5 )
+ )
+ {
+ return 0L;
+ }
+ }
+
+ SvLBoxEntry* pEntry = GetCurEntry();
+ if( pEntry )
+ {
+ ShowCursor( FALSE );
+ pView->ImplEditEntry( pEntry );
+ ShowCursor( TRUE );
+ }
+ }
+ return 0;
+}
+
+BOOL SvImpLBox::RequestHelp( const HelpEvent& rHEvt )
+{
+ if( rHEvt.GetMode() & HELPMODE_QUICK )
+ {
+ Point aPos( pView->ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
+ if( !GetVisibleArea().IsInside( aPos ))
+ return FALSE;
+
+ SvLBoxEntry* pEntry = GetEntry( aPos );
+ if( pEntry )
+ {
+ // Rechteck des Textes berechnen
+ SvLBoxTab* pTab;
+ SvLBoxString* pItem = (SvLBoxString*)(pView->GetItem( pEntry, aPos.X(), &pTab ));
+ if( !pItem || pItem->IsA() != SV_ITEM_ID_LBOXSTRING )
+ return FALSE;
+
+ aPos = GetEntryPosition( pEntry );
+ aPos.X() = pView->GetTabPos( pEntry, pTab ); //pTab->GetPos();
+ Size aSize( pItem->GetSize( pView, pEntry ) );
+ SvLBoxTab* pNextTab = NextTab( pTab );
+ BOOL bItemClipped = FALSE;
+ // wurde das Item von seinem rechten Nachbarn abgeschnitten?
+ if( pNextTab && pView->GetTabPos(pEntry,pNextTab) < aPos.X()+aSize.Width() )
+ {
+ aSize.Width() = pNextTab->GetPos() - pTab->GetPos();
+ bItemClipped = TRUE;
+ }
+ Rectangle aItemRect( aPos, aSize );
+
+ Rectangle aViewRect( GetVisibleArea() );
+
+ if( bItemClipped || !aViewRect.IsInside( aItemRect ) )
+ {
+ // rechten Item-Rand am View-Rand clippen
+ //if( aItemRect.Right() > aViewRect.Right() )
+ // aItemRect.Right() = aViewRect.Right();
+
+ Point aPt = pView->OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = pView->OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+
+ Help::ShowQuickHelp( pView, aItemRect,
+ pItem->GetText(), QUICKHELP_LEFT | QUICKHELP_VCENTER );
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+SvLBoxTab* SvImpLBox::NextTab( SvLBoxTab* pTab )
+{
+ USHORT nTabCount = pView->TabCount();
+ if( nTabCount <= 1 )
+ return 0;
+ for( USHORT nTab=0; nTab < (nTabCount-1); nTab++)
+ {
+ if( pView->aTabs[nTab]==pTab )
+ return (SvLBoxTab*)(pView->aTabs[nTab+1]);
+ }
+ return 0;
+}
+
+void SvImpLBox::EndSelection()
+{
+ DestroyAnchor();
+ nFlags &= ~F_START_EDITTIMER;
+}
+
+void SvImpLBox::RepaintScrollBars()
+{
+}
+
+void SvImpLBox::SetUpdateMode( BOOL bMode )
+{
+ if( bUpdateMode != bMode )
+ {
+ bUpdateMode = bMode;
+ if( bUpdateMode )
+ UpdateAll( FALSE );
+ }
+}
+
+void SvImpLBox::SetUpdateModeFast( BOOL bMode )
+{
+ if( bUpdateMode != bMode )
+ {
+ bUpdateMode = bMode;
+ if( bUpdateMode )
+ UpdateAll( FALSE, FALSE );
+ }
+}
+
+
+BOOL SvImpLBox::SetMostRight( SvLBoxEntry* pEntry )
+{
+ if( pView->nTreeFlags & TREEFLAG_RECALCTABS )
+ {
+ nFlags |= F_IGNORE_CHANGED_TABS;
+ pView->SetTabs();
+ nFlags &= ~F_IGNORE_CHANGED_TABS;
+ }
+
+ USHORT nLastTab = pView->aTabs.Count() - 1;
+ USHORT nLastItem = pEntry->ItemCount() - 1;
+ if( nLastTab != USHRT_MAX && nLastItem != USHRT_MAX )
+ {
+ if( nLastItem < nLastTab )
+ nLastTab = nLastItem;
+
+ SvLBoxTab* pTab = (SvLBoxTab*)pView->aTabs[ nLastTab ];
+ SvLBoxItem* pItem = pEntry->GetItem( nLastTab );
+
+ long nTabPos = pView->GetTabPos( pEntry, pTab );
+
+ long nMaxRight = GetOutputSize().Width();
+ Point aPos( pView->GetMapMode().GetOrigin() );
+ aPos.X() *= -1; // Umrechnung Dokumentkoord.
+ nMaxRight = nMaxRight + aPos.X() - 1;
+
+ long nNextTab = nTabPos < nMaxRight ? nMaxRight : nMaxRight + 50;
+ long nTabWidth = nNextTab - nTabPos + 1;
+ long nItemSize = pItem->GetSize(pView,pEntry).Width();
+ long nOffset = pTab->CalcOffset( nItemSize, nTabWidth );
+
+ long nRight = nTabPos + nOffset + nItemSize;
+ if( nRight > nMostRight )
+ {
+ nMostRight = nRight;
+ pMostRightEntry = pEntry;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void SvImpLBox::FindMostRight( SvLBoxEntry* pEntryToIgnore )
+{
+ nMostRight = -1;
+ pMostRightEntry = 0;
+ if( !pView->GetModel() )
+ return;
+
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)pView->FirstVisible();
+ while( pEntry )
+ {
+ if( pEntry != pEntryToIgnore )
+ SetMostRight( pEntry );
+ pEntry = (SvLBoxEntry*)pView->NextVisible( pEntry );
+ }
+}
+
+void SvImpLBox::FindMostRight( SvLBoxEntry* pParent, SvLBoxEntry* pEntryToIgnore )
+{
+ if( !pParent )
+ FindMostRight( pEntryToIgnore );
+ else
+ FindMostRight_Impl( pParent, pEntryToIgnore );
+}
+
+void SvImpLBox::FindMostRight_Impl( SvLBoxEntry* pParent, SvLBoxEntry* pEntryToIgnore )
+{
+ SvTreeEntryList* pList = pTree->GetChildList( pParent );
+
+ if( !pList )
+ return;
+
+ ULONG nCount = pList->Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvLBoxEntry* pChild = (SvLBoxEntry*)pList->GetObject( nCur );
+ if( pChild != pEntryToIgnore )
+ {
+ SetMostRight( pChild );
+ if( pChild->HasChilds() && pView->IsExpanded( pChild ))
+ FindMostRight_Impl( pChild, pEntryToIgnore );
+ }
+ }
+}
+
+void SvImpLBox::NotifyTabsChanged()
+{
+ if( GetUpdateMode() && !(nFlags & F_IGNORE_CHANGED_TABS ) &&
+ nCurUserEvent == 0xffffffff )
+ {
+ nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)0);
+ }
+}
+
+IMPL_LINK(SvImpLBox,MyUserEvent,void*, pArg )
+{
+ nCurUserEvent = 0xffffffff;
+ if( !pArg )
+ {
+ pView->Invalidate();
+ pView->Update();
+ }
+ else
+ {
+ FindMostRight( 0 );
+ ShowVerSBar();
+ pView->Invalidate( GetVisibleArea() );
+ }
+ return 0;
+}
+
+
+void SvImpLBox::StopUserEvent()
+{
+ if( nCurUserEvent != 0xffffffff )
+ {
+ Application::RemoveUserEvent( nCurUserEvent );
+ nCurUserEvent = 0xffffffff;
+ }
+}
+
+void SvImpLBox::ShowFocusRect( const SvLBoxEntry* pEntry )
+{
+ if( pEntry )
+ {
+ long nY = GetEntryLine( (SvLBoxEntry*)pEntry );
+ Rectangle aRect = pView->GetFocusRect( (SvLBoxEntry*)pEntry, nY );
+ Region aOldClip( pView->GetClipRegion());
+ Region aClipRegion( GetClipRegionRect() );
+ pView->SetClipRegion( aClipRegion );
+ pView->ShowFocus( aRect );
+ pView->SetClipRegion( aOldClip );
+
+ }
+ else
+ {
+ pView->HideFocus();
+ }
+}
+
+void SvImpLBox::SetTabBar( TabBar* _pTabBar )
+{
+ pTabBar = _pTabBar;
+}
+
+void SvImpLBox::CancelPendingEdit()
+{
+ if( aEditTimer.IsActive() )
+ aEditTimer.Stop();
+ nFlags &= ~F_START_EDITTIMER;
+}
+
+// -----------------------------------------------------------------------
+void SvImpLBox::implInitDefaultNodeImages()
+{
+ if ( s_pDefCollapsed )
+ // assume that all or nothing is initialized
+ return;
+
+ s_pDefCollapsed = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED ) );
+ s_pDefCollapsedHC = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED_HC ) );
+ s_pDefExpanded = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED ) );
+ s_pDefExpandedHC = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED_HC ) );
+}
+
+// -----------------------------------------------------------------------
+const Image& SvImpLBox::GetDefaultExpandedNodeImage( BmpColorMode _eMode )
+{
+ implInitDefaultNodeImages();
+ return ( BMP_COLOR_NORMAL == _eMode ) ? *s_pDefExpanded : *s_pDefExpandedHC;
+}
+
+// -----------------------------------------------------------------------
+const Image& SvImpLBox::GetDefaultCollapsedNodeImage( BmpColorMode _eMode )
+{
+ implInitDefaultNodeImages();
+ return ( BMP_COLOR_NORMAL == _eMode ) ? *s_pDefCollapsed : *s_pDefCollapsedHC;
+}
+
+// -----------------------------------------------------------------------
+void SvImpLBox::CallEventListeners( ULONG nEvent, void* pData )
+{
+ if ( pView )
+ pView->CallImplEventListeners( nEvent, pData);
+}
+
+// -----------------------------------------------------------------------
+
+bool SvImpLBox::SetCurrentTabPos( USHORT _nNewPos )
+{
+ bool bRet = false;
+
+ if ( pView && _nNewPos < ( pView->TabCount() - 2 ) )
+ {
+ nCurTabPos = _nNewPos;
+ ShowCursor( TRUE );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+bool SvImpLBox::IsSelectable( const SvLBoxEntry* pEntry )
+{
+ if( pEntry )
+ {
+ SvViewDataEntry* pViewDataNewCur = pView->GetViewDataEntry(const_cast<SvLBoxEntry*>(pEntry));
+ return (pViewDataNewCur == 0) || pViewDataNewCur->IsSelectable();
+ }
+ else
+ {
+ return false;
+ }
+}
+
diff --git a/svtools/source/contnr/svimpicn.cxx b/svtools/source/contnr/svimpicn.cxx
new file mode 100644
index 000000000000..2d4c9cf2df0e
--- /dev/null
+++ b/svtools/source/contnr/svimpicn.cxx
@@ -0,0 +1,4167 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+#include <limits.h>
+#ifndef _METRIC_HXX
+#include <vcl/metric.hxx>
+#endif
+#include <vcl/svapp.hxx>
+#ifdef DBG_UTIL
+#include <vcl/sound.hxx>
+#endif
+
+#include <svtools/svlbox.hxx>
+#include <svtools/svicnvw.hxx>
+#include <svimpicn.hxx>
+#ifndef _SVLBITM_HXX
+#include <svtools/svlbitm.hxx>
+#endif
+#include <svl/svarray.hxx>
+
+
+
+#define VIEWMODE_ICON 0x0001 // Text unter Bitmap
+#define VIEWMODE_NAME 0x0002 // Text rechts neben Bitmap
+#define VIEWMODE_TEXT 0x0004 // Text ohne Bitmap
+
+#define DD_SCROLL_PIXEL 10
+
+// alle Angaben in Pixel
+
+#define ICONVIEW_OFFS_BMP_STRING 3
+
+// fuer das Bounding-Rectangle
+#define LROFFS_BOUND 2
+#define TBOFFS_BOUND 2
+
+// fuer das Focus-Rectangle um Icons
+#define LROFFS_ICON 2
+#define TBOFFS_ICON 2
+
+#define NAMEVIEW_OFFS_BMP_STRING 3
+
+// Abstaende von Fensterraendern
+#define LROFFS_WINBORDER 4
+#define TBOFFS_WINBORDER 4
+
+// Breitenoffset Highlight-Rect bei Text
+#define LROFFS_TEXT 2
+
+
+#define ICNVIEWDATA(xPtr) (SvIcnVwDataEntry*)(pView->GetViewDataEntry(xPtr))
+#define ICNVIEWDATA2(xPtr) (SvIcnVwDataEntry*)(pView->pView->GetViewDataEntry(xPtr))
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+// -------------------------------------------------------------------------
+// Hilfsfunktionen von Thomas Hosemann zur mehrzeiligen Ausgabe von
+// Strings. Die Funktionen werden spaeter in StarView integriert.
+// -------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+
+// keine doppelten Defines
+#ifdef TEXT_DRAW_CLIP
+#undef TEXT_DRAW_CLIP
+#endif
+#ifdef TEXT_DRAW_MULTILINE
+#undef TEXT_DRAW_MULTILINE
+#endif
+#ifdef TEXT_DRAW_WORDBREAK
+#undef TEXT_DRAW_WORDBREAK
+#endif
+
+// #define TEXT_DRAW_DISABLE ((USHORT)0x0001)
+// #define TEXT_DRAW_3DLOOK ((USHORT)0x0002)
+// #define TEXT_DRAW_MNEMONIC ((USHORT)0x0004)
+#define TEXT_DRAW_LEFT ((USHORT)0x0010)
+#define TEXT_DRAW_CENTER ((USHORT)0x0020)
+#define TEXT_DRAW_RIGHT ((USHORT)0x0040)
+#define TEXT_DRAW_TOP ((USHORT)0x0080)
+#define TEXT_DRAW_VCENTER ((USHORT)0x0100)
+#define TEXT_DRAW_BOTTOM ((USHORT)0x0200)
+#define TEXT_DRAW_ENDELLIPSIS ((USHORT)0x0400)
+#define TEXT_DRAW_PATHELLIPSIS ((USHORT)0x0800)
+#define TEXT_DRAW_CLIP ((USHORT)0x1000)
+#define TEXT_DRAW_MULTILINE ((USHORT)0x2000)
+#define TEXT_DRAW_WORDBREAK ((USHORT)0x4000)
+
+XubString GetEllipsisString( OutputDevice* pDev,
+ const XubString& rStr, long nMaxWidth,
+ USHORT nStyle = TEXT_DRAW_ENDELLIPSIS )
+{
+ XubString aStr = rStr;
+
+ if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
+ {
+ USHORT nIndex = pDev->GetTextBreak( rStr, nMaxWidth );
+ if ( nIndex != STRING_LEN )
+ {
+ aStr.Erase( nIndex );
+ if ( nIndex > 1 )
+ {
+ aStr.AppendAscii("...");
+ while ( aStr.Len() &&
+ (pDev->GetTextWidth( aStr ) > nMaxWidth) )
+ {
+ if ( (nIndex > 1) || (nIndex == aStr.Len()) )
+ nIndex--;
+ aStr.Erase( nIndex, 1 );
+ }
+ }
+
+ if ( !aStr.Len() && (nStyle & TEXT_DRAW_CLIP) )
+ aStr += rStr.GetChar( 0 );
+ }
+ }
+
+ return aStr;
+}
+
+class TextLineInfo
+{
+private:
+ long mnWidth;
+ USHORT mnIndex;
+ USHORT mnLen;
+
+public:
+ TextLineInfo( long nWidth, USHORT nIndex, USHORT nLen )
+ {
+ mnWidth = nWidth;
+ mnIndex = nIndex;
+ mnLen = nLen;
+ }
+
+ long GetWidth() const { return mnWidth; }
+ USHORT GetIndex() const { return mnIndex; }
+ USHORT GetLen() const { return mnLen; }
+};
+
+#define MULTITEXTLINEINFO_RESIZE 16
+typedef TextLineInfo* PTextLineInfo;
+
+class MultiTextLineInfo
+{
+private:
+ PTextLineInfo* mpLines;
+ USHORT mnLines;
+ USHORT mnSize;
+
+public:
+ MultiTextLineInfo();
+ ~MultiTextLineInfo();
+
+ void AddLine( TextLineInfo* pLine );
+ void Clear();
+
+ TextLineInfo* GetLine( USHORT nLine ) const
+ { return mpLines[nLine]; }
+ USHORT Count() const { return mnLines; }
+
+private:
+ MultiTextLineInfo( const MultiTextLineInfo& );
+ MultiTextLineInfo& operator=( const MultiTextLineInfo& );
+};
+
+MultiTextLineInfo::MultiTextLineInfo()
+{
+ mpLines = new PTextLineInfo[MULTITEXTLINEINFO_RESIZE];
+ mnLines = 0;
+ mnSize = MULTITEXTLINEINFO_RESIZE;
+}
+
+MultiTextLineInfo::~MultiTextLineInfo()
+{
+ for ( USHORT i = 0; i < mnLines; i++ )
+ delete mpLines[i];
+ delete [] mpLines;
+}
+
+void MultiTextLineInfo::AddLine( TextLineInfo* pLine )
+{
+ if ( mnSize == mnLines )
+ {
+ mnSize += MULTITEXTLINEINFO_RESIZE;
+ PTextLineInfo* pNewLines = new PTextLineInfo[mnSize];
+ memcpy( pNewLines, mpLines, mnLines*sizeof(PTextLineInfo) );
+ mpLines = pNewLines;
+ }
+
+ mpLines[mnLines] = pLine;
+ mnLines++;
+}
+
+void MultiTextLineInfo::Clear()
+{
+ for ( USHORT i = 0; i < mnLines; i++ )
+ delete mpLines[i];
+ mnLines = 0;
+}
+
+// -----------------------------------------------------------------------
+
+long GetTextLines( OutputDevice* pDev, MultiTextLineInfo& rLineInfo,
+ long nWidth, const XubString& rStr,
+ USHORT nStyle = TEXT_DRAW_WORDBREAK )
+{
+ rLineInfo.Clear();
+ if ( !rStr.Len() )
+ return 0;
+ if ( nWidth <= 0 )
+ nWidth = 1;
+
+ USHORT nStartPos = 0; // Start-Position der Zeile
+ USHORT nLastLineLen = 0; // Zeilenlaenge bis zum vorherigen Wort
+ USHORT nLastWordPos = 0; // Position des letzten Wortanfangs
+ USHORT i = 0;
+ USHORT nPos; // StartPositon der Zeile (nur Temp)
+ USHORT nLen; // Laenge der Zeile (nur Temp)
+ USHORT nStrLen = rStr.Len();
+ long nMaxLineWidth = 0; // Maximale Zeilenlaenge
+ long nLineWidth; // Aktuelle Zeilenlaenge
+ long nLastLineWidth = 0; // Zeilenlaenge der letzten Zeile
+ xub_Unicode c;
+ xub_Unicode c2;
+ const xub_Unicode* pStr = rStr.GetBuffer();
+ BOOL bHardBreak = FALSE;
+
+ do
+ {
+ c = pStr[i];
+
+ // Auf Zeilenende ermitteln
+ if ( (c == _CR) || (c == _LF) )
+ bHardBreak = TRUE;
+ else
+ bHardBreak = FALSE;
+
+ // Testen, ob ein Wortende erreicht ist
+ if ( bHardBreak || (i == nStrLen) ||
+ (((c == ' ') || (c == '-')) && (nStyle & TEXT_DRAW_WORDBREAK)) )
+ {
+ nLen = i-nStartPos;
+ if ( c == '-' )
+ nLen++;
+ nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLen );
+
+ // Findet ein Zeilenumbruch statt
+ if ( bHardBreak || (i == nStrLen) ||
+ ((nLineWidth >= nWidth) && (nStyle & TEXT_DRAW_WORDBREAK)) )
+ {
+ nPos = nStartPos;
+
+ if ( (nLineWidth >= nWidth) && (nStyle & TEXT_DRAW_WORDBREAK) )
+ {
+ nLineWidth = nLastLineWidth;
+ nLen = nLastLineLen;
+ nStartPos = nLastWordPos;
+ nLastLineLen = i-nStartPos;
+ nLastWordPos = nStartPos+nLastLineLen+1;
+ if ( c == '-' )
+ nLastLineLen++;
+ else if ( bHardBreak && (i > nStartPos) )
+ i--;
+ }
+ else
+ {
+ nStartPos = i;
+ // Zeilenende-Zeichen und '-' beruecksichtigen
+ if ( bHardBreak )
+ {
+ nStartPos++;
+ c2 = pStr[i+1];
+ if ( (c != c2) && ((c2 == _CR) || (c2 == _LF)) )
+ {
+ nStartPos++;
+ i++;
+ }
+ }
+ else if ( c != '-' )
+ nStartPos++;
+ nLastWordPos = nStartPos;
+ nLastLineLen = 0;
+ }
+
+ if ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+
+ if ( nLen || bHardBreak )
+ rLineInfo.AddLine( new TextLineInfo( nLineWidth, nPos, nLen ) );
+
+ // Testen, ob aktuelles Wort noch auf die Zeile passt,
+ // denn ansonsten mueessen wir es auftrennen
+ if ( nLastLineLen )
+ {
+ nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLastLineLen );
+ if ( nLineWidth > nWidth )
+ {
+ // Wenn ein Wortumbruch in einem Wort stattfindet,
+ // ist die maximale Zeilenlaenge die Laenge
+ // des laengsten Wortes
+ if ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+
+ // Solange Wort auftrennen, bis es auf eine Zeile passt
+ do
+ {
+ nPos = pDev->GetTextBreak( rStr, nWidth, nStartPos, nLastLineLen );
+ nLen = nPos-nStartPos;
+ if ( !nLen )
+ {
+ nPos++;
+ nLen++;
+ }
+ nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLen );
+ rLineInfo.AddLine( new TextLineInfo( nLineWidth, nStartPos, nLen ) );
+ nStartPos = nPos;
+ nLastLineLen = nLastLineLen - nLen;
+ nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLastLineLen );
+ }
+ while ( nLineWidth > nWidth );
+ }
+ nLastLineWidth = nLineWidth;
+
+ // Bei Stringende muessen wir die letzte Zeile auch noch
+ // dranhaengen
+ if ( (i == nStrLen) && nLastLineLen )
+ rLineInfo.AddLine( new TextLineInfo( nLastLineWidth, nStartPos, nLastLineLen ) );
+ }
+ else
+ nLastLineWidth = 0;
+ }
+ else
+ {
+ nLastLineWidth = nLineWidth;
+ nLastLineLen = nLen;
+ nLastWordPos = nStartPos+nLastLineLen;
+ if ( c != '-' )
+ nLastWordPos++;
+ }
+ }
+
+ i++;
+ }
+ while ( i <= nStrLen );
+
+ return nMaxLineWidth;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT GetTextLines( OutputDevice* pDev, const Rectangle& rRect,
+ const XubString& rStr,
+ USHORT nStyle = TEXT_DRAW_WORDBREAK,
+ long* pMaxWidth = NULL )
+{
+ MultiTextLineInfo aMultiLineInfo;
+ long nMaxWidth = GetTextLines( pDev, aMultiLineInfo,
+ rRect.GetWidth(), rStr, nStyle );
+ if ( pMaxWidth )
+ *pMaxWidth = nMaxWidth;
+ return aMultiLineInfo.Count();
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle GetTextRect( OutputDevice* pDev, const Rectangle& rRect,
+ const XubString& rStr,
+ USHORT nStyle = TEXT_DRAW_WORDBREAK )
+{
+ Rectangle aRect = rRect;
+ USHORT nLines;
+ long nWidth = rRect.GetWidth();
+ long nMaxWidth;
+ long nTextHeight;
+
+ if ( nStyle & TEXT_DRAW_MULTILINE )
+ {
+ MultiTextLineInfo aMultiLineInfo;
+ TextLineInfo* pLineInfo;
+ USHORT nFormatLines;
+
+ nMaxWidth = 0;
+ GetTextLines( pDev, aMultiLineInfo, nWidth, rStr, nStyle );
+ nFormatLines = aMultiLineInfo.Count();
+ nTextHeight = pDev->GetTextHeight();
+ nLines = (USHORT)(aRect.GetHeight()/nTextHeight);
+ if ( nFormatLines <= nLines )
+ nLines = nFormatLines;
+ else
+ {
+ if ( !(nStyle & TEXT_DRAW_ENDELLIPSIS) )
+ nLines = nFormatLines;
+ else
+ nMaxWidth = nWidth;
+ }
+ for ( USHORT i = 0; i < nLines; i++ )
+ {
+ pLineInfo = aMultiLineInfo.GetLine( i );
+ if ( pLineInfo->GetWidth() > nMaxWidth )
+ nMaxWidth = pLineInfo->GetWidth();
+ }
+ }
+ else
+ {
+ nLines = 1;
+ nMaxWidth = pDev->GetTextWidth( rStr );
+ nTextHeight = pDev->GetTextHeight();
+ if ( (nMaxWidth > nWidth) && (nStyle & TEXT_DRAW_ENDELLIPSIS) )
+ nMaxWidth = nWidth;
+ }
+
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aRect.Left() = aRect.Right()-nMaxWidth+1;
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ {
+ aRect.Left() += (nWidth-nMaxWidth)/2;
+ aRect.Right() = aRect.Left()+nMaxWidth-1;
+ }
+ else
+ aRect.Right() = aRect.Left()+nMaxWidth-1;
+
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aRect.Top() = aRect.Bottom()-(nTextHeight*nLines)+1;
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ {
+ aRect.Top() += (aRect.GetHeight()-(nTextHeight*nLines))/2;
+ aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
+ }
+ else
+ aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void DrawText( OutputDevice* pDev, const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle = 0 )
+{
+ if ( !rStr.Len() || rRect.IsEmpty() )
+ return;
+
+ Point aPos = rRect.TopLeft();
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+ FontAlign eAlign = pDev->GetFont().GetAlign();
+
+ if ( ((nWidth <= 0) || (nHeight <= 0)) && (nStyle & TEXT_DRAW_CLIP) )
+ return;
+
+ // Mehrzeiligen Text behandeln wir anders
+ if ( nStyle & TEXT_DRAW_MULTILINE )
+ {
+ String aLastLine;
+ Region aOldRegion;
+ MultiTextLineInfo aMultiLineInfo;
+ TextLineInfo* pLineInfo;
+ long nTextHeight = pDev->GetTextHeight();
+ long nMaxTextWidth;
+ USHORT i;
+ USHORT nLines = (USHORT)(nHeight/nTextHeight);
+ USHORT nFormatLines;
+ BOOL bIsClipRegion = FALSE;
+ nMaxTextWidth = GetTextLines( pDev, aMultiLineInfo, nWidth, rStr, nStyle );
+
+ nFormatLines = aMultiLineInfo.Count();
+ if ( nFormatLines > nLines )
+ {
+ if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
+ {
+ // Letzte Zeile zusammenbauen und kuerzen
+ nFormatLines = nLines-1;
+ pLineInfo = aMultiLineInfo.GetLine( nFormatLines );
+ aLastLine = rStr.Copy( pLineInfo->GetIndex() );
+ aLastLine.ConvertLineEnd( LINEEND_LF );
+ aLastLine.SearchAndReplace( _LF, ' ' );
+ aLastLine = GetEllipsisString( pDev, aLastLine, nWidth, nStyle );
+ nStyle &= ~(TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM);
+ nStyle |= TEXT_DRAW_TOP;
+ }
+ }
+ else
+ {
+ if ( nMaxTextWidth <= nWidth )
+ nStyle &= ~TEXT_DRAW_CLIP;
+ }
+
+ // Clipping setzen
+ if ( nStyle & TEXT_DRAW_CLIP )
+ {
+ bIsClipRegion = pDev->IsClipRegion();
+ if ( bIsClipRegion )
+ {
+ aOldRegion = pDev->GetClipRegion();
+ pDev->IntersectClipRegion( rRect );
+ }
+ else
+ {
+ Region aRegion( rRect );
+ pDev->SetClipRegion( aRegion );
+ }
+ }
+
+ // Vertikales Alignment
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aPos.Y() += nHeight-(nFormatLines*nTextHeight);
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ aPos.Y() += (nHeight-(nFormatLines*nTextHeight))/2;
+
+ // Font Alignment
+ if ( eAlign == ALIGN_BOTTOM )
+ aPos.Y() += nTextHeight;
+ else if ( eAlign == ALIGN_BASELINE )
+ aPos.Y() += pDev->GetFontMetric().GetAscent();
+
+ // Alle Zeilen ausgeben, bis auf die letzte
+ for ( i = 0; i < nFormatLines; i++ )
+ {
+ pLineInfo = aMultiLineInfo.GetLine( i );
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aPos.X() += nWidth-pLineInfo->GetWidth();
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ aPos.X() += (nWidth-pLineInfo->GetWidth())/2;
+ pDev->DrawText( aPos, rStr, pLineInfo->GetIndex(), pLineInfo->GetLen() );
+ aPos.Y() += nTextHeight;
+ aPos.X() = rRect.Left();
+ }
+
+ // Gibt es noch eine letzte Zeile, dann diese linksbuendig ausgeben,
+ // da die Zeile gekuerzt wurde
+ if ( aLastLine.Len() )
+ pDev->DrawText( aPos, aLastLine );
+
+ // Clipping zuruecksetzen
+ if ( nStyle & TEXT_DRAW_CLIP )
+ {
+ if ( bIsClipRegion )
+ pDev->SetClipRegion( aOldRegion );
+ else
+ pDev->SetClipRegion();
+ }
+ }
+ else
+ {
+ XubString aStr = rStr;
+ Size aTextSize(pDev->GetTextWidth( aStr ), pDev->GetTextHeight());
+
+ // Evt. Text kuerzen
+ if ( aTextSize.Width() > nWidth )
+ {
+ if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
+ {
+ aStr = GetEllipsisString( pDev, rStr, nWidth, nStyle );
+ nStyle &= ~(TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT);
+ nStyle |= TEXT_DRAW_LEFT;
+ aTextSize.Width() = pDev->GetTextWidth(aStr);
+ }
+ }
+ else
+ {
+ if ( aTextSize.Height() <= nHeight )
+ nStyle &= ~TEXT_DRAW_CLIP;
+ }
+
+ // Vertikales Alignment
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aPos.X() += nWidth-aTextSize.Width();
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ aPos.X() += (nWidth-aTextSize.Width())/2;
+
+ // Font Alignment
+ if ( eAlign == ALIGN_BOTTOM )
+ aPos.Y() += aTextSize.Height();
+ else if ( eAlign == ALIGN_BASELINE )
+ aPos.Y() += pDev->GetFontMetric().GetAscent();
+
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aPos.Y() += nHeight-aTextSize.Height();
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ aPos.Y() += (nHeight-aTextSize.Height())/2;
+
+ if ( nStyle & TEXT_DRAW_CLIP )
+ {
+ BOOL bIsClipRegion = pDev->IsClipRegion();
+ if ( bIsClipRegion )
+ {
+ Region aOldRegion = pDev->GetClipRegion();
+ pDev->IntersectClipRegion( rRect );
+ pDev->DrawText( aPos, aStr );
+ pDev->SetClipRegion( aOldRegion );
+ }
+ else
+ {
+ Region aRegion( rRect );
+ pDev->SetClipRegion( aRegion );
+ pDev->DrawText( aPos, aStr );
+ pDev->SetClipRegion();
+ }
+ }
+ else
+ pDev->DrawText( aPos, aStr );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+
+
+#define DRAWTEXT_FLAGS (TEXT_DRAW_CENTER|TEXT_DRAW_TOP|TEXT_DRAW_ENDELLIPSIS|\
+ TEXT_DRAW_CLIP|TEXT_DRAW_MULTILINE|TEXT_DRAW_WORDBREAK)
+
+
+class ImpIcnCursor
+{
+ SvImpIconView* pView;
+ SvPtrarr* pColumns;
+ SvPtrarr* pRows;
+ BOOL* pGridMap;
+ long nGridDX, nGridDY;
+ long nGridCols, nGridRows;
+ long nCols;
+ long nRows;
+ short nDeltaWidth;
+ short nDeltaHeight;
+ SvLBoxEntry* pCurEntry;
+ void SetDeltas();
+ void ImplCreate();
+ void Create() { if( !pColumns ) ImplCreate(); }
+
+ USHORT GetSortListPos( SvPtrarr* pList, long nValue, int bVertical);
+ SvLBoxEntry* SearchCol(USHORT nCol,USHORT nTop,USHORT nBottom,USHORT nPref,
+ BOOL bDown, BOOL bSimple );
+ SvLBoxEntry* SearchRow(USHORT nRow,USHORT nRight,USHORT nLeft,USHORT nPref,
+ BOOL bRight, BOOL bSimple );
+
+ void ExpandGrid();
+ void CreateGridMap();
+ // Rueckgabe FALSE: Eintrag liegt nicht in der GridMap. rGridx,y werden
+ // dann an nGridCols, nGridRows geclippt
+ BOOL GetGrid( const Point& rDocPos, USHORT& rGridX, USHORT& rGridY ) const;
+ void SetGridUsed( USHORT nDX, USHORT nDY, BOOL bUsed )
+ {
+ pGridMap[ (nDY * nGridCols) + nDX ] = bUsed;
+ }
+ BOOL IsGridUsed( USHORT nDX, USHORT nDY )
+ {
+ return pGridMap[ (nDY * nGridCols) + nDX ];
+ }
+public:
+ ImpIcnCursor( SvImpIconView* pOwner );
+ ~ImpIcnCursor();
+ void Clear( BOOL bGridToo = TRUE );
+
+ // fuer Cursortravelling usw.
+ SvLBoxEntry* GoLeftRight( SvLBoxEntry*, BOOL bRight );
+ SvLBoxEntry* GoUpDown( SvLBoxEntry*, BOOL bDown );
+
+ // Rueckgaebe: FALSE == Das leere Rect steht hinter dem letzten
+ // Eintrag; d.h. beim naechsten Einfuegen ergibt sich das naechste
+ // leere Rechteck durch Addition. Hinweis: Das Rechteck kann dann
+ // ausserhalb des View-Space liegen
+ BOOL FindEmptyGridRect( Rectangle& rRect );
+
+ // Erzeugt fuer jede Zeile (Hoehe=nGridDY) eine nach BoundRect.Left()
+ // sortierte Liste der Eintraege, die in ihr stehen. Eine Liste kann
+ // leer sein. Die Listen gehen in das Eigentum des Rufenden ueber und
+ // muessen mit DestroyGridAdjustData geloescht werden
+ void CreateGridAjustData( SvPtrarr& pLists, SvLBoxEntry* pRow=0);
+ static void DestroyGridAdjustData( SvPtrarr& rLists );
+ void SetGridUsed( const Rectangle&, BOOL bUsed = TRUE );
+};
+
+
+
+
+SvImpIconView::SvImpIconView( SvIconView* pCurView, SvLBoxTreeList* pTree,
+ WinBits nWinStyle ) :
+ aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ),
+ aHorSBar( pCurView, WB_DRAG | WB_HSCROLL )
+{
+ pView = pCurView;
+ pModel = pTree;
+ pCurParent = 0;
+ pZOrderList = new SvPtrarr;
+ SetWindowBits( nWinStyle );
+ nHorDist = 0;
+ nVerDist = 0;
+ nFlags = 0;
+ nCurUserEvent = 0;
+ nMaxVirtWidth = 200;
+ pDDRefEntry = 0;
+ pDDDev = 0;
+ pDDBufDev = 0;
+ pDDTempDev = 0;
+ eTextMode = ShowTextShort;
+ pImpCursor = new ImpIcnCursor( this );
+
+ aVerSBar.SetScrollHdl( LINK( this, SvImpIconView, ScrollUpDownHdl ) );
+ aHorSBar.SetScrollHdl( LINK( this, SvImpIconView, ScrollLeftRightHdl ) );
+ nHorSBarHeight = aHorSBar.GetSizePixel().Height();
+ nVerSBarWidth = aVerSBar.GetSizePixel().Width();
+
+ aMouseMoveTimer.SetTimeout( 20 );
+ aMouseMoveTimer.SetTimeoutHdl(LINK(this,SvImpIconView,MouseMoveTimeoutHdl));
+
+ aEditTimer.SetTimeout( 800 );
+ aEditTimer.SetTimeoutHdl(LINK(this,SvImpIconView,EditTimeoutHdl));
+
+ Clear( TRUE );
+}
+
+SvImpIconView::~SvImpIconView()
+{
+ StopEditTimer();
+ CancelUserEvent();
+ delete pZOrderList;
+ delete pImpCursor;
+ delete pDDDev;
+ delete pDDBufDev;
+ delete pDDTempDev;
+ ClearSelectedRectList();
+}
+
+void SvImpIconView::Clear( BOOL bInCtor )
+{
+ StopEditTimer();
+ CancelUserEvent();
+ nMaxBmpWidth = 0;
+ nMaxBmpHeight = 0;
+ nMaxTextWidth = 0;
+ bMustRecalcBoundingRects = FALSE;
+ nMaxBoundHeight = 0;
+
+ //XXX
+ nFlags |= F_GRID_INSERT;
+ nFlags &= ~F_PAINTED;
+ SetNextEntryPos( Point( LROFFS_WINBORDER, TBOFFS_WINBORDER ) );
+ pCursor = 0;
+ if( !bInCtor )
+ {
+ pImpCursor->Clear();
+ aVirtOutputSize.Width() = 0;
+ aVirtOutputSize.Height() = 0;
+ pZOrderList->Remove(0,pZOrderList->Count());
+ MapMode aMapMode( pView->GetMapMode());
+ aMapMode.SetOrigin( Point() );
+ pView->SetMapMode( aMapMode );
+ if( pView->IsUpdateMode() )
+ pView->Invalidate();
+ }
+ AdjustScrollBars();
+}
+
+void SvImpIconView::SetWindowBits( WinBits nWinStyle )
+{
+ nWinBits = nWinStyle;
+ nViewMode = VIEWMODE_TEXT;
+ if( nWinStyle & WB_NAME )
+ nViewMode = VIEWMODE_NAME;
+ if( nWinStyle & WB_ICON )
+ nViewMode = VIEWMODE_ICON;
+}
+
+
+IMPL_LINK( SvImpIconView, ScrollUpDownHdl, ScrollBar *, pScrollBar )
+{
+ pView->EndEditing( TRUE );
+ // Pfeil hoch: delta=-1; Pfeil runter: delta=+1
+ Scroll( 0, pScrollBar->GetDelta(), TRUE );
+ return 0;
+}
+
+IMPL_LINK( SvImpIconView, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
+{
+ pView->EndEditing( TRUE );
+ // Pfeil links: delta=-1; Pfeil rechts: delta=+1
+ Scroll( pScrollBar->GetDelta(), 0, TRUE );
+ return 0;
+}
+
+void SvImpIconView::ChangedFont()
+{
+ StopEditTimer();
+ ImpArrange();
+}
+
+
+void SvImpIconView::CheckAllSizes()
+{
+ nMaxTextWidth = 0;
+ nMaxBmpWidth = 0;
+ nMaxBmpHeight = 0;
+ SvLBoxEntry* pEntry = pModel->First();
+ while( pEntry )
+ {
+ CheckSizes( pEntry );
+ pEntry = pModel->Next( pEntry );
+ }
+}
+
+void SvImpIconView::CheckSizes( SvLBoxEntry* pEntry,
+ const SvIcnVwDataEntry* pViewData )
+{
+ Size aSize;
+
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(pEntry);
+
+ SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ if( pStringItem )
+ {
+ aSize = GetItemSize( pView, pEntry, pStringItem, pViewData );
+ if( aSize.Width() > nMaxTextWidth )
+ {
+ nMaxTextWidth = aSize.Width();
+ if( !(nFlags & F_GRIDMODE ) )
+ bMustRecalcBoundingRects = TRUE;
+ }
+ }
+ SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ if( pBmpItem )
+ {
+ aSize = GetItemSize( pView, pEntry, pBmpItem, pViewData );
+ if( aSize.Width() > nMaxBmpWidth )
+ {
+ nMaxBmpWidth = aSize.Width();
+ nMaxBmpWidth += (2*LROFFS_ICON);
+ if( !(nFlags & F_GRIDMODE ) )
+ bMustRecalcBoundingRects = TRUE;
+ }
+ if( aSize.Height() > nMaxBmpHeight )
+ {
+ nMaxBmpHeight = aSize.Height();
+ nMaxBmpHeight += (2*TBOFFS_ICON);;
+ if( !(nFlags & F_GRIDMODE ) )
+ bMustRecalcBoundingRects = TRUE;
+ }
+ }
+}
+
+void SvImpIconView::EntryInserted( SvLBoxEntry* pEntry )
+{
+ if( pModel->GetParent(pEntry) == pCurParent )
+ {
+ StopEditTimer();
+ DBG_ASSERT(pZOrderList->GetPos(pEntry)==0xffff,"EntryInserted:ZOrder?");
+ pZOrderList->Insert( pEntry, pZOrderList->Count() );
+ if( nFlags & F_GRIDMODE )
+ pImpCursor->Clear( FALSE );
+ else
+ pImpCursor->Clear( TRUE );
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ CheckSizes( pEntry, pViewData );
+ if( pView->IsUpdateMode() )
+ {
+ FindBoundingRect( pEntry, pViewData );
+ PaintEntry( pEntry, pViewData );
+ }
+ else
+ InvalidateBoundingRect( pViewData->aRect );
+ }
+}
+
+void SvImpIconView::RemovingEntry( SvLBoxEntry* pEntry )
+{
+ if( pModel->GetParent(pEntry) == pCurParent)
+ {
+ StopEditTimer();
+ DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"RemovingEntry:ZOrder?");
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ if( IsBoundingRectValid( pViewData->aRect ) )
+ {
+ // bei gueltigem Bounding-Rect muss in EntryRemoved eine
+ // Sonderbehandlung erfolgen
+ nFlags |= F_ENTRY_REMOVED;
+ pView->Invalidate( pViewData->aRect );
+ }
+ if( pEntry == pCursor )
+ {
+ SvLBoxEntry* pNewCursor = GetNewCursor();
+ ShowCursor( FALSE );
+ pCursor = 0; // damit er nicht deselektiert wird
+ SetCursor( pNewCursor );
+ }
+ USHORT nPos = pZOrderList->GetPos( (void*)pEntry );
+ pZOrderList->Remove( nPos, 1 );
+ pImpCursor->Clear();
+ }
+}
+
+void SvImpIconView::EntryRemoved()
+{
+ if( (nFlags & (F_ENTRY_REMOVED | F_PAINTED)) == (F_ENTRY_REMOVED | F_PAINTED))
+ {
+ // Ein Eintrag mit gueltigem BoundRect wurde geloescht und wir
+ // haben schon mal gepaintet. In diesem Fall muessen wir die
+ // Position des naechsten Eintrags, der eingefuegt wird oder noch
+ // kein gueltiges BoundRect hat, "suchen" d.h. ein "Loch" in
+ // der View auffuellen.
+ nFlags &= ~( F_ENTRY_REMOVED | F_GRID_INSERT );
+ }
+}
+
+
+void SvImpIconView::MovingEntry( SvLBoxEntry* pEntry )
+{
+ DBG_ASSERT(pEntry,"MovingEntry: 0!");
+ pNextCursor = 0;
+ StopEditTimer();
+ if( pModel->GetParent(pEntry) == pCurParent )
+ {
+ DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"MovingEntry:ZOrder?");
+ nFlags |= F_MOVING_SIBLING;
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ if( IsBoundingRectValid( pViewData->aRect ) )
+ pView->Invalidate( pViewData->aRect );
+ // falls Eintrag seinen Parent wechselt vorsichtshalber
+ // die neue Cursorposition berechnen
+ if( pEntry == pCursor )
+ pNextCursor = GetNewCursor();
+ pImpCursor->Clear();
+ }
+}
+
+
+void SvImpIconView::EntryMoved( SvLBoxEntry* pEntry )
+{
+ ShowCursor( FALSE );
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ if( pModel->GetParent(pEntry)==pCurParent )
+ {
+ if( nFlags & F_MOVING_SIBLING )
+ {
+ // die Neu-Positionierung eines Eintrags bei D&D innerhalb
+ // einer IconView findet bereits in NotifyMoving statt
+ // (MovingEntry/EntryMoved wird dann nicht mehr gerufen)
+ ToTop( pEntry );
+ }
+ else
+ {
+ pImpCursor->Clear();
+ pZOrderList->Insert( pEntry, pZOrderList->Count() );
+ DBG_ASSERT(pZOrderList->Count()==pModel->GetChildCount(pCurParent),"EntryMoved:Bad zorder count");
+ FindBoundingRect( pEntry, pViewData );
+ }
+ PaintEntry( pEntry, pViewData );
+ }
+ else
+ {
+ if( pEntry == pCursor )
+ {
+ DBG_ASSERT(pNextCursor,"EntryMoved: Next cursor bad");
+ SetCursor( pNextCursor );
+ }
+ pImpCursor->Clear();
+ USHORT nPos = pZOrderList->GetPos( (void*)pEntry );
+ pZOrderList->Remove( nPos, 1 );
+ pView->Select( pEntry, FALSE );
+ // wenn er nochmal in dieser View auftaucht, muss sein
+ // Bounding-Rect neu berechnet werden
+ InvalidateBoundingRect( pViewData->aRect );
+ }
+ nFlags &= (~F_MOVING_SIBLING);
+}
+
+void SvImpIconView::TreeInserted( SvLBoxEntry* pEntry )
+{
+ EntryMoved( pEntry ); // vorlaeufig
+}
+
+void SvImpIconView::EntryExpanded( SvLBoxEntry* )
+{
+}
+
+void SvImpIconView::EntryCollapsed( SvLBoxEntry*)
+{
+}
+
+void SvImpIconView::CollapsingEntry( SvLBoxEntry* )
+{
+}
+
+void SvImpIconView::EntrySelected( SvLBoxEntry* pEntry, BOOL bSelect )
+{
+ if( pModel->GetParent(pEntry) != pCurParent )
+ return;
+
+ // bei SingleSelection dafuer sorgen, dass der Cursor immer
+ // auf dem (einzigen) selektierten Eintrag steht
+ if( bSelect && pCursor &&
+ pView->GetSelectionMode() == SINGLE_SELECTION &&
+ pEntry != pCursor )
+ {
+ SetCursor( pEntry );
+ DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
+ }
+ // bei Gummibandselektion ist uns das zu teuer
+ if( !(nFlags & F_RUBBERING ))
+ ToTop( pEntry );
+ if( pView->IsUpdateMode() )
+ {
+ if( pEntry == pCursor )
+ ShowCursor( FALSE );
+ if( nFlags & F_RUBBERING )
+ PaintEntry( pEntry );
+ else
+ pView->Invalidate( GetBoundingRect( pEntry ) );
+ if( pEntry == pCursor )
+ ShowCursor( TRUE );
+ }
+}
+
+void SvImpIconView::SetNextEntryPos(const Point& rPos)
+{
+ aPrevBoundRect.SetPos( rPos );
+ aPrevBoundRect.Right() = LONG_MAX; // dont know
+}
+
+Point SvImpIconView::FindNextEntryPos( const Size& rBoundSize )
+{
+ if( nFlags & F_GRIDMODE )
+ {
+ if( nFlags & F_GRID_INSERT )
+ {
+ if( aPrevBoundRect.Right() != LONG_MAX )
+ {
+ // passt der naechste Entry noch in die Zeile ?
+ long nNextWidth = aPrevBoundRect.Right() + nGridDX + LROFFS_WINBORDER;
+ if( nNextWidth > aVirtOutputSize.Width() )
+ {
+ // darf aVirtOutputSize verbreitert werden ?
+ if( nNextWidth < nMaxVirtWidth )
+ {
+ // verbreitern & in Zeile aufnehmen
+ aPrevBoundRect.Left() += nGridDX;
+ }
+ else
+ {
+ // erhoehen & neue Zeile beginnen
+ aPrevBoundRect.Top() += nGridDY;
+ aPrevBoundRect.Left() = LROFFS_WINBORDER;
+ }
+ }
+ else
+ {
+ // in die Zeile aufnehmen
+ aPrevBoundRect.Left() += nGridDX;
+ }
+ }
+ aPrevBoundRect.SetSize( Size( nGridDX, nGridDY ) );
+ }
+ else
+ {
+ if( !pImpCursor->FindEmptyGridRect( aPrevBoundRect ) )
+ {
+ // mitten in den Entries gibts keine Loecher mehr,
+ // wir koennen also wieder ins "Fast Insert" springen
+ nFlags |= F_GRID_INSERT;
+ }
+ }
+ }
+ else
+ {
+ if( aPrevBoundRect.Right() != LONG_MAX )
+ {
+ // passt der naechste Entry noch in die Zeile ?
+ long nNextWidth=aPrevBoundRect.Right()+rBoundSize.Width()+LROFFS_BOUND+nHorDist;
+ if( nNextWidth > aVirtOutputSize.Width() )
+ {
+ // darf aVirtOutputSize verbreitert werden ?
+ if( nNextWidth < nMaxVirtWidth )
+ {
+ // verbreitern & in Zeile aufnehmen
+ aPrevBoundRect.SetPos( aPrevBoundRect.TopRight() );
+ aPrevBoundRect.Left() += nHorDist;
+ }
+ else
+ {
+ // erhoehen & neue Zeile beginnen
+ aPrevBoundRect.Top() += nMaxBoundHeight + nVerDist + TBOFFS_BOUND;
+ aPrevBoundRect.Left() = LROFFS_WINBORDER;
+ }
+ }
+ else
+ {
+ // in die Zeile aufnehmen
+ aPrevBoundRect.SetPos( aPrevBoundRect.TopRight() );
+ aPrevBoundRect.Left() += nHorDist;
+ }
+ }
+ aPrevBoundRect.SetSize( rBoundSize );
+ }
+ return aPrevBoundRect.TopLeft();
+}
+
+void SvImpIconView::ResetVirtSize()
+{
+ StopEditTimer();
+ aVirtOutputSize.Width() = 0;
+ aVirtOutputSize.Height() = 0;
+ BOOL bLockedEntryFound = FALSE;
+ nFlags &= (~F_GRID_INSERT);
+ SvLBoxEntry* pCur = pModel->FirstChild( pCurParent );
+ while( pCur )
+ {
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
+ if( pViewData->IsEntryPosLocked() )
+ {
+ // VirtSize u.a. anpassen
+ if( !IsBoundingRectValid( pViewData->aRect ) )
+ FindBoundingRect( pCur, pViewData );
+ else
+ AdjustVirtSize( pViewData->aRect );
+ bLockedEntryFound = TRUE;
+ }
+ else
+ InvalidateBoundingRect( pViewData->aRect );
+
+ pCur = pModel->NextSibling( pCur );
+ }
+ if( !bLockedEntryFound )
+ {
+ //XXX
+ nFlags |= F_GRID_INSERT;
+ }
+
+ SetNextEntryPos( Point( LROFFS_WINBORDER, TBOFFS_WINBORDER ) );
+ pImpCursor->Clear();
+}
+
+
+void SvImpIconView::AdjustVirtSize( const Rectangle& rRect )
+{
+ long nHeightOffs = 0;
+ long nWidthOffs = 0;
+
+ if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
+ nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
+
+ if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
+ nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
+
+ if( nWidthOffs || nHeightOffs )
+ {
+ Range aRange;
+ aVirtOutputSize.Width() += nWidthOffs;
+ aRange.Max() = aVirtOutputSize.Width();
+ aHorSBar.SetRange( aRange );
+
+ aVirtOutputSize.Height() += nHeightOffs;
+ aRange.Max() = aVirtOutputSize.Height();
+ aVerSBar.SetRange( aRange );
+
+ pImpCursor->Clear();
+ AdjustScrollBars();
+ }
+}
+
+void SvImpIconView::Arrange()
+{
+ nMaxVirtWidth = aOutputSize.Width();
+ ImpArrange();
+}
+
+void SvImpIconView::ImpArrange()
+{
+ StopEditTimer();
+ ShowCursor( FALSE );
+ ResetVirtSize();
+ bMustRecalcBoundingRects = FALSE;
+ MapMode aMapMode( pView->GetMapMode());
+ aMapMode.SetOrigin( Point() );
+ pView->SetMapMode( aMapMode );
+ CheckAllSizes();
+ RecalcAllBoundingRectsSmart();
+ pView->Invalidate();
+ ShowCursor( TRUE );
+}
+
+void SvImpIconView::Paint( const Rectangle& rRect )
+{
+ if( !pView->IsUpdateMode() )
+ return;
+
+#if defined(DBG_UTIL) && defined(OV_DRAWGRID)
+ if( nFlags & F_GRIDMODE )
+ {
+ Color aOldColor = pView->GetLineColor();
+ Color aNewColor( COL_BLACK );
+ pView->SetLineColor( aNewColor );
+ Point aOffs( pView->GetMapMode().GetOrigin());
+ Size aXSize( pView->GetOutputSizePixel() );
+ for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
+ {
+ Point aStart( nDX+LROFFS_BOUND, 0 );
+ Point aEnd( nDX+LROFFS_BOUND, aXSize.Height());
+ aStart -= aOffs;
+ aEnd -= aOffs;
+ pView->DrawLine( aStart, aEnd );
+ }
+ for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
+ {
+ Point aStart( 0, nDY+TBOFFS_BOUND );
+ Point aEnd( aXSize.Width(), nDY+TBOFFS_BOUND );
+ aStart -= aOffs;
+ aEnd -= aOffs;
+ pView->DrawLine( aStart, aEnd );
+ }
+ pView->SetLineColor( aOldColor );
+ }
+#endif
+ nFlags |= F_PAINTED;
+
+ if( !(pModel->HasChilds( pCurParent ) ))
+ return;
+ if( !pCursor )
+ pCursor = pModel->FirstChild( pCurParent );
+
+ USHORT nCount = pZOrderList->Count();
+ if( !nCount )
+ return;
+
+ SvPtrarr* pNewZOrderList = new SvPtrarr;
+ SvPtrarr* pPaintedEntries = new SvPtrarr;
+
+ USHORT nPos = 0;
+ while( nCount )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nPos ));
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ const Rectangle& rBoundRect = GetBoundingRect( pEntry, pViewData );
+ if( rRect.IsOver( rBoundRect ) )
+ {
+ PaintEntry( pEntry, rBoundRect.TopLeft(), pViewData );
+ // Eintraege, die neu gezeichnet werden, auf Top setzen
+ pPaintedEntries->Insert( pEntry, pPaintedEntries->Count() );
+ }
+ else
+ pNewZOrderList->Insert( pEntry, pNewZOrderList->Count() );
+
+ nCount--;
+ nPos++;
+ }
+ delete pZOrderList;
+ pZOrderList = pNewZOrderList;
+ nCount = pPaintedEntries->Count();
+ if( nCount )
+ {
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ pZOrderList->Insert( pPaintedEntries->GetObject( nCur ),pZOrderList->Count());
+ }
+ delete pPaintedEntries;
+
+ Rectangle aRect;
+ if( GetResizeRect( aRect ))
+ PaintResizeRect( aRect );
+}
+
+BOOL SvImpIconView::GetResizeRect( Rectangle& rRect )
+{
+ if( aHorSBar.IsVisible() && aVerSBar.IsVisible() )
+ {
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin());
+ aOrigin *= -1;
+ aOrigin.X() += aOutputSize.Width();
+ aOrigin.Y() += aOutputSize.Height();
+ rRect.SetPos( aOrigin );
+ rRect.SetSize( Size( nVerSBarWidth, nHorSBarHeight));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void SvImpIconView::PaintResizeRect( const Rectangle& rRect )
+{
+ const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
+ Color aNewColor = rStyleSettings.GetFaceColor();
+ Color aOldColor = pView->GetFillColor();
+ pView->SetFillColor( aNewColor );
+ pView->DrawRect( rRect );
+ pView->SetFillColor( aOldColor );
+}
+
+void SvImpIconView::RepaintSelectionItems()
+{
+ DBG_ERROR("RepaintSelectionItems");
+ pView->Invalidate(); // vorlaeufig
+}
+
+SvLBoxItem* SvImpIconView::GetItem( SvLBoxEntry* pEntry,
+ const Point& rAbsPos )
+{
+ Rectangle aRect;
+ SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ if( pStringItem )
+ {
+ aRect = CalcTextRect( pEntry, pStringItem );
+ if( aRect.IsInside( rAbsPos ) )
+ return pStringItem;
+ }
+ SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ if( pBmpItem )
+ {
+ aRect = CalcBmpRect( pEntry );
+ if( aRect.IsInside( rAbsPos ) )
+ return pBmpItem;
+ }
+ return 0;
+}
+
+void SvImpIconView::CalcDocPos( Point& aMaeuschenPos )
+{
+ aMaeuschenPos -= pView->GetMapMode().GetOrigin();
+}
+
+void SvImpIconView::MouseButtonDown( const MouseEvent& rMEvt)
+{
+ StopEditTimer();
+ pView->GrabFocus();
+ Point aDocPos( rMEvt.GetPosPixel() );
+ if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
+ return;
+ CalcDocPos( aDocPos );
+ SvLBoxEntry* pEntry = GetEntry( aDocPos );
+ if( !pEntry )
+ {
+ if( pView->GetSelectionMode() != SINGLE_SELECTION )
+ {
+ if( !rMEvt.IsMod1() ) // Ctrl
+ {
+ pView->SelectAll( FALSE );
+ ClearSelectedRectList();
+ }
+ else
+ nFlags |= F_ADD_MODE;
+ nFlags |= F_RUBBERING;
+ aCurSelectionRect.SetPos( aDocPos );
+ pView->CaptureMouse();
+ }
+ return;
+ }
+
+ BOOL bSelected = pView->IsSelected( pEntry );
+ BOOL bEditingEnabled = pView->IsInplaceEditingEnabled();
+
+ if( rMEvt.GetClicks() == 2 )
+ {
+ DeselectAllBut( pEntry );
+ pView->pHdlEntry = pEntry;
+ pView->DoubleClickHdl();
+ }
+ else
+ {
+ // Inplace-Editing ?
+ if( rMEvt.IsMod2() ) // Alt?
+ {
+ if( bEditingEnabled )
+ {
+ SvLBoxItem* pItem = GetItem(pEntry,aDocPos);
+ if( pItem )
+ pView->EditingRequest( pEntry, pItem, aDocPos);
+ }
+ }
+ else if( pView->GetSelectionMode() == SINGLE_SELECTION )
+ {
+ DeselectAllBut( pEntry );
+ SetCursor( pEntry );
+ pView->Select( pEntry, TRUE );
+ if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
+ rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
+ {
+ nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
+ }
+ }
+ else
+ {
+ if( !rMEvt.GetModifier() )
+ {
+ if( !bSelected )
+ {
+ DeselectAllBut( pEntry );
+ SetCursor( pEntry );
+ pView->Select( pEntry, TRUE );
+ }
+ else
+ {
+ // erst im Up deselektieren, falls Move per D&D!
+ nFlags |= F_DOWN_DESELECT;
+ if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
+ rMEvt.IsLeft())
+ {
+ nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
+ }
+ }
+ }
+ else if( rMEvt.IsMod1() )
+ nFlags |= F_DOWN_CTRL;
+ }
+ }
+}
+
+void SvImpIconView::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ aMouseMoveTimer.Stop();
+ pView->ReleaseMouse();
+ // HACK, da Einar noch nicht PrepareCommandEvent aufruft
+ if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
+ nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
+
+ if( nFlags & F_RUBBERING )
+ {
+ aMouseMoveTimer.Stop();
+ AddSelectedRect( aCurSelectionRect );
+ HideSelectionRect();
+ nFlags &= ~(F_RUBBERING | F_ADD_MODE);
+ }
+
+ SvLBoxEntry* pEntry = pView->GetEntry( rMEvt.GetPosPixel(), TRUE );
+ if( pEntry )
+ {
+ if( nFlags & F_DOWN_CTRL )
+ {
+ // Ctrl & MultiSelection
+ ToggleSelection( pEntry );
+ SetCursor( pEntry );
+ }
+ else if( nFlags & F_DOWN_DESELECT )
+ {
+ DeselectAllBut( pEntry );
+ SetCursor( pEntry );
+ pView->Select( pEntry, TRUE );
+ }
+ }
+
+ nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
+ if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
+ {
+ StartEditTimer();
+ nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
+ }
+}
+
+void SvImpIconView::MouseMove( const MouseEvent& rMEvt )
+{
+ if( nFlags & F_RUBBERING )
+ {
+ const Point& rPosPixel = rMEvt.GetPosPixel();
+ if( !aMouseMoveTimer.IsActive() )
+ {
+ aMouseMoveEvent = rMEvt;
+ aMouseMoveTimer.Start();
+ // ausserhalb des Fensters liegende Move-Events muessen
+ // vom Timer kommen, damit die Scrollgeschwindigkeit
+ // unabhaengig von Mausbewegungen ist.
+ if( rPosPixel.X() < 0 || rPosPixel.Y() < 0 )
+ return;
+ const Size& rSize = pView->GetOutputSizePixel();
+ if( rPosPixel.X() > rSize.Width() || rPosPixel.Y() > rSize.Height())
+ return;
+ }
+
+ if( &rMEvt != &aMouseMoveEvent )
+ aMouseMoveEvent = rMEvt;
+
+ long nScrollDX, nScrollDY;
+
+ CalcScrollOffsets(rMEvt.GetPosPixel(),nScrollDX,nScrollDY,FALSE );
+ BOOL bSelRectHidden = FALSE;
+ if( nScrollDX || nScrollDY )
+ {
+ HideSelectionRect();
+ bSelRectHidden = TRUE;
+ pView->Scroll( nScrollDX, nScrollDY );
+ }
+ Point aDocPos( rMEvt.GetPosPixel() );
+ aDocPos = pView->PixelToLogic( aDocPos );
+ Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos );
+ if( aRect != aCurSelectionRect )
+ {
+ HideSelectionRect();
+ bSelRectHidden = TRUE;
+ BOOL bAdd = (nFlags & F_ADD_MODE) ? TRUE : FALSE;
+ SelectRect( aRect, bAdd, &aSelectedRectList );
+ }
+ if( bSelRectHidden )
+ DrawSelectionRect( aRect );
+ }
+}
+
+BOOL SvImpIconView::KeyInput( const KeyEvent& rKEvt )
+{
+ StopEditTimer();
+ BOOL bKeyUsed = TRUE;
+ BOOL bMod1 = rKEvt.GetKeyCode().IsMod1();
+ BOOL bInAddMode = (BOOL)((nFlags & F_ADD_MODE) != 0);
+ int bDeselAll = (pView->GetSelectionMode() != SINGLE_SELECTION) &&
+ !bInAddMode;
+ SvLBoxEntry* pNewCursor;
+ USHORT nCode = rKEvt.GetKeyCode().GetCode();
+ switch( nCode )
+ {
+ case KEY_UP:
+ if( pCursor )
+ {
+ MakeVisible( pCursor );
+ pNewCursor = pImpCursor->GoUpDown(pCursor,FALSE);
+ if( pNewCursor )
+ {
+ if( bDeselAll )
+ pView->SelectAll( FALSE );
+ ShowCursor( FALSE );
+ MakeVisible( pNewCursor );
+ SetCursor( pNewCursor );
+ if( !bInAddMode )
+ pView->Select( pCursor, TRUE );
+ }
+ else
+ {
+ Rectangle aRect( GetBoundingRect( pCursor ) );
+ if( aRect.Top())
+ {
+ aRect.Bottom() -= aRect.Top();
+ aRect.Top() = 0;
+ MakeVisible( aRect );
+ }
+ }
+ }
+ break;
+
+ case KEY_DOWN:
+ if( pCursor )
+ {
+ pNewCursor=pImpCursor->GoUpDown( pCursor,TRUE );
+ if( pNewCursor )
+ {
+ MakeVisible( pCursor );
+ if( bDeselAll )
+ pView->SelectAll( FALSE );
+ ShowCursor( FALSE );
+ MakeVisible( pNewCursor );
+ SetCursor( pNewCursor );
+ if( !bInAddMode )
+ pView->Select( pCursor, TRUE );
+ }
+ }
+ break;
+
+ case KEY_RIGHT:
+ if( pCursor )
+ {
+ pNewCursor=pImpCursor->GoLeftRight(pCursor,TRUE );
+ if( pNewCursor )
+ {
+ MakeVisible( pCursor );
+ if( bDeselAll )
+ pView->SelectAll( FALSE );
+ ShowCursor( FALSE );
+ MakeVisible( pNewCursor );
+ SetCursor( pNewCursor );
+ if( !bInAddMode )
+ pView->Select( pCursor, TRUE );
+ }
+ }
+ break;
+
+ case KEY_LEFT:
+ if( pCursor )
+ {
+ MakeVisible( pCursor );
+ pNewCursor = pImpCursor->GoLeftRight(pCursor,FALSE );
+ if( pNewCursor )
+ {
+ if( bDeselAll )
+ pView->SelectAll( FALSE );
+ ShowCursor( FALSE );
+ MakeVisible( pNewCursor );
+ SetCursor( pNewCursor );
+ if( !bInAddMode )
+ pView->Select( pCursor, TRUE );
+ }
+ else
+ {
+ Rectangle aRect( GetBoundingRect(pCursor));
+ if( aRect.Left() )
+ {
+ aRect.Right() -= aRect.Left();
+ aRect.Left() = 0;
+ MakeVisible( aRect );
+ }
+ }
+ }
+ break;
+
+ case KEY_ESCAPE:
+ if( nFlags & F_RUBBERING )
+ {
+ HideSelectionRect();
+ pView->SelectAll( FALSE );
+ nFlags &= ~F_RUBBERING;
+ }
+ break;
+
+ case KEY_F8:
+ if( rKEvt.GetKeyCode().IsShift() )
+ {
+ if( nFlags & F_ADD_MODE )
+ nFlags &= (~F_ADD_MODE);
+ else
+ nFlags |= F_ADD_MODE;
+ }
+ break;
+
+#ifdef OS2
+ case KEY_F9:
+ if( rKEvt.GetKeyCode().IsShift() )
+ {
+ if( pCursor && pView->IsInplaceEditingEnabled() )
+ pView->EditEntry( pCursor );
+ }
+ break;
+#endif
+
+ case KEY_SPACE:
+ if( pCursor )
+ {
+ ToggleSelection( pCursor );
+ }
+ break;
+
+
+ case KEY_PAGEDOWN:
+ break;
+ case KEY_PAGEUP:
+ break;
+
+ case KEY_ADD:
+ case KEY_DIVIDE :
+ if( bMod1 )
+ pView->SelectAll( TRUE );
+ break;
+
+ case KEY_SUBTRACT:
+ case KEY_COMMA :
+ if( bMod1 )
+ pView->SelectAll( FALSE );
+ break;
+
+ case KEY_RETURN:
+ if( bMod1 )
+ {
+ if( pCursor && pView->IsInplaceEditingEnabled() )
+ pView->EditEntry( pCursor );
+ }
+ break;
+
+ default:
+ bKeyUsed = FALSE;
+
+ }
+ return bKeyUsed;
+}
+
+
+void SvImpIconView::PositionScrollBars( long nRealWidth, long nRealHeight )
+{
+ // hor scrollbar
+ Point aPos( 0, nRealHeight );
+ aPos.Y() -= nHorSBarHeight;
+
+#ifdef WIN
+ // vom linken und unteren Rand ein Pixel abschneiden
+ aPos.Y()++;
+ aPos.X()--;
+#endif
+#ifdef OS2
+ aPos.Y()++;
+#endif
+ if( aHorSBar.GetPosPixel() != aPos )
+ aHorSBar.SetPosPixel( aPos );
+
+ // ver scrollbar
+ aPos.X() = nRealWidth; aPos.Y() = 0;
+ aPos.X() -= nVerSBarWidth;
+
+#if defined(WIN) || defined(WNT)
+ aPos.X()++;
+ aPos.Y()--;
+#endif
+
+#ifdef OS2
+ aPos.Y()--;
+ aPos.X()++;
+#endif
+
+ if( aVerSBar.GetPosPixel() != aPos )
+ aVerSBar.SetPosPixel( aPos );
+}
+
+
+
+void SvImpIconView::AdjustScrollBars()
+{
+ long nVirtHeight = aVirtOutputSize.Height();
+ long nVirtWidth = aVirtOutputSize.Width();
+
+ Size aOSize( pView->Control::GetOutputSizePixel() );
+ long nRealHeight = aOSize.Height();
+ long nRealWidth = aOSize.Width();
+
+ PositionScrollBars( nRealWidth, nRealHeight );
+
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin() );
+
+ long nVisibleWidth;
+ if( nRealWidth > nVirtWidth )
+ nVisibleWidth = nVirtWidth + aOrigin.X();
+ else
+ nVisibleWidth = nRealWidth;
+
+ long nVisibleHeight;
+ if( nRealHeight > nVirtHeight )
+ nVisibleHeight = nVirtHeight + aOrigin.Y();
+ else
+ nVisibleHeight = nRealHeight;
+
+ bool bVerSBar = (pView->nWindowStyle & WB_VSCROLL) ? true : false;
+ bool bHorSBar = (pView->nWindowStyle & WB_HSCROLL) ? true : false;
+
+ USHORT nResult = 0;
+ if( nVirtHeight )
+ {
+ // activate ver scrollbar ?
+ if( bVerSBar || ( nVirtHeight > nVisibleHeight) )
+ {
+ nResult = 0x0001;
+ nRealWidth -= nVerSBarWidth;
+
+ if( nRealWidth > nVirtWidth )
+ nVisibleWidth = nVirtWidth + aOrigin.X();
+ else
+ nVisibleWidth = nRealWidth;
+
+ nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
+ }
+ // activate hor scrollbar ?
+ if( bHorSBar || (nVirtWidth > nVisibleWidth) )
+ {
+ nResult |= 0x0002;
+ nRealHeight -= nHorSBarHeight;
+
+ if( nRealHeight > nVirtHeight )
+ nVisibleHeight = nVirtHeight + aOrigin.Y();
+ else
+ nVisibleHeight = nRealHeight;
+
+ // brauchen wir jetzt doch eine senkrechte Scrollbar ?
+ if( !(nResult & 0x0001) && // nur wenn nicht schon da
+ ( (nVirtHeight > nVisibleHeight) || bVerSBar) )
+ {
+ nResult = 3; // both are active
+ nRealWidth -= nVerSBarWidth;
+
+ if( nRealWidth > nVirtWidth )
+ nVisibleWidth = nVirtWidth + aOrigin.X();
+ else
+ nVisibleWidth = nRealWidth;
+
+ nFlags |= F_VER_SBARSIZE_WITH_HBAR;
+ }
+ }
+ }
+
+ // size ver scrollbar
+ long nThumb = aVerSBar.GetThumbPos();
+ Size aSize( nVerSBarWidth, nRealHeight );
+#if defined(WIN) || defined(WNT)
+ aSize.Height() += 2;
+#endif
+#ifdef OS2
+ aSize.Height() += 3;
+#endif
+ if( aSize != aVerSBar.GetSizePixel() )
+ aVerSBar.SetSizePixel( aSize );
+ aVerSBar.SetVisibleSize( nVisibleHeight );
+ aVerSBar.SetPageSize( (nVisibleHeight*75)/100 );
+ if( nResult & 0x0001 )
+ {
+ aVerSBar.SetThumbPos( nThumb );
+ aVerSBar.Show();
+ }
+ else
+ {
+ aVerSBar.SetThumbPos( 0 );
+ aVerSBar.Hide();
+ }
+
+ // size hor scrollbar
+ nThumb = aHorSBar.GetThumbPos();
+ aSize.Width() = nRealWidth;
+ aSize.Height() = nHorSBarHeight;
+#if defined(WIN) || defined(WNT)
+ aSize.Width()++;
+#endif
+#ifdef OS2
+ aSize.Width() += 3;
+ if( nResult & 0x0001 ) // vertikale Scrollbar ?
+ aSize.Width()--;
+#endif
+#if defined(WIN) || defined(WNT)
+ if( nResult & 0x0001 ) // vertikale Scrollbar ?
+ {
+ aSize.Width()++;
+ nRealWidth++;
+ }
+#endif
+ if( aSize != aHorSBar.GetSizePixel() )
+ aHorSBar.SetSizePixel( aSize );
+ aHorSBar.SetVisibleSize( nVisibleWidth ); //nRealWidth );
+ aHorSBar.SetPageSize( (nVisibleWidth*75)/100 );
+ if( nResult & 0x0002 )
+ {
+ aHorSBar.SetThumbPos( nThumb );
+ aHorSBar.Show();
+ }
+ else
+ {
+ aHorSBar.SetThumbPos( 0 );
+ aHorSBar.Hide();
+ }
+
+#ifdef OS2
+ nRealWidth++;
+#endif
+ aOutputSize.Width() = nRealWidth;
+#if defined(WIN) || defined(WNT)
+ if( nResult & 0x0002 ) // hor scrollbar ?
+ nRealHeight++; // weil unterer Rand geclippt wird
+#endif
+#ifdef OS2
+ if( nResult & 0x0002 ) // hor scrollbar ?
+ nRealHeight++;
+#endif
+ aOutputSize.Height() = nRealHeight;
+}
+
+void __EXPORT SvImpIconView::Resize()
+{
+ StopEditTimer();
+ Rectangle aRect;
+ if( GetResizeRect(aRect) )
+ pView->Invalidate( aRect );
+ aOutputSize = pView->GetOutputSizePixel();
+ pImpCursor->Clear();
+
+#if 1
+ const Size& rSize = pView->Control::GetOutputSizePixel();
+ PositionScrollBars( rSize.Width(), rSize.Height() );
+ // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete
+ // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass
+ // die ScrollBars aufblitzen (SfxExplorerIconView!)
+ nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpIconView,UserEventHdl),0);
+#else
+ AdjustScrollBars();
+ if( GetResizeRect(aRect) )
+ PaintResizeRect( aRect );
+#endif
+}
+
+BOOL SvImpIconView::CheckHorScrollBar()
+{
+ if( !pZOrderList || !aHorSBar.IsVisible() )
+ return FALSE;
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin() );
+ if(!(pView->nWindowStyle & WB_HSCROLL) && !aOrigin.X() )
+ {
+ long nWidth = aOutputSize.Width();
+ USHORT nCount = pZOrderList->Count();
+ long nMostRight = 0;
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)pZOrderList->operator[](nCur);
+ long nRight = GetBoundingRect(pEntry).Right();
+ if( nRight > nWidth )
+ return FALSE;
+ if( nRight > nMostRight )
+ nMostRight = nRight;
+ }
+ aHorSBar.Hide();
+ aOutputSize.Height() += nHorSBarHeight;
+ aVirtOutputSize.Width() = nMostRight;
+ aHorSBar.SetThumbPos( 0 );
+ Range aRange;
+ aRange.Max() = nMostRight - 1;
+ aHorSBar.SetRange( aRange );
+ if( aVerSBar.IsVisible() )
+ {
+ Size aSize( aVerSBar.GetSizePixel());
+ aSize.Height() += nHorSBarHeight;
+ aVerSBar.SetSizePixel( aSize );
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL SvImpIconView::CheckVerScrollBar()
+{
+ if( !pZOrderList || !aVerSBar.IsVisible() )
+ return FALSE;
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin() );
+ if(!(pView->nWindowStyle & WB_VSCROLL) && !aOrigin.Y() )
+ {
+ long nDeepest = 0;
+ long nHeight = aOutputSize.Height();
+ USHORT nCount = pZOrderList->Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)pZOrderList->operator[](nCur);
+ long nBottom = GetBoundingRect(pEntry).Bottom();
+ if( nBottom > nHeight )
+ return FALSE;
+ if( nBottom > nDeepest )
+ nDeepest = nBottom;
+ }
+ aVerSBar.Hide();
+ aOutputSize.Width() += nVerSBarWidth;
+ aVirtOutputSize.Height() = nDeepest;
+ aVerSBar.SetThumbPos( 0 );
+ Range aRange;
+ aRange.Max() = nDeepest - 1;
+ aVerSBar.SetRange( aRange );
+ if( aHorSBar.IsVisible() )
+ {
+ Size aSize( aHorSBar.GetSizePixel());
+ aSize.Width() += nVerSBarWidth;
+ aHorSBar.SetSizePixel( aSize );
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+// blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden
+void SvImpIconView::CheckScrollBars()
+{
+ CheckVerScrollBar();
+ if( CheckHorScrollBar() )
+ CheckVerScrollBar();
+}
+
+
+void __EXPORT SvImpIconView::GetFocus()
+{
+ if( pCursor )
+ {
+ pView->SetEntryFocus( pCursor, TRUE );
+ ShowCursor( TRUE );
+ }
+}
+
+void __EXPORT SvImpIconView::LoseFocus()
+{
+ StopEditTimer();
+ if( pCursor )
+ pView->SetEntryFocus( pCursor,FALSE );
+ ShowCursor( FALSE );
+}
+
+void SvImpIconView::UpdateAll()
+{
+ AdjustScrollBars();
+ pImpCursor->Clear();
+ pView->Invalidate();
+}
+
+void SvImpIconView::PaintEntry( SvLBoxEntry* pEntry, SvIcnVwDataEntry* pViewData )
+{
+ Point aPos( GetEntryPosition( pEntry ) );
+ PaintEntry( pEntry, aPos, pViewData );
+}
+
+void SvImpIconView::PaintEmphasis( const Rectangle& rRect, BOOL bSelected,
+ BOOL bCursored, OutputDevice* pOut )
+{
+ // HACK fuer D&D
+ if( nFlags & F_NO_EMPHASIS )
+ return;
+
+ if( !pOut )
+ pOut = pView;
+
+ // Selektion painten
+ Color aOldFillColor = pOut->GetFillColor();
+ Color aOldLineColor = pOut->GetLineColor();
+ Color aNewColor;
+ const StyleSettings& rStyleSettings = pOut->GetSettings().GetStyleSettings();
+ if( bSelected )
+ {
+ aNewColor = rStyleSettings.GetHighlightColor();
+ }
+ else
+ {
+#ifndef OS2
+ aNewColor =rStyleSettings.GetFieldColor();
+#else
+ aNewColor = pOut->GetBackground().GetColor();
+#endif
+ }
+
+ if( bCursored )
+ {
+ pOut->SetLineColor( Color( COL_BLACK ) );
+ }
+ pOut->SetFillColor( aNewColor );
+ pOut->DrawRect( rRect );
+ pOut->SetFillColor( aOldFillColor );
+ pOut->SetLineColor( aOldLineColor );
+}
+
+void SvImpIconView::PaintItem( const Rectangle& rRect,
+ SvLBoxItem* pItem, SvLBoxEntry* pEntry, USHORT nPaintFlags,
+ OutputDevice* pOut )
+{
+ if( nViewMode == VIEWMODE_ICON && pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
+ {
+ const String& rStr = ((SvLBoxString*)pItem)->GetText();
+ DrawText( pOut, rRect, rStr, DRAWTEXT_FLAGS );
+ }
+ else
+ {
+ Point aPos( rRect.TopLeft() );
+ const Size& rSize = GetItemSize( pView, pEntry, pItem );
+ if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
+ aPos.X() += (rRect.GetWidth() - rSize.Width() ) / 2;
+ if( nPaintFlags & PAINTFLAG_VER_CENTERED )
+ aPos.Y() += (rRect.GetHeight() - rSize.Height() ) / 2;
+ pItem->Paint( aPos, *(SvLBox*)pOut, 0, pEntry );
+ }
+}
+
+void SvImpIconView::PaintEntry( SvLBoxEntry* pEntry, const Point& rPos,
+ SvIcnVwDataEntry* pViewData, OutputDevice* pOut )
+{
+ if( !pView->IsUpdateMode() )
+ return;
+
+ if( !pOut )
+ pOut = pView;
+
+ SvLBoxContextBmp* pBmpItem;
+
+ pView->PreparePaint( pEntry );
+
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(pEntry);
+
+ SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+
+ BOOL bSelected = pViewData->IsSelected();
+ BOOL bCursored = pViewData->IsCursored();
+
+ Font aTempFont( pOut->GetFont() );
+ // waehrend D&D nicht die Fontfarbe wechseln, da sonst auch die
+ // Emphasis gezeichnet werden muss! (weisser Adler auf weissem Grund)
+ if( bSelected && !(nFlags & F_NO_EMPHASIS) )
+ {
+ const StyleSettings& rStyleSettings = pOut->GetSettings().GetStyleSettings();
+ Font aNewFont( aTempFont );
+ aNewFont.SetColor( rStyleSettings.GetHighlightTextColor() );
+ pOut->SetFont( aNewFont );
+ }
+ Rectangle aTextRect( CalcTextRect(pEntry,pStringItem,&rPos,FALSE,pViewData));
+ Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos, pViewData ) );
+
+ switch( nViewMode )
+ {
+ case VIEWMODE_ICON:
+ pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ PaintEmphasis( aBmpRect, bSelected, bCursored, pOut );
+ PaintItem( aBmpRect, pBmpItem, pEntry,
+ PAINTFLAG_HOR_CENTERED | PAINTFLAG_VER_CENTERED, pOut );
+ PaintEmphasis( aTextRect, bSelected, FALSE, pOut );
+ PaintItem( aTextRect, pStringItem, pEntry, PAINTFLAG_HOR_CENTERED, pOut );
+ break;
+
+ case VIEWMODE_NAME:
+ pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ PaintEmphasis( aBmpRect, bSelected, bCursored, pOut );
+ PaintItem( aBmpRect, pBmpItem, pEntry, PAINTFLAG_VER_CENTERED, pOut );
+ PaintEmphasis( aTextRect, bSelected, FALSE, pOut );
+ PaintItem( aTextRect, pStringItem, pEntry,PAINTFLAG_VER_CENTERED, pOut );
+ break;
+
+ case VIEWMODE_TEXT:
+ PaintEmphasis( aTextRect, bSelected, bCursored, pOut );
+ PaintItem( aTextRect, pStringItem, pEntry, PAINTFLAG_VER_CENTERED, pOut );
+ break;
+ }
+ pOut->SetFont( aTempFont );
+}
+
+void SvImpIconView::SetEntryPosition( SvLBoxEntry* pEntry, const Point& rPos,
+ BOOL bAdjustAtGrid, BOOL bCheckScrollBars )
+{
+ if( pModel->GetParent(pEntry) == pCurParent )
+ {
+ ShowCursor( FALSE );
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ Rectangle aBoundRect( GetBoundingRect( pEntry, pViewData ));
+ pView->Invalidate( aBoundRect );
+ ToTop( pEntry );
+ if( rPos != aBoundRect.TopLeft() )
+ {
+ Point aGridOffs = pViewData->aGridRect.TopLeft() -
+ pViewData->aRect.TopLeft();
+ pImpCursor->Clear();
+ nFlags &= ~F_GRID_INSERT;
+ aBoundRect.SetPos( rPos );
+ pViewData->aRect = aBoundRect;
+ pViewData->aGridRect.SetPos( rPos + aGridOffs );
+ AdjustVirtSize( aBoundRect );
+ }
+ //HACK(Billigloesung, die noch verbessert werden muss)
+ if( bAdjustAtGrid )
+ {
+ AdjustAtGrid( pEntry );
+ ToTop( pEntry );
+ }
+ if( bCheckScrollBars && pView->IsUpdateMode() )
+ CheckScrollBars();
+
+ PaintEntry( pEntry, pViewData );
+ ShowCursor( TRUE );
+ }
+}
+
+void SvImpIconView::ViewDataInitialized( SvLBoxEntry*)
+{
+}
+
+void SvImpIconView::ModelHasEntryInvalidated( SvListEntry* pEntry )
+{
+ if( pEntry == pCursor )
+ ShowCursor( FALSE );
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ pView->Invalidate( pViewData->aRect );
+
+ if( nFlags & F_GRIDMODE )
+ Center( (SvLBoxEntry*)pEntry, pViewData );
+ else
+ pViewData->aRect.SetSize( CalcBoundingSize(
+ (SvLBoxEntry*)pEntry, pViewData ) );
+
+ ViewDataInitialized( (SvLBoxEntry*)pEntry );
+ pView->Invalidate( pViewData->aRect );
+ if( pEntry == pCursor )
+ ShowCursor( TRUE );
+}
+
+
+void SvImpIconView::InvalidateEntry( SvLBoxEntry* pEntry )
+{
+ const Rectangle& rRect = GetBoundingRect( pEntry );
+ pView->Invalidate( rRect );
+}
+
+void SvImpIconView::SetNoSelection()
+{
+}
+
+void SvImpIconView::SetDragDropMode( DragDropMode )
+{
+}
+
+void SvImpIconView::SetSelectionMode( SelectionMode )
+{
+}
+
+BOOL SvImpIconView::IsEntryInView( SvLBoxEntry* )
+{
+ return FALSE;
+}
+
+SvLBoxEntry* SvImpIconView::GetDropTarget( const Point& rPos )
+{
+ Point aDocPos( rPos );
+ CalcDocPos( aDocPos );
+ SvLBoxEntry* pTarget = GetEntry( aDocPos );
+ if( !pTarget || !pTarget->HasChilds() )
+ pTarget = pCurParent;
+ return pTarget;
+}
+
+SvLBoxEntry* SvImpIconView::GetEntry( const Point& rDocPos )
+{
+ CheckBoundingRects();
+ SvLBoxEntry* pTarget = 0;
+ // Z-Order-Liste vom Ende her absuchen
+ USHORT nCount = pZOrderList->Count();
+ while( nCount )
+ {
+ nCount--;
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nCount));
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ if( pViewData->aRect.IsInside( rDocPos ) )
+ {
+ pTarget = pEntry;
+ break;
+ }
+ }
+ return pTarget;
+}
+
+SvLBoxEntry* SvImpIconView::GetNextEntry( const Point& rDocPos, SvLBoxEntry* pCurEntry )
+{
+ CheckBoundingRects();
+ SvLBoxEntry* pTarget = 0;
+ USHORT nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
+ if( nStartPos != USHRT_MAX )
+ {
+ USHORT nCount = pZOrderList->Count();
+ for( USHORT nCur = nStartPos+1; nCur < nCount; nCur++ )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nCur));
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ if( pViewData->aRect.IsInside( rDocPos ) )
+ {
+ pTarget = pEntry;
+ break;
+ }
+ }
+ }
+ return pTarget;
+}
+
+SvLBoxEntry* SvImpIconView::GetPrevEntry( const Point& rDocPos, SvLBoxEntry* pCurEntry )
+{
+ CheckBoundingRects();
+ SvLBoxEntry* pTarget = 0;
+ USHORT nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
+ if( nStartPos != USHRT_MAX && nStartPos != 0 )
+ {
+ nStartPos--;
+ do
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nStartPos));
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ if( pViewData->aRect.IsInside( rDocPos ) )
+ {
+ pTarget = pEntry;
+ break;
+ }
+ } while( nStartPos > 0 );
+ }
+ return pTarget;
+}
+
+
+Point SvImpIconView::GetEntryPosition( SvLBoxEntry* pEntry )
+{
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ DBG_ASSERT(pViewData,"Entry not in model");
+ return pViewData->aRect.TopLeft();
+}
+
+const Rectangle& SvImpIconView::GetBoundingRect( SvLBoxEntry* pEntry, SvIcnVwDataEntry* pViewData )
+{
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(pEntry);
+ DBG_ASSERT(pViewData,"Entry not in model");
+ if( !IsBoundingRectValid( pViewData->aRect ))
+ FindBoundingRect( pEntry, pViewData );
+ return pViewData->aRect;
+}
+
+void SvImpIconView::SetSpaceBetweenEntries( long nHor, long nVer )
+{
+ nHorDist = nHor;
+ nVerDist = nVer;
+}
+
+Rectangle SvImpIconView::CalcBmpRect( SvLBoxEntry* pEntry, const Point* pPos,
+ SvIcnVwDataEntry* pViewData )
+{
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(pEntry);
+
+ Rectangle aBound = GetBoundingRect( pEntry, pViewData );
+ if( pPos )
+ aBound.SetPos( *pPos );
+ Point aPos( aBound.TopLeft() );
+
+ switch( nViewMode )
+ {
+ case VIEWMODE_ICON:
+ {
+ aPos.X() += ( aBound.GetWidth() - nMaxBmpWidth ) / 2;
+ Size aSize( nMaxBmpWidth, nMaxBmpHeight );
+ // das Bitmap-Rechteck soll nicht das TextRect beruehren
+ aSize.Height() -= 3;
+ return Rectangle( aPos, aSize );
+ }
+
+ case VIEWMODE_NAME:
+ return Rectangle( aPos,
+ Size( nMaxBmpWidth, aBound.GetHeight() ));
+
+ case VIEWMODE_TEXT:
+ return Rectangle( aPos, aBound.GetSize() );
+
+ default:
+ {
+ Rectangle aRect;
+ return aRect;
+ }
+ }
+}
+
+Rectangle SvImpIconView::CalcTextRect( SvLBoxEntry* pEntry,
+ SvLBoxString* pItem, const Point* pPos, BOOL bForInplaceEdit,
+ SvIcnVwDataEntry* pViewData )
+{
+ long nBmpHeight, nBmpWidth;
+
+ if( !pItem )
+ pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(pEntry);
+
+ Size aTextSize( GetItemSize( pView, pEntry, pItem, pViewData ));
+ aTextSize.Width() += 2*LROFFS_TEXT;
+
+ Size aContextBmpSize(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry));
+ Rectangle aBound = GetBoundingRect( pEntry, pViewData );
+ if( pPos )
+ aBound.SetPos( *pPos );
+ Point aPos( aBound.TopLeft() );
+
+ switch( nViewMode )
+ {
+ case VIEWMODE_ICON:
+ nBmpHeight = aContextBmpSize.Height();
+ if( nBmpHeight < nMaxBmpHeight )
+ nBmpHeight = nMaxBmpHeight;
+ aPos.Y() += nBmpHeight;
+
+ // beim Inplace-Editieren, spendieren wir ein bisschen mehr Platz
+ if( bForInplaceEdit )
+ {
+ // 20% rauf
+ long nMinWidth = (( (aContextBmpSize.Width()*10) / 100 ) * 2 ) +
+ aContextBmpSize.Width();
+ if( nMinWidth > aBound.GetWidth() )
+ nMinWidth = aBound.GetWidth();
+
+ if( aTextSize.Width() < nMinWidth )
+ aTextSize.Width() = nMinWidth;
+
+ // beim Inplace-Ed. darfs auch untere Eintraege ueberlappen
+ Rectangle aMaxGridTextRect = CalcMaxTextRect(pEntry, pViewData);
+ Size aOptSize = aMaxGridTextRect.GetSize();
+ if( aOptSize.Height() > aTextSize.Height() )
+ aTextSize.Height() = aOptSize.Height();
+ }
+
+
+ aPos.X() += ( aBound.GetWidth() - aTextSize.Width() ) / 2;
+ break;
+
+ case VIEWMODE_NAME:
+ nBmpWidth = aContextBmpSize.Width();
+ if( nBmpWidth < nMaxBmpWidth )
+ nBmpWidth = nMaxBmpWidth;
+ aPos.X() += nBmpWidth;
+ // vertikal ausrichten
+ aPos.Y() += ( nBmpWidth - aTextSize.Height() ) / 2;
+ break;
+ }
+
+ Rectangle aRect( aPos, aTextSize );
+// KNALLT BEIM D&D, WENN GECLIPPT WIRD (In DrawText von Thomas)
+// ClipAtVirtOutRect( aRect );
+ return aRect;
+}
+
+
+long SvImpIconView::CalcBoundingWidth( SvLBoxEntry* pEntry,
+ const SvIcnVwDataEntry* pViewData ) const
+{
+ DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP),"No Bitmaps");
+ DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),"No Text");
+ long nStringWidth = GetItemSize( pView, pEntry, pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),pViewData).Width();
+ nStringWidth += 2*LROFFS_TEXT;
+ long nBmpWidth = pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry).Width();
+ long nWidth = 0;
+
+ switch( nViewMode )
+ {
+ case VIEWMODE_ICON:
+ nWidth = Max( nStringWidth, nBmpWidth );
+ nWidth = Max( nWidth, nMaxBmpWidth );
+ break;
+
+ case VIEWMODE_NAME:
+ nWidth = Max( nBmpWidth, nMaxBmpWidth );
+ nWidth += NAMEVIEW_OFFS_BMP_STRING; // Abstand Bitmap String
+ nWidth += nStringWidth;
+ break;
+
+ case VIEWMODE_TEXT:
+ nWidth = nStringWidth;
+ break;
+ }
+ return nWidth;
+}
+
+long SvImpIconView::CalcBoundingHeight( SvLBoxEntry* pEntry,
+ const SvIcnVwDataEntry* pViewData ) const
+{
+ DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP),"No Bitmaps");
+ DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),"No Text");
+ long nStringHeight = GetItemSize(pView,pEntry,pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),pViewData).Height();
+ long nBmpHeight = pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry).Height();
+ long nHeight = 0;
+
+ switch( nViewMode )
+ {
+ case VIEWMODE_ICON:
+ nHeight = Max( nBmpHeight, nMaxBmpHeight );
+ nHeight += ICONVIEW_OFFS_BMP_STRING; // Abstand Bitmap String
+ nHeight += nStringHeight;
+ break;
+
+ case VIEWMODE_NAME:
+ nHeight = Max( nBmpHeight, nMaxBmpHeight );
+ nHeight = Max( nHeight, nStringHeight );
+ break;
+
+ case VIEWMODE_TEXT:
+ nHeight = nStringHeight;
+ break;
+ }
+ if( nHeight > nMaxBoundHeight )
+ {
+ ((SvImpIconView*)this)->nMaxBoundHeight = nHeight;
+ ((SvImpIconView*)this)->aHorSBar.SetLineSize( nHeight / 2 );
+ ((SvImpIconView*)this)->aVerSBar.SetLineSize( nHeight / 2 );
+ }
+ return nHeight;
+}
+
+Size SvImpIconView::CalcBoundingSize( SvLBoxEntry* pEntry,
+ SvIcnVwDataEntry* pViewData ) const
+{
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(pEntry);
+ return Size( CalcBoundingWidth(pEntry,pViewData),
+ CalcBoundingHeight(pEntry,pViewData) );
+}
+
+void SvImpIconView::RecalcAllBoundingRects()
+{
+ nMaxBoundHeight = 0;
+ pZOrderList->Remove(0, pZOrderList->Count() );
+ SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
+ while( pEntry )
+ {
+ FindBoundingRect( pEntry );
+ pZOrderList->Insert( pEntry, pZOrderList->Count() );
+ pEntry = pModel->NextSibling( pEntry );
+ }
+ bMustRecalcBoundingRects = FALSE;
+ AdjustScrollBars();
+}
+
+void SvImpIconView::RecalcAllBoundingRectsSmart()
+{
+ nMaxBoundHeight = 0;
+ pZOrderList->Remove(0, pZOrderList->Count() );
+ SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
+ while( pEntry )
+ {
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ if( IsBoundingRectValid( pViewData->aRect ))
+ {
+ Size aBoundSize( pViewData->aRect.GetSize() );
+ if( aBoundSize.Height() > nMaxBoundHeight )
+ nMaxBoundHeight = aBoundSize.Height();
+ pZOrderList->Insert( pEntry, pZOrderList->Count() );
+ }
+ else
+ {
+ FindBoundingRect( pEntry, pViewData );
+ }
+ pZOrderList->Insert( pEntry, pZOrderList->Count() );
+ pEntry = pModel->NextSibling( pEntry );
+ }
+ AdjustScrollBars();
+}
+
+void SvImpIconView::UpdateBoundingRects()
+{
+ SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
+ while( pEntry )
+ {
+ GetBoundingRect( pEntry );
+ pEntry = pModel->NextSibling( pEntry );
+ }
+}
+
+void SvImpIconView::FindBoundingRect( SvLBoxEntry* pEntry,
+ SvIcnVwDataEntry* pViewData )
+{
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(pEntry);
+
+ Size aSize( CalcBoundingSize( pEntry, pViewData ) );
+ Point aPos;
+
+ DBG_ASSERT(!pViewData->IsEntryPosLocked(),"Locked entry pos in FindBoundingRect");
+ // damits in der IconView nicht drunter & drueber geht
+ if( pViewData->IsEntryPosLocked() && IsBoundingRectValid(pViewData->aRect) )
+ {
+ AdjustVirtSize( pViewData->aRect );
+ return;
+ }
+
+ aPos = FindNextEntryPos( aSize );
+
+ if( nFlags & F_GRIDMODE )
+ {
+ Rectangle aGridRect( aPos, Size(nGridDX, nGridDY) );
+ pViewData->aGridRect = aGridRect;
+ Center( pEntry, pViewData );
+ AdjustVirtSize( pViewData->aRect );
+ pImpCursor->SetGridUsed( pViewData->aRect );
+ }
+ else
+ {
+ pViewData->aRect = Rectangle( aPos, aSize );
+ AdjustVirtSize( pViewData->aRect );
+ }
+}
+
+
+void SvImpIconView::SetCursor( SvLBoxEntry* pEntry )
+{
+ if( pEntry == pCursor )
+ return;
+
+ ShowCursor( FALSE );
+ if( pCursor )
+ {
+ pView->SetEntryFocus( pCursor, FALSE );
+ if( pView->GetSelectionMode() == SINGLE_SELECTION )
+ pView->Select( pCursor, FALSE );
+ }
+ pCursor = pEntry;
+ ToTop( pCursor );
+ if( pCursor )
+ {
+ pView->SetEntryFocus(pCursor, TRUE );
+ if( pView->GetSelectionMode() == SINGLE_SELECTION )
+ pView->Select( pCursor, TRUE );
+ ShowCursor( TRUE );
+ }
+}
+
+
+void SvImpIconView::ShowCursor( BOOL bShow )
+{
+ if( !pCursor || !bShow || !pView->HasFocus() )
+ {
+ pView->HideFocus();
+ return;
+ }
+ Rectangle aRect ( CalcFocusRect( pCursor ) );
+ pView->ShowFocus( aRect );
+}
+
+
+void SvImpIconView::HideDDIcon()
+{
+ pView->Update();
+ ImpHideDDIcon();
+ pDDBufDev = pDDDev;
+ pDDDev = 0;
+}
+
+void SvImpIconView::ImpHideDDIcon()
+{
+ if( pDDDev )
+ {
+ Size aSize( pDDDev->GetOutputSizePixel() );
+ // pView restaurieren
+ pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
+ }
+}
+
+
+void SvImpIconView::ShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPosPix )
+{
+ pView->Update();
+ if( pRefEntry != pDDRefEntry )
+ {
+ DELETEZ(pDDDev);
+ DELETEZ(pDDBufDev);
+ }
+ BOOL bSelected = pView->SvListView::Select( pRefEntry, FALSE );
+ if( !pDDDev )
+ {
+ if( pDDBufDev )
+ {
+ // nicht bei jedem Move ein Device anlegen, da dies besonders
+ // auf Remote-Clients zu langsam ist
+ pDDDev = pDDBufDev;
+ pDDBufDev = 0;
+ }
+ else
+ {
+ pDDDev = new VirtualDevice( *pView );
+ pDDDev->SetFont( pView->GetFont() );
+ }
+ }
+ else
+ {
+ ImpHideDDIcon();
+ }
+ const Rectangle& rRect = GetBoundingRect( pRefEntry );
+ pDDDev->SetOutputSizePixel( rRect.GetSize() );
+
+ Point aPos( rPosPix );
+ CalcDocPos( aPos );
+
+ Size aSize( pDDDev->GetOutputSizePixel() );
+ pDDRefEntry = pRefEntry;
+ aDDLastEntryPos = aPos;
+ aDDLastRectPos = aPos;
+
+ // Hintergrund sichern
+ pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView );
+ // Icon in pView malen
+ nFlags |= F_NO_EMPHASIS;
+ PaintEntry( pRefEntry, aPos );
+ nFlags &= ~F_NO_EMPHASIS;
+ if( bSelected )
+ pView->SvListView::Select( pRefEntry, TRUE );
+}
+
+void SvImpIconView::HideShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPosPix )
+{
+/* In Notfaellen folgenden flackernden Code aktivieren:
+
+ HideDDIcon();
+ ShowDDIcon( pRefEntry, rPosPix );
+ return;
+*/
+ if( !pDDDev )
+ {
+ ShowDDIcon( pRefEntry, rPosPix );
+ return;
+ }
+
+ if( pRefEntry != pDDRefEntry )
+ {
+ HideDDIcon();
+ ShowDDIcon( pRefEntry, rPosPix );
+ return;
+ }
+
+ Point aEmptyPoint;
+
+ Point aCurEntryPos( rPosPix );
+ CalcDocPos( aCurEntryPos );
+
+ const Rectangle& rRect = GetBoundingRect( pRefEntry );
+ Size aEntrySize( rRect.GetSize() );
+ Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize );
+ Rectangle aCurEntryRect( aCurEntryPos, aEntrySize );
+
+ if( !aPrevEntryRect.IsOver( aCurEntryRect ) )
+ {
+ HideDDIcon();
+ ShowDDIcon( pRefEntry, rPosPix );
+ return;
+ }
+
+ // Ueberlappung des neuen und alten D&D-Pointers!
+
+ Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) );
+ if( !pDDTempDev )
+ {
+ pDDTempDev = new VirtualDevice( *pView );
+ pDDTempDev->SetFont( pView->GetFont() );
+ }
+
+ Size aFullSize( aFullRect.GetSize() );
+ Point aFullPos( aFullRect.TopLeft() );
+
+ pDDTempDev->SetOutputSizePixel( aFullSize );
+
+ // Hintergrund (mit dem alten D&D-Pointer!) sichern
+ pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView );
+ // den alten Buffer in den neuen Buffer pasten
+ aDDLastRectPos = aDDLastRectPos - aFullPos;
+
+ pDDTempDev->DrawOutDev(
+ aDDLastRectPos,
+ pDDDev->GetOutputSizePixel(),
+ aEmptyPoint,
+ pDDDev->GetOutputSizePixel(),
+ *pDDDev );
+
+ // Swap
+ VirtualDevice* pTemp = pDDDev;
+ pDDDev = pDDTempDev;
+ pDDTempDev = pTemp;
+
+ // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen
+ pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() );
+ pDDTempDev->DrawOutDev(
+ aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev );
+ Point aRelPos = aCurEntryPos - aFullPos;
+ nFlags |= F_NO_EMPHASIS;
+ PaintEntry( pRefEntry, aRelPos, 0, pDDTempDev );
+ nFlags &= ~F_NO_EMPHASIS;
+
+ aDDLastRectPos = aFullPos;
+ aDDLastEntryPos = aCurEntryPos;
+
+ pView->DrawOutDev(
+ aDDLastRectPos,
+ pDDDev->GetOutputSizePixel(),
+ aEmptyPoint,
+ pDDDev->GetOutputSizePixel(),
+ *pDDTempDev );
+
+ BOOL bSelected = pView->SvListView::Select( pRefEntry, FALSE );
+ if( bSelected )
+ pView->SvListView::Select( pRefEntry, TRUE );
+}
+
+void SvImpIconView::ShowTargetEmphasis( SvLBoxEntry* pEntry, BOOL )
+{
+ CheckBoundingRects();
+ Rectangle aRect;
+ if( pEntry != pCurParent &&
+ (pEntry->HasChilds() || pEntry->HasChildsOnDemand()) )
+ aRect = CalcBmpRect( pEntry );
+ else
+ {
+ aRect.SetSize( aOutputSize );
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin());
+ aOrigin *= -1; // in Doc-Koord wandeln
+ aRect.SetPos( aOrigin );
+ aRect.Left()++; aRect.Top()++;
+ aRect.Right()--; aRect.Bottom()--;
+ }
+ ImpDrawXORRect( aRect );
+}
+
+BOOL SvImpIconView::NotifyMoving( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
+ SvLBoxEntry*& rpNewPar, ULONG& rNewChildPos )
+{
+ if( pTarget == pCurParent && pModel->GetParent(pEntry) == pCurParent )
+ {
+ // D&D innerhalb einer Childlist
+ StopEditTimer();
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ Size aSize( pViewData->aRect.GetSize() );
+ Point aNewPos = FindNextEntryPos( aSize );
+ AdjustVirtSize( Rectangle( aNewPos, aSize ) );
+ SetEntryPosition( pEntry, aNewPos, FALSE, TRUE );
+ return FALSE;
+ }
+ return pView->SvLBox::NotifyMoving(pTarget,pEntry,rpNewPar,rNewChildPos);
+}
+
+BOOL SvImpIconView::NotifyCopying( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
+ SvLBoxEntry*& rpNewParent, ULONG& rNewChildPos )
+{
+ return pView->SvLBox::NotifyCopying(pTarget,pEntry,rpNewParent,rNewChildPos);
+}
+
+void SvImpIconView::WriteDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo)
+{
+ SvLBoxEntry* pCurEntry = GetCurEntry();
+ Point aEntryPos;
+ if( pCurEntry )
+ {
+ aEntryPos = rPos;
+ aEntryPos -= GetEntryPosition( pCurEntry );
+ }
+ pInfo->nMouseRelX = aEntryPos.X();
+ pInfo->nMouseRelY = aEntryPos.Y();
+}
+
+void SvImpIconView::ReadDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo )
+{
+ Point aDropPos( rPos );
+ aDropPos.X() -= pInfo->nMouseRelX;
+ aDropPos.Y() -= pInfo->nMouseRelY;
+ SetNextEntryPos( aDropPos );
+}
+
+void SvImpIconView::InvalidateBoundingRect( SvLBoxEntry* pEntry )
+{
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ InvalidateBoundingRect( pViewData->aRect );
+}
+
+void SvImpIconView::PrepareCommandEvent( const Point& rPt )
+{
+ aMouseMoveTimer.Stop();
+ StopEditTimer();
+ nFlags |= F_CMD_ARRIVED;
+ SvLBoxEntry* pEntry = pView->GetEntry( rPt, TRUE );
+ if( (nFlags & F_DOWN_CTRL) && pEntry && !pView->IsSelected(pEntry) )
+ pView->Select( pEntry, TRUE );
+ nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
+}
+
+void SvImpIconView::SttDrag( const Point& rPos )
+{
+ PrepareCommandEvent( rPos );
+
+ nFlags |= F_DRAG_SOURCE;
+ ShowCursor( FALSE );
+}
+
+void SvImpIconView::EndDrag()
+{
+ ShowCursor( TRUE );
+ nFlags &= (~F_DRAG_SOURCE);
+}
+
+void SvImpIconView::ToTop( SvLBoxEntry* pEntry )
+{
+ DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"ToTop:ZOrder?");
+ if( pZOrderList->GetObject( pZOrderList->Count() -1 ) != pEntry )
+ {
+ USHORT nPos = pZOrderList->GetPos( (void*)pEntry );
+ pZOrderList->Remove( nPos, 1 );
+ pZOrderList->Insert( pEntry, pZOrderList->Count() );
+ }
+}
+
+void SvImpIconView::SetCurParent( SvLBoxEntry* pNewParent )
+{
+ Clear();
+ pCurParent = pNewParent;
+ ImpArrange();
+}
+
+void SvImpIconView::ClipAtVirtOutRect( Rectangle& rRect ) const
+{
+ if( rRect.Bottom() >= aVirtOutputSize.Height() )
+ rRect.Bottom() = aVirtOutputSize.Height() - 1;
+ if( rRect.Right() >= aVirtOutputSize.Width() )
+ rRect.Right() = aVirtOutputSize.Width() - 1;
+ if( rRect.Top() < 0 )
+ rRect.Top() = 0;
+ if( rRect.Left() < 0 )
+ rRect.Left() = 0;
+}
+
+// rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der
+// sichtbar gemacht werden soll.
+// bScrBar == TRUE: Das Rect wurde aufgrund eines ScrollBar-Events berechnet
+
+void SvImpIconView::MakeVisible( const Rectangle& rRect, BOOL bScrBar )
+{
+ Rectangle aRect( rRect );
+ ClipAtVirtOutRect( aRect );
+ MapMode aMapMode( pView->GetMapMode() );
+ Point aOrigin( aMapMode.GetOrigin() );
+ // in Dokumentkoordinate umwandeln
+ aOrigin *= -1;
+
+ Rectangle aOutputArea( aOrigin, aOutputSize );
+ if( aOutputArea.IsInside( aRect ) )
+ return; // ist schon sichtbar
+
+ long nDy;
+ if( aRect.Top() < aOutputArea.Top() )
+ {
+ // nach oben scrollen (nDy < 0)
+ nDy = aRect.Top() - aOutputArea.Top();
+ }
+ else if( aRect.Bottom() > aOutputArea.Bottom() )
+ {
+ // nach unten scrollen (nDy > 0)
+ nDy = aRect.Bottom() - aOutputArea.Bottom();
+ }
+ else
+ nDy = 0;
+
+ long nDx;
+ if( aRect.Left() < aOutputArea.Left() )
+ {
+ // nach links scrollen (nDx < 0)
+ nDx = aRect.Left() - aOutputArea.Left();
+ }
+ else if( aRect.Right() > aOutputArea.Right() )
+ {
+ // nach rechts scrollen (nDx > 0)
+ nDx = aRect.Right() - aOutputArea.Right();
+ }
+ else
+ nDx = 0;
+
+ aOrigin.X() += nDx;
+ aOrigin.Y() += nDy;
+ aOutputArea.SetPos( aOrigin );
+
+ pView->Update();
+
+ // Origin fuer SV invertieren (damit wir in
+ // Dokumentkoordinaten scrollen/painten koennen)
+ aOrigin *= -1;
+ aMapMode.SetOrigin( aOrigin );
+ pView->SetMapMode( aMapMode );
+
+ // in umgekehrte Richtung scrollen!
+ pView->Control::Scroll( -nDx, -nDy, aOutputArea, TRUE );
+ if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
+ {
+ if( !bScrBar )
+ {
+ aOrigin *= -1;
+ // Thumbs korrigieren
+ if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
+ aHorSBar.SetThumbPos( aOrigin.X() );
+ if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
+ aVerSBar.SetThumbPos( aOrigin.Y() );
+ }
+ }
+ // pruefen, ob ScrollBars noch benoetigt werden
+ CheckScrollBars();
+ pView->Update();
+}
+
+
+SvLBoxEntry* SvImpIconView::GetNewCursor()
+{
+ SvLBoxEntry* pNewCursor;
+ if( pCursor )
+ {
+ pNewCursor = pImpCursor->GoLeftRight( pCursor, FALSE );
+ if( !pNewCursor )
+ {
+ pNewCursor = pImpCursor->GoLeftRight( pCursor, TRUE );
+ if( !pNewCursor )
+ {
+ pNewCursor = pImpCursor->GoUpDown( pCursor, FALSE );
+ if( !pNewCursor )
+ pNewCursor = pImpCursor->GoUpDown( pCursor, TRUE );
+ }
+ }
+ }
+ else
+ pNewCursor = pModel->FirstChild( pCurParent );
+ DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"GetNewCursor failed");
+ return pNewCursor;
+}
+
+
+USHORT SvImpIconView:: GetSelectionCount() const
+{
+ USHORT nSelected = 0;
+ SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent);
+ while( pEntry )
+ {
+ if( pView->IsSelected( pEntry ) )
+ nSelected++;
+ pEntry = pModel->NextSibling( pEntry );
+ }
+ return nSelected;
+}
+
+
+void SvImpIconView::ToggleSelection( SvLBoxEntry* pEntry )
+{
+ BOOL bSel;
+ if( pView->IsSelected( pEntry ) )
+ bSel = FALSE;
+ else
+ bSel = TRUE;
+ pView->Select( pEntry, bSel );
+}
+
+void SvImpIconView::DeselectAllBut( SvLBoxEntry* pThisEntryNot )
+{
+ ClearSelectedRectList();
+ SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
+ while( pEntry )
+ {
+ if( pEntry != pThisEntryNot && pView->IsSelected( pEntry ))
+ pView->Select( pEntry, FALSE );
+ pEntry = pModel->NextSibling( pEntry );
+ }
+}
+
+#define ICN_ROWS 50
+#define ICN_COLS 30
+
+ImpIcnCursor::ImpIcnCursor( SvImpIconView* pOwner )
+{
+ pView = pOwner;
+ pColumns = 0;
+ pRows = 0;
+ pCurEntry = 0;
+ nDeltaWidth = 0;
+ nDeltaHeight= 0;
+ nCols = 0;
+ nRows = 0;
+ nGridCols = 0;
+ nGridRows = 0;
+ pGridMap = 0;
+}
+
+ImpIcnCursor::~ImpIcnCursor()
+{
+ delete[] pColumns;
+ delete[] pRows;
+ delete pGridMap;
+}
+
+USHORT ImpIcnCursor::GetSortListPos( SvPtrarr* pList, long nValue,
+ int bVertical )
+{
+ USHORT nCount = (USHORT)pList->Count();
+ if( !nCount )
+ return 0;
+
+ USHORT nCurPos = 0;
+ long nPrevValue = LONG_MIN;
+ while( nCount )
+ {
+ const Rectangle& rRect=
+ pView->GetBoundingRect((SvLBoxEntry*)(pList->GetObject(nCurPos)));
+ long nCurValue;
+ if( bVertical )
+ nCurValue = rRect.Top();
+ else
+ nCurValue = rRect.Left();
+ if( nValue >= nPrevValue && nValue <= nCurValue )
+ return (USHORT)nCurPos;
+ nPrevValue = nCurValue;
+ nCount--;
+ nCurPos++;
+ }
+ return pList->Count();
+}
+
+void ImpIcnCursor::ImplCreate()
+{
+ pView->CheckBoundingRects();
+ DBG_ASSERT(pColumns==0&&pRows==0,"ImplCreate: Not cleared");
+
+ SetDeltas();
+
+ pColumns = new SvPtrarr[ nCols ];
+ pRows = new SvPtrarr[ nRows ];
+
+ DELETEZ(pGridMap);
+
+ SvLBoxTreeList* pModel = pView->pModel;
+ SvLBoxEntry* pEntry = pModel->FirstChild( pView->pCurParent );
+ while( pEntry )
+ {
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
+ // const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ Rectangle rRect( pView->CalcBmpRect( pEntry,0,pViewData ) );
+ short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight );
+ short nX = (short)( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth );
+
+ // Rundungsfehler abfangen
+ if( nY >= nRows )
+ nY = sal::static_int_cast< short >(nRows - 1);
+ if( nX >= nCols )
+ nX = sal::static_int_cast< short >(nCols - 1);
+
+ USHORT nIns = GetSortListPos( &pColumns[nX], rRect.Top(), TRUE );
+ pColumns[ nX ].Insert( pEntry, nIns );
+
+ nIns = GetSortListPos( &pRows[nY], rRect.Left(), FALSE );
+ pRows[ nY ].Insert( pEntry, nIns );
+
+ pViewData->nX = nX;
+ pViewData->nY = nY;
+
+ pEntry = pModel->NextSibling( pEntry );
+ }
+}
+
+void ImpIcnCursor::CreateGridMap()
+{
+ if( pGridMap )
+ return;
+
+ const Size& rSize = pView->aVirtOutputSize;
+ long nWidth = rSize.Width();
+ if( nWidth < pView->nMaxVirtWidth )
+ nWidth = pView->nMaxVirtWidth;
+ nWidth -= 2*LROFFS_WINBORDER;
+ if( nWidth <= 0 )
+ nWidth = 1;
+
+ nGridDX = pView->nGridDX;
+ nGridDY = pView->nGridDY;
+
+ // Hinweis: Wegen der Abrundung bei Berechnung von nGridCols
+ // ist es moeglich, dass Eintrage nicht im Grid liegen. Diese
+ // wurden typischerweise manuell verschoben und gelockt
+ nGridCols = nWidth / nGridDX;
+ if( !nGridCols ) nGridCols = 1;
+
+ nGridRows = rSize.Height() / nGridDY;
+ // nRows nicht abrunden, da zur Vermeidung von Ueberlappungen
+ // das gesamte BoundingRect des Eintrags zur Markierung im Grid
+ // herangezogen wird.
+ if( (nGridRows * nGridDY) < rSize.Height() )
+ nGridRows++;
+ else if( !nGridRows )
+ nGridRows = 1;
+
+ //XXX
+ //nGridRows += 50; // in fuenfziger-Schritten
+
+ pGridMap = new BOOL[ nGridRows*nGridCols];
+ memset( (void*)pGridMap, 0, nGridRows*nGridCols );
+
+ SvLBoxTreeList* pModel = pView->pModel;
+ SvLBoxEntry* pEntry = pModel->FirstChild( pView->pCurParent );
+ while( pEntry )
+ {
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
+ const Rectangle& rRect = pViewData->aRect;
+ // nur, wenn der Entry schon plaziert ist
+ if( pView->IsBoundingRectValid( rRect ))
+ {
+ // Alle vom Eintrag beruehrten Grids kennzeichnen
+ SetGridUsed( pView->GetBoundingRect( pEntry, pViewData ) );
+ }
+ pEntry = pModel->NextSibling( pEntry );
+ }
+}
+
+BOOL ImpIcnCursor::GetGrid( const Point& rDocPos, USHORT& rGridX, USHORT& rGridY ) const
+{
+ Point aPos( rDocPos );
+ aPos.X() -= LROFFS_WINBORDER;
+ aPos.Y() -= TBOFFS_WINBORDER;
+ rGridX = (USHORT)(aPos.X() / nGridDX);
+ rGridY = (USHORT)(aPos.Y() / nGridDY);
+ BOOL bInGrid = TRUE;
+ if( rGridX >= nGridCols )
+ {
+ rGridX = sal::static_int_cast< USHORT >(nGridCols - 1);
+ bInGrid = FALSE;
+ }
+ if( rGridY >= nGridRows )
+ {
+ rGridY = sal::static_int_cast< USHORT >(nGridRows - 1);
+ if( !bInGrid )
+ return FALSE; // beide Koordinaten nicht im Grid
+ }
+ return TRUE;
+}
+
+void ImpIcnCursor::SetGridUsed( const Rectangle& rRect, BOOL bUsed )
+{
+ CreateGridMap();
+ USHORT nTLX, nTLY, nBRX, nBRY;
+
+ BOOL bTLInGrid = GetGrid( rRect.TopLeft(), nTLX, nTLY );
+ BOOL bBRInGrid = GetGrid( rRect.BottomRight(), nBRX, nBRY );
+
+ if( !bTLInGrid && !bBRInGrid )
+ return;
+
+ for( USHORT nCurY = nTLY; nCurY <= nBRY; nCurY++ )
+ {
+ for( USHORT nCurX = nTLX; nCurX <= nBRX; nCurX++ )
+ {
+ SetGridUsed( nCurX, nCurY, bUsed );
+ }
+ }
+}
+
+void ImpIcnCursor::Clear( BOOL bGridToo )
+{
+ if( pColumns )
+ {
+ delete[] pColumns;
+ delete[] pRows;
+ pColumns = 0;
+ pRows = 0;
+ pCurEntry = 0;
+ nDeltaWidth = 0;
+ nDeltaHeight = 0;
+ }
+ if( bGridToo && pGridMap )
+ {
+ DELETEZ(pGridMap);
+ nGridRows = 0;
+ nGridCols = 0;
+ }
+}
+
+SvLBoxEntry* ImpIcnCursor::SearchCol(USHORT nCol,USHORT nTop,USHORT nBottom,
+ USHORT, BOOL bDown, BOOL bSimple )
+{
+ DBG_ASSERT(pCurEntry,"SearchCol: No reference entry");
+ SvPtrarr* pList = &(pColumns[ nCol ]);
+ USHORT nCount = pList->Count();
+ if( !nCount )
+ return 0;
+
+ const Rectangle& rRefRect = pView->GetBoundingRect(pCurEntry);
+
+ if( bSimple )
+ {
+ USHORT nListPos = pList->GetPos( pCurEntry );
+ DBG_ASSERT(nListPos!=0xffff,"Entry not in Col-List");
+ if( bDown )
+ {
+ while( nListPos < nCount-1 )
+ {
+ nListPos++;
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
+ const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ if( rRect.Top() > rRefRect.Top() )
+ return pEntry;
+ }
+ return 0;
+ }
+ else
+ {
+ while( nListPos )
+ {
+ nListPos--;
+ if( nListPos < nCount )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
+ const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ if( rRect.Top() < rRefRect.Top() )
+ return pEntry;
+ }
+ }
+ return 0;
+ }
+ }
+
+ if( nTop > nBottom )
+ {
+ USHORT nTemp = nTop;
+ nTop = nBottom;
+ nBottom = nTemp;
+ }
+ long nMinDistance = LONG_MAX;
+ SvLBoxEntry* pResult = 0;
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pList->GetObject( nCur ));
+ if( pEntry != pCurEntry )
+ {
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
+ USHORT nY = pViewData->nY;
+ if( nY >= nTop && nY <= nBottom )
+ {
+ const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ long nDistance = rRect.Top() - rRefRect.Top();
+ if( nDistance < 0 )
+ nDistance *= -1;
+ if( nDistance && nDistance < nMinDistance )
+ {
+ nMinDistance = nDistance;
+ pResult = pEntry;
+ }
+ }
+ }
+ }
+ return pResult;
+}
+
+SvLBoxEntry* ImpIcnCursor::SearchRow(USHORT nRow,USHORT nLeft,USHORT nRight,
+ USHORT, BOOL bRight, BOOL bSimple )
+{
+ DBG_ASSERT(pCurEntry,"SearchRow: No reference entry");
+ SvPtrarr* pList = &(pRows[ nRow ]);
+ USHORT nCount = pList->Count();
+ if( !nCount )
+ return 0;
+
+ const Rectangle& rRefRect = pView->GetBoundingRect(pCurEntry);
+
+ if( bSimple )
+ {
+ USHORT nListPos = pList->GetPos( pCurEntry );
+ DBG_ASSERT(nListPos!=0xffff,"Entry not in Row-List");
+ if( bRight )
+ {
+ while( nListPos < nCount-1 )
+ {
+ nListPos++;
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
+ const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ if( rRect.Left() > rRefRect.Left() )
+ return pEntry;
+ }
+ return 0;
+ }
+ else
+ {
+ while( nListPos )
+ {
+ nListPos--;
+ if( nListPos < nCount )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
+ const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ if( rRect.Left() < rRefRect.Left() )
+ return pEntry;
+ }
+ }
+ return 0;
+ }
+
+ }
+ if( nRight < nLeft )
+ {
+ USHORT nTemp = nRight;
+ nRight = nLeft;
+ nLeft = nTemp;
+ }
+ long nMinDistance = LONG_MAX;
+ SvLBoxEntry* pResult = 0;
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pList->GetObject( nCur ));
+ if( pEntry != pCurEntry )
+ {
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
+ USHORT nX = pViewData->nX;
+ if( nX >= nLeft && nX <= nRight )
+ {
+ const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ long nDistance = rRect.Left() - rRefRect.Left();
+ if( nDistance < 0 )
+ nDistance *= -1;
+ if( nDistance && nDistance < nMinDistance )
+ {
+ nMinDistance = nDistance;
+ pResult = pEntry;
+ }
+ }
+ }
+ }
+ return pResult;
+}
+
+
+
+/*
+ Sucht ab dem uebergebenen Eintrag den naechsten rechts- bzw.
+ linksstehenden. Suchverfahren am Beispiel bRight = TRUE:
+
+ c
+ b c
+ a b c
+ S 1 1 1 ====> Suchrichtung
+ a b c
+ b c
+ c
+
+ S : Startposition
+ 1 : erstes Suchrechteck
+ a,b,c : 2., 3., 4. Suchrechteck
+*/
+
+SvLBoxEntry* ImpIcnCursor::GoLeftRight( SvLBoxEntry* pIcnEntry, BOOL bRight )
+{
+ SvLBoxEntry* pResult;
+ pCurEntry = pIcnEntry;
+ Create();
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pIcnEntry);
+ USHORT nY = pViewData->nY;
+ USHORT nX = pViewData->nX;
+ DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column");
+ DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row");
+ // Nachbar auf gleicher Zeile ?
+ if( bRight )
+ pResult = SearchRow(
+ nY, nX, sal::static_int_cast< USHORT >(nCols-1), nX, TRUE, TRUE );
+ else
+ pResult = SearchRow( nY, nX ,0, nX, FALSE, TRUE );
+ if( pResult )
+ return pResult;
+
+ long nCurCol = nX;
+
+ long nColOffs, nLastCol;
+ if( bRight )
+ {
+ nColOffs = 1;
+ nLastCol = nCols;
+ }
+ else
+ {
+ nColOffs = -1;
+ nLastCol = -1; // 0-1
+ }
+
+ USHORT nRowMin = nY;
+ USHORT nRowMax = nY;
+ do
+ {
+ SvLBoxEntry* pEntry = SearchCol((USHORT)nCurCol,nRowMin,nRowMax,nY,TRUE, FALSE);
+ if( pEntry )
+ return pEntry;
+ if( nRowMin )
+ nRowMin--;
+ if( nRowMax < (nRows-1))
+ nRowMax++;
+ nCurCol += nColOffs;
+ } while( nCurCol != nLastCol );
+ return 0;
+}
+
+SvLBoxEntry* ImpIcnCursor::GoUpDown( SvLBoxEntry* pIcnEntry, BOOL bDown)
+{
+ SvLBoxEntry* pResult;
+ pCurEntry = pIcnEntry;
+ Create();
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pIcnEntry);
+ USHORT nY = pViewData->nY;
+ USHORT nX = pViewData->nX;
+ DBG_ASSERT(nY<nRows,"GoUpDown:Bad column");
+ DBG_ASSERT(nX<nCols,"GoUpDown:Bad row");
+
+ // Nachbar in gleicher Spalte ?
+ if( bDown )
+ pResult = SearchCol(
+ nX, nY, sal::static_int_cast< USHORT >(nRows-1), nY, TRUE, TRUE );
+ else
+ pResult = SearchCol( nX, nY ,0, nY, FALSE, TRUE );
+ if( pResult )
+ return pResult;
+
+ long nCurRow = nY;
+
+ long nRowOffs, nLastRow;
+ if( bDown )
+ {
+ nRowOffs = 1;
+ nLastRow = nRows;
+ }
+ else
+ {
+ nRowOffs = -1;
+ nLastRow = -1; // 0-1
+ }
+
+ USHORT nColMin = nX;
+ USHORT nColMax = nX;
+ do
+ {
+ SvLBoxEntry* pEntry = SearchRow((USHORT)nCurRow,nColMin,nColMax,nX,TRUE, FALSE);
+ if( pEntry )
+ return pEntry;
+ if( nColMin )
+ nColMin--;
+ if( nColMax < (nCols-1))
+ nColMax++;
+ nCurRow += nRowOffs;
+ } while( nCurRow != nLastRow );
+ return 0;
+}
+
+void ImpIcnCursor::SetDeltas()
+{
+ const Size& rSize = pView->aVirtOutputSize;
+ if( pView->nFlags & F_GRIDMODE )
+ {
+ nGridDX = pView->nGridDX;
+ nGridDY = pView->nGridDY;
+ }
+ else
+ {
+ nGridDX = 20;
+ nGridDY = 20;
+ }
+ nCols = rSize.Width() / nGridDX;
+ if( !nCols )
+ nCols = 1;
+ nRows = rSize.Height() / nGridDY;
+ if( (nRows * nGridDY) < rSize.Height() )
+ nRows++;
+ if( !nRows )
+ nRows = 1;
+
+ nDeltaWidth = (short)(rSize.Width() / nCols);
+ nDeltaHeight = (short)(rSize.Height() / nRows);
+ if( !nDeltaHeight )
+ {
+ nDeltaHeight = 1;
+ DBG_WARNING("SetDeltas:Bad height");
+ }
+ if( !nDeltaWidth )
+ {
+ nDeltaWidth = 1;
+ DBG_WARNING("SetDeltas:Bad width");
+ }
+}
+
+
+void ImpIcnCursor::ExpandGrid()
+{
+ if( pGridMap )
+ {
+ long nNewGridRows = nGridRows + 20;
+ unsigned char* pTempMap = new unsigned char[ nNewGridRows * nGridCols ];
+ memcpy( pTempMap, pGridMap, nGridRows * nGridCols );
+ delete pGridMap;
+ pGridMap = pTempMap;
+ nGridRows = nNewGridRows;
+ }
+}
+
+BOOL ImpIcnCursor::FindEmptyGridRect( Rectangle& rRect )
+{
+ CreateGridMap();
+ USHORT nCount = (USHORT)(nGridCols * nGridRows);
+ if( !nCount )
+ return FALSE;
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ if( !pGridMap[ nCur ] )
+ {
+ USHORT nCol = (USHORT)(nCur % nGridCols);
+ USHORT nRow = (USHORT)(nCur / nGridCols);
+ rRect.Top() = nRow * nGridDY + TBOFFS_WINBORDER;
+ rRect.Bottom() = rRect.Top() + nGridDY;
+ rRect.Left() = nCol * nGridDX+ LROFFS_WINBORDER;
+ rRect.Right() = rRect.Left() + nGridDX;
+ SetGridUsed( nCol, nRow, TRUE );
+
+ //XXX
+ //if( nRow + 5 > nGridRows )
+ // ExpandGrid();
+ DBG_ASSERT(pGridMap[nCur],"SetGridUsed failed");
+ return TRUE;
+ }
+ }
+ // Gridmap ist voll: Um eine Zeile erweitern
+ rRect.Top() = nGridRows * nGridDY + TBOFFS_WINBORDER;
+ rRect.Bottom() = rRect.Top() + nGridDY;
+ rRect.Left() = LROFFS_WINBORDER;
+ rRect.Right() = rRect.Left() + nGridDX;
+ return FALSE;
+ //XXX
+ //ExpandGrid();
+ //return TRUE;
+}
+
+void ImpIcnCursor::CreateGridAjustData( SvPtrarr& rLists, SvLBoxEntry* pRefEntry)
+{
+ if( !pRefEntry )
+ {
+ USHORT nAdjustRows = (USHORT)(pView->aVirtOutputSize.Height() / pView->nGridDY);
+ nAdjustRows++; // wg. Abrundung!
+
+ if( !nAdjustRows )
+ return;
+ for( USHORT nCurList = 0; nCurList < nAdjustRows; nCurList++ )
+ {
+ SvPtrarr* pRow = new SvPtrarr;
+ rLists.Insert( (void*)pRow, nCurList );
+ }
+ SvLBoxEntry* pEntry = pView->pModel->FirstChild( pView->pCurParent );
+ while( pEntry )
+ {
+ const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
+ USHORT nIns = GetSortListPos((SvPtrarr*)rLists[nY],rRect.Left(),FALSE);
+ ((SvPtrarr*)rLists[ nY ])->Insert( pEntry, nIns );
+ pEntry = pView->pModel->NextSibling( pEntry );
+ }
+ }
+ else
+ {
+ // Aufbau eines hor. "Schlauchs" auf der RefEntry-Zeile
+
+ // UEBERLEGEN: BoundingRect nehmen wg. Ueberlappungen???
+
+ Rectangle rRefRect( pView->CalcBmpRect( pRefEntry ) );
+ //const Rectangle& rRefRect = pView->GetBoundingRect( pRefEntry );
+ short nRefRow = (short)( ((rRefRect.Top()+rRefRect.Bottom())/2) / pView->nGridDY );
+ SvPtrarr* pRow = new SvPtrarr;
+ rLists.Insert( (void*)pRow, 0 );
+ SvLBoxEntry* pEntry = pView->pModel->FirstChild( pView->pCurParent );
+ while( pEntry )
+ {
+ Rectangle rRect( pView->CalcBmpRect(pEntry) );
+ //const Rectangle& rRect = pView->GetBoundingRect( pEntry );
+ short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
+ if( nY == nRefRow )
+ {
+ USHORT nIns = GetSortListPos( pRow, rRect.Left(), FALSE );
+ pRow->Insert( pEntry, nIns );
+ }
+ pEntry = pView->pModel->NextSibling( pEntry );
+ }
+ }
+}
+
+//static
+void ImpIcnCursor::DestroyGridAdjustData( SvPtrarr& rLists )
+{
+ USHORT nCount = rLists.Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvPtrarr* pArr = (SvPtrarr*)rLists[ nCur ];
+ delete pArr;
+ }
+ rLists.Remove( 0, rLists.Count() );
+}
+
+void SvImpIconView::SetGrid( long nDX, long nDY )
+{
+ nGridDX = nDX;
+ nGridDY = nDY;
+ nFlags |= F_GRIDMODE;
+}
+
+Rectangle SvImpIconView::CalcMaxTextRect( const SvLBoxEntry* pEntry,
+ const SvIcnVwDataEntry* pViewData ) const
+{
+ Rectangle aRect = pViewData->aGridRect;
+ long nBmpHeight = ((SvLBoxEntry*)pEntry)->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,(SvLBoxEntry*)pEntry).Height();
+ aRect.Top() += nBmpHeight;
+ aRect.Top() += ICONVIEW_OFFS_BMP_STRING;
+ if( aRect.Top() > aRect.Bottom())
+ aRect.Top() = aRect.Bottom();
+ aRect.Left() += LROFFS_BOUND;
+ aRect.Left()++;
+ aRect.Right() -= LROFFS_BOUND;
+ aRect.Right()--;
+ if( aRect.Left() > aRect.Right())
+ aRect.Left() = aRect.Right();
+ if( GetTextMode( pEntry, pViewData ) == ShowTextFull )
+ aRect.Bottom() = LONG_MAX;
+ return aRect;
+}
+
+void SvImpIconView::Center( SvLBoxEntry* pEntry,
+ SvIcnVwDataEntry* pViewData ) const
+{
+ SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ const String& rEntryText = pStringItem->GetText();
+
+ Rectangle aTextRect = CalcMaxTextRect(pEntry,pViewData);
+ aTextRect = GetTextRect( pView, aTextRect, rEntryText, DRAWTEXT_FLAGS );
+ pViewData->aTextSize = aTextRect.GetSize();
+
+ pViewData->aRect = pViewData->aGridRect;
+ Size aSize( CalcBoundingSize( pEntry, pViewData ) );
+ long nBorder = pViewData->aGridRect.GetWidth() - aSize.Width();
+ pViewData->aRect.Left() += nBorder / 2;
+ pViewData->aRect.Right() -= nBorder / 2;
+ pViewData->aRect.Bottom() = pViewData->aRect.Top() + aSize.Height();
+}
+
+
+// Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird
+// links, hoch: Offsets < 0
+// rechts, runter: Offsets > 0
+void SvImpIconView::Scroll( long nDeltaX, long nDeltaY, BOOL bScrollBar )
+{
+ const MapMode& rMapMode = pView->GetMapMode();
+ Point aOrigin( rMapMode.GetOrigin() );
+ // in Dokumentkoordinate umwandeln
+ aOrigin *= -1;
+ aOrigin.Y() += nDeltaY;
+ aOrigin.X() += nDeltaX;
+ Rectangle aRect( aOrigin, aOutputSize );
+ MakeVisible( aRect, bScrollBar );
+}
+
+
+const Size& SvImpIconView::GetItemSize( SvIconView* pIconView,
+ SvLBoxEntry* pEntry, SvLBoxItem* pItem, const SvIcnVwDataEntry* pViewData) const
+{
+ if( (nFlags & F_GRIDMODE) && pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
+ {
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(pEntry);
+ return pViewData->aTextSize;
+ }
+ else
+ return pItem->GetSize( pIconView, pEntry );
+}
+
+Rectangle SvImpIconView::CalcFocusRect( SvLBoxEntry* pEntry )
+{
+#if !defined(OS2)
+ SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ DBG_ASSERT(pStringItem,"Text not set");
+ return CalcTextRect( pEntry, pStringItem );
+#else
+ return CalcBmpRect( pEntry );
+#endif
+}
+
+
+void SvImpIconView::SelectRect( const Rectangle& rRect, BOOL bAdd,
+ SvPtrarr* pOtherRects, short nBorderOffs )
+{
+ if( !pZOrderList || !pZOrderList->Count() )
+ return;
+
+ CheckBoundingRects();
+ pView->Update();
+ USHORT nCount = pZOrderList->Count();
+
+ Rectangle aRect( rRect );
+ aRect.Justify();
+ if( nBorderOffs )
+ {
+ aRect.Left() -= nBorderOffs;
+ aRect.Right() += nBorderOffs;
+ aRect.Top() -= nBorderOffs;
+ aRect.Bottom() += nBorderOffs;
+ }
+ BOOL bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? TRUE : FALSE;
+
+ for( USHORT nPos = 0; nPos < nCount; nPos++ )
+ {
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nPos ));
+
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ DBG_ASSERT(pViewData,"Entry not in model");
+ if( !IsBoundingRectValid( pViewData->aRect ))
+ FindBoundingRect( pEntry, pViewData );
+ const Rectangle& rBoundRect = pViewData->aRect;
+ BOOL bSelected = pViewData->IsSelected();
+
+ BOOL bOverlaps;
+ if( bCalcOverlap )
+ bOverlaps = IsOver( pOtherRects, rBoundRect );
+ else
+ bOverlaps = FALSE;
+ BOOL bOver = aRect.IsOver( rBoundRect );
+
+ if( bOver && !bOverlaps )
+ {
+ // Ist im neuen Selektionsrechteck und in keinem alten
+ // => selektieren
+ if( !bSelected )
+ pView->Select( pEntry, TRUE );
+ }
+ else if( !bAdd )
+ {
+ // ist ausserhalb des Selektionsrechtecks
+ // => Selektion entfernen
+ if( bSelected )
+ pView->Select( pEntry, FALSE );
+ }
+ else if( bAdd && bOverlaps )
+ {
+ // Der Eintrag befindet sich in einem alten (=>Aufspannen
+ // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck
+
+ // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags
+ // in einem vorherigen Rechteck, muss restauriert werden, wenn
+ // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber
+ // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber
+ // pauschal davon aus, dass die Eintraege in den alten Rechtecken
+ // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge
+ // nur zu deselektieren.
+ // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf-
+ // spannen des Rechtecks merken
+ if( rBoundRect.IsOver( rRect))
+ {
+ // Schnittmenge zwischen alten Rects & aktuellem Rect desel.
+ if( bSelected )
+ pView->Select( pEntry, FALSE );
+ }
+ else
+ {
+ // Eintrag eines alten Rects selektieren
+ if( !bSelected )
+ pView->Select( pEntry, TRUE );
+ }
+ }
+ else if( !bOver && bSelected )
+ {
+ // Der Eintrag liegt voellig ausserhalb und wird deshalb desel.
+ pView->Select( pEntry, FALSE );
+ }
+ }
+ pView->Update();
+}
+
+BOOL SvImpIconView::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const
+{
+ USHORT nCount = pRectList->Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur );
+ if( rBoundRect.IsOver( *pRect ))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void SvImpIconView::AddSelectedRect( const Rectangle& rRect, short nBorderOffs )
+{
+ Rectangle* pRect = new Rectangle( rRect );
+ pRect->Justify();
+ if( nBorderOffs )
+ {
+ pRect->Left() -= nBorderOffs;
+ pRect->Right() += nBorderOffs;
+ pRect->Top() -= nBorderOffs;
+ pRect->Bottom() += nBorderOffs;
+ }
+ aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() );
+}
+
+void SvImpIconView::ClearSelectedRectList()
+{
+ USHORT nCount = aSelectedRectList.Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur );
+ delete pRect;
+ }
+ aSelectedRectList.Remove( 0, aSelectedRectList.Count() );
+}
+
+
+void SvImpIconView::DrawSelectionRect( const Rectangle& rRect )
+{
+ pView->HideTracking();
+ nFlags |= F_SELRECT_VISIBLE;
+ pView->ShowTracking( rRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
+ aCurSelectionRect = rRect;
+}
+
+void SvImpIconView::HideSelectionRect()
+{
+ if( nFlags & F_SELRECT_VISIBLE )
+ {
+ pView->HideTracking();
+ nFlags &= ~F_SELRECT_VISIBLE;
+ }
+}
+
+void SvImpIconView::ImpDrawXORRect( const Rectangle& rRect )
+{
+ RasterOp eOldOp = pView->GetRasterOp();
+ pView->SetRasterOp( ROP_XOR );
+ Color aOldColor = pView->GetFillColor();
+ pView->SetFillColor();
+ pView->DrawRect( rRect );
+ pView->SetFillColor( aOldColor );
+ pView->SetRasterOp( eOldOp );
+}
+
+void SvImpIconView::CalcScrollOffsets( const Point& rPosPixel,
+ long& rX, long& rY, BOOL bInDragDrop, USHORT nBorderWidth)
+{
+ // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des
+ // Fensters befindet
+ long nPixelToScrollX = 0;
+ long nPixelToScrollY = 0;
+ Size aWndSize = aOutputSize;
+
+ nBorderWidth = (USHORT)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth ));
+ nBorderWidth = (USHORT)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth ));
+
+ if ( rPosPixel.X() < nBorderWidth )
+ {
+ if( bInDragDrop )
+ nPixelToScrollX = -DD_SCROLL_PIXEL;
+ else
+ nPixelToScrollX = rPosPixel.X()- nBorderWidth;
+ }
+ else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth )
+ {
+ if( bInDragDrop )
+ nPixelToScrollX = DD_SCROLL_PIXEL;
+ else
+ nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth);
+ }
+ if ( rPosPixel.Y() < nBorderWidth )
+ {
+ if( bInDragDrop )
+ nPixelToScrollY = -DD_SCROLL_PIXEL;
+ else
+ nPixelToScrollY = rPosPixel.Y() - nBorderWidth;
+ }
+ else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth )
+ {
+ if( bInDragDrop )
+ nPixelToScrollY = DD_SCROLL_PIXEL;
+ else
+ nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth);
+ }
+
+ rX = nPixelToScrollX;
+ rY = nPixelToScrollY;
+}
+
+IMPL_LINK(SvImpIconView, MouseMoveTimeoutHdl, Timer*, pTimer )
+{
+ pTimer->Start();
+ MouseMove( aMouseMoveEvent );
+ return 0;
+}
+
+void SvImpIconView::EndTracking()
+{
+ pView->ReleaseMouse();
+ if( nFlags & F_RUBBERING )
+ {
+ aMouseMoveTimer.Stop();
+ nFlags &= ~(F_RUBBERING | F_ADD_MODE);
+ }
+}
+
+BOOL SvImpIconView::IsTextHit( SvLBoxEntry* pEntry, const Point& rDocPos )
+{
+ SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ if( pItem )
+ {
+ Rectangle aRect( CalcTextRect( pEntry, pItem ));
+ if( aRect.IsInside( rDocPos ) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+IMPL_LINK(SvImpIconView, EditTimeoutHdl, Timer*, EMPTYARG )
+{
+ SvLBoxEntry* pEntry = GetCurEntry();
+ if( pView->IsInplaceEditingEnabled() && pEntry &&
+ pView->IsSelected( pEntry ))
+ {
+ pView->EditEntry( pEntry );
+ }
+ return 0;
+}
+
+
+//
+// Funktionen zum Ausrichten der Eintraege am Grid
+//
+
+// pStart == 0: Alle Eintraege werden ausgerichtet
+// sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet
+void SvImpIconView::AdjustAtGrid( SvLBoxEntry* pStart )
+{
+ SvPtrarr aLists;
+ pImpCursor->CreateGridAjustData( aLists, pStart );
+ USHORT nCount = aLists.Count();
+ for( USHORT nCur = 0; nCur < nCount; nCur++ )
+ {
+ AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart );
+ }
+ ImpIcnCursor::DestroyGridAdjustData( aLists );
+ CheckScrollBars();
+}
+
+// Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
+void SvImpIconView::AdjustAtGrid( const SvPtrarr& rRow, SvLBoxEntry* pStart )
+{
+ if( !rRow.Count() )
+ return;
+
+ BOOL bGo;
+ if( !pStart )
+ bGo = TRUE;
+ else
+ bGo = FALSE;
+
+ long nCurRight = 0;
+ for( USHORT nCur = 0; nCur < rRow.Count(); nCur++ )
+ {
+ SvLBoxEntry* pCur = (SvLBoxEntry*)rRow[ nCur ];
+ if( !bGo && pCur == pStart )
+ bGo = TRUE;
+
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
+ // Massgebend (fuer das menschliche Auge) ist die Bitmap, da sonst
+ // durch lange Texte der Eintrag stark springen kann
+ const Rectangle& rBoundRect = GetBoundingRect( pCur, pViewData );
+ Rectangle aCenterRect( CalcBmpRect( pCur, 0, pViewData ));
+ if( bGo && !pViewData->IsEntryPosLocked() )
+ {
+ long nWidth = aCenterRect.GetSize().Width();
+ Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
+ while( aNewPos.X() < nCurRight )
+ aNewPos.X() += nGridDX;
+ if( aNewPos != rBoundRect.TopLeft() )
+ SetEntryPosition( pCur, aNewPos );
+ nCurRight = aNewPos.X() + nWidth;
+ }
+ else
+ {
+ nCurRight = rBoundRect.Right();
+ }
+ }
+}
+
+// Richtet Rect am Grid aus, garantiert jedoch nicht, dass die
+// neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden.
+// Das CenterRect beschreibt den Teil des BoundRects, der fuer
+// die Berechnung des Ziel-Rechtecks verwendet wird.
+Point SvImpIconView::AdjustAtGrid( const Rectangle& rCenterRect,
+ const Rectangle& rBoundRect ) const
+{
+ Point aPos( rCenterRect.TopLeft() );
+ Size aSize( rCenterRect.GetSize() );
+
+ aPos.X() -= LROFFS_WINBORDER;
+ aPos.Y() -= TBOFFS_WINBORDER;
+
+ // align (ref ist mitte des rects)
+ short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
+ short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
+ aPos.X() = nGridX * nGridDX;
+ aPos.Y() = nGridY * nGridDY;
+ // hor. center
+ aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
+
+ aPos.X() += LROFFS_WINBORDER;
+ aPos.Y() += TBOFFS_WINBORDER;
+
+ return aPos;
+}
+
+
+void SvImpIconView::SetTextMode( SvIconViewTextMode eMode, SvLBoxEntry* pEntry )
+{
+ if( !pEntry )
+ {
+ if( eTextMode != eMode )
+ {
+ if( eTextMode == ShowTextDontKnow )
+ eTextMode = ShowTextShort;
+ eTextMode = eMode;
+ pView->Arrange();
+ }
+ }
+ else
+ {
+ SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
+ if( pViewData->eTextMode != eMode )
+ {
+ pViewData->eTextMode = eMode;
+ pModel->InvalidateEntry( pEntry );
+ AdjustVirtSize( pViewData->aRect );
+ }
+ }
+}
+
+SvIconViewTextMode SvImpIconView::GetTextMode( const SvLBoxEntry* pEntry,
+ const SvIcnVwDataEntry* pViewData ) const
+{
+ if( !pEntry )
+ return eTextMode;
+ else
+ {
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(((SvLBoxEntry*)pEntry));
+ return pViewData->GetTextMode();
+ }
+}
+
+SvIconViewTextMode SvImpIconView::GetEntryTextModeSmart( const SvLBoxEntry* pEntry,
+ const SvIcnVwDataEntry* pViewData ) const
+{
+ DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
+ if( !pViewData )
+ pViewData = ICNVIEWDATA(((SvLBoxEntry*)pEntry));
+ SvIconViewTextMode eMode = pViewData->GetTextMode();
+ if( eMode == ShowTextDontKnow )
+ return eTextMode;
+ return eMode;
+}
+
+void SvImpIconView::ShowFocusRect( const SvLBoxEntry* pEntry )
+{
+ if( !pEntry )
+ pView->HideFocus();
+ else
+ {
+ Rectangle aRect ( CalcFocusRect( (SvLBoxEntry*)pEntry ) );
+ pView->ShowFocus( aRect );
+ }
+}
+
+IMPL_LINK(SvImpIconView, UserEventHdl, void*, EMPTYARG )
+{
+ nCurUserEvent = 0;
+ AdjustScrollBars();
+ Rectangle aRect;
+ if( GetResizeRect(aRect) )
+ PaintResizeRect( aRect );
+ return 0;
+}
+
+void SvImpIconView::CancelUserEvent()
+{
+ if( nCurUserEvent )
+ {
+ Application::RemoveUserEvent( nCurUserEvent );
+ nCurUserEvent = 0;
+ }
+}
+
+
diff --git a/svtools/source/contnr/svlbitm.cxx b/svtools/source/contnr/svlbitm.cxx
new file mode 100644
index 000000000000..d260f984c2b0
--- /dev/null
+++ b/svtools/source/contnr/svlbitm.cxx
@@ -0,0 +1,651 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+
+#include <svtools/svlbox.hxx>
+#include <svtools/svlbitm.hxx>
+#include <vcl/svapp.hxx>
+#ifndef _SV_BUTTON_HXX
+#include <vcl/button.hxx>
+#endif
+#include <vcl/decoview.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/salnativewidgets.hxx>
+
+#define TABOFFS_NOT_VALID -2000000
+
+struct SvLBoxButtonData_Impl
+{
+ SvLBoxEntry* pEntry;
+ BOOL bDefaultImages;
+ BOOL bShowRadioButton;
+
+ SvLBoxButtonData_Impl() : pEntry( NULL ), bDefaultImages( FALSE ), bShowRadioButton( FALSE ) {}
+};
+
+
+DBG_NAME(SvLBoxButtonData)
+
+void SvLBoxButtonData::InitData( BOOL bImagesFromDefault, bool _bRadioBtn, const Control* pCtrl )
+{
+ pImpl = new SvLBoxButtonData_Impl;
+
+ bDataOk = FALSE;
+ eState = SV_BUTTON_UNCHECKED;
+ pImpl->bDefaultImages = bImagesFromDefault;
+ pImpl->bShowRadioButton = ( _bRadioBtn != false );
+
+ if ( bImagesFromDefault )
+ SetDefaultImages( pCtrl );
+}
+
+SvLBoxButtonData::SvLBoxButtonData( const Control* pControlForSettings )
+{
+ DBG_CTOR(SvLBoxButtonData,0);
+
+ InitData( TRUE, false, pControlForSettings );
+}
+
+SvLBoxButtonData::SvLBoxButtonData( const Control* pControlForSettings, bool _bRadioBtn )
+{
+ DBG_CTOR(SvLBoxButtonData,0);
+
+ InitData( TRUE, _bRadioBtn, pControlForSettings );
+}
+
+SvLBoxButtonData::SvLBoxButtonData()
+{
+ DBG_CTOR(SvLBoxButtonData,0);
+
+ InitData( FALSE, false );
+}
+
+SvLBoxButtonData::~SvLBoxButtonData()
+{
+ DBG_DTOR(SvLBoxButtonData,0);
+
+ delete pImpl;
+#ifdef DBG_UTIL
+ pImpl = NULL;
+#endif
+}
+
+void SvLBoxButtonData::CallLink()
+{
+ DBG_CHKTHIS(SvLBoxButtonData,0);
+ aLink.Call( this );
+}
+
+USHORT SvLBoxButtonData::GetIndex( USHORT nItemState )
+{
+ DBG_CHKTHIS(SvLBoxButtonData,0);
+ nItemState &= 0x000F;
+ USHORT nIdx;
+ switch( nItemState )
+ {
+ case SV_ITEMSTATE_UNCHECKED:
+ nIdx = SV_BMP_UNCHECKED; break;
+ case SV_ITEMSTATE_CHECKED:
+ nIdx = SV_BMP_CHECKED; break;
+ case SV_ITEMSTATE_TRISTATE:
+ nIdx = SV_BMP_TRISTATE; break;
+ case SV_ITEMSTATE_UNCHECKED | SV_ITEMSTATE_HILIGHTED:
+ nIdx = SV_BMP_HIUNCHECKED; break;
+ case SV_ITEMSTATE_CHECKED | SV_ITEMSTATE_HILIGHTED:
+ nIdx = SV_BMP_HICHECKED; break;
+ case SV_ITEMSTATE_TRISTATE | SV_ITEMSTATE_HILIGHTED:
+ nIdx = SV_BMP_HITRISTATE; break;
+ default:
+ nIdx = SV_BMP_UNCHECKED;
+ }
+ return nIdx;
+}
+
+void SvLBoxButtonData::SetWidthAndHeight()
+{
+ DBG_CHKTHIS(SvLBoxButtonData,0);
+ Size aSize = aBmps[0].GetSizePixel();
+ nWidth = aSize.Width();
+ nHeight = aSize.Height();
+ bDataOk = TRUE;
+}
+
+
+void SvLBoxButtonData::StoreButtonState( SvLBoxEntry* pActEntry, USHORT nItemFlags )
+{
+ DBG_CHKTHIS(SvLBoxButtonData,0);
+ pImpl->pEntry = pActEntry;
+ eState = ConvertToButtonState( nItemFlags );
+}
+
+SvButtonState SvLBoxButtonData::ConvertToButtonState( USHORT nItemFlags ) const
+{
+ DBG_CHKTHIS(SvLBoxButtonData,0);
+ nItemFlags &= (SV_ITEMSTATE_UNCHECKED |
+ SV_ITEMSTATE_CHECKED |
+ SV_ITEMSTATE_TRISTATE);
+ switch( nItemFlags )
+ {
+ case SV_ITEMSTATE_UNCHECKED:
+ return SV_BUTTON_UNCHECKED;
+
+ case SV_ITEMSTATE_CHECKED:
+ return SV_BUTTON_CHECKED;
+
+ case SV_ITEMSTATE_TRISTATE:
+ return SV_BUTTON_TRISTATE;
+ default:
+ return SV_BUTTON_UNCHECKED;
+ }
+}
+
+SvLBoxEntry* SvLBoxButtonData::GetActEntry() const
+{
+ DBG_ASSERT( pImpl, "-SvLBoxButtonData::GetActEntry(): don't use me that way!" );
+ return pImpl->pEntry;
+}
+
+void SvLBoxButtonData::SetDefaultImages( const Control* pCtrl )
+{
+ const AllSettings& rSettings = pCtrl? pCtrl->GetSettings() : Application::GetSettings();
+
+ if ( pImpl->bShowRadioButton )
+ {
+ aBmps[ SV_BMP_UNCHECKED ] = RadioButton::GetRadioImage( rSettings, BUTTON_DRAW_DEFAULT );
+ aBmps[ SV_BMP_CHECKED ] = RadioButton::GetRadioImage( rSettings, BUTTON_DRAW_CHECKED );
+ aBmps[ SV_BMP_HICHECKED ] = RadioButton::GetRadioImage( rSettings, BUTTON_DRAW_CHECKED | BUTTON_DRAW_PRESSED );
+ aBmps[ SV_BMP_HIUNCHECKED ] = RadioButton::GetRadioImage( rSettings, BUTTON_DRAW_DEFAULT | BUTTON_DRAW_PRESSED );
+ aBmps[ SV_BMP_TRISTATE ] = RadioButton::GetRadioImage( rSettings, BUTTON_DRAW_DONTKNOW );
+ aBmps[ SV_BMP_HITRISTATE ] = RadioButton::GetRadioImage( rSettings, BUTTON_DRAW_DONTKNOW | BUTTON_DRAW_PRESSED );
+ }
+ else
+ {
+ aBmps[ SV_BMP_UNCHECKED ] = CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_DEFAULT );
+ aBmps[ SV_BMP_CHECKED ] = CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_CHECKED );
+ aBmps[ SV_BMP_HICHECKED ] = CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_CHECKED | BUTTON_DRAW_PRESSED );
+ aBmps[ SV_BMP_HIUNCHECKED ] = CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_DEFAULT | BUTTON_DRAW_PRESSED );
+ aBmps[ SV_BMP_TRISTATE ] = CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_DONTKNOW );
+ aBmps[ SV_BMP_HITRISTATE ] = CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_DONTKNOW | BUTTON_DRAW_PRESSED );
+ }
+}
+
+BOOL SvLBoxButtonData::HasDefaultImages( void ) const
+{
+ return pImpl->bDefaultImages;
+}
+
+BOOL SvLBoxButtonData::IsRadio() {
+ return pImpl->bShowRadioButton;
+}
+
+// ***************************************************************
+// class SvLBoxString
+// ***************************************************************
+
+DBG_NAME(SvLBoxString);
+
+SvLBoxString::SvLBoxString( SvLBoxEntry* pEntry,USHORT nFlags,const XubString& rStr) :
+ SvLBoxItem( pEntry, nFlags )
+{
+ DBG_CTOR(SvLBoxString,0);
+ SetText( pEntry, rStr );
+}
+
+SvLBoxString::SvLBoxString() : SvLBoxItem()
+{
+ DBG_CTOR(SvLBoxString,0);
+}
+
+SvLBoxString::~SvLBoxString()
+{
+ DBG_DTOR(SvLBoxString,0);
+}
+
+USHORT SvLBoxString::IsA()
+{
+ DBG_CHKTHIS(SvLBoxString,0);
+ return SV_ITEM_ID_LBOXSTRING;
+}
+
+void SvLBoxString::Paint( const Point& rPos, SvLBox& rDev, USHORT /* nFlags */,
+ SvLBoxEntry* _pEntry)
+{
+ DBG_CHKTHIS(SvLBoxString,0);
+ if ( _pEntry )
+ {
+ USHORT nStyle = rDev.IsEnabled() ? 0 : TEXT_DRAW_DISABLE;
+ if ( rDev.IsEntryMnemonicsEnabled() )
+ nStyle |= TEXT_DRAW_MNEMONIC;
+ rDev.DrawText( Rectangle(rPos,GetSize(&rDev,_pEntry)),aStr,nStyle);
+ }
+ else
+ rDev.DrawText( rPos, aStr);
+
+}
+
+SvLBoxItem* SvLBoxString::Create() const
+{
+ DBG_CHKTHIS(SvLBoxString,0);
+ return new SvLBoxString;
+}
+
+void SvLBoxString::Clone( SvLBoxItem* pSource )
+{
+ DBG_CHKTHIS(SvLBoxString,0);
+ aStr = ((SvLBoxString*)pSource)->aStr;
+}
+
+void SvLBoxString::SetText( SvLBoxEntry*, const XubString& rStr )
+{
+ DBG_CHKTHIS(SvLBoxString,0);
+ aStr = rStr;
+}
+
+void SvLBoxString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry,
+ SvViewDataItem* pViewData)
+{
+ DBG_CHKTHIS(SvLBoxString,0);
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+ pViewData->aSize = Size(pView->GetTextWidth( aStr ), pView->GetTextHeight());
+}
+
+// ***************************************************************
+// class SvLBoxBmp
+// ***************************************************************
+
+DBG_NAME(SvLBoxBmp);
+
+SvLBoxBmp::SvLBoxBmp( SvLBoxEntry* pEntry, USHORT nFlags, Image aBitmap ) :
+ SvLBoxItem( pEntry, nFlags )
+{
+ DBG_CTOR(SvLBoxBmp,0);
+ SetBitmap( pEntry, aBitmap);
+}
+
+SvLBoxBmp::SvLBoxBmp() : SvLBoxItem()
+{
+ DBG_CTOR(SvLBoxBmp,0);
+}
+
+SvLBoxBmp::~SvLBoxBmp()
+{
+ DBG_DTOR(SvLBoxBmp,0);
+}
+
+USHORT SvLBoxBmp::IsA()
+{
+ DBG_CHKTHIS(SvLBoxBmp,0);
+ return SV_ITEM_ID_LBOXBMP;
+}
+
+void SvLBoxBmp::SetBitmap( SvLBoxEntry*, Image aBitmap)
+{
+ DBG_CHKTHIS(SvLBoxBmp,0);
+ aBmp = aBitmap;
+}
+
+void SvLBoxBmp::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry,
+ SvViewDataItem* pViewData)
+{
+ DBG_CHKTHIS(SvLBoxBmp,0);
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+ pViewData->aSize = aBmp.GetSizePixel();
+}
+
+void SvLBoxBmp::Paint( const Point& rPos, SvLBox& rDev, USHORT /* nFlags */,
+ SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBoxBmp,0);
+ USHORT nStyle = rDev.IsEnabled() ? 0 : IMAGE_DRAW_DISABLE;
+ rDev.DrawImage( rPos, aBmp ,nStyle);
+}
+
+SvLBoxItem* SvLBoxBmp::Create() const
+{
+ DBG_CHKTHIS(SvLBoxBmp,0);
+ return new SvLBoxBmp;
+}
+
+void SvLBoxBmp::Clone( SvLBoxItem* pSource )
+{
+ DBG_CHKTHIS(SvLBoxBmp,0);
+ aBmp = ((SvLBoxBmp*)pSource)->aBmp;
+}
+
+// ***************************************************************
+// class SvLBoxButton
+// ***************************************************************
+
+DBG_NAME(SvLBoxButton);
+
+SvLBoxButton::SvLBoxButton( SvLBoxEntry* pEntry, SvLBoxButtonKind eTheKind,
+ USHORT nFlags, SvLBoxButtonData* pBData )
+ : SvLBoxItem( pEntry, nFlags )
+{
+ DBG_CTOR(SvLBoxButton,0);
+ eKind = eTheKind;
+ nBaseOffs = 0;
+ nItemFlags = 0;
+ SetStateUnchecked();
+ pData = pBData;
+}
+
+SvLBoxButton::SvLBoxButton() : SvLBoxItem()
+{
+ DBG_CTOR(SvLBoxButton,0);
+ eKind = SvLBoxButtonKind_enabledCheckbox;
+ nItemFlags = 0;
+ SetStateUnchecked();
+}
+
+SvLBoxButton::~SvLBoxButton()
+{
+ DBG_DTOR(SvLBoxButton,0);
+}
+
+USHORT SvLBoxButton::IsA()
+{
+ DBG_CHKTHIS(SvLBoxButton,0);
+ return SV_ITEM_ID_LBOXBUTTON;
+}
+
+void SvLBoxButton::Check(SvLBox*, SvLBoxEntry*, BOOL bOn)
+{
+ DBG_CHKTHIS(SvLBoxButton,0);
+ if ( bOn != IsStateChecked() )
+ {
+ if ( bOn )
+ SetStateChecked();
+ else
+ SetStateUnchecked();
+ }
+}
+
+BOOL SvLBoxButton::ClickHdl( SvLBox*, SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvLBoxButton,0);
+ if ( CheckModification() )
+ {
+ if ( IsStateChecked() )
+ SetStateUnchecked();
+ else
+ SetStateChecked();
+ pData->StoreButtonState( pEntry, nItemFlags );
+ pData->CallLink();
+ }
+ return FALSE;
+}
+
+void SvLBoxButton::Paint( const Point& rPos, SvLBox& rDev, USHORT /* nFlags */,
+ SvLBoxEntry* /*pEntry*/ )
+{
+ DBG_CHKTHIS(SvLBoxButton,0);
+ USHORT nIndex = eKind == SvLBoxButtonKind_staticImage
+ ? SV_BMP_STATICIMAGE : pData->GetIndex( nItemFlags );
+ USHORT nStyle = eKind != SvLBoxButtonKind_disabledCheckbox &&
+ rDev.IsEnabled() ? 0 : IMAGE_DRAW_DISABLE;
+
+///
+//Native drawing
+///
+ BOOL bNativeOK = FALSE;
+ ControlType eCtrlType = (pData->IsRadio())? CTRL_RADIOBUTTON : CTRL_CHECKBOX;
+ if ( nIndex != SV_BMP_STATICIMAGE && rDev.IsNativeControlSupported( eCtrlType, PART_ENTIRE_CONTROL) )
+ {
+ Size aSize(pData->Width(), pData->Height());
+ ImplAdjustBoxSize( aSize, eCtrlType, &rDev );
+ ImplControlValue aControlValue;
+ Rectangle aCtrlRegion( rPos, aSize );
+ ControlState nState = 0;
+
+ //states CTRL_STATE_DEFAULT, CTRL_STATE_PRESSED and CTRL_STATE_ROLLOVER are not implemented
+ if ( IsStateHilighted() ) nState |= CTRL_STATE_FOCUSED;
+ if ( nStyle != IMAGE_DRAW_DISABLE ) nState |= CTRL_STATE_ENABLED;
+
+ if ( IsStateChecked() )
+ aControlValue.setTristateVal( BUTTONVALUE_ON );
+ else if ( IsStateUnchecked() )
+ aControlValue.setTristateVal( BUTTONVALUE_OFF );
+ else if ( IsStateTristate() )
+ aControlValue.setTristateVal( BUTTONVALUE_MIXED );
+
+ bNativeOK = rDev.DrawNativeControl( eCtrlType, PART_ENTIRE_CONTROL,
+ aCtrlRegion, nState, aControlValue, rtl::OUString() );
+ }
+
+ if( !bNativeOK)
+ rDev.DrawImage( rPos, pData->aBmps[nIndex + nBaseOffs] ,nStyle);
+}
+
+SvLBoxItem* SvLBoxButton::Create() const
+{
+ DBG_CHKTHIS(SvLBoxButton,0);
+ return new SvLBoxButton;
+}
+
+void SvLBoxButton::Clone( SvLBoxItem* pSource )
+{
+ DBG_CHKTHIS(SvLBoxButton,0);
+ pData = ((SvLBoxButton*)pSource)->pData;
+}
+
+void SvLBoxButton::ImplAdjustBoxSize( Size& io_rSize, ControlType i_eType, Window* i_pParent )
+{
+ if ( i_pParent->IsNativeControlSupported( i_eType, PART_ENTIRE_CONTROL) )
+ {
+ ImplControlValue aControlValue;
+ Rectangle aCtrlRegion( Point( 0, 0 ), io_rSize );
+ ControlState nState = CTRL_STATE_ENABLED;
+
+ aControlValue.setTristateVal( BUTTONVALUE_ON );
+
+ Rectangle aNativeBounds, aNativeContent;
+ bool bNativeOK = i_pParent->GetNativeControlRegion( i_eType,
+ PART_ENTIRE_CONTROL,
+ aCtrlRegion,
+ nState,
+ aControlValue,
+ rtl::OUString(),
+ aNativeBounds,
+ aNativeContent );
+ if( bNativeOK )
+ {
+ Size aContentSize( aNativeContent.GetSize() );
+ // leave a little space around the box image (looks better
+ if( aContentSize.Height() + 2 > io_rSize.Height() )
+ io_rSize.Height() = aContentSize.Height() + 2;
+ }
+ }
+}
+
+void SvLBoxButton::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry,
+ SvViewDataItem* pViewData )
+{
+ DBG_CHKTHIS(SvLBoxButton,0);
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+ Size aSize( pData->Width(), pData->Height() );
+
+ ControlType eCtrlType = (pData->IsRadio())? CTRL_RADIOBUTTON : CTRL_CHECKBOX;
+ if ( eKind != SvLBoxButtonKind_staticImage && pView )
+ ImplAdjustBoxSize( aSize, eCtrlType, pView );
+ pViewData->aSize = aSize;
+}
+
+bool SvLBoxButton::CheckModification() const
+{
+ if( eKind == SvLBoxButtonKind_disabledCheckbox )
+ Sound::Beep();
+ return eKind == SvLBoxButtonKind_enabledCheckbox;
+}
+
+// ***************************************************************
+// class SvLBoxContextBmp
+// ***************************************************************
+
+struct SvLBoxContextBmp_Impl
+{
+ Image m_aImage1;
+ Image m_aImage2;
+
+ Image m_aImage1_hc;
+ Image m_aImage2_hc;
+
+ USHORT m_nB2IndicatorFlags;
+};
+
+// ***************************************************************
+DBG_NAME(SvLBoxContextBmp)
+
+SvLBoxContextBmp::SvLBoxContextBmp( SvLBoxEntry* pEntry, USHORT nItemFlags,
+ Image aBmp1, Image aBmp2, USHORT nEntryFlags )
+ :SvLBoxItem( pEntry, nItemFlags )
+ ,m_pImpl( new SvLBoxContextBmp_Impl )
+{
+ DBG_CTOR(SvLBoxContextBmp,0);
+
+ m_pImpl->m_nB2IndicatorFlags = nEntryFlags;
+ SetModeImages( aBmp1, aBmp2 );
+}
+
+SvLBoxContextBmp::SvLBoxContextBmp()
+ :SvLBoxItem( )
+ ,m_pImpl( new SvLBoxContextBmp_Impl )
+{
+ m_pImpl->m_nB2IndicatorFlags = 0;
+ DBG_CTOR(SvLBoxContextBmp,0);
+}
+
+SvLBoxContextBmp::~SvLBoxContextBmp()
+{
+ delete m_pImpl;
+ DBG_DTOR(SvLBoxContextBmp,0);
+}
+
+USHORT SvLBoxContextBmp::IsA()
+{
+ DBG_CHKTHIS(SvLBoxContextBmp,0);
+ return SV_ITEM_ID_LBOXCONTEXTBMP;
+}
+
+BOOL SvLBoxContextBmp::SetModeImages( const Image& _rBitmap1, const Image& _rBitmap2, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvLBoxContextBmp,0);
+
+ sal_Bool bSuccess = sal_True;
+ switch ( _eMode )
+ {
+ case BMP_COLOR_NORMAL:
+ m_pImpl->m_aImage1 = _rBitmap1;
+ m_pImpl->m_aImage2 = _rBitmap2;
+ break;
+
+ case BMP_COLOR_HIGHCONTRAST:
+ m_pImpl->m_aImage1_hc = _rBitmap1;
+ m_pImpl->m_aImage2_hc = _rBitmap2;
+ break;
+
+ default:
+ DBG_ERROR( "SvLBoxContextBmp::SetModeImages: unexpected mode!");
+ bSuccess = sal_False;
+ break;
+ }
+ return bSuccess;
+}
+
+Image& SvLBoxContextBmp::implGetImageStore( sal_Bool _bFirst, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvLBoxContextBmp,0);
+
+ switch ( _eMode )
+ {
+ case BMP_COLOR_NORMAL:
+ return _bFirst ? m_pImpl->m_aImage1 : m_pImpl->m_aImage2;
+
+ case BMP_COLOR_HIGHCONTRAST:
+ return _bFirst ? m_pImpl->m_aImage1_hc : m_pImpl->m_aImage2_hc;
+
+ default:
+ DBG_ERROR( "SvLBoxContextBmp::implGetImageStore: unexpected mode!");
+ }
+
+ // OJ: #i27071# wrong mode so we just return the normal images
+ return _bFirst ? m_pImpl->m_aImage1 : m_pImpl->m_aImage2;
+}
+
+void SvLBoxContextBmp::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry,
+ SvViewDataItem* pViewData)
+{
+ DBG_CHKTHIS(SvLBoxContextBmp,0);
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+ pViewData->aSize = m_pImpl->m_aImage1.GetSizePixel();
+}
+
+void SvLBoxContextBmp::Paint( const Point& _rPos, SvLBox& _rDev,
+ USHORT _nViewDataEntryFlags, SvLBoxEntry* _pEntry )
+{
+ DBG_CHKTHIS(SvLBoxContextBmp,0);
+
+ // determine the image set
+ BmpColorMode eMode( BMP_COLOR_NORMAL );
+ if ( !!m_pImpl->m_aImage1_hc )
+ { // we really have HC images
+ if ( _rDev.GetSettings().GetStyleSettings().GetHighContrastMode() )
+ eMode = BMP_COLOR_HIGHCONTRAST;
+ }
+
+ // get the image
+ const Image& rImage = implGetImageStore( 0 == ( _nViewDataEntryFlags & m_pImpl->m_nB2IndicatorFlags ), eMode );
+
+ sal_Bool _bSemiTransparent = _pEntry && ( 0 != ( SV_ENTRYFLAG_SEMITRANSPARENT & _pEntry->GetFlags( ) ) );
+ // draw
+ USHORT nStyle = _rDev.IsEnabled() ? 0 : IMAGE_DRAW_DISABLE;
+ if ( _bSemiTransparent )
+ nStyle |= IMAGE_DRAW_SEMITRANSPARENT;
+ _rDev.DrawImage( _rPos, rImage, nStyle);
+}
+
+SvLBoxItem* SvLBoxContextBmp::Create() const
+{
+ DBG_CHKTHIS(SvLBoxContextBmp,0);
+ return new SvLBoxContextBmp;
+}
+
+void SvLBoxContextBmp::Clone( SvLBoxItem* pSource )
+{
+ DBG_CHKTHIS(SvLBoxContextBmp,0);
+ m_pImpl->m_aImage1 = static_cast< SvLBoxContextBmp* >( pSource )->m_pImpl->m_aImage1;
+ m_pImpl->m_aImage2 = static_cast< SvLBoxContextBmp* >( pSource )->m_pImpl->m_aImage2;
+ m_pImpl->m_nB2IndicatorFlags = static_cast< SvLBoxContextBmp* >( pSource )->m_pImpl->m_nB2IndicatorFlags;
+}
+
diff --git a/svtools/source/contnr/svlbox.cxx b/svtools/source/contnr/svlbox.cxx
new file mode 100644
index 000000000000..fb71f64772ad
--- /dev/null
+++ b/svtools/source/contnr/svlbox.cxx
@@ -0,0 +1,1923 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+/*
+ Todo:
+ - Anker loeschen in SelectionEngine bei manuellem Selektieren
+ - SelectAll( FALSE ), nur die deselektierten Entries repainten
+*/
+
+#include <string.h>
+#include <svtools/svlbox.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/accel.hxx>
+#include <vcl/i18nhelp.hxx>
+#include <sot/formats.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <rtl/instance.hxx>
+
+#define _SVSTDARR_ULONGSSORT
+#include <svl/svstdarr.hxx>
+
+#ifndef _SVEDI_HXX
+#include <svtools/svmedit.hxx>
+#endif
+#include <svtools/svlbitm.hxx>
+
+using namespace ::com::sun::star::accessibility;
+
+// Drag&Drop
+static SvLBox* pDDSource = NULL;
+static SvLBox* pDDTarget = NULL;
+
+DBG_NAME(SvInplaceEdit)
+DBG_NAME(SvInplaceEdit2)
+
+#define SVLBOX_ACC_RETURN 1
+#define SVLBOX_ACC_ESCAPE 2
+
+SvInplaceEdit::SvInplaceEdit
+(
+ Window* pParent,
+ const Point& rPos,
+ const Size& rSize,
+ const String& rData,
+ const Link& rNotifyEditEnd,
+ const Selection& rSelection
+) :
+
+ Edit( pParent, WB_LEFT ),
+
+ aCallBackHdl ( rNotifyEditEnd ),
+ bCanceled ( FALSE ),
+ bAlreadyInCallBack ( FALSE )
+
+{
+ DBG_CTOR(SvInplaceEdit,0);
+
+ Font aFont( pParent->GetFont() );
+ aFont.SetTransparent( FALSE );
+ Color aColor( pParent->GetBackground().GetColor() );
+ aFont.SetFillColor(aColor );
+ SetFont( aFont );
+ SetBackground( pParent->GetBackground() );
+ SetPosPixel( rPos );
+ SetSizePixel( rSize );
+ SetText( rData );
+ SetSelection( rSelection );
+ SaveValue();
+
+ aAccReturn.InsertItem( SVLBOX_ACC_RETURN, KeyCode(KEY_RETURN) );
+ aAccEscape.InsertItem( SVLBOX_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
+
+ aAccReturn.SetActivateHdl( LINK( this, SvInplaceEdit, ReturnHdl_Impl) );
+ aAccEscape.SetActivateHdl( LINK( this, SvInplaceEdit, EscapeHdl_Impl) );
+ GetpApp()->InsertAccel( &aAccReturn );
+ GetpApp()->InsertAccel( &aAccEscape );
+
+ Show();
+ GrabFocus();
+}
+
+SvInplaceEdit::~SvInplaceEdit()
+{
+ DBG_DTOR(SvInplaceEdit,0);
+ if( !bAlreadyInCallBack )
+ {
+ GetpApp()->RemoveAccel( &aAccReturn );
+ GetpApp()->RemoveAccel( &aAccEscape );
+ }
+}
+
+IMPL_LINK_INLINE_START( SvInplaceEdit, ReturnHdl_Impl, Accelerator *, EMPTYARG )
+{
+ DBG_CHKTHIS(SvInplaceEdit,0);
+ bCanceled = FALSE;
+ CallCallBackHdl_Impl();
+ return 1;
+}
+IMPL_LINK_INLINE_END( SvInplaceEdit, ReturnHdl_Impl, Accelerator *, EMPTYARG )
+
+IMPL_LINK_INLINE_START( SvInplaceEdit, EscapeHdl_Impl, Accelerator *, EMPTYARG )
+{
+ DBG_CHKTHIS(SvInplaceEdit,0);
+ bCanceled = TRUE;
+ CallCallBackHdl_Impl();
+ return 1;
+}
+IMPL_LINK_INLINE_END( SvInplaceEdit, EscapeHdl_Impl, Accelerator *, EMPTYARG )
+
+void SvInplaceEdit::KeyInput( const KeyEvent& rKEvt )
+{
+ DBG_CHKTHIS(SvInplaceEdit,0);
+ USHORT nCode = rKEvt.GetKeyCode().GetCode();
+ switch ( nCode )
+ {
+ case KEY_ESCAPE:
+ bCanceled = TRUE;
+ CallCallBackHdl_Impl();
+ break;
+
+ case KEY_RETURN:
+ bCanceled = FALSE;
+ CallCallBackHdl_Impl();
+ break;
+
+ default:
+ Edit::KeyInput( rKEvt );
+ }
+}
+
+void SvInplaceEdit::StopEditing( BOOL bCancel )
+{
+ DBG_CHKTHIS(SvInplaceEdit,0);
+ if ( !bAlreadyInCallBack )
+ {
+ bCanceled = bCancel;
+ CallCallBackHdl_Impl();
+ }
+}
+
+void SvInplaceEdit::LoseFocus()
+{
+ DBG_CHKTHIS(SvInplaceEdit,0);
+ if ( !bAlreadyInCallBack )
+ {
+ bCanceled = FALSE;
+ aTimer.SetTimeout(10);
+ aTimer.SetTimeoutHdl(LINK(this,SvInplaceEdit,Timeout_Impl));
+ aTimer.Start();
+ }
+}
+
+IMPL_LINK_INLINE_START( SvInplaceEdit, Timeout_Impl, Timer *, EMPTYARG )
+{
+ DBG_CHKTHIS(SvInplaceEdit,0);
+ CallCallBackHdl_Impl();
+ return 0;
+}
+IMPL_LINK_INLINE_END( SvInplaceEdit, Timeout_Impl, Timer *, EMPTYARG )
+
+void SvInplaceEdit::CallCallBackHdl_Impl()
+{
+ DBG_CHKTHIS(SvInplaceEdit,0);
+ aTimer.Stop();
+ if ( !bAlreadyInCallBack )
+ {
+ bAlreadyInCallBack = TRUE;
+ GetpApp()->RemoveAccel( &aAccReturn );
+ GetpApp()->RemoveAccel( &aAccEscape );
+ Hide();
+ aCallBackHdl.Call( this );
+ // bAlreadyInCallBack = FALSE;
+ }
+}
+
+
+// ***************************************************************
+
+class MyEdit_Impl : public Edit
+{
+ SvInplaceEdit2* pOwner;
+public:
+ MyEdit_Impl( Window* pParent, SvInplaceEdit2* pOwner );
+ virtual void KeyInput( const KeyEvent& rKEvt );
+ virtual void LoseFocus();
+};
+
+class MyMultiEdit_Impl : public MultiLineEdit
+{
+ SvInplaceEdit2* pOwner;
+public:
+ MyMultiEdit_Impl( Window* pParent, SvInplaceEdit2* pOwner );
+ virtual void KeyInput( const KeyEvent& rKEvt );
+ virtual void LoseFocus();
+};
+
+MyEdit_Impl::MyEdit_Impl( Window* pParent, SvInplaceEdit2* _pOwner ) :
+
+ Edit( pParent, WB_LEFT ),
+
+ pOwner( _pOwner )
+
+{
+}
+
+void MyEdit_Impl::KeyInput( const KeyEvent& rKEvt )
+{
+ if( !pOwner->KeyInput( rKEvt ))
+ Edit::KeyInput( rKEvt );
+}
+
+void MyEdit_Impl::LoseFocus()
+{
+ pOwner->LoseFocus();
+}
+
+MyMultiEdit_Impl::MyMultiEdit_Impl( Window* pParent, SvInplaceEdit2* _pOwner )
+ : MultiLineEdit( pParent,
+ WB_CENTER
+ ), pOwner(_pOwner)
+{
+}
+
+void MyMultiEdit_Impl::KeyInput( const KeyEvent& rKEvt )
+{
+ if( !pOwner->KeyInput( rKEvt ))
+ MultiLineEdit::KeyInput( rKEvt );
+}
+
+void MyMultiEdit_Impl::LoseFocus()
+{
+ pOwner->LoseFocus();
+}
+
+
+SvInplaceEdit2::SvInplaceEdit2
+(
+ Window* pParent, const Point& rPos,
+ const Size& rSize,
+ const String& rData,
+ const Link& rNotifyEditEnd,
+ const Selection& rSelection,
+ BOOL bMulti
+) :
+
+ aCallBackHdl ( rNotifyEditEnd ),
+ bCanceled ( FALSE ),
+ bAlreadyInCallBack ( FALSE ),
+ bMultiLine ( bMulti )
+
+{
+ DBG_CTOR(SvInplaceEdit2,0);
+
+ if( bMulti )
+ pEdit = new MyMultiEdit_Impl( pParent, this );
+ else
+ pEdit = new MyEdit_Impl( pParent, this );
+
+ Font aFont( pParent->GetFont() );
+ aFont.SetTransparent( FALSE );
+ Color aColor( pParent->GetBackground().GetColor() );
+ aFont.SetFillColor(aColor );
+ pEdit->SetFont( aFont );
+ pEdit->SetBackground( pParent->GetBackground() );
+ pEdit->SetPosPixel( rPos );
+ pEdit->SetSizePixel( rSize );
+ pEdit->SetText( rData );
+ pEdit->SetSelection( rSelection );
+ pEdit->SaveValue();
+
+ aAccReturn.InsertItem( SVLBOX_ACC_RETURN, KeyCode(KEY_RETURN) );
+ aAccEscape.InsertItem( SVLBOX_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
+
+ aAccReturn.SetActivateHdl( LINK( this, SvInplaceEdit2, ReturnHdl_Impl) );
+ aAccEscape.SetActivateHdl( LINK( this, SvInplaceEdit2, EscapeHdl_Impl) );
+ GetpApp()->InsertAccel( &aAccReturn );
+ GetpApp()->InsertAccel( &aAccEscape );
+
+ pEdit->Show();
+ pEdit->GrabFocus();
+}
+
+SvInplaceEdit2::~SvInplaceEdit2()
+{
+ DBG_DTOR(SvInplaceEdit2,0);
+ if( !bAlreadyInCallBack )
+ {
+ GetpApp()->RemoveAccel( &aAccReturn );
+ GetpApp()->RemoveAccel( &aAccEscape );
+ }
+ delete pEdit;
+}
+
+String SvInplaceEdit2::GetSavedValue() const
+{
+ return pEdit->GetSavedValue();
+}
+
+void SvInplaceEdit2::Hide()
+{
+ pEdit->Hide();
+}
+
+
+IMPL_LINK_INLINE_START( SvInplaceEdit2, ReturnHdl_Impl, Accelerator *, EMPTYARG )
+{
+ DBG_CHKTHIS(SvInplaceEdit2,0);
+ bCanceled = FALSE;
+ CallCallBackHdl_Impl();
+ return 1;
+}
+IMPL_LINK_INLINE_END( SvInplaceEdit2, ReturnHdl_Impl, Accelerator *, EMPTYARG )
+
+IMPL_LINK_INLINE_START( SvInplaceEdit2, EscapeHdl_Impl, Accelerator *, EMPTYARG )
+{
+ DBG_CHKTHIS(SvInplaceEdit2,0);
+ bCanceled = TRUE;
+ CallCallBackHdl_Impl();
+ return 1;
+}
+IMPL_LINK_INLINE_END( SvInplaceEdit2, EscapeHdl_Impl, Accelerator *, EMPTYARG )
+
+
+BOOL SvInplaceEdit2::KeyInput( const KeyEvent& rKEvt )
+{
+ DBG_CHKTHIS(SvInplaceEdit2,0);
+ KeyCode aCode = rKEvt.GetKeyCode();
+ USHORT nCode = aCode.GetCode();
+
+ switch ( nCode )
+ {
+ case KEY_ESCAPE:
+ bCanceled = TRUE;
+ CallCallBackHdl_Impl();
+ return TRUE;
+
+ case KEY_RETURN:
+ bCanceled = FALSE;
+ CallCallBackHdl_Impl();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void SvInplaceEdit2::StopEditing( BOOL bCancel )
+{
+ DBG_CHKTHIS(SvInplaceEdit2,0);
+ if ( !bAlreadyInCallBack )
+ {
+ bCanceled = bCancel;
+ CallCallBackHdl_Impl();
+ }
+}
+
+void SvInplaceEdit2::LoseFocus()
+{
+ DBG_CHKTHIS(SvInplaceEdit2,0);
+ if ( !bAlreadyInCallBack
+ && ((!Application::GetFocusWindow()) || !pEdit->IsChild( Application::GetFocusWindow()) )
+ )
+ {
+ bCanceled = FALSE;
+ aTimer.SetTimeout(10);
+ aTimer.SetTimeoutHdl(LINK(this,SvInplaceEdit2,Timeout_Impl));
+ aTimer.Start();
+ }
+}
+
+IMPL_LINK_INLINE_START( SvInplaceEdit2, Timeout_Impl, Timer *, EMPTYARG )
+{
+ DBG_CHKTHIS(SvInplaceEdit2,0);
+ CallCallBackHdl_Impl();
+ return 0;
+}
+IMPL_LINK_INLINE_END( SvInplaceEdit2, Timeout_Impl, Timer *, EMPTYARG )
+
+void SvInplaceEdit2::CallCallBackHdl_Impl()
+{
+ DBG_CHKTHIS(SvInplaceEdit2,0);
+ aTimer.Stop();
+ if ( !bAlreadyInCallBack )
+ {
+ bAlreadyInCallBack = TRUE;
+ GetpApp()->RemoveAccel( &aAccReturn );
+ GetpApp()->RemoveAccel( &aAccEscape );
+ pEdit->Hide();
+ aCallBackHdl.Call( this );
+ }
+}
+
+String SvInplaceEdit2::GetText() const
+{
+ return pEdit->GetText();
+}
+
+// ***************************************************************
+// class SvLBoxTab
+// ***************************************************************
+
+DBG_NAME(SvLBoxTab);
+
+SvLBoxTab::SvLBoxTab()
+{
+ DBG_CTOR(SvLBoxTab,0);
+ nPos = 0;
+ pUserData = 0;
+ nFlags = 0;
+}
+
+SvLBoxTab::SvLBoxTab( long nPosition, USHORT nTabFlags )
+{
+ DBG_CTOR(SvLBoxTab,0);
+ nPos = nPosition;
+ pUserData = 0;
+ nFlags = nTabFlags;
+}
+
+SvLBoxTab::SvLBoxTab( const SvLBoxTab& rTab )
+{
+ DBG_CTOR(SvLBoxTab,0);
+ nPos = rTab.nPos;
+ pUserData = rTab.pUserData;
+ nFlags = rTab.nFlags;
+}
+
+SvLBoxTab::~SvLBoxTab()
+{
+ DBG_DTOR(SvLBoxTab,0);
+}
+
+
+long SvLBoxTab::CalcOffset( long nItemWidth, long nTabWidth )
+{
+ DBG_CHKTHIS(SvLBoxTab,0);
+ long nOffset = 0;
+ if ( nFlags & SV_LBOXTAB_ADJUST_RIGHT )
+ {
+ nOffset = nTabWidth - nItemWidth;
+ if( nOffset < 0 )
+ nOffset = 0;
+ }
+ else if ( nFlags & SV_LBOXTAB_ADJUST_CENTER )
+ {
+ if( nFlags & SV_LBOXTAB_FORCE )
+ {
+ //richtige Implementierung der Zentrierung
+ nOffset = ( nTabWidth - nItemWidth ) / 2;
+ if( nOffset < 0 )
+ nOffset = 0;
+ }
+ else
+ {
+ // historisch gewachsene falsche Berechnung des Tabs, auf die sich
+ // Abo-Tabbox, Extras/Optionen/Anpassen etc. verlassen
+ nItemWidth++;
+ nOffset = -( nItemWidth / 2 );
+ }
+ }
+ return nOffset;
+}
+
+/*
+long SvLBoxTab::CalcOffset( const String& rStr, const OutputDevice& rOutDev )
+{
+ DBG_CHKTHIS(SvLBoxTab,0);
+ long nWidth;
+ if ( nFlags & SV_LBOXTAB_ADJUST_NUMERIC )
+ {
+ USHORT nPos = rStr.Search( '.' );
+ if ( nPos == STRING_NOTFOUND )
+ nPos = rStr.Search( ',' );
+ if ( nPos == STRING_NOTFOUND )
+ nPos = STRING_LEN;
+
+ nWidth = rOutDev.GetTextSize( rStr, 0, nPos ).Width();
+ nWidth *= -1;
+ }
+ else
+ {
+ nWidth = rOutDev.GetTextSize( rStr ).Width();
+ nWidth = CalcOffset( nWidth );
+ }
+ return nWidth;
+}
+*/
+
+// ***************************************************************
+// class SvLBoxItem
+// ***************************************************************
+
+DBG_NAME(SvLBoxItem);
+
+SvLBoxItem::SvLBoxItem( SvLBoxEntry*, USHORT )
+{
+ DBG_CTOR(SvLBoxItem,0);
+}
+
+SvLBoxItem::SvLBoxItem()
+{
+ DBG_CTOR(SvLBoxItem,0);
+}
+
+SvLBoxItem::~SvLBoxItem()
+{
+ DBG_DTOR(SvLBoxItem,0);
+}
+
+const Size& SvLBoxItem::GetSize( SvLBox* pView,SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvLBoxItem,0);
+ SvViewDataItem* pViewData = pView->GetViewDataItem( pEntry, this );
+ return pViewData->aSize;
+}
+
+const Size& SvLBoxItem::GetSize( SvLBoxEntry* pEntry, SvViewDataEntry* pViewData)
+{
+ DBG_CHKTHIS(SvLBoxItem,0);
+ USHORT nItemPos = pEntry->GetPos( this );
+ SvViewDataItem* pItemData = pViewData->pItemData+nItemPos;
+ return pItemData->aSize;
+}
+
+DBG_NAME(SvViewDataItem);
+
+SvViewDataItem::SvViewDataItem()
+{
+ DBG_CTOR(SvViewDataItem,0);
+}
+
+SvViewDataItem::~SvViewDataItem()
+{
+ DBG_DTOR(SvViewDataItem,0);
+}
+
+
+
+// ***************************************************************
+// class SvLBoxEntry
+// ***************************************************************
+
+DBG_NAME(SvLBoxEntry);
+
+SvLBoxEntry::SvLBoxEntry() : aItems()
+{
+ DBG_CTOR(SvLBoxEntry,0);
+ nEntryFlags = 0;
+ pUserData = 0;
+}
+
+SvLBoxEntry::~SvLBoxEntry()
+{
+ DBG_DTOR(SvLBoxEntry,0);
+ DeleteItems_Impl();
+}
+
+void SvLBoxEntry::DeleteItems_Impl()
+{
+ DBG_CHKTHIS(SvLBoxEntry,0);
+ USHORT nCount = aItems.Count();
+ while( nCount )
+ {
+ nCount--;
+ SvLBoxItem* pItem = (SvLBoxItem*)aItems.GetObject( nCount );
+ delete pItem;
+ }
+ aItems.Remove(0, aItems.Count() );
+}
+
+
+void SvLBoxEntry::AddItem( SvLBoxItem* pItem )
+{
+ DBG_CHKTHIS(SvLBoxEntry,0);
+ aItems.Insert( pItem, aItems.Count() );
+}
+
+void SvLBoxEntry::Clone( SvListEntry* pSource )
+{
+ DBG_CHKTHIS(SvLBoxEntry,0);
+ SvListEntry::Clone( pSource );
+ SvLBoxItem* pNewItem;
+ DeleteItems_Impl();
+ USHORT nCount = ((SvLBoxEntry*)pSource)->ItemCount();
+ USHORT nCurPos = 0;
+ while( nCurPos < nCount )
+ {
+ SvLBoxItem* pItem = ((SvLBoxEntry*)pSource)->GetItem( nCurPos );
+ pNewItem = pItem->Create();
+ pNewItem->Clone( pItem );
+ AddItem( pNewItem );
+ nCurPos++;
+ }
+ pUserData = ((SvLBoxEntry*)pSource)->GetUserData();
+ nEntryFlags = ((SvLBoxEntry*)pSource)->nEntryFlags;
+}
+
+void SvLBoxEntry::EnableChildsOnDemand( BOOL bEnable )
+{
+ DBG_CHKTHIS(SvLBoxEntry,0);
+ if ( bEnable )
+ nEntryFlags |= SV_ENTRYFLAG_CHILDS_ON_DEMAND;
+ else
+ nEntryFlags &= (~SV_ENTRYFLAG_CHILDS_ON_DEMAND);
+}
+
+void SvLBoxEntry::ReplaceItem( SvLBoxItem* pNewItem, USHORT nPos )
+{
+ DBG_CHKTHIS(SvLBoxEntry,0);
+ DBG_ASSERT(pNewItem,"ReplaceItem:No Item");
+ SvLBoxItem* pOld = GetItem( nPos );
+ if ( pOld )
+ {
+ aItems.Remove( nPos );
+ aItems.Insert( pNewItem, nPos );
+ delete pOld;
+ }
+}
+
+SvLBoxItem* SvLBoxEntry::GetFirstItem( USHORT nId )
+{
+ USHORT nCount = aItems.Count();
+ USHORT nCur = 0;
+ SvLBoxItem* pItem;
+ while( nCur < nCount )
+ {
+ pItem = GetItem( nCur );
+ if( pItem->IsA() == nId )
+ return pItem;
+ nCur++;
+ }
+ return 0;
+}
+
+// ***************************************************************
+// class SvLBoxViewData
+// ***************************************************************
+
+DBG_NAME(SvViewDataEntry);
+
+SvViewDataEntry::SvViewDataEntry()
+ : SvViewData()
+{
+ DBG_CTOR(SvViewDataEntry,0);
+ pItemData = 0;
+}
+
+SvViewDataEntry::~SvViewDataEntry()
+{
+ DBG_DTOR(SvViewDataEntry,0);
+ delete [] pItemData;
+}
+
+// ***************************************************************
+// struct SvLBox_Impl
+// ***************************************************************
+SvLBox_Impl::SvLBox_Impl( SvLBox& _rBox )
+ :m_bIsEmptyTextAllowed( true )
+ ,m_bEntryMnemonicsEnabled( false )
+ ,m_pLink( NULL )
+ ,m_aMnemonicEngine( _rBox )
+{
+}
+
+// ***************************************************************
+// class SvLBox
+// ***************************************************************
+
+DBG_NAME(SvLBox);
+
+SvLBox::SvLBox( Window* pParent, WinBits nWinStyle ) :
+ Control( pParent, nWinStyle | WB_CLIPCHILDREN ),
+ DropTargetHelper( this ), DragSourceHelper( this ), eSelMode( NO_SELECTION )
+{
+ DBG_CTOR(SvLBox,0);
+ nWindowStyle = nWinStyle;
+ nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
+ nImpFlags = 0;
+ pTargetEntry = 0;
+ nDragDropMode = 0;
+ pLBoxImpl = new SvLBox_Impl( *this );
+ SvLBoxTreeList* pTempModel = new SvLBoxTreeList;
+ pTempModel->SetRefCount( 0 );
+ SetModel( pTempModel );
+ pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
+ pModel->InsertView( this );
+ pHdlEntry = 0;
+ pEdCtrl = 0;
+ SetSelectionMode( SINGLE_SELECTION ); // pruefen ob TreeListBox gecallt wird
+ SetDragDropMode( SV_DRAGDROP_NONE );
+ SetType(WINDOW_TREELISTBOX);
+}
+
+SvLBox::SvLBox( Window* pParent, const ResId& rResId ) :
+ Control( pParent, rResId ),
+ DropTargetHelper( this ), DragSourceHelper( this ), eSelMode( NO_SELECTION )
+{
+ DBG_CTOR(SvLBox,0);
+ pTargetEntry = 0;
+ nImpFlags = 0;
+ nWindowStyle = 0;
+ pLBoxImpl = new SvLBox_Impl( *this );
+ nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
+ nDragDropMode = 0;
+ SvLBoxTreeList* pTempModel = new SvLBoxTreeList;
+ pTempModel->SetRefCount( 0 );
+ SetModel( pTempModel );
+ pModel->InsertView( this );
+ pHdlEntry = 0;
+ pEdCtrl = 0;
+ pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
+ SetType(WINDOW_TREELISTBOX);
+}
+
+__EXPORT SvLBox::~SvLBox()
+{
+ DBG_DTOR(SvLBox,0);
+ delete pEdCtrl;
+ pEdCtrl = 0;
+ pModel->RemoveView( this );
+ if ( pModel->GetRefCount() == 0 )
+ {
+ pModel->Clear();
+ delete pModel;
+ pModel = NULL;
+ }
+
+ SvLBox::RemoveBoxFromDDList_Impl( *this );
+
+ if( this == pDDSource )
+ pDDSource = 0;
+ if( this == pDDTarget )
+ pDDTarget = 0;
+ delete pLBoxImpl;
+}
+
+void SvLBox::SetModel( SvLBoxTreeList* pNewModel )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ // erledigt das ganz CleanUp
+ SvListView::SetModel( pNewModel );
+ pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
+ SvLBoxEntry* pEntry = First();
+ while( pEntry )
+ {
+ ModelHasInserted( pEntry );
+ pEntry = Next( pEntry );
+ }
+}
+
+void SvLBox::DisconnectFromModel()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ SvLBoxTreeList* pNewModel = new SvLBoxTreeList;
+ pNewModel->SetRefCount( 0 ); // else this will never be deleted
+ SvListView::SetModel( pNewModel );
+}
+
+void SvLBox::Clear()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ pModel->Clear(); // Model ruft SvLBox::ModelHasCleared() auf
+}
+
+void SvLBox::EnableEntryMnemonics( bool _bEnable )
+{
+ if ( _bEnable == IsEntryMnemonicsEnabled() )
+ return;
+
+ pLBoxImpl->m_bEntryMnemonicsEnabled = _bEnable;
+ Invalidate();
+}
+
+bool SvLBox::IsEntryMnemonicsEnabled() const
+{
+ return pLBoxImpl->m_bEntryMnemonicsEnabled;
+}
+
+USHORT SvLBox::IsA()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return SVLISTBOX_ID_LBOX;
+}
+
+IMPL_LINK_INLINE_START( SvLBox, CloneHdl_Impl, SvListEntry*, pEntry )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return (long)(CloneEntry((SvLBoxEntry*)pEntry));
+}
+IMPL_LINK_INLINE_END( SvLBox, CloneHdl_Impl, SvListEntry*, pEntry )
+
+ULONG SvLBox::Insert( SvLBoxEntry* pEntry, SvLBoxEntry* pParent, ULONG nPos )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ ULONG nInsPos = pModel->Insert( pEntry, pParent, nPos );
+ return nInsPos;
+}
+
+ULONG SvLBox::Insert( SvLBoxEntry* pEntry,ULONG nRootPos )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ ULONG nInsPos = pModel->Insert( pEntry, nRootPos );
+ return nInsPos;
+}
+
+long SvLBox::ExpandingHdl()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return aExpandingHdl.IsSet() ? aExpandingHdl.Call( this ) : 1;
+}
+
+void SvLBox::ExpandedHdl()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ aExpandedHdl.Call( this );
+}
+
+void SvLBox::SelectHdl()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ aSelectHdl.Call( this );
+}
+
+void SvLBox::DeselectHdl()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ aDeselectHdl.Call( this );
+}
+
+BOOL SvLBox::DoubleClickHdl()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ aDoubleClickHdl.Call( this );
+ return TRUE;
+}
+
+
+BOOL SvLBox::CheckDragAndDropMode( SvLBox* pSource, sal_Int8 nAction )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ if ( pSource == this )
+ {
+ if ( !(nDragDropMode & (SV_DRAGDROP_CTRL_MOVE | SV_DRAGDROP_CTRL_COPY) ) )
+ return FALSE; // D&D innerhalb der Liste gesperrt
+ if( DND_ACTION_MOVE == nAction )
+ {
+ if ( !(nDragDropMode & SV_DRAGDROP_CTRL_MOVE) )
+ return FALSE; // kein lokales Move
+ }
+ else
+ {
+ if ( !(nDragDropMode & SV_DRAGDROP_CTRL_COPY))
+ return FALSE; // kein lokales Copy
+ }
+ }
+ else
+ {
+ if ( !(nDragDropMode & SV_DRAGDROP_APP_DROP ) )
+ return FALSE; // kein Drop
+ if ( DND_ACTION_MOVE == nAction )
+ {
+ if ( !(nDragDropMode & SV_DRAGDROP_APP_MOVE) )
+ return FALSE; // kein globales Move
+ }
+ else
+ {
+ if ( !(nDragDropMode & SV_DRAGDROP_APP_COPY))
+ return FALSE; // kein globales Copy
+ }
+ }
+ return TRUE;
+}
+
+
+
+
+void SvLBox::NotifyRemoving( SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+/*
+ NotifyMoving/Copying
+ ====================
+
+ Standard-Verhalten:
+
+ 1. Target hat keine Childs
+ - Entry wird Sibling des Targets. Entry steht hinter dem
+ Target (->Fenster: Unter dem Target)
+ 2. Target ist ein aufgeklappter Parent
+ - Entry wird an den Anfang der Target-Childlist gehaengt
+ 3. Target ist ein zugeklappter Parent
+ - Entry wird an das Ende der Target-Childlist gehaengt
+*/
+#ifdef DBG_UTIL
+BOOL SvLBox::NotifyMoving(
+ SvLBoxEntry* pTarget, // D&D-Drop-Position in this->GetModel()
+ SvLBoxEntry* pEntry, // Zu verschiebender Entry aus
+ // GetSourceListBox()->GetModel()
+ SvLBoxEntry*& rpNewParent, // Neuer Target-Parent
+ ULONG& rNewChildPos) // Position in Childlist des Target-Parents
+#else
+BOOL SvLBox::NotifyMoving(
+ SvLBoxEntry* pTarget, // D&D-Drop-Position in this->GetModel()
+ SvLBoxEntry*, // Zu verschiebender Entry aus
+ // GetSourceListBox()->GetModel()
+ SvLBoxEntry*& rpNewParent, // Neuer Target-Parent
+ ULONG& rNewChildPos) // Position in Childlist des Target-Parents
+#endif
+{
+ DBG_CHKTHIS(SvLBox,0);
+ DBG_ASSERT(pEntry,"NotifyMoving:SoureEntry?");
+ if( !pTarget )
+ {
+ rpNewParent = 0;
+ rNewChildPos = 0;
+ return TRUE;
+ }
+ if ( !pTarget->HasChilds() && !pTarget->HasChildsOnDemand() )
+ {
+ // Fall 1
+ rpNewParent = GetParent( pTarget );
+ rNewChildPos = pModel->GetRelPos( pTarget ) + 1;
+ rNewChildPos += nCurEntrySelPos;
+ nCurEntrySelPos++;
+ }
+ else
+ {
+ // Faelle 2 & 3
+ rpNewParent = pTarget;
+ if( IsExpanded(pTarget))
+ rNewChildPos = 0;
+ else
+ rNewChildPos = LIST_APPEND;
+ }
+ return TRUE;
+}
+
+BOOL SvLBox::NotifyCopying(
+ SvLBoxEntry* pTarget, // D&D-Drop-Position in this->GetModel()
+ SvLBoxEntry* pEntry, // Zu kopierender Entry aus
+ // GetSourceListBox()->GetModel()
+ SvLBoxEntry*& rpNewParent, // Neuer Target-Parent
+ ULONG& rNewChildPos) // Position in Childlist des Target-Parents
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return NotifyMoving(pTarget,pEntry,rpNewParent,rNewChildPos);
+ /*
+ DBG_ASSERT(pEntry,"NotifyCopying:SourceEntry?");
+ if( !pTarget )
+ {
+ rpNewParent = 0;
+ rNewChildPos = 0;
+ return TRUE;
+ }
+ if ( !pTarget->HasChilds() && !pTarget->HasChildsOnDemand() )
+ {
+ // Fall 1
+ rpNewParent = GetParent( pTarget );
+ rNewChildPos = GetRelPos( pTarget ) + 1;
+ }
+ else
+ {
+ // Faelle 2 & 3
+ rpNewParent = pTarget;
+ if( IsExpanded(pTarget))
+ rNewChildPos = 0;
+ else
+ rNewChildPos = LIST_APPEND;
+ }
+ return TRUE;
+ */
+}
+
+SvLBoxEntry* SvLBox::CloneEntry( SvLBoxEntry* pSource )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ SvLBoxEntry* pEntry = (SvLBoxEntry*)CreateEntry(); // new SvLBoxEntry;
+ pEntry->Clone( (SvListEntry*)pSource );
+ return pEntry;
+}
+
+
+// Rueckgabe: Alle Entries wurden kopiert
+BOOL SvLBox::CopySelection( SvLBox* pSource, SvLBoxEntry* pTarget )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ nCurEntrySelPos = 0; // Selektionszaehler fuer NotifyMoving/Copying
+ BOOL bSuccess = TRUE;
+ SvTreeEntryList aList;
+ BOOL bClone = (BOOL)( (ULONG)(pSource->GetModel()) != (ULONG)GetModel() );
+ Link aCloneLink( pModel->GetCloneLink() );
+ pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
+
+ // Selektion zwischenspeichern, um bei D&D-Austausch
+ // innerhalb der gleichen Listbox das Iterieren ueber
+ // die Selektion zu vereinfachen
+ SvLBoxEntry* pSourceEntry = pSource->FirstSelected();
+ while ( pSourceEntry )
+ {
+ // Childs werden automatisch mitkopiert
+ pSource->SelectChilds( pSourceEntry, FALSE );
+ aList.Insert( pSourceEntry, LIST_APPEND );
+ pSourceEntry = pSource->NextSelected( pSourceEntry );
+ }
+
+ pSourceEntry = (SvLBoxEntry*)aList.First();
+ while ( pSourceEntry )
+ {
+ SvLBoxEntry* pNewParent = 0;
+ ULONG nInsertionPos = LIST_APPEND;
+ BOOL bOk=NotifyCopying(pTarget,pSourceEntry,pNewParent,nInsertionPos);
+ if ( bOk )
+ {
+ if ( bClone )
+ {
+ ULONG nCloneCount = 0;
+ pSourceEntry = (SvLBoxEntry*)
+ pModel->Clone( (SvListEntry*)pSourceEntry, nCloneCount );
+ pModel->InsertTree( (SvListEntry*)pSourceEntry,
+ (SvListEntry*)pNewParent, nInsertionPos );
+ }
+ else
+ {
+ ULONG nListPos = pModel->Copy( (SvListEntry*)pSourceEntry,
+ (SvListEntry*)pNewParent, nInsertionPos );
+ pSourceEntry = GetEntry( pNewParent, nListPos );
+ }
+ }
+ else
+ bSuccess = FALSE;
+
+ if( bOk == (BOOL)2 ) // !!!HACK verschobenen Entry sichtbar machen?
+ MakeVisible( pSourceEntry );
+
+ pSourceEntry = (SvLBoxEntry*)aList.Next();
+ }
+ pModel->SetCloneLink( aCloneLink );
+ return bSuccess;
+}
+
+// Rueckgabe: Alle Entries wurden verschoben
+BOOL SvLBox::MoveSelection( SvLBox* pSource, SvLBoxEntry* pTarget )
+{
+ return MoveSelectionCopyFallbackPossible( pSource, pTarget, sal_False );
+}
+
+BOOL SvLBox::MoveSelectionCopyFallbackPossible( SvLBox* pSource, SvLBoxEntry* pTarget, sal_Bool bAllowCopyFallback )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ nCurEntrySelPos = 0; // Selektionszaehler fuer NotifyMoving/Copying
+ BOOL bSuccess = TRUE;
+ SvTreeEntryList aList;
+ BOOL bClone = (BOOL)( (ULONG)(pSource->GetModel()) != (ULONG)GetModel() );
+ Link aCloneLink( pModel->GetCloneLink() );
+ if ( bClone )
+ pModel->SetCloneLink( LINK(this, SvLBox, CloneHdl_Impl ));
+
+ SvLBoxEntry* pSourceEntry = pSource->FirstSelected();
+ while ( pSourceEntry )
+ {
+ // Childs werden automatisch mitbewegt
+ pSource->SelectChilds( pSourceEntry, FALSE );
+ aList.Insert( pSourceEntry, LIST_APPEND );
+ pSourceEntry = pSource->NextSelected( pSourceEntry );
+ }
+
+ pSourceEntry = (SvLBoxEntry*)aList.First();
+ while ( pSourceEntry )
+ {
+ SvLBoxEntry* pNewParent = 0;
+ ULONG nInsertionPos = LIST_APPEND;
+ sal_Bool bOk = NotifyMoving(pTarget,pSourceEntry,pNewParent,nInsertionPos);
+ sal_Bool bCopyOk = bOk;
+ if ( !bOk && bAllowCopyFallback )
+ {
+ nInsertionPos = LIST_APPEND;
+ bCopyOk = NotifyCopying(pTarget,pSourceEntry,pNewParent,nInsertionPos);
+ }
+
+ if ( bOk || bCopyOk )
+ {
+ if ( bClone )
+ {
+ ULONG nCloneCount = 0;
+ pSourceEntry = (SvLBoxEntry*)
+ pModel->Clone( (SvListEntry*)pSourceEntry, nCloneCount );
+ pModel->InsertTree( (SvListEntry*)pSourceEntry,
+ (SvListEntry*)pNewParent, nInsertionPos );
+ }
+ else
+ {
+ if ( bOk )
+ pModel->Move( (SvListEntry*)pSourceEntry,
+ (SvListEntry*)pNewParent, nInsertionPos );
+ else
+ pModel->Copy( (SvListEntry*)pSourceEntry,
+ (SvListEntry*)pNewParent, nInsertionPos );
+ }
+ }
+ else
+ bSuccess = FALSE;
+
+ if( bOk == (BOOL)2 ) // !!!HACK verschobenen Entry sichtbar machen?
+ MakeVisible( pSourceEntry );
+
+ pSourceEntry = (SvLBoxEntry*)aList.Next();
+ }
+ pModel->SetCloneLink( aCloneLink );
+ return bSuccess;
+}
+
+void SvLBox::RemoveSelection()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ SvTreeEntryList aList;
+ // Selektion zwischenspeichern, da die Impl bei
+ // dem ersten Remove alles deselektiert!
+ SvLBoxEntry* pEntry = FirstSelected();
+ while ( pEntry )
+ {
+ aList.Insert( pEntry );
+ if ( pEntry->HasChilds() )
+ // Remove loescht Childs automatisch
+ SelectChilds( pEntry, FALSE );
+ pEntry = NextSelected( pEntry );
+ }
+ pEntry = (SvLBoxEntry*)aList.First();
+ while ( pEntry )
+ {
+ pModel->Remove( pEntry );
+ pEntry = (SvLBoxEntry*)aList.Next();
+ }
+}
+
+SvLBox* SvLBox::GetSourceView() const
+{
+ return pDDSource;
+}
+
+SvLBox* SvLBox::GetTargetView() const
+{
+ return pDDTarget;
+}
+
+void SvLBox::RequestingChilds( SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ DBG_ERROR("Child-Request-Hdl not implemented!");
+}
+
+void SvLBox::RecalcViewData()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ SvLBoxEntry* pEntry = First();
+ while( pEntry )
+ {
+ USHORT nCount = pEntry->ItemCount();
+ USHORT nCurPos = 0;
+ while ( nCurPos < nCount )
+ {
+ SvLBoxItem* pItem = pEntry->GetItem( nCurPos );
+ pItem->InitViewData( this, pEntry );
+ nCurPos++;
+ }
+ ViewDataInitialized( pEntry );
+ pEntry = Next( pEntry );
+ }
+}
+
+void SvLBox::ViewDataInitialized( SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+void SvLBox::StateChanged( StateChangedType eType )
+{
+ if( eType == STATE_CHANGE_ENABLE )
+ Invalidate( INVALIDATE_CHILDREN );
+ Control::StateChanged( eType );
+}
+
+void SvLBox::ImplShowTargetEmphasis( SvLBoxEntry* pEntry, BOOL bShow)
+{
+ DBG_CHKTHIS(SvLBox,0);
+ if ( bShow && (nImpFlags & SVLBOX_TARGEMPH_VIS) )
+ return;
+ if ( !bShow && !(nImpFlags & SVLBOX_TARGEMPH_VIS) )
+ return;
+ ShowTargetEmphasis( pEntry, bShow );
+ if( bShow )
+ nImpFlags |= SVLBOX_TARGEMPH_VIS;
+ else
+ nImpFlags &= ~SVLBOX_TARGEMPH_VIS;
+}
+
+void SvLBox::ShowTargetEmphasis( SvLBoxEntry*, BOOL /* bShow */ )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+
+BOOL SvLBox::Expand( SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return TRUE;
+}
+
+BOOL SvLBox::Collapse( SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return TRUE;
+}
+
+BOOL SvLBox::Select( SvLBoxEntry*, BOOL )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return FALSE;
+}
+
+ULONG SvLBox::SelectChilds( SvLBoxEntry* , BOOL )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return 0;
+}
+
+void SvLBox::SelectAll( BOOL /* bSelect */ , BOOL /* bPaint */ )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+SvLBoxEntry* SvLBox::GetEntryFromPath( const ::std::deque< sal_Int32 >& _rPath ) const
+{
+ DBG_CHKTHIS(SvLBox,0);
+
+ SvLBoxEntry* pEntry = NULL;
+ SvLBoxEntry* pParent = NULL;
+ for( ::std::deque< sal_Int32 >::const_iterator pItem = _rPath.begin(); pItem != _rPath.end(); ++pItem )
+ {
+ pEntry = GetEntry( pParent, *pItem );
+ if ( !pEntry )
+ break;
+ pParent = pEntry;
+ }
+
+ return pEntry;
+}
+
+void SvLBox::FillEntryPath( SvLBoxEntry* pEntry, ::std::deque< sal_Int32 >& _rPath ) const
+{
+ DBG_CHKTHIS(SvLBox,0);
+
+ if ( pEntry )
+ {
+ SvLBoxEntry* pParentEntry = GetParent( pEntry );
+ while ( TRUE )
+ {
+ ULONG i, nCount = GetLevelChildCount( pParentEntry );
+ for ( i = 0; i < nCount; ++i )
+ {
+ SvLBoxEntry* pTemp = GetEntry( pParentEntry, i );
+ DBG_ASSERT( pEntry, "invalid entry" );
+ if ( pEntry == pTemp )
+ {
+ _rPath.push_front( (sal_Int32)i );
+ break;
+ }
+ }
+
+ if ( pParentEntry )
+ {
+ pEntry = pParentEntry;
+ pParentEntry = GetParent( pParentEntry );
+ }
+ else
+ break;
+ }
+ }
+}
+
+String SvLBox::GetEntryText( SvLBoxEntry* ) const
+{
+ DBG_CHKTHIS(SvLBox,0);
+
+ return String();
+}
+
+ULONG SvLBox::GetLevelChildCount( SvLBoxEntry* _pParent ) const
+{
+ DBG_CHKTHIS(SvLBox,0);
+
+ ULONG nCount = 0;
+ SvLBoxEntry* pEntry = FirstChild( _pParent );
+ while ( pEntry )
+ {
+ ++nCount;
+ pEntry = NextSibling( pEntry );
+ }
+
+ return nCount;
+}
+
+void SvLBox::SetSelectionMode( SelectionMode eSelectMode )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ eSelMode = eSelectMode;
+}
+
+void SvLBox::SetDragDropMode( DragDropMode nDDMode )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ nDragDropMode = nDDMode;
+}
+
+SvViewData* SvLBox::CreateViewData( SvListEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ SvViewDataEntry* pEntryData = new SvViewDataEntry;
+ return (SvViewData*)pEntryData;
+}
+
+void SvLBox::InitViewData( SvViewData* pData, SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ SvLBoxEntry* pInhEntry = (SvLBoxEntry*)pEntry;
+ SvViewDataEntry* pEntryData = (SvViewDataEntry*)pData;
+
+ pEntryData->pItemData = new SvViewDataItem[ pInhEntry->ItemCount() ];
+ SvViewDataItem* pItemData = pEntryData->pItemData;
+ pEntryData->nItmCnt = pInhEntry->ItemCount(); // Anzahl Items fuer delete
+ USHORT nCount = pInhEntry->ItemCount();
+ USHORT nCurPos = 0;
+ while( nCurPos < nCount )
+ {
+ SvLBoxItem* pItem = pInhEntry->GetItem( nCurPos );
+ pItem->InitViewData( this, pInhEntry, pItemData );
+ pItemData++;
+ nCurPos++;
+ }
+}
+
+
+
+void SvLBox::EnableSelectionAsDropTarget( BOOL bEnable, BOOL bWithChilds )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ USHORT nRefDepth;
+ SvLBoxEntry* pTemp;
+
+ SvLBoxEntry* pSelEntry = FirstSelected();
+ while( pSelEntry )
+ {
+ if ( !bEnable )
+ {
+ pSelEntry->nEntryFlags |= SV_ENTRYFLAG_DISABLE_DROP;
+ if ( bWithChilds )
+ {
+ nRefDepth = pModel->GetDepth( pSelEntry );
+ pTemp = Next( pSelEntry );
+ while( pTemp && pModel->GetDepth( pTemp ) > nRefDepth )
+ {
+ pTemp->nEntryFlags |= SV_ENTRYFLAG_DISABLE_DROP;
+ pTemp = Next( pTemp );
+ }
+ }
+ }
+ else
+ {
+ pSelEntry->nEntryFlags &= (~SV_ENTRYFLAG_DISABLE_DROP);
+ if ( bWithChilds )
+ {
+ nRefDepth = pModel->GetDepth( pSelEntry );
+ pTemp = Next( pSelEntry );
+ while( pTemp && pModel->GetDepth( pTemp ) > nRefDepth )
+ {
+ pTemp->nEntryFlags &= (~SV_ENTRYFLAG_DISABLE_DROP);
+ pTemp = Next( pTemp );
+ }
+ }
+ }
+ pSelEntry = NextSelected( pSelEntry );
+ }
+}
+
+SvLBoxEntry* SvLBox::GetDropTarget( const Point& )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return 0;
+}
+
+// ******************************************************************
+// InplaceEditing
+// ******************************************************************
+
+void SvLBox::EditText( const String& rStr, const Rectangle& rRect,
+ const Selection& rSel )
+{
+ EditText( rStr, rRect, rSel, FALSE );
+}
+
+void SvLBox::EditText( const String& rStr, const Rectangle& rRect,
+ const Selection& rSel, BOOL bMulti )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ if( pEdCtrl )
+ delete pEdCtrl;
+ nImpFlags |= SVLBOX_IN_EDT;
+ nImpFlags &= ~SVLBOX_EDTEND_CALLED;
+ HideFocus();
+ pEdCtrl = new SvInplaceEdit2(
+ this, rRect.TopLeft(), rRect.GetSize(), rStr,
+ LINK( this, SvLBox, TextEditEndedHdl_Impl ),
+ rSel, bMulti );
+}
+
+IMPL_LINK( SvLBox, TextEditEndedHdl_Impl, SvInplaceEdit2 *, EMPTYARG )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ if ( nImpFlags & SVLBOX_EDTEND_CALLED ) // Nesting verhindern
+ return 0;
+ nImpFlags |= SVLBOX_EDTEND_CALLED;
+ String aStr;
+ if ( !pEdCtrl->EditingCanceled() )
+ aStr = pEdCtrl->GetText();
+ else
+ aStr = pEdCtrl->GetSavedValue();
+ if ( IsEmptyTextAllowed() || aStr.Len() > 0 )
+ EditedText( aStr );
+ // Hide darf erst gerufen werden, nachdem der neue Text in den
+ // Entry gesetzt wurde, damit im GetFocus der ListBox nicht
+ // der Selecthandler mit dem alten EntryText gerufen wird.
+ pEdCtrl->Hide();
+ // delete pEdCtrl;
+ // pEdCtrl = 0;
+ nImpFlags &= (~SVLBOX_IN_EDT);
+ GrabFocus();
+ return 0;
+}
+
+void SvLBox::CancelTextEditing()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ if ( pEdCtrl )
+ pEdCtrl->StopEditing( TRUE );
+ nImpFlags &= (~SVLBOX_IN_EDT);
+}
+
+void SvLBox::EndEditing( BOOL bCancel )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ if( pEdCtrl )
+ pEdCtrl->StopEditing( bCancel );
+ nImpFlags &= (~SVLBOX_IN_EDT);
+}
+
+
+bool SvLBox::IsEmptyTextAllowed() const
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return pLBoxImpl->m_bIsEmptyTextAllowed;
+}
+
+void SvLBox::ForbidEmptyText()
+{
+ DBG_CHKTHIS(SvLBox,0);
+ pLBoxImpl->m_bIsEmptyTextAllowed = false;
+}
+
+void SvLBox::EditedText( const String& )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+void SvLBox::EditingRequest( SvLBoxEntry*, SvLBoxItem*,const Point& )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+
+SvLBoxEntry* SvLBox::CreateEntry() const
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return new SvLBoxEntry;
+}
+
+void SvLBox::MakeVisible( SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+void SvLBox::Command( const CommandEvent& i_rCommandEvent )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ Control::Command( i_rCommandEvent );
+}
+
+void SvLBox::KeyInput( const KeyEvent& rKEvt )
+{
+ bool bHandled = HandleKeyInput( rKEvt );
+ if ( !bHandled )
+ Control::KeyInput( rKEvt );
+}
+
+const void* SvLBox::FirstSearchEntry( String& _rEntryText )
+{
+ SvLBoxEntry* pEntry = GetCurEntry();
+ if ( pEntry )
+ pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( NextSearchEntry( pEntry, _rEntryText ) ) );
+ else
+ {
+ if ( !pEntry )
+ pEntry = FirstSelected();
+ if ( !pEntry )
+ pEntry = First();
+ }
+
+ if ( pEntry )
+ _rEntryText = GetEntryText( pEntry );
+
+ return pEntry;
+}
+
+const void* SvLBox::NextSearchEntry( const void* _pCurrentSearchEntry, String& _rEntryText )
+{
+ SvLBoxEntry* pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( _pCurrentSearchEntry ) );
+
+ pEntry = Next( pEntry );
+ if ( !pEntry )
+ pEntry = First();
+
+ if ( pEntry )
+ _rEntryText = GetEntryText( pEntry );
+
+ return pEntry;
+}
+
+void SvLBox::SelectSearchEntry( const void* _pEntry )
+{
+ SvLBoxEntry* pEntry = const_cast< SvLBoxEntry* >( static_cast< const SvLBoxEntry* >( _pEntry ) );
+ DBG_ASSERT( pEntry, "SvLBox::SelectSearchEntry: invalid entry!" );
+ if ( pEntry )
+ return;
+
+ SelectAll( FALSE );
+ SetCurEntry( pEntry );
+ Select( pEntry );
+}
+
+void SvLBox::ExecuteSearchEntry( const void* /*_pEntry*/ )
+{
+ // nothing to do here, we have no "execution"
+}
+
+bool SvLBox::HandleKeyInput( const KeyEvent& _rKEvt )
+{
+ if ( !IsEntryMnemonicsEnabled() )
+ return false;
+
+ return pLBoxImpl->m_aMnemonicEngine.HandleKeyEvent( _rKEvt );
+}
+
+SvLBoxEntry* SvLBox::GetEntry( const Point&, BOOL ) const
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return 0;
+}
+
+void SvLBox::ModelHasEntryInvalidated( SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ USHORT nCount = ((SvLBoxEntry*)pEntry)->ItemCount();
+ for( USHORT nIdx = 0; nIdx < nCount; nIdx++ )
+ {
+ SvLBoxItem* pItem = ((SvLBoxEntry*)pEntry)->GetItem( nIdx );
+ pItem->InitViewData( this, (SvLBoxEntry*)pEntry, 0 );
+ }
+}
+
+void SvLBox::SetInUseEmphasis( SvLBoxEntry* pEntry, BOOL bInUse )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
+ if( bInUse )
+ {
+ if( !pEntry->HasInUseEmphasis() )
+ {
+ pEntry->nEntryFlags |= SV_ENTRYFLAG_IN_USE;
+ pModel->InvalidateEntry( pEntry );
+ }
+ }
+ else
+ {
+ if( pEntry->HasInUseEmphasis() )
+ {
+ pEntry->nEntryFlags &= (~SV_ENTRYFLAG_IN_USE);
+ pModel->InvalidateEntry( pEntry );
+ }
+ }
+}
+
+void SvLBox::SetCursorEmphasis( SvLBoxEntry* pEntry, BOOL bCursored )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
+ SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
+ if( pViewData && (bCursored != pViewData->IsCursored()) )
+ {
+ pViewData->SetCursored( bCursored );
+ // paintet in allen Views
+ // pModel->InvalidateEntry( pEntry );
+ // invalidiert nur in dieser View
+ ModelHasEntryInvalidated( pEntry );
+ }
+}
+
+BOOL SvLBox::HasCursorEmphasis( SvLBoxEntry* pEntry ) const
+{
+ DBG_CHKTHIS(SvLBox,0);
+ DBG_ASSERT(pEntry,"SetInUseEmphasis:No Entry");
+ SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
+ DBG_ASSERT(pViewData,"Entry not in View");
+ return pViewData->IsCursored();
+}
+
+void SvLBox::WriteDragServerInfo( const Point&, SvLBoxDDInfo* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+void SvLBox::ReadDragServerInfo(const Point&, SvLBoxDDInfo* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+}
+
+BOOL SvLBox::EditingCanceled() const
+{
+ if( pEdCtrl && pEdCtrl->EditingCanceled() )
+ return TRUE;
+ return FALSE;
+}
+
+
+//JP 28.3.2001: new Drag & Drop API
+sal_Int8 SvLBox::AcceptDrop( const AcceptDropEvent& rEvt )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ sal_Int8 nRet = DND_ACTION_NONE;
+
+ if( rEvt.mbLeaving || !CheckDragAndDropMode( pDDSource, rEvt.mnAction ) )
+ {
+ ImplShowTargetEmphasis( pTargetEntry, FALSE );
+ }
+ else if( !nDragDropMode )
+ {
+ DBG_ERRORFILE( "SvLBox::QueryDrop(): no target" );
+ }
+ else
+ {
+ SvLBoxEntry* pEntry = GetDropTarget( rEvt.maPosPixel );
+ if( !IsDropFormatSupported( SOT_FORMATSTR_ID_TREELISTBOX ) )
+ {
+ DBG_ERRORFILE( "SvLBox::QueryDrop(): no format" );
+ }
+ else
+ {
+ DBG_ASSERT( pDDSource, "SvLBox::QueryDrop(): SourceBox == 0 (__EXPORT?)" );
+ if( !( pEntry && pDDSource->GetModel() == this->GetModel()
+ && DND_ACTION_MOVE == rEvt.mnAction
+ && ( pEntry->nEntryFlags & SV_ENTRYFLAG_DISABLE_DROP ) ))
+ {
+ if( NotifyAcceptDrop( pEntry ))
+ nRet = rEvt.mnAction;
+ }
+ }
+
+ // **** Emphasis zeichnen ****
+ if( DND_ACTION_NONE == nRet )
+ ImplShowTargetEmphasis( pTargetEntry, FALSE );
+ else if( pEntry != pTargetEntry || !(nImpFlags & SVLBOX_TARGEMPH_VIS) )
+ {
+ ImplShowTargetEmphasis( pTargetEntry, FALSE );
+ pTargetEntry = pEntry;
+ ImplShowTargetEmphasis( pTargetEntry, TRUE );
+ }
+ }
+ return nRet;
+}
+
+sal_Int8 SvLBox::ExecuteDrop( const ExecuteDropEvent& rEvt, SvLBox* pSourceView )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ sal_Int8 nRet = DND_ACTION_NONE;
+
+ DBG_ASSERT( pSourceView, "SvLBox::ExecuteDrop(): no source view" );
+ pSourceView->EnableSelectionAsDropTarget( TRUE, TRUE );
+
+ ImplShowTargetEmphasis( pTargetEntry, FALSE );
+ pDDTarget = this;
+
+ SvLBoxDDInfo aDDInfo;
+
+ TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
+ if( aData.HasFormat( SOT_FORMATSTR_ID_TREELISTBOX ))
+ {
+ ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
+ if( aData.GetSequence( SOT_FORMATSTR_ID_TREELISTBOX, aSeq ) &&
+ sizeof(SvLBoxDDInfo) == aSeq.getLength() )
+ {
+ memcpy( &aDDInfo, aSeq.getConstArray(), sizeof(SvLBoxDDInfo) );
+ nRet = rEvt.mnAction;
+ }
+ }
+
+ if( DND_ACTION_NONE != nRet )
+ {
+ nRet = DND_ACTION_NONE;
+
+ ReadDragServerInfo( rEvt.maPosPixel, &aDDInfo );
+
+ SvLBoxEntry* pTarget = pTargetEntry; // !!! kann 0 sein !!!
+
+ if( DND_ACTION_COPY == rEvt.mnAction )
+ {
+ if ( CopySelection( aDDInfo.pSource, pTarget ) )
+ nRet = rEvt.mnAction;
+ }
+ else if( DND_ACTION_MOVE == rEvt.mnAction )
+ {
+ if ( MoveSelection( aDDInfo.pSource, pTarget ) )
+ nRet = rEvt.mnAction;
+ }
+ else if( DND_ACTION_COPYMOVE == rEvt.mnAction )
+ {
+ if ( MoveSelectionCopyFallbackPossible( aDDInfo.pSource, pTarget, sal_True ) )
+ nRet = rEvt.mnAction;
+ }
+ }
+ return nRet;
+}
+
+sal_Int8 SvLBox::ExecuteDrop( const ExecuteDropEvent& rEvt )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return ExecuteDrop( rEvt, GetSourceView() );
+}
+
+void SvLBox::StartDrag( sal_Int8, const Point& rPosPixel )
+{
+ DBG_CHKTHIS(SvLBox,0);
+
+ nOldDragMode = GetDragDropMode();
+ if ( !nOldDragMode )
+ return;
+
+ ReleaseMouse();
+
+ SvLBoxEntry* pEntry = GetEntry( rPosPixel ); // GetDropTarget( rPos );
+ if( !pEntry )
+ {
+ DragFinished( DND_ACTION_NONE );
+ return;
+ }
+
+ TransferDataContainer* pContainer = new TransferDataContainer;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::datatransfer::XTransferable > xRef( pContainer );
+
+ nDragDropMode = NotifyStartDrag( *pContainer, pEntry );
+ if( !nDragDropMode || 0 == GetSelectionCount() )
+ {
+ nDragDropMode = nOldDragMode;
+ DragFinished( DND_ACTION_NONE );
+ return;
+ }
+
+ SvLBoxDDInfo aDDInfo;
+ memset(&aDDInfo,0,sizeof(SvLBoxDDInfo));
+ aDDInfo.pApp = GetpApp();
+ aDDInfo.pSource = this;
+ aDDInfo.pDDStartEntry = pEntry;
+ // abgeleitete Views zum Zuge kommen lassen
+ WriteDragServerInfo( rPosPixel, &aDDInfo );
+
+ pContainer->CopyAnyData( SOT_FORMATSTR_ID_TREELISTBOX,
+ (sal_Char*)&aDDInfo, sizeof(SvLBoxDDInfo) );
+ pDDSource = this;
+ pDDTarget = 0;
+
+ BOOL bOldUpdateMode = Control::IsUpdateMode();
+ Control::SetUpdateMode( TRUE );
+ Update();
+ Control::SetUpdateMode( bOldUpdateMode );
+
+ // Selektion & deren Childs im Model als DropTargets sperren
+ // Wichtig: Wenn im DropHandler die Selektion der
+ // SourceListBox veraendert wird, muessen vorher die Eintraege
+ // als DropTargets wieder freigeschaltet werden:
+ // (GetSourceListBox()->EnableSelectionAsDropTarget( TRUE, TRUE );)
+ EnableSelectionAsDropTarget( FALSE, TRUE /* with Childs */ );
+
+ pContainer->StartDrag( this, nDragOptions, GetDragFinishedHdl() );
+}
+
+void SvLBox::DragFinished( sal_Int8
+#ifndef UNX
+nAction
+#endif
+)
+{
+ EnableSelectionAsDropTarget( TRUE, TRUE );
+
+#ifndef UNX
+ if( (nAction == DND_ACTION_MOVE) && ( (pDDTarget &&
+ ((ULONG)(pDDTarget->GetModel())!=(ULONG)(this->GetModel()))) ||
+ !pDDTarget ))
+ {
+ RemoveSelection();
+ }
+#endif
+
+ ImplShowTargetEmphasis( pTargetEntry, FALSE );
+ pDDSource = 0;
+ pDDTarget = 0;
+ pTargetEntry = 0;
+ nDragDropMode = nOldDragMode;
+}
+
+DragDropMode SvLBox::NotifyStartDrag( TransferDataContainer&, SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return (DragDropMode)0xffff;
+}
+
+BOOL SvLBox::NotifyAcceptDrop( SvLBoxEntry* )
+{
+ DBG_CHKTHIS(SvLBox,0);
+ return TRUE;
+}
+
+// handler and methods for Drag - finished handler.
+// The with get GetDragFinishedHdl() get link can set on the
+// TransferDataContainer. This link is a callback for the DragFinished
+// call. AddBox method is called from the GetDragFinishedHdl() and the
+// remove is called in link callback and in the destructor. So it can't
+// called to a deleted object.
+
+namespace
+{
+ struct SortLBoxes : public rtl::Static<SvULongsSort, SortLBoxes> {};
+}
+
+void SvLBox::AddBoxToDDList_Impl( const SvLBox& rB )
+{
+ ULONG nVal = (ULONG)&rB;
+ SortLBoxes::get().Insert( nVal );
+}
+
+void SvLBox::RemoveBoxFromDDList_Impl( const SvLBox& rB )
+{
+ ULONG nVal = (ULONG)&rB;
+ SortLBoxes::get().Remove( nVal );
+}
+
+IMPL_STATIC_LINK( SvLBox, DragFinishHdl_Impl, sal_Int8*, pAction )
+{
+ ULONG nVal = (ULONG)pThis;
+ USHORT nFnd;
+ SvULongsSort &rSortLBoxes = SortLBoxes::get();
+ if( rSortLBoxes.Seek_Entry( nVal, &nFnd ) )
+ {
+ pThis->DragFinished( *pAction );
+ rSortLBoxes.Remove( nFnd, 1 );
+ }
+ return 0;
+}
+
+Link SvLBox::GetDragFinishedHdl() const
+{
+ AddBoxToDDList_Impl( *this );
+ return STATIC_LINK( this, SvLBox, DragFinishHdl_Impl );
+}
+
+void SvLBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& ) const
+{
+}
+
+::com::sun::star::uno::Reference< XAccessible > SvLBox::CreateAccessible()
+{
+ return ::com::sun::star::uno::Reference< XAccessible >();
+}
+
+Rectangle SvLBox::GetBoundingRect( SvLBoxEntry* )
+{
+ return Rectangle();
+}
+
diff --git a/svtools/source/contnr/svtabbx.cxx b/svtools/source/contnr/svtabbx.cxx
new file mode 100644
index 000000000000..53fbded59f11
--- /dev/null
+++ b/svtools/source/contnr/svtabbx.cxx
@@ -0,0 +1,1304 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svtools.hxx"
+#include <svtools/svtabbx.hxx>
+#include <svtools/headbar.hxx>
+#include <svtools/svtdata.hxx>
+#ifndef _SVTOOLS_HRC
+#include <svtools/svtools.hrc>
+#endif
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#ifndef SVTOOLS_ACCESSIBLE_FACTORY_HXX
+#include "svtaccessiblefactory.hxx"
+#endif
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+
+#define MYTABMASK \
+ ( SV_LBOXTAB_ADJUST_RIGHT | SV_LBOXTAB_ADJUST_LEFT | SV_LBOXTAB_ADJUST_CENTER | SV_LBOXTAB_ADJUST_NUMERIC )
+
+// SvTreeListBox-Callback
+
+void SvTabListBox::SetTabs()
+{
+ SvTreeListBox::SetTabs();
+ if( nTabCount )
+ {
+ DBG_ASSERT(pTabList,"TabList ?");
+
+ // die TreeListBox hat jetzt ihre Tabulatoren in die Liste eingefuegt.
+ // jetzt plustern wir die Liste mit zusaetzlichen Tabulatoren auf,
+ // und passen den ganz rechten Tab der Treelistbox an.
+
+ // den ganz rechten Tab nehmen
+ // HACK fuer den Explorer! Wenn der ViewParent != 0 ist, dann wird
+ // der erste Tab der TreeListBox von der TreelistBox berechnet!
+ // Dies wird fuer ButtonsOnRoot benoetigt, da der Explorer nicht
+ // weiss, welchen zusaetzlichen Offset er in diesem Modus auf
+ // den Tabulator addieren muss. Die TreeListBox weiss es!
+ /*
+ if( !pViewParent )
+ {
+ SvLBoxTab* pFirstTab = (SvLBoxTab*)aTabs.GetObject( aTabs.Count()-1 );
+ pFirstTab->SetPos( pTabList[0].GetPos() );
+ pFirstTab->nFlags &= ~MYTABMASK;
+ pFirstTab->nFlags |= pTabList[0].nFlags;
+ }
+ */
+
+ // alle anderen Tabs an Liste haengen
+ for( USHORT nCurTab = 1; nCurTab < nTabCount; nCurTab++ )
+ {
+ SvLBoxTab* pTab = pTabList+nCurTab;
+ AddTab( pTab->GetPos(), pTab->nFlags );
+ }
+ }
+}
+
+void SvTabListBox::InitEntry( SvLBoxEntry* pEntry, const XubString& rStr,
+ const Image& rColl, const Image& rExp, SvLBoxButtonKind eButtonKind )
+{
+ SvTreeListBox::InitEntry( pEntry, rStr, rColl, rExp, eButtonKind );
+ XubString aToken;
+
+ const xub_Unicode* pCurToken = aCurEntry.GetBuffer();
+ USHORT nCurTokenLen;
+ const xub_Unicode* pNextToken = GetToken( pCurToken, nCurTokenLen );
+ USHORT nCount = nTabCount; nCount--;
+ for( USHORT nToken = 0; nToken < nCount; nToken++ )
+ {
+ if( pCurToken && nCurTokenLen )
+ // aToken.Assign( pCurToken, nCurTokenLen );
+ aToken = XubString( pCurToken, nCurTokenLen );
+ else
+ aToken.Erase();
+ SvLBoxString* pStr = new SvLBoxString( pEntry, 0, aToken );
+ pEntry->AddItem( pStr );
+ pCurToken = pNextToken;
+ if( pCurToken )
+ pNextToken = GetToken( pCurToken, nCurTokenLen );
+ else
+ nCurTokenLen = 0;
+ }
+}
+
+
+SvTabListBox::SvTabListBox( Window* pParent, WinBits nBits )
+ : SvTreeListBox( pParent, nBits )
+{
+ pTabList = 0;
+ nTabCount = 0;
+ pViewParent = 0;
+ SetHighlightRange(); // ueber volle Breite selektieren
+}
+
+SvTabListBox::SvTabListBox( Window* pParent, const ResId& rResId )
+ : SvTreeListBox( pParent, rResId )
+{
+ pTabList = 0;
+ nTabCount = 0;
+ pViewParent = 0;
+ SvTabListBox::Resize();
+ SetHighlightRange();
+}
+
+SvTabListBox::~SvTabListBox()
+{
+ // array-delete
+ delete [] pTabList;
+#ifdef DBG_UTIL
+ pTabList = 0;
+ nTabCount = 0;
+#endif
+}
+
+void SvTabListBox::SetTabs( long* pTabs, MapUnit eMapUnit )
+{
+ DBG_ASSERT(pTabs,"SetTabs:NULL-Ptr");
+ if( !pTabs )
+ return;
+
+ delete [] pTabList;
+ USHORT nCount = (USHORT)(*pTabs);
+ pTabList = new SvLBoxTab[ nCount ];
+ nTabCount = nCount;
+
+ MapMode aMMSource( eMapUnit );
+ MapMode aMMDest( MAP_PIXEL );
+
+ pTabs++;
+ for( USHORT nIdx = 0; nIdx < nCount; nIdx++, pTabs++ )
+ {
+ Size aSize( *pTabs, 0 );
+ aSize = LogicToLogic( aSize, &aMMSource, &aMMDest );
+ long nNewTab = aSize.Width();
+ pTabList[nIdx].SetPos( nNewTab );
+ pTabList[nIdx].nFlags=(SV_LBOXTAB_ADJUST_LEFT| SV_LBOXTAB_INV_ALWAYS);
+ }
+ SvTreeListBox::nTreeFlags |= TREEFLAG_RECALCTABS;
+ if( IsUpdateMode() )
+ Invalidate();
+}
+
+void SvTabListBox::SetTab( USHORT nTab,long nValue,MapUnit eMapUnit )
+{
+ DBG_ASSERT(nTab<nTabCount,"Invalid Tab-Pos");
+ if( nTab < nTabCount )
+ {
+ DBG_ASSERT(pTabList,"TabList?");
+ MapMode aMMSource( eMapUnit );
+ MapMode aMMDest( MAP_PIXEL );
+ Size aSize( nValue, 0 );
+ aSize = LogicToLogic( aSize, &aMMSource, &aMMDest );
+ nValue = aSize.Width();
+ pTabList[ nTab ].SetPos( nValue );
+ SvTreeListBox::nTreeFlags |= TREEFLAG_RECALCTABS;
+ if( IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+SvLBoxEntry* SvTabListBox::InsertEntry( const XubString& rText, SvLBoxEntry* pParent,
+ BOOL /*bChildsOnDemand*/,
+ ULONG nPos, void* pUserData,
+ SvLBoxButtonKind )
+{
+ return InsertEntryToColumn( rText, pParent, nPos, 0xffff, pUserData );
+}
+
+SvLBoxEntry* SvTabListBox::InsertEntry( const XubString& rText,
+ const Image& rExpandedEntryBmp,
+ const Image& rCollapsedEntryBmp,
+ SvLBoxEntry* pParent,
+ BOOL /*bChildsOnDemand*/,
+ ULONG nPos, void* pUserData,
+ SvLBoxButtonKind )
+{
+ return InsertEntryToColumn( rText, rExpandedEntryBmp, rCollapsedEntryBmp,
+ pParent, nPos, 0xffff, pUserData );
+}
+
+SvLBoxEntry* SvTabListBox::InsertEntryToColumn(const XubString& rStr,SvLBoxEntry* pParent,ULONG nPos,USHORT nCol,
+ void* pUser )
+{
+ XubString aStr;
+ if( nCol != 0xffff )
+ {
+ while( nCol )
+ {
+ aStr += '\t';
+ nCol--;
+ }
+ }
+ aStr += rStr;
+ XubString aFirstStr( aStr );
+ USHORT nEnd = aFirstStr.Search( '\t' );
+ if( nEnd != STRING_NOTFOUND )
+ {
+ aFirstStr.Erase( nEnd );
+ aCurEntry = aStr;
+ aCurEntry.Erase( 0, ++nEnd );
+ }
+ else
+ aCurEntry.Erase();
+ return SvTreeListBox::InsertEntry( aFirstStr, pParent, FALSE, nPos, pUser );
+}
+
+SvLBoxEntry* SvTabListBox::InsertEntryToColumn( const XubString& rStr,
+ const Image& rExpandedEntryBmp, const Image& rCollapsedEntryBmp,
+ SvLBoxEntry* pParent,ULONG nPos,USHORT nCol, void* pUser )
+{
+ XubString aStr;
+ if( nCol != 0xffff )
+ {
+ while( nCol )
+ {
+ aStr += '\t';
+ nCol--;
+ }
+ }
+ aStr += rStr;
+ XubString aFirstStr( aStr );
+ USHORT nEnd = aFirstStr.Search( '\t' );
+ if( nEnd != STRING_NOTFOUND )
+ {
+ aFirstStr.Erase( nEnd );
+ aCurEntry = aStr;
+ aCurEntry.Erase( 0, ++nEnd );
+ }
+ else
+ aCurEntry.Erase();
+
+ return SvTreeListBox::InsertEntry(
+ aFirstStr,
+ rExpandedEntryBmp, rCollapsedEntryBmp,
+ pParent, FALSE, nPos, pUser );
+}
+
+SvLBoxEntry* SvTabListBox::InsertEntryToColumn( const XubString& rStr, ULONG nPos,
+ USHORT nCol, void* pUser )
+{
+ return InsertEntryToColumn( rStr,0,nPos, nCol, pUser );
+}
+
+String SvTabListBox::GetEntryText( SvLBoxEntry* pEntry ) const
+{
+ return GetEntryText( pEntry, 0xffff );
+}
+
+String SvTabListBox::GetEntryText( SvLBoxEntry* pEntry, USHORT nCol ) const
+{
+ DBG_ASSERT(pEntry,"GetEntryText:Invalid Entry");
+ XubString aResult;
+ if( pEntry )
+ {
+ USHORT nCount = pEntry->ItemCount();
+ USHORT nCur = 0;
+ while( nCur < nCount )
+ {
+ SvLBoxItem* pStr = pEntry->GetItem( nCur );
+ if( pStr->IsA() == SV_ITEM_ID_LBOXSTRING )
+ {
+ if( nCol == 0xffff )
+ {
+ if( aResult.Len() )
+ aResult += '\t';
+ aResult += static_cast<SvLBoxString*>( pStr )->GetText();
+ }
+ else
+ {
+ if( nCol == 0 )
+ return static_cast<SvLBoxString*>( pStr )->GetText();
+ nCol--;
+ }
+ }
+ nCur++;
+ }
+ }
+ return aResult;
+}
+
+String SvTabListBox::GetEntryText( ULONG nPos, USHORT nCol ) const
+{
+ SvLBoxEntry* pEntry = GetEntryOnPos( nPos );
+ return GetEntryText( pEntry, nCol );
+}
+
+void SvTabListBox::SetEntryText( const XubString& rStr, ULONG nPos, USHORT nCol )
+{
+ SvLBoxEntry* pEntry = SvTreeListBox::GetEntry( nPos );
+ SetEntryText( rStr, pEntry, nCol );
+}
+
+void SvTabListBox::SetEntryText( const XubString& rStr, SvLBoxEntry* pEntry, USHORT nCol )
+{
+ DBG_ASSERT(pEntry,"SetEntryText:Invalid Entry");
+ if( !pEntry )
+ return;
+
+ String sOldText = GetEntryText( pEntry, nCol );
+ if ( sOldText == rStr )
+ return;
+
+ USHORT nTextColumn = nCol;
+ const xub_Unicode* pCurToken = rStr.GetBuffer();
+ USHORT nCurTokenLen;
+ const xub_Unicode* pNextToken = GetToken( pCurToken, nCurTokenLen );
+
+ XubString aTemp;
+ USHORT nCount = pEntry->ItemCount();
+ USHORT nCur = 0;
+ while( nCur < nCount )
+ {
+ SvLBoxItem* pStr = pEntry->GetItem( nCur );
+ if( pStr && pStr->IsA() == SV_ITEM_ID_LBOXSTRING )
+ {
+ if( nCol == 0xffff )
+ {
+ if( pCurToken )
+ aTemp = XubString( pCurToken, nCurTokenLen );
+ else
+ aTemp.Erase(); // alle Spalten ohne Token loeschen
+ ((SvLBoxString*)pStr)->SetText( pEntry, aTemp );
+ pCurToken = pNextToken;
+ pNextToken = GetToken( pCurToken, nCurTokenLen );
+ }
+ else
+ {
+ if( !nCol )
+ {
+ aTemp = XubString( pCurToken, nCurTokenLen );
+ ((SvLBoxString*)pStr)->SetText( pEntry, aTemp );
+ if( !pNextToken )
+ break;
+ pCurToken = pNextToken;
+ pNextToken = GetToken( pCurToken, nCurTokenLen );
+ }
+ else
+ nCol--;
+ }
+ }
+ nCur++;
+ }
+ GetModel()->InvalidateEntry( pEntry );
+
+ TabListBoxEventData* pData = new TabListBoxEventData( pEntry, nTextColumn, sOldText );
+ ImplCallEventListeners( VCLEVENT_TABLECELL_NAMECHANGED, pData );
+ delete pData;
+}
+
+String SvTabListBox::GetCellText( ULONG nPos, USHORT nCol ) const
+{
+ SvLBoxEntry* pEntry = GetEntryOnPos( nPos );
+ DBG_ASSERT( pEntry, "SvTabListBox::GetCellText(): Invalid Entry" );
+ XubString aResult;
+ if ( pEntry && pEntry->ItemCount() > ( nCol + 1 ) )
+ {
+ SvLBoxItem* pStr = pEntry->GetItem( nCol + 1 );
+ if ( pStr && pStr->IsA() == SV_ITEM_ID_LBOXSTRING )
+ aResult = static_cast< SvLBoxString* >( pStr )->GetText();
+ }
+ return aResult;
+}
+
+ULONG SvTabListBox::GetEntryPos( const XubString& rStr, USHORT nCol )
+{
+ ULONG nPos = 0;
+ SvLBoxEntry* pEntry = First();
+ while( pEntry )
+ {
+ XubString aStr( GetEntryText( pEntry, nCol ));
+ if( aStr == rStr )
+ return nPos;
+ pEntry = Next( pEntry );
+ nPos++;
+ }
+ return 0xffffffff;
+}
+
+ULONG SvTabListBox::GetEntryPos( const SvLBoxEntry* pEntry ) const
+{
+ ULONG nPos = 0;
+ SvLBoxEntry* pTmpEntry = First();
+ while( pTmpEntry )
+ {
+ if ( pTmpEntry == pEntry )
+ return nPos;
+ pTmpEntry = Next( pTmpEntry );
+ ++nPos;
+ }
+ return 0xffffffff;
+}
+
+void __EXPORT SvTabListBox::Resize()
+{
+ SvTreeListBox::Resize();
+}
+
+// static
+const xub_Unicode* SvTabListBox::GetToken( const xub_Unicode* pPtr, USHORT& rLen )
+{
+ if( !pPtr || *pPtr == 0 )
+ {
+ rLen = 0;
+ return 0;
+ }
+ xub_Unicode c = *pPtr;
+ USHORT nLen = 0;
+ while( c != '\t' && c != 0 )
+ {
+ pPtr++;
+ nLen++;
+ c = *pPtr;
+ }
+ if( c )
+ pPtr++; // Tab ueberspringen
+ else
+ pPtr = 0;
+ rLen = nLen;
+ return pPtr;
+}
+
+String SvTabListBox::GetTabEntryText( ULONG nPos, USHORT nCol ) const
+{
+ SvLBoxEntry* pEntry = SvTreeListBox::GetEntry( nPos );
+ DBG_ASSERT( pEntry, "GetTabEntryText(): Invalid entry " );
+ XubString aResult;
+ if ( pEntry )
+ {
+ USHORT nCount = pEntry->ItemCount();
+ USHORT nCur = ( 0 == nCol && IsCellFocusEnabled() ) ? GetCurrentTabPos() : 0;
+ while( nCur < nCount )
+ {
+ SvLBoxItem* pStr = pEntry->GetItem( nCur );
+ if ( pStr->IsA() == SV_ITEM_ID_LBOXSTRING )
+ {
+ if ( nCol == 0xffff )
+ {
+ if ( aResult.Len() )
+ aResult += '\t';
+ aResult += static_cast<SvLBoxString*>( pStr )->GetText();
+ }
+ else
+ {
+ if ( nCol == 0 )
+ {
+ String sRet = static_cast<SvLBoxString*>( pStr )->GetText();
+ if ( sRet.Len() == 0 )
+ sRet = String( SvtResId( STR_SVT_ACC_EMPTY_FIELD ) );
+ return sRet;
+ }
+ --nCol;
+ }
+ }
+ ++nCur;
+ }
+ }
+ return aResult;
+}
+
+SvLBoxEntry* SvTabListBox::GetEntryOnPos( ULONG _nEntryPos ) const
+{
+ SvLBoxEntry* pEntry = NULL;
+ ULONG i, nPos = 0, nCount = GetLevelChildCount( NULL );
+ for ( i = 0; i < nCount; ++i )
+ {
+ SvLBoxEntry* pParent = GetEntry(i);
+ if ( nPos == _nEntryPos )
+ {
+ pEntry = pParent;
+ break;
+ }
+ else
+ {
+ nPos++;
+ pEntry = GetChildOnPos( pParent, _nEntryPos, nPos );
+ if ( pEntry )
+ break;
+ }
+ }
+
+ return pEntry;
+}
+
+SvLBoxEntry* SvTabListBox::GetChildOnPos( SvLBoxEntry* _pParent, ULONG _nEntryPos, ULONG& _rPos ) const
+{
+ ULONG i, nCount = GetLevelChildCount( _pParent );
+ for ( i = 0; i < nCount; ++i )
+ {
+ SvLBoxEntry* pParent = GetEntry( _pParent, i );
+ if ( _rPos == _nEntryPos )
+ return pParent;
+ else
+ {
+ _rPos++;
+ SvLBoxEntry* pEntry = GetChildOnPos( pParent, _nEntryPos, _rPos );
+ if ( pEntry )
+ return pEntry;
+ }
+ }
+
+ return NULL;
+}
+
+void SvTabListBox::SetTabJustify( USHORT nTab, SvTabJustify eJustify)
+{
+ if( nTab >= nTabCount )
+ return;
+ SvLBoxTab* pTab = &(pTabList[ nTab ]);
+ USHORT nFlags = pTab->nFlags;
+ nFlags &= (~MYTABMASK);
+ nFlags |= (USHORT)eJustify;
+ pTab->nFlags = nFlags;
+ SvTreeListBox::nTreeFlags |= TREEFLAG_RECALCTABS;
+ if( IsUpdateMode() )
+ Invalidate();
+}
+
+SvTabJustify SvTabListBox::GetTabJustify( USHORT nTab ) const
+{
+ SvTabJustify eResult = AdjustLeft;
+ if( nTab >= nTabCount )
+ return eResult;
+ SvLBoxTab* pTab = &(pTabList[ nTab ]);
+ USHORT nFlags = pTab->nFlags;
+ nFlags &= MYTABMASK;
+ eResult = (SvTabJustify)nFlags;
+ return eResult;
+}
+
+long SvTabListBox::GetLogicTab( USHORT nTab )
+{
+ if( SvTreeListBox::nTreeFlags & TREEFLAG_RECALCTABS )
+ ((SvTabListBox*)this)->SetTabs();
+
+ DBG_ASSERT(nTab<nTabCount,"GetTabPos:Invalid Tab");
+ return ((SvLBoxTab*)aTabs.GetObject( nTab ))->GetPos();
+}
+
+// class SvHeaderTabListBoxImpl ------------------------------------------
+
+namespace svt
+{
+ struct SvHeaderTabListBoxImpl
+ {
+ HeaderBar* m_pHeaderBar;
+ AccessibleFactoryAccess m_aFactoryAccess;
+
+ SvHeaderTabListBoxImpl() : m_pHeaderBar( NULL ) { }
+ };
+}
+
+// class SvHeaderTabListBox ----------------------------------------------
+
+SvHeaderTabListBox::SvHeaderTabListBox( Window* pParent, WinBits nWinStyle ) :
+
+ SvTabListBox( pParent, nWinStyle ),
+
+ m_bFirstPaint ( TRUE ),
+ m_pImpl ( new ::svt::SvHeaderTabListBoxImpl ),
+ m_pAccessible ( NULL )
+{
+}
+
+// -----------------------------------------------------------------------
+
+SvHeaderTabListBox::SvHeaderTabListBox( Window* pParent, const ResId& rResId ) :
+
+ SvTabListBox( pParent, rResId ),
+
+ m_bFirstPaint ( TRUE ),
+ m_pImpl ( new ::svt::SvHeaderTabListBoxImpl ),
+ m_pAccessible ( NULL )
+{
+}
+
+// -----------------------------------------------------------------------
+
+SvHeaderTabListBox::~SvHeaderTabListBox()
+{
+ delete m_pImpl;
+}
+
+// -----------------------------------------------------------------------
+
+void SvHeaderTabListBox::Paint( const Rectangle& rRect )
+{
+ if ( m_bFirstPaint )
+ {
+ m_bFirstPaint = FALSE;
+ RepaintScrollBars();
+ }
+ SvTabListBox::Paint( rRect );
+}
+
+// -----------------------------------------------------------------------
+
+void SvHeaderTabListBox::InitHeaderBar( HeaderBar* pHeaderBar )
+{
+ DBG_ASSERT( !m_pImpl->m_pHeaderBar, "header bar already initialized" );
+ DBG_ASSERT( pHeaderBar, "invalid header bar initialization" );
+ m_pImpl->m_pHeaderBar = pHeaderBar;
+ SetScrolledHdl( LINK( this, SvHeaderTabListBox, ScrollHdl_Impl ) );
+ m_pImpl->m_pHeaderBar->SetCreateAccessibleHdl( LINK( this, SvHeaderTabListBox, CreateAccessibleHdl_Impl ) );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SvHeaderTabListBox::IsItemChecked( SvLBoxEntry* pEntry, USHORT nCol ) const
+{
+ SvButtonState eState = SV_BUTTON_UNCHECKED;
+ SvLBoxButton* pItem = (SvLBoxButton*)( pEntry->GetItem( nCol + 1 ) );
+
+ if ( pItem && ( (SvLBoxItem*)pItem )->IsA() == SV_ITEM_ID_LBOXBUTTON )
+ {
+ USHORT nButtonFlags = pItem->GetButtonFlags();
+ eState = pCheckButtonData->ConvertToButtonState( nButtonFlags );
+ }
+
+ return ( eState == SV_BUTTON_CHECKED );
+}
+
+// -----------------------------------------------------------------------
+
+SvLBoxEntry* SvHeaderTabListBox::InsertEntryToColumn(
+ const XubString& rStr, ULONG nPos, USHORT nCol, void* pUserData )
+{
+ SvLBoxEntry* pEntry = SvTabListBox::InsertEntryToColumn( rStr, nPos, nCol, pUserData );
+ RecalculateAccessibleChildren();
+ return pEntry;
+}
+
+// -----------------------------------------------------------------------
+
+SvLBoxEntry* SvHeaderTabListBox::InsertEntryToColumn(
+ const XubString& rStr, SvLBoxEntry* pParent, ULONG nPos, USHORT nCol, void* pUserData )
+{
+ SvLBoxEntry* pEntry = SvTabListBox::InsertEntryToColumn( rStr, pParent, nPos, nCol, pUserData );
+ RecalculateAccessibleChildren();
+ return pEntry;
+}
+
+// -----------------------------------------------------------------------
+
+SvLBoxEntry* SvHeaderTabListBox::InsertEntryToColumn(
+ const XubString& rStr, const Image& rExpandedEntryBmp, const Image& rCollapsedEntryBmp,
+ SvLBoxEntry* pParent, ULONG nPos, USHORT nCol, void* pUserData )
+{
+ SvLBoxEntry* pEntry = SvTabListBox::InsertEntryToColumn(
+ rStr, rExpandedEntryBmp, rCollapsedEntryBmp, pParent, nPos, nCol, pUserData );
+ RecalculateAccessibleChildren();
+ return pEntry;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG SvHeaderTabListBox::Insert(
+ SvLBoxEntry* pEnt, SvLBoxEntry* pPar, ULONG nPos )
+{
+ ULONG n = SvTabListBox::Insert( pEnt, pPar, nPos );
+ RecalculateAccessibleChildren();
+ return n;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG SvHeaderTabListBox::Insert( SvLBoxEntry* pEntry, ULONG nRootPos )
+{
+ ULONG nPos = SvTabListBox::Insert( pEntry, nRootPos );
+ RecalculateAccessibleChildren();
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+void SvHeaderTabListBox::RemoveEntry( SvLBoxEntry* _pEntry )
+{
+ GetModel()->Remove( _pEntry );
+ m_aAccessibleChildren.clear();
+}
+
+// -----------------------------------------------------------------------
+
+void SvHeaderTabListBox::Clear()
+{
+ SvTabListBox::Clear();
+ m_aAccessibleChildren.clear();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( SvHeaderTabListBox, ScrollHdl_Impl, SvTabListBox*, EMPTYARG )
+{
+ m_pImpl->m_pHeaderBar->SetOffset( -GetXOffset() );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( SvHeaderTabListBox, CreateAccessibleHdl_Impl, HeaderBar*, EMPTYARG )
+{
+ Window* pParent = m_pImpl->m_pHeaderBar->GetAccessibleParentWindow();
+ DBG_ASSERT( pParent, "SvHeaderTabListBox..CreateAccessibleHdl_Impl - accessible parent not found" );
+ if ( pParent )
+ {
+ ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
+ if ( xAccParent.is() )
+ {
+ Reference< XAccessible > xAccessible = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleBrowseBoxHeaderBar(
+ xAccParent, *this, ::svt::BBTYPE_COLUMNHEADERBAR );
+ m_pImpl->m_pHeaderBar->SetAccessible( xAccessible );
+ }
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SvHeaderTabListBox::RecalculateAccessibleChildren()
+{
+ if ( !m_aAccessibleChildren.empty() )
+ {
+ sal_uInt32 nCount = ( GetRowCount() + 1 ) * GetColumnCount();
+ if ( m_aAccessibleChildren.size() < nCount )
+ m_aAccessibleChildren.resize( nCount );
+ else
+ {
+ DBG_ASSERT( m_aAccessibleChildren.size() == nCount, "wrong children count" );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SvHeaderTabListBox::IsCellCheckBox( long _nRow, sal_uInt16 _nColumn, TriState& _rState )
+{
+ sal_Bool bRet = sal_False;
+ SvLBoxEntry* pEntry = GetEntry( _nRow );
+ if ( pEntry )
+ {
+ USHORT nItemCount = pEntry->ItemCount();
+ if ( nItemCount > ( _nColumn + 1 ) )
+ {
+ SvLBoxButton* pItem = (SvLBoxButton*)( pEntry->GetItem( _nColumn + 1 ) );
+ if ( pItem && ( (SvLBoxItem*)pItem )->IsA() == SV_ITEM_ID_LBOXBUTTON )
+ {
+ bRet = sal_True;
+ _rState = ( ( pItem->GetButtonFlags() & SV_ITEMSTATE_UNCHECKED ) == 0 )
+ ? STATE_CHECK : STATE_NOCHECK;
+ }
+ }
+ else
+ {
+ DBG_ERRORFILE( "SvHeaderTabListBox::IsCellCheckBox(): column out of range" );
+ }
+ }
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+long SvHeaderTabListBox::GetRowCount() const
+{
+ return GetEntryCount();
+}
+// -----------------------------------------------------------------------
+sal_uInt16 SvHeaderTabListBox::GetColumnCount() const
+{
+ return m_pImpl->m_pHeaderBar->GetItemCount();
+}
+// -----------------------------------------------------------------------
+sal_Int32 SvHeaderTabListBox::GetCurrRow() const
+{
+ sal_Int32 nRet = -1;
+ SvLBoxEntry* pEntry = GetCurEntry();
+ if ( pEntry )
+ {
+ ULONG nCount = GetEntryCount();
+ for ( ULONG i = 0; i < nCount; ++i )
+ {
+ if ( pEntry == GetEntry(i) )
+ {
+ nRet = i;
+ break;
+ }
+ }
+ }
+
+ return nRet;
+}
+// -----------------------------------------------------------------------
+sal_uInt16 SvHeaderTabListBox::GetCurrColumn() const
+{
+ sal_uInt16 nPos = GetCurrentTabPos() - 1;
+ return nPos;
+}
+// -----------------------------------------------------------------------
+::rtl::OUString SvHeaderTabListBox::GetRowDescription( sal_Int32 _nRow ) const
+{
+ return ::rtl::OUString( GetEntryText( _nRow ) );
+}
+// -----------------------------------------------------------------------
+::rtl::OUString SvHeaderTabListBox::GetColumnDescription( sal_uInt16 _nColumn ) const
+{
+ return ::rtl::OUString( m_pImpl->m_pHeaderBar->GetItemText( m_pImpl->m_pHeaderBar->GetItemId( _nColumn ) ) );
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::HasRowHeader() const
+{
+ return sal_False;
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::IsCellFocusable() const
+{
+ return IsCellFocusEnabled();
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::GoToCell( sal_Int32 _nRow, sal_uInt16 _nColumn )
+{
+ sal_Bool bRet = ( IsCellFocusEnabled() == TRUE );
+ if ( bRet )
+ {
+ // first set cursor to _nRow
+ SetCursor( GetEntry( _nRow ), TRUE );
+ // then set the focus into _nColumn
+ bRet = ( SetCurrentTabPos( _nColumn ) == true );
+ }
+ return bRet;
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::SetNoSelection()
+{
+ SvLBox::SelectAll( FALSE );
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::SelectAll()
+{
+ SvLBox::SelectAll( TRUE );
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::SelectAll( BOOL bSelect, BOOL bPaint )
+{
+ // overwritten just to disambiguate the SelectAll() from the base' class SelectAll( BOOl, BOOL )
+ SvTabListBox::SelectAll( bSelect, bPaint );
+}
+
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::SelectRow( long _nRow, BOOL _bSelect, BOOL )
+{
+ Select( GetEntry( _nRow ), _bSelect );
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::SelectColumn( sal_uInt16, sal_Bool )
+{
+}
+// -----------------------------------------------------------------------
+sal_Int32 SvHeaderTabListBox::GetSelectedRowCount() const
+{
+ return GetSelectionCount();
+}
+// -----------------------------------------------------------------------
+sal_Int32 SvHeaderTabListBox::GetSelectedColumnCount() const
+{
+ return 0;
+}
+// -----------------------------------------------------------------------
+bool SvHeaderTabListBox::IsRowSelected( long _nRow ) const
+{
+ SvLBoxEntry* pEntry = GetEntry( _nRow );
+ return ( pEntry && IsSelected( pEntry ) );
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::IsColumnSelected( long ) const
+{
+ return FALSE;
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::GetAllSelectedRows( ::com::sun::star::uno::Sequence< sal_Int32 >& ) const
+{
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::GetAllSelectedColumns( ::com::sun::star::uno::Sequence< sal_Int32 >& ) const
+{
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::IsCellVisible( sal_Int32, sal_uInt16 ) const
+{
+ return sal_True;
+}
+// -----------------------------------------------------------------------
+String SvHeaderTabListBox::GetAccessibleCellText( long _nRow, USHORT _nColumnPos ) const
+{
+ return ::rtl::OUString( GetTabEntryText( _nRow, _nColumnPos ) );
+}
+// -----------------------------------------------------------------------
+Rectangle SvHeaderTabListBox::calcHeaderRect( sal_Bool _bIsColumnBar, BOOL _bOnScreen )
+{
+ Rectangle aRect;
+ if ( _bIsColumnBar )
+ {
+ Window* pParent = NULL;
+ if ( !_bOnScreen )
+ pParent = m_pImpl->m_pHeaderBar->GetAccessibleParentWindow();
+
+ aRect = m_pImpl->m_pHeaderBar->GetWindowExtentsRelative( pParent );
+ }
+ return aRect;
+}
+// -----------------------------------------------------------------------
+Rectangle SvHeaderTabListBox::calcTableRect( BOOL _bOnScreen )
+{
+ Window* pParent = NULL;
+ if ( !_bOnScreen )
+ pParent = GetAccessibleParentWindow();
+
+ Rectangle aRect( GetWindowExtentsRelative( pParent ) );
+ return aRect;
+}
+// -----------------------------------------------------------------------
+Rectangle SvHeaderTabListBox::GetFieldRectPixelAbs( sal_Int32 _nRow, sal_uInt16 _nColumn, BOOL _bIsHeader, BOOL _bOnScreen )
+{
+ DBG_ASSERT( !_bIsHeader || 0 == _nRow, "invalid parameters" );
+ Rectangle aRect;
+ SvLBoxEntry* pEntry = GetEntry( _nRow );
+ if ( pEntry )
+ {
+ aRect = _bIsHeader ? calcHeaderRect( sal_True, FALSE ) : GetBoundingRect( pEntry );
+ Point aTopLeft = aRect.TopLeft();
+ DBG_ASSERT( m_pImpl->m_pHeaderBar->GetItemCount() > _nColumn, "invalid column" );
+ Rectangle aItemRect = m_pImpl->m_pHeaderBar->GetItemRect( m_pImpl->m_pHeaderBar->GetItemId( _nColumn ) );
+ aTopLeft.X() = aItemRect.Left();
+ Size aSize = aItemRect.GetSize();
+ aRect = Rectangle( aTopLeft, aSize );
+ Window* pParent = NULL;
+ if ( !_bOnScreen )
+ pParent = GetAccessibleParentWindow();
+ aTopLeft = aRect.TopLeft();
+ aTopLeft += GetWindowExtentsRelative( pParent ).TopLeft();
+ aRect = Rectangle( aTopLeft, aRect.GetSize() );
+ }
+
+ return aRect;
+}
+// -----------------------------------------------------------------------
+Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
+{
+ OSL_ENSURE( m_pAccessible, "Invalid call: Accessible is null" );
+
+ Reference< XAccessible > xChild;
+ sal_Int32 nIndex = -1;
+
+ if ( !AreChildrenTransient() )
+ {
+ const sal_uInt16 nColumnCount = GetColumnCount();
+
+ // first call? -> initial list
+ if ( m_aAccessibleChildren.empty() )
+ {
+ sal_Int32 nCount = ( GetRowCount() + 1 ) * nColumnCount;
+ m_aAccessibleChildren.assign( nCount, Reference< XAccessible >() );
+ }
+
+ nIndex = ( _nRow * nColumnCount ) + _nColumnPos + nColumnCount;
+ xChild = m_aAccessibleChildren[ nIndex ];
+ }
+
+ if ( !xChild.is() )
+ {
+ TriState eState = STATE_DONTKNOW;
+ sal_Bool bIsCheckBox = IsCellCheckBox( _nRow, _nColumnPos, eState );
+ if ( bIsCheckBox )
+ xChild = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleCheckBoxCell(
+ m_pAccessible->getAccessibleChild( 0 ), *this, NULL, _nRow, _nColumnPos, eState, sal_True, sal_False );
+ else
+ xChild = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleBrowseBoxTableCell(
+ m_pAccessible->getAccessibleChild( 0 ), *this, NULL, _nRow, _nColumnPos, OFFSET_NONE );
+
+ // insert into list
+ if ( !AreChildrenTransient() )
+ m_aAccessibleChildren[ nIndex ] = xChild;
+ }
+
+ return xChild;
+}
+// -----------------------------------------------------------------------
+Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleRowHeader( sal_Int32 )
+{
+ Reference< XAccessible > xHeader;
+ return xHeader;
+}
+// -----------------------------------------------------------------------
+Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleColumnHeader( sal_uInt16 _nColumn )
+{
+ // first call? -> initial list
+ if ( m_aAccessibleChildren.empty() )
+ {
+ const sal_uInt16 nColumnCount = GetColumnCount();
+ sal_Int32 nCount = AreChildrenTransient() ?
+ nColumnCount : ( GetRowCount() + 1 ) * nColumnCount;
+ m_aAccessibleChildren.assign( nCount, Reference< XAccessible >() );
+ }
+
+ // get header
+ Reference< XAccessible > xChild = m_aAccessibleChildren[ _nColumn ];
+ // already exists?
+ if ( !xChild.is() && m_pAccessible )
+ {
+ // no -> create new header cell
+ xChild = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleBrowseBoxHeaderCell(
+ _nColumn, m_pAccessible->getHeaderBar( ::svt::BBTYPE_COLUMNHEADERBAR ),
+ *this, NULL, ::svt::BBTYPE_COLUMNHEADERCELL
+ );
+
+ // insert into list
+ m_aAccessibleChildren[ _nColumn ] = xChild;
+ }
+
+ return xChild;
+}
+// -----------------------------------------------------------------------
+sal_Int32 SvHeaderTabListBox::GetAccessibleControlCount() const
+{
+ return -1;
+}
+// -----------------------------------------------------------------------
+Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleControl( sal_Int32 )
+{
+ Reference< XAccessible > xControl;
+ return xControl;
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::ConvertPointToControlIndex( sal_Int32&, const Point& )
+{
+ return sal_False;
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::ConvertPointToCellAddress( sal_Int32&, sal_uInt16&, const Point& )
+{
+ return sal_False;
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::ConvertPointToRowHeader( sal_Int32&, const Point& )
+{
+ return sal_False;
+}
+// -----------------------------------------------------------------------
+sal_Bool SvHeaderTabListBox::ConvertPointToColumnHeader( sal_uInt16&, const Point& )
+{
+ return sal_False;
+}
+// -----------------------------------------------------------------------
+::rtl::OUString SvHeaderTabListBox::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
+{
+ ::rtl::OUString aRetText;
+ switch( _eType )
+ {
+ case ::svt::BBTYPE_BROWSEBOX:
+ case ::svt::BBTYPE_TABLE:
+ case ::svt::BBTYPE_COLUMNHEADERBAR:
+ // should be empty now (see #i63983)
+ aRetText = ::rtl::OUString();
+ break;
+
+ case ::svt::BBTYPE_TABLECELL:
+ {
+ // here we need a valid pos, we can not handle -1
+ if ( _nPos >= 0 )
+ {
+ sal_uInt16 nColumnCount = GetColumnCount();
+ if (nColumnCount > 0)
+ {
+ sal_Int32 nRow = _nPos / nColumnCount;
+ sal_uInt16 nColumn = static_cast< sal_uInt16 >( _nPos % nColumnCount );
+ aRetText = GetCellText( nRow, nColumn );
+ }
+ }
+ break;
+ }
+ case ::svt::BBTYPE_CHECKBOXCELL:
+ {
+ break; // checkbox cells have no name
+ }
+ case ::svt::BBTYPE_COLUMNHEADERCELL:
+ {
+ aRetText = m_pImpl->m_pHeaderBar->GetItemText( m_pImpl->m_pHeaderBar->GetItemId( (USHORT)_nPos ) );
+ break;
+ }
+
+ case ::svt::BBTYPE_ROWHEADERBAR:
+ case ::svt::BBTYPE_ROWHEADERCELL:
+ aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "error" ) );
+ break;
+
+ default:
+ OSL_ENSURE(0,"BrowseBox::GetAccessibleName: invalid enum!");
+ }
+ return aRetText;
+}
+// -----------------------------------------------------------------------
+::rtl::OUString SvHeaderTabListBox::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
+{
+ ::rtl::OUString aRetText;
+
+ if( _eType == ::svt::BBTYPE_TABLECELL && _nPos != -1 )
+ {
+ static const String sVar1( RTL_CONSTASCII_USTRINGPARAM( "%1" ) );
+ static const String sVar2( RTL_CONSTASCII_USTRINGPARAM( "%2" ) );
+
+ sal_uInt16 nColumnCount = GetColumnCount();
+ if (nColumnCount > 0)
+ {
+ sal_Int32 nRow = _nPos / nColumnCount;
+ sal_uInt16 nColumn = static_cast< sal_uInt16 >( _nPos % nColumnCount );
+
+ String aText( SvtResId( STR_SVT_ACC_DESC_TABLISTBOX ) );
+ aText.SearchAndReplace( sVar1, String::CreateFromInt32( nRow ) );
+ String sColHeader = m_pImpl->m_pHeaderBar->GetItemText( m_pImpl->m_pHeaderBar->GetItemId( nColumn ) );
+ if ( sColHeader.Len() == 0 )
+ sColHeader = String::CreateFromInt32( nColumn );
+ aText.SearchAndReplace( sVar2, sColHeader );
+ aRetText = aText;
+ }
+ }
+
+ return aRetText;
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& _rStateSet, ::svt::AccessibleBrowseBoxObjType _eType ) const
+{
+ switch( _eType )
+ {
+ case ::svt::BBTYPE_BROWSEBOX:
+ case ::svt::BBTYPE_TABLE:
+ {
+ _rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ if ( HasFocus() )
+ _rStateSet.AddState( AccessibleStateType::FOCUSED );
+ if ( IsActive() )
+ _rStateSet.AddState( AccessibleStateType::ACTIVE );
+ if ( IsEnabled() )
+ {
+ _rStateSet.AddState( AccessibleStateType::ENABLED );
+ _rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+ if ( IsReallyVisible() )
+ _rStateSet.AddState( AccessibleStateType::VISIBLE );
+ if ( _eType == ::svt::BBTYPE_TABLE )
+ {
+
+ if ( AreChildrenTransient() )
+ _rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
+ _rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
+ }
+ break;
+ }
+
+ case ::svt::BBTYPE_COLUMNHEADERBAR:
+ {
+ sal_Int32 nCurRow = GetCurrRow();
+ sal_uInt16 nCurColumn = GetCurrColumn();
+ if ( IsCellVisible( nCurRow, nCurColumn ) )
+ _rStateSet.AddState( AccessibleStateType::VISIBLE );
+ _rStateSet.AddState( AccessibleStateType::TRANSIENT );
+ break;
+ }
+
+ case ::svt::BBTYPE_ROWHEADERCELL:
+ case ::svt::BBTYPE_COLUMNHEADERCELL:
+ {
+ _rStateSet.AddState( AccessibleStateType::VISIBLE );
+ _rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ _rStateSet.AddState( AccessibleStateType::TRANSIENT );
+ break;
+ }
+ default:
+ break;
+ }
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumn ) const
+{
+ _rStateSet.AddState( AccessibleStateType::SELECTABLE );
+ if ( AreChildrenTransient() )
+ _rStateSet.AddState( AccessibleStateType::TRANSIENT );
+
+ if ( IsCellVisible( _nRow, _nColumn ) )
+ {
+ _rStateSet.AddState( AccessibleStateType::VISIBLE );
+ _rStateSet.AddState( AccessibleStateType::ENABLED );
+ }
+
+ if ( IsRowSelected( _nRow ) )
+ {
+ _rStateSet.AddState( AccessibleStateType::ACTIVE );
+ _rStateSet.AddState( AccessibleStateType::SELECTED );
+ }
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::GrabTableFocus()
+{
+ GrabFocus();
+}
+// -----------------------------------------------------------------------
+BOOL SvHeaderTabListBox::GetGlyphBoundRects( const Point& rOrigin, const String& rStr, int nIndex, int nLen, int nBase, MetricVector& rVector )
+{
+ return Control::GetGlyphBoundRects( rOrigin, rStr, nIndex, nLen, nBase, rVector );
+}
+// -----------------------------------------------------------------------
+Rectangle SvHeaderTabListBox::GetWindowExtentsRelative( Window *pRelativeWindow ) const
+{
+ return Control::GetWindowExtentsRelative( pRelativeWindow );
+}
+// -----------------------------------------------------------------------
+void SvHeaderTabListBox::GrabFocus()
+{
+ Control::GrabFocus();
+}
+// -----------------------------------------------------------------------
+Reference< XAccessible > SvHeaderTabListBox::GetAccessible( BOOL bCreate )
+{
+ return Control::GetAccessible( bCreate );
+}
+// -----------------------------------------------------------------------
+Window* SvHeaderTabListBox::GetAccessibleParentWindow() const
+{
+ return Control::GetAccessibleParentWindow();
+}
+// -----------------------------------------------------------------------
+Window* SvHeaderTabListBox::GetWindowInstance()
+{
+ return this;
+}
+// -----------------------------------------------------------------------
+Reference< XAccessible > SvHeaderTabListBox::CreateAccessible()
+{
+ Window* pParent = GetAccessibleParentWindow();
+ DBG_ASSERT( pParent, "SvHeaderTabListBox::::CreateAccessible - accessible parent not found" );
+
+ Reference< XAccessible > xAccessible;
+ if ( m_pAccessible ) xAccessible = m_pAccessible->getMyself();
+
+ if( pParent && !m_pAccessible )
+ {
+ Reference< XAccessible > xAccParent = pParent->GetAccessible();
+ if ( xAccParent.is() )
+ {
+ m_pAccessible = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleTabListBox( xAccParent, *this );
+ if ( m_pAccessible )
+ xAccessible = m_pAccessible->getMyself();
+ }
+ }
+ return xAccessible;
+}
+// -----------------------------------------------------------------------------
+Rectangle SvHeaderTabListBox::GetFieldCharacterBounds(sal_Int32,sal_Int32,sal_Int32)
+{
+ Rectangle aRect;
+ return aRect;
+}
+// -----------------------------------------------------------------------------
+sal_Int32 SvHeaderTabListBox::GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint)
+{
+ String sText = GetAccessibleCellText( _nRow, static_cast< USHORT >( _nColumnPos ) );
+ MetricVector aRects;
+ if ( GetGlyphBoundRects(Point(0,0),sText,0,STRING_LEN,0,aRects) )
+ {
+ for (MetricVector::iterator aIter = aRects.begin(); aIter != aRects.end(); ++aIter)
+ {
+ if( aIter->IsInside(_rPoint) )
+ return aIter - aRects.begin();
+ }
+ }
+
+ return -1;
+}
+// -----------------------------------------------------------------------------
+
+
diff --git a/svtools/source/contnr/svtreebx.cxx b/svtools/source/contnr/svtreebx.cxx
new file mode 100644
index 000000000000..b11a3f12ddf3
--- /dev/null
+++ b/svtools/source/contnr/svtreebx.cxx
@@ -0,0 +1,2670 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+#define _SVTREEBX_CXX
+#include <vcl/svapp.hxx>
+#ifndef GCC
+#endif
+
+class TabBar;
+
+// #102891# -----------------------
+
+#include <svtools/svlbox.hxx>
+#include <svtools/svlbitm.hxx>
+#include <svtools/svtreebx.hxx>
+#include <tools/diagnose_ex.h>
+#include <svimpbox.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+
+
+using namespace ::com::sun::star::accessibility;
+
+/*
+ Bugs/ToDo
+
+ - Berechnung Rectangle beim Inplace-Editing (Bug bei manchen Fonts)
+ - SetSpaceBetweenEntries: Offset wird in SetEntryHeight nicht
+ beruecksichtigt
+*/
+
+#define TREEFLAG_FIXEDHEIGHT 0x0010
+
+
+DBG_NAME(SvTreeListBox)
+
+#define SV_LBOX_DEFAULT_INDENT_PIXEL 20
+
+SvTreeListBox::SvTreeListBox( Window* pParent, WinBits nWinStyle )
+ : SvLBox(pParent,nWinStyle )
+{
+ DBG_CTOR(SvTreeListBox,0);
+ InitTreeView( nWinStyle );
+
+ SetSublistOpenWithLeftRight();
+}
+
+SvTreeListBox::SvTreeListBox( Window* pParent , const ResId& rResId )
+ : SvLBox( pParent,rResId )
+{
+ DBG_CTOR(SvTreeListBox,0);
+
+ InitTreeView( 0 );
+ Resize();
+
+ SetSublistOpenWithLeftRight();
+}
+
+void SvTreeListBox::InitTreeView( WinBits nWinStyle )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pCheckButtonData = NULL;
+ pEdEntry = NULL;
+ pEdItem = NULL;
+ nEntryHeight = 0;
+ pEdCtrl = NULL;
+ nFirstSelTab = 0;
+ nLastSelTab = 0;
+ nFocusWidth = -1;
+
+ Link* pLink = new Link( LINK(this,SvTreeListBox, DefaultCompare) );
+ pLBoxImpl->m_pLink = pLink;
+
+ nTreeFlags = TREEFLAG_RECALCTABS;
+ nIndent = SV_LBOX_DEFAULT_INDENT_PIXEL;
+ nEntryHeightOffs = SV_ENTRYHEIGHTOFFS_PIXEL;
+ pImp = new SvImpLBox( this, GetModel(), nWinStyle );
+
+ aContextBmpMode = SVLISTENTRYFLAG_EXPANDED;
+ nContextBmpWidthMax = 0;
+ SetFont( GetFont() );
+ SetSpaceBetweenEntries( 0 );
+ SetLineColor();
+ InitSettings( TRUE, TRUE, TRUE );
+ SetWindowBits( nWinStyle );
+ SetTabs();
+}
+
+
+SvTreeListBox::~SvTreeListBox()
+{
+ DBG_DTOR(SvTreeListBox,0);
+ pImp->CallEventListeners( VCLEVENT_OBJECT_DYING );
+ delete pImp;
+ delete pLBoxImpl->m_pLink;
+ ClearTabList();
+}
+
+void SvTreeListBox::SetExtendedWinBits( ExtendedWinBits _nBits )
+{
+ pImp->SetExtendedWindowBits( _nBits );
+}
+
+ExtendedWinBits SvTreeListBox::GetExtendedWinBits() const
+{
+ return pImp->GetExtendedWindowBits();
+}
+
+void SvTreeListBox::SetModel( SvLBoxTreeList* pNewModel )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->SetModel( pNewModel );
+ SvLBox::SetModel( pNewModel );
+}
+
+void SvTreeListBox::DisconnectFromModel()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBox::DisconnectFromModel();
+ pImp->SetModel( GetModel() );
+}
+
+
+USHORT SvTreeListBox::IsA()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ return SV_LISTBOX_ID_TREEBOX;
+}
+
+void SvTreeListBox::SetSublistOpenWithReturn( BOOL b )
+{
+ pImp->bSubLstOpRet = b;
+}
+
+BOOL SvTreeListBox::IsSublistOpenWithReturn() const
+{
+ return pImp->bSubLstOpRet;
+}
+
+void SvTreeListBox::SetSublistOpenWithLeftRight( BOOL b )
+{
+ pImp->bSubLstOpLR = b;
+}
+
+BOOL SvTreeListBox::IsSublistOpenWithLeftRight() const
+{
+ return pImp->bSubLstOpLR;
+}
+
+void SvTreeListBox::Resize()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( IsEditingActive() )
+ EndEditing( TRUE );
+ SvLBox::Resize();
+ pImp->Resize();
+ nFocusWidth = -1;
+ pImp->ShowCursor( FALSE );
+ pImp->ShowCursor( TRUE );
+}
+
+/* Faelle:
+
+ A) Entries haben Bitmaps
+ 0. Keine Buttons
+ 1. Node-Buttons (optional auch an Root-Items)
+ 2. Node-Buttons (optional auch an Root-Items) + CheckButton
+ 3. CheckButton
+ B) Entries haben keine Bitmaps (->ueber WindowBits wg. D&D !!!!!!)
+ 0. Keine Buttons
+ 1. Node-Buttons (optional auch an Root-Items)
+ 2. Node-Buttons (optional auch an Root-Items) + CheckButton
+ 3. CheckButton
+*/
+
+#define NO_BUTTONS 0
+#define NODE_BUTTONS 1
+#define NODE_AND_CHECK_BUTTONS 2
+#define CHECK_BUTTONS 3
+
+#define TABFLAGS_TEXT (SV_LBOXTAB_DYNAMIC | \
+ SV_LBOXTAB_ADJUST_LEFT | \
+ SV_LBOXTAB_EDITABLE | \
+ SV_LBOXTAB_SHOW_SELECTION)
+
+#define TABFLAGS_CONTEXTBMP (SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER)
+
+#define TABFLAGS_CHECKBTN (SV_LBOXTAB_DYNAMIC | \
+ SV_LBOXTAB_ADJUST_CENTER | \
+ SV_LBOXTAB_PUSHABLE)
+
+#define TAB_STARTPOS 2
+
+// bei Aenderungen GetTextOffset beruecksichtigen
+void SvTreeListBox::SetTabs()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( IsEditingActive() )
+ EndEditing( TRUE );
+ nTreeFlags &= (~TREEFLAG_RECALCTABS);
+ nFocusWidth = -1;
+ BOOL bHasButtons = (nWindowStyle & WB_HASBUTTONS)!=0;
+ BOOL bHasButtonsAtRoot = (nWindowStyle & (WB_HASLINESATROOT |
+ WB_HASBUTTONSATROOT))!=0;
+ long nStartPos = TAB_STARTPOS;
+ long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width();
+
+ long nCheckWidth = 0;
+ if( nTreeFlags & TREEFLAG_CHKBTN )
+ nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width();
+ long nCheckWidthDIV2 = nCheckWidth / 2;
+
+ long nContextWidth = nContextBmpWidthMax;
+ long nContextWidthDIV2 = nContextWidth / 2;
+
+ ClearTabList();
+
+ int nCase = NO_BUTTONS;
+ if( !(nTreeFlags & TREEFLAG_CHKBTN) )
+ {
+ if( bHasButtons )
+ nCase = NODE_BUTTONS;
+ }
+ else
+ {
+ if( bHasButtons )
+ nCase = NODE_AND_CHECK_BUTTONS;
+ else
+ nCase = CHECK_BUTTONS;
+ }
+
+ switch( nCase )
+ {
+ case NO_BUTTONS :
+ nStartPos += nContextWidthDIV2; // wg. Zentrierung
+ AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
+ nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp
+ // Abstand setzen nur wenn Bitmaps da
+ if( nContextBmpWidthMax )
+ nStartPos += 5; // Abstand Context-Bmp - Text
+ AddTab( nStartPos, TABFLAGS_TEXT );
+ break;
+
+ case NODE_BUTTONS :
+ if( bHasButtonsAtRoot )
+ nStartPos += ( nIndent + (nNodeWidthPixel/2) );
+ else
+ nStartPos += nContextWidthDIV2;
+ AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
+ nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp
+ // Abstand setzen nur wenn Bitmaps da
+ if( nContextBmpWidthMax )
+ nStartPos += 5; // Abstand Context-Bmp - Text
+ AddTab( nStartPos, TABFLAGS_TEXT );
+ break;
+
+ case NODE_AND_CHECK_BUTTONS :
+ if( bHasButtonsAtRoot )
+ nStartPos += ( nIndent + nNodeWidthPixel );
+ else
+ nStartPos += nCheckWidthDIV2;
+ AddTab( nStartPos, TABFLAGS_CHECKBTN );
+ nStartPos += nCheckWidthDIV2; // rechter Rand des CheckButtons
+ nStartPos += 3; // Abstand CheckButton Context-Bmp
+ nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp
+ AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
+ nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp
+ // Abstand setzen nur wenn Bitmaps da
+ if( nContextBmpWidthMax )
+ nStartPos += 5; // Abstand Context-Bmp - Text
+ AddTab( nStartPos, TABFLAGS_TEXT );
+ break;
+
+ case CHECK_BUTTONS :
+ nStartPos += nCheckWidthDIV2;
+ AddTab( nStartPos, TABFLAGS_CHECKBTN );
+ nStartPos += nCheckWidthDIV2; // rechter Rand CheckButton
+ nStartPos += 3; // Abstand CheckButton Context-Bmp
+ nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp
+ AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
+ nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp
+ // Abstand setzen nur wenn Bitmaps da
+ if( nContextBmpWidthMax )
+ nStartPos += 5; // Abstand Context-Bmp - Text
+ AddTab( nStartPos, TABFLAGS_TEXT );
+ break;
+ }
+ pImp->NotifyTabsChanged();
+}
+
+void SvTreeListBox::InitEntry( SvLBoxEntry* pEntry,
+ const XubString& aStr, const Image& aCollEntryBmp, const Image& aExpEntryBmp,
+ SvLBoxButtonKind eButtonKind)
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBoxButton* pButton;
+ SvLBoxString* pString;
+ SvLBoxContextBmp* pContextBmp;
+
+ if( nTreeFlags & TREEFLAG_CHKBTN )
+ {
+ pButton= new SvLBoxButton( pEntry,eButtonKind,0,pCheckButtonData );
+ pEntry->AddItem( pButton );
+ }
+
+ pContextBmp= new SvLBoxContextBmp( pEntry,0, aCollEntryBmp,aExpEntryBmp,
+ aContextBmpMode );
+ pEntry->AddItem( pContextBmp );
+
+ pString = new SvLBoxString( pEntry, 0, aStr );
+ pEntry->AddItem( pString );
+}
+
+String SvTreeListBox::GetEntryText(SvLBoxEntry* pEntry) const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): no entry" );
+ SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): item not found" );
+ return pItem->GetText();
+}
+
+String SvTreeListBox::SearchEntryText( SvLBoxEntry* pEntry ) const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT( pEntry, "SvTreeListBox::SearchEntryText(): no entry" );
+ String sRet;
+ USHORT nCount = pEntry->ItemCount();
+ USHORT nCur = 0;
+ SvLBoxItem* pItem;
+ while( nCur < nCount )
+ {
+ pItem = pEntry->GetItem( nCur );
+ if ( pItem->IsA() == SV_ITEM_ID_LBOXSTRING &&
+ static_cast<SvLBoxString*>( pItem )->GetText().Len() > 0 )
+ {
+ sRet = static_cast<SvLBoxString*>( pItem )->GetText();
+ break;
+ }
+ nCur++;
+ }
+ return sRet;
+}
+
+const Image& SvTreeListBox::GetExpandedEntryBmp(SvLBoxEntry* pEntry, BmpColorMode _eMode) const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(pEntry,"Entry?");
+ SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ DBG_ASSERT(pItem,"GetContextBmp:Item not found");
+ return pItem->GetBitmap2( _eMode );
+}
+
+const Image& SvTreeListBox::GetCollapsedEntryBmp( SvLBoxEntry* pEntry, BmpColorMode _eMode ) const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(pEntry,"Entry?");
+ SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ DBG_ASSERT(pItem,"GetContextBmp:Item not found");
+ return pItem->GetBitmap1( _eMode );
+}
+
+IMPL_LINK_INLINE_START( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pHdlEntry = pData->GetActEntry();
+ CheckButtonHdl();
+ return 0;
+}
+IMPL_LINK_INLINE_END( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData )
+
+SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText,SvLBoxEntry* pParent,
+ BOOL bChildsOnDemand, ULONG nPos, void* pUser,
+ SvLBoxButtonKind eButtonKind )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ nTreeFlags |= TREEFLAG_MANINS;
+
+ const Image& rDefExpBmp = pImp->GetDefaultEntryExpBmp( );
+ const Image& rDefColBmp = pImp->GetDefaultEntryColBmp( );
+
+ aCurInsertedExpBmp = rDefExpBmp;
+ aCurInsertedColBmp = rDefColBmp;
+
+ SvLBoxEntry* pEntry = CreateEntry();
+ pEntry->SetUserData( pUser );
+ InitEntry( pEntry, aText, rDefColBmp, rDefExpBmp, eButtonKind );
+ pEntry->EnableChildsOnDemand( bChildsOnDemand );
+
+ // Add the HC versions of the default images
+ SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
+ if( pBmpItem )
+ {
+ pBmpItem->SetBitmap1( pImp->GetDefaultEntryColBmp( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
+ pBmpItem->SetBitmap2( pImp->GetDefaultEntryExpBmp( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
+ }
+
+ if( !pParent )
+ SvLBox::Insert( pEntry, nPos );
+ else
+ SvLBox::Insert( pEntry, pParent, nPos );
+
+ aPrevInsertedExpBmp = rDefExpBmp;
+ aPrevInsertedColBmp = rDefColBmp;
+
+ nTreeFlags &= (~TREEFLAG_MANINS);
+
+ return pEntry;
+}
+
+SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText,
+ const Image& aExpEntryBmp, const Image& aCollEntryBmp,
+ SvLBoxEntry* pParent, BOOL bChildsOnDemand, ULONG nPos, void* pUser,
+ SvLBoxButtonKind eButtonKind )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ nTreeFlags |= TREEFLAG_MANINS;
+
+ aCurInsertedExpBmp = aExpEntryBmp;
+ aCurInsertedColBmp = aCollEntryBmp;
+
+ SvLBoxEntry* pEntry = CreateEntry();
+ pEntry->SetUserData( pUser );
+ InitEntry( pEntry, aText, aCollEntryBmp, aExpEntryBmp, eButtonKind );
+
+ pEntry->EnableChildsOnDemand( bChildsOnDemand );
+
+ if( !pParent )
+ SvLBox::Insert( pEntry, nPos );
+ else
+ SvLBox::Insert( pEntry, pParent, nPos );
+
+ aPrevInsertedExpBmp = aExpEntryBmp;
+ aPrevInsertedColBmp = aCollEntryBmp;
+
+ nTreeFlags &= (~TREEFLAG_MANINS);
+
+ return pEntry;
+}
+
+void SvTreeListBox::SetEntryText( SvLBoxEntry* pEntry, const XubString& aStr)
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ DBG_ASSERT(pItem,"SetText:Item not found");
+ pItem->SetText( pEntry, aStr );
+ pItem->InitViewData( this, pEntry, 0 );
+ GetModel()->InvalidateEntry( pEntry );
+}
+
+void SvTreeListBox::SetExpandedEntryBmp( SvLBoxEntry* pEntry, const Image& aBmp, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+
+ DBG_ASSERT(pItem,"SetExpBmp:Item not found");
+ pItem->SetBitmap2( aBmp, _eMode );
+
+ GetModel()->InvalidateEntry( pEntry );
+ SetEntryHeight( pEntry );
+ Size aSize = aBmp.GetSizePixel();
+ // #97680# ---------------
+ short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() );
+ if( nWidth > nContextBmpWidthMax )
+ {
+ nContextBmpWidthMax = nWidth;
+ SetTabs();
+ }
+}
+
+void SvTreeListBox::SetCollapsedEntryBmp(SvLBoxEntry* pEntry,const Image& aBmp, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+
+ DBG_ASSERT(pItem,"SetExpBmp:Item not found");
+ pItem->SetBitmap1( aBmp, _eMode );
+
+ GetModel()->InvalidateEntry( pEntry );
+ SetEntryHeight( pEntry );
+ Size aSize = aBmp.GetSizePixel();
+ // #97680# -----------
+ short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() );
+ if( nWidth > nContextBmpWidthMax )
+ {
+ nContextBmpWidthMax = nWidth;
+ SetTabs();
+ }
+}
+
+void SvTreeListBox::ImpEntryInserted( SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+
+ SvLBoxEntry* pParent = (SvLBoxEntry*)pModel->GetParent( pEntry );
+ if( pParent )
+ {
+ USHORT nFlags = pParent->GetFlags();
+ nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP;
+ pParent->SetFlags( nFlags );
+ }
+
+ if(!((nTreeFlags & TREEFLAG_MANINS) &&
+ (aPrevInsertedExpBmp == aCurInsertedExpBmp) &&
+ (aPrevInsertedColBmp == aCurInsertedColBmp) ))
+ {
+ Size aSize = GetCollapsedEntryBmp( pEntry ).GetSizePixel();
+ if( aSize.Width() > nContextBmpWidthMax )
+ {
+ nContextBmpWidthMax = (short)aSize.Width();
+ nTreeFlags |= TREEFLAG_RECALCTABS;
+ }
+ aSize = GetExpandedEntryBmp( pEntry ).GetSizePixel();
+ if( aSize.Width() > nContextBmpWidthMax )
+ {
+ nContextBmpWidthMax = (short)aSize.Width();
+ nTreeFlags |= TREEFLAG_RECALCTABS;
+ }
+ }
+ SetEntryHeight( (SvLBoxEntry*)pEntry );
+}
+
+
+
+void SvTreeListBox::SetCheckButtonState( SvLBoxEntry* pEntry, SvButtonState eState)
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( nTreeFlags & TREEFLAG_CHKBTN )
+ {
+ SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
+ if(!(pItem && pItem->CheckModification()))
+ return ;
+ switch( eState )
+ {
+ case SV_BUTTON_CHECKED:
+ pItem->SetStateChecked();
+ break;
+
+ case SV_BUTTON_UNCHECKED:
+ pItem->SetStateUnchecked();
+ break;
+
+ case SV_BUTTON_TRISTATE:
+ pItem->SetStateTristate();
+ break;
+ }
+ InvalidateEntry( pEntry );
+ }
+}
+
+SvButtonState SvTreeListBox::GetCheckButtonState( SvLBoxEntry* pEntry ) const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvButtonState eState = SV_BUTTON_UNCHECKED;
+ if( nTreeFlags & TREEFLAG_CHKBTN )
+ {
+ SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
+ if(!pItem)
+ return SV_BUTTON_TRISTATE;
+ USHORT nButtonFlags = pItem->GetButtonFlags();
+ eState = pCheckButtonData->ConvertToButtonState( nButtonFlags );
+ }
+ return eState;
+}
+
+void SvTreeListBox::CheckButtonHdl()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ aCheckButtonHdl.Call( this );
+ if ( pCheckButtonData )
+ pImp->CallEventListeners( VCLEVENT_CHECKBOX_TOGGLE, (void*)pCheckButtonData->GetActEntry() );
+}
+
+// *********************************************************************
+// *********************************************************************
+
+//
+// TODO: Momentan werden die Daten so geklont, dass sie dem
+// Standard-TreeView-Format entsprechen. Hier sollte eigentlich
+// das Model als Referenz dienen. Dies fuehrt dazu, dass
+// SvLBoxEntry::Clone _nicht_ gerufen wird, sondern nur dessen
+// Basisklasse SvListEntry
+//
+
+SvLBoxEntry* SvTreeListBox::CloneEntry( SvLBoxEntry* pSource )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ XubString aStr;
+ Image aCollEntryBmp;
+ Image aExpEntryBmp;
+ SvLBoxButtonKind eButtonKind = SvLBoxButtonKind_enabledCheckbox;
+
+ SvLBoxString* pStringItem = (SvLBoxString*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
+ if( pStringItem )
+ aStr = pStringItem->GetText();
+ SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
+ if( pBmpItem )
+ {
+ aCollEntryBmp = pBmpItem->GetBitmap1( BMP_COLOR_NORMAL );
+ aExpEntryBmp = pBmpItem->GetBitmap2( BMP_COLOR_NORMAL );
+ }
+ SvLBoxButton* pButtonItem = (SvLBoxButton*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
+ if( pButtonItem )
+ eButtonKind = pButtonItem->GetKind();
+ SvLBoxEntry* pClone = CreateEntry();
+ InitEntry( pClone, aStr, aCollEntryBmp, aExpEntryBmp, eButtonKind );
+ pClone->SvListEntry::Clone( pSource );
+ pClone->EnableChildsOnDemand( pSource->HasChildsOnDemand() );
+ pClone->SetUserData( pSource->GetUserData() );
+
+ if ( pBmpItem )
+ {
+ SvLBoxContextBmp* pCloneBitmap = static_cast< SvLBoxContextBmp* >( pClone->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
+ if ( pCloneBitmap )
+ {
+ pCloneBitmap->SetBitmap1( pBmpItem->GetBitmap1( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
+ pCloneBitmap->SetBitmap2( pBmpItem->GetBitmap2( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
+ }
+ }
+
+ return pClone;
+}
+
+// *********************************************************************
+// *********************************************************************
+
+
+void SvTreeListBox::ShowExpandBitmapOnCursor( BOOL bYes )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( bYes )
+ aContextBmpMode = SVLISTENTRYFLAG_FOCUSED;
+ else
+ aContextBmpMode = SVLISTENTRYFLAG_EXPANDED;
+}
+
+void SvTreeListBox::SetIndent( short nNewIndent )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ nIndent = nNewIndent;
+ SetTabs();
+ if( IsUpdateMode() )
+ Invalidate();
+}
+
+const Image& SvTreeListBox::GetDefaultExpandedEntryBmp( BmpColorMode _eMode ) const
+{
+ return pImp->GetDefaultEntryExpBmp( _eMode );
+}
+
+const Image& SvTreeListBox::GetDefaultCollapsedEntryBmp( BmpColorMode _eMode ) const
+{
+ return pImp->GetDefaultEntryColBmp( _eMode );
+}
+
+void SvTreeListBox::SetDefaultExpandedEntryBmp( const Image& aBmp, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ Size aSize = aBmp.GetSizePixel();
+ if( aSize.Width() > nContextBmpWidthMax )
+ nContextBmpWidthMax = (short)aSize.Width();
+ SetTabs();
+
+ pImp->SetDefaultEntryExpBmp( aBmp, _eMode );
+}
+
+void SvTreeListBox::SetDefaultCollapsedEntryBmp( const Image& aBmp, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ Size aSize = aBmp.GetSizePixel();
+ if( aSize.Width() > nContextBmpWidthMax )
+ nContextBmpWidthMax = (short)aSize.Width();
+ SetTabs();
+
+ pImp->SetDefaultEntryColBmp( aBmp, _eMode );
+}
+
+void SvTreeListBox::EnableCheckButton( SvLBoxButtonData* pData )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(!GetEntryCount(),"EnableCheckButton: Entry count != 0");
+ if( !pData )
+ nTreeFlags &= (~TREEFLAG_CHKBTN);
+ else
+ {
+ SetCheckButtonData( pData );
+ nTreeFlags |= TREEFLAG_CHKBTN;
+ pData->SetLink( LINK(this, SvTreeListBox, CheckButtonClick));
+ }
+
+ SetTabs();
+ if( IsUpdateMode() )
+ Invalidate();
+}
+
+void SvTreeListBox::SetCheckButtonData( SvLBoxButtonData* pData )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if ( pData )
+ pCheckButtonData = pData;
+}
+
+const Image& SvTreeListBox::GetDefaultExpandedNodeImage( BmpColorMode _eMode )
+{
+ return SvImpLBox::GetDefaultExpandedNodeImage( _eMode );
+}
+
+const Image& SvTreeListBox::GetDefaultCollapsedNodeImage( BmpColorMode _eMode )
+{
+ return SvImpLBox::GetDefaultCollapsedNodeImage( _eMode );
+}
+
+void SvTreeListBox::SetNodeBitmaps( const Image& rCollapsedNodeBmp, const Image& rExpandedNodeBmp, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SetExpandedNodeBmp( rExpandedNodeBmp, _eMode );
+ SetCollapsedNodeBmp( rCollapsedNodeBmp, _eMode );
+ SetTabs();
+}
+
+void SvTreeListBox::SetDontKnowNodeBitmap( const Image& rDontKnowBmp, BmpColorMode _eMode )
+{
+ pImp->SetDontKnowNodeBmp( rDontKnowBmp, _eMode );
+}
+
+BOOL SvTreeListBox::EditingEntry( SvLBoxEntry*, Selection& )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ return TRUE;
+}
+
+BOOL SvTreeListBox::EditedEntry( SvLBoxEntry* /*pEntry*/,const XubString& /*rNewText*/)
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ return TRUE;
+}
+
+void SvTreeListBox::EnableInplaceEditing( BOOL bOn )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBox::EnableInplaceEditing( bOn );
+}
+
+void SvTreeListBox::KeyInput( const KeyEvent& rKEvt )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ // unter OS/2 bekommen wir auch beim Editieren Key-Up/Down
+ if( IsEditingActive() )
+ return;
+
+ nImpFlags |= SVLBOX_IS_TRAVELSELECT;
+
+#ifdef OVDEBUG
+ USHORT nCode = rKEvt.GetKeyCode().GetCode();
+ switch ( nCode )
+ {
+ case KEY_F1:
+ {
+ SvLBoxEntry* pEntry = First();
+ pEntry = NextVisible( pEntry );
+ SetEntryText( pEntry, "SetEntryText" );
+ Sound::Beep();
+ }
+ break;
+ }
+#endif
+
+ if( !pImp->KeyInput( rKEvt ) )
+ SvLBox::KeyInput( rKEvt );
+
+ nImpFlags &= ~SVLBOX_IS_TRAVELSELECT;
+}
+
+void SvTreeListBox::RequestingChilds( SvLBoxEntry* pParent )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( !pParent->HasChilds() )
+ InsertEntry( String::CreateFromAscii("<dummy>"), pParent, FALSE, LIST_APPEND );
+}
+
+void SvTreeListBox::GetFocus()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->GetFocus();
+ SvLBox::GetFocus();
+
+ SvLBoxEntry* pEntry = FirstSelected();
+ if ( pEntry )
+ pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
+
+}
+
+void SvTreeListBox::LoseFocus()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->LoseFocus();
+ SvLBox::LoseFocus();
+}
+
+void SvTreeListBox::ModelHasCleared()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->pCursor = 0; //sonst Absturz beim Inplace-Editieren im GetFocus
+ delete pEdCtrl;
+ pEdCtrl = NULL;
+ pImp->Clear();
+ nFocusWidth = -1;
+
+ nContextBmpWidthMax = 0;
+ SetDefaultExpandedEntryBmp( GetDefaultExpandedEntryBmp() );
+ SetDefaultCollapsedEntryBmp( GetDefaultCollapsedEntryBmp() );
+
+ if( !(nTreeFlags & TREEFLAG_FIXEDHEIGHT ))
+ nEntryHeight = 0;
+ AdjustEntryHeight( GetFont() );
+ AdjustEntryHeight( GetDefaultExpandedEntryBmp() );
+ AdjustEntryHeight( GetDefaultCollapsedEntryBmp() );
+
+ SvLBox::ModelHasCleared();
+// if( IsUpdateMode() )
+// Invalidate();
+}
+
+void SvTreeListBox::ShowTargetEmphasis( SvLBoxEntry* pEntry, BOOL /* bShow */ )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->PaintDDCursor( pEntry );
+}
+
+void SvTreeListBox::ScrollOutputArea( short nDeltaEntries )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( !nDeltaEntries || !pImp->aVerSBar.IsVisible() )
+ return;
+
+ long nThumb = pImp->aVerSBar.GetThumbPos();
+ long nMax = pImp->aVerSBar.GetRange().Max();
+
+ NotifyBeginScroll();
+ if( nDeltaEntries < 0 )
+ {
+ // das Fenster nach oben verschieben
+ nDeltaEntries *= -1;
+ long nVis = pImp->aVerSBar.GetVisibleSize();
+ long nTemp = nThumb + nVis;
+ if( nDeltaEntries > (nMax - nTemp) )
+ nDeltaEntries = (short)(nMax - nTemp);
+ pImp->PageDown( (USHORT)nDeltaEntries );
+ }
+ else
+ {
+ if( nDeltaEntries > nThumb )
+ nDeltaEntries = (short)nThumb;
+ pImp->PageUp( (USHORT)nDeltaEntries );
+ }
+ pImp->SyncVerThumb();
+ NotifyEndScroll();
+}
+
+void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBox::SetSelectionMode( eSelectMode );
+ pImp->SetSelectionMode( eSelectMode );
+}
+
+void SvTreeListBox::SetDragDropMode( DragDropMode nDDMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBox::SetDragDropMode( nDDMode );
+ pImp->SetDragDropMode( nDDMode );
+}
+
+short SvTreeListBox::GetHeightOffset(const Image& rBmp, Size& aSizeLogic )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ short nOffset = 0;
+ aSizeLogic = rBmp.GetSizePixel();
+ if( GetEntryHeight() > aSizeLogic.Height() )
+ nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2;
+ return nOffset;
+}
+
+short SvTreeListBox::GetHeightOffset(const Font& /* rFont */, Size& aSizeLogic )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ short nOffset = 0;
+ aSizeLogic = Size(GetTextWidth('X'), GetTextHeight());
+ if( GetEntryHeight() > aSizeLogic.Height() )
+ nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2;
+ return nOffset;
+}
+
+void SvTreeListBox::SetEntryHeight( SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ short nHeight, nHeightMax=0;
+ USHORT nCount = pEntry->ItemCount();
+ USHORT nCur = 0;
+ SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
+ while( nCur < nCount )
+ {
+ SvLBoxItem* pItem = pEntry->GetItem( nCur );
+ nHeight = (short)(pItem->GetSize( pViewData, nCur ).Height());
+ if( nHeight > nHeightMax )
+ nHeightMax = nHeight;
+ nCur++;
+ }
+
+ if( nHeightMax > nEntryHeight )
+ {
+ nEntryHeight = nHeightMax;
+ SvLBox::SetFont( GetFont() );
+ pImp->SetEntryHeight( nHeightMax );
+ }
+}
+
+void SvTreeListBox::SetEntryHeight( short nHeight, BOOL bAlways )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+
+ if( bAlways || nHeight > nEntryHeight )
+ {
+ nEntryHeight = nHeight;
+ if( nEntryHeight )
+ nTreeFlags |= TREEFLAG_FIXEDHEIGHT;
+ else
+ nTreeFlags &= ~TREEFLAG_FIXEDHEIGHT;
+ SvLBox::SetFont( GetFont() );
+ pImp->SetEntryHeight( nHeight );
+ }
+}
+
+
+void SvTreeListBox::AdjustEntryHeight( const Image& rBmp )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ Size aSize;
+ GetHeightOffset( rBmp, aSize );
+ if( aSize.Height() > nEntryHeight )
+ {
+ nEntryHeight = (short)aSize.Height() + nEntryHeightOffs;
+ pImp->SetEntryHeight( nEntryHeight );
+ }
+}
+
+void SvTreeListBox::AdjustEntryHeight( const Font& rFont )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ Size aSize;
+ GetHeightOffset( rFont, aSize );
+ if( aSize.Height() > nEntryHeight )
+ {
+ nEntryHeight = (short)aSize.Height() + nEntryHeightOffs;
+ pImp->SetEntryHeight( nEntryHeight );
+ }
+}
+
+BOOL SvTreeListBox::Expand( SvLBoxEntry* pParent )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pHdlEntry = pParent;
+ BOOL bExpanded = FALSE;
+ USHORT nFlags;
+
+ if( pParent->HasChildsOnDemand() )
+ RequestingChilds( pParent );
+ if( pParent->HasChilds() )
+ {
+ nImpFlags |= SVLBOX_IS_EXPANDING;
+ if( ExpandingHdl() )
+ {
+ bExpanded = TRUE;
+ SvListView::Expand( pParent );
+ pImp->EntryExpanded( pParent );
+ pHdlEntry = pParent;
+ ExpandedHdl();
+ }
+ nFlags = pParent->GetFlags();
+ nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP;
+ nFlags |= SV_ENTRYFLAG_HAD_CHILDREN;
+ pParent->SetFlags( nFlags );
+ }
+ else
+ {
+ nFlags = pParent->GetFlags();
+ nFlags |= SV_ENTRYFLAG_NO_NODEBMP;
+ pParent->SetFlags( nFlags );
+ GetModel()->InvalidateEntry( pParent ); // neu zeichnen
+ }
+
+ // --> OD 2009-04-01 #i92103#
+ if ( bExpanded )
+ {
+ pImp->CallEventListeners( VCLEVENT_ITEM_EXPANDED, pParent );
+ }
+ // <--
+
+ return bExpanded;
+}
+
+BOOL SvTreeListBox::Collapse( SvLBoxEntry* pParent )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ nImpFlags &= ~SVLBOX_IS_EXPANDING;
+ pHdlEntry = pParent;
+ BOOL bCollapsed = FALSE;
+
+ if( ExpandingHdl() )
+ {
+ bCollapsed = TRUE;
+ pImp->CollapsingEntry( pParent );
+ SvListView::Collapse( pParent );
+ pImp->EntryCollapsed( pParent );
+ pHdlEntry = pParent;
+ ExpandedHdl();
+ }
+
+ // --> OD 2009-04-01 #i92103#
+ if ( bCollapsed )
+ {
+ pImp->CallEventListeners( VCLEVENT_ITEM_COLLAPSED, pParent );
+ }
+ // <--
+
+ return bCollapsed;
+}
+
+BOOL SvTreeListBox::Select( SvLBoxEntry* pEntry, BOOL bSelect )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(pEntry,"Select: Null-Ptr");
+ BOOL bRetVal = SvListView::Select( pEntry, bSelect );
+ DBG_ASSERT(IsSelected(pEntry)==bSelect,"Select failed");
+ if( bRetVal )
+ {
+ pImp->EntrySelected( pEntry, bSelect );
+ pHdlEntry = pEntry;
+ if( bSelect )
+ {
+ SelectHdl();
+ pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
+ }
+ else
+ DeselectHdl();
+ }
+ return bRetVal;
+}
+
+ULONG SvTreeListBox::SelectChilds( SvLBoxEntry* pParent, BOOL bSelect )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->DestroyAnchor();
+ ULONG nRet = 0;
+ if( !pParent->HasChilds() )
+ return 0;
+ USHORT nRefDepth = pModel->GetDepth( pParent );
+ SvLBoxEntry* pChild = FirstChild( pParent );
+ do {
+ nRet++;
+ Select( pChild, bSelect );
+ pChild = Next( pChild );
+ } while( pChild && pModel->GetDepth( pChild ) > nRefDepth );
+ return nRet;
+}
+
+void SvTreeListBox::SelectAll( BOOL bSelect, BOOL )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->SelAllDestrAnch(
+ bSelect,
+ TRUE, // Anker loeschen,
+ TRUE ); // auch bei SINGLE_SELECTION den Cursor deselektieren
+}
+
+void SvTreeListBox::ModelHasInsertedTree( SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ USHORT nRefDepth = pModel->GetDepth( (SvLBoxEntry*)pEntry );
+ SvLBoxEntry* pTmp = (SvLBoxEntry*)pEntry;
+ do
+ {
+ ImpEntryInserted( pTmp );
+ pTmp = Next( pTmp );
+ } while( pTmp && nRefDepth < pModel->GetDepth( pTmp ) );
+ pImp->TreeInserted( (SvLBoxEntry*)pEntry );
+}
+
+void SvTreeListBox::ModelHasInserted( SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ ImpEntryInserted( (SvLBoxEntry*)pEntry );
+ pImp->EntryInserted( (SvLBoxEntry*)pEntry );
+}
+
+void SvTreeListBox::ModelIsMoving(SvListEntry* pSource,
+ SvListEntry* /* pTargetParent */,
+ ULONG /* nChildPos */ )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->MovingEntry( (SvLBoxEntry*)pSource );
+}
+
+void SvTreeListBox::ModelHasMoved( SvListEntry* pSource )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->EntryMoved( (SvLBoxEntry*)pSource );
+}
+
+void SvTreeListBox::ModelIsRemoving( SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if(pEdEntry == pEntry)
+ pEdEntry = NULL;
+
+ pImp->RemovingEntry( (SvLBoxEntry*)pEntry );
+ NotifyRemoving( (SvLBoxEntry*)pEntry );
+}
+
+void SvTreeListBox::ModelHasRemoved( SvListEntry* /* pEntry */ )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->EntryRemoved();
+}
+
+void SvTreeListBox::SetCollapsedNodeBmp( const Image& rBmp, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ AdjustEntryHeight( rBmp );
+ pImp->SetCollapsedNodeBmp( rBmp, _eMode );
+}
+
+void SvTreeListBox::SetExpandedNodeBmp( const Image& rBmp, BmpColorMode _eMode )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ AdjustEntryHeight( rBmp );
+ pImp->SetExpandedNodeBmp( rBmp, _eMode );
+}
+
+
+void SvTreeListBox::SetFont( const Font& rFont )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ Font aTempFont( rFont );
+ aTempFont.SetTransparent( TRUE );
+ Control::SetFont( aTempFont );
+ AdjustEntryHeight( aTempFont );
+ // immer Invalidieren, sonst fallen wir
+ // bei SetEntryHeight auf die Nase
+ RecalcViewData();
+}
+
+
+void SvTreeListBox::Paint( const Rectangle& rRect )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBox::Paint( rRect );
+ if( nTreeFlags & TREEFLAG_RECALCTABS )
+ SetTabs();
+ pImp->Paint( rRect );
+}
+
+void SvTreeListBox::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->MouseButtonDown( rMEvt );
+}
+
+void SvTreeListBox::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->MouseButtonUp( rMEvt );
+}
+
+void SvTreeListBox::MouseMove( const MouseEvent& rMEvt )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->MouseMove( rMEvt );
+}
+
+
+void SvTreeListBox::SetUpdateMode( BOOL bUpdate )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->SetUpdateMode( bUpdate );
+}
+
+void SvTreeListBox::SetUpdateModeFast( BOOL bUpdate )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->SetUpdateModeFast( bUpdate );
+}
+
+void SvTreeListBox::SetSpaceBetweenEntries( short nOffsLogic )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( nOffsLogic != nEntryHeightOffs )
+ {
+ nEntryHeight = nEntryHeight - nEntryHeightOffs;
+ nEntryHeightOffs = (short)nOffsLogic;
+ nEntryHeight = nEntryHeight + nOffsLogic;
+ AdjustEntryHeight( GetFont() );
+ RecalcViewData();
+ pImp->SetEntryHeight( nEntryHeight );
+ }
+}
+
+void SvTreeListBox::SetCursor( SvLBoxEntry* pEntry, BOOL bForceNoSelect )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->SetCursor(pEntry, bForceNoSelect);
+}
+
+void SvTreeListBox::SetCurEntry( SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ pImp->SetCurEntry( pEntry );
+}
+
+Image SvTreeListBox::GetCollapsedNodeBmp( BmpColorMode _eMode ) const
+{
+ return pImp->GetCollapsedNodeBmp( _eMode );
+}
+
+Image SvTreeListBox::GetExpandedNodeBmp( BmpColorMode _eMode ) const
+{
+ return pImp->GetExpandedNodeBmp( _eMode );
+}
+
+Point SvTreeListBox::GetEntryPosition( SvLBoxEntry* pEntry ) const
+{
+ return pImp->GetEntryPosition( pEntry );
+}
+
+void SvTreeListBox::ShowEntry( SvLBoxEntry* pEntry )
+{
+ MakeVisible( pEntry );
+}
+
+void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry )
+{
+ pImp->MakeVisible(pEntry);
+}
+
+void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry, BOOL bMoveToTop )
+{
+ pImp->MakeVisible( pEntry, bMoveToTop );
+}
+
+void SvTreeListBox::ModelHasEntryInvalidated( SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ // die einzelnen Items des Entries reinitialisieren
+ SvLBox::ModelHasEntryInvalidated( pEntry );
+ // repainten
+ pImp->InvalidateEntry( (SvLBoxEntry*)pEntry );
+}
+
+void SvTreeListBox::EditItemText( SvLBoxEntry* pEntry, SvLBoxString* pItem,
+ const Selection& rSelection )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(pEntry&&pItem,"EditItemText: Bad params");
+ if( IsSelected( pEntry ))
+ {
+ pImp->ShowCursor( FALSE );
+ SvListView::Select( pEntry, FALSE );
+ PaintEntry( pEntry );
+ SvListView::Select( pEntry, TRUE );
+ pImp->ShowCursor( TRUE );
+ }
+ pEdEntry = pEntry;
+ pEdItem = pItem;
+ SvLBoxTab* pTab = GetTab( pEntry, pItem );
+ DBG_ASSERT(pTab,"EditItemText:Tab not found");
+
+ Size aItemSize( pItem->GetSize(this, pEntry) );
+ Point aPos = GetEntryPosition( pEntry );
+ aPos.Y() += ( nEntryHeight - aItemSize.Height() ) / 2;
+ aPos.X() = GetTabPos( pEntry, pTab );
+ long nOutputWidth = pImp->GetOutputSize().Width();
+ Size aSize( nOutputWidth - aPos.X(), aItemSize.Height() );
+ USHORT nPos = aTabs.GetPos( pTab );
+ if( nPos+1 < aTabs.Count() )
+ {
+ SvLBoxTab* pRightTab = (SvLBoxTab*)aTabs.GetObject( nPos + 1 );
+ long nRight = GetTabPos( pEntry, pRightTab );
+ if( nRight <= nOutputWidth )
+ aSize.Width() = nRight - aPos.X();
+ }
+ Point aOrigin( GetMapMode().GetOrigin() );
+ aPos += aOrigin; // in Win-Koord umrechnen
+ aSize.Width() -= aOrigin.X();
+ Rectangle aRect( aPos, aSize );
+#ifdef OS2
+ // Platz lassen fuer WB_BORDER
+ aRect.Left() -= 2;
+ aRect.Top() -= 3;
+ aRect.Bottom() += 3;
+#endif
+ EditText( pItem->GetText(), aRect, rSelection );
+}
+
+void SvTreeListBox::CancelEditing()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBox::CancelTextEditing();
+}
+
+void SvTreeListBox::EditEntry( SvLBoxEntry* pEntry )
+{
+ pImp->aEditClickPos = Point( -1, -1 );
+ ImplEditEntry( pEntry );
+}
+
+void SvTreeListBox::ImplEditEntry( SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( IsEditingActive() )
+ EndEditing();
+ if( !pEntry )
+ pEntry = GetCurEntry();
+ if( pEntry )
+ {
+ long nClickX = pImp->aEditClickPos.X();
+ bool bIsMouseTriggered = nClickX >= 0;
+
+ SvLBoxString* pItem = NULL;
+ USHORT nCount = pEntry->ItemCount();
+ for( USHORT i = 0 ; i < nCount ; i++ )
+ {
+ SvLBoxItem* pTmpItem = pEntry->GetItem( i );
+ if( pTmpItem->IsA() != SV_ITEM_ID_LBOXSTRING )
+ continue;
+
+ SvLBoxTab* pTab = GetTab( pEntry, pTmpItem );
+ long nTabPos = pTab->GetPos();
+ long nNextTabPos = -1;
+ if( i < nCount - 1 )
+ {
+ SvLBoxItem* pNextItem = pEntry->GetItem( i + 1 );
+ SvLBoxTab* pNextTab = GetTab( pEntry, pNextItem );
+ nNextTabPos = pNextTab->GetPos();
+ }
+
+ if( pTab && pTab->IsEditable() )
+ {
+ if( !bIsMouseTriggered || (nClickX > nTabPos && (nNextTabPos == -1 || nClickX < nNextTabPos ) ) )
+ {
+ pItem = static_cast<SvLBoxString*>( pTmpItem );
+ break;
+ }
+ }
+ }
+
+ Selection aSel( SELECTION_MIN, SELECTION_MAX );
+ if( pItem && EditingEntry( pEntry, aSel ) )
+ {
+ SelectAll( FALSE );
+ MakeVisible( pEntry );
+ EditItemText( pEntry, pItem, aSel );
+ }
+ }
+}
+
+sal_Bool SvTreeListBox::AreChildrenTransient() const
+{
+ return pImp->AreChildrenTransient();
+}
+
+void SvTreeListBox::SetChildrenNotTransient()
+{
+ pImp->SetChildrenNotTransient();
+}
+
+void SvTreeListBox::EditedText( const XubString& rStr )
+
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if(pEdEntry) // we have to check if this entry is null that means that it is removed while editing
+ {
+ Point aPos = GetEntryPosition( pEdEntry );
+ if( EditedEntry( pEdEntry, rStr ) )
+ {
+ ((SvLBoxString*)pEdItem)->SetText( pEdEntry, rStr );
+ pModel->InvalidateEntry( pEdEntry );
+ }
+ //if( GetSelectionMode() == SINGLE_SELECTION )
+ //{
+ if( GetSelectionCount() == 0 )
+ Select( pEdEntry );
+ if( GetSelectionMode() == MULTIPLE_SELECTION && !GetCurEntry() )
+ SetCurEntry( pEdEntry );
+ //}
+ }
+}
+
+void SvTreeListBox::EditingRequest( SvLBoxEntry* pEntry, SvLBoxItem* pItem,
+ const Point& )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( IsEditingActive() )
+ EndEditing();
+ if( pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
+ {
+ Selection aSel( SELECTION_MIN, SELECTION_MAX );
+ if( EditingEntry( pEntry, aSel ) )
+ {
+ SelectAll( FALSE );
+ EditItemText( pEntry, (SvLBoxString*)pItem, aSel );
+ }
+ }
+}
+
+
+
+SvLBoxEntry* SvTreeListBox::GetDropTarget( const Point& rPos )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ // Scrollen
+ if( rPos.Y() < 12 )
+ {
+ SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, FALSE );
+ ScrollOutputArea( +1 );
+ }
+ else
+ {
+ Size aSize( pImp->GetOutputSize() );
+ if( rPos.Y() > aSize.Height() - 12 )
+ {
+ SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, FALSE );
+ ScrollOutputArea( -1 );
+ }
+ }
+
+ SvLBoxEntry* pTarget = pImp->GetEntry( rPos );
+ // bei Droppen in leere Flaeche -> den letzten Eintrag nehmen
+ if( !pTarget )
+ return (SvLBoxEntry*)LastVisible();
+ else if( (GetDragDropMode() & SV_DRAGDROP_ENABLE_TOP) &&
+ pTarget == First() && rPos.Y() < 6 )
+ return 0;
+
+ return pTarget;
+}
+
+
+SvLBoxEntry* SvTreeListBox::GetEntry( const Point& rPos, BOOL bHit ) const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBoxEntry* pEntry = pImp->GetEntry( rPos );
+ if( pEntry && bHit )
+ {
+ long nLine = pImp->GetEntryLine( pEntry );
+ if( !(pImp->EntryReallyHit( pEntry, rPos, nLine)) )
+ return 0;
+ }
+ return pEntry;
+}
+
+SvLBoxEntry* SvTreeListBox::GetCurEntry() const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ return pImp->GetCurEntry();
+}
+
+void SvTreeListBox::SetWindowBits( WinBits nWinStyle )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ nWindowStyle = nWinStyle;
+ nTreeFlags |= TREEFLAG_RECALCTABS;
+ if( nWinStyle & WB_SORT )
+ {
+ GetModel()->SetSortMode( SortAscending );
+ GetModel()->SetCompareHdl( LINK(this,SvTreeListBox,DefaultCompare));
+ }
+ else
+ {
+ GetModel()->SetSortMode( SortNone );
+ GetModel()->SetCompareHdl( Link() );
+ }
+#ifdef OS2
+ nWinStyle |= WB_VSCROLL;
+#endif
+ pImp->SetWindowBits( nWinStyle );
+ pImp->Resize();
+ Invalidate();
+}
+
+void SvTreeListBox::PaintEntry( SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(pEntry,"PaintEntry:No Entry");
+ if( pEntry )
+ pImp->PaintEntry( pEntry );
+}
+
+void SvTreeListBox::InvalidateEntry( SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(pEntry,"InvalidateEntry:No Entry");
+ if( pEntry )
+ {
+ GetModel()->InvalidateEntry( pEntry );
+ // pImp->InvalidateEntry( pEntry );
+ }
+}
+
+
+long SvTreeListBox::PaintEntry(SvLBoxEntry* pEntry,long nLine,USHORT nTabFlags)
+{
+ return PaintEntry1(pEntry,nLine,nTabFlags);
+}
+
+#define SV_TAB_BORDER 8
+
+long SvTreeListBox::PaintEntry1(SvLBoxEntry* pEntry,long nLine,USHORT nTabFlags,
+ BOOL bHasClipRegion )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+
+ Rectangle aRect; // multi purpose
+
+ BOOL bHorSBar = pImp->HasHorScrollBar();
+ PreparePaint( pEntry );
+
+ // #97680# ------------------
+ pImp->UpdateContextBmpWidthMax( pEntry );
+
+ if( nTreeFlags & TREEFLAG_RECALCTABS )
+ SetTabs();
+
+ short nTempEntryHeight = GetEntryHeight();
+ long nWidth = pImp->GetOutputSize().Width();
+
+ // wurde innerhalb des PreparePaints die horizontale ScrollBar
+ // angeschaltet? Wenn ja, muss die ClipRegion neu gesetzt werden
+ if( !bHorSBar && pImp->HasHorScrollBar() )
+ SetClipRegion( Region(pImp->GetClipRegionRect()) );
+
+ Point aEntryPos( GetMapMode().GetOrigin() );
+ aEntryPos.X() *= -1; // Umrechnung Dokumentkoord.
+ long nMaxRight = nWidth + aEntryPos.X() - 1;
+
+ Color aBackupTextColor( GetTextColor() );
+ Font aBackupFont( GetFont() );
+ Color aBackupColor = GetFillColor();
+
+ bool bCurFontIsSel = false;
+ BOOL bInUse = pEntry->HasInUseEmphasis();
+ // wenn eine ClipRegion von aussen gesetzt wird, dann
+ // diese nicht zuruecksetzen
+ BOOL bResetClipRegion = !bHasClipRegion;
+ BOOL bHideSelection = ((nWindowStyle & WB_HIDESELECTION) && !HasFocus())!=0;
+ const StyleSettings& rSettings = GetSettings().GetStyleSettings();
+
+ Font aHighlightFont( GetFont() );
+ const Color aHighlightTextColor( rSettings.GetHighlightTextColor() );
+ aHighlightFont.SetColor( aHighlightTextColor );
+
+ Size aRectSize( 0, nTempEntryHeight );
+
+ if( !bHasClipRegion && nWindowStyle & WB_HSCROLL )
+ {
+ SetClipRegion( Region(pImp->GetClipRegionRect()) );
+ bHasClipRegion = TRUE;
+ }
+
+ SvViewDataEntry* pViewDataEntry = GetViewDataEntry( pEntry );
+
+ USHORT nTabCount = aTabs.Count();
+ USHORT nItemCount = pEntry->ItemCount();
+ USHORT nCurTab = 0;
+ USHORT nCurItem = 0;
+
+ while( nCurTab < nTabCount && nCurItem < nItemCount )
+ {
+ SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nCurTab );
+ USHORT nNextTab = nCurTab + 1;
+ SvLBoxTab* pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0;
+ SvLBoxItem* pItem = nCurItem < nItemCount ? pEntry->GetItem(nCurItem) : 0;
+
+ USHORT nFlags = pTab->nFlags;
+ Size aSize( pItem->GetSize( pViewDataEntry, nCurItem ));
+ long nTabPos = GetTabPos( pEntry, pTab );
+
+ long nNextTabPos;
+ if( pNextTab )
+ nNextTabPos = GetTabPos( pEntry, pNextTab );
+ else
+ {
+ nNextTabPos = nMaxRight;
+ if( nTabPos > nMaxRight )
+ nNextTabPos += 50;
+ }
+
+ long nX;
+ if( pTab->nFlags & SV_LBOXTAB_ADJUST_RIGHT )
+ //verhindern, das rechter Rand von der Tabtrennung abgeschnitten wird
+ nX = nTabPos + pTab->CalcOffset(aSize.Width(), (nNextTabPos-SV_TAB_BORDER-1) -nTabPos);
+ else
+ nX = nTabPos + pTab->CalcOffset(aSize.Width(), nNextTabPos-nTabPos);
+
+ if( nFlags & nTabFlags )
+ {
+ if( !bHasClipRegion && nX + aSize.Width() >= nMaxRight )
+ {
+ SetClipRegion( Region(pImp->GetClipRegionRect()) );
+ bHasClipRegion = TRUE;
+ }
+ aEntryPos.X() = nX;
+ aEntryPos.Y() = nLine;
+
+ // Hintergrund-Muster & Farbe bestimmen
+
+ Wallpaper aWallpaper = GetBackground();
+
+ int bSelTab = nFlags & SV_LBOXTAB_SHOW_SELECTION;
+ USHORT nItemType = pItem->IsA();
+
+ if ( pViewDataEntry->IsSelected() && bSelTab && !pViewDataEntry->IsCursored() )
+ {
+ Color aNewWallColor = rSettings.GetHighlightColor();
+ if ( !bInUse || nItemType != SV_ITEM_ID_LBOXCONTEXTBMP )
+ {
+ // if the face color is bright then the deactive color is also bright
+ // -> so you can't see any deactive selection
+ if ( bHideSelection && !rSettings.GetFaceColor().IsBright() &&
+ aWallpaper.GetColor().IsBright() != rSettings.GetDeactiveColor().IsBright() )
+ aNewWallColor = rSettings.GetDeactiveColor();
+ // set font color to highlight
+ if ( !bCurFontIsSel )
+ {
+ SetTextColor( aHighlightTextColor );
+ SetFont( aHighlightFont );
+ bCurFontIsSel = true;
+ }
+ }
+ aWallpaper.SetColor( aNewWallColor );
+ }
+ else // keine Selektion
+ {
+ if( bInUse && nItemType == SV_ITEM_ID_LBOXCONTEXTBMP )
+ aWallpaper.SetColor( rSettings.GetFieldColor() );
+ else if( bCurFontIsSel )
+ {
+ bCurFontIsSel = false;
+ SetTextColor( aBackupTextColor );
+ SetFont( aBackupFont );
+ }
+ }
+
+ // Hintergrund zeichnen
+ if( !(nTreeFlags & TREEFLAG_USESEL))
+ {
+ // nur den Bereich zeichnen, den das Item einnimmt
+ aRectSize.Width() = aSize.Width();
+ aRect.SetPos( aEntryPos );
+ aRect.SetSize( aRectSize );
+ }
+ else
+ {
+ // vom aktuellen bis zum naechsten Tab zeichnen
+ if( nCurTab != 0 )
+ aRect.Left() = nTabPos;
+ else
+ // beim nullten Tab immer ab Spalte 0 zeichnen
+ // (sonst Probleme bei Tabs mit Zentrierung)
+ aRect.Left() = 0;
+ aRect.Top() = nLine;
+ aRect.Bottom() = nLine + nTempEntryHeight - 1;
+ if( pNextTab )
+ {
+ long nRight;
+ nRight = GetTabPos(pEntry,pNextTab)-1;
+ if( nRight > nMaxRight )
+ nRight = nMaxRight;
+ aRect.Right() = nRight;
+ }
+ else
+ aRect.Right() = nMaxRight;
+ }
+ // bei anwenderdefinierter Selektion, die bei einer Tabposition
+ // groesser 0 beginnt den Hintergrund des 0.ten Items nicht
+ // fuellen, da sonst z.B. TablistBoxen mit Linien nicht
+ // realisiert werden koennen.
+ if( !(nCurTab==0 && (nTreeFlags & TREEFLAG_USESEL) && nFirstSelTab) )
+ {
+ SetFillColor( aWallpaper.GetColor() );
+ // Bei kleinen hor. Resizes tritt dieser Fall auf
+ if( aRect.Left() < aRect.Right() )
+ DrawRect( aRect );
+ }
+ // Item zeichnen
+ // vertikal zentrieren
+ aEntryPos.Y() += ( nTempEntryHeight - aSize.Height() ) / 2;
+ pItem->Paint( aEntryPos, *this, pViewDataEntry->GetFlags(), pEntry );
+
+ // Trennungslinie zwischen Tabs
+ if( pNextTab && pItem->IsA() == SV_ITEM_ID_LBOXSTRING &&
+ // nicht am rechten Fensterrand!
+ aRect.Right() < nMaxRight )
+ {
+ aRect.Left() = aRect.Right() - SV_TAB_BORDER;
+ DrawRect( aRect );
+ }
+
+ SetFillColor( aBackupColor );
+ }
+ nCurItem++;
+ nCurTab++;
+ }
+ if( pViewDataEntry->IsCursored() && !HasFocus() )
+ {
+ // Cursor-Emphasis
+ SetFillColor();
+ Color aOldLineColor = GetLineColor();
+ SetLineColor( Color( COL_BLACK ) );
+ aRect = GetFocusRect( pEntry, nLine );
+ aRect.Top()++;
+ aRect.Bottom()--;
+ DrawRect( aRect );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aBackupColor );
+ }
+
+ if( bCurFontIsSel )
+ {
+ SetTextColor( aBackupTextColor );
+ SetFont( aBackupFont );
+ }
+
+ USHORT nFirstDynTabPos;
+ SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab( nFirstDynTabPos );
+ long nDynTabPos = GetTabPos( pEntry, pFirstDynamicTab );
+ nDynTabPos += pImp->nNodeBmpTabDistance;
+ nDynTabPos += pImp->nNodeBmpWidth / 2;
+ nDynTabPos += 4; // 4 Pixel Reserve, damit die Node-Bitmap
+ // nicht zu nah am naechsten Tab steht
+
+ if( (!(pEntry->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP)) &&
+ (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab &&
+ ( pEntry->HasChilds() || pEntry->HasChildsOnDemand() ) )
+ {
+ // ersten festen Tab suchen, und pruefen ob die Node-Bitmap
+ // in ihn hineinragt
+ USHORT nNextTab = nFirstDynTabPos;
+ SvLBoxTab* pNextTab;
+ do
+ {
+ nNextTab++;
+ pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0;
+ } while( pNextTab && pNextTab->IsDynamic() );
+
+ if( !pNextTab || (GetTabPos( pEntry, pNextTab ) > nDynTabPos) )
+ {
+ if((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(pEntry) > 0)
+ {
+ Point aPos( GetTabPos(pEntry,pFirstDynamicTab), nLine );
+ aPos.X() += pImp->nNodeBmpTabDistance;
+
+ const Image* pImg = 0;
+ BmpColorMode eBitmapMode = BMP_COLOR_NORMAL;
+ if ( GetSettings().GetStyleSettings().GetHighContrastMode() )
+ eBitmapMode = BMP_COLOR_HIGHCONTRAST;
+
+ if( IsExpanded(pEntry) )
+ pImg = &pImp->GetExpandedNodeBmp( eBitmapMode );
+ else
+ {
+ if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
+ (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
+ pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
+ pImg = &pImp->GetDontKnowNodeBmp( eBitmapMode );
+ else
+ pImg = &pImp->GetCollapsedNodeBmp( eBitmapMode );
+ }
+ aPos.Y() += (nTempEntryHeight - pImg->GetSizePixel().Height()) / 2;
+
+ USHORT nStyle = 0;
+ if ( !IsEnabled() )
+ nStyle |= IMAGE_DRAW_DISABLE;
+
+ //native
+ BOOL bNativeOK = FALSE;
+ if ( IsNativeControlSupported( CTRL_LISTNODE, PART_ENTIRE_CONTROL) )
+ {
+ ImplControlValue aControlValue;
+ Rectangle aCtrlRegion( aPos, pImg->GetSizePixel() );
+ ControlState nState = 0;
+
+ if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED;
+
+ if ( IsExpanded(pEntry) )
+ aControlValue.setTristateVal( BUTTONVALUE_ON );//expanded node
+ else
+ {
+ if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
+ (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
+ pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
+ aControlValue.setTristateVal( BUTTONVALUE_DONTKNOW );//dont know
+ else
+ aControlValue.setTristateVal( BUTTONVALUE_OFF );//collapsed node
+ }
+
+ bNativeOK = DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL,
+ aCtrlRegion, nState, aControlValue, rtl::OUString() );
+ }
+
+ if( !bNativeOK) {
+ //non native
+ DrawImage( aPos, *pImg ,nStyle);
+ }
+ }
+ }
+ }
+
+
+ if( bHasClipRegion && bResetClipRegion )
+ SetClipRegion();
+ return 0; // nRowLen;
+}
+
+void SvTreeListBox::PreparePaint( SvLBoxEntry* )
+{
+}
+
+Rectangle SvTreeListBox::GetFocusRect( SvLBoxEntry* pEntry, long nLine )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ Size aSize;
+ Rectangle aRect;
+ aRect.Top() = nLine;
+ aSize.Height() = GetEntryHeight();
+
+ long nRealWidth = pImp->GetOutputSize().Width();
+ nRealWidth -= GetMapMode().GetOrigin().X();
+
+ USHORT nCurTab;
+ SvLBoxTab* pTab = GetFirstTab( SV_LBOXTAB_SHOW_SELECTION, nCurTab );
+ long nTabPos = 0;
+ if( pTab )
+ nTabPos = GetTabPos( pEntry, pTab );
+ long nNextTabPos;
+ if( pTab && nCurTab < aTabs.Count() - 1 )
+ {
+ SvLBoxTab* pNextTab = (SvLBoxTab*)aTabs.GetObject( nCurTab + 1 );
+ nNextTabPos = GetTabPos( pEntry, pNextTab );
+ }
+ else
+ {
+ nNextTabPos = nRealWidth;
+ if( nTabPos > nRealWidth )
+ nNextTabPos += 50;
+ }
+
+ BOOL bUserSelection = (BOOL)( nTreeFlags & TREEFLAG_USESEL ) != 0;
+ if( !bUserSelection )
+ {
+ if( pTab && nCurTab < pEntry->ItemCount() )
+ {
+ SvLBoxItem* pItem = pEntry->GetItem( nCurTab );
+ aSize.Width() = pItem->GetSize( this, pEntry ).Width();
+ if( !aSize.Width() )
+ aSize.Width() = 15;
+ long nX = nTabPos; //GetTabPos( pEntry, pTab );
+ // Ausrichtung
+ nX += pTab->CalcOffset( aSize.Width(), nNextTabPos - nTabPos );
+ aRect.Left() = nX;
+ // damit erster & letzter Buchstabe nicht angeknabbert werden
+ aRect.SetSize( aSize );
+ if( aRect.Left() > 0 )
+ aRect.Left()--;
+ aRect.Right()++;
+ }
+ }
+ else
+ {
+ // wenn erster SelTab != 0, dann muessen wir auch rechnen
+ if( nFocusWidth == -1 || nFirstSelTab )
+ {
+ USHORT nLastTab;
+ SvLBoxTab* pLastTab = GetLastTab(SV_LBOXTAB_SHOW_SELECTION,nLastTab);
+ nLastTab++;
+ if( nLastTab < aTabs.Count() ) // gibts noch einen ?
+ pLastTab = (SvLBoxTab*)aTabs.GetObject( nLastTab );
+ else
+ pLastTab = 0; // ueber gesamte Breite selektieren
+ aSize.Width() = pLastTab ? pLastTab->GetPos() : 0x0fffffff;
+ nFocusWidth = (short)aSize.Width();
+ if( pTab )
+ nFocusWidth = nFocusWidth - (short)nTabPos; //pTab->GetPos();
+ }
+ else
+ {
+ aSize.Width() = nFocusWidth;
+ if( pTab )
+ {
+ if( nCurTab )
+ aSize.Width() += nTabPos;
+ else
+ aSize.Width() += pTab->GetPos(); // Tab0 immer ab ganz links
+ }
+ }
+ // wenn Sel. beim nullten Tab anfaengt, dann ab Spalte 0 sel. zeichnen
+ if( nCurTab != 0 )
+ {
+ aRect.Left() = nTabPos;
+ aSize.Width() -= nTabPos;
+ }
+ aRect.SetSize( aSize );
+ }
+ // rechten Rand anpassen wg. Clipping
+ if( aRect.Right() >= nRealWidth )
+ {
+ aRect.Right() = nRealWidth-1;
+ nFocusWidth = (short)aRect.GetWidth();
+ }
+ return aRect;
+}
+
+
+long SvTreeListBox::GetTabPos( SvLBoxEntry* pEntry, SvLBoxTab* pTab)
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(pTab,"No Tab");
+ long nPos = pTab->GetPos();
+ if( pTab->IsDynamic() )
+ {
+ USHORT nDepth = pModel->GetDepth( pEntry );
+ nDepth = nDepth * (USHORT)nIndent;
+ nPos += (long)nDepth;
+ }
+ return nPos;
+}
+
+SvLBoxItem* SvTreeListBox::GetItem_Impl( SvLBoxEntry* pEntry, long nX,
+ SvLBoxTab** ppTab, USHORT nEmptyWidth )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBoxItem* pItemClicked = 0;
+ USHORT nTabCount = aTabs.Count();
+ USHORT nItemCount = pEntry->ItemCount();
+ SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0);
+ SvLBoxItem* pItem = pEntry->GetItem(0);
+ USHORT nNextItem = 1;
+ nX -= GetMapMode().GetOrigin().X();
+ long nRealWidth = pImp->GetOutputSize().Width();
+ nRealWidth -= GetMapMode().GetOrigin().X();
+
+ while( 1 )
+ {
+ SvLBoxTab* pNextTab=nNextItem<nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextItem) : 0;
+ long nStart = GetTabPos( pEntry, pTab );
+
+ long nNextTabPos;
+ if( pNextTab )
+ nNextTabPos = GetTabPos( pEntry, pNextTab );
+ else
+ {
+ nNextTabPos = nRealWidth;
+ if( nStart > nRealWidth )
+ nNextTabPos += 50;
+ }
+
+ Size aItemSize( pItem->GetSize(this, pEntry));
+ nStart += pTab->CalcOffset( aItemSize.Width(), nNextTabPos - nStart );
+ long nLen = aItemSize.Width();
+ if( pNextTab )
+ {
+ long nTabWidth = GetTabPos( pEntry, pNextTab ) - nStart;
+ if( nTabWidth < nLen )
+ nLen = nTabWidth;
+ }
+
+ if( !nLen )
+ nLen = nEmptyWidth;
+
+ if( nX >= nStart && nX < (nStart+nLen ) )
+ {
+ pItemClicked = pItem;
+ if( ppTab )
+ {
+ *ppTab = pTab;
+ break;
+ }
+ }
+ if( nNextItem >= nItemCount || nNextItem >= nTabCount)
+ break;
+ pTab = (SvLBoxTab*)aTabs.GetObject( nNextItem );
+ pItem = pEntry->GetItem( nNextItem );
+ nNextItem++;
+ }
+ return pItemClicked;
+}
+
+SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX,SvLBoxTab** ppTab)
+{
+ return GetItem_Impl( pEntry, nX, ppTab, 0 );
+}
+
+SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ SvLBoxTab* pDummyTab;
+ return GetItem_Impl( pEntry, nX, &pDummyTab, 0 );
+}
+
+SvLBoxItem* SvTreeListBox::GetFirstDynamicItem( SvLBoxEntry* pEntry )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+
+ SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0);
+ SvLBoxItem* pItem = pEntry->GetItem(0);
+ USHORT nTabCount = aTabs.Count();
+
+ USHORT nNext = 1;
+ while ( !pTab->IsDynamic() && nNext < nTabCount )
+ {
+ pItem = pEntry->GetItem( nNext );
+ pTab = (SvLBoxTab*)aTabs.GetObject( nNext );
+ nNext++;
+ }
+ return pItem;
+}
+
+void SvTreeListBox::AddTab(long nTabPos,USHORT nFlags,void* pUserData )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ nFocusWidth = -1;
+ SvLBoxTab* pTab = new SvLBoxTab( nTabPos, nFlags );
+ pTab->SetUserData( pUserData );
+ aTabs.Insert( pTab, aTabs.Count() );
+ if( nTreeFlags & TREEFLAG_USESEL )
+ {
+ USHORT nPos = aTabs.Count() - 1;
+ if( nPos >= nFirstSelTab && nPos <= nLastSelTab )
+ pTab->nFlags |= SV_LBOXTAB_SHOW_SELECTION;
+ else
+ // String-Items werden normalerweise immer selektiert
+ // deshalb explizit ausschalten
+ pTab->nFlags &= ~SV_LBOXTAB_SHOW_SELECTION;
+ }
+}
+
+
+
+SvLBoxTab* SvTreeListBox::GetFirstDynamicTab( USHORT& rPos ) const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ USHORT nCurTab = 0;
+ USHORT nTabCount = aTabs.Count();
+ while( nCurTab < nTabCount )
+ {
+ SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(nCurTab);
+ if( pTab->nFlags & SV_LBOXTAB_DYNAMIC )
+ {
+ rPos = nCurTab;
+ return pTab;
+ }
+ nCurTab++;
+ }
+ return 0;
+}
+
+SvLBoxTab* SvTreeListBox::GetFirstDynamicTab() const
+{
+ USHORT nDummy;
+ return GetFirstDynamicTab( nDummy );
+}
+
+SvLBoxTab* SvTreeListBox::GetTab( SvLBoxEntry* pEntry, SvLBoxItem* pItem) const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ USHORT nPos = pEntry->GetPos( pItem );
+ return (SvLBoxTab*)aTabs.GetObject( nPos );
+}
+
+void SvTreeListBox::ClearTabList()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ USHORT nTabCount = aTabs.Count();
+ while( nTabCount )
+ {
+ nTabCount--;
+ SvLBoxTab* pDelTab = (SvLBoxTab*)aTabs.GetObject( nTabCount );
+ delete pDelTab;
+ }
+ aTabs.Remove(0,aTabs.Count());
+}
+
+
+Size SvTreeListBox::GetOutputSizePixel() const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ Size aSize = pImp->GetOutputSize();
+ return aSize;
+}
+
+void SvTreeListBox::NotifyBeginScroll()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+}
+
+void SvTreeListBox::NotifyEndScroll()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+}
+
+void SvTreeListBox::NotifyScrolling( long )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+}
+
+void SvTreeListBox::NotifyScrolled()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ aScrolledHdl.Call( this );
+}
+
+void SvTreeListBox::NotifyInvalidating()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+}
+
+void SvTreeListBox::Invalidate( USHORT nInvalidateFlags )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( nFocusWidth == -1 )
+ // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt
+ pImp->RecalcFocusRect();
+ NotifyInvalidating();
+ SvLBox::Invalidate( nInvalidateFlags );
+ pImp->Invalidate();
+}
+
+void SvTreeListBox::Invalidate( const Rectangle& rRect, USHORT nInvalidateFlags )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if( nFocusWidth == -1 )
+ // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt
+ pImp->RecalcFocusRect();
+ NotifyInvalidating();
+ SvLBox::Invalidate( rRect, nInvalidateFlags );
+}
+
+
+void SvTreeListBox::SetHighlightRange( USHORT nStart, USHORT nEnd)
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+
+ USHORT nTemp;
+ nTreeFlags |= TREEFLAG_USESEL;
+ if( nStart > nEnd )
+ {
+ nTemp = nStart;
+ nStart = nEnd;
+ nEnd = nTemp;
+ }
+ // alle Tabs markieren, die im Bereich liegen
+ nTreeFlags |= TREEFLAG_RECALCTABS;
+ nFirstSelTab = nStart;
+ nLastSelTab = nEnd;
+ pImp->RecalcFocusRect();
+}
+
+void SvTreeListBox::RemoveHighlightRange()
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ nTreeFlags &= (~TREEFLAG_USESEL);
+ if( IsUpdateMode() )
+ Invalidate();
+}
+
+ULONG SvTreeListBox::GetAscInsertionPos(SvLBoxEntry*,SvLBoxEntry*)
+{
+ return LIST_APPEND;
+}
+
+ULONG SvTreeListBox::GetDescInsertionPos(SvLBoxEntry*,SvLBoxEntry*)
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ return LIST_APPEND;
+}
+
+Region SvTreeListBox::GetDragRegion() const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ Rectangle aRect;
+ SvLBoxEntry* pEntry = GetCurEntry();
+ if( pEntry )
+ {
+ Point aPos = GetEntryPosition( pEntry );
+ aRect = ((SvTreeListBox*)this)->GetFocusRect( pEntry, aPos.Y() );
+ }
+ Region aRegion( aRect );
+ return aRegion;
+}
+
+
+void SvTreeListBox::Command( const CommandEvent& rCEvt )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ if ( !pImp->Command( rCEvt ) )
+ SvLBox::Command( rCEvt );
+}
+
+
+void SvTreeListBox::RemoveParentKeepChilds( SvLBoxEntry* pParent )
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ DBG_ASSERT(pParent,"RemoveParentKeepChilds:No Parent");
+ SvLBoxEntry* pNewParent = GetParent( pParent );
+ if( pParent->HasChilds())
+ {
+ SvLBoxEntry* pChild = FirstChild( pParent );
+ while( pChild )
+ {
+ pModel->Move( pChild, pNewParent, LIST_APPEND );
+ pChild = FirstChild( pParent );
+ }
+ }
+ pModel->Remove( pParent );
+}
+
+SvLBoxTab* SvTreeListBox::GetFirstTab( USHORT nFlagMask, USHORT& rPos )
+{
+ USHORT nTabCount = aTabs.Count();
+ for( USHORT nPos = 0; nPos < nTabCount; nPos++ )
+ {
+ SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nPos );
+ if( (pTab->nFlags & nFlagMask) )
+ {
+ rPos = nPos;
+ return pTab;
+ }
+ }
+ rPos = 0xffff;
+ return 0;
+}
+
+SvLBoxTab* SvTreeListBox::GetLastTab( USHORT nFlagMask, USHORT& rTabPos )
+{
+ short nTabCount = (short)aTabs.Count();
+ if( nTabCount )
+ {
+ for( short nPos = nTabCount-1; nPos >= 0; nPos-- )
+ {
+ SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( (USHORT)nPos );
+ if( (pTab->nFlags & nFlagMask) )
+ {
+ rTabPos = (USHORT)nPos;
+ return pTab;
+ }
+ }
+ }
+ rTabPos = 0xffff;
+ return 0;
+}
+
+void SvTreeListBox::SetAddMode( BOOL bAdd )
+{
+ pImp->SetAddMode( bAdd );
+}
+
+BOOL SvTreeListBox::IsAddMode() const
+{
+ return pImp->IsAddMode();
+}
+
+void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt )
+{
+ if( !pImp->RequestHelp( rHEvt ) )
+ SvLBox::RequestHelp( rHEvt );
+}
+
+void SvTreeListBox::CursorMoved( SvLBoxEntry* )
+{
+}
+
+IMPL_LINK( SvTreeListBox, DefaultCompare, SvSortData*, pData )
+{
+ SvLBoxEntry* pLeft = (SvLBoxEntry*)(pData->pLeft );
+ SvLBoxEntry* pRight = (SvLBoxEntry*)(pData->pRight );
+ String aLeft( ((SvLBoxString*)(pLeft->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
+ String aRight( ((SvLBoxString*)(pRight->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
+ // #102891# ----------------
+ pImp->UpdateIntlWrapper();
+ return pImp->pIntlWrapper->getCaseCollator()->compareString( aLeft, aRight );
+}
+
+void SvTreeListBox::ModelNotification( USHORT nActionId, SvListEntry* pEntry1,
+ SvListEntry* pEntry2, ULONG nPos )
+{
+ if( nActionId == LISTACTION_CLEARING )
+ CancelTextEditing();
+
+ SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos );
+ switch( nActionId )
+ {
+ case LISTACTION_INSERTED:
+ {
+ SvLBoxEntry* pEntry( dynamic_cast< SvLBoxEntry* >( pEntry1 ) );
+ ENSURE_OR_BREAK( pEntry, "SvTreeListBox::ModelNotification: invalid entry!" );
+ SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
+ if ( !pBmpItem )
+ break;
+ const Image& rBitmap1( pBmpItem->GetBitmap1() );
+ const Image& rBitmap2( pBmpItem->GetBitmap2() );
+ short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) );
+ nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth );
+ if( nMaxWidth > nContextBmpWidthMax )
+ {
+ nContextBmpWidthMax = nMaxWidth;
+ SetTabs();
+ }
+ }
+ break;
+
+ case LISTACTION_RESORTING:
+ SetUpdateMode( FALSE );
+ break;
+
+ case LISTACTION_RESORTED:
+ // nach Sortierung den ersten Eintrag anzeigen, dabei die
+ // Selektion erhalten.
+ MakeVisible( (SvLBoxEntry*)pModel->First(), TRUE );
+ SetUpdateMode( TRUE );
+ break;
+
+ case LISTACTION_CLEARED:
+ if( IsUpdateMode() )
+ Update();
+ break;
+ }
+}
+
+// bei Aenderungen SetTabs beruecksichtigen
+long SvTreeListBox::GetTextOffset() const
+{
+ DBG_CHKTHIS(SvTreeListBox,0);
+ BOOL bHasButtons = (nWindowStyle & WB_HASBUTTONS)!=0;
+ BOOL bHasButtonsAtRoot = (nWindowStyle & (WB_HASLINESATROOT |
+ WB_HASBUTTONSATROOT))!=0;
+ long nStartPos = TAB_STARTPOS;
+ long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width();
+
+ long nCheckWidth = 0;
+ if( nTreeFlags & TREEFLAG_CHKBTN )
+ nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width();
+ long nCheckWidthDIV2 = nCheckWidth / 2;
+
+ long nContextWidth = nContextBmpWidthMax;
+ long nContextWidthDIV2 = nContextWidth / 2;
+
+ int nCase = NO_BUTTONS;
+ if( !(nTreeFlags & TREEFLAG_CHKBTN) )
+ {
+ if( bHasButtons )
+ nCase = NODE_BUTTONS;
+ }
+ else
+ {
+ if( bHasButtons )
+ nCase = NODE_AND_CHECK_BUTTONS;
+ else
+ nCase = CHECK_BUTTONS;
+ }
+
+ switch( nCase )
+ {
+ case NO_BUTTONS :
+ nStartPos += nContextWidthDIV2; // wg. Zentrierung
+ nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp
+ if( nContextBmpWidthMax )
+ nStartPos += 5; // Abstand Context-Bmp - Text
+ break;
+
+ case NODE_BUTTONS :
+ if( bHasButtonsAtRoot )
+ nStartPos += ( nIndent + (nNodeWidthPixel/2) );
+ else
+ nStartPos += nContextWidthDIV2;
+ nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp
+ if( nContextBmpWidthMax )
+ nStartPos += 5; // Abstand Context-Bmp - Text
+ break;
+
+ case NODE_AND_CHECK_BUTTONS :
+ if( bHasButtonsAtRoot )
+ nStartPos += ( nIndent + nNodeWidthPixel );
+ else
+ nStartPos += nCheckWidthDIV2;
+ nStartPos += nCheckWidthDIV2; // rechter Rand des CheckButtons
+ nStartPos += 3; // Abstand CheckButton Context-Bmp
+ nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp
+ nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp
+ // Abstand setzen nur wenn Bitmaps da
+ if( nContextBmpWidthMax )
+ nStartPos += 5; // Abstand Context-Bmp - Text
+ break;
+
+ case CHECK_BUTTONS :
+ nStartPos += nCheckWidthDIV2;
+ nStartPos += nCheckWidthDIV2; // rechter Rand CheckButton
+ nStartPos += 3; // Abstand CheckButton Context-Bmp
+ nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp
+ nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp
+ if( nContextBmpWidthMax )
+ nStartPos += 5; // Abstand Context-Bmp - Text
+ break;
+ }
+ return nStartPos;
+}
+
+void SvTreeListBox::EndSelection()
+{
+ pImp->EndSelection();
+}
+
+BOOL SvTreeListBox::IsNodeButton( const Point& rPos ) const
+{
+ SvLBoxEntry* pEntry = GetEntry( rPos );
+ if( pEntry )
+ return pImp->IsNodeButton( rPos, pEntry );
+ return FALSE;
+}
+
+void SvTreeListBox::RepaintScrollBars() const
+{
+ ((SvTreeListBox*)this)->pImp->RepaintScrollBars();
+}
+
+ScrollBar *SvTreeListBox::GetVScroll()
+{
+ return &((SvTreeListBox*)this)->pImp->aVerSBar;
+}
+
+ScrollBar *SvTreeListBox::GetHScroll()
+{
+ return &((SvTreeListBox*)this)->pImp->aHorSBar;
+}
+
+void SvTreeListBox::EnableAsyncDrag( BOOL b )
+{
+ pImp->EnableAsyncDrag( b );
+}
+
+SvLBoxEntry* SvTreeListBox::GetFirstEntryInView() const
+{
+ Point aPos;
+ return GetEntry( aPos );
+}
+
+SvLBoxEntry* SvTreeListBox::GetNextEntryInView(SvLBoxEntry* pEntry ) const
+{
+ SvLBoxEntry* pNext = (SvLBoxEntry*)NextVisible( pEntry );
+ if( pNext )
+ {
+ Point aPos( GetEntryPosition(pNext) );
+ const Size& rSize = pImp->GetOutputSize();
+ if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() )
+ return 0;
+ }
+ return pNext;
+}
+
+void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry )
+{
+ pImp->ShowFocusRect( pEntry );
+}
+
+void SvTreeListBox::SetTabBar( TabBar* pTabBar )
+{
+ pImp->SetTabBar( pTabBar );
+}
+
+void SvTreeListBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if( (rDCEvt.GetType()==DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ nEntryHeight = 0; // _together_ with TRUE of 1. par (bFont) of InitSettings() a zero-height
+ // forces complete recalc of heights!
+ InitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+ else
+ Control::DataChanged( rDCEvt );
+}
+
+void SvTreeListBox::InitSettings(BOOL bFont,BOOL bForeground,BOOL bBackground)
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ if( bFont )
+ {
+ Font aFont;
+ aFont = rStyleSettings.GetFieldFont();
+ aFont.SetColor( rStyleSettings.GetWindowTextColor() );
+ SetPointFont( aFont );
+ AdjustEntryHeight( aFont );
+ RecalcViewData();
+ }
+
+ if( bForeground || bFont )
+ {
+ SetTextColor( rStyleSettings.GetFieldTextColor() );
+ SetTextFillColor();
+ }
+
+ if( bBackground )
+ SetBackground( rStyleSettings.GetFieldColor() );
+
+ // always try to re-create default-SvLBoxButtonData
+ if( pCheckButtonData && pCheckButtonData->HasDefaultImages() )
+ pCheckButtonData->SetDefaultImages( this );
+}
+
+BOOL SvTreeListBox::IsCellFocusEnabled() const
+{
+ return pImp->IsCellFocusEnabled();
+}
+
+bool SvTreeListBox::SetCurrentTabPos( USHORT _nNewPos )
+{
+ return pImp->SetCurrentTabPos( _nNewPos );
+}
+
+USHORT SvTreeListBox::GetCurrentTabPos() const
+{
+ return pImp->GetCurrentTabPos();
+}
+
+void SvTreeListBox::InitStartEntry()
+{
+ if( !pImp->pStartEntry )
+ pImp->pStartEntry = GetModel()->First();
+}
+
+void SvTreeListBox::CancelPendingEdit()
+{
+ if( pImp )
+ pImp->CancelPendingEdit();
+}
+
+PopupMenu* SvTreeListBox::CreateContextMenu( void )
+{
+ return NULL;
+}
+
+void SvTreeListBox::ExcecuteContextMenuAction( USHORT )
+{
+ DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" );
+}
+
+void SvTreeListBox::EnableContextMenuHandling( void )
+{
+ DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
+
+ pImp->bContextMenuHandling = TRUE;
+}
+
+void SvTreeListBox::EnableContextMenuHandling( BOOL b )
+{
+ DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
+
+ pImp->bContextMenuHandling = b;
+}
+
+BOOL SvTreeListBox::IsContextMenuHandlingEnabled( void ) const
+{
+ DBG_ASSERT( pImp, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" );
+
+ return pImp->bContextMenuHandling;
+}
+
+void SvTreeListBox::EnableList( bool _bEnable )
+{
+ // call base class method
+ Window::Enable( _bEnable != false );
+ // then paint immediately
+ Paint( Rectangle( Point(), GetSizePixel() ) );
+}
+
+::com::sun::star::uno::Reference< XAccessible > SvTreeListBox::CreateAccessible()
+{
+ Window* pParent = GetAccessibleParentWindow();
+ DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" );
+
+ ::com::sun::star::uno::Reference< XAccessible > xAccessible;
+ if ( pParent )
+ {
+ ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
+ if ( xAccParent.is() )
+ {
+ // need to be done here to get the vclxwindow later on in the accessbile
+ ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface());
+ xAccessible = pImp->m_aFactoryAccess.getFactory().createAccessibleTreeListBox( *this, xAccParent );
+ }
+ }
+ return xAccessible;
+}
+
+void SvTreeListBox::FillAccessibleEntryStateSet( SvLBoxEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const
+{
+ DBG_ASSERT( pEntry, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" );
+
+ if ( pEntry->HasChildsOnDemand() || pEntry->HasChilds() )
+ {
+ rStateSet.AddState( AccessibleStateType::EXPANDABLE );
+ if ( IsExpanded( pEntry ) )
+ rStateSet.AddState( (sal_Int16)AccessibleStateType::EXPANDED );
+ }
+
+ if ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+ if ( IsEntryVisible( pEntry ) )
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ if ( IsSelected( pEntry ) )
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+}
+
+Rectangle SvTreeListBox::GetBoundingRect( SvLBoxEntry* pEntry )
+{
+ Point aPos = GetEntryPosition( pEntry );
+ Rectangle aRect = GetFocusRect( pEntry, aPos.Y() );
+ return aRect;
+}
+
+void SvTreeListBox::EnableCellFocus()
+{
+ pImp->EnableCellFocus();
+}
+
+void SvTreeListBox::CallImplEventListeners(ULONG nEvent, void* pData)
+{
+ CallEventListeners(nEvent, pData);
+}
+
+void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& rStateSet ) const
+{
+ SvLBox::FillAccessibleStateSet( rStateSet );
+}
diff --git a/svtools/source/contnr/templwin.cxx b/svtools/source/contnr/templwin.cxx
new file mode 100644
index 000000000000..61112f6669ca
--- /dev/null
+++ b/svtools/source/contnr/templwin.cxx
@@ -0,0 +1,2025 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+#include "templwin.hxx"
+#include "templdlg.hxx"
+#include <svtools/svtdata.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/dynamicmenuoptions.hxx>
+#include <unotools/extendedsecurityoptions.hxx>
+#include <svtools/xtextedt.hxx>
+#include <svl/inettype.hxx>
+#include "imagemgr.hxx"
+#include <svtools/miscopt.hxx>
+#include "templatefoldercache.hxx"
+#include "imgdef.hxx"
+#include "txtattr.hxx"
+#ifndef _SVTOOLS_HRC
+#include <svtools/svtools.hrc>
+#endif
+#ifndef _SVTOOLS_TEMPLWIN_HRC
+#include "templwin.hrc"
+#endif
+#ifndef _SVT_HELPID_HRC
+#include <svtools/helpid.hrc>
+#endif
+#include <unotools/pathoptions.hxx>
+#include <unotools/viewoptions.hxx>
+#include <unotools/ucbhelper.hxx>
+
+#include "unotools/configmgr.hxx"
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XDocumentTemplates.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/view/XPrintable.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/script/XTypeConverter.hpp>
+#include <com/sun/star/system/XSystemShellExecute.hpp>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <unotools/localedatawrapper.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <vcl/waitobj.hxx>
+#include <comphelper/processfactory.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/datetime.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/split.hxx>
+#include <vcl/msgbox.hxx>
+#include "DocumentInfoPreview.hxx"
+#include <vcl/mnemonic.hxx>
+
+#include <ucbhelper/content.hxx>
+#include <comphelper/string.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::view;
+using namespace svtools;
+
+extern ::rtl::OUString CreateExactSizeText_Impl( sal_Int64 nSize ); // fileview.cxx
+
+#define SPLITSET_ID 0
+#define COLSET_ID 1
+#define ICONWIN_ID 2
+#define FILEWIN_ID 3
+#define FRAMEWIN_ID 4
+
+#define ICON_POS_NEWDOC 0
+#define ICON_POS_TEMPLATES 1
+#define ICON_POS_MYDOCS 2
+#define ICON_POS_SAMPLES 3
+
+#define ASCII_STR(s) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(s) )
+#define VIEWSETTING_NEWFROMTEMPLATE ASCII_STR("NewFromTemplate")
+#define VIEWSETTING_SELECTEDGROUP ASCII_STR("SelectedGroup")
+#define VIEWSETTING_SELECTEDVIEW ASCII_STR("SelectedView")
+#define VIEWSETTING_SPLITRATIO ASCII_STR("SplitRatio")
+#define VIEWSETTING_LASTFOLDER ASCII_STR("LastFolder")
+
+struct FolderHistory
+{
+ String m_sURL;
+ ULONG m_nGroup;
+
+ FolderHistory( const String& _rURL, sal_Int32 _nGroup ) :
+ m_sURL( _rURL ), m_nGroup( _nGroup ) {}
+};
+
+DECLARE_LIST( HistoryList_Impl, FolderHistory* )
+DECLARE_LIST( NewDocList_Impl, ::rtl::OUString* )
+
+ODocumentInfoPreview::ODocumentInfoPreview( Window* pParent ,WinBits _nBits) : Window(pParent,WB_DIALOGCONTROL)
+{
+ m_pEditWin = new SvtExtendedMultiLineEdit_Impl(this,_nBits);
+ m_pEditWin->Show();
+ m_pEditWin->EnableCursor( FALSE );
+ m_pInfoTable = new SvtDocInfoTable_Impl();
+ // detect application language
+ m_aLocale = SvtPathOptions().GetLocale();
+}
+// -----------------------------------------------------------------------------
+ODocumentInfoPreview::~ODocumentInfoPreview()
+{
+ delete m_pEditWin;
+ delete m_pInfoTable;
+}
+// -----------------------------------------------------------------------------
+void ODocumentInfoPreview::Resize()
+{
+ Size aOutputSize( GetOutputSize() );
+ m_pEditWin->SetPosSizePixel( Point(0,0),aOutputSize);
+}
+// -----------------------------------------------------------------------------
+void ODocumentInfoPreview::Clear()
+{
+ m_pEditWin->Clear();
+}
+// -----------------------------------------------------------------------------
+
+void lcl_insertDateTimeEntry(SvtExtendedMultiLineEdit_Impl* i_pEditWin,
+ const ::rtl::OUString & i_rName, const util::DateTime & i_rUDT)
+{
+ DateTime aToolsDT =
+ DateTime( Date( i_rUDT.Day, i_rUDT.Month, i_rUDT.Year ),
+ Time( i_rUDT.Hours, i_rUDT.Minutes,
+ i_rUDT.Seconds, i_rUDT.HundredthSeconds ) );
+ if ( aToolsDT.IsValid() )
+ {
+ LocaleDataWrapper aLocaleWrapper(
+ ::comphelper::getProcessServiceFactory(),
+ Application::GetSettings().GetLocale() );
+ String aDateStr = aLocaleWrapper.getDate( aToolsDT );
+ aDateStr += String( RTL_CONSTASCII_STRINGPARAM(", ") );
+ aDateStr += aLocaleWrapper.getTime( aToolsDT );
+ i_pEditWin->InsertEntry( i_rName, aDateStr );
+ }
+}
+
+void ODocumentInfoPreview::fill(
+ const Reference< XDocumentProperties >& i_xDocProps, const String& i_rURL)
+{
+ if (!i_xDocProps.is()) throw RuntimeException();
+
+ ::rtl::OUString aStr;
+ m_pEditWin->SetAutoScroll( FALSE );
+
+ aStr = i_xDocProps->getTitle();
+ if (aStr.getLength()) {
+ m_pEditWin->InsertEntry( m_pInfoTable->GetString( DI_TITLE ), aStr );
+ }
+
+ aStr = i_xDocProps->getAuthor();
+ if (aStr.getLength()) {
+ m_pEditWin->InsertEntry( m_pInfoTable->GetString( DI_FROM ), aStr );
+ }
+
+ lcl_insertDateTimeEntry(m_pEditWin,
+ m_pInfoTable->GetString( DI_DATE ),
+ i_xDocProps->getCreationDate());
+
+ aStr = i_xDocProps->getModifiedBy();
+ if (aStr.getLength()) {
+ m_pEditWin->InsertEntry( m_pInfoTable->GetString(DI_MODIFIEDBY), aStr );
+ }
+
+ lcl_insertDateTimeEntry(m_pEditWin,
+ m_pInfoTable->GetString( DI_MODIFIEDDATE ),
+ i_xDocProps->getModificationDate());
+
+ aStr = i_xDocProps->getPrintedBy();
+ if (aStr.getLength()) {
+ m_pEditWin->InsertEntry( m_pInfoTable->GetString( DI_PRINTBY ), aStr );
+ }
+
+ lcl_insertDateTimeEntry(m_pEditWin,
+ m_pInfoTable->GetString( DI_PRINTDATE ),
+ i_xDocProps->getPrintDate());
+
+ aStr = i_xDocProps->getSubject();
+ if (aStr.getLength()) {
+ m_pEditWin->InsertEntry( m_pInfoTable->GetString( DI_THEME ), aStr );
+ }
+
+ aStr =
+ ::comphelper::string::convertCommaSeparated(i_xDocProps->getKeywords());
+ if (aStr.getLength()) {
+ m_pEditWin->InsertEntry( m_pInfoTable->GetString( DI_KEYWORDS ), aStr );
+ }
+
+ aStr = i_xDocProps->getDescription();
+ if (aStr.getLength()) {
+ m_pEditWin->InsertEntry( m_pInfoTable->GetString( DI_DESCRIPTION ),
+ aStr );
+ }
+
+ // size
+ if ( i_rURL.Len() > 0 )
+ {
+ ULONG nDocSize = ::utl::UCBContentHelper::GetSize( i_rURL );
+ m_pEditWin->InsertEntry(
+ m_pInfoTable->GetString( DI_SIZE ),
+ CreateExactSizeText_Impl( nDocSize ) );
+ }
+
+ // MIMEType
+ if ( i_rURL.Len() > 0 )
+ {
+ INetContentType eTypeID =
+ INetContentTypes::GetContentTypeFromURL( i_rURL );
+ if ( eTypeID != CONTENT_TYPE_APP_OCTSTREAM ) {
+ aStr = INetContentTypes::GetPresentation( eTypeID, m_aLocale );
+ } else {
+ aStr = SvFileInformationManager::GetDescription(
+ INetURLObject(i_rURL) );
+ }
+ if (aStr.getLength()) {
+ m_pEditWin->InsertEntry( m_pInfoTable->GetString( DI_MIMETYPE ),
+ aStr );
+ }
+ }
+
+ // user-defined (custom) properties
+ Reference< XPropertySet > xUserDefined(
+ i_xDocProps->getUserDefinedProperties(), UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xUDInfo = xUserDefined->getPropertySetInfo();
+ Sequence< Property > props = xUDInfo->getProperties();
+ for (sal_Int32 i = 0; i < props.getLength(); ++i) {
+ const ::rtl::OUString name = props[i].Name;
+ uno::Any aAny;
+ try {
+ aAny = xUserDefined->getPropertyValue(name);
+ uno::Reference < script::XTypeConverter > xConverter(
+ comphelper::getProcessServiceFactory()->createInstance(
+ ASCII_STR("com.sun.star.script.Converter")),
+ UNO_QUERY );
+ uno::Any aNew;
+ aNew = xConverter->convertToSimpleType( aAny, TypeClass_STRING );
+ if ((aNew >>= aStr) && aStr.getLength()) {
+ m_pEditWin->InsertEntry( name, aStr);
+ }
+ } catch (uno::Exception &) {
+ // ignore
+ }
+ }
+
+ m_pEditWin->SetSelection( Selection( 0, 0 ) );
+ m_pEditWin->SetAutoScroll( TRUE );
+}
+
+// -----------------------------------------------------------------------------
+void ODocumentInfoPreview::InsertEntry( const String& rTitle, const String& rValue )
+{
+ m_pEditWin->InsertEntry( rTitle, rValue);
+}
+// -----------------------------------------------------------------------------
+
+// class SvtDummyHeaderBar_Impl ------------------------------------------
+
+void SvtDummyHeaderBar_Impl::UpdateBackgroundColor()
+{
+ SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetWindowColor() ) );
+}
+
+SvtDummyHeaderBar_Impl::SvtDummyHeaderBar_Impl( Window* pPar ) : Window( pPar )
+{
+ SetSizePixel( HeaderBar( this, 0 ).CalcWindowSizePixel() ); // HeaderBar used only to calculate size
+
+ UpdateBackgroundColor();
+}
+
+SvtDummyHeaderBar_Impl::~SvtDummyHeaderBar_Impl()
+{
+}
+
+void SvtDummyHeaderBar_Impl::DataChanged( const DataChangedEvent& r )
+{
+ Window::DataChanged( r );
+ if( r.GetType() == DATACHANGED_SETTINGS )
+ UpdateBackgroundColor();
+}
+
+// class SvtIconWindow_Impl ----------------------------------------------
+
+SvtIconWindow_Impl::SvtIconWindow_Impl( Window* pParent ) :
+
+ Window( pParent, WB_DIALOGCONTROL | WB_BORDER | WB_3DLOOK ),
+
+ aDummyHeaderBar( this ),
+ aIconCtrl( this, WB_ICON | WB_NOCOLUMNHEADER | WB_HIGHLIGHTFRAME | /*!WB_NOSELECTION |*/
+ WB_NODRAGSELECTION | WB_TABSTOP | WB_CLIPCHILDREN ),
+ aNewDocumentRootURL( ASCII_STR("private:newdoc") ),
+ aMyDocumentsRootURL( SvtPathOptions().GetWorkPath() ),
+ aSamplesFolderRootURL( SvtPathOptions().
+ SubstituteVariable( String( ASCII_STR("$(insturl)/share/samples/$(vlang)") ) ) ),
+ nMaxTextLength( 0 )
+
+{
+ aDummyHeaderBar.Show();
+
+ aIconCtrl.SetAccessibleName( String( RTL_CONSTASCII_USTRINGPARAM("Groups") ) );
+ aIconCtrl.SetHelpId( HID_TEMPLATEDLG_ICONCTRL );
+ aIconCtrl.SetChoiceWithCursor( TRUE );
+ aIconCtrl.SetSelectionMode( SINGLE_SELECTION );
+ aIconCtrl.Show();
+
+ // detect the root URL of templates
+ Reference< XDocumentTemplates > xTemplates( ::comphelper::getProcessServiceFactory()->
+ createInstance( ASCII_STR("com.sun.star.frame.DocumentTemplates") ), UNO_QUERY );
+
+ if ( xTemplates.is() )
+ {
+ Reference < XContent > aRootContent = xTemplates->getContent();
+ Reference < XCommandEnvironment > aCmdEnv;
+
+ if ( aRootContent.is() )
+ aTemplateRootURL = aRootContent->getIdentifier()->getContentIdentifier();
+ }
+
+ // insert the categories
+ // "New Document"
+ sal_Bool bHiContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
+ Image aImage( SvtResId( bHiContrast ? IMG_SVT_NEWDOC_HC : IMG_SVT_NEWDOC ) );
+ nMaxTextLength = aImage.GetSizePixel().Width();
+ String aEntryStr = String( SvtResId( STR_SVT_NEWDOC ) );
+ SvxIconChoiceCtrlEntry* pEntry =
+ aIconCtrl.InsertEntry( aEntryStr, aImage, ICON_POS_NEWDOC );
+ pEntry->SetUserData( new String( aNewDocumentRootURL ) );
+ pEntry->SetQuickHelpText( String( SvtResId( STR_SVT_NEWDOC_HELP ) ) );
+ DBG_ASSERT( !pEntry->GetBoundRect().IsEmpty(), "empty rectangle" );
+ long nTemp = pEntry->GetBoundRect().GetSize().Width();
+ if (nTemp > nMaxTextLength)
+ nMaxTextLength = nTemp;
+
+ // "Templates"
+ if( aTemplateRootURL.Len() > 0 )
+ {
+ aEntryStr = String( SvtResId( STR_SVT_TEMPLATES ) );
+ pEntry = aIconCtrl.InsertEntry(
+ aEntryStr, Image( SvtResId( bHiContrast ? IMG_SVT_TEMPLATES_HC : IMG_SVT_TEMPLATES ) ), ICON_POS_TEMPLATES );
+ pEntry->SetUserData( new String( aTemplateRootURL ) );
+ pEntry->SetQuickHelpText( String( SvtResId( STR_SVT_TEMPLATES_HELP ) ) );
+ DBG_ASSERT( !pEntry->GetBoundRect().IsEmpty(), "empty rectangle" );
+ nTemp = pEntry->GetBoundRect().GetSize().Width();
+ if (nTemp > nMaxTextLength)
+ nMaxTextLength = nTemp;
+ }
+
+ // "My Documents"
+ aEntryStr = String( SvtResId( STR_SVT_MYDOCS ) );
+ pEntry = aIconCtrl.InsertEntry(
+ aEntryStr, Image( SvtResId( bHiContrast ? IMG_SVT_MYDOCS_HC : IMG_SVT_MYDOCS ) ), ICON_POS_MYDOCS );
+ pEntry->SetUserData( new String( aMyDocumentsRootURL ) );
+ pEntry->SetQuickHelpText( String( SvtResId( STR_SVT_MYDOCS_HELP ) ) );
+ DBG_ASSERT( !pEntry->GetBoundRect().IsEmpty(), "empty rectangle" );
+ nTemp = pEntry->GetBoundRect().GetSize().Width();
+ if( nTemp > nMaxTextLength )
+ nMaxTextLength = nTemp;
+
+ // "Samples"
+ aEntryStr = String( SvtResId( STR_SVT_SAMPLES ) );
+ pEntry = aIconCtrl.InsertEntry(
+ aEntryStr, Image( SvtResId( bHiContrast ? IMG_SVT_SAMPLES_HC : IMG_SVT_SAMPLES ) ), ICON_POS_SAMPLES );
+ pEntry->SetUserData( new String( aSamplesFolderRootURL ) );
+ pEntry->SetQuickHelpText( String( SvtResId( STR_SVT_SAMPLES_HELP ) ) );
+ DBG_ASSERT( !pEntry->GetBoundRect().IsEmpty(), "empty rectangle" );
+ nTemp = pEntry->GetBoundRect().GetSize().Width();
+ if (nTemp > nMaxTextLength)
+ nMaxTextLength = nTemp;
+
+ aIconCtrl.CreateAutoMnemonics();
+}
+
+SvtIconWindow_Impl::~SvtIconWindow_Impl()
+{
+ for ( ULONG i = 0; i < aIconCtrl.GetEntryCount(); ++i )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = aIconCtrl.GetEntry( i );
+ delete (String*)pEntry->GetUserData();
+ }
+}
+
+SvxIconChoiceCtrlEntry* SvtIconWindow_Impl::GetEntry( const String& rURL ) const
+{
+ SvxIconChoiceCtrlEntry* pEntry = NULL;
+ for ( ULONG i = 0; i < aIconCtrl.GetEntryCount(); ++i )
+ {
+ SvxIconChoiceCtrlEntry* pTemp = aIconCtrl.GetEntry( i );
+ String aURL( *( (String*)pTemp->GetUserData() ) );
+ if ( aURL == rURL )
+ {
+ pEntry = pTemp;
+ break;
+ }
+ }
+
+ return pEntry;
+}
+
+void SvtIconWindow_Impl::Resize()
+{
+ Size aWinSize = GetOutputSizePixel();
+ Size aHeaderSize = aDummyHeaderBar.GetSizePixel();
+ aHeaderSize.Width() = aWinSize.Width();
+ aDummyHeaderBar.SetSizePixel( aHeaderSize );
+ long nHeaderHeight = aHeaderSize.Height();
+ aWinSize.Height() -= nHeaderHeight;
+ aIconCtrl.SetPosSizePixel( Point( 0, nHeaderHeight ), aWinSize );
+ aIconCtrl.ArrangeIcons();
+}
+
+String SvtIconWindow_Impl::GetCursorPosIconURL() const
+{
+ String aURL;
+ SvxIconChoiceCtrlEntry* pEntry = aIconCtrl.GetCursor( );
+ if ( pEntry )
+ aURL = *static_cast<String*>(pEntry->GetUserData());
+ return aURL;
+
+}
+
+String SvtIconWindow_Impl::GetSelectedIconURL() const
+{
+ ULONG nPos;
+ SvxIconChoiceCtrlEntry* pEntry = aIconCtrl.GetSelectedEntry( nPos );
+ String aURL;
+ if ( pEntry )
+ aURL = *static_cast<String*>(pEntry->GetUserData());
+ return aURL;
+}
+
+String SvtIconWindow_Impl::GetSelectedIconText() const
+{
+ ULONG nPos;
+ return MnemonicGenerator::EraseAllMnemonicChars( aIconCtrl.GetSelectedEntry( nPos )->GetText() );
+}
+
+String SvtIconWindow_Impl::GetIconText( const String& rURL ) const
+{
+ String aText;
+ SvxIconChoiceCtrlEntry* pEntry = GetEntry( rURL );
+ if ( pEntry )
+ aText = MnemonicGenerator::EraseAllMnemonicChars( pEntry->GetText() );
+ return aText;
+}
+
+void SvtIconWindow_Impl::InvalidateIconControl()
+{
+ aIconCtrl.Invalidate();
+}
+
+ULONG SvtIconWindow_Impl::GetCursorPos() const
+{
+ ULONG nPos = ~ULONG(0);
+
+ SvxIconChoiceCtrlEntry* pCursorEntry = aIconCtrl.GetCursor( );
+ if ( pCursorEntry )
+ nPos = aIconCtrl.GetEntryListPos( pCursorEntry );
+
+ return nPos;
+}
+
+ULONG SvtIconWindow_Impl::GetSelectEntryPos() const
+{
+ ULONG nPos;
+ if ( !aIconCtrl.GetSelectedEntry( nPos ) )
+ nPos = ~ULONG(0);
+ return nPos;
+}
+
+void SvtIconWindow_Impl::SetCursorPos( ULONG nPos )
+{
+ SvxIconChoiceCtrlEntry* pEntry = aIconCtrl.GetEntry( nPos );
+ aIconCtrl.SetCursor( pEntry );
+ aIconCtrl.Invalidate();
+ aIconCtrl.Update();
+}
+
+void SvtIconWindow_Impl::SetFocus()
+{
+ aIconCtrl.GrabFocus();
+}
+
+long SvtIconWindow_Impl::CalcHeight() const
+{
+ // calculate the required height of the IconControl
+ long nHeight = 0;
+ ULONG nCount = aIconCtrl.GetEntryCount();
+ if ( nCount > 0 )
+ // bottom of the last icon
+ nHeight = aIconCtrl.GetEntry(nCount-1)->GetBoundRect().Bottom();
+
+ // + headerbar height
+ nHeight += aDummyHeaderBar.GetSizePixel().Height();
+
+ return nHeight;
+}
+
+sal_Bool SvtIconWindow_Impl::IsRootURL( const String& rURL ) const
+{
+ return rURL == aNewDocumentRootURL ||
+ rURL == aTemplateRootURL ||
+ rURL == aMyDocumentsRootURL ||
+ rURL == aSamplesFolderRootURL;
+}
+
+ULONG SvtIconWindow_Impl::GetRootPos( const String& rURL ) const
+{
+ ULONG nPos = ~ULONG(0);
+ if ( aNewDocumentRootURL.Match( rURL ) == STRING_MATCH )
+ nPos = 0;
+ else if ( aTemplateRootURL.Match( rURL ) == STRING_MATCH )
+ nPos = 1;
+ else if ( aMyDocumentsRootURL.Match( rURL ) == STRING_MATCH )
+ nPos = 2;
+ else if ( aSamplesFolderRootURL.Match( rURL ) == STRING_MATCH )
+ nPos = 3;
+ else if ( rURL.Match( aMyDocumentsRootURL ) == STRING_MATCH )
+ nPos = 2;
+ else
+ {
+ DBG_WARNING( "SvtIconWindow_Impl::GetRootPos(): invalid position" );
+ nPos = 2;
+ }
+
+ return nPos;
+}
+
+void SvtIconWindow_Impl::UpdateIcons( sal_Bool _bHiContrast )
+{
+ aIconCtrl.GetEntry( ICON_POS_NEWDOC )->SetImage(
+ Image( SvtResId( _bHiContrast ? IMG_SVT_NEWDOC_HC : IMG_SVT_NEWDOC ) ) );
+ aIconCtrl.GetEntry( ICON_POS_TEMPLATES )->SetImage(
+ Image( SvtResId( _bHiContrast ? IMG_SVT_TEMPLATES_HC : IMG_SVT_TEMPLATES ) ) );
+ aIconCtrl.GetEntry( ICON_POS_MYDOCS )->SetImage(
+ Image( SvtResId( _bHiContrast ? IMG_SVT_MYDOCS_HC : IMG_SVT_MYDOCS ) ) );
+ aIconCtrl.GetEntry( ICON_POS_SAMPLES )->SetImage(
+ Image( SvtResId( _bHiContrast ? IMG_SVT_SAMPLES_HC : IMG_SVT_SAMPLES ) ) );
+}
+/* -----------------27.11.2002 16:58-----------------
+ *
+ * --------------------------------------------------*/
+void SvtIconWindow_Impl::SelectFolder(sal_Int32 nFolderPosition)
+{
+ SvxIconChoiceCtrlEntry* pEntry = aIconCtrl.GetEntry( nFolderPosition );
+ if(pEntry)
+ {
+ aIconCtrl.SetCursor( pEntry );
+ aIconCtrl.GetClickHdl().Call(&aIconCtrl);
+ }
+}
+
+// class SvtFileViewWindow_Impl -----------------------------------------_
+
+SvtFileViewWindow_Impl::SvtFileViewWindow_Impl( SvtTemplateWindow* pParent ) :
+
+ Window( pParent, WB_DIALOGCONTROL | WB_TABSTOP | WB_BORDER | WB_3DLOOK ),
+
+ rParent ( *pParent ),
+ aFileView ( this, SvtResId( CTRL_FILEVIEW ), FILEVIEW_SHOW_TITLE ),
+ bIsTemplateFolder ( sal_False )
+
+{
+ aFileView.SetStyle( aFileView.GetStyle() | WB_DIALOGCONTROL | WB_TABSTOP );
+ aFileView.SetHelpId( HID_TEMPLATEDLG_FILEVIEW );
+ aFileView.Show();
+ aFileView.SetPosPixel( Point( 0, 0 ) );
+ aFileView.EnableAutoResize();
+ aFileView.EnableContextMenu( sal_False );
+ aFileView.EnableDelete( sal_False );
+}
+
+SvtFileViewWindow_Impl::~SvtFileViewWindow_Impl()
+{
+}
+
+void GetMenuEntry_Impl
+(
+ Sequence< PropertyValue >& aDynamicMenuEntry,
+ ::rtl::OUString& rTitle,
+ ::rtl::OUString& rURL,
+ ::rtl::OUString& rFrame,
+ ::rtl::OUString& rImageId
+)
+{
+ for ( int i = 0; i < aDynamicMenuEntry.getLength(); i++ )
+ {
+ if ( aDynamicMenuEntry[i].Name == DYNAMICMENU_PROPERTYNAME_URL )
+ aDynamicMenuEntry[i].Value >>= rURL;
+ else if ( aDynamicMenuEntry[i].Name == DYNAMICMENU_PROPERTYNAME_TITLE )
+ aDynamicMenuEntry[i].Value >>= rTitle;
+ else if ( aDynamicMenuEntry[i].Name == DYNAMICMENU_PROPERTYNAME_IMAGEIDENTIFIER )
+ aDynamicMenuEntry[i].Value >>= rImageId;
+ else if ( aDynamicMenuEntry[i].Name == DYNAMICMENU_PROPERTYNAME_TARGETNAME )
+ aDynamicMenuEntry[i].Value >>= rFrame;
+ }
+}
+Sequence< ::rtl::OUString > SvtFileViewWindow_Impl::GetNewDocContents() const
+{
+ NewDocList_Impl aNewDocs;
+ Sequence< Sequence< PropertyValue > > aDynamicMenuEntries;
+ aDynamicMenuEntries = SvtDynamicMenuOptions().GetMenu( E_NEWMENU );
+
+ ::rtl::OUString aTitle;
+ ::rtl::OUString aURL;
+ ::rtl::OUString aImageURL;
+ ::rtl::OUString aTargetFrame;
+
+ UINT32 i, nCount = aDynamicMenuEntries.getLength();
+ ::rtl::OUString sSeparator( ASCII_STR("private:separator") );
+ ::rtl::OUString sSlotURL( ASCII_STR("slot:5500") );
+
+ for ( i = 0; i < nCount; ++i )
+ {
+ GetMenuEntry_Impl( aDynamicMenuEntries[i], aTitle, aURL, aTargetFrame, aImageURL );
+
+ if ( aURL == sSeparator || aURL == sSlotURL )
+ continue;
+ else
+ {
+ // title
+ String aRow = MnemonicGenerator::EraseAllMnemonicChars( String( aTitle ) );
+ aRow += '\t';
+ // no type
+ aRow += '\t';
+ // no size
+ aRow += '\t';
+ // no date
+ aRow += '\t';
+ // url
+ aRow += String( aURL );
+ aRow += '\t';
+ // folder == false
+ aRow += '0';
+ // image url?
+ if ( aImageURL.getLength() > 0 )
+ {
+ aRow += '\t';
+ aRow += String( aImageURL );
+ }
+
+ ::rtl::OUString* pRow = new ::rtl::OUString( aRow );
+ aNewDocs.Insert( pRow, LIST_APPEND );
+ }
+ }
+
+ nCount = aNewDocs.Count();
+ Sequence < ::rtl::OUString > aRet( nCount );
+ ::rtl::OUString* pRet = aRet.getArray();
+ for ( i = 0; i < nCount; ++i )
+ {
+ ::rtl::OUString* pNewDoc = aNewDocs.GetObject(i);
+ pRet[i] = *( pNewDoc );
+ delete pNewDoc;
+ }
+
+ return aRet;
+}
+
+void SvtFileViewWindow_Impl::Resize()
+{
+ Size aWinSize = GetOutputSizePixel();
+
+ static int x = 0;
+ static int y = 0;
+
+ aWinSize.nA += x;
+ aWinSize.nB += y;
+ aFileView.SetSizePixel( aWinSize );
+}
+
+String SvtFileViewWindow_Impl::GetSelectedFile() const
+{
+ return aFileView.GetCurrentURL();
+}
+
+void SvtFileViewWindow_Impl::OpenFolder( const String& rURL )
+{
+ aFolderURL = rURL;
+
+ rParent.SetPrevLevelButtonState( rURL );
+
+ aFileView.SetUrlFilter( &aURLFilter );
+
+ INetProtocol eProt = INetURLObject( rURL ).GetProtocol();
+ bIsTemplateFolder = ( eProt == INET_PROT_VND_SUN_STAR_HIER );
+ bool isNewDocumentFolder = ( eProt == INET_PROT_PRIVATE );
+
+ aURLFilter.enableFilter( !bIsTemplateFolder && !isNewDocumentFolder );
+
+ if ( isNewDocumentFolder )
+ {
+ aFileView.EnableNameReplacing( sal_False );
+ aFileView.Initialize( GetNewDocContents() );
+ }
+ else
+ {
+ xub_StrLen nSampFoldLen = aSamplesFolderURL.Len();
+ aFileView.EnableNameReplacing(
+ nSampFoldLen && rURL.CompareTo( aSamplesFolderURL, nSampFoldLen ) == COMPARE_EQUAL );
+ aFileView.Initialize( rURL, String(), NULL );
+ }
+ aNewFolderLink.Call( this );
+}
+
+sal_Bool SvtFileViewWindow_Impl::HasPreviousLevel( String& rURL ) const
+{
+ INetURLObject aViewObj( aFileView.GetViewURL() );
+ INetURLObject aRootObj( aCurrentRootURL );
+ INetURLObject aMyDocObj( aMyDocumentsURL );
+
+ return ( ( aViewObj != aRootObj || aRootObj == aMyDocObj ) && aFileView.GetParentURL( rURL ) );
+}
+
+String SvtFileViewWindow_Impl::GetFolderTitle() const
+{
+ String aTitle;
+ ::utl::UCBContentHelper::GetTitle( aFolderURL, aTitle );
+ return aTitle;
+}
+
+void SvtFileViewWindow_Impl::SetFocus()
+{
+ aFileView.SetFocus();
+}
+
+// class SvtDocInfoTable_Impl --------------------------------------------
+
+SvtDocInfoTable_Impl::SvtDocInfoTable_Impl() :
+
+ ResStringArray( SvtResId( STRARY_SVT_DOCINFO ) )
+
+{
+}
+// -----------------------------------------------------------------------------
+// class SvtExtendedMultiLineEdit_Impl --------------------------------------------
+SvtExtendedMultiLineEdit_Impl::SvtExtendedMultiLineEdit_Impl( Window* pParent,WinBits _nBits ) :
+
+ ExtMultiLineEdit( pParent, _nBits )
+
+{
+ SetLeftMargin( 10 );
+}
+// -----------------------------------------------------------------------------
+void SvtExtendedMultiLineEdit_Impl::InsertEntry( const String& rTitle, const String& rValue )
+{
+ String aText( '\n' );
+ aText += rTitle;
+ aText += ':';
+ InsertText( aText );
+ ULONG nPara = GetParagraphCount() - 1;
+ SetAttrib( TextAttribFontWeight( WEIGHT_BOLD ), nPara, 0, aText.Len() );
+
+ aText = '\n';
+ aText += rValue;
+ InsertText( aText );
+ nPara = GetParagraphCount() - 1;
+ SetAttrib( TextAttribFontWeight( WEIGHT_NORMAL ), nPara, 0, aText.Len() );
+
+ InsertText( String( '\n' ) );
+}
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------
+
+const String& SvtDocInfoTable_Impl::GetString( long nId ) const
+{
+ sal_uInt32 nPos( FindIndex( nId ) );
+
+ if ( RESARRAY_INDEX_NOTFOUND != nPos )
+ return ResStringArray::GetString( nPos );
+ else
+ return aEmptyString;
+}
+
+// class SvtFrameWindow_Impl ---------------------------------------------
+
+SvtFrameWindow_Impl::SvtFrameWindow_Impl( Window* pParent ) :
+
+ Window( pParent )
+
+{
+ // detect application language
+ aLocale= SvtPathOptions().GetLocale();
+
+ // create windows and frame
+ pEditWin = new ODocumentInfoPreview( this ,WB_LEFT | WB_VSCROLL | WB_READONLY | WB_BORDER | WB_3DLOOK);
+ pTextWin = new Window( this );
+ xFrame = Reference < XFrame > ( ::comphelper::getProcessServiceFactory()->
+ createInstance( ASCII_STR("com.sun.star.frame.Frame") ), UNO_QUERY );
+ xWindow = VCLUnoHelper::GetInterface( pTextWin );
+ xFrame->initialize( xWindow );
+
+ // create docinfo instance
+ m_xDocProps.set( ::comphelper::getProcessServiceFactory()->createInstance(
+ ASCII_STR("com.sun.star.document.DocumentProperties") ),
+ UNO_QUERY );
+
+ pEmptyWin = new Window( this, WB_BORDER | WB_3DLOOK );
+}
+
+SvtFrameWindow_Impl::~SvtFrameWindow_Impl()
+{
+ delete pEditWin;
+ delete pEmptyWin;
+ xFrame->dispose();
+}
+
+void SvtFrameWindow_Impl::ViewEditWin()
+{
+ pEmptyWin->Hide();
+ xWindow->setVisible( sal_False );
+ pTextWin->Hide();
+ pEditWin->Show();
+}
+
+void SvtFrameWindow_Impl::ViewTextWin()
+{
+ pEmptyWin->Hide();
+ pEditWin->Hide();
+ xWindow->setVisible( sal_True );
+ pTextWin->Show();
+}
+
+void SvtFrameWindow_Impl::ViewEmptyWin()
+{
+ xWindow->setVisible( sal_False );
+ pTextWin->Hide();
+ pEditWin->Hide();
+ pEmptyWin->Show();
+}
+
+void SvtFrameWindow_Impl::ViewNonEmptyWin()
+{
+ if( bDocInfo )
+ ViewEditWin();
+ else
+ ViewTextWin();
+}
+
+IMPL_STATIC_LINK_NOINSTANCE( SvtFrameWindow_Impl, ExecuteHdl_Impl, SvtExecuteInfo*, pExecuteInfo )
+{
+ try
+ {
+ pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, Sequence < PropertyValue >() );
+ }
+ catch ( Exception& )
+ {
+ }
+
+ delete pExecuteInfo;
+ return 0;
+}
+
+void SvtFrameWindow_Impl::ShowDocInfo( const String& rURL )
+{
+ try
+ {
+ uno::Reference < task::XInteractionHandler > xInteractionHandler( ::comphelper::getProcessServiceFactory()->createInstance(
+ ::rtl::OUString::createFromAscii("com.sun.star.task.InteractionHandler") ), uno::UNO_QUERY );
+ uno::Sequence < beans::PropertyValue> aProps(1);
+ aProps[0].Name = ::rtl::OUString::createFromAscii("InteractionHandler");
+ aProps[0].Value <<= xInteractionHandler;
+ m_xDocProps->loadFromMedium( rURL, aProps );
+ pEditWin->fill( m_xDocProps, rURL );
+ }
+ catch ( UnknownPropertyException& ) {}
+ catch ( Exception& ) {}
+}
+
+void SvtFrameWindow_Impl::Resize()
+{
+ Size aWinSize = GetOutputSizePixel();
+ pEditWin->SetSizePixel( aWinSize );
+ pTextWin->SetSizePixel( aWinSize );
+ pEmptyWin->SetSizePixel( aWinSize );
+}
+
+void SvtFrameWindow_Impl::OpenFile( const String& rURL, sal_Bool bPreview, sal_Bool bIsTemplate, sal_Bool bAsTemplate )
+{
+ if ( bPreview )
+ aCurrentURL = rURL;
+
+ ViewNonEmptyWin();
+ pEditWin->Clear();
+
+ if ( rURL.Len() > 0 && bPreview && m_xDocProps.is() )
+ ShowDocInfo( rURL );
+
+ if ( rURL.Len() == 0 )
+ {
+ xFrame->setComponent( Reference < com::sun::star::awt::XWindow >(), Reference < XController >() );
+ ViewEmptyWin();
+ }
+ else if ( !::utl::UCBContentHelper::IsFolder( rURL ) )
+ {
+ com::sun::star::util::URL aURL;
+ aURL.Complete = rURL;
+ Reference < com::sun::star::util::XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->
+ createInstance( ASCII_STR("com.sun.star.util.URLTransformer" ) ), UNO_QUERY );
+ xTrans->parseStrict( aURL );
+
+ String aTarget;
+ Reference < XDispatchProvider > xProv( xFrame, UNO_QUERY );
+ if ( bPreview )
+ aTarget = ASCII_STR("_self");
+ else
+ {
+ // can be removed if the database application change its URL
+ String sServiceScheme( RTL_CONSTASCII_STRINGPARAM( "service:" ) );
+ if ( rURL.Match( sServiceScheme ) != sServiceScheme.Len() )
+ // service URL has no default target
+ aTarget = ASCII_STR("_default");
+ xProv = Reference < XDispatchProvider >( ::comphelper::getProcessServiceFactory()->
+ createInstance( ASCII_STR("com.sun.star.frame.Desktop") ), UNO_QUERY );
+ }
+
+ Reference < XDispatch > xDisp = xProv.is() ?
+ xProv->queryDispatch( aURL, aTarget, 0 ) : Reference < XDispatch >();
+
+ if ( xDisp.is() )
+ {
+ if ( bPreview )
+ {
+ if ( m_aOpenURL != aURL.Complete )
+ {
+ WaitObject aWaitCursor( GetParent() );
+ // disabling must be done here, does not work in ctor because
+ // execute of the dialog will overwrite it
+ // ( own execute method would help )
+ pTextWin->EnableInput( FALSE, TRUE );
+ if ( pTextWin->IsReallyVisible() )
+ {
+ sal_Bool b = sal_True;
+ Sequence < PropertyValue > aArgs( 4 );
+ aArgs[0].Name = ASCII_STR("Preview");
+ aArgs[0].Value.setValue( &b, ::getBooleanCppuType() );
+ aArgs[1].Name = ASCII_STR("ReadOnly");
+ aArgs[1].Value.setValue( &b, ::getBooleanCppuType() );
+ aArgs[2].Name = ASCII_STR("AsTemplate"); // prevents getting an empty URL with getURL()!
+
+ uno::Reference < task::XInteractionHandler > xInteractionHandler( ::comphelper::getProcessServiceFactory()->createInstance(
+ ::rtl::OUString::createFromAscii("com.sun.star.task.InteractionHandler") ), uno::UNO_QUERY );
+ aArgs[3].Name = ::rtl::OUString::createFromAscii("InteractionHandler");
+ aArgs[3].Value <<= xInteractionHandler;
+
+ b = sal_False;
+ aArgs[2].Value.setValue( &b, ::getBooleanCppuType() );
+ xDisp->dispatch( aURL, aArgs );
+
+ ::rtl::OUString aDispURL;
+ Reference< ::com::sun::star::frame::XController > xCtrl = xFrame->getController();
+ if( xCtrl.is() )
+ {
+ Reference< ::com::sun::star::frame::XModel > xMdl = xCtrl->getModel();
+ if( xMdl.is() )
+ aDispURL = xMdl->getURL();
+ }
+
+ if( aDispURL != aURL.Complete )
+ {
+ xFrame->setComponent( Reference < com::sun::star::awt::XWindow >(), Reference < XController >() );
+ ViewEmptyWin();
+ m_aOpenURL = rtl::OUString();
+ }
+ else
+ m_aOpenURL = aDispURL;
+ }
+ }
+ }
+ else if ( bIsTemplate )
+ {
+ Sequence < PropertyValue > aArgs( 1 );
+ aArgs[0].Name = ASCII_STR("AsTemplate");
+ aArgs[0].Value <<= bAsTemplate;
+ xDisp->dispatch( aURL, aArgs );
+ m_aOpenURL = rtl::OUString();
+ }
+ else
+ {
+ /*
+ SvtExecuteInfo* pExecuteInfo = new SvtExecuteInfo;
+ pExecuteInfo->xDispatch = xDisp;
+ pExecuteInfo->aTargetURL = aURL;
+ Application::PostUserEvent(
+ STATIC_LINK(0, SvtFrameWindow_Impl, ExecuteHdl_Impl), pExecuteInfo );
+ */
+ Sequence < PropertyValue > aArgs;
+ xDisp->dispatch( aURL, aArgs );
+ m_aOpenURL = rtl::OUString();
+ }
+ }
+ }
+}
+
+void SvtFrameWindow_Impl::ToggleView( sal_Bool bDI )
+{
+ bDocInfo = bDI;
+
+ // view is set properly in OpenFile()
+
+ OpenFile( aCurrentURL, sal_True, sal_False, sal_False );
+}
+
+// class SvtTemplateWindow -----------------------------------------------
+
+SvtTemplateWindow::SvtTemplateWindow( Window* pParent ) :
+
+ Window( pParent, WB_DIALOGCONTROL ),
+
+ aFileViewTB ( this, SvtResId( TB_SVT_FILEVIEW ) ),
+ aFrameWinTB ( this, SvtResId( TB_SVT_FRAMEWIN ) ),
+ aSplitWin ( this, WB_DIALOGCONTROL | WB_NOSPLITDRAW ),
+ pHistoryList ( NULL )
+
+{
+ // create windows
+ pIconWin = new SvtIconWindow_Impl( this );
+ pFileWin = new SvtFileViewWindow_Impl( this );
+ pFileWin->SetMyDocumentsURL( pIconWin->GetMyDocumentsRootURL() );
+ pFileWin->SetSamplesFolderURL( pIconWin->GetSamplesFolderURL() );
+ pFrameWin = new SvtFrameWindow_Impl( this );
+
+ // set handlers
+ pIconWin->SetClickHdl( LINK( this, SvtTemplateWindow, IconClickHdl_Impl ) );
+ pFileWin->SetSelectHdl( LINK( this, SvtTemplateWindow, FileSelectHdl_Impl ) );
+ pFileWin->SetDoubleClickHdl( LINK( this, SvtTemplateWindow, FileDblClickHdl_Impl ) );
+ pFileWin->SetNewFolderHdl( LINK( this, SvtTemplateWindow, NewFolderHdl_Impl ) );
+
+ // create the split items
+ aSplitWin.SetAlign( WINDOWALIGN_LEFT );
+ long nWidth = pIconWin->GetMaxTextLength() * 8 / 7 + 1; // extra space for border
+ aSplitWin.InsertItem( ICONWIN_ID, pIconWin, nWidth, SPLITWINDOW_APPEND, 0, SWIB_FIXED );
+ aSplitWin.InsertItem( FILEWIN_ID, pFileWin, 50, SPLITWINDOW_APPEND, 0, SWIB_PERCENTSIZE );
+ aSplitWin.InsertItem( FRAMEWIN_ID, pFrameWin, 50, SPLITWINDOW_APPEND, 0, SWIB_PERCENTSIZE );
+ aSplitWin.SetSplitHdl( LINK( this, SvtTemplateWindow, ResizeHdl_Impl ) );
+
+ // show the windows
+ pIconWin->Show();
+ pFileWin->Show();
+ pFrameWin->Show();
+ aSplitWin.Show();
+
+ // initialize the timers
+ aSelectTimer.SetTimeout( 200 );
+ aSelectTimer.SetTimeoutHdl( LINK( this, SvtTemplateWindow, TimeoutHdl_Impl ) );
+
+ // initialize the toolboxes and then show them
+ InitToolBoxes();
+ aFileViewTB.Show();
+ aFrameWinTB.Show();
+
+ ReadViewSettings( );
+
+ Application::PostUserEvent( LINK( this, SvtTemplateWindow, ResizeHdl_Impl ) );
+}
+
+// ------------------------------------------------------------------------
+
+SvtTemplateWindow::~SvtTemplateWindow()
+{
+ WriteViewSettings( );
+
+ delete pIconWin;
+ delete pFileWin;
+ delete pFrameWin;
+ if ( pHistoryList )
+ {
+ for ( UINT32 i = 0; i < pHistoryList->Count(); ++i )
+ delete pHistoryList->GetObject(i);
+ delete pHistoryList;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtTemplateWindow , IconClickHdl_Impl, SvtIconChoiceCtrl *, EMPTYARG )
+{
+ String aURL = pIconWin->GetSelectedIconURL();
+ if ( !aURL.Len() )
+ aURL = pIconWin->GetCursorPosIconURL();
+ if ( pFileWin->GetRootURL() != aURL )
+ {
+ pFileWin->OpenRoot( aURL );
+ pIconWin->InvalidateIconControl();
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_PRINT, FALSE );
+ }
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtTemplateWindow , FileSelectHdl_Impl, SvtFileView *, EMPTYARG )
+{
+ aSelectTimer.Start();
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtTemplateWindow , FileDblClickHdl_Impl, SvtFileView *, EMPTYARG )
+{
+ if ( aSelectTimer.IsActive() )
+ aSelectTimer.Stop();
+
+ String aURL = pFileWin->GetSelectedFile();
+ if ( aURL.Len() > 0 )
+ {
+ if ( ::utl::UCBContentHelper::IsFolder( aURL ) )
+ pFileWin->OpenFolder( aURL );
+ else
+ aDoubleClickHdl.Call( this );
+ }
+
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtTemplateWindow , NewFolderHdl_Impl, SvtFileView *, EMPTYARG )
+{
+ pFrameWin->OpenFile( String(), sal_True, sal_False, sal_False );
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_PRINT, FALSE );
+
+ String sURL = pFileWin->GetFolderURL();
+ ULONG nPos = pIconWin->GetRootPos( sURL );
+ AppendHistoryURL( sURL, nPos );
+
+ aNewFolderHdl.Call( this );
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtTemplateWindow , TimeoutHdl_Impl, Timer *, EMPTYARG )
+{
+ aSelectHdl.Call( this );
+ String sURL = pFileWin->GetSelectedFile();
+ sal_Bool bIsNewDoc = ( pIconWin->GetSelectEntryPos() == ICON_POS_NEWDOC );
+ sal_Bool bIsFile = ( sURL.Len() != 0 && !::utl::UCBContentHelper::IsFolder( sURL ) &&
+ INetURLObject( sURL ).GetProtocol() != INET_PROT_PRIVATE && !bIsNewDoc );
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_PRINT, bIsFile );
+ aFrameWinTB.EnableItem( TI_DOCTEMPLATE_PREVIEW, !bIsNewDoc );
+
+ if ( bIsFile )
+ pFrameWin->OpenFile( sURL, sal_True, sal_False, sal_False );
+ else if ( bIsNewDoc && aFrameWinTB.IsItemChecked( TI_DOCTEMPLATE_PREVIEW ) )
+ {
+ aFrameWinTB.CheckItem( TI_DOCTEMPLATE_DOCINFO );
+ DoAction( TI_DOCTEMPLATE_DOCINFO );
+ }
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtTemplateWindow , ClickHdl_Impl, ToolBox *, pToolBox )
+{
+ DoAction( pToolBox->GetCurItemId() );
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtTemplateWindow , ResizeHdl_Impl, SplitWindow *, EMPTYARG )
+{
+ Resize();
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::PrintFile( const String& rURL )
+{
+ // open the file readonly and hidden
+ Sequence < PropertyValue > aArgs( 2 );
+ aArgs[0].Name = ASCII_STR("ReadOnly");
+ aArgs[0].Value <<= sal_True;
+ aArgs[1].Name = ASCII_STR("Hidden");
+ aArgs[1].Value <<= sal_True;
+
+ Reference < XComponentLoader > xDesktop( ::comphelper::getProcessServiceFactory()->
+ createInstance( ASCII_STR("com.sun.star.frame.Desktop") ), UNO_QUERY );
+ Reference < XModel > xModel( xDesktop->loadComponentFromURL(
+ rURL, ASCII_STR("_blank"), 0, aArgs ), UNO_QUERY );
+ if ( xModel.is() )
+ {
+ // print
+ Reference < XPrintable > xPrintable( xModel, UNO_QUERY );
+ if ( xPrintable.is() )
+ xPrintable->print( Sequence < PropertyValue >() );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::AppendHistoryURL( const String& rURL, ULONG nGroup )
+{
+ sal_Bool bInsert = sal_True;
+ if ( !pHistoryList )
+ pHistoryList = new HistoryList_Impl;
+ else if ( pHistoryList->Count() > 0 )
+ {
+ FolderHistory* pLastEntry = pHistoryList->GetObject( pHistoryList->Count() - 1 );
+ bInsert = ( rURL != pLastEntry->m_sURL);
+ }
+
+ if ( bInsert )
+ {
+ FolderHistory* pEntry = new FolderHistory( rURL, nGroup );
+ pHistoryList->Insert( pEntry, LIST_APPEND );
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_BACK, pHistoryList->Count() > 1 );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::OpenHistory()
+{
+ FolderHistory* pEntry = pHistoryList->Remove( pHistoryList->Count() - 1 );
+ pEntry = pHistoryList->Remove( pHistoryList->Count() - 1 );
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_BACK, pHistoryList->Count() > 1 );
+ pFileWin->OpenFolder( pEntry->m_sURL );
+ pIconWin->SetCursorPos( pEntry->m_nGroup );
+ delete pEntry;
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::DoAction( USHORT nAction )
+{
+ switch( nAction )
+ {
+ case TI_DOCTEMPLATE_BACK :
+ {
+ if ( pHistoryList && pHistoryList->Count() > 1 )
+ OpenHistory();
+ break;
+ }
+
+ case TI_DOCTEMPLATE_PREV :
+ {
+ String aURL;
+ if ( pFileWin->HasPreviousLevel( aURL ) )
+ pFileWin->OpenFolder( aURL );
+ break;
+ }
+
+ case TI_DOCTEMPLATE_PRINT :
+ {
+ String sPrintFile( pFileWin->GetSelectedFile() );
+ if ( sPrintFile.Len() > 0 )
+ PrintFile( sPrintFile );
+ break;
+ }
+
+ case TI_DOCTEMPLATE_DOCINFO :
+ case TI_DOCTEMPLATE_PREVIEW :
+ {
+ pFrameWin->ToggleView( TI_DOCTEMPLATE_DOCINFO == nAction );
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::InitToolBoxes()
+{
+ InitToolBoxImages();
+
+ Size aSize = aFileViewTB.CalcWindowSizePixel();
+ aSize.Height() += 4;
+ aFileViewTB.SetPosSizePixel( Point( 0, 2 ), aSize );
+ aSize = aFrameWinTB.CalcWindowSizePixel();
+ aSize.Height() += 4;
+ aFrameWinTB.SetPosSizePixel( Point( pFrameWin->GetPosPixel().X() + 2, 2 ), aSize );
+
+ BOOL bFlat = ( SvtMiscOptions().GetToolboxStyle() == TOOLBOX_STYLE_FLAT );
+ if ( bFlat )
+ {
+ aFileViewTB.SetOutStyle( TOOLBOX_STYLE_FLAT );
+ aFrameWinTB.SetOutStyle( TOOLBOX_STYLE_FLAT );
+ }
+
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_BACK, FALSE );
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_PREV, FALSE );
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_PRINT, FALSE );
+
+ Link aLink = LINK( this, SvtTemplateWindow, ClickHdl_Impl );
+ aFileViewTB.SetClickHdl( aLink );
+ aFrameWinTB.SetClickHdl( aLink );
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::InitToolBoxImages()
+{
+ SvtMiscOptions aMiscOpt;
+ BOOL bLarge = aMiscOpt.AreCurrentSymbolsLarge();
+ sal_Bool bHiContrast = aFileViewTB.GetSettings().GetStyleSettings().GetHighContrastMode();
+
+ aFileViewTB.SetItemImage( TI_DOCTEMPLATE_BACK, Image( SvtResId(
+ bLarge ? bHiContrast ? IMG_SVT_DOCTEMPL_HC_BACK_LARGE : IMG_SVT_DOCTEMPLATE_BACK_LARGE
+ : bHiContrast ? IMG_SVT_DOCTEMPL_HC_BACK_SMALL : IMG_SVT_DOCTEMPLATE_BACK_SMALL ) ) );
+ aFileViewTB.SetItemImage( TI_DOCTEMPLATE_PREV, Image( SvtResId(
+ bLarge ? bHiContrast ? IMG_SVT_DOCTEMPL_HC_PREV_LARGE : IMG_SVT_DOCTEMPLATE_PREV_LARGE
+ : bHiContrast ? IMG_SVT_DOCTEMPL_HC_PREV_SMALL : IMG_SVT_DOCTEMPLATE_PREV_SMALL ) ) );
+ aFileViewTB.SetItemImage( TI_DOCTEMPLATE_PRINT, Image( SvtResId(
+ bLarge ? bHiContrast ? IMG_SVT_DOCTEMPL_HC_PRINT_LARGE : IMG_SVT_DOCTEMPLATE_PRINT_LARGE
+ : bHiContrast ? IMG_SVT_DOCTEMPL_HC_PRINT_SMALL : IMG_SVT_DOCTEMPLATE_PRINT_SMALL ) ) );
+
+ aFrameWinTB.SetItemImage( TI_DOCTEMPLATE_DOCINFO, Image( SvtResId(
+ bLarge ? bHiContrast ? IMG_SVT_DOCTEMPL_HC_DOCINFO_LARGE : IMG_SVT_DOCTEMPLATE_DOCINFO_LARGE
+ : bHiContrast ? IMG_SVT_DOCTEMPL_HC_DOCINFO_SMALL : IMG_SVT_DOCTEMPLATE_DOCINFO_SMALL ) ) );
+ aFrameWinTB.SetItemImage( TI_DOCTEMPLATE_PREVIEW, Image( SvtResId(
+ bLarge ? bHiContrast ? IMG_SVT_DOCTEMPL_HC_PREVIEW_LARGE : IMG_SVT_DOCTEMPLATE_PREVIEW_LARGE
+ : bHiContrast ? IMG_SVT_DOCTEMPL_HC_PREVIEW_SMALL : IMG_SVT_DOCTEMPLATE_PREVIEW_SMALL ) ) );
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::UpdateIcons()
+{
+ pIconWin->UpdateIcons( aFileViewTB.GetSettings().GetStyleSettings().GetHighContrastMode() );
+}
+
+// ------------------------------------------------------------------------
+
+long SvtTemplateWindow::PreNotify( NotifyEvent& rNEvt )
+{
+ USHORT nType = rNEvt.GetType();
+ long nRet = 0;
+
+ if ( EVENT_KEYINPUT == nType && rNEvt.GetKeyEvent() )
+ {
+ const KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
+ USHORT nCode = rKeyCode.GetCode();
+
+ if ( KEY_BACKSPACE == nCode && !rKeyCode.GetModifier() && pFileWin->HasChildPathFocus() )
+ {
+ DoAction( TI_DOCTEMPLATE_BACK );
+ nRet = 1;
+ }
+ else if ( pIconWin->ProcessKeyEvent( *rNEvt.GetKeyEvent() ) )
+ {
+ nRet = 1;
+ }
+ }
+
+ return nRet ? nRet : Window::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------------
+
+void SvtTemplateWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( ( ( rDCEvt.GetType() == DATACHANGED_SETTINGS ) ||
+ ( rDCEvt.GetType() == DATACHANGED_DISPLAY ) ) &&
+ ( rDCEvt.GetFlags() & SETTINGS_STYLE ) )
+ {
+ // update of the background for the area left of the FileView toolbox
+ SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFaceColor() ) );
+ // update of the images of the IconChoiceControl
+ UpdateIcons();
+ // update of the toolbox images
+ InitToolBoxImages();
+ }
+}
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::Resize()
+{
+ long nItemSize = aSplitWin.GetItemSize( ICONWIN_ID );
+ long nSplitterWidth = Splitter( this, 0 ).GetSizePixel().Width();
+
+ Point aPos = aFileViewTB.GetPosPixel();
+ aPos.X() = nItemSize + nSplitterWidth / 2;
+ aFileViewTB.SetPosPixel( aPos );
+
+ Size aWinSize = GetOutputSizePixel();
+ long nWidth = aWinSize.Width() - aPos.X();
+
+ nItemSize = nWidth * aSplitWin.GetItemSize( FILEWIN_ID ) / 100;
+ aPos.X() = pFrameWin->GetPosPixel().X() + 2;
+ aFrameWinTB.SetPosPixel( aPos );
+
+ Size aSize = aFileViewTB.GetSizePixel();
+ aSize.Width() = nItemSize;
+ aFileViewTB.SetSizePixel( aSize );
+
+ aSize = aFrameWinTB.GetSizePixel();
+ aSize.Width() = nWidth - nItemSize;
+ aFrameWinTB.SetSizePixel( aSize );
+
+ long nToolBoxHeight = aSize.Height() + aFrameWinTB.GetPosPixel().Y();
+ aSize = aWinSize;
+ aSize.Height() -= nToolBoxHeight;
+ aSplitWin.SetPosSizePixel( Point( 0, nToolBoxHeight ), aSize );
+}
+
+// ------------------------------------------------------------------------
+
+String SvtTemplateWindow::GetSelectedFile() const
+{
+ return pFileWin->GetSelectedFile();
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool SvtTemplateWindow::IsFileSelected() const
+{
+ String aURL = pFileWin->GetSelectedFile();
+ sal_Bool bRet = ( aURL.Len() > 0 && !::utl::UCBContentHelper::IsFolder( aURL ) );
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::OpenFile( sal_Bool bNotAsTemplate )
+{
+ String aURL = pFileWin->GetSelectedFile();
+ if ( aURL.Len() > 0 && !::utl::UCBContentHelper::IsFolder( aURL ) )
+ pFrameWin->OpenFile( aURL, sal_False, pFileWin->IsTemplateFolder(), !bNotAsTemplate );
+}
+
+// ------------------------------------------------------------------------
+
+String SvtTemplateWindow::GetFolderTitle() const
+{
+ String sTitle;
+ String sFolderURL = pFileWin->GetFolderURL();
+ if ( pIconWin->IsRootURL( sFolderURL ) )
+ sTitle = pIconWin->GetIconText( sFolderURL );
+ else
+ sTitle = pFileWin->GetFolderTitle();
+ return sTitle;
+}
+
+// ------------------------------------------------------------------------
+
+String SvtTemplateWindow::GetFolderURL() const
+{
+ return pFileWin->GetFolderURL();
+}
+
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::SetFocus( sal_Bool bIconWin )
+{
+ if ( bIconWin )
+ pIconWin->SetFocus();
+ else
+ pFileWin->SetFocus();
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::OpenTemplateRoot()
+{
+ pFileWin->OpenFolder( pIconWin->GetTemplateRootURL() );
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::SetPrevLevelButtonState( const String& rURL )
+{
+ // disable the prev level button on root folder of the icon pane (except My Documents)
+ // and on the root of all (file:/// -> count == 0)
+ INetURLObject aObj( rURL );
+ sal_Int32 nCount = aObj.getSegmentCount();
+ sal_Bool bEnable =
+ ( nCount > 0 &&
+ ( !pIconWin->IsRootURL( rURL ) || rURL == pIconWin->GetMyDocumentsRootURL() ) );
+ aFileViewTB.EnableItem( TI_DOCTEMPLATE_PREV, bEnable );
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::ClearHistory()
+{
+ if( pHistoryList )
+ pHistoryList->Clear();
+}
+
+// ------------------------------------------------------------------------
+
+long SvtTemplateWindow::CalcHeight() const
+{
+ // toolbox height
+ long nHeight = aFileViewTB.GetSizePixel().Height();
+ // + iconwin height
+ nHeight += pIconWin->CalcHeight();
+ // + little offset
+ nHeight += 8;
+ return nHeight;
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::ReadViewSettings()
+{
+ // defaults
+ sal_Int32 nSelectedGroup = ICON_POS_TEMPLATES;
+ sal_Int32 nSelectedView = TI_DOCTEMPLATE_DOCINFO;
+ double nSplitRatio = 0.5;
+ ::rtl::OUString sLastFolder;
+
+ SvtViewOptions aViewSettings( E_DIALOG, VIEWSETTING_NEWFROMTEMPLATE );
+ if ( aViewSettings.Exists() )
+ {
+ // read the settings
+ Sequence< NamedValue > aSettings = aViewSettings.GetUserData( );
+
+ aViewSettings.GetUserItem( VIEWSETTING_SELECTEDGROUP ) >>= nSelectedGroup;
+ aViewSettings.GetUserItem( VIEWSETTING_SELECTEDVIEW ) >>= nSelectedView;
+ aViewSettings.GetUserItem( VIEWSETTING_SPLITRATIO ) >>= nSplitRatio;
+ aViewSettings.GetUserItem( VIEWSETTING_LASTFOLDER ) >>= sLastFolder;
+ }
+ // normalize
+ if ( nSelectedGroup < ICON_POS_NEWDOC ) nSelectedGroup = ICON_POS_NEWDOC;
+ if ( nSelectedGroup > ICON_POS_SAMPLES ) nSelectedGroup = ICON_POS_SAMPLES;
+
+ if ( ( TI_DOCTEMPLATE_DOCINFO != nSelectedView ) && ( TI_DOCTEMPLATE_PREVIEW != nSelectedView ) )
+ nSelectedView = TI_DOCTEMPLATE_DOCINFO;
+
+ if ( nSplitRatio < 0.2 ) nSplitRatio = 0.2;
+ if ( nSplitRatio > 0.8 ) nSplitRatio = 0.8;
+
+ // change our view according to the settings
+
+ // the selected view (details or preview)
+ pFrameWin->ToggleView( TI_DOCTEMPLATE_DOCINFO == nSelectedView );
+ aFrameWinTB.CheckItem( (sal_uInt16)nSelectedView, TRUE );
+
+ // the split ratio
+ sal_Int32 nSplitFileAndFrameSize = aSplitWin.GetItemSize( FILEWIN_ID ) + aSplitWin.GetItemSize( FRAMEWIN_ID );
+ sal_Int32 nSplitFileSize = (sal_Int32)(nSplitFileAndFrameSize * nSplitRatio);
+ sal_Int32 nSplitFrameSize = nSplitFileAndFrameSize - nSplitFileSize;
+ aSplitWin.SetItemSize( FILEWIN_ID, nSplitFileSize );
+ aSplitWin.SetItemSize( FRAMEWIN_ID, nSplitFrameSize );
+ Resize();
+
+ // the selected folder
+ pIconWin->SetCursorPos( nSelectedGroup );
+
+ // open the last folder or the selected group
+ if ( sLastFolder.getLength() > 0 )
+ pFileWin->OpenFolder( sLastFolder );
+ else
+ IconClickHdl_Impl( NULL );
+}
+
+// ------------------------------------------------------------------------
+
+void SvtTemplateWindow::WriteViewSettings()
+{
+ // collect
+ Sequence< NamedValue > aSettings(4);
+
+ // the selected group
+ aSettings[0].Name = VIEWSETTING_SELECTEDGROUP;
+ pIconWin->SetFocus();
+ aSettings[0].Value <<= (sal_Int32)pIconWin->GetCursorPos( );
+
+ // the selected view mode
+ aSettings[1].Name = VIEWSETTING_SELECTEDVIEW;
+ aSettings[1].Value <<= sal_Int32( aFrameWinTB.IsItemChecked( TI_DOCTEMPLATE_DOCINFO ) ? TI_DOCTEMPLATE_DOCINFO : TI_DOCTEMPLATE_PREVIEW );
+
+ // the split ratio
+ aSettings[2].Name = VIEWSETTING_SPLITRATIO;
+ sal_Int32 nSplitFileSize = aSplitWin.GetItemSize( FILEWIN_ID );
+ sal_Int32 nSplitFileAndFrameSize = nSplitFileSize + aSplitWin.GetItemSize( FRAMEWIN_ID );
+ aSettings[2].Value <<= double( 1.0 * nSplitFileSize / nSplitFileAndFrameSize );
+
+ // last folder
+ aSettings[3].Name = VIEWSETTING_LASTFOLDER;
+ aSettings[3].Value <<= ::rtl::OUString( pFileWin->GetFolderURL() );
+
+ // write
+ SvtViewOptions aViewSettings( E_DIALOG, VIEWSETTING_NEWFROMTEMPLATE );
+ aViewSettings.SetUserData( aSettings );
+}
+/* -----------------27.11.2002 17:20-----------------
+ *
+ * --------------------------------------------------*/
+
+void SvtTemplateWindow::SelectFolder(sal_Int32 nFolderPosition)
+{
+ pIconWin->SelectFolder(nFolderPosition);
+}
+// struct SvtTmplDlg_Impl ------------------------------------------------
+
+struct SvtTmplDlg_Impl
+{
+ SvtTemplateWindow* pWin;
+ String aTitle;
+ Timer aUpdateTimer;
+ sal_Bool bSelectNoOpen;
+
+ uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
+
+
+ SvtTmplDlg_Impl( Window* pParent ) : pWin( new SvtTemplateWindow( pParent ) ) ,bSelectNoOpen( sal_False ) {}
+
+ ~SvtTmplDlg_Impl() { delete pWin; }
+
+ uno::Reference< util::XOfficeInstallationDirectories > getOfficeInstDirs();
+};
+
+uno::Reference< util::XOfficeInstallationDirectories > SvtTmplDlg_Impl::getOfficeInstDirs()
+{
+ if ( !m_xOfficeInstDirs.is() )
+ {
+ try
+ {
+ uno::Reference< lang::XMultiServiceFactory > xSMgr = comphelper::getProcessServiceFactory();
+
+ uno::Reference< beans::XPropertySet > xPropSet( xSMgr, uno::UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ uno::Reference< uno::XComponentContext > xCtx;
+ xPropSet->getPropertyValue(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
+ >>= xCtx;
+
+ if ( xCtx.is() )
+ {
+ xCtx->getValueByName(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "/singletons/com.sun.star.util.theOfficeInstallationDirectories" ) ) )
+ >>= m_xOfficeInstDirs;
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ return m_xOfficeInstDirs;
+}
+
+// class SvtDocumentTemplateDialog ---------------------------------------
+
+SvtDocumentTemplateDialog::SvtDocumentTemplateDialog( Window* _pParent, SelectOnly ) :
+ ModalDialog( _pParent, SvtResId( DLG_DOCTEMPLATE ) ),
+
+ aMoreTemplatesLink ( this, SvtResId( FT_DOCTEMPLATE_LINK ) ),
+ aLine ( this, SvtResId( FL_DOCTEMPLATE ) ),
+ aManageBtn ( this, SvtResId( BTN_DOCTEMPLATE_MANAGE ) ),
+ aEditBtn ( this, SvtResId( BTN_DOCTEMPLATE_EDIT ) ),
+ aOKBtn ( this, SvtResId( BTN_DOCTEMPLATE_OPEN ) ),
+ aCancelBtn ( this, SvtResId( BTN_DOCTEMPLATE_CANCEL ) ),
+ aHelpBtn ( this, SvtResId( BTN_DOCTEMPLATE_HELP ) ),
+ pImpl ( NULL )
+{
+ FreeResource();
+ InitImpl( );
+
+ // no editing of templates
+ aEditBtn.Hide();
+
+ pImpl->bSelectNoOpen = sal_True;
+}
+
+// ------------------------------------------------------------------------
+
+SvtDocumentTemplateDialog::SvtDocumentTemplateDialog( Window* pParent ) :
+
+ ModalDialog( pParent, SvtResId( DLG_DOCTEMPLATE ) ),
+
+ aMoreTemplatesLink ( this, SvtResId( FT_DOCTEMPLATE_LINK ) ),
+ aLine ( this, SvtResId( FL_DOCTEMPLATE ) ),
+ aManageBtn ( this, SvtResId( BTN_DOCTEMPLATE_MANAGE ) ),
+ aEditBtn ( this, SvtResId( BTN_DOCTEMPLATE_EDIT ) ),
+ aOKBtn ( this, SvtResId( BTN_DOCTEMPLATE_OPEN ) ),
+ aCancelBtn ( this, SvtResId( BTN_DOCTEMPLATE_CANCEL ) ),
+ aHelpBtn ( this, SvtResId( BTN_DOCTEMPLATE_HELP ) ),
+ pImpl ( NULL )
+{
+ FreeResource();
+ InitImpl( );
+}
+
+// ------------------------------------------------------------------------
+
+void SvtDocumentTemplateDialog::InitImpl( )
+{
+ pImpl = new SvtTmplDlg_Impl( this );
+ pImpl->aTitle = GetText();
+
+ bool bHideLink = ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode()
+ == SvtExtendedSecurityOptions::OPEN_NEVER );
+ if ( !bHideLink )
+ {
+ aMoreTemplatesLink.SetURL( String(
+ RTL_CONSTASCII_STRINGPARAM( "http://templates.services.openoffice.org/?cid=923508" ) ) );
+ aMoreTemplatesLink.SetClickHdl( LINK( this, SvtDocumentTemplateDialog, OpenLinkHdl_Impl ) );
+ }
+ else
+ aMoreTemplatesLink.Hide();
+
+ aManageBtn.SetClickHdl( LINK( this, SvtDocumentTemplateDialog, OrganizerHdl_Impl ) );
+ Link aLink = LINK( this, SvtDocumentTemplateDialog, OKHdl_Impl );
+ aEditBtn.SetClickHdl( aLink );
+ aOKBtn.SetClickHdl( aLink );
+
+ pImpl->pWin->SetSelectHdl( LINK( this, SvtDocumentTemplateDialog, SelectHdl_Impl ) );
+ pImpl->pWin->SetDoubleClickHdl( LINK( this, SvtDocumentTemplateDialog, DoubleClickHdl_Impl ) );
+ pImpl->pWin->SetNewFolderHdl( LINK( this, SvtDocumentTemplateDialog, NewFolderHdl_Impl ) );
+ pImpl->pWin->SetSendFocusHdl( LINK( this, SvtDocumentTemplateDialog, SendFocusHdl_Impl ) );
+
+ // dynamic height adjustment
+ long nHeight = pImpl->pWin->CalcHeight();
+
+ Size aSize = GetOutputSizePixel();
+ Point aPos = aMoreTemplatesLink.GetPosPixel();
+ Size a6Size = LogicToPixel( Size( 6, 6 ), MAP_APPFONT );
+ if ( bHideLink )
+ aPos.Y() += aMoreTemplatesLink.GetSizePixel().Height();
+ else
+ aPos.Y() -= a6Size.Height();
+ long nDelta = aPos.Y() - nHeight;
+ aSize.Height() -= nDelta;
+ SetOutputSizePixel( aSize );
+
+ aSize.Height() = nHeight;
+ aSize.Width() -= ( a6Size.Width() * 2 );
+ pImpl->pWin->SetPosSizePixel( Point( a6Size.Width(), 0 ), aSize );
+
+ aPos = aMoreTemplatesLink.GetPosPixel();
+ aPos.Y() -= nDelta;
+ aMoreTemplatesLink.SetPosPixel( aPos );
+ aPos = aLine.GetPosPixel();
+ aPos.Y() -= nDelta;
+ aLine.SetPosPixel( aPos );
+ aPos = aManageBtn.GetPosPixel();
+ aPos.Y() -= nDelta;
+ aManageBtn.SetPosPixel( aPos );
+ aPos = aEditBtn.GetPosPixel();
+ aPos.Y() -= nDelta;
+ aEditBtn.SetPosPixel( aPos );
+ aPos = aOKBtn.GetPosPixel();
+ aPos.Y() -= nDelta;
+ aOKBtn.SetPosPixel( aPos );
+ aPos = aCancelBtn.GetPosPixel();
+ aPos.Y() -= nDelta;
+ aCancelBtn.SetPosPixel( aPos );
+ aPos = aHelpBtn.GetPosPixel();
+ aPos.Y() -= nDelta;
+ aHelpBtn.SetPosPixel( aPos );
+
+ pImpl->pWin->Show();
+
+ SelectHdl_Impl( NULL );
+ NewFolderHdl_Impl( NULL );
+
+ UpdateHdl_Impl( NULL );
+}
+
+// ------------------------------------------------------------------------
+
+SvtDocumentTemplateDialog::~SvtDocumentTemplateDialog()
+{
+ delete pImpl;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool SvtDocumentTemplateDialog::IsFileSelected( ) const
+{
+ return pImpl->pWin->IsFileSelected();
+}
+
+// ------------------------------------------------------------------------
+
+String SvtDocumentTemplateDialog::GetSelectedFileURL( ) const
+{
+ return pImpl->pWin->GetSelectedFile();
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool SvtDocumentTemplateDialog::CanEnableEditBtn() const
+{
+ sal_Bool bEnable = sal_False;
+
+ ::rtl::OUString aFolderURL = pImpl->pWin->GetFolderURL();
+ if ( pImpl->pWin->IsFileSelected() && aFolderURL.getLength() )
+ {
+ ::rtl::OUString aFileTargetURL = pImpl->pWin->GetSelectedFile();
+ bEnable = aFileTargetURL.getLength() > 0;
+ }
+
+ return bEnable;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtDocumentTemplateDialog , SelectHdl_Impl, SvtTemplateWindow *, EMPTYARG )
+{
+ aEditBtn.Enable( pImpl->pWin->IsTemplateFolderOpen() && CanEnableEditBtn() );
+ aOKBtn.Enable( pImpl->pWin->IsFileSelected() );
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtDocumentTemplateDialog , DoubleClickHdl_Impl, SvtTemplateWindow *, EMPTYARG )
+{
+ EndDialog( RET_OK );
+
+ if ( !pImpl->bSelectNoOpen )
+ pImpl->pWin->OpenFile( !pImpl->pWin->IsTemplateFolderOpen() );
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtDocumentTemplateDialog , NewFolderHdl_Impl, SvtTemplateWindow *, EMPTYARG )
+{
+ String aNewTitle( pImpl->aTitle );
+ aNewTitle += String( ASCII_STR(" - ") );
+ aNewTitle += pImpl->pWin->GetFolderTitle();
+ SetText( aNewTitle );
+
+ SelectHdl_Impl( NULL );
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtDocumentTemplateDialog , SendFocusHdl_Impl, SvtTemplateWindow *, EMPTYARG )
+{
+ if ( pImpl->pWin->HasIconWinFocus() )
+ aHelpBtn.GrabFocus();
+ else
+ {
+ if ( aEditBtn.IsEnabled() )
+ aEditBtn.GrabFocus();
+ else if ( aOKBtn.IsEnabled() )
+ aOKBtn.GrabFocus();
+ else
+ aCancelBtn.GrabFocus();
+ }
+
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtDocumentTemplateDialog , OKHdl_Impl, PushButton *, pBtn )
+{
+ if ( pImpl->pWin->IsFileSelected() )
+ {
+ EndDialog( RET_OK );
+
+ if ( !pImpl->bSelectNoOpen )
+ pImpl->pWin->OpenFile( &aEditBtn == pBtn );
+ }
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtDocumentTemplateDialog , OrganizerHdl_Impl, PushButton *, EMPTYARG )
+{
+ Window* pOldDefWin = Application::GetDefDialogParent();
+ Application::SetDefDialogParent( this );
+ Reference < XFramesSupplier > xDesktop = Reference < XFramesSupplier >(
+ ::comphelper::getProcessServiceFactory()->
+ createInstance( ASCII_STR("com.sun.star.frame.Desktop") ), UNO_QUERY );
+ Reference < XFrame > xFrame( xDesktop->getActiveFrame() );
+ if ( !xFrame.is() )
+ xFrame = Reference < XFrame >( xDesktop, UNO_QUERY );
+
+ com::sun::star::util::URL aTargetURL;
+ aTargetURL.Complete = ASCII_STR("slot:5540");
+ Reference < com::sun::star::util::XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->
+ createInstance( ASCII_STR("com.sun.star.util.URLTransformer") ), UNO_QUERY );
+ xTrans->parseStrict( aTargetURL );
+
+ Reference < XDispatchProvider > xProv( xFrame, UNO_QUERY );
+ Reference < XDispatch > xDisp;
+ xDisp = xProv->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
+
+ if ( xDisp.is() )
+ {
+ Sequence<PropertyValue> aArgs(1);
+ PropertyValue* pArg = aArgs.getArray();
+ pArg[0].Name = ASCII_STR("Referer");
+ pArg[0].Value <<= ASCII_STR("private:user");
+ xDisp->dispatch( aTargetURL, aArgs );
+ }
+
+ Application::SetDefDialogParent( pOldDefWin );
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtDocumentTemplateDialog, UpdateHdl_Impl, Timer*, _pEventSource )
+{
+ pImpl->pWin->SetFocus( sal_False );
+ Reference< XDocumentTemplates > xTemplates( ::comphelper::getProcessServiceFactory()->
+ createInstance( ASCII_STR("com.sun.star.frame.DocumentTemplates") ), UNO_QUERY );
+ if ( xTemplates.is() )
+ {
+ if ( _pEventSource )
+ { // it was no direct call, which means it was triggered by the timer, which means we alread checked the necessity
+ WaitObject aWaitCursor( this );
+ xTemplates->update();
+ if ( pImpl->pWin->IsTemplateFolderOpen() )
+ {
+ pImpl->pWin->ClearHistory();
+ pImpl->pWin->OpenTemplateRoot();
+ }
+ }
+ else
+ {
+ // check if we really need to do the update
+ ::svt::TemplateFolderCache aCache;
+ if ( aCache.needsUpdate() )
+ { // yes -> do it asynchronous (it will take a noticeable time)
+
+ // (but first store the current state)
+ aCache.storeState();
+
+ // start the timer for the async update
+ pImpl->aUpdateTimer.SetTimeout( 300 );
+ pImpl->aUpdateTimer.SetTimeoutHdl( LINK( this, SvtDocumentTemplateDialog, UpdateHdl_Impl ) );
+ pImpl->aUpdateTimer.Start();
+ }
+ }
+ }
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK ( SvtDocumentTemplateDialog, OpenLinkHdl_Impl, svt::FixedHyperlink*, EMPTYARG )
+{
+ ::rtl::OUString sURL( aMoreTemplatesLink.GetURL() );
+ if ( sURL.getLength() > 0 )
+ {
+ try
+ {
+ uno::Reference< lang::XMultiServiceFactory > xSMGR =
+ ::comphelper::getProcessServiceFactory();
+ uno::Reference< com::sun::star::system::XSystemShellExecute > xSystemShell(
+ xSMGR->createInstance( ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SystemShellExecute" ) ) ),
+ uno::UNO_QUERY_THROW );
+ if ( xSystemShell.is() )
+ xSystemShell->execute( sURL, ::rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::DEFAULTS );
+ EndDialog( RET_CANCEL );
+ }
+ catch( const uno::Exception& e )
+ {
+ OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ }
+ return 0;
+}
+
+/* -----------------27.11.2002 16:54-----------------
+ *
+ * --------------------------------------------------*/
+void SvtDocumentTemplateDialog::SelectTemplateFolder()
+{
+ pImpl->pWin->SelectFolder(ICON_POS_TEMPLATES);
+}
+
diff --git a/svtools/source/contnr/templwin.hrc b/svtools/source/contnr/templwin.hrc
new file mode 100644
index 000000000000..5a0d84f1d377
--- /dev/null
+++ b/svtools/source/contnr/templwin.hrc
@@ -0,0 +1,59 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+#ifndef _SVTOOLS_TEMPLWIN_HRC
+#define _SVTOOLS_TEMPLWIN_HRC
+
+#define FL_DOCTEMPLATE 10
+#define BTN_DOCTEMPLATE_MANAGE 11
+#define BTN_DOCTEMPLATE_EDIT 12
+#define BTN_DOCTEMPLATE_OPEN 13
+#define BTN_DOCTEMPLATE_CANCEL 14
+#define BTN_DOCTEMPLATE_HELP 15
+#define FT_DOCTEMPLATE_LINK 16
+
+#define TI_DOCTEMPLATE_BACK 1
+#define TI_DOCTEMPLATE_PREV 2
+#define TI_DOCTEMPLATE_PRINT 3
+#define TI_DOCTEMPLATE_DOCINFO 4
+#define TI_DOCTEMPLATE_PREVIEW 5
+
+#define HBI_CATEGORY 1
+
+#define DI_TITLE 1
+#define DI_FROM 2
+#define DI_DATE 3
+#define DI_KEYWORDS 4
+#define DI_DESCRIPTION 5
+#define DI_MIMETYPE 6
+#define DI_MODIFIEDDATE 7
+#define DI_MODIFIEDBY 8
+#define DI_PRINTDATE 9
+#define DI_PRINTBY 10
+#define DI_THEME 11
+#define DI_SIZE 12
+
+#endif // _SVTOOLS_TEMPLWIN_HRC
diff --git a/svtools/source/contnr/templwin.hxx b/svtools/source/contnr/templwin.hxx
new file mode 100644
index 000000000000..acb7c602ad30
--- /dev/null
+++ b/svtools/source/contnr/templwin.hxx
@@ -0,0 +1,309 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+#ifndef _SVTOOLS_TEMPLWIN_HXX
+#define _SVTOOLS_TEMPLWIN_HXX
+
+#include <tools/resary.hxx>
+#include <vcl/splitwin.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/window.hxx>
+#include <svtools/headbar.hxx>
+#include "fileview.hxx"
+#include "ivctrl.hxx"
+#include <svtools/svmedit2.hxx>
+#include <svl/restrictedpaths.hxx>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+
+namespace com{ namespace sun { namespace star { namespace awt { class XWindow; } } } }
+namespace com{ namespace sun { namespace star { namespace frame { class XFrame; } } } }
+namespace com{ namespace sun { namespace star { namespace document {
+ class XDocumentProperties;
+} } } }
+namespace svtools
+{
+ class ODocumentInfoPreview;
+}
+
+// class SvtDummyHeaderBar_Impl ------------------------------------------
+
+class SvtDummyHeaderBar_Impl : public Window
+{
+private:
+ void UpdateBackgroundColor();
+
+public:
+ SvtDummyHeaderBar_Impl( Window* pParent );
+ ~SvtDummyHeaderBar_Impl();
+
+ virtual void DataChanged( const DataChangedEvent& rDCEvt );
+};
+
+// class SvtIconWindow_Impl ----------------------------------------------
+
+class SvtIconWindow_Impl : public Window
+{
+private:
+ SvtDummyHeaderBar_Impl aDummyHeaderBar; // spaceholder instead of HeaderBar
+ SvtIconChoiceCtrl aIconCtrl;
+
+ String aNewDocumentRootURL;
+ String aTemplateRootURL;
+ String aMyDocumentsRootURL;
+ String aSamplesFolderRootURL;
+
+ long nMaxTextLength;
+
+ SvxIconChoiceCtrlEntry* GetEntry( const String& rURL ) const;
+
+public:
+ SvtIconWindow_Impl( Window* pParent );
+ ~SvtIconWindow_Impl();
+
+ virtual void Resize();
+
+ inline long GetMaxTextLength() const { return nMaxTextLength; }
+ inline void SetClickHdl( const Link& rLink ) { aIconCtrl.SetClickHdl( rLink ); }
+
+ String GetSelectedIconURL() const;
+ String GetSelectedIconText() const;
+ String GetCursorPosIconURL() const;
+ String GetIconText( const String& rURL ) const;
+ void InvalidateIconControl();
+ void SetCursorPos( ULONG nPos );
+ ULONG GetCursorPos() const;
+ ULONG GetSelectEntryPos() const;
+ void SetFocus();
+ long CalcHeight() const;
+ sal_Bool IsRootURL( const String& rURL ) const;
+ ULONG GetRootPos( const String& rURL ) const;
+ void UpdateIcons( sal_Bool _bHiContrast );
+
+ inline sal_Bool ProcessKeyEvent( const KeyEvent& rKEvt );
+
+ inline const String& GetTemplateRootURL() const { return aTemplateRootURL; }
+ inline const String& GetMyDocumentsRootURL() const { return aMyDocumentsRootURL; }
+ inline const String& GetSamplesFolderURL() const { return aSamplesFolderRootURL; }
+
+ void SelectFolder(sal_Int32 nFolderPos);
+};
+
+inline sal_Bool SvtIconWindow_Impl::ProcessKeyEvent( const KeyEvent& rKEvt )
+{
+ return ( rKEvt.GetKeyCode().IsMod2() ? aIconCtrl.DoKeyInput( rKEvt ) : sal_False );
+}
+
+// class SvtFileViewWindow_Impl ------------------------------------------
+
+class SvtTemplateWindow;
+
+class SvtFileViewWindow_Impl : public Window
+{
+private:
+ SvtTemplateWindow& rParent;
+ SvtFileView aFileView;
+ Link aNewFolderLink;
+ String aCurrentRootURL;
+ String aFolderURL;
+ String aMyDocumentsURL;
+ String aSamplesFolderURL;
+ ::svt::RestrictedPaths
+ aURLFilter;
+
+ sal_Bool bIsTemplateFolder;
+
+ ::com::sun::star::uno::Sequence< ::rtl::OUString >
+ GetNewDocContents() const;
+
+public:
+ SvtFileViewWindow_Impl( SvtTemplateWindow* pParent );
+ ~SvtFileViewWindow_Impl();
+
+ virtual void Resize();
+
+ inline void SetSelectHdl( const Link& rLink ) { aFileView.SetSelectHdl( rLink ); }
+ inline void SetDoubleClickHdl( const Link& rLink ) { aFileView.SetDoubleClickHdl( rLink ); }
+ inline void SetNewFolderHdl( const Link& rLink ) { aNewFolderLink = rLink; }
+ inline void ResetCursor() { aFileView.ResetCursor(); }
+ inline sal_Bool IsTemplateFolder() const { return bIsTemplateFolder; }
+ inline String GetFolderURL() const { return aFolderURL; }
+ inline String GetRootURL() const { return aCurrentRootURL; }
+ inline void OpenRoot( const String& rRootURL )
+ { aCurrentRootURL = rRootURL; OpenFolder( rRootURL ); }
+ inline void SetMyDocumentsURL( const String& _rNewURL ) { aMyDocumentsURL = _rNewURL; }
+ inline void SetSamplesFolderURL( const String& _rNewURL ) { aSamplesFolderURL = _rNewURL; }
+
+ String GetSelectedFile() const;
+ void OpenFolder( const String& rURL );
+ sal_Bool HasPreviousLevel( String& rURL ) const;
+ String GetFolderTitle() const;
+ void SetFocus();
+};
+
+// class SvtFrameWindow_Impl ---------------------------------------------
+
+class SvtDocInfoTable_Impl : public ResStringArray
+{
+private:
+ String aEmptyString;
+
+public:
+ SvtDocInfoTable_Impl();
+
+ const String& GetString( long nId ) const;
+};
+
+class SvtExtendedMultiLineEdit_Impl : public ExtMultiLineEdit
+{
+public:
+ SvtExtendedMultiLineEdit_Impl( Window* pParent,WinBits _nBits );
+ inline ~SvtExtendedMultiLineEdit_Impl() {}
+
+ inline void Clear() { SetText( String() ); }
+ void InsertEntry( const String& rTitle, const String& rValue );
+};
+
+class SvtFrameWindow_Impl : public Window
+{
+private:
+ ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame >
+ xFrame;
+ ::com::sun::star::uno::Reference < ::com::sun::star::document::XDocumentProperties>
+ m_xDocProps;
+ ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >
+ xWindow;
+
+ ::svtools::ODocumentInfoPreview*
+ pEditWin;
+ Window* pTextWin;
+ Window* pEmptyWin;
+ ::com::sun::star::lang::Locale aLocale;
+ SvtDocInfoTable_Impl aInfoTable;
+ String aCurrentURL;
+ ::rtl::OUString m_aOpenURL;
+ sal_Bool bDocInfo;
+
+ void ShowDocInfo( const String& rURL );
+ void ViewEditWin();
+ void ViewTextWin();
+ void ViewEmptyWin();
+ void ViewNonEmptyWin(); // views depending on bDocInfo
+
+ struct SvtExecuteInfo
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDispatch;
+ ::com::sun::star::util::URL aTargetURL;
+ };
+
+ DECL_STATIC_LINK( SvtFrameWindow_Impl, ExecuteHdl_Impl, SvtExecuteInfo* );
+
+public:
+ SvtFrameWindow_Impl( Window* pParent );
+ ~SvtFrameWindow_Impl();
+
+ virtual void Resize();
+
+ void OpenFile( const String& rURL, sal_Bool bPreview, sal_Bool bIsTemplate, sal_Bool bAsTemplate );
+ void ToggleView( sal_Bool bDocInfo );
+};
+
+// class SvtTemplateWindow -----------------------------------------------
+
+class HistoryList_Impl;
+
+class SvtTemplateWindow : public Window
+{
+private:
+ ToolBox aFileViewTB;
+ ToolBox aFrameWinTB;
+ SplitWindow aSplitWin;
+
+ SvtIconWindow_Impl* pIconWin;
+ SvtFileViewWindow_Impl* pFileWin;
+ SvtFrameWindow_Impl* pFrameWin;
+ HistoryList_Impl* pHistoryList;
+
+ Link aSelectHdl;
+ Link aDoubleClickHdl;
+ Link aNewFolderHdl;
+ Link aSendFocusHdl;
+
+ Timer aSelectTimer;
+
+ String aFolderTitle;
+
+ virtual void Resize();
+
+ DECL_LINK( IconClickHdl_Impl, SvtIconChoiceCtrl* );
+ DECL_LINK( FileSelectHdl_Impl, SvtFileView* );
+ DECL_LINK( FileDblClickHdl_Impl, SvtFileView* );
+ DECL_LINK( NewFolderHdl_Impl, SvtFileView* );
+ DECL_LINK( TimeoutHdl_Impl, Timer* );
+ DECL_LINK( ClickHdl_Impl, ToolBox* );
+ DECL_LINK( ResizeHdl_Impl, SplitWindow* ); // used for split and initial setting of toolbar pos
+
+ void PrintFile( const String& rURL );
+ void AppendHistoryURL( const String& rURL, ULONG nGroup );
+ void OpenHistory();
+ void DoAction( USHORT nAction );
+ void InitToolBoxes();
+ void InitToolBoxImages();
+ void UpdateIcons();
+
+protected:
+ virtual long PreNotify( NotifyEvent& rNEvt );
+ virtual void DataChanged( const DataChangedEvent& rDCEvt );
+
+public:
+ SvtTemplateWindow( Window* pParent );
+ ~SvtTemplateWindow();
+
+ inline void SetSelectHdl( const Link& rLink ) { aSelectHdl = rLink; }
+ inline void SetDoubleClickHdl( const Link& rLink ) { aDoubleClickHdl = rLink; }
+ inline void SetNewFolderHdl( const Link& rLink ) { aNewFolderHdl = rLink; }
+ inline void SetSendFocusHdl( const Link& rLink ) { aSendFocusHdl = rLink; }
+ inline sal_Bool IsTemplateFolderOpen() const { return pFileWin->IsTemplateFolder(); }
+ inline sal_Bool HasIconWinFocus() const { return pIconWin->HasChildPathFocus(); }
+
+ void ReadViewSettings( );
+ void WriteViewSettings( );
+ sal_Bool IsFileSelected() const;
+ String GetSelectedFile() const;
+ void OpenFile( sal_Bool bNotAsTemplate );
+ String GetFolderTitle() const;
+ String GetFolderURL() const;
+ void SetFocus( sal_Bool bIconWin );
+ void OpenTemplateRoot();
+ void SetPrevLevelButtonState( const String& rURL ); // sets state (enable/disable) for previous level button
+ void ClearHistory();
+ long CalcHeight() const;
+
+ void SelectFolder(sal_Int32 nFolderPosition);
+};
+
+#endif // _SVTOOLS_TEMPLWIN_HXX
+
diff --git a/svtools/source/contnr/templwin.src b/svtools/source/contnr/templwin.src
new file mode 100644
index 000000000000..048d052c18d8
--- /dev/null
+++ b/svtools/source/contnr/templwin.src
@@ -0,0 +1,376 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+ // includes ------------------------------------------------------------------
+
+#include "templwin.hrc"
+#include "controldims.hrc"
+#include <svtools/helpid.hrc>
+#include <svtools/svtools.hrc>
+
+// Magenta and Grey as mask colors
+#define MASK_COL_MAGENTA Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; };
+
+Control CTRL_FILEVIEW
+{
+ Pos = MAP_APPFONT ( 0 , 0 ) ;
+ Size = MAP_APPFONT ( 200 , 180 ) ;
+};
+
+String STR_SVT_NEWDOC
+{
+ Text [ en-US ] = "New Document";
+};
+
+Image IMG_SVT_NEWDOC
+{
+ ImageBitmap = Bitmap { File = "new_doc.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+Image IMG_SVT_NEWDOC_HC
+{
+ ImageBitmap = Bitmap { File = "new_doc_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+String STR_SVT_MYDOCS
+{
+ Text [ en-US ] = "My Documents";
+};
+
+Image IMG_SVT_MYDOCS
+{
+ ImageBitmap = Bitmap { File = "my_docs.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+Image IMG_SVT_MYDOCS_HC
+{
+ ImageBitmap = Bitmap { File = "my_docs_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+String STR_SVT_TEMPLATES
+{
+ Text [ en-US ] = "Templates";
+};
+
+Image IMG_SVT_TEMPLATES
+{
+ ImageBitmap = Bitmap { File = "template.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+Image IMG_SVT_TEMPLATES_HC
+{
+ ImageBitmap = Bitmap { File = "template_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+String STR_SVT_SAMPLES
+{
+ Text [ en-US ] = "Samples";
+};
+
+Image IMG_SVT_SAMPLES
+{
+ ImageBitmap = Bitmap { File = "samples.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+Image IMG_SVT_SAMPLES_HC
+{
+ ImageBitmap = Bitmap { File = "samples_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+ToolBox TB_SVT_FILEVIEW
+{
+ Pos = MAP_APPFONT ( 0 , 0 ) ;
+ Size = MAP_APPFONT ( 100 , 12 ) ;
+ ItemList =
+ {
+ ToolBoxItem
+ {
+ Identifier = TI_DOCTEMPLATE_BACK;
+ HelpId = HID_TEMPLATEDLG_TB_BACK;
+ Text [ en-US ] = "Back" ;
+ };
+ ToolBoxItem
+ {
+ Identifier = TI_DOCTEMPLATE_PREV;
+ HelpId = HID_TEMPLATEDLG_TB_PREV;
+ Text [ en-US ] = "Up One Level" ;
+ };
+ ToolBoxItem
+ {
+ Type = TOOLBOXITEM_SEPARATOR ;
+ };
+ ToolBoxItem
+ {
+ Identifier = TI_DOCTEMPLATE_PRINT;
+ HelpId = HID_TEMPLATEDLG_TB_PRINT;
+ Text [ en-US ] = "Print" ;
+ };
+ };
+};
+
+Image IMG_SVT_DOCTEMPLATE_BACK_SMALL
+{
+ ImageBitmap = Bitmap { File = "back_small.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPLATE_BACK_LARGE
+{
+ ImageBitmap = Bitmap { File = "back_large.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPLATE_PREV_SMALL
+{
+ ImageBitmap = Bitmap { File = "up_small.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPLATE_PREV_LARGE
+{
+ ImageBitmap = Bitmap { File = "up_large.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPLATE_PRINT_SMALL
+{
+ ImageBitmap = Bitmap { File = "sc05509.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPLATE_PRINT_LARGE
+{
+ ImageBitmap = Bitmap { File = "lc05509.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_BACK_SMALL
+{
+ ImageBitmap = Bitmap { File = "back_small_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_BACK_LARGE
+{
+ ImageBitmap = Bitmap { File = "back_large_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_PREV_SMALL
+{
+ ImageBitmap = Bitmap { File = "up_small_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_PREV_LARGE
+{
+ ImageBitmap = Bitmap { File = "up_large_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_PRINT_SMALL
+{
+ ImageBitmap = Bitmap { File = "sch05509.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_PRINT_LARGE
+{
+ ImageBitmap = Bitmap { File = "lch05509.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+ToolBox TB_SVT_FRAMEWIN
+{
+ Pos = MAP_APPFONT ( 0 , 0 ) ;
+ Size = MAP_APPFONT ( 100 , 12 ) ;
+ ItemList =
+ {
+ ToolBoxItem
+ {
+ RadioCheck = TRUE;
+ AutoCheck = TRUE;
+ Identifier = TI_DOCTEMPLATE_DOCINFO;
+ HelpId = HID_TEMPLATEDLG_TB_DOCINFO;
+ Text [ en-US ] = "Document Properties" ;
+ };
+ ToolBoxItem
+ {
+ RadioCheck = TRUE;
+ AutoCheck = TRUE;
+ Identifier = TI_DOCTEMPLATE_PREVIEW;
+ HelpId = HID_TEMPLATEDLG_TB_PREVIEW;
+ Text [ en-US ] = "Preview" ;
+ };
+ };
+};
+
+Image IMG_SVT_DOCTEMPLATE_DOCINFO_SMALL
+{
+ ImageBitmap = Bitmap { File = "info_small.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPLATE_DOCINFO_LARGE
+{
+ ImageBitmap = Bitmap { File = "info_large.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPLATE_PREVIEW_SMALL
+{
+ ImageBitmap = Bitmap { File = "preview_small.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPLATE_PREVIEW_LARGE
+{
+ ImageBitmap = Bitmap { File = "preview_large.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_DOCINFO_SMALL
+{
+ ImageBitmap = Bitmap { File = "info_small_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_DOCINFO_LARGE
+{
+ ImageBitmap = Bitmap { File = "info_large_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_PREVIEW_SMALL
+{
+ ImageBitmap = Bitmap { File = "preview_small_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+Image IMG_SVT_DOCTEMPL_HC_PREVIEW_LARGE
+{
+ ImageBitmap = Bitmap { File = "preview_large_h.bmp" ; };
+ MaskColor = MASK_COL_MAGENTA
+};
+
+ModalDialog DLG_DOCTEMPLATE
+{
+ HelpId = HID_TEMPLATEDLG_DIALOG ;
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT( 320, 250 );
+ Text [ en-US ] = "Templates and Documents" ;
+ Moveable = TRUE ;
+ FixedText FT_DOCTEMPLATE_LINK
+ {
+ Left = TRUE ;
+ Pos = MAP_APPFONT ( 6 , 208 ) ;
+ Size = MAP_APPFONT ( 311 , RSC_CD_FIXEDTEXT_HEIGHT ) ;
+ Text [ en-US ] = "~Get more templates online...";
+ };
+ FixedLine FL_DOCTEMPLATE
+ {
+ Pos = MAP_APPFONT( 0, 219 );
+ Size = MAP_APPFONT( 320, 8 );
+ };
+ PushButton BTN_DOCTEMPLATE_MANAGE
+ {
+ Pos = MAP_APPFONT( 6, 230 );
+ Size = MAP_APPFONT( 50, 14 );
+ Text [ en-US ] = "Organi~ze...";
+ };
+ PushButton BTN_DOCTEMPLATE_EDIT
+ {
+ Pos = MAP_APPFONT( 59, 230 );
+ Size = MAP_APPFONT( 50, 14 );
+ Text [ en-US ] = "~Edit";
+ };
+ OKButton BTN_DOCTEMPLATE_OPEN
+ {
+ Pos = MAP_APPFONT( 155, 230 );
+ Size = MAP_APPFONT( 50, 14 );
+ DefButton = TRUE;
+ Text [ en-US ] = "~Open";
+ };
+ CancelButton BTN_DOCTEMPLATE_CANCEL
+ {
+ Pos = MAP_APPFONT( 208, 230 );
+ Size = MAP_APPFONT( 50, 14 );
+ };
+ HelpButton BTN_DOCTEMPLATE_HELP
+ {
+ Pos = MAP_APPFONT( 264, 230 );
+ Size = MAP_APPFONT( 50, 14 );
+ };
+};
+
+StringArray STRARY_SVT_DOCINFO
+{
+ ItemList [ en-US ] =
+ {
+ < "Title" ; DI_TITLE ; > ;
+ < "By" ; DI_FROM ; > ;
+ < "Date" ; DI_DATE ; > ;
+ < "Keywords" ; DI_KEYWORDS ; > ;
+ < "Description" ; DI_DESCRIPTION ; > ;
+ < "Type" ; DI_MIMETYPE ; > ;
+ < "Modified on" ; DI_MODIFIEDDATE ; > ;
+ < "Modified by" ; DI_MODIFIEDBY ; > ;
+ < "Printed on" ; DI_PRINTDATE ; > ;
+ < "Printed by" ; DI_PRINTBY ; > ;
+ < "Subject" ; DI_THEME ; > ;
+ < "Size" ; DI_SIZE ; > ;
+ };
+ };
+
+String STR_SVT_NEWDOC_HELP
+{
+ Text [ en-US ] = "Click here to create new documents.";
+};
+String STR_SVT_MYDOCS_HELP
+{
+ Text [ en-US ] = "Contains your letters, reports and other documents";
+};
+String STR_SVT_TEMPLATES_HELP
+{
+ Text [ en-US ] = "Contains templates for creating new documents";
+};
+String STR_SVT_SAMPLES_HELP
+{
+ Text [ en-US ] = "Contains a selection of sample letters, reports and other documents";
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svtools/source/contnr/tooltiplbox.cxx b/svtools/source/contnr/tooltiplbox.cxx
new file mode 100644
index 000000000000..6aae495bd504
--- /dev/null
+++ b/svtools/source/contnr/tooltiplbox.cxx
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+#include "tooltiplbox.hxx"
+#include <vcl/help.hxx>
+
+// ============================================================================
+
+namespace svtools {
+
+// ----------------------------------------------------------------------------
+
+void lcl_ToolTipLBox_ShowToolTip( ListBox& rListBox, const HelpEvent& rHEvt )
+{
+ // only show tooltip if helpmode is BALLOON or QUICK
+ if ( !( rHEvt.GetMode() & HELPMODE_BALLOON ) && !( rHEvt.GetMode() & HELPMODE_QUICK ) )
+ {
+ // else call base class method
+ rListBox.ListBox::RequestHelp( rHEvt );
+ return ;
+ }
+
+ // find the list box entry the mouse points to
+ Point aMousePos( rListBox.ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+
+ sal_uInt16 nTop = rListBox.GetTopEntry();
+ sal_uInt16 nBottom = nTop + rListBox.GetDisplayLineCount();
+
+ sal_uInt16 nPos;
+ for( nPos = nTop; nPos < nBottom; ++nPos )
+ {
+ Rectangle aItemRect( rListBox.GetBoundingRectangle( nPos ) );
+ if( (aItemRect.Top() <= aMousePos.Y()) && (aMousePos.Y() <= aItemRect.Bottom()) )
+ break;
+ }
+
+ // show text content of the entry, if it does not fit
+ if( nPos < nBottom )
+ {
+ String aHelpText( rListBox.GetEntry( nPos ) );
+ if( rListBox.GetTextWidth( aHelpText ) > rListBox.GetOutputSizePixel().Width() )
+ {
+ Point aLBoxPos( rListBox.OutputToScreenPixel( Point( 0, 0 ) ) );
+ Size aLBoxSize( rListBox.GetSizePixel() );
+ Rectangle aLBoxRect( aLBoxPos, aLBoxSize );
+
+ if( rHEvt.GetMode() == HELPMODE_BALLOON )
+ Help::ShowBalloon( &rListBox, aLBoxRect.Center(), aLBoxRect, aHelpText );
+ else
+ Help::ShowQuickHelp( &rListBox, aLBoxRect, aHelpText );
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+ToolTipListBox::ToolTipListBox( Window* pParent, WinBits nStyle ) :
+ ListBox( pParent, nStyle )
+{
+}
+
+ToolTipListBox::ToolTipListBox( Window* pParent, const ResId& rResId ) :
+ ListBox( pParent, rResId )
+{
+}
+
+void ToolTipListBox::RequestHelp( const HelpEvent& rHEvt )
+{
+ lcl_ToolTipLBox_ShowToolTip( *this, rHEvt );
+}
+
+// ----------------------------------------------------------------------------
+
+ToolTipMultiListBox::ToolTipMultiListBox( Window* pParent, WinBits nStyle ) :
+ MultiListBox( pParent, nStyle )
+{
+}
+
+ToolTipMultiListBox::ToolTipMultiListBox( Window* pParent, const ResId& rResId ) :
+ MultiListBox( pParent, rResId )
+{
+}
+
+void ToolTipMultiListBox::RequestHelp( const HelpEvent& rHEvt )
+{
+ lcl_ToolTipLBox_ShowToolTip( *this, rHEvt );
+}
+
+// ----------------------------------------------------------------------------
+
+} // namespace svtools
+
+// ============================================================================
+
diff --git a/svtools/source/contnr/treelist.cxx b/svtools/source/contnr/treelist.cxx
new file mode 100644
index 000000000000..3395dffc28f5
--- /dev/null
+++ b/svtools/source/contnr/treelist.cxx
@@ -0,0 +1,2126 @@
+/*************************************************************************
+ *
+ * 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_svtools.hxx"
+
+#define _TREELIST_CXX
+
+#ifndef GCC
+#endif
+
+#include <svtools/treelist.hxx>
+
+#ifdef DBG_UTIL
+// Prueft Integritaet der Liste nach jeder Operation
+//#define CHECK_INTEGRITY
+#endif
+
+
+DBG_NAME(SvListEntry);
+
+SvListEntry::SvListEntry()
+{
+ DBG_CTOR(SvListEntry,0);
+ pChilds = 0;
+ pParent = 0;
+ nListPos = 0;
+ nAbsPos = 0;
+}
+
+SvListEntry::SvListEntry( const SvListEntry& rEntry )
+{
+ DBG_CTOR(SvListEntry,0);
+ pChilds = 0;
+ pParent = 0;
+ nListPos &= 0x80000000;
+ nListPos |= ( rEntry.nListPos & 0x7fffffff);
+ nAbsPos = rEntry.nAbsPos;
+}
+
+SvListEntry::~SvListEntry()
+{
+ DBG_DTOR(SvListEntry,0);
+ if ( pChilds )
+ {
+ pChilds->DestroyAll();
+ delete pChilds;
+ }
+#ifdef DBG_UTIL
+ pChilds = 0;
+ pParent = 0;
+#endif
+}
+
+void SvListEntry::Clone( SvListEntry* pSource)
+{
+ DBG_CHKTHIS(SvListEntry,0);
+ nListPos &= 0x80000000;
+ nListPos |= ( pSource->nListPos & 0x7fffffff);
+ nAbsPos = pSource->nAbsPos;
+}
+
+void SvListEntry::SetListPositions()
+{
+ if( pChilds )
+ {
+ SvListEntry *pEntry = (SvListEntry*)pChilds->First();
+ ULONG nCur = 0;
+ while ( pEntry )
+ {
+ pEntry->nListPos &= 0x80000000;
+ pEntry->nListPos |= nCur;
+ nCur++;
+ pEntry = (SvListEntry*)pChilds->Next();
+ }
+ }
+ nListPos &= (~0x80000000);
+}
+
+
+DBG_NAME(SvViewData);
+
+SvViewData::SvViewData()
+{
+ DBG_CTOR(SvViewData,0);
+ nFlags = 0;
+ nVisPos = 0;
+}
+
+SvViewData::SvViewData( const SvViewData& rData )
+{
+ DBG_CTOR(SvViewData,0);
+ nFlags = rData.nFlags;
+ nFlags &= ~( SVLISTENTRYFLAG_SELECTED | SVLISTENTRYFLAG_FOCUSED );
+ nVisPos = rData.nVisPos;
+}
+
+SvViewData::~SvViewData()
+{
+ DBG_DTOR(SvViewData,0);
+#ifdef DBG_UTIL
+ nVisPos = 0x12345678;
+ nFlags = 0x1234;
+#endif
+}
+
+void SvTreeEntryList::DestroyAll()
+{
+ SvListEntry* pPtr = (SvListEntry*)First();
+ while( pPtr )
+ {
+ delete pPtr;
+ pPtr = (SvListEntry*)Next();
+ }
+}
+
+
+
+
+#if defined (WIN) && defined (MSC)
+// siehe BugId 42896: Die Funktionen Prev, PrevVisible, Next, NextVisible
+// (andere?) funktionieren nicht mit Optimierung.
+#pragma optimize ("", off)
+#endif
+
+
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvTreeList::SvTreeList()
+{
+ nEntryCount = 0;
+ bAbsPositionsValid = FALSE;
+ nRefCount = 1;
+ pRootItem = new SvListEntry;
+ eSortMode = SortNone;
+}
+
+
+/*************************************************************************
+|*
+|* SvTreeList::~SvTreeList
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvTreeList::~SvTreeList()
+{
+ Clear();
+ delete pRootItem;
+#ifdef DBG_UTIL
+ pRootItem = 0;
+#endif
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::Broadcast
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+void SvTreeList::Broadcast( USHORT nActionId, SvListEntry* pEntry1,
+ SvListEntry* pEntry2, ULONG nPos )
+{
+ ULONG nViewCount = aViewList.Count();
+ for( ULONG nCurView = 0; nCurView < nViewCount; nCurView++ )
+ {
+ SvListView* pView = (SvListView*)aViewList.GetObject( nCurView );
+ if( pView )
+ pView->ModelNotification( nActionId, pEntry1, pEntry2, nPos );
+ }
+}
+
+void SvTreeList::InsertView( SvListView* pView)
+{
+ ULONG nPos = aViewList.GetPos( pView );
+ if ( nPos == LIST_ENTRY_NOTFOUND )
+ {
+ aViewList.Insert( pView, LIST_APPEND );
+ nRefCount++;
+ }
+}
+
+void SvTreeList::RemoveView( SvListView* pView )
+{
+ ULONG nPos = aViewList.GetPos( pView );
+ if ( nPos != LIST_ENTRY_NOTFOUND )
+ {
+ aViewList.Remove( pView );
+ nRefCount--;
+ }
+}
+
+
+// Ein Entry ist sichtbar, wenn alle Parents expandiert sind
+BOOL SvTreeList::IsEntryVisible( const SvListView* pView, SvListEntry* pEntry ) const
+{
+ DBG_ASSERT(pView&&pEntry,"IsVisible:Invalid Params");
+ BOOL bRetVal=FALSE;
+ do
+ {
+ if ( pEntry == pRootItem )
+ {
+ bRetVal=TRUE;
+ break;
+ }
+ pEntry = pEntry->pParent;
+ } while( pView->IsExpanded( pEntry ) );
+ return bRetVal;
+}
+
+USHORT SvTreeList::GetDepth( SvListEntry* pEntry ) const
+{
+ DBG_ASSERT(pEntry&&pEntry!=pRootItem,"GetDepth:Bad Entry");
+ USHORT nDepth = 0;
+ while( pEntry->pParent != pRootItem )
+ {
+ nDepth++;
+ pEntry = pEntry->pParent;
+ }
+ return nDepth;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+void SvTreeList::Clear()
+{
+ Broadcast( LISTACTION_CLEARING );
+ SvTreeEntryList* pRootList = pRootItem->pChilds;
+ if ( pRootList )
+ {
+ SvListEntry* pEntry = (SvListEntry*)(pRootList->First());
+ while( pEntry )
+ {
+ delete pEntry;
+ pEntry = (SvListEntry*)(pRootList->Next());
+ }
+ delete pRootItem->pChilds;
+ pRootItem->pChilds = 0;
+ }
+ nEntryCount = 0;
+ Broadcast( LISTACTION_CLEARED );
+}
+
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+BOOL SvTreeList::IsChild( SvListEntry* pParent, SvListEntry* pChild ) const
+{
+ if ( !pParent )
+ pParent = pRootItem;
+
+ BOOL bIsChild = FALSE;
+ SvTreeEntryList* pList = pParent->pChilds;
+ if ( !pList )
+ return FALSE;
+ SvListEntry* pActualChild = (SvListEntry*)(pList->First());
+ while( !bIsChild && pActualChild )
+ {
+ if ( pActualChild == pChild )
+ bIsChild = TRUE;
+ else
+ {
+ if ( pActualChild->pChilds )
+ bIsChild = IsChild( pActualChild, pChild );
+ pActualChild = (SvListEntry*)(pList->Next());
+ }
+ }
+ return bIsChild;
+}
+
+ULONG SvTreeList::Move(SvListEntry* pSrcEntry,SvListEntry* pTargetParent,ULONG nListPos)
+{
+ // pDest darf Null sein!
+ DBG_ASSERT(pSrcEntry,"Entry?");
+ if ( !pTargetParent )
+ pTargetParent = pRootItem;
+ DBG_ASSERT(pSrcEntry!=pTargetParent,"Move:Source=Target");
+
+ Broadcast( LISTACTION_MOVING, pSrcEntry, pTargetParent, nListPos );
+
+ if ( !pTargetParent->pChilds )
+ pTargetParent->pChilds = new SvTreeEntryList;
+ if ( pSrcEntry == pTargetParent )
+ return pSrcEntry->GetChildListPos();
+
+ bAbsPositionsValid = FALSE;
+
+ SvTreeEntryList* pDstList = pTargetParent->pChilds;
+ SvTreeEntryList* pSrcList = pSrcEntry->pParent->pChilds;
+
+ // Dummy-Ptr einfuegen, weil nListPos durch das
+ // folgende Remove ungueltig werden koennte
+ SvListEntry* pDummy = 0; pDstList->Insert( pDummy, nListPos );
+
+ // loeschen
+ pSrcList->Remove( pSrcEntry );
+ // Hat Parent noch Childs ?
+ if ( pSrcList->Count() == 0 )
+ {
+ // Keine Childs, deshalb Child-List loeschen
+ SvListEntry* pParent = pSrcEntry->pParent;
+ pParent->pChilds = 0;
+ delete pSrcList;
+ pSrcList = 0;
+ }
+
+ // Parent umsetzen (erst hier, weil wir zum Loeschen
+ // der ChildList den alten Parent noch benoetigen!)
+ pSrcEntry->pParent = pTargetParent;
+
+ pDstList->Replace( pSrcEntry, pDummy );
+
+ // Listenpositionen in Zielliste korrigieren
+ SetListPositions( pDstList );
+ if ( pSrcList && (ULONG)pSrcList != (ULONG)pDstList )
+ SetListPositions( pSrcList );
+
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+
+ ULONG nRetVal = pDstList->GetPos( pSrcEntry );
+ DBG_ASSERT(nRetVal==pSrcEntry->GetChildListPos(),"ListPos not valid");
+ Broadcast( LISTACTION_MOVED,pSrcEntry,pTargetParent,nRetVal);
+ return nRetVal;
+}
+
+ULONG SvTreeList::Copy(SvListEntry* pSrcEntry,SvListEntry* pTargetParent,ULONG nListPos)
+{
+ // pDest darf Null sein!
+ DBG_ASSERT(pSrcEntry,"Entry?");
+ if ( !pTargetParent )
+ pTargetParent = pRootItem;
+ if ( !pTargetParent->pChilds )
+ pTargetParent->pChilds = new SvTreeEntryList;
+
+ bAbsPositionsValid = FALSE;
+
+ ULONG nCloneCount = 0;
+ SvListEntry* pClonedEntry = Clone( pSrcEntry, nCloneCount );
+ nEntryCount += nCloneCount;
+
+ SvTreeEntryList* pDstList = pTargetParent->pChilds;
+ pClonedEntry->pParent = pTargetParent; // Parent umsetzen
+ pDstList->Insert( pClonedEntry, nListPos ); // Einfuegen
+ SetListPositions( pDstList ); // Listenpositionen in Zielliste korrigieren
+
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+ Broadcast( LISTACTION_INSERTED_TREE, pClonedEntry );
+ ULONG nRetVal = pDstList->GetPos( pClonedEntry );
+ return nRetVal;
+}
+
+
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+void SvTreeList::Move( SvListEntry* pSrcEntry, SvListEntry* pDstEntry )
+{
+ SvListEntry* pParent;
+ ULONG nPos;
+
+ if ( !pDstEntry )
+ {
+ pParent = pRootItem;
+ nPos = 0UL;
+ }
+ else
+ {
+ pParent = pDstEntry->pParent;
+ nPos = pDstEntry->GetChildListPos();
+ nPos++; // UNTER (Bildschirm) pDstEntry einfuegen
+ }
+ Move( pSrcEntry, pParent, nPos );
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+void SvTreeList::Copy( SvListEntry* pSrcEntry, SvListEntry* pDstEntry )
+{
+ SvListEntry* pParent;
+ ULONG nPos;
+
+ if ( !pDstEntry )
+ {
+ pParent = pRootItem;
+ nPos = 0UL;
+ }
+ else
+ {
+ pParent = pDstEntry->pParent;
+ nPos = pDstEntry->GetChildListPos()+1;
+ }
+ Copy( pSrcEntry, pParent, nPos );
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+void SvTreeList::InsertTree( SvListEntry* pSrcEntry, SvListEntry* pDstEntry)
+{
+ SvListEntry* pParent;
+ ULONG nPos;
+
+ if ( !pDstEntry )
+ {
+ pParent = pRootItem;
+ nPos = 0UL;
+ }
+ else
+ {
+ pParent = pDstEntry->pParent;
+ nPos = pDstEntry->GetChildListPos()+1;
+ }
+ InsertTree( pSrcEntry, pParent, nPos );
+}
+
+
+void SvTreeList::InsertTree(SvListEntry* pSrcEntry,
+ SvListEntry* pTargetParent,ULONG nListPos)
+{
+ DBG_ASSERT(pSrcEntry,"InsertTree:Entry?");
+ if ( !pSrcEntry )
+ return;
+
+ if ( !pTargetParent )
+ pTargetParent = pRootItem;
+ if ( !pTargetParent->pChilds )
+ pTargetParent->pChilds = new SvTreeEntryList;
+
+ // Sortierung beruecksichtigen
+ GetInsertionPos( pSrcEntry, pTargetParent, nListPos );
+
+ bAbsPositionsValid = FALSE;
+
+ pSrcEntry->pParent = pTargetParent; // Parent umsetzen
+ SvTreeEntryList* pDstList = pTargetParent->pChilds;
+ pDstList->Insert( pSrcEntry, nListPos ); // einfuegen
+ SetListPositions(pDstList); // Listenpositionen in Zielliste korrigieren
+ nEntryCount += GetChildCount( pSrcEntry );
+ nEntryCount++; // der Parent ist ja auch neu
+
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+ Broadcast(LISTACTION_INSERTED_TREE, pSrcEntry );
+}
+
+SvListEntry* SvTreeList::CloneEntry( SvListEntry* pSource ) const
+{
+ if( aCloneLink.IsSet() )
+ return (SvListEntry*)aCloneLink.Call( pSource );
+ SvListEntry* pEntry = CreateEntry();
+ pSource->Clone( pEntry );
+ return pSource;
+}
+
+SvListEntry* SvTreeList::CreateEntry() const
+{
+ return new SvListEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::Clone( SvListEntry* pEntry, ULONG& nCloneCount ) const
+{
+ SvListEntry* pClonedEntry = CloneEntry( pEntry );
+ nCloneCount = 1;
+ SvTreeEntryList* pChilds = pEntry->pChilds;
+ if ( pChilds )
+ pClonedEntry->pChilds=CloneChilds(pChilds,pClonedEntry,nCloneCount);
+ return pClonedEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvTreeEntryList* SvTreeList::CloneChilds( SvTreeEntryList* pChilds,
+ SvListEntry* pNewParent,
+ ULONG& nCloneCount ) const
+{
+ DBG_ASSERT(pChilds->Count(),"Childs?");
+ SvTreeEntryList* pClonedChilds = new SvTreeEntryList;
+ SvListEntry* pChild = (SvListEntry*)pChilds->First();
+ while ( pChild )
+ {
+ SvListEntry* pNewChild = CloneEntry( pChild );
+ nCloneCount++;
+ pNewChild->pParent = pNewParent;
+ SvTreeEntryList* pSubChilds = pChild->pChilds;
+ if ( pSubChilds )
+ {
+ pSubChilds = CloneChilds( pSubChilds, pNewChild, nCloneCount );
+ pNewChild->pChilds = pSubChilds;
+ }
+
+ pClonedChilds->Insert( pNewChild, LIST_APPEND );
+ pChild = (SvListEntry*)pChilds->Next();
+ }
+ return pClonedChilds;
+}
+
+
+/*************************************************************************
+|*
+|* SvTreeList::GetChildCount
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+ULONG SvTreeList::GetChildCount( SvListEntry* pParent ) const
+{
+ if ( !pParent )
+ return GetEntryCount();
+
+ if ( !pParent || !pParent->pChilds)
+ return 0;
+ ULONG nCount = 0;
+ USHORT nRefDepth = GetDepth( pParent );
+ USHORT nActDepth = nRefDepth;
+ do
+ {
+ pParent = Next( pParent, &nActDepth );
+ nCount++;
+ } while( pParent && nRefDepth < nActDepth );
+ nCount--;
+ return nCount;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+ULONG SvTreeList::GetVisibleChildCount(const SvListView* pView, SvListEntry* pParent) const
+{
+ DBG_ASSERT(pView,"GetVisChildCount:No View");
+ if ( !pParent )
+ pParent = pRootItem;
+ if ( !pParent || !pView->IsExpanded(pParent) || !pParent->pChilds )
+ return 0;
+ ULONG nCount = 0;
+ USHORT nRefDepth = GetDepth( pParent );
+ USHORT nActDepth = nRefDepth;
+ do
+ {
+ pParent = NextVisible( pView, pParent, &nActDepth );
+ nCount++;
+ } while( pParent && nRefDepth < nActDepth );
+ nCount--;
+ return nCount;
+}
+
+ULONG SvTreeList::GetChildSelectionCount(const SvListView* pView,SvListEntry* pParent) const
+{
+ DBG_ASSERT(pView,"GetChildSelCount:No View");
+ if ( !pParent )
+ pParent = pRootItem;
+ if ( !pParent || !pParent->pChilds)
+ return 0;
+ ULONG nCount = 0;
+ USHORT nRefDepth = GetDepth( pParent );
+ USHORT nActDepth = nRefDepth;
+ do
+ {
+ pParent = Next( pParent, &nActDepth );
+ if( pParent && pView->IsSelected( pParent ) && nRefDepth < nActDepth)
+ nCount++;
+ } while( pParent && nRefDepth < nActDepth );
+// nCount--;
+ return nCount;
+}
+
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::First() const
+{
+ if ( nEntryCount )
+ return (SvListEntry*)(pRootItem->pChilds->GetObject(0));
+ else
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::Next
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+SvListEntry* SvTreeList::Next( SvListEntry* pActEntry, USHORT* pDepth ) const
+{
+ DBG_ASSERT( pActEntry && pActEntry->pParent, "SvTreeList::Next: invalid entry/parent!" );
+ if ( !pActEntry || !pActEntry->pParent )
+ return NULL;
+
+ USHORT nDepth = 0;
+ int bWithDepth = FALSE;
+ if ( pDepth )
+ {
+ nDepth = *pDepth;
+ bWithDepth = TRUE;
+ }
+
+ SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
+ ULONG nActualPos = pActEntry->GetChildListPos();
+
+ if ( pActEntry->pChilds /* && pActEntry->pChilds->Count() */ )
+ {
+ nDepth++;
+ pActEntry = (SvListEntry*)(pActEntry->pChilds->GetObject(0));
+ if ( bWithDepth )
+ *pDepth = nDepth;
+ return pActEntry;
+ }
+
+ if ( pActualList->Count() > ( nActualPos + 1 ) )
+ {
+ pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos + 1 ));
+ if ( bWithDepth )
+ *pDepth = nDepth;
+ return pActEntry;
+ }
+
+ SvListEntry* pParent = pActEntry->pParent;
+ nDepth--;
+ while( pParent != pRootItem && pParent != 0 )
+ {
+ DBG_ASSERT(pParent!=0,"TreeData corrupt!");
+ pActualList = pParent->pParent->pChilds;
+ DBG_ASSERT(pActualList,"TreeData corrupt!");
+ nActualPos = pParent->GetChildListPos();
+ if ( pActualList->Count() > ( nActualPos + 1 ) )
+ {
+ pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos + 1 ));
+ if ( bWithDepth )
+ *pDepth = nDepth;
+ return pActEntry;
+ }
+ pParent = pParent->pParent;
+ nDepth--;
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::Prev
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+SvListEntry* SvTreeList::Prev( SvListEntry* pActEntry, USHORT* pDepth ) const
+{
+ DBG_ASSERT(pActEntry!=0,"Entry?");
+
+ USHORT nDepth = 0;
+ int bWithDepth = FALSE;
+ if ( pDepth )
+ {
+ nDepth = *pDepth;
+ bWithDepth = TRUE;
+ }
+
+ SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
+ ULONG nActualPos = pActEntry->GetChildListPos();
+
+ if ( nActualPos > 0 )
+ {
+ pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos - 1 ));
+ while( pActEntry->pChilds /* && pActEntry->pChilds->Count() */ )
+ {
+ pActualList = pActEntry->pChilds;
+ nDepth++;
+ pActEntry = (SvListEntry*)(pActualList->Last());
+ }
+ if ( bWithDepth )
+ *pDepth = nDepth;
+ return pActEntry;
+ }
+ if ( pActEntry->pParent == pRootItem )
+ return 0;
+
+ pActEntry = pActEntry->pParent;
+
+ if ( pActEntry )
+ {
+ nDepth--;
+ if ( bWithDepth )
+ *pDepth = nDepth;
+ return pActEntry;
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::Last( USHORT* /* nDepth */ ) const
+{
+ SvTreeEntryList* pActList = pRootItem->pChilds;
+// if ( pActList->Count() == 0 )
+// return 0;
+ SvListEntry* pEntry = 0;
+ while( pActList )
+ {
+ pEntry = (SvListEntry*)(pActList->Last());
+ pActList = pEntry->pChilds;
+// if ( pActList->Count() == 0 )
+// pActList = 0;
+ }
+ return pEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+ULONG SvTreeList::GetVisiblePos( const SvListView* pView, SvListEntry* pEntry ) const
+{
+ DBG_ASSERT(pView&&pEntry,"View/Entry?");
+
+ if ( !pView->bVisPositionsValid )
+ {
+ // damit GetVisibleCount die Positionen aktualisiert
+ ((SvListView*)pView)->nVisibleCount = 0;
+ GetVisibleCount( pView );
+ }
+ SvViewData* pViewData = pView->GetViewData( pEntry );
+ return pViewData->nVisPos;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+ULONG SvTreeList::GetVisibleCount( const SvListView* pView ) const
+{
+ DBG_ASSERT(pView,"GetVisCount:No View");
+ if( !pView->HasViewData() )
+ return 0;
+ if ( pView->nVisibleCount )
+ return pView->nVisibleCount;
+
+ ULONG nPos = 0;
+ SvListEntry* pEntry = First(); // erster Eintrag immer sichtbar
+ while ( pEntry )
+ {
+ SvViewData* pViewData = pView->GetViewData( pEntry );
+ pViewData->nVisPos = nPos;
+ nPos++;
+ pEntry = NextVisible( pView, pEntry );
+ }
+#ifdef DBG_UTIL
+ if( nPos > 10000000 )
+ {
+ DBG_ERROR("nVisibleCount bad");
+ }
+#endif
+ ((SvListView*)pView)->nVisibleCount = nPos;
+ ((SvListView*)pView)->bVisPositionsValid = TRUE;
+ return nPos;
+}
+
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+// Funktion geht aus Geschwindigkeitsgruenden davon aus,
+// das der uebergebene Eintrag bereits sichtbar ist
+
+SvListEntry* SvTreeList::NextVisible(const SvListView* pView,SvListEntry* pActEntry,USHORT* pActDepth) const
+{
+ DBG_ASSERT(pView,"NextVisible:No View");
+ if ( !pActEntry )
+ return 0;
+
+ USHORT nDepth = 0;
+ int bWithDepth = FALSE;
+ if ( pActDepth )
+ {
+ nDepth = *pActDepth;
+ bWithDepth = TRUE;
+ }
+
+ SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
+ ULONG nActualPos = pActEntry->GetChildListPos();
+
+ if ( pView->IsExpanded(pActEntry) )
+ {
+ DBG_ASSERT(pActEntry->pChilds,"Childs?");
+ nDepth++;
+ pActEntry = (SvListEntry*)(pActEntry->pChilds->GetObject(0));
+ if ( bWithDepth )
+ *pActDepth = nDepth;
+ return pActEntry;
+ }
+
+ nActualPos++;
+ if ( pActualList->Count() > nActualPos )
+ {
+ pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos ));
+ if ( bWithDepth )
+ *pActDepth = nDepth;
+ return pActEntry;
+ }
+
+ SvListEntry* pParent = pActEntry->pParent;
+ nDepth--;
+ while( pParent != pRootItem )
+ {
+ pActualList = pParent->pParent->pChilds;
+ nActualPos = pParent->GetChildListPos();
+ nActualPos++;
+ if ( pActualList->Count() > nActualPos )
+ {
+ pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos ));
+ if ( bWithDepth )
+ *pActDepth = nDepth;
+ return pActEntry;
+ }
+ pParent = pParent->pParent;
+ nDepth--;
+ }
+ return 0;
+}
+
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+// Funktion geht aus Geschwindigkeitsgruenden davon aus,
+// das der uebergebene Eintrag bereits sichtbar ist
+
+SvListEntry* SvTreeList::PrevVisible(const SvListView* pView, SvListEntry* pActEntry, USHORT* pActDepth) const
+{
+ DBG_ASSERT(pView&&pActEntry,"PrevVis:View/Entry?");
+
+ USHORT nDepth = 0;
+ int bWithDepth = FALSE;
+ if ( pActDepth )
+ {
+ nDepth = *pActDepth;
+ bWithDepth = TRUE;
+ }
+
+ SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
+ ULONG nActualPos = pActEntry->GetChildListPos();
+
+ if ( nActualPos > 0 )
+ {
+ pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos - 1 ));
+ while( pView->IsExpanded(pActEntry) )
+ {
+ pActualList = pActEntry->pChilds;
+ nDepth++;
+ pActEntry = (SvListEntry*)(pActualList->Last());
+ }
+ if ( bWithDepth )
+ *pActDepth = nDepth;
+ return pActEntry;
+ }
+
+ if ( pActEntry->pParent == pRootItem )
+ return 0;
+
+ pActEntry = pActEntry->pParent;
+ if ( pActEntry )
+ {
+ nDepth--;
+ if ( bWithDepth )
+ *pActDepth = nDepth;
+ return pActEntry;
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::LastVisible( const SvListView* pView, USHORT* pDepth) const
+{
+ DBG_ASSERT(pView,"LastVis:No View");
+ SvListEntry* pEntry = Last();
+ while( pEntry && !IsEntryVisible( pView, pEntry ) )
+ pEntry = PrevVisible( pView, pEntry );
+ if ( pEntry && pDepth )
+ *pDepth = GetDepth( pEntry );
+ return pEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::NextVisible(const SvListView* pView,SvListEntry* pEntry,USHORT& nDelta) const
+{
+ DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"NextVis:Wrong Prms/!Vis");
+
+ ULONG nVisPos = GetVisiblePos( pView, pEntry );
+ // nDelta Eintraege vorhanden ?
+ // Beispiel: 0,1,2,3,4,5,6,7,8,9 nVisPos=5 nDelta=7
+ // nNewDelta = 10-nVisPos-1 == 4
+ if ( nVisPos+nDelta >= pView->nVisibleCount )
+ {
+ nDelta = (USHORT)(pView->nVisibleCount-nVisPos);
+ nDelta--;
+ }
+ USHORT nDeltaTmp = nDelta;
+ while( nDeltaTmp )
+ {
+ pEntry = NextVisible( pView, pEntry );
+ nDeltaTmp--;
+ DBG_ASSERT(pEntry,"Entry?");
+ }
+ return pEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvListEntry* pEntry, USHORT& nDelta ) const
+{
+ DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis");
+
+ ULONG nVisPos = GetVisiblePos( pView, pEntry );
+ // nDelta Eintraege vorhanden ?
+ // Beispiel: 0,1,2,3,4,5,6,7,8,9 nVisPos=8 nDelta=20
+ // nNewDelta = nNewVisPos
+ if ( nDelta > nVisPos )
+ nDelta = (USHORT)nVisPos;
+ USHORT nDeltaTmp = nDelta;
+ while( nDeltaTmp )
+ {
+ pEntry = PrevVisible( pView, pEntry );
+ nDeltaTmp--;
+ DBG_ASSERT(pEntry,"Entry?");
+ }
+ return pEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::FirstSelected( const SvListView* pView) const
+{
+ DBG_ASSERT(pView,"FirstSel:No View");
+ if( !pView )
+ return 0;
+ SvListEntry* pActSelEntry = First();
+ while( pActSelEntry && !pView->IsSelected(pActSelEntry) )
+ pActSelEntry = NextVisible( pView, pActSelEntry );
+ return pActSelEntry;
+}
+
+
+SvListEntry* SvTreeList::FirstChild( SvListEntry* pParent ) const
+{
+ if ( !pParent )
+ pParent = pRootItem;
+ SvListEntry* pResult;
+ if ( pParent->pChilds )
+ pResult = (SvListEntry*)(pParent->pChilds->GetObject( 0 ));
+ else
+ pResult = 0;
+ return pResult;
+}
+
+SvListEntry* SvTreeList::NextSibling( SvListEntry* pEntry ) const
+{
+ DBG_ASSERT(pEntry,"Entry?");
+ if( !pEntry )
+ return 0;
+ SvTreeEntryList* pList = pEntry->pParent->pChilds;
+// ULONG nPos = pList->GetPos( pEntry );
+ ULONG nPos = pEntry->GetChildListPos();
+ nPos++;
+ pEntry = (SvListEntry*)(pList->GetObject( nPos ));
+ return pEntry;
+}
+
+SvListEntry* SvTreeList::PrevSibling( SvListEntry* pEntry ) const
+{
+ DBG_ASSERT(pEntry,"Entry?");
+ if( !pEntry )
+ return 0;
+
+ SvTreeEntryList* pList = pEntry->pParent->pChilds;
+ // ULONG nPos = pList->GetPos( pEntry );
+ ULONG nPos = pEntry->GetChildListPos();
+ if ( nPos == 0 )
+ return 0;
+ nPos--;
+ pEntry = (SvListEntry*)(pList->GetObject( nPos ));
+ return pEntry;
+}
+
+
+SvListEntry* SvTreeList::LastSibling( SvListEntry* pEntry ) const
+{
+ DBG_ASSERT(pEntry,"LastSibling:Entry?");
+ if( !pEntry )
+ return 0;
+ SvListEntry* pSib = 0;
+ SvTreeEntryList* pSibs = pEntry->pParent->pChilds;
+ if ( pSibs )
+ pSib = (SvListEntry*)(pSibs->Last());
+ return pSib;
+}
+
+
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::NextSelected( const SvListView* pView, SvListEntry* pEntry ) const
+{
+ DBG_ASSERT(pView&&pEntry,"NextSel:View/Entry?");
+ pEntry = Next( pEntry );
+ while( pEntry && !pView->IsSelected(pEntry) )
+ pEntry = Next( pEntry );
+ return pEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::PrevSelected( const SvListView* pView, SvListEntry* pEntry) const
+{
+ DBG_ASSERT(pView&&pEntry,"PrevSel:View/Entry?");
+ pEntry = Prev( pEntry );
+ while( pEntry && !pView->IsSelected(pEntry) )
+ pEntry = Prev( pEntry );
+
+ return pEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+SvListEntry* SvTreeList::LastSelected( const SvListView* pView ) const
+{
+ DBG_ASSERT(pView,"LastSel:No View");
+ SvListEntry* pEntry = Last();
+ while( pEntry && !pView->IsSelected(pEntry) )
+ pEntry = Prev( pEntry );
+ return pEntry;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::Insert
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+ULONG SvTreeList::Insert( SvListEntry* pEntry,SvListEntry* pParent,ULONG nPos )
+{
+ DBG_ASSERT( pEntry,"Entry?");
+
+ if ( !pParent )
+ pParent = pRootItem;
+
+
+ SvTreeEntryList* pList = pParent->pChilds;
+ if ( !pList )
+ {
+ // Parent bekommt zum erstenmal ein Kind
+ pList = new SvTreeEntryList;
+ pParent->pChilds = pList;
+ }
+
+ // Sortierung beruecksichtigen
+ GetInsertionPos( pEntry, pParent, nPos );
+
+ bAbsPositionsValid = FALSE;
+ pEntry->pParent = pParent;
+
+ pList->Insert( pEntry, nPos );
+ nEntryCount++;
+ if( nPos != LIST_APPEND && (nPos != (pList->Count()-1)) )
+ SetListPositions( pList );
+ else
+ pEntry->nListPos = pList->Count()-1;
+
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+ Broadcast( LISTACTION_INSERTED, pEntry );
+ return nPos; // pEntry->nListPos;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+ULONG SvTreeList::GetAbsPos( SvListEntry* pEntry) const
+{
+ if ( !bAbsPositionsValid )
+ ((SvTreeList*)this)->SetAbsolutePositions();
+ return pEntry->nAbsPos;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+void SvTreeList::SetAbsolutePositions()
+{
+ ULONG nPos = 0;
+ SvListEntry* pEntry = First();
+ while ( pEntry )
+ {
+ pEntry->nAbsPos = nPos;
+ nPos++;
+ pEntry = Next( pEntry );
+ }
+ bAbsPositionsValid = TRUE;
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+}
+
+
+/*************************************************************************
+|*
+|* SvTreeList::Expand
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+void SvTreeList::Expand( SvListView* pView, SvListEntry* pEntry )
+{
+ DBG_ASSERT(pEntry&&pView,"Expand:View/Entry?");
+ if ( pView->IsExpanded(pEntry) )
+ return;
+
+ DBG_ASSERT(pEntry->pChilds,"Expand:No Childs!");
+
+ SvViewData* pViewData = pView->GetViewData(pEntry);
+ pViewData->nFlags |= SVLISTENTRYFLAG_EXPANDED;
+ SvListEntry* pParent = pEntry->pParent;
+ // wenn Parent sichtbar dann Statusdaten invalidieren
+ if ( pView->IsExpanded( pParent ) )
+ {
+ pView->bVisPositionsValid = FALSE;
+ pView->nVisibleCount = 0;
+ }
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::Collapse
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+void SvTreeList::Collapse( SvListView* pView, SvListEntry* pEntry )
+{
+ DBG_ASSERT(pView&&pEntry,"Collapse:View/Entry?");
+ if ( !pView->IsExpanded(pEntry) )
+ return;
+
+ DBG_ASSERT(pEntry->pChilds,"Collapse:No Childs!");
+
+ SvViewData* pViewData = pView->GetViewData( pEntry );
+ pViewData->nFlags &=(~SVLISTENTRYFLAG_EXPANDED);
+
+ SvListEntry* pParent = pEntry->pParent;
+ if ( pView->IsExpanded(pParent) )
+ {
+ pView->nVisibleCount = 0;
+ pView->bVisPositionsValid = FALSE;
+ }
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+}
+
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+BOOL SvTreeList::Select( SvListView* pView, SvListEntry* pEntry, BOOL bSelect )
+{
+ DBG_ASSERT(pView&&pEntry,"Select:View/Entry?");
+ SvViewData* pViewData = pView->GetViewData( pEntry );
+ if ( bSelect )
+ {
+ if ( pViewData->IsSelected() || !pViewData->IsSelectable() )
+ return FALSE;
+ else
+ {
+ pViewData->nFlags |= SVLISTENTRYFLAG_SELECTED;
+ pView->nSelectionCount++;
+ }
+ }
+ else
+ {
+ if ( !pViewData->IsSelected() )
+ return FALSE;
+ else
+ {
+ pViewData->nFlags &= ~( SVLISTENTRYFLAG_SELECTED );
+ pView->nSelectionCount--;
+ }
+ }
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::Remove
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 05.04.01
+|*
+*************************************************************************/
+BOOL SvTreeList::Remove( SvListEntry* pEntry )
+{
+ DBG_ASSERT(pEntry,"Cannot remove root, use clear");
+
+ if( !pEntry->pParent )
+ {
+ DBG_ERROR("Removing entry not in model!");
+ // unter gewissen Umstaenden (welche?) loescht der
+ // Explorer aus der View Eintraege, die er nicht in die View
+ // eingefuegt hat. Da sich der Kunde fuer ein platzendes
+ // Office nichts kaufen kann, fange ich diesen Fall ab.
+ return FALSE;
+ }
+
+ Broadcast( LISTACTION_REMOVING, pEntry );
+ ULONG nRemoved = 1 + GetChildCount(pEntry);
+ bAbsPositionsValid = FALSE;
+
+ SvListEntry* pParent = pEntry->pParent;
+ SvTreeEntryList* pList = pParent->pChilds;
+ DBG_ASSERT(pList,"Remove:No Childlist");
+ BOOL bLastEntry = FALSE;
+
+ if ( pEntry->HasChildListPos() )
+ {
+ ULONG nListPos = pEntry->GetChildListPos();
+ bLastEntry = (nListPos == (pList->Count()-1) ) ? TRUE : FALSE;
+ pList->Remove( nListPos );
+ }
+ else
+ {
+ pList->Remove( (void*) pEntry );
+ }
+
+
+ // moved to end of method because it is used later with Broadcast
+ // delete pEntry; // loescht auch alle Childs
+
+ if ( pList->Count() == 0 )
+ {
+ pParent->pChilds = 0;
+ delete pList;
+ }
+ else
+ {
+ if( !bLastEntry )
+ SetListPositions( pList );
+ }
+ nEntryCount -= nRemoved;
+
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+ Broadcast( LISTACTION_REMOVED, pEntry );
+
+ delete pEntry; // loescht auch alle Childs
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* SvTreeList::
+|*
+|* Beschreibung
+|* Ersterstellung 17.08.94
+|* Letzte Aenderung 17.08.94
+|*
+*************************************************************************/
+
+ULONG SvTreeList::SelectChilds(SvListView* pView, SvListEntry* pParent,BOOL bSelect )
+{
+ DBG_ASSERT(pView&&pParent,"SelChilds:View/Parent?");
+ if ( !pParent->pChilds )
+ return 0;
+ if ( pParent->pChilds->Count() == 0 )
+ return 0;
+
+ USHORT nRefDepth = GetDepth( pParent );
+ USHORT nDepth = nRefDepth;
+ ULONG nCount = 0;
+ pParent = Next( pParent );
+ do
+ {
+ if ( Select( pView, pParent, bSelect ) )
+ nCount++; // nur die tatsaechlichen Selektierungen zaehlen
+ pParent = Next( pParent, &nDepth );
+ }
+ while( pParent && nDepth > nRefDepth );
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+ return nCount;
+}
+
+void SvTreeList::SelectAll( SvListView* pView, BOOL bSelect )
+{
+ DBG_ASSERT(pView,"SelectAll:NoView");
+ SvListEntry* pEntry = First();
+ while ( pEntry )
+ {
+ SvViewData* pViewData = pView->GetViewData( pEntry );
+ if ( bSelect )
+ pViewData->nFlags |= SVLISTENTRYFLAG_SELECTED;
+ else
+ pViewData->nFlags &= (~SVLISTENTRYFLAG_SELECTED);
+
+ pEntry = Next( pEntry );
+ }
+ if ( bSelect )
+ pView->nSelectionCount = nEntryCount;
+ else
+ pView->nSelectionCount = 0;
+#ifdef CHECK_INTEGRITY
+CheckIntegrity();
+#endif
+}
+
+
+SvListEntry* SvTreeList::GetEntryAtAbsPos( ULONG nAbsPos ) const
+{
+ SvListEntry* pEntry = First();
+ while ( nAbsPos && pEntry )
+ {
+ pEntry = Next( pEntry );
+ nAbsPos--;
+ }
+ return pEntry;
+}
+
+SvListEntry* SvTreeList::GetEntryAtVisPos( const SvListView* pView, ULONG nVisPos ) const
+{
+ DBG_ASSERT(pView,"GetEntryAtVisPos:No View");
+ SvListEntry* pEntry = First();
+ while ( nVisPos && pEntry )
+ {
+ pEntry = NextVisible( pView, pEntry );
+ nVisPos--;
+ }
+ return pEntry;
+}
+
+void SvTreeList::SetListPositions( SvTreeEntryList* pList )
+{
+ if( pList->Count() )
+ {
+ SvListEntry* pEntry = (SvListEntry*)(pList->GetObject(0));
+ if( pEntry->pParent )
+ pEntry->pParent->InvalidateChildrensListPositions();
+ }
+ /*
+ ULONG nListPos = 0;
+ SvListEntry* pEntry = (SvListEntry*)(pList->First());
+ while( pEntry )
+ {
+ pEntry->nListPos = nListPos;
+ nListPos++;
+ pEntry = (SvListEntry*)(pList->Next());
+ }
+ */
+}
+
+
+void SvTreeList::InvalidateEntry( SvListEntry* pEntry )
+{
+ Broadcast( LISTACTION_INVALIDATE_ENTRY, pEntry );
+}
+
+BOOL SvTreeList::IsInChildList( SvListEntry* pParent, SvListEntry* pChild) const
+{
+ if ( !pParent )
+ pParent = pRootItem;
+ BOOL bIsChild = FALSE;
+ if ( pParent->pChilds )
+ bIsChild = (BOOL)(pParent->pChilds->GetPos(pChild) != LIST_ENTRY_NOTFOUND);
+ return bIsChild;
+}
+
+
+void lcl_CheckList( SvTreeEntryList* pList )
+{
+ SvListEntry* pEntry = (SvListEntry*)(pList->First());
+ ULONG nPos = 0;
+ while ( pEntry )
+ {
+ DBG_ASSERT(pEntry->GetChildListPos()==nPos,"Wrong ListPos");
+ pEntry = (SvListEntry*)(pList->Next());
+ nPos++;
+ }
+}
+
+void SvTreeList::CheckIntegrity() const
+{
+ ULONG nMyEntryCount = 0;
+ if ( pRootItem->pChilds )
+ {
+ lcl_CheckList( pRootItem->pChilds );
+ SvListEntry* pEntry = First();
+ while( pEntry )
+ {
+ nMyEntryCount++;
+ if ( pEntry->pChilds )
+ lcl_CheckList( pEntry->pChilds );
+ pEntry = Next( pEntry );
+ }
+ }
+ DBG_ASSERT(nMyEntryCount==GetEntryCount(),"Entry count invalid");
+}
+
+SvListEntry* SvTreeList::GetRootLevelParent( SvListEntry* pEntry ) const
+{
+ DBG_ASSERT(pEntry,"GetRootLevelParent:No Entry");
+ SvListEntry* pCurParent = 0;
+ if ( pEntry )
+ {
+ pCurParent = pEntry->pParent;
+ if ( pCurParent == pRootItem )
+ return pEntry; // ist sein eigener Parent
+ while( pCurParent && pCurParent->pParent != pRootItem )
+ pCurParent = pCurParent->pParent;
+ }
+ return pCurParent;
+}
+
+
+
+
+//*************************************************************************
+//*************************************************************************
+//*************************************************************************
+//*************************************************************************
+//*************************************************************************
+//*************************************************************************
+//*************************************************************************
+//*************************************************************************
+
+DBG_NAME(SvListView);
+
+SvListView::SvListView( SvTreeList* pModell )
+{
+ DBG_CTOR(SvListView,0);
+ pModel = 0;
+ nSelectionCount = 0;
+ nVisibleCount = 0;
+ bVisPositionsValid = FALSE;
+ SetModel( pModell );
+}
+
+SvListView::SvListView()
+{
+ DBG_CTOR(SvListView,0);
+ pModel = 0;
+ nSelectionCount = 0;
+ nVisibleCount = 0;
+ bVisPositionsValid = FALSE;
+}
+
+
+SvListView::~SvListView()
+{
+ DBG_DTOR(SvListView,0);
+ ClearTable();
+}
+
+void SvListView::InitTable()
+{
+ DBG_CHKTHIS(SvListView,0);
+ DBG_ASSERT(pModel,"InitTable:No Model");
+ DBG_ASSERT(!nSelectionCount&&!nVisibleCount&&!bVisPositionsValid,"InitTable: Not cleared!");
+
+ if( aDataTable.Count() )
+ {
+ DBG_ASSERT(aDataTable.Count()==1,"InitTable: TableCount != 1");
+ // die im Clear fuer die Root allozierten View-Daten loeschen
+ // Achtung: Das zu dem RootEntry (und damit auch der Entry)
+ // gehoerende Model kann bereits geloescht sein!
+ SvViewData* pViewData = (SvViewData*)aDataTable.GetObject( 0 );
+ delete pViewData;
+ aDataTable.Clear();
+ }
+
+ SvListEntry* pEntry;
+ SvViewData* pViewData;
+
+ // RootEntry einfuegen
+ pEntry = pModel->pRootItem;
+ pViewData = new SvViewData;
+ pViewData->nFlags = SVLISTENTRYFLAG_EXPANDED;
+ aDataTable.Insert( (ULONG)pEntry, pViewData );
+ // Jetzt alle anderen Entries
+ pEntry = pModel->First();
+ while( pEntry )
+ {
+ pViewData = CreateViewData( pEntry );
+ DBG_ASSERT(pViewData,"InitTable:No ViewData");
+ InitViewData( pViewData, pEntry );
+ aDataTable.Insert( (ULONG)pEntry, pViewData );
+ pEntry = pModel->Next( pEntry );
+ }
+}
+
+SvViewData* SvListView::CreateViewData( SvListEntry* )
+{
+ DBG_CHKTHIS(SvListView,0);
+ return new SvViewData;
+}
+
+void SvListView::ClearTable()
+{
+ DBG_CHKTHIS(SvListView,0);
+ SvViewData* pViewData = (SvViewData*)aDataTable.First();
+ while( pViewData )
+ {
+ delete pViewData;
+ pViewData = (SvViewData*)aDataTable.Next();
+ }
+ aDataTable.Clear();
+}
+
+void SvListView::Clear()
+{
+ ClearTable();
+ nSelectionCount = 0;
+ nVisibleCount = 0;
+ bVisPositionsValid = FALSE;
+ if( pModel )
+ {
+ // RootEntry einfuegen
+ SvListEntry* pEntry = pModel->pRootItem;
+ SvViewData* pViewData = new SvViewData;
+ pViewData->nFlags = SVLISTENTRYFLAG_EXPANDED;
+ aDataTable.Insert( (ULONG)pEntry, pViewData );
+ }
+}
+
+void SvListView::SetModel( SvTreeList* pNewModel )
+{
+ DBG_CHKTHIS(SvListView,0);
+ BOOL bBroadcastCleared = FALSE;
+ if ( pModel )
+ {
+ pModel->RemoveView( this );
+ bBroadcastCleared = TRUE;
+ ModelNotification( LISTACTION_CLEARING,0,0,0 );
+ if ( pModel->GetRefCount() == 0 )
+ delete pModel;
+ }
+ pModel = pNewModel;
+ InitTable();
+ pNewModel->InsertView( this );
+ if( bBroadcastCleared )
+ ModelNotification( LISTACTION_CLEARED,0,0,0 );
+}
+
+
+void SvListView::ModelHasCleared()
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+void SvListView::ModelHasInserted( SvListEntry* )
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+void SvListView::ModelHasInsertedTree( SvListEntry* )
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+void SvListView::ModelIsMoving( SvListEntry* /* pSource */ ,
+ SvListEntry* /* pTargetParent */ , ULONG /* nPos */ )
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+
+void SvListView::ModelHasMoved( SvListEntry* )
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+void SvListView::ModelIsRemoving( SvListEntry* )
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+void SvListView::ModelHasRemoved( SvListEntry* )
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+void SvListView::ModelHasEntryInvalidated( SvListEntry*)
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+void SvListView::ActionMoving( SvListEntry* pEntry,SvListEntry*,ULONG)
+{
+ DBG_CHKTHIS(SvListView,0);
+ SvListEntry* pParent = pEntry->pParent;
+ DBG_ASSERT(pParent,"Model not consistent");
+ if( pParent != pModel->pRootItem && pParent->pChilds->Count() == 1 )
+ {
+ SvViewData* pViewData = (SvViewData*)aDataTable.Get( (ULONG)pParent );
+ pViewData->nFlags &= (~SVLISTENTRYFLAG_EXPANDED);
+ }
+ // vorlaeufig
+ nVisibleCount = 0;
+ bVisPositionsValid = FALSE;
+}
+
+void SvListView::ActionMoved( SvListEntry* /* pEntry */ ,
+ SvListEntry* /* pTargetPrnt */ ,
+ ULONG /* nChildPos */ )
+{
+ DBG_CHKTHIS(SvListView,0);
+ nVisibleCount = 0;
+ bVisPositionsValid = FALSE;
+}
+
+void SvListView::ActionInserted( SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvListView,0);
+ DBG_ASSERT(pEntry,"Insert:No Entry");
+ SvViewData* pData = CreateViewData( pEntry );
+ InitViewData( pData, pEntry );
+ #ifdef DBG_UTIL
+ BOOL bSuccess =
+ #endif
+ aDataTable.Insert( (ULONG)pEntry, pData );
+ DBG_ASSERT(bSuccess,"Entry already in View");
+ if ( nVisibleCount && pModel->IsEntryVisible( this, pEntry ))
+ {
+ nVisibleCount = 0;
+ bVisPositionsValid = FALSE;
+ }
+}
+
+void SvListView::ActionInsertedTree( SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvListView,0);
+ if ( pModel->IsEntryVisible( this, pEntry ))
+ {
+ nVisibleCount = 0;
+ bVisPositionsValid = FALSE;
+ }
+ // ueber Entry und seine Childs iterieren
+ SvListEntry* pCurEntry = pEntry;
+ USHORT nRefDepth = pModel->GetDepth( pCurEntry );
+ while( pCurEntry )
+ {
+ DBG_ASSERT(aDataTable.Get((ULONG)pCurEntry)==0,"Entry already in Table");
+ SvViewData* pViewData = CreateViewData( pCurEntry );
+ DBG_ASSERT(pViewData,"No ViewData");
+ InitViewData( pViewData, pEntry );
+ aDataTable.Insert( (ULONG)pCurEntry, pViewData );
+ pCurEntry = pModel->Next( pCurEntry );
+ if ( pCurEntry && pModel->GetDepth(pCurEntry) <= nRefDepth)
+ pCurEntry = 0;
+ }
+}
+
+void SvListView::RemoveViewData( SvListEntry* pParent )
+{
+ SvTreeEntryList* pChilds = pParent->pChilds;
+ if( pChilds )
+ {
+ SvListEntry* pCur = (SvListEntry*)pChilds->First();
+ while( pCur )
+ {
+ SvViewData* pViewData = (SvViewData*)aDataTable.Get((ULONG)pCur);
+ delete pViewData;
+ aDataTable.Remove( (ULONG)pCur );
+ if( pCur->HasChilds())
+ RemoveViewData( pCur );
+ pCur = (SvListEntry*)pChilds->Next();
+ }
+ }
+}
+
+
+
+void SvListView::ActionRemoving( SvListEntry* pEntry )
+{
+ DBG_CHKTHIS(SvListView,0);
+ DBG_ASSERT(pEntry,"Remove:No Entry");
+
+ SvViewData* pViewData = (SvViewData*)aDataTable.Get( (ULONG)pEntry );
+ ULONG nSelRemoved = 0;
+ if ( pViewData->IsSelected() )
+ nSelRemoved = 1 + pModel->GetChildSelectionCount( this, pEntry );
+ nSelectionCount -= nSelRemoved;
+ ULONG nVisibleRemoved = 0;
+ if ( pModel->IsEntryVisible( this, pEntry ) )
+ nVisibleRemoved = 1 + pModel->GetVisibleChildCount( this, pEntry );
+ if( nVisibleCount )
+ {
+#ifdef DBG_UTIL
+ if( nVisibleCount < nVisibleRemoved )
+ {
+ DBG_ERROR("nVisibleRemoved bad");
+ }
+#endif
+ nVisibleCount -= nVisibleRemoved;
+ }
+ bVisPositionsValid = FALSE;
+
+ pViewData = (SvViewData*)aDataTable.Get((ULONG)pEntry);
+ delete pViewData;
+ aDataTable.Remove( (ULONG)pEntry );
+ RemoveViewData( pEntry );
+
+ SvListEntry* pCurEntry = pEntry->pParent;
+ if ( pCurEntry && pCurEntry != pModel->pRootItem &&
+ pCurEntry->pChilds->Count() == 1 )
+ {
+ pViewData = (SvViewData*)aDataTable.Get((ULONG)pCurEntry);
+ pViewData->nFlags &= (~SVLISTENTRYFLAG_EXPANDED);
+ }
+}
+
+void SvListView::ActionRemoved( SvListEntry* /* pEntry */ )
+{
+ DBG_CHKTHIS(SvListView,0);
+}
+
+void SvListView::ActionClear()
+{
+ DBG_CHKTHIS(SvListView,0);
+ Clear();
+}
+
+void SvListView::ModelNotification( USHORT nActionId, SvListEntry* pEntry1,
+ SvListEntry* pEntry2, ULONG nPos )
+{
+ DBG_CHKTHIS(SvListView,0);
+ switch( nActionId )
+ {
+ case LISTACTION_INSERTED:
+ ActionInserted( pEntry1 );
+ ModelHasInserted( pEntry1 );
+ break;
+ case LISTACTION_INSERTED_TREE:
+ ActionInsertedTree( pEntry1 );
+ ModelHasInsertedTree( pEntry1 );
+ break;
+ case LISTACTION_REMOVING:
+ ModelIsRemoving( pEntry1 );
+ ActionRemoving( pEntry1 );
+ break;
+ case LISTACTION_REMOVED:
+ ActionRemoved( pEntry1 );
+ ModelHasRemoved( pEntry1 );
+ break;
+ case LISTACTION_MOVING:
+ ModelIsMoving( pEntry1, pEntry2, nPos );
+ ActionMoving( pEntry1, pEntry2, nPos );
+ break;
+ case LISTACTION_MOVED:
+ ActionMoved( pEntry1, pEntry2, nPos );
+ ModelHasMoved( pEntry1 );
+ break;
+ case LISTACTION_CLEARING:
+ ActionClear();
+ ModelHasCleared(); //sic! wg. Kompatibilitaet!
+ break;
+ case LISTACTION_CLEARED:
+ break;
+ case LISTACTION_INVALIDATE_ENTRY:
+ // keine Action fuer die Basisklasse
+ ModelHasEntryInvalidated( pEntry1 );
+ break;
+ case LISTACTION_RESORTED:
+ bVisPositionsValid = FALSE;
+ break;
+ case LISTACTION_RESORTING:
+ break;
+ default:
+ DBG_ERROR("unknown ActionId");
+ }
+}
+
+void SvListView::InitViewData( SvViewData*, SvListEntry* )
+{
+}
+
+StringCompare SvTreeList::Compare( SvListEntry* pLeft, SvListEntry* pRight) const
+{
+ if( aCompareLink.IsSet())
+ {
+ SvSortData aSortData;
+ aSortData.pLeft = pLeft;
+ aSortData.pRight = pRight;
+ return (StringCompare)aCompareLink.Call( &aSortData );
+ }
+ return COMPARE_EQUAL;
+}
+
+void SvTreeList::Resort()
+{
+ Broadcast( LISTACTION_RESORTING );
+ bAbsPositionsValid = FALSE;
+ ResortChilds( pRootItem );
+ Broadcast( LISTACTION_RESORTED );
+}
+
+void SvTreeList::ResortChilds( SvListEntry* pParent )
+{
+ DBG_ASSERT(pParent,"Parent not set");
+ List* pChildList = pParent->pChilds;
+ if( !pChildList )
+ return;
+ List aList( *pChildList );
+ pChildList->Clear();
+
+ ULONG nCount = aList.Count();
+ for( ULONG nCur = 0; nCur < nCount; nCur++ )
+ {
+ SvListEntry* pCurEntry = (SvListEntry*)aList.GetObject( nCur );
+ ULONG nListPos = LIST_APPEND;
+ GetInsertionPos( pCurEntry, pParent, nListPos );
+ pChildList->Insert( pCurEntry, nListPos );
+ if( pCurEntry->pChilds )
+ ResortChilds( pCurEntry );
+ }
+ SetListPositions( (SvTreeEntryList*)pChildList );
+}
+
+void SvTreeList::GetInsertionPos( SvListEntry* pEntry, SvListEntry* pParent,
+ ULONG& rPos )
+{
+ DBG_ASSERT(pEntry,"No Entry");
+
+ if( eSortMode == SortNone )
+ return;
+
+ rPos = LIST_APPEND;
+ SvTreeEntryList* pChildList = GetChildList( pParent );
+
+ if( pChildList && pChildList->Count() )
+ {
+ long i = 0;
+ long j = pChildList->Count()-1;
+ long k;
+ StringCompare eCompare = COMPARE_GREATER;
+
+ do
+ {
+ k = (i+j)/2;
+ SvListEntry* pTempEntry = (SvListEntry*)(pChildList->GetObject(k));
+ eCompare = Compare( pEntry, pTempEntry );
+ if( eSortMode == SortDescending && eCompare != COMPARE_EQUAL )
+ {
+ if( eCompare == COMPARE_LESS )
+ eCompare = COMPARE_GREATER;
+ else
+ eCompare = COMPARE_LESS;
+ }
+ if( eCompare == COMPARE_GREATER )
+ i = k + 1;
+ else
+ j = k - 1;
+ } while( (eCompare != COMPARE_EQUAL) && (i <= j) );
+
+ if( eCompare != COMPARE_EQUAL )
+ {
+ if(i > ((long)pChildList->Count() - 1)) // nicht gefunden, Ende der Liste
+ rPos = LIST_APPEND;
+ else
+ rPos = i; // nicht gefunden, Mitte
+ }
+ else
+ rPos = k;
+ }
+}
+
+