xref: /AOO41X/main/accessibility/source/extended/accessibletablistboxtable.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
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