1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleCell.cxx,v $
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"
45 #include "miscuno.hxx"
46 #include "unoguard.hxx"
47 #include "editsrc.hxx"
48 #include "dociter.hxx"
51 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
52 #include <unotools/accessiblestatesethelper.hxx>
54 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
55 #include <com/sun/star/accessibility/AccessibleRole.hpp>
57 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
58 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
60 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
61 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
63 #include <tools/debug.hxx>
64 #include <svx/brshitem.hxx>
65 #include <comphelper/sequence.hxx>
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
,
79 ScAccessibleDocument
* pAccDoc
)
81 ScAccessibleCellBase(rxParent
, GetDocument(pViewShell
), rCellAddress
, nIndex
),
82 ::accessibility::AccessibleStaticTextBase(CreateEditSource(pViewShell
, rCellAddress
, eSplitPos
)),
83 mpViewShell(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
102 void ScAccessibleCell::Init()
104 ScAccessibleCellBase::Init();
106 SetEventSource(this);
109 void SAL_CALL
ScAccessibleCell::disposing()
112 // #100593# dispose in AccessibleStaticTextBase
117 mpViewShell
->RemoveAccessibilityObject(*this);
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
)
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());
164 Window
* pWindow
= mpViewShell
->GetWindowByPos(meSplitPos
);
167 Rectangle aRect
= pWindow
->GetWindowExtentsRelative(NULL
);
168 aCellRect
.setX(aCellRect
.getX() + aRect
.getX());
169 aCellRect
.setY(aCellRect
.getY() + aRect
.getY());
175 Rectangle
ScAccessibleCell::GetBoundingBox(void) const
176 throw (uno::RuntimeException
)
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
);
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. */
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));
217 //===== XAccessibleContext ==============================================
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
)
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
);
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
);
262 pStateSet
->AddState(AccessibleStateType::SELECTED
);
264 pStateSet
->AddState(AccessibleStateType::SHOWING
);
265 pStateSet
->AddState(AccessibleStateType::TRANSIENT
);
267 pStateSet
->AddState(AccessibleStateType::VISIBLE
);
272 uno::Reference
<XAccessibleRelationSet
> SAL_CALL
273 ScAccessibleCell::getAccessibleRelationSet(void)
274 throw (uno::RuntimeException
)
278 utl::AccessibleRelationSetHelper
* pRelationSet
= NULL
;
280 pRelationSet
= mpAccDoc
->GetRelationSet(&maCellAddress
);
282 pRelationSet
= new utl::AccessibleRelationSetHelper();
283 FillDependends(pRelationSet
);
284 FillPrecedents(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"));
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
) &&
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
);
331 bEditable
= !pItem
->GetProtection();
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
);
343 const SvxBrushItem
* pItem
= (const SvxBrushItem
*)mpDoc
->GetAttr(
344 maCellAddress
.Col(), maCellAddress
.Row(),
345 maCellAddress
.Tab(), ATTR_BACKGROUND
);
347 bOpaque
= pItem
->GetColor() != COL_TRANSPARENT
;
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());
363 ScDocument
* ScAccessibleCell::GetDocument(ScTabViewShell
* pViewShell
)
365 ScDocument
* pDoc
= NULL
;
366 if (pViewShell
&& pViewShell
->GetViewData())
367 pDoc
= pViewShell
->GetViewData()->GetDocument();
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
));
380 void ScAccessibleCell::FillDependends(utl::AccessibleRelationSetHelper
* pRelationSet
)
384 ScCellIterator
aCellIter( mpDoc
, 0,0, maCellAddress
.Tab(), MAXCOL
,MAXROW
, maCellAddress
.Tab() );
385 ScBaseCell
* pCell
= aCellIter
.GetFirst();
388 if (pCell
->GetCellType() == CELLTYPE_FORMULA
)
390 sal_Bool
bFound(sal_False
);
391 ScDetectiveRefIter
aIter( (ScFormulaCell
*) pCell
);
393 while ( !bFound
&& aIter
.GetNextRef( aRef
) )
395 if (aRef
.In(maCellAddress
))
399 AddRelation(ScAddress(aCellIter
.GetCol(), aCellIter
.GetRow(), aCellIter
.GetTab()), AccessibleRelationType::CONTROLLER_FOR
, pRelationSet
);
401 pCell
= aCellIter
.GetNext();
406 void ScAccessibleCell::FillPrecedents(utl::AccessibleRelationSetHelper
* pRelationSet
)
410 ScBaseCell
* pBaseCell
= mpDoc
->GetCell(maCellAddress
);
411 if (pBaseCell
&& (pBaseCell
->GetCellType() == CELLTYPE_FORMULA
))
413 ScFormulaCell
* pFCell
= (ScFormulaCell
*) pBaseCell
;
415 ScDetectiveRefIter
aIter( pFCell
);
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
);
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();
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
);
455 DBG_ASSERT(nCount
== nPos
, "something wents wrong");
457 AccessibleRelation aRelation
;
458 aRelation
.RelationType
= aRelationType
;
459 aRelation
.TargetSet
= aTargetSet
;
460 pRelationSet
->AddRelation(aRelation
);