1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_unotools.hxx"
30 #ifndef GCC
31 #endif
32 
33 //_________________________________________________________________________________________________________________
34 //	includes
35 //_________________________________________________________________________________________________________________
36 
37 #include <unotools/workingsetoptions.hxx>
38 #include <unotools/configmgr.hxx>
39 #include <unotools/configitem.hxx>
40 #include <tools/debug.hxx>
41 #include <com/sun/star/uno/Any.hxx>
42 #include <com/sun/star/uno/Sequence.hxx>
43 
44 #include <itemholder1.hxx>
45 
46 //_________________________________________________________________________________________________________________
47 //	namespaces
48 //_________________________________________________________________________________________________________________
49 
50 using namespace ::utl					;
51 using namespace ::rtl					;
52 using namespace ::osl					;
53 using namespace ::com::sun::star::uno	;
54 
55 //_________________________________________________________________________________________________________________
56 //	const
57 //_________________________________________________________________________________________________________________
58 
59 #define	ROOTNODE_WORKINGSET				OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/WorkingSet"))
60 #define	DEFAULT_WINDOWLIST				Sequence< OUString >()
61 
62 #define	PROPERTYNAME_WINDOWLIST			OUString(RTL_CONSTASCII_USTRINGPARAM("WindowList"		))
63 
64 #define	PROPERTYHANDLE_WINDOWLIST		0
65 
66 #define	PROPERTYCOUNT					1
67 
68 //_________________________________________________________________________________________________________________
69 //	private declarations!
70 //_________________________________________________________________________________________________________________
71 
72 class SvtWorkingSetOptions_Impl : public ConfigItem
73 {
74 	//-------------------------------------------------------------------------------------------------------------
75 	//	public methods
76 	//-------------------------------------------------------------------------------------------------------------
77 
78 	public:
79 
80 		//---------------------------------------------------------------------------------------------------------
81 		//	constructor / destructor
82 		//---------------------------------------------------------------------------------------------------------
83 
84 		 SvtWorkingSetOptions_Impl();
85 		~SvtWorkingSetOptions_Impl();
86 
87 		//---------------------------------------------------------------------------------------------------------
88 		//	overloaded methods of baseclass
89 		//---------------------------------------------------------------------------------------------------------
90 
91 		/*-****************************************************************************************************//**
92 			@short		called for notify of configmanager
93 			@descr		These method is called from the ConfigManager before application ends or from the
94 			 			PropertyChangeListener if the sub tree broadcasts changes. You must update your
95 						internal values.
96 
97 			@seealso	baseclass ConfigItem
98 
99 			@param		"seqPropertyNames" is the list of properties which should be updated.
100 			@return		-
101 
102 			@onerror	-
103 		*//*-*****************************************************************************************************/
104 
105     	virtual void Notify( const Sequence< OUString >& seqPropertyNames );
106 
107 		/*-****************************************************************************************************//**
108 			@short		write changes to configuration
109 			@descr		These method writes the changed values into the sub tree
110 						and should always called in our destructor to guarantee consistency of config data.
111 
112 			@seealso	baseclass ConfigItem
113 
114 			@param		-
115 			@return		-
116 
117 			@onerror	-
118 		*//*-*****************************************************************************************************/
119 
120     	virtual void Commit();
121 
122 		//---------------------------------------------------------------------------------------------------------
123 		//	public interface
124 		//---------------------------------------------------------------------------------------------------------
125 
126 		/*-****************************************************************************************************//**
127 			@short		access method to get internal values
128 			@descr		These method give us a chance to regulate acces to ouer internal values.
129 						It's not used in the moment - but it's possible for the feature!
130 
131 			@seealso	-
132 
133 			@param		-
134 			@return		-
135 
136 			@onerror	-
137 		*//*-*****************************************************************************************************/
138 
139 		Sequence< OUString >	GetWindowList(												) const	;
140 		void					SetWindowList( const Sequence< OUString >&	seqWindowList	)		;
141 
142 	//-------------------------------------------------------------------------------------------------------------
143 	//	private methods
144 	//-------------------------------------------------------------------------------------------------------------
145 
146 	private:
147 
148 		/*-****************************************************************************************************//**
149 			@short		return list of key names of ouer configuration management which represent oue module tree
150 			@descr		These methods return a static const list of key names. We need it to get needed values from our
151 						configuration management.
152 
153 			@seealso	-
154 
155 			@param		-
156 			@return		A list of needed configuration keys is returned.
157 
158 			@onerror	-
159 		*//*-*****************************************************************************************************/
160 
161 		static Sequence< OUString > GetPropertyNames();
162 
163 	//-------------------------------------------------------------------------------------------------------------
164 	//	private member
165 	//-------------------------------------------------------------------------------------------------------------
166 
167 	private:
168 
169 		Sequence< OUString >	m_seqWindowList		;
170 };
171 
172 //_________________________________________________________________________________________________________________
173 //	definitions
174 //_________________________________________________________________________________________________________________
175 
176 //*****************************************************************************************************************
177 //	constructor
178 //*****************************************************************************************************************
179 SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()
180 	// Init baseclasses first
181     :	ConfigItem			( ROOTNODE_WORKINGSET	)
182 	// Init member then.
183 	,	m_seqWindowList		( DEFAULT_WINDOWLIST	)
184 {
185 	// Use our static list of configuration keys to get his values.
186 	Sequence< OUString >	seqNames	= GetPropertyNames	(			);
187 	Sequence< Any >			seqValues	= GetProperties		( seqNames	);
188 
189 	// Safe impossible cases.
190 	// We need values from ALL configuration keys.
191 	// Follow assignment use order of values in relation to our list of key names!
192 	DBG_ASSERT( !(seqNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nI miss some values of configuration keys!\n" );
193 
194 	// Copy values from list in right order to ouer internal member.
195 	sal_Int32 nPropertyCount = seqValues.getLength();
196 	for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
197 	{
198 		// Safe impossible cases.
199 		// Check any for valid value.
200 		DBG_ASSERT( !(seqValues[nProperty].hasValue()==sal_False), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nInvalid property value detected!\n" );
201         switch( nProperty )
202         {
203             case PROPERTYHANDLE_WINDOWLIST		:	{
204 														DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
205 														seqValues[nProperty] >>= m_seqWindowList;
206 													}
207 													break;
208         }
209 	}
210 
211 	// Enable notification mechanism of ouer baseclass.
212 	// We need it to get information about changes outside these class on ouer used configuration keys!
213 	EnableNotification( seqNames );
214 }
215 
216 //*****************************************************************************************************************
217 //	destructor
218 //*****************************************************************************************************************
219 SvtWorkingSetOptions_Impl::~SvtWorkingSetOptions_Impl()
220 {
221 	// We must save our current values .. if user forget it!
222 	if( IsModified() == sal_True )
223 	{
224 		Commit();
225 	}
226 }
227 
228 //*****************************************************************************************************************
229 //	public method
230 //*****************************************************************************************************************
231 void SvtWorkingSetOptions_Impl::Notify( const Sequence< OUString >& seqPropertyNames )
232 {
233 	// Use given list of updated properties to get his values from configuration directly!
234 	Sequence< Any > seqValues = GetProperties( seqPropertyNames );
235 	// Safe impossible cases.
236 	// We need values from ALL notified configuration keys.
237 	DBG_ASSERT( !(seqPropertyNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
238 	// Step over list of property names and get right value from coreesponding value list to set it on internal members!
239 	sal_Int32 nCount = seqPropertyNames.getLength();
240 	for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
241 	{
242 		if( seqPropertyNames[nProperty] == PROPERTYNAME_WINDOWLIST )
243 		{
244 			DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
245 			seqValues[nProperty] >>= m_seqWindowList;
246 		}
247         #if OSL_DEBUG_LEVEL > 1
248 		else DBG_ASSERT( sal_False, "SvtWorkingSetOptions_Impl::Notify()\nUnkown property detected ... I can't handle these!\n" );
249 		#endif
250 	}
251 }
252 
253 //*****************************************************************************************************************
254 //	public method
255 //*****************************************************************************************************************
256 void SvtWorkingSetOptions_Impl::Commit()
257 {
258 	// Get names of supported properties, create a list for values and copy current values to it.
259 	Sequence< OUString >	seqNames	= GetPropertyNames	();
260 	sal_Int32				nCount		= seqNames.getLength();
261 	Sequence< Any >			seqValues	( nCount );
262 	for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
263 	{
264         switch( nProperty )
265         {
266             case PROPERTYHANDLE_WINDOWLIST		:	{
267                 										seqValues[nProperty] <<= m_seqWindowList;
268 													}
269                 									break;
270         }
271 	}
272 	// Set properties in configuration.
273 	PutProperties( seqNames, seqValues );
274 }
275 
276 //*****************************************************************************************************************
277 //	public method
278 //*****************************************************************************************************************
279 Sequence< OUString > SvtWorkingSetOptions_Impl::GetWindowList() const
280 {
281 	return m_seqWindowList;
282 }
283 
284 //*****************************************************************************************************************
285 //	public method
286 //*****************************************************************************************************************
287 void SvtWorkingSetOptions_Impl::SetWindowList( const Sequence< OUString >& seqWindowList )
288 {
289 	m_seqWindowList = seqWindowList;
290 	SetModified();
291 }
292 
293 //*****************************************************************************************************************
294 //	private method
295 //*****************************************************************************************************************
296 Sequence< OUString > SvtWorkingSetOptions_Impl::GetPropertyNames()
297 {
298 	// Build static list of configuration key names.
299 	static const OUString pProperties[] =
300 	{
301 		PROPERTYNAME_WINDOWLIST	,
302 	};
303 	// Initialize return sequence with these list ...
304 	static const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT );
305 	// ... and return it.
306 	return seqPropertyNames;
307 }
308 
309 //*****************************************************************************************************************
310 //	initialize static member
311 //	DON'T DO IT IN YOUR HEADER!
312 //	see definition for further informations
313 //*****************************************************************************************************************
314 SvtWorkingSetOptions_Impl*	SvtWorkingSetOptions::m_pDataContainer	= NULL	;
315 sal_Int32					SvtWorkingSetOptions::m_nRefCount		= 0		;
316 
317 //*****************************************************************************************************************
318 //	constructor
319 //*****************************************************************************************************************
320 SvtWorkingSetOptions::SvtWorkingSetOptions()
321 {
322     // Global access, must be guarded (multithreading!).
323     MutexGuard aGuard( GetOwnStaticMutex() );
324 	// Increase ouer refcount ...
325 	++m_nRefCount;
326 	// ... and initialize ouer data container only if it not already exist!
327     if( m_pDataContainer == NULL )
328 	{
329         m_pDataContainer = new SvtWorkingSetOptions_Impl;
330 		ItemHolder1::holdConfigItem(E_WORKINGSETOPTIONS);
331 	}
332 }
333 
334 //*****************************************************************************************************************
335 //	destructor
336 //*****************************************************************************************************************
337 SvtWorkingSetOptions::~SvtWorkingSetOptions()
338 {
339     // Global access, must be guarded (multithreading!)
340     MutexGuard aGuard( GetOwnStaticMutex() );
341 	// Decrease ouer refcount.
342 	--m_nRefCount;
343 	// If last instance was deleted ...
344 	// we must destroy ouer static data container!
345     if( m_nRefCount <= 0 )
346 	{
347 		delete m_pDataContainer;
348 		m_pDataContainer = NULL;
349 	}
350 }
351 
352 //*****************************************************************************************************************
353 //	public method
354 //*****************************************************************************************************************
355 Sequence< OUString > SvtWorkingSetOptions::GetWindowList() const
356 {
357     MutexGuard aGuard( GetOwnStaticMutex() );
358 	return m_pDataContainer->GetWindowList();
359 }
360 
361 //*****************************************************************************************************************
362 //	public method
363 //*****************************************************************************************************************
364 void SvtWorkingSetOptions::SetWindowList( const Sequence< OUString >& seqWindowList )
365 {
366     MutexGuard aGuard( GetOwnStaticMutex() );
367 	m_pDataContainer->SetWindowList( seqWindowList );
368 }
369 
370 //*****************************************************************************************************************
371 //	private method
372 //*****************************************************************************************************************
373 Mutex& SvtWorkingSetOptions::GetOwnStaticMutex()
374 {
375 	// Initialize static mutex only for one time!
376     static Mutex* pMutex = NULL;
377 	// If these method first called (Mutex not already exist!) ...
378     if( pMutex == NULL )
379     {
380 		// ... we must create a new one. Protect follow code with the global mutex -
381 		// It must be - we create a static variable!
382         MutexGuard aGuard( Mutex::getGlobalMutex() );
383 		// We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
384         if( pMutex == NULL )
385         {
386 			// Create the new mutex and set it for return on static variable.
387             static Mutex aMutex;
388             pMutex = &aMutex;
389         }
390     }
391 	// Return new created or already existing mutex object.
392     return *pMutex;
393 }
394