diff options
Diffstat (limited to 'forms/source/component')
80 files changed, 31744 insertions, 0 deletions
diff --git a/forms/source/component/BaseListBox.hxx b/forms/source/component/BaseListBox.hxx new file mode 100644 index 000000000000..4e7d112bac80 --- /dev/null +++ b/forms/source/component/BaseListBox.hxx @@ -0,0 +1,43 @@ +/************************************************************************* + * + * 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_BASELISTBOX_HXX_ +#define _FORMS_BASELISTBOX_HXX_ + +//......................................................................... +namespace frm +{ + +const sal_uInt16 ENTRY_NOT_FOUND = 0xFFFF; +const sal_uInt16 BOUNDCOLUMN = 0x0001; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_BASELISTBOX_HXX_ + diff --git a/forms/source/component/Button.cxx b/forms/source/component/Button.cxx new file mode 100644 index 000000000000..6a326f749bdc --- /dev/null +++ b/forms/source/component/Button.cxx @@ -0,0 +1,780 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "Button.hxx" + +#include <com/sun/star/awt/XVclWindowPeer.hpp> + +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> +#include <tools/diagnose_ex.h> +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using ::com::sun::star::frame::XDispatchProviderInterceptor; + +//================================================================== +//= OButtonModel +//================================================================== +DBG_NAME(OButtonModel) +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OButtonModel(_rxFactory)); +} + +//------------------------------------------------------------------ +OButtonModel::OButtonModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseModel( _rxFactory, VCL_CONTROLMODEL_COMMANDBUTTON, FRM_SUN_CONTROL_COMMANDBUTTON ) + // use the old control name for compatibility reasons + ,m_aResetHelper( *this, m_aMutex ) + ,m_eDefaultState( STATE_NOCHECK ) +{ + DBG_CTOR( OButtonModel, NULL ); + m_nClassId = FormComponentType::COMMANDBUTTON; +} + +//------------------------------------------------------------------ +Any SAL_CALL OButtonModel::queryAggregation( const Type& _type ) throw(RuntimeException) +{ + Any aReturn = OClickableImageBaseModel::queryAggregation( _type ); + if ( !aReturn.hasValue() ) + aReturn = OButtonModel_Base::queryInterface( _type ); + return aReturn; +} + +//------------------------------------------------------------------ +Sequence< Type > OButtonModel::_getTypes() +{ + return ::comphelper::concatSequences( + OClickableImageBaseModel::_getTypes(), + OButtonModel_Base::getTypes() + ); +} + +//------------------------------------------------------------------ +OButtonModel::OButtonModel( const OButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OClickableImageBaseModel( _pOriginal, _rxFactory ) + ,m_aResetHelper( *this, m_aMutex ) + ,m_eDefaultState( _pOriginal->m_eDefaultState ) +{ + DBG_CTOR( OButtonModel, NULL ); + m_nClassId = FormComponentType::COMMANDBUTTON; + + implInitializeImageURL(); +} + +//------------------------------------------------------------------------------ +OButtonModel::~OButtonModel() +{ + DBG_DTOR(OButtonModel, NULL); +} + +//------------------------------------------------------------------------------ +void OButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 6, OClickableImageBaseModel ) + DECL_PROP1( BUTTONTYPE, FormButtonType, BOUND ); + DECL_PROP1( DEFAULT_STATE, sal_Int16, BOUND ); + DECL_PROP1( DISPATCHURLINTERNAL, sal_Bool, BOUND ); + DECL_PROP1( TARGET_URL, ::rtl::OUString, BOUND ); + DECL_PROP1( TARGET_FRAME, ::rtl::OUString, BOUND ); + DECL_PROP1( TABINDEX, sal_Int16, BOUND ); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OButtonModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OButtonModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OClickableImageBaseModel::getSupportedServiceNames(); + aSupported.realloc( aSupported.getLength() + 1 ); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_COMMANDBUTTON; + + return aSupported; +} + +//------------------------------------------------------------------------------ +::rtl::OUString OButtonModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_COMMANDBUTTON; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OClickableImageBaseModel::write(_rxOutStream); + + _rxOutStream->writeShort(0x0003); // Version + + { + OStreamSection aSection( _rxOutStream.get() ); + // this will allow readers to skip unknown bytes in their dtor + + _rxOutStream->writeShort( (sal_uInt16)m_eButtonType ); + + ::rtl::OUString sTmp = INetURLObject::decode( m_sTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS); + _rxOutStream << sTmp; + _rxOutStream << m_sTargetFrame; + writeHelpTextCompatibly(_rxOutStream); + _rxOutStream << isDispatchUrlInternal(); + } +} + +//------------------------------------------------------------------------------ +void OButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OClickableImageBaseModel::read(_rxInStream); + + sal_uInt16 nVersion = _rxInStream->readShort(); // Version + switch (nVersion) + { + case 0x0001: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + + _rxInStream >> m_sTargetURL; + _rxInStream >> m_sTargetFrame; + } + break; + + case 0x0002: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + + _rxInStream >> m_sTargetURL; + _rxInStream >> m_sTargetFrame; + readHelpTextCompatibly(_rxInStream); + } + break; + + case 0x0003: + { + OStreamSection aSection( _rxInStream.get() ); + // this will skip any unknown bytes in it's dtor + + // button type + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + + // URL + _rxInStream >> m_sTargetURL; + + // target frame + _rxInStream >> m_sTargetFrame; + + // help text + readHelpTextCompatibly(_rxInStream); + + // DispatchInternal + sal_Bool bDispath; + _rxInStream >> bDispath; + setDispatchUrlInternal(bDispath); + } + break; + + default: + DBG_ERROR("OButtonModel::read : unknown version !"); + m_eButtonType = FormButtonType_PUSH; + m_sTargetURL = ::rtl::OUString(); + m_sTargetFrame = ::rtl::OUString(); + break; + } +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::disposing() +{ + m_aResetHelper.disposing(); + OClickableImageBaseModel::disposing(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::reset() throw (RuntimeException) +{ + if ( !m_aResetHelper.approveReset() ) + return; + + impl_resetNoBroadcast_nothrow(); + + m_aResetHelper.notifyResetted(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::addResetListener( const Reference< XResetListener >& _listener ) throw (RuntimeException) +{ + m_aResetHelper.addResetListener( _listener ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::removeResetListener( const Reference< XResetListener >& _listener ) throw (RuntimeException) +{ + m_aResetHelper.removeResetListener( _listener ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const +{ + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_STATE: + _rValue <<= (sal_Int16)m_eDefaultState; + break; + + default: + OClickableImageBaseModel::getFastPropertyValue( _rValue, _nHandle ); + break; + } +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) +{ + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_STATE: + { + sal_Int16 nDefaultState( (sal_Int16)STATE_NOCHECK ); + OSL_VERIFY( _rValue >>= nDefaultState ); + m_eDefaultState = (ToggleState)nDefaultState; + impl_resetNoBroadcast_nothrow(); + } + break; + + default: + OClickableImageBaseModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + break; + } +} + +//-------------------------------------------------------------------- +sal_Bool SAL_CALL OButtonModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException) +{ + sal_Bool bModified = sal_False; + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_STATE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_eDefaultState ); + break; + + default: + bModified = OClickableImageBaseModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + break; + } + return bModified; +} + +//-------------------------------------------------------------------- +Any OButtonModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const +{ + Any aDefault; + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_STATE: + aDefault <<= (sal_Int16)STATE_NOCHECK; + break; + + default: + aDefault = OClickableImageBaseModel::getPropertyDefaultByHandle( _nHandle ); + break; + } + return aDefault; +} + +//-------------------------------------------------------------------- +void OButtonModel::impl_resetNoBroadcast_nothrow() +{ + try + { + setPropertyValue( PROPERTY_STATE, getPropertyValue( PROPERTY_DEFAULT_STATE ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//================================================================== +// OButtonControl +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OButtonControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OButtonControl::_getTypes() +{ + return ::comphelper::concatSequences( + OButtonControl_BASE::getTypes(), + OClickableImageBaseControl::_getTypes(), + OFormNavigationHelper::getTypes() + ); +} + +//------------------------------------------------------------------------------ +StringSequence OButtonControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OClickableImageBaseControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_COMMANDBUTTON; + return aSupported; +} + +//------------------------------------------------------------------------------ +OButtonControl::OButtonControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseControl(_rxFactory, VCL_CONTROL_COMMANDBUTTON) + ,OFormNavigationHelper( _rxFactory ) + ,m_nClickEvent( 0 ) + ,m_nTargetUrlFeatureId( -1 ) + ,m_bEnabledByPropertyValue( sal_False ) +{ + increment(m_refCount); + { + // als ActionListener anmelden + Reference<XButton> xButton; + query_aggregation( m_xAggregate, xButton); + if (xButton.is()) + xButton->addActionListener(this); + } + // Refcount bei 1 fuer Listener + decrement(m_refCount); +} + +//------------------------------------------------------------------------------ +OButtonControl::~OButtonControl() +{ + if (m_nClickEvent) + Application::RemoveUserEvent(m_nClickEvent); +} + +// UNO Anbindung +//------------------------------------------------------------------------------ +Any SAL_CALL OButtonControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + // if asked for the XTypeProvider, don't let OButtonControl_BASE do this + Any aReturn; + if ( !_rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) ) + aReturn = OButtonControl_BASE::queryInterface( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = OClickableImageBaseControl::queryAggregation( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = OFormNavigationHelper::queryInterface( _rType ); + + return aReturn; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::disposing() +{ + startOrStopModelPropertyListening( false ); + + OClickableImageBaseControl::disposing(); + OFormNavigationHelper::dispose(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::disposing( const EventObject& _rSource ) throw( RuntimeException ) +{ + OControl::disposing( _rSource ); + OFormNavigationHelper::disposing( _rSource ); +} + +// ActionListener +//------------------------------------------------------------------------------ +void OButtonControl::actionPerformed(const ActionEvent& /*rEvent*/) throw ( ::com::sun::star::uno::RuntimeException) +{ + // Asynchron fuer starutil::URL-Button + sal_uInt32 n = Application::PostUserEvent( LINK(this, OButtonControl,OnClick) ); + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_nClickEvent = n; + } +} + +//------------------------------------------------------------------------------ +IMPL_LINK( OButtonControl, OnClick, void*, EMPTYARG ) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + m_nClickEvent = 0; + + if (m_aApproveActionListeners.getLength()) + { + // if there are listeners, start the action in an own thread, to not allow + // them to block us here (we're in the application's main thread) + getImageProducerThread()->addEvent(); + } + else + { + // Sonst nicht. Dann darf man aber auf keinen Fal die Listener + // benachrichtigen, auch dann nicht, wenn er spaeter hinzukommt. + aGuard.clear(); + + // recognize the button type + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (!xSet.is()) + return 0L; + + if (FormButtonType_PUSH == *(FormButtonType*)xSet->getPropertyValue(PROPERTY_BUTTONTYPE).getValue()) + { + // notify the action listeners for a push button + ::cppu::OInterfaceIteratorHelper aIter(m_aActionListeners); + ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand); + while(aIter.hasMoreElements() ) + { + // catch exceptions + // and catch them on a per-listener basis - if one listener fails, the others still need + // to get notified + // 97676 - 21.02.2002 - fs@openoffice.org + try + { + static_cast< XActionListener* >( aIter.next() )->actionPerformed(aEvt); + } +#ifdef DBG_UTIL + catch( const RuntimeException& ) + { + // silent this + } +#endif + catch( const Exception& ) + { + DBG_ERROR( "OButtonControl::OnClick: caught a exception other than RuntimeException!" ); + } + } + } + else + actionPerformed_Impl( sal_False, ::com::sun::star::awt::MouseEvent() ); + } + return 0L; +} + +//------------------------------------------------------------------------------ +void OButtonControl::actionPerformed_Impl( sal_Bool _bNotifyListener, const ::com::sun::star::awt::MouseEvent& _rEvt ) +{ + { + sal_Int16 nFeatureId = -1; + { + ::osl::MutexGuard aGuard( m_aMutex ); + nFeatureId = m_nTargetUrlFeatureId; + } + + if ( nFeatureId != -1 ) + { + if ( !approveAction() ) + return; + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + dispatch( nFeatureId ); + return; + } + } + + OClickableImageBaseControl::actionPerformed_Impl( _bNotifyListener, _rEvt ); +} + +// XButton +//------------------------------------------------------------------------------ +void OButtonControl::setLabel(const ::rtl::OUString& Label) throw( RuntimeException ) +{ + Reference<XButton> xButton; + query_aggregation( m_xAggregate, xButton ); + if (xButton.is()) + xButton->setLabel(Label); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::setActionCommand(const ::rtl::OUString& _rCommand) throw( RuntimeException ) +{ + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_aActionCommand = _rCommand; + } + + Reference<XButton> xButton; + query_aggregation( m_xAggregate, xButton); + if (xButton.is()) + xButton->setActionCommand(_rCommand); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::addActionListener(const Reference<XActionListener>& _rxListener) throw( RuntimeException ) +{ + m_aActionListeners.addInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::removeActionListener(const Reference<XActionListener>& _rxListener) throw( RuntimeException ) +{ + m_aActionListeners.removeInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +class DoPropertyListening +{ +private: + Reference< XPropertySet > m_xProps; + Reference< XPropertyChangeListener > m_xListener; + bool m_bStartListening; + +public: + DoPropertyListening( + const Reference< XInterface >& _rxComponent, + const Reference< XPropertyChangeListener >& _rxListener, + bool _bStart + ); + + void handleListening( const ::rtl::OUString& _rPropertyName ); +}; + +//.............................................................................. +DoPropertyListening::DoPropertyListening( + const Reference< XInterface >& _rxComponent, const Reference< XPropertyChangeListener >& _rxListener, + bool _bStart ) + :m_xProps( _rxComponent, UNO_QUERY ) + ,m_xListener( _rxListener ) + ,m_bStartListening( _bStart ) +{ + DBG_ASSERT( m_xProps.is() || !_rxComponent.is(), "DoPropertyListening::DoPropertyListening: valid component, but no property set!" ); + DBG_ASSERT( m_xListener.is(), "DoPropertyListening::DoPropertyListening: invalid listener!" ); +} + +//.............................................................................. +void DoPropertyListening::handleListening( const ::rtl::OUString& _rPropertyName ) +{ + if ( m_xProps.is() ) + { + if ( m_bStartListening ) + m_xProps->addPropertyChangeListener( _rPropertyName, m_xListener ); + else + m_xProps->removePropertyChangeListener( _rPropertyName, m_xListener ); + } +} + +//------------------------------------------------------------------------------ +void OButtonControl::startOrStopModelPropertyListening( bool _bStart ) +{ + DoPropertyListening aListeningHandler( getModel(), this, _bStart ); + aListeningHandler.handleListening( PROPERTY_TARGET_URL ); + aListeningHandler.handleListening( PROPERTY_BUTTONTYPE ); + aListeningHandler.handleListening( PROPERTY_ENABLED ); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OButtonControl::setModel( const Reference< XControlModel >& _rxModel ) throw ( RuntimeException ) +{ + startOrStopModelPropertyListening( false ); + sal_Bool bResult = OClickableImageBaseControl::setModel( _rxModel ); + startOrStopModelPropertyListening( true ); + + m_bEnabledByPropertyValue = sal_True; + Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY ); + if ( xModelProps.is() ) + xModelProps->getPropertyValue( PROPERTY_ENABLED ) >>= m_bEnabledByPropertyValue; + + modelFeatureUrlPotentiallyChanged( ); + + return bResult; +} + +//------------------------------------------------------------------------------ +void OButtonControl::modelFeatureUrlPotentiallyChanged( ) +{ + sal_Int16 nOldUrlFeatureId = m_nTargetUrlFeatureId; + + // doe we have another TargetURL now? If so, we need to update our dispatches + m_nTargetUrlFeatureId = getModelUrlFeatureId( ); + if ( nOldUrlFeatureId != m_nTargetUrlFeatureId ) + { + invalidateSupportedFeaturesSet(); + if ( !isDesignMode() ) + updateDispatches( ); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OButtonControl::propertyChange( const PropertyChangeEvent& _rEvent ) throw ( RuntimeException ) +{ + if ( _rEvent.PropertyName.equals( PROPERTY_TARGET_URL ) + || _rEvent.PropertyName.equals( PROPERTY_BUTTONTYPE ) + ) + { + modelFeatureUrlPotentiallyChanged( ); + } + else if ( _rEvent.PropertyName.equals( PROPERTY_ENABLED ) ) + { + _rEvent.NewValue >>= m_bEnabledByPropertyValue; + } +} + +//------------------------------------------------------------------------------ +namespace +{ + bool isFormControllerURL( const ::rtl::OUString& _rURL ) + { + const sal_Int32 nPrefixLen = URL_CONTROLLER_PREFIX.length; + return ( _rURL.getLength() > nPrefixLen ) + && ( _rURL.compareToAscii( URL_CONTROLLER_PREFIX, nPrefixLen ) == 0 ); + } +} + +//------------------------------------------------------------------------------ +sal_Int16 OButtonControl::getModelUrlFeatureId( ) const +{ + sal_Int16 nFeatureId = -1; + + // some URL related properties of the model + ::rtl::OUString sUrl; + FormButtonType eButtonType = FormButtonType_PUSH; + + Reference< XPropertySet > xModelProps( const_cast< OButtonControl* >( this )->getModel(), UNO_QUERY ); + if ( xModelProps.is() ) + { + xModelProps->getPropertyValue( PROPERTY_TARGET_URL ) >>= sUrl; + xModelProps->getPropertyValue( PROPERTY_BUTTONTYPE ) >>= eButtonType; + } + + // are we an URL button? + if ( eButtonType == FormButtonType_URL ) + { + // is it a feature URL? + if ( isFormControllerURL( sUrl ) ) + { + OFormNavigationMapper aMapper( m_aContext.getLegacyServiceFactory() ); + nFeatureId = aMapper.getFeatureId( sUrl ); + } + } + + return nFeatureId; +} + +//------------------------------------------------------------------ +void SAL_CALL OButtonControl::setDesignMode( sal_Bool _bOn ) throw( RuntimeException ) +{ + OClickableImageBaseControl::setDesignMode( _bOn ); + + if ( _bOn ) + disconnectDispatchers(); + else + connectDispatchers(); + // this will connect if not already connected and just update else +} + +//------------------------------------------------------------------------------ +void OButtonControl::getSupportedFeatures( ::std::vector< sal_Int16 >& /* [out] */ _rFeatureIds ) +{ + if ( -1 != m_nTargetUrlFeatureId ) + _rFeatureIds.push_back( m_nTargetUrlFeatureId ); +} + +//------------------------------------------------------------------ +void OButtonControl::featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled ) +{ + if ( _nFeatureId == m_nTargetUrlFeatureId ) + { + // enable or disable our peer, according to the new state + Reference< XVclWindowPeer > xPeer( getPeer(), UNO_QUERY ); + if ( xPeer.is() ) + xPeer->setProperty( PROPERTY_ENABLED, makeAny( m_bEnabledByPropertyValue ? _bEnabled : sal_False ) ); + // if we're disabled according to our model's property, then + // we don't care for the feature state, but *are* disabled. + // If the model's property states that we're enabled, then we *do* + // care for the feature state + } + + // base class + OFormNavigationHelper::featureStateChanged( _nFeatureId, _bEnabled ); +} + +//------------------------------------------------------------------ +void OButtonControl::allFeatureStatesChanged( ) +{ + if ( -1 != m_nTargetUrlFeatureId ) + // we have only one supported feature, so simulate it has changed ... + featureStateChanged( m_nTargetUrlFeatureId, isEnabled( m_nTargetUrlFeatureId ) ); + + // base class + OFormNavigationHelper::allFeatureStatesChanged( ); +} + +//------------------------------------------------------------------ +bool OButtonControl::isEnabled( sal_Int16 _nFeatureId ) const +{ + if ( const_cast< OButtonControl* >( this )->isDesignMode() ) + // TODO: the model property? + return true; + + return OFormNavigationHelper::isEnabled( _nFeatureId ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) +{ + OClickableImageBaseControl::registerDispatchProviderInterceptor( _rxInterceptor ); + OFormNavigationHelper::registerDispatchProviderInterceptor( _rxInterceptor ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OButtonControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) +{ + OClickableImageBaseControl::releaseDispatchProviderInterceptor( _rxInterceptor ); + OFormNavigationHelper::releaseDispatchProviderInterceptor( _rxInterceptor ); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Button.hxx b/forms/source/component/Button.hxx new file mode 100644 index 000000000000..c3528f9f86d2 --- /dev/null +++ b/forms/source/component/Button.hxx @@ -0,0 +1,210 @@ +/************************************************************************* + * + * 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 _FRM_BUTTON_HXX_ +#define _FRM_BUTTON_HXX_ + +#include "clickableimage.hxx" +#include "togglestate.hxx" +#include "formnavigation.hxx" +#include "resettable.hxx" + +#include <com/sun/star/awt/MouseEvent.hpp> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/awt/ActionEvent.hpp> +#include <com/sun/star/awt/XActionListener.hpp> +#include <com/sun/star/awt/XButton.hpp> +#include <com/sun/star/form/XReset.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> + +#include <cppuhelper/implbase1.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OButtonModel +//================================================================== +typedef ::cppu::ImplHelper1 < ::com::sun::star::form::XReset + > OButtonModel_Base; +class OButtonModel :public OClickableImageBaseModel + ,public OButtonModel_Base +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( OButtonModel ); + + // UNO + DECLARE_UNO3_AGG_DEFAULTS( OButtonModel, OClickableImageBaseModel ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(::com::sun::star::uno::RuntimeException); + + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +// ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OButtonModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + +// ::com::sun::star::io::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); + + // 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); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // XPropertySet and friends + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + 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 ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // OComponentHelper + virtual void SAL_CALL disposing(); + +protected: + DECLARE_XCLONEABLE(); + +private: + void impl_resetNoBroadcast_nothrow(); + + using ::cppu::OPropertySetHelper::getFastPropertyValue; + +private: + ResetHelper m_aResetHelper; + + // <properties> + ToggleState m_eDefaultState; // the default check state + // </properties> +protected: + using OClickableImageBaseModel::disposing; +}; + +//================================================================== +// OButtonControl +//================================================================== +typedef ::cppu::ImplHelper3 < ::com::sun::star::awt::XButton + , ::com::sun::star::awt::XActionListener + , ::com::sun::star::beans::XPropertyChangeListener + > OButtonControl_BASE; + +class OButtonControl :public OButtonControl_BASE + ,public OClickableImageBaseControl + ,public OFormNavigationHelper +{ +private: + sal_uInt32 m_nClickEvent; + sal_Int16 m_nTargetUrlFeatureId; + /// caches the value of the "Enabled" property of our model + sal_Bool m_bEnabledByPropertyValue; + +protected: + + // UNO Anbindung + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OButtonControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + virtual ~OButtonControl(); + + // XServiceInfo + IMPLEMENTATION_NAME(OButtonControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OButtonControl, OClickableImageBaseControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XActionListener + virtual void SAL_CALL actionPerformed(const ::com::sun::star::awt::ActionEvent& rEvent) throw ( ::com::sun::star::uno::RuntimeException); + + // XButton + virtual void SAL_CALL addActionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeActionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLabel(const ::rtl::OUString& Label) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setActionCommand(const ::rtl::OUString& _rCommand) throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw(::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // XControl + virtual sal_Bool SAL_CALL setModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& _rxModel ) throw ( ::com::sun::star::uno::RuntimeException ); + void SAL_CALL setDesignMode(sal_Bool bOn) throw (::com::sun::star::uno::RuntimeException); + +protected: + // OFormNavigationHelper overriables + virtual void getSupportedFeatures( ::std::vector< sal_Int16 >& /* [out] */ _rFeatureIds ); + virtual void featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled ); + virtual void allFeatureStatesChanged( ); + virtual bool isEnabled( sal_Int16 _nFeatureId ) const; + + // XDispatchProviderInterception disambiguaiton + virtual void SAL_CALL registerDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL releaseDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + + // OImageControl overridables + virtual void actionPerformed_Impl( sal_Bool bNotifyListener, const ::com::sun::star::awt::MouseEvent& _rEvt ); + +private: + DECL_LINK( OnClick, void* ); + + /** to be called whenever the feature URL represented by our model has potentially changed + */ + void modelFeatureUrlPotentiallyChanged( ); + + /** retrieves the feature id (see OFormNavigationHelper) of the TargetURL of + the model. + */ + sal_Int16 getModelUrlFeatureId( ) const; + + /** starts or stops listening for changes in model properties we're interested in + */ + void startOrStopModelPropertyListening( bool _bStart ); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_BUTTON_HXX_ + diff --git a/forms/source/component/CheckBox.cxx b/forms/source/component/CheckBox.cxx new file mode 100644 index 000000000000..3e2531f92f5c --- /dev/null +++ b/forms/source/component/CheckBox.cxx @@ -0,0 +1,275 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "CheckBox.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/basicio.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//================================================================== +//= OCheckBoxControl +//================================================================== + +//------------------------------------------------------------------ +OCheckBoxControl::OCheckBoxControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_CHECKBOX) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OCheckBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OCheckBoxControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OCheckBoxControl::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_CHECKBOX; + return aSupported; +} + +//================================================================== +//= OCheckBoxModel +//================================================================== + +//================================================================== +InterfaceRef SAL_CALL OCheckBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OCheckBoxModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( OCheckBoxModel ) +//------------------------------------------------------------------ +OCheckBoxModel::OCheckBoxModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OReferenceValueComponent( _rxFactory, VCL_CONTROLMODEL_CHECKBOX, FRM_SUN_CONTROL_CHECKBOX, sal_True ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( OCheckBoxModel, NULL ); + + m_nClassId = FormComponentType::CHECKBOX; + initValueProperty( PROPERTY_STATE, PROPERTY_ID_STATE ); +} + +//------------------------------------------------------------------ +OCheckBoxModel::OCheckBoxModel( const OCheckBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OReferenceValueComponent( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OCheckBoxModel, NULL ); +} + +//------------------------------------------------------------------------------ +OCheckBoxModel::~OCheckBoxModel() +{ + DBG_DTOR( OCheckBoxModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OCheckBoxModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OCheckBoxModel::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) +{ + StringSequence aSupported = OReferenceValueComponent::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_CHECKBOX; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_CHECKBOX; + *pStoreTo++ = BINDABLE_DATABASE_CHECK_BOX; + + return aSupported; +} + +//------------------------------------------------------------------------------ +void OCheckBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 1, OReferenceValueComponent ) + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OCheckBoxModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_CHECKBOX; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OCheckBoxModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) + throw(stario::IOException, RuntimeException) +{ + OReferenceValueComponent::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0003); + // Properties + _rxOutStream << getReferenceValue(); + _rxOutStream << (sal_Int16)getDefaultChecked(); + writeHelpTextCompatibly(_rxOutStream); + // from version 0x0003 : common properties + writeCommonProperties(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OCheckBoxModel::read(const Reference<stario::XObjectInputStream>& _rxInStream) throw(stario::IOException, RuntimeException) +{ + OReferenceValueComponent::read(_rxInStream); + osl::MutexGuard aGuard(m_aMutex); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + + ::rtl::OUString sReferenceValue; + sal_Int16 nDefaultChecked( 0 ); + switch ( nVersion ) + { + case 0x0001: + _rxInStream >> sReferenceValue; + nDefaultChecked = _rxInStream->readShort(); + break; + case 0x0002: + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + readHelpTextCompatibly( _rxInStream ); + break; + case 0x0003: + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + readHelpTextCompatibly(_rxInStream); + readCommonProperties(_rxInStream); + break; + default: + DBG_ERROR("OCheckBoxModel::read : unknown version !"); + defaultCommonProperties(); + break; + } + setReferenceValue( sReferenceValue ); + setDefaultChecked( static_cast< ToggleState >( nDefaultChecked ) ); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + // (not if we don't have a control source - the "State" property acts like it is persistent, then + resetNoBroadcast(); +} + +//------------------------------------------------------------------------------ +Any OCheckBoxModel::translateDbColumnToControlValue() +{ + Any aValue; + + ////////////////////////////////////////////////////////////////// + // Wert an ControlModel setzen + sal_Bool bValue = m_xColumn->getBoolean(); + if ( m_xColumn->wasNull() ) + { + sal_Bool bTriState = sal_True; + if ( m_xAggregateSet.is() ) + m_xAggregateSet->getPropertyValue( PROPERTY_TRISTATE ) >>= bTriState; + aValue <<= (sal_Int16)( bTriState ? STATE_DONTKNOW : getDefaultChecked() ); + } + else + aValue <<= (sal_Int16)( bValue ? STATE_CHECK : STATE_NOCHECK ); + + return aValue; +} + +//----------------------------------------------------------------------------- +sal_Bool OCheckBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + OSL_PRECOND( m_xColumnUpdate.is(), "OCheckBoxModel::commitControlValueToDbColumn: not bound!" ); + if ( m_xColumnUpdate.is() ) + { + Any aControlValue( m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) ); + try + { + sal_Int16 nValue = STATE_DONTKNOW; + aControlValue >>= nValue; + switch (nValue) + { + case STATE_DONTKNOW: + m_xColumnUpdate->updateNull(); + break; + case STATE_CHECK: + m_xColumnUpdate->updateBoolean( sal_True ); + break; + case STATE_NOCHECK: + m_xColumnUpdate->updateBoolean( sal_False ); + break; + default: + DBG_ERROR("OCheckBoxModel::commitControlValueToDbColumn: invalid value !"); + } + } + catch(Exception&) + { + DBG_ERROR("OCheckBoxModel::commitControlValueToDbColumn: could not commit !"); + } + } + return sal_True; +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/CheckBox.hxx b/forms/source/component/CheckBox.hxx new file mode 100644 index 000000000000..21073c27306d --- /dev/null +++ b/forms/source/component/CheckBox.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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_CHECKBOX_HXX_ +#define _FORMS_CHECKBOX_HXX_ + +#include "refvaluecomponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +//= OCheckBoxModel +//================================================================== +class OCheckBoxModel :public OReferenceValueComponent +{ +protected: + sal_Int16 getState(const ::com::sun::star::uno::Any& rValue); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OCheckBoxModel ); + + // XServiceInfo + IMPLEMENTATION_NAME(OCheckBoxModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // 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); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + DECLARE_XCLONEABLE(); + + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); +}; + +//================================================================== +//= OCheckBoxControl +//================================================================== +class OCheckBoxControl : public OBoundControl +{ +public: + OCheckBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(OCheckBoxControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_CHECKBOX_HXX_ + diff --git a/forms/source/component/Columns.cxx b/forms/source/component/Columns.cxx new file mode 100644 index 000000000000..a93d121d4b99 --- /dev/null +++ b/forms/source/component/Columns.cxx @@ -0,0 +1,602 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Columns.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "property.hxx" +#include "componenttools.hxx" +#include "ids.hxx" +#include "findpos.hxx" +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/io/XObjectInputStream.hpp> +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <comphelper/sequence.hxx> +#include <comphelper/property.hxx> +#include <comphelper/basicio.hxx> +#include "services.hxx" +#ifndef _FRM_RESOURCE_HRC_ +#include "frm_resource.hrc" +#endif +#include <tools/debug.hxx> +#include <rtl/uuid.h> +#include <rtl/memory.h> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +const sal_uInt16 WIDTH = 0x0001; +const sal_uInt16 ALIGN = 0x0002; +const sal_uInt16 OLD_HIDDEN = 0x0004; +const sal_uInt16 COMPATIBLE_HIDDEN = 0x0008; + +//------------------------------------------------------------------------------ +const StringSequence& getColumnTypes() +{ + static StringSequence aColumnTypes(10); + if (!aColumnTypes.getConstArray()[0].getLength()) + { + ::rtl::OUString* pNames = aColumnTypes.getArray(); + pNames[TYPE_CHECKBOX] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CheckBox" ) ); + pNames[TYPE_COMBOBOX] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ComboBox" ) ); + pNames[TYPE_CURRENCYFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CurrencyField" ) ); + pNames[TYPE_DATEFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateField" ) ); + pNames[TYPE_FORMATTEDFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FormattedField" ) ); + pNames[TYPE_LISTBOX] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListBox" ) ); + pNames[TYPE_NUMERICFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NumericField" ) ); + pNames[TYPE_PATTERNFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PatternField" ) ); + pNames[TYPE_TEXTFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TextField" ) ); + pNames[TYPE_TIMEFIELD] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TimeField" ) ); + } + return aColumnTypes; +} + +//------------------------------------------------------------------------------ +sal_Int32 getColumnTypeByModelName(const ::rtl::OUString& aModelName) +{ + const ::rtl::OUString aModelPrefix = ::rtl::OUString::createFromAscii("com.sun.star.form.component."); + const ::rtl::OUString aCompatibleModelPrefix = ::rtl::OUString::createFromAscii("stardiv.one.form.component."); + + sal_Int32 nTypeId = -1; + if (aModelName == FRM_COMPONENT_EDIT) + nTypeId = TYPE_TEXTFIELD; + else + { + sal_Int32 nPrefixPos = aModelName.indexOf(aModelPrefix); +#ifdef DBG_UTIL + sal_Int32 nCompatiblePrefixPos = aModelName.indexOf(aCompatibleModelPrefix); +#endif + DBG_ASSERT( (nPrefixPos != -1) || (nCompatiblePrefixPos != -1), + "::getColumnTypeByModelName() : wrong servivce !"); + + ::rtl::OUString aColumnType = (nPrefixPos != -1) + ? aModelName.copy(aModelPrefix.getLength()) + : aModelName.copy(aCompatibleModelPrefix.getLength()); + + const StringSequence& rColumnTypes = getColumnTypes(); + nTypeId = ::detail::findPos(aColumnType, rColumnTypes); + } + return nTypeId; +} + +/*************************************************************************/ + +//------------------------------------------------------------------ +const Sequence<sal_Int8>& OGridColumn::getUnoTunnelImplementationId() +{ + static Sequence< sal_Int8 > * pSeq = 0; + if( !pSeq ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +//------------------------------------------------------------------ +sal_Int64 SAL_CALL OGridColumn::getSomething( const Sequence<sal_Int8>& _rIdentifier) throw(RuntimeException) +{ + sal_Int64 nReturn(0); + + if ( (_rIdentifier.getLength() == 16) + && (0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 )) + ) + { + nReturn = reinterpret_cast<sal_Int64>(this); + } + else + { + Reference< XUnoTunnel > xAggTunnel; + if ( query_aggregation( m_xAggregate, xAggTunnel ) ) + return xAggTunnel->getSomething( _rIdentifier ); + } + return nReturn; +} + +//------------------------------------------------------------------ +Sequence<sal_Int8> SAL_CALL OGridColumn::getImplementationId() throw(RuntimeException) +{ + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------ +Sequence<Type> SAL_CALL OGridColumn::getTypes() throw(RuntimeException) +{ + TypeBag aTypes( OGridColumn_BASE::getTypes() ); + // erase the types which we do not support + aTypes.removeType( XFormComponent::static_type() ); + aTypes.removeType( XServiceInfo::static_type() ); + aTypes.removeType( XBindableValue::static_type() ); + aTypes.removeType( XPropertyContainer::static_type() ); + // but re-add their base class(es) + aTypes.addType( XChild::static_type() ); + + Reference< XTypeProvider > xProv; + if ( query_aggregation( m_xAggregate, xProv )) + aTypes.addTypes( xProv->getTypes() ); + + return aTypes.getTypes(); +} + +//------------------------------------------------------------------ +Any SAL_CALL OGridColumn::queryAggregation( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn; + // some functionality at our aggregate cannot be reasonably fullfilled here. + if ( _rType.equals(::getCppuType(static_cast< Reference< XFormComponent >* >(NULL))) + || _rType.equals(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) + || _rType.equals(::getCppuType(static_cast< Reference< XBindableValue >* >(NULL))) + || _rType.equals(::getCppuType(static_cast< Reference< XPropertyContainer >* >(NULL))) + ) + return aReturn; + + aReturn = OGridColumn_BASE::queryAggregation(_rType); + if (!aReturn.hasValue()) + { + aReturn = OPropertySetAggregationHelper::queryInterface(_rType); + if (!aReturn.hasValue() && m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + + return aReturn; +} + +DBG_NAME(OGridColumn); +//------------------------------------------------------------------------------ +OGridColumn::OGridColumn( const comphelper::ComponentContext& _rContext, const ::rtl::OUString& _sModelName ) + :OGridColumn_BASE(m_aMutex) + ,OPropertySetAggregationHelper(OGridColumn_BASE::rBHelper) + ,m_aHidden( makeAny( sal_False ) ) + ,m_aContext( _rContext ) + ,m_aModelName(_sModelName) +{ + DBG_CTOR(OGridColumn,NULL); + + // Anlegen des UnoControlModels + if ( m_aModelName.getLength() ) // is there a to-be-aggregated model? + { + increment( m_refCount ); + + { + m_xAggregate.set( m_aContext.createComponent( m_aModelName ), UNO_QUERY ); + setAggregation( m_xAggregate ); + } + + if ( m_xAggregate.is() ) + { // don't omit those brackets - they ensure that the following temporary is properly deleted + m_xAggregate->setDelegator( static_cast< ::cppu::OWeakObject* >( this ) ); + } + + // Refcount wieder bei NULL + decrement( m_refCount ); + } +} + +//------------------------------------------------------------------------------ +OGridColumn::OGridColumn( const OGridColumn* _pOriginal ) + :OGridColumn_BASE( m_aMutex ) + ,OPropertySetAggregationHelper( OGridColumn_BASE::rBHelper ) + ,m_aContext( _pOriginal->m_aContext ) +{ + DBG_CTOR(OGridColumn,NULL); + + m_aWidth = _pOriginal->m_aWidth; + m_aAlign = _pOriginal->m_aAlign; + m_aHidden = _pOriginal->m_aHidden; + m_aModelName = _pOriginal->m_aModelName; + m_aLabel = _pOriginal->m_aLabel; + + increment( m_refCount ); + { + { + m_xAggregate = createAggregateClone( _pOriginal ); + setAggregation( m_xAggregate ); + } + + if ( m_xAggregate.is() ) + { // don't omit this brackets - they ensure that the following temporary is properly deleted + m_xAggregate->setDelegator( static_cast< ::cppu::OWeakObject* >( this ) ); + } + } + decrement( m_refCount ); +} + +//------------------------------------------------------------------------------ +OGridColumn::~OGridColumn() +{ + if (!OGridColumn_BASE::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + // freigeben der Agg + if (m_xAggregate.is()) + { + InterfaceRef xIface; + m_xAggregate->setDelegator(xIface); + } + + DBG_DTOR(OGridColumn,NULL); +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OGridColumn::disposing(const EventObject& _rSource) throw(RuntimeException) +{ + OPropertySetAggregationHelper::disposing(_rSource); + + Reference<XEventListener> xEvtLstner; + if (query_aggregation(m_xAggregate, xEvtLstner)) + xEvtLstner->disposing(_rSource); +} + +// OGridColumn_BASE +//----------------------------------------------------------------------------- +void OGridColumn::disposing() +{ + OGridColumn_BASE::disposing(); + OPropertySetAggregationHelper::disposing(); + + Reference<XComponent> xComp; + if (query_aggregation(m_xAggregate, xComp)) + xComp->dispose(); +} + +//------------------------------------------------------------------------------ +void OGridColumn::clearAggregateProperties( Sequence< Property >& _rProps, sal_Bool bAllowDropDown ) +{ + // some properties are not to be exposed to the outer world + ::std::set< ::rtl::OUString > aForbiddenProperties; + aForbiddenProperties.insert( PROPERTY_ALIGN ); + aForbiddenProperties.insert( PROPERTY_AUTOCOMPLETE ); + aForbiddenProperties.insert( PROPERTY_BACKGROUNDCOLOR ); + aForbiddenProperties.insert( PROPERTY_BORDER ); + aForbiddenProperties.insert( PROPERTY_BORDERCOLOR ); + aForbiddenProperties.insert( PROPERTY_ECHO_CHAR ); + aForbiddenProperties.insert( PROPERTY_FILLCOLOR ); + aForbiddenProperties.insert( PROPERTY_FONT ); + aForbiddenProperties.insert( PROPERTY_FONT_NAME ); + aForbiddenProperties.insert( PROPERTY_FONT_STYLENAME ); + aForbiddenProperties.insert( PROPERTY_FONT_FAMILY ); + aForbiddenProperties.insert( PROPERTY_FONT_CHARSET ); + aForbiddenProperties.insert( PROPERTY_FONT_HEIGHT ); + aForbiddenProperties.insert( PROPERTY_FONT_WEIGHT ); + aForbiddenProperties.insert( PROPERTY_FONT_SLANT ); + aForbiddenProperties.insert( PROPERTY_FONT_UNDERLINE ); + aForbiddenProperties.insert( PROPERTY_FONT_STRIKEOUT ); + aForbiddenProperties.insert( PROPERTY_FONT_WORDLINEMODE ); + aForbiddenProperties.insert( PROPERTY_TEXTLINECOLOR ); + aForbiddenProperties.insert( PROPERTY_FONTEMPHASISMARK ); + aForbiddenProperties.insert( PROPERTY_FONTRELIEF ); + aForbiddenProperties.insert( PROPERTY_HARDLINEBREAKS ); + aForbiddenProperties.insert( PROPERTY_HSCROLL ); + aForbiddenProperties.insert( PROPERTY_LABEL ); + aForbiddenProperties.insert( PROPERTY_LINECOLOR ); + aForbiddenProperties.insert( PROPERTY_MULTISELECTION ); + aForbiddenProperties.insert( PROPERTY_PRINTABLE ); + aForbiddenProperties.insert( PROPERTY_TABINDEX ); + aForbiddenProperties.insert( PROPERTY_TABSTOP ); + aForbiddenProperties.insert( PROPERTY_TEXTCOLOR ); + aForbiddenProperties.insert( PROPERTY_VSCROLL ); + aForbiddenProperties.insert( PROPERTY_CONTROLLABEL ); + aForbiddenProperties.insert( PROPERTY_RICH_TEXT ); + aForbiddenProperties.insert( PROPERTY_VERTICAL_ALIGN ); + aForbiddenProperties.insert( PROPERTY_IMAGE_URL ); + aForbiddenProperties.insert( PROPERTY_IMAGE_POSITION ); + aForbiddenProperties.insert( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EnableVisible" ) ) ); + if ( !bAllowDropDown ) + aForbiddenProperties.insert( PROPERTY_DROPDOWN ); + + Sequence< Property > aNewProps( _rProps.getLength() ); + Property* pNewProps = aNewProps.getArray(); + + const Property* pProps = _rProps.getConstArray(); + const Property* pPropsEnd = pProps + _rProps.getLength(); + for ( ; pProps != pPropsEnd; ++pProps ) + { + if ( aForbiddenProperties.find( pProps->Name ) == aForbiddenProperties.end() ) + *pNewProps++ = *pProps; + } + + aNewProps.realloc( pNewProps - aNewProps.getArray() ); + _rProps = aNewProps; +} + +//------------------------------------------------------------------------------ +void OGridColumn::setOwnProperties(Sequence<Property>& aDescriptor) +{ + aDescriptor.realloc(5); + Property* pProperties = aDescriptor.getArray(); + DECL_PROP1(LABEL, ::rtl::OUString, BOUND); + DECL_PROP3(WIDTH, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT); + DECL_PROP3(ALIGN, sal_Int16, BOUND, MAYBEVOID, MAYBEDEFAULT); + DECL_BOOL_PROP2(HIDDEN, BOUND, MAYBEDEFAULT); + DECL_PROP1(COLUMNSERVICENAME, ::rtl::OUString, READONLY); +} + +// Reference<XPropertySet> +//------------------------------------------------------------------------------ +void OGridColumn::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_COLUMNSERVICENAME: + rValue <<= m_aModelName; + break; + case PROPERTY_ID_LABEL: + rValue <<= m_aLabel; + break; + case PROPERTY_ID_WIDTH: + rValue = m_aWidth; + break; + case PROPERTY_ID_ALIGN: + rValue = m_aAlign; + break; + case PROPERTY_ID_HIDDEN: + rValue = m_aHidden; + break; + default: + OPropertySetAggregationHelper::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OGridColumn::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue )throw( IllegalArgumentException ) +{ + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_LABEL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aLabel); + break; + case PROPERTY_ID_WIDTH: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aWidth, ::getCppuType((const sal_Int32*)NULL)); + break; + case PROPERTY_ID_ALIGN: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aAlign, ::getCppuType( (const sal_Int32*)NULL ) ); + // strange enough, css.awt.TextAlign is a 32-bit integer, while the Align property (both here for grid controls + // and for ordinary toolkit controls) is a 16-bit integer. So, allow for 32 bit, but normalize it to 16 bit + if ( bModified ) + { + sal_Int32 nAlign( 0 ); + if ( rConvertedValue >>= nAlign ) + rConvertedValue <<= (sal_Int16)nAlign; + } + break; + case PROPERTY_ID_HIDDEN: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, getBOOL(m_aHidden)); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OGridColumn::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_LABEL: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "invalid type" ); + rValue >>= m_aLabel; + break; + case PROPERTY_ID_WIDTH: + m_aWidth = rValue; + break; + case PROPERTY_ID_ALIGN: + m_aAlign = rValue; + break; + case PROPERTY_ID_HIDDEN: + m_aHidden = rValue; + break; + } +} + + +// XPropertyState +//------------------------------------------------------------------------------ +Any OGridColumn::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_WIDTH: + case PROPERTY_ID_ALIGN: + return Any(); + case PROPERTY_ID_HIDDEN: + return makeAny((sal_Bool)sal_False); + default: + return OPropertySetAggregationHelper::getPropertyDefaultByHandle(nHandle); + } +} + +// XCloneable +//------------------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL OGridColumn::createClone( ) throw (RuntimeException) +{ + OGridColumn* pNewColumn = createCloneColumn(); + return pNewColumn; +} + +//XPersistObject +//------------------------------------------------------------------------------ +void SAL_CALL OGridColumn::write(const Reference<XObjectOutputStream>& _rxOutStream) +{ + // 1. Schreiben des UnoControls + Reference<XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + sal_Int32 nMark = xMark->createMark(); + + sal_Int32 nLen = 0; + _rxOutStream->writeLong(nLen); + + Reference<XPersistObject> xPersist; + if (query_aggregation(m_xAggregate, xPersist)) + xPersist->write(_rxOutStream); + + // feststellen der Laenge + nLen = xMark->offsetToMark(nMark) - 4; + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); + + // 2. Schreiben einer VersionsNummer + _rxOutStream->writeShort(0x0002); + + sal_uInt16 nAnyMask = 0; + if (m_aWidth.getValueType().getTypeClass() == TypeClass_LONG) + nAnyMask |= WIDTH; + + if (m_aAlign.getValueTypeClass() == TypeClass_SHORT) + nAnyMask |= ALIGN; + + nAnyMask |= COMPATIBLE_HIDDEN; + + _rxOutStream->writeShort(nAnyMask); + + if (nAnyMask & WIDTH) + _rxOutStream->writeLong(getINT32(m_aWidth)); + if (nAnyMask & ALIGN) + _rxOutStream->writeShort(getINT16(m_aAlign)); + + // Name + _rxOutStream << m_aLabel; + + // the new place for the hidden flag : after m_aLabel, so older office version read the correct label, too + if (nAnyMask & COMPATIBLE_HIDDEN) + _rxOutStream->writeBoolean(getBOOL(m_aHidden)); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OGridColumn::read(const Reference<XObjectInputStream>& _rxInStream) +{ + // 1. Lesen des UnoControls + sal_Int32 nLen = _rxInStream->readLong(); + if (nLen) + { + Reference<XMarkableStream> xMark(_rxInStream, UNO_QUERY); + sal_Int32 nMark = xMark->createMark(); + Reference<XPersistObject> xPersist; + if (query_aggregation(m_xAggregate, xPersist)) + xPersist->read(_rxInStream); + + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nLen); + xMark->deleteMark(nMark); + } + + // 2. Lesen des Versionsnummer + sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion; + sal_uInt16 nAnyMask = _rxInStream->readShort(); + + if (nAnyMask & WIDTH) + { + sal_Int32 nValue = _rxInStream->readLong(); + m_aWidth <<= (sal_Int32)nValue; + } + + if (nAnyMask & ALIGN) + { + sal_Int16 nValue = _rxInStream->readShort(); + m_aAlign <<= nValue; + } + if (nAnyMask & OLD_HIDDEN) + { + sal_Bool bValue = _rxInStream->readBoolean(); + m_aHidden <<= (sal_Bool)bValue; + } + + // Name + _rxInStream >> m_aLabel; + + if (nAnyMask & COMPATIBLE_HIDDEN) + { + sal_Bool bValue = _rxInStream->readBoolean(); + m_aHidden <<= (sal_Bool)bValue; + } +} + +//------------------------------------------------------------------------------ +IMPL_COLUMN(TextFieldColumn, FRM_SUN_COMPONENT_TEXTFIELD, sal_False); +IMPL_COLUMN(PatternFieldColumn, FRM_SUN_COMPONENT_PATTERNFIELD, sal_False); +IMPL_COLUMN(DateFieldColumn, FRM_SUN_COMPONENT_DATEFIELD, sal_True); +IMPL_COLUMN(TimeFieldColumn, FRM_SUN_COMPONENT_TIMEFIELD, sal_False); +IMPL_COLUMN(NumericFieldColumn, FRM_SUN_COMPONENT_NUMERICFIELD, sal_False); +IMPL_COLUMN(CurrencyFieldColumn, FRM_SUN_COMPONENT_CURRENCYFIELD, sal_False); +IMPL_COLUMN(CheckBoxColumn, FRM_SUN_COMPONENT_CHECKBOX, sal_False); +IMPL_COLUMN(ComboBoxColumn, FRM_SUN_COMPONENT_COMBOBOX, sal_False); +IMPL_COLUMN(ListBoxColumn, FRM_SUN_COMPONENT_LISTBOX, sal_False); +IMPL_COLUMN(FormattedFieldColumn, FRM_SUN_COMPONENT_FORMATTEDFIELD, sal_False); + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Columns.hxx b/forms/source/component/Columns.hxx new file mode 100644 index 000000000000..f52d8db1afa9 --- /dev/null +++ b/forms/source/component/Columns.hxx @@ -0,0 +1,221 @@ +/************************************************************************* + * + * 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 _FRM_COLUMNS_HXX +#define _FRM_COLUMNS_HXX + +#include "cloneable.hxx" +#include "frm_strings.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/io/XObjectInputStream.hpp> +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/util/XCloneable.hpp> +/** === end UNO includes === **/ + +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/propagg.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/compbase2.hxx> +#include <cppuhelper/component.hxx> + +using namespace comphelper; + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OGridColumn +//================================================================== +typedef ::cppu::WeakAggComponentImplHelper2 < ::com::sun::star::lang::XUnoTunnel + , ::com::sun::star::util::XCloneable > OGridColumn_BASE; +class OGridColumn :public ::comphelper::OBaseMutex + ,public OGridColumn_BASE + ,public OPropertySetAggregationHelper + ,public OCloneableAggregation +{ +protected: +// [properties] + ::com::sun::star::uno::Any m_aWidth; // column width + ::com::sun::star::uno::Any m_aAlign; // column alignment + ::com::sun::star::uno::Any m_aHidden; // column hidden? +// [properties] + + ::comphelper::ComponentContext m_aContext; + ::rtl::OUString m_aModelName; + +// [properties] + ::rtl::OUString m_aLabel; // Name der Spalte +// [properties] + +public: + OGridColumn(const ::comphelper::ComponentContext& _rContext, const ::rtl::OUString& _sModelName = ::rtl::OUString()); + OGridColumn(const OGridColumn* _pOriginal ); + virtual ~OGridColumn(); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OGridControlModel, OGridColumn_BASE); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + static const ::com::sun::star::uno::Sequence<sal_Int8>& getUnoTunnelImplementationId(); + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence<sal_Int8>& _rIdentifier) 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(); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream); + virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream); + + // XPropertySet + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() = 0; + 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 OPropertySetAggregationHelper::getFastPropertyValue; + + // ::com::sun::star::beans::XPropertyState + 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); + + const ::rtl::OUString& getModelName() const { return m_aModelName; } + +protected: + static void clearAggregateProperties(::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property>& seqProps, sal_Bool bAllowDropDown); + static void setOwnProperties(::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property>& seqProps); + + virtual OGridColumn* createCloneColumn() const = 0; +}; + +#define DECL_COLUMN(ClassName) \ +class ClassName \ + :public OGridColumn \ + ,public OAggregationArrayUsageHelper< ClassName > \ +{ \ +public: \ + ClassName(const ::comphelper::ComponentContext& _rContext ); \ + ClassName(const ClassName* _pCloneFrom); \ + \ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException); \ + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); \ + \ + virtual void fillProperties( \ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps, \ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps \ + ) const; \ + \ + virtual OGridColumn* createCloneColumn() const; \ +}; + + +#define IMPL_COLUMN(ClassName, Model, bAllowDropDown) \ + ClassName::ClassName( const ::comphelper::ComponentContext& _rContext ) \ + :OGridColumn(_rContext, Model) \ +{ \ +} \ +ClassName::ClassName( const ClassName* _pCloneFrom ) \ + :OGridColumn( _pCloneFrom ) \ +{ \ +} \ +::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> ClassName::getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException) \ +{ \ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) ); \ + return xInfo; \ +} \ +::cppu::IPropertyArrayHelper& ClassName::getInfoHelper() \ +{ \ + return *const_cast<ClassName*>(this)->getArrayHelper(); \ +} \ +void ClassName::fillProperties( \ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps, \ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps \ + ) const \ +{ \ + if (m_xAggregateSet.is()) \ + { \ + _rAggregateProps = m_xAggregateSet->getPropertySetInfo()->getProperties(); \ + clearAggregateProperties(_rAggregateProps, bAllowDropDown); \ + setOwnProperties(_rProps); \ + } \ +} \ +OGridColumn* ClassName::createCloneColumn() const \ +{ \ + return new ClassName( this ); \ +} \ + \ +// column type ids +#define TYPE_CHECKBOX 0 +#define TYPE_COMBOBOX 1 +#define TYPE_CURRENCYFIELD 2 +#define TYPE_DATEFIELD 3 +#define TYPE_FORMATTEDFIELD 4 +#define TYPE_LISTBOX 5 +#define TYPE_NUMERICFIELD 6 +#define TYPE_PATTERNFIELD 7 +#define TYPE_TEXTFIELD 8 +#define TYPE_TIMEFIELD 9 + +// liste aller bekannten columns +const StringSequence& getColumnTypes(); +sal_Int32 getColumnTypeByModelName(const ::rtl::OUString& aModelName); + +// Columns +DECL_COLUMN(TextFieldColumn) +DECL_COLUMN(PatternFieldColumn) +DECL_COLUMN(DateFieldColumn) +DECL_COLUMN(TimeFieldColumn) +DECL_COLUMN(NumericFieldColumn) +DECL_COLUMN(CurrencyFieldColumn) +DECL_COLUMN(CheckBoxColumn) +DECL_COLUMN(ComboBoxColumn) +DECL_COLUMN(ListBoxColumn) +DECL_COLUMN(FormattedFieldColumn) + +#endif // _FRM_COLUMNS_HXX + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/ComboBox.cxx b/forms/source/component/ComboBox.cxx new file mode 100644 index 000000000000..278e561de251 --- /dev/null +++ b/forms/source/component/ComboBox.cxx @@ -0,0 +1,914 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "ComboBox.hxx" +#include "property.hxx" +#include "property.hrc" +#include "services.hxx" + +#include "frm_resource.hxx" +#include "frm_resource.hrc" +#include "BaseListBox.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/SQLErrorEvent.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +/** === end UNO includes === **/ + +#include <comphelper/numbers.hxx> +#include <comphelper/basicio.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbconversion.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/sharedunocomponent.hxx> + +#include <limits.h> + +using namespace dbtools; + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//======================================================================== +// class OComboBoxModel +//======================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OComboBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return (*new OComboBoxModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OComboBoxModel::_getTypes() +{ + return ::comphelper::concatSequences( + OBoundControlModel::_getTypes(), + OEntryListHelper::getTypes(), + OErrorBroadcaster::getTypes() + ); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OComboBoxModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_COMBOBOX; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_COMBOBOX; + *pStoreTo++ = BINDABLE_DATABASE_COMBO_BOX; + + return aSupported; +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OComboBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OBoundControlModel::queryAggregation( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OEntryListHelper::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OErrorBroadcaster::queryInterface( _rType ); + return aReturn; +} + +//------------------------------------------------------------------ +DBG_NAME( OComboBoxModel ) +//------------------------------------------------------------------ +OComboBoxModel::OComboBoxModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_COMBOBOX, FRM_SUN_CONTROL_COMBOBOX, sal_True, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OEntryListHelper( (OControlModel&)*this ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,m_aListRowSet( getContext() ) + ,m_eListSourceType(ListSourceType_TABLE) + ,m_bEmptyIsNull(sal_True) +{ + DBG_CTOR( OComboBoxModel, NULL ); + + m_nClassId = FormComponentType::COMBOBOX; + initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT ); +} + +//------------------------------------------------------------------ +OComboBoxModel::OComboBoxModel( const OComboBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + ,OEntryListHelper( *_pOriginal, (OControlModel&)*this ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,m_aListRowSet( getContext() ) + ,m_aListSource( _pOriginal->m_aListSource ) + ,m_aDefaultText( _pOriginal->m_aDefaultText ) + ,m_eListSourceType( _pOriginal->m_eListSourceType ) + ,m_bEmptyIsNull( _pOriginal->m_bEmptyIsNull ) +{ + DBG_CTOR( OComboBoxModel, NULL ); +} + +//------------------------------------------------------------------ +OComboBoxModel::~OComboBoxModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR( OComboBoxModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OComboBoxModel ) + +//------------------------------------------------------------------------------ +void OComboBoxModel::disposing() +{ + OBoundControlModel::disposing(); + OEntryListHelper::disposing(); + OErrorBroadcaster::disposing(); + m_xFormatter = NULL; +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const +{ + switch (_nHandle) + { + case PROPERTY_ID_LISTSOURCETYPE: + _rValue <<= m_eListSourceType; + break; + + case PROPERTY_ID_LISTSOURCE: + _rValue <<= m_aListSource; + break; + + case PROPERTY_ID_EMPTY_IS_NULL: + _rValue <<= m_bEmptyIsNull; + break; + + case PROPERTY_ID_DEFAULT_TEXT: + _rValue <<= m_aDefaultText; + break; + + case PROPERTY_ID_STRINGITEMLIST: + _rValue <<= getStringItemList(); + break; + + default: + OBoundControlModel::getFastPropertyValue(_rValue, _nHandle); + } +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) + throw (Exception) +{ + switch (_nHandle) + { + case PROPERTY_ID_LISTSOURCETYPE : + DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(reinterpret_cast<ListSourceType*>(NULL))), + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_eListSourceType; + break; + + case PROPERTY_ID_LISTSOURCE : + DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_STRING, + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_aListSource; + // die ListSource hat sich geaendert -> neu laden + if (ListSourceType_VALUELIST != m_eListSourceType) + { + if ( m_xCursor.is() && !hasField() && !hasExternalListSource() ) + // combo box is already connected to a database, and no external list source + // data source changed -> refresh + loadData( false ); + } + break; + + case PROPERTY_ID_EMPTY_IS_NULL : + DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_bEmptyIsNull; + break; + + case PROPERTY_ID_DEFAULT_TEXT : + DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_STRING, + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_aDefaultText; + resetNoBroadcast(); + break; + + case PROPERTY_ID_STRINGITEMLIST: + { + ControlModelLock aLock( *this ); + setNewStringItemList( _rValue, aLock ); + // TODO: this is bogus. setNewStringItemList expects a guard which has the *only* + // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with + // a lock - so we effectively has two locks here, of which setNewStringItemList can + // only control one. + } + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OComboBoxModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) + throw (IllegalArgumentException) +{ + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_LISTSOURCETYPE : + bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType); + break; + + case PROPERTY_ID_LISTSOURCE : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aListSource); + break; + + case PROPERTY_ID_EMPTY_IS_NULL : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bEmptyIsNull); + break; + + case PROPERTY_ID_DEFAULT_TEXT : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultText); + break; + + case PROPERTY_ID_STRINGITEMLIST: + bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue ); + break; + + default: + bModified = OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 6, OBoundControlModel ) + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP1(LISTSOURCETYPE, ListSourceType, BOUND); + DECL_PROP1(LISTSOURCE, ::rtl::OUString, BOUND); + DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND); + DECL_PROP1(DEFAULT_TEXT, ::rtl::OUString, BOUND); + DECL_PROP1(STRINGITEMLIST, Sequence< ::rtl::OUString >,BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OBoundControlModel::describeAggregateProperties( _rAggregateProps ); + + // superseded properties: + RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST ); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OComboBoxModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_COMBOBOX; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OComboBoxModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) + throw(stario::IOException, RuntimeException) +{ + OBoundControlModel::write(_rxOutStream); + + // Version + // Version 0x0002: EmptyIsNull + // Version 0x0003: ListSource->Seq + // Version 0x0004: DefaultText + // Version 0x0005: HelpText + _rxOutStream->writeShort(0x0006); + + // Maskierung fuer any + sal_uInt16 nAnyMask = 0; + if (m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT) + nAnyMask |= BOUNDCOLUMN; + _rxOutStream << nAnyMask; + + StringSequence aListSourceSeq(&m_aListSource, 1); + _rxOutStream << aListSourceSeq; + _rxOutStream << (sal_Int16)m_eListSourceType; + + if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) + { + sal_Int16 nBoundColumn = 0; + m_aBoundColumn >>= nBoundColumn; + _rxOutStream << nBoundColumn; + } + + _rxOutStream << (sal_Bool)m_bEmptyIsNull; + _rxOutStream << m_aDefaultText; + writeHelpTextCompatibly(_rxOutStream); + + // from version 0x0006 : common properties + writeCommonProperties(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OComboBoxModel::read(const Reference<stario::XObjectInputStream>& _rxInStream) throw(stario::IOException, RuntimeException) +{ + OBoundControlModel::read(_rxInStream); + ControlModelLock aLock( *this ); + + // since we are "overwriting" the StringItemList of our aggregate (means we have + // an own place to store the value, instead of relying on our aggregate storing it), + // we need to respect what the aggregate just read for the StringItemList property. + try + { + if ( m_xAggregateSet.is() ) + setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" ); + } + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + DBG_ASSERT(nVersion > 0, "OComboBoxModel::read : version 0 ? this should never have been written !"); + + if (nVersion > 0x0006) + { + DBG_ERROR("OComboBoxModel::read : invalid (means unknown) version !"); + m_aListSource = ::rtl::OUString(); + m_aBoundColumn <<= (sal_Int16)0; + m_aDefaultText = ::rtl::OUString(); + m_eListSourceType = ListSourceType_TABLE; + m_bEmptyIsNull = sal_True; + defaultCommonProperties(); + return; + } + + // Maskierung fuer any + sal_uInt16 nAnyMask; + _rxInStream >> nAnyMask; + + // ListSource + if (nVersion < 0x0003) + { + ::rtl::OUString sListSource; + _rxInStream >> m_aListSource; + } + else // nVersion == 4 + { + m_aListSource = ::rtl::OUString(); + StringSequence aListSource; + _rxInStream >> aListSource; + const ::rtl::OUString* pToken = aListSource.getConstArray(); + sal_Int32 nLen = aListSource.getLength(); + for (sal_Int32 i = 0; i < nLen; ++i, ++pToken) + m_aListSource += *pToken; + } + + sal_Int16 nListSourceType; + _rxInStream >> nListSourceType; + m_eListSourceType = (ListSourceType)nListSourceType; + + if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) + { + sal_Int16 nValue; + _rxInStream >> nValue; + m_aBoundColumn <<= nValue; + } + + if (nVersion > 0x0001) + { + sal_Bool bNull; + _rxInStream >> bNull; + m_bEmptyIsNull = bNull; + } + + if (nVersion > 0x0003) // nVersion == 4 + _rxInStream >> m_aDefaultText; + + // Stringliste muss geleert werden, wenn eine Listenquelle gesetzt ist + // dieses kann der Fall sein wenn im alive modus gespeichert wird + if ( m_aListSource.getLength() + && !hasExternalListSource() + ) + { + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) ); + } + + if (nVersion > 0x0004) + readHelpTextCompatibly(_rxInStream); + + if (nVersion > 0x0005) + readCommonProperties(_rxInStream); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + { + // (not if we don't have a control source - the "State" property acts like it is persistent, then + resetNoBroadcast(); + } +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::loadData( bool _bForce ) +{ + DBG_ASSERT(m_eListSourceType != ListSourceType_VALUELIST, "OComboBoxModel::loadData : do not call for a value list !"); + DBG_ASSERT( !hasExternalListSource(), "OComboBoxModel::loadData: cannot load from DB when I have an external list source!" ); + + if ( hasExternalListSource() ) + return; + + // Connection holen + Reference<XRowSet> xForm(m_xCursor, UNO_QUERY); + if (!xForm.is()) + return; + Reference<XConnection> xConnection = getConnection(xForm); + if (!xConnection.is()) + return; + + Reference<XServiceInfo> xServiceInfo(xConnection, UNO_QUERY); + if (!xServiceInfo.is() || !xServiceInfo->supportsService(SRV_SDB_CONNECTION)) + { + DBG_ERROR("OComboBoxModel::loadData : invalid connection !"); + return; + } + + if (!m_aListSource.getLength() || m_eListSourceType == ListSourceType_VALUELIST) + return; + + ::utl::SharedUNOComponent< XResultSet > xListCursor; + try + { + m_aListRowSet.setConnection( xConnection ); + + bool bExecuteRowSet( false ); + switch (m_eListSourceType) + { + case ListSourceType_TABLEFIELDS: + // don't work with a statement here, the fields will be collected below + break; + case ListSourceType_TABLE: + { + // does the bound field belong to the table ? + // if we use an alias for the bound field, we won't find it + // in that case we use the first field of the table + + Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, m_aListSource); + Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY); + + ::rtl::OUString aFieldName; + if ( xFieldsByName.is() && xFieldsByName->hasByName( getControlSource() ) ) + { + aFieldName = getControlSource(); + } + else + { + // otherwise look for the alias + Reference<XPropertySet> xFormProp(xForm,UNO_QUERY); + Reference< XColumnsSupplier > xSupplyFields; + xFormProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSupplyFields; + + // search the field + DBG_ASSERT(xSupplyFields.is(), "OComboBoxModel::loadData : invalid query composer !"); + + Reference< XNameAccess > xFieldNames = xSupplyFields->getColumns(); + if ( xFieldNames->hasByName( getControlSource() ) ) + { + Reference< XPropertySet > xComposerFieldAsSet; + xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet; + if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet)) + xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName; + } + } + + if (!aFieldName.getLength()) + break; + + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + OSL_ENSURE(xMeta.is(),"No database meta data!"); + if ( xMeta.is() ) + { + ::rtl::OUString aQuote = xMeta->getIdentifierQuoteString(); + + ::rtl::OUString sCatalog, sSchema, sTable; + qualifiedNameComponents( xMeta, m_aListSource, sCatalog, sSchema, sTable, eInDataManipulation ); + + ::rtl::OUStringBuffer aStatement; + aStatement.appendAscii( "SELECT DISTINCT " ); + aStatement.append ( quoteName( aQuote, aFieldName ) ); + aStatement.appendAscii( " FROM " ); + aStatement.append ( composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) ); + + m_aListRowSet.setEscapeProcessing( sal_False ); + m_aListRowSet.setCommand( aStatement.makeStringAndClear() ); + bExecuteRowSet = true; + } + } break; + case ListSourceType_QUERY: + { + m_aListRowSet.setCommandFromQuery( m_aListSource ); + bExecuteRowSet = true; + } + break; + + default: + { + m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType ); + m_aListRowSet.setCommand( m_aListSource ); + bExecuteRowSet = true; + } + } + + if ( bExecuteRowSet ) + { + if ( !_bForce && !m_aListRowSet.isDirty() ) + { + // if none of the settings of the row set changed, compared to the last + // invocation of loadData, then don't re-fill the list. Instead, assume + // the list entries are the same. + return; + } + xListCursor.reset( m_aListRowSet.execute() ); + } + } + catch(SQLException& eSQL) + { + onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); + return; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + ::std::vector< ::rtl::OUString > aStringList; + aStringList.reserve(16); + try + { + OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ), + "OComboBoxModel::loadData: logic error!" ); + if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) ) + return; + + switch (m_eListSourceType) + { + case ListSourceType_SQL: + case ListSourceType_SQLPASSTHROUGH: + case ListSourceType_TABLE: + case ListSourceType_QUERY: + { + // die XDatabaseVAriant der ersten Spalte + Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY); + DBG_ASSERT(xSupplyCols.is(), "OComboBoxModel::loadData : cursor supports the row set service but is no column supplier?!"); + Reference<XIndexAccess> xColumns; + if (xSupplyCols.is()) + { + xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY); + DBG_ASSERT(xColumns.is(), "OComboBoxModel::loadData : no columns supplied by the row set !"); + } + Reference< XPropertySet > xDataField; + if ( xColumns.is() ) + xColumns->getByIndex(0) >>= xDataField; + if ( !xDataField.is() ) + return; + + ::dbtools::FormattedColumnValue aValueFormatter( getContext(), xForm, xDataField ); + + // Listen fuellen + sal_Int16 i = 0; + // per definitionem the list cursor is positioned _before_ the first row at the moment + while (xListCursor->next() && (i++<SHRT_MAX)) // max anzahl eintraege + { + aStringList.push_back( aValueFormatter.getFormattedValue() ); + } + } + break; + case ListSourceType_TABLEFIELDS: + { + Reference<XNameAccess> xFieldNames = getTableFields(xConnection, m_aListSource); + if (xFieldNames.is()) + { + StringSequence seqNames = xFieldNames->getElementNames(); + sal_Int32 nFieldsCount = seqNames.getLength(); + const ::rtl::OUString* pustrNames = seqNames.getConstArray(); + + for (sal_Int32 k=0; k<nFieldsCount; ++k) + aStringList.push_back(pustrNames[k]); + } + } + break; + default: + OSL_ENSURE( false, "OComboBoxModel::loadData: unreachable!" ); + break; + } + } + catch(SQLException& eSQL) + { + onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); + return; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + // String-Sequence fuer ListBox erzeugen + StringSequence aStringSeq(aStringList.size()); + ::rtl::OUString* pStringAry = aStringSeq.getArray(); + for (sal_Int32 i = 0; i<aStringSeq.getLength(); ++i) + pStringAry[i] = aStringList[i]; + + // String-Sequence an ListBox setzen + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( aStringSeq ) ); +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + Reference<XPropertySet> xField = getField(); + if ( xField.is() ) + m_pValueFormatter.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) ); + getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= m_aDesignModeStringItems; + + // Daten nur laden, wenn eine Listenquelle angegeben wurde + if ( m_aListSource.getLength() && m_xCursor.is() && !hasExternalListSource() ) + loadData( false ); +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::onDisconnectedDbColumn() +{ + m_pValueFormatter.reset(); + + // reset the string item list + if ( !hasExternalListSource() ) + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( m_aDesignModeStringItems ) ); + + m_aListRowSet.dispose(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OComboBoxModel::reloaded( const EventObject& aEvent ) throw(RuntimeException) +{ + OBoundControlModel::reloaded(aEvent); + + // reload data if we have a list source + if ( m_aListSource.getLength() && m_xCursor.is() && !hasExternalListSource() ) + loadData( false ); +} + +//------------------------------------------------------------------------------ +void OComboBoxModel::resetNoBroadcast() +{ + OBoundControlModel::resetNoBroadcast(); + m_aLastKnownValue.clear(); +} + +//----------------------------------------------------------------------------- +sal_Bool OComboBoxModel::commitControlValueToDbColumn( bool _bPostReset ) +{ + Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + + ::rtl::OUString sNewValue; + aNewValue >>= sNewValue; + + bool bModified = ( aNewValue != m_aLastKnownValue ); + if ( bModified ) + { + if ( !aNewValue.hasValue() + || ( !sNewValue.getLength() // an empty string + && m_bEmptyIsNull // which should be interpreted as NULL + ) + ) + { + m_xColumnUpdate->updateNull(); + } + else + { + try + { + OSL_PRECOND( m_pValueFormatter.get(), "OComboBoxModel::commitControlValueToDbColumn: no value formatter!" ); + if ( m_pValueFormatter.get() ) + { + if ( !m_pValueFormatter->setFormattedValue( sNewValue ) ) + return sal_False; + } + else + m_xColumnUpdate->updateString( sNewValue ); + } + catch ( const Exception& ) + { + return sal_False; + } + } + + m_aLastKnownValue = aNewValue; + } + + // add the new value to the list + sal_Bool bAddToList = bModified && !_bPostReset; + // (only if this is not the "commit" triggered by a "reset") + + if ( bAddToList ) + { + StringSequence aStringItemList; + if ( getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aStringItemList ) + { + const ::rtl::OUString* pStringItems = aStringItemList.getConstArray(); + sal_Int32 i; + for (i=0; i<aStringItemList.getLength(); ++i, ++pStringItems) + { + if ( pStringItems->equals( sNewValue ) ) + break; + } + + // not found -> add + if (i >= aStringItemList.getLength()) + { + sal_Int32 nOldLen = aStringItemList.getLength(); + aStringItemList.realloc( nOldLen + 1 ); + aStringItemList.getArray()[ nOldLen ] = sNewValue; + + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( aStringItemList ) ); + } + } + } + + return sal_True; +} + +// XPropertiesChangeListener +//------------------------------------------------------------------------------ +Any OComboBoxModel::translateDbColumnToControlValue() +{ + OSL_PRECOND( m_pValueFormatter.get(), "OComboBoxModel::translateDbColumnToControlValue: no value formatter!" ); + if ( m_pValueFormatter.get() ) + { + ::rtl::OUString sValue( m_pValueFormatter->getFormattedValue() ); + if ( !sValue.getLength() + && m_pValueFormatter->getColumn().is() + && m_pValueFormatter->getColumn()->wasNull() + ) + { + m_aLastKnownValue.clear(); + } + else + { + + m_aLastKnownValue <<= sValue; + } + } + else + m_aLastKnownValue.clear(); + + return m_aLastKnownValue.hasValue() ? m_aLastKnownValue : makeAny( ::rtl::OUString() ); + // (m_aLastKnownValue is alllowed to be VOID, the control value isn't) +} + +//------------------------------------------------------------------------------ +Any OComboBoxModel::getDefaultForReset() const +{ + return makeAny( m_aDefaultText ); +} + +//-------------------------------------------------------------------- +void OComboBoxModel::stringItemListChanged( ControlModelLock& /*_rInstanceLock*/ ) +{ + if ( m_xAggregateSet.is() ) + m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) ); +} + +//-------------------------------------------------------------------- +void OComboBoxModel::connectedExternalListSource( ) +{ + // TODO? +} + +//-------------------------------------------------------------------- +void OComboBoxModel::disconnectedExternalListSource( ) +{ + // TODO? +} + +//-------------------------------------------------------------------- +void OComboBoxModel::refreshInternalEntryList() +{ + DBG_ASSERT( !hasExternalListSource(), "OComboBoxModel::refreshInternalEntryList: invalid call!" ); + + if ( !hasExternalListSource( ) + && ( m_eListSourceType != ListSourceType_VALUELIST ) + && ( m_xCursor.is() ) + ) + { + loadData( true ); + } +} + +//-------------------------------------------------------------------- +void SAL_CALL OComboBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException ) +{ + if ( !OEntryListHelper::handleDisposing( _rSource ) ) + OBoundControlModel::disposing( _rSource ); +} + +//======================================================================== +//= OComboBoxControl +//======================================================================== + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OComboBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OComboBoxControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +OComboBoxControl::OComboBoxControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_COMBOBOX) +{ +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OComboBoxControl::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_COMBOBOX; + return aSupported; +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/ComboBox.hxx b/forms/source/component/ComboBox.hxx new file mode 100644 index 000000000000..55ebcbe168e2 --- /dev/null +++ b/forms/source/component/ComboBox.hxx @@ -0,0 +1,178 @@ +/************************************************************************* + * + * 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_COMBOBOX_HXX_ +#define _FORMS_COMBOBOX_HXX_ + +#include "FormComponent.hxx" +#include "errorbroadcaster.hxx" +#include "entrylisthelper.hxx" +#include "cachedrowset.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp> +#include <com/sun/star/form/ListSourceType.hpp> +#include <com/sun/star/awt/XItemListener.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +/** === end UNO includes === **/ + +#include <connectivity/formattedcolumnvalue.hxx> + +#include <cppuhelper/interfacecontainer.hxx> + +#include <vcl/timer.hxx> + +#include <tools/date.hxx> + +//......................................................................... +namespace frm +{ + +//================================================================== +// OComboBoxModel +//================================================================== +class OComboBoxModel + :public OBoundControlModel + ,public OEntryListHelper + ,public OErrorBroadcaster +{ + CachedRowSet m_aListRowSet; // the row set to fill the list + ::com::sun::star::uno::Any m_aBoundColumn; // obsolet + ::rtl::OUString m_aListSource; // + ::rtl::OUString m_aDefaultText; // DefaultText + ::com::sun::star::uno::Any m_aLastKnownValue; + + StringSequence m_aDesignModeStringItems; + // upon loading, in some cases we reset fill our string item list ourself. We don't want + // to lose the user's items then, so we remember them here. + + + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter> m_xFormatter; + + ::com::sun::star::form::ListSourceType m_eListSourceType; // type der list source + sal_Bool m_bEmptyIsNull; // LeerString wird als NULL interpretiert + + ::std::auto_ptr< ::dbtools::FormattedColumnValue > + m_pValueFormatter; + + + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OComboBoxModel ); + + virtual void SAL_CALL disposing(); + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + 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); + + // XLoadListener + virtual void SAL_CALL reloaded( const ::com::sun::star::lang::EventObject& aEvent ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OComboBoxModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // UNO + DECLARE_UNO3_AGG_DEFAULTS(OComboBoxModel, OBoundControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // 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); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OBoundControlModel::getFastPropertyValue; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual void resetNoBroadcast(); + + // OEntryListHelper overriables + virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ); + virtual void connectedExternalListSource( ); + virtual void disconnectedExternalListSource( ); + virtual void refreshInternalEntryList(); + +protected: + void loadData( bool _bForce ); + + DECLARE_XCLONEABLE(); +}; + +//================================================================== +// OComboBoxControl +//================================================================== + +class OComboBoxControl : public OBoundControl +{ +public: + OComboBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(OComboBoxControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_COMBOBOX_HXX_ + diff --git a/forms/source/component/Currency.cxx b/forms/source/component/Currency.cxx new file mode 100644 index 000000000000..89a3b93b4a43 --- /dev/null +++ b/forms/source/component/Currency.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Currency.hxx" +#include <tools/debug.hxx> +#include <unotools/localedatawrapper.hxx> +#include <vcl/svapp.hxx> +#include <unotools/syslocale.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//================================================================== +// OCurrencyControl +//================================================================== +//------------------------------------------------------------------ +OCurrencyControl::OCurrencyControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_CURRENCYFIELD) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OCurrencyControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OCurrencyControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OCurrencyControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OCurrencyControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_CURRENCYFIELD; + return aSupported; +} + +//================================================================== +// OCurrencyModel +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OCurrencyModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OCurrencyModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OCurrencyModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + +//------------------------------------------------------------------ +void OCurrencyModel::implConstruct() +{ + if (m_xAggregateSet.is()) + { + try + { + // get the system international informations + const LocaleDataWrapper& aLocaleInfo = SvtSysLocale().GetLocaleData(); + + ::rtl::OUString sCurrencySymbol; + sal_Bool bPrependCurrencySymbol; + switch ( aLocaleInfo.getCurrPositiveFormat() ) + { + case 0: // $1 + sCurrencySymbol = String(aLocaleInfo.getCurrSymbol()); + bPrependCurrencySymbol = sal_True; + break; + case 1: // 1$ + sCurrencySymbol = String(aLocaleInfo.getCurrSymbol()); + bPrependCurrencySymbol = sal_False; + break; + case 2: // $ 1 + sCurrencySymbol = ::rtl::OUString(String(aLocaleInfo.getCurrSymbol())) + ::rtl::OUString::createFromAscii(" "); + bPrependCurrencySymbol = sal_True; + break; + case 3: // 1 $ + sCurrencySymbol = ::rtl::OUString::createFromAscii(" ") + ::rtl::OUString(String(aLocaleInfo.getCurrSymbol())); + bPrependCurrencySymbol = sal_False; + break; + } + if (sCurrencySymbol.getLength()) + { + m_xAggregateSet->setPropertyValue(PROPERTY_CURRENCYSYMBOL, makeAny(sCurrencySymbol)); + m_xAggregateSet->setPropertyValue(PROPERTY_CURRSYM_POSITION, makeAny(bPrependCurrencySymbol)); + } + } + catch(Exception&) + { + DBG_ERROR( "OCurrencyModel::implConstruct: caught an exception while initializing the aggregate!" ); + } + } +} + +//------------------------------------------------------------------ +DBG_NAME( OCurrencyModel ) +//------------------------------------------------------------------ +OCurrencyModel::OCurrencyModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_CURRENCYFIELD, FRM_SUN_CONTROL_CURRENCYFIELD, sal_False, sal_True ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( OCurrencyModel, NULL ); + + m_nClassId = FormComponentType::CURRENCYFIELD; + initValueProperty( PROPERTY_VALUE, PROPERTY_ID_VALUE ); + + implConstruct(); +} + +//------------------------------------------------------------------ +OCurrencyModel::OCurrencyModel( const OCurrencyModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OCurrencyModel, NULL ); + implConstruct(); +} + +//------------------------------------------------------------------ +OCurrencyModel::~OCurrencyModel() +{ + DBG_DTOR( OCurrencyModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OCurrencyModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OCurrencyModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 4 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_CURRENCYFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_CURRENCYFIELD; + + return aSupported; +} + +//------------------------------------------------------------------------------ +void OCurrencyModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 2, OEditBaseModel ) + // Value auf transient setzen +// ModifyPropertyAttributes(_rAggregateProps, PROPERTY_VALUE, PropertyAttribute::TRANSIENT, 0); + + DECL_PROP3(DEFAULT_VALUE, double, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OCurrencyModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_CURRENCYFIELD; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +sal_Bool OCurrencyModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( !compare( aControlValue, m_aSaveValue ) ) + { + if ( aControlValue.getValueType().getTypeClass() == TypeClass_VOID ) + m_xColumnUpdate->updateNull(); + else + { + try + { + m_xColumnUpdate->updateDouble( getDouble( aControlValue ) ); + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +Any OCurrencyModel::translateDbColumnToControlValue() +{ + m_aSaveValue <<= m_xColumn->getDouble(); + if ( m_xColumn->wasNull() ) + m_aSaveValue.clear(); + return m_aSaveValue; +} + +// XReset +//------------------------------------------------------------------------------ +Any OCurrencyModel::getDefaultForReset() const +{ + Any aValue; + if ( m_aDefault.getValueType().getTypeClass() == TypeClass_DOUBLE ) + aValue = m_aDefault; + + return aValue; +} + +//------------------------------------------------------------------------------ +void OCurrencyModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Currency.hxx b/forms/source/component/Currency.hxx new file mode 100644 index 000000000000..f35840933240 --- /dev/null +++ b/forms/source/component/Currency.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * 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_CURRENCY_HXX_ +#define _FORMS_CURRENCY_HXX_ + +#include "EditBase.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= OCurrencyModel +//================================================================== +class OCurrencyModel + :public OEditBaseModel +{ + ::com::sun::star::uno::Any m_aSaveValue; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OCurrencyModel ); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OCurrencyModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun ::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual void resetNoBroadcast(); + +protected: + DECLARE_XCLONEABLE(); + + void implConstruct(); +}; + +//================================================================== +//= OCurrencyControl +//================================================================== +class OCurrencyControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OCurrencyControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OCurrencyControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_CURRENCY_HXX_ + diff --git a/forms/source/component/DatabaseForm.cxx b/forms/source/component/DatabaseForm.cxx new file mode 100644 index 000000000000..154ed4b00272 --- /dev/null +++ b/forms/source/component/DatabaseForm.cxx @@ -0,0 +1,4162 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "componenttools.hxx" +#include "DatabaseForm.hxx" +#include "EventThread.hxx" +#include "frm_module.hxx" +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "GroupManager.hxx" +#include "property.hrc" +#include "property.hxx" +#include "services.hxx" + +#include <com/sun/star/awt/XControlContainer.hpp> +#include <com/sun/star/awt/XTextComponent.hpp> +#include <com/sun/star/form/DataSelectionType.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/form/TabulatorCycle.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/io/XObjectInputStream.hpp> +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/RowSetVetoException.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdb/XColumnUpdate.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/util/XCancellable.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/XModifiable2.hpp> + +#include <comphelper/basicio.hxx> +#include <comphelper/container.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/stl_types.hxx> +#include <comphelper/uno3.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/implbase2.hxx> +#include <osl/mutex.hxx> +#include <rtl/math.hxx> +#include <rtl/tencinfo.h> +#include <svl/inetstrm.hxx> +#include <svl/inettype.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <tools/fsys.hxx> +#include <tools/inetmsg.hxx> +#include <tools/urlobj.hxx> +#include <unotools/ucblockbytes.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/svapp.hxx> +#include <vcl/timer.hxx> +#include <vos/mutex.hxx> + +#include <ctype.h> +#include <hash_map> + +// compatiblity: DatabaseCursorType is dead, but for compatiblity reasons we still have to write it ... +namespace com { +namespace sun { +namespace star { +namespace data { + +enum DatabaseCursorType +{ + DatabaseCursorType_FORWARD = 0, + DatabaseCursorType_SNAPSHOT = 1, + DatabaseCursorType_KEYSET = 2, + DatabaseCursorType_DYNAMIC = 3, + DatabaseCursorType_MAKE_FIXED_SIZE = SAL_MAX_ENUM +}; + +} } } } + +using namespace ::dbtools; +using namespace ::comphelper; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::data; +using namespace ::com::sun::star::util; + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ODatabaseForm() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::ODatabaseForm > aAutoRegistration; +} + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= DocumentModifyGuard +//================================================================== +class DocumentModifyGuard +{ +public: + DocumentModifyGuard( const Reference< XInterface >& _rxFormComponent ) + :m_xDocumentModify( getXModel( _rxFormComponent ), UNO_QUERY ) + { + impl_changeModifiableFlag_nothrow( false ); + } + ~DocumentModifyGuard() + { + impl_changeModifiableFlag_nothrow( true ); + } + +private: + void impl_changeModifiableFlag_nothrow( const bool _enable ) + { + try + { + if ( m_xDocumentModify.is() ) + _enable ? m_xDocumentModify->enableSetModified() : m_xDocumentModify->disableSetModified(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + +private: + Reference< XModifiable2 > m_xDocumentModify; +}; + +//================================================================== +//= OFormSubmitResetThread +//=----------------------------------------------------------------- +//= submitting and resetting html-forms asynchronously +//================================================================== + +//------------------------------------------------------------------ +class OFormSubmitResetThread: public OComponentEventThread +{ +protected: + + // duplicate an event with respect to it's type + virtual EventObject *cloneEvent( const EventObject *pEvt ) const; + + // process an event. while processing the mutex isn't locked, and pCompImpl + // is made sure to remain valid + virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl, + const EventObject* _pEvt, + const Reference<XControl>& _rControl, + sal_Bool _bSubmit); + +public: + + OFormSubmitResetThread(ODatabaseForm* pControl) : OComponentEventThread(pControl) { } +}; + +//------------------------------------------------------------------ +EventObject* OFormSubmitResetThread::cloneEvent( + const EventObject *pEvt ) const +{ + return new ::com::sun::star::awt::MouseEvent( *(::com::sun::star::awt::MouseEvent *)pEvt ); +} + +//------------------------------------------------------------------ +void OFormSubmitResetThread::processEvent( + ::cppu::OComponentHelper* pCompImpl, + const EventObject *_pEvt, + const Reference<XControl>& _rControl, + sal_Bool _bSubmit) +{ + if (_bSubmit) + ((ODatabaseForm *)pCompImpl)->submit_impl(_rControl, *static_cast<const ::com::sun::star::awt::MouseEvent*>(_pEvt), true); + else + ((ODatabaseForm *)pCompImpl)->reset_impl(true); +} + +//================================================================== +//= ODatabaseForm +//================================================================== + +//------------------------------------------------------------------ +Reference< XInterface > SAL_CALL ODatabaseForm::Create( const Reference< XMultiServiceFactory >& _rxFactory ) +{ + return *( new ODatabaseForm( _rxFactory ) ); +} + +//------------------------------------------------------------------------------ +Sequence<sal_Int8> SAL_CALL ODatabaseForm::getImplementationId() throw(RuntimeException) +{ + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------ +Sequence<Type> SAL_CALL ODatabaseForm::getTypes() throw(RuntimeException) +{ + // ask the aggregate + Sequence<Type> aAggregateTypes; + Reference<XTypeProvider> xAggregateTypes; + if (query_aggregation(m_xAggregate, xAggregateTypes)) + aAggregateTypes = xAggregateTypes->getTypes(); + + Sequence< Type > aRet = concatSequences( + aAggregateTypes, ODatabaseForm_BASE1::getTypes(), OFormComponents::getTypes() + ); + aRet = concatSequences( aRet, ODatabaseForm_BASE2::getTypes(), ODatabaseForm_BASE3::getTypes() ); + return concatSequences( aRet, OPropertySetAggregationHelper::getTypes() ); +} + +//------------------------------------------------------------------ +Any SAL_CALL ODatabaseForm::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn = ODatabaseForm_BASE1::queryInterface(_rType); + // our own interfaces + if (!aReturn.hasValue()) + { + aReturn = ODatabaseForm_BASE2::queryInterface(_rType); + // property set related interfaces + if (!aReturn.hasValue()) + { + aReturn = OPropertySetAggregationHelper::queryInterface(_rType); + + // form component collection related interfaces + if (!aReturn.hasValue()) + { + aReturn = OFormComponents::queryAggregation(_rType); + + // interfaces already present in the aggregate which we want to reroute + // only available if we could create the aggregate + if (!aReturn.hasValue() && m_xAggregateAsRowSet.is()) + aReturn = ODatabaseForm_BASE3::queryInterface(_rType); + + // aggregate interfaces + // (ask the aggregated object _after_ the OComponentHelper (base of OFormComponents), + // so calls to the XComponent interface reach us and not the aggreagtion) + if (!aReturn.hasValue() && m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + } + } + + return aReturn; +} + +DBG_NAME(ODatabaseForm); +//------------------------------------------------------------------ +ODatabaseForm::ODatabaseForm(const Reference<XMultiServiceFactory>& _rxFactory) + :OFormComponents(_rxFactory) + ,OPropertySetAggregationHelper(OComponentHelper::rBHelper) + ,OPropertyChangeListener(m_aMutex) + ,m_aLoadListeners(m_aMutex) + ,m_aRowSetApproveListeners(m_aMutex) + ,m_aRowSetListeners(m_aMutex) + ,m_aSubmitListeners(m_aMutex) + ,m_aErrorListeners(m_aMutex) + ,m_aResetListeners( *this, m_aMutex ) + ,m_aPropertyBagHelper( *this ) + ,m_pAggregatePropertyMultiplexer(NULL) + ,m_pGroupManager( NULL ) + ,m_aParameterManager( m_aMutex, _rxFactory ) + ,m_aFilterManager( _rxFactory ) + ,m_pLoadTimer(NULL) + ,m_pThread(NULL) + ,m_nResetsPending(0) + ,m_nPrivileges(0) + ,m_bInsertOnly( sal_False ) + ,m_eSubmitMethod(FormSubmitMethod_GET) + ,m_eSubmitEncoding(FormSubmitEncoding_URL) + ,m_eNavigation(NavigationBarMode_CURRENT) + ,m_bAllowInsert(sal_True) + ,m_bAllowUpdate(sal_True) + ,m_bAllowDelete(sal_True) + ,m_bLoaded(sal_False) + ,m_bSubForm(sal_False) + ,m_bForwardingConnection(sal_False) + ,m_bSharingConnection( sal_False ) +{ + DBG_CTOR( ODatabaseForm, NULL ); + impl_construct(); +} + +//------------------------------------------------------------------ +ODatabaseForm::ODatabaseForm( const ODatabaseForm& _cloneSource ) + :OFormComponents( _cloneSource ) + ,OPropertySetAggregationHelper( OComponentHelper::rBHelper ) + ,OPropertyChangeListener( m_aMutex ) + ,ODatabaseForm_BASE1() + ,ODatabaseForm_BASE2() + ,ODatabaseForm_BASE3() + ,IPropertyBagHelperContext() + ,m_aLoadListeners( m_aMutex ) + ,m_aRowSetApproveListeners( m_aMutex ) + ,m_aRowSetListeners( m_aMutex ) + ,m_aSubmitListeners( m_aMutex ) + ,m_aErrorListeners( m_aMutex ) + ,m_aResetListeners( *this, m_aMutex ) + ,m_aPropertyBagHelper( *this ) + ,m_pAggregatePropertyMultiplexer( NULL ) + ,m_pGroupManager( NULL ) + ,m_aParameterManager( m_aMutex, _cloneSource.m_xServiceFactory ) + ,m_aFilterManager( _cloneSource.m_xServiceFactory ) + ,m_pLoadTimer( NULL ) + ,m_pThread( NULL ) + ,m_nResetsPending( 0 ) + ,m_nPrivileges( 0 ) + ,m_bInsertOnly( _cloneSource.m_bInsertOnly ) + ,m_aControlBorderColorFocus( _cloneSource.m_aControlBorderColorFocus ) + ,m_aControlBorderColorMouse( _cloneSource.m_aControlBorderColorMouse ) + ,m_aControlBorderColorInvalid( _cloneSource.m_aControlBorderColorInvalid ) + ,m_aDynamicControlBorder( _cloneSource.m_aDynamicControlBorder ) + ,m_sName( _cloneSource.m_sName ) + ,m_aTargetURL( _cloneSource.m_aTargetURL ) + ,m_aTargetFrame( _cloneSource.m_aTargetFrame ) + ,m_eSubmitMethod( _cloneSource.m_eSubmitMethod ) + ,m_eSubmitEncoding( _cloneSource.m_eSubmitEncoding ) + ,m_eNavigation( _cloneSource.m_eNavigation ) + ,m_bAllowInsert( _cloneSource.m_bAllowInsert ) + ,m_bAllowUpdate( _cloneSource.m_bAllowUpdate ) + ,m_bAllowDelete( _cloneSource.m_bAllowDelete ) + ,m_bLoaded( sal_False ) + ,m_bSubForm( sal_False ) + ,m_bForwardingConnection( sal_False ) + ,m_bSharingConnection( sal_False ) +{ + DBG_CTOR( ODatabaseForm, NULL ); + + impl_construct(); + + osl_incrementInterlockedCount( &m_refCount ); + { + // our aggregated rowset itself is not cloneable, so simply copy the properties + ::comphelper::copyProperties( _cloneSource.m_xAggregateSet, m_xAggregateSet ); + + // also care for the dynamic properties: If the clone source has properties which we do not have, + // then add them + try + { + Reference< XPropertySet > xSourceProps( const_cast< ODatabaseForm& >( _cloneSource ).queryAggregation( + XPropertySet::static_type() ), UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xSourcePSI( xSourceProps->getPropertySetInfo(), UNO_SET_THROW ); + Reference< XPropertyState > xSourcePropState( xSourceProps, UNO_QUERY ); + + Reference< XPropertySetInfo > xDestPSI( getPropertySetInfo(), UNO_QUERY_THROW ); + + Sequence< Property > aSourceProperties( xSourcePSI->getProperties() ); + for ( const Property* pSourceProperty = aSourceProperties.getConstArray(); + pSourceProperty != aSourceProperties.getConstArray() + aSourceProperties.getLength(); + ++pSourceProperty + ) + { + if ( xDestPSI->hasPropertyByName( pSourceProperty->Name ) ) + continue; + + // the initial value passed to XPropertyContainer is also used as default, usually. So, try + // to retrieve the default of the source property + Any aInitialValue; + if ( xSourcePropState.is() ) + { + aInitialValue = xSourcePropState->getPropertyDefault( pSourceProperty->Name ); + } + else + { + aInitialValue = xSourceProps->getPropertyValue( pSourceProperty->Name ); + } + addProperty( pSourceProperty->Name, pSourceProperty->Attributes, aInitialValue ); + setPropertyValue( pSourceProperty->Name, xSourceProps->getPropertyValue( pSourceProperty->Name ) ); + } + } + catch( const Exception& ) + { + throw WrappedTargetException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not clone the given database form." ) ), + *const_cast< ODatabaseForm* >( &_cloneSource ), + ::cppu::getCaughtException() + ); + } + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//------------------------------------------------------------------ +void ODatabaseForm::impl_construct() +{ + // aggregate a row set + increment(m_refCount); + { + m_xAggregate = Reference< XAggregation >( m_xServiceFactory->createInstance( SRV_SDB_ROWSET ), UNO_QUERY_THROW ); + m_xAggregateAsRowSet.set( m_xAggregate, UNO_QUERY_THROW ); + setAggregation( m_xAggregate ); + } + + // listen for the properties, important for Parameters + if ( m_xAggregateSet.is() ) + { + m_pAggregatePropertyMultiplexer = new OPropertyChangeMultiplexer(this, m_xAggregateSet, sal_False); + m_pAggregatePropertyMultiplexer->acquire(); + m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_COMMAND); + m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_ACTIVE_CONNECTION); + } + + { + Reference< XWarningsSupplier > xRowSetWarnings( m_xAggregate, UNO_QUERY ); + m_aWarnings.setExternalWarnings( xRowSetWarnings ); + } + + if ( m_xAggregate.is() ) + { + m_xAggregate->setDelegator( static_cast< XWeak* >( this ) ); + } + + { + m_aFilterManager.initialize( m_xAggregateSet ); + m_aParameterManager.initialize( this, m_xAggregate ); + + declareForwardedProperty( PROPERTY_ID_ACTIVE_CONNECTION ); + } + decrement( m_refCount ); + + m_pGroupManager = new OGroupManager( this ); + m_pGroupManager->acquire(); +} + +//------------------------------------------------------------------ +ODatabaseForm::~ODatabaseForm() +{ + DBG_DTOR(ODatabaseForm,NULL); + + m_pGroupManager->release(); + m_pGroupManager = NULL; + + if (m_xAggregate.is()) + m_xAggregate->setDelegator( NULL ); + + m_aWarnings.setExternalWarnings( NULL ); + + if (m_pAggregatePropertyMultiplexer) + { + m_pAggregatePropertyMultiplexer->dispose(); + m_pAggregatePropertyMultiplexer->release(); + m_pAggregatePropertyMultiplexer = NULL; + } +} + +//============================================================================== +// html tools +//------------------------------------------------------------------------ +::rtl::OUString ODatabaseForm::GetDataURLEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + return GetDataEncoded(true,SubmitButton,MouseEvt); +} +// ----------------------------------------------------------------------------- +::rtl::OUString ODatabaseForm::GetDataEncoded(bool _bURLEncoded,const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + // Liste von successful Controls fuellen + HtmlSuccessfulObjList aSuccObjList; + FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt ); + + + // Liste zu ::rtl::OUString zusammensetzen + ::rtl::OUStringBuffer aResult; + ::rtl::OUString aName; + ::rtl::OUString aValue; + + for ( HtmlSuccessfulObjListIterator pSuccObj = aSuccObjList.begin(); + pSuccObj < aSuccObjList.end(); + ++pSuccObj + ) + { + aName = pSuccObj->aName; + aValue = pSuccObj->aValue; + if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE && aValue.getLength() ) + { + // Bei File-URLs wird der Dateiname und keine URL uebertragen, + // weil Netscape dies so macht. + INetURLObject aURL; + aURL.SetSmartProtocol(INET_PROT_FILE); + aURL.SetSmartURL(aValue); + if( INET_PROT_FILE == aURL.GetProtocol() ) + aValue = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS); + } + Encode( aName ); + Encode( aValue ); + + aResult.append(aName); + aResult.append(sal_Unicode('=')); + aResult.append(aValue); + + if (pSuccObj < aSuccObjList.end() - 1) + { + if ( _bURLEncoded ) + aResult.append(sal_Unicode('&')); + else + aResult.appendAscii("\r\n"); + } + } + + + aSuccObjList.clear(); + + return aResult.makeStringAndClear(); +} + +//============================================================================== +// html tools +//------------------------------------------------------------------------ +::rtl::OUString ODatabaseForm::GetDataTextEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + return GetDataEncoded(false,SubmitButton,MouseEvt); +} + +//------------------------------------------------------------------------ +Sequence<sal_Int8> ODatabaseForm::GetDataMultiPartEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt, ::rtl::OUString& rContentType) +{ + + // Parent erzeugen + INetMIMEMessage aParent; + aParent.EnableAttachChild( INETMSG_MULTIPART_FORM_DATA ); + + + // Liste von successful Controls fuellen + HtmlSuccessfulObjList aSuccObjList; + FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt ); + + + // Liste zu ::rtl::OUString zusammensetzen + ::rtl::OUString aResult; + for ( HtmlSuccessfulObjListIterator pSuccObj = aSuccObjList.begin(); + pSuccObj < aSuccObjList.end(); + ++pSuccObj + ) + { + if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_TEXT ) + InsertTextPart( aParent, pSuccObj->aName, pSuccObj->aValue ); + else if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE ) + InsertFilePart( aParent, pSuccObj->aName, pSuccObj->aValue ); + } + + + // Liste loeschen + aSuccObjList.clear(); + + // Fuer Parent MessageStream erzeugen + INetMIMEMessageStream aMessStream; + aMessStream.SetSourceMessage( &aParent ); + aMessStream.GenerateHeader( sal_False ); + + // MessageStream in SvStream kopieren + SvMemoryStream aMemStream; + char* pBuf = new char[1025]; + int nRead; + while( (nRead = aMessStream.Read(pBuf, 1024)) > 0 ) + aMemStream.Write( pBuf, nRead ); + delete[] pBuf; + + aMemStream.Flush(); + aMemStream.Seek( 0 ); + void* pData = (void*)aMemStream.GetData(); + sal_Int32 nLen = aMemStream.Seek(STREAM_SEEK_TO_END); + + rContentType = UniString(aParent.GetContentType()); + return Sequence<sal_Int8>((sal_Int8*)pData, nLen); +} + +//------------------------------------------------------------------------ +namespace +{ + static void appendDigits( sal_Int32 _nNumber, sal_Int8 nDigits, ::rtl::OUStringBuffer& _rOut ) + { + sal_Int32 nCurLen = _rOut.getLength(); + _rOut.append( _nNumber ); + while ( _rOut.getLength() - nCurLen < nDigits ) + _rOut.insert( nCurLen, (sal_Unicode)'0' ); + } +} + +//------------------------------------------------------------------------ +void ODatabaseForm::AppendComponent(HtmlSuccessfulObjList& rList, const Reference<XPropertySet>& xComponentSet, const ::rtl::OUString& rNamePrefix, + const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + if (!xComponentSet.is()) + return; + + // MIB 25.6.98: Geschachtelte Formulare abfangen ... oder muesste + // man sie submitten? + if (!hasProperty(PROPERTY_CLASSID, xComponentSet)) + return; + + // Namen ermitteln + if (!hasProperty(PROPERTY_NAME, xComponentSet)) + return; + + sal_Int16 nClassId = 0; + xComponentSet->getPropertyValue(PROPERTY_CLASSID) >>= nClassId; + ::rtl::OUString aName; + xComponentSet->getPropertyValue( PROPERTY_NAME ) >>= aName; + if( !aName.getLength() && nClassId != FormComponentType::IMAGEBUTTON) + return; + else // Name um den Prefix erweitern + aName = rNamePrefix + aName; + + switch( nClassId ) + { + // Buttons + case FormComponentType::COMMANDBUTTON: + { + // Es wird nur der gedrueckte Submit-Button ausgewertet + // MIB: Sofern ueberhaupt einer uebergeben wurde + if( rxSubmitButton.is() ) + { + Reference<XPropertySet> xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY); + if (xSubmitButtonComponent == xComponentSet && hasProperty(PROPERTY_LABEL, xComponentSet)) + { + // <name>=<label> + ::rtl::OUString aLabel; + xComponentSet->getPropertyValue( PROPERTY_LABEL ) >>= aLabel; + rList.push_back( HtmlSuccessfulObj(aName, aLabel) ); + } + } + } break; + + // ImageButtons + case FormComponentType::IMAGEBUTTON: + { + // Es wird nur der gedrueckte Submit-Button ausgewertet + // MIB: Sofern ueberhaupt einer uebergeben wurde + if( rxSubmitButton.is() ) + { + Reference<XPropertySet> xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY); + if (xSubmitButtonComponent == xComponentSet) + { + // <name>.x=<pos.X>&<name>.y=<pos.Y> + ::rtl::OUString aLhs = aName; + ::rtl::OUString aRhs = ::rtl::OUString::valueOf( MouseEvt.X ); + + // nur wenn ein Name vorhanden ist, kann ein name.x + aLhs += aName.getLength() ? UniString::CreateFromAscii(".x") : UniString::CreateFromAscii("x"); + rList.push_back( HtmlSuccessfulObj(aLhs, aRhs) ); + + aLhs = aName; + aRhs = ::rtl::OUString::valueOf( MouseEvt.Y ); + aLhs += aName.getLength() ? UniString::CreateFromAscii(".y") : UniString::CreateFromAscii("y"); + rList.push_back( HtmlSuccessfulObj(aLhs, aRhs) ); + + } + } + } break; + + // CheckBoxen / RadioButtons + case FormComponentType::CHECKBOX: + case FormComponentType::RADIOBUTTON: + { + // <name>=<refValue> + if( !hasProperty(PROPERTY_STATE, xComponentSet) ) + break; + sal_Int16 nChecked = 0; + xComponentSet->getPropertyValue( PROPERTY_STATE ) >>= nChecked; + if( nChecked != 1 ) + break; + + ::rtl::OUString aStrValue; + if( hasProperty(PROPERTY_REFVALUE, xComponentSet) ) + xComponentSet->getPropertyValue( PROPERTY_REFVALUE ) >>= aStrValue; + + rList.push_back( HtmlSuccessfulObj(aName, aStrValue) ); + } break; + + // Edit + case FormComponentType::TEXTFIELD: + { + // <name>=<text> + if( !hasProperty(PROPERTY_TEXT, xComponentSet) ) + break; + + // MIB: Spezial-Behandlung fuer Multiline-Edit nur dann, wenn + // es auch ein Control dazu gibt. + Any aTmp = xComponentSet->getPropertyValue( PROPERTY_MULTILINE ); + sal_Bool bMulti = rxSubmitButton.is() + && (aTmp.getValueType().getTypeClass() == TypeClass_BOOLEAN) + && getBOOL(aTmp); + ::rtl::OUString sText; + if ( bMulti ) // Bei MultiLineEdit Text am Control abholen + { + + Reference<XControlContainer> xControlContainer(rxSubmitButton->getContext(), UNO_QUERY); + if( !xControlContainer.is() ) break; + + Sequence<Reference<XControl> > aControlSeq = xControlContainer->getControls(); + Reference<XControl> xControl; + Reference<XFormComponent> xControlComponent; + + // Richtiges Control suchen + sal_Int32 i; + for( i=0; i<aControlSeq.getLength(); i++ ) + { + xControl = aControlSeq.getConstArray()[i]; + Reference<XPropertySet> xModel(xControl->getModel(), UNO_QUERY); + if (xModel == xComponentSet) + { + Reference<XTextComponent> xTextComponent(xControl, UNO_QUERY); + if( xTextComponent.is() ) + sText = xTextComponent->getText(); + break; + } + } + // Control nicht gefunden oder nicht existent, (Edit im Grid) + if (i == aControlSeq.getLength()) + xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText; + } + else + xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText; + + rList.push_back( HtmlSuccessfulObj(aName, sText) ); + } break; + + // ComboBox, Patternfield + case FormComponentType::COMBOBOX: + case FormComponentType::PATTERNFIELD: + { + // <name>=<text> + if( hasProperty(PROPERTY_TEXT, xComponentSet) ) + { + ::rtl::OUString aText; + xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText; + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + case FormComponentType::CURRENCYFIELD: + case FormComponentType::NUMERICFIELD: + { + // <name>=<wert> // wert wird als double mit Punkt als Decimaltrenner + // kein Wert angegeben (NULL) -> wert leer + if( hasProperty(PROPERTY_VALUE, xComponentSet) ) + { + ::rtl::OUString aText; + Any aVal = xComponentSet->getPropertyValue( PROPERTY_VALUE ); + + double aDoubleVal = 0; + if (aVal >>= aDoubleVal) + { + sal_Int16 nScale = 0; + xComponentSet->getPropertyValue( PROPERTY_DECIMAL_ACCURACY ) >>= nScale; + aText = ::rtl::math::doubleToUString(aDoubleVal, rtl_math_StringFormat_F, nScale, '.', sal_True); + } + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + case FormComponentType::DATEFIELD: + { + // <name>=<wert> // Wert wird als Datum im Format (MM-DD-YYYY) + // kein Wert angegeben (NULL) -> wert leer + if( hasProperty(PROPERTY_DATE, xComponentSet) ) + { + ::rtl::OUString aText; + Any aVal = xComponentSet->getPropertyValue( PROPERTY_DATE ); + sal_Int32 nInt32Val = 0; + if (aVal >>= nInt32Val) + { + ::Date aDate( nInt32Val ); + ::rtl::OUStringBuffer aBuffer; + appendDigits( aDate.GetMonth(), 2, aBuffer ); + aBuffer.append( (sal_Unicode)'-' ); + appendDigits( aDate.GetDay(), 2, aBuffer ); + aBuffer.append( (sal_Unicode)'-' ); + appendDigits( aDate.GetYear(), 4, aBuffer ); + aText = aBuffer.makeStringAndClear(); + } + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + case FormComponentType::TIMEFIELD: + { + // <name>=<wert> // Wert wird als Zeit im Format (HH:MM:SS) angegeben + // kein Wert angegeben (NULL) -> wert leer + if( hasProperty(PROPERTY_TIME, xComponentSet) ) + { + ::rtl::OUString aText; + Any aVal = xComponentSet->getPropertyValue( PROPERTY_TIME ); + sal_Int32 nInt32Val = 0; + if (aVal >>= nInt32Val) + { + ::Time aTime(nInt32Val); + ::rtl::OUStringBuffer aBuffer; + appendDigits( aTime.GetHour(), 2, aBuffer ); + aBuffer.append( (sal_Unicode)'-' ); + appendDigits( aTime.GetMin(), 2, aBuffer ); + aBuffer.append( (sal_Unicode)'-' ); + appendDigits( aTime.GetSec(), 2, aBuffer ); + aText = aBuffer.makeStringAndClear(); + } + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + + // starform + case FormComponentType::HIDDENCONTROL: + { + + // <name>=<value> + if( hasProperty(PROPERTY_HIDDEN_VALUE, xComponentSet) ) + { + ::rtl::OUString aText; + xComponentSet->getPropertyValue( PROPERTY_HIDDEN_VALUE ) >>= aText; + rList.push_back( HtmlSuccessfulObj(aName, aText) ); + } + } break; + + // starform + case FormComponentType::FILECONTROL: + { + // <name>=<text> + if( hasProperty(PROPERTY_TEXT, xComponentSet) ) + { + + ::rtl::OUString aText; + xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText; + rList.push_back( HtmlSuccessfulObj(aName, aText, SUCCESSFUL_REPRESENT_FILE) ); + } + } break; + + // starform + case FormComponentType::LISTBOX: + { + + // <name>=<Token0>&<name>=<Token1>&...&<name>=<TokenN> (Mehrfachselektion) + if (!hasProperty(PROPERTY_SELECT_SEQ, xComponentSet) || + !hasProperty(PROPERTY_STRINGITEMLIST, xComponentSet)) + break; + + // angezeigte Werte + Sequence< ::rtl::OUString > aVisibleList; + xComponentSet->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aVisibleList; + sal_Int32 nStringCnt = aVisibleList.getLength(); + const ::rtl::OUString* pStrings = aVisibleList.getConstArray(); + + // Werte-Liste + Sequence< ::rtl::OUString > aValueList; + xComponentSet->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueList; + sal_Int32 nValCnt = aValueList.getLength(); + const ::rtl::OUString* pVals = aValueList.getConstArray(); + + // Selektion + Sequence<sal_Int16> aSelectList; + xComponentSet->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectList; + sal_Int32 nSelCount = aSelectList.getLength(); + const sal_Int16* pSels = aSelectList.getConstArray(); + + // Einfach- oder Mehrfach-Selektion + // Bei Einfach-Selektionen beruecksichtigt MT nur den ersten Eintrag + // in der Liste. + if (nSelCount > 1 && !getBOOL(xComponentSet->getPropertyValue(PROPERTY_MULTISELECTION))) + nSelCount = 1; + + // Die Indizes in der Selektions-Liste koennen auch ungueltig sein, + // also muss man die gueltigen erstmal raussuchen um die Laenge + // der neuen Liste zu bestimmen. + sal_Int32 nCurCnt = 0; + sal_Int32 i; + for( i=0; i<nSelCount; ++i ) + { + if( pSels[i] < nStringCnt ) + ++nCurCnt; + } + + ::rtl::OUString aSubValue; + for(i=0; i<nCurCnt; ++i ) + { + sal_Int16 nSelPos = pSels[i]; + if (nSelPos < nValCnt && pVals[nSelPos].getLength()) + { + aSubValue = pVals[nSelPos]; + } + else + { + aSubValue = pStrings[nSelPos]; + } + rList.push_back( HtmlSuccessfulObj(aName, aSubValue) ); + } + } break; + case FormComponentType::GRIDCONTROL: + { + // Die einzelnen Spaltenwerte werden verschickt, + // der Name wird mit dem Prefix des Names des Grids erweitert + Reference<XIndexAccess> xContainer(xComponentSet, UNO_QUERY); + if (!xContainer.is()) + break; + + aName += UniString('.'); + + Reference<XPropertySet> xSet; + sal_Int32 nCount = xContainer->getCount(); + // we know already how many objects should be appended, + // so why not allocate the space for them + rList.reserve( nCount + rList.capacity() ); // not size() + for (sal_Int32 i = 0; i < nCount; ++i) + { + xContainer->getByIndex(i) >>= xSet; + if (xSet.is()) + AppendComponent(rList, xSet, aName, rxSubmitButton, MouseEvt); + } + } + } +} + +//------------------------------------------------------------------------ +void ODatabaseForm::FillSuccessfulList( HtmlSuccessfulObjList& rList, + const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt ) +{ + // Liste loeschen + rList.clear(); + // Ueber Components iterieren + Reference<XPropertySet> xComponentSet; + ::rtl::OUString aPrefix; + + // we know already how many objects should be appended, + // so why not allocate the space for them + rList.reserve( getCount() ); + for( sal_Int32 nIndex=0; nIndex < getCount(); nIndex++ ) + { + getByIndex( nIndex ) >>= xComponentSet; + AppendComponent(rList, xComponentSet, aPrefix, rxSubmitButton, MouseEvt); + } +} + +//------------------------------------------------------------------------ +void ODatabaseForm::Encode( ::rtl::OUString& rString ) const +{ + ::rtl::OUString aResult; + + // Immer ANSI #58641 +// rString.Convert(CHARSET_SYSTEM, CHARSET_ANSI); + + + // Zeilenendezeichen werden als CR dargestellt + UniString sConverter = rString; + sConverter.ConvertLineEnd( LINEEND_CR ); + rString = sConverter; + + + // Jeden einzelnen Character ueberpruefen + sal_Int32 nStrLen = rString.getLength(); + sal_Unicode nCharCode; + for( sal_Int32 nCurPos=0; nCurPos < nStrLen; ++nCurPos ) + { + nCharCode = rString[nCurPos]; + + // Behandlung fuer chars, die kein alphanumerisches Zeichen sind + // und CharacterCodes > 127 + if( (!isalnum(nCharCode) && nCharCode != (sal_Unicode)' ') || nCharCode > 127 ) + { + switch( nCharCode ) + { + case 13: // CR + aResult += ::rtl::OUString::createFromAscii("%0D%0A"); // Hex-Darstellung CR LF + break; + + + // Netscape Sonderbehandlung + case 42: // '*' + case 45: // '-' + case 46: // '.' + case 64: // '@' + case 95: // '_' + aResult += UniString(nCharCode); + break; + + default: + { + // In Hex umrechnen + short nHi = ((sal_Int16)nCharCode) / 16; + short nLo = ((sal_Int16)nCharCode) - (nHi*16); + if( nHi > 9 ) nHi += (int)'A'-10; else nHi += (int)'0'; + if( nLo > 9 ) nLo += (int)'A'-10; else nLo += (int)'0'; + aResult += UniString('%'); + aResult += UniString((sal_Unicode)nHi); + aResult += UniString((sal_Unicode)nLo); + } + } + } + else + aResult += UniString(nCharCode); + } + + + // Spaces durch '+' ersetzen + aResult = aResult.replace(' ', '+'); + + rString = aResult; +} + +//------------------------------------------------------------------------ +void ODatabaseForm::InsertTextPart( INetMIMEMessage& rParent, const ::rtl::OUString& rName, + const ::rtl::OUString& rData ) +{ + + // Part als Message-Child erzeugen + INetMIMEMessage* pChild = new INetMIMEMessage(); + + + // Header + ::rtl::OUString aContentDisp = ::rtl::OUString::createFromAscii("form-data; name=\""); + aContentDisp += rName; + aContentDisp += UniString('\"'); + pChild->SetContentDisposition( aContentDisp ); + pChild->SetContentType( UniString::CreateFromAscii("text/plain") ); + + rtl_TextEncoding eSystemEncoding = gsl_getSystemTextEncoding(); + const sal_Char* pBestMatchingEncoding = rtl_getBestMimeCharsetFromTextEncoding( eSystemEncoding ); + UniString aBestMatchingEncoding = UniString::CreateFromAscii( pBestMatchingEncoding ); + pChild->SetContentTransferEncoding(aBestMatchingEncoding); + + // Body + SvMemoryStream* pStream = new SvMemoryStream; + pStream->WriteLine( ByteString( UniString(rData), rtl_getTextEncodingFromMimeCharset(pBestMatchingEncoding) ) ); + pStream->Flush(); + pStream->Seek( 0 ); + pChild->SetDocumentLB( new SvLockBytes(pStream, sal_True) ); + rParent.AttachChild( *pChild ); +} + +//------------------------------------------------------------------------ +sal_Bool ODatabaseForm::InsertFilePart( INetMIMEMessage& rParent, const ::rtl::OUString& rName, + const ::rtl::OUString& rFileName ) +{ + UniString aFileName( rFileName ); + UniString aContentType(UniString::CreateFromAscii(CONTENT_TYPE_STR_TEXT_PLAIN)); + SvStream *pStream = 0; + + if( aFileName.Len() ) + { + // Bisher koennen wir nur File-URLs verarbeiten + INetURLObject aURL; + aURL.SetSmartProtocol(INET_PROT_FILE); + aURL.SetSmartURL(rFileName); + if( INET_PROT_FILE == aURL.GetProtocol() ) + { + aFileName = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS); + DirEntry aDirEntry( aFileName ); + if( aDirEntry.Exists() ) + { + pStream = ::utl::UcbStreamHelper::CreateStream(aFileName, STREAM_READ); + if (!pStream || (pStream->GetError() != ERRCODE_NONE)) + { + delete pStream; + pStream = 0; + } + } + INetContentType eContentType = INetContentTypes::GetContentType4Extension( + aDirEntry.GetExtension() ); + if (eContentType != CONTENT_TYPE_UNKNOWN) + aContentType = INetContentTypes::GetContentType(eContentType); + } + } + + // Wenn irgendetwas nicht geklappt hat, legen wir einen leeren + // MemoryStream an + if( !pStream ) + pStream = new SvMemoryStream; + + + // Part als Message-Child erzeugen + INetMIMEMessage* pChild = new INetMIMEMessage; + + + // Header + ::rtl::OUString aContentDisp = ::rtl::OUString::createFromAscii( "form-data; name=\"" ); + aContentDisp += rName; + aContentDisp += UniString('\"'); + aContentDisp += ::rtl::OUString::createFromAscii("; filename=\""); + aContentDisp += aFileName; + aContentDisp += UniString('\"'); + pChild->SetContentDisposition( aContentDisp ); + pChild->SetContentType( aContentType ); + pChild->SetContentTransferEncoding( UniString(::rtl::OUString::createFromAscii("8bit")) ); + + + // Body + pChild->SetDocumentLB( new SvLockBytes(pStream, sal_True) ); + rParent.AttachChild( *pChild ); + + return sal_True; +} + +//============================================================================== +// internals +//------------------------------------------------------------------------------ +void ODatabaseForm::onError( const SQLErrorEvent& _rEvent ) +{ + m_aErrorListeners.notifyEach( &XSQLErrorListener::errorOccured, _rEvent ); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::onError( const SQLException& _rException, const ::rtl::OUString& _rContextDescription ) +{ + if ( !m_aErrorListeners.getLength() ) + return; + + SQLErrorEvent aEvent( *this, makeAny( prependErrorInfo( _rException, *this, _rContextDescription ) ) ); + onError( aEvent ); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::updateParameterInfo() +{ + m_aParameterManager.updateParameterInfo( m_aFilterManager ); +} + +//------------------------------------------------------------------------------ +bool ODatabaseForm::hasValidParent() const +{ + // do we have to fill the parameters again? + if (m_bSubForm) + { + Reference<XResultSet> xResultSet(m_xParent, UNO_QUERY); + if (!xResultSet.is()) + { + DBG_ERROR("ODatabaseForm::hasValidParent() : no parent resultset !"); + return false; + } + try + { + Reference< XPropertySet > xSet( m_xParent, UNO_QUERY ); + Reference< XLoadable > xLoad( m_xParent, UNO_QUERY ); + if ( xLoad->isLoaded() + && ( xResultSet->isBeforeFirst() + || xResultSet->isAfterLast() + || getBOOL( xSet->getPropertyValue( PROPERTY_ISNEW ) ) + ) + ) + // the parent form is loaded and on a "virtual" row -> not valid + return false; + } + catch(Exception&) + { + // parent could be forwardonly? + return false; + } + } + return true; +} + +//------------------------------------------------------------------------------ +bool ODatabaseForm::fillParameters( ::osl::ResettableMutexGuard& _rClearForNotifies, const Reference< XInteractionHandler >& _rxCompletionHandler ) +{ + // do we have to fill the parameters again? + if ( !m_aParameterManager.isUpToDate() ) + updateParameterInfo(); + + // is there a valid parent? + if ( m_bSubForm && !hasValidParent() ) + return true; + + // ensure we're connected + if ( !implEnsureConnection() ) + return false; + + if ( m_aParameterManager.isUpToDate() ) + return m_aParameterManager.fillParameterValues( _rxCompletionHandler, _rClearForNotifies ); + + return true; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::saveInsertOnlyState( ) +{ + OSL_ENSURE( !m_aIgnoreResult.hasValue(), "ODatabaseForm::saveInsertOnlyState: overriding old value!" ); + m_aIgnoreResult = m_xAggregateSet->getPropertyValue( PROPERTY_INSERTONLY ); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::restoreInsertOnlyState( ) +{ + if ( m_aIgnoreResult.hasValue() ) + { + m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, m_aIgnoreResult ); + m_aIgnoreResult = Any(); + } +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseForm::executeRowSet(::osl::ResettableMutexGuard& _rClearForNotifies, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler) +{ + if (!m_xAggregateAsRowSet.is()) + return sal_False; + + if (!fillParameters(_rClearForNotifies, _rxCompletionHandler)) + return sal_False; + + restoreInsertOnlyState( ); + + // ensure the aggregated row set has the correct properties + sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY; + + // if we have a parent, who is not positioned on a valid row + // we can't be updatable! + if (m_bSubForm && !hasValidParent()) + { + nConcurrency = ResultSetConcurrency::READ_ONLY; + + // don't use any parameters if we don't have a valid parent + m_aParameterManager.setAllParametersNull(); + + // switch to "insert only" mode + saveInsertOnlyState( ); + m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( sal_True ) ); + } + else if (m_bAllowInsert || m_bAllowUpdate || m_bAllowDelete) + nConcurrency = ResultSetConcurrency::UPDATABLE; + else + nConcurrency = ResultSetConcurrency::READ_ONLY; + + m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_CONCURRENCY, makeAny( (sal_Int32)nConcurrency ) ); + m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_TYPE, makeAny( (sal_Int32)ResultSetType::SCROLL_SENSITIVE ) ); + + sal_Bool bSuccess = sal_False; + try + { + m_xAggregateAsRowSet->execute(); + bSuccess = sal_True; + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + } + catch(SQLException& eDb) + { + _rClearForNotifies.clear(); + if (m_sCurrentErrorContext.getLength()) + onError(eDb, m_sCurrentErrorContext); + else + onError(eDb, FRM_RES_STRING(RID_STR_READERROR)); + _rClearForNotifies.reset(); + + restoreInsertOnlyState( ); + } + + if (bSuccess) + { + // adjust the privilege property + // m_nPrivileges; + m_xAggregateSet->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges; + if (!m_bAllowInsert) + m_nPrivileges &= ~Privilege::INSERT; + if (!m_bAllowUpdate) + m_nPrivileges &= ~Privilege::UPDATE; + if (!m_bAllowDelete) + m_nPrivileges &= ~Privilege::DELETE; + + if (bMoveToFirst) + { + // the row set is positioned _before_ the first row (per definitionem), so move the set ... + try + { + // if we have an insert only rowset we move to the insert row + next(); + if (((m_nPrivileges & Privilege::INSERT) == Privilege::INSERT) + && isAfterLast()) + { + // move on the insert row of set + // resetting must be done later, after the load events have been posted + // see :moveToInsertRow and load , reload + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->moveToInsertRow(); + } + } + catch(SQLException& eDB) + { + _rClearForNotifies.clear(); + if (m_sCurrentErrorContext.getLength()) + onError(eDB, m_sCurrentErrorContext); + else + onError(eDB, FRM_RES_STRING(RID_STR_READERROR)); + _rClearForNotifies.reset(); + bSuccess = sal_False; + } + } + } + return bSuccess; +} + +//------------------------------------------------------------------ +void ODatabaseForm::disposing() +{ + if (m_pAggregatePropertyMultiplexer) + m_pAggregatePropertyMultiplexer->dispose(); + + if (m_bLoaded) + unload(); + + // cancel the submit/reset-thread + { + ::osl::MutexGuard aGuard( m_aMutex ); + if (m_pThread) + { + m_pThread->release(); + m_pThread = NULL; + } + } + + EventObject aEvt(static_cast<XWeak*>(this)); + m_aLoadListeners.disposeAndClear(aEvt); + m_aRowSetApproveListeners.disposeAndClear(aEvt); + m_aParameterManager.disposing( aEvt ); + m_aResetListeners.disposing(); + m_aSubmitListeners.disposeAndClear(aEvt); + m_aErrorListeners.disposeAndClear(aEvt); + + m_aParameterManager.dispose(); // (to free any references it may have to me) + m_aFilterManager.dispose(); // (dito) + + OFormComponents::disposing(); + OPropertySetAggregationHelper::disposing(); + + // stop listening on the aggregate + if (m_xAggregateAsRowSet.is()) + m_xAggregateAsRowSet->removeRowSetListener(this); + + // dispose the active connection + Reference<XComponent> xAggregationComponent; + if (query_aggregation(m_xAggregate, xAggregationComponent)) + xAggregationComponent->dispose(); + + m_aPropertyBagHelper.dispose(); +} + +//------------------------------------------------------------------------------ +Reference< XConnection > ODatabaseForm::getConnection() +{ + Reference< XConnection > xConn; + m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConn; + return xConn; +} + +//------------------------------------------------------------------------------ +::osl::Mutex& ODatabaseForm::getMutex() +{ + return m_aMutex; +} + +//============================================================================== +// property handling +//------------------------------------------------------------------------------ +void ODatabaseForm::describeFixedAndAggregateProperties( + Sequence< Property >& _rProps, + Sequence< Property >& _rAggregateProps ) const +{ + BEGIN_DESCRIBE_AGGREGATION_PROPERTIES(22, m_xAggregateSet) + // we want to "override" the privileges, since we have additional "AllowInsert" etc. properties + RemoveProperty( _rAggregateProps, PROPERTY_PRIVILEGES ); + + // InsertOnly is also to be overridden, since we sometimes change it ourself + RemoveProperty( _rAggregateProps, PROPERTY_INSERTONLY ); + + // we remove and re-declare the DataSourceName property, 'cause we want it to be constrained, and the + // original property of our aggregate isn't + RemoveProperty( _rAggregateProps, PROPERTY_DATASOURCE ); + + // for connection sharing, we need to override the ActiveConnection property, too + RemoveProperty( _rAggregateProps, PROPERTY_ACTIVE_CONNECTION ); + + // the Filter property is also overwritten, since we have some implicit filters + // (e.g. the ones which result from linking master fields to detail fields + // via column names instead of parameters) + RemoveProperty( _rAggregateProps, PROPERTY_FILTER ); + RemoveProperty( _rAggregateProps, PROPERTY_APPLYFILTER ); + + DECL_IFACE_PROP4(ACTIVE_CONNECTION, XConnection, BOUND, TRANSIENT, MAYBEVOID, CONSTRAINED); + DECL_BOOL_PROP2 ( APPLYFILTER, BOUND, MAYBEDEFAULT ); + DECL_PROP1 ( NAME, ::rtl::OUString, BOUND ); + DECL_PROP1 ( MASTERFIELDS, Sequence< ::rtl::OUString >, BOUND ); + DECL_PROP1 ( DETAILFIELDS, Sequence< ::rtl::OUString >, BOUND ); + DECL_PROP2 ( DATASOURCE, ::rtl::OUString, BOUND, CONSTRAINED ); + DECL_PROP3 ( CYCLE, TabulatorCycle, BOUND, MAYBEVOID, MAYBEDEFAULT ); + DECL_PROP2 ( FILTER, ::rtl::OUString, BOUND, MAYBEDEFAULT ); + DECL_BOOL_PROP2 ( INSERTONLY, BOUND, MAYBEDEFAULT ); + DECL_PROP1 ( NAVIGATION, NavigationBarMode, BOUND ); + DECL_BOOL_PROP1 ( ALLOWADDITIONS, BOUND ); + DECL_BOOL_PROP1 ( ALLOWEDITS, BOUND ); + DECL_BOOL_PROP1 ( ALLOWDELETIONS, BOUND ); + DECL_PROP2 ( PRIVILEGES, sal_Int32, TRANSIENT, READONLY ); + DECL_PROP1 ( TARGET_URL, ::rtl::OUString, BOUND ); + DECL_PROP1 ( TARGET_FRAME, ::rtl::OUString, BOUND ); + DECL_PROP1 ( SUBMIT_METHOD, FormSubmitMethod, BOUND ); + DECL_PROP1 ( SUBMIT_ENCODING, FormSubmitEncoding, BOUND ); + DECL_BOOL_PROP3 ( DYNAMIC_CONTROL_BORDER, BOUND, MAYBEVOID, MAYBEDEFAULT ); + DECL_PROP3 ( CONTROL_BORDER_COLOR_FOCUS, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT ); + DECL_PROP3 ( CONTROL_BORDER_COLOR_MOUSE, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT ); + DECL_PROP3 ( CONTROL_BORDER_COLOR_INVALID, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT ); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +Reference< XMultiPropertySet > ODatabaseForm::getPropertiesInterface() +{ + return Reference< XMultiPropertySet >( *this, UNO_QUERY ); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& ODatabaseForm::getInfoHelper() +{ + return m_aPropertyBagHelper.getInfoHelper(); +} + +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > ODatabaseForm::getPropertySetInfo() throw( RuntimeException ) +{ + return createPropertySetInfo( getInfoHelper() ); +} + +//-------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException) +{ + m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue ); +} + +//-------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException) +{ + m_aPropertyBagHelper.removeProperty( _rName ); +} + +//-------------------------------------------------------------------- +Sequence< PropertyValue > SAL_CALL ODatabaseForm::getPropertyValues() throw (RuntimeException) +{ + return m_aPropertyBagHelper.getPropertyValues(); +} + +//-------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + m_aPropertyBagHelper.setPropertyValues( _rProps ); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL ODatabaseForm::getWarnings( ) throw (SQLException, RuntimeException) +{ + return m_aWarnings.getWarnings(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::clearWarnings( ) throw (SQLException, RuntimeException) +{ + m_aWarnings.clearWarnings(); +} + +//------------------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL ODatabaseForm::createClone( ) throw (RuntimeException) +{ + ODatabaseForm* pClone = new ODatabaseForm( *this ); + osl_incrementInterlockedCount( &pClone->m_refCount ); + pClone->clonedFrom( *this ); + osl_decrementInterlockedCount( &pClone->m_refCount ); + return pClone; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::fire( sal_Int32* pnHandles, const Any* pNewValues, const Any* pOldValues, sal_Int32 nCount, sal_Bool bVetoable ) +{ + // same as in getFastPropertyValue(INT32) : if we're resetting currently don't fire any changes of the + // IsModified property from FALSE to TRUE, as this is only temporary 'til the reset is done + if (m_nResetsPending > 0) + { + // look for the PROPERTY_ID_ISMODIFIED + sal_Int32 nPos = 0; + for (nPos=0; nPos<nCount; ++nPos) + if (pnHandles[nPos] == PROPERTY_ID_ISMODIFIED) + break; + + if ((nPos < nCount) && (pNewValues[nPos].getValueType().getTypeClass() == TypeClass_BOOLEAN) && getBOOL(pNewValues[nPos])) + { // yeah, we found it, and it changed to TRUE + if (nPos == 0) + { // just cut the first element + ++pnHandles; + ++pNewValues; + ++pOldValues; + --nCount; + } + else if (nPos == nCount - 1) + // just cut the last element + --nCount; + else + { // split into two base class calls + OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nPos, bVetoable); + ++nPos; + OPropertySetAggregationHelper::fire(pnHandles + nPos, pNewValues + nPos, pOldValues + nPos, nCount - nPos, bVetoable); + return; + } + } + } + + OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nCount, bVetoable); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL ODatabaseForm::getFastPropertyValue( sal_Int32 nHandle ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + if ((nHandle == PROPERTY_ID_ISMODIFIED) && (m_nResetsPending > 0)) + return ::cppu::bool2any((sal_False)); + // don't allow the aggregate which is currently being reset to return a (temporary) "yes" + else + return OPropertySetAggregationHelper::getFastPropertyValue(nHandle); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + rValue <<= m_bInsertOnly; + break; + + case PROPERTY_ID_FILTER: + rValue <<= m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ); + break; + + case PROPERTY_ID_APPLYFILTER: + rValue <<= m_aFilterManager.isApplyPublicFilter(); + break; + + case PROPERTY_ID_DATASOURCE: + rValue = m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE ); + break; + + case PROPERTY_ID_TARGET_URL: + rValue <<= m_aTargetURL; + break; + case PROPERTY_ID_TARGET_FRAME: + rValue <<= m_aTargetFrame; + break; + case PROPERTY_ID_SUBMIT_METHOD: + rValue <<= m_eSubmitMethod; + break; + case PROPERTY_ID_SUBMIT_ENCODING: + rValue <<= m_eSubmitEncoding; + break; + case PROPERTY_ID_NAME: + rValue <<= m_sName; + break; + case PROPERTY_ID_MASTERFIELDS: + rValue <<= m_aMasterFields; + break; + case PROPERTY_ID_DETAILFIELDS: + rValue <<= m_aDetailFields; + break; + case PROPERTY_ID_CYCLE: + rValue = m_aCycle; + break; + case PROPERTY_ID_NAVIGATION: + rValue <<= m_eNavigation; + break; + case PROPERTY_ID_ALLOWADDITIONS: + rValue <<= (sal_Bool)m_bAllowInsert; + break; + case PROPERTY_ID_ALLOWEDITS: + rValue <<= (sal_Bool)m_bAllowUpdate; + break; + case PROPERTY_ID_ALLOWDELETIONS: + rValue <<= (sal_Bool)m_bAllowDelete; + break; + case PROPERTY_ID_PRIVILEGES: + rValue <<= (sal_Int32)m_nPrivileges; + break; + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + rValue = m_aDynamicControlBorder; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + rValue = m_aControlBorderColorFocus; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + rValue = m_aControlBorderColorMouse; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + rValue = m_aControlBorderColorInvalid; + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) ) + m_aPropertyBagHelper.getDynamicFastPropertyValue( nHandle, rValue ); + else + OPropertySetAggregationHelper::getFastPropertyValue( rValue, nHandle ); + break; + } +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseForm::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bInsertOnly ); + break; + + case PROPERTY_ID_FILTER: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ) ); + break; + + case PROPERTY_ID_APPLYFILTER: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.isApplyPublicFilter() ); + break; + + case PROPERTY_ID_DATASOURCE: + { + Any aAggregateProperty; + getFastPropertyValue(aAggregateProperty, PROPERTY_ID_DATASOURCE); + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, aAggregateProperty, ::getCppuType(static_cast<const ::rtl::OUString*>(NULL))); + } + break; + case PROPERTY_ID_TARGET_URL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetURL); + break; + case PROPERTY_ID_TARGET_FRAME: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetFrame); + break; + case PROPERTY_ID_SUBMIT_METHOD: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitMethod); + break; + case PROPERTY_ID_SUBMIT_ENCODING: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitEncoding); + break; + case PROPERTY_ID_NAME: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sName); + break; + case PROPERTY_ID_MASTERFIELDS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aMasterFields); + break; + case PROPERTY_ID_DETAILFIELDS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDetailFields); + break; + case PROPERTY_ID_CYCLE: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL))); + break; + case PROPERTY_ID_NAVIGATION: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eNavigation); + break; + case PROPERTY_ID_ALLOWADDITIONS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowInsert); + break; + case PROPERTY_ID_ALLOWEDITS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowUpdate); + break; + case PROPERTY_ID_ALLOWDELETIONS: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowDelete); + break; + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aDynamicControlBorder, ::getBooleanCppuType() ); + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorFocus, getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorMouse, getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorInvalid, getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle ( nHandle ) ) + bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( nHandle, rValue, rConvertedValue, rOldValue ); + else + bModified = OPropertySetAggregationHelper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw( Exception ) +{ + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + rValue >>= m_bInsertOnly; + if ( m_aIgnoreResult.hasValue() ) + m_aIgnoreResult <<= m_bInsertOnly; + else + m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( m_bInsertOnly ) ); + break; + + case PROPERTY_ID_FILTER: + { + ::rtl::OUString sNewFilter; + rValue >>= sNewFilter; + m_aFilterManager.setFilterComponent( FilterManager::fcPublicFilter, sNewFilter ); + } + break; + + case PROPERTY_ID_APPLYFILTER: + { + sal_Bool bApply = sal_True; + rValue >>= bApply; + m_aFilterManager.setApplyPublicFilter( bApply ); + } + break; + + case PROPERTY_ID_DATASOURCE: + { + Reference< XConnection > xSomeConnection; + if ( ::dbtools::isEmbeddedInDatabase( getParent(), xSomeConnection ) ) + throw PropertyVetoException(); + + try + { + m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, rValue); + } + catch(Exception&) { } + } + break; + case PROPERTY_ID_TARGET_URL: + rValue >>= m_aTargetURL; + break; + case PROPERTY_ID_TARGET_FRAME: + rValue >>= m_aTargetFrame; + break; + case PROPERTY_ID_SUBMIT_METHOD: + rValue >>= m_eSubmitMethod; + break; + case PROPERTY_ID_SUBMIT_ENCODING: + rValue >>= m_eSubmitEncoding; + break; + case PROPERTY_ID_NAME: + rValue >>= m_sName; + break; + case PROPERTY_ID_MASTERFIELDS: + rValue >>= m_aMasterFields; + invlidateParameters(); + break; + case PROPERTY_ID_DETAILFIELDS: + rValue >>= m_aDetailFields; + invlidateParameters(); + break; + case PROPERTY_ID_CYCLE: + m_aCycle = rValue; + break; + case PROPERTY_ID_NAVIGATION: + rValue >>= m_eNavigation; + break; + case PROPERTY_ID_ALLOWADDITIONS: + m_bAllowInsert = getBOOL(rValue); + break; + case PROPERTY_ID_ALLOWEDITS: + m_bAllowUpdate = getBOOL(rValue); + break; + case PROPERTY_ID_ALLOWDELETIONS: + m_bAllowDelete = getBOOL(rValue); + break; + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + m_aDynamicControlBorder = rValue; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + m_aControlBorderColorFocus = rValue; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + m_aControlBorderColorMouse = rValue; + break; + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + m_aControlBorderColorInvalid = rValue; + break; + + case PROPERTY_ID_ACTIVE_CONNECTION: + { + Reference< XConnection > xOuterConnection; + if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) ) + { + if ( xOuterConnection != Reference< XConnection >( rValue, UNO_QUERY ) ) + // somebody's trying to set a connection which is not equal the connection + // implied by the database we're embedded in + throw PropertyVetoException(); + } + OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + break; + } + + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) ) + m_aPropertyBagHelper.setDynamicFastPropertyValue( nHandle, rValue ); + else + OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + break; + } +} + +//------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::forwardingPropertyValue( sal_Int32 _nHandle ) +{ + OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardingPropertyValue: unexpected property!" ); + if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION ) + { + if ( m_bSharingConnection ) + stopSharingConnection( ); + m_bForwardingConnection = sal_True; + } +} + +//------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::forwardedPropertyValue( sal_Int32 _nHandle, bool /*_bSuccess*/ ) +{ + OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardedPropertyValue: unexpected property!" ); + if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION ) + { + m_bForwardingConnection = sal_False; + } +} + +//============================================================================== +// com::sun::star::beans::XPropertyState +//------------------------------------------------------------------ +PropertyState ODatabaseForm::getPropertyStateByHandle(sal_Int32 nHandle) +{ + PropertyState eState; + switch (nHandle) + { + case PROPERTY_ID_NAVIGATION: + return (NavigationBarMode_CURRENT == m_eNavigation) ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE; + + case PROPERTY_ID_CYCLE: + eState = m_aCycle.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_INSERTONLY: + eState = m_bInsertOnly ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_FILTER: + if ( !m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ).getLength() ) + eState = PropertyState_DEFAULT_VALUE; + else + eState = PropertyState_DIRECT_VALUE; + break; + + case PROPERTY_ID_APPLYFILTER: + eState = m_aFilterManager.isApplyPublicFilter() ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE; + break; + + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + eState = m_aDynamicControlBorder.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + eState = m_aControlBorderColorFocus.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + eState = m_aControlBorderColorMouse.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + eState = m_aControlBorderColorInvalid.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + break; + + default: + eState = OPropertySetAggregationHelper::getPropertyStateByHandle(nHandle); + } + return eState; +} + +//------------------------------------------------------------------ +void ODatabaseForm::setPropertyToDefaultByHandle(sal_Int32 nHandle) +{ + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + case PROPERTY_ID_FILTER: + case PROPERTY_ID_APPLYFILTER: + case PROPERTY_ID_NAVIGATION: + case PROPERTY_ID_CYCLE: + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + setFastPropertyValue( nHandle, getPropertyDefaultByHandle( nHandle ) ); + break; + + default: + OPropertySetAggregationHelper::setPropertyToDefaultByHandle(nHandle); + } +} + +//------------------------------------------------------------------ +Any ODatabaseForm::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + Any aReturn; + switch (nHandle) + { + case PROPERTY_ID_INSERTONLY: + case PROPERTY_ID_DYNAMIC_CONTROL_BORDER: + aReturn <<= sal_False; + break; + + case PROPERTY_ID_FILTER: + aReturn <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_APPLYFILTER: + aReturn <<= sal_True; + break; + + case PROPERTY_ID_NAVIGATION: + aReturn = makeAny(NavigationBarMode_CURRENT); + break; + + case PROPERTY_ID_CYCLE: + case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS: + case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE: + case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID: + break; + + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) ) + m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( nHandle, aReturn ); + else + aReturn = OPropertySetAggregationHelper::getPropertyDefaultByHandle( nHandle ); + break; + } + return aReturn; +} + +//============================================================================== +// com::sun::star::form::XReset +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::reset() throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + if (isLoaded()) + { + ::osl::MutexGuard aResetGuard(m_aResetSafety); + ++m_nResetsPending; + reset_impl(true); + return; + } + + if ( !m_aResetListeners.empty() ) + { + ::osl::MutexGuard aResetGuard(m_aResetSafety); + ++m_nResetsPending; + // create an own thread if we have (approve-)reset-listeners (so the listeners can't do that much damage + // to this thread which is probably the main one) + if (!m_pThread) + { + m_pThread = new OFormSubmitResetThread(this); + m_pThread->acquire(); + m_pThread->create(); + } + EventObject aEvt; + m_pThread->addEvent(&aEvt, sal_False); + } + else + { + // direct call without any approving by the listeners + aGuard.clear(); + + ::osl::MutexGuard aResetGuard(m_aResetSafety); + ++m_nResetsPending; + reset_impl(false); + } +} + +//----------------------------------------------------------------------------- +void ODatabaseForm::reset_impl(bool _bAproveByListeners) +{ + if ( _bAproveByListeners ) + if ( !m_aResetListeners.approveReset() ) + return; + + ::osl::ResettableMutexGuard aResetGuard(m_aResetSafety); + // do we have a database connected form and stay on the insert row + sal_Bool bInsertRow = sal_False; + if (m_xAggregateSet.is()) + bInsertRow = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW)); + if (bInsertRow) + { + try + { + // Iterate through all columns and set the default value + Reference< XColumnsSupplier > xColsSuppl( m_xAggregateSet, UNO_QUERY ); + Reference< XIndexAccess > xIndexCols( xColsSuppl->getColumns(), UNO_QUERY ); + for (sal_Int32 i = 0; i < xIndexCols->getCount(); ++i) + { + Reference< XPropertySet > xColProps; + xIndexCols->getByIndex(i) >>= xColProps; + + Reference< XColumnUpdate > xColUpdate( xColProps, UNO_QUERY ); + if ( !xColUpdate.is() ) + continue; + + Reference< XPropertySetInfo > xPSI; + if ( xColProps.is() ) + xPSI = xColProps->getPropertySetInfo( ); + + static const ::rtl::OUString PROPERTY_CONTROLDEFAULT( RTL_CONSTASCII_USTRINGPARAM( "ControlDefault" ) ); + if ( xPSI.is() && xPSI->hasPropertyByName( PROPERTY_CONTROLDEFAULT ) ) + { + Any aDefault = xColProps->getPropertyValue( PROPERTY_CONTROLDEFAULT ); + + sal_Bool bReadOnly = sal_False; + if ( xPSI->hasPropertyByName( PROPERTY_ISREADONLY ) ) + xColProps->getPropertyValue( PROPERTY_ISREADONLY ) >>= bReadOnly; + + if ( !bReadOnly ) + { + try + { + if ( aDefault.hasValue() ) + xColUpdate->updateObject( aDefault ); + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + } + } + catch(Exception&) + { + } + + if (m_bSubForm) + { + Reference< XColumnsSupplier > xParentColSupp( m_xParent, UNO_QUERY ); + Reference< XNameAccess > xParentCols; + if ( xParentColSupp.is() ) + xParentCols = xParentColSupp->getColumns(); + + if ( xParentCols.is() && xParentCols->hasElements() && m_aMasterFields.getLength() ) + { + try + { + // analyze our parameters + if ( !m_aParameterManager.isUpToDate() ) + updateParameterInfo(); + + m_aParameterManager.resetParameterValues( ); + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "ODatabaseForm::reset_impl: could not initialize the master-detail-driven parameters!"); + } + } + } + } + + aResetGuard.clear(); + // iterate through all components. don't use an XIndexAccess as this will cause massive + // problems with the count. + Reference<XEnumeration> xIter = createEnumeration(); + while (xIter->hasMoreElements()) + { + Reference<XReset> xReset; + xIter->nextElement() >>= xReset; + if (xReset.is()) + { + // TODO : all reset-methods have to be thread-safe + xReset->reset(); + } + } + + aResetGuard.reset(); + // ensure that the row isn't modified + // (do this _before_ the listeners are notified ! their reaction (maybe asynchronous) may depend + // on the modified state of the row + // 21.02.00 - 73265 - FS) + if (bInsertRow) + m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, ::cppu::bool2any(sal_Bool(sal_False))); + + aResetGuard.clear(); + { + m_aResetListeners.resetted(); + } + + aResetGuard.reset(); + // and again : ensure the row isn't modified + // we already did this after we (and maybe our dependents) resetted the values, but the listeners may have changed the row, too + if (bInsertRow) + m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, ::cppu::bool2any((sal_False))); + + --m_nResetsPending; +} + +//----------------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::addResetListener(const Reference<XResetListener>& _rListener) throw( RuntimeException ) +{ + m_aResetListeners.addTypedListener( _rListener ); +} + +//----------------------------------------------------------------------------- +void SAL_CALL ODatabaseForm::removeResetListener(const Reference<XResetListener>& _rListener) throw( RuntimeException ) +{ + m_aResetListeners.removeTypedListener( _rListener ); +} + +//============================================================================== +// com::sun::star::form::XSubmit +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::submit( const Reference<XControl>& Control, + const ::com::sun::star::awt::MouseEvent& MouseEvt ) throw( RuntimeException ) +{ + { + ::osl::MutexGuard aGuard(m_aMutex); + // Sind Controls und eine Submit-URL vorhanden? + if( !getCount() || !m_aTargetURL.getLength() ) + return; + } + + ::osl::ClearableMutexGuard aGuard(m_aMutex); + if (m_aSubmitListeners.getLength()) + { + // create an own thread if we have (approve-)submit-listeners (so the listeners can't do that much damage + // to this thread which is probably the main one) + if (!m_pThread) + { + m_pThread = new OFormSubmitResetThread(this); + m_pThread->acquire(); + m_pThread->create(); + } + m_pThread->addEvent(&MouseEvt, Control, sal_True); + } + else + { + // direct call without any approving by the listeners + aGuard.clear(); + submit_impl( Control, MouseEvt, true ); + } +} +// ----------------------------------------------------------------------------- +void lcl_dispatch(const Reference< XFrame >& xFrame,const Reference<XURLTransformer>& xTransformer,const ::rtl::OUString& aURLStr,const ::rtl::OUString& aReferer,const ::rtl::OUString& aTargetName + ,const ::rtl::OUString& aData,rtl_TextEncoding _eEncoding) +{ + URL aURL; + aURL.Complete = aURLStr; + xTransformer->parseStrict(aURL); + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName, + FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN | + FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS); + + if (xDisp.is()) + { + Sequence<PropertyValue> aArgs(2); + aArgs.getArray()[0].Name = ::rtl::OUString::createFromAscii("Referer"); + aArgs.getArray()[0].Value <<= aReferer; + + // build a sequence from the to-be-submitted string + ByteString a8BitData(aData.getStr(), (sal_uInt16)aData.getLength(), _eEncoding); + // always ANSI #58641 + Sequence< sal_Int8 > aPostData((sal_Int8*)a8BitData.GetBuffer(), a8BitData.Len()); + Reference< XInputStream > xPostData = new SequenceInputStream(aPostData); + + aArgs.getArray()[1].Name = ::rtl::OUString::createFromAscii("PostData"); + aArgs.getArray()[1].Value <<= xPostData; + + xDisp->dispatch(aURL, aArgs); + } // if (xDisp.is()) +} +//------------------------------------------------------------------------------ +void ODatabaseForm::submit_impl(const Reference<XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt, bool _bAproveByListeners) +{ + + if (_bAproveByListeners) + { + ::cppu::OInterfaceIteratorHelper aIter(m_aSubmitListeners); + EventObject aEvt(static_cast<XWeak*>(this)); + sal_Bool bCanceled = sal_False; + while (aIter.hasMoreElements() && !bCanceled) + { + if (!((XSubmitListener*)aIter.next())->approveSubmit(aEvt)) + bCanceled = sal_True; + } + + if (bCanceled) + return; + } + + FormSubmitEncoding eSubmitEncoding; + FormSubmitMethod eSubmitMethod; + ::rtl::OUString aURLStr; + ::rtl::OUString aReferer; + ::rtl::OUString aTargetName; + Reference< XModel > xModel; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + // starform->Forms + + Reference<XChild> xParent(m_xParent, UNO_QUERY); + + if (xParent.is()) + xModel = getXModel(xParent->getParent()); + + if (xModel.is()) + aReferer = xModel->getURL(); + + // TargetItem + aTargetName = m_aTargetFrame; + + eSubmitEncoding = m_eSubmitEncoding; + eSubmitMethod = m_eSubmitMethod; + aURLStr = m_aTargetURL; + } + + if (!xModel.is()) + return; + Reference< XFrame > xFrame = xModel->getCurrentController()->getFrame(); + if (!xFrame.is()) + return; + + Reference<XURLTransformer> + xTransformer(m_xServiceFactory->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY); + DBG_ASSERT(xTransformer.is(), "ODatabaseForm::submit_impl : could not create an URL transformer !"); + + // URL-Encoding + if( eSubmitEncoding == FormSubmitEncoding_URL ) + { + ::rtl::OUString aData; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + aData = GetDataURLEncoded( Control, MouseEvt ); + } + + URL aURL; + // FormMethod GET + if( eSubmitMethod == FormSubmitMethod_GET ) + { + INetURLObject aUrlObj( aURLStr, INetURLObject::WAS_ENCODED ); + aUrlObj.SetParam( aData, INetURLObject::ENCODE_ALL ); + aURL.Complete = aUrlObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ); + if (xTransformer.is()) + xTransformer->parseStrict(aURL); + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName, + FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN | + FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS); + + if (xDisp.is()) + { + Sequence<PropertyValue> aArgs(1); + aArgs.getArray()->Name = ::rtl::OUString::createFromAscii("Referer"); + aArgs.getArray()->Value <<= aReferer; + xDisp->dispatch(aURL, aArgs); + } + } + // FormMethod POST + else if( eSubmitMethod == FormSubmitMethod_POST ) + { + lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,RTL_TEXTENCODING_MS_1252); + } + } + else if( eSubmitEncoding == FormSubmitEncoding_MULTIPART ) + { + URL aURL; + aURL.Complete = aURLStr; + xTransformer->parseStrict(aURL); + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName, + FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN | + FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS); + + if (xDisp.is()) + { + ::rtl::OUString aContentType; + Sequence<sal_Int8> aData; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + aData = GetDataMultiPartEncoded(Control, MouseEvt, aContentType); + } + if (!aData.getLength()) + return; + + Sequence<PropertyValue> aArgs(3); + aArgs.getArray()[0].Name = ::rtl::OUString::createFromAscii("Referer"); + aArgs.getArray()[0].Value <<= aReferer; + aArgs.getArray()[1].Name = ::rtl::OUString::createFromAscii("ContentType"); + aArgs.getArray()[1].Value <<= aContentType; + + // build a sequence from the to-be-submitted string + Reference< XInputStream > xPostData = new SequenceInputStream(aData); + + aArgs.getArray()[2].Name = ::rtl::OUString::createFromAscii("PostData"); + aArgs.getArray()[2].Value <<= xPostData; + + xDisp->dispatch(aURL, aArgs); + } + } + else if( eSubmitEncoding == FormSubmitEncoding_TEXT ) + { + ::rtl::OUString aData; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + aData = GetDataTextEncoded( Reference<XControl> (), MouseEvt ); + } + + lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,osl_getThreadTextEncoding()); + } + else { + DBG_ERROR("ODatabaseForm::submit_Impl : wrong encoding !"); + } + +} + +// XSubmit +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addSubmitListener(const Reference<XSubmitListener>& _rListener) throw( RuntimeException ) +{ + m_aSubmitListeners.addInterface(_rListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeSubmitListener(const Reference<XSubmitListener>& _rListener) throw( RuntimeException ) +{ + m_aSubmitListeners.removeInterface(_rListener); +} + +//============================================================================== +// com::sun::star::sdbc::XSQLErrorBroadcaster +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addSQLErrorListener(const Reference<XSQLErrorListener>& _rListener) throw( RuntimeException ) +{ + m_aErrorListeners.addInterface(_rListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeSQLErrorListener(const Reference<XSQLErrorListener>& _rListener) throw( RuntimeException ) +{ + m_aErrorListeners.removeInterface(_rListener); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::invlidateParameters() +{ + ::osl::MutexGuard aGuard(m_aMutex); + m_aParameterManager.clearAllParameterInformation(); +} + +//============================================================================== +// OChangeListener +//------------------------------------------------------------------------------ +void ODatabaseForm::_propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException ) +{ + if ((0 == evt.PropertyName.compareToAscii(PROPERTY_ACTIVE_CONNECTION)) && !m_bForwardingConnection) + { + // the rowset changed its active connection itself (without interaction from our side), so + // we need to fire this event, too + sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION; + fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, sal_False); + } + else // it was one of the statement relevant props + { + // if the statement has changed we have to delete the parameter info + invlidateParameters(); + } +} + +//============================================================================== +// smartXChild +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setParent(const InterfaceRef& Parent) throw ( ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException) +{ + // SYNCHRONIZED -----> + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + Reference<XForm> xParentForm(getParent(), UNO_QUERY); + if (xParentForm.is()) + { + try + { + Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW ); + xParentApprBroadcast->removeRowSetApproveListener( this ); + + Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW ); + xParentLoadable->removeLoadListener( this ); + + Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW ); + xParentProperties->removePropertyChangeListener( PROPERTY_ISNEW, this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + OFormComponents::setParent(Parent); + + xParentForm.set(getParent(), UNO_QUERY); + if ( xParentForm.is() ) + { + try + { + Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW ); + xParentApprBroadcast->addRowSetApproveListener( this ); + + Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW ); + xParentLoadable->addLoadListener( this ); + + Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW ); + xParentProperties->addPropertyChangeListener( PROPERTY_ISNEW, this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + Reference< XPropertySet > xAggregateProperties( m_xAggregateSet ); + aGuard.clear(); + // <----- SYNCHRONIZED + + Reference< XConnection > xOuterConnection; + sal_Bool bIsEmbedded = ::dbtools::isEmbeddedInDatabase( Parent, xOuterConnection ); + + if ( bIsEmbedded ) + xAggregateProperties->setPropertyValue( PROPERTY_DATASOURCE, makeAny( ::rtl::OUString() ) ); +} + +//============================================================================== +// smartXTabControllerModel +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::getGroupControl() throw(com::sun::star::uno::RuntimeException) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + // Sollen Controls in einer TabOrder gruppe zusammengefasst werden? + if (m_aCycle.hasValue()) + { + sal_Int32 nCycle = 0; + ::cppu::enum2int(nCycle, m_aCycle); + return nCycle != TabulatorCycle_PAGE; + } + + if (isLoaded() && getConnection().is()) + return sal_True; + + return sal_False; +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setControlModels(const Sequence<Reference<XControlModel> >& rControls) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + // TabIndex in der Reihenfolge der Sequence setzen + const Reference<XControlModel>* pControls = rControls.getConstArray(); + sal_Int16 nTabIndex = 1; + sal_Int32 nCount = getCount(); + sal_Int32 nNewCount = rControls.getLength(); + + // HiddenControls und Formulare werden nicht aufgefuehrt + if (nNewCount <= nCount) + { + Any aElement; + for (sal_Int32 i=0; i < nNewCount; ++i, ++pControls) + { + Reference<XFormComponent> xComp(*pControls, UNO_QUERY); + if (xComp.is()) + { + // suchen der Componente in der Liste + for (sal_Int32 j = 0; j < nCount; ++j) + { + Reference<XFormComponent> xElement; + ::cppu::extractInterface(xElement, getByIndex(j)); + if (xComp == xElement) + { + Reference<XPropertySet> xSet(xComp, UNO_QUERY); + if (xSet.is() && hasProperty(PROPERTY_TABINDEX, xSet)) + xSet->setPropertyValue( PROPERTY_TABINDEX, makeAny(nTabIndex++) ); + break; + } + } + } + } + } +} + +//------------------------------------------------------------------------------ +Sequence<Reference<XControlModel> > SAL_CALL ODatabaseForm::getControlModels() throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + return m_pGroupManager->getControlModels(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setGroup( const Sequence<Reference<XControlModel> >& _rGroup, const ::rtl::OUString& Name ) throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + + // Die Controls werden gruppiert, indem ihr Name dem Namen des ersten + // Controls der Sequenz angepasst wird + const Reference<XControlModel>* pControls = _rGroup.getConstArray(); + Reference< XPropertySet > xSet; + ::rtl::OUString sGroupName( Name ); + + for( sal_Int32 i=0; i<_rGroup.getLength(); ++i, ++pControls ) + { + xSet = xSet.query( *pControls ); + if ( !xSet.is() ) + { + // can't throw an exception other than a RuntimeException (which would not be appropriate), + // so we ignore (and only assert) this + OSL_ENSURE( sal_False, "ODatabaseForm::setGroup: invalid arguments!" ); + continue; + } + + if (!sGroupName.getLength()) + xSet->getPropertyValue(PROPERTY_NAME) >>= sGroupName; + else + xSet->setPropertyValue(PROPERTY_NAME, makeAny(sGroupName)); + } +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL ODatabaseForm::getGroupCount() throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + return m_pGroupManager->getGroupCount(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::getGroup( sal_Int32 nGroup, Sequence<Reference<XControlModel> >& _rGroup, ::rtl::OUString& _rName ) throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + _rGroup.realloc(0); + _rName = ::rtl::OUString(); + + if ((nGroup < 0) || (nGroup >= m_pGroupManager->getGroupCount())) + return; + m_pGroupManager->getGroup( nGroup, _rGroup, _rName ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::getGroupByName(const ::rtl::OUString& Name, Sequence< Reference<XControlModel> >& _rGroup) throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + _rGroup.realloc(0); + m_pGroupManager->getGroupByName( Name, _rGroup ); +} + +//============================================================================== +// com::sun::star::lang::XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::disposing(const EventObject& Source) throw( RuntimeException ) +{ + // does the call come from the connection which we are sharing with our parent? + if ( isSharingConnection() ) + { + Reference< XConnection > xConnSource( Source.Source, UNO_QUERY ); + if ( xConnSource.is() ) + { +#if OSL_DEBUG_LEVEL > 0 + Reference< XConnection > xActiveConn; + m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xActiveConn; + OSL_ENSURE( xActiveConn.get() == xConnSource.get(), "ODatabaseForm::disposing: where did this come from?" ); + // there should be exactly one XConnection object we're listening at - our aggregate connection +#endif + disposingSharedConnection( xConnSource ); + } + } + + OInterfaceContainer::disposing(Source); + + // does the disposing come from the aggregate ? + if (m_xAggregate.is()) + { // no -> forward it + com::sun::star::uno::Reference<com::sun::star::lang::XEventListener> xListener; + if (query_aggregation(m_xAggregate, xListener)) + xListener->disposing(Source); + } +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::impl_createLoadTimer() +{ + OSL_PRECOND( m_pLoadTimer == NULL, "ODatabaseForm::impl_createLoadTimer: timer already exists!" ); + m_pLoadTimer = new Timer(); + m_pLoadTimer->SetTimeout(100); + m_pLoadTimer->SetTimeoutHdl(LINK(this,ODatabaseForm,OnTimeout)); +} + +//============================================================================== +// com::sun::star::form::XLoadListener +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::loaded(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + { + ::osl::MutexGuard aGuard( m_aMutex ); + Reference< XRowSet > xParentRowSet( m_xParent, UNO_QUERY_THROW ); + xParentRowSet->addRowSetListener( this ); + + impl_createLoadTimer(); + } + + load_impl( sal_True ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::unloading(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + { + // now stop the rowset listening if we are a subform + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pLoadTimer && m_pLoadTimer->IsActive() ) + m_pLoadTimer->Stop(); + DELETEZ( m_pLoadTimer ); + + Reference< XRowSet > xParentRowSet( m_xParent, UNO_QUERY_THROW ); + xParentRowSet->removeRowSetListener( this ); + } + + unload(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::unloaded(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + // nothing to do +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::reloading(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + // now stop the rowset listening if we are a subform + ::osl::MutexGuard aGuard(m_aMutex); + Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY); + if (xParentRowSet.is()) + xParentRowSet->removeRowSetListener(this); + + if (m_pLoadTimer && m_pLoadTimer->IsActive()) + m_pLoadTimer->Stop(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::reloaded(const EventObject& /*aEvent*/) throw( RuntimeException ) +{ + reload_impl(sal_True); + { + ::osl::MutexGuard aGuard(m_aMutex); + Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY); + if (xParentRowSet.is()) + xParentRowSet->addRowSetListener(this); + } +} + +//------------------------------------------------------------------------------ +IMPL_LINK( ODatabaseForm, OnTimeout, void*, EMPTYARG ) +{ + reload_impl(sal_True); + return 1; +} + +//============================================================================== +// com::sun::star::form::XLoadable +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::load() throw( RuntimeException ) +{ + load_impl(sal_False); +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseForm::canShareConnection( const Reference< XPropertySet >& _rxParentProps ) +{ + // our own data source + ::rtl::OUString sOwnDatasource; + m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE ) >>= sOwnDatasource; + + // our parents data source + ::rtl::OUString sParentDataSource; + OSL_ENSURE( _rxParentProps.is() && _rxParentProps->getPropertySetInfo().is() && _rxParentProps->getPropertySetInfo()->hasPropertyByName( PROPERTY_DATASOURCE ), + "ODatabaseForm::doShareConnection: invalid parent form!" ); + if ( _rxParentProps.is() ) + _rxParentProps->getPropertyValue( PROPERTY_DATASOURCE ) >>= sParentDataSource; + + sal_Bool bCanShareConnection = sal_False; + + // both rowsets share are connected to the same data source + if ( sParentDataSource == sOwnDatasource ) + { + if ( 0 != sParentDataSource.getLength() ) + // and it's really a data source name (not empty) + bCanShareConnection = sal_True; + else + { // the data source name is empty + // -> ook for the URL + ::rtl::OUString sParentURL; + ::rtl::OUString sMyURL; + _rxParentProps->getPropertyValue( PROPERTY_URL ) >>= sParentURL; + m_xAggregateSet->getPropertyValue( PROPERTY_URL ) >>= sMyURL; + + bCanShareConnection = (sParentURL == sMyURL); + } + } + + if ( bCanShareConnection ) + { + // check for the user/password + + // take the user property on the rowset (if any) into account + ::rtl::OUString sParentUser, sParentPwd; + _rxParentProps->getPropertyValue( PROPERTY_USER ) >>= sParentUser; + _rxParentProps->getPropertyValue( PROPERTY_PASSWORD ) >>= sParentPwd; + + ::rtl::OUString sMyUser, sMyPwd; + m_xAggregateSet->getPropertyValue( PROPERTY_USER ) >>= sMyUser; + m_xAggregateSet->getPropertyValue( PROPERTY_PASSWORD ) >>= sMyPwd; + + bCanShareConnection = + ( sParentUser == sMyUser ) + && ( sParentPwd == sMyPwd ); + } + + return bCanShareConnection; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::doShareConnection( const Reference< XPropertySet >& _rxParentProps ) +{ + // get the conneciton of the parent + Reference< XConnection > xParentConn; + _rxParentProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xParentConn; + OSL_ENSURE( xParentConn.is(), "ODatabaseForm::doShareConnection: we're a valid sub-form, but the parent has no connection?!" ); + + if ( xParentConn.is() ) + { + // add as dispose listener to the connection + Reference< XComponent > xParentConnComp( xParentConn, UNO_QUERY ); + OSL_ENSURE( xParentConnComp.is(), "ODatabaseForm::doShareConnection: invalid connection!" ); + xParentConnComp->addEventListener( static_cast< XLoadListener* >( this ) ); + + // forward the connection to our own aggreagte + m_bForwardingConnection = sal_True; + m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xParentConn ) ); + m_bForwardingConnection = sal_False; + + m_bSharingConnection = sal_True; + } + else + m_bSharingConnection = sal_False; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::disposingSharedConnection( const Reference< XConnection >& /*_rxConn*/ ) +{ + stopSharingConnection(); + + // TODO: we could think about whether or not to re-connect. + unload( ); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::stopSharingConnection( ) +{ + OSL_ENSURE( m_bSharingConnection, "ODatabaseForm::stopSharingConnection: invalid call!" ); + + if ( m_bSharingConnection ) + { + // get the connection + Reference< XConnection > xSharedConn; + m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xSharedConn; + OSL_ENSURE( xSharedConn.is(), "ODatabaseForm::stopSharingConnection: there's no conn!" ); + + // remove ourself as event listener + Reference< XComponent > xSharedConnComp( xSharedConn, UNO_QUERY ); + if ( xSharedConnComp.is() ) + xSharedConnComp->removeEventListener( static_cast< XLoadListener* >( this ) ); + + // no need to dispose the conn: we're not the owner, this is our parent + // (in addition, this method may be called if the connection is beeing disposed while we use it) + + // reset the property + xSharedConn.clear(); + m_bForwardingConnection = sal_True; + m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xSharedConn ) ); + m_bForwardingConnection = sal_False; + + // reset the flag + m_bSharingConnection = sal_False; + } +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseForm::implEnsureConnection() +{ + try + { + if ( getConnection( ).is() ) + // if our aggregate already has a connection, nothing needs to be done about it + return sal_True; + + // see whether we're an embedded form + Reference< XConnection > xOuterConnection; + if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) ) + { + m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xOuterConnection ) ); + return xOuterConnection.is(); + } + + m_bSharingConnection = sal_False; + + // if we're a sub form, we try to re-use the connection of our parent + if (m_bSubForm) + { + OSL_ENSURE( Reference< XForm >( getParent(), UNO_QUERY ).is(), + "ODatabaseForm::implEnsureConnection: m_bSubForm is TRUE, but the parent is no form?" ); + + Reference< XPropertySet > xParentProps( getParent(), UNO_QUERY ); + + // can we re-use (aka share) the connection of the parent? + if ( canShareConnection( xParentProps ) ) + { + // yep -> do it + doShareConnection( xParentProps ); + // success? + if ( m_bSharingConnection ) + // yes -> outta here + return sal_True; + } + } + + if (m_xAggregateSet.is()) + { + Reference< XConnection > xConnection = connectRowset( + Reference<XRowSet> (m_xAggregate, UNO_QUERY), + m_xServiceFactory, + sal_True // set a calculated connection as ActiveConnection + ); + return xConnection.is(); + } + } + catch(SQLException& eDB) + { + onError(eDB, FRM_RES_STRING(RID_STR_CONNECTERROR)); + } + catch( Exception ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return sal_False; +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::load_impl(sal_Bool bCausedByParentForm, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler ) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + // are we already loaded? + if (isLoaded()) + return; + + m_bSubForm = bCausedByParentForm; + + // if we don't have a connection, we are not intended to be a database form or the aggregate was not able + // to establish a connection + sal_Bool bConnected = implEnsureConnection(); + + // we don't have to execute if we do not have a command to execute + sal_Bool bExecute = bConnected && m_xAggregateSet.is() && getString(m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND)).getLength(); + + // a database form always uses caching + // we use starting fetchsize with at least 10 rows + if (bConnected) + m_xAggregateSet->setPropertyValue(PROPERTY_FETCHSIZE, makeAny((sal_Int32)10)); + + // if we're loaded as sub form we got a "rowSetChanged" from the parent rowset _before_ we got the "loaded" + // so we don't need to execute the statement again, this was already done + // (and there were no relevant changes between these two listener calls, the "load" of a form is quite an + // atomar operation.) + + sal_Bool bSuccess = sal_False; + if (bExecute) + { + m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_LOADING_FORM); + bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler); + } + + if (bSuccess) + { + m_bLoaded = sal_True; + aGuard.clear(); + EventObject aEvt(static_cast<XWeak*>(this)); + m_aLoadListeners.notifyEach( &XLoadListener::loaded, aEvt ); + + // if we are on the insert row, we have to reset all controls + // to set the default values + if (bExecute && getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW))) + reset(); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::unload() throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + if (!isLoaded()) + return; + + DELETEZ(m_pLoadTimer); + + aGuard.clear(); + EventObject aEvt(static_cast<XWeak*>(this)); + m_aLoadListeners.notifyEach( &XLoadListener::unloading, aEvt ); + + if (m_xAggregateAsRowSet.is()) + { + // we may have reset the InsertOnly property on the aggregate - restore it + restoreInsertOnlyState( ); + + // clear the parameters if there are any + invlidateParameters(); + + try + { + // close the aggregate + Reference<XCloseable> xCloseable; + query_aggregation( m_xAggregate, xCloseable); + aGuard.clear(); + if (xCloseable.is()) + xCloseable->close(); + } + catch( const SQLException& e ) + { + (void)e; + } + aGuard.reset(); + } + + m_bLoaded = sal_False; + + // if the connection we used while we were loaded is only shared with our parent, we + // reset it + if ( isSharingConnection() ) + stopSharingConnection(); + + aGuard.clear(); + m_aLoadListeners.notifyEach( &XLoadListener::unloaded, aEvt ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::reload() throw( RuntimeException ) +{ + reload_impl(sal_True); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::reload_impl(sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler ) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + if (!isLoaded()) + return; + + DocumentModifyGuard aModifyGuard( *this ); + // ensures the document is not marked as "modified" just because we change some control's content during + // reloading ... + + EventObject aEvent(static_cast<XWeak*>(this)); + { + // only if there is no approve listener we can post the event at this time + // otherwise see approveRowsetChange + // the aprrovement is done by the aggregate + if (!m_aRowSetApproveListeners.getLength()) + { + ::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners); + aGuard.clear(); + + while (aIter.hasMoreElements()) + ((XLoadListener*)aIter.next())->reloading(aEvent); + + aGuard.reset(); + } + } + + sal_Bool bSuccess = sal_True; + try + { + m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_REFRESHING_FORM); + bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler); + } + catch( const SQLException& e ) + { + DBG_ERROR("ODatabaseForm::reload_impl : shouldn't executeRowSet catch this exception?"); + (void)e; + } + + if (bSuccess) + { + ::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners); + aGuard.clear(); + while (aIter.hasMoreElements()) + ((XLoadListener*)aIter.next())->reloaded(aEvent); + + // if we are on the insert row, we have to reset all controls + // to set the default values + if (getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW))) + reset(); + } + else + m_bLoaded = sal_False; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isLoaded() throw( RuntimeException ) +{ + return m_bLoaded; +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addLoadListener(const Reference<XLoadListener>& aListener) throw( RuntimeException ) +{ + m_aLoadListeners.addInterface(aListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeLoadListener(const Reference<XLoadListener>& aListener) throw( RuntimeException ) +{ + m_aLoadListeners.removeInterface(aListener); +} + +//============================================================================== +// com::sun::star::sdbc::XCloseable +//============================================================================== +void SAL_CALL ODatabaseForm::close() throw( SQLException, RuntimeException ) +{ + // unload will close the aggregate + unload(); +} + +//============================================================================== +// com::sun::star::sdbc::XRowSetListener +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::cursorMoved(const EventObject& /*event*/) throw( RuntimeException ) +{ + // reload the subform with the new parameters of the parent + // do this handling delayed to provide of execute too many SQL Statements + ::osl::ResettableMutexGuard aGuard(m_aMutex); + + DBG_ASSERT( m_pLoadTimer, "ODatabaseForm::cursorMoved: how can this happen?!" ); + if ( !m_pLoadTimer ) + impl_createLoadTimer(); + + if ( m_pLoadTimer->IsActive() ) + m_pLoadTimer->Stop(); + + // and start the timer again + m_pLoadTimer->Start(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::rowChanged(const EventObject& /*event*/) throw( RuntimeException ) +{ + // ignore it +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException ) +{ + // not interested in : + // if our parent is an ODatabaseForm, too, then after this rowSetChanged we'll get a "reloaded" + // or a "loaded" event. + // If somebody gave us another parent which is an XRowSet but doesn't handle an execute as + // "load" respectivly "reload" ... can't do anything .... +} + +//------------------------------------------------------------------------------ +bool ODatabaseForm::impl_approveRowChange_throw( const EventObject& _rEvent, const bool _bAllowSQLException, + ::osl::ClearableMutexGuard& _rGuard ) +{ + ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners ); + _rGuard.clear(); + while ( aIter.hasMoreElements() ) + { + Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) ); + if ( !xListener.is() ) + continue; + + try + { + if ( !xListener->approveRowSetChange( _rEvent ) ) + return false; + } + catch ( const DisposedException& e ) + { + if ( e.Context == xListener ) + aIter.remove(); + } + catch ( const RuntimeException& ) { throw; } + catch ( const SQLException& ) + { + if ( _bAllowSQLException ) + throw; + DBG_UNHANDLED_EXCEPTION(); + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return true; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::approveCursorMove(const EventObject& event) throw( RuntimeException ) +{ + // is our aggregate calling? + if (event.Source == InterfaceRef(static_cast<XWeak*>(this))) + { + // Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface + // for XRowSetApproveBroadcaster-interface. + // So we have to multiplex this approve request. + ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners ); + while ( aIter.hasMoreElements() ) + { + Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) ); + if ( !xListener.is() ) + continue; + + try + { + if ( !xListener->approveCursorMove( event ) ) + return sal_False; + } + catch ( const DisposedException& e ) + { + if ( e.Context == xListener ) + aIter.remove(); + } + catch ( const RuntimeException& ) { throw; } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return true; + } + else + { + // this is a call from our parent ... + // a parent's cursor move will result in a re-execute of our own row-set, so we have to + // ask our own RowSetChangesListeners, too + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if ( !impl_approveRowChange_throw( event, false, aGuard ) ) + return sal_False; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::approveRowChange(const RowChangeEvent& event) throw( RuntimeException ) +{ + // is our aggregate calling? + if (event.Source == InterfaceRef(static_cast<XWeak*>(this))) + { + // Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface + // for XRowSetApproveBroadcaster-interface. + // So we have to multiplex this approve request. + ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners ); + while ( aIter.hasMoreElements() ) + { + Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) ); + if ( !xListener.is() ) + continue; + + try + { + if ( !xListener->approveRowChange( event ) ) + return false; + } + catch ( const DisposedException& e ) + { + if ( e.Context == xListener ) + aIter.remove(); + } + catch ( const RuntimeException& ) { throw; } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return true; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::approveRowSetChange(const EventObject& event) throw( RuntimeException ) +{ + if (event.Source == InterfaceRef(static_cast<XWeak*>(this))) // ignore our aggregate as we handle this approve ourself + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + bool bWasLoaded = isLoaded(); + if ( !impl_approveRowChange_throw( event, false, aGuard ) ) + return sal_False; + + if ( bWasLoaded ) + { + m_aLoadListeners.notifyEach( &XLoadListener::reloading, event ); + } + } + else + { + // this is a call from our parent ... + // a parent's cursor move will result in a re-execute of our own row-set, so we have to + // ask our own RowSetChangesListeners, too + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if ( !impl_approveRowChange_throw( event, false, aGuard ) ) + return sal_False; + } + return sal_True; +} + +//============================================================================== +// com::sun::star::sdb::XRowSetApproveBroadcaster +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + m_aRowSetApproveListeners.addInterface(_rListener); + + // do we have to multiplex ? + if (m_aRowSetApproveListeners.getLength() == 1) + { + Reference<XRowSetApproveBroadcaster> xBroadcaster; + if (query_aggregation( m_xAggregate, xBroadcaster)) + { + Reference<XRowSetApproveListener> xListener((XRowSetApproveListener*)this); + xBroadcaster->addRowSetApproveListener(xListener); + } + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener) throw( RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + // do we have to remove the multiplex ? + m_aRowSetApproveListeners.removeInterface(_rListener); + if ( m_aRowSetApproveListeners.getLength() == 0 ) + { + Reference<XRowSetApproveBroadcaster> xBroadcaster; + if (query_aggregation( m_xAggregate, xBroadcaster)) + { + Reference<XRowSetApproveListener> xListener((XRowSetApproveListener*)this); + xBroadcaster->removeRowSetApproveListener(xListener); + } + } +} + +//============================================================================== +// com::sun:star::form::XDatabaseParameterBroadcaster +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException ) +{ + m_aParameterManager.addParameterListener( _rListener ); +} +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException ) +{ + m_aParameterManager.removeParameterListener( _rListener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException ) +{ + ODatabaseForm::addDatabaseParameterListener( _rListener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException ) +{ + ODatabaseForm::removeDatabaseParameterListener( _rListener ); +} + +//============================================================================== +// com::sun::star::sdb::XCompletedExecution +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard(m_aMutex); + // the difference between execute and load is, that we position on the first row in case of load + // after execute we remain before the first row + if (!isLoaded()) + { + aGuard.clear(); + load_impl(sal_False, sal_False, _rxHandler); + } + else + { + EventObject event(static_cast< XWeak* >(this)); + if ( !impl_approveRowChange_throw( event, true, aGuard ) ) + return; + + // we're loaded and somebody want's to execute ourself -> this means a reload + reload_impl(sal_False, _rxHandler); + } +} + +//============================================================================== +// com::sun::star::sdbc::XRowSet +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::execute() throw( SQLException, RuntimeException ) +{ + ::osl::ResettableMutexGuard aGuard(m_aMutex); + // if somebody calls an execute and we're not loaded we reroute this call to our load method. + + // the difference between execute and load is, that we position on the first row in case of load + // after execute we remain before the first row + if (!isLoaded()) + { + aGuard.clear(); + load_impl(sal_False, sal_False); + } + else + { + EventObject event(static_cast< XWeak* >(this)); + if ( !impl_approveRowChange_throw( event, true, aGuard ) ) + return; + + // we're loaded and somebody want's to execute ourself -> this means a reload + reload_impl(sal_False); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::addRowSetListener(const Reference<XRowSetListener>& _rListener) throw( RuntimeException ) +{ + if (m_xAggregateAsRowSet.is()) + m_xAggregateAsRowSet->addRowSetListener(_rListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::removeRowSetListener(const Reference<XRowSetListener>& _rListener) throw( RuntimeException ) +{ + if (m_xAggregateAsRowSet.is()) + m_xAggregateAsRowSet->removeRowSetListener(_rListener); +} + +//============================================================================== +// com::sun::star::sdbc::XResultSet +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::next() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->next(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isBeforeFirst() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->isBeforeFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isAfterLast() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->isAfterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isFirst() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->isFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::isLast() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->isLast(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::beforeFirst() throw( SQLException, RuntimeException ) +{ + m_xAggregateAsRowSet->beforeFirst(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::afterLast() throw( SQLException, RuntimeException ) +{ + m_xAggregateAsRowSet->afterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::first() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->first(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::last() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->last(); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL ODatabaseForm::getRow() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->getRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::absolute(sal_Int32 row) throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->absolute(row); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::relative(sal_Int32 rows) throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->relative(rows); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::previous() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->previous(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::refreshRow() throw( SQLException, RuntimeException ) +{ + m_xAggregateAsRowSet->refreshRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::rowUpdated() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->rowUpdated(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::rowInserted() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->rowInserted(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::rowDeleted() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->rowDeleted(); +} + +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL ODatabaseForm::getStatement() throw( SQLException, RuntimeException ) +{ + return m_xAggregateAsRowSet->getStatement(); +} + +// com::sun::star::sdbc::XResultSetUpdate +// exceptions during insert update and delete will be forwarded to the errorlistener +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::insertRow() throw( SQLException, RuntimeException ) +{ + try + { + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->insertRow(); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD)); + throw; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::updateRow() throw( SQLException, RuntimeException ) +{ + try + { + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->updateRow(); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_UPDATERECORD)); + throw; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::deleteRow() throw( SQLException, RuntimeException ) +{ + try + { + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->deleteRow(); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORD)); + throw; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::cancelRowUpdates() throw( SQLException, RuntimeException ) +{ + try + { + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->cancelRowUpdates(); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD)); + throw; + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::moveToInsertRow() throw( SQLException, RuntimeException ) +{ + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + { + // _always_ move to the insert row + // + // Formerly, the following line was conditioned with a "not is new", means we did not move the aggregate + // to the insert row if it was already positioned there. + // + // This prevented the RowSet implementation from resetting it's column values. We, ourself, formerly + // did this reset of columns in reset_impl, where we set every column to the ControlDefault, or, if this + // was not present, to NULL. However, the problem with setting to NULL was #88888#, the problem with + // _not_ setting to NULL (which was the original fix for #88888#) was #97955#. + // + // So now we + // * move our aggregate to the insert row + // * in reset_impl + // - set the control defaults into the columns if not void + // - do _not_ set the columns to NULL if no control default is set + // This fixes both #88888# and #97955# + // + // Still, there is #72756#. During fixing this bug, DG introduced not calling the aggregate here. So + // in theory, we re-introduced #72756#. But the bug described therein does not happen anymore, as the + // preliminaries for it changed (no display of guessed values for new records with autoinc fields) + // + // BTW: the public Issuezilla bug for #97955# is #i2815# + // + // 16.04.2002 - 97955 - fs@openoffice.org + xUpdate->moveToInsertRow(); + + // then set the default values and the parameters given from the parent + reset(); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::moveToCurrentRow() throw( SQLException, RuntimeException ) +{ + Reference<XResultSetUpdate> xUpdate; + if (query_aggregation( m_xAggregate, xUpdate)) + xUpdate->moveToCurrentRow(); +} + +// com::sun::star::sdbcx::XDeleteRows +//------------------------------------------------------------------------------ +Sequence<sal_Int32> SAL_CALL ODatabaseForm::deleteRows(const Sequence<Any>& rows) throw( SQLException, RuntimeException ) +{ + try + { + Reference<XDeleteRows> xDelete; + if (query_aggregation( m_xAggregate, xDelete)) + return xDelete->deleteRows(rows); + } + catch( const RowSetVetoException& eVeto ) + { + (void)eVeto; // make compiler happy + throw; + } + catch(SQLException& eDb) + { + onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORDS)); + throw; + } + + return Sequence< sal_Int32 >(); +} + +// com::sun::star::sdbc::XParameters +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setNull(parameterIndex, sqlType); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObjectNull(parameterIndex, sqlType, typeName); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setBoolean(sal_Int32 parameterIndex, sal_Bool x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBoolean(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setByte(sal_Int32 parameterIndex, sal_Int8 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setByte(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setShort(sal_Int32 parameterIndex, sal_Int16 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setShort(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setInt(sal_Int32 parameterIndex, sal_Int32 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setInt(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setLong(sal_Int32 parameterIndex, sal_Int64 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setLong(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setFloat(sal_Int32 parameterIndex, float x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setFloat(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setDouble(sal_Int32 parameterIndex, double x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setDouble(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setString(sal_Int32 parameterIndex, const ::rtl::OUString& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setString(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setBytes(sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBytes(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setDate(sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setDate(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setTime(sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setTime(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setTimestamp(sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setTimestamp(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setBinaryStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBinaryStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setCharacterStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setCharacterStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setObjectWithInfo(sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObjectWithInfo(parameterIndex, x, targetSqlType, scale); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setObject(sal_Int32 parameterIndex, const Any& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObject(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setRef(sal_Int32 parameterIndex, const Reference<XRef>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setRef(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setBlob(sal_Int32 parameterIndex, const Reference<XBlob>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBlob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setClob(sal_Int32 parameterIndex, const Reference<XClob>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setClob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setArray(sal_Int32 parameterIndex, const Reference<XArray>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setArray(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::clearParameters() throw( SQLException, RuntimeException ) +{ + m_aParameterManager.clearParameters(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException) +{ + if ( evt.Source == m_xParent ) + { + if ( evt.PropertyName == PROPERTY_ISNEW ) + { + sal_Bool bCurrentIsNew( sal_False ); + OSL_VERIFY( evt.NewValue >>= bCurrentIsNew ); + if ( !bCurrentIsNew ) + reload_impl( sal_True ); + } + return; + } + OFormComponents::propertyChange( evt ); +} + +// com::sun::star::lang::XServiceInfo +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODatabaseForm::getImplementationName_Static() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.ODatabaseForm" ) ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getCompatibleServiceNames_Static() +{ + Sequence< ::rtl::OUString > aServices( 1 ); + ::rtl::OUString* pServices = aServices.getArray(); + + *pServices++ = FRM_COMPONENT_FORM; + + return aServices; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getCurrentServiceNames_Static() +{ + Sequence< ::rtl::OUString > aServices( 5 ); + ::rtl::OUString* pServices = aServices.getArray(); + + *pServices++ = FRM_SUN_FORMCOMPONENT; + *pServices++ = ::rtl::OUString::createFromAscii("com.sun.star.form.FormComponents"); + *pServices++ = FRM_SUN_COMPONENT_FORM; + *pServices++ = FRM_SUN_COMPONENT_HTMLFORM; + *pServices++ = FRM_SUN_COMPONENT_DATAFORM; + + return aServices; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames_Static() +{ + return ::comphelper::concatSequences( + getCurrentServiceNames_Static(), + getCompatibleServiceNames_Static() + ); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODatabaseForm::getImplementationName() throw( RuntimeException ) +{ + return getImplementationName_Static(); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames() throw( RuntimeException ) +{ + // the services of our aggregate + Sequence< ::rtl::OUString > aServices; + Reference< XServiceInfo > xInfo; + if (query_aggregation(m_xAggregate, xInfo)) + aServices = xInfo->getSupportedServiceNames(); + + // concat with out own services + return ::comphelper::concatSequences( + getCurrentServiceNames_Static(), + aServices + ); + // use getCurrentXXX instead of getSupportedXXX, because at runtime, we do not want to have + // the compatible names + // This is maily to be consistent with the implementation before fixing #97083#, though the + // better solution _may_ be to return the compatible names at runtime, too + // 04.03.2002 - fs@openoffice.org +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODatabaseForm::supportsService(const ::rtl::OUString& ServiceName) throw( RuntimeException ) +{ + Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() ); + const ::rtl::OUString* pArray = aSupported.getConstArray(); + for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray ) + if( pArray->equals( ServiceName ) ) + return sal_True; + return sal_False; +} + +//============================================================================== +// com::sun::star::io::XPersistObject +//------------------------------------------------------------------------------ + +const sal_uInt16 CYCLE = 0x0001; +const sal_uInt16 DONTAPPLYFILTER = 0x0002; + +//------------------------------------------------------------------------------ +::rtl::OUString ODatabaseForm::getServiceName() throw( RuntimeException ) +{ + return FRM_COMPONENT_FORM; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::write(const Reference<XObjectOutputStream>& _rxOutStream) throw( IOException, RuntimeException ) +{ + DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::write : only to be called if the aggregate exists !"); + + // all children + OFormComponents::write(_rxOutStream); + + // version + _rxOutStream->writeShort(0x0003); + + // Name + _rxOutStream << m_sName; + + ::rtl::OUString sDataSource; + if (m_xAggregateSet.is()) + m_xAggregateSet->getPropertyValue(PROPERTY_DATASOURCE) >>= sDataSource; + _rxOutStream << sDataSource; + + // former CursorSource + ::rtl::OUString sCommand; + if (m_xAggregateSet.is()) + m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; + _rxOutStream << sCommand; + + // former MasterFields + _rxOutStream << m_aMasterFields; + // former DetailFields + _rxOutStream << m_aDetailFields; + + // former DataSelectionType + DataSelectionType eTranslated = DataSelectionType_TABLE; + if (m_xAggregateSet.is()) + { + sal_Int32 nCommandType = 0; + m_xAggregateSet->getPropertyValue(PROPERTY_COMMANDTYPE) >>= nCommandType; + switch (nCommandType) + { + case CommandType::TABLE : eTranslated = DataSelectionType_TABLE; break; + case CommandType::QUERY : eTranslated = DataSelectionType_QUERY; break; + case CommandType::COMMAND: + { + sal_Bool bEscapeProcessing = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)); + eTranslated = bEscapeProcessing ? DataSelectionType_SQL : DataSelectionType_SQLPASSTHROUGH; + } + break; + default : DBG_ERROR("ODatabaseForm::write : wrong CommandType !"); + } + } + _rxOutStream->writeShort((sal_Int16)eTranslated); // former DataSelectionType + + // very old versions expect a CursorType here + _rxOutStream->writeShort(DatabaseCursorType_KEYSET); + + _rxOutStream->writeBoolean(m_eNavigation != NavigationBarMode_NONE); + + // former DataEntry + if (m_xAggregateSet.is()) + _rxOutStream->writeBoolean(getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_INSERTONLY))); + else + _rxOutStream->writeBoolean(sal_False); + + _rxOutStream->writeBoolean(m_bAllowInsert); + _rxOutStream->writeBoolean(m_bAllowUpdate); + _rxOutStream->writeBoolean(m_bAllowDelete); + + // html form stuff + ::rtl::OUString sTmp = INetURLObject::decode( m_aTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS); + _rxOutStream << sTmp; + _rxOutStream->writeShort( (sal_Int16)m_eSubmitMethod ); + _rxOutStream->writeShort( (sal_Int16)m_eSubmitEncoding ); + _rxOutStream << m_aTargetFrame; + + // version 2 didn't know some options and the "default" state + sal_Int32 nCycle = TabulatorCycle_RECORDS; + if (m_aCycle.hasValue()) + { + ::cppu::enum2int(nCycle, m_aCycle); + if (m_aCycle == TabulatorCycle_PAGE) + // unknown in earlier versions + nCycle = TabulatorCycle_RECORDS; + } + _rxOutStream->writeShort((sal_Int16) nCycle); + + _rxOutStream->writeShort((sal_Int16)m_eNavigation); + + ::rtl::OUString sFilter; + ::rtl::OUString sOrder; + if (m_xAggregateSet.is()) + { + m_xAggregateSet->getPropertyValue(PROPERTY_FILTER) >>= sFilter; + m_xAggregateSet->getPropertyValue(PROPERTY_SORT) >>= sOrder; + } + _rxOutStream << sFilter; + _rxOutStream << sOrder; + + + // version 3 + sal_uInt16 nAnyMask = 0; + if (m_aCycle.hasValue()) + nAnyMask |= CYCLE; + + if (m_xAggregateSet.is() && !getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_APPLYFILTER))) + nAnyMask |= DONTAPPLYFILTER; + + _rxOutStream->writeShort(nAnyMask); + + if (nAnyMask & CYCLE) + { + sal_Int32 nRealCycle = 0; + ::cppu::enum2int(nRealCycle, m_aCycle); + _rxOutStream->writeShort((sal_Int16)nRealCycle); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException ) +{ + DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::read : only to be called if the aggregate exists !"); + + OFormComponents::read(_rxInStream); + + // version + sal_uInt16 nVersion = _rxInStream->readShort(); + + _rxInStream >> m_sName; + + ::rtl::OUString sAggregateProp; + _rxInStream >> sAggregateProp; + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, makeAny(sAggregateProp)); + _rxInStream >> sAggregateProp; + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_COMMAND, makeAny(sAggregateProp)); + + _rxInStream >> m_aMasterFields; + _rxInStream >> m_aDetailFields; + + sal_Int16 nCursorSourceType = _rxInStream->readShort(); + sal_Int32 nCommandType = 0; + switch ((DataSelectionType)nCursorSourceType) + { + case DataSelectionType_TABLE : nCommandType = CommandType::TABLE; break; + case DataSelectionType_QUERY : nCommandType = CommandType::QUERY; break; + case DataSelectionType_SQL: + case DataSelectionType_SQLPASSTHROUGH: + { + nCommandType = CommandType::COMMAND; + sal_Bool bEscapeProcessing = ((DataSelectionType)nCursorSourceType) != DataSelectionType_SQLPASSTHROUGH; + m_xAggregateSet->setPropertyValue(PROPERTY_ESCAPE_PROCESSING, makeAny((sal_Bool)bEscapeProcessing)); + } + break; + default : DBG_ERROR("ODatabaseForm::read : wrong CommandType !"); + } + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_COMMANDTYPE, makeAny(nCommandType)); + + // obsolete + _rxInStream->readShort(); + + // navigation mode was a boolean in version 1 + // war in der version 1 ein sal_Bool + sal_Bool bNavigation = _rxInStream->readBoolean(); + if (nVersion == 1) + m_eNavigation = bNavigation ? NavigationBarMode_CURRENT : NavigationBarMode_NONE; + + sal_Bool bInsertOnly = _rxInStream->readBoolean(); + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_INSERTONLY, makeAny(bInsertOnly)); + + m_bAllowInsert = _rxInStream->readBoolean(); + m_bAllowUpdate = _rxInStream->readBoolean(); + m_bAllowDelete = _rxInStream->readBoolean(); + + // html stuff + ::rtl::OUString sTmp; + _rxInStream >> sTmp; + m_aTargetURL = INetURLObject::decode( sTmp, '%', INetURLObject::DECODE_UNAMBIGUOUS); + m_eSubmitMethod = (FormSubmitMethod)_rxInStream->readShort(); + m_eSubmitEncoding = (FormSubmitEncoding)_rxInStream->readShort(); + _rxInStream >> m_aTargetFrame; + + if (nVersion > 1) + { + sal_Int32 nCycle = _rxInStream->readShort(); + m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL))); + m_eNavigation = (NavigationBarMode)_rxInStream->readShort(); + + _rxInStream >> sAggregateProp; + setPropertyValue(PROPERTY_FILTER, makeAny(sAggregateProp)); + + _rxInStream >> sAggregateProp; + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_SORT, makeAny(sAggregateProp)); + } + + sal_uInt16 nAnyMask = 0; + if (nVersion > 2) + { + nAnyMask = _rxInStream->readShort(); + if (nAnyMask & CYCLE) + { + sal_Int32 nCycle = _rxInStream->readShort(); + m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL))); + } + else + m_aCycle.clear(); + } + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_APPLYFILTER, makeAny((sal_Bool)((nAnyMask & DONTAPPLYFILTER) == 0))); +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::implInserted( const ElementDescription* _pElement ) +{ + OFormComponents::implInserted( _pElement ); + + Reference< XSQLErrorBroadcaster > xBroadcaster( _pElement->xInterface, UNO_QUERY ); + Reference< XForm > xForm ( _pElement->xInterface, UNO_QUERY ); + + if ( xBroadcaster.is() && !xForm.is() ) + { // the object is an error broadcaster, but no form itself -> add ourself as listener + xBroadcaster->addSQLErrorListener( this ); + } +} + +//------------------------------------------------------------------------------ +void ODatabaseForm::implRemoved(const InterfaceRef& _rxObject) +{ + OFormComponents::implRemoved( _rxObject ); + + Reference<XSQLErrorBroadcaster> xBroadcaster(_rxObject, UNO_QUERY); + Reference<XForm> xForm(_rxObject, UNO_QUERY); + if (xBroadcaster.is() && !xForm.is()) + { // the object is an error broadcaster, but no form itself -> remove ourself as listener + xBroadcaster->removeSQLErrorListener(this); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::errorOccured(const SQLErrorEvent& _rEvent) throw( RuntimeException ) +{ + // give it to my own error listener + onError(_rEvent); + // TODO : think about extending the chain with an SQLContext object saying + // "this was an error of one of my children" +} + +// com::sun::star::container::XNamed +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODatabaseForm::getName() throw( RuntimeException ) +{ + ::rtl::OUString sReturn; + OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= sReturn; + return sReturn; +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseForm::setName(const ::rtl::OUString& aName) throw( RuntimeException ) +{ + setFastPropertyValue(PROPERTY_ID_NAME, makeAny(aName)); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/DatabaseForm.hxx b/forms/source/component/DatabaseForm.hxx new file mode 100644 index 000000000000..af506aa305d2 --- /dev/null +++ b/forms/source/component/DatabaseForm.hxx @@ -0,0 +1,569 @@ +/************************************************************************* + * + * 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 _FRM_DATABASEFORM_HXX_ +#define _FRM_DATABASEFORM_HXX_ + +#include "propertybaghelper.hxx" +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/sdb/XSQLErrorListener.hpp> +#include <com/sun/star/io/XPersistObject.hpp> +#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp> +#include <com/sun/star/form/FormSubmitMethod.hpp> +#include <com/sun/star/form/FormSubmitEncoding.hpp> +#include <com/sun/star/form/XSubmit.hpp> +#include <com/sun/star/form/XReset.hpp> +#include <com/sun/star/form/XDatabaseParameterBroadcaster2.hpp> +#include <com/sun/star/sdb/XCompletedExecution.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#include <com/sun/star/sdb/XRowSetApproveListener.hpp> +#include <com/sun/star/sdb/XRowSetApproveBroadcaster.hpp> +#include <com/sun/star/form/NavigationBarMode.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/form/XLoadListener.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/awt/XTabControllerModel.hpp> +#include <com/sun/star/script/XEventAttacherManager.hpp> +#include <com/sun/star/sdbc/XRowSetListener.hpp> +#include <com/sun/star/sdb/XResultSetAccess.hpp> +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> + + +#include <tools/link.hxx> +#include "InterfaceContainer.hxx" + +#include <connectivity/parameters.hxx> +#include <connectivity/filtermanager.hxx> +#include <connectivity/warningscontainer.hxx> + +#ifndef FORMS_SOURCE_MISC_LISTENERCONTAINERS_HXX +#include "listenercontainers.hxx" +#endif +#include "ids.hxx" +#include <comphelper/propmultiplex.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/proparrhlp.hxx> +#include <cppuhelper/implbase12.hxx> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/implbase7.hxx> + +namespace com { namespace sun { namespace star { namespace sdbc { + class SQLException; +} } } } + +class Timer; +class INetMIMEMessage; + +//......................................................................... +namespace frm +{ +//......................................................................... + +//======================================================================== +//= html tools +//======================================================================== + +const sal_uInt16 SUCCESSFUL_REPRESENT_TEXT = 0x0001; +const sal_uInt16 SUCCESSFUL_REPRESENT_FILE = 0x0002; + +//------------------------------------------------------------------------------ +class HtmlSuccessfulObj +{ +public: + ::rtl::OUString aName; + ::rtl::OUString aValue; + sal_uInt16 nRepresentation; + + HtmlSuccessfulObj( const ::rtl::OUString& _rName, const ::rtl::OUString& _rValue, + sal_uInt16 _nRepresent = SUCCESSFUL_REPRESENT_TEXT ) + :aName( _rName ) + ,aValue( _rValue ) + ,nRepresentation( _nRepresent ) + { + } + + HtmlSuccessfulObj() + { + } +}; + + +DECLARE_STL_VECTOR(HtmlSuccessfulObj, HtmlSuccessfulObjList); + +//======================================================================== +class OGroupManager; +class OFormSubmitResetThread; +typedef ::cppu::ImplHelper12 < ::com::sun::star::form::XForm + , ::com::sun::star::awt::XTabControllerModel + , ::com::sun::star::form::XLoadListener + , ::com::sun::star::sdbc::XRowSetListener + , ::com::sun::star::sdb::XRowSetApproveListener + , ::com::sun::star::form::XDatabaseParameterBroadcaster2 + , ::com::sun::star::sdb::XSQLErrorListener + , ::com::sun::star::sdb::XSQLErrorBroadcaster + , ::com::sun::star::form::XReset + , ::com::sun::star::form::XSubmit + , ::com::sun::star::form::XLoadable + , ::com::sun::star::container::XNamed + > ODatabaseForm_BASE1; + + +typedef ::cppu::ImplHelper4 < ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::beans::XPropertyContainer + , ::com::sun::star::beans::XPropertyAccess + , ::com::sun::star::sdbc::XWarningsSupplier + > ODatabaseForm_BASE2; + +typedef ::cppu::ImplHelper7< ::com::sun::star::sdbc::XCloseable, + ::com::sun::star::sdbc::XRowSet, + ::com::sun::star::sdb::XCompletedExecution, + ::com::sun::star::sdb::XRowSetApproveBroadcaster, + ::com::sun::star::sdbc::XResultSetUpdate, + ::com::sun::star::sdbcx::XDeleteRows, + ::com::sun::star::sdbc::XParameters > ODatabaseForm_BASE3; + + +class ODatabaseForm :public OFormComponents + ,public OPropertySetAggregationHelper + ,public OPropertyChangeListener + ,public ODatabaseForm_BASE1 + ,public ODatabaseForm_BASE2 + ,public ODatabaseForm_BASE3 + ,public IPropertyBagHelperContext +{ + friend class OFormSubmitResetThread; + + OImplementationIdsRef m_aHoldIdHelper; + + // listener administration + ::cppu::OInterfaceContainerHelper m_aLoadListeners; + ::cppu::OInterfaceContainerHelper m_aRowSetApproveListeners; + ::cppu::OInterfaceContainerHelper m_aRowSetListeners; + ::cppu::OInterfaceContainerHelper m_aSubmitListeners; + ::cppu::OInterfaceContainerHelper m_aErrorListeners; + ResetListeners m_aResetListeners; + ::osl::Mutex m_aResetSafety; + ::com::sun::star::uno::Any m_aCycle; + ::com::sun::star::uno::Any m_aIgnoreResult; // set when we are a subform and our master form positioned on a new row + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aMasterFields; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aDetailFields; + + // the object doin' most of the work - an SDB-rowset + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> m_xAggregate; + // same object, interface as member because of performance reasons + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet> m_xAggregateAsRowSet; + + PropertyBagHelper m_aPropertyBagHelper; + ::dbtools::WarningsContainer m_aWarnings; + OPropertyChangeMultiplexer* m_pAggregatePropertyMultiplexer; + // Verwaltung der ControlGruppen + OGroupManager* m_pGroupManager; + ::dbtools::ParameterManager m_aParameterManager; + ::dbtools::FilterManager m_aFilterManager; + Timer* m_pLoadTimer; + + OFormSubmitResetThread* m_pThread; + ::rtl::OUString m_sCurrentErrorContext; + // will be used as additional context information + // when an exception is catched and forwarded to the listeners + + INT32 m_nResetsPending; +// <overwritten_properties> + sal_Int32 m_nPrivileges; + sal_Bool m_bInsertOnly; +// </overwritten_properties> + +// <properties> + ::com::sun::star::uno::Any m_aControlBorderColorFocus; + ::com::sun::star::uno::Any m_aControlBorderColorMouse; + ::com::sun::star::uno::Any m_aControlBorderColorInvalid; + ::com::sun::star::uno::Any m_aDynamicControlBorder; + ::rtl::OUString m_sName; + ::rtl::OUString m_aTargetURL; + ::rtl::OUString m_aTargetFrame; + ::com::sun::star::form::FormSubmitMethod m_eSubmitMethod; + ::com::sun::star::form::FormSubmitEncoding m_eSubmitEncoding; + ::com::sun::star::form::NavigationBarMode m_eNavigation; + sal_Bool m_bAllowInsert : 1; + sal_Bool m_bAllowUpdate : 1; + sal_Bool m_bAllowDelete : 1; +// </properties> + sal_Bool m_bLoaded : 1; + sal_Bool m_bSubForm : 1; + sal_Bool m_bForwardingConnection : 1; // sal_True if we're setting the ActiveConnection on the aggregate + sal_Bool m_bSharingConnection : 1; // sal_True if the connection we're using is shared with out parent + +public: + ODatabaseForm(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + ODatabaseForm( const ODatabaseForm& _cloneSource ); + ~ODatabaseForm(); + + // UNO binding + DECLARE_UNO3_AGG_DEFAULTS(ODatabaseForm, OFormComponents); + 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< ::com::sun::star::uno::Type> SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XComponent + virtual void SAL_CALL disposing(); + + // property handling + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + 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 ); + + ::com::sun::star::uno::Any SAL_CALL getFastPropertyValue( sal_Int32 nHandle ) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + void fire( sal_Int32 * pnHandles, const ::com::sun::star::uno::Any * pNewValues, const ::com::sun::star::uno::Any * pOldValues, sal_Int32 nCount, sal_Bool bVetoable ); + + // 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(); + + // 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; + + // com::sun::star::sdbc::XSQLErrorBroadcaster + virtual void SAL_CALL addSQLErrorListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLErrorListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSQLErrorListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLErrorListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::form::XForm + // nothing to implement + + // com::sun::star::form::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>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::form::XSubmit + virtual void SAL_CALL submit(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& aControl, const ::com::sun::star::awt::MouseEvent& aMouseEvt) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addSubmitListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XSubmitListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSubmitListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XSubmitListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::container::XChild + virtual InterfaceRef SAL_CALL getParent() throw ( ::com::sun::star::uno::RuntimeException) { return OFormComponents::getParent(); } + virtual void SAL_CALL setParent(const InterfaceRef& Parent) throw ( :: com::sun::star::lang::NoSupportException , ::com::sun::star::uno::RuntimeException); + + // com::sun::star::container::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); + + // com::sun::star::awt::XTabControllerModel + virtual sal_Bool SAL_CALL getGroupControl() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setGroupControl(sal_Bool /*_bGroupControl*/) throw(::com::sun::star::uno::RuntimeException) { } + virtual void SAL_CALL setControlModels(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& _rControls) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > SAL_CALL getControlModels() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setGroup(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& _rGroup, const ::rtl::OUString& _rGroupName) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getGroupCount() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL getGroup(sal_Int32 _nGroup, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& _rxGroup, ::rtl::OUString& _rName) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL getGroupByName(const ::rtl::OUString& _rName, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& _rxGroup) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::form::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); + + // com::sun::star::form::XLoadable + virtual void SAL_CALL load() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL unload() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reload() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLoaded() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addLoadListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XLoadListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeLoadListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XLoadListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XRowSetListener + virtual void SAL_CALL cursorMoved(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rowChanged(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rowSetChanged(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdb::XRowSetApproveListener + virtual sal_Bool SAL_CALL approveCursorMove(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL approveRowChange(const ::com::sun::star::sdb::RowChangeEvent& event) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL approveRowSetChange(const ::com::sun::star::lang::EventObject& event) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdb::XRowSetApproveBroadcaster + virtual void SAL_CALL addRowSetApproveListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetApproveListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetApproveListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetApproveListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun:star::form::XDatabaseParameterBroadcaster2 + virtual void SAL_CALL addDatabaseParameterListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeDatabaseParameterListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun:star::form::XDatabaseParameterBroadcaster + virtual void SAL_CALL addParameterListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeParameterListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XDatabaseParameterListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRowSetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdb::XCompletedExecution + virtual void SAL_CALL executeWithCompletion( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& handler ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute(sal_Int32 row) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative(sal_Int32 rows) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual InterfaceRef SAL_CALL getStatement() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& rows) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XServiceInfo + virtual sal_Bool SAL_CALL supportsService(const ::rtl::OUString& ServiceName) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getCurrentServiceNames_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getCompatibleServiceNames_Static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + // com::sun::star::io::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); + + // com::sun::star::sdbc::XSQLErrorListener + virtual void SAL_CALL errorOccured(const ::com::sun::star::sdb::SQLErrorEvent& aEvent) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XParameters + virtual void SAL_CALL setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBoolean(sal_Int32 parameterIndex, sal_Bool x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setByte(sal_Int32 parameterIndex, sal_Int8 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setShort(sal_Int32 parameterIndex, sal_Int16 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setInt(sal_Int32 parameterIndex, sal_Int32 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLong(sal_Int32 parameterIndex, sal_Int64 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFloat(sal_Int32 parameterIndex, float x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDouble(sal_Int32 parameterIndex, double x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setString(sal_Int32 parameterIndex, const ::rtl::OUString& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBytes(sal_Int32 parameterIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDate(sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTime(sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTimestamp(sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBinaryStream(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCharacterStream(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObject(sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectWithInfo(sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRef(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBlob(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setClob(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setArray(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearParameters() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException); + + // 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); + using OPropertySetAggregationHelper::setPropertyValues; + + // XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException); + + inline void submitNBC( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt ); + +protected: + // OPropertySetAggregationHelper overridables + virtual void SAL_CALL forwardingPropertyValue( sal_Int32 _nHandle ); + virtual void SAL_CALL forwardedPropertyValue( sal_Int32 _nHandle, bool _bSuccess ); + + // OInterfaceContainer overridables + virtual void implInserted( const ElementDescription* _pElement ); + virtual void implRemoved(const InterfaceRef& _rxObject); + + // OPropertyChangeListener + virtual void _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& ) throw(::com::sun::star::uno::RuntimeException); + +private: + sal_Bool executeRowSet(::osl::ResettableMutexGuard& _rClearForNotifies, sal_Bool bMoveToFirst = sal_True, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler = ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >()); + bool fillParameters(::osl::ResettableMutexGuard& _rClearForNotifies, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler = ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >()); + void updateParameterInfo(); + bool hasValidParent() const; + + // impl methods + void load_impl(sal_Bool bCausedByParentForm, sal_Bool bMoveToFirst = sal_True, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler = ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >()) + throw(::com::sun::star::uno::RuntimeException); + void reload_impl(sal_Bool bMoveToFirst, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxCompletionHandler = ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >()) + throw(::com::sun::star::uno::RuntimeException); + void submit_impl(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt, bool _bAproveByListeners); + void reset_impl(bool _bAproveByListeners); + + sal_Bool implEnsureConnection(); + + // connection sharing + + /// checks if we can re-use (aka share) the connection of the given parent + sal_Bool canShareConnection( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxParentProps ); + + /// starts sharing the connection with the parent + void doShareConnection( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxParentProps ); + + /// stops sharing the connection with the parent + void stopSharingConnection( ); + + /// called when the connection which we share with our parent is beeing disposed + void disposingSharedConnection( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConn ); + + /// checks if we currently share our connection with our parent + sal_Bool isSharingConnection( ) const { return m_bSharingConnection; } + + /** calls our row set approval listeners + + @param _rEvent + the event to notify + @param _bAllowSQLException + <TRUE/> if SQLExceptions are allowed to leave the method + @param _rGuard + the guard to be cleared before actually calling into the listeners, but after making + a copy of the listeners array to operate on. + @return + <TRUE/> if and only if the execution has been approved + */ + bool impl_approveRowChange_throw( + const ::com::sun::star::lang::EventObject& _rEvent, + const bool _bAllowSQLException, + ::osl::ClearableMutexGuard& _rGuard + ); + + /// invalidate all our parameter-related stuff + void invlidateParameters(); + + void saveInsertOnlyState( ); + void restoreInsertOnlyState( ); + + // error handling + void onError(const ::com::sun::star::sdb::SQLErrorEvent& _rEvent); + void onError(const ::com::sun::star::sdbc::SQLException&, const ::rtl::OUString& _rContextDescription); + + // html tools + ::rtl::OUString GetDataEncoded(bool _bURLEncoded,const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + ::rtl::OUString GetDataURLEncoded(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + ::rtl::OUString GetDataTextEncoded(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + ::com::sun::star::uno::Sequence<sal_Int8> GetDataMultiPartEncoded(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt, + ::rtl::OUString& rContentType); + + void AppendComponent(HtmlSuccessfulObjList& rList, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& xComponentSet, const ::rtl::OUString& rNamePrefix, + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + + void FillSuccessfulList(HtmlSuccessfulObjList& rList, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt); + + void InsertTextPart(INetMIMEMessage& rParent, const ::rtl::OUString& rName, const ::rtl::OUString& rData); + sal_Bool InsertFilePart(INetMIMEMessage& rParent, const ::rtl::OUString& rName, const ::rtl::OUString& rFileName); + void Encode(::rtl::OUString& rString) const; + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > getConnection(); + + void impl_createLoadTimer(); + + void impl_construct(); + + DECL_LINK( OnTimeout, void* ); +protected: + using OPropertySetHelper::getPropertyValues; +}; + +inline void ODatabaseForm::submitNBC(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt) +{ + submit_impl(Control, MouseEvt, sal_False); +} + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_DATABASEFORM_HXX_ + + diff --git a/forms/source/component/Date.cxx b/forms/source/component/Date.cxx new file mode 100644 index 000000000000..1e04a63bfb0b --- /dev/null +++ b/forms/source/component/Date.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Date.hxx" +#include <tools/debug.hxx> +#include <tools/date.hxx> +#include <connectivity/dbconversion.hxx> +#include <com/sun/star/sdbc/DataType.hpp> + +using namespace dbtools; + +//......................................................................... +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; + +//------------------------------------------------------------------ +ODateControl::ODateControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_DATEFIELD) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL ODateControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new ODateControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> ODateControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL ODateControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_DATEFIELD; + return aSupported; +} + +/*************************************************************************/ +//------------------------------------------------------------------ +InterfaceRef SAL_CALL ODateModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new ODateModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> ODateModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + +//------------------------------------------------------------------ +DBG_NAME( ODateModel ) +//------------------------------------------------------------------ +ODateModel::ODateModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_DATEFIELD, FRM_SUN_CONTROL_DATEFIELD, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OLimitedFormats( _rxFactory, FormComponentType::DATEFIELD ) +{ + DBG_CTOR( ODateModel, NULL ); + + m_nClassId = FormComponentType::DATEFIELD; + initValueProperty( PROPERTY_DATE, PROPERTY_ID_DATE ); + + setAggregateSet(m_xAggregateFastSet, getOriginalHandle(PROPERTY_ID_DATEFORMAT)); + + osl_incrementInterlockedCount( &m_refCount ); + try + { + if ( m_xAggregateSet.is() ) + m_xAggregateSet->setPropertyValue( PROPERTY_DATEMIN, makeAny( (sal_Int32)( ::Date( 1, 1, 1800 ).GetDate() ) ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ODateModel::ODateModel: caught an exception!" ); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//------------------------------------------------------------------------------ +ODateModel::ODateModel( const ODateModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) + ,OLimitedFormats( _rxFactory, FormComponentType::DATEFIELD ) +{ + DBG_CTOR( ODateModel, NULL ); + + setAggregateSet( m_xAggregateFastSet, getOriginalHandle( PROPERTY_ID_DATEFORMAT ) ); +} + +//------------------------------------------------------------------------------ +ODateModel::~ODateModel( ) +{ + setAggregateSet(Reference< XFastPropertySet >(), -1); + DBG_DTOR( ODateModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( ODateModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL ODateModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_DATEFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_DATEFIELD; + *pStoreTo++ = BINDABLE_DATABASE_DATE_FIELD; + + return aSupported; +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODateModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_DATEFIELD; // old (non-sun) name for compatibility ! +} + +// XPropertySet +//------------------------------------------------------------------------------ +void ODateModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 4, OEditBaseModel ) + DECL_PROP3(DEFAULT_DATE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP1(FORMATKEY, sal_Int32, TRANSIENT); + DECL_IFACE_PROP2(FORMATSSUPPLIER, XNumberFormatsSupplier, READONLY, TRANSIENT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODateModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle ) const +{ + switch (_nHandle) + { + case PROPERTY_ID_FORMATKEY: + getFormatKeyPropertyValue(_rValue); + break; + case PROPERTY_ID_FORMATSSUPPLIER: + _rValue <<= getFormatsSupplier(); + break; + default: + OEditBaseModel::getFastPropertyValue(_rValue, _nHandle); + break; + } +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL ODateModel::convertFastPropertyValue(Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue ) throw(IllegalArgumentException) +{ + if (PROPERTY_ID_FORMATKEY == _nHandle) + return convertFormatKeyPropertyValue(_rConvertedValue, _rOldValue, _rValue); + else + return OEditBaseModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODateModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw ( ::com::sun::star::uno::Exception) +{ + if (PROPERTY_ID_FORMATKEY == _nHandle) + setFormatKeyPropertyValue(_rValue); + else + OEditBaseModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); +} + +// XLoadListener +//------------------------------------------------------------------------------ +void ODateModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + OBoundControlModel::onConnectedDbColumn( _rxForm ); + Reference<XPropertySet> xField = getField(); + if (xField.is()) + { + m_bDateTimeField = sal_False; + try + { + sal_Int32 nFieldType = 0; + xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nFieldType; + m_bDateTimeField = (nFieldType == DataType::TIMESTAMP); + } + catch(Exception&) + { + } + } +} + +//------------------------------------------------------------------------------ +sal_Bool ODateModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( !compare( aControlValue, m_aSaveValue ) ) + { + if ( !aControlValue.hasValue() ) + m_xColumnUpdate->updateNull(); + else + { + try + { + util::Date aDate; + if ( !( aControlValue >>= aDate ) ) + { + sal_Int32 nAsInt(0); + aControlValue >>= nAsInt; + aDate = DBTypeConversion::toDate(nAsInt); + } + + if ( !m_bDateTimeField ) + m_xColumnUpdate->updateDate( aDate ); + else + { + util::DateTime aDateTime = m_xColumn->getTimestamp(); + aDateTime.Day = aDate.Day; + aDateTime.Month = aDate.Month; + aDateTime.Year = aDate.Year; + m_xColumnUpdate->updateTimestamp( aDateTime ); + } + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +void ODateModel::impl_translateControlValueToUNODate( Any& _rUNOValue ) const +{ + _rUNOValue = getControlValue(); + if ( _rUNOValue.hasValue() ) + { + sal_Int32 nDate = 0; + OSL_VERIFY( _rUNOValue >>= nDate ); + _rUNOValue <<= DBTypeConversion::toDate( nDate ); + } +} + +//------------------------------------------------------------------------------ +Any ODateModel::translateControlValueToExternalValue( ) const +{ + Any aExternalValue; + impl_translateControlValueToUNODate( aExternalValue ); + return aExternalValue; +} + +//------------------------------------------------------------------------------ +Any ODateModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + Any aControlValue; + if ( _rExternalValue.hasValue() ) + { + util::Date aDate; + OSL_VERIFY( _rExternalValue >>= aDate ); + aControlValue <<= DBTypeConversion::toINT32( aDate ); + } + return aControlValue; +} + +//------------------------------------------------------------------------------ +Any ODateModel::translateControlValueToValidatableValue( ) const +{ + Any aValidatableValue; + impl_translateControlValueToUNODate( aValidatableValue ); + return aValidatableValue; +} + +//------------------------------------------------------------------------------ +Any ODateModel::translateDbColumnToControlValue() +{ + util::Date aDate = m_xColumn->getDate(); + if (m_xColumn->wasNull()) + m_aSaveValue.clear(); + else + // the aggregated set expects an Int32 as value ... + m_aSaveValue <<= DBTypeConversion::toINT32(aDate); + + return m_aSaveValue; +} + +//------------------------------------------------------------------------------ +Any ODateModel::getDefaultForReset() const +{ + return m_aDefault; +} + +//------------------------------------------------------------------------------ +void ODateModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//------------------------------------------------------------------------------ +Sequence< Type > ODateModel::getSupportedBindingTypes() +{ + return Sequence< Type >( &::getCppuType( static_cast< util::Date* >( NULL ) ), 1 ); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Date.hxx b/forms/source/component/Date.hxx new file mode 100644 index 000000000000..8ff6d1433508 --- /dev/null +++ b/forms/source/component/Date.hxx @@ -0,0 +1,133 @@ +/************************************************************************* + * + * 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_DATE_HXX_ +#define _FORMS_DATE_HXX_ + +#include "EditBase.hxx" +#include "limitedformats.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= ODateModel +//================================================================== +class ODateModel + :public OEditBaseModel + ,public OLimitedFormats +{ + ::com::sun::star::uno::Any m_aSaveValue; + sal_Bool m_bDateTimeField; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( ODateModel ); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::beans::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); + + // XServiceInfo + IMPLEMENTATION_NAME(ODateModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // XPropertySet + using OEditBaseModel::getFastPropertyValue; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + + virtual ::com::sun::star::uno::Any + translateControlValueToValidatableValue( ) const; + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual void resetNoBroadcast(); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + +protected: + DECLARE_XCLONEABLE(); + +private: + /** translates the control value (the VCL-internal integer representation of a date) into + a UNO-Date. + */ + void impl_translateControlValueToUNODate( + ::com::sun::star::uno::Any& _rUNOValue ) const; +}; + +//================================================================== +//= ODateControl +//================================================================== +class ODateControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + ODateControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + DECLARE_UNO3_AGG_DEFAULTS(ODateControl, OBoundControl); + +// ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(ODateControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_DATE_HXX_ + diff --git a/forms/source/component/Edit.cxx b/forms/source/component/Edit.cxx new file mode 100644 index 000000000000..3a36078a7fed --- /dev/null +++ b/forms/source/component/Edit.cxx @@ -0,0 +1,766 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "Edit.hxx" + +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/form/XSubmit.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> + +#include <vcl/svapp.hxx> +#include <vcl/wintypes.hxx> + +#include <connectivity/dbtools.hxx> +#include <connectivity/formattedcolumnvalue.hxx> +#include <connectivity/dbconversion.hxx> + +#include <tools/diagnose_ex.h> +#include <tools/debug.hxx> + +#include <comphelper/container.hxx> +#include <comphelper/numbers.hxx> + +using namespace dbtools; + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OEditControl_CreateInstance(const Reference< XMultiServiceFactory > & _rxFactory) +{ + return *(new OEditControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OEditControl::_getTypes() +{ + static Sequence<Type> aTypes; + if (!aTypes.getLength()) + { + // my two base classes + aTypes = concatSequences(OBoundControl::_getTypes(), OEditControl_BASE::getTypes()); + } + return aTypes; +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OEditControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OBoundControl::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = OEditControl_BASE::queryInterface(_rType); + + return aReturn; +} + +DBG_NAME(OEditControl); +//------------------------------------------------------------------------------ +OEditControl::OEditControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl( _rxFactory, FRM_SUN_CONTROL_RICHTEXTCONTROL ) + ,m_aChangeListeners(m_aMutex) + ,m_nKeyEvent( 0 ) +{ + DBG_CTOR(OEditControl,NULL); + + increment(m_refCount); + { + Reference<XWindow> xComp; + if (query_aggregation(m_xAggregate, xComp)) + { + xComp->addFocusListener(this); + xComp->addKeyListener(this); + } + } + decrement(m_refCount); +} + +//------------------------------------------------------------------------------ +OEditControl::~OEditControl() +{ + if( m_nKeyEvent ) + Application::RemoveUserEvent( m_nKeyEvent ); + + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OEditControl,NULL); +} + +// XChangeBroadcaster +//------------------------------------------------------------------------------ +void OEditControl::addChangeListener(const Reference<XChangeListener>& l) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aChangeListeners.addInterface( l ); +} + +//------------------------------------------------------------------------------ +void OEditControl::removeChangeListener(const Reference<XChangeListener>& l) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aChangeListeners.removeInterface( l ); +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OEditControl::disposing() +{ + OBoundControl::disposing(); + + EventObject aEvt(static_cast<XWeak*>(this)); + m_aChangeListeners.disposeAndClear(aEvt); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OEditControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_TEXTFIELD; + return aSupported; +} + +// XEventListener +//------------------------------------------------------------------------------ +void OEditControl::disposing(const EventObject& Source) throw( RuntimeException ) +{ + OBoundControl::disposing(Source); +} + +// XFocusListener +//------------------------------------------------------------------------------ +void OEditControl::focusGained( const FocusEvent& /*e*/ ) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (xSet.is()) + xSet->getPropertyValue( PROPERTY_TEXT ) >>= m_aHtmlChangeValue; +} + +//------------------------------------------------------------------------------ +void OEditControl::focusLost( const FocusEvent& /*e*/ ) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (xSet.is()) + { + ::rtl::OUString sNewHtmlChangeValue; + xSet->getPropertyValue( PROPERTY_TEXT ) >>= sNewHtmlChangeValue; + if( sNewHtmlChangeValue != m_aHtmlChangeValue ) + { + EventObject aEvt( *this ); + m_aChangeListeners.notifyEach( &XChangeListener::changed, aEvt ); + } + } +} + +// XKeyListener +//------------------------------------------------------------------------------ +void OEditControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException) +{ + if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 ) + return; + + // Steht das Control in einem Formular mit einer Submit-URL? + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if( !xSet.is() ) + return; + + // nicht fuer multiline edits + Any aTmp( xSet->getPropertyValue(PROPERTY_MULTILINE)); + if ((aTmp.getValueType().equals(::getBooleanCppuType())) && getBOOL(aTmp)) + return; + + Reference<XFormComponent> xFComp(xSet, UNO_QUERY); + InterfaceRef xParent = xFComp->getParent(); + if( !xParent.is() ) + return; + + Reference<XPropertySet> xFormSet(xParent, UNO_QUERY); + if( !xFormSet.is() ) + return; + + aTmp = xFormSet->getPropertyValue( PROPERTY_TARGET_URL ); + if (!aTmp.getValueType().equals(::getCppuType((const ::rtl::OUString*)NULL)) || + !getString(aTmp).getLength() ) + return; + + Reference<XIndexAccess> xElements(xParent, UNO_QUERY); + sal_Int32 nCount = xElements->getCount(); + if( nCount > 1 ) + { + Reference<XPropertySet> xFCSet; + for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ ) + { + // Any aElement(xElements->getByIndex(nIndex)); + xElements->getByIndex(nIndex) >>= xFCSet; + OSL_ENSURE(xFCSet.is(),"OEditControl::keyPressed: No XPropertySet!"); + + if (hasProperty(PROPERTY_CLASSID, xFCSet) && + getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD) + { + // Noch ein weiteres Edit gefunden ==> dann nicht submitten + if (xFCSet != xSet) + return; + } + } + } + + // Da wir noch im Haender stehen, submit asynchron ausloesen + if( m_nKeyEvent ) + Application::RemoveUserEvent( m_nKeyEvent ); + m_nKeyEvent = Application::PostUserEvent( LINK(this, OEditControl,OnKeyPressed) ); +} + +//------------------------------------------------------------------------------ +void OEditControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +IMPL_LINK(OEditControl, OnKeyPressed, void*, /*EMPTYARG*/) +{ + m_nKeyEvent = 0; + + Reference<XFormComponent> xFComp(getModel(), UNO_QUERY); + InterfaceRef xParent = xFComp->getParent(); + Reference<XSubmit> xSubmit(xParent, UNO_QUERY); + if (xSubmit.is()) + xSubmit->submit( Reference<XControl>(), ::com::sun::star::awt::MouseEvent() ); + return 0L; +} + +//------------------------------------------------------------------ +void SAL_CALL OEditControl::createPeer( const Reference< XToolkit>& _rxToolkit, const Reference< XWindowPeer>& _rxParent ) throw ( RuntimeException ) +{ + OBoundControl::createPeer(_rxToolkit, _rxParent); +} + +/*************************************************************************/ +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OEditModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OEditModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OEditModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + + +DBG_NAME(OEditModel); +//------------------------------------------------------------------ +OEditModel::OEditModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, FRM_SUN_COMPONENT_RICHTEXTCONTROL, FRM_SUN_CONTROL_TEXTFIELD, sal_True, sal_True ) + ,m_bMaxTextLenModified(sal_False) + ,m_bWritingFormattedFake(sal_False) +{ + DBG_CTOR(OEditModel,NULL); + + m_nClassId = FormComponentType::TEXTFIELD; + initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT ); +} + +//------------------------------------------------------------------ +OEditModel::OEditModel( const OEditModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) + ,m_bMaxTextLenModified(sal_False) + ,m_bWritingFormattedFake(sal_False) +{ + DBG_CTOR( OEditModel, NULL ); + + // Note that most of the properties are not clone from the original object: + // Things as the format key, it's type, and such, depend on the field being part of a loaded form + // (they're initialized in onConnectedDbColumn). Even if the original object _is_ part of such a form, we ourself + // certainly aren't, so these members are defaulted. If we're inserted into a form which is already loaded, + // they will be set to new values, anyway .... +} + +//------------------------------------------------------------------ +OEditModel::~OEditModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OEditModel,NULL); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OEditModel ) + +//------------------------------------------------------------------------------ +void OEditModel::disposing() +{ + OEditBaseModel::disposing(); + m_pValueFormatter.reset(); +} + +// XPersistObject +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OEditModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_EDIT; // old (non-sun) name for compatibility ! +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OEditModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_TEXTFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_TEXTFIELD; + *pStoreTo++ = BINDABLE_DATABASE_TEXT_FIELD; + + return aSupported; +} + +// XPropertySet +void SAL_CALL OEditModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const +{ + if ( PROPERTY_ID_PERSISTENCE_MAXTEXTLENGTH == nHandle ) + { + if ( m_bMaxTextLenModified ) + rValue <<= sal_Int16(0); + else if ( m_xAggregateSet.is() ) + rValue = m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN); + } + else + { + OEditBaseModel::getFastPropertyValue(rValue, nHandle ); + } +} + +//------------------------------------------------------------------------------ +void OEditModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 5, OEditBaseModel ) + DECL_PROP2(PERSISTENCE_MAXTEXTLENGTH,sal_Int16, READONLY, TRANSIENT); + DECL_PROP2(DEFAULT_TEXT, ::rtl::OUString, BOUND, MAYBEDEFAULT); + DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_BOOL_PROP2(FILTERPROPOSAL, BOUND, MAYBEDEFAULT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void OEditModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OEditBaseModel::describeAggregateProperties( _rAggregateProps ); + + // our aggregate is a rich text model, which also derives from OControlModel, as + // do we, so we need to remove some duplicate properties + RemoveProperty( _rAggregateProps, PROPERTY_TABINDEX ); + RemoveProperty( _rAggregateProps, PROPERTY_CLASSID ); + RemoveProperty( _rAggregateProps, PROPERTY_NAME ); + RemoveProperty( _rAggregateProps, PROPERTY_TAG ); + RemoveProperty( _rAggregateProps, PROPERTY_NATIVE_LOOK ); + +} + +//------------------------------------------------------------------------------ +bool OEditModel::implActsAsRichText( ) const +{ + sal_Bool bActAsRichText = sal_False; + if ( m_xAggregateSet.is() ) + { + OSL_VERIFY( m_xAggregateSet->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bActAsRichText ); + } + return bActAsRichText; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OEditModel::reset( ) throw(RuntimeException) +{ + // no reset if we currently act as rich text control + if ( implActsAsRichText() ) + return; + + OEditBaseModel::reset(); +} + +//------------------------------------------------------------------------------ +namespace +{ + void lcl_transferProperties( const Reference< XPropertySet >& _rxSource, const Reference< XPropertySet >& _rxDest ) + { + try + { + Reference< XPropertySetInfo > xSourceInfo; + if ( _rxSource.is() ) + xSourceInfo = _rxSource->getPropertySetInfo(); + + Reference< XPropertySetInfo > xDestInfo; + if ( _rxDest.is() ) + xDestInfo = _rxDest->getPropertySetInfo(); + + if ( !xSourceInfo.is() || !xDestInfo.is() ) + { + OSL_ENSURE( sal_False, "lcl_transferProperties: invalid property set(s)!" ); + return; + } + + Sequence< Property > aSourceProps( xSourceInfo->getProperties() ); + const Property* pSourceProps = aSourceProps.getConstArray(); + const Property* pSourcePropsEnd = aSourceProps.getConstArray() + aSourceProps.getLength(); + while ( pSourceProps != pSourcePropsEnd ) + { + if ( !xDestInfo->hasPropertyByName( pSourceProps->Name ) ) + { + ++pSourceProps; + continue; + } + + Property aDestProp( xDestInfo->getPropertyByName( pSourceProps->Name ) ); + if ( 0 != ( aDestProp.Attributes & PropertyAttribute::READONLY ) ) + { + ++pSourceProps; + continue; + } + + try + { + _rxDest->setPropertyValue( pSourceProps->Name, _rxSource->getPropertyValue( pSourceProps->Name ) ); + } + catch( IllegalArgumentException e ) + { +#if OSL_DEBUG_LEVEL > 0 + ::rtl::OString sMessage( "could not transfer the property named '" ); + sMessage += ::rtl::OString( pSourceProps->Name.getStr(), pSourceProps->Name.getLength(), RTL_TEXTENCODING_ASCII_US ); + sMessage += ::rtl::OString( "'." ); + if ( e.Message.getLength() ) + { + sMessage += ::rtl::OString( "\n\nMessage:\n" ); + sMessage += ::rtl::OString( e.Message.getStr(), e.Message.getLength(), RTL_TEXTENCODING_ASCII_US ); + } + OSL_ENSURE( sal_False, sMessage.getStr() ); +#endif + } + + ++pSourceProps; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +//------------------------------------------------------------------------------ +void OEditModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const +{ + // we need to fake the writing of our aggregate. Since #i24387#, we have another aggregate, + // but for compatibility, we need to use an "old" aggregate for writing and reading + + Reference< XPropertySet > xFakedAggregate( + getContext().createComponent( (rtl::OUString)VCL_CONTROLMODEL_EDIT ), + UNO_QUERY + ); + OSL_ENSURE( xFakedAggregate.is(), "OEditModel::writeAggregate: could not create an old EditControlModel!" ); + if ( !xFakedAggregate.is() ) + return; + + lcl_transferProperties( m_xAggregateSet, xFakedAggregate ); + + Reference< XPersistObject > xFakedPersist( xFakedAggregate, UNO_QUERY ); + OSL_ENSURE( xFakedPersist.is(), "OEditModel::writeAggregate: no XPersistObject!" ); + if ( xFakedPersist.is() ) + xFakedPersist->write( _rxOutStream ); +} + +//------------------------------------------------------------------------------ +void OEditModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream ) +{ + // we need to fake the reading of our aggregate. Since #i24387#, we have another aggregate, + // but for compatibility, we need to use an "old" aggregate for writing and reading + + Reference< XPropertySet > xFakedAggregate( + getContext().createComponent( (rtl::OUString)VCL_CONTROLMODEL_EDIT ), + UNO_QUERY + ); + Reference< XPersistObject > xFakedPersist( xFakedAggregate, UNO_QUERY ); + OSL_ENSURE( xFakedPersist.is(), "OEditModel::readAggregate: no XPersistObject, or no faked aggregate at all!" ); + if ( xFakedPersist.is() ) + { + xFakedPersist->read( _rxInStream ); + lcl_transferProperties( xFakedAggregate, m_xAggregateSet ); + } +} + +//------------------------------------------------------------------------------ +void OEditModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + Any aCurrentText; + sal_Int16 nOldTextLen = 0; + // bin ich gerade loaded und habe dazu zeitweilig die MaxTextLen umgesetzt ? + if ( m_bMaxTextLenModified ) + { // -> fuer die Dauer des Speicherns meinem aggregierten Model die alte TextLen einreden + + // before doing this we have to save the current text value of the aggregate, as this may be affected by resetting the text len + // FS - 08.12.99 - 70606 + aCurrentText = m_xAggregateSet->getPropertyValue(PROPERTY_TEXT); + + m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN) >>= nOldTextLen; + m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, makeAny((sal_Int16)0)); + } + + OEditBaseModel::write(_rxOutStream); + + if ( m_bMaxTextLenModified ) + { // wieder zuruecksetzen + m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, makeAny(nOldTextLen)); + // and reset the text + // First we set it to an empty string : Without this the second setPropertyValue would not do anything as it thinks + // we aren't changing the prop (it didn't notify the - implicite - change of the text prop while setting the max text len) + // This seems to be a bug with in toolkit's EditControl-implementation. + m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, makeAny(::rtl::OUString())); + m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, aCurrentText); + } +} + +//------------------------------------------------------------------------------ +void OEditModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OEditBaseModel::read(_rxInStream); + + // Some versions (5.1 'til about 552) wrote a wrong DefaultControl-property value which is unknown + // to older versions (5.0). + // correct this ... + if (m_xAggregateSet.is()) + { + Any aDefaultControl = m_xAggregateSet->getPropertyValue(PROPERTY_DEFAULTCONTROL); + if ( (aDefaultControl.getValueType().getTypeClass() == TypeClass_STRING) + && (getString(aDefaultControl).compareTo(STARDIV_ONE_FORM_CONTROL_TEXTFIELD) == COMPARE_EQUAL) + ) + { + m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( (::rtl::OUString)STARDIV_ONE_FORM_CONTROL_EDIT ) ); + // Older as well as current versions should understand this : the former knew only the STARDIV_ONE_FORM_CONTROL_EDIT, + // the latter are registered for both STARDIV_ONE_FORM_CONTROL_EDIT and STARDIV_ONE_FORM_CONTROL_TEXTFIELD. + } + } +} + +//------------------------------------------------------------------------------ +sal_uInt16 OEditModel::getPersistenceFlags() const +{ + sal_uInt16 nFlags = OEditBaseModel::getPersistenceFlags(); + + if (m_bWritingFormattedFake) + nFlags |= PF_FAKE_FORMATTED_FIELD; + + return nFlags; +} + +//------------------------------------------------------------------------------ +void OEditModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + Reference< XPropertySet > xField = getField(); + if ( xField.is() ) + { + m_pValueFormatter.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) ); + + if ( m_pValueFormatter->getKeyType() != NumberFormat::SCIENTIFIC ) + { + m_bMaxTextLenModified = getINT16(m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN)) != 0; + if ( !m_bMaxTextLenModified ) + { + sal_Int32 nFieldLen = 0; + xField->getPropertyValue(::rtl::OUString::createFromAscii("Precision")) >>= nFieldLen; + + if (nFieldLen && nFieldLen <= USHRT_MAX) + { + Any aVal; + aVal <<= (sal_Int16)nFieldLen; + m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, aVal); + + m_bMaxTextLenModified = sal_True; + } + } + else + m_bMaxTextLenModified = sal_False; // to get sure that the text len won't be set in unloaded + } + } +} + +//------------------------------------------------------------------------------ +void OEditModel::onDisconnectedDbColumn() +{ + OEditBaseModel::onDisconnectedDbColumn(); + + m_pValueFormatter.reset(); + + if ( hasField() && m_bMaxTextLenModified ) + { + Any aVal; + aVal <<= (sal_Int16)0; // nur wenn es 0 war, habe ich es in onConnectedDbColumn umgesetzt + m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, aVal); + m_bMaxTextLenModified = sal_False; + } +} + +//------------------------------------------------------------------------------ +sal_Bool OEditModel::approveDbColumnType( sal_Int32 _nColumnType ) +{ + // if we act as rich text curently, we do not allow binding to a database column + if ( implActsAsRichText() ) + return sal_False; + + return OEditBaseModel::approveDbColumnType( _nColumnType ); +} + +//------------------------------------------------------------------------------ +void OEditModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aLastKnownValue.clear(); +} + +//------------------------------------------------------------------------------ +sal_Bool OEditModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + + if ( aNewValue != m_aLastKnownValue ) + { + ::rtl::OUString sNewValue; + aNewValue >>= sNewValue; + + if ( !aNewValue.hasValue() + || ( !sNewValue.getLength() // an empty string + && m_bEmptyIsNull // which should be interpreted as NULL + ) + ) + { + m_xColumnUpdate->updateNull(); + } + else + { + OSL_PRECOND( m_pValueFormatter.get(), "OEditModel::commitControlValueToDbColumn: no value formatter!" ); + try + { + if ( m_pValueFormatter.get() ) + { + if ( !m_pValueFormatter->setFormattedValue( sNewValue ) ) + return sal_False; + } + else + m_xColumnUpdate->updateString( sNewValue ); + } + catch ( const Exception& ) + { + return sal_False; + } + } + m_aLastKnownValue = aNewValue; + } + + return sal_True; +} + +//------------------------------------------------------------------------------ +Any OEditModel::translateDbColumnToControlValue() +{ + OSL_PRECOND( m_pValueFormatter.get(), "OEditModel::translateDbColumnToControlValue: no value formatter!" ); + if ( m_pValueFormatter.get() ) + { + ::rtl::OUString sValue( m_pValueFormatter->getFormattedValue() ); + if ( !sValue.getLength() + && m_pValueFormatter->getColumn().is() + && m_pValueFormatter->getColumn()->wasNull() + ) + { + m_aLastKnownValue.clear(); + } + else + { + // #i2817# OJ + sal_uInt16 nMaxTextLen = getINT16( m_xAggregateSet->getPropertyValue( PROPERTY_MAXTEXTLEN ) ); + if ( nMaxTextLen && sValue.getLength() > nMaxTextLen ) + { + sal_Int32 nDiff = sValue.getLength() - nMaxTextLen; + sValue = sValue.replaceAt( nMaxTextLen, nDiff, ::rtl::OUString() ); + } + + m_aLastKnownValue <<= sValue; + } + } + else + m_aLastKnownValue.clear(); + + return m_aLastKnownValue.hasValue() ? m_aLastKnownValue : makeAny( ::rtl::OUString() ); + // (m_aLastKnownValue is alllowed to be VOID, the control value isn't) +} + +//------------------------------------------------------------------------------ +Any OEditModel::getDefaultForReset() const +{ + return makeAny( m_aDefaultText ); +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/Edit.hxx b/forms/source/component/Edit.hxx new file mode 100644 index 000000000000..5b4146b82d06 --- /dev/null +++ b/forms/source/component/Edit.hxx @@ -0,0 +1,188 @@ +/************************************************************************* + * + * 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_EDIT_HXX_ +#define _FORMS_EDIT_HXX_ + +#include "EditBase.hxx" + +#include <cppuhelper/implbase3.hxx> + +namespace dbtools { class FormattedColumnValue; } + +//......................................................................... +namespace frm +{ + +//================================================================== +//= OEditModel +//================================================================== +class OEditModel + :public OEditBaseModel +{ + ::com::sun::star::uno::Any m_aLastKnownValue; + ::std::auto_ptr< ::dbtools::FormattedColumnValue > + m_pValueFormatter; + sal_Bool m_bMaxTextLenModified : 1; // set to <TRUE/> when we change the MaxTextLen of the aggregate + + sal_Bool m_bWritingFormattedFake : 1; + // are we writing something which should be interpreted as formatted upon reading? + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + DECLARE_DEFAULT_LEAF_XTOR( OEditModel ); + + void enableFormattedWriteFake() { m_bWritingFormattedFake = sal_True; } + void disableFormattedWriteFake() { m_bWritingFormattedFake = sal_False; } + sal_Bool lastReadWasFormattedFake() const { return (getLastReadVersion() & PF_FAKE_FORMATTED_FIELD) != 0; } + + friend InterfaceRef SAL_CALL OEditModel_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + friend class OFormattedFieldWrapper; + friend class OFormattedModel; // temporary + +public: + virtual void SAL_CALL disposing(); + + // XPropertySet + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + + // XPersistObject + 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); + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // XPropertySet + using OBoundControlModel::getFastPropertyValue; + + // XReset + virtual void SAL_CALL reset( ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OEditModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // XEventListener + using OBoundControlModel::disposing; + +protected: + // OControlModel overridables + 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 ); + + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + virtual sal_Bool approveDbColumnType( sal_Int32 _nColumnType ); + + virtual void resetNoBroadcast(); + +protected: + virtual sal_uInt16 getPersistenceFlags() const; + + DECLARE_XCLONEABLE(); + +private: + bool implActsAsRichText( ) const; +}; + +//================================================================== +//= OEditControl +//================================================================== +typedef ::cppu::ImplHelper3< ::com::sun::star::awt::XFocusListener, + ::com::sun::star::awt::XKeyListener, + ::com::sun::star::form::XChangeBroadcaster > OEditControl_BASE; + +class OEditControl : public OBoundControl + ,public OEditControl_BASE +{ + ::cppu::OInterfaceContainerHelper + m_aChangeListeners; + + ::rtl::OUString m_aHtmlChangeValue; + sal_uInt32 m_nKeyEvent; + +public: + OEditControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + virtual ~OEditControl(); + + DECLARE_UNO3_AGG_DEFAULTS(OEditControl, OBoundControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +// OComponentHelper + virtual void SAL_CALL disposing(); + +// ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OEditControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + +// ::com::sun::star::form::XChangeBroadcaster + virtual void SAL_CALL addChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::awt::XFocusListener + virtual void SAL_CALL focusGained( const ::com::sun::star::awt::FocusEvent& e ) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL focusLost( const ::com::sun::star::awt::FocusEvent& e ) throw ( ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::awt::XKeyListener + virtual void SAL_CALL keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + + // XControl + virtual void SAL_CALL createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit >& _rxToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& _rxParent ) throw ( ::com::sun::star::uno::RuntimeException ); + +private: + DECL_LINK( OnKeyPressed, void* ); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_EDIT_HXX_ + diff --git a/forms/source/component/EditBase.cxx b/forms/source/component/EditBase.cxx new file mode 100644 index 000000000000..b8dcbb336ebb --- /dev/null +++ b/forms/source/component/EditBase.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "EditBase.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/basicio.hxx> +#include <cppuhelper/queryinterface.hxx> +#include "frm_resource.hxx" +#ifndef _FRM_RESOURCE_HRC_ +#include "frm_resource.hrc" +#endif + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +const sal_uInt16 DEFAULT_LONG = 0x0001; +const sal_uInt16 DEFAULT_DOUBLE = 0x0002; +const sal_uInt16 FILTERPROPOSAL = 0x0004; + +DBG_NAME( OEditBaseModel ) +//------------------------------------------------------------------ +OEditBaseModel::OEditBaseModel( const Reference< XMultiServiceFactory >& _rxFactory, const ::rtl::OUString& rUnoControlModelName, + const ::rtl::OUString& rDefault, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation ) + :OBoundControlModel( _rxFactory, rUnoControlModelName, rDefault, sal_True, _bSupportExternalBinding, _bSupportsValidation ) + ,m_nLastReadVersion(0) + ,m_bEmptyIsNull(sal_True) + ,m_bFilterProposal(sal_False) +{ + DBG_CTOR( OEditBaseModel, NULL ); +} + +//------------------------------------------------------------------ +OEditBaseModel::OEditBaseModel( const OEditBaseModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + ,m_nLastReadVersion(0) +{ + DBG_CTOR( OEditBaseModel, NULL ); + + m_bFilterProposal = _pOriginal->m_bFilterProposal; + m_bEmptyIsNull = _pOriginal->m_bEmptyIsNull; + m_aDefault = _pOriginal->m_aDefault; + m_aDefaultText = _pOriginal->m_aDefaultText; +} + +//------------------------------------------------------------------ +OEditBaseModel::~OEditBaseModel( ) +{ + DBG_DTOR( OEditBaseModel, NULL ); +} + +// XPersist +//------------------------------------------------------------------------------ +void OEditBaseModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OBoundControlModel::write(_rxOutStream); + + // Version + sal_uInt16 nVersionId = 0x0005; + DBG_ASSERT((getPersistenceFlags() & ~PF_SPECIAL_FLAGS) == 0, + "OEditBaseModel::write : invalid special version flags !"); + // please don't use other flags, older versions can't interpret them ! + + nVersionId |= getPersistenceFlags(); + _rxOutStream->writeShort(nVersionId); + + // Name + _rxOutStream->writeShort(0); // obsolete + _rxOutStream << m_aDefaultText; + + // Maskierung fuer any + sal_uInt16 nAnyMask = 0; + if (m_aDefault.getValueType().getTypeClass() == TypeClass_LONG) + nAnyMask |= DEFAULT_LONG; + else if (m_aDefault.getValueType().getTypeClass() == TypeClass_DOUBLE) + nAnyMask |= DEFAULT_DOUBLE; + + if (m_bFilterProposal) // da boolean, kein Wert speichern + nAnyMask |= FILTERPROPOSAL; + + _rxOutStream->writeBoolean(m_bEmptyIsNull); + _rxOutStream->writeShort(nAnyMask); + + if ((nAnyMask & DEFAULT_LONG) == DEFAULT_LONG) + _rxOutStream->writeLong(getINT32(m_aDefault)); + else if ((nAnyMask & DEFAULT_DOUBLE) == DEFAULT_DOUBLE) + _rxOutStream->writeDouble(getDouble(m_aDefault)); + + // since version 5 we write the help text + writeHelpTextCompatibly(_rxOutStream); + // (that's potentially bad : at the time I added the above line we had two derived classes : OEditModel and + // OFormattedModel. The first one does not have an own version handling, so it can't write the help text itself, + // the second one does it's own writing (reading) after calling our method, so normally we shouldn't write any + // additional members as this is not compatible to older office versions. + // We decided to place the writing of the help text here as it seems the less worse alternative. There is no delivered + // office version including formatted controls (and thus the OFormattedModel), and the OFormattedModel::read seems + // robust against this change (as it will read a wrong and unknown file version and thus set it's members to defaults). + + if ((nVersionId & PF_HANDLE_COMMON_PROPS) != 0) + writeCommonEditProperties(_rxOutStream); + + // !!! properties common to all OEditBaseModel derived classes should be written in writeCommonEditProperties !!! +} + +//------------------------------------------------------------------------------ +sal_uInt16 OEditBaseModel::getPersistenceFlags() const +{ + return PF_HANDLE_COMMON_PROPS; +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OBoundControlModel::read(_rxInStream); + ::osl::MutexGuard aGuard(m_aMutex); + + // Version eigene Versionsnummer + sal_uInt16 nVersion = _rxInStream->readShort(); + m_nLastReadVersion = nVersion; + + sal_Bool bHandleCommonProps = (nVersion & PF_HANDLE_COMMON_PROPS) != 0; + nVersion = nVersion & ~PF_SPECIAL_FLAGS; + + // obsolete + _rxInStream->readShort(); + + _rxInStream >> m_aDefaultText; + + if (nVersion >= 0x0003) + { + m_bEmptyIsNull = _rxInStream->readBoolean(); + + sal_uInt16 nAnyMask = _rxInStream->readShort(); + if ((nAnyMask & DEFAULT_LONG) == DEFAULT_LONG) + { + sal_Int32 nValue = _rxInStream->readLong(); + m_aDefault <<= (sal_Int32)nValue; + } + else if ((nAnyMask & DEFAULT_DOUBLE) == DEFAULT_DOUBLE) + { + double fValue = _rxInStream->readDouble(); + m_aDefault <<= (double)fValue; + } + + if ((nAnyMask & FILTERPROPOSAL) == FILTERPROPOSAL) + m_bFilterProposal = sal_True; + } + + if (nVersion > 4) + readHelpTextCompatibly(_rxInStream); + + if (bHandleCommonProps) + readCommonEditProperties(_rxInStream); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + // (not if we don't have a control source - the "State" property acts like it is persistent, then) + resetNoBroadcast(); +}; + +//------------------------------------------------------------------------------ +void OEditBaseModel::defaultCommonEditProperties() +{ + OBoundControlModel::defaultCommonProperties(); + // no own common properties at the moment +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::readCommonEditProperties(const Reference<XObjectInputStream>& _rxInStream) +{ + sal_Int32 nLen = _rxInStream->readLong(); + + Reference<XMarkableStream> xMark(_rxInStream, UNO_QUERY); + DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !"); + sal_Int32 nMark = xMark->createMark(); + + // read properties common to all OBoundControlModels + OBoundControlModel::readCommonProperties(_rxInStream); + + // read properties common to all OEditBaseModels + + // skip the remaining bytes + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nLen); + xMark->deleteMark(nMark); +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::writeCommonEditProperties(const Reference<XObjectOutputStream>& _rxOutStream) +{ + Reference<XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + DBG_ASSERT(xMark.is(), "OEditBaseModel::writeCommonProperties : can only work with markable streams !"); + sal_Int32 nMark = xMark->createMark(); + + // a placeholder where we will write the overall length (later in this method) + sal_Int32 nLen = 0; + _rxOutStream->writeLong(nLen); + + // write properties common to all OBoundControlModels + OBoundControlModel::writeCommonProperties(_rxOutStream); + + // write properties common to all OEditBaseModels + + // close the block - write the correct length at the beginning + nLen = xMark->offsetToMark(nMark) - sizeof(nLen); + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_EMPTY_IS_NULL: + rValue <<= (sal_Bool)m_bEmptyIsNull; + break; + case PROPERTY_ID_FILTERPROPOSAL: + rValue <<= (sal_Bool)m_bFilterProposal; + break; + case PROPERTY_ID_DEFAULT_TEXT: + rValue <<= m_aDefaultText; + break; + case PROPERTY_ID_DEFAULT_VALUE: + case PROPERTY_ID_DEFAULT_DATE: + case PROPERTY_ID_DEFAULT_TIME: + rValue = m_aDefault; + break; + default: + OBoundControlModel::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OEditBaseModel::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_EMPTY_IS_NULL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEmptyIsNull); + break; + case PROPERTY_ID_FILTERPROPOSAL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bFilterProposal); + break; + case PROPERTY_ID_DEFAULT_TEXT: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefaultText); + break; + case PROPERTY_ID_DEFAULT_VALUE: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefault, ::getCppuType((const double*)0)); + break; + case PROPERTY_ID_DEFAULT_DATE: + case PROPERTY_ID_DEFAULT_TIME: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefault, ::getCppuType((const sal_Int32*)0)); + break; + default: + bModified = OBoundControlModel::convertFastPropertyValue( + rConvertedValue, + rOldValue, + nHandle, + rValue); + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OEditBaseModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw ( ::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_EMPTY_IS_NULL: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "invalid type" ); + m_bEmptyIsNull = getBOOL(rValue); + break; + case PROPERTY_ID_FILTERPROPOSAL: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "invalid type" ); + m_bFilterProposal = getBOOL(rValue); + break; + // Aenderung der defaultwerte fuehrt zu reset + case PROPERTY_ID_DEFAULT_TEXT: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "invalid type" ); + rValue >>= m_aDefaultText; + resetNoBroadcast(); + break; + case PROPERTY_ID_DEFAULT_VALUE: + case PROPERTY_ID_DEFAULT_DATE: + case PROPERTY_ID_DEFAULT_TIME: + m_aDefault = rValue; + resetNoBroadcast(); + break; + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue ); + } +} + +//XPropertyState +//------------------------------------------------------------------------------ +Any OEditBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_DEFAULT_TEXT: + return makeAny(::rtl::OUString()); + case PROPERTY_ID_FILTERPROPOSAL: + return Any(makeAny((sal_Bool)sal_False)); + case PROPERTY_ID_DEFAULT_VALUE: + case PROPERTY_ID_DEFAULT_DATE: + case PROPERTY_ID_DEFAULT_TIME: + return Any(); + default: + return OBoundControlModel::getPropertyDefaultByHandle(nHandle); + } +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/EditBase.hxx b/forms/source/component/EditBase.hxx new file mode 100644 index 000000000000..bfa51cb2d1ee --- /dev/null +++ b/forms/source/component/EditBase.hxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * 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_EDITBASE_HXX_ +#define _FORMS_EDITBASE_HXX_ + +#include "FormComponent.hxx" +#include <tools/date.hxx> +#include <tools/link.hxx> +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +#include <com/sun/star/awt/XKeyListener.hpp> +#include <com/sun/star/form/XChangeBroadcaster.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> + +// persistence flags for use with the version id +#define PF_HANDLE_COMMON_PROPS 0x8000 + // Derived classes which use their own persistence methods (read/write) and have an own + // version handling therein may want to clear this flag in getPersistenceFlags. + // If done so, this class will write an version without a call to writeCommonEditProperties. +#define PF_FAKE_FORMATTED_FIELD 0x4000 + // .... hmmm .... a fake, as the name suggests. see OFormattedFieldWrapper +#define PF_RESERVED_2 0x2000 +#define PF_RESERVED_3 0x1000 +#define PF_RESERVED_4 0x0800 +#define PF_RESERVED_5 0x0400 +#define PF_RESERVED_6 0x0200 +#define PF_RESERVED_7 0x0100 + +#define PF_SPECIAL_FLAGS 0xFF00 + +//......................................................................... +namespace frm +{ + +//================================================================== +//= OEditBaseModel +//================================================================== +class OEditBaseModel : public OBoundControlModel +{ + sal_Int16 m_nLastReadVersion; + +protected: +// [properties] fuer all Editierfelder + ::com::sun::star::uno::Any m_aDefault; + ::rtl::OUString m_aDefaultText; // default value + sal_Bool m_bEmptyIsNull : 1; // empty string will be interepreted as NULL when committing + sal_Bool m_bFilterProposal : 1; // use a list of possible value in filtermode +// [properties] + + sal_Int16 getLastReadVersion() const { return m_nLastReadVersion; } + +public: + DECLARE_DEFAULT_BOUND_XTOR( OEditBaseModel ); + + // XPersistObject + 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); + + // 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; + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + +protected: + // new properties common to all edit models should be handled with the following two methods + void SAL_CALL readCommonEditProperties(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream); + void SAL_CALL writeCommonEditProperties(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream); + void defaultCommonEditProperties(); + + virtual sal_uInt16 getPersistenceFlags() const; + // derived classes may use this if they want this base class to write additinal version flags + // (one of the PF_.... constants). After ::read they may ask for that flags with getLastReadVersion +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_EDITBASE_HXX_ + diff --git a/forms/source/component/EventThread.cxx b/forms/source/component/EventThread.cxx new file mode 100644 index 000000000000..504a180f6ee5 --- /dev/null +++ b/forms/source/component/EventThread.cxx @@ -0,0 +1,251 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "EventThread.hxx" +#include <comphelper/guarding.hxx> +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; + +DBG_NAME( OComponentEventThread ) +OComponentEventThread::OComponentEventThread( ::cppu::OComponentHelper* pCompImpl ) : + m_pCompImpl( pCompImpl ) +{ + DBG_CTOR( OComponentEventThread, NULL ); + + increment(m_refCount); + + // Eine Referenz des Controls halten + { + InterfaceRef xIFace(static_cast<XWeak*>(pCompImpl)); + query_interface(xIFace, m_xComp); + } + + // und uns an dem Control anmelden + { + Reference<XEventListener> xEvtLstnr = static_cast<XEventListener*>(this); + m_xComp->addEventListener( xEvtLstnr ); + } + + decrement(m_refCount); +} + +OComponentEventThread::~OComponentEventThread() +{ + DBG_DTOR( OComponentEventThread, NULL ); + + DBG_ASSERT( m_aEvents.size() == 0, + "OComponentEventThread::~OComponentEventThread: Kein dispose gerufen?" ); + + impl_clearEventQueue(); +} + +Any SAL_CALL OComponentEventThread::queryInterface(const Type& _rType) throw (RuntimeException) +{ + Any aReturn; + + aReturn = OWeakObject::queryInterface(_rType); + + if (!aReturn.hasValue()) + aReturn = ::cppu::queryInterface(_rType, + static_cast<XEventListener*>(this) + ); + + return aReturn; +} + +void OComponentEventThread::impl_clearEventQueue() +{ + while ( m_aEvents.size() ) + { + delete *m_aEvents.begin(); + m_aEvents.erase( m_aEvents.begin() ); + } + m_aControls.erase( m_aControls.begin(), m_aControls.end() ); + m_aFlags.erase( m_aFlags.begin(), m_aFlags.end() ); +} + +void OComponentEventThread::disposing( const EventObject& evt ) throw ( ::com::sun::star::uno::RuntimeException) +{ + if( evt.Source == m_xComp ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // Event-Listener abmelden + Reference<XEventListener> xEvtLstnr = static_cast<XEventListener*>(this); + m_xComp->removeEventListener( xEvtLstnr ); + + // Event-Queue loeschen + impl_clearEventQueue(); + + // Das Control loslassen und pCompImpl auf 0 setzen, damit der + // Thread weiss, dass er sich beenden soll. + m_xComp = 0; + m_pCompImpl = 0; + + // Den Thread aufwecken und beenden. + m_aCond.set(); + terminate(); + } +} + +void OComponentEventThread::addEvent( const EventObject* _pEvt, sal_Bool bFlag ) +{ + Reference<XControl> xTmp; + addEvent( _pEvt, xTmp, bFlag ); +} + +void OComponentEventThread::addEvent( const EventObject* _pEvt, + const Reference<XControl>& rControl, + sal_Bool bFlag ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + // Daten in die Queue stellen + m_aEvents.push_back( cloneEvent( _pEvt ) ); + + Reference<XWeak> xWeakControl(rControl, UNO_QUERY); + Reference<XAdapter> xControlAdapter = xWeakControl.is() ? xWeakControl->queryAdapter() : Reference<XAdapter>(); + m_aControls.push_back( xControlAdapter ); + + m_aFlags.push_back( bFlag ); + + // Thread aufwecken + m_aCond.set(); +} + +//--------------------------------------------------------------------- +//--- 22.08.01 15:48:15 ----------------------------------------------- + +void OComponentEventThread::implStarted( ) +{ + acquire( ); +} + +//--------------------------------------------------------------------- +//--- 22.08.01 15:48:16 ----------------------------------------------- + +void OComponentEventThread::implTerminated( ) +{ + release( ); +} + +//--------------------------------------------------------------------- +//--- 22.08.01 15:47:31 ----------------------------------------------- + +void SAL_CALL OComponentEventThread::kill() +{ + OComponentEventThread_TBASE::kill(); + + implTerminated( ); +} + +//--------------------------------------------------------------------- +//--- 22.08.01 15:47:33 ----------------------------------------------- + +void SAL_CALL OComponentEventThread::onTerminated() +{ + OComponentEventThread_TBASE::onTerminated(); + + implTerminated( ); +} + +void OComponentEventThread::run() +{ + implStarted( ); + + // uns selbst festhalten, damit wir nicht geloescht werden, + // wenn zwischendrinne mal ein dispose gerufen wird. + InterfaceRef xThis(static_cast<XWeak*>(this)); + + do + { + ::osl::MutexGuard aGuard(m_aMutex); + + while( m_aEvents.size() > 0 ) + { + // Das Control holen und festhalten, damit es waehrend des + // actionPerformed nicht geloescht werden kann. + Reference<XComponent> xComp = m_xComp; + ::cppu::OComponentHelper *pCompImpl = m_pCompImpl; + + ThreadEvents::iterator firstEvent( m_aEvents.begin() ); + EventObject* pEvt = *firstEvent; + m_aEvents.erase( firstEvent ); + + ThreadObjects::iterator firstControl( m_aControls.begin() ); + Reference<XAdapter> xControlAdapter = *firstControl; + m_aControls.erase( firstControl ); + + ThreadBools::iterator firstFlag( m_aFlags.begin() ); + sal_Bool bFlag = *firstFlag; + m_aFlags.erase( firstFlag ); + + { + MutexRelease aReleaseOnce(m_aMutex); + // Weil ein queryHardRef eine Exception schmeissen kann sollte + // es nicht bei gelocktem Mutex aufgerufen werden. + Reference<XControl> xControl; + if ( xControlAdapter.is() ) + query_interface(xControlAdapter->queryAdapted(), xControl); + + if( xComp.is() ) + processEvent( pCompImpl, pEvt, xControl, bFlag ); + } + + delete pEvt; + }; + + // Nach einem dispose kennen wir das Control nicht mehr. Dann darf + // auch nicht gewartet werden. + if( !m_xComp.is() ) + return; + + // Warte-Bedingung zuruecksetzen + m_aCond.reset(); + { + MutexRelease aReleaseOnce(m_aMutex); + // und warten ... falls nicht zwischenzeitlich doch noch ein + // Event eingetroffen ist. + m_aCond.wait(); + } + } + while( sal_True ); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/EventThread.hxx b/forms/source/component/EventThread.hxx new file mode 100644 index 000000000000..b36743f85b47 --- /dev/null +++ b/forms/source/component/EventThread.hxx @@ -0,0 +1,126 @@ +/************************************************************************* + * + * 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 _FRM_EVENT_THREAD_HXX_ +#define _FRM_EVENT_THREAD_HXX_ + +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <vos/thread.hxx> + + +#include <osl/conditn.hxx> +#include <cppuhelper/component.hxx> +#include <comphelper/stl_types.hxx> +#include <comphelper/uno3.hxx> +using namespace comphelper; + +//......................................................................... +namespace frm +{ +//......................................................................... + +// *************************************************************************************************** +// *************************************************************************************************** + +typedef ::vos::OThread OComponentEventThread_TBASE; +class OComponentEventThread + :public OComponentEventThread_TBASE + ,public ::com::sun::star::lang::XEventListener + ,public ::cppu::OWeakObject +{ + DECLARE_STL_VECTOR(::com::sun::star::lang::EventObject*, ThreadEvents); + DECLARE_STL_VECTOR(::com::sun::star::uno::Reference< ::com::sun::star::uno::XAdapter> , ThreadObjects); + DECLARE_STL_VECTOR(sal_Bool, ThreadBools); + + ::osl::Mutex m_aMutex; + ::osl::Condition m_aCond; // Queue gefuellt? + ThreadEvents m_aEvents; // Event-Queue + ThreadObjects m_aControls; // Control fuer Submit + ThreadBools m_aFlags; // Flags fuer Submit/Reset + + ::cppu::OComponentHelper* m_pCompImpl; // Implementierung des Controls + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> m_xComp; // ::com::sun::star::lang::XComponent des Controls + +protected: + + // XThread + virtual void SAL_CALL run(); + + virtual void SAL_CALL kill(); + virtual void SAL_CALL onTerminated(); + + // Die folgende Methode wird gerufen um das Event unter Beruecksichtigung + // seines Typs zu duplizieren. + virtual ::com::sun::star::lang::EventObject* cloneEvent(const ::com::sun::star::lang::EventObject* _pEvt) const = 0; + + // Ein Event bearbeiten. Der Mutex ist dabei nicht gelockt, pCompImpl + // bleibt aber in jedem Fall gueltig. Bei pEvt kann es sich auch um + // einen abgeleiteten Typ handeln, naemlich den, den cloneEvent + // zurueckgibt. rControl ist nur gesetzt, wenn beim addEvent ein + // Control uebergeben wurde. Da das Control nur als WeakRef gehalten + // wird kann es auch zwischenzeitlich verschwinden. + virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl, + const ::com::sun::star::lang::EventObject* _pEvt, + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& _rControl, + sal_Bool _bFlag) = 0; + +public: + + // UNO Anbindung + DECLARE_UNO3_DEFAULTS(OComponentEventThread, OWeakObject); + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type& _rType) throw (::com::sun::star::uno::RuntimeException); + + OComponentEventThread(::cppu::OComponentHelper* pCompImpl); + virtual ~OComponentEventThread(); + + void addEvent( const ::com::sun::star::lang::EventObject* _pEvt, sal_Bool bFlag = sal_False ); + void addEvent( const ::com::sun::star::lang::EventObject* _pEvt, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& rControl, + sal_Bool bFlag = sal_False ); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException); + +/* resolve ambiguity : both OWeakObject and OObject have these memory operators */ + void * SAL_CALL operator new( size_t size ) throw() { return OThread::operator new(size); } + void SAL_CALL operator delete( void * p ) throw() { OThread::operator delete(p); } + +private: + void implStarted( ); + void implTerminated( ); + + void impl_clearEventQueue(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_EVENT_THREAD_HXX_ + diff --git a/forms/source/component/File.cxx b/forms/source/component/File.cxx new file mode 100644 index 000000000000..d92386b26405 --- /dev/null +++ b/forms/source/component/File.cxx @@ -0,0 +1,307 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + + +#include "File.hxx" + +#include <com/sun/star/form/FormComponentType.hpp> + +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/container.hxx> +#include <comphelper/basicio.hxx> +#include <comphelper/guarding.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFileControlModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFileControlModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OFileControlModel::_getTypes() +{ + static Sequence<Type> aTypes; + if (!aTypes.getLength()) + { + // my base class + Sequence<Type> aBaseClassTypes = OControlModel::_getTypes(); + + Sequence<Type> aOwnTypes(1); + Type* pOwnTypes = aOwnTypes.getArray(); + pOwnTypes[0] = getCppuType((Reference<XReset>*)NULL); + + aTypes = concatSequences(aBaseClassTypes, aOwnTypes); + } + return aTypes; +} + + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OFileControlModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_FILECONTROL; + return aSupported; +} + +//------------------------------------------------------------------ +DBG_NAME( OFileControlModel ) +//------------------------------------------------------------------ +OFileControlModel::OFileControlModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OControlModel(_rxFactory, VCL_CONTROLMODEL_FILECONTROL) + ,m_aResetListeners(m_aMutex) +{ + DBG_CTOR( OFileControlModel, NULL ); + m_nClassId = FormComponentType::FILECONTROL; +} + +//------------------------------------------------------------------ +OFileControlModel::OFileControlModel( const OFileControlModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + ,m_aResetListeners( m_aMutex ) +{ + DBG_CTOR( OFileControlModel, NULL ); + + m_sDefaultValue = _pOriginal->m_sDefaultValue; +} + +//------------------------------------------------------------------ +OFileControlModel::~OFileControlModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + DBG_DTOR( OFileControlModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OFileControlModel ) + +//------------------------------------------------------------------------------ +Any SAL_CALL OFileControlModel::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OControlModel::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = ::cppu::queryInterface(_rType + ,static_cast<XReset*>(this) + ); + + return aReturn; +} + +// OComponentHelper +//----------------------------------------------------------------------------- +void OFileControlModel::disposing() +{ + OControlModel::disposing(); + + EventObject aEvt(static_cast<XWeak*>(this)); + m_aResetListeners.disposeAndClear(aEvt); +} + +//------------------------------------------------------------------------------ +Any OFileControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const +{ + Any aReturn; + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_TEXT: + return makeAny( ::rtl::OUString() ); + } + return OControlModel::getPropertyDefaultByHandle( _nHandle ); +} + +//------------------------------------------------------------------------------ +void OFileControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const +{ + switch (nHandle) + { + case PROPERTY_ID_DEFAULT_TEXT : rValue <<= m_sDefaultValue; break; + default: + OControlModel::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +void OFileControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_DEFAULT_TEXT : + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OFileControlModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_sDefaultValue; + break; + default: + OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OFileControlModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) + throw( IllegalArgumentException ) +{ + switch (nHandle) + { + case PROPERTY_ID_DEFAULT_TEXT : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sDefaultValue); + default: + return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); + } +} + +//------------------------------------------------------------------------------ +void OFileControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 2, OControlModel ) + DECL_PROP1(DEFAULT_TEXT, ::rtl::OUString, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFileControlModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_FILECONTROL; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OFileControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::write(_rxOutStream); + + ::osl::MutexGuard aGuard(m_aMutex); + + // Version + _rxOutStream->writeShort(0x0002); + // Default-Wert + _rxOutStream << m_sDefaultValue; + writeHelpTextCompatibly(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void OFileControlModel::read(const Reference<stario::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::read(_rxInStream); + ::osl::MutexGuard aGuard(m_aMutex); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + // Default-Wert + switch (nVersion) + { + case 1: + _rxInStream >> m_sDefaultValue; break; + case 2: + _rxInStream >> m_sDefaultValue; + readHelpTextCompatibly(_rxInStream); + break; + default: + DBG_ERROR("OFileControlModel::read : unknown version !"); + m_sDefaultValue = ::rtl::OUString(); + } + + // Nach dem Lesen die Defaultwerte anzeigen +// _reset(); +} + +//----------------------------------------------------------------------------- +void SAL_CALL OFileControlModel::reset() throw ( ::com::sun::star::uno::RuntimeException) +{ + ::cppu::OInterfaceIteratorHelper aIter(m_aResetListeners); + EventObject aEvt(static_cast<XWeak*>(this)); + sal_Bool bContinue = sal_True; + while (aIter.hasMoreElements() && bContinue) + bContinue =((XResetListener*)aIter.next())->approveReset(aEvt); + + if (bContinue) + { + { + // Wenn Models threadSave + ::osl::MutexGuard aGuard(m_aMutex); + _reset(); + } + m_aResetListeners.notifyEach( &XResetListener::resetted, aEvt ); + } +} + +//----------------------------------------------------------------------------- +void OFileControlModel::addResetListener(const Reference<XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aResetListeners.addInterface(_rxListener); +} + +//----------------------------------------------------------------------------- +void OFileControlModel::removeResetListener(const Reference<XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aResetListeners.removeInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void OFileControlModel::_reset() +{ + { // release our mutex once (it's acquired in the calling method !), as setting aggregate properties + // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with + // our own mutex locked + // FS - 72451 - 31.01.00 + MutexRelease aRelease(m_aMutex); + m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, makeAny(m_sDefaultValue)); + } +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/File.hxx b/forms/source/component/File.hxx new file mode 100644 index 000000000000..200cac5545ea --- /dev/null +++ b/forms/source/component/File.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * 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_FILE_HXX_ +#define _FORMS_FILE_HXX_ + +#include "FormComponent.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OFileControlModel +//================================================================== +class OFileControlModel + :public OControlModel + ,public ::com::sun::star::form::XReset +{ + ::cppu::OInterfaceContainerHelper m_aResetListeners; + ::rtl::OUString m_sDefaultValue; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OFileControlModel ); + + DECLARE_UNO3_AGG_DEFAULTS(OFileControlModel, OControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OFileControlModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XPropertySet and friends + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + 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 ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 _nHandle ) const; + + // 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); + + // 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>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OControlModel::disposing; + using OControlModel::getFastPropertyValue; + +protected: + virtual void _reset(); + + DECLARE_XCLONEABLE(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_FILE_HXX_ + diff --git a/forms/source/component/Filter.cxx b/forms/source/component/Filter.cxx new file mode 100644 index 000000000000..9cbc5237cf95 --- /dev/null +++ b/forms/source/component/Filter.cxx @@ -0,0 +1,873 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + + +#include "Filter.hxx" +#include "FormComponent.hxx" +#include "frm_module.hxx" +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "property.hrc" +#include "property.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/VclWindowPeerAttribute.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/XRadioButton.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/sdb/BooleanComparisonMode.hpp> +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +/** === end UNO includes === **/ + +#include <comphelper/numbers.hxx> +#include <comphelper/property.hxx> +#include <connectivity/dbconversion.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/formattedcolumnvalue.hxx> +#include <connectivity/predicateinput.hxx> +#include <rtl/ustrbuf.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/localedatawrapper.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wintypes.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_OFilterControl() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::OFilterControl > aAutoRegistration; +} + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::ui::dialogs; + + using namespace ::connectivity; + + //===================================================================== + // OFilterControl + //===================================================================== + //--------------------------------------------------------------------- + OFilterControl::OFilterControl( const Reference< XMultiServiceFactory >& _rxORB ) + :m_aTextListeners( *this ) + ,m_aContext( _rxORB ) + ,m_aParser( _rxORB ) + ,m_nControlClass( FormComponentType::TEXTFIELD ) + ,m_bFilterList( sal_False ) + ,m_bMultiLine( sal_False ) + ,m_bFilterListFilled( sal_False ) + { + } + + //--------------------------------------------------------------------- + sal_Bool OFilterControl::ensureInitialized( ) + { + if ( !m_xField.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: improperly initialized: no field!" ); + return sal_False; + } + + if ( !m_xConnection.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: improperly initialized: no connection!" ); + return sal_False; + } + + if ( !m_xFormatter.is() ) + { + // we can create one from the connection, if it's an SDB connection + Reference< XNumberFormatsSupplier > xFormatSupplier = ::dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getLegacyServiceFactory() ); + + if ( xFormatSupplier.is() ) + { + m_aContext.createComponent( "com.sun.star.util.NumberFormatter", m_xFormatter ); + if ( m_xFormatter.is() ) + m_xFormatter->attachNumberFormatsSupplier( xFormatSupplier ); + } + } + if ( !m_xFormatter.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: no number formatter!" ); + // no fallback anymore + return sal_False; + } + + return sal_True; + } + + //--------------------------------------------------------------------- + Any SAL_CALL OFilterControl::queryAggregation( const Type & rType ) throw(RuntimeException) + { + Any aRet = UnoControl::queryAggregation( rType); + if(!aRet.hasValue()) + aRet = OFilterControl_BASE::queryInterface(rType); + + return aRet; + } + + //------------------------------------------------------------------ + ::rtl::OUString OFilterControl::GetComponentServiceName() + { + ::rtl::OUString aServiceName; + switch (m_nControlClass) + { + case FormComponentType::RADIOBUTTON: + aServiceName = ::rtl::OUString::createFromAscii("radiobutton"); + break; + case FormComponentType::CHECKBOX: + aServiceName = ::rtl::OUString::createFromAscii("checkbox"); + break; + case FormComponentType::COMBOBOX: + aServiceName = ::rtl::OUString::createFromAscii("combobox"); + break; + case FormComponentType::LISTBOX: + aServiceName = ::rtl::OUString::createFromAscii("listbox"); + break; + default: + if (m_bMultiLine) + aServiceName = ::rtl::OUString::createFromAscii("MultiLineEdit"); + else + aServiceName = ::rtl::OUString::createFromAscii("Edit"); + } + return aServiceName; + } + + // XComponent + //--------------------------------------------------------------------- + void OFilterControl::dispose() throw( RuntimeException ) + { + EventObject aEvt(*this); + m_aTextListeners.disposeAndClear( aEvt ); + UnoControl::dispose(); + } + + //--------------------------------------------------------------------- + void OFilterControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw(RuntimeException) + { + UnoControl::createPeer( rxToolkit, rParentPeer ); + + try + { + Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY_THROW ); + switch ( m_nControlClass ) + { + case FormComponentType::CHECKBOX: + { + // checkboxes always have a tristate-mode + xVclWindow->setProperty( PROPERTY_TRISTATE, makeAny( sal_Bool( sal_True ) ) ); + xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_DONTKNOW ) ) ); + + Reference< XCheckBox > xBox( getPeer(), UNO_QUERY_THROW ); + xBox->addItemListener( this ); + + } + break; + + case FormComponentType::RADIOBUTTON: + { + xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_NOCHECK ) ) ); + + Reference< XRadioButton > xRadio( getPeer(), UNO_QUERY_THROW ); + xRadio->addItemListener( this ); + } + break; + + case FormComponentType::LISTBOX: + { + Reference< XListBox > xListBox( getPeer(), UNO_QUERY_THROW ); + xListBox->addItemListener( this ); + } + // no break + + case FormComponentType::COMBOBOX: + { + xVclWindow->setProperty(PROPERTY_AUTOCOMPLETE, makeAny( sal_Bool( sal_True ) ) ); + } + // no break + + default: + { + Reference< XWindow > xWindow( getPeer(), UNO_QUERY ); + xWindow->addFocusListener( this ); + + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + xText->setMaxTextLen(0); + } + break; + } + + OControl::initFormControlPeer( getPeer() ); + + // filter controls are _never_ readonly + // #107013# - 2002-02-03 - fs@openoffice.org + Reference< XPropertySet > xModel( getModel(), UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW ); + if ( xModelPSI->hasPropertyByName( PROPERTY_READONLY ) ) + xVclWindow->setProperty( PROPERTY_READONLY, makeAny( sal_Bool( sal_False ) ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if (m_bFilterList) + m_bFilterListFilled = sal_False; + } + + //--------------------------------------------------------------------- + void OFilterControl::PrepareWindowDescriptor( WindowDescriptor& rDescr ) + { + if (m_bFilterList) + rDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN; + } + + //--------------------------------------------------------------------- + void OFilterControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal ) + { + // these properties are ignored + if (rPropName == PROPERTY_TEXT || + rPropName == PROPERTY_STATE) + return; + + UnoControl::ImplSetPeerProperty( rPropName, rVal ); + } + + // XEventListener + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::disposing(const EventObject& Source) throw( RuntimeException ) + { + UnoControl::disposing(Source); + } + + // XItemListener + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::itemStateChanged( const ItemEvent& rEvent ) throw(RuntimeException) + { + ::rtl::OUStringBuffer aText; + switch (m_nControlClass) + { + case FormComponentType::CHECKBOX: + { + if ( ( rEvent.Selected == STATE_CHECK ) || ( rEvent.Selected == STATE_NOCHECK ) ) + { + sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( m_xConnection ).getBooleanComparisonMode(); + + bool bSelected = ( rEvent.Selected == STATE_CHECK ); + + ::rtl::OUString sExpressionMarker( RTL_CONSTASCII_USTRINGPARAM( "$expression$" ) ); + ::dbtools::getBoleanComparisonPredicate( + sExpressionMarker, + bSelected, + nBooleanComparisonMode, + aText + ); + + ::rtl::OUString sText( aText.makeStringAndClear() ); + sal_Int32 nMarkerPos( sText.indexOf( sExpressionMarker ) ); + OSL_ENSURE( nMarkerPos == 0, "OFilterControl::itemStateChanged: unsupported boolean comparison mode!" ); + // If this assertion fails, then getBoleanComparisonPredicate created a predicate which + // does not start with the expression we gave it. The only known case is when + // the comparison mode is ACCESS_COMPAT, and the value is TRUE. In this case, + // the expression is rather complex. + // Well, so this is a known issue - the filter controls (and thus the form based filter) + // do not work with boolean MS Access fields. + // To fix this, we would probably have to revert here to always return "1" or "0" as normalized + // filter, and change our client code to properly translate this (which could be some effort). + if ( nMarkerPos == 0 ) + aText.append( sText.copy( sExpressionMarker.getLength() ) ); + else + { + // fallback + aText.appendAscii( bSelected ? "1" : "0" ); + } + } + } + break; + + case FormComponentType::LISTBOX: + { + Sequence< ::rtl::OUString> aValueSelection; + Reference< XPropertySet > aPropertyPointer(getModel(), UNO_QUERY); + aPropertyPointer->getPropertyValue(PROPERTY_VALUE_SEQ) >>= aValueSelection; + if (rEvent.Selected <= aValueSelection.getLength()) + aText.append( aValueSelection[ rEvent.Selected ] ); + } + break; + + case FormComponentType::RADIOBUTTON: + { + if ( rEvent.Selected == STATE_CHECK ) + aText.append( ::comphelper::getString( Reference< XPropertySet >( getModel(), UNO_QUERY )->getPropertyValue( PROPERTY_REFVALUE ) ) ); + } + break; + } + + ::rtl::OUString sText( aText.makeStringAndClear() ); + if ( m_aText.compareTo( sText ) ) + { + m_aText = sText; + TextEvent aEvt; + aEvt.Source = *this; + ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners ); + while( aIt.hasMoreElements() ) + ((XTextListener *)aIt.next())->textChanged( aEvt ); + } + } + + //--------------------------------------------------------------------- + void OFilterControl::implInitFilterList() + { + if ( !ensureInitialized( ) ) + // already asserted in ensureInitialized + return; + + // ensure the cursor and the statement are disposed as soon as we leave + ::utl::SharedUNOComponent< XResultSet > xListCursor; + ::utl::SharedUNOComponent< XStatement > xStatement; + + try + { + m_bFilterListFilled = sal_True; + + if ( !m_xField.is() ) + return; + + ::rtl::OUString sFieldName; + m_xField->getPropertyValue( PROPERTY_NAME ) >>= sFieldName; + + // here we need a table to which the field belongs to + const Reference< XChild > xModelAsChild( getModel(), UNO_QUERY_THROW ); + const Reference< XRowSet > xForm( xModelAsChild->getParent(), UNO_QUERY_THROW ); + const Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW ); + + // create a query composer + Reference< XColumnsSupplier > xSuppColumns; + xFormProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSuppColumns; + + const Reference< XConnection > xConnection( ::dbtools::getConnection( xForm ), UNO_SET_THROW ); + const Reference< XNameAccess > xFieldNames( xSuppColumns->getColumns(), UNO_SET_THROW ); + if ( !xFieldNames->hasByName( sFieldName ) ) + return; + ::rtl::OUString sRealFieldName, sTableName; + const Reference< XPropertySet > xComposerFieldProps( xFieldNames->getByName( sFieldName ), UNO_QUERY_THROW ); + xComposerFieldProps->getPropertyValue( PROPERTY_REALNAME ) >>= sRealFieldName; + xComposerFieldProps->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName; + + // obtain the table of the field + const Reference< XTablesSupplier > xSuppTables( xSuppColumns, UNO_QUERY_THROW ); + const Reference< XNameAccess > xTablesNames( xSuppTables->getTables(), UNO_SET_THROW ); + const Reference< XNamed > xNamedTable( xTablesNames->getByName( sTableName ), UNO_QUERY_THROW ); + sTableName = xNamedTable->getName(); + + // create a statement selecting all values for the given field + ::rtl::OUStringBuffer aStatement; + + const Reference< XDatabaseMetaData > xMeta( xConnection->getMetaData(), UNO_SET_THROW ); + const ::rtl::OUString sQuoteChar = xMeta->getIdentifierQuoteString(); + + aStatement.appendAscii( "SELECT DISTINCT " ); + aStatement.append( sQuoteChar ); + aStatement.append( sRealFieldName ); + aStatement.append( sQuoteChar ); + + // if the field had an alias in our form's statement, give it this alias in the new statement, too + if ( sFieldName.getLength() && ( sFieldName != sRealFieldName ) ) + { + aStatement.appendAscii(" AS "); + aStatement.append( sQuoteChar ); + aStatement.append( sFieldName ); + aStatement.append( sQuoteChar ); + } + + aStatement.appendAscii( " FROM " ); + + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( xMeta, sTableName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + aStatement.append( ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) ); + + // execute the statement + xStatement.reset( xConnection->createStatement() ); + const ::rtl::OUString sSelectStatement( aStatement.makeStringAndClear( ) ); + xListCursor.reset( xStatement->executeQuery( sSelectStatement ) ); + + // retrieve the one column which we take the values from + const Reference< XColumnsSupplier > xSupplyCols( xListCursor, UNO_QUERY_THROW ); + const Reference< XIndexAccess > xFields( xSupplyCols->getColumns(), UNO_QUERY_THROW ); + const Reference< XPropertySet > xDataField( xFields->getByIndex(0), UNO_QUERY_THROW ); + + // ensure the values will be formatted according to the field format + const ::dbtools::FormattedColumnValue aFormatter( m_xFormatter, xDataField ); + + ::std::vector< ::rtl::OUString > aProposals; + aProposals.reserve(16); + + while ( xListCursor->next() && ( aProposals.size() < size_t( SHRT_MAX ) ) ) + { + const ::rtl::OUString sCurrentValue = aFormatter.getFormattedValue(); + aProposals.push_back( sCurrentValue ); + } + + // fill the list items into our peer + Sequence< ::rtl::OUString> aStringSeq( aProposals.size() ); + ::std::copy( aProposals.begin(), aProposals.end(), aStringSeq.getArray() ); + + const Reference< XComboBox > xComboBox( getPeer(), UNO_QUERY_THROW ); + xComboBox->addItems( aStringSeq, 0 ); + + // set the drop down line count to something reasonable + const sal_Int16 nLineCount = ::std::min( sal_Int16( 16 ), sal_Int16( aStringSeq.getLength() ) ); + xComboBox->setDropDownLineCount( nLineCount ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + // XFocusListener + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::focusGained(const FocusEvent& /*e*/) throw( RuntimeException ) + { + // should we fill the combobox? + if (m_bFilterList && !m_bFilterListFilled) + implInitFilterList(); + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::focusLost(const FocusEvent& /*e*/) throw( RuntimeException ) + { + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OFilterControl::commit() throw(RuntimeException) + { + if ( !ensureInitialized( ) ) + // already asserted in ensureInitialized + return sal_True; + + ::rtl::OUString aText; + switch (m_nControlClass) + { + case FormComponentType::TEXTFIELD: + case FormComponentType::COMBOBOX: + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + aText = xText->getText(); + } break; + default: + return sal_True; + } + if (m_aText.compareTo(aText)) + { + // check the text with the SQL-Parser + ::rtl::OUString aNewText(aText); + aNewText.trim(); + if ( aNewText.getLength() ) + { + ::dbtools::OPredicateInputController aPredicateInput( m_aContext.getLegacyServiceFactory(), m_xConnection, getParseContext() ); + ::rtl::OUString sErrorMessage; + if ( !aPredicateInput.normalizePredicateString( aNewText, m_xField, &sErrorMessage ) ) + { + // display the error and outta here + SQLContext aError; + aError.Message = String( FRM_RES_STRING( RID_STR_SYNTAXERROR ) ); + aError.Details = sErrorMessage; + displayException( aError ); + return sal_False; + } + } + + setText(aNewText); + TextEvent aEvt; + aEvt.Source = *this; + ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners ); + while( aIt.hasMoreElements() ) + static_cast< XTextListener* >( aIt.next() )->textChanged( aEvt ); + } + return sal_True; + } + + // XTextComponent + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::addTextListener(const Reference< XTextListener > & l) throw(RuntimeException) + { + m_aTextListeners.addInterface( l ); + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::removeTextListener(const Reference< XTextListener > & l) throw(RuntimeException) + { + m_aTextListeners.removeInterface( l ); + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::setText( const ::rtl::OUString& aText ) throw(RuntimeException) + { + if ( !ensureInitialized( ) ) + // already asserted in ensureInitialized + return; + + switch (m_nControlClass) + { + case FormComponentType::CHECKBOX: + { + Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY ); + if (xVclWindow.is()) + { + Any aValue; + if ( aText.equalsAscii( "1" ) + || aText.equalsIgnoreAsciiCaseAscii( "TRUE" ) + || aText.equalsIgnoreAsciiCaseAscii( "IS TRUE" ) + ) + { + aValue <<= (sal_Int32)STATE_CHECK; + } + else if ( aText.equalsAscii( "0" ) + || aText.equalsIgnoreAsciiCaseAscii( "FALSE" ) + ) + { + aValue <<= (sal_Int32)STATE_NOCHECK; + } + else + aValue <<= (sal_Int32)STATE_DONTKNOW; + + m_aText = aText; + xVclWindow->setProperty( PROPERTY_STATE, aValue ); + } + } break; + case FormComponentType::RADIOBUTTON: + { + Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY ); + if (xVclWindow.is()) + { + ::rtl::OUString aRefText = ::comphelper::getString(com::sun::star::uno::Reference< XPropertySet > (getModel(), UNO_QUERY)->getPropertyValue(PROPERTY_REFVALUE)); + Any aValue; + if (aText == aRefText) + aValue <<= (sal_Int32)STATE_CHECK; + else + aValue <<= (sal_Int32)STATE_NOCHECK; + m_aText = aText; + xVclWindow->setProperty(PROPERTY_STATE, aValue); + } + } break; + case FormComponentType::LISTBOX: + { + Reference< XListBox > xListBox( getPeer(), UNO_QUERY ); + if (xListBox.is()) + { + m_aText = aText; + xListBox->selectItem(m_aText, sal_True); + } + } break; + default: + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + { + m_aText = aText; + xText->setText(aText); + } + } + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + { + xText->insertText(rSel, aText); + m_aText = xText->getText(); + } + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OFilterControl::getText() throw(RuntimeException) + { + return m_aText; + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OFilterControl::getSelectedText( void ) throw(RuntimeException) + { + ::rtl::OUString aSelected; + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + aSelected = xText->getSelectedText(); + + return aSelected; + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw(::com::sun::star::uno::RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + xText->setSelection( aSelection ); + } + + //--------------------------------------------------------------------- + ::com::sun::star::awt::Selection SAL_CALL OFilterControl::getSelection( void ) throw(::com::sun::star::uno::RuntimeException) + { + ::com::sun::star::awt::Selection aSel; + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + aSel = xText->getSelection(); + return aSel; + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OFilterControl::isEditable( void ) throw(RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + return xText.is() && xText->isEditable(); + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::setEditable( sal_Bool bEditable ) throw(RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + xText->setEditable(bEditable); + } + + //--------------------------------------------------------------------- + sal_Int16 SAL_CALL OFilterControl::getMaxTextLen() throw(RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + return xText.is() ? xText->getMaxTextLen() : 0; + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::setMaxTextLen( sal_Int16 nLength ) throw(RuntimeException) + { + Reference< XTextComponent > xText( getPeer(), UNO_QUERY ); + if (xText.is()) + xText->setMaxTextLen(nLength); + } + + //--------------------------------------------------------------------- + void OFilterControl::displayException( const ::com::sun::star::sdb::SQLContext& _rExcept ) + { + try + { + Sequence< Any > aArgs(2); + aArgs[0] <<= PropertyValue(::rtl::OUString::createFromAscii("SQLException"), 0, makeAny( _rExcept ), PropertyState_DIRECT_VALUE); + aArgs[1] <<= PropertyValue(::rtl::OUString::createFromAscii("ParentWindow"), 0, makeAny( m_xMessageParent ), PropertyState_DIRECT_VALUE); + + static ::rtl::OUString s_sDialogServiceName = ::rtl::OUString::createFromAscii( "com.sun.star.sdb.ErrorMessageDialog" ); + + Reference< XExecutableDialog > xErrorDialog( m_aContext.createComponentWithArguments( s_sDialogServiceName, aArgs ), UNO_QUERY ); + if ( xErrorDialog.is() ) + xErrorDialog->execute(); + else + { + Window* pMessageParent = VCLUnoHelper::GetWindow( m_xMessageParent ); + ShowServiceNotAvailableError( pMessageParent, s_sDialogServiceName, sal_True ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OFilterControl::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) + { + const Any* pArguments = aArguments.getConstArray(); + const Any* pArgumentsEnd = pArguments + aArguments.getLength(); + + PropertyValue aProp; + NamedValue aValue; + const ::rtl::OUString* pName = NULL; + const Any* pValue = NULL; + + for ( ; pArguments != pArgumentsEnd; ++pArguments ) + { + // we recognize PropertyValues and NamedValues + if ( *pArguments >>= aProp ) + { + pName = &aProp.Name; + pValue = &aProp.Value; + } + else if ( *pArguments >>= aValue ) + { + pName = &aValue.Name; + pValue = &aValue.Value; + } + else + { + DBG_ERROR( "OFilterControl::initialize: unrecognized argument!" ); + continue; + } + + if ( 0 == pName->compareToAscii( "MessageParent" ) ) + { + // the message parent + *pValue >>= m_xMessageParent; + OSL_ENSURE( m_xMessageParent.is(), "OFilterControl::initialize: invalid MessageParent!" ); + } + else if ( 0 == pName->compareToAscii( "NumberFormatter" ) ) + { + // the number format. This argument is optional. + *pValue >>= m_xFormatter; + OSL_ENSURE( m_xFormatter.is(), "OFilterControl::initialize: invalid NumberFormatter!" ); + } + else if ( 0 == pName->compareToAscii( "ControlModel" ) ) + { + // the control model for which we act as filter control + Reference< XPropertySet > xControlModel; + if ( !(*pValue >>= xControlModel ) || !xControlModel.is() ) + { + OSL_ENSURE( sal_False, "OFilterControl::initialize: invalid control model argument!" ); + continue; + } + + // some properties which are "derived" from the control model we're working for + // ................................................... + // the field + m_xField.clear(); + OSL_ENSURE( ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ), "OFilterControl::initialize: control model needs a bound field property!" ); + xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= m_xField; + + // ................................................... + // filter list and control class + m_bFilterList = ::comphelper::hasProperty( PROPERTY_FILTERPROPOSAL, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_FILTERPROPOSAL ) ); + if ( m_bFilterList ) + m_nControlClass = FormComponentType::COMBOBOX; + else + { + sal_Int16 nClassId = ::comphelper::getINT16( xControlModel->getPropertyValue( PROPERTY_CLASSID ) ); + switch (nClassId) + { + case FormComponentType::CHECKBOX: + case FormComponentType::RADIOBUTTON: + case FormComponentType::LISTBOX: + case FormComponentType::COMBOBOX: + m_nControlClass = nClassId; + break; + default: + m_bMultiLine = ::comphelper::hasProperty( PROPERTY_MULTILINE, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_MULTILINE ) ); + m_nControlClass = FormComponentType::TEXTFIELD; + break; + } + } + + // ................................................... + // the connection meta data for the form which we're working for + Reference< XChild > xModel( xControlModel, UNO_QUERY ); + Reference< XRowSet > xForm; + if ( xModel.is() ) + xForm = xForm.query( xModel->getParent() ); + m_xConnection = ::dbtools::getConnection( xForm ); + OSL_ENSURE( m_xConnection.is(), "OFilterControl::initialize: unable to determine the form's connection!" ); + } + } + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OFilterControl::getImplementationName( ) throw (RuntimeException) + { + return getImplementationName_Static(); + } + + //--------------------------------------------------------------------- + sal_Bool SAL_CALL OFilterControl::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() ); + const ::rtl::OUString* pArray = aSupported.getConstArray(); + for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray ) + if( pArray->equals( ServiceName ) ) + return sal_True; + return sal_False; + } + + //--------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames( ) throw (RuntimeException) + { + return getSupportedServiceNames_Static(); + } + + //--------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OFilterControl::getImplementationName_Static() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.OFilterControl" ) ); + } + + //--------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames_Static() + { + Sequence< ::rtl::OUString > aNames( 2 ); + aNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.control.FilterControl" ) ); + aNames[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) ); + return aNames; + } + + //--------------------------------------------------------------------- + Reference< XInterface > SAL_CALL OFilterControl::Create( const Reference< XMultiServiceFactory >& _rxFactory ) + { + return static_cast< XServiceInfo* >( new OFilterControl( _rxFactory ) ); + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/component/Filter.hxx b/forms/source/component/Filter.hxx new file mode 100644 index 000000000000..8e2933e93158 --- /dev/null +++ b/forms/source/component/Filter.hxx @@ -0,0 +1,156 @@ +/************************************************************************* + * + * 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_COMPONENT_FILTER_HXX +#define FORMS_COMPONENT_FILTER_HXX + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/form/XBoundComponent.hpp> +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/awt/XTextComponent.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <toolkit/controls/unocontrol.hxx> + +#include <toolkit/helper/listenermultiplexer.hxx> +#include <cppuhelper/implbase5.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/componentcontext.hxx> +#include <cppuhelper/implbase4.hxx> +#include <connectivity/sqlparse.hxx> +#include <svx/ParseContext.hxx> + +class Window; + +//......................................................................... +namespace frm +{ +//......................................................................... + + //===================================================================== + // OFilterControl + //===================================================================== + typedef ::cppu::ImplHelper5 < ::com::sun::star::awt::XTextComponent + , ::com::sun::star::awt::XFocusListener + , ::com::sun::star::awt::XItemListener + , ::com::sun::star::form::XBoundComponent + , ::com::sun::star::lang::XInitialization + > OFilterControl_BASE; + + class OFilterControl :public UnoControl + ,public OFilterControl_BASE + ,public ::svxform::OParseContextClient + { + TextListenerMultiplexer m_aTextListeners; + + ::comphelper::ComponentContext m_aContext; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xField; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > m_xFormatter; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData > m_xMetaData; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xMessageParent; + + ::rtl::OUString m_aText; + ::connectivity::OSQLParser m_aParser; + sal_Int16 m_nControlClass; // which kind of control do we use? + sal_Bool m_bFilterList : 1; + sal_Bool m_bMultiLine : 1; + sal_Bool m_bFilterListFilled : 1; + + private: +// OFilterControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB); + + void implInitFilterList(); + + public: + OFilterControl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB ); + + DECLARE_UNO3_AGG_DEFAULTS(OFilterControl,OWeakAggObject); + ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString GetComponentServiceName(); + virtual void SAL_CALL createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > & rxToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > & rParentPeer ) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::lang::XComponent + virtual void SAL_CALL dispose(void) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::awt::XTextComponent + virtual void SAL_CALL addTextListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeTextListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setText( const ::rtl::OUString& aText ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getText() throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getSelectedText() throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::awt::Selection SAL_CALL getSelection() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL isEditable() throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setEditable( sal_Bool bEditable ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setMaxTextLen( sal_Int16 nLength ) throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int16 SAL_CALL getMaxTextLen() throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::form::XBoundComponent + virtual void SAL_CALL addUpdateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener > & /*l*/) throw( ::com::sun::star::uno::RuntimeException ) {} + virtual void SAL_CALL removeUpdateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener > & /*l*/) throw( ::com::sun::star::uno::RuntimeException ) {} + virtual sal_Bool SAL_CALL commit() throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::awt::XFocusListener + virtual void SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& e) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& e) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::awt::XItemListener + virtual void SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& rEvent) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::util::XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + protected: + virtual void PrepareWindowDescriptor( ::com::sun::star::awt::WindowDescriptor& rDesc ); + virtual void ImplSetPeerProperty( const ::rtl::OUString& rPropName, const ::com::sun::star::uno::Any& rVal ); + + sal_Bool ensureInitialized( ); + + void displayException( const ::com::sun::star::sdb::SQLContext& _rExcept ); + }; +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_COMPONENT_FILTER_HXX diff --git a/forms/source/component/FixedText.cxx b/forms/source/component/FixedText.cxx new file mode 100644 index 000000000000..9396e7aabb59 --- /dev/null +++ b/forms/source/component/FixedText.cxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + + +#include "FixedText.hxx" +#include "services.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "property.hxx" +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL OFixedTextModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OFixedTextModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( OFixedTextModel ) +//------------------------------------------------------------------ +OFixedTextModel::OFixedTextModel( const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel(_rxFactory, VCL_CONTROLMODEL_FIXEDTEXT) + +{ + DBG_CTOR( OFixedTextModel, NULL ); + m_nClassId = FormComponentType::FIXEDTEXT; +} + +//------------------------------------------------------------------ +OFixedTextModel::OFixedTextModel( const OFixedTextModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + +{ + DBG_CTOR( OFixedTextModel, NULL ); +} + +//------------------------------------------------------------------ +OFixedTextModel::~OFixedTextModel( ) +{ + DBG_DTOR( OFixedTextModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OFixedTextModel ) + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OFixedTextModel::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) +{ + StringSequence aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_FIXEDTEXT; + return aSupported; +} + +//------------------------------------------------------------------------------ +void OFixedTextModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OControlModel::describeAggregateProperties( _rAggregateProps ); + RemoveProperty( _rAggregateProps, PROPERTY_TABSTOP ); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFixedTextModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_FIXEDTEXT; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OFixedTextModel::write(const Reference<XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) +{ + OControlModel::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0002); + writeHelpTextCompatibly(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OFixedTextModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) +{ + OControlModel::read(_rxInStream); + + // Version + sal_Int16 nVersion = _rxInStream->readShort(); + if (nVersion > 1) + readHelpTextCompatibly(_rxInStream); +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/FixedText.hxx b/forms/source/component/FixedText.hxx new file mode 100644 index 000000000000..5adb15225702 --- /dev/null +++ b/forms/source/component/FixedText.hxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * 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_FIXEDTEXT_HXX_ +#define _FORMS_FIXEDTEXT_HXX_ + +#include "FormComponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +// OFixedTextModel +//================================================================== +class OFixedTextModel + :public OControlModel +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( OFixedTextModel ); + +// XServiceInfo + IMPLEMENTATION_NAME(OFixedTextModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + +// 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); + + // OControlModel's property handling + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + DECLARE_XCLONEABLE(); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_FIXEDTEXT_HXX_ + diff --git a/forms/source/component/FormComponent.cxx b/forms/source/component/FormComponent.cxx new file mode 100644 index 000000000000..148e4c9aa298 --- /dev/null +++ b/forms/source/component/FormComponent.cxx @@ -0,0 +1,3116 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "componenttools.hxx" +#include "FormComponent.hxx" +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "property.hrc" +#include "services.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XTextComponent.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp> +#include <com/sun/star/sdb/XRowSetSupplier.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +/** === end UNO includes === **/ + +#include <comphelper/basicio.hxx> +#include <comphelper/guarding.hxx> +#include <comphelper/listenernotification.hxx> +#include <comphelper/property.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <rtl/logfile.hxx> +#include <toolkit/helper/emptyfontdescriptor.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +#include <functional> +#include <algorithm> + +#include <functional> +#include <algorithm> + + +//... namespace frm ....................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form::binding; + using namespace ::com::sun::star::form::validation; + using namespace ::dbtools; + using namespace ::comphelper; + + //========================================================================= + //= FieldChangeNotifier + //========================================================================= + //------------------------------------------------------------------------- + void ControlModelLock::impl_notifyAll_nothrow() + { + m_rModel.firePropertyChanges( m_aHandles, m_aOldValues, m_aNewValues, OControlModel::LockAccess() ); + } + + //------------------------------------------------------------------------- + void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue ) + { + sal_Int32 nOldLength = m_aHandles.getLength(); + if ( ( nOldLength != m_aOldValues.getLength() ) + || ( nOldLength != m_aNewValues.getLength() ) + ) + throw RuntimeException( ::rtl::OUString(), m_rModel ); + + m_aHandles.realloc( nOldLength + 1 ); + m_aHandles[ nOldLength ] = _nHandle; + m_aOldValues.realloc( nOldLength + 1 ); + m_aOldValues[ nOldLength ] = _rOldValue; + m_aNewValues.realloc( nOldLength + 1 ); + m_aNewValues[ nOldLength ] = _rNewValue; + } + + //========================================================================= + //= FieldChangeNotifier + //========================================================================= + //------------------------------------------------------------------------- + class FieldChangeNotifier + { + public: + FieldChangeNotifier( ControlModelLock& _rLock ) + :m_rLock( _rLock ) + ,m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) ) + { + m_xOldField = m_rModel.getField(); + } + + ~FieldChangeNotifier() + { + Reference< XPropertySet > xNewField( m_rModel.getField() ); + if ( m_xOldField != xNewField ) + m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, makeAny( m_xOldField ), makeAny( xNewField ) ); + } + + private: + ControlModelLock& m_rLock; + OBoundControlModel& m_rModel; + Reference< XPropertySet > m_xOldField; + }; + +//============================================================================= +//= base class for form layer controls +//============================================================================= +DBG_NAME(frm_OControl) +//------------------------------------------------------------------------------ +OControl::OControl( const Reference< XMultiServiceFactory >& _rxFactory, const rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator ) + :OComponentHelper(m_aMutex) + ,m_aContext( _rxFactory ) +{ + DBG_CTOR(frm_OControl, NULL); + // VCL-Control aggregieren + // bei Aggregation den Refcount um eins erhoehen da im setDelegator + // das Aggregat selbst den Refcount erhoeht + increment( m_refCount ); + { + m_xAggregate = m_xAggregate.query( _rxFactory->createInstance( _rAggregateService ) ); + m_xControl = m_xControl.query( m_xAggregate ); + } + decrement( m_refCount ); + + if ( _bSetDelegator ) + doSetDelegator(); +} + +//------------------------------------------------------------------------------ +OControl::~OControl() +{ + DBG_DTOR(frm_OControl, NULL); + doResetDelegator(); +} + +//------------------------------------------------------------------------------ +void OControl::doResetDelegator() +{ + if ( m_xAggregate.is() ) + m_xAggregate->setDelegator( NULL ); +} + +//------------------------------------------------------------------------------ +void OControl::doSetDelegator() +{ + increment( m_refCount ); + if ( m_xAggregate.is() ) + { // those brackets are important for some compilers, don't remove! + // (they ensure that the temporary object created in the line below + // is destroyed *before* the refcount-decrement) + m_xAggregate->setDelegator( static_cast< XWeak* >( this ) ); + } + decrement( m_refCount ); +} + +// UNO Anbindung +//------------------------------------------------------------------------------ +Any SAL_CALL OControl::queryAggregation( const Type& _rType ) throw(RuntimeException) +{ + // ask the base class + Any aReturn( OComponentHelper::queryAggregation(_rType) ); + // ask our own interfaces + if (!aReturn.hasValue()) + { + aReturn = OControl_BASE::queryInterface(_rType); + // ask our aggregate + if (!aReturn.hasValue() && m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + + return aReturn; +} + +//------------------------------------------------------------------------------ +Sequence<sal_Int8> SAL_CALL OControl::getImplementationId() throw(RuntimeException) +{ + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------------------ +Sequence<Type> SAL_CALL OControl::getTypes() throw(RuntimeException) +{ + TypeBag aTypes( _getTypes() ); + + Reference< XTypeProvider > xProv; + if ( query_aggregation( m_xAggregate, xProv ) ) + aTypes.addTypes( xProv->getTypes() ); + + return aTypes.getTypes(); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OControl::_getTypes() +{ + return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes(); +} + +//------------------------------------------------------------------------------ +void OControl::initFormControlPeer( const Reference< XWindowPeer >& /*_rxPeer*/ ) +{ + // nothing to do here +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OControl::disposing() +{ + OComponentHelper::disposing(); + + m_aWindowStateGuard.attach( NULL, NULL ); + + Reference< XComponent > xComp; + if (query_aggregation(m_xAggregate, xComp)) + xComp->dispose(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControl::supportsService(const rtl::OUString& _rsServiceName) throw ( RuntimeException) +{ + Sequence<rtl::OUString> aSupported = getSupportedServiceNames(); + const rtl::OUString* pSupported = aSupported.getConstArray(); + for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported) + if (pSupported->equals(_rsServiceName)) + return sal_True; + return sal_False; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OControl::getAggregateServiceNames() +{ + Sequence< ::rtl::OUString > aAggServices; + Reference< XServiceInfo > xInfo; + if ( query_aggregation( m_xAggregate, xInfo ) ) + aAggServices = xInfo->getSupportedServiceNames(); + return aAggServices; +} + +//------------------------------------------------------------------------------ +Sequence<rtl::OUString> SAL_CALL OControl::getSupportedServiceNames() throw(RuntimeException) +{ + return ::comphelper::concatSequences( + getAggregateServiceNames(), + getSupportedServiceNames_Static() + ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL OControl::getSupportedServiceNames_Static() throw( RuntimeException ) +{ + // no own supported service names + return Sequence< ::rtl::OUString >(); +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OControl::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException) +{ + InterfaceRef xAggAsIface; + query_aggregation(m_xAggregate, xAggAsIface); + + // does the disposing come from the aggregate ? + if (xAggAsIface != InterfaceRef(_rEvent.Source, UNO_QUERY)) + { // no -> forward it + Reference<com::sun::star::lang::XEventListener> xListener; + if (query_aggregation(m_xAggregate, xListener)) + xListener->disposing(_rEvent); + } +} + +// XControl +//------------------------------------------------------------------------------ +void SAL_CALL OControl::setContext(const InterfaceRef& Context) throw (RuntimeException) +{ + if (m_xControl.is()) + m_xControl->setContext(Context); +} + +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL OControl::getContext() throw (RuntimeException) +{ + return m_xControl.is() ? m_xControl->getContext() : InterfaceRef(); +} + +//------------------------------------------------------------------------------ +void OControl::impl_resetStateGuard_nothrow() +{ + Reference< XWindow2 > xWindow; + Reference< XControlModel > xModel; + try + { + xWindow.set( getPeer(), UNO_QUERY ); + xModel.set( getModel(), UNO_QUERY ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_aWindowStateGuard.attach( xWindow, xModel ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent) throw (RuntimeException) +{ + if ( m_xControl.is() ) + { + m_xControl->createPeer( _rxToolkit, _rxParent ); + + initFormControlPeer( getPeer() ); + + impl_resetStateGuard_nothrow(); + } +} + +//------------------------------------------------------------------------------ +Reference<XWindowPeer> SAL_CALL OControl::getPeer() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model) throw ( RuntimeException) +{ + if ( !m_xControl.is() ) + return sal_False; + + sal_Bool bSuccess = m_xControl->setModel( Model ); + impl_resetStateGuard_nothrow(); + return bSuccess; +} + +//------------------------------------------------------------------------------ +Reference<XControlModel> SAL_CALL OControl::getModel() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>(); +} + +//------------------------------------------------------------------------------ +Reference<XView> SAL_CALL OControl::getView() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->getView() : Reference<XView>(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControl::setDesignMode(sal_Bool bOn) throw ( RuntimeException) +{ + if (m_xControl.is()) + m_xControl->setDesignMode(bOn); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControl::isDesignMode() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->isDesignMode() : sal_True; +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControl::isTransparent() throw ( RuntimeException) +{ + return m_xControl.is() ? m_xControl->isTransparent() : sal_True; +} + +//================================================================== +//= OBoundControl +//================================================================== +DBG_NAME(frm_OBoundControl); +//------------------------------------------------------------------ +OBoundControl::OBoundControl( const Reference< XMultiServiceFactory >& _rxFactory, + const ::rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator ) + :OControl( _rxFactory, _rAggregateService, _bSetDelegator ) + ,m_bLocked(sal_False) + ,m_aOriginalFont( EmptyFontDescriptor() ) + ,m_nOriginalTextLineColor( 0 ) +{ + DBG_CTOR(frm_OBoundControl, NULL); +} + +//------------------------------------------------------------------ +OBoundControl::~OBoundControl() +{ + DBG_DTOR(frm_OBoundControl, NULL); +} +// ----------------------------------------------------------------------------- +Sequence< Type> OBoundControl::_getTypes() +{ + return TypeBag( OControl::_getTypes(), OBoundControl_BASE::getTypes() ).getTypes(); +} +//------------------------------------------------------------------ +Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn; + + // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types + if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) ) + aReturn = OControl::queryAggregation( _rType ); + + // ask our own interfaces + // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener) + if ( !aReturn.hasValue() ) + aReturn = OBoundControl_BASE::queryInterface( _rType ); + + // ask the base class + if ( !aReturn.hasValue() ) + aReturn = OControl::queryAggregation( _rType ); + + return aReturn; +} + +//------------------------------------------------------------------ +sal_Bool SAL_CALL OBoundControl::getLock() throw(RuntimeException) +{ + return m_bLocked; +} + +//------------------------------------------------------------------ +void SAL_CALL OBoundControl::setLock(sal_Bool _bLock) throw(RuntimeException) +{ + if (m_bLocked == _bLock) + return; + + osl::MutexGuard aGuard(m_aMutex); + _setLock(_bLock); + m_bLocked = _bLock; +} + +//------------------------------------------------------------------ +void OBoundControl::_setLock(sal_Bool _bLock) +{ + // try to set the text component to readonly + Reference< XWindowPeer > xPeer = getPeer(); + Reference< XTextComponent > xText( xPeer, UNO_QUERY ); + + if ( xText.is() ) + xText->setEditable( !_bLock ); + else + { + // disable the window + Reference< XWindow > xComp( xPeer, UNO_QUERY ); + if ( xComp.is() ) + xComp->setEnable( !_bLock ); + } +} + +//-------------------------------------------------------------------- +sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel ) throw (RuntimeException) +{ + return OControl::setModel( _rxModel ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControl::disposing(const EventObject& Source) throw (RuntimeException) +{ + // just disambiguate + OControl::disposing(Source); +} + +//-------------------------------------------------------------------- +void OBoundControl::disposing() +{ + OControl::disposing(); +} + +//================================================================== +//= OControlModel +//================================================================== +DBG_NAME(OControlModel) +//------------------------------------------------------------------ +Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getImplementationId" ); + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------ +Sequence<Type> SAL_CALL OControlModel::getTypes() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getTypes" ); + TypeBag aTypes( _getTypes() ); + + Reference< XTypeProvider > xProv; + if ( query_aggregation( m_xAggregate, xProv ) ) + aTypes.addTypes( xProv->getTypes() ); + + return aTypes.getTypes(); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OControlModel::_getTypes() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::_getTypes" ); + return TypeBag( OComponentHelper::getTypes(), + OPropertySetAggregationHelper::getTypes(), + OControlModel_BASE::getTypes() + ).getTypes(); +} + +//------------------------------------------------------------------ +Any SAL_CALL OControlModel::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::queryAggregation" ); + // base class 1 + Any aReturn(OComponentHelper::queryAggregation(_rType)); + + // base class 2 + if (!aReturn.hasValue()) + { + aReturn = OControlModel_BASE::queryInterface(_rType); + + // our own interfaces + if (!aReturn.hasValue()) + { + aReturn = OPropertySetAggregationHelper::queryInterface(_rType); + // our aggregate + if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(::getCppuType(static_cast< Reference< XCloneable>* >(NULL)))) + aReturn = m_xAggregate->queryAggregation(_rType); + } + } + return aReturn; +} + +//------------------------------------------------------------------------------ +void OControlModel::readHelpTextCompatibly(const staruno::Reference< stario::XObjectInputStream >& _rxInStream) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::readHelpTextCompatibly" ); + ::rtl::OUString sHelpText; + ::comphelper::operator>>( _rxInStream, sHelpText); + try + { + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, makeAny(sHelpText)); + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!"); + } +} + +//------------------------------------------------------------------------------ +void OControlModel::writeHelpTextCompatibly(const staruno::Reference< stario::XObjectOutputStream >& _rxOutStream) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::writeHelpTextCompatibly" ); + ::rtl::OUString sHelpText; + try + { + if (m_xAggregateSet.is()) + m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText; + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!"); + } + ::comphelper::operator<<( _rxOutStream, sHelpText); +} + +//------------------------------------------------------------------ +OControlModel::OControlModel( + const Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory, + const ::rtl::OUString& _rUnoControlModelTypeName, + const ::rtl::OUString& rDefault, const sal_Bool _bSetDelegator) + :OComponentHelper(m_aMutex) + ,OPropertySetAggregationHelper(OComponentHelper::rBHelper) + ,m_aContext( _rxFactory ) + ,m_lockCount( 0 ) + ,m_aPropertyBagHelper( *this ) + ,m_nTabIndex(FRM_DEFAULT_TABINDEX) + ,m_nClassId(FormComponentType::CONTROL) + ,m_bNativeLook( sal_False ) + // form controls are usually embedded into documents, not dialogs, and in documents + // the native look is ugly .... + // #i37342# / 2004-11-19 / frank.schoenheit@sun.com +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::OControlModel" ); + DBG_CTOR(OControlModel, NULL); + if (_rUnoControlModelTypeName.getLength()) // the is a model we have to aggregate + { + increment(m_refCount); + + { + m_xAggregate = Reference<XAggregation>(_rxFactory->createInstance(_rUnoControlModelTypeName), UNO_QUERY); + setAggregation(m_xAggregate); + + if ( m_xAggregateSet.is() ) + { + try + { + if ( rDefault.getLength() ) + m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( rDefault ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OControlModel::OControlModel: caught an exception!" ); + } + } + } + + if (_bSetDelegator) + doSetDelegator(); + + // Refcount wieder bei NULL + decrement(m_refCount); + } +} + +//------------------------------------------------------------------ +OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory, const sal_Bool _bCloneAggregate, const sal_Bool _bSetDelegator ) + :OComponentHelper( m_aMutex ) + ,OPropertySetAggregationHelper( OComponentHelper::rBHelper ) + ,m_aContext( _rxFactory ) + ,m_lockCount( 0 ) + ,m_aPropertyBagHelper( *this ) + ,m_nTabIndex( FRM_DEFAULT_TABINDEX ) + ,m_nClassId( FormComponentType::CONTROL ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::OControlModel(copy)" ); + DBG_CTOR( OControlModel, NULL ); + DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" ); + + // copy members + m_aName = _pOriginal->m_aName; + m_aTag = _pOriginal->m_aTag; + m_nTabIndex = _pOriginal->m_nTabIndex; + m_nClassId = _pOriginal->m_nClassId; + m_bNativeLook = _pOriginal->m_bNativeLook; + + if ( _bCloneAggregate ) + { + // temporarily increment refcount because of temporary references to ourself in the following + increment( m_refCount ); + + { + // transfer the (only, at the very moment!) ref count + m_xAggregate = createAggregateClone( _pOriginal ); + + // set aggregation (retrieve other direct interfaces of the aggregate) + setAggregation( m_xAggregate ); + } + + // set the delegator, if allowed by our derived class + if ( _bSetDelegator ) + doSetDelegator(); + + // decrement ref count + decrement( m_refCount ); + } +} + +//------------------------------------------------------------------ +OControlModel::~OControlModel() +{ + // release the aggregate + doResetDelegator( ); + + DBG_DTOR(OControlModel, NULL); +} + +//------------------------------------------------------------------ +void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::clonedFrom" ); + // nothing to do in this base class +} + +//------------------------------------------------------------------------------ +void OControlModel::doResetDelegator() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::doResetDelegator" ); + if (m_xAggregate.is()) + m_xAggregate->setDelegator(NULL); +} + +//------------------------------------------------------------------------------ +void OControlModel::doSetDelegator() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::doSetDelegator" ); + increment(m_refCount); + if (m_xAggregate.is()) + { + m_xAggregate->setDelegator(static_cast<XWeak*>(this)); + } + decrement(m_refCount); +} + +// XChild +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL OControlModel::getParent() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getParent" ); + return m_xParent; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControlModel::setParent(const InterfaceRef& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setParent" ); + osl::MutexGuard aGuard(m_aMutex); + + Reference<XComponent> xComp(m_xParent, UNO_QUERY); + if (xComp.is()) + xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this)); + + m_xParent = _rxParent; + xComp = xComp.query( m_xParent ); + + if ( xComp.is() ) + xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this)); +} + +// XNamed +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OControlModel::getName() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getName" ); + ::rtl::OUString aReturn; + OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= aReturn; + return aReturn; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControlModel::setName(const ::rtl::OUString& _rName) throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setName" ); + setFastPropertyValue(PROPERTY_ID_NAME, makeAny(_rName)); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OControlModel::supportsService(const rtl::OUString& _rServiceName) throw ( RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::supportsService" ); + Sequence<rtl::OUString> aSupported = getSupportedServiceNames(); + const rtl::OUString* pSupported = aSupported.getConstArray(); + for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported) + if (pSupported->equals(_rServiceName)) + return sal_True; + return sal_False; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OControlModel::getAggregateServiceNames() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getAggregateServiceNames" ); + Sequence< ::rtl::OUString > aAggServices; + Reference< XServiceInfo > xInfo; + if ( query_aggregation( m_xAggregate, xInfo ) ) + aAggServices = xInfo->getSupportedServiceNames(); + return aAggServices; +} + +//------------------------------------------------------------------------------ +Sequence<rtl::OUString> SAL_CALL OControlModel::getSupportedServiceNames() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames" ); + return ::comphelper::concatSequences( + getAggregateServiceNames(), + getSupportedServiceNames_Static() + ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL OControlModel::getSupportedServiceNames_Static() throw( RuntimeException ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames_Static" ); + Sequence< ::rtl::OUString > aServiceNames( 2 ); + aServiceNames[ 0 ] = FRM_SUN_FORMCOMPONENT; + aServiceNames[ 1 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.FormControlModel" ); + return aServiceNames; +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OControlModel::disposing(const com::sun::star::lang::EventObject& _rSource) throw (RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" ); + // release the parent + if (_rSource.Source == m_xParent) + { + osl::MutexGuard aGuard(m_aMutex); + m_xParent = NULL; + } + else + { + Reference<com::sun::star::lang::XEventListener> xEvtLst; + if (query_aggregation(m_xAggregate, xEvtLst)) + { + osl::MutexGuard aGuard(m_aMutex); + xEvtLst->disposing(_rSource); + } + } +} + +// OComponentHelper +//----------------------------------------------------------------------------- +void OControlModel::disposing() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" ); + OPropertySetAggregationHelper::disposing(); + + Reference<com::sun::star::lang::XComponent> xComp; + if (query_aggregation(m_xAggregate, xComp)) + xComp->dispose(); + + setParent(Reference<XFormComponent>()); + + m_aPropertyBagHelper.dispose(); +} + +//------------------------------------------------------------------------------ +void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::writeAggregate" ); + Reference< XPersistObject > xPersist; + if ( query_aggregation( m_xAggregate, xPersist ) ) + xPersist->write( _rxOutStream ); +} + +//------------------------------------------------------------------------------ +void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::readAggregate" ); + Reference< XPersistObject > xPersist; + if ( query_aggregation( m_xAggregate, xPersist ) ) + xPersist->read( _rxInStream ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream) + throw(stario::IOException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::write" ); + osl::MutexGuard aGuard(m_aMutex); + + // 1. Schreiben des UnoControls + Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + if ( !xMark.is() ) + { + throw IOException( + FRM_RES_STRING( RID_STR_INVALIDSTREAM ), + static_cast< ::cppu::OWeakObject* >( this ) + ); + } + + sal_Int32 nMark = xMark->createMark(); + sal_Int32 nLen = 0; + + _rxOutStream->writeLong(nLen); + + writeAggregate( _rxOutStream ); + + // feststellen der Laenge + nLen = xMark->offsetToMark(nMark) - 4; + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); + + // 2. Schreiben einer VersionsNummer + _rxOutStream->writeShort(0x0003); + + // 3. Schreiben der allgemeinen Properties + ::comphelper::operator<<( _rxOutStream, m_aName); + _rxOutStream->writeShort(m_nTabIndex); + ::comphelper::operator<<( _rxOutStream, m_aTag); // 3. version + + // !!! IMPORTANT NOTE !!! + // don't write any new members here : this wouldn't be compatible with older versions, as OControlModel + // is a base class which is called in derived classes "read" method. So if you increment the version + // and write new stuff, older office versions will read this in the _derived_ classes, which may result + // in anything from data loss to crash. + // !!! EOIN !!! +} + +//------------------------------------------------------------------------------ +void OControlModel::read(const Reference<stario::XObjectInputStream>& InStream) throw (::com::sun::star::io::IOException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::read" ); + osl::MutexGuard aGuard(m_aMutex); + + Reference<stario::XMarkableStream> xMark(InStream, UNO_QUERY); + if ( !xMark.is() ) + { + throw IOException( + FRM_RES_STRING( RID_STR_INVALIDSTREAM ), + static_cast< ::cppu::OWeakObject* >( this ) + ); + } + + // 1. Lesen des UnoControls + sal_Int32 nLen = InStream->readLong(); + if (nLen) + { + sal_Int32 nMark = xMark->createMark(); + + try + { + readAggregate( InStream ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + xMark->jumpToMark(nMark); + InStream->skipBytes(nLen); + xMark->deleteMark(nMark); + } + + // 2. Lesen des Versionsnummer + UINT16 nVersion = InStream->readShort(); + + // 3. Lesen der allgemeinen Properties + ::comphelper::operator>>( InStream, m_aName); + m_nTabIndex = InStream->readShort(); + + if (nVersion > 0x0002) + ::comphelper::operator>>( InStream, m_aTag); + + // we had a version where we wrote the help text + if (nVersion == 0x0004) + readHelpTextCompatibly(InStream); + + DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !"); + // 4 was the version where we wrote the help text + // later versions shouldn't exist (see write for a detailed comment) +} + +//------------------------------------------------------------------------------ +PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle ) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyStateByHandle" ); + // simply compare the current and the default value + Any aCurrentValue = getPropertyDefaultByHandle( _nHandle ); + Any aDefaultValue; getFastPropertyValue( aDefaultValue, _nHandle ); + + sal_Bool bEqual = uno_type_equalData( + const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(), + const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(), + reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) + ); + return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE; +} + +//------------------------------------------------------------------------------ +void OControlModel::setPropertyToDefaultByHandle( sal_Int32 _nHandle) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setPropertyToDefaultByHandle" ); + Any aDefault = getPropertyDefaultByHandle( _nHandle ); + + Any aConvertedValue, aOldValue; + if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) ) + { + setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue ); + // TODO: fire the property change + } +} + +//------------------------------------------------------------------------------ +Any OControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyDefaultByHandle" ); + Any aReturn; + switch ( _nHandle ) + { + case PROPERTY_ID_NAME: + case PROPERTY_ID_TAG: + aReturn <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_CLASSID: + aReturn <<= (sal_Int16)FormComponentType::CONTROL; + break; + + case PROPERTY_ID_TABINDEX: + aReturn <<= (sal_Int16)FRM_DEFAULT_TABINDEX; + break; + + case PROPERTY_ID_NATIVE_LOOK: + aReturn <<= (sal_Bool)sal_True; + break; + + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) + m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn ); + else + OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" ); + } + return aReturn; +} + +//------------------------------------------------------------------------------ +void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getFastPropertyValue" ); + switch ( _nHandle ) + { + case PROPERTY_ID_NAME: + _rValue <<= m_aName; + break; + case PROPERTY_ID_TAG: + _rValue <<= m_aTag; + break; + case PROPERTY_ID_CLASSID: + _rValue <<= m_nClassId; + break; + case PROPERTY_ID_TABINDEX: + _rValue <<= m_nTabIndex; + break; + case PROPERTY_ID_NATIVE_LOOK: + _rValue <<= (sal_Bool)m_bNativeLook; + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) + m_aPropertyBagHelper.getDynamicFastPropertyValue( _nHandle, _rValue ); + else + OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle ); + break; + } +} + +//------------------------------------------------------------------------------ +sal_Bool OControlModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) + throw (com::sun::star::lang::IllegalArgumentException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::convertFastPropertyValue" ); + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_NAME: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName); + break; + case PROPERTY_ID_TAG: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag); + break; + case PROPERTY_ID_TABINDEX: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex); + break; + case PROPERTY_ID_NATIVE_LOOK: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook); + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) + bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue ); + else + OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" ); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) + throw (Exception) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setFastPropertyValue_NoBroadcast" ); + switch (_nHandle) + { + case PROPERTY_ID_NAME: + DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL), + "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); + _rValue >>= m_aName; + break; + case PROPERTY_ID_TAG: + DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL), + "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); + _rValue >>= m_aTag; + break; + case PROPERTY_ID_TABINDEX: + DBG_ASSERT(_rValue.getValueType() == getCppuType((const sal_Int16*)NULL), + "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" ); + _rValue >>= m_nTabIndex; + break; + case PROPERTY_ID_NATIVE_LOOK: + OSL_VERIFY( _rValue >>= m_bNativeLook ); + break; + default: + if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) ) + m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue ); + else + OSL_ENSURE( false, "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle!" ); + break; + } +} + +//------------------------------------------------------------------------------ +void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeFixedProperties" ); + BEGIN_DESCRIBE_BASE_PROPERTIES( 4 ) + DECL_PROP2 (CLASSID, sal_Int16, READONLY, TRANSIENT); + DECL_PROP1 (NAME, ::rtl::OUString, BOUND); + DECL_BOOL_PROP2 (NATIVE_LOOK, BOUND, TRANSIENT); + DECL_PROP1 (TAG, ::rtl::OUString, BOUND); + END_DESCRIBE_PROPERTIES() +} + +//------------------------------------------------------------------------------ +void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeAggregateProperties" ); + if ( m_xAggregateSet.is() ) + { + Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() ); + if ( xPSI.is() ) + _rAggregateProps = xPSI->getProperties(); + } +} + +//------------------------------------------------------------------------------ +::osl::Mutex& OControlModel::getMutex() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getMutex" ); + return m_aMutex; +} + +//------------------------------------------------------------------------------ +void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeFixedAndAggregateProperties" ); + describeFixedProperties( _out_rFixedProperties ); + describeAggregateProperties( _out_rAggregateProperties ); +} + +//------------------------------------------------------------------------------ +Reference< XMultiPropertySet > OControlModel::getPropertiesInterface() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertiesInterface" ); + return Reference< XMultiPropertySet >( *this, UNO_QUERY ); +} + +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo() throw( RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertySetInfo" ); + return createPropertySetInfo( getInfoHelper() ); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OControlModel::getInfoHelper() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getInfoHelper" ); + return m_aPropertyBagHelper.getInfoHelper(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OControlModel::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::addProperty" ); + m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OControlModel::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::removeProperty" ); + m_aPropertyBagHelper.removeProperty( _rName ); +} + +//-------------------------------------------------------------------- +Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues() throw (RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyValues" ); + return m_aPropertyBagHelper.getPropertyValues(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setPropertyValues" ); + m_aPropertyBagHelper.setPropertyValues( _rProps ); +} + +//-------------------------------------------------------------------- +void OControlModel::lockInstance( LockAccess ) +{ + m_aMutex.acquire(); + osl_incrementInterlockedCount( &m_lockCount ); +} + +//-------------------------------------------------------------------- +oslInterlockedCount OControlModel::unlockInstance( LockAccess ) +{ + OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" ); + oslInterlockedCount lockCount = osl_decrementInterlockedCount( &m_lockCount ); + m_aMutex.release(); + return lockCount; +} + +//-------------------------------------------------------------------- +void OControlModel::firePropertyChanges( const Sequence< sal_Int32 >& _rHandles, const Sequence< Any >& _rOldValues, + const Sequence< Any >& _rNewValues, LockAccess ) +{ + OPropertySetHelper::fire( + const_cast< Sequence< sal_Int32 >& >( _rHandles ).getArray(), + _rNewValues.getConstArray(), + _rOldValues.getConstArray(), + _rHandles.getLength(), + sal_False + ); +} + +//================================================================== +//= OBoundControlModel +//================================================================== +DBG_NAME(frm_OBoundControlModel); +//------------------------------------------------------------------ +Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn( OControlModel::queryAggregation(_rType) ); + if (!aReturn.hasValue()) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::queryAggregation" ); + aReturn = OBoundControlModel_BASE1::queryInterface(_rType); + + if ( !aReturn.hasValue() && m_bCommitable ) + aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType ); + + if ( !aReturn.hasValue() && m_bSupportsExternalBinding ) + aReturn = OBoundControlModel_BINDING::queryInterface( _rType ); + + if ( !aReturn.hasValue() && m_bSupportsValidation ) + aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType ); + } + + return aReturn; +} + +//------------------------------------------------------------------ +OBoundControlModel::OBoundControlModel( + const Reference< XMultiServiceFactory>& _rxFactory, + const ::rtl::OUString& _rUnoControlModelTypeName, const ::rtl::OUString& _rDefault, + const sal_Bool _bCommitable, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation ) + :OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False ) + ,OPropertyChangeListener( m_aMutex ) + ,m_xField() + ,m_xAmbientForm() + ,m_nValuePropertyAggregateHandle( -1 ) + ,m_nFieldType( DataType::OTHER ) + ,m_bValuePropertyMayBeVoid( false ) + ,m_aResetHelper( *this, m_aMutex ) + ,m_aUpdateListeners(m_aMutex) + ,m_aFormComponentListeners( m_aMutex ) + ,m_bInputRequired( sal_True ) + ,m_pAggPropMultiplexer( NULL ) + ,m_bFormListening( false ) + ,m_bLoaded(sal_False) + ,m_bRequired(sal_False) + ,m_bCommitable(_bCommitable) + ,m_bSupportsExternalBinding( _bSupportExternalBinding ) + ,m_bSupportsValidation( _bSupportsValidation ) + ,m_bForwardValueChanges(sal_True) + ,m_bTransferingValue( sal_False ) + ,m_bIsCurrentValueValid( sal_True ) + ,m_bBindingControlsRO( sal_False ) + ,m_bBindingControlsEnable( sal_False ) + ,m_eControlValueChangeInstigator( eOther ) + ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT) +{ + DBG_CTOR(frm_OBoundControlModel, NULL); + + // start property listening at the aggregate + implInitAggMultiplexer( ); +} + +//------------------------------------------------------------------ +OBoundControlModel::OBoundControlModel( + const OBoundControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory, sal_True, sal_False ) + ,OPropertyChangeListener( m_aMutex ) + ,m_xField() + ,m_xAmbientForm() + ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle ) + ,m_nFieldType( DataType::OTHER ) + ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid ) + ,m_aResetHelper( *this, m_aMutex ) + ,m_aUpdateListeners( m_aMutex ) + ,m_aFormComponentListeners( m_aMutex ) + ,m_xValidator( _pOriginal->m_xValidator ) + ,m_bInputRequired( sal_True ) + ,m_pAggPropMultiplexer( NULL ) + ,m_bFormListening( false ) + ,m_bLoaded( sal_False ) + ,m_bRequired( sal_False ) + ,m_bCommitable( _pOriginal->m_bCommitable ) + ,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding ) + ,m_bSupportsValidation( _pOriginal->m_bSupportsValidation ) + ,m_bForwardValueChanges( sal_True ) + ,m_bTransferingValue( sal_False ) + ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid ) + ,m_bBindingControlsRO( sal_False ) + ,m_bBindingControlsEnable( sal_False ) + ,m_eControlValueChangeInstigator( eOther ) +{ + DBG_CTOR(frm_OBoundControlModel, NULL); + + // start property listening at the aggregate + implInitAggMultiplexer( ); + + m_aLabelServiceName = _pOriginal->m_aLabelServiceName; + m_sValuePropertyName = _pOriginal->m_sValuePropertyName; + m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle; + m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid; + m_aValuePropertyType = _pOriginal->m_aValuePropertyType; + m_aControlSource = _pOriginal->m_aControlSource; + m_bInputRequired = _pOriginal->m_bInputRequired; + // m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transfered. + // (the former should be clear - a clone of the object we're only referencing does not make sense) + // (the second would violate the restriction for label controls that they're part of the + // same form component hierarchy - we ourself are no part, yet, so we can't have a label control) + + // start listening for changes at the value property + implInitValuePropertyListening( ); +} + +//------------------------------------------------------------------ +OBoundControlModel::~OBoundControlModel() +{ + if ( !OComponentHelper::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } + + doResetDelegator( ); + + OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" ); + if ( m_pAggPropMultiplexer ) + { + m_pAggPropMultiplexer->dispose(); + m_pAggPropMultiplexer->release(); + m_pAggPropMultiplexer = NULL; + } + + DBG_DTOR(frm_OBoundControlModel, NULL); +} + +//------------------------------------------------------------------ +void OBoundControlModel::clonedFrom( const OControlModel* _pOriginal ) +{ + const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal ); + // the value binding can be handled as if somebody called setValueBinding here + // By definition, bindings can be share between bindables + if ( pBoundOriginal && pBoundOriginal->m_xExternalBinding.is() ) + { + try + { + setValueBinding( pBoundOriginal->m_xExternalBinding ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::implInitAggMultiplexer( ) +{ + increment( m_refCount ); + if ( m_xAggregateSet.is() ) + { + m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, sal_False ); + m_pAggPropMultiplexer->acquire(); + } + decrement( m_refCount ); + + doSetDelegator(); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::implInitValuePropertyListening( ) const +{ + // start listening for changes at the value property + // There are three pre-requisites for this to be done: + // 1. We support external value bindings. In this case, the changes in the control value need to + // be propagated to the external binding immediately when they happen + // 2. We support external validation. In this case, we need to listen for changes in the value + // property, since we need to revalidate then. + // 3. We are not committable. In this case, changes in the control value need to be propagated + // to the database column immediately when they happen. + if ( m_bSupportsExternalBinding || m_bSupportsValidation || !m_bCommitable ) + { + OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" ); + if ( m_pAggPropMultiplexer && m_sValuePropertyName.getLength() ) + m_pAggPropMultiplexer->addProperty( m_sValuePropertyName ); + } +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::initValueProperty( const ::rtl::OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle ) +{ + OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle, + "OBoundControlModel::initValueProperty: already called before!" ); + OSL_ENSURE( _rValuePropertyName.getLength(), "OBoundControlModel::initValueProperty: invalid property name!" ); + OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" ); + + m_sValuePropertyName = _rValuePropertyName; + m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle ); + OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" ); + + if ( m_nValuePropertyAggregateHandle != -1 ) + { + Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW ); + Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName ); + m_aValuePropertyType = aValuePropDesc.Type; + m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0; + } + + // start listening for changes at the value property + implInitValuePropertyListening( ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::suspendValueListening( ) +{ + OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::suspendValueListening: don't have a value property!" ); + OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" ); + + if ( m_pAggPropMultiplexer ) + m_pAggPropMultiplexer->lock(); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::resumeValueListening( ) +{ + OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::resumeValueListening: don't have a value property!" ); + OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" ); + OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" ); + + if ( m_pAggPropMultiplexer ) + m_pAggPropMultiplexer->unlock(); +} + +//----------------------------------------------------------------------------- +Sequence< Type > OBoundControlModel::_getTypes() +{ + TypeBag aTypes( + OControlModel::_getTypes(), + OBoundControlModel_BASE1::getTypes() + ); + + if ( m_bCommitable ) + aTypes.addTypes( OBoundControlModel_COMMITTING::getTypes() ); + + if ( m_bSupportsExternalBinding ) + aTypes.addTypes( OBoundControlModel_BINDING::getTypes() ); + + if ( m_bSupportsValidation ) + aTypes.addTypes( OBoundControlModel_VALIDATION::getTypes() ); + + return aTypes.getTypes(); +} + +// OComponentHelper +//----------------------------------------------------------------------------- +void OBoundControlModel::disposing() +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::_getTypes" ); + OControlModel::disposing(); + + ::osl::ClearableMutexGuard aGuard(m_aMutex); + + if ( m_pAggPropMultiplexer ) + m_pAggPropMultiplexer->dispose(); + + // notify all our listeners + com::sun::star::lang::EventObject aEvt( static_cast< XWeak* >( this ) ); + m_aUpdateListeners.disposeAndClear( aEvt ); + m_aResetHelper.disposing(); + + // disconnect from our database column + // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify? + // The only more thing which it does is calling onDisconnectedDbColumn - could this + // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*. + if ( hasField() ) + { + getField()->removePropertyChangeListener( PROPERTY_VALUE, this ); + resetField(); + } + m_xCursor = NULL; + + Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY ); + if ( xComp.is() ) + xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) ); + + // disconnect from our external value binding + if ( hasExternalValueBinding() ) + disconnectExternalValueBinding(); + + // dito for the validator + if ( hasValidator() ) + disconnectValidator( ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) throw ( RuntimeException ) +{ + ControlModelLock aLock( *this ); + + OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName, + "OBoundControlModel::_propertyChanged: where did this come from (1)?" ); + OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(), + "OBoundControlModel::_propertyChanged: where did this come from (2)?" ); + + if ( _rEvt.PropertyName == m_sValuePropertyName ) + { // our control value changed + + if ( hasExternalValueBinding() ) + { // the control value changed, while we have an external value binding + // -> forward the value to it + if ( m_eControlValueChangeInstigator != eExternalBinding ) + transferControlValueToExternal( aLock ); + } + else if ( !m_bCommitable && m_xColumnUpdate.is() ) + { // the control value changed, while we are bound to a database column, + // but not committable (which means changes in the control have to be reflected to + // the underlying database column immediately) + // -> forward the value to the database column + if ( m_eControlValueChangeInstigator != eDbColumnBinding ) + commitControlValueToDbColumn( false ); + } + + // validate the new value + if ( m_bSupportsValidation ) + recheckValidity( true ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::startAggregatePropertyListening( const ::rtl::OUString& _rPropertyName ) +{ + OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" ); + OSL_ENSURE( _rPropertyName.getLength(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" ); + + if ( m_pAggPropMultiplexer && _rPropertyName.getLength() ) + { + m_pAggPropMultiplexer->addProperty( _rPropertyName ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::doFormListening( const bool _bStart ) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" ); + + if ( isFormListening() == _bStart ) + return; + + if ( m_xAmbientForm.is() ) + _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this ); + + Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY ); + if ( getParent().is() && !xParentLoadable.is() ) + { + // if our parent does not directly support the XLoadable interface, then it might support the + // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes + // broadcasted by the latter. + Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY ); + if ( xRowSetBroadcaster.is() ) + _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this ); + } + + m_bFormListening = _bStart && m_xAmbientForm.is(); +} + +// XChild +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + if ( getParent() == _rxParent ) + return; + + // disconnect from database column (which is controlled by parent, directly or indirectly) + if ( hasField() ) + impl_disconnectDatabaseColumn_noNotify(); + + // log off old listeners + if ( isFormListening() ) + doFormListening( false ); + + // actually set the new parent + OControlModel::setParent( _rxParent ); + + // a new parent means a new ambient form + impl_determineAmbientForm_nothrow(); + + if ( !hasExternalValueBinding() ) + { + // log on new listeners + doFormListening( true ); + + // re-connect to database column of the new parent + if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) + impl_connectDatabaseColumn_noNotify( false ); + } +} + +// XEventListener +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException) +{ + ControlModelLock aLock( *this ); + + if ( _rEvent.Source == getField() ) + { + resetField(); + } + else if ( _rEvent.Source == m_xLabelControl ) + { + Reference<XPropertySet> xOldValue = m_xLabelControl; + m_xLabelControl = NULL; + + // fire a propertyChanged (when we leave aLock's scope) + aLock.addPropertyNotification( PROPERTY_ID_CONTROLLABEL, makeAny( xOldValue ), makeAny( m_xLabelControl ) ); + } + else if ( _rEvent.Source == m_xExternalBinding ) + { // *first* check for the external binding + disconnectExternalValueBinding( ); + } + else if ( _rEvent.Source == m_xValidator ) + { // *then* check for the validator. Reason is that bindings may also act as validator at the same + // time, in this case, the validator is automatically revoked when the binding is revoked + disconnectValidator( ); + } + else + OControlModel::disposing(_rEvent); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OBoundControlModel::getSupportedServiceNames() throw(RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" ); + return ::comphelper::concatSequences( + getAggregateServiceNames(), + getSupportedServiceNames_Static() + ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL OBoundControlModel::getSupportedServiceNames_Static() throw( RuntimeException ) +{ + Sequence< ::rtl::OUString > aOwnServiceNames( 1 ); + aOwnServiceNames[ 0 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.DataAwareControlModel" ); + + return ::comphelper::concatSequences( + OControlModel::getSupportedServiceNames_Static(), + aOwnServiceNames + ); +} + +// XPersist +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::write( const Reference<stario::XObjectOutputStream>& _rxOutStream ) throw(stario::IOException, RuntimeException) +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames_Static" ); + OControlModel::write(_rxOutStream); + + osl::MutexGuard aGuard(m_aMutex); + + // Version + _rxOutStream->writeShort(0x0002); + + // Controlsource + ::comphelper::operator<<( _rxOutStream, m_aControlSource); + + // !!! IMPORTANT NOTE !!! + // don't write any new members here : this wouldn't be compatible with older versions, as OBoundControlModel + // is a base class which is called in derived classes "read" method. So if you increment the version + // and write new stuff, older office versions will read this in the _derived_ classes, which may result + // in anything from data loss to crash. + // (use writeCommonProperties instead, this is called in derived classes write-method) + // !!! EOIN !!! + // FS - 68876 - 28.09.1999 +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::defaultCommonProperties() +{ + Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); + if (xComp.is()) + xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); + m_xLabelControl = NULL; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::readCommonProperties(const Reference<stario::XObjectInputStream>& _rxInStream) +{ + sal_Int32 nLen = _rxInStream->readLong(); + + Reference<stario::XMarkableStream> xMark(_rxInStream, UNO_QUERY); + DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !"); + sal_Int32 nMark = xMark->createMark(); + + // read the reference to the label control + Reference<stario::XPersistObject> xPersist; + sal_Int32 nUsedFlag; + nUsedFlag = _rxInStream->readLong(); + if (nUsedFlag) + xPersist = _rxInStream->readObject(); + m_xLabelControl = m_xLabelControl.query( xPersist ); + Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY ); + if (xComp.is()) + xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); + + // read any other new common properties here + + // skip the remaining bytes + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nLen); + xMark->deleteMark(nMark); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::writeCommonProperties(const Reference<stario::XObjectOutputStream>& _rxOutStream) +{ + Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !"); + sal_Int32 nMark = xMark->createMark(); + + // a placeholder where we will write the overall length (later in this method) + sal_Int32 nLen = 0; + _rxOutStream->writeLong(nLen); + + // write the reference to the label control + Reference<stario::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY); + sal_Int32 nUsedFlag = 0; + if (xPersist.is()) + nUsedFlag = 1; + _rxOutStream->writeLong(nUsedFlag); + if (xPersist.is()) + _rxOutStream->writeObject(xPersist); + + // write any other new common properties here + + // write the correct length at the beginning of the block + nLen = xMark->offsetToMark(nMark) - sizeof(nLen); + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::read( const Reference< stario::XObjectInputStream >& _rxInStream ) throw(stario::IOException, RuntimeException) +{ + OControlModel::read(_rxInStream); + + osl::MutexGuard aGuard(m_aMutex); + UINT16 nVersion = _rxInStream->readShort(); (void)nVersion; + ::comphelper::operator>>( _rxInStream, m_aControlSource); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OBoundControlModel::getFastPropertyValue" ); + switch (nHandle) + { + case PROPERTY_ID_INPUT_REQUIRED: + rValue <<= m_bInputRequired; + break; + case PROPERTY_ID_CONTROLSOURCEPROPERTY: + rValue <<= m_sValuePropertyName; + break; + case PROPERTY_ID_CONTROLSOURCE: + rValue <<= m_aControlSource; + break; + case PROPERTY_ID_BOUNDFIELD: + rValue <<= getField(); + break; + case PROPERTY_ID_CONTROLLABEL: + if (!m_xLabelControl.is()) + rValue.clear(); + else + rValue <<= m_xLabelControl; + break; + default: + OControlModel::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OBoundControlModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, + const Any& _rValue) + throw (com::sun::star::lang::IllegalArgumentException) +{ + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_INPUT_REQUIRED: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired ); + break; + case PROPERTY_ID_CONTROLSOURCE: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource); + break; + case PROPERTY_ID_BOUNDFIELD: + DBG_ERROR( "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" ); + throw com::sun::star::lang::IllegalArgumentException(); + case PROPERTY_ID_CONTROLLABEL: + if (!_rValue.hasValue()) + { // property set to void + _rConvertedValue = Any(); + getFastPropertyValue(_rOldValue, _nHandle); + bModified = m_xLabelControl.is(); + } + else + { + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl); + if (!m_xLabelControl.is()) + // an empty interface is interpreted as VOID + _rOldValue.clear(); + } + break; + default: + bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); + } + return bModified; +} + +//------------------------------------------------------------------------------ +Any OBoundControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const +{ + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::convertFastPropertyValue" ); + Any aDefault; + switch ( _nHandle ) + { + case PROPERTY_ID_INPUT_REQUIRED: + aDefault <<= sal_Bool( sal_True ); + break; + + case PROPERTY_ID_CONTROLSOURCE: + aDefault <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_CONTROLLABEL: + aDefault <<= Reference< XPropertySet >(); + break; + } + return aDefault; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_INPUT_REQUIRED: + OSL_VERIFY( rValue >>= m_bInputRequired ); + break; + case PROPERTY_ID_CONTROLSOURCE: + OSL_VERIFY( rValue >>= m_aControlSource ); + break; + case PROPERTY_ID_BOUNDFIELD: + DBG_ERROR("OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !"); + throw com::sun::star::lang::IllegalArgumentException(); + case PROPERTY_ID_CONTROLLABEL: + { + DBG_ASSERT(!rValue.hasValue() || (rValue.getValueType().getTypeClass() == TypeClass_INTERFACE), + "OBoundControlModel::setFastPropertyValue_NoBroadcast : invalid argument !"); + if (!rValue.hasValue()) + { // set property to "void" + Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); + if (xComp.is()) + xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); + m_xLabelControl = NULL; + break; + } + + InterfaceRef xNewValue; + rValue >>= xNewValue; + + Reference<XControlModel> xAsModel(xNewValue, UNO_QUERY); + Reference<com::sun::star::lang::XServiceInfo> xAsServiceInfo(xNewValue, UNO_QUERY); + Reference<XPropertySet> xAsPropSet(xNewValue, UNO_QUERY); + Reference<XChild> xAsChild(xNewValue, UNO_QUERY); + if (!xAsModel.is() || !xAsServiceInfo.is() || !xAsPropSet.is() || !xAsChild.is()) + { + throw com::sun::star::lang::IllegalArgumentException(); + } + + if (!xAsServiceInfo->supportsService(m_aLabelServiceName)) + { + throw com::sun::star::lang::IllegalArgumentException(); + } + + // check if weself and the given model have a common anchestor (up to the forms collection) + Reference<XChild> xCont; + query_interface(static_cast<XWeak*>(this), xCont); + InterfaceRef xMyTopLevel = xCont->getParent(); + while (xMyTopLevel.is()) + { + Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY); + if (!xAsForm.is()) + // found my root + break; + + Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY); + xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : InterfaceRef(); + } + InterfaceRef xNewTopLevel = xAsChild->getParent(); + while (xNewTopLevel.is()) + { + Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY); + if (!xAsForm.is()) + break; + + Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY); + xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : InterfaceRef(); + } + if (xNewTopLevel != xMyTopLevel) + { + // the both objects don't belong to the same forms collection -> not acceptable + throw com::sun::star::lang::IllegalArgumentException(); + } + + m_xLabelControl = xAsPropSet; + Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY); + if (xComp.is()) + xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this))); + } + break; + default: + OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue ); + } +} + +// XPropertyChangeListener +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException) +{ + // if the DBColumn value changed, transfer it to the control + if ( evt.PropertyName.equals( PROPERTY_VALUE ) ) + { + OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database colum?" ); + osl::MutexGuard aGuard(m_aMutex); + if ( m_bForwardValueChanges && m_xColumn.is() ) + transferDbValueToControl(); + } + else + { + OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" ); + + // our binding has properties which can control properties of ourself + ::rtl::OUString sBindingControlledProperty; + bool bForwardToLabelControl = false; + if ( evt.PropertyName.equals( PROPERTY_READONLY ) ) + { + sBindingControlledProperty = PROPERTY_READONLY; + } + else if ( evt.PropertyName.equals( PROPERTY_RELEVANT ) ) + { + sBindingControlledProperty = PROPERTY_ENABLED; + bForwardToLabelControl = true; + } + else + return; + + try + { + setPropertyValue( sBindingControlledProperty, evt.NewValue ); + if ( bForwardToLabelControl && m_xLabelControl.is() ) + m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!" ); + } + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ ) throw (RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + // disconnect from database column (which is controlled by parent, directly or indirectly) + if ( hasField() ) + impl_disconnectDatabaseColumn_noNotify(); + + // log off old listeners + if ( isFormListening() ) + doFormListening( false ); + + // determine the new ambient form + impl_determineAmbientForm_nothrow(); + + // log on new listeners + doFormListening( true ); + + // re-connect to database column if needed and possible + if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) + impl_connectDatabaseColumn_noNotify( false ); +} + +// XBoundComponent +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener) throw(RuntimeException) +{ + m_aUpdateListeners.addInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener) throw(RuntimeException) +{ + m_aUpdateListeners.removeInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OBoundControlModel::commit() throw(RuntimeException) +{ + ControlModelLock aLock( *this ); + + OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not commitable !) " ); + if ( hasExternalValueBinding() ) + { + // in most cases, no action is required: For most derivees, we know the value property of + // our control (see initValueProperty), and when an external binding is active, we + // instantly forward all changes in this property to the external binding. + if ( !m_sValuePropertyName.getLength() ) + // but for those derivees which did not use this feature, we need an + // explicit transfer + transferControlValueToExternal( aLock ); + return sal_True; + } + + OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" ); + // we reach this only if we're not working with an external binding + + if ( !hasField() ) + return sal_True; + + ::cppu::OInterfaceIteratorHelper aIter( m_aUpdateListeners ); + EventObject aEvent; + aEvent.Source = static_cast< XWeak* >( this ); + sal_Bool bSuccess = sal_True; + + aLock.release(); + // >>>>>>>> ----- UNSAFE ----- >>>>>>>> + while (aIter.hasMoreElements() && bSuccess) + bSuccess = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvent ); + // <<<<<<<< ----- UNSAFE ----- <<<<<<<< + aLock.acquire(); + + if ( bSuccess ) + { + try + { + if ( m_xColumnUpdate.is() ) + bSuccess = commitControlValueToDbColumn( sal_False ); + } + catch(Exception&) + { + bSuccess = sal_False; + } + } + + if ( bSuccess ) + { + aLock.release(); + m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent ); + } + + return bSuccess; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::resetField() +{ + m_xColumnUpdate.clear(); + m_xColumn.clear(); + m_xField.clear(); + m_nFieldType = DataType::OTHER; +} + +//------------------------------------------------------------------------------ +sal_Bool OBoundControlModel::connectToField(const Reference<XRowSet>& rForm) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" ); + + // wenn eine Verbindung zur Datenbank existiert + if (rForm.is() && getConnection(rForm).is()) + { + // Feld bestimmen und PropertyChangeListener + m_xCursor = rForm; + Reference<XPropertySet> xFieldCandidate; + + if (m_xCursor.is()) + { + Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY); + DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the com::sun::star::sdb::ResultSet service !"); + if (xColumnsSupplier.is()) + { + Reference<XNameAccess> xColumns(xColumnsSupplier->getColumns(), UNO_QUERY); + if (xColumns.is() && xColumns->hasByName(m_aControlSource)) + { + OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate ); + } + } + } + + try + { + sal_Int32 nFieldType = DataType::OTHER; + if ( xFieldCandidate.is() ) + { + xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType; + if ( approveDbColumnType( nFieldType ) ) + impl_setField_noNotify( xFieldCandidate ); + } + else + impl_setField_noNotify( NULL ); + + if ( m_xField.is() ) + { + if( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) ) + { + m_nFieldType = nFieldType; + + // an wertaenderungen horchen + m_xField->addPropertyChangeListener( PROPERTY_VALUE, this ); + m_xColumnUpdate = Reference< XColumnUpdate >( m_xField, UNO_QUERY ); + m_xColumn = Reference< XColumn >( m_xField, UNO_QUERY ); + + INT32 nNullableFlag = ColumnValue::NO_NULLS; + m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag; + m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag); + // we're optimistic : in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability .... + } + else + { + OSL_ENSURE(sal_False, "OBoundControlModel::connectToField: property NAME not supported!"); + impl_setField_noNotify( NULL ); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + resetField(); + } + } + return hasField(); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet ) +{ + // but only if the rowset if posisitioned on a valid record + if ( hasField() && _rxRowSet.is() ) + { + if ( !_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast() ) + transferDbValueToControl(); + else + // reset the field if the row set is empty + // #i30661# / 2004-12-16 / frank.schoenheit@sun.com + resetNoBroadcast(); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OBoundControlModel::approveDbColumnType(sal_Int32 _nColumnType) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" ); + + if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY) + || (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER) + || (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT) + || (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY) + || (_nColumnType == DataType::BLOB) /*|| (_nColumnType == DataType::CLOB)*/ + || (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL)) + return sal_False; + + return sal_True; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::impl_determineAmbientForm_nothrow() +{ + Reference< XInterface > xParent( const_cast< OBoundControlModel* >( this )->getParent() ); + + m_xAmbientForm.set( xParent, UNO_QUERY ); + if ( !m_xAmbientForm.is() ) + { + Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY ); + if ( xSupRowSet.is() ) + m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::impl_connectDatabaseColumn_noNotify( bool _bFromReload ) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" ); + + // consistency checks + DBG_ASSERT( !( hasField() && !_bFromReload ), + "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" ); + (void)_bFromReload; + + Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY ); + OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" ); + if ( !xRowSet.is() ) + return; + + if ( !hasField() ) + { + // connect to the column + connectToField( xRowSet ); + } + + // now that we're connected (more or less, even if we did not find a column), + // we definately want to forward any potentially occuring value changes + m_bForwardValueChanges = sal_True; + + // let derived classes react on this new connection + m_bLoaded = sal_True; + onConnectedDbColumn( xRowSet ); + + // initially transfer the db column value to the control, if we successfully connected to a database column + if ( hasField() ) + initFromField( xRowSet ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::impl_disconnectDatabaseColumn_noNotify() +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" ); + + // let derived classes react on this + onDisconnectedDbColumn(); + + if ( hasField() ) + { + getField()->removePropertyChangeListener( PROPERTY_VALUE, this ); + resetField(); + } + + m_xCursor = NULL; + m_bLoaded = sal_False; +} + +//============================================================================== +// XLoadListener +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent ) throw(RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" ); + (void)_rEvent; + + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" ); + if ( hasExternalValueBinding() ) + return; + + impl_connectDatabaseColumn_noNotify( false ); +} + + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::unloaded( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::reloading( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" ); + if ( hasExternalValueBinding() ) + return; + + osl::MutexGuard aGuard(m_aMutex); + m_bForwardValueChanges = sal_False; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::unloading(const com::sun::star::lang::EventObject& /*aEvent*/) throw(RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" ); + if ( hasExternalValueBinding() ) + return; + + impl_disconnectDatabaseColumn_noNotify(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent ) throw(RuntimeException) +{ + ControlModelLock aLock( *this ); + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" ); + (void)_rEvent; + + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" ); + if ( hasExternalValueBinding() ) + return; + + impl_connectDatabaseColumn_noNotify( true ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator ) +{ + m_eControlValueChangeInstigator = _eInstigator; + doSetControlValue( _rValue ); + m_eControlValueChangeInstigator = eOther; +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::doSetControlValue( const Any& _rValue ) +{ + OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(), + "OBoundControlModel::doSetControlValue: invalid aggregate !" ); + OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ), + "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" ); + + try + { + // release our mutex once (it's acquired in one of the the calling methods), as setting aggregate properties + // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with + // our own mutex locked + // #72451# / 2000-01-31 / frank.schoenheit@sun.com + MutexRelease aRelease( m_aMutex ); + if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() ) + { + m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue ); + } + else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() ) + { + m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::doSetControlValue: caught an exception!" ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onConnectedValidator( ) +{ + try + { + // if we have an external validator, we do not want the control to force invalid + // inputs to the default value. Instead, invalid inputs should be translated + // to NaN (not a number) + Reference< XPropertySetInfo > xAggregatePropertyInfo; + if ( m_xAggregateSet.is() ) + xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo(); + if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) ) + m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_False ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::onConnectedValidator: caught an exception!" ); + } + recheckValidity( false ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onDisconnectedValidator( ) +{ + try + { + Reference< XPropertySetInfo > xAggregatePropertyInfo; + if ( m_xAggregateSet.is() ) + xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo(); + if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) ) + m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_True ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::onDisconnectedValidator: caught an exception!" ); + } + recheckValidity( false ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onConnectedExternalValue( ) +{ + calculateExternalValueType(); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onDisconnectedExternalValue( ) +{ +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ ) +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::onDisconnectedDbColumn() +{ + OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" ); +} + +// XReset +//----------------------------------------------------------------------------- +Any OBoundControlModel::getDefaultForReset() const +{ + return Any(); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::resetNoBroadcast() +{ + setControlValue( getDefaultForReset(), eOther ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::addResetListener(const Reference<XResetListener>& l) throw (RuntimeException) +{ + m_aResetHelper.addResetListener( l ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l) throw (RuntimeException) +{ + m_aResetHelper.removeResetListener( l ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::reset() throw (RuntimeException) +{ + if ( !m_aResetHelper.approveReset() ) + return; + + ControlModelLock aLock( *this ); + + // on a new record? + sal_Bool bIsNewRecord = sal_False; + Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY ); + if ( xSet.is() ) + { + try + { + xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + // cursor on an invalid row? + sal_Bool bInvalidCursorPosition = sal_True; + try + { + bInvalidCursorPosition = m_xCursor.is() + && ( m_xCursor->isAfterLast() + || m_xCursor->isBeforeFirst() + ) + && !bIsNewRecord; + } + catch( const SQLException& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::reset: caught an SQL exception!" ); + } + // don't count the insert row as "invalid" + // @since #i24495# + // @date 2004-05-14 + // @author fs@openoffice.org + + sal_Bool bSimpleReset = + ( !m_xColumn.is() // no connection to a database column + || ( m_xCursor.is() // OR we have an improperly positioned cursor + && bInvalidCursorPosition + ) + || hasExternalValueBinding() // OR we have an external value binding + ); + + if ( !bSimpleReset ) + { + // The default values will be set if and only if the current value of the field which we're bound + // to is NULL. + // Else, the current field value should be refreshed + // This behaviour is not completely ... "matured": What should happen if the field as well as the + // control have a default value? + + sal_Bool bIsNull = sal_True; + // we have to access the field content at least once to get a reliable result by XColumn::wasNull + try + { + // normally, we'd do a getString here. However, this is extremely expensive in the case + // of binary fields. Unfortunately, getString is the only method which is guaranteed + // to *always* succeed, all other getXXX methods may fail if the column is asked for a + // non-convertible type + sal_Int32 nFieldType = DataType::OBJECT; + getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType; + if ( ( nFieldType == DataType::BINARY ) + || ( nFieldType == DataType::VARBINARY ) + || ( nFieldType == DataType::LONGVARBINARY ) + || ( nFieldType == DataType::OBJECT ) + /*|| ( nFieldType == DataType::CLOB )*/ + ) + m_xColumn->getBinaryStream(); + else if ( nFieldType == DataType::BLOB ) + m_xColumn->getBlob(); + else + m_xColumn->getString(); + + bIsNull = m_xColumn->wasNull(); + } + catch(Exception&) + { + DBG_ERROR("OBoundControlModel::reset: this should have succeeded in all cases!"); + } + + sal_Bool bNeedValueTransfer = sal_True; + + if ( bIsNull ) + { + if ( bIsNewRecord ) + { + // reset the control to it's default + resetNoBroadcast(); + // and immediately commit the changes to the DB column, to keep consistency + commitControlValueToDbColumn( sal_True ); + + bNeedValueTransfer = sal_False; + } + } + + if ( bNeedValueTransfer ) + transferDbValueToControl(); + } + else + { + resetNoBroadcast(); + + // transfer to the external binding, if necessary + if ( hasExternalValueBinding() ) + transferControlValueToExternal( aLock ); + } + + // revalidate, if necessary + if ( hasValidator() ) + recheckValidity( true ); + + aLock.release(); + + m_aResetHelper.notifyResetted(); +} + +// ----------------------------------------------------------------------------- +void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField ) +{ + DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" ); + m_xField = _rxField; +} + +//-------------------------------------------------------------------- +sal_Bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding ) +{ + if ( !_rxBinding.is() ) + return sal_False; + + Sequence< Type > aTypeCandidates; + { + // SYNCHRONIZED --> + ::osl::MutexGuard aGuard( m_aMutex ); + aTypeCandidates = getSupportedBindingTypes(); + // <-- SYNCHRONIZED + } + + for ( const Type* pType = aTypeCandidates.getConstArray(); + pType != aTypeCandidates.getConstArray() + aTypeCandidates.getLength(); + ++pType + ) + { + if ( _rxBinding->supportsType( *pType ) ) + return sal_True; + } + + return sal_False; +} + +//-------------------------------------------------------------------- +void OBoundControlModel::connectExternalValueBinding( + const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock ) +{ + OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" ); + OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" ); + + // if we're connected to a database column, suspend this + if ( hasField() ) + impl_disconnectDatabaseColumn_noNotify(); + + // suspend listening for load-related events at out ambient form. + // This is because an external value binding overrules a possible database binding. + if ( isFormListening() ) + doFormListening( false ); + + // remember this new binding + m_xExternalBinding = _rxBinding; + + // tell the derivee + onConnectedExternalValue(); + + try + { + // add as value listener so we get notified when the value changes + Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY ); + if ( xModifiable.is() ) + xModifiable->addModifyListener( this ); + + // add as property change listener for some (possibly present) properties we're + // interested in + Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY ); + Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() ); + if ( xBindingPropsInfo.is() ) + { + if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) ) + { + xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this ); + m_bBindingControlsRO = sal_True; + } + if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) ) + { + xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this ); + m_bBindingControlsEnable = sal_True; + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + // propagate our new value + transferExternalValueToControl( _rInstanceLock ); + + // if the binding is also a validator, use it, too. This is a constraint of the + // com.sun.star.form.binding.ValidatableBindableFormComponent service + if ( m_bSupportsValidation ) + { + try + { + Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY ); + if ( xAsValidator.is() ) + setValidator( xAsValidator ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +//-------------------------------------------------------------------- +void OBoundControlModel::disconnectExternalValueBinding( ) +{ + try + { + // not listening at the binding anymore + Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY ); + if ( xModifiable.is() ) + xModifiable->removeModifyListener( this ); + + // remove as property change listener + Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY ); + if ( m_bBindingControlsRO ) + xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this ); + if ( m_bBindingControlsEnable ) + xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::disconnectExternalValueBinding: caught an exception!" ); + } + + // if the binding also acts as our validator, disconnect the validator, too + if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() ) + disconnectValidator( ); + + // no binding anymore + m_xExternalBinding.clear(); + + // be a load listener at our form, again. This was suspended while we had + // an external value binding in place. + doFormListening( true ); + + // re-connect to database column of the new parent + if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() ) + impl_connectDatabaseColumn_noNotify( false ); + + // tell the derivee + onDisconnectedExternalValue(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding ) throw (IncompatibleTypesException, RuntimeException) +{ + OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support binding to external data + + if ( !impl_approveValueBinding_nolock( _rxBinding ) ) + { + throw IncompatibleTypesException( + FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ), + *this + ); + } + + ControlModelLock aLock( *this ); + + // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding + // might trigger a change in our BoundField. + FieldChangeNotifier aBoundFieldNotifier( aLock ); + + // disconnect from the old binding + if ( hasExternalValueBinding() ) + disconnectExternalValueBinding( ); + + // connect to the new binding + if ( _rxBinding.is() ) + connectExternalValueBinding( _rxBinding, aLock ); +} + +//-------------------------------------------------------------------- +Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support binding to external data + + return m_xExternalBinding; +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent ) throw ( RuntimeException ) +{ + ControlModelLock aLock( *this ); + + OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" ); + if ( !m_bTransferingValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() ) + { + transferExternalValueToControl( aLock ); + } +} + +//-------------------------------------------------------------------- +void OBoundControlModel::transferDbValueToControl( ) +{ + try + { + setControlValue( translateDbColumnToControlValue(), eDbColumnBinding ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::transferExternalValueToControl( ControlModelLock& _rInstanceLock ) +{ + Reference< XValueBinding > xExternalBinding( m_xExternalBinding ); + Type aValueExchangeType( getExternalValueType() ); + + _rInstanceLock.release(); + // >>>>>>>> ----- UNSAFE ----- >>>>>>>> + Any aExternalValue; + try + { + aExternalValue = xExternalBinding->getValue( aValueExchangeType ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + // <<<<<<<< ----- UNSAFE ----- <<<<<<<< + _rInstanceLock.acquire(); + + setControlValue( translateExternalValueToControlValue( aExternalValue ), eExternalBinding ); +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::transferControlValueToExternal( ControlModelLock& _rInstanceLock ) +{ + OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(), + "OBoundControlModel::transferControlValueToExternal: precondition not met!" ); + + if ( m_xExternalBinding.is() ) + { + Any aExternalValue( translateControlValueToExternalValue() ); + m_bTransferingValue = sal_True; + + _rInstanceLock.release(); + // >>>>>>>> ----- UNSAFE ----- >>>>>>>> + try + { + m_xExternalBinding->setValue( aExternalValue ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + // <<<<<<<< ----- UNSAFE ----- <<<<<<<< + _rInstanceLock.acquire(); + + m_bTransferingValue = sal_False; + } +} + +// ----------------------------------------------------------------------------- +Sequence< Type > OBoundControlModel::getSupportedBindingTypes() +{ + return Sequence< Type >( &m_aValuePropertyType, 1 ); +} + +//----------------------------------------------------------------------------- +void OBoundControlModel::calculateExternalValueType() +{ + m_aExternalValueType = Type(); + if ( !m_xExternalBinding.is() ) + return; + + Sequence< Type > aTypeCandidates( getSupportedBindingTypes() ); + for ( const Type* pTypeCandidate = aTypeCandidates.getConstArray(); + pTypeCandidate != aTypeCandidates.getConstArray() + aTypeCandidates.getLength(); + ++pTypeCandidate + ) + { + if ( m_xExternalBinding->supportsType( *pTypeCandidate ) ) + { + m_aExternalValueType = *pTypeCandidate; + break; + } + } +} + +//----------------------------------------------------------------------------- +Any OBoundControlModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(), + "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" ); + + Any aControlValue( _rExternalValue ); + + // if the external value is VOID, and our value property is not allowed to be VOID, + // then default-construct a value + if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid ) + aControlValue.setValue( NULL, m_aValuePropertyType ); + + // outta here + return aControlValue; +} + +//------------------------------------------------------------------------------ +Any OBoundControlModel::translateControlValueToExternalValue( ) const +{ + return getControlValue( ); +} + +//------------------------------------------------------------------------------ +Any OBoundControlModel::translateControlValueToValidatableValue( ) const +{ + OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" ); + if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() ) + return translateControlValueToExternalValue(); + return getControlValue(); +} + +//------------------------------------------------------------------------------ +Any OBoundControlModel::getControlValue( ) const +{ + OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(), + "OBoundControlModel::getControlValue: invalid aggregate !" ); + OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ), + "OBoundControlModel::getControlValue: please override if you have own value property handling!" ); + + // determine the current control value + Any aControlValue; + if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() ) + { + aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle ); + } + else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() ) + { + aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName ); + } + + return aControlValue; +} + +//-------------------------------------------------------------------- +void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator ) +{ + OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" ); + OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" ); + + m_xValidator = _rxValidator; + + // add as value listener so we get notified when the value changes + if ( m_xValidator.is() ) + { + try + { + m_xValidator->addValidityConstraintListener( this ); + } + catch( const RuntimeException& ) + { + } + } + + onConnectedValidator( ); +} + +//-------------------------------------------------------------------- +void OBoundControlModel::disconnectValidator( ) +{ + OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" ); + + // add as value listener so we get notified when the value changes + if ( m_xValidator.is() ) + { + try + { + m_xValidator->removeValidityConstraintListener( this ); + } + catch( const RuntimeException& ) + { + } + } + + m_xValidator.clear(); + + onDisconnectedValidator( ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator ) throw (VetoException,RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support validation + + // early out if the validator does not change + if( _rxValidator == m_xValidator ) + return; + + if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) ) + throw VetoException( + FRM_RES_STRING( RID_STR_INVALID_VALIDATOR ), + *this + ); + + // disconnect from the old validator + if ( hasValidator() ) + disconnectValidator( ); + + // connect to the new validator + if ( _rxValidator.is() ) + connectValidator( _rxValidator ); +} + +//-------------------------------------------------------------------- +Reference< XValidator > SAL_CALL OBoundControlModel::getValidator( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support validation + + return m_xValidator; +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& /*Source*/ ) throw (RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" ); + // the interface for this method should not have been exposed if we do not + // support validation + + recheckValidity( false ); +} + +//-------------------------------------------------------------------- +sal_Bool SAL_CALL OBoundControlModel::isValid( ) throw (RuntimeException) +{ + return m_bIsCurrentValueValid; +} + +//-------------------------------------------------------------------- +::com::sun::star::uno::Any OBoundControlModel::getCurrentFormComponentValue() const +{ + if ( hasValidator() ) + return translateControlValueToValidatableValue(); + return getControlValue(); +} + +//-------------------------------------------------------------------- +Any SAL_CALL OBoundControlModel::getCurrentValue( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return getCurrentFormComponentValue(); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException) +{ + if ( Listener.is() ) + m_aFormComponentListeners.addInterface( Listener ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException) +{ + if ( Listener.is() ) + m_aFormComponentListeners.removeInterface( Listener ); +} + +//-------------------------------------------------------------------- +void OBoundControlModel::recheckValidity( bool _bForceNotification ) +{ + try + { + sal_Bool bIsCurrentlyValid = sal_True; + if ( hasValidator() ) + bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() ); + + if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification ) + { + m_bIsCurrentValueValid = bIsCurrentlyValid; + + // release our mutex for the notifications + MutexRelease aRelease( m_aMutex ); + m_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OBoundControlModel::recheckValidity: caught an exception!" ); + } +} + +//------------------------------------------------------------------------------ +void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 5, OControlModel ) + DECL_PROP1 ( CONTROLSOURCE, ::rtl::OUString, BOUND ); + DECL_IFACE_PROP3( BOUNDFIELD, XPropertySet, BOUND, READONLY, TRANSIENT ); + DECL_IFACE_PROP2( CONTROLLABEL, XPropertySet, BOUND, MAYBEVOID ); + DECL_PROP2 ( CONTROLSOURCEPROPERTY, ::rtl::OUString, READONLY, TRANSIENT ); + DECL_BOOL_PROP1 ( INPUT_REQUIRED, BOUND ); + END_DESCRIBE_PROPERTIES() +} + +// ----------------------------------------------------------------------------- + +//......................................................................... +} +//... namespace frm ....................................................... + diff --git a/forms/source/component/FormattedField.cxx b/forms/source/component/FormattedField.cxx new file mode 100644 index 000000000000..a35a300dda78 --- /dev/null +++ b/forms/source/component/FormattedField.cxx @@ -0,0 +1,1257 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "FormattedField.hxx" +#include "services.hxx" +#include "property.hrc" +#include "property.hxx" +#include "frm_resource.hxx" +#include "frm_resource.hrc" +#include "propertybaghelper.hxx" +#include <comphelper/sequence.hxx> +#include <comphelper/numbers.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbconversion.hxx> +#include <svl/zforlist.hxx> +#include <svl/numuno.hxx> +#include <vcl/svapp.hxx> +#include <tools/debug.hxx> +#include <vcl/wintypes.hxx> +#include <i18npool/mslangid.hxx> +#include <rtl/textenc.h> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/awt/MouseEvent.hpp> +#include <com/sun/star/form/XSubmit.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XKeyListener.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <vos/mutex.hxx> + // needed as long as we use the SolarMutex +#include <comphelper/streamsection.hxx> +#include <cppuhelper/weakref.hxx> +#include <unotools/desktopterminationobserver.hxx> + +#include <list> +#include <algorithm> + +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +namespace +{ + typedef com::sun::star::util::Date UNODate; + typedef com::sun::star::util::Time UNOTime; + typedef com::sun::star::util::DateTime UNODateTime; +} + +//......................................................................... +namespace frm +{ + +/*************************************************************************/ + +class StandardFormatsSupplier : protected SvNumberFormatsSupplierObj, public ::utl::ITerminationListener +{ +protected: + SvNumberFormatter* m_pMyPrivateFormatter; + static WeakReference< XNumberFormatsSupplier > s_xDefaultFormatsSupplier; + +public: + static Reference< XNumberFormatsSupplier > get( const Reference< XMultiServiceFactory >& _rxORB ); + + using SvNumberFormatsSupplierObj::operator new; + using SvNumberFormatsSupplierObj::operator delete; + +protected: + StandardFormatsSupplier(const Reference<XMultiServiceFactory>& _rxFactory,LanguageType _eSysLanguage); + ~StandardFormatsSupplier(); + +protected: + virtual bool queryTermination() const; + virtual void notifyTermination(); +}; + +//------------------------------------------------------------------ +WeakReference< XNumberFormatsSupplier > StandardFormatsSupplier::s_xDefaultFormatsSupplier; + +//------------------------------------------------------------------ +StandardFormatsSupplier::StandardFormatsSupplier(const Reference< XMultiServiceFactory > & _rxFactory,LanguageType _eSysLanguage) + :SvNumberFormatsSupplierObj() + ,m_pMyPrivateFormatter(new SvNumberFormatter(_rxFactory, _eSysLanguage)) +{ + SetNumberFormatter(m_pMyPrivateFormatter); + + // #i29147# - 2004-06-18 - fs@openoffice.org + ::utl::DesktopTerminationObserver::registerTerminationListener( this ); +} + +//------------------------------------------------------------------ +StandardFormatsSupplier::~StandardFormatsSupplier() +{ + ::utl::DesktopTerminationObserver::revokeTerminationListener( this ); + + DELETEZ( m_pMyPrivateFormatter ); +} + +//------------------------------------------------------------------ +Reference< XNumberFormatsSupplier > StandardFormatsSupplier::get( const Reference< XMultiServiceFactory >& _rxORB ) +{ + LanguageType eSysLanguage = LANGUAGE_SYSTEM; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier; + if ( xSupplier.is() ) + return xSupplier; + + // get the Office's locale + const Locale& rSysLocale = SvtSysLocale().GetLocaleData().getLocale(); + // translate + eSysLanguage = MsLangId::convertLocaleToLanguage( rSysLocale ); + } + + StandardFormatsSupplier* pSupplier = new StandardFormatsSupplier( _rxORB, eSysLanguage ); + Reference< XNumberFormatsSupplier > xNewlyCreatedSupplier( pSupplier ); + + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier; + if ( xSupplier.is() ) + // somebody used the small time frame where the mutex was not locked to create and set + // the supplier + return xSupplier; + + s_xDefaultFormatsSupplier = xNewlyCreatedSupplier; + } + + return xNewlyCreatedSupplier; +} + +//------------------------------------------------------------------ +bool StandardFormatsSupplier::queryTermination() const +{ + return true; +} + +//------------------------------------------------------------------ +void StandardFormatsSupplier::notifyTermination() +{ + Reference< XNumberFormatsSupplier > xKeepAlive = this; + // when the application is terminating, release our static reference so that we are cleared/destructed + // earlier than upon unloading the library + // #i29147# - 2004-06-18 - fs@openoffice.org + s_xDefaultFormatsSupplier = WeakReference< XNumberFormatsSupplier >( ); + + SetNumberFormatter( NULL ); + DELETEZ( m_pMyPrivateFormatter ); +} + +/*************************************************************************/ +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFormattedControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFormattedControl(_rxFactory)); +} + +//------------------------------------------------------------------ +Sequence<Type> OFormattedControl::_getTypes() +{ + return ::comphelper::concatSequences( + OFormattedControl_BASE::getTypes(), + OBoundControl::_getTypes() + ); +} + +//------------------------------------------------------------------ +Any SAL_CALL OFormattedControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OBoundControl::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = OFormattedControl_BASE::queryInterface(_rType); + return aReturn; +} + + +DBG_NAME(OFormattedControl); +//------------------------------------------------------------------------------ +OFormattedControl::OFormattedControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_FORMATTEDFIELD) + ,m_nKeyEvent(0) +{ + DBG_CTOR(OFormattedControl,NULL); + + increment(m_refCount); + { + Reference<XWindow> xComp; + if (query_aggregation(m_xAggregate, xComp)) + { + xComp->addKeyListener(this); + } + } + decrement(m_refCount); +} + +//------------------------------------------------------------------------------ +OFormattedControl::~OFormattedControl() +{ + if( m_nKeyEvent ) + Application::RemoveUserEvent( m_nKeyEvent ); + + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OFormattedControl,NULL); +} + +// XKeyListener +//------------------------------------------------------------------------------ +void OFormattedControl::disposing(const EventObject& _rSource) throw(RuntimeException) +{ + OBoundControl::disposing(_rSource); +} + +//------------------------------------------------------------------------------ +void OFormattedControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException) +{ + if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 ) + return; + + // Steht das Control in einem Formular mit einer Submit-URL? + Reference<com::sun::star::beans::XPropertySet> xSet(getModel(), UNO_QUERY); + if( !xSet.is() ) + return; + + Reference<XFormComponent> xFComp(xSet, UNO_QUERY); + InterfaceRef xParent = xFComp->getParent(); + if( !xParent.is() ) + return; + + Reference<com::sun::star::beans::XPropertySet> xFormSet(xParent, UNO_QUERY); + if( !xFormSet.is() ) + return; + + Any aTmp(xFormSet->getPropertyValue( PROPERTY_TARGET_URL )); + if (!isA(aTmp, static_cast< ::rtl::OUString* >(NULL)) || + !getString(aTmp).getLength() ) + return; + + Reference<XIndexAccess> xElements(xParent, UNO_QUERY); + sal_Int32 nCount = xElements->getCount(); + if( nCount > 1 ) + { + + Reference<com::sun::star::beans::XPropertySet> xFCSet; + for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ ) + { + // Any aElement(xElements->getByIndex(nIndex)); + xElements->getByIndex(nIndex) >>= xFCSet; + + if (hasProperty(PROPERTY_CLASSID, xFCSet) && + getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD) + { + // Noch ein weiteres Edit gefunden ==> dann nicht submitten + if (xFCSet != xSet) + return; + } + } + } + + // Da wir noch im Haender stehen, submit asynchron ausloesen + if( m_nKeyEvent ) + Application::RemoveUserEvent( m_nKeyEvent ); + m_nKeyEvent = Application::PostUserEvent( LINK(this, OFormattedControl, + OnKeyPressed) ); +} + +//------------------------------------------------------------------------------ +void OFormattedControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +IMPL_LINK(OFormattedControl, OnKeyPressed, void*, /*EMPTYARG*/) +{ + m_nKeyEvent = 0; + + Reference<XFormComponent> xFComp(getModel(), UNO_QUERY); + InterfaceRef xParent = xFComp->getParent(); + Reference<XSubmit> xSubmit(xParent, UNO_QUERY); + if (xSubmit.is()) + xSubmit->submit( Reference<XControl> (), ::com::sun::star::awt::MouseEvent() ); + return 0L; +} + +//------------------------------------------------------------------------------ +StringSequence OFormattedControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_FORMATTEDFIELD; + return aSupported; +} + +//------------------------------------------------------------------------------ +void OFormattedControl::setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException) +{ + OBoundControl::setDesignMode(bOn); +} + +/*************************************************************************/ +DBG_NAME(OFormattedModel) +//------------------------------------------------------------------ +void OFormattedModel::implConstruct() +{ + // members + m_bOriginalNumeric = sal_False; + m_bNumeric = sal_False; + m_xOriginalFormatter = NULL; + m_nKeyType = NumberFormat::UNDEFINED; + m_aNullDate = DBTypeConversion::getStandardDate(); + m_nFieldType = DataType::OTHER; + + // default our formats supplier + increment(m_refCount); + setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER); + decrement(m_refCount); + + startAggregatePropertyListening( PROPERTY_FORMATKEY ); + startAggregatePropertyListening( PROPERTY_FORMATSSUPPLIER ); +} + +//------------------------------------------------------------------ +OFormattedModel::OFormattedModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel(_rxFactory, VCL_CONTROLMODEL_FORMATTEDFIELD, FRM_SUN_CONTROL_FORMATTEDFIELD, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OErrorBroadcaster( OComponentHelper::rBHelper ) +{ + DBG_CTOR(OFormattedModel, NULL); + + implConstruct(); + + m_nClassId = FormComponentType::TEXTFIELD; + initValueProperty( PROPERTY_EFFECTIVE_VALUE, PROPERTY_ID_EFFECTIVE_VALUE ); +} + +//------------------------------------------------------------------ +OFormattedModel::OFormattedModel( const OFormattedModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) +{ + DBG_CTOR(OFormattedModel, NULL); + + implConstruct(); +} + +//------------------------------------------------------------------------------ +OFormattedModel::~OFormattedModel() +{ + DBG_DTOR(OFormattedModel, NULL); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OFormattedModel ) + +//------------------------------------------------------------------------------ +void SAL_CALL OFormattedModel::disposing() +{ + OErrorBroadcaster::disposing(); + OEditBaseModel::disposing(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OFormattedModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OEditBaseModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_FORMATTEDFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_FORMATTEDFIELD; + *pStoreTo++ = BINDABLE_DATABASE_FORMATTED_FIELD; + + return aSupported; +} + +// XAggregation +//------------------------------------------------------------------------------ +Any SAL_CALL OFormattedModel::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn = OEditBaseModel::queryAggregation( _rType ); + return aReturn.hasValue() ? aReturn : OErrorBroadcaster::queryInterface( _rType ); +} + +// XTypeProvider +//------------------------------------------------------------------------------ +Sequence< Type > OFormattedModel::_getTypes() +{ + return ::comphelper::concatSequences( + OEditBaseModel::_getTypes(), + OErrorBroadcaster::getTypes() + ); +} + +// XPersistObject +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormattedModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString(FRM_COMPONENT_EDIT); +} + +// XPropertySet +//------------------------------------------------------------------------------ +void OFormattedModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 3, OEditBaseModel ) + DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_BOOL_PROP2(FILTERPROPOSAL, BOUND, MAYBEDEFAULT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OEditBaseModel::describeAggregateProperties( _rAggregateProps ); + + // TreatAsNumeric nicht transient : wir wollen es an der UI anbinden (ist noetig, um dem EffectiveDefault + // - der kann Text oder Zahl sein - einen Sinn zu geben) + ModifyPropertyAttributes(_rAggregateProps, PROPERTY_TREATASNUMERIC, 0, PropertyAttribute::TRANSIENT); + // same for FormatKey + // (though the paragraph above for the TreatAsNumeric does not hold anymore - we do not have an UI for this. + // But we have for the format key ...) + // 25.06.2001 - 87862 - frank.schoenheit@sun.com + ModifyPropertyAttributes(_rAggregateProps, PROPERTY_FORMATKEY, 0, PropertyAttribute::TRANSIENT); + + RemoveProperty(_rAggregateProps, PROPERTY_STRICTFORMAT); + // no strict format property for formatted fields: it does not make sense, 'cause + // there is no general way to decide which characters/sub strings are allowed during the input of an + // arbitraryly formatted control + // 81441 - 12/07/00 - FS +} + +//------------------------------------------------------------------------------ +void OFormattedModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const +{ + OEditBaseModel::getFastPropertyValue(rValue, nHandle); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception) +{ + OEditBaseModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); +} + +//------------------------------------------------------------------------------ +sal_Bool OFormattedModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) + throw( IllegalArgumentException ) +{ + return OEditBaseModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::setPropertyToDefaultByHandle(sal_Int32 nHandle) +{ + if (nHandle == PROPERTY_ID_FORMATSSUPPLIER) + { + Reference<XNumberFormatsSupplier> xSupplier = calcDefaultFormatsSupplier(); + DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::setPropertyToDefaultByHandle(FORMATSSUPPLIER) : have no aggregate !"); + if (m_xAggregateSet.is()) + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier)); + } + else + OEditBaseModel::setPropertyToDefaultByHandle(nHandle); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException ) +{ + OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper(); + sal_Int32 nHandle = rPH.getHandleByName( aPropertyName ); + + if (nHandle == PROPERTY_ID_FORMATSSUPPLIER) + setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER); + else + OEditBaseModel::setPropertyToDefault(aPropertyName); +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + if (nHandle == PROPERTY_ID_FORMATSSUPPLIER) + { + Reference<XNumberFormatsSupplier> xSupplier = calcDefaultFormatsSupplier(); + return makeAny(xSupplier); + } + else + return OEditBaseModel::getPropertyDefaultByHandle(nHandle); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OFormattedModel::getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException ) +{ + OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper(); + sal_Int32 nHandle = rPH.getHandleByName( aPropertyName ); + + if (nHandle == PROPERTY_ID_FORMATSSUPPLIER) + return getPropertyDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER); + else + return OEditBaseModel::getPropertyDefault(aPropertyName); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::_propertyChanged( const com::sun::star::beans::PropertyChangeEvent& evt ) throw(RuntimeException) +{ + // TODO: check how this works with external bindings + + OSL_ENSURE( evt.Source == m_xAggregateSet, "OFormattedModel::_propertyChanged: where did this come from?" ); + if ( evt.Source == m_xAggregateSet ) + { + Reference< XPropertySet > xSourceSet( evt.Source, UNO_QUERY ); + if ( evt.PropertyName.equals( PROPERTY_FORMATKEY ) ) + { + if ( evt.NewValue.getValueType().getTypeClass() == TypeClass_LONG ) + { + try + { + ::osl::MutexGuard aGuard( m_aMutex ); + + Reference<XNumberFormatsSupplier> xSupplier( calcFormatsSupplier() ); + m_nKeyType = getNumberFormatType(xSupplier->getNumberFormats(), getINT32( evt.NewValue ) ); + + // as m_aSaveValue (which is used by commitControlValueToDbColumn) is format dependent we have + // to recalc it, which is done by translateDbColumnToControlValue + if ( m_xColumn.is() && m_xAggregateFastSet.is() && !m_xCursor->isBeforeFirst() && !m_xCursor->isAfterLast()) + { + setControlValue( translateDbColumnToControlValue(), eOther ); + } + + // if we're connected to an external value binding, then re-calculate the type + // used to exchange the value - it depends on the format, too + if ( hasExternalValueBinding() ) + { + calculateExternalValueType(); + } + } + catch(Exception&) + { + } + } + return; + } + + if ( evt.PropertyName.equals( PROPERTY_FORMATSSUPPLIER ) ) + { + updateFormatterNullDate(); + return; + } + + OBoundControlModel::_propertyChanged( evt ); + } +} + +//------------------------------------------------------------------------------ +void OFormattedModel::updateFormatterNullDate() +{ + // calc the current NULL date + Reference< XNumberFormatsSupplier > xSupplier( calcFormatsSupplier() ); + if ( xSupplier.is() ) + xSupplier->getNumberFormatSettings()->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NullDate" ) ) ) >>= m_aNullDate; +} + +//------------------------------------------------------------------------------ +Reference< XNumberFormatsSupplier > OFormattedModel::calcFormatsSupplier() const +{ + Reference<XNumberFormatsSupplier> xSupplier; + + DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::calcFormatsSupplier : have no aggregate !"); + // hat mein aggregiertes Model einen FormatSupplier ? + if( m_xAggregateSet.is() ) + m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xSupplier; + + if (!xSupplier.is()) + // check if my parent form has a supplier + xSupplier = calcFormFormatsSupplier(); + + if (!xSupplier.is()) + xSupplier = calcDefaultFormatsSupplier(); + + DBG_ASSERT(xSupplier.is(), "OFormattedModel::calcFormatsSupplier : no supplier !"); + // jetzt sollte aber einer da sein + return xSupplier; +} + +//------------------------------------------------------------------------------ +Reference<XNumberFormatsSupplier> OFormattedModel::calcFormFormatsSupplier() const +{ + Reference<XChild> xMe; + query_interface(static_cast<XWeak*>(const_cast<OFormattedModel*>(this)), xMe); + // damit stellen wir sicher, dass wir auch fuer den Fall der Aggregation das richtige + // Objekt bekommen + DBG_ASSERT(xMe.is(), "OFormattedModel::calcFormFormatsSupplier : I should have a content interface !"); + + // jetzt durchhangeln nach oben, bis wir auf eine starform treffen (angefangen mit meinem eigenen Parent) + Reference<XChild> xParent(xMe->getParent(), UNO_QUERY); + Reference<XForm> xNextParentForm(xParent, UNO_QUERY); + while (!xNextParentForm.is() && xParent.is()) + { + xParent = xParent.query( xParent->getParent() ); + xNextParentForm = xNextParentForm.query( xParent ); + } + + if (!xNextParentForm.is()) + { + DBG_ERROR("OFormattedModel::calcFormFormatsSupplier : have no ancestor which is a form !"); + return NULL; + } + + // den FormatSupplier von meinem Vorfahren (falls der einen hat) + Reference< XRowSet > xRowSet( xNextParentForm, UNO_QUERY ); + Reference< XNumberFormatsSupplier > xSupplier; + if (xRowSet.is()) + xSupplier = getNumberFormats( getConnection(xRowSet), sal_True, getContext().getLegacyServiceFactory() ); + return xSupplier; +} + +//------------------------------------------------------------------------------ +Reference< XNumberFormatsSupplier > OFormattedModel::calcDefaultFormatsSupplier() const +{ + return StandardFormatsSupplier::get( getContext().getLegacyServiceFactory() ); +} + +// XBoundComponent +//------------------------------------------------------------------------------ +void OFormattedModel::loaded(const EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException) +{ + // HACK : our onConnectedDbColumn accesses our NumberFormatter which locks the solar mutex (as it doesn't have + // an own one). To prevent deadlocks with other threads which may request a property from us in an + // UI-triggered action (e.g. an tooltip) we lock the solar mutex _here_ before our base class locks + // it's own muext (which is used for property requests) + // alternative a): we use two mutexes, one which is passed to the OPropertysetHelper and used for + // property requests and one for our own code. This would need a lot of code rewriting + // alternative b): The NumberFormatter has to be really threadsafe (with an own mutex), which is + // the only "clean" solution for me. + // FS - 69603 - 02.11.99 + + ::vos::OGuard aGuard(Application::GetSolarMutex()); + OEditBaseModel::loaded(rEvent); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + m_xOriginalFormatter = NULL; + + // get some properties of the field + m_nFieldType = DataType::OTHER; + Reference<XPropertySet> xField = getField(); + if ( xField.is() ) + xField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= m_nFieldType; + + sal_Int32 nFormatKey = 0; + + DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::onConnectedDbColumn : have no aggregate !"); + if (m_xAggregateSet.is()) + { // all the following doesn't make any sense if we have no aggregate ... + Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER); + DBG_ASSERT( aSupplier.hasValue(), "OFormattedModel::onConnectedDbColumn : invalid property value !" ); + // das sollte im Constructor oder im read auf was richtiges gesetzt worden sein + + Any aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY); + if ( !(aFmtKey >>= nFormatKey ) ) + { // nobody gave us a format to use. So we examine the field we're bound to for a + // format key, and use it ourself, too + sal_Int32 nType = DataType::VARCHAR; + if (xField.is()) + { + aFmtKey = xField->getPropertyValue(PROPERTY_FORMATKEY); + xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType ; + } + + Reference<XNumberFormatsSupplier> xSupplier = calcFormFormatsSupplier(); + DBG_ASSERT(xSupplier.is(), "OFormattedModel::onConnectedDbColumn : bound to a field but no parent with a formatter ? how this ?"); + if (xSupplier.is()) + { + m_bOriginalNumeric = getBOOL(getPropertyValue(PROPERTY_TREATASNUMERIC)); + + if (!aFmtKey.hasValue()) + { // we aren't bound to a field (or this field's format is invalid) + // -> determine the standard text (or numeric) format of the supplier + Reference<XNumberFormatTypes> xTypes(xSupplier->getNumberFormats(), UNO_QUERY); + if (xTypes.is()) + { + Locale aApplicationLocale = Application::GetSettings().GetUILocale(); + + if (m_bOriginalNumeric) + aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::NUMBER, aApplicationLocale); + else + aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::TEXT, aApplicationLocale); + } + } + + aSupplier >>= m_xOriginalFormatter; + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier)); + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, aFmtKey); + + // das Numeric-Flag an mein gebundenes Feld anpassen + if (xField.is()) + { + m_bNumeric = sal_False; + switch (nType) + { + case DataType::BIT: + case DataType::BOOLEAN: + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::INTEGER: + case DataType::BIGINT: + case DataType::FLOAT: + case DataType::REAL: + case DataType::DOUBLE: + case DataType::NUMERIC: + case DataType::DECIMAL: + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + m_bNumeric = sal_True; + break; + } + } + else + m_bNumeric = m_bOriginalNumeric; + + setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bNumeric)); + + OSL_VERIFY( aFmtKey >>= nFormatKey ); + } + } + } + + Reference<XNumberFormatsSupplier> xSupplier = calcFormatsSupplier(); + m_bNumeric = getBOOL( getPropertyValue( PROPERTY_TREATASNUMERIC ) ); + m_nKeyType = getNumberFormatType( xSupplier->getNumberFormats(), nFormatKey ); + xSupplier->getNumberFormatSettings()->getPropertyValue( ::rtl::OUString::createFromAscii("NullDate") ) >>= m_aNullDate; + + OEditBaseModel::onConnectedDbColumn( _rxForm ); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::onDisconnectedDbColumn() +{ + OEditBaseModel::onDisconnectedDbColumn(); + if (m_xOriginalFormatter.is()) + { // unser aggregiertes Model hatte keinerlei Format-Informationen + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(m_xOriginalFormatter)); + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, Any()); + setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bOriginalNumeric)); + m_xOriginalFormatter = NULL; + } + + m_nFieldType = DataType::OTHER; + m_nKeyType = NumberFormat::UNDEFINED; + m_aNullDate = DBTypeConversion::getStandardDate(); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OEditBaseModel::write(_rxOutStream); + _rxOutStream->writeShort(0x0003); + + DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::write : have no aggregate !"); + + // mein Format (evtl. void) in ein persistentes Format bringen (der Supplier zusammen mit dem Key ist es zwar auch, + // aber deswegen muessen wir ja nicht gleich den ganzen Supplier speichern, das waere ein klein wenig Overhead ;) + + Reference<XNumberFormatsSupplier> xSupplier; + Any aFmtKey; + sal_Bool bVoidKey = sal_True; + if (m_xAggregateSet.is()) + { + Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER); + if (aSupplier.getValueType().getTypeClass() != TypeClass_VOID) + { + OSL_VERIFY( aSupplier >>= xSupplier ); + } + + aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY); + bVoidKey = (!xSupplier.is() || !aFmtKey.hasValue()) || (isLoaded() && m_xOriginalFormatter.is()); + // (kein Fomatter und/oder Key) oder (loaded und faked Formatter) + } + + _rxOutStream->writeBoolean(!bVoidKey); + if (!bVoidKey) + { + // aus dem FormatKey und dem Formatter persistente Angaben basteln + + Any aKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY); + sal_Int32 nKey = aKey.hasValue() ? getINT32(aKey) : 0; + + Reference<XNumberFormats> xFormats = xSupplier->getNumberFormats(); + + ::rtl::OUString sFormatDescription; + LanguageType eFormatLanguage = LANGUAGE_DONTKNOW; + + static const ::rtl::OUString s_aLocaleProp = ::rtl::OUString::createFromAscii("Locale"); + Reference<com::sun::star::beans::XPropertySet> xFormat = xFormats->getByKey(nKey); + if (hasProperty(s_aLocaleProp, xFormat)) + { + Any aLocale = xFormat->getPropertyValue(s_aLocaleProp); + DBG_ASSERT(isA(aLocale, static_cast<Locale*>(NULL)), "OFormattedModel::write : invalid language property !"); + if (isA(aLocale, static_cast<Locale*>(NULL))) + { + Locale* pLocale = (Locale*)aLocale.getValue(); + eFormatLanguage = MsLangId::convertLocaleToLanguage( *pLocale ); + } + } + + static const ::rtl::OUString s_aFormatStringProp = ::rtl::OUString::createFromAscii("FormatString"); + if (hasProperty(s_aFormatStringProp, xFormat)) + xFormat->getPropertyValue(s_aFormatStringProp) >>= sFormatDescription; + + _rxOutStream->writeUTF(sFormatDescription); + _rxOutStream->writeLong((sal_Int32)eFormatLanguage); + } + + // version 2 : write the properties common to all OEditBaseModels + writeCommonEditProperties(_rxOutStream); + + // version 3 : write the effective value property of the aggregate + // Due to a bug within the UnoControlFormattedFieldModel implementation (our default aggregate) this props value isn't correctly read + // and this can't be corrected without being incompatible. + // so we have our own handling. + + // and to be a little bit more compatible we make the following section skippable + { + Reference< XDataOutputStream > xOut(_rxOutStream, UNO_QUERY); + OStreamSection aDownCompat(xOut); + + // a sub version within the skippable block + _rxOutStream->writeShort(0x0000); + + // version 0: the effective value of the aggregate + Any aEffectiveValue; + if (m_xAggregateSet.is()) + { + try { aEffectiveValue = m_xAggregateSet->getPropertyValue(PROPERTY_EFFECTIVE_VALUE); } catch(Exception&) { } + } + + { + OStreamSection aDownCompat2(xOut); + switch (aEffectiveValue.getValueType().getTypeClass()) + { + case TypeClass_STRING: + _rxOutStream->writeShort(0x0000); + _rxOutStream->writeUTF(::comphelper::getString(aEffectiveValue)); + break; + case TypeClass_DOUBLE: + _rxOutStream->writeShort(0x0001); + _rxOutStream->writeDouble(::comphelper::getDouble(aEffectiveValue)); + break; + default: // void and all unknown states + DBG_ASSERT(!aEffectiveValue.hasValue(), "FmXFormattedModel::write : unknown property value type !"); + _rxOutStream->writeShort(0x0002); + break; + } + } + } +} + +//------------------------------------------------------------------------------ +void OFormattedModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OEditBaseModel::read(_rxInStream); + sal_uInt16 nVersion = _rxInStream->readShort(); + + Reference<XNumberFormatsSupplier> xSupplier; + sal_Int32 nKey = -1; + switch (nVersion) + { + case 0x0001 : + case 0x0002 : + case 0x0003 : + { + sal_Bool bNonVoidKey = _rxInStream->readBoolean(); + if (bNonVoidKey) + { + // den String und die Language lesen .... + ::rtl::OUString sFormatDescription = _rxInStream->readUTF(); + LanguageType eDescriptionLanguage = (LanguageType)_rxInStream->readLong(); + + // und daraus von einem Formatter zu einem Key zusammenwuerfeln lassen ... + xSupplier = calcFormatsSupplier(); + // calcFormatsSupplier nimmt erst den vom Model, dann einen von der starform, dann einen ganz neuen .... + Reference<XNumberFormats> xFormats = xSupplier->getNumberFormats(); + + if (xFormats.is()) + { + Locale aDescriptionLanguage( MsLangId::convertLanguageToLocale(eDescriptionLanguage)); + + nKey = xFormats->queryKey(sFormatDescription, aDescriptionLanguage, sal_False); + if (nKey == (sal_Int32)-1) + { // noch nicht vorhanden in meinem Formatter ... + nKey = xFormats->addNew(sFormatDescription, aDescriptionLanguage); + } + } + } + if ((nVersion == 0x0002) || (nVersion == 0x0003)) + readCommonEditProperties(_rxInStream); + + if (nVersion == 0x0003) + { // since version 3 there is a "skippable" block at this position + Reference< XDataInputStream > xIn(_rxInStream, UNO_QUERY); + OStreamSection aDownCompat(xIn); + + sal_Int16 nSubVersion = _rxInStream->readShort(); + (void)nSubVersion; + + // version 0 and higher : the "effective value" property + Any aEffectiveValue; + { + OStreamSection aDownCompat2(xIn); + switch (_rxInStream->readShort()) + { + case 0: // String + aEffectiveValue <<= _rxInStream->readUTF(); + break; + case 1: // double + aEffectiveValue <<= (double)_rxInStream->readDouble(); + break; + case 2: + break; + case 3: + DBG_ERROR("FmXFormattedModel::read : unknown effective value type !"); + } + } + + // this property is only to be set if we have no control source : in all other cases the base class did a + // reset after it's read and this set the effective value to a default value + if ( m_xAggregateSet.is() && ( getControlSource().getLength() == 0 ) ) + { + try + { + m_xAggregateSet->setPropertyValue(PROPERTY_EFFECTIVE_VALUE, aEffectiveValue); + } + catch(Exception&) + { + } + } + } + } + break; + default : + DBG_ERROR("OFormattedModel::read : unknown version !"); + // dann bleibt das Format des aggregierten Sets, wie es bei der Erzeugung ist : void + defaultCommonEditProperties(); + break; + } + + if ((nKey != -1) && m_xAggregateSet.is()) + { + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier)); + m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, makeAny((sal_Int32)nKey)); + } + else + { + setPropertyToDefault(PROPERTY_FORMATSSUPPLIER); + setPropertyToDefault(PROPERTY_FORMATKEY); + } +} + +//------------------------------------------------------------------------------ +sal_uInt16 OFormattedModel::getPersistenceFlags() const +{ + return (OEditBaseModel::getPersistenceFlags() & ~PF_HANDLE_COMMON_PROPS); + // a) we do our own call to writeCommonEditProperties +} + +//------------------------------------------------------------------------------ +sal_Bool OFormattedModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( aControlValue != m_aSaveValue ) + { + // Leerstring + EmptyIsNull = void + if ( !aControlValue.hasValue() + || ( ( aControlValue.getValueType().getTypeClass() == TypeClass_STRING ) + && ( getString( aControlValue ).getLength() == 0 ) + && m_bEmptyIsNull + ) + ) + m_xColumnUpdate->updateNull(); + else + { + // als Value koennen nur double, string oder void auftreten + try + { + if ( aControlValue.getValueType().getTypeClass() == TypeClass_DOUBLE ) + { + DBTypeConversion::setValue( m_xColumnUpdate, m_aNullDate, getDouble( aControlValue ), m_nKeyType ); + } + else + { + DBG_ASSERT( aControlValue.getValueType().getTypeClass() == TypeClass_STRING, "OFormattedModel::commitControlValueToDbColumn: invalud value type !" ); + m_xColumnUpdate->updateString( getString( aControlValue ) ); + } + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +void OFormattedModel::onConnectedExternalValue( ) +{ + OEditBaseModel::onConnectedExternalValue(); + updateFormatterNullDate(); +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + Any aControlValue; + switch( _rExternalValue.getValueTypeClass() ) + { + case TypeClass_VOID: + break; + + case TypeClass_STRING: + aControlValue = _rExternalValue; + break; + + case TypeClass_BOOLEAN: + { + sal_Bool bExternalValue = sal_False; + _rExternalValue >>= bExternalValue; + aControlValue <<= (double)( bExternalValue ? 1 : 0 ); + } + break; + + default: + { + if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) ) + { + UNODate aDate; + _rExternalValue >>= aDate; + aControlValue <<= DBTypeConversion::toDouble( aDate, m_aNullDate ); + } + else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) ) + { + UNOTime aTime; + _rExternalValue >>= aTime; + aControlValue <<= DBTypeConversion::toDouble( aTime ); + } + else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) ) + { + UNODateTime aDateTime; + _rExternalValue >>= aDateTime; + aControlValue <<= DBTypeConversion::toDouble( aDateTime, m_aNullDate ); + } + else + { + OSL_ENSURE( _rExternalValue.getValueTypeClass() == TypeClass_DOUBLE, + "OFormattedModel::translateExternalValueToControlValue: don't know how to translate this type!" ); + double fValue = 0; + OSL_VERIFY( _rExternalValue >>= fValue ); + aControlValue <<= fValue; + } + } + } + + return aControlValue; +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::translateControlValueToExternalValue( ) const +{ + OSL_PRECOND( hasExternalValueBinding(), + "OFormattedModel::translateControlValueToExternalValue: precondition not met!" ); + + Any aControlValue( getControlValue() ); + if ( !aControlValue.hasValue() ) + return aControlValue; + + Any aExternalValue; + + // translate into the the external value type + Type aExternalValueType( getExternalValueType() ); + switch ( aExternalValueType.getTypeClass() ) + { + case TypeClass_STRING: + { + ::rtl::OUString sString; + if ( aControlValue >>= sString ) + { + aExternalValue <<= sString; + break; + } + } + // NO break here! + + case TypeClass_BOOLEAN: + { + double fValue = 0; + OSL_VERIFY( aControlValue >>= fValue ); + // if this asserts ... well, the somebody set the TreatAsNumeric property to false, + // and the control value is a string. This implies some weird misconfiguration + // of the FormattedModel, so we won't care for it for the moment. + aExternalValue <<= (sal_Bool)( fValue ? sal_True : sal_False ); + } + break; + + default: + { + double fValue = 0; + OSL_VERIFY( aControlValue >>= fValue ); + // if this asserts ... well, the somebody set the TreatAsNumeric property to false, + // and the control value is a string. This implies some weird misconfiguration + // of the FormattedModel, so we won't care for it for the moment. + + if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) ) + { + aExternalValue <<= DBTypeConversion::toDate( fValue, m_aNullDate ); + } + else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) ) + { + aExternalValue <<= DBTypeConversion::toTime( fValue ); + } + else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) ) + { + aExternalValue <<= DBTypeConversion::toDateTime( fValue, m_aNullDate ); + } + else + { + OSL_ENSURE( aExternalValueType.equals( ::getCppuType( static_cast< double* >( NULL ) ) ), + "OFormattedModel::translateControlValueToExternalValue: don't know how to translate this type!" ); + aExternalValue <<= fValue; + } + } + break; + } + return aExternalValue; +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::translateDbColumnToControlValue() +{ + if ( m_bNumeric ) + m_aSaveValue <<= DBTypeConversion::getValue( m_xColumn, m_aNullDate, m_nKeyType ); // #100056# OJ + else + m_aSaveValue <<= m_xColumn->getString(); + + if ( m_xColumn->wasNull() ) + m_aSaveValue.clear(); + + return m_aSaveValue; +} + +// ----------------------------------------------------------------------------- +Sequence< Type > OFormattedModel::getSupportedBindingTypes() +{ + ::std::list< Type > aTypes; + aTypes.push_back( ::getCppuType( static_cast< double* >( NULL ) ) ); + + switch ( m_nKeyType & ~NumberFormat::DEFINED ) + { + case NumberFormat::DATE: + aTypes.push_front(::getCppuType( static_cast< UNODate* >( NULL ) ) ); + break; + case NumberFormat::TIME: + aTypes.push_front(::getCppuType( static_cast< UNOTime* >( NULL ) ) ); + break; + case NumberFormat::DATETIME: + aTypes.push_front(::getCppuType( static_cast< UNODateTime* >( NULL ) ) ); + break; + case NumberFormat::TEXT: + aTypes.push_front(::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ) ); + break; + case NumberFormat::LOGICAL: + aTypes.push_front(::getCppuType( static_cast< sal_Bool* >( NULL ) ) ); + break; + } + + Sequence< Type > aTypesRet( aTypes.size() ); + ::std::copy( aTypes.begin(), aTypes.end(), aTypesRet.getArray() ); + return aTypesRet; +} + +//------------------------------------------------------------------------------ +Any OFormattedModel::getDefaultForReset() const +{ + return m_xAggregateSet->getPropertyValue( PROPERTY_EFFECTIVE_DEFAULT ); +} + +//------------------------------------------------------------------------------ +void OFormattedModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//......................................................................... +} +//......................................................................... diff --git a/forms/source/component/FormattedField.hxx b/forms/source/component/FormattedField.hxx new file mode 100644 index 000000000000..42c7a5b1bf2a --- /dev/null +++ b/forms/source/component/FormattedField.hxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * 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_FORMATTEDFIELD_HXX_ +#define _FORMS_FORMATTEDFIELD_HXX_ + +#include "EditBase.hxx" +#include <comphelper/propmultiplex.hxx> +#include <cppuhelper/implbase1.hxx> +#include "errorbroadcaster.hxx" + +//......................................................................... +namespace frm +{ + + //================================================================== + //= OFormattedModel + //================================================================== + + class OFormattedModel + :public OEditBaseModel + ,public OErrorBroadcaster + { + // das Original, falls ich die Format-Properties meines aggregierten Models gefaket, d.h. von dem Feld, an das + // ich gebunden bin, weitergereicht habe (nur gueltig wenn loaded) + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier> m_xOriginalFormatter; + ::com::sun::star::util::Date m_aNullDate; + ::com::sun::star::uno::Any m_aSaveValue; + + sal_Int32 m_nFieldType; + sal_Int16 m_nKeyType; + sal_Bool m_bOriginalNumeric : 1, + m_bNumeric : 1; // analog fuer TreatAsNumeric-Property + + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier> calcDefaultFormatsSupplier() const; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier> calcFormFormatsSupplier() const; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier> calcFormatsSupplier() const; + + DECLARE_DEFAULT_LEAF_XTOR( OFormattedModel ); + + friend class OFormattedFieldWrapper; + + protected: + // XInterface + DECLARE_UNO3_AGG_DEFAULTS( OFormattedModel, OEditBaseModel ); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + // XAggregation + 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(); + + // XServiceInfo + IMPLEMENTATION_NAME(OFormattedModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // XPersistObject + 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); + virtual ::rtl::OUString SAL_CALL getServiceName() 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); + + // XLoadListener + virtual void SAL_CALL loaded(const ::com::sun::star::lang::EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException); + + // XPropertyState + void setPropertyToDefaultByHandle(sal_Int32 nHandle); + ::com::sun::star::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const; + + void SAL_CALL setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Any SAL_CALL getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // XPropertyChangeListener + virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OEditBaseModel::disposing; + using OEditBaseModel::getFastPropertyValue; + + protected: + virtual sal_uInt16 getPersistenceFlags() const; + // as we have an own version handling for persistence + + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + virtual void onConnectedExternalValue( ); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + private: + DECLARE_XCLONEABLE(); + + void implConstruct(); + + void updateFormatterNullDate(); + }; + + //================================================================== + //= OFormattedControl + //================================================================== + typedef ::cppu::ImplHelper1< ::com::sun::star::awt::XKeyListener> OFormattedControl_BASE; + class OFormattedControl : public OBoundControl + ,public OFormattedControl_BASE + { + sal_uInt32 m_nKeyEvent; + + public: + OFormattedControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + virtual ~OFormattedControl(); + + DECLARE_UNO3_AGG_DEFAULTS(OFormattedControl, OBoundControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OFormattedControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::awt::XKeyListener + virtual void SAL_CALL keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::awt::XControl + virtual void SAL_CALL setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException); + + // disambiguation + using OBoundControl::disposing; + + private: + DECL_LINK( OnKeyPressed, void* ); + }; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_FORMATTEDFIELD_HXX_ + diff --git a/forms/source/component/FormattedFieldWrapper.cxx b/forms/source/component/FormattedFieldWrapper.cxx new file mode 100644 index 000000000000..cf9a04074cfc --- /dev/null +++ b/forms/source/component/FormattedFieldWrapper.cxx @@ -0,0 +1,398 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "FormattedFieldWrapper.hxx" +#include "Edit.hxx" +#include "FormattedField.hxx" +#include <tools/debug.hxx> +#include "EditBase.hxx" +#include "services.hxx" +#include <connectivity/dbtools.hxx> +#include <vcl/svapp.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//================================================================== +// OFormattedFieldWrapper +//================================================================== +DBG_NAME(OFormattedFieldWrapper) +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance_ForceFormatted(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFormattedFieldWrapper(_rxFactory, sal_True)); +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFormattedFieldWrapper(_rxFactory, sal_False)); +} + +//------------------------------------------------------------------ +OFormattedFieldWrapper::OFormattedFieldWrapper(const Reference<XMultiServiceFactory>& _rxFactory, sal_Bool _bActAsFormatted) + :m_xServiceFactory(_rxFactory) + ,m_pEditPart(NULL) +{ + DBG_CTOR(OFormattedFieldWrapper, NULL); + + if (_bActAsFormatted) + { + increment(m_refCount); + { + // instantiate an FormattedModel + InterfaceRef xFormattedModel; + // (instantiate it directly ..., as the OFormattedModel isn't registered for any service names anymore) + OFormattedModel* pModel = new OFormattedModel(m_xServiceFactory); + query_interface(static_cast<XWeak*>(pModel), xFormattedModel); + + m_xAggregate = Reference<XAggregation> (xFormattedModel, UNO_QUERY); + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::OFormattedFieldWrapper : the OFormattedModel didn't have an XAggregation interface !"); + + // _before_ setting the delegator, give it to the member references + query_interface(xFormattedModel, m_xFormattedPart); + m_pEditPart = new OEditModel(m_xServiceFactory); + m_pEditPart->acquire(); + } + if (m_xAggregate.is()) + { // has to be in it's own block because of the temporary variable created by *this + m_xAggregate->setDelegator(static_cast<XWeak*>(this)); + } + decrement(m_refCount); + } +} + +//------------------------------------------------------------------ +OFormattedFieldWrapper::OFormattedFieldWrapper( const OFormattedFieldWrapper* _pCloneSource ) + :m_xServiceFactory( _pCloneSource->m_xServiceFactory ) + ,m_pEditPart( NULL ) +{ + Reference< XCloneable > xCloneAccess; + query_aggregation( _pCloneSource->m_xAggregate, xCloneAccess ); + + // clone the aggregate + if ( xCloneAccess.is() ) + { + increment( m_refCount ); + { + Reference< XCloneable > xClone = xCloneAccess->createClone(); + m_xAggregate = Reference< XAggregation >( xClone, UNO_QUERY ); + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::OFormattedFieldWrapper : invalid aggregate clone!"); + + query_interface( Reference< XInterface >( xClone.get() ), m_xFormattedPart ); + + if ( _pCloneSource->m_pEditPart ) + { + m_pEditPart = new OEditModel( _pCloneSource->m_pEditPart, _pCloneSource->m_xServiceFactory ); + m_pEditPart->acquire(); + } + } + if ( m_xAggregate.is() ) + { // has to be in it's own block because of the temporary variable created by *this + m_xAggregate->setDelegator( static_cast< XWeak* >( this ) ); + } + decrement( m_refCount ); + } + else + { // the clone source does not yet have an aggregate -> we don't yet need one, too + } +} + +//------------------------------------------------------------------ +OFormattedFieldWrapper::~OFormattedFieldWrapper() +{ + // release the aggregated object (if any) + if (m_xAggregate.is()) + m_xAggregate->setDelegator(InterfaceRef ()); + + if (m_pEditPart) + m_pEditPart->release(); + + DBG_DTOR(OFormattedFieldWrapper, NULL); +} + +//------------------------------------------------------------------ +Any SAL_CALL OFormattedFieldWrapper::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn; + + if (_rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >(NULL) ) ) ) + { // a XTypeProvider interface needs a working aggregate - we don't want to give the type provider + // of our base class (OFormattedFieldWrapper_Base) to the caller as it supplies nearly nothing + ensureAggregate(); + if (m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + + if (!aReturn.hasValue()) + { + aReturn = OFormattedFieldWrapper_Base::queryAggregation(_rType); + + if ((_rType.equals( ::getCppuType( static_cast< Reference< XServiceInfo >* >(NULL) ) ) ) && aReturn.hasValue()) + { // somebody requested an XServiceInfo interface and our base class provided it + // check our aggregate if it has one, too + ensureAggregate(); + } + + if (!aReturn.hasValue()) + { + aReturn = ::cppu::queryInterface( _rType, + static_cast< XPersistObject* >( this ), + static_cast< XCloneable* >( this ) + ); + + if (!aReturn.hasValue()) + { + // somebody requests an interface other than the basics (XInterface) and other than + // the two we can supply without an aggregate. So ensure + // the aggregate exists. + ensureAggregate(); + if (m_xAggregate.is()) + aReturn = m_xAggregate->queryAggregation(_rType); + } + } + } + + return aReturn; +} + +//------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormattedFieldWrapper::getServiceName() throw(RuntimeException) +{ + // return the old compatibility name for an EditModel + return FRM_COMPONENT_EDIT; +} + +//------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormattedFieldWrapper::getImplementationName( ) throw (RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.forms.OFormattedFieldWrapper"); +} + +//------------------------------------------------------------------ +sal_Bool SAL_CALL OFormattedFieldWrapper::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::supportsService: should never have made it 'til here without an aggregate!"); + Reference< XServiceInfo > xSI; + m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI; + return xSI->supportsService(_rServiceName); +} + +//------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL OFormattedFieldWrapper::getSupportedServiceNames( ) throw (RuntimeException) +{ + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::getSupportedServiceNames: should never have made it 'til here without an aggregate!"); + Reference< XServiceInfo > xSI; + m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI; + return xSI->getSupportedServiceNames(); +} + +//------------------------------------------------------------------ +void SAL_CALL OFormattedFieldWrapper::write(const Reference<XObjectOutputStream>& _rxOutStream) throw( IOException, RuntimeException ) +{ + // can't write myself + ensureAggregate(); + + // if we act as real edit field, we can simple forward this write request + if (!m_xFormattedPart.is()) + { + Reference<XPersistObject> xAggregatePersistence; + query_aggregation(m_xAggregate, xAggregatePersistence); + DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::write : don't know how to handle this : can't write !"); + // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ... + if (xAggregatePersistence.is()) + xAggregatePersistence->write(_rxOutStream); + return; + } + + // else we have to write an edit part first + DBG_ASSERT(m_pEditPart, "OFormattedFieldWrapper::write : formatted part without edit part ?"); + if ( !m_pEditPart ) + throw RuntimeException( ::rtl::OUString(), *this ); + + // for this we transfer the current props of the formatted part to the edit part + Reference<XPropertySet> xFormatProps(m_xFormattedPart, UNO_QUERY); + Reference<XPropertySet> xEditProps; + query_interface(static_cast<XWeak*>(m_pEditPart), xEditProps); + + Locale aAppLanguage = Application::GetSettings().GetUILocale(); + dbtools::TransferFormComponentProperties(xFormatProps, xEditProps, aAppLanguage); + + // then write the edit part, after switching to "fake mode" + m_pEditPart->enableFormattedWriteFake(); + m_pEditPart->write(_rxOutStream); + m_pEditPart->disableFormattedWriteFake(); + + // and finally write the formatted part we're really interested in + m_xFormattedPart->write(_rxOutStream); +} + +//------------------------------------------------------------------ +void SAL_CALL OFormattedFieldWrapper::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException ) +{ + if (m_xAggregate.is()) + { // we alread did a decision if we're an EditModel or a FormattedModel + + // if we act as formatted, we have to read the edit part first + if (m_xFormattedPart.is()) + { + // two possible cases: + // a) the stuff was written by a version which didn't work with an Edit header (all intermediate + // versions >5.1 && <=568) + // b) it was written by a version using edit headers + // as we can distinguish a) from b) only after we have read the edit part, we need to remember the + // position + Reference<XMarkableStream> xInMarkable(_rxInStream, UNO_QUERY); + DBG_ASSERT(xInMarkable.is(), "OFormattedFieldWrapper::read : can only work with markable streams !"); + sal_Int32 nBeforeEditPart = xInMarkable->createMark(); + + m_pEditPart->read(_rxInStream); + // this only works because an edit model can read the stuff written by a formatted model (maybe with + // some assertions) , but not vice versa + if (!m_pEditPart->lastReadWasFormattedFake()) + { // case a), written with a version without the edit part fake, so seek to the start position, again + xInMarkable->jumpToMark(nBeforeEditPart); + } + xInMarkable->deleteMark(nBeforeEditPart); + } + + Reference<XPersistObject> xAggregatePersistence; + query_aggregation(m_xAggregate, xAggregatePersistence); + DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::read : don't know how to handle this : can't read !"); + // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ... + + if (xAggregatePersistence.is()) + xAggregatePersistence->read(_rxInStream); + return; + } + + // we have to decide from the data within the stream whether we should be an EditModel or a FormattedModel + OEditBaseModel* pNewAggregate = NULL; + + // let an OEditModel do the reading + OEditModel* pBasicReader = new OEditModel(m_xServiceFactory); + Reference< XInterface > xHoldBasicReaderAlive( *pBasicReader ); + pBasicReader->read(_rxInStream); + + // was it really an edit model ? + if (!pBasicReader->lastReadWasFormattedFake()) + // yes -> all fine + pNewAggregate = pBasicReader; + else + { // no -> substitute it with a formatted model + + // let the formmatted model do the reading + OFormattedModel* pFormattedReader = new OFormattedModel(m_xServiceFactory); + Reference< XInterface > xHoldAliveWhileRead( *pFormattedReader ); + pFormattedReader->read(_rxInStream); + + // for the next write (if any) : the FormattedModel and the EditModel parts + query_interface(static_cast<XWeak*>(pFormattedReader), m_xFormattedPart); + m_pEditPart = pBasicReader; + m_pEditPart->acquire(); + + // aggregate the formatted part below + pNewAggregate = pFormattedReader; + } + + // do the aggregation + increment(m_refCount); + { + query_interface(static_cast<XWeak*>(pNewAggregate), m_xAggregate); + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::read : the OEditModel didn't have an XAggregation interface !"); + } + if (m_xAggregate.is()) + { // has to be in it's own block because of the temporary variable created by *this + m_xAggregate->setDelegator(static_cast<XWeak*>(this)); + } + decrement(m_refCount); +} + +//------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL OFormattedFieldWrapper::createClone( ) throw (RuntimeException) +{ + ensureAggregate(); + + return new OFormattedFieldWrapper( this ); +} + +//------------------------------------------------------------------ +void OFormattedFieldWrapper::ensureAggregate() +{ + if (m_xAggregate.is()) + return; + + increment(m_refCount); + { + // instantiate an EditModel (the only place where we are allowed to decide that we're an FormattedModel + // is in ::read) + InterfaceRef xEditModel = m_xServiceFactory->createInstance(FRM_SUN_COMPONENT_TEXTFIELD); + if (!xEditModel.is()) + { + // arghhh ... instantiate it directly ... it's dirty, but we really need this aggregate + OEditModel* pModel = new OEditModel(m_xServiceFactory); + query_interface(static_cast<XWeak*>(pModel), xEditModel); + } + + m_xAggregate = Reference<XAggregation> (xEditModel, UNO_QUERY); + DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::ensureAggregate : the OEditModel didn't have an XAggregation interface !"); + + { + Reference< XServiceInfo > xSI(m_xAggregate, UNO_QUERY); + if (!xSI.is()) + { + DBG_ERROR("OFormattedFieldWrapper::ensureAggregate: the aggregate has no XServiceInfo!"); + m_xAggregate.clear(); + } + } + } + if (m_xAggregate.is()) + { // has to be in it's own block because of the temporary variable created by *this + m_xAggregate->setDelegator(static_cast<XWeak*>(this)); + } + decrement(m_refCount); +} + +//......................................................................... +} +//......................................................................... + + diff --git a/forms/source/component/FormattedFieldWrapper.hxx b/forms/source/component/FormattedFieldWrapper.hxx new file mode 100644 index 000000000000..a3cfcaab50d0 --- /dev/null +++ b/forms/source/component/FormattedFieldWrapper.hxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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 _FRM_FORMATTED_FIELD_WRAPPER_HXX_ +#define _FRM_FORMATTED_FIELD_WRAPPER_HXX_ + +#include "FormComponent.hxx" +#include <cppuhelper/implbase3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XCloneable.hpp> + +//......................................................................... +namespace frm +{ + +class OEditModel; +//================================================================== +//= OFormattedFieldWrapper +//================================================================== +typedef ::cppu::WeakAggImplHelper3 < ::com::sun::star::io::XPersistObject + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::util::XCloneable + > OFormattedFieldWrapper_Base; + +class OFormattedFieldWrapper : public OFormattedFieldWrapper_Base +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory> m_xServiceFactory; + +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> m_xAggregate; + + OEditModel* m_pEditPart; + // if we act as formatted this is used to write the EditModel part + ::com::sun::star::uno::Reference< ::com::sun::star::io::XPersistObject> m_xFormattedPart; + // if we act as formatted, this is the PersistObject interface of our aggregate, used + // to read and write the FormattedModel part + + OFormattedFieldWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, sal_Bool _bActAsFormatted); + // if _bActAsFormatted is sal_False, the state is undetermined until somebody calls ::read or does + // anything which requires a living aggregate + OFormattedFieldWrapper( const OFormattedFieldWrapper* _pCloneSource ); + virtual ~OFormattedFieldWrapper(); + + friend InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance_ForceFormatted(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + friend InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + +public: + // UNO + DECLARE_UNO3_AGG_DEFAULTS(OFormattedFieldWrapper, OWeakAggObject); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // 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); + + // XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException); + +protected: + /// ensure we're in a defined state, which means a FormattedModel _OR_ an EditModel + void ensureAggregate(); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FRM_FORMATTED_FIELD_WRAPPER_HXX_ + diff --git a/forms/source/component/FormsCollection.cxx b/forms/source/component/FormsCollection.cxx new file mode 100644 index 000000000000..2664a74546e8 --- /dev/null +++ b/forms/source/component/FormsCollection.cxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "FormsCollection.hxx" +#include "services.hxx" +#include <comphelper/sequence.hxx> +#include <tools/debug.hxx> +#include <com/sun/star/form/XForm.hpp> +#include <rtl/logfile.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; + +//------------------------------------------------------------------ +DBG_NAME(OFormsCollection) +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OFormsCollection_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OFormsCollection(_rxFactory)); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormsCollection::getServiceName() throw(RuntimeException) +{ + return FRM_SUN_FORMS_COLLECTION; +} + +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > SAL_CALL OFormsCollection::getImplementationId( ) throw(RuntimeException) +{ + return OImplementationIds::getImplementationId(getTypes()); +} + +//------------------------------------------------------------------------------ +Sequence<Type> SAL_CALL OFormsCollection::getTypes() throw(RuntimeException) +{ + return concatSequences(OInterfaceContainer::getTypes(), FormsCollectionComponentBase::getTypes(), OFormsCollection_BASE::getTypes()); +} + +//------------------------------------------------------------------ +OFormsCollection::OFormsCollection(const Reference<XMultiServiceFactory>& _rxFactory) + :FormsCollectionComponentBase( m_aMutex ) + ,OInterfaceContainer( _rxFactory, m_aMutex, XForm::static_type() ) + ,OFormsCollection_BASE() +{ + DBG_CTOR(OFormsCollection, NULL); +} + +//------------------------------------------------------------------------------ +OFormsCollection::OFormsCollection( const OFormsCollection& _cloneSource ) + :FormsCollectionComponentBase( m_aMutex ) + ,OInterfaceContainer( m_aMutex, _cloneSource ) + ,OFormsCollection_BASE() +{ + DBG_CTOR( OFormsCollection, NULL ); +} + +//------------------------------------------------------------------------------ +OFormsCollection::~OFormsCollection() +{ + DBG_DTOR(OFormsCollection, NULL); + if (!FormsCollectionComponentBase::rBHelper.bDisposed) + { + acquire(); + dispose(); + } +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OFormsCollection::queryAggregation(const Type& _rType) throw(RuntimeException) +{ + Any aReturn = OFormsCollection_BASE::queryInterface(_rType); + if (!aReturn.hasValue()) + { + aReturn = OInterfaceContainer::queryInterface(_rType); + + if (!aReturn.hasValue()) + aReturn = FormsCollectionComponentBase::queryAggregation(_rType); + } + + return aReturn; +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OFormsCollection::getImplementationName() throw(RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.forms.OFormsCollection"); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OFormsCollection::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) +{ + Sequence<rtl::OUString> aSupported = getSupportedServiceNames(); + const rtl::OUString* pSupported = aSupported.getConstArray(); + for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported) + if (pSupported->equals(_rServiceName)) + return sal_True; + return sal_False; +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OFormsCollection::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aReturn(2); + + aReturn.getArray()[0] = FRM_SUN_FORMS_COLLECTION; + aReturn.getArray()[1] = ::rtl::OUString::createFromAscii("com.sun.star.form.FormComponents"); + + return aReturn; +} + +// XCloneable +//------------------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL OFormsCollection::createClone( ) throw (RuntimeException) +{ + OFormsCollection* pClone = new OFormsCollection( *this ); + osl_incrementInterlockedCount( &pClone->m_refCount ); + pClone->clonedFrom( *this ); + osl_decrementInterlockedCount( &pClone->m_refCount ); + return pClone; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OFormsCollection::disposing() +{ + { + RTL_LOGFILE_CONTEXT( aLogger, "forms::OFormsCollection::disposing" ); + OInterfaceContainer::disposing(); + } + FormsCollectionComponentBase::disposing(); + m_xParent = NULL; +} + +//XChild +//------------------------------------------------------------------------------ +void OFormsCollection::setParent(const InterfaceRef& Parent) throw( NoSupportException, RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_xParent = Parent; +} + +//------------------------------------------------------------------------------ +InterfaceRef OFormsCollection::getParent() throw( RuntimeException ) +{ + return m_xParent; +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/FormsCollection.hxx b/forms/source/component/FormsCollection.hxx new file mode 100644 index 000000000000..705ac89b211a --- /dev/null +++ b/forms/source/component/FormsCollection.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#include "InterfaceContainer.hxx" +#include "ids.hxx" +#include <cppuhelper/component.hxx> +#include <cppuhelper/implbase2.hxx> +#include <comphelper/uno3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OFormsCollection +// Implementiert den UNO-Container fuer Formulare +// enthaelt alle zugeordneten Forms +// dieses Container kann selbst den Context fuer Formulare darstellen +// oder aussen einen Context uebergeben bekommen +//================================================================== +typedef ::cppu::OComponentHelper FormsCollectionComponentBase; +typedef ::cppu::ImplHelper2< ::com::sun::star::container::XChild + ,::com::sun::star::lang::XServiceInfo > OFormsCollection_BASE; + + // else MSVC kills itself on some statements +class OFormsCollection + :public FormsCollectionComponentBase + ,public OInterfaceContainer + ,public OFormsCollection_BASE +{ + ::osl::Mutex m_aMutex; + OImplementationIdsRef m_aHoldIdHelper; + ::comphelper::InterfaceRef m_xParent; // Parent + +public: + OFormsCollection(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + OFormsCollection( const OFormsCollection& _cloneSource ); + virtual ~OFormsCollection(); + +public: + DECLARE_UNO3_AGG_DEFAULTS(OFormsCollection, FormsCollectionComponentBase); + + 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< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + + // XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + 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); + + // XCloneable + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone( ) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // ::com::sun::star::container::XChild + virtual ::comphelper::InterfaceRef SAL_CALL getParent() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent(const ::comphelper::InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OInterfaceContainer::disposing; +}; + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Grid.cxx b/forms/source/component/Grid.cxx new file mode 100644 index 000000000000..c7b65906dc30 --- /dev/null +++ b/forms/source/component/Grid.cxx @@ -0,0 +1,1163 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "Columns.hxx" +#include "findpos.hxx" +#include "Grid.hxx" +#include "property.hrc" +#include "property.hxx" +#include "services.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/text/WritingMode2.hpp> +/** === end UNO includes === **/ + +#include <comphelper/basicio.hxx> +#include <comphelper/container.hxx> +#include <comphelper/extract.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> + +using namespace ::com::sun::star::uno; + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::view; + +namespace WritingMode2 = ::com::sun::star::text::WritingMode2; + +const sal_uInt16 ROWHEIGHT = 0x0001; +const sal_uInt16 FONTTYPE = 0x0002; +const sal_uInt16 FONTSIZE = 0x0004; +const sal_uInt16 FONTATTRIBS = 0x0008; +const sal_uInt16 TABSTOP = 0x0010; +const sal_uInt16 TEXTCOLOR = 0x0020; +const sal_uInt16 FONTDESCRIPTOR = 0x0040; +const sal_uInt16 RECORDMARKER = 0x0080; +const sal_uInt16 BACKGROUNDCOLOR = 0x0100; + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OGridControlModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OGridControlModel(_rxFactory)); +} + +DBG_NAME(OGridControlModel); +//------------------------------------------------------------------ +OGridControlModel::OGridControlModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OControlModel(_rxFactory, ::rtl::OUString()) + ,OInterfaceContainer(_rxFactory, m_aMutex, ::getCppuType(static_cast<Reference<XPropertySet>*>(NULL))) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,FontControlModel( false ) + ,m_aSelectListeners(m_aMutex) + ,m_aResetListeners(m_aMutex) + ,m_aRowSetChangeListeners(m_aMutex) + ,m_aDefaultControl( FRM_SUN_CONTROL_GRIDCONTROL ) + ,m_nBorder(1) + ,m_nWritingMode( WritingMode2::CONTEXT ) + ,m_nContextWritingMode( WritingMode2::CONTEXT ) + ,m_bEnableVisible(sal_True) + ,m_bEnable(sal_True) + ,m_bNavigation(sal_True) + ,m_bRecordMarker(sal_True) + ,m_bPrintable(sal_True) + ,m_bAlwaysShowCursor(sal_False) + ,m_bDisplaySynchron(sal_True) +{ + DBG_CTOR(OGridControlModel,NULL); + + m_nClassId = FormComponentType::GRIDCONTROL; +} + +//------------------------------------------------------------------ +OGridControlModel::OGridControlModel( const OGridControlModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + ,OInterfaceContainer( _rxFactory, m_aMutex, ::getCppuType( static_cast<Reference<XPropertySet>*>( NULL ) ) ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,FontControlModel( _pOriginal ) + ,m_aSelectListeners( m_aMutex ) + ,m_aResetListeners( m_aMutex ) + ,m_aRowSetChangeListeners( m_aMutex ) +{ + DBG_CTOR(OGridControlModel,NULL); + + m_aDefaultControl = _pOriginal->m_aDefaultControl; + m_bEnable = _pOriginal->m_bEnable; + m_bEnableVisible = _pOriginal->m_bEnableVisible; + m_bNavigation = _pOriginal->m_bNavigation; + m_nBorder = _pOriginal->m_nBorder; + m_nWritingMode = _pOriginal->m_nWritingMode; + m_nContextWritingMode = _pOriginal->m_nContextWritingMode; + m_bRecordMarker = _pOriginal->m_bRecordMarker; + m_bPrintable = _pOriginal->m_bPrintable; + m_bAlwaysShowCursor = _pOriginal->m_bAlwaysShowCursor; + m_bDisplaySynchron = _pOriginal->m_bDisplaySynchron; + + // clone the columns + cloneColumns( _pOriginal ); + + // TODO: clone the events? +} + +//------------------------------------------------------------------ +OGridControlModel::~OGridControlModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OGridControlModel,NULL); +} + +// XCloneable +//------------------------------------------------------------------------------ +Reference< XCloneable > SAL_CALL OGridControlModel::createClone( ) throw (RuntimeException) +{ + OGridControlModel* pClone = new OGridControlModel( this, getContext().getLegacyServiceFactory() ); + osl_incrementInterlockedCount( &pClone->m_refCount ); + pClone->OControlModel::clonedFrom( this ); + // do not call OInterfaceContainer::clonedFrom, it would clone the elements aka columns, which is + // already done in the ctor + //pClone->OInterfaceContainer::clonedFrom( *this ); + osl_decrementInterlockedCount( &pClone->m_refCount ); + return static_cast< XCloneable* >( static_cast< OControlModel* >( pClone ) ); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::cloneColumns( const OGridControlModel* _pOriginalContainer ) +{ + try + { + Reference< XCloneable > xColCloneable; + + const OInterfaceArray::const_iterator pColumnStart = _pOriginalContainer->m_aItems.begin(); + const OInterfaceArray::const_iterator pColumnEnd = _pOriginalContainer->m_aItems.end(); + for ( OInterfaceArray::const_iterator pColumn = pColumnStart; pColumn != pColumnEnd; ++pColumn ) + { + // ask the col for a factory for the clone + xColCloneable = xColCloneable.query( *pColumn ); + DBG_ASSERT( xColCloneable.is(), "OGridControlModel::cloneColumns: column is not cloneable!" ); + + if ( xColCloneable.is() ) + { + // create a clone of the column + Reference< XCloneable > xColClone( xColCloneable->createClone() ); + DBG_ASSERT( xColClone.is(), "OGridControlModel::cloneColumns: invalid column clone!" ); + + if ( xColClone.is() ) + { + // insert this clone into our own container + insertByIndex( pColumn - pColumnStart, xColClone->queryInterface( m_aElementType ) ); + } + + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "OGridControlModel::cloneColumns: caught an exception while cloning the columns!" ); + } +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OGridControlModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 2); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-2] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlModel")); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_GRIDCONTROL; + return aSupported; +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OGridControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn = OGridControlModel_BASE::queryInterface(_rType); + + if ( !aReturn.hasValue() ) + { + aReturn = OControlModel::queryAggregation( _rType ); + if ( !aReturn.hasValue() ) + { + aReturn = OInterfaceContainer::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OErrorBroadcaster::queryInterface( _rType ); + } + } + return aReturn; +} + +// XSQLErrorListener +//------------------------------------------------------------------------------ +void SAL_CALL OGridControlModel::errorOccured( const SQLErrorEvent& _rEvent ) throw (RuntimeException) +{ + // forward the errors which happened to my columns to my own listeners + onError( _rEvent ); +} + +// XRowSetSupplier +//------------------------------------------------------------------------------ +Reference< XRowSet > SAL_CALL OGridControlModel::getRowSet( ) throw (RuntimeException) +{ + return Reference< XRowSet >( getParent(), UNO_QUERY ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OGridControlModel::setRowSet( const Reference< XRowSet >& /*_rxDataSource*/ ) throw (RuntimeException) +{ + OSL_ENSURE( false, "OGridControlModel::setRowSet: not supported!" ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OGridControlModel::addRowSetChangeListener( const Reference< XRowSetChangeListener >& i_Listener ) throw (RuntimeException) +{ + if ( i_Listener.is() ) + m_aRowSetChangeListeners.addInterface( i_Listener ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OGridControlModel::removeRowSetChangeListener( const Reference< XRowSetChangeListener >& i_Listener ) throw (RuntimeException) +{ + m_aRowSetChangeListeners.removeInterface( i_Listener ); +} + +// XChild +//------------------------------------------------------------------------------ +void SAL_CALL OGridControlModel::setParent( const InterfaceRef& i_Parent ) throw(NoSupportException, RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if ( i_Parent == getParent() ) + return; + + OControlModel::setParent( i_Parent ); + + EventObject aEvent( *this ); + aGuard.clear(); + m_aRowSetChangeListeners.notifyEach( &XRowSetChangeListener::onRowSetChanged, aEvent ); +} + +//------------------------------------------------------------------------------ +Sequence< Type > SAL_CALL OGridControlModel::getTypes( ) throw(RuntimeException) +{ + return concatSequences( + concatSequences( + OControlModel::getTypes(), + OInterfaceContainer::getTypes(), + OErrorBroadcaster::getTypes() + ), + OGridControlModel_BASE::getTypes() + ); +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OGridControlModel::disposing() +{ + OControlModel::disposing(); + OErrorBroadcaster::disposing(); + OInterfaceContainer::disposing(); + + setParent(NULL); + + EventObject aEvt(static_cast<XWeak*>(this)); + m_aSelectListeners.disposeAndClear(aEvt); + m_aResetListeners.disposeAndClear(aEvt); + m_aRowSetChangeListeners.disposeAndClear(aEvt); +} + +// XEventListener +//------------------------------------------------------------------------------ +void OGridControlModel::disposing(const EventObject& _rEvent) throw( RuntimeException ) +{ + OControlModel::disposing( _rEvent ); + OInterfaceContainer::disposing( _rEvent ); +} + +// XSelectionSupplier +//----------------------------------------------------------------------------- +sal_Bool SAL_CALL OGridControlModel::select(const Any& rElement) throw(IllegalArgumentException, RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + Reference<XPropertySet> xSel; + if (rElement.hasValue() && !::cppu::extractInterface(xSel, rElement)) + { + throw IllegalArgumentException(); + } + InterfaceRef xMe = static_cast<XWeak*>(this); + + if (xSel.is()) + { + Reference<XChild> xAsChild(xSel, UNO_QUERY); + if (!xAsChild.is() || (xAsChild->getParent() != xMe)) + { + throw IllegalArgumentException(); + } + } + + if ( xSel != m_xSelection ) + { + m_xSelection = xSel; + aGuard.clear(); + m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, EventObject( *this ) ); + return sal_True; + } + return sal_False; +} + +//----------------------------------------------------------------------------- +Any SAL_CALL OGridControlModel::getSelection() throw(RuntimeException) +{ + return makeAny(m_xSelection); +} + +//----------------------------------------------------------------------------- +void OGridControlModel::addSelectionChangeListener(const Reference< XSelectionChangeListener >& _rxListener) throw( RuntimeException ) +{ + m_aSelectListeners.addInterface(_rxListener); +} + +//----------------------------------------------------------------------------- +void OGridControlModel::removeSelectionChangeListener(const Reference< XSelectionChangeListener >& _rxListener) throw( RuntimeException ) +{ + m_aSelectListeners.removeInterface(_rxListener); +} + +// XGridColumnFactory +//------------------------------------------------------------------------------ +Reference<XPropertySet> SAL_CALL OGridControlModel::createColumn(const ::rtl::OUString& ColumnType) throw ( :: com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + const Sequence< ::rtl::OUString >& rColumnTypes = frm::getColumnTypes(); + return createColumn( detail::findPos( ColumnType, rColumnTypes ) ); +} + +//------------------------------------------------------------------------------ +Reference<XPropertySet> OGridControlModel::createColumn(sal_Int32 nTypeId) const +{ + Reference<XPropertySet> xReturn; + switch (nTypeId) + { + case TYPE_CHECKBOX: xReturn = new CheckBoxColumn( getContext() ); break; + case TYPE_COMBOBOX: xReturn = new ComboBoxColumn( getContext() ); break; + case TYPE_CURRENCYFIELD: xReturn = new CurrencyFieldColumn( getContext() ); break; + case TYPE_DATEFIELD: xReturn = new DateFieldColumn( getContext() ); break; + case TYPE_LISTBOX: xReturn = new ListBoxColumn( getContext() ); break; + case TYPE_NUMERICFIELD: xReturn = new NumericFieldColumn( getContext() ); break; + case TYPE_PATTERNFIELD: xReturn = new PatternFieldColumn( getContext() ); break; + case TYPE_TEXTFIELD: xReturn = new TextFieldColumn( getContext() ); break; + case TYPE_TIMEFIELD: xReturn = new TimeFieldColumn( getContext() ); break; + case TYPE_FORMATTEDFIELD: xReturn = new FormattedFieldColumn( getContext() ); break; + default: + DBG_ERROR("OGridControlModel::createColumn: Unknown Column"); + break; + } + return xReturn; +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OGridControlModel::getColumnTypes() throw ( ::com::sun::star::uno::RuntimeException) +{ + return frm::getColumnTypes(); +} + +// XReset +//----------------------------------------------------------------------------- +void SAL_CALL OGridControlModel::reset() throw ( ::com::sun::star::uno::RuntimeException) +{ + ::cppu::OInterfaceIteratorHelper aIter(m_aResetListeners); + EventObject aEvt(static_cast<XWeak*>(this)); + sal_Bool bContinue = sal_True; + while (aIter.hasMoreElements() && bContinue) + bContinue =((XResetListener*)aIter.next())->approveReset(aEvt); + + if (bContinue) + { + _reset(); + m_aResetListeners.notifyEach( &XResetListener::resetted, aEvt ); + } +} + +//----------------------------------------------------------------------------- +void SAL_CALL OGridControlModel::addResetListener(const Reference<XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aResetListeners.addInterface(_rxListener); +} + +//----------------------------------------------------------------------------- +void SAL_CALL OGridControlModel::removeResetListener(const Reference<XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException) +{ + m_aResetListeners.removeInterface(_rxListener); +} + +//----------------------------------------------------------------------------- +void OGridControlModel::_reset() +{ + Reference<XReset> xReset; + sal_Int32 nCount = getCount(); + for (sal_Int32 nIndex=0; nIndex < nCount; nIndex++) + { + getByIndex( nIndex ) >>= xReset; + if (xReset.is()) + xReset->reset(); + } +} + +// XPropertySet +//------------------------------------------------------------------------------ +void OGridControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_BASE_PROPERTIES( 37 ) + DECL_PROP1(NAME, ::rtl::OUString, BOUND); + DECL_PROP2(CLASSID, sal_Int16, READONLY, TRANSIENT); + DECL_PROP1(TAG, ::rtl::OUString, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP3(TABSTOP, sal_Bool, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP2(HASNAVIGATION, sal_Bool, BOUND, MAYBEDEFAULT); + DECL_PROP1(ENABLED, sal_Bool, BOUND); + DECL_PROP2(ENABLEVISIBLE, sal_Bool, BOUND, MAYBEDEFAULT); + DECL_PROP1(BORDER, sal_Int16, BOUND); + DECL_PROP2(BORDERCOLOR, sal_Int16, BOUND, MAYBEVOID); + DECL_PROP1(DEFAULTCONTROL, ::rtl::OUString, BOUND); + DECL_PROP3(TEXTCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP3(BACKGROUNDCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP2(FONT, FontDescriptor, BOUND, MAYBEDEFAULT); + DECL_PROP3(ROWHEIGHT, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(HELPTEXT, ::rtl::OUString, BOUND); + DECL_PROP1(FONT_NAME, ::rtl::OUString, MAYBEDEFAULT); + DECL_PROP1(FONT_STYLENAME, ::rtl::OUString, MAYBEDEFAULT); + DECL_PROP1(FONT_FAMILY, sal_Int16, MAYBEDEFAULT); + DECL_PROP1(FONT_CHARSET, sal_Int16, MAYBEDEFAULT); + DECL_PROP1(FONT_HEIGHT, float, MAYBEDEFAULT); + DECL_PROP1(FONT_WEIGHT, float, MAYBEDEFAULT); + DECL_PROP1(FONT_SLANT, sal_Int16, MAYBEDEFAULT); + DECL_PROP1(FONT_UNDERLINE, sal_Int16, MAYBEDEFAULT); + DECL_BOOL_PROP1(FONT_WORDLINEMODE, MAYBEDEFAULT); + DECL_PROP3(TEXTLINECOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP2(FONTEMPHASISMARK, sal_Int16, BOUND, MAYBEDEFAULT); + DECL_PROP2(FONTRELIEF, sal_Int16, BOUND, MAYBEDEFAULT); + DECL_PROP1(FONT_STRIKEOUT, sal_Int16, MAYBEDEFAULT); + DECL_PROP2(RECORDMARKER, sal_Bool, BOUND, MAYBEDEFAULT ); + DECL_PROP2(PRINTABLE, sal_Bool, BOUND, MAYBEDEFAULT ); + DECL_PROP4(CURSORCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID , TRANSIENT); + DECL_PROP3(ALWAYSSHOWCURSOR, sal_Bool, BOUND, MAYBEDEFAULT, TRANSIENT); + DECL_PROP3(DISPLAYSYNCHRON, sal_Bool, BOUND, MAYBEDEFAULT, TRANSIENT); + DECL_PROP2(HELPURL, ::rtl::OUString, BOUND, MAYBEDEFAULT); + DECL_PROP2(WRITING_MODE, sal_Int16, BOUND, MAYBEDEFAULT); + DECL_PROP3(CONTEXT_WRITING_MODE,sal_Int16, BOUND, MAYBEDEFAULT, TRANSIENT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const +{ + switch (nHandle) + { + case PROPERTY_ID_CONTEXT_WRITING_MODE: + rValue <<= m_nContextWritingMode; + break; + case PROPERTY_ID_WRITING_MODE: + rValue <<= m_nWritingMode; + break; + case PROPERTY_ID_HELPTEXT: + rValue <<= m_sHelpText; + break; + case PROPERTY_ID_HELPURL: + rValue <<= m_sHelpURL; + break; + case PROPERTY_ID_DISPLAYSYNCHRON: + setBOOL(rValue, m_bDisplaySynchron); + break; + case PROPERTY_ID_ALWAYSSHOWCURSOR: + setBOOL(rValue, m_bAlwaysShowCursor); + break; + case PROPERTY_ID_CURSORCOLOR: + rValue = m_aCursorColor; + break; + case PROPERTY_ID_PRINTABLE: + setBOOL(rValue, m_bPrintable); + break; + case PROPERTY_ID_TABSTOP: + rValue = m_aTabStop; + break; + case PROPERTY_ID_HASNAVIGATION: + setBOOL(rValue, m_bNavigation); + break; + case PROPERTY_ID_RECORDMARKER: + setBOOL(rValue, m_bRecordMarker); + break; + case PROPERTY_ID_ENABLED: + setBOOL(rValue, m_bEnable); + break; + case PROPERTY_ID_ENABLEVISIBLE: + setBOOL(rValue, m_bEnableVisible); + break; + case PROPERTY_ID_BORDER: + rValue <<= (sal_Int16)m_nBorder; + break; + case PROPERTY_ID_BORDERCOLOR: + rValue <<= m_aBorderColor; + break; + case PROPERTY_ID_DEFAULTCONTROL: + rValue <<= m_aDefaultControl; + break; + case PROPERTY_ID_BACKGROUNDCOLOR: + rValue = m_aBackgroundColor; + break; + case PROPERTY_ID_ROWHEIGHT: + rValue = m_aRowHeight; + break; + + default: + if ( isFontRelatedProperty( nHandle ) ) + FontControlModel::getFastPropertyValue( rValue, nHandle ); + else + OControlModel::getFastPropertyValue( rValue, nHandle ); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OGridControlModel::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue )throw( IllegalArgumentException ) +{ + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_CONTEXT_WRITING_MODE: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_nContextWritingMode ); + break; + case PROPERTY_ID_WRITING_MODE: + bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_nWritingMode ); + break; + case PROPERTY_ID_HELPTEXT: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sHelpText); + break; + case PROPERTY_ID_HELPURL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sHelpURL); + break; + case PROPERTY_ID_DISPLAYSYNCHRON: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDisplaySynchron); + break; + case PROPERTY_ID_ALWAYSSHOWCURSOR: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAlwaysShowCursor); + break; + case PROPERTY_ID_CURSORCOLOR: + if (!rValue.hasValue() || !m_aCursorColor.hasValue()) + { + if (rValue.hasValue() && (TypeClass_LONG != rValue.getValueType().getTypeClass())) + { + throw IllegalArgumentException(); + } + rOldValue = m_aCursorColor; + rConvertedValue = rValue; + bModified = (rOldValue.getValue() != rConvertedValue.getValue()); + } + else + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, getINT32(m_aCursorColor)); + break; + case PROPERTY_ID_PRINTABLE: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bPrintable); + break; + case PROPERTY_ID_TABSTOP: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTabStop, ::getBooleanCppuType()); + break; + case PROPERTY_ID_HASNAVIGATION: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bNavigation); + break; + case PROPERTY_ID_RECORDMARKER: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bRecordMarker); + break; + case PROPERTY_ID_ENABLED: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEnable); + break; + case PROPERTY_ID_ENABLEVISIBLE: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEnableVisible); + break; + case PROPERTY_ID_BORDER: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_nBorder); + break; + case PROPERTY_ID_BORDERCOLOR: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aBorderColor, ::getCppuType((const sal_Int32*)NULL)); + break; + case PROPERTY_ID_DEFAULTCONTROL: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefaultControl); + break; + case PROPERTY_ID_BACKGROUNDCOLOR: + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aBackgroundColor, ::getCppuType((const sal_Int32*)NULL)); + break; + case PROPERTY_ID_ROWHEIGHT: + { + bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aRowHeight, ::getCppuType((const sal_Int32*)NULL)); + + sal_Int32 nNewVal( 0 ); + if ( ( rConvertedValue >>= nNewVal ) && ( nNewVal <= 0 ) ) + { + rConvertedValue.clear(); + bModified = m_aRowHeight.hasValue(); + } + } + break; + default: + if ( isFontRelatedProperty( nHandle ) ) + bModified = FontControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); + else + bModified = OControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue); + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OGridControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw ( ::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_CONTEXT_WRITING_MODE: + rValue >>= m_nContextWritingMode; + break; + case PROPERTY_ID_WRITING_MODE: + rValue >>= m_nWritingMode; + break; + case PROPERTY_ID_HELPTEXT: + rValue >>= m_sHelpText; + break; + case PROPERTY_ID_HELPURL: + rValue >>= m_sHelpURL; + break; + case PROPERTY_ID_DISPLAYSYNCHRON: + m_bDisplaySynchron = getBOOL(rValue); + break; + case PROPERTY_ID_ALWAYSSHOWCURSOR: + m_bAlwaysShowCursor = getBOOL(rValue); + break; + case PROPERTY_ID_CURSORCOLOR: + m_aCursorColor = rValue; + break; + case PROPERTY_ID_PRINTABLE: + m_bPrintable = getBOOL(rValue); + break; + case PROPERTY_ID_TABSTOP: + m_aTabStop = rValue; + break; + case PROPERTY_ID_HASNAVIGATION: + m_bNavigation = getBOOL(rValue); + break; + case PROPERTY_ID_ENABLED: + m_bEnable = getBOOL(rValue); + break; + case PROPERTY_ID_ENABLEVISIBLE: + m_bEnableVisible = getBOOL(rValue); + break; + case PROPERTY_ID_RECORDMARKER: + m_bRecordMarker = getBOOL(rValue); + break; + case PROPERTY_ID_BORDER: + rValue >>= m_nBorder; + break; + case PROPERTY_ID_BORDERCOLOR: + m_aBorderColor = rValue; + break; + case PROPERTY_ID_DEFAULTCONTROL: + rValue >>= m_aDefaultControl; + break; + case PROPERTY_ID_BACKGROUNDCOLOR: + m_aBackgroundColor = rValue; + break; + case PROPERTY_ID_ROWHEIGHT: + m_aRowHeight = rValue; + break; + + default: + if ( isFontRelatedProperty( nHandle ) ) + { + FontDescriptor aOldFont( getFont() ); + + FontControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + + if ( isFontAggregateProperty( nHandle ) ) + firePropertyChange( PROPERTY_ID_FONT, makeAny( getFont() ), makeAny( aOldFont ) ); + } + else + OControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + } + +} + +//XPropertyState + +//------------------------------------------------------------------------------ +Any OGridControlModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const +{ + Any aReturn; + switch (nHandle) + { + case PROPERTY_ID_CONTEXT_WRITING_MODE: + case PROPERTY_ID_WRITING_MODE: + aReturn <<= WritingMode2::CONTEXT; + break; + + case PROPERTY_ID_DEFAULTCONTROL: + aReturn <<= ::rtl::OUString( STARDIV_ONE_FORM_CONTROL_GRID ); + break; + + case PROPERTY_ID_PRINTABLE: + case PROPERTY_ID_HASNAVIGATION: + case PROPERTY_ID_RECORDMARKER: + case PROPERTY_ID_DISPLAYSYNCHRON: + case PROPERTY_ID_ENABLED: + case PROPERTY_ID_ENABLEVISIBLE: + aReturn = makeBoolAny(sal_True); + break; + + case PROPERTY_ID_ALWAYSSHOWCURSOR: + aReturn = makeBoolAny(sal_False); + break; + + case PROPERTY_ID_HELPURL: + case PROPERTY_ID_HELPTEXT: + aReturn <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_BORDER: + aReturn <<= (sal_Int16)1; + break; + + case PROPERTY_ID_BORDERCOLOR: + case PROPERTY_ID_TABSTOP: + case PROPERTY_ID_BACKGROUNDCOLOR: + case PROPERTY_ID_ROWHEIGHT: + case PROPERTY_ID_CURSORCOLOR: + // void + break; + + default: + if ( isFontRelatedProperty( nHandle ) ) + aReturn = FontControlModel::getPropertyDefaultByHandle( nHandle ); + else + aReturn = OControlModel::getPropertyDefaultByHandle(nHandle); + } + return aReturn; +} + +//------------------------------------------------------------------------------ +OGridColumn* OGridControlModel::getColumnImplementation(const InterfaceRef& _rxIFace) const +{ + OGridColumn* pImplementation = NULL; + Reference< XUnoTunnel > xUnoTunnel( _rxIFace, UNO_QUERY ); + if ( xUnoTunnel.is() ) + pImplementation = reinterpret_cast<OGridColumn*>(xUnoTunnel->getSomething(OGridColumn::getUnoTunnelImplementationId())); + + return pImplementation; +} + +//------------------------------------------------------------------------------ +void OGridControlModel::gotColumn( const Reference< XInterface >& _rxColumn ) +{ + Reference< XSQLErrorBroadcaster > xBroadcaster( _rxColumn, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->addSQLErrorListener( this ); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::lostColumn(const Reference< XInterface >& _rxColumn) +{ + if ( m_xSelection == _rxColumn ) + { // the currently selected element was replaced + m_xSelection.clear(); + EventObject aEvt( static_cast< XWeak* >( this ) ); + m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvt ); + } + + Reference< XSQLErrorBroadcaster > xBroadcaster( _rxColumn, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->removeSQLErrorListener( this ); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::implRemoved(const InterfaceRef& _rxObject) +{ + OInterfaceContainer::implRemoved(_rxObject); + lostColumn(_rxObject); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::implInserted( const ElementDescription* _pElement ) +{ + OInterfaceContainer::implInserted( _pElement ); + gotColumn( _pElement->xInterface ); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::impl_replacedElement( const ContainerEvent& _rEvent, ::osl::ClearableMutexGuard& _rInstanceLock ) +{ + Reference< XInterface > xOldColumn( _rEvent.ReplacedElement, UNO_QUERY ); + Reference< XInterface > xNewColumn( _rEvent.Element, UNO_QUERY ); + + bool bNewSelection = ( xOldColumn == m_xSelection ); + + lostColumn( xOldColumn ); + gotColumn( xNewColumn ); + + if ( bNewSelection ) + m_xSelection.set( xNewColumn, UNO_QUERY ); + + OInterfaceContainer::impl_replacedElement( _rEvent, _rInstanceLock ); + // <<---- SYNCHRONIZED + + if ( bNewSelection ) + { + m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, EventObject( *this ) ); + } +} + +//------------------------------------------------------------------------------ +ElementDescription* OGridControlModel::createElementMetaData( ) +{ + return new ColumnDescription; +} + +//------------------------------------------------------------------------------ +void OGridControlModel::approveNewElement( const Reference< XPropertySet >& _rxObject, ElementDescription* _pElement ) +{ + OGridColumn* pCol = getColumnImplementation( _rxObject ); + if ( !pCol ) + throw IllegalArgumentException(); + + OInterfaceContainer::approveNewElement( _rxObject, _pElement ); + + // if we're here, the object passed all tests + if ( _pElement ) + static_cast< ColumnDescription* >( _pElement )->pColumn = pCol; +} + +// XPersistObject +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OGridControlModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_GRID; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OGridControlModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::write(_rxOutStream); + + Reference<XMarkableStream> xMark(_rxOutStream, UNO_QUERY); + + // 1. Version + _rxOutStream->writeShort(0x0008); + + // 2. Columns + sal_Int32 nLen = getCount(); + _rxOutStream->writeLong(nLen); + OGridColumn* pCol; + for (sal_Int32 i = 0; i < nLen; i++) + { + // zuerst den Servicenamen fuer das darunterliegende Model + pCol = getColumnImplementation(m_aItems[i]); + DBG_ASSERT(pCol != NULL, "OGridControlModel::write : such items should never reach it into my container !"); + + _rxOutStream << pCol->getModelName(); + + // dann das Object selbst + sal_Int32 nMark = xMark->createMark(); + sal_Int32 nObjLen = 0; + _rxOutStream->writeLong(nObjLen); + + // schreiben der Col + pCol->write(_rxOutStream); + + // feststellen der Laenge + nObjLen = xMark->offsetToMark(nMark) - 4; + xMark->jumpToMark(nMark); + _rxOutStream->writeLong(nObjLen); + xMark->jumpToFurthest(); + xMark->deleteMark(nMark); + } + + // 3. Events + writeEvents(_rxOutStream); + + // 4. Attribute + // Maskierung fuer alle any Typen + sal_uInt16 nAnyMask = 0; + if (m_aRowHeight.getValueType().getTypeClass() == TypeClass_LONG) + nAnyMask |= ROWHEIGHT; + if ( getFont() != getDefaultFont() ) + nAnyMask |= FONTATTRIBS | FONTSIZE | FONTTYPE | FONTDESCRIPTOR; + if (m_aTabStop.getValueType().getTypeClass() == TypeClass_BOOLEAN) + nAnyMask |= TABSTOP; + if ( hasTextColor() ) + nAnyMask |= TEXTCOLOR; + if (m_aBackgroundColor.getValueType().getTypeClass() == TypeClass_LONG) + nAnyMask |= BACKGROUNDCOLOR; + if (!m_bRecordMarker) + nAnyMask |= RECORDMARKER; + + _rxOutStream->writeShort(nAnyMask); + + if (nAnyMask & ROWHEIGHT) + _rxOutStream->writeLong(getINT32(m_aRowHeight)); + + // old structures + const FontDescriptor& aFont = getFont(); + if ( nAnyMask & FONTDESCRIPTOR ) + { + // Attrib + _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( VCLUnoHelper::ConvertFontWeight( aFont.Weight ) ) ); + _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( aFont.Slant ) ); + _rxOutStream->writeShort( aFont.Underline ); + _rxOutStream->writeShort( aFont.Strikeout ); + _rxOutStream->writeShort( sal_Int16(aFont.Orientation * 10) ); + _rxOutStream->writeBoolean( aFont.Kerning ); + _rxOutStream->writeBoolean( aFont.WordLineMode ); + + // Size + _rxOutStream->writeLong( aFont.Width ); + _rxOutStream->writeLong( aFont.Height ); + _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( VCLUnoHelper::ConvertFontWidth( aFont.CharacterWidth ) ) ); + + // Type + _rxOutStream->writeUTF( aFont.Name ); + _rxOutStream->writeUTF( aFont.StyleName ); + _rxOutStream->writeShort( aFont.Family ); + _rxOutStream->writeShort( aFont.CharSet ); + _rxOutStream->writeShort( aFont.Pitch ); + } + + _rxOutStream << m_aDefaultControl; + + _rxOutStream->writeShort(m_nBorder); + _rxOutStream->writeBoolean(m_bEnable); + + if (nAnyMask & TABSTOP) + _rxOutStream->writeBoolean(getBOOL(m_aTabStop)); + + _rxOutStream->writeBoolean(m_bNavigation); + + if (nAnyMask & TEXTCOLOR) + _rxOutStream->writeLong( getTextColor() ); + + // neu ab Version 6 + _rxOutStream << m_sHelpText; + + if (nAnyMask & FONTDESCRIPTOR) + _rxOutStream << getFont(); + + if (nAnyMask & RECORDMARKER) + _rxOutStream->writeBoolean(m_bRecordMarker); + + // neu ab Version 7 + _rxOutStream->writeBoolean(m_bPrintable); + + // new since 8 + if (nAnyMask & BACKGROUNDCOLOR) + _rxOutStream->writeLong(getINT32(m_aBackgroundColor)); +} + +//------------------------------------------------------------------------------ +void OGridControlModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::read(_rxInStream); + + Reference<XMarkableStream> xMark(_rxInStream, UNO_QUERY); + + // 1. Version + sal_Int16 nVersion = _rxInStream->readShort(); + + // 2. Einlesen der Spalten + sal_Int32 nLen = _rxInStream->readLong(); + if (nLen) + { + for (sal_Int32 i = 0; i < nLen; i++) + { + // Lesen des Modelnamen + + ::rtl::OUString sModelName; + _rxInStream >> sModelName; + + Reference<XPropertySet> xCol(createColumn(getColumnTypeByModelName(sModelName))); + DBG_ASSERT(xCol.is(), "OGridControlModel::read : unknown column type !"); + sal_Int32 nObjLen = _rxInStream->readLong(); + if (nObjLen) + { + sal_Int32 nMark = xMark->createMark(); + if (xCol.is()) + { + OGridColumn* pCol = getColumnImplementation(xCol); + pCol->read(_rxInStream); + } + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nObjLen); + xMark->deleteMark(nMark); + } + + if ( xCol.is() ) + implInsert( i, xCol, sal_False, NULL, sal_False ); + } + } + + // In der Basisimplementierung werden die Events nur gelesen, Elemente im Container existieren + // da aber vor TF_ONE fuer das GridControl immer Events geschrieben wurden, muessen sie auch immer + // mit gelesen werden + sal_Int32 nObjLen = _rxInStream->readLong(); + if (nObjLen) + { + sal_Int32 nMark = xMark->createMark(); + Reference<XPersistObject> xObj(m_xEventAttacher, UNO_QUERY); + if (xObj.is()) + xObj->read(_rxInStream); + xMark->jumpToMark(nMark); + _rxInStream->skipBytes(nObjLen); + xMark->deleteMark(nMark); + } + + // Attachement lesen + for (sal_Int32 i = 0; i < nLen; i++) + { + InterfaceRef xIfc(m_aItems[i], UNO_QUERY); + Reference<XPropertySet> xSet(xIfc, UNO_QUERY); + Any aHelper; + aHelper <<= xSet; + m_xEventAttacher->attach( i, xIfc, aHelper ); + } + + // 4. Einlesen der Attribute + if (nVersion == 1) + return; + + // Maskierung fuer any + sal_uInt16 nAnyMask = _rxInStream->readShort(); + + if (nAnyMask & ROWHEIGHT) + { + sal_Int32 nValue = _rxInStream->readLong(); + m_aRowHeight <<= (sal_Int32)nValue; + } + + FontDescriptor aFont( getFont() ); + if ( nAnyMask & FONTATTRIBS ) + { + aFont.Weight = (float)VCLUnoHelper::ConvertFontWeight( _rxInStream->readShort() ); + + aFont.Slant = (FontSlant)_rxInStream->readShort(); + aFont.Underline = _rxInStream->readShort(); + aFont.Strikeout = _rxInStream->readShort(); + aFont.Orientation = ( (float)_rxInStream->readShort() ) / 10; + aFont.Kerning = _rxInStream->readBoolean(); + aFont.WordLineMode = _rxInStream->readBoolean(); + } + if ( nAnyMask & FONTSIZE ) + { + aFont.Width = (sal_Int16)_rxInStream->readLong(); + aFont.Height = (sal_Int16)_rxInStream->readLong(); + aFont.CharacterWidth = (float)VCLUnoHelper::ConvertFontWidth( _rxInStream->readShort() ); + } + if ( nAnyMask & FONTTYPE ) + { + aFont.Name = _rxInStream->readUTF(); + aFont.StyleName = _rxInStream->readUTF(); + aFont.Family = _rxInStream->readShort(); + aFont.CharSet = _rxInStream->readShort(); + aFont.Pitch = _rxInStream->readShort(); + } + + if ( nAnyMask & ( FONTATTRIBS | FONTSIZE | FONTTYPE ) ) + setFont( aFont ); + + // Name + _rxInStream >> m_aDefaultControl; + m_nBorder = _rxInStream->readShort(); + m_bEnable = _rxInStream->readBoolean(); + + if (nAnyMask & TABSTOP) + { + m_aTabStop = makeBoolAny(_rxInStream->readBoolean()); + } + + if (nVersion > 3) + m_bNavigation = _rxInStream->readBoolean(); + + if (nAnyMask & TEXTCOLOR) + { + sal_Int32 nValue = _rxInStream->readLong(); + setTextColor( (sal_Int32)nValue ); + } + + // neu ab Version 6 + if (nVersion > 5) + _rxInStream >> m_sHelpText; + + if (nAnyMask & FONTDESCRIPTOR) + { + FontDescriptor aUNOFont; + _rxInStream >> aUNOFont; + setFont( aFont ); + } + + if (nAnyMask & RECORDMARKER) + m_bRecordMarker = _rxInStream->readBoolean(); + + // neu ab Version 7 + if (nVersion > 6) + m_bPrintable = _rxInStream->readBoolean(); + + if (nAnyMask & BACKGROUNDCOLOR) + { + sal_Int32 nValue = _rxInStream->readLong(); + m_aBackgroundColor <<= (sal_Int32)nValue; + } +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Grid.hxx b/forms/source/component/Grid.hxx new file mode 100644 index 000000000000..6cd0e9787ef1 --- /dev/null +++ b/forms/source/component/Grid.hxx @@ -0,0 +1,219 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#include "errorbroadcaster.hxx" +#include "FormComponent.hxx" +#include "formcontrolfont.hxx" +#include "InterfaceContainer.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/form/XGridColumnFactory.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/sdb/XRowSetSupplier.hpp> +#include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +/** === end UNO includes === **/ + +#include <comphelper/proparrhlp.hxx> +#include <cppuhelper/implbase7.hxx> +#include <tools/link.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + +class OGridColumn; + +//================================================================== +// ColumnDescription +//================================================================== + + struct ColumnDescription : public ElementDescription + { + public: + OGridColumn* pColumn; // not owned by this instance! only to prevent duplicate XUnoTunnel usage + }; + +//================================================================== +// OGridControlModel +//================================================================== +typedef ::cppu::ImplHelper7 < ::com::sun::star::awt::XControlModel + , ::com::sun::star::form::XGridColumnFactory + , ::com::sun::star::form::XReset + , ::com::sun::star::view::XSelectionSupplier + , ::com::sun::star::sdb::XSQLErrorListener + , ::com::sun::star::sdb::XRowSetSupplier + , ::com::sun::star::sdb::XRowSetChangeBroadcaster + > OGridControlModel_BASE; + +class OGridControlModel :public OControlModel + ,public OInterfaceContainer + ,public OErrorBroadcaster + ,public FontControlModel + ,public OGridControlModel_BASE +{ + ::cppu::OInterfaceContainerHelper m_aSelectListeners, + m_aResetListeners, + m_aRowSetChangeListeners; + +// [properties] + ::com::sun::star::uno::Any m_aRowHeight; // Zeilenhoehe + ::com::sun::star::uno::Any m_aTabStop; + ::com::sun::star::uno::Any m_aBackgroundColor; + ::com::sun::star::uno::Any m_aCursorColor; // transient + ::com::sun::star::uno::Any m_aBorderColor; + ::rtl::OUString m_aDefaultControl; + ::rtl::OUString m_sHelpText; +// [properties] + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xSelection; + +// [properties] + ::rtl::OUString m_sHelpURL; // URL + sal_Int16 m_nBorder; + sal_Int16 m_nWritingMode; + sal_Int16 m_nContextWritingMode; + sal_Bool m_bEnableVisible : 1; + sal_Bool m_bEnable : 1; + sal_Bool m_bNavigation : 1; + sal_Bool m_bRecordMarker : 1; + sal_Bool m_bPrintable : 1; + sal_Bool m_bAlwaysShowCursor : 1; // transient + sal_Bool m_bDisplaySynchron : 1; // transient +// [properties] + +protected: + void _reset(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OGridControlModel ); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OGridControlModel, OControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // XChild + virtual void SAL_CALL setParent(const InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OGridControlModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + 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(); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // 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>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeResetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XResetListener>& _rxListener) throw ( ::com::sun::star::uno::RuntimeException); + + // XSelectionSupplier + virtual sal_Bool SAL_CALL select(const ::com::sun::star::uno::Any& aElement) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getSelection() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addSelectionChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::view::XSelectionChangeListener >& xListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSelectionChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::view::XSelectionChangeListener >& xListener) throw(::com::sun::star::uno::RuntimeException); + + // XGridColumnFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> SAL_CALL createColumn(const ::rtl::OUString& ColumnType) throw ( :: com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual StringSequence SAL_CALL getColumnTypes() throw ( ::com::sun::star::uno::RuntimeException); + + // 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); + + // 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); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // XSQLErrorListener + virtual void SAL_CALL errorOccured( const ::com::sun::star::sdb::SQLErrorEvent& _rEvent ) throw (::com::sun::star::uno::RuntimeException); + + // XRowSetSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > SAL_CALL getRowSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRowSet( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet >& xDataSource ) throw (::com::sun::star::uno::RuntimeException); + + // XRowSetChangeBroadcaster + virtual void SAL_CALL addRowSetChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetChangeListener >& i_Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetChangeListener >& i_Listener ) throw (::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OControlModel::disposing; + using OControlModel::getFastPropertyValue; + +protected: + DECLARE_XCLONEABLE(); + +protected: + virtual void approveNewElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxObject, + ElementDescription* _pElement + ); + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> createColumn(sal_Int32 nTypeId) const; + + OGridColumn* getColumnImplementation(const InterfaceRef& _rxIFace) const; + + virtual ElementDescription* createElementMetaData( ); + +protected: + virtual void implRemoved(const InterfaceRef& _rxObject); + virtual void implInserted( const ElementDescription* _pElement ); + virtual void impl_replacedElement( + const ::com::sun::star::container::ContainerEvent& _rEvent, + ::osl::ClearableMutexGuard& _rInstanceLock + ); + + void gotColumn(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxColumn); + void lostColumn(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxColumn); + + void cloneColumns( const OGridControlModel* _pOriginalContainer ); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + + diff --git a/forms/source/component/GroupBox.cxx b/forms/source/component/GroupBox.cxx new file mode 100644 index 000000000000..adf055955f3a --- /dev/null +++ b/forms/source/component/GroupBox.cxx @@ -0,0 +1,175 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "GroupBox.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//================================================================== +// OGroupBoxModel +//================================================================== + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OGroupBoxModel_CreateInstance(const Reference<starlang::XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OGroupBoxModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( OGroupBoxModel ) +//------------------------------------------------------------------ +OGroupBoxModel::OGroupBoxModel(const Reference<starlang::XMultiServiceFactory>& _rxFactory) + :OControlModel(_rxFactory, VCL_CONTROLMODEL_GROUPBOX, VCL_CONTROL_GROUPBOX) +{ + DBG_CTOR( OGroupBoxModel, NULL ); + m_nClassId = FormComponentType::GROUPBOX; +} + +//------------------------------------------------------------------ +OGroupBoxModel::OGroupBoxModel( const OGroupBoxModel* _pOriginal, const Reference<starlang::XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OGroupBoxModel, NULL ); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OGroupBoxModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_GROUPBOX; + return aSupported; +} + +//------------------------------------------------------------------ +OGroupBoxModel::~OGroupBoxModel() +{ + DBG_DTOR( OGroupBoxModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OGroupBoxModel ) + +//------------------------------------------------------------------------------ +void OGroupBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const +{ + OControlModel::describeAggregateProperties( _rAggregateProps ); + // don't want to have the TabStop property + RemoveProperty(_rAggregateProps, PROPERTY_TABSTOP); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OGroupBoxModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_GROUPBOX; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OGroupBoxModel::write(const Reference< XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) +{ + OControlModel::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0002); + writeHelpTextCompatibly(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OGroupBoxModel::read(const Reference< XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) +{ + OControlModel::read( _rxInStream ); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + DBG_ASSERT(nVersion > 0, "OGroupBoxModel::read : version 0 ? this should never have been written !"); + // ups, ist das Englisch richtig ? ;) + + if (nVersion == 2) + readHelpTextCompatibly(_rxInStream); + + if (nVersion > 0x0002) + { + DBG_ERROR("OGroupBoxModel::read : unknown version !"); + } +}; + +//================================================================== +// OGroupBoxControl +//================================================================== + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OGroupBoxControl_CreateInstance(const Reference<starlang::XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OGroupBoxControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +OGroupBoxControl::OGroupBoxControl(const Reference<starlang::XMultiServiceFactory>& _rxFactory) + :OControl(_rxFactory, VCL_CONTROL_GROUPBOX) +{ +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OGroupBoxControl::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_GROUPBOX; + return aSupported; +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/GroupBox.hxx b/forms/source/component/GroupBox.hxx new file mode 100644 index 000000000000..902c60ced488 --- /dev/null +++ b/forms/source/component/GroupBox.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * 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_GROUPBOX_HXX_ +#define _FORMS_GROUPBOX_HXX_ + +#include "FormComponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +// OGroupBoxModel +//================================================================== +class OGroupBoxModel + :public OControlModel +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( OGroupBoxModel ); + + // XServiceInfo + IMPLEMENTATION_NAME(OGroupBoxModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // 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); + + // OControlModel's property handling + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + +protected: + DECLARE_XCLONEABLE(); +}; + +//================================================================== +// OGroupBoxControl (nur aus Kompatibilitaet zur 5.0) +//================================================================== +class OGroupBoxControl : public OControl +{ +public: + OGroupBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(OGroupBoxControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_GROUPBOX_HXX_ + diff --git a/forms/source/component/GroupManager.cxx b/forms/source/component/GroupManager.cxx new file mode 100644 index 000000000000..fde6aa1a23ca --- /dev/null +++ b/forms/source/component/GroupManager.cxx @@ -0,0 +1,501 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "GroupManager.hxx" +#include <com/sun/star/beans/XFastPropertySet.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <comphelper/property.hxx> +#include <comphelper/uno3.hxx> +#include <tools/solar.h> +#include <tools/debug.hxx> + +#include "property.hrc" + +#include <algorithm> + +//......................................................................... +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::form; + +namespace +{ + bool isRadioButton( const Reference< XPropertySet >& _rxComponent ) + { + bool bIs = false; + if ( hasProperty( PROPERTY_CLASSID, _rxComponent ) ) + { + sal_Int16 nClassId = FormComponentType::CONTROL; + _rxComponent->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId; + if ( nClassId == FormComponentType::RADIOBUTTON ) + bIs = true; + } + return bIs; + } +} + +//======================================================================== +// class OGroupCompAcc +//======================================================================== +//------------------------------------------------------------------ +OGroupCompAcc::OGroupCompAcc(const Reference<XPropertySet>& rxElement, const OGroupComp& _rGroupComp ) + :m_xComponent( rxElement ) + ,m_aGroupComp( _rGroupComp ) +{ +} + +//------------------------------------------------------------------ +sal_Bool OGroupCompAcc::operator==( const OGroupCompAcc& rCompAcc ) const +{ + return (m_xComponent == rCompAcc.GetComponent()); +} + +//------------------------------------------------------------------ +class OGroupCompAccLess : public ::std::binary_function<OGroupCompAcc, OGroupCompAcc, sal_Bool> +{ +public: + sal_Bool operator() (const OGroupCompAcc& lhs, const OGroupCompAcc& rhs) const + { + return + reinterpret_cast<sal_Int64>(lhs.m_xComponent.get()) + < reinterpret_cast<sal_Int64>(rhs.m_xComponent.get()); + } +}; + +//======================================================================== +// class OGroupComp +//======================================================================== + +//------------------------------------------------------------------ +OGroupComp::OGroupComp() + :m_nPos( -1 ) + ,m_nTabIndex( 0 ) +{ +} + +//------------------------------------------------------------------ +OGroupComp::OGroupComp(const OGroupComp& _rSource) + :m_aName( _rSource.m_aName ) + ,m_xComponent( _rSource.m_xComponent ) + ,m_xControlModel(_rSource.m_xControlModel) + ,m_nPos( _rSource.m_nPos ) + ,m_nTabIndex( _rSource.m_nTabIndex ) +{ +} + +//------------------------------------------------------------------ +OGroupComp::OGroupComp(const Reference<XPropertySet>& rxSet, sal_Int32 nInsertPos ) + :m_xComponent( rxSet ) + ,m_xControlModel(rxSet,UNO_QUERY) + ,m_nPos( nInsertPos ) + ,m_nTabIndex(0) +{ + if (m_xComponent.is()) + { + if (hasProperty( PROPERTY_TABINDEX, m_xComponent ) ) + // Indices kleiner 0 werden wie 0 behandelt + m_nTabIndex = Max(getINT16(m_xComponent->getPropertyValue( PROPERTY_TABINDEX )) , sal_Int16(0)); + + m_xComponent->getPropertyValue( PROPERTY_NAME ) >>= m_aName; + } +} + +//------------------------------------------------------------------ +sal_Bool OGroupComp::operator==( const OGroupComp& rComp ) const +{ + return m_nTabIndex == rComp.GetTabIndex() && m_nPos == rComp.GetPos(); +} + +//------------------------------------------------------------------ +class OGroupCompLess : public ::std::binary_function<OGroupComp, OGroupComp, sal_Bool> +{ +public: + sal_Bool operator() (const OGroupComp& lhs, const OGroupComp& rhs) const + { + sal_Bool bResult; + // TabIndex von 0 wird hinten einsortiert + if (lhs.m_nTabIndex == rhs.GetTabIndex()) + bResult = lhs.m_nPos < rhs.GetPos(); + else if (lhs.m_nTabIndex && rhs.GetTabIndex()) + bResult = lhs.m_nTabIndex < rhs.GetTabIndex(); + else + bResult = lhs.m_nTabIndex != 0; + return bResult; + } +}; + +//======================================================================== +// class OGroup +//======================================================================== + +DBG_NAME(OGroup) +//------------------------------------------------------------------ +OGroup::OGroup( const ::rtl::OUString& rGroupName ) + :m_aGroupName( rGroupName ) + ,m_nInsertPos(0) +{ + DBG_CTOR(OGroup,NULL); +} + +#ifdef DBG_UTIL +//------------------------------------------------------------------ +OGroup::OGroup( const OGroup& _rSource ) +:m_aCompArray(_rSource.m_aCompArray) + ,m_aCompAccArray(_rSource.m_aCompAccArray) + ,m_aGroupName(_rSource.m_aGroupName) + ,m_nInsertPos(_rSource.m_nInsertPos) +{ + DBG_CTOR(OGroup,NULL); +} +#endif + +//------------------------------------------------------------------ +OGroup::~OGroup() +{ + DBG_DTOR(OGroup,NULL); +} + +//------------------------------------------------------------------ +void OGroup::InsertComponent( const Reference<XPropertySet>& xSet ) +{ + OGroupComp aNewGroupComp( xSet, m_nInsertPos ); + sal_Int32 nPosInserted = insert_sorted(m_aCompArray, aNewGroupComp, OGroupCompLess()); + + OGroupCompAcc aNewGroupCompAcc( xSet, m_aCompArray[nPosInserted] ); + insert_sorted(m_aCompAccArray, aNewGroupCompAcc, OGroupCompAccLess()); + m_nInsertPos++; +} + +//------------------------------------------------------------------ +void OGroup::RemoveComponent( const Reference<XPropertySet>& rxElement ) +{ + sal_Int32 nGroupCompAccPos; + OGroupCompAcc aSearchCompAcc( rxElement, OGroupComp() ); + if ( seek_entry(m_aCompAccArray, aSearchCompAcc, nGroupCompAccPos, OGroupCompAccLess()) ) + { + OGroupCompAcc& aGroupCompAcc = m_aCompAccArray[nGroupCompAccPos]; + const OGroupComp& aGroupComp = aGroupCompAcc.GetGroupComponent(); + + sal_Int32 nGroupCompPos; + if ( seek_entry(m_aCompArray, aGroupComp, nGroupCompPos, OGroupCompLess()) ) + { + m_aCompAccArray.erase( m_aCompAccArray.begin() + nGroupCompAccPos ); + m_aCompArray.erase( m_aCompArray.begin() + nGroupCompPos ); + + /*============================================================ + Durch das Entfernen der GroupComp ist die Einfuegeposition + ungueltig geworden. Sie braucht hier aber nicht angepasst werden, + da sie fortlaufend vergeben wird und damit immer + aufsteigend eindeutig ist. + ============================================================*/ + } + else + { + DBG_ERROR( "OGroup::RemoveComponent: Component nicht in Gruppe" ); + } + } + else + { + DBG_ERROR( "OGroup::RemoveComponent: Component nicht in Gruppe" ); + } +} + +//------------------------------------------------------------------ +sal_Bool OGroup::operator==( const OGroup& rGroup ) const +{ + return m_aGroupName.equals(rGroup.GetGroupName()); +} + +//------------------------------------------------------------------ +class OGroupLess : public ::std::binary_function<OGroup, OGroup, sal_Bool> +{ +public: + sal_Bool operator() (const OGroup& lhs, const OGroup& rhs) const + { + return lhs.m_aGroupName < rhs.m_aGroupName; + } +}; + +//------------------------------------------------------------------ +Sequence< Reference<XControlModel> > OGroup::GetControlModels() const +{ + sal_Int32 nLen = m_aCompArray.size(); + Sequence<Reference<XControlModel> > aControlModelSeq( nLen ); + Reference<XControlModel>* pModels = aControlModelSeq.getArray(); + + ConstOGroupCompArrIterator aGroupComps = m_aCompArray.begin(); + for (sal_Int32 i = 0; i < nLen; ++i, ++pModels, ++aGroupComps) + { + *pModels = aGroupComps->GetControlModel(); + } + return aControlModelSeq; +} + +DBG_NAME(OGroupManager); +//------------------------------------------------------------------ +OGroupManager::OGroupManager(const Reference< XContainer >& _rxContainer) + :m_pCompGroup( new OGroup( ::rtl::OUString::createFromAscii( "AllComponentGroup" ) ) ) + ,m_xContainer(_rxContainer) +{ + DBG_CTOR(OGroupManager,NULL); + + increment(m_refCount); + { + _rxContainer->addContainerListener(this); + } + decrement(m_refCount); +} + +//------------------------------------------------------------------ +OGroupManager::~OGroupManager() +{ + DBG_DTOR(OGroupManager,NULL); + // Alle Components und CompGroup loeschen + delete m_pCompGroup; +} + +// XPropertyChangeListener +//------------------------------------------------------------------ +void OGroupManager::disposing(const EventObject& evt) throw( RuntimeException ) +{ + Reference<XContainer> xContainer(evt.Source, UNO_QUERY); + if (xContainer.get() == m_xContainer.get()) + { + DELETEZ(m_pCompGroup); + + //////////////////////////////////////////////////////////////// + // Gruppen loeschen + m_aGroupArr.clear(); + m_xContainer.clear(); + } +} +// ----------------------------------------------------------------------------- +void OGroupManager::removeFromGroupMap(const ::rtl::OUString& _sGroupName,const Reference<XPropertySet>& _xSet) +{ + // Component aus CompGroup entfernen + m_pCompGroup->RemoveComponent( _xSet ); + + OGroupArr::iterator aFind = m_aGroupArr.find(_sGroupName); + + if ( aFind != m_aGroupArr.end() ) + { + // Gruppe vorhanden + aFind->second.RemoveComponent( _xSet ); + + // Wenn Anzahl der Gruppenelemente == 1 ist, Gruppe deaktivieren + if ( aFind->second.Count() == 1 ) + { + OActiveGroups::iterator aActiveFind = ::std::find( + m_aActiveGroupMap.begin(), + m_aActiveGroupMap.end(), + aFind + ); + if ( aActiveFind != m_aActiveGroupMap.end() ) + { + // the group is active. Deactivate it if the remaining component + // is *no* radio button + if ( !isRadioButton( aFind->second.GetObject( 0 ) ) ) + m_aActiveGroupMap.erase( aActiveFind ); + } + } + } + + + // Bei Component als PropertyChangeListener abmelden + _xSet->removePropertyChangeListener( PROPERTY_NAME, this ); + if (hasProperty(PROPERTY_TABINDEX, _xSet)) + _xSet->removePropertyChangeListener( PROPERTY_TABINDEX, this ); +} +//------------------------------------------------------------------ +void SAL_CALL OGroupManager::propertyChange(const PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xSet(evt.Source, UNO_QUERY); + + // Component aus Gruppe entfernen + ::rtl::OUString sGroupName; + if (evt.PropertyName == PROPERTY_NAME) + evt.OldValue >>= sGroupName; + else + xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; + + removeFromGroupMap(sGroupName,xSet); + + // Component neu einordnen + InsertElement( xSet ); +} + +// XContainerListener +//------------------------------------------------------------------ +void SAL_CALL OGroupManager::elementInserted(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference< XPropertySet > xProps; + Event.Element >>= xProps; + if ( xProps.is() ) + InsertElement( xProps ); +} + +//------------------------------------------------------------------ +void SAL_CALL OGroupManager::elementRemoved(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xProps; + Event.Element >>= xProps; + if ( xProps.is() ) + RemoveElement( xProps ); +} + +//------------------------------------------------------------------ +void SAL_CALL OGroupManager::elementReplaced(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySet> xProps; + Event.ReplacedElement >>= xProps; + if ( xProps.is() ) + RemoveElement( xProps ); + + xProps.clear(); + Event.Element >>= xProps; + if ( xProps.is() ) + InsertElement( xProps ); +} + +// Other functions +//------------------------------------------------------------------ +Sequence<Reference<XControlModel> > OGroupManager::getControlModels() +{ + return m_pCompGroup->GetControlModels(); +} + +//------------------------------------------------------------------ +sal_Int32 OGroupManager::getGroupCount() +{ + return m_aActiveGroupMap.size(); +} + +//------------------------------------------------------------------ +void OGroupManager::getGroup(sal_Int32 nGroup, Sequence< Reference<XControlModel> >& _rGroup, ::rtl::OUString& _rName) +{ + OSL_ENSURE(nGroup >= 0 && (size_t)nGroup < m_aActiveGroupMap.size(),"OGroupManager::getGroup: Invalid group index!"); + OGroupArr::iterator aGroupPos = m_aActiveGroupMap[nGroup]; + _rName = aGroupPos->second.GetGroupName(); + _rGroup = aGroupPos->second.GetControlModels(); +} + +//------------------------------------------------------------------ +void OGroupManager::getGroupByName(const ::rtl::OUString& _rName, Sequence< Reference<XControlModel> >& _rGroup) +{ + OGroupArr::iterator aFind = m_aGroupArr.find(_rName); + if ( aFind != m_aGroupArr.end() ) + _rGroup = aFind->second.GetControlModels(); +} + +//------------------------------------------------------------------ +void OGroupManager::InsertElement( const Reference<XPropertySet>& xSet ) +{ + // Nur ControlModels + Reference<XControlModel> xControl(xSet, UNO_QUERY); + if (!xControl.is() ) + return; + + // Component in CompGroup aufnehmen + m_pCompGroup->InsertComponent( xSet ); + + // Component in Gruppe aufnehmen + ::rtl::OUString sGroupName; + xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; + + OGroupArr::iterator aFind = m_aGroupArr.find(sGroupName); + + if ( aFind == m_aGroupArr.end() ) + { + aFind = m_aGroupArr.insert(OGroupArr::value_type(sGroupName,OGroup(sGroupName))).first; + } + + aFind->second.InsertComponent( xSet ); + + // if we have at least 2 elements in the group, then this is an "active group" + bool bActivateGroup = aFind->second.Count() == 2; + + // Additionally, if the component is a radio button, then it's group becomes active, + // too. With this, we ensure that in a container with n radio buttons which all are + // in different groups the selection still works reliably (means that all radios can be + // clicked independently) + if ( aFind->second.Count() == 1 ) + { + if ( isRadioButton( xSet ) ) + bActivateGroup = true; + } + + if ( bActivateGroup ) + { + OActiveGroups::iterator aAlreadyExistent = ::std::find( + m_aActiveGroupMap.begin(), + m_aActiveGroupMap.end(), + aFind + ); + if ( aAlreadyExistent == m_aActiveGroupMap.end() ) + m_aActiveGroupMap.push_back( aFind ); + } + + + // Bei Component als PropertyChangeListener anmelden + xSet->addPropertyChangeListener( PROPERTY_NAME, this ); + + // Tabindex muss nicht jeder unterstuetzen + if (hasProperty(PROPERTY_TABINDEX, xSet)) + xSet->addPropertyChangeListener( PROPERTY_TABINDEX, this ); + +} + +//------------------------------------------------------------------ +void OGroupManager::RemoveElement( const Reference<XPropertySet>& xSet ) +{ + // Nur ControlModels + Reference<XControlModel> xControl(xSet, UNO_QUERY); + if (!xControl.is() ) + return; + + // Component aus Gruppe entfernen + ::rtl::OUString sGroupName; + xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; + + removeFromGroupMap(sGroupName,xSet); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/GroupManager.hxx b/forms/source/component/GroupManager.hxx new file mode 100644 index 000000000000..fc9d8ce82c61 --- /dev/null +++ b/forms/source/component/GroupManager.hxx @@ -0,0 +1,228 @@ +/************************************************************************* + * + * 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 _FRM_GROUPMANAGER_HXX_ +#define _FRM_GROUPMANAGER_HXX_ + +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/container/XContainerListener.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <comphelper/stl_types.hxx> +#include <cppuhelper/implbase2.hxx> +#include <comphelper/stl_types.hxx> +#include <comphelper/types.hxx> +using namespace comphelper; + +/*======================================================================== +Funktionsweise GroupManager: + +Der GroupManager horcht an der starform, ob FormComponents eingefuegt oder entfernt +werden. Zusaetzlich horcht er bei den FormComponents an den Properties +"Name" und "TabIndex". Mit diesen Infos aktualisiert er seine Gruppen. + +Der GroupManager verwaltet eine Gruppe, in der alle Controls nach TabIndex +geordnet sind, und ein Array von Gruppen, in dem jede FormComponent noch +einmal einer Gruppe dem Namen nach zugeordnet wird. +Die einzelnen Gruppen werden ueber eine Map aktiviert, wenn sie mehr als +ein Element besitzen. + +Die Gruppen verwalten intern die FormComponents in zwei Arrays. In dem +GroupCompArray werden die Components nach TabIndex und Einfuegepostion +sortiert. Da auf dieses Array ueber die FormComponent zugegriffen +wird, gibt es noch das GroupCompAccessArray, in dem die FormComponents +nach ihrer Speicheradresse sortiert sind. Jedes Element des +GroupCompAccessArrays ist mit einem Element des GroupCompArrays verpointert. + +========================================================================*/ + +//......................................................................... +namespace frm +{ +//......................................................................... + +//======================================================================== + template <class ELEMENT, class LESS_COMPARE> + sal_Int32 insert_sorted(::std::vector<ELEMENT>& _rArray, const ELEMENT& _rNewElement, const LESS_COMPARE& _rCompareOp) + { + typename ::std::vector<ELEMENT>::iterator aInsertPos = lower_bound( + _rArray.begin(), + _rArray.end(), + _rNewElement, + _rCompareOp + ); + aInsertPos = _rArray.insert(aInsertPos, _rNewElement); + return aInsertPos - _rArray.begin(); + } + + template <class ELEMENT, class LESS_COMPARE> + sal_Bool seek_entry(const ::std::vector<ELEMENT>& _rArray, const ELEMENT& _rNewElement, sal_Int32& nPos, const LESS_COMPARE& _rCompareOp) + { + typename ::std::vector<ELEMENT>::const_iterator aExistentPos = lower_bound( + _rArray.begin(), + _rArray.end(), + _rNewElement, + _rCompareOp + ); + if ((aExistentPos != _rArray.end()) && (*aExistentPos == _rNewElement)) + { // we have a valid "lower or equal" element and it's really "equal" + nPos = aExistentPos - _rArray.begin(); + return sal_True; + } + nPos = -1; + return sal_False; + } + +//======================================================================== +class OGroupComp +{ + ::rtl::OUString m_aName; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> m_xComponent; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> m_xControlModel; + sal_Int32 m_nPos; + sal_Int16 m_nTabIndex; + + friend class OGroupCompLess; + +public: + OGroupComp(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement, sal_Int32 nInsertPos ); + OGroupComp(const OGroupComp& _rSource); + OGroupComp(); + + sal_Bool operator==( const OGroupComp& rComp ) const; + + inline const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& GetComponent() const { return m_xComponent; } + inline const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel>& GetControlModel() const { return m_xControlModel; } + + sal_Int32 GetPos() const { return m_nPos; } + sal_Int16 GetTabIndex() const { return m_nTabIndex; } + ::rtl::OUString GetName() const { return m_aName; } +}; + +DECLARE_STL_VECTOR(OGroupComp, OGroupCompArr); + +//======================================================================== +class OGroupComp; +class OGroupCompAcc +{ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> m_xComponent; + + OGroupComp m_aGroupComp; + + friend class OGroupCompAccLess; + +public: + OGroupCompAcc(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement, const OGroupComp& _rGroupComp ); + + sal_Bool operator==( const OGroupCompAcc& rCompAcc ) const; + + inline const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& GetComponent() const { return m_xComponent; } + const OGroupComp& GetGroupComponent() const { return m_aGroupComp; } +}; + +DECLARE_STL_VECTOR(OGroupCompAcc, OGroupCompAccArr); + +//======================================================================== +class OGroup +{ + OGroupCompArr m_aCompArray; + OGroupCompAccArr m_aCompAccArray; + + ::rtl::OUString m_aGroupName; + sal_uInt16 m_nInsertPos; // Die Einfugeposition der GroupComps wird von der Gruppe bestimmt. + + friend class OGroupLess; + +public: + OGroup( const ::rtl::OUString& rGroupName ); +#ifdef DBG_UTIL + OGroup( const OGroup& _rSource ); // just to ensure the DBG_CTOR call +#endif + virtual ~OGroup(); + + sal_Bool operator==( const OGroup& rGroup ) const; + + ::rtl::OUString GetGroupName() const { return m_aGroupName; } + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> > GetControlModels() const; + + void InsertComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement ); + void RemoveComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement ); + sal_uInt16 Count() const { return sal::static_int_cast< sal_uInt16 >(m_aCompArray.size()); } + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& GetObject( sal_uInt16 nP ) const + { return m_aCompArray[nP].GetComponent(); } +}; + +DECLARE_STL_USTRINGACCESS_MAP(OGroup, OGroupArr); +DECLARE_STL_VECTOR(OGroupArr::iterator, OActiveGroups); + +//======================================================================== +class OGroupManager : public ::cppu::WeakImplHelper2< ::com::sun::star::beans::XPropertyChangeListener, ::com::sun::star::container::XContainerListener> +{ + OGroup* m_pCompGroup; // Alle Components nach TabIndizes sortiert + OGroupArr m_aGroupArr; // Alle Components nach Gruppen sortiert + OActiveGroups m_aActiveGroupMap; // In dieser Map werden die Indizes aller Gruppen gehalten, + // die mehr als 1 Element haben + + ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer > + m_xContainer; + + // Helper functions + void InsertElement( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement ); + void RemoveElement( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& rxElement ); + void removeFromGroupMap(const ::rtl::OUString& _sGroupName,const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _xSet); + +public: + OGroupManager(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer >& _rxContainer); + virtual ~OGroupManager(); + +// ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::beans::XPropertyChangeListener + virtual void SAL_CALL propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XContainerListener + virtual void SAL_CALL elementInserted(const ::com::sun::star::container::ContainerEvent& _rEvent) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved(const ::com::sun::star::container::ContainerEvent& _rEvent) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced(const ::com::sun::star::container::ContainerEvent& _rEvent) throw ( ::com::sun::star::uno::RuntimeException); + +// Other functions + sal_Int32 getGroupCount(); + void getGroup(sal_Int32 nGroup, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> >& _rGroup, ::rtl::OUString& Name); + void getGroupByName(const ::rtl::OUString& Name, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> >& _rGroup); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel> > getControlModels(); +}; + + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_GROUPMANAGER_HXX_ + diff --git a/forms/source/component/Hidden.cxx b/forms/source/component/Hidden.cxx new file mode 100644 index 000000000000..9c20de263d80 --- /dev/null +++ b/forms/source/component/Hidden.cxx @@ -0,0 +1,190 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Hidden.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/basicio.hxx> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OHiddenModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new OHiddenModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( OHiddenModel ) +//------------------------------------------------------------------ +OHiddenModel::OHiddenModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OControlModel(_rxFactory, ::rtl::OUString()) +{ + DBG_CTOR( OHiddenModel, NULL ); + m_nClassId = FormComponentType::HIDDENCONTROL; +} + +//------------------------------------------------------------------ +OHiddenModel::OHiddenModel( const OHiddenModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OHiddenModel, NULL ); + m_sHiddenValue = _pOriginal->m_sHiddenValue; +} + +//------------------------------------------------------------------------------ +OHiddenModel::~OHiddenModel( ) +{ + DBG_CTOR( OHiddenModel, NULL ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OHiddenModel ) + +//------------------------------------------------------------------------------ +void OHiddenModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const +{ + switch (_nHandle) + { + case PROPERTY_ID_HIDDEN_VALUE : _rValue <<= m_sHiddenValue; break; + default: + OControlModel::getFastPropertyValue(_rValue, _nHandle); + } +} + +//------------------------------------------------------------------------------ +void OHiddenModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception) +{ + switch (_nHandle) + { + case PROPERTY_ID_HIDDEN_VALUE : + DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_STRING, "OHiddenModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_sHiddenValue; + break; + default: + OControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OHiddenModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) + throw (IllegalArgumentException) +{ + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_HIDDEN_VALUE : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_sHiddenValue); + break; + default: + bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OHiddenModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_BASE_PROPERTIES(4) + DECL_PROP2(CLASSID, sal_Int16, READONLY, TRANSIENT); + DECL_PROP1(HIDDEN_VALUE, ::rtl::OUString, BOUND); + DECL_PROP1(NAME, ::rtl::OUString, BOUND); + DECL_PROP1(TAG, ::rtl::OUString, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OHiddenModel::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) +{ + StringSequence aSupported( 2 ); + aSupported[ 0 ] = FRM_SUN_COMPONENT_HIDDENCONTROL; + aSupported[ 1 ] = FRM_SUN_FORMCOMPONENT; + return aSupported; +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OHiddenModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_HIDDEN; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL OHiddenModel::write(const Reference<XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) +{ + // Version + _rxOutStream->writeShort(0x0002); + + // Wert + _rxOutStream << m_sHiddenValue; + + OControlModel::write(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OHiddenModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) +{ + // Version + UINT16 nVersion = _rxInStream->readShort(); + + // Name + DBG_ASSERT(nVersion != 1, "OHiddenModel::read : this version is obsolete !"); + switch (nVersion) + { + case 1 : { ::rtl::OUString sDummy; _rxInStream >> sDummy; _rxInStream >> m_sHiddenValue; } break; + case 2 : _rxInStream >> m_sHiddenValue; break; + default : DBG_ERROR("OHiddenModel::read : unknown version !"); m_sHiddenValue = ::rtl::OUString(); + } + OControlModel::read(_rxInStream); +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/Hidden.hxx b/forms/source/component/Hidden.hxx new file mode 100644 index 000000000000..9052417c3f2c --- /dev/null +++ b/forms/source/component/Hidden.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * 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_HIDDEN_HXX_ +#define _FORMS_HIDDEN_HXX_ + +#include "FormComponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +// OHiddenModel +//================================================================== +class OHiddenModel + :public OControlModel +{ + ::rtl::OUString m_sHiddenValue; + +public: + DECLARE_DEFAULT_LEAF_XTOR( OHiddenModel ); + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + 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); + + // XServiceInfo + IMPLEMENTATION_NAME(OHiddenModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // 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); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OControlModel::getFastPropertyValue; + +protected: + DECLARE_XCLONEABLE( ); +}; + +#endif // _FORMS_HIDDEN_HXX_ + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/ImageButton.cxx b/forms/source/component/ImageButton.cxx new file mode 100644 index 000000000000..e026f5380bc1 --- /dev/null +++ b/forms/source/component/ImageButton.cxx @@ -0,0 +1,273 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "ImageButton.hxx" +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <comphelper/basicio.hxx> +#include <com/sun/star/awt/MouseButton.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; + +//================================================================== +//= OImageButtonModel +//================================================================== +DBG_NAME(OImageButtonModel) +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OImageButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OImageButtonModel(_rxFactory)); +} + +//------------------------------------------------------------------ +OImageButtonModel::OImageButtonModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseModel( _rxFactory, VCL_CONTROLMODEL_IMAGEBUTTON, FRM_SUN_CONTROL_IMAGEBUTTON ) + // use the old control name for compytibility reasons +{ + DBG_CTOR(OImageButtonModel, NULL); + m_nClassId = FormComponentType::IMAGEBUTTON; +} + +//------------------------------------------------------------------ +OImageButtonModel::OImageButtonModel( const OImageButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR(OImageButtonModel, NULL); + implInitializeImageURL(); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OImageButtonModel ) + +//------------------------------------------------------------------------------ +OImageButtonModel::~OImageButtonModel() +{ + DBG_DTOR(OImageButtonModel, NULL); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OImageButtonModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OClickableImageBaseModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_IMAGEBUTTON; + return aSupported; +} + +//------------------------------------------------------------------------------ +void OImageButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 5, OClickableImageBaseModel ) + DECL_PROP1(BUTTONTYPE, FormButtonType, BOUND); + DECL_PROP1(DISPATCHURLINTERNAL, sal_Bool, BOUND); + DECL_PROP1(TARGET_URL, ::rtl::OUString, BOUND); + DECL_PROP1(TARGET_FRAME, ::rtl::OUString, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString OImageButtonModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_IMAGEBUTTON; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OImageButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0003); + _rxOutStream->writeShort((sal_uInt16)m_eButtonType); + + ::rtl::OUString sTmp(INetURLObject::decode( m_sTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS)); + _rxOutStream << sTmp; + _rxOutStream << m_sTargetFrame; + writeHelpTextCompatibly(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void OImageButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OControlModel::read(_rxInStream); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + + switch (nVersion) + { + case 0x0001: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + } + break; + case 0x0002: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + _rxInStream >> m_sTargetURL; + _rxInStream >> m_sTargetFrame; + } + break; + case 0x0003: + { + m_eButtonType = (FormButtonType)_rxInStream->readShort(); + _rxInStream >> m_sTargetURL; + _rxInStream >> m_sTargetFrame; + readHelpTextCompatibly(_rxInStream); + } + break; + + default : + DBG_ERROR("OImageButtonModel::read : unknown version !"); + m_eButtonType = FormButtonType_PUSH; + m_sTargetURL = ::rtl::OUString(); + m_sTargetFrame = ::rtl::OUString(); + break; + } +} + +//================================================================== +// OImageButtonControl +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OImageButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OImageButtonControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OImageButtonControl::_getTypes() +{ + static Sequence<Type> aTypes; + if (!aTypes.getLength()) + aTypes = concatSequences(OClickableImageBaseControl::_getTypes(), OImageButtonControl_BASE::getTypes()); + return aTypes; +} + +//------------------------------------------------------------------------------ +StringSequence OImageButtonControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OClickableImageBaseControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_IMAGEBUTTON; + return aSupported; +} + +//------------------------------------------------------------------------------ +OImageButtonControl::OImageButtonControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OClickableImageBaseControl(_rxFactory, VCL_CONTROL_IMAGEBUTTON) +{ + increment(m_refCount); + { + // als MouseListener anmelden + Reference< awt::XWindow > xComp; + query_aggregation( m_xAggregate, xComp); + if (xComp.is()) + xComp->addMouseListener( static_cast< awt::XMouseListener* >( this ) ); + } + decrement(m_refCount); +} + +// UNO Anbindung +//------------------------------------------------------------------------------ +Any SAL_CALL OImageButtonControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OClickableImageBaseControl::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = OImageButtonControl_BASE::queryInterface(_rType); + + return aReturn; +} + +//------------------------------------------------------------------------------ +void OImageButtonControl::mousePressed(const awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + if (e.Buttons != awt::MouseButton::LEFT) + return; + + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if( m_aApproveActionListeners.getLength() ) + { + // if there are listeners, start the action in an own thread, to not allow + // them to block us here (we're in the application's main thread) + getImageProducerThread()->OComponentEventThread::addEvent( &e ); + } + else + { + // Sonst nicht. Dann darf man aber auf keinen Fal die Listener + // benachrichtigen, auch dann nicht, wenn er spaeter hinzukommt. + aGuard.clear(); + actionPerformed_Impl( sal_False, e ); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageButtonControl::mouseReleased(const awt::MouseEvent& /*e*/) throw ( RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageButtonControl::mouseEntered(const awt::MouseEvent& /*e*/) throw ( RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageButtonControl::mouseExited(const awt::MouseEvent& /*e*/) throw ( RuntimeException) +{ +} + + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/ImageButton.hxx b/forms/source/component/ImageButton.hxx new file mode 100644 index 000000000000..188ee8558e70 --- /dev/null +++ b/forms/source/component/ImageButton.hxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * 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 _FRM_IMAGE_BUTTON_HXX_ +#define _FRM_IMAGE_BUTTON_HXX_ + +#include "clickableimage.hxx" +#include <com/sun/star/awt/XMouseListener.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OImageButtonModel +//================================================================== +class OImageButtonModel + :public OClickableImageBaseModel +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( OImageButtonModel ); + +// ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OImageButtonModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + +// ::com::sun::star::io::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); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + DECLARE_XCLONEABLE(); +}; + +//================================================================== +// OImageButtonControl +//================================================================== +typedef ::cppu::ImplHelper1< ::com::sun::star::awt::XMouseListener> OImageButtonControl_BASE; +class OImageButtonControl : public OClickableImageBaseControl, + public OImageButtonControl_BASE +{ +protected: + // UNO Anbindung + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OImageButtonControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(OImageButtonControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OImageButtonControl, OClickableImageBaseControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException) + { OControl::disposing(_rSource); } + + // XMouseListener + virtual void SAL_CALL mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseReleased(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseEntered(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseExited(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + + // prevent method hiding + using OClickableImageBaseControl::disposing; +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_IMAGE_BUTTON_HXX_ + diff --git a/forms/source/component/ImageControl.cxx b/forms/source/component/ImageControl.cxx new file mode 100644 index 000000000000..f74e82135708 --- /dev/null +++ b/forms/source/component/ImageControl.cxx @@ -0,0 +1,960 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "ImageControl.hxx" + +#include "property.hrc" +#include "frm_resource.hrc" +#include "frm_resource.hxx" +#include "services.hxx" +#include "componenttools.hxx" + +#include <svtools/imageresourceaccess.hxx> +#include <unotools/ucblockbytes.hxx> +#include <sfx2/filedlghelper.hxx> +#include <com/sun/star/awt/XPopupMenu.hpp> +#include <com/sun/star/awt/PopupMenuDirection.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XDialog.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/NotConnectedException.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/graphic/GraphicObject.hpp> +#include <tools/urlobj.hxx> +#include <tools/stream.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/svapp.hxx> +#include <unotools/streamhelper.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/guarding.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <svl/urihelper.hxx> + +#include <memory> + +#define ID_OPEN_GRAPHICS 1 +#define ID_CLEAR_GRAPHICS 2 + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::frame; + +//============================================================================== +//= OImageControlModel +//============================================================================== +namespace +{ + enum ImageStoreType + { + ImageStoreBinary, + ImageStoreLink, + + ImageStoreInvalid + }; + + ImageStoreType lcl_getImageStoreType( const sal_Int32 _nFieldType ) + { + // binary/longvarchar types could be used to store images in binary representation + if ( ( _nFieldType == DataType::BINARY ) + || ( _nFieldType == DataType::VARBINARY ) + || ( _nFieldType == DataType::LONGVARBINARY ) + || ( _nFieldType == DataType::OTHER ) + || ( _nFieldType == DataType::OBJECT ) + || ( _nFieldType == DataType::BLOB ) + || ( _nFieldType == DataType::LONGVARCHAR ) + || ( _nFieldType == DataType::CLOB ) + ) + return ImageStoreBinary; + + // char types could be used to store links to images + if ( ( _nFieldType == DataType::CHAR ) + || ( _nFieldType == DataType::VARCHAR ) + ) + return ImageStoreLink; + + return ImageStoreInvalid; + } +} + +//============================================================================== +// OImageControlModel +//============================================================================== + +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL OImageControlModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OImageControlModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OImageControlModel::_getTypes() +{ + return concatSequences( + OBoundControlModel::_getTypes(), + OImageControlModel_Base::getTypes() + ); +} + +DBG_NAME(OImageControlModel) +//------------------------------------------------------------------ +OImageControlModel::OImageControlModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_IMAGECONTROL, FRM_SUN_CONTROL_IMAGECONTROL, sal_False, sal_False, sal_False ) + // use the old control name for compytibility reasons + ,m_pImageProducer( NULL ) + ,m_bReadOnly( sal_False ) +{ + DBG_CTOR( OImageControlModel, NULL ); + m_nClassId = FormComponentType::IMAGECONTROL; + initValueProperty( PROPERTY_IMAGE_URL, PROPERTY_ID_IMAGE_URL); + + implConstruct(); +} + +//------------------------------------------------------------------ +OImageControlModel::OImageControlModel( const OImageControlModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + // use the old control name for compytibility reasons + ,m_pImageProducer( NULL ) +{ + DBG_CTOR( OImageControlModel, NULL ); + implConstruct(); + m_bReadOnly = _pOriginal->m_bReadOnly; + + osl_incrementInterlockedCount( &m_refCount ); + { + // simulate a propertyChanged event for the ImageURL + // 2003-05-15 - #109591# - fs@openoffice.org + Any aImageURL; + getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL ); + ::rtl::OUString sImageURL; + aImageURL >>= sImageURL; + + ::osl::MutexGuard aGuard( m_aMutex ); + impl_handleNewImageURL_lck( sImageURL, eOther ); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//------------------------------------------------------------------ +void OImageControlModel::implConstruct() +{ + m_pImageProducer = new ImageProducer; + m_xImageProducer = m_pImageProducer; + m_pImageProducer->SetDoneHdl( LINK( this, OImageControlModel, OnImageImportDone ) ); +} + +//------------------------------------------------------------------ +OImageControlModel::~OImageControlModel() +{ + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OImageControlModel,NULL); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OImageControlModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence OImageControlModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_IMAGECONTROL; + return aSupported; +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OImageControlModel::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + // oder matters: we want to "override" the XImageProducer interface of the aggreate with out + // own XImageProducer interface, thus we need to query OImageControlModel_Base first + Any aReturn = OImageControlModel_Base::queryInterface( _rType ); + + // BUT: _don't_ let it feel responsible for the XTypeProvider interface + // (as this is implemented by our base class in the proper way) + if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) + || !aReturn.hasValue() + ) + aReturn = OBoundControlModel::queryAggregation( _rType ); + + return aReturn; +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::approveDbColumnType( sal_Int32 _nColumnType ) +{ + return ImageStoreInvalid != lcl_getImageStoreType( _nColumnType ); +} + + +//------------------------------------------------------------------------------ +void OImageControlModel::_propertyChanged( const PropertyChangeEvent& _rEvent ) + throw( RuntimeException ) +{ + if ( m_xColumnUpdate.is() ) + { + OBoundControlModel::_propertyChanged( _rEvent ); + } + else + { // we're not bound. In this case, we have to manually care for updating the + // image producer, since the base class will not do this + ::rtl::OUString sImageURL; + _rEvent.NewValue >>= sImageURL; + + ::osl::MutexGuard aGuard( m_aMutex ); + impl_handleNewImageURL_lck( sImageURL, eOther ); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const +{ + switch (nHandle) + { + case PROPERTY_ID_READONLY : rValue <<= (sal_Bool)m_bReadOnly; break; + default: + OBoundControlModel::getFastPropertyValue(rValue, nHandle); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception) +{ + switch (nHandle) + { + case PROPERTY_ID_READONLY : + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OImageControlModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + m_bReadOnly = getBOOL(rValue); + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) + throw( IllegalArgumentException ) +{ + switch (nHandle) + { + case PROPERTY_ID_READONLY : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bReadOnly); + + default: + return OBoundControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 2, OBoundControlModel ) + DECL_BOOL_PROP1 ( READONLY, BOUND ); + DECL_PROP1 ( TABINDEX, sal_Int16, BOUND ); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString OImageControlModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_IMAGECONTROL; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void OImageControlModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + // Basisklasse + OBoundControlModel::write(_rxOutStream); + // Version + _rxOutStream->writeShort(0x0003); + // Name + _rxOutStream->writeBoolean(m_bReadOnly); + writeHelpTextCompatibly(_rxOutStream); + // from version 0x0003 : common properties + writeCommonProperties(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void OImageControlModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + OBoundControlModel::read(_rxInStream); + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + switch (nVersion) + { + case 0x0001: + m_bReadOnly = _rxInStream->readBoolean(); + break; + case 0x0002: + m_bReadOnly = _rxInStream->readBoolean(); + readHelpTextCompatibly(_rxInStream); + break; + case 0x0003: + m_bReadOnly = _rxInStream->readBoolean(); + readHelpTextCompatibly(_rxInStream); + readCommonProperties(_rxInStream); + break; + default : + DBG_ERROR("OImageControlModel::read : unknown version !"); + m_bReadOnly = sal_False; + defaultCommonProperties(); + break; + } + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + { // (not if we don't have a control source - the "State" property acts like it is persistent, then + ::osl::MutexGuard aGuard(m_aMutex); // resetNoBroadcast expects this mutex guarding + resetNoBroadcast(); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::impl_updateStreamForURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator ) +{ + // create a stream for the image specified by the URL + ::std::auto_ptr< SvStream > pImageStream; + Reference< XInputStream > xImageStream; + + if ( ::svt::GraphicAccess::isSupportedURL( _rURL ) ) + { + xImageStream = ::svt::GraphicAccess::getImageXStream( getContext().getLegacyServiceFactory(), _rURL ); + } + else + { + pImageStream.reset( ::utl::UcbStreamHelper::CreateStream( _rURL, STREAM_READ ) ); + sal_Bool bSetNull = ( pImageStream.get() == NULL ) || ( ERRCODE_NONE != pImageStream->GetErrorCode() ); + + if ( !bSetNull ) + { + // get the size of the stream + pImageStream->Seek(STREAM_SEEK_TO_END); + sal_Int32 nSize = (sal_Int32)pImageStream->Tell(); + if (pImageStream->GetBufferSize() < 8192) + pImageStream->SetBufferSize(8192); + pImageStream->Seek(STREAM_SEEK_TO_BEGIN); + + xImageStream = new ::utl::OInputStreamHelper( new SvLockBytes( pImageStream.get(), sal_False ), nSize ); + } + } + + if ( xImageStream.is() ) + { + if ( m_xColumnUpdate.is() ) + m_xColumnUpdate->updateBinaryStream( xImageStream, xImageStream->available() ); + else + setControlValue( makeAny( xImageStream ), _eInstigator ); + xImageStream->closeInput(); + return sal_True; + } + + return sal_False; +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::impl_handleNewImageURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator ) +{ + switch ( lcl_getImageStoreType( getFieldType() ) ) + { + case ImageStoreBinary: + if ( impl_updateStreamForURL_lck( _rURL, _eInstigator ) ) + return sal_True; + break; + + case ImageStoreLink: + { + ::rtl::OUString sCommitURL( _rURL ); + if ( m_sDocumentURL.getLength() ) + sCommitURL = URIHelper::simpleNormalizedMakeRelative( m_sDocumentURL, sCommitURL ); + OSL_ENSURE( m_xColumnUpdate.is(), "OImageControlModel::impl_handleNewImageURL_lck: no bound field, but ImageStoreLink?!" ); + if ( m_xColumnUpdate.is() ) + { + m_xColumnUpdate->updateString( sCommitURL ); + return sal_True; + } + } + break; + + case ImageStoreInvalid: + OSL_ENSURE( false, "OImageControlModel::impl_handleNewImageURL_lck: invalid current field type!" ); + break; + } + + // if we're here, then the above code was unable to update our field/control from the given URL + // => fall back to NULL/VOID + if ( m_xColumnUpdate.is() ) + m_xColumnUpdate->updateNull(); + else + setControlValue( Any(), _eInstigator ); + + return sal_True; +} + +//------------------------------------------------------------------------------ +sal_Bool OImageControlModel::commitControlValueToDbColumn( bool _bPostReset ) +{ + if ( _bPostReset ) + { + // since this is a "commit after reset", we can simply update the column + // with null - this is our "default" which we were just reset to + if ( m_xColumnUpdate.is() ) + m_xColumnUpdate->updateNull(); + } + else + { + ::osl::MutexGuard aGuard(m_aMutex); + + ::rtl::OUString sImageURL; + m_xAggregateSet->getPropertyValue( PROPERTY_IMAGE_URL ) >>= sImageURL; + return impl_handleNewImageURL_lck( sImageURL, eDbColumnBinding ); + } + + return sal_True; +} + +//------------------------------------------------------------------------------ +namespace +{ + bool lcl_isValidDocumentURL( const ::rtl::OUString& _rDocURL ) + { + return ( _rDocURL.getLength() && !_rDocURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:object" ) ) ); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + OBoundControlModel::onConnectedDbColumn( _rxForm ); + + try + { + Reference< XModel > xDocument( getXModel( *this ) ); + if ( xDocument.is() ) + { + m_sDocumentURL = xDocument->getURL(); + if ( !lcl_isValidDocumentURL( m_sDocumentURL ) ) + { + Reference< XChild > xAsChild( xDocument, UNO_QUERY ); + while ( xAsChild.is() && !lcl_isValidDocumentURL( m_sDocumentURL ) ) + { + xDocument.set( xAsChild->getParent(), UNO_QUERY ); + if ( xDocument.is() ) + m_sDocumentURL = xDocument->getURL(); + xAsChild.set( xDocument, UNO_QUERY ); + } + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::onDisconnectedDbColumn() +{ + OBoundControlModel::onDisconnectedDbColumn(); + + m_sDocumentURL = ::rtl::OUString(); +} + +//------------------------------------------------------------------------------ +Any OImageControlModel::translateDbColumnToControlValue() +{ + switch ( lcl_getImageStoreType( getFieldType() ) ) + { + case ImageStoreBinary: return makeAny( m_xColumn->getBinaryStream() ); + case ImageStoreLink: + { + ::rtl::OUString sImageLink( m_xColumn->getString() ); + if ( m_sDocumentURL.getLength() ) + sImageLink = INetURLObject::GetAbsURL( m_sDocumentURL, sImageLink ); + return makeAny( sImageLink ); + } + case ImageStoreInvalid: + OSL_ENSURE( false, "OImageControlModel::translateDbColumnToControlValue: invalid field type!" ); + break; + } + return Any(); +} + +//------------------------------------------------------------------------------ +void OImageControlModel::doSetControlValue( const Any& _rValue ) +{ + DBG_ASSERT( GetImageProducer() && m_xImageProducer.is(), "OImageControlModel::doSetControlValue: no image producer!" ); + if ( !GetImageProducer() || !m_xImageProducer.is() ) + return; + + bool bStartProduction = false; + switch ( lcl_getImageStoreType( getFieldType() ) ) + { + case ImageStoreBinary: + { + // give the image producer the stream + Reference< XInputStream > xInStream; + _rValue >>= xInStream; + GetImageProducer()->setImage( xInStream ); + bStartProduction = true; + } + break; + + case ImageStoreLink: + { + ::rtl::OUString sImageURL; + _rValue >>= sImageURL; + GetImageProducer()->SetImage( sImageURL ); + bStartProduction = true; + } + break; + + case ImageStoreInvalid: + OSL_ENSURE( false, "OImageControlModel::doSetControlValue: invalid field type!" ); + break; + + } // switch ( lcl_getImageStoreType( getFieldType() ) ) + + if ( bStartProduction ) + { + // start production + Reference< XImageProducer > xProducer = m_xImageProducer; + { + // release our mutex once (it's acquired in the calling method!), as starting the image production may + // result in the locking of the solar mutex (unfortunally the default implementation of our aggregate, + // VCLXImageControl, does this locking) + // FS - 74438 - 30.03.00 + MutexRelease aRelease(m_aMutex); + xProducer->startProduction(); + } + } +} + +// OComponentHelper +//------------------------------------------------------------------ +void SAL_CALL OImageControlModel::disposing() +{ + OBoundControlModel::disposing(); + + { + ::osl::MutexGuard aGuard( m_aMutex ); // setControlValue expects this + setControlValue( Any(), eOther ); + } +} + +//------------------------------------------------------------------------------ +void OImageControlModel::resetNoBroadcast() +{ + if ( hasField() ) // only reset when we are connected to a column + OBoundControlModel::resetNoBroadcast( ); +} + +//-------------------------------------------------------------------- +Reference< XImageProducer > SAL_CALL OImageControlModel::getImageProducer() throw ( RuntimeException) +{ + return this; +} + +//-------------------------------------------------------------------- +void SAL_CALL OImageControlModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) +{ + GetImageProducer()->addConsumer( _rxConsumer ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OImageControlModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) +{ + GetImageProducer()->removeConsumer( _rxConsumer ); +} + +//-------------------------------------------------------------------- +void SAL_CALL OImageControlModel::startProduction( ) throw (RuntimeException) +{ + GetImageProducer()->startProduction(); +} + +//------------------------------------------------------------------------------ +IMPL_LINK( OImageControlModel, OnImageImportDone, ::Graphic*, i_pGraphic ) +{ + ENSURE_OR_RETURN( i_pGraphic, "OImageControlModel::OnImageImportDone: illegal graphic!", 0L ); + setPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" ) ), + makeAny( Image( i_pGraphic->GetBitmapEx() ).GetXGraphic() ) + ); + return 1L; +} + +//================================================================== +// OImageControlControl +//================================================================== + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OImageControlControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OImageControlControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OImageControlControl::_getTypes() +{ + return concatSequences( + OBoundControl::_getTypes(), + OImageControlControl_Base::getTypes() + ); +} + +//------------------------------------------------------------------------------ +OImageControlControl::OImageControlControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_IMAGECONTROL) + ,m_aModifyListeners( m_aMutex ) +{ + increment(m_refCount); + { + // als Focus- und MouseListener anmelden + Reference< XWindow > xComp; + query_aggregation( m_xAggregate, xComp ); + if ( xComp.is() ) + xComp->addMouseListener( this ); + } + decrement(m_refCount); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OImageControlControl::queryAggregation(const Type& _rType) throw (RuntimeException) +{ + Any aReturn = OBoundControl::queryAggregation( _rType ); + if ( !aReturn.hasValue() ) + aReturn = ::cppu::queryInterface( + _rType, + static_cast< XMouseListener* >( this ), + static_cast< XModifyBroadcaster* >( this ) + ); + + return aReturn; +} + +//------------------------------------------------------------------------------ +StringSequence OImageControlControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_IMAGECONTROL; + return aSupported; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::addModifyListener( const Reference< XModifyListener >& _Listener ) throw (RuntimeException) +{ + m_aModifyListeners.addInterface( _Listener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::removeModifyListener( const Reference< XModifyListener >& _Listener ) throw (RuntimeException) +{ + m_aModifyListeners.removeInterface( _Listener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::disposing() +{ + EventObject aEvent( *this ); + m_aModifyListeners.disposeAndClear( aEvent ); + + OBoundControl::disposing(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::disposing( const EventObject& _Event ) throw(RuntimeException) +{ + OBoundControl::disposing( _Event ); +} + +//------------------------------------------------------------------------------ +void OImageControlControl::implClearGraphics( sal_Bool _bForce ) +{ + Reference< XPropertySet > xSet( getModel(), UNO_QUERY ); + if ( xSet.is() ) + { + if ( _bForce ) + { + ::rtl::OUString sOldImageURL; + xSet->getPropertyValue( PROPERTY_IMAGE_URL ) >>= sOldImageURL; + + if ( !sOldImageURL.getLength() ) + // the ImageURL is already empty, so simply setting a new empty one would not suffice + // (since it would be ignored) + xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:emptyImage" ) ) ) ); + // (the concrete URL we're passing here doens't matter. It's important that + // the model cannot resolve it to a a valid resource describing an image stream + } + + xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString() ) ); + } +} + +//------------------------------------------------------------------------------ +bool OImageControlControl::implInsertGraphics() +{ + Reference< XPropertySet > xSet( getModel(), UNO_QUERY ); + if ( !xSet.is() ) + return false; + + ::rtl::OUString sTitle = FRM_RES_STRING(RID_STR_IMPORT_GRAPHIC); + // build some arguments for the upcoming dialog + try + { + ::sfx2::FileDialogHelper aDialog( TemplateDescription::FILEOPEN_LINK_PREVIEW, SFXWB_GRAPHIC ); + aDialog.SetTitle( sTitle ); + + Reference< XFilePickerControlAccess > xController( aDialog.GetFilePicker(), UNO_QUERY_THROW ); + xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, ::cppu::bool2any(sal_True)); + + Reference<XPropertySet> xBoundField; + if ( hasProperty( PROPERTY_BOUNDFIELD, xSet ) ) + xSet->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xBoundField; + sal_Bool bHasField = xBoundField.is(); + + // if the control is bound to a DB field, then it's not possible to decide whether or not to link + xController->enableControl(ExtendedFilePickerElementIds::CHECKBOX_LINK, !bHasField ); + + // if the control is bound to a DB field, then linking of the image depends on the type of the field + sal_Bool bImageIsLinked = sal_True; + if ( bHasField ) + { + sal_Int32 nFieldType = DataType::OTHER; + OSL_VERIFY( xBoundField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType ); + bImageIsLinked = ( lcl_getImageStoreType( nFieldType ) == ImageStoreLink ); + } + xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, makeAny( bImageIsLinked ) ); + + if ( ERRCODE_NONE == aDialog.Execute() ) + { + // reset the url property in case it already has the value we're about to set - in this case + // our propertyChanged would not get called without this. + implClearGraphics( sal_False ); + sal_Bool bIsLink = sal_False; + xController->getValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0) >>= bIsLink; + if ( !bIsLink ) + { + Graphic aGraphic; + aDialog.GetGraphic( aGraphic ); + + Reference< graphic::XGraphicObject > xGrfObj = graphic::GraphicObject::create( m_aContext.getUNOContext() ); + xGrfObj->setGraphic( aGraphic.GetXGraphic() ); + rtl::OUString sObjectID( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) ); + sObjectID = sObjectID + xGrfObj->getUniqueID(); + xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( sObjectID ) ) ); + } + else + xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( aDialog.GetPath() ) ) ); + + return true; + } + } + catch(Exception&) + { + DBG_ERROR("OImageControlControl::implInsertGraphics: caught an exception while attempting to execute the FilePicker!"); + } + return false; +} + +//------------------------------------------------------------------------------ +bool OImageControlControl::impl_isEmptyGraphics_nothrow() const +{ + bool bIsEmpty = true; + + try + { + Reference< XPropertySet > xModelProps( const_cast< OImageControlControl* >( this )->getModel(), UNO_QUERY_THROW ); + Reference< XGraphic > xGraphic; + OSL_VERIFY( xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" ) ) ) >>= xGraphic ); + bIsEmpty = !xGraphic.is(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return bIsEmpty; +} + +// MouseListener +//------------------------------------------------------------------------------ +void OImageControlControl::mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if (e.Buttons != MouseButton::LEFT) + return; + + bool bModified = false; + // is this a request for a context menu? + if ( e.PopupTrigger ) + { + Reference< XPopupMenu > xMenu( m_aContext.createComponent( "com.sun.star.awt.PopupMenu" ), UNO_QUERY ); + DBG_ASSERT( xMenu.is(), "OImageControlControl::mousePressed: could not create a popup menu!" ); + + Reference< XWindowPeer > xWindowPeer = getPeer(); + DBG_ASSERT( xWindowPeer.is(), "OImageControlControl::mousePressed: no window!" ); + + if ( xMenu.is() && xWindowPeer.is() ) + { + xMenu->insertItem( ID_OPEN_GRAPHICS, FRM_RES_STRING( RID_STR_OPEN_GRAPHICS ), 0, 0 ); + xMenu->insertItem( ID_CLEAR_GRAPHICS, FRM_RES_STRING( RID_STR_CLEAR_GRAPHICS ), 0, 1 ); + + // check if the ImageURL is empty + if ( impl_isEmptyGraphics_nothrow() ) + xMenu->enableItem( ID_CLEAR_GRAPHICS, sal_False ); + + awt::Rectangle aRect( e.X, e.Y, 0, 0 ); + if ( ( e.X < 0 ) || ( e.Y < 0 ) ) + { // context menu triggered by keyboard + // position it in the center of the control + // 102205 - 16.08.2002 - fs@openoffice.org + Reference< XWindow > xWindow( static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY ); + OSL_ENSURE( xWindow.is(), "OImageControlControl::mousePressed: me not a window? How this?" ); + if ( xWindow.is() ) + { + awt::Rectangle aPosSize = xWindow->getPosSize(); + aRect.X = aPosSize.Width / 2; + aRect.Y = aPosSize.Height / 2; + } + } + + const sal_Int16 nResult = xMenu->execute( xWindowPeer, aRect, PopupMenuDirection::EXECUTE_DEFAULT ); + + switch ( nResult ) + { + case ID_OPEN_GRAPHICS: + implInsertGraphics(); + bModified = true; + break; + + case ID_CLEAR_GRAPHICS: + implClearGraphics( sal_True ); + bModified = true; + break; + } + } + } + else + { + ////////////////////////////////////////////////////////////////////// + // Doppelclick + if (e.ClickCount == 2) + { + + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (!xSet.is()) + return; + + // wenn Control nicht gebunden ist, kein Dialog (da die zu schickende URL hinterher sowieso + // versanden wuerde) + // FS - #64946# - 19.04.99 + Reference<XPropertySet> xBoundField; + if (hasProperty(PROPERTY_BOUNDFIELD, xSet)) + ::cppu::extractInterface(xBoundField, xSet->getPropertyValue(PROPERTY_BOUNDFIELD)); + if (!xBoundField.is()) + { + // but only if our IMAGE_URL property is handled as if it is transient, which is equivalent to + // an empty control source + if (!hasProperty(PROPERTY_CONTROLSOURCE, xSet) || (::comphelper::getString(xSet->getPropertyValue(PROPERTY_CONTROLSOURCE)).getLength() != 0)) + return; + } + + sal_Bool bReadOnly = false; + xSet->getPropertyValue(PROPERTY_READONLY) >>= bReadOnly; + if (bReadOnly) + return; + + if ( implInsertGraphics() ) + bModified = true; + } + } + + if ( bModified ) + { + EventObject aEvent( *this ); + m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent ); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::mouseReleased(const awt::MouseEvent& /*e*/) throw ( RuntimeException ) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::mouseEntered(const awt::MouseEvent& /*e*/) throw ( RuntimeException ) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OImageControlControl::mouseExited(const awt::MouseEvent& /*e*/) throw ( RuntimeException ) +{ +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/ImageControl.hxx b/forms/source/component/ImageControl.hxx new file mode 100644 index 000000000000..c31216fc8aca --- /dev/null +++ b/forms/source/component/ImageControl.hxx @@ -0,0 +1,203 @@ +/************************************************************************* + * + * 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 _FRM_IMAGE_CONTROL_HXX_ +#define _FRM_IMAGE_CONTROL_HXX_ + +#include "FormComponent.hxx" +#include "imgprod.hxx" +#include <com/sun/star/form/XImageProducerSupplier.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <comphelper/propmultiplex.hxx> +#include <comphelper/implementationreference.hxx> +#include <cppuhelper/implbase2.hxx> + +using namespace comphelper; + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +// OImageControlModel +//================================================================== +typedef ::cppu::ImplHelper2 < ::com::sun::star::form::XImageProducerSupplier + , ::com::sun::star::awt::XImageProducer + > OImageControlModel_Base; + +class OImageControlModel + :public OImageControlModel_Base + ,public OBoundControlModel +{ + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageProducer> m_xImageProducer; + ImageProducer* m_pImageProducer; + sal_Bool m_bReadOnly; + ::rtl::OUString m_sDocumentURL; + +protected: + // UNO Anbindung + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + + inline ImageProducer* GetImageProducer() { return m_pImageProducer; } + +public: + DECLARE_DEFAULT_LEAF_XTOR( OImageControlModel ); + + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception); + + 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); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OImageControlModel, OBoundControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OImageControlModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // OPropertyChangeListener + virtual void _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& ) throw(::com::sun::star::uno::RuntimeException); + + // 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); + + // XImageProducerSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageProducer> SAL_CALL getImageProducer() throw ( ::com::sun::star::uno::RuntimeException); + + // XImageProducer + virtual void SAL_CALL addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& xConsumer ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& xConsumer ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL startProduction( ) throw (::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OBoundControlModel::disposing; + using OBoundControlModel::getFastPropertyValue; + +protected: + // OBoundControlModel overridables + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual void doSetControlValue( const ::com::sun::star::uno::Any& _rValue ); + + virtual sal_Bool approveDbColumnType(sal_Int32 _nColumnType); + + virtual void resetNoBroadcast(); + +protected: + DECLARE_XCLONEABLE(); + + void implConstruct(); + + /** displays the image described by the given URL + @precond + our own mutex is locked + */ + sal_Bool impl_handleNewImageURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator ); + + /** updates the binary stream, created from loading the file which the given URL points to, into our + bound field, or the control itself if there is no bound field + */ + sal_Bool impl_updateStreamForURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator ); + + DECL_LINK( OnImageImportDone, ::Graphic* ); +}; + +//================================================================== +//= OImageControlControl +//================================================================== +typedef ::cppu::ImplHelper2 < ::com::sun::star::awt::XMouseListener + , ::com::sun::star::util::XModifyBroadcaster + > OImageControlControl_Base; +class OImageControlControl : public OBoundControl + , public OImageControlControl_Base +{ +private: + ::cppu::OInterfaceContainerHelper m_aModifyListeners; + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OImageControlControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // UNO + DECLARE_UNO3_AGG_DEFAULTS( OImageControlControl, OBoundControl ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + IMPLEMENTATION_NAME(OImageControlControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // XMouseListener + virtual void SAL_CALL mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseReleased(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseEntered(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL mouseExited(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException); + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + +private: + void implClearGraphics( sal_Bool _bForce ); + bool implInsertGraphics(); + + /** determines whether the control does currently have an empty grahic set + */ + bool impl_isEmptyGraphics_nothrow() const; +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FRM_IMAGE_CONTROL_HXX_ + diff --git a/forms/source/component/ListBox.cxx b/forms/source/component/ListBox.cxx new file mode 100644 index 000000000000..d2de4882dead --- /dev/null +++ b/forms/source/component/ListBox.cxx @@ -0,0 +1,1846 @@ +/************************************************************************* +* + * 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. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "ListBox.hxx" +#include "property.hxx" +#include "property.hrc" +#include "services.hxx" +#include "frm_resource.hxx" +#include "frm_resource.hrc" +#include "BaseListBox.hxx" +#include "listenercontainers.hxx" +#include "componenttools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +/** === end UNO includes === **/ + +#include <comphelper/basicio.hxx> +#include <comphelper/container.hxx> +#include <comphelper/numbers.hxx> +#include <comphelper/listenernotification.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/formattedcolumnvalue.hxx> +#include <connectivity/dbconversion.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <rtl/logfile.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/sharedunocomponent.hxx> +#include <vcl/svapp.hxx> + +#include <algorithm> +#include <functional> + + +//......................................................................... +namespace frm +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form::binding; + using namespace ::dbtools; + + using ::connectivity::ORowSetValue; + + //============================================================================== + //= helper + //============================================================================== + namespace + { + //-------------------------------------------------------------------------- + struct RowSetValueToString : public ::std::unary_function< ORowSetValue, ::rtl::OUString > + { + ::rtl::OUString operator()( const ORowSetValue& _value ) const + { + return _value.getString(); + } + }; + + //-------------------------------------------------------------------------- + struct AppendRowSetValueString : public ::std::unary_function< ::rtl::OUString, void > + { + AppendRowSetValueString( ::rtl::OUString& _string ) + :m_string( _string ) + { + } + + void operator()( const ::rtl::OUString _append ) + { + m_string += _append; + } + + private: + ::rtl::OUString& m_string; + }; + + //-------------------------------------------------------------------------- + Sequence< ::rtl::OUString > lcl_convertToStringSequence( const ValueList& _values ) + { + Sequence< ::rtl::OUString > aStrings( _values.size() ); + ::std::transform( + _values.begin(), + _values.end(), + aStrings.getArray(), + RowSetValueToString() + ); + return aStrings; + } + } + + //============================================================================== + //= ItemEventDescription + //============================================================================== + typedef ::comphelper::EventHolder< ItemEvent > ItemEventDescription; + + //============================================================================== + //= OListBoxModel + //============================================================================== + //------------------------------------------------------------------ + InterfaceRef SAL_CALL OListBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) + { + return *(new OListBoxModel(_rxFactory)); + } + + //------------------------------------------------------------------------------ + Sequence< Type> OListBoxModel::_getTypes() + { + return TypeBag( + OBoundControlModel::_getTypes(), + OEntryListHelper::getTypes(), + OErrorBroadcaster::getTypes() + ).getTypes(); + } + + + DBG_NAME(OListBoxModel); + //------------------------------------------------------------------ + OListBoxModel::OListBoxModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_LISTBOX, FRM_SUN_CONTROL_LISTBOX, sal_True, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OEntryListHelper( (OControlModel&)*this ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,m_aListRowSet( getContext() ) + ,m_nNULLPos(-1) + ,m_nBoundColumnType( DataType::SQLNULL ) + { + DBG_CTOR(OListBoxModel,NULL); + + m_nClassId = FormComponentType::LISTBOX; + m_eListSourceType = ListSourceType_VALUELIST; + m_aBoundColumn <<= (sal_Int16)1; + initValueProperty( PROPERTY_SELECT_SEQ, PROPERTY_ID_SELECT_SEQ); + + startAggregatePropertyListening( PROPERTY_STRINGITEMLIST ); + } + + //------------------------------------------------------------------ + OListBoxModel::OListBoxModel( const OListBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + ,OEntryListHelper( *_pOriginal, (OControlModel&)*this ) + ,OErrorBroadcaster( OComponentHelper::rBHelper ) + ,m_aListRowSet( getContext() ) + ,m_eListSourceType( _pOriginal->m_eListSourceType ) + ,m_aBoundColumn( _pOriginal->m_aBoundColumn ) + ,m_aListSourceValues( _pOriginal->m_aListSourceValues ) + ,m_aBoundValues( _pOriginal->m_aBoundValues ) + ,m_aDefaultSelectSeq( _pOriginal->m_aDefaultSelectSeq ) + ,m_nNULLPos(-1) + ,m_nBoundColumnType( DataType::SQLNULL ) + { + DBG_CTOR(OListBoxModel,NULL); + + startAggregatePropertyListening( PROPERTY_STRINGITEMLIST ); + } + + //------------------------------------------------------------------ + OListBoxModel::~OListBoxModel() + { + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + DBG_DTOR(OListBoxModel,NULL); + } + + // XCloneable + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( OListBoxModel ) + + // XServiceInfo + //------------------------------------------------------------------------------ + StringSequence SAL_CALL OListBoxModel::getSupportedServiceNames() throw(RuntimeException) + { + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_LISTBOX; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_LISTBOX; + *pStoreTo++ = BINDABLE_DATABASE_LIST_BOX; + + return aSupported; + } + + //------------------------------------------------------------------------------ + Any SAL_CALL OListBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException) + { + Any aReturn = OBoundControlModel::queryAggregation( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OEntryListHelper::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OErrorBroadcaster::queryInterface( _rType ); + return aReturn; + } + + // OComponentHelper + //------------------------------------------------------------------------------ + void OListBoxModel::disposing() + { + OBoundControlModel::disposing(); + OEntryListHelper::disposing(); + OErrorBroadcaster::disposing(); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const + { + switch (_nHandle) + { + case PROPERTY_ID_BOUNDCOLUMN: + _rValue <<= m_aBoundColumn; + break; + + case PROPERTY_ID_LISTSOURCETYPE: + _rValue <<= m_eListSourceType; + break; + + case PROPERTY_ID_LISTSOURCE: + _rValue <<= lcl_convertToStringSequence( m_aListSourceValues ); + break; + + case PROPERTY_ID_VALUE_SEQ: + _rValue <<= lcl_convertToStringSequence( m_aBoundValues ); + break; + + case PROPERTY_ID_DEFAULT_SELECT_SEQ: + _rValue <<= m_aDefaultSelectSeq; + break; + + case PROPERTY_ID_STRINGITEMLIST: + _rValue <<= getStringItemList(); + break; + + default: + OBoundControlModel::getFastPropertyValue(_rValue, _nHandle); + } + } + + //------------------------------------------------------------------------------ + void OListBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception) + { + switch (_nHandle) + { + case PROPERTY_ID_BOUNDCOLUMN : + DBG_ASSERT((_rValue.getValueType().getTypeClass() == TypeClass_SHORT) || (_rValue.getValueType().getTypeClass() == TypeClass_VOID), + "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + m_aBoundColumn = _rValue; + break; + + case PROPERTY_ID_LISTSOURCETYPE : + DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(reinterpret_cast<ListSourceType*>(NULL))), + "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_eListSourceType; + break; + + case PROPERTY_ID_LISTSOURCE: + { + // extract + Sequence< ::rtl::OUString > aListSource; + OSL_VERIFY( _rValue >>= aListSource ); + + // copy to member + ValueList().swap(m_aListSourceValues); + ::std::copy( + aListSource.getConstArray(), + aListSource.getConstArray() + aListSource.getLength(), + ::std::insert_iterator< ValueList >( m_aListSourceValues, m_aListSourceValues.end() ) + ); + + // propagate + if ( m_eListSourceType == ListSourceType_VALUELIST ) + { + m_aBoundValues = m_aListSourceValues; + } + else + { + if ( m_xCursor.is() && !hasField() && !hasExternalListSource() ) + // listbox is already connected to a database, and no external list source + // data source changed -> refresh + loadData( false ); + } + } + break; + + case PROPERTY_ID_VALUE_SEQ : + OSL_ENSURE( false, "ValueItemList is read-only!" ); + throw PropertyVetoException(); + + case PROPERTY_ID_DEFAULT_SELECT_SEQ : + DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(reinterpret_cast< Sequence<sal_Int16>*>(NULL))), + "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + _rValue >>= m_aDefaultSelectSeq; + + DBG_ASSERT(m_xAggregateFastSet.is(), "OListBoxModel::setFastPropertyValue_NoBroadcast(DEFAULT_SELECT_SEQ) : invalid aggregate !"); + if ( m_xAggregateFastSet.is() ) + setControlValue( _rValue, eOther ); + break; + + case PROPERTY_ID_STRINGITEMLIST: + { + ControlModelLock aLock( *this ); + setNewStringItemList( _rValue, aLock ); + // TODO: this is bogus. setNewStringItemList expects a guard which has the *only* + // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with + // a lock - so we effectively has two locks here, of which setNewStringItemList can + // only control one. + } + resetNoBroadcast(); + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + } + } + + //------------------------------------------------------------------------------ + sal_Bool OListBoxModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue) + throw (IllegalArgumentException) + { + sal_Bool bModified(sal_False); + switch (_nHandle) + { + case PROPERTY_ID_BOUNDCOLUMN : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aBoundColumn, ::getCppuType(reinterpret_cast<sal_Int16*>(NULL))); + break; + + case PROPERTY_ID_LISTSOURCETYPE: + bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType); + break; + + case PROPERTY_ID_LISTSOURCE: + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, lcl_convertToStringSequence( m_aListSourceValues ) ); + break; + + case PROPERTY_ID_VALUE_SEQ : + OSL_ENSURE( false, "ValueItemList is read-only!" ); + throw PropertyVetoException(); + + case PROPERTY_ID_DEFAULT_SELECT_SEQ : + bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultSelectSeq); + break; + + case PROPERTY_ID_STRINGITEMLIST: + bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue ); + break; + + default: + return OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue); + } + return bModified; + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxModel::setPropertyValues( const Sequence< ::rtl::OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) + { + // if both SelectedItems and StringItemList are set, care for this + // #i27024# / 2004-04-05 / fs@openoffice.org + const Any* pSelectSequenceValue = NULL; + + const ::rtl::OUString* pStartPos = _rPropertyNames.getConstArray(); + const ::rtl::OUString* pEndPos = _rPropertyNames.getConstArray() + _rPropertyNames.getLength(); + const ::rtl::OUString* pSelectedItemsPos = ::std::find_if( + pStartPos, pEndPos, + ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_SELECT_SEQ ) + ); + const ::rtl::OUString* pStringItemListPos = ::std::find_if( + pStartPos, pEndPos, + ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_STRINGITEMLIST ) + ); + if ( ( pSelectedItemsPos != pEndPos ) && ( pStringItemListPos != pEndPos ) ) + { + // both properties are present + // -> remember the value for the select sequence + pSelectSequenceValue = _rValues.getConstArray() + ( pSelectedItemsPos - pStartPos ); + } + + OBoundControlModel::setPropertyValues( _rPropertyNames, _rValues ); + + if ( pSelectSequenceValue ) + { + setPropertyValue( PROPERTY_SELECT_SEQ, *pSelectSequenceValue ); + // Note that this is the only reliable way, since one of the properties is implemented + // by ourself, and one is implemented by the aggregate, we cannot rely on any particular + // results when setting them both - too many undocumented behavior in all the involved + // classes + } + } + + //------------------------------------------------------------------------------ + void OListBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 7, OBoundControlModel ) + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP2(BOUNDCOLUMN, sal_Int16, BOUND, MAYBEVOID); + DECL_PROP1(LISTSOURCETYPE, ListSourceType, BOUND); + DECL_PROP1(LISTSOURCE, StringSequence, BOUND); + DECL_PROP3(VALUE_SEQ, StringSequence, BOUND, READONLY, TRANSIENT); + DECL_PROP1(DEFAULT_SELECT_SEQ, Sequence<sal_Int16>, BOUND); + DECL_PROP1(STRINGITEMLIST, Sequence< ::rtl::OUString >, BOUND); + END_DESCRIBE_PROPERTIES(); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::_propertyChanged( const PropertyChangeEvent& i_rEvent ) throw ( RuntimeException ) + { + if ( i_rEvent.PropertyName == PROPERTY_STRINGITEMLIST ) + { + ControlModelLock aLock( *this ); + // SYNCHRONIZED -----> + // our aggregate internally changed its StringItemList property - reflect this in our "overridden" + // version of the property + setNewStringItemList( i_rEvent.NewValue, aLock ); + // <----- SYNCHRONIZED + return; + } + OBoundControlModel::_propertyChanged( i_rEvent ); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const + { + OBoundControlModel::describeAggregateProperties( _rAggregateProps ); + + // superseded properties: + RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST ); + } + + //------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL OListBoxModel::getServiceName() throw(RuntimeException) + { + return FRM_COMPONENT_LISTBOX; // old (non-sun) name for compatibility ! + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxModel::write(const Reference<XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) + { + OBoundControlModel::write(_rxOutStream); + + // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird + Sequence<sal_Int16> aDummySeq; + + // Version + // Version 0x0002: ListSource wird StringSeq + _rxOutStream->writeShort(0x0004); + + // Maskierung fuer any + sal_uInt16 nAnyMask = 0; + if (m_aBoundColumn.getValueType().getTypeClass() != TypeClass_VOID) + nAnyMask |= BOUNDCOLUMN; + + _rxOutStream << nAnyMask; + + _rxOutStream << lcl_convertToStringSequence( m_aListSourceValues ); + _rxOutStream << (sal_Int16)m_eListSourceType; + _rxOutStream << aDummySeq; + _rxOutStream << m_aDefaultSelectSeq; + + if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) + { + sal_Int16 nBoundColumn = 0; + m_aBoundColumn >>= nBoundColumn; + _rxOutStream << nBoundColumn; + } + writeHelpTextCompatibly(_rxOutStream); + + // from version 0x0004 : common properties + writeCommonProperties(_rxOutStream); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) + { + // Bei manchen Variblen muessen Abhaengigkeiten beruecksichtigt werden. + // Deshalb muessen sie explizit ueber setPropertyValue() gesetzt werden. + + OBoundControlModel::read(_rxInStream); + ControlModelLock aLock( *this ); + + // since we are "overwriting" the StringItemList of our aggregate (means we have + // an own place to store the value, instead of relying on our aggregate storing it), + // we need to respect what the aggregate just read for the StringItemList property. + try + { + if ( m_xAggregateSet.is() ) + setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" ); + } + + // Version + sal_uInt16 nVersion = _rxInStream->readShort(); + DBG_ASSERT(nVersion > 0, "OListBoxModel::read : version 0 ? this should never have been written !"); + + if (nVersion > 0x0004) + { + DBG_ERROR("OListBoxModel::read : invalid (means unknown) version !"); + ValueList().swap(m_aListSourceValues); + m_aBoundColumn <<= (sal_Int16)0; + ValueList().swap(m_aBoundValues); + m_eListSourceType = ListSourceType_VALUELIST; + m_aDefaultSelectSeq.realloc(0); + defaultCommonProperties(); + return; + } + + // Maskierung fuer any + sal_uInt16 nAnyMask; + _rxInStream >> nAnyMask; + + // ListSourceSeq + StringSequence aListSourceSeq; + if (nVersion == 0x0001) + { + // ListSourceSeq aus String zusammenstellen; + ::rtl::OUString sListSource; + _rxInStream >> sListSource; + + sal_Int32 nTokens = 1; + const sal_Unicode* pStr = sListSource.getStr(); + while ( *pStr ) + { + if ( *pStr == ';' ) + nTokens++; + pStr++; + } + aListSourceSeq.realloc( nTokens ); + for (sal_uInt16 i=0; i<nTokens; ++i) + { + sal_Int32 nTmp = 0; + aListSourceSeq.getArray()[i] = sListSource.getToken(i,';',nTmp); + } + } + else + _rxInStream >> aListSourceSeq; + + sal_Int16 nListSourceType; + _rxInStream >> nListSourceType; + m_eListSourceType = (ListSourceType)nListSourceType; + Any aListSourceSeqAny; + aListSourceSeqAny <<= aListSourceSeq; + + setFastPropertyValue(PROPERTY_ID_LISTSOURCE, aListSourceSeqAny ); + + // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird + Sequence<sal_Int16> aDummySeq; + _rxInStream >> aDummySeq; + + // DefaultSelectSeq + Sequence<sal_Int16> aDefaultSelectSeq; + _rxInStream >> aDefaultSelectSeq; + Any aDefaultSelectSeqAny; + aDefaultSelectSeqAny <<= aDefaultSelectSeq; + setFastPropertyValue(PROPERTY_ID_DEFAULT_SELECT_SEQ, aDefaultSelectSeqAny); + + // BoundColumn + if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN) + { + sal_Int16 nValue; + _rxInStream >> nValue; + m_aBoundColumn <<= nValue; + } + + if (nVersion > 2) + readHelpTextCompatibly(_rxInStream); + + // if our string list is not filled from the value list, we must empty it + // this can be the case when somebody saves in alive mode + if ( ( m_eListSourceType != ListSourceType_VALUELIST ) + && !hasExternalListSource() + ) + { + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) ); + } + + if (nVersion > 3) + readCommonProperties(_rxInStream); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + // (not if we don't have a control source - the "State" property acts like it is persistent, then + resetNoBroadcast(); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::loadData( bool _bForce ) + { + RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData" ); + DBG_ASSERT( m_eListSourceType != ListSourceType_VALUELIST, "OListBoxModel::loadData: cannot load value list from DB!" ); + DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::loadData: cannot load from DB when I have an external list source!" ); + + m_nNULLPos = -1; + m_nBoundColumnType = DataType::SQLNULL; + + // pre-requisites: + // PRE1: connection + Reference< XConnection > xConnection; + // is the active connection of our form + Reference< XPropertySet > xFormProps( m_xCursor, UNO_QUERY ); + if ( xFormProps.is() ) + xFormProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection; + + // PRE2: list source + ::rtl::OUString sListSource; + // if our list source type is no value list, we need to concatenate + // the single list source elements + ::std::for_each( + m_aListSourceValues.begin(), + m_aListSourceValues.end(), + AppendRowSetValueString( sListSource ) + ); + + // outta here if we don't have all pre-requisites + if ( !xConnection.is() || !sListSource.getLength() ) + { + ValueList().swap(m_aBoundValues); + return; + } + + sal_Int16 nBoundColumn = 0; + if (m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT) + m_aBoundColumn >>= nBoundColumn; + + ::utl::SharedUNOComponent< XResultSet > xListCursor; + try + { + m_aListRowSet.setConnection( xConnection ); + + sal_Bool bExecute = sal_False; + switch (m_eListSourceType) + { + case ListSourceType_TABLEFIELDS: + // don't work with a statement here, the fields will be collected below + break; + + case ListSourceType_TABLE: + { + Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, sListSource); + Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY); + + // do we have a bound column if yes we have to select it + // and the displayed column is the first column othwhise we act as a combobox + ::rtl::OUString aFieldName; + ::rtl::OUString aBoundFieldName; + + if ((nBoundColumn > 0) && xFieldsByIndex.is()) + { + if (xFieldsByIndex->getCount() <= nBoundColumn) + break; + + Reference<XPropertySet> xFieldAsSet(xFieldsByIndex->getByIndex(nBoundColumn),UNO_QUERY); + xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aBoundFieldName; + nBoundColumn = 1; + + xFieldAsSet.set(xFieldsByIndex->getByIndex(0),UNO_QUERY); + xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aFieldName; + } + else if (xFieldsByName.is()) + { + if ( xFieldsByName->hasByName( getControlSource() ) ) + aFieldName = getControlSource(); + else + { + // otherwise look for the alias + Reference< XColumnsSupplier > xSupplyFields; + xFormProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSupplyFields; + + // search the field + DBG_ASSERT(xSupplyFields.is(), "OListBoxModel::loadData : invalid query composer !"); + + Reference<XNameAccess> xFieldNames = xSupplyFields->getColumns(); + if ( xFieldNames->hasByName( getControlSource() ) ) + { + Reference<XPropertySet> xComposerFieldAsSet; + xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet; + if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet)) + xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName; + } + } + } + if (!aFieldName.getLength()) + break; + + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + ::rtl::OUString aQuote = xMeta->getIdentifierQuoteString(); + ::rtl::OUString aStatement = ::rtl::OUString::createFromAscii("SELECT "); + if (!aBoundFieldName.getLength()) // act like a combobox + aStatement += ::rtl::OUString::createFromAscii("DISTINCT "); + + aStatement += quoteName(aQuote,aFieldName); + if (aBoundFieldName.getLength()) + { + aStatement += ::rtl::OUString::createFromAscii(", "); + aStatement += quoteName(aQuote, aBoundFieldName); + } + aStatement += ::rtl::OUString::createFromAscii(" FROM "); + + ::rtl::OUString sCatalog, sSchema, sTable; + qualifiedNameComponents( xMeta, sListSource, sCatalog, sSchema, sTable, eInDataManipulation ); + aStatement += composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ); + + m_aListRowSet.setEscapeProcessing( sal_False ); + m_aListRowSet.setCommand( aStatement ); + bExecute = sal_True; + } + break; + + case ListSourceType_QUERY: + m_aListRowSet.setCommandFromQuery( sListSource ); + bExecute = sal_True; + break; + + default: + m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType ); + m_aListRowSet.setCommand( sListSource ); + bExecute = sal_True; + break; + } + + if (bExecute) + { + if ( !_bForce && !m_aListRowSet.isDirty() ) + { + // if none of the settings of the row set changed, compared to the last + // invocation of loadData, then don't re-fill the list. Instead, assume + // the list entries are the same. + return; + } + xListCursor.reset( m_aListRowSet.execute() ); + } + } + catch(SQLException& eSQL) + { + onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); + return; + } + catch(const Exception& eUnknown) + { + (void)eUnknown; + return; + } + + // Anzeige- und Werteliste fuellen + ValueList aDisplayList, aValueList; + sal_Bool bUseNULL = hasField() && !isRequired(); + + try + { + OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ), + "OListBoxModel::loadData: logic error!" ); + if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) ) + return; + + switch (m_eListSourceType) + { + case ListSourceType_SQL: + case ListSourceType_SQLPASSTHROUGH: + case ListSourceType_TABLE: + case ListSourceType_QUERY: + { + // Feld der 1. Column des ResultSets holen + Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY); + DBG_ASSERT(xSupplyCols.is(), "OListBoxModel::loadData : cursor supports the row set service but is no column supplier?!"); + Reference<XIndexAccess> xColumns; + if (xSupplyCols.is()) + { + xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY); + DBG_ASSERT(xColumns.is(), "OListBoxModel::loadData : no columns supplied by the row set !"); + } + + Reference< XPropertySet > xDataField; + if ( xColumns.is() ) + xColumns->getByIndex(0) >>= xDataField; + if ( !xDataField.is() ) + return; + + ::dbtools::FormattedColumnValue aValueFormatter( getContext(), m_xCursor, xDataField ); + + // Feld der BoundColumn des ResultSets holen + m_nBoundColumnType = DataType::SQLNULL; + if ( ( nBoundColumn > 0 ) && m_xColumn.is() ) + { // don't look for a bound column if we're not connected to a field + try + { + Reference< XPropertySet > xBoundField( xColumns->getByIndex( nBoundColumn ), UNO_QUERY_THROW ); + OSL_VERIFY( xBoundField->getPropertyValue( ::rtl::OUString::createFromAscii( "Type" ) ) >>= m_nBoundColumnType ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + // Ist die LB an ein Feld gebunden und sind Leereintraege zulaessig + // dann wird die Position fuer einen Leereintrag gemerkt + + RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData: string collection" ); + ::rtl::OUString aStr; + sal_Int16 entryPos = 0; + ORowSetValue aBoundValue; + Reference< XRow > xCursorRow( xListCursor, UNO_QUERY_THROW ); + while ( xListCursor->next() && ( entryPos++ < SHRT_MAX ) ) // SHRT_MAX is the maximum number of entries + { + aStr = aValueFormatter.getFormattedValue(); + aDisplayList.push_back( aStr ); + + if ( impl_hasBoundComponent() ) + { + aBoundValue.fill( nBoundColumn + 1, m_nBoundColumnType, xCursorRow ); + aValueList.push_back( aBoundValue ); + } + + if ( bUseNULL && ( m_nNULLPos == -1 ) && !aStr.getLength() ) + m_nNULLPos = sal_Int16( aDisplayList.size() - 1 ); + } + } + break; + + case ListSourceType_TABLEFIELDS: + { + Reference<XNameAccess> xFieldNames = getTableFields(xConnection, sListSource); + if (xFieldNames.is()) + { + StringSequence seqNames = xFieldNames->getElementNames(); + ::std::copy( + seqNames.getConstArray(), + seqNames.getConstArray() + seqNames.getLength(), + ::std::insert_iterator< ValueList >( aDisplayList, aDisplayList.end() ) + ); + } + } + break; + default: + OSL_ENSURE( false, "OListBoxModel::loadData: unreachable!" ); + break; + } + } + catch(SQLException& eSQL) + { + onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST)); + return; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + + // Value-Sequence erzeugen + // NULL eintrag hinzufuegen + if (bUseNULL && m_nNULLPos == -1) + { + if ( impl_hasBoundComponent() ) + aValueList.insert( aValueList.begin(), ORowSetValue() ); + + aDisplayList.insert( aDisplayList.begin(), ORowSetValue( ::rtl::OUString() ) ); + m_nNULLPos = 0; + } + + m_aBoundValues = aValueList; + + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( lcl_convertToStringSequence( aDisplayList ) ) ); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ ) + { + // list boxes which are bound to a db column don't have multi selection + // - this would be unable to reflect in the db column + if ( hasField() ) + { + setFastPropertyValue( PROPERTY_ID_MULTISELECTION, ::cppu::bool2any( ( sal_False ) ) ); + } + + if ( !hasExternalListSource() ) + impl_refreshDbEntryList( false ); + } + + //------------------------------------------------------------------------------ + void OListBoxModel::onDisconnectedDbColumn() + { + if ( m_eListSourceType != ListSourceType_VALUELIST ) + { + ValueList().swap(m_aBoundValues); + m_nNULLPos = -1; + m_nBoundColumnType = DataType::SQLNULL; + + if ( !hasExternalListSource() ) + setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) ); + + m_aListRowSet.dispose(); + } + } + + //------------------------------------------------------------------------------ + ValueList OListBoxModel::impl_getValues() const + { + if ( !m_aBoundValues.empty() ) + return m_aBoundValues; + + Sequence< ::rtl::OUString > aStringItems( getStringItemList() ); + ValueList aValues( aStringItems.getLength() ); + ::std::copy( + aStringItems.getConstArray(), + aStringItems.getConstArray() + aStringItems.getLength(), + aValues.begin() + ); + + return aValues; + } + //------------------------------------------------------------------------------ + ORowSetValue OListBoxModel::getFirstSelectedValue() const + { + static const ORowSetValue s_aEmptyVaue; + + DBG_ASSERT( m_xAggregateFastSet.is(), "OListBoxModel::getFirstSelectedValue: invalid aggregate!" ); + if ( !m_xAggregateFastSet.is() ) + return s_aEmptyVaue; + + Sequence< sal_Int16 > aSelectedIndices; + OSL_VERIFY( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) >>= aSelectedIndices ); + if ( !aSelectedIndices.getLength() ) + // nothing selected at all + return s_aEmptyVaue; + + if ( ( m_nNULLPos != -1 ) && ( aSelectedIndices[0] == m_nNULLPos ) ) + // the dedicated "NULL" entry is selected + return s_aEmptyVaue; + + ValueList aValues( impl_getValues() ); + + size_t selectedValue = aSelectedIndices[0]; + if ( selectedValue >= aValues.size() ) + { + OSL_ENSURE( false, "OListBoxModel::getFirstSelectedValue: inconsistent selection/valuelist!" ); + return s_aEmptyVaue; + } + + return aValues[ selectedValue ]; + } + + //------------------------------------------------------------------------------ + sal_Bool OListBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) + { + // current selektion list + const ORowSetValue aCurrentValue( getFirstSelectedValue() ); + if ( aCurrentValue != m_aSaveValue ) + { + if ( aCurrentValue.isNull() ) + m_xColumnUpdate->updateNull(); + else + { + try + { + m_xColumnUpdate->updateObject( aCurrentValue.makeAny() ); + } + catch ( const Exception& ) + { + return sal_False; + } + } + m_aSaveValue = aCurrentValue; + } + return sal_True; + } + + // XPropertiesChangeListener + //------------------------------------------------------------------------------ + Any OListBoxModel::translateDbColumnToControlValue() + { + Reference< XPropertySet > xBoundField( getField() ); + if ( !xBoundField.is() ) + { + OSL_ENSURE( false, "OListBoxModel::translateDbColumnToControlValue: no field? How could that happen?!" ); + return Any(); + } + + Sequence< sal_Int16 > aSelectionIndicies; + + ORowSetValue aCurrentValue; + aCurrentValue.fill( impl_hasBoundComponent() ? m_nBoundColumnType : getFieldType(), m_xColumn ); + + // reset selection for NULL values + if ( aCurrentValue.isNull() ) + { + if ( m_nNULLPos != -1 ) + { + aSelectionIndicies.realloc(1); + aSelectionIndicies[0] = m_nNULLPos; + } + } + else + { + ValueList aValues( impl_getValues() ); + ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), aCurrentValue ); + if ( curValuePos != aValues.end() ) + { + aSelectionIndicies.realloc( 1 ); + aSelectionIndicies[0] = curValuePos - aValues.begin(); + } + } + + m_aSaveValue = aCurrentValue; + + return makeAny( aSelectionIndicies ); + } + + // XReset + //------------------------------------------------------------------------------ + Any OListBoxModel::getDefaultForReset() const + { + Any aValue; + if (m_aDefaultSelectSeq.getLength()) + aValue <<= m_aDefaultSelectSeq; + else if (m_nNULLPos != -1) // gebundene Listbox + { + Sequence<sal_Int16> aSeq(1); + aSeq.getArray()[0] = m_nNULLPos; + aValue <<= aSeq; + } + else + { + Sequence<sal_Int16> aSeq; + aValue <<= aSeq; + } + + return aValue; + } + + //-------------------------------------------------------------------- + void OListBoxModel::resetNoBroadcast() + { + OBoundControlModel::resetNoBroadcast(); + m_aSaveValue.setNull(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException ) + { + if ( !OEntryListHelper::handleDisposing( _rSource ) ) + OBoundControlModel::disposing( _rSource ); + } + + //-------------------------------------------------------------------- + namespace + { + /** type how we should transfer our selection to external value bindings + */ + enum ExchangeType + { + eIndexList, /// as list of indexes of selected entries + eIndex, /// as index of the selected entry + eEntryList, /// as list of string representations of selected entries + eEntry /// as string representation of the selected entry + }; + + //-------------------------------------------------------------------- + ExchangeType lcl_getCurrentExchangeType( const Type& _rExchangeType ) + { + switch ( _rExchangeType.getTypeClass() ) + { + case TypeClass_STRING: + return eEntry; + case TypeClass_LONG: + return eIndex; + case TypeClass_SEQUENCE: + { + Type aElementType = ::comphelper::getSequenceElementType( _rExchangeType ); + switch ( aElementType.getTypeClass() ) + { + case TypeClass_STRING: + return eEntryList; + case TypeClass_LONG: + return eIndexList; + default: + break; + } + } + default: + break; + } + OSL_ENSURE( false, "lcl_getCurrentExchangeType: unsupported (unexpected) exchange type!" ); + return eEntry; + } + } + + //-------------------------------------------------------------------- + Any OListBoxModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const + { + Sequence< sal_Int16 > aSelectIndexes; + + switch ( lcl_getCurrentExchangeType( getExternalValueType() ) ) + { + case eIndexList: + { + // unfortunately, our select sequence is a sequence<short>, while the external binding + // supplies sequence<int> only -> transform this + Sequence< sal_Int32 > aSelectIndexesPure; + OSL_VERIFY( _rExternalValue >>= aSelectIndexesPure ); + aSelectIndexes.realloc( aSelectIndexesPure.getLength() ); + ::std::copy( + aSelectIndexesPure.getConstArray(), + aSelectIndexesPure.getConstArray() + aSelectIndexesPure.getLength(), + aSelectIndexes.getArray() + ); + } + break; + + case eIndex: + { + sal_Int32 nSelectIndex = -1; + OSL_VERIFY( _rExternalValue >>= nSelectIndex ); + if ( ( nSelectIndex >= 0 ) && ( nSelectIndex < getStringItemList().getLength() ) ) + { + aSelectIndexes.realloc( 1 ); + aSelectIndexes[ 0 ] = static_cast< sal_Int16 >( nSelectIndex ); + } + } + break; + + case eEntryList: + { + // we can retrieve a string list from the binding for multiple selection + Sequence< ::rtl::OUString > aSelectEntries; + OSL_VERIFY( _rExternalValue >>= aSelectEntries ); + + ::std::set< sal_Int16 > aSelectionSet; + + // find the selection entries in our item list + const ::rtl::OUString* pSelectEntries = aSelectEntries.getArray(); + const ::rtl::OUString* pSelectEntriesEnd = pSelectEntries + aSelectEntries.getLength(); + while ( pSelectEntries != pSelectEntriesEnd ) + { + // the indexes where the current string appears in our string items + Sequence< sal_Int16 > aThisEntryIndexes; + aThisEntryIndexes = findValue( getStringItemList(), *pSelectEntries++, sal_False ); + + // insert all the indexes of this entry into our set + ::std::copy( + aThisEntryIndexes.getConstArray(), + aThisEntryIndexes.getConstArray() + aThisEntryIndexes.getLength(), + ::std::insert_iterator< ::std::set< sal_Int16 > >( aSelectionSet, aSelectionSet.begin() ) + ); + } + + // copy the indexes to the sequence + aSelectIndexes.realloc( aSelectionSet.size() ); + ::std::copy( + aSelectionSet.begin(), + aSelectionSet.end(), + aSelectIndexes.getArray() + ); + } + break; + + case eEntry: + { + ::rtl::OUString sStringToSelect; + OSL_VERIFY( _rExternalValue >>= sStringToSelect ); + + aSelectIndexes = findValue( getStringItemList(), sStringToSelect, sal_False ); + } + break; + } + + return makeAny( aSelectIndexes ); + } + + //-------------------------------------------------------------------- + namespace + { + //................................................................ + struct ExtractStringFromSequence_Safe : public ::std::unary_function< sal_Int16, ::rtl::OUString > + { + protected: + const Sequence< ::rtl::OUString >& m_rList; + + public: + ExtractStringFromSequence_Safe( const Sequence< ::rtl::OUString >& _rList ) : m_rList( _rList ) { } + + ::rtl::OUString operator ()( sal_Int16 _nIndex ) + { + OSL_ENSURE( _nIndex < m_rList.getLength(), "ExtractStringFromSequence_Safe: inconsistence!" ); + if ( _nIndex < m_rList.getLength() ) + return m_rList[ _nIndex ]; + return ::rtl::OUString(); + } + }; + + //................................................................ + Any lcl_getSingleSelectedEntry( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList ) + { + Any aReturn; + + // by definition, multiple selected entries are transfered as NULL if the + // binding does not support string lists + if ( _rSelectSequence.getLength() <= 1 ) + { + ::rtl::OUString sSelectedEntry; + + if ( _rSelectSequence.getLength() == 1 ) + sSelectedEntry = ExtractStringFromSequence_Safe( _rStringList )( _rSelectSequence[0] ); + + aReturn <<= sSelectedEntry; + } + + return aReturn; + } + + //................................................................ + Any lcl_getMultiSelectedEntries( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList ) + { + Sequence< ::rtl::OUString > aSelectedEntriesTexts( _rSelectSequence.getLength() ); + ::std::transform( + _rSelectSequence.getConstArray(), + _rSelectSequence.getConstArray() + _rSelectSequence.getLength(), + aSelectedEntriesTexts.getArray(), + ExtractStringFromSequence_Safe( _rStringList ) + ); + return makeAny( aSelectedEntriesTexts ); + } + } + + //-------------------------------------------------------------------- + Any OListBoxModel::translateControlValueToExternalValue( ) const + { + OSL_PRECOND( hasExternalValueBinding(), "OListBoxModel::translateControlValueToExternalValue: no binding!" ); + + Sequence< sal_Int16 > aSelectSequence; + const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence; + + Any aReturn; + switch ( lcl_getCurrentExchangeType( getExternalValueType() ) ) + { + case eIndexList: + { + // unfortunately, the select sequence is a sequence<short>, but our binding + // expects int's + Sequence< sal_Int32 > aTransformed( aSelectSequence.getLength() ); + ::std::copy( + aSelectSequence.getConstArray(), + aSelectSequence.getConstArray() + aSelectSequence.getLength(), + aTransformed.getArray() + ); + aReturn <<= aTransformed; + } + break; + + case eIndex: + if ( aSelectSequence.getLength() <= 1 ) + { + sal_Int32 nIndex = -1; + + if ( aSelectSequence.getLength() == 1 ) + nIndex = aSelectSequence[0]; + + aReturn <<= nIndex; + } + break; + + case eEntryList: + aReturn = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() ); + break; + + case eEntry: + aReturn = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() ); + break; + } + + return aReturn; + } + + //-------------------------------------------------------------------- + Any OListBoxModel::getCurrentFormComponentValue() const + { + if ( hasValidator() ) + return OBoundControlModel::getCurrentFormComponentValue(); + + Any aCurretnValue; + + try + { + Sequence< sal_Int16 > aSelectSequence; + OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence ); + + sal_Bool bMultiSelection( sal_False ); + OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_MULTISELECTION ) >>= bMultiSelection ); + + if ( bMultiSelection ) + aCurretnValue = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() ); + else + aCurretnValue = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return aCurretnValue; + } + + //-------------------------------------------------------------------- + Sequence< Type > OListBoxModel::getSupportedBindingTypes() + { + Sequence< Type > aTypes(4); + aTypes[0] = ::getCppuType( static_cast< Sequence< sal_Int32 >* >( NULL ) ); + aTypes[1] = ::getCppuType( static_cast< sal_Int32* >( NULL ) ); + aTypes[2] = ::getCppuType( static_cast< Sequence< ::rtl::OUString >* >( NULL ) ); + aTypes[3] = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ); + return aTypes; + } + + //-------------------------------------------------------------------- + void OListBoxModel::stringItemListChanged( ControlModelLock& _rInstanceLock ) + { + if ( !m_xAggregateSet.is() ) + return; + + suspendValueListening(); + try + { + m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + resumeValueListening(); + + // update the selection here + if ( hasExternalValueBinding( ) ) + transferExternalValueToControl( _rInstanceLock ); + else + { + if ( hasField() ) + { + // TODO: update the selection in case we're bound to a database column + } + else + { + if ( m_aDefaultSelectSeq.getLength() ) + setControlValue( makeAny( m_aDefaultSelectSeq ), eOther ); + } + } + } + + //-------------------------------------------------------------------- + void OListBoxModel::connectedExternalListSource( ) + { + // TODO? + } + + //-------------------------------------------------------------------- + void OListBoxModel::disconnectedExternalListSource( ) + { + // TODO: in case we're part of an already loaded form, we should probably simulate + // an onConnectedDbColumn, so our list get's filled with the data as indicated + // by our SQL-binding related properties + } + + //-------------------------------------------------------------------- + void OListBoxModel::impl_refreshDbEntryList( bool _bForce ) + { + DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::impl_refreshDbEntryList: invalid call!" ); + + if ( !hasExternalListSource( ) + && ( m_eListSourceType != ListSourceType_VALUELIST ) + && ( m_xCursor.is() ) + ) + { + loadData( _bForce ); + } + } + + //-------------------------------------------------------------------- + void OListBoxModel::refreshInternalEntryList() + { + impl_refreshDbEntryList( true ); + if ( hasField() && m_xCursor.is() ) + initFromField( m_xCursor ); + } + + //================================================================== + // OListBoxControl + //================================================================== + + //------------------------------------------------------------------ + InterfaceRef SAL_CALL OListBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) + { + return *(new OListBoxControl(_rxFactory)); + } + + //------------------------------------------------------------------------------ + Sequence< Type> OListBoxControl::_getTypes() + { + return TypeBag( + OBoundControl::_getTypes(), + OListBoxControl_BASE::getTypes() + ).getTypes(); + } + + //------------------------------------------------------------------ + Any SAL_CALL OListBoxControl::queryAggregation(const Type& _rType) throw (RuntimeException) + { + Any aReturn = OListBoxControl_BASE::queryInterface( _rType ); + + if ( !aReturn.hasValue() + || _rType.equals( XTypeProvider::static_type() ) + ) + aReturn = OBoundControl::queryAggregation( _rType ); + + return aReturn; + } + + DBG_NAME(OListBoxControl); + //------------------------------------------------------------------------------ + OListBoxControl::OListBoxControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl( _rxFactory, VCL_CONTROL_LISTBOX, sal_False ) + ,m_aChangeListeners( m_aMutex ) + ,m_aItemListeners( m_aMutex ) + ,m_pItemBroadcaster( NULL ) + { + DBG_CTOR(OListBoxControl,NULL); + + increment(m_refCount); + { + // als FocusListener anmelden + Reference<XWindow> xComp; + if (query_aggregation(m_xAggregate, xComp)) + xComp->addFocusListener(this); + + // als ItemListener anmelden + if ( query_aggregation( m_xAggregate, m_xAggregateListBox ) ) + m_xAggregateListBox->addItemListener(this); + } + // Refcount bei 2 fuer angemeldete Listener + decrement(m_refCount); + + doSetDelegator(); + + m_aChangeTimer.SetTimeout(500); + m_aChangeTimer.SetTimeoutHdl(LINK(this,OListBoxControl,OnTimeout)); + } + + //------------------------------------------------------------------------------ + OListBoxControl::~OListBoxControl() + { + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + + doResetDelegator(); + m_xAggregateListBox.clear(); + + DBG_DTOR(OListBoxControl,NULL); + } + + //------------------------------------------------------------------------------ + StringSequence SAL_CALL OListBoxControl::getSupportedServiceNames() throw(RuntimeException) + { + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_LISTBOX; + return aSupported; + } + + + // XFocusListener + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::focusGained(const FocusEvent& /*_rEvent*/) throw(RuntimeException) + { + ::osl::MutexGuard aGuard(m_aMutex); + if ( m_aChangeListeners.getLength() ) // only if there are listeners + { + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (xSet.is()) + { + // memorize the current selection for posting the change event + m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); + } + } + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::focusLost(const FocusEvent& /*_rEvent*/) throw(RuntimeException) + { + m_aCurrentSelection.clear(); + } + + // XItemListener + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::itemStateChanged(const ItemEvent& _rEvent) throw(RuntimeException) + { + // forward this to our listeners + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_aItemListeners.getLength() ) + { + if ( !m_pItemBroadcaster.is() ) + { + m_pItemBroadcaster.set( new ::comphelper::AsyncEventNotifier ); + m_pItemBroadcaster->create(); + } + m_pItemBroadcaster->addEvent( new ItemEventDescription( _rEvent ), this ); + } + } + + // and do the handling for the ChangeListeners + ::osl::ClearableMutexGuard aGuard(m_aMutex); + if ( m_aChangeTimer.IsActive() ) + { + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); + + m_aChangeTimer.Stop(); + m_aChangeTimer.Start(); + } + else + { + if ( m_aChangeListeners.getLength() && m_aCurrentSelection.hasValue() ) + { + Reference<XPropertySet> xSet(getModel(), UNO_QUERY); + if (xSet.is()) + { + // Has the selection been changed? + sal_Bool bModified(sal_False); + Any aValue = xSet->getPropertyValue(PROPERTY_SELECT_SEQ); + + Sequence<sal_Int16>& rSelection = *(Sequence<sal_Int16> *)aValue.getValue(); + Sequence<sal_Int16>& rOldSelection = *(Sequence<sal_Int16> *)m_aCurrentSelection.getValue(); + sal_Int32 nLen = rSelection.getLength(); + if (nLen != rOldSelection.getLength()) + bModified = sal_True; + else + { + const sal_Int16* pVal = rSelection.getConstArray(); + const sal_Int16* pCompVal = rOldSelection.getConstArray(); + + while (nLen-- && !bModified) + bModified = pVal[nLen] != pCompVal[nLen]; + } + + if (bModified) + { + m_aCurrentSelection = aValue; + m_aChangeTimer.Start(); + } + } + } + else if (m_aCurrentSelection.hasValue()) + m_aCurrentSelection.clear(); + } + } + + // XEventListener + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::disposing(const EventObject& _rSource) throw (RuntimeException) + { + OBoundControl::disposing(_rSource); + } + + // XChangeBroadcaster + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::addChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException) + { + m_aChangeListeners.addInterface( _rxListener ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OListBoxControl::removeChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException) + { + m_aChangeListeners.removeInterface( _rxListener ); + } + + // OComponentHelper + //------------------------------------------------------------------------------ + void OListBoxControl::disposing() + { + if (m_aChangeTimer.IsActive()) + m_aChangeTimer.Stop(); + + EventObject aEvent( *this ); + m_aChangeListeners.disposeAndClear( aEvent ); + m_aItemListeners.disposeAndClear( aEvent ); + + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_pItemBroadcaster.is() ) + { + m_pItemBroadcaster->removeEventsForProcessor( this ); + m_pItemBroadcaster->terminate(); + m_pItemBroadcaster = NULL; + } + } + + OBoundControl::disposing(); + } + + //------------------------------------------------------------------------------ + void OListBoxControl::processEvent( const AnyEvent& _rEvent ) + { + Reference< XListBox > xKeepAlive( this ); + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( OComponentHelper::rBHelper.bDisposed ) + return; + } + const ItemEventDescription& rItemEvent = static_cast< const ItemEventDescription& >( _rEvent ); + m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, rItemEvent.getEventObject() ); + } + + //------------------------------------------------------------------------------ + IMPL_LINK(OListBoxControl, OnTimeout, void*, /*EMPTYTAG*/) + { + m_aChangeListeners.notifyEach( &XChangeListener::changed, EventObject( *this ) ); + return 0L; + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::addItemListener( const Reference< XItemListener >& l ) throw (RuntimeException) + { + m_aItemListeners.addInterface( l ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::removeItemListener( const Reference< XItemListener >& l ) throw (RuntimeException) + { + m_aItemListeners.removeInterface( l ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::addActionListener( const Reference< XActionListener >& l ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->addActionListener( l ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::removeActionListener( const Reference< XActionListener >& l ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->removeActionListener( l ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::addItem( const ::rtl::OUString& aItem, ::sal_Int16 nPos ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->addItem( aItem, nPos ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::addItems( const Sequence< ::rtl::OUString >& aItems, ::sal_Int16 nPos ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->addItems( aItems, nPos ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->removeItems( nPos, nCount ); + } + + //-------------------------------------------------------------------- + ::sal_Int16 SAL_CALL OListBoxControl::getItemCount( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getItemCount(); + return 0; + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OListBoxControl::getItem( ::sal_Int16 nPos ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getItem( nPos ); + return ::rtl::OUString( ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getItems( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getItems(); + return Sequence< ::rtl::OUString >( ); + } + + //-------------------------------------------------------------------- + ::sal_Int16 SAL_CALL OListBoxControl::getSelectedItemPos( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getSelectedItemPos(); + return 0; + } + + //-------------------------------------------------------------------- + Sequence< ::sal_Int16 > SAL_CALL OListBoxControl::getSelectedItemsPos( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getSelectedItemsPos(); + return Sequence< ::sal_Int16 >( ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OListBoxControl::getSelectedItem( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getSelectedItem(); + return ::rtl::OUString( ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getSelectedItems( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getSelectedItems(); + return Sequence< ::rtl::OUString >( ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::selectItemPos( ::sal_Int16 nPos, ::sal_Bool bSelect ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->selectItemPos( nPos, bSelect ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::selectItemsPos( const Sequence< ::sal_Int16 >& aPositions, ::sal_Bool bSelect ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->selectItemsPos( aPositions, bSelect ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::selectItem( const ::rtl::OUString& aItem, ::sal_Bool bSelect ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->selectItem( aItem, bSelect ); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL OListBoxControl::isMutipleMode( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->isMutipleMode(); + return sal_False; + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::setMultipleMode( ::sal_Bool bMulti ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->setMultipleMode( bMulti ); + } + + //-------------------------------------------------------------------- + ::sal_Int16 SAL_CALL OListBoxControl::getDropDownLineCount( ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + return m_xAggregateListBox->getDropDownLineCount(); + return 0; + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::setDropDownLineCount( ::sal_Int16 nLines ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->setDropDownLineCount( nLines ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OListBoxControl::makeVisible( ::sal_Int16 nEntry ) throw (RuntimeException) + { + if ( m_xAggregateListBox.is() ) + m_xAggregateListBox->makeVisible( nEntry ); + } + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/ListBox.hxx b/forms/source/component/ListBox.hxx new file mode 100644 index 000000000000..46ab6b872fb8 --- /dev/null +++ b/forms/source/component/ListBox.hxx @@ -0,0 +1,286 @@ +/************************************************************************* + * + * 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_LISTBOX_HXX_ +#define _FORMS_LISTBOX_HXX_ + +#include "FormComponent.hxx" +#include "cachedrowset.hxx" +#include "errorbroadcaster.hxx" +#include "entrylisthelper.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp> +#include <com/sun/star/form/ListSourceType.hpp> +#include <com/sun/star/awt/XItemListener.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +#include <com/sun/star/awt/XListBox.hpp> +#include <com/sun/star/form/XChangeBroadcaster.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +/** === end UNO includes === **/ + +#include <comphelper/asyncnotification.hxx> +#include <connectivity/FValue.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/implbase1.hxx> +#include <vcl/timer.hxx> + +#include <vector> + +namespace dbtools +{ + class FormattedColumnValue; +} + +//......................................................................... +namespace frm +{ + +//================================================================== +//= OListBoxModel +//================================================================== +typedef ::std::vector< ::connectivity::ORowSetValue > ValueList; + +class OListBoxModel :public OBoundControlModel + ,public OEntryListHelper + ,public OErrorBroadcaster +{ + + CachedRowSet m_aListRowSet; // the row set to fill the list + ::connectivity::ORowSetValue m_aSaveValue; + + // <properties> + ::com::sun::star::form::ListSourceType m_eListSourceType; // type der list source + ::com::sun::star::uno::Any m_aBoundColumn; + ValueList m_aListSourceValues; + ValueList m_aBoundValues; + ::com::sun::star::uno::Sequence<sal_Int16> m_aDefaultSelectSeq; // DefaultSelected + // </properties> + + sal_Int16 m_nNULLPos; // position of the NULL value in our list + sal_Int32 m_nBoundColumnType; + +private: + ::connectivity::ORowSetValue getFirstSelectedValue() const; + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OListBoxModel ); + +// XServiceInfo + IMPLEMENTATION_NAME(OListBoxModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + +// UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OListBoxModel, OBoundControlModel); + 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(); + +// OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + 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); + +protected: + // XMultiPropertySet + virtual void SAL_CALL setPropertyValues(const ::com::sun::star::uno::Sequence< ::rtl::OUString >& PropertyNames, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Values) throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // 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); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + virtual void describeAggregateProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps + ) const; + + // XEventListener + virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException); + + // OPropertyChangeListener + virtual void _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& _rEvt ) throw ( ::com::sun::star::uno::RuntimeException ); + + // prevent method hiding + using OBoundControlModel::getFastPropertyValue; + using OBoundControlModel::setPropertyValues; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + + virtual ::com::sun::star::uno::Any + getCurrentFormComponentValue() const; + + // OEntryListHelper overriables + virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ); + virtual void connectedExternalListSource( ); + virtual void disconnectedExternalListSource( ); + virtual void refreshInternalEntryList(); + +protected: + DECLARE_XCLONEABLE(); + +private: + void loadData( bool _bForce ); + + /** refreshes the list boxes list data + @precond we don't actually have an external list source + */ + void impl_refreshDbEntryList( bool _bForce ); + + ValueList impl_getValues() const; + + bool impl_hasBoundComponent() const { return m_nBoundColumnType != ::com::sun::star::sdbc::DataType::SQLNULL; } +}; + +//================================================================== +//= OListBoxControl +//================================================================== +typedef ::cppu::ImplHelper4 < ::com::sun::star::awt::XFocusListener + , ::com::sun::star::awt::XItemListener + , ::com::sun::star::awt::XListBox + , ::com::sun::star::form::XChangeBroadcaster + > OListBoxControl_BASE; + +class ChangeListeners; + +class OListBoxControl :public OBoundControl + ,public OListBoxControl_BASE + ,public IEventProcessor +{ +private: + ::cppu::OInterfaceContainerHelper m_aChangeListeners; + ::cppu::OInterfaceContainerHelper m_aItemListeners; + + ::com::sun::star::uno::Any m_aCurrentSelection; + Timer m_aChangeTimer; + + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox > + m_xAggregateListBox; + + ::rtl::Reference< ::comphelper::AsyncEventNotifier > + m_pItemBroadcaster; + +protected: + // UNO Anbindung + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OListBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + virtual ~OListBoxControl(); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OListBoxControl, OBoundControl); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + +// XServiceInfo + IMPLEMENTATION_NAME(OListBoxControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + +// XChangeBroadcaster + virtual void SAL_CALL addChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + +// XFocusListener + virtual void SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException); + +// XItemListener + virtual void SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& _rEvent) 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(); + +// XListBox + virtual void SAL_CALL addItemListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XItemListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeItemListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XItemListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addActionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeActionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addItem( const ::rtl::OUString& aItem, ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addItems( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aItems, ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getItemCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getItem( ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getItems( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getSelectedItemPos( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int16 > SAL_CALL getSelectedItemsPos( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getSelectedItem( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSelectedItems( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectItemPos( ::sal_Int16 nPos, ::sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectItemsPos( const ::com::sun::star::uno::Sequence< ::sal_Int16 >& aPositions, ::sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectItem( const ::rtl::OUString& aItem, ::sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isMutipleMode( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setMultipleMode( ::sal_Bool bMulti ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getDropDownLineCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDropDownLineCount( ::sal_Int16 nLines ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL makeVisible( ::sal_Int16 nEntry ) throw (::com::sun::star::uno::RuntimeException); + +protected: + // IEventProcessor + virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ); + +private: + DECL_LINK( OnTimeout, void* ); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_LISTBOX_HXX_ + diff --git a/forms/source/component/Numeric.cxx b/forms/source/component/Numeric.cxx new file mode 100644 index 000000000000..0d60fd2f62fb --- /dev/null +++ b/forms/source/component/Numeric.cxx @@ -0,0 +1,222 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Numeric.hxx" +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//================================================================== +// ONumericControl +//================================================================== + +//------------------------------------------------------------------ +ONumericControl::ONumericControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_NUMERICFIELD) +{ +} + +//------------------------------------------------------------------------------ +StringSequence ONumericControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_NUMERICFIELD; + return aSupported; +} + + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL ONumericControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new ONumericControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> ONumericControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//================================================================== +// ONumericModel +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL ONumericModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new ONumericModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> ONumericModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + +//------------------------------------------------------------------ +DBG_NAME( ONumericModel ) +//------------------------------------------------------------------ +ONumericModel::ONumericModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_NUMERICFIELD, FRM_SUN_CONTROL_NUMERICFIELD, sal_True, sal_True ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( ONumericModel, NULL ); + + m_nClassId = FormComponentType::NUMERICFIELD; + initValueProperty( PROPERTY_VALUE, PROPERTY_ID_VALUE ); +} + +//------------------------------------------------------------------ +ONumericModel::ONumericModel( const ONumericModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( ONumericModel, NULL ); +} + +//------------------------------------------------------------------ +ONumericModel::~ONumericModel() +{ + DBG_DTOR( ONumericModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( ONumericModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence ONumericModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_NUMERICFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_NUMERICFIELD; + *pStoreTo++ = BINDABLE_DATABASE_NUMERIC_FIELD; + + return aSupported; +} + +//------------------------------------------------------------------------------ +void ONumericModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 2, OEditBaseModel ) + DECL_PROP3(DEFAULT_VALUE, double, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ONumericModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_NUMERICFIELD; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +sal_Bool ONumericModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( !compare( aControlValue, m_aSaveValue ) ) + { + if ( !aControlValue.hasValue() ) + m_xColumnUpdate->updateNull(); + else + { + try + { + m_xColumnUpdate->updateDouble( getDouble( aControlValue ) ); + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +Any ONumericModel::translateDbColumnToControlValue() +{ + m_aSaveValue <<= (double)m_xColumn->getDouble(); + if ( m_xColumn->wasNull() ) + m_aSaveValue.clear(); + + return m_aSaveValue; +} + +//------------------------------------------------------------------------------ +Any ONumericModel::getDefaultForReset() const +{ + Any aValue; + if (m_aDefault.getValueType().getTypeClass() == TypeClass_DOUBLE) + aValue = m_aDefault; + + return aValue; +} + +//------------------------------------------------------------------------------ +void ONumericModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Numeric.hxx b/forms/source/component/Numeric.hxx new file mode 100644 index 000000000000..1159ad98c3f0 --- /dev/null +++ b/forms/source/component/Numeric.hxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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_NUMERIC_HXX_ +#define _FORMS_NUMERIC_HXX_ + +#include "EditBase.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= ONumericModel +//================================================================== +class ONumericModel + :public OEditBaseModel +{ +private: + ::com::sun::star::uno::Any m_aSaveValue; +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( ONumericModel ); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(ONumericModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + +protected: + DECLARE_XCLONEABLE(); +}; + +//================================================================== +//= ONumericControl +//================================================================== +class ONumericControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + ONumericControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(ONumericControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_NUMERIC_HXX_ + diff --git a/forms/source/component/Pattern.cxx b/forms/source/component/Pattern.cxx new file mode 100644 index 000000000000..e7b6c695d0cf --- /dev/null +++ b/forms/source/component/Pattern.cxx @@ -0,0 +1,262 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "Pattern.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//......................................................................... +namespace frm +{ +//......................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::beans::Property; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::sdbc::XRowSet; + using ::com::sun::star::uno::UNO_QUERY; + /** === end UNO using === **/ + namespace FormComponentType = ::com::sun::star::form::FormComponentType; + +//================================================================== +// OPatternControl +//================================================================== +//------------------------------------------------------------------ +OPatternControl::OPatternControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_PATTERNFIELD) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OPatternControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OPatternControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OPatternControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//------------------------------------------------------------------------------ +StringSequence OPatternControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_PATTERNFIELD; + return aSupported; +} + +//================================================================== +// OPatternModel +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OPatternModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OPatternModel(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OPatternModel::_getTypes() +{ + return OEditBaseModel::_getTypes(); +} + +//------------------------------------------------------------------ +DBG_NAME( OPatternModel ) +//------------------------------------------------------------------ +OPatternModel::OPatternModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_PATTERNFIELD, FRM_SUN_CONTROL_PATTERNFIELD, sal_False, sal_False ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( OPatternModel, NULL ); + + m_nClassId = FormComponentType::PATTERNFIELD; + initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT ); +} + +//------------------------------------------------------------------ +OPatternModel::OPatternModel( const OPatternModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) +{ + DBG_CTOR( OPatternModel, NULL ); +} + +//------------------------------------------------------------------ +OPatternModel::~OPatternModel() +{ + DBG_DTOR( OPatternModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OPatternModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OPatternModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 2); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-2] = FRM_SUN_COMPONENT_DATABASE_PATTERNFIELD; + pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_PATTERNFIELD; + return aSupported; +} + + +//------------------------------------------------------------------------------ +void OPatternModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 4, OEditBaseModel ) + DECL_PROP2(DEFAULT_TEXT, ::rtl::OUString, BOUND, MAYBEDEFAULT); + DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP2(FILTERPROPOSAL, sal_Bool, BOUND, MAYBEDEFAULT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OPatternModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_PATTERNFIELD; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +sal_Bool OPatternModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + + if ( aNewValue != m_aLastKnownValue ) + { + ::rtl::OUString sNewValue; + aNewValue >>= sNewValue; + + if ( !aNewValue.hasValue() + || ( !sNewValue.getLength() // an empty string + && m_bEmptyIsNull // which should be interpreted as NULL + ) + ) + { + m_xColumnUpdate->updateNull(); + } + else + { + OSL_ENSURE( m_pFormattedValue.get(), "OPatternModel::commitControlValueToDbColumn: no value helper!" ); + if ( !m_pFormattedValue.get() ) + return sal_False; + + if ( !m_pFormattedValue->setFormattedValue( sNewValue ) ) + return sal_False; + } + + m_aLastKnownValue = aNewValue; + } + + return sal_True; +} + +//------------------------------------------------------------------------------ +void OPatternModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + OEditBaseModel::onConnectedDbColumn( _rxForm ); + + Reference< XPropertySet > xField( getField() ); + if ( !xField.is() ) + return; + + m_pFormattedValue.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) ); +} + +//------------------------------------------------------------------------------ +void OPatternModel::onDisconnectedDbColumn() +{ + OEditBaseModel::onDisconnectedDbColumn(); + m_pFormattedValue.reset(); +} + +// XPropertyChangeListener +//------------------------------------------------------------------------------ +Any OPatternModel::translateDbColumnToControlValue() +{ + OSL_PRECOND( m_pFormattedValue.get(), "OPatternModel::translateDbColumnToControlValue: no value helper!" ); + + if ( m_pFormattedValue.get() ) + { + ::rtl::OUString sValue( m_pFormattedValue->getFormattedValue() ); + if ( !sValue.getLength() + && m_pFormattedValue->getColumn().is() + && m_pFormattedValue->getColumn()->wasNull() + ) + { + m_aLastKnownValue.clear(); + } + else + { + m_aLastKnownValue <<= sValue; + } + } + else + m_aLastKnownValue.clear(); + + return m_aLastKnownValue.hasValue() ? m_aLastKnownValue : makeAny( ::rtl::OUString() ); + // (m_aLastKnownValue is alllowed to be VOID, the control value isn't) +} + +// XReset +//------------------------------------------------------------------------------ +Any OPatternModel::getDefaultForReset() const +{ + return makeAny( m_aDefaultText ); +} + +//------------------------------------------------------------------------------ +void OPatternModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aLastKnownValue.clear(); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Pattern.hxx b/forms/source/component/Pattern.hxx new file mode 100644 index 000000000000..9a96a39820ff --- /dev/null +++ b/forms/source/component/Pattern.hxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * 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_PATTERN_HXX_ +#define _FORMS_PATTERN_HXX_ + +#include "EditBase.hxx" + +#include <connectivity/formattedcolumnvalue.hxx> + +#include <memory> + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= OPatternModel +//================================================================== +class OPatternModel + :public OEditBaseModel +{ +private: + ::com::sun::star::uno::Any m_aLastKnownValue; + ::std::auto_ptr< ::dbtools::FormattedColumnValue > + m_pFormattedValue; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OPatternModel ); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OPatternModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // ::com::sun::star::io::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + virtual void onDisconnectedDbColumn(); + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + +protected: + DECLARE_XCLONEABLE(); +}; + +//================================================================== +//= OPatternControl +//================================================================== +class OPatternControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OPatternControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OPatternControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_PATTERN_HXX_ + diff --git a/forms/source/component/RadioButton.cxx b/forms/source/component/RadioButton.cxx new file mode 100644 index 000000000000..c4a1216ad76c --- /dev/null +++ b/forms/source/component/RadioButton.cxx @@ -0,0 +1,411 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "RadioButton.hxx" +#include "property.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "services.hxx" +#include <tools/debug.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/basicio.hxx> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> + +//......................................................................... +namespace frm +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::form::binding; + +//================================================================== +//------------------------------------------------------------------------------ +InterfaceRef SAL_CALL ORadioButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new ORadioButtonControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL ORadioButtonControl::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_RADIOBUTTON; + return aSupported; +} + + +//------------------------------------------------------------------ +ORadioButtonControl::ORadioButtonControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_RADIOBUTTON) +{ +} + +//------------------------------------------------------------------ +void SAL_CALL ORadioButtonControl::createPeer(const Reference<starawt::XToolkit>& _rxToolkit, const Reference<starawt::XWindowPeer>& _rxParent) throw (RuntimeException) +{ + OBoundControl::createPeer(_rxToolkit, _rxParent); + + // switch off the auto-toggle, we do this ourself .... + // (formerly this switch-off was done in the toolkit - but the correct place is here ...) +// Reference< XVclWindowPeer > xVclWindowPeer( getPeer(), UNO_QUERY ); +// if (xVclWindowPeer.is()) +// xVclWindowPeer->setProperty(::rtl::OUString::createFromAscii("AutoToggle"), ::cppu::bool2any(sal_False)); + // new order: do _not_ switch off the auto toggle because: + // * today, it is not necessary anymore to handle the toggling ourself (everything works fine without it) + // * without auto toggle, the AccessibleEvents as fired by the radio buttons are + // a. newly checked button: "unchecked"->"checked" + // b. previously checked button: "checked"->"unchecked" + // This is deadly for AT-tools, which then get the "unchecked" event _immediately_ after the "checked" event, + // and only read the latter. This makes radio buttons pretty unusable in form documents. + // So we switched AutoToggle _on_, again, because then VCL can handle the notifications, and will send + // them in the proper order. +} + +//================================================================== +InterfaceRef SAL_CALL ORadioButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException) +{ + return *(new ORadioButtonModel(_rxFactory)); +} + +//------------------------------------------------------------------ +DBG_NAME( ORadioButtonModel ) +//------------------------------------------------------------------ +ORadioButtonModel::ORadioButtonModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OReferenceValueComponent( _rxFactory, VCL_CONTROLMODEL_RADIOBUTTON, FRM_SUN_CONTROL_RADIOBUTTON,sal_True ) + // use the old control name for compytibility reasons +{ + DBG_CTOR( ORadioButtonModel, NULL ); + + m_nClassId = FormComponentType::RADIOBUTTON; + m_aLabelServiceName = FRM_SUN_COMPONENT_GROUPBOX; + initValueProperty( PROPERTY_STATE, PROPERTY_ID_STATE ); +} + +//------------------------------------------------------------------ +ORadioButtonModel::ORadioButtonModel( const ORadioButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OReferenceValueComponent( _pOriginal, _rxFactory ) +{ + DBG_CTOR( ORadioButtonModel, NULL ); +} + +//------------------------------------------------------------------------------ +ORadioButtonModel::~ORadioButtonModel() +{ + DBG_DTOR( ORadioButtonModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( ORadioButtonModel ) + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL ORadioButtonModel::getSupportedServiceNames() throw(RuntimeException) +{ + StringSequence aSupported = OReferenceValueComponent::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_RADIOBUTTON; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_RADIOBUTTON; + *pStoreTo++ = BINDABLE_DATABASE_RADIO_BUTTON; + + return aSupported; +} + +//------------------------------------------------------------------------------ +void ORadioButtonModel::SetSiblingPropsTo(const ::rtl::OUString& rPropName, const Any& rValue) +{ + // mein Name + ::rtl::OUString sMyName(m_aName); + + // meine Siblings durchiterieren + Reference<XIndexAccess> xIndexAccess(getParent(), UNO_QUERY); + if (xIndexAccess.is()) + { + Reference<XPropertySet> xMyProps; + query_interface(static_cast<XWeak*>(this), xMyProps); + ::rtl::OUString sCurrentName; + for (sal_Int32 i=0; i<xIndexAccess->getCount(); ++i) + { + Reference<XPropertySet> xSiblingProperties(*(InterfaceRef*)xIndexAccess->getByIndex(i).getValue(), UNO_QUERY); + if (!xSiblingProperties.is()) + continue; + if (xMyProps == xSiblingProperties) + continue; // mich selber nicht umsetzen + + // nur wenn es ein Radio-Button ist + if (!hasProperty(PROPERTY_CLASSID, xSiblingProperties)) + continue; + sal_Int16 nType = 0; + xSiblingProperties->getPropertyValue(PROPERTY_CLASSID) >>= nType; + if (nType != FormComponentType::RADIOBUTTON) + continue; + + // das 'zur selben Gruppe gehoeren' wird am Namen festgemacht + xSiblingProperties->getPropertyValue(PROPERTY_NAME) >>= sCurrentName; + if (sCurrentName == sMyName) + xSiblingProperties->setPropertyValue(rPropName, rValue); + } + } +} + +//------------------------------------------------------------------------------ +void ORadioButtonModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw (Exception) +{ + OReferenceValueComponent::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + + // if the label control changed ... + if (nHandle == PROPERTY_ID_CONTROLLABEL) + { // ... forward this to our siblings + SetSiblingPropsTo(PROPERTY_CONTROLLABEL, rValue); + } + + // wenn sich die ControlSource-Eigenschaft geaendert hat ... + if (nHandle == PROPERTY_ID_CONTROLSOURCE) + { // ... muss ich allen meinen Siblings, die in der selben RadioButton-Gruppe sind wie ich, auch die + // neue ControlSource mitgeben + SetSiblingPropsTo(PROPERTY_CONTROLSOURCE, rValue); + } + + // die andere Richtung : wenn sich mein Name aendert ... + if (nHandle == PROPERTY_ID_NAME) + { + // ... muss ich testen, ob ich Siblings mit dem selben Namen habe, damit ich deren ControlSource uebernehmen kann + Reference<XIndexAccess> xIndexAccess(getParent(), UNO_QUERY); + if (xIndexAccess.is()) + { + ::rtl::OUString sName; + ::rtl::OUString sControlSource; + + Reference<XPropertySet> xMyProps; + query_interface(static_cast<XWeak*>(this), xMyProps); + for (sal_Int32 i=0; i<xIndexAccess->getCount(); ++i) + { + Reference<XPropertySet> xSiblingProperties(*(InterfaceRef*)xIndexAccess->getByIndex(i).getValue(), UNO_QUERY); + if (!xSiblingProperties.is()) + continue; + + if (xMyProps == xSiblingProperties) + // nur wenn ich nicht mich selber gefunden habe + continue; + + sal_Int16 nType = 0; + xSiblingProperties->getPropertyValue(PROPERTY_CLASSID) >>= nType; + if (nType != FormComponentType::RADIOBUTTON) + // nur Radio-Buttons + continue; + + xSiblingProperties->getPropertyValue(PROPERTY_NAME) >>= sName; + // Control, das zur gleichen Gruppe gehoert ? + if (rValue == sName) + { + setPropertyValue(PROPERTY_CONTROLSOURCE, xSiblingProperties->getPropertyValue(PROPERTY_CONTROLSOURCE)); + break; + } + } + } + } + + if (nHandle == PROPERTY_ID_DEFAULT_STATE) + { + sal_Int16 nValue; + rValue >>= nValue; + if (1 == nValue) + { // bei allen Radios der selben Gruppe das 'default checked' ruecksetzen, denn wie schon der highlander wusste : + // es kann nur einen geben. + Any aZero; + nValue = 0; + aZero <<= nValue; + SetSiblingPropsTo(PROPERTY_DEFAULT_STATE, aZero); + } + } +} + +//------------------------------------------------------------------------------ +void ORadioButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 1, OReferenceValueComponent ) + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ORadioButtonModel::getServiceName() throw(RuntimeException) +{ + return FRM_COMPONENT_RADIOBUTTON; // old (non-sun) name for compatibility ! +} + +//------------------------------------------------------------------------------ +void SAL_CALL ORadioButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream) + throw(IOException, RuntimeException) +{ + OReferenceValueComponent::write(_rxOutStream); + + // Version + _rxOutStream->writeShort(0x0003); + + // Properties + _rxOutStream << getReferenceValue(); + _rxOutStream << (sal_Int16)getDefaultChecked(); + writeHelpTextCompatibly(_rxOutStream); + + // from version 0x0003 : common properties + writeCommonProperties(_rxOutStream); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ORadioButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException) +{ + OReferenceValueComponent::read(_rxInStream); + ::osl::MutexGuard aGuard(m_aMutex); + + // Version + UINT16 nVersion = _rxInStream->readShort(); + + ::rtl::OUString sReferenceValue; + sal_Int16 nDefaultChecked( 0 ); + switch (nVersion) + { + case 0x0001 : + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + break; + case 0x0002 : + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + readHelpTextCompatibly(_rxInStream); + break; + case 0x0003 : + _rxInStream >> sReferenceValue; + _rxInStream >> nDefaultChecked; + readHelpTextCompatibly(_rxInStream); + readCommonProperties(_rxInStream); + break; + default : + DBG_ERROR("ORadioButtonModel::read : unknown version !"); + defaultCommonProperties(); + break; + } + + setReferenceValue( sReferenceValue ); + setDefaultChecked( (ToggleState)nDefaultChecked ); + + // Nach dem Lesen die Defaultwerte anzeigen + if ( getControlSource().getLength() ) + // (not if we don't have a control source - the "State" property acts like it is persistent, then + resetNoBroadcast(); +} + +//------------------------------------------------------------------------------ +void ORadioButtonModel::_propertyChanged(const PropertyChangeEvent& _rEvent) throw(RuntimeException) +{ + if ( _rEvent.PropertyName.equals( PROPERTY_STATE ) ) + { + if ( _rEvent.NewValue == (sal_Int16)1 ) + { + // wenn sich mein Status auf 'checked' geaendert hat, muss ich alle meine Siblings, die in der selben Gruppe + // sind wie ich, entsprechend zuruecksetzen + Any aZero; + aZero <<= (sal_Int16)0; + SetSiblingPropsTo( PROPERTY_STATE, aZero ); + } + } + + OReferenceValueComponent::_propertyChanged( _rEvent ); +} + +//------------------------------------------------------------------------------ +Any ORadioButtonModel::translateDbColumnToControlValue() +{ + return makeAny( (sal_Int16) + ( ( m_xColumn->getString() == getReferenceValue() ) ? STATE_CHECK : STATE_NOCHECK ) + ); +} + +//------------------------------------------------------------------------------ +Any ORadioButtonModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + Any aControlValue = OReferenceValueComponent::translateExternalValueToControlValue( _rExternalValue ); + sal_Int16 nState = STATE_NOCHECK; + if ( ( aControlValue >>= nState ) && ( nState == STATE_DONTKNOW ) ) + // radio buttons do not have the DONTKNOW state + aControlValue <<= (sal_Int16)STATE_NOCHECK; + return aControlValue; +} + +//----------------------------------------------------------------------------- +sal_Bool ORadioButtonModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Reference< XPropertySet > xField( getField() ); + OSL_PRECOND( xField.is(), "ORadioButtonModel::commitControlValueToDbColumn: not bound!" ); + if ( xField.is() ) + { + try + { + sal_Int16 nValue = 0; + m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) >>= nValue; + if ( nValue == 1 ) + xField->setPropertyValue( PROPERTY_VALUE, makeAny( getReferenceValue() ) ); + } + catch(Exception&) + { + DBG_ERROR("ORadioButtonModel::commitControlValueToDbColumn: could not commit !"); + } + } + return sal_True; +} + +//......................................................................... +} +//......................................................................... + diff --git a/forms/source/component/RadioButton.hxx b/forms/source/component/RadioButton.hxx new file mode 100644 index 000000000000..3f122fe7b27c --- /dev/null +++ b/forms/source/component/RadioButton.hxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * 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_RADIOBUTTON_HXX_ +#define _FORMS_RADIOBUTTON_HXX_ + +#include "refvaluecomponent.hxx" + +//......................................................................... +namespace frm +{ + +//================================================================== +// ORadioButtonModel +//================================================================== +class ORadioButtonModel :public OReferenceValueComponent +{ +public: + DECLARE_DEFAULT_LEAF_XTOR( ORadioButtonModel ); + + // XServiceInfo + IMPLEMENTATION_NAME(ORadioButtonModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // OPropertySetHelper + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + + // 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); + + // OPropertyChangeListener + virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + +protected: + void SetSiblingPropsTo(const ::rtl::OUString& rPropName, const ::com::sun::star::uno::Any& rValue); + + DECLARE_XCLONEABLE( ); + +private: + /** sets the given value as new State at the aggregate + @precond + our mutex is aquired exactly once + */ + void setNewAggregateState( const ::com::sun::star::uno::Any& _rValue ); +}; + +//================================================================== +// ORadioButtonControl +//================================================================== +class ORadioButtonControl: public OBoundControl +{ +public: + ORadioButtonControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + + // XServiceInfo + IMPLEMENTATION_NAME(ORadioButtonControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + +protected: + // XControl + 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); +}; + +//......................................................................... +} +//......................................................................... + +#endif // _FORMS_RADIOBUTTON_HXX_ + diff --git a/forms/source/component/Time.cxx b/forms/source/component/Time.cxx new file mode 100644 index 000000000000..49b07adf84e4 --- /dev/null +++ b/forms/source/component/Time.cxx @@ -0,0 +1,365 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "Time.hxx" +#include <tools/debug.hxx> +#include <tools/time.hxx> +#include <connectivity/dbconversion.hxx> +#include <com/sun/star/sdbc/DataType.hpp> + +using namespace dbtools; + +//......................................................................... +namespace frm +{ +//......................................................................... + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; + +//================================================================== +//= +//================================================================== + +//================================================================== +//= OTimeControl +//================================================================== +//------------------------------------------------------------------ +OTimeControl::OTimeControl(const Reference<XMultiServiceFactory>& _rxFactory) + :OBoundControl(_rxFactory, VCL_CONTROL_TIMEFIELD) +{ +} + +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OTimeControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OTimeControl(_rxFactory)); +} + +//------------------------------------------------------------------------------ +Sequence<Type> OTimeControl::_getTypes() +{ + return OBoundControl::_getTypes(); +} + +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OTimeControl::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControl::getSupportedServiceNames(); + aSupported.realloc(aSupported.getLength() + 1); + + ::rtl::OUString*pArray = aSupported.getArray(); + pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_TIMEFIELD; + return aSupported; +} + +//================================================================== +//= OTimeModel +//================================================================== +//------------------------------------------------------------------ +InterfaceRef SAL_CALL OTimeModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) +{ + return *(new OTimeModel(_rxFactory)); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +StringSequence SAL_CALL OTimeModel::getSupportedServiceNames() throw() +{ + StringSequence aSupported = OBoundControlModel::getSupportedServiceNames(); + + sal_Int32 nOldLen = aSupported.getLength(); + aSupported.realloc( nOldLen + 8 ); + ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen; + + *pStoreTo++ = BINDABLE_CONTROL_MODEL; + *pStoreTo++ = DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_CONTROL_MODEL; + + *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL; + *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL; + + *pStoreTo++ = FRM_SUN_COMPONENT_TIMEFIELD; + *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_TIMEFIELD; + *pStoreTo++ = BINDABLE_DATABASE_TIME_FIELD; + + return aSupported; +} + +//------------------------------------------------------------------------------ +Sequence<Type> OTimeModel::_getTypes() +{ + return OBoundControlModel::_getTypes(); +} + +//------------------------------------------------------------------ +DBG_NAME( OTimeModel ) +//------------------------------------------------------------------ +OTimeModel::OTimeModel(const Reference<XMultiServiceFactory>& _rxFactory) + :OEditBaseModel( _rxFactory, VCL_CONTROLMODEL_TIMEFIELD, FRM_SUN_CONTROL_TIMEFIELD, sal_True, sal_True ) + // use the old control name for compytibility reasons + ,OLimitedFormats(_rxFactory, FormComponentType::TIMEFIELD) +{ + DBG_CTOR( OTimeModel, NULL ); + + m_nClassId = FormComponentType::TIMEFIELD; + initValueProperty( PROPERTY_TIME, PROPERTY_ID_TIME ); + + setAggregateSet(m_xAggregateFastSet, getOriginalHandle(PROPERTY_ID_TIMEFORMAT)); +} + +//------------------------------------------------------------------------------ +OTimeModel::OTimeModel( const OTimeModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OEditBaseModel( _pOriginal, _rxFactory ) + ,OLimitedFormats( _rxFactory, FormComponentType::TIMEFIELD ) +{ + DBG_CTOR( OTimeModel, NULL ); + + setAggregateSet( m_xAggregateFastSet, getOriginalHandle( PROPERTY_ID_TIMEFORMAT ) ); +} + +//------------------------------------------------------------------------------ +OTimeModel::~OTimeModel( ) +{ + setAggregateSet(Reference< XFastPropertySet >(), -1); + DBG_DTOR( OTimeModel, NULL ); +} + +// XCloneable +//------------------------------------------------------------------------------ +IMPLEMENT_DEFAULT_CLONING( OTimeModel ) + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OTimeModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) +{ + return FRM_COMPONENT_TIMEFIELD; // old (non-sun) name for compatibility ! +} + +// XPropertySet +//------------------------------------------------------------------------------ +void OTimeModel::describeFixedProperties( Sequence< Property >& _rProps ) const +{ + BEGIN_DESCRIBE_PROPERTIES( 4, OEditBaseModel ) + DECL_PROP3(DEFAULT_TIME, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID); + DECL_PROP1(TABINDEX, sal_Int16, BOUND); + DECL_PROP1(FORMATKEY, sal_Int32, TRANSIENT); + DECL_IFACE_PROP2(FORMATSSUPPLIER, XNumberFormatsSupplier, READONLY, TRANSIENT); + END_DESCRIBE_PROPERTIES(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OTimeModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle ) const +{ + switch (_nHandle) + { + case PROPERTY_ID_FORMATKEY: + getFormatKeyPropertyValue(_rValue); + break; + case PROPERTY_ID_FORMATSSUPPLIER: + _rValue <<= getFormatsSupplier(); + break; + default: + OEditBaseModel::getFastPropertyValue(_rValue, _nHandle); + break; + } +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OTimeModel::convertFastPropertyValue(Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue ) throw(IllegalArgumentException) +{ + if (PROPERTY_ID_FORMATKEY == _nHandle) + return convertFormatKeyPropertyValue(_rConvertedValue, _rOldValue, _rValue); + else + return OEditBaseModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OTimeModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw ( ::com::sun::star::uno::Exception) +{ + if (PROPERTY_ID_FORMATKEY == _nHandle) + setFormatKeyPropertyValue(_rValue); + else + OEditBaseModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); +} + +// XLoadListener +//------------------------------------------------------------------------------ +void OTimeModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm ) +{ + OBoundControlModel::onConnectedDbColumn( _rxForm ); + Reference<XPropertySet> xField = getField(); + if (xField.is()) + { + m_bDateTimeField = sal_False; + try + { + sal_Int32 nFieldType = 0; + xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nFieldType; + m_bDateTimeField = (nFieldType == DataType::TIMESTAMP); + } + catch(Exception&) + { + } + } +} + +//------------------------------------------------------------------------------ +sal_Bool OTimeModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) +{ + Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) ); + if ( !compare( aControlValue, m_aSaveValue ) ) + { + if ( !aControlValue.hasValue() ) + m_xColumnUpdate->updateNull(); + else + { + try + { + util::Time aTime; + if ( !( aControlValue >>= aTime ) ) + { + sal_Int32 nAsInt(0); + aControlValue >>= nAsInt; + aTime = DBTypeConversion::toTime(nAsInt); + } + + if (!m_bDateTimeField) + m_xColumnUpdate->updateTime(aTime); + else + { + util::DateTime aDateTime = m_xColumn->getTimestamp(); + aDateTime.HundredthSeconds = aTime.HundredthSeconds; + aDateTime.Seconds = aTime.Seconds; + aDateTime.Minutes = aTime.Minutes; + aDateTime.Hours = aTime.Hours; + m_xColumnUpdate->updateTimestamp(aDateTime); + } + } + catch(Exception&) + { + return sal_False; + } + } + m_aSaveValue = aControlValue; + } + return sal_True; +} + +//------------------------------------------------------------------------------ +void OTimeModel::impl_translateControlValueToUNOTime( Any& _rUNOValue ) const +{ + _rUNOValue = getControlValue(); + if ( _rUNOValue.hasValue() ) + { + sal_Int32 nTime = 0; + OSL_VERIFY( _rUNOValue >>= nTime ); + if ( nTime == ::Time( 99, 99, 99 ).GetTime() ) + // "invalid time" in VCL is different from "invalid time" in UNO + _rUNOValue.clear(); + else + _rUNOValue <<= DBTypeConversion::toTime( nTime ); + } +} + +//------------------------------------------------------------------------------ +Any OTimeModel::translateControlValueToExternalValue( ) const +{ + Any aExternalValue; + impl_translateControlValueToUNOTime( aExternalValue ); + return aExternalValue; +} + +//------------------------------------------------------------------------------ +Any OTimeModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const +{ + Any aControlValue; + if ( _rExternalValue.hasValue() ) + { + util::Time aTime; + OSL_VERIFY( _rExternalValue >>= aTime ); + aControlValue <<= DBTypeConversion::toINT32( aTime ); + } + return aControlValue; +} + +//------------------------------------------------------------------------------ +Any OTimeModel::translateControlValueToValidatableValue( ) const +{ + Any aValidatableValue; + impl_translateControlValueToUNOTime( aValidatableValue ); + return aValidatableValue; +} + +//------------------------------------------------------------------------------ +Any OTimeModel::translateDbColumnToControlValue() +{ + util::Time aTime = m_xColumn->getTime(); + if ( m_xColumn->wasNull() ) + m_aSaveValue.clear(); + else + // the aggregated set expects an Int32 as value ... + m_aSaveValue <<= DBTypeConversion::toINT32( aTime ); + + return m_aSaveValue; +} + +//------------------------------------------------------------------------------ +Any OTimeModel::getDefaultForReset() const +{ + return m_aDefault; +} + +//------------------------------------------------------------------------------ +void OTimeModel::resetNoBroadcast() +{ + OEditBaseModel::resetNoBroadcast(); + m_aSaveValue.clear(); +} + +//------------------------------------------------------------------------------ +Sequence< Type > OTimeModel::getSupportedBindingTypes() +{ + return Sequence< Type >( &::getCppuType( static_cast< util::Time* >( NULL ) ), 1 ); +} + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/Time.hxx b/forms/source/component/Time.hxx new file mode 100644 index 000000000000..a9ac1b4adfd0 --- /dev/null +++ b/forms/source/component/Time.hxx @@ -0,0 +1,133 @@ +/************************************************************************* + * + * 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_TIME_HXX_ +#define _FORMS_TIME_HXX_ + +#include "EditBase.hxx" +#include "limitedformats.hxx" + +//......................................................................... +namespace frm +{ +//......................................................................... + +//================================================================== +//= OTimeModel +//================================================================== +class OTimeModel + :public OEditBaseModel + ,public OLimitedFormats +{ +private: + ::com::sun::star::uno::Any m_aSaveValue; + sal_Bool m_bDateTimeField; + +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + DECLARE_DEFAULT_LEAF_XTOR( OTimeModel ); + + // stario::XPersistObject + virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::beans::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); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OTimeModel); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OBoundControlModel::getFastPropertyValue; + +protected: + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + + virtual ::com::sun::star::uno::Any + translateControlValueToValidatableValue( ) const; + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + virtual void resetNoBroadcast(); + + virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ); + +protected: + DECLARE_XCLONEABLE(); + +private: + /** translates the control value (the VCL-internal integer representation of a date) into + a UNO-Date. + */ + void impl_translateControlValueToUNOTime( + ::com::sun::star::uno::Any& _rUNOValue ) const; +}; + +//================================================================== +//= OTimeControl +//================================================================== +class OTimeControl: public OBoundControl +{ +protected: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + +public: + OTimeControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory); + DECLARE_UNO3_AGG_DEFAULTS(OTimeControl, OBoundControl); + + // ::com::sun::star::lang::XServiceInfo + IMPLEMENTATION_NAME(OTimeControl); + virtual StringSequence SAL_CALL getSupportedServiceNames() throw(); +}; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // _FORMS_TIME_HXX_ + diff --git a/forms/source/component/cachedrowset.cxx b/forms/source/component/cachedrowset.cxx new file mode 100644 index 000000000000..2c9cd82e9fee --- /dev/null +++ b/forms/source/component/cachedrowset.cxx @@ -0,0 +1,202 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "cachedrowset.hxx" +#include "services.hxx" +#include "frm_strings.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::sdbc::SQLException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::sdb::XQueriesSupplier; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::sdbc::XResultSet; + using ::com::sun::star::sdbc::XStatement; + /** === end UNO using === **/ + namespace ResultSetType = ::com::sun::star::sdbc::ResultSetType; + + //==================================================================== + //= CachedRowSet_Data + //==================================================================== + struct CachedRowSet_Data + { + ::comphelper::ComponentContext aContext; + ::rtl::OUString sCommand; + sal_Bool bEscapeProcessing; + Reference< XConnection > xConnection; + + bool bStatementDirty; + + CachedRowSet_Data( const ::comphelper::ComponentContext& _rContext ) + :aContext( _rContext ) + ,sCommand() + ,bEscapeProcessing( sal_False ) + ,xConnection() + ,bStatementDirty( true ) + { + } + }; + + //==================================================================== + //= CachedRowSet + //==================================================================== + //-------------------------------------------------------------------- + CachedRowSet::CachedRowSet( const ::comphelper::ComponentContext& _rContext ) + :m_pData( new CachedRowSet_Data( _rContext ) ) + { + } + + //-------------------------------------------------------------------- + CachedRowSet::~CachedRowSet() + { + dispose(); + } + + //-------------------------------------------------------------------- + void CachedRowSet::setCommand( const ::rtl::OUString& _rCommand ) + { + if ( m_pData->sCommand == _rCommand ) + return; + + m_pData->sCommand = _rCommand; + m_pData->bStatementDirty = true; + } + + //-------------------------------------------------------------------- + void CachedRowSet::setCommandFromQuery( const ::rtl::OUString& _rQueryName ) + { + Reference< XQueriesSupplier > xSupplyQueries( m_pData->xConnection, UNO_QUERY_THROW ); + Reference< XNameAccess > xQueries ( xSupplyQueries->getQueries(), UNO_QUERY_THROW ); + Reference< XPropertySet > xQuery ( xQueries->getByName( _rQueryName ), UNO_QUERY_THROW ); + + sal_Bool bEscapeProcessing( sal_False ); + OSL_VERIFY( xQuery->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bEscapeProcessing ); + setEscapeProcessing( bEscapeProcessing ); + + ::rtl::OUString sCommand; + OSL_VERIFY( xQuery->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand ); + setCommand( sCommand ); + } + + //-------------------------------------------------------------------- + void CachedRowSet::setEscapeProcessing ( const sal_Bool _bEscapeProcessing ) + { + if ( m_pData->bEscapeProcessing == _bEscapeProcessing ) + return; + + m_pData->bEscapeProcessing = _bEscapeProcessing; + m_pData->bStatementDirty = true; + } + + //-------------------------------------------------------------------- + void CachedRowSet::setConnection( const Reference< XConnection >& _rxConnection ) + { + if ( m_pData->xConnection == _rxConnection ) + return; + + m_pData->xConnection = _rxConnection; + m_pData->bStatementDirty = true; + } + + //-------------------------------------------------------------------- + Reference< XResultSet > CachedRowSet::execute() + { + Reference< XResultSet > xResult; + try + { + OSL_PRECOND( m_pData->xConnection.is(), "CachedRowSet::execute: how am I expected to do this without a connection?" ); + if ( !m_pData->xConnection.is() ) + return xResult; + + Reference< XStatement > xStatement( m_pData->xConnection->createStatement(), UNO_SET_THROW ); + Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW ); + xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( m_pData->bEscapeProcessing ) ); + xStatementProps->setPropertyValue( PROPERTY_RESULTSET_TYPE, makeAny( ResultSetType::FORWARD_ONLY ) ); + + xResult.set( xStatement->executeQuery( m_pData->sCommand ), UNO_SET_THROW ); + m_pData->bStatementDirty = false; + } + catch( const SQLException& ) + { + throw; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return xResult; + } + + //-------------------------------------------------------------------- + bool CachedRowSet::isDirty() const + { + return m_pData->bStatementDirty; + } + + //-------------------------------------------------------------------- + void CachedRowSet::dispose() + { + try + { + m_pData.reset( new CachedRowSet_Data( m_pData->aContext ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/component/cachedrowset.hxx b/forms/source/component/cachedrowset.hxx new file mode 100644 index 000000000000..d2310bf8fc8c --- /dev/null +++ b/forms/source/component/cachedrowset.hxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * 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 CACHEDROWSET_HXX +#define CACHEDROWSET_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <unotools/sharedunocomponent.hxx> + +#include <memory> + +//........................................................................ +namespace frm +{ +//........................................................................ + + struct CachedRowSet_Data; + //==================================================================== + //= CachedRowSet + //==================================================================== + /** caches a result set obtained from a SQL statement + */ + class CachedRowSet + { + public: + CachedRowSet( const ::comphelper::ComponentContext& _rContext ); + ~CachedRowSet(); + + public: + /** executes the statement + + @return + the result set produced by the statement. The caller takes ownership of the + given object. + + @throws ::com::sun::star::sdbc::SQLException + if such an exception is thrown when executing the statement + */ + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > + execute(); + + /// determines whether the row set properties are dirty, i.e. have changed since the last call to execute + bool isDirty() const; + + /// disposes the instance and frees all associated resources + void dispose(); + + /** sets the command of a query as command to be executed + + A connection must have been set before. + + @throws Exception + */ + void setCommandFromQuery ( const ::rtl::OUString& _rQueryName ); + + void setCommand ( const ::rtl::OUString& _rCommand ); + void setEscapeProcessing ( const sal_Bool _bEscapeProcessing ); + void setConnection ( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection ); + + private: + ::std::auto_ptr< CachedRowSet_Data > m_pData; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // CACHEDROWSET_HXX diff --git a/forms/source/component/clickableimage.cxx b/forms/source/component/clickableimage.cxx new file mode 100644 index 000000000000..8deb10c2f170 --- /dev/null +++ b/forms/source/component/clickableimage.cxx @@ -0,0 +1,929 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "clickableimage.hxx" +#include "controlfeatureinterception.hxx" +#include "urltransformer.hxx" +#include "componenttools.hxx" +#include <com/sun/star/form/XSubmit.hpp> +#include <com/sun/star/awt/SystemPointer.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/awt/ActionEvent.hpp> +#include <com/sun/star/awt/XActionListener.hpp> +#include <tools/urlobj.hxx> +#include <tools/debug.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/objsh.hxx> +#include <vos/mutex.hxx> +#include "services.hxx" +#include <comphelper/container.hxx> +#include <comphelper/listenernotification.hxx> +#include <svtools/imageresourceaccess.hxx> +#define LOCAL_URL_PREFIX '#' + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::form::submission; + using ::com::sun::star::awt::MouseEvent; + using ::com::sun::star::task::XInteractionHandler; + + //================================================================== + // OClickableImageBaseControl + //================================================================== + //------------------------------------------------------------------------------ + Sequence<Type> OClickableImageBaseControl::_getTypes() + { + static Sequence<Type> aTypes; + if (!aTypes.getLength()) + aTypes = concatSequences(OControl::_getTypes(), OClickableImageBaseControl_BASE::getTypes()); + return aTypes; + } + + //------------------------------------------------------------------------------ + OClickableImageBaseControl::OClickableImageBaseControl(const Reference<XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _aService) + :OControl(_rxFactory, _aService) + ,m_pThread(NULL) + ,m_aSubmissionVetoListeners( m_aMutex ) + ,m_aApproveActionListeners( m_aMutex ) + ,m_aActionListeners( m_aMutex ) + { + m_pFeatureInterception.reset( new ControlFeatureInterception( _rxFactory ) ); + } + + //------------------------------------------------------------------------------ + OClickableImageBaseControl::~OClickableImageBaseControl() + { + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + } + + // UNO Anbindung + //------------------------------------------------------------------------------ + Any SAL_CALL OClickableImageBaseControl::queryAggregation(const Type& _rType) throw (RuntimeException) + { + Any aReturn = OControl::queryAggregation(_rType); + if (!aReturn.hasValue()) + aReturn = OClickableImageBaseControl_BASE::queryInterface(_rType); + return aReturn; + } + + // XApproveActionBroadcaster + //------------------------------------------------------------------------------ + void OClickableImageBaseControl::addApproveActionListener( + const Reference<XApproveActionListener>& l) throw( RuntimeException ) + { + m_aApproveActionListeners.addInterface(l); + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseControl::removeApproveActionListener( + const Reference<XApproveActionListener>& l) throw( RuntimeException ) + { + m_aApproveActionListeners.removeInterface(l); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) + { + m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) + { + m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor ); + } + + // OComponentHelper + //------------------------------------------------------------------------------ + void OClickableImageBaseControl::disposing() + { + EventObject aEvent( static_cast< XWeak* >( this ) ); + m_aApproveActionListeners.disposeAndClear( aEvent ); + m_aActionListeners.disposeAndClear( aEvent ); + m_aSubmissionVetoListeners.disposeAndClear( aEvent ); + m_pFeatureInterception->dispose(); + + { + ::osl::MutexGuard aGuard( m_aMutex ); + if( m_pThread ) + { + m_pThread->release(); + m_pThread = NULL; + } + } + + OControl::disposing(); + } + + //------------------------------------------------------------------------------ + OImageProducerThread_Impl* OClickableImageBaseControl::getImageProducerThread() + { + if ( !m_pThread ) + { + m_pThread = new OImageProducerThread_Impl( this ); + m_pThread->acquire(); + m_pThread->create(); + } + return m_pThread; + } + + //------------------------------------------------------------------------------ + bool OClickableImageBaseControl::approveAction( ) + { + sal_Bool bCancelled = sal_False; + EventObject aEvent( static_cast< XWeak* >( this ) ); + + ::cppu::OInterfaceIteratorHelper aIter( m_aApproveActionListeners ); + while( !bCancelled && aIter.hasMoreElements() ) + { + // Jede approveAction-Methode muss thread-safe sein!!! + if( !static_cast< XApproveActionListener* >( aIter.next() )->approveAction( aEvent ) ) + bCancelled = sal_True; + } + + return !bCancelled; + } + + //------------------------------------------------------------------------------ + // Diese Methode wird auch aus einem Thread gerufen und muss deshalb + // thread-safe sein. + void OClickableImageBaseControl::actionPerformed_Impl(sal_Bool bNotifyListener, const MouseEvent& rEvt) + { + if( bNotifyListener ) + { + if ( !approveAction() ) + return; + } + + // Ob der Rest des Codes Thread-Safe ist weiss man nicht genau. Deshalb + // wird das meiste bei gelocktem Solar-Mutex erledigen. + Reference<XPropertySet> xSet; + Reference< XInterface > xModelsParent; + FormButtonType eButtonType = FormButtonType_PUSH; + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Parent holen + Reference<XFormComponent> xComp(getModel(), UNO_QUERY); + if (!xComp.is()) + return; + + xModelsParent = xComp->getParent(); + if (!xModelsParent.is()) + return; + + // which button type? + xSet = xSet.query( xComp ); + if ( !xSet.is() ) + return; + xSet->getPropertyValue(PROPERTY_BUTTONTYPE) >>= eButtonType; + } + + switch (eButtonType) + { + case FormButtonType_RESET: + { + // reset-Methoden muessen thread-safe sein! + Reference<XReset> xReset(xModelsParent, UNO_QUERY); + if (!xReset.is()) + return; + + xReset->reset(); + } + break; + + case FormButtonType_SUBMIT: + { + // if some outer component can provide an interaction handler, use it + Reference< XInteractionHandler > xHandler( m_pFeatureInterception->queryDispatch( "private:/InteractionHandler" ), UNO_QUERY ); + try + { + implSubmit( rEvt, xHandler ); + } + catch( const Exception& ) + { + // ignore + } + } + break; + + case FormButtonType_URL: + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + Reference< XModel > xModel = getXModel(xModelsParent); + if (!xModel.is()) + return; + + /////////////////////////////////////////////////////////////////////// + // Jetzt URL ausfuehren + Reference< XController > xController = xModel->getCurrentController(); + if (!xController.is()) + return; + + Reference< XFrame > xFrame = xController->getFrame(); + if( !xFrame.is() ) + return; + + URL aURL; + aURL.Complete = + getString(xSet->getPropertyValue(PROPERTY_TARGET_URL)); + + if (aURL.Complete.getLength() && (LOCAL_URL_PREFIX == aURL.Complete.getStr()[0])) + { // the URL contains a local URL only. Since the URLTransformer does not handle this case correctly + // (it can't: it does not know the document URL), we have to take care for this ourself. + // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all + // URLs have to be absolute), but for compatibility reasons this is no option. + // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it + // could be "#mark" as well. + // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete + // solutiuon would be: + // * recognize URLs consisting of a mark only while _reading_ the document + // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to + // transform such mark-only URLs into correct absolute URLs + // * at the UI, show only the mark + // * !!!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems + // rather impossible !!! + // 89752 - 23.07.2001 - frank.schoenheit@sun.com + aURL.Mark = aURL.Complete; + aURL.Complete = xModel->getURL(); + aURL.Complete += aURL.Mark; + } + + sal_Bool bDispatchUrlInternal = sal_False; + xSet->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL) >>= bDispatchUrlInternal; + if ( bDispatchUrlInternal ) + { + m_pFeatureInterception->getTransformer().parseSmartWithAsciiProtocol( aURL, INET_FILE_SCHEME ); + + ::rtl::OUString aTargetFrame; + xSet->getPropertyValue(PROPERTY_TARGET_FRAME) >>= aTargetFrame; + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch( aURL, aTargetFrame, + FrameSearchFlag::SELF | FrameSearchFlag::PARENT | + FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE ); + + Sequence<PropertyValue> aArgs(1); + PropertyValue& rProp = aArgs.getArray()[0]; + rProp.Name = ::rtl::OUString::createFromAscii("Referer"); + rProp.Value <<= xModel->getURL(); + + if (xDisp.is()) + xDisp->dispatch( aURL, aArgs ); + } + else + { + URL aHyperLink = m_pFeatureInterception->getTransformer().getStrictURLFromAscii( ".uno:OpenHyperlink" ); + + Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aHyperLink, ::rtl::OUString() , 0); + + if ( xDisp.is() ) + { + Sequence<PropertyValue> aProps(3); + aProps[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL")); + aProps[0].Value <<= aURL.Complete; + + aProps[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FrameName")); + aProps[1].Value = xSet->getPropertyValue(PROPERTY_TARGET_FRAME); + + aProps[2].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer")); + aProps[2].Value <<= xModel->getURL(); + + xDisp->dispatch( aHyperLink, aProps ); + } + } + } break; + default: + { + // notify the action listeners for a push button + ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand); + m_aActionListeners.notifyEach( &XActionListener::actionPerformed, aEvt ); + } + } + } + + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException) + { + m_aSubmissionVetoListeners.addInterface( listener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException) + { + m_aSubmissionVetoListeners.removeInterface( listener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler ) throw (VetoException, WrappedTargetException, RuntimeException) + { + implSubmit( MouseEvent(), _rxHandler ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseControl::submit( ) throw (VetoException, WrappedTargetException, RuntimeException) + { + implSubmit( MouseEvent(), NULL ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseControl::getSupportedServiceNames( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupported = OControl::getSupportedServiceNames(); + aSupported.realloc( aSupported.getLength() + 1 ); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[ aSupported.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON; + + return aSupported; + } + + //-------------------------------------------------------------------- + void OClickableImageBaseControl::implSubmit( const MouseEvent& _rEvent, const Reference< XInteractionHandler >& _rxHandler ) SAL_THROW((VetoException, WrappedTargetException, RuntimeException)) + { + try + { + // allow the veto listeners to join the game + m_aSubmissionVetoListeners.notifyEach( &XSubmissionVetoListener::submitting, EventObject( *this ) ); + + // see whether there's an "submit interceptor" set at our model + Reference< submission::XSubmissionSupplier > xSubmissionSupp( getModel(), UNO_QUERY ); + Reference< XSubmission > xSubmission; + if ( xSubmissionSupp.is() ) + xSubmission = xSubmissionSupp->getSubmission(); + + if ( xSubmission.is() ) + { + if ( !_rxHandler.is() ) + xSubmission->submit(); + else + xSubmission->submitWithInteraction( _rxHandler ); + } + else + { + // no "interceptor" -> ordinary (old-way) submission + Reference< XChild > xChild( getModel(), UNO_QUERY ); + Reference< XSubmit > xParentSubmission; + if ( xChild.is() ) + xParentSubmission = xParentSubmission.query( xChild->getParent() ); + if ( xParentSubmission.is() ) + xParentSubmission->submit( this, _rEvent ); + } + } + catch( const VetoException& ) + { + // allowed to leave + throw; + } + catch( const RuntimeException& ) + { + // allowed to leave + throw; + } + catch( const WrappedTargetException& e ) + { + // allowed to leave + throw; + } + catch( const Exception& e ) + { + OSL_ENSURE( sal_False, "OClickableImageBaseControl::implSubmit: caught an unknown exception!" ); + throw WrappedTargetException( ::rtl::OUString(), *this, makeAny( e ) ); + } + } + + //================================================================== + // OClickableImageBaseModel + //================================================================== + //------------------------------------------------------------------------------ + Sequence<Type> OClickableImageBaseModel::_getTypes() + { + return concatSequences( + OControlModel::_getTypes(), + OClickableImageBaseModel_Base::getTypes() + ); + } + + //------------------------------------------------------------------ + DBG_NAME( OClickableImageBaseModel ) + //------------------------------------------------------------------ + OClickableImageBaseModel::OClickableImageBaseModel( const Reference< XMultiServiceFactory >& _rxFactory, const ::rtl::OUString& _rUnoControlModelTypeName, + const ::rtl::OUString& rDefault ) + :OControlModel( _rxFactory, _rUnoControlModelTypeName, rDefault ) + ,OPropertyChangeListener(m_aMutex) + ,m_pMedium(NULL) + ,m_pProducer( NULL ) + ,m_bDispatchUrlInternal(sal_False) + ,m_bDownloading(sal_False) + ,m_bProdStarted(sal_False) + { + DBG_CTOR( OClickableImageBaseModel, NULL ); + implConstruct(); + m_eButtonType = FormButtonType_PUSH; + } + + //------------------------------------------------------------------ + OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + ,OPropertyChangeListener( m_aMutex ) + ,m_pMedium( NULL ) + ,m_pProducer( NULL ) + ,m_bDispatchUrlInternal(sal_False) + ,m_bDownloading( sal_False ) + ,m_bProdStarted( sal_False ) + { + DBG_CTOR( OClickableImageBaseModel, NULL ); + implConstruct(); + + // copy properties + m_eButtonType = _pOriginal->m_eButtonType; + m_sTargetURL = _pOriginal->m_sTargetURL; + m_sTargetFrame = _pOriginal->m_sTargetFrame; + m_bDispatchUrlInternal = _pOriginal->m_bDispatchUrlInternal; + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::implInitializeImageURL( ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + // simulate a propertyChanged event for the ImageURL + // 2003-05-15 - #109591# - fs@openoffice.org + Any aImageURL; + getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL ); + _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL, sal_False, PROPERTY_ID_IMAGE_URL, Any( ), aImageURL ) ); + } + osl_decrementInterlockedCount( &m_refCount ); + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::implConstruct() + { + m_pProducer = new ImageProducer; + increment( m_refCount ); + { + m_xProducer = m_pProducer; + + if ( m_xAggregateSet.is() ) + { + OPropertyChangeMultiplexer* pMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet ); + pMultiplexer->addProperty( PROPERTY_IMAGE_URL ); + } + } + decrement(m_refCount); + } + + //------------------------------------------------------------------------------ + OClickableImageBaseModel::~OClickableImageBaseModel() + { + if (!OComponentHelper::rBHelper.bDisposed) + { + acquire(); + dispose(); + } + DBG_ASSERT(m_pMedium == NULL, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ..."); + // spaetestens im dispose sollte das aufgeraeumt worden sein + + DBG_DTOR( OClickableImageBaseModel, NULL ); + } + + // XImageProducer + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) + { + ImageModelMethodGuard aGuard( *this ); + GetImageProducer()->addConsumer( _rxConsumer ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) + { + ImageModelMethodGuard aGuard( *this ); + GetImageProducer()->removeConsumer( _rxConsumer ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseModel::startProduction( ) throw (RuntimeException) + { + ImageModelMethodGuard aGuard( *this ); + GetImageProducer()->startProduction(); + } + + //-------------------------------------------------------------------- + Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission() throw (RuntimeException) + { + return m_xSubmissionDelegate; + } + + //-------------------------------------------------------------------- + void SAL_CALL OClickableImageBaseModel::setSubmission( const Reference< submission::XSubmission >& _submission ) throw (RuntimeException) + { + m_xSubmissionDelegate = _submission; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseModel::getSupportedServiceNames( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupported = OControlModel::getSupportedServiceNames(); + aSupported.realloc( aSupported.getLength() + 1 ); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON; + + return aSupported; + } + + // OComponentHelper + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::disposing() + { + OControlModel::disposing(); + if (m_pMedium) + { + delete m_pMedium; + m_pMedium = NULL; + } + + m_xProducer = NULL; + m_pProducer = NULL; + } + + //------------------------------------------------------------------------------ + Any SAL_CALL OClickableImageBaseModel::queryAggregation(const Type& _rType) throw (RuntimeException) + { + // order matters: + // we definately want to "overload" the XImageProducer interface of our aggregate, + // thus check OClickableImageBaseModel_Base (which provides this) first + Any aReturn = OClickableImageBaseModel_Base::queryInterface( _rType ); + + // BUT: _don't_ let it feel responsible for the XTypeProvider interface + // (as this is implemented by our base class in the proper way) + if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) + || !aReturn.hasValue() + ) + aReturn = OControlModel::queryAggregation( _rType ); + + return aReturn; + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const + { + switch (nHandle) + { + case PROPERTY_ID_BUTTONTYPE : rValue <<= m_eButtonType; break; + case PROPERTY_ID_TARGET_URL : rValue <<= m_sTargetURL; break; + case PROPERTY_ID_TARGET_FRAME : rValue <<= m_sTargetFrame; break; + case PROPERTY_ID_DISPATCHURLINTERNAL : rValue <<= m_bDispatchUrlInternal; break; + default: + OControlModel::getFastPropertyValue(rValue, nHandle); + } + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( Exception) + { + switch (nHandle) + { + case PROPERTY_ID_BUTTONTYPE : + DBG_ASSERT(isA(rValue, static_cast<FormButtonType*>(NULL)), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_eButtonType; + break; + + case PROPERTY_ID_TARGET_URL : + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_sTargetURL; + break; + + case PROPERTY_ID_TARGET_FRAME : + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_sTargetFrame; + break; + + case PROPERTY_ID_DISPATCHURLINTERNAL: + DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); + rValue >>= m_bDispatchUrlInternal; + break; + + default: + OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); + } + } + + //------------------------------------------------------------------------------ + sal_Bool OClickableImageBaseModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) + throw( IllegalArgumentException ) + { + switch (nHandle) + { + case PROPERTY_ID_BUTTONTYPE : + return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType ); + + case PROPERTY_ID_TARGET_URL : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL); + + case PROPERTY_ID_TARGET_FRAME : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame); + + case PROPERTY_ID_DISPATCHURLINTERNAL : + return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal); + + default: + return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); + } + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::StartProduction() + { + ImageProducer *pImgProd = GetImageProducer(); + // grab the ImageURL + rtl::OUString sURL; + getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ImageURL") ) ) >>= sURL; + if (!m_pMedium) + { + if ( ::svt::GraphicAccess::isSupportedURL( sURL ) ) + pImgProd->SetImage( sURL ); + else + // caution: the medium may be NULL if somebody gave us a invalid URL to work with + // 11/24/2000 - 79667 - FS + pImgProd->SetImage(String()); + m_bDownloading = sal_False; + return; + } + if (m_pMedium->GetErrorCode()==0) + { + SvStream* pStream = m_pMedium->GetInStream(); + + pImgProd->SetImage(*pStream); + pImgProd->startProduction(); + m_bProdStarted = sal_True; + } + else + { + pImgProd->SetImage(String()); + delete m_pMedium; + m_pMedium = 0; + m_bDownloading = sal_False; + } + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::SetURL( const ::rtl::OUString& rURL ) + { + if (m_pMedium || !rURL.getLength()) + { + // Den Stream am Producer freigeben, bevor das Medium geloscht wird. + GetImageProducer()->SetImage(String()); + delete m_pMedium; + m_pMedium = NULL; + } + + // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first + // 23.01.2001 - 81927 - FS + INetURLObject aUrl(rURL); + if (INET_PROT_NOT_VALID == aUrl.GetProtocol()) + // we treat an invalid URL like we would treat no URL + return; + + if (rURL.getLength() && !::svt::GraphicAccess::isSupportedURL( rURL ) ) + { + if (m_pMedium) + delete m_pMedium; + + m_pMedium = new SfxMedium(rURL, STREAM_STD_READ, sal_False); + m_pMedium->SetDataAvailableLink( + STATIC_LINK(this, OClickableImageBaseModel, DataAvailableLink)); + + // Das XModel suchen, um an die Object-Shell oder zumindest den + // Referer zu gelangen. + // Das Model findet man allerdings nur beim Laden von HTML-Dokumenten + // und dann, wenn die URL in einem bereits geladenen Dokument + // geaendert wird. Waehrend des Ladens kommt man nicht an das + // Model ran. + Reference< XModel > xModel; + InterfaceRef xIfc( *this ); + while( !xModel.is() && xIfc.is() ) + { + Reference<XChild> xChild( xIfc, UNO_QUERY ); + xIfc = xChild->getParent(); + query_interface(xIfc, xModel); + } + + // Die Object-Shell suchen, indem wir + // ueber alle Object-Shells iterieren und deren XModel mit dem + // eigenen vergleichen. Als Optimierung probieren wir aber erstmal + // die aktuelle Object-Shell. + // wir unser XModel mit dem aller Object + SfxObjectShell *pObjSh = 0; + + if( xModel.is() ) + { + SfxObjectShell *pTestObjSh = SfxObjectShell::Current(); + if( pTestObjSh ) + { + Reference< XModel > xTestModel = pTestObjSh->GetModel(); + if( xTestModel == xModel ) + pObjSh = pTestObjSh; + } + if( !pObjSh ) + { + pTestObjSh = SfxObjectShell::GetFirst(); + while( !pObjSh && pTestObjSh ) + { + Reference< XModel > xTestModel = pTestObjSh->GetModel(); + if( xTestModel == xModel ) + pObjSh = pTestObjSh; + else + pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh ); + } + } + } + + #ifdef USE_REGISTER_TRANSFER + if( pObjSh ) + { + // Medium registrieren, damit abgebrochen werden kann + pObjSh->RegisterTransfer( *m_pMedium ); + + // Target-Frame uebertragen, damit auch javascript:-URLs + // "geladen" werden koennen. + const SfxMedium *pShMedium = pObjSh->GetMedium(); + if( pShMedium ) + m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); + } + else + { + // Keine Object-Shell, aber ein Medium? Dann uebernehmen wir + // zumindest den Referer. + if( xModel.is() ) + { + ::rtl::OUString sReferer( xModel->getURL() ); + if( sReferer.getLength() ) + m_pMedium->SetReferer( OUStringToString(sReferer, CHARSET_SYSTEM) ); + } + } + #else + if( pObjSh ) + { + // Target-Frame uebertragen, damit auch javascript:-URLs + // "geladen" werden koennen. + const SfxMedium *pShMedium = pObjSh->GetMedium(); + if( pShMedium ) + m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); + } + + if( xModel.is() ) + { + ::rtl::OUString sReferer( xModel->getURL() ); + if( sReferer.getLength() ) + m_pMedium->SetReferer( sReferer ); + } + #endif + + // Downloading-Flag auf sal_True setzen. Es werden dann auch + // Data-Available-Links, wenn wir in den Pending-Staus gelangen. + m_bDownloading = sal_True; + m_bProdStarted = sal_False; + + // Download anstossen (Achtung: Kann auch synchron sein). + m_pMedium->DownLoad(STATIC_LINK(this, OClickableImageBaseModel, DownloadDoneLink)); + } + else + { + if ( ::svt::GraphicAccess::isSupportedURL( rURL ) ) + GetImageProducer()->SetImage( rURL ); + GetImageProducer()->startProduction(); + } + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::DataAvailable() + { + if (!m_bProdStarted) + StartProduction(); + + GetImageProducer()->NewDataAvailable(); + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::DownloadDone() + { + DataAvailable(); + m_bDownloading = sal_False; + } + + //------------------------------------------------------------------------------ + IMPL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void*, EMPTYARG ) + { + ::osl::MutexGuard aGuard( pThis->m_aMutex ); + pThis->DownloadDone(); + return 0; + } + + //------------------------------------------------------------------------------ + IMPL_STATIC_LINK( OClickableImageBaseModel, DataAvailableLink, void*, EMPTYARG ) + { + ::osl::MutexGuard aGuard( pThis->m_aMutex ); + pThis->DataAvailable(); + return 0; + } + + //------------------------------------------------------------------------------ + void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt ) + throw( RuntimeException ) + { + // Wenn eine URL gesetzt worden ist, muss die noch an den ImageProducer + // weitergereicht werden. + ::osl::MutexGuard aGuard(m_aMutex); + SetURL( getString(rEvt.NewValue) ); + } + + // ----------------------------------------------------------------------------- + Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const + { + switch (nHandle) + { + case PROPERTY_ID_BUTTONTYPE : return makeAny( FormButtonType_PUSH ); + case PROPERTY_ID_TARGET_URL : + case PROPERTY_ID_TARGET_FRAME : return makeAny( ::rtl::OUString() ); + case PROPERTY_ID_DISPATCHURLINTERNAL : return makeAny( sal_False ); + default: + return OControlModel::getPropertyDefaultByHandle(nHandle); + } + } + + //================================================================== + // OImageProducerThread_Impl + //================================================================== + //------------------------------------------------------------------ + EventObject* OImageProducerThread_Impl::cloneEvent( const EventObject* _pEvt ) const + { + return new EventObject( *_pEvt ); + } + + //------------------------------------------------------------------ + void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper *pCompImpl, + const EventObject* pEvt, + const Reference<XControl>&, + sal_Bool ) + { + ((OClickableImageBaseControl *)pCompImpl)->actionPerformed_Impl( sal_True, *(MouseEvent *)pEvt ); + } + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/clickableimage.hxx b/forms/source/component/clickableimage.hxx new file mode 100644 index 000000000000..f888aa4e3309 --- /dev/null +++ b/forms/source/component/clickableimage.hxx @@ -0,0 +1,295 @@ +/************************************************************************* + * + * 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_SOURCE_CLICKABLEIMAGE_HXX +#define FORMS_SOURCE_CLICKABLEIMAGE_HXX + +#include "FormComponent.hxx" +#include "EventThread.hxx" +#include "imgprod.hxx" +#include <tools/link.hxx> +#include <comphelper/propmultiplex.hxx> +#include <com/sun/star/form/XImageProducerSupplier.hpp> +#include <com/sun/star/form/FormButtonType.hpp> +#include <com/sun/star/form/XApproveActionListener.hpp> +#include <com/sun/star/form/XApproveActionBroadcaster.hpp> +#include <com/sun/star/form/submission/XSubmissionSupplier.hpp> +#include <com/sun/star/form/submission/XSubmission.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XDispatchProviderInterception.hpp> +#include <cppuhelper/implbase3.hxx> + + +class SfxMedium; + +//......................................................................... +namespace frm +{ +//......................................................................... + + class OImageProducerThread_Impl; + class ControlFeatureInterception; + //================================================================== + // OClickableImageBaseModel + //================================================================== + typedef ::cppu::ImplHelper3 < ::com::sun::star::form::XImageProducerSupplier + , ::com::sun::star::awt::XImageProducer + , ::com::sun::star::form::submission::XSubmissionSupplier + > OClickableImageBaseModel_Base; + + class OClickableImageBaseModel :public OClickableImageBaseModel_Base + ,public OControlModel + ,public OPropertyChangeListener + { + protected: + ::com::sun::star::form::FormButtonType m_eButtonType; // Art des Buttons (push,submit,reset) + ::rtl::OUString m_sTargetURL; // URL fuer den URL-Button + ::rtl::OUString m_sTargetFrame; // TargetFrame zum Oeffnen + + // ImageProducer stuff + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageProducer> m_xProducer; + SfxMedium* m_pMedium; // Download-Medium + ImageProducer* m_pProducer; + sal_Bool m_bDispatchUrlInternal; // property: is not allowed to set : 1 + sal_Bool m_bDownloading : 1; // laeuft ein Download? + sal_Bool m_bProdStarted : 1; + + // XSubmission stuff + ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmission > + m_xSubmissionDelegate; + + + DECL_STATIC_LINK( OClickableImageBaseModel, DataAvailableLink, void* ); + DECL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void* ); + + inline ImageProducer* GetImageProducer() { return m_pProducer; } + + void StartProduction(); + void SetURL(const ::rtl::OUString& rURL); + void DataAvailable(); + void DownloadDone(); + + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes(); + inline sal_Bool isDispatchUrlInternal() const { return m_bDispatchUrlInternal; } + inline void setDispatchUrlInternal(sal_Bool _bDispatch) { m_bDispatchUrlInternal = _bDispatch; } + + public: + DECLARE_DEFAULT_XTOR( OClickableImageBaseModel ); + + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OClickableImageBaseModel, OControlModel); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException); + + protected: + // OComponentHelper + virtual void SAL_CALL disposing(); + + // ::com::sun::star::form::XImageProducerSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageProducer> SAL_CALL getImageProducer() throw (::com::sun::star::uno::RuntimeException) { return m_xProducer; } + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception); + + 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); + + using ::cppu::OPropertySetHelper::getFastPropertyValue; + + // OPropertyChangeListener + virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent&) throw(::com::sun::star::uno::RuntimeException); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // XImageProducer + virtual void SAL_CALL addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& xConsumer ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& xConsumer ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL startProduction( ) throw (::com::sun::star::uno::RuntimeException); + + // XSubmissionSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmission > SAL_CALL getSubmission() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setSubmission( const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmission >& _submission ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + using OControlModel::disposing; + + public: + struct GuardAccess { friend class ImageModelMethodGuard; private: GuardAccess() { } }; + ::osl::Mutex& getMutex( GuardAccess ) { return m_aMutex; } + ImageProducer* getImageProducer( GuardAccess ) { return m_pProducer; } + + protected: + using OControlModel::getMutex; + + void implConstruct(); + + // to be called from within the cloning-ctor of your derived class + void implInitializeImageURL( ); + }; + + //================================================================== + // ImageModelMethodGuard + //================================================================== + class ImageModelMethodGuard : public ::osl::MutexGuard + { + private: + typedef ::osl::MutexGuard GuardBase; + + public: + ImageModelMethodGuard( OClickableImageBaseModel& _rModel ) + :GuardBase( _rModel.getMutex( OClickableImageBaseModel::GuardAccess() ) ) + { + if ( NULL == _rModel.getImageProducer( OClickableImageBaseModel::GuardAccess() ) ) + throw ::com::sun::star::lang::DisposedException( + ::rtl::OUString(), + static_cast< ::com::sun::star::form::XImageProducerSupplier* >( &_rModel ) + ); + } + }; + + //================================================================== + // OClickableImageBaseControl + //================================================================== + typedef ::cppu::ImplHelper3 < ::com::sun::star::form::XApproveActionBroadcaster + , ::com::sun::star::form::submission::XSubmission + , ::com::sun::star::frame::XDispatchProviderInterception + > OClickableImageBaseControl_BASE; + + class OClickableImageBaseControl :public OClickableImageBaseControl_BASE + ,public OControl + { + friend class OImageProducerThread_Impl; + + private: + OImageProducerThread_Impl* m_pThread; + ::cppu::OInterfaceContainerHelper m_aSubmissionVetoListeners; + ::std::auto_ptr< ControlFeatureInterception > + m_pFeatureInterception; + + protected: + ::cppu::OInterfaceContainerHelper m_aApproveActionListeners; + ::cppu::OInterfaceContainerHelper m_aActionListeners; + ::rtl::OUString m_aActionCommand; + + // XSubmission + virtual void SAL_CALL submit( ) throw (::com::sun::star::util::VetoException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL submitWithInteraction( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler ) throw (::com::sun::star::util::VetoException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addSubmissionVetoListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmissionVetoListener >& listener ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSubmissionVetoListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmissionVetoListener >& listener ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + using OControl::disposing; + + public: + OClickableImageBaseControl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, + const ::rtl::OUString& _aService); + virtual ~OClickableImageBaseControl(); + + protected: + // UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OClickableImageBaseControl, OControl); + 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(); + + // ::com::sun::star::form::XApproveActionBroadcaster + virtual void SAL_CALL addApproveActionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XApproveActionListener>& _rxListener) + throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeApproveActionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XApproveActionListener>& _rxListener) + throw(::com::sun::star::uno::RuntimeException); + + // XDispatchProviderInterception + virtual void SAL_CALL registerDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL releaseDispatchProviderInterceptor( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& Interceptor ) throw (::com::sun::star::uno::RuntimeException); + + protected: + virtual void actionPerformed_Impl( sal_Bool bNotifyListener, const ::com::sun::star::awt::MouseEvent& rEvt ); + + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > _getTypes(); + + /** approves the action by calling the approve listeners + @return <TRUE/> if and only if the action has <em>not</em> been cancelled by a listener + */ + bool approveAction( ); + + /** retrieves (and if necessary creates) the image producer thread. + + Must be called with our mutex locked + */ + OImageProducerThread_Impl* getImageProducerThread(); + + private: + void implSubmit( + const ::com::sun::star::awt::MouseEvent& _rEvent, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler + ) SAL_THROW((com::sun::star::util::VetoException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)); + }; + + //================================================================== + // OImageProducerThread_Impl + //================================================================== + class OImageProducerThread_Impl: public OComponentEventThread + { + protected: + + // Die folgende Methode wrrd gerufen um das Event unter Beruecksichtigung + // seines Typs zu duplizieren + virtual ::com::sun::star::lang::EventObject* cloneEvent( const ::com::sun::star::lang::EventObject* _pEvt ) const; + + // Ein Event bearbeiten. Der Mutex ist dabei nicht gelockt, pCompImpl + // bleibt aber in jedem Fall gueltig. + virtual void processEvent( ::cppu::OComponentHelper *pCompImpl, + const ::com::sun::star::lang::EventObject*, + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>&, + sal_Bool ); + + public: + OImageProducerThread_Impl( OClickableImageBaseControl *pControl ) : + OComponentEventThread( pControl ) + {} + + void addEvent() { ::com::sun::star::lang::EventObject aEvt; OComponentEventThread::addEvent( &aEvt ); } + + protected: + using OComponentEventThread::addEvent; + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_SOURCE_CLICKABLEIMAGE_HXX + diff --git a/forms/source/component/cloneable.cxx b/forms/source/component/cloneable.cxx new file mode 100644 index 000000000000..5392dbee3e7f --- /dev/null +++ b/forms/source/component/cloneable.cxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "cloneable.hxx" +#include <com/sun/star/util/XCloneable.hpp> +#include <comphelper/uno3.hxx> +#include <tools/debug.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::comphelper; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::util; + + //==================================================================== + //= OCloneableAggregation + //==================================================================== + //------------------------------------------------------------------ + Reference< XAggregation > OCloneableAggregation::createAggregateClone( const OCloneableAggregation* _pOriginal ) + { + Reference< XCloneable > xAggregateCloneable; // will be the aggregate's XCloneable + Reference< XAggregation > xAggregateClone; // will be the aggregate's clone + + if ( query_aggregation( _pOriginal->m_xAggregate, xAggregateCloneable ) ) + { + xAggregateClone = xAggregateClone.query( xAggregateCloneable->createClone() ); + DBG_ASSERT( xAggregateClone.is(), "OCloneableAggregation::createAggregateClone: invalid clone returned by the aggregate!" ); + } + else { + DBG_ASSERT( !_pOriginal->m_xAggregate.is(), "OCloneableAggregation::createAggregateClone: aggregate is not cloneable!" ); + } + + return xAggregateClone; + } + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/entrylisthelper.cxx b/forms/source/component/entrylisthelper.cxx new file mode 100644 index 000000000000..065bd4ca6896 --- /dev/null +++ b/forms/source/component/entrylisthelper.cxx @@ -0,0 +1,321 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "entrylisthelper.hxx" +#include "FormComponent.hxx" + +#include <osl/diagnose.h> +#include <comphelper/sequence.hxx> +#include <comphelper/property.hxx> +#include <algorithm> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form::binding; + + //===================================================================== + //= OEntryListHelper + //===================================================================== + //--------------------------------------------------------------------- + OEntryListHelper::OEntryListHelper( OControlModel& _rControlModel ) + :m_rControlModel( _rControlModel ) + ,m_aRefreshListeners( _rControlModel.getInstanceMutex() ) + { + } + + //--------------------------------------------------------------------- + OEntryListHelper::OEntryListHelper( const OEntryListHelper& _rSource, OControlModel& _rControlModel ) + :m_rControlModel( _rControlModel ) + ,m_xListSource ( _rSource.m_xListSource ) + ,m_aStringItems( _rSource.m_aStringItems ) + ,m_aRefreshListeners( _rControlModel.getInstanceMutex() ) + { + } + + //--------------------------------------------------------------------- + OEntryListHelper::~OEntryListHelper( ) + { + } + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::setListEntrySource( const Reference< XListEntrySource >& _rxSource ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + // disconnect from the current external list source + disconnectExternalListSource(); + + // and connect to the new one + if ( _rxSource.is() ) + connectExternalListSource( _rxSource, aLock ); + } + + //--------------------------------------------------------------------- + Reference< XListEntrySource > SAL_CALL OEntryListHelper::getListEntrySource( ) throw (RuntimeException) + { + return m_xListSource; + } + + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::entryChanged( const ListEntryEvent& _rEvent ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + OSL_ENSURE( _rEvent.Source == m_xListSource, + "OEntryListHelper::entryChanged: where did this come from?" ); + OSL_ENSURE( ( _rEvent.Position >= 0 ) && ( _rEvent.Position < m_aStringItems.getLength() ), + "OEntryListHelper::entryChanged: invalid index!" ); + OSL_ENSURE( _rEvent.Entries.getLength() == 1, + "OEntryListHelper::entryChanged: invalid string list!" ); + + if ( ( _rEvent.Position >= 0 ) + && ( _rEvent.Position < m_aStringItems.getLength() ) + && ( _rEvent.Entries.getLength() > 0 ) + ) + { + m_aStringItems[ _rEvent.Position ] = _rEvent.Entries[ 0 ]; + stringItemListChanged( aLock ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::entryRangeInserted( const ListEntryEvent& _rEvent ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + OSL_ENSURE( _rEvent.Source == m_xListSource, + "OEntryListHelper::entryRangeInserted: where did this come from?" ); + OSL_ENSURE( ( _rEvent.Position > 0 ) && ( _rEvent.Position < m_aStringItems.getLength() ) && ( _rEvent.Entries.getLength() > 0 ), + "OEntryListHelper::entryRangeRemoved: invalid count and/or position!" ); + + if ( ( _rEvent.Position > 0 ) + && ( _rEvent.Position < m_aStringItems.getLength() ) + && ( _rEvent.Entries.getLength() > 0 ) + ) + { + // the entries *before* the insertion pos + Sequence< ::rtl::OUString > aKeepEntries( + m_aStringItems.getConstArray(), + _rEvent.Position + ); + // the entries *behind* the insertion pos + Sequence< ::rtl::OUString > aMovedEntries( + m_aStringItems.getConstArray() + _rEvent.Position, + m_aStringItems.getLength() - _rEvent.Position + ); + + // concat all three parts + m_aStringItems = ::comphelper::concatSequences( + aKeepEntries, + _rEvent.Entries, + aMovedEntries + ); + + stringItemListChanged( aLock ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::entryRangeRemoved( const ListEntryEvent& _rEvent ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + OSL_ENSURE( _rEvent.Source == m_xListSource, + "OEntryListHelper::entryRangeRemoved: where did this come from?" ); + OSL_ENSURE( ( _rEvent.Position > 0 ) && ( _rEvent.Count > 0 ) && ( _rEvent.Position + _rEvent.Count <= m_aStringItems.getLength() ), + "OEntryListHelper::entryRangeRemoved: invalid count and/or position!" ); + + if ( ( _rEvent.Position > 0 ) + && ( _rEvent.Count > 0 ) + && ( _rEvent.Position + _rEvent.Count <= m_aStringItems.getLength() ) + ) + { + // copy all items after the removed ones + ::std::copy( + m_aStringItems.getConstArray() + _rEvent.Position + _rEvent.Count, + m_aStringItems.getConstArray() + m_aStringItems.getLength(), + m_aStringItems.getArray( ) + _rEvent.Position + ); + // shrink the array + m_aStringItems.realloc( m_aStringItems.getLength() - _rEvent.Count ); + + stringItemListChanged( aLock ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OEntryListHelper::allEntriesChanged( const EventObject& _rEvent ) throw (RuntimeException) + { + ControlModelLock aLock( m_rControlModel ); + + OSL_ENSURE( _rEvent.Source == m_xListSource, + "OEntryListHelper::allEntriesChanged: where did this come from?" ); + + Reference< XListEntrySource > xSource( _rEvent.Source, UNO_QUERY ); + if ( _rEvent.Source == m_xListSource ) + { + impl_lock_refreshList( aLock ); + } + } + + // XRefreshable + //------------------------------------------------------------------------------ + void SAL_CALL OEntryListHelper::addRefreshListener(const Reference<XRefreshListener>& _rxListener) throw(RuntimeException) + { + if ( _rxListener.is() ) + m_aRefreshListeners.addInterface( _rxListener ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OEntryListHelper::removeRefreshListener(const Reference<XRefreshListener>& _rxListener) throw(RuntimeException) + { + if ( _rxListener.is() ) + m_aRefreshListeners.removeInterface( _rxListener ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OEntryListHelper::refresh() throw(RuntimeException) + { + { + ControlModelLock aLock( m_rControlModel ); + impl_lock_refreshList( aLock ); + } + + EventObject aEvt( static_cast< XRefreshable* >( this ) ); + m_aRefreshListeners.notifyEach( &XRefreshListener::refreshed, aEvt ); + } + + //--------------------------------------------------------------------- + void OEntryListHelper::impl_lock_refreshList( ControlModelLock& _rInstanceLock ) + { + if ( hasExternalListSource() ) + { + m_aStringItems = m_xListSource->getAllListEntries( ); + stringItemListChanged( _rInstanceLock ); + } + else + refreshInternalEntryList(); + } + + //--------------------------------------------------------------------- + bool OEntryListHelper::handleDisposing( const EventObject& _rEvent ) + { + if ( m_xListSource .is() && ( _rEvent.Source == m_xListSource ) ) + { + disconnectExternalListSource( ); + return true; + } + return false; + } + + //--------------------------------------------------------------------- + void OEntryListHelper::disposing( ) + { + EventObject aEvt( static_cast< XRefreshable* >( this ) ); + m_aRefreshListeners.disposeAndClear(aEvt); + + if ( hasExternalListSource( ) ) + disconnectExternalListSource( ); + } + + //--------------------------------------------------------------------- + void OEntryListHelper::disconnectExternalListSource( ) + { + if ( m_xListSource.is() ) + m_xListSource->removeListEntryListener( this ); + + m_xListSource.clear(); + + disconnectedExternalListSource(); + } + + //--------------------------------------------------------------------- + void OEntryListHelper::connectedExternalListSource( ) + { + // nothing to do here + } + + //--------------------------------------------------------------------- + void OEntryListHelper::disconnectedExternalListSource( ) + { + // nothing to do here + } + + //--------------------------------------------------------------------- + void OEntryListHelper::connectExternalListSource( const Reference< XListEntrySource >& _rxSource, ControlModelLock& _rInstanceLock ) + { + OSL_ENSURE( !hasExternalListSource(), "OEntryListHelper::connectExternalListSource: only to be called if no external source is active!" ); + OSL_ENSURE( _rxSource.is(), "OEntryListHelper::connectExternalListSource: invalid list source!" ); + + // remember it + m_xListSource = _rxSource; + + // initially fill our item list + if ( m_xListSource.is() ) + { + // be notified when the list changes ... + m_xListSource->addListEntryListener( this ); + + m_aStringItems = m_xListSource->getAllListEntries( ); + stringItemListChanged( _rInstanceLock ); + + // let derivees react on the new list source + connectedExternalListSource(); + } + } + + //--------------------------------------------------------------------- + sal_Bool OEntryListHelper::convertNewListSourceProperty( Any& _rConvertedValue, + Any& _rOldValue, const Any& _rValue ) SAL_THROW( ( IllegalArgumentException ) ) + { + if ( hasExternalListSource() ) + throw IllegalArgumentException( ); + // TODO: error message + + return ::comphelper::tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aStringItems ); + } + + //--------------------------------------------------------------------- + void OEntryListHelper::setNewStringItemList( const ::com::sun::star::uno::Any& _rValue, ControlModelLock& _rInstanceLock ) + { + OSL_PRECOND( !hasExternalListSource(), "OEntryListHelper::setNewStringItemList: this should never have survived convertNewListSourceProperty!" ); + OSL_VERIFY( _rValue >>= m_aStringItems ); + stringItemListChanged( _rInstanceLock ); + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/component/entrylisthelper.hxx b/forms/source/component/entrylisthelper.hxx new file mode 100644 index 000000000000..64778e9abdc3 --- /dev/null +++ b/forms/source/component/entrylisthelper.hxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * 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_ENTRYLISTHELPER_HXX +#define FORMS_ENTRYLISTHELPER_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/form/binding/XListEntrySink.hpp> +#include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/form/binding/XListEntryListener.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/interfacecontainer.hxx> + +//......................................................................... +namespace frm +{ +//......................................................................... + + class OControlModel; + class ControlModelLock; + + //===================================================================== + //= OEntryListHelper + //===================================================================== + typedef ::cppu::ImplHelper3 < ::com::sun::star::form::binding::XListEntrySink + , ::com::sun::star::form::binding::XListEntryListener + , ::com::sun::star::util::XRefreshable + > OEntryListHelper_BASE; + + class OEntryListHelper : public OEntryListHelper_BASE + { + private: + OControlModel& m_rControlModel; + + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > + m_xListSource; /// our external list source + ::com::sun::star::uno::Sequence< ::rtl::OUString > + m_aStringItems; /// "overridden" StringItemList property value + ::cppu::OInterfaceContainerHelper + m_aRefreshListeners; + + + protected: + OEntryListHelper( OControlModel& _rControlModel ); + OEntryListHelper( const OEntryListHelper& _rSource, OControlModel& _rControlModel ); + virtual ~OEntryListHelper( ); + + /// returns the current string item list + inline const ::com::sun::star::uno::Sequence< ::rtl::OUString >& + getStringItemList() const { return m_aStringItems; } + inline const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& + getExternalListEntrySource() const { return m_xListSource; } + + /// determines whether we actually have an external list source + inline bool hasExternalListSource( ) const { return m_xListSource.is(); } + + /** handling the XEventListener::disposing call for the case where + our list source is being disposed + @return + <TRUE/> if and only if the disposed object was our list source, and so the + event was handled + */ + bool handleDisposing( const ::com::sun::star::lang::EventObject& _rEvent ); + + /** to be called by derived classes' instances when they're being disposed + */ + void disposing( ); + + // prevent method hiding + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException) = 0; + + /** helper for implementing convertFastPropertyValue( StringItemList ) + + <p>The signature of this method and the return type have the same semantics + as convertFastPropertyValue.</p> + */ + sal_Bool convertNewListSourceProperty( + ::com::sun::star::uno::Any& _rConvertedValue, + ::com::sun::star::uno::Any& _rOldValue, + const ::com::sun::star::uno::Any& _rValue + ) + SAL_THROW( ( ::com::sun::star::lang::IllegalArgumentException ) ); + + /** helper for implementing setFastPropertyValueNoBroadcast + + <p>Will internally call stringItemListChanged after the new item list + has been set.</p> + + @precond + not to be called when we have an external list source + @see hasExternalListSource + */ + void setNewStringItemList( const ::com::sun::star::uno::Any& _rValue, ControlModelLock& _rInstanceLock ); + + /** announces that the list of entries has changed. + + <p>Derived classes have to override this. Most probably, they'll set the new + as model property.</p> + + @pure + @see getStringItemList + */ + virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ) = 0; + + /** called whenever a connection to a new external list source has been established + */ + virtual void connectedExternalListSource( ); + + /** called whenever a connection to a new external list source has been revoked + */ + virtual void disconnectedExternalListSource( ); + + /** called when XRefreshable::refresh has been called, and we do *not* have an external + list source + */ + virtual void refreshInternalEntryList() = 0; + + private: + // XListEntrySink + virtual void SAL_CALL setListEntrySource( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > SAL_CALL getListEntrySource( ) throw (::com::sun::star::uno::RuntimeException); + + // XListEntryListener + virtual void SAL_CALL entryChanged( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL entryRangeInserted( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL entryRangeRemoved( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL allEntriesChanged( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException); + + // XRefreshable + virtual void SAL_CALL refresh() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRefreshListener(const ::com::sun::star::uno::Reference< ::com::sun::star::util::XRefreshListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRefreshListener(const ::com::sun::star::uno::Reference< ::com::sun::star::util::XRefreshListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + private: + /** disconnects from the active external list source, if present + @see connectExternalListSource + */ + void disconnectExternalListSource( ); + + /** connects to a new external list source + @param _rxSource + the new list source. Must not be <NULL/> + @see disconnectExternalListSource + */ + void connectExternalListSource( + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource, + ControlModelLock& _rInstanceLock + ); + + /** refreshes our list entries + + In case we have an external list source, its used to obtain the new entries, and then + stringItemListChanged is called to give the derived class the possibility to + react on this. + + In case we do not have an external list source, refreshInternalEntryList is called. + */ + void impl_lock_refreshList( ControlModelLock& _rInstanceLock ); + + private: + OEntryListHelper(); // never implemented + OEntryListHelper( const OEntryListHelper& ); // never implemented + OEntryListHelper& operator=( const OEntryListHelper& ); // never implemented + }; + +//......................................................................... +} // namespace frm +//......................................................................... + + +#endif // FORMS_ENTRYLISTHELPER_HXX diff --git a/forms/source/component/errorbroadcaster.cxx b/forms/source/component/errorbroadcaster.cxx new file mode 100644 index 000000000000..e388a35480a1 --- /dev/null +++ b/forms/source/component/errorbroadcaster.cxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "errorbroadcaster.hxx" +#include <connectivity/dbtools.hxx> +#include <com/sun/star/sdb/SQLContext.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::dbtools; + + //===================================================================== + //= OErrorBroadcaster + //===================================================================== + //--------------------------------------------------------------------- + OErrorBroadcaster::OErrorBroadcaster( ::cppu::OBroadcastHelper& _rBHelper ) + :m_rBHelper( _rBHelper ) + ,m_aErrorListeners( _rBHelper.rMutex ) + { + } + + //--------------------------------------------------------------------- + OErrorBroadcaster::~OErrorBroadcaster( ) + { + OSL_ENSURE( m_rBHelper.bDisposed || m_rBHelper.bInDispose, + "OErrorBroadcaster::~OErrorBroadcaster: not disposed!" ); + // herein, we don't have a chance to do the dispose ourself .... + + OSL_ENSURE( 0 == m_aErrorListeners.getLength(), + "OErrorBroadcaster::~OErrorBroadcaster: still have listeners!" ); + // either we're not disposed, or the derived class did not call our dispose from within their dispose + } + + //--------------------------------------------------------------------- + void SAL_CALL OErrorBroadcaster::disposing() + { + EventObject aDisposeEvent( static_cast< XSQLErrorBroadcaster* >( this ) ); + m_aErrorListeners.disposeAndClear( aDisposeEvent ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OErrorBroadcaster::onError( const SQLException& _rException, const ::rtl::OUString& _rContextDescription ) + { + Any aError; + if ( _rContextDescription.getLength() ) + aError = makeAny( prependErrorInfo( _rException, static_cast< XSQLErrorBroadcaster* >( this ), _rContextDescription ) ); + else + aError = makeAny( _rException ); + + onError( SQLErrorEvent( static_cast< XSQLErrorBroadcaster* >( this ), aError ) ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OErrorBroadcaster::onError( const ::com::sun::star::sdb::SQLErrorEvent& _rError ) + { + if ( m_aErrorListeners.getLength() ) + { + + ::cppu::OInterfaceIteratorHelper aIter( m_aErrorListeners ); + while ( aIter.hasMoreElements() ) + static_cast< XSQLErrorListener* >( aIter.next() )->errorOccured( _rError ); + } + } + + //------------------------------------------------------------------------------ + void SAL_CALL OErrorBroadcaster::addSQLErrorListener( const Reference< XSQLErrorListener >& _rxListener ) throw( RuntimeException ) + { + m_aErrorListeners.addInterface( _rxListener ); + } + + //------------------------------------------------------------------------------ + void SAL_CALL OErrorBroadcaster::removeSQLErrorListener( const Reference< XSQLErrorListener >& _rxListener ) throw( RuntimeException ) + { + m_aErrorListeners.removeInterface( _rxListener ); + } + +//......................................................................... +} // namespace frm +//......................................................................... + diff --git a/forms/source/component/errorbroadcaster.hxx b/forms/source/component/errorbroadcaster.hxx new file mode 100644 index 000000000000..c91cc220c58d --- /dev/null +++ b/forms/source/component/errorbroadcaster.hxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * 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_ERRORBROADCASTER_HXX +#define FORMS_ERRORBROADCASTER_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/sdb/SQLErrorEvent.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //===================================================================== + //= OErrorBroadcaster + //===================================================================== + typedef ::cppu::ImplHelper1 < ::com::sun::star::sdb::XSQLErrorBroadcaster + > OErrorBroadcaster_BASE; + + class OErrorBroadcaster : public OErrorBroadcaster_BASE + { + private: + ::cppu::OBroadcastHelper& m_rBHelper; + ::cppu::OInterfaceContainerHelper m_aErrorListeners; + + protected: + OErrorBroadcaster( ::cppu::OBroadcastHelper& _rBHelper ); + virtual ~OErrorBroadcaster( ); + + void SAL_CALL disposing(); + + void SAL_CALL onError( const ::com::sun::star::sdbc::SQLException& _rException, const ::rtl::OUString& _rContextDescription ); + void SAL_CALL onError( const ::com::sun::star::sdb::SQLErrorEvent& _rException ); + + protected: + // XSQLErrorBroadcaster + virtual void SAL_CALL addSQLErrorListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLErrorListener >& _rListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeSQLErrorListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLErrorListener >& _rListener ) throw (::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_ERRORBROADCASTER_HXX + diff --git a/forms/source/component/findpos.cxx b/forms/source/component/findpos.cxx new file mode 100644 index 000000000000..87ea53b27e29 --- /dev/null +++ b/forms/source/component/findpos.cxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "sal/config.h" + +#include "findpos.hxx" + +#include "com/sun/star/uno/Sequence.hxx" +#include "comphelper/types.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include <algorithm> + +namespace detail { + +sal_Int32 findPos( + const ::rtl::OUString& aStr, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rList) +{ + const ::rtl::OUString* pStrList = rList.getConstArray(); + const ::rtl::OUString* pResult = ::std::lower_bound( + pStrList, pStrList + rList.getLength(), aStr ); + if ( ( pResult != pStrList + rList.getLength() ) && ( *pResult == aStr ) ) + return ( pResult - pStrList ); + + return -1; +} + +} diff --git a/forms/source/component/findpos.hxx b/forms/source/component/findpos.hxx new file mode 100644 index 000000000000..67fb2a8996a3 --- /dev/null +++ b/forms/source/component/findpos.hxx @@ -0,0 +1,45 @@ +/************************************************************************* + * + * 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 INCLUDED_FORMS_SOURCE_COMPONENT_FINDPOS_HXX +#define INCLUDED_FORMS_SOURCE_COMPONENT_FINDPOS_HXX + +#include "sal/config.h" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace rtl { class OUString; } + +namespace detail { + +sal_Int32 findPos( + const ::rtl::OUString& aStr, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rList); + +} + +#endif diff --git a/forms/source/component/formcontrolfont.cxx b/forms/source/component/formcontrolfont.cxx new file mode 100644 index 000000000000..1029a7678536 --- /dev/null +++ b/forms/source/component/formcontrolfont.cxx @@ -0,0 +1,551 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "formcontrolfont.hxx" +#ifndef _FRM_PROPERTY_HRC_ +#include "property.hrc" +#endif +#include "property.hxx" +#include <tools/debug.hxx> +#include <comphelper/property.hxx> +#include <comphelper/types.hxx> +#include <tools/color.hxx> +#include <toolkit/helper/emptyfontdescriptor.hxx> +#include <com/sun/star/awt/FontRelief.hpp> +#include <com/sun/star/awt/FontEmphasisMark.hpp> + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::comphelper; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + + //------------------------------------------------------------------------------ + namespace + { + Any lcl_extractFontDescriptorAggregate( sal_Int32 _nHandle, const FontDescriptor& _rFont ) + { + Any aValue; + switch ( _nHandle ) + { + case PROPERTY_ID_FONT_NAME: + aValue <<= _rFont.Name; + break; + + case PROPERTY_ID_FONT_STYLENAME: + aValue <<= _rFont.StyleName; + break; + + case PROPERTY_ID_FONT_FAMILY: + aValue <<= (sal_Int16)_rFont.Family; + break; + + case PROPERTY_ID_FONT_CHARSET: + aValue <<= (sal_Int16)_rFont.CharSet; + break; + + case PROPERTY_ID_FONT_CHARWIDTH: + aValue <<= _rFont.CharacterWidth; + break; + + case PROPERTY_ID_FONT_KERNING: + aValue <<= _rFont.Kerning; + break; + + case PROPERTY_ID_FONT_ORIENTATION: + aValue <<= _rFont.Orientation; + break; + + case PROPERTY_ID_FONT_PITCH: + aValue <<= _rFont.Pitch; + break; + + case PROPERTY_ID_FONT_TYPE: + aValue <<= _rFont.Type; + break; + + case PROPERTY_ID_FONT_WIDTH: + aValue <<= _rFont.Width; + break; + + case PROPERTY_ID_FONT_HEIGHT: + aValue <<= (float)( _rFont.Height ); + break; + + case PROPERTY_ID_FONT_WEIGHT: + aValue <<= (float)_rFont.Weight; + break; + + case PROPERTY_ID_FONT_SLANT: + aValue = makeAny(_rFont.Slant); + break; + + case PROPERTY_ID_FONT_UNDERLINE: + aValue <<= (sal_Int16)_rFont.Underline; + break; + + case PROPERTY_ID_FONT_STRIKEOUT: + aValue <<= (sal_Int16)_rFont.Strikeout; + break; + + case PROPERTY_ID_FONT_WORDLINEMODE: + aValue = makeAny( (sal_Bool)_rFont.WordLineMode ); + break; + + default: + OSL_ENSURE( sal_False, "lcl_extractFontDescriptorAggregate: invalid handle!" ); + break; + } + return aValue; + } + } + + //===================================================================== + //= FontControlModel + //===================================================================== + //--------------------------------------------------------------------- + FontControlModel::FontControlModel( bool _bToolkitCompatibleDefaults ) + :m_nFontRelief( FontRelief::NONE ) + ,m_nFontEmphasis( FontEmphasisMark::NONE ) + ,m_bToolkitCompatibleDefaults( _bToolkitCompatibleDefaults ) + { + } + + //--------------------------------------------------------------------- + FontControlModel::FontControlModel( const FontControlModel* _pOriginal ) + { + m_aFont = _pOriginal->m_aFont; + m_nFontRelief = _pOriginal->m_nFontRelief; + m_nFontEmphasis = _pOriginal->m_nFontEmphasis; + m_aTextLineColor = _pOriginal->m_aTextLineColor; + m_aTextColor = _pOriginal->m_aTextColor; + m_bToolkitCompatibleDefaults = _pOriginal->m_bToolkitCompatibleDefaults; + } + + //--------------------------------------------------------------------- + bool FontControlModel::isFontRelatedProperty( sal_Int32 _nPropertyHandle ) const + { + return isFontAggregateProperty( _nPropertyHandle ) + || ( _nPropertyHandle == PROPERTY_ID_FONT ) + || ( _nPropertyHandle == PROPERTY_ID_FONTEMPHASISMARK ) + || ( _nPropertyHandle == PROPERTY_ID_FONTRELIEF ) + || ( _nPropertyHandle == PROPERTY_ID_TEXTLINECOLOR ) + || ( _nPropertyHandle == PROPERTY_ID_TEXTCOLOR ); + } + + //--------------------------------------------------------------------- + bool FontControlModel::isFontAggregateProperty( sal_Int32 _nPropertyHandle ) const + { + return ( _nPropertyHandle == PROPERTY_ID_FONT_CHARWIDTH ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_ORIENTATION ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_WIDTH ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_NAME ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_STYLENAME ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_FAMILY ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_CHARSET ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_HEIGHT ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_WEIGHT ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_SLANT ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_UNDERLINE ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_STRIKEOUT ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_WORDLINEMODE ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_PITCH ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_KERNING ) + || ( _nPropertyHandle == PROPERTY_ID_FONT_TYPE ); + } + + //--------------------------------------------------------------------- + sal_Int32 FontControlModel::getTextColor( ) const + { + sal_Int32 nColor = COL_TRANSPARENT; + m_aTextColor >>= nColor; + return nColor; + } + + //--------------------------------------------------------------------- + sal_Int32 FontControlModel::getTextLineColor( ) const + { + sal_Int32 nColor = COL_TRANSPARENT; + m_aTextLineColor >>= nColor; + return nColor; + } + + //------------------------------------------------------------------------------ + void FontControlModel::describeFontRelatedProperties( Sequence< Property >& /* [out] */ _rProps ) const + { + sal_Int32 nPos = _rProps.getLength(); + _rProps.realloc( nPos + 21 ); + Property* pProperties = _rProps.getArray(); + + DECL_PROP2 ( FONT, FontDescriptor, BOUND, MAYBEDEFAULT ); + DECL_PROP2 ( FONTEMPHASISMARK, sal_Int16, BOUND, MAYBEDEFAULT ); + DECL_PROP2 ( FONTRELIEF, sal_Int16, BOUND, MAYBEDEFAULT ); + DECL_PROP3 ( TEXTCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ); + DECL_PROP3 ( TEXTLINECOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ); + + DECL_PROP1 ( FONT_CHARWIDTH, float, MAYBEDEFAULT ); + DECL_BOOL_PROP1 ( FONT_KERNING, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_ORIENTATION, float, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_PITCH, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_TYPE, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_WIDTH, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_NAME, ::rtl::OUString, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_STYLENAME, ::rtl::OUString, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_FAMILY, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_CHARSET, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_HEIGHT, float, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_WEIGHT, float, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_SLANT, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_UNDERLINE, sal_Int16, MAYBEDEFAULT ); + DECL_PROP1 ( FONT_STRIKEOUT, sal_Int16, MAYBEDEFAULT ); + DECL_BOOL_PROP1 ( FONT_WORDLINEMODE, MAYBEDEFAULT ); + } + + //--------------------------------------------------------------------- + void FontControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + switch( _nHandle ) + { + case PROPERTY_ID_TEXTCOLOR: + _rValue = m_aTextColor; + break; + + case PROPERTY_ID_FONTEMPHASISMARK: + _rValue <<= m_nFontEmphasis; + break; + + case PROPERTY_ID_FONTRELIEF: + _rValue <<= m_nFontRelief; + break; + + case PROPERTY_ID_TEXTLINECOLOR: + _rValue = m_aTextLineColor; + break; + + case PROPERTY_ID_FONT: + _rValue = makeAny( m_aFont ); + break; + + default: + _rValue = lcl_extractFontDescriptorAggregate( _nHandle, m_aFont ); + break; + } + } + + //--------------------------------------------------------------------- + sal_Bool FontControlModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue ) throw( IllegalArgumentException ) + { + sal_Bool bModified = sal_False; + switch( _nHandle ) + { + case PROPERTY_ID_TEXTCOLOR: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aTextColor, ::getCppuType( static_cast< const sal_Int32* >( NULL ) ) ); + break; + + case PROPERTY_ID_TEXTLINECOLOR: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aTextLineColor, ::getCppuType( static_cast< sal_Int32* >( NULL ) ) ); + break; + + case PROPERTY_ID_FONTEMPHASISMARK: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_nFontEmphasis ); + break; + + case PROPERTY_ID_FONTRELIEF: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_nFontRelief ); + break; + + case PROPERTY_ID_FONT: + { + Any aWorkAroundGccLimitation = makeAny( m_aFont ); + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, aWorkAroundGccLimitation, ::getCppuType( &m_aFont ) ); + } + break; + + case PROPERTY_ID_FONT_NAME: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aFont.Name ); + break; + + case PROPERTY_ID_FONT_STYLENAME: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aFont.StyleName ); + break; + + case PROPERTY_ID_FONT_FAMILY: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Family ); + break; + + case PROPERTY_ID_FONT_CHARSET: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.CharSet ); + break; + + case PROPERTY_ID_FONT_CHARWIDTH: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, float( m_aFont.CharacterWidth ) ); + break; + + case PROPERTY_ID_FONT_KERNING: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Kerning ); + break; + + case PROPERTY_ID_FONT_ORIENTATION: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, float( m_aFont.Orientation ) ); + break; + + case PROPERTY_ID_FONT_PITCH: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Pitch ); + break; + + case PROPERTY_ID_FONT_TYPE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Type ); + break; + + case PROPERTY_ID_FONT_WIDTH: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Width ); + break; + + case PROPERTY_ID_FONT_HEIGHT: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, float( m_aFont.Height ) ); + break; + + case PROPERTY_ID_FONT_WEIGHT: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aFont.Weight ); + break; + + case PROPERTY_ID_FONT_SLANT: + bModified = tryPropertyValueEnum( _rConvertedValue, _rOldValue, _rValue, m_aFont.Slant ); + break; + + case PROPERTY_ID_FONT_UNDERLINE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Underline ); + break; + + case PROPERTY_ID_FONT_STRIKEOUT: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_aFont.Strikeout ); + break; + + case PROPERTY_ID_FONT_WORDLINEMODE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Bool)m_aFont.WordLineMode ); + break; + + default: + DBG_ERROR( "FontControlModel::convertFastPropertyValue: no font aggregate!" ); + } + return bModified; + } + + //------------------------------------------------------------------------------ + void FontControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception ) + { + switch( _nHandle ) + { + case PROPERTY_ID_TEXTCOLOR: + m_aTextColor = _rValue; + break; + + case PROPERTY_ID_TEXTLINECOLOR: + m_aTextLineColor = _rValue; + break; + + case PROPERTY_ID_FONTEMPHASISMARK: + _rValue >>= m_nFontEmphasis; + break; + + case PROPERTY_ID_FONTRELIEF: + _rValue >>= m_nFontRelief; + break; + + case PROPERTY_ID_FONT: + _rValue >>= m_aFont; + break; + + case PROPERTY_ID_FONT_NAME: + _rValue >>= m_aFont.Name; + break; + + case PROPERTY_ID_FONT_STYLENAME: + _rValue >>= m_aFont.StyleName; + break; + + case PROPERTY_ID_FONT_FAMILY: + _rValue >>= m_aFont.Family; + break; + + case PROPERTY_ID_FONT_CHARSET: + _rValue >>= m_aFont.CharSet; + break; + + case PROPERTY_ID_FONT_CHARWIDTH: + _rValue >>= m_aFont.CharacterWidth; + break; + + case PROPERTY_ID_FONT_KERNING: + _rValue >>= m_aFont.Kerning; + break; + + case PROPERTY_ID_FONT_ORIENTATION: + _rValue >>= m_aFont.Orientation; + break; + + case PROPERTY_ID_FONT_PITCH: + _rValue >>= m_aFont.Pitch; + break; + + case PROPERTY_ID_FONT_TYPE: + _rValue >>= m_aFont.Type; + break; + + case PROPERTY_ID_FONT_WIDTH: + _rValue >>= m_aFont.Width; + break; + + case PROPERTY_ID_FONT_HEIGHT: + { + float nHeight = 0; + _rValue >>= nHeight; + m_aFont.Height = (sal_Int16)nHeight; + } + break; + + case PROPERTY_ID_FONT_WEIGHT: + _rValue >>= m_aFont.Weight; + break; + + case PROPERTY_ID_FONT_SLANT: + _rValue >>= m_aFont.Slant; + break; + + case PROPERTY_ID_FONT_UNDERLINE: + _rValue >>= m_aFont.Underline; + break; + + case PROPERTY_ID_FONT_STRIKEOUT: + _rValue >>= m_aFont.Strikeout; + break; + + case PROPERTY_ID_FONT_WORDLINEMODE: + { + sal_Bool bWordLineMode = sal_False; + _rValue >>= bWordLineMode; + m_aFont.WordLineMode = bWordLineMode; + } + break; + + default: + DBG_ERROR( "FontControlModel::setFastPropertyValue_NoBroadcast: invalid property!" ); + } + } + + //------------------------------------------------------------------------------ + Any FontControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aReturn; + // some defaults which are the same, not matter if we have toolkit-compatible + // defaults or not + bool bHandled = false; + switch( _nHandle ) + { + case PROPERTY_ID_TEXTCOLOR: + case PROPERTY_ID_TEXTLINECOLOR: + // void + bHandled = true; + break; + + case PROPERTY_ID_FONTEMPHASISMARK: + aReturn <<= FontEmphasisMark::NONE; + bHandled = true; + break; + + case PROPERTY_ID_FONTRELIEF: + aReturn <<= FontRelief::NONE; + bHandled = true; + break; + } + if ( bHandled ) + return aReturn; + + if ( m_bToolkitCompatibleDefaults ) + { + EmptyFontDescriptor aEmpty; + if ( PROPERTY_ID_FONT == _nHandle ) + return makeAny( (FontDescriptor)aEmpty ); + return lcl_extractFontDescriptorAggregate( _nHandle, aEmpty ); + } + + switch( _nHandle ) + { + case PROPERTY_ID_FONT: + aReturn <<= ::comphelper::getDefaultFont(); + break; + + case PROPERTY_ID_FONT_WORDLINEMODE: + aReturn = makeBoolAny(sal_False); + + case PROPERTY_ID_FONT_NAME: + case PROPERTY_ID_FONT_STYLENAME: + aReturn <<= ::rtl::OUString(); + + case PROPERTY_ID_FONT_FAMILY: + case PROPERTY_ID_FONT_CHARSET: + case PROPERTY_ID_FONT_SLANT: + case PROPERTY_ID_FONT_UNDERLINE: + case PROPERTY_ID_FONT_STRIKEOUT: + aReturn <<= (sal_Int16)1; + break; + + case PROPERTY_ID_FONT_KERNING: + aReturn = makeBoolAny(sal_False); + break; + + case PROPERTY_ID_FONT_PITCH: + case PROPERTY_ID_FONT_TYPE: + case PROPERTY_ID_FONT_WIDTH: + aReturn <<= (sal_Int16)0; + break; + + case PROPERTY_ID_FONT_HEIGHT: + case PROPERTY_ID_FONT_WEIGHT: + case PROPERTY_ID_FONT_CHARWIDTH: + case PROPERTY_ID_FONT_ORIENTATION: + aReturn <<= (float)0; + break; + + default: + DBG_ERROR( "FontControlModel::getPropertyDefaultByHandle: invalid property!" ); + } + + return aReturn; + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/component/imgprod.cxx b/forms/source/component/imgprod.cxx new file mode 100644 index 000000000000..7e0293be334e --- /dev/null +++ b/forms/source/component/imgprod.cxx @@ -0,0 +1,622 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" + +#include "imgprod.hxx" + +#include <vcl/bmpacc.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/svapp.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <svtools/filter.hxx> +#include <com/sun/star/io/XInputStream.hpp> + +#ifndef SVTOOLS_SOURCE_MISC_IMAGERESOURCEACCESS_HXX +#include "svtools/imageresourceaccess.hxx" +#endif +#include <comphelper/processfactory.hxx> + +// -------------------- +// - ImgProdLockBytes - +// -------------------- + +class ImgProdLockBytes : public SvLockBytes +{ + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xStmRef; + ::com::sun::star::uno::Sequence<sal_Int8> maSeq; + + ImgProdLockBytes() {}; + +public: + + ImgProdLockBytes( SvStream* pStm, sal_Bool bOwner ); + ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStreamRef ); + virtual ~ImgProdLockBytes(); + + virtual ErrCode ReadAt( sal_Size nPos, void* pBuffer, sal_Size nCount, sal_Size* pRead ) const; + virtual ErrCode WriteAt( sal_Size nPos, const void* pBuffer, sal_Size nCount, sal_Size* pWritten ); + virtual ErrCode Flush() const; + virtual ErrCode SetSize( sal_Size nSize ); + virtual ErrCode Stat( SvLockBytesStat*, SvLockBytesStatFlag ) const; +}; + +// ------------------------------------------------------------------------ + +ImgProdLockBytes::ImgProdLockBytes( SvStream* pStm, sal_Bool bOwner ) : + SvLockBytes( pStm, bOwner ) +{ +} + +// ------------------------------------------------------------------------ + +ImgProdLockBytes::ImgProdLockBytes( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStmRef ) : + xStmRef( rStmRef ) +{ + if( xStmRef.is() ) + { + const sal_uInt32 nBytesToRead = 65535; + sal_uInt32 nRead; + + do + { + ::com::sun::star::uno::Sequence< sal_Int8 > aReadSeq; + + nRead = xStmRef->readSomeBytes( aReadSeq, nBytesToRead ); + + if( nRead ) + { + const sal_uInt32 nOldLength = maSeq.getLength(); + maSeq.realloc( nOldLength + nRead ); + rtl_copyMemory( maSeq.getArray() + nOldLength, aReadSeq.getConstArray(), aReadSeq.getLength() ); + } + } + while( nBytesToRead == nRead ); + } +} + +// ------------------------------------------------------------------------ + +ImgProdLockBytes::~ImgProdLockBytes() +{ +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::ReadAt( sal_Size nPos, void* pBuffer, sal_Size nCount, sal_Size* pRead ) const +{ + if( GetStream() ) + { + ( (SvStream*) GetStream() )->ResetError(); + const ErrCode nErr = SvLockBytes::ReadAt( nPos, pBuffer, nCount, pRead ); + ( (SvStream*) GetStream() )->ResetError(); + return nErr; + } + else + { + const sal_Size nSeqLen = maSeq.getLength(); + ErrCode nErr = ERRCODE_NONE; + + if( nPos < nSeqLen ) + { + if( ( nPos + nCount ) > nSeqLen ) + nCount = nSeqLen - nPos; + + memcpy( pBuffer, maSeq.getConstArray() + nPos, nCount ); + *pRead = nCount; + } + else + *pRead = 0UL; + + return nErr; + } +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::WriteAt( sal_Size nPos, const void* pBuffer, sal_Size nCount, sal_Size* pWritten ) +{ + if( GetStream() ) + return SvLockBytes::WriteAt( nPos, pBuffer, nCount, pWritten ); + else + { + DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::WriteAt: xInputStream has no reference..." ); + return ERRCODE_IO_CANTWRITE; + } +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::Flush() const +{ + return ERRCODE_NONE; +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::SetSize( sal_Size nSize ) +{ + if( GetStream() ) + return SvLockBytes::SetSize( nSize ); + else + { + DBG_ERROR( "ImgProdLockBytes::SetSize not supported for xInputStream..." ); + return ERRCODE_IO_CANTWRITE; + } +} + +// ------------------------------------------------------------------------ + +ErrCode ImgProdLockBytes::Stat( SvLockBytesStat* pStat, SvLockBytesStatFlag eFlag ) const +{ + if( GetStream() ) + return SvLockBytes::Stat( pStat, eFlag ); + else + { + DBG_ASSERT( xStmRef.is(), "ImgProdLockBytes::Stat: xInputStream has no reference..." ); + pStat->nSize = maSeq.getLength(); + return ERRCODE_NONE; + } +} + +// ----------------- +// - ImageProducer - +// ----------------- + +ImageProducer::ImageProducer() : + mpStm ( NULL ), + mbConsInit ( sal_False ) +{ + mpGraphic = new Graphic; + DBG_ASSERT( Application::GetFilterHdl().IsSet(), "ImageProducer::ImageProducer(): No filter handler set" ); +} + +// ------------------------------------------------------------ + +ImageProducer::~ImageProducer() +{ + delete mpGraphic; + mpGraphic = NULL; + + delete mpStm; + mpStm = NULL; + + for( void* pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; +} + +// ------------------------------------------------------------ + +// ::com::sun::star::uno::XInterface +::com::sun::star::uno::Any ImageProducer::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException) +{ + ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType, + SAL_STATIC_CAST( ::com::sun::star::lang::XInitialization*, this ), + SAL_STATIC_CAST( ::com::sun::star::awt::XImageProducer*, this ) ); + return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType )); +} + +// ------------------------------------------------------------ + +void ImageProducer::addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException) +{ + DBG_ASSERT( rxConsumer.is(), "::AddConsumer(...): No consumer referenced!" ); + if( rxConsumer.is() ) + maConsList.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( rxConsumer ), LIST_APPEND ); +} + +// ------------------------------------------------------------ + +void ImageProducer::removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException) +{ + for( sal_uInt32 n = maConsList.Count(); n; ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > * pRef = (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) maConsList.GetObject( --n ); + + if( *pRef == rxConsumer ) + { + delete pRef; + maConsList.Remove( n ); + break; + } + } +} + +// ------------------------------------------------------------ + +void ImageProducer::SetImage( const ::rtl::OUString& rPath ) +{ + maURL = rPath; + mpGraphic->Clear(); + mbConsInit = sal_False; + delete mpStm; + + if ( ::svt::GraphicAccess::isSupportedURL( maURL ) ) + { + mpStm = ::svt::GraphicAccess::getImageStream( ::comphelper::getProcessServiceFactory(), maURL ); + } + else if( maURL.getLength() ) + { + SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_STD_READ ); + mpStm = pIStm ? new SvStream( new ImgProdLockBytes( pIStm, sal_True ) ) : NULL; + } + else + mpStm = NULL; +} + +// ------------------------------------------------------------ + +void ImageProducer::SetImage( SvStream& rStm ) +{ + maURL = ::rtl::OUString(); + mpGraphic->Clear(); + mbConsInit = sal_False; + + delete mpStm; + mpStm = new SvStream( new ImgProdLockBytes( &rStm, sal_False ) ); +} + +// ------------------------------------------------------------ + +void ImageProducer::setImage( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rInputStmRef ) +{ + maURL = ::rtl::OUString(); + mpGraphic->Clear(); + mbConsInit = sal_False; + delete mpStm; + + if( rInputStmRef.is() ) + mpStm = new SvStream( new ImgProdLockBytes( rInputStmRef ) ); + else + mpStm = NULL; +} + +// ------------------------------------------------------------ + +void ImageProducer::NewDataAvailable() +{ + if( ( GRAPHIC_NONE == mpGraphic->GetType() ) || mpGraphic->GetContext() ) + startProduction(); +} + +// ------------------------------------------------------------ + +void ImageProducer::startProduction() throw(::com::sun::star::uno::RuntimeException) +{ + if( maConsList.Count() || maDoneHdl.IsSet() ) + { + bool bNotifyEmptyGraphics = false; + + // valid stream or filled graphic? => update consumers + if( mpStm || ( mpGraphic->GetType() != GRAPHIC_NONE ) ) + { + // if we already have a graphic, we don't have to import again; + // graphic is cleared if a new Stream is set + if( ( mpGraphic->GetType() == GRAPHIC_NONE ) || mpGraphic->GetContext() ) + { + if ( ImplImportGraphic( *mpGraphic ) && maDoneHdl.IsSet() ) + maDoneHdl.Call( mpGraphic ); + } + + if( mpGraphic->GetType() != GRAPHIC_NONE ) + ImplUpdateData( *mpGraphic ); + else + bNotifyEmptyGraphics = true; + } + else + bNotifyEmptyGraphics = true; + + if ( bNotifyEmptyGraphics ) + { + // reset image + List aTmp; + void* pCons; + + // create temporary list to hold interfaces + for( pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + aTmp.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons ), LIST_APPEND ); + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + { + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->init( 0, 0 ); + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this ); + } + + // delete interfaces in temporary list + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; + } + } +} + +// ------------------------------------------------------------ + +sal_Bool ImageProducer::ImplImportGraphic( Graphic& rGraphic ) +{ + if( ERRCODE_IO_PENDING == mpStm->GetError() ) + mpStm->ResetError(); + + mpStm->Seek( 0UL ); + + sal_Bool bRet = GraphicConverter::Import( *mpStm, rGraphic ) == ERRCODE_NONE; + + if( ERRCODE_IO_PENDING == mpStm->GetError() ) + mpStm->ResetError(); + + return bRet; +} + +// ------------------------------------------------------------ + +void ImageProducer::ImplUpdateData( const Graphic& rGraphic ) +{ + ImplInitConsumer( rGraphic ); + + if( mbConsInit && maConsList.Count() ) + { + List aTmp; + void* pCons; + + ImplUpdateConsumer( rGraphic ); + mbConsInit = sal_False; + + // create temporary list to hold interfaces + for( pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + aTmp.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons ), LIST_APPEND ); + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->complete( ::com::sun::star::awt::ImageStatus::IMAGESTATUS_STATICIMAGEDONE, this ); + + // delete interfaces in temporary list + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; + } +} + +// ------------------------------------------------------------ + +void ImageProducer::ImplInitConsumer( const Graphic& rGraphic ) +{ + Bitmap aBmp( rGraphic.GetBitmapEx().GetBitmap() ); + BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess(); + + if( pBmpAcc ) + { + List aTmp; + void * pCons; + sal_uInt16 nPalCount = 0; + sal_uInt32 nRMask = 0; + sal_uInt32 nGMask = 0; + sal_uInt32 nBMask = 0; + sal_uInt32 nAMask = 0; + ::com::sun::star::uno::Sequence< sal_Int32 > aRGBPal; + + if( pBmpAcc->HasPalette() ) + { + nPalCount = pBmpAcc->GetPaletteEntryCount(); + + if( nPalCount ) + { + aRGBPal = ::com::sun::star::uno::Sequence< sal_Int32 >( nPalCount + 1 ); + + sal_Int32* pTmp = aRGBPal.getArray(); + + for( sal_uInt32 i = 0; i < nPalCount; i++, pTmp++ ) + { + const BitmapColor& rCol = pBmpAcc->GetPaletteColor( (sal_uInt16) i ); + + *pTmp = ( (sal_Int32) rCol.GetRed() ) << (sal_Int32)(24L); + *pTmp |= ( (sal_Int32) rCol.GetGreen() ) << (sal_Int32)(16L); + *pTmp |= ( (sal_Int32) rCol.GetBlue() ) << (sal_Int32)(8L); + *pTmp |= (sal_Int32)(0x000000ffL); + } + + if( rGraphic.IsTransparent() ) + { + // append transparent entry + *pTmp = (sal_Int32)(0xffffff00L); + mnTransIndex = nPalCount; + nPalCount++; + } + else + mnTransIndex = 0; + + } + } + else + { + nRMask = 0xff000000UL; + nGMask = 0x00ff0000UL; + nBMask = 0x0000ff00UL; + nAMask = 0x000000ffUL; + } + + // create temporary list to hold interfaces + for( pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + aTmp.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons ), LIST_APPEND ); + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + { + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->init( pBmpAcc->Width(), pBmpAcc->Height() ); + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->setColorModel( pBmpAcc->GetBitCount(), + aRGBPal, nRMask, nGMask, nBMask, nAMask ); + } + + // delete interfaces in temporary list + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; + + aBmp.ReleaseAccess( pBmpAcc ); + mbConsInit = sal_True; + } +} + +// ------------------------------------------------------------ + +void ImageProducer::ImplUpdateConsumer( const Graphic& rGraphic ) +{ + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + Bitmap aBmp( aBmpEx.GetBitmap() ); + BitmapReadAccess* pBmpAcc = aBmp.AcquireReadAccess(); + + if( pBmpAcc ) + { + List aTmp; + void* pCons; + Bitmap aMask( aBmpEx.GetMask() ); + BitmapReadAccess* pMskAcc = !!aMask ? aMask.AcquireReadAccess() : NULL; + const long nWidth = pBmpAcc->Width(); + const long nHeight = pBmpAcc->Height(); + const long nStartX = 0L; + const long nEndX = nWidth - 1L; + const long nStartY = 0L; + const long nEndY = nHeight - 1L; + const long nPartWidth = nEndX - nStartX + 1; + const long nPartHeight = nEndY - nStartY + 1; + + if( !pMskAcc ) + { + aMask = Bitmap( aBmp.GetSizePixel(), 1 ); + aMask.Erase( COL_BLACK ); + pMskAcc = aMask.AcquireReadAccess(); + } + + // create temporary list to hold interfaces + for( pCons = maConsList.First(); pCons; pCons = maConsList.Next() ) + aTmp.Insert( new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons ), LIST_APPEND ); + + if( pBmpAcc->HasPalette() ) + { + const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); + + if( mnTransIndex < 256 ) + { + ::com::sun::star::uno::Sequence<sal_Int8> aData( nPartWidth * nPartHeight ); + sal_Int8* pTmp = aData.getArray(); + + for( long nY = nStartY; nY <= nEndY; nY++ ) + { + for( long nX = nStartX; nX <= nEndX; nX++ ) + { + if( pMskAcc->GetPixel( nY, nX ) == aWhite ) + *pTmp++ = sal::static_int_cast< sal_Int8 >( + mnTransIndex ); + else + *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex(); + } + } + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->setPixelsByBytes( nStartX, nStartY, nPartWidth, nPartHeight, + aData, 0UL, nPartWidth ); + } + else + { + ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight ); + sal_Int32* pTmp = aData.getArray(); + + for( long nY = nStartY; nY <= nEndY; nY++ ) + { + for( long nX = nStartX; nX <= nEndX; nX++ ) + { + if( pMskAcc->GetPixel( nY, nX ) == aWhite ) + *pTmp++ = mnTransIndex; + else + *pTmp++ = pBmpAcc->GetPixel( nY, nX ).GetIndex(); + } + } + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, + aData, 0UL, nPartWidth ); + } + } + else + { + ::com::sun::star::uno::Sequence<sal_Int32> aData( nPartWidth * nPartHeight ); + const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); + sal_Int32* pTmp = aData.getArray(); + + for( long nY = nStartY; nY <= nEndY; nY++ ) + { + for( long nX = nStartX; nX <= nEndX; nX++, pTmp++ ) + { + const BitmapColor aCol( pBmpAcc->GetPixel( nY, nX ) ); + + *pTmp = ( (sal_Int32) aCol.GetRed() ) << (sal_Int32)(24L); + *pTmp |= ( (sal_Int32) aCol.GetGreen() ) << (sal_Int32)(16L); + *pTmp |= ( (sal_Int32) aCol.GetBlue() ) << (sal_Int32)(8L); + + if( pMskAcc->GetPixel( nY, nX ) != aWhite ) + *pTmp |= 0x000000ffUL; + } + } + + // iterate through interfaces + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + ( *(::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons )->setPixelsByLongs( nStartX, nStartY, nPartWidth, nPartHeight, + aData, 0UL, nPartWidth ); + } + + // delete interfaces in temporary list + for( pCons = aTmp.First(); pCons; pCons = aTmp.Next() ) + delete (::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer > *) pCons; + + aBmp.ReleaseAccess( pBmpAcc ); + aMask.ReleaseAccess( pMskAcc ); + } +} + +void ImageProducer::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + if ( aArguments.getLength() == 1 ) + { + ::com::sun::star::uno::Any aArg = aArguments.getConstArray()[0]; + rtl::OUString aURL; + if ( aArg >>= aURL ) + { + SetImage( aURL ); + } + } +} + +namespace frm +{ +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL ImageProducer_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ) +{ + return ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface >( + ( ::cppu::OWeakObject* ) new ImageProducer ); +} +} // namespace frm diff --git a/forms/source/component/imgprod.hxx b/forms/source/component/imgprod.hxx new file mode 100644 index 000000000000..170fc186fa73 --- /dev/null +++ b/forms/source/component/imgprod.hxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * 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 _PRODUCE_HXX +#define _PRODUCE_HXX + +#include <tools/link.hxx> +#include <tools/string.hxx> +#include <tools/list.hxx> +#include <com/sun/star/awt/ImageStatus.hpp> +#include <com/sun/star/awt/XImageConsumer.hpp> +#include <com/sun/star/awt/XImageProducer.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/weak.hxx> + + +// ----------------- +// - ImageProducer - +// ----------------- + + + +class SvStream; +class ImageConsumer; +class Graphic; +class GraphicFilter; + +namespace com { namespace sun { namespace star { namespace io { + class XInputStream; +}}}} + + +class ImageProducer : public ::com::sun::star::awt::XImageProducer, + public ::com::sun::star::lang::XInitialization, + public ::cppu::OWeakObject +{ +private: + + ::rtl::OUString maURL; + List maConsList; + Graphic* mpGraphic; + SvStream* mpStm; + sal_uInt32 mnTransIndex; + sal_Bool mbConsInit; + Link maDoneHdl; + + sal_Bool ImplImportGraphic( Graphic& rGraphic ); + void ImplUpdateData( const Graphic& rGraphic ); + void ImplInitConsumer( const Graphic& rGraphic ); + void ImplUpdateConsumer( const Graphic& rGraphic ); + +public: + + ImageProducer(); + ~ImageProducer(); + + void SetImage( const ::rtl::OUString& rPath ); + void SetImage( SvStream& rStm ); + + void NewDataAvailable(); + + void SetDoneHdl( const Link& i_rHdl ) { maDoneHdl = i_rHdl; } + const Link& GetDoneHdl() const { return maDoneHdl; } + + // ::com::sun::star::uno::XInterface + ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL acquire() throw() { OWeakObject::acquire(); } + void SAL_CALL release() throw() { OWeakObject::release(); } + + // MT: ??? + void setImage( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > & rStmRef ); + + // ::com::sun::star::awt::XImageProducer + void SAL_CALL addConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL removeConsumer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XImageConsumer >& rxConsumer ) throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL startProduction( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XInitialization + void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + +}; + +#endif // _PRODUCE_HXX diff --git a/forms/source/component/makefile.mk b/forms/source/component/makefile.mk new file mode 100644 index 000000000000..c3bfce4d3247 --- /dev/null +++ b/forms/source/component/makefile.mk @@ -0,0 +1,95 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/.. +PRJINC=.. +PRJNAME=forms +TARGET=component + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/makefile.pmk + +# --- Types ------------------------------------- + +INCPRE+=$(SOLARINCDIR)$/offuh + +# --- Files ------------------------------------- + +.IF "$(COM)"=="GCC" +NOOPTFILES= $(SLO)$/EventThread.obj +.ENDIF + +SLOFILES= $(SLO)$/Grid.obj \ + $(SLO)$/Columns.obj \ + $(SLO)$/DatabaseForm.obj \ + $(SLO)$/GroupManager.obj \ + $(SLO)$/FormsCollection.obj \ + $(SLO)$/EventThread.obj \ + $(SLO)$/File.obj \ + $(SLO)$/Edit.obj \ + $(SLO)$/EditBase.obj \ + $(SLO)$/Numeric.obj \ + $(SLO)$/Pattern.obj \ + $(SLO)$/Currency.obj \ + $(SLO)$/Date.obj \ + $(SLO)$/Time.obj \ + $(SLO)$/FormattedField.obj \ + $(SLO)$/FormattedFieldWrapper.obj \ + $(SLO)$/ListBox.obj \ + $(SLO)$/ComboBox.obj \ + $(SLO)$/GroupBox.obj \ + $(SLO)$/Hidden.obj \ + $(SLO)$/CheckBox.obj \ + $(SLO)$/RadioButton.obj \ + $(SLO)$/FixedText.obj \ + $(SLO)$/FormComponent.obj \ + $(SLO)$/clickableimage.obj \ + $(SLO)$/Button.obj \ + $(SLO)$/ImageButton.obj \ + $(SLO)$/ImageControl.obj \ + $(SLO)$/errorbroadcaster.obj \ + $(SLO)$/cloneable.obj \ + $(SLO)$/Filter.obj \ + $(SLO)$/entrylisthelper.obj \ + $(SLO)$/scrollbar.obj \ + $(SLO)$/spinbutton.obj \ + $(SLO)$/navigationbar.obj \ + $(SLO)$/formcontrolfont.obj \ + $(SLO)$/refvaluecomponent.obj \ + $(SLO)$/imgprod.obj \ + $(SLO)$/findpos.obj \ + $(SLO)$/propertybaghelper.obj \ + $(SLO)$/cachedrowset.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/forms/source/component/navigationbar.cxx b/forms/source/component/navigationbar.cxx new file mode 100644 index 000000000000..617c830f104d --- /dev/null +++ b/forms/source/component/navigationbar.cxx @@ -0,0 +1,509 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "navigationbar.hxx" +#include "frm_module.hxx" + +#include <com/sun/star/text/WritingMode2.hpp> + +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ONavigationBarModel() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::ONavigationBarModel > aAutoRegistration; +} + +//......................................................................... +namespace frm +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::container; + using namespace ::comphelper; + + namespace WritingMode2 = ::com::sun::star::text::WritingMode2; + +#define REGISTER_VOID_PROP( prop, memberAny, type ) \ + registerMayBeVoidProperty( PROPERTY_##prop, PROPERTY_ID_##prop, PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT | PropertyAttribute::MAYBEVOID, \ + &memberAny, ::getCppuType( static_cast< type* >( NULL ) ) ); + + //================================================================== + // ONavigationBarModel + //================================================================== + DBG_NAME( ONavigationBarModel ) + //------------------------------------------------------------------ + ONavigationBarModel::ONavigationBarModel( const Reference< XMultiServiceFactory >& _rxFactory ) + :OControlModel( _rxFactory, ::rtl::OUString() ) + ,FontControlModel( true ) + { + DBG_CTOR( ONavigationBarModel, NULL ); + + m_nClassId = FormComponentType::NAVIGATIONBAR; + implInitPropertyContainer(); + + getPropertyDefaultByHandle( PROPERTY_ID_DEFAULTCONTROL ) >>= m_sDefaultControl; + getPropertyDefaultByHandle( PROPERTY_ID_ICONSIZE ) >>= m_nIconSize; + getPropertyDefaultByHandle( PROPERTY_ID_BORDER ) >>= m_nBorder; + getPropertyDefaultByHandle( PROPERTY_ID_DELAY ) >>= m_nDelay; + getPropertyDefaultByHandle( PROPERTY_ID_ENABLED ) >>= m_bEnabled; + getPropertyDefaultByHandle( PROPERTY_ID_ENABLEVISIBLE ) >>= m_bEnableVisible; + getPropertyDefaultByHandle( PROPERTY_ID_SHOW_POSITION ) >>= m_bShowPosition; + getPropertyDefaultByHandle( PROPERTY_ID_SHOW_NAVIGATION ) >>= m_bShowNavigation; + getPropertyDefaultByHandle( PROPERTY_ID_SHOW_RECORDACTIONS ) >>= m_bShowActions; + getPropertyDefaultByHandle( PROPERTY_ID_SHOW_FILTERSORT ) >>= m_bShowFilterSort; + getPropertyDefaultByHandle( PROPERTY_ID_WRITING_MODE ) >>= m_nWritingMode; + getPropertyDefaultByHandle( PROPERTY_ID_CONTEXT_WRITING_MODE ) >>= m_nContextWritingMode; + } + + //------------------------------------------------------------------ + ONavigationBarModel::ONavigationBarModel( const ONavigationBarModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OControlModel( _pOriginal, _rxFactory ) + ,FontControlModel( _pOriginal ) + { + DBG_CTOR( ONavigationBarModel, NULL ); + + implInitPropertyContainer(); + + m_aTabStop = _pOriginal->m_aTabStop; + m_aBackgroundColor = _pOriginal->m_aBackgroundColor; + m_sDefaultControl = _pOriginal->m_sDefaultControl; + m_sHelpText = _pOriginal->m_sHelpText; + m_sHelpURL = _pOriginal->m_sHelpURL; + m_bEnabled = _pOriginal->m_bEnabled; + m_bEnableVisible = _pOriginal->m_bEnableVisible; + m_nIconSize = _pOriginal->m_nIconSize; + m_nBorder = _pOriginal->m_nBorder; + m_nDelay = _pOriginal->m_nDelay; + m_bShowPosition = _pOriginal->m_bShowPosition; + m_bShowNavigation = _pOriginal->m_bShowNavigation; + m_bShowActions = _pOriginal->m_bShowActions; + m_bShowFilterSort = _pOriginal->m_bShowFilterSort; + m_nWritingMode = _pOriginal->m_nWritingMode; + m_nContextWritingMode = _pOriginal->m_nContextWritingMode; + } + + //------------------------------------------------------------------ + void ONavigationBarModel::implInitPropertyContainer() + { + REGISTER_PROP_2( DEFAULTCONTROL, m_sDefaultControl, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HELPTEXT, m_sHelpText, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( HELPURL, m_sHelpURL, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( ENABLED, m_bEnabled, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( ENABLEVISIBLE, m_bEnableVisible, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( ICONSIZE, m_nIconSize, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( BORDER, m_nBorder, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( DELAY, m_nDelay, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( SHOW_POSITION, m_bShowPosition, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( SHOW_NAVIGATION, m_bShowNavigation, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( SHOW_RECORDACTIONS, m_bShowActions, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( SHOW_FILTERSORT, m_bShowFilterSort, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_2( WRITING_MODE, m_nWritingMode, BOUND, MAYBEDEFAULT ); + REGISTER_PROP_3( CONTEXT_WRITING_MODE,m_nContextWritingMode, BOUND, MAYBEDEFAULT, TRANSIENT ); + + REGISTER_VOID_PROP( TABSTOP, m_aTabStop, sal_Bool ); + REGISTER_VOID_PROP( BACKGROUNDCOLOR, m_aBackgroundColor, sal_Int32 ); + } + + //------------------------------------------------------------------ + ONavigationBarModel::~ONavigationBarModel() + { + if ( !OComponentHelper::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } + + DBG_DTOR( ONavigationBarModel, NULL ); + } + + //------------------------------------------------------------------ + Any SAL_CALL ONavigationBarModel::queryAggregation( const Type& _rType ) throw ( RuntimeException ) + { + Any aReturn = ONavigationBarModel_BASE::queryInterface( _rType ); + + if ( !aReturn.hasValue() ) + aReturn = OControlModel::queryAggregation( _rType ); + + return aReturn; + } + + //------------------------------------------------------------------ + IMPLEMENT_FORWARD_XTYPEPROVIDER2( ONavigationBarModel, OControlModel, ONavigationBarModel_BASE ) + + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( ONavigationBarModel ) + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ONavigationBarModel::getImplementationName() throw(RuntimeException) + { + return getImplementationName_Static(); + } + + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ONavigationBarModel::getSupportedServiceNames() throw(RuntimeException) + { + return getSupportedServiceNames_Static(); + } + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ONavigationBarModel::getImplementationName_Static() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.form.ONavigationBarModel" ) ); + } + + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ONavigationBarModel::getSupportedServiceNames_Static() + { + Sequence< ::rtl::OUString > aSupported = OControlModel::getSupportedServiceNames_Static(); + aSupported.realloc( aSupported.getLength() + 2 ); + + ::rtl::OUString* pArray = aSupported.getArray(); + pArray[ aSupported.getLength() - 2 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlModel" ) ); + pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_NAVTOOLBAR; + return aSupported; + } + + //------------------------------------------------------------------ + Reference< XInterface > SAL_CALL ONavigationBarModel::Create( const Reference< XMultiServiceFactory >& _rxFactory ) + { + return *( new ONavigationBarModel( _rxFactory ) ); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::disposing() + { + OControlModel::disposing( ); + } + + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ONavigationBarModel::getServiceName() throw ( RuntimeException ) + { + return FRM_SUN_COMPONENT_NAVTOOLBAR; + } + + //------------------------------------------------------------------ + #define PERSIST_TABSTOP 0x0001 + #define PERSIST_BACKGROUND 0x0002 + #define PERSIST_TEXTCOLOR 0x0004 + #define PERSIST_TEXTLINECOLOR 0x0008 + + #define PERSIST_ENABLED 0x0001 + #define PERSIST_LARGEICONS 0x0002 + // leaf a leap here - this will allow for two more icon size values to be stored compatibly + #define PERSIST_SHOW_POSITION 0x0008 + #define PERSIST_SHOW_NAVIGATION 0x0010 + #define PERSIST_SHOW_ACTIONS 0x0020 + #define PERSIST_SHOW_FILTERSORT 0x0040 + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::write( const Reference< XObjectOutputStream >& _rxOutStream ) throw ( IOException, RuntimeException ) + { + // open a section for compatibility - if we later on write additional members, + // then older versions can skip them + Reference< XDataOutputStream > xDataOut( _rxOutStream, UNO_QUERY ); + OStreamSection aEnsureBlockCompat( xDataOut ); + + // base class + OControlModel::write( _rxOutStream ); + + { + OStreamSection aEnsureCompat( xDataOut ); + // determine which properties are not void and need to be written + sal_Int32 nNonVoids = 0; + if ( m_aTabStop.hasValue() ) + nNonVoids |= PERSIST_TABSTOP; + if ( m_aBackgroundColor.hasValue() ) + nNonVoids |= PERSIST_BACKGROUND; + if ( hasTextColor() ) + nNonVoids |= PERSIST_TEXTCOLOR; + if ( hasTextLineColor() ) + nNonVoids |= PERSIST_TEXTLINECOLOR; + + _rxOutStream->writeLong( nNonVoids ); + + // the maybeboid anys + if ( nNonVoids & PERSIST_TABSTOP ) + { + sal_Bool bTabStop( sal_False ); + m_aTabStop >>= bTabStop; + _rxOutStream->writeBoolean( bTabStop ); + } + if ( nNonVoids & PERSIST_BACKGROUND ) + { + sal_Int32 nBackgroundColor = 0; + m_aBackgroundColor >>= nBackgroundColor; + _rxOutStream->writeLong( nBackgroundColor ); + } + if ( nNonVoids & PERSIST_TEXTCOLOR ) + { + _rxOutStream->writeLong( getTextColor() ); + } + if ( nNonVoids & PERSIST_TEXTLINECOLOR ) + { + _rxOutStream->writeLong( getTextLineColor() ); + } + } + + { + OStreamSection aEnsureCompat( xDataOut ); + ::comphelper::operator<<( _rxOutStream, getFont() ); + } + + // our boolean flags + sal_Int32 nFlags = 0; + if ( m_bEnabled ) nFlags |= PERSIST_ENABLED; + if ( m_nIconSize ) nFlags |= PERSIST_LARGEICONS; // at the moment, this is quasi boolean + if ( m_bShowPosition ) nFlags |= PERSIST_SHOW_POSITION; + if ( m_bShowNavigation ) nFlags |= PERSIST_SHOW_NAVIGATION; + if ( m_bShowActions ) nFlags |= PERSIST_SHOW_ACTIONS; + if ( m_bShowFilterSort ) nFlags |= PERSIST_SHOW_FILTERSORT; + _rxOutStream->writeLong( nFlags ); + + // our strings + _rxOutStream->writeUTF( m_sHelpText ); + _rxOutStream->writeUTF( m_sHelpURL ); + _rxOutStream->writeUTF( m_sDefaultControl ); + + // misc + _rxOutStream->writeShort( m_nBorder ); + _rxOutStream->writeLong ( m_nDelay ); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::read( const Reference< XObjectInputStream >& _rxInStream ) throw ( IOException, RuntimeException ) + { + Reference< XDataInputStream > xDataIn( _rxInStream, UNO_QUERY ); + OStreamSection aEnsureBlockCompat( xDataIn ); + + // base class + OControlModel::read( _rxInStream ); + + { + OStreamSection aEnsureCompat( xDataIn ); + // determine which properties were non-void + sal_Int32 nNonVoids = _rxInStream->readLong( ); + + // the maybeboid anys + if ( nNonVoids & PERSIST_TABSTOP ) + m_aTabStop = makeAny( _rxInStream->readBoolean() ); + else + m_aTabStop.clear(); + + if ( nNonVoids & PERSIST_BACKGROUND ) + m_aBackgroundColor = makeAny( _rxInStream->readLong() ); + else + m_aBackgroundColor.clear(); + + if ( nNonVoids & PERSIST_TEXTCOLOR ) + setTextColor( _rxInStream->readLong() ); + else + clearTextColor(); + + if ( nNonVoids & PERSIST_TEXTLINECOLOR ) + setTextLineColor( _rxInStream->readLong() ); + else + clearTextLineColor(); + } + + { + OStreamSection aEnsureCompat( xDataIn ); + FontDescriptor aFont; + ::comphelper::operator>>( _rxInStream, aFont ); + setFont( aFont ); + } + + // our boolean flags + sal_Int32 nFlags = _rxInStream->readLong( ); + m_bEnabled = ( nFlags & PERSIST_ENABLED ) ? sal_True : sal_False; + m_nIconSize = ( nFlags & PERSIST_LARGEICONS ) ? 1 : 0; + m_bShowPosition = ( nFlags & PERSIST_SHOW_POSITION ) ? sal_True : sal_False; + m_bShowNavigation = ( nFlags & PERSIST_SHOW_NAVIGATION ) ? sal_True : sal_False; + m_bShowActions = ( nFlags & PERSIST_SHOW_ACTIONS ) ? sal_True : sal_False; + m_bShowFilterSort = ( nFlags & PERSIST_SHOW_FILTERSORT ) ? sal_True : sal_False; + + // our strings + m_sHelpText = _rxInStream->readUTF( ); + m_sHelpURL = _rxInStream->readUTF( ); + m_sDefaultControl = _rxInStream->readUTF( ); + + // misc + m_nBorder = _rxInStream->readShort(); + m_nDelay = _rxInStream->readLong(); + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + if ( isRegisteredProperty( _nHandle ) ) + { + OPropertyContainerHelper::getFastPropertyValue( _rValue, _nHandle ); + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + FontControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + else + { + OControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //------------------------------------------------------------------ + sal_Bool SAL_CALL ONavigationBarModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue ) throw( IllegalArgumentException ) + { + sal_Bool bModified = sal_False; + + if ( isRegisteredProperty( _nHandle ) ) + { + bModified = OPropertyContainerHelper::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + bModified = FontControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + else + { + bModified = OControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + } + + return bModified; + } + + //------------------------------------------------------------------ + void SAL_CALL ONavigationBarModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception ) + { + if ( isRegisteredProperty( _nHandle ) ) + { + OPropertyContainerHelper::setFastPropertyValue( _nHandle, _rValue ); + } + else if ( isFontRelatedProperty( _nHandle ) ) + { + FontDescriptor aOldFont( getFont() ); + + FontControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + + if ( isFontAggregateProperty( _nHandle ) ) + firePropertyChange( PROPERTY_ID_FONT, makeAny( getFont() ), makeAny( aOldFont ) ); + } + else + { + OControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + } + } + + //------------------------------------------------------------------ + Any ONavigationBarModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aDefault; + + switch ( _nHandle ) + { + case PROPERTY_ID_TABSTOP: + case PROPERTY_ID_BACKGROUNDCOLOR: + /* void */ + break; + case PROPERTY_ID_WRITING_MODE: + case PROPERTY_ID_CONTEXT_WRITING_MODE: + aDefault <<= WritingMode2::CONTEXT; + break; + + case PROPERTY_ID_ENABLED: + case PROPERTY_ID_ENABLEVISIBLE: + case PROPERTY_ID_SHOW_POSITION: + case PROPERTY_ID_SHOW_NAVIGATION: + case PROPERTY_ID_SHOW_RECORDACTIONS: + case PROPERTY_ID_SHOW_FILTERSORT: + aDefault <<= (sal_Bool)sal_True; + break; + + case PROPERTY_ID_ICONSIZE: + aDefault <<= (sal_Int16)0; + break; + + case PROPERTY_ID_DEFAULTCONTROL: + aDefault <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.control.NavigationToolBar" ) ); + break; + + case PROPERTY_ID_HELPTEXT: + case PROPERTY_ID_HELPURL: + aDefault <<= ::rtl::OUString(); + break; + + case PROPERTY_ID_BORDER: + aDefault <<= (sal_Int16)0; + break; + + case PROPERTY_ID_DELAY: + aDefault <<= (sal_Int32)20; + break; + + default: + if ( isFontRelatedProperty( _nHandle ) ) + aDefault = FontControlModel::getPropertyDefaultByHandle( _nHandle ); + else + aDefault = OControlModel::getPropertyDefaultByHandle( _nHandle ); + } + return aDefault; + } + + //------------------------------------------------------------------ + void ONavigationBarModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 1, OControlModel ) + DECL_PROP2( TABINDEX, sal_Int16, BOUND, MAYBEDEFAULT ); + END_DESCRIBE_PROPERTIES(); + + // properties which the OPropertyContainerHelper is responsible for + Sequence< Property > aContainedProperties; + describeProperties( aContainedProperties ); + + // properties which the FontControlModel is responsible for + Sequence< Property > aFontProperties; + describeFontRelatedProperties( aFontProperties ); + + _rProps = concatSequences( + aContainedProperties, + aFontProperties, + _rProps + ); + } + +//......................................................................... +} // namespace frm +//......................................................................... diff --git a/forms/source/component/navigationbar.hxx b/forms/source/component/navigationbar.hxx new file mode 100644 index 000000000000..d57c6d1542ac --- /dev/null +++ b/forms/source/component/navigationbar.hxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * 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_COMPONENT_NAVIGATION_BAR_HXX +#define FORMS_COMPONENT_NAVIGATION_BAR_HXX + +#include "FormComponent.hxx" +#include <com/sun/star/io/XPersistObject.hpp> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/propertycontainerhelper.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include "formcontrolfont.hxx" + +#include <set> + +//......................................................................... +namespace frm +{ +//......................................................................... + + //================================================================== + // ONavigationBarModel + //================================================================== + typedef ::cppu::ImplHelper1 < ::com::sun::star::awt::XControlModel + > ONavigationBarModel_BASE; + + class ONavigationBarModel + :public OControlModel + ,public FontControlModel + ,public OPropertyContainerHelper + ,public ONavigationBarModel_BASE + { + // <properties> + ::com::sun::star::uno::Any m_aTabStop; + ::com::sun::star::uno::Any m_aBackgroundColor; + ::rtl::OUString m_sDefaultControl; + ::rtl::OUString m_sHelpText; + ::rtl::OUString m_sHelpURL; + sal_Int16 m_nIconSize; + sal_Int16 m_nBorder; + sal_Int32 m_nDelay; + sal_Bool m_bEnabled; + sal_Bool m_bEnableVisible; + sal_Bool m_bShowPosition; + sal_Bool m_bShowNavigation; + sal_Bool m_bShowActions; + sal_Bool m_bShowFilterSort; + sal_Int16 m_nWritingMode; + sal_Int16 m_nContextWritingMode; + // </properties> + + public: + DECLARE_DEFAULT_LEAF_XTOR( ONavigationBarModel ); + + // XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_Static(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory ); + + protected: + // UNO + DECLARE_UNO3_AGG_DEFAULTS( ONavigationBarModel, OControlModel ); + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // 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); + + // 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); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // prevent method hiding + using OControlModel::disposing; + using OControlModel::getFastPropertyValue; + + protected: + DECLARE_XCLONEABLE(); + + private: + void implInitPropertyContainer(); + }; + +//......................................................................... +} // namespace frm +//......................................................................... + +#endif // FORMS_COMPONENT_NAVIGATION_BAR_HXX + diff --git a/forms/source/component/propertybaghelper.cxx b/forms/source/component/propertybaghelper.cxx new file mode 100644 index 000000000000..0b049043cb28 --- /dev/null +++ b/forms/source/component/propertybaghelper.cxx @@ -0,0 +1,369 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "propertybaghelper.hxx" + +#include "property.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/PropertyExistException.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/NotRemoveableException.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +#include <comphelper/sequence.hxx> +#include <rtl/logfile.hxx> +#include "rtl/instance.hxx" + + +#define NEW_HANDLE_BASE 10000 + +//........................................................................ +namespace frm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::beans::Property; + using ::com::sun::star::uno::Any; + using ::com::sun::star::beans::PropertyExistException; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::beans::XMultiPropertySet; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::beans::NotRemoveableException; + using ::com::sun::star::beans::UnknownPropertyException; + /** === end UNO using === **/ + namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; + + //==================================================================== + //= helper + //==================================================================== + namespace + { + //---------------------------------------------------------------- + static ::comphelper::IPropertyInfoService& lcl_getPropertyInfos() + { + static ConcreteInfoService s_aPropInfos; + return s_aPropInfos; + } + } + + //==================================================================== + //= PropertyBagHelper + //==================================================================== + //-------------------------------------------------------------------- + PropertyBagHelper::PropertyBagHelper( IPropertyBagHelperContext& _rContext ) + :m_rContext( _rContext ) + ,m_pPropertyArrayHelper( NULL ) + ,m_bDisposed( false ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::PropertyBagHelper" ); + } + + //-------------------------------------------------------------------- + PropertyBagHelper::~PropertyBagHelper() + { + delete m_pPropertyArrayHelper, m_pPropertyArrayHelper = NULL; + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::dispose() + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::dispose" ); + m_bDisposed = true; + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::impl_nts_checkDisposed_throw() const + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::impl_nts_checkDisposed_throw" ); + if ( m_bDisposed ) + throw DisposedException(); + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::impl_nts_invalidatePropertySetInfo() + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::impl_nts_invalidatePropertySetInfo" ); + delete m_pPropertyArrayHelper, m_pPropertyArrayHelper = NULL; + } + + //-------------------------------------------------------------------- + sal_Int32 PropertyBagHelper::impl_findFreeHandle( const ::rtl::OUString& _rPropertyName ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::impl_findFreeHandle" ); + ::comphelper::OPropertyArrayAggregationHelper& rPropInfo( impl_ts_getArrayHelper() ); + + // check the preferred handle + sal_Int32 nHandle = lcl_getPropertyInfos().getPreferedPropertyId( _rPropertyName ); + if ( ( nHandle != -1 ) && rPropInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) ) + nHandle = -1; + + // seach a free handle in <math>F_1009</math> + if ( nHandle == -1 ) + { + sal_Int32 nPrime = 1009; + sal_Int32 nFactor = 11; + sal_Int32 nNum = nFactor; + while ( nNum != 1 ) + { + if ( !rPropInfo.fillPropertyMembersByHandle( NULL, NULL, nNum + NEW_HANDLE_BASE ) ) + { + // handle not used, yet + nHandle = nNum + NEW_HANDLE_BASE; + break; + } + nNum = ( nNum * nFactor ) % nPrime; + } + } + + // search a free handle greater NEW_HANDLE_BASE + if ( nHandle == -1 ) + { + nHandle = NEW_HANDLE_BASE + 1009; + while ( rPropInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) ) + ++nHandle; + } + + return nHandle; + } + + //-------------------------------------------------------------------- + ::comphelper::OPropertyArrayAggregationHelper& PropertyBagHelper::impl_ts_getArrayHelper() const + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::impl_ts_getArrayHelper" ); + //::osl::MutexGuard aGuard( m_rContext.getMutex() ); + OPropertyArrayAggregationHelper* p = m_pPropertyArrayHelper; + if ( !p ) + { + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + p = m_pPropertyArrayHelper; + if ( !p ) + { + // our own fixed and our aggregate's properties + Sequence< Property > aFixedProps; + Sequence< Property > aAggregateProps; + m_rContext.describeFixedAndAggregateProperties( aFixedProps, aAggregateProps ); + + // our dynamic properties + Sequence< Property > aDynamicProps; + m_aDynamicProperties.describeProperties( aDynamicProps ); + + Sequence< Property > aOwnProps( + ::comphelper::concatSequences( aFixedProps, aDynamicProps ) ); + + p = new OPropertyArrayAggregationHelper( aOwnProps, aAggregateProps, &lcl_getPropertyInfos(), NEW_HANDLE_BASE ); + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + const_cast< PropertyBagHelper* >( this )->m_pPropertyArrayHelper = p; + } + } // if ( !p ) + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + return *p; + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::addProperty" ); + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + impl_nts_checkDisposed_throw(); + + //---------------------------------------------- + // check name sanity + ::comphelper::OPropertyArrayAggregationHelper& aPropInfo( impl_ts_getArrayHelper() ); + if ( aPropInfo.hasPropertyByName( _rName ) ) + throw PropertyExistException( _rName, m_rContext.getPropertiesInterface() ); + + //---------------------------------------------- + // normalize the REMOVEABLE attribute - the FormComponent service + // requires that all dynamic properties are REMOVEABLE + _nAttributes |= PropertyAttribute::REMOVEABLE; + + //---------------------------------------------- + // find a free handle + sal_Int32 nHandle = impl_findFreeHandle( _rName ); + + //---------------------------------------------- + // register the property, and invalidate our property meta data + m_aDynamicProperties.addProperty( _rName, nHandle, _nAttributes, _rInitialValue ); + impl_nts_invalidatePropertySetInfo(); + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::removeProperty( const ::rtl::OUString& _rName ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::removeProperty" ); + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + impl_nts_checkDisposed_throw(); + + // check whether it's removeable at all + Reference< XMultiPropertySet > xMe( m_rContext.getPropertiesInterface(), UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xPSI( xMe->getPropertySetInfo(), UNO_QUERY_THROW ); + Property aProperty( xPSI->getPropertyByName( _rName ) ); + if ( ( aProperty.Attributes & PropertyAttribute::REMOVEABLE ) == 0 ) + throw NotRemoveableException( _rName, xMe ); + + m_aDynamicProperties.removeProperty( _rName ); + impl_nts_invalidatePropertySetInfo(); + } + + //-------------------------------------------------------------------- + namespace + { + //---------------------------------------------------------------- + struct SelectNameOfProperty : public ::std::unary_function< Property, ::rtl::OUString > + { + const ::rtl::OUString& operator()( const Property& _rProp ) const { return _rProp.Name; } + }; + + //---------------------------------------------------------------- + struct SelectNameOfPropertyValue : public ::std::unary_function< PropertyValue, ::rtl::OUString > + { + const ::rtl::OUString& operator()( const PropertyValue& _rProp ) const { return _rProp.Name; } + }; + + //---------------------------------------------------------------- + struct SelectValueOfPropertyValue : public ::std::unary_function< PropertyValue, Any > + { + const Any& operator()( const PropertyValue& _rProp ) const { return _rProp.Value; } + }; + + //---------------------------------------------------------------- + struct PropertyValueLessByName : public ::std::binary_function< PropertyValue, PropertyValue, bool > + { + bool operator()( const PropertyValue& _lhs, const PropertyValue _rhs ) const + { + return _lhs.Name < _rhs.Name; + } + }; + } + + //-------------------------------------------------------------------- + Sequence< PropertyValue > PropertyBagHelper::getPropertyValues() + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::getPropertyValues" ); + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + impl_nts_checkDisposed_throw(); + + Reference< XMultiPropertySet > xMe( m_rContext.getPropertiesInterface(), UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xPSI( xMe->getPropertySetInfo(), UNO_QUERY_THROW ); + + Sequence< Property > aProperties( xPSI->getProperties() ); + Sequence< ::rtl::OUString > aPropertyNames( aProperties.getLength() ); + ::std::transform( aProperties.getConstArray(), aProperties.getConstArray() + aProperties.getLength(), + aPropertyNames.getArray(), SelectNameOfProperty() ); + + Sequence< Any > aValues; + try + { + aValues = xMe->getPropertyValues( aPropertyNames ); + + if ( aValues.getLength() != aPropertyNames.getLength() ) + throw RuntimeException(); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + Sequence< PropertyValue > aPropertyValues( aValues.getLength() ); + PropertyValue* pPropertyValue = aPropertyValues.getArray(); + + const ::rtl::OUString* pName = aPropertyNames.getConstArray(); + const ::rtl::OUString* pNameEnd = aPropertyNames.getConstArray() + aPropertyNames.getLength(); + const Any* pValue = aValues.getConstArray(); + for ( ; pName != pNameEnd; ++pName, ++pValue, ++pPropertyValue ) + { + pPropertyValue->Name = *pName; + pPropertyValue->Value = *pValue; + } + + return aPropertyValues; + } + + //-------------------------------------------------------------------- + void PropertyBagHelper::setPropertyValues( const Sequence< PropertyValue >& _rProps ) + { + // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "PropertyBagHelper::setPropertyValues" ); + ::osl::ClearableMutexGuard aGuard( m_rContext.getMutex() ); + impl_nts_checkDisposed_throw(); + + sal_Int32 nPropertyValues = _rProps.getLength(); + + // XMultiPropertySet::setPropertyValues expects its arguments to be sorted by name + // while XPropertyAccess::setPropertyValues doesn't. So first of all, sort. + Sequence< PropertyValue > aSortedProps( _rProps ); + ::std::sort( aSortedProps.getArray(), aSortedProps.getArray() + nPropertyValues, PropertyValueLessByName() ); + + // also, XPropertyAccess::setPropertyValues is expected to throw an UnknownPropertyException + // for unsupported properties, while XMultiPropertySet::setPropertyValues is expected to ignore + // those. So, check for unsupported properties first. + ::comphelper::OPropertyArrayAggregationHelper& rArrayHelper( impl_ts_getArrayHelper() ); + for ( const PropertyValue* pProperties = aSortedProps.getConstArray(); + pProperties != aSortedProps.getConstArray() + nPropertyValues; + ++pProperties + ) + { + if ( !rArrayHelper.hasPropertyByName( pProperties->Name ) ) + throw UnknownPropertyException( pProperties->Name, m_rContext.getPropertiesInterface() ); + } + + // Now finally split into a Name and a Value sequence, and forward to + // XMultiPropertySet::setPropertyValues + Sequence< ::rtl::OUString > aNames( nPropertyValues ); + ::std::transform( aSortedProps.getConstArray(), aSortedProps.getConstArray() + nPropertyValues, + aNames.getArray(), SelectNameOfPropertyValue() ); + + Sequence< Any > aValues( nPropertyValues ); + ::std::transform( aSortedProps.getConstArray(), aSortedProps.getConstArray() + nPropertyValues, + aValues.getArray(), SelectValueOfPropertyValue() ); + + Reference< XMultiPropertySet > xMe( m_rContext.getPropertiesInterface(), UNO_QUERY_THROW ); + + aGuard.clear(); + xMe->setPropertyValues( aNames, aValues ); + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/component/refvaluecomponent.cxx b/forms/source/component/refvaluecomponent.cxx new file mode 100644 index 000000000000..3061a275378b --- /dev/null +++ b/forms/source/component/refvaluecomponent.cxx @@ -0,0 +1,301 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "refvaluecomponent.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +#include <list> + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form::binding; + + //==================================================================== + //= + //==================================================================== + //-------------------------------------------------------------------- + OReferenceValueComponent::OReferenceValueComponent( const Reference< XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _rUnoControlModelTypeName, const ::rtl::OUString& _rDefault, sal_Bool _bSupportNoCheckRefValue ) + :OBoundControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False, sal_True, sal_True ) + ,m_eDefaultChecked( STATE_NOCHECK ) + ,m_bSupportSecondRefValue( _bSupportNoCheckRefValue ) + { + } + + //-------------------------------------------------------------------- + OReferenceValueComponent::OReferenceValueComponent( const OReferenceValueComponent* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + { + m_sReferenceValue = _pOriginal->m_sReferenceValue; + m_sNoCheckReferenceValue = _pOriginal->m_sNoCheckReferenceValue; + m_eDefaultChecked = _pOriginal->m_eDefaultChecked; + m_bSupportSecondRefValue = _pOriginal->m_bSupportSecondRefValue; + + calculateExternalValueType(); + } + + //-------------------------------------------------------------------- + OReferenceValueComponent::~OReferenceValueComponent() + { + } + + //-------------------------------------------------------------------- + void OReferenceValueComponent::setReferenceValue( const ::rtl::OUString& _rRefValue ) + { + m_sReferenceValue = _rRefValue; + calculateExternalValueType(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OReferenceValueComponent::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + switch ( _nHandle ) + { + case PROPERTY_ID_REFVALUE: _rValue <<= m_sReferenceValue; break; + case PROPERTY_ID_DEFAULT_STATE: _rValue <<= (sal_Int16)m_eDefaultChecked; break; + + case PROPERTY_ID_UNCHECKED_REFVALUE: + OSL_ENSURE( m_bSupportSecondRefValue, "OReferenceValueComponent::getFastPropertyValue: not supported!" ); + _rValue <<= m_sNoCheckReferenceValue; + break; + + default: + OBoundControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OReferenceValueComponent::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) + { + switch ( _nHandle ) + { + case PROPERTY_ID_REFVALUE : + OSL_VERIFY( _rValue >>= m_sReferenceValue ); + calculateExternalValueType(); + break; + + case PROPERTY_ID_UNCHECKED_REFVALUE: + OSL_ENSURE( m_bSupportSecondRefValue, "OReferenceValueComponent::setFastPropertyValue_NoBroadcast: not supported!" ); + OSL_VERIFY( _rValue >>= m_sNoCheckReferenceValue ); + break; + + case PROPERTY_ID_DEFAULT_STATE: + { + sal_Int16 nDefaultChecked( (sal_Int16)STATE_NOCHECK ); + OSL_VERIFY( _rValue >>= nDefaultChecked ); + m_eDefaultChecked = (ToggleState)nDefaultChecked; + resetNoBroadcast(); + } + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + } + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OReferenceValueComponent::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException) + { + sal_Bool bModified = sal_False; + switch ( _nHandle ) + { + case PROPERTY_ID_REFVALUE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_sReferenceValue ); + break; + + case PROPERTY_ID_UNCHECKED_REFVALUE: + OSL_ENSURE( m_bSupportSecondRefValue, "OReferenceValueComponent::convertFastPropertyValue: not supported!" ); + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_sNoCheckReferenceValue ); + break; + + case PROPERTY_ID_DEFAULT_STATE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_eDefaultChecked ); + break; + + default: + bModified = OBoundControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + break; + } + return bModified; + } + + //------------------------------------------------------------------------------ + Any OReferenceValueComponent::getDefaultForReset() const + { + return makeAny( (sal_Int16)m_eDefaultChecked ); + } + + //-------------------------------------------------------------------- + void OReferenceValueComponent::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( m_bSupportSecondRefValue ? 3 : 2, OBoundControlModel ) + DECL_PROP1( REFVALUE, ::rtl::OUString, BOUND ); + DECL_PROP1( DEFAULT_STATE, sal_Int16, BOUND ); + if ( m_bSupportSecondRefValue ) + { + DECL_PROP1( UNCHECKED_REFVALUE, ::rtl::OUString, BOUND ); + } + END_DESCRIBE_PROPERTIES(); + } + + //----------------------------------------------------------------------------- + Sequence< Type > OReferenceValueComponent::getSupportedBindingTypes() + { + ::std::list< Type > aTypes; + aTypes.push_back( ::getCppuType( static_cast< sal_Bool* >( NULL ) ) ); + + if ( m_sReferenceValue.getLength() ) + aTypes.push_front( ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ) ); + // push_front, because this is the preferred type + + Sequence< Type > aTypesRet( aTypes.size() ); + ::std::copy( aTypes.begin(), aTypes.end(), aTypesRet.getArray() ); + return aTypesRet; + } + + //----------------------------------------------------------------------------- + Any OReferenceValueComponent::translateExternalValueToControlValue( const Any& _rExternalValue ) const + { + sal_Int16 nState = STATE_DONTKNOW; + + sal_Bool bExternalState = sal_False; + ::rtl::OUString sExternalValue; + if ( _rExternalValue >>= bExternalState ) + { + nState = ::sal::static_int_cast< sal_Int16 >( bExternalState ? STATE_CHECK : STATE_NOCHECK ); + } + else if ( _rExternalValue >>= sExternalValue ) + { + if ( sExternalValue == m_sReferenceValue ) + nState = STATE_CHECK; + else + { + if ( !m_bSupportSecondRefValue || ( sExternalValue == m_sNoCheckReferenceValue ) ) + nState = STATE_NOCHECK; + else + nState = STATE_DONTKNOW; + } + } + else if ( !_rExternalValue.hasValue() ) + { + nState = STATE_DONTKNOW; + } + else + { + OSL_ENSURE( false, "OReferenceValueComponent::translateExternalValueToControlValue: unexpected value type!" ); + } + + return makeAny( nState ); + } + + //----------------------------------------------------------------------------- + Any OReferenceValueComponent::translateControlValueToExternalValue( ) const + { + Any aExternalValue; + + try + { + Any aControlValue( m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) ); + sal_Int16 nControlValue = STATE_DONTKNOW; + aControlValue >>= nControlValue; + + bool bBooleanExchange = getExternalValueType().getTypeClass() == TypeClass_BOOLEAN; + bool bStringExchange = getExternalValueType().getTypeClass() == TypeClass_STRING; + OSL_ENSURE( bBooleanExchange || bStringExchange, + "OReferenceValueComponent::translateControlValueToExternalValue: unexpected value exchange type!" ); + + switch( nControlValue ) + { + case STATE_CHECK: + if ( bBooleanExchange ) + { + aExternalValue <<= (sal_Bool)sal_True; + } + else if ( bStringExchange ) + { + aExternalValue <<= m_sReferenceValue; + } + break; + + case STATE_NOCHECK: + if ( bBooleanExchange ) + { + aExternalValue <<= (sal_Bool)sal_False; + } + else if ( bStringExchange ) + { + aExternalValue <<= m_bSupportSecondRefValue ? m_sNoCheckReferenceValue : ::rtl::OUString(); + } + break; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OReferenceValueComponent::translateControlValueToExternalValue: caught an exception!" ); + } + + return aExternalValue; + } + + //----------------------------------------------------------------------------- + Any OReferenceValueComponent::translateControlValueToValidatableValue( ) const + { + if ( !m_xAggregateSet.is() ) + return Any(); + + Any aControlValue( m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) ); + sal_Int16 nControlValue = STATE_DONTKNOW; + aControlValue >>= nControlValue; + + Any aValidatableValue; + switch ( nControlValue ) + { + case STATE_CHECK: + aValidatableValue <<= (sal_Bool)sal_True; + break; + case STATE_NOCHECK: + aValidatableValue <<= (sal_Bool)sal_False; + break; + } + return aValidatableValue; + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/forms/source/component/refvaluecomponent.hxx b/forms/source/component/refvaluecomponent.hxx new file mode 100644 index 000000000000..dedc86c315be --- /dev/null +++ b/forms/source/component/refvaluecomponent.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * 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_SOURCE_COMPONENT_REFVALUECOMPONENT_HXX +#define FORMS_SOURCE_COMPONENT_REFVALUECOMPONENT_HXX + +#include "FormComponent.hxx" +#include "togglestate.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OReferenceValueComponent + //==================================================================== + /** a OBoundControlModel which features the exchange of a reference value + */ + class OReferenceValueComponent : public OBoundControlModel + { + private: + // <properties> + ::rtl::OUString m_sReferenceValue; // the reference value to use for data exchange + ::rtl::OUString m_sNoCheckReferenceValue; // the reference value to be exchanged when the control is not checked + ToggleState m_eDefaultChecked; // the default check state + // </properties> + + sal_Bool m_bSupportSecondRefValue; // do we support the SecondaryRefValue property? + + protected: + const ::rtl::OUString& getReferenceValue() const { return m_sReferenceValue; } + void setReferenceValue( const ::rtl::OUString& _rRefValue ); + + const ::rtl::OUString& getNoCheckReferenceValue() const { return m_sNoCheckReferenceValue; } + + ToggleState getDefaultChecked() const { return m_eDefaultChecked; } + void setDefaultChecked( ToggleState _eChecked ) { m_eDefaultChecked = _eChecked; } + + protected: + OReferenceValueComponent( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, + const ::rtl::OUString& _rUnoControlModelTypeName, + const ::rtl::OUString& _rDefault, + sal_Bool _bSupportNoCheckRefValue = sal_False + ); + DECLARE_DEFAULT_CLONE_CTOR( OReferenceValueComponent ) + DECLARE_DEFAULT_DTOR( OReferenceValueComponent ); + + // OPropertySet and friends + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + 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 describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + using ::cppu::OPropertySetHelper::getFastPropertyValue; + + // OBoundControlModel overridables + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + + virtual ::com::sun::star::uno::Any + translateControlValueToValidatableValue( ) const; + + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + }; + +//........................................................................ +} // namespace frm +//........................................................................ + +#endif // FORMS_SOURCE_COMPONENT_REFVALUECOMPONENT_HXX + diff --git a/forms/source/component/scrollbar.cxx b/forms/source/component/scrollbar.cxx new file mode 100644 index 000000000000..5bd5744164a6 --- /dev/null +++ b/forms/source/component/scrollbar.cxx @@ -0,0 +1,319 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "scrollbar.hxx" +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> +#include <rtl/math.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_OScrollBarModel() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::OScrollBarModel > aRegisterModel; +} + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::form::binding; + + //==================================================================== + //= helper + //==================================================================== + //-------------------------------------------------------------------- + Any translateExternalDoubleToControlIntValue( + const Any& _rExternalValue, const Reference< XPropertySet >& _rxProperties, + const ::rtl::OUString& _rMinValueName, const ::rtl::OUString& _rMaxValueName ) + { + OSL_ENSURE( _rxProperties.is(), "translateExternalDoubleToControlIntValue: no aggregate!?" ); + + sal_Int32 nControlValue( 0 ); + double nExternalValue = 0; + if ( _rExternalValue >>= nExternalValue ) + { + if ( ::rtl::math::isInf( nExternalValue ) ) + { + // set the minimum or maximum of the scroll values + ::rtl::OUString sLimitPropertyName = ::rtl::math::isSignBitSet( nExternalValue ) + ? _rMinValueName : _rMaxValueName; + if ( _rxProperties.is() ) + _rxProperties->getPropertyValue( sLimitPropertyName ) >>= nControlValue; + } + else + { + nControlValue = (sal_Int32)::rtl::math::round( nExternalValue ); + } + } + else + { + if ( _rxProperties.is() ) + _rxProperties->getPropertyValue( _rMinValueName ) >>= nControlValue; + } + + return makeAny( nControlValue ); + } + + //-------------------------------------------------------------------- + Any translateControlIntToExternalDoubleValue( const Any& _rControlIntValue ) + { + Any aExternalDoubleValue; + sal_Int32 nScrollValue = 0; + if ( _rControlIntValue >>= nScrollValue ) + aExternalDoubleValue <<= (double)nScrollValue; + else + { + OSL_ENSURE( sal_False, "translateControlIntToExternalDoubleValue: no integer scroll value!" ); + // aExternalDoubleValue is void here, which is okay for this purpose ... + } + + return aExternalDoubleValue; + } + + //==================================================================== + //= OScrollBarModel + //==================================================================== + //-------------------------------------------------------------------- + DBG_NAME( OScrollBarModel ) + //-------------------------------------------------------------------- + OScrollBarModel::OScrollBarModel( const Reference<XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_SCROLLBAR, VCL_CONTROL_SCROLLBAR, sal_True, sal_True, sal_False ) + ,m_nDefaultScrollValue( 0 ) + { + DBG_CTOR( OScrollBarModel, NULL ); + + m_nClassId = FormComponentType::SCROLLBAR; + initValueProperty( PROPERTY_SCROLL_VALUE, PROPERTY_ID_SCROLL_VALUE ); + } + + //-------------------------------------------------------------------- + OScrollBarModel::OScrollBarModel( const OScrollBarModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + { + DBG_CTOR( OScrollBarModel, NULL ); + m_nDefaultScrollValue = _pOriginal->m_nDefaultScrollValue; + } + + //-------------------------------------------------------------------- + OScrollBarModel::~OScrollBarModel( ) + { + DBG_DTOR( OScrollBarModel, NULL ); + } + + //-------------------------------------------------------------------- + IMPLEMENT_SERVICE_REGISTRATION_2( OScrollBarModel, OControlModel, FRM_SUN_COMPONENT_SCROLLBAR, BINDABLE_INTEGER_VALUE_RANGE ) + // note that we're passing OControlModel as "base class". This is because + // OBoundControlModel, our real base class, claims to support the DataAwareControlModel + // service, which isn't really true for us. We only derive from this class + // to benefit from the functionality for binding to spreadsheet cells + + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( OScrollBarModel ) + + //------------------------------------------------------------------------------ + void SAL_CALL OScrollBarModel::disposing() + { + OBoundControlModel::disposing(); + } + + //-------------------------------------------------------------------- + void OScrollBarModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 3, OControlModel ) + DECL_PROP1( DEFAULT_SCROLL_VALUE, sal_Int32, BOUND ); + DECL_PROP1( TABINDEX, sal_Int16, BOUND ); + DECL_PROP2( CONTROLSOURCEPROPERTY,::rtl::OUString, READONLY, TRANSIENT ); + END_DESCRIBE_PROPERTIES(); + } + + //------------------------------------------------------------------------------ + void OScrollBarModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SCROLL_VALUE: + _rValue <<= m_nDefaultScrollValue; + break; + + default: + OBoundControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //------------------------------------------------------------------------------ + void OScrollBarModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception ) + { + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SCROLL_VALUE: + OSL_VERIFY( _rValue >>= m_nDefaultScrollValue ); + resetNoBroadcast(); + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + } + } + + //------------------------------------------------------------------------------ + sal_Bool OScrollBarModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) + throw ( IllegalArgumentException ) + { + sal_Bool bModified( sal_False ); + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SCROLL_VALUE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_nDefaultScrollValue ); + break; + + default: + bModified = OBoundControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + break; + } + return bModified; + } + + //-------------------------------------------------------------------- + Any OScrollBarModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aReturn; + + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SCROLL_VALUE: + aReturn <<= (sal_Int32)0; + break; + + default: + aReturn = OBoundControlModel::getPropertyDefaultByHandle( _nHandle ); + break; + } + + return aReturn; + } + + //------------------------------------------------------------------------------ + Any OScrollBarModel::translateDbColumnToControlValue( ) + { + OSL_ENSURE( sal_False, "OScrollBarModel::commitControlValueToDbColumn: never to be called (we're not bound)!" ); + return Any(); + } + + //------------------------------------------------------------------------------ + sal_Bool OScrollBarModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) + { + OSL_ENSURE( sal_False, "OScrollBarModel::commitControlValueToDbColumn: never to be called (we're not bound)!" ); + return sal_True; + } + + //------------------------------------------------------------------------------ + Any OScrollBarModel::getDefaultForReset() const + { + return makeAny( (sal_Int32)m_nDefaultScrollValue ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OScrollBarModel::getServiceName() throw( RuntimeException ) + { + return FRM_SUN_COMPONENT_SCROLLBAR; + } + + //-------------------------------------------------------------------- + void SAL_CALL OScrollBarModel::write( const Reference< XObjectOutputStream >& _rxOutStream ) + throw( IOException, RuntimeException ) + { + OBoundControlModel::write( _rxOutStream ); + ::osl::MutexGuard aGuard( m_aMutex ); + + OStreamSection aSection( Reference< XDataOutputStream >( _rxOutStream, UNO_QUERY ) ); + + // version + _rxOutStream->writeShort( 0x0001 ); + + // properties + _rxOutStream << m_nDefaultScrollValue; + writeHelpTextCompatibly( _rxOutStream ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OScrollBarModel::read( const Reference< XObjectInputStream>& _rxInStream ) throw( IOException, RuntimeException ) + { + OBoundControlModel::read( _rxInStream ); + ::osl::MutexGuard aGuard( m_aMutex ); + + // version + { + OStreamSection aSection( Reference< XDataInputStream >( _rxInStream, UNO_QUERY ) ); + + sal_uInt16 nVersion = _rxInStream->readShort(); + if ( nVersion == 0x0001 ) + { + _rxInStream >> m_nDefaultScrollValue; + readHelpTextCompatibly( _rxInStream ); + } + else + defaultCommonProperties(); + + // here, everything in the stream section which is left will be skipped + } + } + + //-------------------------------------------------------------------- + Any OScrollBarModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const + { + return translateExternalDoubleToControlIntValue( _rExternalValue, m_xAggregateSet, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScrollValueMin" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScrollValueMax" ) ) ); + } + + //-------------------------------------------------------------------- + Any OScrollBarModel::translateControlValueToExternalValue( ) const + { + // by definition, the base class simply obtains the property value + return translateControlIntToExternalDoubleValue( OBoundControlModel::translateControlValueToExternalValue() ); + } + + //-------------------------------------------------------------------- + Sequence< Type > OScrollBarModel::getSupportedBindingTypes() + { + return Sequence< Type >( &::getCppuType( static_cast< double* >( NULL ) ), 1 ); + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/component/scrollbar.hxx b/forms/source/component/scrollbar.hxx new file mode 100644 index 000000000000..1d528dabe8bc --- /dev/null +++ b/forms/source/component/scrollbar.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * 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_SOURCE_COMPONENT_SCROLLBAR_HXX +#define FORMS_SOURCE_COMPONENT_SCROLLBAR_HXX + +#include "FormComponent.hxx" +#include "frm_module.hxx" + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OScrollBarModel + //==================================================================== + class OScrollBarModel :public OBoundControlModel + { + private: + // <properties> + sal_Int32 m_nDefaultScrollValue; + // </properties> + + protected: + DECLARE_DEFAULT_LEAF_XTOR( OScrollBarModel ); + + // XServiceInfo + DECLARE_SERVICE_REGISTRATION( OScrollBarModel ) + + // XPersistObject + DECLARE_XPERSISTOBJECT() + + // XCloneable + DECLARE_XCLONEABLE(); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 _nHandle ) const; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& _rValue, sal_Int32 _nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw ( ::com::sun::star::uno::Exception ); + 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 ); + + // OBoundControlModel + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + + // XCoponent and related helpers + virtual void SAL_CALL disposing(); + + // prevent method hiding + using OBoundControlModel::disposing; + using OBoundControlModel::getFastPropertyValue; + + }; +//........................................................................ +} // namespacefrm +//........................................................................ + +#endif // FORMS_SOURCE_COMPONENT_SCROLLBAR_HXX diff --git a/forms/source/component/spinbutton.cxx b/forms/source/component/spinbutton.cxx new file mode 100644 index 000000000000..332fccd2e744 --- /dev/null +++ b/forms/source/component/spinbutton.cxx @@ -0,0 +1,275 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_forms.hxx" +#include "spinbutton.hxx" +#include <comphelper/streamsection.hxx> +#include <comphelper/basicio.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_OSpinButtonModel() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::OSpinButtonModel > aRegisterModel; +} + +//........................................................................ +namespace frm +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::io; + using namespace ::com::sun::star::form::binding; + + //==================================================================== + //= OSpinButtonModel + //==================================================================== + // implemented elsewhere + Any translateExternalDoubleToControlIntValue( + const Any& _rExternalValue, const Reference< XPropertySet >& _rxProperties, + const ::rtl::OUString& _rMinValueName, const ::rtl::OUString& _rMaxValueName ); + Any translateControlIntToExternalDoubleValue( const Any& _rControlIntValue ); + + //==================================================================== + //= OSpinButtonModel + //==================================================================== + //-------------------------------------------------------------------- + DBG_NAME( OSpinButtonModel ) + //-------------------------------------------------------------------- + OSpinButtonModel::OSpinButtonModel( const Reference<XMultiServiceFactory>& _rxFactory ) + :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_SPINBUTTON, VCL_CONTROL_SPINBUTTON, sal_True, sal_True, sal_False ) + ,m_nDefaultSpinValue( 0 ) + { + DBG_CTOR( OSpinButtonModel, NULL ); + + m_nClassId = FormComponentType::SPINBUTTON; + initValueProperty( PROPERTY_SPIN_VALUE, PROPERTY_ID_SPIN_VALUE ); + } + + //-------------------------------------------------------------------- + OSpinButtonModel::OSpinButtonModel( const OSpinButtonModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory ) + :OBoundControlModel( _pOriginal, _rxFactory ) + { + DBG_CTOR( OSpinButtonModel, NULL ); + m_nDefaultSpinValue = _pOriginal->m_nDefaultSpinValue; + } + + //-------------------------------------------------------------------- + OSpinButtonModel::~OSpinButtonModel( ) + { + DBG_DTOR( OSpinButtonModel, NULL ); + } + + //-------------------------------------------------------------------- + IMPLEMENT_SERVICE_REGISTRATION_2( OSpinButtonModel, OControlModel, FRM_SUN_COMPONENT_SPINBUTTON, BINDABLE_INTEGER_VALUE_RANGE ) + // note that we're passing OControlModel as "base class". This is because + // OBoundControlModel, our real base class, claims to support the DataAwareControlModel + // service, which isn't really true for us. We only derive from this class + // to benefit from the functionality for binding to spreadsheet cells + + //------------------------------------------------------------------------------ + IMPLEMENT_DEFAULT_CLONING( OSpinButtonModel ) + + //------------------------------------------------------------------------------ + void SAL_CALL OSpinButtonModel::disposing() + { + OBoundControlModel::disposing(); + } + + //-------------------------------------------------------------------- + void OSpinButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const + { + BEGIN_DESCRIBE_PROPERTIES( 3, OControlModel ) + DECL_PROP1( DEFAULT_SPIN_VALUE, sal_Int32, BOUND ); + DECL_PROP1( TABINDEX, sal_Int16, BOUND ); + DECL_PROP2( CONTROLSOURCEPROPERTY,::rtl::OUString, READONLY, TRANSIENT ); + END_DESCRIBE_PROPERTIES(); + } + + //------------------------------------------------------------------------------ + void OSpinButtonModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SPIN_VALUE: + _rValue <<= m_nDefaultSpinValue; + break; + + default: + OBoundControlModel::getFastPropertyValue( _rValue, _nHandle ); + } + } + + //------------------------------------------------------------------------------ + void OSpinButtonModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception ) + { + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SPIN_VALUE: + OSL_VERIFY( _rValue >>= m_nDefaultSpinValue ); + resetNoBroadcast(); + break; + + default: + OBoundControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); + } + } + + //------------------------------------------------------------------------------ + sal_Bool OSpinButtonModel::convertFastPropertyValue( + Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) + throw ( IllegalArgumentException ) + { + sal_Bool bModified( sal_False ); + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SPIN_VALUE: + bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_nDefaultSpinValue ); + break; + + default: + bModified = OBoundControlModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); + break; + } + return bModified; + } + + //-------------------------------------------------------------------- + Any OSpinButtonModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aReturn; + + switch ( _nHandle ) + { + case PROPERTY_ID_DEFAULT_SPIN_VALUE: + aReturn <<= (sal_Int32)0; + break; + + default: + aReturn = OBoundControlModel::getPropertyDefaultByHandle( _nHandle ); + break; + } + + return aReturn; + } + + //------------------------------------------------------------------------------ + Any OSpinButtonModel::translateDbColumnToControlValue( ) + { + OSL_ENSURE( sal_False, "OSpinButtonModel::commitControlValueToDbColumn: never to be called (we're not bound)!" ); + return Any(); + } + + //------------------------------------------------------------------------------ + sal_Bool OSpinButtonModel::commitControlValueToDbColumn( bool /*_bPostReset*/ ) + { + OSL_ENSURE( sal_False, "OSpinButtonModel::commitControlValueToDbColumn: never to be called (we're not bound)!" ); + return sal_True; + } + + //------------------------------------------------------------------------------ + Any OSpinButtonModel::getDefaultForReset() const + { + return makeAny( (sal_Int32)m_nDefaultSpinValue ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OSpinButtonModel::getServiceName() throw( RuntimeException ) + { + return FRM_SUN_COMPONENT_SPINBUTTON; + } + + //-------------------------------------------------------------------- + void SAL_CALL OSpinButtonModel::write( const Reference< XObjectOutputStream >& _rxOutStream ) + throw( IOException, RuntimeException ) + { + OBoundControlModel::write( _rxOutStream ); + ::osl::MutexGuard aGuard( m_aMutex ); + + OStreamSection aSection( Reference< XDataOutputStream >( _rxOutStream, UNO_QUERY ) ); + + // version + _rxOutStream->writeShort( 0x0001 ); + + // properties + _rxOutStream << m_nDefaultSpinValue; + writeHelpTextCompatibly( _rxOutStream ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OSpinButtonModel::read( const Reference< XObjectInputStream>& _rxInStream ) throw( IOException, RuntimeException ) + { + OBoundControlModel::read( _rxInStream ); + ::osl::MutexGuard aGuard( m_aMutex ); + + // version + { + OStreamSection aSection( Reference< XDataInputStream >( _rxInStream, UNO_QUERY ) ); + + sal_uInt16 nVersion = _rxInStream->readShort(); + if ( nVersion == 0x0001 ) + { + _rxInStream >> m_nDefaultSpinValue; + readHelpTextCompatibly( _rxInStream ); + } + else + defaultCommonProperties(); + + // here, everything in the stream section which is left will be skipped + } + } + + //-------------------------------------------------------------------- + Any OSpinButtonModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const + { + return translateExternalDoubleToControlIntValue( _rExternalValue, m_xAggregateSet, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SpinValueMin" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SpinValueMax" ) ) ); + } + + //-------------------------------------------------------------------- + Any OSpinButtonModel::translateControlValueToExternalValue( ) const + { + // by definition, the base class simply obtains the property value + return translateControlIntToExternalDoubleValue( OBoundControlModel::translateControlValueToExternalValue() ); + } + + //-------------------------------------------------------------------- + Sequence< Type > OSpinButtonModel::getSupportedBindingTypes() + { + return Sequence< Type >( &::getCppuType( static_cast< double* >( NULL ) ), 1 ); + } + +//........................................................................ +} // namespace frm +//........................................................................ diff --git a/forms/source/component/spinbutton.hxx b/forms/source/component/spinbutton.hxx new file mode 100644 index 000000000000..4e9437bb8d0e --- /dev/null +++ b/forms/source/component/spinbutton.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * 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_SOURCE_COMPONENT_SPINBUTTON_HXX +#define FORMS_SOURCE_COMPONENT_SPINBUTTON_HXX + +#include "FormComponent.hxx" +#include "frm_module.hxx" + +//........................................................................ +namespace frm +{ +//........................................................................ + + //==================================================================== + //= OSpinButtonModel + //==================================================================== + class OSpinButtonModel :public OBoundControlModel + { + private: + // <properties> + sal_Int32 m_nDefaultSpinValue; + // </properties> + + protected: + DECLARE_DEFAULT_LEAF_XTOR( OSpinButtonModel ); + + // XServiceInfo + DECLARE_SERVICE_REGISTRATION( OSpinButtonModel ) + + // XPersistObject + DECLARE_XPERSISTOBJECT() + + // XCloneable + DECLARE_XCLONEABLE(); + + // XPropertyState + virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 _nHandle ) const; + + // OControlModel's property handling + virtual void describeFixedProperties( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps + ) const; + + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& _rValue, sal_Int32 _nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) + throw ( ::com::sun::star::uno::Exception ); + 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 ); + + // OBoundControlModel + virtual ::com::sun::star::uno::Any + translateDbColumnToControlValue( ); + virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ); + virtual ::com::sun::star::uno::Any + getDefaultForReset() const; + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > + getSupportedBindingTypes(); + virtual ::com::sun::star::uno::Any + translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const; + virtual ::com::sun::star::uno::Any + translateControlValueToExternalValue( ) const; + + // XCoponent and related helpers + virtual void SAL_CALL disposing(); + + // prevent method hiding + using OBoundControlModel::disposing; + using OBoundControlModel::getFastPropertyValue; + + }; +//........................................................................ +} // namespacefrm +//........................................................................ + +#endif // FORMS_SOURCE_COMPONENT_SPINBUTTON_HXX |