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 <sal/log.hxx>
24 #include <com/sun/star/accessibility/AccessibleRole.hpp>
25 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
26 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
27 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
28 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <o3tl/safeint.hxx>
31 #include <vcl/svapp.hxx>
34 #include <cellfrm.hxx>
35 #include <swtable.hxx>
38 #include "accfrmobjslist.hxx"
40 #include <strings.hrc>
41 #include "acctable.hxx"
43 #include <com/sun/star/accessibility/XAccessibleText.hpp>
45 #include <editeng/brushitem.hxx>
46 #include <swatrset.hxx>
49 #include <cppuhelper/supportsservice.hxx>
50 #include <cppuhelper/typeprovider.hxx>
52 using namespace ::com::sun::star
;
53 using namespace ::com::sun::star::accessibility
;
54 using namespace ::sw::access
;
56 typedef o3tl::sorted_vector
< sal_Int32
> Int32Set_Impl
;
58 const unsigned int SELECTION_WITH_NUM
= 10;
62 class SwAccTableSelHandler_Impl
65 virtual void Unselect( sal_Int32 nRowOrCol
, sal_Int32 nExt
) = 0;
68 ~SwAccTableSelHandler_Impl() {}
73 class SwAccessibleTableData_Impl
75 SwAccessibleMap
& mrAccMap
;
77 Int32Set_Impl maColumns
;
79 const SwTabFrame
*mpTabFrame
;
80 bool mbIsInPagePreview
;
81 bool mbOnlyTableColumnHeader
;
83 void CollectData( const SwFrame
*pFrame
);
85 bool FindCell( const Point
& rPos
, const SwFrame
*pFrame
,
86 bool bExact
, const SwFrame
*& rFrame
) const;
88 void GetSelection( const Point
& rTabPos
, const SwRect
& rArea
,
89 const SwSelBoxes
& rSelBoxes
, const SwFrame
*pFrame
,
90 SwAccTableSelHandler_Impl
& rSelHdl
,
91 bool bColumns
) const;
94 bool IncludeRow( const SwFrame
& rFrame
) const
96 return !mbOnlyTableColumnHeader
||
97 mpTabFrame
->IsInHeadline( rFrame
);
100 // #i77106# - add third optional parameter <bOnlyTableColumnHeader>, default value <false>
101 SwAccessibleTableData_Impl( SwAccessibleMap
& rAccMap
,
102 const SwTabFrame
*pTabFrame
,
103 bool bIsInPagePreview
,
104 bool bOnlyTableColumnHeader
= false );
106 const Int32Set_Impl
& GetRows() const { return maRows
; }
107 const Int32Set_Impl
& GetColumns() const { return maColumns
; }
109 inline Int32Set_Impl::const_iterator
GetRowIter( sal_Int32 nRow
) const;
110 inline Int32Set_Impl::const_iterator
GetColumnIter( sal_Int32 nCol
) const;
112 /// @throws lang::IndexOutOfBoundsException
113 /// @throws uno::RuntimeException
114 const SwFrame
*GetCell( sal_Int32 nRow
, sal_Int32 nColumn
, SwAccessibleTable
*pThis
) const;
115 const SwFrame
*GetCellAtPos( sal_Int32 nLeft
, sal_Int32 nTop
) const;
116 inline sal_Int32
GetRowCount() const;
117 inline sal_Int32
GetColumnCount() const;
118 bool CompareExtents( const SwAccessibleTableData_Impl
& r
) const;
120 void GetSelection( sal_Int32 nStart
, sal_Int32 nEnd
,
121 const SwSelBoxes
& rSelBoxes
,
122 SwAccTableSelHandler_Impl
& rSelHdl
,
123 bool bColumns
) const;
125 /// @throws lang::IndexOutOfBoundsException
126 void CheckRowAndCol( sal_Int32 nRow
, sal_Int32 nCol
,
127 SwAccessibleTable
*pThis
) const;
129 const Point
& GetTablePos() const { return maTabFramePos
; }
130 void SetTablePos( const Point
& rPos
) { maTabFramePos
= rPos
; }
133 void SwAccessibleTableData_Impl::CollectData( const SwFrame
*pFrame
)
135 const SwAccessibleChildSList
aList( *pFrame
, mrAccMap
);
136 SwAccessibleChildSList::const_iterator
aIter( aList
.begin() );
137 SwAccessibleChildSList::const_iterator
aEndIter( aList
.end() );
138 while( aIter
!= aEndIter
)
140 const SwAccessibleChild
& rLower
= *aIter
;
141 const SwFrame
*pLower
= rLower
.GetSwFrame();
144 if( pLower
->IsRowFrame() )
147 if ( IncludeRow( *pLower
) )
149 maRows
.insert( pLower
->getFrameArea().Top() - maTabFramePos
.getY() );
150 CollectData( pLower
);
153 else if( pLower
->IsCellFrame() &&
154 rLower
.IsAccessible( mbIsInPagePreview
) )
156 maColumns
.insert( pLower
->getFrameArea().Left() - maTabFramePos
.getX() );
160 CollectData( pLower
);
167 bool SwAccessibleTableData_Impl::FindCell(
168 const Point
& rPos
, const SwFrame
*pFrame
, bool bExact
,
169 const SwFrame
*& rRet
) const
173 const SwAccessibleChildSList
aList( *pFrame
, mrAccMap
);
174 SwAccessibleChildSList::const_iterator
aIter( aList
.begin() );
175 SwAccessibleChildSList::const_iterator
aEndIter( aList
.end() );
176 while( !bFound
&& aIter
!= aEndIter
)
178 const SwAccessibleChild
& rLower
= *aIter
;
179 const SwFrame
*pLower
= rLower
.GetSwFrame();
180 OSL_ENSURE( pLower
, "child should be a frame" );
183 if( rLower
.IsAccessible( mbIsInPagePreview
) )
185 OSL_ENSURE( pLower
->IsCellFrame(), "lower is not a cell frame" );
186 const SwRect
& rFrame
= pLower
->getFrameArea();
187 if( rFrame
.Right() >= rPos
.X() && rFrame
.Bottom() >= rPos
.Y() )
189 // We have found the cell
190 OSL_ENSURE( rFrame
.Left() <= rPos
.X() && rFrame
.Top() <= rPos
.Y(),
191 "find frame moved to far!" );
194 (rFrame
.Top() == rPos
.Y() && rFrame
.Left() == rPos
.Y() ) )
203 if ( !pLower
->IsRowFrame() ||
204 IncludeRow( *pLower
) )
206 bFound
= FindCell( rPos
, pLower
, bExact
, rRet
);
216 void SwAccessibleTableData_Impl::GetSelection(
217 const Point
& rTabPos
,
219 const SwSelBoxes
& rSelBoxes
,
220 const SwFrame
*pFrame
,
221 SwAccTableSelHandler_Impl
& rSelHdl
,
222 bool bColumns
) const
224 const SwAccessibleChildSList
aList( *pFrame
, mrAccMap
);
225 SwAccessibleChildSList::const_iterator
aIter( aList
.begin() );
226 SwAccessibleChildSList::const_iterator
aEndIter( aList
.end() );
227 while( aIter
!= aEndIter
)
229 const SwAccessibleChild
& rLower
= *aIter
;
230 const SwFrame
*pLower
= rLower
.GetSwFrame();
231 OSL_ENSURE( pLower
, "child should be a frame" );
232 const SwRect
& rBox
= rLower
.GetBox( mrAccMap
);
233 if( pLower
&& rBox
.Overlaps( rArea
) )
235 if( rLower
.IsAccessible( mbIsInPagePreview
) )
237 OSL_ENSURE( pLower
->IsCellFrame(), "lower is not a cell frame" );
238 const SwCellFrame
*pCFrame
=
239 static_cast < const SwCellFrame
* >( pLower
);
241 const_cast< SwTableBox
*>( pCFrame
->GetTabBox() );
242 if( rSelBoxes
.find( pBox
) == rSelBoxes
.end() )
244 const Int32Set_Impl rRowsOrCols
=
245 bColumns
? maColumns
: maRows
;
247 sal_Int32 nPos
= bColumns
? (rBox
.Left() - rTabPos
.X())
248 : (rBox
.Top() - rTabPos
.Y());
249 Int32Set_Impl::const_iterator
aSttRowOrCol(
250 rRowsOrCols
.lower_bound( nPos
) );
251 sal_Int32 nRowOrCol
=
252 static_cast< sal_Int32
>( std::distance(
253 rRowsOrCols
.begin(), aSttRowOrCol
) );
255 nPos
= bColumns
? (rBox
.Right() - rTabPos
.X())
256 : (rBox
.Bottom() - rTabPos
.Y());
257 Int32Set_Impl::const_iterator
aEndRowOrCol(
258 rRowsOrCols
.upper_bound( nPos
) );
260 static_cast< sal_Int32
>( std::distance(
261 aSttRowOrCol
, aEndRowOrCol
) );
263 rSelHdl
.Unselect( nRowOrCol
, nExt
);
269 if ( !pLower
->IsRowFrame() ||
270 IncludeRow( *pLower
) )
272 GetSelection( rTabPos
, rArea
, rSelBoxes
, pLower
, rSelHdl
,
281 const SwFrame
*SwAccessibleTableData_Impl::GetCell(
282 sal_Int32 nRow
, sal_Int32 nColumn
,
283 SwAccessibleTable
*pThis
) const
285 CheckRowAndCol( nRow
, nColumn
, pThis
);
287 Int32Set_Impl::const_iterator
aSttCol( GetColumnIter( nColumn
) );
288 Int32Set_Impl::const_iterator
aSttRow( GetRowIter( nRow
) );
289 const SwFrame
*pCellFrame
= GetCellAtPos( *aSttCol
, *aSttRow
);
294 void SwAccessibleTableData_Impl::GetSelection(
295 sal_Int32 nStart
, sal_Int32 nEnd
,
296 const SwSelBoxes
& rSelBoxes
,
297 SwAccTableSelHandler_Impl
& rSelHdl
,
298 bool bColumns
) const
300 SwRect
aArea( mpTabFrame
->getFrameArea() );
301 Point
aPos( aArea
.Pos() );
303 const Int32Set_Impl
& rRowsOrColumns
= bColumns
? maColumns
: maRows
;
306 Int32Set_Impl::const_iterator
aStt( rRowsOrColumns
.begin() );
308 static_cast< Int32Set_Impl::difference_type
>( nStart
) );
310 aArea
.Left( *aStt
+ aPos
.getX() );
312 aArea
.Top( *aStt
+ aPos
.getY() );
314 if( nEnd
< static_cast< sal_Int32
>( rRowsOrColumns
.size() ) )
316 Int32Set_Impl::const_iterator
aEnd( rRowsOrColumns
.begin() );
318 static_cast< Int32Set_Impl::difference_type
>( nEnd
) );
320 aArea
.Right( *aEnd
+ aPos
.getX() - 1 );
322 aArea
.Bottom( *aEnd
+ aPos
.getY() - 1 );
325 GetSelection( aPos
, aArea
, rSelBoxes
, mpTabFrame
, rSelHdl
, bColumns
);
328 const SwFrame
*SwAccessibleTableData_Impl::GetCellAtPos(
329 sal_Int32 nLeft
, sal_Int32 nTop
) const
331 Point
aPos( mpTabFrame
->getFrameArea().Pos() );
332 aPos
.Move( nLeft
, nTop
);
333 const SwFrame
*pRet
= nullptr;
334 FindCell( aPos
, mpTabFrame
, false/*bExact*/, pRet
);
339 inline sal_Int32
SwAccessibleTableData_Impl::GetRowCount() const
341 sal_Int32 count
= static_cast< sal_Int32
>( maRows
.size() ) ;
342 count
= (count
<=0)? 1:count
;
346 inline sal_Int32
SwAccessibleTableData_Impl::GetColumnCount() const
348 return static_cast< sal_Int32
>( maColumns
.size() );
351 bool SwAccessibleTableData_Impl::CompareExtents(
352 const SwAccessibleTableData_Impl
& rCmp
) const
354 return maRows
== rCmp
.maRows
355 && maColumns
== rCmp
.maColumns
;
358 SwAccessibleTableData_Impl::SwAccessibleTableData_Impl( SwAccessibleMap
& rAccMap
,
359 const SwTabFrame
*pTabFrame
,
360 bool bIsInPagePreview
,
361 bool bOnlyTableColumnHeader
)
362 : mrAccMap( rAccMap
)
363 , maTabFramePos( pTabFrame
->getFrameArea().Pos() )
364 , mpTabFrame( pTabFrame
)
365 , mbIsInPagePreview( bIsInPagePreview
)
366 , mbOnlyTableColumnHeader( bOnlyTableColumnHeader
)
368 CollectData( mpTabFrame
);
371 inline Int32Set_Impl::const_iterator
SwAccessibleTableData_Impl::GetRowIter(
372 sal_Int32 nRow
) const
374 Int32Set_Impl::const_iterator
aCol( GetRows().begin() );
378 static_cast< Int32Set_Impl::difference_type
>( nRow
) );
383 inline Int32Set_Impl::const_iterator
SwAccessibleTableData_Impl::GetColumnIter(
384 sal_Int32 nColumn
) const
386 Int32Set_Impl::const_iterator aCol
= GetColumns().begin();
390 static_cast< Int32Set_Impl::difference_type
>( nColumn
) );
395 void SwAccessibleTableData_Impl::CheckRowAndCol(
396 sal_Int32 nRow
, sal_Int32 nCol
, SwAccessibleTable
*pThis
) const
398 if( ( nRow
< 0 || o3tl::make_unsigned(nRow
) >= maRows
.size() ) ||
399 ( nCol
< 0 || o3tl::make_unsigned(nCol
) >= maColumns
.size() ) )
401 uno::Reference
< XAccessibleTable
> xThis( pThis
);
402 lang::IndexOutOfBoundsException
aExcept(
403 "row or column index out of range",
411 class SwAccSingleTableSelHandler_Impl
: public SwAccTableSelHandler_Impl
417 inline SwAccSingleTableSelHandler_Impl();
419 virtual ~SwAccSingleTableSelHandler_Impl() {}
421 bool IsSelected() const { return m_bSelected
; }
423 virtual void Unselect( sal_Int32
, sal_Int32
) override
;
428 inline SwAccSingleTableSelHandler_Impl::SwAccSingleTableSelHandler_Impl() :
433 void SwAccSingleTableSelHandler_Impl::Unselect( sal_Int32
, sal_Int32
)
440 class SwAccAllTableSelHandler_Impl
: public SwAccTableSelHandler_Impl
443 std::vector
< bool > m_aSelected
;
447 explicit SwAccAllTableSelHandler_Impl(sal_Int32 nSize
)
448 : m_aSelected(nSize
, true)
453 uno::Sequence
< sal_Int32
> GetSelSequence();
455 virtual void Unselect( sal_Int32 nRowOrCol
, sal_Int32 nExt
) override
;
456 virtual ~SwAccAllTableSelHandler_Impl();
461 SwAccAllTableSelHandler_Impl::~SwAccAllTableSelHandler_Impl()
465 uno::Sequence
< sal_Int32
> SwAccAllTableSelHandler_Impl::GetSelSequence()
467 OSL_ENSURE( m_nCount
>= 0, "underflow" );
468 uno::Sequence
< sal_Int32
> aRet( m_nCount
);
469 sal_Int32
*pRet
= aRet
.getArray();
471 size_t nSize
= m_aSelected
.size();
472 for( size_t i
=0; i
< nSize
&& nPos
< m_nCount
; i
++ )
481 OSL_ENSURE( nPos
== m_nCount
, "count is wrong" );
486 void SwAccAllTableSelHandler_Impl::Unselect( sal_Int32 nRowOrCol
,
489 OSL_ENSURE( o3tl::make_unsigned( nRowOrCol
) < m_aSelected
.size(),
491 OSL_ENSURE( o3tl::make_unsigned( nRowOrCol
+nExt
) <= m_aSelected
.size(),
492 "extent too large" );
495 if( m_aSelected
[static_cast< size_t >( nRowOrCol
)] )
497 m_aSelected
[static_cast< size_t >( nRowOrCol
)] = false;
505 const SwSelBoxes
*SwAccessibleTable::GetSelBoxes() const
507 const SwSelBoxes
*pSelBoxes
= nullptr;
508 const SwCursorShell
*pCSh
= GetCursorShell();
509 if( (pCSh
!= nullptr) && pCSh
->IsTableMode() )
511 pSelBoxes
= &pCSh
->GetTableCursor()->GetSelectedBoxes();
517 void SwAccessibleTable::FireTableChangeEvent(
518 const SwAccessibleTableData_Impl
& rTableData
)
520 AccessibleTableModelChange aModelChange
;
521 aModelChange
.Type
= AccessibleTableModelChangeType::UPDATE
;
522 aModelChange
.FirstRow
= 0;
523 aModelChange
.LastRow
= rTableData
.GetRowCount() - 1;
524 aModelChange
.FirstColumn
= 0;
525 aModelChange
.LastColumn
= rTableData
.GetColumnCount() - 1;
527 AccessibleEventObject aEvent
;
528 aEvent
.EventId
= AccessibleEventId::TABLE_MODEL_CHANGED
;
529 aEvent
.NewValue
<<= aModelChange
;
531 FireAccessibleEvent( aEvent
);
534 const SwTableBox
* SwAccessibleTable::GetTableBox( sal_Int64 nChildIndex
) const
536 OSL_ENSURE( nChildIndex
>= 0, "Illegal child index." );
537 OSL_ENSURE( nChildIndex
< const_cast<SwAccessibleTable
*>(this)->getAccessibleChildCount(), "Illegal child index." ); // #i77106#
539 const SwTableBox
* pBox
= nullptr;
541 // get table box for 'our' table cell
542 SwAccessibleChild
aCell( GetChild( *const_cast<SwAccessibleMap
*>(GetMap()), nChildIndex
) );
543 if( aCell
.GetSwFrame() )
545 const SwFrame
* pChildFrame
= aCell
.GetSwFrame();
546 if( (pChildFrame
!= nullptr) && pChildFrame
->IsCellFrame() )
548 const SwCellFrame
* pCellFrame
=
549 static_cast<const SwCellFrame
*>( pChildFrame
);
550 pBox
= pCellFrame
->GetTabBox();
554 OSL_ENSURE( pBox
!= nullptr, "We need the table box." );
558 bool SwAccessibleTable::IsChildSelected( sal_Int64 nChildIndex
) const
561 const SwSelBoxes
* pSelBoxes
= GetSelBoxes();
564 const SwTableBox
* pBox
= GetTableBox( nChildIndex
);
565 OSL_ENSURE( pBox
!= nullptr, "We need the table box." );
566 bRet
= pSelBoxes
->find( const_cast<SwTableBox
*>( pBox
) ) != pSelBoxes
->end();
572 sal_Int64
SwAccessibleTable::GetIndexOfSelectedChild(
573 sal_Int64 nSelectedChildIndex
) const
575 // iterate over all children to n-th isAccessibleChildSelected()
576 sal_Int64 nChildren
= const_cast<SwAccessibleTable
*>(this)->getAccessibleChildCount(); // #i77106#
577 if( nSelectedChildIndex
>= nChildren
)
581 while( n
< nChildren
)
583 if( IsChildSelected( n
) )
585 if( 0 == nSelectedChildIndex
)
588 --nSelectedChildIndex
;
593 return n
< nChildren
? n
: -1;
596 void SwAccessibleTable::GetStates( sal_Int64
& rStateSet
)
598 SwAccessibleContext::GetStates( rStateSet
);
599 //Add resizable state to table
600 rStateSet
|= AccessibleStateType::RESIZABLE
;
602 rStateSet
|= AccessibleStateType::MULTI_SELECTABLE
;
603 SwCursorShell
* pCursorShell
= GetCursorShell();
605 rStateSet
|= AccessibleStateType::MULTI_SELECTABLE
;
608 SwAccessibleTable::SwAccessibleTable(
609 std::shared_ptr
<SwAccessibleMap
> const& pInitMap
,
610 const SwTabFrame
* pTabFrame
) :
611 SwAccessibleContext( pInitMap
, AccessibleRole::TABLE
, pTabFrame
)
613 const SwFrameFormat
* pFrameFormat
= pTabFrame
->GetFormat();
615 StartListening(const_cast<SwFrameFormat
*>(pFrameFormat
)->GetNotifier());
617 SetName( pFrameFormat
->GetName() + "-" + OUString::number( pTabFrame
->GetPhyPageNum() ) );
619 const OUString
sArg1( static_cast< const SwTabFrame
* >( GetFrame() )->GetFormat()->GetName() );
620 const OUString
sArg2( GetFormattedPageNumber() );
622 m_sDesc
= GetResource( STR_ACCESS_TABLE_DESC
, &sArg1
, &sArg2
);
626 SwAccessibleTable::~SwAccessibleTable()
628 SolarMutexGuard aGuard
;
633 void SwAccessibleTable::Notify(const SfxHint
& rHint
)
635 const SwTabFrame
* pTabFrame
= static_cast<const SwTabFrame
*>(GetFrame());
636 if(rHint
.GetId() == SfxHintId::Dying
)
640 else if (rHint
.GetId() == SfxHintId::SwNameChanged
&& pTabFrame
)
642 const SwFrameFormat
*pFrameFormat
= pTabFrame
->GetFormat();
643 const OUString
sOldName( GetName() );
644 const OUString sNewTabName
= pFrameFormat
->GetName();
646 SetName( sNewTabName
+ "-" + OUString::number( pTabFrame
->GetPhyPageNum() ) );
648 if( sOldName
!= GetName() )
650 AccessibleEventObject aEvent
;
651 aEvent
.EventId
= AccessibleEventId::NAME_CHANGED
;
652 aEvent
.OldValue
<<= sOldName
;
653 aEvent
.NewValue
<<= GetName();
654 FireAccessibleEvent( aEvent
);
657 const OUString
sOldDesc( m_sDesc
);
658 const OUString
sArg2( GetFormattedPageNumber() );
660 m_sDesc
= GetResource( STR_ACCESS_TABLE_DESC
, &sNewTabName
, &sArg2
);
661 if( m_sDesc
!= sOldDesc
)
663 AccessibleEventObject aEvent
;
664 aEvent
.EventId
= AccessibleEventId::DESCRIPTION_CHANGED
;
665 aEvent
.OldValue
<<= sOldDesc
;
666 aEvent
.NewValue
<<= m_sDesc
;
667 FireAccessibleEvent( aEvent
);
672 uno::Any
SwAccessibleTable::queryInterface( const uno::Type
& rType
)
675 if ( rType
== cppu::UnoType
<XAccessibleTable
>::get() )
677 uno::Reference
<XAccessibleTable
> xThis( this );
680 else if ( rType
== cppu::UnoType
<XAccessibleSelection
>::get() )
682 uno::Reference
<XAccessibleSelection
> xSelection( this );
685 else if ( rType
== cppu::UnoType
<XAccessibleTableSelection
>::get() )
687 uno::Reference
<XAccessibleTableSelection
> xTableExtent( this );
688 aRet
<<= xTableExtent
;
692 aRet
= SwAccessibleContext::queryInterface(rType
);
699 uno::Sequence
< uno::Type
> SAL_CALL
SwAccessibleTable::getTypes()
701 return cppu::OTypeCollection(
702 cppu::UnoType
<XAccessibleSelection
>::get(),
703 cppu::UnoType
<XAccessibleTable
>::get(),
704 SwAccessibleContext::getTypes() ).getTypes();
707 uno::Sequence
< sal_Int8
> SAL_CALL
SwAccessibleTable::getImplementationId()
709 return css::uno::Sequence
<sal_Int8
>();
713 std::unique_ptr
<SwAccessibleTableData_Impl
> SwAccessibleTable::CreateNewTableData()
715 const SwTabFrame
* pTabFrame
= static_cast<const SwTabFrame
*>( GetFrame() );
716 return std::unique_ptr
<SwAccessibleTableData_Impl
>(new SwAccessibleTableData_Impl( *GetMap(), pTabFrame
, IsInPagePreview() ));
719 void SwAccessibleTable::UpdateTableData()
721 // #i77106# - usage of new method <CreateNewTableData()>
722 mpTableData
= CreateNewTableData();
725 void SwAccessibleTable::ClearTableData()
730 OUString SAL_CALL
SwAccessibleTable::getAccessibleDescription()
732 SolarMutexGuard aGuard
;
739 sal_Int32 SAL_CALL
SwAccessibleTable::getAccessibleRowCount()
741 SolarMutexGuard aGuard
;
745 return GetTableData().GetRowCount();
748 sal_Int32 SAL_CALL
SwAccessibleTable::getAccessibleColumnCount( )
750 SolarMutexGuard aGuard
;
754 return GetTableData().GetColumnCount();
757 OUString SAL_CALL
SwAccessibleTable::getAccessibleRowDescription(
760 // #i87532# - determine table cell in <nRow>th row and
761 // in first column of row header table and return its text content.
764 GetTableData().CheckRowAndCol(nRow
, 0, this);
766 uno::Reference
< XAccessibleTable
> xTableRowHeader
= getAccessibleRowHeaders();
767 if ( xTableRowHeader
.is() )
769 uno::Reference
< XAccessible
> xRowHeaderCell
=
770 xTableRowHeader
->getAccessibleCellAt( nRow
, 0 );
771 OSL_ENSURE( xRowHeaderCell
.is(),
772 "<SwAccessibleTable::getAccessibleRowDescription(..)> - missing row header cell -> serious issue." );
773 uno::Reference
< XAccessibleContext
> xRowHeaderCellContext
=
774 xRowHeaderCell
->getAccessibleContext();
775 const sal_Int64
nCellChildCount( xRowHeaderCellContext
->getAccessibleChildCount() );
776 for ( sal_Int64 nChildIndex
= 0; nChildIndex
< nCellChildCount
; ++nChildIndex
)
778 uno::Reference
< XAccessible
> xChild
= xRowHeaderCellContext
->getAccessibleChild( nChildIndex
);
779 uno::Reference
< XAccessibleText
> xChildText( xChild
, uno::UNO_QUERY
);
780 if ( xChildText
.is() )
782 sRowDesc
+= xChildText
->getText();
790 OUString SAL_CALL
SwAccessibleTable::getAccessibleColumnDescription(
793 // #i87532# - determine table cell in first row and
794 // in <nColumn>th column of column header table and return its text content.
795 OUString sColumnDesc
;
797 GetTableData().CheckRowAndCol(0, nColumn
, this);
799 uno::Reference
< XAccessibleTable
> xTableColumnHeader
= getAccessibleColumnHeaders();
800 if ( xTableColumnHeader
.is() )
802 uno::Reference
< XAccessible
> xColumnHeaderCell
=
803 xTableColumnHeader
->getAccessibleCellAt( 0, nColumn
);
804 OSL_ENSURE( xColumnHeaderCell
.is(),
805 "<SwAccessibleTable::getAccessibleColumnDescription(..)> - missing column header cell -> serious issue." );
806 uno::Reference
< XAccessibleContext
> xColumnHeaderCellContext
=
807 xColumnHeaderCell
->getAccessibleContext();
808 const sal_Int64
nCellChildCount( xColumnHeaderCellContext
->getAccessibleChildCount() );
809 for ( sal_Int64 nChildIndex
= 0; nChildIndex
< nCellChildCount
; ++nChildIndex
)
811 uno::Reference
< XAccessible
> xChild
= xColumnHeaderCellContext
->getAccessibleChild( nChildIndex
);
812 uno::Reference
< XAccessibleText
> xChildText( xChild
, uno::UNO_QUERY
);
813 if ( xChildText
.is() )
815 sColumnDesc
+= xChildText
->getText();
823 sal_Int32 SAL_CALL
SwAccessibleTable::getAccessibleRowExtentAt(
824 sal_Int32 nRow
, sal_Int32 nColumn
)
826 sal_Int32 nExtend
= -1;
828 SolarMutexGuard aGuard
;
833 GetTableData().CheckRowAndCol( nRow
, nColumn
, this );
835 Int32Set_Impl::const_iterator
aSttCol(
836 GetTableData().GetColumnIter( nColumn
) );
837 Int32Set_Impl::const_iterator
aSttRow(
838 GetTableData().GetRowIter( nRow
) );
839 const SwFrame
*pCellFrame
= GetTableData().GetCellAtPos( *aSttCol
, *aSttRow
);
842 sal_Int32 nBottom
= pCellFrame
->getFrameArea().Bottom();
843 nBottom
-= GetFrame()->getFrameArea().Top();
844 Int32Set_Impl::const_iterator
aEndRow(
845 GetTableData().GetRows().upper_bound( nBottom
) );
847 static_cast< sal_Int32
>( std::distance( aSttRow
, aEndRow
) );
853 sal_Int32 SAL_CALL
SwAccessibleTable::getAccessibleColumnExtentAt(
854 sal_Int32 nRow
, sal_Int32 nColumn
)
856 sal_Int32 nExtend
= -1;
858 SolarMutexGuard aGuard
;
863 GetTableData().CheckRowAndCol( nRow
, nColumn
, this );
865 Int32Set_Impl::const_iterator
aSttCol(
866 GetTableData().GetColumnIter( nColumn
) );
867 Int32Set_Impl::const_iterator
aSttRow(
868 GetTableData().GetRowIter( nRow
) );
869 const SwFrame
*pCellFrame
= GetTableData().GetCellAtPos( *aSttCol
, *aSttRow
);
872 sal_Int32 nRight
= pCellFrame
->getFrameArea().Right();
873 nRight
-= GetFrame()->getFrameArea().Left();
874 Int32Set_Impl::const_iterator
aEndCol(
875 GetTableData().GetColumns().upper_bound( nRight
) );
877 static_cast< sal_Int32
>( std::distance( aSttCol
, aEndCol
) );
883 uno::Reference
< XAccessibleTable
> SAL_CALL
884 SwAccessibleTable::getAccessibleRowHeaders( )
886 // Row headers aren't supported
887 return uno::Reference
< XAccessibleTable
>();
890 uno::Reference
< XAccessibleTable
> SAL_CALL
891 SwAccessibleTable::getAccessibleColumnHeaders( )
893 SolarMutexGuard aGuard
;
895 // #i87532# - assure that return accessible object is empty,
896 // if no column header exists.
897 rtl::Reference
<SwAccessibleTableColHeaders
> pTableColHeaders
=
898 new SwAccessibleTableColHeaders(GetMap()->shared_from_this(),
899 static_cast<const SwTabFrame
*>(GetFrame()));
900 if ( pTableColHeaders
->getAccessibleChildCount() <= 0 )
902 return uno::Reference
< XAccessibleTable
>();
905 return pTableColHeaders
;
908 uno::Sequence
< sal_Int32
> SAL_CALL
SwAccessibleTable::getSelectedAccessibleRows()
910 SolarMutexGuard aGuard
;
914 const SwSelBoxes
*pSelBoxes
= GetSelBoxes();
917 sal_Int32 nRows
= GetTableData().GetRowCount();
918 SwAccAllTableSelHandler_Impl
aSelRows( nRows
);
920 GetTableData().GetSelection( 0, nRows
, *pSelBoxes
, aSelRows
,
923 return aSelRows
.GetSelSequence();
927 return uno::Sequence
< sal_Int32
>( 0 );
931 uno::Sequence
< sal_Int32
> SAL_CALL
SwAccessibleTable::getSelectedAccessibleColumns()
933 SolarMutexGuard aGuard
;
937 const SwSelBoxes
*pSelBoxes
= GetSelBoxes();
940 sal_Int32 nCols
= GetTableData().GetColumnCount();
941 SwAccAllTableSelHandler_Impl
aSelCols( nCols
);
943 GetTableData().GetSelection( 0, nCols
, *pSelBoxes
, aSelCols
, true );
945 return aSelCols
.GetSelSequence();
949 return uno::Sequence
< sal_Int32
>( 0 );
953 sal_Bool SAL_CALL
SwAccessibleTable::isAccessibleRowSelected( sal_Int32 nRow
)
955 SolarMutexGuard aGuard
;
959 GetTableData().CheckRowAndCol( nRow
, 0, this );
962 const SwSelBoxes
*pSelBoxes
= GetSelBoxes();
965 SwAccSingleTableSelHandler_Impl aSelRow
;
966 GetTableData().GetSelection( nRow
, nRow
+1, *pSelBoxes
, aSelRow
,
968 bRet
= aSelRow
.IsSelected();
978 sal_Bool SAL_CALL
SwAccessibleTable::isAccessibleColumnSelected(
981 SolarMutexGuard aGuard
;
985 GetTableData().CheckRowAndCol( 0, nColumn
, this );
988 const SwSelBoxes
*pSelBoxes
= GetSelBoxes();
991 SwAccSingleTableSelHandler_Impl aSelCol
;
993 GetTableData().GetSelection( nColumn
, nColumn
+1, *pSelBoxes
, aSelCol
,
995 bRet
= aSelCol
.IsSelected();
1005 uno::Reference
< XAccessible
> SAL_CALL
SwAccessibleTable::getAccessibleCellAt(
1006 sal_Int32 nRow
, sal_Int32 nColumn
)
1008 uno::Reference
< XAccessible
> xRet
;
1010 SolarMutexGuard aGuard
;
1014 const SwFrame
*pCellFrame
=
1015 GetTableData().GetCell( nRow
, nColumn
, this );
1017 xRet
= GetMap()->GetContext( pCellFrame
);
1022 uno::Reference
< XAccessible
> SAL_CALL
SwAccessibleTable::getAccessibleCaption()
1024 // captions aren't supported
1025 return uno::Reference
< XAccessible
>();
1028 uno::Reference
< XAccessible
> SAL_CALL
SwAccessibleTable::getAccessibleSummary()
1030 // summaries aren't supported
1031 return uno::Reference
< XAccessible
>();
1034 sal_Bool SAL_CALL
SwAccessibleTable::isAccessibleSelected(
1035 sal_Int32 nRow
, sal_Int32 nColumn
)
1039 SolarMutexGuard aGuard
;
1043 const SwFrame
*pFrame
=
1044 GetTableData().GetCell( nRow
, nColumn
, this );
1045 if( pFrame
&& pFrame
->IsCellFrame() )
1047 const SwSelBoxes
*pSelBoxes
= GetSelBoxes();
1050 const SwCellFrame
*pCFrame
= static_cast < const SwCellFrame
* >( pFrame
);
1052 const_cast< SwTableBox
*>( pCFrame
->GetTabBox() );
1053 bRet
= pSelBoxes
->find( pBox
) != pSelBoxes
->end();
1060 sal_Int64 SAL_CALL
SwAccessibleTable::getAccessibleIndex(
1061 sal_Int32 nRow
, sal_Int32 nColumn
)
1063 sal_Int32 nRet
= -1;
1065 SolarMutexGuard aGuard
;
1069 SwAccessibleChild
aCell( GetTableData().GetCell( nRow
, nColumn
, this ));
1070 if ( aCell
.IsValid() )
1072 nRet
= GetChildIndex( *(GetMap()), aCell
);
1078 sal_Int32 SAL_CALL
SwAccessibleTable::getAccessibleRow( sal_Int64 nChildIndex
)
1080 sal_Int32 nRet
= -1;
1082 SolarMutexGuard aGuard
;
1087 if ( ( nChildIndex
< 0 ) ||
1088 ( nChildIndex
>= getAccessibleChildCount() ) )
1090 throw lang::IndexOutOfBoundsException();
1093 SwAccessibleChild
aCell( GetChild( *(GetMap()), nChildIndex
) );
1094 if ( aCell
.GetSwFrame() )
1096 sal_Int32 nTop
= aCell
.GetSwFrame()->getFrameArea().Top();
1097 nTop
-= GetFrame()->getFrameArea().Top();
1098 Int32Set_Impl::const_iterator
aRow(
1099 GetTableData().GetRows().lower_bound( nTop
) );
1100 nRet
= static_cast< sal_Int32
>( std::distance(
1101 GetTableData().GetRows().begin(), aRow
) );
1105 OSL_ENSURE( !aCell
.IsValid(), "SwAccessibleTable::getAccessibleColumn:"
1106 "aCell not expected to be valid.");
1108 throw lang::IndexOutOfBoundsException();
1114 sal_Int32 SAL_CALL
SwAccessibleTable::getAccessibleColumn(
1115 sal_Int64 nChildIndex
)
1117 sal_Int32 nRet
= -1;
1119 SolarMutexGuard aGuard
;
1124 if ( ( nChildIndex
< 0 ) ||
1125 ( nChildIndex
>= getAccessibleChildCount() ) )
1127 throw lang::IndexOutOfBoundsException();
1130 SwAccessibleChild
aCell( GetChild( *(GetMap()), nChildIndex
) );
1131 if ( aCell
.GetSwFrame() )
1133 sal_Int32 nLeft
= aCell
.GetSwFrame()->getFrameArea().Left();
1134 nLeft
-= GetFrame()->getFrameArea().Left();
1135 Int32Set_Impl::const_iterator
aCol(
1136 GetTableData().GetColumns().lower_bound( nLeft
) );
1137 nRet
= static_cast< sal_Int32
>( std::distance(
1138 GetTableData().GetColumns().begin(), aCol
) );
1142 OSL_ENSURE( !aCell
.IsValid(), "SwAccessibleTable::getAccessibleColumn:"
1143 "aCell not expected to be valid.");
1145 throw lang::IndexOutOfBoundsException();
1151 OUString SAL_CALL
SwAccessibleTable::getImplementationName()
1153 return "com.sun.star.comp.Writer.SwAccessibleTableView";
1156 sal_Bool SAL_CALL
SwAccessibleTable::supportsService(
1157 const OUString
& sTestServiceName
)
1159 return cppu::supportsService(this, sTestServiceName
);
1162 uno::Sequence
< OUString
> SAL_CALL
SwAccessibleTable::getSupportedServiceNames()
1164 return { "com.sun.star.table.AccessibleTableView", sAccessibleServiceName
};
1167 void SwAccessibleTable::InvalidatePosOrSize( const SwRect
& rOldBox
)
1169 SolarMutexGuard aGuard
;
1171 //need to update children
1172 std::unique_ptr
<SwAccessibleTableData_Impl
> pNewTableData
= CreateNewTableData();
1173 if( !pNewTableData
->CompareExtents( GetTableData() ) )
1175 mpTableData
= std::move(pNewTableData
);
1176 FireTableChangeEvent(*mpTableData
);
1178 if( HasTableData() )
1179 GetTableData().SetTablePos( GetFrame()->getFrameArea().Pos() );
1181 SwAccessibleContext::InvalidatePosOrSize( rOldBox
);
1184 void SwAccessibleTable::Dispose(bool bRecursive
, bool bCanSkipInvisible
)
1186 SolarMutexGuard aGuard
;
1188 SwAccessibleContext::Dispose(bRecursive
, bCanSkipInvisible
);
1191 void SwAccessibleTable::DisposeChild( const SwAccessibleChild
& rChildFrameOrObj
,
1192 bool bRecursive
, bool bCanSkipInvisible
)
1194 SolarMutexGuard aGuard
;
1196 const SwFrame
*pFrame
= rChildFrameOrObj
.GetSwFrame();
1197 OSL_ENSURE( pFrame
, "frame expected" );
1198 if( HasTableData() )
1200 FireTableChangeEvent( GetTableData() );
1204 // There are two reason why this method has been called. The first one
1205 // is there is no context for pFrame. The method is then called by
1206 // the map, and we have to call our superclass.
1207 // The other situation is that we have been call by a call to get notified
1208 // about its change. We then must not call the superclass
1209 uno::Reference
< XAccessible
> xAcc( GetMap()->GetContext( pFrame
, false ) );
1211 SwAccessibleContext::DisposeChild( rChildFrameOrObj
, bRecursive
, bCanSkipInvisible
);
1214 void SwAccessibleTable::InvalidateChildPosOrSize( const SwAccessibleChild
& rChildFrameOrObj
,
1215 const SwRect
& rOldBox
)
1217 SolarMutexGuard aGuard
;
1219 if( HasTableData() )
1221 SAL_WARN_IF( HasTableData() &&
1222 GetFrame()->getFrameArea().Pos() != GetTableData().GetTablePos(),
1223 "sw.a11y", "table has invalid position" );
1224 if( HasTableData() )
1226 std::unique_ptr
<SwAccessibleTableData_Impl
> pNewTableData
= CreateNewTableData(); // #i77106#
1227 if( !pNewTableData
->CompareExtents( GetTableData() ) )
1229 if (pNewTableData
->GetRowCount() != mpTableData
->GetRowCount()
1230 && 1 < GetTableData().GetRowCount())
1232 Int32Set_Impl::const_iterator
aSttCol( GetTableData().GetColumnIter( 0 ) );
1233 Int32Set_Impl::const_iterator
aSttRow( GetTableData().GetRowIter( 1 ) );
1234 const SwFrame
*pCellFrame
= GetTableData().GetCellAtPos( *aSttCol
, *aSttRow
);
1235 Int32Set_Impl::const_iterator
aSttCol2( pNewTableData
->GetColumnIter( 0 ) );
1236 Int32Set_Impl::const_iterator
aSttRow2( pNewTableData
->GetRowIter( 0 ) );
1237 const SwFrame
*pCellFrame2
= pNewTableData
->GetCellAtPos( *aSttCol2
, *aSttRow2
);
1239 if(pCellFrame
== pCellFrame2
)
1241 AccessibleTableModelChange aModelChange
;
1242 aModelChange
.Type
= AccessibleTableModelChangeType::UPDATE
;
1243 aModelChange
.FirstRow
= 0;
1244 aModelChange
.LastRow
= mpTableData
->GetRowCount() - 1;
1245 aModelChange
.FirstColumn
= 0;
1246 aModelChange
.LastColumn
= mpTableData
->GetColumnCount() - 1;
1248 AccessibleEventObject aEvent
;
1249 aEvent
.EventId
= AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED
;
1250 aEvent
.NewValue
<<= aModelChange
;
1252 FireAccessibleEvent( aEvent
);
1256 FireTableChangeEvent( GetTableData() );
1258 mpTableData
= std::move(pNewTableData
);
1263 // #i013961# - always call super class method
1264 SwAccessibleContext::InvalidateChildPosOrSize( rChildFrameOrObj
, rOldBox
);
1267 // XAccessibleSelection
1269 void SAL_CALL
SwAccessibleTable::selectAccessibleChild(
1270 sal_Int64 nChildIndex
)
1272 SolarMutexGuard aGuard
;
1276 if( (nChildIndex
< 0) || (nChildIndex
>= getAccessibleChildCount()) ) // #i77106#
1277 throw lang::IndexOutOfBoundsException();
1279 // preliminaries: get 'our' table box, and get the cursor shell
1280 const SwTableBox
* pBox
= GetTableBox( nChildIndex
);
1281 OSL_ENSURE( pBox
!= nullptr, "We need the table box." );
1283 SwCursorShell
* pCursorShell
= GetCursorShell();
1284 if( pCursorShell
== nullptr )
1287 // assure, that child, identified by the given index, isn't already selected.
1288 if ( IsChildSelected( nChildIndex
) )
1293 // now we can start to do the work: check whether we already have
1294 // a table selection (in 'our' table). If so, extend the
1295 // selection, else select the current cell.
1297 // if we have a selection in a table, check if it's in the
1298 // same table that we're trying to select in
1299 const SwTableNode
* pSelectedTable
= pCursorShell
->IsCursorInTable();
1300 if( pSelectedTable
!= nullptr )
1302 // get top-most table line
1303 const SwTableLine
* pUpper
= pBox
->GetUpper();
1304 while( pUpper
->GetUpper() != nullptr )
1305 pUpper
= pUpper
->GetUpper()->GetUpper();
1307 pSelectedTable
->GetTable().GetTabLines().GetPos( pUpper
);
1308 if( nPos
== USHRT_MAX
)
1309 pSelectedTable
= nullptr;
1312 // create the new selection
1313 const SwStartNode
* pStartNode
= pBox
->GetSttNd();
1314 if( pSelectedTable
== nullptr || !pCursorShell
->GetTableCrs() )
1316 pCursorShell
->StartAction();
1317 // Set cursor into current cell. This deletes any table cursor.
1318 SwPaM
aPaM( *pStartNode
);
1319 aPaM
.Move( fnMoveForward
, GoInNode
);
1321 // Move cursor to the end of the table creating a selection and a table
1323 pCursorShell
->SetMark();
1324 pCursorShell
->MoveTable( GotoCurrTable
, fnTableEnd
);
1325 // now set the cursor into the cell again.
1326 SwPaM
*pPaM
= pCursorShell
->GetTableCrs() ? pCursorShell
->GetTableCrs()
1327 : pCursorShell
->GetCursor();
1328 *pPaM
->GetPoint() = *pPaM
->GetMark();
1329 pCursorShell
->EndAction();
1330 // we now have one cell selected!
1334 // if the cursor is already in this table,
1335 // expand the current selection (i.e., set
1336 // point to new position; keep mark)
1337 SwPaM
aPaM( *pStartNode
);
1338 aPaM
.Move( fnMoveForward
, GoInNode
);
1340 const SwPaM
*pPaM
= pCursorShell
->GetTableCrs() ? pCursorShell
->GetTableCrs()
1341 : pCursorShell
->GetCursor();
1342 *(aPaM
.GetMark()) = *pPaM
->GetMark();
1348 sal_Bool SAL_CALL
SwAccessibleTable::isAccessibleChildSelected(
1349 sal_Int64 nChildIndex
)
1351 SolarMutexGuard aGuard
;
1355 if( (nChildIndex
< 0) || (nChildIndex
>= getAccessibleChildCount()) ) // #i77106#
1356 throw lang::IndexOutOfBoundsException();
1358 return IsChildSelected( nChildIndex
);
1361 void SAL_CALL
SwAccessibleTable::clearAccessibleSelection( )
1363 SolarMutexGuard aGuard
;
1367 SwCursorShell
* pCursorShell
= GetCursorShell();
1368 if( pCursorShell
!= nullptr )
1370 pCursorShell
->StartAction();
1371 pCursorShell
->ClearMark();
1372 pCursorShell
->EndAction();
1376 void SAL_CALL
SwAccessibleTable::selectAllAccessibleChildren( )
1378 // first clear selection, then select first and last child
1379 clearAccessibleSelection();
1380 selectAccessibleChild( 0 );
1381 selectAccessibleChild( getAccessibleChildCount()-1 ); // #i77106#
1384 sal_Int64 SAL_CALL
SwAccessibleTable::getSelectedAccessibleChildCount( )
1386 SolarMutexGuard aGuard
;
1390 // iterate over all children and count isAccessibleChildSelected()
1391 sal_Int64 nCount
= 0;
1393 sal_Int64 nChildren
= getAccessibleChildCount(); // #i71106#
1394 for( sal_Int64 n
= 0; n
< nChildren
; n
++ )
1395 if( IsChildSelected( n
) )
1401 uno::Reference
<XAccessible
> SAL_CALL
SwAccessibleTable::getSelectedAccessibleChild(
1402 sal_Int64 nSelectedChildIndex
)
1404 SolarMutexGuard aGuard
;
1408 // parameter checking (part 1): index lower 0
1409 if( nSelectedChildIndex
< 0 )
1410 throw lang::IndexOutOfBoundsException();
1412 sal_Int64 nChildIndex
= GetIndexOfSelectedChild( nSelectedChildIndex
);
1414 // parameter checking (part 2): index higher than selected children?
1415 if( nChildIndex
< 0 )
1416 throw lang::IndexOutOfBoundsException();
1419 if ( nChildIndex
>= getAccessibleChildCount() )
1421 throw lang::IndexOutOfBoundsException();
1424 return getAccessibleChild( nChildIndex
);
1427 // index has to be treated as global child index.
1428 void SAL_CALL
SwAccessibleTable::deselectAccessibleChild(
1429 sal_Int64 nChildIndex
)
1431 SolarMutexGuard aGuard
;
1435 SwCursorShell
* pCursorShell
= GetCursorShell();
1437 // index has to be treated as global child index
1438 if ( !pCursorShell
)
1439 throw lang::IndexOutOfBoundsException();
1441 // assure, that given child index is in bounds.
1442 if ( nChildIndex
< 0 || nChildIndex
>= getAccessibleChildCount() ) // #i77106#
1443 throw lang::IndexOutOfBoundsException();
1445 // assure, that child, identified by the given index, is selected.
1446 if ( !IsChildSelected( nChildIndex
) )
1449 const SwTableBox
* pBox
= GetTableBox( nChildIndex
);
1450 OSL_ENSURE( pBox
!= nullptr, "We need the table box." );
1452 // If we unselect point, then set cursor to mark. If we clear another
1453 // selected box, then set cursor to point.
1454 // reduce selection to mark.
1455 SwPaM
*pPaM
= pCursorShell
->GetTableCrs() ? pCursorShell
->GetTableCrs()
1456 : pCursorShell
->GetCursor();
1457 bool bDeselectPoint
=
1459 pPaM
->GetPoint()->GetNode().FindTableBoxStartNode();
1461 SwPaM
aPaM( bDeselectPoint
? *pPaM
->GetMark() : *pPaM
->GetPoint() );
1463 pCursorShell
->StartAction();
1465 // Set cursor into either point or mark
1467 // Move cursor to the end of the table creating a selection and a table
1469 pCursorShell
->SetMark();
1470 pCursorShell
->MoveTable( GotoCurrTable
, fnTableEnd
);
1471 // now set the cursor into the cell again.
1472 pPaM
= pCursorShell
->GetTableCrs() ? pCursorShell
->GetTableCrs()
1473 : pCursorShell
->GetCursor();
1474 *pPaM
->GetPoint() = *pPaM
->GetMark();
1475 pCursorShell
->EndAction();
1478 sal_Int32 SAL_CALL
SwAccessibleTable::getBackground()
1480 const SvxBrushItem
&rBack
= GetFrame()->GetAttrSet()->GetBackground();
1481 Color crBack
= rBack
.GetColor();
1483 if (COL_AUTO
== crBack
)
1485 uno::Reference
<XAccessible
> xAccDoc
= getAccessibleParent();
1488 uno::Reference
<XAccessibleComponent
> xComponentDoc(xAccDoc
,uno::UNO_QUERY
);
1489 if (xComponentDoc
.is())
1491 crBack
= Color(ColorTransparency
, xComponentDoc
->getBackground());
1495 return sal_Int32(crBack
);
1498 void SwAccessibleTable::FireSelectionEvent( )
1500 AccessibleEventObject aEvent
;
1502 aEvent
.EventId
= AccessibleEventId::SELECTION_CHANGED_REMOVE
;
1504 for (const auto& rCell
: m_vecCellRemove
)
1506 // fdo#57197: check if the object is still alive
1507 uno::Reference
<XAccessible
> const xAcc(rCell
.second
);
1510 SwAccessibleContext
*const pAccCell(rCell
.first
);
1512 pAccCell
->FireAccessibleEvent(aEvent
);
1516 if (m_vecCellAdd
.size() <= SELECTION_WITH_NUM
)
1518 aEvent
.EventId
= AccessibleEventId::SELECTION_CHANGED_ADD
;
1519 for (const auto& rCell
: m_vecCellAdd
)
1521 // fdo#57197: check if the object is still alive
1522 uno::Reference
<XAccessible
> const xAcc(rCell
.second
);
1525 SwAccessibleContext
*const pAccCell(rCell
.first
);
1527 pAccCell
->FireAccessibleEvent(aEvent
);
1534 aEvent
.EventId
= AccessibleEventId::SELECTION_CHANGED_WITHIN
;
1535 FireAccessibleEvent(aEvent
);
1539 void SwAccessibleTable::AddSelectionCell(
1540 SwAccessibleContext
*const pAccCell
, bool const bAddOrRemove
)
1542 uno::Reference
<XAccessible
> const xTmp(pAccCell
);
1545 m_vecCellAdd
.emplace_back(pAccCell
, xTmp
);
1549 m_vecCellRemove
.emplace_back(pAccCell
, xTmp
);
1553 // XAccessibleTableSelection
1554 sal_Bool SAL_CALL
SwAccessibleTable::selectRow( sal_Int32 row
)
1558 if( isAccessibleRowSelected( row
) )
1561 tools::Long lColumnCount
= getAccessibleColumnCount();
1562 for(tools::Long lCol
= 0; lCol
< lColumnCount
; lCol
++)
1564 sal_Int64 nChildIndex
= getAccessibleIndex(row
, lCol
);
1565 selectAccessibleChild(nChildIndex
);
1570 sal_Bool SAL_CALL
SwAccessibleTable::selectColumn( sal_Int32 column
)
1574 if( isAccessibleColumnSelected( column
) )
1577 sal_Int32 lRowCount
= getAccessibleRowCount();
1579 for(sal_Int32 lRow
= 0; lRow
< lRowCount
; lRow
++)
1581 sal_Int64 nChildIndex
= getAccessibleIndex(lRow
, column
);
1582 selectAccessibleChild(nChildIndex
);
1587 sal_Bool SAL_CALL
SwAccessibleTable::unselectRow( sal_Int32 row
)
1591 if( isAccessibleSelected( row
, 0 ) && isAccessibleSelected( row
, getAccessibleColumnCount()-1 ) )
1593 SwCursorShell
* pCursorShell
= GetCursorShell();
1594 if( pCursorShell
!= nullptr )
1596 pCursorShell
->StartAction();
1597 pCursorShell
->ClearMark();
1598 pCursorShell
->EndAction();
1605 sal_Bool SAL_CALL
SwAccessibleTable::unselectColumn( sal_Int32 column
)
1609 if( isAccessibleSelected( 0 , column
) && isAccessibleSelected( getAccessibleRowCount()-1,column
))
1611 SwCursorShell
* pCursorShell
= GetCursorShell();
1612 if( pCursorShell
!= nullptr )
1614 pCursorShell
->StartAction();
1615 pCursorShell
->ClearMark();
1616 pCursorShell
->EndAction();
1623 // #i77106# - implementation of class <SwAccessibleTableColHeaders>
1624 SwAccessibleTableColHeaders::SwAccessibleTableColHeaders(
1625 std::shared_ptr
<SwAccessibleMap
> const& pMap
,
1626 const SwTabFrame
*const pTabFrame
)
1627 : SwAccessibleTable(pMap
, pTabFrame
)
1629 SolarMutexGuard aGuard
;
1631 const SwFrameFormat
* pFrameFormat
= pTabFrame
->GetFormat();
1633 StartListening(const_cast<SwFrameFormat
*>(pFrameFormat
)->GetNotifier());
1634 const OUString aName
= pFrameFormat
->GetName() + "-ColumnHeaders";
1636 SetName( aName
+ "-" + OUString::number( pTabFrame
->GetPhyPageNum() ) );
1638 const OUString
sArg2( GetFormattedPageNumber() );
1640 SetDesc( GetResource( STR_ACCESS_TABLE_DESC
, &aName
, &sArg2
) );
1642 NotRegisteredAtAccessibleMap(); // #i85634#
1645 std::unique_ptr
<SwAccessibleTableData_Impl
> SwAccessibleTableColHeaders::CreateNewTableData()
1647 const SwTabFrame
* pTabFrame
= static_cast<const SwTabFrame
*>( GetFrame() );
1648 return std::unique_ptr
<SwAccessibleTableData_Impl
>(new SwAccessibleTableData_Impl( *(GetMap()), pTabFrame
, IsInPagePreview(), true ));
1651 void SwAccessibleTableColHeaders::Notify(const SfxHint
& )
1656 uno::Any SAL_CALL
SwAccessibleTableColHeaders::queryInterface( const uno::Type
& aType
)
1658 return SwAccessibleTable::queryInterface( aType
);
1661 // XAccessibleContext
1662 sal_Int64 SAL_CALL
SwAccessibleTableColHeaders::getAccessibleChildCount()
1664 SolarMutexGuard aGuard
;
1668 sal_Int32 nCount
= 0;
1670 const SwTabFrame
* pTabFrame
= static_cast<const SwTabFrame
*>( GetFrame() );
1671 const SwAccessibleChildSList
aVisList( GetVisArea(), *pTabFrame
, *(GetMap()) );
1672 SwAccessibleChildSList::const_iterator
aIter( aVisList
.begin() );
1673 while( aIter
!= aVisList
.end() )
1675 const SwAccessibleChild
& rLower
= *aIter
;
1676 if( rLower
.IsAccessible( IsInPagePreview() ) )
1680 else if( rLower
.GetSwFrame() )
1682 // There are no unaccessible SdrObjects that count
1683 if ( !rLower
.GetSwFrame()->IsRowFrame() ||
1684 pTabFrame
->IsInHeadline( *(rLower
.GetSwFrame()) ) )
1686 nCount
+= SwAccessibleFrame::GetChildCount( *(GetMap()),
1688 rLower
.GetSwFrame(),
1689 IsInPagePreview() );
1698 uno::Reference
< XAccessible
> SAL_CALL
1699 SwAccessibleTableColHeaders::getAccessibleChild (sal_Int64 nIndex
)
1701 if ( nIndex
< 0 || nIndex
>= getAccessibleChildCount() )
1703 throw lang::IndexOutOfBoundsException();
1706 return SwAccessibleTable::getAccessibleChild( nIndex
);
1710 uno::Reference
< XAccessibleTable
>
1711 SAL_CALL
SwAccessibleTableColHeaders::getAccessibleRowHeaders()
1713 return uno::Reference
< XAccessibleTable
>();
1716 uno::Reference
< XAccessibleTable
>
1717 SAL_CALL
SwAccessibleTableColHeaders::getAccessibleColumnHeaders()
1719 return uno::Reference
< XAccessibleTable
>();
1724 OUString SAL_CALL
SwAccessibleTableColHeaders::getImplementationName()
1726 static constexpr OUStringLiteral sImplName
1727 = u
"com.sun.star.comp.Writer.SwAccessibleTableColumnHeadersView";
1731 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */