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 "AccessibleCellBase.hxx"
33 #include "attrib.hxx"
34 #include "scitems.hxx"
35 #include "miscuno.hxx"
36 #include "document.hxx"
37 #include "docfunc.hxx"
38 #include "cell.hxx"
39 #include "unoguard.hxx"
40 #include "scresid.hxx"
41 #ifndef SC_SC_HRC
42 #include "sc.hrc"
43 #endif
44 #include "unonames.hxx"
45 
46 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
47 #include <com/sun/star/accessibility/AccessibleRole.hpp>
48 #endif
49 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
50 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
51 #endif
52 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
53 #include <com/sun/star/sheet/XSpreadsheet.hpp>
54 #include <tools/debug.hxx>
55 #include <editeng/brshitem.hxx>
56 #include <rtl/uuid.h>
57 #include <comphelper/sequence.hxx>
58 #include <sfx2/objsh.hxx>
59 
60 #include <float.h>
61 
62 using namespace	::com::sun::star;
63 using namespace	::com::sun::star::accessibility;
64 
65 //=====  internal  ============================================================
66 
67 ScAccessibleCellBase::ScAccessibleCellBase(
68         const uno::Reference<XAccessible>& rxParent,
69 		ScDocument* pDoc,
70 		const ScAddress& rCellAddress,
71 		sal_Int32 nIndex)
72 	:
73 	ScAccessibleContextBase(rxParent, AccessibleRole::TABLE_CELL),
74 	maCellAddress(rCellAddress),
75 	mpDoc(pDoc),
76 	mnIndex(nIndex)
77 {
78 }
79 
80 ScAccessibleCellBase::~ScAccessibleCellBase()
81 {
82 }
83 
84 	//=====  XAccessibleComponent  ============================================
85 
86 sal_Bool SAL_CALL ScAccessibleCellBase::isVisible(  )
87 		throw (uno::RuntimeException)
88 {
89  	ScUnoGuard aGuard;
90     IsObjectValid();
91 	// test whether the cell is hidden (column/row - hidden/filtered)
92 	sal_Bool bVisible(sal_True);
93 	if (mpDoc)
94 	{
95         bool bColHidden = mpDoc->ColHidden(maCellAddress.Col(), maCellAddress.Tab());
96         bool bRowHidden = mpDoc->RowHidden(maCellAddress.Row(), maCellAddress.Tab());
97         bool bColFiltered = mpDoc->ColFiltered(maCellAddress.Col(), maCellAddress.Tab());
98         bool bRowFiltered = mpDoc->RowFiltered(maCellAddress.Row(), maCellAddress.Tab());
99 
100         if (bColHidden || bColFiltered || bRowHidden || bRowFiltered)
101 			bVisible = sal_False;
102 	}
103 	return bVisible;
104 }
105 
106 sal_Int32 SAL_CALL ScAccessibleCellBase::getForeground()
107     throw (uno::RuntimeException)
108 {
109     ScUnoGuard aGuard;
110     IsObjectValid();
111     sal_Int32 nColor(0);
112     if (mpDoc)
113     {
114         SfxObjectShell* pObjSh = mpDoc->GetDocumentShell();
115         if ( pObjSh )
116         {
117             uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( pObjSh->GetModel(), uno::UNO_QUERY );
118             if ( xSpreadDoc.is() )
119             {
120                 uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
121                 uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
122                 if ( xIndex.is() )
123                 {
124                     uno::Any aTable = xIndex->getByIndex(maCellAddress.Tab());
125                     uno::Reference<sheet::XSpreadsheet> xTable;
126                     if (aTable>>=xTable)
127                     {
128                         uno::Reference<table::XCell> xCell = xTable->getCellByPosition(maCellAddress.Col(), maCellAddress.Row());
129                         if (xCell.is())
130                         {
131                             uno::Reference<beans::XPropertySet> xCellProps(xCell, uno::UNO_QUERY);
132                             if (xCellProps.is())
133                             {
134                                 uno::Any aAny = xCellProps->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CCOLOR)));
135                                 aAny >>= nColor;
136                             }
137                         }
138                     }
139                 }
140             }
141         }
142     }
143     return nColor;
144 }
145 
146 sal_Int32 SAL_CALL ScAccessibleCellBase::getBackground()
147     throw (uno::RuntimeException)
148 {
149     ScUnoGuard aGuard;
150     IsObjectValid();
151     sal_Int32 nColor(0);
152 
153     if (mpDoc)
154     {
155         SfxObjectShell* pObjSh = mpDoc->GetDocumentShell();
156         if ( pObjSh )
157         {
158             uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( pObjSh->GetModel(), uno::UNO_QUERY );
159             if ( xSpreadDoc.is() )
160             {
161                 uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
162                 uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
163                 if ( xIndex.is() )
164                 {
165                     uno::Any aTable = xIndex->getByIndex(maCellAddress.Tab());
166                     uno::Reference<sheet::XSpreadsheet> xTable;
167                     if (aTable>>=xTable)
168                     {
169                         uno::Reference<table::XCell> xCell = xTable->getCellByPosition(maCellAddress.Col(), maCellAddress.Row());
170                         if (xCell.is())
171                         {
172                             uno::Reference<beans::XPropertySet> xCellProps(xCell, uno::UNO_QUERY);
173                             if (xCellProps.is())
174                             {
175                                 uno::Any aAny = xCellProps->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLBACK)));
176                                 aAny >>= nColor;
177                             }
178                         }
179                     }
180                 }
181             }
182         }
183     }
184 
185     return nColor;
186 }
187 
188 	//=====  XInterface  =====================================================
189 
190 uno::Any SAL_CALL ScAccessibleCellBase::queryInterface( uno::Type const & rType )
191 	throw (uno::RuntimeException)
192 {
193 	uno::Any aAny (ScAccessibleCellBaseImpl::queryInterface(rType));
194 	return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
195 }
196 
197 void SAL_CALL ScAccessibleCellBase::acquire()
198 	throw ()
199 {
200 	ScAccessibleContextBase::acquire();
201 }
202 
203 void SAL_CALL ScAccessibleCellBase::release()
204 	throw ()
205 {
206 	ScAccessibleContextBase::release();
207 }
208 
209 	//=====  XAccessibleContext  ==============================================
210 
211 sal_Int32
212 	ScAccessibleCellBase::getAccessibleIndexInParent(void)
213         throw (uno::RuntimeException)
214 {
215 	ScUnoGuard aGuard;
216     IsObjectValid();
217 	return mnIndex;
218 }
219 
220 ::rtl::OUString SAL_CALL
221     ScAccessibleCellBase::createAccessibleDescription(void)
222     throw (uno::RuntimeException)
223 {
224 	rtl::OUString sDescription = String(ScResId(STR_ACC_CELL_DESCR));
225 
226 	return sDescription;
227 }
228 
229 ::rtl::OUString SAL_CALL
230     ScAccessibleCellBase::createAccessibleName(void)
231     throw (uno::RuntimeException)
232 {
233 	String sName( ScResId(STR_ACC_CELL_NAME) );
234 	String sAddress;
235 	// Document not needed, because only the cell address, but not the tablename is needed
236 	// always us OOO notation
237 	maCellAddress.Format( sAddress, SCA_VALID, NULL );
238 	sName.SearchAndReplaceAscii("%1", sAddress);
239     /*  #i65103# ZoomText merges cell address and contents, e.g. if value 2 is
240         contained in cell A1, ZT reads "cell A twelve" instead of "cell A1 - 2".
241         Simple solution: Append a space character to the cell address. */
242     sName.Append( ' ' );
243     return rtl::OUString(sName);
244 }
245 
246 	//=====  XAccessibleValue  ================================================
247 
248 uno::Any SAL_CALL
249 	ScAccessibleCellBase::getCurrentValue(  )
250 	throw (uno::RuntimeException)
251 {
252  	ScUnoGuard aGuard;
253     IsObjectValid();
254 	uno::Any aAny;
255 	if (mpDoc)
256 		aAny <<= mpDoc->GetValue(maCellAddress);
257 
258 	return aAny;
259 }
260 
261 sal_Bool SAL_CALL
262 	ScAccessibleCellBase::setCurrentValue( const uno::Any& aNumber )
263 	throw (uno::RuntimeException)
264 {
265  	ScUnoGuard aGuard;
266     IsObjectValid();
267 	double fValue = 0;
268 	sal_Bool bResult(sal_False);
269 	if((aNumber >>= fValue) && mpDoc && mpDoc->GetDocumentShell())
270 	{
271 		uno::Reference<XAccessibleStateSet> xParentStates;
272 		if (getAccessibleParent().is())
273 		{
274 			uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
275 			xParentStates = xParentContext->getAccessibleStateSet();
276 		}
277 		if (IsEditable(xParentStates))
278 		{
279 			ScDocShell* pDocShell = (ScDocShell*) mpDoc->GetDocumentShell();
280 			ScDocFunc aFunc(*pDocShell);
281 			bResult = aFunc.PutCell( maCellAddress, new ScValueCell(fValue), sal_True );
282 		}
283 	}
284 	return bResult;
285 }
286 
287 uno::Any SAL_CALL
288 	ScAccessibleCellBase::getMaximumValue(  )
289 	throw (uno::RuntimeException)
290 {
291 	uno::Any aAny;
292 	aAny <<= DBL_MAX;
293 
294 	return aAny;
295 }
296 
297 uno::Any SAL_CALL
298 	ScAccessibleCellBase::getMinimumValue(  )
299 	throw (uno::RuntimeException)
300 {
301 	uno::Any aAny;
302 	aAny <<= -DBL_MAX;
303 
304 	return aAny;
305 }
306 
307 	//=====  XServiceInfo  ====================================================
308 
309 ::rtl::OUString SAL_CALL ScAccessibleCellBase::getImplementationName(void)
310         throw (uno::RuntimeException)
311 {
312 	return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleCellBase"));
313 }
314 
315 	//=====  XTypeProvider  ===================================================
316 
317 uno::Sequence< uno::Type > SAL_CALL ScAccessibleCellBase::getTypes()
318 		throw (uno::RuntimeException)
319 {
320 	return comphelper::concatSequences(ScAccessibleCellBaseImpl::getTypes(), ScAccessibleContextBase::getTypes());
321 }
322 
323 uno::Sequence<sal_Int8> SAL_CALL
324 	ScAccessibleCellBase::getImplementationId(void)
325     throw (uno::RuntimeException)
326 {
327     ScUnoGuard aGuard;
328     IsObjectValid();
329 	static uno::Sequence<sal_Int8> aId;
330 	if (aId.getLength() == 0)
331 	{
332 		aId.realloc (16);
333 		rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
334 	}
335 	return aId;
336 }
337 
338 sal_Bool ScAccessibleCellBase::IsEditable(
339 	const uno::Reference<XAccessibleStateSet>& rxParentStates)
340 {
341 	sal_Bool bEditable(sal_False);
342 	if (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::EDITABLE))
343 		bEditable = sal_True;
344 	return bEditable;
345 }
346