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