Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <svtools/menuoptions.hxx>
22 : #include <unotools/configmgr.hxx>
23 : #include <unotools/configitem.hxx>
24 : #include <tools/debug.hxx>
25 : #include <com/sun/star/uno/Any.hxx>
26 : #include <com/sun/star/uno/Sequence.hxx>
27 : #include <vcl/svapp.hxx>
28 : #include <vcl/settings.hxx>
29 :
30 : #include "itemholder2.hxx"
31 :
32 : #include <list>
33 :
34 :
35 : // namespaces
36 :
37 :
38 : using namespace ::utl ;
39 : using namespace ::osl ;
40 : using namespace ::com::sun::star::uno ;
41 :
42 : #define ROOTNODE_MENU OUString("Office.Common/View/Menu" )
43 : #define DEFAULT_DONTHIDEDISABLEDENTRIES false
44 : #define DEFAULT_FOLLOWMOUSE true
45 : #define DEFAULT_MENUICONS TRISTATE_INDET
46 :
47 : #define PROPERTYNAME_DONTHIDEDISABLEDENTRIES OUString("DontHideDisabledEntry" )
48 : #define PROPERTYNAME_FOLLOWMOUSE OUString("FollowMouse" )
49 : #define PROPERTYNAME_SHOWICONSINMENUES OUString("ShowIconsInMenues" )
50 : #define PROPERTYNAME_SYSTEMICONSINMENUES OUString("IsSystemIconsInMenus" )
51 :
52 : #define PROPERTYHANDLE_DONTHIDEDISABLEDENTRIES 0
53 : #define PROPERTYHANDLE_FOLLOWMOUSE 1
54 : #define PROPERTYHANDLE_SHOWICONSINMENUES 2
55 : #define PROPERTYHANDLE_SYSTEMICONSINMENUES 3
56 :
57 : #define PROPERTYCOUNT 4
58 :
59 : #include <tools/link.hxx>
60 :
61 :
62 : // private declarations!
63 :
64 :
65 : class SvtMenuOptions_Impl : public ConfigItem
66 : {
67 :
68 : // private member
69 :
70 :
71 : private:
72 : ::std::list<Link> aList;
73 : bool m_bDontHideDisabledEntries ; /// cache "DontHideDisabledEntries" of Menu section
74 : bool m_bFollowMouse ; /// cache "FollowMouse" of Menu section
75 : TriState m_eMenuIcons ; /// cache "MenuIcons" of Menu section
76 :
77 :
78 : // public methods
79 :
80 :
81 : public:
82 :
83 :
84 : // constructor / destructor
85 :
86 :
87 : SvtMenuOptions_Impl();
88 : virtual ~SvtMenuOptions_Impl();
89 :
90 : void AddListenerLink( const Link& rLink );
91 : void RemoveListenerLink( const Link& rLink );
92 :
93 :
94 : // overloaded methods of baseclass
95 :
96 :
97 : /*-****************************************************************************************************
98 : @short called for notify of configmanager
99 : @descr These method is called from the ConfigManager before application ends or from the
100 : PropertyChangeListener if the sub tree broadcasts changes. You must update your
101 : internal values.
102 :
103 : @seealso baseclass ConfigItem
104 :
105 : @param "seqPropertyNames" is the list of properties which should be updated.
106 : *//*-*****************************************************************************************************/
107 :
108 : virtual void Notify( const Sequence< OUString >& seqPropertyNames ) SAL_OVERRIDE;
109 :
110 : /*-****************************************************************************************************
111 : @short write changes to configuration
112 : @descr These method writes the changed values into the sub tree
113 : and should always called in our destructor to guarantee consistency of config data.
114 :
115 : @seealso baseclass ConfigItem
116 : *//*-*****************************************************************************************************/
117 :
118 : virtual void Commit() SAL_OVERRIDE;
119 :
120 :
121 : // public interface
122 :
123 :
124 : /*-****************************************************************************************************
125 : @short access method to get internal values
126 : @descr These methods give us a chance to regulate access to our internal values.
127 : It's not used in the moment - but it's possible for the future!
128 : *//*-*****************************************************************************************************/
129 :
130 36 : bool IsEntryHidingEnabled() const
131 36 : { return m_bDontHideDisabledEntries; }
132 :
133 160 : TriState GetMenuIconsState() const
134 160 : { return m_eMenuIcons; }
135 :
136 0 : void SetMenuIconsState(TriState eState)
137 : {
138 0 : m_eMenuIcons = eState;
139 0 : SetModified();
140 0 : for ( ::std::list<Link>::const_iterator iter = aList.begin(); iter != aList.end(); ++iter )
141 0 : iter->Call( this );
142 0 : Commit();
143 0 : }
144 :
145 :
146 : // private methods
147 :
148 :
149 : private:
150 :
151 : /*-****************************************************************************************************
152 : @short return list of fix key names of our configuration management which represent our module tree
153 : @descr These methods return a static const list of key names. We need it to get needed values from our
154 : configuration management.
155 : @return A list of needed configuration keys is returned.
156 : *//*-*****************************************************************************************************/
157 :
158 : static Sequence< OUString > impl_GetPropertyNames();
159 : };
160 :
161 :
162 : // constructor
163 :
164 160 : SvtMenuOptions_Impl::SvtMenuOptions_Impl()
165 : // Init baseclasses first
166 : : ConfigItem ( ROOTNODE_MENU )
167 : // Init member then.
168 : , m_bDontHideDisabledEntries ( DEFAULT_DONTHIDEDISABLEDENTRIES )
169 : , m_bFollowMouse ( DEFAULT_FOLLOWMOUSE )
170 160 : , m_eMenuIcons ( DEFAULT_MENUICONS )
171 : {
172 : // Use our static list of configuration keys to get his values.
173 160 : Sequence< OUString > seqNames = impl_GetPropertyNames();
174 320 : Sequence< Any > seqValues = GetProperties( seqNames ) ;
175 :
176 : // Safe impossible cases.
177 : // We need values from ALL configuration keys.
178 : // Follow assignment use order of values in relation to our list of key names!
179 : DBG_ASSERT( !(seqNames.getLength()!=seqValues.getLength()), "SvtMenuOptions_Impl::SvtMenuOptions_Impl()\nI miss some values of configuration keys!\n" );
180 :
181 160 : bool bMenuIcons = true;
182 160 : bool bSystemMenuIcons = true;
183 160 : if (m_eMenuIcons == TRISTATE_INDET)
184 160 : bMenuIcons = Application::GetSettings().GetStyleSettings().GetPreferredUseImagesInMenus();
185 : else
186 : {
187 0 : bSystemMenuIcons = false;
188 0 : bMenuIcons = m_eMenuIcons ? sal_True : sal_False;
189 : }
190 :
191 : // Copy values from list in right order to our internal member.
192 160 : sal_Int32 nPropertyCount = seqValues.getLength() ;
193 160 : sal_Int32 nProperty = 0 ;
194 800 : for( nProperty=0; nProperty<nPropertyCount; ++nProperty )
195 : {
196 : // Safe impossible cases.
197 : // Check any for valid value.
198 : DBG_ASSERT( seqValues[nProperty].hasValue(), "SvtMenuOptions_Impl::SvtMenuOptions_Impl()\nInvalid property value for property detected!\n" );
199 :
200 640 : if (!seqValues[nProperty].hasValue())
201 0 : continue;
202 :
203 640 : switch( nProperty )
204 : {
205 : case PROPERTYHANDLE_DONTHIDEDISABLEDENTRIES : {
206 : DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtMenuOptions_Impl::SvtMenuOptions_Impl()\nWho has changed the value type of \"Office.Common\\View\\Menu\\DontHideDisabledEntry\"?" );
207 160 : seqValues[nProperty] >>= m_bDontHideDisabledEntries;
208 : }
209 160 : break;
210 :
211 : case PROPERTYHANDLE_FOLLOWMOUSE : {
212 : DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtMenuOptions_Impl::SvtMenuOptions_Impl()\nWho has changed the value type of \"Office.Common\\View\\Menu\\FollowMouse\"?" );
213 160 : seqValues[nProperty] >>= m_bFollowMouse;
214 : }
215 160 : break;
216 : case PROPERTYHANDLE_SHOWICONSINMENUES : {
217 : DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtMenuOptions_Impl::SvtMenuOptions_Impl()\nWho has changed the value type of \"Office.Common\\View\\Menu\\ShowIconsInMenues\"?" );
218 160 : seqValues[nProperty] >>= bMenuIcons;
219 : }
220 160 : break;
221 : case PROPERTYHANDLE_SYSTEMICONSINMENUES : {
222 : DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtMenuOptions_Impl::SvtMenuOptions_Impl()\nWho has changed the value type of \"Office.Common\\View\\Menu\\IsSystemIconsInMenus\"?" );
223 160 : seqValues[nProperty] >>= bSystemMenuIcons;
224 : }
225 160 : break;
226 : }
227 : }
228 :
229 160 : m_eMenuIcons = bSystemMenuIcons ? TRISTATE_INDET : static_cast<TriState>(bMenuIcons);
230 :
231 320 : EnableNotification( seqNames );
232 160 : }
233 :
234 :
235 : // destructor
236 :
237 480 : SvtMenuOptions_Impl::~SvtMenuOptions_Impl()
238 : {
239 : // Flush data to configuration!
240 : // User has no chance to do that.
241 160 : if( IsModified() )
242 : {
243 0 : Commit();
244 : }
245 320 : }
246 :
247 :
248 : // public method
249 :
250 0 : void SvtMenuOptions_Impl::Notify( const Sequence< OUString >& seqPropertyNames )
251 : {
252 : // Use given list of updated properties to get his values from configuration directly!
253 0 : Sequence< Any > seqValues = GetProperties( seqPropertyNames );
254 : // Safe impossible cases.
255 : // We need values from ALL notified configuration keys.
256 : DBG_ASSERT( !(seqPropertyNames.getLength()!=seqValues.getLength()), "SvtMenuOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
257 :
258 0 : bool bMenuSettingsChanged = false;
259 0 : bool bMenuIcons = true;
260 0 : bool bSystemMenuIcons = true;
261 0 : if (m_eMenuIcons == TRISTATE_INDET)
262 0 : bMenuIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
263 : else
264 : {
265 0 : bSystemMenuIcons = false;
266 0 : bMenuIcons = m_eMenuIcons ? sal_True : sal_False;
267 : }
268 :
269 : // Step over list of property names and get right value from coreesponding value list to set it on internal members!
270 0 : sal_Int32 nCount = seqPropertyNames.getLength();
271 0 : for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
272 : {
273 0 : if( seqPropertyNames[nProperty] == PROPERTYNAME_DONTHIDEDISABLEDENTRIES )
274 : {
275 : DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtMenuOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\View\\Menu\\DontHideDisabledEntry\"?" );
276 0 : seqValues[nProperty] >>= m_bDontHideDisabledEntries;
277 : }
278 0 : else if( seqPropertyNames[nProperty] == PROPERTYNAME_FOLLOWMOUSE )
279 : {
280 : DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtMenuOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\View\\Menu\\FollowMouse\"?" );
281 0 : seqValues[nProperty] >>= m_bFollowMouse;
282 : }
283 0 : else if( seqPropertyNames[nProperty] == PROPERTYNAME_SHOWICONSINMENUES )
284 : {
285 : DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtMenuOptions_Impl::SvtMenuOptions_Impl()\nWho has changed the value type of \"Office.Common\\View\\Menu\\ShowIconsInMenues\"?" );
286 0 : bMenuSettingsChanged |= seqValues[nProperty] >>= bMenuIcons;
287 : }
288 0 : else if( seqPropertyNames[nProperty] == PROPERTYNAME_SYSTEMICONSINMENUES )
289 : {
290 : DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtMenuOptions_Impl::SvtMenuOptions_Impl()\nWho has changed the value type of \"Office.Common\\View\\Menu\\IsSystemIconsInMenus\"?" );
291 0 : bMenuSettingsChanged |= seqValues[nProperty] >>= bSystemMenuIcons;
292 : }
293 :
294 : #if OSL_DEBUG_LEVEL > 1
295 : else DBG_ASSERT( sal_False, "SvtMenuOptions_Impl::Notify()\nUnknown property detected ... I can't handle these!\n" );
296 : #endif
297 : }
298 :
299 0 : if ( bMenuSettingsChanged )
300 0 : m_eMenuIcons = bSystemMenuIcons ? TRISTATE_INDET : static_cast<TriState>(bMenuIcons);
301 :
302 0 : for ( ::std::list<Link>::const_iterator iter = aList.begin(); iter != aList.end(); ++iter )
303 0 : iter->Call( this );
304 0 : }
305 :
306 :
307 : // public method
308 :
309 0 : void SvtMenuOptions_Impl::Commit()
310 : {
311 : // Get names of supported properties, create a list for values and copy current values to it.
312 0 : Sequence< OUString > seqNames = impl_GetPropertyNames();
313 0 : sal_Int32 nCount = seqNames.getLength();
314 0 : Sequence< Any > seqValues ( nCount );
315 0 : for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
316 : {
317 0 : switch( nProperty )
318 : {
319 : case PROPERTYHANDLE_DONTHIDEDISABLEDENTRIES : {
320 0 : seqValues[nProperty] <<= m_bDontHideDisabledEntries;
321 : }
322 0 : break;
323 :
324 : case PROPERTYHANDLE_FOLLOWMOUSE : {
325 0 : seqValues[nProperty] <<= m_bFollowMouse;
326 : }
327 0 : break;
328 : //Output cache of current setting as possibly modified by System Theme for older version
329 : case PROPERTYHANDLE_SHOWICONSINMENUES : {
330 0 : bool bValue = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
331 0 : seqValues[nProperty] <<= bValue;
332 : }
333 0 : break;
334 : case PROPERTYHANDLE_SYSTEMICONSINMENUES : {
335 0 : bool bValue = m_eMenuIcons == TRISTATE_INDET;
336 0 : seqValues[nProperty] <<= bValue;
337 : }
338 0 : break;
339 : }
340 : }
341 : // Set properties in configuration.
342 0 : PutProperties( seqNames, seqValues );
343 0 : }
344 :
345 :
346 : // private method
347 :
348 160 : Sequence< OUString > SvtMenuOptions_Impl::impl_GetPropertyNames()
349 : {
350 : // Build static list of configuration key names.
351 : static const OUString pProperties[] =
352 : {
353 : PROPERTYNAME_DONTHIDEDISABLEDENTRIES ,
354 : PROPERTYNAME_FOLLOWMOUSE ,
355 : PROPERTYNAME_SHOWICONSINMENUES ,
356 : PROPERTYNAME_SYSTEMICONSINMENUES
357 320 : };
358 : // Initialize return sequence with these list ...
359 160 : static const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT );
360 : // ... and return it.
361 160 : return seqPropertyNames;
362 : }
363 :
364 0 : void SvtMenuOptions_Impl::AddListenerLink( const Link& rLink )
365 : {
366 0 : aList.push_back( rLink );
367 0 : }
368 :
369 0 : void SvtMenuOptions_Impl::RemoveListenerLink( const Link& rLink )
370 : {
371 0 : for ( ::std::list<Link>::iterator iter = aList.begin(); iter != aList.end(); ++iter )
372 : {
373 0 : if ( *iter == rLink )
374 : {
375 0 : aList.erase(iter);
376 0 : break;
377 : }
378 : }
379 0 : }
380 :
381 :
382 : // initialize static member
383 : // DON'T DO IT IN YOUR HEADER!
384 : // see definition for further information
385 :
386 : SvtMenuOptions_Impl* SvtMenuOptions::m_pDataContainer = NULL ;
387 : sal_Int32 SvtMenuOptions::m_nRefCount = 0 ;
388 :
389 :
390 : // constructor
391 :
392 356 : SvtMenuOptions::SvtMenuOptions()
393 : {
394 : // Global access, must be guarded (multithreading!).
395 356 : MutexGuard aGuard( GetOwnStaticMutex() );
396 : // Increase our refcount ...
397 356 : ++m_nRefCount;
398 : // ... and initialize our data container only if it not already!
399 356 : if( m_pDataContainer == NULL )
400 : {
401 160 : m_pDataContainer = new SvtMenuOptions_Impl();
402 :
403 160 : svtools::ItemHolder2::holdConfigItem(E_MENUOPTIONS);
404 356 : }
405 356 : }
406 :
407 :
408 : // destructor
409 :
410 872 : SvtMenuOptions::~SvtMenuOptions()
411 : {
412 : // Global access, must be guarded (multithreading!)
413 356 : MutexGuard aGuard( GetOwnStaticMutex() );
414 : // Decrease our refcount.
415 356 : --m_nRefCount;
416 : // If last instance was deleted ...
417 : // we must destroy our static data container!
418 356 : if( m_nRefCount <= 0 )
419 : {
420 160 : delete m_pDataContainer;
421 160 : m_pDataContainer = NULL;
422 356 : }
423 516 : }
424 :
425 :
426 : // public method
427 :
428 36 : bool SvtMenuOptions::IsEntryHidingEnabled() const
429 : {
430 36 : MutexGuard aGuard( GetOwnStaticMutex() );
431 36 : return m_pDataContainer->IsEntryHidingEnabled();
432 : }
433 :
434 :
435 : // public method
436 :
437 160 : TriState SvtMenuOptions::GetMenuIconsState() const
438 : {
439 160 : MutexGuard aGuard( GetOwnStaticMutex() );
440 160 : return m_pDataContainer->GetMenuIconsState();
441 : }
442 :
443 :
444 : // public method
445 :
446 0 : void SvtMenuOptions::SetMenuIconsState(TriState eState)
447 : {
448 0 : MutexGuard aGuard( GetOwnStaticMutex() );
449 0 : m_pDataContainer->SetMenuIconsState(eState);
450 0 : }
451 :
452 :
453 : // private method
454 :
455 908 : Mutex& SvtMenuOptions::GetOwnStaticMutex()
456 : {
457 : // Initialize static mutex only for one time!
458 : static Mutex* pMutex = NULL;
459 : // If these method first called (Mutex not already exist!) ...
460 908 : if( pMutex == NULL )
461 : {
462 : // ... we must create a new one. Protect follow code with the global mutex -
463 : // It must be - we create a static variable!
464 160 : MutexGuard aGuard( Mutex::getGlobalMutex() );
465 : // We must check our pointer again - because it can be that another instance of our class will be faster than these!
466 160 : if( pMutex == NULL )
467 : {
468 : // Create the new mutex and set it for return on static variable.
469 160 : static Mutex aMutex;
470 160 : pMutex = &aMutex;
471 160 : }
472 : }
473 : // Return new created or already existing mutex object.
474 908 : return *pMutex;
475 : }
476 :
477 0 : void SvtMenuOptions::AddListenerLink( const Link& rLink )
478 : {
479 0 : m_pDataContainer->AddListenerLink( rLink );
480 0 : }
481 :
482 0 : void SvtMenuOptions::RemoveListenerLink( const Link& rLink )
483 : {
484 0 : m_pDataContainer->RemoveListenerLink( rLink );
485 1227 : }
486 :
487 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|