34#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
35#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
36#include <com/sun/star/accessibility/AccessibleEventId.hpp>
41#define SCROLL_FLAGS (ScrollFlags::Clip | ScrollFlags::NoChildren)
43using namespace com::sun::star::accessibility::AccessibleEventId;
44using namespace com::sun::star::accessibility::AccessibleTableModelChangeType;
45using com::sun::star::accessibility::AccessibleTableModelChange;
64 SAL_INFO(
"svtools",
"BrowseBox:ConstructImpl " <<
this );
69 m_pImpl.reset( new ::svt::BrowseBoxImpl() );
153 return nScrollBarSize;
165 ,DragSourceHelper( this )
166 ,DropTargetHelper( this )
172 ,m_nActualCornerWidth(0)
173 ,m_bNavigationBar(false)
187 disposeAndClearHeaderCell(
m_pImpl->m_aColHeaderCellMap);
188 disposeAndClearHeaderCell(
m_pImpl->m_aRowHeaderCellMap);
189 m_pImpl->m_pAccessible->dispose();
190 m_pImpl->m_pAccessible =
nullptr;
196 SAL_INFO(
"svtools",
"BrowseBox:dispose " <<
this );
212 DragSourceHelper::dispose();
213 DropTargetHelper::dispose();
228 short nHiddenCount = --
pDataWin->nCursorHidden;
231 if (1 == nHiddenCount)
236 if (0 == nHiddenCount)
244 short nHiddenCount = ++
pDataWin->nCursorHidden;
247 if (2 == nHiddenCount)
252 if (1 == nHiddenCount)
260 pDataWin->aRealRowCount = rRealRowCount;
277 return pDataWin->GetTextWidth( _rText ) +
pDataWin->GetTextWidth(OUString(
'0')) * 4;
284#if OSL_DEBUG_LEVEL > 0
288 OSL_ENSURE(
col->GetId() !=
HandleColumnId,
"BrowseBox::InsertHandleColumn: there is a non-Handle column with handle ID" );
298 pDataWin->pHeaderBar->SetPosSizePixel(
312 OSL_ENSURE( nItemId !=
HandleColumnId,
"BrowseBox::InsertDataColumn: nItemId is HandleColumnId" );
313 OSL_ENSURE( nItemId !=
BROWSER_INVALIDID,
"BrowseBox::InsertDataColumn: nItemId is reserved value BROWSER_INVALIDID" );
315#if OSL_DEBUG_LEVEL > 0
318 OSL_ENSURE(
col->GetId() != nItemId,
"BrowseBox::InsertDataColumn: duplicate column Id" );
336 sal_uInt16 nHeaderPos =
nPos;
340 nItemId, rText, nWidth, nBits, nHeaderPos );
354 nSelectedColId =
mvCols[nSelected]->GetId();
357 return nSelectedColId;
366 SAL_INFO(
"svtools",
"BrowseBox::SetToggledSelectedColumn " <<
this );
375 if ( nItemPos >=
mvCols.size() )
391 std::unique_ptr<BrowserColumn> pColumn = std::move(
mvCols[ nItemPos ]);
393 nItemPos = nFirstScrollable;
394 mvCols.insert(
mvCols.begin() + nItemPos, std::move(pColumn) );
402 mvCols[ nItemPos ]->Freeze();
424 if ( nOldPos >=
mvCols.size() )
443 sal_uInt16 nNextPos = nOldPos + 1;
444 if ( nOldPos >
nPos )
445 nNextPos = nOldPos - 1;
452 std::unique_ptr<BrowserColumn> pTemp = std::move(
mvCols[nOldPos]);
462 if(
pDataWin->GetBackground().IsScrollable() )
466 if ( nOldPos >
nPos )
469 if ( aToRect.
Left() < nFrozenWidth )
470 aToRect.
SetLeft( nFrozenWidth );
479 pDataWin->Scroll( nScroll, 0, aScrollArea );
485 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
490 sal_uInt16 nNewPos =
nPos;
493 pDataWin->pHeaderBar->MoveItem(nColumnId,nNewPos);
503 Any( AccessibleTableModelChange(
516 Any( AccessibleTableModelChange(
539 if ( nItemPos >=
mvCols.size() )
545 if ( pCol->
Title() == rTitle )
548 OUString sOld(pCol->
Title());
550 pCol->
Title() = rTitle;
554 pDataWin->pHeaderBar->SetItemText( nItemId, rTitle );
578 if ( nItemPos >=
mvCols.size() )
591 nMaxWidth -=
pDataWin->bAutoSizeLastCol
596 nWidth = nMaxWidth > 16 ? nMaxWidth : nOldWidth;
603 if(
static_cast<sal_uLong>(nOldWidth) == nWidth )
627 for (
size_t nCol = 0; nCol < nItemPos; ++nCol )
635 pDataWin->GetOutDev()->SetClipRegion();
654 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
669 nItemId ? nItemId : USHRT_MAX - 1, nWidth );
672 if ( nItemPos !=
mvCols.size() - 1 )
710 OSL_ENSURE(
nFirstCol > 0,
"FirstCol must be greater zero!");
718 pDataWin->pHeaderBar->RemoveItem( nItemId );
725 pDataWin->pHeaderBar->SetPosSizePixel(
749 Any( AccessibleTableModelChange(COLUMNS_REMOVED,
770 size_t nOldCount =
mvCols.size();
802 if (
mvCols.size() == nOldCount )
810 Any(
m_pImpl->getAccessibleHeaderBar(AccessibleBrowseBoxObjType::ColumnHeaderBar))
816 Any(
m_pImpl->getAccessibleHeaderBar(AccessibleBrowseBoxObjType::ColumnHeaderBar)),
823 Any ( AccessibleTableModelChange( COLUMNS_REMOVED,
839 if ( nItemPos >=
mvCols.size() )
841 return mvCols[ nItemPos ]->Title();
851 return static_cast<sal_uInt16
>(
mvCols.size());
887 bool bScrollable =
pDataWin->GetBackground().IsScrollable();
888 bool bInvalidateView =
false;
899 bInvalidateView =
true;
919 aInvalidateRect.
SetLeft( nFrozenWidth );
920 aInvalidateRect.
SetRight( nFrozenWidth + nDelta - 1 );
931 aScrollRect.
SetLeft( nFrozenWidth );
932 aScrollRect.
SetRight( nFrozenWidth + nDelta - 1 );
933 pDataWin->Invalidate( aScrollRect );
938 else if ( nCols == -1 )
945 bInvalidateView =
true;
988 for (
size_t nCol = 0;
997 pDataWin->pHeaderBar->SetOffset( nWidth );
1000 if( bInvalidateView )
1003 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
1022 sal_Int32 nTmpMin = std::min(
static_cast<sal_Int32
>(
nTopRow + nRows),
static_cast<sal_Int32
>(
nRowCount - 1) );
1024 sal_Int32 nNewTopRow = std::max<sal_Int32>( nTmpMin, 0 );
1029 sal_uInt16 nVisibleRows =
1037 nNewTopRow = std::max<tools::Long>( nTmpMin, 0 );
1043 sal_Int32 nOldTopRow =
nTopRow;
1051 if(
pDataWin->GetBackground().IsScrollable() &&
1052 std::abs( nDeltaY ) > 0 &&
1053 std::abs( nDeltaY ) <
pDataWin->GetSizePixel().Height() )
1130 Any(
m_pImpl->getAccessibleHeaderBar( AccessibleBrowseBoxObjType::RowHeaderBar ) )
1136 Any(
m_pImpl->getAccessibleHeaderBar( AccessibleBrowseBoxObjType::RowHeaderBar ) ),
1143 Any( AccessibleTableModelChange(ROWS_REMOVED,
1161 if ( nNumRows <= 0 )
1171 sal_Int32 nOldCurRow =
nCurRow;
1173 if ( bDoPaint && nRow >=
nTopRow &&
1180 pDataWin->GetOutDev()->SetClipRegion();
1181 if(
pDataWin->GetBackground().IsScrollable() )
1189 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
1203 uRow.pSel->Insert( nRow, nNumRows );
1205 uRow.nSel += nNumRows;
1209 GoToRow( 0,
false, bKeepSelection );
1229 Any( AccessibleTableModelChange(
1260void BrowseBox::RowRemoved( sal_Int32 nRow, sal_Int32 nNumRows, bool bDoPaint )
1265 else if ( nRow >= nRowCount )
1266 nRow = nRowCount - 1;
1268 if ( nNumRows <= 0 )
1271 if ( nRowCount <= 0 )
1276 // hide cursor and selection
1277 SAL_INFO("svtools", "BrowseBox::HideCursor
" << this );
1282 // adjust total row count
1283 nRowCount -= nNumRows;
1284 if (nRowCount < 0) nRowCount = 0;
1285 sal_Int32 nOldCurRow = nCurRow;
1287 // adjust the selection
1288 if ( bMultiSelection )
1289 // uRow.pSel->Remove( nRow, nNumRows );
1290 for ( tools::Long i = 0; i < nNumRows; i++ )
1291 uRow.pSel->Remove( nRow );
1292 else if ( nRow < uRow.nSel && uRow.nSel >= nNumRows )
1293 uRow.nSel -= nNumRows;
1294 else if ( nRow <= uRow.nSel )
1295 uRow.nSel = BROWSER_ENDOFSELECTION;
1297 // adjust the cursor
1298 if ( nRowCount == 0 ) // don't compare nRowCount with nNumRows as nNumRows already was subtracted from nRowCount
1299 nCurRow = BROWSER_ENDOFSELECTION;
1300 else if ( nRow < nCurRow )
1302 nCurRow -= std::min( nCurRow - nRow, nNumRows );
1303 // with the above nCurRow points a) to the first row after the removed block or b) to the same line
1304 // as before, but moved up nNumRows
1305 // case a) needs an additional correction if the last n lines were deleted, as 'the first row after the
1306 // removed block' is an invalid position then
1307 // FS - 09/28/99 - 68429
1308 if (nCurRow == nRowCount)
1311 else if( nRow == nCurRow && nCurRow == nRowCount )
1312 nCurRow = nRowCount-1;
1314 // is the deleted row visible?
1315 Size aSz = pDataWin->GetOutputSizePixel();
1316 if ( nRow >= nTopRow &&
1317 nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1321 // scroll up the rows behind the deleted row
1322 // if there are Rows behind
1323 if (nRow < nRowCount)
1325 tools::Long nY = (nRow-nTopRow) * GetDataRowHeight();
1326 pDataWin->GetOutDev()->SetClipRegion();
1327 if( pDataWin->GetBackground().IsScrollable() )
1329 pDataWin->Scroll( 0, - static_cast<short>(GetDataRowHeight()) * nNumRows,
1330 tools::Rectangle( Point( 0, nY ), Size( aSz.Width(),
1331 aSz.Height() - nY + nNumRows*GetDataRowHeight() ) ),
1335 pDataWin->Window::Invalidate( InvalidateFlags::NoChildren );
1339 // Repaint the Rect of the deleted row
1340 tools::Rectangle aRect(
1341 Point( 0, (nRow-nTopRow)*GetDataRowHeight() ),
1342 Size( pDataWin->GetSizePixel().Width(),
1343 nNumRows * GetDataRowHeight() ) );
1344 pDataWin->Invalidate( aRect );
1348 // is the deleted row above of the visible area?
1349 else if ( nRow < nTopRow )
1350 nTopRow = nTopRow >= nNumRows ? nTopRow-nNumRows : 0;
1354 // reshow cursor and selection
1356 SAL_INFO("svtools", "BrowseBox::ShowCursor
" << this );
1359 // adjust the vertical scrollbar
1361 AutoSizeLastColumn();
1364 if ( isAccessibleAlive() )
1366 if ( nRowCount == 0 )
1368 // all columns should be removed, so we remove the column header bar and append it again
1369 // to avoid to notify every column remove
1370 commitBrowseBoxEvent(
1373 Any( m_pImpl->getAccessibleHeaderBar( AccessibleBrowseBoxObjType::RowHeaderBar ) )
1376 // and now append it again
1377 commitBrowseBoxEvent(
1379 Any(m_pImpl->getAccessibleHeaderBar(AccessibleBrowseBoxObjType::RowHeaderBar)),
1382 commitBrowseBoxEvent(
1385 Any( m_pImpl->getAccessibleTable() )
1388 // and now append it again
1389 commitBrowseBoxEvent(
1391 Any( m_pImpl->getAccessibleTable() ),
1398 TABLE_MODEL_CHANGED,
1399 Any( AccessibleTableModelChange(
1410 for (tools::Long i = nRow+1 ; i <= (nRow+nNumRows) ; ++i)
1412 commitHeaderBarEvent(
1415 Any( CreateAccessibleRowHeader( i ) ),
1422 if ( nOldCurRow != nCurRow )
1431bool BrowseBox::GoToRow( sal_Int32 nRow)
1433 return GoToRow(nRow, false);
1437bool BrowseBox::GoToRow( sal_Int32 nRow, bool bRowColMove, bool bKeepSelection )
1439 sal_Int32 nOldCurRow = nCurRow;
1442 if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) )
1446 if ( nRow < 0 || nRow >= nRowCount )
1450 if ( !bRowColMove && !IsCursorMoveAllowed( nRow, nCurColId ) )
1453 // compute the last visible row
1454 Size aSz( pDataWin->GetSizePixel() );
1455 sal_uInt16 nVisibleRows = sal_uInt16( aSz.Height() / GetDataRowHeight() - 1 );
1456 sal_Int32 nLastRow = nTopRow + nVisibleRows;
1459 pDataWin->EnterUpdateLock();
1461 // remove old highlight, if necessary
1462 if ( !bMultiSelection && !bKeepSelection )
1467 bool bWasVisible = bSelectionIsVisible;
1468 if (! bMultiSelection)
1470 if( !bKeepSelection )
1471 bSelectionIsVisible = false;
1473 if ( nRow < nTopRow )
1474 ScrollRows( nRow - nTopRow );
1475 else if ( nRow > nLastRow )
1476 ScrollRows( nRow - nLastRow );
1477 bSelectionIsVisible = bWasVisible;
1479 // adjust cursor (selection) and thumb
1480 if ( GetUpdateMode() )
1481 pVScroll->SetThumbPos( nTopRow );
1483 // relative positioning (because nCurRow might have changed in the meantime)!
1484 if (nCurRow != BROWSER_ENDOFSELECTION )
1485 nCurRow = nCurRow + (nRow - nOldCurRow);
1487 // make sure that the current position is valid
1488 if (nCurRow == BROWSER_ENDOFSELECTION && nRowCount > 0)
1490 else if ( nCurRow >= nRowCount )
1491 nCurRow = nRowCount - 1;
1492 aSelRange = Range( nCurRow, nCurRow );
1494 // display new highlight if necessary
1495 if ( !bMultiSelection && !bKeepSelection )
1499 pDataWin->LeaveUpdateLock();
1502 if ( !bMultiSelection && !bKeepSelection)
1505 if ( !bRowColMove && nOldCurRow != nCurRow )
1508 if ( !bMultiSelection && !bKeepSelection )
1519bool BrowseBox::GoToColumnId( sal_uInt16 nColId)
1521 return GoToColumnId(nColId, true);
1525bool BrowseBox::GoToColumnId( sal_uInt16 nColId, bool bMakeVisible, bool bRowColMove)
1531 if (!bRowColMove && !IsCursorMoveAllowed( nCurRow, nColId ) )
1534 if ( nColId != nCurColId || (bMakeVisible && !IsFieldVisible(nCurRow, nColId, true)))
1536 sal_uInt16 nNewPos = GetColumnPos(nColId);
1537 BrowserColumn* pColumn = (nNewPos < mvCols.size()) ? mvCols[ nNewPos ].get() : nullptr;
1538 DBG_ASSERT( pColumn, "no column
object - invalid
id?
" );
1545 bool bScrolled = false;
1547 sal_uInt16 nFirstPos = nFirstCol;
1548 sal_uInt16 nWidth = static_cast<sal_uInt16>(pColumn->Width());
1549 sal_uInt16 nLastPos = GetColumnAtXPosPixel(
1550 pDataWin->GetSizePixel().Width()-nWidth );
1551 sal_uInt16 nFrozen = FrozenColCount();
1552 if ( bMakeVisible && nLastPos &&
1553 nNewPos >= nFrozen && ( nNewPos < nFirstPos || nNewPos > nLastPos ) )
1555 if ( nNewPos < nFirstPos )
1556 ScrollColumns( nNewPos-nFirstPos );
1557 else if ( nNewPos > nLastPos )
1558 ScrollColumns( nNewPos-nLastPos );
1565 //try to move to nCurRow, nColId
1566 CursorMoveAttempt aAttempt(nCurRow, nColId, bScrolled);
1567 //Detect if we are already in a call to BrowseBox::GoToColumnId
1568 //but the attempt is impossible and we are simply recursing
1569 //into BrowseBox::GoToColumnId with the same impossible to
1570 //fulfill conditions
1571 if (m_aGotoStack.empty() || aAttempt != m_aGotoStack.top())
1573 m_aGotoStack.push(aAttempt);
1584bool BrowseBox::GoToRowColumnId( sal_Int32 nRow, sal_uInt16 nColId )
1588 if ( nRow < 0 || nRow >= nRowCount )
1595 if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) &&
1596 nColId == nCurColId && IsFieldVisible(nCurRow, nColId, true))
1600 if (!IsCursorMoveAllowed(nRow, nColId))
1604 bool bMoved = GoToRow(nRow, true) && GoToColumnId(nColId, true, true);
1614void BrowseBox::SetNoSelection()
1617 // is there no selection
1618 if ( ( !pColSel || !pColSel->GetSelectCount() ) &&
1619 ( ( !bMultiSelection && uRow.nSel == BROWSER_ENDOFSELECTION ) ||
1620 ( bMultiSelection && !uRow.pSel->GetSelectCount() ) ) )
1624 SAL_INFO("svtools", "BrowseBox::HideCursor
" << this );
1628 if ( bMultiSelection )
1629 uRow.pSel->SelectAll(false);
1631 uRow.nSel = BROWSER_ENDOFSELECTION;
1633 pColSel->SelectAll(false);
1640 SAL_INFO("svtools", "BrowseBox::ShowCursor
" << this );
1642 if ( isAccessibleAlive() )
1653void BrowseBox::SelectAll()
1656 if ( !bMultiSelection )
1659 SAL_INFO("svtools", "BrowseBox::HideCursor
" << this );
1664 pColSel->SelectAll(false);
1665 uRow.pSel->SelectAll();
1667 // don't highlight handle column
1668 BrowserColumn *pFirstCol = mvCols[ 0 ].get();
1669 tools::Long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1671 // highlight the row selection
1674 tools::Rectangle aHighlightRect;
1675 sal_uInt16 nVisibleRows =
1676 static_cast<sal_uInt16>(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1677 for ( sal_Int32 nRow = std::max<sal_Int32>( nTopRow, uRow.pSel->FirstSelected() );
1678 nRow != BROWSER_ENDOFSELECTION && nRow < nTopRow + nVisibleRows;
1679 nRow = uRow.pSel->NextSelected() )
1680 aHighlightRect.Union( tools::Rectangle(
1681 Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1682 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) ) );
1683 pDataWin->Invalidate( aHighlightRect );
1692 SAL_INFO("svtools", "BrowseBox::ShowCursor
" << this );
1694 if ( !isAccessibleAlive() )
1702 commitHeaderBarEvent(
1707 ); // column header event
1709 commitHeaderBarEvent(
1714 ); // row header event
1718void BrowseBox::SelectRow( sal_Int32 nRow, bool _bSelect, bool bExpand )
1721 if ( !bMultiSelection )
1723 // deselecting is impossible, selecting via cursor
1725 GoToRow(nRow, false);
1729 SAL_INFO("svtools", "BrowseBox::HideCursor
" << this );
1731 // remove old selection?
1732 if ( !bExpand || !bMultiSelection )
1735 if ( bMultiSelection )
1736 uRow.pSel->SelectAll(false);
1738 uRow.nSel = BROWSER_ENDOFSELECTION;
1740 pColSel->SelectAll(false);
1743 // set new selection
1745 && ( ( bMultiSelection
1746 && uRow.pSel->GetTotalRange().Max() >= nRow
1747 && uRow.pSel->Select( nRow, _bSelect )
1749 || ( !bMultiSelection
1750 && ( uRow.nSel = nRow ) != BROWSER_ENDOFSELECTION )
1754 // don't highlight handle column
1755 BrowserColumn *pFirstCol = mvCols[ 0 ].get();
1756 tools::Long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1758 // highlight only newly selected part
1759 tools::Rectangle aRect(
1760 Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1761 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1762 pDataWin->Invalidate( aRect );
1771 SAL_INFO("svtools", "BrowseBox::ShowCursor
" << this );
1773 if ( !isAccessibleAlive() )
1781 commitHeaderBarEvent(
1786 ); // row header event
1790sal_Int32 BrowseBox::GetSelectRowCount() const
1793 return bMultiSelection ? uRow.pSel->GetSelectCount() :
1794 uRow.nSel == BROWSER_ENDOFSELECTION ? 0 : 1;
1798void BrowseBox::SelectColumnPos( sal_uInt16 nNewColPos, bool _bSelect, bool bMakeVisible )
1801 if ( !bColumnCursor || nNewColPos == BROWSER_INVALIDID )
1804 if ( !bMultiSelection )
1807 GoToColumnId( mvCols[ nNewColPos ]->GetId(), bMakeVisible );
1812 if ( !GoToColumnId( mvCols[ nNewColPos ]->GetId(), bMakeVisible ) )
1816 SAL_INFO("svtools", "BrowseBox::HideCursor
" << this );
1818 if ( bMultiSelection )
1819 uRow.pSel->SelectAll(false);
1821 uRow.nSel = BROWSER_ENDOFSELECTION;
1822 pColSel->SelectAll(false);
1824 if ( pColSel->Select( nNewColPos, _bSelect ) )
1826 // GoToColumnId( mvCols->GetObject(nNewColPos)->GetId(), bMakeVisible );
1828 // only highlight painted areas
1830 tools::Rectangle aFieldRectPix( GetFieldRectPixel( nCurRow, nCurColId, false ) );
1831 tools::Rectangle aRect(
1832 Point( aFieldRectPix.Left() - MIN_COLUMNWIDTH, 0 ),
1833 Size( mvCols[ nNewColPos ]->Width(),
1834 pDataWin->GetOutputSizePixel().Height() ) );
1835 pDataWin->Invalidate( aRect );
1841 if ( isAccessibleAlive() )
1848 commitHeaderBarEvent(
1853 ); // column header event
1858 SAL_INFO("svtools", "BrowseBox::ShowCursor
" << this );
1862sal_uInt16 BrowseBox::GetSelectColumnCount() const
1865 // while bAutoSelect (==!pColSel), 1 if any rows (yes rows!) else none
1866 return pColSel ? static_cast<sal_uInt16>(pColSel->GetSelectCount()) :
1867 nCurRow >= 0 ? 1 : 0;
1871sal_Int32 BrowseBox::FirstSelectedColumn( ) const
1873 return pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION;
1877sal_Int32 BrowseBox::FirstSelectedRow()
1880 return bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
1884sal_Int32 BrowseBox::NextSelectedRow()
1887 return bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION;
1891sal_Int32 BrowseBox::LastSelectedRow()
1894 return bMultiSelection ? uRow.pSel->LastSelected() : uRow.nSel;
1898bool BrowseBox::IsRowSelected( sal_Int32 nRow ) const
1901 return bMultiSelection ? uRow.pSel->IsSelected(nRow) : nRow == uRow.nSel;
1905bool BrowseBox::IsColumnSelected( sal_uInt16 nColumnId ) const
1908 return pColSel ? pColSel->IsSelected( GetColumnPos(nColumnId) ) :
1909 nCurColId == nColumnId;
1913void BrowseBox::MakeFieldVisible
1915 sal_Int32 nRow, // line number of the field (starting with 0)
1916 sal_uInt16 nColId // column ID of the field
1921 Makes visible the field described in 'nRow' and 'nColId' by scrolling
1930 Size aTestSize = pDataWin->GetSizePixel();
1932 if ( !bBootstrapped || aTestSize.IsEmpty() )
1935 // is it visible already?
1936 bool bVisible = IsFieldVisible( nRow, nColId, true/*bComplete*/ );
1940 // calculate column position, field rectangle and painting area
1941 sal_uInt16 nColPos = GetColumnPos( nColId );
1942 tools::Rectangle aFieldRect = GetFieldRectPixel( nRow, nColId, false );
1943 tools::Rectangle aDataRect( Point(0, 0), pDataWin->GetSizePixel() );
1945 // positioned outside on the left?
1946 if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
1947 // => scroll to the right
1948 ScrollColumns( nColPos - nFirstCol );
1950 // while outside on the right
1951 while ( aDataRect.Right() < aFieldRect.Right() )
1953 // => scroll to the left
1954 if ( ScrollColumns( 1 ) != 1 )
1955 // no more need to scroll
1957 aFieldRect = GetFieldRectPixel( nRow, nColId, false );
1960 // positioned outside above?
1961 if ( nRow < nTopRow )
1962 // scroll further to the bottom
1963 ScrollRows( nRow - nTopRow );
1965 // positioned outside below?
1966 sal_Int32 nBottomRow = nTopRow + GetVisibleRows();
1967 // decrement nBottomRow to make it the number of the last visible line
1968 // (count starts with 0!).
1969 // Example: BrowseBox contains exactly one entry. nBottomRow := 0 + 1 - 1
1973 if ( nRow > nBottomRow )
1974 // scroll further to the top
1975 ScrollRows( nRow - nBottomRow );
1979bool BrowseBox::IsFieldVisible( sal_Int32 nRow, sal_uInt16 nColumnId,
1980 bool bCompletely ) const
1983 // hidden by frozen column?
1984 sal_uInt16 nColPos = GetColumnPos( nColumnId );
1985 if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
1988 tools::Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
1989 if ( aRect.IsEmpty() )
1992 // get the visible area
1993 tools::Rectangle aOutRect( Point(0, 0), pDataWin->GetOutputSizePixel() );
1996 // test if the field is completely visible
1997 return aOutRect.Contains( aRect );
1999 // test if the field is partly of completely visible
2000 return !aOutRect.Intersection( aRect ).IsEmpty();
2004tools::Rectangle BrowseBox::GetFieldRectPixel( sal_Int32 nRow, sal_uInt16 nColumnId,
2005 bool bRelToBrowser) const
2008 // get the rectangle relative to DataWin
2009 tools::Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
2010 if ( aRect.IsEmpty() )
2013 // adjust relative to BrowseBox's output area
2014 Point aTopLeft( aRect.TopLeft() );
2015 if ( bRelToBrowser )
2017 aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2018 aTopLeft = ScreenToOutputPixel( aTopLeft );
2021 return tools::Rectangle( aTopLeft, aRect.GetSize() );
2025tools::Rectangle BrowseBox::GetRowRectPixel( sal_Int32 nRow ) const
2028 // get the rectangle relative to DataWin
2029 tools::Rectangle aRect;
2030 if ( nTopRow > nRow )
2031 // row is above visible area
2033 aRect = tools::Rectangle(
2034 Point( 0, GetDataRowHeight() * (nRow-nTopRow) ),
2035 Size( pDataWin->GetOutputSizePixel().Width(), GetDataRowHeight() ) );
2036 if ( aRect.Top() > pDataWin->GetOutputSizePixel().Height() )
2037 // row is below visible area
2040 // adjust relative to BrowseBox's output area
2041 Point aTopLeft( aRect.TopLeft() );
2042 aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2043 aTopLeft = ScreenToOutputPixel( aTopLeft );
2045 return tools::Rectangle( aTopLeft, aRect.GetSize() );
2049tools::Rectangle BrowseBox::ImplFieldRectPixel( sal_Int32 nRow, sal_uInt16 nColumnId ) const
2052 // compute the X-coordinate relative to DataWin by accumulation
2053 tools::Long nColX = 0;
2054 sal_uInt16 nFrozenCols = FrozenColCount();
2057 nCol < mvCols.size() && mvCols[ nCol ]->GetId() != nColumnId;
2059 if ( mvCols[ nCol ]->IsFrozen() || nCol >= nFirstCol )
2060 nColX += mvCols[ nCol ]->Width();
2062 if ( nCol >= mvCols.size() || ( nCol >= nFrozenCols && nCol < nFirstCol ) )
2063 return tools::Rectangle();
2065 // compute the Y-coordinate relative to DataWin
2066 tools::Long nRowY = GetDataRowHeight();
2067 if ( nRow != BROWSER_ENDOFSELECTION ) // #105497# OJ
2068 nRowY = ( nRow - nTopRow ) * GetDataRowHeight();
2070 // assemble the Rectangle relative to DataWin
2071 return tools::Rectangle(
2072 Point( nColX + MIN_COLUMNWIDTH, nRowY ),
2073 Size( (mvCols[nCol]->Width() == LONG_MAX
2074 ? LONG_MAX - (nColX + MIN_COLUMNWIDTH) : mvCols[ nCol ]->Width() - 2*MIN_COLUMNWIDTH),
2075 GetDataRowHeight() - 1 ) );
2079sal_Int32 BrowseBox::GetRowAtYPosPixel( tools::Long nY, bool bRelToBrowser ) const
2082 // compute the Y-coordinate
2083 if ( bRelToBrowser )
2085 Point aDataTopLeft = pDataWin->OutputToScreenPixel( Point(0, 0) );
2086 Point aTopLeft = OutputToScreenPixel( Point(0, 0) );
2087 nY -= aDataTopLeft.Y() - aTopLeft.Y();
2090 // no row there (e.g. in the header)
2091 if ( nY < 0 || nY >= pDataWin->GetOutputSizePixel().Height() )
2094 return nY / GetDataRowHeight() + nTopRow;
2098tools::Rectangle BrowseBox::GetFieldRect( sal_uInt16 nColumnId ) const
2101 return GetFieldRectPixel( nCurRow, nColumnId );
2105sal_uInt16 BrowseBox::GetColumnAtXPosPixel( tools::Long nX ) const
2108 // accumulate the widths of the visible columns
2109 tools::Long nColX = 0;
2110 for ( size_t nCol = 0; nCol < mvCols.size(); ++nCol )
2112 BrowserColumn *pCol = mvCols[ nCol ].get();
2113 if ( pCol->IsFrozen() || nCol >= nFirstCol )
2114 nColX += pCol->Width();
2120 return BROWSER_INVALIDID;
2123bool BrowseBox::ReserveControlArea(sal_uInt16 nWidth)
2125 if (nWidth != nControlAreaWidth)
2127 OSL_ENSURE(nWidth,"Control area of 0 is not allowed, Use USHRT_MAX instead!
");
2128 nControlAreaWidth = nWidth;
2135tools::Rectangle BrowseBox::GetControlArea() const
2137 auto nHeight = aHScroll->GetSizePixel().Height();
2138 auto nEndRight = aHScroll->GetPosPixel().X();
2140 return tools::Rectangle(
2141 Point( 0, GetOutputSizePixel().Height() - nHeight ),
2142 Size( nEndRight, nHeight ) );
2145void BrowseBox::SetMode( BrowserMode nMode )
2148 pDataWin->bAutoHScroll = BrowserMode::AUTO_HSCROLL == ( nMode & BrowserMode::AUTO_HSCROLL );
2149 pDataWin->bAutoVScroll = BrowserMode::AUTO_VSCROLL == ( nMode & BrowserMode::AUTO_VSCROLL );
2150 pDataWin->bNoHScroll = BrowserMode::NO_HSCROLL == ( nMode & BrowserMode::NO_HSCROLL );
2151 pDataWin->bNoVScroll = BrowserMode::NO_VSCROLL == ( nMode & BrowserMode::NO_VSCROLL );
2153 DBG_ASSERT( !( pDataWin->bAutoHScroll && pDataWin->bNoHScroll ),
2155 DBG_ASSERT( !( pDataWin->bAutoVScroll && pDataWin->bNoVScroll ),
2157 if ( pDataWin->bAutoHScroll )
2158 pDataWin->bNoHScroll = false;
2159 if ( pDataWin->bAutoVScroll )
2160 pDataWin->bNoVScroll = false;
2162 if ( pDataWin->bNoHScroll )
2165 nControlAreaWidth = USHRT_MAX;
2167 tools::Long nOldRowSel = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
2168 MultiSelection *pOldRowSel = bMultiSelection ? uRow.pSel : nullptr;
2170 pVScroll.disposeAndClear();
2172 bMultiSelection = bool( nMode & BrowserMode::MULTISELECTION );
2173 bColumnCursor = bool( nMode & BrowserMode::COLUMNSELECTION );
2174 bKeepHighlight = bool( nMode & BrowserMode::KEEPHIGHLIGHT );
2176 bHideSelect = ((nMode & BrowserMode::HIDESELECT) == BrowserMode::HIDESELECT);
2177 // default: do not hide the cursor at all (untaken scrolling and such)
2178 bHideCursor = TRISTATE_FALSE;
2180 if ( BrowserMode::HIDECURSOR == ( nMode & BrowserMode::HIDECURSOR ) )
2182 bHideCursor = TRISTATE_TRUE;
2185 m_bFocusOnlyCursor = ((nMode & BrowserMode::CURSOR_WO_FOCUS) == BrowserMode::NONE);
2187 bHLines = ( nMode & BrowserMode::HLINES ) == BrowserMode::HLINES;
2188 bVLines = ( nMode & BrowserMode::VLINES ) == BrowserMode::VLINES;
2190 pVScroll = VclPtr<ScrollAdaptor>::Create(this, false);
2191 pVScroll->SetLineSize( 1 );
2192 pVScroll->SetPageSize(1);
2193 pVScroll->SetScrollHdl( LINK( this, BrowseBox, VertScrollHdl ) );
2195 pDataWin->bAutoSizeLastCol =
2196 BrowserMode::AUTOSIZE_LASTCOL == ( nMode & BrowserMode::AUTOSIZE_LASTCOL );
2198 // create a headerbar. what happens, if a headerbar has to be created and
2199 // there already are columns?
2200 if ( BrowserMode::HEADERBAR_NEW == ( nMode & BrowserMode::HEADERBAR_NEW ) )
2202 if (!pDataWin->pHeaderBar)
2203 pDataWin->pHeaderBar = CreateHeaderBar( this );
2207 pDataWin->pHeaderBar.disposeAndClear();
2210 if ( bColumnCursor )
2213 pColSel.reset(new MultiSelection);
2214 pColSel->SetTotalRange( Range( 0, mvCols.size()-1 ) );
2221 if ( bMultiSelection )
2224 uRow.pSel = pOldRowSel;
2226 uRow.pSel = new MultiSelection;
2230 uRow.nSel = nOldRowSel;
2234 if ( bBootstrapped )
2236 StateChanged( StateChangedType::InitShow );
2237 if ( bMultiSelection && !pOldRowSel &&
2238 nOldRowSel != BROWSER_ENDOFSELECTION )
2239 uRow.pSel->Select( nOldRowSel );
2243 pDataWin->Invalidate();
2245 // no cursor on handle column
2246 if ( nCurColId == HandleColumnId )
2247 nCurColId = GetColumnId( 1 );
2249 m_nCurrentMode = nMode;
2253void BrowseBox::VisibleRowsChanged( sal_Int32, sal_uInt16 )
2256 // old behavior: automatically correct NumRows:
2257 if ( nRowCount < GetRowCount() )
2259 RowInserted(nRowCount,GetRowCount() - nRowCount, false);
2261 else if ( nRowCount > GetRowCount() )
2263 RowRemoved(nRowCount-(nRowCount - GetRowCount()),nRowCount - GetRowCount(), false);
2268bool BrowseBox::IsCursorMoveAllowed( sal_Int32, sal_uInt16 ) const
2272 This virtual method is always called before the cursor is moved directly.
2273 By means of 'return false', we avoid doing this if e.g. a record
2274 contradicts any rules.
2276 This method is not called, if the cursor movement results from removing or
2277 deleting a row/column (thus, in cases where only a "cursor correction
" happens).
2279 The base implementation currently always returns true.
2287tools::Long BrowseBox::GetDataRowHeight() const
2289 return CalcZoom(m_nDataRowHeight ? m_nDataRowHeight : ImpGetDataRowHeight());
2293VclPtr<BrowserHeader> BrowseBox::CreateHeaderBar( BrowseBox* pParent )
2295 VclPtr<BrowserHeader> pNewBar = VclPtr<BrowserHeader>::Create( pParent );
2296 pNewBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2300void BrowseBox::SetHeaderBar( BrowserHeader* pHeaderBar )
2302 pDataWin->pHeaderBar.disposeAndClear();
2303 pDataWin->pHeaderBar = pHeaderBar;
2304 pDataWin->pHeaderBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2307tools::Long BrowseBox::GetTitleHeight() const
2309 tools::Long nHeight;
2310 // ask the header bar for the text height (if possible), as the header bar's font is adjusted with
2311 // our (and the header's) zoom factor
2312 HeaderBar* pHeaderBar = pDataWin->pHeaderBar;
2314 nHeight = pHeaderBar->GetTextHeight();
2316 nHeight = GetTextHeight();
2318 return nTitleLines ? nTitleLines * nHeight + 4 : 0;
2321tools::Long BrowseBox::CalcReverseZoom(tools::Long nVal) const
2325 const Fraction& rZoom = GetZoom();
2326 double n = static_cast<double>(nVal);
2327 n *= static_cast<double>(rZoom.GetDenominator());
2328 if (!rZoom.GetNumerator())
2329 throw o3tl::divide_by_zero();
2330 n /= static_cast<double>(rZoom.GetNumerator());
2331 nVal = n>0 ? static_cast<tools::Long>(n + 0.5) : -static_cast<tools::Long>(-n + 0.5);
2337void BrowseBox::CursorMoved()
2339 // before implementing more here, please adjust the EditBrowseBox
2341 if ( isAccessibleAlive() && HasFocus() )
2343 ACTIVE_DESCENDANT_CHANGED,
2344 Any( CreateAccessibleCell( GetCurRow(),GetColumnPos( GetCurColumnId() ) ) ),
2349void BrowseBox::LoseFocus()
2355 SAL_INFO("svtools", "BrowseBox::HideCursor
" << this );
2358 if ( !bKeepHighlight )
2361 bSelectionIsVisible = false;
2366 Control::LoseFocus();
2370void BrowseBox::GetFocus()
2376 if ( !bSelectionIsVisible )
2378 bSelectionIsVisible = true;
2379 if ( bBootstrapped )
2386 Control::GetFocus();
2390sal_uInt16 BrowseBox::GetVisibleRows() const
2392 return static_cast<sal_uInt16>((pDataWin->GetOutputSizePixel().Height() - 1 )/ GetDataRowHeight() + 1);
2395BrowserDataWin& BrowseBox::GetDataWindow() const
2400/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr sal_Int32 BROWSER_ENDOFSELECTION
#define BROWSER_INVALIDID
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
void SetToggledSelectedColumn(sal_uInt16 _nSelectedColumnId)
SVT_DLLPRIVATE void AutoSizeLastColumn()
tools::Long GetDataRowHeight() const
sal_uInt16 GetColumnId(sal_uInt16 nPos) const
virtual void GetFocus() override
virtual void dispose() override
SVT_DLLPRIVATE sal_uInt16 FrozenColCount() const
void SetRealRowCount(const OUString &rRealRowCount)
virtual void CursorMoved()
VclPtr< BrowserDataWin > pDataWin
bool bSelectionIsVisible
select or deselect
void InsertDataColumn(sal_uInt16 nItemId, const OUString &rText, tools::Long nSize, HeaderBarItemBits nBits=HeaderBarItemBits::STDSTYLE, sal_uInt16 nPos=HEADERBAR_APPEND)
tools::Long GetTitleHeight() const
SVT_DLLPRIVATE void ColumnInserted(sal_uInt16 nPos)
VclPtr< ScrollAdaptor > pVScroll
virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleColumnHeader(sal_uInt16 nColumnPos) override
Creates the accessible object of a column header.
tools::Long m_nDataRowHeight
void SetColumnPos(sal_uInt16 nColumnId, sal_uInt16 nPos)
sal_uLong nControlAreaWidth
void FreezeColumn(sal_uInt16 nColumnId)
bool mbInteractiveRowHeight
BrowserMode m_nCurrentMode
BrowseBox(vcl::Window *pParent, WinBits nBits, BrowserMode nMode=BrowserMode::NONE)
tools::Long CalcReverseZoom(tools::Long nVal) const
sal_uInt16 ColCount() const
void InsertHandleColumn(sal_uLong nWidth)
VclPtr< MeasureStatusBar > aStatusBarHeight
SVT_DLLPRIVATE tools::Long GetFrozenWidth() const
void SetColumnTitle(sal_uInt16 nColumnId, const OUString &rTitle)
void RowModified(sal_Int32 nRow, sal_uInt16 nColId=BROWSER_INVALIDID)
void commitTableEvent(sal_Int16 nEventId, const css::uno::Any &rNewValue, const css::uno::Any &rOldValue)
commitTableEvent commit the event at all listeners of the table
void SetFont(const vcl::Font &rNewFont)
bool PaintCursorIfHiddenOnce() const
void SetMode(BrowserMode nMode)
sal_Int32 ScrollColumns(sal_Int32 nColumns)
virtual void ColumnResized(sal_uInt16 nColId)
void SetColumnWidth(sal_uInt16 nColumnId, sal_uLong nWidth)
sal_uInt16 GetColumnPos(sal_uInt16 nColumnId) const
void RemoveColumn(sal_uInt16 nColumnId)
OUString GetColumnTitle(sal_uInt16 nColumnId) const
static const sal_uInt16 HandleColumnId
sal_Int32 ScrollRows(sal_Int32 nRows)
bool GetUpdateMode() const
sal_uLong GetDefaultColumnWidth(const OUString &_rText) const
suggests a default width for a column containing a given text
SVT_DLLPRIVATE tools::Long ImpGetDataRowHeight() const
tools::Rectangle GetFieldRectPixel(sal_Int32 nRow, sal_uInt16 nColId, bool bRelToBrowser=true) const
const vcl::Font & GetFont() const
bool GoToRow(sal_Int32 nRow, bool bRowColMove, bool bDoNotModifySelection=false)
virtual void Resize() override
void SetDataRowHeight(tools::Long nPixel)
void RowInserted(sal_Int32 nRow, sal_Int32 nNumRows=1, bool bDoPaint=true, bool bKeepSelection=false)
virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleRowHeader(sal_Int32 nRow) override
Creates the accessible object of a row header.
SVT_DLLPRIVATE void UpdateScrollbars()
virtual sal_Int32 GetRowCount() const override
SVT_DLLPRIVATE void ToggleSelection()
virtual ~BrowseBox() override
bool isAccessibleAlive() const
return <TRUE> if and only if the accessible object for this instance has been created and is alive
short GetCursorHideCount() const
virtual void VisibleRowsChanged(sal_Int32 nNewTopRow, sal_uInt16 nNumRows)
virtual void LoseFocus() override
void commitHeaderBarEvent(sal_Int16 nEventId, const css::uno::Any &rNewValue, const css::uno::Any &rOldValue, bool _bColumnHeaderBar)
fires an AccessibleEvent relative to a header bar AccessibleContext
virtual void SetNoSelection() override
SVT_DLLPRIVATE tools::Long GetBarHeight() const
tools::Rectangle GetFieldRect(sal_uInt16 nColumnId) const
::std::vector< std::unique_ptr< BrowserColumn > > mvCols
SVT_DLLPRIVATE void ConstructImpl(BrowserMode nMode)
void SetTitleLines(sal_uInt16 nLines)
sal_uInt16 ToggleSelectedColumn()
bool IsFrozen(sal_uInt16 nColumnId) const
::std::unique_ptr< ::svt::BrowseBoxImpl > m_pImpl
VclPtr< ScrollAdaptor > aHScroll
std::unique_ptr< MultiSelection > pColSel
void commitBrowseBoxEvent(sal_Int16 nEventId, const css::uno::Any &rNewValue, const css::uno::Any &rOldValue)
commitBrowseBoxEvent commit the event at all listeners of the browsebox
virtual void dispose() override
virtual void dispose() override
std::unique_ptr< weld::Builder > m_xBuilder
MeasureStatusBar(vcl::Window *pParent)
std::unique_ptr< weld::Entry > m_xAbsolute
std::unique_ptr< weld::Label > m_xRecordText
std::unique_ptr< weld::Label > m_xRecordCount
virtual void dispose() override
std::unique_ptr< weld::Label > m_xRecordOf
constexpr tools::Long Height() const
tools::Long AdjustHeight(tools::Long n)
constexpr tools::Long Width() const
sal_Int32 GetScrollBarSize() const
static VclPtr< reference_type > Create(Arg &&... arg)
::std::map< sal_Int32, css::uno::Reference< css::accessibility::XAccessible > > THeaderCellMap
const Wallpaper & GetBackground() const
bool HasChildPathFocus(bool bSystemWindow=false) const
virtual void SetSizePixel(const Size &rNewSize)
Size get_preferred_size() const
const Fraction & GetZoom() const
const AllSettings & GetSettings() const
virtual void Scroll(tools::Long nHorzScroll, tools::Long nVertScroll, ScrollFlags nFlags=ScrollFlags::NONE)
virtual Size GetSizePixel() const
Size GetOutputSizePixel() const
void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
bool IsScrollable() const
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
void InitSettings_Impl(vcl::Window *pWin)
#define DBG_ASSERT(sCon, aError)
virtual sal_uInt32 GetId() const override
#define LINK(Instance, Class, Member)
#define SAL_INFO(area, stream)
RttiCompleteObjectLocator col
#define SFX_ENDOFSELECTION
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
@ TABLE_COLUMN_DESCRIPTION_CHANGED