Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <utility>
23 :
24 : #include "AccessibleCell.hxx"
25 : #include "scitems.hxx"
26 : #include <editeng/eeitem.hxx>
27 :
28 : #include "AccessibleText.hxx"
29 : #include "AccessibleDocument.hxx"
30 : #include "tabvwsh.hxx"
31 : #include "document.hxx"
32 : #include "attrib.hxx"
33 : #include "miscuno.hxx"
34 : #include "editsrc.hxx"
35 : #include "dociter.hxx"
36 : #include "markdata.hxx"
37 : #include "cellvalue.hxx"
38 : #include "formulaiter.hxx"
39 : #include "validat.hxx"
40 :
41 : #include <unotools/accessiblestatesethelper.hxx>
42 : #include <com/sun/star/accessibility/AccessibleRole.hpp>
43 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
44 : #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
45 : #include <com/sun/star/accessibility/XAccessibleTable.hpp>
46 : #include <editeng/brushitem.hxx>
47 : #include <comphelper/sequence.hxx>
48 : #include <float.h>
49 : #include <vcl/svapp.hxx>
50 :
51 : #include "AccessibleSpreadsheet.hxx"
52 :
53 : using namespace ::com::sun::star;
54 : using namespace ::com::sun::star::accessibility;
55 :
56 10 : rtl::Reference<ScAccessibleCell> ScAccessibleCell::create(
57 : const uno::Reference<XAccessible>& rxParent,
58 : ScTabViewShell* pViewShell,
59 : ScAddress& rCellAddress,
60 : sal_Int32 nIndex,
61 : ScSplitPos eSplitPos,
62 : ScAccessibleDocument* pAccDoc)
63 : {
64 : rtl::Reference<ScAccessibleCell> x(new ScAccessibleCell(
65 10 : rxParent, pViewShell, rCellAddress, nIndex, eSplitPos, pAccDoc));
66 10 : x->Init();
67 10 : return x;
68 : }
69 :
70 10 : ScAccessibleCell::ScAccessibleCell(
71 : const uno::Reference<XAccessible>& rxParent,
72 : ScTabViewShell* pViewShell,
73 : ScAddress& rCellAddress,
74 : sal_Int32 nIndex,
75 : ScSplitPos eSplitPos,
76 : ScAccessibleDocument* pAccDoc)
77 : :
78 : ScAccessibleCellBase(rxParent, GetDocument(pViewShell), rCellAddress, nIndex),
79 : ::accessibility::AccessibleStaticTextBase(CreateEditSource(pViewShell, rCellAddress, eSplitPos)),
80 : mpViewShell(pViewShell),
81 : mpAccDoc(pAccDoc),
82 10 : meSplitPos(eSplitPos)
83 : {
84 10 : if (pViewShell)
85 10 : pViewShell->AddAccessibilityObject(*this);
86 10 : }
87 :
88 30 : ScAccessibleCell::~ScAccessibleCell()
89 : {
90 10 : if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
91 : {
92 : // increment refcount to prevent double call off dtor
93 0 : osl_atomic_increment( &m_refCount );
94 : // call dispose to inform object which have a weak reference to this object
95 0 : dispose();
96 : }
97 20 : }
98 :
99 10 : void ScAccessibleCell::Init()
100 : {
101 10 : ScAccessibleCellBase::Init();
102 :
103 10 : SetEventSource(this);
104 10 : }
105 :
106 10 : void SAL_CALL ScAccessibleCell::disposing()
107 : {
108 10 : SolarMutexGuard aGuard;
109 : // dispose in AccessibleStaticTextBase
110 10 : Dispose();
111 :
112 10 : if (mpViewShell)
113 : {
114 10 : mpViewShell->RemoveAccessibilityObject(*this);
115 10 : mpViewShell = NULL;
116 : }
117 10 : mpAccDoc = NULL;
118 :
119 10 : ScAccessibleCellBase::disposing();
120 10 : }
121 :
122 : //===== XInterface =====================================================
123 :
124 650 : IMPLEMENT_FORWARD_XINTERFACE3( ScAccessibleCell, ScAccessibleCellBase, AccessibleStaticTextBase, ScAccessibleCellAttributeImpl )
125 :
126 : //===== XTypeProvider ===================================================
127 :
128 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER3( ScAccessibleCell, ScAccessibleCellBase, AccessibleStaticTextBase, ScAccessibleCellAttributeImpl )
129 :
130 : //===== XAccessibleComponent ============================================
131 :
132 0 : uno::Reference< XAccessible > SAL_CALL ScAccessibleCell::getAccessibleAtPoint(
133 : const awt::Point& rPoint )
134 : throw (uno::RuntimeException, std::exception)
135 : {
136 0 : return AccessibleStaticTextBase::getAccessibleAtPoint(rPoint);
137 : }
138 :
139 2 : void SAL_CALL ScAccessibleCell::grabFocus( )
140 : throw (uno::RuntimeException, std::exception)
141 : {
142 2 : SolarMutexGuard aGuard;
143 2 : IsObjectValid();
144 2 : if (getAccessibleParent().is() && mpViewShell)
145 : {
146 2 : uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
147 2 : if (xAccessibleComponent.is())
148 : {
149 2 : xAccessibleComponent->grabFocus();
150 2 : mpViewShell->SetCursor(maCellAddress.Col(), maCellAddress.Row());
151 2 : }
152 2 : }
153 2 : }
154 :
155 2 : Rectangle ScAccessibleCell::GetBoundingBoxOnScreen(void) const
156 : throw (uno::RuntimeException, std::exception)
157 : {
158 2 : Rectangle aCellRect(GetBoundingBox());
159 2 : if (mpViewShell)
160 : {
161 2 : vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
162 2 : if (pWindow)
163 : {
164 2 : Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL);
165 2 : aCellRect.setX(aCellRect.getX() + aRect.getX());
166 2 : aCellRect.setY(aCellRect.getY() + aRect.getY());
167 : }
168 : }
169 2 : return aCellRect;
170 : }
171 :
172 530 : Rectangle ScAccessibleCell::GetBoundingBox() const
173 : throw (uno::RuntimeException, std::exception)
174 : {
175 530 : Rectangle aCellRect;
176 530 : if (mpViewShell)
177 : {
178 : long nSizeX, nSizeY;
179 530 : mpViewShell->GetViewData().GetMergeSizePixel(
180 1060 : maCellAddress.Col(), maCellAddress.Row(), nSizeX, nSizeY);
181 530 : aCellRect.SetSize(Size(nSizeX, nSizeY));
182 530 : aCellRect.SetPos(mpViewShell->GetViewData().GetScrPos(maCellAddress.Col(), maCellAddress.Row(), meSplitPos, true));
183 :
184 530 : vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
185 530 : if (pWindow)
186 : {
187 530 : Rectangle aRect(pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow()));
188 530 : aRect.Move(-aRect.Left(), -aRect.Top());
189 530 : aCellRect = aRect.Intersection(aCellRect);
190 : }
191 :
192 : /* #i19430# Gnopernicus reads text partly if it sticks out of the cell
193 : boundaries. This leads to wrong results in cases where the cell
194 : text is rotated, because rotation is not taken into account when
195 : calculating the visible part of the text. In these cases we will
196 : simply expand the cell size to the width of the unrotated text. */
197 530 : if (mpDoc)
198 : {
199 : const SfxInt32Item* pItem = static_cast< const SfxInt32Item* >(
200 530 : mpDoc->GetAttr( maCellAddress.Col(), maCellAddress.Row(), maCellAddress.Tab(), ATTR_ROTATE_VALUE ) );
201 530 : if( pItem && (pItem->GetValue() != 0) )
202 : {
203 0 : Rectangle aParaRect = GetParagraphBoundingBox();
204 0 : if( !aParaRect.IsEmpty() && (aCellRect.GetWidth() < aParaRect.GetWidth()) )
205 0 : aCellRect.SetSize( Size( aParaRect.GetWidth(), aCellRect.GetHeight() ) );
206 : }
207 : }
208 : }
209 530 : if (aCellRect.IsEmpty())
210 0 : aCellRect.SetPos(Point(-1, -1));
211 530 : return aCellRect;
212 : }
213 :
214 : //===== XAccessibleContext ==============================================
215 :
216 : sal_Int32 SAL_CALL
217 16 : ScAccessibleCell::getAccessibleChildCount(void)
218 : throw (uno::RuntimeException, std::exception)
219 : {
220 16 : return AccessibleStaticTextBase::getAccessibleChildCount();
221 : }
222 :
223 : uno::Reference< XAccessible > SAL_CALL
224 0 : ScAccessibleCell::getAccessibleChild(sal_Int32 nIndex)
225 : throw (uno::RuntimeException,
226 : lang::IndexOutOfBoundsException, std::exception)
227 : {
228 0 : return AccessibleStaticTextBase::getAccessibleChild(nIndex);
229 : }
230 :
231 : uno::Reference<XAccessibleStateSet> SAL_CALL
232 10 : ScAccessibleCell::getAccessibleStateSet(void)
233 : throw (uno::RuntimeException, std::exception)
234 : {
235 10 : SolarMutexGuard aGuard;
236 20 : uno::Reference<XAccessibleStateSet> xParentStates;
237 10 : if (getAccessibleParent().is())
238 : {
239 10 : uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
240 10 : xParentStates = xParentContext->getAccessibleStateSet();
241 : }
242 10 : utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
243 10 : if (IsDefunc(xParentStates))
244 0 : pStateSet->AddState(AccessibleStateType::DEFUNC);
245 : else
246 : {
247 10 : if (IsFormulaMode())
248 : {
249 0 : pStateSet->AddState(AccessibleStateType::ENABLED);
250 0 : pStateSet->AddState(AccessibleStateType::MULTI_LINE);
251 0 : pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
252 0 : if (IsOpaque(xParentStates))
253 0 : pStateSet->AddState(AccessibleStateType::OPAQUE);
254 0 : pStateSet->AddState(AccessibleStateType::SELECTABLE);
255 0 : if (IsSelected())
256 0 : pStateSet->AddState(AccessibleStateType::SELECTED);
257 0 : if (isShowing())
258 0 : pStateSet->AddState(AccessibleStateType::SHOWING);
259 0 : pStateSet->AddState(AccessibleStateType::TRANSIENT);
260 0 : if (isVisible())
261 0 : pStateSet->AddState(AccessibleStateType::VISIBLE);
262 0 : return pStateSet;
263 : }
264 10 : if (IsEditable(xParentStates))
265 : {
266 10 : pStateSet->AddState(AccessibleStateType::EDITABLE);
267 10 : pStateSet->AddState(AccessibleStateType::RESIZABLE);
268 : }
269 10 : pStateSet->AddState(AccessibleStateType::ENABLED);
270 10 : pStateSet->AddState(AccessibleStateType::MULTI_LINE);
271 10 : pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
272 10 : pStateSet->AddState(AccessibleStateType::FOCUSABLE);
273 10 : if (IsOpaque(xParentStates))
274 0 : pStateSet->AddState(AccessibleStateType::OPAQUE);
275 10 : pStateSet->AddState(AccessibleStateType::SELECTABLE);
276 10 : if (IsSelected())
277 0 : pStateSet->AddState(AccessibleStateType::SELECTED);
278 10 : if (isShowing())
279 10 : pStateSet->AddState(AccessibleStateType::SHOWING);
280 10 : pStateSet->AddState(AccessibleStateType::TRANSIENT);
281 10 : if (isVisible())
282 10 : pStateSet->AddState(AccessibleStateType::VISIBLE);
283 : }
284 20 : return pStateSet;
285 : }
286 :
287 : uno::Reference<XAccessibleRelationSet> SAL_CALL
288 2 : ScAccessibleCell::getAccessibleRelationSet()
289 : throw (uno::RuntimeException, std::exception)
290 : {
291 2 : SolarMutexGuard aGuard;
292 2 : IsObjectValid();
293 2 : utl::AccessibleRelationSetHelper* pRelationSet = NULL;
294 2 : if (mpAccDoc)
295 2 : pRelationSet = mpAccDoc->GetRelationSet(&maCellAddress);
296 2 : if (!pRelationSet)
297 2 : pRelationSet = new utl::AccessibleRelationSetHelper();
298 2 : FillDependends(pRelationSet);
299 2 : FillPrecedents(pRelationSet);
300 2 : return pRelationSet;
301 : }
302 :
303 : //===== XServiceInfo ====================================================
304 :
305 10 : OUString SAL_CALL ScAccessibleCell::getImplementationName(void)
306 : throw (uno::RuntimeException, std::exception)
307 : {
308 10 : return OUString("ScAccessibleCell");
309 : }
310 :
311 : uno::Sequence< OUString> SAL_CALL
312 0 : ScAccessibleCell::getSupportedServiceNames(void)
313 : throw (uno::RuntimeException, std::exception)
314 : {
315 0 : uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
316 0 : sal_Int32 nOldSize(aSequence.getLength());
317 0 : aSequence.realloc(nOldSize + 1);
318 :
319 0 : aSequence[nOldSize] = "com.sun.star.sheet.AccessibleCell";
320 :
321 0 : return aSequence;
322 : }
323 :
324 : //==== internal =========================================================
325 :
326 10 : bool ScAccessibleCell::IsDefunc(
327 : const uno::Reference<XAccessibleStateSet>& rxParentStates)
328 : {
329 40 : return ScAccessibleContextBase::IsDefunc() || (mpDoc == NULL) || (mpViewShell == NULL) || !getAccessibleParent().is() ||
330 40 : (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
331 : }
332 :
333 20 : bool ScAccessibleCell::IsEditable(
334 : const uno::Reference<XAccessibleStateSet>& rxParentStates)
335 : {
336 20 : bool bEditable(true);
337 20 : if (rxParentStates.is() && !rxParentStates->contains(AccessibleStateType::EDITABLE) &&
338 : mpDoc)
339 : {
340 : // here I have to test whether the protection of the table should influence this cell.
341 : const ScProtectionAttr* pItem = static_cast<const ScProtectionAttr*>(mpDoc->GetAttr(
342 0 : maCellAddress.Col(), maCellAddress.Row(),
343 0 : maCellAddress.Tab(), ATTR_PROTECTION));
344 0 : if (pItem)
345 0 : bEditable = !pItem->GetProtection();
346 : }
347 20 : return bEditable;
348 : }
349 :
350 10 : bool ScAccessibleCell::IsOpaque(
351 : const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
352 : {
353 : // test whether there is a background color
354 10 : bool bOpaque(true);
355 10 : if (mpDoc)
356 : {
357 : const SvxBrushItem* pItem = static_cast<const SvxBrushItem*>(mpDoc->GetAttr(
358 10 : maCellAddress.Col(), maCellAddress.Row(),
359 20 : maCellAddress.Tab(), ATTR_BACKGROUND));
360 10 : if (pItem)
361 10 : bOpaque = pItem->GetColor() != COL_TRANSPARENT;
362 : }
363 10 : return bOpaque;
364 : }
365 :
366 10 : bool ScAccessibleCell::IsSelected()
367 : {
368 10 : if (IsFormulaMode())
369 : {
370 0 : const ScAccessibleSpreadsheet *pSheet =static_cast<const ScAccessibleSpreadsheet*>(mxParent.get());
371 0 : if (pSheet)
372 : {
373 0 : return pSheet->IsScAddrFormulaSel(maCellAddress);
374 : }
375 0 : return false;
376 : }
377 :
378 10 : bool bResult(false);
379 10 : if (mpViewShell)
380 : {
381 10 : const ScMarkData& rMarkdata = mpViewShell->GetViewData().GetMarkData();
382 10 : bResult = rMarkdata.IsCellMarked(maCellAddress.Col(), maCellAddress.Row());
383 : }
384 10 : return bResult;
385 : }
386 :
387 10 : ScDocument* ScAccessibleCell::GetDocument(ScTabViewShell* pViewShell)
388 : {
389 10 : ScDocument* pDoc = NULL;
390 10 : if (pViewShell)
391 10 : pDoc = pViewShell->GetViewData().GetDocument();
392 10 : return pDoc;
393 : }
394 :
395 10 : ::std::unique_ptr< SvxEditSource > ScAccessibleCell::CreateEditSource(ScTabViewShell* pViewShell, ScAddress aCell, ScSplitPos eSplitPos)
396 : {
397 10 : if (IsFormulaMode())
398 : {
399 0 : return ::std::unique_ptr< SvxEditSource >();
400 : }
401 : ::std::unique_ptr < ScAccessibleTextData > pAccessibleCellTextData
402 10 : ( new ScAccessibleCellTextData( pViewShell, aCell, eSplitPos, this ) );
403 20 : ::std::unique_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(std::move(pAccessibleCellTextData)));
404 :
405 20 : return pEditSource;
406 : }
407 :
408 2 : void ScAccessibleCell::FillDependends(utl::AccessibleRelationSetHelper* pRelationSet)
409 : {
410 2 : if (mpDoc)
411 : {
412 2 : ScRange aRange(0, 0, maCellAddress.Tab(), MAXCOL, MAXROW, maCellAddress.Tab());
413 2 : ScCellIterator aCellIter(mpDoc, aRange);
414 :
415 4 : for (bool bHasCell = aCellIter.first(); bHasCell; bHasCell = aCellIter.next())
416 : {
417 2 : if (aCellIter.getType() == CELLTYPE_FORMULA)
418 : {
419 0 : bool bFound = false;
420 0 : ScDetectiveRefIter aIter(aCellIter.getFormulaCell());
421 0 : ScRange aRef;
422 0 : while ( !bFound && aIter.GetNextRef( aRef ) )
423 : {
424 0 : if (aRef.In(maCellAddress))
425 0 : bFound = true;
426 : }
427 0 : if (bFound)
428 0 : AddRelation(aCellIter.GetPos(), AccessibleRelationType::CONTROLLER_FOR, pRelationSet);
429 : }
430 2 : }
431 : }
432 2 : }
433 :
434 2 : void ScAccessibleCell::FillPrecedents(utl::AccessibleRelationSetHelper* pRelationSet)
435 : {
436 2 : if (mpDoc && mpDoc->GetCellType(maCellAddress) == CELLTYPE_FORMULA)
437 : {
438 0 : ScFormulaCell* pCell = mpDoc->GetFormulaCell(maCellAddress);
439 0 : if (!pCell)
440 2 : return;
441 0 : ScDetectiveRefIter aIter(pCell);
442 0 : ScRange aRef;
443 0 : while ( aIter.GetNextRef( aRef ) )
444 : {
445 0 : AddRelation( aRef, AccessibleRelationType::CONTROLLED_BY, pRelationSet);
446 : }
447 : }
448 : }
449 :
450 0 : void ScAccessibleCell::AddRelation(const ScAddress& rCell,
451 : const sal_uInt16 aRelationType,
452 : utl::AccessibleRelationSetHelper* pRelationSet)
453 : {
454 0 : AddRelation(ScRange(rCell, rCell), aRelationType, pRelationSet);
455 0 : }
456 :
457 0 : void ScAccessibleCell::AddRelation(const ScRange& rRange,
458 : const sal_uInt16 aRelationType,
459 : utl::AccessibleRelationSetHelper* pRelationSet)
460 : {
461 0 : uno::Reference < XAccessibleTable > xTable ( getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY );
462 0 : if (xTable.is())
463 : {
464 0 : sal_uInt32 nCount(static_cast<sal_uInt32>(rRange.aEnd.Col() -
465 0 : rRange.aStart.Col() + 1) * (rRange.aEnd.Row() -
466 0 : rRange.aStart.Row() + 1));
467 0 : uno::Sequence < uno::Reference < uno::XInterface > > aTargetSet( nCount );
468 0 : uno::Reference < uno::XInterface >* pTargetSet = aTargetSet.getArray();
469 0 : if (pTargetSet)
470 : {
471 0 : sal_uInt32 nPos(0);
472 0 : for (sal_uInt32 nRow = rRange.aStart.Row(); nRow <= sal::static_int_cast<sal_uInt32>(rRange.aEnd.Row()); ++nRow)
473 : {
474 0 : for (sal_uInt32 nCol = rRange.aStart.Col(); nCol <= sal::static_int_cast<sal_uInt32>(rRange.aEnd.Col()); ++nCol)
475 : {
476 0 : pTargetSet[nPos] = xTable->getAccessibleCellAt(nRow, nCol);
477 0 : ++nPos;
478 : }
479 : }
480 : OSL_ENSURE(nCount == nPos, "something wents wrong");
481 : }
482 0 : AccessibleRelation aRelation;
483 0 : aRelation.RelationType = aRelationType;
484 0 : aRelation.TargetSet = aTargetSet;
485 0 : pRelationSet->AddRelation(aRelation);
486 0 : }
487 0 : }
488 :
489 0 : static OUString ReplaceOneChar(const OUString& oldOUString, const OUString& replacedChar, const OUString& replaceStr)
490 : {
491 0 : int iReplace = oldOUString.lastIndexOf(replacedChar);
492 0 : OUString aRet = oldOUString;
493 0 : while(iReplace > -1)
494 : {
495 0 : aRet = aRet.replaceAt(iReplace, 1, replaceStr);
496 0 : iReplace = aRet.lastIndexOf(replacedChar, iReplace);
497 : }
498 0 : return aRet;
499 : }
500 :
501 0 : static OUString ReplaceFourChar(const OUString& oldOUString)
502 : {
503 0 : OUString aRet = ReplaceOneChar(oldOUString, "\\", "\\\\");
504 0 : aRet = ReplaceOneChar(aRet, ";", "\\;");
505 0 : aRet = ReplaceOneChar(aRet, "=", "\\=");
506 0 : aRet = ReplaceOneChar(aRet, ",", "\\,");
507 0 : aRet = ReplaceOneChar(aRet, ":", "\\:");
508 0 : return aRet;
509 : }
510 :
511 0 : uno::Any SAL_CALL ScAccessibleCell::getExtendedAttributes()
512 : throw (::com::sun::star::lang::IndexOutOfBoundsException,
513 : ::com::sun::star::uno::RuntimeException,
514 : std::exception)
515 : {
516 0 : SolarMutexGuard aGuard;
517 :
518 0 : uno::Any strRet;
519 0 : if (mpViewShell)
520 : {
521 0 : OUString strFor = mpViewShell->GetFormula(maCellAddress) ;
522 0 : strFor = strFor.replaceAt(0,1,"");
523 0 : strFor = ReplaceFourChar(strFor);
524 0 : strFor = "Formula:" + strFor;
525 0 : strFor += ";Note:";
526 0 : strFor += ReplaceFourChar(GetAllDisplayNote());
527 0 : strFor += ";";
528 0 : strFor += getShadowAttrs();//the string returned contains the spliter ";"
529 0 : strFor += getBorderAttrs();//the string returned contains the spliter ";"
530 : //end of cell attributes
531 0 : if( mpDoc )
532 : {
533 0 : strFor += "isdropdown:";
534 0 : if( IsDropdown() )
535 0 : strFor += "true";
536 : else
537 0 : strFor += "false";
538 0 : strFor += ";";
539 : }
540 0 : strRet <<= strFor ;
541 : }
542 0 : return strRet;
543 : }
544 :
545 : // cell has its own ParaIndent property, so when calling character attributes on cell, the ParaIndent should replace the ParaLeftMargin if its value is not zero.
546 0 : uno::Sequence< beans::PropertyValue > SAL_CALL ScAccessibleCell::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< OUString >& aRequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
547 : {
548 0 : SolarMutexGuard aGuard;
549 :
550 0 : uno::Sequence< beans::PropertyValue > aAttribs = AccessibleStaticTextBase::getCharacterAttributes( nIndex, aRequestedAttributes );
551 0 : beans::PropertyValue *pAttribs = aAttribs.getArray();
552 :
553 0 : sal_uInt16 nParaIndent = static_cast< const SfxUInt16Item* >( mpDoc->GetAttr( maCellAddress.Col(), maCellAddress.Row(), maCellAddress.Tab(), ATTR_INDENT ) )->GetValue();
554 0 : if (nParaIndent > 0)
555 : {
556 0 : OUString sLeftMarginName ("ParaLeftMargin");
557 0 : for (int i = 0; i < aAttribs.getLength(); ++i)
558 : {
559 0 : if (sLeftMarginName == pAttribs[i].Name)
560 : {
561 0 : pAttribs[i].Value = uno::makeAny( nParaIndent );
562 0 : break;
563 : }
564 0 : }
565 : }
566 0 : return aAttribs;
567 : }
568 :
569 30 : bool ScAccessibleCell::IsFormulaMode()
570 : {
571 30 : ScAccessibleSpreadsheet* pSheet = static_cast<ScAccessibleSpreadsheet*>(mxParent.get());
572 30 : if (pSheet)
573 : {
574 30 : return pSheet->IsFormulaMode();
575 : }
576 0 : return false;
577 : }
578 :
579 0 : bool ScAccessibleCell::IsDropdown()
580 : {
581 0 : sal_uInt16 nPosX = maCellAddress.Col();
582 0 : sal_uInt16 nPosY = sal_uInt16(maCellAddress.Row());
583 0 : sal_uInt16 nTab = maCellAddress.Tab();
584 0 : sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( mpDoc->GetAttr( nPosX, nPosY, nTab, ATTR_VALIDDATA ) )->GetValue();
585 0 : if( nValidation )
586 : {
587 0 : const ScValidationData* pData = mpDoc->GetValidationEntry( nValidation );
588 0 : if( pData && pData->HasSelectionList() )
589 0 : return true;
590 : }
591 : const ScMergeFlagAttr* pAttr;
592 0 : pAttr = static_cast<const ScMergeFlagAttr*>(mpDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG ));
593 0 : if( pAttr->HasAutoFilter() )
594 : {
595 0 : return true;
596 : }
597 : else
598 : {
599 0 : sal_uInt16 nTabCount = mpDoc->GetTableCount();
600 0 : if ( nTab+1<nTabCount && mpDoc->IsScenario(nTab+1) && !mpDoc->IsScenario(nTab) )
601 : {
602 : SCTAB i;
603 0 : ScMarkData aMarks;
604 0 : for (i=nTab+1; i<nTabCount && mpDoc->IsScenario(i); i++)
605 0 : mpDoc->MarkScenario( i, nTab, aMarks, false, SC_SCENARIO_SHOWFRAME );
606 0 : ScRangeList aRanges;
607 0 : aMarks.FillRangeListWithMarks( &aRanges, false );
608 : bool bHasScenario;
609 0 : SCTAB nRangeCount = aRanges.size();
610 0 : for (i=0; i<nRangeCount; i++)
611 : {
612 0 : ScRange aRange = *aRanges[i];
613 0 : mpDoc->ExtendTotalMerge( aRange );
614 0 : bool bTextBelow = ( aRange.aStart.Row() == 0 );
615 : // MT IA2: Not used: sal_Bool bIsInScen = sal_False;
616 0 : if ( bTextBelow )
617 : {
618 0 : bHasScenario = (aRange.aStart.Col() == nPosX && aRange.aEnd.Row() == nPosY-1);
619 : }
620 : else
621 : {
622 0 : bHasScenario = (aRange.aStart.Col() == nPosX && aRange.aStart.Row() == nPosY+1);
623 : }
624 0 : if( bHasScenario ) return true;
625 0 : }
626 : }
627 : }
628 0 : return false;
629 228 : }
630 :
631 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|