1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ImageControl.cxx,v $
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>
72 #define ID_OPEN_GRAPHICS 1
73 #define ID_CLEAR_GRAPHICS 2
75 //.........................................................................
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 //==============================================================================
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
);
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
);
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
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
)
206 DBG_DTOR(OImageControlModel
,NULL
);
210 //------------------------------------------------------------------------------
211 IMPLEMENT_DEFAULT_CLONING( OImageControlModel
)
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
;
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
);
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
);
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
273 case PROPERTY_ID_READONLY
: rValue
<<= (sal_Bool
)m_bReadOnly
; break;
275 OBoundControlModel::getFastPropertyValue(rValue
, nHandle
);
279 //------------------------------------------------------------------------------
280 void OImageControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
, const Any
& rValue
) throw ( ::com::sun::star::uno::Exception
)
284 case PROPERTY_ID_READONLY
:
285 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_BOOLEAN
, "OImageControlModel::setFastPropertyValue_NoBroadcast : invalid type !" );
286 m_bReadOnly
= getBOOL(rValue
);
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
)
300 case PROPERTY_ID_READONLY
:
301 return tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_bReadOnly
);
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
)
327 OBoundControlModel::write(_rxOutStream
);
329 _rxOutStream
->writeShort(0x0003);
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
);
343 sal_uInt16 nVersion
= _rxInStream
->readShort();
347 m_bReadOnly
= _rxInStream
->readBoolean();
350 m_bReadOnly
= _rxInStream
->readBoolean();
351 readHelpTextCompatibly(_rxInStream
);
354 m_bReadOnly
= _rxInStream
->readBoolean();
355 readHelpTextCompatibly(_rxInStream
);
356 readCommonProperties(_rxInStream
);
359 DBG_ERROR("OImageControlModel::read : unknown version !");
360 m_bReadOnly
= sal_False
;
361 defaultCommonProperties();
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
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
);
385 pImageStream
.reset( ::utl::UcbStreamHelper::CreateStream( _rURL
, STREAM_READ
) );
386 sal_Bool bSetNull
= ( pImageStream
.get() == NULL
) || ( ERRCODE_NONE
!= pImageStream
->GetErrorCode() );
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() );
406 setControlValue( makeAny( xImageStream
), _eInstigator
);
407 xImageStream
->closeInput();
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
) )
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
);
438 case ImageStoreInvalid
:
439 OSL_ENSURE( false, "OImageControlModel::impl_handleNewImageURL_lck: invalid current field type!" );
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();
448 setControlValue( Any(), _eInstigator
);
453 //------------------------------------------------------------------------------
454 sal_Bool
OImageControlModel::commitControlValueToDbColumn( bool _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();
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
);
475 //------------------------------------------------------------------------------
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() );
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!" );
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() )
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;
564 ::rtl::OUString sImageURL
;
565 _rValue
>>= sImageURL
;
566 GetImageProducer()->SetImage( sImageURL
);
567 bStartProduction
= true;
571 case ImageStoreInvalid
:
572 OSL_ENSURE( false, "OImageControlModel::doSetControlValue: invalid field type!" );
575 } // switch ( lcl_getImageStoreType( getFieldType() ) )
577 if ( bStartProduction
)
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();
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
)
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
);
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(
678 static_cast< XMouseListener
* >( this ),
679 static_cast< XModifyBroadcaster
* >( this )
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
;
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
);
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
);
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
;
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
;
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
) ) );
800 xSet
->setPropertyValue( PROPERTY_IMAGE_URL
, makeAny( ::rtl::OUString( aDialog
.GetPath() ) ) );
807 DBG_ERROR("OImageControlControl::implInsertGraphics: caught an exception while attempting to execute the FilePicker!");
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();
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
)
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?" );
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
);
879 case ID_OPEN_GRAPHICS
:
880 implInsertGraphics();
884 case ID_CLEAR_GRAPHICS
:
885 implClearGraphics( sal_True
);
893 //////////////////////////////////////////////////////////////////////
895 if (e
.ClickCount
== 2)
898 Reference
<XPropertySet
> xSet(getModel(), UNO_QUERY
);
902 // wenn Control nicht gebunden ist, kein Dialog (da die zu schickende URL hinterher sowieso
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))
916 sal_Bool bReadOnly
= false;
917 xSet
->getPropertyValue(PROPERTY_READONLY
) >>= bReadOnly
;
921 if ( implInsertGraphics() )
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 //.........................................................................
950 //.........................................................................