1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <scitems.hxx>
21 #include <AccessiblePreviewTable.hxx>
22 #include <AccessiblePreviewCell.hxx>
23 #include <AccessiblePreviewHeaderCell.hxx>
24 #include <prevwsh.hxx>
25 #include <prevloc.hxx>
27 #include <document.hxx>
28 #include <scresid.hxx>
29 #include <strings.hrc>
30 #include <strings.hxx>
32 #include <com/sun/star/accessibility/AccessibleRole.hpp>
33 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
35 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
37 #include <vcl/window.hxx>
38 #include <vcl/svapp.hxx>
39 #include <svl/hint.hxx>
40 #include <unotools/accessiblestatesethelper.hxx>
41 #include <comphelper/sequence.hxx>
43 using namespace ::com::sun::star
;
44 using namespace ::com::sun::star::accessibility
;
46 //===== internal ============================================================
48 ScAccessiblePreviewTable::ScAccessiblePreviewTable( const css::uno::Reference
<css::accessibility::XAccessible
>& rxParent
,
49 ScPreviewShell
* pViewShell
, sal_Int32 nIndex
) :
50 ScAccessibleContextBase( rxParent
, AccessibleRole::TABLE
),
51 mpViewShell( pViewShell
),
55 mpViewShell
->AddAccessibilityObject(*this);
58 ScAccessiblePreviewTable::~ScAccessiblePreviewTable()
60 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper
.bInDispose
)
62 // increment refcount to prevent double call off dtor
63 osl_atomic_increment( &m_refCount
);
68 void SAL_CALL
ScAccessiblePreviewTable::disposing()
70 SolarMutexGuard aGuard
;
73 mpViewShell
->RemoveAccessibilityObject(*this);
74 mpViewShell
= nullptr;
79 ScAccessibleContextBase::disposing();
82 //===== SfxListener =====================================================
84 void ScAccessiblePreviewTable::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
86 const SfxHintId nId
= rHint
.GetId();
87 if ( nId
== SfxHintId::DataChanged
)
89 // column / row layout may change with any document change,
90 // so it must be invalidated
93 else if (nId
== SfxHintId::ScAccVisAreaChanged
)
95 AccessibleEventObject aEvent
;
96 aEvent
.EventId
= AccessibleEventId::VISIBLE_DATA_CHANGED
;
97 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
101 ScAccessibleContextBase::Notify(rBC
, rHint
);
104 //===== XInterface =====================================================
106 uno::Any SAL_CALL
ScAccessiblePreviewTable::queryInterface( uno::Type
const & rType
)
108 uno::Any
aAny (ScAccessiblePreviewTableImpl::queryInterface(rType
));
109 return aAny
.hasValue() ? aAny
: ScAccessibleContextBase::queryInterface(rType
);
112 void SAL_CALL
ScAccessiblePreviewTable::acquire()
115 ScAccessibleContextBase::acquire();
118 void SAL_CALL
ScAccessiblePreviewTable::release()
121 ScAccessibleContextBase::release();
124 //===== XAccessibleTable ================================================
126 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleRowCount()
128 SolarMutexGuard aGuard
;
135 nRet
= mpTableInfo
->GetRows();
139 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumnCount()
141 SolarMutexGuard aGuard
;
148 nRet
= mpTableInfo
->GetCols();
152 OUString SAL_CALL
ScAccessiblePreviewTable::getAccessibleRowDescription( sal_Int32 nRow
)
154 SolarMutexGuard aGuard
;
156 if ( nRow
< 0 || (mpTableInfo
&& nRow
>= mpTableInfo
->GetRows()) )
157 throw lang::IndexOutOfBoundsException();
162 OUString SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumnDescription( sal_Int32 nColumn
)
164 SolarMutexGuard aGuard
;
166 if ( nColumn
< 0 || (mpTableInfo
&& nColumn
>= mpTableInfo
->GetCols()) )
167 throw lang::IndexOutOfBoundsException();
172 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleRowExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
174 SolarMutexGuard aGuard
;
180 if ( !mpViewShell
|| !mpTableInfo
|| nColumn
< 0 || nRow
< 0 ||
181 nColumn
>= mpTableInfo
->GetCols() || nRow
>= mpTableInfo
->GetRows() )
182 throw lang::IndexOutOfBoundsException();
184 const ScPreviewColRowInfo
& rColInfo
= mpTableInfo
->GetColInfo()[nColumn
];
185 const ScPreviewColRowInfo
& rRowInfo
= mpTableInfo
->GetRowInfo()[nRow
];
187 if ( rColInfo
.bIsHeader
|| rRowInfo
.bIsHeader
)
189 // header cells only span a single cell
193 ScDocument
& rDoc
= mpViewShell
->GetDocument();
194 const ScMergeAttr
* pItem
= rDoc
.GetAttr(
195 static_cast<SCCOL
>(rColInfo
.nDocIndex
), static_cast<SCROW
>(rRowInfo
.nDocIndex
), mpTableInfo
->GetTab(), ATTR_MERGE
);
196 if ( pItem
&& pItem
->GetRowMerge() > 0 )
197 nRows
= pItem
->GetRowMerge();
203 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumnExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
205 SolarMutexGuard aGuard
;
210 sal_Int32 nColumns
= 1;
211 if ( !mpViewShell
|| !mpTableInfo
|| nColumn
< 0 || nRow
< 0 ||
212 nColumn
>= mpTableInfo
->GetCols() || nRow
>= mpTableInfo
->GetRows() )
213 throw lang::IndexOutOfBoundsException();
215 const ScPreviewColRowInfo
& rColInfo
= mpTableInfo
->GetColInfo()[nColumn
];
216 const ScPreviewColRowInfo
& rRowInfo
= mpTableInfo
->GetRowInfo()[nRow
];
218 if ( rColInfo
.bIsHeader
|| rRowInfo
.bIsHeader
)
220 // header cells only span a single cell
224 ScDocument
& rDoc
= mpViewShell
->GetDocument();
225 const ScMergeAttr
* pItem
= rDoc
.GetAttr(
226 static_cast<SCCOL
>(rColInfo
.nDocIndex
), static_cast<SCROW
>(rRowInfo
.nDocIndex
), mpTableInfo
->GetTab(), ATTR_MERGE
);
227 if ( pItem
&& pItem
->GetColMerge() > 0 )
228 nColumns
= pItem
->GetColMerge();
234 uno::Reference
< XAccessibleTable
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleRowHeaders()
240 uno::Reference
< XAccessibleTable
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumnHeaders()
246 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessiblePreviewTable::getSelectedAccessibleRows()
248 // in the page preview, there is no selection
249 return uno::Sequence
<sal_Int32
>(0);
252 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessiblePreviewTable::getSelectedAccessibleColumns()
254 // in the page preview, there is no selection
255 return uno::Sequence
<sal_Int32
>(0);
258 sal_Bool SAL_CALL
ScAccessiblePreviewTable::isAccessibleRowSelected( sal_Int32 nRow
)
260 // in the page preview, there is no selection
262 SolarMutexGuard aGuard
;
264 if ( nRow
< 0 || (mpTableInfo
&& nRow
>= mpTableInfo
->GetRows()) )
265 throw lang::IndexOutOfBoundsException();
270 sal_Bool SAL_CALL
ScAccessiblePreviewTable::isAccessibleColumnSelected( sal_Int32 nColumn
)
272 // in the page preview, there is no selection
274 SolarMutexGuard aGuard
;
276 if ( nColumn
< 0 || (mpTableInfo
&& nColumn
>= mpTableInfo
->GetCols()) )
277 throw lang::IndexOutOfBoundsException();
282 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleCellAt( sal_Int32 nRow
, sal_Int32 nColumn
)
284 SolarMutexGuard aGuard
;
289 uno::Reference
<XAccessible
> xRet
;
290 if ( mpTableInfo
&& nColumn
>= 0 && nRow
>= 0 && nColumn
< mpTableInfo
->GetCols() && nRow
< mpTableInfo
->GetRows() )
292 // index iterates horizontally
293 tools::Long nNewIndex
= nRow
* mpTableInfo
->GetCols() + nColumn
;
295 const ScPreviewColRowInfo
& rColInfo
= mpTableInfo
->GetColInfo()[nColumn
];
296 const ScPreviewColRowInfo
& rRowInfo
= mpTableInfo
->GetRowInfo()[nRow
];
298 ScAddress
aCellPos( static_cast<SCCOL
>(rColInfo
.nDocIndex
), static_cast<SCROW
>(rRowInfo
.nDocIndex
), mpTableInfo
->GetTab() );
299 if ( rColInfo
.bIsHeader
|| rRowInfo
.bIsHeader
)
301 const bool bRotatedColHeader
= rRowInfo
.bIsHeader
;
302 const bool bRotatedRowHeader
= rColInfo
.bIsHeader
;
303 rtl::Reference
<ScAccessiblePreviewHeaderCell
> pHeaderCell(new ScAccessiblePreviewHeaderCell(this, mpViewShell
, aCellPos
,
304 bRotatedColHeader
, bRotatedRowHeader
, nNewIndex
));
305 xRet
= pHeaderCell
.get();
310 rtl::Reference
<ScAccessiblePreviewCell
> pCell(new ScAccessiblePreviewCell( this, mpViewShell
, aCellPos
, nNewIndex
));
317 throw lang::IndexOutOfBoundsException();
322 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleCaption()
328 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleSummary()
334 sal_Bool SAL_CALL
ScAccessiblePreviewTable::isAccessibleSelected( sal_Int32 nRow
, sal_Int32 nColumn
)
336 // in the page preview, there is no selection
337 SolarMutexGuard aGuard
;
342 if ( !mpTableInfo
|| nColumn
< 0 || nRow
< 0 || nColumn
>= mpTableInfo
->GetCols() || nRow
>= mpTableInfo
->GetRows() )
343 throw lang::IndexOutOfBoundsException();
345 // index iterates horizontally
349 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleIndex( sal_Int32 nRow
, sal_Int32 nColumn
)
351 SolarMutexGuard aGuard
;
356 if ( !mpTableInfo
|| nColumn
< 0 || nRow
< 0 || nColumn
>= mpTableInfo
->GetCols() || nRow
>= mpTableInfo
->GetRows() )
357 throw lang::IndexOutOfBoundsException();
359 // index iterates horizontally
360 sal_Int32 nRet
= nRow
* mpTableInfo
->GetCols() + nColumn
;
364 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleRow( sal_Int32 nChildIndex
)
366 SolarMutexGuard aGuard
;
371 if ( !mpTableInfo
|| nChildIndex
< 0 || nChildIndex
>= static_cast<sal_Int32
>(mpTableInfo
->GetRows()) * mpTableInfo
->GetCols() )
372 throw lang::IndexOutOfBoundsException();
374 sal_Int32 nRow
= nChildIndex
/ mpTableInfo
->GetCols();
378 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumn( sal_Int32 nChildIndex
)
380 SolarMutexGuard aGuard
;
385 if ( !mpTableInfo
|| nChildIndex
< 0 || nChildIndex
>= static_cast<sal_Int32
>(mpTableInfo
->GetRows()) * mpTableInfo
->GetCols() )
386 throw lang::IndexOutOfBoundsException();
388 sal_Int32 nCol
= nChildIndex
% static_cast<sal_Int32
>(mpTableInfo
->GetCols());
392 //===== XAccessibleComponent ============================================
394 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleAtPoint( const awt::Point
& aPoint
)
396 uno::Reference
<XAccessible
> xRet
;
397 if (containsPoint(aPoint
))
399 SolarMutexGuard aGuard
;
406 SCCOL nCols
= mpTableInfo
->GetCols();
407 SCROW nRows
= mpTableInfo
->GetRows();
408 const ScPreviewColRowInfo
* pColInfo
= mpTableInfo
->GetColInfo();
409 const ScPreviewColRowInfo
* pRowInfo
= mpTableInfo
->GetRowInfo();
411 tools::Rectangle
aScreenRect(GetBoundingBox());
413 awt::Point aMovedPoint
= aPoint
;
414 aMovedPoint
.X
+= aScreenRect
.Left();
415 aMovedPoint
.Y
+= aScreenRect
.Top();
417 if ( nCols
> 0 && nRows
> 0 && aMovedPoint
.X
>= pColInfo
[0].nPixelStart
&& aMovedPoint
.Y
>= pRowInfo
[0].nPixelStart
)
420 while ( nColIndex
< nCols
&& aMovedPoint
.X
> pColInfo
[nColIndex
].nPixelEnd
)
423 while ( nRowIndex
< nRows
&& aMovedPoint
.Y
> pRowInfo
[nRowIndex
].nPixelEnd
)
425 if ( nColIndex
< nCols
&& nRowIndex
< nRows
)
429 xRet
= getAccessibleCellAt( nRowIndex
, nColIndex
);
431 catch (uno::Exception
&)
442 void SAL_CALL
ScAccessiblePreviewTable::grabFocus()
444 SolarMutexGuard aGuard
;
446 if (getAccessibleParent().is())
448 uno::Reference
<XAccessibleComponent
> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY
);
449 if (xAccessibleComponent
.is())
450 xAccessibleComponent
->grabFocus();
454 //===== XAccessibleContext ==============================================
456 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleChildCount()
458 SolarMutexGuard aGuard
;
463 tools::Long nRet
= 0;
465 nRet
= static_cast<sal_Int32
>(mpTableInfo
->GetCols()) * mpTableInfo
->GetRows();
469 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleChild( sal_Int32 nIndex
)
471 SolarMutexGuard aGuard
;
476 uno::Reference
<XAccessible
> xRet
;
479 sal_Int32 nColumns
= mpTableInfo
->GetCols();
482 // nCol, nRow are within the visible table, not the document
483 sal_Int32 nCol
= nIndex
% nColumns
;
484 sal_Int32 nRow
= nIndex
/ nColumns
;
486 xRet
= getAccessibleCellAt( nRow
, nCol
);
491 throw lang::IndexOutOfBoundsException();
496 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleIndexInParent()
501 uno::Reference
< XAccessibleStateSet
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleStateSet()
503 SolarMutexGuard aGuard
;
504 uno::Reference
<XAccessibleStateSet
> xParentStates
;
505 if (getAccessibleParent().is())
507 uno::Reference
<XAccessibleContext
> xParentContext
= getAccessibleParent()->getAccessibleContext();
508 xParentStates
= xParentContext
->getAccessibleStateSet();
510 utl::AccessibleStateSetHelper
* pStateSet
= new utl::AccessibleStateSetHelper();
511 if (IsDefunc(xParentStates
))
512 pStateSet
->AddState(AccessibleStateType::DEFUNC
);
515 pStateSet
->AddState(AccessibleStateType::MANAGES_DESCENDANTS
);
516 pStateSet
->AddState(AccessibleStateType::ENABLED
);
517 pStateSet
->AddState(AccessibleStateType::OPAQUE
);
519 pStateSet
->AddState(AccessibleStateType::SHOWING
);
521 pStateSet
->AddState(AccessibleStateType::VISIBLE
);
526 //===== XServiceInfo ====================================================
528 OUString SAL_CALL
ScAccessiblePreviewTable::getImplementationName()
530 return "ScAccessiblePreviewTable";
533 uno::Sequence
<OUString
> SAL_CALL
ScAccessiblePreviewTable::getSupportedServiceNames()
535 uno::Sequence
< OUString
> aSequence
= ScAccessibleContextBase::getSupportedServiceNames();
536 sal_Int32
nOldSize(aSequence
.getLength());
537 aSequence
.realloc(nOldSize
+ 1);
539 aSequence
[nOldSize
] = "com.sun.star.table.AccessibleTableView";
544 //===== XTypeProvider ===================================================
546 uno::Sequence
< uno::Type
> SAL_CALL
ScAccessiblePreviewTable::getTypes()
548 return comphelper::concatSequences(ScAccessiblePreviewTableImpl::getTypes(), ScAccessibleContextBase::getTypes());
551 uno::Sequence
<sal_Int8
> SAL_CALL
ScAccessiblePreviewTable::getImplementationId()
553 return css::uno::Sequence
<sal_Int8
>();
556 //==== internal =========================================================
558 OUString
ScAccessiblePreviewTable::createAccessibleDescription()
560 return STR_ACC_TABLE_DESCR
;
563 OUString
ScAccessiblePreviewTable::createAccessibleName()
565 OUString
sName(ScResId(STR_ACC_TABLE_NAME
));
574 if (mpViewShell
->GetDocument().GetName( mpTableInfo
->GetTab(), sCoreName
))
575 sName
= sName
.replaceFirst("%1", sCoreName
);
582 tools::Rectangle
ScAccessiblePreviewTable::GetBoundingBoxOnScreen() const
584 tools::Rectangle
aCellRect(GetBoundingBox());
587 vcl::Window
* pWindow
= mpViewShell
->GetWindow();
590 tools::Rectangle aRect
= pWindow
->GetWindowExtentsRelative(nullptr);
591 aCellRect
.setX(aCellRect
.getX() + aRect
.getX());
592 aCellRect
.setY(aCellRect
.getY() + aRect
.getY());
598 tools::Rectangle
ScAccessiblePreviewTable::GetBoundingBox() const
602 tools::Rectangle aRect
;
605 SCCOL nColumns
= mpTableInfo
->GetCols();
606 SCROW nRows
= mpTableInfo
->GetRows();
607 if ( nColumns
> 0 && nRows
> 0 )
609 const ScPreviewColRowInfo
* pColInfo
= mpTableInfo
->GetColInfo();
610 const ScPreviewColRowInfo
* pRowInfo
= mpTableInfo
->GetRowInfo();
612 aRect
= tools::Rectangle( pColInfo
[0].nPixelStart
,
613 pRowInfo
[0].nPixelStart
,
614 pColInfo
[nColumns
-1].nPixelEnd
,
615 pRowInfo
[nRows
-1].nPixelEnd
);
621 bool ScAccessiblePreviewTable::IsDefunc( const uno::Reference
<XAccessibleStateSet
>& rxParentStates
)
623 return ScAccessibleContextBase::IsDefunc() || (mpViewShell
== nullptr) || !getAccessibleParent().is() ||
624 (rxParentStates
.is() && rxParentStates
->contains(AccessibleStateType::DEFUNC
));
627 void ScAccessiblePreviewTable::FillTableInfo() const
629 if ( mpViewShell
&& !mpTableInfo
)
632 vcl::Window
* pWindow
= mpViewShell
->GetWindow();
634 aOutputSize
= pWindow
->GetOutputSizePixel();
635 tools::Rectangle
aVisRect( Point(), aOutputSize
);
637 mpTableInfo
.reset( new ScPreviewTableInfo
);
638 mpViewShell
->GetLocationData().GetTableInfo( aVisRect
, *mpTableInfo
);
642 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */