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