Branch libreoffice-5-0-4
[LibreOffice.git] / accessibility / source / extended / AccessibleGridControl.cxx
blob34ca1fba3c6f547245985b8effc686025c274c5c
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 .
20 #include "accessibility/extended/AccessibleGridControl.hxx"
21 #include "accessibility/extended/AccessibleGridControlTable.hxx"
22 #include "accessibility/extended/AccessibleGridControlHeader.hxx"
23 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
24 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
25 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
26 #include <svtools/accessibletable.hxx>
27 #include <comphelper/types.hxx>
28 #include <toolkit/helper/vclunohelper.hxx>
32 namespace accessibility
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::lang;
40 using namespace ::com::sun::star::accessibility;
41 using namespace ::svt;
42 using namespace ::svt::table;
45 class AccessibleGridControl_Impl
47 public:
48 /// the XAccessible which created the AccessibleGridControl
49 WeakReference< XAccessible > m_aCreator;
51 /** The data table child. */
52 Reference<
53 ::com::sun::star::accessibility::XAccessible > m_xTable;
54 AccessibleGridControlTable* m_pTable;
56 /** The header bar for rows. */
57 Reference<
58 ::com::sun::star::accessibility::XAccessible > m_xRowHeaderBar;
59 AccessibleGridControlHeader* m_pRowHeaderBar;
61 /** The header bar for columns (first row of the table). */
62 Reference<
63 ::com::sun::star::accessibility::XAccessible > m_xColumnHeaderBar;
64 AccessibleGridControlHeader* m_pColumnHeaderBar;
66 /** The table cell child. */
67 Reference<
68 ::com::sun::star::accessibility::XAccessible > m_xCell;
69 AccessibleGridControlTableCell* m_pCell;
73 AccessibleGridControl::AccessibleGridControl(
74 const Reference< XAccessible >& _rxParent, const Reference< XAccessible >& _rxCreator,
75 IAccessibleTable& _rTable )
76 : AccessibleGridControlBase( _rxParent, _rTable, TCTYPE_GRIDCONTROL )
78 m_xImpl.reset( new AccessibleGridControl_Impl() );
79 m_xImpl->m_aCreator = _rxCreator;
83 AccessibleGridControl::~AccessibleGridControl()
88 void SAL_CALL AccessibleGridControl::disposing()
90 SolarMutexGuard g;
92 m_xImpl->m_pTable = NULL;
93 m_xImpl->m_pColumnHeaderBar = NULL;
94 m_xImpl->m_pRowHeaderBar = NULL;
95 m_xImpl->m_pCell = NULL;
96 m_xImpl->m_aCreator.clear();
98 Reference< XAccessible > xTable = m_xImpl->m_xTable;
100 Reference< XComponent > xComp( m_xImpl->m_xTable, UNO_QUERY );
101 if ( xComp.is() )
103 xComp->dispose();
105 Reference< XAccessible > xCell = m_xImpl->m_xCell;
107 Reference< XComponent > xCellComp( m_xImpl->m_xCell, UNO_QUERY );
108 if ( xCellComp.is() )
110 xCellComp->dispose();
113 ::comphelper::disposeComponent(m_xImpl->m_xRowHeaderBar);
114 ::comphelper::disposeComponent(m_xImpl->m_xColumnHeaderBar);
115 AccessibleGridControlBase::disposing();
119 // XAccessibleContext ---------------------------------------------------------
121 sal_Int32 SAL_CALL AccessibleGridControl::getAccessibleChildCount()
122 throw ( uno::RuntimeException, std::exception )
124 SolarMutexGuard aSolarGuard;
125 ensureIsAlive();
126 return m_aTable.GetAccessibleControlCount();
130 Reference< XAccessible > SAL_CALL
131 AccessibleGridControl::getAccessibleChild( sal_Int32 nChildIndex )
132 throw ( lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception )
134 SolarMutexGuard aSolarGuard;
136 if (nChildIndex<0 || nChildIndex>=getAccessibleChildCount())
137 throw IndexOutOfBoundsException();
139 Reference< XAccessible > xChild;
140 if (isAlive())
142 if(nChildIndex == 0 && m_aTable.HasColHeader())
144 if(!m_xImpl->m_xColumnHeaderBar.is())
146 AccessibleGridControlHeader* pColHeaderBar = new AccessibleGridControlHeader(m_xImpl->m_aCreator, m_aTable, svt::table::TCTYPE_COLUMNHEADERBAR);
147 m_xImpl->m_xColumnHeaderBar = pColHeaderBar;
149 xChild = m_xImpl->m_xColumnHeaderBar;
151 else if(m_aTable.HasRowHeader() && (nChildIndex == 1 || nChildIndex == 0))
153 if(!m_xImpl->m_xRowHeaderBar.is())
155 AccessibleGridControlHeader* pRowHeaderBar = new AccessibleGridControlHeader(m_xImpl->m_aCreator, m_aTable, svt::table::TCTYPE_ROWHEADERBAR);
156 m_xImpl->m_xRowHeaderBar = pRowHeaderBar;
158 xChild = m_xImpl->m_xRowHeaderBar;
160 else
162 if(!m_xImpl->m_xTable.is())
164 AccessibleGridControlTable* pTable = new AccessibleGridControlTable(m_xImpl->m_aCreator, m_aTable, svt::table::TCTYPE_TABLE);
165 m_xImpl->m_xTable = pTable;
166 m_xImpl->m_pTable = pTable;
168 xChild = m_xImpl->m_xTable;
171 return xChild;
175 sal_Int16 SAL_CALL AccessibleGridControl::getAccessibleRole()
176 throw ( uno::RuntimeException, std::exception )
178 SolarMutexGuard g;
180 ensureIsAlive();
181 return AccessibleRole::PANEL;
185 // XAccessibleComponent -------------------------------------------------------
187 Reference< XAccessible > SAL_CALL
188 AccessibleGridControl::getAccessibleAtPoint( const awt::Point& rPoint )
189 throw ( uno::RuntimeException, std::exception )
191 SolarMutexGuard aSolarGuard;
192 ensureIsAlive();
194 Reference< XAccessible > xChild;
195 sal_Int32 nIndex = 0;
196 if( m_aTable.ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) )
197 xChild = m_aTable.CreateAccessibleControl( nIndex );
198 else
200 // try whether point is in one of the fixed children
201 // (table, header bars, corner control)
202 Point aPoint( VCLPoint( rPoint ) );
203 for( nIndex = 0; (nIndex < 3) && !xChild.is(); ++nIndex )
205 Reference< XAccessible > xCurrChild( implGetFixedChild( nIndex ) );
206 Reference< XAccessibleComponent >
207 xCurrChildComp( xCurrChild, uno::UNO_QUERY );
209 if( xCurrChildComp.is() &&
210 VCLRectangle( xCurrChildComp->getBounds() ).IsInside( aPoint ) )
211 xChild = xCurrChild;
214 return xChild;
218 void SAL_CALL AccessibleGridControl::grabFocus()
219 throw ( uno::RuntimeException, std::exception )
221 SolarMutexGuard aSolarGuard;
222 ensureIsAlive();
223 m_aTable.GrabFocus();
226 // XServiceInfo ---------------------------------------------------------------
228 OUString SAL_CALL AccessibleGridControl::getImplementationName()
229 throw ( uno::RuntimeException, std::exception )
231 return OUString( "com.sun.star.accessibility.AccessibleGridControl" );
235 // internal virtual methods ---------------------------------------------------
237 Rectangle AccessibleGridControl::implGetBoundingBox()
239 vcl::Window* pParent = m_aTable.GetAccessibleParentWindow();
240 OSL_ENSURE( pParent, "implGetBoundingBox - missing parent window" );
241 return m_aTable.GetWindowExtentsRelative( pParent );
245 Rectangle AccessibleGridControl::implGetBoundingBoxOnScreen()
247 return m_aTable.GetWindowExtentsRelative( NULL );
249 // internal helper methods ----------------------------------------------------
251 Reference< XAccessible > AccessibleGridControl::implGetTable()
253 if( !m_xImpl->m_xTable.is() )
255 m_xImpl->m_pTable = createAccessibleTable();
256 m_xImpl->m_xTable = m_xImpl->m_pTable;
258 return m_xImpl->m_xTable;
262 Reference< XAccessible >
263 AccessibleGridControl::implGetHeaderBar( AccessibleTableControlObjType eObjType )
265 Reference< XAccessible > xRet;
266 Reference< XAccessible >* pxMember = NULL;
268 if( eObjType == TCTYPE_ROWHEADERBAR )
269 pxMember = &m_xImpl->m_xRowHeaderBar;
270 else if( eObjType == TCTYPE_COLUMNHEADERBAR )
271 pxMember = &m_xImpl->m_xColumnHeaderBar;
273 if( pxMember )
275 if( !pxMember->is() )
277 AccessibleGridControlHeader* pHeaderBar = new AccessibleGridControlHeader(
278 m_xImpl->m_aCreator, m_aTable, eObjType );
280 if ( TCTYPE_COLUMNHEADERBAR == eObjType)
281 m_xImpl->m_pColumnHeaderBar = pHeaderBar;
282 else
283 m_xImpl->m_pRowHeaderBar = pHeaderBar;
285 *pxMember = pHeaderBar;
287 xRet = *pxMember;
289 return xRet;
292 Reference< XAccessible >
293 AccessibleGridControl::implGetFixedChild( sal_Int32 nChildIndex )
295 Reference< XAccessible > xRet;
296 switch( nChildIndex )
298 case TCINDEX_COLUMNHEADERBAR:
299 xRet = implGetHeaderBar( TCTYPE_COLUMNHEADERBAR );
300 break;
301 case TCINDEX_ROWHEADERBAR:
302 xRet = implGetHeaderBar( TCTYPE_ROWHEADERBAR );
303 break;
304 case TCINDEX_TABLE:
305 xRet = implGetTable();
306 break;
308 return xRet;
311 AccessibleGridControlTable* AccessibleGridControl::createAccessibleTable()
313 Reference< XAccessible > xCreator(m_xImpl->m_aCreator);
314 OSL_ENSURE( xCreator.is(), "accessibility/extended/AccessibleGirdControl::createAccessibleTable: my creator died - how this?" );
315 return new AccessibleGridControlTable( xCreator, m_aTable, TCTYPE_TABLE );
318 void AccessibleGridControl::commitCellEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
320 sal_Int32 nChildCount = getAccessibleChildCount();
321 if(nChildCount != 0)
323 for(sal_Int32 i=0;i<nChildCount;i++)
325 Reference< XAccessible > xAccessible = getAccessibleChild(i);
326 com::sun::star::uno::Reference< com::sun::star::accessibility::XAccessibleContext > xAccessibleChild = xAccessible->getAccessibleContext();
327 if(m_xImpl->m_xTable == xAccessible)
329 std::vector< AccessibleGridControlTableCell* >& rCells =
330 m_xImpl->m_pTable->getCellVector();
331 size_t nIndex = m_aTable.GetCurrentRow() * m_aTable.GetColumnCount()
332 + m_aTable.GetCurrentColumn();
333 if (nIndex < rCells.size() && rCells[nIndex])
335 m_xImpl->m_pCell = rCells[nIndex];
336 m_xImpl->m_pCell->commitEvent( _nEventId, _rNewValue, _rOldValue );
341 else
343 if ( m_xImpl->m_xTable.is() )
344 m_xImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
348 void AccessibleGridControl::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
350 if ( m_xImpl->m_xTable.is() )
352 if(_nEventId == AccessibleEventId::ACTIVE_DESCENDANT_CHANGED)
354 Reference< XAccessible > xChild = m_xImpl->m_pTable->getAccessibleChild(m_aTable.GetCurrentRow()*m_aTable.GetColumnCount()+m_aTable.GetCurrentColumn());
355 m_xImpl->m_pTable->commitEvent(_nEventId, makeAny(xChild),_rOldValue);
357 else if(_nEventId == AccessibleEventId::TABLE_MODEL_CHANGED)
359 AccessibleTableModelChange aChange;
360 if(_rNewValue >>= aChange)
362 if(aChange.Type == AccessibleTableModelChangeType::DELETE)
364 std::vector< AccessibleGridControlTableCell* >& rCells =
365 m_xImpl->m_pTable->getCellVector();
366 std::vector< Reference< XAccessible > >& rAccCells =
367 m_xImpl->m_pTable->getAccessibleCellVector();
368 int nColCount = m_aTable.GetColumnCount();
369 // check valid index - entries are inserted lazily
370 size_t const nStart = nColCount * aChange.FirstRow;
371 size_t const nEnd = nColCount * aChange.LastRow;
372 if (nStart < rCells.size())
374 m_xImpl->m_pTable->getCellVector().erase(
375 rCells.begin() + nStart,
376 rCells.begin() + std::min(rCells.size(), nEnd));
378 if (nStart < rAccCells.size())
380 m_xImpl->m_pTable->getAccessibleCellVector().erase(
381 rAccCells.begin() + nStart,
382 rAccCells.begin() + std::min(rAccCells.size(), nEnd));
384 m_xImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
386 else
387 m_xImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
390 else
391 m_xImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
395 // = AccessibleGridControlAccess
399 AccessibleGridControlAccess::AccessibleGridControlAccess(
400 const Reference< XAccessible >& rxParent, IAccessibleTable& rTable )
401 : m_xParent( rxParent )
402 , m_pTable( & rTable )
403 , m_pContext( 0 )
408 AccessibleGridControlAccess::~AccessibleGridControlAccess()
413 void AccessibleGridControlAccess::DisposeAccessImpl()
415 SolarMutexGuard g;
417 m_pTable = 0;
418 m_pContext = NULL;
419 ::comphelper::disposeComponent( m_xContext );
423 Reference< XAccessibleContext > SAL_CALL AccessibleGridControlAccess::getAccessibleContext() throw ( RuntimeException, std::exception )
425 SolarMutexGuard g;
427 OSL_ENSURE( ( m_pContext && m_xContext.is() ) || ( !m_pContext && !m_xContext.is() ),
428 "accessibility/extended/AccessibleGridControlAccess::getAccessibleContext: inconsistency!" );
430 // if the context died meanwhile (we're no listener, so it won't tell us explicitily when this happens),
431 // then reset an re-create.
432 if ( m_pContext && !m_pContext->isAlive() )
433 m_xContext = m_pContext = NULL;
435 if (!m_xContext.is() && m_pTable)
436 m_xContext = m_pContext =
437 new AccessibleGridControl(m_xParent, this, *m_pTable);
439 return m_xContext;
443 bool AccessibleGridControlAccess::isContextAlive() const
445 return ( NULL != m_pContext ) && m_pContext->isAlive();
450 } // namespace accessibility
452 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */