Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / vcl / source / treelist / svtabbx.cxx
blobc7e17fe66f4bbad9fd7e9446ff1bd416742cabd6
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/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>
31 #include <svdata.hxx>
32 #include <memory>
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() )
46 return;
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!
61 if( !pViewParent )
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);
83 sal_Int32 nIndex = 0;
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()
101 disposeOnce();
104 void SvTabListBox::dispose()
106 mvTabList.clear();
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;
126 if( IsUpdateMode() )
127 Invalidate();
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() )
134 return;
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;
143 if( IsUpdateMode() )
144 Invalidate();
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,
166 void* pUser )
168 OUString aStr;
169 if( nCol != 0xffff )
171 while( nCol )
173 aStr += "\t";
174 nCol--;
177 aStr += rStr;
178 OUString aFirstStr( aStr );
179 sal_Int32 nEnd = aFirstStr.indexOf( '\t' );
180 if( nEnd != -1 )
182 aFirstStr = aFirstStr.copy(0, nEnd);
183 aCurEntry = aStr.copy(++nEnd);
185 else
186 aCurEntry.clear();
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 )
194 OUString aStr;
195 if( nCol != 0xffff )
197 while( nCol )
199 aStr += "\t";
200 nCol--;
203 aStr += rStr;
204 OUString aFirstStr( aStr );
205 sal_Int32 nEnd = aFirstStr.indexOf('\t');
206 if (nEnd != -1)
208 aFirstStr = aFirstStr.copy(0, nEnd);
209 aCurEntry = aStr.copy(++nEnd);
211 else
212 aCurEntry.clear();
214 return SvTreeListBox::InsertEntry(
215 aFirstStr,
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;
229 if( pEntry )
231 sal_uInt16 nCount = pEntry->ItemCount();
232 sal_uInt16 nCur = 0;
233 while( nCur < nCount )
235 const SvLBoxItem& rStr = pEntry->GetItem( nCur );
236 if (rStr.GetType() == SvLBoxItemType::String)
238 if( nCol == 0xffff )
240 if (!aResult.isEmpty())
241 aResult.append("\t");
242 aResult.append(static_cast<const SvLBoxString&>(rStr).GetText());
244 else
246 if( nCol == 0 )
247 return static_cast<const SvLBoxString&>(rStr).GetText();
248 nCol--;
251 nCur++;
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");
266 if( !pEntry )
267 return;
269 OUString sOldText = GetEntryText(pEntry, nCol);
270 if (sOldText == rStr)
271 return;
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)
286 break;
288 else
290 --nCol;
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" );
304 OUString aResult;
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();
311 return aResult;
314 sal_uLong SvTabListBox::GetEntryPos( const SvTreeListEntry* pEntry ) const
316 sal_uLong nPos = 0;
317 SvTreeListEntry* pTmpEntry = First();
318 while( pTmpEntry )
320 if ( pTmpEntry == pEntry )
321 return nPos;
322 pTmpEntry = Next( pTmpEntry );
323 ++nPos;
325 return 0xffffffff;
328 // static
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;
339 if ( pEntry )
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());
354 else
356 if ( nCol == 0 )
358 OUString sRet = static_cast<const SvLBoxString&>(rBoxItem).GetText();
359 if ( sRet.isEmpty() )
360 sRet = VclResId( STR_SVT_ACC_EMPTY_FIELD );
361 return sRet;
363 --nCol;
366 ++nCur;
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 )
381 pEntry = pParent;
382 break;
384 else
386 nPos++;
387 pEntry = GetChildOnPos( pParent, _nEntryPos, nPos );
388 if ( pEntry )
389 break;
393 return pEntry;
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 )
403 return pParent;
404 else
406 _rPos++;
407 SvTreeListEntry* pEntry = GetChildOnPos( pParent, _nEntryPos, _rPos );
408 if ( pEntry )
409 return pEntry;
413 return nullptr;
416 void SvTabListBox::SetTabJustify( sal_uInt16 nTab, SvTabJustify eJustify)
418 DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
419 if( nTab >= mvTabList.size() )
420 return;
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;
428 if( IsUpdateMode() )
429 Invalidate();
432 long SvTabListBox::GetLogicTab( sal_uInt16 nTab )
434 if( SvTreeListBox::nTreeFlags & SvTreeFlags::RECALCTABS )
435 SetTabs();
437 DBG_ASSERT(nTab<mvTabList.size(),"GetTabPos:Invalid Tab");
438 return aTabs[ nTab ]->GetPos();
441 namespace vcl
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()
462 disposeOnce();
465 void SvHeaderTabListBox::dispose()
467 m_pImpl.reset();
468 SvTabListBox::dispose();
471 void SvHeaderTabListBox::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect )
473 if (m_bFirstPaint)
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();
513 return pEntry;
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();
523 return pEntry;
526 sal_uLong SvHeaderTabListBox::Insert(
527 SvTreeListEntry* pEnt, SvTreeListEntry* pPar, sal_uLong nPos )
529 sal_uLong n = SvTabListBox::Insert( pEnt, pPar, nPos );
530 RecalculateAccessibleChildren();
531 return n;
534 sal_uLong SvHeaderTabListBox::Insert( SvTreeListEntry* pEntry, sal_uLong nRootPos )
536 sal_uLong nPos = SvTabListBox::Insert( pEntry, nRootPos );
537 RecalculateAccessibleChildren();
538 return nPos;
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" );
550 if ( pParent )
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 );
569 else
571 DBG_ASSERT( m_aAccessibleChildren.size() == nCount, "wrong children count" );
576 bool SvHeaderTabListBox::IsCellCheckBox( long _nRow, sal_uInt16 _nColumn, TriState& _rState )
578 bool bRet = false;
579 SvTreeListEntry* pEntry = GetEntry( _nRow );
580 if ( pEntry )
582 sal_uInt16 nItemCount = pEntry->ItemCount();
583 if ( nItemCount > ( _nColumn + 1 ) )
585 SvLBoxItem& rItem = pEntry->GetItem( _nColumn + 1 );
586 if (rItem.GetType() == SvLBoxItemType::Button)
588 bRet = true;
589 _rState = ( ( static_cast<SvLBoxButton&>(rItem).GetButtonFlags() & SvItemStateFlags::UNCHECKED ) == SvItemStateFlags::NONE )
590 ? TRISTATE_TRUE : TRISTATE_FALSE;
593 else
595 SAL_WARN( "svtools.contnr", "SvHeaderTabListBox::IsCellCheckBox(): column out of range" );
598 return bRet;
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
612 sal_Int32 nRet = -1;
613 SvTreeListEntry* pEntry = GetCurEntry();
614 if ( pEntry )
616 sal_uLong nCount = GetEntryCount();
617 for ( sal_uLong i = 0; i < nCount; ++i )
619 if ( pEntry == GetEntry(i) )
621 nRet = i;
622 break;
627 return nRet;
630 sal_uInt16 SvHeaderTabListBox::GetCurrColumn() const
632 sal_uInt16 nPos = GetCurrentTabPos() - 1;
633 return nPos;
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
648 return false;
651 bool SvHeaderTabListBox::GoToCell( sal_Int32 _nRow, sal_uInt16 _nColumn )
653 bool bRet = IsCellFocusEnabled();
654 if ( bRet )
656 // first set cursor to _nRow
657 SetCursor( GetEntry( _nRow ), true );
658 // then set the focus into _nColumn
659 bRet = SetCurrentTabPos( _nColumn );
661 return bRet;
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
690 return 0;
693 bool SvHeaderTabListBox::IsRowSelected( long _nRow ) const
695 SvTreeListEntry* pEntry = GetEntry( _nRow );
696 return ( pEntry && IsSelected( pEntry ) );
699 bool SvHeaderTabListBox::IsColumnSelected( long ) const
701 return false;
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
714 return true;
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;
725 if ( _bIsColumnBar )
727 vcl::Window* pParent = nullptr;
728 if ( !_bOnScreen )
729 pParent = m_pImpl->m_pHeaderBar->GetAccessibleParentWindow();
731 aRect = m_pImpl->m_pHeaderBar->GetWindowExtentsRelative( pParent );
733 return aRect;
736 tools::Rectangle SvHeaderTabListBox::calcTableRect( bool _bOnScreen )
738 vcl::Window* pParent = nullptr;
739 if ( !_bOnScreen )
740 pParent = GetAccessibleParentWindow();
742 tools::Rectangle aRect( GetWindowExtentsRelative( pParent ) );
743 return aRect;
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 );
751 if ( pEntry )
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;
761 if ( !_bOnScreen )
762 pParent = GetAccessibleParentWindow();
763 aTopLeft = aRect.TopLeft();
764 aTopLeft += GetWindowExtentsRelative( pParent ).TopLeft();
765 aRect = tools::Rectangle( aTopLeft, aRect.GetSize() );
768 return aRect;
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 ];
793 if ( !xChild.is() )
795 TriState eState = TRISTATE_INDET;
796 bool bIsCheckBox = IsCellCheckBox( _nRow, _nColumnPos, eState );
797 if ( bIsCheckBox )
798 xChild = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleCheckBoxCell(
799 m_pAccessible->getHeaderBar(), *this, nullptr, _nRow, _nColumnPos, eState, false );
800 else
801 xChild = m_pImpl->m_aFactoryAccess.getFactory().createAccessibleBrowseBoxTableCell(
802 m_pAccessible->getHeaderBar(), *this, nullptr, _nRow, _nColumnPos, OFFSET_NONE );
804 // insert into list
805 if ( !AreChildrenTransient() )
806 m_aAccessibleChildren[ nIndex ] = xChild;
809 return xChild;
812 Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleRowHeader( sal_Int32 )
814 Reference< XAccessible > xHeader;
815 return 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 >() );
829 // get header
830 Reference< XAccessible > xChild = m_aAccessibleChildren[ _nColumn ];
831 // already exists?
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
840 // insert into list
841 m_aAccessibleChildren[ _nColumn ] = xChild;
843 return xChild;
846 sal_Int32 SvHeaderTabListBox::GetAccessibleControlCount() const
848 return -1;
851 Reference< XAccessible > SvHeaderTabListBox::CreateAccessibleControl( sal_Int32 )
853 Reference< XAccessible > xControl;
854 return xControl;
857 bool SvHeaderTabListBox::ConvertPointToControlIndex( sal_Int32&, const Point& )
859 return false;
862 bool SvHeaderTabListBox::ConvertPointToCellAddress( sal_Int32&, sal_uInt16&, const Point& )
864 return false;
867 bool SvHeaderTabListBox::ConvertPointToRowHeader( sal_Int32&, const Point& )
869 return false;
872 bool SvHeaderTabListBox::ConvertPointToColumnHeader( sal_uInt16&, const Point& )
874 return false;
877 OUString SvHeaderTabListBox::GetAccessibleObjectName( ::vcl::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
879 OUString aRetText;
880 switch( _eType )
882 case ::vcl::BBTYPE_BROWSEBOX:
883 case ::vcl::BBTYPE_TABLE:
884 case ::vcl::BBTYPE_COLUMNHEADERBAR:
885 // should be empty now (see #i63983)
886 aRetText.clear();
887 break;
889 case ::vcl::BBTYPE_TABLECELL:
891 // here we need a valid pos, we can not handle -1
892 if ( _nPos >= 0 )
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 );
902 break;
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) ) );
911 break;
914 case ::vcl::BBTYPE_ROWHEADERBAR:
915 case ::vcl::BBTYPE_ROWHEADERCELL:
916 aRetText = "error";
917 break;
919 default:
920 OSL_FAIL("BrowseBox::GetAccessibleName: invalid enum!");
922 return aRetText;
925 OUString SvHeaderTabListBox::GetAccessibleObjectDescription( ::vcl::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
927 OUString aRetText;
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 );
946 aRetText = aText;
950 return aRetText;
953 void SvHeaderTabListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& _rStateSet, ::vcl::AccessibleBrowseBoxObjType _eType ) const
955 switch( _eType )
957 case ::vcl::BBTYPE_BROWSEBOX:
958 case ::vcl::BBTYPE_TABLE:
960 _rStateSet.AddState( AccessibleStateType::FOCUSABLE );
961 if ( HasFocus() )
962 _rStateSet.AddState( AccessibleStateType::FOCUSED );
963 if ( IsActive() )
964 _rStateSet.AddState( AccessibleStateType::ACTIVE );
965 if ( IsEnabled() )
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 );
979 break;
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 );
988 if ( IsEnabled() )
989 _rStateSet.AddState( AccessibleStateType::ENABLED );
990 _rStateSet.AddState( AccessibleStateType::TRANSIENT );
991 break;
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 );
1000 if ( IsEnabled() )
1001 _rStateSet.AddState( AccessibleStateType::ENABLED );
1002 break;
1004 default:
1005 break;
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 );
1026 if ( IsEnabled() )
1027 _rStateSet.AddState( AccessibleStateType::ENABLED );
1030 void SvHeaderTabListBox::GrabTableFocus()
1032 GrabFocus();
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()
1062 return this;
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();
1083 return xAccessible;
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) )
1097 sal_Int32 nPos = 0;
1098 for (auto const& rectangle : aRects)
1100 if( rectangle.IsInside(_rPoint) )
1101 return nPos;
1102 ++nPos;
1106 return -1;
1109 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */