nss: upgrade to release 3.73
[LibreOffice.git] / vcl / source / treelist / svtabbx.cxx
bloba789607a21938b2e45ec13b5bb1ea145dbc42963
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <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>
33 #include <svdata.hxx>
34 #include <memory>
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() )
48 return;
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!
63 if( !pViewParent )
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);
85 sal_Int32 nIndex = 0;
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()
103 disposeOnce();
106 void SvTabListBox::dispose()
108 mvTabList.clear();
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;
128 if( IsUpdateMode() )
129 Invalidate();
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,
151 void* pUser )
153 OUString aStr;
154 if( nCol != 0xffff )
156 while( nCol )
158 aStr += "\t";
159 nCol--;
162 aStr += rStr;
163 OUString aFirstStr( aStr );
164 sal_Int32 nEnd = aFirstStr.indexOf( '\t' );
165 if( nEnd != -1 )
167 aFirstStr = aFirstStr.copy(0, nEnd);
168 aCurEntry = aStr.copy(++nEnd);
170 else
171 aCurEntry.clear();
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 )
179 OUString aStr;
180 if( nCol != 0xffff )
182 while( nCol )
184 aStr += "\t";
185 nCol--;
188 aStr += rStr;
189 OUString aFirstStr( aStr );
190 sal_Int32 nEnd = aFirstStr.indexOf('\t');
191 if (nEnd != -1)
193 aFirstStr = aFirstStr.copy(0, nEnd);
194 aCurEntry = aStr.copy(++nEnd);
196 else
197 aCurEntry.clear();
199 return SvTreeListBox::InsertEntry(
200 aFirstStr,
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;
214 if( pEntry )
216 sal_uInt16 nCount = pEntry->ItemCount();
217 sal_uInt16 nCur = 0;
218 while( nCur < nCount )
220 const SvLBoxItem& rStr = pEntry->GetItem( nCur );
221 if (rStr.GetType() == SvLBoxItemType::String)
223 if( nCol == 0xffff )
225 if (!aResult.isEmpty())
226 aResult.append("\t");
227 aResult.append(static_cast<const SvLBoxString&>(rStr).GetText());
229 else
231 if( nCol == 0 )
232 return static_cast<const SvLBoxString&>(rStr).GetText();
233 nCol--;
236 nCur++;
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" );
252 OUString aResult;
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();
259 return aResult;
262 sal_uLong SvTabListBox::GetEntryPos( const SvTreeListEntry* pEntry ) const
264 sal_uLong nPos = 0;
265 SvTreeListEntry* pTmpEntry = First();
266 while( pTmpEntry )
268 if ( pTmpEntry == pEntry )
269 return nPos;
270 pTmpEntry = Next( pTmpEntry );
271 ++nPos;
273 return 0xffffffff;
276 // static
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;
287 if ( pEntry )
289 sal_uInt16 nCount = pEntry->ItemCount();
290 sal_uInt16 nCur = 0;
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());
302 else
304 if ( nCol == 0 )
306 OUString sRet = static_cast<const SvLBoxString&>(rBoxItem).GetText();
307 if ( sRet.isEmpty() )
308 sRet = VclResId( STR_SVT_ACC_EMPTY_FIELD );
309 return sRet;
311 --nCol;
314 ++nCur;
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 )
329 pEntry = pParent;
330 break;
332 else
334 nPos++;
335 pEntry = GetChildOnPos( pParent, _nEntryPos, nPos );
336 if ( pEntry )
337 break;
341 return pEntry;
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 )
351 return pParent;
352 else
354 _rPos++;
355 SvTreeListEntry* pEntry = GetChildOnPos( pParent, _nEntryPos, _rPos );
356 if ( pEntry )
357 return pEntry;
361 return nullptr;
364 void SvTabListBox::SetTabJustify( sal_uInt16 nTab, SvTabJustify eJustify)
366 DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
367 if( nTab >= mvTabList.size() )
368 return;
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;
376 if( IsUpdateMode() )
377 Invalidate();
380 void SvTabListBox::SetTabEditable(sal_uInt16 nTab, bool bEditable)
382 DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
383 if( nTab >= mvTabList.size() )
384 return;
385 SvLBoxTab& rTab = mvTabList[ nTab ];
386 if (bEditable)
387 rTab.nFlags |= SvLBoxTabFlags::EDITABLE;
388 else
389 rTab.nFlags &= ~SvLBoxTabFlags::EDITABLE;
392 tools::Long SvTabListBox::GetLogicTab( sal_uInt16 nTab )
394 if( SvTreeListBox::nTreeFlags & SvTreeFlags::RECALCTABS )
395 SetTabs();
397 DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
398 return aTabs[ nTab ]->GetPos();
401 namespace vcl
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()
422 disposeOnce();
425 void SvHeaderTabListBox::dispose()
427 m_pImpl.reset();
428 SvTabListBox::dispose();
431 void SvHeaderTabListBox::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect )
433 if (m_bFirstPaint)
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();
473 return pEntry;
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();
483 return pEntry;
486 sal_uLong SvHeaderTabListBox::Insert(
487 SvTreeListEntry* pEnt, SvTreeListEntry* pPar, sal_uLong nPos )
489 sal_uLong n = SvTabListBox::Insert( pEnt, pPar, nPos );
490 RecalculateAccessibleChildren();
491 return n;
494 sal_uLong SvHeaderTabListBox::Insert( SvTreeListEntry* pEntry, sal_uLong nRootPos )
496 sal_uLong nPos = SvTabListBox::Insert( pEntry, nRootPos );
497 RecalculateAccessibleChildren();
498 return nPos;
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" );
510 if ( pParent )
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 );
529 else
531 DBG_ASSERT( m_aAccessibleChildren.size() == nCount, "wrong children count" );
536 bool SvHeaderTabListBox::IsCellCheckBox( sal_Int32 _nRow, sal_uInt16 _nColumn, TriState& _rState )
538 bool bRet = false;
539 SvTreeListEntry* pEntry = GetEntry( _nRow );
540 if ( pEntry )
542 sal_uInt16 nItemCount = pEntry->ItemCount();
543 if ( nItemCount > ( _nColumn + 1 ) )
545 SvLBoxItem& rItem = pEntry->GetItem( _nColumn + 1 );
546 if (rItem.GetType() == SvLBoxItemType::Button)
548 bRet = true;
549 _rState = ( ( static_cast<SvLBoxButton&>(rItem).GetButtonFlags() & SvItemStateFlags::UNCHECKED ) == SvItemStateFlags::NONE )
550 ? TRISTATE_TRUE : TRISTATE_FALSE;
553 else
555 SAL_WARN( "svtools.contnr", "SvHeaderTabListBox::IsCellCheckBox(): column out of range" );
558 return bRet;
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
572 sal_Int32 nRet = -1;
573 SvTreeListEntry* pEntry = GetCurEntry();
574 if ( pEntry )
576 sal_uLong nCount = GetEntryCount();
577 for ( sal_uLong i = 0; i < nCount; ++i )
579 if ( pEntry == GetEntry(i) )
581 nRet = i;
582 break;
587 return nRet;
590 sal_uInt16 SvHeaderTabListBox::GetCurrColumn() const
592 return 0;
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
607 return false;
610 bool SvHeaderTabListBox::GoToCell( sal_Int32 /*_nRow*/, sal_uInt16 /*_nColumn*/ )
612 return false;
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
641 return 0;
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
652 return false;
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
665 return true;
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;
676 if ( _bIsColumnBar )
678 vcl::Window* pParent = nullptr;
679 if ( !_bOnScreen )
680 pParent = m_pImpl->m_pHeaderBar->GetAccessibleParentWindow();
682 aRect = m_pImpl->m_pHeaderBar->GetWindowExtentsRelative( pParent );
684 return aRect;
687 tools::Rectangle SvHeaderTabListBox::calcTableRect( bool _bOnScreen )
689 vcl::Window* pParent = nullptr;
690 if ( !_bOnScreen )
691 pParent = GetAccessibleParentWindow();
693 tools::Rectangle aRect( GetWindowExtentsRelative( pParent ) );
694 return aRect;
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 );
702 if ( pEntry )
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;
712 if ( !_bOnScreen )
713 pParent = GetAccessibleParentWindow();
714 aTopLeft = aRect.TopLeft();
715 aTopLeft += GetWindowExtentsRelative( pParent ).TopLeft();
716 aRect = tools::Rectangle( aTopLeft, aRect.GetSize() );
719 return aRect;
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 );
730 if ( bIsCheckBox )
731 xChild = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleCheckBoxCell(
732 m_pAccessible->getHeaderBar(), *this, nullptr, _nRow, _nColumnPos, eState, false );
733 else
734 xChild = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleBrowseBoxTableCell(
735 m_pAccessible->getHeaderBar(), *this, nullptr, _nRow, _nColumnPos, OFFSET_NONE );
737 return xChild;
740 Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleRowHeader( sal_Int32 )
742 Reference< XAccessible > xHeader;
743 return 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 >() );
755 // get header
756 Reference< XAccessible > xChild = m_aAccessibleChildren[ _nColumn ];
757 // already exists?
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
766 // insert into list
767 m_aAccessibleChildren[ _nColumn ] = xChild;
769 return xChild;
772 sal_Int32 SvHeaderTabListBox::GetAccessibleControlCount() const
774 return -1;
777 Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleControl( sal_Int32 )
779 Reference< XAccessible > xControl;
780 return xControl;
783 bool SvHeaderTabListBox::ConvertPointToControlIndex( sal_Int32&, const Point& )
785 return false;
788 bool SvHeaderTabListBox::ConvertPointToCellAddress( sal_Int32&, sal_uInt16&, const Point& )
790 return false;
793 bool SvHeaderTabListBox::ConvertPointToRowHeader( sal_Int32&, const Point& )
795 return false;
798 bool SvHeaderTabListBox::ConvertPointToColumnHeader( sal_uInt16&, const Point& )
800 return false;
803 OUString SvHeaderTabListBox::GetAccessibleObjectName( ::vcl::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
805 OUString aRetText;
806 switch( _eType )
808 case ::vcl::BBTYPE_BROWSEBOX:
809 case ::vcl::BBTYPE_TABLE:
810 case ::vcl::BBTYPE_COLUMNHEADERBAR:
811 // should be empty now (see #i63983)
812 aRetText.clear();
813 break;
815 case ::vcl::BBTYPE_TABLECELL:
817 // here we need a valid pos, we can not handle -1
818 if ( _nPos >= 0 )
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 );
828 break;
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) ) );
837 break;
840 case ::vcl::BBTYPE_ROWHEADERBAR:
841 case ::vcl::BBTYPE_ROWHEADERCELL:
842 aRetText = "error";
843 break;
845 default:
846 OSL_FAIL("BrowseBox::GetAccessibleName: invalid enum!");
848 return aRetText;
851 OUString SvHeaderTabListBox::GetAccessibleObjectDescription( ::vcl::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
853 OUString aRetText;
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 );
869 aRetText = aText;
873 return aRetText;
876 void SvHeaderTabListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& _rStateSet, ::vcl::AccessibleBrowseBoxObjType _eType ) const
878 switch( _eType )
880 case ::vcl::BBTYPE_BROWSEBOX:
881 case ::vcl::BBTYPE_TABLE:
883 _rStateSet.AddState( AccessibleStateType::FOCUSABLE );
884 if ( HasFocus() )
885 _rStateSet.AddState( AccessibleStateType::FOCUSED );
886 if ( IsActive() )
887 _rStateSet.AddState( AccessibleStateType::ACTIVE );
888 if ( IsEnabled() )
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 );
901 break;
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 );
910 if ( IsEnabled() )
911 _rStateSet.AddState( AccessibleStateType::ENABLED );
912 _rStateSet.AddState( AccessibleStateType::TRANSIENT );
913 break;
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 );
922 if ( IsEnabled() )
923 _rStateSet.AddState( AccessibleStateType::ENABLED );
924 break;
926 default:
927 break;
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 );
947 if ( IsEnabled() )
948 _rStateSet.AddState( AccessibleStateType::ENABLED );
951 void SvHeaderTabListBox::GrabTableFocus()
953 GrabFocus();
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()
983 return this;
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();
1004 return xAccessible;
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) )
1018 sal_Int32 nPos = 0;
1019 for (auto const& rectangle : aRects)
1021 if( rectangle.IsInside(_rPoint) )
1022 return nPos;
1023 ++nPos;
1027 return -1;
1030 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */