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