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