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_sc.hxx"
30 
31 
32 #include "AccessibleTableBase.hxx"
33 #include "miscuno.hxx"
34 #include "document.hxx"
35 #include "unoguard.hxx"
36 #include "scresid.hxx"
37 #ifndef SC_SC_HRC
38 #include "sc.hrc"
39 #endif
40 
41 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
42 #include <com/sun/star/accessibility/AccessibleRole.hpp>
43 #endif
44 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
45 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
46 #include <rtl/uuid.h>
47 #include <tools/debug.hxx>
48 #include <comphelper/sequence.hxx>
49 
50 
51 using namespace	::com::sun::star;
52 using namespace	::com::sun::star::accessibility;
53 
54 //=====  internal  ============================================================
55 
56 ScAccessibleTableBase::ScAccessibleTableBase(
57         const uno::Reference<XAccessible>& rxParent,
58 		ScDocument* pDoc,
59 		const ScRange& rRange)
60 	:
61 	ScAccessibleContextBase (rxParent, AccessibleRole::TABLE),
62 	maRange(rRange),
63 	mpDoc(pDoc)
64 {
65 }
66 
67 ScAccessibleTableBase::~ScAccessibleTableBase()
68 {
69 }
70 
71 void SAL_CALL ScAccessibleTableBase::disposing()
72 {
73     ScUnoGuard aGuard;
74 	mpDoc = NULL;
75 
76 	ScAccessibleContextBase::disposing();
77 }
78 
79 	//=====  XInterface  =====================================================
80 
81 uno::Any SAL_CALL ScAccessibleTableBase::queryInterface( uno::Type const & rType )
82 	throw (uno::RuntimeException)
83 {
84 	uno::Any aAny (ScAccessibleTableBaseImpl::queryInterface(rType));
85 	return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
86 }
87 
88 void SAL_CALL ScAccessibleTableBase::acquire()
89 	throw ()
90 {
91 	ScAccessibleContextBase::acquire();
92 }
93 
94 void SAL_CALL ScAccessibleTableBase::release()
95 	throw ()
96 {
97 	ScAccessibleContextBase::release();
98 }
99 
100 	//=====  XAccessibleTable  ================================================
101 
102 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleRowCount(  )
103     				throw (uno::RuntimeException)
104 {
105 	ScUnoGuard aGuard;
106     IsObjectValid();
107 	return maRange.aEnd.Row() - maRange.aStart.Row() + 1;
108 }
109 
110 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleColumnCount(  )
111     				throw (uno::RuntimeException)
112 {
113 	ScUnoGuard aGuard;
114     IsObjectValid();
115 	return maRange.aEnd.Col() - maRange.aStart.Col() + 1;
116 }
117 
118 ::rtl::OUString SAL_CALL ScAccessibleTableBase::getAccessibleRowDescription( sal_Int32 nRow )
119     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
120 {
121 	DBG_ERROR("Here should be a implementation to fill the description");
122 
123     if ((nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
124         throw lang::IndexOutOfBoundsException();
125 
126     //setAccessibleRowDescription(nRow, xAccessible); // to remember the created Description
127 	return rtl::OUString();
128 }
129 
130 ::rtl::OUString SAL_CALL ScAccessibleTableBase::getAccessibleColumnDescription( sal_Int32 nColumn )
131     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
132 {
133 	DBG_ERROR("Here should be a implementation to fill the description");
134 
135     if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0))
136         throw lang::IndexOutOfBoundsException();
137 
138     //setAccessibleColumnDescription(nColumn, xAccessible); // to remember the created Description
139 	return rtl::OUString();
140 }
141 
142 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
143     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
144 {
145 	ScUnoGuard aGuard;
146     IsObjectValid();
147 
148     if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0) ||
149         (nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
150         throw lang::IndexOutOfBoundsException();
151 
152     sal_Int32 nCount(1); // the same cell
153 	nRow += maRange.aStart.Row();
154 	nColumn += maRange.aStart.Col();
155 
156 	if (mpDoc)
157 	{
158 		SCROW nEndRow(0);
159         SCCOL nEndCol(0);
160 		if (mpDoc->ExtendMerge(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow),
161 			nEndCol, nEndRow, maRange.aStart.Tab()))
162         {
163 		    if (nEndRow > nRow)
164 			    nCount = nEndRow - nRow + 1;
165         }
166 	}
167 
168 	return nCount;
169 }
170 
171 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
172     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
173 {
174 	ScUnoGuard aGuard;
175     IsObjectValid();
176 
177     if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0) ||
178         (nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
179         throw lang::IndexOutOfBoundsException();
180 
181     sal_Int32 nCount(1); // the same cell
182 	nRow += maRange.aStart.Row();
183 	nColumn += maRange.aStart.Col();
184 
185 	if (mpDoc)
186 	{
187 		SCROW nEndRow(0);
188         SCCOL nEndCol(0);
189 		if (mpDoc->ExtendMerge(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow),
190 			nEndCol, nEndRow, maRange.aStart.Tab()))
191         {
192 		    if (nEndCol > nColumn)
193 			    nCount = nEndCol - nColumn + 1;
194         }
195 	}
196 
197 	return nCount;
198 }
199 
200 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleTableBase::getAccessibleRowHeaders(  )
201     				throw (uno::RuntimeException)
202 {
203 	uno::Reference< XAccessibleTable > xAccessibleTable;
204 	DBG_ERROR("Here should be a implementation to fill the row headers");
205 
206     //CommitChange
207 	return xAccessibleTable;
208 }
209 
210 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleTableBase::getAccessibleColumnHeaders(  )
211     				throw (uno::RuntimeException)
212 {
213 	uno::Reference< XAccessibleTable > xAccessibleTable;
214 	DBG_ERROR("Here should be a implementation to fill the column headers");
215 
216     //CommitChange
217 	return xAccessibleTable;
218 }
219 
220 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleTableBase::getSelectedAccessibleRows(  )
221     				throw (uno::RuntimeException)
222 {
223 	DBG_ERROR("not implemented yet");
224 	uno::Sequence< sal_Int32 > aSequence;
225 	return aSequence;
226 }
227 
228 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleTableBase::getSelectedAccessibleColumns(  )
229     				throw (uno::RuntimeException)
230 {
231 	DBG_ERROR("not implemented yet");
232 	uno::Sequence< sal_Int32 > aSequence;
233 	return aSequence;
234 }
235 
236 sal_Bool SAL_CALL ScAccessibleTableBase::isAccessibleRowSelected( sal_Int32 /* nRow */ )
237     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
238 {
239 	DBG_ERROR("not implemented yet");
240 	return sal_False;
241 }
242 
243 sal_Bool SAL_CALL ScAccessibleTableBase::isAccessibleColumnSelected( sal_Int32 /* nColumn */ )
244     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
245 {
246 	DBG_ERROR("not implemented yet");
247 	return sal_False;
248 }
249 
250 uno::Reference< XAccessible > SAL_CALL ScAccessibleTableBase::getAccessibleCellAt( sal_Int32 /* nRow */, sal_Int32 /* nColumn */ )
251     				throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
252 {
253 	DBG_ERROR("not implemented yet");
254 	uno::Reference< XAccessible > xAccessible;
255 	return xAccessible;
256 }
257 
258 uno::Reference< XAccessible > SAL_CALL ScAccessibleTableBase::getAccessibleCaption(  )
259     				throw (uno::RuntimeException)
260 {
261 	DBG_ERROR("not implemented yet");
262 	uno::Reference< XAccessible > xAccessible;
263 	return xAccessible;
264 }
265 
266 uno::Reference< XAccessible > SAL_CALL ScAccessibleTableBase::getAccessibleSummary(  )
267     				throw (uno::RuntimeException)
268 {
269 	DBG_ERROR("not implemented yet");
270 	uno::Reference< XAccessible > xAccessible;
271 	return xAccessible;
272 }
273 
274 sal_Bool SAL_CALL ScAccessibleTableBase::isAccessibleSelected( sal_Int32 /* nRow */, sal_Int32 /* nColumn */ )
275     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
276 {
277 	DBG_ERROR("not implemented yet");
278 	return sal_False;
279 }
280 
281 	//=====  XAccessibleExtendedTable  ========================================
282 
283 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
284     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
285 {
286 	ScUnoGuard aGuard;
287     IsObjectValid();
288 
289     if (nRow > (maRange.aEnd.Row() - maRange.aStart.Row()) ||
290         nRow < 0 ||
291         nColumn > (maRange.aEnd.Col() - maRange.aStart.Col()) ||
292         nColumn < 0)
293         throw lang::IndexOutOfBoundsException();
294 
295     nRow -= maRange.aStart.Row();
296 	nColumn -= maRange.aStart.Col();
297 	return (nRow * (maRange.aEnd.Col() + 1)) + nColumn;
298 }
299 
300 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleRow( sal_Int32 nChildIndex )
301     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
302 {
303 	ScUnoGuard aGuard;
304     IsObjectValid();
305 
306     if (nChildIndex >= getAccessibleChildCount() || nChildIndex < 0)
307         throw lang::IndexOutOfBoundsException();
308 
309     return nChildIndex / (maRange.aEnd.Col() - maRange.aStart.Col() + 1);
310 }
311 
312 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleColumn( sal_Int32 nChildIndex )
313     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
314 {
315 	ScUnoGuard aGuard;
316     IsObjectValid();
317 
318     if (nChildIndex >= getAccessibleChildCount() || nChildIndex < 0)
319         throw lang::IndexOutOfBoundsException();
320 
321     return nChildIndex % static_cast<sal_Int32>(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
322 }
323 
324 	//=====  XAccessibleContext  ==============================================
325 
326 sal_Int32 SAL_CALL
327 	ScAccessibleTableBase::getAccessibleChildCount(void)
328     				throw (uno::RuntimeException)
329 {
330 	ScUnoGuard aGuard;
331     IsObjectValid();
332 	return static_cast<sal_Int32>(maRange.aEnd.Row() - maRange.aStart.Row() + 1) *
333 			(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
334 //	return 1;
335 }
336 
337 uno::Reference< XAccessible > SAL_CALL
338 	ScAccessibleTableBase::getAccessibleChild(sal_Int32 nIndex)
339         throw (uno::RuntimeException,
340 		lang::IndexOutOfBoundsException)
341 {
342 	ScUnoGuard aGuard;
343     IsObjectValid();
344 
345     if (nIndex >= getAccessibleChildCount() || nIndex < 0)
346         throw lang::IndexOutOfBoundsException();
347 
348 	sal_Int32 nRow(0);
349 	sal_Int32 nColumn(0);
350 	sal_Int32 nTemp(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
351 	nRow = nIndex / nTemp;
352 	nColumn = nIndex % nTemp;
353 	return getAccessibleCellAt(nRow, nColumn);
354 }
355 
356 ::rtl::OUString SAL_CALL
357     ScAccessibleTableBase::createAccessibleDescription(void)
358     throw (uno::RuntimeException)
359 {
360     String sDesc(ScResId(STR_ACC_TABLE_DESCR));
361 /*	String sCoreName;
362 	if (mpDoc && mpDoc->GetName( maRange.aStart.Tab(), sCoreName ))
363 		sDesc.SearchAndReplaceAscii("%1", sCoreName);
364     sDesc.SearchAndReplaceAscii("%2", String(ScResId(SCSTR_UNKNOWN)));*/
365     return rtl::OUString(sDesc);
366 }
367 
368 ::rtl::OUString SAL_CALL
369     ScAccessibleTableBase::createAccessibleName(void)
370     throw (uno::RuntimeException)
371 {
372     String sName(ScResId(STR_ACC_TABLE_NAME));
373 	String sCoreName;
374 	if (mpDoc && mpDoc->GetName( maRange.aStart.Tab(), sCoreName ))
375 		sName.SearchAndReplaceAscii("%1", sCoreName);
376     return rtl::OUString(sName);
377 }
378 
379 uno::Reference<XAccessibleRelationSet> SAL_CALL
380     ScAccessibleTableBase::getAccessibleRelationSet(void)
381     throw (uno::RuntimeException)
382 {
383 	DBG_ERROR("should be implemented in the abrevated class");
384 	return uno::Reference<XAccessibleRelationSet>();
385 }
386 
387 uno::Reference<XAccessibleStateSet> SAL_CALL
388 	ScAccessibleTableBase::getAccessibleStateSet(void)
389     throw (uno::RuntimeException)
390 {
391 	DBG_ERROR("should be implemented in the abrevated class");
392 	uno::Reference< XAccessibleStateSet > xAccessibleStateSet;
393 	return xAccessibleStateSet;
394 }
395 
396 	///=====  XAccessibleSelection  ===========================================
397 
398 void SAL_CALL
399         ScAccessibleTableBase::selectAccessibleChild( sal_Int32 /* nChildIndex */ )
400 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
401 {
402 }
403 
404 sal_Bool SAL_CALL
405 		ScAccessibleTableBase::isAccessibleChildSelected( sal_Int32 nChildIndex )
406 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
407 {
408     // I don't need to guard, because the called funtions have a guard
409 //    ScUnoGuard aGuard;
410     if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
411         throw lang::IndexOutOfBoundsException();
412 	return isAccessibleSelected(getAccessibleRow(nChildIndex), getAccessibleColumn(nChildIndex));
413 }
414 
415 void SAL_CALL
416 		ScAccessibleTableBase::clearAccessibleSelection(  )
417 		throw (uno::RuntimeException)
418 {
419 }
420 
421 void SAL_CALL
422 		ScAccessibleTableBase::selectAllAccessibleChildren(  )
423 		throw (uno::RuntimeException)
424 {
425 }
426 
427 sal_Int32 SAL_CALL
428 		ScAccessibleTableBase::getSelectedAccessibleChildCount(  )
429 		throw (uno::RuntimeException)
430 {
431 	sal_Int32 nResult(0);
432 	return nResult;
433 }
434 
435 uno::Reference<XAccessible > SAL_CALL
436         ScAccessibleTableBase::getSelectedAccessibleChild( sal_Int32 /* nSelectedChildIndex */ )
437 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
438 {
439 	uno::Reference < XAccessible > xAccessible;
440 	return xAccessible;
441 }
442 
443 void SAL_CALL
444         ScAccessibleTableBase::deselectAccessibleChild( sal_Int32 /* nSelectedChildIndex */ )
445 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
446 {
447 }
448 
449 	//=====  XServiceInfo  ====================================================
450 
451 ::rtl::OUString SAL_CALL ScAccessibleTableBase::getImplementationName(void)
452         throw (uno::RuntimeException)
453 {
454 	return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleTableBase"));
455 }
456 
457 	//=====  XTypeProvider  ===================================================
458 
459 uno::Sequence< uno::Type > SAL_CALL ScAccessibleTableBase::getTypes()
460 		throw (uno::RuntimeException)
461 {
462 	return comphelper::concatSequences(ScAccessibleTableBaseImpl::getTypes(), ScAccessibleContextBase::getTypes());
463 }
464 
465 uno::Sequence<sal_Int8> SAL_CALL
466 	ScAccessibleTableBase::getImplementationId(void)
467     throw (uno::RuntimeException)
468 {
469     ScUnoGuard aGuard;
470     IsObjectValid();
471 	static uno::Sequence<sal_Int8> aId;
472 	if (aId.getLength() == 0)
473 	{
474 		aId.realloc (16);
475 		rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
476 	}
477 	return aId;
478 }
479 
480 void ScAccessibleTableBase::CommitTableModelChange(sal_Int32 nStartRow, sal_Int32 nStartCol, sal_Int32 nEndRow, sal_Int32 nEndCol, sal_uInt16 nId)
481 {
482 	AccessibleTableModelChange aModelChange;
483 	aModelChange.FirstRow = nStartRow;
484 	aModelChange.FirstColumn = nStartCol;
485 	aModelChange.LastRow = nEndRow;
486 	aModelChange.LastColumn = nEndCol;
487 	aModelChange.Type = nId;
488 
489 	AccessibleEventObject aEvent;
490 	aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED;
491 	aEvent.Source = uno::Reference< XAccessibleContext >(this);
492 	aEvent.NewValue <<= aModelChange;
493 
494 	CommitChange(aEvent);
495 }
496