1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_forms.hxx" 30 31 #include "Button.hxx" 32 33 #include <com/sun/star/awt/XVclWindowPeer.hpp> 34 35 #include <comphelper/streamsection.hxx> 36 #include <comphelper/basicio.hxx> 37 #include <tools/diagnose_ex.h> 38 #include <tools/debug.hxx> 39 #include <tools/urlobj.hxx> 40 #include <vcl/svapp.hxx> 41 #include <vos/mutex.hxx> 42 43 //......................................................................... 44 namespace frm 45 { 46 //......................................................................... 47 48 using namespace ::com::sun::star::uno; 49 using namespace ::com::sun::star::sdb; 50 using namespace ::com::sun::star::sdbc; 51 using namespace ::com::sun::star::sdbcx; 52 using namespace ::com::sun::star::beans; 53 using namespace ::com::sun::star::container; 54 using namespace ::com::sun::star::form; 55 using namespace ::com::sun::star::awt; 56 using namespace ::com::sun::star::io; 57 using namespace ::com::sun::star::lang; 58 using namespace ::com::sun::star::util; 59 using ::com::sun::star::frame::XDispatchProviderInterceptor; 60 61 //================================================================== 62 //= OButtonModel 63 //================================================================== 64 DBG_NAME(OButtonModel) 65 //------------------------------------------------------------------ 66 InterfaceRef SAL_CALL OButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) 67 { 68 return *(new OButtonModel(_rxFactory)); 69 } 70 71 //------------------------------------------------------------------ 72 OButtonModel::OButtonModel(const Reference<XMultiServiceFactory>& _rxFactory) 73 :OClickableImageBaseModel( _rxFactory, VCL_CONTROLMODEL_COMMANDBUTTON, FRM_SUN_CONTROL_COMMANDBUTTON ) 74 // use the old control name for compatibility reasons 75 ,m_aResetHelper( *this, m_aMutex ) 76 ,m_eDefaultState( STATE_NOCHECK ) 77 { 78 DBG_CTOR( OButtonModel, NULL ); 79 m_nClassId = FormComponentType::COMMANDBUTTON; 80 } 81 82 //------------------------------------------------------------------ 83 Any SAL_CALL OButtonModel::queryAggregation( const Type& _type ) throw(RuntimeException) 84 { 85 Any aReturn = OClickableImageBaseModel::queryAggregation( _type ); 86 if ( !aReturn.hasValue() ) 87 aReturn = OButtonModel_Base::queryInterface( _type ); 88 return aReturn; 89 } 90 91 //------------------------------------------------------------------ 92 Sequence< Type > OButtonModel::_getTypes() 93 { 94 return ::comphelper::concatSequences( 95 OClickableImageBaseModel::_getTypes(), 96 OButtonModel_Base::getTypes() 97 ); 98 } 99 100 //------------------------------------------------------------------ 101 OButtonModel::OButtonModel( const OButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) 102 :OClickableImageBaseModel( _pOriginal, _rxFactory ) 103 ,m_aResetHelper( *this, m_aMutex ) 104 ,m_eDefaultState( _pOriginal->m_eDefaultState ) 105 { 106 DBG_CTOR( OButtonModel, NULL ); 107 m_nClassId = FormComponentType::COMMANDBUTTON; 108 109 implInitializeImageURL(); 110 } 111 112 //------------------------------------------------------------------------------ 113 OButtonModel::~OButtonModel() 114 { 115 DBG_DTOR(OButtonModel, NULL); 116 } 117 118 //------------------------------------------------------------------------------ 119 void OButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const 120 { 121 BEGIN_DESCRIBE_PROPERTIES( 6, OClickableImageBaseModel ) 122 DECL_PROP1( BUTTONTYPE, FormButtonType, BOUND ); 123 DECL_PROP1( DEFAULT_STATE, sal_Int16, BOUND ); 124 DECL_PROP1( DISPATCHURLINTERNAL, sal_Bool, BOUND ); 125 DECL_PROP1( TARGET_URL, ::rtl::OUString, BOUND ); 126 DECL_PROP1( TARGET_FRAME, ::rtl::OUString, BOUND ); 127 DECL_PROP1( TABINDEX, sal_Int16, BOUND ); 128 END_DESCRIBE_PROPERTIES(); 129 } 130 131 //------------------------------------------------------------------------------ 132 IMPLEMENT_DEFAULT_CLONING( OButtonModel ) 133 134 // XServiceInfo 135 //------------------------------------------------------------------------------ 136 StringSequence OButtonModel::getSupportedServiceNames() throw() 137 { 138 StringSequence aSupported = OClickableImageBaseModel::getSupportedServiceNames(); 139 aSupported.realloc( aSupported.getLength() + 1 ); 140 141 ::rtl::OUString* pArray = aSupported.getArray(); 142 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_COMMANDBUTTON; 143 144 return aSupported; 145 } 146 147 //------------------------------------------------------------------------------ 148 ::rtl::OUString OButtonModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException) 149 { 150 return FRM_COMPONENT_COMMANDBUTTON; // old (non-sun) name for compatibility ! 151 } 152 153 //------------------------------------------------------------------------------ 154 void OButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) 155 { 156 OClickableImageBaseModel::write(_rxOutStream); 157 158 _rxOutStream->writeShort(0x0003); // Version 159 160 { 161 OStreamSection aSection( _rxOutStream.get() ); 162 // this will allow readers to skip unknown bytes in their dtor 163 164 _rxOutStream->writeShort( (sal_uInt16)m_eButtonType ); 165 166 ::rtl::OUString sTmp = INetURLObject::decode( m_sTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS); 167 _rxOutStream << sTmp; 168 _rxOutStream << m_sTargetFrame; 169 writeHelpTextCompatibly(_rxOutStream); 170 _rxOutStream << isDispatchUrlInternal(); 171 } 172 } 173 174 //------------------------------------------------------------------------------ 175 void OButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) 176 { 177 OClickableImageBaseModel::read(_rxInStream); 178 179 sal_uInt16 nVersion = _rxInStream->readShort(); // Version 180 switch (nVersion) 181 { 182 case 0x0001: 183 { 184 m_eButtonType = (FormButtonType)_rxInStream->readShort(); 185 186 _rxInStream >> m_sTargetURL; 187 _rxInStream >> m_sTargetFrame; 188 } 189 break; 190 191 case 0x0002: 192 { 193 m_eButtonType = (FormButtonType)_rxInStream->readShort(); 194 195 _rxInStream >> m_sTargetURL; 196 _rxInStream >> m_sTargetFrame; 197 readHelpTextCompatibly(_rxInStream); 198 } 199 break; 200 201 case 0x0003: 202 { 203 OStreamSection aSection( _rxInStream.get() ); 204 // this will skip any unknown bytes in it's dtor 205 206 // button type 207 m_eButtonType = (FormButtonType)_rxInStream->readShort(); 208 209 // URL 210 _rxInStream >> m_sTargetURL; 211 212 // target frame 213 _rxInStream >> m_sTargetFrame; 214 215 // help text 216 readHelpTextCompatibly(_rxInStream); 217 218 // DispatchInternal 219 sal_Bool bDispath; 220 _rxInStream >> bDispath; 221 setDispatchUrlInternal(bDispath); 222 } 223 break; 224 225 default: 226 DBG_ERROR("OButtonModel::read : unknown version !"); 227 m_eButtonType = FormButtonType_PUSH; 228 m_sTargetURL = ::rtl::OUString(); 229 m_sTargetFrame = ::rtl::OUString(); 230 break; 231 } 232 } 233 234 //-------------------------------------------------------------------- 235 void SAL_CALL OButtonModel::disposing() 236 { 237 m_aResetHelper.disposing(); 238 OClickableImageBaseModel::disposing(); 239 } 240 241 //-------------------------------------------------------------------- 242 void SAL_CALL OButtonModel::reset() throw (RuntimeException) 243 { 244 if ( !m_aResetHelper.approveReset() ) 245 return; 246 247 impl_resetNoBroadcast_nothrow(); 248 249 m_aResetHelper.notifyResetted(); 250 } 251 252 //-------------------------------------------------------------------- 253 void SAL_CALL OButtonModel::addResetListener( const Reference< XResetListener >& _listener ) throw (RuntimeException) 254 { 255 m_aResetHelper.addResetListener( _listener ); 256 } 257 258 //-------------------------------------------------------------------- 259 void SAL_CALL OButtonModel::removeResetListener( const Reference< XResetListener >& _listener ) throw (RuntimeException) 260 { 261 m_aResetHelper.removeResetListener( _listener ); 262 } 263 264 //-------------------------------------------------------------------- 265 void SAL_CALL OButtonModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const 266 { 267 switch ( _nHandle ) 268 { 269 case PROPERTY_ID_DEFAULT_STATE: 270 _rValue <<= (sal_Int16)m_eDefaultState; 271 break; 272 273 default: 274 OClickableImageBaseModel::getFastPropertyValue( _rValue, _nHandle ); 275 break; 276 } 277 } 278 279 //-------------------------------------------------------------------- 280 void SAL_CALL OButtonModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) 281 { 282 switch ( _nHandle ) 283 { 284 case PROPERTY_ID_DEFAULT_STATE: 285 { 286 sal_Int16 nDefaultState( (sal_Int16)STATE_NOCHECK ); 287 OSL_VERIFY( _rValue >>= nDefaultState ); 288 m_eDefaultState = (ToggleState)nDefaultState; 289 impl_resetNoBroadcast_nothrow(); 290 } 291 break; 292 293 default: 294 OClickableImageBaseModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue ); 295 break; 296 } 297 } 298 299 //-------------------------------------------------------------------- 300 sal_Bool SAL_CALL OButtonModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException) 301 { 302 sal_Bool bModified = sal_False; 303 switch ( _nHandle ) 304 { 305 case PROPERTY_ID_DEFAULT_STATE: 306 bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_eDefaultState ); 307 break; 308 309 default: 310 bModified = OClickableImageBaseModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ); 311 break; 312 } 313 return bModified; 314 } 315 316 //-------------------------------------------------------------------- 317 Any OButtonModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const 318 { 319 Any aDefault; 320 switch ( _nHandle ) 321 { 322 case PROPERTY_ID_DEFAULT_STATE: 323 aDefault <<= (sal_Int16)STATE_NOCHECK; 324 break; 325 326 default: 327 aDefault = OClickableImageBaseModel::getPropertyDefaultByHandle( _nHandle ); 328 break; 329 } 330 return aDefault; 331 } 332 333 //-------------------------------------------------------------------- 334 void OButtonModel::impl_resetNoBroadcast_nothrow() 335 { 336 try 337 { 338 setPropertyValue( PROPERTY_STATE, getPropertyValue( PROPERTY_DEFAULT_STATE ) ); 339 } 340 catch( const Exception& ) 341 { 342 DBG_UNHANDLED_EXCEPTION(); 343 } 344 } 345 346 //================================================================== 347 // OButtonControl 348 //================================================================== 349 //------------------------------------------------------------------ 350 InterfaceRef SAL_CALL OButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) 351 { 352 return *(new OButtonControl(_rxFactory)); 353 } 354 355 //------------------------------------------------------------------------------ 356 Sequence<Type> OButtonControl::_getTypes() 357 { 358 return ::comphelper::concatSequences( 359 OButtonControl_BASE::getTypes(), 360 OClickableImageBaseControl::_getTypes(), 361 OFormNavigationHelper::getTypes() 362 ); 363 } 364 365 //------------------------------------------------------------------------------ 366 StringSequence OButtonControl::getSupportedServiceNames() throw() 367 { 368 StringSequence aSupported = OClickableImageBaseControl::getSupportedServiceNames(); 369 aSupported.realloc(aSupported.getLength() + 1); 370 371 ::rtl::OUString*pArray = aSupported.getArray(); 372 pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_COMMANDBUTTON; 373 return aSupported; 374 } 375 376 //------------------------------------------------------------------------------ 377 OButtonControl::OButtonControl(const Reference<XMultiServiceFactory>& _rxFactory) 378 :OClickableImageBaseControl(_rxFactory, VCL_CONTROL_COMMANDBUTTON) 379 ,OFormNavigationHelper( _rxFactory ) 380 ,m_nClickEvent( 0 ) 381 ,m_nTargetUrlFeatureId( -1 ) 382 ,m_bEnabledByPropertyValue( sal_False ) 383 { 384 increment(m_refCount); 385 { 386 // als ActionListener anmelden 387 Reference<XButton> xButton; 388 query_aggregation( m_xAggregate, xButton); 389 if (xButton.is()) 390 xButton->addActionListener(this); 391 } 392 // Refcount bei 1 fuer Listener 393 decrement(m_refCount); 394 } 395 396 //------------------------------------------------------------------------------ 397 OButtonControl::~OButtonControl() 398 { 399 if (m_nClickEvent) 400 Application::RemoveUserEvent(m_nClickEvent); 401 } 402 403 // UNO Anbindung 404 //------------------------------------------------------------------------------ 405 Any SAL_CALL OButtonControl::queryAggregation(const Type& _rType) throw (RuntimeException) 406 { 407 // if asked for the XTypeProvider, don't let OButtonControl_BASE do this 408 Any aReturn; 409 if ( !_rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) ) 410 aReturn = OButtonControl_BASE::queryInterface( _rType ); 411 412 if ( !aReturn.hasValue() ) 413 aReturn = OClickableImageBaseControl::queryAggregation( _rType ); 414 415 if ( !aReturn.hasValue() ) 416 aReturn = OFormNavigationHelper::queryInterface( _rType ); 417 418 return aReturn; 419 } 420 421 //------------------------------------------------------------------------------ 422 void SAL_CALL OButtonControl::disposing() 423 { 424 startOrStopModelPropertyListening( false ); 425 426 OClickableImageBaseControl::disposing(); 427 OFormNavigationHelper::dispose(); 428 } 429 430 //------------------------------------------------------------------------------ 431 void SAL_CALL OButtonControl::disposing( const EventObject& _rSource ) throw( RuntimeException ) 432 { 433 OControl::disposing( _rSource ); 434 OFormNavigationHelper::disposing( _rSource ); 435 } 436 437 // ActionListener 438 //------------------------------------------------------------------------------ 439 void OButtonControl::actionPerformed(const ActionEvent& /*rEvent*/) throw ( ::com::sun::star::uno::RuntimeException) 440 { 441 // Asynchron fuer starutil::URL-Button 442 sal_uLong n = Application::PostUserEvent( LINK(this, OButtonControl,OnClick) ); 443 { 444 ::osl::MutexGuard aGuard( m_aMutex ); 445 m_nClickEvent = n; 446 } 447 } 448 449 //------------------------------------------------------------------------------ 450 IMPL_LINK( OButtonControl, OnClick, void*, EMPTYARG ) 451 { 452 ::osl::ClearableMutexGuard aGuard( m_aMutex ); 453 m_nClickEvent = 0; 454 455 if (m_aApproveActionListeners.getLength()) 456 { 457 // if there are listeners, start the action in an own thread, to not allow 458 // them to block us here (we're in the application's main thread) 459 getImageProducerThread()->addEvent(); 460 } 461 else 462 { 463 // Sonst nicht. Dann darf man aber auf keinen Fal die Listener 464 // benachrichtigen, auch dann nicht, wenn er spaeter hinzukommt. 465 aGuard.clear(); 466 467 // recognize the button type 468 Reference<XPropertySet> xSet(getModel(), UNO_QUERY); 469 if (!xSet.is()) 470 return 0L; 471 472 if (FormButtonType_PUSH == *(FormButtonType*)xSet->getPropertyValue(PROPERTY_BUTTONTYPE).getValue()) 473 { 474 // notify the action listeners for a push button 475 ::cppu::OInterfaceIteratorHelper aIter(m_aActionListeners); 476 ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand); 477 while(aIter.hasMoreElements() ) 478 { 479 // catch exceptions 480 // and catch them on a per-listener basis - if one listener fails, the others still need 481 // to get notified 482 // 97676 - 21.02.2002 - fs@openoffice.org 483 try 484 { 485 static_cast< XActionListener* >( aIter.next() )->actionPerformed(aEvt); 486 } 487 #ifdef DBG_UTIL 488 catch( const RuntimeException& ) 489 { 490 // silent this 491 } 492 #endif 493 catch( const Exception& ) 494 { 495 DBG_ERROR( "OButtonControl::OnClick: caught a exception other than RuntimeException!" ); 496 } 497 } 498 } 499 else 500 actionPerformed_Impl( sal_False, ::com::sun::star::awt::MouseEvent() ); 501 } 502 return 0L; 503 } 504 505 //------------------------------------------------------------------------------ 506 void OButtonControl::actionPerformed_Impl( sal_Bool _bNotifyListener, const ::com::sun::star::awt::MouseEvent& _rEvt ) 507 { 508 { 509 sal_Int16 nFeatureId = -1; 510 { 511 ::osl::MutexGuard aGuard( m_aMutex ); 512 nFeatureId = m_nTargetUrlFeatureId; 513 } 514 515 if ( nFeatureId != -1 ) 516 { 517 if ( !approveAction() ) 518 return; 519 520 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 521 dispatch( nFeatureId ); 522 return; 523 } 524 } 525 526 OClickableImageBaseControl::actionPerformed_Impl( _bNotifyListener, _rEvt ); 527 } 528 529 // XButton 530 //------------------------------------------------------------------------------ 531 void OButtonControl::setLabel(const ::rtl::OUString& Label) throw( RuntimeException ) 532 { 533 Reference<XButton> xButton; 534 query_aggregation( m_xAggregate, xButton ); 535 if (xButton.is()) 536 xButton->setLabel(Label); 537 } 538 539 //------------------------------------------------------------------------------ 540 void SAL_CALL OButtonControl::setActionCommand(const ::rtl::OUString& _rCommand) throw( RuntimeException ) 541 { 542 { 543 ::osl::MutexGuard aGuard( m_aMutex ); 544 m_aActionCommand = _rCommand; 545 } 546 547 Reference<XButton> xButton; 548 query_aggregation( m_xAggregate, xButton); 549 if (xButton.is()) 550 xButton->setActionCommand(_rCommand); 551 } 552 553 //------------------------------------------------------------------------------ 554 void SAL_CALL OButtonControl::addActionListener(const Reference<XActionListener>& _rxListener) throw( RuntimeException ) 555 { 556 m_aActionListeners.addInterface(_rxListener); 557 } 558 559 //------------------------------------------------------------------------------ 560 void SAL_CALL OButtonControl::removeActionListener(const Reference<XActionListener>& _rxListener) throw( RuntimeException ) 561 { 562 m_aActionListeners.removeInterface(_rxListener); 563 } 564 565 //------------------------------------------------------------------------------ 566 class DoPropertyListening 567 { 568 private: 569 Reference< XPropertySet > m_xProps; 570 Reference< XPropertyChangeListener > m_xListener; 571 bool m_bStartListening; 572 573 public: 574 DoPropertyListening( 575 const Reference< XInterface >& _rxComponent, 576 const Reference< XPropertyChangeListener >& _rxListener, 577 bool _bStart 578 ); 579 580 void handleListening( const ::rtl::OUString& _rPropertyName ); 581 }; 582 583 //.............................................................................. 584 DoPropertyListening::DoPropertyListening( 585 const Reference< XInterface >& _rxComponent, const Reference< XPropertyChangeListener >& _rxListener, 586 bool _bStart ) 587 :m_xProps( _rxComponent, UNO_QUERY ) 588 ,m_xListener( _rxListener ) 589 ,m_bStartListening( _bStart ) 590 { 591 DBG_ASSERT( m_xProps.is() || !_rxComponent.is(), "DoPropertyListening::DoPropertyListening: valid component, but no property set!" ); 592 DBG_ASSERT( m_xListener.is(), "DoPropertyListening::DoPropertyListening: invalid listener!" ); 593 } 594 595 //.............................................................................. 596 void DoPropertyListening::handleListening( const ::rtl::OUString& _rPropertyName ) 597 { 598 if ( m_xProps.is() ) 599 { 600 if ( m_bStartListening ) 601 m_xProps->addPropertyChangeListener( _rPropertyName, m_xListener ); 602 else 603 m_xProps->removePropertyChangeListener( _rPropertyName, m_xListener ); 604 } 605 } 606 607 //------------------------------------------------------------------------------ 608 void OButtonControl::startOrStopModelPropertyListening( bool _bStart ) 609 { 610 DoPropertyListening aListeningHandler( getModel(), this, _bStart ); 611 aListeningHandler.handleListening( PROPERTY_TARGET_URL ); 612 aListeningHandler.handleListening( PROPERTY_BUTTONTYPE ); 613 aListeningHandler.handleListening( PROPERTY_ENABLED ); 614 } 615 616 //------------------------------------------------------------------------------ 617 sal_Bool SAL_CALL OButtonControl::setModel( const Reference< XControlModel >& _rxModel ) throw ( RuntimeException ) 618 { 619 startOrStopModelPropertyListening( false ); 620 sal_Bool bResult = OClickableImageBaseControl::setModel( _rxModel ); 621 startOrStopModelPropertyListening( true ); 622 623 m_bEnabledByPropertyValue = sal_True; 624 Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY ); 625 if ( xModelProps.is() ) 626 xModelProps->getPropertyValue( PROPERTY_ENABLED ) >>= m_bEnabledByPropertyValue; 627 628 modelFeatureUrlPotentiallyChanged( ); 629 630 return bResult; 631 } 632 633 //------------------------------------------------------------------------------ 634 void OButtonControl::modelFeatureUrlPotentiallyChanged( ) 635 { 636 sal_Int16 nOldUrlFeatureId = m_nTargetUrlFeatureId; 637 638 // doe we have another TargetURL now? If so, we need to update our dispatches 639 m_nTargetUrlFeatureId = getModelUrlFeatureId( ); 640 if ( nOldUrlFeatureId != m_nTargetUrlFeatureId ) 641 { 642 invalidateSupportedFeaturesSet(); 643 if ( !isDesignMode() ) 644 updateDispatches( ); 645 } 646 } 647 648 //------------------------------------------------------------------------------ 649 void SAL_CALL OButtonControl::propertyChange( const PropertyChangeEvent& _rEvent ) throw ( RuntimeException ) 650 { 651 if ( _rEvent.PropertyName.equals( PROPERTY_TARGET_URL ) 652 || _rEvent.PropertyName.equals( PROPERTY_BUTTONTYPE ) 653 ) 654 { 655 modelFeatureUrlPotentiallyChanged( ); 656 } 657 else if ( _rEvent.PropertyName.equals( PROPERTY_ENABLED ) ) 658 { 659 _rEvent.NewValue >>= m_bEnabledByPropertyValue; 660 } 661 } 662 663 //------------------------------------------------------------------------------ 664 namespace 665 { 666 bool isFormControllerURL( const ::rtl::OUString& _rURL ) 667 { 668 const sal_Int32 nPrefixLen = URL_CONTROLLER_PREFIX.length; 669 return ( _rURL.getLength() > nPrefixLen ) 670 && ( _rURL.compareToAscii( URL_CONTROLLER_PREFIX, nPrefixLen ) == 0 ); 671 } 672 } 673 674 //------------------------------------------------------------------------------ 675 sal_Int16 OButtonControl::getModelUrlFeatureId( ) const 676 { 677 sal_Int16 nFeatureId = -1; 678 679 // some URL related properties of the model 680 ::rtl::OUString sUrl; 681 FormButtonType eButtonType = FormButtonType_PUSH; 682 683 Reference< XPropertySet > xModelProps( const_cast< OButtonControl* >( this )->getModel(), UNO_QUERY ); 684 if ( xModelProps.is() ) 685 { 686 xModelProps->getPropertyValue( PROPERTY_TARGET_URL ) >>= sUrl; 687 xModelProps->getPropertyValue( PROPERTY_BUTTONTYPE ) >>= eButtonType; 688 } 689 690 // are we an URL button? 691 if ( eButtonType == FormButtonType_URL ) 692 { 693 // is it a feature URL? 694 if ( isFormControllerURL( sUrl ) ) 695 { 696 OFormNavigationMapper aMapper( m_aContext.getLegacyServiceFactory() ); 697 nFeatureId = aMapper.getFeatureId( sUrl ); 698 } 699 } 700 701 return nFeatureId; 702 } 703 704 //------------------------------------------------------------------ 705 void SAL_CALL OButtonControl::setDesignMode( sal_Bool _bOn ) throw( RuntimeException ) 706 { 707 OClickableImageBaseControl::setDesignMode( _bOn ); 708 709 if ( _bOn ) 710 disconnectDispatchers(); 711 else 712 connectDispatchers(); 713 // this will connect if not already connected and just update else 714 } 715 716 //------------------------------------------------------------------------------ 717 void OButtonControl::getSupportedFeatures( ::std::vector< sal_Int16 >& /* [out] */ _rFeatureIds ) 718 { 719 if ( -1 != m_nTargetUrlFeatureId ) 720 _rFeatureIds.push_back( m_nTargetUrlFeatureId ); 721 } 722 723 //------------------------------------------------------------------ 724 void OButtonControl::featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled ) 725 { 726 if ( _nFeatureId == m_nTargetUrlFeatureId ) 727 { 728 // enable or disable our peer, according to the new state 729 Reference< XVclWindowPeer > xPeer( getPeer(), UNO_QUERY ); 730 if ( xPeer.is() ) 731 xPeer->setProperty( PROPERTY_ENABLED, makeAny( m_bEnabledByPropertyValue ? _bEnabled : sal_False ) ); 732 // if we're disabled according to our model's property, then 733 // we don't care for the feature state, but *are* disabled. 734 // If the model's property states that we're enabled, then we *do* 735 // care for the feature state 736 } 737 738 // base class 739 OFormNavigationHelper::featureStateChanged( _nFeatureId, _bEnabled ); 740 } 741 742 //------------------------------------------------------------------ 743 void OButtonControl::allFeatureStatesChanged( ) 744 { 745 if ( -1 != m_nTargetUrlFeatureId ) 746 // we have only one supported feature, so simulate it has changed ... 747 featureStateChanged( m_nTargetUrlFeatureId, isEnabled( m_nTargetUrlFeatureId ) ); 748 749 // base class 750 OFormNavigationHelper::allFeatureStatesChanged( ); 751 } 752 753 //------------------------------------------------------------------ 754 bool OButtonControl::isEnabled( sal_Int16 _nFeatureId ) const 755 { 756 if ( const_cast< OButtonControl* >( this )->isDesignMode() ) 757 // TODO: the model property? 758 return true; 759 760 return OFormNavigationHelper::isEnabled( _nFeatureId ); 761 } 762 763 //-------------------------------------------------------------------- 764 void SAL_CALL OButtonControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) 765 { 766 OClickableImageBaseControl::registerDispatchProviderInterceptor( _rxInterceptor ); 767 OFormNavigationHelper::registerDispatchProviderInterceptor( _rxInterceptor ); 768 } 769 770 //-------------------------------------------------------------------- 771 void SAL_CALL OButtonControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) 772 { 773 OClickableImageBaseControl::releaseDispatchProviderInterceptor( _rxInterceptor ); 774 OFormNavigationHelper::releaseDispatchProviderInterceptor( _rxInterceptor ); 775 } 776 777 //......................................................................... 778 } // namespace frm 779 //......................................................................... 780 781