Files
loongoffice/svx/source/form/formcontroller.cxx
Thomas Arnhold ba0a57702c remove OUString wrap for string literals
For some functions and all kinds of Exceptions.

CannotConvertException
CloseVetoException
DisposedException
EmptyUndoStackException
ErrorCodeIOException
Exception
GridInvalidDataException
GridInvalidModelException
IOException
IllegalAccessException
IllegalArgumentException
IllegalTypeException
IndexOutOfBoundsException
NoMasterException
NoSuchElementException
NoSupportException
PropertyVetoException
RuntimeException
SAXException
ScannerException
StorageWrappedTargetException
UnsupportedFlavorException
VetoException
WrappedTargetException
ZipIOException
throwGenericSQLException
throwIllegallArgumentException

createInstance
createInstanceWithContext
forName
getByName
getPackageManager
getPropertyValue
getUnpackedValueOrDefault
getValueByName
hasPropertyByName
openKey
setName
setPropertyValue
supportsService

bash command:

for i in `cat list`; do git grep "$i\s*(\s*OUString(\s*\"" -- '*.[hc]xx'
	| cut -d ':' -f1 | sort -u
	| xargs sed -i
		-e "s/\(\<$i\s*(\)\s*OUString(\s*\(\"[^\")\\]*\"\)\s*)\s*/\1\2/g"
		-e "s/\($i.*\)\"+ /\1\" + /g";
done

Change-Id: Iaf8e641b0abf28c082906014f87a183517630535
Reviewed-on: https://gerrit.libreoffice.org/4624
Tested-by: LibreOffice gerrit bot <gerrit@libreoffice.org>
Reviewed-by: Thomas Arnhold <thomas@arnhold.org>
Tested-by: Thomas Arnhold <thomas@arnhold.org>
2013-06-29 21:52:54 +00:00

