tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / Accessibility / AccessiblePreviewTable.cxx
blob5dfc06ca063bf9ebe68e571ec941493d2e6fd275
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
26 #include <attrib.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 ),
51 mnIndex( nIndex )
53 if (mpViewShell)
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 );
63 dispose();
67 void SAL_CALL ScAccessiblePreviewTable::disposing()
69 SolarMutexGuard aGuard;
70 if (mpViewShell)
72 mpViewShell->RemoveAccessibilityObject(*this);
73 mpViewShell = nullptr;
76 mpTableInfo.reset();
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
90 mpTableInfo.reset();
92 else if (nId == SfxHintId::ScAccVisAreaChanged)
94 AccessibleEventObject aEvent;
95 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
96 aEvent.Source = uno::Reference< XAccessibleContext >(this);
97 CommitChange(aEvent);
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()
112 noexcept
114 ScAccessibleContextBase::acquire();
117 void SAL_CALL ScAccessiblePreviewTable::release()
118 noexcept
120 ScAccessibleContextBase::release();
123 //===== XAccessibleTable ================================================
125 sal_Int32 SAL_CALL ScAccessiblePreviewTable::getAccessibleRowCount()
127 SolarMutexGuard aGuard;
128 IsObjectValid();
130 FillTableInfo();
132 sal_Int32 nRet = 0;
133 if ( mpTableInfo )
134 nRet = mpTableInfo->GetRows();
135 return nRet;
138 sal_Int32 SAL_CALL ScAccessiblePreviewTable::getAccessibleColumnCount()
140 SolarMutexGuard aGuard;
141 IsObjectValid();
143 FillTableInfo();
145 sal_Int32 nRet = 0;
146 if ( mpTableInfo )
147 nRet = mpTableInfo->GetCols();
148 return nRet;
151 OUString SAL_CALL ScAccessiblePreviewTable::getAccessibleRowDescription( sal_Int32 nRow )
153 SolarMutexGuard aGuard;
154 FillTableInfo();
155 if ( nRow < 0 || (mpTableInfo && nRow >= mpTableInfo->GetRows()) )
156 throw lang::IndexOutOfBoundsException();
158 return OUString();
161 OUString SAL_CALL ScAccessiblePreviewTable::getAccessibleColumnDescription( sal_Int32 nColumn )
163 SolarMutexGuard aGuard;
164 FillTableInfo();
165 if ( nColumn < 0 || (mpTableInfo && nColumn >= mpTableInfo->GetCols()) )
166 throw lang::IndexOutOfBoundsException();
168 return OUString();
171 sal_Int32 SAL_CALL ScAccessiblePreviewTable::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
173 SolarMutexGuard aGuard;
174 IsObjectValid();
176 FillTableInfo();
178 sal_Int32 nRows = 1;
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
190 else
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();
199 return nRows;
202 sal_Int32 SAL_CALL ScAccessiblePreviewTable::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
204 SolarMutexGuard aGuard;
205 IsObjectValid();
207 FillTableInfo();
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
221 else
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();
230 return nColumns;
233 uno::Reference< XAccessibleTable > SAL_CALL ScAccessiblePreviewTable::getAccessibleRowHeaders()
235 //! missing
236 return nullptr;
239 uno::Reference< XAccessibleTable > SAL_CALL ScAccessiblePreviewTable::getAccessibleColumnHeaders()
241 //! missing
242 return nullptr;
245 uno::Sequence< sal_Int32 > SAL_CALL ScAccessiblePreviewTable::getSelectedAccessibleRows()
247 // in the page preview, there is no selection
248 return {};
251 uno::Sequence< sal_Int32 > SAL_CALL ScAccessiblePreviewTable::getSelectedAccessibleColumns()
253 // in the page preview, there is no selection
254 return {};
257 sal_Bool SAL_CALL ScAccessiblePreviewTable::isAccessibleRowSelected( sal_Int32 nRow )
259 // in the page preview, there is no selection
261 SolarMutexGuard aGuard;
262 FillTableInfo();
263 if ( nRow < 0 || (mpTableInfo && nRow >= mpTableInfo->GetRows()) )
264 throw lang::IndexOutOfBoundsException();
266 return false;
269 sal_Bool SAL_CALL ScAccessiblePreviewTable::isAccessibleColumnSelected( sal_Int32 nColumn )
271 // in the page preview, there is no selection
273 SolarMutexGuard aGuard;
274 FillTableInfo();
275 if ( nColumn < 0 || (mpTableInfo && nColumn >= mpTableInfo->GetCols()) )
276 throw lang::IndexOutOfBoundsException();
278 return false;
281 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewTable::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
283 SolarMutexGuard aGuard;
284 IsObjectValid();
286 FillTableInfo();
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();
305 pHeaderCell->Init();
307 else
309 rtl::Reference<ScAccessiblePreviewCell> pCell(new ScAccessiblePreviewCell( this, mpViewShell, aCellPos, nNewIndex ));
310 xRet = pCell.get();
311 pCell->Init();
315 if ( !xRet.is() )
316 throw lang::IndexOutOfBoundsException();
318 return xRet;
321 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewTable::getAccessibleCaption()
323 //! missing
324 return nullptr;
327 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewTable::getAccessibleSummary()
329 //! missing
330 return nullptr;
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;
337 IsObjectValid();
339 FillTableInfo();
341 if ( !mpTableInfo || nColumn < 0 || nRow < 0 || nColumn >= mpTableInfo->GetCols() || nRow >= mpTableInfo->GetRows() )
342 throw lang::IndexOutOfBoundsException();
344 // index iterates horizontally
345 return false;
348 sal_Int64 SAL_CALL ScAccessiblePreviewTable::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
350 SolarMutexGuard aGuard;
351 IsObjectValid();
353 FillTableInfo();
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;
360 return nRet;
363 sal_Int32 SAL_CALL ScAccessiblePreviewTable::getAccessibleRow( sal_Int64 nChildIndex )
365 SolarMutexGuard aGuard;
366 IsObjectValid();
368 FillTableInfo();
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();
374 return nRow;
377 sal_Int32 SAL_CALL ScAccessiblePreviewTable::getAccessibleColumn( sal_Int64 nChildIndex )
379 SolarMutexGuard aGuard;
380 IsObjectValid();
382 FillTableInfo();
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());
388 return nCol;
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;
399 IsObjectValid();
401 FillTableInfo();
403 if ( mpTableInfo )
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 )
418 SCCOL nColIndex = 0;
419 while ( nColIndex < nCols && aMovedPoint.X > pColInfo[nColIndex].nPixelEnd )
420 ++nColIndex;
421 SCROW nRowIndex = 0;
422 while ( nRowIndex < nRows && aMovedPoint.Y > pRowInfo[nRowIndex].nPixelEnd )
423 ++nRowIndex;
424 if ( nColIndex < nCols && nRowIndex < nRows )
428 xRet = getAccessibleCellAt( nRowIndex, nColIndex );
430 catch (uno::Exception&)
438 return xRet;
441 void SAL_CALL ScAccessiblePreviewTable::grabFocus()
443 SolarMutexGuard aGuard;
444 IsObjectValid();
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;
458 IsObjectValid();
460 FillTableInfo();
462 tools::Long nRet = 0;
463 if ( mpTableInfo )
464 nRet = static_cast<sal_Int64>(mpTableInfo->GetCols()) * mpTableInfo->GetRows();
465 return nRet;
468 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewTable::getAccessibleChild( sal_Int64 nIndex )
470 SolarMutexGuard aGuard;
471 IsObjectValid();
473 FillTableInfo();
475 uno::Reference<XAccessible> xRet;
476 if ( mpTableInfo )
478 sal_Int32 nColumns = mpTableInfo->GetCols();
479 if ( nColumns > 0 )
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 );
489 if ( !xRet.is() )
490 throw lang::IndexOutOfBoundsException();
492 return xRet;
495 sal_Int64 SAL_CALL ScAccessiblePreviewTable::getAccessibleIndexInParent()
497 return mnIndex;
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;
512 else
514 nStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
515 nStateSet |= AccessibleStateType::ENABLED;
516 nStateSet |= AccessibleStateType::OPAQUE;
517 if (isShowing())
518 nStateSet |= AccessibleStateType::SHOWING;
519 if (isVisible())
520 nStateSet |= AccessibleStateType::VISIBLE;
522 return nStateSet;
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";
540 return aSequence;
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));
566 if (mpViewShell)
568 FillTableInfo();
570 if ( mpTableInfo )
572 OUString sCoreName;
573 if (mpViewShell->GetDocument().GetName( mpTableInfo->GetTab(), sCoreName ))
574 sName = sName.replaceFirst("%1", sCoreName);
578 return sName;
581 AbsoluteScreenPixelRectangle ScAccessiblePreviewTable::GetBoundingBoxOnScreen() const
583 tools::Rectangle aCellRect(GetBoundingBox());
584 if (mpViewShell)
586 vcl::Window* pWindow = mpViewShell->GetWindow();
587 if (pWindow)
589 AbsoluteScreenPixelRectangle aRect = pWindow->GetWindowExtentsAbsolute();
590 aCellRect.Move(aRect.Left(), aRect.Top());
593 return AbsoluteScreenPixelRectangle(aCellRect);
596 tools::Rectangle ScAccessiblePreviewTable::GetBoundingBox() const
598 FillTableInfo();
600 tools::Rectangle aRect;
601 if ( mpTableInfo )
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 );
616 return aRect;
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 )
629 Size aOutputSize;
630 vcl::Window* pWindow = mpViewShell->GetWindow();
631 if ( pWindow )
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: */