LibreOffice Module forms (master) 1
clickableimage.cxx
Go to the documentation of this file.
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"
22#include <urltransformer.hxx>
23#include <componenttools.hxx>
24#include <com/sun/star/form/XSubmit.hpp>
25#include <com/sun/star/frame/XDispatch.hpp>
26#include <com/sun/star/frame/XDispatchProvider.hpp>
27#include <com/sun/star/frame/FrameSearchFlag.hpp>
28#include <com/sun/star/frame/XController.hpp>
29#include <com/sun/star/frame/XFrame.hpp>
30#include <com/sun/star/awt/ActionEvent.hpp>
31#include <com/sun/star/graphic/XGraphic.hpp>
32#include <com/sun/star/graphic/GraphicObject.hpp>
33#include <com/sun/star/util/VetoException.hpp>
34#include <tools/urlobj.hxx>
35#include <tools/debug.hxx>
37#include <vcl/graph.hxx>
38#include <vcl/svapp.hxx>
39#include <sfx2/docfile.hxx>
40#include <sfx2/objsh.hxx>
41#include <osl/mutex.hxx>
42#include <property.hxx>
43#include <services.hxx>
47#include <comphelper/types.hxx>
50#define LOCAL_URL_PREFIX '#'
51
52
53namespace frm
54{
55
56
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::sdb;
59 using namespace ::com::sun::star::sdbc;
60 using namespace ::com::sun::star::beans;
61 using namespace ::com::sun::star::container;
62 using namespace ::com::sun::star::form;
63 using namespace ::com::sun::star::awt;
64 using namespace ::com::sun::star::io;
65 using namespace ::com::sun::star::lang;
66 using namespace ::com::sun::star::util;
67 using namespace ::com::sun::star::frame;
68 using namespace ::com::sun::star::form::submission;
69 using namespace ::com::sun::star::graphic;
70 using ::com::sun::star::awt::MouseEvent;
71 using ::com::sun::star::task::XInteractionHandler;
72
73
74 // OClickableImageBaseControl
75
76
78 {
79 static Sequence<Type> const aTypes =
81 return aTypes;
82 }
83
84
85 OClickableImageBaseControl::OClickableImageBaseControl(const Reference<XComponentContext>& _rxFactory, const OUString& _aService)
86 :OControl(_rxFactory, _aService)
87 ,m_aSubmissionVetoListeners( m_aMutex )
88 ,m_aFeatureInterception( _rxFactory )
89 ,m_aApproveActionListeners( m_aMutex )
90 ,m_aActionListeners( m_aMutex )
91 {
92 }
93
94
96 {
97 if (!OComponentHelper::rBHelper.bDisposed)
98 {
99 acquire();
100 dispose();
101 }
102 }
103
104 // UNO Binding
105
107 {
108 Any aReturn = OControl::queryAggregation(_rType);
109 if (!aReturn.hasValue())
111 return aReturn;
112 }
113
114 // XApproveActionBroadcaster
115
117 const Reference<XApproveActionListener>& l)
118 {
120 }
121
122
124 const Reference<XApproveActionListener>& l)
125 {
127 }
128
129
130 void SAL_CALL OClickableImageBaseControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor )
131 {
133 }
134
135
136 void SAL_CALL OClickableImageBaseControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor )
137 {
139 }
140
141 // OComponentHelper
142
144 {
145 EventObject aEvent( static_cast< XWeak* >( this ) );
150
151 {
152 ::osl::MutexGuard aGuard( m_aMutex );
153 m_pThread.clear();
154 }
155
157 }
158
159
161 {
162 if ( !m_pThread.is() )
163 {
165 m_pThread->create();
166 }
167 return m_pThread.get();
168 }
169
170
172 {
173 bool bCancelled = false;
174 EventObject aEvent( static_cast< XWeak* >( this ) );
175
177 while( !bCancelled && aIter.hasMoreElements() )
178 {
179 // Every approveAction method must be thread-safe!
180 if( !aIter.next()->approveAction( aEvent ) )
181 bCancelled = true;
182 }
183
184 return !bCancelled;
185 }
186
187
188 // This method is also called from a thread and thus must be thread-safe.
189 void OClickableImageBaseControl::actionPerformed_Impl(bool bNotifyListener, const MouseEvent& rEvt)
190 {
191 if( bNotifyListener )
192 {
193 if ( !approveAction() )
194 return;
195 }
196
197 // Whether the rest of the code is thread-safe, one can't tell. Therefore
198 // we do most of the work on a locked solar mutex.
199 Reference<XPropertySet> xSet;
200 Reference< XInterface > xModelsParent;
201 FormButtonType eButtonType = FormButtonType_PUSH;
202 {
203 SolarMutexGuard aGuard;
204
205 // Get parent
206 Reference<XFormComponent> xComp(getModel(), UNO_QUERY);
207 if (!xComp.is())
208 return;
209
210 xModelsParent = xComp->getParent();
211 if (!xModelsParent.is())
212 return;
213
214 // Which button type?
215 xSet.set(xComp, css::uno::UNO_QUERY);
216 if ( !xSet.is() )
217 return;
218 xSet->getPropertyValue(PROPERTY_BUTTONTYPE) >>= eButtonType;
219 }
220
221 switch (eButtonType)
222 {
223 case FormButtonType_RESET:
225 // Reset methods must be thread-safe!
226 Reference<XReset> xReset(xModelsParent, UNO_QUERY);
227 if (!xReset.is())
228 return;
229
230 xReset->reset();
231 }
232 break;
233
234 case FormButtonType_SUBMIT:
235 {
236 // if some outer component can provide an interaction handler, use it
237 Reference< XInteractionHandler > xHandler( m_aFeatureInterception.queryDispatch( "private:/InteractionHandler" ), UNO_QUERY );
238 try
239 {
240 implSubmit( rEvt, xHandler );
241 }
242 catch( const Exception& )
243 {
244 // ignore
245 }
246 }
247 break;
248
249 case FormButtonType_URL:
250 {
251 SolarMutexGuard aGuard;
252
253 Reference< XModel > xModel = getXModel(xModelsParent);
254 if (!xModel.is())
255 return;
256
257
258 // Execute URL now
259 Reference< XController > xController = xModel->getCurrentController();
260 if (!xController.is())
261 return;
262
263 Reference< XFrame > xFrame = xController->getFrame();
264 if( !xFrame.is() )
265 return;
266
267 URL aURL;
268 aURL.Complete =
269 getString(xSet->getPropertyValue(PROPERTY_TARGET_URL));
270
271 if (!aURL.Complete.isEmpty() && (LOCAL_URL_PREFIX == aURL.Complete[0]))
272 { // FIXME: The URL contains a local URL only. Since the URLTransformer does not handle this case correctly
273 // (it can't: it does not know the document URL), we have to take care for this ourself.
274 // The real solution would be to not allow such relative URLs (there is a rule that at runtime, all
275 // URLs have to be absolute), but for compatibility reasons this is no option.
276 // The more as the user does not want to see a local URL as "file://<path>/<document>#mark" if it
277 // could be "#mark" as well.
278 // If we someday say that this hack (yes, it's kind of a hack) is not sustainable anymore, the complete
279 // solution would be:
280 // * recognize URLs consisting of a mark only while _reading_ the document
281 // * for this, allow the INetURLObject (which at the moment is invoked when reading URLs) to
282 // transform such mark-only URLs into correct absolute URLs
283 // * at the UI, show only the mark
284 // * !!! recognize every SAVEAS on the document, so the absolute URL can be adjusted. This seems
285 // rather impossible !!!
286 aURL.Mark = aURL.Complete;
287 aURL.Complete = xModel->getURL();
288 aURL.Complete += aURL.Mark;
289 }
290
291 bool bDispatchUrlInternal = false;
292 xSet->getPropertyValue(PROPERTY_DISPATCHURLINTERNAL) >>= bDispatchUrlInternal;
293 if ( bDispatchUrlInternal )
294 {
296
297 OUString aTargetFrame;
298 xSet->getPropertyValue(PROPERTY_TARGET_FRAME) >>= aTargetFrame;
299
300 Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY_THROW)->queryDispatch( aURL, aTargetFrame,
301 FrameSearchFlag::SELF | FrameSearchFlag::PARENT |
302 FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE );
303
304 Sequence<PropertyValue> aArgs { comphelper::makePropertyValue("Referer", xModel->getURL()) };
305
306 if (xDisp.is())
307 xDisp->dispatch( aURL, aArgs );
308 }
309 else
310 {
311 URL aHyperLink = m_aFeatureInterception.getTransformer().getStrictURL( ".uno:OpenHyperlink" );
312
313 Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY_THROW)->queryDispatch(aHyperLink, OUString() , 0);
314
315 if ( xDisp.is() )
316 {
317 Sequence<PropertyValue> aProps{
318 comphelper::makePropertyValue("URL", aURL.Complete),
320 "FrameName", xSet->getPropertyValue(PROPERTY_TARGET_FRAME)),
321 comphelper::makePropertyValue("Referer", xModel->getURL())
322 };
323
324 xDisp->dispatch( aHyperLink, aProps );
325 }
326 }
327 } break;
328 default:
329 {
330 // notify the action listeners for a push button
331 ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand);
332 m_aActionListeners.notifyEach( &XActionListener::actionPerformed, aEvt );
333 }
334 }
335 }
336
337
338 void SAL_CALL OClickableImageBaseControl::addSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener )
339 {
341 }
342
343
344 void SAL_CALL OClickableImageBaseControl::removeSubmissionVetoListener( const Reference< submission::XSubmissionVetoListener >& listener )
345 {
347 }
348
349
350 void SAL_CALL OClickableImageBaseControl::submitWithInteraction( const Reference< XInteractionHandler >& _rxHandler )
351 {
352 implSubmit( MouseEvent(), _rxHandler );
353 }
354
355
357 {
358 implSubmit( MouseEvent(), nullptr );
359 }
360
361
363 {
364 Sequence< OUString > aSupported = OControl::getSupportedServiceNames();
365 aSupported.realloc( aSupported.getLength() + 1 );
366
367 OUString* pArray = aSupported.getArray();
368 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_CONTROL_SUBMITBUTTON;
369
370 return aSupported;
371 }
372
373
374 void OClickableImageBaseControl::implSubmit( const MouseEvent& _rEvent, const Reference< XInteractionHandler >& _rxHandler )
375 {
376 try
377 {
378 // allow the veto listeners to join the game
379 m_aSubmissionVetoListeners.notifyEach( &XSubmissionVetoListener::submitting, EventObject( *this ) );
380
381 // see whether there's an "submit interceptor" set at our model
382 Reference< submission::XSubmissionSupplier > xSubmissionSupp( getModel(), UNO_QUERY );
383 Reference< XSubmission > xSubmission;
384 if ( xSubmissionSupp.is() )
385 xSubmission = xSubmissionSupp->getSubmission();
386
387 if ( xSubmission.is() )
388 {
389 if ( !_rxHandler.is() )
390 xSubmission->submit();
391 else
392 xSubmission->submitWithInteraction( _rxHandler );
393 }
394 else
395 {
396 // no "interceptor" -> ordinary (old-way) submission
397 Reference< XChild > xChild( getModel(), UNO_QUERY );
398 Reference< XSubmit > xParentSubmission;
399 if ( xChild.is() )
400 xParentSubmission.set(xChild->getParent(), css::uno::UNO_QUERY);
401 if ( xParentSubmission.is() )
402 xParentSubmission->submit( this, _rEvent );
403 }
404 }
405 catch( const VetoException& )
406 {
407 // allowed to leave
408 throw;
409 }
410 catch( const RuntimeException& )
411 {
412 // allowed to leave
413 throw;
414 }
415 catch( const WrappedTargetException& )
416 {
417 // allowed to leave
418 throw;
419 }
420 catch( const Exception& )
421 {
422 css::uno::Any anyEx = cppu::getCaughtException();
423 TOOLS_WARN_EXCEPTION( "forms.component", "OClickableImageBaseControl::implSubmit: caught an unknown exception!" );
424 throw WrappedTargetException( OUString(), *this, anyEx );
425 }
426 }
427
428
429 // OClickableImageBaseModel
430
431
433 {
434 return concatSequences(
437 );
438 }
439
440
441 OClickableImageBaseModel::OClickableImageBaseModel( const Reference< XComponentContext >& _rxFactory, const OUString& _rUnoControlModelTypeName,
442 const OUString& rDefault )
443 :OControlModel( _rxFactory, _rUnoControlModelTypeName, rDefault )
445 ,m_bDispatchUrlInternal(false)
446 ,m_bProdStarted(false)
447 {
449 m_eButtonType = FormButtonType_PUSH;
450 }
451
452
453 OClickableImageBaseModel::OClickableImageBaseModel( const OClickableImageBaseModel* _pOriginal, const Reference<XComponentContext>& _rxFactory )
454 :OControlModel( _pOriginal, _rxFactory )
456 ,m_xGraphicObject( _pOriginal->m_xGraphicObject )
457 ,m_bDispatchUrlInternal(false)
458 ,m_bProdStarted( false )
459 {
461
462 // copy properties
463 m_eButtonType = _pOriginal->m_eButtonType;
464 m_sTargetURL = _pOriginal->m_sTargetURL;
465 m_sTargetFrame = _pOriginal->m_sTargetFrame;
466 m_bDispatchUrlInternal = _pOriginal->m_bDispatchUrlInternal;
467 }
468
469
471 {
472 osl_atomic_increment( &m_refCount );
473 {
474 // simulate a propertyChanged event for the ImageURL
475 Any aImageURL;
477 _propertyChanged( PropertyChangeEvent( *this, PROPERTY_IMAGE_URL, false, PROPERTY_ID_IMAGE_URL, Any( ), aImageURL ) );
478 }
479 osl_atomic_decrement( &m_refCount );
480 }
481
482
484 {
486 m_xProducer->SetDoneHdl( LINK( this, OClickableImageBaseModel, OnImageImportDone ) );
487 osl_atomic_increment( &m_refCount );
488 {
489 if ( m_xAggregateSet.is() )
490 {
491 rtl::Reference<OPropertyChangeMultiplexer> pMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet );
492 pMultiplexer->addProperty( PROPERTY_IMAGE_URL );
493 }
494 }
495 osl_atomic_decrement(&m_refCount);
496 }
497
498
500 {
501 if (!OComponentHelper::rBHelper.bDisposed)
502 {
503 acquire();
504 dispose();
505 }
506 DBG_ASSERT(m_pMedium == nullptr, "OClickableImageBaseModel::~OClickableImageBaseModel : leaving a memory leak ...");
507 // This should be cleaned up at least in the dispose
508
509 }
510
511 // XImageProducer
512
513 void SAL_CALL OClickableImageBaseModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer )
514 {
515 ImageModelMethodGuard aGuard( *this );
516 GetImageProducer()->addConsumer( _rxConsumer );
517 }
518
519
520 void SAL_CALL OClickableImageBaseModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer )
521 {
522 ImageModelMethodGuard aGuard( *this );
523 GetImageProducer()->removeConsumer( _rxConsumer );
524 }
525
526
528 {
529 ImageModelMethodGuard aGuard( *this );
531 }
532
533
534 Reference< submission::XSubmission > SAL_CALL OClickableImageBaseModel::getSubmission()
535 {
537 }
538
539
540 void SAL_CALL OClickableImageBaseModel::setSubmission( const Reference< submission::XSubmission >& _submission )
541 {
542 m_xSubmissionDelegate = _submission;
543 }
544
545
547 {
548 Sequence< OUString > aSupported = OControlModel::getSupportedServiceNames();
549 aSupported.realloc( aSupported.getLength() + 1 );
550
551 OUString* pArray = aSupported.getArray();
552 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_SUBMITBUTTON;
553
554 return aSupported;
555 }
556
557 // OComponentHelper
558
560 {
562 m_pMedium.reset();
563 m_xProducer.clear();
564 }
565
566
568 {
569 // order matters:
570 // we definitely want to "override" the XImageProducer interface of our aggregate,
571 // thus check OClickableImageBaseModel_Base (which provides this) first
573
574 // BUT: _don't_ let it feel responsible for the XTypeProvider interface
575 // (as this is implemented by our base class in the proper way)
576 if ( _rType.equals( cppu::UnoType<XTypeProvider>::get() )
577 || !aReturn.hasValue()
578 )
579 aReturn = OControlModel::queryAggregation( _rType );
580
581 return aReturn;
582 }
583
584
585 void OClickableImageBaseModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
586 {
587 switch (nHandle)
588 {
589 case PROPERTY_ID_BUTTONTYPE : rValue <<= m_eButtonType; break;
590 case PROPERTY_ID_TARGET_URL : rValue <<= m_sTargetURL; break;
591 case PROPERTY_ID_TARGET_FRAME : rValue <<= m_sTargetFrame; break;
593 default:
595 }
596 }
597
598
599 void OClickableImageBaseModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue)
600 {
601 switch (nHandle)
602 {
604 DBG_ASSERT(rValue.has<FormButtonType>(), "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
605 rValue >>= m_eButtonType;
606 break;
607
609 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
610 rValue >>= m_sTargetURL;
611 break;
612
614 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_STRING, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
615 rValue >>= m_sTargetFrame;
616 break;
617
619 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OClickableImageBaseModel::setFastPropertyValue_NoBroadcast : invalid type !" );
620 rValue >>= m_bDispatchUrlInternal;
621 break;
622
623 default:
625 }
626 }
627
628
629 sal_Bool OClickableImageBaseModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
630 {
631 switch (nHandle)
632 {
634 return tryPropertyValueEnum( rConvertedValue, rOldValue, rValue, m_eButtonType );
635
637 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetURL);
638
640 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sTargetFrame);
641
643 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDispatchUrlInternal);
644
645 default:
646 return OControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
647 }
648 }
649
650
652 {
653 ImageProducer *pImgProd = GetImageProducer();
654 // grab the ImageURL
655 OUString sURL;
656 getPropertyValue("ImageURL") >>= sURL;
657 if (!m_pMedium)
658 {
659 if ( ::svt::GraphicAccess::isSupportedURL( sURL ) )
660 pImgProd->SetImage( sURL );
661 else
662 // caution: the medium may be NULL if somebody gave us an invalid URL to work with
663 pImgProd->SetImage(OUString());
664 return;
665 }
666 if (m_pMedium->GetErrorCode()==ERRCODE_NONE)
667 {
668 SvStream* pStream = m_pMedium->GetInStream();
669
670 pImgProd->SetImage(*pStream);
671 pImgProd->startProduction();
672 m_bProdStarted = true;
673 }
674 else
675 {
676 pImgProd->SetImage(OUString());
677 m_pMedium.reset();
678 }
679 }
680
682 {
683 // Find the XModel to get to the Object shell or at least the
684 // Referer.
685 // There's only a Model if we load HTML documents and the URL is
686 // changed in a document that is already loaded. There's no way
687 // we can get to the Model during loading.
688 Reference< XModel > xModel;
689 css::uno::Reference<css::uno::XInterface> xIfc( *this );
690 while( !xModel.is() && xIfc.is() )
691 {
692 Reference<XChild> xChild( xIfc, UNO_QUERY );
693 xIfc = xChild->getParent();
694 xModel.set(xIfc, css::uno::UNO_QUERY);
695 }
696
697 // Search for the Object shell by iterating over all Object shells
698 // and comparing their XModel to ours.
699 // As an optimization, we try the current Object shell first.
700 SfxObjectShell *pObjSh = nullptr;
701
702 if( xModel.is() )
703 {
705 if( pTestObjSh )
706 {
707 Reference< XModel > xTestModel = pTestObjSh->GetModel();
708 if( xTestModel == xModel )
709 pObjSh = pTestObjSh;
710 }
711 if( !pObjSh )
712 {
713 pTestObjSh = SfxObjectShell::GetFirst();
714 while( !pObjSh && pTestObjSh )
715 {
716 Reference< XModel > xTestModel = pTestObjSh->GetModel();
717 if( xTestModel == xModel )
718 pObjSh = pTestObjSh;
719 else
720 pTestObjSh = SfxObjectShell::GetNext( *pTestObjSh );
721 }
722 }
723 }
724
725 return pObjSh;
726 }
727
728 void OClickableImageBaseModel::SetURL( const OUString& rURL )
729 {
730 if (m_pMedium || rURL.isEmpty())
731 {
732 // Free the stream at the Producer, before the medium is deleted
733 GetImageProducer()->SetImage(OUString());
734 m_pMedium.reset();
735 }
736
737 // the SfxMedium is not allowed to be created with an invalid URL, so we have to check this first
738 INetURLObject aUrl(rURL);
739 if (INetProtocol::NotValid == aUrl.GetProtocol())
740 // we treat an invalid URL like we would treat no URL
741 return;
742
743 if (!rURL.isEmpty() && !::svt::GraphicAccess::isSupportedURL( rURL ) )
744 {
745 m_pMedium.reset(new SfxMedium(rURL, StreamMode::STD_READ));
746
747 SfxObjectShell *pObjSh = GetObjectShell();
748
749 if( pObjSh )
750 {
751 // Transfer target frame, so that javascript: URLs
752 // can also be "loaded"
753 const SfxMedium *pShMedium = pObjSh->GetMedium();
754 if( pShMedium )
755 m_pMedium->SetLoadTargetFrame(pShMedium->GetLoadTargetFrame());
756 }
757
758 m_bProdStarted = false;
759
760 // Kick off download (caution: can be synchronous).
761 m_pMedium->Download(LINK(this, OClickableImageBaseModel, DownloadDoneLink));
762 }
763 else
764 {
765 if ( ::svt::GraphicAccess::isSupportedURL( rURL ) )
766 GetImageProducer()->SetImage( rURL );
768 }
769 }
770
771
773 {
774 if (!m_bProdStarted)
776
778 }
779
780
781 IMPL_LINK_NOARG( OClickableImageBaseModel, DownloadDoneLink, void*, void )
782 {
783 ::osl::MutexGuard aGuard( m_aMutex );
784 DataAvailable();
785 }
786
787
788 void OClickableImageBaseModel::_propertyChanged( const PropertyChangeEvent& rEvt )
789 {
790 // If a URL was set, it needs to be passed onto the ImageProducer.
791 ::osl::MutexGuard aGuard(m_aMutex);
792 SetURL( getString(rEvt.NewValue) );
793 }
794
795
797 {
798 switch (nHandle)
799 {
800 case PROPERTY_ID_BUTTONTYPE : return Any( FormButtonType_PUSH );
802 case PROPERTY_ID_TARGET_FRAME : return Any( OUString() );
803 case PROPERTY_ID_DISPATCHURLINTERNAL : return Any( false );
804 default:
806 }
807 }
808
809 IMPL_LINK( OClickableImageBaseModel, OnImageImportDone, Graphic*, i_pGraphic, void )
810 {
811 const Reference< XGraphic > xGraphic( i_pGraphic != nullptr ? Graphic(i_pGraphic->GetBitmapEx()).GetXGraphic() : nullptr );
812 if ( !xGraphic.is() )
813 {
814 m_xGraphicObject.clear();
815 }
816 else
817 {
818 m_xGraphicObject = css::graphic::GraphicObject::create( m_xContext );
819 m_xGraphicObject->setGraphic( xGraphic );
820 }
821 }
822
823
824 // OImageProducerThread_Impl
825
827 const EventObject* pEvt,
828 const Reference<XControl>&,
829 bool )
830 {
831 static_cast<OClickableImageBaseControl *>(pCompImpl)->actionPerformed_Impl( true, *static_cast<const MouseEvent *>(pEvt) );
832 }
833
834
835} // namespace frm
836
837
838/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
AnyEventRef aEvent
css::uno::Reference< css::graphic::XGraphic > GetXGraphic() const
INetProtocol GetProtocol() const
void SAL_CALL removeConsumer(const css::uno::Reference< css::awt::XImageConsumer > &rxConsumer) override
Definition: imgprod.cxx:194
void SAL_CALL startProduction() override
Definition: imgprod.cxx:252
void SAL_CALL addConsumer(const css::uno::Reference< css::awt::XImageConsumer > &rxConsumer) override
Definition: imgprod.cxx:186
void SetImage(const OUString &rPath)
Definition: imgprod.cxx:203
void NewDataAvailable()
Definition: imgprod.cxx:245
SfxFrame * GetLoadTargetFrame() const
static SAL_WARN_UNUSED_RESULT SfxObjectShell * GetNext(const SfxObjectShell &rPrev, const std::function< bool(const SfxObjectShell *)> &isObjectShell=nullptr, bool bOnlyVisible=true)
SfxMedium * GetMedium() const
css::uno::Reference< css::frame::XModel3 > GetModel() const
static SAL_WARN_UNUSED_RESULT SfxObjectShell * GetFirst(const std::function< bool(const SfxObjectShell *)> &isObjectShell=nullptr, bool bOnlyVisible=true)
static SAL_WARN_UNUSED_RESULT SfxObjectShell * Current()
sal_Int32 addInterface(const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(const css::uno::Reference< ListenerT > &rxIFace)
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
css::uno::Reference< ListenerT > const & next()
friend friend class OPropertyChangeMultiplexer
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual void SAL_CALL acquire() SAL_NOEXCEPT SAL_OVERRIDE
virtual void SAL_CALL dispose() SAL_OVERRIDE
oslInterlockedCount m_refCount
void releaseDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor > &Interceptor)
const UrlTransformer & getTransformer() const
retrieves our URL transformer, so our clients may use it, too
void registerDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor > &Interceptor)
css::uno::Reference< css::frame::XDispatch > queryDispatch(const css::util::URL &_rURL)
queries the interceptor chain for the given dispatch, with a blank target frame and no frame search f...
void implSubmit(const css::awt::MouseEvent &_rEvent, const css::uno::Reference< css::task::XInteractionHandler > &aHandler)
virtual void SAL_CALL addSubmissionVetoListener(const css::uno::Reference< css::form::submission::XSubmissionVetoListener > &listener) override
OClickableImageBaseControl(const css::uno::Reference< css::uno::XComponentContext > &_rxFactory, const OUString &_aService)
virtual void SAL_CALL submit() override
virtual void SAL_CALL removeSubmissionVetoListener(const css::uno::Reference< css::form::submission::XSubmissionVetoListener > &listener) override
::comphelper::OInterfaceContainerHelper3< css::form::submission::XSubmissionVetoListener > m_aSubmissionVetoListeners
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &_rType) override
virtual void SAL_CALL addApproveActionListener(const css::uno::Reference< css::form::XApproveActionListener > &_rxListener) override
bool approveAction()
approves the action by calling the approve listeners
virtual void SAL_CALL releaseDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor > &Interceptor) override
OImageProducerThread_Impl * getImageProducerThread()
retrieves (and if necessary creates) the image producer thread.
virtual void SAL_CALL submitWithInteraction(const css::uno::Reference< css::task::XInteractionHandler > &aHandler) override
virtual void actionPerformed_Impl(bool bNotifyListener, const css::awt::MouseEvent &rEvt)
virtual ~OClickableImageBaseControl() override
virtual void SAL_CALL removeApproveActionListener(const css::uno::Reference< css::form::XApproveActionListener > &_rxListener) override
rtl::Reference< OImageProducerThread_Impl > m_pThread
::comphelper::OInterfaceContainerHelper3< css::awt::XActionListener > m_aActionListeners
::comphelper::OInterfaceContainerHelper3< css::form::XApproveActionListener > m_aApproveActionListeners
css::uno::Sequence< css::uno::Type > _getTypes() override
virtual void SAL_CALL registerDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor > &Interceptor) override
virtual void SAL_CALL disposing() override
ControlFeatureInterception m_aFeatureInterception
virtual void SAL_CALL getFastPropertyValue(css::uno::Any &rValue, sal_Int32 nHandle) const override
virtual css::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const override
ImageProducer * GetImageProducer()
virtual void SAL_CALL startProduction() override
std::unique_ptr< SfxMedium > m_pMedium
void SetURL(const OUString &rURL)
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
virtual void SAL_CALL removeConsumer(const css::uno::Reference< css::awt::XImageConsumer > &xConsumer) override
css::form::FormButtonType m_eButtonType
virtual void SAL_CALL setSubmission(const css::uno::Reference< css::form::submission::XSubmission > &_submission) override
virtual void SAL_CALL addConsumer(const css::uno::Reference< css::awt::XImageConsumer > &xConsumer) override
virtual void SAL_CALL disposing() override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
SfxObjectShell * GetObjectShell()
virtual sal_Bool SAL_CALL convertFastPropertyValue(css::uno::Any &rConvertedValue, css::uno::Any &rOldValue, sal_Int32 nHandle, const css::uno::Any &rValue) override
virtual css::uno::Reference< css::form::submission::XSubmission > SAL_CALL getSubmission() override
rtl::Reference< ImageProducer > m_xProducer
css::uno::Reference< css::form::submission::XSubmission > m_xSubmissionDelegate
virtual void _propertyChanged(const css::beans::PropertyChangeEvent &) override
OClickableImageBaseModel(const css::uno::Reference< css::uno::XComponentContext > &_rxFactory, const OUString &_rUnoControlModelTypeName, const OUString &_rDefault)
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &_rType) override
css::uno::Sequence< css::uno::Type > _getTypes() override
virtual ~OClickableImageBaseModel() override
virtual css::uno::Sequence< css::uno::Type > _getTypes()
virtual void SAL_CALL getFastPropertyValue(css::uno::Any &rValue, sal_Int32 nHandle) const override
::osl::Mutex m_aMutex
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL disposing() override
virtual css::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const override
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &_rType) override
virtual sal_Bool SAL_CALL convertFastPropertyValue(css::uno::Any &_rConvertedValue, css::uno::Any &_rOldValue, sal_Int32 _nHandle, const css::uno::Any &_rValue) override
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &_rType) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual css::uno::Reference< css::awt::XControlModel > SAL_CALL getModel() override
virtual void SAL_CALL disposing() override
virtual css::uno::Sequence< css::uno::Type > _getTypes()
::osl::Mutex m_aMutex
virtual void SAL_CALL dispose() override
virtual void processEvent(::cppu::OComponentHelper *pCompImpl, const css::lang::EventObject *, const css::uno::Reference< css::awt::XControl > &, bool) override
css::util::URL getStrictURL(const OUString &_rURL) const
returns a URL object for the given URL string
void parseSmartWithProtocol(css::util::URL &_rURL, const OUString &_rProtocol) const
parses a given URL smartly, with a given protocol
#define LOCAL_URL_PREFIX
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
URL aURL
#define ERRCODE_NONE
constexpr OUStringLiteral PROPERTY_TARGET_URL
Definition: frm_strings.hxx:49
constexpr OUStringLiteral PROPERTY_DISPATCHURLINTERNAL
constexpr OUStringLiteral PROPERTY_TARGET_FRAME
Definition: frm_strings.hxx:50
constexpr OUStringLiteral PROPERTY_IMAGE_URL
Definition: frm_strings.hxx:72
constexpr OUStringLiteral PROPERTY_BUTTONTYPE
Definition: frm_strings.hxx:61
std::mutex m_aMutex
@ Exception
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &... rSn)
bool tryPropertyValue(Any &_rConvertedValue, Any &_rOldValue, const Any &_rValueToSet, const Any &_rCurrentValue, const Type &_rExpectedType)
std::enable_if< std::is_enum< ENUMTYPE >::value, bool >::type tryPropertyValueEnum(css::uno::Any &_rConvertedValue, css::uno::Any &_rOldValue, const css::uno::Any &_rValueToSet, const ENUMTYPE &_rCurrentValue)
OUString getString(const Any &_rAny)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
Type
Any SAL_CALL getCaughtException()
ListBox is a bit confusing / different from other form components, so here are a few notes:
Definition: BaseListBox.hxx:25
IMPL_LINK_NOARG(OButtonControl, OnClick, void *, void)
Definition: Button.cxx:440
IMPL_LINK(OClickableImageBaseModel, OnImageImportDone, Graphic *, i_pGraphic, void)
css::uno::Reference< css::frame::XModel > getXModel(const css::uno::Reference< css::uno::XInterface > &_rxComponent)
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
#define PROPERTY_ID_DISPATCHURLINTERNAL
Definition: property.hxx:248
#define PROPERTY_ID_TARGET_FRAME
Definition: property.hxx:154
#define PROPERTY_ID_TARGET_URL
Definition: property.hxx:153
#define PROPERTY_ID_BUTTONTYPE
Definition: property.hxx:105
#define PROPERTY_ID_IMAGE_URL
Definition: property.hxx:114
sal_Int32 nHandle
constexpr OUStringLiteral FRM_SUN_COMPONENT_SUBMITBUTTON
Definition: services.hxx:135
constexpr OUStringLiteral FRM_SUN_CONTROL_SUBMITBUTTON
Definition: services.hxx:167
Reference< XController > xController
Reference< XFrame > xFrame
Reference< XModel > xModel
unsigned char sal_Bool
const SvXMLTokenMapEntry aTypes[]