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