Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "clickableimage.hxx"
30 : : #include "controlfeatureinterception.hxx"
31 : : #include "urltransformer.hxx"
32 : : #include "componenttools.hxx"
33 : : #include <com/sun/star/form/XSubmit.hpp>
34 : : #include <com/sun/star/awt/SystemPointer.hpp>
35 : : #include <com/sun/star/form/FormComponentType.hpp>
36 : : #include <com/sun/star/frame/XDispatch.hpp>
37 : : #include <com/sun/star/frame/XDispatchProvider.hpp>
38 : : #include <com/sun/star/frame/FrameSearchFlag.hpp>
39 : : #include <com/sun/star/frame/XController.hpp>
40 : : #include <com/sun/star/frame/XFrame.hpp>
41 : : #include <com/sun/star/awt/ActionEvent.hpp>
42 : : #include <com/sun/star/awt/XActionListener.hpp>
43 : : #include <tools/urlobj.hxx>
44 : : #include <tools/debug.hxx>
45 : : #include <vcl/svapp.hxx>
46 : : #include <sfx2/docfile.hxx>
47 : : #include <sfx2/objsh.hxx>
48 : : #include <osl/mutex.hxx>
49 : : #include "services.hxx"
50 : : #include <comphelper/container.hxx>
51 : : #include <comphelper/listenernotification.hxx>
52 : : #include <svtools/imageresourceaccess.hxx>
53 : : #define LOCAL_URL_PREFIX '#'
54 : :
55 : : //.........................................................................
56 : : namespace frm
57 : : {
58 : : //.........................................................................
59 : :
60 : : using namespace ::com::sun::star::uno;
61 : : using namespace ::com::sun::star::sdb;
62 : : using namespace ::com::sun::star::sdbc;
63 : : using namespace ::com::sun::star::sdbcx;
64 : : using namespace ::com::sun::star::beans;
65 : : using namespace ::com::sun::star::container;
66 : : using namespace ::com::sun::star::form;
67 : : using namespace ::com::sun::star::awt;
68 : : using namespace ::com::sun::star::io;
69 : : using namespace ::com::sun::star::lang;
70 : : using namespace ::com::sun::star::util;
71 : : using namespace ::com::sun::star::frame;
72 : : using namespace ::com::sun::star::form::submission;
73 : : using ::com::sun::star::awt::MouseEvent;
74 : : using ::com::sun::star::task::XInteractionHandler;
75 : :
76 : : //==================================================================
77 : : // OClickableImageBaseControl
78 : : //==================================================================
79 : : //------------------------------------------------------------------------------
80 : 64 : Sequence<Type> OClickableImageBaseControl::_getTypes()
81 : : {
82 [ + + ][ + - ]: 64 : static Sequence<Type> aTypes;
[ + - ][ # # ]
83 [ + + ]: 64 : if (!aTypes.getLength())
84 [ + - ][ + - ]: 6 : aTypes = concatSequences(OControl::_getTypes(), OClickableImageBaseControl_BASE::getTypes());
[ + - ][ + - ]
[ + - ]
85 : 64 : return aTypes;
86 : : }
87 : :
88 : : //------------------------------------------------------------------------------
89 : 95 : OClickableImageBaseControl::OClickableImageBaseControl(const Reference<XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _aService)
90 : : :OControl(_rxFactory, _aService)
91 : : ,m_pThread(NULL)
92 : : ,m_aSubmissionVetoListeners( m_aMutex )
93 : : ,m_aApproveActionListeners( m_aMutex )
94 [ + - ][ + - ]: 95 : ,m_aActionListeners( m_aMutex )
[ + - ][ + - ]
95 : : {
96 [ + - ][ + - ]: 95 : m_pFeatureInterception.reset( new ControlFeatureInterception( _rxFactory ) );
97 : 95 : }
98 : :
99 : : //------------------------------------------------------------------------------
100 [ + - ][ + - ]: 95 : OClickableImageBaseControl::~OClickableImageBaseControl()
[ + - ][ + - ]
[ + - ]
101 : : {
102 [ - + ]: 95 : if (!OComponentHelper::rBHelper.bDisposed)
103 : : {
104 : 0 : acquire();
105 [ # # ]: 0 : dispose();
106 : : }
107 [ - + ]: 95 : }
108 : :
109 : : // UNO Anbindung
110 : : //------------------------------------------------------------------------------
111 : 2326 : Any SAL_CALL OClickableImageBaseControl::queryAggregation(const Type& _rType) throw (RuntimeException)
112 : : {
113 : 2326 : Any aReturn = OControl::queryAggregation(_rType);
114 [ + + ]: 2326 : if (!aReturn.hasValue())
115 [ + - ]: 278 : aReturn = OClickableImageBaseControl_BASE::queryInterface(_rType);
116 : 2326 : return aReturn;
117 : : }
118 : :
119 : : // XApproveActionBroadcaster
120 : : //------------------------------------------------------------------------------
121 : 4 : void OClickableImageBaseControl::addApproveActionListener(
122 : : const Reference<XApproveActionListener>& l) throw( RuntimeException )
123 : : {
124 : 4 : m_aApproveActionListeners.addInterface(l);
125 : 4 : }
126 : :
127 : : //------------------------------------------------------------------------------
128 : 4 : void OClickableImageBaseControl::removeApproveActionListener(
129 : : const Reference<XApproveActionListener>& l) throw( RuntimeException )
130 : : {
131 : 4 : m_aApproveActionListeners.removeInterface(l);
132 : 4 : }
133 : :
134 : : //--------------------------------------------------------------------
135 : 18 : void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException)
136 : : {
137 : 18 : m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor );
138 : 18 : }
139 : :
140 : : //--------------------------------------------------------------------
141 : 18 : void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException)
142 : : {
143 : 18 : m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor );
144 : 18 : }
145 : :
146 : : // OComponentHelper
147 : : //------------------------------------------------------------------------------
148 : 95 : void OClickableImageBaseControl::disposing()
149 : : {
150 [ + - ][ + - ]: 95 : EventObject aEvent( static_cast< XWeak* >( this ) );
151 [ + - ]: 95 : m_aApproveActionListeners.disposeAndClear( aEvent );
152 [ + - ]: 95 : m_aActionListeners.disposeAndClear( aEvent );
153 [ + - ]: 95 : m_aSubmissionVetoListeners.disposeAndClear( aEvent );
154 [ + - ]: 95 : m_pFeatureInterception->dispose();
155 : :
156 : : {
157 [ + - ]: 95 : ::osl::MutexGuard aGuard( m_aMutex );
158 [ - + ]: 95 : if( m_pThread )
159 : : {
160 : 0 : m_pThread->release();
161 : 0 : m_pThread = NULL;
162 [ + - ]: 95 : }
163 : : }
164 : :
165 [ + - ][ + - ]: 95 : OControl::disposing();
166 : 95 : }
167 : :
168 : : //------------------------------------------------------------------------------
169 : 0 : OImageProducerThread_Impl* OClickableImageBaseControl::getImageProducerThread()
170 : : {
171 [ # # ]: 0 : if ( !m_pThread )
172 : : {
173 [ # # ][ # # ]: 0 : m_pThread = new OImageProducerThread_Impl( this );
174 : 0 : m_pThread->acquire();
175 : 0 : m_pThread->create();
176 : : }
177 : 0 : return m_pThread;
178 : : }
179 : :
180 : : //------------------------------------------------------------------------------
181 : 0 : bool OClickableImageBaseControl::approveAction( )
182 : : {
183 : 0 : sal_Bool bCancelled = sal_False;
184 [ # # ][ # # ]: 0 : EventObject aEvent( static_cast< XWeak* >( this ) );
185 : :
186 [ # # ]: 0 : ::cppu::OInterfaceIteratorHelper aIter( m_aApproveActionListeners );
187 [ # # ][ # # ]: 0 : while( !bCancelled && aIter.hasMoreElements() )
[ # # ]
188 : : {
189 : : // Jede approveAction-Methode muss thread-safe sein!!!
190 [ # # ][ # # ]: 0 : if( !static_cast< XApproveActionListener* >( aIter.next() )->approveAction( aEvent ) )
[ # # ]
191 : 0 : bCancelled = sal_True;
192 : : }
193 : :
194 [ # # ][ # # ]: 0 : return !bCancelled;
195 : : }
196 : :
197 : : //------------------------------------------------------------------------------
198 : : // Diese Methode wird auch aus einem Thread gerufen und muss deshalb
199 : : // thread-safe sein.
200 : 0 : void OClickableImageBaseControl::actionPerformed_Impl(sal_Bool bNotifyListener, const MouseEvent& rEvt)
201 : : {
202 [ # # ]: 0 : if( bNotifyListener )
203 : : {
204 [ # # ][ # # ]: 0 : if ( !approveAction() )
205 : : return;
206 : : }
207 : :
208 : : // Ob der Rest des Codes Thread-Safe ist weiss man nicht genau. Deshalb
209 : : // wird das meiste bei gelocktem Solar-Mutex erledigen.
210 : 0 : Reference<XPropertySet> xSet;
211 : 0 : Reference< XInterface > xModelsParent;
212 : 0 : FormButtonType eButtonType = FormButtonType_PUSH;
213 : : {
214 [ # # ]: 0 : SolarMutexGuard aGuard;
215 : :
216 : : // Parent holen
217 [ # # ][ # # ]: 0 : Reference<XFormComponent> xComp(getModel(), UNO_QUERY);
218 [ # # ]: 0 : if (!xComp.is())
219 : : return;
220 : :
221 [ # # ][ # # ]: 0 : xModelsParent = xComp->getParent();
[ # # ]
222 [ # # ]: 0 : if (!xModelsParent.is())
223 : : return;
224 : :
225 : : // which button type?
226 [ # # ][ # # ]: 0 : xSet = xSet.query( xComp );
227 [ # # ]: 0 : if ( !xSet.is() )
228 : : return;
229 [ # # ][ # # ]: 0 : xSet->getPropertyValue(PROPERTY_BUTTONTYPE) >>= eButtonType;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
230 : : }
231 : :
232 [ # # # # ]: 0 : switch (eButtonType)
233 : : {
234 : : case FormButtonType_RESET:
235 : : {
236 : : // reset-Methoden muessen thread-safe sein!
237 [ # # ]: 0 : Reference<XReset> xReset(xModelsParent, UNO_QUERY);
238 [ # # ]: 0 : if (!xReset.is())
239 : : return;
240 : :
241 [ # # ][ # # ]: 0 : xReset->reset();
[ # # ]
242 : : }
243 : 0 : break;
244 : :
245 : : case FormButtonType_SUBMIT:
246 : : {
247 : : // if some outer component can provide an interaction handler, use it
248 [ # # ][ # # ]: 0 : Reference< XInteractionHandler > xHandler( m_pFeatureInterception->queryDispatch( "private:/InteractionHandler" ), UNO_QUERY );
[ # # ]
249 : : try
250 : : {
251 [ # # ]: 0 : implSubmit( rEvt, xHandler );
252 : : }
253 [ # # ]: 0 : catch( const Exception& )
254 : : {
255 : : // ignore
256 : 0 : }
257 : : }
258 : 0 : break;
259 : :
260 : : case FormButtonType_URL:
261 : : {
262 [ # # ]: 0 : SolarMutexGuard aGuard;
263 : :
264 [ # # ]: 0 : Reference< XModel > xModel = getXModel(xModelsParent);
265 [ # # ]: 0 : if (!xModel.is())
266 : : return;
267 : :
268 : : ///////////////////////////////////////////////////////////////////////
269 : : // Jetzt URL ausfuehren
270 [ # # ][ # # ]: 0 : Reference< XController > xController = xModel->getCurrentController();
271 [ # # ]: 0 : if (!xController.is())
272 : : return;
273 : :
274 [ # # ][ # # ]: 0 : Reference< XFrame > xFrame = xController->getFrame();
275 [ # # ]: 0 : if( !xFrame.is() )
276 : : return;
277 : :
278 : 0 : URL aURL;
279 : : aURL.Complete =
280 [ # # ][ # # ]: 0 : getString(xSet->getPropertyValue(PROPERTY_TARGET_URL));
[ # # ][ # # ]
281 : :
282 [ # # ][ # # ]: 0 : if (!aURL.Complete.isEmpty() && (LOCAL_URL_PREFIX == aURL.Complete.getStr()[0]))
[ # # ]
283 : : { // the URL contains a local URL only. Since the URLTransformer does not handle this case correctly
284 : : // (it can't: it does not know the document URL), we have to take care for this ourself.
285 : : // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all
286 : : // URLs have to be absolute), but for compatibility reasons this is no option.
287 : : // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it
288 : : // could be "#mark" as well.
289 : : // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete
290 : : // solutiuon would be:
291 : : // * recognize URLs consisting of a mark only while _reading_ the document
292 : : // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to
293 : : // transform such mark-only URLs into correct absolute URLs
294 : : // * at the UI, show only the mark
295 : : // * !!!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems
296 : : // rather impossible !!!
297 : 0 : aURL.Mark = aURL.Complete;
298 [ # # ][ # # ]: 0 : aURL.Complete = xModel->getURL();
299 : 0 : aURL.Complete += aURL.Mark;
300 : : }
301 : :
302 : 0 : sal_Bool bDispatchUrlInternal = sal_False;
303 [ # # ][ # # ]: 0 : xSet->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL) >>= bDispatchUrlInternal;
[ # # ]
304 [ # # ]: 0 : if ( bDispatchUrlInternal )
305 : : {
306 [ # # ]: 0 : m_pFeatureInterception->getTransformer().parseSmartWithAsciiProtocol( aURL, INET_FILE_SCHEME );
307 : :
308 : 0 : ::rtl::OUString aTargetFrame;
309 [ # # ][ # # ]: 0 : xSet->getPropertyValue(PROPERTY_TARGET_FRAME) >>= aTargetFrame;
[ # # ]
310 : :
311 [ # # ][ # # ]: 0 : Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch( aURL, aTargetFrame,
312 : : FrameSearchFlag::SELF | FrameSearchFlag::PARENT |
313 [ # # ]: 0 : FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE );
314 : :
315 [ # # ]: 0 : Sequence<PropertyValue> aArgs(1);
316 [ # # ]: 0 : PropertyValue& rProp = aArgs.getArray()[0];
317 [ # # ]: 0 : rProp.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer") );
318 [ # # ][ # # ]: 0 : rProp.Value <<= xModel->getURL();
[ # # ]
319 : :
320 [ # # ]: 0 : if (xDisp.is())
321 [ # # ][ # # ]: 0 : xDisp->dispatch( aURL, aArgs );
[ # # ]
322 : : }
323 : : else
324 : : {
325 [ # # ]: 0 : URL aHyperLink = m_pFeatureInterception->getTransformer().getStrictURLFromAscii( ".uno:OpenHyperlink" );
326 : :
327 [ # # ][ # # ]: 0 : Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aHyperLink, ::rtl::OUString() , 0);
[ # # ]
328 : :
329 [ # # ]: 0 : if ( xDisp.is() )
330 : : {
331 [ # # ]: 0 : Sequence<PropertyValue> aProps(3);
332 [ # # ][ # # ]: 0 : aProps[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"));
333 [ # # ][ # # ]: 0 : aProps[0].Value <<= aURL.Complete;
334 : :
335 [ # # ][ # # ]: 0 : aProps[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FrameName"));
336 [ # # ][ # # ]: 0 : aProps[1].Value = xSet->getPropertyValue(PROPERTY_TARGET_FRAME);
[ # # ][ # # ]
337 : :
338 [ # # ][ # # ]: 0 : aProps[2].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer"));
339 [ # # ][ # # ]: 0 : aProps[2].Value <<= xModel->getURL();
[ # # ][ # # ]
340 : :
341 [ # # ][ # # ]: 0 : xDisp->dispatch( aHyperLink, aProps );
[ # # ]
342 : 0 : }
343 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ]
344 : 0 : } break;
345 : : default:
346 : : {
347 : : // notify the action listeners for a push button
348 [ # # ][ # # ]: 0 : ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand);
349 [ # # ][ # # ]: 0 : m_aActionListeners.notifyEach( &XActionListener::actionPerformed, aEvt );
350 : : }
351 [ # # ][ # # ]: 0 : }
352 : : }
353 : :
354 : :
355 : : //--------------------------------------------------------------------
356 : 0 : void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException)
357 : : {
358 : 0 : m_aSubmissionVetoListeners.addInterface( listener );
359 : 0 : }
360 : :
361 : : //--------------------------------------------------------------------
362 : 0 : void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener ) throw (NoSupportException, RuntimeException)
363 : : {
364 : 0 : m_aSubmissionVetoListeners.removeInterface( listener );
365 : 0 : }
366 : :
367 : : //--------------------------------------------------------------------
368 : 0 : void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler ) throw (VetoException, WrappedTargetException, RuntimeException)
369 : : {
370 [ # # ]: 0 : implSubmit( MouseEvent(), _rxHandler );
371 : 0 : }
372 : :
373 : : //--------------------------------------------------------------------
374 : 0 : void SAL_CALL OClickableImageBaseControl::submit( ) throw (VetoException, WrappedTargetException, RuntimeException)
375 : : {
376 [ # # ][ # # ]: 0 : implSubmit( MouseEvent(), NULL );
[ # # ]
377 : 0 : }
378 : :
379 : : //--------------------------------------------------------------------
380 : 0 : Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseControl::getSupportedServiceNames( ) throw (RuntimeException)
381 : : {
382 : 0 : Sequence< ::rtl::OUString > aSupported = OControl::getSupportedServiceNames();
383 [ # # ]: 0 : aSupported.realloc( aSupported.getLength() + 1 );
384 : :
385 [ # # ]: 0 : ::rtl::OUString* pArray = aSupported.getArray();
386 [ # # ]: 0 : pArray[ aSupported.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON;
387 : :
388 : 0 : return aSupported;
389 : : }
390 : :
391 : : //--------------------------------------------------------------------
392 : 0 : void OClickableImageBaseControl::implSubmit( const MouseEvent& _rEvent, const Reference< XInteractionHandler >& _rxHandler ) SAL_THROW((VetoException, WrappedTargetException, RuntimeException))
393 : : {
394 : : try
395 : : {
396 : : // allow the veto listeners to join the game
397 [ # # ][ # # ]: 0 : m_aSubmissionVetoListeners.notifyEach( &XSubmissionVetoListener::submitting, EventObject( *this ) );
[ # # ][ # # ]
398 : :
399 : : // see whether there's an "submit interceptor" set at our model
400 [ # # ][ # # ]: 0 : Reference< submission::XSubmissionSupplier > xSubmissionSupp( getModel(), UNO_QUERY );
401 : 0 : Reference< XSubmission > xSubmission;
402 [ # # ]: 0 : if ( xSubmissionSupp.is() )
403 [ # # ][ # # ]: 0 : xSubmission = xSubmissionSupp->getSubmission();
[ # # ]
404 : :
405 [ # # ]: 0 : if ( xSubmission.is() )
406 : : {
407 [ # # ]: 0 : if ( !_rxHandler.is() )
408 [ # # ][ # # ]: 0 : xSubmission->submit();
409 : : else
410 [ # # ][ # # ]: 0 : xSubmission->submitWithInteraction( _rxHandler );
411 : : }
412 : : else
413 : : {
414 : : // no "interceptor" -> ordinary (old-way) submission
415 [ # # ][ # # ]: 0 : Reference< XChild > xChild( getModel(), UNO_QUERY );
416 : 0 : Reference< XSubmit > xParentSubmission;
417 [ # # ]: 0 : if ( xChild.is() )
418 [ # # ][ # # ]: 0 : xParentSubmission = xParentSubmission.query( xChild->getParent() );
[ # # ][ # # ]
419 [ # # ]: 0 : if ( xParentSubmission.is() )
420 [ # # ][ # # ]: 0 : xParentSubmission->submit( this, _rEvent );
[ # # ]
421 : 0 : }
422 : : }
423 : 0 : catch( const VetoException& )
424 : : {
425 : : // allowed to leave
426 : 0 : throw;
427 : : }
428 : 0 : catch( const RuntimeException& )
429 : : {
430 : : // allowed to leave
431 : 0 : throw;
432 : : }
433 : 0 : catch( const WrappedTargetException& )
434 : : {
435 : : // allowed to leave
436 : 0 : throw;
437 : : }
438 [ # # # # : 0 : catch( const Exception& e )
# ]
439 : : {
440 : : OSL_FAIL( "OClickableImageBaseControl::implSubmit: caught an unknown exception!" );
441 [ # # # # : 0 : throw WrappedTargetException( ::rtl::OUString(), *this, makeAny( e ) );
# # ]
442 : : }
443 : 0 : }
444 : :
445 : : //==================================================================
446 : : // OClickableImageBaseModel
447 : : //==================================================================
448 : : //------------------------------------------------------------------------------
449 : 36 : Sequence<Type> OClickableImageBaseModel::_getTypes()
450 : : {
451 : : return concatSequences(
452 : : OControlModel::_getTypes(),
453 : : OClickableImageBaseModel_Base::getTypes()
454 [ + - ][ + - ]: 36 : );
[ + - ]
455 : : }
456 : :
457 : : //------------------------------------------------------------------
458 : : DBG_NAME( OClickableImageBaseModel )
459 : : //------------------------------------------------------------------
460 : 76 : OClickableImageBaseModel::OClickableImageBaseModel( const Reference< XMultiServiceFactory >& _rxFactory, const ::rtl::OUString& _rUnoControlModelTypeName,
461 : : const ::rtl::OUString& rDefault )
462 : : :OControlModel( _rxFactory, _rUnoControlModelTypeName, rDefault )
463 : : ,OPropertyChangeListener(m_aMutex)
464 : : ,m_pMedium(NULL)
465 : : ,m_pProducer( NULL )
466 : : ,m_bDispatchUrlInternal(sal_False)
467 : : ,m_bDownloading(sal_False)
468 [ + - ]: 76 : ,m_bProdStarted(sal_False)
469 : : {
470 : : DBG_CTOR( OClickableImageBaseModel, NULL );
471 [ + - ]: 76 : implConstruct();
472 : 76 : m_eButtonType = FormButtonType_PUSH;
473 : 76 : }
474 : :
475 : : //------------------------------------------------------------------
476 : 2 : OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory )
477 : : :OControlModel( _pOriginal, _rxFactory )
478 : : ,OPropertyChangeListener( m_aMutex )
479 : : ,m_pMedium( NULL )
480 : : ,m_pProducer( NULL )
481 : : ,m_bDispatchUrlInternal(sal_False)
482 : : ,m_bDownloading( sal_False )
483 [ + - ][ + - ]: 2 : ,m_bProdStarted( sal_False )
484 : : {
485 : : DBG_CTOR( OClickableImageBaseModel, NULL );
486 [ + - ]: 2 : implConstruct();
487 : :
488 : : // copy properties
489 : 2 : m_eButtonType = _pOriginal->m_eButtonType;
490 : 2 : m_sTargetURL = _pOriginal->m_sTargetURL;
491 : 2 : m_sTargetFrame = _pOriginal->m_sTargetFrame;
492 : 2 : m_bDispatchUrlInternal = _pOriginal->m_bDispatchUrlInternal;
493 : 2 : }
494 : :
495 : : //------------------------------------------------------------------------------
496 : 2 : void OClickableImageBaseModel::implInitializeImageURL( )
497 : : {
498 : 2 : osl_incrementInterlockedCount( &m_refCount );
499 : : {
500 : : // simulate a propertyChanged event for the ImageURL
501 : 2 : Any aImageURL;
502 [ + - ]: 2 : getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL );
503 [ + - ][ + - ]: 2 : _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL, sal_False, PROPERTY_ID_IMAGE_URL, Any( ), aImageURL ) );
[ + - ][ + - ]
[ + - ]
504 : : }
505 : 2 : osl_decrementInterlockedCount( &m_refCount );
506 : 2 : }
507 : :
508 : : //------------------------------------------------------------------------------
509 : 78 : void OClickableImageBaseModel::implConstruct()
510 : : {
511 [ + - ]: 78 : m_pProducer = new ImageProducer;
512 : 78 : increment( m_refCount );
513 : : {
514 : 78 : m_xProducer = m_pProducer;
515 : :
516 [ + - ]: 78 : if ( m_xAggregateSet.is() )
517 : : {
518 [ + - ]: 78 : OPropertyChangeMultiplexer* pMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet );
519 [ + - ]: 78 : pMultiplexer->addProperty( PROPERTY_IMAGE_URL );
520 : : }
521 : : }
522 : 78 : decrement(m_refCount);
523 : 78 : }
524 : :
525 : : //------------------------------------------------------------------------------
526 [ + - ][ + - ]: 68 : OClickableImageBaseModel::~OClickableImageBaseModel()
527 : : {
528 [ - + ]: 68 : if (!OComponentHelper::rBHelper.bDisposed)
529 : : {
530 : 0 : acquire();
531 [ # # ]: 0 : dispose();
532 : : }
533 : : DBG_ASSERT(m_pMedium == NULL, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ...");
534 : : // spaetestens im dispose sollte das aufgeraeumt worden sein
535 : :
536 : : DBG_DTOR( OClickableImageBaseModel, NULL );
537 [ - + ]: 68 : }
538 : :
539 : : // XImageProducer
540 : : //--------------------------------------------------------------------
541 : 0 : void SAL_CALL OClickableImageBaseModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException)
542 : : {
543 [ # # ]: 0 : ImageModelMethodGuard aGuard( *this );
544 [ # # ][ # # ]: 0 : GetImageProducer()->addConsumer( _rxConsumer );
545 : 0 : }
546 : :
547 : : //--------------------------------------------------------------------
548 : 0 : void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException)
549 : : {
550 [ # # ]: 0 : ImageModelMethodGuard aGuard( *this );
551 [ # # ][ # # ]: 0 : GetImageProducer()->removeConsumer( _rxConsumer );
552 : 0 : }
553 : :
554 : : //--------------------------------------------------------------------
555 : 0 : void SAL_CALL OClickableImageBaseModel::startProduction( ) throw (RuntimeException)
556 : : {
557 [ # # ]: 0 : ImageModelMethodGuard aGuard( *this );
558 [ # # ][ # # ]: 0 : GetImageProducer()->startProduction();
559 : 0 : }
560 : :
561 : : //--------------------------------------------------------------------
562 : 2 : Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission() throw (RuntimeException)
563 : : {
564 : 2 : return m_xSubmissionDelegate;
565 : : }
566 : :
567 : : //--------------------------------------------------------------------
568 : 2 : void SAL_CALL OClickableImageBaseModel::setSubmission( const Reference< submission::XSubmission >& _submission ) throw (RuntimeException)
569 : : {
570 : 2 : m_xSubmissionDelegate = _submission;
571 : 2 : }
572 : :
573 : : //--------------------------------------------------------------------
574 : 10 : Sequence< ::rtl::OUString > SAL_CALL OClickableImageBaseModel::getSupportedServiceNames( ) throw (RuntimeException)
575 : : {
576 : 10 : Sequence< ::rtl::OUString > aSupported = OControlModel::getSupportedServiceNames();
577 [ + - ]: 10 : aSupported.realloc( aSupported.getLength() + 1 );
578 : :
579 [ + - ]: 10 : ::rtl::OUString* pArray = aSupported.getArray();
580 [ + - ]: 10 : pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON;
581 : :
582 : 10 : return aSupported;
583 : : }
584 : :
585 : : // OComponentHelper
586 : : //------------------------------------------------------------------------------
587 : 68 : void OClickableImageBaseModel::disposing()
588 : : {
589 : 68 : OControlModel::disposing();
590 [ - + ]: 68 : if (m_pMedium)
591 : : {
592 [ # # ]: 0 : delete m_pMedium;
593 : 0 : m_pMedium = NULL;
594 : : }
595 : :
596 : 68 : m_xProducer = NULL;
597 : 68 : m_pProducer = NULL;
598 : 68 : }
599 : :
600 : : //------------------------------------------------------------------------------
601 : 13993 : Any SAL_CALL OClickableImageBaseModel::queryAggregation(const Type& _rType) throw (RuntimeException)
602 : : {
603 : : // order matters:
604 : : // we definately want to "overload" the XImageProducer interface of our aggregate,
605 : : // thus check OClickableImageBaseModel_Base (which provides this) first
606 : 13993 : Any aReturn = OClickableImageBaseModel_Base::queryInterface( _rType );
607 : :
608 : : // BUT: _don't_ let it feel responsible for the XTypeProvider interface
609 : : // (as this is implemented by our base class in the proper way)
610 [ + + + + ]: 27966 : if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) )
[ + + ][ + - ]
611 : 13973 : || !aReturn.hasValue()
612 : : )
613 [ + - ]: 10468 : aReturn = OControlModel::queryAggregation( _rType );
614 : :
615 : 13993 : return aReturn;
616 : : }
617 : :
618 : : //------------------------------------------------------------------------------
619 : 6041 : void OClickableImageBaseModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
620 : : {
621 [ + + + + : 6041 : switch (nHandle)
+ ]
622 : : {
623 : 235 : case PROPERTY_ID_BUTTONTYPE : rValue <<= m_eButtonType; break;
624 : 219 : case PROPERTY_ID_TARGET_URL : rValue <<= m_sTargetURL; break;
625 : 152 : case PROPERTY_ID_TARGET_FRAME : rValue <<= m_sTargetFrame; break;
626 : 148 : case PROPERTY_ID_DISPATCHURLINTERNAL : rValue <<= m_bDispatchUrlInternal; break;
627 : : default:
628 : 5287 : OControlModel::getFastPropertyValue(rValue, nHandle);
629 : : }
630 : 6041 : }
631 : :
632 : : //------------------------------------------------------------------------------
633 : 242 : void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( Exception)
634 : : {
635 [ + + + + : 242 : switch (nHandle)
+ ]
636 : : {
637 : : case PROPERTY_ID_BUTTONTYPE :
638 : : DBG_ASSERT(isA(rValue, static_cast<FormButtonType*>(NULL)), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
639 : 18 : rValue >>= m_eButtonType;
640 : 18 : break;
641 : :
642 : : case PROPERTY_ID_TARGET_URL :
643 : : DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
644 : 10 : rValue >>= m_sTargetURL;
645 : 10 : break;
646 : :
647 : : case PROPERTY_ID_TARGET_FRAME :
648 : : DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
649 : 18 : rValue >>= m_sTargetFrame;
650 : 18 : break;
651 : :
652 : : case PROPERTY_ID_DISPATCHURLINTERNAL:
653 : : DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
654 : 16 : rValue >>= m_bDispatchUrlInternal;
655 : 16 : break;
656 : :
657 : : default:
658 : 180 : OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue);
659 : : }
660 : 242 : }
661 : :
662 : : //------------------------------------------------------------------------------
663 : 595 : sal_Bool OClickableImageBaseModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
664 : : throw( IllegalArgumentException )
665 : : {
666 [ + + + + : 595 : switch (nHandle)
+ ]
667 : : {
668 : : case PROPERTY_ID_BUTTONTYPE :
669 : 56 : return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType );
670 : :
671 : : case PROPERTY_ID_TARGET_URL :
672 : 67 : return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL);
673 : :
674 : : case PROPERTY_ID_TARGET_FRAME :
675 : 75 : return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame);
676 : :
677 : : case PROPERTY_ID_DISPATCHURLINTERNAL :
678 : 54 : return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal);
679 : :
680 : : default:
681 : 595 : return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
682 : : }
683 : : }
684 : :
685 : : //------------------------------------------------------------------------------
686 : 0 : void OClickableImageBaseModel::StartProduction()
687 : : {
688 : 0 : ImageProducer *pImgProd = GetImageProducer();
689 : : // grab the ImageURL
690 : 0 : rtl::OUString sURL;
691 [ # # ][ # # ]: 0 : getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ImageURL") ) ) >>= sURL;
692 [ # # ]: 0 : if (!m_pMedium)
693 : : {
694 [ # # ][ # # ]: 0 : if ( ::svt::GraphicAccess::isSupportedURL( sURL ) )
695 [ # # ]: 0 : pImgProd->SetImage( sURL );
696 : : else
697 : : // caution: the medium may be NULL if somebody gave us a invalid URL to work with
698 [ # # ][ # # ]: 0 : pImgProd->SetImage(String());
[ # # ][ # # ]
699 : 0 : m_bDownloading = sal_False;
700 : 0 : return;
701 : : }
702 [ # # ][ # # ]: 0 : if (m_pMedium->GetErrorCode()==0)
703 : : {
704 [ # # ]: 0 : SvStream* pStream = m_pMedium->GetInStream();
705 : :
706 [ # # ]: 0 : pImgProd->SetImage(*pStream);
707 [ # # ]: 0 : pImgProd->startProduction();
708 : 0 : m_bProdStarted = sal_True;
709 : : }
710 : : else
711 : : {
712 [ # # ][ # # ]: 0 : pImgProd->SetImage(String());
[ # # ][ # # ]
713 [ # # ][ # # ]: 0 : delete m_pMedium;
714 : 0 : m_pMedium = 0;
715 : 0 : m_bDownloading = sal_False;
716 [ # # ]: 0 : }
717 : : }
718 : :
719 : : //------------------------------------------------------------------------------
720 : 11 : void OClickableImageBaseModel::SetURL( const ::rtl::OUString& rURL )
721 : : {
722 [ + - ][ + + ]: 11 : if (m_pMedium || rURL.isEmpty())
[ + + ]
723 : : {
724 : : // Den Stream am Producer freigeben, bevor das Medium geloscht wird.
725 [ + - ][ + - ]: 2 : GetImageProducer()->SetImage(String());
[ + - ][ + - ]
726 [ - + ][ # # ]: 2 : delete m_pMedium;
727 : 2 : m_pMedium = NULL;
728 : : }
729 : :
730 : : // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first
731 [ + - ]: 11 : INetURLObject aUrl(rURL);
732 [ + - ]: 11 : if (INET_PROT_NOT_VALID == aUrl.GetProtocol())
733 : : // we treat an invalid URL like we would treat no URL
734 : 11 : return;
735 : :
736 [ # # ][ # # ]: 0 : if (!rURL.isEmpty() && !::svt::GraphicAccess::isSupportedURL( rURL ) )
[ # # ][ # # ]
737 : : {
738 [ # # ]: 0 : if (m_pMedium)
739 [ # # ][ # # ]: 0 : delete m_pMedium;
740 : :
741 [ # # ][ # # ]: 0 : m_pMedium = new SfxMedium(rURL, STREAM_STD_READ);
[ # # ][ # # ]
742 : :
743 : : // Das XModel suchen, um an die Object-Shell oder zumindest den
744 : : // Referer zu gelangen.
745 : : // Das Model findet man allerdings nur beim Laden von HTML-Dokumenten
746 : : // und dann, wenn die URL in einem bereits geladenen Dokument
747 : : // geaendert wird. Waehrend des Ladens kommt man nicht an das
748 : : // Model ran.
749 : 0 : Reference< XModel > xModel;
750 [ # # ]: 0 : InterfaceRef xIfc( *this );
751 [ # # ][ # # ]: 0 : while( !xModel.is() && xIfc.is() )
[ # # ]
752 : : {
753 [ # # ]: 0 : Reference<XChild> xChild( xIfc, UNO_QUERY );
754 [ # # ][ # # ]: 0 : xIfc = xChild->getParent();
[ # # ]
755 [ # # ]: 0 : query_interface(xIfc, xModel);
756 : 0 : }
757 : :
758 : : // Die Object-Shell suchen, indem wir
759 : : // ueber alle Object-Shells iterieren und deren XModel mit dem
760 : : // eigenen vergleichen. Als Optimierung probieren wir aber erstmal
761 : : // die aktuelle Object-Shell.
762 : : // wir unser XModel mit dem aller Object
763 : 0 : SfxObjectShell *pObjSh = 0;
764 : :
765 [ # # ]: 0 : if( xModel.is() )
766 : : {
767 [ # # ]: 0 : SfxObjectShell *pTestObjSh = SfxObjectShell::Current();
768 [ # # ]: 0 : if( pTestObjSh )
769 : : {
770 [ # # ]: 0 : Reference< XModel > xTestModel = pTestObjSh->GetModel();
771 [ # # ][ # # ]: 0 : if( xTestModel == xModel )
772 : 0 : pObjSh = pTestObjSh;
773 : : }
774 [ # # ]: 0 : if( !pObjSh )
775 : : {
776 [ # # ]: 0 : pTestObjSh = SfxObjectShell::GetFirst();
777 [ # # ][ # # ]: 0 : while( !pObjSh && pTestObjSh )
[ # # ]
778 : : {
779 [ # # ]: 0 : Reference< XModel > xTestModel = pTestObjSh->GetModel();
780 [ # # ][ # # ]: 0 : if( xTestModel == xModel )
781 : 0 : pObjSh = pTestObjSh;
782 : : else
783 [ # # ]: 0 : pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh );
784 : 0 : }
785 : : }
786 : : }
787 : :
788 : : #ifdef USE_REGISTER_TRANSFER
789 : : if( pObjSh )
790 : : {
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());
796 : : }
797 : : #else
798 [ # # ]: 0 : if( pObjSh )
799 : : {
800 : : // Target-Frame uebertragen, damit auch javascript:-URLs
801 : : // "geladen" werden koennen.
802 : 0 : const SfxMedium *pShMedium = pObjSh->GetMedium();
803 [ # # ]: 0 : if( pShMedium )
804 [ # # ][ # # ]: 0 : m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame());
805 : : }
806 : : #endif
807 : :
808 : : // Downloading-Flag auf sal_True setzen. Es werden dann auch
809 : : // Data-Available-Links, wenn wir in den Pending-Staus gelangen.
810 : 0 : m_bDownloading = sal_True;
811 : 0 : m_bProdStarted = sal_False;
812 : :
813 : : // Download anstossen (Achtung: Kann auch synchron sein).
814 [ # # ][ # # ]: 0 : m_pMedium->DownLoad(STATIC_LINK(this, OClickableImageBaseModel, DownloadDoneLink));
815 : : }
816 : : else
817 : : {
818 [ # # ][ # # ]: 0 : if ( ::svt::GraphicAccess::isSupportedURL( rURL ) )
819 [ # # ]: 0 : GetImageProducer()->SetImage( rURL );
820 [ # # ]: 0 : GetImageProducer()->startProduction();
821 [ + - ][ - + ]: 11 : }
822 : : }
823 : :
824 : : //------------------------------------------------------------------------------
825 : 0 : void OClickableImageBaseModel::DataAvailable()
826 : : {
827 [ # # ]: 0 : if (!m_bProdStarted)
828 : 0 : StartProduction();
829 : :
830 : 0 : GetImageProducer()->NewDataAvailable();
831 : 0 : }
832 : :
833 : : //------------------------------------------------------------------------------
834 : 0 : void OClickableImageBaseModel::DownloadDone()
835 : : {
836 : 0 : DataAvailable();
837 : 0 : m_bDownloading = sal_False;
838 : 0 : }
839 : :
840 : : //------------------------------------------------------------------------------
841 : 0 : IMPL_STATIC_LINK( OClickableImageBaseModel, DownloadDoneLink, void*, EMPTYARG )
842 : : {
843 [ # # ]: 0 : ::osl::MutexGuard aGuard( pThis->m_aMutex );
844 [ # # ]: 0 : pThis->DownloadDone();
845 [ # # ]: 0 : return 0;
846 : : }
847 : :
848 : : //------------------------------------------------------------------------------
849 : 11 : void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt )
850 : : throw( RuntimeException )
851 : : {
852 : : // Wenn eine URL gesetzt worden ist, muss die noch an den ImageProducer
853 : : // weitergereicht werden.
854 [ + - ]: 11 : ::osl::MutexGuard aGuard(m_aMutex);
855 [ + - ][ + - ]: 11 : SetURL( getString(rEvt.NewValue) );
[ + - ]
856 : 11 : }
857 : :
858 : : // -----------------------------------------------------------------------------
859 : 0 : Any OClickableImageBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
860 : : {
861 [ # # # # ]: 0 : switch (nHandle)
862 : : {
863 [ # # ]: 0 : case PROPERTY_ID_BUTTONTYPE : return makeAny( FormButtonType_PUSH );
864 : : case PROPERTY_ID_TARGET_URL :
865 [ # # ]: 0 : case PROPERTY_ID_TARGET_FRAME : return makeAny( ::rtl::OUString() );
866 [ # # ]: 0 : case PROPERTY_ID_DISPATCHURLINTERNAL : return makeAny( sal_False );
867 : : default:
868 : 0 : return OControlModel::getPropertyDefaultByHandle(nHandle);
869 : : }
870 : : }
871 : :
872 : : //==================================================================
873 : : // OImageProducerThread_Impl
874 : : //==================================================================
875 : : //------------------------------------------------------------------
876 : 0 : EventObject* OImageProducerThread_Impl::cloneEvent( const EventObject* _pEvt ) const
877 : : {
878 [ # # ]: 0 : return new EventObject( *_pEvt );
879 : : }
880 : :
881 : : //------------------------------------------------------------------
882 : 0 : void OImageProducerThread_Impl::processEvent( ::cppu::OComponentHelper *pCompImpl,
883 : : const EventObject* pEvt,
884 : : const Reference<XControl>&,
885 : : sal_Bool )
886 : : {
887 [ # # ][ # # ]: 0 : ((OClickableImageBaseControl *)pCompImpl)->actionPerformed_Impl( sal_True, *(MouseEvent *)pEvt );
[ # # ]
888 : 0 : }
889 : :
890 : : //.........................................................................
891 : : } // namespace frm
892 : : //.........................................................................
893 : :
894 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|