xref: /trunk/main/forms/source/component/FormComponent.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_forms.hxx"
26 
27 #include "componenttools.hxx"
28 #include "FormComponent.hxx"
29 #include "frm_resource.hrc"
30 #include "frm_resource.hxx"
31 #include "property.hrc"
32 #include "services.hxx"
33 
34 /** === begin UNO includes === **/
35 #include <com/sun/star/awt/XTextComponent.hpp>
36 #include <com/sun/star/awt/XVclWindowPeer.hpp>
37 #include <com/sun/star/awt/XWindow.hpp>
38 #include <com/sun/star/form/XForm.hpp>
39 #include <com/sun/star/form/XLoadable.hpp>
40 #include <com/sun/star/io/XMarkableStream.hpp>
41 #include <com/sun/star/lang/DisposedException.hpp>
42 #include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp>
43 #include <com/sun/star/sdb/XRowSetSupplier.hpp>
44 #include <com/sun/star/sdbc/ColumnValue.hpp>
45 #include <com/sun/star/sdbc/DataType.hpp>
46 #include <com/sun/star/util/XModifyBroadcaster.hpp>
47 /** === end UNO includes === **/
48 
49 #include <comphelper/basicio.hxx>
50 #include <comphelper/guarding.hxx>
51 #include <comphelper/listenernotification.hxx>
52 #include <comphelper/property.hxx>
53 #include <connectivity/dbtools.hxx>
54 #include <cppuhelper/queryinterface.hxx>
55 #include <rtl/logfile.hxx>
56 #include <toolkit/helper/emptyfontdescriptor.hxx>
57 #include <tools/debug.hxx>
58 #include <tools/diagnose_ex.h>
59 
60 #include <functional>
61 #include <algorithm>
62 
63 #include <functional>
64 #include <algorithm>
65 
66 
67 //... namespace frm .......................................................
68 namespace frm
69 {
70 //.........................................................................
71 
72     using namespace ::com::sun::star::uno;
73     using namespace ::com::sun::star::sdb;
74     using namespace ::com::sun::star::sdbc;
75     using namespace ::com::sun::star::sdbcx;
76     using namespace ::com::sun::star::beans;
77     using namespace ::com::sun::star::container;
78     using namespace ::com::sun::star::form;
79     using namespace ::com::sun::star::awt;
80     using namespace ::com::sun::star::io;
81     using namespace ::com::sun::star::lang;
82     using namespace ::com::sun::star::util;
83     using namespace ::com::sun::star::form::binding;
84     using namespace ::com::sun::star::form::validation;
85     using namespace ::dbtools;
86     using namespace ::comphelper;
87 
88     //=========================================================================
89     //= FieldChangeNotifier
90     //=========================================================================
91     //-------------------------------------------------------------------------
impl_notifyAll_nothrow()92     void ControlModelLock::impl_notifyAll_nothrow()
93     {
94         m_rModel.firePropertyChanges( m_aHandles, m_aOldValues, m_aNewValues, OControlModel::LockAccess() );
95     }
96 
97     //-------------------------------------------------------------------------
addPropertyNotification(const sal_Int32 _nHandle,const Any & _rOldValue,const Any & _rNewValue)98     void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue )
99     {
100         sal_Int32 nOldLength = m_aHandles.getLength();
101         if  (   ( nOldLength != m_aOldValues.getLength() )
102             ||  ( nOldLength != m_aNewValues.getLength() )
103             )
104             throw RuntimeException( ::rtl::OUString(), m_rModel );
105 
106         m_aHandles.realloc( nOldLength + 1 );
107         m_aHandles[ nOldLength ] = _nHandle;
108         m_aOldValues.realloc( nOldLength + 1 );
109         m_aOldValues[ nOldLength ] = _rOldValue;
110         m_aNewValues.realloc( nOldLength + 1 );
111         m_aNewValues[ nOldLength ] = _rNewValue;
112     }
113 
114     //=========================================================================
115     //= FieldChangeNotifier
116     //=========================================================================
117     //-------------------------------------------------------------------------
118     class FieldChangeNotifier
119     {
120     public:
FieldChangeNotifier(ControlModelLock & _rLock)121         FieldChangeNotifier( ControlModelLock& _rLock )
122             :m_rLock( _rLock )
123             ,m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) )
124         {
125             m_xOldField = m_rModel.getField();
126         }
127 
~FieldChangeNotifier()128         ~FieldChangeNotifier()
129         {
130             Reference< XPropertySet > xNewField( m_rModel.getField() );
131             if ( m_xOldField != xNewField )
132                 m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, makeAny( m_xOldField ), makeAny( xNewField ) );
133         }
134 
135     private:
136         ControlModelLock&           m_rLock;
137         OBoundControlModel&         m_rModel;
138         Reference< XPropertySet >   m_xOldField;
139     };
140 
141 //=============================================================================
142 //= base class for form layer controls
143 //=============================================================================
DBG_NAME(frm_OControl)144 DBG_NAME(frm_OControl)
145 //------------------------------------------------------------------------------
146 OControl::OControl( const Reference< XMultiServiceFactory >& _rxFactory, const rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator )
147             :OComponentHelper(m_aMutex)
148             ,m_aContext( _rxFactory )
149 {
150     DBG_CTOR(frm_OControl, NULL);
151     // VCL-Control aggregieren
152     // bei Aggregation den Refcount um eins erhoehen da im setDelegator
153     // das Aggregat selbst den Refcount erhoeht
154     increment( m_refCount );
155     {
156         m_xAggregate = m_xAggregate.query( _rxFactory->createInstance( _rAggregateService ) );
157         m_xControl = m_xControl.query( m_xAggregate );
158     }
159     decrement( m_refCount );
160 
161     if ( _bSetDelegator )
162         doSetDelegator();
163 }
164 
165 //------------------------------------------------------------------------------
~OControl()166 OControl::~OControl()
167 {
168     DBG_DTOR(frm_OControl, NULL);
169     doResetDelegator();
170 }
171 
172 //------------------------------------------------------------------------------
doResetDelegator()173 void OControl::doResetDelegator()
174 {
175     if ( m_xAggregate.is() )
176         m_xAggregate->setDelegator( NULL );
177 }
178 
179 //------------------------------------------------------------------------------
doSetDelegator()180 void OControl::doSetDelegator()
181 {
182     increment( m_refCount );
183     if ( m_xAggregate.is() )
184     {   // those brackets are important for some compilers, don't remove!
185         // (they ensure that the temporary object created in the line below
186         // is destroyed *before* the refcount-decrement)
187         m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
188     }
189     decrement( m_refCount );
190 }
191 
192 // UNO Anbindung
193 //------------------------------------------------------------------------------
queryAggregation(const Type & _rType)194 Any SAL_CALL OControl::queryAggregation( const Type& _rType )
195 {
196     // ask the base class
197     Any aReturn( OComponentHelper::queryAggregation(_rType) );
198     // ask our own interfaces
199     if (!aReturn.hasValue())
200     {
201         aReturn = OControl_BASE::queryInterface(_rType);
202         // ask our aggregate
203         if (!aReturn.hasValue() && m_xAggregate.is())
204             aReturn = m_xAggregate->queryAggregation(_rType);
205     }
206 
207     return aReturn;
208 }
209 
210 //------------------------------------------------------------------------------
getImplementationId()211 Sequence<sal_Int8> SAL_CALL OControl::getImplementationId()
212 {
213     return OImplementationIds::getImplementationId(getTypes());
214 }
215 
216 //------------------------------------------------------------------------------
getTypes()217 Sequence<Type> SAL_CALL OControl::getTypes()
218 {
219     TypeBag aTypes( _getTypes() );
220 
221     Reference< XTypeProvider > xProv;
222     if ( query_aggregation( m_xAggregate, xProv ) )
223         aTypes.addTypes( xProv->getTypes() );
224 
225     return aTypes.getTypes();
226 }
227 
228 //------------------------------------------------------------------------------
_getTypes()229 Sequence<Type> OControl::_getTypes()
230 {
231     return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes();
232 }
233 
234 //------------------------------------------------------------------------------
initFormControlPeer(const Reference<XWindowPeer> &)235 void OControl::initFormControlPeer( const Reference< XWindowPeer >& /*_rxPeer*/ )
236 {
237     // nothing to do here
238 }
239 
240 // OComponentHelper
241 //------------------------------------------------------------------------------
disposing()242 void OControl::disposing()
243 {
244     OComponentHelper::disposing();
245 
246     m_aWindowStateGuard.attach( NULL, NULL );
247 
248     Reference< XComponent > xComp;
249     if (query_aggregation(m_xAggregate, xComp))
250         xComp->dispose();
251 }
252 
253 // XServiceInfo
254 //------------------------------------------------------------------------------
supportsService(const rtl::OUString & _rsServiceName)255 sal_Bool SAL_CALL OControl::supportsService(const rtl::OUString& _rsServiceName)
256 {
257     Sequence<rtl::OUString> aSupported = getSupportedServiceNames();
258     const rtl::OUString* pSupported = aSupported.getConstArray();
259     for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported)
260         if (pSupported->equals(_rsServiceName))
261             return sal_True;
262     return sal_False;
263 }
264 
265 //------------------------------------------------------------------------------
getAggregateServiceNames()266 Sequence< ::rtl::OUString > OControl::getAggregateServiceNames()
267 {
268     Sequence< ::rtl::OUString > aAggServices;
269     Reference< XServiceInfo > xInfo;
270     if ( query_aggregation( m_xAggregate, xInfo ) )
271         aAggServices = xInfo->getSupportedServiceNames();
272     return aAggServices;
273 }
274 
275 //------------------------------------------------------------------------------
getSupportedServiceNames()276 Sequence<rtl::OUString> SAL_CALL OControl::getSupportedServiceNames()
277 {
278     return ::comphelper::concatSequences(
279         getAggregateServiceNames(),
280         getSupportedServiceNames_Static()
281    );
282 }
283 
284 //------------------------------------------------------------------------------
getSupportedServiceNames_Static()285 Sequence< ::rtl::OUString > SAL_CALL OControl::getSupportedServiceNames_Static()
286 {
287     // no own supported service names
288     return Sequence< ::rtl::OUString >();
289 }
290 
291 // XEventListener
292 //------------------------------------------------------------------------------
disposing(const com::sun::star::lang::EventObject & _rEvent)293 void SAL_CALL OControl::disposing(const com::sun::star::lang::EventObject& _rEvent)
294 {
295     Reference< XInterface > xAggAsIface;
296     query_aggregation(m_xAggregate, xAggAsIface);
297 
298     // does the disposing come from the aggregate ?
299     if (xAggAsIface != Reference< XInterface >(_rEvent.Source, UNO_QUERY))
300     {   // no -> forward it
301                 Reference<com::sun::star::lang::XEventListener> xListener;
302         if (query_aggregation(m_xAggregate, xListener))
303             xListener->disposing(_rEvent);
304     }
305 }
306 
307 // XControl
308 //------------------------------------------------------------------------------
setContext(const Reference<XInterface> & Context)309 void SAL_CALL OControl::setContext(const Reference< XInterface >& Context)
310 {
311     if (m_xControl.is())
312         m_xControl->setContext(Context);
313 }
314 
315 //------------------------------------------------------------------------------
getContext()316 Reference< XInterface > SAL_CALL OControl::getContext()
317 {
318     return m_xControl.is() ? m_xControl->getContext() : Reference< XInterface >();
319 }
320 
321 //------------------------------------------------------------------------------
impl_resetStateGuard_nothrow()322 void OControl::impl_resetStateGuard_nothrow()
323 {
324     Reference< XWindow2 > xWindow;
325     Reference< XControlModel > xModel;
326     try
327     {
328         xWindow.set( getPeer(), UNO_QUERY );
329         xModel.set( getModel(), UNO_QUERY );
330     }
331     catch( const Exception& )
332     {
333         DBG_UNHANDLED_EXCEPTION();
334     }
335     m_aWindowStateGuard.attach( xWindow, xModel );
336 }
337 
338 //------------------------------------------------------------------------------
createPeer(const Reference<XToolkit> & _rxToolkit,const Reference<XWindowPeer> & _rxParent)339 void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent)
340 {
341     if ( m_xControl.is() )
342     {
343         m_xControl->createPeer( _rxToolkit, _rxParent );
344 
345         initFormControlPeer( getPeer() );
346 
347         impl_resetStateGuard_nothrow();
348     }
349 }
350 
351 //------------------------------------------------------------------------------
getPeer()352 Reference<XWindowPeer> SAL_CALL OControl::getPeer()
353 {
354     return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>();
355 }
356 
357 //------------------------------------------------------------------------------
setModel(const Reference<XControlModel> & Model)358 sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model)
359 {
360     if ( !m_xControl.is() )
361         return sal_False;
362 
363     sal_Bool bSuccess = m_xControl->setModel( Model );
364     impl_resetStateGuard_nothrow();
365     return bSuccess;
366 }
367 
368 //------------------------------------------------------------------------------
getModel()369 Reference<XControlModel> SAL_CALL OControl::getModel()
370 {
371     return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>();
372 }
373 
374 //------------------------------------------------------------------------------
getView()375 Reference<XView> SAL_CALL OControl::getView()
376 {
377     return m_xControl.is() ? m_xControl->getView() : Reference<XView>();
378 }
379 
380 //------------------------------------------------------------------------------
setDesignMode(sal_Bool bOn)381 void SAL_CALL OControl::setDesignMode(sal_Bool bOn)
382 {
383     if (m_xControl.is())
384         m_xControl->setDesignMode(bOn);
385 }
386 
387 //------------------------------------------------------------------------------
isDesignMode()388 sal_Bool SAL_CALL OControl::isDesignMode()
389 {
390     return m_xControl.is() ? m_xControl->isDesignMode() : sal_True;
391 }
392 
393 //------------------------------------------------------------------------------
isTransparent()394 sal_Bool SAL_CALL OControl::isTransparent()
395 {
396     return m_xControl.is() ? m_xControl->isTransparent() : sal_True;
397 }
398 
399 //==================================================================
400 //= OBoundControl
401 //==================================================================
402 DBG_NAME(frm_OBoundControl);
403 //------------------------------------------------------------------
OBoundControl(const Reference<XMultiServiceFactory> & _rxFactory,const::rtl::OUString & _rAggregateService,const sal_Bool _bSetDelegator)404 OBoundControl::OBoundControl( const Reference< XMultiServiceFactory >& _rxFactory,
405             const ::rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator )
406     :OControl( _rxFactory, _rAggregateService, _bSetDelegator )
407     ,m_bLocked(sal_False)
408     ,m_aOriginalFont( EmptyFontDescriptor() )
409     ,m_nOriginalTextLineColor( 0 )
410 {
411     DBG_CTOR(frm_OBoundControl, NULL);
412 }
413 
414 //------------------------------------------------------------------
~OBoundControl()415 OBoundControl::~OBoundControl()
416 {
417     DBG_DTOR(frm_OBoundControl, NULL);
418 }
419 // -----------------------------------------------------------------------------
_getTypes()420 Sequence< Type> OBoundControl::_getTypes()
421 {
422     return TypeBag( OControl::_getTypes(), OBoundControl_BASE::getTypes() ).getTypes();
423 }
424 //------------------------------------------------------------------
queryAggregation(const Type & _rType)425 Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType)
426 {
427     Any aReturn;
428 
429     // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types
430     if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) )
431         aReturn = OControl::queryAggregation( _rType );
432 
433     // ask our own interfaces
434     // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener)
435     if ( !aReturn.hasValue() )
436         aReturn = OBoundControl_BASE::queryInterface( _rType );
437 
438     // ask the base class
439     if ( !aReturn.hasValue() )
440         aReturn = OControl::queryAggregation( _rType );
441 
442     return aReturn;
443 }
444 
445 //------------------------------------------------------------------
getLock()446 sal_Bool SAL_CALL OBoundControl::getLock()
447 {
448     return m_bLocked;
449 }
450 
451 //------------------------------------------------------------------
setLock(sal_Bool _bLock)452 void SAL_CALL OBoundControl::setLock(sal_Bool _bLock)
453 {
454     if (m_bLocked == _bLock)
455         return;
456 
457     osl::MutexGuard aGuard(m_aMutex);
458     _setLock(_bLock);
459     m_bLocked = _bLock;
460 }
461 
462 //------------------------------------------------------------------
_setLock(sal_Bool _bLock)463 void OBoundControl::_setLock(sal_Bool _bLock)
464 {
465     // try to set the text component to readonly
466     Reference< XWindowPeer > xPeer = getPeer();
467     Reference< XTextComponent > xText( xPeer, UNO_QUERY );
468 
469     if ( xText.is() )
470         xText->setEditable( !_bLock );
471     else
472     {
473         // disable the window
474         Reference< XWindow > xComp( xPeer, UNO_QUERY );
475         if ( xComp.is() )
476             xComp->setEnable( !_bLock );
477     }
478 }
479 
480 //--------------------------------------------------------------------
setModel(const Reference<XControlModel> & _rxModel)481 sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel )
482 {
483     return OControl::setModel( _rxModel );
484 }
485 
486 //--------------------------------------------------------------------
disposing(const EventObject & Source)487 void SAL_CALL OBoundControl::disposing(const EventObject& Source)
488 {
489     // just disambiguate
490     OControl::disposing(Source);
491 }
492 
493 //--------------------------------------------------------------------
disposing()494 void OBoundControl::disposing()
495 {
496     OControl::disposing();
497 }
498 
499 //==================================================================
500 //= OControlModel
501 //==================================================================
DBG_NAME(OControlModel)502 DBG_NAME(OControlModel)
503 //------------------------------------------------------------------
504 Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId()
505 {
506     return OImplementationIds::getImplementationId(getTypes());
507 }
508 
509 //------------------------------------------------------------------
getTypes()510 Sequence<Type> SAL_CALL OControlModel::getTypes()
511 {
512     TypeBag aTypes( _getTypes() );
513 
514     Reference< XTypeProvider > xProv;
515     if ( query_aggregation( m_xAggregate, xProv ) )
516         aTypes.addTypes( xProv->getTypes() );
517 
518     return aTypes.getTypes();
519 }
520 
521 //------------------------------------------------------------------------------
_getTypes()522 Sequence<Type> OControlModel::_getTypes()
523 {
524     return TypeBag( OComponentHelper::getTypes(),
525         OPropertySetAggregationHelper::getTypes(),
526         OControlModel_BASE::getTypes()
527     ).getTypes();
528 }
529 
530 //------------------------------------------------------------------
queryAggregation(const Type & _rType)531 Any SAL_CALL OControlModel::queryAggregation(const Type& _rType)
532 {
533     // base class 1
534     Any aReturn(OComponentHelper::queryAggregation(_rType));
535 
536     // base class 2
537     if (!aReturn.hasValue())
538     {
539         aReturn = OControlModel_BASE::queryInterface(_rType);
540 
541         // our own interfaces
542         if (!aReturn.hasValue())
543         {
544             aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
545             // our aggregate
546             if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(::getCppuType(static_cast< Reference< XCloneable>* >(NULL))))
547                 aReturn = m_xAggregate->queryAggregation(_rType);
548         }
549     }
550     return aReturn;
551 }
552 
553 //------------------------------------------------------------------------------
readHelpTextCompatibly(const staruno::Reference<stario::XObjectInputStream> & _rxInStream)554 void OControlModel::readHelpTextCompatibly(const staruno::Reference< stario::XObjectInputStream >& _rxInStream)
555 {
556     ::rtl::OUString sHelpText;
557     ::comphelper::operator>>( _rxInStream, sHelpText);
558     try
559     {
560         if (m_xAggregateSet.is())
561             m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, makeAny(sHelpText));
562     }
563     catch(const Exception&)
564     {
565         OSL_ENSURE(sal_False, "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!");
566     }
567 }
568 
569 //------------------------------------------------------------------------------
writeHelpTextCompatibly(const staruno::Reference<stario::XObjectOutputStream> & _rxOutStream)570 void OControlModel::writeHelpTextCompatibly(const staruno::Reference< stario::XObjectOutputStream >& _rxOutStream)
571 {
572     ::rtl::OUString sHelpText;
573     try
574     {
575         if (m_xAggregateSet.is())
576             m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
577     }
578     catch(const Exception&)
579     {
580         OSL_ENSURE(sal_False, "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!");
581     }
582     ::comphelper::operator<<( _rxOutStream, sHelpText);
583 }
584 
585 //------------------------------------------------------------------
OControlModel(const Reference<com::sun::star::lang::XMultiServiceFactory> & _rxFactory,const::rtl::OUString & _rUnoControlModelTypeName,const::rtl::OUString & rDefault,const sal_Bool _bSetDelegator)586 OControlModel::OControlModel(
587                         const Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory,
588             const ::rtl::OUString& _rUnoControlModelTypeName,
589             const ::rtl::OUString& rDefault, const sal_Bool _bSetDelegator)
590     :OComponentHelper(m_aMutex)
591     ,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
592     ,m_aContext( _rxFactory )
593     ,m_lockCount( 0 )
594     ,m_aPropertyBagHelper( *this )
595     ,m_nTabIndex(FRM_DEFAULT_TABINDEX)
596     ,m_nClassId(FormComponentType::CONTROL)
597     ,m_bNativeLook( sal_False )
598     ,m_nControlTypeinMSO(0) // 0 : default value is create from AOO
599     ,m_nObjIDinMSO(INVALID_OBJ_ID_IN_MSO)
600         // form controls are usually embedded into documents, not dialogs, and in documents
601         // the native look is ugly ....
602         // #i37342# / 2004-11-19 / frank.schoenheit@sun.com
603 {
604     DBG_CTOR(OControlModel, NULL);
605     if (_rUnoControlModelTypeName.getLength())  // the is a model we have to aggregate
606     {
607         increment(m_refCount);
608 
609         {
610             m_xAggregate = Reference<XAggregation>(_rxFactory->createInstance(_rUnoControlModelTypeName), UNO_QUERY);
611             setAggregation(m_xAggregate);
612 
613             if ( m_xAggregateSet.is() )
614             {
615                 try
616                 {
617                     if ( rDefault.getLength() )
618                         m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( rDefault ) );
619                 }
620                 catch( const Exception& )
621                 {
622                     OSL_ENSURE( sal_False, "OControlModel::OControlModel: caught an exception!" );
623                 }
624             }
625         }
626 
627         if (_bSetDelegator)
628             doSetDelegator();
629 
630         // Refcount wieder bei NULL
631         decrement(m_refCount);
632     }
633 }
634 
635 //------------------------------------------------------------------
OControlModel(const OControlModel * _pOriginal,const Reference<XMultiServiceFactory> & _rxFactory,const sal_Bool _bCloneAggregate,const sal_Bool _bSetDelegator)636 OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory, const sal_Bool _bCloneAggregate, const sal_Bool _bSetDelegator )
637     :OComponentHelper( m_aMutex )
638     ,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
639     ,m_aContext( _rxFactory )
640     ,m_lockCount( 0 )
641     ,m_aPropertyBagHelper( *this )
642     ,m_nTabIndex( FRM_DEFAULT_TABINDEX )
643     ,m_nClassId( FormComponentType::CONTROL )
644 {
645     DBG_CTOR( OControlModel, NULL );
646     DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" );
647 
648     // copy members
649     m_aName = _pOriginal->m_aName;
650     m_aTag = _pOriginal->m_aTag;
651     m_nTabIndex = _pOriginal->m_nTabIndex;
652     m_nClassId = _pOriginal->m_nClassId;
653     m_bNativeLook = _pOriginal->m_bNativeLook;
654     m_nControlTypeinMSO = _pOriginal->m_nControlTypeinMSO;
655     m_nObjIDinMSO = _pOriginal->m_nObjIDinMSO;
656 
657     if ( _bCloneAggregate )
658     {
659         // temporarily increment refcount because of temporary references to ourself in the following
660         increment( m_refCount );
661 
662         {
663             // transfer the (only, at the very moment!) ref count
664             m_xAggregate = createAggregateClone( _pOriginal );
665 
666             // set aggregation (retrieve other direct interfaces of the aggregate)
667             setAggregation( m_xAggregate );
668         }
669 
670         // set the delegator, if allowed by our derived class
671         if ( _bSetDelegator )
672             doSetDelegator();
673 
674         // decrement ref count
675         decrement( m_refCount );
676     }
677 }
678 
679 //------------------------------------------------------------------
~OControlModel()680 OControlModel::~OControlModel()
681 {
682     // release the aggregate
683     doResetDelegator( );
684 
685     DBG_DTOR(OControlModel, NULL);
686 }
687 
688 //------------------------------------------------------------------
clonedFrom(const OControlModel *)689 void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ )
690 {
691     // nothing to do in this base class
692 }
693 
694 //------------------------------------------------------------------------------
doResetDelegator()695 void OControlModel::doResetDelegator()
696 {
697     if (m_xAggregate.is())
698         m_xAggregate->setDelegator(NULL);
699 }
700 
701 //------------------------------------------------------------------------------
doSetDelegator()702 void OControlModel::doSetDelegator()
703 {
704     increment(m_refCount);
705     if (m_xAggregate.is())
706     {
707         m_xAggregate->setDelegator(static_cast<XWeak*>(this));
708     }
709     decrement(m_refCount);
710 }
711 
712 // XChild
713 //------------------------------------------------------------------------------
getParent()714 Reference< XInterface > SAL_CALL OControlModel::getParent()
715 {
716     return m_xParent;
717 }
718 
719 //------------------------------------------------------------------------------
setParent(const Reference<XInterface> & _rxParent)720 void SAL_CALL OControlModel::setParent(const Reference< XInterface >& _rxParent)
721 {
722     osl::MutexGuard aGuard(m_aMutex);
723 
724     Reference<XComponent> xComp(m_xParent, UNO_QUERY);
725     if (xComp.is())
726         xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this));
727 
728     m_xParent = _rxParent;
729     xComp = xComp.query( m_xParent );
730 
731     if ( xComp.is() )
732         xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this));
733 }
734 
735 // XNamed
736 //------------------------------------------------------------------------------
getName()737 ::rtl::OUString SAL_CALL OControlModel::getName()
738 {
739     ::rtl::OUString aReturn;
740     OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= aReturn;
741     return aReturn;
742 }
743 
744 //------------------------------------------------------------------------------
setName(const::rtl::OUString & _rName)745 void SAL_CALL OControlModel::setName(const ::rtl::OUString& _rName)
746 {
747         setFastPropertyValue(PROPERTY_ID_NAME, makeAny(_rName));
748 }
749 
750 // XServiceInfo
751 //------------------------------------------------------------------------------
supportsService(const rtl::OUString & _rServiceName)752 sal_Bool SAL_CALL OControlModel::supportsService(const rtl::OUString& _rServiceName)
753 {
754     Sequence<rtl::OUString> aSupported = getSupportedServiceNames();
755     const rtl::OUString* pSupported = aSupported.getConstArray();
756     for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported)
757         if (pSupported->equals(_rServiceName))
758             return sal_True;
759     return sal_False;
760 }
761 
762 //------------------------------------------------------------------------------
getAggregateServiceNames()763 Sequence< ::rtl::OUString > OControlModel::getAggregateServiceNames()
764 {
765     Sequence< ::rtl::OUString > aAggServices;
766     Reference< XServiceInfo > xInfo;
767     if ( query_aggregation( m_xAggregate, xInfo ) )
768         aAggServices = xInfo->getSupportedServiceNames();
769     return aAggServices;
770 }
771 
772 //------------------------------------------------------------------------------
getSupportedServiceNames()773 Sequence<rtl::OUString> SAL_CALL OControlModel::getSupportedServiceNames()
774 {
775     return ::comphelper::concatSequences(
776         getAggregateServiceNames(),
777         getSupportedServiceNames_Static()
778     );
779 }
780 
781 //------------------------------------------------------------------------------
getSupportedServiceNames_Static()782 Sequence< ::rtl::OUString > SAL_CALL OControlModel::getSupportedServiceNames_Static()
783 {
784     Sequence< ::rtl::OUString > aServiceNames( 2 );
785     aServiceNames[ 0 ] = FRM_SUN_FORMCOMPONENT;
786     aServiceNames[ 1 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.FormControlModel" );
787     return aServiceNames;
788 }
789 
790 // XEventListener
791 //------------------------------------------------------------------------------
disposing(const com::sun::star::lang::EventObject & _rSource)792 void SAL_CALL OControlModel::disposing(const com::sun::star::lang::EventObject& _rSource)
793 {
794     // release the parent
795     if (_rSource.Source == m_xParent)
796     {
797         osl::MutexGuard aGuard(m_aMutex);
798         m_xParent = NULL;
799     }
800     else
801     {
802         Reference<com::sun::star::lang::XEventListener> xEvtLst;
803         if (query_aggregation(m_xAggregate, xEvtLst))
804         {
805             osl::MutexGuard aGuard(m_aMutex);
806             xEvtLst->disposing(_rSource);
807         }
808     }
809 }
810 
811 // OComponentHelper
812 //-----------------------------------------------------------------------------
disposing()813 void OControlModel::disposing()
814 {
815     OPropertySetAggregationHelper::disposing();
816 
817     Reference<com::sun::star::lang::XComponent> xComp;
818     if (query_aggregation(m_xAggregate, xComp))
819         xComp->dispose();
820 
821     setParent(Reference<XFormComponent>());
822 
823     m_aPropertyBagHelper.dispose();
824 }
825 
826 //------------------------------------------------------------------------------
writeAggregate(const Reference<XObjectOutputStream> & _rxOutStream) const827 void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const
828 {
829     Reference< XPersistObject > xPersist;
830     if ( query_aggregation( m_xAggregate, xPersist ) )
831         xPersist->write( _rxOutStream );
832 }
833 
834 //------------------------------------------------------------------------------
readAggregate(const Reference<XObjectInputStream> & _rxInStream)835 void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream )
836 {
837     Reference< XPersistObject > xPersist;
838     if ( query_aggregation( m_xAggregate, xPersist ) )
839         xPersist->read( _rxInStream );
840 }
841 
842 //------------------------------------------------------------------------------
write(const Reference<stario::XObjectOutputStream> & _rxOutStream)843 void SAL_CALL OControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream)
844 {
845     osl::MutexGuard aGuard(m_aMutex);
846 
847     // 1. Schreiben des UnoControls
848     Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
849     if ( !xMark.is() )
850     {
851         throw IOException(
852             FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
853             static_cast< ::cppu::OWeakObject* >( this )
854         );
855     }
856 
857     sal_Int32 nMark = xMark->createMark();
858     sal_Int32 nLen = 0;
859 
860     _rxOutStream->writeLong(nLen);
861 
862     writeAggregate( _rxOutStream );
863 
864     // feststellen der Laenge
865     nLen = xMark->offsetToMark(nMark) - 4;
866     xMark->jumpToMark(nMark);
867     _rxOutStream->writeLong(nLen);
868     xMark->jumpToFurthest();
869     xMark->deleteMark(nMark);
870 
871     // 2. Schreiben einer VersionsNummer
872     _rxOutStream->writeShort(0x0003);
873 
874     // 3. Schreiben der allgemeinen Properties
875     ::comphelper::operator<<( _rxOutStream, m_aName);
876     _rxOutStream->writeShort(m_nTabIndex);
877     ::comphelper::operator<<( _rxOutStream, m_aTag); // 3. version
878 
879     // !!! IMPORTANT NOTE !!!
880     // don't write any new members here : this wouldn't be compatible with older versions, as OControlModel
881     // is a base class which is called in derived classes "read" method. So if you increment the version
882     // and write new stuff, older office versions will read this in the _derived_ classes, which may result
883     // in anything from data loss to crash.
884     // !!! EOIN !!!
885 }
886 
887 //------------------------------------------------------------------------------
read(const Reference<stario::XObjectInputStream> & InStream)888 void OControlModel::read(const Reference<stario::XObjectInputStream>& InStream)
889 {
890     osl::MutexGuard aGuard(m_aMutex);
891 
892     Reference<stario::XMarkableStream> xMark(InStream, UNO_QUERY);
893     if ( !xMark.is() )
894     {
895         throw IOException(
896             FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
897             static_cast< ::cppu::OWeakObject* >( this )
898         );
899     }
900 
901     // 1. Lesen des UnoControls
902     sal_Int32 nLen = InStream->readLong();
903     if (nLen)
904     {
905         sal_Int32 nMark = xMark->createMark();
906 
907         try
908         {
909             readAggregate( InStream );
910         }
911         catch( const Exception& )
912         {
913             DBG_UNHANDLED_EXCEPTION();
914         }
915 
916         xMark->jumpToMark(nMark);
917         InStream->skipBytes(nLen);
918         xMark->deleteMark(nMark);
919     }
920 
921     // 2. Lesen des Versionsnummer
922     sal_uInt16 nVersion = InStream->readShort();
923 
924     // 3. Lesen der allgemeinen Properties
925     ::comphelper::operator>>( InStream, m_aName);
926     m_nTabIndex  = InStream->readShort();
927 
928     if (nVersion > 0x0002)
929         ::comphelper::operator>>( InStream, m_aTag);
930 
931     // we had a version where we wrote the help text
932     if (nVersion == 0x0004)
933         readHelpTextCompatibly(InStream);
934 
935     DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !");
936     // 4 was the version where we wrote the help text
937     // later versions shouldn't exist (see write for a detailed comment)
938 }
939 
940 //------------------------------------------------------------------------------
getPropertyStateByHandle(sal_Int32 _nHandle)941 PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle )
942 {
943     // simply compare the current and the default value
944     Any aCurrentValue = getPropertyDefaultByHandle( _nHandle );
945     Any aDefaultValue;  getFastPropertyValue( aDefaultValue, _nHandle );
946 
947     sal_Bool bEqual = uno_type_equalData(
948             const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(),
949             const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(),
950             reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
951             reinterpret_cast< uno_ReleaseFunc >(cpp_release)
952         );
953     return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
954 }
955 
956 //------------------------------------------------------------------------------
setPropertyToDefaultByHandle(sal_Int32 _nHandle)957 void OControlModel::setPropertyToDefaultByHandle( sal_Int32 _nHandle)
958 {
959     Any aDefault = getPropertyDefaultByHandle( _nHandle );
960 
961     Any aConvertedValue, aOldValue;
962     if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) )
963     {
964         setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue );
965         // TODO: fire the property change
966     }
967 }
968 
969 //------------------------------------------------------------------------------
getPropertyDefaultByHandle(sal_Int32 _nHandle) const970 Any OControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
971 {
972     Any aReturn;
973     switch ( _nHandle )
974     {
975         case PROPERTY_ID_NAME:
976         case PROPERTY_ID_TAG:
977             aReturn <<= ::rtl::OUString();
978             break;
979 
980         case PROPERTY_ID_CLASSID:
981             aReturn <<= (sal_Int16)FormComponentType::CONTROL;
982             break;
983 
984         case PROPERTY_ID_TABINDEX:
985             aReturn <<= (sal_Int16)FRM_DEFAULT_TABINDEX;
986             break;
987 
988         case PROPERTY_ID_NATIVE_LOOK:
989             aReturn <<= (sal_Bool)sal_True;
990             break;
991         //added for exporting OCX control
992         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
993             aReturn <<= (sal_Int16)0;
994             break;
995         case PROPERTY_ID_OBJ_ID_IN_MSO:
996             aReturn <<= (sal_uInt16)INVALID_OBJ_ID_IN_MSO;
997             break;
998         default:
999             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1000                 m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn );
1001             else
1002                 OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" );
1003     }
1004     return aReturn;
1005 }
1006 
1007 //------------------------------------------------------------------------------
getFastPropertyValue(Any & _rValue,sal_Int32 _nHandle) const1008 void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
1009 {
1010     switch ( _nHandle )
1011     {
1012         case PROPERTY_ID_NAME:
1013             _rValue <<= m_aName;
1014             break;
1015         case PROPERTY_ID_TAG:
1016             _rValue <<= m_aTag;
1017             break;
1018         case PROPERTY_ID_CLASSID:
1019             _rValue <<= m_nClassId;
1020             break;
1021         case PROPERTY_ID_TABINDEX:
1022             _rValue <<= m_nTabIndex;
1023             break;
1024         case PROPERTY_ID_NATIVE_LOOK:
1025             _rValue <<= (sal_Bool)m_bNativeLook;
1026             break;
1027         //added for exporting OCX control
1028         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
1029             _rValue <<= (sal_Int16)m_nControlTypeinMSO;
1030             break;
1031         case PROPERTY_ID_OBJ_ID_IN_MSO:
1032             _rValue <<= (sal_uInt16)m_nObjIDinMSO;
1033             break;
1034         default:
1035             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1036                 m_aPropertyBagHelper.getDynamicFastPropertyValue( _nHandle, _rValue );
1037             else
1038                 OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle );
1039             break;
1040     }
1041 }
1042 
1043 //------------------------------------------------------------------------------
convertFastPropertyValue(Any & _rConvertedValue,Any & _rOldValue,sal_Int32 _nHandle,const Any & _rValue)1044 sal_Bool OControlModel::convertFastPropertyValue(
1045                         Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
1046 {
1047     sal_Bool bModified(sal_False);
1048     switch (_nHandle)
1049     {
1050         case PROPERTY_ID_NAME:
1051             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName);
1052             break;
1053         case PROPERTY_ID_TAG:
1054             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag);
1055             break;
1056         case PROPERTY_ID_TABINDEX:
1057             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex);
1058             break;
1059         case PROPERTY_ID_NATIVE_LOOK:
1060             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook);
1061             break;
1062         //added for exporting OCX control
1063         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
1064             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nControlTypeinMSO);
1065             break;
1066         case PROPERTY_ID_OBJ_ID_IN_MSO:
1067             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nObjIDinMSO);
1068             break;
1069         default:
1070             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1071                 bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue );
1072             else
1073                 OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" );
1074             break;
1075     }
1076     return bModified;
1077 }
1078 
1079 //------------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle,const Any & _rValue)1080 void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
1081 {
1082     switch (_nHandle)
1083     {
1084         case PROPERTY_ID_NAME:
1085             DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL),
1086                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1087             _rValue >>= m_aName;
1088             break;
1089         case PROPERTY_ID_TAG:
1090             DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL),
1091                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1092             _rValue >>= m_aTag;
1093             break;
1094         case PROPERTY_ID_TABINDEX:
1095             DBG_ASSERT(_rValue.getValueType() == getCppuType((const sal_Int16*)NULL),
1096                 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1097             _rValue >>= m_nTabIndex;
1098             break;
1099         case PROPERTY_ID_NATIVE_LOOK:
1100             OSL_VERIFY( _rValue >>= m_bNativeLook );
1101             break;
1102         //added for exporting OCX control
1103         case PROPERTY_ID_CONTROL_TYPE_IN_MSO:
1104             OSL_VERIFY( _rValue >>= m_nControlTypeinMSO );
1105             break;
1106         case PROPERTY_ID_OBJ_ID_IN_MSO:
1107             OSL_VERIFY( _rValue >>= m_nObjIDinMSO );
1108             break;
1109         default:
1110             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1111                 m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue );
1112             else
1113                 OSL_ENSURE( false, "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle!" );
1114             break;
1115     }
1116 }
1117 
1118 //------------------------------------------------------------------------------
describeFixedProperties(Sequence<Property> & _rProps) const1119 void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
1120 {
1121     //BEGIN_DESCRIBE_BASE_PROPERTIES( 4 )
1122     BEGIN_DESCRIBE_BASE_PROPERTIES( 6 )
1123         DECL_PROP2      (CLASSID,     sal_Int16,        READONLY, TRANSIENT);
1124         DECL_PROP1      (NAME,        ::rtl::OUString,  BOUND);
1125         DECL_BOOL_PROP2 (NATIVE_LOOK,                   BOUND, TRANSIENT);
1126         DECL_PROP1      (TAG,         ::rtl::OUString,  BOUND);
1127         DECL_PROP1      (CONTROL_TYPE_IN_MSO,sal_Int16,     BOUND);
1128         DECL_PROP1      (OBJ_ID_IN_MSO,sal_uInt16,      BOUND);
1129     END_DESCRIBE_PROPERTIES()
1130 }
1131 
1132 //------------------------------------------------------------------------------
describeAggregateProperties(Sequence<Property> & _rAggregateProps) const1133 void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const
1134 {
1135     if ( m_xAggregateSet.is() )
1136     {
1137         Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() );
1138         if ( xPSI.is() )
1139             _rAggregateProps = xPSI->getProperties();
1140     }
1141 }
1142 
1143 //------------------------------------------------------------------------------
getMutex()1144 ::osl::Mutex& OControlModel::getMutex()
1145 {
1146     return m_aMutex;
1147 }
1148 
1149 //------------------------------------------------------------------------------
describeFixedAndAggregateProperties(Sequence<Property> & _out_rFixedProperties,Sequence<Property> & _out_rAggregateProperties) const1150 void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const
1151 {
1152     describeFixedProperties( _out_rFixedProperties );
1153     describeAggregateProperties( _out_rAggregateProperties );
1154 }
1155 
1156 //------------------------------------------------------------------------------
getPropertiesInterface()1157 Reference< XMultiPropertySet > OControlModel::getPropertiesInterface()
1158 {
1159     return Reference< XMultiPropertySet >( *this, UNO_QUERY );
1160 }
1161 
1162 //------------------------------------------------------------------------------
getPropertySetInfo()1163 Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo()
1164 {
1165     return createPropertySetInfo( getInfoHelper() );
1166 }
1167 
1168 //------------------------------------------------------------------------------
getInfoHelper()1169 ::cppu::IPropertyArrayHelper& OControlModel::getInfoHelper()
1170 {
1171     return m_aPropertyBagHelper.getInfoHelper();
1172 }
1173 
1174 //--------------------------------------------------------------------
addProperty(const::rtl::OUString & _rName,::sal_Int16 _nAttributes,const Any & _rInitialValue)1175 void SAL_CALL OControlModel::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue )
1176 {
1177     m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
1178 }
1179 
1180 //--------------------------------------------------------------------
removeProperty(const::rtl::OUString & _rName)1181 void SAL_CALL OControlModel::removeProperty( const ::rtl::OUString& _rName )
1182 {
1183     m_aPropertyBagHelper.removeProperty( _rName );
1184 }
1185 
1186 //--------------------------------------------------------------------
getPropertyValues()1187 Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues()
1188 {
1189     return m_aPropertyBagHelper.getPropertyValues();
1190 }
1191 
1192 //--------------------------------------------------------------------
setPropertyValues(const Sequence<PropertyValue> & _rProps)1193 void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps )
1194 {
1195     m_aPropertyBagHelper.setPropertyValues( _rProps );
1196 }
1197 
1198 //--------------------------------------------------------------------
lockInstance(LockAccess)1199 void OControlModel::lockInstance( LockAccess )
1200 {
1201     m_aMutex.acquire();
1202     osl_incrementInterlockedCount( &m_lockCount );
1203 }
1204 
1205 //--------------------------------------------------------------------
unlockInstance(LockAccess)1206 oslInterlockedCount OControlModel::unlockInstance( LockAccess )
1207 {
1208     OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" );
1209     oslInterlockedCount lockCount = osl_decrementInterlockedCount( &m_lockCount );
1210     m_aMutex.release();
1211     return lockCount;
1212 }
1213 
1214 //--------------------------------------------------------------------
firePropertyChanges(const Sequence<sal_Int32> & _rHandles,const Sequence<Any> & _rOldValues,const Sequence<Any> & _rNewValues,LockAccess)1215 void OControlModel::firePropertyChanges( const Sequence< sal_Int32 >& _rHandles, const Sequence< Any >& _rOldValues,
1216                                         const Sequence< Any >& _rNewValues, LockAccess )
1217 {
1218     OPropertySetHelper::fire(
1219         const_cast< Sequence< sal_Int32 >& >( _rHandles ).getArray(),
1220         _rNewValues.getConstArray(),
1221         _rOldValues.getConstArray(),
1222         _rHandles.getLength(),
1223         sal_False
1224     );
1225 }
1226 
1227 //==================================================================
1228 //= OBoundControlModel
1229 //==================================================================
1230 DBG_NAME(frm_OBoundControlModel);
1231 //------------------------------------------------------------------
queryAggregation(const Type & _rType)1232 Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType )
1233 {
1234     Any aReturn( OControlModel::queryAggregation(_rType) );
1235     if (!aReturn.hasValue())
1236     {
1237         aReturn = OBoundControlModel_BASE1::queryInterface(_rType);
1238 
1239         if ( !aReturn.hasValue() && m_bCommitable )
1240             aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType );
1241 
1242         if ( !aReturn.hasValue() && m_bSupportsExternalBinding )
1243             aReturn = OBoundControlModel_BINDING::queryInterface( _rType );
1244 
1245         if ( !aReturn.hasValue() && m_bSupportsValidation )
1246             aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType );
1247     }
1248 
1249     return aReturn;
1250 }
1251 
1252 //------------------------------------------------------------------
OBoundControlModel(const Reference<XMultiServiceFactory> & _rxFactory,const::rtl::OUString & _rUnoControlModelTypeName,const::rtl::OUString & _rDefault,const sal_Bool _bCommitable,const sal_Bool _bSupportExternalBinding,const sal_Bool _bSupportsValidation)1253 OBoundControlModel::OBoundControlModel(
1254         const Reference< XMultiServiceFactory>& _rxFactory,
1255         const ::rtl::OUString& _rUnoControlModelTypeName, const ::rtl::OUString& _rDefault,
1256         const sal_Bool _bCommitable, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation )
1257     :OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False )
1258     ,OPropertyChangeListener( m_aMutex )
1259     ,m_xField()
1260     ,m_xAmbientForm()
1261     ,m_nValuePropertyAggregateHandle( -1 )
1262     ,m_nFieldType( DataType::OTHER )
1263     ,m_bValuePropertyMayBeVoid( false )
1264     ,m_aResetHelper( *this, m_aMutex )
1265     ,m_aUpdateListeners(m_aMutex)
1266     ,m_aFormComponentListeners( m_aMutex )
1267     ,m_bInputRequired( sal_True )
1268     ,m_pAggPropMultiplexer( NULL )
1269     ,m_bFormListening( false )
1270     ,m_bLoaded(sal_False)
1271     ,m_bRequired(sal_False)
1272     ,m_bCommitable(_bCommitable)
1273     ,m_bSupportsExternalBinding( _bSupportExternalBinding )
1274     ,m_bSupportsValidation( _bSupportsValidation )
1275     ,m_bForwardValueChanges(sal_True)
1276     ,m_bTransferingValue( sal_False )
1277     ,m_bIsCurrentValueValid( sal_True )
1278     ,m_bBindingControlsRO( sal_False )
1279     ,m_bBindingControlsEnable( sal_False )
1280     ,m_eControlValueChangeInstigator( eOther )
1281     ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT)
1282 {
1283     DBG_CTOR(frm_OBoundControlModel, NULL);
1284 
1285     // start property listening at the aggregate
1286     implInitAggMultiplexer( );
1287 }
1288 
1289 //------------------------------------------------------------------
OBoundControlModel(const OBoundControlModel * _pOriginal,const Reference<XMultiServiceFactory> & _rxFactory)1290 OBoundControlModel::OBoundControlModel(
1291         const OBoundControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory )
1292     :OControlModel( _pOriginal, _rxFactory, sal_True, sal_False )
1293     ,OPropertyChangeListener( m_aMutex )
1294     ,m_xField()
1295     ,m_xAmbientForm()
1296     ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle )
1297     ,m_nFieldType( DataType::OTHER )
1298     ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid )
1299     ,m_aResetHelper( *this, m_aMutex )
1300     ,m_aUpdateListeners( m_aMutex )
1301     ,m_aFormComponentListeners( m_aMutex )
1302     ,m_xValidator( _pOriginal->m_xValidator )
1303     ,m_bInputRequired( sal_True )
1304     ,m_pAggPropMultiplexer( NULL )
1305     ,m_bFormListening( false )
1306     ,m_bLoaded( sal_False )
1307     ,m_bRequired( sal_False )
1308     ,m_bCommitable( _pOriginal->m_bCommitable )
1309     ,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding )
1310     ,m_bSupportsValidation( _pOriginal->m_bSupportsValidation )
1311     ,m_bForwardValueChanges( sal_True )
1312     ,m_bTransferingValue( sal_False )
1313     ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid )
1314     ,m_bBindingControlsRO( sal_False )
1315     ,m_bBindingControlsEnable( sal_False )
1316     ,m_eControlValueChangeInstigator( eOther )
1317 {
1318     DBG_CTOR(frm_OBoundControlModel, NULL);
1319 
1320     // start property listening at the aggregate
1321     implInitAggMultiplexer( );
1322 
1323     m_aLabelServiceName = _pOriginal->m_aLabelServiceName;
1324     m_sValuePropertyName = _pOriginal->m_sValuePropertyName;
1325     m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle;
1326     m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid;
1327     m_aValuePropertyType = _pOriginal->m_aValuePropertyType;
1328     m_aControlSource = _pOriginal->m_aControlSource;
1329     m_bInputRequired = _pOriginal->m_bInputRequired;
1330     // m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transferred.
1331     // (the former should be clear - a clone of the object we're only referencing does not make sense)
1332     // (the second would violate the restriction for label controls that they're part of the
1333     // same form component hierarchy - we ourself are no part, yet, so we can't have a label control)
1334 
1335     // start listening for changes at the value property
1336     implInitValuePropertyListening( );
1337 }
1338 
1339 //------------------------------------------------------------------
~OBoundControlModel()1340 OBoundControlModel::~OBoundControlModel()
1341 {
1342     if ( !OComponentHelper::rBHelper.bDisposed )
1343     {
1344         acquire();
1345         dispose();
1346     }
1347 
1348     doResetDelegator( );
1349 
1350     OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" );
1351     if ( m_pAggPropMultiplexer )
1352     {
1353         m_pAggPropMultiplexer->dispose();
1354         m_pAggPropMultiplexer->release();
1355         m_pAggPropMultiplexer = NULL;
1356     }
1357 
1358     DBG_DTOR(frm_OBoundControlModel, NULL);
1359 }
1360 
1361 //------------------------------------------------------------------
clonedFrom(const OControlModel * _pOriginal)1362 void OBoundControlModel::clonedFrom( const OControlModel* _pOriginal )
1363 {
1364     const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal );
1365     // the value binding can be handled as if somebody called setValueBinding here
1366     // By definition, bindings can be share between bindables
1367     if ( pBoundOriginal && pBoundOriginal->m_xExternalBinding.is() )
1368     {
1369         try
1370         {
1371             setValueBinding( pBoundOriginal->m_xExternalBinding );
1372         }
1373         catch( const Exception& )
1374         {
1375             DBG_UNHANDLED_EXCEPTION();
1376         }
1377     }
1378 }
1379 
1380 //-----------------------------------------------------------------------------
implInitAggMultiplexer()1381 void OBoundControlModel::implInitAggMultiplexer( )
1382 {
1383     increment( m_refCount );
1384     if ( m_xAggregateSet.is() )
1385     {
1386         m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, sal_False );
1387         m_pAggPropMultiplexer->acquire();
1388     }
1389     decrement( m_refCount );
1390 
1391     doSetDelegator();
1392 }
1393 
1394 //-----------------------------------------------------------------------------
implInitValuePropertyListening() const1395 void OBoundControlModel::implInitValuePropertyListening( ) const
1396 {
1397     // start listening for changes at the value property
1398     // There are three pre-requisites for this to be done:
1399     // 1. We support external value bindings. In this case, the changes in the control value need to
1400     //    be propagated to the external binding immediately when they happen
1401     // 2. We support external validation. In this case, we need to listen for changes in the value
1402     //    property, since we need to revalidate then.
1403     // 3. We are not committable. In this case, changes in the control value need to be propagated
1404     //    to the database column immediately when they happen.
1405     if ( m_bSupportsExternalBinding || m_bSupportsValidation || !m_bCommitable )
1406     {
1407         OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" );
1408         if ( m_pAggPropMultiplexer && m_sValuePropertyName.getLength() )
1409             m_pAggPropMultiplexer->addProperty( m_sValuePropertyName );
1410     }
1411 }
1412 
1413 //-----------------------------------------------------------------------------
initOwnValueProperty(const::rtl::OUString & i_rValuePropertyName)1414 void OBoundControlModel::initOwnValueProperty( const ::rtl::OUString& i_rValuePropertyName )
1415 {
1416     OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle,
1417         "OBoundControlModel::initOwnValueProperty: value property is already initialized!" );
1418     OSL_ENSURE( i_rValuePropertyName.getLength(), "OBoundControlModel::initOwnValueProperty: invalid property name!" );
1419     m_sValuePropertyName = i_rValuePropertyName;
1420 }
1421 
1422 //-----------------------------------------------------------------------------
initValueProperty(const::rtl::OUString & _rValuePropertyName,sal_Int32 _nValuePropertyExternalHandle)1423 void OBoundControlModel::initValueProperty( const ::rtl::OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle )
1424 {
1425     OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle,
1426         "OBoundControlModel::initValueProperty: value property is already initialized!" );
1427     OSL_ENSURE( _rValuePropertyName.getLength(), "OBoundControlModel::initValueProperty: invalid property name!" );
1428     OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" );
1429 
1430     m_sValuePropertyName = _rValuePropertyName;
1431     m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle );
1432     OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" );
1433 
1434     if ( m_nValuePropertyAggregateHandle != -1 )
1435     {
1436         Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW );
1437         Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName );
1438         m_aValuePropertyType = aValuePropDesc.Type;
1439         m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0;
1440     }
1441 
1442     // start listening for changes at the value property
1443     implInitValuePropertyListening( );
1444 }
1445 
1446 //-----------------------------------------------------------------------------
suspendValueListening()1447 void OBoundControlModel::suspendValueListening( )
1448 {
1449     OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::suspendValueListening: don't have a value property!" );
1450     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" );
1451 
1452     if ( m_pAggPropMultiplexer )
1453         m_pAggPropMultiplexer->lock();
1454 }
1455 
1456 //-----------------------------------------------------------------------------
resumeValueListening()1457 void OBoundControlModel::resumeValueListening( )
1458 {
1459     OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::resumeValueListening: don't have a value property!" );
1460     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" );
1461     OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" );
1462 
1463     if ( m_pAggPropMultiplexer )
1464         m_pAggPropMultiplexer->unlock();
1465 }
1466 
1467 //-----------------------------------------------------------------------------
_getTypes()1468 Sequence< Type > OBoundControlModel::_getTypes()
1469 {
1470     TypeBag aTypes(
1471         OControlModel::_getTypes(),
1472         OBoundControlModel_BASE1::getTypes()
1473     );
1474 
1475     if ( m_bCommitable )
1476         aTypes.addTypes( OBoundControlModel_COMMITTING::getTypes() );
1477 
1478     if ( m_bSupportsExternalBinding )
1479         aTypes.addTypes( OBoundControlModel_BINDING::getTypes() );
1480 
1481     if ( m_bSupportsValidation )
1482         aTypes.addTypes( OBoundControlModel_VALIDATION::getTypes() );
1483 
1484     return aTypes.getTypes();
1485 }
1486 
1487 // OComponentHelper
1488 //-----------------------------------------------------------------------------
disposing()1489 void OBoundControlModel::disposing()
1490 {
1491     OControlModel::disposing();
1492 
1493     ::osl::ClearableMutexGuard aGuard(m_aMutex);
1494 
1495     if ( m_pAggPropMultiplexer )
1496         m_pAggPropMultiplexer->dispose();
1497 
1498     // notify all our listeners
1499     com::sun::star::lang::EventObject aEvt( static_cast< XWeak* >( this ) );
1500     m_aUpdateListeners.disposeAndClear( aEvt );
1501     m_aResetHelper.disposing();
1502 
1503     // disconnect from our database column
1504     // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify?
1505     // The only more thing which it does is calling onDisconnectedDbColumn - could this
1506     // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*.
1507     if ( hasField() )
1508     {
1509         getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
1510         resetField();
1511     }
1512     m_xCursor = NULL;
1513 
1514     Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1515     if ( xComp.is() )
1516         xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) );
1517 
1518     // disconnect from our external value binding
1519     if ( hasExternalValueBinding() )
1520         disconnectExternalValueBinding();
1521 
1522     // dito for the validator
1523     if ( hasValidator() )
1524         disconnectValidator( );
1525 }
1526 
1527 //------------------------------------------------------------------------------
onValuePropertyChange(ControlModelLock & i_rControLock)1528 void OBoundControlModel::onValuePropertyChange( ControlModelLock& i_rControLock )
1529 {
1530     if ( hasExternalValueBinding() )
1531     {   // the control value changed, while we have an external value binding
1532         // -> forward the value to it
1533         if ( m_eControlValueChangeInstigator != eExternalBinding )
1534             transferControlValueToExternal( i_rControLock );
1535     }
1536     else if ( !m_bCommitable && m_xColumnUpdate.is() )
1537     {   // the control value changed, while we are  bound to a database column,
1538         // but not committable (which means changes in the control have to be reflected to
1539         // the underlying database column immediately)
1540         // -> forward the value to the database column
1541         if ( m_eControlValueChangeInstigator != eDbColumnBinding )
1542             commitControlValueToDbColumn( false );
1543     }
1544 
1545     // validate the new value
1546     if ( m_bSupportsValidation )
1547         recheckValidity( true );
1548 }
1549 
1550 //------------------------------------------------------------------------------
_propertyChanged(const PropertyChangeEvent & _rEvt)1551 void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt )
1552 {
1553     ControlModelLock aLock( *this );
1554 
1555     OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName,
1556         "OBoundControlModel::_propertyChanged: where did this come from (1)?" );
1557     OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(),
1558         "OBoundControlModel::_propertyChanged: where did this come from (2)?" );
1559 
1560     if ( _rEvt.PropertyName == m_sValuePropertyName )
1561     {
1562         onValuePropertyChange( aLock );
1563     }
1564 }
1565 
1566 //------------------------------------------------------------------------------
startAggregatePropertyListening(const::rtl::OUString & _rPropertyName)1567 void OBoundControlModel::startAggregatePropertyListening( const ::rtl::OUString& _rPropertyName )
1568 {
1569     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" );
1570     OSL_ENSURE( _rPropertyName.getLength(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" );
1571 
1572     if ( m_pAggPropMultiplexer && _rPropertyName.getLength() )
1573     {
1574         m_pAggPropMultiplexer->addProperty( _rPropertyName );
1575     }
1576 }
1577 
1578 //------------------------------------------------------------------------------
doFormListening(const bool _bStart)1579 void OBoundControlModel::doFormListening( const bool _bStart )
1580 {
1581     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" );
1582 
1583     if ( isFormListening() == _bStart )
1584         return;
1585 
1586     if ( m_xAmbientForm.is() )
1587         _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this );
1588 
1589     Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY );
1590     if ( getParent().is() && !xParentLoadable.is() )
1591     {
1592         // if our parent does not directly support the XLoadable interface, then it might support the
1593         // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes
1594         // broadcasted by the latter.
1595         Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY );
1596         if ( xRowSetBroadcaster.is() )
1597             _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this );
1598     }
1599 
1600     m_bFormListening = _bStart && m_xAmbientForm.is();
1601 }
1602 
1603 // XChild
1604 //------------------------------------------------------------------------------
setParent(const Reference<XInterface> & _rxParent)1605 void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent)
1606 {
1607     ControlModelLock aLock( *this );
1608     FieldChangeNotifier aBoundFieldNotifier( aLock );
1609 
1610     if ( getParent() == _rxParent )
1611         return;
1612 
1613     // disconnect from database column (which is controlled by parent, directly or indirectly)
1614     if ( hasField() )
1615         impl_disconnectDatabaseColumn_noNotify();
1616 
1617     // log off old listeners
1618     if ( isFormListening() )
1619         doFormListening( false );
1620 
1621     // actually set the new parent
1622     OControlModel::setParent( _rxParent );
1623 
1624     // a new parent means a new ambient form
1625     impl_determineAmbientForm_nothrow();
1626 
1627     if ( !hasExternalValueBinding() )
1628     {
1629         // log on new listeners
1630         doFormListening( true );
1631 
1632         // re-connect to database column of the new parent
1633         if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
1634             impl_connectDatabaseColumn_noNotify( false );
1635     }
1636 }
1637 
1638 // XEventListener
1639 //------------------------------------------------------------------------------
disposing(const com::sun::star::lang::EventObject & _rEvent)1640 void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent)
1641 {
1642     ControlModelLock aLock( *this );
1643 
1644     if ( _rEvent.Source == getField() )
1645     {
1646         resetField();
1647     }
1648     else if ( _rEvent.Source == m_xLabelControl )
1649     {
1650         Reference<XPropertySet> xOldValue = m_xLabelControl;
1651         m_xLabelControl = NULL;
1652 
1653         // fire a propertyChanged (when we leave aLock's scope)
1654         aLock.addPropertyNotification( PROPERTY_ID_CONTROLLABEL, makeAny( xOldValue ), makeAny( m_xLabelControl ) );
1655     }
1656     else if ( _rEvent.Source == m_xExternalBinding )
1657     {   // *first* check for the external binding
1658         disconnectExternalValueBinding( );
1659     }
1660     else if ( _rEvent.Source == m_xValidator )
1661     {   // *then* check for the validator. Reason is that bindings may also act as validator at the same
1662         // time, in this case, the validator is automatically revoked when the binding is revoked
1663         disconnectValidator( );
1664     }
1665     else
1666         OControlModel::disposing(_rEvent);
1667 }
1668 
1669 // XServiceInfo
1670 //------------------------------------------------------------------------------
getSupportedServiceNames()1671 StringSequence SAL_CALL OBoundControlModel::getSupportedServiceNames()
1672 {
1673     return ::comphelper::concatSequences(
1674         getAggregateServiceNames(),
1675         getSupportedServiceNames_Static()
1676     );
1677 }
1678 
1679 //------------------------------------------------------------------------------
getSupportedServiceNames_Static()1680 Sequence< ::rtl::OUString > SAL_CALL OBoundControlModel::getSupportedServiceNames_Static()
1681 {
1682     Sequence< ::rtl::OUString > aOwnServiceNames( 1 );
1683     aOwnServiceNames[ 0 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.DataAwareControlModel" );
1684 
1685     return ::comphelper::concatSequences(
1686         OControlModel::getSupportedServiceNames_Static(),
1687         aOwnServiceNames
1688     );
1689 }
1690 
1691 // XPersist
1692 //------------------------------------------------------------------------------
write(const Reference<stario::XObjectOutputStream> & _rxOutStream)1693 void SAL_CALL OBoundControlModel::write( const Reference<stario::XObjectOutputStream>& _rxOutStream )
1694 {
1695     OControlModel::write(_rxOutStream);
1696 
1697     osl::MutexGuard aGuard(m_aMutex);
1698 
1699     // Version
1700     _rxOutStream->writeShort(0x0002);
1701 
1702     // Controlsource
1703     ::comphelper::operator<<( _rxOutStream, m_aControlSource);
1704 
1705     // !!! IMPORTANT NOTE !!!
1706     // don't write any new members here : this wouldn't be compatible with older versions, as OBoundControlModel
1707     // is a base class which is called in derived classes "read" method. So if you increment the version
1708     // and write new stuff, older office versions will read this in the _derived_ classes, which may result
1709     // in anything from data loss to crash.
1710     // (use writeCommonProperties instead, this is called in derived classes write-method)
1711     // !!! EOIN !!!
1712     // FS - 68876 - 28.09.1999
1713 }
1714 
1715 //------------------------------------------------------------------------------
defaultCommonProperties()1716 void OBoundControlModel::defaultCommonProperties()
1717 {
1718     Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1719     if (xComp.is())
1720         xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1721     m_xLabelControl = NULL;
1722 }
1723 
1724 //------------------------------------------------------------------------------
readCommonProperties(const Reference<stario::XObjectInputStream> & _rxInStream)1725 void OBoundControlModel::readCommonProperties(const Reference<stario::XObjectInputStream>& _rxInStream)
1726 {
1727     sal_Int32 nLen = _rxInStream->readLong();
1728 
1729     Reference<stario::XMarkableStream> xMark(_rxInStream, UNO_QUERY);
1730     DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
1731     sal_Int32 nMark = xMark->createMark();
1732 
1733     // read the reference to the label control
1734     Reference<stario::XPersistObject> xPersist;
1735     sal_Int32 nUsedFlag;
1736     nUsedFlag = _rxInStream->readLong();
1737     if (nUsedFlag)
1738         xPersist = _rxInStream->readObject();
1739     m_xLabelControl = m_xLabelControl.query( xPersist );
1740     Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1741     if (xComp.is())
1742         xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1743 
1744     // read any other new common properties here
1745 
1746     // skip the remaining bytes
1747     xMark->jumpToMark(nMark);
1748     _rxInStream->skipBytes(nLen);
1749     xMark->deleteMark(nMark);
1750 }
1751 
1752 //------------------------------------------------------------------------------
writeCommonProperties(const Reference<stario::XObjectOutputStream> & _rxOutStream)1753 void OBoundControlModel::writeCommonProperties(const Reference<stario::XObjectOutputStream>& _rxOutStream)
1754 {
1755     Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
1756     DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !");
1757     sal_Int32 nMark = xMark->createMark();
1758 
1759     // a placeholder where we will write the overall length (later in this method)
1760     sal_Int32 nLen = 0;
1761     _rxOutStream->writeLong(nLen);
1762 
1763     // write the reference to the label control
1764     Reference<stario::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY);
1765     sal_Int32 nUsedFlag = 0;
1766     if (xPersist.is())
1767         nUsedFlag = 1;
1768     _rxOutStream->writeLong(nUsedFlag);
1769     if (xPersist.is())
1770         _rxOutStream->writeObject(xPersist);
1771 
1772     // write any other new common properties here
1773 
1774     // write the correct length at the beginning of the block
1775     nLen = xMark->offsetToMark(nMark) - sizeof(nLen);
1776     xMark->jumpToMark(nMark);
1777     _rxOutStream->writeLong(nLen);
1778     xMark->jumpToFurthest();
1779     xMark->deleteMark(nMark);
1780 }
1781 
1782 //------------------------------------------------------------------------------
read(const Reference<stario::XObjectInputStream> & _rxInStream)1783 void SAL_CALL OBoundControlModel::read( const Reference< stario::XObjectInputStream >& _rxInStream )
1784 {
1785     OControlModel::read(_rxInStream);
1786 
1787     osl::MutexGuard aGuard(m_aMutex);
1788     sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion;
1789     ::comphelper::operator>>( _rxInStream, m_aControlSource);
1790 }
1791 
1792 //------------------------------------------------------------------------------
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const1793 void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
1794 {
1795     switch (nHandle)
1796     {
1797         case PROPERTY_ID_INPUT_REQUIRED:
1798             rValue <<= m_bInputRequired;
1799             break;
1800         case PROPERTY_ID_CONTROLSOURCEPROPERTY:
1801             rValue <<= m_sValuePropertyName;
1802             break;
1803         case PROPERTY_ID_CONTROLSOURCE:
1804             rValue <<= m_aControlSource;
1805             break;
1806         case PROPERTY_ID_BOUNDFIELD:
1807             rValue <<= getField();
1808             break;
1809         case PROPERTY_ID_CONTROLLABEL:
1810             if (!m_xLabelControl.is())
1811                 rValue.clear();
1812             else
1813                 rValue <<= m_xLabelControl;
1814             break;
1815         default:
1816             OControlModel::getFastPropertyValue(rValue, nHandle);
1817     }
1818 }
1819 
1820 //------------------------------------------------------------------------------
convertFastPropertyValue(Any & _rConvertedValue,Any & _rOldValue,sal_Int32 _nHandle,const Any & _rValue)1821 sal_Bool OBoundControlModel::convertFastPropertyValue(
1822                                 Any& _rConvertedValue, Any& _rOldValue,
1823                 sal_Int32 _nHandle,
1824                                 const Any& _rValue)
1825 {
1826     sal_Bool bModified(sal_False);
1827     switch (_nHandle)
1828     {
1829         case PROPERTY_ID_INPUT_REQUIRED:
1830             bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired );
1831             break;
1832         case PROPERTY_ID_CONTROLSOURCE:
1833             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource);
1834             break;
1835         case PROPERTY_ID_BOUNDFIELD:
1836             DBG_ERROR( "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" );
1837             throw com::sun::star::lang::IllegalArgumentException();
1838         case PROPERTY_ID_CONTROLLABEL:
1839             if (!_rValue.hasValue())
1840             {   // property set to void
1841                 _rConvertedValue = Any();
1842                 getFastPropertyValue(_rOldValue, _nHandle);
1843                 bModified = m_xLabelControl.is();
1844             }
1845             else
1846             {
1847                 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl);
1848                 if (!m_xLabelControl.is())
1849                     // an empty interface is interpreted as VOID
1850                     _rOldValue.clear();
1851             }
1852             break;
1853         default:
1854             bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
1855     }
1856     return bModified;
1857 }
1858 
1859 //------------------------------------------------------------------------------
getPropertyDefaultByHandle(sal_Int32 _nHandle) const1860 Any OBoundControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
1861 {
1862     Any aDefault;
1863     switch ( _nHandle )
1864     {
1865         case PROPERTY_ID_INPUT_REQUIRED:
1866             aDefault <<= sal_Bool( sal_True );
1867             break;
1868 
1869         case PROPERTY_ID_CONTROLSOURCE:
1870             aDefault <<= ::rtl::OUString();
1871             break;
1872 
1873         case PROPERTY_ID_CONTROLLABEL:
1874             aDefault <<= Reference< XPropertySet >();
1875             break;
1876     }
1877     return aDefault;
1878 }
1879 
1880 //------------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)1881 void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
1882 {
1883     switch (nHandle)
1884     {
1885         case PROPERTY_ID_INPUT_REQUIRED:
1886             OSL_VERIFY( rValue >>= m_bInputRequired );
1887             break;
1888         case PROPERTY_ID_CONTROLSOURCE:
1889             OSL_VERIFY( rValue >>= m_aControlSource );
1890             break;
1891         case PROPERTY_ID_BOUNDFIELD:
1892             DBG_ERROR("OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !");
1893             throw com::sun::star::lang::IllegalArgumentException();
1894         case PROPERTY_ID_CONTROLLABEL:
1895         {
1896             if ( rValue.hasValue() && ( rValue.getValueTypeClass() != TypeClass_INTERFACE ) )
1897                 throw com::sun::star::lang::IllegalArgumentException();
1898 
1899             Reference< XInterface > xNewValue( rValue, UNO_QUERY );
1900             if ( !xNewValue.is() )
1901             {   // set property to "void"
1902                 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1903                 if ( xComp.is() )
1904                     xComp->removeEventListener( static_cast< XPropertyChangeListener* >( this ) );
1905                 m_xLabelControl = NULL;
1906                 break;
1907             }
1908 
1909             Reference< XControlModel >  xAsModel        ( xNewValue,        UNO_QUERY );
1910             Reference< XServiceInfo >   xAsServiceInfo  ( xAsModel,         UNO_QUERY );
1911             Reference< XPropertySet >   xAsPropSet      ( xAsServiceInfo,   UNO_QUERY );
1912             Reference< XChild >         xAsChild        ( xAsPropSet,       UNO_QUERY );
1913             if ( !xAsChild.is() || !xAsServiceInfo->supportsService( m_aLabelServiceName ) )
1914             {
1915                 throw com::sun::star::lang::IllegalArgumentException();
1916             }
1917 
1918             // check if weself and the given model have a common anchestor (up to the forms collection)
1919             Reference<XChild> xCont;
1920             query_interface(static_cast<XWeak*>(this), xCont);
1921             Reference< XInterface > xMyTopLevel = xCont->getParent();
1922             while (xMyTopLevel.is())
1923             {
1924                 Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY);
1925                 if (!xAsForm.is())
1926                     // found my root
1927                     break;
1928 
1929                 Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY);
1930                 xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
1931             }
1932             Reference< XInterface > xNewTopLevel = xAsChild->getParent();
1933             while (xNewTopLevel.is())
1934             {
1935                 Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY);
1936                 if (!xAsForm.is())
1937                     break;
1938 
1939                 Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY);
1940                 xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
1941             }
1942             if (xNewTopLevel != xMyTopLevel)
1943             {
1944                 // the both objects don't belong to the same forms collection -> not acceptable
1945                 throw com::sun::star::lang::IllegalArgumentException();
1946             }
1947 
1948             m_xLabelControl = xAsPropSet;
1949             Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1950             if (xComp.is())
1951                 xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1952         }
1953         break;
1954         default:
1955             OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue );
1956     }
1957 }
1958 
1959 // XPropertyChangeListener
1960 //------------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)1961 void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt )
1962 {
1963     // if the DBColumn value changed, transfer it to the control
1964     if ( evt.PropertyName.equals( PROPERTY_VALUE ) )
1965     {
1966         OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database column?" );
1967         osl::MutexGuard aGuard(m_aMutex);
1968         if ( m_bForwardValueChanges && m_xColumn.is() )
1969             transferDbValueToControl();
1970     }
1971     else
1972     {
1973         OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" );
1974 
1975         // our binding has properties which can control properties of ourself
1976         ::rtl::OUString sBindingControlledProperty;
1977         bool bForwardToLabelControl = false;
1978         if ( evt.PropertyName.equals( PROPERTY_READONLY ) )
1979         {
1980             sBindingControlledProperty = PROPERTY_READONLY;
1981         }
1982         else if ( evt.PropertyName.equals( PROPERTY_RELEVANT ) )
1983         {
1984             sBindingControlledProperty = PROPERTY_ENABLED;
1985             bForwardToLabelControl = true;
1986         }
1987         else
1988             return;
1989 
1990         try
1991         {
1992             setPropertyValue( sBindingControlledProperty, evt.NewValue );
1993             if ( bForwardToLabelControl && m_xLabelControl.is() )
1994                 m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue );
1995         }
1996         catch( const Exception& )
1997         {
1998             OSL_ENSURE( sal_False, "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!" );
1999         }
2000     }
2001 }
2002 
2003 //------------------------------------------------------------------------------
onRowSetChanged(const EventObject &)2004 void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ )
2005 {
2006     ControlModelLock aLock( *this );
2007     FieldChangeNotifier aBoundFieldNotifier( aLock );
2008 
2009     // disconnect from database column (which is controlled by parent, directly or indirectly)
2010     if ( hasField() )
2011         impl_disconnectDatabaseColumn_noNotify();
2012 
2013     // log off old listeners
2014     if ( isFormListening() )
2015         doFormListening( false );
2016 
2017     // determine the new ambient form
2018     impl_determineAmbientForm_nothrow();
2019 
2020     // log on new listeners
2021     doFormListening( true );
2022 
2023     // re-connect to database column if needed and possible
2024     if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
2025         impl_connectDatabaseColumn_noNotify( false );
2026 }
2027 
2028 // XBoundComponent
2029 //------------------------------------------------------------------------------
addUpdateListener(const Reference<XUpdateListener> & _rxListener)2030 void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener)
2031 {
2032     m_aUpdateListeners.addInterface(_rxListener);
2033 }
2034 
2035 //------------------------------------------------------------------------------
removeUpdateListener(const Reference<XUpdateListener> & _rxListener)2036 void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener)
2037 {
2038     m_aUpdateListeners.removeInterface(_rxListener);
2039 }
2040 
2041 //------------------------------------------------------------------------------
commit()2042 sal_Bool SAL_CALL OBoundControlModel::commit()
2043 {
2044     ControlModelLock aLock( *this );
2045 
2046     OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not commitable !) " );
2047     if ( hasExternalValueBinding() )
2048     {
2049         // in most cases, no action is required: For most derivees, we know the value property of
2050         // our control (see initValueProperty), and when an external binding is active, we
2051         // instantly forward all changes in this property to the external binding.
2052         if ( !m_sValuePropertyName.getLength() )
2053             // but for those derivees which did not use this feature, we need an
2054             // explicit transfer
2055             transferControlValueToExternal( aLock );
2056         return sal_True;
2057     }
2058 
2059     OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" );
2060         // we reach this only if we're not working with an external binding
2061 
2062     if ( !hasField() )
2063         return sal_True;
2064 
2065     ::cppu::OInterfaceIteratorHelper aIter( m_aUpdateListeners );
2066     EventObject aEvent;
2067     aEvent.Source = static_cast< XWeak* >( this );
2068     sal_Bool bSuccess = sal_True;
2069 
2070     aLock.release();
2071     // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2072     while (aIter.hasMoreElements() && bSuccess)
2073         bSuccess = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvent );
2074     // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2075     aLock.acquire();
2076 
2077     if ( bSuccess )
2078     {
2079         try
2080         {
2081             if ( m_xColumnUpdate.is() )
2082                 bSuccess = commitControlValueToDbColumn( sal_False );
2083         }
2084         catch(Exception&)
2085         {
2086             bSuccess = sal_False;
2087         }
2088     }
2089 
2090     if ( bSuccess )
2091     {
2092         aLock.release();
2093         m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent );
2094     }
2095 
2096     return bSuccess;
2097 }
2098 
2099 //------------------------------------------------------------------------------
resetField()2100 void OBoundControlModel::resetField()
2101 {
2102     m_xColumnUpdate.clear();
2103     m_xColumn.clear();
2104     m_xField.clear();
2105     m_nFieldType = DataType::OTHER;
2106 }
2107 
2108 //------------------------------------------------------------------------------
connectToField(const Reference<XRowSet> & rForm)2109 sal_Bool OBoundControlModel::connectToField(const Reference<XRowSet>& rForm)
2110 {
2111     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" );
2112 
2113     // wenn eine Verbindung zur Datenbank existiert
2114     if (rForm.is() && getConnection(rForm).is())
2115     {
2116         // Feld bestimmen und PropertyChangeListener
2117         m_xCursor = rForm;
2118         Reference<XPropertySet> xFieldCandidate;
2119 
2120         if (m_xCursor.is())
2121         {
2122             Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY);
2123             DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the com::sun::star::sdb::ResultSet service !");
2124             if (xColumnsSupplier.is())
2125             {
2126                 Reference<XNameAccess> xColumns(xColumnsSupplier->getColumns(), UNO_QUERY);
2127                 if (xColumns.is() && xColumns->hasByName(m_aControlSource))
2128                 {
2129                     OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate );
2130                 }
2131             }
2132         }
2133 
2134         try
2135         {
2136             sal_Int32 nFieldType = DataType::OTHER;
2137             if ( xFieldCandidate.is() )
2138             {
2139                 xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
2140                 if ( approveDbColumnType( nFieldType ) )
2141                     impl_setField_noNotify( xFieldCandidate );
2142             }
2143             else
2144                 impl_setField_noNotify( NULL );
2145 
2146             if ( m_xField.is() )
2147             {
2148                 if( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) )
2149                 {
2150                     m_nFieldType = nFieldType;
2151 
2152                     // an wertaenderungen horchen
2153                     m_xField->addPropertyChangeListener( PROPERTY_VALUE, this );
2154                     m_xColumnUpdate = Reference< XColumnUpdate >( m_xField, UNO_QUERY );
2155                     m_xColumn = Reference< XColumn >( m_xField, UNO_QUERY );
2156 
2157                     sal_Int32 nNullableFlag = ColumnValue::NO_NULLS;
2158                     m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag;
2159                     m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag);
2160                         // we're optimistic : in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability ....
2161                 }
2162                 else
2163                 {
2164                     OSL_ENSURE(sal_False, "OBoundControlModel::connectToField: property NAME not supported!");
2165                     impl_setField_noNotify( NULL );
2166                 }
2167             }
2168         }
2169         catch( const Exception& )
2170         {
2171             DBG_UNHANDLED_EXCEPTION();
2172             resetField();
2173         }
2174     }
2175     return hasField();
2176 }
2177 
2178 //------------------------------------------------------------------------------
initFromField(const Reference<XRowSet> & _rxRowSet)2179 void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet )
2180 {
2181     // but only if the rowset if positioned on a valid record
2182     if ( hasField() && _rxRowSet.is() )
2183     {
2184         if ( !_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast() )
2185             transferDbValueToControl();
2186         else
2187             // reset the field if the row set is empty
2188             // #i30661# / 2004-12-16 / frank.schoenheit@sun.com
2189             resetNoBroadcast();
2190     }
2191 }
2192 
2193 //------------------------------------------------------------------------------
approveDbColumnType(sal_Int32 _nColumnType)2194 sal_Bool OBoundControlModel::approveDbColumnType(sal_Int32 _nColumnType)
2195 {
2196     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" );
2197 
2198     if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY)
2199         || (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER)
2200         || (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT)
2201         || (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY)
2202         || (_nColumnType == DataType::BLOB) /*|| (_nColumnType == DataType::CLOB)*/
2203         || (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL))
2204         return sal_False;
2205 
2206     return sal_True;
2207 }
2208 
2209 //------------------------------------------------------------------------------
impl_determineAmbientForm_nothrow()2210 void OBoundControlModel::impl_determineAmbientForm_nothrow()
2211 {
2212     Reference< XInterface > xParent( const_cast< OBoundControlModel* >( this )->getParent() );
2213 
2214     m_xAmbientForm.set( xParent, UNO_QUERY );
2215     if ( !m_xAmbientForm.is() )
2216     {
2217         Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY );
2218         if ( xSupRowSet.is() )
2219             m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY );
2220     }
2221 }
2222 
2223 //------------------------------------------------------------------------------
impl_connectDatabaseColumn_noNotify(bool _bFromReload)2224 void OBoundControlModel::impl_connectDatabaseColumn_noNotify( bool _bFromReload )
2225 {
2226     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" );
2227 
2228     // consistency checks
2229     DBG_ASSERT( !( hasField() && !_bFromReload ),
2230         "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" );
2231     (void)_bFromReload;
2232 
2233     Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY );
2234     OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" );
2235     if ( !xRowSet.is() )
2236         return;
2237 
2238     if ( !hasField() )
2239     {
2240         // connect to the column
2241         connectToField( xRowSet );
2242     }
2243 
2244     // now that we're connected (more or less, even if we did not find a column),
2245     // we definitely want to forward any potentially occurring value changes
2246     m_bForwardValueChanges = sal_True;
2247 
2248     // let derived classes react on this new connection
2249     m_bLoaded = sal_True;
2250     onConnectedDbColumn( xRowSet );
2251 
2252     // initially transfer the db column value to the control, if we successfully connected to a database column
2253     if ( hasField() )
2254         initFromField( xRowSet );
2255 }
2256 
2257 //------------------------------------------------------------------------------
impl_disconnectDatabaseColumn_noNotify()2258 void OBoundControlModel::impl_disconnectDatabaseColumn_noNotify()
2259 {
2260     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" );
2261 
2262     // let derived classes react on this
2263     onDisconnectedDbColumn();
2264 
2265     if ( hasField() )
2266     {
2267         getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
2268         resetField();
2269     }
2270 
2271     m_xCursor = NULL;
2272     m_bLoaded = sal_False;
2273 }
2274 
2275 //==============================================================================
2276 // XLoadListener
2277 //------------------------------------------------------------------------------
loaded(const EventObject & _rEvent)2278 void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent )
2279 {
2280     ControlModelLock aLock( *this );
2281     FieldChangeNotifier aBoundFieldNotifier( aLock );
2282 
2283     OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" );
2284     (void)_rEvent;
2285 
2286     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" );
2287     if ( hasExternalValueBinding() )
2288         return;
2289 
2290     impl_connectDatabaseColumn_noNotify( false );
2291 }
2292 
2293 
2294 //------------------------------------------------------------------------------
unloaded(const com::sun::star::lang::EventObject &)2295 void SAL_CALL OBoundControlModel::unloaded( const com::sun::star::lang::EventObject& /*aEvent*/ )
2296 {
2297     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" );
2298 }
2299 
2300 //------------------------------------------------------------------------------
reloading(const com::sun::star::lang::EventObject &)2301 void SAL_CALL OBoundControlModel::reloading( const com::sun::star::lang::EventObject& /*aEvent*/ )
2302 {
2303     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" );
2304     if ( hasExternalValueBinding() )
2305         return;
2306 
2307     osl::MutexGuard aGuard(m_aMutex);
2308     m_bForwardValueChanges = sal_False;
2309 }
2310 
2311 //------------------------------------------------------------------------------
unloading(const com::sun::star::lang::EventObject &)2312 void SAL_CALL OBoundControlModel::unloading(const com::sun::star::lang::EventObject& /*aEvent*/)
2313 {
2314     ControlModelLock aLock( *this );
2315     FieldChangeNotifier aBoundFieldNotifier( aLock );
2316 
2317     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" );
2318     if ( hasExternalValueBinding() )
2319         return;
2320 
2321     impl_disconnectDatabaseColumn_noNotify();
2322 }
2323 
2324 //------------------------------------------------------------------------------
reloaded(const EventObject & _rEvent)2325 void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent )
2326 {
2327     ControlModelLock aLock( *this );
2328     FieldChangeNotifier aBoundFieldNotifier( aLock );
2329 
2330     OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" );
2331     (void)_rEvent;
2332 
2333     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" );
2334     if ( hasExternalValueBinding() )
2335         return;
2336 
2337     impl_connectDatabaseColumn_noNotify( true );
2338 }
2339 
2340 //------------------------------------------------------------------------------
setControlValue(const Any & _rValue,ValueChangeInstigator _eInstigator)2341 void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator )
2342 {
2343     m_eControlValueChangeInstigator = _eInstigator;
2344     doSetControlValue( _rValue );
2345     m_eControlValueChangeInstigator = eOther;
2346 }
2347 
2348 //------------------------------------------------------------------------------
doSetControlValue(const Any & _rValue)2349 void OBoundControlModel::doSetControlValue( const Any& _rValue )
2350 {
2351     OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
2352         "OBoundControlModel::doSetControlValue: invalid aggregate !" );
2353     OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ),
2354         "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" );
2355 
2356     try
2357     {
2358         // release our mutex once (it's acquired in one of the calling methods), as setting aggregate properties
2359         // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with
2360         // our own mutex locked
2361         // #72451# / 2000-01-31 / frank.schoenheit@sun.com
2362         MutexRelease aRelease( m_aMutex );
2363         if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
2364         {
2365             m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue );
2366         }
2367         else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() )
2368         {
2369             m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue );
2370         }
2371     }
2372     catch( const Exception& )
2373     {
2374         OSL_ENSURE( sal_False, "OBoundControlModel::doSetControlValue: caught an exception!" );
2375     }
2376 }
2377 
2378 //------------------------------------------------------------------------------
onConnectedValidator()2379 void OBoundControlModel::onConnectedValidator( )
2380 {
2381     try
2382     {
2383         // if we have an external validator, we do not want the control to force invalid
2384         // inputs to the default value. Instead, invalid inputs should be translated
2385         // to NaN (not a number)
2386         Reference< XPropertySetInfo > xAggregatePropertyInfo;
2387         if ( m_xAggregateSet.is() )
2388             xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
2389         if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
2390             m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_False ) );
2391     }
2392     catch( const Exception& )
2393     {
2394         OSL_ENSURE( sal_False, "OBoundControlModel::onConnectedValidator: caught an exception!" );
2395     }
2396     recheckValidity( false );
2397 }
2398 
2399 //------------------------------------------------------------------------------
onDisconnectedValidator()2400 void OBoundControlModel::onDisconnectedValidator( )
2401 {
2402     try
2403     {
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_True ) );
2409     }
2410     catch( const Exception& )
2411     {
2412         OSL_ENSURE( sal_False, "OBoundControlModel::onDisconnectedValidator: caught an exception!" );
2413     }
2414     recheckValidity( false );
2415 }
2416 
2417 //------------------------------------------------------------------------------
onConnectedExternalValue()2418 void OBoundControlModel::onConnectedExternalValue( )
2419 {
2420     calculateExternalValueType();
2421 }
2422 
2423 //------------------------------------------------------------------------------
onDisconnectedExternalValue()2424 void OBoundControlModel::onDisconnectedExternalValue( )
2425 {
2426 }
2427 
2428 //------------------------------------------------------------------------------
onConnectedDbColumn(const Reference<XInterface> &)2429 void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
2430 {
2431     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" );
2432 }
2433 
2434 //------------------------------------------------------------------------------
onDisconnectedDbColumn()2435 void OBoundControlModel::onDisconnectedDbColumn()
2436 {
2437     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" );
2438 }
2439 
2440 // XReset
2441 //-----------------------------------------------------------------------------
getDefaultForReset() const2442 Any OBoundControlModel::getDefaultForReset() const
2443 {
2444     return Any();
2445 }
2446 
2447 //-----------------------------------------------------------------------------
resetNoBroadcast()2448 void OBoundControlModel::resetNoBroadcast()
2449 {
2450     setControlValue( getDefaultForReset(), eOther );
2451 }
2452 
2453 //-----------------------------------------------------------------------------
addResetListener(const Reference<XResetListener> & l)2454 void OBoundControlModel::addResetListener(const Reference<XResetListener>& l)
2455 {
2456     m_aResetHelper.addResetListener( l );
2457 }
2458 
2459 //-----------------------------------------------------------------------------
removeResetListener(const Reference<XResetListener> & l)2460 void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l)
2461 {
2462     m_aResetHelper.removeResetListener( l );
2463 }
2464 
2465 //-----------------------------------------------------------------------------
reset()2466 void OBoundControlModel::reset()
2467 {
2468     if ( !m_aResetHelper.approveReset() )
2469        return;
2470 
2471     ControlModelLock aLock( *this );
2472 
2473     // on a new record?
2474     sal_Bool bIsNewRecord = sal_False;
2475     Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY );
2476     if ( xSet.is() )
2477     {
2478         try
2479         {
2480             xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord;
2481         }
2482         catch( const Exception& )
2483         {
2484             DBG_UNHANDLED_EXCEPTION();
2485         }
2486     }
2487 
2488     // cursor on an invalid row?
2489     sal_Bool bInvalidCursorPosition = sal_True;
2490     try
2491     {
2492         bInvalidCursorPosition =    m_xCursor.is()
2493                                 &&  (  m_xCursor->isAfterLast()
2494                                     || m_xCursor->isBeforeFirst()
2495                                     )
2496                                 &&  !bIsNewRecord;
2497     }
2498     catch( const SQLException& )
2499     {
2500         OSL_ENSURE( sal_False, "OBoundControlModel::reset: caught an SQL exception!" );
2501     }
2502     // don't count the insert row as "invalid"
2503     // @since  #i24495#
2504     // @date   2004-05-14
2505     // @author fs@openoffice.org
2506 
2507     sal_Bool bSimpleReset =
2508                         (   !m_xColumn.is()                     // no connection to a database column
2509                         ||  (   m_xCursor.is()                  // OR   we have an improperly positioned cursor
2510                             &&  bInvalidCursorPosition
2511                             )
2512                         ||  hasExternalValueBinding()           // OR we have an external value binding
2513                         );
2514 
2515     if ( !bSimpleReset )
2516     {
2517         // The default values will be set if and only if the current value of the field which we're bound
2518         // to is NULL.
2519         // Else, the current field value should be refreshed
2520         // This behaviour is not completely ... "matured": What should happen if the field as well as the
2521         // control have a default value?
2522 
2523         sal_Bool bIsNull = sal_True;
2524         // we have to access the field content at least once to get a reliable result by XColumn::wasNull
2525         try
2526         {
2527             // normally, we'd do a getString here. However, this is extremely expensive in the case
2528             // of binary fields. Unfortunately, getString is the only method which is guaranteed
2529             // to *always* succeed, all other getXXX methods may fail if the column is asked for a
2530             // non-convertible type
2531             sal_Int32 nFieldType = DataType::OBJECT;
2532             getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
2533             if  (  ( nFieldType == DataType::BINARY        )
2534                 || ( nFieldType == DataType::VARBINARY     )
2535                 || ( nFieldType == DataType::LONGVARBINARY )
2536                 || ( nFieldType == DataType::OBJECT        )
2537                 /*|| ( nFieldType == DataType::CLOB          )*/
2538                 )
2539                 m_xColumn->getBinaryStream();
2540             else if ( nFieldType == DataType::BLOB          )
2541                 m_xColumn->getBlob();
2542             else
2543                 m_xColumn->getString();
2544 
2545             bIsNull = m_xColumn->wasNull();
2546         }
2547         catch(Exception&)
2548         {
2549             DBG_ERROR("OBoundControlModel::reset: this should have succeeded in all cases!");
2550         }
2551 
2552         sal_Bool bNeedValueTransfer = sal_True;
2553 
2554         if ( bIsNull )
2555         {
2556             if ( bIsNewRecord )
2557             {
2558                 // reset the control to it's default
2559                 resetNoBroadcast();
2560                 // and immediately commit the changes to the DB column, to keep consistency
2561                 commitControlValueToDbColumn( sal_True );
2562 
2563                 bNeedValueTransfer = sal_False;
2564             }
2565         }
2566 
2567         if ( bNeedValueTransfer )
2568             transferDbValueToControl();
2569     }
2570     else
2571     {
2572         resetNoBroadcast();
2573 
2574         // transfer to the external binding, if necessary
2575         if ( hasExternalValueBinding() )
2576             transferControlValueToExternal( aLock );
2577     }
2578 
2579     // revalidate, if necessary
2580     if ( hasValidator() )
2581         recheckValidity( true );
2582 
2583     aLock.release();
2584 
2585     m_aResetHelper.notifyResetted();
2586 }
2587 
2588 // -----------------------------------------------------------------------------
impl_setField_noNotify(const Reference<XPropertySet> & _rxField)2589 void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField )
2590 {
2591     DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" );
2592     m_xField = _rxField;
2593 }
2594 
2595 //--------------------------------------------------------------------
impl_approveValueBinding_nolock(const Reference<XValueBinding> & _rxBinding)2596 sal_Bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding )
2597 {
2598     if ( !_rxBinding.is() )
2599         return sal_False;
2600 
2601     Sequence< Type > aTypeCandidates;
2602     {
2603         // SYNCHRONIZED -->
2604         ::osl::MutexGuard aGuard( m_aMutex );
2605         aTypeCandidates = getSupportedBindingTypes();
2606         // <-- SYNCHRONIZED
2607     }
2608 
2609     for (   const Type* pType = aTypeCandidates.getConstArray();
2610             pType != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
2611             ++pType
2612         )
2613     {
2614         if ( _rxBinding->supportsType( *pType ) )
2615             return sal_True;
2616     }
2617 
2618     return sal_False;
2619 }
2620 
2621 //--------------------------------------------------------------------
connectExternalValueBinding(const Reference<XValueBinding> & _rxBinding,ControlModelLock & _rInstanceLock)2622 void OBoundControlModel::connectExternalValueBinding(
2623         const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock )
2624 {
2625     OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" );
2626     OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" );
2627 
2628     // if we're connected to a database column, suspend this
2629     if ( hasField() )
2630         impl_disconnectDatabaseColumn_noNotify();
2631 
2632     // suspend listening for load-related events at out ambient form.
2633     // This is because an external value binding overrules a possible database binding.
2634     if ( isFormListening() )
2635         doFormListening( false );
2636 
2637     // remember this new binding
2638     m_xExternalBinding = _rxBinding;
2639 
2640     // tell the derivee
2641     onConnectedExternalValue();
2642 
2643     try
2644     {
2645         // add as value listener so we get notified when the value changes
2646         Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
2647         if ( xModifiable.is() )
2648             xModifiable->addModifyListener( this );
2649 
2650         // add as property change listener for some (possibly present) properties we're
2651         // interested in
2652         Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
2653         Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() );
2654         if ( xBindingPropsInfo.is() )
2655         {
2656             if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) )
2657             {
2658                 xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this );
2659                 m_bBindingControlsRO = sal_True;
2660             }
2661             if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) )
2662             {
2663                 xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this );
2664                 m_bBindingControlsEnable = sal_True;
2665             }
2666         }
2667     }
2668     catch( const Exception& )
2669     {
2670         DBG_UNHANDLED_EXCEPTION();
2671     }
2672 
2673     // propagate our new value
2674     transferExternalValueToControl( _rInstanceLock );
2675 
2676     // if the binding is also a validator, use it, too. This is a constraint of the
2677     // com.sun.star.form.binding.ValidatableBindableFormComponent service
2678     if ( m_bSupportsValidation )
2679     {
2680         try
2681         {
2682             Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY );
2683             if ( xAsValidator.is() )
2684                 setValidator( xAsValidator );
2685         }
2686         catch( const Exception& )
2687         {
2688             DBG_UNHANDLED_EXCEPTION();
2689         }
2690     }
2691 }
2692 
2693 //--------------------------------------------------------------------
disconnectExternalValueBinding()2694 void OBoundControlModel::disconnectExternalValueBinding( )
2695 {
2696     try
2697     {
2698         // not listening at the binding anymore
2699         Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
2700         if ( xModifiable.is() )
2701             xModifiable->removeModifyListener( this );
2702 
2703         // remove as property change listener
2704         Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
2705         if ( m_bBindingControlsRO )
2706             xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this );
2707         if ( m_bBindingControlsEnable )
2708             xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this );
2709     }
2710     catch( const Exception& )
2711     {
2712         OSL_ENSURE( sal_False, "OBoundControlModel::disconnectExternalValueBinding: caught an exception!" );
2713     }
2714 
2715     // if the binding also acts as our validator, disconnect the validator, too
2716     if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() )
2717         disconnectValidator( );
2718 
2719     // no binding anymore
2720     m_xExternalBinding.clear();
2721 
2722     // be a load listener at our form, again. This was suspended while we had
2723     // an external value binding in place.
2724     doFormListening( true );
2725 
2726     // re-connect to database column of the new parent
2727     if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
2728         impl_connectDatabaseColumn_noNotify( false );
2729 
2730     // tell the derivee
2731     onDisconnectedExternalValue();
2732 }
2733 
2734 //--------------------------------------------------------------------
setValueBinding(const Reference<XValueBinding> & _rxBinding)2735 void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding )
2736 {
2737     OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" );
2738         // the interface for this method should not have been exposed if we do not
2739         // support binding to external data
2740 
2741     if ( !impl_approveValueBinding_nolock( _rxBinding ) )
2742     {
2743         throw IncompatibleTypesException(
2744             FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ),
2745             *this
2746         );
2747     }
2748 
2749     ControlModelLock aLock( *this );
2750 
2751     // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding
2752     // might trigger a change in our BoundField.
2753     FieldChangeNotifier aBoundFieldNotifier( aLock );
2754 
2755     // disconnect from the old binding
2756     if ( hasExternalValueBinding() )
2757         disconnectExternalValueBinding( );
2758 
2759     // connect to the new binding
2760     if ( _rxBinding.is() )
2761         connectExternalValueBinding( _rxBinding, aLock );
2762 }
2763 
2764 //--------------------------------------------------------------------
getValueBinding()2765 Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding(  )
2766 {
2767     ::osl::MutexGuard aGuard( m_aMutex );
2768     OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" );
2769         // the interface for this method should not have been exposed if we do not
2770         // support binding to external data
2771 
2772     return m_xExternalBinding;
2773 }
2774 
2775 //--------------------------------------------------------------------
modified(const EventObject & _rEvent)2776 void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent )
2777 {
2778     ControlModelLock aLock( *this );
2779 
2780     OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" );
2781     if ( !m_bTransferingValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() )
2782     {
2783         transferExternalValueToControl( aLock );
2784     }
2785 }
2786 
2787 //--------------------------------------------------------------------
transferDbValueToControl()2788 void OBoundControlModel::transferDbValueToControl( )
2789 {
2790     try
2791     {
2792         setControlValue( translateDbColumnToControlValue(), eDbColumnBinding );
2793     }
2794     catch( const Exception& )
2795     {
2796         DBG_UNHANDLED_EXCEPTION();
2797     }
2798 }
2799 
2800 //------------------------------------------------------------------------------
transferExternalValueToControl(ControlModelLock & _rInstanceLock)2801 void OBoundControlModel::transferExternalValueToControl( ControlModelLock& _rInstanceLock )
2802 {
2803         Reference< XValueBinding > xExternalBinding( m_xExternalBinding );
2804         Type aValueExchangeType( getExternalValueType() );
2805 
2806         _rInstanceLock.release();
2807         // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2808         Any aExternalValue;
2809         try
2810         {
2811             aExternalValue = xExternalBinding->getValue( aValueExchangeType );
2812         }
2813         catch( const Exception& )
2814         {
2815             DBG_UNHANDLED_EXCEPTION();
2816         }
2817         // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2818         _rInstanceLock.acquire();
2819 
2820         setControlValue( translateExternalValueToControlValue( aExternalValue ), eExternalBinding );
2821 }
2822 
2823 //------------------------------------------------------------------------------
transferControlValueToExternal(ControlModelLock & _rInstanceLock)2824 void OBoundControlModel::transferControlValueToExternal( ControlModelLock& _rInstanceLock )
2825 {
2826     OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
2827         "OBoundControlModel::transferControlValueToExternal: precondition not met!" );
2828 
2829     if ( m_xExternalBinding.is() )
2830     {
2831         Any aExternalValue( translateControlValueToExternalValue() );
2832         m_bTransferingValue = sal_True;
2833 
2834         _rInstanceLock.release();
2835          // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2836         try
2837         {
2838             m_xExternalBinding->setValue( aExternalValue );
2839         }
2840         catch( const Exception& )
2841         {
2842             DBG_UNHANDLED_EXCEPTION();
2843         }
2844         // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2845         _rInstanceLock.acquire();
2846 
2847         m_bTransferingValue = sal_False;
2848     }
2849 }
2850 
2851 // -----------------------------------------------------------------------------
getSupportedBindingTypes()2852 Sequence< Type > OBoundControlModel::getSupportedBindingTypes()
2853 {
2854     return Sequence< Type >( &m_aValuePropertyType, 1 );
2855 }
2856 
2857 //-----------------------------------------------------------------------------
calculateExternalValueType()2858 void OBoundControlModel::calculateExternalValueType()
2859 {
2860     m_aExternalValueType = Type();
2861     if ( !m_xExternalBinding.is() )
2862         return;
2863 
2864     Sequence< Type > aTypeCandidates( getSupportedBindingTypes() );
2865     for (   const Type* pTypeCandidate = aTypeCandidates.getConstArray();
2866             pTypeCandidate != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
2867             ++pTypeCandidate
2868         )
2869     {
2870         if ( m_xExternalBinding->supportsType( *pTypeCandidate ) )
2871         {
2872             m_aExternalValueType = *pTypeCandidate;
2873             break;
2874         }
2875     }
2876 }
2877 
2878 //-----------------------------------------------------------------------------
translateExternalValueToControlValue(const Any & _rExternalValue) const2879 Any OBoundControlModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
2880 {
2881     OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
2882         "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" );
2883 
2884     Any aControlValue( _rExternalValue );
2885 
2886     // if the external value is VOID, and our value property is not allowed to be VOID,
2887     // then default-construct a value
2888     if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid )
2889         aControlValue.setValue( NULL, m_aValuePropertyType );
2890 
2891     // outta here
2892     return aControlValue;
2893 }
2894 
2895 //------------------------------------------------------------------------------
translateControlValueToExternalValue() const2896 Any OBoundControlModel::translateControlValueToExternalValue( ) const
2897 {
2898     return getControlValue( );
2899 }
2900 
2901 //------------------------------------------------------------------------------
translateControlValueToValidatableValue() const2902 Any OBoundControlModel::translateControlValueToValidatableValue( ) const
2903 {
2904     OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" );
2905     if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() )
2906         return translateControlValueToExternalValue();
2907     return getControlValue();
2908 }
2909 
2910 //------------------------------------------------------------------------------
getControlValue() const2911 Any OBoundControlModel::getControlValue( ) const
2912 {
2913     OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
2914         "OBoundControlModel::getControlValue: invalid aggregate !" );
2915     OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ),
2916         "OBoundControlModel::getControlValue: please override if you have own value property handling!" );
2917 
2918     // determine the current control value
2919     Any aControlValue;
2920     if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
2921     {
2922         aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle );
2923     }
2924     else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() )
2925     {
2926         aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName );
2927     }
2928 
2929     return aControlValue;
2930 }
2931 
2932 //--------------------------------------------------------------------
connectValidator(const Reference<XValidator> & _rxValidator)2933 void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator )
2934 {
2935     OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" );
2936     OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" );
2937 
2938     m_xValidator = _rxValidator;
2939 
2940     // add as value listener so we get notified when the value changes
2941     if ( m_xValidator.is() )
2942     {
2943         try
2944         {
2945             m_xValidator->addValidityConstraintListener( this );
2946         }
2947         catch( const RuntimeException& )
2948         {
2949         }
2950     }
2951 
2952     onConnectedValidator( );
2953 }
2954 
2955 //--------------------------------------------------------------------
disconnectValidator()2956 void OBoundControlModel::disconnectValidator( )
2957 {
2958     OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" );
2959 
2960     // add as value listener so we get notified when the value changes
2961     if ( m_xValidator.is() )
2962     {
2963         try
2964         {
2965             m_xValidator->removeValidityConstraintListener( this );
2966         }
2967         catch( const RuntimeException& )
2968         {
2969         }
2970     }
2971 
2972     m_xValidator.clear();
2973 
2974     onDisconnectedValidator( );
2975 }
2976 
2977 //--------------------------------------------------------------------
setValidator(const Reference<XValidator> & _rxValidator)2978 void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator )
2979 {
2980     ::osl::ClearableMutexGuard aGuard( m_aMutex );
2981     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" );
2982         // the interface for this method should not have been exposed if we do not
2983         // support validation
2984 
2985     // early out if the validator does not change
2986     if( _rxValidator == m_xValidator )
2987         return;
2988 
2989     if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) )
2990         throw VetoException(
2991             FRM_RES_STRING( RID_STR_INVALID_VALIDATOR ),
2992             *this
2993         );
2994 
2995     // disconnect from the old validator
2996     if ( hasValidator() )
2997         disconnectValidator( );
2998 
2999     // connect to the new validator
3000     if ( _rxValidator.is() )
3001         connectValidator( _rxValidator );
3002 }
3003 
3004 //--------------------------------------------------------------------
getValidator()3005 Reference< XValidator > SAL_CALL OBoundControlModel::getValidator(  )
3006 {
3007     ::osl::MutexGuard aGuard( m_aMutex );
3008     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" );
3009         // the interface for this method should not have been exposed if we do not
3010         // support validation
3011 
3012     return m_xValidator;
3013 }
3014 
3015 //--------------------------------------------------------------------
validityConstraintChanged(const EventObject &)3016 void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& /*Source*/ )
3017 {
3018     ::osl::ClearableMutexGuard aGuard( m_aMutex );
3019     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" );
3020         // the interface for this method should not have been exposed if we do not
3021         // support validation
3022 
3023     recheckValidity( false );
3024 }
3025 
3026 //--------------------------------------------------------------------
isValid()3027 sal_Bool SAL_CALL OBoundControlModel::isValid(  )
3028 {
3029     return m_bIsCurrentValueValid;
3030 }
3031 
3032 //--------------------------------------------------------------------
getCurrentFormComponentValue() const3033 ::com::sun::star::uno::Any OBoundControlModel::getCurrentFormComponentValue() const
3034 {
3035     if ( hasValidator() )
3036         return translateControlValueToValidatableValue();
3037     return getControlValue();
3038 }
3039 
3040 //--------------------------------------------------------------------
getCurrentValue()3041 Any SAL_CALL OBoundControlModel::getCurrentValue(  )
3042 {
3043     ::osl::MutexGuard aGuard( m_aMutex );
3044     return getCurrentFormComponentValue();
3045 }
3046 
3047 //--------------------------------------------------------------------
addFormComponentValidityListener(const Reference<validation::XFormComponentValidityListener> & Listener)3048 void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener )
3049 {
3050     if ( Listener.is() )
3051         m_aFormComponentListeners.addInterface( Listener );
3052 }
3053 
3054 //--------------------------------------------------------------------
removeFormComponentValidityListener(const Reference<validation::XFormComponentValidityListener> & Listener)3055 void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener )
3056 {
3057     if ( Listener.is() )
3058         m_aFormComponentListeners.removeInterface( Listener );
3059 }
3060 
3061 //--------------------------------------------------------------------
recheckValidity(bool _bForceNotification)3062 void OBoundControlModel::recheckValidity( bool _bForceNotification )
3063 {
3064     try
3065     {
3066         sal_Bool bIsCurrentlyValid = sal_True;
3067         if ( hasValidator() )
3068             bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() );
3069 
3070         if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification )
3071         {
3072             m_bIsCurrentValueValid = bIsCurrentlyValid;
3073 
3074             // release our mutex for the notifications
3075             MutexRelease aRelease( m_aMutex );
3076             m_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) );
3077         }
3078     }
3079     catch( const Exception& )
3080     {
3081         OSL_ENSURE( sal_False, "OBoundControlModel::recheckValidity: caught an exception!" );
3082     }
3083 }
3084 
3085 //------------------------------------------------------------------------------
describeFixedProperties(Sequence<Property> & _rProps) const3086 void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
3087 {
3088     BEGIN_DESCRIBE_PROPERTIES( 5, OControlModel )
3089         DECL_PROP1      ( CONTROLSOURCE,           ::rtl::OUString,     BOUND );
3090         DECL_IFACE_PROP3( BOUNDFIELD,               XPropertySet,       BOUND, READONLY, TRANSIENT );
3091         DECL_IFACE_PROP2( CONTROLLABEL,             XPropertySet,       BOUND, MAYBEVOID );
3092         DECL_PROP2      ( CONTROLSOURCEPROPERTY,    ::rtl::OUString,    READONLY, TRANSIENT );
3093         DECL_BOOL_PROP1 ( INPUT_REQUIRED,                               BOUND );
3094     END_DESCRIBE_PROPERTIES()
3095 }
3096 
3097 // -----------------------------------------------------------------------------
3098 
3099 //.........................................................................
3100 }
3101 //... namespace frm .......................................................
3102