lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / accessibility / source / extended / accessibletablistboxtable.cxx
blob8c8dd1156b2f28b2eb01987308d3ca672e55385b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <extended/accessibletablistboxtable.hxx>
22 #include <extended/AccessibleBrowseBoxTableCell.hxx>
23 #include <extended/AccessibleBrowseBoxCheckBoxCell.hxx>
24 #include <vcl/svtabbx.hxx>
25 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
28 namespace accessibility
32 // class AccessibleTabListBoxTable ---------------------------------------------
34 using namespace ::com::sun::star::accessibility;
35 using namespace ::com::sun::star::uno;
36 using namespace ::com::sun::star::lang;
37 using namespace ::com::sun::star;
40 // Ctor() and Dtor()
42 AccessibleTabListBoxTable::AccessibleTabListBoxTable( const Reference< XAccessible >& rxParent, SvHeaderTabListBox& rBox ) :
44 AccessibleBrowseBoxTable( rxParent, rBox ),
46 m_pTabListBox ( &rBox )
49 m_pTabListBox->AddEventListener( LINK( this, AccessibleTabListBoxTable, WindowEventListener ) );
52 AccessibleTabListBoxTable::~AccessibleTabListBoxTable()
54 if ( isAlive() )
56 m_pTabListBox = nullptr;
58 // increment ref count to prevent double call of Dtor
59 osl_atomic_increment( &m_refCount );
60 dispose();
64 void AccessibleTabListBoxTable::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
66 if ( isAlive() )
68 VclEventId nEventId = rVclWindowEvent.GetId();
69 switch ( nEventId )
71 case VclEventId::ObjectDying :
73 m_pTabListBox->RemoveEventListener( LINK( this, AccessibleTabListBoxTable, WindowEventListener ) );
74 m_pTabListBox = nullptr;
75 break;
78 case VclEventId::ControlGetFocus :
79 case VclEventId::ControlLoseFocus :
81 uno::Any aOldValue, aNewValue;
82 if ( nEventId == VclEventId::ControlGetFocus )
83 aNewValue <<= AccessibleStateType::FOCUSED;
84 else
85 aOldValue <<= AccessibleStateType::FOCUSED;
86 commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
87 break;
90 case VclEventId::ListboxSelect :
92 // First send an event that tells the listeners of a
93 // modified selection. The active descendant event is
94 // send after that so that the receiving AT has time to
95 // read the text or name of the active child.
96 commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
97 if ( m_pTabListBox && m_pTabListBox->HasFocus() )
99 SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
100 if ( pEntry )
102 sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
103 sal_uInt16 nCol = m_pTabListBox->GetCurrColumn();
104 Reference< XAccessible > xChild =
105 m_pTabListBox->CreateAccessibleCell( nRow, nCol );
106 uno::Any aOldValue, aNewValue;
108 if ( m_pTabListBox->IsTransientChildrenDisabled() )
110 aNewValue <<= AccessibleStateType::FOCUSED;
111 TriState eState = TRISTATE_INDET;
112 if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) )
114 AccessibleCheckBoxCell* pCell =
115 static_cast< AccessibleCheckBoxCell* >( xChild.get() );
116 pCell->commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
118 else
120 AccessibleBrowseBoxTableCell* pCell =
121 static_cast< AccessibleBrowseBoxTableCell* >( xChild.get() );
122 pCell->commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
125 else
127 aNewValue <<= xChild;
128 commitEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aNewValue, aOldValue );
132 break;
134 case VclEventId::WindowGetFocus :
136 uno::Any aOldValue, aNewValue;
137 aNewValue <<= AccessibleStateType::FOCUSED;
138 commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
139 break;
142 case VclEventId::WindowLoseFocus :
144 uno::Any aOldValue, aNewValue;
145 aOldValue <<= AccessibleStateType::FOCUSED;
146 commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
147 break;
149 case VclEventId::ListboxTreeSelect:
151 SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
152 if (pEntry)
154 sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
155 Reference< XAccessible > xChild = m_pTabListBox->CreateAccessibleCell( nRow, m_pTabListBox->GetCurrColumn() );
156 TriState eState = TRISTATE_INDET;
157 if ( m_pTabListBox->IsCellCheckBox( nRow, m_pTabListBox->GetCurrColumn(), eState ) )
159 AccessibleCheckBoxCell* pCell = static_cast< AccessibleCheckBoxCell* >( xChild.get() );
160 pCell->commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
162 else
164 AccessibleBrowseBoxTableCell* pCell = static_cast< AccessibleBrowseBoxTableCell* >( xChild.get() );
165 pCell->commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
169 break;
170 case VclEventId::ListboxTreeFocus:
172 if ( m_pTabListBox && m_pTabListBox->HasFocus() )
174 uno::Any aOldValue, aNewValue;
175 SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
176 if ( pEntry )
178 sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
179 m_xCurChild = m_pTabListBox->CreateAccessibleCell( nRow, m_pTabListBox->GetCurrColumn() );
180 aNewValue <<= m_xCurChild;
181 commitEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aNewValue ,aOldValue);
183 else
185 aNewValue <<= AccessibleStateType::FOCUSED;
186 commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue ,aOldValue);
190 break;
192 case VclEventId::CheckboxToggle :
194 if ( m_pTabListBox && m_pTabListBox->HasFocus() )
196 SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
197 if ( pEntry )
199 sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
200 sal_uInt16 nCol = m_pTabListBox->GetCurrColumn();
201 TriState eState = TRISTATE_INDET;
202 if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) )
204 Reference< XAccessible > xChild =
205 m_pTabListBox->CreateAccessibleCell( nRow, nCol );
206 AccessibleCheckBoxCell* pCell =
207 static_cast< AccessibleCheckBoxCell* >( xChild.get() );
208 pCell->SetChecked( SvHeaderTabListBox::IsItemChecked( pEntry, nCol ) );
212 break;
215 case VclEventId::TableCellNameChanged :
217 if ( m_pTabListBox->IsTransientChildrenDisabled() )
219 commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
220 TabListBoxEventData* pData = static_cast< TabListBoxEventData* >( rVclWindowEvent.GetData() );
221 SvTreeListEntry* pEntry = pData != nullptr ? pData->m_pEntry : nullptr;
222 if ( pEntry )
224 sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
225 sal_uInt16 nCol = pData->m_nColumn;
226 Reference< XAccessible > xChild =
227 m_pTabListBox->CreateAccessibleCell( nRow, nCol );
228 uno::Any aOldValue, aNewValue;
229 aOldValue <<= pData->m_sOldText;
230 OUString sNewText( m_pTabListBox->GetCellText( nRow, nCol ) );
231 aNewValue <<= sNewText;
232 TriState eState = TRISTATE_INDET;
234 if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) )
236 AccessibleCheckBoxCell* pCell =
237 static_cast< AccessibleCheckBoxCell* >( xChild.get() );
238 pCell->commitEvent( AccessibleEventId::NAME_CHANGED, aNewValue, aOldValue );
240 else
242 AccessibleBrowseBoxTableCell* pCell =
243 static_cast< AccessibleBrowseBoxTableCell* >( xChild.get() );
244 pCell->nameChanged( sNewText, pData->m_sOldText );
248 break;
250 default: break;
255 IMPL_LINK( AccessibleTabListBoxTable, WindowEventListener, VclWindowEvent&, rEvent, void )
257 OSL_ENSURE( rEvent.GetWindow() && m_pTabListBox, "no event window" );
258 ProcessWindowEvent( rEvent );
260 // helpers --------------------------------------------------------------------
262 void AccessibleTabListBoxTable::ensureValidIndex( sal_Int32 _nIndex ) const
264 if ( ( _nIndex < 0 ) || ( _nIndex >= (implGetRowCount() * implGetColumnCount()) ) )
265 throw IndexOutOfBoundsException();
268 void AccessibleTabListBoxTable::implSelectRow( sal_Int32 _nRow, bool _bSelect )
270 if ( m_pTabListBox )
271 m_pTabListBox->Select( m_pTabListBox->GetEntry( _nRow ), _bSelect );
274 sal_Int32 AccessibleTabListBoxTable::implGetRowCount() const
276 return m_pTabListBox ? m_pTabListBox->GetEntryCount() : 0;
279 sal_Int32 AccessibleTabListBoxTable::implGetColumnCount() const
281 return m_pTabListBox ? m_pTabListBox->GetColumnCount() : 0;
284 sal_Int32 AccessibleTabListBoxTable::implGetSelRowCount() const
286 return m_pTabListBox ? m_pTabListBox->GetSelectionCount() : 0;
289 sal_Int32 AccessibleTabListBoxTable::implGetSelRow( sal_Int32 nSelRow ) const
291 if ( m_pTabListBox )
293 sal_Int32 nRow = 0;
294 SvTreeListEntry* pEntry = m_pTabListBox->FirstSelected();
295 while ( pEntry )
297 ++nRow;
298 if ( nRow == nSelRow )
299 return m_pTabListBox->GetEntryPos( pEntry );
300 pEntry = m_pTabListBox->NextSelected( pEntry );
304 return 0;
307 // XInterface & XTypeProvider
309 IMPLEMENT_FORWARD_XINTERFACE2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper)
310 IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper)
312 // XServiceInfo
314 OUString AccessibleTabListBoxTable::getImplementationName()
316 return OUString( "com.sun.star.comp.svtools.AccessibleTabListBoxTable" );
319 // XAccessibleSelection
321 void SAL_CALL AccessibleTabListBoxTable::selectAccessibleChild( sal_Int32 nChildIndex )
323 SolarMutexGuard aSolarGuard;
324 ::osl::MutexGuard aGuard( getMutex() );
326 ensureIsAlive();
327 ensureValidIndex( nChildIndex );
329 implSelectRow( implGetRow( nChildIndex ), true );
332 sal_Bool SAL_CALL AccessibleTabListBoxTable::isAccessibleChildSelected( sal_Int32 nChildIndex )
334 SolarMutexGuard aSolarGuard;
335 ::osl::MutexGuard aGuard( getMutex() );
337 ensureIsAlive();
338 ensureValidIndex( nChildIndex );
340 return m_pTabListBox && m_pTabListBox->IsSelected( m_pTabListBox->GetEntry( implGetRow( nChildIndex ) ) );
343 void SAL_CALL AccessibleTabListBoxTable::clearAccessibleSelection( )
345 SolarMutexGuard aSolarGuard;
346 ::osl::MutexGuard aGuard( getMutex() );
348 ensureIsAlive();
350 m_pTabListBox->SetNoSelection();
353 void SAL_CALL AccessibleTabListBoxTable::selectAllAccessibleChildren( )
355 SolarMutexGuard aSolarGuard;
356 ::osl::MutexGuard aGuard( getMutex() );
358 ensureIsAlive();
360 m_pTabListBox->SelectAll();
363 sal_Int32 SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChildCount( )
365 SolarMutexGuard aSolarGuard;
366 ::osl::MutexGuard aGuard( getMutex() );
368 ensureIsAlive();
370 return implGetColumnCount() * implGetSelRowCount();
373 Reference< XAccessible > SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
375 SolarMutexGuard aSolarGuard;
376 ::osl::MutexGuard aGuard( getMutex() );
378 ensureIsAlive();
380 sal_Int32 nRows = implGetSelRowCount();
381 if ( nRows == 0 )
382 throw IndexOutOfBoundsException();
384 sal_Int32 nRow = implGetSelRow( nSelectedChildIndex % nRows );
385 sal_Int32 nColumn = nSelectedChildIndex / nRows;
386 return getAccessibleCellAt( nRow, nColumn );
389 void SAL_CALL AccessibleTabListBoxTable::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
391 SolarMutexGuard aSolarGuard;
392 ::osl::MutexGuard aGuard( getMutex() );
394 ensureIsAlive();
395 ensureValidIndex( nSelectedChildIndex );
397 implSelectRow( implGetRow( nSelectedChildIndex ), false );
401 }// namespace accessibility
404 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */