LCOV - code coverage report
Current view: top level - svx/source/form - formcontroller.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 473 2008 23.6 %
Date: 2015-06-13 12:38:46 Functions: 52 202 25.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "fmcontrolbordermanager.hxx"
      22             : #include "fmcontrollayout.hxx"
      23             : #include "formcontroller.hxx"
      24             : #include "formfeaturedispatcher.hxx"
      25             : #include "fmdocumentclassification.hxx"
      26             : #include "formcontrolling.hxx"
      27             : #include "fmprop.hrc"
      28             : #include "svx/dialmgr.hxx"
      29             : #include "svx/fmresids.hrc"
      30             : #include "fmservs.hxx"
      31             : #include "svx/fmtools.hxx"
      32             : #include "fmurl.hxx"
      33             : 
      34             : #include <com/sun/star/awt/FocusChangeReason.hpp>
      35             : #include <com/sun/star/awt/XCheckBox.hpp>
      36             : #include <com/sun/star/awt/XComboBox.hpp>
      37             : #include <com/sun/star/awt/XListBox.hpp>
      38             : #include <com/sun/star/awt/XVclWindowPeer.hpp>
      39             : #include <com/sun/star/awt/TabController.hpp>
      40             : #include <com/sun/star/beans/NamedValue.hpp>
      41             : #include <com/sun/star/beans/PropertyAttribute.hpp>
      42             : #include <com/sun/star/container/XIdentifierReplace.hpp>
      43             : #include <com/sun/star/form/TabulatorCycle.hpp>
      44             : #include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
      45             : #include <com/sun/star/form/XBoundComponent.hpp>
      46             : #include <com/sun/star/form/XBoundControl.hpp>
      47             : #include <com/sun/star/form/XGridControl.hpp>
      48             : #include <com/sun/star/form/XLoadable.hpp>
      49             : #include <com/sun/star/form/XReset.hpp>
      50             : #include <com/sun/star/form/control/FilterControl.hpp>
      51             : #include <com/sun/star/frame/XController.hpp>
      52             : #include <com/sun/star/sdb/ParametersRequest.hpp>
      53             : #include <com/sun/star/sdb/RowChangeAction.hpp>
      54             : #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
      55             : #include <com/sun/star/sdbc/ColumnValue.hpp>
      56             : #include <com/sun/star/sdbc/DataType.hpp>
      57             : #include <com/sun/star/task/InteractionHandler.hpp>
      58             : #include <com/sun/star/util/XURLTransformer.hpp>
      59             : #include <com/sun/star/form/runtime/FormOperations.hpp>
      60             : #include <com/sun/star/form/runtime/FormFeature.hpp>
      61             : #include <com/sun/star/container/XContainer.hpp>
      62             : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
      63             : #include <com/sun/star/util/NumberFormatter.hpp>
      64             : #include <com/sun/star/sdb/SQLContext.hpp>
      65             : #include <com/sun/star/sdb/XColumn.hpp>
      66             : 
      67             : #include <comphelper/enumhelper.hxx>
      68             : #include <comphelper/interaction.hxx>
      69             : #include <comphelper/namedvaluecollection.hxx>
      70             : #include <comphelper/processfactory.hxx>
      71             : #include <comphelper/propagg.hxx>
      72             : #include <comphelper/property.hxx>
      73             : #include <comphelper/sequence.hxx>
      74             : #include <comphelper/flagguard.hxx>
      75             : #include <cppuhelper/queryinterface.hxx>
      76             : #include <cppuhelper/supportsservice.hxx>
      77             : #include <cppuhelper/typeprovider.hxx>
      78             : #include <connectivity/IParseContext.hxx>
      79             : #include <connectivity/dbtools.hxx>
      80             : #include <connectivity/sqlparse.hxx>
      81             : #include <toolkit/controls/unocontrol.hxx>
      82             : #include <toolkit/helper/vclunohelper.hxx>
      83             : #include <tools/debug.hxx>
      84             : #include <tools/diagnose_ex.h>
      85             : #include <vcl/msgbox.hxx>
      86             : #include <vcl/svapp.hxx>
      87             : #include <vcl/settings.hxx>
      88             : #include <osl/mutex.hxx>
      89             : 
      90             : #include <algorithm>
      91             : 
      92             : #include <o3tl/compat_functional.hxx>
      93             : 
      94             : using namespace ::com::sun::star;
      95             : using namespace ::comphelper;
      96             : using namespace ::connectivity;
      97             : using namespace ::dbtools;
      98             : 
      99             : 
     100             : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
     101          95 :     FormController_NewInstance_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & _rxORB )
     102             :     throw (css::uno::Exception)
     103             : {
     104          95 :     return *( new ::svxform::FormController( comphelper::getComponentContext(_rxORB) ) );
     105             : }
     106             : 
     107             : namespace svxform
     108             : {
     109             : 
     110             :     using ::com::sun::star::sdb::XColumn;
     111             :     using ::com::sun::star::awt::XControl;
     112             :     using ::com::sun::star::awt::XTabController;
     113             :     using ::com::sun::star::awt::TabController;
     114             :     using ::com::sun::star::awt::XToolkit;
     115             :     using ::com::sun::star::awt::XWindowPeer;
     116             :     using ::com::sun::star::form::XGrid;
     117             :     using ::com::sun::star::beans::XPropertySet;
     118             :     using ::com::sun::star::uno::UNO_SET_THROW;
     119             :     using ::com::sun::star::uno::UNO_QUERY_THROW;
     120             :     using ::com::sun::star::container::XIndexAccess;
     121             :     using ::com::sun::star::uno::Exception;
     122             :     using ::com::sun::star::uno::XInterface;
     123             :     using ::com::sun::star::uno::UNO_QUERY;
     124             :     using ::com::sun::star::uno::Sequence;
     125             :     using ::com::sun::star::uno::Reference;
     126             :     using ::com::sun::star::beans::XPropertySetInfo;
     127             :     using ::com::sun::star::beans::PropertyValue;
     128             :     using ::com::sun::star::uno::RuntimeException;
     129             :     using ::com::sun::star::lang::IndexOutOfBoundsException;
     130             :     using ::com::sun::star::sdb::XInteractionSupplyParameters;
     131             :     using ::com::sun::star::awt::XTextComponent;
     132             :     using ::com::sun::star::awt::XTextListener;
     133             :     using ::com::sun::star::uno::Any;
     134             :     using ::com::sun::star::frame::XDispatch;
     135             :     using ::com::sun::star::lang::XMultiServiceFactory;
     136             :     using ::com::sun::star::uno::XAggregation;
     137             :     using ::com::sun::star::uno::Type;
     138             :     using ::com::sun::star::lang::IllegalArgumentException;
     139             :     using ::com::sun::star::sdbc::XConnection;
     140             :     using ::com::sun::star::sdbc::XRowSet;
     141             :     using ::com::sun::star::sdbc::XDatabaseMetaData;
     142             :     using ::com::sun::star::util::XNumberFormatsSupplier;
     143             :     using ::com::sun::star::util::NumberFormatter;
     144             :     using ::com::sun::star::util::XNumberFormatter;
     145             :     using ::com::sun::star::sdbcx::XColumnsSupplier;
     146             :     using ::com::sun::star::container::XNameAccess;
     147             :     using ::com::sun::star::lang::EventObject;
     148             :     using ::com::sun::star::beans::Property;
     149             :     using ::com::sun::star::container::XEnumeration;
     150             :     using ::com::sun::star::form::XFormComponent;
     151             :     using ::com::sun::star::form::runtime::XFormOperations;
     152             :     using ::com::sun::star::form::runtime::FilterEvent;
     153             :     using ::com::sun::star::form::runtime::XFilterControllerListener;
     154             :     using ::com::sun::star::awt::XControlContainer;
     155             :     using ::com::sun::star::container::XIdentifierReplace;
     156             :     using ::com::sun::star::lang::WrappedTargetException;
     157             :     using ::com::sun::star::form::XFormControllerListener;
     158             :     using ::com::sun::star::awt::XWindow;
     159             :     using ::com::sun::star::sdbc::XResultSet;
     160             :     using ::com::sun::star::awt::XControlModel;
     161             :     using ::com::sun::star::awt::XTabControllerModel;
     162             :     using ::com::sun::star::beans::PropertyChangeEvent;
     163             :     using ::com::sun::star::form::validation::XValidatableFormComponent;
     164             :     using ::com::sun::star::form::XLoadable;
     165             :     using ::com::sun::star::script::XEventAttacherManager;
     166             :     using ::com::sun::star::form::XBoundControl;
     167             :     using ::com::sun::star::beans::XPropertyChangeListener;
     168             :     using ::com::sun::star::awt::TextEvent;
     169             :     using ::com::sun::star::form::XBoundComponent;
     170             :     using ::com::sun::star::awt::XCheckBox;
     171             :     using ::com::sun::star::awt::XComboBox;
     172             :     using ::com::sun::star::awt::XListBox;
     173             :     using ::com::sun::star::awt::ItemEvent;
     174             :     using ::com::sun::star::util::XModifyListener;
     175             :     using ::com::sun::star::form::XReset;
     176             :     using ::com::sun::star::frame::XDispatchProviderInterception;
     177             :     using ::com::sun::star::form::XGridControl;
     178             :     using ::com::sun::star::awt::XVclWindowPeer;
     179             :     using ::com::sun::star::form::validation::XValidator;
     180             :     using ::com::sun::star::awt::FocusEvent;
     181             :     using ::com::sun::star::sdb::SQLContext;
     182             :     using ::com::sun::star::container::XChild;
     183             :     using ::com::sun::star::form::TabulatorCycle_RECORDS;
     184             :     using ::com::sun::star::container::ContainerEvent;
     185             :     using ::com::sun::star::lang::DisposedException;
     186             :     using ::com::sun::star::lang::Locale;
     187             :     using ::com::sun::star::beans::NamedValue;
     188             :     using ::com::sun::star::lang::NoSupportException;
     189             :     using ::com::sun::star::sdb::RowChangeEvent;
     190             :     using ::com::sun::star::frame::XStatusListener;
     191             :     using ::com::sun::star::frame::XDispatchProviderInterceptor;
     192             :     using ::com::sun::star::sdb::SQLErrorEvent;
     193             :     using ::com::sun::star::form::DatabaseParameterEvent;
     194             :     using ::com::sun::star::sdb::ParametersRequest;
     195             :     using ::com::sun::star::task::XInteractionRequest;
     196             :     using ::com::sun::star::util::URL;
     197             :     using ::com::sun::star::frame::FeatureStateEvent;
     198             :     using ::com::sun::star::form::runtime::XFormControllerContext;
     199             :     using ::com::sun::star::task::InteractionHandler;
     200             :     using ::com::sun::star::task::XInteractionHandler;
     201             :     using ::com::sun::star::form::runtime::FormOperations;
     202             :     using ::com::sun::star::container::XContainer;
     203             :     using ::com::sun::star::sdbc::SQLWarning;
     204             : 
     205             :     namespace ColumnValue = ::com::sun::star::sdbc::ColumnValue;
     206             :     namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
     207             :     namespace FocusChangeReason = ::com::sun::star::awt::FocusChangeReason;
     208             :     namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
     209             :     namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
     210             :     namespace DataType = ::com::sun::star::sdbc::DataType;
     211             : 
     212           0 : struct ColumnInfo
     213             : {
     214             :     // information about the column itself
     215             :     Reference< XColumn >    xColumn;
     216             :     sal_Int32               nNullable;
     217             :     bool                bAutoIncrement;
     218             :     bool                bReadOnly;
     219             :     OUString         sName;
     220             : 
     221             :     // information about the control(s) bound to this column
     222             : 
     223             :     /// the first control which is bound to the given column, and which requires input
     224             :     Reference< XControl >   xFirstControlWithInputRequired;
     225             :     /** the first grid control which contains a column which is bound to the given database column, and requires
     226             :         input
     227             :     */
     228             :     Reference< XGrid >      xFirstGridWithInputRequiredColumn;
     229             :     /** if xFirstControlWithInputRequired is a grid control, then nRequiredGridColumn specifies the position
     230             :         of the grid column which is actually bound
     231             :     */
     232             :     sal_Int32               nRequiredGridColumn;
     233             : 
     234           0 :     ColumnInfo()
     235             :         :xColumn()
     236             :         ,nNullable( ColumnValue::NULLABLE_UNKNOWN )
     237             :         ,bAutoIncrement( false )
     238             :         ,bReadOnly( false )
     239             :         ,sName()
     240             :         ,xFirstControlWithInputRequired()
     241             :         ,xFirstGridWithInputRequiredColumn()
     242           0 :         ,nRequiredGridColumn( -1 )
     243             :     {
     244           0 :     }
     245             : };
     246             : 
     247           0 : class ColumnInfoCache
     248             : {
     249             : public:
     250             :     explicit ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier );
     251             : 
     252           0 :     size_t        getColumnCount() const { return m_aColumns.size(); }
     253             :     const ColumnInfo&   getColumnInfo( size_t _pos );
     254             : 
     255           0 :     bool    controlsInitialized() const { return m_bControlsInitialized; }
     256             :     void    initializeControls( const Sequence< Reference< XControl > >& _rControls );
     257             :     void    deinitializeControls();
     258             : 
     259             : private:
     260             :     typedef ::std::vector< ColumnInfo > ColumnInfos;
     261             :     ColumnInfos                         m_aColumns;
     262             :     bool                                m_bControlsInitialized;
     263             : };
     264             : 
     265             : 
     266           0 : ColumnInfoCache::ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier )
     267             :     :m_aColumns()
     268           0 :     ,m_bControlsInitialized( false )
     269             : {
     270             :     try
     271             :     {
     272           0 :         m_aColumns.clear();
     273             : 
     274           0 :         Reference< XIndexAccess > xColumns( _rxColSupplier->getColumns(), UNO_QUERY_THROW );
     275           0 :         sal_Int32 nColumnCount = xColumns->getCount();
     276           0 :         m_aColumns.reserve( nColumnCount );
     277             : 
     278           0 :         Reference< XPropertySet >   xColumnProps;
     279           0 :         for ( sal_Int32 i = 0; i < nColumnCount; ++i )
     280             :         {
     281           0 :             ColumnInfo aColInfo;
     282           0 :             aColInfo.xColumn.set( xColumns->getByIndex(i), UNO_QUERY_THROW );
     283             : 
     284           0 :             xColumnProps.set( aColInfo.xColumn, UNO_QUERY_THROW );
     285           0 :             OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISNULLABLE ) >>= aColInfo.nNullable );
     286           0 :             OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_AUTOINCREMENT ) >>= aColInfo.bAutoIncrement );
     287           0 :             OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_NAME ) >>= aColInfo.sName );
     288           0 :             OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISREADONLY ) >>= aColInfo.bReadOnly );
     289             : 
     290           0 :             m_aColumns.push_back( aColInfo );
     291           0 :         }
     292             :     }
     293           0 :     catch( const Exception& )
     294             :     {
     295             :         DBG_UNHANDLED_EXCEPTION();
     296             :     }
     297           0 : }
     298             : 
     299             : 
     300             : namespace
     301             : {
     302           0 :     bool lcl_isBoundTo( const Reference< XPropertySet >& _rxControlModel, const Reference< XInterface >& _rxNormDBField )
     303             :     {
     304           0 :         Reference< XInterface > xNormBoundField( _rxControlModel->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY );
     305           0 :         return ( xNormBoundField == _rxNormDBField );
     306             :     }
     307             : 
     308           0 :     bool lcl_isInputRequired( const Reference< XPropertySet >& _rxControlModel )
     309             :     {
     310           0 :         bool bInputRequired = true;
     311           0 :         OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_INPUT_REQUIRED ) >>= bInputRequired );
     312           0 :         return bInputRequired;
     313             :     }
     314             : 
     315           0 :     void lcl_resetColumnControlInfo( ColumnInfo& _rColInfo )
     316             :     {
     317           0 :         _rColInfo.xFirstControlWithInputRequired.clear();
     318           0 :         _rColInfo.xFirstGridWithInputRequiredColumn.clear();
     319           0 :         _rColInfo.nRequiredGridColumn = -1;
     320           0 :     }
     321             : }
     322             : 
     323             : 
     324           0 : void ColumnInfoCache::deinitializeControls()
     325             : {
     326           0 :     for (   ColumnInfos::iterator col = m_aColumns.begin();
     327           0 :             col != m_aColumns.end();
     328             :             ++col
     329             :         )
     330             :     {
     331           0 :         lcl_resetColumnControlInfo( *col );
     332             :     }
     333           0 : }
     334             : 
     335             : 
     336           0 : void ColumnInfoCache::initializeControls( const Sequence< Reference< XControl > >& _rControls )
     337             : {
     338             :     try
     339             :     {
     340             :         // for every of our known columns, find the controls which are bound to this column
     341           0 :         for (   ColumnInfos::iterator col = m_aColumns.begin();
     342           0 :                 col != m_aColumns.end();
     343             :                 ++col
     344             :             )
     345             :         {
     346             :             OSL_ENSURE( !col->xFirstControlWithInputRequired.is() && !col->xFirstGridWithInputRequiredColumn.is()
     347             :                 && ( col->nRequiredGridColumn == -1 ), "ColumnInfoCache::initializeControls: called me twice?" );
     348             : 
     349           0 :             lcl_resetColumnControlInfo( *col );
     350             : 
     351           0 :             Reference< XInterface > xNormColumn( col->xColumn, UNO_QUERY_THROW );
     352             : 
     353           0 :             const Reference< XControl >* pControl( _rControls.getConstArray() );
     354           0 :             const Reference< XControl >* pControlEnd( pControl + _rControls.getLength() );
     355           0 :             for ( ; pControl != pControlEnd; ++pControl )
     356             :             {
     357           0 :                 if ( !pControl->is() )
     358           0 :                     continue;
     359             : 
     360           0 :                 Reference< XPropertySet > xModel( (*pControl)->getModel(), UNO_QUERY_THROW );
     361           0 :                 Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
     362             : 
     363             :                 // special handling for grid controls
     364           0 :                 Reference< XGrid > xGrid( *pControl, UNO_QUERY );
     365           0 :                 if ( xGrid.is() )
     366             :                 {
     367           0 :                     Reference< XIndexAccess > xGridColAccess( xModel, UNO_QUERY_THROW );
     368           0 :                     sal_Int32 gridColCount = xGridColAccess->getCount();
     369           0 :                     sal_Int32 gridCol = 0;
     370           0 :                     for ( gridCol = 0; gridCol < gridColCount; ++gridCol )
     371             :                     {
     372           0 :                         Reference< XPropertySet > xGridColumnModel( xGridColAccess->getByIndex( gridCol ), UNO_QUERY_THROW );
     373             : 
     374           0 :                         if  (   !lcl_isBoundTo( xGridColumnModel, xNormColumn )
     375           0 :                             ||  !lcl_isInputRequired( xGridColumnModel )
     376             :                             )
     377           0 :                             continue;   // with next grid column
     378             : 
     379           0 :                         break;
     380           0 :                     }
     381             : 
     382           0 :                     if ( gridCol < gridColCount )
     383             :                     {
     384             :                         // found a grid column which is bound to the given
     385           0 :                         col->xFirstGridWithInputRequiredColumn = xGrid;
     386           0 :                         col->nRequiredGridColumn = gridCol;
     387           0 :                         break;
     388             :                     }
     389             : 
     390           0 :                     continue;   // with next control
     391             :                 }
     392             : 
     393           0 :                 if  (   !xModelPSI->hasPropertyByName( FM_PROP_BOUNDFIELD )
     394           0 :                     ||  !lcl_isBoundTo( xModel, xNormColumn )
     395           0 :                     ||  !lcl_isInputRequired( xModel )
     396             :                     )
     397           0 :                     continue;   // with next control
     398             : 
     399           0 :                 break;
     400           0 :             }
     401             : 
     402           0 :             if ( pControl == pControlEnd )
     403             :                 // did not find a control which is bound to this particular column, and for which the input is required
     404           0 :                 continue;   // with next DB column
     405             : 
     406           0 :             col->xFirstControlWithInputRequired = *pControl;
     407           0 :         }
     408             :     }
     409           0 :     catch( const Exception& )
     410             :     {
     411             :         DBG_UNHANDLED_EXCEPTION();
     412             :     }
     413             : 
     414           0 :     m_bControlsInitialized = true;
     415           0 : }
     416             : 
     417             : 
     418           0 : const ColumnInfo& ColumnInfoCache::getColumnInfo( size_t _pos )
     419             : {
     420           0 :     if ( _pos >= m_aColumns.size() )
     421           0 :         throw IndexOutOfBoundsException();
     422             : 
     423           0 :     return m_aColumns[ _pos ];
     424             : }
     425             : 
     426           0 : class OParameterContinuation : public OInteraction< XInteractionSupplyParameters >
     427             : {
     428             :     Sequence< PropertyValue >       m_aValues;
     429             : 
     430             : public:
     431           0 :     OParameterContinuation() { }
     432             : 
     433           0 :     Sequence< PropertyValue >   getValues() const { return m_aValues; }
     434             : 
     435             : // XInteractionSupplyParameters
     436             :     virtual void SAL_CALL setParameters( const Sequence< PropertyValue >& _rValues ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
     437             : };
     438             : 
     439             : 
     440           0 : void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) throw(RuntimeException, std::exception)
     441             : {
     442           0 :     m_aValues = _rValues;
     443           0 : }
     444             : 
     445             : 
     446             : // FmXAutoControl
     447             : 
     448           0 : struct FmFieldInfo
     449             : {
     450             :     OUString       aFieldName;
     451             :     Reference< XPropertySet >   xField;
     452             :     Reference< XTextComponent >  xText;
     453             : 
     454           0 :     FmFieldInfo(const Reference< XPropertySet >& _xField, const Reference< XTextComponent >& _xText)
     455             :         :xField(_xField)
     456           0 :         ,xText(_xText)
     457           0 :     {xField->getPropertyValue(FM_PROP_NAME) >>= aFieldName;}
     458             : };
     459             : 
     460           0 : class FmXAutoControl: public UnoControl
     461             : 
     462             : {
     463             : public:
     464           0 :     FmXAutoControl() :UnoControl()
     465             :     {
     466           0 :     }
     467             : 
     468           0 :     virtual OUString GetComponentServiceName() SAL_OVERRIDE {return OUString("Edit");}
     469             :     virtual void SAL_CALL createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer >  & rParentPeer ) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
     470             : 
     471             : protected:
     472             :     virtual void ImplSetPeerProperty( const OUString& rPropName, const Any& rVal ) SAL_OVERRIDE;
     473             : };
     474             : 
     475             : 
     476           0 : void FmXAutoControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer >  & rParentPeer ) throw( RuntimeException, std::exception )
     477             : {
     478           0 :     UnoControl::createPeer( rxToolkit, rParentPeer );
     479             : 
     480           0 :     Reference< XTextComponent >  xText(getPeer() , UNO_QUERY);
     481           0 :     if (xText.is())
     482             :     {
     483           0 :         xText->setText(SVX_RESSTR(RID_STR_AUTOFIELD));
     484           0 :         xText->setEditable(sal_False);
     485           0 :     }
     486           0 : }
     487             : 
     488             : 
     489           0 : void FmXAutoControl::ImplSetPeerProperty( const OUString& rPropName, const Any& rVal )
     490             : {
     491             :     // these properties are ignored
     492           0 :     if (rPropName == FM_PROP_TEXT)
     493           0 :         return;
     494             : 
     495           0 :     UnoControl::ImplSetPeerProperty( rPropName, rVal );
     496             : }
     497             : 
     498             : 
     499          16 : IMPL_LINK_NOARG_TYPED( FormController, OnActivateTabOrder, Idle*, void )
     500             : {
     501           8 :     activateTabOrder();
     502           8 : }
     503             : 
     504             : 
     505             : struct UpdateAllListeners : public ::std::unary_function< Reference< XDispatch >, bool >
     506             : {
     507           0 :     bool operator()( const Reference< XDispatch >& _rxDispatcher ) const
     508             :     {
     509           0 :         static_cast< svx::OSingleFeatureDispatcher* >( _rxDispatcher.get() )->updateAllListeners();
     510             :         // the return is a dummy only so we can use this struct in a o3tl::compose1 call
     511           0 :         return true;
     512             :     }
     513             : };
     514             : 
     515           0 : IMPL_LINK_NOARG_TYPED( FormController, OnInvalidateFeatures, Timer*, void )
     516             : {
     517           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     518           0 :     for ( ::std::set< sal_Int16 >::const_iterator aLoop = m_aInvalidFeatures.begin();
     519           0 :           aLoop != m_aInvalidFeatures.end();
     520             :           ++aLoop
     521             :         )
     522             :     {
     523           0 :         DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( *aLoop );
     524           0 :         if ( aDispatcherPos != m_aFeatureDispatchers.end() )
     525             :         {
     526             :             // TODO: for the real and actual listener notifications, we should release
     527             :             // our mutex
     528           0 :             UpdateAllListeners( )( aDispatcherPos->second );
     529             :         }
     530           0 :     }
     531           0 : }
     532             : 
     533          95 : FormController::FormController(const Reference< css::uno::XComponentContext > & _rxORB )
     534             :                   :FormController_BASE( m_aMutex )
     535             :                   ,OPropertySetHelper( FormController_BASE::rBHelper )
     536             :                   ,OSQLParserClient( _rxORB )
     537             :                   ,m_xComponentContext( _rxORB )
     538             :                   ,m_aActivateListeners(m_aMutex)
     539             :                   ,m_aModifyListeners(m_aMutex)
     540             :                   ,m_aErrorListeners(m_aMutex)
     541             :                   ,m_aDeleteListeners(m_aMutex)
     542             :                   ,m_aRowSetApproveListeners(m_aMutex)
     543             :                   ,m_aParameterListeners(m_aMutex)
     544             :                   ,m_aFilterListeners(m_aMutex)
     545          95 :                   ,m_pControlBorderManager( new ::svxform::ControlBorderManager )
     546             :                   ,m_xFormOperations()
     547             :                   ,m_aMode( OUString( "DataMode"  ) )
     548             :                   ,m_aLoadEvent( LINK( this, FormController, OnLoad ) )
     549             :                   ,m_aToggleEvent( LINK( this, FormController, OnToggleAutoFields ) )
     550             :                   ,m_aActivationEvent( LINK( this, FormController, OnActivated ) )
     551             :                   ,m_aDeactivationEvent( LINK( this, FormController, OnDeactivated ) )
     552             :                   ,m_nCurrentFilterPosition(-1)
     553             :                   ,m_bCurrentRecordModified(false)
     554             :                   ,m_bCurrentRecordNew(false)
     555             :                   ,m_bLocked(false)
     556             :                   ,m_bDBConnection(false)
     557             :                   ,m_bCycle(false)
     558             :                   ,m_bCanInsert(false)
     559             :                   ,m_bCanUpdate(false)
     560             :                   ,m_bCommitLock(false)
     561             :                   ,m_bModified(false)
     562             :                   ,m_bControlsSorted(false)
     563             :                   ,m_bFiltering(false)
     564             :                   ,m_bAttachEvents(true)
     565             :                   ,m_bDetachEvents(true)
     566             :                   ,m_bAttemptedHandlerCreation( false )
     567         190 :                   ,m_bSuspendFilterTextListening( false )
     568             : {
     569             : 
     570          95 :     osl_atomic_increment(&m_refCount);
     571             :     {
     572          95 :         m_xTabController = TabController::create( m_xComponentContext );
     573          95 :         m_xAggregate = Reference< XAggregation >( m_xTabController, UNO_QUERY_THROW );
     574          95 :         m_xAggregate->setDelegator( *this );
     575             :     }
     576          95 :     osl_atomic_decrement(&m_refCount);
     577             : 
     578          95 :     m_aTabActivationIdle.SetPriority( SchedulerPriority::LOWEST );
     579          95 :     m_aTabActivationIdle.SetIdleHdl( LINK( this, FormController, OnActivateTabOrder ) );
     580             : 
     581          95 :     m_aFeatureInvalidationTimer.SetTimeout( 200 );
     582          95 :     m_aFeatureInvalidationTimer.SetTimeoutHdl( LINK( this, FormController, OnInvalidateFeatures ) );
     583          95 : }
     584             : 
     585             : 
     586         285 : FormController::~FormController()
     587             : {
     588             :     {
     589          95 :         ::osl::MutexGuard aGuard( m_aMutex );
     590             : 
     591          95 :         m_aLoadEvent.CancelPendingCall();
     592          95 :         m_aToggleEvent.CancelPendingCall();
     593          95 :         m_aActivationEvent.CancelPendingCall();
     594          95 :         m_aDeactivationEvent.CancelPendingCall();
     595             : 
     596          95 :         if ( m_aTabActivationIdle.IsActive() )
     597           0 :             m_aTabActivationIdle.Stop();
     598             :     }
     599             : 
     600          95 :     if ( m_aFeatureInvalidationTimer.IsActive() )
     601           0 :         m_aFeatureInvalidationTimer.Stop();
     602             : 
     603          95 :     disposeAllFeaturesAndDispatchers();
     604             : 
     605          95 :     if ( m_xFormOperations.is() )
     606           0 :         m_xFormOperations->dispose();
     607          95 :     m_xFormOperations.clear();
     608             : 
     609             :     // Freigeben der Aggregation
     610          95 :     if ( m_xAggregate.is() )
     611             :     {
     612          95 :         m_xAggregate->setDelegator( NULL );
     613          95 :         m_xAggregate.clear();
     614             :     }
     615             : 
     616          95 :     DELETEZ( m_pControlBorderManager );
     617             : 
     618         190 : }
     619             : 
     620             : 
     621        6034 : void SAL_CALL FormController::acquire() throw ()
     622             : {
     623        6034 :     FormController_BASE::acquire();
     624        6034 : }
     625             : 
     626             : 
     627        6034 : void SAL_CALL FormController::release() throw ()
     628             : {
     629        6034 :     FormController_BASE::release();
     630        6034 : }
     631             : 
     632             : 
     633         928 : Any SAL_CALL FormController::queryInterface( const Type& _rType ) throw(RuntimeException, std::exception)
     634             : {
     635         928 :     Any aRet = FormController_BASE::queryInterface( _rType );
     636         928 :     if ( !aRet.hasValue() )
     637           0 :         aRet = OPropertySetHelper::queryInterface( _rType );
     638         928 :     if ( !aRet.hasValue() )
     639           0 :         aRet = m_xAggregate->queryAggregation( _rType );
     640         928 :     return aRet;
     641             : }
     642             : 
     643             : 
     644           0 : Sequence< sal_Int8 > SAL_CALL FormController::getImplementationId() throw( RuntimeException, std::exception )
     645             : {
     646           0 :     return css::uno::Sequence<sal_Int8>();
     647             : }
     648             : 
     649           0 : Sequence< Type > SAL_CALL FormController::getTypes(  ) throw(RuntimeException, std::exception)
     650             : {
     651             :     return comphelper::concatSequences(
     652             :         FormController_BASE::getTypes(),
     653             :         ::cppu::OPropertySetHelper::getTypes()
     654           0 :     );
     655             : }
     656             : 
     657             : // XServiceInfo
     658           0 : sal_Bool SAL_CALL FormController::supportsService(const OUString& ServiceName) throw( RuntimeException, std::exception )
     659             : {
     660           0 :     return cppu::supportsService(this, ServiceName);
     661             : }
     662             : 
     663           0 : OUString SAL_CALL FormController::getImplementationName() throw( RuntimeException, std::exception )
     664             : {
     665           0 :     return OUString("org.openoffice.comp.svx.FormController");
     666             : }
     667             : 
     668           0 : Sequence< OUString> SAL_CALL FormController::getSupportedServiceNames() throw( RuntimeException, std::exception )
     669             : {
     670             :     // service names which are supported only, but cannot be used to created an
     671             :     // instance at a service factory
     672           0 :     Sequence< OUString > aNonCreatableServiceNames( 1 );
     673           0 :     aNonCreatableServiceNames[ 0 ] = "com.sun.star.form.FormControllerDispatcher";
     674             : 
     675             :     // services which can be used to created an instance at a service factory
     676           0 :     Sequence< OUString > aCreatableServiceNames( getSupportedServiceNames_Static() );
     677           0 :     return ::comphelper::concatSequences( aCreatableServiceNames, aNonCreatableServiceNames );
     678             : }
     679             : 
     680             : 
     681           0 : sal_Bool SAL_CALL FormController::approveReset(const EventObject& /*rEvent*/) throw( RuntimeException, std::exception )
     682             : {
     683           0 :     return sal_True;
     684             : }
     685             : 
     686             : 
     687           0 : void SAL_CALL FormController::resetted(const EventObject& rEvent) throw( RuntimeException, std::exception )
     688             : {
     689           0 :     ::osl::MutexGuard aGuard(m_aMutex);
     690           0 :     if (getCurrentControl().is() &&  (getCurrentControl()->getModel() == rEvent.Source))
     691           0 :         m_bModified = false;
     692           0 : }
     693             : 
     694             : 
     695           0 : Sequence< OUString> FormController::getSupportedServiceNames_Static()
     696             : {
     697           0 :     static Sequence< OUString> aServices;
     698           0 :     if (!aServices.getLength())
     699             :     {
     700           0 :         aServices.realloc(2);
     701           0 :         aServices.getArray()[0] = "com.sun.star.form.runtime.FormController";
     702           0 :         aServices.getArray()[1] = "com.sun.star.awt.control.TabController";
     703             :     }
     704           0 :     return aServices;
     705             : }
     706             : 
     707             : 
     708             : namespace
     709             : {
     710             :     struct ResetComponentText : public ::std::unary_function< Reference< XTextComponent >, void >
     711             :     {
     712           0 :         void operator()( const Reference< XTextComponent >& _rxText )
     713             :         {
     714           0 :             _rxText->setText( OUString() );
     715           0 :         }
     716             :     };
     717             : 
     718         285 :     struct RemoveComponentTextListener : public ::std::unary_function< Reference< XTextComponent >, void >
     719             :     {
     720          95 :         explicit RemoveComponentTextListener( const Reference< XTextListener >& _rxListener )
     721          95 :             :m_xListener( _rxListener )
     722             :         {
     723          95 :         }
     724             : 
     725           0 :         void operator()( const Reference< XTextComponent >& _rxText )
     726             :         {
     727           0 :             _rxText->removeTextListener( m_xListener );
     728           0 :         }
     729             : 
     730             :     private:
     731             :         Reference< XTextListener >  m_xListener;
     732             :     };
     733             : }
     734             : 
     735             : 
     736           0 : void FormController::impl_setTextOnAllFilter_throw()
     737             : {
     738           0 :     m_bSuspendFilterTextListening = true;
     739           0 :     ::comphelper::FlagGuard aResetFlag( m_bSuspendFilterTextListening );
     740             : 
     741             :     // reset the text for all controls
     742           0 :     ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), ResetComponentText() );
     743             : 
     744           0 :     if ( m_aFilterRows.empty() )
     745             :         // nothing to do anymore
     746           0 :         return;
     747             : 
     748           0 :     if ( m_nCurrentFilterPosition < 0 )
     749           0 :         return;
     750             : 
     751             :     // set the text for all filters
     752             :     OSL_ENSURE( m_aFilterRows.size() > (size_t)m_nCurrentFilterPosition,
     753             :         "FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big" );
     754             : 
     755           0 :     if ( (size_t)m_nCurrentFilterPosition < m_aFilterRows.size() )
     756             :     {
     757           0 :         FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
     758           0 :         for (   FmFilterRow::const_iterator iter2 = rRow.begin();
     759           0 :                 iter2 != rRow.end();
     760             :                 ++iter2
     761             :             )
     762             :         {
     763           0 :             iter2->first->setText( iter2->second );
     764             :         }
     765           0 :     }
     766             : }
     767             : // OPropertySetHelper
     768             : 
     769           0 : sal_Bool FormController::convertFastPropertyValue( Any & /*rConvertedValue*/, Any & /*rOldValue*/,
     770             :                                             sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
     771             :                 throw( IllegalArgumentException )
     772             : {
     773           0 :     return sal_False;
     774             : }
     775             : 
     776             : 
     777           0 : void FormController::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
     778             :                          throw( Exception, std::exception )
     779             : {
     780           0 : }
     781             : 
     782             : 
     783           0 : void FormController::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
     784             : {
     785           0 :     switch (nHandle)
     786             :     {
     787             :         case FM_ATTR_FILTER:
     788             :         {
     789           0 :             OUStringBuffer aFilter;
     790           0 :             Reference<XConnection> xConnection(getConnection(Reference< XRowSet>(m_xModelAsIndex, UNO_QUERY)));
     791           0 :             if (xConnection.is())
     792             :             {
     793           0 :                 Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
     794           0 :                 Reference< XNumberFormatsSupplier> xFormatSupplier( getNumberFormats( xConnection, true ) );
     795           0 :                 Reference< XNumberFormatter> xFormatter = NumberFormatter::create(m_xComponentContext);
     796           0 :                 xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
     797             : 
     798           0 :                 Reference< XColumnsSupplier> xSupplyCols(m_xModelAsIndex, UNO_QUERY);
     799           0 :                 Reference< XNameAccess> xFields(xSupplyCols->getColumns(), UNO_QUERY);
     800             : 
     801             :                 // now add the filter rows
     802             :                 try
     803             :                 {
     804           0 :                     for ( FmFilterRows::const_iterator row = m_aFilterRows.begin(); row != m_aFilterRows.end(); ++row )
     805             :                     {
     806           0 :                         const FmFilterRow& rRow = *row;
     807             : 
     808           0 :                         if ( rRow.empty() )
     809           0 :                             continue;
     810             : 
     811           0 :                         OUStringBuffer aRowFilter;
     812           0 :                         for ( FmFilterRow::const_iterator condition = rRow.begin(); condition != rRow.end(); ++condition )
     813             :                         {
     814             :                             // get the field of the controls map
     815           0 :                             Reference< XControl > xControl( condition->first, UNO_QUERY_THROW );
     816           0 :                             Reference< XPropertySet > xModelProps( xControl->getModel(), UNO_QUERY_THROW );
     817           0 :                             Reference< XPropertySet > xField( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW );
     818             : 
     819           0 :                             OUString sFilterValue( condition->second );
     820             : 
     821           0 :                             OUString sErrorMsg, sCriteria;
     822             :                             const std::shared_ptr< OSQLParseNode > pParseNode =
     823           0 :                                 predicateTree( sErrorMsg, sFilterValue, xFormatter, xField );
     824             :                             OSL_ENSURE( pParseNode != nullptr, "FormController::getFastPropertyValue: could not parse the field value predicate!" );
     825           0 :                             if ( pParseNode != nullptr )
     826             :                             {
     827             :                                 // don't use a parse context here, we need it unlocalized
     828           0 :                                 pParseNode->parseNodeToStr( sCriteria, xConnection, NULL );
     829           0 :                                 if ( condition != rRow.begin() )
     830           0 :                                     aRowFilter.appendAscii( " AND " );
     831           0 :                                 aRowFilter.append( sCriteria );
     832             :                             }
     833           0 :                         }
     834           0 :                         if ( !aRowFilter.isEmpty() )
     835             :                         {
     836           0 :                             if ( !aFilter.isEmpty() )
     837           0 :                                 aFilter.appendAscii( " OR " );
     838             : 
     839           0 :                             aFilter.appendAscii( "( " );
     840           0 :                             aFilter.append( aRowFilter.makeStringAndClear() );
     841           0 :                             aFilter.appendAscii( " )" );
     842             :                         }
     843           0 :                     }
     844             :                 }
     845           0 :                 catch( const Exception& )
     846             :                 {
     847             :                     DBG_UNHANDLED_EXCEPTION();
     848           0 :                     aFilter.setLength(0);
     849           0 :                 }
     850             :             }
     851           0 :             rValue <<= aFilter.makeStringAndClear();
     852             :         }
     853           0 :         break;
     854             : 
     855             :         case FM_ATTR_FORM_OPERATIONS:
     856           0 :             rValue <<= m_xFormOperations;
     857           0 :             break;
     858             :     }
     859           0 : }
     860             : 
     861             : 
     862           0 : Reference< XPropertySetInfo >  FormController::getPropertySetInfo() throw( RuntimeException, std::exception )
     863             : {
     864           0 :     static Reference< XPropertySetInfo >  xInfo( createPropertySetInfo( getInfoHelper() ) );
     865           0 :     return xInfo;
     866             : }
     867             : 
     868             : 
     869           0 : void FormController::fillProperties(
     870             :         Sequence< Property >& /* [out] */ _rProps,
     871             :         Sequence< Property >& /* [out] */ /*_rAggregateProps*/
     872             :         ) const
     873             : {
     874           0 :     _rProps.realloc(2);
     875           0 :     sal_Int32 nPos = 0;
     876           0 :     Property* pDesc = _rProps.getArray();
     877             : 
     878           0 :     pDesc[nPos++] = Property(FM_PROP_FILTER, FM_ATTR_FILTER,
     879           0 :                              cppu::UnoType<OUString>::get(),
     880           0 :                              PropertyAttribute::READONLY);
     881           0 :     pDesc[nPos++] = Property(FM_PROP_FORM_OPERATIONS, FM_ATTR_FORM_OPERATIONS,
     882           0 :                              cppu::UnoType<XFormOperations>::get(),
     883           0 :                              PropertyAttribute::READONLY);
     884           0 : }
     885             : 
     886             : 
     887           0 : ::cppu::IPropertyArrayHelper& FormController::getInfoHelper()
     888             : {
     889           0 :     return *getArrayHelper();
     890             : }
     891             : 
     892             : // XFilterController
     893             : 
     894           0 : void SAL_CALL FormController::addFilterControllerListener( const Reference< XFilterControllerListener >& _Listener ) throw( RuntimeException, std::exception )
     895             : {
     896           0 :     m_aFilterListeners.addInterface( _Listener );
     897           0 : }
     898             : 
     899             : 
     900           0 : void SAL_CALL FormController::removeFilterControllerListener( const Reference< XFilterControllerListener >& _Listener ) throw( RuntimeException, std::exception )
     901             : {
     902           0 :     m_aFilterListeners.removeInterface( _Listener );
     903           0 : }
     904             : 
     905             : 
     906           0 : ::sal_Int32 SAL_CALL FormController::getFilterComponents() throw( ::com::sun::star::uno::RuntimeException, std::exception )
     907             : {
     908           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     909           0 :     impl_checkDisposed_throw();
     910             : 
     911           0 :     return m_aFilterComponents.size();
     912             : }
     913             : 
     914             : 
     915           0 : ::sal_Int32 SAL_CALL FormController::getDisjunctiveTerms() throw( ::com::sun::star::uno::RuntimeException, std::exception )
     916             : {
     917           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     918           0 :     impl_checkDisposed_throw();
     919             : 
     920           0 :     return m_aFilterRows.size();
     921             : }
     922             : 
     923             : 
     924           0 : void SAL_CALL FormController::setPredicateExpression( ::sal_Int32 _Component, ::sal_Int32 _Term, const OUString& _PredicateExpression ) throw( RuntimeException, IndexOutOfBoundsException, std::exception )
     925             : {
     926           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     927           0 :     impl_checkDisposed_throw();
     928             : 
     929           0 :     if ( ( _Component < 0 ) || ( _Component >= getFilterComponents() ) || ( _Term < 0 ) || ( _Term >= getDisjunctiveTerms() ) )
     930           0 :         throw IndexOutOfBoundsException( OUString(), *this );
     931             : 
     932           0 :     Reference< XTextComponent > xText( m_aFilterComponents[ _Component ] );
     933           0 :     xText->setText( _PredicateExpression );
     934             : 
     935           0 :     FmFilterRow& rFilterRow = m_aFilterRows[ _Term ];
     936           0 :     if ( !_PredicateExpression.isEmpty() )
     937           0 :         rFilterRow[ xText ] = _PredicateExpression;
     938             :     else
     939           0 :         rFilterRow.erase( xText );
     940           0 : }
     941             : 
     942             : 
     943           0 : Reference< XControl > FormController::getFilterComponent( ::sal_Int32 _Component ) throw( RuntimeException, IndexOutOfBoundsException, std::exception )
     944             : {
     945           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     946           0 :     impl_checkDisposed_throw();
     947             : 
     948           0 :     if ( ( _Component < 0 ) || ( _Component >= getFilterComponents() ) )
     949           0 :         throw IndexOutOfBoundsException( OUString(), *this );
     950             : 
     951           0 :     return Reference< XControl >( m_aFilterComponents[ _Component ], UNO_QUERY );
     952             : }
     953             : 
     954             : 
     955           0 : Sequence< Sequence< OUString > > FormController::getPredicateExpressions() throw( RuntimeException, std::exception )
     956             : {
     957           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     958           0 :     impl_checkDisposed_throw();
     959             : 
     960           0 :     Sequence< Sequence< OUString > > aExpressions( m_aFilterRows.size() );
     961           0 :     sal_Int32 termIndex = 0;
     962           0 :     for (   FmFilterRows::const_iterator row = m_aFilterRows.begin();
     963           0 :             row != m_aFilterRows.end();
     964             :             ++row, ++termIndex
     965             :         )
     966             :     {
     967           0 :         const FmFilterRow& rRow( *row );
     968             : 
     969           0 :         Sequence< OUString > aConjunction( m_aFilterComponents.size() );
     970           0 :         sal_Int32 componentIndex = 0;
     971           0 :         for (   FilterComponents::const_iterator comp = m_aFilterComponents.begin();
     972           0 :                 comp != m_aFilterComponents.end();
     973             :                 ++comp, ++componentIndex
     974             :             )
     975             :         {
     976           0 :             FmFilterRow::const_iterator predicate = rRow.find( *comp );
     977           0 :             if ( predicate != rRow.end() )
     978           0 :                 aConjunction[ componentIndex ] = predicate->second;
     979             :         }
     980             : 
     981           0 :         aExpressions[ termIndex ] = aConjunction;
     982           0 :     }
     983             : 
     984           0 :     return aExpressions;
     985             : }
     986             : 
     987             : 
     988           0 : void SAL_CALL FormController::removeDisjunctiveTerm( ::sal_Int32 _Term ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
     989             : {
     990             :     // SYNCHRONIZED -->
     991           0 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
     992           0 :     impl_checkDisposed_throw();
     993             : 
     994           0 :     if ( ( _Term < 0 ) || ( _Term >= getDisjunctiveTerms() ) )
     995           0 :         throw IndexOutOfBoundsException( OUString(), *this );
     996             : 
     997             :     // if the to-be-deleted row is our current row, we need to shift
     998           0 :     if ( _Term == m_nCurrentFilterPosition )
     999             :     {
    1000           0 :         if ( m_nCurrentFilterPosition < sal_Int32( m_aFilterRows.size() - 1 ) )
    1001           0 :             ++m_nCurrentFilterPosition;
    1002             :         else
    1003           0 :             --m_nCurrentFilterPosition;
    1004             :     }
    1005             : 
    1006           0 :     FmFilterRows::iterator pos = m_aFilterRows.begin() + _Term;
    1007           0 :     m_aFilterRows.erase( pos );
    1008             : 
    1009             :     // adjust m_nCurrentFilterPosition if the removed row preceded it
    1010           0 :     if ( _Term < m_nCurrentFilterPosition )
    1011           0 :         --m_nCurrentFilterPosition;
    1012             : 
    1013             :     SAL_WARN_IF( !( ( m_nCurrentFilterPosition < 0 ) != ( m_aFilterRows.empty() ) ),
    1014             :         "svx.form", "FormController::removeDisjunctiveTerm: inconsistency!" );
    1015             : 
    1016             :     // update the texts in the filter controls
    1017           0 :     impl_setTextOnAllFilter_throw();
    1018             : 
    1019           0 :     FilterEvent aEvent;
    1020           0 :     aEvent.Source = *this;
    1021           0 :     aEvent.DisjunctiveTerm = _Term;
    1022           0 :     aGuard.clear();
    1023             :     // <-- SYNCHRONIZED
    1024             : 
    1025           0 :     m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermRemoved, aEvent );
    1026           0 : }
    1027             : 
    1028             : 
    1029           0 : void SAL_CALL FormController::appendEmptyDisjunctiveTerm() throw (RuntimeException, std::exception)
    1030             : {
    1031             :     // SYNCHRONIZED -->
    1032           0 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    1033           0 :     impl_checkDisposed_throw();
    1034             : 
    1035           0 :     impl_appendEmptyFilterRow( aGuard );
    1036             :     // <-- SYNCHRONIZED
    1037           0 : }
    1038             : 
    1039             : 
    1040           0 : ::sal_Int32 SAL_CALL FormController::getActiveTerm() throw (RuntimeException, std::exception)
    1041             : {
    1042           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1043           0 :     impl_checkDisposed_throw();
    1044             : 
    1045           0 :     return m_nCurrentFilterPosition;
    1046             : }
    1047             : 
    1048             : 
    1049           0 : void SAL_CALL FormController::setActiveTerm( ::sal_Int32 _ActiveTerm ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
    1050             : {
    1051           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1052           0 :     impl_checkDisposed_throw();
    1053             : 
    1054           0 :     if ( ( _ActiveTerm < 0 ) || ( _ActiveTerm >= getDisjunctiveTerms() ) )
    1055           0 :         throw IndexOutOfBoundsException( OUString(), *this );
    1056             : 
    1057           0 :     if ( _ActiveTerm == getActiveTerm() )
    1058           0 :         return;
    1059             : 
    1060           0 :     m_nCurrentFilterPosition = _ActiveTerm;
    1061           0 :     impl_setTextOnAllFilter_throw();
    1062             : }
    1063             : 
    1064             : // XElementAccess
    1065             : 
    1066           0 : sal_Bool SAL_CALL FormController::hasElements() throw( RuntimeException, std::exception )
    1067             : {
    1068           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1069           0 :     return !m_aChildren.empty();
    1070             : }
    1071             : 
    1072             : 
    1073           0 : Type SAL_CALL  FormController::getElementType() throw( RuntimeException, std::exception )
    1074             : {
    1075           0 :     return cppu::UnoType<XFormController>::get();
    1076             : 
    1077             : }
    1078             : 
    1079             : // XEnumerationAccess
    1080             : 
    1081           0 : Reference< XEnumeration > SAL_CALL  FormController::createEnumeration() throw( RuntimeException, std::exception )
    1082             : {
    1083           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1084           0 :     return new ::comphelper::OEnumerationByIndex(this);
    1085             : }
    1086             : 
    1087             : // XIndexAccess
    1088             : 
    1089           0 : sal_Int32 SAL_CALL FormController::getCount() throw( RuntimeException, std::exception )
    1090             : {
    1091           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1092           0 :     return m_aChildren.size();
    1093             : }
    1094             : 
    1095             : 
    1096           0 : Any SAL_CALL FormController::getByIndex(sal_Int32 Index) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
    1097             : {
    1098           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1099           0 :     if (Index < 0 ||
    1100           0 :         Index >= (sal_Int32)m_aChildren.size())
    1101           0 :         throw IndexOutOfBoundsException();
    1102             : 
    1103           0 :     return makeAny( m_aChildren[ Index ] );
    1104             : }
    1105             : 
    1106             : //  EventListener
    1107             : 
    1108           0 : void SAL_CALL FormController::disposing(const EventObject& e) throw( RuntimeException, std::exception )
    1109             : {
    1110             :     // Ist der Container disposed worden
    1111           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    1112           0 :     Reference< XControlContainer >  xContainer(e.Source, UNO_QUERY);
    1113           0 :     if (xContainer.is())
    1114             :     {
    1115           0 :         setContainer(Reference< XControlContainer > ());
    1116             :     }
    1117             :     else
    1118             :     {
    1119             :         // ist ein Control disposed worden
    1120           0 :         Reference< XControl >  xControl(e.Source, UNO_QUERY);
    1121           0 :         if (xControl.is())
    1122             :         {
    1123           0 :             if (getContainer().is())
    1124           0 :                 removeControl(xControl);
    1125           0 :         }
    1126           0 :     }
    1127           0 : }
    1128             : 
    1129             : // OComponentHelper
    1130             : 
    1131         380 : void FormController::disposeAllFeaturesAndDispatchers()
    1132             : {
    1133        1140 :     for ( DispatcherContainer::iterator aDispatcher = m_aFeatureDispatchers.begin();
    1134         760 :           aDispatcher != m_aFeatureDispatchers.end();
    1135             :           ++aDispatcher
    1136             :         )
    1137             :     {
    1138             :         try
    1139             :         {
    1140           0 :             ::comphelper::disposeComponent( aDispatcher->second );
    1141             :         }
    1142           0 :         catch( const Exception& )
    1143             :         {
    1144             :             DBG_UNHANDLED_EXCEPTION();
    1145             :         }
    1146             :     }
    1147         380 :     m_aFeatureDispatchers.clear();
    1148         380 : }
    1149             : 
    1150             : 
    1151          95 : void FormController::disposing()
    1152             : {
    1153          95 :     EventObject aEvt( *this );
    1154             : 
    1155             :     // if we're still active, simulate a "deactivated" event
    1156          95 :     if ( m_xActiveControl.is() )
    1157           0 :         m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvt );
    1158             : 
    1159             :     // notify all our listeners
    1160          95 :     m_aActivateListeners.disposeAndClear(aEvt);
    1161          95 :     m_aModifyListeners.disposeAndClear(aEvt);
    1162          95 :     m_aErrorListeners.disposeAndClear(aEvt);
    1163          95 :     m_aDeleteListeners.disposeAndClear(aEvt);
    1164          95 :     m_aRowSetApproveListeners.disposeAndClear(aEvt);
    1165          95 :     m_aParameterListeners.disposeAndClear(aEvt);
    1166          95 :     m_aFilterListeners.disposeAndClear(aEvt);
    1167             : 
    1168          95 :     removeBoundFieldListener();
    1169          95 :     stopFiltering();
    1170             : 
    1171          95 :     m_pControlBorderManager->restoreAll();
    1172             : 
    1173          95 :     m_aFilterRows.clear();
    1174             : 
    1175         190 :     ::osl::MutexGuard aGuard( m_aMutex );
    1176          95 :     m_xActiveControl = NULL;
    1177          95 :     implSetCurrentControl( NULL );
    1178             : 
    1179             :     // clean up our children
    1180         285 :     for (FmFormControllers::const_iterator i = m_aChildren.begin();
    1181         190 :         i != m_aChildren.end(); ++i)
    1182             :     {
    1183             :         // search the position of the model within the form
    1184           0 :         Reference< XFormComponent >  xForm((*i)->getModel(), UNO_QUERY);
    1185           0 :         sal_uInt32 nPos = m_xModelAsIndex->getCount();
    1186           0 :         Reference< XFormComponent > xTemp;
    1187           0 :         for( ; nPos; )
    1188             :         {
    1189             : 
    1190           0 :             m_xModelAsIndex->getByIndex( --nPos ) >>= xTemp;
    1191           0 :             if ( xForm.get() == xTemp.get() )
    1192             :             {
    1193           0 :                 Reference< XInterface > xIfc( *i, UNO_QUERY );
    1194           0 :                 m_xModelAsManager->detach( nPos, xIfc );
    1195           0 :                 break;
    1196             :             }
    1197             :         }
    1198             : 
    1199           0 :         Reference< XComponent > (*i, UNO_QUERY)->dispose();
    1200           0 :     }
    1201          95 :     m_aChildren.clear();
    1202             : 
    1203          95 :     disposeAllFeaturesAndDispatchers();
    1204             : 
    1205          95 :     if ( m_xFormOperations.is() )
    1206          95 :         m_xFormOperations->dispose();
    1207          95 :     m_xFormOperations.clear();
    1208             : 
    1209          95 :     if (m_bDBConnection)
    1210           0 :         unload();
    1211             : 
    1212          95 :     setContainer( NULL );
    1213          95 :     setModel( NULL );
    1214          95 :     setParent( NULL );
    1215             : 
    1216          95 :     ::comphelper::disposeComponent( m_xComposer );
    1217             : 
    1218         190 :     m_bDBConnection = false;
    1219          95 : }
    1220             : 
    1221             : 
    1222             : namespace
    1223             : {
    1224          95 :     static bool lcl_shouldUseDynamicControlBorder( const Reference< XInterface >& _rxForm, const Any& _rDynamicColorProp )
    1225             :     {
    1226          95 :         bool bDoUse = false;
    1227          95 :         if ( !( _rDynamicColorProp >>= bDoUse ) )
    1228             :         {
    1229          95 :             DocumentType eDocType = DocumentClassification::classifyHostDocument( _rxForm );
    1230          95 :             return ControlLayouter::useDynamicBorderColor( eDocType );
    1231             :         }
    1232           0 :         return bDoUse;
    1233             :     }
    1234             : }
    1235             : 
    1236             : 
    1237           0 : void SAL_CALL FormController::propertyChange(const PropertyChangeEvent& evt) throw( RuntimeException, std::exception )
    1238             : {
    1239             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1240           0 :     if ( evt.PropertyName == FM_PROP_BOUNDFIELD )
    1241             :     {
    1242           0 :         Reference<XPropertySet> xOldBound;
    1243           0 :         evt.OldValue >>= xOldBound;
    1244           0 :         if ( !xOldBound.is() && evt.NewValue.hasValue() )
    1245             :         {
    1246           0 :             Reference< XControlModel > xControlModel(evt.Source,UNO_QUERY);
    1247           0 :             Reference< XControl > xControl = findControl(m_aControls,xControlModel,false,false);
    1248           0 :             if ( xControl.is() )
    1249             :             {
    1250           0 :                 startControlModifyListening( xControl );
    1251           0 :                 Reference<XPropertySet> xProp(xControlModel,UNO_QUERY);
    1252           0 :                 if ( xProp.is() )
    1253           0 :                     xProp->removePropertyChangeListener(FM_PROP_BOUNDFIELD, this);
    1254           0 :             }
    1255           0 :         }
    1256             :     }
    1257             :     else
    1258             :     {
    1259           0 :         bool bModifiedChanged = (evt.PropertyName == FM_PROP_ISMODIFIED);
    1260           0 :         bool bNewChanged = (evt.PropertyName == FM_PROP_ISNEW);
    1261           0 :         if (bModifiedChanged || bNewChanged)
    1262             :         {
    1263           0 :             ::osl::MutexGuard aGuard( m_aMutex );
    1264           0 :             if (bModifiedChanged)
    1265           0 :                 m_bCurrentRecordModified = ::comphelper::getBOOL(evt.NewValue);
    1266             :             else
    1267           0 :                 m_bCurrentRecordNew = ::comphelper::getBOOL(evt.NewValue);
    1268             : 
    1269             :             // toggle the locking
    1270           0 :             if (m_bLocked != determineLockState())
    1271             :             {
    1272           0 :                 m_bLocked = !m_bLocked;
    1273           0 :                 setLocks();
    1274           0 :                 if (isListeningForChanges())
    1275           0 :                     startListening();
    1276             :                 else
    1277           0 :                     stopListening();
    1278             :             }
    1279             : 
    1280           0 :             if ( bNewChanged )
    1281           0 :                 m_aToggleEvent.Call();
    1282             : 
    1283           0 :             if (!m_bCurrentRecordModified)
    1284           0 :                 m_bModified = false;
    1285             :         }
    1286           0 :         else if ( evt.PropertyName == FM_PROP_DYNAMIC_CONTROL_BORDER )
    1287             :         {
    1288           0 :             bool bEnable = lcl_shouldUseDynamicControlBorder( evt.Source, evt.NewValue );
    1289           0 :             if ( bEnable )
    1290             :             {
    1291           0 :                 m_pControlBorderManager->enableDynamicBorderColor();
    1292           0 :                 if ( m_xActiveControl.is() )
    1293           0 :                     m_pControlBorderManager->focusGained( m_xActiveControl.get() );
    1294             :             }
    1295             :             else
    1296             :             {
    1297           0 :                 m_pControlBorderManager->disableDynamicBorderColor();
    1298             :             }
    1299             :         }
    1300             :     }
    1301           0 : }
    1302             : 
    1303             : 
    1304           0 : bool FormController::replaceControl( const Reference< XControl >& _rxExistentControl, const Reference< XControl >& _rxNewControl )
    1305             : {
    1306           0 :     bool bSuccess = false;
    1307             :     try
    1308             :     {
    1309           0 :         Reference< XIdentifierReplace > xContainer( getContainer(), UNO_QUERY );
    1310             :         DBG_ASSERT( xContainer.is(), "FormController::replaceControl: yes, it's not required by the service description, but XItentifierReplaces would be nice!" );
    1311           0 :         if ( xContainer.is() )
    1312             :         {
    1313             :             // look up the ID of _rxExistentControl
    1314           0 :             Sequence< sal_Int32 > aIdentifiers( xContainer->getIdentifiers() );
    1315           0 :             const sal_Int32* pIdentifiers = aIdentifiers.getConstArray();
    1316           0 :             const sal_Int32* pIdentifiersEnd = aIdentifiers.getConstArray() + aIdentifiers.getLength();
    1317           0 :             for ( ; pIdentifiers != pIdentifiersEnd; ++pIdentifiers )
    1318             :             {
    1319           0 :                 Reference< XControl > xCheck( xContainer->getByIdentifier( *pIdentifiers ), UNO_QUERY );
    1320           0 :                 if ( xCheck == _rxExistentControl )
    1321           0 :                     break;
    1322           0 :             }
    1323             :             DBG_ASSERT( pIdentifiers != pIdentifiersEnd, "FormController::replaceControl: did not find the control in the container!" );
    1324           0 :             if ( pIdentifiers != pIdentifiersEnd )
    1325             :             {
    1326           0 :                 bool bReplacedWasActive = ( m_xActiveControl.get() == _rxExistentControl.get() );
    1327           0 :                 bool bReplacedWasCurrent = ( m_xCurrentControl.get() == _rxExistentControl.get() );
    1328             : 
    1329           0 :                 if ( bReplacedWasActive )
    1330             :                 {
    1331           0 :                     m_xActiveControl = NULL;
    1332           0 :                     implSetCurrentControl( NULL );
    1333             :                 }
    1334           0 :                 else if ( bReplacedWasCurrent )
    1335             :                 {
    1336           0 :                     implSetCurrentControl( _rxNewControl );
    1337             :                 }
    1338             : 
    1339             :                 // carry over the model
    1340           0 :                 _rxNewControl->setModel( _rxExistentControl->getModel() );
    1341             : 
    1342           0 :                 xContainer->replaceByIdentifer( *pIdentifiers, makeAny( _rxNewControl ) );
    1343           0 :                 bSuccess = true;
    1344             : 
    1345           0 :                 if ( bReplacedWasActive )
    1346             :                 {
    1347           0 :                     Reference< XWindow > xControlWindow( _rxNewControl, UNO_QUERY );
    1348           0 :                     if ( xControlWindow.is() )
    1349           0 :                         xControlWindow->setFocus();
    1350             :                 }
    1351           0 :             }
    1352           0 :         }
    1353             :     }
    1354           0 :     catch( const Exception& )
    1355             :     {
    1356             :         DBG_UNHANDLED_EXCEPTION();
    1357             :     }
    1358             : 
    1359           0 :     Reference< XControl > xDisposeIt( bSuccess ? _rxExistentControl : _rxNewControl );
    1360           0 :     ::comphelper::disposeComponent( xDisposeIt );
    1361           0 :     return bSuccess;
    1362             : }
    1363             : 
    1364             : 
    1365           0 : void FormController::toggleAutoFields(bool bAutoFields)
    1366             : {
    1367             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1368             : 
    1369             : 
    1370           0 :     Sequence< Reference< XControl > > aControlsCopy( m_aControls );
    1371           0 :     const Reference< XControl >* pControls = aControlsCopy.getConstArray();
    1372           0 :     sal_Int32 nControls = aControlsCopy.getLength();
    1373             : 
    1374           0 :     if (bAutoFields)
    1375             :     {
    1376             :         // as we don't want new controls to be attached to the scripting environment
    1377             :         // we change attach flags
    1378           0 :         m_bAttachEvents = false;
    1379           0 :         for (sal_Int32 i = nControls; i > 0;)
    1380             :         {
    1381           0 :             Reference< XControl > xControl = pControls[--i];
    1382           0 :             if (xControl.is())
    1383             :             {
    1384           0 :                 Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
    1385           0 :                 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
    1386             :                 {
    1387             :                     // does the model use a bound field ?
    1388           0 :                     Reference< XPropertySet >  xField;
    1389           0 :                     xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
    1390             : 
    1391             :                     // is it a autofield?
    1392           0 :                     if  (   xField.is()
    1393           0 :                         &&  ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT, xField )
    1394           0 :                         &&  ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_AUTOINCREMENT ) )
    1395             :                         )
    1396             :                     {
    1397           0 :                         replaceControl( xControl, new FmXAutoControl() );
    1398           0 :                     }
    1399           0 :                 }
    1400             :             }
    1401           0 :         }
    1402           0 :         m_bAttachEvents = true;
    1403             :     }
    1404             :     else
    1405             :     {
    1406           0 :         m_bDetachEvents = false;
    1407           0 :         for (sal_Int32 i = nControls; i > 0;)
    1408             :         {
    1409           0 :             Reference< XControl > xControl = pControls[--i];
    1410           0 :             if (xControl.is())
    1411             :             {
    1412           0 :                 Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
    1413           0 :                 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
    1414             :                 {
    1415             :                     // does the model use a bound field ?
    1416           0 :                     Reference< XPropertySet >  xField;
    1417           0 :                     xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
    1418             : 
    1419             :                     // is it a autofield?
    1420           0 :                     if  (   xField.is()
    1421           0 :                         &&  ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT, xField )
    1422           0 :                         &&  ::comphelper::getBOOL( xField->getPropertyValue(FM_PROP_AUTOINCREMENT ) )
    1423             :                         )
    1424             :                     {
    1425           0 :                         OUString sServiceName;
    1426           0 :                         OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName );
    1427           0 :                         Reference< XControl > xNewControl( m_xComponentContext->getServiceManager()->createInstanceWithContext( sServiceName, m_xComponentContext ), UNO_QUERY );
    1428           0 :                         replaceControl( xControl, xNewControl );
    1429           0 :                     }
    1430           0 :                 }
    1431             :             }
    1432           0 :         }
    1433           0 :         m_bDetachEvents = true;
    1434           0 :     }
    1435           0 : }
    1436             : 
    1437             : 
    1438           0 : IMPL_LINK_NOARG(FormController, OnToggleAutoFields)
    1439             : {
    1440             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1441             : 
    1442           0 :     toggleAutoFields(m_bCurrentRecordNew);
    1443           0 :     return 1L;
    1444             : }
    1445             : 
    1446             : // XTextListener
    1447             : 
    1448           0 : void SAL_CALL FormController::textChanged(const TextEvent& e) throw( RuntimeException, std::exception )
    1449             : {
    1450             :     // SYNCHRONIZED -->
    1451           0 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    1452             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1453           0 :     if ( !m_bFiltering )
    1454             :     {
    1455           0 :         impl_onModify();
    1456           0 :         return;
    1457             :     }
    1458             : 
    1459           0 :     if ( m_bSuspendFilterTextListening )
    1460           0 :         return;
    1461             : 
    1462           0 :     Reference< XTextComponent >  xText(e.Source,UNO_QUERY);
    1463           0 :     OUString aText = xText->getText();
    1464             : 
    1465           0 :     if ( m_aFilterRows.empty() )
    1466           0 :         appendEmptyDisjunctiveTerm();
    1467             : 
    1468             :     // Suchen der aktuellen Row
    1469           0 :     if ( ( (size_t)m_nCurrentFilterPosition >= m_aFilterRows.size() ) || ( m_nCurrentFilterPosition < 0 ) )
    1470             :     {
    1471             :         OSL_ENSURE( false, "FormController::textChanged: m_nCurrentFilterPosition is wrong!" );
    1472           0 :         return;
    1473             :     }
    1474             : 
    1475           0 :     FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
    1476             : 
    1477             :     // do we have a new filter
    1478           0 :     if (!aText.isEmpty())
    1479           0 :         rRow[xText] = aText;
    1480             :     else
    1481             :     {
    1482             :         // do we have the control in the row
    1483           0 :         FmFilterRow::iterator iter = rRow.find(xText);
    1484             :         // erase the entry out of the row
    1485           0 :         if (iter != rRow.end())
    1486           0 :             rRow.erase(iter);
    1487             :     }
    1488             : 
    1489             :     // multiplex the event to our FilterControllerListeners
    1490           0 :     FilterEvent aEvent;
    1491           0 :     aEvent.Source = *this;
    1492           0 :     aEvent.FilterComponent = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xText ) - m_aFilterComponents.begin();
    1493           0 :     aEvent.DisjunctiveTerm = getActiveTerm();
    1494           0 :     aEvent.PredicateExpression = aText;
    1495             : 
    1496           0 :     aGuard.clear();
    1497             :     // <-- SYNCHRONIZED
    1498             : 
    1499             :     // notify the changed filter expression
    1500           0 :     m_aFilterListeners.notifyEach( &XFilterControllerListener::predicateExpressionChanged, aEvent );
    1501             : }
    1502             : 
    1503             : // XItemListener
    1504             : 
    1505           0 : void SAL_CALL FormController::itemStateChanged(const ItemEvent& /*rEvent*/) throw( RuntimeException, std::exception )
    1506             : {
    1507             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1508           0 :     impl_onModify();
    1509           0 : }
    1510             : 
    1511             : // XModificationBroadcaster
    1512             : 
    1513          96 : void SAL_CALL FormController::addModifyListener(const Reference< XModifyListener > & l) throw( RuntimeException, std::exception )
    1514             : {
    1515          96 :     ::osl::MutexGuard aGuard( m_aMutex );
    1516          96 :     impl_checkDisposed_throw();
    1517          96 :     m_aModifyListeners.addInterface( l );
    1518          96 : }
    1519             : 
    1520             : 
    1521          96 : void FormController::removeModifyListener(const Reference< XModifyListener > & l) throw( RuntimeException, std::exception )
    1522             : {
    1523          96 :     ::osl::MutexGuard aGuard( m_aMutex );
    1524          96 :     impl_checkDisposed_throw();
    1525          96 :     m_aModifyListeners.removeInterface( l );
    1526          96 : }
    1527             : 
    1528             : // XModificationListener
    1529             : 
    1530           0 : void FormController::modified( const EventObject& _rEvent ) throw( RuntimeException, std::exception )
    1531             : {
    1532             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1533             : 
    1534             :     try
    1535             :     {
    1536           0 :         if ( _rEvent.Source != m_xActiveControl )
    1537             :         {   // let this control grab the focus
    1538             :             // (this case may happen if somebody moves the scroll wheel of the mouse over a control
    1539             :             // which does not have the focus)
    1540             :             // 85511 - 29.05.2001 - frank.schoenheit@germany.sun.com
    1541             : 
    1542             :             // also, it happens when an image control gets a new image by double-clicking it
    1543             :             // #i88458# / 2009-01-12 / frank.schoenheit@sun.com
    1544           0 :             Reference< XWindow > xControlWindow( _rEvent.Source, UNO_QUERY_THROW );
    1545           0 :             xControlWindow->setFocus();
    1546             :         }
    1547             :     }
    1548           0 :     catch( const Exception& )
    1549             :     {
    1550             :         DBG_UNHANDLED_EXCEPTION();
    1551             :     }
    1552             : 
    1553           0 :     impl_onModify();
    1554           0 : }
    1555             : 
    1556             : 
    1557        1418 : void FormController::impl_checkDisposed_throw() const
    1558             : {
    1559        1418 :     if ( impl_isDisposed_nofail() )
    1560           0 :         throw DisposedException( OUString(), *const_cast< FormController* >( this ) );
    1561        1418 : }
    1562             : 
    1563             : 
    1564           0 : void FormController::impl_onModify()
    1565             : {
    1566             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1567             : 
    1568             :     {
    1569           0 :         ::osl::MutexGuard aGuard( m_aMutex );
    1570           0 :         if ( !m_bModified )
    1571           0 :             m_bModified = true;
    1572             :     }
    1573             : 
    1574           0 :     EventObject aEvt(static_cast<cppu::OWeakObject*>(this));
    1575           0 :     m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt );
    1576           0 : }
    1577             : 
    1578             : 
    1579           0 : void FormController::impl_addFilterRow( const FmFilterRow& _row )
    1580             : {
    1581           0 :     m_aFilterRows.push_back( _row );
    1582             : 
    1583           0 :     if ( m_aFilterRows.size() == 1 )
    1584             :     {   // that's the first row ever
    1585             :         OSL_ENSURE( m_nCurrentFilterPosition == -1, "FormController::impl_addFilterRow: inconsistency!" );
    1586           0 :         m_nCurrentFilterPosition = 0;
    1587             :     }
    1588           0 : }
    1589             : 
    1590             : 
    1591           0 : void FormController::impl_appendEmptyFilterRow( ::osl::ClearableMutexGuard& _rClearBeforeNotify )
    1592             : {
    1593             :     // SYNCHRONIZED -->
    1594           0 :     impl_addFilterRow( FmFilterRow() );
    1595             : 
    1596             :     // notify the listeners
    1597           0 :     FilterEvent aEvent;
    1598           0 :     aEvent.Source = *this;
    1599           0 :     aEvent.DisjunctiveTerm = (sal_Int32)m_aFilterRows.size() - 1;
    1600           0 :     _rClearBeforeNotify.clear();
    1601             :     // <-- SYNCHRONIZED
    1602           0 :     m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermAdded, aEvent );
    1603           0 : }
    1604             : 
    1605             : 
    1606           0 : bool FormController::determineLockState() const
    1607             : {
    1608             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1609             :     // a.) in filter mode we are always locked
    1610             :     // b.) if we have no valid model or our model (a result set) is not alive -> we're locked
    1611             :     // c.) if we are inserting everything is OK and we are not locked
    1612             :     // d.) if are not updatable or on invalid position
    1613           0 :     Reference< XResultSet >  xResultSet(m_xModelAsIndex, UNO_QUERY);
    1614           0 :     if (m_bFiltering || !xResultSet.is() || !isRowSetAlive(xResultSet))
    1615           0 :         return true;
    1616             :     else
    1617           0 :         return !(m_bCanInsert && m_bCurrentRecordNew)
    1618           0 :             && (xResultSet->isBeforeFirst() || xResultSet->isAfterLast() || xResultSet->rowDeleted() || !m_bCanUpdate);
    1619             : }
    1620             : 
    1621             : //  FocusListener
    1622             : 
    1623           1 : void FormController::focusGained(const FocusEvent& e) throw( RuntimeException, std::exception )
    1624             : {
    1625             :     // SYNCHRONIZED -->
    1626           1 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    1627           1 :     impl_checkDisposed_throw();
    1628             : 
    1629           1 :     m_pControlBorderManager->focusGained( e.Source );
    1630             : 
    1631           2 :     Reference< XControl >  xControl(e.Source, UNO_QUERY);
    1632           1 :     if (m_bDBConnection)
    1633             :     {
    1634             :         // do we need to keep the locking of the commit
    1635             :         // we hold the lock as long as the control differs from the current
    1636             :         // otherwise we disabled the lock
    1637           0 :         m_bCommitLock = m_bCommitLock && xControl.get() != m_xCurrentControl.get();
    1638           0 :         if (m_bCommitLock)
    1639           0 :             return;
    1640             : 
    1641             :         // when do we have to commit a value to form or a filter
    1642             :         // a.) if the current value is modified
    1643             :         // b.) there must be a current control
    1644             :         // c.) and it must be different from the new focus owning control or
    1645             :         // d.) the focus is moving around (so we have only one control)
    1646             : 
    1647           0 :         if  (   ( m_bModified || m_bFiltering )
    1648           0 :             &&  m_xCurrentControl.is()
    1649           0 :             &&  (   ( xControl.get() != m_xCurrentControl.get() )
    1650           0 :                 ||  (   ( e.FocusFlags & FocusChangeReason::AROUND )
    1651           0 :                     &&  ( m_bCycle || m_bFiltering )
    1652             :                     )
    1653             :                 )
    1654             :             )
    1655             :         {
    1656             :             // check the old control if the content is ok
    1657             : #if OSL_DEBUG_LEVEL > 1
    1658             :             Reference< XBoundControl >  xLockingTest(m_xCurrentControl, UNO_QUERY);
    1659             :             sal_Bool bControlIsLocked = xLockingTest.is() && xLockingTest->getLock();
    1660             :             OSL_ENSURE(!bControlIsLocked, "FormController::Gained: I'm modified and the current control is locked ? How this ?");
    1661             :             // normalerweise sollte ein gelocktes Control nicht modified sein, also muss wohl mein bModified aus einem anderen Kontext
    1662             :             // gesetzt worden sein, was ich nicht verstehen wuerde ...
    1663             : #endif
    1664             :             DBG_ASSERT(m_xCurrentControl.is(), "kein CurrentControl gesetzt");
    1665             :             // zunaechst das Control fragen ob es das IFace unterstuetzt
    1666           0 :             Reference< XBoundComponent >  xBound(m_xCurrentControl, UNO_QUERY);
    1667           0 :             if (!xBound.is() && m_xCurrentControl.is())
    1668           0 :                 xBound  = Reference< XBoundComponent > (m_xCurrentControl->getModel(), UNO_QUERY);
    1669             : 
    1670             :             // lock if we lose the focus during commit
    1671           0 :             m_bCommitLock = true;
    1672             : 
    1673             :             // Commit nicht erfolgreich, Focus zuruecksetzen
    1674           0 :             if (xBound.is() && !xBound->commit())
    1675             :             {
    1676             :                 // the commit failed and we don't commit again until the current control
    1677             :                 // which couldn't be commit gains the focus again
    1678           0 :                 Reference< XWindow >  xWindow(m_xCurrentControl, UNO_QUERY);
    1679           0 :                 if (xWindow.is())
    1680           0 :                     xWindow->setFocus();
    1681           0 :                 return;
    1682             :             }
    1683             :             else
    1684             :             {
    1685           0 :                 m_bModified = false;
    1686           0 :                 m_bCommitLock = false;
    1687           0 :             }
    1688             :         }
    1689             : 
    1690           0 :         if (!m_bFiltering && m_bCycle && (e.FocusFlags & FocusChangeReason::AROUND) && m_xCurrentControl.is())
    1691             :         {
    1692           0 :             SQLErrorEvent aErrorEvent;
    1693             :             OSL_ENSURE( m_xFormOperations.is(), "FormController::focusGained: hmm?" );
    1694             :                 // should have been created in setModel
    1695             :             try
    1696             :             {
    1697           0 :                 if ( e.FocusFlags & FocusChangeReason::FORWARD )
    1698             :                 {
    1699           0 :                     if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToNext ) )
    1700           0 :                         m_xFormOperations->execute( FormFeature::MoveToNext );
    1701             :                 }
    1702             :                 else // backward
    1703             :                 {
    1704           0 :                     if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToPrevious ) )
    1705           0 :                         m_xFormOperations->execute( FormFeature::MoveToPrevious );
    1706             :                 }
    1707             :             }
    1708           0 :             catch ( const Exception& )
    1709             :             {
    1710             :                 // don't handle this any further. That's an ... admissible error.
    1711             :                 DBG_UNHANDLED_EXCEPTION();
    1712           0 :             }
    1713             :         }
    1714             :     }
    1715             : 
    1716             :     // Immer noch ein und dasselbe Control
    1717           2 :     if  (   ( m_xActiveControl == xControl )
    1718           1 :         &&  ( xControl == m_xCurrentControl )
    1719             :         )
    1720             :     {
    1721             :         DBG_ASSERT(m_xCurrentControl.is(), "Kein CurrentControl selektiert");
    1722           0 :         return;
    1723             :     }
    1724             : 
    1725           1 :     bool bActivated = !m_xActiveControl.is() && xControl.is();
    1726             : 
    1727           1 :     m_xActiveControl  = xControl;
    1728             : 
    1729           1 :     implSetCurrentControl( xControl );
    1730             :     SAL_WARN_IF( !m_xCurrentControl.is(), "svx.form", "implSetCurrentControl did nonsense!" );
    1731             : 
    1732           1 :     if ( bActivated )
    1733             :     {
    1734             :         // (asynchronously) call activation handlers
    1735           1 :         m_aActivationEvent.Call();
    1736             : 
    1737             :         // call modify listeners
    1738           1 :         if ( m_bModified )
    1739           0 :             m_aModifyListeners.notifyEach( &XModifyListener::modified, EventObject( *this ) );
    1740             :     }
    1741             : 
    1742             :     // invalidate all features which depend on the currently focused control
    1743           1 :     if ( m_bDBConnection && !m_bFiltering )
    1744           0 :         implInvalidateCurrentControlDependentFeatures();
    1745             : 
    1746           1 :     if ( !m_xCurrentControl.is() )
    1747           0 :         return;
    1748             : 
    1749             :     // Control erhaelt Focus, dann eventuell in den sichtbaren Bereich
    1750           2 :     Reference< XFormControllerContext > xContext( m_xFormControllerContext );
    1751           2 :     Reference< XControl > xCurrentControl( m_xCurrentControl );
    1752           1 :     aGuard.clear();
    1753             :     // <-- SYNCHRONIZED
    1754             : 
    1755           1 :     if ( xContext.is() )
    1756           2 :         xContext->makeVisible( xCurrentControl );
    1757             : }
    1758             : 
    1759             : 
    1760           2 : IMPL_LINK_NOARG( FormController, OnActivated )
    1761             : {
    1762           1 :     EventObject aEvent;
    1763           1 :     aEvent.Source = *this;
    1764           1 :     m_aActivateListeners.notifyEach( &XFormControllerListener::formActivated, aEvent );
    1765             : 
    1766           1 :     return 0L;
    1767             : }
    1768             : 
    1769             : 
    1770           2 : IMPL_LINK_NOARG( FormController, OnDeactivated )
    1771             : {
    1772           1 :     EventObject aEvent;
    1773           1 :     aEvent.Source = *this;
    1774           1 :     m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvent );
    1775             : 
    1776           1 :     return 0L;
    1777             : }
    1778             : 
    1779             : 
    1780           1 : void FormController::focusLost(const FocusEvent& e) throw( RuntimeException, std::exception )
    1781             : {
    1782             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1783             : 
    1784           1 :     m_pControlBorderManager->focusLost( e.Source );
    1785             : 
    1786           1 :     Reference< XControl >  xControl(e.Source, UNO_QUERY);
    1787           2 :     Reference< XWindowPeer >  xNext(e.NextFocus, UNO_QUERY);
    1788           2 :     Reference< XControl >  xNextControl = isInList(xNext);
    1789           1 :     if (!xNextControl.is())
    1790             :     {
    1791           1 :         m_xActiveControl = NULL;
    1792           1 :         m_aDeactivationEvent.Call();
    1793           1 :     }
    1794           1 : }
    1795             : 
    1796             : 
    1797           0 : void SAL_CALL FormController::mousePressed( const awt::MouseEvent& /*_rEvent*/ ) throw (RuntimeException, std::exception)
    1798             : {
    1799             :     // not interested in
    1800           0 : }
    1801             : 
    1802             : 
    1803           0 : void SAL_CALL FormController::mouseReleased( const awt::MouseEvent& /*_rEvent*/ ) throw (RuntimeException, std::exception)
    1804             : {
    1805             :     // not interested in
    1806           0 : }
    1807             : 
    1808             : 
    1809           0 : void SAL_CALL FormController::mouseEntered( const awt::MouseEvent& _rEvent ) throw (RuntimeException, std::exception)
    1810             : {
    1811           0 :     m_pControlBorderManager->mouseEntered( _rEvent.Source );
    1812           0 : }
    1813             : 
    1814             : 
    1815           0 : void SAL_CALL FormController::mouseExited( const awt::MouseEvent& _rEvent ) throw (RuntimeException, std::exception)
    1816             : {
    1817           0 :     m_pControlBorderManager->mouseExited( _rEvent.Source );
    1818           0 : }
    1819             : 
    1820             : 
    1821          17 : void SAL_CALL FormController::componentValidityChanged( const EventObject& _rSource ) throw (RuntimeException, std::exception)
    1822             : {
    1823          17 :     Reference< XControl > xControl( findControl( m_aControls, Reference< XControlModel >( _rSource.Source, UNO_QUERY ), false, false ) );
    1824          34 :     Reference< XValidatableFormComponent > xValidatable( _rSource.Source, UNO_QUERY );
    1825             : 
    1826             :     OSL_ENSURE( xControl.is() && xValidatable.is(), "FormController::componentValidityChanged: huh?" );
    1827             : 
    1828          17 :     if ( xControl.is() && xValidatable.is() )
    1829          34 :         m_pControlBorderManager->validityChanged( xControl, xValidatable );
    1830          17 : }
    1831             : 
    1832             : 
    1833         190 : void FormController::setModel(const Reference< XTabControllerModel > & Model) throw( RuntimeException, std::exception )
    1834             : {
    1835         190 :     ::osl::MutexGuard aGuard( m_aMutex );
    1836         190 :     impl_checkDisposed_throw();
    1837             : 
    1838             :     DBG_ASSERT(m_xTabController.is(), "FormController::setModel : invalid aggregate !");
    1839             : 
    1840             :     try
    1841             :     {
    1842             :         // disconnect from the old model
    1843         190 :         if (m_xModelAsIndex.is())
    1844             :         {
    1845          95 :             if (m_bDBConnection)
    1846             :             {
    1847             :                 // we are currently working on the model
    1848           0 :                 EventObject aEvt(m_xModelAsIndex);
    1849           0 :                 unloaded(aEvt);
    1850             :             }
    1851             : 
    1852          95 :             Reference< XLoadable >  xForm(m_xModelAsIndex, UNO_QUERY);
    1853          95 :             if (xForm.is())
    1854          95 :                 xForm->removeLoadListener(this);
    1855             : 
    1856         190 :             Reference< XSQLErrorBroadcaster >  xBroadcaster(m_xModelAsIndex, UNO_QUERY);
    1857          95 :             if (xBroadcaster.is())
    1858          95 :                 xBroadcaster->removeSQLErrorListener(this);
    1859             : 
    1860         190 :             Reference< XDatabaseParameterBroadcaster >  xParamBroadcaster(m_xModelAsIndex, UNO_QUERY);
    1861          95 :             if (xParamBroadcaster.is())
    1862         190 :                 xParamBroadcaster->removeParameterListener(this);
    1863             : 
    1864             :         }
    1865             : 
    1866         190 :         disposeAllFeaturesAndDispatchers();
    1867             : 
    1868         190 :         if ( m_xFormOperations.is() )
    1869           0 :             m_xFormOperations->dispose();
    1870         190 :         m_xFormOperations.clear();
    1871             : 
    1872             :         // set the new model wait for the load event
    1873         190 :         if (m_xTabController.is())
    1874         190 :             m_xTabController->setModel(Model);
    1875         190 :         m_xModelAsIndex = Reference< XIndexAccess > (Model, UNO_QUERY);
    1876         190 :         m_xModelAsManager = Reference< XEventAttacherManager > (Model, UNO_QUERY);
    1877             : 
    1878             :         // only if both ifaces exit, the controller will work successful
    1879         190 :         if (!m_xModelAsIndex.is() || !m_xModelAsManager.is())
    1880             :         {
    1881          95 :             m_xModelAsManager = NULL;
    1882          95 :             m_xModelAsIndex = NULL;
    1883             :         }
    1884             : 
    1885         190 :         if (m_xModelAsIndex.is())
    1886             :         {
    1887             :             // re-create m_xFormOperations
    1888          95 :             m_xFormOperations = FormOperations::createWithFormController( m_xComponentContext, this );
    1889          95 :             m_xFormOperations->setFeatureInvalidation( this );
    1890             : 
    1891             :             // adding load and ui interaction listeners
    1892          95 :             Reference< XLoadable >  xForm(Model, UNO_QUERY);
    1893          95 :             if (xForm.is())
    1894          95 :                 xForm->addLoadListener(this);
    1895             : 
    1896         190 :             Reference< XSQLErrorBroadcaster >  xBroadcaster(Model, UNO_QUERY);
    1897          95 :             if (xBroadcaster.is())
    1898          95 :                 xBroadcaster->addSQLErrorListener(this);
    1899             : 
    1900         190 :             Reference< XDatabaseParameterBroadcaster >  xParamBroadcaster(Model, UNO_QUERY);
    1901          95 :             if (xParamBroadcaster.is())
    1902          95 :                 xParamBroadcaster->addParameterListener(this);
    1903             : 
    1904             :             // well, is the database already loaded?
    1905             :             // then we have to simulate a load event
    1906         190 :             Reference< XLoadable >  xCursor(m_xModelAsIndex, UNO_QUERY);
    1907          95 :             if (xCursor.is() && xCursor->isLoaded())
    1908             :             {
    1909           0 :                 EventObject aEvt(xCursor);
    1910           0 :                 loaded(aEvt);
    1911             :             }
    1912             : 
    1913         190 :             Reference< XPropertySet > xModelProps( m_xModelAsIndex, UNO_QUERY );
    1914         190 :             Reference< XPropertySetInfo > xPropInfo( xModelProps->getPropertySetInfo() );
    1915         285 :             if (  xPropInfo.is()
    1916         285 :                && xPropInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER )
    1917         190 :                && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_FOCUS )
    1918         190 :                && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_MOUSE )
    1919         380 :                && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_INVALID )
    1920             :                )
    1921             :             {
    1922             :                 bool bEnableDynamicControlBorder = lcl_shouldUseDynamicControlBorder(
    1923          95 :                     xModelProps.get(), xModelProps->getPropertyValue( FM_PROP_DYNAMIC_CONTROL_BORDER ) );
    1924          95 :                 if ( bEnableDynamicControlBorder )
    1925           0 :                     m_pControlBorderManager->enableDynamicBorderColor();
    1926             :                 else
    1927          95 :                     m_pControlBorderManager->disableDynamicBorderColor();
    1928             : 
    1929          95 :                 sal_Int32 nColor = 0;
    1930          95 :                 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_FOCUS ) >>= nColor )
    1931           0 :                     m_pControlBorderManager->setStatusColor( CONTROL_STATUS_FOCUSED, nColor );
    1932          95 :                 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_MOUSE ) >>= nColor )
    1933           0 :                     m_pControlBorderManager->setStatusColor( CONTROL_STATUS_MOUSE_HOVER, nColor );
    1934          95 :                 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_INVALID ) >>= nColor )
    1935           0 :                     m_pControlBorderManager->setStatusColor( CONTROL_STATUS_INVALID, nColor );
    1936          95 :             }
    1937             :         }
    1938             :     }
    1939           0 :     catch( const Exception& )
    1940             :     {
    1941             :         DBG_UNHANDLED_EXCEPTION();
    1942         190 :     }
    1943         190 : }
    1944             : 
    1945             : 
    1946         501 : Reference< XTabControllerModel >  FormController::getModel() throw( RuntimeException, std::exception )
    1947             : {
    1948         501 :     ::osl::MutexGuard aGuard( m_aMutex );
    1949         501 :     impl_checkDisposed_throw();
    1950             : 
    1951             :     DBG_ASSERT(m_xTabController.is(), "FormController::getModel : invalid aggregate !");
    1952         501 :     if (!m_xTabController.is())
    1953           0 :         return Reference< XTabControllerModel > ();
    1954         501 :     return m_xTabController->getModel();
    1955             : }
    1956             : 
    1957             : 
    1958          56 : void FormController::addToEventAttacher(const Reference< XControl > & xControl)
    1959             : {
    1960             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1961             :     OSL_ENSURE( xControl.is(), "FormController::addToEventAttacher: invalid control - how did you reach this?" );
    1962          56 :     if ( !xControl.is() )
    1963          56 :         return; /* throw IllegalArgumentException(); */
    1964             : 
    1965             :     // anmelden beim Eventattacher
    1966          56 :     Reference< XFormComponent >  xComp(xControl->getModel(), UNO_QUERY);
    1967          56 :     if (xComp.is() && m_xModelAsIndex.is())
    1968             :     {
    1969             :         // Und die Position des ControlModel darin suchen
    1970          56 :         sal_uInt32 nPos = m_xModelAsIndex->getCount();
    1971          56 :         Reference< XFormComponent > xTemp;
    1972          56 :         for( ; nPos; )
    1973             :         {
    1974         116 :             m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
    1975         116 :             if (xComp.get() == xTemp.get())
    1976             :             {
    1977          56 :                 m_xModelAsManager->attach( nPos, Reference<XInterface>( xControl, UNO_QUERY ), makeAny(xControl) );
    1978          56 :                 break;
    1979             :             }
    1980          56 :         }
    1981          56 :     }
    1982             : }
    1983             : 
    1984             : 
    1985          56 : void FormController::removeFromEventAttacher(const Reference< XControl > & xControl)
    1986             : {
    1987             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    1988             :     OSL_ENSURE( xControl.is(), "FormController::removeFromEventAttacher: invalid control - how did you reach this?" );
    1989          56 :     if ( !xControl.is() )
    1990          56 :         return; /* throw IllegalArgumentException(); */
    1991             : 
    1992             :     // abmelden beim Eventattacher
    1993          56 :     Reference< XFormComponent >  xComp(xControl->getModel(), UNO_QUERY);
    1994          56 :     if ( xComp.is() && m_xModelAsIndex.is() )
    1995             :     {
    1996             :         // Und die Position des ControlModel darin suchen
    1997          56 :         sal_uInt32 nPos = m_xModelAsIndex->getCount();
    1998          56 :         Reference< XFormComponent > xTemp;
    1999          56 :         for( ; nPos; )
    2000             :         {
    2001         116 :             m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
    2002         116 :             if (xComp.get() == xTemp.get())
    2003             :             {
    2004          56 :                 m_xModelAsManager->detach( nPos, Reference<XInterface>( xControl, UNO_QUERY ) );
    2005          56 :                 break;
    2006             :             }
    2007          56 :         }
    2008          56 :     }
    2009             : }
    2010             : 
    2011             : 
    2012         190 : void FormController::setContainer(const Reference< XControlContainer > & xContainer) throw( RuntimeException, std::exception )
    2013             : {
    2014             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2015         190 :     Reference< XTabControllerModel >  xTabModel(getModel());
    2016             :     DBG_ASSERT(xTabModel.is() || !xContainer.is(), "No Model defined");
    2017             :         // if we have a new container we need a model
    2018             :     DBG_ASSERT(m_xTabController.is(), "FormController::setContainer : invalid aggregate !");
    2019             : 
    2020         380 :     ::osl::MutexGuard aGuard( m_aMutex );
    2021         380 :     Reference< XContainer >  xCurrentContainer;
    2022         190 :     if (m_xTabController.is())
    2023         190 :         xCurrentContainer = Reference< XContainer > (m_xTabController->getContainer(), UNO_QUERY);
    2024         190 :     if (xCurrentContainer.is())
    2025             :     {
    2026          95 :         xCurrentContainer->removeContainerListener(this);
    2027             : 
    2028          95 :         if ( m_aTabActivationIdle.IsActive() )
    2029          24 :             m_aTabActivationIdle.Stop();
    2030             : 
    2031             :         // clear the filter map
    2032          95 :         ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
    2033          95 :         m_aFilterComponents.clear();
    2034             : 
    2035             :         // einsammeln der Controls
    2036          95 :         const Reference< XControl >* pControls = m_aControls.getConstArray();
    2037          95 :         const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
    2038         245 :         while ( pControls != pControlsEnd )
    2039          55 :             implControlRemoved( *pControls++, true );
    2040             : 
    2041             :         // Datenbank spezifische Dinge vornehmen
    2042          95 :         if (m_bDBConnection && isListeningForChanges())
    2043           0 :             stopListening();
    2044             : 
    2045          95 :         m_aControls.realloc( 0 );
    2046             :     }
    2047             : 
    2048         190 :     if (m_xTabController.is())
    2049         190 :         m_xTabController->setContainer(xContainer);
    2050             : 
    2051             :     // Welche Controls gehoeren zum Container ?
    2052         190 :     if (xContainer.is() && xTabModel.is())
    2053             :     {
    2054          95 :         Sequence< Reference< XControlModel > > aModels = xTabModel->getControlModels();
    2055          95 :         const Reference< XControlModel > * pModels = aModels.getConstArray();
    2056         190 :         Sequence< Reference< XControl > > aAllControls = xContainer->getControls();
    2057             : 
    2058          95 :         sal_Int32 nCount = aModels.getLength();
    2059          95 :         m_aControls = Sequence< Reference< XControl > >( nCount );
    2060          95 :         Reference< XControl > * pControls = m_aControls.getArray();
    2061             : 
    2062             :         // einsammeln der Controls
    2063             :         sal_Int32 i, j;
    2064         233 :         for (i = 0, j = 0; i < nCount; ++i, ++pModels )
    2065             :         {
    2066         138 :             Reference< XControl > xControl = findControl( aAllControls, *pModels, false, true );
    2067         138 :             if ( xControl.is() )
    2068             :             {
    2069           3 :                 pControls[j++] = xControl;
    2070           3 :                 implControlInserted( xControl, true );
    2071             :             }
    2072         138 :         }
    2073             : 
    2074             :         // not every model had an associated control
    2075          95 :         if (j != i)
    2076          91 :             m_aControls.realloc(j);
    2077             : 
    2078             :         // am Container horchen
    2079         190 :         Reference< XContainer >  xNewContainer(xContainer, UNO_QUERY);
    2080          95 :         if (xNewContainer.is())
    2081          95 :             xNewContainer->addContainerListener(this);
    2082             : 
    2083             :         // Datenbank spezifische Dinge vornehmen
    2084          95 :         if (m_bDBConnection)
    2085             :         {
    2086           0 :             m_bLocked = determineLockState();
    2087           0 :             setLocks();
    2088           0 :             if (!isLocked())
    2089           0 :                 startListening();
    2090          95 :         }
    2091             :     }
    2092             :     // befinden sich die Controls in der richtigen Reihenfolge
    2093         380 :     m_bControlsSorted = true;
    2094         190 : }
    2095             : 
    2096             : 
    2097           0 : Reference< XControlContainer >  FormController::getContainer() throw( RuntimeException, std::exception )
    2098             : {
    2099           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2100           0 :     impl_checkDisposed_throw();
    2101             : 
    2102             :     DBG_ASSERT(m_xTabController.is(), "FormController::getContainer : invalid aggregate !");
    2103           0 :     if (!m_xTabController.is())
    2104           0 :         return Reference< XControlContainer > ();
    2105           0 :     return m_xTabController->getContainer();
    2106             : }
    2107             : 
    2108             : 
    2109         150 : Sequence< Reference< XControl > > FormController::getControls() throw( RuntimeException, std::exception )
    2110             : {
    2111         150 :     ::osl::MutexGuard aGuard( m_aMutex );
    2112         150 :     impl_checkDisposed_throw();
    2113             : 
    2114         150 :     if (!m_bControlsSorted)
    2115             :     {
    2116          32 :         Reference< XTabControllerModel >  xModel = getModel();
    2117          32 :         if (!xModel.is())
    2118           0 :             return m_aControls;
    2119             : 
    2120          64 :         Sequence< Reference< XControlModel > > aControlModels = xModel->getControlModels();
    2121          32 :         const Reference< XControlModel > * pModels = aControlModels.getConstArray();
    2122          32 :         sal_Int32 nModels = aControlModels.getLength();
    2123             : 
    2124          64 :         Sequence< Reference< XControl > > aNewControls(nModels);
    2125             : 
    2126          32 :         Reference< XControl > * pControls = aNewControls.getArray();
    2127          64 :         Reference< XControl >  xControl;
    2128             : 
    2129             :         // Umsortieren der Controls entsprechend der TabReihenfolge
    2130          32 :         sal_Int32 j = 0;
    2131          96 :         for (sal_Int32 i = 0; i < nModels; ++i, ++pModels )
    2132             :         {
    2133          64 :             xControl = findControl( m_aControls, *pModels, true, true );
    2134          64 :             if ( xControl.is() )
    2135          53 :                 pControls[j++] = xControl;
    2136             :         }
    2137             : 
    2138             :         // not every model had an associated control
    2139          32 :         if ( j != nModels )
    2140           4 :             aNewControls.realloc( j );
    2141             : 
    2142          32 :         m_aControls = aNewControls;
    2143          64 :         m_bControlsSorted = true;
    2144             :     }
    2145         150 :     return m_aControls;
    2146             : }
    2147             : 
    2148             : 
    2149           0 : void FormController::autoTabOrder() throw( RuntimeException, std::exception )
    2150             : {
    2151           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2152           0 :     impl_checkDisposed_throw();
    2153             : 
    2154             :     DBG_ASSERT(m_xTabController.is(), "FormController::autoTabOrder : invalid aggregate !");
    2155           0 :     if (m_xTabController.is())
    2156           0 :         m_xTabController->autoTabOrder();
    2157           0 : }
    2158             : 
    2159             : 
    2160         135 : void FormController::activateTabOrder() throw( RuntimeException, std::exception )
    2161             : {
    2162         135 :     ::osl::MutexGuard aGuard( m_aMutex );
    2163         135 :     impl_checkDisposed_throw();
    2164             : 
    2165             :     DBG_ASSERT(m_xTabController.is(), "FormController::activateTabOrder : invalid aggregate !");
    2166         135 :     if (m_xTabController.is())
    2167         135 :         m_xTabController->activateTabOrder();
    2168         135 : }
    2169             : 
    2170             : 
    2171           0 : void FormController::setControlLock(const Reference< XControl > & xControl)
    2172             : {
    2173             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2174           0 :     bool bLocked = isLocked();
    2175             : 
    2176             :     // es wird gelockt
    2177             :     // a.) wenn der ganze Datensatz gesperrt ist
    2178             :     // b.) wenn das zugehoerige Feld gespeert ist
    2179           0 :     Reference< XBoundControl >  xBound(xControl, UNO_QUERY);
    2180           0 :     if (xBound.is() && (( (bLocked && bLocked != bool(xBound->getLock())) ||
    2181           0 :                          !bLocked)))    // beim entlocken immer einzelne Felder ueberprüfen
    2182             :     {
    2183             :         // gibt es eine Datenquelle
    2184           0 :         Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
    2185           0 :         if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
    2186             :         {
    2187             :             // wie sieht mit den Properties ReadOnly und Enable aus
    2188           0 :             bool bTouch = true;
    2189           0 :             if (::comphelper::hasProperty(FM_PROP_ENABLED, xSet))
    2190           0 :                 bTouch = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ENABLED));
    2191           0 :             if (::comphelper::hasProperty(FM_PROP_READONLY, xSet))
    2192           0 :                 bTouch = !::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_READONLY));
    2193             : 
    2194           0 :             if (bTouch)
    2195             :             {
    2196           0 :                 Reference< XPropertySet >  xField;
    2197           0 :                 xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
    2198           0 :                 if (xField.is())
    2199             :                 {
    2200           0 :                     if (bLocked)
    2201           0 :                         xBound->setLock(bLocked);
    2202             :                     else
    2203             :                     {
    2204             :                         try
    2205             :                         {
    2206           0 :                             Any aVal = xField->getPropertyValue(FM_PROP_ISREADONLY);
    2207           0 :                             if (aVal.hasValue() && ::comphelper::getBOOL(aVal))
    2208           0 :                                 xBound->setLock(sal_True);
    2209             :                             else
    2210           0 :                                 xBound->setLock(bLocked);
    2211             :                         }
    2212           0 :                         catch( const Exception& )
    2213             :                         {
    2214             :                             DBG_UNHANDLED_EXCEPTION();
    2215             :                         }
    2216             : 
    2217             :                     }
    2218           0 :                 }
    2219             :             }
    2220           0 :         }
    2221           0 :     }
    2222           0 : }
    2223             : 
    2224             : 
    2225           0 : void FormController::setLocks()
    2226             : {
    2227             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2228             :     // alle Controls, die mit einer Datenquelle verbunden sind locken/unlocken
    2229           0 :     const Reference< XControl >* pControls = m_aControls.getConstArray();
    2230           0 :     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
    2231           0 :     while ( pControls != pControlsEnd )
    2232           0 :         setControlLock( *pControls++ );
    2233           0 : }
    2234             : 
    2235             : 
    2236             : namespace
    2237             : {
    2238           0 :     bool lcl_shouldListenForModifications( const Reference< XControl >& _rxControl, const Reference< XPropertyChangeListener >& _rxBoundFieldListener )
    2239             :     {
    2240           0 :         bool bShould = false;
    2241             : 
    2242           0 :         Reference< XBoundComponent > xBound( _rxControl, UNO_QUERY );
    2243           0 :         if ( xBound.is() )
    2244             :         {
    2245           0 :             bShould = true;
    2246             :         }
    2247           0 :         else if ( _rxControl.is() )
    2248             :         {
    2249           0 :             Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
    2250           0 :             if ( xModelProps.is() && ::comphelper::hasProperty( FM_PROP_BOUNDFIELD, xModelProps ) )
    2251             :             {
    2252           0 :                 Reference< XPropertySet > xField;
    2253           0 :                 xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
    2254           0 :                 bShould = xField.is();
    2255             : 
    2256           0 :                 if ( !bShould && _rxBoundFieldListener.is() )
    2257           0 :                     xModelProps->addPropertyChangeListener( FM_PROP_BOUNDFIELD, _rxBoundFieldListener );
    2258           0 :             }
    2259             :         }
    2260             : 
    2261           0 :         return bShould;
    2262             :     }
    2263             : }
    2264             : 
    2265             : 
    2266           0 : void FormController::startControlModifyListening(const Reference< XControl > & xControl)
    2267             : {
    2268             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2269             : 
    2270           0 :     bool bModifyListening = lcl_shouldListenForModifications( xControl, this );
    2271             : 
    2272             :     // artificial while
    2273           0 :     while ( bModifyListening )
    2274             :     {
    2275           0 :         Reference< XModifyBroadcaster >  xMod(xControl, UNO_QUERY);
    2276           0 :         if (xMod.is())
    2277             :         {
    2278           0 :             xMod->addModifyListener(this);
    2279           0 :             break;
    2280             :         }
    2281             : 
    2282             :         // alle die Text um vorzeitig ein modified zu erkennen
    2283           0 :         Reference< XTextComponent >  xText(xControl, UNO_QUERY);
    2284           0 :         if (xText.is())
    2285             :         {
    2286           0 :             xText->addTextListener(this);
    2287           0 :             break;
    2288             :         }
    2289             : 
    2290           0 :         Reference< XCheckBox >  xBox(xControl, UNO_QUERY);
    2291           0 :         if (xBox.is())
    2292             :         {
    2293           0 :             xBox->addItemListener(this);
    2294           0 :             break;
    2295             :         }
    2296             : 
    2297           0 :         Reference< XComboBox >  xCbBox(xControl, UNO_QUERY);
    2298           0 :         if (xCbBox.is())
    2299             :         {
    2300           0 :             xCbBox->addItemListener(this);
    2301           0 :             break;
    2302             :         }
    2303             : 
    2304           0 :         Reference< XListBox >  xListBox(xControl, UNO_QUERY);
    2305           0 :         if (xListBox.is())
    2306             :         {
    2307           0 :             xListBox->addItemListener(this);
    2308           0 :             break;
    2309             :         }
    2310           0 :         break;
    2311           0 :     }
    2312           0 : }
    2313             : 
    2314             : 
    2315           0 : void FormController::stopControlModifyListening(const Reference< XControl > & xControl)
    2316             : {
    2317             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2318             : 
    2319           0 :     bool bModifyListening = lcl_shouldListenForModifications( xControl, NULL );
    2320             : 
    2321             :     // kuenstliches while
    2322           0 :     while (bModifyListening)
    2323             :     {
    2324           0 :         Reference< XModifyBroadcaster >  xMod(xControl, UNO_QUERY);
    2325           0 :         if (xMod.is())
    2326             :         {
    2327           0 :             xMod->removeModifyListener(this);
    2328           0 :             break;
    2329             :         }
    2330             :         // alle die Text um vorzeitig ein modified zu erkennen
    2331           0 :         Reference< XTextComponent >  xText(xControl, UNO_QUERY);
    2332           0 :         if (xText.is())
    2333             :         {
    2334           0 :             xText->removeTextListener(this);
    2335           0 :             break;
    2336             :         }
    2337             : 
    2338           0 :         Reference< XCheckBox >  xBox(xControl, UNO_QUERY);
    2339           0 :         if (xBox.is())
    2340             :         {
    2341           0 :             xBox->removeItemListener(this);
    2342           0 :             break;
    2343             :         }
    2344             : 
    2345           0 :         Reference< XComboBox >  xCbBox(xControl, UNO_QUERY);
    2346           0 :         if (xCbBox.is())
    2347             :         {
    2348           0 :             xCbBox->removeItemListener(this);
    2349           0 :             break;
    2350             :         }
    2351             : 
    2352           0 :         Reference< XListBox >  xListBox(xControl, UNO_QUERY);
    2353           0 :         if (xListBox.is())
    2354             :         {
    2355           0 :             xListBox->removeItemListener(this);
    2356           0 :             break;
    2357             :         }
    2358           0 :         break;
    2359           0 :     }
    2360           0 : }
    2361             : 
    2362             : 
    2363           0 : void FormController::startListening()
    2364             : {
    2365             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2366           0 :     m_bModified  = false;
    2367             : 
    2368             :     // jetzt anmelden bei gebundenen feldern
    2369           0 :     const Reference< XControl >* pControls = m_aControls.getConstArray();
    2370           0 :     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
    2371           0 :     while ( pControls != pControlsEnd )
    2372           0 :         startControlModifyListening( *pControls++ );
    2373           0 : }
    2374             : 
    2375             : 
    2376           0 : void FormController::stopListening()
    2377             : {
    2378             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2379           0 :     m_bModified  = false;
    2380             : 
    2381             :     // jetzt anmelden bei gebundenen feldern
    2382           0 :     const Reference< XControl >* pControls = m_aControls.getConstArray();
    2383           0 :     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
    2384           0 :     while ( pControls != pControlsEnd )
    2385           0 :         stopControlModifyListening( *pControls++ );
    2386           0 : }
    2387             : 
    2388             : 
    2389             : 
    2390         219 : Reference< XControl >  FormController::findControl(Sequence< Reference< XControl > >& _rControls, const Reference< XControlModel > & xCtrlModel ,bool _bRemove,bool _bOverWrite) const
    2391             : {
    2392             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2393             :     DBG_ASSERT( xCtrlModel.is(), "findControl - welches ?!" );
    2394             : 
    2395         219 :     Reference< XControl >* pControls = _rControls.getArray();
    2396         219 :     Reference< XControlModel >  xModel;
    2397         238 :     for ( sal_Int32 i = 0, nCount = _rControls.getLength(); i < nCount; ++i, ++pControls )
    2398             :     {
    2399          92 :         if ( pControls->is() )
    2400             :         {
    2401          91 :             xModel = (*pControls)->getModel();
    2402          91 :             if ( xModel.get() == xCtrlModel.get() )
    2403             :             {
    2404          73 :                 Reference< XControl > xControl( *pControls );
    2405          73 :                 if ( _bRemove )
    2406          53 :                     ::comphelper::removeElementAt( _rControls, i );
    2407          20 :                 else if ( _bOverWrite )
    2408           3 :                     pControls->clear();
    2409          73 :                 return xControl;
    2410             :             }
    2411             :         }
    2412             :     }
    2413         146 :     return Reference< XControl > ();
    2414             : }
    2415             : 
    2416             : 
    2417          56 : void FormController::implControlInserted( const Reference< XControl>& _rxControl, bool _bAddToEventAttacher )
    2418             : {
    2419          56 :     Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
    2420          56 :     if ( xWindow.is() )
    2421             :     {
    2422          56 :         xWindow->addFocusListener( this );
    2423          56 :         xWindow->addMouseListener( this );
    2424             : 
    2425          56 :         if ( _bAddToEventAttacher )
    2426          56 :             addToEventAttacher( _rxControl );
    2427             :     }
    2428             : 
    2429             :     // add a dispatch interceptor to the control (if supported)
    2430         112 :     Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY );
    2431          56 :     if ( xInterception.is() )
    2432          31 :         createInterceptor( xInterception );
    2433             : 
    2434          56 :     if ( _rxControl.is() )
    2435             :     {
    2436          56 :         Reference< XControlModel > xModel( _rxControl->getModel() );
    2437             : 
    2438             :         // we want to know about the reset of the model of our controls
    2439             :         // (for correctly resetting m_bModified)
    2440         112 :         Reference< XReset >  xReset( xModel, UNO_QUERY );
    2441          56 :         if ( xReset.is() )
    2442          56 :             xReset->addResetListener( this );
    2443             : 
    2444             :         // and we want to know about the validity, to visually indicate it
    2445         112 :         Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
    2446          56 :         if ( xValidatable.is() )
    2447             :         {
    2448          25 :             xValidatable->addFormComponentValidityListener( this );
    2449          25 :             m_pControlBorderManager->validityChanged( _rxControl, xValidatable );
    2450          56 :         }
    2451          56 :     }
    2452             : 
    2453          56 : }
    2454             : 
    2455             : 
    2456          56 : void FormController::implControlRemoved( const Reference< XControl>& _rxControl, bool _bRemoveFromEventAttacher )
    2457             : {
    2458          56 :     Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
    2459          56 :     if ( xWindow.is() )
    2460             :     {
    2461          56 :         xWindow->removeFocusListener( this );
    2462          56 :         xWindow->removeMouseListener( this );
    2463             : 
    2464          56 :         if ( _bRemoveFromEventAttacher )
    2465          56 :             removeFromEventAttacher( _rxControl );
    2466             :     }
    2467             : 
    2468         112 :     Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY);
    2469          56 :     if ( xInterception.is() )
    2470          31 :         deleteInterceptor( xInterception );
    2471             : 
    2472          56 :     if ( _rxControl.is() )
    2473             :     {
    2474          56 :         Reference< XControlModel > xModel( _rxControl->getModel() );
    2475             : 
    2476         112 :         Reference< XReset >  xReset( xModel, UNO_QUERY );
    2477          56 :         if ( xReset.is() )
    2478          56 :             xReset->removeResetListener( this );
    2479             : 
    2480         112 :         Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
    2481          56 :         if ( xValidatable.is() )
    2482          81 :             xValidatable->removeFormComponentValidityListener( this );
    2483          56 :     }
    2484          56 : }
    2485             : 
    2486             : 
    2487          96 : void FormController::implSetCurrentControl( const Reference< XControl >& _rxControl )
    2488             : {
    2489          96 :     if ( m_xCurrentControl.get() == _rxControl.get() )
    2490         190 :         return;
    2491             : 
    2492           2 :     Reference< XGridControl > xGridControl( m_xCurrentControl, UNO_QUERY );
    2493           2 :     if ( xGridControl.is() )
    2494           0 :         xGridControl->removeGridControlListener( this );
    2495             : 
    2496           2 :     m_xCurrentControl = _rxControl;
    2497             : 
    2498           2 :     xGridControl.set( m_xCurrentControl, UNO_QUERY );
    2499           2 :     if ( xGridControl.is() )
    2500           0 :         xGridControl->addGridControlListener( this );
    2501             : }
    2502             : 
    2503             : 
    2504          53 : void FormController::insertControl(const Reference< XControl > & xControl)
    2505             : {
    2506             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2507          53 :     m_bControlsSorted = false;
    2508          53 :     m_aControls.realloc(m_aControls.getLength() + 1);
    2509          53 :     m_aControls.getArray()[m_aControls.getLength() - 1] = xControl;
    2510             : 
    2511          53 :     if ( m_pColumnInfoCache.get() )
    2512           0 :         m_pColumnInfoCache->deinitializeControls();
    2513             : 
    2514          53 :     implControlInserted( xControl, m_bAttachEvents );
    2515             : 
    2516          53 :     if (m_bDBConnection && !m_bFiltering)
    2517           0 :         setControlLock(xControl);
    2518             : 
    2519          53 :     if (isListeningForChanges() && m_bAttachEvents)
    2520           0 :         startControlModifyListening( xControl );
    2521          53 : }
    2522             : 
    2523             : 
    2524           1 : void FormController::removeControl(const Reference< XControl > & xControl)
    2525             : {
    2526             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2527           1 :     const Reference< XControl >* pControls = m_aControls.getConstArray();
    2528           1 :     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
    2529           2 :     while ( pControls != pControlsEnd )
    2530             :     {
    2531           1 :         if ( xControl.get() == (*pControls++).get() )
    2532             :         {
    2533           1 :             ::comphelper::removeElementAt( m_aControls, pControls - m_aControls.getConstArray() - 1 );
    2534           1 :             break;
    2535             :         }
    2536             :     }
    2537             : 
    2538           1 :     FilterComponents::iterator componentPos = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
    2539           1 :     if ( componentPos != m_aFilterComponents.end() )
    2540           0 :         m_aFilterComponents.erase( componentPos );
    2541             : 
    2542           1 :     implControlRemoved( xControl, m_bDetachEvents );
    2543             : 
    2544           1 :     if ( isListeningForChanges() && m_bDetachEvents )
    2545           0 :         stopControlModifyListening( xControl );
    2546           1 : }
    2547             : 
    2548             : // XLoadListener
    2549             : 
    2550           0 : void FormController::loaded(const EventObject& rEvent) throw( RuntimeException, std::exception )
    2551             : {
    2552             :     OSL_ENSURE( rEvent.Source == m_xModelAsIndex, "FormController::loaded: where did this come from?" );
    2553             : 
    2554             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2555           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2556           0 :     Reference< XRowSet >  xForm(rEvent.Source, UNO_QUERY);
    2557             :     // do we have a connected data source
    2558           0 :     if (xForm.is() && getConnection(xForm).is())
    2559             :     {
    2560           0 :         Reference< XPropertySet >  xSet(xForm, UNO_QUERY);
    2561           0 :         if (xSet.is())
    2562             :         {
    2563           0 :             Any aVal        = xSet->getPropertyValue(FM_PROP_CYCLE);
    2564           0 :             sal_Int32 aVal2 = 0;
    2565           0 :             ::cppu::enum2int(aVal2,aVal);
    2566           0 :             m_bCycle        = !aVal.hasValue() || aVal2 == TabulatorCycle_RECORDS;
    2567           0 :             m_bCanUpdate    = canUpdate(xSet);
    2568           0 :             m_bCanInsert    = canInsert(xSet);
    2569           0 :             m_bCurrentRecordModified = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED));
    2570           0 :             m_bCurrentRecordNew      = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW));
    2571             : 
    2572           0 :             startFormListening( xSet, false );
    2573             : 
    2574             :             // set the locks for the current controls
    2575           0 :             if (getContainer().is())
    2576             :             {
    2577           0 :                 m_aLoadEvent.Call();
    2578           0 :             }
    2579             :         }
    2580             :         else
    2581             :         {
    2582           0 :             m_bCanInsert = m_bCanUpdate = m_bCycle = false;
    2583           0 :             m_bCurrentRecordModified = false;
    2584           0 :             m_bCurrentRecordNew = false;
    2585           0 :             m_bLocked = false;
    2586             :         }
    2587           0 :         m_bDBConnection = true;
    2588             :     }
    2589             :     else
    2590             :     {
    2591           0 :         m_bDBConnection = false;
    2592           0 :         m_bCanInsert = m_bCanUpdate = m_bCycle = false;
    2593           0 :         m_bCurrentRecordModified = false;
    2594           0 :         m_bCurrentRecordNew = false;
    2595           0 :         m_bLocked = false;
    2596             :     }
    2597             : 
    2598           0 :     Reference< XColumnsSupplier > xFormColumns( xForm, UNO_QUERY );
    2599           0 :     m_pColumnInfoCache.reset( xFormColumns.is() ? new ColumnInfoCache( xFormColumns ) : NULL );
    2600             : 
    2601           0 :     updateAllDispatchers();
    2602           0 : }
    2603             : 
    2604             : 
    2605           0 : void FormController::updateAllDispatchers() const
    2606             : {
    2607             :     ::std::for_each(
    2608             :         m_aFeatureDispatchers.begin(),
    2609             :         m_aFeatureDispatchers.end(),
    2610             :         ::o3tl::compose1(
    2611             :             UpdateAllListeners(),
    2612             :             ::o3tl::select2nd< DispatcherContainer::value_type >()
    2613             :         )
    2614           0 :     );
    2615           0 : }
    2616             : 
    2617             : 
    2618           0 : IMPL_LINK_NOARG(FormController, OnLoad)
    2619             : {
    2620             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2621           0 :     m_bLocked = determineLockState();
    2622             : 
    2623           0 :     setLocks();
    2624             : 
    2625           0 :     if (!m_bLocked)
    2626           0 :         startListening();
    2627             : 
    2628             :     // just one exception toggle the auto values
    2629           0 :     if (m_bCurrentRecordNew)
    2630           0 :         toggleAutoFields(true);
    2631             : 
    2632           0 :     return 1L;
    2633             : }
    2634             : 
    2635             : 
    2636           0 : void FormController::unloaded(const EventObject& /*rEvent*/) throw( RuntimeException, std::exception )
    2637             : {
    2638           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2639           0 :     impl_checkDisposed_throw();
    2640             : 
    2641           0 :     updateAllDispatchers();
    2642           0 : }
    2643             : 
    2644             : 
    2645           0 : void FormController::reloading(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
    2646             : {
    2647           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2648           0 :     impl_checkDisposed_throw();
    2649             : 
    2650             :     // do the same like in unloading
    2651             :     // just one exception toggle the auto values
    2652           0 :     m_aToggleEvent.CancelPendingCall();
    2653           0 :     unload();
    2654           0 : }
    2655             : 
    2656             : 
    2657           0 : void FormController::reloaded(const EventObject& aEvent) throw( RuntimeException, std::exception )
    2658             : {
    2659           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2660           0 :     impl_checkDisposed_throw();
    2661             : 
    2662           0 :     loaded(aEvent);
    2663           0 : }
    2664             : 
    2665             : 
    2666           0 : void FormController::unloading(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
    2667             : {
    2668           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2669           0 :     impl_checkDisposed_throw();
    2670             : 
    2671           0 :     unload();
    2672           0 : }
    2673             : 
    2674             : 
    2675           0 : void FormController::unload() throw( RuntimeException )
    2676             : {
    2677           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2678           0 :     impl_checkDisposed_throw();
    2679             : 
    2680           0 :     m_aLoadEvent.CancelPendingCall();
    2681             : 
    2682             :     // be sure not to have autofields
    2683           0 :     if (m_bCurrentRecordNew)
    2684           0 :         toggleAutoFields(false);
    2685             : 
    2686             :     // remove bound field listing again
    2687           0 :     removeBoundFieldListener();
    2688             : 
    2689           0 :     if (m_bDBConnection && isListeningForChanges())
    2690           0 :         stopListening();
    2691             : 
    2692           0 :     Reference< XPropertySet >  xSet( m_xModelAsIndex, UNO_QUERY );
    2693           0 :     if ( m_bDBConnection && xSet.is() )
    2694           0 :         stopFormListening( xSet, false );
    2695             : 
    2696           0 :     m_bDBConnection = false;
    2697           0 :     m_bCanInsert = m_bCanUpdate = m_bCycle = false;
    2698           0 :     m_bCurrentRecordModified = m_bCurrentRecordNew = m_bLocked = false;
    2699             : 
    2700           0 :     m_pColumnInfoCache.reset();
    2701           0 : }
    2702             : 
    2703             : 
    2704          95 : void FormController::removeBoundFieldListener()
    2705             : {
    2706          95 :     const Reference< XControl >* pControls = m_aControls.getConstArray();
    2707          95 :     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
    2708         245 :     while ( pControls != pControlsEnd )
    2709             :     {
    2710          55 :         Reference< XPropertySet > xProp( *pControls++, UNO_QUERY );
    2711          55 :         if ( xProp.is() )
    2712           0 :             xProp->removePropertyChangeListener( FM_PROP_BOUNDFIELD, this );
    2713          55 :     }
    2714          95 : }
    2715             : 
    2716             : 
    2717           0 : void FormController::startFormListening( const Reference< XPropertySet >& _rxForm, bool _bPropertiesOnly )
    2718             : {
    2719             :     try
    2720             :     {
    2721           0 :         if ( m_bCanInsert || m_bCanUpdate )   // form can be modified
    2722             :         {
    2723           0 :             _rxForm->addPropertyChangeListener( FM_PROP_ISNEW, this );
    2724           0 :             _rxForm->addPropertyChangeListener( FM_PROP_ISMODIFIED, this );
    2725             : 
    2726           0 :             if ( !_bPropertiesOnly )
    2727             :             {
    2728             :                 // set the Listener for UI interaction
    2729           0 :                 Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
    2730           0 :                 if ( xApprove.is() )
    2731           0 :                     xApprove->addRowSetApproveListener( this );
    2732             : 
    2733             :                 // listener for row set changes
    2734           0 :                 Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
    2735           0 :                 if ( xRowSet.is() )
    2736           0 :                     xRowSet->addRowSetListener( this );
    2737             :             }
    2738             :         }
    2739             : 
    2740           0 :         Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
    2741           0 :         if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER ) )
    2742           0 :             _rxForm->addPropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER, this );
    2743             :     }
    2744           0 :     catch( const Exception& )
    2745             :     {
    2746             :         DBG_UNHANDLED_EXCEPTION();
    2747             :     }
    2748           0 : }
    2749             : 
    2750             : 
    2751           0 : void FormController::stopFormListening( const Reference< XPropertySet >& _rxForm, bool _bPropertiesOnly )
    2752             : {
    2753             :     try
    2754             :     {
    2755           0 :         if ( m_bCanInsert || m_bCanUpdate )
    2756             :         {
    2757           0 :             _rxForm->removePropertyChangeListener( FM_PROP_ISNEW, this );
    2758           0 :             _rxForm->removePropertyChangeListener( FM_PROP_ISMODIFIED, this );
    2759             : 
    2760           0 :             if ( !_bPropertiesOnly )
    2761             :             {
    2762           0 :                 Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
    2763           0 :                 if (xApprove.is())
    2764           0 :                     xApprove->removeRowSetApproveListener(this);
    2765             : 
    2766           0 :                 Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
    2767           0 :                 if ( xRowSet.is() )
    2768           0 :                     xRowSet->removeRowSetListener( this );
    2769             :             }
    2770             :         }
    2771             : 
    2772           0 :         Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
    2773           0 :         if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER ) )
    2774           0 :             _rxForm->removePropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER, this );
    2775             :     }
    2776           0 :     catch( const Exception& )
    2777             :     {
    2778             :         DBG_UNHANDLED_EXCEPTION();
    2779             :     }
    2780           0 : }
    2781             : 
    2782             : // com::sun::star::sdbc::XRowSetListener
    2783             : 
    2784           0 : void FormController::cursorMoved(const EventObject& /*event*/) throw( RuntimeException, std::exception )
    2785             : {
    2786           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2787           0 :     impl_checkDisposed_throw();
    2788             : 
    2789             :     // toggle the locking ?
    2790           0 :     if (m_bLocked != determineLockState())
    2791             :     {
    2792           0 :         m_bLocked = !m_bLocked;
    2793           0 :         setLocks();
    2794           0 :         if (isListeningForChanges())
    2795           0 :             startListening();
    2796             :         else
    2797           0 :             stopListening();
    2798             :     }
    2799             : 
    2800             :     // neither the current control nor the current record are modified anymore
    2801           0 :     m_bCurrentRecordModified = m_bModified = false;
    2802           0 : }
    2803             : 
    2804             : 
    2805           0 : void FormController::rowChanged(const EventObject& /*event*/) throw( RuntimeException, std::exception )
    2806             : {
    2807             :     // not interested in ...
    2808           0 : }
    2809             : 
    2810           0 : void FormController::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException, std::exception )
    2811             : {
    2812             :     // not interested in ...
    2813           0 : }
    2814             : 
    2815             : 
    2816             : // XContainerListener
    2817             : 
    2818          53 : void SAL_CALL FormController::elementInserted(const ContainerEvent& evt) throw( RuntimeException, std::exception )
    2819             : {
    2820          53 :     ::osl::MutexGuard aGuard( m_aMutex );
    2821          53 :     impl_checkDisposed_throw();
    2822             : 
    2823         106 :     Reference< XControl > xControl( evt.Element, UNO_QUERY );
    2824          53 :     if ( !xControl.is() )
    2825          53 :         return;
    2826             : 
    2827         106 :     Reference< XFormComponent >  xModel(xControl->getModel(), UNO_QUERY);
    2828          53 :     if (xModel.is() && m_xModelAsIndex == xModel->getParent())
    2829             :     {
    2830          53 :         insertControl(xControl);
    2831             : 
    2832          53 :         if ( m_aTabActivationIdle.IsActive() )
    2833          21 :             m_aTabActivationIdle.Stop();
    2834             : 
    2835          53 :         m_aTabActivationIdle.Start();
    2836             :     }
    2837             :     // are we in filtermode and a XModeSelector has inserted an element
    2838           0 :     else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
    2839             :     {
    2840           0 :         xModel = Reference< XFormComponent > (evt.Source, UNO_QUERY);
    2841           0 :         if (xModel.is() && m_xModelAsIndex == xModel->getParent())
    2842             :         {
    2843           0 :             Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
    2844           0 :             if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
    2845             :             {
    2846             :                 // does the model use a bound field ?
    2847           0 :                 Reference< XPropertySet >  xField;
    2848           0 :                 xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
    2849             : 
    2850           0 :                 Reference< XTextComponent >  xText(xControl, UNO_QUERY);
    2851             :                 // may we filter the field?
    2852           0 :                 if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE, xField) &&
    2853           0 :                     ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE)))
    2854             :                 {
    2855           0 :                     m_aFilterComponents.push_back( xText );
    2856           0 :                     xText->addTextListener( this );
    2857           0 :                 }
    2858           0 :             }
    2859             :         }
    2860          53 :     }
    2861             : }
    2862             : 
    2863             : 
    2864           0 : void SAL_CALL FormController::elementReplaced(const ContainerEvent& evt) throw( RuntimeException, std::exception )
    2865             : {
    2866             :     // simulate an elementRemoved
    2867           0 :     ContainerEvent aRemoveEvent( evt );
    2868           0 :     aRemoveEvent.Element = evt.ReplacedElement;
    2869           0 :     aRemoveEvent.ReplacedElement = Any();
    2870           0 :     elementRemoved( aRemoveEvent );
    2871             : 
    2872             :     // simulate an elementInserted
    2873           0 :     ContainerEvent aInsertEvent( evt );
    2874           0 :     aInsertEvent.ReplacedElement = Any();
    2875           0 :     elementInserted( aInsertEvent );
    2876           0 : }
    2877             : 
    2878             : 
    2879           1 : void SAL_CALL FormController::elementRemoved(const ContainerEvent& evt) throw( RuntimeException, std::exception )
    2880             : {
    2881           1 :     ::osl::MutexGuard aGuard( m_aMutex );
    2882           1 :     impl_checkDisposed_throw();
    2883             : 
    2884           2 :     Reference< XControl >  xControl;
    2885           1 :     evt.Element >>= xControl;
    2886           1 :     if (!xControl.is())
    2887           1 :         return;
    2888             : 
    2889           2 :     Reference< XFormComponent >  xModel(xControl->getModel(), UNO_QUERY);
    2890           1 :     if (xModel.is() && m_xModelAsIndex == xModel->getParent())
    2891             :     {
    2892           1 :         removeControl(xControl);
    2893             :         // TabOrder nicht neu berechnen, da das intern schon funktionieren muss!
    2894             :     }
    2895             :     // are we in filtermode and a XModeSelector has inserted an element
    2896           0 :     else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
    2897             :     {
    2898             :         FilterComponents::iterator componentPos = ::std::find(
    2899           0 :             m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
    2900           0 :         if ( componentPos != m_aFilterComponents.end() )
    2901           0 :             m_aFilterComponents.erase( componentPos );
    2902           1 :     }
    2903             : }
    2904             : 
    2905             : 
    2906           1 : Reference< XControl >  FormController::isInList(const Reference< XWindowPeer > & xPeer) const
    2907             : {
    2908             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    2909           1 :     const Reference< XControl >* pControls = m_aControls.getConstArray();
    2910             : 
    2911           1 :     sal_uInt32 nCtrls = m_aControls.getLength();
    2912           1 :     for ( sal_uInt32 n = 0; n < nCtrls && xPeer.is(); ++n, ++pControls )
    2913             :     {
    2914           0 :         if ( pControls->is() )
    2915             :         {
    2916           0 :             Reference< XVclWindowPeer >  xCtrlPeer( (*pControls)->getPeer(), UNO_QUERY);
    2917           0 :             if ( ( xCtrlPeer.get() == xPeer.get() ) || xCtrlPeer->isChild( xPeer ) )
    2918           0 :                 return *pControls;
    2919             :         }
    2920             :     }
    2921           1 :     return Reference< XControl > ();
    2922             : }
    2923             : 
    2924             : 
    2925           0 : void FormController::activateFirst() throw( RuntimeException, std::exception )
    2926             : {
    2927           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2928           0 :     impl_checkDisposed_throw();
    2929             : 
    2930             :     DBG_ASSERT(m_xTabController.is(), "FormController::activateFirst : invalid aggregate !");
    2931           0 :     if (m_xTabController.is())
    2932           0 :         m_xTabController->activateFirst();
    2933           0 : }
    2934             : 
    2935             : 
    2936           0 : void FormController::activateLast() throw( RuntimeException, std::exception )
    2937             : {
    2938           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2939           0 :     impl_checkDisposed_throw();
    2940             : 
    2941             :     DBG_ASSERT(m_xTabController.is(), "FormController::activateLast : invalid aggregate !");
    2942           0 :     if (m_xTabController.is())
    2943           0 :         m_xTabController->activateLast();
    2944           0 : }
    2945             : 
    2946             : // XFormController
    2947             : 
    2948           0 : Reference< XFormOperations > SAL_CALL FormController::getFormOperations() throw (RuntimeException, std::exception)
    2949             : {
    2950           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2951           0 :     impl_checkDisposed_throw();
    2952             : 
    2953           0 :     return m_xFormOperations;
    2954             : }
    2955             : 
    2956             : 
    2957           4 : Reference< XControl> SAL_CALL FormController::getCurrentControl() throw( RuntimeException, std::exception )
    2958             : {
    2959           4 :     ::osl::MutexGuard aGuard( m_aMutex );
    2960           4 :     impl_checkDisposed_throw();
    2961           4 :     return m_xCurrentControl;
    2962             : }
    2963             : 
    2964             : 
    2965          95 : void SAL_CALL FormController::addActivateListener(const Reference< XFormControllerListener > & l) throw( RuntimeException, std::exception )
    2966             : {
    2967          95 :     ::osl::MutexGuard aGuard( m_aMutex );
    2968          95 :     impl_checkDisposed_throw();
    2969          95 :     m_aActivateListeners.addInterface(l);
    2970          95 : }
    2971             : 
    2972           0 : void SAL_CALL FormController::removeActivateListener(const Reference< XFormControllerListener > & l) throw( RuntimeException, std::exception )
    2973             : {
    2974           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2975           0 :     impl_checkDisposed_throw();
    2976           0 :     m_aActivateListeners.removeInterface(l);
    2977           0 : }
    2978             : 
    2979             : 
    2980           0 : void SAL_CALL FormController::addChildController( const Reference< XFormController >& _ChildController ) throw( RuntimeException, IllegalArgumentException, std::exception )
    2981             : {
    2982           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    2983           0 :     impl_checkDisposed_throw();
    2984             : 
    2985           0 :     if ( !_ChildController.is() )
    2986           0 :         throw IllegalArgumentException( OUString(), *this, 1 );
    2987             :         // TODO: (localized) error message
    2988             : 
    2989             :     // the parent of our (to-be-)child must be our own model
    2990           0 :     Reference< XFormComponent > xFormOfChild( _ChildController->getModel(), UNO_QUERY );
    2991           0 :     if ( !xFormOfChild.is() )
    2992           0 :         throw IllegalArgumentException( OUString(), *this, 1 );
    2993             :         // TODO: (localized) error message
    2994             : 
    2995           0 :     if ( xFormOfChild->getParent() != m_xModelAsIndex )
    2996           0 :         throw IllegalArgumentException( OUString(), *this, 1 );
    2997             :         // TODO: (localized) error message
    2998             : 
    2999           0 :     m_aChildren.push_back( _ChildController );
    3000           0 :     _ChildController->setParent( *this );
    3001             : 
    3002             :     // search the position of the model within the form
    3003           0 :     sal_uInt32 nPos = m_xModelAsIndex->getCount();
    3004           0 :     Reference< XFormComponent > xTemp;
    3005           0 :     for( ; nPos; )
    3006             :     {
    3007           0 :         m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
    3008           0 :         if ( xFormOfChild == xTemp )
    3009             :         {
    3010           0 :             m_xModelAsManager->attach( nPos, Reference<XInterface>( _ChildController, UNO_QUERY ), makeAny( _ChildController) );
    3011           0 :             break;
    3012             :         }
    3013           0 :     }
    3014           0 : }
    3015             : 
    3016             : 
    3017           0 : Reference< XFormControllerContext > SAL_CALL FormController::getContext() throw (RuntimeException, std::exception)
    3018             : {
    3019           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3020           0 :     impl_checkDisposed_throw();
    3021           0 :     return m_xFormControllerContext;
    3022             : }
    3023             : 
    3024             : 
    3025          95 : void SAL_CALL FormController::setContext( const Reference< XFormControllerContext >& _context ) throw (RuntimeException, std::exception)
    3026             : {
    3027          95 :     ::osl::MutexGuard aGuard( m_aMutex );
    3028          95 :     impl_checkDisposed_throw();
    3029          95 :     m_xFormControllerContext = _context;
    3030          95 : }
    3031             : 
    3032             : 
    3033           0 : Reference< XInteractionHandler > SAL_CALL FormController::getInteractionHandler() throw (RuntimeException, std::exception)
    3034             : {
    3035           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3036           0 :     impl_checkDisposed_throw();
    3037           0 :     return m_xInteractionHandler;
    3038             : }
    3039             : 
    3040             : 
    3041           0 : void SAL_CALL FormController::setInteractionHandler( const Reference< XInteractionHandler >& _interactionHandler ) throw (RuntimeException, std::exception)
    3042             : {
    3043           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3044           0 :     impl_checkDisposed_throw();
    3045           0 :     m_xInteractionHandler = _interactionHandler;
    3046           0 : }
    3047             : 
    3048             : 
    3049           0 : void FormController::setFilter(::std::vector<FmFieldInfo>& rFieldInfos)
    3050             : {
    3051             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    3052             :     // create the composer
    3053           0 :     Reference< XRowSet > xForm(m_xModelAsIndex, UNO_QUERY);
    3054           0 :     Reference< XConnection > xConnection(getConnection(xForm));
    3055           0 :     if (xForm.is())
    3056             :     {
    3057             :         try
    3058             :         {
    3059           0 :             Reference< XMultiServiceFactory > xFactory( xConnection, UNO_QUERY_THROW );
    3060             :             m_xComposer.set(
    3061           0 :                 xFactory->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"),
    3062           0 :                 UNO_QUERY_THROW );
    3063             : 
    3064           0 :             Reference< XPropertySet > xSet( xForm, UNO_QUERY );
    3065           0 :             OUString sStatement  = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_ACTIVECOMMAND ) );
    3066           0 :             OUString sFilter     = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_FILTER ) );
    3067           0 :             m_xComposer->setElementaryQuery( sStatement );
    3068           0 :             m_xComposer->setFilter( sFilter );
    3069             :         }
    3070           0 :         catch( const Exception& )
    3071             :         {
    3072             :             DBG_UNHANDLED_EXCEPTION();
    3073             :         }
    3074             :     }
    3075             : 
    3076           0 :     if (m_xComposer.is())
    3077             :     {
    3078           0 :         Sequence< Sequence < PropertyValue > > aFilterRows = m_xComposer->getStructuredFilter();
    3079             : 
    3080             :         // ok, we receive the list of filters as sequence of fieldnames, value
    3081             :         // now we have to transform the fieldname into UI names, that could be a label of the field or
    3082             :         // a aliasname or the fieldname itself
    3083             : 
    3084             :         // first adjust the field names if necessary
    3085             :         Reference< XNameAccess > xQueryColumns =
    3086           0 :             Reference< XColumnsSupplier >( m_xComposer, UNO_QUERY_THROW )->getColumns();
    3087             : 
    3088           0 :         for (::std::vector<FmFieldInfo>::iterator iter = rFieldInfos.begin();
    3089           0 :             iter != rFieldInfos.end(); ++iter)
    3090             :         {
    3091           0 :             if ( xQueryColumns->hasByName((*iter).aFieldName) )
    3092             :             {
    3093           0 :                 if ( (xQueryColumns->getByName((*iter).aFieldName) >>= (*iter).xField) && (*iter).xField.is() )
    3094           0 :                     (*iter).xField->getPropertyValue(FM_PROP_REALNAME) >>= (*iter).aFieldName;
    3095             :             }
    3096             :         }
    3097             : 
    3098           0 :         Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
    3099             :         // now transfer the filters into Value/TextComponent pairs
    3100           0 :         ::comphelper::UStringMixEqual aCompare(xMetaData->storesMixedCaseQuotedIdentifiers());
    3101             : 
    3102             :         // need to parse criteria localized
    3103           0 :         Reference< XNumberFormatsSupplier> xFormatSupplier( getNumberFormats(xConnection, true));
    3104           0 :         Reference< XNumberFormatter> xFormatter = NumberFormatter::create(m_xComponentContext);
    3105           0 :         xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
    3106           0 :         Locale aAppLocale = Application::GetSettings().GetUILanguageTag().getLocale();
    3107           0 :         const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetUILocaleDataWrapper() );
    3108             :         /* FIXME: casting this to sal_Char is plain wrong and of course only
    3109             :          * works for ASCII separators, but
    3110             :          * pParseNode->parseNodeToPredicateStr() expects a sal_Char. Fix it
    3111             :          * there. */
    3112           0 :         sal_Char cDecimalSeparator = (sal_Char)rLocaleWrapper.getNumDecimalSep()[0];
    3113             :         SAL_WARN_IF( (sal_Unicode)cDecimalSeparator != rLocaleWrapper.getNumDecimalSep()[0],
    3114             :                 "svx.form", "FormController::setFilter: wrong cast of decimal separator to sal_Char!");
    3115             : 
    3116             :         // retrieving the filter
    3117           0 :         const Sequence < PropertyValue >* pRow = aFilterRows.getConstArray();
    3118           0 :         for (sal_Int32 i = 0, nLen = aFilterRows.getLength(); i < nLen; ++i)
    3119             :         {
    3120           0 :             FmFilterRow aRow;
    3121             : 
    3122             :             // search a field for the given name
    3123           0 :             const PropertyValue* pRefValues = pRow[i].getConstArray();
    3124           0 :             for (sal_Int32 j = 0, nLen1 = pRow[i].getLength(); j < nLen1; j++)
    3125             :             {
    3126             :                 // look for the text component
    3127           0 :                 Reference< XPropertySet > xField;
    3128             :                 try
    3129             :                 {
    3130           0 :                     Reference< XPropertySet > xSet;
    3131           0 :                     OUString aRealName;
    3132             : 
    3133             :                     // first look with the given name
    3134           0 :                     if (xQueryColumns->hasByName(pRefValues[j].Name))
    3135             :                     {
    3136           0 :                         xQueryColumns->getByName(pRefValues[j].Name) >>= xSet;
    3137             : 
    3138             :                         // get the RealName
    3139           0 :                         xSet->getPropertyValue("RealName") >>= aRealName;
    3140             : 
    3141             :                         // compare the condition field name and the RealName
    3142           0 :                         if (aCompare(aRealName, pRefValues[j].Name))
    3143           0 :                             xField = xSet;
    3144             :                     }
    3145           0 :                     if (!xField.is())
    3146             :                     {
    3147             :                         // no we have to check every column to find the realname
    3148           0 :                         Reference< XIndexAccess > xColumnsByIndex(xQueryColumns, UNO_QUERY);
    3149           0 :                         for (sal_Int32 n = 0, nCount = xColumnsByIndex->getCount(); n < nCount; n++)
    3150             :                         {
    3151           0 :                             xColumnsByIndex->getByIndex(n) >>= xSet;
    3152           0 :                             xSet->getPropertyValue("RealName") >>= aRealName;
    3153           0 :                             if (aCompare(aRealName, pRefValues[j].Name))
    3154             :                             {
    3155             :                                 // get the column by its alias
    3156           0 :                                 xField = xSet;
    3157           0 :                                 break;
    3158             :                             }
    3159           0 :                         }
    3160             :                     }
    3161           0 :                     if (!xField.is())
    3162           0 :                         continue;
    3163             :                 }
    3164           0 :                 catch (const Exception&)
    3165             :                 {
    3166           0 :                     continue;
    3167             :                 }
    3168             : 
    3169             :                 // find the text component
    3170           0 :                 for (::std::vector<FmFieldInfo>::iterator iter = rFieldInfos.begin();
    3171           0 :                     iter != rFieldInfos.end(); ++iter)
    3172             :                 {
    3173             :                     // we found the field so insert a new entry to the filter row
    3174           0 :                     if ((*iter).xField == xField)
    3175             :                     {
    3176             :                         // do we already have the control ?
    3177           0 :                         if (aRow.find((*iter).xText) != aRow.end())
    3178             :                         {
    3179           0 :                             OUString aCompText = aRow[(*iter).xText];
    3180           0 :                             aCompText += " ";
    3181           0 :                             OString aVal = m_pParser->getContext().getIntlKeywordAscii(IParseContext::KEY_AND);
    3182           0 :                             aCompText += OUString(aVal.getStr(),aVal.getLength(),RTL_TEXTENCODING_ASCII_US);
    3183           0 :                             aCompText += " ";
    3184           0 :                             aCompText += ::comphelper::getString(pRefValues[j].Value);
    3185           0 :                             aRow[(*iter).xText] = aCompText;
    3186             :                         }
    3187             :                         else
    3188             :                         {
    3189           0 :                             OUString sPredicate,sErrorMsg;
    3190           0 :                             pRefValues[j].Value >>= sPredicate;
    3191           0 :                             std::shared_ptr< OSQLParseNode > pParseNode = predicateTree(sErrorMsg, sPredicate, xFormatter, xField);
    3192           0 :                             if ( pParseNode != nullptr )
    3193             :                             {
    3194           0 :                                 OUString sCriteria;
    3195             :                                 pParseNode->parseNodeToPredicateStr( sCriteria
    3196             :                                                                     ,xConnection
    3197             :                                                                     ,xFormatter
    3198             :                                                                     ,xField
    3199             :                                                                     ,OUString()
    3200             :                                                                     ,aAppLocale
    3201             :                                                                     ,cDecimalSeparator
    3202           0 :                                                                     ,getParseContext());
    3203           0 :                                 aRow[(*iter).xText] = sCriteria;
    3204           0 :                             }
    3205             :                         }
    3206             :                     }
    3207             :                 }
    3208           0 :             }
    3209             : 
    3210           0 :             if (aRow.empty())
    3211           0 :                 continue;
    3212             : 
    3213           0 :             impl_addFilterRow( aRow );
    3214           0 :         }
    3215             :     }
    3216             : 
    3217             :     // now set the filter controls
    3218           0 :     for (   ::std::vector<FmFieldInfo>::iterator field = rFieldInfos.begin();
    3219           0 :             field != rFieldInfos.end();
    3220             :             ++field
    3221             :         )
    3222             :     {
    3223           0 :         m_aFilterComponents.push_back( field->xText );
    3224           0 :     }
    3225           0 : }
    3226             : 
    3227             : 
    3228           0 : void FormController::startFiltering()
    3229             : {
    3230             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    3231             : 
    3232           0 :     Reference< XConnection >  xConnection( getConnection( Reference< XRowSet >( m_xModelAsIndex, UNO_QUERY ) ) );
    3233           0 :     if ( !xConnection.is() )
    3234             :         // nothing to do - can't filter a form which is not connected
    3235           0 :         return;
    3236             : 
    3237             :     // stop listening for controls
    3238           0 :     if (isListeningForChanges())
    3239           0 :         stopListening();
    3240             : 
    3241           0 :     m_bFiltering = true;
    3242             : 
    3243             :     // as we don't want new controls to be attached to the scripting environment
    3244             :     // we change attach flags
    3245           0 :     m_bAttachEvents = false;
    3246             : 
    3247             :     // Austauschen der Kontrols fuer das aktuelle Formular
    3248           0 :     Sequence< Reference< XControl > > aControlsCopy( m_aControls );
    3249           0 :     const Reference< XControl >* pControls = aControlsCopy.getConstArray();
    3250           0 :     sal_Int32 nControlCount = aControlsCopy.getLength();
    3251             : 
    3252             :     // the control we have to activate after replacement
    3253           0 :     Reference< XDatabaseMetaData >  xMetaData(xConnection->getMetaData());
    3254           0 :     Reference< XNumberFormatsSupplier >  xFormatSupplier = getNumberFormats(xConnection, true);
    3255           0 :     Reference< XNumberFormatter >  xFormatter = NumberFormatter::create(m_xComponentContext);
    3256           0 :     xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
    3257             : 
    3258             :     // structure for storing the field info
    3259           0 :     ::std::vector<FmFieldInfo> aFieldInfos;
    3260             : 
    3261           0 :     for (sal_Int32 i = nControlCount; i > 0;)
    3262             :     {
    3263           0 :         Reference< XControl > xControl = pControls[--i];
    3264           0 :         if (xControl.is())
    3265             :         {
    3266             :             // no events for the control anymore
    3267           0 :             removeFromEventAttacher(xControl);
    3268             : 
    3269             :             // do we have a mode selector
    3270           0 :             Reference< XModeSelector >  xSelector(xControl, UNO_QUERY);
    3271           0 :             if (xSelector.is())
    3272             :             {
    3273           0 :                 xSelector->setMode( OUString( "FilterMode"  ) );
    3274             : 
    3275             :                 // listening for new controls of the selector
    3276           0 :                 Reference< XContainer >  xContainer(xSelector, UNO_QUERY);
    3277           0 :                 if (xContainer.is())
    3278           0 :                     xContainer->addContainerListener(this);
    3279             : 
    3280           0 :                 Reference< XEnumerationAccess >  xElementAccess(xSelector, UNO_QUERY);
    3281           0 :                 if (xElementAccess.is())
    3282             :                 {
    3283           0 :                     Reference< XEnumeration >  xEnumeration(xElementAccess->createEnumeration());
    3284           0 :                     Reference< XControl >  xSubControl;
    3285           0 :                     while (xEnumeration->hasMoreElements())
    3286             :                     {
    3287           0 :                         xEnumeration->nextElement() >>= xSubControl;
    3288           0 :                         if (xSubControl.is())
    3289             :                         {
    3290           0 :                             Reference< XPropertySet >  xSet(xSubControl->getModel(), UNO_QUERY);
    3291           0 :                             if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
    3292             :                             {
    3293             :                                 // does the model use a bound field ?
    3294           0 :                                 Reference< XPropertySet >  xField;
    3295           0 :                                 xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
    3296             : 
    3297           0 :                                 Reference< XTextComponent >  xText(xSubControl, UNO_QUERY);
    3298             :                                 // may we filter the field?
    3299           0 :                                 if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE, xField) &&
    3300           0 :                                     ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE)))
    3301             :                                 {
    3302           0 :                                     aFieldInfos.push_back(FmFieldInfo(xField, xText));
    3303           0 :                                     xText->addTextListener(this);
    3304           0 :                                 }
    3305           0 :                             }
    3306             :                         }
    3307           0 :                     }
    3308             :                 }
    3309           0 :                 continue;
    3310             :             }
    3311             : 
    3312           0 :             Reference< XPropertySet >  xModel( xControl->getModel(), UNO_QUERY );
    3313           0 :             if (xModel.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xModel))
    3314             :             {
    3315             :                 // does the model use a bound field ?
    3316           0 :                 Any aVal = xModel->getPropertyValue(FM_PROP_BOUNDFIELD);
    3317           0 :                 Reference< XPropertySet >  xField;
    3318           0 :                 aVal >>= xField;
    3319             : 
    3320             :                 // may we filter the field?
    3321             : 
    3322           0 :                 if  (   xField.is()
    3323           0 :                     &&  ::comphelper::hasProperty( FM_PROP_SEARCHABLE, xField )
    3324           0 :                     && ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE ) )
    3325             :                     )
    3326             :                 {
    3327             :                     // create a filter control
    3328             :                     Reference< XControl > xFilterControl = form::control::FilterControl::createWithFormat(
    3329             :                         m_xComponentContext,
    3330             :                         VCLUnoHelper::GetInterface( getDialogParentWindow() ),
    3331             :                         xFormatter,
    3332           0 :                         xModel);
    3333             : 
    3334           0 :                     if ( replaceControl( xControl, xFilterControl ) )
    3335             :                     {
    3336           0 :                         Reference< XTextComponent > xFilterText( xFilterControl, UNO_QUERY );
    3337           0 :                         aFieldInfos.push_back( FmFieldInfo( xField, xFilterText ) );
    3338           0 :                         xFilterText->addTextListener(this);
    3339           0 :                     }
    3340           0 :                 }
    3341             :             }
    3342             :             else
    3343             :             {
    3344             :                 // abmelden vom EventManager
    3345           0 :             }
    3346             :         }
    3347           0 :     }
    3348             : 
    3349             :     // we have all filter controls now, so the next step is to read the filters from the form
    3350             :     // resolve all aliases and set the current filter to the according structure
    3351           0 :     setFilter(aFieldInfos);
    3352             : 
    3353           0 :     Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
    3354           0 :     if ( xSet.is() )
    3355           0 :         stopFormListening( xSet, true );
    3356             : 
    3357           0 :     impl_setTextOnAllFilter_throw();
    3358             : 
    3359             :     // lock all controls which are not used for filtering
    3360           0 :     m_bLocked = determineLockState();
    3361           0 :     setLocks();
    3362           0 :     m_bAttachEvents = true;
    3363             : }
    3364             : 
    3365             : 
    3366          95 : void FormController::stopFiltering()
    3367             : {
    3368             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    3369          95 :     if ( !m_bFiltering ) // #104693# OJ
    3370             :     {   // nothing to do
    3371         190 :         return;
    3372             :     }
    3373             : 
    3374           0 :     m_bFiltering = false;
    3375           0 :     m_bDetachEvents = false;
    3376             : 
    3377           0 :     ::comphelper::disposeComponent(m_xComposer);
    3378             : 
    3379             :     // Austauschen der Kontrols fuer das aktuelle Formular
    3380           0 :     Sequence< Reference< XControl > > aControlsCopy( m_aControls );
    3381           0 :     const Reference< XControl > * pControls = aControlsCopy.getConstArray();
    3382           0 :     sal_Int32 nControlCount = aControlsCopy.getLength();
    3383             : 
    3384             :     // clear the filter control map
    3385           0 :     ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
    3386           0 :     m_aFilterComponents.clear();
    3387             : 
    3388           0 :     for ( sal_Int32 i = nControlCount; i > 0; )
    3389             :     {
    3390           0 :         Reference< XControl > xControl = pControls[--i];
    3391           0 :         if (xControl.is())
    3392             :         {
    3393             :             // now enable eventhandling again
    3394           0 :             addToEventAttacher(xControl);
    3395             : 
    3396           0 :             Reference< XModeSelector >  xSelector(xControl, UNO_QUERY);
    3397           0 :             if (xSelector.is())
    3398             :             {
    3399           0 :                 xSelector->setMode( OUString( "DataMode"  ) );
    3400             : 
    3401             :                 // listening for new controls of the selector
    3402           0 :                 Reference< XContainer >  xContainer(xSelector, UNO_QUERY);
    3403           0 :                 if (xContainer.is())
    3404           0 :                     xContainer->removeContainerListener(this);
    3405           0 :                 continue;
    3406             :             }
    3407             : 
    3408           0 :             Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
    3409           0 :             if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
    3410             :             {
    3411             :                 // does the model use a bound field ?
    3412           0 :                 Reference< XPropertySet >  xField;
    3413           0 :                 xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
    3414             : 
    3415             :                 // may we filter the field?
    3416           0 :                 if  (   xField.is()
    3417           0 :                     &&  ::comphelper::hasProperty( FM_PROP_SEARCHABLE, xField )
    3418           0 :                     &&  ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE ) )
    3419             :                     )
    3420             :                 {
    3421           0 :                     OUString sServiceName;
    3422           0 :                     OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName );
    3423           0 :                     Reference< XControl > xNewControl( m_xComponentContext->getServiceManager()->createInstanceWithContext( sServiceName, m_xComponentContext ), UNO_QUERY );
    3424           0 :                     replaceControl( xControl, xNewControl );
    3425           0 :                 }
    3426           0 :             }
    3427             :         }
    3428           0 :     }
    3429             : 
    3430           0 :     Reference< XPropertySet >  xSet( m_xModelAsIndex, UNO_QUERY );
    3431           0 :     if ( xSet.is() )
    3432           0 :         startFormListening( xSet, true );
    3433             : 
    3434           0 :     m_bDetachEvents = true;
    3435             : 
    3436           0 :     m_aFilterRows.clear();
    3437           0 :     m_nCurrentFilterPosition = -1;
    3438             : 
    3439             :     // release the locks if possible
    3440             :     // lock all controls which are not used for filtering
    3441           0 :     m_bLocked = determineLockState();
    3442           0 :     setLocks();
    3443             : 
    3444             :     // restart listening for control modifications
    3445           0 :     if (isListeningForChanges())
    3446           0 :         startListening();
    3447             : }
    3448             : 
    3449             : // XModeSelector
    3450             : 
    3451           0 : void FormController::setMode(const OUString& Mode) throw( NoSupportException, RuntimeException, std::exception )
    3452             : {
    3453           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3454           0 :     impl_checkDisposed_throw();
    3455             : 
    3456           0 :     if (!supportsMode(Mode))
    3457           0 :         throw NoSupportException();
    3458             : 
    3459           0 :     if (Mode == m_aMode)
    3460           0 :         return;
    3461             : 
    3462           0 :     m_aMode = Mode;
    3463             : 
    3464           0 :     if ( Mode == "FilterMode" )
    3465           0 :         startFiltering();
    3466             :     else
    3467           0 :         stopFiltering();
    3468             : 
    3469           0 :     for (FmFormControllers::const_iterator i = m_aChildren.begin();
    3470           0 :         i != m_aChildren.end(); ++i)
    3471             :     {
    3472           0 :         Reference< XModeSelector > xMode(*i, UNO_QUERY);
    3473           0 :         if ( xMode.is() )
    3474           0 :             xMode->setMode(Mode);
    3475           0 :     }
    3476             : }
    3477             : 
    3478             : 
    3479           0 : OUString SAL_CALL FormController::getMode() throw( RuntimeException, std::exception )
    3480             : {
    3481           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3482           0 :     impl_checkDisposed_throw();
    3483             : 
    3484           0 :     return m_aMode;
    3485             : }
    3486             : 
    3487             : 
    3488           0 : Sequence< OUString > SAL_CALL FormController::getSupportedModes() throw( RuntimeException, std::exception )
    3489             : {
    3490           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3491           0 :     impl_checkDisposed_throw();
    3492             : 
    3493           0 :     static Sequence< OUString > aModes;
    3494           0 :     if (!aModes.getLength())
    3495             :     {
    3496           0 :         aModes.realloc(2);
    3497           0 :         aModes[0] = "DataMode";
    3498           0 :         aModes[1] = "FilterMode";
    3499             :     }
    3500           0 :     return aModes;
    3501             : }
    3502             : 
    3503             : 
    3504           0 : sal_Bool SAL_CALL FormController::supportsMode(const OUString& Mode) throw( RuntimeException, std::exception )
    3505             : {
    3506           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3507           0 :     impl_checkDisposed_throw();
    3508             : 
    3509           0 :     Sequence< OUString > aModes(getSupportedModes());
    3510           0 :     const OUString* pModes = aModes.getConstArray();
    3511           0 :     for (sal_Int32 i = aModes.getLength(); i > 0; )
    3512             :     {
    3513           0 :         if (pModes[--i] == Mode)
    3514           0 :             return sal_True;
    3515             :     }
    3516           0 :     return sal_False;
    3517             : }
    3518             : 
    3519             : 
    3520           0 : vcl::Window* FormController::getDialogParentWindow()
    3521             : {
    3522             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    3523           0 :     vcl::Window* pParentWindow = NULL;
    3524             :     try
    3525             :     {
    3526           0 :         Reference< XControl > xContainerControl( getContainer(), UNO_QUERY_THROW );
    3527           0 :         Reference< XWindowPeer > xContainerPeer( xContainerControl->getPeer(), UNO_QUERY_THROW );
    3528           0 :         pParentWindow = VCLUnoHelper::GetWindow( xContainerPeer );
    3529             :     }
    3530           0 :     catch( const Exception& )
    3531             :     {
    3532             :         DBG_UNHANDLED_EXCEPTION();
    3533             :     }
    3534           0 :     return pParentWindow;
    3535             : }
    3536             : 
    3537           0 : bool FormController::checkFormComponentValidity( OUString& /* [out] */ _rFirstInvalidityExplanation, Reference< XControlModel >& /* [out] */ _rxFirstInvalidModel )
    3538             : {
    3539             :     try
    3540             :     {
    3541           0 :         Reference< XEnumerationAccess > xControlEnumAcc( getModel(), UNO_QUERY );
    3542           0 :         Reference< XEnumeration > xControlEnumeration;
    3543           0 :         if ( xControlEnumAcc.is() )
    3544           0 :             xControlEnumeration = xControlEnumAcc->createEnumeration();
    3545             :         OSL_ENSURE( xControlEnumeration.is(), "FormController::checkFormComponentValidity: cannot enumerate the controls!" );
    3546           0 :         if ( !xControlEnumeration.is() )
    3547             :             // assume all valid
    3548           0 :             return true;
    3549             : 
    3550           0 :         Reference< XValidatableFormComponent > xValidatable;
    3551           0 :         while ( xControlEnumeration->hasMoreElements() )
    3552             :         {
    3553           0 :             if ( !( xControlEnumeration->nextElement() >>= xValidatable ) )
    3554             :                 // control does not support validation
    3555           0 :                 continue;
    3556             : 
    3557           0 :             if ( xValidatable->isValid() )
    3558           0 :                 continue;
    3559             : 
    3560           0 :             Reference< XValidator > xValidator( xValidatable->getValidator() );
    3561             :             OSL_ENSURE( xValidator.is(), "FormController::checkFormComponentValidity: invalid, but no validator?" );
    3562           0 :             if ( !xValidator.is() )
    3563             :                 // this violates the interface definition of css.form.validation.XValidatableFormComponent ...
    3564           0 :                 continue;
    3565             : 
    3566           0 :             _rFirstInvalidityExplanation = xValidator->explainInvalid( xValidatable->getCurrentValue() );
    3567           0 :             _rxFirstInvalidModel.set(xValidatable, css::uno::UNO_QUERY);
    3568           0 :             return false;
    3569           0 :         }
    3570             :     }
    3571           0 :     catch( const Exception& )
    3572             :     {
    3573             :         DBG_UNHANDLED_EXCEPTION();
    3574             :     }
    3575           0 :     return true;
    3576             : }
    3577             : 
    3578             : 
    3579           0 : Reference< XControl > FormController::locateControl( const Reference< XControlModel >& _rxModel )
    3580             : {
    3581             :     try
    3582             :     {
    3583           0 :         Sequence< Reference< XControl > > aControls( getControls() );
    3584           0 :         const Reference< XControl >* pControls = aControls.getConstArray();
    3585           0 :         const Reference< XControl >* pControlsEnd = aControls.getConstArray() + aControls.getLength();
    3586             : 
    3587           0 :         for ( ; pControls != pControlsEnd; ++pControls )
    3588             :         {
    3589             :             OSL_ENSURE( pControls->is(), "FormController::locateControl: NULL-control?" );
    3590           0 :             if ( pControls->is() )
    3591             :             {
    3592           0 :                 if ( ( *pControls)->getModel() == _rxModel )
    3593           0 :                     return *pControls;
    3594             :             }
    3595             :         }
    3596           0 :         OSL_FAIL( "FormController::locateControl: did not find a control for this model!" );
    3597             :     }
    3598           0 :     catch( const Exception& )
    3599             :     {
    3600             :         DBG_UNHANDLED_EXCEPTION();
    3601             :     }
    3602           0 :     return NULL;
    3603             : }
    3604             : 
    3605             : 
    3606             : namespace
    3607             : {
    3608           0 :     void displayErrorSetFocus( const OUString& _rMessage, const Reference< XControl >& _rxFocusControl, vcl::Window* _pDialogParent )
    3609             :     {
    3610           0 :         SQLContext aError;
    3611           0 :         aError.Message = SVX_RESSTR(RID_STR_WRITEERROR);
    3612           0 :         aError.Details = _rMessage;
    3613           0 :         displayException( aError, _pDialogParent );
    3614             : 
    3615           0 :         if ( _rxFocusControl.is() )
    3616             :         {
    3617           0 :             Reference< XWindow > xControlWindow( _rxFocusControl, UNO_QUERY );
    3618             :             OSL_ENSURE( xControlWindow.is(), "displayErrorSetFocus: invalid control!" );
    3619           0 :             if ( xControlWindow.is() )
    3620           0 :                 xControlWindow->setFocus();
    3621           0 :         }
    3622           0 :     }
    3623             : 
    3624           0 :     bool lcl_shouldValidateRequiredFields_nothrow( const Reference< XInterface >& _rxForm )
    3625             :     {
    3626             :         try
    3627             :         {
    3628             :             static const char s_sFormsCheckRequiredFields[] = "FormsCheckRequiredFields";
    3629             : 
    3630             :             // first, check whether the form has a property telling us the answer
    3631             :             // this allows people to use the XPropertyContainer interface of a form to control
    3632             :             // the behaviour on a per-form basis.
    3633           0 :             Reference< XPropertySet > xFormProps( _rxForm, UNO_QUERY_THROW );
    3634           0 :             Reference< XPropertySetInfo > xPSI( xFormProps->getPropertySetInfo() );
    3635           0 :             if ( xPSI->hasPropertyByName( s_sFormsCheckRequiredFields ) )
    3636             :             {
    3637           0 :                 bool bShouldValidate = true;
    3638           0 :                 OSL_VERIFY( xFormProps->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate );
    3639           0 :                 return bShouldValidate;
    3640             :             }
    3641             : 
    3642             :             // next, check the data source which created the connection
    3643           0 :             Reference< XChild > xConnectionAsChild( xFormProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION ), UNO_QUERY_THROW );
    3644           0 :             Reference< XPropertySet > xDataSource( xConnectionAsChild->getParent(), UNO_QUERY );
    3645           0 :             if ( !xDataSource.is() )
    3646             :                 // seldom (but possible): this is not a connection created by a data source
    3647           0 :                 return true;
    3648             : 
    3649             :             Reference< XPropertySet > xDataSourceSettings(
    3650           0 :                 xDataSource->getPropertyValue("Settings"),
    3651           0 :                 UNO_QUERY_THROW );
    3652             : 
    3653           0 :             bool bShouldValidate = true;
    3654           0 :             OSL_VERIFY( xDataSourceSettings->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate );
    3655           0 :             return bShouldValidate;
    3656             :         }
    3657           0 :         catch( const Exception& )
    3658             :         {
    3659             :             DBG_UNHANDLED_EXCEPTION();
    3660             :         }
    3661             : 
    3662           0 :         return true;
    3663             :     }
    3664             : }
    3665             : 
    3666             : // XRowSetApproveListener
    3667             : 
    3668           0 : sal_Bool SAL_CALL FormController::approveRowChange(const RowChangeEvent& _rEvent) throw( RuntimeException, std::exception )
    3669             : {
    3670           0 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    3671           0 :     impl_checkDisposed_throw();
    3672             : 
    3673           0 :     ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
    3674           0 :     bool bValid = true;
    3675           0 :     if (aIter.hasMoreElements())
    3676             :     {
    3677           0 :         RowChangeEvent aEvt( _rEvent );
    3678           0 :         aEvt.Source = *this;
    3679           0 :         bValid = static_cast<XRowSetApproveListener*>(aIter.next())->approveRowChange(aEvt);
    3680             :     }
    3681             : 
    3682           0 :     if ( !bValid )
    3683           0 :         return bValid;
    3684             : 
    3685           0 :     if  (   ( _rEvent.Action != RowChangeAction::INSERT )
    3686           0 :         &&  ( _rEvent.Action != RowChangeAction::UPDATE )
    3687             :         )
    3688           0 :         return bValid;
    3689             : 
    3690             :     // if some of the control models are bound to validators, check them
    3691           0 :     OUString sInvalidityExplanation;
    3692           0 :     Reference< XControlModel > xInvalidModel;
    3693           0 :     if ( !checkFormComponentValidity( sInvalidityExplanation, xInvalidModel ) )
    3694             :     {
    3695           0 :         Reference< XControl > xControl( locateControl( xInvalidModel ) );
    3696           0 :         aGuard.clear();
    3697           0 :         displayErrorSetFocus( sInvalidityExplanation, xControl, getDialogParentWindow() );
    3698           0 :         return false;
    3699             :     }
    3700             : 
    3701             :     // check values on NULL and required flag
    3702           0 :     if ( !lcl_shouldValidateRequiredFields_nothrow( _rEvent.Source ) )
    3703           0 :         return sal_True;
    3704             : 
    3705             :     OSL_ENSURE( m_pColumnInfoCache.get(), "FormController::approveRowChange: no column infos!" );
    3706           0 :     if ( !m_pColumnInfoCache.get() )
    3707           0 :         return sal_True;
    3708             : 
    3709             :     try
    3710             :     {
    3711           0 :         if ( !m_pColumnInfoCache->controlsInitialized() )
    3712           0 :             m_pColumnInfoCache->initializeControls( getControls() );
    3713             : 
    3714           0 :         size_t colCount = m_pColumnInfoCache->getColumnCount();
    3715           0 :         for ( size_t col = 0; col < colCount; ++col )
    3716             :         {
    3717           0 :             const ColumnInfo& rColInfo = m_pColumnInfoCache->getColumnInfo( col );
    3718           0 :             if ( rColInfo.nNullable != ColumnValue::NO_NULLS )
    3719           0 :                 continue;
    3720             : 
    3721           0 :             if ( rColInfo.bAutoIncrement )
    3722           0 :                 continue;
    3723             : 
    3724           0 :             if ( rColInfo.bReadOnly )
    3725           0 :                 continue;
    3726             : 
    3727           0 :             if ( !rColInfo.xFirstControlWithInputRequired.is() && !rColInfo.xFirstGridWithInputRequiredColumn.is() )
    3728           0 :                 continue;
    3729             : 
    3730             :             // TODO: in case of binary fields, this "getString" below is extremely expensive
    3731           0 :             if ( !rColInfo.xColumn->getString().isEmpty() || !rColInfo.xColumn->wasNull() )
    3732           0 :                 continue;
    3733             : 
    3734           0 :             OUString sMessage( SVX_RESSTR( RID_ERR_FIELDREQUIRED ) );
    3735           0 :             sMessage = sMessage.replaceFirst( "#", rColInfo.sName );
    3736             : 
    3737             :             // the control to focus
    3738           0 :             Reference< XControl > xControl( rColInfo.xFirstControlWithInputRequired );
    3739           0 :             if ( !xControl.is() )
    3740           0 :                 xControl.set( rColInfo.xFirstGridWithInputRequiredColumn, UNO_QUERY );
    3741             : 
    3742           0 :             aGuard.clear();
    3743           0 :             displayErrorSetFocus( sMessage, rColInfo.xFirstControlWithInputRequired, getDialogParentWindow() );
    3744           0 :             return sal_False;
    3745           0 :         }
    3746             :     }
    3747           0 :     catch( const Exception& )
    3748             :     {
    3749             :         DBG_UNHANDLED_EXCEPTION();
    3750             :     }
    3751             : 
    3752           0 :     return true;
    3753             : }
    3754             : 
    3755             : 
    3756           0 : sal_Bool SAL_CALL FormController::approveCursorMove(const EventObject& event) throw( RuntimeException, std::exception )
    3757             : {
    3758           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3759           0 :     impl_checkDisposed_throw();
    3760             : 
    3761           0 :     ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
    3762           0 :     if (aIter.hasMoreElements())
    3763             :     {
    3764           0 :         EventObject aEvt(event);
    3765           0 :         aEvt.Source = *this;
    3766           0 :         return static_cast<XRowSetApproveListener*>(aIter.next())->approveCursorMove(aEvt);
    3767             :     }
    3768             : 
    3769           0 :     return sal_True;
    3770             : }
    3771             : 
    3772             : 
    3773           0 : sal_Bool SAL_CALL FormController::approveRowSetChange(const EventObject& event) throw( RuntimeException, std::exception )
    3774             : {
    3775           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3776           0 :     impl_checkDisposed_throw();
    3777             : 
    3778           0 :     ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
    3779           0 :     if (aIter.hasMoreElements())
    3780             :     {
    3781           0 :         EventObject aEvt(event);
    3782           0 :         aEvt.Source = *this;
    3783           0 :         return static_cast<XRowSetApproveListener*>(aIter.next())->approveRowSetChange(aEvt);
    3784             :     }
    3785             : 
    3786           0 :     return sal_True;
    3787             : }
    3788             : 
    3789             : // XRowSetApproveBroadcaster
    3790             : 
    3791           0 : void SAL_CALL FormController::addRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener) throw( RuntimeException, std::exception )
    3792             : {
    3793           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3794           0 :     impl_checkDisposed_throw();
    3795             : 
    3796           0 :     m_aRowSetApproveListeners.addInterface(_rxListener);
    3797           0 : }
    3798             : 
    3799             : 
    3800           0 : void SAL_CALL FormController::removeRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener) throw( RuntimeException, std::exception )
    3801             : {
    3802           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3803           0 :     impl_checkDisposed_throw();
    3804             : 
    3805           0 :     m_aRowSetApproveListeners.removeInterface(_rxListener);
    3806           0 : }
    3807             : 
    3808             : // XErrorListener
    3809             : 
    3810           0 : void SAL_CALL FormController::errorOccured(const SQLErrorEvent& aEvent) throw( RuntimeException, std::exception )
    3811             : {
    3812           0 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    3813           0 :     impl_checkDisposed_throw();
    3814             : 
    3815           0 :     ::cppu::OInterfaceIteratorHelper aIter(m_aErrorListeners);
    3816           0 :     if (aIter.hasMoreElements())
    3817             :     {
    3818           0 :         SQLErrorEvent aEvt(aEvent);
    3819           0 :         aEvt.Source = *this;
    3820           0 :         static_cast<XSQLErrorListener*>(aIter.next())->errorOccured(aEvt);
    3821             :     }
    3822             :     else
    3823             :     {
    3824           0 :         aGuard.clear();
    3825           0 :         displayException( aEvent );
    3826           0 :     }
    3827           0 : }
    3828             : 
    3829             : // XErrorBroadcaster
    3830             : 
    3831           1 : void SAL_CALL FormController::addSQLErrorListener(const Reference< XSQLErrorListener > & aListener) throw( RuntimeException, std::exception )
    3832             : {
    3833           1 :     ::osl::MutexGuard aGuard( m_aMutex );
    3834           1 :     impl_checkDisposed_throw();
    3835             : 
    3836           1 :     m_aErrorListeners.addInterface(aListener);
    3837           1 : }
    3838             : 
    3839             : 
    3840           0 : void SAL_CALL FormController::removeSQLErrorListener(const Reference< XSQLErrorListener > & aListener) throw( RuntimeException, std::exception )
    3841             : {
    3842           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3843           0 :     impl_checkDisposed_throw();
    3844             : 
    3845           0 :     m_aErrorListeners.removeInterface(aListener);
    3846           0 : }
    3847             : 
    3848             : // XDatabaseParameterBroadcaster2
    3849             : 
    3850           0 : void SAL_CALL FormController::addDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException, std::exception )
    3851             : {
    3852           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3853           0 :     impl_checkDisposed_throw();
    3854             : 
    3855           0 :     m_aParameterListeners.addInterface(aListener);
    3856           0 : }
    3857             : 
    3858             : 
    3859           0 : void SAL_CALL FormController::removeDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException, std::exception )
    3860             : {
    3861           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3862           0 :     impl_checkDisposed_throw();
    3863             : 
    3864           0 :     m_aParameterListeners.removeInterface(aListener);
    3865           0 : }
    3866             : 
    3867             : // XDatabaseParameterBroadcaster
    3868             : 
    3869           0 : void SAL_CALL FormController::addParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException, std::exception )
    3870             : {
    3871           0 :     FormController::addDatabaseParameterListener( aListener );
    3872           0 : }
    3873             : 
    3874             : 
    3875           0 : void SAL_CALL FormController::removeParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException, std::exception )
    3876             : {
    3877           0 :     FormController::removeDatabaseParameterListener( aListener );
    3878           0 : }
    3879             : 
    3880             : // XDatabaseParameterListener
    3881             : 
    3882           0 : sal_Bool SAL_CALL FormController::approveParameter(const DatabaseParameterEvent& aEvent) throw( RuntimeException, std::exception )
    3883             : {
    3884           0 :     SolarMutexGuard aSolarGuard;
    3885           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3886           0 :     impl_checkDisposed_throw();
    3887             : 
    3888           0 :     ::cppu::OInterfaceIteratorHelper aIter(m_aParameterListeners);
    3889           0 :     if (aIter.hasMoreElements())
    3890             :     {
    3891           0 :         DatabaseParameterEvent aEvt(aEvent);
    3892           0 :         aEvt.Source = *this;
    3893           0 :         return static_cast<XDatabaseParameterListener*>(aIter.next())->approveParameter(aEvt);
    3894             :     }
    3895             :     else
    3896             :     {
    3897             :         // default handling: instantiate an interaction handler and let it handle the parameter request
    3898             :         try
    3899             :         {
    3900           0 :             if ( !ensureInteractionHandler() )
    3901           0 :                 return sal_False;
    3902             : 
    3903             :             // two continuations allowed: OK and Cancel
    3904           0 :             OParameterContinuation* pParamValues = new OParameterContinuation;
    3905           0 :             OInteractionAbort* pAbort = new OInteractionAbort;
    3906             :             // the request
    3907           0 :             ParametersRequest aRequest;
    3908           0 :             aRequest.Parameters = aEvent.Parameters;
    3909           0 :             aRequest.Connection = getConnection(Reference< XRowSet >(aEvent.Source, UNO_QUERY));
    3910           0 :             OInteractionRequest* pParamRequest = new OInteractionRequest(makeAny(aRequest));
    3911           0 :             Reference< XInteractionRequest > xParamRequest(pParamRequest);
    3912             :             // some knittings
    3913           0 :             pParamRequest->addContinuation(pParamValues);
    3914           0 :             pParamRequest->addContinuation(pAbort);
    3915             : 
    3916             :             // handle the request
    3917           0 :             m_xInteractionHandler->handle(xParamRequest);
    3918             : 
    3919           0 :             if (!pParamValues->wasSelected())
    3920             :                 // canceled
    3921           0 :                 return sal_False;
    3922             : 
    3923             :             // transfer the values into the parameter supplier
    3924           0 :             Sequence< PropertyValue > aFinalValues = pParamValues->getValues();
    3925           0 :             if (aFinalValues.getLength() != aRequest.Parameters->getCount())
    3926             :             {
    3927             :                 OSL_FAIL("FormController::approveParameter: the InteractionHandler returned nonsense!");
    3928           0 :                 return sal_False;
    3929             :             }
    3930           0 :             const PropertyValue* pFinalValues = aFinalValues.getConstArray();
    3931           0 :             for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
    3932             :             {
    3933             :                 Reference< XPropertySet > xParam(
    3934           0 :                     aRequest.Parameters->getByIndex(i), css::uno::UNO_QUERY);
    3935           0 :                 if (xParam.is())
    3936             :                 {
    3937             : #ifdef DBG_UTIL
    3938             :                     OUString sName;
    3939             :                     xParam->getPropertyValue(FM_PROP_NAME) >>= sName;
    3940             :                     DBG_ASSERT(sName.equals(pFinalValues->Name), "FormController::approveParameter: suspicious value names!");
    3941             : #endif
    3942           0 :                     try { xParam->setPropertyValue(FM_PROP_VALUE, pFinalValues->Value); }
    3943           0 :                     catch(Exception&)
    3944             :                     {
    3945             :                         OSL_FAIL("FormController::approveParameter: setting one of the properties failed!");
    3946             :                     }
    3947             :                 }
    3948           0 :             }
    3949             :         }
    3950           0 :         catch(Exception&)
    3951             :         {
    3952             :             DBG_UNHANDLED_EXCEPTION();
    3953             :         }
    3954             :     }
    3955           0 :     return sal_True;
    3956             : }
    3957             : 
    3958             : // XConfirmDeleteBroadcaster
    3959             : 
    3960           0 : void SAL_CALL FormController::addConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener) throw( RuntimeException, std::exception )
    3961             : {
    3962           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3963           0 :     impl_checkDisposed_throw();
    3964             : 
    3965           0 :     m_aDeleteListeners.addInterface(aListener);
    3966           0 : }
    3967             : 
    3968             : 
    3969           0 : void SAL_CALL FormController::removeConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener) throw( RuntimeException, std::exception )
    3970             : {
    3971           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3972           0 :     impl_checkDisposed_throw();
    3973             : 
    3974           0 :     m_aDeleteListeners.removeInterface(aListener);
    3975           0 : }
    3976             : 
    3977             : // XConfirmDeleteListener
    3978             : 
    3979           0 : sal_Bool SAL_CALL FormController::confirmDelete(const RowChangeEvent& aEvent) throw( RuntimeException, std::exception )
    3980             : {
    3981           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    3982           0 :     impl_checkDisposed_throw();
    3983             : 
    3984           0 :     ::cppu::OInterfaceIteratorHelper aIter(m_aDeleteListeners);
    3985           0 :     if (aIter.hasMoreElements())
    3986             :     {
    3987           0 :         RowChangeEvent aEvt(aEvent);
    3988           0 :         aEvt.Source = *this;
    3989           0 :         return static_cast<XConfirmDeleteListener*>(aIter.next())->confirmDelete(aEvt);
    3990             :     }
    3991             :     // default handling: instantiate an interaction handler and let it handle the request
    3992             : 
    3993           0 :     OUString sTitle;
    3994           0 :     sal_Int32 nLength = aEvent.Rows;
    3995           0 :     if ( nLength > 1 )
    3996             :     {
    3997           0 :         sTitle = SVX_RESSTR( RID_STR_DELETECONFIRM_RECORDS );
    3998           0 :         sTitle = sTitle.replaceFirst( "#", OUString::number(nLength) );
    3999             :     }
    4000             :     else
    4001           0 :         sTitle = SVX_RESSTR( RID_STR_DELETECONFIRM_RECORD );
    4002             : 
    4003             :     try
    4004             :     {
    4005           0 :         if ( !ensureInteractionHandler() )
    4006           0 :             return sal_False;
    4007             : 
    4008             :         // two continuations allowed: Yes and No
    4009           0 :         OInteractionApprove* pApprove = new OInteractionApprove;
    4010           0 :         OInteractionDisapprove* pDisapprove = new OInteractionDisapprove;
    4011             : 
    4012             :         // the request
    4013           0 :         SQLWarning aWarning;
    4014           0 :         aWarning.Message = sTitle;
    4015           0 :         SQLWarning aDetails;
    4016           0 :         aDetails.Message = SVX_RESSTR(RID_STR_DELETECONFIRM);
    4017           0 :         aWarning.NextException <<= aDetails;
    4018             : 
    4019           0 :         OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aWarning ) );
    4020           0 :         Reference< XInteractionRequest > xRequest( pRequest );
    4021             : 
    4022             :         // some knittings
    4023           0 :         pRequest->addContinuation( pApprove );
    4024           0 :         pRequest->addContinuation( pDisapprove );
    4025             : 
    4026             :         // handle the request
    4027           0 :         m_xInteractionHandler->handle( xRequest );
    4028             : 
    4029           0 :         if ( pApprove->wasSelected() )
    4030           0 :             return sal_True;
    4031             :     }
    4032           0 :     catch( const Exception& )
    4033             :     {
    4034             :         DBG_UNHANDLED_EXCEPTION();
    4035             :     }
    4036             : 
    4037           0 :     return sal_False;
    4038             : }
    4039             : 
    4040             : 
    4041           0 : void SAL_CALL FormController::invalidateFeatures( const Sequence< ::sal_Int16 >& _Features ) throw (RuntimeException, std::exception)
    4042             : {
    4043           0 :     ::osl::MutexGuard aGuard( m_aMutex );
    4044             :     // for now, just copy the ids of the features, because ....
    4045             :     ::std::copy( _Features.begin(), _Features.end(),
    4046             :         ::std::insert_iterator< ::std::set< sal_Int16 > >( m_aInvalidFeatures, m_aInvalidFeatures.begin() )
    4047           0 :     );
    4048             : 
    4049             :     // ... we will do the real invalidation asynchronously
    4050           0 :     if ( !m_aFeatureInvalidationTimer.IsActive() )
    4051           0 :         m_aFeatureInvalidationTimer.Start();
    4052           0 : }
    4053             : 
    4054             : 
    4055           0 : void SAL_CALL FormController::invalidateAllFeatures(  ) throw (RuntimeException, std::exception)
    4056             : {
    4057           0 :     ::osl::ClearableMutexGuard aGuard( m_aMutex );
    4058             : 
    4059           0 :     Sequence< sal_Int16 > aInterceptedFeatures( m_aFeatureDispatchers.size() );
    4060             :     ::std::transform(
    4061             :         m_aFeatureDispatchers.begin(),
    4062             :         m_aFeatureDispatchers.end(),
    4063             :         aInterceptedFeatures.getArray(),
    4064             :         ::o3tl::select1st< DispatcherContainer::value_type >()
    4065           0 :     );
    4066             : 
    4067           0 :     aGuard.clear();
    4068           0 :     if ( aInterceptedFeatures.getLength() )
    4069           0 :         invalidateFeatures( aInterceptedFeatures );
    4070           0 : }
    4071             : 
    4072             : 
    4073             : Reference< XDispatch >
    4074           0 : FormController::interceptedQueryDispatch( const URL& aURL,
    4075             :                                             const OUString& /*aTargetFrameName*/, sal_Int32 /*nSearchFlags*/)
    4076             :                                             throw( RuntimeException )
    4077             : {
    4078             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    4079           0 :     Reference< XDispatch >  xReturn;
    4080             :     // dispatches handled by ourself
    4081           0 :     if  (   ( aURL.Complete == FMURL_CONFIRM_DELETION )
    4082           0 :         ||  (   ( aURL.Complete == "private:/InteractionHandler" )
    4083           0 :             &&  ensureInteractionHandler()
    4084             :             )
    4085             :         )
    4086           0 :         xReturn = static_cast< XDispatch* >( this );
    4087             : 
    4088             :     // dispatches of FormSlot-URLs we have to translate
    4089           0 :     if ( !xReturn.is() && m_xFormOperations.is() )
    4090             :     {
    4091             :         // find the slot id which corresponds to the URL
    4092           0 :         sal_Int32 nFeatureSlotId = svx::FeatureSlotTranslation::getControllerFeatureSlotIdForURL( aURL.Main );
    4093           0 :         sal_Int16 nFormFeature = ( nFeatureSlotId != -1 ) ? svx::FeatureSlotTranslation::getFormFeatureForSlotId( nFeatureSlotId ) : -1;
    4094           0 :         if ( nFormFeature > 0 )
    4095             :         {
    4096             :             // get the dispatcher for this feature, create if necessary
    4097           0 :             DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( nFormFeature );
    4098           0 :             if ( aDispatcherPos == m_aFeatureDispatchers.end() )
    4099             :             {
    4100             :                 aDispatcherPos = m_aFeatureDispatchers.insert(
    4101           0 :                     DispatcherContainer::value_type( nFormFeature, new svx::OSingleFeatureDispatcher( aURL, nFormFeature, m_xFormOperations, m_aMutex ) )
    4102           0 :                 ).first;
    4103             :             }
    4104             : 
    4105             :             OSL_ENSURE( aDispatcherPos->second.is(), "FormController::interceptedQueryDispatch: should have a dispatcher by now!" );
    4106           0 :             return aDispatcherPos->second;
    4107             :         }
    4108             :     }
    4109             : 
    4110             :     // no more to offer
    4111           0 :     return xReturn;
    4112             : }
    4113             : 
    4114             : 
    4115           0 : void SAL_CALL FormController::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArgs ) throw (RuntimeException, std::exception)
    4116             : {
    4117           0 :     if ( _rArgs.getLength() != 1 )
    4118             :     {
    4119             :         OSL_FAIL( "FormController::dispatch: no arguments -> no dispatch!" );
    4120           0 :         return;
    4121             :     }
    4122             : 
    4123           0 :     if ( _rURL.Complete == "private:/InteractionHandler" )
    4124             :     {
    4125           0 :         Reference< XInteractionRequest > xRequest;
    4126           0 :         OSL_VERIFY( _rArgs[0].Value >>= xRequest );
    4127           0 :         if ( xRequest.is() )
    4128           0 :             handle( xRequest );
    4129           0 :         return;
    4130             :     }
    4131             : 
    4132           0 :     if  ( _rURL.Complete == FMURL_CONFIRM_DELETION )
    4133             :     {
    4134             :         OSL_FAIL( "FormController::dispatch: How do you expect me to return something via this call?" );
    4135             :             // confirmDelete has a return value - dispatch hasn't
    4136           0 :         return;
    4137             :     }
    4138             : 
    4139             :     OSL_FAIL( "FormController::dispatch: unknown URL!" );
    4140             : }
    4141             : 
    4142             : 
    4143           0 : void SAL_CALL FormController::addStatusListener( const Reference< XStatusListener >& _rxListener, const URL& _rURL ) throw (RuntimeException, std::exception)
    4144             : {
    4145           0 :     if (_rURL.Complete == FMURL_CONFIRM_DELETION)
    4146             :     {
    4147           0 :         if (_rxListener.is())
    4148             :         {   // send an initial statusChanged event
    4149           0 :             FeatureStateEvent aEvent;
    4150           0 :             aEvent.FeatureURL = _rURL;
    4151           0 :             aEvent.IsEnabled = sal_True;
    4152           0 :             _rxListener->statusChanged(aEvent);
    4153             :             // and don't add the listener at all (the status will never change)
    4154             :         }
    4155             :     }
    4156             :     else
    4157             :         OSL_FAIL("FormController::addStatusListener: invalid (unsupported) URL!");
    4158           0 : }
    4159             : 
    4160             : 
    4161           0 : Reference< XInterface > SAL_CALL FormController::getParent() throw( RuntimeException, std::exception )
    4162             : {
    4163           0 :     return m_xParent;
    4164             : }
    4165             : 
    4166             : 
    4167         190 : void SAL_CALL FormController::setParent( const Reference< XInterface >& Parent) throw( NoSupportException, RuntimeException, std::exception )
    4168             : {
    4169         190 :     m_xParent = Parent;
    4170         190 : }
    4171             : 
    4172             : 
    4173           0 : void SAL_CALL FormController::removeStatusListener( const Reference< XStatusListener >& /*_rxListener*/, const URL& _rURL ) throw (RuntimeException, std::exception)
    4174             : {
    4175             :     (void)_rURL;
    4176             :     OSL_ENSURE(_rURL.Complete == FMURL_CONFIRM_DELETION, "FormController::removeStatusListener: invalid (unsupported) URL!");
    4177             :     // we never really added the listener, so we don't need to remove it
    4178           0 : }
    4179             : 
    4180             : 
    4181          31 : Reference< XDispatchProviderInterceptor >  FormController::createInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
    4182             : {
    4183             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    4184             : #ifdef DBG_UTIL
    4185             :     // check if we already have a interceptor for the given object
    4186             :     for (   Interceptors::const_iterator aIter = m_aControlDispatchInterceptors.begin();
    4187             :             aIter != m_aControlDispatchInterceptors.end();
    4188             :             ++aIter
    4189             :         )
    4190             :     {
    4191             :         if ((*aIter)->getIntercepted() == _xInterception)
    4192             :             OSL_FAIL("FormController::createInterceptor : we already do intercept this objects dispatches !");
    4193             :     }
    4194             : #endif
    4195             : 
    4196          31 :     DispatchInterceptionMultiplexer* pInterceptor = new DispatchInterceptionMultiplexer( _xInterception, this );
    4197          31 :     pInterceptor->acquire();
    4198          31 :     m_aControlDispatchInterceptors.insert( m_aControlDispatchInterceptors.end(), pInterceptor );
    4199             : 
    4200          31 :     return pInterceptor;
    4201             : }
    4202             : 
    4203             : 
    4204           0 : bool FormController::ensureInteractionHandler()
    4205             : {
    4206           0 :     if ( m_xInteractionHandler.is() )
    4207           0 :         return true;
    4208           0 :     if ( m_bAttemptedHandlerCreation )
    4209           0 :         return false;
    4210           0 :     m_bAttemptedHandlerCreation = true;
    4211             : 
    4212           0 :     m_xInteractionHandler = InteractionHandler::createWithParent(m_xComponentContext, 0);
    4213           0 :     return m_xInteractionHandler.is();
    4214             : }
    4215             : 
    4216             : 
    4217           0 : void SAL_CALL FormController::handle( const Reference< XInteractionRequest >& _rRequest ) throw (RuntimeException, std::exception)
    4218             : {
    4219           0 :     if ( !ensureInteractionHandler() )
    4220           0 :         return;
    4221           0 :     m_xInteractionHandler->handle( _rRequest );
    4222             : }
    4223             : 
    4224             : 
    4225          31 : void FormController::deleteInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
    4226             : {
    4227             :     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
    4228             :     // search the interceptor responsible for the given object
    4229          31 :     Interceptors::iterator aIter;
    4230          96 :     for (   aIter = m_aControlDispatchInterceptors.begin();
    4231          64 :             aIter != m_aControlDispatchInterceptors.end();
    4232             :             ++aIter
    4233             :         )
    4234             :     {
    4235          32 :         if ((*aIter)->getIntercepted() == _xInterception)
    4236          31 :             break;
    4237             :     }
    4238          31 :     if (aIter == m_aControlDispatchInterceptors.end())
    4239             :     {
    4240          31 :         return;
    4241             :     }
    4242             : 
    4243             :     // log off the interception from it's interception object
    4244          31 :     DispatchInterceptionMultiplexer* pInterceptorImpl = *aIter;
    4245          31 :     pInterceptorImpl->dispose();
    4246          31 :     pInterceptorImpl->release();
    4247             : 
    4248             :     // remove the interceptor from our array
    4249          31 :     m_aControlDispatchInterceptors.erase(aIter);
    4250             : }
    4251             : 
    4252             : 
    4253           0 : void FormController::implInvalidateCurrentControlDependentFeatures()
    4254             : {
    4255           0 :     Sequence< sal_Int16 > aCurrentControlDependentFeatures(4);
    4256             : 
    4257           0 :     aCurrentControlDependentFeatures[0] = FormFeature::SortAscending;
    4258           0 :     aCurrentControlDependentFeatures[1] = FormFeature::SortDescending;
    4259           0 :     aCurrentControlDependentFeatures[2] = FormFeature::AutoFilter;
    4260           0 :     aCurrentControlDependentFeatures[3] = FormFeature::RefreshCurrentControl;
    4261             : 
    4262           0 :     invalidateFeatures( aCurrentControlDependentFeatures );
    4263           0 : }
    4264             : 
    4265             : 
    4266           0 : void SAL_CALL FormController::columnChanged( const EventObject& /*_event*/ ) throw (RuntimeException, std::exception)
    4267             : {
    4268           0 :     implInvalidateCurrentControlDependentFeatures();
    4269           0 : }
    4270             : 
    4271         435 : }
    4272             : 
    4273             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11