update credits
[LibreOffice.git] / forms / source / component / clickableimage.cxx
blob93ef01e01053598de90fdafabf7e864118c1f2b6
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 <tools/urlobj.hxx>
35 #include <tools/debug.hxx>
36 #include <vcl/svapp.hxx>
37 #include <sfx2/docfile.hxx>
38 #include <sfx2/objsh.hxx>
39 #include <osl/mutex.hxx>
40 #include "services.hxx"
41 #include <comphelper/container.hxx>
42 #include <comphelper/listenernotification.hxx>
43 #include <svtools/imageresourceaccess.hxx>
44 #define LOCAL_URL_PREFIX '#'
46 //.........................................................................
47 namespace frm
49 //.........................................................................
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::sdb;
53 using namespace ::com::sun::star::sdbc;
54 using namespace ::com::sun::star::sdbcx;
55 using namespace ::com::sun::star::beans;
56 using namespace ::com::sun::star::container;
57 using namespace ::com::sun::star::form;
58 using namespace ::com::sun::star::awt;
59 using namespace ::com::sun::star::io;
60 using namespace ::com::sun::star::lang;
61 using namespace ::com::sun::star::util;
62 using namespace ::com::sun::star::frame;
63 using namespace ::com::sun::star::form::submission;
64 using ::com::sun::star::awt::MouseEvent;
65 using ::com::sun::star::task::XInteractionHandler;
67 //==================================================================
68 // OClickableImageBaseControl
69 //==================================================================
70 //------------------------------------------------------------------------------
71 Sequence<Type> OClickableImageBaseControl::_getTypes()
73 static Sequence<Type> aTypes;
74 if (!aTypes.getLength())
75 aTypes = concatSequences(OControl::_getTypes(), OClickableImageBaseControl_BASE::getTypes());
76 return aTypes;
79 //------------------------------------------------------------------------------
80 OClickableImageBaseControl::OClickableImageBaseControl(const Reference<XMultiServiceFactory>& _rxFactory, const OUString& _aService)
81 :OControl(_rxFactory, _aService)
82 ,m_pThread(NULL)
83 ,m_aSubmissionVetoListeners( m_aMutex )
84 ,m_aApproveActionListeners( m_aMutex )
85 ,m_aActionListeners( m_aMutex )
87 m_pFeatureInterception.reset( new ControlFeatureInterception( _rxFactory ) );
90 //------------------------------------------------------------------------------
91 OClickableImageBaseControl::~OClickableImageBaseControl()
93 if (!OComponentHelper::rBHelper.bDisposed)
95 acquire();
96 dispose();
100 // UNO Anbindung
101 //------------------------------------------------------------------------------
102 Any SAL_CALL OClickableImageBaseControl::queryAggregation(const Type& _rType) throw (RuntimeException)
104 Any aReturn = OControl::queryAggregation(_rType);
105 if (!aReturn.hasValue())
106 aReturn = OClickableImageBaseControl_BASE::queryInterface(_rType);
107 return aReturn;
110 // XApproveActionBroadcaster
111 //------------------------------------------------------------------------------
112 void OClickableImageBaseControl::addApproveActionListener(
113 const Reference<XApproveActionListener>& l) throw( RuntimeException )
115 m_aApproveActionListeners.addInterface(l);
118 //------------------------------------------------------------------------------
119 void OClickableImageBaseControl::removeApproveActionListener(
120 const Reference<XApproveActionListener>& l) throw( RuntimeException )
122 m_aApproveActionListeners.removeInterface(l);
125 //--------------------------------------------------------------------
126 void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException)
128 m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor );
131 //--------------------------------------------------------------------
132 void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException)
134 m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor );
137 // OComponentHelper
138 //------------------------------------------------------------------------------
139 void OClickableImageBaseControl::disposing()
141 EventObject aEvent( static_cast< XWeak* >( this ) );
142 m_aApproveActionListeners.disposeAndClear( aEvent );
143 m_aActionListeners.disposeAndClear( aEvent );
144 m_aSubmissionVetoListeners.disposeAndClear( aEvent );
145 m_pFeatureInterception->dispose();
148 ::osl::MutexGuard aGuard( m_aMutex );
149 if( m_pThread )
151 m_pThread->release();
152 m_pThread = NULL;
156 OControl::disposing();
159 //------------------------------------------------------------------------------
160 OImageProducerThread_Impl* OClickableImageBaseControl::getImageProducerThread()
162 if ( !m_pThread )
164 m_pThread = new OImageProducerThread_Impl( this );
165 m_pThread->acquire();
166 m_pThread->create();
168 return m_pThread;
171 //------------------------------------------------------------------------------
172 bool OClickableImageBaseControl::approveAction( )
174 sal_Bool bCancelled = sal_False;
175 EventObject aEvent( static_cast< XWeak* >( this ) );
177 ::cppu::OInterfaceIteratorHelper aIter( m_aApproveActionListeners );
178 while( !bCancelled && aIter.hasMoreElements() )
180 // Jede approveAction-Methode muss thread-safe sein!!!
181 if( !static_cast< XApproveActionListener* >( aIter.next() )->approveAction( aEvent ) )
182 bCancelled = sal_True;
185 return !bCancelled;
188 //------------------------------------------------------------------------------
189 // Diese Methode wird auch aus einem Thread gerufen und muss deshalb
190 // thread-safe sein.
191 void OClickableImageBaseControl::actionPerformed_Impl(sal_Bool bNotifyListener, const MouseEvent& rEvt)
193 if( bNotifyListener )
195 if ( !approveAction() )
196 return;
199 // Ob der Rest des Codes Thread-Safe ist weiss man nicht genau. Deshalb
200 // wird das meiste bei gelocktem Solar-Mutex erledigen.
201 Reference<XPropertySet> xSet;
202 Reference< XInterface > xModelsParent;
203 FormButtonType eButtonType = FormButtonType_PUSH;
205 SolarMutexGuard aGuard;
207 // Parent holen
208 Reference<XFormComponent> xComp(getModel(), UNO_QUERY);
209 if (!xComp.is())
210 return;
212 xModelsParent = xComp->getParent();
213 if (!xModelsParent.is())
214 return;
216 // which button type?
217 xSet = xSet.query( xComp );
218 if ( !xSet.is() )
219 return;
220 xSet->getPropertyValue(PROPERTY_BUTTONTYPE) >>= eButtonType;
223 switch (eButtonType)
225 case FormButtonType_RESET:
227 // reset-Methoden muessen thread-safe sein!
228 Reference<XReset> xReset(xModelsParent, UNO_QUERY);
229 if (!xReset.is())
230 return;
232 xReset->reset();
234 break;
236 case FormButtonType_SUBMIT:
238 // if some outer component can provide an interaction handler, use it
239 Reference< XInteractionHandler > xHandler( m_pFeatureInterception->queryDispatch( "private:/InteractionHandler" ), UNO_QUERY );
242 implSubmit( rEvt, xHandler );
244 catch( const Exception& )
246 // ignore
249 break;
251 case FormButtonType_URL:
253 SolarMutexGuard aGuard;
255 Reference< XModel > xModel = getXModel(xModelsParent);
256 if (!xModel.is())
257 return;
259 ///////////////////////////////////////////////////////////////////////
260 // Jetzt URL ausfuehren
261 Reference< XController > xController = xModel->getCurrentController();
262 if (!xController.is())
263 return;
265 Reference< XFrame > xFrame = xController->getFrame();
266 if( !xFrame.is() )
267 return;
269 URL aURL;
270 aURL.Complete =
271 getString(xSet->getPropertyValue(PROPERTY_TARGET_URL));
273 if (!aURL.Complete.isEmpty() && (LOCAL_URL_PREFIX == aURL.Complete.getStr()[0]))
274 { // the URL contains a local URL only. Since the URLTransformer does not handle this case correctly
275 // (it can't: it does not know the document URL), we have to take care for this ourself.
276 // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all
277 // URLs have to be absolute), but for compatibility reasons this is no option.
278 // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it
279 // could be "#mark" as well.
280 // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete
281 // solutiuon would be:
282 // * recognize URLs consisting of a mark only while _reading_ the document
283 // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to
284 // transform such mark-only URLs into correct absolute URLs
285 // * at the UI, show only the mark
286 // * !!!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems
287 // rather impossible !!!
288 aURL.Mark = aURL.Complete;
289 aURL.Complete = xModel->getURL();
290 aURL.Complete += aURL.Mark;
293 sal_Bool bDispatchUrlInternal = sal_False;
294 xSet->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL) >>= bDispatchUrlInternal;
295 if ( bDispatchUrlInternal )
297 m_pFeatureInterception->getTransformer().parseSmartWithAsciiProtocol( aURL, INET_FILE_SCHEME );
299 OUString aTargetFrame;
300 xSet->getPropertyValue(PROPERTY_TARGET_FRAME) >>= aTargetFrame;
302 Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch( aURL, aTargetFrame,
303 FrameSearchFlag::SELF | FrameSearchFlag::PARENT |
304 FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE );
306 Sequence<PropertyValue> aArgs(1);
307 PropertyValue& rProp = aArgs.getArray()[0];
308 rProp.Name = OUString("Referer");
309 rProp.Value <<= xModel->getURL();
311 if (xDisp.is())
312 xDisp->dispatch( aURL, aArgs );
314 else
316 URL aHyperLink = m_pFeatureInterception->getTransformer().getStrictURLFromAscii( ".uno:OpenHyperlink" );
318 Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aHyperLink, OUString() , 0);
320 if ( xDisp.is() )
322 Sequence<PropertyValue> aProps(3);
323 aProps[0].Name = OUString("URL");
324 aProps[0].Value <<= aURL.Complete;
326 aProps[1].Name = OUString("FrameName");
327 aProps[1].Value = xSet->getPropertyValue(PROPERTY_TARGET_FRAME);
329 aProps[2].Name = OUString("Referer");
330 aProps[2].Value <<= xModel->getURL();
332 xDisp->dispatch( aHyperLink, aProps );
335 } break;
336 default:
338 // notify the action listeners for a push button
339 ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand);
340 m_aActionListeners.notifyEach( &XActionListener::actionPerformed, aEvt );
346 //--------------------------------------------------------------------
347 void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException)
349 m_aSubmissionVetoListeners.addInterface( listener );
352 //--------------------------------------------------------------------
353 void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException)
355 m_aSubmissionVetoListeners.removeInterface( listener );
358 //--------------------------------------------------------------------
359 void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler ) throw (VetoException, WrappedTargetException, RuntimeException)
361 implSubmit( MouseEvent(), _rxHandler );
364 //--------------------------------------------------------------------
365 void SAL_CALL OClickableImageBaseControl::submit( ) throw (VetoException, WrappedTargetException, RuntimeException)
367 implSubmit( MouseEvent(), NULL );
370 //--------------------------------------------------------------------
371 Sequence< OUString > SAL_CALL OClickableImageBaseControl::getSupportedServiceNames( ) throw (RuntimeException)
373 Sequence< OUString > aSupported = OControl::getSupportedServiceNames();
374 aSupported.realloc( aSupported.getLength() + 1 );
376 OUString* pArray = aSupported.getArray();
377 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON;
379 return aSupported;
382 //--------------------------------------------------------------------
383 void OClickableImageBaseControl::implSubmit( const MouseEvent& _rEvent, const Reference< XInteractionHandler >& _rxHandler ) SAL_THROW((VetoException, WrappedTargetException, RuntimeException))
387 // allow the veto listeners to join the game
388 m_aSubmissionVetoListeners.notifyEach( &XSubmissionVetoListener::submitting, EventObject( *this ) );
390 // see whether there's an "submit interceptor" set at our model
391 Reference< submission::XSubmissionSupplier > xSubmissionSupp( getModel(), UNO_QUERY );
392 Reference< XSubmission > xSubmission;
393 if ( xSubmissionSupp.is() )
394 xSubmission = xSubmissionSupp->getSubmission();
396 if ( xSubmission.is() )
398 if ( !_rxHandler.is() )
399 xSubmission->submit();
400 else
401 xSubmission->submitWithInteraction( _rxHandler );
403 else
405 // no "interceptor" -> ordinary (old-way) submission
406 Reference< XChild > xChild( getModel(), UNO_QUERY );
407 Reference< XSubmit > xParentSubmission;
408 if ( xChild.is() )
409 xParentSubmission = xParentSubmission.query( xChild->getParent() );
410 if ( xParentSubmission.is() )
411 xParentSubmission->submit( this, _rEvent );
414 catch( const VetoException& )
416 // allowed to leave
417 throw;
419 catch( const RuntimeException& )
421 // allowed to leave
422 throw;
424 catch( const WrappedTargetException& )
426 // allowed to leave
427 throw;
429 catch( const Exception& e )
431 OSL_FAIL( "OClickableImageBaseControl::implSubmit: caught an unknown exception!" );
432 throw WrappedTargetException( OUString(), *this, makeAny( e ) );
436 //==================================================================
437 // OClickableImageBaseModel
438 //==================================================================
439 //------------------------------------------------------------------------------
440 Sequence<Type> OClickableImageBaseModel::_getTypes()
442 return concatSequences(
443 OControlModel::_getTypes(),
444 OClickableImageBaseModel_Base::getTypes()
448 //------------------------------------------------------------------
449 DBG_NAME( OClickableImageBaseModel )
450 //------------------------------------------------------------------
451 OClickableImageBaseModel::OClickableImageBaseModel( const Reference< XMultiServiceFactory >& _rxFactory, const OUString& _rUnoControlModelTypeName,
452 const OUString& rDefault )
453 :OControlModel( _rxFactory, _rUnoControlModelTypeName, rDefault )
454 ,OPropertyChangeListener(m_aMutex)
455 ,m_pMedium(NULL)
456 ,m_pProducer( NULL )
457 ,m_bDispatchUrlInternal(sal_False)
458 ,m_bDownloading(sal_False)
459 ,m_bProdStarted(sal_False)
461 DBG_CTOR( OClickableImageBaseModel, NULL );
462 implConstruct();
463 m_eButtonType = FormButtonType_PUSH;
466 //------------------------------------------------------------------
467 OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory )
468 :OControlModel( _pOriginal, _rxFactory )
469 ,OPropertyChangeListener( m_aMutex )
470 ,m_pMedium( NULL )
471 ,m_pProducer( NULL )
472 ,m_bDispatchUrlInternal(sal_False)
473 ,m_bDownloading( sal_False )
474 ,m_bProdStarted( sal_False )
476 DBG_CTOR( OClickableImageBaseModel, NULL );
477 implConstruct();
479 // copy properties
480 m_eButtonType = _pOriginal->m_eButtonType;
481 m_sTargetURL = _pOriginal->m_sTargetURL;
482 m_sTargetFrame = _pOriginal->m_sTargetFrame;
483 m_bDispatchUrlInternal = _pOriginal->m_bDispatchUrlInternal;
486 //------------------------------------------------------------------------------
487 void OClickableImageBaseModel::implInitializeImageURL( )
489 osl_atomic_increment( &m_refCount );
491 // simulate a propertyChanged event for the ImageURL
492 Any aImageURL;
493 getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL );
494 _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL, sal_False, PROPERTY_ID_IMAGE_URL, Any( ), aImageURL ) );
496 osl_atomic_decrement( &m_refCount );
499 //------------------------------------------------------------------------------
500 void OClickableImageBaseModel::implConstruct()
502 m_pProducer = new ImageProducer;
503 increment( m_refCount );
505 m_xProducer = m_pProducer;
507 if ( m_xAggregateSet.is() )
509 OPropertyChangeMultiplexer* pMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet );
510 pMultiplexer->addProperty( PROPERTY_IMAGE_URL );
513 decrement(m_refCount);
516 //------------------------------------------------------------------------------
517 OClickableImageBaseModel::~OClickableImageBaseModel()
519 if (!OComponentHelper::rBHelper.bDisposed)
521 acquire();
522 dispose();
524 DBG_ASSERT(m_pMedium == NULL, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ...");
525 // spaetestens im dispose sollte das aufgeraeumt worden sein
527 DBG_DTOR( OClickableImageBaseModel, NULL );
530 // XImageProducer
531 //--------------------------------------------------------------------
532 void SAL_CALL OClickableImageBaseModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException)
534 ImageModelMethodGuard aGuard( *this );
535 GetImageProducer()->addConsumer( _rxConsumer );
538 //--------------------------------------------------------------------
539 void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException)
541 ImageModelMethodGuard aGuard( *this );
542 GetImageProducer()->removeConsumer( _rxConsumer );
545 //--------------------------------------------------------------------
546 void SAL_CALL OClickableImageBaseModel::startProduction( ) throw (RuntimeException)
548 ImageModelMethodGuard aGuard( *this );
549 GetImageProducer()->startProduction();
552 //--------------------------------------------------------------------
553 Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission() throw (RuntimeException)
555 return m_xSubmissionDelegate;
558 //--------------------------------------------------------------------
559 void SAL_CALL OClickableImageBaseModel::setSubmission( const Reference< submission::XSubmission >& _submission ) throw (RuntimeException)
561 m_xSubmissionDelegate = _submission;
564 //--------------------------------------------------------------------
565 Sequence< OUString > SAL_CALL OClickableImageBaseModel::getSupportedServiceNames( ) throw (RuntimeException)
567 Sequence< OUString > aSupported = OControlModel::getSupportedServiceNames();
568 aSupported.realloc( aSupported.getLength() + 1 );
570 OUString* pArray = aSupported.getArray();
571 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON;
573 return aSupported;
576 // OComponentHelper
577 //------------------------------------------------------------------------------
578 void OClickableImageBaseModel::disposing()
580 OControlModel::disposing();
581 if (m_pMedium)
583 delete m_pMedium;
584 m_pMedium = NULL;
587 m_xProducer = NULL;
588 m_pProducer = NULL;
591 //------------------------------------------------------------------------------
592 Any SAL_CALL OClickableImageBaseModel::queryAggregation(const Type& _rType) throw (RuntimeException)
594 // order matters:
595 // we definitely want to "overload" the XImageProducer interface of our aggregate,
596 // thus check OClickableImageBaseModel_Base (which provides this) first
597 Any aReturn = OClickableImageBaseModel_Base::queryInterface( _rType );
599 // BUT: _don't_ let it feel responsible for the XTypeProvider interface
600 // (as this is implemented by our base class in the proper way)
601 if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) )
602 || !aReturn.hasValue()
604 aReturn = OControlModel::queryAggregation( _rType );
606 return aReturn;
609 //------------------------------------------------------------------------------
610 void OClickableImageBaseModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
612 switch (nHandle)
614 case PROPERTY_ID_BUTTONTYPE : rValue <<= m_eButtonType; break;
615 case PROPERTY_ID_TARGET_URL : rValue <<= m_sTargetURL; break;
616 case PROPERTY_ID_TARGET_FRAME : rValue <<= m_sTargetFrame; break;
617 case PROPERTY_ID_DISPATCHURLINTERNAL : rValue <<= m_bDispatchUrlInternal; break;
618 default:
619 OControlModel::getFastPropertyValue(rValue, nHandle);
623 //------------------------------------------------------------------------------
624 void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( Exception)
626 switch (nHandle)
628 case PROPERTY_ID_BUTTONTYPE :
629 DBG_ASSERT(isA(rValue, static_cast<FormButtonType*>(NULL)), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
630 rValue >>= m_eButtonType;
631 break;
633 case PROPERTY_ID_TARGET_URL :
634 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
635 rValue >>= m_sTargetURL;
636 break;
638 case PROPERTY_ID_TARGET_FRAME :
639 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
640 rValue >>= m_sTargetFrame;
641 break;
643 case PROPERTY_ID_DISPATCHURLINTERNAL:
644 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
645 rValue >>= m_bDispatchUrlInternal;
646 break;
648 default:
649 OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue);
653 //------------------------------------------------------------------------------
654 sal_Bool OClickableImageBaseModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
655 throw( IllegalArgumentException )
657 switch (nHandle)
659 case PROPERTY_ID_BUTTONTYPE :
660 return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType );
662 case PROPERTY_ID_TARGET_URL :
663 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL);
665 case PROPERTY_ID_TARGET_FRAME :
666 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame);
668 case PROPERTY_ID_DISPATCHURLINTERNAL :
669 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal);
671 default:
672 return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
676 //------------------------------------------------------------------------------
677 void OClickableImageBaseModel::StartProduction()
679 ImageProducer *pImgProd = GetImageProducer();
680 // grab the ImageURL
681 OUString sURL;
682 getPropertyValue( OUString("ImageURL") ) >>= sURL;
683 if (!m_pMedium)
685 if ( ::svt::GraphicAccess::isSupportedURL( sURL ) )
686 pImgProd->SetImage( sURL );
687 else
688 // caution: the medium may be NULL if somebody gave us a invalid URL to work with
689 pImgProd->SetImage(String());
690 m_bDownloading = sal_False;
691 return;
693 if (m_pMedium->GetErrorCode()==0)
695 SvStream* pStream = m_pMedium->GetInStream();
697 pImgProd->SetImage(*pStream);
698 pImgProd->startProduction();
699 m_bProdStarted = sal_True;
701 else
703 pImgProd->SetImage(String());
704 delete m_pMedium;
705 m_pMedium = 0;
706 m_bDownloading = sal_False;
710 //------------------------------------------------------------------------------
711 void OClickableImageBaseModel::SetURL( const OUString& rURL )
713 if (m_pMedium || rURL.isEmpty())
715 // Den Stream am Producer freigeben, bevor das Medium geloscht wird.
716 GetImageProducer()->SetImage(String());
717 delete m_pMedium;
718 m_pMedium = NULL;
721 // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first
722 INetURLObject aUrl(rURL);
723 if (INET_PROT_NOT_VALID == aUrl.GetProtocol())
724 // we treat an invalid URL like we would treat no URL
725 return;
727 if (!rURL.isEmpty() && !::svt::GraphicAccess::isSupportedURL( rURL ) )
729 if (m_pMedium)
730 delete m_pMedium;
732 m_pMedium = new SfxMedium(rURL, STREAM_STD_READ);
734 // Das XModel suchen, um an die Object-Shell oder zumindest den
735 // Referer zu gelangen.
736 // Das Model findet man allerdings nur beim Laden von HTML-Dokumenten
737 // und dann, wenn die URL in einem bereits geladenen Dokument
738 // geaendert wird. Waehrend des Ladens kommt man nicht an das
739 // Model ran.
740 Reference< XModel > xModel;
741 InterfaceRef xIfc( *this );
742 while( !xModel.is() && xIfc.is() )
744 Reference<XChild> xChild( xIfc, UNO_QUERY );
745 xIfc = xChild->getParent();
746 query_interface(xIfc, xModel);
749 // Die Object-Shell suchen, indem wir
750 // ueber alle Object-Shells iterieren und deren XModel mit dem
751 // eigenen vergleichen. Als Optimierung probieren wir aber erstmal
752 // die aktuelle Object-Shell.
753 // wir unser XModel mit dem aller Object
754 SfxObjectShell *pObjSh = 0;
756 if( xModel.is() )
758 SfxObjectShell *pTestObjSh = SfxObjectShell::Current();
759 if( pTestObjSh )
761 Reference< XModel > xTestModel = pTestObjSh->GetModel();
762 if( xTestModel == xModel )
763 pObjSh = pTestObjSh;
765 if( !pObjSh )
767 pTestObjSh = SfxObjectShell::GetFirst();
768 while( !pObjSh && pTestObjSh )
770 Reference< XModel > xTestModel = pTestObjSh->GetModel();
771 if( xTestModel == xModel )
772 pObjSh = pTestObjSh;
773 else
774 pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh );
779 #ifdef USE_REGISTER_TRANSFER
780 if( pObjSh )
782 // Target-Frame uebertragen, damit auch javascript:-URLs
783 // "geladen" werden koennen.
784 const SfxMedium *pShMedium = pObjSh->GetMedium();
785 if( pShMedium )
786 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame());
788 #else
789 if( pObjSh )
791 // Target-Frame uebertragen, damit auch javascript:-URLs
792 // "geladen" werden koennen.
793 const SfxMedium *pShMedium = pObjSh->GetMedium();
794 if( pShMedium )
795 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame());
797 #endif
799 // Downloading-Flag auf sal_True setzen. Es werden dann auch
800 // Data-Available-Links, wenn wir in den Pending-Staus gelangen.
801 m_bDownloading = sal_True;
802 m_bProdStarted = sal_False;
804 // Download anstossen (Achtung: Kann auch synchron sein).
805 m_pMedium->DownLoad(STATIC_LINK(this, OClickableImageBaseModel, DownloadDoneLink));
807 else
809 if ( ::svt::GraphicAccess::isSupportedURL( rURL ) )
810 GetImageProducer()->SetImage( rURL );
811 GetImageProducer()->startProduction();
815 //------------------------------------------------------------------------------
816 void OClickableImageBaseModel::DataAvailable()
818 if (!m_bProdStarted)
819 StartProduction();
821 GetImageProducer()->NewDataAvailable();
824 //------------------------------------------------------------------------------
825 void OClickableImageBaseModel::DownloadDone()
827 DataAvailable();
828 m_bDownloading = sal_False;
831 //------------------------------------------------------------------------------
832 IMPL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void*, EMPTYARG )
834 ::osl::MutexGuard aGuard( pThis->m_aMutex );
835 pThis->DownloadDone();
836 return 0;
839 //------------------------------------------------------------------------------
840 void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt )
841 throw( RuntimeException )
843 // Wenn eine URL gesetzt worden ist, muss die noch an den ImageProducer
844 // weitergereicht werden.
845 ::osl::MutexGuard aGuard(m_aMutex);
846 SetURL( getString(rEvt.NewValue) );
849 // -----------------------------------------------------------------------------
850 Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
852 switch (nHandle)
854 case PROPERTY_ID_BUTTONTYPE : return makeAny( FormButtonType_PUSH );
855 case PROPERTY_ID_TARGET_URL :
856 case PROPERTY_ID_TARGET_FRAME : return makeAny( OUString() );
857 case PROPERTY_ID_DISPATCHURLINTERNAL : return makeAny( sal_False );
858 default:
859 return OControlModel::getPropertyDefaultByHandle(nHandle);
863 //==================================================================
864 // OImageProducerThread_Impl
865 //==================================================================
866 //------------------------------------------------------------------
867 EventObject* OImageProducerThread_Impl::cloneEvent( const EventObject* _pEvt ) const
869 return new EventObject( *_pEvt );
872 //------------------------------------------------------------------
873 void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper *pCompImpl,
874 const EventObject* pEvt,
875 const Reference<XControl>&,
876 sal_Bool )
878 ((OClickableImageBaseControl *)pCompImpl)->actionPerformed_Impl( sal_True, *(MouseEvent *)pEvt );
881 //.........................................................................
882 } // namespace frm
883 //.........................................................................
885 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */