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