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