Tag: cws_dev300_dba30d User: fs Date: 2008-06-11 20:25:25+0000 Modified: dba/dbaccess/source/ui/app/AppController.cxx dba/dbaccess/source/ui/app/AppController.hxx
Log: #i80943# implement XSelectionSupplier (not implemented by the base class anymore) and properly implement ::select when a (sequence of) NamedDatabaseObject is selected File Changes: Directory: /dba/dbaccess/source/ui/app/ ======================================= File [changed]: AppController.cxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ui/app/AppController.cxx?r1=1.60.10.6&r2=1.60.10.7 Delta lines: +227 -19 ---------------------- --- AppController.cxx 2008-06-10 14:00:09+0000 1.60.10.6 +++ AppController.cxx 2008-06-11 20:25:22+0000 1.60.10.7 @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: AppController.cxx,v $ - * $Revision: 1.60.10.6 $ + * $Revision: 1.60.10.7 $ * * This file is part of OpenOffice.org. * @@ -74,6 +74,8 @@ #include "com/sun/star/beans/NamedValue.hpp" #include <com/sun/star/awt/XTopWindow.hpp> #include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/sdb/application/DatabaseObject.hpp> +#include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp> /** === end UNO includes === **/ #ifndef _TOOLS_DEBUG_HXX @@ -233,6 +235,8 @@ #include <algorithm> #include <functional> +#include <boost/noncopyable.hpp> + extern "C" void SAL_CALL createRegistryInfo_ODBApplication() { static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OApplicationController > aAutoRegistration; @@ -261,6 +265,9 @@ using ::com::sun::star::document::XEmbeddedScripts; using ::com::sun::star::sdb::application::NamedDatabaseObject; +namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject; +namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer; + //------------------------------------------------------------------------------ ::rtl::OUString SAL_CALL OApplicationController::getImplementationName() throw( RuntimeException ) { @@ -308,6 +315,91 @@ //==================================================================== //= OApplicationController //==================================================================== +class SelectionNotifier : public ::boost::noncopyable +{ +private: + ::cppu::OInterfaceContainerHelper m_aSelectionListeners; + ::cppu::OWeakObject& m_rContext; + sal_Int32 m_nSelectionNestingLevel; + +public: + SelectionNotifier( ::osl::Mutex& _rMutex, ::cppu::OWeakObject& _rContext ) + :m_aSelectionListeners( _rMutex ) + ,m_rContext( _rContext ) + ,m_nSelectionNestingLevel( 0 ) + { + } + + void addListener( const Reference< XSelectionChangeListener >& _Listener ) + { + m_aSelectionListeners.addInterface( _Listener ); + } + + void removeListener( const Reference< XSelectionChangeListener >& _Listener ) + { + m_aSelectionListeners.removeInterface( _Listener ); + } + + void disposing() + { + EventObject aEvent( m_rContext ); + m_aSelectionListeners.disposeAndClear( aEvent ); + } + + ~SelectionNotifier() + { + } + + struct SelectionGuardAccess { friend class SelectionGuard; private: SelectionGuardAccess() { } }; + + /** enters a block which modifies the selection of our owner. + + Can be called multiple times, the only important thing is to call leaveSelection + equally often. + */ + void enterSelection( SelectionGuardAccess ) + { + ++m_nSelectionNestingLevel; + } + + /** leaves a block which modifies the selection of our owner + + Must be paired with enterSelection calls. + + When the last block is left, i.e. the last leaveSelection call is made on the current stack, + then our SelectionChangeListeners are notified + */ + void leaveSelection( SelectionGuardAccess ) + { + if ( --m_nSelectionNestingLevel == 0 ) + { + EventObject aEvent( m_rContext ); + m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvent ); + } + } +}; + +class SelectionGuard : public ::boost::noncopyable +{ +public: + SelectionGuard( SelectionNotifier& _rNotifier ) + :m_rNotifier( _rNotifier ) + { + m_rNotifier.enterSelection( SelectionNotifier::SelectionGuardAccess() ); + } + + ~SelectionGuard() + { + m_rNotifier.leaveSelection( SelectionNotifier::SelectionGuardAccess() ); + } + +private: + SelectionNotifier& m_rNotifier; +}; + +//==================================================================== +//= OApplicationController +//==================================================================== DBG_NAME(OApplicationController) //-------------------------------------------------------------------- OApplicationController::OApplicationController(const Reference< XMultiServiceFactory >& _rxORB) @@ -317,10 +409,12 @@ ,m_pClipbordNotifier(NULL) ,m_nAsyncDrop(0) ,m_aControllerConnectedEvent( LINK( this, OApplicationController, OnFirstControllerConnected ) ) + ,m_aSelectContainerEvent( LINK( this, OApplicationController, OnSelectContainer ) ) ,m_ePreviewMode(E_PREVIEWNONE) ,m_eCurrentType(E_NONE) ,m_bNeedToReconnect(sal_False) ,m_bSuspended( sal_False ) + ,m_pSelectionNotifier( new SelectionNotifier( m_aMutex, *this ) ) { DBG_CTOR(OApplicationController,NULL); @@ -377,6 +471,7 @@ m_aCurrentContainers.clear(); m_aSpecialSubFrames.clear(); m_aDocuments.clear(); + m_pSelectionNotifier->disposing(); if ( getView() ) { @@ -1397,17 +1492,16 @@ impl_migrateScripts_nothrow(); break; case SID_DB_APP_VIEW_TABLES: - getContainer()->PostUserEvent( LINK( this, OApplicationController, OnSelectContainer ), reinterpret_cast< void* >( E_TABLE ) ); - // getContainer()->selectContainer(E_TABLE); + m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_TABLE ) ); break; case SID_DB_APP_VIEW_QUERIES: - getContainer()->PostUserEvent( LINK( this, OApplicationController, OnSelectContainer ), reinterpret_cast< void* >( E_QUERY ) ); + m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_QUERY ) ); break; case SID_DB_APP_VIEW_FORMS: - getContainer()->PostUserEvent( LINK( this, OApplicationController, OnSelectContainer ), reinterpret_cast< void* >( E_FORM ) ); + m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_FORM ) ); break; case SID_DB_APP_VIEW_REPORTS: - getContainer()->PostUserEvent( LINK( this, OApplicationController, OnSelectContainer ), reinterpret_cast< void* >( E_REPORT ) ); + m_aSelectContainerEvent.Call( reinterpret_cast< void* >( E_REPORT ) ); break; case SID_DB_APP_DISABLE_PREVIEW: m_ePreviewMode = E_PREVIEWNONE; @@ -1707,6 +1801,8 @@ if ( m_eCurrentType != _eType && _eType != E_NONE ) { + SelectionGuard aSelGuard( *m_pSelectionNotifier ); + if ( _eType == E_TABLE ) { try @@ -1753,9 +1849,17 @@ getContainer()->getDetailView()->createPage(_eType,xContainer); } + SelectionByElementType::iterator pendingSelection = m_aPendingSelection.find( _eType ); + if ( pendingSelection != m_aPendingSelection.end() ) + { + Sequence< ::rtl::OUString > aSelected( pendingSelection->second.size() ); + ::std::copy( pendingSelection->second.begin(), pendingSelection->second.end(), aSelected.getArray() ); + getContainer()->selectElements( aSelected ); + + m_aPendingSelection.erase( pendingSelection ); + } + InvalidateAll(); - EventObject aEvent(*this); - m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvent ); } m_eCurrentType = _eType; @@ -2182,9 +2286,9 @@ // ----------------------------------------------------------------------------- void OApplicationController::onEntryDeSelect(SvTreeListBox& /*_rTree*/) { + SelectionGuard aSelGuard( *m_pSelectionNotifier ); + InvalidateAll(); - EventObject aEvent(*this); - m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvent ); } // ----------------------------------------------------------------------------- void OApplicationController::onEntrySelect(SvLBoxEntry* _pEntry) @@ -2194,15 +2298,14 @@ OApplicationView* pView = getContainer(); if ( pView ) { + SelectionGuard aSelGuard( *m_pSelectionNotifier ); + const ElementType eType = pView->getElementType(); if ( _pEntry && pView->isALeafSelected() ) { const ::rtl::OUString sName = pView->getQualifiedName( _pEntry ); selectEntry(eType,sName); } - - EventObject aEvent(*this); - m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvent ); } } // ----------------------------------------------------------------------------- @@ -2778,6 +2881,19 @@ } return sName; } + +// ----------------------------------------------------------------------------- +void SAL_CALL OApplicationController::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& _Listener ) throw (RuntimeException) +{ + m_pSelectionNotifier->addListener( _Listener ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OApplicationController::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& _Listener ) throw (RuntimeException) +{ + m_pSelectionNotifier->removeListener( _Listener ); +} + // ----------------------------------------------------------------------------- ::sal_Bool SAL_CALL OApplicationController::select( const Any& _aSelection ) throw (IllegalArgumentException, RuntimeException) { @@ -2789,6 +2905,9 @@ getContainer()->selectElements(aSelection); return sal_True; } + + // -------------------------------------------------------------- + // BEGIN compatibility Sequence< NamedValue > aCurrentSelection; if ( (_aSelection >>= aCurrentSelection) && aCurrentSelection.getLength() ) { @@ -2801,19 +2920,107 @@ { sal_Int32 nType = 0; pIter->Value >>= nType; - if ( nType < 0 || nType > 4) + if ( nType < DatabaseObject::TABLE || nType > DatabaseObject::REPORT ) throw IllegalArgumentException(); - eType = static_cast<ElementType>(nType); + eType = static_cast< ElementType >( nType ); } else if ( pIter->Name.equalsAscii("Selection") ) pIter->Value >>= aSelection; } + m_aSelectContainerEvent.CancelCall(); // just in case the async select request was running getContainer()->selectContainer(eType); getContainer()->selectElements(aSelection); return sal_True; } + // END compatibility + // -------------------------------------------------------------- + + Sequence< NamedDatabaseObject > aSelectedObjects; + if ( !( _aSelection >>= aSelectedObjects ) ) + { + aSelectedObjects.realloc( 1 ); + if ( !( _aSelection >>= aSelectedObjects[0] ) ) throw IllegalArgumentException(); + } + + SelectionByElementType aSelectedElements; + ElementType eSelectedCategory = E_NONE; + for ( const NamedDatabaseObject* pObject = aSelectedObjects.getConstArray(); + pObject != aSelectedObjects.getConstArray() + aSelectedObjects.getLength(); + ++pObject + ) + { + switch ( pObject->Type ) + { + case DatabaseObject::TABLE: + case DatabaseObjectContainer::SCHEMA: + case DatabaseObjectContainer::CATALOG: + aSelectedElements[ E_TABLE ].push_back( pObject->Name ); + break; + case DatabaseObject::QUERY: + aSelectedElements[ E_QUERY ].push_back( pObject->Name ); + break; + case DatabaseObject::FORM: + case DatabaseObjectContainer::FORMS_FOLDER: + aSelectedElements[ E_FORM ].push_back( pObject->Name ); + break; + case DatabaseObject::REPORT: + case DatabaseObjectContainer::REPORTS_FOLDER: + aSelectedElements[ E_REPORT ].push_back( pObject->Name ); + break; + case DatabaseObjectContainer::TABLES: + case DatabaseObjectContainer::QUERIES: + case DatabaseObjectContainer::FORMS: + case DatabaseObjectContainer::REPORTS: + if ( eSelectedCategory != E_NONE ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "You cannot select different categories." ) ), + // TODO: resource + *this, sal_Int16( pObject - aSelectedObjects.getConstArray() ) ); + eSelectedCategory = + ( pObject->Type == DatabaseObjectContainer::TABLES ) ? E_TABLE + : ( pObject->Type == DatabaseObjectContainer::QUERIES ) ? E_QUERY + : ( pObject->Type == DatabaseObjectContainer::FORMS ) ? E_FORM + : ( pObject->Type == DatabaseObjectContainer::REPORTS ) ? E_REPORT + : E_NONE; + break; + + default: + case DatabaseObjectContainer::DATA_SOURCE: + { + ::rtl::OUStringBuffer aMessage; + aMessage.appendAscii( "Unsupported object type found (" ); + aMessage.append ( sal_Int32( pObject->Type ) ); + aMessage.appendAscii( ")." ); + // TODO: resource + throw IllegalArgumentException( + aMessage.makeStringAndClear(), *this, sal_Int16( pObject - aSelectedObjects.getConstArray() ) ); + } + } + } + + for ( SelectionByElementType::const_iterator sel = aSelectedElements.begin(); + sel != aSelectedElements.end(); + ++sel + ) + { + if ( sel->first == m_eCurrentType ) + { + Sequence< ::rtl::OUString > aSelected( sel->second.size() ); + ::std::copy( sel->second.begin(), sel->second.end(), aSelected.getArray() ); + getContainer()->selectElements( aSelected ); + } + else + { + m_aPendingSelection[ sel->first ] = sel->second; + } + } + + m_aSelectContainerEvent.CancelCall(); // just in case the async select request was running + getContainer()->selectContainer( eSelectedCategory ); + + return sal_True; } // ----------------------------------------------------------------------------- Any SAL_CALL OApplicationController::getSelection( ) throw (RuntimeException) @@ -2874,6 +3081,7 @@ } // while ( aFind != m_aSpecialSubFrames.end() ) return bFound; } + //........................................................................ } // namespace dbaui //........................................................................ File [changed]: AppController.hxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ui/app/AppController.hxx?r1=1.28.10.4&r2=1.28.10.5 Delta lines: +15 -4 -------------------- --- AppController.hxx 2008-06-10 06:40:53+0000 1.28.10.4 +++ AppController.hxx 2008-06-11 20:25:22+0000 1.28.10.5 @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: AppController.hxx,v $ - * $Revision: 1.28.10.4 $ + * $Revision: 1.28.10.5 $ * * This file is part of OpenOffice.org. * @@ -53,7 +53,7 @@ #include <comphelper/stl_types.hxx> #include <comphelper/namedvaluecollection.hxx> #include <comphelper/uno3.hxx> -#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implbase5.hxx> #include <sot/storage.hxx> #include <svtools/transfer.hxx> #include <svx/dataaccessdescriptor.hxx> @@ -83,12 +83,15 @@ class OApplicationView; class OLinkedDocumentsAccess; typedef OGenericUnoController OApplicationController_CBASE; - typedef ::cppu::ImplHelper4 < ::com::sun::star::container::XContainerListener + typedef ::cppu::ImplHelper5 < ::com::sun::star::container::XContainerListener , ::com::sun::star::beans::XPropertyChangeListener , ::com::sun::star::sdb::application::XDatabaseDocumentUI , ::com::sun::star::ui::XContextMenuInterception + , ::com::sun::star::view::XSelectionSupplier > OApplicationController_Base; + class SelectionNotifier; + class OApplicationController :public OApplicationController_CBASE ,public OApplicationController_Base @@ -136,11 +139,17 @@ mutable ::rtl::OUString m_sDatabaseName; sal_Int32 m_nAsyncDrop; OAsyncronousLink m_aControllerConnectedEvent; + OAsyncronousLink m_aSelectContainerEvent; PreviewMode m_ePreviewMode; // the mode of the preview ElementType m_eCurrentType; sal_Bool m_bNeedToReconnect; // true when the settings of the data source were modified and the connection is no longer up to date sal_Bool m_bSuspended; // is true when the controller was already suspended + ::std::auto_ptr< SelectionNotifier > + m_pSelectionNotifier; + typedef ::std::map< ElementType, ::std::vector< ::rtl::OUString > > SelectionByElementType; + SelectionByElementType m_aPendingSelection; + private: OApplicationView* getContainer() const; @@ -497,6 +506,8 @@ // XSelectionSupplier virtual ::sal_Bool SAL_CALL select( const ::com::sun::star::uno::Any& xSelection ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Any SAL_CALL getSelection( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addSelectionChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XSelectionChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSelectionChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XSelectionChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); /** retrieves the current connection, creates it if necessary */ --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
