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_framework.hxx"
30 
31 #include <classes/rootactiontriggercontainer.hxx>
32 #include <classes/actiontriggercontainer.hxx>
33 #include <classes/actiontriggerpropertyset.hxx>
34 #include <classes/actiontriggerseparatorpropertyset.hxx>
35 #include <framework/actiontriggerhelper.hxx>
36 #include <threadhelp/resetableguard.hxx>
37 #include <osl/mutex.hxx>
38 #include <vcl/svapp.hxx>
39 #include <cppuhelper/typeprovider.hxx>
40 
41 
42 using namespace cppu;
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::lang;
45 using namespace com::sun::star::container;
46 using namespace com::sun::star::beans;
47 
48 
49 namespace framework
50 {
51 
52 static Sequence< sal_Int8 > impl_getStaticIdentifier()
53 {
54     static sal_uInt8 pGUID[16] = { 0x17, 0x0F, 0xA2, 0xC9, 0xCA, 0x50, 0x4A, 0xD3, 0xA6, 0x3B, 0x39, 0x99, 0xC5, 0x96, 0x43, 0x27 };
55     static ::com::sun::star::uno::Sequence< sal_Int8 > seqID((sal_Int8*)pGUID,16) ;
56     return seqID ;
57 }
58 
59 
60 RootActionTriggerContainer::RootActionTriggerContainer( const Menu* pMenu, const ::rtl::OUString* pMenuIdentifier, const Reference< XMultiServiceFactory >& rServiceManager ) :
61 	PropertySetContainer( rServiceManager )
62 	,	m_bContainerCreated( sal_False )
63 	,	m_bContainerChanged( sal_False )
64 	,	m_bInContainerCreation( sal_False )
65     ,   m_pMenu( pMenu )
66     ,   m_pMenuIdentifier( pMenuIdentifier )
67 {
68 }
69 
70 RootActionTriggerContainer::~RootActionTriggerContainer()
71 {
72 }
73 
74 Sequence< sal_Int8 > RootActionTriggerContainer::GetUnoTunnelId() const
75 {
76 	return impl_getStaticIdentifier();
77 }
78 
79 const Menu* RootActionTriggerContainer::GetMenu()
80 {
81 	if ( !m_bContainerChanged )
82 		return m_pMenu;
83 	else
84 	{
85 		ResetableGuard aGuard( m_aLock );
86 
87 		Menu* pNewMenu = new PopupMenu;
88 
89 		ActionTriggerHelper::CreateMenuFromActionTriggerContainer( pNewMenu, this );
90 		m_pMenu = pNewMenu;
91 		m_bContainerChanged = sal_False;
92 
93 		return m_pMenu;
94 	}
95 }
96 
97 
98 // XInterface
99 Any SAL_CALL RootActionTriggerContainer::queryInterface( const Type& aType )
100 throw ( RuntimeException )
101 {
102 	Any a = ::cppu::queryInterface(
103 				aType ,
104 				SAL_STATIC_CAST( XMultiServiceFactory*	, this ),
105 				SAL_STATIC_CAST( XServiceInfo*			, this ),
106 				SAL_STATIC_CAST( XUnoTunnel*			, this ),
107                 SAL_STATIC_CAST( XTypeProvider*         , this ),
108                 SAL_STATIC_CAST( XNamed*                , this ));
109 
110 	if( a.hasValue() )
111 	{
112 		return a;
113 	}
114 
115 	return PropertySetContainer::queryInterface( aType );
116 }
117 
118 void SAL_CALL RootActionTriggerContainer::acquire() throw ()
119 {
120 	PropertySetContainer::acquire();
121 }
122 
123 void SAL_CALL RootActionTriggerContainer::release() throw ()
124 {
125 	PropertySetContainer::release();
126 }
127 
128 // XMultiServiceFactory
129 Reference< XInterface > SAL_CALL RootActionTriggerContainer::createInstance( const ::rtl::OUString& aServiceSpecifier )
130 throw ( Exception,  RuntimeException )
131 {
132 	if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGER ))
133 		return (OWeakObject *)( new ActionTriggerPropertySet( m_xServiceManager ));
134 	else if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGERCONTAINER ))
135 		return (OWeakObject *)( new ActionTriggerContainer( m_xServiceManager ));
136 	else if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGERSEPARATOR ))
137 		return (OWeakObject *)( new ActionTriggerSeparatorPropertySet( m_xServiceManager ));
138 	else
139 		throw com::sun::star::uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unknown service specifier!" )), (OWeakObject *)this );
140 }
141 
142 Reference< XInterface > SAL_CALL RootActionTriggerContainer::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const Sequence< Any >& /*Arguments*/ )
143 throw ( Exception, RuntimeException )
144 {
145 	return createInstance( ServiceSpecifier );
146 }
147 
148 Sequence< ::rtl::OUString > SAL_CALL RootActionTriggerContainer::getAvailableServiceNames()
149 throw ( RuntimeException )
150 {
151 	Sequence< ::rtl::OUString > aSeq( 3 );
152 
153 	aSeq[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGER ));
154 	aSeq[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERCONTAINER ));
155 	aSeq[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR ));
156 
157 	return aSeq;
158 }
159 
160 
161 // XIndexContainer
162 void SAL_CALL RootActionTriggerContainer::insertByIndex( sal_Int32 Index, const Any& Element )
163 throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
164 {
165 	ResetableGuard aGuard( m_aLock );
166 
167 	if ( !m_bContainerCreated )
168 		FillContainer();
169 
170 	if ( !m_bInContainerCreation )
171 		m_bContainerChanged = sal_True;
172 	PropertySetContainer::insertByIndex( Index, Element );
173 }
174 
175 void SAL_CALL RootActionTriggerContainer::removeByIndex( sal_Int32 Index )
176 throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
177 {
178 	ResetableGuard aGuard( m_aLock );
179 
180 	if ( !m_bContainerCreated )
181 		FillContainer();
182 
183 	if ( !m_bInContainerCreation )
184 		m_bContainerChanged = sal_True;
185 	PropertySetContainer::removeByIndex( Index );
186 }
187 
188 
189 // XIndexReplace
190 void SAL_CALL RootActionTriggerContainer::replaceByIndex( sal_Int32 Index, const Any& Element )
191 throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
192 {
193 	ResetableGuard aGuard( m_aLock );
194 
195 	if ( !m_bContainerCreated )
196 		FillContainer();
197 
198 	if ( !m_bInContainerCreation )
199 		m_bContainerChanged = sal_True;
200 	PropertySetContainer::replaceByIndex( Index, Element );
201 }
202 
203 
204 // XIndexAccess
205 sal_Int32 SAL_CALL RootActionTriggerContainer::getCount()
206 throw ( RuntimeException )
207 {
208 	ResetableGuard aGuard( m_aLock );
209 
210 	if ( !m_bContainerCreated )
211 	{
212 		if ( m_pMenu )
213 		{
214 			vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
215 			return m_pMenu->GetItemCount();
216 		}
217 		else
218 			return 0;
219 	}
220 	else
221 	{
222 		return PropertySetContainer::getCount();
223 	}
224 }
225 
226 Any SAL_CALL RootActionTriggerContainer::getByIndex( sal_Int32 Index )
227 throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
228 {
229 	ResetableGuard aGuard( m_aLock );
230 
231 	if ( !m_bContainerCreated )
232 		FillContainer();
233 
234 	return PropertySetContainer::getByIndex( Index );
235 }
236 
237 
238 // XElementAccess
239 Type SAL_CALL RootActionTriggerContainer::getElementType()
240 	throw (::com::sun::star::uno::RuntimeException)
241 {
242 	return ::getCppuType(( Reference< XPropertySet >*)0);
243 }
244 
245 sal_Bool SAL_CALL RootActionTriggerContainer::hasElements()
246 throw (::com::sun::star::uno::RuntimeException)
247 {
248 	if ( m_pMenu )
249 	{
250 		vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
251 		return ( m_pMenu->GetItemCount() > 0 );
252 	}
253 
254 	return sal_False;
255 }
256 
257 
258 // XServiceInfo
259 ::rtl::OUString SAL_CALL RootActionTriggerContainer::getImplementationName()
260 throw ( RuntimeException )
261 {
262 	return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATIONNAME_ROOTACTIONTRIGGERCONTAINER ));
263 }
264 
265 sal_Bool SAL_CALL RootActionTriggerContainer::supportsService( const ::rtl::OUString& ServiceName )
266 throw ( RuntimeException )
267 {
268 	if ( ServiceName.equalsAscii( SERVICENAME_ACTIONTRIGGERCONTAINER ))
269 		return sal_True;
270 
271 	return sal_False;
272 }
273 
274 Sequence< ::rtl::OUString > SAL_CALL RootActionTriggerContainer::getSupportedServiceNames()
275 throw ( RuntimeException )
276 {
277     Sequence< ::rtl::OUString > seqServiceNames( 1 );
278 
279 	seqServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERCONTAINER ));
280 	return seqServiceNames;
281 }
282 
283 // XUnoTunnel
284 sal_Int64 SAL_CALL RootActionTriggerContainer::getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw ( RuntimeException )
285 {
286     if ( aIdentifier == impl_getStaticIdentifier() )
287         return reinterpret_cast< sal_Int64 >( this );
288     else
289         return 0;
290 }
291 
292 // XTypeProvider
293 Sequence< Type > SAL_CALL RootActionTriggerContainer::getTypes() throw ( RuntimeException )
294 {
295 	// Optimize this method !
296 	// We initialize a static variable only one time. And we don't must use a mutex at every call!
297 	// For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL!
298 	static ::cppu::OTypeCollection* pTypeCollection = NULL ;
299 
300 	if ( pTypeCollection == NULL )
301 	{
302 		// Ready for multithreading; get global mutex for first call of this method only! see before
303 		osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
304 
305 		// Control these pointer again ... it can be, that another instance will be faster then these!
306 		if ( pTypeCollection == NULL )
307 		{
308 			// Create a static typecollection ...
309 			static ::cppu::OTypeCollection aTypeCollection(
310 						::getCppuType(( const Reference< XMultiServiceFactory	>*)NULL ) ,
311 						::getCppuType(( const Reference< XIndexContainer		>*)NULL ) ,
312 						::getCppuType(( const Reference< XIndexAccess			>*)NULL ) ,
313 						::getCppuType(( const Reference< XIndexReplace			>*)NULL ) ,
314 						::getCppuType(( const Reference< XServiceInfo			>*)NULL ) ,
315 						::getCppuType(( const Reference< XTypeProvider			>*)NULL ) ,
316                         ::getCppuType(( const Reference< XUnoTunnel             >*)NULL ) ,
317                         ::getCppuType(( const Reference< XNamed                 >*)NULL )) ;
318 
319 			// ... and set his address to static pointer!
320 			pTypeCollection = &aTypeCollection ;
321 		}
322 	}
323 
324 	return pTypeCollection->getTypes() ;
325 }
326 
327 Sequence< sal_Int8 > SAL_CALL RootActionTriggerContainer::getImplementationId() throw ( RuntimeException )
328 {
329 	// Create one Id for all instances of this class.
330 	// Use ethernet address to do this! (sal_True)
331 
332 	// Optimize this method
333 	// We initialize a static variable only one time. And we don't must use a mutex at every call!
334 	// For the first call; pID is NULL - for the second call pID is different from NULL!
335 	static ::cppu::OImplementationId* pID = NULL ;
336 
337 	if ( pID == NULL )
338 	{
339 		// Ready for multithreading; get global mutex for first call of this method only! see before
340 		osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
341 
342 		// Control these pointer again ... it can be, that another instance will be faster then these!
343 		if ( pID == NULL )
344 		{
345 			// Create a new static ID ...
346 			static ::cppu::OImplementationId aID( sal_False ) ;
347 			// ... and set his address to static pointer!
348 			pID = &aID ;
349 		}
350 	}
351 
352 	return pID->getImplementationId() ;
353 }
354 
355 // private implementation helper
356 void RootActionTriggerContainer::FillContainer()
357 {
358 	m_bContainerCreated = sal_True;
359 	m_bInContainerCreation = sal_True;
360     Reference<XIndexContainer> xXIndexContainer( (OWeakObject *)this, UNO_QUERY );
361 	ActionTriggerHelper::FillActionTriggerContainerFromMenu(
362 		xXIndexContainer,
363 		m_pMenu );
364 	m_bInContainerCreation = sal_False;
365 }
366 ::rtl::OUString RootActionTriggerContainer::getName() throw ( RuntimeException )
367 {
368     ::rtl::OUString sRet;
369     if( m_pMenuIdentifier )
370         sRet = *m_pMenuIdentifier;
371     return sRet;
372 }
373 
374 void RootActionTriggerContainer::setName( const ::rtl::OUString& ) throw ( RuntimeException)
375 {
376     throw RuntimeException();
377 }
378 }
379 
380