diff options
Diffstat (limited to 'forms/source/inc/FormComponent.hxx')
-rw-r--r-- | forms/source/inc/FormComponent.hxx | 1320 |
1 files changed, 1320 insertions, 0 deletions
diff --git a/forms/source/inc/FormComponent.hxx b/forms/source/inc/FormComponent.hxx new file mode 100644 index 000000000000..0c8b421008a3 --- /dev/null +++ b/forms/source/inc/FormComponent.hxx @@ -0,0 +1,1320 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORMS_FORMCOMPONENT_HXX_ +#define _FORMS_FORMCOMPONENT_HXX_ + +#include "cloneable.hxx" +#include "ids.hxx" +#include "property.hrc" +#include "property.hxx" +#include "propertybaghelper.hxx" +#include "resettable.hxx" +#include "services.hxx" +#include "windowstateguard.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/form/validation/XValidatableFormComponent.hpp> +#include <com/sun/star/form/validation/XValidityConstraintListener.hpp> +#include <com/sun/star/form/XBoundComponent.hpp> +#include <com/sun/star/form/XBoundControl.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include <com/sun/star/form/XLoadListener.hpp> +#include <com/sun/star/form/XReset.hpp> +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/sdb/XColumnUpdate.hpp> +#include <com/sun/star/sdb/XRowSetChangeListener.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/uno/XAggregation.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/util/XModifyListener.hpp> +#include <com/sun/star/form/XLoadable.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/propagg.hxx> +#include <comphelper/propertybag.hxx> +#include <comphelper/propmultiplex.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/component.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/implbase7.hxx> +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> + +#include <memory> + +//......................................................................... +namespace frm +{ +//......................................................................... + + // default tab index for components + const sal_Int16 FRM_DEFAULT_TABINDEX = 0; + + // macros for quickly declaring/implementing XServiceInfo + #define DECLARE_XPERSISTOBJECT() \ + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); \ + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); \ + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); \ + + // old macro for quickly implementing XServiceInfo::getImplementationName + #define IMPLEMENTATION_NAME(ImplName) \ + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException) \ + { return ::rtl::OUString::createFromAscii("com.sun.star.comp.forms.") + ::rtl::OUString::createFromAscii(#ImplName); } + + class OControlModel; + + //========================================================================= + //= ControlModelLock + //========================================================================= + /** class whose instances lock a OControlModel + + Locking here merely means locking the OControlModel's mutex. + + In addition to the locking facility, the class is also able to fire property + change notifications. This happens when the last ControlModelLock instance on a stack + dies. + */ + class ControlModelLock + { + public: + ControlModelLock( OControlModel& _rModel ) + :m_rModel( _rModel ) + ,m_bLocked( false ) + { + acquire(); + } + + ~ControlModelLock() + { + if ( m_bLocked ) + release(); + } + inline void acquire(); + inline void release(); + + inline OControlModel& getModel() const { return m_rModel; }; + + /** adds a property change notification, which is to be fired when the last lock on the model + (in the current thread) is released. + */ + void addPropertyNotification( + const sal_Int32 _nHandle, + const ::com::sun::star::uno::Any& _rOldValue, + const ::com::sun::star::uno::Any& _rNewValue + ); + + private: + void impl_notifyAll_nothrow(); + + private: + OControlModel& m_rModel; + bool m_bLocked; + ::com::sun::star::uno::Sequence< sal_Int32 > m_aHandles; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > m_aOldValues; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > m_aNewValues; + + private: + ControlModelLock(); // never implemented + ControlModelLock( const ControlModelLock& ); // never implemented + ControlModelLock& operator=( const ControlModelLock& ); // never implemented + }; + +//========================================================================= +//= OControl +//= base class for form layer controls +//========================================================================= +typedef ::cppu::ImplHelper3 < ::com::sun::star::awt::XControl + , ::com::sun::star::lang::XEventListener + , ::com::sun::star::lang::XServiceInfo + > OControl_BASE; + +class OControl :public ::cppu::OComponentHelper + ,public OControl_BASE +{ +protected: + ::osl::Mutex m_aMutex; + OImplementationIdsRef m_aHoldIdHelper; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl > + m_xControl; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> + m_xAggregate; + + ::comphelper::ComponentContext m_aContext; + WindowStateGuard m_aWindowStateGuard; + +public: + /** constructs a control + + @param _rFactory + the service factory for this control + @param _rAggregateService + the service name of the component to aggregate + @param _bSetDelegator + set this to <FALSE/> if you don't want the constructor to set the delegator at + the aggregate. In this case, you <em>have</em> to call doSetDelegator within your + own constructor. + + This is helpfull, if your derived class wants to cache an interface of the aggregate. + In this case, the aggregate needs to be queried for this interface <b>before</b> the + <member scope="com::sun::star::uno">XAggregation::setDelegator</member> call. + + In such a case, pass <FALSE/> to this parameter. Then, cache the aggregate's interface(s) + as needed. Afterwards, call <member>doSetDelegator</member>. + + In your destructor, you need to call <member>doResetDelegator</member> before + resetting the cached interfaces. This will reset the aggregates delegator to <NULL/>, + which will ensure that the <member scope="com::sun::star::uno">XInterface::release</member> + calls on the cached interfaces are really applied to the aggregate, instead of + the <type>OControl</type> itself. + */ + OControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rFactory, + const ::rtl::OUString& _rAggregateService, + const sal_Bool _bSetDelegator = sal_True + ); + + /** initializes the given peer with various settings necessary for form controls + */ + static void initFormControlPeer( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& _rxPeer ); + +protected: + virtual ~OControl(); + + /** sets the control as delegator at the aggregate + + This has to be called from within your derived class' constructor, if and only + if you passed <FALSE/> to the <arg>_bSetDelegator</arg> parameter of the + <type>OControl</type> constructor. + */ + void doSetDelegator(); + void doResetDelegator(); + +// UNO + DECLARE_UNO3_AGG_DEFAULTS(OControl, OComponentHelper); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(::com::sun::star::uno::RuntimeException); + +// XTypeProvider + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// XComponent (as base of XControl) + virtual void SAL_CALL dispose( ) throw(::com::sun::star::uno::RuntimeException) + { OComponentHelper::dispose(); } + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException) + { OComponentHelper::addEventListener(_rxListener); } + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException) + { OComponentHelper::removeEventListener(_rxListener); } + +// XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + +// XServiceInfo + virtual sal_Bool SAL_CALL supportsService(const ::rtl::OUString& ServiceName) throw (::com::sun::star::uno::RuntimeException); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException) = 0; + +// XServiceInfo - static version + static StringSequence SAL_CALL getSupportedServiceNames_Static() throw(::com::sun::star::uno::RuntimeException); + +// XControl + virtual void SAL_CALL setContext(const InterfaceRef& Context) throw (::com::sun::star::uno::RuntimeException); + virtual InterfaceRef SAL_CALL getContext() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL createPeer(const ::com::sun::star::uno::Reference<starawt::XToolkit>& Toolkit, const ::com::sun::star::uno::Reference<starawt::XWindowPeer>& Parent) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference<starawt::XWindowPeer> SAL_CALL getPeer() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setModel(const ::com::sun::star::uno::Reference<starawt::XControlModel>& Model) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference<starawt::XControlModel> SAL_CALL getModel() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference<starawt::XView> SAL_CALL getView() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDesignMode(sal_Bool bOn) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isDesignMode() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isTransparent() throw (::com::sun::star::uno::RuntimeException); + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + // overwrite this and call the base class if you have additional types + + ::com::sun::star::uno::Sequence< ::rtl::OUString > getAggregateServiceNames(); + +private: + void impl_resetStateGuard_nothrow(); +}; + +//================================================================== +//= OBoundControl +//= a form control implementing the XBoundControl interface +//================================================================== +typedef ::cppu::ImplHelper1 < ::com::sun::star::form::XBoundControl + > OBoundControl_BASE; +class OBoundControl :public OControl + ,public OBoundControl_BASE +{ +protected: + sal_Bool m_bLocked : 1; + + ::rtl::OUString m_sOriginalHelpText; // as long as the text/value is invalid, we change the help text of our peer + ::com::sun::star::awt::FontDescriptor + m_aOriginalFont; // as long as the text/value is invalid, we also change the font + sal_Int32 m_nOriginalTextLineColor; // (we add red underlining) + +public: + OBoundControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory, + const ::rtl::OUString& _rAggregateService, + const sal_Bool _bSetDelegator = sal_True + ); + + virtual ~OBoundControl(); + + DECLARE_UNO3_AGG_DEFAULTS(OBoundControl, OControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(::com::sun::star::uno::RuntimeException); + + // XBoundControl + virtual sal_Bool SAL_CALL getLock() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLock(sal_Bool _bLock) throw(::com::sun::star::uno::RuntimeException); + // default implementation just disables the controls, overwrite _setLock to change this behaviour + + // XControl + virtual sal_Bool SAL_CALL setModel(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& Model) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + // implement the lock setting + virtual void _setLock(sal_Bool _bLock); +}; + +//================================================================== +//= OControlModel +//= model of a form layer control +//================================================================== + +typedef ::cppu::ImplHelper7 < ::com::sun::star::form::XFormComponent + , ::com::sun::star::io::XPersistObject + , ::com::sun::star::container::XNamed + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::util::XCloneable + , ::com::sun::star::beans::XPropertyContainer + , ::com::sun::star::beans::XPropertyAccess + > OControlModel_BASE; + +class OControlModel :public ::cppu::OComponentHelper + ,public OPropertySetAggregationHelper + ,public OControlModel_BASE + ,public OCloneableAggregation + ,public IPropertyBagHelperContext +{ + +protected: + ::comphelper::ComponentContext m_aContext; + + ::osl::Mutex m_aMutex; + oslInterlockedCount m_lockCount; + + InterfaceRef m_xParent; // ParentComponent + OImplementationIdsRef m_aHoldIdHelper; + PropertyBagHelper m_aPropertyBagHelper; + + const ::comphelper::ComponentContext& + getContext() const { return m_aContext; } + +// <properties> + ::rtl::OUString m_aName; // name of the control + ::rtl::OUString m_aTag; // tag for additional data + sal_Int16 m_nTabIndex; // index within the taborder + sal_Int16 m_nClassId; // type of the control + sal_Bool m_bNativeLook; // should the control use the native platform look? +// </properties> + + +protected: + OControlModel( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rFactory, // factory to create the aggregate with + const ::rtl::OUString& _rUnoControlModelTypeName, // service name of te model to aggregate + const ::rtl::OUString& rDefault = ::rtl::OUString(), // service name of the default control + const sal_Bool _bSetDelegator = sal_True // set to FALSE if you want to call setDelegator later (after returning from this ctor) + ); + OControlModel( + const OControlModel* _pOriginal, // the original object to clone + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rFactory, // factory to create the aggregate with + const sal_Bool _bCloneAggregate = sal_True, // should the aggregate of the original be cloned, too? + const sal_Bool _bSetDelegator = sal_True // set to FALSE if you want to call setDelegator later (after returning from this ctor) + ); + virtual ~OControlModel(); + + /** to be called after a OBoundControlModel (a derivee, respectively) has been cloned + + <p>This method contains late initializations which cannot be done in the + constructor of this base class, since the virtual method of derived classes do + not yet work there.</p> + */ + virtual void clonedFrom( const OControlModel* _pOriginal ); + + using OComponentHelper::rBHelper; + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + void readHelpTextCompatibly(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& _rxInStream); + void writeHelpTextCompatibly(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& _rxOutStream); + + void doSetDelegator(); + void doResetDelegator(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > getAggregateServiceNames(); + +public: + DECLARE_UNO3_AGG_DEFAULTS(OControl, OComponentHelper); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + +// XTypeProvider + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// XNamed + virtual ::rtl::OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setName(const ::rtl::OUString& aName) throw(::com::sun::star::uno::RuntimeException); + +// XServiceInfo + virtual sal_Bool SAL_CALL supportsService(const ::rtl::OUString& ServiceName) throw (::com::sun::star::uno::RuntimeException); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException) = 0; + +// XSericeInfo - static version(s) + static StringSequence SAL_CALL getSupportedServiceNames_Static() throw(::com::sun::star::uno::RuntimeException); + +// XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL + write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL + read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + +// XChild (base of XFormComponent) + virtual InterfaceRef SAL_CALL getParent() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent(const InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + +// XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + +// XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + using ::cppu::OPropertySetHelper::getFastPropertyValue; + +// ::com::sun::star::beans::XPropertyState + virtual ::com::sun::star::beans::PropertyState getPropertyStateByHandle(sal_Int32 nHandle); + virtual void setPropertyToDefaultByHandle(sal_Int32 nHandle); + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + +// XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException) = 0; + +// XPropertyContainer + virtual void SAL_CALL addProperty( const ::rtl::OUString& Name, ::sal_Int16 Attributes, const ::com::sun::star::uno::Any& DefaultValue ) throw (::com::sun::star::beans::PropertyExistException, ::com::sun::star::beans::IllegalTypeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeProperty( const ::rtl::OUString& Name ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::NotRemoveableException, ::com::sun::star::uno::RuntimeException); + +// XPropertyAccess + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPropertyValues( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValues( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aProps ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +protected: + using OPropertySetAggregationHelper::setPropertyValues; + using OPropertySetAggregationHelper::getPropertyValues; + +protected: + virtual void writeAggregate( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& _rxOutStream ) const; + virtual void readAggregate( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& _rxInStream ); + +protected: + // XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() throw( ::com::sun::star::uno::RuntimeException); + // OPropertySetHelper + virtual cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + /** describes the properties provided by this class, or its respective + derived class + + Derived classes usually call the base class first, and then append own properties. + */ + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // IPropertyBagHelperContext + virtual ::osl::Mutex& getMutex(); + virtual void describeFixedAndAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& _out_rFixedProperties, + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& _out_rAggregateProperties + ) const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet > + getPropertiesInterface(); + + /** describes the properties of our aggregate + + The default implementation simply asks m_xAggregateSet for its properties. + + You usually only need to overload this method if you want to filter the aggregate + properties. + */ + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + +public: + struct LockAccess { friend class ControlModelLock; private: LockAccess() { } }; + + void lockInstance( LockAccess ); + oslInterlockedCount unlockInstance( LockAccess ); + + void firePropertyChanges( + const ::com::sun::star::uno::Sequence< sal_Int32 >& _rHandles, + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& _rOldValues, + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& _rNewValues, + LockAccess + ); + + inline ::osl::Mutex& + getInstanceMutex() { return m_aMutex; } +}; + +//================================================================== +// simple destructor +#define DECLARE_DEFAULT_DTOR( classname ) \ + ~classname() \ + +// constructor for cloning a class +#define DECLARE_DEFAULT_CLONE_CTOR( classname ) \ + classname( \ + const classname* _pOriginal, \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory \ + ); \ + +// all xtors for an inner class of the object hierarchy +#define DECLARE_DEFAULT_XTOR( classname ) \ + classname( \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, \ + const ::rtl::OUString& _rUnoControlModelTypeName, \ + const ::rtl::OUString& _rDefault \ + ); \ + DECLARE_DEFAULT_CLONE_CTOR( classname ) \ + DECLARE_DEFAULT_DTOR( classname ) \ + +// all xtors for an inner class of the object hierarchy which is *bound* +#define DECLARE_DEFAULT_BOUND_XTOR( classname ) \ + classname( \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, \ + const ::rtl::OUString& _rUnoControlModelTypeName, \ + const ::rtl::OUString& _rDefault, \ + const sal_Bool _bSupportExternalBinding, \ + const sal_Bool _bSupportsValidation \ + ); \ + DECLARE_DEFAULT_CLONE_CTOR( classname ) \ + DECLARE_DEFAULT_DTOR( classname ) \ + +// all xtors for a leas class of the object hierarchy +#define DECLARE_DEFAULT_LEAF_XTOR( classname ) \ + classname( \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory \ + ); \ + classname( \ + const classname* _pOriginal, \ + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory \ + ); \ + DECLARE_DEFAULT_DTOR( classname ) \ + +//================================================================== +// XCloneable +#define DECLARE_XCLONEABLE( ) \ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException) + +#define IMPLEMENT_DEFAULT_CLONING( classname ) \ + ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL classname::createClone( ) throw (::com::sun::star::uno::RuntimeException) \ + { \ + classname* pClone = new classname( this, getContext().getLegacyServiceFactory() ); \ + pClone->clonedFrom( this ); \ + return pClone; \ + } + +//================================================================== +//= OBoundControlModel +//= model of a form layer control which is bound to a data source field +//================================================================== +typedef ::cppu::ImplHelper4 < ::com::sun::star::form::XLoadListener + , ::com::sun::star::form::XReset + , ::com::sun::star::beans::XPropertyChangeListener + , ::com::sun::star::sdb::XRowSetChangeListener + > OBoundControlModel_BASE1; + +// separated into an own base class since derivees can disable the support for this +// interface, thus we want to easily exclude it in the queryInterface and getTypes +typedef ::cppu::ImplHelper1 < ::com::sun::star::form::XBoundComponent + > OBoundControlModel_COMMITTING; + +// dito +typedef ::cppu::ImplHelper2 < ::com::sun::star::form::binding::XBindableValue + , ::com::sun::star::util::XModifyListener + > OBoundControlModel_BINDING; + +// dito +typedef ::cppu::ImplHelper2 < ::com::sun::star::form::validation::XValidityConstraintListener + , ::com::sun::star::form::validation::XValidatableFormComponent + > OBoundControlModel_VALIDATION; + +class OBoundControlModel :public OControlModel + ,public OBoundControlModel_BASE1 + ,public OBoundControlModel_COMMITTING + ,public OBoundControlModel_BINDING + ,public OBoundControlModel_VALIDATION + ,public ::comphelper::OPropertyChangeListener +{ +protected: + enum ValueChangeInstigator + { + eDbColumnBinding, + eExternalBinding, + eOther + }; + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xField; + // the form which controls supplies the field we bind to. + ::com::sun::star::uno::Reference< ::com::sun::star::form::XLoadable > + m_xAmbientForm; + + ::rtl::OUString m_sValuePropertyName; + sal_Int32 m_nValuePropertyAggregateHandle; + sal_Int32 m_nFieldType; + ::com::sun::star::uno::Type m_aValuePropertyType; + bool m_bValuePropertyMayBeVoid; + + ResetHelper m_aResetHelper; + ::cppu::OInterfaceContainerHelper m_aUpdateListeners; + ::cppu::OInterfaceContainerHelper m_aFormComponentListeners; + + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding > + m_xExternalBinding; + ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XValidator > + m_xValidator; + ::com::sun::star::uno::Type m_aExternalValueType; + +// <properties> + ::rtl::OUString m_aControlSource; // Datenquelle, Name des Feldes + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xLabelControl; // reference to a sibling control (model) which is our label + sal_Bool m_bInputRequired; +// </properties> + + ::comphelper::OPropertyChangeMultiplexer* + m_pAggPropMultiplexer; + + bool m_bFormListening : 1; // are we currently a XLoadListener at our ambient form? + sal_Bool m_bLoaded : 1; + sal_Bool m_bRequired : 1; + const sal_Bool m_bCommitable : 1; // do we support XBoundComponent? + const sal_Bool m_bSupportsExternalBinding : 1; // do we support XBindableValue? + const sal_Bool m_bSupportsValidation : 1; // do we support XValidatable? + sal_Bool m_bForwardValueChanges : 1; // do we currently handle changes in the bound database field? + sal_Bool m_bTransferingValue : 1; // true if we're currently transfering our value to an external binding + sal_Bool m_bIsCurrentValueValid : 1; // flag specifying whether our current value is valid, relative to our external validator + sal_Bool m_bBindingControlsRO : 1; // is our ReadOnly property currently controlled by our external binding? + sal_Bool m_bBindingControlsEnable : 1; // is our Enabled property currently controlled by our external binding? + + ValueChangeInstigator m_eControlValueChangeInstigator; + +protected: + ::rtl::OUString m_aLabelServiceName; + // when setting the label for our control (property FM_PROP_CONTROLLABEL, member m_xLabelControl), + // we accept only objects supporting an XControlModel interface, an XServiceInfo interface and + // support for a service (XServiceInfo::supportsService) determined by this string. + // Any other arguments will throw an IllegalArgumentException. + // The default value is FM_COMPONENT_FIXEDTEXT. + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > + m_xCursor; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XColumnUpdate > + m_xColumnUpdate; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XColumn > + m_xColumn; + +protected: + inline const ::rtl::OUString& getValuePropertyName( ) const { return m_sValuePropertyName; } + inline sal_Int32 getValuePropertyAggHandle( ) const { return m_nValuePropertyAggregateHandle; } + inline const ::rtl::OUString& getControlSource( ) const { return m_aControlSource; } + inline sal_Bool isRequired() const { return m_bRequired; } + inline sal_Bool isLoaded() const { return m_bLoaded; } + +protected: + + OBoundControlModel( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rFactory, + // factory to create the aggregate with + const ::rtl::OUString& _rUnoControlModelTypeName, // service name of te model to aggregate + const ::rtl::OUString& _rDefault, // service name of the default control + const sal_Bool _bCommitable, // is the control (model) commitable ? + const sal_Bool _bSupportExternalBinding, // set to TRUE if you want to support XBindableValue + const sal_Bool _bSupportsValidation // set to TRUE if you want to support XValidatable + ); + OBoundControlModel( + const OBoundControlModel* _pOriginal, // the original object to clone + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rFactory + // factory to create the aggregate with + ); + virtual ~OBoundControlModel(); + + /// late ctor after cloning + virtual void clonedFrom( const OControlModel* _pOriginal ); + + /** initializes the part of the class which is related to the control value. + + <p>Kind of late ctor, to be called for derivees which have a dedicated value property.<br/> + The value property is the property which's value is synced with either the database + column the object is bound to, or with the external value binding, if present.<br/> + E.g. for a text control model, this property will most probably be "Text".</p> + + <p>Derived classes are stronly recommend to call this method - at least the + "DataFieldProperty" (exposed in getFastPropertyValue) relies on the information + given herein, and needs to be supplied otherwise else.</p> + + <p>If this method has been called properly, then <member>setControlValue</member> + does not need to be overridden - it will simply set the property value at the + aggregate then.</p> + + @precond + The method has not be called before during the life time of the object. + + @param _rValuePropertyName + the name of the value property + @param _nValuePropertyExternalHandle + the handle of the property, as exposed to external components.<br/> + Normally, this information can be obtained dynamically (e.g. from describeFixedProperties), + but since this method is to be called from within the constructor of derived classes, + we prefer to be on the *really* safe side here .... + + @see setControlValue + @see suspendValueListening + @see resumeValueListening + @see describeFixedProperties + */ + void initValueProperty( + const ::rtl::OUString& _rValuePropertyName, + sal_Int32 _nValuePropertyExternalHandle + ); + + /** initializes the part of the class which is related to the control value. + + <p>In opposite to ->initValueProperty, this method is to be used for value properties which are <em>not</em> + implemented by our aggregate, but by ourselves.</p> + + <p>Certain functionality is not available when using own value properties. This includes binding to an external + value and external validation. (This is not a conceptual limit, but simply missing implementation.)</p> + */ + void initOwnValueProperty( + const ::rtl::OUString& i_rValuePropertyName + ); + + /** suspends listening at the value property + + <p>As long as this listening is suspended, changes in the value property will not be + recognized and not be handled.</p> + + @see initValueProperty + @see resumeValueListening + */ + void suspendValueListening( ); + + /** resumes listening at the value property + + <p>As long as this listening is suspended, changes in the value property will not be + recognized and not be handled.</p> + + @precond + listening at the value property is currently suspended + + @see initValueProperty + @see resumeValueListening + */ + void resumeValueListening( ); + + /** (to be) called when the value property changed + + Normally, this is done automatically, since the value property is a property of our aggregate, and we're + a listener at this property. + However, in some cases the value property might not be an aggregate property, but a property of the + delegator instance. In this case, you'll need to call <code>onValuePropertyChange</code> whenever this + property changes. + */ + void onValuePropertyChange( ControlModelLock& i_rControLock ); + + /** starts listening at the aggregate, for changes in the given property + + <p>The OBoundControlModel automatically registers a multiplexer which listens for + changes in the aggregate property values. By default, only the control value property + is observed. You may add additional properties to be observed with this method.</p> + + @see initValueProperty + @see _propertyChanged + */ + void startAggregatePropertyListening( const ::rtl::OUString& _rPropertyName ); + + /** returns the default which should be used when resetting the control + + <p>The default implementation returns an empty Any.</p> + + @see resetNoBroadcast + */ + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + /** translates a db column value into a control value. + + <p>Must transform the very current value of the database column we're bound to + (<member>m_xColumn</member>) into a value which can be used as current value + for the control.</p> + + @see setControlValue + @pure + */ + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ) = 0; + + /** returns the data types which the control could use to exchange data with + an external value binding + + The types returned here are completely independent from the concrete value binding, + they're just candidates which depend on the control type, and possible the concrete state + of the control (i.e. some property value). + + If a control implementation supports multiple types, the ordering in the returned + sequence indicates preference: Preferred types are mentioned first. + + The default implementation returns the type of our value property. + */ + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + + /** translates the given value, which was obtained from the current external value binding, + to a value which can be used in setControlValue + + <p>The default implementation returns the value itself, exception when it is VOID, and + our value property is not allowed to be void - in this case, the returned value is a + default-constructed value of the type required by our value property. + + @see hasExternalValueBinding + @see getExternalValueType + */ + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + + /** commits the current control value to our external value binding + + <p>The default implementation simply calls getControlValue.</p> + + @see hasExternalValueBinding + @see initValueProperty + */ + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + + /** commits the current control value to the database column we're bound to + @precond + we're properly bound to a database column, especially <member>m_xColumnUpdate</member> + is not <NULL/> + @param _bPostReset + <TRUE/> if and only if the current control value results from a reset (<member>getDefaultForReset</member>) + @pure + */ + virtual sal_Bool commitControlValueToDbColumn( + bool _bPostReset + ) = 0; + + /** sets the given value as new current value for the control + + Besides some administrative work (such as caring for <member>m_eControlValueChangeInstigator</member>), + this method simply calls <member>doSetControlValue</member>. + + @precond + Our own mutex is locked. + @param _rValue + The value to set. This value is guaranteed to be created by + <member>translateDbColumnToControlValue</member> or + <member>translateExternalValueToControlValue</member> + @param _eInstigator + the instigator of the value change + */ + void setControlValue( + const ::com::sun::star::uno::Any& _rValue, + ValueChangeInstigator _eInstigator + ); + /** + <p>The default implementation will forward the given value to the aggregate, using + m_nValuePropertyAggregateHandle and/or m_sValuePropertyName.</p> + + @precond + Our own mutex is locked. + @param _rValue + The value to set. This value is guaranteed to be created by + <member>translateDbColumnToControlValue</member> or + <member>translateExternalValueToControlValue</member> + */ + virtual void doSetControlValue( + const ::com::sun::star::uno::Any& _rValue + ); + + /** retrieves the current value of the control + + <p>The default implementation will ask the aggregate for the property value + determined by either m_nValuePropertyAggregateHandle and/or m_sValuePropertyName.</p> + + @precond + Our own mutex is locked. + */ + virtual ::com::sun::star::uno::Any + getControlValue( ) const; + + /** called whenever a connection to a database column has been established + */ + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + /** called whenever a connection to a database column has been suspended + */ + virtual void onDisconnectedDbColumn(); + + /** called whenever a connection to an external supplier of values (XValueBinding) has been established + @see m_xExternalBinding + */ + virtual void onConnectedExternalValue( ); + /** called whenever a connection to an external supplier of values (XValueBinding) has been suspended + */ + virtual void onDisconnectedExternalValue(); + + /** called whenever an external validator has been registered + */ + virtual void onConnectedValidator( ); + /** called whenever an external validator has been revoked + */ + virtual void onDisconnectedValidator( ); + + /** nFieldType ist der Typ des Feldes, an das das Model gebunden werden soll. + Das Binden erfolgt genau dann, wenn Rueckgabewert sal_True. + Die Standard-Implementation erlaubt alles ausser den drei binary-Typen und + FieldType_OTHER. + */ + virtual sal_Bool approveDbColumnType(sal_Int32 _nColumnType); + + /** retrieves the current value of the control, in a shape which can be used with our + external validator. + + The default implementation simply calls <member>>translateControlValueToExternalValue</member>. + + @precond + Our own mutex is locked. + */ + virtual ::com::sun::star::uno::Any + translateControlValueToValidatableValue( ) const; + + /** retrieves the current value of the form component + + This is the implementation method for XValidatableFormComponent::getCurrentValue. The default implementation + calls translateControlValueToValidatableValue if a validator is present, otherwise getControlValue. + + @precond + our mutex is locked when this method is called + */ + virtual ::com::sun::star::uno::Any + getCurrentFormComponentValue() const; + + /** We can't write (new) common properties in this base class, as the file format doesn't allow this + (unfortunally). So derived classes may use the following to methods. They secure the written + data with marks, so any new common properties in newer versions will be skipped by older ones. + */ + void writeCommonProperties(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream); + void readCommonProperties(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream); + // the next method may be used in derived classes's read when an unknown version is encountered + void defaultCommonProperties(); + + /** called to reset the control to some kind of default. + + <p>The semantics of "default" is finally defined by the derived class (in particular, + by <member>getDefaultForReset</member>).</p> + + <p>No listener notification needs to be done in the derived class.</p> + + <p>Normally, you won't override this method, but <member>getDefaultForReset</member> instead.</p> + + @see getDefaultForReset + */ + virtual void resetNoBroadcast(); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + /// sets m_xField to the given new value, without notifying our listeners + void impl_setField_noNotify( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _rxField + ); + inline bool hasField() const + { + return m_xField.is(); + } + inline sal_Int32 getFieldType() const + { + return m_nFieldType; + } + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +public: + inline const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& getField() const + { + return m_xField; + } + +public: + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OBoundControlModel, OControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XReset + virtual void SAL_CALL reset( ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addResetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& aListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener >& aListener ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual StringSequence SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo - static version + static StringSequence SAL_CALL getSupportedServiceNames_Static() throw(::com::sun::star::uno::RuntimeException); + + // XChild + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual void SAL_CALL write( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& OutStream ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL read( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& InStream ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XBoundComponent + virtual sal_Bool SAL_CALL commit() throw(::com::sun::star::uno::RuntimeException); + + // XUpdateBroadcaster (base of XBoundComponent) + virtual void SAL_CALL addUpdateListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener >& aListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeUpdateListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener >& aListener ) throw(::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + using ::cppu::OPropertySetHelper::getFastPropertyValue; + +// ::com::sun::star::beans::XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + +// XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + +// XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw(::com::sun::star::uno::RuntimeException); + + // XRowSetChangeListener + virtual void SAL_CALL onRowSetChanged( const ::com::sun::star::lang::EventObject& i_Event ) throw (::com::sun::star::uno::RuntimeException); + +// XLoadListener + virtual void SAL_CALL loaded( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL unloading( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL unloaded( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reloading( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reloaded( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + +private: + // XBindableValue + virtual void SAL_CALL setValueBinding( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding ) throw (::com::sun::star::form::binding::IncompatibleTypesException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding > SAL_CALL getValueBinding( ) throw (::com::sun::star::uno::RuntimeException); + + // XModifyListener + virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& _rEvent ) throw (::com::sun::star::uno::RuntimeException); + + // XValidatable + virtual void SAL_CALL setValidator( const ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XValidator >& Validator ) throw (::com::sun::star::util::VetoException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XValidator > SAL_CALL getValidator( ) throw (::com::sun::star::uno::RuntimeException); + + // XValidityConstraintListener + virtual void SAL_CALL validityConstraintChanged( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + // XValidatableFormComponent + virtual sal_Bool SAL_CALL isValid( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getCurrentValue( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addFormComponentValidityListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XFormComponentValidityListener >& Listener ) throw (::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeFormComponentValidityListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XFormComponentValidityListener >& Listener ) throw (::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); + +protected: + // OPropertyChangeListener + virtual void + _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& _rEvt ) throw ( ::com::sun::star::uno::RuntimeException ); + + /// checks whether we currently have an external value binding in place + inline bool hasExternalValueBinding() const { return m_xExternalBinding.is(); } + + // checks whether we currently have an external validator + inline bool hasValidator() const { return m_xValidator.is(); } + + /** transfers the very current value of the db column we're bound to the control + @precond + our own mutex is locked + @precond + we don't have an external binding in place + */ + void transferDbValueToControl( ); + + /** transfers the current value of the active external binding to the control + @precond + we do have an active external binding in place + */ + void transferExternalValueToControl( ControlModelLock& _rInstanceLock ); + + /** transfers the control value to the external binding + @precond + our own mutex is locked, and _rInstanceLock is the guard locking it + @precond + we do have an active external binding in place + */ + void transferControlValueToExternal( ControlModelLock& _rInstanceLock ); + + /** calculates the type which is to be used to communicate with the current external binding, + and stores it in m_aExternalValueType + + The method checks the possible type candidates as returned by getSupportedBindingTypes, + and the types supported by the current external binding, if any. + */ + void calculateExternalValueType(); + + /** returns the type which should be used to exchange data with our external value binding + + @see initValueProperty + */ + const ::com::sun::star::uno::Type& + getExternalValueType() const { return m_aExternalValueType; } + + /** initializes the control from m_xField + + Basically, this method calls transferDbValueToControl - but only if our cursor is positioned + on a valid row. Otherwise, the control is reset. + + @precond + m_xField is not <NULL/> + */ + void initFromField( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet>& _rxForm ); + +private: + sal_Bool connectToField( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet>& _rxForm ); + void resetField(); + + /** does a new validation of the control value + + If necessary, our <member>m_bIsCurrentValueValid</member> member will be adjusted, + and changes will be notified. + + Note that it's not necessary that we're connected to a validator. If we are not, + it's assumed that our value is valid, and this is handled appropriately. + + Use this method if there is a potential that <b>only</b> the validity flag changed. If + any of the other aspects (our current value, or our current text) changed, then + pass <TRUE/> for <member>_bForceNotification</member>. + + @param _bForceNotification + if <TRUE/>, then the validity listeners will be notified, not matter whether the validity + changed. + */ + void recheckValidity( bool _bForceNotification ); + + /// initializes m_pAggPropMultiplexer + void implInitAggMultiplexer( ); + + /// initializes listening at the value property + void implInitValuePropertyListening( ) const; + + /** adds or removes the component as load listener to/from our form, and (if necessary) as RowSetChange listener at + our parent. + + @precond there must no external value binding be in place + */ + void doFormListening( const bool _bStart ); + + inline bool isFormListening() const { return m_bFormListening; } + + /** determines the new value of m_xAmbientForm + */ + void impl_determineAmbientForm_nothrow(); + + /** connects to a value supplier which is an database column. + + The column is take from our parent, which must be a database form respectively row set. + + @precond The control does not have an external value supplier + + @param _bFromReload + Determines whether the connection is made after the row set has been loaded (<FALSE/>) + or reloaded (<TRUE/>) + + @see impl_disconnectDatabaseColumn_noNotify + */ + void impl_connectDatabaseColumn_noNotify( + bool _bFromReload + ); + + /** disconnects from a value supplier which is an database column + + @precond The control does not have an external value supplier + @see impl_connectDatabaseColumn_noNotify + */ + void impl_disconnectDatabaseColumn_noNotify(); + + /** connects to an external value binding + + <p>Note that by definition, external data bindings superseede the SQL data binding which + is defined by our RowSet-column-related properties. This means that in case we're currently + connected to a database column when this is called, this connection is suspended.</p> + + @precond + the new external binding has already been approved (see <member>impl_approveValueBinding_nolock</member>) + @precond + there currently is no external binding in place + */ + void connectExternalValueBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding, + ControlModelLock& _rInstanceLock + ); + + /** disconnects from an external value binding + + @precond + there currently is an external binding in place + */ + void disconnectExternalValueBinding( ); + + /** connects the component to an external validator + + @precond + there currently is no active validator + @precond + our mutex is currently locked exactly once + */ + void connectValidator( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::validation::XValidator >& _rxValidator + ); + + /** disconnects the component from it's current an external validator + + @precond + there currently is an active validator + @precond + our mutex is currently locked exactly once + */ + void disconnectValidator( ); + + /** called from within <member scope="com::sun::star:::form::binding">XBindableValue::setValueBinding</member> + to approve the new binding + + The default implementation approves the binding if and only if it is not <NULL/>, and supports + the type returned by getExternalValueType. + + @param _rxBinding + the binding which applies for being responsible for our value, Must not be + <NULL/> + @return + <TRUE/> if and only if the given binding can supply values in the proper type + + @seealso getExternalValueType + */ + sal_Bool impl_approveValueBinding_nolock( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + ); +}; + + //========================================================================= + //= inlines + //========================================================================= + inline void ControlModelLock::acquire() + { + m_rModel.lockInstance( OControlModel::LockAccess() ); + m_bLocked = true; + } + inline void ControlModelLock::release() + { + OSL_ENSURE( m_bLocked, "ControlModelLock::release: not locked!" ); + m_bLocked = false; + + if ( 0 == m_rModel.unlockInstance( OControlModel::LockAccess() ) ) + impl_notifyAll_nothrow(); + } + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_FORMCOMPONENT_HXX_ + |