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 <vcl/svtaccessiblefactory.hxx>
21 #include <vcl/accessiblefactory.hxx>
22 #include <vcl/toolkit/svtabbx.hxx>
23 #include <vcl/headbar.hxx>
24 #include <vcl/toolkit/svlbitm.hxx>
25 #include <vcl/toolkit/treelistentry.hxx>
26 #include <unotools/accessiblestatesethelper.hxx>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <rtl/ustrbuf.hxx>
29 #include <sal/log.hxx>
30 #include <o3tl/safeint.hxx>
31 #include <osl/diagnose.h>
32 #include <strings.hrc>
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::accessibility
;
39 constexpr SvLBoxTabFlags MYTABMASK
=
40 SvLBoxTabFlags::ADJUST_RIGHT
| SvLBoxTabFlags::ADJUST_LEFT
| SvLBoxTabFlags::ADJUST_CENTER
| SvLBoxTabFlags::FORCE
;
42 // SvTreeListBox callback
44 void SvTabListBox::SetTabs()
46 SvTreeListBox::SetTabs();
47 if( mvTabList
.empty() )
50 DBG_ASSERT(!mvTabList
.empty(),"TabList ?");
52 // The tree listbox has now inserted its tabs into the list. Now we
53 // fluff up the list with additional tabs and adjust the rightmost tab
54 // of the tree listbox.
56 // Picking the rightmost tab.
57 // HACK for the explorer! If ViewParent != 0, the first tab of the tree
58 // listbox is calculated by the tree listbox itself! This behavior is
59 // necessary for ButtonsOnRoot, as the explorer does not know in this
60 // case, which additional offset it needs to add to the tabs in this mode
61 // -- the tree listbox knows that, though!
65 SvLBoxTab* pFirstTab = (SvLBoxTab*)aTabs.GetObject( aTabs.Count()-1 );
66 pFirstTab->SetPos( pTabList[0].GetPos() );
67 pFirstTab->nFlags &= ~MYTABMASK;
68 pFirstTab->nFlags |= pTabList[0].nFlags;
72 // append all other tabs to the list
73 for( sal_uInt16 nCurTab
= 1; nCurTab
< sal_uInt16(mvTabList
.size()); nCurTab
++ )
75 SvLBoxTab
& rTab
= mvTabList
[nCurTab
];
76 AddTab( rTab
.GetPos(), rTab
.nFlags
);
80 void SvTabListBox::InitEntry(SvTreeListEntry
* pEntry
, const OUString
& rStr
,
81 const Image
& rColl
, const Image
& rExp
)
83 SvTreeListBox::InitEntry(pEntry
, rStr
, rColl
, rExp
);
86 // TODO: verify if nTabCount is always >0 here!
87 const sal_uInt16 nCount
= mvTabList
.size() - 1;
88 for( sal_uInt16 nToken
= 0; nToken
< nCount
; nToken
++ )
90 const OUString aToken
= GetToken(aCurEntry
, nIndex
);
91 pEntry
->AddItem(std::make_unique
<SvLBoxString
>(aToken
));
95 SvTabListBox::SvTabListBox( vcl::Window
* pParent
, WinBits nBits
)
96 : SvTreeListBox( pParent
, nBits
)
98 SetHighlightRange(); // select full width
101 SvTabListBox::~SvTabListBox()
106 void SvTabListBox::dispose()
109 SvTreeListBox::dispose();
112 void SvTabListBox::SetTabs(sal_uInt16 nTabs
, tools::Long
const pTabPositions
[], MapUnit eMapUnit
)
114 mvTabList
.resize(nTabs
);
116 MapMode
aMMSource( eMapUnit
);
117 MapMode
aMMDest( MapUnit::MapPixel
);
119 for( sal_uInt16 nIdx
= 0; nIdx
< sal_uInt16(mvTabList
.size()); nIdx
++, pTabPositions
++ )
121 Size
aSize( *pTabPositions
, 0 );
122 aSize
= LogicToLogic( aSize
, &aMMSource
, &aMMDest
);
123 tools::Long nNewTab
= aSize
.Width();
124 mvTabList
[nIdx
].SetPos( nNewTab
);
125 mvTabList
[nIdx
].nFlags
&= MYTABMASK
;
127 SvTreeListBox::nTreeFlags
|= SvTreeFlags::RECALCTABS
;
132 SvTreeListEntry
* SvTabListBox::InsertEntry( const OUString
& rText
, SvTreeListEntry
* pParent
,
133 bool /*bChildrenOnDemand*/,
134 sal_uLong nPos
, void* pUserData
)
136 return InsertEntryToColumn( rText
, pParent
, nPos
, 0xffff, pUserData
);
139 SvTreeListEntry
* SvTabListBox::InsertEntry( const OUString
& rText
,
140 const Image
& rExpandedEntryBmp
,
141 const Image
& rCollapsedEntryBmp
,
142 SvTreeListEntry
* pParent
,
143 bool /*bChildrenOnDemand*/,
144 sal_uLong nPos
, void* pUserData
)
146 return InsertEntryToColumn( rText
, rExpandedEntryBmp
, rCollapsedEntryBmp
,
147 pParent
, nPos
, 0xffff, pUserData
);
150 SvTreeListEntry
* SvTabListBox::InsertEntryToColumn(const OUString
& rStr
,SvTreeListEntry
* pParent
,sal_uLong nPos
,sal_uInt16 nCol
,
163 OUString
aFirstStr( aStr
);
164 sal_Int32 nEnd
= aFirstStr
.indexOf( '\t' );
167 aFirstStr
= aFirstStr
.copy(0, nEnd
);
168 aCurEntry
= aStr
.copy(++nEnd
);
172 return SvTreeListBox::InsertEntry( aFirstStr
, pParent
, false, nPos
, pUser
);
175 SvTreeListEntry
* SvTabListBox::InsertEntryToColumn( const OUString
& rStr
,
176 const Image
& rExpandedEntryBmp
, const Image
& rCollapsedEntryBmp
,
177 SvTreeListEntry
* pParent
,sal_uLong nPos
,sal_uInt16 nCol
, void* pUser
)
189 OUString
aFirstStr( aStr
);
190 sal_Int32 nEnd
= aFirstStr
.indexOf('\t');
193 aFirstStr
= aFirstStr
.copy(0, nEnd
);
194 aCurEntry
= aStr
.copy(++nEnd
);
199 return SvTreeListBox::InsertEntry(
201 rExpandedEntryBmp
, rCollapsedEntryBmp
,
202 pParent
, false, nPos
, pUser
);
205 OUString
SvTabListBox::GetEntryText( SvTreeListEntry
* pEntry
) const
207 return GetEntryText( pEntry
, 0xffff );
210 OUString
SvTabListBox::GetEntryText( SvTreeListEntry
* pEntry
, sal_uInt16 nCol
)
212 DBG_ASSERT(pEntry
,"GetEntryText:Invalid Entry");
213 OUStringBuffer aResult
;
216 sal_uInt16 nCount
= pEntry
->ItemCount();
218 while( nCur
< nCount
)
220 const SvLBoxItem
& rStr
= pEntry
->GetItem( nCur
);
221 if (rStr
.GetType() == SvLBoxItemType::String
)
225 if (!aResult
.isEmpty())
226 aResult
.append("\t");
227 aResult
.append(static_cast<const SvLBoxString
&>(rStr
).GetText());
232 return static_cast<const SvLBoxString
&>(rStr
).GetText();
239 return aResult
.makeStringAndClear();
242 OUString
SvTabListBox::GetEntryText( sal_uLong nPos
, sal_uInt16 nCol
) const
244 SvTreeListEntry
* pEntry
= GetEntryOnPos( nPos
);
245 return GetEntryText( pEntry
, nCol
);
248 OUString
SvTabListBox::GetCellText( sal_uLong nPos
, sal_uInt16 nCol
) const
250 SvTreeListEntry
* pEntry
= GetEntryOnPos( nPos
);
251 DBG_ASSERT( pEntry
, "SvTabListBox::GetCellText(): Invalid Entry" );
253 if (pEntry
&& pEntry
->ItemCount() > o3tl::make_unsigned(nCol
+1))
255 const SvLBoxItem
& rStr
= pEntry
->GetItem( nCol
+ 1 );
256 if (rStr
.GetType() == SvLBoxItemType::String
)
257 aResult
= static_cast<const SvLBoxString
&>(rStr
).GetText();
262 sal_uLong
SvTabListBox::GetEntryPos( const SvTreeListEntry
* pEntry
) const
265 SvTreeListEntry
* pTmpEntry
= First();
268 if ( pTmpEntry
== pEntry
)
270 pTmpEntry
= Next( pTmpEntry
);
277 OUString
SvTabListBox::GetToken( const OUString
&sStr
, sal_Int32
& nIndex
)
279 return sStr
.getToken(0, '\t', nIndex
);
282 OUString
SvTabListBox::GetTabEntryText( sal_uLong nPos
, sal_uInt16 nCol
) const
284 SvTreeListEntry
* pEntry
= SvTreeListBox::GetEntry( nPos
);
285 DBG_ASSERT( pEntry
, "GetTabEntryText(): Invalid entry " );
286 OUStringBuffer aResult
;
289 sal_uInt16 nCount
= pEntry
->ItemCount();
291 while( nCur
< nCount
)
293 const SvLBoxItem
& rBoxItem
= pEntry
->GetItem( nCur
);
294 if (rBoxItem
.GetType() == SvLBoxItemType::String
)
296 if ( nCol
== 0xffff )
298 if (!aResult
.isEmpty())
299 aResult
.append("\t");
300 aResult
.append(static_cast<const SvLBoxString
&>(rBoxItem
).GetText());
306 OUString sRet
= static_cast<const SvLBoxString
&>(rBoxItem
).GetText();
307 if ( sRet
.isEmpty() )
308 sRet
= VclResId( STR_SVT_ACC_EMPTY_FIELD
);
317 return aResult
.makeStringAndClear();
320 SvTreeListEntry
* SvTabListBox::GetEntryOnPos( sal_uLong _nEntryPos
) const
322 SvTreeListEntry
* pEntry
= nullptr;
323 sal_uLong i
, nPos
= 0, nCount
= GetLevelChildCount( nullptr );
324 for ( i
= 0; i
< nCount
; ++i
)
326 SvTreeListEntry
* pParent
= GetEntry(i
);
327 if ( nPos
== _nEntryPos
)
335 pEntry
= GetChildOnPos( pParent
, _nEntryPos
, nPos
);
344 SvTreeListEntry
* SvTabListBox::GetChildOnPos( SvTreeListEntry
* _pParent
, sal_uLong _nEntryPos
, sal_uLong
& _rPos
) const
346 sal_uLong i
, nCount
= GetLevelChildCount( _pParent
);
347 for ( i
= 0; i
< nCount
; ++i
)
349 SvTreeListEntry
* pParent
= GetEntry( _pParent
, i
);
350 if ( _rPos
== _nEntryPos
)
355 SvTreeListEntry
* pEntry
= GetChildOnPos( pParent
, _nEntryPos
, _rPos
);
364 void SvTabListBox::SetTabJustify( sal_uInt16 nTab
, SvTabJustify eJustify
)
366 DBG_ASSERT(nTab
<mvTabList
.size(),"GetTabPos:Invalid Tab");
367 if( nTab
>= mvTabList
.size() )
369 SvLBoxTab
& rTab
= mvTabList
[ nTab
];
370 SvLBoxTabFlags nFlags
= rTab
.nFlags
;
371 nFlags
&= ~MYTABMASK
;
372 // see SvLBoxTab::CalcOffset for force, which only matters for centering
373 nFlags
|= static_cast<SvLBoxTabFlags
>(eJustify
) | SvLBoxTabFlags::FORCE
;
374 rTab
.nFlags
= nFlags
;
375 SvTreeListBox::nTreeFlags
|= SvTreeFlags::RECALCTABS
;
380 void SvTabListBox::SetTabEditable(sal_uInt16 nTab
, bool bEditable
)
382 DBG_ASSERT(nTab
<mvTabList
.size(),"GetTabPos:Invalid Tab");
383 if( nTab
>= mvTabList
.size() )
385 SvLBoxTab
& rTab
= mvTabList
[ nTab
];
387 rTab
.nFlags
|= SvLBoxTabFlags::EDITABLE
;
389 rTab
.nFlags
&= ~SvLBoxTabFlags::EDITABLE
;
392 tools::Long
SvTabListBox::GetLogicTab( sal_uInt16 nTab
)
394 if( SvTreeListBox::nTreeFlags
& SvTreeFlags::RECALCTABS
)
397 DBG_ASSERT(nTab
<mvTabList
.size(),"GetTabPos:Invalid Tab");
398 return aTabs
[ nTab
]->GetPos();
403 struct SvHeaderTabListBoxImpl
405 VclPtr
<HeaderBar
> m_pHeaderBar
;
406 AccessibleFactoryAccess m_aFactoryAccess
;
408 SvHeaderTabListBoxImpl() : m_pHeaderBar( nullptr ) { }
412 SvHeaderTabListBox::SvHeaderTabListBox( vcl::Window
* pParent
, WinBits nWinStyle
)
413 : SvTabListBox(pParent
, nWinStyle
)
414 , m_bFirstPaint(true)
415 , m_pImpl(new ::vcl::SvHeaderTabListBoxImpl
)
416 , m_pAccessible(nullptr)
420 SvHeaderTabListBox::~SvHeaderTabListBox()
425 void SvHeaderTabListBox::dispose()
428 SvTabListBox::dispose();
431 void SvHeaderTabListBox::Paint( vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
435 m_bFirstPaint
= false;
437 SvTabListBox::Paint(rRenderContext
, rRect
);
440 void SvHeaderTabListBox::InitHeaderBar( HeaderBar
* pHeaderBar
)
442 DBG_ASSERT( !m_pImpl
->m_pHeaderBar
, "header bar already initialized" );
443 DBG_ASSERT( pHeaderBar
, "invalid header bar initialization" );
444 m_pImpl
->m_pHeaderBar
= pHeaderBar
;
445 SetScrolledHdl( LINK( this, SvHeaderTabListBox
, ScrollHdl_Impl
) );
446 m_pImpl
->m_pHeaderBar
->SetCreateAccessibleHdl( LINK( this, SvHeaderTabListBox
, CreateAccessibleHdl_Impl
) );
449 HeaderBar
* SvHeaderTabListBox::GetHeaderBar()
451 return m_pImpl
? m_pImpl
->m_pHeaderBar
: nullptr;
454 bool SvHeaderTabListBox::IsItemChecked( SvTreeListEntry
* pEntry
, sal_uInt16 nCol
)
456 SvButtonState eState
= SvButtonState::Unchecked
;
457 SvLBoxButton
& rItem
= static_cast<SvLBoxButton
&>( pEntry
->GetItem( nCol
+ 1 ) );
459 if (rItem
.GetType() == SvLBoxItemType::Button
)
461 SvItemStateFlags nButtonFlags
= rItem
.GetButtonFlags();
462 eState
= SvLBoxButtonData::ConvertToButtonState( nButtonFlags
);
465 return ( eState
== SvButtonState::Checked
);
468 SvTreeListEntry
* SvHeaderTabListBox::InsertEntryToColumn(
469 const OUString
& rStr
, SvTreeListEntry
* pParent
, sal_uLong nPos
, sal_uInt16 nCol
, void* pUserData
)
471 SvTreeListEntry
* pEntry
= SvTabListBox::InsertEntryToColumn( rStr
, pParent
, nPos
, nCol
, pUserData
);
472 RecalculateAccessibleChildren();
476 SvTreeListEntry
* SvHeaderTabListBox::InsertEntryToColumn(
477 const OUString
& rStr
, const Image
& rExpandedEntryBmp
, const Image
& rCollapsedEntryBmp
,
478 SvTreeListEntry
* pParent
, sal_uLong nPos
, sal_uInt16 nCol
, void* pUserData
)
480 SvTreeListEntry
* pEntry
= SvTabListBox::InsertEntryToColumn(
481 rStr
, rExpandedEntryBmp
, rCollapsedEntryBmp
, pParent
, nPos
, nCol
, pUserData
);
482 RecalculateAccessibleChildren();
486 sal_uLong
SvHeaderTabListBox::Insert(
487 SvTreeListEntry
* pEnt
, SvTreeListEntry
* pPar
, sal_uLong nPos
)
489 sal_uLong n
= SvTabListBox::Insert( pEnt
, pPar
, nPos
);
490 RecalculateAccessibleChildren();
494 sal_uLong
SvHeaderTabListBox::Insert( SvTreeListEntry
* pEntry
, sal_uLong nRootPos
)
496 sal_uLong nPos
= SvTabListBox::Insert( pEntry
, nRootPos
);
497 RecalculateAccessibleChildren();
501 IMPL_LINK_NOARG(SvHeaderTabListBox
, ScrollHdl_Impl
, SvTreeListBox
*, void)
503 m_pImpl
->m_pHeaderBar
->SetOffset( -GetXOffset() );
506 IMPL_LINK_NOARG(SvHeaderTabListBox
, CreateAccessibleHdl_Impl
, HeaderBar
*, void)
508 vcl::Window
* pParent
= m_pImpl
->m_pHeaderBar
->GetAccessibleParentWindow();
509 DBG_ASSERT( pParent
, "SvHeaderTabListBox..CreateAccessibleHdl_Impl - accessible parent not found" );
512 css::uno::Reference
< XAccessible
> xAccParent
= pParent
->GetAccessible();
513 if ( xAccParent
.is() )
515 Reference
< XAccessible
> xAccessible
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleBrowseBoxHeaderBar(
516 xAccParent
, *this, ::vcl::BBTYPE_COLUMNHEADERBAR
);
517 m_pImpl
->m_pHeaderBar
->SetAccessible( xAccessible
);
522 void SvHeaderTabListBox::RecalculateAccessibleChildren()
524 if ( !m_aAccessibleChildren
.empty() )
526 sal_uInt32 nCount
= ( GetRowCount() + 1 ) * GetColumnCount();
527 if ( m_aAccessibleChildren
.size() < nCount
)
528 m_aAccessibleChildren
.resize( nCount
);
531 DBG_ASSERT( m_aAccessibleChildren
.size() == nCount
, "wrong children count" );
536 bool SvHeaderTabListBox::IsCellCheckBox( sal_Int32 _nRow
, sal_uInt16 _nColumn
, TriState
& _rState
)
539 SvTreeListEntry
* pEntry
= GetEntry( _nRow
);
542 sal_uInt16 nItemCount
= pEntry
->ItemCount();
543 if ( nItemCount
> ( _nColumn
+ 1 ) )
545 SvLBoxItem
& rItem
= pEntry
->GetItem( _nColumn
+ 1 );
546 if (rItem
.GetType() == SvLBoxItemType::Button
)
549 _rState
= ( ( static_cast<SvLBoxButton
&>(rItem
).GetButtonFlags() & SvItemStateFlags::UNCHECKED
) == SvItemStateFlags::NONE
)
550 ? TRISTATE_TRUE
: TRISTATE_FALSE
;
555 SAL_WARN( "svtools.contnr", "SvHeaderTabListBox::IsCellCheckBox(): column out of range" );
560 sal_Int32
SvHeaderTabListBox::GetRowCount() const
562 return GetEntryCount();
565 sal_uInt16
SvHeaderTabListBox::GetColumnCount() const
567 return m_pImpl
->m_pHeaderBar
->GetItemCount();
570 sal_Int32
SvHeaderTabListBox::GetCurrRow() const
573 SvTreeListEntry
* pEntry
= GetCurEntry();
576 sal_uLong nCount
= GetEntryCount();
577 for ( sal_uLong i
= 0; i
< nCount
; ++i
)
579 if ( pEntry
== GetEntry(i
) )
590 sal_uInt16
SvHeaderTabListBox::GetCurrColumn() const
595 OUString
SvHeaderTabListBox::GetRowDescription( sal_Int32 _nRow
) const
597 return GetEntryText( _nRow
);
600 OUString
SvHeaderTabListBox::GetColumnDescription( sal_uInt16 _nColumn
) const
602 return m_pImpl
->m_pHeaderBar
->GetItemText( m_pImpl
->m_pHeaderBar
->GetItemId( _nColumn
) );
605 bool SvHeaderTabListBox::HasRowHeader() const
610 bool SvHeaderTabListBox::GoToCell( sal_Int32
/*_nRow*/, sal_uInt16
/*_nColumn*/ )
615 void SvHeaderTabListBox::SetNoSelection()
617 SvTreeListBox::SelectAll(false);
620 void SvHeaderTabListBox::SelectAll()
622 SvTreeListBox::SelectAll(true);
625 void SvHeaderTabListBox::SelectRow( sal_Int32 _nRow
, bool _bSelect
, bool )
627 Select( GetEntry( _nRow
), _bSelect
);
630 void SvHeaderTabListBox::SelectColumn( sal_uInt16
, bool )
634 sal_Int32
SvHeaderTabListBox::GetSelectedRowCount() const
636 return GetSelectionCount();
639 sal_Int32
SvHeaderTabListBox::GetSelectedColumnCount() const
644 bool SvHeaderTabListBox::IsRowSelected( sal_Int32 _nRow
) const
646 SvTreeListEntry
* pEntry
= GetEntry( _nRow
);
647 return ( pEntry
&& IsSelected( pEntry
) );
650 bool SvHeaderTabListBox::IsColumnSelected( sal_Int32
) const
655 void SvHeaderTabListBox::GetAllSelectedRows( css::uno::Sequence
< sal_Int32
>& ) const
659 void SvHeaderTabListBox::GetAllSelectedColumns( css::uno::Sequence
< sal_Int32
>& ) const
663 bool SvHeaderTabListBox::IsCellVisible( sal_Int32
, sal_uInt16
) const
668 OUString
SvHeaderTabListBox::GetAccessibleCellText( sal_Int32 _nRow
, sal_uInt16 _nColumnPos
) const
670 return GetTabEntryText(_nRow
, _nColumnPos
);
673 tools::Rectangle
SvHeaderTabListBox::calcHeaderRect( bool _bIsColumnBar
, bool _bOnScreen
)
675 tools::Rectangle aRect
;
678 vcl::Window
* pParent
= nullptr;
680 pParent
= m_pImpl
->m_pHeaderBar
->GetAccessibleParentWindow();
682 aRect
= m_pImpl
->m_pHeaderBar
->GetWindowExtentsRelative( pParent
);
687 tools::Rectangle
SvHeaderTabListBox::calcTableRect( bool _bOnScreen
)
689 vcl::Window
* pParent
= nullptr;
691 pParent
= GetAccessibleParentWindow();
693 tools::Rectangle
aRect( GetWindowExtentsRelative( pParent
) );
697 tools::Rectangle
SvHeaderTabListBox::GetFieldRectPixelAbs( sal_Int32 _nRow
, sal_uInt16 _nColumn
, bool _bIsHeader
, bool _bOnScreen
)
699 DBG_ASSERT( !_bIsHeader
|| 0 == _nRow
, "invalid parameters" );
700 tools::Rectangle aRect
;
701 SvTreeListEntry
* pEntry
= GetEntry( _nRow
);
704 aRect
= _bIsHeader
? calcHeaderRect( true, false ) : GetBoundingRect( pEntry
);
705 Point aTopLeft
= aRect
.TopLeft();
706 DBG_ASSERT( m_pImpl
->m_pHeaderBar
->GetItemCount() > _nColumn
, "invalid column" );
707 tools::Rectangle aItemRect
= m_pImpl
->m_pHeaderBar
->GetItemRect( m_pImpl
->m_pHeaderBar
->GetItemId( _nColumn
) );
708 aTopLeft
.setX( aItemRect
.Left() );
709 Size aSize
= aItemRect
.GetSize();
710 aRect
= tools::Rectangle( aTopLeft
, aSize
);
711 vcl::Window
* pParent
= nullptr;
713 pParent
= GetAccessibleParentWindow();
714 aTopLeft
= aRect
.TopLeft();
715 aTopLeft
+= GetWindowExtentsRelative( pParent
).TopLeft();
716 aRect
= tools::Rectangle( aTopLeft
, aRect
.GetSize() );
722 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessibleCell( sal_Int32 _nRow
, sal_uInt16 _nColumnPos
)
724 OSL_ENSURE( m_pAccessible
, "Invalid call: Accessible is null" );
726 Reference
< XAccessible
> xChild
;
728 TriState eState
= TRISTATE_INDET
;
729 bool bIsCheckBox
= IsCellCheckBox( _nRow
, _nColumnPos
, eState
);
731 xChild
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleCheckBoxCell(
732 m_pAccessible
->getHeaderBar(), *this, nullptr, _nRow
, _nColumnPos
, eState
, false );
734 xChild
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleBrowseBoxTableCell(
735 m_pAccessible
->getHeaderBar(), *this, nullptr, _nRow
, _nColumnPos
, OFFSET_NONE
);
740 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessibleRowHeader( sal_Int32
)
742 Reference
< XAccessible
> xHeader
;
746 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessibleColumnHeader( sal_uInt16 _nColumn
)
748 // first call? -> initial list
749 if ( m_aAccessibleChildren
.empty() )
751 const sal_uInt16 nColumnCount
= GetColumnCount();
752 m_aAccessibleChildren
.assign( nColumnCount
, Reference
< XAccessible
>() );
756 Reference
< XAccessible
> xChild
= m_aAccessibleChildren
[ _nColumn
];
758 if ( !xChild
.is() && m_pAccessible
)
760 // no -> create new header cell
761 xChild
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleBrowseBoxHeaderCell(
762 _nColumn
, m_pAccessible
->getHeaderBar(),
763 *this, nullptr, ::vcl::BBTYPE_COLUMNHEADERCELL
767 m_aAccessibleChildren
[ _nColumn
] = xChild
;
772 sal_Int32
SvHeaderTabListBox::GetAccessibleControlCount() const
777 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessibleControl( sal_Int32
)
779 Reference
< XAccessible
> xControl
;
783 bool SvHeaderTabListBox::ConvertPointToControlIndex( sal_Int32
&, const Point
& )
788 bool SvHeaderTabListBox::ConvertPointToCellAddress( sal_Int32
&, sal_uInt16
&, const Point
& )
793 bool SvHeaderTabListBox::ConvertPointToRowHeader( sal_Int32
&, const Point
& )
798 bool SvHeaderTabListBox::ConvertPointToColumnHeader( sal_uInt16
&, const Point
& )
803 OUString
SvHeaderTabListBox::GetAccessibleObjectName( ::vcl::AccessibleBrowseBoxObjType _eType
, sal_Int32 _nPos
) const
808 case ::vcl::BBTYPE_BROWSEBOX
:
809 case ::vcl::BBTYPE_TABLE
:
810 case ::vcl::BBTYPE_COLUMNHEADERBAR
:
811 // should be empty now (see #i63983)
815 case ::vcl::BBTYPE_TABLECELL
:
817 // here we need a valid pos, we can not handle -1
820 sal_uInt16 nColumnCount
= GetColumnCount();
821 if (nColumnCount
> 0)
823 sal_Int32 nRow
= _nPos
/ nColumnCount
;
824 sal_uInt16 nColumn
= static_cast< sal_uInt16
>( _nPos
% nColumnCount
);
825 aRetText
= GetCellText( nRow
, nColumn
);
830 case ::vcl::BBTYPE_CHECKBOXCELL
:
832 break; // checkbox cells have no name
834 case ::vcl::BBTYPE_COLUMNHEADERCELL
:
836 aRetText
= m_pImpl
->m_pHeaderBar
->GetItemText( m_pImpl
->m_pHeaderBar
->GetItemId( static_cast<sal_uInt16
>(_nPos
) ) );
840 case ::vcl::BBTYPE_ROWHEADERBAR
:
841 case ::vcl::BBTYPE_ROWHEADERCELL
:
846 OSL_FAIL("BrowseBox::GetAccessibleName: invalid enum!");
851 OUString
SvHeaderTabListBox::GetAccessibleObjectDescription( ::vcl::AccessibleBrowseBoxObjType _eType
, sal_Int32 _nPos
) const
855 if( _eType
== ::vcl::BBTYPE_TABLECELL
&& _nPos
!= -1 )
857 sal_uInt16 nColumnCount
= GetColumnCount();
858 if (nColumnCount
> 0)
860 sal_Int32 nRow
= _nPos
/ nColumnCount
;
861 sal_uInt16 nColumn
= static_cast< sal_uInt16
>( _nPos
% nColumnCount
);
863 OUString
aText( VclResId(STR_SVT_ACC_DESC_TABLISTBOX
) );
864 aText
= aText
.replaceFirst( "%1", OUString::number( nRow
) );
865 OUString sColHeader
= m_pImpl
->m_pHeaderBar
->GetItemText( m_pImpl
->m_pHeaderBar
->GetItemId( nColumn
) );
866 if ( sColHeader
.isEmpty() )
867 sColHeader
= OUString::number( nColumn
);
868 aText
= aText
.replaceFirst( "%2", sColHeader
);
876 void SvHeaderTabListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper
& _rStateSet
, ::vcl::AccessibleBrowseBoxObjType _eType
) const
880 case ::vcl::BBTYPE_BROWSEBOX
:
881 case ::vcl::BBTYPE_TABLE
:
883 _rStateSet
.AddState( AccessibleStateType::FOCUSABLE
);
885 _rStateSet
.AddState( AccessibleStateType::FOCUSED
);
887 _rStateSet
.AddState( AccessibleStateType::ACTIVE
);
890 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
891 _rStateSet
.AddState( AccessibleStateType::SENSITIVE
);
893 if ( IsReallyVisible() )
894 _rStateSet
.AddState( AccessibleStateType::VISIBLE
);
895 if ( _eType
== ::vcl::BBTYPE_TABLE
)
898 _rStateSet
.AddState( AccessibleStateType::MANAGES_DESCENDANTS
);
899 _rStateSet
.AddState( AccessibleStateType::MULTI_SELECTABLE
);
904 case ::vcl::BBTYPE_COLUMNHEADERBAR
:
906 sal_Int32 nCurRow
= GetCurrRow();
907 sal_uInt16 nCurColumn
= GetCurrColumn();
908 if ( IsCellVisible( nCurRow
, nCurColumn
) )
909 _rStateSet
.AddState( AccessibleStateType::VISIBLE
);
911 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
912 _rStateSet
.AddState( AccessibleStateType::TRANSIENT
);
916 case ::vcl::BBTYPE_ROWHEADERCELL
:
917 case ::vcl::BBTYPE_COLUMNHEADERCELL
:
919 _rStateSet
.AddState( AccessibleStateType::VISIBLE
);
920 _rStateSet
.AddState( AccessibleStateType::FOCUSABLE
);
921 _rStateSet
.AddState( AccessibleStateType::TRANSIENT
);
923 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
931 void SvHeaderTabListBox::FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper
& _rStateSet
, sal_Int32 _nRow
, sal_uInt16 _nColumn
) const
933 _rStateSet
.AddState( AccessibleStateType::SELECTABLE
);
934 _rStateSet
.AddState( AccessibleStateType::TRANSIENT
);
936 if ( IsCellVisible( _nRow
, _nColumn
) )
938 _rStateSet
.AddState( AccessibleStateType::VISIBLE
);
939 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
942 if ( IsRowSelected( _nRow
) )
944 _rStateSet
.AddState( AccessibleStateType::ACTIVE
);
945 _rStateSet
.AddState( AccessibleStateType::SELECTED
);
948 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
951 void SvHeaderTabListBox::GrabTableFocus()
956 bool SvHeaderTabListBox::GetGlyphBoundRects( const Point
& rOrigin
, const OUString
& rStr
, int nIndex
, int nLen
, MetricVector
& rVector
)
958 return Control::GetGlyphBoundRects( rOrigin
, rStr
, nIndex
, nLen
, rVector
);
961 tools::Rectangle
SvHeaderTabListBox::GetWindowExtentsRelative(const vcl::Window
*pRelativeWindow
) const
963 return Control::GetWindowExtentsRelative( pRelativeWindow
);
966 void SvHeaderTabListBox::GrabFocus()
968 Control::GrabFocus();
971 Reference
< XAccessible
> SvHeaderTabListBox::GetAccessible()
973 return Control::GetAccessible();
976 vcl::Window
* SvHeaderTabListBox::GetAccessibleParentWindow() const
978 return Control::GetAccessibleParentWindow();
981 vcl::Window
* SvHeaderTabListBox::GetWindowInstance()
986 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessible()
988 vcl::Window
* pParent
= GetAccessibleParentWindow();
989 DBG_ASSERT( pParent
, "SvHeaderTabListBox::::CreateAccessible - accessible parent not found" );
991 Reference
< XAccessible
> xAccessible
;
992 if ( m_pAccessible
) xAccessible
= m_pAccessible
->getMyself();
994 if( pParent
&& !m_pAccessible
)
996 Reference
< XAccessible
> xAccParent
= pParent
->GetAccessible();
997 if ( xAccParent
.is() )
999 m_pAccessible
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleTabListBox( xAccParent
, *this );
1000 if ( m_pAccessible
)
1001 xAccessible
= m_pAccessible
->getMyself();
1007 tools::Rectangle
SvHeaderTabListBox::GetFieldCharacterBounds(sal_Int32
,sal_Int32
,sal_Int32
)
1009 return tools::Rectangle();
1012 sal_Int32
SvHeaderTabListBox::GetFieldIndexAtPoint(sal_Int32 _nRow
,sal_Int32 _nColumnPos
,const Point
& _rPoint
)
1014 OUString sText
= GetAccessibleCellText( _nRow
, static_cast< sal_uInt16
>( _nColumnPos
) );
1015 MetricVector aRects
;
1016 if ( GetGlyphBoundRects(Point(0,0), sText
, 0, sText
.getLength(), aRects
) )
1019 for (auto const& rectangle
: aRects
)
1021 if( rectangle
.IsInside(_rPoint
) )
1030 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */