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) throw (RuntimeException) 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) throw( RuntimeException ) 120 { 121 m_aApproveActionListeners.addInterface(l); 122 } 123 124 //------------------------------------------------------------------------------ removeApproveActionListener(const Reference<XApproveActionListener> & l)125 void OClickableImageBaseControl::removeApproveActionListener( 126 const Reference<XApproveActionListener>& l) throw( RuntimeException ) 127 { 128 m_aApproveActionListeners.removeInterface(l); 129 } 130 131 //-------------------------------------------------------------------- registerDispatchProviderInterceptor(const Reference<XDispatchProviderInterceptor> & _rxInterceptor)132 void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) 133 { 134 m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor ); 135 } 136 137 //-------------------------------------------------------------------- releaseDispatchProviderInterceptor(const Reference<XDispatchProviderInterceptor> & _rxInterceptor)138 void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) 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 ) throw (NoSupportException, RuntimeException) 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 ) throw (NoSupportException, RuntimeException) 361 { 362 m_aSubmissionVetoListeners.removeInterface( listener ); 363 } 364 365 //-------------------------------------------------------------------- submitWithInteraction(const Reference<XInteractionHandler> & _rxHandler)366 void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler ) throw (VetoException, WrappedTargetException, RuntimeException) 367 { 368 implSubmit( MouseEvent(), _rxHandler ); 369 } 370 371 //-------------------------------------------------------------------- submit()372 void SAL_CALL OClickableImageBaseControl::submit( ) throw (VetoException, WrappedTargetException, RuntimeException) 373 { 374 implSubmit( MouseEvent(), NULL ); 375 } 376 377 //-------------------------------------------------------------------- getSupportedServiceNames()378 Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseControl::getSupportedServiceNames( ) throw (RuntimeException) 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 ) SAL_THROW((VetoException, WrappedTargetException, RuntimeException)) 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 ) throw (RuntimeException) 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 ) throw (RuntimeException) 548 { 549 ImageModelMethodGuard aGuard( *this ); 550 GetImageProducer()->removeConsumer( _rxConsumer ); 551 } 552 553 //-------------------------------------------------------------------- startProduction()554 void SAL_CALL OClickableImageBaseModel::startProduction( ) throw (RuntimeException) 555 { 556 ImageModelMethodGuard aGuard( *this ); 557 GetImageProducer()->startProduction(); 558 } 559 560 //-------------------------------------------------------------------- getSubmission()561 Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission() throw (RuntimeException) 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 ) throw (RuntimeException) 568 { 569 m_xSubmissionDelegate = _submission; 570 } 571 572 //-------------------------------------------------------------------- getSupportedServiceNames()573 Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseModel::getSupportedServiceNames( ) throw (RuntimeException) 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) throw (RuntimeException) 601 { 602 // order matters: 603 // we definately 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) throw ( Exception) 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 throw( IllegalArgumentException ) 664 { 665 switch (nHandle) 666 { 667 case PROPERTY_ID_BUTTONTYPE : 668 return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType ); 669 670 case PROPERTY_ID_TARGET_URL : 671 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL); 672 673 case PROPERTY_ID_TARGET_FRAME : 674 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame); 675 676 case PROPERTY_ID_DISPATCHURLINTERNAL : 677 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal); 678 679 default: 680 return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); 681 } 682 } 683 684 //------------------------------------------------------------------------------ StartProduction()685 void OClickableImageBaseModel::StartProduction() 686 { 687 ImageProducer *pImgProd = GetImageProducer(); 688 // grab the ImageURL 689 rtl::OUString sURL; 690 getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ImageURL") ) ) >>= sURL; 691 if (!m_pMedium) 692 { 693 if ( ::svt::GraphicAccess::isSupportedURL( sURL ) ) 694 pImgProd->SetImage( sURL ); 695 else 696 // caution: the medium may be NULL if somebody gave us a invalid URL to work with 697 // 11/24/2000 - 79667 - FS 698 pImgProd->SetImage(String()); 699 m_bDownloading = sal_False; 700 return; 701 } 702 if (m_pMedium->GetErrorCode()==0) 703 { 704 SvStream* pStream = m_pMedium->GetInStream(); 705 706 pImgProd->SetImage(*pStream); 707 pImgProd->startProduction(); 708 m_bProdStarted = sal_True; 709 } 710 else 711 { 712 pImgProd->SetImage(String()); 713 delete m_pMedium; 714 m_pMedium = 0; 715 m_bDownloading = sal_False; 716 } 717 } 718 719 //------------------------------------------------------------------------------ SetURL(const::rtl::OUString & rURL)720 void OClickableImageBaseModel::SetURL( const ::rtl::OUString& rURL ) 721 { 722 if (m_pMedium || !rURL.getLength()) 723 { 724 // Den Stream am Producer freigeben, bevor das Medium geloscht wird. 725 GetImageProducer()->SetImage(String()); 726 delete m_pMedium; 727 m_pMedium = NULL; 728 } 729 730 // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first 731 // 23.01.2001 - 81927 - FS 732 INetURLObject aUrl(rURL); 733 if (INET_PROT_NOT_VALID == aUrl.GetProtocol()) 734 // we treat an invalid URL like we would treat no URL 735 return; 736 737 if (rURL.getLength() && !::svt::GraphicAccess::isSupportedURL( rURL ) ) 738 { 739 if (m_pMedium) 740 delete m_pMedium; 741 742 m_pMedium = new SfxMedium(rURL, STREAM_STD_READ, sal_False); 743 m_pMedium->SetDataAvailableLink( 744 STATIC_LINK(this, OClickableImageBaseModel, DataAvailableLink)); 745 746 // Das XModel suchen, um an die Object-Shell oder zumindest den 747 // Referer zu gelangen. 748 // Das Model findet man allerdings nur beim Laden von HTML-Dokumenten 749 // und dann, wenn die URL in einem bereits geladenen Dokument 750 // geaendert wird. Waehrend des Ladens kommt man nicht an das 751 // Model ran. 752 Reference< XModel > xModel; 753 InterfaceRef xIfc( *this ); 754 while( !xModel.is() && xIfc.is() ) 755 { 756 Reference<XChild> xChild( xIfc, UNO_QUERY ); 757 xIfc = xChild->getParent(); 758 query_interface(xIfc, xModel); 759 } 760 761 // Die Object-Shell suchen, indem wir 762 // ueber alle Object-Shells iterieren und deren XModel mit dem 763 // eigenen vergleichen. Als Optimierung probieren wir aber erstmal 764 // die aktuelle Object-Shell. 765 // wir unser XModel mit dem aller Object 766 SfxObjectShell *pObjSh = 0; 767 768 if( xModel.is() ) 769 { 770 SfxObjectShell *pTestObjSh = SfxObjectShell::Current(); 771 if( pTestObjSh ) 772 { 773 Reference< XModel > xTestModel = pTestObjSh->GetModel(); 774 if( xTestModel == xModel ) 775 pObjSh = pTestObjSh; 776 } 777 if( !pObjSh ) 778 { 779 pTestObjSh = SfxObjectShell::GetFirst(); 780 while( !pObjSh && pTestObjSh ) 781 { 782 Reference< XModel > xTestModel = pTestObjSh->GetModel(); 783 if( xTestModel == xModel ) 784 pObjSh = pTestObjSh; 785 else 786 pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh ); 787 } 788 } 789 } 790 791 #ifdef USE_REGISTER_TRANSFER 792 if( pObjSh ) 793 { 794 // Medium registrieren, damit abgebrochen werden kann 795 pObjSh->RegisterTransfer( *m_pMedium ); 796 797 // Target-Frame uebertragen, damit auch javascript:-URLs 798 // "geladen" werden koennen. 799 const SfxMedium *pShMedium = pObjSh->GetMedium(); 800 if( pShMedium ) 801 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); 802 } 803 else 804 { 805 // Keine Object-Shell, aber ein Medium? Dann uebernehmen wir 806 // zumindest den Referer. 807 if( xModel.is() ) 808 { 809 ::rtl::OUString sReferer( xModel->getURL() ); 810 if( sReferer.getLength() ) 811 m_pMedium->SetReferer( OUStringToString(sReferer, CHARSET_SYSTEM) ); 812 } 813 } 814 #else 815 if( pObjSh ) 816 { 817 // Target-Frame uebertragen, damit auch javascript:-URLs 818 // "geladen" werden koennen. 819 const SfxMedium *pShMedium = pObjSh->GetMedium(); 820 if( pShMedium ) 821 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); 822 } 823 824 if( xModel.is() ) 825 { 826 ::rtl::OUString sReferer( xModel->getURL() ); 827 if( sReferer.getLength() ) 828 m_pMedium->SetReferer( sReferer ); 829 } 830 #endif 831 832 // Downloading-Flag auf sal_True setzen. Es werden dann auch 833 // Data-Available-Links, wenn wir in den Pending-Staus gelangen. 834 m_bDownloading = sal_True; 835 m_bProdStarted = sal_False; 836 837 // Download anstossen (Achtung: Kann auch synchron sein). 838 m_pMedium->DownLoad(STATIC_LINK(this, OClickableImageBaseModel, DownloadDoneLink)); 839 } 840 else 841 { 842 if ( ::svt::GraphicAccess::isSupportedURL( rURL ) ) 843 GetImageProducer()->SetImage( rURL ); 844 GetImageProducer()->startProduction(); 845 } 846 } 847 848 //------------------------------------------------------------------------------ DataAvailable()849 void OClickableImageBaseModel::DataAvailable() 850 { 851 if (!m_bProdStarted) 852 StartProduction(); 853 854 GetImageProducer()->NewDataAvailable(); 855 } 856 857 //------------------------------------------------------------------------------ DownloadDone()858 void OClickableImageBaseModel::DownloadDone() 859 { 860 DataAvailable(); 861 m_bDownloading = sal_False; 862 } 863 864 //------------------------------------------------------------------------------ IMPL_STATIC_LINK(OClickableImageBaseModel,DownloadDoneLink,void *,EMPTYARG)865 IMPL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void*, EMPTYARG ) 866 { 867 ::osl::MutexGuard aGuard( pThis->m_aMutex ); 868 pThis->DownloadDone(); 869 return 0; 870 } 871 872 //------------------------------------------------------------------------------ IMPL_STATIC_LINK(OClickableImageBaseModel,DataAvailableLink,void *,EMPTYARG)873 IMPL_STATIC_LINK( OClickableImageBaseModel, DataAvailableLink, void*, EMPTYARG ) 874 { 875 ::osl::MutexGuard aGuard( pThis->m_aMutex ); 876 pThis->DataAvailable(); 877 return 0; 878 } 879 880 //------------------------------------------------------------------------------ _propertyChanged(const PropertyChangeEvent & rEvt)881 void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt ) 882 throw( RuntimeException ) 883 { 884 // Wenn eine URL gesetzt worden ist, muss die noch an den ImageProducer 885 // weitergereicht werden. 886 ::osl::MutexGuard aGuard(m_aMutex); 887 SetURL( getString(rEvt.NewValue) ); 888 } 889 890 // ----------------------------------------------------------------------------- getPropertyDefaultByHandle(sal_Int32 nHandle) const891 Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const 892 { 893 switch (nHandle) 894 { 895 case PROPERTY_ID_BUTTONTYPE : return makeAny( FormButtonType_PUSH ); 896 case PROPERTY_ID_TARGET_URL : 897 case PROPERTY_ID_TARGET_FRAME : return makeAny( ::rtl::OUString() ); 898 case PROPERTY_ID_DISPATCHURLINTERNAL : return makeAny( sal_False ); 899 default: 900 return OControlModel::getPropertyDefaultByHandle(nHandle); 901 } 902 } 903 904 //================================================================== 905 // OImageProducerThread_Impl 906 //================================================================== 907 //------------------------------------------------------------------ cloneEvent(const EventObject * _pEvt) const908 EventObject* OImageProducerThread_Impl::cloneEvent( const EventObject* _pEvt ) const 909 { 910 return new EventObject( *_pEvt ); 911 } 912 913 //------------------------------------------------------------------ processEvent(::cppu::OComponentHelper * pCompImpl,const EventObject * pEvt,const Reference<XControl> &,sal_Bool)914 void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper *pCompImpl, 915 const EventObject* pEvt, 916 const Reference<XControl>&, 917 sal_Bool ) 918 { 919 ((OClickableImageBaseControl *)pCompImpl)->actionPerformed_Impl( sal_True, *(MouseEvent *)pEvt ); 920 } 921 922 //......................................................................... 923 } // namespace frm 924 //......................................................................... 925 926