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