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