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