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_accessibility.hxx"
26 #include "accessibility/extended/accessibleiconchoicectrl.hxx"
27 #include "accessibility/extended/accessibleiconchoicectrlentry.hxx"
28 #include <svtools/ivctrl.hxx>
29 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
30 #include <com/sun/star/accessibility/AccessibleRole.hpp>
31 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
32 #include <unotools/accessiblestatesethelper.hxx>
33 #include <tools/debug.hxx>
34 #include <vcl/svapp.hxx>
35 #include <cppuhelper/typeprovider.hxx>
36 
37 //........................................................................
38 namespace accessibility
39 {
40 //........................................................................
41 
42 	// class AccessibleIconChoiceCtrl ----------------------------------------------
43 
44 	using namespace ::com::sun::star::accessibility;
45 	using namespace ::com::sun::star::uno;
46 	using namespace ::com::sun::star::lang;
47 	using namespace ::com::sun::star;
48 
49 	DBG_NAME(AccessibleIconChoiceCtrl)
50 
51 	// -----------------------------------------------------------------------------
52 	// Ctor() and Dtor()
53 	// -----------------------------------------------------------------------------
54 	AccessibleIconChoiceCtrl::AccessibleIconChoiceCtrl( SvtIconChoiceCtrl& _rIconCtrl, const Reference< XAccessible >& _xParent ) :
55 
56 		VCLXAccessibleComponent( _rIconCtrl.GetWindowPeer() ),
57 		m_xParent		( _xParent )
58 	{
59 		DBG_CTOR( AccessibleIconChoiceCtrl, NULL );
60 	}
61 	// -----------------------------------------------------------------------------
62 	AccessibleIconChoiceCtrl::~AccessibleIconChoiceCtrl()
63 	{
64 		DBG_DTOR( AccessibleIconChoiceCtrl, NULL );
65 	}
66 	// -----------------------------------------------------------------------------
67 	IMPLEMENT_FORWARD_XINTERFACE2(AccessibleIconChoiceCtrl, VCLXAccessibleComponent, AccessibleIconChoiceCtrl_BASE)
68 	IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleIconChoiceCtrl, VCLXAccessibleComponent, AccessibleIconChoiceCtrl_BASE)
69 	// -----------------------------------------------------------------------------
70 	void AccessibleIconChoiceCtrl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
71 	{
72     	if ( isAlive() )
73 		{
74 			switch ( rVclWindowEvent.GetId() )
75 			{
76 				case VCLEVENT_LISTBOX_SELECT :
77 				{
78                     // First send an event that tells the listeners of a
79                     // modified selection.  The active descendant event is
80                     // send after that so that the receiving AT has time to
81                     // read the text or name of the active child.
82 //                  NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
83 
84 					if ( getCtrl() && getCtrl()->HasFocus() )
85 					{
86 						SvxIconChoiceCtrlEntry* pEntry = static_cast< SvxIconChoiceCtrlEntry* >( rVclWindowEvent.GetData() );
87 						if ( pEntry )
88 						{
89 							sal_uLong nPos = getCtrl()->GetEntryListPos( pEntry );
90 							Reference< XAccessible > xChild = new AccessibleIconChoiceCtrlEntry( *getCtrl(), nPos, this );
91 							uno::Any aOldValue, aNewValue;
92 							aNewValue <<= xChild;
93 							NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
94 
95 							NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOldValue, aNewValue );
96 
97 						}
98 					}
99 					break;
100 				}
101 				case VCLEVENT_WINDOW_GETFOCUS :
102 				{
103 					SvtIconChoiceCtrl* pCtrl = getCtrl();
104 					if ( pCtrl && pCtrl->HasFocus() )
105 					{
106 						SvxIconChoiceCtrlEntry* pEntry = static_cast< SvxIconChoiceCtrlEntry* >( rVclWindowEvent.GetData() );
107 						if ( pEntry == NULL )
108 						{
109 							sal_uLong nPos=0;
110 							pEntry = getCtrl()->GetSelectedEntry ( nPos );
111 						}
112 						if ( pEntry )
113 						{
114 							sal_uLong nPos = pCtrl->GetEntryListPos( pEntry );
115                             Reference< XAccessible > xChild = new AccessibleIconChoiceCtrlEntry( *pCtrl, nPos, this );
116 							uno::Any aOldValue, aNewValue;
117 							aNewValue <<= xChild;
118 							NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
119 							NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOldValue, aNewValue );
120 						}
121 					}
122 					break;
123 				}
124 				default:
125 					VCLXAccessibleComponent::ProcessWindowChildEvent (rVclWindowEvent);
126 			}
127 		}
128 	}
129 	// -----------------------------------------------------------------------------
130 	// XComponent
131 	// -----------------------------------------------------------------------------
132 	void SAL_CALL AccessibleIconChoiceCtrl::disposing()
133 	{
134 		::osl::MutexGuard aGuard( m_aMutex );
135 
136 	    m_xParent = NULL;
137 	}
138 	// -----------------------------------------------------------------------------
139 	// XServiceInfo
140 	// -----------------------------------------------------------------------------
141 	::rtl::OUString SAL_CALL AccessibleIconChoiceCtrl::getImplementationName() throw (RuntimeException)
142 	{
143 		return getImplementationName_Static();
144 	}
145 	// -----------------------------------------------------------------------------
146 	Sequence< ::rtl::OUString > SAL_CALL AccessibleIconChoiceCtrl::getSupportedServiceNames() throw (RuntimeException)
147 	{
148 		return getSupportedServiceNames_Static();
149 	}
150 	// -----------------------------------------------------------------------------
151 	sal_Bool SAL_CALL AccessibleIconChoiceCtrl::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
152 	{
153 		Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
154 		const ::rtl::OUString* pSupported = aSupported.getConstArray();
155 		const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
156 		for ( ; pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported )
157 			;
158 
159 		return pSupported != pEnd;
160 	}
161 	// -----------------------------------------------------------------------------
162 	// XServiceInfo - static methods
163 	// -----------------------------------------------------------------------------
164 	Sequence< ::rtl::OUString > AccessibleIconChoiceCtrl::getSupportedServiceNames_Static(void) throw (RuntimeException)
165 	{
166 		Sequence< ::rtl::OUString > aSupported(3);
167 		aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext") );
168 		aSupported[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleComponent") );
169 		aSupported[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AccessibleIconChoiceControl") );
170 		return aSupported;
171 	}
172 	// -----------------------------------------------------------------------------
173 	::rtl::OUString AccessibleIconChoiceCtrl::getImplementationName_Static(void) throw (RuntimeException)
174 	{
175 		return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svtools.AccessibleIconChoiceControl") );
176 	}
177 	// -----------------------------------------------------------------------------
178 	// XAccessible
179 	// -----------------------------------------------------------------------------
180 	Reference< XAccessibleContext > SAL_CALL AccessibleIconChoiceCtrl::getAccessibleContext(  ) throw (RuntimeException)
181 	{
182 		ensureAlive();
183 		return this;
184 	}
185 	// -----------------------------------------------------------------------------
186 	// XAccessibleContext
187 	// -----------------------------------------------------------------------------
188 	sal_Int32 SAL_CALL AccessibleIconChoiceCtrl::getAccessibleChildCount(  ) throw (RuntimeException)
189 	{
190 		::comphelper::OExternalLockGuard aGuard( this );
191 
192 		ensureAlive();
193 		return getCtrl()->GetEntryCount();
194 	}
195 	// -----------------------------------------------------------------------------
196 	Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrl::getAccessibleChild( sal_Int32 i ) throw (RuntimeException, IndexOutOfBoundsException)
197 	{
198 		::comphelper::OExternalLockGuard aGuard( this );
199 
200 		ensureAlive();
201 		SvtIconChoiceCtrl* pCtrl = getCtrl();
202 		SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry(i);
203 		if ( !pEntry )
204 			throw RuntimeException();
205 
206 		return new AccessibleIconChoiceCtrlEntry( *pCtrl, i, this );
207 	}
208 	// -----------------------------------------------------------------------------
209 	Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrl::getAccessibleParent(  ) throw (RuntimeException)
210 	{
211 		::osl::MutexGuard aGuard( m_aMutex );
212 
213 		ensureAlive();
214 		return m_xParent;
215 	}
216 	// -----------------------------------------------------------------------------
217 	sal_Int16 SAL_CALL AccessibleIconChoiceCtrl::getAccessibleRole(  ) throw (RuntimeException)
218 	{
219 		//return AccessibleRole::TREE;
220 		return AccessibleRole::LIST;
221 	}
222 	// -----------------------------------------------------------------------------
223 	::rtl::OUString SAL_CALL AccessibleIconChoiceCtrl::getAccessibleDescription(  ) throw (RuntimeException)
224 	{
225 		::comphelper::OExternalLockGuard aGuard( this );
226 
227 		ensureAlive();
228 		return getCtrl()->GetAccessibleDescription();
229 	}
230 	// -----------------------------------------------------------------------------
231 	::rtl::OUString SAL_CALL AccessibleIconChoiceCtrl::getAccessibleName(  ) throw (RuntimeException)
232 	{
233 		::comphelper::OExternalLockGuard aGuard( this );
234 
235 		ensureAlive();
236 
237         ::rtl::OUString sName = getCtrl()->GetAccessibleName();
238         if ( sName.isEmpty() )
239             sName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IconChoiceControl" ) );
240         return sName;
241 	}
242 	// -----------------------------------------------------------------------------
243 	// XAccessibleSelection
244 	// -----------------------------------------------------------------------------
245 	void SAL_CALL AccessibleIconChoiceCtrl::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
246 	{
247     	::comphelper::OExternalLockGuard aGuard( this );
248 
249 		ensureAlive();
250 
251 		SvtIconChoiceCtrl* pCtrl = getCtrl();
252 		SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( nChildIndex );
253 		if ( !pEntry )
254 			throw IndexOutOfBoundsException();
255 
256 		pCtrl->SetCursor( pEntry );
257 	}
258 	// -----------------------------------------------------------------------------
259 	sal_Bool SAL_CALL AccessibleIconChoiceCtrl::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
260 	{
261     	::comphelper::OExternalLockGuard aGuard( this );
262 
263 		ensureAlive();
264 
265 		SvtIconChoiceCtrl* pCtrl = getCtrl();
266 		SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( nChildIndex );
267 		if ( !pEntry )
268 			throw IndexOutOfBoundsException();
269 
270 		return ( pCtrl->GetCursor() == pEntry );
271 	}
272 	// -----------------------------------------------------------------------------
273 	void SAL_CALL AccessibleIconChoiceCtrl::clearAccessibleSelection(  ) throw (RuntimeException)
274 	{
275     	::comphelper::OExternalLockGuard aGuard( this );
276 
277 		ensureAlive();
278 		getCtrl()->SetNoSelection();
279 	}
280 	// -----------------------------------------------------------------------------
281 	void SAL_CALL AccessibleIconChoiceCtrl::selectAllAccessibleChildren(  ) throw (RuntimeException)
282 	{
283     	::comphelper::OExternalLockGuard aGuard( this );
284 
285 		ensureAlive();
286 
287     	sal_Int32 i, nCount = 0;
288 		SvtIconChoiceCtrl* pCtrl = getCtrl();
289 		nCount = pCtrl->GetEntryCount();
290 		for ( i = 0; i < nCount; ++i )
291 		{
292 			SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( i );
293 			if ( pCtrl->GetCursor() != pEntry )
294 				pCtrl->SetCursor( pEntry );
295 		}
296 	}
297 	// -----------------------------------------------------------------------------
298 	sal_Int32 SAL_CALL AccessibleIconChoiceCtrl::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
299 	{
300     	::comphelper::OExternalLockGuard aGuard( this );
301 
302 		ensureAlive();
303 
304     	sal_Int32 i, nSelCount = 0, nCount = 0;
305 		SvtIconChoiceCtrl* pCtrl = getCtrl();
306 		nCount = pCtrl->GetEntryCount();
307 		for ( i = 0; i < nCount; ++i )
308 		{
309 			SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( i );
310 			if ( pCtrl->GetCursor() == pEntry )
311 				++nSelCount;
312 		}
313 
314     	return nSelCount;
315 	}
316 	// -----------------------------------------------------------------------------
317 	Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrl::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
318 	{
319     	::comphelper::OExternalLockGuard aGuard( this );
320 
321 		ensureAlive();
322 
323 		if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
324 			throw IndexOutOfBoundsException();
325 
326 		Reference< XAccessible > xChild;
327     	sal_Int32 i, nSelCount = 0, nCount = 0;
328 		SvtIconChoiceCtrl* pCtrl = getCtrl();
329 		nCount = pCtrl->GetEntryCount();
330 		for ( i = 0; i < nCount; ++i )
331 		{
332 			SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( i );
333 			if ( pCtrl->GetCursor() == pEntry )
334 				++nSelCount;
335 
336             if ( nSelCount == ( nSelectedChildIndex + 1 ) )
337 			{
338                 xChild = new AccessibleIconChoiceCtrlEntry( *pCtrl, i, this );
339 				break;
340 			}
341 		}
342 
343 		return xChild;
344 	}
345 	// -----------------------------------------------------------------------------
346 	void SAL_CALL AccessibleIconChoiceCtrl::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
347 	{
348     	::comphelper::OExternalLockGuard aGuard( this );
349 
350 		ensureAlive();
351 
352 		if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getAccessibleChildCount() )
353 			throw IndexOutOfBoundsException();
354 
355 		Reference< XAccessible > xChild;
356     	sal_Int32 i, nSelCount = 0, nCount = 0;
357 		SvtIconChoiceCtrl* pCtrl = getCtrl();
358 		nCount = pCtrl->GetEntryCount();
359 		bool bFound = false;
360 		for ( i = 0; i < nCount; ++i )
361 		{
362 			SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( i );
363 			if ( pEntry->IsSelected() )
364 			{
365 				++nSelCount;
366 				if ( i == nSelectedChildIndex )
367 					bFound = true;
368 			}
369 		}
370 
371 		// if only one entry is selected and its index is chosen to deselect -> no selection anymore
372 		if ( 1 == nSelCount && bFound )
373 			pCtrl->SetNoSelection();
374 	}
375 	// -----------------------------------------------------------------------------
376 	void AccessibleIconChoiceCtrl::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
377 	{
378 		VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
379 		if ( isAlive() )
380 		{
381 			rStateSet.AddState( AccessibleStateType::FOCUSABLE );
382 			rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
383             rStateSet.AddState( AccessibleStateType::SELECTABLE );
384 		}
385 	}
386 	// -----------------------------------------------------------------------------
387 	SvtIconChoiceCtrl* AccessibleIconChoiceCtrl::getCtrl()
388 	{
389 		return static_cast<SvtIconChoiceCtrl*>(GetWindow());
390 	}
391 
392 //........................................................................
393 }// namespace accessibility
394 //........................................................................
395 
396