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