1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26
27 //_________________________________________________________________________________________________________________
28 // my own includes
29 //_________________________________________________________________________________________________________________
30
31 #ifndef __FRAMEWORK_UICONFIGURATION_UICATEGORYDESCRPTION_HXX_
32 #include "uiconfiguration/uicategorydescription.hxx"
33 #endif
34 #include <threadhelp/resetableguard.hxx>
35 #include "services.h"
36
37 #include "properties.h"
38
39 //_________________________________________________________________________________________________________________
40 // interface includes
41 //_________________________________________________________________________________________________________________
42 #include <com/sun/star/beans/PropertyValue.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/container/XNameAccess.hpp>
45 #include <com/sun/star/container/XNameContainer.hpp>
46 #include <com/sun/star/container/XContainer.hpp>
47
48 //_________________________________________________________________________________________________________________
49 // includes of other projects
50 //_________________________________________________________________________________________________________________
51 #include <rtl/ustrbuf.hxx>
52 #include <cppuhelper/implbase2.hxx>
53 #include <unotools/configmgr.hxx>
54 #include <tools/string.hxx>
55
56 #ifndef _VCL_MNEMONIC_HXX_
57 #include <vcl/mnemonic.hxx>
58 #endif
59 #include <comphelper/sequence.hxx>
60 #include <rtl/logfile.hxx>
61
62 //_________________________________________________________________________________________________________________
63 // Defines
64 //_________________________________________________________________________________________________________________
65 //
66
67 using namespace com::sun::star::uno;
68 using namespace com::sun::star::lang;
69 using namespace com::sun::star::beans;
70 using namespace com::sun::star::container;
71 using namespace ::com::sun::star::frame;
72
73 //_________________________________________________________________________________________________________________
74 // Namespace
75 //_________________________________________________________________________________________________________________
76 //
77
78 struct ModuleToCategory
79 {
80 const char* pModuleId;
81 const char* pCommands;
82 };
83
84 static const char CATEGORY[] = "Category";
85 static const char GENERIC_MODULE_NAME[] = "generic";
86 static const char CONFIGURATION_ROOT_ACCESS[] = "/org.openoffice.Office.UI.";
87 static const char CONFIGURATION_CATEGORY_ELEMENT_ACCESS[] = "/Commands/Categories";
88 static const char CONFIGURATION_PROPERTY_NAME[] = "Name";
89
90 namespace framework
91 {
92
93 //*****************************************************************************************************************
94 // Configuration access class for PopupMenuControllerFactory implementation
95 //*****************************************************************************************************************
96
97 class ConfigurationAccess_UICategory : // Order is necessary for right initialization!
98 private ThreadHelpBase ,
99 public ::cppu::WeakImplHelper2<XNameAccess,XContainerListener>
100 {
101 public:
102 ConfigurationAccess_UICategory( const ::rtl::OUString& aModuleName, const Reference< XNameAccess >& xGenericUICommands, const Reference< XMultiServiceFactory >& rServiceManager );
103 virtual ~ConfigurationAccess_UICategory();
104
105 // XNameAccess
106 virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
107 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
108
109 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames()
110 throw (::com::sun::star::uno::RuntimeException);
111
112 virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
113 throw (::com::sun::star::uno::RuntimeException);
114
115 // XElementAccess
116 virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
117 throw (::com::sun::star::uno::RuntimeException);
118
119 virtual sal_Bool SAL_CALL hasElements()
120 throw (::com::sun::star::uno::RuntimeException);
121
122 // container.XContainerListener
123 virtual void SAL_CALL elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException);
124 virtual void SAL_CALL elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException);
125 virtual void SAL_CALL elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException);
126
127 // lang.XEventListener
128 virtual void SAL_CALL disposing( const EventObject& aEvent ) throw(RuntimeException);
129
130 protected:
131 Any getUINameFromID( const rtl::OUString& rId );
132 Any getUINameFromCache( const rtl::OUString& rId );
133 Sequence< rtl::OUString > getAllIds();
134 sal_Bool fillCache();
135
136 private:
137 typedef ::std::hash_map< ::rtl::OUString,
138 ::rtl::OUString,
139 rtl::OUStringHash,
140 ::std::equal_to< ::rtl::OUString > > IdToInfoCache;
141
142 sal_Bool initializeConfigAccess();
143
144 rtl::OUString m_aConfigCategoryAccess;
145 rtl::OUString m_aPropUIName;
146 Reference< XNameAccess > m_xGenericUICategories;
147 Reference< XMultiServiceFactory > m_xServiceManager;
148 Reference< XMultiServiceFactory > m_xConfigProvider;
149 Reference< XNameAccess > m_xConfigAccess;
150 sal_Bool m_bConfigAccessInitialized;
151 sal_Bool m_bCacheFilled;
152 IdToInfoCache m_aIdCache;
153 };
154
155 //*****************************************************************************************************************
156 // XInterface, XTypeProvider
157 //*****************************************************************************************************************
158
ConfigurationAccess_UICategory(const rtl::OUString & aModuleName,const Reference<XNameAccess> & rGenericUICategories,const Reference<XMultiServiceFactory> & rServiceManager)159 ConfigurationAccess_UICategory::ConfigurationAccess_UICategory( const rtl::OUString& aModuleName, const Reference< XNameAccess >& rGenericUICategories, const Reference< XMultiServiceFactory >& rServiceManager ) :
160 ThreadHelpBase(),
161 m_aConfigCategoryAccess( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_ROOT_ACCESS )),
162 m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_PROPERTY_NAME )),
163 m_xGenericUICategories( rGenericUICategories ),
164 m_xServiceManager( rServiceManager ),
165 m_bConfigAccessInitialized( sal_False ),
166 m_bCacheFilled( sal_False )
167 {
168 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::ConfigurationAccess_UICategory" );
169 // Create configuration hierarchical access name
170 m_aConfigCategoryAccess += aModuleName;
171 m_aConfigCategoryAccess += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_CATEGORY_ELEMENT_ACCESS ));
172
173 m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY );
174 }
175
~ConfigurationAccess_UICategory()176 ConfigurationAccess_UICategory::~ConfigurationAccess_UICategory()
177 {
178 // SAFE
179 ResetableGuard aLock( m_aLock );
180 Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
181 if ( xContainer.is() )
182 xContainer->removeContainerListener( this );
183 }
184
185 // XNameAccess
getByName(const::rtl::OUString & rId)186 Any SAL_CALL ConfigurationAccess_UICategory::getByName( const ::rtl::OUString& rId )
187 throw ( NoSuchElementException, WrappedTargetException, RuntimeException)
188 {
189 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getByName" );
190 ResetableGuard aLock( m_aLock );
191 if ( !m_bConfigAccessInitialized )
192 {
193 initializeConfigAccess();
194 m_bConfigAccessInitialized = sal_True;
195 fillCache();
196 }
197
198 // SAFE
199 Any a = getUINameFromID( rId );
200
201 if ( !a.hasValue() )
202 throw NoSuchElementException();
203
204 return a;
205 }
206
getElementNames()207 Sequence< ::rtl::OUString > SAL_CALL ConfigurationAccess_UICategory::getElementNames()
208 throw ( RuntimeException )
209 {
210 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getElementNames" );
211 return getAllIds();
212 }
213
hasByName(const::rtl::OUString & rId)214 sal_Bool SAL_CALL ConfigurationAccess_UICategory::hasByName( const ::rtl::OUString& rId )
215 throw (::com::sun::star::uno::RuntimeException)
216 {
217 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::hasByName" );
218 return getByName( rId ).hasValue();
219 }
220
221 // XElementAccess
getElementType()222 Type SAL_CALL ConfigurationAccess_UICategory::getElementType()
223 throw ( RuntimeException )
224 {
225 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getElementType" );
226 return( ::getCppuType( (const rtl::OUString*)NULL ) );
227 }
228
hasElements()229 sal_Bool SAL_CALL ConfigurationAccess_UICategory::hasElements()
230 throw ( RuntimeException )
231 {
232 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::hasElements" );
233 // There must be global categories!
234 return sal_True;
235 }
236
fillCache()237 sal_Bool ConfigurationAccess_UICategory::fillCache()
238 {
239 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::fillCache" );
240 RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ConfigurationAccess_UICategory::fillCache" );
241
242 if ( m_bCacheFilled )
243 return sal_True;
244
245 sal_Int32 i( 0 );
246 rtl::OUString aUIName;
247 Sequence< ::rtl::OUString > aNameSeq = m_xConfigAccess->getElementNames();
248
249 for ( i = 0; i < aNameSeq.getLength(); i++ )
250 {
251 try
252 {
253 Reference< XNameAccess > xNameAccess(m_xConfigAccess->getByName( aNameSeq[i] ),UNO_QUERY);
254 if ( xNameAccess.is() )
255 {
256 xNameAccess->getByName( m_aPropUIName ) >>= aUIName;
257
258 m_aIdCache.insert( IdToInfoCache::value_type( aNameSeq[i], aUIName ));
259 }
260 }
261 catch ( com::sun::star::lang::WrappedTargetException& )
262 {
263 }
264 catch ( com::sun::star::container::NoSuchElementException& )
265 {
266 }
267 }
268
269 m_bCacheFilled = sal_True;
270
271 return sal_True;
272 }
273
getUINameFromID(const rtl::OUString & rId)274 Any ConfigurationAccess_UICategory::getUINameFromID( const rtl::OUString& rId )
275 {
276 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getUINameFromID" );
277 Any a;
278
279 try
280 {
281 a = getUINameFromCache( rId );
282 if ( !a.hasValue() )
283 {
284 // Try to ask our global commands configuration access
285 if ( m_xGenericUICategories.is() )
286 {
287 try
288 {
289 return m_xGenericUICategories->getByName( rId );
290 }
291 catch ( com::sun::star::lang::WrappedTargetException& )
292 {
293 }
294 catch ( com::sun::star::container::NoSuchElementException& )
295 {
296 }
297 }
298 }
299 }
300 catch( com::sun::star::container::NoSuchElementException& )
301 {
302 }
303 catch ( com::sun::star::lang::WrappedTargetException& )
304 {
305 }
306
307 return a;
308 }
309
getUINameFromCache(const rtl::OUString & rId)310 Any ConfigurationAccess_UICategory::getUINameFromCache( const rtl::OUString& rId )
311 {
312 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getUINameFromCache" );
313 Any a;
314
315 IdToInfoCache::const_iterator pIter = m_aIdCache.find( rId );
316 if ( pIter != m_aIdCache.end() )
317 a <<= pIter->second;
318
319 return a;
320 }
321
getAllIds()322 Sequence< rtl::OUString > ConfigurationAccess_UICategory::getAllIds()
323 {
324 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getAllIds" );
325 // SAFE
326 ResetableGuard aLock( m_aLock );
327
328 if ( !m_bConfigAccessInitialized )
329 {
330 initializeConfigAccess();
331 m_bConfigAccessInitialized = sal_True;
332 fillCache();
333 }
334
335 if ( m_xConfigAccess.is() )
336 {
337 Any a;
338 Reference< XNameAccess > xNameAccess;
339
340 try
341 {
342 Sequence< ::rtl::OUString > aNameSeq = m_xConfigAccess->getElementNames();
343
344 if ( m_xGenericUICategories.is() )
345 {
346 // Create concat list of supported user interface commands of the module
347 Sequence< ::rtl::OUString > aGenericNameSeq = m_xGenericUICategories->getElementNames();
348 sal_uInt32 nCount1 = aNameSeq.getLength();
349 sal_uInt32 nCount2 = aGenericNameSeq.getLength();
350
351 aNameSeq.realloc( nCount1 + nCount2 );
352 ::rtl::OUString* pNameSeq = aNameSeq.getArray();
353 const ::rtl::OUString* pGenericSeq = aGenericNameSeq.getConstArray();
354 for ( sal_uInt32 i = 0; i < nCount2; i++ )
355 pNameSeq[nCount1+i] = pGenericSeq[i];
356 }
357
358 return aNameSeq;
359 }
360 catch( com::sun::star::container::NoSuchElementException& )
361 {
362 }
363 catch ( com::sun::star::lang::WrappedTargetException& )
364 {
365 }
366 }
367
368 return Sequence< rtl::OUString >();
369 }
370
initializeConfigAccess()371 sal_Bool ConfigurationAccess_UICategory::initializeConfigAccess()
372 {
373 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::initializeConfigAccess" );
374 Sequence< Any > aArgs( 1 );
375 PropertyValue aPropValue;
376
377 try
378 {
379 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ));
380 aPropValue.Value <<= m_aConfigCategoryAccess;
381 aArgs[0] <<= aPropValue;
382
383 m_xConfigAccess = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ),UNO_QUERY );
384 if ( m_xConfigAccess.is() )
385 {
386 // Add as container listener
387 Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
388 if ( xContainer.is() )
389 xContainer->addContainerListener( this );
390 }
391
392 return sal_True;
393 }
394 catch ( WrappedTargetException& )
395 {
396 }
397 catch ( Exception& )
398 {
399 }
400
401 return sal_False;
402 }
403
404 // container.XContainerListener
elementInserted(const ContainerEvent &)405 void SAL_CALL ConfigurationAccess_UICategory::elementInserted( const ContainerEvent& ) throw(RuntimeException)
406 {
407 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementInserted" );
408 }
409
elementRemoved(const ContainerEvent &)410 void SAL_CALL ConfigurationAccess_UICategory::elementRemoved ( const ContainerEvent& ) throw(RuntimeException)
411 {
412 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementRemoved " );
413 }
414
elementReplaced(const ContainerEvent &)415 void SAL_CALL ConfigurationAccess_UICategory::elementReplaced( const ContainerEvent& ) throw(RuntimeException)
416 {
417 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementReplaced" );
418 }
419
420 // lang.XEventListener
disposing(const EventObject & aEvent)421 void SAL_CALL ConfigurationAccess_UICategory::disposing( const EventObject& aEvent ) throw(RuntimeException)
422 {
423 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::disposing" );
424 // SAFE
425 // remove our reference to the config access
426 ResetableGuard aLock( m_aLock );
427
428 Reference< XInterface > xIfac1( aEvent.Source, UNO_QUERY );
429 Reference< XInterface > xIfac2( m_xConfigAccess, UNO_QUERY );
430 if ( xIfac1 == xIfac2 )
431 m_xConfigAccess.clear();
432 }
433
434 //*****************************************************************************************************************
435 // XInterface, XTypeProvider, XServiceInfo
436 //*****************************************************************************************************************
DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(UICategoryDescription,::cppu::OWeakObject,SERVICENAME_UICATEGORYDESCRIPTION,IMPLEMENTATIONNAME_UICATEGORYDESCRIPTION)437 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( UICategoryDescription ,
438 ::cppu::OWeakObject ,
439 SERVICENAME_UICATEGORYDESCRIPTION ,
440 IMPLEMENTATIONNAME_UICATEGORYDESCRIPTION
441 )
442
443 DEFINE_INIT_SERVICE ( UICategoryDescription, {} )
444
445 UICategoryDescription::UICategoryDescription( const Reference< XMultiServiceFactory >& xServiceManager ) :
446 UICommandDescription(xServiceManager,true)
447 {
448 Reference< XNameAccess > xEmpty;
449 rtl::OUString aGenericCategories( RTL_CONSTASCII_USTRINGPARAM( "GenericCategories" ));
450 m_xGenericUICommands = new ConfigurationAccess_UICategory( aGenericCategories, xEmpty, xServiceManager );
451
452 // insert generic categories mappings
453 m_aModuleToCommandFileMap.insert( ModuleToCommandFileMap::value_type(
454 rtl::OUString::createFromAscii( GENERIC_MODULE_NAME ), aGenericCategories ));
455
456 UICommandsHashMap::iterator pCatIter = m_aUICommandsHashMap.find( aGenericCategories );
457 if ( pCatIter != m_aUICommandsHashMap.end() )
458 pCatIter->second = m_xGenericUICommands;
459
460 impl_fillElements("ooSetupFactoryCmdCategoryConfigRef");
461 }
462
~UICategoryDescription()463 UICategoryDescription::~UICategoryDescription()
464 {
465 }
impl_createConfigAccess(const::rtl::OUString & _sName)466 Reference< XNameAccess > UICategoryDescription::impl_createConfigAccess(const ::rtl::OUString& _sName)
467 {
468 return new ConfigurationAccess_UICategory( _sName,m_xGenericUICommands,m_xServiceManager );
469 }
470
471 } // namespace framework
472
473