1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "imagemanagerimpl.hxx"
21 #include <xml/imagesconfiguration.hxx>
22 #include <uiconfiguration/imagetype.hxx>
23 #include <uiconfiguration/graphicnameaccess.hxx>
26 #include <properties.h>
28 #include <com/sun/star/frame/theUICommandDescription.hpp>
29 #include <com/sun/star/ui/UIElementType.hpp>
30 #include <com/sun/star/ui/ConfigurationEvent.hpp>
31 #include <com/sun/star/lang/DisposedException.hpp>
32 #include <com/sun/star/lang/IllegalAccessException.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/embed/ElementModes.hpp>
36 #include <com/sun/star/embed/InvalidStorageException.hpp>
37 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
38 #include <com/sun/star/io/IOException.hpp>
39 #include <com/sun/star/io/XStream.hpp>
40 #include <com/sun/star/ui/ImageType.hpp>
41 #include <vcl/graph.hxx>
42 #include <vcl/svapp.hxx>
43 #include <rtl/ustrbuf.hxx>
44 #include <o3tl/enumrange.hxx>
45 #include <osl/mutex.hxx>
46 #include <comphelper/sequence.hxx>
47 #include <tools/urlobj.hxx>
48 #include <unotools/ucbstreamhelper.hxx>
49 #include <vcl/pngread.hxx>
50 #include <vcl/pngwrite.hxx>
51 #include <rtl/instance.hxx>
52 #include <svtools/miscopt.hxx>
55 using ::com::sun::star::uno::Sequence
;
56 using ::com::sun::star::uno::XInterface
;
57 using ::com::sun::star::uno::RuntimeException
;
58 using ::com::sun::star::uno::UNO_QUERY
;
59 using ::com::sun::star::uno::Any
;
60 using ::com::sun::star::graphic::XGraphic
;
61 using namespace ::com::sun::star
;
62 using namespace ::com::sun::star::io
;
63 using namespace ::com::sun::star::embed
;
64 using namespace ::com::sun::star::lang
;
65 using namespace ::com::sun::star::container
;
66 using namespace ::com::sun::star::beans
;
67 using namespace ::com::sun::star::ui
;
68 using namespace ::cppu
;
70 const sal_Int16 MAX_IMAGETYPE_VALUE
= css::ui::ImageType::SIZE_32
;
72 static const char IMAGE_FOLDER
[] = "images";
73 static const char BITMAPS_FOLDER
[] = "Bitmaps";
75 static const o3tl::enumarray
<vcl::ImageType
, const char*> IMAGELIST_XML_FILE
=
82 static const o3tl::enumarray
<vcl::ImageType
, const char*> BITMAP_FILE_NAMES
=
92 static GlobalImageList
* pGlobalImageList
= nullptr;
96 class theGlobalImageListMutex
97 : public rtl::Static
<osl::Mutex
, theGlobalImageListMutex
> {};
100 static osl::Mutex
& getGlobalImageListMutex()
102 return theGlobalImageListMutex::get();
105 static GlobalImageList
* getGlobalImageList( const uno::Reference
< uno::XComponentContext
>& rxContext
)
107 osl::MutexGuard
guard( getGlobalImageListMutex() );
109 if ( pGlobalImageList
== nullptr )
110 pGlobalImageList
= new GlobalImageList( rxContext
);
112 return pGlobalImageList
;
115 CmdImageList::CmdImageList( const uno::Reference
< uno::XComponentContext
>& rxContext
, const OUString
& aModuleIdentifier
) :
116 m_bInitialized(false),
117 m_aModuleIdentifier( aModuleIdentifier
),
118 m_xContext( rxContext
)
122 CmdImageList::~CmdImageList()
126 void CmdImageList::initialize()
130 const OUString
aCommandImageList(UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDIMAGELIST
);
132 Sequence
<OUString
> aCommandImageSeq
;
133 uno::Reference
<XNameAccess
> xCommandDesc
= frame::theUICommandDescription::get(m_xContext
);
135 if (!m_aModuleIdentifier
.isEmpty())
137 // If we have a module identifier - use to retrieve the command image name list from it.
138 // Otherwise we will use the global command image list
141 xCommandDesc
->getByName(m_aModuleIdentifier
) >>= xCommandDesc
;
142 if (xCommandDesc
.is())
143 xCommandDesc
->getByName(aCommandImageList
) >>= aCommandImageSeq
;
145 catch (const NoSuchElementException
&)
147 // Module unknown we will work with an empty command image list!
152 if (xCommandDesc
.is())
156 xCommandDesc
->getByName(aCommandImageList
) >>= aCommandImageSeq
;
158 catch (const NoSuchElementException
&)
161 catch (const WrappedTargetException
&)
166 m_aResolver
.registerCommands(aCommandImageSeq
);
168 m_bInitialized
= true;
173 Image
CmdImageList::getImageFromCommandURL(vcl::ImageType nImageType
, const OUString
& rCommandURL
)
176 return m_aResolver
.getImageFromCommandURL(nImageType
, rCommandURL
);
179 bool CmdImageList::hasImage(vcl::ImageType
/*nImageType*/, const OUString
& rCommandURL
)
182 return m_aResolver
.hasImage(rCommandURL
);
185 std::vector
<OUString
>& CmdImageList::getImageCommandNames()
187 return m_aResolver
.getCommandNames();
190 GlobalImageList::GlobalImageList( const uno::Reference
< uno::XComponentContext
>& rxContext
) :
191 CmdImageList( rxContext
, OUString() )
195 GlobalImageList::~GlobalImageList()
197 osl::MutexGuard
guard( getGlobalImageListMutex() );
198 // remove global pointer as we destroy the object now
199 pGlobalImageList
= nullptr;
202 Image
GlobalImageList::getImageFromCommandURL( vcl::ImageType nImageType
, const OUString
& rCommandURL
)
204 osl::MutexGuard
guard( getGlobalImageListMutex() );
205 return CmdImageList::getImageFromCommandURL( nImageType
, rCommandURL
);
208 bool GlobalImageList::hasImage( vcl::ImageType nImageType
, const OUString
& rCommandURL
)
210 osl::MutexGuard
guard( getGlobalImageListMutex() );
211 return CmdImageList::hasImage( nImageType
, rCommandURL
);
214 ::std::vector
< OUString
>& GlobalImageList::getImageCommandNames()
216 osl::MutexGuard
guard( getGlobalImageListMutex() );
217 return CmdImageList::getImageCommandNames();
220 static bool implts_checkAndScaleGraphic( uno::Reference
< XGraphic
>& rOutGraphic
, const uno::Reference
< XGraphic
>& rInGraphic
, vcl::ImageType nImageType
)
222 static Size
aNormSize(16, 16);
223 static Size
aLargeSize(26, 26);
224 static Size
aSize32(32, 32);
226 if ( !rInGraphic
.is() )
228 rOutGraphic
= uno::Reference
<graphic::XGraphic
>();
232 // Check size and scale it
233 Graphic
aImage(rInGraphic
);
234 Size aSize
= aImage
.GetSizePixel();
235 bool bMustScale( false );
237 if (nImageType
== vcl::ImageType::Size26
)
238 bMustScale
= (aSize
!= aLargeSize
);
239 else if (nImageType
== vcl::ImageType::Size32
)
240 bMustScale
= (aSize
!= aSize32
);
242 bMustScale
= (aSize
!= aNormSize
);
246 BitmapEx aBitmap
= aImage
.GetBitmapEx();
247 aBitmap
.Scale( aNormSize
);
248 aImage
= Graphic(aBitmap
);
249 rOutGraphic
= aImage
.GetXGraphic();
252 rOutGraphic
= rInGraphic
;
257 static vcl::ImageType
implts_convertImageTypeToIndex( sal_Int16 nImageType
)
259 if (nImageType
& css::ui::ImageType::SIZE_LARGE
)
260 return vcl::ImageType::Size26
;
261 else if (nImageType
& css::ui::ImageType::SIZE_32
)
262 return vcl::ImageType::Size32
;
264 return vcl::ImageType::Size16
;
267 ImageList
* ImageManagerImpl::implts_getUserImageList( vcl::ImageType nImageType
)
270 if ( !m_pUserImageList
[nImageType
] )
271 implts_loadUserImages( nImageType
, m_xUserImageStorage
, m_xUserBitmapsStorage
);
273 return m_pUserImageList
[nImageType
].get();
276 void ImageManagerImpl::implts_initialize()
278 // Initialize the top-level structures with the storage data
279 if ( m_xUserConfigStorage
.is() )
281 long nModes
= m_bReadOnly
? ElementModes::READ
: ElementModes::READWRITE
;
285 m_xUserImageStorage
= m_xUserConfigStorage
->openStorageElement( IMAGE_FOLDER
,
287 if ( m_xUserImageStorage
.is() )
289 m_xUserBitmapsStorage
= m_xUserImageStorage
->openStorageElement( BITMAPS_FOLDER
,
293 catch ( const css::container::NoSuchElementException
& )
296 catch ( const css::embed::InvalidStorageException
& )
299 catch ( const css::lang::IllegalArgumentException
& )
302 catch ( const css::io::IOException
& )
305 catch ( const css::embed::StorageWrappedTargetException
& )
311 void ImageManagerImpl::implts_loadUserImages(
312 vcl::ImageType nImageType
,
313 const uno::Reference
< XStorage
>& xUserImageStorage
,
314 const uno::Reference
< XStorage
>& xUserBitmapsStorage
)
318 if ( xUserImageStorage
.is() && xUserBitmapsStorage
.is() )
322 uno::Reference
< XStream
> xStream
= xUserImageStorage
->openStreamElement( OUString::createFromAscii( IMAGELIST_XML_FILE
[nImageType
] ),
323 ElementModes::READ
);
324 uno::Reference
< XInputStream
> xInputStream
= xStream
->getInputStream();
326 ImageItemDescriptorList aUserImageListInfo
;
327 ImagesConfiguration::LoadImages( m_xContext
,
329 aUserImageListInfo
);
330 if ( !aUserImageListInfo
.empty() )
332 sal_Int32 nCount
= aUserImageListInfo
.size();
333 std::vector
< OUString
> aUserImagesVector
;
334 aUserImagesVector
.reserve(nCount
);
335 for ( sal_Int32 i
=0; i
< nCount
; i
++ )
337 const ImageItemDescriptor
& rItem
= aUserImageListInfo
[i
];
338 aUserImagesVector
.push_back( rItem
.aCommandURL
);
341 uno::Reference
< XStream
> xBitmapStream
= xUserBitmapsStorage
->openStreamElement(
342 OUString::createFromAscii( BITMAP_FILE_NAMES
[nImageType
] ),
343 ElementModes::READ
);
345 if ( xBitmapStream
.is() )
347 BitmapEx aUserBitmap
;
349 std::unique_ptr
<SvStream
> pSvStream(utl::UcbStreamHelper::CreateStream( xBitmapStream
));
350 vcl::PNGReader
aPngReader( *pSvStream
);
351 aUserBitmap
= aPngReader
.Read();
354 // Delete old image list and create a new one from the read bitmap
355 m_pUserImageList
[nImageType
].reset(new ImageList());
356 m_pUserImageList
[nImageType
]->InsertFromHorizontalStrip
357 ( aUserBitmap
, aUserImagesVector
);
362 catch ( const css::container::NoSuchElementException
& )
365 catch ( const css::embed::InvalidStorageException
& )
368 catch ( const css::lang::IllegalArgumentException
& )
371 catch ( const css::io::IOException
& )
374 catch ( const css::embed::StorageWrappedTargetException
& )
379 // Destroy old image list - create a new empty one
380 m_pUserImageList
[nImageType
].reset(new ImageList
);
383 bool ImageManagerImpl::implts_storeUserImages(
384 vcl::ImageType nImageType
,
385 const uno::Reference
< XStorage
>& xUserImageStorage
,
386 const uno::Reference
< XStorage
>& xUserBitmapsStorage
)
392 ImageList
* pImageList
= implts_getUserImageList( nImageType
);
393 if ( pImageList
->GetImageCount() > 0 )
395 ImageItemDescriptorList aUserImageListInfo
;
397 for ( sal_uInt16 i
=0; i
< pImageList
->GetImageCount(); i
++ )
399 ImageItemDescriptor aItem
;
400 aItem
.aCommandURL
= pImageList
->GetImageName( i
);
401 aUserImageListInfo
.push_back( aItem
);
404 uno::Reference
< XTransactedObject
> xTransaction
;
405 uno::Reference
< XOutputStream
> xOutputStream
;
406 uno::Reference
< XStream
> xStream
= xUserImageStorage
->openStreamElement( OUString::createFromAscii( IMAGELIST_XML_FILE
[nImageType
] ),
407 ElementModes::WRITE
|ElementModes::TRUNCATE
);
410 uno::Reference
< XStream
> xBitmapStream
=
411 xUserBitmapsStorage
->openStreamElement( OUString::createFromAscii( BITMAP_FILE_NAMES
[nImageType
] ),
412 ElementModes::WRITE
|ElementModes::TRUNCATE
);
413 if ( xBitmapStream
.is() )
416 std::unique_ptr
<SvStream
> pSvStream(utl::UcbStreamHelper::CreateStream( xBitmapStream
));
417 vcl::PNGWriter
aPngWriter( pImageList
->GetAsHorizontalStrip() );
418 aPngWriter
.Write( *pSvStream
);
421 // Commit user bitmaps storage
422 xTransaction
.set( xUserBitmapsStorage
, UNO_QUERY
);
423 if ( xTransaction
.is() )
424 xTransaction
->commit();
427 xOutputStream
= xStream
->getOutputStream();
428 if ( xOutputStream
.is() )
429 ImagesConfiguration::StoreImages( m_xContext
, xOutputStream
, aUserImageListInfo
);
431 // Commit user image storage
432 xTransaction
.set( xUserImageStorage
, UNO_QUERY
);
433 if ( xTransaction
.is() )
434 xTransaction
->commit();
441 // Remove the streams from the storage, if we have no data. We have to catch
442 // the NoSuchElementException as it can be possible that there is no stream at all!
445 xUserImageStorage
->removeElement( OUString::createFromAscii( IMAGELIST_XML_FILE
[nImageType
] ));
447 catch ( const css::container::NoSuchElementException
& )
453 xUserBitmapsStorage
->removeElement( OUString::createFromAscii( BITMAP_FILE_NAMES
[nImageType
] ));
455 catch ( const css::container::NoSuchElementException
& )
459 uno::Reference
< XTransactedObject
> xTransaction
;
461 // Commit user image storage
462 xTransaction
.set( xUserImageStorage
, UNO_QUERY
);
463 if ( xTransaction
.is() )
464 xTransaction
->commit();
466 // Commit user bitmaps storage
467 xTransaction
.set( xUserBitmapsStorage
, UNO_QUERY
);
468 if ( xTransaction
.is() )
469 xTransaction
->commit();
478 const rtl::Reference
< GlobalImageList
>& ImageManagerImpl::implts_getGlobalImageList()
482 if ( !m_pGlobalImageList
.is() )
483 m_pGlobalImageList
= getGlobalImageList( m_xContext
);
484 return m_pGlobalImageList
;
487 CmdImageList
* ImageManagerImpl::implts_getDefaultImageList()
491 if ( !m_pDefaultImageList
)
492 m_pDefaultImageList
.reset(new CmdImageList( m_xContext
, m_aModuleIdentifier
));
494 return m_pDefaultImageList
.get();
497 ImageManagerImpl::ImageManagerImpl( const uno::Reference
< uno::XComponentContext
>& rxContext
,::cppu::OWeakObject
* pOwner
,bool _bUseGlobal
) :
498 m_xContext( rxContext
)
500 , m_aResourceString( "private:resource/images/moduleimages" )
501 , m_aListenerContainer( m_mutex
)
502 , m_bUseGlobal(_bUseGlobal
)
503 , m_bReadOnly( true )
504 , m_bInitialized( false )
505 , m_bModified( false )
506 , m_bDisposed( false )
508 for ( vcl::ImageType n
: o3tl::enumrange
<vcl::ImageType
>() )
510 m_pUserImageList
[n
] = nullptr;
511 m_bUserImageListModified
[n
] = false;
515 ImageManagerImpl::~ImageManagerImpl()
520 void ImageManagerImpl::dispose()
522 uno::Reference
< uno::XInterface
> xOwner(m_pOwner
);
523 css::lang::EventObject
aEvent( xOwner
);
524 m_aListenerContainer
.disposeAndClear( aEvent
);
528 m_xUserConfigStorage
.clear();
529 m_xUserImageStorage
.clear();
530 m_xUserRootCommit
.clear();
534 // delete user and default image list on dispose
535 for (auto& n
: m_pUserImageList
)
539 m_pDefaultImageList
.reset();
543 void ImageManagerImpl::addEventListener( const uno::Reference
< XEventListener
>& xListener
)
548 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
550 throw DisposedException();
553 m_aListenerContainer
.addInterface( cppu::UnoType
<XEventListener
>::get(), xListener
);
556 void ImageManagerImpl::removeEventListener( const uno::Reference
< XEventListener
>& xListener
)
558 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
559 m_aListenerContainer
.removeInterface( cppu::UnoType
<XEventListener
>::get(), xListener
);
563 void ImageManagerImpl::initialize( const Sequence
< Any
>& aArguments
)
567 if ( !m_bInitialized
)
569 for ( sal_Int32 n
= 0; n
< aArguments
.getLength(); n
++ )
571 PropertyValue aPropValue
;
572 if ( aArguments
[n
] >>= aPropValue
)
574 if ( aPropValue
.Name
== "UserConfigStorage" )
576 aPropValue
.Value
>>= m_xUserConfigStorage
;
578 else if ( aPropValue
.Name
== "ModuleIdentifier" )
580 aPropValue
.Value
>>= m_aModuleIdentifier
;
582 else if ( aPropValue
.Name
== "UserRootCommit" )
584 aPropValue
.Value
>>= m_xUserRootCommit
;
589 if ( m_xUserConfigStorage
.is() )
591 uno::Reference
< XPropertySet
> xPropSet( m_xUserConfigStorage
, UNO_QUERY
);
595 if ( xPropSet
->getPropertyValue("OpenMode") >>= nOpenMode
)
596 m_bReadOnly
= !( nOpenMode
& ElementModes::WRITE
);
602 m_bInitialized
= true;
607 void ImageManagerImpl::reset()
611 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
613 throw DisposedException();
615 std::vector
< OUString
> aUserImageNames
;
617 for ( vcl::ImageType i
: o3tl::enumrange
<vcl::ImageType
>() )
619 aUserImageNames
.clear();
620 ImageList
* pImageList
= implts_getUserImageList(i
);
621 pImageList
->GetImageNames( aUserImageNames
);
623 Sequence
< OUString
> aRemoveList( comphelper::containerToSequence(aUserImageNames
) );
626 removeImages( sal_Int16( i
), aRemoveList
);
627 m_bUserImageListModified
[i
] = true;
633 Sequence
< OUString
> ImageManagerImpl::getAllImageNames( ::sal_Int16 nImageType
)
637 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
639 throw DisposedException();
641 ImageNameMap aImageCmdNameMap
;
643 vcl::ImageType nIndex
= implts_convertImageTypeToIndex( nImageType
);
648 rtl::Reference
< GlobalImageList
> rGlobalImageList
= implts_getGlobalImageList();
650 const std::vector
< OUString
>& rGlobalImageNameVector
= rGlobalImageList
->getImageCommandNames();
651 const sal_uInt32 nGlobalCount
= rGlobalImageNameVector
.size();
652 for ( i
= 0; i
< nGlobalCount
; i
++ )
653 aImageCmdNameMap
.emplace( rGlobalImageNameVector
[i
], true );
655 const std::vector
< OUString
>& rModuleImageNameVector
= implts_getDefaultImageList()->getImageCommandNames();
656 const sal_uInt32 nModuleCount
= rModuleImageNameVector
.size();
657 for ( i
= 0; i
< nModuleCount
; i
++ )
658 aImageCmdNameMap
.emplace( rModuleImageNameVector
[i
], true );
661 ImageList
* pImageList
= implts_getUserImageList(nIndex
);
662 std::vector
< OUString
> rUserImageNames
;
663 pImageList
->GetImageNames( rUserImageNames
);
664 const sal_uInt32 nUserCount
= rUserImageNames
.size();
665 for ( i
= 0; i
< nUserCount
; i
++ )
666 aImageCmdNameMap
.emplace( rUserImageNames
[i
], true );
668 return comphelper::mapKeysToSequence( aImageCmdNameMap
);
671 bool ImageManagerImpl::hasImage( ::sal_Int16 nImageType
, const OUString
& aCommandURL
)
675 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
677 throw DisposedException();
679 if (( nImageType
< 0 ) || ( nImageType
> MAX_IMAGETYPE_VALUE
))
680 throw IllegalArgumentException();
682 vcl::ImageType nIndex
= implts_convertImageTypeToIndex( nImageType
);
683 if ( m_bUseGlobal
&& implts_getGlobalImageList()->hasImage( nIndex
, aCommandURL
))
687 if ( m_bUseGlobal
&& implts_getDefaultImageList()->hasImage( nIndex
, aCommandURL
))
692 ImageList
* pImageList
= implts_getUserImageList(nIndex
);
694 return ( pImageList
->GetImagePos( aCommandURL
) != IMAGELIST_IMAGE_NOTFOUND
);
703 css::uno::Reference
< css::graphic::XGraphic
> GetXGraphic(const Image
&rImage
)
705 return Graphic(rImage
).GetXGraphic();
709 Sequence
< uno::Reference
< XGraphic
> > ImageManagerImpl::getImages(
710 ::sal_Int16 nImageType
,
711 const Sequence
< OUString
>& aCommandURLSequence
)
715 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
717 throw DisposedException();
719 if (( nImageType
< 0 ) || ( nImageType
> MAX_IMAGETYPE_VALUE
))
720 throw IllegalArgumentException();
722 Sequence
< uno::Reference
< XGraphic
> > aGraphSeq( aCommandURLSequence
.getLength() );
724 const OUString
* aStrArray
= aCommandURLSequence
.getConstArray();
726 vcl::ImageType nIndex
= implts_convertImageTypeToIndex( nImageType
);
727 rtl::Reference
< GlobalImageList
> rGlobalImageList
;
728 CmdImageList
* pDefaultImageList
= nullptr;
731 rGlobalImageList
= implts_getGlobalImageList();
732 pDefaultImageList
= implts_getDefaultImageList();
734 ImageList
* pUserImageList
= implts_getUserImageList(nIndex
);
736 // We have to search our image list in the following order:
737 // 1. user image list (read/write)
738 // 2. module image list (read)
739 // 3. global image list (read)
740 for ( sal_Int32 n
= 0; n
< aCommandURLSequence
.getLength(); n
++ )
742 Image aImage
= pUserImageList
->GetImage( aStrArray
[n
] );
743 if ( !aImage
&& m_bUseGlobal
)
745 aImage
= pDefaultImageList
->getImageFromCommandURL( nIndex
, aStrArray
[n
] );
747 aImage
= rGlobalImageList
->getImageFromCommandURL( nIndex
, aStrArray
[n
] );
750 aGraphSeq
[n
] = GetXGraphic(aImage
);
756 void ImageManagerImpl::replaceImages(
757 ::sal_Int16 nImageType
,
758 const Sequence
< OUString
>& aCommandURLSequence
,
759 const Sequence
< uno::Reference
< XGraphic
> >& aGraphicsSequence
)
761 GraphicNameAccess
* pInsertedImages( nullptr );
762 GraphicNameAccess
* pReplacedImages( nullptr );
767 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
769 throw DisposedException();
771 if (( aCommandURLSequence
.getLength() != aGraphicsSequence
.getLength() ) ||
772 (( nImageType
< 0 ) || ( nImageType
> MAX_IMAGETYPE_VALUE
)))
773 throw IllegalArgumentException();
776 throw IllegalAccessException();
778 vcl::ImageType nIndex
= implts_convertImageTypeToIndex( nImageType
);
779 ImageList
* pImageList
= implts_getUserImageList(nIndex
);
781 uno::Reference
< XGraphic
> xGraphic
;
782 for ( sal_Int32 i
= 0; i
< aCommandURLSequence
.getLength(); i
++ )
784 // Check size and scale. If we don't have any graphics ignore it
785 if ( !implts_checkAndScaleGraphic( xGraphic
, aGraphicsSequence
[i
], nIndex
))
788 sal_uInt16 nPos
= pImageList
->GetImagePos( aCommandURLSequence
[i
] );
789 if ( nPos
== IMAGELIST_IMAGE_NOTFOUND
)
791 pImageList
->AddImage(aCommandURLSequence
[i
], Image(xGraphic
));
792 if ( !pInsertedImages
)
793 pInsertedImages
= new GraphicNameAccess();
794 pInsertedImages
->addElement( aCommandURLSequence
[i
], xGraphic
);
798 pImageList
->ReplaceImage(aCommandURLSequence
[i
], Image(xGraphic
));
799 if ( !pReplacedImages
)
800 pReplacedImages
= new GraphicNameAccess();
801 pReplacedImages
->addElement( aCommandURLSequence
[i
], xGraphic
);
805 if (( pInsertedImages
!= nullptr ) || ( pReplacedImages
!= nullptr ))
808 m_bUserImageListModified
[nIndex
] = true;
812 uno::Reference
< uno::XInterface
> xOwner(m_pOwner
);
814 if ( pInsertedImages
!= nullptr )
816 ConfigurationEvent aInsertEvent
;
817 aInsertEvent
.aInfo
<<= nImageType
;
818 aInsertEvent
.Accessor
<<= xOwner
;
819 aInsertEvent
.Source
= xOwner
;
820 aInsertEvent
.ResourceURL
= m_aResourceString
;
821 aInsertEvent
.Element
<<= uno::Reference
< XNameAccess
>(
822 static_cast< OWeakObject
*>( pInsertedImages
), UNO_QUERY
);
823 implts_notifyContainerListener( aInsertEvent
, NotifyOp_Insert
);
825 if ( pReplacedImages
!= nullptr )
827 ConfigurationEvent aReplaceEvent
;
828 aReplaceEvent
.aInfo
<<= nImageType
;
829 aReplaceEvent
.Accessor
<<= xOwner
;
830 aReplaceEvent
.Source
= xOwner
;
831 aReplaceEvent
.ResourceURL
= m_aResourceString
;
832 aReplaceEvent
.ReplacedElement
= Any();
833 aReplaceEvent
.Element
<<= uno::Reference
< XNameAccess
>(
834 static_cast< OWeakObject
*>( pReplacedImages
), UNO_QUERY
);
835 implts_notifyContainerListener( aReplaceEvent
, NotifyOp_Replace
);
839 void ImageManagerImpl::removeImages( ::sal_Int16 nImageType
, const Sequence
< OUString
>& aCommandURLSequence
)
841 GraphicNameAccess
* pRemovedImages( nullptr );
842 GraphicNameAccess
* pReplacedImages( nullptr );
847 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
849 throw DisposedException();
851 if (( nImageType
< 0 ) || ( nImageType
> MAX_IMAGETYPE_VALUE
))
852 throw IllegalArgumentException();
855 throw IllegalAccessException();
857 vcl::ImageType nIndex
= implts_convertImageTypeToIndex( nImageType
);
858 rtl::Reference
< GlobalImageList
> rGlobalImageList
;
859 CmdImageList
* pDefaultImageList
= nullptr;
862 rGlobalImageList
= implts_getGlobalImageList();
863 pDefaultImageList
= implts_getDefaultImageList();
865 ImageList
* pImageList
= implts_getUserImageList(nIndex
);
866 uno::Reference
<XGraphic
> xEmptyGraphic
;
868 for ( sal_Int32 i
= 0; i
< aCommandURLSequence
.getLength(); i
++ )
870 sal_uInt16 nPos
= pImageList
->GetImagePos( aCommandURLSequence
[i
] );
871 if ( nPos
!= IMAGELIST_IMAGE_NOTFOUND
)
873 sal_uInt16 nId
= pImageList
->GetImageId( nPos
);
874 pImageList
->RemoveImage( nId
);
878 // Check, if we have an image in our module/global image list. If we find one =>
879 // this is a replace instead of a remove operation!
880 Image aNewImage
= pDefaultImageList
->getImageFromCommandURL( nIndex
, aCommandURLSequence
[i
] );
882 aNewImage
= rGlobalImageList
->getImageFromCommandURL( nIndex
, aCommandURLSequence
[i
] );
885 if ( !pRemovedImages
)
886 pRemovedImages
= new GraphicNameAccess();
887 pRemovedImages
->addElement( aCommandURLSequence
[i
], xEmptyGraphic
);
891 if ( !pReplacedImages
)
892 pReplacedImages
= new GraphicNameAccess();
893 pReplacedImages
->addElement(aCommandURLSequence
[i
], GetXGraphic(aNewImage
));
895 } // if ( m_bUseGlobal )
898 if ( !pRemovedImages
)
899 pRemovedImages
= new GraphicNameAccess();
900 pRemovedImages
->addElement( aCommandURLSequence
[i
], xEmptyGraphic
);
905 if (( pReplacedImages
!= nullptr ) || ( pRemovedImages
!= nullptr ))
908 m_bUserImageListModified
[nIndex
] = true;
913 uno::Reference
< uno::XInterface
> xOwner(m_pOwner
);
914 if ( pRemovedImages
!= nullptr )
916 ConfigurationEvent aRemoveEvent
;
917 aRemoveEvent
.aInfo
<<= nImageType
;
918 aRemoveEvent
.Accessor
<<= xOwner
;
919 aRemoveEvent
.Source
= xOwner
;
920 aRemoveEvent
.ResourceURL
= m_aResourceString
;
921 aRemoveEvent
.Element
<<= uno::Reference
< XNameAccess
>(
922 static_cast< OWeakObject
*>( pRemovedImages
), UNO_QUERY
);
923 implts_notifyContainerListener( aRemoveEvent
, NotifyOp_Remove
);
925 if ( pReplacedImages
!= nullptr )
927 ConfigurationEvent aReplaceEvent
;
928 aReplaceEvent
.aInfo
<<= nImageType
;
929 aReplaceEvent
.Accessor
<<= xOwner
;
930 aReplaceEvent
.Source
= xOwner
;
931 aReplaceEvent
.ResourceURL
= m_aResourceString
;
932 aReplaceEvent
.ReplacedElement
= Any();
933 aReplaceEvent
.Element
<<= uno::Reference
< XNameAccess
>(
934 static_cast< OWeakObject
*>( pReplacedImages
), UNO_QUERY
);
935 implts_notifyContainerListener( aReplaceEvent
, NotifyOp_Replace
);
939 void ImageManagerImpl::insertImages( ::sal_Int16 nImageType
, const Sequence
< OUString
>& aCommandURLSequence
, const Sequence
< uno::Reference
< XGraphic
> >& aGraphicSequence
)
941 replaceImages(nImageType
,aCommandURLSequence
,aGraphicSequence
);
944 // XUIConfigurationPersistence
945 void ImageManagerImpl::reload()
947 SolarMutexClearableGuard aGuard
;
950 throw DisposedException();
952 CommandMap aOldUserCmdImageSet
;
953 std::vector
< OUString
> aNewUserCmdImageSet
;
957 for ( vcl::ImageType i
: o3tl::enumrange
<vcl::ImageType
>() )
959 if ( !m_bDisposed
&& m_bUserImageListModified
[i
] )
961 std::vector
< OUString
> aOldUserCmdImageVector
;
962 ImageList
* pImageList
= implts_getUserImageList(i
);
963 pImageList
->GetImageNames( aOldUserCmdImageVector
);
965 // Fill hash map to speed up search afterwards
967 const sal_uInt32 nOldCount
= aOldUserCmdImageVector
.size();
968 for ( j
= 0; j
< nOldCount
; j
++ )
969 aOldUserCmdImageSet
.emplace( aOldUserCmdImageVector
[j
], false );
971 // Attention: This can make the old image list pointer invalid!
972 implts_loadUserImages( i
, m_xUserImageStorage
, m_xUserBitmapsStorage
);
973 pImageList
= implts_getUserImageList(i
);
974 pImageList
->GetImageNames( aNewUserCmdImageSet
);
976 GraphicNameAccess
* pInsertedImages( nullptr );
977 GraphicNameAccess
* pReplacedImages( nullptr );
978 GraphicNameAccess
* pRemovedImages( nullptr );
980 for (auto const& newUserCmdImage
: aNewUserCmdImageSet
)
982 CommandMap::iterator pIter
= aOldUserCmdImageSet
.find(newUserCmdImage
);
983 if ( pIter
!= aOldUserCmdImageSet
.end() )
985 pIter
->second
= true; // mark entry as replaced
986 if ( !pReplacedImages
)
987 pReplacedImages
= new GraphicNameAccess();
988 pReplacedImages
->addElement( newUserCmdImage
,
989 GetXGraphic(pImageList
->GetImage(newUserCmdImage
)) );
993 if ( !pInsertedImages
)
994 pInsertedImages
= new GraphicNameAccess();
995 pInsertedImages
->addElement( newUserCmdImage
,
996 GetXGraphic(pImageList
->GetImage(newUserCmdImage
)) );
1000 // Search map for unmarked entries => they have been removed from the user list
1001 // through this reload operation.
1002 // We have to search the module and global image list!
1003 rtl::Reference
< GlobalImageList
> rGlobalImageList
;
1004 CmdImageList
* pDefaultImageList
= nullptr;
1007 rGlobalImageList
= implts_getGlobalImageList();
1008 pDefaultImageList
= implts_getDefaultImageList();
1010 uno::Reference
<XGraphic
> xEmptyGraphic
;
1011 for (auto const& oldUserCmdImage
: aOldUserCmdImageSet
)
1013 if ( !oldUserCmdImage
.second
)
1017 Image aImage
= pDefaultImageList
->getImageFromCommandURL( i
, oldUserCmdImage
.first
);
1019 aImage
= rGlobalImageList
->getImageFromCommandURL( i
, oldUserCmdImage
.first
);
1023 // No image in the module/global image list => remove user image
1024 if ( !pRemovedImages
)
1025 pRemovedImages
= new GraphicNameAccess();
1026 pRemovedImages
->addElement( oldUserCmdImage
.first
, xEmptyGraphic
);
1030 // Image has been found in the module/global image list => replace user image
1031 if ( !pReplacedImages
)
1032 pReplacedImages
= new GraphicNameAccess();
1033 pReplacedImages
->addElement(oldUserCmdImage
.first
, GetXGraphic(aImage
));
1035 } // if ( m_bUseGlobal )
1038 // No image in the user image list => remove user image
1039 if ( !pRemovedImages
)
1040 pRemovedImages
= new GraphicNameAccess();
1041 pRemovedImages
->addElement( oldUserCmdImage
.first
, xEmptyGraphic
);
1048 // Now notify our listeners. Unlock mutex to prevent deadlocks
1049 uno::Reference
< uno::XInterface
> xOwner(m_pOwner
);
1050 if ( pInsertedImages
!= nullptr )
1052 ConfigurationEvent aInsertEvent
;
1053 aInsertEvent
.aInfo
<<=static_cast<sal_uInt16
>(i
);
1054 aInsertEvent
.Accessor
<<= xOwner
;
1055 aInsertEvent
.Source
= xOwner
;
1056 aInsertEvent
.ResourceURL
= m_aResourceString
;
1057 aInsertEvent
.Element
<<= uno::Reference
< XNameAccess
>(
1058 static_cast< OWeakObject
*>( pInsertedImages
), UNO_QUERY
);
1059 implts_notifyContainerListener( aInsertEvent
, NotifyOp_Insert
);
1061 if ( pReplacedImages
!= nullptr )
1063 ConfigurationEvent aReplaceEvent
;
1064 aReplaceEvent
.aInfo
<<= static_cast<sal_uInt16
>(i
);
1065 aReplaceEvent
.Accessor
<<= xOwner
;
1066 aReplaceEvent
.Source
= xOwner
;
1067 aReplaceEvent
.ResourceURL
= m_aResourceString
;
1068 aReplaceEvent
.ReplacedElement
= Any();
1069 aReplaceEvent
.Element
<<= uno::Reference
< XNameAccess
>(
1070 static_cast< OWeakObject
*>( pReplacedImages
), UNO_QUERY
);
1071 implts_notifyContainerListener( aReplaceEvent
, NotifyOp_Replace
);
1073 if ( pRemovedImages
!= nullptr )
1075 ConfigurationEvent aRemoveEvent
;
1076 aRemoveEvent
.aInfo
<<= static_cast<sal_uInt16
>(i
);
1077 aRemoveEvent
.Accessor
<<= xOwner
;
1078 aRemoveEvent
.Source
= xOwner
;
1079 aRemoveEvent
.ResourceURL
= m_aResourceString
;
1080 aRemoveEvent
.Element
<<= uno::Reference
< XNameAccess
>(
1081 static_cast< OWeakObject
*>( pRemovedImages
), UNO_QUERY
);
1082 implts_notifyContainerListener( aRemoveEvent
, NotifyOp_Remove
);
1091 void ImageManagerImpl::store()
1096 throw DisposedException();
1100 bool bWritten( false );
1101 for ( vcl::ImageType i
: o3tl::enumrange
<vcl::ImageType
>() )
1103 bool bSuccess
= implts_storeUserImages(i
, m_xUserImageStorage
, m_xUserBitmapsStorage
);
1106 m_bUserImageListModified
[i
] = false;
1110 m_xUserConfigStorage
.is() )
1112 uno::Reference
< XTransactedObject
> xUserConfigStorageCommit( m_xUserConfigStorage
, UNO_QUERY
);
1113 if ( xUserConfigStorageCommit
.is() )
1114 xUserConfigStorageCommit
->commit();
1115 if ( m_xUserRootCommit
.is() )
1116 m_xUserRootCommit
->commit();
1119 m_bModified
= false;
1123 void ImageManagerImpl::storeToStorage( const uno::Reference
< XStorage
>& Storage
)
1128 throw DisposedException();
1130 if ( m_bModified
&& Storage
.is() )
1132 long nModes
= ElementModes::READWRITE
;
1134 uno::Reference
< XStorage
> xUserImageStorage
= Storage
->openStorageElement( IMAGE_FOLDER
,
1136 if ( xUserImageStorage
.is() )
1138 uno::Reference
< XStorage
> xUserBitmapsStorage
= xUserImageStorage
->openStorageElement( BITMAPS_FOLDER
,
1140 for ( vcl::ImageType i
: o3tl::enumrange
<vcl::ImageType
>() )
1142 implts_getUserImageList(i
);
1143 implts_storeUserImages( i
, xUserImageStorage
, xUserBitmapsStorage
);
1146 uno::Reference
< XTransactedObject
> xTransaction( Storage
, UNO_QUERY
);
1147 if ( xTransaction
.is() )
1148 xTransaction
->commit();
1153 bool ImageManagerImpl::isModified() const
1159 bool ImageManagerImpl::isReadOnly() const
1165 void ImageManagerImpl::addConfigurationListener( const uno::Reference
< css::ui::XUIConfigurationListener
>& xListener
)
1170 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1172 throw DisposedException();
1175 m_aListenerContainer
.addInterface( cppu::UnoType
<XUIConfigurationListener
>::get(), xListener
);
1178 void ImageManagerImpl::removeConfigurationListener( const uno::Reference
< css::ui::XUIConfigurationListener
>& xListener
)
1180 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1181 m_aListenerContainer
.removeInterface( cppu::UnoType
<XUIConfigurationListener
>::get(), xListener
);
1184 void ImageManagerImpl::implts_notifyContainerListener( const ConfigurationEvent
& aEvent
, NotifyOp eOp
)
1186 ::cppu::OInterfaceContainerHelper
* pContainer
= m_aListenerContainer
.getContainer(
1187 cppu::UnoType
<css::ui::XUIConfigurationListener
>::get());
1188 if ( pContainer
!= nullptr )
1190 ::cppu::OInterfaceIteratorHelper
pIterator( *pContainer
);
1191 while ( pIterator
.hasMoreElements() )
1197 case NotifyOp_Replace
:
1198 static_cast< css::ui::XUIConfigurationListener
*>(pIterator
.next())->elementReplaced( aEvent
);
1200 case NotifyOp_Insert
:
1201 static_cast< css::ui::XUIConfigurationListener
*>(pIterator
.next())->elementInserted( aEvent
);
1203 case NotifyOp_Remove
:
1204 static_cast< css::ui::XUIConfigurationListener
*>(pIterator
.next())->elementRemoved( aEvent
);
1208 catch( const css::uno::RuntimeException
& )
1215 void ImageManagerImpl::clear()
1219 for (auto & n
: m_pUserImageList
)
1224 } // namespace framework
1226 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */