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 <comphelper/sequence.hxx>
42 using namespace ::com::sun::star
;
43 using namespace ::com::sun::star::accessibility
;
45 //===== internal ============================================================
47 ScAccessiblePreviewTable::ScAccessiblePreviewTable( const css::uno::Reference
<css::accessibility::XAccessible
>& rxParent
,
48 ScPreviewShell
* pViewShell
, sal_Int32 nIndex
) :
49 ScAccessibleContextBase( rxParent
, AccessibleRole::TABLE
),
50 mpViewShell( pViewShell
),
54 mpViewShell
->AddAccessibilityObject(*this);
57 ScAccessiblePreviewTable::~ScAccessiblePreviewTable()
59 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper
.bInDispose
)
61 // increment refcount to prevent double call off dtor
62 osl_atomic_increment( &m_refCount
);
67 void SAL_CALL
ScAccessiblePreviewTable::disposing()
69 SolarMutexGuard aGuard
;
72 mpViewShell
->RemoveAccessibilityObject(*this);
73 mpViewShell
= nullptr;
78 ScAccessibleContextBase::disposing();
81 //===== SfxListener =====================================================
83 void ScAccessiblePreviewTable::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
85 const SfxHintId nId
= rHint
.GetId();
86 if ( nId
== SfxHintId::DataChanged
)
88 // column / row layout may change with any document change,
89 // so it must be invalidated
92 else if (nId
== SfxHintId::ScAccVisAreaChanged
)
94 AccessibleEventObject aEvent
;
95 aEvent
.EventId
= AccessibleEventId::VISIBLE_DATA_CHANGED
;
96 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
100 ScAccessibleContextBase::Notify(rBC
, rHint
);
103 //===== XInterface =====================================================
105 uno::Any SAL_CALL
ScAccessiblePreviewTable::queryInterface( uno::Type
const & rType
)
107 uno::Any
aAny (ScAccessiblePreviewTableImpl::queryInterface(rType
));
108 return aAny
.hasValue() ? aAny
: ScAccessibleContextBase::queryInterface(rType
);
111 void SAL_CALL
ScAccessiblePreviewTable::acquire()
114 ScAccessibleContextBase::acquire();
117 void SAL_CALL
ScAccessiblePreviewTable::release()
120 ScAccessibleContextBase::release();
123 //===== XAccessibleTable ================================================
125 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleRowCount()
127 SolarMutexGuard aGuard
;
134 nRet
= mpTableInfo
->GetRows();
138 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumnCount()
140 SolarMutexGuard aGuard
;
147 nRet
= mpTableInfo
->GetCols();
151 OUString SAL_CALL
ScAccessiblePreviewTable::getAccessibleRowDescription( sal_Int32 nRow
)
153 SolarMutexGuard aGuard
;
155 if ( nRow
< 0 || (mpTableInfo
&& nRow
>= mpTableInfo
->GetRows()) )
156 throw lang::IndexOutOfBoundsException();
161 OUString SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumnDescription( sal_Int32 nColumn
)
163 SolarMutexGuard aGuard
;
165 if ( nColumn
< 0 || (mpTableInfo
&& nColumn
>= mpTableInfo
->GetCols()) )
166 throw lang::IndexOutOfBoundsException();
171 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleRowExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
173 SolarMutexGuard aGuard
;
179 if ( !mpViewShell
|| !mpTableInfo
|| nColumn
< 0 || nRow
< 0 ||
180 nColumn
>= mpTableInfo
->GetCols() || nRow
>= mpTableInfo
->GetRows() )
181 throw lang::IndexOutOfBoundsException();
183 const ScPreviewColRowInfo
& rColInfo
= mpTableInfo
->GetColInfo()[nColumn
];
184 const ScPreviewColRowInfo
& rRowInfo
= mpTableInfo
->GetRowInfo()[nRow
];
186 if ( rColInfo
.bIsHeader
|| rRowInfo
.bIsHeader
)
188 // header cells only span a single cell
192 ScDocument
& rDoc
= mpViewShell
->GetDocument();
193 const ScMergeAttr
* pItem
= rDoc
.GetAttr(
194 static_cast<SCCOL
>(rColInfo
.nDocIndex
), static_cast<SCROW
>(rRowInfo
.nDocIndex
), mpTableInfo
->GetTab(), ATTR_MERGE
);
195 if ( pItem
&& pItem
->GetRowMerge() > 0 )
196 nRows
= pItem
->GetRowMerge();
202 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumnExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
204 SolarMutexGuard aGuard
;
209 sal_Int32 nColumns
= 1;
210 if ( !mpViewShell
|| !mpTableInfo
|| nColumn
< 0 || nRow
< 0 ||
211 nColumn
>= mpTableInfo
->GetCols() || nRow
>= mpTableInfo
->GetRows() )
212 throw lang::IndexOutOfBoundsException();
214 const ScPreviewColRowInfo
& rColInfo
= mpTableInfo
->GetColInfo()[nColumn
];
215 const ScPreviewColRowInfo
& rRowInfo
= mpTableInfo
->GetRowInfo()[nRow
];
217 if ( rColInfo
.bIsHeader
|| rRowInfo
.bIsHeader
)
219 // header cells only span a single cell
223 ScDocument
& rDoc
= mpViewShell
->GetDocument();
224 const ScMergeAttr
* pItem
= rDoc
.GetAttr(
225 static_cast<SCCOL
>(rColInfo
.nDocIndex
), static_cast<SCROW
>(rRowInfo
.nDocIndex
), mpTableInfo
->GetTab(), ATTR_MERGE
);
226 if ( pItem
&& pItem
->GetColMerge() > 0 )
227 nColumns
= pItem
->GetColMerge();
233 uno::Reference
< XAccessibleTable
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleRowHeaders()
239 uno::Reference
< XAccessibleTable
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumnHeaders()
245 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessiblePreviewTable::getSelectedAccessibleRows()
247 // in the page preview, there is no selection
251 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessiblePreviewTable::getSelectedAccessibleColumns()
253 // in the page preview, there is no selection
257 sal_Bool SAL_CALL
ScAccessiblePreviewTable::isAccessibleRowSelected( sal_Int32 nRow
)
259 // in the page preview, there is no selection
261 SolarMutexGuard aGuard
;
263 if ( nRow
< 0 || (mpTableInfo
&& nRow
>= mpTableInfo
->GetRows()) )
264 throw lang::IndexOutOfBoundsException();
269 sal_Bool SAL_CALL
ScAccessiblePreviewTable::isAccessibleColumnSelected( sal_Int32 nColumn
)
271 // in the page preview, there is no selection
273 SolarMutexGuard aGuard
;
275 if ( nColumn
< 0 || (mpTableInfo
&& nColumn
>= mpTableInfo
->GetCols()) )
276 throw lang::IndexOutOfBoundsException();
281 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleCellAt( sal_Int32 nRow
, sal_Int32 nColumn
)
283 SolarMutexGuard aGuard
;
288 uno::Reference
<XAccessible
> xRet
;
289 if ( mpTableInfo
&& nColumn
>= 0 && nRow
>= 0 && nColumn
< mpTableInfo
->GetCols() && nRow
< mpTableInfo
->GetRows() )
291 // index iterates horizontally
292 tools::Long nNewIndex
= nRow
* mpTableInfo
->GetCols() + nColumn
;
294 const ScPreviewColRowInfo
& rColInfo
= mpTableInfo
->GetColInfo()[nColumn
];
295 const ScPreviewColRowInfo
& rRowInfo
= mpTableInfo
->GetRowInfo()[nRow
];
297 ScAddress
aCellPos( static_cast<SCCOL
>(rColInfo
.nDocIndex
), static_cast<SCROW
>(rRowInfo
.nDocIndex
), mpTableInfo
->GetTab() );
298 if ( rColInfo
.bIsHeader
|| rRowInfo
.bIsHeader
)
300 const bool bRotatedColHeader
= rRowInfo
.bIsHeader
;
301 const bool bRotatedRowHeader
= rColInfo
.bIsHeader
;
302 rtl::Reference
<ScAccessiblePreviewHeaderCell
> pHeaderCell(new ScAccessiblePreviewHeaderCell(this, mpViewShell
, aCellPos
,
303 bRotatedColHeader
, bRotatedRowHeader
, nNewIndex
));
304 xRet
= pHeaderCell
.get();
309 rtl::Reference
<ScAccessiblePreviewCell
> pCell(new ScAccessiblePreviewCell( this, mpViewShell
, aCellPos
, nNewIndex
));
316 throw lang::IndexOutOfBoundsException();
321 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleCaption()
327 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleSummary()
333 sal_Bool SAL_CALL
ScAccessiblePreviewTable::isAccessibleSelected( sal_Int32 nRow
, sal_Int32 nColumn
)
335 // in the page preview, there is no selection
336 SolarMutexGuard aGuard
;
341 if ( !mpTableInfo
|| nColumn
< 0 || nRow
< 0 || nColumn
>= mpTableInfo
->GetCols() || nRow
>= mpTableInfo
->GetRows() )
342 throw lang::IndexOutOfBoundsException();
344 // index iterates horizontally
348 sal_Int64 SAL_CALL
ScAccessiblePreviewTable::getAccessibleIndex( sal_Int32 nRow
, sal_Int32 nColumn
)
350 SolarMutexGuard aGuard
;
355 if ( !mpTableInfo
|| nColumn
< 0 || nRow
< 0 || nColumn
>= mpTableInfo
->GetCols() || nRow
>= mpTableInfo
->GetRows() )
356 throw lang::IndexOutOfBoundsException();
358 // index iterates horizontally
359 sal_Int64 nRet
= static_cast<sal_Int64
>(nRow
) * static_cast<sal_Int64
>(mpTableInfo
->GetCols()) + nColumn
;
363 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleRow( sal_Int64 nChildIndex
)
365 SolarMutexGuard aGuard
;
370 if ( !mpTableInfo
|| nChildIndex
< 0 || nChildIndex
>= static_cast<sal_Int64
>(mpTableInfo
->GetRows()) * mpTableInfo
->GetCols() )
371 throw lang::IndexOutOfBoundsException();
373 sal_Int32 nRow
= nChildIndex
/ mpTableInfo
->GetCols();
377 sal_Int32 SAL_CALL
ScAccessiblePreviewTable::getAccessibleColumn( sal_Int64 nChildIndex
)
379 SolarMutexGuard aGuard
;
384 if ( !mpTableInfo
|| nChildIndex
< 0 || nChildIndex
>= static_cast<sal_Int64
>(mpTableInfo
->GetRows()) * mpTableInfo
->GetCols() )
385 throw lang::IndexOutOfBoundsException();
387 sal_Int32 nCol
= nChildIndex
% static_cast<sal_Int32
>(mpTableInfo
->GetCols());
391 //===== XAccessibleComponent ============================================
393 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleAtPoint( const awt::Point
& aPoint
)
395 uno::Reference
<XAccessible
> xRet
;
396 if (containsPoint(aPoint
))
398 SolarMutexGuard aGuard
;
405 SCCOL nCols
= mpTableInfo
->GetCols();
406 SCROW nRows
= mpTableInfo
->GetRows();
407 const ScPreviewColRowInfo
* pColInfo
= mpTableInfo
->GetColInfo();
408 const ScPreviewColRowInfo
* pRowInfo
= mpTableInfo
->GetRowInfo();
410 tools::Rectangle
aScreenRect(GetBoundingBox());
412 awt::Point aMovedPoint
= aPoint
;
413 aMovedPoint
.X
+= aScreenRect
.Left();
414 aMovedPoint
.Y
+= aScreenRect
.Top();
416 if ( nCols
> 0 && nRows
> 0 && aMovedPoint
.X
>= pColInfo
[0].nPixelStart
&& aMovedPoint
.Y
>= pRowInfo
[0].nPixelStart
)
419 while ( nColIndex
< nCols
&& aMovedPoint
.X
> pColInfo
[nColIndex
].nPixelEnd
)
422 while ( nRowIndex
< nRows
&& aMovedPoint
.Y
> pRowInfo
[nRowIndex
].nPixelEnd
)
424 if ( nColIndex
< nCols
&& nRowIndex
< nRows
)
428 xRet
= getAccessibleCellAt( nRowIndex
, nColIndex
);
430 catch (uno::Exception
&)
441 void SAL_CALL
ScAccessiblePreviewTable::grabFocus()
443 SolarMutexGuard aGuard
;
445 if (getAccessibleParent().is())
447 uno::Reference
<XAccessibleComponent
> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY
);
448 if (xAccessibleComponent
.is())
449 xAccessibleComponent
->grabFocus();
453 //===== XAccessibleContext ==============================================
455 sal_Int64 SAL_CALL
ScAccessiblePreviewTable::getAccessibleChildCount()
457 SolarMutexGuard aGuard
;
462 tools::Long nRet
= 0;
464 nRet
= static_cast<sal_Int64
>(mpTableInfo
->GetCols()) * mpTableInfo
->GetRows();
468 uno::Reference
< XAccessible
> SAL_CALL
ScAccessiblePreviewTable::getAccessibleChild( sal_Int64 nIndex
)
470 SolarMutexGuard aGuard
;
475 uno::Reference
<XAccessible
> xRet
;
478 sal_Int32 nColumns
= mpTableInfo
->GetCols();
481 // nCol, nRow are within the visible table, not the document
482 sal_Int32 nCol
= nIndex
% nColumns
;
483 sal_Int64 nRow
= nIndex
/ nColumns
;
484 assert(nRow
<= std::numeric_limits
<sal_Int32
>::max());
485 xRet
= getAccessibleCellAt( nRow
, nCol
);
490 throw lang::IndexOutOfBoundsException();
495 sal_Int64 SAL_CALL
ScAccessiblePreviewTable::getAccessibleIndexInParent()
500 sal_Int64 SAL_CALL
ScAccessiblePreviewTable::getAccessibleStateSet()
502 SolarMutexGuard aGuard
;
503 sal_Int64 nParentStates
= 0;
504 if (getAccessibleParent().is())
506 uno::Reference
<XAccessibleContext
> xParentContext
= getAccessibleParent()->getAccessibleContext();
507 nParentStates
= xParentContext
->getAccessibleStateSet();
509 sal_Int64 nStateSet
= 0;
510 if (IsDefunc(nParentStates
))
511 nStateSet
|= AccessibleStateType::DEFUNC
;
514 nStateSet
|= AccessibleStateType::MANAGES_DESCENDANTS
;
515 nStateSet
|= AccessibleStateType::ENABLED
;
516 nStateSet
|= AccessibleStateType::OPAQUE
;
518 nStateSet
|= AccessibleStateType::SHOWING
;
520 nStateSet
|= AccessibleStateType::VISIBLE
;
525 //===== XServiceInfo ====================================================
527 OUString SAL_CALL
ScAccessiblePreviewTable::getImplementationName()
529 return u
"ScAccessiblePreviewTable"_ustr
;
532 uno::Sequence
<OUString
> SAL_CALL
ScAccessiblePreviewTable::getSupportedServiceNames()
534 uno::Sequence
< OUString
> aSequence
= ScAccessibleContextBase::getSupportedServiceNames();
535 sal_Int32
nOldSize(aSequence
.getLength());
536 aSequence
.realloc(nOldSize
+ 1);
538 aSequence
.getArray()[nOldSize
] = "com.sun.star.table.AccessibleTableView";
543 //===== XTypeProvider ===================================================
545 uno::Sequence
< uno::Type
> SAL_CALL
ScAccessiblePreviewTable::getTypes()
547 return comphelper::concatSequences(ScAccessiblePreviewTableImpl::getTypes(), ScAccessibleContextBase::getTypes());
550 uno::Sequence
<sal_Int8
> SAL_CALL
ScAccessiblePreviewTable::getImplementationId()
552 return css::uno::Sequence
<sal_Int8
>();
555 //==== internal =========================================================
557 OUString
ScAccessiblePreviewTable::createAccessibleDescription()
559 return STR_ACC_TABLE_DESCR
;
562 OUString
ScAccessiblePreviewTable::createAccessibleName()
564 OUString
sName(ScResId(STR_ACC_TABLE_NAME
));
573 if (mpViewShell
->GetDocument().GetName( mpTableInfo
->GetTab(), sCoreName
))
574 sName
= sName
.replaceFirst("%1", sCoreName
);
581 AbsoluteScreenPixelRectangle
ScAccessiblePreviewTable::GetBoundingBoxOnScreen() const
583 tools::Rectangle
aCellRect(GetBoundingBox());
586 vcl::Window
* pWindow
= mpViewShell
->GetWindow();
589 AbsoluteScreenPixelRectangle aRect
= pWindow
->GetWindowExtentsAbsolute();
590 aCellRect
.Move(aRect
.Left(), aRect
.Top());
593 return AbsoluteScreenPixelRectangle(aCellRect
);
596 tools::Rectangle
ScAccessiblePreviewTable::GetBoundingBox() const
600 tools::Rectangle aRect
;
603 SCCOL nColumns
= mpTableInfo
->GetCols();
604 SCROW nRows
= mpTableInfo
->GetRows();
605 if ( nColumns
> 0 && nRows
> 0 )
607 const ScPreviewColRowInfo
* pColInfo
= mpTableInfo
->GetColInfo();
608 const ScPreviewColRowInfo
* pRowInfo
= mpTableInfo
->GetRowInfo();
610 aRect
= tools::Rectangle( pColInfo
[0].nPixelStart
,
611 pRowInfo
[0].nPixelStart
,
612 pColInfo
[nColumns
-1].nPixelEnd
,
613 pRowInfo
[nRows
-1].nPixelEnd
);
619 bool ScAccessiblePreviewTable::IsDefunc( sal_Int64 nParentStates
)
621 return ScAccessibleContextBase::IsDefunc() || (mpViewShell
== nullptr) || !getAccessibleParent().is() ||
622 (nParentStates
& AccessibleStateType::DEFUNC
);
625 void ScAccessiblePreviewTable::FillTableInfo() const
627 if ( mpViewShell
&& !mpTableInfo
)
630 vcl::Window
* pWindow
= mpViewShell
->GetWindow();
632 aOutputSize
= pWindow
->GetOutputSizePixel();
633 tools::Rectangle
aVisRect( Point(), aOutputSize
);
635 mpTableInfo
.reset( new ScPreviewTableInfo
);
636 mpViewShell
->GetLocationData().GetTableInfo( aVisRect
, *mpTableInfo
);
640 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */