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