update dev300-m58
[ooovba.git] / forms / source / component / ImageControl.cxx
blob73530380a0323cf592e1215b7ef40027d3f82344
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ImageControl.cxx,v $
10 * $Revision: 1.49 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_forms.hxx"
33 #include "ImageControl.hxx"
35 #include "property.hrc"
36 #include "frm_resource.hrc"
37 #include "frm_resource.hxx"
38 #include "services.hxx"
39 #include "componenttools.hxx"
41 #include <svtools/imageresourceaccess.hxx>
42 #include <unotools/ucblockbytes.hxx>
43 #include <sfx2/filedlghelper.hxx>
44 #include <com/sun/star/awt/XPopupMenu.hpp>
45 #include <com/sun/star/awt/PopupMenuDirection.hpp>
46 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
47 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
48 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
49 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
50 #include <com/sun/star/sdbc/DataType.hpp>
51 #include <com/sun/star/awt/MouseButton.hpp>
52 #include <com/sun/star/awt/XWindow.hpp>
53 #include <com/sun/star/awt/XDialog.hpp>
54 #include <com/sun/star/io/XActiveDataSink.hpp>
55 #include <com/sun/star/io/NotConnectedException.hpp>
56 #include <com/sun/star/beans/PropertyValue.hpp>
57 #include <com/sun/star/graphic/XGraphic.hpp>
58 #include <com/sun/star/graphic/GraphicObject.hpp>
59 #include <tools/urlobj.hxx>
60 #include <tools/stream.hxx>
61 #include <tools/debug.hxx>
62 #include <tools/diagnose_ex.h>
63 #include <vcl/svapp.hxx>
64 #include <unotools/streamhelper.hxx>
65 #include <comphelper/extract.hxx>
66 #include <comphelper/guarding.hxx>
67 #include <unotools/ucbstreamhelper.hxx>
68 #include <svtools/urihelper.hxx>
70 #include <memory>
72 #define ID_OPEN_GRAPHICS 1
73 #define ID_CLEAR_GRAPHICS 2
75 //.........................................................................
76 namespace frm
78 //.........................................................................
79 using namespace ::com::sun::star;
80 using namespace ::com::sun::star::uno;
81 using namespace ::com::sun::star::sdb;
82 using namespace ::com::sun::star::sdbc;
83 using namespace ::com::sun::star::sdbcx;
84 using namespace ::com::sun::star::beans;
85 using namespace ::com::sun::star::container;
86 using namespace ::com::sun::star::form;
87 using namespace ::com::sun::star::awt;
88 using namespace ::com::sun::star::io;
89 using namespace ::com::sun::star::ui::dialogs;
90 using namespace ::com::sun::star::lang;
91 using namespace ::com::sun::star::util;
92 using namespace ::com::sun::star::graphic;
93 using namespace ::com::sun::star::frame;
95 //==============================================================================
96 //= OImageControlModel
97 //==============================================================================
98 namespace
100 enum ImageStoreType
102 ImageStoreBinary,
103 ImageStoreLink,
105 ImageStoreInvalid
108 ImageStoreType lcl_getImageStoreType( const sal_Int32 _nFieldType )
110 // binary/longvarchar types could be used to store images in binary representation
111 if ( ( _nFieldType == DataType::BINARY )
112 || ( _nFieldType == DataType::VARBINARY )
113 || ( _nFieldType == DataType::LONGVARBINARY )
114 || ( _nFieldType == DataType::OTHER )
115 || ( _nFieldType == DataType::OBJECT )
116 || ( _nFieldType == DataType::BLOB )
117 || ( _nFieldType == DataType::LONGVARCHAR )
119 return ImageStoreBinary;
121 // char types could be used to store links to images
122 if ( ( _nFieldType == DataType::CHAR )
123 || ( _nFieldType == DataType::VARCHAR )
125 return ImageStoreLink;
127 return ImageStoreInvalid;
131 //==============================================================================
132 // OImageControlModel
133 //==============================================================================
135 //------------------------------------------------------------------------------
136 InterfaceRef SAL_CALL OImageControlModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
138 return *(new OImageControlModel(_rxFactory));
141 //------------------------------------------------------------------------------
142 Sequence<Type> OImageControlModel::_getTypes()
144 return concatSequences(
145 OBoundControlModel::_getTypes(),
146 OImageControlModel_Base::getTypes()
150 DBG_NAME(OImageControlModel)
151 //------------------------------------------------------------------
152 OImageControlModel::OImageControlModel(const Reference<XMultiServiceFactory>& _rxFactory)
153 :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_IMAGECONTROL, FRM_SUN_CONTROL_IMAGECONTROL, sal_False, sal_False, sal_False )
154 // use the old control name for compytibility reasons
155 ,m_pImageProducer( NULL )
156 ,m_bReadOnly( sal_False )
158 DBG_CTOR( OImageControlModel, NULL );
159 m_nClassId = FormComponentType::IMAGECONTROL;
160 initValueProperty( PROPERTY_IMAGE_URL, PROPERTY_ID_IMAGE_URL);
162 implConstruct();
165 //------------------------------------------------------------------
166 OImageControlModel::OImageControlModel( const OImageControlModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory )
167 :OBoundControlModel( _pOriginal, _rxFactory )
168 // use the old control name for compytibility reasons
169 ,m_pImageProducer( NULL )
171 DBG_CTOR( OImageControlModel, NULL );
172 implConstruct();
173 m_bReadOnly = _pOriginal->m_bReadOnly;
175 osl_incrementInterlockedCount( &m_refCount );
177 // simulate a propertyChanged event for the ImageURL
178 // 2003-05-15 - #109591# - fs@openoffice.org
179 Any aImageURL;
180 getFastPropertyValue( aImageURL, PROPERTY_ID_IMAGE_URL );
181 ::rtl::OUString sImageURL;
182 aImageURL >>= sImageURL;
184 ::osl::MutexGuard aGuard( m_aMutex );
185 impl_handleNewImageURL_lck( sImageURL, eOther );
187 osl_decrementInterlockedCount( &m_refCount );
190 //------------------------------------------------------------------
191 void OImageControlModel::implConstruct()
193 m_pImageProducer = new ImageProducer;
194 m_xImageProducer = m_pImageProducer;
197 //------------------------------------------------------------------
198 OImageControlModel::~OImageControlModel()
200 if (!OComponentHelper::rBHelper.bDisposed)
202 acquire();
203 dispose();
206 DBG_DTOR(OImageControlModel,NULL);
209 // XCloneable
210 //------------------------------------------------------------------------------
211 IMPLEMENT_DEFAULT_CLONING( OImageControlModel )
213 // XServiceInfo
214 //------------------------------------------------------------------------------
215 StringSequence OImageControlModel::getSupportedServiceNames() throw()
217 StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
218 aSupported.realloc(aSupported.getLength() + 1);
220 ::rtl::OUString*pArray = aSupported.getArray();
221 pArray[aSupported.getLength()-1] = FRM_SUN_COMPONENT_IMAGECONTROL;
222 return aSupported;
225 //------------------------------------------------------------------------------
226 Any SAL_CALL OImageControlModel::queryAggregation(const Type& _rType) throw (RuntimeException)
228 // oder matters: we want to "override" the XImageProducer interface of the aggreate with out
229 // own XImageProducer interface, thus we need to query OImageControlModel_Base first
230 Any aReturn = OImageControlModel_Base::queryInterface( _rType );
232 // BUT: _don't_ let it feel responsible for the XTypeProvider interface
233 // (as this is implemented by our base class in the proper way)
234 if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) )
235 || !aReturn.hasValue()
237 aReturn = OBoundControlModel::queryAggregation( _rType );
239 return aReturn;
242 //------------------------------------------------------------------------------
243 sal_Bool OImageControlModel::approveDbColumnType( sal_Int32 _nColumnType )
245 return ImageStoreInvalid != lcl_getImageStoreType( _nColumnType );
249 //------------------------------------------------------------------------------
250 void OImageControlModel::_propertyChanged( const PropertyChangeEvent& _rEvent )
251 throw( RuntimeException )
253 if ( m_xColumnUpdate.is() )
255 OBoundControlModel::_propertyChanged( _rEvent );
257 else
258 { // we're not bound. In this case, we have to manually care for updating the
259 // image producer, since the base class will not do this
260 ::rtl::OUString sImageURL;
261 _rEvent.NewValue >>= sImageURL;
263 ::osl::MutexGuard aGuard( m_aMutex );
264 impl_handleNewImageURL_lck( sImageURL, eOther );
268 //------------------------------------------------------------------------------
269 void OImageControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
271 switch (nHandle)
273 case PROPERTY_ID_READONLY : rValue <<= (sal_Bool)m_bReadOnly; break;
274 default:
275 OBoundControlModel::getFastPropertyValue(rValue, nHandle);
279 //------------------------------------------------------------------------------
280 void OImageControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception)
282 switch (nHandle)
284 case PROPERTY_ID_READONLY :
285 DBG_ASSERT(rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, "OImageControlModel::setFastPropertyValue_NoBroadcast : invalid type !" );
286 m_bReadOnly = getBOOL(rValue);
287 break;
289 default:
290 OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue);
294 //------------------------------------------------------------------------------
295 sal_Bool OImageControlModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
296 throw( IllegalArgumentException )
298 switch (nHandle)
300 case PROPERTY_ID_READONLY :
301 return tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bReadOnly);
303 default:
304 return OBoundControlModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
308 //------------------------------------------------------------------------------
309 void OImageControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
311 BEGIN_DESCRIBE_PROPERTIES( 2, OBoundControlModel )
312 DECL_BOOL_PROP1 ( READONLY, BOUND );
313 DECL_PROP1 ( TABINDEX, sal_Int16, BOUND );
314 END_DESCRIBE_PROPERTIES();
317 //------------------------------------------------------------------------------
318 ::rtl::OUString OImageControlModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException)
320 return FRM_COMPONENT_IMAGECONTROL; // old (non-sun) name for compatibility !
323 //------------------------------------------------------------------------------
324 void OImageControlModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
326 // Basisklasse
327 OBoundControlModel::write(_rxOutStream);
328 // Version
329 _rxOutStream->writeShort(0x0003);
330 // Name
331 _rxOutStream->writeBoolean(m_bReadOnly);
332 writeHelpTextCompatibly(_rxOutStream);
333 // from version 0x0003 : common properties
334 writeCommonProperties(_rxOutStream);
337 //------------------------------------------------------------------------------
338 void OImageControlModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
340 OBoundControlModel::read(_rxInStream);
342 // Version
343 sal_uInt16 nVersion = _rxInStream->readShort();
344 switch (nVersion)
346 case 0x0001:
347 m_bReadOnly = _rxInStream->readBoolean();
348 break;
349 case 0x0002:
350 m_bReadOnly = _rxInStream->readBoolean();
351 readHelpTextCompatibly(_rxInStream);
352 break;
353 case 0x0003:
354 m_bReadOnly = _rxInStream->readBoolean();
355 readHelpTextCompatibly(_rxInStream);
356 readCommonProperties(_rxInStream);
357 break;
358 default :
359 DBG_ERROR("OImageControlModel::read : unknown version !");
360 m_bReadOnly = sal_False;
361 defaultCommonProperties();
362 break;
364 // Nach dem Lesen die Defaultwerte anzeigen
365 if ( getControlSource().getLength() )
366 { // (not if we don't have a control source - the "State" property acts like it is persistent, then
367 ::osl::MutexGuard aGuard(m_aMutex); // resetNoBroadcast expects this mutex guarding
368 resetNoBroadcast();
372 //------------------------------------------------------------------------------
373 sal_Bool OImageControlModel::impl_updateStreamForURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator )
375 // create a stream for the image specified by the URL
376 ::std::auto_ptr< SvStream > pImageStream;
377 Reference< XInputStream > xImageStream;
379 if ( ::svt::GraphicAccess::isSupportedURL( _rURL ) )
381 xImageStream = ::svt::GraphicAccess::getImageXStream( getContext().getLegacyServiceFactory(), _rURL );
383 else
385 pImageStream.reset( ::utl::UcbStreamHelper::CreateStream( _rURL, STREAM_READ ) );
386 sal_Bool bSetNull = ( pImageStream.get() == NULL ) || ( ERRCODE_NONE != pImageStream->GetErrorCode() );
388 if ( !bSetNull )
390 // get the size of the stream
391 pImageStream->Seek(STREAM_SEEK_TO_END);
392 sal_Int32 nSize = (sal_Int32)pImageStream->Tell();
393 if (pImageStream->GetBufferSize() < 8192)
394 pImageStream->SetBufferSize(8192);
395 pImageStream->Seek(STREAM_SEEK_TO_BEGIN);
397 xImageStream = new ::utl::OInputStreamHelper( new SvLockBytes( pImageStream.get(), sal_False ), nSize );
401 if ( xImageStream.is() )
403 if ( m_xColumnUpdate.is() )
404 m_xColumnUpdate->updateBinaryStream( xImageStream, xImageStream->available() );
405 else
406 setControlValue( makeAny( xImageStream ), _eInstigator );
407 xImageStream->closeInput();
408 return sal_True;
411 return sal_False;
414 //------------------------------------------------------------------------------
415 sal_Bool OImageControlModel::impl_handleNewImageURL_lck( const ::rtl::OUString& _rURL, ValueChangeInstigator _eInstigator )
417 switch ( lcl_getImageStoreType( getFieldType() ) )
419 case ImageStoreBinary:
420 if ( impl_updateStreamForURL_lck( _rURL, _eInstigator ) )
421 return sal_True;
422 break;
424 case ImageStoreLink:
426 ::rtl::OUString sCommitURL( _rURL );
427 if ( m_sDocumentURL.getLength() )
428 sCommitURL = URIHelper::simpleNormalizedMakeRelative( m_sDocumentURL, sCommitURL );
429 OSL_ENSURE( m_xColumnUpdate.is(), "OImageControlModel::impl_handleNewImageURL_lck: no bound field, but ImageStoreLink?!" );
430 if ( m_xColumnUpdate.is() )
432 m_xColumnUpdate->updateString( sCommitURL );
433 return sal_True;
436 break;
438 case ImageStoreInvalid:
439 OSL_ENSURE( false, "OImageControlModel::impl_handleNewImageURL_lck: invalid current field type!" );
440 break;
443 // if we're here, then the above code was unable to update our field/control from the given URL
444 // => fall back to NULL/VOID
445 if ( m_xColumnUpdate.is() )
446 m_xColumnUpdate->updateNull();
447 else
448 setControlValue( Any(), _eInstigator );
450 return sal_True;
453 //------------------------------------------------------------------------------
454 sal_Bool OImageControlModel::commitControlValueToDbColumn( bool _bPostReset )
456 if ( _bPostReset )
458 // since this is a "commit after reset", we can simply update the column
459 // with null - this is our "default" which we were just reset to
460 if ( m_xColumnUpdate.is() )
461 m_xColumnUpdate->updateNull();
463 else
465 ::osl::MutexGuard aGuard(m_aMutex);
467 ::rtl::OUString sImageURL;
468 m_xAggregateSet->getPropertyValue( PROPERTY_IMAGE_URL ) >>= sImageURL;
469 return impl_handleNewImageURL_lck( sImageURL, eDbColumnBinding );
472 return sal_True;
475 //------------------------------------------------------------------------------
476 namespace
478 bool lcl_isValidDocumentURL( const ::rtl::OUString& _rDocURL )
480 return ( _rDocURL.getLength() && !_rDocURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:object" ) ) );
484 //------------------------------------------------------------------------------
485 void OImageControlModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm )
487 OBoundControlModel::onConnectedDbColumn( _rxForm );
491 Reference< XModel > xDocument( getXModel( *this ) );
492 if ( xDocument.is() )
494 m_sDocumentURL = xDocument->getURL();
495 if ( !lcl_isValidDocumentURL( m_sDocumentURL ) )
497 Reference< XChild > xAsChild( xDocument, UNO_QUERY );
498 while ( xAsChild.is() && !lcl_isValidDocumentURL( m_sDocumentURL ) )
500 xDocument.set( xAsChild->getParent(), UNO_QUERY );
501 if ( xDocument.is() )
502 m_sDocumentURL = xDocument->getURL();
503 xAsChild.set( xDocument, UNO_QUERY );
508 catch( const Exception& )
510 DBG_UNHANDLED_EXCEPTION();
514 //------------------------------------------------------------------------------
515 void OImageControlModel::onDisconnectedDbColumn()
517 OBoundControlModel::onDisconnectedDbColumn();
519 m_sDocumentURL = ::rtl::OUString();
522 //------------------------------------------------------------------------------
523 Any OImageControlModel::translateDbColumnToControlValue()
525 switch ( lcl_getImageStoreType( getFieldType() ) )
527 case ImageStoreBinary: return makeAny( m_xColumn->getBinaryStream() );
528 case ImageStoreLink:
530 ::rtl::OUString sImageLink( m_xColumn->getString() );
531 if ( m_sDocumentURL.getLength() )
532 sImageLink = INetURLObject::GetAbsURL( m_sDocumentURL, sImageLink );
533 return makeAny( sImageLink );
535 case ImageStoreInvalid:
536 OSL_ENSURE( false, "OImageControlModel::translateDbColumnToControlValue: invalid field type!" );
537 break;
539 return Any();
542 //------------------------------------------------------------------------------
543 void OImageControlModel::doSetControlValue( const Any& _rValue )
545 DBG_ASSERT( GetImageProducer() && m_xImageProducer.is(), "OImageControlModel::doSetControlValue: no image producer!" );
546 if ( !GetImageProducer() || !m_xImageProducer.is() )
547 return;
549 bool bStartProduction = false;
550 switch ( lcl_getImageStoreType( getFieldType() ) )
552 case ImageStoreBinary:
554 // give the image producer the stream
555 Reference< XInputStream > xInStream;
556 _rValue >>= xInStream;
557 GetImageProducer()->setImage( xInStream );
558 bStartProduction = true;
560 break;
562 case ImageStoreLink:
564 ::rtl::OUString sImageURL;
565 _rValue >>= sImageURL;
566 GetImageProducer()->SetImage( sImageURL );
567 bStartProduction = true;
569 break;
571 case ImageStoreInvalid:
572 OSL_ENSURE( false, "OImageControlModel::doSetControlValue: invalid field type!" );
573 break;
575 } // switch ( lcl_getImageStoreType( getFieldType() ) )
577 if ( bStartProduction )
579 // start production
580 Reference< XImageProducer > xProducer = m_xImageProducer;
582 // release our mutex once (it's acquired in the calling method!), as starting the image production may
583 // result in the locking of the solar mutex (unfortunally the default implementation of our aggregate,
584 // VCLXImageControl, does this locking)
585 // FS - 74438 - 30.03.00
586 MutexRelease aRelease(m_aMutex);
587 xProducer->startProduction();
592 // OComponentHelper
593 //------------------------------------------------------------------
594 void SAL_CALL OImageControlModel::disposing()
596 OBoundControlModel::disposing();
599 ::osl::MutexGuard aGuard( m_aMutex ); // setControlValue expects this
600 setControlValue( Any(), eOther );
604 //------------------------------------------------------------------------------
605 void OImageControlModel::resetNoBroadcast()
607 if ( hasField() ) // only reset when we are connected to a column
608 OBoundControlModel::resetNoBroadcast( );
611 //--------------------------------------------------------------------
612 Reference< XImageProducer > SAL_CALL OImageControlModel::getImageProducer() throw ( RuntimeException)
614 return this;
617 //--------------------------------------------------------------------
618 void SAL_CALL OImageControlModel::addConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException)
620 GetImageProducer()->addConsumer( _rxConsumer );
623 //--------------------------------------------------------------------
624 void SAL_CALL OImageControlModel::removeConsumer( const Reference< XImageConsumer >& _rxConsumer ) throw (RuntimeException)
626 GetImageProducer()->removeConsumer( _rxConsumer );
629 //--------------------------------------------------------------------
630 void SAL_CALL OImageControlModel::startProduction( ) throw (RuntimeException)
632 GetImageProducer()->startProduction();
636 //==================================================================
637 // OImageControlControl
638 //==================================================================
640 //------------------------------------------------------------------
641 InterfaceRef SAL_CALL OImageControlControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
643 return *(new OImageControlControl(_rxFactory));
646 //------------------------------------------------------------------------------
647 Sequence<Type> OImageControlControl::_getTypes()
649 return concatSequences(
650 OBoundControl::_getTypes(),
651 OImageControlControl_Base::getTypes()
655 //------------------------------------------------------------------------------
656 OImageControlControl::OImageControlControl(const Reference<XMultiServiceFactory>& _rxFactory)
657 :OBoundControl(_rxFactory, VCL_CONTROL_IMAGECONTROL)
658 ,m_aModifyListeners( m_aMutex )
660 increment(m_refCount);
662 // als Focus- und MouseListener anmelden
663 Reference< XWindow > xComp;
664 query_aggregation( m_xAggregate, xComp );
665 if ( xComp.is() )
666 xComp->addMouseListener( this );
668 decrement(m_refCount);
671 //------------------------------------------------------------------------------
672 Any SAL_CALL OImageControlControl::queryAggregation(const Type& _rType) throw (RuntimeException)
674 Any aReturn = OBoundControl::queryAggregation( _rType );
675 if ( !aReturn.hasValue() )
676 aReturn = ::cppu::queryInterface(
677 _rType,
678 static_cast< XMouseListener* >( this ),
679 static_cast< XModifyBroadcaster* >( this )
682 return aReturn;
685 //------------------------------------------------------------------------------
686 StringSequence OImageControlControl::getSupportedServiceNames() throw()
688 StringSequence aSupported = OBoundControl::getSupportedServiceNames();
689 aSupported.realloc(aSupported.getLength() + 1);
691 ::rtl::OUString*pArray = aSupported.getArray();
692 pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_IMAGECONTROL;
693 return aSupported;
696 //------------------------------------------------------------------------------
697 void SAL_CALL OImageControlControl::addModifyListener( const Reference< XModifyListener >& _Listener ) throw (RuntimeException)
699 m_aModifyListeners.addInterface( _Listener );
702 //------------------------------------------------------------------------------
703 void SAL_CALL OImageControlControl::removeModifyListener( const Reference< XModifyListener >& _Listener ) throw (RuntimeException)
705 m_aModifyListeners.removeInterface( _Listener );
708 //------------------------------------------------------------------------------
709 void SAL_CALL OImageControlControl::disposing()
711 EventObject aEvent( *this );
712 m_aModifyListeners.disposeAndClear( aEvent );
714 OBoundControl::disposing();
717 //------------------------------------------------------------------------------
718 void SAL_CALL OImageControlControl::disposing( const EventObject& _Event ) throw(RuntimeException)
720 OBoundControl::disposing( _Event );
723 //------------------------------------------------------------------------------
724 void OImageControlControl::implClearGraphics( sal_Bool _bForce )
726 Reference< XPropertySet > xSet( getModel(), UNO_QUERY );
727 if ( xSet.is() )
729 if ( _bForce )
731 ::rtl::OUString sOldImageURL;
732 xSet->getPropertyValue( PROPERTY_IMAGE_URL ) >>= sOldImageURL;
734 if ( !sOldImageURL.getLength() )
735 // the ImageURL is already empty, so simply setting a new empty one would not suffice
736 // (since it would be ignored)
737 xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:emptyImage" ) ) ) );
738 // (the concrete URL we're passing here doens't matter. It's important that
739 // the model cannot resolve it to a a valid resource describing an image stream
742 xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString() ) );
746 //------------------------------------------------------------------------------
747 bool OImageControlControl::implInsertGraphics()
749 Reference< XPropertySet > xSet( getModel(), UNO_QUERY );
750 if ( !xSet.is() )
751 return false;
753 ::rtl::OUString sTitle = FRM_RES_STRING(RID_STR_IMPORT_GRAPHIC);
754 // build some arguments for the upcoming dialog
757 ::sfx2::FileDialogHelper aDialog( TemplateDescription::FILEOPEN_LINK_PREVIEW, SFXWB_GRAPHIC );
758 aDialog.SetTitle( sTitle );
760 Reference< XFilePickerControlAccess > xController( aDialog.GetFilePicker(), UNO_QUERY_THROW );
761 xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, ::cppu::bool2any(sal_True));
763 Reference<XPropertySet> xBoundField;
764 if ( hasProperty( PROPERTY_BOUNDFIELD, xSet ) )
765 xSet->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xBoundField;
766 sal_Bool bHasField = xBoundField.is();
768 // if the control is bound to a DB field, then it's not possible to decide whether or not to link
769 xController->enableControl(ExtendedFilePickerElementIds::CHECKBOX_LINK, !bHasField );
771 // if the control is bound to a DB field, then linking of the image depends on the type of the field
772 sal_Bool bImageIsLinked = sal_True;
773 if ( bHasField )
775 sal_Int32 nFieldType = DataType::OTHER;
776 OSL_VERIFY( xBoundField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType );
777 bImageIsLinked = ( lcl_getImageStoreType( nFieldType ) == ImageStoreLink );
779 xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, makeAny( bImageIsLinked ) );
781 if ( ERRCODE_NONE == aDialog.Execute() )
783 // reset the url property in case it already has the value we're about to set - in this case
784 // our propertyChanged would not get called without this.
785 implClearGraphics( sal_False );
786 sal_Bool bIsLink = sal_False;
787 xController->getValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0) >>= bIsLink;
788 if ( !bIsLink )
790 Graphic aGraphic;
791 aDialog.GetGraphic( aGraphic );
793 Reference< graphic::XGraphicObject > xGrfObj = graphic::GraphicObject::create( m_aContext.getUNOContext() );
794 xGrfObj->setGraphic( aGraphic.GetXGraphic() );
795 rtl::OUString sObjectID( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
796 sObjectID = sObjectID + xGrfObj->getUniqueID();
797 xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( sObjectID ) ) );
799 else
800 xSet->setPropertyValue( PROPERTY_IMAGE_URL, makeAny( ::rtl::OUString( aDialog.GetPath() ) ) );
802 return true;
805 catch(Exception&)
807 DBG_ERROR("OImageControlControl::implInsertGraphics: caught an exception while attempting to execute the FilePicker!");
809 return false;
812 //------------------------------------------------------------------------------
813 bool OImageControlControl::impl_isEmptyGraphics_nothrow() const
815 bool bIsEmpty = true;
819 Reference< XPropertySet > xModelProps( const_cast< OImageControlControl* >( this )->getModel(), UNO_QUERY_THROW );
820 Reference< XGraphic > xGraphic;
821 OSL_VERIFY( xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" ) ) ) >>= xGraphic );
822 bIsEmpty = !xGraphic.is();
824 catch( const Exception& )
826 DBG_UNHANDLED_EXCEPTION();
829 return bIsEmpty;
832 // MouseListener
833 //------------------------------------------------------------------------------
834 void OImageControlControl::mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw ( ::com::sun::star::uno::RuntimeException)
836 ::vos::OGuard aGuard( Application::GetSolarMutex() );
838 if (e.Buttons != MouseButton::LEFT)
839 return;
841 bool bModified = false;
842 // is this a request for a context menu?
843 if ( e.PopupTrigger )
845 Reference< XPopupMenu > xMenu( m_aContext.createComponent( "com.sun.star.awt.PopupMenu" ), UNO_QUERY );
846 DBG_ASSERT( xMenu.is(), "OImageControlControl::mousePressed: could not create a popup menu!" );
848 Reference< XWindowPeer > xWindowPeer = getPeer();
849 DBG_ASSERT( xWindowPeer.is(), "OImageControlControl::mousePressed: no window!" );
851 if ( xMenu.is() && xWindowPeer.is() )
853 xMenu->insertItem( ID_OPEN_GRAPHICS, FRM_RES_STRING( RID_STR_OPEN_GRAPHICS ), 0, 0 );
854 xMenu->insertItem( ID_CLEAR_GRAPHICS, FRM_RES_STRING( RID_STR_CLEAR_GRAPHICS ), 0, 1 );
856 // check if the ImageURL is empty
857 if ( impl_isEmptyGraphics_nothrow() )
858 xMenu->enableItem( ID_CLEAR_GRAPHICS, sal_False );
860 awt::Rectangle aRect( e.X, e.Y, 0, 0 );
861 if ( ( e.X < 0 ) || ( e.Y < 0 ) )
862 { // context menu triggered by keyboard
863 // position it in the center of the control
864 // 102205 - 16.08.2002 - fs@openoffice.org
865 Reference< XWindow > xWindow( static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY );
866 OSL_ENSURE( xWindow.is(), "OImageControlControl::mousePressed: me not a window? How this?" );
867 if ( xWindow.is() )
869 awt::Rectangle aPosSize = xWindow->getPosSize();
870 aRect.X = aPosSize.Width / 2;
871 aRect.Y = aPosSize.Height / 2;
875 const sal_Int16 nResult = xMenu->execute( xWindowPeer, aRect, PopupMenuDirection::EXECUTE_DEFAULT );
877 switch ( nResult )
879 case ID_OPEN_GRAPHICS:
880 implInsertGraphics();
881 bModified = true;
882 break;
884 case ID_CLEAR_GRAPHICS:
885 implClearGraphics( sal_True );
886 bModified = true;
887 break;
891 else
893 //////////////////////////////////////////////////////////////////////
894 // Doppelclick
895 if (e.ClickCount == 2)
898 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
899 if (!xSet.is())
900 return;
902 // wenn Control nicht gebunden ist, kein Dialog (da die zu schickende URL hinterher sowieso
903 // versanden wuerde)
904 // FS - #64946# - 19.04.99
905 Reference<XPropertySet> xBoundField;
906 if (hasProperty(PROPERTY_BOUNDFIELD, xSet))
907 ::cppu::extractInterface(xBoundField, xSet->getPropertyValue(PROPERTY_BOUNDFIELD));
908 if (!xBoundField.is())
910 // but only if our IMAGE_URL property is handled as if it is transient, which is equivalent to
911 // an empty control source
912 if (!hasProperty(PROPERTY_CONTROLSOURCE, xSet) || (::comphelper::getString(xSet->getPropertyValue(PROPERTY_CONTROLSOURCE)).getLength() != 0))
913 return;
916 sal_Bool bReadOnly = false;
917 xSet->getPropertyValue(PROPERTY_READONLY) >>= bReadOnly;
918 if (bReadOnly)
919 return;
921 if ( implInsertGraphics() )
922 bModified = true;
926 if ( bModified )
928 EventObject aEvent( *this );
929 m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
933 //------------------------------------------------------------------------------
934 void SAL_CALL OImageControlControl::mouseReleased(const awt::MouseEvent& /*e*/) throw ( RuntimeException )
938 //------------------------------------------------------------------------------
939 void SAL_CALL OImageControlControl::mouseEntered(const awt::MouseEvent& /*e*/) throw ( RuntimeException )
943 //------------------------------------------------------------------------------
944 void SAL_CALL OImageControlControl::mouseExited(const awt::MouseEvent& /*e*/) throw ( RuntimeException )
948 //.........................................................................
949 } // namespace frm
950 //.........................................................................