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 #include "clickableimage.hxx" 27 #include "controlfeatureinterception.hxx" 28 #include "urltransformer.hxx" 29 #include "componenttools.hxx" 30 #include <com/sun/star/form/XSubmit.hpp> 31 #include <com/sun/star/awt/SystemPointer.hpp> 32 #include <com/sun/star/form/FormComponentType.hpp> 33 #include <com/sun/star/frame/XDispatch.hpp> 34 #include <com/sun/star/frame/XDispatchProvider.hpp> 35 #include <com/sun/star/frame/FrameSearchFlag.hpp> 36 #include <com/sun/star/frame/XController.hpp> 37 #include <com/sun/star/frame/XFrame.hpp> 38 #include <com/sun/star/awt/ActionEvent.hpp> 39 #include <com/sun/star/awt/XActionListener.hpp> 40 #include <tools/urlobj.hxx> 41 #include <tools/debug.hxx> 42 #include <vcl/svapp.hxx> 43 #include <sfx2/docfile.hxx> 44 #include <sfx2/objsh.hxx> 45 #include <vos/mutex.hxx> 46 #include "services.hxx" 47 #include <comphelper/container.hxx> 48 #include <comphelper/listenernotification.hxx> 49 #include <svtools/imageresourceaccess.hxx> 50 #define LOCAL_URL_PREFIX '#' 51 52 //......................................................................... 53 namespace frm 54 { 55 //......................................................................... 56 57 using namespace ::com::sun::star::uno; 58 using namespace ::com::sun::star::sdb; 59 using namespace ::com::sun::star::sdbc; 60 using namespace ::com::sun::star::sdbcx; 61 using namespace ::com::sun::star::beans; 62 using namespace ::com::sun::star::container; 63 using namespace ::com::sun::star::form; 64 using namespace ::com::sun::star::awt; 65 using namespace ::com::sun::star::io; 66 using namespace ::com::sun::star::lang; 67 using namespace ::com::sun::star::util; 68 using namespace ::com::sun::star::frame; 69 using namespace ::com::sun::star::form::submission; 70 using ::com::sun::star::awt::MouseEvent; 71 using ::com::sun::star::task::XInteractionHandler; 72 73 //================================================================== 74 // OClickableImageBaseControl 75 //================================================================== 76 //------------------------------------------------------------------------------ _getTypes()77 Sequence<Type> OClickableImageBaseControl::_getTypes() 78 { 79 static Sequence<Type> aTypes; 80 if (!aTypes.getLength()) 81 aTypes = concatSequences(OControl::_getTypes(), OClickableImageBaseControl_BASE::getTypes()); 82 return aTypes; 83 } 84 85 //------------------------------------------------------------------------------ OClickableImageBaseControl(const Reference<XMultiServiceFactory> & _rxFactory,const::rtl::OUString & _aService)86 OClickableImageBaseControl::OClickableImageBaseControl(const Reference<XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _aService) 87 :OControl(_rxFactory, _aService) 88 ,m_pThread(NULL) 89 ,m_aSubmissionVetoListeners( m_aMutex ) 90 ,m_aApproveActionListeners( m_aMutex ) 91 ,m_aActionListeners( m_aMutex ) 92 { 93 m_pFeatureInterception.reset( new ControlFeatureInterception( _rxFactory ) ); 94 } 95 96 //------------------------------------------------------------------------------ ~OClickableImageBaseControl()97 OClickableImageBaseControl::~OClickableImageBaseControl() 98 { 99 if (!OComponentHelper::rBHelper.bDisposed) 100 { 101 acquire(); 102 dispose(); 103 } 104 } 105 106 // UNO Anbindung 107 //------------------------------------------------------------------------------ queryAggregation(const Type & _rType)108 Any SAL_CALL OClickableImageBaseControl::queryAggregation(const Type& _rType) 109 { 110 Any aReturn = OControl::queryAggregation(_rType); 111 if (!aReturn.hasValue()) 112 aReturn = OClickableImageBaseControl_BASE::queryInterface(_rType); 113 return aReturn; 114 } 115 116 // XApproveActionBroadcaster 117 //------------------------------------------------------------------------------ addApproveActionListener(const Reference<XApproveActionListener> & l)118 void OClickableImageBaseControl::addApproveActionListener( 119 const Reference<XApproveActionListener>& l) 120 { 121 m_aApproveActionListeners.addInterface(l); 122 } 123 124 //------------------------------------------------------------------------------ removeApproveActionListener(const Reference<XApproveActionListener> & l)125 void OClickableImageBaseControl::removeApproveActionListener( 126 const Reference<XApproveActionListener>& l) 127 { 128 m_aApproveActionListeners.removeInterface(l); 129 } 130 131 //-------------------------------------------------------------------- registerDispatchProviderInterceptor(const Reference<XDispatchProviderInterceptor> & _rxInterceptor)132 void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) 133 { 134 m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor ); 135 } 136 137 //-------------------------------------------------------------------- releaseDispatchProviderInterceptor(const Reference<XDispatchProviderInterceptor> & _rxInterceptor)138 void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) 139 { 140 m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor ); 141 } 142 143 // OComponentHelper 144 //------------------------------------------------------------------------------ disposing()145 void OClickableImageBaseControl::disposing() 146 { 147 EventObject aEvent( static_cast< XWeak* >( this ) ); 148 m_aApproveActionListeners.disposeAndClear( aEvent ); 149 m_aActionListeners.disposeAndClear( aEvent ); 150 m_aSubmissionVetoListeners.disposeAndClear( aEvent ); 151 m_pFeatureInterception->dispose(); 152 153 { 154 ::osl::MutexGuard aGuard( m_aMutex ); 155 if( m_pThread ) 156 { 157 m_pThread->release(); 158 m_pThread = NULL; 159 } 160 } 161 162 OControl::disposing(); 163 } 164 165 //------------------------------------------------------------------------------ getImageProducerThread()166 OImageProducerThread_Impl* OClickableImageBaseControl::getImageProducerThread() 167 { 168 if ( !m_pThread ) 169 { 170 m_pThread = new OImageProducerThread_Impl( this ); 171 m_pThread->acquire(); 172 m_pThread->create(); 173 } 174 return m_pThread; 175 } 176 177 //------------------------------------------------------------------------------ approveAction()178 bool OClickableImageBaseControl::approveAction( ) 179 { 180 sal_Bool bCancelled = sal_False; 181 EventObject aEvent( static_cast< XWeak* >( this ) ); 182 183 ::cppu::OInterfaceIteratorHelper aIter( m_aApproveActionListeners ); 184 while( !bCancelled && aIter.hasMoreElements() ) 185 { 186 // Jede approveAction-Methode muss thread-safe sein!!! 187 if( !static_cast< XApproveActionListener* >( aIter.next() )->approveAction( aEvent ) ) 188 bCancelled = sal_True; 189 } 190 191 return !bCancelled; 192 } 193 194 //------------------------------------------------------------------------------ 195 // Diese Methode wird auch aus einem Thread gerufen und muss deshalb 196 // thread-safe sein. actionPerformed_Impl(sal_Bool bNotifyListener,const MouseEvent & rEvt)197 void OClickableImageBaseControl::actionPerformed_Impl(sal_Bool bNotifyListener, const MouseEvent& rEvt) 198 { 199 if( bNotifyListener ) 200 { 201 if ( !approveAction() ) 202 return; 203 } 204 205 // Ob der Rest des Codes Thread-Safe ist weiss man nicht genau. Deshalb 206 // wird das meiste bei gelocktem Solar-Mutex erledigen. 207 Reference<XPropertySet> xSet; 208 Reference< XInterface > xModelsParent; 209 FormButtonType eButtonType = FormButtonType_PUSH; 210 { 211 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 212 213 // Parent holen 214 Reference<XFormComponent> xComp(getModel(), UNO_QUERY); 215 if (!xComp.is()) 216 return; 217 218 xModelsParent = xComp->getParent(); 219 if (!xModelsParent.is()) 220 return; 221 222 // which button type? 223 xSet = xSet.query( xComp ); 224 if ( !xSet.is() ) 225 return; 226 xSet->getPropertyValue(PROPERTY_BUTTONTYPE) >>= eButtonType; 227 } 228 229 switch (eButtonType) 230 { 231 case FormButtonType_RESET: 232 { 233 // reset-Methoden muessen thread-safe sein! 234 Reference<XReset> xReset(xModelsParent, UNO_QUERY); 235 if (!xReset.is()) 236 return; 237 238 xReset->reset(); 239 } 240 break; 241 242 case FormButtonType_SUBMIT: 243 { 244 // if some outer component can provide an interaction handler, use it 245 Reference< XInteractionHandler > xHandler( m_pFeatureInterception->queryDispatch( "private:/InteractionHandler" ), UNO_QUERY ); 246 try 247 { 248 implSubmit( rEvt, xHandler ); 249 } 250 catch( const Exception& ) 251 { 252 // ignore 253 } 254 } 255 break; 256 257 case FormButtonType_URL: 258 { 259 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 260 261 Reference< XModel > xModel = getXModel(xModelsParent); 262 if (!xModel.is()) 263 return; 264 265 /////////////////////////////////////////////////////////////////////// 266 // Jetzt URL ausfuehren 267 Reference< XController > xController = xModel->getCurrentController(); 268 if (!xController.is()) 269 return; 270 271 Reference< XFrame > xFrame = xController->getFrame(); 272 if( !xFrame.is() ) 273 return; 274 275 URL aURL; 276 aURL.Complete = 277 getString(xSet->getPropertyValue(PROPERTY_TARGET_URL)); 278 279 if (aURL.Complete.getLength() && (LOCAL_URL_PREFIX == aURL.Complete.getStr()[0])) 280 { // the URL contains a local URL only. Since the URLTransformer does not handle this case correctly 281 // (it can't: it does not know the document URL), we have to take care for this ourself. 282 // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all 283 // URLs have to be absolute), but for compatibility reasons this is no option. 284 // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it 285 // could be "#mark" as well. 286 // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete 287 // solutiuon would be: 288 // * recognize URLs consisting of a mark only while _reading_ the document 289 // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to 290 // transform such mark-only URLs into correct absolute URLs 291 // * at the UI, show only the mark 292 // * !!!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems 293 // rather impossible !!! 294 // 89752 - 23.07.2001 - frank.schoenheit@sun.com 295 aURL.Mark = aURL.Complete; 296 aURL.Complete = xModel->getURL(); 297 aURL.Complete += aURL.Mark; 298 } 299 300 sal_Bool bDispatchUrlInternal = sal_False; 301 xSet->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL) >>= bDispatchUrlInternal; 302 if ( bDispatchUrlInternal ) 303 { 304 m_pFeatureInterception->getTransformer().parseSmartWithAsciiProtocol( aURL, INET_FILE_SCHEME ); 305 306 ::rtl::OUString aTargetFrame; 307 xSet->getPropertyValue(PROPERTY_TARGET_FRAME) >>= aTargetFrame; 308 309 Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch( aURL, aTargetFrame, 310 FrameSearchFlag::SELF | FrameSearchFlag::PARENT | 311 FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE ); 312 313 Sequence<PropertyValue> aArgs(1); 314 PropertyValue& rProp = aArgs.getArray()[0]; 315 rProp.Name = ::rtl::OUString::createFromAscii("Referer"); 316 rProp.Value <<= xModel->getURL(); 317 318 if (xDisp.is()) 319 xDisp->dispatch( aURL, aArgs ); 320 } 321 else 322 { 323 URL aHyperLink = m_pFeatureInterception->getTransformer().getStrictURLFromAscii( ".uno:OpenHyperlink" ); 324 325 Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aHyperLink, ::rtl::OUString() , 0); 326 327 if ( xDisp.is() ) 328 { 329 Sequence<PropertyValue> aProps(3); 330 aProps[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL")); 331 aProps[0].Value <<= aURL.Complete; 332 333 aProps[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FrameName")); 334 aProps[1].Value = xSet->getPropertyValue(PROPERTY_TARGET_FRAME); 335 336 aProps[2].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer")); 337 aProps[2].Value <<= xModel->getURL(); 338 339 xDisp->dispatch( aHyperLink, aProps ); 340 } 341 } 342 } break; 343 default: 344 { 345 // notify the action listeners for a push button 346 ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand); 347 m_aActionListeners.notifyEach( &XActionListener::actionPerformed, aEvt ); 348 } 349 } 350 } 351 352 353 //-------------------------------------------------------------------- addSubmissionVetoListener(const Reference<submission::XSubmissionVetoListener> & listener)354 void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) 355 { 356 m_aSubmissionVetoListeners.addInterface( listener ); 357 } 358 359 //-------------------------------------------------------------------- removeSubmissionVetoListener(const Reference<submission::XSubmissionVetoListener> & listener)360 void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) 361 { 362 m_aSubmissionVetoListeners.removeInterface( listener ); 363 } 364 365 //-------------------------------------------------------------------- submitWithInteraction(const Reference<XInteractionHandler> & _rxHandler)366 void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler ) 367 { 368 implSubmit( MouseEvent(), _rxHandler ); 369 } 370 371 //-------------------------------------------------------------------- submit()372 void SAL_CALL OClickableImageBaseControl::submit( ) 373 { 374 implSubmit( MouseEvent(), NULL ); 375 } 376 377 //-------------------------------------------------------------------- getSupportedServiceNames()378 Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseControl::getSupportedServiceNames( ) 379 { 380 Sequence< ::rtl::OUString > aSupported = OControl::getSupportedServiceNames(); 381 aSupported.realloc( aSupported.getLength() + 1 ); 382 383 ::rtl::OUString* pArray = aSupported.getArray(); 384 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON; 385 386 return aSupported; 387 } 388 389 //-------------------------------------------------------------------- implSubmit(const MouseEvent & _rEvent,const Reference<XInteractionHandler> & _rxHandler)390 void OClickableImageBaseControl::implSubmit( const MouseEvent& _rEvent, const Reference< XInteractionHandler >& _rxHandler ) 391 { 392 try 393 { 394 // allow the veto listeners to join the game 395 m_aSubmissionVetoListeners.notifyEach( &XSubmissionVetoListener::submitting, EventObject( *this ) ); 396 397 // see whether there's an "submit interceptor" set at our model 398 Reference< submission::XSubmissionSupplier > xSubmissionSupp( getModel(), UNO_QUERY ); 399 Reference< XSubmission > xSubmission; 400 if ( xSubmissionSupp.is() ) 401 xSubmission = xSubmissionSupp->getSubmission(); 402 403 if ( xSubmission.is() ) 404 { 405 if ( !_rxHandler.is() ) 406 xSubmission->submit(); 407 else 408 xSubmission->submitWithInteraction( _rxHandler ); 409 } 410 else 411 { 412 // no "interceptor" -> ordinary (old-way) submission 413 Reference< XChild > xChild( getModel(), UNO_QUERY ); 414 Reference< XSubmit > xParentSubmission; 415 if ( xChild.is() ) 416 xParentSubmission = xParentSubmission.query( xChild->getParent() ); 417 if ( xParentSubmission.is() ) 418 xParentSubmission->submit( this, _rEvent ); 419 } 420 } 421 catch( const VetoException& ) 422 { 423 // allowed to leave 424 throw; 425 } 426 catch( const RuntimeException& ) 427 { 428 // allowed to leave 429 throw; 430 } 431 catch( const WrappedTargetException& e ) 432 { 433 // allowed to leave 434 throw; 435 } 436 catch( const Exception& e ) 437 { 438 OSL_ENSURE( sal_False, "OClickableImageBaseControl::implSubmit: caught an unknown exception!" ); 439 throw WrappedTargetException( ::rtl::OUString(), *this, makeAny( e ) ); 440 } 441 } 442 443 //================================================================== 444 // OClickableImageBaseModel 445 //================================================================== 446 //------------------------------------------------------------------------------ _getTypes()447 Sequence<Type> OClickableImageBaseModel::_getTypes() 448 { 449 return concatSequences( 450 OControlModel::_getTypes(), 451 OClickableImageBaseModel_Base::getTypes() 452 ); 453 } 454 455 //------------------------------------------------------------------ DBG_NAME(OClickableImageBaseModel)456 DBG_NAME( OClickableImageBaseModel ) 457 //------------------------------------------------------------------ 458 OClickableImageBaseModel::OClickableImageBaseModel( const Reference< XMultiServiceFactory >& _rxFactory, const ::rtl::OUString& _rUnoControlModelTypeName, 459 const ::rtl::OUString& rDefault ) 460 :OControlModel( _rxFactory, _rUnoControlModelTypeName, rDefault ) 461 ,OPropertyChangeListener(m_aMutex) 462 ,m_pMedium(NULL) 463 ,m_pProducer( NULL ) 464 ,m_bDispatchUrlInternal(sal_False) 465 ,m_bDownloading(sal_False) 466 ,m_bProdStarted(sal_False) 467 { 468 DBG_CTOR( OClickableImageBaseModel, NULL ); 469 implConstruct(); 470 m_eButtonType = FormButtonType_PUSH; 471 } 472 473 //------------------------------------------------------------------ OClickableImageBaseModel(const OClickableImageBaseModel * _pOriginal,const Reference<XMultiServiceFactory> & _rxFactory)474 OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) 475 :OControlModel( _pOriginal, _rxFactory ) 476 ,OPropertyChangeListener( m_aMutex ) 477 ,m_pMedium( NULL ) 478 ,m_pProducer( NULL ) 479 ,m_bDispatchUrlInternal(sal_False) 480 ,m_bDownloading( sal_False ) 481 ,m_bProdStarted( sal_False ) 482 { 483 DBG_CTOR( OClickableImageBaseModel, NULL ); 484 implConstruct(); 485 486 // copy properties 487 m_eButtonType = _pOriginal->m_eButtonType; 488 m_sTargetURL = _pOriginal->m_sTargetURL; 489 m_sTargetFrame = _pOriginal->m_sTargetFrame; 490 m_bDispatchUrlInternal = _pOriginal->m_bDispatchUrlInternal; 491 } 492 493 //------------------------------------------------------------------------------ implInitializeImageURL()494 void OClickableImageBaseModel::implInitializeImageURL( ) 495 { 496 osl_incrementInterlockedCount( &m_refCount ); 497 { 498 // simulate a propertyChanged event for the ImageURL 499 // 2003-05-15 - #109591# - fs@openoffice.org 500 Any aImageURL; 501 getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL ); 502 _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL, sal_False, PROPERTY_ID_IMAGE_URL, Any( ), aImageURL ) ); 503 } 504 osl_decrementInterlockedCount( &m_refCount ); 505 } 506 507 //------------------------------------------------------------------------------ implConstruct()508 void OClickableImageBaseModel::implConstruct() 509 { 510 m_pProducer = new ImageProducer; 511 increment( m_refCount ); 512 { 513 m_xProducer = m_pProducer; 514 515 if ( m_xAggregateSet.is() ) 516 { 517 OPropertyChangeMultiplexer* pMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet ); 518 pMultiplexer->addProperty( PROPERTY_IMAGE_URL ); 519 } 520 } 521 decrement(m_refCount); 522 } 523 524 //------------------------------------------------------------------------------ ~OClickableImageBaseModel()525 OClickableImageBaseModel::~OClickableImageBaseModel() 526 { 527 if (!OComponentHelper::rBHelper.bDisposed) 528 { 529 acquire(); 530 dispose(); 531 } 532 DBG_ASSERT(m_pMedium == NULL, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ..."); 533 // spaetestens im dispose sollte das aufgeraeumt worden sein 534 535 DBG_DTOR( OClickableImageBaseModel, NULL ); 536 } 537 538 // XImageProducer 539 //-------------------------------------------------------------------- addConsumer(const Reference<XImageConsumer> & _rxConsumer)540 void SAL_CALL OClickableImageBaseModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) 541 { 542 ImageModelMethodGuard aGuard( *this ); 543 GetImageProducer()->addConsumer( _rxConsumer ); 544 } 545 546 //-------------------------------------------------------------------- removeConsumer(const Reference<XImageConsumer> & _rxConsumer)547 void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) 548 { 549 ImageModelMethodGuard aGuard( *this ); 550 GetImageProducer()->removeConsumer( _rxConsumer ); 551 } 552 553 //-------------------------------------------------------------------- startProduction()554 void SAL_CALL OClickableImageBaseModel::startProduction( ) 555 { 556 ImageModelMethodGuard aGuard( *this ); 557 GetImageProducer()->startProduction(); 558 } 559 560 //-------------------------------------------------------------------- getSubmission()561 Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission() 562 { 563 return m_xSubmissionDelegate; 564 } 565 566 //-------------------------------------------------------------------- setSubmission(const Reference<submission::XSubmission> & _submission)567 void SAL_CALL OClickableImageBaseModel::setSubmission( const Reference< submission::XSubmission >& _submission ) 568 { 569 m_xSubmissionDelegate = _submission; 570 } 571 572 //-------------------------------------------------------------------- getSupportedServiceNames()573 Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseModel::getSupportedServiceNames( ) 574 { 575 Sequence< ::rtl::OUString > aSupported = OControlModel::getSupportedServiceNames(); 576 aSupported.realloc( aSupported.getLength() + 1 ); 577 578 ::rtl::OUString* pArray = aSupported.getArray(); 579 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON; 580 581 return aSupported; 582 } 583 584 // OComponentHelper 585 //------------------------------------------------------------------------------ disposing()586 void OClickableImageBaseModel::disposing() 587 { 588 OControlModel::disposing(); 589 if (m_pMedium) 590 { 591 delete m_pMedium; 592 m_pMedium = NULL; 593 } 594 595 m_xProducer = NULL; 596 m_pProducer = NULL; 597 } 598 599 //------------------------------------------------------------------------------ queryAggregation(const Type & _rType)600 Any SAL_CALL OClickableImageBaseModel::queryAggregation(const Type& _rType) 601 { 602 // order matters: 603 // we definitely want to "overload" the XImageProducer interface of our aggregate, 604 // thus check OClickableImageBaseModel_Base (which provides this) first 605 Any aReturn = OClickableImageBaseModel_Base::queryInterface( _rType ); 606 607 // BUT: _don't_ let it feel responsible for the XTypeProvider interface 608 // (as this is implemented by our base class in the proper way) 609 if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) 610 || !aReturn.hasValue() 611 ) 612 aReturn = OControlModel::queryAggregation( _rType ); 613 614 return aReturn; 615 } 616 617 //------------------------------------------------------------------------------ getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const618 void OClickableImageBaseModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const 619 { 620 switch (nHandle) 621 { 622 case PROPERTY_ID_BUTTONTYPE : rValue <<= m_eButtonType; break; 623 case PROPERTY_ID_TARGET_URL : rValue <<= m_sTargetURL; break; 624 case PROPERTY_ID_TARGET_FRAME : rValue <<= m_sTargetFrame; break; 625 case PROPERTY_ID_DISPATCHURLINTERNAL : rValue <<= m_bDispatchUrlInternal; break; 626 default: 627 OControlModel::getFastPropertyValue(rValue, nHandle); 628 } 629 } 630 631 //------------------------------------------------------------------------------ setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)632 void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) 633 { 634 switch (nHandle) 635 { 636 case PROPERTY_ID_BUTTONTYPE : 637 DBG_ASSERT(isA(rValue, static_cast<FormButtonType*>(NULL)), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); 638 rValue >>= m_eButtonType; 639 break; 640 641 case PROPERTY_ID_TARGET_URL : 642 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); 643 rValue >>= m_sTargetURL; 644 break; 645 646 case PROPERTY_ID_TARGET_FRAME : 647 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); 648 rValue >>= m_sTargetFrame; 649 break; 650 651 case PROPERTY_ID_DISPATCHURLINTERNAL: 652 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); 653 rValue >>= m_bDispatchUrlInternal; 654 break; 655 656 default: 657 OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); 658 } 659 } 660 661 //------------------------------------------------------------------------------ convertFastPropertyValue(Any & rConvertedValue,Any & rOldValue,sal_Int32 nHandle,const Any & rValue)662 sal_Bool OClickableImageBaseModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) 663 { 664 switch (nHandle) 665 { 666 case PROPERTY_ID_BUTTONTYPE : 667 return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType ); 668 669 case PROPERTY_ID_TARGET_URL : 670 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL); 671 672 case PROPERTY_ID_TARGET_FRAME : 673 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame); 674 675 case PROPERTY_ID_DISPATCHURLINTERNAL : 676 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal); 677 678 default: 679 return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); 680 } 681 } 682 683 //------------------------------------------------------------------------------ StartProduction()684 void OClickableImageBaseModel::StartProduction() 685 { 686 ImageProducer *pImgProd = GetImageProducer(); 687 // grab the ImageURL 688 rtl::OUString sURL; 689 getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ImageURL") ) ) >>= sURL; 690 if (!m_pMedium) 691 { 692 if ( ::svt::GraphicAccess::isSupportedURL( sURL ) ) 693 pImgProd->SetImage( sURL ); 694 else 695 // caution: the medium may be NULL if somebody gave us a invalid URL to work with 696 // 11/24/2000 - 79667 - FS 697 pImgProd->SetImage(String()); 698 m_bDownloading = sal_False; 699 return; 700 } 701 if (m_pMedium->GetErrorCode()==0) 702 { 703 SvStream* pStream = m_pMedium->GetInStream(); 704 705 pImgProd->SetImage(*pStream); 706 pImgProd->startProduction(); 707 m_bProdStarted = sal_True; 708 } 709 else 710 { 711 pImgProd->SetImage(String()); 712 delete m_pMedium; 713 m_pMedium = 0; 714 m_bDownloading = sal_False; 715 } 716 } 717 718 //------------------------------------------------------------------------------ SetURL(const::rtl::OUString & rURL)719 void OClickableImageBaseModel::SetURL( const ::rtl::OUString& rURL ) 720 { 721 if (m_pMedium || !rURL.getLength()) 722 { 723 // Den Stream am Producer freigeben, bevor das Medium geloscht wird. 724 GetImageProducer()->SetImage(String()); 725 delete m_pMedium; 726 m_pMedium = NULL; 727 } 728 729 // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first 730 // 23.01.2001 - 81927 - FS 731 INetURLObject aUrl(rURL); 732 if (INET_PROT_NOT_VALID == aUrl.GetProtocol()) 733 // we treat an invalid URL like we would treat no URL 734 return; 735 736 if (rURL.getLength() && !::svt::GraphicAccess::isSupportedURL( rURL ) ) 737 { 738 if (m_pMedium) 739 delete m_pMedium; 740 741 m_pMedium = new SfxMedium(rURL, STREAM_STD_READ, sal_False); 742 m_pMedium->SetDataAvailableLink( 743 STATIC_LINK(this, OClickableImageBaseModel, DataAvailableLink)); 744 745 // Das XModel suchen, um an die Object-Shell oder zumindest den 746 // Referer zu gelangen. 747 // Das Model findet man allerdings nur beim Laden von HTML-Dokumenten 748 // und dann, wenn die URL in einem bereits geladenen Dokument 749 // geaendert wird. Waehrend des Ladens kommt man nicht an das 750 // Model ran. 751 Reference< XModel > xModel; 752 InterfaceRef xIfc( *this ); 753 while( !xModel.is() && xIfc.is() ) 754 { 755 Reference<XChild> xChild( xIfc, UNO_QUERY ); 756 xIfc = xChild->getParent(); 757 query_interface(xIfc, xModel); 758 } 759 760 // Die Object-Shell suchen, indem wir 761 // ueber alle Object-Shells iterieren und deren XModel mit dem 762 // eigenen vergleichen. Als Optimierung probieren wir aber erstmal 763 // die aktuelle Object-Shell. 764 // wir unser XModel mit dem aller Object 765 SfxObjectShell *pObjSh = 0; 766 767 if( xModel.is() ) 768 { 769 SfxObjectShell *pTestObjSh = SfxObjectShell::Current(); 770 if( pTestObjSh ) 771 { 772 Reference< XModel > xTestModel = pTestObjSh->GetModel(); 773 if( xTestModel == xModel ) 774 pObjSh = pTestObjSh; 775 } 776 if( !pObjSh ) 777 { 778 pTestObjSh = SfxObjectShell::GetFirst(); 779 while( !pObjSh && pTestObjSh ) 780 { 781 Reference< XModel > xTestModel = pTestObjSh->GetModel(); 782 if( xTestModel == xModel ) 783 pObjSh = pTestObjSh; 784 else 785 pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh ); 786 } 787 } 788 } 789 790 #ifdef USE_REGISTER_TRANSFER 791 if( pObjSh ) 792 { 793 // Medium registrieren, damit abgebrochen werden kann 794 pObjSh->RegisterTransfer( *m_pMedium ); 795 796 // Target-Frame uebertragen, damit auch javascript:-URLs 797 // "geladen" werden koennen. 798 const SfxMedium *pShMedium = pObjSh->GetMedium(); 799 if( pShMedium ) 800 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); 801 } 802 else 803 { 804 // Keine Object-Shell, aber ein Medium? Dann uebernehmen wir 805 // zumindest den Referer. 806 if( xModel.is() ) 807 { 808 ::rtl::OUString sReferer( xModel->getURL() ); 809 if( sReferer.getLength() ) 810 m_pMedium->SetReferer( OUStringToString(sReferer, CHARSET_SYSTEM) ); 811 } 812 } 813 #else 814 if( pObjSh ) 815 { 816 // Target-Frame uebertragen, damit auch javascript:-URLs 817 // "geladen" werden koennen. 818 const SfxMedium *pShMedium = pObjSh->GetMedium(); 819 if( pShMedium ) 820 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); 821 } 822 823 if( xModel.is() ) 824 { 825 ::rtl::OUString sReferer( xModel->getURL() ); 826 if( sReferer.getLength() ) 827 m_pMedium->SetReferer( sReferer ); 828 } 829 #endif 830 831 // Downloading-Flag auf sal_True setzen. Es werden dann auch 832 // Data-Available-Links, wenn wir in den Pending-Staus gelangen. 833 m_bDownloading = sal_True; 834 m_bProdStarted = sal_False; 835 836 // Download anstossen (Achtung: Kann auch synchron sein). 837 m_pMedium->DownLoad(STATIC_LINK(this, OClickableImageBaseModel, DownloadDoneLink)); 838 } 839 else 840 { 841 if ( ::svt::GraphicAccess::isSupportedURL( rURL ) ) 842 GetImageProducer()->SetImage( rURL ); 843 GetImageProducer()->startProduction(); 844 } 845 } 846 847 //------------------------------------------------------------------------------ DataAvailable()848 void OClickableImageBaseModel::DataAvailable() 849 { 850 if (!m_bProdStarted) 851 StartProduction(); 852 853 GetImageProducer()->NewDataAvailable(); 854 } 855 856 //------------------------------------------------------------------------------ DownloadDone()857 void OClickableImageBaseModel::DownloadDone() 858 { 859 DataAvailable(); 860 m_bDownloading = sal_False; 861 } 862 863 //------------------------------------------------------------------------------ IMPL_STATIC_LINK(OClickableImageBaseModel,DownloadDoneLink,void *,EMPTYARG)864 IMPL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void*, EMPTYARG ) 865 { 866 ::osl::MutexGuard aGuard( pThis->m_aMutex ); 867 pThis->DownloadDone(); 868 return 0; 869 } 870 871 //------------------------------------------------------------------------------ IMPL_STATIC_LINK(OClickableImageBaseModel,DataAvailableLink,void *,EMPTYARG)872 IMPL_STATIC_LINK( OClickableImageBaseModel, DataAvailableLink, void*, EMPTYARG ) 873 { 874 ::osl::MutexGuard aGuard( pThis->m_aMutex ); 875 pThis->DataAvailable(); 876 return 0; 877 } 878 879 //------------------------------------------------------------------------------ _propertyChanged(const PropertyChangeEvent & rEvt)880 void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt ) 881 { 882 // Wenn eine URL gesetzt worden ist, muss die noch an den ImageProducer 883 // weitergereicht werden. 884 ::osl::MutexGuard aGuard(m_aMutex); 885 SetURL( getString(rEvt.NewValue) ); 886 } 887 888 // ----------------------------------------------------------------------------- getPropertyDefaultByHandle(sal_Int32 nHandle) const889 Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const 890 { 891 switch (nHandle) 892 { 893 case PROPERTY_ID_BUTTONTYPE : return makeAny( FormButtonType_PUSH ); 894 case PROPERTY_ID_TARGET_URL : 895 case PROPERTY_ID_TARGET_FRAME : return makeAny( ::rtl::OUString() ); 896 case PROPERTY_ID_DISPATCHURLINTERNAL : return makeAny( sal_False ); 897 default: 898 return OControlModel::getPropertyDefaultByHandle(nHandle); 899 } 900 } 901 902 //================================================================== 903 // OImageProducerThread_Impl 904 //================================================================== 905 //------------------------------------------------------------------ cloneEvent(const EventObject * _pEvt) const906 EventObject* OImageProducerThread_Impl::cloneEvent( const EventObject* _pEvt ) const 907 { 908 return new EventObject( *_pEvt ); 909 } 910 911 //------------------------------------------------------------------ processEvent(::cppu::OComponentHelper * pCompImpl,const EventObject * pEvt,const Reference<XControl> &,sal_Bool)912 void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper *pCompImpl, 913 const EventObject* pEvt, 914 const Reference<XControl>&, 915 sal_Bool ) 916 { 917 ((OClickableImageBaseControl *)pCompImpl)->actionPerformed_Impl( sal_True, *(MouseEvent *)pEvt ); 918 } 919 920 //......................................................................... 921 } // namespace frm 922 //......................................................................... 923