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