4321 lines
161 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "fmcontrolbordermanager.hxx"
#include "fmcontrollayout.hxx"
#include "formcontroller.hxx"
#include "formfeaturedispatcher.hxx"
#include "fmdocumentclassification.hxx"
#include "formcontrolling.hxx"
#include "fmprop.hrc"
#include "svx/dialmgr.hxx"
#include "svx/fmresids.hrc"
#include "fmservs.hxx"
#include "svx/fmtools.hxx"
#include "fmurl.hxx"
#include <com/sun/star/awt/FocusChangeReason.hpp>
#include <com/sun/star/awt/XCheckBox.hpp>
#include <com/sun/star/awt/XComboBox.hpp>
#include <com/sun/star/awt/XListBox.hpp>
#include <com/sun/star/awt/XVclWindowPeer.hpp>
#include <com/sun/star/awt/TabController.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/container/XIdentifierReplace.hpp>
#include <com/sun/star/form/TabulatorCycle.hpp>
#include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
#include <com/sun/star/form/XBoundComponent.hpp>
#include <com/sun/star/form/XBoundControl.hpp>
#include <com/sun/star/form/XGridControl.hpp>
#include <com/sun/star/form/XLoadable.hpp>
#include <com/sun/star/form/XReset.hpp>
#include <com/sun/star/form/control/FilterControl.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/sdb/ParametersRequest.hpp>
#include <com/sun/star/sdb/RowChangeAction.hpp>
#include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
#include <com/sun/star/sdbc/ColumnValue.hpp>
#include <com/sun/star/sdbc/DataType.hpp>
#include <com/sun/star/task/InteractionHandler.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/form/runtime/FormOperations.hpp>
#include <com/sun/star/form/runtime/FormFeature.hpp>
#include <com/sun/star/container/XContainer.hpp>
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#include <com/sun/star/util/NumberFormatter.hpp>
#include <com/sun/star/sdb/SQLContext.hpp>
#include <com/sun/star/sdb/XColumn.hpp>
#include <comphelper/enumhelper.hxx>
#include <comphelper/extract.hxx>
#include <comphelper/interaction.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propagg.hxx>
#include <comphelper/property.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/uno3.hxx>
#include <comphelper/flagguard.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <connectivity/IParseContext.hxx>
#include <toolkit/controls/unocontrol.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <tools/debug.hxx>
#include <tools/diagnose_ex.h>
#include <tools/shl.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/svapp.hxx>
#include <osl/mutex.hxx>
#include <rtl/logfile.hxx>
#include <algorithm>
#include <o3tl/compat_functional.hxx>
using namespace ::com::sun::star;
using namespace ::comphelper;
using namespace ::connectivity;
using namespace ::connectivity::simple;
//------------------------------------------------------------------
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
FormController_NewInstance_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & _rxORB )
{
return *( new ::svxform::FormController( comphelper::getComponentContext(_rxORB) ) );
}
namespace svxform
{
using ::com::sun::star::sdb::XColumn;
using ::com::sun::star::awt::XControl;
using ::com::sun::star::awt::XTabController;
using ::com::sun::star::awt::TabController;
using ::com::sun::star::awt::XToolkit;
using ::com::sun::star::awt::XWindowPeer;
using ::com::sun::star::form::XGrid;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::uno::UNO_SET_THROW;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::container::XIndexAccess;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::beans::XPropertySetInfo;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::lang::IndexOutOfBoundsException;
using ::com::sun::star::sdb::XInteractionSupplyParameters;
using ::com::sun::star::awt::XTextComponent;
using ::com::sun::star::awt::XTextListener;
using ::com::sun::star::uno::Any;
using ::com::sun::star::frame::XDispatch;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::uno::XAggregation;
using ::com::sun::star::uno::Type;
using ::com::sun::star::lang::IllegalArgumentException;
using ::com::sun::star::sdbc::XConnection;
using ::com::sun::star::sdbc::XRowSet;
using ::com::sun::star::sdbc::XDatabaseMetaData;
using ::com::sun::star::util::XNumberFormatsSupplier;
using ::com::sun::star::util::NumberFormatter;
using ::com::sun::star::util::XNumberFormatter;
using ::com::sun::star::sdbcx::XColumnsSupplier;
using ::com::sun::star::container::XNameAccess;
using ::com::sun::star::lang::EventObject;
using ::com::sun::star::beans::Property;
using ::com::sun::star::container::XEnumeration;
using ::com::sun::star::form::XFormComponent;
using ::com::sun::star::form::runtime::XFormOperations;
using ::com::sun::star::form::runtime::FilterEvent;
using ::com::sun::star::form::runtime::XFilterControllerListener;
using ::com::sun::star::awt::XControlContainer;
using ::com::sun::star::container::XIdentifierReplace;
using ::com::sun::star::lang::WrappedTargetException;
using ::com::sun::star::form::XFormControllerListener;
using ::com::sun::star::awt::XWindow;
using ::com::sun::star::sdbc::XResultSet;
using ::com::sun::star::awt::XControlModel;
using ::com::sun::star::awt::XTabControllerModel;
using ::com::sun::star::beans::PropertyChangeEvent;
using ::com::sun::star::form::validation::XValidatableFormComponent;
using ::com::sun::star::form::XLoadable;
using ::com::sun::star::script::XEventAttacherManager;
using ::com::sun::star::form::XBoundControl;
using ::com::sun::star::beans::XPropertyChangeListener;
using ::com::sun::star::awt::TextEvent;
using ::com::sun::star::form::XBoundComponent;
using ::com::sun::star::awt::XCheckBox;
using ::com::sun::star::awt::XComboBox;
using ::com::sun::star::awt::XListBox;
using ::com::sun::star::awt::ItemEvent;
using ::com::sun::star::util::XModifyListener;
using ::com::sun::star::form::XReset;
using ::com::sun::star::frame::XDispatchProviderInterception;
using ::com::sun::star::form::XGridControl;
using ::com::sun::star::awt::XVclWindowPeer;
using ::com::sun::star::form::validation::XValidator;
using ::com::sun::star::awt::FocusEvent;
using ::com::sun::star::sdb::SQLContext;
using ::com::sun::star::container::XChild;
using ::com::sun::star::form::TabulatorCycle_RECORDS;
using ::com::sun::star::container::ContainerEvent;
using ::com::sun::star::lang::DisposedException;
using ::com::sun::star::lang::Locale;
using ::com::sun::star::beans::NamedValue;
using ::com::sun::star::lang::NoSupportException;
using ::com::sun::star::sdb::RowChangeEvent;
using ::com::sun::star::frame::XStatusListener;
using ::com::sun::star::frame::XDispatchProviderInterceptor;
using ::com::sun::star::sdb::SQLErrorEvent;
using ::com::sun::star::form::DatabaseParameterEvent;
using ::com::sun::star::sdb::ParametersRequest;
using ::com::sun::star::task::XInteractionRequest;
using ::com::sun::star::util::URL;
using ::com::sun::star::frame::FeatureStateEvent;
using ::com::sun::star::form::runtime::XFormControllerContext;
using ::com::sun::star::task::InteractionHandler;
using ::com::sun::star::task::XInteractionHandler;
using ::com::sun::star::form::runtime::FormOperations;
using ::com::sun::star::container::XContainer;
using ::com::sun::star::sdbc::SQLWarning;
namespace ColumnValue = ::com::sun::star::sdbc::ColumnValue;
namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
namespace FocusChangeReason = ::com::sun::star::awt::FocusChangeReason;
namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
namespace DataType = ::com::sun::star::sdbc::DataType;
//==============================================================================
// ColumnInfo
//==============================================================================
struct ColumnInfo
{
// information about the column itself
Reference< XColumn > xColumn;
sal_Int32 nNullable;
sal_Bool bAutoIncrement;
sal_Bool bReadOnly;
OUString sName;
// information about the control(s) bound to this column
/// the first control which is bound to the given column, and which requires input
Reference< XControl > xFirstControlWithInputRequired;
/** the first grid control which contains a column which is bound to the given database column, and requires
input
*/
Reference< XGrid > xFirstGridWithInputRequiredColumn;
/** if xFirstControlWithInputRequired is a grid control, then nRequiredGridColumn specifies the position
of the grid column which is actually bound
*/
sal_Int32 nRequiredGridColumn;
ColumnInfo()
:xColumn()
,nNullable( ColumnValue::NULLABLE_UNKNOWN )
,bAutoIncrement( sal_False )
,bReadOnly( sal_False )
,sName()
,xFirstControlWithInputRequired()
,xFirstGridWithInputRequiredColumn()
,nRequiredGridColumn( -1 )
{
}
};
//==============================================================================
//= ColumnInfoCache
//==============================================================================
class ColumnInfoCache
{
public:
ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier );
size_t getColumnCount() const { return m_aColumns.size(); }
const ColumnInfo& getColumnInfo( size_t _pos );
bool controlsInitialized() const { return m_bControlsInitialized; }
void initializeControls( const Sequence< Reference< XControl > >& _rControls );
void deinitializeControls();
private:
typedef ::std::vector< ColumnInfo > ColumnInfos;
ColumnInfos m_aColumns;
bool m_bControlsInitialized;
};
//------------------------------------------------------------------------------
ColumnInfoCache::ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier )
:m_aColumns()
,m_bControlsInitialized( false )
{
try
{
m_aColumns.clear();
Reference< XIndexAccess > xColumns( _rxColSupplier->getColumns(), UNO_QUERY_THROW );
sal_Int32 nColumnCount = xColumns->getCount();
m_aColumns.reserve( nColumnCount );
Reference< XPropertySet > xColumnProps;
for ( sal_Int32 i = 0; i < nColumnCount; ++i )
{
ColumnInfo aColInfo;
aColInfo.xColumn.set( xColumns->getByIndex(i), UNO_QUERY_THROW );
xColumnProps.set( aColInfo.xColumn, UNO_QUERY_THROW );
OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISNULLABLE ) >>= aColInfo.nNullable );
OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_AUTOINCREMENT ) >>= aColInfo.bAutoIncrement );
OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_NAME ) >>= aColInfo.sName );
OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISREADONLY ) >>= aColInfo.bReadOnly );
m_aColumns.push_back( aColInfo );
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
//------------------------------------------------------------------------------
namespace
{
bool lcl_isBoundTo( const Reference< XPropertySet >& _rxControlModel, const Reference< XInterface >& _rxNormDBField )
{
Reference< XInterface > xNormBoundField( _rxControlModel->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY );
return ( xNormBoundField.get() == _rxNormDBField.get() );
}
bool lcl_isInputRequired( const Reference< XPropertySet >& _rxControlModel )
{
sal_Bool bInputRequired = sal_True;
OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_INPUT_REQUIRED ) >>= bInputRequired );
return ( bInputRequired != sal_False );
}
void lcl_resetColumnControlInfo( ColumnInfo& _rColInfo )
{
_rColInfo.xFirstControlWithInputRequired.clear();
_rColInfo.xFirstGridWithInputRequiredColumn.clear();
_rColInfo.nRequiredGridColumn = -1;
}
}
//------------------------------------------------------------------------------
void ColumnInfoCache::deinitializeControls()
{
for ( ColumnInfos::iterator col = m_aColumns.begin();
col != m_aColumns.end();
++col
)
{
lcl_resetColumnControlInfo( *col );
}
}
//------------------------------------------------------------------------------
void ColumnInfoCache::initializeControls( const Sequence< Reference< XControl > >& _rControls )
{
try
{
// for every of our known columns, find the controls which are bound to this column
for ( ColumnInfos::iterator col = m_aColumns.begin();
col != m_aColumns.end();
++col
)
{
OSL_ENSURE( !col->xFirstControlWithInputRequired.is() && !col->xFirstGridWithInputRequiredColumn.is()
&& ( col->nRequiredGridColumn == -1 ), "ColumnInfoCache::initializeControls: called me twice?" );
lcl_resetColumnControlInfo( *col );
const Reference< XControl >* pControl( _rControls.getConstArray() );
const Reference< XControl >* pControlEnd( pControl + _rControls.getLength() );
for ( ; pControl != pControlEnd; ++pControl )
{
if ( !pControl->is() )
continue;
Reference< XPropertySet > xModel( (*pControl)->getModel(), UNO_QUERY_THROW );
Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
// special handling for grid controls
Reference< XGrid > xGrid( *pControl, UNO_QUERY );
if ( xGrid.is() )
{
Reference< XIndexAccess > xGridColAccess( xModel, UNO_QUERY_THROW );
sal_Int32 gridColCount = xGridColAccess->getCount();
sal_Int32 gridCol = 0;
for ( gridCol = 0; gridCol < gridColCount; ++gridCol )
{
Reference< XPropertySet > xGridColumnModel( xGridColAccess->getByIndex( gridCol ), UNO_QUERY_THROW );
if ( !lcl_isBoundTo( xGridColumnModel, col->xColumn )
|| !lcl_isInputRequired( xGridColumnModel )
)
continue; // with next grid column
break;
}
if ( gridCol < gridColCount )
{
// found a grid column which is bound to the given
col->xFirstGridWithInputRequiredColumn = xGrid;
col->nRequiredGridColumn = gridCol;
break;
}
continue; // with next control
}
if ( !xModelPSI->hasPropertyByName( FM_PROP_BOUNDFIELD )
|| !lcl_isBoundTo( xModel, col->xColumn )
|| !lcl_isInputRequired( xModel )
)
continue; // with next control
break;
}
if ( pControl == pControlEnd )
// did not find a control which is bound to this particular column, and for which the input is required
continue; // with next DB column
col->xFirstControlWithInputRequired = *pControl;
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
m_bControlsInitialized = true;
}
//------------------------------------------------------------------------------
const ColumnInfo& ColumnInfoCache::getColumnInfo( size_t _pos )
{
if ( _pos >= m_aColumns.size() )
throw IndexOutOfBoundsException();
return m_aColumns[ _pos ];
}
//==================================================================
// OParameterContinuation
//==================================================================
class OParameterContinuation : public OInteraction< XInteractionSupplyParameters >
{
Sequence< PropertyValue > m_aValues;
public:
OParameterContinuation() { }
Sequence< PropertyValue > getValues() const { return m_aValues; }
// XInteractionSupplyParameters
virtual void SAL_CALL setParameters( const Sequence< PropertyValue >& _rValues ) throw(RuntimeException);
};
//------------------------------------------------------------------
void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) throw(RuntimeException)
{
m_aValues = _rValues;
}
//==================================================================
// FmXAutoControl
//==================================================================
struct FmFieldInfo
{
OUString aFieldName;
Reference< XPropertySet > xField;
Reference< XTextComponent > xText;
FmFieldInfo(const Reference< XPropertySet >& _xField, const Reference< XTextComponent >& _xText)
:xField(_xField)
,xText(_xText)
{xField->getPropertyValue(FM_PROP_NAME) >>= aFieldName;}
};
//==================================================================
// FmXAutoControl
//==================================================================
class FmXAutoControl: public UnoControl
{
friend Reference< XInterface > SAL_CALL FmXAutoControl_NewInstance_Impl();
public:
FmXAutoControl() :UnoControl()
{
}
virtual OUString GetComponentServiceName() {return OUString("Edit");}
virtual void SAL_CALL createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw( RuntimeException );
protected:
virtual void ImplSetPeerProperty( const OUString& rPropName, const Any& rVal );
};
//------------------------------------------------------------------------------
void FmXAutoControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw( RuntimeException )
{
UnoControl::createPeer( rxToolkit, rParentPeer );
Reference< XTextComponent > xText(getPeer() , UNO_QUERY);
if (xText.is())
{
xText->setText(OUString(String(SVX_RES(RID_STR_AUTOFIELD))));
xText->setEditable(sal_False);
}
}
//------------------------------------------------------------------------------
void FmXAutoControl::ImplSetPeerProperty( const OUString& rPropName, const Any& rVal )
{
// these properties are ignored
if (rPropName == FM_PROP_TEXT)
return;
UnoControl::ImplSetPeerProperty( rPropName, rVal );
}
//------------------------------------------------------------------------------
IMPL_LINK( FormController, OnActivateTabOrder, void*, /*EMPTYTAG*/ )
{
activateTabOrder();
return 1;
}
//------------------------------------------------------------------------------
struct UpdateAllListeners : public ::std::unary_function< Reference< XDispatch >, bool >
{
bool operator()( const Reference< XDispatch >& _rxDispatcher ) const
{
static_cast< ::svx::OSingleFeatureDispatcher* >( _rxDispatcher.get() )->updateAllListeners();
// the return is a dummy only so we can use this struct in a o3tl::compose1 call
return true;
}
};
//..............................................................................
IMPL_LINK( FormController, OnInvalidateFeatures, void*, /*_pNotInterestedInThisParam*/ )
{
::osl::MutexGuard aGuard( m_aMutex );
for ( ::std::set< sal_Int16 >::const_iterator aLoop = m_aInvalidFeatures.begin();
aLoop != m_aInvalidFeatures.end();
++aLoop
)
{
DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( *aLoop );
if ( aDispatcherPos != m_aFeatureDispatchers.end() )
{
// TODO: for the real and actual listener notifications, we should release
// our mutex
UpdateAllListeners( )( aDispatcherPos->second );
}
}
return 1;
}
/*************************************************************************/
DBG_NAME( FormController )
//------------------------------------------------------------------
FormController::FormController(const Reference< css::uno::XComponentContext > & _rxORB )
:FormController_BASE( m_aMutex )
,OPropertySetHelper( FormController_BASE::rBHelper )
,OSQLParserClient( _rxORB )
,m_xComponentContext( _rxORB )
,m_aActivateListeners(m_aMutex)
,m_aModifyListeners(m_aMutex)
,m_aErrorListeners(m_aMutex)
,m_aDeleteListeners(m_aMutex)
,m_aRowSetApproveListeners(m_aMutex)
,m_aParameterListeners(m_aMutex)
,m_aFilterListeners(m_aMutex)
,m_pControlBorderManager( new ::svxform::ControlBorderManager )
,m_xFormOperations()
,m_aMode( OUString( "DataMode" ) )
,m_aLoadEvent( LINK( this, FormController, OnLoad ) )
,m_aToggleEvent( LINK( this, FormController, OnToggleAutoFields ) )
,m_aActivationEvent( LINK( this, FormController, OnActivated ) )
,m_aDeactivationEvent( LINK( this, FormController, OnDeactivated ) )
,m_nCurrentFilterPosition(-1)
,m_bCurrentRecordModified(sal_False)
,m_bCurrentRecordNew(sal_False)
,m_bLocked(sal_False)
,m_bDBConnection(sal_False)
,m_bCycle(sal_False)
,m_bCanInsert(sal_False)
,m_bCanUpdate(sal_False)
,m_bCommitLock(sal_False)
,m_bModified(sal_False)
,m_bControlsSorted(sal_False)
,m_bFiltering(sal_False)
,m_bAttachEvents(sal_True)
,m_bDetachEvents(sal_True)
,m_bAttemptedHandlerCreation( false )
,m_bSuspendFilterTextListening( false )
{
DBG_CTOR( FormController, NULL );
::comphelper::increment(m_refCount);
{
m_xTabController = TabController::create( m_xComponentContext );
m_xAggregate = Reference< XAggregation >( m_xTabController, UNO_QUERY_THROW );
m_xAggregate->setDelegator( *this );
}
::comphelper::decrement(m_refCount);
m_aTabActivationTimer.SetTimeout( 500 );
m_aTabActivationTimer.SetTimeoutHdl( LINK( this, FormController, OnActivateTabOrder ) );
m_aFeatureInvalidationTimer.SetTimeout( 200 );
m_aFeatureInvalidationTimer.SetTimeoutHdl( LINK( this, FormController, OnInvalidateFeatures ) );
}
//------------------------------------------------------------------
FormController::~FormController()
{
{
::osl::MutexGuard aGuard( m_aMutex );
m_aLoadEvent.CancelPendingCall();
m_aToggleEvent.CancelPendingCall();
m_aActivationEvent.CancelPendingCall();
m_aDeactivationEvent.CancelPendingCall();
if ( m_aTabActivationTimer.IsActive() )
m_aTabActivationTimer.Stop();
}
if ( m_aFeatureInvalidationTimer.IsActive() )
m_aFeatureInvalidationTimer.Stop();
disposeAllFeaturesAndDispatchers();
if ( m_xFormOperations.is() )
m_xFormOperations->dispose();
m_xFormOperations.clear();
// Freigeben der Aggregation
if ( m_xAggregate.is() )
{
m_xAggregate->setDelegator( NULL );
m_xAggregate.clear();
}
DELETEZ( m_pControlBorderManager );
DBG_DTOR( FormController, NULL );
}
// -----------------------------------------------------------------------------
void SAL_CALL FormController::acquire() throw ()
{
FormController_BASE::acquire();
}
// -----------------------------------------------------------------------------
void SAL_CALL FormController::release() throw ()
{
FormController_BASE::release();
}
//------------------------------------------------------------------
Any SAL_CALL FormController::queryInterface( const Type& _rType ) throw(RuntimeException)
{
Any aRet = FormController_BASE::queryInterface( _rType );
if ( !aRet.hasValue() )
aRet = OPropertySetHelper::queryInterface( _rType );
if ( !aRet.hasValue() )
aRet = m_xAggregate->queryAggregation( _rType );
return aRet;
}
//------------------------------------------------------------------------------
Sequence< sal_Int8 > SAL_CALL FormController::getImplementationId() throw( RuntimeException )
{
static ::cppu::OImplementationId* pId = NULL;
if ( !pId )
{
::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
if ( !pId )
{
static ::cppu::OImplementationId aId;
pId = &aId;
}
}
return pId->getImplementationId();
}
//------------------------------------------------------------------------------
Sequence< Type > SAL_CALL FormController::getTypes( ) throw(RuntimeException)
{
return comphelper::concatSequences(
FormController_BASE::getTypes(),
::cppu::OPropertySetHelper::getTypes()
);
}
// XServiceInfo
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::supportsService(const OUString& ServiceName) throw( RuntimeException )
{
Sequence< OUString> aSNL(getSupportedServiceNames());
const OUString * pArray = aSNL.getConstArray();
for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
if( pArray[i] == ServiceName )
return sal_True;
return sal_False;
}
//------------------------------------------------------------------------------
OUString SAL_CALL FormController::getImplementationName() throw( RuntimeException )
{
return OUString("org.openoffice.comp.svx.FormController");
}
//------------------------------------------------------------------------------
Sequence< OUString> SAL_CALL FormController::getSupportedServiceNames(void) throw( RuntimeException )
{
// service names which are supported only, but cannot be used to created an
// instance at a service factory
Sequence< OUString > aNonCreatableServiceNames( 1 );
aNonCreatableServiceNames[ 0 ] = OUString( "com.sun.star.form.FormControllerDispatcher" );
// services which can be used to created an instance at a service factory
Sequence< OUString > aCreatableServiceNames( getSupportedServiceNames_Static() );
return ::comphelper::concatSequences( aCreatableServiceNames, aNonCreatableServiceNames );
}
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::approveReset(const EventObject& /*rEvent*/) throw( RuntimeException )
{
return sal_True;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::resetted(const EventObject& rEvent) throw( RuntimeException )
{
::osl::MutexGuard aGuard(m_aMutex);
if (getCurrentControl().is() && (getCurrentControl()->getModel() == rEvent.Source))
m_bModified = sal_False;
}
//------------------------------------------------------------------------------
Sequence< OUString> FormController::getSupportedServiceNames_Static(void)
{
static Sequence< OUString> aServices;
if (!aServices.getLength())
{
aServices.realloc(2);
aServices.getArray()[0] = OUString( "com.sun.star.form.runtime.FormController" );
aServices.getArray()[1] = OUString("com.sun.star.awt.control.TabController");
}
return aServices;
}
// -----------------------------------------------------------------------------
namespace
{
struct ResetComponentText : public ::std::unary_function< Reference< XTextComponent >, void >
{
void operator()( const Reference< XTextComponent >& _rxText )
{
_rxText->setText( OUString() );
}
};
struct RemoveComponentTextListener : public ::std::unary_function< Reference< XTextComponent >, void >
{
RemoveComponentTextListener( const Reference< XTextListener >& _rxListener )
:m_xListener( _rxListener )
{
}
void operator()( const Reference< XTextComponent >& _rxText )
{
_rxText->removeTextListener( m_xListener );
}
private:
Reference< XTextListener > m_xListener;
};
}
// -----------------------------------------------------------------------------
void FormController::impl_setTextOnAllFilter_throw()
{
m_bSuspendFilterTextListening = true;
::comphelper::FlagGuard aResetFlag( m_bSuspendFilterTextListening );
// reset the text for all controls
::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), ResetComponentText() );
if ( m_aFilterRows.empty() )
// nothing to do anymore
return;
if ( m_nCurrentFilterPosition < 0 )
return;
// set the text for all filters
OSL_ENSURE( m_aFilterRows.size() > (size_t)m_nCurrentFilterPosition,
"FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big" );
if ( (size_t)m_nCurrentFilterPosition < m_aFilterRows.size() )
{
FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
for ( FmFilterRow::const_iterator iter2 = rRow.begin();
iter2 != rRow.end();
++iter2
)
{
iter2->first->setText( iter2->second );
}
}
}
// OPropertySetHelper
//------------------------------------------------------------------------------
sal_Bool FormController::convertFastPropertyValue( Any & /*rConvertedValue*/, Any & /*rOldValue*/,
sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
throw( IllegalArgumentException )
{
return sal_False;
}
//------------------------------------------------------------------------------
void FormController::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
throw( Exception )
{
}
//------------------------------------------------------------------------------
void FormController::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
{
switch (nHandle)
{
case FM_ATTR_FILTER:
{
OUStringBuffer aFilter;
OStaticDataAccessTools aStaticTools;
Reference<XConnection> xConnection(aStaticTools.getRowSetConnection(Reference< XRowSet>(m_xModelAsIndex, UNO_QUERY)));
if (xConnection.is())
{
Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
Reference< XNumberFormatsSupplier> xFormatSupplier( aStaticTools.getNumberFormats( xConnection, sal_True ) );
Reference< XNumberFormatter> xFormatter = NumberFormatter::create(m_xComponentContext);
xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
Reference< XColumnsSupplier> xSupplyCols(m_xModelAsIndex, UNO_QUERY);
Reference< XNameAccess> xFields(xSupplyCols->getColumns(), UNO_QUERY);
// now add the filter rows
try
{
for ( FmFilterRows::const_iterator row = m_aFilterRows.begin(); row != m_aFilterRows.end(); ++row )
{
const FmFilterRow& rRow = *row;
if ( rRow.empty() )
continue;
OUStringBuffer aRowFilter;
for ( FmFilterRow::const_iterator condition = rRow.begin(); condition != rRow.end(); ++condition )
{
// get the field of the controls map
Reference< XControl > xControl( condition->first, UNO_QUERY_THROW );
Reference< XPropertySet > xModelProps( xControl->getModel(), UNO_QUERY_THROW );
Reference< XPropertySet > xField( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW );
OUString sFilterValue( condition->second );
OUString sErrorMsg, sCriteria;
const ::rtl::Reference< ISQLParseNode > xParseNode =
predicateTree( sErrorMsg, sFilterValue, xFormatter, xField );
OSL_ENSURE( xParseNode.is(), "FormController::getFastPropertyValue: could not parse the field value predicate!" );
if ( xParseNode.is() )
{
// don't use a parse context here, we need it unlocalized
xParseNode->parseNodeToStr( sCriteria, xConnection, NULL );
if ( condition != rRow.begin() )
aRowFilter.appendAscii( " AND " );
aRowFilter.append( sCriteria );
}
}
if ( !aRowFilter.isEmpty() )
{
if ( !aFilter.isEmpty() )
aFilter.appendAscii( " OR " );
aFilter.appendAscii( "( " );
aFilter.append( aRowFilter.makeStringAndClear() );
aFilter.appendAscii( " )" );
}
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
aFilter.setLength(0);
}
}
rValue <<= aFilter.makeStringAndClear();
}
break;
case FM_ATTR_FORM_OPERATIONS:
rValue <<= m_xFormOperations;
break;
}
}
//------------------------------------------------------------------------------
Reference< XPropertySetInfo > FormController::getPropertySetInfo() throw( RuntimeException )
{
static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
return xInfo;
}
//------------------------------------------------------------------------------
#define DECL_PROP_CORE(varname, type) \
pDesc[nPos++] = Property(FM_PROP_##varname, FM_ATTR_##varname, ::getCppuType((const type*)0),
#define DECL_PROP1(varname, type, attrib1) \
DECL_PROP_CORE(varname, type) PropertyAttribute::attrib1)
//------------------------------------------------------------------------------
void FormController::fillProperties(
Sequence< Property >& /* [out] */ _rProps,
Sequence< Property >& /* [out] */ /*_rAggregateProps*/
) const
{
_rProps.realloc(2);
sal_Int32 nPos = 0;
Property* pDesc = _rProps.getArray();
DECL_PROP1(FILTER, OUString, READONLY);
DECL_PROP1(FORM_OPERATIONS, Reference< XFormOperations >, READONLY);
}
//------------------------------------------------------------------------------
::cppu::IPropertyArrayHelper& FormController::getInfoHelper()
{
return *getArrayHelper();
}
// XFilterController
//------------------------------------------------------------------------------
void SAL_CALL FormController::addFilterControllerListener( const Reference< XFilterControllerListener >& _Listener ) throw( RuntimeException )
{
m_aFilterListeners.addInterface( _Listener );
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeFilterControllerListener( const Reference< XFilterControllerListener >& _Listener ) throw( RuntimeException )
{
m_aFilterListeners.removeInterface( _Listener );
}
//------------------------------------------------------------------------------
::sal_Int32 SAL_CALL FormController::getFilterComponents() throw( ::com::sun::star::uno::RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
return m_aFilterComponents.size();
}
//------------------------------------------------------------------------------
::sal_Int32 SAL_CALL FormController::getDisjunctiveTerms() throw( ::com::sun::star::uno::RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
return m_aFilterRows.size();
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::setPredicateExpression( ::sal_Int32 _Component, ::sal_Int32 _Term, const OUString& _PredicateExpression ) throw( RuntimeException, IndexOutOfBoundsException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
if ( ( _Component < 0 ) || ( _Component >= getFilterComponents() ) || ( _Term < 0 ) || ( _Term >= getDisjunctiveTerms() ) )
throw IndexOutOfBoundsException( OUString(), *this );
Reference< XTextComponent > xText( m_aFilterComponents[ _Component ] );
xText->setText( _PredicateExpression );
FmFilterRow& rFilterRow = m_aFilterRows[ _Term ];
if ( !_PredicateExpression.isEmpty() )
rFilterRow[ xText ] = _PredicateExpression;
else
rFilterRow.erase( xText );
}
//------------------------------------------------------------------------------
Reference< XControl > FormController::getFilterComponent( ::sal_Int32 _Component ) throw( RuntimeException, IndexOutOfBoundsException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
if ( ( _Component < 0 ) || ( _Component >= getFilterComponents() ) )
throw IndexOutOfBoundsException( OUString(), *this );
return Reference< XControl >( m_aFilterComponents[ _Component ], UNO_QUERY );
}
//------------------------------------------------------------------------------
Sequence< Sequence< OUString > > FormController::getPredicateExpressions() throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
Sequence< Sequence< OUString > > aExpressions( m_aFilterRows.size() );
sal_Int32 termIndex = 0;
for ( FmFilterRows::const_iterator row = m_aFilterRows.begin();
row != m_aFilterRows.end();
++row, ++termIndex
)
{
const FmFilterRow& rRow( *row );
Sequence< OUString > aConjunction( m_aFilterComponents.size() );
sal_Int32 componentIndex = 0;
for ( FilterComponents::const_iterator comp = m_aFilterComponents.begin();
comp != m_aFilterComponents.end();
++comp, ++componentIndex
)
{
FmFilterRow::const_iterator predicate = rRow.find( *comp );
if ( predicate != rRow.end() )
aConjunction[ componentIndex ] = predicate->second;
}
aExpressions[ termIndex ] = aConjunction;
}
return aExpressions;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeDisjunctiveTerm( ::sal_Int32 _Term ) throw (IndexOutOfBoundsException, RuntimeException)
{
// SYNCHRONIZED -->
::osl::ClearableMutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
if ( ( _Term < 0 ) || ( _Term >= getDisjunctiveTerms() ) )
throw IndexOutOfBoundsException( OUString(), *this );
// if the to-be-deleted row is our current row, we need to shift
if ( _Term == m_nCurrentFilterPosition )
{
if ( m_nCurrentFilterPosition < sal_Int32( m_aFilterRows.size() - 1 ) )
++m_nCurrentFilterPosition;
else
--m_nCurrentFilterPosition;
}
FmFilterRows::iterator pos = m_aFilterRows.begin() + _Term;
m_aFilterRows.erase( pos );
// adjust m_nCurrentFilterPosition if the removed row preceeded it
if ( _Term < m_nCurrentFilterPosition )
--m_nCurrentFilterPosition;
OSL_POSTCOND( ( m_nCurrentFilterPosition < 0 ) == ( m_aFilterRows.empty() ),
"FormController::removeDisjunctiveTerm: inconsistency!" );
// update the texts in the filter controls
impl_setTextOnAllFilter_throw();
FilterEvent aEvent;
aEvent.Source = *this;
aEvent.DisjunctiveTerm = _Term;
aGuard.clear();
// <-- SYNCHRONIZED
m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermRemoved, aEvent );
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::appendEmptyDisjunctiveTerm() throw (RuntimeException)
{
// SYNCHRONIZED -->
::osl::ClearableMutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
impl_appendEmptyFilterRow( aGuard );
// <-- SYNCHRONIZED
}
//------------------------------------------------------------------------------
::sal_Int32 SAL_CALL FormController::getActiveTerm() throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
return m_nCurrentFilterPosition;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::setActiveTerm( ::sal_Int32 _ActiveTerm ) throw (IndexOutOfBoundsException, RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
if ( ( _ActiveTerm < 0 ) || ( _ActiveTerm >= getDisjunctiveTerms() ) )
throw IndexOutOfBoundsException( OUString(), *this );
if ( _ActiveTerm == getActiveTerm() )
return;
m_nCurrentFilterPosition = _ActiveTerm;
impl_setTextOnAllFilter_throw();
}
// XElementAccess
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::hasElements(void) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
return !m_aChildren.empty();
}
//------------------------------------------------------------------------------
Type SAL_CALL FormController::getElementType(void) throw( RuntimeException )
{
return ::getCppuType((const Reference< XFormController>*)0);
}
// XEnumerationAccess
//------------------------------------------------------------------------------
Reference< XEnumeration > SAL_CALL FormController::createEnumeration(void) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
return new ::comphelper::OEnumerationByIndex(this);
}
// XIndexAccess
//------------------------------------------------------------------------------
sal_Int32 SAL_CALL FormController::getCount(void) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
return m_aChildren.size();
}
//------------------------------------------------------------------------------
Any SAL_CALL FormController::getByIndex(sal_Int32 Index) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
if (Index < 0 ||
Index >= (sal_Int32)m_aChildren.size())
throw IndexOutOfBoundsException();
return makeAny( m_aChildren[ Index ] );
}
// EventListener
//------------------------------------------------------------------------------
void SAL_CALL FormController::disposing(const EventObject& e) throw( RuntimeException )
{
// Ist der Container disposed worden
::osl::MutexGuard aGuard( m_aMutex );
Reference< XControlContainer > xContainer(e.Source, UNO_QUERY);
if (xContainer.is())
{
setContainer(Reference< XControlContainer > ());
}
else
{
// ist ein Control disposed worden
Reference< XControl > xControl(e.Source, UNO_QUERY);
if (xControl.is())
{
if (getContainer().is())
removeControl(xControl);
}
}
}
// OComponentHelper
//-----------------------------------------------------------------------------
void FormController::disposeAllFeaturesAndDispatchers() SAL_THROW(())
{
for ( DispatcherContainer::iterator aDispatcher = m_aFeatureDispatchers.begin();
aDispatcher != m_aFeatureDispatchers.end();
++aDispatcher
)
{
try
{
::comphelper::disposeComponent( aDispatcher->second );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
m_aFeatureDispatchers.clear();
}
//-----------------------------------------------------------------------------
void FormController::disposing(void)
{
EventObject aEvt( *this );
// if we're still active, simulate a "deactivated" event
if ( m_xActiveControl.is() )
m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvt );
// notify all our listeners
m_aActivateListeners.disposeAndClear(aEvt);
m_aModifyListeners.disposeAndClear(aEvt);
m_aErrorListeners.disposeAndClear(aEvt);
m_aDeleteListeners.disposeAndClear(aEvt);
m_aRowSetApproveListeners.disposeAndClear(aEvt);
m_aParameterListeners.disposeAndClear(aEvt);
m_aFilterListeners.disposeAndClear(aEvt);
removeBoundFieldListener();
stopFiltering();
m_pControlBorderManager->restoreAll();
m_aFilterRows.clear();
::osl::MutexGuard aGuard( m_aMutex );
m_xActiveControl = NULL;
implSetCurrentControl( NULL );
// clean up our children
for (FmFormControllers::const_iterator i = m_aChildren.begin();
i != m_aChildren.end(); ++i)
{
// search the position of the model within the form
Reference< XFormComponent > xForm((*i)->getModel(), UNO_QUERY);
sal_uInt32 nPos = m_xModelAsIndex->getCount();
Reference< XFormComponent > xTemp;
for( ; nPos; )
{
m_xModelAsIndex->getByIndex( --nPos ) >>= xTemp;
if ( xForm.get() == xTemp.get() )
{
Reference< XInterface > xIfc( *i, UNO_QUERY );
m_xModelAsManager->detach( nPos, xIfc );
break;
}
}
Reference< XComponent > (*i, UNO_QUERY)->dispose();
}
m_aChildren.clear();
disposeAllFeaturesAndDispatchers();
if ( m_xFormOperations.is() )
m_xFormOperations->dispose();
m_xFormOperations.clear();
if (m_bDBConnection)
unload();
setContainer( NULL );
setModel( NULL );
setParent( NULL );
::comphelper::disposeComponent( m_xComposer );
m_bDBConnection = sal_False;
}
//------------------------------------------------------------------------------
namespace
{
static bool lcl_shouldUseDynamicControlBorder( const Reference< XInterface >& _rxForm, const Any& _rDynamicColorProp )
{
bool bDoUse = false;
if ( !( _rDynamicColorProp >>= bDoUse ) )
{
DocumentType eDocType = DocumentClassification::classifyHostDocument( _rxForm );
return ControlLayouter::useDynamicBorderColor( eDocType );
}
return bDoUse;
}
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::propertyChange(const PropertyChangeEvent& evt) throw( RuntimeException )
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
if ( evt.PropertyName == FM_PROP_BOUNDFIELD )
{
Reference<XPropertySet> xOldBound;
evt.OldValue >>= xOldBound;
if ( !xOldBound.is() && evt.NewValue.hasValue() )
{
Reference< XControlModel > xControlModel(evt.Source,UNO_QUERY);
Reference< XControl > xControl = findControl(m_aControls,xControlModel,sal_False,sal_False);
if ( xControl.is() )
{
startControlModifyListening( xControl );
Reference<XPropertySet> xProp(xControlModel,UNO_QUERY);
if ( xProp.is() )
xProp->removePropertyChangeListener(FM_PROP_BOUNDFIELD, this);
}
}
}
else
{
sal_Bool bModifiedChanged = (evt.PropertyName == FM_PROP_ISMODIFIED);
sal_Bool bNewChanged = (evt.PropertyName == FM_PROP_ISNEW);
if (bModifiedChanged || bNewChanged)
{
::osl::MutexGuard aGuard( m_aMutex );
if (bModifiedChanged)
m_bCurrentRecordModified = ::comphelper::getBOOL(evt.NewValue);
else
m_bCurrentRecordNew = ::comphelper::getBOOL(evt.NewValue);
// toggle the locking
if (m_bLocked != determineLockState())
{
m_bLocked = !m_bLocked;
setLocks();
if (isListeningForChanges())
startListening();
else
stopListening();
}
if ( bNewChanged )
m_aToggleEvent.Call();
if (!m_bCurrentRecordModified)
m_bModified = sal_False;
}
else if ( evt.PropertyName == FM_PROP_DYNAMIC_CONTROL_BORDER )
{
bool bEnable = lcl_shouldUseDynamicControlBorder( evt.Source, evt.NewValue );
if ( bEnable )
{
m_pControlBorderManager->enableDynamicBorderColor();
if ( m_xActiveControl.is() )
m_pControlBorderManager->focusGained( m_xActiveControl.get() );
}
else
{
m_pControlBorderManager->disableDynamicBorderColor();
}
}
}
}
//------------------------------------------------------------------------------
bool FormController::replaceControl( const Reference< XControl >& _rxExistentControl, const Reference< XControl >& _rxNewControl )
{
bool bSuccess = false;
try
{
Reference< XIdentifierReplace > xContainer( getContainer(), UNO_QUERY );
DBG_ASSERT( xContainer.is(), "FormController::replaceControl: yes, it's not required by the service description, but XItentifierReplaces would be nice!" );
if ( xContainer.is() )
{
// look up the ID of _rxExistentControl
Sequence< sal_Int32 > aIdentifiers( xContainer->getIdentifiers() );
const sal_Int32* pIdentifiers = aIdentifiers.getConstArray();
const sal_Int32* pIdentifiersEnd = aIdentifiers.getConstArray() + aIdentifiers.getLength();
for ( ; pIdentifiers != pIdentifiersEnd; ++pIdentifiers )
{
Reference< XControl > xCheck( xContainer->getByIdentifier( *pIdentifiers ), UNO_QUERY );
if ( xCheck == _rxExistentControl )
break;
}
DBG_ASSERT( pIdentifiers != pIdentifiersEnd, "FormController::replaceControl: did not find the control in the container!" );
if ( pIdentifiers != pIdentifiersEnd )
{
bool bReplacedWasActive = ( m_xActiveControl.get() == _rxExistentControl.get() );
bool bReplacedWasCurrent = ( m_xCurrentControl.get() == _rxExistentControl.get() );
if ( bReplacedWasActive )
{
m_xActiveControl = NULL;
implSetCurrentControl( NULL );
}
else if ( bReplacedWasCurrent )
{
implSetCurrentControl( _rxNewControl );
}
// carry over the model
_rxNewControl->setModel( _rxExistentControl->getModel() );
xContainer->replaceByIdentifer( *pIdentifiers, makeAny( _rxNewControl ) );
bSuccess = true;
if ( bReplacedWasActive )
{
Reference< XWindow > xControlWindow( _rxNewControl, UNO_QUERY );
if ( xControlWindow.is() )
xControlWindow->setFocus();
}
}
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
Reference< XControl > xDisposeIt( bSuccess ? _rxExistentControl : _rxNewControl );
::comphelper::disposeComponent( xDisposeIt );
return bSuccess;
}
//------------------------------------------------------------------------------
void FormController::toggleAutoFields(sal_Bool bAutoFields)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
Sequence< Reference< XControl > > aControlsCopy( m_aControls );
const Reference< XControl >* pControls = aControlsCopy.getConstArray();
sal_Int32 nControls = aControlsCopy.getLength();
if (bAutoFields)
{
// as we don't want new controls to be attached to the scripting environment
// we change attach flags
m_bAttachEvents = sal_False;
for (sal_Int32 i = nControls; i > 0;)
{
Reference< XControl > xControl = pControls[--i];
if (xControl.is())
{
Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
{
// does the model use a bound field ?
Reference< XPropertySet > xField;
xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
// is it a autofield?
if ( xField.is()
&& ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT, xField )
&& ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_AUTOINCREMENT ) )
)
{
replaceControl( xControl, new FmXAutoControl() );
}
}
}
}
m_bAttachEvents = sal_True;
}
else
{
m_bDetachEvents = sal_False;
for (sal_Int32 i = nControls; i > 0;)
{
Reference< XControl > xControl = pControls[--i];
if (xControl.is())
{
Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
{
// does the model use a bound field ?
Reference< XPropertySet > xField;
xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
// is it a autofield?
if ( xField.is()
&& ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT, xField )
&& ::comphelper::getBOOL( xField->getPropertyValue(FM_PROP_AUTOINCREMENT ) )
)
{
OUString sServiceName;
OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName );
Reference< XControl > xNewControl( m_xComponentContext->getServiceManager()->createInstanceWithContext( sServiceName, m_xComponentContext ), UNO_QUERY );
replaceControl( xControl, xNewControl );
}
}
}
}
m_bDetachEvents = sal_True;
}
}
//------------------------------------------------------------------------------
IMPL_LINK_NOARG(FormController, OnToggleAutoFields)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
toggleAutoFields(m_bCurrentRecordNew);
return 1L;
}
// XTextListener
//------------------------------------------------------------------------------
void SAL_CALL FormController::textChanged(const TextEvent& e) throw( RuntimeException )
{
// SYNCHRONIZED -->
::osl::ClearableMutexGuard aGuard( m_aMutex );
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
if ( !m_bFiltering )
{
impl_onModify();
return;
}
if ( m_bSuspendFilterTextListening )
return;
Reference< XTextComponent > xText(e.Source,UNO_QUERY);
OUString aText = xText->getText();
if ( m_aFilterRows.empty() )
appendEmptyDisjunctiveTerm();
// Suchen der aktuellen Row
if ( ( (size_t)m_nCurrentFilterPosition >= m_aFilterRows.size() ) || ( m_nCurrentFilterPosition < 0 ) )
{
OSL_ENSURE( false, "FormController::textChanged: m_nCurrentFilterPosition is wrong!" );
return;
}
FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
// do we have a new filter
if (!aText.isEmpty())
rRow[xText] = aText;
else
{
// do we have the control in the row
FmFilterRow::iterator iter = rRow.find(xText);
// erase the entry out of the row
if (iter != rRow.end())
rRow.erase(iter);
}
// multiplex the event to our FilterControllerListeners
FilterEvent aEvent;
aEvent.Source = *this;
aEvent.FilterComponent = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xText ) - m_aFilterComponents.begin();
aEvent.DisjunctiveTerm = getActiveTerm();
aEvent.PredicateExpression = aText;
aGuard.clear();
// <-- SYNCHRONIZED
// notify the changed filter expression
m_aFilterListeners.notifyEach( &XFilterControllerListener::predicateExpressionChanged, aEvent );
}
// XItemListener
//------------------------------------------------------------------------------
void SAL_CALL FormController::itemStateChanged(const ItemEvent& /*rEvent*/) throw( RuntimeException )
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
impl_onModify();
}
// XModificationBroadcaster
//------------------------------------------------------------------------------
void SAL_CALL FormController::addModifyListener(const Reference< XModifyListener > & l) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aModifyListeners.addInterface( l );
}
//------------------------------------------------------------------------------
void FormController::removeModifyListener(const Reference< XModifyListener > & l) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aModifyListeners.removeInterface( l );
}
// XModificationListener
//------------------------------------------------------------------------------
void FormController::modified( const EventObject& _rEvent ) throw( RuntimeException )
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
try
{
if ( _rEvent.Source != m_xActiveControl )
{ // let this control grab the focus
// (this case may happen if somebody moves the scroll wheel of the mouse over a control
// which does not have the focus)
// 85511 - 29.05.2001 - frank.schoenheit@germany.sun.com
//
// also, it happens when an image control gets a new image by double-clicking it
// #i88458# / 2009-01-12 / frank.schoenheit@sun.com
Reference< XWindow > xControlWindow( _rEvent.Source, UNO_QUERY_THROW );
xControlWindow->setFocus();
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
impl_onModify();
}
//------------------------------------------------------------------------------
void FormController::impl_checkDisposed_throw() const
{
if ( impl_isDisposed_nofail() )
throw DisposedException( OUString(), *const_cast< FormController* >( this ) );
}
//------------------------------------------------------------------------------
void FormController::impl_onModify()
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
{
::osl::MutexGuard aGuard( m_aMutex );
if ( !m_bModified )
m_bModified = sal_True;
}
EventObject aEvt(static_cast<cppu::OWeakObject*>(this));
m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt );
}
//------------------------------------------------------------------------------
void FormController::impl_addFilterRow( const FmFilterRow& _row )
{
m_aFilterRows.push_back( _row );
if ( m_aFilterRows.size() == 1 )
{ // that's the first row ever
OSL_ENSURE( m_nCurrentFilterPosition == -1, "FormController::impl_addFilterRow: inconsistency!" );
m_nCurrentFilterPosition = 0;
}
}
//------------------------------------------------------------------------------
void FormController::impl_appendEmptyFilterRow( ::osl::ClearableMutexGuard& _rClearBeforeNotify )
{
// SYNCHRONIZED -->
impl_addFilterRow( FmFilterRow() );
// notify the listeners
FilterEvent aEvent;
aEvent.Source = *this;
aEvent.DisjunctiveTerm = (sal_Int32)m_aFilterRows.size() - 1;
_rClearBeforeNotify.clear();
// <-- SYNCHRONIZED
m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermAdded, aEvent );
}
//------------------------------------------------------------------------------
sal_Bool FormController::determineLockState() const
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
// a.) in filter mode we are always locked
// b.) if we have no valid model or our model (a result set) is not alive -> we're locked
// c.) if we are inserting everything is OK and we are not locked
// d.) if are not updatable or on invalid position
Reference< XResultSet > xResultSet(m_xModelAsIndex, UNO_QUERY);
if (m_bFiltering || !xResultSet.is() || !isRowSetAlive(xResultSet))
return sal_True;
else
return (m_bCanInsert && m_bCurrentRecordNew) ? sal_False
: xResultSet->isBeforeFirst() || xResultSet->isAfterLast() || xResultSet->rowDeleted() || !m_bCanUpdate;
}
// FocusListener
//------------------------------------------------------------------------------
void FormController::focusGained(const FocusEvent& e) throw( RuntimeException )
{
// SYNCHRONIZED -->
::osl::ClearableMutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_pControlBorderManager->focusGained( e.Source );
Reference< XControl > xControl(e.Source, UNO_QUERY);
if (m_bDBConnection)
{
// do we need to keep the locking of the commit
// we hold the lock as long as the control differs from the current
// otherwise we disabled the lock
m_bCommitLock = m_bCommitLock && (XControl*)xControl.get() != (XControl*)m_xCurrentControl.get();
if (m_bCommitLock)
return;
// when do we have to commit a value to form or a filter
// a.) if the current value is modified
// b.) there must be a current control
// c.) and it must be different from the new focus owning control or
// d.) the focus is moving around (so we have only one control)
if ( ( m_bModified || m_bFiltering )
&& m_xCurrentControl.is()
&& ( ( xControl.get() != m_xCurrentControl.get() )
|| ( ( e.FocusFlags & FocusChangeReason::AROUND )
&& ( m_bCycle || m_bFiltering )
)
)
)
{
// check the old control if the content is ok
#if OSL_DEBUG_LEVEL > 1
Reference< XBoundControl > xLockingTest(m_xCurrentControl, UNO_QUERY);
sal_Bool bControlIsLocked = xLockingTest.is() && xLockingTest->getLock();
OSL_ENSURE(!bControlIsLocked, "FormController::Gained: I'm modified and the current control is locked ? How this ?");
// normalerweise sollte ein gelocktes Control nicht modified sein, also muss wohl mein bModified aus einem anderen Kontext
// gesetzt worden sein, was ich nicht verstehen wuerde ...
#endif
DBG_ASSERT(m_xCurrentControl.is(), "kein CurrentControl gesetzt");
// zunaechst das Control fragen ob es das IFace unterstuetzt
Reference< XBoundComponent > xBound(m_xCurrentControl, UNO_QUERY);
if (!xBound.is() && m_xCurrentControl.is())
xBound = Reference< XBoundComponent > (m_xCurrentControl->getModel(), UNO_QUERY);
// lock if we lose the focus during commit
m_bCommitLock = sal_True;
// Commit nicht erfolgreich, Focus zuruecksetzen
if (xBound.is() && !xBound->commit())
{
// the commit failed and we don't commit again until the current control
// which couldn't be commit gains the focus again
Reference< XWindow > xWindow(m_xCurrentControl, UNO_QUERY);
if (xWindow.is())
xWindow->setFocus();
return;
}
else
{
m_bModified = sal_False;
m_bCommitLock = sal_False;
}
}
if (!m_bFiltering && m_bCycle && (e.FocusFlags & FocusChangeReason::AROUND) && m_xCurrentControl.is())
{
SQLErrorEvent aErrorEvent;
OSL_ENSURE( m_xFormOperations.is(), "FormController::focusGained: hmm?" );
// should have been created in setModel
try
{
if ( e.FocusFlags & FocusChangeReason::FORWARD )
{
if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToNext ) )
m_xFormOperations->execute( FormFeature::MoveToNext );
}
else // backward
{
if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToPrevious ) )
m_xFormOperations->execute( FormFeature::MoveToPrevious );
}
}
catch ( const Exception& )
{
// don't handle this any further. That's an ... admissible error.
DBG_UNHANDLED_EXCEPTION();
}
}
}
// Immer noch ein und dasselbe Control
if ( ( m_xActiveControl == xControl )
&& ( xControl == m_xCurrentControl )
)
{
DBG_ASSERT(m_xCurrentControl.is(), "Kein CurrentControl selektiert");
return;
}
sal_Bool bActivated = !m_xActiveControl.is() && xControl.is();
m_xActiveControl = xControl;
implSetCurrentControl( xControl );
OSL_POSTCOND( m_xCurrentControl.is(), "implSetCurrentControl did nonsense!" );
if ( bActivated )
{
// (asynchronously) call activation handlers
m_aActivationEvent.Call();
// call modify listeners
if ( m_bModified )
m_aModifyListeners.notifyEach( &XModifyListener::modified, EventObject( *this ) );
}
// invalidate all features which depend on the currently focused control
if ( m_bDBConnection && !m_bFiltering )
implInvalidateCurrentControlDependentFeatures();
if ( !m_xCurrentControl.is() )
return;
// Control erhaelt Focus, dann eventuell in den sichtbaren Bereich
Reference< XFormControllerContext > xContext( m_xFormControllerContext );
Reference< XControl > xCurrentControl( m_xCurrentControl );
aGuard.clear();
// <-- SYNCHRONIZED
if ( xContext.is() )
xContext->makeVisible( xCurrentControl );
}
//------------------------------------------------------------------------------
IMPL_LINK( FormController, OnActivated, void*, /**/ )
{
EventObject aEvent;
aEvent.Source = *this;
m_aActivateListeners.notifyEach( &XFormControllerListener::formActivated, aEvent );
return 0L;
}
//------------------------------------------------------------------------------
IMPL_LINK( FormController, OnDeactivated, void*, /**/ )
{
EventObject aEvent;
aEvent.Source = *this;
m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvent );
return 0L;
}
//------------------------------------------------------------------------------
void FormController::focusLost(const FocusEvent& e) throw( RuntimeException )
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
m_pControlBorderManager->focusLost( e.Source );
Reference< XControl > xControl(e.Source, UNO_QUERY);
Reference< XWindowPeer > xNext(e.NextFocus, UNO_QUERY);
Reference< XControl > xNextControl = isInList(xNext);
if (!xNextControl.is())
{
m_xActiveControl = NULL;
m_aDeactivationEvent.Call();
}
}
//--------------------------------------------------------------------
void SAL_CALL FormController::mousePressed( const awt::MouseEvent& /*_rEvent*/ ) throw (RuntimeException)
{
// not interested in
}
//--------------------------------------------------------------------
void SAL_CALL FormController::mouseReleased( const awt::MouseEvent& /*_rEvent*/ ) throw (RuntimeException)
{
// not interested in
}
//--------------------------------------------------------------------
void SAL_CALL FormController::mouseEntered( const awt::MouseEvent& _rEvent ) throw (RuntimeException)
{
m_pControlBorderManager->mouseEntered( _rEvent.Source );
}
//--------------------------------------------------------------------
void SAL_CALL FormController::mouseExited( const awt::MouseEvent& _rEvent ) throw (RuntimeException)
{
m_pControlBorderManager->mouseExited( _rEvent.Source );
}
//--------------------------------------------------------------------
void SAL_CALL FormController::componentValidityChanged( const EventObject& _rSource ) throw (RuntimeException)
{
Reference< XControl > xControl( findControl( m_aControls, Reference< XControlModel >( _rSource.Source, UNO_QUERY ), sal_False, sal_False ) );
Reference< XValidatableFormComponent > xValidatable( _rSource.Source, UNO_QUERY );
OSL_ENSURE( xControl.is() && xValidatable.is(), "FormController::componentValidityChanged: huh?" );
if ( xControl.is() && xValidatable.is() )
m_pControlBorderManager->validityChanged( xControl, xValidatable );
}
//--------------------------------------------------------------------
void FormController::setModel(const Reference< XTabControllerModel > & Model) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
DBG_ASSERT(m_xTabController.is(), "FormController::setModel : invalid aggregate !");
try
{
// disconnect from the old model
if (m_xModelAsIndex.is())
{
if (m_bDBConnection)
{
// we are currently working on the model
EventObject aEvt(m_xModelAsIndex);
unloaded(aEvt);
}
Reference< XLoadable > xForm(m_xModelAsIndex, UNO_QUERY);
if (xForm.is())
xForm->removeLoadListener(this);
Reference< XSQLErrorBroadcaster > xBroadcaster(m_xModelAsIndex, UNO_QUERY);
if (xBroadcaster.is())
xBroadcaster->removeSQLErrorListener(this);
Reference< XDatabaseParameterBroadcaster > xParamBroadcaster(m_xModelAsIndex, UNO_QUERY);
if (xParamBroadcaster.is())
xParamBroadcaster->removeParameterListener(this);
}
disposeAllFeaturesAndDispatchers();
if ( m_xFormOperations.is() )
m_xFormOperations->dispose();
m_xFormOperations.clear();
// set the new model wait for the load event
if (m_xTabController.is())
m_xTabController->setModel(Model);
m_xModelAsIndex = Reference< XIndexAccess > (Model, UNO_QUERY);
m_xModelAsManager = Reference< XEventAttacherManager > (Model, UNO_QUERY);
// only if both ifaces exit, the controller will work successful
if (!m_xModelAsIndex.is() || !m_xModelAsManager.is())
{
m_xModelAsManager = NULL;
m_xModelAsIndex = NULL;
}
if (m_xModelAsIndex.is())
{
// re-create m_xFormOperations
m_xFormOperations = FormOperations::createWithFormController( m_xComponentContext, this );
m_xFormOperations->setFeatureInvalidation( this );
// adding load and ui interaction listeners
Reference< XLoadable > xForm(Model, UNO_QUERY);
if (xForm.is())
xForm->addLoadListener(this);
Reference< XSQLErrorBroadcaster > xBroadcaster(Model, UNO_QUERY);
if (xBroadcaster.is())
xBroadcaster->addSQLErrorListener(this);
Reference< XDatabaseParameterBroadcaster > xParamBroadcaster(Model, UNO_QUERY);
if (xParamBroadcaster.is())
xParamBroadcaster->addParameterListener(this);
// well, is the database already loaded?
// then we have to simulate a load event
Reference< XLoadable > xCursor(m_xModelAsIndex, UNO_QUERY);
if (xCursor.is() && xCursor->isLoaded())
{
EventObject aEvt(xCursor);
loaded(aEvt);
}
Reference< XPropertySet > xModelProps( m_xModelAsIndex, UNO_QUERY );
Reference< XPropertySetInfo > xPropInfo( xModelProps->getPropertySetInfo() );
if ( xPropInfo.is()
&& xPropInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER )
&& xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_FOCUS )
&& xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_MOUSE )
&& xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_INVALID )
)
{
bool bEnableDynamicControlBorder = lcl_shouldUseDynamicControlBorder(
xModelProps.get(), xModelProps->getPropertyValue( FM_PROP_DYNAMIC_CONTROL_BORDER ) );
if ( bEnableDynamicControlBorder )
m_pControlBorderManager->enableDynamicBorderColor();
else
m_pControlBorderManager->disableDynamicBorderColor();
sal_Int32 nColor = 0;
if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_FOCUS ) >>= nColor )
m_pControlBorderManager->setStatusColor( CONTROL_STATUS_FOCUSED, nColor );
if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_MOUSE ) >>= nColor )
m_pControlBorderManager->setStatusColor( CONTROL_STATUS_MOUSE_HOVER, nColor );
if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_INVALID ) >>= nColor )
m_pControlBorderManager->setStatusColor( CONTROL_STATUS_INVALID, nColor );
}
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
//------------------------------------------------------------------------------
Reference< XTabControllerModel > FormController::getModel() throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
DBG_ASSERT(m_xTabController.is(), "FormController::getModel : invalid aggregate !");
if (!m_xTabController.is())
return Reference< XTabControllerModel > ();
return m_xTabController->getModel();
}
//------------------------------------------------------------------------------
void FormController::addToEventAttacher(const Reference< XControl > & xControl)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
OSL_ENSURE( xControl.is(), "FormController::addToEventAttacher: invalid control - how did you reach this?" );
if ( !xControl.is() )
return; /* throw IllegalArgumentException(); */
// anmelden beim Eventattacher
Reference< XFormComponent > xComp(xControl->getModel(), UNO_QUERY);
if (xComp.is() && m_xModelAsIndex.is())
{
// Und die Position des ControlModel darin suchen
sal_uInt32 nPos = m_xModelAsIndex->getCount();
Reference< XFormComponent > xTemp;
for( ; nPos; )
{
m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
if ((XFormComponent*)xComp.get() == (XFormComponent*)xTemp.get())
{
m_xModelAsManager->attach( nPos, xControl, makeAny(xControl) );
break;
}
}
}
}
//------------------------------------------------------------------------------
void FormController::removeFromEventAttacher(const Reference< XControl > & xControl)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
OSL_ENSURE( xControl.is(), "FormController::removeFromEventAttacher: invalid control - how did you reach this?" );
if ( !xControl.is() )
return; /* throw IllegalArgumentException(); */
// abmelden beim Eventattacher
Reference< XFormComponent > xComp(xControl->getModel(), UNO_QUERY);
if ( xComp.is() && m_xModelAsIndex.is() )
{
// Und die Position des ControlModel darin suchen
sal_uInt32 nPos = m_xModelAsIndex->getCount();
Reference< XFormComponent > xTemp;
for( ; nPos; )
{
m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
if ((XFormComponent*)xComp.get() == (XFormComponent*)xTemp.get())
{
m_xModelAsManager->detach( nPos, xControl );
break;
}
}
}
}
//------------------------------------------------------------------------------
void FormController::setContainer(const Reference< XControlContainer > & xContainer) throw( RuntimeException )
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
Reference< XTabControllerModel > xTabModel(getModel());
DBG_ASSERT(xTabModel.is() || !xContainer.is(), "No Model defined");
// if we have a new container we need a model
DBG_ASSERT(m_xTabController.is(), "FormController::setContainer : invalid aggregate !");
::osl::MutexGuard aGuard( m_aMutex );
Reference< XContainer > xCurrentContainer;
if (m_xTabController.is())
xCurrentContainer = Reference< XContainer > (m_xTabController->getContainer(), UNO_QUERY);
if (xCurrentContainer.is())
{
xCurrentContainer->removeContainerListener(this);
if ( m_aTabActivationTimer.IsActive() )
m_aTabActivationTimer.Stop();
// clear the filter map
::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
m_aFilterComponents.clear();
// einsammeln der Controls
const Reference< XControl >* pControls = m_aControls.getConstArray();
const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
while ( pControls != pControlsEnd )
implControlRemoved( *pControls++, true );
// Datenbank spezifische Dinge vornehmen
if (m_bDBConnection && isListeningForChanges())
stopListening();
m_aControls.realloc( 0 );
}
if (m_xTabController.is())
m_xTabController->setContainer(xContainer);
// Welche Controls gehoeren zum Container ?
if (xContainer.is() && xTabModel.is())
{
Sequence< Reference< XControlModel > > aModels = xTabModel->getControlModels();
const Reference< XControlModel > * pModels = aModels.getConstArray();
Sequence< Reference< XControl > > aAllControls = xContainer->getControls();
sal_Int32 nCount = aModels.getLength();
m_aControls = Sequence< Reference< XControl > >( nCount );
Reference< XControl > * pControls = m_aControls.getArray();
// einsammeln der Controls
sal_Int32 i, j;
for (i = 0, j = 0; i < nCount; ++i, ++pModels )
{
Reference< XControl > xControl = findControl( aAllControls, *pModels, sal_False, sal_True );
if ( xControl.is() )
{
pControls[j++] = xControl;
implControlInserted( xControl, true );
}
}
// not every model had an associated control
if (j != i)
m_aControls.realloc(j);
// am Container horchen
Reference< XContainer > xNewContainer(xContainer, UNO_QUERY);
if (xNewContainer.is())
xNewContainer->addContainerListener(this);
// Datenbank spezifische Dinge vornehmen
if (m_bDBConnection)
{
m_bLocked = determineLockState();
setLocks();
if (!isLocked())
startListening();
}
}
// befinden sich die Controls in der richtigen Reihenfolge
m_bControlsSorted = sal_True;
}
//------------------------------------------------------------------------------
Reference< XControlContainer > FormController::getContainer() throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
DBG_ASSERT(m_xTabController.is(), "FormController::getContainer : invalid aggregate !");
if (!m_xTabController.is())
return Reference< XControlContainer > ();
return m_xTabController->getContainer();
}
//------------------------------------------------------------------------------
Sequence< Reference< XControl > > FormController::getControls(void) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
if (!m_bControlsSorted)
{
Reference< XTabControllerModel > xModel = getModel();
if (!xModel.is())
return m_aControls;
Sequence< Reference< XControlModel > > aControlModels = xModel->getControlModels();
const Reference< XControlModel > * pModels = aControlModels.getConstArray();
sal_Int32 nModels = aControlModels.getLength();
Sequence< Reference< XControl > > aNewControls(nModels);
Reference< XControl > * pControls = aNewControls.getArray();
Reference< XControl > xControl;
// Umsortieren der Controls entsprechend der TabReihenfolge
sal_Int32 j = 0;
for (sal_Int32 i = 0; i < nModels; ++i, ++pModels )
{
xControl = findControl( m_aControls, *pModels, sal_True, sal_True );
if ( xControl.is() )
pControls[j++] = xControl;
}
// not every model had an associated control
if ( j != nModels )
aNewControls.realloc( j );
m_aControls = aNewControls;
m_bControlsSorted = sal_True;
}
return m_aControls;
}
//------------------------------------------------------------------------------
void FormController::autoTabOrder() throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
DBG_ASSERT(m_xTabController.is(), "FormController::autoTabOrder : invalid aggregate !");
if (m_xTabController.is())
m_xTabController->autoTabOrder();
}
//------------------------------------------------------------------------------
void FormController::activateTabOrder() throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
DBG_ASSERT(m_xTabController.is(), "FormController::activateTabOrder : invalid aggregate !");
if (m_xTabController.is())
m_xTabController->activateTabOrder();
}
//------------------------------------------------------------------------------
void FormController::setControlLock(const Reference< XControl > & xControl)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
sal_Bool bLocked = isLocked();
// es wird gelockt
// a.) wenn der ganze Datensatz gesperrt ist
// b.) wenn das zugehoerige Feld gespeert ist
Reference< XBoundControl > xBound(xControl, UNO_QUERY);
if (xBound.is() && (( (bLocked && bLocked != xBound->getLock()) ||
!bLocked))) // beim entlocken immer einzelne Felder ueberpr�fen
{
// gibt es eine Datenquelle
Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
{
// wie sieht mit den Properties ReadOnly und Enable aus
sal_Bool bTouch = sal_True;
if (::comphelper::hasProperty(FM_PROP_ENABLED, xSet))
bTouch = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ENABLED));
if (::comphelper::hasProperty(FM_PROP_READONLY, xSet))
bTouch = !::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_READONLY));
if (bTouch)
{
Reference< XPropertySet > xField;
xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
if (xField.is())
{
if (bLocked)
xBound->setLock(bLocked);
else
{
try
{
Any aVal = xField->getPropertyValue(FM_PROP_ISREADONLY);
if (aVal.hasValue() && ::comphelper::getBOOL(aVal))
xBound->setLock(sal_True);
else
xBound->setLock(bLocked);
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
}
}
}
}
}
//------------------------------------------------------------------------------
void FormController::setLocks()
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
// alle Controls, die mit einer Datenquelle verbunden sind locken/unlocken
const Reference< XControl >* pControls = m_aControls.getConstArray();
const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
while ( pControls != pControlsEnd )
setControlLock( *pControls++ );
}
//------------------------------------------------------------------------------
namespace
{
bool lcl_shouldListenForModifications( const Reference< XControl >& _rxControl, const Reference< XPropertyChangeListener >& _rxBoundFieldListener )
{
bool bShould = false;
Reference< XBoundComponent > xBound( _rxControl, UNO_QUERY );
if ( xBound.is() )
{
bShould = true;
}
else if ( _rxControl.is() )
{
Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
if ( xModelProps.is() && ::comphelper::hasProperty( FM_PROP_BOUNDFIELD, xModelProps ) )
{
Reference< XPropertySet > xField;
xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
bShould = xField.is();
if ( !bShould && _rxBoundFieldListener.is() )
xModelProps->addPropertyChangeListener( FM_PROP_BOUNDFIELD, _rxBoundFieldListener );
}
}
return bShould;
}
}
//------------------------------------------------------------------------------
void FormController::startControlModifyListening(const Reference< XControl > & xControl)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
bool bModifyListening = lcl_shouldListenForModifications( xControl, this );
// artificial while
while ( bModifyListening )
{
Reference< XModifyBroadcaster > xMod(xControl, UNO_QUERY);
if (xMod.is())
{
xMod->addModifyListener(this);
break;
}
// alle die Text um vorzeitig ein modified zu erkennen
Reference< XTextComponent > xText(xControl, UNO_QUERY);
if (xText.is())
{
xText->addTextListener(this);
break;
}
Reference< XCheckBox > xBox(xControl, UNO_QUERY);
if (xBox.is())
{
xBox->addItemListener(this);
break;
}
Reference< XComboBox > xCbBox(xControl, UNO_QUERY);
if (xCbBox.is())
{
xCbBox->addItemListener(this);
break;
}
Reference< XListBox > xListBox(xControl, UNO_QUERY);
if (xListBox.is())
{
xListBox->addItemListener(this);
break;
}
break;
}
}
//------------------------------------------------------------------------------
void FormController::stopControlModifyListening(const Reference< XControl > & xControl)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
bool bModifyListening = lcl_shouldListenForModifications( xControl, NULL );
// kuenstliches while
while (bModifyListening)
{
Reference< XModifyBroadcaster > xMod(xControl, UNO_QUERY);
if (xMod.is())
{
xMod->removeModifyListener(this);
break;
}
// alle die Text um vorzeitig ein modified zu erkennen
Reference< XTextComponent > xText(xControl, UNO_QUERY);
if (xText.is())
{
xText->removeTextListener(this);
break;
}
Reference< XCheckBox > xBox(xControl, UNO_QUERY);
if (xBox.is())
{
xBox->removeItemListener(this);
break;
}
Reference< XComboBox > xCbBox(xControl, UNO_QUERY);
if (xCbBox.is())
{
xCbBox->removeItemListener(this);
break;
}
Reference< XListBox > xListBox(xControl, UNO_QUERY);
if (xListBox.is())
{
xListBox->removeItemListener(this);
break;
}
break;
}
}
//------------------------------------------------------------------------------
void FormController::startListening()
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
m_bModified = sal_False;
// jetzt anmelden bei gebundenen feldern
const Reference< XControl >* pControls = m_aControls.getConstArray();
const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
while ( pControls != pControlsEnd )
startControlModifyListening( *pControls++ );
}
//------------------------------------------------------------------------------
void FormController::stopListening()
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
m_bModified = sal_False;
// jetzt anmelden bei gebundenen feldern
const Reference< XControl >* pControls = m_aControls.getConstArray();
const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
while ( pControls != pControlsEnd )
stopControlModifyListening( *pControls++ );
}
//------------------------------------------------------------------------------
Reference< XControl > FormController::findControl(Sequence< Reference< XControl > >& _rControls, const Reference< XControlModel > & xCtrlModel ,sal_Bool _bRemove,sal_Bool _bOverWrite) const
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
DBG_ASSERT( xCtrlModel.is(), "findControl - welches ?!" );
Reference< XControl >* pControls = _rControls.getArray();
Reference< XControlModel > xModel;
for ( sal_Int32 i = 0, nCount = _rControls.getLength(); i < nCount; ++i, ++pControls )
{
if ( pControls->is() )
{
xModel = (*pControls)->getModel();
if ( xModel.get() == xCtrlModel.get() )
{
Reference< XControl > xControl( *pControls );
if ( _bRemove )
::comphelper::removeElementAt( _rControls, i );
else if ( _bOverWrite )
pControls->clear();
return xControl;
}
}
}
return Reference< XControl > ();
}
//------------------------------------------------------------------------------
void FormController::implControlInserted( const Reference< XControl>& _rxControl, bool _bAddToEventAttacher )
{
Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
if ( xWindow.is() )
{
xWindow->addFocusListener( this );
xWindow->addMouseListener( this );
if ( _bAddToEventAttacher )
addToEventAttacher( _rxControl );
}
// add a dispatch interceptor to the control (if supported)
Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY );
if ( xInterception.is() )
createInterceptor( xInterception );
if ( _rxControl.is() )
{
Reference< XControlModel > xModel( _rxControl->getModel() );
// we want to know about the reset of the model of our controls
// (for correctly resetting m_bModified)
Reference< XReset > xReset( xModel, UNO_QUERY );
if ( xReset.is() )
xReset->addResetListener( this );
// and we want to know about the validity, to visually indicate it
Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
if ( xValidatable.is() )
{
xValidatable->addFormComponentValidityListener( this );
m_pControlBorderManager->validityChanged( _rxControl, xValidatable );
}
}
}
//------------------------------------------------------------------------------
void FormController::implControlRemoved( const Reference< XControl>& _rxControl, bool _bRemoveFromEventAttacher )
{
Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
if ( xWindow.is() )
{
xWindow->removeFocusListener( this );
xWindow->removeMouseListener( this );
if ( _bRemoveFromEventAttacher )
removeFromEventAttacher( _rxControl );
}
Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY);
if ( xInterception.is() )
deleteInterceptor( xInterception );
if ( _rxControl.is() )
{
Reference< XControlModel > xModel( _rxControl->getModel() );
Reference< XReset > xReset( xModel, UNO_QUERY );
if ( xReset.is() )
xReset->removeResetListener( this );
Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
if ( xValidatable.is() )
xValidatable->removeFormComponentValidityListener( this );
}
}
//------------------------------------------------------------------------------
void FormController::implSetCurrentControl( const Reference< XControl >& _rxControl )
{
if ( m_xCurrentControl.get() == _rxControl.get() )
return;
Reference< XGridControl > xGridControl( m_xCurrentControl, UNO_QUERY );
if ( xGridControl.is() )
xGridControl->removeGridControlListener( this );
m_xCurrentControl = _rxControl;
xGridControl.set( m_xCurrentControl, UNO_QUERY );
if ( xGridControl.is() )
xGridControl->addGridControlListener( this );
}
//------------------------------------------------------------------------------
void FormController::insertControl(const Reference< XControl > & xControl)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
m_bControlsSorted = sal_False;
m_aControls.realloc(m_aControls.getLength() + 1);
m_aControls.getArray()[m_aControls.getLength() - 1] = xControl;
if ( m_pColumnInfoCache.get() )
m_pColumnInfoCache->deinitializeControls();
implControlInserted( xControl, m_bAttachEvents );
if (m_bDBConnection && !m_bFiltering)
setControlLock(xControl);
if (isListeningForChanges() && m_bAttachEvents)
startControlModifyListening( xControl );
}
//------------------------------------------------------------------------------
void FormController::removeControl(const Reference< XControl > & xControl)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
const Reference< XControl >* pControls = m_aControls.getConstArray();
const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
while ( pControls != pControlsEnd )
{
if ( xControl.get() == (*pControls++).get() )
{
::comphelper::removeElementAt( m_aControls, pControls - m_aControls.getConstArray() - 1 );
break;
}
}
FilterComponents::iterator componentPos = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
if ( componentPos != m_aFilterComponents.end() )
m_aFilterComponents.erase( componentPos );
implControlRemoved( xControl, m_bDetachEvents );
if ( isListeningForChanges() && m_bDetachEvents )
stopControlModifyListening( xControl );
}
// XLoadListener
//------------------------------------------------------------------------------
void FormController::loaded(const EventObject& rEvent) throw( RuntimeException )
{
OSL_ENSURE( rEvent.Source == m_xModelAsIndex, "FormController::loaded: where did this come from?" );
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
::osl::MutexGuard aGuard( m_aMutex );
Reference< XRowSet > xForm(rEvent.Source, UNO_QUERY);
// do we have a connected data source
OStaticDataAccessTools aStaticTools;
if (xForm.is() && aStaticTools.getRowSetConnection(xForm).is())
{
Reference< XPropertySet > xSet(xForm, UNO_QUERY);
if (xSet.is())
{
Any aVal = xSet->getPropertyValue(FM_PROP_CYCLE);
sal_Int32 aVal2 = 0;
::cppu::enum2int(aVal2,aVal);
m_bCycle = !aVal.hasValue() || aVal2 == TabulatorCycle_RECORDS;
m_bCanUpdate = aStaticTools.canUpdate(xSet);
m_bCanInsert = aStaticTools.canInsert(xSet);
m_bCurrentRecordModified = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED));
m_bCurrentRecordNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW));
startFormListening( xSet, sal_False );
// set the locks for the current controls
if (getContainer().is())
{
m_aLoadEvent.Call();
}
}
else
{
m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
m_bCurrentRecordModified = sal_False;
m_bCurrentRecordNew = sal_False;
m_bLocked = sal_False;
}
m_bDBConnection = sal_True;
}
else
{
m_bDBConnection = sal_False;
m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
m_bCurrentRecordModified = sal_False;
m_bCurrentRecordNew = sal_False;
m_bLocked = sal_False;
}
Reference< XColumnsSupplier > xFormColumns( xForm, UNO_QUERY );
m_pColumnInfoCache.reset( xFormColumns.is() ? new ColumnInfoCache( xFormColumns ) : NULL );
updateAllDispatchers();
}
//------------------------------------------------------------------------------
void FormController::updateAllDispatchers() const
{
::std::for_each(
m_aFeatureDispatchers.begin(),
m_aFeatureDispatchers.end(),
::o3tl::compose1(
UpdateAllListeners(),
::o3tl::select2nd< DispatcherContainer::value_type >()
)
);
}
//------------------------------------------------------------------------------
IMPL_LINK_NOARG(FormController, OnLoad)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
m_bLocked = determineLockState();
setLocks();
if (!m_bLocked)
startListening();
// just one exception toggle the auto values
if (m_bCurrentRecordNew)
toggleAutoFields(sal_True);
return 1L;
}
//------------------------------------------------------------------------------
void FormController::unloaded(const EventObject& /*rEvent*/) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
updateAllDispatchers();
}
//------------------------------------------------------------------------------
void FormController::reloading(const EventObject& /*aEvent*/) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
// do the same like in unloading
// just one exception toggle the auto values
m_aToggleEvent.CancelPendingCall();
unload();
}
//------------------------------------------------------------------------------
void FormController::reloaded(const EventObject& aEvent) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
loaded(aEvent);
}
//------------------------------------------------------------------------------
void FormController::unloading(const EventObject& /*aEvent*/) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
unload();
}
//------------------------------------------------------------------------------
void FormController::unload() throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aLoadEvent.CancelPendingCall();
// be sure not to have autofields
if (m_bCurrentRecordNew)
toggleAutoFields(sal_False);
// remove bound field listing again
removeBoundFieldListener();
if (m_bDBConnection && isListeningForChanges())
stopListening();
Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
if ( m_bDBConnection && xSet.is() )
stopFormListening( xSet, sal_False );
m_bDBConnection = sal_False;
m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
m_bCurrentRecordModified = m_bCurrentRecordNew = m_bLocked = sal_False;
m_pColumnInfoCache.reset( NULL );
}
// -----------------------------------------------------------------------------
void FormController::removeBoundFieldListener()
{
const Reference< XControl >* pControls = m_aControls.getConstArray();
const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
while ( pControls != pControlsEnd )
{
Reference< XPropertySet > xProp( *pControls++, UNO_QUERY );
if ( xProp.is() )
xProp->removePropertyChangeListener( FM_PROP_BOUNDFIELD, this );
}
}
//------------------------------------------------------------------------------
void FormController::startFormListening( const Reference< XPropertySet >& _rxForm, sal_Bool _bPropertiesOnly )
{
try
{
if ( m_bCanInsert || m_bCanUpdate ) // form can be modified
{
_rxForm->addPropertyChangeListener( FM_PROP_ISNEW, this );
_rxForm->addPropertyChangeListener( FM_PROP_ISMODIFIED, this );
if ( !_bPropertiesOnly )
{
// set the Listener for UI interaction
Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
if ( xApprove.is() )
xApprove->addRowSetApproveListener( this );
// listener for row set changes
Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
if ( xRowSet.is() )
xRowSet->addRowSetListener( this );
}
}
Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER ) )
_rxForm->addPropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER, this );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
//------------------------------------------------------------------------------
void FormController::stopFormListening( const Reference< XPropertySet >& _rxForm, sal_Bool _bPropertiesOnly )
{
try
{
if ( m_bCanInsert || m_bCanUpdate )
{
_rxForm->removePropertyChangeListener( FM_PROP_ISNEW, this );
_rxForm->removePropertyChangeListener( FM_PROP_ISMODIFIED, this );
if ( !_bPropertiesOnly )
{
Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
if (xApprove.is())
xApprove->removeRowSetApproveListener(this);
Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
if ( xRowSet.is() )
xRowSet->removeRowSetListener( this );
}
}
Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER ) )
_rxForm->removePropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER, this );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
// com::sun::star::sdbc::XRowSetListener
//------------------------------------------------------------------------------
void FormController::cursorMoved(const EventObject& /*event*/) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
// toggle the locking ?
if (m_bLocked != determineLockState())
{
m_bLocked = !m_bLocked;
setLocks();
if (isListeningForChanges())
startListening();
else
stopListening();
}
// neither the current control nor the current record are modified anymore
m_bCurrentRecordModified = m_bModified = sal_False;
}
//------------------------------------------------------------------------------
void FormController::rowChanged(const EventObject& /*event*/) throw( RuntimeException )
{
// not interested in ...
}
//------------------------------------------------------------------------------
void FormController::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException )
{
// not interested in ...
}
// XContainerListener
//------------------------------------------------------------------------------
void SAL_CALL FormController::elementInserted(const ContainerEvent& evt) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
Reference< XControl > xControl( evt.Element, UNO_QUERY );
if ( !xControl.is() )
return;
Reference< XFormComponent > xModel(xControl->getModel(), UNO_QUERY);
if (xModel.is() && m_xModelAsIndex == xModel->getParent())
{
insertControl(xControl);
if ( m_aTabActivationTimer.IsActive() )
m_aTabActivationTimer.Stop();
m_aTabActivationTimer.Start();
}
// are we in filtermode and a XModeSelector has inserted an element
else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
{
xModel = Reference< XFormComponent > (evt.Source, UNO_QUERY);
if (xModel.is() && m_xModelAsIndex == xModel->getParent())
{
Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
{
// does the model use a bound field ?
Reference< XPropertySet > xField;
xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
Reference< XTextComponent > xText(xControl, UNO_QUERY);
// may we filter the field?
if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE, xField) &&
::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE)))
{
m_aFilterComponents.push_back( xText );
xText->addTextListener( this );
}
}
}
}
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::elementReplaced(const ContainerEvent& evt) throw( RuntimeException )
{
// simulate an elementRemoved
ContainerEvent aRemoveEvent( evt );
aRemoveEvent.Element = evt.ReplacedElement;
aRemoveEvent.ReplacedElement = Any();
elementRemoved( aRemoveEvent );
// simulate an elementInserted
ContainerEvent aInsertEvent( evt );
aInsertEvent.ReplacedElement = Any();
elementInserted( aInsertEvent );
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::elementRemoved(const ContainerEvent& evt) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
Reference< XControl > xControl;
evt.Element >>= xControl;
if (!xControl.is())
return;
Reference< XFormComponent > xModel(xControl->getModel(), UNO_QUERY);
if (xModel.is() && m_xModelAsIndex == xModel->getParent())
{
removeControl(xControl);
// TabOrder nicht neu berechnen, da das intern schon funktionieren mu�!
}
// are we in filtermode and a XModeSelector has inserted an element
else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
{
FilterComponents::iterator componentPos = ::std::find(
m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
if ( componentPos != m_aFilterComponents.end() )
m_aFilterComponents.erase( componentPos );
}
}
//------------------------------------------------------------------------------
Reference< XControl > FormController::isInList(const Reference< XWindowPeer > & xPeer) const
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
const Reference< XControl >* pControls = m_aControls.getConstArray();
sal_uInt32 nCtrls = m_aControls.getLength();
for ( sal_uInt32 n = 0; n < nCtrls && xPeer.is(); ++n, ++pControls )
{
if ( pControls->is() )
{
Reference< XVclWindowPeer > xCtrlPeer( (*pControls)->getPeer(), UNO_QUERY);
if ( ( xCtrlPeer.get() == xPeer.get() ) || xCtrlPeer->isChild( xPeer ) )
return *pControls;
}
}
return Reference< XControl > ();
}
//------------------------------------------------------------------------------
void FormController::activateFirst() throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
DBG_ASSERT(m_xTabController.is(), "FormController::activateFirst : invalid aggregate !");
if (m_xTabController.is())
m_xTabController->activateFirst();
}
//------------------------------------------------------------------------------
void FormController::activateLast() throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
DBG_ASSERT(m_xTabController.is(), "FormController::activateLast : invalid aggregate !");
if (m_xTabController.is())
m_xTabController->activateLast();
}
// XFormController
//------------------------------------------------------------------------------
Reference< XFormOperations > SAL_CALL FormController::getFormOperations() throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
return m_xFormOperations;
}
//------------------------------------------------------------------------------
Reference< XControl> SAL_CALL FormController::getCurrentControl(void) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
return m_xCurrentControl;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::addActivateListener(const Reference< XFormControllerListener > & l) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aActivateListeners.addInterface(l);
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeActivateListener(const Reference< XFormControllerListener > & l) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aActivateListeners.removeInterface(l);
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::addChildController( const Reference< XFormController >& _ChildController ) throw( RuntimeException, IllegalArgumentException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
if ( !_ChildController.is() )
throw IllegalArgumentException( OUString(), *this, 1 );
// TODO: (localized) error message
// the parent of our (to-be-)child must be our own model
Reference< XFormComponent > xFormOfChild( _ChildController->getModel(), UNO_QUERY );
if ( !xFormOfChild.is() )
throw IllegalArgumentException( OUString(), *this, 1 );
// TODO: (localized) error message
if ( xFormOfChild->getParent() != m_xModelAsIndex )
throw IllegalArgumentException( OUString(), *this, 1 );
// TODO: (localized) error message
m_aChildren.push_back( _ChildController );
_ChildController->setParent( *this );
// search the position of the model within the form
sal_uInt32 nPos = m_xModelAsIndex->getCount();
Reference< XFormComponent > xTemp;
for( ; nPos; )
{
m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
if ( xFormOfChild == xTemp )
{
m_xModelAsManager->attach( nPos, _ChildController, makeAny( _ChildController) );
break;
}
}
}
//------------------------------------------------------------------------------
Reference< XFormControllerContext > SAL_CALL FormController::getContext() throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
return m_xFormControllerContext;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::setContext( const Reference< XFormControllerContext >& _context ) throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_xFormControllerContext = _context;
}
//------------------------------------------------------------------------------
Reference< XInteractionHandler > SAL_CALL FormController::getInteractionHandler() throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
return m_xInteractionHandler;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::setInteractionHandler( const Reference< XInteractionHandler >& _interactionHandler ) throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_xInteractionHandler = _interactionHandler;
}
//------------------------------------------------------------------------------
void FormController::setFilter(::std::vector<FmFieldInfo>& rFieldInfos)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
// create the composer
Reference< XRowSet > xForm(m_xModelAsIndex, UNO_QUERY);
Reference< XConnection > xConnection(OStaticDataAccessTools().getRowSetConnection(xForm));
if (xForm.is())
{
try
{
Reference< XMultiServiceFactory > xFactory( xConnection, UNO_QUERY_THROW );
m_xComposer.set(
xFactory->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"),
UNO_QUERY_THROW );
Reference< XPropertySet > xSet( xForm, UNO_QUERY );
OUString sStatement = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_ACTIVECOMMAND ) );
OUString sFilter = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_FILTER ) );
m_xComposer->setElementaryQuery( sStatement );
m_xComposer->setFilter( sFilter );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
if (m_xComposer.is())
{
Sequence < PropertyValue> aLevel;
Sequence< Sequence < PropertyValue > > aFilterRows = m_xComposer->getStructuredFilter();
// ok, we receive the list of filters as sequence of fieldnames, value
// now we have to transform the fieldname into UI names, that could be a label of the field or
// a aliasname or the fieldname itself
// first adjust the field names if necessary
Reference< XNameAccess > xQueryColumns =
Reference< XColumnsSupplier >( m_xComposer, UNO_QUERY_THROW )->getColumns();
for (::std::vector<FmFieldInfo>::iterator iter = rFieldInfos.begin();
iter != rFieldInfos.end(); ++iter)
{
if ( xQueryColumns->hasByName((*iter).aFieldName) )
{
if ( (xQueryColumns->getByName((*iter).aFieldName) >>= (*iter).xField) && (*iter).xField.is() )
(*iter).xField->getPropertyValue(FM_PROP_REALNAME) >>= (*iter).aFieldName;
}
}
Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
// now transfer the filters into Value/TextComponent pairs
::comphelper::UStringMixEqual aCompare(xMetaData->storesMixedCaseQuotedIdentifiers());
// need to parse criteria localized
OStaticDataAccessTools aStaticTools;
Reference< XNumberFormatsSupplier> xFormatSupplier( aStaticTools.getNumberFormats(xConnection, sal_True));
Reference< XNumberFormatter> xFormatter = NumberFormatter::create(m_xComponentContext);
xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
Locale aAppLocale = Application::GetSettings().GetUILanguageTag().getLocale();
const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetUILocaleDataWrapper() );
/* FIXME: casting this to sal_Char is plain wrong and of course only
* works for ASCII separators, but
* xParseNode->parseNodeToPredicateStr() expects a sal_Char. Fix it
* there. */
sal_Char cDecimalSeparator = (sal_Char)rLocaleWrapper.getNumDecimalSep()[0];
SAL_WARN_IF( (sal_Unicode)cDecimalSeparator != rLocaleWrapper.getNumDecimalSep()[0],
"svx.form", "FormController::setFilter: wrong cast of decimal separator to sal_Char!");
// retrieving the filter
const Sequence < PropertyValue >* pRow = aFilterRows.getConstArray();
for (sal_Int32 i = 0, nLen = aFilterRows.getLength(); i < nLen; ++i)
{
FmFilterRow aRow;
// search a field for the given name
const PropertyValue* pRefValues = pRow[i].getConstArray();
for (sal_Int32 j = 0, nLen1 = pRow[i].getLength(); j < nLen1; j++)
{
// look for the text component
Reference< XPropertySet > xField;
try
{
Reference< XPropertySet > xSet;
OUString aRealName;
// first look with the given name
if (xQueryColumns->hasByName(pRefValues[j].Name))
{
xQueryColumns->getByName(pRefValues[j].Name) >>= xSet;
// get the RealName
xSet->getPropertyValue("RealName") >>= aRealName;
// compare the condition field name and the RealName
if (aCompare(aRealName, pRefValues[j].Name))
xField = xSet;
}
if (!xField.is())
{
// no we have to check every column to find the realname
Reference< XIndexAccess > xColumnsByIndex(xQueryColumns, UNO_QUERY);
for (sal_Int32 n = 0, nCount = xColumnsByIndex->getCount(); n < nCount; n++)
{
xColumnsByIndex->getByIndex(n) >>= xSet;
xSet->getPropertyValue("RealName") >>= aRealName;
if (aCompare(aRealName, pRefValues[j].Name))
{
// get the column by its alias
xField = xSet;
break;
}
}
}
if (!xField.is())
continue;
}
catch (const Exception&)
{
continue;
}
// find the text component
for (::std::vector<FmFieldInfo>::iterator iter = rFieldInfos.begin();
iter != rFieldInfos.end(); ++iter)
{
// we found the field so insert a new entry to the filter row
if ((*iter).xField == xField)
{
// do we already have the control ?
if (aRow.find((*iter).xText) != aRow.end())
{
OUString aCompText = aRow[(*iter).xText];
aCompText += OUString(" ");
OString aVal = m_xParser->getContext().getIntlKeywordAscii(IParseContext::KEY_AND);
aCompText += OUString(aVal.getStr(),aVal.getLength(),RTL_TEXTENCODING_ASCII_US);
aCompText += OUString(" ");
aCompText += ::comphelper::getString(pRefValues[j].Value);
aRow[(*iter).xText] = aCompText;
}
else
{
OUString sPredicate,sErrorMsg;
pRefValues[j].Value >>= sPredicate;
::rtl::Reference< ISQLParseNode > xParseNode = predicateTree(sErrorMsg, sPredicate, xFormatter, xField);
if ( xParseNode.is() )
{
OUString sCriteria;
xParseNode->parseNodeToPredicateStr( sCriteria
,xConnection
,xFormatter
,xField
,OUString()
,aAppLocale
,cDecimalSeparator
,getParseContext());
aRow[(*iter).xText] = sCriteria;
}
}
}
}
}
if (aRow.empty())
continue;
impl_addFilterRow( aRow );
}
}
// now set the filter controls
for ( ::std::vector<FmFieldInfo>::iterator field = rFieldInfos.begin();
field != rFieldInfos.end();
++field
)
{
m_aFilterComponents.push_back( field->xText );
}
}
//------------------------------------------------------------------------------
void FormController::startFiltering()
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
OStaticDataAccessTools aStaticTools;
Reference< XConnection > xConnection( aStaticTools.getRowSetConnection( Reference< XRowSet >( m_xModelAsIndex, UNO_QUERY ) ) );
if ( !xConnection.is() )
// nothing to do - can't filter a form which is not connected
return;
// stop listening for controls
if (isListeningForChanges())
stopListening();
m_bFiltering = sal_True;
// as we don't want new controls to be attached to the scripting environment
// we change attach flags
m_bAttachEvents = sal_False;
// Austauschen der Kontrols fuer das aktuelle Formular
Sequence< Reference< XControl > > aControlsCopy( m_aControls );
const Reference< XControl >* pControls = aControlsCopy.getConstArray();
sal_Int32 nControlCount = aControlsCopy.getLength();
// the control we have to activate after replacement
Reference< XDatabaseMetaData > xMetaData(xConnection->getMetaData());
Reference< XNumberFormatsSupplier > xFormatSupplier = aStaticTools.getNumberFormats(xConnection, sal_True);
Reference< XNumberFormatter > xFormatter = NumberFormatter::create(m_xComponentContext);
xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
// structure for storing the field info
::std::vector<FmFieldInfo> aFieldInfos;
for (sal_Int32 i = nControlCount; i > 0;)
{
Reference< XControl > xControl = pControls[--i];
if (xControl.is())
{
// no events for the control anymore
removeFromEventAttacher(xControl);
// do we have a mode selector
Reference< XModeSelector > xSelector(xControl, UNO_QUERY);
if (xSelector.is())
{
xSelector->setMode( OUString( "FilterMode" ) );
// listening for new controls of the selector
Reference< XContainer > xContainer(xSelector, UNO_QUERY);
if (xContainer.is())
xContainer->addContainerListener(this);
Reference< XEnumerationAccess > xElementAccess(xSelector, UNO_QUERY);
if (xElementAccess.is())
{
Reference< XEnumeration > xEnumeration(xElementAccess->createEnumeration());
Reference< XControl > xSubControl;
while (xEnumeration->hasMoreElements())
{
xEnumeration->nextElement() >>= xSubControl;
if (xSubControl.is())
{
Reference< XPropertySet > xSet(xSubControl->getModel(), UNO_QUERY);
if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
{
// does the model use a bound field ?
Reference< XPropertySet > xField;
xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
Reference< XTextComponent > xText(xSubControl, UNO_QUERY);
// may we filter the field?
if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE, xField) &&
::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE)))
{
aFieldInfos.push_back(FmFieldInfo(xField, xText));
xText->addTextListener(this);
}
}
}
}
}
continue;
}
Reference< XPropertySet > xModel( xControl->getModel(), UNO_QUERY );
if (xModel.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xModel))
{
// does the model use a bound field ?
Any aVal = xModel->getPropertyValue(FM_PROP_BOUNDFIELD);
Reference< XPropertySet > xField;
aVal >>= xField;
// may we filter the field?
if ( xField.is()
&& ::comphelper::hasProperty( FM_PROP_SEARCHABLE, xField )
&& ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE ) )
)
{
// create a filter control
Reference< XControl > xFilterControl = form::control::FilterControl::createWithFormat(
m_xComponentContext,
VCLUnoHelper::GetInterface( getDialogParentWindow() ),
xFormatter,
xModel);
if ( replaceControl( xControl, xFilterControl ) )
{
Reference< XTextComponent > xFilterText( xFilterControl, UNO_QUERY );
aFieldInfos.push_back( FmFieldInfo( xField, xFilterText ) );
xFilterText->addTextListener(this);
}
}
}
else
{
// abmelden vom EventManager
}
}
}
// we have all filter controls now, so the next step is to read the filters from the form
// resolve all aliases and set the current filter to the according structure
setFilter(aFieldInfos);
Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
if ( xSet.is() )
stopFormListening( xSet, sal_True );
impl_setTextOnAllFilter_throw();
// lock all controls which are not used for filtering
m_bLocked = determineLockState();
setLocks();
m_bAttachEvents = sal_True;
}
//------------------------------------------------------------------------------
void FormController::stopFiltering()
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
if ( !m_bFiltering ) // #104693# OJ
{ // nothing to do
return;
}
m_bFiltering = sal_False;
m_bDetachEvents = sal_False;
::comphelper::disposeComponent(m_xComposer);
// Austauschen der Kontrols fuer das aktuelle Formular
Sequence< Reference< XControl > > aControlsCopy( m_aControls );
const Reference< XControl > * pControls = aControlsCopy.getConstArray();
sal_Int32 nControlCount = aControlsCopy.getLength();
// clear the filter control map
::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
m_aFilterComponents.clear();
for ( sal_Int32 i = nControlCount; i > 0; )
{
Reference< XControl > xControl = pControls[--i];
if (xControl.is())
{
// now enable eventhandling again
addToEventAttacher(xControl);
Reference< XModeSelector > xSelector(xControl, UNO_QUERY);
if (xSelector.is())
{
xSelector->setMode( OUString( "DataMode" ) );
// listening for new controls of the selector
Reference< XContainer > xContainer(xSelector, UNO_QUERY);
if (xContainer.is())
xContainer->removeContainerListener(this);
continue;
}
Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
{
// does the model use a bound field ?
Reference< XPropertySet > xField;
xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
// may we filter the field?
if ( xField.is()
&& ::comphelper::hasProperty( FM_PROP_SEARCHABLE, xField )
&& ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE ) )
)
{
OUString sServiceName;
OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName );
Reference< XControl > xNewControl( m_xComponentContext->getServiceManager()->createInstanceWithContext( sServiceName, m_xComponentContext ), UNO_QUERY );
replaceControl( xControl, xNewControl );
}
}
}
}
Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
if ( xSet.is() )
startFormListening( xSet, sal_True );
m_bDetachEvents = sal_True;
m_aFilterRows.clear();
m_nCurrentFilterPosition = -1;
// release the locks if possible
// lock all controls which are not used for filtering
m_bLocked = determineLockState();
setLocks();
// restart listening for control modifications
if (isListeningForChanges())
startListening();
}
// XModeSelector
//------------------------------------------------------------------------------
void FormController::setMode(const OUString& Mode) throw( NoSupportException, RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
if (!supportsMode(Mode))
throw NoSupportException();
if (Mode == m_aMode)
return;
m_aMode = Mode;
if ( Mode == "FilterMode" )
startFiltering();
else
stopFiltering();
for (FmFormControllers::const_iterator i = m_aChildren.begin();
i != m_aChildren.end(); ++i)
{
Reference< XModeSelector > xMode(*i, UNO_QUERY);
if ( xMode.is() )
xMode->setMode(Mode);
}
}
//------------------------------------------------------------------------------
OUString SAL_CALL FormController::getMode(void) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
return m_aMode;
}
//------------------------------------------------------------------------------
Sequence< OUString > SAL_CALL FormController::getSupportedModes(void) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
static Sequence< OUString > aModes;
if (!aModes.getLength())
{
aModes.realloc(2);
OUString* pModes = aModes.getArray();
pModes[0] = OUString( "DataMode" );
pModes[1] = OUString( "FilterMode" );
}
return aModes;
}
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::supportsMode(const OUString& Mode) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
Sequence< OUString > aModes(getSupportedModes());
const OUString* pModes = aModes.getConstArray();
for (sal_Int32 i = aModes.getLength(); i > 0; )
{
if (pModes[--i] == Mode)
return sal_True;
}
return sal_False;
}
//------------------------------------------------------------------------------
Window* FormController::getDialogParentWindow()
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
Window* pParentWindow = NULL;
try
{
Reference< XControl > xContainerControl( getContainer(), UNO_QUERY_THROW );
Reference< XWindowPeer > xContainerPeer( xContainerControl->getPeer(), UNO_QUERY_THROW );
pParentWindow = VCLUnoHelper::GetWindow( xContainerPeer );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
return pParentWindow;
}
//------------------------------------------------------------------------------
bool FormController::checkFormComponentValidity( OUString& /* [out] */ _rFirstInvalidityExplanation, Reference< XControlModel >& /* [out] */ _rxFirstInvalidModel ) SAL_THROW(())
{
try
{
Reference< XEnumerationAccess > xControlEnumAcc( getModel(), UNO_QUERY );
Reference< XEnumeration > xControlEnumeration;
if ( xControlEnumAcc.is() )
xControlEnumeration = xControlEnumAcc->createEnumeration();
OSL_ENSURE( xControlEnumeration.is(), "FormController::checkFormComponentValidity: cannot enumerate the controls!" );
if ( !xControlEnumeration.is() )
// assume all valid
return true;
Reference< XValidatableFormComponent > xValidatable;
while ( xControlEnumeration->hasMoreElements() )
{
if ( !( xControlEnumeration->nextElement() >>= xValidatable ) )
// control does not support validation
continue;
if ( xValidatable->isValid() )
continue;
Reference< XValidator > xValidator( xValidatable->getValidator() );
OSL_ENSURE( xValidator.is(), "FormController::checkFormComponentValidity: invalid, but no validator?" );
if ( !xValidator.is() )
// this violates the interface definition of css.form.validation.XValidatableFormComponent ...
continue;
_rFirstInvalidityExplanation = xValidator->explainInvalid( xValidatable->getCurrentValue() );
_rxFirstInvalidModel = _rxFirstInvalidModel.query( xValidatable );
return false;
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
return true;
}
//------------------------------------------------------------------------------
Reference< XControl > FormController::locateControl( const Reference< XControlModel >& _rxModel ) SAL_THROW(())
{
try
{
Sequence< Reference< XControl > > aControls( getControls() );
const Reference< XControl >* pControls = aControls.getConstArray();
const Reference< XControl >* pControlsEnd = aControls.getConstArray() + aControls.getLength();
for ( ; pControls != pControlsEnd; ++pControls )
{
OSL_ENSURE( pControls->is(), "FormController::locateControl: NULL-control?" );
if ( pControls->is() )
{
if ( ( *pControls)->getModel() == _rxModel )
return *pControls;
}
}
OSL_FAIL( "FormController::locateControl: did not find a control for this model!" );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
return NULL;
}
//------------------------------------------------------------------------------
namespace
{
void displayErrorSetFocus( const String& _rMessage, const Reference< XControl >& _rxFocusControl, Window* _pDialogParent )
{
SQLContext aError;
aError.Message = String( SVX_RES( RID_STR_WRITEERROR ) );
aError.Details = _rMessage;
displayException( aError, _pDialogParent );
if ( _rxFocusControl.is() )
{
Reference< XWindow > xControlWindow( _rxFocusControl, UNO_QUERY );
OSL_ENSURE( xControlWindow.is(), "displayErrorSetFocus: invalid control!" );
if ( xControlWindow.is() )
xControlWindow->setFocus();
}
}
sal_Bool lcl_shouldValidateRequiredFields_nothrow( const Reference< XInterface >& _rxForm )
{
try
{
static OUString s_sFormsCheckRequiredFields( "FormsCheckRequiredFields" );
// first, check whether the form has a property telling us the answer
// this allows people to use the XPropertyContainer interface of a form to control
// the behaviour on a per-form basis.
Reference< XPropertySet > xFormProps( _rxForm, UNO_QUERY_THROW );
Reference< XPropertySetInfo > xPSI( xFormProps->getPropertySetInfo() );
if ( xPSI->hasPropertyByName( s_sFormsCheckRequiredFields ) )
{
sal_Bool bShouldValidate = true;
OSL_VERIFY( xFormProps->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate );
return bShouldValidate;
}
// next, check the data source which created the connection
Reference< XChild > xConnectionAsChild( xFormProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION ), UNO_QUERY_THROW );
Reference< XPropertySet > xDataSource( xConnectionAsChild->getParent(), UNO_QUERY );
if ( !xDataSource.is() )
// seldom (but possible): this is not a connection created by a data source
return sal_True;
Reference< XPropertySet > xDataSourceSettings(
xDataSource->getPropertyValue("Settings"),
UNO_QUERY_THROW );
sal_Bool bShouldValidate = true;
OSL_VERIFY( xDataSourceSettings->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate );
return bShouldValidate;
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
return sal_True;
}
}
// XRowSetApproveListener
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::approveRowChange(const RowChangeEvent& _rEvent) throw( RuntimeException )
{
::osl::ClearableMutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
sal_Bool bValid = sal_True;
if (aIter.hasMoreElements())
{
RowChangeEvent aEvt( _rEvent );
aEvt.Source = *this;
bValid = ((XRowSetApproveListener*)aIter.next())->approveRowChange(aEvt);
}
if ( !bValid )
return bValid;
if ( ( _rEvent.Action != RowChangeAction::INSERT )
&& ( _rEvent.Action != RowChangeAction::UPDATE )
)
return bValid;
// if some of the control models are bound to validators, check them
OUString sInvalidityExplanation;
Reference< XControlModel > xInvalidModel;
if ( !checkFormComponentValidity( sInvalidityExplanation, xInvalidModel ) )
{
Reference< XControl > xControl( locateControl( xInvalidModel ) );
aGuard.clear();
displayErrorSetFocus( sInvalidityExplanation, xControl, getDialogParentWindow() );
return false;
}
// check values on NULL and required flag
if ( !lcl_shouldValidateRequiredFields_nothrow( _rEvent.Source ) )
return sal_True;
OSL_ENSURE( m_pColumnInfoCache.get(), "FormController::approveRowChange: no column infos!" );
if ( !m_pColumnInfoCache.get() )
return sal_True;
try
{
if ( !m_pColumnInfoCache->controlsInitialized() )
m_pColumnInfoCache->initializeControls( getControls() );
size_t colCount = m_pColumnInfoCache->getColumnCount();
for ( size_t col = 0; col < colCount; ++col )
{
const ColumnInfo& rColInfo = m_pColumnInfoCache->getColumnInfo( col );
if ( rColInfo.nNullable != ColumnValue::NO_NULLS )
continue;
if ( rColInfo.bAutoIncrement )
continue;
if ( rColInfo.bReadOnly )
continue;
if ( !rColInfo.xFirstControlWithInputRequired.is() && !rColInfo.xFirstGridWithInputRequiredColumn.is() )
continue;
// TODO: in case of binary fields, this "getString" below is extremely expensive
if ( !rColInfo.xColumn->getString().isEmpty() || !rColInfo.xColumn->wasNull() )
continue;
String sMessage( SVX_RES( RID_ERR_FIELDREQUIRED ) );
sMessage.SearchAndReplace( OUString('#'), rColInfo.sName );
// the control to focus
Reference< XControl > xControl( rColInfo.xFirstControlWithInputRequired );
if ( !xControl.is() )
xControl.set( rColInfo.xFirstGridWithInputRequiredColumn, UNO_QUERY );
aGuard.clear();
displayErrorSetFocus( sMessage, rColInfo.xFirstControlWithInputRequired, getDialogParentWindow() );
return sal_False;
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
return true;
}
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::approveCursorMove(const EventObject& event) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
if (aIter.hasMoreElements())
{
EventObject aEvt(event);
aEvt.Source = *this;
return ((XRowSetApproveListener*)aIter.next())->approveCursorMove(aEvt);
}
return sal_True;
}
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::approveRowSetChange(const EventObject& event) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
if (aIter.hasMoreElements())
{
EventObject aEvt(event);
aEvt.Source = *this;
return ((XRowSetApproveListener*)aIter.next())->approveRowSetChange(aEvt);
}
return sal_True;
}
// XRowSetApproveBroadcaster
//------------------------------------------------------------------------------
void SAL_CALL FormController::addRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aRowSetApproveListeners.addInterface(_rxListener);
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aRowSetApproveListeners.removeInterface(_rxListener);
}
// XErrorListener
//------------------------------------------------------------------------------
void SAL_CALL FormController::errorOccured(const SQLErrorEvent& aEvent) throw( RuntimeException )
{
::osl::ClearableMutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
::cppu::OInterfaceIteratorHelper aIter(m_aErrorListeners);
if (aIter.hasMoreElements())
{
SQLErrorEvent aEvt(aEvent);
aEvt.Source = *this;
((XSQLErrorListener*)aIter.next())->errorOccured(aEvt);
}
else
{
aGuard.clear();
displayException( aEvent );
}
}
// XErrorBroadcaster
//------------------------------------------------------------------------------
void SAL_CALL FormController::addSQLErrorListener(const Reference< XSQLErrorListener > & aListener) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aErrorListeners.addInterface(aListener);
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeSQLErrorListener(const Reference< XSQLErrorListener > & aListener) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aErrorListeners.removeInterface(aListener);
}
// XDatabaseParameterBroadcaster2
//------------------------------------------------------------------------------
void SAL_CALL FormController::addDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aParameterListeners.addInterface(aListener);
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aParameterListeners.removeInterface(aListener);
}
// XDatabaseParameterBroadcaster
//------------------------------------------------------------------------------
void SAL_CALL FormController::addParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException )
{
FormController::addDatabaseParameterListener( aListener );
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException )
{
FormController::removeDatabaseParameterListener( aListener );
}
// XDatabaseParameterListener
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::approveParameter(const DatabaseParameterEvent& aEvent) throw( RuntimeException )
{
SolarMutexGuard aSolarGuard;
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
::cppu::OInterfaceIteratorHelper aIter(m_aParameterListeners);
if (aIter.hasMoreElements())
{
DatabaseParameterEvent aEvt(aEvent);
aEvt.Source = *this;
return ((XDatabaseParameterListener*)aIter.next())->approveParameter(aEvt);
}
else
{
// default handling: instantiate an interaction handler and let it handle the parameter request
try
{
if ( !ensureInteractionHandler() )
return sal_False;
// two continuations allowed: OK and Cancel
OParameterContinuation* pParamValues = new OParameterContinuation;
OInteractionAbort* pAbort = new OInteractionAbort;
// the request
ParametersRequest aRequest;
aRequest.Parameters = aEvent.Parameters;
aRequest.Connection = OStaticDataAccessTools().getRowSetConnection(Reference< XRowSet >(aEvent.Source, UNO_QUERY));
OInteractionRequest* pParamRequest = new OInteractionRequest(makeAny(aRequest));
Reference< XInteractionRequest > xParamRequest(pParamRequest);
// some knittings
pParamRequest->addContinuation(pParamValues);
pParamRequest->addContinuation(pAbort);
// handle the request
m_xInteractionHandler->handle(xParamRequest);
if (!pParamValues->wasSelected())
// canceled
return sal_False;
// transfer the values into the parameter supplier
Sequence< PropertyValue > aFinalValues = pParamValues->getValues();
if (aFinalValues.getLength() != aRequest.Parameters->getCount())
{
OSL_FAIL("FormController::approveParameter: the InteractionHandler returned nonsense!");
return sal_False;
}
const PropertyValue* pFinalValues = aFinalValues.getConstArray();
for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
{
Reference< XPropertySet > xParam;
::cppu::extractInterface(xParam, aRequest.Parameters->getByIndex(i));
if (xParam.is())
{
#ifdef DBG_UTIL
OUString sName;
xParam->getPropertyValue(FM_PROP_NAME) >>= sName;
DBG_ASSERT(sName.equals(pFinalValues->Name), "FormController::approveParameter: suspicious value names!");
#endif
try { xParam->setPropertyValue(FM_PROP_VALUE, pFinalValues->Value); }
catch(Exception&)
{
OSL_FAIL("FormController::approveParameter: setting one of the properties failed!");
}
}
}
}
catch(Exception&)
{
DBG_UNHANDLED_EXCEPTION();
}
}
return sal_True;
}
// XConfirmDeleteBroadcaster
//------------------------------------------------------------------------------
void SAL_CALL FormController::addConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aDeleteListeners.addInterface(aListener);
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
m_aDeleteListeners.removeInterface(aListener);
}
// XConfirmDeleteListener
//------------------------------------------------------------------------------
sal_Bool SAL_CALL FormController::confirmDelete(const RowChangeEvent& aEvent) throw( RuntimeException )
{
::osl::MutexGuard aGuard( m_aMutex );
impl_checkDisposed_throw();
::cppu::OInterfaceIteratorHelper aIter(m_aDeleteListeners);
if (aIter.hasMoreElements())
{
RowChangeEvent aEvt(aEvent);
aEvt.Source = *this;
return ((XConfirmDeleteListener*)aIter.next())->confirmDelete(aEvt);
}
// default handling: instantiate an interaction handler and let it handle the request
String sTitle;
sal_Int32 nLength = aEvent.Rows;
if ( nLength > 1 )
{
sTitle = SVX_RESSTR( RID_STR_DELETECONFIRM_RECORDS );
sTitle.SearchAndReplace( OUString('#'), OUString::valueOf(nLength) );
}
else
sTitle = SVX_RESSTR( RID_STR_DELETECONFIRM_RECORD );
try
{
if ( !ensureInteractionHandler() )
return sal_False;
// two continuations allowed: Yes and No
OInteractionApprove* pApprove = new OInteractionApprove;
OInteractionDisapprove* pDisapprove = new OInteractionDisapprove;
// the request
SQLWarning aWarning;
aWarning.Message = sTitle;
SQLWarning aDetails;
aDetails.Message = String( SVX_RES( RID_STR_DELETECONFIRM ) );
aWarning.NextException <<= aDetails;
OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aWarning ) );
Reference< XInteractionRequest > xRequest( pRequest );
// some knittings
pRequest->addContinuation( pApprove );
pRequest->addContinuation( pDisapprove );
// handle the request
m_xInteractionHandler->handle( xRequest );
if ( pApprove->wasSelected() )
return sal_True;
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
return sal_False;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::invalidateFeatures( const Sequence< ::sal_Int16 >& _Features ) throw (RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
// for now, just copy the ids of the features, because ....
::std::copy( _Features.getConstArray(), _Features.getConstArray() + _Features.getLength(),
::std::insert_iterator< ::std::set< sal_Int16 > >( m_aInvalidFeatures, m_aInvalidFeatures.begin() )
);
// ... we will do the real invalidation asynchronously
if ( !m_aFeatureInvalidationTimer.IsActive() )
m_aFeatureInvalidationTimer.Start();
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::invalidateAllFeatures( ) throw (RuntimeException)
{
::osl::ClearableMutexGuard aGuard( m_aMutex );
Sequence< sal_Int16 > aInterceptedFeatures( m_aFeatureDispatchers.size() );
::std::transform(
m_aFeatureDispatchers.begin(),
m_aFeatureDispatchers.end(),
aInterceptedFeatures.getArray(),
::o3tl::select1st< DispatcherContainer::value_type >()
);
aGuard.clear();
if ( aInterceptedFeatures.getLength() )
invalidateFeatures( aInterceptedFeatures );
}
//------------------------------------------------------------------------------
Reference< XDispatch >
FormController::interceptedQueryDispatch( const URL& aURL,
const OUString& /*aTargetFrameName*/, sal_Int32 /*nSearchFlags*/)
throw( RuntimeException )
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
Reference< XDispatch > xReturn;
// dispatches handled by ourself
if ( ( aURL.Complete == FMURL_CONFIRM_DELETION )
|| ( ( aURL.Complete.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:/InteractionHandler" ) ) )
&& ensureInteractionHandler()
)
)
xReturn = static_cast< XDispatch* >( this );
// dispatches of FormSlot-URLs we have to translate
if ( !xReturn.is() && m_xFormOperations.is() )
{
// find the slot id which corresponds to the URL
sal_Int32 nFeatureSlotId = ::svx::FeatureSlotTranslation::getControllerFeatureSlotIdForURL( aURL.Main );
sal_Int16 nFormFeature = ( nFeatureSlotId != -1 ) ? ::svx::FeatureSlotTranslation::getFormFeatureForSlotId( nFeatureSlotId ) : -1;
if ( nFormFeature > 0 )
{
// get the dispatcher for this feature, create if necessary
DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( nFormFeature );
if ( aDispatcherPos == m_aFeatureDispatchers.end() )
{
aDispatcherPos = m_aFeatureDispatchers.insert(
DispatcherContainer::value_type( nFormFeature, new ::svx::OSingleFeatureDispatcher( aURL, nFormFeature, m_xFormOperations, m_aMutex ) )
).first;
}
OSL_ENSURE( aDispatcherPos->second.is(), "FormController::interceptedQueryDispatch: should have a dispatcher by now!" );
return aDispatcherPos->second;
}
}
// no more to offer
return xReturn;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArgs ) throw (RuntimeException)
{
if ( _rArgs.getLength() != 1 )
{
OSL_FAIL( "FormController::dispatch: no arguments -> no dispatch!" );
return;
}
if ( _rURL.Complete == "private:/InteractionHandler" )
{
Reference< XInteractionRequest > xRequest;
OSL_VERIFY( _rArgs[0].Value >>= xRequest );
if ( xRequest.is() )
handle( xRequest );
return;
}
if ( _rURL.Complete == FMURL_CONFIRM_DELETION )
{
OSL_FAIL( "FormController::dispatch: How do you expect me to return something via this call?" );
// confirmDelete has a return value - dispatch hasn't
return;
}
OSL_FAIL( "FormController::dispatch: unknown URL!" );
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::addStatusListener( const Reference< XStatusListener >& _rxListener, const URL& _rURL ) throw (RuntimeException)
{
if (_rURL.Complete == FMURL_CONFIRM_DELETION)
{
if (_rxListener.is())
{ // send an initial statusChanged event
FeatureStateEvent aEvent;
aEvent.FeatureURL = _rURL;
aEvent.IsEnabled = sal_True;
_rxListener->statusChanged(aEvent);
// and don't add the listener at all (the status will never change)
}
}
else
OSL_FAIL("FormController::addStatusListener: invalid (unsupported) URL!");
}
//------------------------------------------------------------------------------
Reference< XInterface > SAL_CALL FormController::getParent() throw( RuntimeException )
{
return m_xParent;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::setParent( const Reference< XInterface >& Parent) throw( NoSupportException, RuntimeException )
{
m_xParent = Parent;
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::removeStatusListener( const Reference< XStatusListener >& /*_rxListener*/, const URL& _rURL ) throw (RuntimeException)
{
(void)_rURL;
OSL_ENSURE(_rURL.Complete == FMURL_CONFIRM_DELETION, "FormController::removeStatusListener: invalid (unsupported) URL!");
// we never really added the listener, so we don't need to remove it
}
//------------------------------------------------------------------------------
Reference< XDispatchProviderInterceptor > FormController::createInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
#ifdef DBG_UTIL
// check if we already have a interceptor for the given object
for ( ConstInterceptorsIterator aIter = m_aControlDispatchInterceptors.begin();
aIter != m_aControlDispatchInterceptors.end();
++aIter
)
{
if ((*aIter)->getIntercepted() == _xInterception)
OSL_FAIL("FormController::createInterceptor : we already do intercept this objects dispatches !");
}
#endif
DispatchInterceptionMultiplexer* pInterceptor = new DispatchInterceptionMultiplexer( _xInterception, this );
pInterceptor->acquire();
m_aControlDispatchInterceptors.insert( m_aControlDispatchInterceptors.end(), pInterceptor );
return pInterceptor;
}
//------------------------------------------------------------------------------
bool FormController::ensureInteractionHandler()
{
if ( m_xInteractionHandler.is() )
return true;
if ( m_bAttemptedHandlerCreation )
return false;
m_bAttemptedHandlerCreation = true;
m_xInteractionHandler = InteractionHandler::createWithParent(m_xComponentContext, 0);
return m_xInteractionHandler.is();
}
//------------------------------------------------------------------------------
void SAL_CALL FormController::handle( const Reference< XInteractionRequest >& _rRequest ) throw (RuntimeException)
{
if ( !ensureInteractionHandler() )
return;
m_xInteractionHandler->handle( _rRequest );
}
//------------------------------------------------------------------------------
void FormController::deleteInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
{
OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
// search the interceptor responsible for the given object
InterceptorsIterator aIter;
for ( aIter = m_aControlDispatchInterceptors.begin();
aIter != m_aControlDispatchInterceptors.end();
++aIter
)
{
if ((*aIter)->getIntercepted() == _xInterception)
break;
}
if (aIter == m_aControlDispatchInterceptors.end())
{
return;
}
// log off the interception from it's interception object
DispatchInterceptionMultiplexer* pInterceptorImpl = *aIter;
pInterceptorImpl->dispose();
pInterceptorImpl->release();
// remove the interceptor from our array
m_aControlDispatchInterceptors.erase(aIter);
}
//--------------------------------------------------------------------
void FormController::implInvalidateCurrentControlDependentFeatures()
{
Sequence< sal_Int16 > aCurrentControlDependentFeatures(4);
aCurrentControlDependentFeatures[0] = FormFeature::SortAscending;
aCurrentControlDependentFeatures[1] = FormFeature::SortDescending;
aCurrentControlDependentFeatures[2] = FormFeature::AutoFilter;
aCurrentControlDependentFeatures[3] = FormFeature::RefreshCurrentControl;
invalidateFeatures( aCurrentControlDependentFeatures );
}
//--------------------------------------------------------------------
void SAL_CALL FormController::columnChanged( const EventObject& /*_event*/ ) throw (RuntimeException)
{
implInvalidateCurrentControlDependentFeatures();
}
} // namespace svxform
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */