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