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 #include "accessibility/extended/AccessibleGridControl.hxx"
27 #include "accessibility/extended/AccessibleGridControlTable.hxx"
28 #include "accessibility/extended/AccessibleGridControlHeader.hxx"
29 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
30 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
31 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
32 #include <svtools/accessibletable.hxx>
33 #include <comphelper/types.hxx>
34 #include <toolkit/helper/vclunohelper.hxx>
35
36 // ============================================================================
37
38 namespace accessibility
39 {
40
41 // ============================================================================
42
43 using ::rtl::OUString;
44
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::accessibility;
49 using namespace ::svt;
50 using namespace ::svt::table;
51
52 // ============================================================================
53 class AccessibleGridControl_Impl
54 {
55 public:
56 /// the XAccessible which created the AccessibleGridControl
57 WeakReference< XAccessible > m_aCreator;
58
59 /** The data table child. */
60 Reference<
61 ::com::sun::star::accessibility::XAccessible > m_xTable;
62 AccessibleGridControlTable* m_pTable;
63
64 /** The header bar for rows. */
65 Reference<
66 ::com::sun::star::accessibility::XAccessible > m_xRowHeaderBar;
67 AccessibleGridControlHeader* m_pRowHeaderBar;
68
69 /** The header bar for columns (first row of the table). */
70 Reference<
71 ::com::sun::star::accessibility::XAccessible > m_xColumnHeaderBar;
72 AccessibleGridControlHeader* m_pColumnHeaderBar;
73
74 /** The table cell child. */
75 Reference<
76 ::com::sun::star::accessibility::XAccessible > m_xCell;
77 AccessibleGridControlTableCell* m_pCell;
78 };
79
DBG_NAME(AccessibleGridControl)80 DBG_NAME( AccessibleGridControl )
81
82 AccessibleGridControl::AccessibleGridControl(
83 const Reference< XAccessible >& _rxParent, const Reference< XAccessible >& _rxCreator,
84 IAccessibleTable& _rTable )
85 : AccessibleGridControlBase( _rxParent, _rTable, TCTYPE_GRIDCONTROL )
86 {
87 m_pImpl.reset( new AccessibleGridControl_Impl() );
88 m_pImpl->m_aCreator = _rxCreator;
89 }
90
91 // -----------------------------------------------------------------------------
~AccessibleGridControl()92 AccessibleGridControl::~AccessibleGridControl()
93 {
94 }
95 // -----------------------------------------------------------------------------
96
disposing()97 void SAL_CALL AccessibleGridControl::disposing()
98 {
99 ::osl::MutexGuard aGuard( getOslMutex() );
100
101 m_pImpl->m_pTable = NULL;
102 m_pImpl->m_pColumnHeaderBar = NULL;
103 m_pImpl->m_pRowHeaderBar = NULL;
104 m_pImpl->m_pCell = NULL;
105 m_pImpl->m_aCreator = Reference< XAccessible >();
106
107 Reference< XAccessible > xTable = m_pImpl->m_xTable;
108
109 Reference< XComponent > xComp( m_pImpl->m_xTable, UNO_QUERY );
110 if ( xComp.is() )
111 {
112 xComp->dispose();
113 }
114 Reference< XAccessible > xCell = m_pImpl->m_xCell;
115
116 Reference< XComponent > xCellComp( m_pImpl->m_xCell, UNO_QUERY );
117 if ( xCellComp.is() )
118 {
119 xCellComp->dispose();
120 }
121
122 ::comphelper::disposeComponent(m_pImpl->m_xRowHeaderBar);
123 ::comphelper::disposeComponent(m_pImpl->m_xColumnHeaderBar);
124 AccessibleGridControlBase::disposing();
125 }
126 // -----------------------------------------------------------------------------
127
128 // XAccessibleContext ---------------------------------------------------------
129
getAccessibleChildCount()130 sal_Int32 SAL_CALL AccessibleGridControl::getAccessibleChildCount()
131 throw ( uno::RuntimeException )
132 {
133 TCSolarGuard aSolarGuard;
134 ::osl::MutexGuard aGuard( getOslMutex() );
135 ensureIsAlive();
136 return m_aTable.GetAccessibleControlCount();
137 }
138 // -----------------------------------------------------------------------------
139
140 Reference< XAccessible > SAL_CALL
getAccessibleChild(sal_Int32 nChildIndex)141 AccessibleGridControl::getAccessibleChild( sal_Int32 nChildIndex )
142 throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
143 {
144 TCSolarGuard aSolarGuard;
145 ::osl::MutexGuard aGuard( getOslMutex() );
146
147 if (nChildIndex<0 || nChildIndex>=getAccessibleChildCount())
148 throw IndexOutOfBoundsException();
149
150 Reference< XAccessible > xChild;
151 if (isAlive())
152 {
153 if(nChildIndex == 0 && m_aTable.HasColHeader())
154 {
155 if(!m_pImpl->m_xColumnHeaderBar.is())
156 {
157 AccessibleGridControlHeader* pColHeaderBar = new AccessibleGridControlHeader(m_pImpl->m_aCreator, m_aTable, svt::table::TCTYPE_COLUMNHEADERBAR);
158 m_pImpl->m_xColumnHeaderBar = pColHeaderBar;
159 }
160 xChild = m_pImpl->m_xColumnHeaderBar;
161 }
162 else if(m_aTable.HasRowHeader() && (nChildIndex == 1 || nChildIndex == 0))
163 {
164 if(!m_pImpl->m_xRowHeaderBar.is())
165 {
166 AccessibleGridControlHeader* pRowHeaderBar = new AccessibleGridControlHeader(m_pImpl->m_aCreator, m_aTable, svt::table::TCTYPE_ROWHEADERBAR);
167 m_pImpl->m_xRowHeaderBar = pRowHeaderBar;
168 }
169 xChild = m_pImpl->m_xRowHeaderBar;
170 }
171 else
172 {
173 if(!m_pImpl->m_xTable.is())
174 {
175 AccessibleGridControlTable* pTable = new AccessibleGridControlTable(m_pImpl->m_aCreator, m_aTable, svt::table::TCTYPE_TABLE);
176 m_pImpl->m_xTable = pTable;
177 m_pImpl->m_pTable = pTable;
178 }
179 xChild = m_pImpl->m_xTable;
180 }
181 }
182 return xChild;
183 }
184 // -----------------------------------------------------------------------------
185
getAccessibleRole()186 sal_Int16 SAL_CALL AccessibleGridControl::getAccessibleRole()
187 throw ( uno::RuntimeException )
188 {
189 ensureIsAlive();
190 return AccessibleRole::PANEL;
191 }
192 // -----------------------------------------------------------------------------
193
194 // XAccessibleComponent -------------------------------------------------------
195
196 Reference< XAccessible > SAL_CALL
getAccessibleAtPoint(const awt::Point & rPoint)197 AccessibleGridControl::getAccessibleAtPoint( const awt::Point& rPoint )
198 throw ( uno::RuntimeException )
199 {
200 TCSolarGuard aSolarGuard;
201 ::osl::MutexGuard aGuard( getOslMutex() );
202 ensureIsAlive();
203
204 Reference< XAccessible > xChild;
205 sal_Int32 nIndex = 0;
206 if( m_aTable.ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) )
207 xChild = m_aTable.CreateAccessibleControl( nIndex );
208 else
209 {
210 // try whether point is in one of the fixed children
211 // (table, header bars, corner control)
212 Point aPoint( VCLPoint( rPoint ) );
213 for( nIndex = 0; (nIndex < 3) && !xChild.is(); ++nIndex )
214 {
215 Reference< XAccessible > xCurrChild( implGetFixedChild( nIndex ) );
216 Reference< XAccessibleComponent >
217 xCurrChildComp( xCurrChild, uno::UNO_QUERY );
218
219 if( xCurrChildComp.is() &&
220 VCLRectangle( xCurrChildComp->getBounds() ).IsInside( aPoint ) )
221 xChild = xCurrChild;
222 }
223 }
224 return xChild;
225 }
226 // -----------------------------------------------------------------------------
227
grabFocus()228 void SAL_CALL AccessibleGridControl::grabFocus()
229 throw ( uno::RuntimeException )
230 {
231 TCSolarGuard aSolarGuard;
232 ::osl::MutexGuard aGuard( getOslMutex() );
233 ensureIsAlive();
234 m_aTable.GrabFocus();
235 }
236 // -----------------------------------------------------------------------------
237
getAccessibleKeyBinding()238 Any SAL_CALL AccessibleGridControl::getAccessibleKeyBinding()
239 throw ( uno::RuntimeException )
240 {
241 ensureIsAlive();
242 return Any();
243 }
244 // -----------------------------------------------------------------------------
245
246 // XServiceInfo ---------------------------------------------------------------
247
getImplementationName()248 OUString SAL_CALL AccessibleGridControl::getImplementationName()
249 throw ( uno::RuntimeException )
250 {
251 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleGridControl" ) );
252 }
253 // -----------------------------------------------------------------------------
254
255 // internal virtual methods ---------------------------------------------------
256
implGetBoundingBox()257 Rectangle AccessibleGridControl::implGetBoundingBox()
258 {
259 Window* pParent = m_aTable.GetAccessibleParentWindow();
260 DBG_ASSERT( pParent, "implGetBoundingBox - missing parent window" );
261 return m_aTable.GetWindowExtentsRelative( pParent );
262 }
263 // -----------------------------------------------------------------------------
264
implGetBoundingBoxOnScreen()265 Rectangle AccessibleGridControl::implGetBoundingBoxOnScreen()
266 {
267 return m_aTable.GetWindowExtentsRelative( NULL );
268 }
269 // internal helper methods ----------------------------------------------------
270
implGetTable()271 Reference< XAccessible > AccessibleGridControl::implGetTable()
272 {
273 if( !m_pImpl->m_xTable.is() )
274 {
275 m_pImpl->m_pTable = createAccessibleTable();
276 m_pImpl->m_xTable = m_pImpl->m_pTable;
277 }
278 return m_pImpl->m_xTable;
279 }
280 // -----------------------------------------------------------------------------
281
282 Reference< XAccessible >
implGetHeaderBar(AccessibleTableControlObjType eObjType)283 AccessibleGridControl::implGetHeaderBar( AccessibleTableControlObjType eObjType )
284 {
285 Reference< XAccessible > xRet;
286 Reference< XAccessible >* pxMember = NULL;
287
288 if( eObjType == TCTYPE_ROWHEADERBAR )
289 pxMember = &m_pImpl->m_xRowHeaderBar;
290 else if( eObjType == TCTYPE_COLUMNHEADERBAR )
291 pxMember = &m_pImpl->m_xColumnHeaderBar;
292
293 if( pxMember )
294 {
295 if( !pxMember->is() )
296 {
297 AccessibleGridControlHeader* pHeaderBar = new AccessibleGridControlHeader(
298 (Reference< XAccessible >)m_pImpl->m_aCreator, m_aTable, eObjType );
299
300 if ( TCTYPE_COLUMNHEADERBAR == eObjType)
301 m_pImpl->m_pColumnHeaderBar = pHeaderBar;
302 else
303 m_pImpl->m_pRowHeaderBar = pHeaderBar;
304
305 *pxMember = pHeaderBar;
306 }
307 xRet = *pxMember;
308 }
309 return xRet;
310 }
311 // -----------------------------------------------------------------------------
312 Reference< XAccessible >
implGetFixedChild(sal_Int32 nChildIndex)313 AccessibleGridControl::implGetFixedChild( sal_Int32 nChildIndex )
314 {
315 Reference< XAccessible > xRet;
316 switch( nChildIndex )
317 {
318 case TCINDEX_COLUMNHEADERBAR:
319 xRet = implGetHeaderBar( TCTYPE_COLUMNHEADERBAR );
320 break;
321 case TCINDEX_ROWHEADERBAR:
322 xRet = implGetHeaderBar( TCTYPE_ROWHEADERBAR );
323 break;
324 case TCINDEX_TABLE:
325 xRet = implGetTable();
326 break;
327 }
328 return xRet;
329 }
330 // -----------------------------------------------------------------------------
createAccessibleTable()331 AccessibleGridControlTable* AccessibleGridControl::createAccessibleTable()
332 {
333 Reference< XAccessible > xCreator = (Reference< XAccessible >)m_pImpl->m_aCreator;
334 DBG_ASSERT( xCreator.is(), "accessibility/extended/AccessibleGirdControl::createAccessibleTable: my creator died - how this?" );
335 return new AccessibleGridControlTable( xCreator, m_aTable, TCTYPE_TABLE );
336 }
337 // -----------------------------------------------------------------------------
commitCellEvent(sal_Int16 _nEventId,const Any & _rNewValue,const Any & _rOldValue)338 void AccessibleGridControl::commitCellEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
339 {
340 sal_Int32 nChildCount = getAccessibleChildCount();
341 if(nChildCount != 0)
342 {
343 for(sal_Int32 i=0;i<nChildCount;i++)
344 {
345 Reference< XAccessible > xAccessible = getAccessibleChild(i);
346 com::sun::star::uno::Reference< com::sun::star::accessibility::XAccessibleContext > xAccessibleChild = xAccessible->getAccessibleContext();
347 if(m_pImpl->m_xTable == xAccessible)
348 {
349 std::vector< AccessibleGridControlTableCell* > xCellCont = m_pImpl->m_pTable->getCellVector();
350 int nIndex = m_aTable.GetCurrentRow()*m_aTable.GetColumnCount()+m_aTable.GetCurrentColumn();
351 if(!xCellCont.empty() && xCellCont[nIndex])
352 {
353 m_pImpl->m_pCell = xCellCont[nIndex];
354 m_pImpl->m_pCell->commitEvent( _nEventId, _rNewValue, _rOldValue );
355 }
356 }
357 }
358 }
359 else
360 {
361 if ( m_pImpl->m_xTable.is() )
362 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
363 }
364 }
commitTableEvent(sal_Int16 _nEventId,const Any & _rNewValue,const Any & _rOldValue)365 void AccessibleGridControl::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
366 {
367 if ( m_pImpl->m_xTable.is() )
368 {
369 if(_nEventId == AccessibleEventId::ACTIVE_DESCENDANT_CHANGED)
370 {
371 Reference< XAccessible > xChild = m_pImpl->m_pTable->getAccessibleChild(m_aTable.GetCurrentRow()*m_aTable.GetColumnCount()+m_aTable.GetCurrentColumn());
372 m_pImpl->m_pTable->commitEvent(_nEventId, makeAny(xChild),_rOldValue);
373 }
374 else if(_nEventId == AccessibleEventId::TABLE_MODEL_CHANGED)
375 {
376 AccessibleTableModelChange aChange;
377 if(_rNewValue >>= aChange)
378 {
379 if(aChange.Type == AccessibleTableModelChangeType::DELETE)
380 {
381 std::vector< AccessibleGridControlTableCell* >::iterator m_pCell = m_pImpl->m_pTable->getCellVector().begin();
382 std::vector< Reference< XAccessible > >::iterator m_xAccessibleVector = m_pImpl->m_pTable->getAccessibleCellVector().begin();
383 int nColCount = m_aTable.GetColumnCount();
384 m_pImpl->m_pTable->getCellVector().erase(m_pCell+nColCount*aChange.FirstRow, m_pCell+nColCount*aChange.LastRow );
385 m_pImpl->m_pTable->getAccessibleCellVector().erase(m_xAccessibleVector+nColCount*aChange.FirstRow, m_xAccessibleVector+nColCount*aChange.LastRow);
386 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
387 }
388 else
389 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
390 }
391 }
392 else
393 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
394 }
395 }
396 // ============================================================================
397 // = AccessibleGridControlAccess
398 // ============================================================================
DBG_NAME(AccessibleGridControlAccess)399 DBG_NAME( AccessibleGridControlAccess )
400 // -----------------------------------------------------------------------------
401 AccessibleGridControlAccess::AccessibleGridControlAccess( const Reference< XAccessible >& _rxParent, IAccessibleTable& _rTable )
402 :m_xParent( _rxParent )
403 ,m_rTable( _rTable )
404 ,m_pContext( NULL )
405 {
406 }
407
408 // -----------------------------------------------------------------------------
~AccessibleGridControlAccess()409 AccessibleGridControlAccess::~AccessibleGridControlAccess()
410 {
411 }
412
413 // -----------------------------------------------------------------------------
dispose()414 void AccessibleGridControlAccess::dispose()
415 {
416 ::osl::MutexGuard aGuard( m_aMutex );
417
418 m_pContext = NULL;
419 ::comphelper::disposeComponent( m_xContext );
420 }
421
422 // -----------------------------------------------------------------------------
getAccessibleContext()423 Reference< XAccessibleContext > SAL_CALL AccessibleGridControlAccess::getAccessibleContext() throw ( RuntimeException )
424 {
425 ::osl::MutexGuard aGuard( m_aMutex );
426
427 DBG_ASSERT( ( m_pContext && m_xContext.is() ) || ( !m_pContext && !m_xContext.is() ),
428 "accessibility/extended/AccessibleGridControlAccess::getAccessibleContext: inconsistency!" );
429
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;
434
435 if ( !m_xContext.is() )
436 m_xContext = m_pContext = new AccessibleGridControl( m_xParent, this, m_rTable );
437
438 return m_xContext;
439 }
440
441 // -----------------------------------------------------------------------------
isContextAlive() const442 bool AccessibleGridControlAccess::isContextAlive() const
443 {
444 return ( NULL != m_pContext ) && m_pContext->isAlive();
445 }
446
447 // ============================================================================
448
449 } // namespace accessibility
450