xref: /AOO41X/main/accessibility/source/extended/accessibletablistboxtable.cxx (revision 24f6443dc28f6479acd9115159f263e09548a0af)
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 
27 #ifndef ACCESSIBILITY_EXT_ACCESSIBLETABLISTBOXTABLE_HXX_
28 #include "accessibility/extended/accessibletablistboxtable.hxx"
29 #endif
30 #include "accessibility/extended/AccessibleBrowseBoxTableCell.hxx"
31 #include "accessibility/extended/AccessibleBrowseBoxCheckBoxCell.hxx"
32 #include <svtools/svtabbx.hxx>
33 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
34 
35 //........................................................................
36 namespace accessibility
37 {
38 //........................................................................
39 
40 	// class TLBSolarGuard ---------------------------------------------------------
41 
42 	/** Aquire the solar mutex. */
43 	class TLBSolarGuard : public ::vos::OGuard
44 	{
45 	public:
46     	inline TLBSolarGuard() : ::vos::OGuard( Application::GetSolarMutex() ) {}
47 	};
48 
49 	// class AccessibleTabListBoxTable ---------------------------------------------
50 
51 	using namespace ::com::sun::star::accessibility;
52 	using namespace ::com::sun::star::uno;
53 	using namespace ::com::sun::star::lang;
54 	using namespace ::com::sun::star;
55 
56 	DBG_NAME(AccessibleTabListBoxTable)
57 
58 	// -----------------------------------------------------------------------------
59 	// Ctor() and Dtor()
60 	// -----------------------------------------------------------------------------
61 	AccessibleTabListBoxTable::AccessibleTabListBoxTable( const Reference< XAccessible >& rxParent, SvHeaderTabListBox& rBox ) :
62 
63 		AccessibleBrowseBoxTable( rxParent, rBox ),
64 
65 		m_pTabListBox	( &rBox )
66 
67 	{
68 		DBG_CTOR( AccessibleTabListBoxTable, NULL );
69 
70 		m_pTabListBox->AddEventListener( LINK( this, AccessibleTabListBoxTable, WindowEventListener ) );
71 	}
72 	// -----------------------------------------------------------------------------
73 	AccessibleTabListBoxTable::~AccessibleTabListBoxTable()
74 	{
75 		DBG_DTOR( AccessibleTabListBoxTable, NULL );
76 
77 		if ( isAlive() )
78 		{
79 			m_pTabListBox = NULL;
80 
81 			// increment ref count to prevent double call of Dtor
82         	osl_incrementInterlockedCount( &m_refCount );
83         	dispose();
84 		}
85 	}
86 	// -----------------------------------------------------------------------------
87 	void AccessibleTabListBoxTable::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
88 	{
89     	if ( isAlive() )
90 		{
91             sal_uLong nEventId = rVclWindowEvent.GetId();
92             switch ( nEventId )
93             {
94 				case  VCLEVENT_OBJECT_DYING :
95 				{
96 					m_pTabListBox->RemoveEventListener( LINK( this, AccessibleTabListBoxTable, WindowEventListener ) );
97 					m_pTabListBox = NULL;
98 					break;
99 				}
100 
101                 case VCLEVENT_CONTROL_GETFOCUS :
102                 case VCLEVENT_CONTROL_LOSEFOCUS :
103                 {
104                     uno::Any aOldValue, aNewValue;
105                     if ( VCLEVENT_CONTROL_GETFOCUS == nEventId )
106                         aNewValue <<= AccessibleStateType::FOCUSED;
107                     else
108                         aOldValue <<= AccessibleStateType::FOCUSED;
109                     commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
110                     break;
111                 }
112 
113                 case VCLEVENT_LISTBOX_SELECT :
114 				{
115                     // First send an event that tells the listeners of a
116                     // modified selection.  The active descendant event is
117                     // send after that so that the receiving AT has time to
118                     // read the text or name of the active child.
119 					commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
120 					if ( m_pTabListBox && m_pTabListBox->HasFocus() )
121 					{
122                         SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
123 						if ( pEntry )
124 						{
125 							sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
126                             sal_uInt16 nCol = m_pTabListBox->GetCurrColumn();
127                             Reference< XAccessible > xChild =
128                                 m_pTabListBox->CreateAccessibleCell( nRow, nCol );
129 							uno::Any aOldValue, aNewValue;
130 
131                             if ( m_pTabListBox->IsTransientChildrenDisabled() )
132                             {
133                                 aNewValue <<= AccessibleStateType::FOCUSED;
134                                 TriState eState = STATE_DONTKNOW;
135                                 if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) )
136                                 {
137                                     AccessibleCheckBoxCell* pCell =
138                                         static_cast< AccessibleCheckBoxCell* >( xChild.get() );
139                                     pCell->commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
140                                 }
141                                 else
142                                 {
143                                     AccessibleBrowseBoxTableCell* pCell =
144                                         static_cast< AccessibleBrowseBoxTableCell* >( xChild.get() );
145                                     pCell->commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
146                                 }
147                             }
148                             else
149                             {
150                                 aNewValue <<= xChild;
151                                 commitEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aNewValue, aOldValue );
152                             }
153 						}
154 					}
155 					break;
156 				}
157 
158                 case VCLEVENT_CHECKBOX_TOGGLE :
159                 {
160                     if ( m_pTabListBox && m_pTabListBox->HasFocus() )
161                     {
162                         SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
163                         if ( pEntry )
164                         {
165                             sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
166                             sal_uInt16 nCol = m_pTabListBox->GetCurrColumn();
167                             TriState eState = STATE_DONTKNOW;
168                             if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) )
169                             {
170                                 Reference< XAccessible > xChild =
171                                     m_pTabListBox->CreateAccessibleCell( nRow, nCol );
172                                 AccessibleCheckBoxCell* pCell =
173                                     static_cast< AccessibleCheckBoxCell* >( xChild.get() );
174                                 pCell->SetChecked( m_pTabListBox->IsItemChecked( pEntry, nCol ) );
175                             }
176                         }
177                     }
178                     break;
179                 }
180 
181                 case VCLEVENT_TABLECELL_NAMECHANGED :
182                 {
183                     if ( m_pTabListBox->IsTransientChildrenDisabled() )
184                     {
185                         commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
186                         TabListBoxEventData* pData = static_cast< TabListBoxEventData* >( rVclWindowEvent.GetData() );
187                         SvLBoxEntry* pEntry = pData != NULL ? pData->m_pEntry : NULL;
188                         if ( pEntry )
189                         {
190                             sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
191                             sal_uInt16 nCol = pData->m_nColumn;
192                             Reference< XAccessible > xChild =
193                                 m_pTabListBox->CreateAccessibleCell( nRow, nCol );
194                             uno::Any aOldValue, aNewValue;
195                             aOldValue <<= ::rtl::OUString( pData->m_sOldText );
196                             ::rtl::OUString sNewText( m_pTabListBox->GetCellText( nRow, nCol ) );
197                             aNewValue <<= sNewText;
198                             TriState eState = STATE_DONTKNOW;
199 
200                             if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) )
201                             {
202                                 AccessibleCheckBoxCell* pCell =
203                                     static_cast< AccessibleCheckBoxCell* >( xChild.get() );
204                                 pCell->commitEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
205                             }
206                             else
207                             {
208                                 AccessibleBrowseBoxTableCell* pCell =
209                                     static_cast< AccessibleBrowseBoxTableCell* >( xChild.get() );
210                                 pCell->nameChanged( sNewText, pData->m_sOldText );
211                             }
212                         }
213                     }
214                     break;
215                 }
216 			}
217 		}
218 	}
219 	// -----------------------------------------------------------------------------
220 	IMPL_LINK( AccessibleTabListBoxTable, WindowEventListener, VclSimpleEvent*, pEvent )
221 	{
222     	DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
223     	if ( pEvent && pEvent->ISA( VclWindowEvent ) )
224     	{
225         	DBG_ASSERT( ( (VclWindowEvent*)pEvent )->GetWindow() && m_pTabListBox, "no event window" );
226         	ProcessWindowEvent( *(VclWindowEvent*)pEvent );
227     	}
228     	return 0;
229 	}
230 	// helpers --------------------------------------------------------------------
231 
232 	void AccessibleTabListBoxTable::ensureValidIndex( sal_Int32 _nIndex ) const
233 	        SAL_THROW( ( IndexOutOfBoundsException ) )
234 	{
235 	    if ( ( _nIndex < 0 ) || ( _nIndex >= implGetCellCount() ) )
236 	        throw IndexOutOfBoundsException();
237 	}
238 
239 	sal_Bool AccessibleTabListBoxTable::implIsRowSelected( sal_Int32 _nRow ) const
240 	{
241 	    return m_pTabListBox ? m_pTabListBox->IsSelected( m_pTabListBox->GetEntry( _nRow ) ) : sal_False;
242 	}
243 
244 	void AccessibleTabListBoxTable::implSelectRow( sal_Int32 _nRow, sal_Bool _bSelect )
245 	{
246 		if ( m_pTabListBox )
247 		    m_pTabListBox->Select( m_pTabListBox->GetEntry( _nRow ), _bSelect );
248 	}
249 
250 	sal_Int32 AccessibleTabListBoxTable::implGetRowCount() const
251 	{
252 	    return m_pTabListBox ? m_pTabListBox->GetEntryCount() : 0;
253 	}
254 
255 	sal_Int32 AccessibleTabListBoxTable::implGetColumnCount() const
256 	{
257 	    return m_pTabListBox ? m_pTabListBox->GetColumnCount() : 0;
258 	}
259 
260 	sal_Int32 AccessibleTabListBoxTable::implGetSelRowCount() const
261 	{
262 	    return m_pTabListBox ? m_pTabListBox->GetSelectionCount() : 0;
263 	}
264 
265 	sal_Int32 AccessibleTabListBoxTable::implGetSelRow( sal_Int32 nSelRow ) const
266 	{
267 		if ( m_pTabListBox )
268 		{
269 		    sal_Int32 nRow = 0;
270 			SvLBoxEntry* pEntry = m_pTabListBox->FirstSelected();
271 			while ( pEntry )
272 			{
273 				++nRow;
274 				if ( nRow == nSelRow )
275 					return m_pTabListBox->GetEntryPos( pEntry );
276 				pEntry = m_pTabListBox->NextSelected( pEntry );
277 			}
278 		}
279 
280 		return 0;
281 	}
282 	// -----------------------------------------------------------------------------
283 	// XInterface & XTypeProvider
284 	// -----------------------------------------------------------------------------
285 	IMPLEMENT_FORWARD_XINTERFACE2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper)
286 	IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper)
287 	// -----------------------------------------------------------------------------
288 	// XServiceInfo
289 	// -----------------------------------------------------------------------------
290 	::rtl::OUString AccessibleTabListBoxTable::getImplementationName (void) throw (RuntimeException)
291 	{
292 		return ::rtl::OUString::createFromAscii("com.sun.star.comp.svtools.AccessibleTabListBoxTable");
293 	}
294 	// -----------------------------------------------------------------------------
295 	// XAccessibleSelection
296 	// -----------------------------------------------------------------------------
297 	void SAL_CALL AccessibleTabListBoxTable::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
298 	{
299     	TLBSolarGuard aSolarGuard;
300 		::osl::MutexGuard aGuard( getOslMutex() );
301 
302 		ensureIsAlive();
303 	    ensureValidIndex( nChildIndex );
304 
305 		implSelectRow( implGetRow( nChildIndex ), sal_True );
306 	}
307 	// -----------------------------------------------------------------------------
308 	sal_Bool SAL_CALL AccessibleTabListBoxTable::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
309 	{
310     	TLBSolarGuard aSolarGuard;
311 		::osl::MutexGuard aGuard( getOslMutex() );
312 
313 		ensureIsAlive();
314 	    ensureValidIndex( nChildIndex );
315 
316 	    return implIsRowSelected( implGetRow( nChildIndex ) );
317 	}
318 	// -----------------------------------------------------------------------------
319 	void SAL_CALL AccessibleTabListBoxTable::clearAccessibleSelection(  ) throw (RuntimeException)
320 	{
321     	TLBSolarGuard aSolarGuard;
322 		::osl::MutexGuard aGuard( getOslMutex() );
323 
324 		ensureIsAlive();
325 
326 		m_pTabListBox->SetNoSelection();
327 	}
328 	// -----------------------------------------------------------------------------
329 	void SAL_CALL AccessibleTabListBoxTable::selectAllAccessibleChildren(  ) throw (RuntimeException)
330 	{
331     	TLBSolarGuard aSolarGuard;
332 		::osl::MutexGuard aGuard( getOslMutex() );
333 
334 		ensureIsAlive();
335 
336 		m_pTabListBox->SelectAll();
337 	}
338 	// -----------------------------------------------------------------------------
339 	sal_Int32 SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
340 	{
341     	TLBSolarGuard aSolarGuard;
342 		::osl::MutexGuard aGuard( getOslMutex() );
343 
344 		ensureIsAlive();
345 
346 	    return implGetColumnCount() * implGetSelRowCount();
347 	}
348 	// -----------------------------------------------------------------------------
349 	Reference< XAccessible > SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
350 	{
351     	TLBSolarGuard aSolarGuard;
352 		::osl::MutexGuard aGuard( getOslMutex() );
353 
354 		ensureIsAlive();
355 
356 	    sal_Int32 nRows = implGetSelRowCount();
357 	    if ( nRows == 0 )
358 	        throw IndexOutOfBoundsException();
359 
360 	    sal_Int32 nRow = implGetSelRow( nSelectedChildIndex % nRows );
361 	    sal_Int32 nColumn = nSelectedChildIndex / nRows;
362 	    return getAccessibleCellAt( nRow, nColumn );
363 	}
364 	// -----------------------------------------------------------------------------
365 	void SAL_CALL AccessibleTabListBoxTable::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
366 	{
367     	TLBSolarGuard aSolarGuard;
368 		::osl::MutexGuard aGuard( getOslMutex() );
369 
370 		ensureIsAlive();
371 	    ensureValidIndex( nSelectedChildIndex );
372 
373 		implSelectRow( implGetRow( nSelectedChildIndex ), sal_False );
374 	}
375 
376 //........................................................................
377 }// namespace accessibility
378 //........................................................................
379 
380