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 : : #include "eformshelper.hxx"
30 : : #include "formstrings.hxx"
31 : : #include "formresid.hrc"
32 : : #include "modulepcr.hxx"
33 : : #include "propeventtranslation.hxx"
34 : : #include "formbrowsertools.hxx"
35 : :
36 : : #include <com/sun/star/lang/XServiceInfo.hpp>
37 : : #include <com/sun/star/form/FormComponentType.hpp>
38 : : #include <com/sun/star/xforms/XFormsUIHelper1.hpp>
39 : : #include <com/sun/star/xsd/DataTypeClass.hpp>
40 : : #include <com/sun/star/form/binding/XListEntrySink.hpp>
41 : : #include <tools/diagnose_ex.h>
42 : : #include <rtl/ustrbuf.hxx>
43 : :
44 : : #include <functional>
45 : : #include <algorithm>
46 : : #include <o3tl/compat_functional.hxx>
47 : :
48 : : //........................................................................
49 : : namespace pcr
50 : : {
51 : : //........................................................................
52 : :
53 : : using namespace ::com::sun::star;
54 : : using namespace ::com::sun::star::uno;
55 : : using namespace ::com::sun::star::beans;
56 : : using namespace ::com::sun::star::container;
57 : : using namespace ::com::sun::star::form::binding;
58 : : using namespace ::com::sun::star::xsd;
59 : : using namespace ::com::sun::star::lang;
60 : : using namespace ::com::sun::star::form;
61 : :
62 : : //====================================================================
63 : : //= file-local helpers
64 : : //====================================================================
65 : : namespace
66 : : {
67 : : //--------------------------------------------------------------------
68 : 0 : ::rtl::OUString composeModelElementUIName( const ::rtl::OUString& _rModelName, const ::rtl::OUString& _rElementName )
69 : : {
70 : 0 : ::rtl::OUStringBuffer aBuffer;
71 : 0 : aBuffer.appendAscii( "[" );
72 : 0 : aBuffer.append( _rModelName );
73 : 0 : aBuffer.appendAscii( "] " );
74 : 0 : aBuffer.append( _rElementName );
75 : 0 : return aBuffer.makeStringAndClear();
76 : : }
77 : : }
78 : :
79 : : //====================================================================
80 : : //= EFormsHelper
81 : : //====================================================================
82 : : //--------------------------------------------------------------------
83 : 0 : EFormsHelper::EFormsHelper( ::osl::Mutex& _rMutex, const Reference< XPropertySet >& _rxControlModel, const Reference< frame::XModel >& _rxContextDocument )
84 : : :m_xControlModel( _rxControlModel )
85 : 0 : ,m_aPropertyListeners( _rMutex )
86 : : {
87 : : OSL_ENSURE( _rxControlModel.is(), "EFormsHelper::EFormsHelper: invalid control model!" );
88 : 0 : m_xBindableControl = m_xBindableControl.query( _rxControlModel );
89 : :
90 : 0 : m_xDocument = m_xDocument.query( _rxContextDocument );
91 : : OSL_ENSURE( m_xDocument.is(), "EFormsHelper::EFormsHelper: invalid document!" );
92 : :
93 : 0 : }
94 : :
95 : : //--------------------------------------------------------------------
96 : 0 : bool EFormsHelper::isEForm( const Reference< frame::XModel >& _rxContextDocument )
97 : : {
98 : : try
99 : : {
100 : 0 : Reference< xforms::XFormsSupplier > xDocument( _rxContextDocument, UNO_QUERY );
101 : 0 : if ( !xDocument.is() )
102 : 0 : return false;
103 : :
104 : 0 : return xDocument->getXForms().is();
105 : : }
106 : 0 : catch( const Exception& )
107 : : {
108 : : OSL_FAIL( "EFormsHelper::isEForm: caught an exception!" );
109 : : }
110 : 0 : return false;
111 : : }
112 : :
113 : : //--------------------------------------------------------------------
114 : 0 : bool EFormsHelper::canBindToDataType( sal_Int32 _nDataType ) const SAL_THROW(())
115 : : {
116 : 0 : if ( !m_xBindableControl.is() )
117 : : // cannot bind at all
118 : 0 : return false;
119 : :
120 : : // some types cannot be bound, independent from the control type
121 : 0 : if ( ( DataTypeClass::hexBinary == _nDataType )
122 : : || ( DataTypeClass::base64Binary == _nDataType )
123 : : || ( DataTypeClass::QName == _nDataType )
124 : : || ( DataTypeClass::NOTATION == _nDataType )
125 : : )
126 : 0 : return false;
127 : :
128 : 0 : bool bCan = false;
129 : : try
130 : : {
131 : : // classify the control model
132 : 0 : sal_Int16 nControlType = FormComponentType::CONTROL;
133 : 0 : OSL_VERIFY( m_xControlModel->getPropertyValue( PROPERTY_CLASSID ) >>= nControlType );
134 : :
135 : : // some lists
136 : 0 : sal_Int16 nNumericCompatibleTypes[] = { DataTypeClass::DECIMAL, DataTypeClass::FLOAT, DataTypeClass::DOUBLE, 0 };
137 : 0 : sal_Int16 nDateCompatibleTypes[] = { DataTypeClass::DATE, 0 };
138 : 0 : sal_Int16 nTimeCompatibleTypes[] = { DataTypeClass::TIME, 0 };
139 : 0 : sal_Int16 nCheckboxCompatibleTypes[] = { DataTypeClass::BOOLEAN, DataTypeClass::STRING, DataTypeClass::anyURI, 0 };
140 : 0 : sal_Int16 nRadiobuttonCompatibleTypes[] = { DataTypeClass::STRING, DataTypeClass::anyURI, 0 };
141 : 0 : sal_Int16 nFormattedCompatibleTypes[] = { DataTypeClass::DECIMAL, DataTypeClass::FLOAT, DataTypeClass::DOUBLE, DataTypeClass::DATETIME, DataTypeClass::DATE, DataTypeClass::TIME, 0 };
142 : :
143 : 0 : sal_Int16* pCompatibleTypes = NULL;
144 : 0 : switch ( nControlType )
145 : : {
146 : : case FormComponentType::SPINBUTTON:
147 : : case FormComponentType::NUMERICFIELD:
148 : 0 : pCompatibleTypes = nNumericCompatibleTypes;
149 : 0 : break;
150 : : case FormComponentType::DATEFIELD:
151 : 0 : pCompatibleTypes = nDateCompatibleTypes;
152 : 0 : break;
153 : : case FormComponentType::TIMEFIELD:
154 : 0 : pCompatibleTypes = nTimeCompatibleTypes;
155 : 0 : break;
156 : : case FormComponentType::CHECKBOX:
157 : 0 : pCompatibleTypes = nCheckboxCompatibleTypes;
158 : 0 : break;
159 : : case FormComponentType::RADIOBUTTON:
160 : 0 : pCompatibleTypes = nRadiobuttonCompatibleTypes;
161 : 0 : break;
162 : :
163 : : case FormComponentType::TEXTFIELD:
164 : : {
165 : : // both the normal text field, and the formatted field, claim to be a TEXTFIELD
166 : : // need to distinguish by service name
167 : 0 : Reference< XServiceInfo > xSI( m_xControlModel, UNO_QUERY );
168 : : OSL_ENSURE( xSI.is(), "EFormsHelper::canBindToDataType: a control model which has no service info?" );
169 : 0 : if ( xSI.is() )
170 : : {
171 : 0 : if ( xSI->supportsService( SERVICE_COMPONENT_FORMATTEDFIELD ) )
172 : : {
173 : 0 : pCompatibleTypes = nFormattedCompatibleTypes;
174 : : break;
175 : : }
176 : 0 : }
177 : : // NO break here!
178 : : }
179 : : case FormComponentType::LISTBOX:
180 : : case FormComponentType::COMBOBOX:
181 : : // edit fields and list/combo boxes can be bound to anything
182 : 0 : bCan = true;
183 : : }
184 : :
185 : 0 : if ( !bCan && pCompatibleTypes )
186 : : {
187 : 0 : if ( _nDataType == -1 )
188 : : {
189 : : // the control can be bound to at least one type, and exactly this is being asked for
190 : 0 : bCan = true;
191 : : }
192 : : else
193 : : {
194 : 0 : while ( *pCompatibleTypes && !bCan )
195 : 0 : bCan = ( *pCompatibleTypes++ == _nDataType );
196 : : }
197 : : }
198 : : }
199 : 0 : catch( const Exception& )
200 : : {
201 : : OSL_FAIL( "EFormsHelper::canBindToDataType: caught an exception!" );
202 : : }
203 : :
204 : 0 : return bCan;
205 : : }
206 : :
207 : : //--------------------------------------------------------------------
208 : 0 : bool EFormsHelper::isListEntrySink() const SAL_THROW(())
209 : : {
210 : 0 : bool bIs = false;
211 : : try
212 : : {
213 : 0 : Reference< XListEntrySink > xAsSink( m_xControlModel, UNO_QUERY );
214 : 0 : bIs = xAsSink.is();
215 : : }
216 : 0 : catch( const Exception& )
217 : : {
218 : : OSL_FAIL( "EFormsHelper::isListEntrySink: caught an exception!" );
219 : : }
220 : 0 : return bIs;
221 : : }
222 : :
223 : : //--------------------------------------------------------------------
224 : 0 : void EFormsHelper::impl_switchBindingListening_throw( bool _bDoListening, const Reference< XPropertyChangeListener >& _rxListener )
225 : : {
226 : 0 : Reference< XPropertySet > xBindingProps;
227 : 0 : if ( m_xBindableControl.is() )
228 : 0 : xBindingProps = xBindingProps.query( m_xBindableControl->getValueBinding() );
229 : 0 : if ( !xBindingProps.is() )
230 : 0 : return;
231 : :
232 : 0 : if ( _bDoListening )
233 : : {
234 : 0 : xBindingProps->addPropertyChangeListener( ::rtl::OUString(), _rxListener );
235 : : }
236 : : else
237 : : {
238 : 0 : xBindingProps->removePropertyChangeListener( ::rtl::OUString(), _rxListener );
239 : 0 : }
240 : : }
241 : :
242 : : //--------------------------------------------------------------------
243 : 0 : void EFormsHelper::registerBindingListener( const Reference< XPropertyChangeListener >& _rxBindingListener )
244 : : {
245 : 0 : if ( !_rxBindingListener.is() )
246 : 0 : return;
247 : 0 : impl_toggleBindingPropertyListening_throw( true, _rxBindingListener );
248 : : }
249 : :
250 : : //--------------------------------------------------------------------
251 : 0 : void EFormsHelper::impl_toggleBindingPropertyListening_throw( bool _bDoListen, const Reference< XPropertyChangeListener >& _rxConcreteListenerOrNull )
252 : : {
253 : 0 : if ( !_bDoListen )
254 : : {
255 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
256 : 0 : ::std::auto_ptr< ::cppu::OInterfaceIteratorHelper > pListenerIterator = m_aPropertyListeners.createIterator();
257 : : SAL_WNODEPRECATED_DECLARATIONS_POP
258 : 0 : while ( pListenerIterator->hasMoreElements() )
259 : : {
260 : 0 : PropertyEventTranslation* pTranslator = dynamic_cast< PropertyEventTranslation* >( pListenerIterator->next() );
261 : : OSL_ENSURE( pTranslator, "EFormsHelper::impl_toggleBindingPropertyListening_throw: invalid listener element in my container!" );
262 : 0 : if ( !pTranslator )
263 : 0 : continue;
264 : :
265 : 0 : Reference< XPropertyChangeListener > xEventSourceTranslator( pTranslator );
266 : 0 : if ( _rxConcreteListenerOrNull.is() )
267 : : {
268 : 0 : if ( pTranslator->getDelegator() == _rxConcreteListenerOrNull )
269 : : {
270 : 0 : impl_switchBindingListening_throw( false, xEventSourceTranslator );
271 : 0 : m_aPropertyListeners.removeListener( xEventSourceTranslator );
272 : : break;
273 : : }
274 : : }
275 : : else
276 : : {
277 : 0 : impl_switchBindingListening_throw( false, xEventSourceTranslator );
278 : : }
279 : 0 : }
280 : : }
281 : : else
282 : : {
283 : 0 : if ( _rxConcreteListenerOrNull.is() )
284 : : {
285 : 0 : Reference< XPropertyChangeListener > xEventSourceTranslator( new PropertyEventTranslation( _rxConcreteListenerOrNull, m_xBindableControl ) );
286 : 0 : m_aPropertyListeners.addListener( xEventSourceTranslator );
287 : 0 : impl_switchBindingListening_throw( true, xEventSourceTranslator );
288 : : }
289 : : else
290 : : {
291 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
292 : 0 : ::std::auto_ptr< ::cppu::OInterfaceIteratorHelper > pListenerIterator = m_aPropertyListeners.createIterator();
293 : : SAL_WNODEPRECATED_DECLARATIONS_POP
294 : 0 : while ( pListenerIterator->hasMoreElements() )
295 : : {
296 : 0 : Reference< XPropertyChangeListener > xListener( pListenerIterator->next(), UNO_QUERY );
297 : 0 : impl_switchBindingListening_throw( true, xListener );
298 : 0 : }
299 : : }
300 : : }
301 : 0 : }
302 : :
303 : : //--------------------------------------------------------------------
304 : 0 : void EFormsHelper::revokeBindingListener( const Reference< XPropertyChangeListener >& _rxBindingListener )
305 : : {
306 : 0 : impl_toggleBindingPropertyListening_throw( false, _rxBindingListener );
307 : 0 : }
308 : :
309 : : //--------------------------------------------------------------------
310 : 0 : void EFormsHelper::getFormModelNames( ::std::vector< ::rtl::OUString >& /* [out] */ _rModelNames ) const SAL_THROW(())
311 : : {
312 : 0 : if ( m_xDocument.is() )
313 : : {
314 : : try
315 : : {
316 : 0 : _rModelNames.resize( 0 );
317 : :
318 : 0 : Reference< XNameContainer > xForms( m_xDocument->getXForms() );
319 : : OSL_ENSURE( xForms.is(), "EFormsHelper::getFormModelNames: invalid forms container!" );
320 : 0 : if ( xForms.is() )
321 : : {
322 : 0 : Sequence< ::rtl::OUString > aModelNames = xForms->getElementNames();
323 : 0 : _rModelNames.resize( aModelNames.getLength() );
324 : 0 : ::std::copy( aModelNames.getConstArray(), aModelNames.getConstArray() + aModelNames.getLength(),
325 : : _rModelNames.begin()
326 : 0 : );
327 : 0 : }
328 : : }
329 : 0 : catch( const Exception& )
330 : : {
331 : : OSL_FAIL( "EFormsHelper::getFormModelNames: caught an exception!" );
332 : : }
333 : : }
334 : 0 : }
335 : :
336 : : //--------------------------------------------------------------------
337 : 0 : void EFormsHelper::getBindingNames( const ::rtl::OUString& _rModelName, ::std::vector< ::rtl::OUString >& /* [out] */ _rBindingNames ) const SAL_THROW(())
338 : : {
339 : 0 : _rBindingNames.resize( 0 );
340 : : try
341 : : {
342 : 0 : Reference< xforms::XModel > xModel( getFormModelByName( _rModelName ) );
343 : 0 : if ( xModel.is() )
344 : : {
345 : 0 : Reference< XNameAccess > xBindings( xModel->getBindings(), UNO_QUERY );
346 : : OSL_ENSURE( xBindings.is(), "EFormsHelper::getBindingNames: invalid bindings container obtained from the model!" );
347 : 0 : if ( xBindings.is() )
348 : : {
349 : 0 : Sequence< ::rtl::OUString > aNames = xBindings->getElementNames();
350 : 0 : _rBindingNames.resize( aNames.getLength() );
351 : 0 : ::std::copy( aNames.getConstArray(), aNames.getConstArray() + aNames.getLength(), _rBindingNames.begin() );
352 : 0 : }
353 : 0 : }
354 : : }
355 : 0 : catch( const Exception& )
356 : : {
357 : : OSL_FAIL( "EFormsHelper::getBindingNames: caught an exception!" );
358 : : }
359 : 0 : }
360 : :
361 : : //--------------------------------------------------------------------
362 : 0 : Reference< xforms::XModel > EFormsHelper::getFormModelByName( const ::rtl::OUString& _rModelName ) const SAL_THROW(())
363 : : {
364 : 0 : Reference< xforms::XModel > xReturn;
365 : : try
366 : : {
367 : 0 : Reference< XNameContainer > xForms( m_xDocument->getXForms() );
368 : : OSL_ENSURE( xForms.is(), "EFormsHelper::getFormModelByName: invalid forms container!" );
369 : 0 : if ( xForms.is() )
370 : 0 : OSL_VERIFY( xForms->getByName( _rModelName ) >>= xReturn );
371 : : }
372 : 0 : catch( const Exception& )
373 : : {
374 : : OSL_FAIL( "EFormsHelper::getFormModelByName: caught an exception!" );
375 : : }
376 : 0 : return xReturn;
377 : : }
378 : :
379 : : //--------------------------------------------------------------------
380 : 0 : Reference< xforms::XModel > EFormsHelper::getCurrentFormModel() const SAL_THROW(())
381 : : {
382 : 0 : Reference< xforms::XModel > xModel;
383 : : try
384 : : {
385 : 0 : Reference< XPropertySet > xBinding( getCurrentBinding() );
386 : 0 : if ( xBinding.is() )
387 : : {
388 : 0 : OSL_VERIFY( xBinding->getPropertyValue( PROPERTY_MODEL ) >>= xModel );
389 : 0 : }
390 : : }
391 : 0 : catch( const Exception& )
392 : : {
393 : : OSL_FAIL( "EFormsHelper::getCurrentFormModel: caught an exception!" );
394 : : }
395 : 0 : return xModel;
396 : : }
397 : :
398 : : //--------------------------------------------------------------------
399 : 0 : ::rtl::OUString EFormsHelper::getCurrentFormModelName() const SAL_THROW(())
400 : : {
401 : 0 : ::rtl::OUString sModelName;
402 : : try
403 : : {
404 : 0 : Reference< xforms::XModel > xFormsModel( getCurrentFormModel() );
405 : 0 : if ( xFormsModel.is() )
406 : 0 : sModelName = xFormsModel->getID();
407 : : }
408 : 0 : catch( const Exception& )
409 : : {
410 : : OSL_FAIL( "EFormsHelper::getCurrentFormModel: caught an exception!" );
411 : : }
412 : 0 : return sModelName;
413 : : }
414 : :
415 : : //--------------------------------------------------------------------
416 : 0 : Reference< XPropertySet > EFormsHelper::getCurrentBinding() const SAL_THROW(())
417 : : {
418 : 0 : Reference< XPropertySet > xBinding;
419 : :
420 : : try
421 : : {
422 : 0 : if ( m_xBindableControl.is() )
423 : 0 : xBinding = xBinding.query( m_xBindableControl->getValueBinding() );
424 : : }
425 : 0 : catch( const Exception& )
426 : : {
427 : : OSL_FAIL( "EFormsHelper::getCurrentBinding: caught an exception!" );
428 : : }
429 : :
430 : 0 : return xBinding;
431 : : }
432 : :
433 : : //--------------------------------------------------------------------
434 : 0 : ::rtl::OUString EFormsHelper::getCurrentBindingName() const SAL_THROW(())
435 : : {
436 : 0 : ::rtl::OUString sBindingName;
437 : : try
438 : : {
439 : 0 : Reference< XPropertySet > xBinding( getCurrentBinding() );
440 : 0 : if ( xBinding.is() )
441 : 0 : xBinding->getPropertyValue( PROPERTY_BINDING_ID ) >>= sBindingName;
442 : : }
443 : 0 : catch( const Exception& )
444 : : {
445 : : OSL_FAIL( "EFormsHelper::getCurrentBindingName: caught an exception!" );
446 : : }
447 : 0 : return sBindingName;
448 : : }
449 : :
450 : : //--------------------------------------------------------------------
451 : 0 : Reference< XListEntrySource > EFormsHelper::getCurrentListSourceBinding() const SAL_THROW(())
452 : : {
453 : 0 : Reference< XListEntrySource > xReturn;
454 : : try
455 : : {
456 : 0 : Reference< XListEntrySink > xAsSink( m_xControlModel, UNO_QUERY );
457 : : OSL_ENSURE( xAsSink.is(), "EFormsHelper::getCurrentListSourceBinding: you should have used isListEntrySink before!" );
458 : 0 : if ( xAsSink.is() )
459 : 0 : xReturn = xAsSink->getListEntrySource();
460 : : }
461 : 0 : catch( const Exception& )
462 : : {
463 : : OSL_FAIL( "EFormsHelper::getCurrentListSourceBinding: caught an exception!" );
464 : : }
465 : 0 : return xReturn;
466 : : }
467 : :
468 : : //--------------------------------------------------------------------
469 : 0 : void EFormsHelper::setListSourceBinding( const Reference< XListEntrySource >& _rxListSource ) SAL_THROW(())
470 : : {
471 : : try
472 : : {
473 : 0 : Reference< XListEntrySink > xAsSink( m_xControlModel, UNO_QUERY );
474 : : OSL_ENSURE( xAsSink.is(), "EFormsHelper::setListSourceBinding: you should have used isListEntrySink before!" );
475 : 0 : if ( xAsSink.is() )
476 : 0 : xAsSink->setListEntrySource( _rxListSource );
477 : : }
478 : 0 : catch( const Exception& )
479 : : {
480 : : OSL_FAIL( "EFormsHelper::setListSourceBinding: caught an exception!" );
481 : : }
482 : 0 : }
483 : :
484 : : //--------------------------------------------------------------------
485 : 0 : void EFormsHelper::setBinding( const Reference< ::com::sun::star::beans::XPropertySet >& _rxBinding ) SAL_THROW(())
486 : : {
487 : 0 : if ( !m_xBindableControl.is() )
488 : 0 : return;
489 : :
490 : : try
491 : : {
492 : 0 : Reference< XPropertySet > xOldBinding( m_xBindableControl->getValueBinding(), UNO_QUERY );
493 : :
494 : 0 : Reference< XValueBinding > xBinding( _rxBinding, UNO_QUERY );
495 : : OSL_ENSURE( xBinding.is() || !_rxBinding.is(), "EFormsHelper::setBinding: invalid binding!" );
496 : :
497 : 0 : impl_toggleBindingPropertyListening_throw( false, NULL );
498 : 0 : m_xBindableControl->setValueBinding( xBinding );
499 : 0 : impl_toggleBindingPropertyListening_throw( true, NULL );
500 : :
501 : 0 : ::std::set< ::rtl::OUString > aSet;
502 : 0 : firePropertyChanges( xOldBinding, _rxBinding, aSet );
503 : : }
504 : 0 : catch( const Exception& )
505 : : {
506 : : OSL_FAIL( "EFormsHelper::setBinding: caught an exception!" );
507 : : }
508 : : }
509 : :
510 : : //--------------------------------------------------------------------
511 : 0 : Reference< XPropertySet > EFormsHelper::getOrCreateBindingForModel( const ::rtl::OUString& _rTargetModel, const ::rtl::OUString& _rBindingName ) const SAL_THROW(())
512 : : {
513 : : OSL_ENSURE( !_rBindingName.isEmpty(), "EFormsHelper::getOrCreateBindingForModel: invalid binding name!" );
514 : 0 : return implGetOrCreateBinding( _rTargetModel, _rBindingName );
515 : : }
516 : :
517 : : //--------------------------------------------------------------------
518 : 0 : Reference< XPropertySet > EFormsHelper::implGetOrCreateBinding( const ::rtl::OUString& _rTargetModel, const ::rtl::OUString& _rBindingName ) const SAL_THROW(())
519 : : {
520 : : OSL_ENSURE( !( _rTargetModel.isEmpty() && !_rBindingName.isEmpty() ), "EFormsHelper::implGetOrCreateBinding: no model, but a binding name?" );
521 : :
522 : 0 : Reference< XPropertySet > xBinding;
523 : : try
524 : : {
525 : 0 : ::rtl::OUString sTargetModel( _rTargetModel );
526 : : // determine the model which the binding should belong to
527 : 0 : if ( sTargetModel.isEmpty() )
528 : : {
529 : 0 : ::std::vector< ::rtl::OUString > aModelNames;
530 : 0 : getFormModelNames( aModelNames );
531 : 0 : if ( !aModelNames.empty() )
532 : 0 : sTargetModel = *aModelNames.begin();
533 : 0 : OSL_ENSURE( !sTargetModel.isEmpty(), "EFormsHelper::implGetOrCreateBinding: unable to obtain a default model!" );
534 : : }
535 : 0 : Reference< xforms::XModel > xModel( getFormModelByName( sTargetModel ) );
536 : 0 : Reference< XNameAccess > xBindingNames( xModel.is() ? xModel->getBindings() : Reference< XSet >(), UNO_QUERY );
537 : 0 : if ( xBindingNames.is() )
538 : : {
539 : : // get or create the binding instance
540 : 0 : if ( !_rBindingName.isEmpty() )
541 : : {
542 : 0 : if ( xBindingNames->hasByName( _rBindingName ) )
543 : 0 : OSL_VERIFY( xBindingNames->getByName( _rBindingName ) >>= xBinding );
544 : : else
545 : : {
546 : 0 : xBinding = xModel->createBinding( );
547 : 0 : if ( xBinding.is() )
548 : : {
549 : 0 : xBinding->setPropertyValue( PROPERTY_BINDING_ID, makeAny( _rBindingName ) );
550 : 0 : xModel->getBindings()->insert( makeAny( xBinding ) );
551 : : }
552 : : }
553 : : }
554 : : else
555 : : {
556 : 0 : xBinding = xModel->createBinding( );
557 : 0 : if ( xBinding.is() )
558 : : {
559 : : // find a nice name for it
560 : 0 : String sBaseName( PcrRes( RID_STR_BINDING_UI_NAME ) );
561 : 0 : sBaseName += rtl::OUString(" ");
562 : 0 : String sNewName;
563 : 0 : sal_Int32 nNumber = 1;
564 : 0 : do
565 : : {
566 : 0 : sNewName = sBaseName + ::rtl::OUString::valueOf( nNumber++ );
567 : : }
568 : 0 : while ( xBindingNames->hasByName( sNewName ) );
569 : 0 : Reference< XNamed > xName( xBinding, UNO_QUERY_THROW );
570 : 0 : xName->setName( sNewName );
571 : : // and insert into the model
572 : 0 : xModel->getBindings()->insert( makeAny( xBinding ) );
573 : : }
574 : : }
575 : 0 : }
576 : : }
577 : 0 : catch( const Exception& )
578 : : {
579 : : DBG_UNHANDLED_EXCEPTION();
580 : : }
581 : :
582 : 0 : return xBinding;
583 : : }
584 : :
585 : : //--------------------------------------------------------------------
586 : : namespace
587 : : {
588 : : //................................................................
589 : : struct PropertyBagInserter : public ::std::unary_function< Property, void >
590 : : {
591 : : private:
592 : : PropertyBag& m_rProperties;
593 : :
594 : : public:
595 : 0 : PropertyBagInserter( PropertyBag& rProperties ) : m_rProperties( rProperties ) { }
596 : :
597 : 0 : void operator()( const Property& _rProp )
598 : : {
599 : 0 : m_rProperties.insert( _rProp );
600 : 0 : }
601 : : };
602 : :
603 : : //................................................................
604 : 0 : Reference< XPropertySetInfo > collectPropertiesGetInfo( const Reference< XPropertySet >& _rxProps, PropertyBag& _rBag )
605 : : {
606 : 0 : Reference< XPropertySetInfo > xInfo;
607 : 0 : if ( _rxProps.is() )
608 : 0 : xInfo = _rxProps->getPropertySetInfo();
609 : 0 : if ( xInfo.is() )
610 : : {
611 : 0 : Sequence< Property > aProperties = xInfo->getProperties();
612 : 0 : ::std::for_each( aProperties.getConstArray(), aProperties.getConstArray() + aProperties.getLength(),
613 : : PropertyBagInserter( _rBag )
614 : 0 : );
615 : : }
616 : 0 : return xInfo;
617 : : }
618 : : }
619 : :
620 : : //--------------------------------------------------------------------
621 : 0 : ::rtl::OUString EFormsHelper::getModelElementUIName( const EFormsHelper::ModelElementType _eType, const Reference< XPropertySet >& _rxElement ) const SAL_THROW(())
622 : : {
623 : 0 : ::rtl::OUString sUIName;
624 : : try
625 : : {
626 : : // determine the model which the element belongs to
627 : 0 : Reference< xforms::XFormsUIHelper1 > xHelper;
628 : 0 : if ( _rxElement.is() )
629 : 0 : _rxElement->getPropertyValue( PROPERTY_MODEL ) >>= xHelper;
630 : : OSL_ENSURE( xHelper.is(), "EFormsHelper::getModelElementUIName: invalid element or model!" );
631 : 0 : if ( xHelper.is() )
632 : : {
633 : 0 : ::rtl::OUString sElementName = ( _eType == Submission ) ? xHelper->getSubmissionName( _rxElement, sal_True ) : xHelper->getBindingName( _rxElement, sal_True );
634 : 0 : Reference< xforms::XModel > xModel( xHelper, UNO_QUERY_THROW );
635 : 0 : sUIName = composeModelElementUIName( xModel->getID(), sElementName );
636 : 0 : }
637 : : }
638 : 0 : catch( const Exception& )
639 : : {
640 : : OSL_FAIL( "EFormsHelper::getModelElementUIName: caught an exception!" );
641 : : }
642 : :
643 : 0 : return sUIName;
644 : : }
645 : :
646 : : //--------------------------------------------------------------------
647 : 0 : Reference< XPropertySet > EFormsHelper::getModelElementFromUIName( const EFormsHelper::ModelElementType _eType, const ::rtl::OUString& _rUIName ) const SAL_THROW(())
648 : : {
649 : 0 : const MapStringToPropertySet& rMapUINameToElement( ( _eType == Submission ) ? m_aSubmissionUINames : m_aBindingUINames );
650 : 0 : MapStringToPropertySet::const_iterator pos = rMapUINameToElement.find( _rUIName );
651 : : OSL_ENSURE( pos != rMapUINameToElement.end(), "EFormsHelper::getModelElementFromUIName: didn't find it!" );
652 : :
653 : 0 : return ( pos != rMapUINameToElement.end() ) ? pos->second : Reference< XPropertySet >();
654 : : }
655 : :
656 : : //--------------------------------------------------------------------
657 : 0 : void EFormsHelper::getAllElementUINames( const ModelElementType _eType, ::std::vector< ::rtl::OUString >& /* [out] */ _rElementNames, bool _bPrepentEmptyEntry )
658 : : {
659 : 0 : MapStringToPropertySet& rMapUINameToElement( ( _eType == Submission ) ? m_aSubmissionUINames : m_aBindingUINames );
660 : 0 : rMapUINameToElement.clear();
661 : 0 : _rElementNames.resize( 0 );
662 : :
663 : 0 : if ( _bPrepentEmptyEntry )
664 : 0 : rMapUINameToElement[ ::rtl::OUString() ] = Reference< XPropertySet >();
665 : :
666 : : try
667 : : {
668 : : // obtain the model names
669 : 0 : ::std::vector< ::rtl::OUString > aModels;
670 : 0 : getFormModelNames( aModels );
671 : 0 : _rElementNames.reserve( aModels.size() * 2 ); // heuristics
672 : :
673 : : // for every model, obtain the element
674 : 0 : for ( ::std::vector< ::rtl::OUString >::const_iterator pModelName = aModels.begin();
675 : 0 : pModelName != aModels.end();
676 : : ++pModelName
677 : : )
678 : : {
679 : 0 : Reference< xforms::XModel > xModel = getFormModelByName( *pModelName );
680 : : OSL_ENSURE( xModel.is(), "EFormsHelper::getAllElementUINames: inconsistency in the models!" );
681 : 0 : Reference< xforms::XFormsUIHelper1 > xHelper( xModel, UNO_QUERY );
682 : :
683 : 0 : Reference< XIndexAccess > xElements;
684 : 0 : if ( xModel.is() )
685 : 0 : xElements = xElements.query( ( _eType == Submission ) ? xModel->getSubmissions() : xModel->getBindings() );
686 : 0 : if ( !xElements.is() )
687 : : break;
688 : :
689 : 0 : sal_Int32 nElementCount = xElements->getCount();
690 : 0 : for ( sal_Int32 i = 0; i < nElementCount; ++i )
691 : : {
692 : 0 : Reference< XPropertySet > xElement( xElements->getByIndex( i ), UNO_QUERY );
693 : : OSL_ENSURE( xElement.is(), "EFormsHelper::getAllElementUINames: empty element!" );
694 : 0 : if ( !xElement.is() )
695 : 0 : continue;
696 : : #if OSL_DEBUG_LEVEL > 0
697 : : {
698 : : Reference< xforms::XModel > xElementsModel;
699 : : xElement->getPropertyValue( PROPERTY_MODEL ) >>= xElementsModel;
700 : : OSL_ENSURE( xElementsModel == xModel, "EFormsHelper::getAllElementUINames: inconsistency in the model-element relationship!" );
701 : : if ( !( xElementsModel == xModel ) )
702 : : xElement->setPropertyValue( PROPERTY_MODEL, makeAny( xModel ) );
703 : : }
704 : : #endif
705 : 0 : ::rtl::OUString sElementName = ( _eType == Submission ) ? xHelper->getSubmissionName( xElement, sal_True ) : xHelper->getBindingName( xElement, sal_True );
706 : 0 : ::rtl::OUString sUIName = composeModelElementUIName( *pModelName, sElementName );
707 : :
708 : : OSL_ENSURE( rMapUINameToElement.find( sUIName ) == rMapUINameToElement.end(), "EFormsHelper::getAllElementUINames: duplicate name!" );
709 : 0 : rMapUINameToElement.insert( MapStringToPropertySet::value_type( sUIName, xElement ) );
710 : 0 : }
711 : 0 : }
712 : : }
713 : 0 : catch( const Exception& )
714 : : {
715 : : OSL_FAIL( "EFormsHelper::getAllElementUINames: caught an exception!" );
716 : : }
717 : :
718 : 0 : _rElementNames.resize( rMapUINameToElement.size() );
719 : 0 : ::std::transform( rMapUINameToElement.begin(), rMapUINameToElement.end(), _rElementNames.begin(), ::o3tl::select1st< MapStringToPropertySet::value_type >() );
720 : 0 : }
721 : :
722 : : //--------------------------------------------------------------------
723 : 0 : void EFormsHelper::firePropertyChange( const ::rtl::OUString& _rName, const Any& _rOldValue, const Any& _rNewValue ) const
724 : : {
725 : 0 : if ( m_aPropertyListeners.empty() )
726 : 0 : return;
727 : :
728 : 0 : if ( _rOldValue == _rNewValue )
729 : 0 : return;
730 : :
731 : : try
732 : : {
733 : 0 : PropertyChangeEvent aEvent;
734 : :
735 : 0 : aEvent.Source = m_xBindableControl.get();
736 : 0 : aEvent.PropertyName = _rName;
737 : 0 : aEvent.OldValue = _rOldValue;
738 : 0 : aEvent.NewValue = _rNewValue;
739 : :
740 : 0 : const_cast< EFormsHelper* >( this )->m_aPropertyListeners.notify( aEvent, &XPropertyChangeListener::propertyChange );
741 : : }
742 : 0 : catch( const Exception& )
743 : : {
744 : : OSL_FAIL( "EFormsHelper::firePropertyChange: caught an exception!" );
745 : : }
746 : : }
747 : :
748 : : //--------------------------------------------------------------------
749 : 0 : void EFormsHelper::firePropertyChanges( const Reference< XPropertySet >& _rxOldProps, const Reference< XPropertySet >& _rxNewProps, ::std::set< ::rtl::OUString >& _rFilter ) const
750 : : {
751 : 0 : if ( m_aPropertyListeners.empty() )
752 : 0 : return;
753 : :
754 : : try
755 : : {
756 : 0 : PropertyBag aProperties;
757 : 0 : Reference< XPropertySetInfo > xOldInfo = collectPropertiesGetInfo( _rxOldProps, aProperties );
758 : 0 : Reference< XPropertySetInfo > xNewInfo = collectPropertiesGetInfo( _rxNewProps, aProperties );
759 : :
760 : 0 : for ( PropertyBag::const_iterator aProp = aProperties.begin();
761 : 0 : aProp != aProperties.end();
762 : : ++aProp
763 : : )
764 : : {
765 : 0 : if ( _rFilter.find( aProp->Name ) != _rFilter.end() )
766 : 0 : continue;
767 : :
768 : 0 : Any aOldValue( NULL, aProp->Type );
769 : 0 : if ( xOldInfo.is() && xOldInfo->hasPropertyByName( aProp->Name ) )
770 : 0 : aOldValue = _rxOldProps->getPropertyValue( aProp->Name );
771 : :
772 : 0 : Any aNewValue( NULL, aProp->Type );
773 : 0 : if ( xNewInfo.is() && xNewInfo->hasPropertyByName( aProp->Name ) )
774 : 0 : aNewValue = _rxNewProps->getPropertyValue( aProp->Name );
775 : :
776 : 0 : firePropertyChange( aProp->Name, aOldValue, aNewValue );
777 : 0 : }
778 : : }
779 : 0 : catch( const Exception& )
780 : : {
781 : : OSL_FAIL( "EFormsHelper::firePropertyChanges: caught an exception!" );
782 : : }
783 : : }
784 : :
785 : : //........................................................................
786 : : } // namespace pcr
787 : : //........................................................................
788 : :
789 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|