2009-08-10 13:16:25 +0200 fs r274805 : #i84390# typo corrected 2009-08-10 13:04:28 +0200 fs r274804 : #i103741# properly terminate the last token in a string with a 0 byte 2009-07-24 08:54:05 +0200 msc r274286 : #103219# changed long name 2009-07-24 08:42:28 +0200 msc r274285 : #i79649# changed behaviour of the wizard 2009-07-22 14:17:49 +0200 oj r274238 : GrabFocus 2009-07-22 13:38:01 +0200 oj r274232 : #i102934# mixed up 2009-07-22 13:37:16 +0200 oj r274231 : #i102934# mixed up 2009-07-21 12:30:36 +0200 oj r274176 : crash when using distinct 2009-07-21 10:03:44 +0200 oj r274163 : set last char to 0 2009-07-21 09:31:22 +0200 oj r274161 : mediatype corrected 2009-07-20 11:45:33 +0200 fs r274118 : typo in formatting string 2009-07-20 11:40:39 +0200 fs r274117 : removed unused include 2009-07-20 11:40:01 +0200 fs r274116 : class name corrected 2009-07-16 13:41:45 +0200 oj r274046 : i101587 wrong check for embeddeddatabase url in confguration, have to check path 2009-07-16 13:12:05 +0200 tbo r274044 : #i103219# adjust declarion to new hid.lst 2009-07-16 12:43:48 +0200 oj r274041 : #i102497# check also fot longvarchar 2009-07-16 12:15:41 +0200 oj r274039 : #i103030# handle type description and exceptions as well 2009-07-16 11:14:26 +0200 fs r274035 : let SVN ignore output paths 2009-07-16 09:23:43 +0200 fs r274030 : TransforFormComponentProperties: no need to check for attribute equality 2009-07-10 14:16:23 +0200 oj r273892 : CWS-TOOLING: rebase CWS dba32e to trunk@273858 (milestone: DEV300:m52) 2009-07-01 21:41:50 +0200 fs r273614 : #i10000# 2009-07-01 15:01:10 +0200 fs r273589 : Input required doesn't make sense at all in XML form documents 2009-07-01 12:10:31 +0200 fs r273562 : updated 2009-07-01 11:46:12 +0200 fs r273560 : #i103219# add about 100 missing long names 2009-07-01 10:11:41 +0200 fs r273551 : moved from socket/port usage to pipe/name usage, which is more common nowadays 2009-07-01 09:50:03 +0200 fs r273549 : removed obsolete (empty) folder 2009-07-01 09:47:35 +0200 fs r273548 : copied the code for the Accessibility Workbench herein, formerly located in the old CVS repository, at gsl/awb 2009-06-30 10:07:47 +0200 fs r273493 : merging latest changes from CWS dba32d 2009-06-29 20:46:31 +0200 fs r273482 : #i103138# Rectangle conversions 2009-06-29 10:01:13 +0200 fs r273453 : #i103138# refactored the code for positioning/zooming the control Basically, we now allow adjustControlGeometry_throw (formerly known as positionControl_throw and setControlZoom) to take an additional ViewTransformation parameter, describing the transformation to obtain the actual control position/size. Consequently, positionControl itself also allows for a ViewTransformation parameter. This has become necessary since during painting, the device which we created our control for might not necessarily have a proper MapMode set. In this case, if we would use this map mode for calculating the control's position/size, this would lead to wrong results. Note that this problem was introduced by the fix for #i101398#: During the fix, we postponed the control creation to a later time (when it is really needed). At this later time, the MapMode at the device is broken, at the earlier time where we formerly crearted the control (createPrimitive2DSequence), it is not yet broken. Whether or not the MapMode is defined as "broken" might depend on one's point of view, however ... I consider it broken, since: - we need the map mode to obtain the proper zoom level, which is to be forwarded to the control - there are scenarios where the MapMode is *not* set to MAP_PIXEL (in those scenarios, everything works fine), and there are scenarios where it *is* set to MAP_PIXEL (in those the bug 103138 appears). It somehow feels wrong that one cannot rely on the device's map mode this way, but on the other hand one has no possibility to obtain the current zoom by other means. Note that one issue (still to be submitted) is left: In the page pane of a Draw/Impress document, controls have a wrong text size. This is because in this pane, the above-mentioned "broken" map mode is used, which means the controls have a zoom of "1:1" set, which is wrong here. 2009-06-29 09:52:13 +0200 fs r273452 : during #i103138#: belongsToDevice is unused nowadays 2009-06-24 12:40:06 +0200 fs r273329 : #i102888# #i102899# 2009-06-24 12:10:29 +0200 oj r273327 : #i103030# some code changes 2009-06-24 09:44:14 +0200 oj r273311 : #i103030# some code changes 2009-06-24 09:24:42 +0200 oj r273309 : #i103030# add log 2009-06-24 09:03:29 +0200 fs r273308 : if a col's table name is schema.table, properly quote all parts 2009-06-24 08:56:06 +0200 oj r273307 : #i102691# changed string 2009-06-23 13:31:43 +0200 oj r273280 : #i102479# fix date, time and datetime 2009-06-23 12:51:28 +0200 oj r273277 : #i103020# clear old expression when updating to avoid dead pointers in treelist userdata 2009-06-23 12:17:16 +0200 oj r273275 : #i103030# add LogBridge 2009-06-23 11:53:10 +0200 oj r273272 : shawdowed var resolved 2009-06-23 11:48:49 +0200 oj r273270 : #i103030# add :log to uno env if var UNO_ENV_LOG is set 2009-06-23 11:47:47 +0200 oj r273269 : #i103030# add LogBridge 2009-06-23 11:47:11 +0200 oj r273268 : #i103030# add LogBridge 2009-06-23 08:05:08 +0200 oj r273253 : #i102934# add key for collapsing 2009-06-22 13:21:33 +0200 fs r273225 : merging latest changes from CWS dba32d 2009-06-22 13:15:22 +0200 fs r273221 : why restrict to 12 entries? 2009-06-22 08:12:21 +0200 oj r273196 : #i102655# choosen > chosen typo fixed 2009-06-22 08:08:04 +0200 oj r273195 : #i102657# typo fix 2009-06-22 08:06:28 +0200 oj r273194 : #i102934# expanding and collasping of section 2009-06-22 08:05:52 +0200 oj r273193 : #i102930# set focus in treelistbox 2009-06-22 08:04:56 +0200 oj r273192 : #i102929# enable tabstop 2009-06-19 13:18:26 +0200 oj r273157 : remove unused param 2009-06-19 10:07:05 +0200 oj r273149 : CWS-TOOLING: rebase CWS dba32e to trunk@272827 (milestone: DEV300:m50) 2009-06-19 07:32:40 +0200 oj r273146 : merge from dba32d to dba32e 2009-06-19 07:22:56 +0200 oj r273145 : merge from dba32d to dba32e 2009-06-19 07:22:33 +0200 oj r273144 : merge from dba32d to dba32e 2009-06-18 14:09:34 +0200 fs r273116 : merging the latest changes from CWS dba32d (up to revision 273108) herein, which effectively is a rebase to DEV300.m50 2009-06-18 08:50:35 +0200 oj r273098 : #i102894# fix for new line in text 2009-06-18 08:28:48 +0200 oj r273097 : #i102892# check any 2009-06-18 08:21:34 +0200 oj r273096 : check if error is valid 2009-06-16 13:49:28 +0200 fs r273019 : why make a drop down control by default? The form control factory in SVX does this better those days ... 2009-06-10 09:53:20 +0200 oj r272797 : add lic text 2009-06-10 09:48:55 +0200 oj r272796 : test added for i101618 2009-06-09 14:57:39 +0200 oj r272771 : #i101618# access database document only when script container is needed 2009-06-09 12:42:25 +0200 oj r272765 : #i102497# check type property 2009-06-09 12:32:49 +0200 oj r272764 : adjust test cases 2009-06-09 12:31:58 +0200 oj r272763 : adjust test cases 2009-06-09 12:31:22 +0200 oj r272762 : adjust test cases 2009-06-09 11:35:42 +0200 oj r272761 : check if error is valid 2009-06-09 11:29:42 +0200 oj r272760 : #i102497# longvarchar was missing 2009-06-08 14:52:49 +0200 fs r272733 : #i102564# when setting a new field, also set m_nFieldType 2009-06-08 13:51:20 +0200 oj r272730 : add tests 2009-06-05 14:38:01 +0200 oj r272686 : add dep 2009-06-05 14:35:00 +0200 oj r272684 : add new tests 2009-06-05 13:41:18 +0200 oj r272681 : code clean ups 2009-06-05 12:40:51 +0200 oj r272678 : code cleanup 2009-06-05 12:02:57 +0200 oj r272677 : code cleanup 2009-06-05 10:42:38 +0200 oj r272670 : #i49320# impl export of single rows and as RTF and HTML 2009-06-03 14:30:37 +0200 oj r272576 : #i79649# check if file matches filter wildcard 2009-06-03 13:41:57 +0200 oj r272560 : #i102470# impl not b like 'c'
3113 lines
119 KiB
C++
3113 lines
119 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: FormComponent.cxx,v $
|
|
* $Revision: 1.62.8.2 $
|
|
*
|
|
* 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)
|
|
{
|
|
// RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setFastPropertyValue_NoBroadcast" );
|
|
// 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::BLOB )
|
|
|| ( nFieldType == DataType::CLOB )
|
|
)
|
|
m_xColumn->getBinaryStream();
|
|
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( )
|
|
{
|
|
setControlValue( translateDbColumnToControlValue(), eDbColumnBinding );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
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 .......................................................
|
|
|