| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_forms.hxx" |
| #include "clickableimage.hxx" |
| #include "controlfeatureinterception.hxx" |
| #include "urltransformer.hxx" |
| #include "componenttools.hxx" |
| #include <com/sun/star/form/XSubmit.hpp> |
| #include <com/sun/star/awt/SystemPointer.hpp> |
| #include <com/sun/star/form/FormComponentType.hpp> |
| #include <com/sun/star/frame/XDispatch.hpp> |
| #include <com/sun/star/frame/XDispatchProvider.hpp> |
| #include <com/sun/star/frame/FrameSearchFlag.hpp> |
| #include <com/sun/star/frame/XController.hpp> |
| #include <com/sun/star/frame/XFrame.hpp> |
| #include <com/sun/star/awt/ActionEvent.hpp> |
| #include <com/sun/star/awt/XActionListener.hpp> |
| #include <tools/urlobj.hxx> |
| #include <tools/debug.hxx> |
| #include <vcl/svapp.hxx> |
| #include <sfx2/docfile.hxx> |
| #include <sfx2/objsh.hxx> |
| #include <vos/mutex.hxx> |
| #include "services.hxx" |
| #include <comphelper/container.hxx> |
| #include <comphelper/listenernotification.hxx> |
| #include <svtools/imageresourceaccess.hxx> |
| #define LOCAL_URL_PREFIX '#' |
| |
| //......................................................................... |
| namespace frm |
| { |
| //......................................................................... |
| |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::sdb; |
| using namespace ::com::sun::star::sdbc; |
| using namespace ::com::sun::star::sdbcx; |
| using namespace ::com::sun::star::beans; |
| using namespace ::com::sun::star::container; |
| using namespace ::com::sun::star::form; |
| using namespace ::com::sun::star::awt; |
| using namespace ::com::sun::star::io; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::util; |
| using namespace ::com::sun::star::frame; |
| using namespace ::com::sun::star::form::submission; |
| using ::com::sun::star::awt::MouseEvent; |
| using ::com::sun::star::task::XInteractionHandler; |
| |
| //================================================================== |
| // OClickableImageBaseControl |
| //================================================================== |
| //------------------------------------------------------------------------------ |
| Sequence<Type> OClickableImageBaseControl::_getTypes() |
| { |
| static Sequence<Type> aTypes; |
| if (!aTypes.getLength()) |
| aTypes = concatSequences(OControl::_getTypes(), OClickableImageBaseControl_BASE::getTypes()); |
| return aTypes; |
| } |
| |
| //------------------------------------------------------------------------------ |
| OClickableImageBaseControl::OClickableImageBaseControl(const Reference<XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _aService) |
| :OControl(_rxFactory, _aService) |
| ,m_pThread(NULL) |
| ,m_aSubmissionVetoListeners( m_aMutex ) |
| ,m_aApproveActionListeners( m_aMutex ) |
| ,m_aActionListeners( m_aMutex ) |
| { |
| m_pFeatureInterception.reset( new ControlFeatureInterception( _rxFactory ) ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| OClickableImageBaseControl::~OClickableImageBaseControl() |
| { |
| if (!OComponentHelper::rBHelper.bDisposed) |
| { |
| acquire(); |
| dispose(); |
| } |
| } |
| |
| // UNO Anbindung |
| //------------------------------------------------------------------------------ |
| Any SAL_CALL OClickableImageBaseControl::queryAggregation(const Type& _rType) throw (RuntimeException) |
| { |
| Any aReturn = OControl::queryAggregation(_rType); |
| if (!aReturn.hasValue()) |
| aReturn = OClickableImageBaseControl_BASE::queryInterface(_rType); |
| return aReturn; |
| } |
| |
| // XApproveActionBroadcaster |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseControl::addApproveActionListener( |
| const Reference<XApproveActionListener>& l) throw( RuntimeException ) |
| { |
| m_aApproveActionListeners.addInterface(l); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseControl::removeApproveActionListener( |
| const Reference<XApproveActionListener>& l) throw( RuntimeException ) |
| { |
| m_aApproveActionListeners.removeInterface(l); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) |
| { |
| m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException) |
| { |
| m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor ); |
| } |
| |
| // OComponentHelper |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseControl::disposing() |
| { |
| EventObject aEvent( static_cast< XWeak* >( this ) ); |
| m_aApproveActionListeners.disposeAndClear( aEvent ); |
| m_aActionListeners.disposeAndClear( aEvent ); |
| m_aSubmissionVetoListeners.disposeAndClear( aEvent ); |
| m_pFeatureInterception->dispose(); |
| |
| { |
| ::osl::MutexGuard aGuard( m_aMutex ); |
| if( m_pThread ) |
| { |
| m_pThread->release(); |
| m_pThread = NULL; |
| } |
| } |
| |
| OControl::disposing(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| OImageProducerThread_Impl* OClickableImageBaseControl::getImageProducerThread() |
| { |
| if ( !m_pThread ) |
| { |
| m_pThread = new OImageProducerThread_Impl( this ); |
| m_pThread->acquire(); |
| m_pThread->create(); |
| } |
| return m_pThread; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool OClickableImageBaseControl::approveAction( ) |
| { |
| sal_Bool bCancelled = sal_False; |
| EventObject aEvent( static_cast< XWeak* >( this ) ); |
| |
| ::cppu::OInterfaceIteratorHelper aIter( m_aApproveActionListeners ); |
| while( !bCancelled && aIter.hasMoreElements() ) |
| { |
| // Jede approveAction-Methode muss thread-safe sein!!! |
| if( !static_cast< XApproveActionListener* >( aIter.next() )->approveAction( aEvent ) ) |
| bCancelled = sal_True; |
| } |
| |
| return !bCancelled; |
| } |
| |
| //------------------------------------------------------------------------------ |
| // Diese Methode wird auch aus einem Thread gerufen und muss deshalb |
| // thread-safe sein. |
| void OClickableImageBaseControl::actionPerformed_Impl(sal_Bool bNotifyListener, const MouseEvent& rEvt) |
| { |
| if( bNotifyListener ) |
| { |
| if ( !approveAction() ) |
| return; |
| } |
| |
| // Ob der Rest des Codes Thread-Safe ist weiss man nicht genau. Deshalb |
| // wird das meiste bei gelocktem Solar-Mutex erledigen. |
| Reference<XPropertySet> xSet; |
| Reference< XInterface > xModelsParent; |
| FormButtonType eButtonType = FormButtonType_PUSH; |
| { |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| |
| // Parent holen |
| Reference<XFormComponent> xComp(getModel(), UNO_QUERY); |
| if (!xComp.is()) |
| return; |
| |
| xModelsParent = xComp->getParent(); |
| if (!xModelsParent.is()) |
| return; |
| |
| // which button type? |
| xSet = xSet.query( xComp ); |
| if ( !xSet.is() ) |
| return; |
| xSet->getPropertyValue(PROPERTY_BUTTONTYPE) >>= eButtonType; |
| } |
| |
| switch (eButtonType) |
| { |
| case FormButtonType_RESET: |
| { |
| // reset-Methoden muessen thread-safe sein! |
| Reference<XReset> xReset(xModelsParent, UNO_QUERY); |
| if (!xReset.is()) |
| return; |
| |
| xReset->reset(); |
| } |
| break; |
| |
| case FormButtonType_SUBMIT: |
| { |
| // if some outer component can provide an interaction handler, use it |
| Reference< XInteractionHandler > xHandler( m_pFeatureInterception->queryDispatch( "private:/InteractionHandler" ), UNO_QUERY ); |
| try |
| { |
| implSubmit( rEvt, xHandler ); |
| } |
| catch( const Exception& ) |
| { |
| // ignore |
| } |
| } |
| break; |
| |
| case FormButtonType_URL: |
| { |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| |
| Reference< XModel > xModel = getXModel(xModelsParent); |
| if (!xModel.is()) |
| return; |
| |
| /////////////////////////////////////////////////////////////////////// |
| // Jetzt URL ausfuehren |
| Reference< XController > xController = xModel->getCurrentController(); |
| if (!xController.is()) |
| return; |
| |
| Reference< XFrame > xFrame = xController->getFrame(); |
| if( !xFrame.is() ) |
| return; |
| |
| URL aURL; |
| aURL.Complete = |
| getString(xSet->getPropertyValue(PROPERTY_TARGET_URL)); |
| |
| if (aURL.Complete.getLength() && (LOCAL_URL_PREFIX == aURL.Complete.getStr()[0])) |
| { // the URL contains a local URL only. Since the URLTransformer does not handle this case correctly |
| // (it can't: it does not know the document URL), we have to take care for this ourself. |
| // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all |
| // URLs have to be absolute), but for compatibility reasons this is no option. |
| // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it |
| // could be "#mark" as well. |
| // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete |
| // solutiuon would be: |
| // * recognize URLs consisting of a mark only while _reading_ the document |
| // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to |
| // transform such mark-only URLs into correct absolute URLs |
| // * at the UI, show only the mark |
| // * !!!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems |
| // rather impossible !!! |
| // 89752 - 23.07.2001 - frank.schoenheit@sun.com |
| aURL.Mark = aURL.Complete; |
| aURL.Complete = xModel->getURL(); |
| aURL.Complete += aURL.Mark; |
| } |
| |
| sal_Bool bDispatchUrlInternal = sal_False; |
| xSet->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL) >>= bDispatchUrlInternal; |
| if ( bDispatchUrlInternal ) |
| { |
| m_pFeatureInterception->getTransformer().parseSmartWithAsciiProtocol( aURL, INET_FILE_SCHEME ); |
| |
| ::rtl::OUString aTargetFrame; |
| xSet->getPropertyValue(PROPERTY_TARGET_FRAME) >>= aTargetFrame; |
| |
| Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch( aURL, aTargetFrame, |
| FrameSearchFlag::SELF | FrameSearchFlag::PARENT | |
| FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE ); |
| |
| Sequence<PropertyValue> aArgs(1); |
| PropertyValue& rProp = aArgs.getArray()[0]; |
| rProp.Name = ::rtl::OUString::createFromAscii("Referer"); |
| rProp.Value <<= xModel->getURL(); |
| |
| if (xDisp.is()) |
| xDisp->dispatch( aURL, aArgs ); |
| } |
| else |
| { |
| URL aHyperLink = m_pFeatureInterception->getTransformer().getStrictURLFromAscii( ".uno:OpenHyperlink" ); |
| |
| Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aHyperLink, ::rtl::OUString() , 0); |
| |
| if ( xDisp.is() ) |
| { |
| Sequence<PropertyValue> aProps(3); |
| aProps[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL")); |
| aProps[0].Value <<= aURL.Complete; |
| |
| aProps[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FrameName")); |
| aProps[1].Value = xSet->getPropertyValue(PROPERTY_TARGET_FRAME); |
| |
| aProps[2].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer")); |
| aProps[2].Value <<= xModel->getURL(); |
| |
| xDisp->dispatch( aHyperLink, aProps ); |
| } |
| } |
| } break; |
| default: |
| { |
| // notify the action listeners for a push button |
| ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand); |
| m_aActionListeners.notifyEach( &XActionListener::actionPerformed, aEvt ); |
| } |
| } |
| } |
| |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException) |
| { |
| m_aSubmissionVetoListeners.addInterface( listener ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException) |
| { |
| m_aSubmissionVetoListeners.removeInterface( listener ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler ) throw (VetoException, WrappedTargetException, RuntimeException) |
| { |
| implSubmit( MouseEvent(), _rxHandler ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseControl::submit( ) throw (VetoException, WrappedTargetException, RuntimeException) |
| { |
| implSubmit( MouseEvent(), NULL ); |
| } |
| |
| //-------------------------------------------------------------------- |
| Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseControl::getSupportedServiceNames( ) throw (RuntimeException) |
| { |
| Sequence< ::rtl::OUString > aSupported = OControl::getSupportedServiceNames(); |
| aSupported.realloc( aSupported.getLength() + 1 ); |
| |
| ::rtl::OUString* pArray = aSupported.getArray(); |
| pArray[ aSupported.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON; |
| |
| return aSupported; |
| } |
| |
| //-------------------------------------------------------------------- |
| void OClickableImageBaseControl::implSubmit( const MouseEvent& _rEvent, const Reference< XInteractionHandler >& _rxHandler ) SAL_THROW((VetoException, WrappedTargetException, RuntimeException)) |
| { |
| try |
| { |
| // allow the veto listeners to join the game |
| m_aSubmissionVetoListeners.notifyEach( &XSubmissionVetoListener::submitting, EventObject( *this ) ); |
| |
| // see whether there's an "submit interceptor" set at our model |
| Reference< submission::XSubmissionSupplier > xSubmissionSupp( getModel(), UNO_QUERY ); |
| Reference< XSubmission > xSubmission; |
| if ( xSubmissionSupp.is() ) |
| xSubmission = xSubmissionSupp->getSubmission(); |
| |
| if ( xSubmission.is() ) |
| { |
| if ( !_rxHandler.is() ) |
| xSubmission->submit(); |
| else |
| xSubmission->submitWithInteraction( _rxHandler ); |
| } |
| else |
| { |
| // no "interceptor" -> ordinary (old-way) submission |
| Reference< XChild > xChild( getModel(), UNO_QUERY ); |
| Reference< XSubmit > xParentSubmission; |
| if ( xChild.is() ) |
| xParentSubmission = xParentSubmission.query( xChild->getParent() ); |
| if ( xParentSubmission.is() ) |
| xParentSubmission->submit( this, _rEvent ); |
| } |
| } |
| catch( const VetoException& ) |
| { |
| // allowed to leave |
| throw; |
| } |
| catch( const RuntimeException& ) |
| { |
| // allowed to leave |
| throw; |
| } |
| catch( const WrappedTargetException& e ) |
| { |
| // allowed to leave |
| throw; |
| } |
| catch( const Exception& e ) |
| { |
| OSL_ENSURE( sal_False, "OClickableImageBaseControl::implSubmit: caught an unknown exception!" ); |
| throw WrappedTargetException( ::rtl::OUString(), *this, makeAny( e ) ); |
| } |
| } |
| |
| //================================================================== |
| // OClickableImageBaseModel |
| //================================================================== |
| //------------------------------------------------------------------------------ |
| Sequence<Type> OClickableImageBaseModel::_getTypes() |
| { |
| return concatSequences( |
| OControlModel::_getTypes(), |
| OClickableImageBaseModel_Base::getTypes() |
| ); |
| } |
| |
| //------------------------------------------------------------------ |
| DBG_NAME( OClickableImageBaseModel ) |
| //------------------------------------------------------------------ |
| OClickableImageBaseModel::OClickableImageBaseModel( const Reference< XMultiServiceFactory >& _rxFactory, const ::rtl::OUString& _rUnoControlModelTypeName, |
| const ::rtl::OUString& rDefault ) |
| :OControlModel( _rxFactory, _rUnoControlModelTypeName, rDefault ) |
| ,OPropertyChangeListener(m_aMutex) |
| ,m_pMedium(NULL) |
| ,m_pProducer( NULL ) |
| ,m_bDispatchUrlInternal(sal_False) |
| ,m_bDownloading(sal_False) |
| ,m_bProdStarted(sal_False) |
| { |
| DBG_CTOR( OClickableImageBaseModel, NULL ); |
| implConstruct(); |
| m_eButtonType = FormButtonType_PUSH; |
| } |
| |
| //------------------------------------------------------------------ |
| OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory ) |
| :OControlModel( _pOriginal, _rxFactory ) |
| ,OPropertyChangeListener( m_aMutex ) |
| ,m_pMedium( NULL ) |
| ,m_pProducer( NULL ) |
| ,m_bDispatchUrlInternal(sal_False) |
| ,m_bDownloading( sal_False ) |
| ,m_bProdStarted( sal_False ) |
| { |
| DBG_CTOR( OClickableImageBaseModel, NULL ); |
| implConstruct(); |
| |
| // copy properties |
| m_eButtonType = _pOriginal->m_eButtonType; |
| m_sTargetURL = _pOriginal->m_sTargetURL; |
| m_sTargetFrame = _pOriginal->m_sTargetFrame; |
| m_bDispatchUrlInternal = _pOriginal->m_bDispatchUrlInternal; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::implInitializeImageURL( ) |
| { |
| osl_incrementInterlockedCount( &m_refCount ); |
| { |
| // simulate a propertyChanged event for the ImageURL |
| // 2003-05-15 - #109591# - fs@openoffice.org |
| Any aImageURL; |
| getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL ); |
| _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL, sal_False, PROPERTY_ID_IMAGE_URL, Any( ), aImageURL ) ); |
| } |
| osl_decrementInterlockedCount( &m_refCount ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::implConstruct() |
| { |
| m_pProducer = new ImageProducer; |
| increment( m_refCount ); |
| { |
| m_xProducer = m_pProducer; |
| |
| if ( m_xAggregateSet.is() ) |
| { |
| OPropertyChangeMultiplexer* pMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet ); |
| pMultiplexer->addProperty( PROPERTY_IMAGE_URL ); |
| } |
| } |
| decrement(m_refCount); |
| } |
| |
| //------------------------------------------------------------------------------ |
| OClickableImageBaseModel::~OClickableImageBaseModel() |
| { |
| if (!OComponentHelper::rBHelper.bDisposed) |
| { |
| acquire(); |
| dispose(); |
| } |
| DBG_ASSERT(m_pMedium == NULL, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ..."); |
| // spaetestens im dispose sollte das aufgeraeumt worden sein |
| |
| DBG_DTOR( OClickableImageBaseModel, NULL ); |
| } |
| |
| // XImageProducer |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) |
| { |
| ImageModelMethodGuard aGuard( *this ); |
| GetImageProducer()->addConsumer( _rxConsumer ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException) |
| { |
| ImageModelMethodGuard aGuard( *this ); |
| GetImageProducer()->removeConsumer( _rxConsumer ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseModel::startProduction( ) throw (RuntimeException) |
| { |
| ImageModelMethodGuard aGuard( *this ); |
| GetImageProducer()->startProduction(); |
| } |
| |
| //-------------------------------------------------------------------- |
| Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission() throw (RuntimeException) |
| { |
| return m_xSubmissionDelegate; |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL OClickableImageBaseModel::setSubmission( const Reference< submission::XSubmission >& _submission ) throw (RuntimeException) |
| { |
| m_xSubmissionDelegate = _submission; |
| } |
| |
| //-------------------------------------------------------------------- |
| Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseModel::getSupportedServiceNames( ) throw (RuntimeException) |
| { |
| Sequence< ::rtl::OUString > aSupported = OControlModel::getSupportedServiceNames(); |
| aSupported.realloc( aSupported.getLength() + 1 ); |
| |
| ::rtl::OUString* pArray = aSupported.getArray(); |
| pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON; |
| |
| return aSupported; |
| } |
| |
| // OComponentHelper |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::disposing() |
| { |
| OControlModel::disposing(); |
| if (m_pMedium) |
| { |
| delete m_pMedium; |
| m_pMedium = NULL; |
| } |
| |
| m_xProducer = NULL; |
| m_pProducer = NULL; |
| } |
| |
| //------------------------------------------------------------------------------ |
| Any SAL_CALL OClickableImageBaseModel::queryAggregation(const Type& _rType) throw (RuntimeException) |
| { |
| // order matters: |
| // we definately want to "overload" the XImageProducer interface of our aggregate, |
| // thus check OClickableImageBaseModel_Base (which provides this) first |
| Any aReturn = OClickableImageBaseModel_Base::queryInterface( _rType ); |
| |
| // BUT: _don't_ let it feel responsible for the XTypeProvider interface |
| // (as this is implemented by our base class in the proper way) |
| if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) |
| || !aReturn.hasValue() |
| ) |
| aReturn = OControlModel::queryAggregation( _rType ); |
| |
| return aReturn; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const |
| { |
| switch (nHandle) |
| { |
| case PROPERTY_ID_BUTTONTYPE : rValue <<= m_eButtonType; break; |
| case PROPERTY_ID_TARGET_URL : rValue <<= m_sTargetURL; break; |
| case PROPERTY_ID_TARGET_FRAME : rValue <<= m_sTargetFrame; break; |
| case PROPERTY_ID_DISPATCHURLINTERNAL : rValue <<= m_bDispatchUrlInternal; break; |
| default: |
| OControlModel::getFastPropertyValue(rValue, nHandle); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( Exception) |
| { |
| switch (nHandle) |
| { |
| case PROPERTY_ID_BUTTONTYPE : |
| DBG_ASSERT(isA(rValue, static_cast<FormButtonType*>(NULL)), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); |
| rValue >>= m_eButtonType; |
| break; |
| |
| case PROPERTY_ID_TARGET_URL : |
| DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); |
| rValue >>= m_sTargetURL; |
| break; |
| |
| case PROPERTY_ID_TARGET_FRAME : |
| DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); |
| rValue >>= m_sTargetFrame; |
| break; |
| |
| case PROPERTY_ID_DISPATCHURLINTERNAL: |
| DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" ); |
| rValue >>= m_bDispatchUrlInternal; |
| break; |
| |
| default: |
| OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| sal_Bool OClickableImageBaseModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) |
| throw( IllegalArgumentException ) |
| { |
| switch (nHandle) |
| { |
| case PROPERTY_ID_BUTTONTYPE : |
| return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType ); |
| |
| case PROPERTY_ID_TARGET_URL : |
| return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL); |
| |
| case PROPERTY_ID_TARGET_FRAME : |
| return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame); |
| |
| case PROPERTY_ID_DISPATCHURLINTERNAL : |
| return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal); |
| |
| default: |
| return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::StartProduction() |
| { |
| ImageProducer *pImgProd = GetImageProducer(); |
| // grab the ImageURL |
| rtl::OUString sURL; |
| getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ImageURL") ) ) >>= sURL; |
| if (!m_pMedium) |
| { |
| if ( ::svt::GraphicAccess::isSupportedURL( sURL ) ) |
| pImgProd->SetImage( sURL ); |
| else |
| // caution: the medium may be NULL if somebody gave us a invalid URL to work with |
| // 11/24/2000 - 79667 - FS |
| pImgProd->SetImage(String()); |
| m_bDownloading = sal_False; |
| return; |
| } |
| if (m_pMedium->GetErrorCode()==0) |
| { |
| SvStream* pStream = m_pMedium->GetInStream(); |
| |
| pImgProd->SetImage(*pStream); |
| pImgProd->startProduction(); |
| m_bProdStarted = sal_True; |
| } |
| else |
| { |
| pImgProd->SetImage(String()); |
| delete m_pMedium; |
| m_pMedium = 0; |
| m_bDownloading = sal_False; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::SetURL( const ::rtl::OUString& rURL ) |
| { |
| if (m_pMedium || !rURL.getLength()) |
| { |
| // Den Stream am Producer freigeben, bevor das Medium geloscht wird. |
| GetImageProducer()->SetImage(String()); |
| delete m_pMedium; |
| m_pMedium = NULL; |
| } |
| |
| // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first |
| // 23.01.2001 - 81927 - FS |
| INetURLObject aUrl(rURL); |
| if (INET_PROT_NOT_VALID == aUrl.GetProtocol()) |
| // we treat an invalid URL like we would treat no URL |
| return; |
| |
| if (rURL.getLength() && !::svt::GraphicAccess::isSupportedURL( rURL ) ) |
| { |
| if (m_pMedium) |
| delete m_pMedium; |
| |
| m_pMedium = new SfxMedium(rURL, STREAM_STD_READ, sal_False); |
| m_pMedium->SetDataAvailableLink( |
| STATIC_LINK(this, OClickableImageBaseModel, DataAvailableLink)); |
| |
| // Das XModel suchen, um an die Object-Shell oder zumindest den |
| // Referer zu gelangen. |
| // Das Model findet man allerdings nur beim Laden von HTML-Dokumenten |
| // und dann, wenn die URL in einem bereits geladenen Dokument |
| // geaendert wird. Waehrend des Ladens kommt man nicht an das |
| // Model ran. |
| Reference< XModel > xModel; |
| InterfaceRef xIfc( *this ); |
| while( !xModel.is() && xIfc.is() ) |
| { |
| Reference<XChild> xChild( xIfc, UNO_QUERY ); |
| xIfc = xChild->getParent(); |
| query_interface(xIfc, xModel); |
| } |
| |
| // Die Object-Shell suchen, indem wir |
| // ueber alle Object-Shells iterieren und deren XModel mit dem |
| // eigenen vergleichen. Als Optimierung probieren wir aber erstmal |
| // die aktuelle Object-Shell. |
| // wir unser XModel mit dem aller Object |
| SfxObjectShell *pObjSh = 0; |
| |
| if( xModel.is() ) |
| { |
| SfxObjectShell *pTestObjSh = SfxObjectShell::Current(); |
| if( pTestObjSh ) |
| { |
| Reference< XModel > xTestModel = pTestObjSh->GetModel(); |
| if( xTestModel == xModel ) |
| pObjSh = pTestObjSh; |
| } |
| if( !pObjSh ) |
| { |
| pTestObjSh = SfxObjectShell::GetFirst(); |
| while( !pObjSh && pTestObjSh ) |
| { |
| Reference< XModel > xTestModel = pTestObjSh->GetModel(); |
| if( xTestModel == xModel ) |
| pObjSh = pTestObjSh; |
| else |
| pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh ); |
| } |
| } |
| } |
| |
| #ifdef USE_REGISTER_TRANSFER |
| if( pObjSh ) |
| { |
| // Medium registrieren, damit abgebrochen werden kann |
| pObjSh->RegisterTransfer( *m_pMedium ); |
| |
| // Target-Frame uebertragen, damit auch javascript:-URLs |
| // "geladen" werden koennen. |
| const SfxMedium *pShMedium = pObjSh->GetMedium(); |
| if( pShMedium ) |
| m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); |
| } |
| else |
| { |
| // Keine Object-Shell, aber ein Medium? Dann uebernehmen wir |
| // zumindest den Referer. |
| if( xModel.is() ) |
| { |
| ::rtl::OUString sReferer( xModel->getURL() ); |
| if( sReferer.getLength() ) |
| m_pMedium->SetReferer( OUStringToString(sReferer, CHARSET_SYSTEM) ); |
| } |
| } |
| #else |
| if( pObjSh ) |
| { |
| // Target-Frame uebertragen, damit auch javascript:-URLs |
| // "geladen" werden koennen. |
| const SfxMedium *pShMedium = pObjSh->GetMedium(); |
| if( pShMedium ) |
| m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame()); |
| } |
| |
| if( xModel.is() ) |
| { |
| ::rtl::OUString sReferer( xModel->getURL() ); |
| if( sReferer.getLength() ) |
| m_pMedium->SetReferer( sReferer ); |
| } |
| #endif |
| |
| // Downloading-Flag auf sal_True setzen. Es werden dann auch |
| // Data-Available-Links, wenn wir in den Pending-Staus gelangen. |
| m_bDownloading = sal_True; |
| m_bProdStarted = sal_False; |
| |
| // Download anstossen (Achtung: Kann auch synchron sein). |
| m_pMedium->DownLoad(STATIC_LINK(this, OClickableImageBaseModel, DownloadDoneLink)); |
| } |
| else |
| { |
| if ( ::svt::GraphicAccess::isSupportedURL( rURL ) ) |
| GetImageProducer()->SetImage( rURL ); |
| GetImageProducer()->startProduction(); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::DataAvailable() |
| { |
| if (!m_bProdStarted) |
| StartProduction(); |
| |
| GetImageProducer()->NewDataAvailable(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::DownloadDone() |
| { |
| DataAvailable(); |
| m_bDownloading = sal_False; |
| } |
| |
| //------------------------------------------------------------------------------ |
| IMPL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void*, EMPTYARG ) |
| { |
| ::osl::MutexGuard aGuard( pThis->m_aMutex ); |
| pThis->DownloadDone(); |
| return 0; |
| } |
| |
| //------------------------------------------------------------------------------ |
| IMPL_STATIC_LINK( OClickableImageBaseModel, DataAvailableLink, void*, EMPTYARG ) |
| { |
| ::osl::MutexGuard aGuard( pThis->m_aMutex ); |
| pThis->DataAvailable(); |
| return 0; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt ) |
| throw( RuntimeException ) |
| { |
| // Wenn eine URL gesetzt worden ist, muss die noch an den ImageProducer |
| // weitergereicht werden. |
| ::osl::MutexGuard aGuard(m_aMutex); |
| SetURL( getString(rEvt.NewValue) ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const |
| { |
| switch (nHandle) |
| { |
| case PROPERTY_ID_BUTTONTYPE : return makeAny( FormButtonType_PUSH ); |
| case PROPERTY_ID_TARGET_URL : |
| case PROPERTY_ID_TARGET_FRAME : return makeAny( ::rtl::OUString() ); |
| case PROPERTY_ID_DISPATCHURLINTERNAL : return makeAny( sal_False ); |
| default: |
| return OControlModel::getPropertyDefaultByHandle(nHandle); |
| } |
| } |
| |
| //================================================================== |
| // OImageProducerThread_Impl |
| //================================================================== |
| //------------------------------------------------------------------ |
| EventObject* OImageProducerThread_Impl::cloneEvent( const EventObject* _pEvt ) const |
| { |
| return new EventObject( *_pEvt ); |
| } |
| |
| //------------------------------------------------------------------ |
| void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper *pCompImpl, |
| const EventObject* pEvt, |
| const Reference<XControl>&, |
| sal_Bool ) |
| { |
| ((OClickableImageBaseControl *)pCompImpl)->actionPerformed_Impl( sal_True, *(MouseEvent *)pEvt ); |
| } |
| |
| //......................................................................... |
| } // namespace frm |
| //......................................................................... |
| |