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