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]

Reply via email to