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