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