merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / Accessibility / AccessibleCell.cxx
blob0a1a00b7df5564946084b206e696422728e90130
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleCell.cxx,v $
10 * $Revision: 1.34 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
35 #include "AccessibleCell.hxx"
36 #include "scitems.hxx"
37 #include <svx/eeitem.hxx>
40 #include "AccessibleText.hxx"
41 #include "AccessibleDocument.hxx"
42 #include "tabvwsh.hxx"
43 #include "document.hxx"
44 #include "attrib.hxx"
45 #include "miscuno.hxx"
46 #include "unoguard.hxx"
47 #include "editsrc.hxx"
48 #include "dociter.hxx"
49 #include "cell.hxx"
51 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
52 #include <unotools/accessiblestatesethelper.hxx>
53 #endif
54 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
55 #include <com/sun/star/accessibility/AccessibleRole.hpp>
56 #endif
57 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
58 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
59 #endif
60 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
61 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
62 #include <rtl/uuid.h>
63 #include <tools/debug.hxx>
64 #include <svx/brshitem.hxx>
65 #include <comphelper/sequence.hxx>
66 #include <float.h>
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::accessibility;
71 //===== internal ============================================================
73 ScAccessibleCell::ScAccessibleCell(
74 const uno::Reference<XAccessible>& rxParent,
75 ScTabViewShell* pViewShell,
76 ScAddress& rCellAddress,
77 sal_Int32 nIndex,
78 ScSplitPos eSplitPos,
79 ScAccessibleDocument* pAccDoc)
81 ScAccessibleCellBase(rxParent, GetDocument(pViewShell), rCellAddress, nIndex),
82 ::accessibility::AccessibleStaticTextBase(CreateEditSource(pViewShell, rCellAddress, eSplitPos)),
83 mpViewShell(pViewShell),
84 mpAccDoc(pAccDoc),
85 meSplitPos(eSplitPos)
87 if (pViewShell)
88 pViewShell->AddAccessibilityObject(*this);
91 ScAccessibleCell::~ScAccessibleCell()
93 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
95 // increment refcount to prevent double call off dtor
96 osl_incrementInterlockedCount( &m_refCount );
97 // call dispose to inform object wich have a weak reference to this object
98 dispose();
102 void ScAccessibleCell::Init()
104 ScAccessibleCellBase::Init();
106 SetEventSource(this);
109 void SAL_CALL ScAccessibleCell::disposing()
111 ScUnoGuard aGuard;
112 // #100593# dispose in AccessibleStaticTextBase
113 Dispose();
115 if (mpViewShell)
117 mpViewShell->RemoveAccessibilityObject(*this);
118 mpViewShell = NULL;
120 mpAccDoc = NULL;
122 ScAccessibleCellBase::disposing();
125 //===== XInterface =====================================================
127 IMPLEMENT_FORWARD_XINTERFACE2( ScAccessibleCell, ScAccessibleCellBase, AccessibleStaticTextBase )
129 //===== XTypeProvider ===================================================
131 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScAccessibleCell, ScAccessibleCellBase, AccessibleStaticTextBase )
133 //===== XAccessibleComponent ============================================
135 uno::Reference< XAccessible > SAL_CALL ScAccessibleCell::getAccessibleAtPoint(
136 const awt::Point& rPoint )
137 throw (uno::RuntimeException)
139 return AccessibleStaticTextBase::getAccessibleAtPoint(rPoint);
142 void SAL_CALL ScAccessibleCell::grabFocus( )
143 throw (uno::RuntimeException)
145 ScUnoGuard aGuard;
146 IsObjectValid();
147 if (getAccessibleParent().is() && mpViewShell)
149 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
150 if (xAccessibleComponent.is())
152 xAccessibleComponent->grabFocus();
153 mpViewShell->SetCursor(maCellAddress.Col(), maCellAddress.Row());
158 Rectangle ScAccessibleCell::GetBoundingBoxOnScreen(void) const
159 throw (uno::RuntimeException)
161 Rectangle aCellRect(GetBoundingBox());
162 if (mpViewShell)
164 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
165 if (pWindow)
167 Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL);
168 aCellRect.setX(aCellRect.getX() + aRect.getX());
169 aCellRect.setY(aCellRect.getY() + aRect.getY());
172 return aCellRect;
175 Rectangle ScAccessibleCell::GetBoundingBox(void) const
176 throw (uno::RuntimeException)
178 Rectangle aCellRect;
179 if (mpViewShell)
181 long nSizeX, nSizeY;
182 mpViewShell->GetViewData()->GetMergeSizePixel(
183 maCellAddress.Col(), maCellAddress.Row(), nSizeX, nSizeY);
184 aCellRect.SetSize(Size(nSizeX, nSizeY));
185 aCellRect.SetPos(mpViewShell->GetViewData()->GetScrPos(maCellAddress.Col(), maCellAddress.Row(), meSplitPos, TRUE));
187 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
188 if (pWindow)
190 Rectangle aRect(pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow()));
191 aRect.Move(-aRect.Left(), -aRect.Top());
192 aCellRect = aRect.Intersection(aCellRect);
195 /* #i19430# Gnopernicus reads text partly if it sticks out of the cell
196 boundaries. This leads to wrong results in cases where the cell
197 text is rotated, because rotation is not taken into account when
198 calculating the visible part of the text. In these cases we will
199 simply expand the cell size to the width of the unrotated text. */
200 if (mpDoc)
202 const SfxInt32Item* pItem = static_cast< const SfxInt32Item* >(
203 mpDoc->GetAttr( maCellAddress.Col(), maCellAddress.Row(), maCellAddress.Tab(), ATTR_ROTATE_VALUE ) );
204 if( pItem && (pItem->GetValue() != 0) )
206 Rectangle aParaRect = GetParagraphBoundingBox();
207 if( !aParaRect.IsEmpty() && (aCellRect.GetWidth() < aParaRect.GetWidth()) )
208 aCellRect.SetSize( Size( aParaRect.GetWidth(), aCellRect.GetHeight() ) );
212 if (aCellRect.IsEmpty())
213 aCellRect.SetPos(Point(-1, -1));
214 return aCellRect;
217 //===== XAccessibleContext ==============================================
219 sal_Int32 SAL_CALL
220 ScAccessibleCell::getAccessibleChildCount(void)
221 throw (uno::RuntimeException)
223 return AccessibleStaticTextBase::getAccessibleChildCount();
226 uno::Reference< XAccessible > SAL_CALL
227 ScAccessibleCell::getAccessibleChild(sal_Int32 nIndex)
228 throw (uno::RuntimeException,
229 lang::IndexOutOfBoundsException)
231 return AccessibleStaticTextBase::getAccessibleChild(nIndex);
234 uno::Reference<XAccessibleStateSet> SAL_CALL
235 ScAccessibleCell::getAccessibleStateSet(void)
236 throw (uno::RuntimeException)
238 ScUnoGuard aGuard;
239 uno::Reference<XAccessibleStateSet> xParentStates;
240 if (getAccessibleParent().is())
242 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
243 xParentStates = xParentContext->getAccessibleStateSet();
245 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
246 if (IsDefunc(xParentStates))
247 pStateSet->AddState(AccessibleStateType::DEFUNC);
248 else
250 if (IsEditable(xParentStates))
252 pStateSet->AddState(AccessibleStateType::EDITABLE);
253 pStateSet->AddState(AccessibleStateType::RESIZABLE);
255 pStateSet->AddState(AccessibleStateType::ENABLED);
256 pStateSet->AddState(AccessibleStateType::MULTI_LINE);
257 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
258 if (IsOpaque(xParentStates))
259 pStateSet->AddState(AccessibleStateType::OPAQUE);
260 pStateSet->AddState(AccessibleStateType::SELECTABLE);
261 if (IsSelected())
262 pStateSet->AddState(AccessibleStateType::SELECTED);
263 if (isShowing())
264 pStateSet->AddState(AccessibleStateType::SHOWING);
265 pStateSet->AddState(AccessibleStateType::TRANSIENT);
266 if (isVisible())
267 pStateSet->AddState(AccessibleStateType::VISIBLE);
269 return pStateSet;
272 uno::Reference<XAccessibleRelationSet> SAL_CALL
273 ScAccessibleCell::getAccessibleRelationSet(void)
274 throw (uno::RuntimeException)
276 ScUnoGuard aGuard;
277 IsObjectValid();
278 utl::AccessibleRelationSetHelper* pRelationSet = NULL;
279 if (mpAccDoc)
280 pRelationSet = mpAccDoc->GetRelationSet(&maCellAddress);
281 if (!pRelationSet)
282 pRelationSet = new utl::AccessibleRelationSetHelper();
283 FillDependends(pRelationSet);
284 FillPrecedents(pRelationSet);
285 return pRelationSet;
288 //===== XServiceInfo ====================================================
290 ::rtl::OUString SAL_CALL ScAccessibleCell::getImplementationName(void)
291 throw (uno::RuntimeException)
293 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleCell"));
296 uno::Sequence< ::rtl::OUString> SAL_CALL
297 ScAccessibleCell::getSupportedServiceNames(void)
298 throw (uno::RuntimeException)
300 uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
301 sal_Int32 nOldSize(aSequence.getLength());
302 aSequence.realloc(nOldSize + 1);
303 ::rtl::OUString* pNames = aSequence.getArray();
305 pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.AccessibleCell"));
307 return aSequence;
310 //==== internal =========================================================
312 sal_Bool ScAccessibleCell::IsDefunc(
313 const uno::Reference<XAccessibleStateSet>& rxParentStates)
315 return ScAccessibleContextBase::IsDefunc() || (mpDoc == NULL) || (mpViewShell == NULL) || !getAccessibleParent().is() ||
316 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
319 sal_Bool ScAccessibleCell::IsEditable(
320 const uno::Reference<XAccessibleStateSet>& rxParentStates)
322 sal_Bool bEditable(sal_True);
323 if (rxParentStates.is() && !rxParentStates->contains(AccessibleStateType::EDITABLE) &&
324 mpDoc)
326 // here I have to test whether the protection of the table should influence this cell.
327 const ScProtectionAttr* pItem = (const ScProtectionAttr*)mpDoc->GetAttr(
328 maCellAddress.Col(), maCellAddress.Row(),
329 maCellAddress.Tab(), ATTR_PROTECTION);
330 if (pItem)
331 bEditable = !pItem->GetProtection();
333 return bEditable;
336 sal_Bool ScAccessibleCell::IsOpaque(
337 const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
339 // test whether there is a background color
340 sal_Bool bOpaque(sal_True);
341 if (mpDoc)
343 const SvxBrushItem* pItem = (const SvxBrushItem*)mpDoc->GetAttr(
344 maCellAddress.Col(), maCellAddress.Row(),
345 maCellAddress.Tab(), ATTR_BACKGROUND);
346 if (pItem)
347 bOpaque = pItem->GetColor() != COL_TRANSPARENT;
349 return bOpaque;
352 sal_Bool ScAccessibleCell::IsSelected()
354 sal_Bool bResult(sal_False);
355 if (mpViewShell && mpViewShell->GetViewData())
357 const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
358 bResult = rMarkdata.IsCellMarked(maCellAddress.Col(), maCellAddress.Row());
360 return bResult;
363 ScDocument* ScAccessibleCell::GetDocument(ScTabViewShell* pViewShell)
365 ScDocument* pDoc = NULL;
366 if (pViewShell && pViewShell->GetViewData())
367 pDoc = pViewShell->GetViewData()->GetDocument();
368 return pDoc;
371 ::std::auto_ptr< SvxEditSource > ScAccessibleCell::CreateEditSource(ScTabViewShell* pViewShell, ScAddress aCell, ScSplitPos eSplitPos)
373 ::std::auto_ptr < ScAccessibleTextData > pAccessibleCellTextData
374 ( new ScAccessibleCellTextData( pViewShell, aCell, eSplitPos, this ) );
375 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleCellTextData));
377 return pEditSource;
380 void ScAccessibleCell::FillDependends(utl::AccessibleRelationSetHelper* pRelationSet)
382 if (mpDoc)
384 ScCellIterator aCellIter( mpDoc, 0,0, maCellAddress.Tab(), MAXCOL,MAXROW, maCellAddress.Tab() );
385 ScBaseCell* pCell = aCellIter.GetFirst();
386 while (pCell)
388 if (pCell->GetCellType() == CELLTYPE_FORMULA)
390 sal_Bool bFound(sal_False);
391 ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
392 ScRange aRef;
393 while ( !bFound && aIter.GetNextRef( aRef ) )
395 if (aRef.In(maCellAddress))
396 bFound = sal_True;
398 if (bFound)
399 AddRelation(ScAddress(aCellIter.GetCol(), aCellIter.GetRow(), aCellIter.GetTab()), AccessibleRelationType::CONTROLLER_FOR, pRelationSet);
401 pCell = aCellIter.GetNext();
406 void ScAccessibleCell::FillPrecedents(utl::AccessibleRelationSetHelper* pRelationSet)
408 if (mpDoc)
410 ScBaseCell* pBaseCell = mpDoc->GetCell(maCellAddress);
411 if (pBaseCell && (pBaseCell->GetCellType() == CELLTYPE_FORMULA))
413 ScFormulaCell* pFCell = (ScFormulaCell*) pBaseCell;
415 ScDetectiveRefIter aIter( pFCell );
416 ScRange aRef;
417 while ( aIter.GetNextRef( aRef ) )
419 AddRelation( aRef, AccessibleRelationType::CONTROLLED_BY, pRelationSet);
425 void ScAccessibleCell::AddRelation(const ScAddress& rCell,
426 const sal_uInt16 aRelationType,
427 utl::AccessibleRelationSetHelper* pRelationSet)
429 AddRelation(ScRange(rCell, rCell), aRelationType, pRelationSet);
432 void ScAccessibleCell::AddRelation(const ScRange& rRange,
433 const sal_uInt16 aRelationType,
434 utl::AccessibleRelationSetHelper* pRelationSet)
436 uno::Reference < XAccessibleTable > xTable ( getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY );
437 if (xTable.is())
439 sal_uInt32 nCount(static_cast<sal_uInt32>(rRange.aEnd.Col() -
440 rRange.aStart.Col() + 1) * (rRange.aEnd.Row() -
441 rRange.aStart.Row() + 1));
442 uno::Sequence < uno::Reference < uno::XInterface > > aTargetSet( nCount );
443 uno::Reference < uno::XInterface >* pTargetSet = aTargetSet.getArray();
444 if (pTargetSet)
446 sal_uInt32 nPos(0);
447 for (sal_uInt32 nRow = rRange.aStart.Row(); nRow <= sal::static_int_cast<sal_uInt32>(rRange.aEnd.Row()); ++nRow)
449 for (sal_uInt32 nCol = rRange.aStart.Col(); nCol <= sal::static_int_cast<sal_uInt32>(rRange.aEnd.Col()); ++nCol)
451 pTargetSet[nPos] = xTable->getAccessibleCellAt(nRow, nCol);
452 ++nPos;
455 DBG_ASSERT(nCount == nPos, "something wents wrong");
457 AccessibleRelation aRelation;
458 aRelation.RelationType = aRelationType;
459 aRelation.TargetSet = aTargetSet;
460 pRelationSet->AddRelation(aRelation);