1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 '#'
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());
84 OClickableImageBaseControl::OClickableImageBaseControl(const Reference
<XComponentContext
>& _rxFactory
, const OUString
& _aService
)
85 :OControl(_rxFactory
, _aService
)
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
)
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
);
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
);
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
);
155 m_pThread
->release();
160 OControl::disposing();
164 OImageProducerThread_Impl
* OClickableImageBaseControl::getImageProducerThread()
168 m_pThread
= new OImageProducerThread_Impl( this );
169 m_pThread
->acquire();
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
) )
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() )
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
;
211 Reference
<XFormComponent
> xComp(getModel(), UNO_QUERY
);
215 xModelsParent
= xComp
->getParent();
216 if (!xModelsParent
.is())
219 // Which button type?
220 xSet
.set(xComp
, css::uno::UNO_QUERY
);
223 xSet
->getPropertyValue(PROPERTY_BUTTONTYPE
) >>= eButtonType
;
228 case FormButtonType_RESET
:
230 // Reset methods must be thread-safe!
231 Reference
<XReset
> xReset(xModelsParent
, UNO_QUERY
);
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
& )
254 case FormButtonType_URL
:
256 SolarMutexGuard aGuard
;
258 Reference
< XModel
> xModel
= getXModel(xModelsParent
);
264 Reference
< XController
> xController
= xModel
->getCurrentController();
265 if (!xController
.is())
268 Reference
< XFrame
> xFrame
= xController
->getFrame();
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();
315 xDisp
->dispatch( aURL
, aArgs
);
319 URL aHyperLink
= m_pFeatureInterception
->getTransformer().getStrictURLFromAscii( ".uno:OpenHyperlink" );
321 Reference
< XDispatch
> xDisp
= Reference
< XDispatchProvider
> (xFrame
,UNO_QUERY
)->queryDispatch(aHyperLink
, OUString() , 0);
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
);
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
;
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();
404 xSubmission
->submitWithInteraction( _rxHandler
);
408 // no "interceptor" -> ordinary (old-way) submission
409 Reference
< XChild
> xChild( getModel(), UNO_QUERY
);
410 Reference
< XSubmit
> xParentSubmission
;
412 xParentSubmission
.set(xChild
->getParent(), css::uno::UNO_QUERY
);
413 if ( xParentSubmission
.is() )
414 xParentSubmission
->submit( this, _rEvent
);
417 catch( const VetoException
& )
422 catch( const RuntimeException
& )
427 catch( const WrappedTargetException
& )
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
)
460 ,m_bDispatchUrlInternal(false)
461 ,m_bDownloading(false)
462 ,m_bProdStarted(false)
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
)
475 ,m_bDispatchUrlInternal(false)
476 ,m_bDownloading( false )
477 ,m_bProdStarted( false )
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
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
)
527 DBG_ASSERT(m_pMedium
== NULL
, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ...");
528 // This should be cleaned up at least in the dispose
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
;
580 void OClickableImageBaseModel::disposing()
582 OControlModel::disposing();
594 Any SAL_CALL
OClickableImageBaseModel::queryAggregation(const Type
& _rType
) throw (RuntimeException
, std::exception
)
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
);
612 void OClickableImageBaseModel::getFastPropertyValue(Any
& rValue
, sal_Int32 nHandle
) const
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;
621 OControlModel::getFastPropertyValue(rValue
, nHandle
);
626 void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
, const Any
& rValue
) throw ( Exception
, std::exception
)
630 case PROPERTY_ID_BUTTONTYPE
:
631 DBG_ASSERT(isA(rValue
, static_cast<FormButtonType
*>(NULL
)), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
632 rValue
>>= m_eButtonType
;
635 case PROPERTY_ID_TARGET_URL
:
636 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_STRING
, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
637 rValue
>>= m_sTargetURL
;
640 case PROPERTY_ID_TARGET_FRAME
:
641 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_STRING
, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
642 rValue
>>= m_sTargetFrame
;
645 case PROPERTY_ID_DISPATCHURLINTERNAL
:
646 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_BOOLEAN
, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
647 rValue
>>= m_bDispatchUrlInternal
;
651 OControlModel::setFastPropertyValue_NoBroadcast(nHandle
, rValue
);
656 sal_Bool
OClickableImageBaseModel::convertFastPropertyValue(Any
& rConvertedValue
, Any
& rOldValue
, sal_Int32 nHandle
, const Any
& rValue
)
657 throw( IllegalArgumentException
)
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
);
674 return OControlModel::convertFastPropertyValue(rConvertedValue
, rOldValue
, nHandle
, rValue
);
679 void OClickableImageBaseModel::StartProduction()
681 ImageProducer
*pImgProd
= GetImageProducer();
684 getPropertyValue("ImageURL") >>= sURL
;
687 if ( ::svt::GraphicAccess::isSupportedURL( sURL
) )
688 pImgProd
->SetImage( sURL
);
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;
695 if (m_pMedium
->GetErrorCode()==0)
697 SvStream
* pStream
= m_pMedium
->GetInStream();
699 pImgProd
->SetImage(*pStream
);
700 pImgProd
->startProduction();
701 m_bProdStarted
= true;
705 pImgProd
->SetImage(OUString());
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());
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
729 if (!rURL
.isEmpty() && !::svt::GraphicAccess::isSupportedURL( rURL
) )
734 m_pMedium
= new SfxMedium(rURL
, STREAM_STD_READ
);
736 // Find the XModel to get to the Object shell or at least the
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;
757 SfxObjectShell
*pTestObjSh
= SfxObjectShell::Current();
760 Reference
< XModel
> xTestModel
= pTestObjSh
->GetModel();
761 if( xTestModel
== xModel
)
766 pTestObjSh
= SfxObjectShell::GetFirst();
767 while( !pObjSh
&& pTestObjSh
)
769 Reference
< XModel
> xTestModel
= pTestObjSh
->GetModel();
770 if( xTestModel
== xModel
)
773 pTestObjSh
= SfxObjectShell::GetNext( *pTestObjSh
);
778 #ifdef USE_REGISTER_TRANSFER
781 // Transfer target frame, so that javascript: URLs
782 // can also be "loaded"
783 const SfxMedium
*pShMedium
= pObjSh
->GetMedium();
785 m_pMedium
->SetLoadTargetFrame(pShMedium
->GetLoadTargetFrame());
790 // Transfer target frame, so that javascript: URLs
791 // can also be "loaded"
792 const SfxMedium
*pShMedium
= pObjSh
->GetMedium();
794 m_pMedium
->SetLoadTargetFrame(pShMedium
->GetLoadTargetFrame());
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
));
808 if ( ::svt::GraphicAccess::isSupportedURL( rURL
) )
809 GetImageProducer()->SetImage( rURL
);
810 GetImageProducer()->startProduction();
815 void OClickableImageBaseModel::DataAvailable()
820 GetImageProducer()->NewDataAvailable();
824 void OClickableImageBaseModel::DownloadDone()
827 m_bDownloading
= false;
831 IMPL_LINK_NOARG( OClickableImageBaseModel
, DownloadDoneLink
)
833 ::osl::MutexGuard
aGuard( m_aMutex
);
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
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
);
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();
870 m_xGraphicObject
= css::graphic::GraphicObject::create( m_xContext
);
871 m_xGraphicObject
->setGraphic( xGraphic
);
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
>&,
891 static_cast<OClickableImageBaseControl
*>(pCompImpl
)->actionPerformed_Impl( true, *static_cast<const MouseEvent
*>(pEvt
) );
898 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */