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 	//	if (mpDoc->ExtendMerge(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow),
174 	//		nEndCol, nEndRow, maRange.aStart.Tab()))
175         //{
176 	//	    if (nEndRow > nRow)
177 	//		    nCount = nEndRow - nRow + 1;
178         //}
179 	}
180 
181 	return nCount;
182 }
183 
184 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
185     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
186 {
187 	ScUnoGuard aGuard;
188     IsObjectValid();
189 
190     if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0) ||
191         (nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
192         throw lang::IndexOutOfBoundsException();
193 
194     sal_Int32 nCount(1); // the same cell
195 	nRow += maRange.aStart.Row();
196 	nColumn += maRange.aStart.Col();
197 
198 	if (mpDoc)
199 	{
200 		SCROW nEndRow(0);
201         SCCOL nEndCol(0);
202 		mpDoc->GetTableByIndex(maRange.aStart.Tab())->GetColumnByIndex(nColumn)->
203 			ExtendMerge( static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow), nRow, nEndCol, nEndRow, sal_False, sal_False );
204 		if (nEndCol > nColumn)
205 			    nCount = nEndCol - nColumn + 1;
206 	//	if (mpDoc->ExtendMerge(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow),
207 	//		nEndCol, nEndRow, maRange.aStart.Tab()))
208         //{
209 	//	    if (nEndCol > nColumn)
210 	//		    nCount = nEndCol - nColumn + 1;
211         //}
212 	}
213 
214 	return nCount;
215 }
216 
217 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleTableBase::getAccessibleRowHeaders(  )
218     				throw (uno::RuntimeException)
219 {
220 	uno::Reference< XAccessibleTable > xAccessibleTable;
221 	DBG_ERROR("Here should be a implementation to fill the row headers");
222 
223     //CommitChange
224 	return xAccessibleTable;
225 }
226 
227 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleTableBase::getAccessibleColumnHeaders(  )
228     				throw (uno::RuntimeException)
229 {
230 	uno::Reference< XAccessibleTable > xAccessibleTable;
231 	DBG_ERROR("Here should be a implementation to fill the column headers");
232 
233     //CommitChange
234 	return xAccessibleTable;
235 }
236 
237 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleTableBase::getSelectedAccessibleRows(  )
238     				throw (uno::RuntimeException)
239 {
240 	DBG_ERROR("not implemented yet");
241 	uno::Sequence< sal_Int32 > aSequence;
242 	return aSequence;
243 }
244 
245 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleTableBase::getSelectedAccessibleColumns(  )
246     				throw (uno::RuntimeException)
247 {
248 	DBG_ERROR("not implemented yet");
249 	uno::Sequence< sal_Int32 > aSequence;
250 	return aSequence;
251 }
252 
253 sal_Bool SAL_CALL ScAccessibleTableBase::isAccessibleRowSelected( sal_Int32 /* nRow */ )
254     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
255 {
256 	DBG_ERROR("not implemented yet");
257 	return sal_False;
258 }
259 
260 sal_Bool SAL_CALL ScAccessibleTableBase::isAccessibleColumnSelected( sal_Int32 /* nColumn */ )
261     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
262 {
263 	DBG_ERROR("not implemented yet");
264 	return sal_False;
265 }
266 
267 uno::Reference< XAccessible > SAL_CALL ScAccessibleTableBase::getAccessibleCellAt( sal_Int32 /* nRow */, sal_Int32 /* nColumn */ )
268     				throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
269 {
270 	DBG_ERROR("not implemented yet");
271 	uno::Reference< XAccessible > xAccessible;
272 	return xAccessible;
273 }
274 
275 uno::Reference< XAccessible > SAL_CALL ScAccessibleTableBase::getAccessibleCaption(  )
276     				throw (uno::RuntimeException)
277 {
278 	DBG_ERROR("not implemented yet");
279 	uno::Reference< XAccessible > xAccessible;
280 	return xAccessible;
281 }
282 
283 uno::Reference< XAccessible > SAL_CALL ScAccessibleTableBase::getAccessibleSummary(  )
284     				throw (uno::RuntimeException)
285 {
286 	DBG_ERROR("not implemented yet");
287 	uno::Reference< XAccessible > xAccessible;
288 	return xAccessible;
289 }
290 
291 sal_Bool SAL_CALL ScAccessibleTableBase::isAccessibleSelected( sal_Int32 /* nRow */, sal_Int32 /* nColumn */ )
292     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
293 {
294 	DBG_ERROR("not implemented yet");
295 	return sal_False;
296 }
297 
298 	//=====  XAccessibleExtendedTable  ========================================
299 
300 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
301     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
302 {
303 	ScUnoGuard aGuard;
304     IsObjectValid();
305 
306     if (nRow > (maRange.aEnd.Row() - maRange.aStart.Row()) ||
307         nRow < 0 ||
308         nColumn > (maRange.aEnd.Col() - maRange.aStart.Col()) ||
309         nColumn < 0)
310         throw lang::IndexOutOfBoundsException();
311 
312     nRow -= maRange.aStart.Row();
313 	nColumn -= maRange.aStart.Col();
314 	return (nRow * (maRange.aEnd.Col() + 1)) + nColumn;
315 }
316 
317 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleRow( 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 / (maRange.aEnd.Col() - maRange.aStart.Col() + 1);
327 }
328 
329 sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleColumn( sal_Int32 nChildIndex )
330     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
331 {
332 	ScUnoGuard aGuard;
333     IsObjectValid();
334 
335     if (nChildIndex >= getAccessibleChildCount() || nChildIndex < 0)
336         throw lang::IndexOutOfBoundsException();
337 
338     return nChildIndex % static_cast<sal_Int32>(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
339 }
340 
341 	//=====  XAccessibleContext  ==============================================
342 
343 sal_Int32 SAL_CALL
344 	ScAccessibleTableBase::getAccessibleChildCount(void)
345     				throw (uno::RuntimeException)
346 {
347 	ScUnoGuard aGuard;
348     IsObjectValid();
349 	return static_cast<sal_Int32>(maRange.aEnd.Row() - maRange.aStart.Row() + 1) *
350 			(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
351 //	return 1;
352 }
353 
354 uno::Reference< XAccessible > SAL_CALL
355 	ScAccessibleTableBase::getAccessibleChild(sal_Int32 nIndex)
356         throw (uno::RuntimeException,
357 		lang::IndexOutOfBoundsException)
358 {
359 	ScUnoGuard aGuard;
360     IsObjectValid();
361 
362     if (nIndex >= getAccessibleChildCount() || nIndex < 0)
363         throw lang::IndexOutOfBoundsException();
364 
365 	sal_Int32 nRow(0);
366 	sal_Int32 nColumn(0);
367 	sal_Int32 nTemp(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
368 	nRow = nIndex / nTemp;
369 	nColumn = nIndex % nTemp;
370 	return getAccessibleCellAt(nRow, nColumn);
371 }
372 
373 ::rtl::OUString SAL_CALL
374     ScAccessibleTableBase::createAccessibleDescription(void)
375     throw (uno::RuntimeException)
376 {
377     String sDesc(ScResId(STR_ACC_TABLE_DESCR));
378 /*	String sCoreName;
379 	if (mpDoc && mpDoc->GetName( maRange.aStart.Tab(), sCoreName ))
380 		sDesc.SearchAndReplaceAscii("%1", sCoreName);
381     sDesc.SearchAndReplaceAscii("%2", String(ScResId(SCSTR_UNKNOWN)));*/
382     return rtl::OUString(sDesc);
383 }
384 
385 ::rtl::OUString SAL_CALL
386     ScAccessibleTableBase::createAccessibleName(void)
387     throw (uno::RuntimeException)
388 {
389     String sName(ScResId(STR_ACC_TABLE_NAME));
390 	String sCoreName;
391 	if (mpDoc && mpDoc->GetName( maRange.aStart.Tab(), sCoreName ))
392 		sName.SearchAndReplaceAscii("%1", sCoreName);
393     return rtl::OUString(sName);
394 }
395 
396 uno::Reference<XAccessibleRelationSet> SAL_CALL
397     ScAccessibleTableBase::getAccessibleRelationSet(void)
398     throw (uno::RuntimeException)
399 {
400 	DBG_ERROR("should be implemented in the abrevated class");
401 	return uno::Reference<XAccessibleRelationSet>();
402 }
403 
404 uno::Reference<XAccessibleStateSet> SAL_CALL
405 	ScAccessibleTableBase::getAccessibleStateSet(void)
406     throw (uno::RuntimeException)
407 {
408 	DBG_ERROR("should be implemented in the abrevated class");
409 	uno::Reference< XAccessibleStateSet > xAccessibleStateSet;
410 	return xAccessibleStateSet;
411 }
412 
413 	///=====  XAccessibleSelection  ===========================================
414 
415 void SAL_CALL
416         ScAccessibleTableBase::selectAccessibleChild( sal_Int32 /* nChildIndex */ )
417 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
418 {
419 }
420 
421 sal_Bool SAL_CALL
422 		ScAccessibleTableBase::isAccessibleChildSelected( sal_Int32 nChildIndex )
423 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
424 {
425     // I don't need to guard, because the called funtions have a guard
426 //    ScUnoGuard aGuard;
427     if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
428         throw lang::IndexOutOfBoundsException();
429 	return isAccessibleSelected(getAccessibleRow(nChildIndex), getAccessibleColumn(nChildIndex));
430 }
431 
432 void SAL_CALL
433 		ScAccessibleTableBase::clearAccessibleSelection(  )
434 		throw (uno::RuntimeException)
435 {
436 }
437 
438 void SAL_CALL
439 		ScAccessibleTableBase::selectAllAccessibleChildren(  )
440 		throw (uno::RuntimeException)
441 {
442 }
443 
444 sal_Int32 SAL_CALL
445 		ScAccessibleTableBase::getSelectedAccessibleChildCount(  )
446 		throw (uno::RuntimeException)
447 {
448 	sal_Int32 nResult(0);
449 	return nResult;
450 }
451 
452 uno::Reference<XAccessible > SAL_CALL
453         ScAccessibleTableBase::getSelectedAccessibleChild( sal_Int32 /* nSelectedChildIndex */ )
454 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
455 {
456 	uno::Reference < XAccessible > xAccessible;
457 	return xAccessible;
458 }
459 
460 void SAL_CALL
461         ScAccessibleTableBase::deselectAccessibleChild( sal_Int32 /* nSelectedChildIndex */ )
462 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
463 {
464 }
465 
466 	//=====  XServiceInfo  ====================================================
467 
468 ::rtl::OUString SAL_CALL ScAccessibleTableBase::getImplementationName(void)
469         throw (uno::RuntimeException)
470 {
471 	return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleTableBase"));
472 }
473 
474 	//=====  XTypeProvider  ===================================================
475 
476 uno::Sequence< uno::Type > SAL_CALL ScAccessibleTableBase::getTypes()
477 		throw (uno::RuntimeException)
478 {
479 	return comphelper::concatSequences(ScAccessibleTableBaseImpl::getTypes(), ScAccessibleContextBase::getTypes());
480 }
481 
482 uno::Sequence<sal_Int8> SAL_CALL
483 	ScAccessibleTableBase::getImplementationId(void)
484     throw (uno::RuntimeException)
485 {
486     ScUnoGuard aGuard;
487     IsObjectValid();
488 	static uno::Sequence<sal_Int8> aId;
489 	if (aId.getLength() == 0)
490 	{
491 		aId.realloc (16);
492 		rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
493 	}
494 	return aId;
495 }
496 
497 void ScAccessibleTableBase::CommitTableModelChange(sal_Int32 nStartRow, sal_Int32 nStartCol, sal_Int32 nEndRow, sal_Int32 nEndCol, sal_uInt16 nId)
498 {
499 	AccessibleTableModelChange aModelChange;
500 	aModelChange.FirstRow = nStartRow;
501 	aModelChange.FirstColumn = nStartCol;
502 	aModelChange.LastRow = nEndRow;
503 	aModelChange.LastColumn = nEndCol;
504 	aModelChange.Type = nId;
505 
506 	AccessibleEventObject aEvent;
507 	aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED;
508 	aEvent.Source = uno::Reference< XAccessibleContext >(this);
509 	aEvent.NewValue <<= aModelChange;
510 
511 	CommitChange(aEvent);
512 }
513 sal_Bool SAL_CALL ScAccessibleTableBase::selectRow( sal_Int32 )
514 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
515 {
516 	return sal_True;
517 }
518 sal_Bool SAL_CALL ScAccessibleTableBase::selectColumn( sal_Int32 )
519 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
520 {
521 	return sal_True;
522 }
523 sal_Bool SAL_CALL ScAccessibleTableBase::unselectRow( sal_Int32 )
524 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
525 {
526 		return sal_True;
527 }
528 sal_Bool SAL_CALL ScAccessibleTableBase::unselectColumn( sal_Int32 )
529 		throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
530 {
531 	return sal_True;
532 }
533 
534 
535