xref: /trunk/main/accessibility/source/extended/accessibletablistboxtable.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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     /** Acquire 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     {
294         if ( ( _nIndex < 0 ) || ( _nIndex >= implGetCellCount() ) )
295             throw IndexOutOfBoundsException();
296     }
297 
implIsRowSelected(sal_Int32 _nRow) const298     sal_Bool AccessibleTabListBoxTable::implIsRowSelected( sal_Int32 _nRow ) const
299     {
300         return m_pTabListBox ? m_pTabListBox->IsSelected( m_pTabListBox->GetEntry( _nRow ) ) : sal_False;
301     }
302 
implSelectRow(sal_Int32 _nRow,sal_Bool _bSelect)303     void AccessibleTabListBoxTable::implSelectRow( sal_Int32 _nRow, sal_Bool _bSelect )
304     {
305         if ( m_pTabListBox )
306             m_pTabListBox->Select( m_pTabListBox->GetEntry( _nRow ), _bSelect );
307     }
308 
implGetRowCount() const309     sal_Int32 AccessibleTabListBoxTable::implGetRowCount() const
310     {
311         return m_pTabListBox ? m_pTabListBox->GetEntryCount() : 0;
312     }
313 
implGetColumnCount() const314     sal_Int32 AccessibleTabListBoxTable::implGetColumnCount() const
315     {
316         return m_pTabListBox ? m_pTabListBox->GetColumnCount() : 0;
317     }
318 
implGetSelRowCount() const319     sal_Int32 AccessibleTabListBoxTable::implGetSelRowCount() const
320     {
321         return m_pTabListBox ? m_pTabListBox->GetSelectionCount() : 0;
322     }
323 
implGetSelRow(sal_Int32 nSelRow) const324     sal_Int32 AccessibleTabListBoxTable::implGetSelRow( sal_Int32 nSelRow ) const
325     {
326         if ( m_pTabListBox )
327         {
328             sal_Int32 nRow = 0;
329             SvLBoxEntry* pEntry = m_pTabListBox->FirstSelected();
330             while ( pEntry )
331             {
332                 ++nRow;
333                 if ( nRow == nSelRow )
334                     return m_pTabListBox->GetEntryPos( pEntry );
335                 pEntry = m_pTabListBox->NextSelected( pEntry );
336             }
337         }
338 
339         return 0;
340     }
341     // -----------------------------------------------------------------------------
342     // XInterface & XTypeProvider
343     // -----------------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2(AccessibleTabListBoxTable,AccessibleBrowseBoxTable,AccessibleTabListBoxTableImplHelper)344     IMPLEMENT_FORWARD_XINTERFACE2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper)
345     IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper)
346     // -----------------------------------------------------------------------------
347     // XServiceInfo
348     // -----------------------------------------------------------------------------
349     ::rtl::OUString AccessibleTabListBoxTable::getImplementationName (void)
350     {
351         return ::rtl::OUString::createFromAscii("com.sun.star.comp.svtools.AccessibleTabListBoxTable");
352     }
353     // -----------------------------------------------------------------------------
354     // XAccessibleSelection
355     // -----------------------------------------------------------------------------
selectAccessibleChild(sal_Int32 nChildIndex)356     void SAL_CALL AccessibleTabListBoxTable::selectAccessibleChild( sal_Int32 nChildIndex )
357     {
358         TLBSolarGuard aSolarGuard;
359         ::osl::MutexGuard aGuard( getOslMutex() );
360 
361         ensureIsAlive();
362         ensureValidIndex( nChildIndex );
363 
364         implSelectRow( implGetRow( nChildIndex ), sal_True );
365     }
366     // -----------------------------------------------------------------------------
isAccessibleChildSelected(sal_Int32 nChildIndex)367     sal_Bool SAL_CALL AccessibleTabListBoxTable::isAccessibleChildSelected( sal_Int32 nChildIndex )
368     {
369         TLBSolarGuard aSolarGuard;
370         ::osl::MutexGuard aGuard( getOslMutex() );
371 
372         ensureIsAlive();
373         ensureValidIndex( nChildIndex );
374 
375         return implIsRowSelected( implGetRow( nChildIndex ) );
376     }
377     // -----------------------------------------------------------------------------
clearAccessibleSelection()378     void SAL_CALL AccessibleTabListBoxTable::clearAccessibleSelection(  )
379     {
380         TLBSolarGuard aSolarGuard;
381         ::osl::MutexGuard aGuard( getOslMutex() );
382 
383         ensureIsAlive();
384 
385         m_pTabListBox->SetNoSelection();
386     }
387     // -----------------------------------------------------------------------------
selectAllAccessibleChildren()388     void SAL_CALL AccessibleTabListBoxTable::selectAllAccessibleChildren(  )
389     {
390         TLBSolarGuard aSolarGuard;
391         ::osl::MutexGuard aGuard( getOslMutex() );
392 
393         ensureIsAlive();
394 
395         m_pTabListBox->SelectAll();
396     }
397     // -----------------------------------------------------------------------------
getSelectedAccessibleChildCount()398     sal_Int32 SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChildCount(  )
399     {
400         TLBSolarGuard aSolarGuard;
401         ::osl::MutexGuard aGuard( getOslMutex() );
402 
403         ensureIsAlive();
404 
405         return implGetColumnCount() * implGetSelRowCount();
406     }
407     // -----------------------------------------------------------------------------
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)408     Reference< XAccessible > SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
409     {
410         TLBSolarGuard aSolarGuard;
411         ::osl::MutexGuard aGuard( getOslMutex() );
412 
413         ensureIsAlive();
414 
415         sal_Int32 nRows = implGetSelRowCount();
416         if ( nRows == 0 )
417             throw IndexOutOfBoundsException();
418 
419         sal_Int32 nRow = implGetSelRow( nSelectedChildIndex % nRows );
420         sal_Int32 nColumn = nSelectedChildIndex / nRows;
421         return getAccessibleCellAt( nRow, nColumn );
422     }
423     // -----------------------------------------------------------------------------
deselectAccessibleChild(sal_Int32 nSelectedChildIndex)424     void SAL_CALL AccessibleTabListBoxTable::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
425     {
426         TLBSolarGuard aSolarGuard;
427         ::osl::MutexGuard aGuard( getOslMutex() );
428 
429         ensureIsAlive();
430         ensureValidIndex( nSelectedChildIndex );
431 
432         implSelectRow( implGetRow( nSelectedChildIndex ), sal_False );
433     }
434 
435 //........................................................................
436 }// namespace accessibility
437 //........................................................................
438