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/svtabbx.hxx>
23 #include <vcl/headbar.hxx>
24 #include <vcl/svlbitm.hxx>
25 #include <vcl/treelistentry.hxx>
26 #include <unotools/accessiblestatesethelper.hxx>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <sal/log.hxx>
29 #include <osl/diagnose.h>
30 #include <strings.hrc>
34 using namespace ::com::sun::star::uno
;
35 using namespace ::com::sun::star::accessibility
;
37 static constexpr SvLBoxTabFlags MYTABMASK
=
38 SvLBoxTabFlags::ADJUST_RIGHT
| SvLBoxTabFlags::ADJUST_LEFT
| SvLBoxTabFlags::ADJUST_CENTER
| SvLBoxTabFlags::FORCE
;
40 // SvTreeListBox callback
42 void SvTabListBox::SetTabs()
44 SvTreeListBox::SetTabs();
45 if( mvTabList
.empty() )
48 DBG_ASSERT(!mvTabList
.empty(),"TabList ?");
50 // The tree listbox has now inserted its tabs into the list. Now we
51 // fluff up the list with additional tabs and adjust the rightmost tab
52 // of the tree listbox.
54 // Picking the rightmost tab.
55 // HACK for the explorer! If ViewParent != 0, the first tab of the tree
56 // listbox is calculated by the tree listbox itself! This behavior is
57 // necessary for ButtonsOnRoot, as the explorer does not know in this
58 // case, which additional offset it needs to add to the tabs in this mode
59 // -- the tree listbox knows that, though!
63 SvLBoxTab* pFirstTab = (SvLBoxTab*)aTabs.GetObject( aTabs.Count()-1 );
64 pFirstTab->SetPos( pTabList[0].GetPos() );
65 pFirstTab->nFlags &= ~MYTABMASK;
66 pFirstTab->nFlags |= pTabList[0].nFlags;
70 // append all other tabs to the list
71 for( sal_uInt16 nCurTab
= 1; nCurTab
< sal_uInt16(mvTabList
.size()); nCurTab
++ )
73 SvLBoxTab
& rTab
= mvTabList
[nCurTab
];
74 AddTab( rTab
.GetPos(), rTab
.nFlags
);
78 void SvTabListBox::InitEntry(SvTreeListEntry
* pEntry
, const OUString
& rStr
,
79 const Image
& rColl
, const Image
& rExp
)
81 SvTreeListBox::InitEntry(pEntry
, rStr
, rColl
, rExp
);
84 // TODO: verify if nTabCount is always >0 here!
85 const sal_uInt16 nCount
= mvTabList
.size() - 1;
86 for( sal_uInt16 nToken
= 0; nToken
< nCount
; nToken
++ )
88 const OUString aToken
= GetToken(aCurEntry
, nIndex
);
89 pEntry
->AddItem(std::make_unique
<SvLBoxString
>(aToken
));
93 SvTabListBox::SvTabListBox( vcl::Window
* pParent
, WinBits nBits
)
94 : SvTreeListBox( pParent
, nBits
)
96 SetHighlightRange(); // select full width
99 SvTabListBox::~SvTabListBox()
104 void SvTabListBox::dispose()
107 SvTreeListBox::dispose();
110 void SvTabListBox::SetTabs(sal_uInt16 nTabs
, long const pTabPositions
[], MapUnit eMapUnit
)
112 mvTabList
.resize(nTabs
);
114 MapMode
aMMSource( eMapUnit
);
115 MapMode
aMMDest( MapUnit::MapPixel
);
117 for( sal_uInt16 nIdx
= 0; nIdx
< sal_uInt16(mvTabList
.size()); nIdx
++, pTabPositions
++ )
119 Size
aSize( *pTabPositions
, 0 );
120 aSize
= LogicToLogic( aSize
, &aMMSource
, &aMMDest
);
121 long nNewTab
= aSize
.Width();
122 mvTabList
[nIdx
].SetPos( nNewTab
);
123 mvTabList
[nIdx
].nFlags
&= MYTABMASK
;
125 SvTreeListBox::nTreeFlags
|= SvTreeFlags::RECALCTABS
;
130 void SvTabListBox::SetTab( sal_uInt16 nTab
,long nValue
,MapUnit eMapUnit
)
132 DBG_ASSERT(nTab
<mvTabList
.size(),"Invalid Tab-Pos");
133 if( nTab
>= mvTabList
.size() )
136 MapMode
aMMSource( eMapUnit
);
137 MapMode
aMMDest( MapUnit::MapPixel
);
138 Size
aSize( nValue
, 0 );
139 aSize
= LogicToLogic( aSize
, &aMMSource
, &aMMDest
);
140 nValue
= aSize
.Width();
141 mvTabList
[ nTab
].SetPos( nValue
);
142 SvTreeListBox::nTreeFlags
|= SvTreeFlags::RECALCTABS
;
147 SvTreeListEntry
* SvTabListBox::InsertEntry( const OUString
& rText
, SvTreeListEntry
* pParent
,
148 bool /*bChildrenOnDemand*/,
149 sal_uLong nPos
, void* pUserData
)
151 return InsertEntryToColumn( rText
, pParent
, nPos
, 0xffff, pUserData
);
154 SvTreeListEntry
* SvTabListBox::InsertEntry( const OUString
& rText
,
155 const Image
& rExpandedEntryBmp
,
156 const Image
& rCollapsedEntryBmp
,
157 SvTreeListEntry
* pParent
,
158 bool /*bChildrenOnDemand*/,
159 sal_uLong nPos
, void* pUserData
)
161 return InsertEntryToColumn( rText
, rExpandedEntryBmp
, rCollapsedEntryBmp
,
162 pParent
, nPos
, 0xffff, pUserData
);
165 SvTreeListEntry
* SvTabListBox::InsertEntryToColumn(const OUString
& rStr
,SvTreeListEntry
* pParent
,sal_uLong nPos
,sal_uInt16 nCol
,
178 OUString
aFirstStr( aStr
);
179 sal_Int32 nEnd
= aFirstStr
.indexOf( '\t' );
182 aFirstStr
= aFirstStr
.copy(0, nEnd
);
183 aCurEntry
= aStr
.copy(++nEnd
);
187 return SvTreeListBox::InsertEntry( aFirstStr
, pParent
, false, nPos
, pUser
);
190 SvTreeListEntry
* SvTabListBox::InsertEntryToColumn( const OUString
& rStr
,
191 const Image
& rExpandedEntryBmp
, const Image
& rCollapsedEntryBmp
,
192 SvTreeListEntry
* pParent
,sal_uLong nPos
,sal_uInt16 nCol
, void* pUser
)
204 OUString
aFirstStr( aStr
);
205 sal_Int32 nEnd
= aFirstStr
.indexOf('\t');
208 aFirstStr
= aFirstStr
.copy(0, nEnd
);
209 aCurEntry
= aStr
.copy(++nEnd
);
214 return SvTreeListBox::InsertEntry(
216 rExpandedEntryBmp
, rCollapsedEntryBmp
,
217 pParent
, false, nPos
, pUser
);
220 OUString
SvTabListBox::GetEntryText( SvTreeListEntry
* pEntry
) const
222 return GetEntryText( pEntry
, 0xffff );
225 OUString
SvTabListBox::GetEntryText( SvTreeListEntry
* pEntry
, sal_uInt16 nCol
)
227 DBG_ASSERT(pEntry
,"GetEntryText:Invalid Entry");
228 OUStringBuffer aResult
;
231 sal_uInt16 nCount
= pEntry
->ItemCount();
233 while( nCur
< nCount
)
235 const SvLBoxItem
& rStr
= pEntry
->GetItem( nCur
);
236 if (rStr
.GetType() == SvLBoxItemType::String
)
240 if (!aResult
.isEmpty())
241 aResult
.append("\t");
242 aResult
.append(static_cast<const SvLBoxString
&>(rStr
).GetText());
247 return static_cast<const SvLBoxString
&>(rStr
).GetText();
254 return aResult
.makeStringAndClear();
257 OUString
SvTabListBox::GetEntryText( sal_uLong nPos
, sal_uInt16 nCol
) const
259 SvTreeListEntry
* pEntry
= GetEntryOnPos( nPos
);
260 return GetEntryText( pEntry
, nCol
);
263 void SvTabListBox::SetEntryText(const OUString
& rStr
, SvTreeListEntry
* pEntry
, sal_uInt16 nCol
)
265 DBG_ASSERT(pEntry
,"SetEntryText:Invalid Entry");
269 OUString sOldText
= GetEntryText(pEntry
, nCol
);
270 if (sOldText
== rStr
)
273 sal_Int32 nIndex
= 0;
274 const sal_uInt16 nTextColumn
= nCol
;
275 const sal_uInt16 nCount
= pEntry
->ItemCount();
276 for (sal_uInt16 nCur
= 0; nCur
< nCount
; ++nCur
)
278 SvLBoxItem
& rBoxItem
= pEntry
->GetItem( nCur
);
279 if (rBoxItem
.GetType() == SvLBoxItemType::String
)
281 if (!nCol
|| nCol
==0xFFFF)
283 const OUString
aTemp(GetToken(rStr
, nIndex
));
284 static_cast<SvLBoxString
&>(rBoxItem
).SetText( aTemp
);
285 if (!nCol
&& nIndex
<0)
294 GetModel()->InvalidateEntry( pEntry
);
296 std::unique_ptr
<TabListBoxEventData
> pData( new TabListBoxEventData( pEntry
, nTextColumn
, sOldText
) );
297 CallEventListeners( VclEventId::TableCellNameChanged
, pData
.get() );
300 OUString
SvTabListBox::GetCellText( sal_uLong nPos
, sal_uInt16 nCol
) const
302 SvTreeListEntry
* pEntry
= GetEntryOnPos( nPos
);
303 DBG_ASSERT( pEntry
, "SvTabListBox::GetCellText(): Invalid Entry" );
305 if (pEntry
&& pEntry
->ItemCount() > static_cast<size_t>(nCol
+1))
307 const SvLBoxItem
& rStr
= pEntry
->GetItem( nCol
+ 1 );
308 if (rStr
.GetType() == SvLBoxItemType::String
)
309 aResult
= static_cast<const SvLBoxString
&>(rStr
).GetText();
314 sal_uLong
SvTabListBox::GetEntryPos( const SvTreeListEntry
* pEntry
) const
317 SvTreeListEntry
* pTmpEntry
= First();
320 if ( pTmpEntry
== pEntry
)
322 pTmpEntry
= Next( pTmpEntry
);
329 OUString
SvTabListBox::GetToken( const OUString
&sStr
, sal_Int32
& nIndex
)
331 return sStr
.getToken(0, '\t', nIndex
);
334 OUString
SvTabListBox::GetTabEntryText( sal_uLong nPos
, sal_uInt16 nCol
) const
336 SvTreeListEntry
* pEntry
= SvTreeListBox::GetEntry( nPos
);
337 DBG_ASSERT( pEntry
, "GetTabEntryText(): Invalid entry " );
338 OUStringBuffer aResult
;
341 sal_uInt16 nCount
= pEntry
->ItemCount();
342 sal_uInt16 nCur
= ( 0 == nCol
&& IsCellFocusEnabled() ) ? GetCurrentTabPos() : 0;
343 while( nCur
< nCount
)
345 const SvLBoxItem
& rBoxItem
= pEntry
->GetItem( nCur
);
346 if (rBoxItem
.GetType() == SvLBoxItemType::String
)
348 if ( nCol
== 0xffff )
350 if (!aResult
.isEmpty())
351 aResult
.append("\t");
352 aResult
.append(static_cast<const SvLBoxString
&>(rBoxItem
).GetText());
358 OUString sRet
= static_cast<const SvLBoxString
&>(rBoxItem
).GetText();
359 if ( sRet
.isEmpty() )
360 sRet
= VclResId( STR_SVT_ACC_EMPTY_FIELD
);
369 return aResult
.makeStringAndClear();
372 SvTreeListEntry
* SvTabListBox::GetEntryOnPos( sal_uLong _nEntryPos
) const
374 SvTreeListEntry
* pEntry
= nullptr;
375 sal_uLong i
, nPos
= 0, nCount
= GetLevelChildCount( nullptr );
376 for ( i
= 0; i
< nCount
; ++i
)
378 SvTreeListEntry
* pParent
= GetEntry(i
);
379 if ( nPos
== _nEntryPos
)
387 pEntry
= GetChildOnPos( pParent
, _nEntryPos
, nPos
);
396 SvTreeListEntry
* SvTabListBox::GetChildOnPos( SvTreeListEntry
* _pParent
, sal_uLong _nEntryPos
, sal_uLong
& _rPos
) const
398 sal_uLong i
, nCount
= GetLevelChildCount( _pParent
);
399 for ( i
= 0; i
< nCount
; ++i
)
401 SvTreeListEntry
* pParent
= GetEntry( _pParent
, i
);
402 if ( _rPos
== _nEntryPos
)
407 SvTreeListEntry
* pEntry
= GetChildOnPos( pParent
, _nEntryPos
, _rPos
);
416 void SvTabListBox::SetTabJustify( sal_uInt16 nTab
, SvTabJustify eJustify
)
418 DBG_ASSERT(nTab
<mvTabList
.size(),"GetTabPos:Invalid Tab");
419 if( nTab
>= mvTabList
.size() )
421 SvLBoxTab
& rTab
= mvTabList
[ nTab
];
422 SvLBoxTabFlags nFlags
= rTab
.nFlags
;
423 nFlags
&= ~MYTABMASK
;
424 // see SvLBoxTab::CalcOffset for force, which only matters for centering
425 nFlags
|= static_cast<SvLBoxTabFlags
>(eJustify
) | SvLBoxTabFlags::FORCE
;
426 rTab
.nFlags
= nFlags
;
427 SvTreeListBox::nTreeFlags
|= SvTreeFlags::RECALCTABS
;
432 long SvTabListBox::GetLogicTab( sal_uInt16 nTab
)
434 if( SvTreeListBox::nTreeFlags
& SvTreeFlags::RECALCTABS
)
437 DBG_ASSERT(nTab
<mvTabList
.size(),"GetTabPos:Invalid Tab");
438 return aTabs
[ nTab
]->GetPos();
443 struct SvHeaderTabListBoxImpl
445 VclPtr
<HeaderBar
> m_pHeaderBar
;
446 AccessibleFactoryAccess m_aFactoryAccess
;
448 SvHeaderTabListBoxImpl() : m_pHeaderBar( nullptr ) { }
452 SvHeaderTabListBox::SvHeaderTabListBox( vcl::Window
* pParent
, WinBits nWinStyle
)
453 : SvTabListBox(pParent
, nWinStyle
)
454 , m_bFirstPaint(true)
455 , m_pImpl(new ::vcl::SvHeaderTabListBoxImpl
)
456 , m_pAccessible(nullptr)
460 SvHeaderTabListBox::~SvHeaderTabListBox()
465 void SvHeaderTabListBox::dispose()
468 SvTabListBox::dispose();
471 void SvHeaderTabListBox::Paint( vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
475 m_bFirstPaint
= false;
477 SvTabListBox::Paint(rRenderContext
, rRect
);
480 void SvHeaderTabListBox::InitHeaderBar( HeaderBar
* pHeaderBar
)
482 DBG_ASSERT( !m_pImpl
->m_pHeaderBar
, "header bar already initialized" );
483 DBG_ASSERT( pHeaderBar
, "invalid header bar initialization" );
484 m_pImpl
->m_pHeaderBar
= pHeaderBar
;
485 SetScrolledHdl( LINK( this, SvHeaderTabListBox
, ScrollHdl_Impl
) );
486 m_pImpl
->m_pHeaderBar
->SetCreateAccessibleHdl( LINK( this, SvHeaderTabListBox
, CreateAccessibleHdl_Impl
) );
489 HeaderBar
* SvHeaderTabListBox::GetHeaderBar()
491 return m_pImpl
? m_pImpl
->m_pHeaderBar
: nullptr;
494 bool SvHeaderTabListBox::IsItemChecked( SvTreeListEntry
* pEntry
, sal_uInt16 nCol
)
496 SvButtonState eState
= SvButtonState::Unchecked
;
497 SvLBoxButton
& rItem
= static_cast<SvLBoxButton
&>( pEntry
->GetItem( nCol
+ 1 ) );
499 if (rItem
.GetType() == SvLBoxItemType::Button
)
501 SvItemStateFlags nButtonFlags
= rItem
.GetButtonFlags();
502 eState
= SvLBoxButtonData::ConvertToButtonState( nButtonFlags
);
505 return ( eState
== SvButtonState::Checked
);
508 SvTreeListEntry
* SvHeaderTabListBox::InsertEntryToColumn(
509 const OUString
& rStr
, SvTreeListEntry
* pParent
, sal_uLong nPos
, sal_uInt16 nCol
, void* pUserData
)
511 SvTreeListEntry
* pEntry
= SvTabListBox::InsertEntryToColumn( rStr
, pParent
, nPos
, nCol
, pUserData
);
512 RecalculateAccessibleChildren();
516 SvTreeListEntry
* SvHeaderTabListBox::InsertEntryToColumn(
517 const OUString
& rStr
, const Image
& rExpandedEntryBmp
, const Image
& rCollapsedEntryBmp
,
518 SvTreeListEntry
* pParent
, sal_uLong nPos
, sal_uInt16 nCol
, void* pUserData
)
520 SvTreeListEntry
* pEntry
= SvTabListBox::InsertEntryToColumn(
521 rStr
, rExpandedEntryBmp
, rCollapsedEntryBmp
, pParent
, nPos
, nCol
, pUserData
);
522 RecalculateAccessibleChildren();
526 sal_uLong
SvHeaderTabListBox::Insert(
527 SvTreeListEntry
* pEnt
, SvTreeListEntry
* pPar
, sal_uLong nPos
)
529 sal_uLong n
= SvTabListBox::Insert( pEnt
, pPar
, nPos
);
530 RecalculateAccessibleChildren();
534 sal_uLong
SvHeaderTabListBox::Insert( SvTreeListEntry
* pEntry
, sal_uLong nRootPos
)
536 sal_uLong nPos
= SvTabListBox::Insert( pEntry
, nRootPos
);
537 RecalculateAccessibleChildren();
541 IMPL_LINK_NOARG(SvHeaderTabListBox
, ScrollHdl_Impl
, SvTreeListBox
*, void)
543 m_pImpl
->m_pHeaderBar
->SetOffset( -GetXOffset() );
546 IMPL_LINK_NOARG(SvHeaderTabListBox
, CreateAccessibleHdl_Impl
, HeaderBar
*, void)
548 vcl::Window
* pParent
= m_pImpl
->m_pHeaderBar
->GetAccessibleParentWindow();
549 DBG_ASSERT( pParent
, "SvHeaderTabListBox..CreateAccessibleHdl_Impl - accessible parent not found" );
552 css::uno::Reference
< XAccessible
> xAccParent
= pParent
->GetAccessible();
553 if ( xAccParent
.is() )
555 Reference
< XAccessible
> xAccessible
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleBrowseBoxHeaderBar(
556 xAccParent
, *this, ::vcl::BBTYPE_COLUMNHEADERBAR
);
557 m_pImpl
->m_pHeaderBar
->SetAccessible( xAccessible
);
562 void SvHeaderTabListBox::RecalculateAccessibleChildren()
564 if ( !m_aAccessibleChildren
.empty() )
566 sal_uInt32 nCount
= ( GetRowCount() + 1 ) * GetColumnCount();
567 if ( m_aAccessibleChildren
.size() < nCount
)
568 m_aAccessibleChildren
.resize( nCount
);
571 DBG_ASSERT( m_aAccessibleChildren
.size() == nCount
, "wrong children count" );
576 bool SvHeaderTabListBox::IsCellCheckBox( long _nRow
, sal_uInt16 _nColumn
, TriState
& _rState
)
579 SvTreeListEntry
* pEntry
= GetEntry( _nRow
);
582 sal_uInt16 nItemCount
= pEntry
->ItemCount();
583 if ( nItemCount
> ( _nColumn
+ 1 ) )
585 SvLBoxItem
& rItem
= pEntry
->GetItem( _nColumn
+ 1 );
586 if (rItem
.GetType() == SvLBoxItemType::Button
)
589 _rState
= ( ( static_cast<SvLBoxButton
&>(rItem
).GetButtonFlags() & SvItemStateFlags::UNCHECKED
) == SvItemStateFlags::NONE
)
590 ? TRISTATE_TRUE
: TRISTATE_FALSE
;
595 SAL_WARN( "svtools.contnr", "SvHeaderTabListBox::IsCellCheckBox(): column out of range" );
600 long SvHeaderTabListBox::GetRowCount() const
602 return GetEntryCount();
605 sal_uInt16
SvHeaderTabListBox::GetColumnCount() const
607 return m_pImpl
->m_pHeaderBar
->GetItemCount();
610 sal_Int32
SvHeaderTabListBox::GetCurrRow() const
613 SvTreeListEntry
* pEntry
= GetCurEntry();
616 sal_uLong nCount
= GetEntryCount();
617 for ( sal_uLong i
= 0; i
< nCount
; ++i
)
619 if ( pEntry
== GetEntry(i
) )
630 sal_uInt16
SvHeaderTabListBox::GetCurrColumn() const
632 sal_uInt16 nPos
= GetCurrentTabPos() - 1;
636 OUString
SvHeaderTabListBox::GetRowDescription( sal_Int32 _nRow
) const
638 return GetEntryText( _nRow
);
641 OUString
SvHeaderTabListBox::GetColumnDescription( sal_uInt16 _nColumn
) const
643 return m_pImpl
->m_pHeaderBar
->GetItemText( m_pImpl
->m_pHeaderBar
->GetItemId( _nColumn
) );
646 bool SvHeaderTabListBox::HasRowHeader() const
651 bool SvHeaderTabListBox::GoToCell( sal_Int32 _nRow
, sal_uInt16 _nColumn
)
653 bool bRet
= IsCellFocusEnabled();
656 // first set cursor to _nRow
657 SetCursor( GetEntry( _nRow
), true );
658 // then set the focus into _nColumn
659 bRet
= SetCurrentTabPos( _nColumn
);
664 void SvHeaderTabListBox::SetNoSelection()
666 SvTreeListBox::SelectAll(false);
669 void SvHeaderTabListBox::SelectAll()
671 SvTreeListBox::SelectAll(true);
674 void SvHeaderTabListBox::SelectRow( long _nRow
, bool _bSelect
, bool )
676 Select( GetEntry( _nRow
), _bSelect
);
679 void SvHeaderTabListBox::SelectColumn( sal_uInt16
, bool )
683 sal_Int32
SvHeaderTabListBox::GetSelectedRowCount() const
685 return GetSelectionCount();
688 sal_Int32
SvHeaderTabListBox::GetSelectedColumnCount() const
693 bool SvHeaderTabListBox::IsRowSelected( long _nRow
) const
695 SvTreeListEntry
* pEntry
= GetEntry( _nRow
);
696 return ( pEntry
&& IsSelected( pEntry
) );
699 bool SvHeaderTabListBox::IsColumnSelected( long ) const
704 void SvHeaderTabListBox::GetAllSelectedRows( css::uno::Sequence
< sal_Int32
>& ) const
708 void SvHeaderTabListBox::GetAllSelectedColumns( css::uno::Sequence
< sal_Int32
>& ) const
712 bool SvHeaderTabListBox::IsCellVisible( sal_Int32
, sal_uInt16
) const
717 OUString
SvHeaderTabListBox::GetAccessibleCellText( long _nRow
, sal_uInt16 _nColumnPos
) const
719 return GetTabEntryText(_nRow
, _nColumnPos
);
722 tools::Rectangle
SvHeaderTabListBox::calcHeaderRect( bool _bIsColumnBar
, bool _bOnScreen
)
724 tools::Rectangle aRect
;
727 vcl::Window
* pParent
= nullptr;
729 pParent
= m_pImpl
->m_pHeaderBar
->GetAccessibleParentWindow();
731 aRect
= m_pImpl
->m_pHeaderBar
->GetWindowExtentsRelative( pParent
);
736 tools::Rectangle
SvHeaderTabListBox::calcTableRect( bool _bOnScreen
)
738 vcl::Window
* pParent
= nullptr;
740 pParent
= GetAccessibleParentWindow();
742 tools::Rectangle
aRect( GetWindowExtentsRelative( pParent
) );
746 tools::Rectangle
SvHeaderTabListBox::GetFieldRectPixelAbs( sal_Int32 _nRow
, sal_uInt16 _nColumn
, bool _bIsHeader
, bool _bOnScreen
)
748 DBG_ASSERT( !_bIsHeader
|| 0 == _nRow
, "invalid parameters" );
749 tools::Rectangle aRect
;
750 SvTreeListEntry
* pEntry
= GetEntry( _nRow
);
753 aRect
= _bIsHeader
? calcHeaderRect( true, false ) : GetBoundingRect( pEntry
);
754 Point aTopLeft
= aRect
.TopLeft();
755 DBG_ASSERT( m_pImpl
->m_pHeaderBar
->GetItemCount() > _nColumn
, "invalid column" );
756 tools::Rectangle aItemRect
= m_pImpl
->m_pHeaderBar
->GetItemRect( m_pImpl
->m_pHeaderBar
->GetItemId( _nColumn
) );
757 aTopLeft
.setX( aItemRect
.Left() );
758 Size aSize
= aItemRect
.GetSize();
759 aRect
= tools::Rectangle( aTopLeft
, aSize
);
760 vcl::Window
* pParent
= nullptr;
762 pParent
= GetAccessibleParentWindow();
763 aTopLeft
= aRect
.TopLeft();
764 aTopLeft
+= GetWindowExtentsRelative( pParent
).TopLeft();
765 aRect
= tools::Rectangle( aTopLeft
, aRect
.GetSize() );
771 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessibleCell( sal_Int32 _nRow
, sal_uInt16 _nColumnPos
)
773 OSL_ENSURE( m_pAccessible
, "Invalid call: Accessible is null" );
775 Reference
< XAccessible
> xChild
;
776 sal_Int32 nIndex
= -1;
778 if ( !AreChildrenTransient() )
780 const sal_uInt16 nColumnCount
= GetColumnCount();
782 // first call? -> initial list
783 if ( m_aAccessibleChildren
.empty() )
785 sal_Int32 nCount
= ( GetRowCount() + 1 ) * nColumnCount
;
786 m_aAccessibleChildren
.assign( nCount
, Reference
< XAccessible
>() );
789 nIndex
= ( _nRow
* nColumnCount
) + _nColumnPos
+ nColumnCount
;
790 xChild
= m_aAccessibleChildren
[ nIndex
];
795 TriState eState
= TRISTATE_INDET
;
796 bool bIsCheckBox
= IsCellCheckBox( _nRow
, _nColumnPos
, eState
);
798 xChild
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleCheckBoxCell(
799 m_pAccessible
->getHeaderBar(), *this, nullptr, _nRow
, _nColumnPos
, eState
, false );
801 xChild
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleBrowseBoxTableCell(
802 m_pAccessible
->getHeaderBar(), *this, nullptr, _nRow
, _nColumnPos
, OFFSET_NONE
);
805 if ( !AreChildrenTransient() )
806 m_aAccessibleChildren
[ nIndex
] = xChild
;
812 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessibleRowHeader( sal_Int32
)
814 Reference
< XAccessible
> xHeader
;
818 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessibleColumnHeader( sal_uInt16 _nColumn
)
820 // first call? -> initial list
821 if ( m_aAccessibleChildren
.empty() )
823 const sal_uInt16 nColumnCount
= GetColumnCount();
824 sal_Int32 nCount
= AreChildrenTransient() ?
825 nColumnCount
: ( GetRowCount() + 1 ) * nColumnCount
;
826 m_aAccessibleChildren
.assign( nCount
, Reference
< XAccessible
>() );
830 Reference
< XAccessible
> xChild
= m_aAccessibleChildren
[ _nColumn
];
832 if ( !xChild
.is() && m_pAccessible
)
834 // no -> create new header cell
835 xChild
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleBrowseBoxHeaderCell(
836 _nColumn
, m_pAccessible
->getHeaderBar(),
837 *this, nullptr, ::vcl::BBTYPE_COLUMNHEADERCELL
841 m_aAccessibleChildren
[ _nColumn
] = xChild
;
846 sal_Int32
SvHeaderTabListBox::GetAccessibleControlCount() const
851 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessibleControl( sal_Int32
)
853 Reference
< XAccessible
> xControl
;
857 bool SvHeaderTabListBox::ConvertPointToControlIndex( sal_Int32
&, const Point
& )
862 bool SvHeaderTabListBox::ConvertPointToCellAddress( sal_Int32
&, sal_uInt16
&, const Point
& )
867 bool SvHeaderTabListBox::ConvertPointToRowHeader( sal_Int32
&, const Point
& )
872 bool SvHeaderTabListBox::ConvertPointToColumnHeader( sal_uInt16
&, const Point
& )
877 OUString
SvHeaderTabListBox::GetAccessibleObjectName( ::vcl::AccessibleBrowseBoxObjType _eType
, sal_Int32 _nPos
) const
882 case ::vcl::BBTYPE_BROWSEBOX
:
883 case ::vcl::BBTYPE_TABLE
:
884 case ::vcl::BBTYPE_COLUMNHEADERBAR
:
885 // should be empty now (see #i63983)
889 case ::vcl::BBTYPE_TABLECELL
:
891 // here we need a valid pos, we can not handle -1
894 sal_uInt16 nColumnCount
= GetColumnCount();
895 if (nColumnCount
> 0)
897 sal_Int32 nRow
= _nPos
/ nColumnCount
;
898 sal_uInt16 nColumn
= static_cast< sal_uInt16
>( _nPos
% nColumnCount
);
899 aRetText
= GetCellText( nRow
, nColumn
);
904 case ::vcl::BBTYPE_CHECKBOXCELL
:
906 break; // checkbox cells have no name
908 case ::vcl::BBTYPE_COLUMNHEADERCELL
:
910 aRetText
= m_pImpl
->m_pHeaderBar
->GetItemText( m_pImpl
->m_pHeaderBar
->GetItemId( static_cast<sal_uInt16
>(_nPos
) ) );
914 case ::vcl::BBTYPE_ROWHEADERBAR
:
915 case ::vcl::BBTYPE_ROWHEADERCELL
:
920 OSL_FAIL("BrowseBox::GetAccessibleName: invalid enum!");
925 OUString
SvHeaderTabListBox::GetAccessibleObjectDescription( ::vcl::AccessibleBrowseBoxObjType _eType
, sal_Int32 _nPos
) const
929 if( _eType
== ::vcl::BBTYPE_TABLECELL
&& _nPos
!= -1 )
931 const OUString
sVar1( "%1" );
932 const OUString
sVar2( "%2" );
934 sal_uInt16 nColumnCount
= GetColumnCount();
935 if (nColumnCount
> 0)
937 sal_Int32 nRow
= _nPos
/ nColumnCount
;
938 sal_uInt16 nColumn
= static_cast< sal_uInt16
>( _nPos
% nColumnCount
);
940 OUString
aText( VclResId(STR_SVT_ACC_DESC_TABLISTBOX
) );
941 aText
= aText
.replaceFirst( sVar1
, OUString::number( nRow
) );
942 OUString sColHeader
= m_pImpl
->m_pHeaderBar
->GetItemText( m_pImpl
->m_pHeaderBar
->GetItemId( nColumn
) );
943 if ( sColHeader
.isEmpty() )
944 sColHeader
= OUString::number( nColumn
);
945 aText
= aText
.replaceFirst( sVar2
, sColHeader
);
953 void SvHeaderTabListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper
& _rStateSet
, ::vcl::AccessibleBrowseBoxObjType _eType
) const
957 case ::vcl::BBTYPE_BROWSEBOX
:
958 case ::vcl::BBTYPE_TABLE
:
960 _rStateSet
.AddState( AccessibleStateType::FOCUSABLE
);
962 _rStateSet
.AddState( AccessibleStateType::FOCUSED
);
964 _rStateSet
.AddState( AccessibleStateType::ACTIVE
);
967 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
968 _rStateSet
.AddState( AccessibleStateType::SENSITIVE
);
970 if ( IsReallyVisible() )
971 _rStateSet
.AddState( AccessibleStateType::VISIBLE
);
972 if ( _eType
== ::vcl::BBTYPE_TABLE
)
975 if ( AreChildrenTransient() )
976 _rStateSet
.AddState( AccessibleStateType::MANAGES_DESCENDANTS
);
977 _rStateSet
.AddState( AccessibleStateType::MULTI_SELECTABLE
);
982 case ::vcl::BBTYPE_COLUMNHEADERBAR
:
984 sal_Int32 nCurRow
= GetCurrRow();
985 sal_uInt16 nCurColumn
= GetCurrColumn();
986 if ( IsCellVisible( nCurRow
, nCurColumn
) )
987 _rStateSet
.AddState( AccessibleStateType::VISIBLE
);
989 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
990 _rStateSet
.AddState( AccessibleStateType::TRANSIENT
);
994 case ::vcl::BBTYPE_ROWHEADERCELL
:
995 case ::vcl::BBTYPE_COLUMNHEADERCELL
:
997 _rStateSet
.AddState( AccessibleStateType::VISIBLE
);
998 _rStateSet
.AddState( AccessibleStateType::FOCUSABLE
);
999 _rStateSet
.AddState( AccessibleStateType::TRANSIENT
);
1001 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
1009 void SvHeaderTabListBox::FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper
& _rStateSet
, sal_Int32 _nRow
, sal_uInt16 _nColumn
) const
1011 _rStateSet
.AddState( AccessibleStateType::SELECTABLE
);
1012 if ( AreChildrenTransient() )
1013 _rStateSet
.AddState( AccessibleStateType::TRANSIENT
);
1015 if ( IsCellVisible( _nRow
, _nColumn
) )
1017 _rStateSet
.AddState( AccessibleStateType::VISIBLE
);
1018 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
1021 if ( IsRowSelected( _nRow
) )
1023 _rStateSet
.AddState( AccessibleStateType::ACTIVE
);
1024 _rStateSet
.AddState( AccessibleStateType::SELECTED
);
1027 _rStateSet
.AddState( AccessibleStateType::ENABLED
);
1030 void SvHeaderTabListBox::GrabTableFocus()
1035 bool SvHeaderTabListBox::GetGlyphBoundRects( const Point
& rOrigin
, const OUString
& rStr
, int nIndex
, int nLen
, MetricVector
& rVector
)
1037 return Control::GetGlyphBoundRects( rOrigin
, rStr
, nIndex
, nLen
, rVector
);
1040 tools::Rectangle
SvHeaderTabListBox::GetWindowExtentsRelative( vcl::Window
*pRelativeWindow
) const
1042 return Control::GetWindowExtentsRelative( pRelativeWindow
);
1045 void SvHeaderTabListBox::GrabFocus()
1047 Control::GrabFocus();
1050 Reference
< XAccessible
> SvHeaderTabListBox::GetAccessible()
1052 return Control::GetAccessible();
1055 vcl::Window
* SvHeaderTabListBox::GetAccessibleParentWindow() const
1057 return Control::GetAccessibleParentWindow();
1060 vcl::Window
* SvHeaderTabListBox::GetWindowInstance()
1065 Reference
< XAccessible
> SvHeaderTabListBox::CreateAccessible()
1067 vcl::Window
* pParent
= GetAccessibleParentWindow();
1068 DBG_ASSERT( pParent
, "SvHeaderTabListBox::::CreateAccessible - accessible parent not found" );
1070 Reference
< XAccessible
> xAccessible
;
1071 if ( m_pAccessible
) xAccessible
= m_pAccessible
->getMyself();
1073 if( pParent
&& !m_pAccessible
)
1075 Reference
< XAccessible
> xAccParent
= pParent
->GetAccessible();
1076 if ( xAccParent
.is() )
1078 m_pAccessible
= m_pImpl
->m_aFactoryAccess
.getFactory().createAccessibleTabListBox( xAccParent
, *this );
1079 if ( m_pAccessible
)
1080 xAccessible
= m_pAccessible
->getMyself();
1086 tools::Rectangle
SvHeaderTabListBox::GetFieldCharacterBounds(sal_Int32
,sal_Int32
,sal_Int32
)
1088 return tools::Rectangle();
1091 sal_Int32
SvHeaderTabListBox::GetFieldIndexAtPoint(sal_Int32 _nRow
,sal_Int32 _nColumnPos
,const Point
& _rPoint
)
1093 OUString sText
= GetAccessibleCellText( _nRow
, static_cast< sal_uInt16
>( _nColumnPos
) );
1094 MetricVector aRects
;
1095 if ( GetGlyphBoundRects(Point(0,0), sText
, 0, sText
.getLength(), aRects
) )
1098 for (auto const& rectangle
: aRects
)
1100 if( rectangle
.IsInside(_rPoint
) )
1109 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */