1072 lines
42 KiB
C++
1072 lines
42 KiB
C++
/*************************************************************************
|
|
*
|
|
* $RCSfile: clickableimage.cxx,v $
|
|
*
|
|
* $Revision: 1.3 $
|
|
*
|
|
* last change: $Author: rt $ $Date: 2004-12-10 17:12:27 $
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* either of the following licenses
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
*
|
|
* Sun Microsystems Inc., October, 2000
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
*
|
|
* Sun Industry Standards Source License Version 1.1
|
|
* =================================================
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
* Source License Version 1.1 (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.openoffice.org/license.html.
|
|
*
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
* See the License for the specific provisions governing your rights and
|
|
* obligations concerning the Software.
|
|
*
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): _______________________________________
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
#ifndef FORMS_SOURCE_CLICKABLEIMAGE_HXX
|
|
#include "clickableimage.hxx"
|
|
#endif
|
|
#ifndef FORMS_SOURCE_INC_CONTROLFEATUREINTERCEPTION_HXX
|
|
#include "controlfeatureinterception.hxx"
|
|
#endif
|
|
#ifndef FORMS_SOURCE_INC_URLTRANSFORMER_HXX
|
|
#include "urltransformer.hxx"
|
|
#endif
|
|
|
|
#ifndef _COM_SUN_STAR_FORM_XSUBMIT_HPP_
|
|
#include <com/sun/star/form/XSubmit.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_AWT_SYSTEMPOINTER_HPP_
|
|
#include <com/sun/star/awt/SystemPointer.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_FORM_FORMCOMPONENTTYPE_HPP_
|
|
#include <com/sun/star/form/FormComponentType.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_FRAME_XDISPATCH_HPP_
|
|
#include <com/sun/star/frame/XDispatch.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDER_HPP_
|
|
#include <com/sun/star/frame/XDispatchProvider.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_
|
|
#include <com/sun/star/frame/FrameSearchFlag.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
|
|
#include <com/sun/star/frame/XController.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
|
|
#include <com/sun/star/frame/XFrame.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_AWT_ACTIONEVENT_HPP_
|
|
#include <com/sun/star/awt/ActionEvent.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_AWT_XACTIONLISTENER_HPP_
|
|
#include <com/sun/star/awt/XActionListener.hpp>
|
|
#endif
|
|
|
|
#ifndef _URLOBJ_HXX
|
|
#include <tools/urlobj.hxx>
|
|
#endif
|
|
#ifndef _TOOLS_DEBUG_HXX
|
|
#include <tools/debug.hxx>
|
|
#endif
|
|
#ifndef _SV_SVAPP_HXX
|
|
#include <vcl/svapp.hxx>
|
|
#endif
|
|
#ifndef _SFXDOCFILE_HXX
|
|
#include <sfx2/docfile.hxx>
|
|
#endif
|
|
#ifndef _SFX_OBJSH_HXX //autogen
|
|
#include <sfx2/objsh.hxx>
|
|
#endif
|
|
#ifndef _VOS_MUTEX_HXX_
|
|
#include <vos/mutex.hxx>
|
|
#endif
|
|
|
|
#ifndef _FRM_SERVICES_HXX_
|
|
#include "services.hxx"
|
|
#endif
|
|
#ifndef _COMPHELPER_CONTAINER_HXX_
|
|
#include <comphelper/container.hxx>
|
|
#endif
|
|
#ifndef COMPHELPER_INC_COMPHELPER_LISTENERNOTIFICATION_HXX
|
|
#include <comphelper/listenernotification.hxx>
|
|
#endif
|
|
|
|
#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;
|
|
|
|
//====================================================================
|
|
//= SubmissionVetoListeners
|
|
//====================================================================
|
|
typedef ::comphelper::OListenerContainerBase < XSubmissionVetoListener
|
|
, EventObject
|
|
> SubmissionVetoListeners_Base;
|
|
|
|
class SubmissionVetoListeners : public SubmissionVetoListeners_Base
|
|
{
|
|
public:
|
|
SubmissionVetoListeners( ::osl::Mutex& _rMutex )
|
|
:SubmissionVetoListeners_Base( _rMutex )
|
|
{
|
|
}
|
|
|
|
protected:
|
|
virtual bool implNotify(
|
|
const Reference< XSubmissionVetoListener >& _rxListener,
|
|
const EventObject& _rEvent
|
|
) SAL_THROW( ( Exception ) );
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool SubmissionVetoListeners::implNotify( const Reference< XSubmissionVetoListener >& _rxListener, const EventObject& _rEvent ) SAL_THROW( ( Exception ) )
|
|
{
|
|
_rxListener->submitting( _rEvent );
|
|
return true; // continue calling listeners
|
|
}
|
|
|
|
//==================================================================
|
|
// 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_aApproveActionListeners(m_aMutex)
|
|
,m_aActionListeners(m_aMutex)
|
|
,m_pThread(NULL)
|
|
{
|
|
m_pSubmissionVetoListeners.reset( new SubmissionVetoListeners( 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_pSubmissionVetoListeners->disposing( aEvent );
|
|
m_pFeatureInterception->dispose();
|
|
|
|
{
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
if( m_pThread )
|
|
{
|
|
m_pThread->release();
|
|
m_pThread = NULL;
|
|
}
|
|
}
|
|
|
|
OControl::disposing();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Reference< XModel > OClickableImageBaseControl::getXModel(const InterfaceRef& xIface) const
|
|
{
|
|
Reference< XModel > xModel(xIface, UNO_QUERY);
|
|
if (xModel.is())
|
|
return xModel;
|
|
else
|
|
{
|
|
Reference<XChild> xChild(xIface, UNO_QUERY);
|
|
if (xChild.is())
|
|
{
|
|
InterfaceRef xParent = xChild->getParent();
|
|
return getXModel(xParent);
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
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);
|
|
NOTIFY_LISTENERS(m_aActionListeners, XActionListener, actionPerformed, aEvt);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException)
|
|
{
|
|
m_pSubmissionVetoListeners->addListener( listener );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException)
|
|
{
|
|
m_pSubmissionVetoListeners->removeListener( 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_pSubmissionVetoListeners->notify( 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 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_pProducer( NULL )
|
|
,m_pMedium(NULL)
|
|
,m_bDownloading(sal_False)
|
|
,m_bProdStarted(sal_False)
|
|
,m_bDispatchUrlInternal(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_pProducer( NULL )
|
|
,m_pMedium( NULL )
|
|
,m_bDownloading( sal_False )
|
|
,m_bProdStarted( sal_False )
|
|
,m_bDispatchUrlInternal(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)
|
|
{
|
|
GetImageProducer()->addConsumer( _rxConsumer );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException)
|
|
{
|
|
GetImageProducer()->removeConsumer( _rxConsumer );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void SAL_CALL OClickableImageBaseModel::startProduction( ) throw (RuntimeException)
|
|
{
|
|
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;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
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();
|
|
if (!m_pMedium)
|
|
{
|
|
// 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())
|
|
{
|
|
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 )
|
|
{
|
|
SfxObjectShell *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) );
|
|
}
|
|
|
|
// Keinen Eintrag im Roter Button Menu
|
|
m_pMedium->SetDontCreateCancellable();
|
|
}
|
|
#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 );
|
|
}
|
|
|
|
// Keinen Eintrag im Roter Button Menu
|
|
m_pMedium->SetDontCreateCancellable();
|
|
#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
|
|
{
|
|
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) );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
PropertyState OClickableImageBaseModel::getPropertyStateByHandle(sal_Int32 nHandle)
|
|
{
|
|
PropertyState eState;
|
|
switch (nHandle)
|
|
{
|
|
case PROPERTY_ID_DISPATCHURLINTERNAL:
|
|
if ( m_bDispatchUrlInternal )
|
|
eState = PropertyState_DIRECT_VALUE;
|
|
else
|
|
eState = PropertyState_DEFAULT_VALUE;
|
|
break;
|
|
default:
|
|
eState = OControlModel::getPropertyStateByHandle(nHandle);
|
|
}
|
|
return eState;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
void OClickableImageBaseModel::setPropertyToDefaultByHandle(sal_Int32 nHandle)
|
|
{
|
|
switch (nHandle)
|
|
{
|
|
case PROPERTY_ID_DISPATCHURLINTERNAL:
|
|
setFastPropertyValue(nHandle, makeAny(sal_False));
|
|
break;
|
|
default:
|
|
OControlModel::setPropertyToDefaultByHandle(nHandle);
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
|
|
{
|
|
switch (nHandle)
|
|
{
|
|
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
|
|
//.........................................................................
|
|
|