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