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