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