update dev300-m58
[ooovba.git] / forms / source / component / FormComponent.cxx
blob0de1cc3dea2b769672e8a9d52e01f8df6f4b9b93
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: FormComponent.cxx,v $
10 * $Revision: 1.62.8.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_forms.hxx"
34 #include "componenttools.hxx"
35 #include "FormComponent.hxx"
36 #include "frm_resource.hrc"
37 #include "frm_resource.hxx"
38 #include "property.hrc"
39 #include "services.hxx"
41 /** === begin UNO includes === **/
42 #include <com/sun/star/awt/XTextComponent.hpp>
43 #include <com/sun/star/awt/XVclWindowPeer.hpp>
44 #include <com/sun/star/awt/XWindow.hpp>
45 #include <com/sun/star/form/XForm.hpp>
46 #include <com/sun/star/form/XLoadable.hpp>
47 #include <com/sun/star/io/XMarkableStream.hpp>
48 #include <com/sun/star/lang/DisposedException.hpp>
49 #include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp>
50 #include <com/sun/star/sdb/XRowSetSupplier.hpp>
51 #include <com/sun/star/sdbc/ColumnValue.hpp>
52 #include <com/sun/star/sdbc/DataType.hpp>
53 #include <com/sun/star/util/XModifyBroadcaster.hpp>
54 /** === end UNO includes === **/
56 #include <comphelper/basicio.hxx>
57 #include <comphelper/guarding.hxx>
58 #include <comphelper/listenernotification.hxx>
59 #include <comphelper/property.hxx>
60 #include <connectivity/dbtools.hxx>
61 #include <cppuhelper/queryinterface.hxx>
62 #include <rtl/logfile.hxx>
63 #include <toolkit/helper/emptyfontdescriptor.hxx>
64 #include <tools/debug.hxx>
65 #include <tools/diagnose_ex.h>
67 #include <functional>
68 #include <algorithm>
70 #include <functional>
71 #include <algorithm>
74 //... namespace frm .......................................................
75 namespace frm
77 //.........................................................................
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::sdb;
81 using namespace ::com::sun::star::sdbc;
82 using namespace ::com::sun::star::sdbcx;
83 using namespace ::com::sun::star::beans;
84 using namespace ::com::sun::star::container;
85 using namespace ::com::sun::star::form;
86 using namespace ::com::sun::star::awt;
87 using namespace ::com::sun::star::io;
88 using namespace ::com::sun::star::lang;
89 using namespace ::com::sun::star::util;
90 using namespace ::com::sun::star::form::binding;
91 using namespace ::com::sun::star::form::validation;
92 using namespace ::dbtools;
93 using namespace ::comphelper;
95 //=========================================================================
96 //= FieldChangeNotifier
97 //=========================================================================
98 //-------------------------------------------------------------------------
99 void ControlModelLock::impl_notifyAll_nothrow()
101 m_rModel.firePropertyChanges( m_aHandles, m_aOldValues, m_aNewValues, OControlModel::LockAccess() );
104 //-------------------------------------------------------------------------
105 void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue )
107 sal_Int32 nOldLength = m_aHandles.getLength();
108 if ( ( nOldLength != m_aOldValues.getLength() )
109 || ( nOldLength != m_aNewValues.getLength() )
111 throw RuntimeException( ::rtl::OUString(), m_rModel );
113 m_aHandles.realloc( nOldLength + 1 );
114 m_aHandles[ nOldLength ] = _nHandle;
115 m_aOldValues.realloc( nOldLength + 1 );
116 m_aOldValues[ nOldLength ] = _rOldValue;
117 m_aNewValues.realloc( nOldLength + 1 );
118 m_aNewValues[ nOldLength ] = _rNewValue;
121 //=========================================================================
122 //= FieldChangeNotifier
123 //=========================================================================
124 //-------------------------------------------------------------------------
125 class FieldChangeNotifier
127 public:
128 FieldChangeNotifier( ControlModelLock& _rLock )
129 :m_rLock( _rLock )
130 ,m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) )
132 m_xOldField = m_rModel.getField();
135 ~FieldChangeNotifier()
137 Reference< XPropertySet > xNewField( m_rModel.getField() );
138 if ( m_xOldField != xNewField )
139 m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, makeAny( m_xOldField ), makeAny( xNewField ) );
142 private:
143 ControlModelLock& m_rLock;
144 OBoundControlModel& m_rModel;
145 Reference< XPropertySet > m_xOldField;
148 //=============================================================================
149 //= base class for form layer controls
150 //=============================================================================
151 DBG_NAME(frm_OControl)
152 //------------------------------------------------------------------------------
153 OControl::OControl( const Reference< XMultiServiceFactory >& _rxFactory, const rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator )
154 :OComponentHelper(m_aMutex)
155 ,m_aContext( _rxFactory )
157 DBG_CTOR(frm_OControl, NULL);
158 // VCL-Control aggregieren
159 // bei Aggregation den Refcount um eins erhoehen da im setDelegator
160 // das Aggregat selbst den Refcount erhoeht
161 increment( m_refCount );
163 m_xAggregate = m_xAggregate.query( _rxFactory->createInstance( _rAggregateService ) );
164 m_xControl = m_xControl.query( m_xAggregate );
166 decrement( m_refCount );
168 if ( _bSetDelegator )
169 doSetDelegator();
172 //------------------------------------------------------------------------------
173 OControl::~OControl()
175 DBG_DTOR(frm_OControl, NULL);
176 doResetDelegator();
179 //------------------------------------------------------------------------------
180 void OControl::doResetDelegator()
182 if ( m_xAggregate.is() )
183 m_xAggregate->setDelegator( NULL );
186 //------------------------------------------------------------------------------
187 void OControl::doSetDelegator()
189 increment( m_refCount );
190 if ( m_xAggregate.is() )
191 { // those brackets are important for some compilers, don't remove!
192 // (they ensure that the temporary object created in the line below
193 // is destroyed *before* the refcount-decrement)
194 m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
196 decrement( m_refCount );
199 // UNO Anbindung
200 //------------------------------------------------------------------------------
201 Any SAL_CALL OControl::queryAggregation( const Type& _rType ) throw(RuntimeException)
203 // ask the base class
204 Any aReturn( OComponentHelper::queryAggregation(_rType) );
205 // ask our own interfaces
206 if (!aReturn.hasValue())
208 aReturn = OControl_BASE::queryInterface(_rType);
209 // ask our aggregate
210 if (!aReturn.hasValue() && m_xAggregate.is())
211 aReturn = m_xAggregate->queryAggregation(_rType);
214 return aReturn;
217 //------------------------------------------------------------------------------
218 Sequence<sal_Int8> SAL_CALL OControl::getImplementationId() throw(RuntimeException)
220 return OImplementationIds::getImplementationId(getTypes());
223 //------------------------------------------------------------------------------
224 Sequence<Type> SAL_CALL OControl::getTypes() throw(RuntimeException)
226 TypeBag aTypes( _getTypes() );
228 Reference< XTypeProvider > xProv;
229 if ( query_aggregation( m_xAggregate, xProv ) )
230 aTypes.addTypes( xProv->getTypes() );
232 return aTypes.getTypes();
235 //------------------------------------------------------------------------------
236 Sequence<Type> OControl::_getTypes()
238 return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes();
241 //------------------------------------------------------------------------------
242 void OControl::initFormControlPeer( const Reference< XWindowPeer >& /*_rxPeer*/ )
244 // nothing to do here
247 // OComponentHelper
248 //------------------------------------------------------------------------------
249 void OControl::disposing()
251 OComponentHelper::disposing();
253 m_aWindowStateGuard.attach( NULL, NULL );
255 Reference< XComponent > xComp;
256 if (query_aggregation(m_xAggregate, xComp))
257 xComp->dispose();
260 // XServiceInfo
261 //------------------------------------------------------------------------------
262 sal_Bool SAL_CALL OControl::supportsService(const rtl::OUString& _rsServiceName) throw ( RuntimeException)
264 Sequence<rtl::OUString> aSupported = getSupportedServiceNames();
265 const rtl::OUString* pSupported = aSupported.getConstArray();
266 for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported)
267 if (pSupported->equals(_rsServiceName))
268 return sal_True;
269 return sal_False;
272 //------------------------------------------------------------------------------
273 Sequence< ::rtl::OUString > OControl::getAggregateServiceNames()
275 Sequence< ::rtl::OUString > aAggServices;
276 Reference< XServiceInfo > xInfo;
277 if ( query_aggregation( m_xAggregate, xInfo ) )
278 aAggServices = xInfo->getSupportedServiceNames();
279 return aAggServices;
282 //------------------------------------------------------------------------------
283 Sequence<rtl::OUString> SAL_CALL OControl::getSupportedServiceNames() throw(RuntimeException)
285 return ::comphelper::concatSequences(
286 getAggregateServiceNames(),
287 getSupportedServiceNames_Static()
291 //------------------------------------------------------------------------------
292 Sequence< ::rtl::OUString > SAL_CALL OControl::getSupportedServiceNames_Static() throw( RuntimeException )
294 // no own supported service names
295 return Sequence< ::rtl::OUString >();
298 // XEventListener
299 //------------------------------------------------------------------------------
300 void SAL_CALL OControl::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException)
302 InterfaceRef xAggAsIface;
303 query_aggregation(m_xAggregate, xAggAsIface);
305 // does the disposing come from the aggregate ?
306 if (xAggAsIface != InterfaceRef(_rEvent.Source, UNO_QUERY))
307 { // no -> forward it
308 Reference<com::sun::star::lang::XEventListener> xListener;
309 if (query_aggregation(m_xAggregate, xListener))
310 xListener->disposing(_rEvent);
314 // XControl
315 //------------------------------------------------------------------------------
316 void SAL_CALL OControl::setContext(const InterfaceRef& Context) throw (RuntimeException)
318 if (m_xControl.is())
319 m_xControl->setContext(Context);
322 //------------------------------------------------------------------------------
323 InterfaceRef SAL_CALL OControl::getContext() throw (RuntimeException)
325 return m_xControl.is() ? m_xControl->getContext() : InterfaceRef();
328 //------------------------------------------------------------------------------
329 void OControl::impl_resetStateGuard_nothrow()
331 Reference< XWindow2 > xWindow;
332 Reference< XControlModel > xModel;
335 xWindow.set( getPeer(), UNO_QUERY );
336 xModel.set( getModel(), UNO_QUERY );
338 catch( const Exception& )
340 DBG_UNHANDLED_EXCEPTION();
342 m_aWindowStateGuard.attach( xWindow, xModel );
345 //------------------------------------------------------------------------------
346 void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent) throw (RuntimeException)
348 if ( m_xControl.is() )
350 m_xControl->createPeer( _rxToolkit, _rxParent );
352 initFormControlPeer( getPeer() );
354 impl_resetStateGuard_nothrow();
358 //------------------------------------------------------------------------------
359 Reference<XWindowPeer> SAL_CALL OControl::getPeer() throw ( RuntimeException)
361 return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>();
364 //------------------------------------------------------------------------------
365 sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model) throw ( RuntimeException)
367 if ( !m_xControl.is() )
368 return sal_False;
370 sal_Bool bSuccess = m_xControl->setModel( Model );
371 impl_resetStateGuard_nothrow();
372 return bSuccess;
375 //------------------------------------------------------------------------------
376 Reference<XControlModel> SAL_CALL OControl::getModel() throw ( RuntimeException)
378 return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>();
381 //------------------------------------------------------------------------------
382 Reference<XView> SAL_CALL OControl::getView() throw ( RuntimeException)
384 return m_xControl.is() ? m_xControl->getView() : Reference<XView>();
387 //------------------------------------------------------------------------------
388 void SAL_CALL OControl::setDesignMode(sal_Bool bOn) throw ( RuntimeException)
390 if (m_xControl.is())
391 m_xControl->setDesignMode(bOn);
394 //------------------------------------------------------------------------------
395 sal_Bool SAL_CALL OControl::isDesignMode() throw ( RuntimeException)
397 return m_xControl.is() ? m_xControl->isDesignMode() : sal_True;
400 //------------------------------------------------------------------------------
401 sal_Bool SAL_CALL OControl::isTransparent() throw ( RuntimeException)
403 return m_xControl.is() ? m_xControl->isTransparent() : sal_True;
406 //==================================================================
407 //= OBoundControl
408 //==================================================================
409 DBG_NAME(frm_OBoundControl);
410 //------------------------------------------------------------------
411 OBoundControl::OBoundControl( const Reference< XMultiServiceFactory >& _rxFactory,
412 const ::rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator )
413 :OControl( _rxFactory, _rAggregateService, _bSetDelegator )
414 ,m_bLocked(sal_False)
415 ,m_aOriginalFont( EmptyFontDescriptor() )
416 ,m_nOriginalTextLineColor( 0 )
418 DBG_CTOR(frm_OBoundControl, NULL);
421 //------------------------------------------------------------------
422 OBoundControl::~OBoundControl()
424 DBG_DTOR(frm_OBoundControl, NULL);
426 // -----------------------------------------------------------------------------
427 Sequence< Type> OBoundControl::_getTypes()
429 return TypeBag( OControl::_getTypes(), OBoundControl_BASE::getTypes() ).getTypes();
431 //------------------------------------------------------------------
432 Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType) throw(RuntimeException)
434 Any aReturn;
436 // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types
437 if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) )
438 aReturn = OControl::queryAggregation( _rType );
440 // ask our own interfaces
441 // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener)
442 if ( !aReturn.hasValue() )
443 aReturn = OBoundControl_BASE::queryInterface( _rType );
445 // ask the base class
446 if ( !aReturn.hasValue() )
447 aReturn = OControl::queryAggregation( _rType );
449 return aReturn;
452 //------------------------------------------------------------------
453 sal_Bool SAL_CALL OBoundControl::getLock() throw(RuntimeException)
455 return m_bLocked;
458 //------------------------------------------------------------------
459 void SAL_CALL OBoundControl::setLock(sal_Bool _bLock) throw(RuntimeException)
461 if (m_bLocked == _bLock)
462 return;
464 osl::MutexGuard aGuard(m_aMutex);
465 _setLock(_bLock);
466 m_bLocked = _bLock;
469 //------------------------------------------------------------------
470 void OBoundControl::_setLock(sal_Bool _bLock)
472 // try to set the text component to readonly
473 Reference< XWindowPeer > xPeer = getPeer();
474 Reference< XTextComponent > xText( xPeer, UNO_QUERY );
476 if ( xText.is() )
477 xText->setEditable( !_bLock );
478 else
480 // disable the window
481 Reference< XWindow > xComp( xPeer, UNO_QUERY );
482 if ( xComp.is() )
483 xComp->setEnable( !_bLock );
487 //--------------------------------------------------------------------
488 sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel ) throw (RuntimeException)
490 return OControl::setModel( _rxModel );
493 //--------------------------------------------------------------------
494 void SAL_CALL OBoundControl::disposing(const EventObject& Source) throw (RuntimeException)
496 // just disambiguate
497 OControl::disposing(Source);
500 //--------------------------------------------------------------------
501 void OBoundControl::disposing()
503 OControl::disposing();
506 //==================================================================
507 //= OControlModel
508 //==================================================================
509 DBG_NAME(OControlModel)
510 //------------------------------------------------------------------
511 Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId() throw(RuntimeException)
513 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getImplementationId" );
514 return OImplementationIds::getImplementationId(getTypes());
517 //------------------------------------------------------------------
518 Sequence<Type> SAL_CALL OControlModel::getTypes() throw(RuntimeException)
520 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getTypes" );
521 TypeBag aTypes( _getTypes() );
523 Reference< XTypeProvider > xProv;
524 if ( query_aggregation( m_xAggregate, xProv ) )
525 aTypes.addTypes( xProv->getTypes() );
527 return aTypes.getTypes();
530 //------------------------------------------------------------------------------
531 Sequence<Type> OControlModel::_getTypes()
533 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::_getTypes" );
534 return TypeBag( OComponentHelper::getTypes(),
535 OPropertySetAggregationHelper::getTypes(),
536 OControlModel_BASE::getTypes()
537 ).getTypes();
540 //------------------------------------------------------------------
541 Any SAL_CALL OControlModel::queryAggregation(const Type& _rType) throw (RuntimeException)
543 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::queryAggregation" );
544 // base class 1
545 Any aReturn(OComponentHelper::queryAggregation(_rType));
547 // base class 2
548 if (!aReturn.hasValue())
550 aReturn = OControlModel_BASE::queryInterface(_rType);
552 // our own interfaces
553 if (!aReturn.hasValue())
555 aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
556 // our aggregate
557 if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(::getCppuType(static_cast< Reference< XCloneable>* >(NULL))))
558 aReturn = m_xAggregate->queryAggregation(_rType);
561 return aReturn;
564 //------------------------------------------------------------------------------
565 void OControlModel::readHelpTextCompatibly(const staruno::Reference< stario::XObjectInputStream >& _rxInStream)
567 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::readHelpTextCompatibly" );
568 ::rtl::OUString sHelpText;
569 ::comphelper::operator>>( _rxInStream, sHelpText);
572 if (m_xAggregateSet.is())
573 m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, makeAny(sHelpText));
575 catch(const Exception&)
577 OSL_ENSURE(sal_False, "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!");
581 //------------------------------------------------------------------------------
582 void OControlModel::writeHelpTextCompatibly(const staruno::Reference< stario::XObjectOutputStream >& _rxOutStream)
584 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::writeHelpTextCompatibly" );
585 ::rtl::OUString sHelpText;
588 if (m_xAggregateSet.is())
589 m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
591 catch(const Exception&)
593 OSL_ENSURE(sal_False, "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!");
595 ::comphelper::operator<<( _rxOutStream, sHelpText);
598 //------------------------------------------------------------------
599 OControlModel::OControlModel(
600 const Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory,
601 const ::rtl::OUString& _rUnoControlModelTypeName,
602 const ::rtl::OUString& rDefault, const sal_Bool _bSetDelegator)
603 :OComponentHelper(m_aMutex)
604 ,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
605 ,m_aContext( _rxFactory )
606 ,m_lockCount( 0 )
607 ,m_aPropertyBagHelper( *this )
608 ,m_nTabIndex(FRM_DEFAULT_TABINDEX)
609 ,m_nClassId(FormComponentType::CONTROL)
610 ,m_bNativeLook( sal_False )
611 // form controls are usually embedded into documents, not dialogs, and in documents
612 // the native look is ugly ....
613 // #i37342# / 2004-11-19 / frank.schoenheit@sun.com
615 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::OControlModel" );
616 DBG_CTOR(OControlModel, NULL);
617 if (_rUnoControlModelTypeName.getLength()) // the is a model we have to aggregate
619 increment(m_refCount);
622 m_xAggregate = Reference<XAggregation>(_rxFactory->createInstance(_rUnoControlModelTypeName), UNO_QUERY);
623 setAggregation(m_xAggregate);
625 if ( m_xAggregateSet.is() )
629 if ( rDefault.getLength() )
630 m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( rDefault ) );
632 catch( const Exception& )
634 OSL_ENSURE( sal_False, "OControlModel::OControlModel: caught an exception!" );
639 if (_bSetDelegator)
640 doSetDelegator();
642 // Refcount wieder bei NULL
643 decrement(m_refCount);
647 //------------------------------------------------------------------
648 OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory, const sal_Bool _bCloneAggregate, const sal_Bool _bSetDelegator )
649 :OComponentHelper( m_aMutex )
650 ,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
651 ,m_aContext( _rxFactory )
652 ,m_lockCount( 0 )
653 ,m_aPropertyBagHelper( *this )
654 ,m_nTabIndex( FRM_DEFAULT_TABINDEX )
655 ,m_nClassId( FormComponentType::CONTROL )
657 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::OControlModel(copy)" );
658 DBG_CTOR( OControlModel, NULL );
659 DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" );
661 // copy members
662 m_aName = _pOriginal->m_aName;
663 m_aTag = _pOriginal->m_aTag;
664 m_nTabIndex = _pOriginal->m_nTabIndex;
665 m_nClassId = _pOriginal->m_nClassId;
666 m_bNativeLook = _pOriginal->m_bNativeLook;
668 if ( _bCloneAggregate )
670 // temporarily increment refcount because of temporary references to ourself in the following
671 increment( m_refCount );
674 // transfer the (only, at the very moment!) ref count
675 m_xAggregate = createAggregateClone( _pOriginal );
677 // set aggregation (retrieve other direct interfaces of the aggregate)
678 setAggregation( m_xAggregate );
681 // set the delegator, if allowed by our derived class
682 if ( _bSetDelegator )
683 doSetDelegator();
685 // decrement ref count
686 decrement( m_refCount );
690 //------------------------------------------------------------------
691 OControlModel::~OControlModel()
693 // release the aggregate
694 doResetDelegator( );
696 DBG_DTOR(OControlModel, NULL);
699 //------------------------------------------------------------------
700 void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ )
702 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::clonedFrom" );
703 // nothing to do in this base class
706 //------------------------------------------------------------------------------
707 void OControlModel::doResetDelegator()
709 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::doResetDelegator" );
710 if (m_xAggregate.is())
711 m_xAggregate->setDelegator(NULL);
714 //------------------------------------------------------------------------------
715 void OControlModel::doSetDelegator()
717 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::doSetDelegator" );
718 increment(m_refCount);
719 if (m_xAggregate.is())
721 m_xAggregate->setDelegator(static_cast<XWeak*>(this));
723 decrement(m_refCount);
726 // XChild
727 //------------------------------------------------------------------------------
728 InterfaceRef SAL_CALL OControlModel::getParent() throw(RuntimeException)
730 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getParent" );
731 return m_xParent;
734 //------------------------------------------------------------------------------
735 void SAL_CALL OControlModel::setParent(const InterfaceRef& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException)
737 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setParent" );
738 osl::MutexGuard aGuard(m_aMutex);
740 Reference<XComponent> xComp(m_xParent, UNO_QUERY);
741 if (xComp.is())
742 xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this));
744 m_xParent = _rxParent;
745 xComp = xComp.query( m_xParent );
747 if ( xComp.is() )
748 xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this));
751 // XNamed
752 //------------------------------------------------------------------------------
753 ::rtl::OUString SAL_CALL OControlModel::getName() throw(RuntimeException)
755 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getName" );
756 ::rtl::OUString aReturn;
757 OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= aReturn;
758 return aReturn;
761 //------------------------------------------------------------------------------
762 void SAL_CALL OControlModel::setName(const ::rtl::OUString& _rName) throw(RuntimeException)
764 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setName" );
765 setFastPropertyValue(PROPERTY_ID_NAME, makeAny(_rName));
768 // XServiceInfo
769 //------------------------------------------------------------------------------
770 sal_Bool SAL_CALL OControlModel::supportsService(const rtl::OUString& _rServiceName) throw ( RuntimeException)
772 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::supportsService" );
773 Sequence<rtl::OUString> aSupported = getSupportedServiceNames();
774 const rtl::OUString* pSupported = aSupported.getConstArray();
775 for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported)
776 if (pSupported->equals(_rServiceName))
777 return sal_True;
778 return sal_False;
781 //------------------------------------------------------------------------------
782 Sequence< ::rtl::OUString > OControlModel::getAggregateServiceNames()
784 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getAggregateServiceNames" );
785 Sequence< ::rtl::OUString > aAggServices;
786 Reference< XServiceInfo > xInfo;
787 if ( query_aggregation( m_xAggregate, xInfo ) )
788 aAggServices = xInfo->getSupportedServiceNames();
789 return aAggServices;
792 //------------------------------------------------------------------------------
793 Sequence<rtl::OUString> SAL_CALL OControlModel::getSupportedServiceNames() throw(RuntimeException)
795 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames" );
796 return ::comphelper::concatSequences(
797 getAggregateServiceNames(),
798 getSupportedServiceNames_Static()
802 //------------------------------------------------------------------------------
803 Sequence< ::rtl::OUString > SAL_CALL OControlModel::getSupportedServiceNames_Static() throw( RuntimeException )
805 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames_Static" );
806 Sequence< ::rtl::OUString > aServiceNames( 2 );
807 aServiceNames[ 0 ] = FRM_SUN_FORMCOMPONENT;
808 aServiceNames[ 1 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.FormControlModel" );
809 return aServiceNames;
812 // XEventListener
813 //------------------------------------------------------------------------------
814 void SAL_CALL OControlModel::disposing(const com::sun::star::lang::EventObject& _rSource) throw (RuntimeException)
816 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" );
817 // release the parent
818 if (_rSource.Source == m_xParent)
820 osl::MutexGuard aGuard(m_aMutex);
821 m_xParent = NULL;
823 else
825 Reference<com::sun::star::lang::XEventListener> xEvtLst;
826 if (query_aggregation(m_xAggregate, xEvtLst))
828 osl::MutexGuard aGuard(m_aMutex);
829 xEvtLst->disposing(_rSource);
834 // OComponentHelper
835 //-----------------------------------------------------------------------------
836 void OControlModel::disposing()
838 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" );
839 OPropertySetAggregationHelper::disposing();
841 Reference<com::sun::star::lang::XComponent> xComp;
842 if (query_aggregation(m_xAggregate, xComp))
843 xComp->dispose();
845 setParent(Reference<XFormComponent>());
847 m_aPropertyBagHelper.dispose();
850 //------------------------------------------------------------------------------
851 void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const
853 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::writeAggregate" );
854 Reference< XPersistObject > xPersist;
855 if ( query_aggregation( m_xAggregate, xPersist ) )
856 xPersist->write( _rxOutStream );
859 //------------------------------------------------------------------------------
860 void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream )
862 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::readAggregate" );
863 Reference< XPersistObject > xPersist;
864 if ( query_aggregation( m_xAggregate, xPersist ) )
865 xPersist->read( _rxInStream );
868 //------------------------------------------------------------------------------
869 void SAL_CALL OControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream)
870 throw(stario::IOException, RuntimeException)
872 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::write" );
873 osl::MutexGuard aGuard(m_aMutex);
875 // 1. Schreiben des UnoControls
876 Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
877 if ( !xMark.is() )
879 throw IOException(
880 FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
881 static_cast< ::cppu::OWeakObject* >( this )
885 sal_Int32 nMark = xMark->createMark();
886 sal_Int32 nLen = 0;
888 _rxOutStream->writeLong(nLen);
890 writeAggregate( _rxOutStream );
892 // feststellen der Laenge
893 nLen = xMark->offsetToMark(nMark) - 4;
894 xMark->jumpToMark(nMark);
895 _rxOutStream->writeLong(nLen);
896 xMark->jumpToFurthest();
897 xMark->deleteMark(nMark);
899 // 2. Schreiben einer VersionsNummer
900 _rxOutStream->writeShort(0x0003);
902 // 3. Schreiben der allgemeinen Properties
903 ::comphelper::operator<<( _rxOutStream, m_aName);
904 _rxOutStream->writeShort(m_nTabIndex);
905 ::comphelper::operator<<( _rxOutStream, m_aTag); // 3. version
907 // !!! IMPORTANT NOTE !!!
908 // don't write any new members here : this wouldn't be compatible with older versions, as OControlModel
909 // is a base class which is called in derived classes "read" method. So if you increment the version
910 // and write new stuff, older office versions will read this in the _derived_ classes, which may result
911 // in anything from data loss to crash.
912 // !!! EOIN !!!
915 //------------------------------------------------------------------------------
916 void OControlModel::read(const Reference<stario::XObjectInputStream>& InStream) throw (::com::sun::star::io::IOException, RuntimeException)
918 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::read" );
919 osl::MutexGuard aGuard(m_aMutex);
921 Reference<stario::XMarkableStream> xMark(InStream, UNO_QUERY);
922 if ( !xMark.is() )
924 throw IOException(
925 FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
926 static_cast< ::cppu::OWeakObject* >( this )
930 // 1. Lesen des UnoControls
931 sal_Int32 nLen = InStream->readLong();
932 if (nLen)
934 sal_Int32 nMark = xMark->createMark();
938 readAggregate( InStream );
940 catch( const Exception& )
942 DBG_UNHANDLED_EXCEPTION();
945 xMark->jumpToMark(nMark);
946 InStream->skipBytes(nLen);
947 xMark->deleteMark(nMark);
950 // 2. Lesen des Versionsnummer
951 UINT16 nVersion = InStream->readShort();
953 // 3. Lesen der allgemeinen Properties
954 ::comphelper::operator>>( InStream, m_aName);
955 m_nTabIndex = InStream->readShort();
957 if (nVersion > 0x0002)
958 ::comphelper::operator>>( InStream, m_aTag);
960 // we had a version where we wrote the help text
961 if (nVersion == 0x0004)
962 readHelpTextCompatibly(InStream);
964 DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !");
965 // 4 was the version where we wrote the help text
966 // later versions shouldn't exist (see write for a detailed comment)
969 //------------------------------------------------------------------------------
970 PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle )
972 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyStateByHandle" );
973 // simply compare the current and the default value
974 Any aCurrentValue = getPropertyDefaultByHandle( _nHandle );
975 Any aDefaultValue; getFastPropertyValue( aDefaultValue, _nHandle );
977 sal_Bool bEqual = uno_type_equalData(
978 const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(),
979 const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(),
980 reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
981 reinterpret_cast< uno_ReleaseFunc >(cpp_release)
983 return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
986 //------------------------------------------------------------------------------
987 void OControlModel::setPropertyToDefaultByHandle( sal_Int32 _nHandle)
989 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setPropertyToDefaultByHandle" );
990 Any aDefault = getPropertyDefaultByHandle( _nHandle );
992 Any aConvertedValue, aOldValue;
993 if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) )
995 setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue );
996 // TODO: fire the property change
1000 //------------------------------------------------------------------------------
1001 Any OControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
1003 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyDefaultByHandle" );
1004 Any aReturn;
1005 switch ( _nHandle )
1007 case PROPERTY_ID_NAME:
1008 case PROPERTY_ID_TAG:
1009 aReturn <<= ::rtl::OUString();
1010 break;
1012 case PROPERTY_ID_CLASSID:
1013 aReturn <<= (sal_Int16)FormComponentType::CONTROL;
1014 break;
1016 case PROPERTY_ID_TABINDEX:
1017 aReturn <<= (sal_Int16)FRM_DEFAULT_TABINDEX;
1018 break;
1020 case PROPERTY_ID_NATIVE_LOOK:
1021 aReturn <<= (sal_Bool)sal_True;
1022 break;
1024 default:
1025 if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1026 m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn );
1027 else
1028 OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" );
1030 return aReturn;
1033 //------------------------------------------------------------------------------
1034 void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
1036 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getFastPropertyValue" );
1037 switch ( _nHandle )
1039 case PROPERTY_ID_NAME:
1040 _rValue <<= m_aName;
1041 break;
1042 case PROPERTY_ID_TAG:
1043 _rValue <<= m_aTag;
1044 break;
1045 case PROPERTY_ID_CLASSID:
1046 _rValue <<= m_nClassId;
1047 break;
1048 case PROPERTY_ID_TABINDEX:
1049 _rValue <<= m_nTabIndex;
1050 break;
1051 case PROPERTY_ID_NATIVE_LOOK:
1052 _rValue <<= (sal_Bool)m_bNativeLook;
1053 break;
1054 default:
1055 if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1056 m_aPropertyBagHelper.getDynamicFastPropertyValue( _nHandle, _rValue );
1057 else
1058 OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle );
1059 break;
1063 //------------------------------------------------------------------------------
1064 sal_Bool OControlModel::convertFastPropertyValue(
1065 Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
1066 throw (com::sun::star::lang::IllegalArgumentException)
1068 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::convertFastPropertyValue" );
1069 sal_Bool bModified(sal_False);
1070 switch (_nHandle)
1072 case PROPERTY_ID_NAME:
1073 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName);
1074 break;
1075 case PROPERTY_ID_TAG:
1076 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag);
1077 break;
1078 case PROPERTY_ID_TABINDEX:
1079 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex);
1080 break;
1081 case PROPERTY_ID_NATIVE_LOOK:
1082 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook);
1083 break;
1084 default:
1085 if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1086 bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue );
1087 else
1088 OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" );
1089 break;
1091 return bModified;
1094 //------------------------------------------------------------------------------
1095 void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
1096 throw (Exception)
1098 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setFastPropertyValue_NoBroadcast" );
1099 switch (_nHandle)
1101 case PROPERTY_ID_NAME:
1102 DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL),
1103 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1104 _rValue >>= m_aName;
1105 break;
1106 case PROPERTY_ID_TAG:
1107 DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL),
1108 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1109 _rValue >>= m_aTag;
1110 break;
1111 case PROPERTY_ID_TABINDEX:
1112 DBG_ASSERT(_rValue.getValueType() == getCppuType((const sal_Int16*)NULL),
1113 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1114 _rValue >>= m_nTabIndex;
1115 break;
1116 case PROPERTY_ID_NATIVE_LOOK:
1117 OSL_VERIFY( _rValue >>= m_bNativeLook );
1118 break;
1119 default:
1120 if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1121 m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue );
1122 else
1123 OSL_ENSURE( false, "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle!" );
1124 break;
1128 //------------------------------------------------------------------------------
1129 void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
1131 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeFixedProperties" );
1132 BEGIN_DESCRIBE_BASE_PROPERTIES( 4 )
1133 DECL_PROP2 (CLASSID, sal_Int16, READONLY, TRANSIENT);
1134 DECL_PROP1 (NAME, ::rtl::OUString, BOUND);
1135 DECL_BOOL_PROP2 (NATIVE_LOOK, BOUND, TRANSIENT);
1136 DECL_PROP1 (TAG, ::rtl::OUString, BOUND);
1137 END_DESCRIBE_PROPERTIES()
1140 //------------------------------------------------------------------------------
1141 void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const
1143 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeAggregateProperties" );
1144 if ( m_xAggregateSet.is() )
1146 Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() );
1147 if ( xPSI.is() )
1148 _rAggregateProps = xPSI->getProperties();
1152 //------------------------------------------------------------------------------
1153 ::osl::Mutex& OControlModel::getMutex()
1155 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getMutex" );
1156 return m_aMutex;
1159 //------------------------------------------------------------------------------
1160 void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const
1162 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::describeFixedAndAggregateProperties" );
1163 describeFixedProperties( _out_rFixedProperties );
1164 describeAggregateProperties( _out_rAggregateProperties );
1167 //------------------------------------------------------------------------------
1168 Reference< XMultiPropertySet > OControlModel::getPropertiesInterface()
1170 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertiesInterface" );
1171 return Reference< XMultiPropertySet >( *this, UNO_QUERY );
1174 //------------------------------------------------------------------------------
1175 Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo() throw( RuntimeException)
1177 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertySetInfo" );
1178 return createPropertySetInfo( getInfoHelper() );
1181 //------------------------------------------------------------------------------
1182 ::cppu::IPropertyArrayHelper& OControlModel::getInfoHelper()
1184 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getInfoHelper" );
1185 return m_aPropertyBagHelper.getInfoHelper();
1188 //--------------------------------------------------------------------
1189 void SAL_CALL OControlModel::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException)
1191 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::addProperty" );
1192 m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
1195 //--------------------------------------------------------------------
1196 void SAL_CALL OControlModel::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException)
1198 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::removeProperty" );
1199 m_aPropertyBagHelper.removeProperty( _rName );
1202 //--------------------------------------------------------------------
1203 Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues() throw (RuntimeException)
1205 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getPropertyValues" );
1206 return m_aPropertyBagHelper.getPropertyValues();
1209 //--------------------------------------------------------------------
1210 void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
1212 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setPropertyValues" );
1213 m_aPropertyBagHelper.setPropertyValues( _rProps );
1216 //--------------------------------------------------------------------
1217 void OControlModel::lockInstance( LockAccess )
1219 m_aMutex.acquire();
1220 osl_incrementInterlockedCount( &m_lockCount );
1223 //--------------------------------------------------------------------
1224 oslInterlockedCount OControlModel::unlockInstance( LockAccess )
1226 OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" );
1227 oslInterlockedCount lockCount = osl_decrementInterlockedCount( &m_lockCount );
1228 m_aMutex.release();
1229 return lockCount;
1232 //--------------------------------------------------------------------
1233 void OControlModel::firePropertyChanges( const Sequence< sal_Int32 >& _rHandles, const Sequence< Any >& _rOldValues,
1234 const Sequence< Any >& _rNewValues, LockAccess )
1236 OPropertySetHelper::fire(
1237 const_cast< Sequence< sal_Int32 >& >( _rHandles ).getArray(),
1238 _rNewValues.getConstArray(),
1239 _rOldValues.getConstArray(),
1240 _rHandles.getLength(),
1241 sal_False
1245 //==================================================================
1246 //= OBoundControlModel
1247 //==================================================================
1248 DBG_NAME(frm_OBoundControlModel);
1249 //------------------------------------------------------------------
1250 Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException)
1252 Any aReturn( OControlModel::queryAggregation(_rType) );
1253 if (!aReturn.hasValue())
1255 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::queryAggregation" );
1256 aReturn = OBoundControlModel_BASE1::queryInterface(_rType);
1258 if ( !aReturn.hasValue() && m_bCommitable )
1259 aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType );
1261 if ( !aReturn.hasValue() && m_bSupportsExternalBinding )
1262 aReturn = OBoundControlModel_BINDING::queryInterface( _rType );
1264 if ( !aReturn.hasValue() && m_bSupportsValidation )
1265 aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType );
1268 return aReturn;
1271 //------------------------------------------------------------------
1272 OBoundControlModel::OBoundControlModel(
1273 const Reference< XMultiServiceFactory>& _rxFactory,
1274 const ::rtl::OUString& _rUnoControlModelTypeName, const ::rtl::OUString& _rDefault,
1275 const sal_Bool _bCommitable, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation )
1276 :OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False )
1277 ,OPropertyChangeListener( m_aMutex )
1278 ,m_xField()
1279 ,m_xAmbientForm()
1280 ,m_nValuePropertyAggregateHandle( -1 )
1281 ,m_nFieldType( DataType::OTHER )
1282 ,m_bValuePropertyMayBeVoid( false )
1283 ,m_aResetHelper( *this, m_aMutex )
1284 ,m_aUpdateListeners(m_aMutex)
1285 ,m_aFormComponentListeners( m_aMutex )
1286 ,m_bInputRequired( sal_True )
1287 ,m_pAggPropMultiplexer( NULL )
1288 ,m_bFormListening( false )
1289 ,m_bLoaded(sal_False)
1290 ,m_bRequired(sal_False)
1291 ,m_bCommitable(_bCommitable)
1292 ,m_bSupportsExternalBinding( _bSupportExternalBinding )
1293 ,m_bSupportsValidation( _bSupportsValidation )
1294 ,m_bForwardValueChanges(sal_True)
1295 ,m_bTransferingValue( sal_False )
1296 ,m_bIsCurrentValueValid( sal_True )
1297 ,m_bBindingControlsRO( sal_False )
1298 ,m_bBindingControlsEnable( sal_False )
1299 ,m_eControlValueChangeInstigator( eOther )
1300 ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT)
1302 DBG_CTOR(frm_OBoundControlModel, NULL);
1304 // start property listening at the aggregate
1305 implInitAggMultiplexer( );
1308 //------------------------------------------------------------------
1309 OBoundControlModel::OBoundControlModel(
1310 const OBoundControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory )
1311 :OControlModel( _pOriginal, _rxFactory, sal_True, sal_False )
1312 ,OPropertyChangeListener( m_aMutex )
1313 ,m_xField()
1314 ,m_xAmbientForm()
1315 ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle )
1316 ,m_nFieldType( DataType::OTHER )
1317 ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid )
1318 ,m_aResetHelper( *this, m_aMutex )
1319 ,m_aUpdateListeners( m_aMutex )
1320 ,m_aFormComponentListeners( m_aMutex )
1321 ,m_xValidator( _pOriginal->m_xValidator )
1322 ,m_bInputRequired( sal_True )
1323 ,m_pAggPropMultiplexer( NULL )
1324 ,m_bFormListening( false )
1325 ,m_bLoaded( sal_False )
1326 ,m_bRequired( sal_False )
1327 ,m_bCommitable( _pOriginal->m_bCommitable )
1328 ,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding )
1329 ,m_bSupportsValidation( _pOriginal->m_bSupportsValidation )
1330 ,m_bForwardValueChanges( sal_True )
1331 ,m_bTransferingValue( sal_False )
1332 ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid )
1333 ,m_bBindingControlsRO( sal_False )
1334 ,m_bBindingControlsEnable( sal_False )
1335 ,m_eControlValueChangeInstigator( eOther )
1337 DBG_CTOR(frm_OBoundControlModel, NULL);
1339 // start property listening at the aggregate
1340 implInitAggMultiplexer( );
1342 m_aLabelServiceName = _pOriginal->m_aLabelServiceName;
1343 m_sValuePropertyName = _pOriginal->m_sValuePropertyName;
1344 m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle;
1345 m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid;
1346 m_aValuePropertyType = _pOriginal->m_aValuePropertyType;
1347 m_aControlSource = _pOriginal->m_aControlSource;
1348 m_bInputRequired = _pOriginal->m_bInputRequired;
1349 // m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transfered.
1350 // (the former should be clear - a clone of the object we're only referencing does not make sense)
1351 // (the second would violate the restriction for label controls that they're part of the
1352 // same form component hierarchy - we ourself are no part, yet, so we can't have a label control)
1354 // start listening for changes at the value property
1355 implInitValuePropertyListening( );
1358 //------------------------------------------------------------------
1359 OBoundControlModel::~OBoundControlModel()
1361 if ( !OComponentHelper::rBHelper.bDisposed )
1363 acquire();
1364 dispose();
1367 doResetDelegator( );
1369 OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" );
1370 if ( m_pAggPropMultiplexer )
1372 m_pAggPropMultiplexer->dispose();
1373 m_pAggPropMultiplexer->release();
1374 m_pAggPropMultiplexer = NULL;
1377 DBG_DTOR(frm_OBoundControlModel, NULL);
1380 //------------------------------------------------------------------
1381 void OBoundControlModel::clonedFrom( const OControlModel* _pOriginal )
1383 const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal );
1384 // the value binding can be handled as if somebody called setValueBinding here
1385 // By definition, bindings can be share between bindables
1386 if ( pBoundOriginal && pBoundOriginal->m_xExternalBinding.is() )
1390 setValueBinding( pBoundOriginal->m_xExternalBinding );
1392 catch( const Exception& )
1394 DBG_UNHANDLED_EXCEPTION();
1399 //-----------------------------------------------------------------------------
1400 void OBoundControlModel::implInitAggMultiplexer( )
1402 increment( m_refCount );
1403 if ( m_xAggregateSet.is() )
1405 m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, sal_False );
1406 m_pAggPropMultiplexer->acquire();
1408 decrement( m_refCount );
1410 doSetDelegator();
1413 //-----------------------------------------------------------------------------
1414 void OBoundControlModel::implInitValuePropertyListening( ) const
1416 // start listening for changes at the value property
1417 // There are three pre-requisites for this to be done:
1418 // 1. We support external value bindings. In this case, the changes in the control value need to
1419 // be propagated to the external binding immediately when they happen
1420 // 2. We support external validation. In this case, we need to listen for changes in the value
1421 // property, since we need to revalidate then.
1422 // 3. We are not committable. In this case, changes in the control value need to be propagated
1423 // to the database column immediately when they happen.
1424 if ( m_bSupportsExternalBinding || m_bSupportsValidation || !m_bCommitable )
1426 OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" );
1427 if ( m_pAggPropMultiplexer && m_sValuePropertyName.getLength() )
1428 m_pAggPropMultiplexer->addProperty( m_sValuePropertyName );
1432 //-----------------------------------------------------------------------------
1433 void OBoundControlModel::initValueProperty( const ::rtl::OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle )
1435 OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle,
1436 "OBoundControlModel::initValueProperty: already called before!" );
1437 OSL_ENSURE( _rValuePropertyName.getLength(), "OBoundControlModel::initValueProperty: invalid property name!" );
1438 OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" );
1440 m_sValuePropertyName = _rValuePropertyName;
1441 m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle );
1442 OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" );
1444 if ( m_nValuePropertyAggregateHandle != -1 )
1446 Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW );
1447 Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName );
1448 m_aValuePropertyType = aValuePropDesc.Type;
1449 m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0;
1452 // start listening for changes at the value property
1453 implInitValuePropertyListening( );
1456 //-----------------------------------------------------------------------------
1457 void OBoundControlModel::suspendValueListening( )
1459 OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::suspendValueListening: don't have a value property!" );
1460 OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" );
1462 if ( m_pAggPropMultiplexer )
1463 m_pAggPropMultiplexer->lock();
1466 //-----------------------------------------------------------------------------
1467 void OBoundControlModel::resumeValueListening( )
1469 OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::resumeValueListening: don't have a value property!" );
1470 OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" );
1471 OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" );
1473 if ( m_pAggPropMultiplexer )
1474 m_pAggPropMultiplexer->unlock();
1477 //-----------------------------------------------------------------------------
1478 Sequence< Type > OBoundControlModel::_getTypes()
1480 TypeBag aTypes(
1481 OControlModel::_getTypes(),
1482 OBoundControlModel_BASE1::getTypes()
1485 if ( m_bCommitable )
1486 aTypes.addTypes( OBoundControlModel_COMMITTING::getTypes() );
1488 if ( m_bSupportsExternalBinding )
1489 aTypes.addTypes( OBoundControlModel_BINDING::getTypes() );
1491 if ( m_bSupportsValidation )
1492 aTypes.addTypes( OBoundControlModel_VALIDATION::getTypes() );
1494 return aTypes.getTypes();
1497 // OComponentHelper
1498 //-----------------------------------------------------------------------------
1499 void OBoundControlModel::disposing()
1501 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::_getTypes" );
1502 OControlModel::disposing();
1504 ::osl::ClearableMutexGuard aGuard(m_aMutex);
1506 if ( m_pAggPropMultiplexer )
1507 m_pAggPropMultiplexer->dispose();
1509 // notify all our listeners
1510 com::sun::star::lang::EventObject aEvt( static_cast< XWeak* >( this ) );
1511 m_aUpdateListeners.disposeAndClear( aEvt );
1512 m_aResetHelper.disposing();
1514 // disconnect from our database column
1515 // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify?
1516 // The only more thing which it does is calling onDisconnectedDbColumn - could this
1517 // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*.
1518 if ( hasField() )
1520 getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
1521 resetField();
1523 m_xCursor = NULL;
1525 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1526 if ( xComp.is() )
1527 xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) );
1529 // disconnect from our external value binding
1530 if ( hasExternalValueBinding() )
1531 disconnectExternalValueBinding();
1533 // dito for the validator
1534 if ( hasValidator() )
1535 disconnectValidator( );
1538 //------------------------------------------------------------------------------
1539 void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) throw ( RuntimeException )
1541 ControlModelLock aLock( *this );
1543 OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName,
1544 "OBoundControlModel::_propertyChanged: where did this come from (1)?" );
1545 OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(),
1546 "OBoundControlModel::_propertyChanged: where did this come from (2)?" );
1548 if ( _rEvt.PropertyName == m_sValuePropertyName )
1549 { // our control value changed
1551 if ( hasExternalValueBinding() )
1552 { // the control value changed, while we have an external value binding
1553 // -> forward the value to it
1554 if ( m_eControlValueChangeInstigator != eExternalBinding )
1555 transferControlValueToExternal( aLock );
1557 else if ( !m_bCommitable && m_xColumnUpdate.is() )
1558 { // the control value changed, while we are bound to a database column,
1559 // but not committable (which means changes in the control have to be reflected to
1560 // the underlying database column immediately)
1561 // -> forward the value to the database column
1562 if ( m_eControlValueChangeInstigator != eDbColumnBinding )
1563 commitControlValueToDbColumn( false );
1566 // validate the new value
1567 if ( m_bSupportsValidation )
1568 recheckValidity( true );
1572 //------------------------------------------------------------------------------
1573 void OBoundControlModel::startAggregatePropertyListening( const ::rtl::OUString& _rPropertyName )
1575 OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" );
1576 OSL_ENSURE( _rPropertyName.getLength(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" );
1578 if ( m_pAggPropMultiplexer && _rPropertyName.getLength() )
1580 m_pAggPropMultiplexer->addProperty( _rPropertyName );
1584 //------------------------------------------------------------------------------
1585 void OBoundControlModel::doFormListening( const bool _bStart )
1587 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" );
1589 if ( isFormListening() == _bStart )
1590 return;
1592 if ( m_xAmbientForm.is() )
1593 _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this );
1595 Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY );
1596 if ( getParent().is() && !xParentLoadable.is() )
1598 // if our parent does not directly support the XLoadable interface, then it might support the
1599 // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes
1600 // broadcasted by the latter.
1601 Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY );
1602 if ( xRowSetBroadcaster.is() )
1603 _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this );
1606 m_bFormListening = _bStart && m_xAmbientForm.is();
1609 // XChild
1610 //------------------------------------------------------------------------------
1611 void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException)
1613 ControlModelLock aLock( *this );
1614 FieldChangeNotifier aBoundFieldNotifier( aLock );
1616 if ( getParent() == _rxParent )
1617 return;
1619 // disconnect from database column (which is controlled by parent, directly or indirectly)
1620 if ( hasField() )
1621 impl_disconnectDatabaseColumn_noNotify();
1623 // log off old listeners
1624 if ( isFormListening() )
1625 doFormListening( false );
1627 // actually set the new parent
1628 OControlModel::setParent( _rxParent );
1630 // a new parent means a new ambient form
1631 impl_determineAmbientForm_nothrow();
1633 if ( !hasExternalValueBinding() )
1635 // log on new listeners
1636 doFormListening( true );
1638 // re-connect to database column of the new parent
1639 if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
1640 impl_connectDatabaseColumn_noNotify( false );
1644 // XEventListener
1645 //------------------------------------------------------------------------------
1646 void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException)
1648 ControlModelLock aLock( *this );
1650 if ( _rEvent.Source == getField() )
1652 resetField();
1654 else if ( _rEvent.Source == m_xLabelControl )
1656 Reference<XPropertySet> xOldValue = m_xLabelControl;
1657 m_xLabelControl = NULL;
1659 // fire a propertyChanged (when we leave aLock's scope)
1660 aLock.addPropertyNotification( PROPERTY_ID_CONTROLLABEL, makeAny( xOldValue ), makeAny( m_xLabelControl ) );
1662 else if ( _rEvent.Source == m_xExternalBinding )
1663 { // *first* check for the external binding
1664 disconnectExternalValueBinding( );
1666 else if ( _rEvent.Source == m_xValidator )
1667 { // *then* check for the validator. Reason is that bindings may also act as validator at the same
1668 // time, in this case, the validator is automatically revoked when the binding is revoked
1669 disconnectValidator( );
1671 else
1672 OControlModel::disposing(_rEvent);
1675 // XServiceInfo
1676 //------------------------------------------------------------------------------
1677 StringSequence SAL_CALL OBoundControlModel::getSupportedServiceNames() throw(RuntimeException)
1679 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::disposing" );
1680 return ::comphelper::concatSequences(
1681 getAggregateServiceNames(),
1682 getSupportedServiceNames_Static()
1686 //------------------------------------------------------------------------------
1687 Sequence< ::rtl::OUString > SAL_CALL OBoundControlModel::getSupportedServiceNames_Static() throw( RuntimeException )
1689 Sequence< ::rtl::OUString > aOwnServiceNames( 1 );
1690 aOwnServiceNames[ 0 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.DataAwareControlModel" );
1692 return ::comphelper::concatSequences(
1693 OControlModel::getSupportedServiceNames_Static(),
1694 aOwnServiceNames
1698 // XPersist
1699 //------------------------------------------------------------------------------
1700 void SAL_CALL OBoundControlModel::write( const Reference<stario::XObjectOutputStream>& _rxOutStream ) throw(stario::IOException, RuntimeException)
1702 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::getSupportedServiceNames_Static" );
1703 OControlModel::write(_rxOutStream);
1705 osl::MutexGuard aGuard(m_aMutex);
1707 // Version
1708 _rxOutStream->writeShort(0x0002);
1710 // Controlsource
1711 ::comphelper::operator<<( _rxOutStream, m_aControlSource);
1713 // !!! IMPORTANT NOTE !!!
1714 // don't write any new members here : this wouldn't be compatible with older versions, as OBoundControlModel
1715 // is a base class which is called in derived classes "read" method. So if you increment the version
1716 // and write new stuff, older office versions will read this in the _derived_ classes, which may result
1717 // in anything from data loss to crash.
1718 // (use writeCommonProperties instead, this is called in derived classes write-method)
1719 // !!! EOIN !!!
1720 // FS - 68876 - 28.09.1999
1723 //------------------------------------------------------------------------------
1724 void OBoundControlModel::defaultCommonProperties()
1726 Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1727 if (xComp.is())
1728 xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1729 m_xLabelControl = NULL;
1732 //------------------------------------------------------------------------------
1733 void OBoundControlModel::readCommonProperties(const Reference<stario::XObjectInputStream>& _rxInStream)
1735 sal_Int32 nLen = _rxInStream->readLong();
1737 Reference<stario::XMarkableStream> xMark(_rxInStream, UNO_QUERY);
1738 DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
1739 sal_Int32 nMark = xMark->createMark();
1741 // read the reference to the label control
1742 Reference<stario::XPersistObject> xPersist;
1743 sal_Int32 nUsedFlag;
1744 nUsedFlag = _rxInStream->readLong();
1745 if (nUsedFlag)
1746 xPersist = _rxInStream->readObject();
1747 m_xLabelControl = m_xLabelControl.query( xPersist );
1748 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1749 if (xComp.is())
1750 xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1752 // read any other new common properties here
1754 // skip the remaining bytes
1755 xMark->jumpToMark(nMark);
1756 _rxInStream->skipBytes(nLen);
1757 xMark->deleteMark(nMark);
1760 //------------------------------------------------------------------------------
1761 void OBoundControlModel::writeCommonProperties(const Reference<stario::XObjectOutputStream>& _rxOutStream)
1763 Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
1764 DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !");
1765 sal_Int32 nMark = xMark->createMark();
1767 // a placeholder where we will write the overall length (later in this method)
1768 sal_Int32 nLen = 0;
1769 _rxOutStream->writeLong(nLen);
1771 // write the reference to the label control
1772 Reference<stario::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY);
1773 sal_Int32 nUsedFlag = 0;
1774 if (xPersist.is())
1775 nUsedFlag = 1;
1776 _rxOutStream->writeLong(nUsedFlag);
1777 if (xPersist.is())
1778 _rxOutStream->writeObject(xPersist);
1780 // write any other new common properties here
1782 // write the correct length at the beginning of the block
1783 nLen = xMark->offsetToMark(nMark) - sizeof(nLen);
1784 xMark->jumpToMark(nMark);
1785 _rxOutStream->writeLong(nLen);
1786 xMark->jumpToFurthest();
1787 xMark->deleteMark(nMark);
1790 //------------------------------------------------------------------------------
1791 void SAL_CALL OBoundControlModel::read( const Reference< stario::XObjectInputStream >& _rxInStream ) throw(stario::IOException, RuntimeException)
1793 OControlModel::read(_rxInStream);
1795 osl::MutexGuard aGuard(m_aMutex);
1796 UINT16 nVersion = _rxInStream->readShort(); (void)nVersion;
1797 ::comphelper::operator>>( _rxInStream, m_aControlSource);
1800 //------------------------------------------------------------------------------
1801 void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
1803 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OBoundControlModel::getFastPropertyValue" );
1804 switch (nHandle)
1806 case PROPERTY_ID_INPUT_REQUIRED:
1807 rValue <<= m_bInputRequired;
1808 break;
1809 case PROPERTY_ID_CONTROLSOURCEPROPERTY:
1810 rValue <<= m_sValuePropertyName;
1811 break;
1812 case PROPERTY_ID_CONTROLSOURCE:
1813 rValue <<= m_aControlSource;
1814 break;
1815 case PROPERTY_ID_BOUNDFIELD:
1816 rValue <<= getField();
1817 break;
1818 case PROPERTY_ID_CONTROLLABEL:
1819 if (!m_xLabelControl.is())
1820 rValue.clear();
1821 else
1822 rValue <<= m_xLabelControl;
1823 break;
1824 default:
1825 OControlModel::getFastPropertyValue(rValue, nHandle);
1829 //------------------------------------------------------------------------------
1830 sal_Bool OBoundControlModel::convertFastPropertyValue(
1831 Any& _rConvertedValue, Any& _rOldValue,
1832 sal_Int32 _nHandle,
1833 const Any& _rValue)
1834 throw (com::sun::star::lang::IllegalArgumentException)
1836 sal_Bool bModified(sal_False);
1837 switch (_nHandle)
1839 case PROPERTY_ID_INPUT_REQUIRED:
1840 bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired );
1841 break;
1842 case PROPERTY_ID_CONTROLSOURCE:
1843 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource);
1844 break;
1845 case PROPERTY_ID_BOUNDFIELD:
1846 DBG_ERROR( "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" );
1847 throw com::sun::star::lang::IllegalArgumentException();
1848 case PROPERTY_ID_CONTROLLABEL:
1849 if (!_rValue.hasValue())
1850 { // property set to void
1851 _rConvertedValue = Any();
1852 getFastPropertyValue(_rOldValue, _nHandle);
1853 bModified = m_xLabelControl.is();
1855 else
1857 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl);
1858 if (!m_xLabelControl.is())
1859 // an empty interface is interpreted as VOID
1860 _rOldValue.clear();
1862 break;
1863 default:
1864 bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
1866 return bModified;
1869 //------------------------------------------------------------------------------
1870 Any OBoundControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
1872 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::convertFastPropertyValue" );
1873 Any aDefault;
1874 switch ( _nHandle )
1876 case PROPERTY_ID_INPUT_REQUIRED:
1877 aDefault <<= sal_Bool( sal_True );
1878 break;
1880 case PROPERTY_ID_CONTROLSOURCE:
1881 aDefault <<= ::rtl::OUString();
1882 break;
1884 case PROPERTY_ID_CONTROLLABEL:
1885 aDefault <<= Reference< XPropertySet >();
1886 break;
1888 return aDefault;
1891 //------------------------------------------------------------------------------
1892 void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
1894 switch (nHandle)
1896 case PROPERTY_ID_INPUT_REQUIRED:
1897 OSL_VERIFY( rValue >>= m_bInputRequired );
1898 break;
1899 case PROPERTY_ID_CONTROLSOURCE:
1900 OSL_VERIFY( rValue >>= m_aControlSource );
1901 break;
1902 case PROPERTY_ID_BOUNDFIELD:
1903 DBG_ERROR("OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !");
1904 throw com::sun::star::lang::IllegalArgumentException();
1905 case PROPERTY_ID_CONTROLLABEL:
1907 DBG_ASSERT(!rValue.hasValue() || (rValue.getValueType().getTypeClass() == TypeClass_INTERFACE),
1908 "OBoundControlModel::setFastPropertyValue_NoBroadcast : invalid argument !");
1909 if (!rValue.hasValue())
1910 { // set property to "void"
1911 Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1912 if (xComp.is())
1913 xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1914 m_xLabelControl = NULL;
1915 break;
1918 InterfaceRef xNewValue;
1919 rValue >>= xNewValue;
1921 Reference<XControlModel> xAsModel(xNewValue, UNO_QUERY);
1922 Reference<com::sun::star::lang::XServiceInfo> xAsServiceInfo(xNewValue, UNO_QUERY);
1923 Reference<XPropertySet> xAsPropSet(xNewValue, UNO_QUERY);
1924 Reference<XChild> xAsChild(xNewValue, UNO_QUERY);
1925 if (!xAsModel.is() || !xAsServiceInfo.is() || !xAsPropSet.is() || !xAsChild.is())
1927 throw com::sun::star::lang::IllegalArgumentException();
1930 if (!xAsServiceInfo->supportsService(m_aLabelServiceName))
1932 throw com::sun::star::lang::IllegalArgumentException();
1935 // check if weself and the given model have a common anchestor (up to the forms collection)
1936 Reference<XChild> xCont;
1937 query_interface(static_cast<XWeak*>(this), xCont);
1938 InterfaceRef xMyTopLevel = xCont->getParent();
1939 while (xMyTopLevel.is())
1941 Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY);
1942 if (!xAsForm.is())
1943 // found my root
1944 break;
1946 Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY);
1947 xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : InterfaceRef();
1949 InterfaceRef xNewTopLevel = xAsChild->getParent();
1950 while (xNewTopLevel.is())
1952 Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY);
1953 if (!xAsForm.is())
1954 break;
1956 Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY);
1957 xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : InterfaceRef();
1959 if (xNewTopLevel != xMyTopLevel)
1961 // the both objects don't belong to the same forms collection -> not acceptable
1962 throw com::sun::star::lang::IllegalArgumentException();
1965 m_xLabelControl = xAsPropSet;
1966 Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1967 if (xComp.is())
1968 xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1970 break;
1971 default:
1972 OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue );
1976 // XPropertyChangeListener
1977 //------------------------------------------------------------------------------
1978 void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException)
1980 // RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "forms", "dev@dba.openoffice.org", "OControlModel::setFastPropertyValue_NoBroadcast" );
1981 // if the DBColumn value changed, transfer it to the control
1982 if ( evt.PropertyName.equals( PROPERTY_VALUE ) )
1984 OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database colum?" );
1985 osl::MutexGuard aGuard(m_aMutex);
1986 if ( m_bForwardValueChanges && m_xColumn.is() )
1987 transferDbValueToControl();
1989 else
1991 OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" );
1993 // our binding has properties which can control properties of ourself
1994 ::rtl::OUString sBindingControlledProperty;
1995 bool bForwardToLabelControl = false;
1996 if ( evt.PropertyName.equals( PROPERTY_READONLY ) )
1998 sBindingControlledProperty = PROPERTY_READONLY;
2000 else if ( evt.PropertyName.equals( PROPERTY_RELEVANT ) )
2002 sBindingControlledProperty = PROPERTY_ENABLED;
2003 bForwardToLabelControl = true;
2005 else
2006 return;
2010 setPropertyValue( sBindingControlledProperty, evt.NewValue );
2011 if ( bForwardToLabelControl && m_xLabelControl.is() )
2012 m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue );
2014 catch( const Exception& )
2016 OSL_ENSURE( sal_False, "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!" );
2021 //------------------------------------------------------------------------------
2022 void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ ) throw (RuntimeException)
2024 ControlModelLock aLock( *this );
2025 FieldChangeNotifier aBoundFieldNotifier( aLock );
2027 // disconnect from database column (which is controlled by parent, directly or indirectly)
2028 if ( hasField() )
2029 impl_disconnectDatabaseColumn_noNotify();
2031 // log off old listeners
2032 if ( isFormListening() )
2033 doFormListening( false );
2035 // determine the new ambient form
2036 impl_determineAmbientForm_nothrow();
2038 // log on new listeners
2039 doFormListening( true );
2041 // re-connect to database column if needed and possible
2042 if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
2043 impl_connectDatabaseColumn_noNotify( false );
2046 // XBoundComponent
2047 //------------------------------------------------------------------------------
2048 void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener) throw(RuntimeException)
2050 m_aUpdateListeners.addInterface(_rxListener);
2053 //------------------------------------------------------------------------------
2054 void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener) throw(RuntimeException)
2056 m_aUpdateListeners.removeInterface(_rxListener);
2059 //------------------------------------------------------------------------------
2060 sal_Bool SAL_CALL OBoundControlModel::commit() throw(RuntimeException)
2062 ControlModelLock aLock( *this );
2064 OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not commitable !) " );
2065 if ( hasExternalValueBinding() )
2067 // in most cases, no action is required: For most derivees, we know the value property of
2068 // our control (see initValueProperty), and when an external binding is active, we
2069 // instantly forward all changes in this property to the external binding.
2070 if ( !m_sValuePropertyName.getLength() )
2071 // but for those derivees which did not use this feature, we need an
2072 // explicit transfer
2073 transferControlValueToExternal( aLock );
2074 return sal_True;
2077 OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" );
2078 // we reach this only if we're not working with an external binding
2080 if ( !hasField() )
2081 return sal_True;
2083 ::cppu::OInterfaceIteratorHelper aIter( m_aUpdateListeners );
2084 EventObject aEvent;
2085 aEvent.Source = static_cast< XWeak* >( this );
2086 sal_Bool bSuccess = sal_True;
2088 aLock.release();
2089 // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2090 while (aIter.hasMoreElements() && bSuccess)
2091 bSuccess = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvent );
2092 // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2093 aLock.acquire();
2095 if ( bSuccess )
2099 if ( m_xColumnUpdate.is() )
2100 bSuccess = commitControlValueToDbColumn( sal_False );
2102 catch(Exception&)
2104 bSuccess = sal_False;
2108 if ( bSuccess )
2110 aLock.release();
2111 m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent );
2114 return bSuccess;
2117 //------------------------------------------------------------------------------
2118 void OBoundControlModel::resetField()
2120 m_xColumnUpdate.clear();
2121 m_xColumn.clear();
2122 m_xField.clear();
2123 m_nFieldType = DataType::OTHER;
2126 //------------------------------------------------------------------------------
2127 sal_Bool OBoundControlModel::connectToField(const Reference<XRowSet>& rForm)
2129 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" );
2131 // wenn eine Verbindung zur Datenbank existiert
2132 if (rForm.is() && getConnection(rForm).is())
2134 // Feld bestimmen und PropertyChangeListener
2135 m_xCursor = rForm;
2136 Reference<XPropertySet> xFieldCandidate;
2138 if (m_xCursor.is())
2140 Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY);
2141 DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the com::sun::star::sdb::ResultSet service !");
2142 if (xColumnsSupplier.is())
2144 Reference<XNameAccess> xColumns(xColumnsSupplier->getColumns(), UNO_QUERY);
2145 if (xColumns.is() && xColumns->hasByName(m_aControlSource))
2147 OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate );
2154 sal_Int32 nFieldType = DataType::OTHER;
2155 if ( xFieldCandidate.is() )
2157 xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
2158 if ( approveDbColumnType( nFieldType ) )
2159 impl_setField_noNotify( xFieldCandidate );
2161 else
2162 impl_setField_noNotify( NULL );
2164 if ( m_xField.is() )
2166 if( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) )
2168 m_nFieldType = nFieldType;
2170 // an wertaenderungen horchen
2171 m_xField->addPropertyChangeListener( PROPERTY_VALUE, this );
2172 m_xColumnUpdate = Reference< XColumnUpdate >( m_xField, UNO_QUERY );
2173 m_xColumn = Reference< XColumn >( m_xField, UNO_QUERY );
2175 INT32 nNullableFlag = ColumnValue::NO_NULLS;
2176 m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag;
2177 m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag);
2178 // we're optimistic : in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability ....
2180 else
2182 OSL_ENSURE(sal_False, "OBoundControlModel::connectToField: property NAME not supported!");
2183 impl_setField_noNotify( NULL );
2187 catch( const Exception& )
2189 DBG_UNHANDLED_EXCEPTION();
2190 resetField();
2193 return hasField();
2196 //------------------------------------------------------------------------------
2197 void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet )
2199 // but only if the rowset if posisitioned on a valid record
2200 if ( hasField() && _rxRowSet.is() )
2202 if ( !_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast() )
2203 transferDbValueToControl();
2204 else
2205 // reset the field if the row set is empty
2206 // #i30661# / 2004-12-16 / frank.schoenheit@sun.com
2207 resetNoBroadcast();
2211 //------------------------------------------------------------------------------
2212 sal_Bool OBoundControlModel::approveDbColumnType(sal_Int32 _nColumnType)
2214 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" );
2216 if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY)
2217 || (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER)
2218 || (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT)
2219 || (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY)
2220 || (_nColumnType == DataType::BLOB) || (_nColumnType == DataType::CLOB)
2221 || (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL))
2222 return sal_False;
2224 return sal_True;
2227 //------------------------------------------------------------------------------
2228 void OBoundControlModel::impl_determineAmbientForm_nothrow()
2230 Reference< XInterface > xParent( const_cast< OBoundControlModel* >( this )->getParent() );
2232 m_xAmbientForm.set( xParent, UNO_QUERY );
2233 if ( !m_xAmbientForm.is() )
2235 Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY );
2236 if ( xSupRowSet.is() )
2237 m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY );
2241 //------------------------------------------------------------------------------
2242 void OBoundControlModel::impl_connectDatabaseColumn_noNotify( bool _bFromReload )
2244 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" );
2246 // consistency checks
2247 DBG_ASSERT( !( hasField() && !_bFromReload ),
2248 "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" );
2249 (void)_bFromReload;
2251 Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY );
2252 OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" );
2253 if ( !xRowSet.is() )
2254 return;
2256 if ( !hasField() )
2258 // connect to the column
2259 connectToField( xRowSet );
2262 // now that we're connected (more or less, even if we did not find a column),
2263 // we definately want to forward any potentially occuring value changes
2264 m_bForwardValueChanges = sal_True;
2266 // let derived classes react on this new connection
2267 m_bLoaded = sal_True;
2268 onConnectedDbColumn( xRowSet );
2270 // initially transfer the db column value to the control, if we successfully connected to a database column
2271 if ( hasField() )
2272 initFromField( xRowSet );
2275 //------------------------------------------------------------------------------
2276 void OBoundControlModel::impl_disconnectDatabaseColumn_noNotify()
2278 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" );
2280 // let derived classes react on this
2281 onDisconnectedDbColumn();
2283 if ( hasField() )
2285 getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
2286 resetField();
2289 m_xCursor = NULL;
2290 m_bLoaded = sal_False;
2293 //==============================================================================
2294 // XLoadListener
2295 //------------------------------------------------------------------------------
2296 void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent ) throw(RuntimeException)
2298 ControlModelLock aLock( *this );
2299 FieldChangeNotifier aBoundFieldNotifier( aLock );
2301 OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" );
2302 (void)_rEvent;
2304 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" );
2305 if ( hasExternalValueBinding() )
2306 return;
2308 impl_connectDatabaseColumn_noNotify( false );
2312 //------------------------------------------------------------------------------
2313 void SAL_CALL OBoundControlModel::unloaded( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException)
2315 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" );
2318 //------------------------------------------------------------------------------
2319 void SAL_CALL OBoundControlModel::reloading( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException)
2321 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" );
2322 if ( hasExternalValueBinding() )
2323 return;
2325 osl::MutexGuard aGuard(m_aMutex);
2326 m_bForwardValueChanges = sal_False;
2329 //------------------------------------------------------------------------------
2330 void SAL_CALL OBoundControlModel::unloading(const com::sun::star::lang::EventObject& /*aEvent*/) throw(RuntimeException)
2332 ControlModelLock aLock( *this );
2333 FieldChangeNotifier aBoundFieldNotifier( aLock );
2335 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" );
2336 if ( hasExternalValueBinding() )
2337 return;
2339 impl_disconnectDatabaseColumn_noNotify();
2342 //------------------------------------------------------------------------------
2343 void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent ) throw(RuntimeException)
2345 ControlModelLock aLock( *this );
2346 FieldChangeNotifier aBoundFieldNotifier( aLock );
2348 OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" );
2349 (void)_rEvent;
2351 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" );
2352 if ( hasExternalValueBinding() )
2353 return;
2355 impl_connectDatabaseColumn_noNotify( true );
2358 //------------------------------------------------------------------------------
2359 void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator )
2361 m_eControlValueChangeInstigator = _eInstigator;
2362 doSetControlValue( _rValue );
2363 m_eControlValueChangeInstigator = eOther;
2366 //------------------------------------------------------------------------------
2367 void OBoundControlModel::doSetControlValue( const Any& _rValue )
2369 OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
2370 "OBoundControlModel::doSetControlValue: invalid aggregate !" );
2371 OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ),
2372 "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" );
2376 // release our mutex once (it's acquired in one of the the calling methods), as setting aggregate properties
2377 // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with
2378 // our own mutex locked
2379 // #72451# / 2000-01-31 / frank.schoenheit@sun.com
2380 MutexRelease aRelease( m_aMutex );
2381 if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
2383 m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue );
2385 else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() )
2387 m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue );
2390 catch( const Exception& )
2392 OSL_ENSURE( sal_False, "OBoundControlModel::doSetControlValue: caught an exception!" );
2396 //------------------------------------------------------------------------------
2397 void OBoundControlModel::onConnectedValidator( )
2401 // if we have an external validator, we do not want the control to force invalid
2402 // inputs to the default value. Instead, invalid inputs should be translated
2403 // to NaN (not a number)
2404 Reference< XPropertySetInfo > xAggregatePropertyInfo;
2405 if ( m_xAggregateSet.is() )
2406 xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
2407 if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
2408 m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_False ) );
2410 catch( const Exception& )
2412 OSL_ENSURE( sal_False, "OBoundControlModel::onConnectedValidator: caught an exception!" );
2414 recheckValidity( false );
2417 //------------------------------------------------------------------------------
2418 void OBoundControlModel::onDisconnectedValidator( )
2422 Reference< XPropertySetInfo > xAggregatePropertyInfo;
2423 if ( m_xAggregateSet.is() )
2424 xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
2425 if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
2426 m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_True ) );
2428 catch( const Exception& )
2430 OSL_ENSURE( sal_False, "OBoundControlModel::onDisconnectedValidator: caught an exception!" );
2432 recheckValidity( false );
2435 //------------------------------------------------------------------------------
2436 void OBoundControlModel::onConnectedExternalValue( )
2438 calculateExternalValueType();
2441 //------------------------------------------------------------------------------
2442 void OBoundControlModel::onDisconnectedExternalValue( )
2446 //------------------------------------------------------------------------------
2447 void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
2449 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" );
2452 //------------------------------------------------------------------------------
2453 void OBoundControlModel::onDisconnectedDbColumn()
2455 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" );
2458 // XReset
2459 //-----------------------------------------------------------------------------
2460 Any OBoundControlModel::getDefaultForReset() const
2462 return Any();
2465 //-----------------------------------------------------------------------------
2466 void OBoundControlModel::resetNoBroadcast()
2468 setControlValue( getDefaultForReset(), eOther );
2471 //-----------------------------------------------------------------------------
2472 void OBoundControlModel::addResetListener(const Reference<XResetListener>& l) throw (RuntimeException)
2474 m_aResetHelper.addResetListener( l );
2477 //-----------------------------------------------------------------------------
2478 void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l) throw (RuntimeException)
2480 m_aResetHelper.removeResetListener( l );
2483 //-----------------------------------------------------------------------------
2484 void OBoundControlModel::reset() throw (RuntimeException)
2486 if ( !m_aResetHelper.approveReset() )
2487 return;
2489 ControlModelLock aLock( *this );
2491 // on a new record?
2492 sal_Bool bIsNewRecord = sal_False;
2493 Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY );
2494 if ( xSet.is() )
2498 xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord;
2500 catch( const Exception& )
2502 DBG_UNHANDLED_EXCEPTION();
2506 // cursor on an invalid row?
2507 sal_Bool bInvalidCursorPosition = sal_True;
2510 bInvalidCursorPosition = m_xCursor.is()
2511 && ( m_xCursor->isAfterLast()
2512 || m_xCursor->isBeforeFirst()
2514 && !bIsNewRecord;
2516 catch( const SQLException& )
2518 OSL_ENSURE( sal_False, "OBoundControlModel::reset: caught an SQL exception!" );
2520 // don't count the insert row as "invalid"
2521 // @since #i24495#
2522 // @date 2004-05-14
2523 // @author fs@openoffice.org
2525 sal_Bool bSimpleReset =
2526 ( !m_xColumn.is() // no connection to a database column
2527 || ( m_xCursor.is() // OR we have an improperly positioned cursor
2528 && bInvalidCursorPosition
2530 || hasExternalValueBinding() // OR we have an external value binding
2533 if ( !bSimpleReset )
2535 // The default values will be set if and only if the current value of the field which we're bound
2536 // to is NULL.
2537 // Else, the current field value should be refreshed
2538 // This behaviour is not completely ... "matured": What should happen if the field as well as the
2539 // control have a default value?
2541 sal_Bool bIsNull = sal_True;
2542 // we have to access the field content at least once to get a reliable result by XColumn::wasNull
2545 // normally, we'd do a getString here. However, this is extremely expensive in the case
2546 // of binary fields. Unfortunately, getString is the only method which is guaranteed
2547 // to *always* succeed, all other getXXX methods may fail if the column is asked for a
2548 // non-convertible type
2549 sal_Int32 nFieldType = DataType::OBJECT;
2550 getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
2551 if ( ( nFieldType == DataType::BINARY )
2552 || ( nFieldType == DataType::VARBINARY )
2553 || ( nFieldType == DataType::LONGVARBINARY )
2554 || ( nFieldType == DataType::OBJECT )
2555 || ( nFieldType == DataType::BLOB )
2556 || ( nFieldType == DataType::CLOB )
2558 m_xColumn->getBinaryStream();
2559 else
2560 m_xColumn->getString();
2562 bIsNull = m_xColumn->wasNull();
2564 catch(Exception&)
2566 DBG_ERROR("OBoundControlModel::reset: this should have succeeded in all cases!");
2569 sal_Bool bNeedValueTransfer = sal_True;
2571 if ( bIsNull )
2573 if ( bIsNewRecord )
2575 // reset the control to it's default
2576 resetNoBroadcast();
2577 // and immediately commit the changes to the DB column, to keep consistency
2578 commitControlValueToDbColumn( sal_True );
2580 bNeedValueTransfer = sal_False;
2584 if ( bNeedValueTransfer )
2585 transferDbValueToControl();
2587 else
2589 resetNoBroadcast();
2591 // transfer to the external binding, if necessary
2592 if ( hasExternalValueBinding() )
2593 transferControlValueToExternal( aLock );
2596 // revalidate, if necessary
2597 if ( hasValidator() )
2598 recheckValidity( true );
2600 aLock.release();
2602 m_aResetHelper.notifyResetted();
2605 // -----------------------------------------------------------------------------
2606 void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField )
2608 DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" );
2609 m_xField = _rxField;
2612 //--------------------------------------------------------------------
2613 sal_Bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding )
2615 if ( !_rxBinding.is() )
2616 return sal_False;
2618 Sequence< Type > aTypeCandidates;
2620 // SYNCHRONIZED -->
2621 ::osl::MutexGuard aGuard( m_aMutex );
2622 aTypeCandidates = getSupportedBindingTypes();
2623 // <-- SYNCHRONIZED
2626 for ( const Type* pType = aTypeCandidates.getConstArray();
2627 pType != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
2628 ++pType
2631 if ( _rxBinding->supportsType( *pType ) )
2632 return sal_True;
2635 return sal_False;
2638 //--------------------------------------------------------------------
2639 void OBoundControlModel::connectExternalValueBinding(
2640 const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock )
2642 OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" );
2643 OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" );
2645 // if we're connected to a database column, suspend this
2646 if ( hasField() )
2647 impl_disconnectDatabaseColumn_noNotify();
2649 // suspend listening for load-related events at out ambient form.
2650 // This is because an external value binding overrules a possible database binding.
2651 if ( isFormListening() )
2652 doFormListening( false );
2654 // remember this new binding
2655 m_xExternalBinding = _rxBinding;
2657 // tell the derivee
2658 onConnectedExternalValue();
2662 // add as value listener so we get notified when the value changes
2663 Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
2664 if ( xModifiable.is() )
2665 xModifiable->addModifyListener( this );
2667 // add as property change listener for some (possibly present) properties we're
2668 // interested in
2669 Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
2670 Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() );
2671 if ( xBindingPropsInfo.is() )
2673 if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) )
2675 xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this );
2676 m_bBindingControlsRO = sal_True;
2678 if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) )
2680 xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this );
2681 m_bBindingControlsEnable = sal_True;
2685 catch( const Exception& )
2687 DBG_UNHANDLED_EXCEPTION();
2690 // propagate our new value
2691 transferExternalValueToControl( _rInstanceLock );
2693 // if the binding is also a validator, use it, too. This is a constraint of the
2694 // com.sun.star.form.binding.ValidatableBindableFormComponent service
2695 if ( m_bSupportsValidation )
2699 Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY );
2700 if ( xAsValidator.is() )
2701 setValidator( xAsValidator );
2703 catch( const Exception& )
2705 DBG_UNHANDLED_EXCEPTION();
2710 //--------------------------------------------------------------------
2711 void OBoundControlModel::disconnectExternalValueBinding( )
2715 // not listening at the binding anymore
2716 Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
2717 if ( xModifiable.is() )
2718 xModifiable->removeModifyListener( this );
2720 // remove as property change listener
2721 Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
2722 if ( m_bBindingControlsRO )
2723 xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this );
2724 if ( m_bBindingControlsEnable )
2725 xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this );
2727 catch( const Exception& )
2729 OSL_ENSURE( sal_False, "OBoundControlModel::disconnectExternalValueBinding: caught an exception!" );
2732 // if the binding also acts as our validator, disconnect the validator, too
2733 if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() )
2734 disconnectValidator( );
2736 // no binding anymore
2737 m_xExternalBinding.clear();
2739 // be a load listener at our form, again. This was suspended while we had
2740 // an external value binding in place.
2741 doFormListening( true );
2743 // re-connect to database column of the new parent
2744 if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
2745 impl_connectDatabaseColumn_noNotify( false );
2747 // tell the derivee
2748 onDisconnectedExternalValue();
2751 //--------------------------------------------------------------------
2752 void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding ) throw (IncompatibleTypesException, RuntimeException)
2754 OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" );
2755 // the interface for this method should not have been exposed if we do not
2756 // support binding to external data
2757 // allow reset
2758 if ( _rxBinding.is() && !impl_approveValueBinding_nolock( _rxBinding ) )
2760 throw IncompatibleTypesException(
2761 FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ),
2762 *this
2766 ControlModelLock aLock( *this );
2768 // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding
2769 // might trigger a change in our BoundField.
2770 FieldChangeNotifier aBoundFieldNotifier( aLock );
2772 // disconnect from the old binding
2773 if ( hasExternalValueBinding() )
2774 disconnectExternalValueBinding( );
2776 // connect to the new binding
2777 if ( _rxBinding.is() )
2778 connectExternalValueBinding( _rxBinding, aLock );
2781 //--------------------------------------------------------------------
2782 Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding( ) throw (RuntimeException)
2784 ::osl::MutexGuard aGuard( m_aMutex );
2785 OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" );
2786 // the interface for this method should not have been exposed if we do not
2787 // support binding to external data
2789 return m_xExternalBinding;
2792 //--------------------------------------------------------------------
2793 void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent ) throw ( RuntimeException )
2795 ControlModelLock aLock( *this );
2797 OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" );
2798 if ( !m_bTransferingValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() )
2800 transferExternalValueToControl( aLock );
2804 //--------------------------------------------------------------------
2805 void OBoundControlModel::transferDbValueToControl( )
2807 setControlValue( translateDbColumnToControlValue(), eDbColumnBinding );
2810 //------------------------------------------------------------------------------
2811 void OBoundControlModel::transferExternalValueToControl( ControlModelLock& _rInstanceLock )
2813 Reference< XValueBinding > xExternalBinding( m_xExternalBinding );
2814 Type aValueExchangeType( getExternalValueType() );
2816 _rInstanceLock.release();
2817 // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2818 Any aExternalValue;
2821 aExternalValue = xExternalBinding->getValue( aValueExchangeType );
2823 catch( const Exception& )
2825 DBG_UNHANDLED_EXCEPTION();
2827 // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2828 _rInstanceLock.acquire();
2830 setControlValue( translateExternalValueToControlValue( aExternalValue ), eExternalBinding );
2833 //------------------------------------------------------------------------------
2834 void OBoundControlModel::transferControlValueToExternal( ControlModelLock& _rInstanceLock )
2836 OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
2837 "OBoundControlModel::transferControlValueToExternal: precondition not met!" );
2839 if ( m_xExternalBinding.is() )
2841 Any aExternalValue( translateControlValueToExternalValue() );
2842 m_bTransferingValue = sal_True;
2844 _rInstanceLock.release();
2845 // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2848 m_xExternalBinding->setValue( aExternalValue );
2850 catch( const Exception& )
2852 DBG_UNHANDLED_EXCEPTION();
2854 // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2855 _rInstanceLock.acquire();
2857 m_bTransferingValue = sal_False;
2861 // -----------------------------------------------------------------------------
2862 Sequence< Type > OBoundControlModel::getSupportedBindingTypes()
2864 return Sequence< Type >( &m_aValuePropertyType, 1 );
2867 //-----------------------------------------------------------------------------
2868 void OBoundControlModel::calculateExternalValueType()
2870 m_aExternalValueType = Type();
2871 if ( !m_xExternalBinding.is() )
2872 return;
2874 Sequence< Type > aTypeCandidates( getSupportedBindingTypes() );
2875 for ( const Type* pTypeCandidate = aTypeCandidates.getConstArray();
2876 pTypeCandidate != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
2877 ++pTypeCandidate
2880 if ( m_xExternalBinding->supportsType( *pTypeCandidate ) )
2882 m_aExternalValueType = *pTypeCandidate;
2883 break;
2888 //-----------------------------------------------------------------------------
2889 Any OBoundControlModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
2891 OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
2892 "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" );
2894 Any aControlValue( _rExternalValue );
2896 // if the external value is VOID, and our value property is not allowed to be VOID,
2897 // then default-construct a value
2898 if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid )
2899 aControlValue.setValue( NULL, m_aValuePropertyType );
2901 // outta here
2902 return aControlValue;
2905 //------------------------------------------------------------------------------
2906 Any OBoundControlModel::translateControlValueToExternalValue( ) const
2908 return getControlValue( );
2911 //------------------------------------------------------------------------------
2912 Any OBoundControlModel::translateControlValueToValidatableValue( ) const
2914 OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" );
2915 if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() )
2916 return translateControlValueToExternalValue();
2917 return getControlValue();
2920 //------------------------------------------------------------------------------
2921 Any OBoundControlModel::getControlValue( ) const
2923 OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
2924 "OBoundControlModel::getControlValue: invalid aggregate !" );
2925 OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ),
2926 "OBoundControlModel::getControlValue: please override if you have own value property handling!" );
2928 // determine the current control value
2929 Any aControlValue;
2930 if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
2932 aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle );
2934 else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() )
2936 aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName );
2939 return aControlValue;
2942 //--------------------------------------------------------------------
2943 void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator )
2945 OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" );
2946 OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" );
2948 m_xValidator = _rxValidator;
2950 // add as value listener so we get notified when the value changes
2951 if ( m_xValidator.is() )
2955 m_xValidator->addValidityConstraintListener( this );
2957 catch( const RuntimeException& )
2962 onConnectedValidator( );
2965 //--------------------------------------------------------------------
2966 void OBoundControlModel::disconnectValidator( )
2968 OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" );
2970 // add as value listener so we get notified when the value changes
2971 if ( m_xValidator.is() )
2975 m_xValidator->removeValidityConstraintListener( this );
2977 catch( const RuntimeException& )
2982 m_xValidator.clear();
2984 onDisconnectedValidator( );
2987 //--------------------------------------------------------------------
2988 void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator ) throw (VetoException,RuntimeException)
2990 ::osl::ClearableMutexGuard aGuard( m_aMutex );
2991 OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" );
2992 // the interface for this method should not have been exposed if we do not
2993 // support validation
2995 // early out if the validator does not change
2996 if( _rxValidator == m_xValidator )
2997 return;
2999 if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) )
3000 throw VetoException(
3001 FRM_RES_STRING( RID_STR_INVALID_VALIDATOR ),
3002 *this
3005 // disconnect from the old validator
3006 if ( hasValidator() )
3007 disconnectValidator( );
3009 // connect to the new validator
3010 if ( _rxValidator.is() )
3011 connectValidator( _rxValidator );
3014 //--------------------------------------------------------------------
3015 Reference< XValidator > SAL_CALL OBoundControlModel::getValidator( ) throw (RuntimeException)
3017 ::osl::MutexGuard aGuard( m_aMutex );
3018 OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" );
3019 // the interface for this method should not have been exposed if we do not
3020 // support validation
3022 return m_xValidator;
3025 //--------------------------------------------------------------------
3026 void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& /*Source*/ ) throw (RuntimeException)
3028 ::osl::ClearableMutexGuard aGuard( m_aMutex );
3029 OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" );
3030 // the interface for this method should not have been exposed if we do not
3031 // support validation
3033 recheckValidity( false );
3036 //--------------------------------------------------------------------
3037 sal_Bool SAL_CALL OBoundControlModel::isValid( ) throw (RuntimeException)
3039 return m_bIsCurrentValueValid;
3042 //--------------------------------------------------------------------
3043 ::com::sun::star::uno::Any OBoundControlModel::getCurrentFormComponentValue() const
3045 if ( hasValidator() )
3046 return translateControlValueToValidatableValue();
3047 return getControlValue();
3050 //--------------------------------------------------------------------
3051 Any SAL_CALL OBoundControlModel::getCurrentValue( ) throw (RuntimeException)
3053 ::osl::MutexGuard aGuard( m_aMutex );
3054 return getCurrentFormComponentValue();
3057 //--------------------------------------------------------------------
3058 void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException)
3060 if ( Listener.is() )
3061 m_aFormComponentListeners.addInterface( Listener );
3064 //--------------------------------------------------------------------
3065 void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException)
3067 if ( Listener.is() )
3068 m_aFormComponentListeners.removeInterface( Listener );
3071 //--------------------------------------------------------------------
3072 void OBoundControlModel::recheckValidity( bool _bForceNotification )
3076 sal_Bool bIsCurrentlyValid = sal_True;
3077 if ( hasValidator() )
3078 bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() );
3080 if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification )
3082 m_bIsCurrentValueValid = bIsCurrentlyValid;
3084 // release our mutex for the notifications
3085 MutexRelease aRelease( m_aMutex );
3086 m_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) );
3089 catch( const Exception& )
3091 OSL_ENSURE( sal_False, "OBoundControlModel::recheckValidity: caught an exception!" );
3095 //------------------------------------------------------------------------------
3096 void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
3098 BEGIN_DESCRIBE_PROPERTIES( 5, OControlModel )
3099 DECL_PROP1 ( CONTROLSOURCE, ::rtl::OUString, BOUND );
3100 DECL_IFACE_PROP3( BOUNDFIELD, XPropertySet, BOUND, READONLY, TRANSIENT );
3101 DECL_IFACE_PROP2( CONTROLLABEL, XPropertySet, BOUND, MAYBEVOID );
3102 DECL_PROP2 ( CONTROLSOURCEPROPERTY, ::rtl::OUString, READONLY, TRANSIENT );
3103 DECL_BOOL_PROP1 ( INPUT_REQUIRED, BOUND );
3104 END_DESCRIBE_PROPERTIES()
3107 // -----------------------------------------------------------------------------
3109 //.........................................................................
3111 //... namespace frm .......................................................