bump product version to 5.0.4.1
[LibreOffice.git] / forms / source / component / clickableimage.cxx
blob8ce0de6419173d7a8cff4cd429efe43d572e253f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "clickableimage.hxx"
21 #include "controlfeatureinterception.hxx"
22 #include "urltransformer.hxx"
23 #include "componenttools.hxx"
24 #include <com/sun/star/form/XSubmit.hpp>
25 #include <com/sun/star/awt/SystemPointer.hpp>
26 #include <com/sun/star/form/FormComponentType.hpp>
27 #include <com/sun/star/frame/XDispatch.hpp>
28 #include <com/sun/star/frame/XDispatchProvider.hpp>
29 #include <com/sun/star/frame/FrameSearchFlag.hpp>
30 #include <com/sun/star/frame/XController.hpp>
31 #include <com/sun/star/frame/XFrame.hpp>
32 #include <com/sun/star/awt/ActionEvent.hpp>
33 #include <com/sun/star/awt/XActionListener.hpp>
34 #include <com/sun/star/graphic/XGraphic.hpp>
35 #include <com/sun/star/graphic/GraphicObject.hpp>
36 #include <tools/urlobj.hxx>
37 #include <tools/debug.hxx>
38 #include <vcl/svapp.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <sfx2/objsh.hxx>
41 #include <osl/mutex.hxx>
42 #include "services.hxx"
43 #include <comphelper/container.hxx>
44 #include <comphelper/listenernotification.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <svtools/imageresourceaccess.hxx>
47 #define LOCAL_URL_PREFIX '#'
50 namespace frm
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::sdb;
56 using namespace ::com::sun::star::sdbc;
57 using namespace ::com::sun::star::sdbcx;
58 using namespace ::com::sun::star::beans;
59 using namespace ::com::sun::star::container;
60 using namespace ::com::sun::star::form;
61 using namespace ::com::sun::star::awt;
62 using namespace ::com::sun::star::io;
63 using namespace ::com::sun::star::lang;
64 using namespace ::com::sun::star::util;
65 using namespace ::com::sun::star::frame;
66 using namespace ::com::sun::star::form::submission;
67 using namespace ::com::sun::star::graphic;
68 using ::com::sun::star::awt::MouseEvent;
69 using ::com::sun::star::task::XInteractionHandler;
72 // OClickableImageBaseControl
75 Sequence<Type> OClickableImageBaseControl::_getTypes()
77 static Sequence<Type> aTypes;
78 if (!aTypes.getLength())
79 aTypes = concatSequences(OControl::_getTypes(), OClickableImageBaseControl_BASE::getTypes());
80 return aTypes;
84 OClickableImageBaseControl::OClickableImageBaseControl(const Reference<XComponentContext>& _rxFactory, const OUString& _aService)
85 :OControl(_rxFactory, _aService)
86 ,m_pThread(NULL)
87 ,m_aSubmissionVetoListeners( m_aMutex )
88 ,m_aApproveActionListeners( m_aMutex )
89 ,m_aActionListeners( m_aMutex )
91 m_pFeatureInterception.reset( new ControlFeatureInterception( _rxFactory ) );
95 OClickableImageBaseControl::~OClickableImageBaseControl()
97 if (!OComponentHelper::rBHelper.bDisposed)
99 acquire();
100 dispose();
104 // UNO Binding
106 Any SAL_CALL OClickableImageBaseControl::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
108 Any aReturn = OControl::queryAggregation(_rType);
109 if (!aReturn.hasValue())
110 aReturn = OClickableImageBaseControl_BASE::queryInterface(_rType);
111 return aReturn;
114 // XApproveActionBroadcaster
116 void OClickableImageBaseControl::addApproveActionListener(
117 const Reference<XApproveActionListener>& l) throw( RuntimeException, std::exception )
119 m_aApproveActionListeners.addInterface(l);
123 void OClickableImageBaseControl::removeApproveActionListener(
124 const Reference<XApproveActionListener>& l) throw( RuntimeException, std::exception )
126 m_aApproveActionListeners.removeInterface(l);
130 void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException, std::exception)
132 m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor );
136 void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException, std::exception)
138 m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor );
141 // OComponentHelper
143 void OClickableImageBaseControl::disposing()
145 EventObject aEvent( static_cast< XWeak* >( this ) );
146 m_aApproveActionListeners.disposeAndClear( aEvent );
147 m_aActionListeners.disposeAndClear( aEvent );
148 m_aSubmissionVetoListeners.disposeAndClear( aEvent );
149 m_pFeatureInterception->dispose();
152 ::osl::MutexGuard aGuard( m_aMutex );
153 if( m_pThread )
155 m_pThread->release();
156 m_pThread = NULL;
160 OControl::disposing();
164 OImageProducerThread_Impl* OClickableImageBaseControl::getImageProducerThread()
166 if ( !m_pThread )
168 m_pThread = new OImageProducerThread_Impl( this );
169 m_pThread->acquire();
170 m_pThread->create();
172 return m_pThread;
176 bool OClickableImageBaseControl::approveAction( )
178 bool bCancelled = false;
179 EventObject aEvent( static_cast< XWeak* >( this ) );
181 ::cppu::OInterfaceIteratorHelper aIter( m_aApproveActionListeners );
182 while( !bCancelled && aIter.hasMoreElements() )
184 // Every approveAction method must be thread-safe!
185 if( !static_cast< XApproveActionListener* >( aIter.next() )->approveAction( aEvent ) )
186 bCancelled = true;
189 return !bCancelled;
193 // This method is also called from a thread and thus must be thread-safe.
194 void OClickableImageBaseControl::actionPerformed_Impl(bool bNotifyListener, const MouseEvent& rEvt)
196 if( bNotifyListener )
198 if ( !approveAction() )
199 return;
202 // Whether the rest of the code is thread-safe, one can't tell. Therefore
203 // we do most of the work on a locked solar mutex.
204 Reference<XPropertySet> xSet;
205 Reference< XInterface > xModelsParent;
206 FormButtonType eButtonType = FormButtonType_PUSH;
208 SolarMutexGuard aGuard;
210 // Get parent
211 Reference<XFormComponent> xComp(getModel(), UNO_QUERY);
212 if (!xComp.is())
213 return;
215 xModelsParent = xComp->getParent();
216 if (!xModelsParent.is())
217 return;
219 // Which button type?
220 xSet.set(xComp, css::uno::UNO_QUERY);
221 if ( !xSet.is() )
222 return;
223 xSet->getPropertyValue(PROPERTY_BUTTONTYPE) >>= eButtonType;
226 switch (eButtonType)
228 case FormButtonType_RESET:
230 // Reset methods must be thread-safe!
231 Reference<XReset> xReset(xModelsParent, UNO_QUERY);
232 if (!xReset.is())
233 return;
235 xReset->reset();
237 break;
239 case FormButtonType_SUBMIT:
241 // if some outer component can provide an interaction handler, use it
242 Reference< XInteractionHandler > xHandler( m_pFeatureInterception->queryDispatch( "private:/InteractionHandler" ), UNO_QUERY );
245 implSubmit( rEvt, xHandler );
247 catch( const Exception& )
249 // ignore
252 break;
254 case FormButtonType_URL:
256 SolarMutexGuard aGuard;
258 Reference< XModel > xModel = getXModel(xModelsParent);
259 if (!xModel.is())
260 return;
263 // Execute URL now
264 Reference< XController > xController = xModel->getCurrentController();
265 if (!xController.is())
266 return;
268 Reference< XFrame > xFrame = xController->getFrame();
269 if( !xFrame.is() )
270 return;
272 URL aURL;
273 aURL.Complete =
274 getString(xSet->getPropertyValue(PROPERTY_TARGET_URL));
276 if (!aURL.Complete.isEmpty() && (LOCAL_URL_PREFIX == aURL.Complete[0]))
277 { // FIXME: The URL contains a local URL only. Since the URLTransformer does not handle this case correctly
278 // (it can't: it does not know the document URL), we have to take care for this ourself.
279 // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all
280 // URLs have to be absolute), but for compatibility reasons this is no option.
281 // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it
282 // could be "#mark" as well.
283 // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete
284 // solution would be:
285 // * recognize URLs consisting of a mark only while _reading_ the document
286 // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to
287 // transform such mark-only URLs into correct absolute URLs
288 // * at the UI, show only the mark
289 // * !!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems
290 // rather impossible !!!
291 aURL.Mark = aURL.Complete;
292 aURL.Complete = xModel->getURL();
293 aURL.Complete += aURL.Mark;
296 bool bDispatchUrlInternal = false;
297 xSet->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL) >>= bDispatchUrlInternal;
298 if ( bDispatchUrlInternal )
300 m_pFeatureInterception->getTransformer().parseSmartWithAsciiProtocol( aURL, INET_FILE_SCHEME );
302 OUString aTargetFrame;
303 xSet->getPropertyValue(PROPERTY_TARGET_FRAME) >>= aTargetFrame;
305 Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch( aURL, aTargetFrame,
306 FrameSearchFlag::SELF | FrameSearchFlag::PARENT |
307 FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE );
309 Sequence<PropertyValue> aArgs(1);
310 PropertyValue& rProp = aArgs.getArray()[0];
311 rProp.Name = "Referer";
312 rProp.Value <<= xModel->getURL();
314 if (xDisp.is())
315 xDisp->dispatch( aURL, aArgs );
317 else
319 URL aHyperLink = m_pFeatureInterception->getTransformer().getStrictURLFromAscii( ".uno:OpenHyperlink" );
321 Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aHyperLink, OUString() , 0);
323 if ( xDisp.is() )
325 Sequence<PropertyValue> aProps(3);
326 aProps[0].Name = "URL";
327 aProps[0].Value <<= aURL.Complete;
329 aProps[1].Name = "FrameName";
330 aProps[1].Value = xSet->getPropertyValue(PROPERTY_TARGET_FRAME);
332 aProps[2].Name = "Referer";
333 aProps[2].Value <<= xModel->getURL();
335 xDisp->dispatch( aHyperLink, aProps );
338 } break;
339 default:
341 // notify the action listeners for a push button
342 ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand);
343 m_aActionListeners.notifyEach( &XActionListener::actionPerformed, aEvt );
350 void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException, std::exception)
352 m_aSubmissionVetoListeners.addInterface( listener );
356 void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException, std::exception)
358 m_aSubmissionVetoListeners.removeInterface( listener );
362 void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler ) throw (VetoException, WrappedTargetException, RuntimeException, std::exception)
364 implSubmit( MouseEvent(), _rxHandler );
368 void SAL_CALL OClickableImageBaseControl::submit( ) throw (VetoException, WrappedTargetException, RuntimeException, std::exception)
370 implSubmit( MouseEvent(), NULL );
374 Sequence< OUString > SAL_CALL OClickableImageBaseControl::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
376 Sequence< OUString > aSupported = OControl::getSupportedServiceNames();
377 aSupported.realloc( aSupported.getLength() + 1 );
379 OUString* pArray = aSupported.getArray();
380 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON;
382 return aSupported;
386 void OClickableImageBaseControl::implSubmit( const MouseEvent& _rEvent, const Reference< XInteractionHandler >& _rxHandler )
390 // allow the veto listeners to join the game
391 m_aSubmissionVetoListeners.notifyEach( &XSubmissionVetoListener::submitting, EventObject( *this ) );
393 // see whether there's an "submit interceptor" set at our model
394 Reference< submission::XSubmissionSupplier > xSubmissionSupp( getModel(), UNO_QUERY );
395 Reference< XSubmission > xSubmission;
396 if ( xSubmissionSupp.is() )
397 xSubmission = xSubmissionSupp->getSubmission();
399 if ( xSubmission.is() )
401 if ( !_rxHandler.is() )
402 xSubmission->submit();
403 else
404 xSubmission->submitWithInteraction( _rxHandler );
406 else
408 // no "interceptor" -> ordinary (old-way) submission
409 Reference< XChild > xChild( getModel(), UNO_QUERY );
410 Reference< XSubmit > xParentSubmission;
411 if ( xChild.is() )
412 xParentSubmission.set(xChild->getParent(), css::uno::UNO_QUERY);
413 if ( xParentSubmission.is() )
414 xParentSubmission->submit( this, _rEvent );
417 catch( const VetoException& )
419 // allowed to leave
420 throw;
422 catch( const RuntimeException& )
424 // allowed to leave
425 throw;
427 catch( const WrappedTargetException& )
429 // allowed to leave
430 throw;
432 catch( const Exception& e )
434 OSL_FAIL( "OClickableImageBaseControl::implSubmit: caught an unknown exception!" );
435 throw WrappedTargetException( OUString(), *this, makeAny( e ) );
440 // OClickableImageBaseModel
443 Sequence<Type> OClickableImageBaseModel::_getTypes()
445 return concatSequences(
446 OControlModel::_getTypes(),
447 OClickableImageBaseModel_Base::getTypes()
453 OClickableImageBaseModel::OClickableImageBaseModel( const Reference< XComponentContext >& _rxFactory, const OUString& _rUnoControlModelTypeName,
454 const OUString& rDefault )
455 :OControlModel( _rxFactory, _rUnoControlModelTypeName, rDefault )
456 ,OPropertyChangeListener(m_aMutex)
457 ,m_xGraphicObject()
458 ,m_pMedium(NULL)
459 ,m_pProducer( NULL )
460 ,m_bDispatchUrlInternal(false)
461 ,m_bDownloading(false)
462 ,m_bProdStarted(false)
464 implConstruct();
465 m_eButtonType = FormButtonType_PUSH;
469 OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel* _pOriginal, const Reference<XComponentContext>& _rxFactory )
470 :OControlModel( _pOriginal, _rxFactory )
471 ,OPropertyChangeListener( m_aMutex )
472 ,m_xGraphicObject( _pOriginal->m_xGraphicObject )
473 ,m_pMedium( NULL )
474 ,m_pProducer( NULL )
475 ,m_bDispatchUrlInternal(false)
476 ,m_bDownloading( false )
477 ,m_bProdStarted( false )
479 implConstruct();
481 // copy properties
482 m_eButtonType = _pOriginal->m_eButtonType;
483 m_sTargetURL = _pOriginal->m_sTargetURL;
484 m_sTargetFrame = _pOriginal->m_sTargetFrame;
485 m_bDispatchUrlInternal = _pOriginal->m_bDispatchUrlInternal;
489 void OClickableImageBaseModel::implInitializeImageURL( )
491 osl_atomic_increment( &m_refCount );
493 // simulate a propertyChanged event for the ImageURL
494 Any aImageURL;
495 getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL );
496 _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL, sal_False, PROPERTY_ID_IMAGE_URL, Any( ), aImageURL ) );
498 osl_atomic_decrement( &m_refCount );
502 void OClickableImageBaseModel::implConstruct()
504 m_pProducer = new ImageProducer;
505 m_pProducer->SetDoneHdl( LINK( this, OClickableImageBaseModel, OnImageImportDone ) );
506 osl_atomic_increment( &m_refCount );
508 m_xProducer = m_pProducer;
510 if ( m_xAggregateSet.is() )
512 OPropertyChangeMultiplexer* pMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet );
513 pMultiplexer->addProperty( PROPERTY_IMAGE_URL );
516 osl_atomic_decrement(&m_refCount);
520 OClickableImageBaseModel::~OClickableImageBaseModel()
522 if (!OComponentHelper::rBHelper.bDisposed)
524 acquire();
525 dispose();
527 DBG_ASSERT(m_pMedium == NULL, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ...");
528 // This should be cleaned up at least in the dispose
532 // XImageProducer
534 void SAL_CALL OClickableImageBaseModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException, std::exception)
536 ImageModelMethodGuard aGuard( *this );
537 GetImageProducer()->addConsumer( _rxConsumer );
541 void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException, std::exception)
543 ImageModelMethodGuard aGuard( *this );
544 GetImageProducer()->removeConsumer( _rxConsumer );
548 void SAL_CALL OClickableImageBaseModel::startProduction( ) throw (RuntimeException, std::exception)
550 ImageModelMethodGuard aGuard( *this );
551 GetImageProducer()->startProduction();
555 Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission() throw (RuntimeException, std::exception)
557 return m_xSubmissionDelegate;
561 void SAL_CALL OClickableImageBaseModel::setSubmission( const Reference< submission::XSubmission >& _submission ) throw (RuntimeException, std::exception)
563 m_xSubmissionDelegate = _submission;
567 Sequence< OUString > SAL_CALL OClickableImageBaseModel::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
569 Sequence< OUString > aSupported = OControlModel::getSupportedServiceNames();
570 aSupported.realloc( aSupported.getLength() + 1 );
572 OUString* pArray = aSupported.getArray();
573 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON;
575 return aSupported;
578 // OComponentHelper
580 void OClickableImageBaseModel::disposing()
582 OControlModel::disposing();
583 if (m_pMedium)
585 delete m_pMedium;
586 m_pMedium = NULL;
589 m_xProducer = NULL;
590 m_pProducer = NULL;
594 Any SAL_CALL OClickableImageBaseModel::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
596 // order matters:
597 // we definitely want to "override" the XImageProducer interface of our aggregate,
598 // thus check OClickableImageBaseModel_Base (which provides this) first
599 Any aReturn = OClickableImageBaseModel_Base::queryInterface( _rType );
601 // BUT: _don't_ let it feel responsible for the XTypeProvider interface
602 // (as this is implemented by our base class in the proper way)
603 if ( _rType.equals( cppu::UnoType<XTypeProvider>::get() )
604 || !aReturn.hasValue()
606 aReturn = OControlModel::queryAggregation( _rType );
608 return aReturn;
612 void OClickableImageBaseModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
614 switch (nHandle)
616 case PROPERTY_ID_BUTTONTYPE : rValue <<= m_eButtonType; break;
617 case PROPERTY_ID_TARGET_URL : rValue <<= m_sTargetURL; break;
618 case PROPERTY_ID_TARGET_FRAME : rValue <<= m_sTargetFrame; break;
619 case PROPERTY_ID_DISPATCHURLINTERNAL : rValue <<= m_bDispatchUrlInternal; break;
620 default:
621 OControlModel::getFastPropertyValue(rValue, nHandle);
626 void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( Exception, std::exception)
628 switch (nHandle)
630 case PROPERTY_ID_BUTTONTYPE :
631 DBG_ASSERT(isA(rValue, static_cast<FormButtonType*>(NULL)), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
632 rValue >>= m_eButtonType;
633 break;
635 case PROPERTY_ID_TARGET_URL :
636 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
637 rValue >>= m_sTargetURL;
638 break;
640 case PROPERTY_ID_TARGET_FRAME :
641 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
642 rValue >>= m_sTargetFrame;
643 break;
645 case PROPERTY_ID_DISPATCHURLINTERNAL:
646 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
647 rValue >>= m_bDispatchUrlInternal;
648 break;
650 default:
651 OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue);
656 sal_Bool OClickableImageBaseModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
657 throw( IllegalArgumentException )
659 switch (nHandle)
661 case PROPERTY_ID_BUTTONTYPE :
662 return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType );
664 case PROPERTY_ID_TARGET_URL :
665 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL);
667 case PROPERTY_ID_TARGET_FRAME :
668 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame);
670 case PROPERTY_ID_DISPATCHURLINTERNAL :
671 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal);
673 default:
674 return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
679 void OClickableImageBaseModel::StartProduction()
681 ImageProducer *pImgProd = GetImageProducer();
682 // grab the ImageURL
683 OUString sURL;
684 getPropertyValue("ImageURL") >>= sURL;
685 if (!m_pMedium)
687 if ( ::svt::GraphicAccess::isSupportedURL( sURL ) )
688 pImgProd->SetImage( sURL );
689 else
690 // caution: the medium may be NULL if somebody gave us an invalid URL to work with
691 pImgProd->SetImage(OUString());
692 m_bDownloading = false;
693 return;
695 if (m_pMedium->GetErrorCode()==0)
697 SvStream* pStream = m_pMedium->GetInStream();
699 pImgProd->SetImage(*pStream);
700 pImgProd->startProduction();
701 m_bProdStarted = true;
703 else
705 pImgProd->SetImage(OUString());
706 delete m_pMedium;
707 m_pMedium = 0;
708 m_bDownloading = false;
713 void OClickableImageBaseModel::SetURL( const OUString& rURL )
715 if (m_pMedium || rURL.isEmpty())
717 // Free the stream at the Producer, before the medium is deleted
718 GetImageProducer()->SetImage(OUString());
719 delete m_pMedium;
720 m_pMedium = NULL;
723 // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first
724 INetURLObject aUrl(rURL);
725 if (INetProtocol::NotValid == aUrl.GetProtocol())
726 // we treat an invalid URL like we would treat no URL
727 return;
729 if (!rURL.isEmpty() && !::svt::GraphicAccess::isSupportedURL( rURL ) )
731 if (m_pMedium)
732 delete m_pMedium;
734 m_pMedium = new SfxMedium(rURL, STREAM_STD_READ);
736 // Find the XModel to get to the Object shell or at least the
737 // Referer.
738 // There's only a Model if we load HTML documents and the URL is
739 // changed in a document that is already loaded. There's no way
740 // we can get to the Model during loading.
741 Reference< XModel > xModel;
742 InterfaceRef xIfc( *this );
743 while( !xModel.is() && xIfc.is() )
745 Reference<XChild> xChild( xIfc, UNO_QUERY );
746 xIfc = xChild->getParent();
747 xModel.set(xIfc, css::uno::UNO_QUERY);
750 // Search for the Object shell by iterating over all Object shells
751 // and comparing their XModel to ourĀ“s.
752 // As an optimization, we try the current Object shell first.
753 SfxObjectShell *pObjSh = 0;
755 if( xModel.is() )
757 SfxObjectShell *pTestObjSh = SfxObjectShell::Current();
758 if( pTestObjSh )
760 Reference< XModel > xTestModel = pTestObjSh->GetModel();
761 if( xTestModel == xModel )
762 pObjSh = pTestObjSh;
764 if( !pObjSh )
766 pTestObjSh = SfxObjectShell::GetFirst();
767 while( !pObjSh && pTestObjSh )
769 Reference< XModel > xTestModel = pTestObjSh->GetModel();
770 if( xTestModel == xModel )
771 pObjSh = pTestObjSh;
772 else
773 pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh );
778 #ifdef USE_REGISTER_TRANSFER
779 if( pObjSh )
781 // Transfer target frame, so that javascript: URLs
782 // can also be "loaded"
783 const SfxMedium *pShMedium = pObjSh->GetMedium();
784 if( pShMedium )
785 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame());
787 #else
788 if( pObjSh )
790 // Transfer target frame, so that javascript: URLs
791 // can also be "loaded"
792 const SfxMedium *pShMedium = pObjSh->GetMedium();
793 if( pShMedium )
794 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame());
796 #endif
798 // Set downloading flag to true. They will be Data Available Links,
799 // if get to the pending staus.
800 m_bDownloading = true;
801 m_bProdStarted = false;
803 // Kick off download (caution: can be synchronous).
804 m_pMedium->Download(LINK(this, OClickableImageBaseModel, DownloadDoneLink));
806 else
808 if ( ::svt::GraphicAccess::isSupportedURL( rURL ) )
809 GetImageProducer()->SetImage( rURL );
810 GetImageProducer()->startProduction();
815 void OClickableImageBaseModel::DataAvailable()
817 if (!m_bProdStarted)
818 StartProduction();
820 GetImageProducer()->NewDataAvailable();
824 void OClickableImageBaseModel::DownloadDone()
826 DataAvailable();
827 m_bDownloading = false;
831 IMPL_LINK_NOARG( OClickableImageBaseModel, DownloadDoneLink )
833 ::osl::MutexGuard aGuard( m_aMutex );
834 DownloadDone();
835 return 0;
839 void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt )
840 throw( RuntimeException )
842 // If a URL was set, it needs to be passed onto the ImageProducer.
843 ::osl::MutexGuard aGuard(m_aMutex);
844 SetURL( getString(rEvt.NewValue) );
848 Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
850 switch (nHandle)
852 case PROPERTY_ID_BUTTONTYPE : return makeAny( FormButtonType_PUSH );
853 case PROPERTY_ID_TARGET_URL :
854 case PROPERTY_ID_TARGET_FRAME : return makeAny( OUString() );
855 case PROPERTY_ID_DISPATCHURLINTERNAL : return makeAny( sal_False );
856 default:
857 return OControlModel::getPropertyDefaultByHandle(nHandle);
861 IMPL_LINK( OClickableImageBaseModel, OnImageImportDone, Graphic*, i_pGraphic )
863 const Reference< XGraphic > xGraphic( i_pGraphic != NULL ? Graphic(i_pGraphic->GetBitmapEx()).GetXGraphic() : NULL );
864 if ( !xGraphic.is() )
866 m_xGraphicObject.clear();
868 else
870 m_xGraphicObject = css::graphic::GraphicObject::create( m_xContext );
871 m_xGraphicObject->setGraphic( xGraphic );
873 return 1L;
877 // OImageProducerThread_Impl
880 EventObject* OImageProducerThread_Impl::cloneEvent( const EventObject* _pEvt ) const
882 return new EventObject( *_pEvt );
886 void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper *pCompImpl,
887 const EventObject* pEvt,
888 const Reference<XControl>&,
889 bool )
891 static_cast<OClickableImageBaseControl *>(pCompImpl)->actionPerformed_Impl( true, *static_cast<const MouseEvent *>(pEvt) );
895 } // namespace frm
898 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */