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 
28 #include "accessibility/extended/AccessibleGridControlTable.hxx"
29 #include "accessibility/extended/AccessibleGridControlTableCell.hxx"
30 #include <svtools/accessibletable.hxx>
31 
32 // ============================================================================
33 
34 using ::rtl::OUString;
35 
36 using ::com::sun::star::uno::Reference;
37 using ::com::sun::star::uno::Sequence;
38 using ::com::sun::star::uno::Any;
39 
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::accessibility;
42 using namespace ::svt;
43 using namespace ::svt::table;
44 // ============================================================================
45 
46 namespace accessibility {
47 
48 // ============================================================================
49 
50 DBG_NAME( AccessibleGridControlTable )
51 
52 AccessibleGridControlTable::AccessibleGridControlTable(
53         const Reference< XAccessible >& rxParent,
54         IAccessibleTable& rTable,
55 		AccessibleTableControlObjType _eType) :
56     AccessibleGridControlTableBase( rxParent, rTable, _eType )
57 		,m_pCellVector( )
58 		,m_pAccessCellVector( )
59 {
60 }
61 
62 AccessibleGridControlTable::~AccessibleGridControlTable()
63 {
64 }
65 
66 // XAccessibleContext ---------------------------------------------------------
67 
68 Reference< XAccessible > SAL_CALL
69 AccessibleGridControlTable::getAccessibleChild( sal_Int32 nChildIndex )
70     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
71 {
72     TCSolarGuard aSolarGuard;
73     ::osl::MutexGuard aGuard( getOslMutex() );
74     ensureIsAlive();
75     ensureIsValidIndex( nChildIndex );
76 	sal_Int32 nCount = getAccessibleChildCount();
77 	if(m_pAccessCellVector.size() == 0 || m_pAccessCellVector.size() != (unsigned)nCount)
78 	{
79 		m_pAccessCellVector.resize(nCount);
80 		m_pCellVector.resize(nCount);
81 	}
82 	if(!m_pAccessCellVector[nChildIndex].is())
83 	{
84 		AccessibleGridControlTableCell* pCell = new AccessibleGridControlTableCell(this, m_aTable, nChildIndex/m_aTable.GetColumnCount(), nChildIndex%m_aTable.GetColumnCount(), TCTYPE_TABLECELL);
85 		m_pCellVector[nChildIndex] = pCell;
86 		m_pAccessCellVector[nChildIndex] = pCell;
87 	}
88 	return m_pAccessCellVector[nChildIndex];
89 }
90 
91 sal_Int32 SAL_CALL AccessibleGridControlTable::getAccessibleIndexInParent()
92     throw ( uno::RuntimeException )
93 {
94     ensureIsAlive();
95     if(m_aTable.HasRowHeader() && m_aTable.HasColHeader())
96 	    return 0;
97     else if((!m_aTable.HasRowHeader() && m_aTable.HasColHeader()) || (m_aTable.HasRowHeader() && !m_aTable.HasColHeader()) )
98 	    return 1;
99     else
100 	    return 2;
101 }
102 
103 // XAccessibleComponent -------------------------------------------------------
104 
105 Reference< XAccessible > SAL_CALL
106 AccessibleGridControlTable::getAccessibleAtPoint( const awt::Point& rPoint )
107     throw ( uno::RuntimeException )
108 {
109     TCSolarGuard aSolarGuard;
110     ::osl::MutexGuard aGuard( getOslMutex() );
111     ensureIsAlive();
112 
113     Reference< XAccessible > xChild;
114     sal_Int32 nRow = 0;
115     sal_Int32 nColumnPos = 0;
116     if( m_aTable.ConvertPointToCellAddress( nRow, nColumnPos, VCLPoint( rPoint ) ) )
117         xChild = new AccessibleGridControlTableCell(this, m_aTable, nRow, nColumnPos, TCTYPE_TABLECELL);
118     return xChild;
119 }
120 
121 void SAL_CALL AccessibleGridControlTable::grabFocus()
122     throw ( uno::RuntimeException )
123 {
124     TCSolarGuard aSolarGuard;
125     ::osl::MutexGuard aGuard( getOslMutex() );
126     ensureIsAlive();
127     m_aTable.GrabFocus();
128 }
129 
130 Any SAL_CALL AccessibleGridControlTable::getAccessibleKeyBinding()
131     throw ( uno::RuntimeException )
132 {
133     ensureIsAlive();
134     return Any();   // no special key bindings for data table
135 }
136 
137 // XAccessibleTable -----------------------------------------------------------
138 
139 OUString SAL_CALL AccessibleGridControlTable::getAccessibleRowDescription( sal_Int32 nRow )
140     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
141 {
142     TCSolarGuard aSolarGuard;
143     ::osl::MutexGuard aGuard( getOslMutex() );
144     ensureIsAlive();
145     ensureIsValidRow( nRow );
146     return m_aTable.GetRowDescription( nRow );
147 }
148 
149 OUString SAL_CALL AccessibleGridControlTable::getAccessibleColumnDescription( sal_Int32 nColumn )
150     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
151 {
152     TCSolarGuard aSolarGuard;
153     ::osl::MutexGuard aGuard( getOslMutex() );
154     ensureIsAlive();
155     ensureIsValidColumn( nColumn );
156     return m_aTable.GetColumnDescription( (sal_uInt16)nColumn );
157 }
158 
159 Reference< XAccessibleTable > SAL_CALL AccessibleGridControlTable::getAccessibleRowHeaders()
160     throw ( uno::RuntimeException )
161 {
162     ::osl::MutexGuard aGuard( getOslMutex() );
163     ensureIsAlive();
164     if(m_aTable.HasColHeader())
165 	    return implGetHeaderBar( 1 );
166     else
167 	    return implGetHeaderBar( 0 );
168 }
169 
170 Reference< XAccessibleTable > SAL_CALL AccessibleGridControlTable::getAccessibleColumnHeaders()
171     throw ( uno::RuntimeException )
172 {
173     ::osl::MutexGuard aGuard( getOslMutex() );
174     ensureIsAlive();
175     return implGetHeaderBar( 0 );
176 }
177 
178 Sequence< sal_Int32 > SAL_CALL AccessibleGridControlTable::getSelectedAccessibleRows()
179     throw ( uno::RuntimeException )
180 {
181     TCSolarGuard aSolarGuard;
182     ::osl::MutexGuard aGuard( getOslMutex() );
183     ensureIsAlive();
184     Sequence< sal_Int32 > aSelSeq;
185     implGetSelectedRows( aSelSeq );
186     return aSelSeq;
187 }
188 
189 //columns aren't selectable
190 Sequence< sal_Int32 > SAL_CALL AccessibleGridControlTable::getSelectedAccessibleColumns()
191     throw ( uno::RuntimeException )
192 {
193 	Sequence< sal_Int32 > aSelSeq(0);
194 	return aSelSeq;
195 }
196 
197 sal_Bool SAL_CALL AccessibleGridControlTable::isAccessibleRowSelected( sal_Int32 nRow )
198     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
199 {
200     TCSolarGuard aSolarGuard;
201     ::osl::MutexGuard aGuard( getOslMutex() );
202     ensureIsAlive();
203     ensureIsValidRow( nRow );
204     sal_Bool bSelected = sal_False;
205     Sequence< sal_Int32 > selectedRows = getSelectedAccessibleRows();
206     for(int i=0; i<selectedRows.getLength(); i++)
207     {
208 	    if(nRow == selectedRows[i])
209 	    {
210 		    bSelected = sal_True;
211 		    continue;
212 	    }
213     }
214     return bSelected;
215 }
216 
217 //columns aren't selectable
218 sal_Bool SAL_CALL AccessibleGridControlTable::isAccessibleColumnSelected( sal_Int32 nColumn )
219     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
220 {
221     (void) nColumn;
222     return sal_False;
223 }
224 
225 Reference< XAccessible > SAL_CALL AccessibleGridControlTable::getAccessibleCellAt(
226         sal_Int32 nRow, sal_Int32 nColumn )
227     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
228 {
229     TCSolarGuard aSolarGuard;
230     ::osl::MutexGuard aGuard( getOslMutex() );
231     ensureIsAlive();
232     ensureIsValidAddress( nRow, nColumn );
233 	sal_Int32 nCount = getAccessibleChildCount();
234 	sal_Int32 nChildIndex = nRow*m_aTable.GetColumnCount() + nColumn;
235 	if(m_pAccessCellVector.size() == 0 || m_pAccessCellVector.size() != (unsigned)nCount)
236 	{
237 		m_pAccessCellVector.resize(nCount);
238 		m_pCellVector.resize(nCount);
239 	}
240 	if(!m_pAccessCellVector[nChildIndex].is())
241 	{
242 		AccessibleGridControlTableCell* pCell = new AccessibleGridControlTableCell(this, m_aTable, nRow, nColumn, TCTYPE_TABLECELL);
243 		m_pCellVector[nChildIndex] = pCell;
244 		m_pAccessCellVector[nChildIndex] = pCell;
245 	}
246 	return m_pAccessCellVector[nChildIndex];
247 }
248 
249 sal_Bool SAL_CALL AccessibleGridControlTable::isAccessibleSelected(
250         sal_Int32 nRow, sal_Int32 nColumn )
251     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
252 {
253     TCSolarGuard aSolarGuard;
254     ::osl::MutexGuard aGuard( getOslMutex() );
255     ensureIsAlive();
256     ensureIsValidAddress( nRow, nColumn );
257     (void) nColumn;
258     //selection of single cells not possible, so if row is selected, the cell will be selected too
259     return isAccessibleRowSelected(nRow);
260 }
261 void SAL_CALL AccessibleGridControlTable::selectAccessibleChild( sal_Int32 nChildIndex )
262     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
263 {
264     TCSolarGuard aSolarGuard;
265     ::osl::MutexGuard aGuard( getOslMutex() );
266     ensureIsAlive();
267     ensureIsValidIndex( nChildIndex );
268     sal_Int32 nColumns = m_aTable.GetColumnCount();
269     sal_Int32 nRow = (nChildIndex / nColumns);
270     m_aTable.SelectRow( nRow, sal_True );
271 }
272 sal_Bool SAL_CALL AccessibleGridControlTable::isAccessibleChildSelected( sal_Int32 nChildIndex )
273     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
274 {
275     TCSolarGuard aSolarGuard;
276     ::osl::MutexGuard aGuard( getOslMutex() );
277     ensureIsAlive();
278     ensureIsValidIndex( nChildIndex );
279     sal_Int32 nColumns = m_aTable.GetColumnCount();
280     sal_Int32 nRow = (nChildIndex / nColumns);
281     return isAccessibleRowSelected(nRow);
282 }
283 void SAL_CALL AccessibleGridControlTable::clearAccessibleSelection()
284     throw ( uno::RuntimeException )
285 {
286     TCSolarGuard aSolarGuard;
287     ::osl::MutexGuard aGuard( getOslMutex() );
288     ensureIsAlive();
289     m_aTable.SelectAllRows( false );
290 }
291 void SAL_CALL AccessibleGridControlTable::selectAllAccessibleChildren()
292     throw ( uno::RuntimeException )
293 {
294     TCSolarGuard aSolarGuard;
295     ::osl::MutexGuard aGuard( getOslMutex() );
296     ensureIsAlive();
297     Sequence< sal_Int32 > selectedRows = getSelectedAccessibleRows();
298     for(int i=0;i<m_aTable.GetRowCount();i++)
299 	    selectedRows[i]=i;
300 }
301 sal_Int32 SAL_CALL AccessibleGridControlTable::getSelectedAccessibleChildCount()
302     throw ( uno::RuntimeException )
303 {
304     TCSolarGuard aSolarGuard;
305     ::osl::MutexGuard aGuard( getOslMutex() );
306     ensureIsAlive();
307     Sequence< sal_Int32 > selectedRows = getSelectedAccessibleRows();
308     sal_Int32 nColumns = m_aTable.GetColumnCount();
309     return selectedRows.getLength()*nColumns;
310 }
311 Reference< XAccessible > SAL_CALL
312 AccessibleGridControlTable::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
313     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
314 {
315     TCSolarGuard aSolarGuard;
316     ::osl::MutexGuard aGuard( getOslMutex() );
317     ensureIsAlive();
318     if(isAccessibleChildSelected(nSelectedChildIndex))
319 	    return getAccessibleChild(nSelectedChildIndex);
320     else
321 	    return NULL;
322 }
323 //not implemented yet, because only row selection possible
324 void SAL_CALL AccessibleGridControlTable::deselectAccessibleChild(
325         sal_Int32 nSelectedChildIndex )
326     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
327 {
328     TCSolarGuard aSolarGuard;
329     ::osl::MutexGuard aGuard( getOslMutex() );
330     ensureIsAlive();
331     (void)nSelectedChildIndex;
332 }
333 // XInterface -----------------------------------------------------------------
334 
335 Any SAL_CALL AccessibleGridControlTable::queryInterface( const uno::Type& rType )
336     throw ( uno::RuntimeException )
337 {
338     Any aAny( AccessibleGridControlTableBase::queryInterface( rType ) );
339     return aAny.hasValue() ?
340     	aAny : AccessibleGridControlTableImplHelper1::queryInterface( rType );
341 }
342 
343 void SAL_CALL AccessibleGridControlTable::acquire() throw ()
344 {
345     AccessibleGridControlTableBase::acquire();
346 }
347 
348 void SAL_CALL AccessibleGridControlTable::release() throw ()
349 {
350     AccessibleGridControlTableBase::release();
351 }
352 // XServiceInfo ---------------------------------------------------------------
353 
354 OUString SAL_CALL AccessibleGridControlTable::getImplementationName()
355     throw ( uno::RuntimeException )
356 {
357     return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleGridControlTable" ) );
358 }
359 
360 // internal virtual methods ---------------------------------------------------
361 
362 Rectangle AccessibleGridControlTable::implGetBoundingBox()
363 {
364 	Window* pParent = m_aTable.GetAccessibleParentWindow();
365 	DBG_ASSERT( pParent, "implGetBoundingBox - missing parent window" );
366 	Rectangle aGridRect( m_aTable.GetWindowExtentsRelative( pParent ));
367 	Rectangle aTableRect( m_aTable.calcTableRect() );
368 	long nX = aGridRect.Left() + aTableRect.Left();
369 	long nY = aGridRect.Top() + aTableRect.Top();
370 	long nWidth = aGridRect.GetSize().Width()-aTableRect.Left();
371 	long nHeight = aGridRect.GetSize().Height()-aTableRect.Top();
372 	Rectangle aTable( Point( nX, nY ), Size( nWidth, nHeight ));
373     return aTable;
374 }
375 
376 Rectangle AccessibleGridControlTable::implGetBoundingBoxOnScreen()
377 {
378 	Rectangle aGridRect( m_aTable.GetWindowExtentsRelative( NULL ));
379 	Rectangle aTableRect( m_aTable.calcTableRect() );
380 	long nX = aGridRect.Left() + aTableRect.Left();
381 	long nY = aGridRect.Top() + aTableRect.Top();
382 	long nWidth = aGridRect.GetSize().Width()-aTableRect.Left();
383 	long nHeight = aGridRect.GetSize().Height()-aTableRect.Top();
384 	Rectangle aTable( Point( nX, nY ), Size( nWidth, nHeight ));
385     return aTable;
386 }
387 // internal helper methods ----------------------------------------------------
388 Reference< XAccessibleTable > AccessibleGridControlTable::implGetHeaderBar(
389         sal_Int32 nChildIndex )
390     throw ( uno::RuntimeException )
391 {
392     Reference< XAccessible > xRet;
393     Reference< XAccessibleContext > xContext( m_xParent, uno::UNO_QUERY );
394     if( xContext.is() )
395     {
396         try
397         {
398             xRet = xContext->getAccessibleChild( nChildIndex );
399         }
400         catch( lang::IndexOutOfBoundsException& )
401         {
402             DBG_ERROR( "implGetHeaderBar - wrong child index" );
403         }
404         // RuntimeException goes to caller
405     }
406     return Reference< XAccessibleTable >( xRet, uno::UNO_QUERY );
407 }
408 
409 std::vector< AccessibleGridControlTableCell* >& AccessibleGridControlTable::getCellVector()
410 {
411 	return m_pCellVector;
412 }
413 
414 std::vector< Reference< XAccessible > >& AccessibleGridControlTable::getAccessibleCellVector()
415 {
416 	return m_pAccessCellVector;
417 }
418 // ============================================================================
419 
420 } // namespace accessibility
421 
422 // ============================================================================
423 
424