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 #ifndef COMPHELPER_ACCESSIBLE_WRAPPER_HXX
25 #define COMPHELPER_ACCESSIBLE_WRAPPER_HXX
26 
27 #include <comphelper/proxyaggregation.hxx>
28 #include <com/sun/star/accessibility/XAccessible.hpp>
29 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
30 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
31 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
32 #include <cppuhelper/compbase3.hxx>
33 #include <cppuhelper/compbase2.hxx>
34 #include <com/sun/star/lang/XComponent.hpp>
35 #include <cppuhelper/implbase2.hxx>
36 #include <cppuhelper/implbase1.hxx>
37 #include <comphelper/sequence.hxx>
38 #include <comphelper/uno3.hxx>
39 #include <cppuhelper/interfacecontainer.hxx>
40 #include <comphelper/broadcasthelper.hxx>
41 #include <comphelper/accessibleeventnotifier.hxx>
42 #include <comphelper/stl_types.hxx>
43 #include "comphelper/comphelperdllapi.h"
44 
45 //.............................................................................
46 namespace comphelper
47 {
48 //.............................................................................
49 
50 	//=========================================================================
51 	//= OAccessibleWrapper
52 	//=========================================================================
53 
54 	class OAccessibleContextWrapper;
55 	class OWrappedAccessibleChildrenManager;
56 
57 	struct OAccessibleWrapper_Base :
58 		public ::cppu::ImplHelper1 < ::com::sun::star::accessibility::XAccessible >
59 	{};
60 
61 	/** a class which aggregates a proxy for an XAccessible, and wrapping the context returned by this
62 		XAccessible.
63 	*/
64 	class COMPHELPER_DLLPUBLIC OAccessibleWrapper:public OAccessibleWrapper_Base
65 							,public OComponentProxyAggregation
66 
67 	{
68 	private:
69 		::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
70 				m_xParentAccessible;
71 		::com::sun::star::uno::WeakReference< ::com::sun::star::accessibility::XAccessibleContext >
72 				m_aContext;
73 
74 	protected:
75 		::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
76 				m_xInnerAccessible;
77 
78 	public:
79 		/** ctor
80 			@param _rxORB
81 				a service factory
82 
83 			@param _rxInnerAccessible
84 				the object to wrap
85 
86 			@param _rxParentAccessible
87 				The XAccessible which is our parent
88 		*/
89 		OAccessibleWrapper(
90 			const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
91 			const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxInnerAccessible,
92 			const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
93 		);
94 		DECLARE_XINTERFACE()
95 		DECLARE_XTYPEPROVIDER()
96 
97 		// returns the context without creating it
98 		::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
99 					getContextNoCreate( ) const;
100 
101 	protected:
102 		virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL
103 					getAccessibleContext(  ) throw (::com::sun::star::uno::RuntimeException);
104 
105 		::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
getParent() const106 					getParent() const { return m_xParentAccessible; }
107 
108 		// own overridables
109 		virtual OAccessibleContextWrapper* createAccessibleContext(
110 				const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerContext
111 			);
112 
113 	protected:
114 		~OAccessibleWrapper( );
115 
116 	private:
117 		COMPHELPER_DLLPRIVATE OAccessibleWrapper( );										// never implemented
118 		COMPHELPER_DLLPRIVATE OAccessibleWrapper( const OAccessibleWrapper& );			// never implemented
119 		COMPHELPER_DLLPRIVATE OAccessibleWrapper& operator=( const OAccessibleWrapper& );	// never implemented
120 	};
121 
122 	//=========================================================================
123 	//= OAccessibleContextWrapperHelper
124 	//=========================================================================
125 
126 	typedef ::cppu::ImplHelper1	<	::com::sun::star::accessibility::XAccessibleEventListener
127 								>	OAccessibleContextWrapperHelper_Base;
128 
129 	/** Helper for wrapping an XAccessibleContext by aggregating a proxy for it.
130 
131 		<p>This class does not have own ref counting. In addition, it does not implement
132 		the XAccesibleContext interface, but provides all the methods from this interface
133 		which must be implemented using the inner context (such as getAccessibleChild*).</p>
134 
135 		<p>Children of the aggregated XAccessibleContext are wrapped, too.</p>
136 
137 		<p>AccessibleEvents fired by the inner context are multiplexed, especially, any references to
138 		children in such events are translated. This means that even in such events, no un-wrapped object
139 		will ever leave this class - if the aggregated context notifies an child event, the child passed
140 		to the event is wrapped</p>
141 
142 		@seealso OAccessibleContextWrapper
143 	*/
144 	class COMPHELPER_DLLPUBLIC OAccessibleContextWrapperHelper
145 				:private OComponentProxyAggregationHelper
146 				,public OAccessibleContextWrapperHelper_Base
147 	{
148 	protected:
149 		/// the context we're wrapping (properly typed, in opposite to OComponentProxyAggregationHelper::m_xInner)
150 		::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
151 															m_xInnerContext;
152 		/// the XAccessible which created this context
153 		::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
154 															m_xOwningAccessible;
155 		/// the XAccessible which is to be returned in getAccessibleParent
156 		::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
157 															m_xParentAccessible;
158 
159 		OWrappedAccessibleChildrenManager*					m_pChildMapper;			// for mapping children from our inner context to our callers
160 
161 	protected:
162 		/** ctor
163 
164 			@param _rxORB
165 				a service factory
166 
167 			@param _rxInnerAccessibleContext
168 				the object to wrap
169 
170 			@param _rxOwningAccessible
171 				The XAccessible which created this object. This is necessary because children
172 				of our wrapped context meed to be wrapped, too, and if they're asked for a parent,
173 				they of course should return the proper parent<br/>
174 				The object will be held with a hard reference
175 
176 			@param _rxParentAccessible
177 				The XAccessible to return in the getAccessibleParent call
178 		*/
179 		OAccessibleContextWrapperHelper(
180 			const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
181 			::cppu::OBroadcastHelper& _rBHelper,
182 			const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerAccessibleContext,
183 			const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxOwningAccessible,
184 			const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
185 		);
186 
187 		/// to be called from within your ctor - does the aggregation of a proxy for m_xInnerContext
188 		void aggregateProxy(
189 			oslInterlockedCount& _rRefCount,
190 			::cppu::OWeakObject& _rDelegator
191 		);
192 
193 	protected:
194 		// XInterface
195 		::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException);
196 
197 		// XTypeProvider
198 		DECLARE_XTYPEPROVIDER( )
199 
200 		// XAccessibleContext
201 		virtual sal_Int32 SAL_CALL getAccessibleChildCount(  ) throw (::com::sun::star::uno::RuntimeException);
202 		virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
203 		virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet(  ) throw (::com::sun::star::uno::RuntimeException);
204 
205 		// XAccessibleEventListener
206 		virtual void SAL_CALL notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
207 
208 	    // XEventListener
209 		virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
210 
211 		// XComponent/OComponentProxyAggregationHelper
212 		virtual void SAL_CALL dispose() throw( ::com::sun::star::uno::RuntimeException );
213 
214 		// own overridables
215 		/** notify an accessible event which has been translated (if necessary)
216 
217 			<p>Usually, you derive your clas from both OAccessibleContextWrapperHelper and XAccessibleEventBroadcaster,
218 			and simply call all your XAccessibleEventListener with the given event.</p>
219 
220 			<p>The mutex of the BroadcastHelper passed to the instance's ctor is <em>not</em> locked when calling
221 			into this method</p>
222 		*/
223 		virtual void notifyTranslatedEvent( const ::com::sun::star::accessibility::AccessibleEventObject& _rEvent ) throw (::com::sun::star::uno::RuntimeException) = 0;
224 
225 	protected:
226 		~OAccessibleContextWrapperHelper( );
227 
228 		OAccessibleContextWrapperHelper( );												// never implemented
229 		OAccessibleContextWrapperHelper( const OAccessibleContextWrapperHelper& );				// never implemented
230 		OAccessibleContextWrapperHelper& operator=( const OAccessibleContextWrapperHelper& );	// never implemented
231 	};
232 
233 	//=========================================================================
234 	//= OAccessibleContextWrapper
235 	//=========================================================================
236 	typedef ::cppu::WeakComponentImplHelper2<	::com::sun::star::accessibility::XAccessibleEventBroadcaster
237 											,	::com::sun::star::accessibility::XAccessibleContext
238 											>	OAccessibleContextWrapper_CBase;
239 
240 	class COMPHELPER_DLLPUBLIC OAccessibleContextWrapper
241 					:public OBaseMutex
242 					,public OAccessibleContextWrapper_CBase
243 					,public OAccessibleContextWrapperHelper
244 	{
245 	private:
246 		::comphelper::AccessibleEventNotifier::TClientId	m_nNotifierClient;		// for notifying AccessibleEvents
247 
248 	public:
249 		/** ctor
250 
251 			@param _rxORB
252 				a service factory
253 
254 			@param _rxInnerAccessibleContext
255 				the object to wrap
256 
257 			@param _rxOwningAccessible
258 				The XAccessible which created this object. This is necessary because children
259 				of our wrapped context meed to be wrapped, too, and if they're asked for a parent,
260 				they of course should return the proper parent<br/>
261 				The object will be held with a hard reference
262 
263 			@param _rxParentAccessible
264 				The XAccessible to return in the getAccessibleParent call
265 		*/
266 		OAccessibleContextWrapper(
267 			const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
268 			const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerAccessibleContext,
269 			const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxOwningAccessible,
270 			const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
271 		);
272 
273 		// XInterface
274 		DECLARE_XINTERFACE( )
275 		// XTypeProvider
276 		DECLARE_XTYPEPROVIDER( )
277 
278 		// XAccessibleContext
279 		virtual sal_Int32 SAL_CALL getAccessibleChildCount(  ) throw (::com::sun::star::uno::RuntimeException);
280 		virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
281 		virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent(  ) throw (::com::sun::star::uno::RuntimeException);
282 		virtual sal_Int32 SAL_CALL getAccessibleIndexInParent(  ) throw (::com::sun::star::uno::RuntimeException);
283 		virtual sal_Int16 SAL_CALL getAccessibleRole(  ) throw (::com::sun::star::uno::RuntimeException);
284 		virtual ::rtl::OUString SAL_CALL getAccessibleDescription(  ) throw (::com::sun::star::uno::RuntimeException);
285 		virtual ::rtl::OUString SAL_CALL getAccessibleName(  ) throw (::com::sun::star::uno::RuntimeException);
286 		virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet(  ) throw (::com::sun::star::uno::RuntimeException);
287 		virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet(  ) throw (::com::sun::star::uno::RuntimeException);
288 		virtual ::com::sun::star::lang::Locale SAL_CALL getLocale(  ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
289 
290 		// XAccessibleEventBroadcaster
291         using WeakComponentImplHelperBase::addEventListener;
292 		virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
293         using WeakComponentImplHelperBase::removeEventListener;
294 		virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
295 
296 		// OAccessibleContextWrapper
297 		virtual void notifyTranslatedEvent( const ::com::sun::star::accessibility::AccessibleEventObject& _rEvent ) throw (::com::sun::star::uno::RuntimeException);
298 
299 		// XComponent/OComponentProxyAggregationHelper
300 		virtual void SAL_CALL dispose() throw( ::com::sun::star::uno::RuntimeException );
301 
302 		// OComponentHelper
303         using OAccessibleContextWrapperHelper::disposing;
304 		virtual void SAL_CALL disposing()  throw (::com::sun::star::uno::RuntimeException);
305 
306 	protected:
307 		virtual ~OAccessibleContextWrapper();
308 
309 	private:
310 		COMPHELPER_DLLPRIVATE OAccessibleContextWrapper();												// never implemented
311 		COMPHELPER_DLLPRIVATE OAccessibleContextWrapper( const OAccessibleContextWrapper& );				// never implemented
312 		COMPHELPER_DLLPRIVATE OAccessibleContextWrapper& operator=( const OAccessibleContextWrapper& );	// never implemented
313 	};
314 
315 	//=========================================================================
316 	//= OWrappedAccessibleChildrenManager
317 	//=========================================================================
318 
319 	typedef	::std::map	<	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
320 						,	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
321 						,	OInterfaceCompare< ::com::sun::star::accessibility::XAccessible >
322 						>	AccessibleMap;
323 						// TODO: think about if we should hold these objects weak
324 
325 	typedef ::cppu::WeakImplHelper1	<	::com::sun::star::lang::XEventListener
326 									>	OWrappedAccessibleChildrenManager_Base;
327 	/** manages wrapping XAccessible's to XAccessible's
328 	*/
329 	class COMPHELPER_DLLPUBLIC OWrappedAccessibleChildrenManager : public OWrappedAccessibleChildrenManager_Base
330 	{
331 	protected:
332 		::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >
333 								m_xORB;
334 		::com::sun::star::uno::WeakReference< ::com::sun::star::accessibility::XAccessible >
335 								m_aOwningAccessible;	// the XAccessible which belongs to the XAccessibleContext which we work for
336 		AccessibleMap			m_aChildrenMap;			// for caching children
337 		sal_Bool				m_bTransientChildren;	// are we prohibited to cache our children?
338 
339 	public:
340 		/// ctor
341 		OWrappedAccessibleChildrenManager(
342 			const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB
343 		);
344 
345 		/** specifies if the children are to be consideren transient (i.e.: not cached)
346 			<p>to be called only once per lifetime</p>
347 		*/
348 		void	setTransientChildren( sal_Bool _bSet = sal_True );
349 
350 		/** sets the XAccessible which belongs to the XAccessibleContext which we work for
351 			<p>to be called only once per lifetime</p>
352 		*/
353 		void	setOwningAccessible( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxAcc );
354 
355 		/// retrieves a wrapper for the given accessible
356 		::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
357 				getAccessibleWrapperFor(
358 					const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxKey,
359 					sal_Bool _bCreate = sal_True
360 				);
361 
362 		/// erases the given key from the map (if it is present there)
363 		void	removeFromCache( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxKey );
364 
365 		/// invalidates (i.e. empties) the map
366 		void	invalidateAll( );
367 
368 		/** disposes (i.e. cleares) the manager
369 
370             <p>Note that the XAccessibleContext's of the mapped XAccessible objects are disposed, too.</p>
371         */
372         void	dispose();
373 
374 		/** handles a notification as got from the parent of the children we're managing
375 			<p>This applies only to the notifications which have a direct impact on our map.</p>
376 		*/
377 		void	handleChildNotification( const ::com::sun::star::accessibility::AccessibleEventObject& _rEvent );
378 
379 		/** translates events as got from the parent of the children we're managing
380 			<p>This applies only to the notifications which deal with child objects which we manage.</p>
381 		*/
382 		void	translateAccessibleEvent(
383 			const	::com::sun::star::accessibility::AccessibleEventObject& _rEvent,
384 					::com::sun::star::accessibility::AccessibleEventObject& _rTranslatedEvent
385 		);
386 
387 	protected:
388 		// XEventListener
389 		virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
390 
391 	protected:
392 		void	implTranslateChildEventValue( const ::com::sun::star::uno::Any& _rInValue, ::com::sun::star::uno::Any& _rOutValue );
393 
394 	protected:
395 		~OWrappedAccessibleChildrenManager( );
396 
397 	private:
398 		COMPHELPER_DLLPRIVATE OWrappedAccessibleChildrenManager( );														// never implemented
399 		COMPHELPER_DLLPRIVATE OWrappedAccessibleChildrenManager( const OWrappedAccessibleChildrenManager& );				// never implemented
400 		COMPHELPER_DLLPRIVATE OWrappedAccessibleChildrenManager& operator=( const OWrappedAccessibleChildrenManager& );	// never implemented
401 	};
402 
403 //.............................................................................
404 }	// namespace accessibility
405 //.............................................................................
406 
407 #endif // COMPHELPER_ACCESSIBLE_WRAPPER_HXX
408