summaryrefslogtreecommitdiffstats
path: root/svtools/source/brwbox/datwin.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--svtools/source/brwbox/datwin.cxx691
1 files changed, 691 insertions, 0 deletions
diff --git a/svtools/source/brwbox/datwin.cxx b/svtools/source/brwbox/datwin.cxx
new file mode 100644
index 000000000..f22ddb19e
--- /dev/null
+++ b/svtools/source/brwbox/datwin.cxx
@@ -0,0 +1,691 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "datwin.hxx"
+#include <o3tl/numeric.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/help.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/scrbar.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <tools/debug.hxx>
+#include <tools/fract.hxx>
+
+
+void ButtonFrame::Draw( OutputDevice& rDev )
+{
+ Color aOldFillColor = rDev.GetFillColor();
+ Color aOldLineColor = rDev.GetLineColor();
+
+ const StyleSettings &rSettings = rDev.GetSettings().GetStyleSettings();
+ Color aColLight( rSettings.GetLightColor() );
+ Color aColShadow( rSettings.GetShadowColor() );
+ Color aColFace( rSettings.GetFaceColor() );
+
+ rDev.SetLineColor( aColFace );
+ rDev.SetFillColor( aColFace );
+ rDev.DrawRect( aRect );
+
+ if( rDev.GetOutDevType() != OUTDEV_WINDOW )
+ {
+ rDev.SetLineColor( aColLight );
+ rDev.DrawLine( aRect.TopLeft(), Point( aRect.Right(), aRect.Top() ) );
+ rDev.DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom() - 1 ) );
+ rDev.SetLineColor( aColShadow );
+ rDev.DrawLine( aRect.BottomRight(), Point( aRect.Right(), aRect.Top() ) );
+ rDev.DrawLine( aRect.BottomRight(), Point( aRect.Left(), aRect.Bottom() ) );
+ }
+
+ if ( !aText.isEmpty() )
+ {
+ OUString aVal = rDev.GetEllipsisString(aText,aInnerRect.GetWidth() - 2*MIN_COLUMNWIDTH);
+
+ vcl::Font aFont( rDev.GetFont() );
+ bool bOldTransp = aFont.IsTransparent();
+ if ( !bOldTransp )
+ {
+ aFont.SetTransparent( true );
+ rDev.SetFont( aFont );
+ }
+
+ Color aOldColor = rDev.GetTextColor();
+ if (m_bDrawDisabled)
+ rDev.SetTextColor(rSettings.GetDisableColor());
+
+ rDev.DrawText( Point(
+ ( aInnerRect.Left() + aInnerRect.Right() ) / 2 - ( rDev.GetTextWidth(aVal) / 2 ),
+ aInnerRect.Top() ), aVal );
+
+ // restore settings
+ if ( !bOldTransp )
+ {
+ aFont.SetTransparent(false);
+ rDev.SetFont( aFont );
+ }
+ if (m_bDrawDisabled)
+ rDev.SetTextColor(aOldColor);
+ }
+
+ rDev.SetLineColor( aOldLineColor );
+ rDev.SetFillColor( aOldFillColor );
+}
+
+BrowserColumn::BrowserColumn( sal_uInt16 nItemId,
+ const OUString& rTitle, sal_uLong nWidthPixel, const Fraction& rCurrentZoom )
+: _nId( nItemId ),
+ _nWidth( nWidthPixel ),
+ _aTitle( rTitle ),
+ _bFrozen( false )
+{
+ double n = static_cast<double>(_nWidth);
+ n *= static_cast<double>(rCurrentZoom.GetDenominator());
+ if (!rCurrentZoom.GetNumerator())
+ throw o3tl::divide_by_zero();
+ n /= static_cast<double>(rCurrentZoom.GetNumerator());
+ _nOriginalWidth = n>0 ? static_cast<long>(n+0.5) : -static_cast<long>(-n+0.5);
+}
+
+BrowserColumn::~BrowserColumn()
+{
+}
+
+void BrowserColumn::SetWidth(sal_uLong nNewWidthPixel, const Fraction& rCurrentZoom)
+{
+ _nWidth = nNewWidthPixel;
+ // Avoid overflow when called with LONG_MAX from
+ // BrowseBox::AutoSizeLastColumn:
+ if (_nWidth == LONG_MAX)
+ {
+ _nOriginalWidth = _nWidth;
+ }
+ else
+ {
+ double n = static_cast<double>(_nWidth);
+ n *= static_cast<double>(rCurrentZoom.GetDenominator());
+ if (!rCurrentZoom.GetNumerator())
+ throw o3tl::divide_by_zero();
+ n /= static_cast<double>(rCurrentZoom.GetNumerator());
+ _nOriginalWidth = n>0 ? static_cast<long>(n+0.5) : -static_cast<long>(-n+0.5);
+ }
+}
+
+void BrowserColumn::Draw( BrowseBox const & rBox, OutputDevice& rDev, const Point& rPos )
+{
+ if ( _nId == 0 )
+ {
+ // paint handle column
+ ButtonFrame( rPos, Size( Width()-1, rBox.GetDataRowHeight()-1 ),
+ "", false ).Draw( rDev );
+ Color aOldLineColor = rDev.GetLineColor();
+ rDev.SetLineColor( COL_BLACK );
+ rDev.DrawLine(
+ Point( rPos.X(), rPos.Y()+rBox.GetDataRowHeight()-1 ),
+ Point( rPos.X() + Width() - 1, rPos.Y()+rBox.GetDataRowHeight()-1 ) );
+ rDev.DrawLine(
+ Point( rPos.X() + Width() - 1, rPos.Y() ),
+ Point( rPos.X() + Width() - 1, rPos.Y()+rBox.GetDataRowHeight()-1 ) );
+ rDev.SetLineColor( aOldLineColor );
+
+ rBox.DoPaintField( rDev,
+ tools::Rectangle(
+ Point( rPos.X() + 2, rPos.Y() + 2 ),
+ Size( Width()-1, rBox.GetDataRowHeight()-1 ) ),
+ GetId(),
+ BrowseBox::BrowserColumnAccess() );
+ }
+ else
+ {
+ // paint data column
+ long nWidth = Width() == LONG_MAX ? rBox.GetDataWindow().GetSizePixel().Width() : Width();
+
+ rBox.DoPaintField( rDev,
+ tools::Rectangle(
+ Point( rPos.X() + MIN_COLUMNWIDTH, rPos.Y() ),
+ Size( nWidth-2*MIN_COLUMNWIDTH, rBox.GetDataRowHeight()-1 ) ),
+ GetId(),
+ BrowseBox::BrowserColumnAccess() );
+ }
+}
+
+
+void BrowserColumn::ZoomChanged(const Fraction& rNewZoom)
+{
+ double n(_nOriginalWidth * rNewZoom);
+ _nWidth = n>0 ? static_cast<long>(n+0.5) : -static_cast<long>(-n+0.5);
+}
+
+
+BrowserDataWin::BrowserDataWin( BrowseBox* pParent )
+ :Control( pParent, WB_CLIPCHILDREN )
+ ,DragSourceHelper( this )
+ ,DropTargetHelper( this )
+ ,pHeaderBar( nullptr )
+ ,pCornerWin( nullptr )
+ ,bInDtor( false )
+ ,bInPaint( false )
+ ,bInCommand( false )
+ ,bNoHScroll( false )
+ ,bNoVScroll( false )
+ ,bAutoHScroll(false)
+ ,bAutoVScroll(false)
+ ,bUpdateMode( true )
+ ,bAutoSizeLastCol(false)
+ ,bResizeOnPaint( false )
+ ,bUpdateOnUnlock( false )
+ ,bInUpdateScrollbars( false )
+ ,bHadRecursion( false )
+ ,bCallingDropCallback( false )
+ ,nUpdateLock( 0 )
+ ,nCursorHidden( 0 )
+ ,m_nDragRowDividerLimit( 0 )
+ ,m_nDragRowDividerOffset( 0 )
+{
+ aMouseTimer.SetInvokeHandler( LINK( this, BrowserDataWin, RepeatedMouseMove ) );
+ aMouseTimer.SetTimeout( 100 );
+}
+
+
+BrowserDataWin::~BrowserDataWin()
+{
+ disposeOnce();
+}
+
+void BrowserDataWin::dispose()
+{
+ bInDtor = true;
+
+ aInvalidRegion.clear();
+ pHeaderBar.clear();
+ pCornerWin.clear();
+ DragSourceHelper::dispose();
+ DropTargetHelper::dispose();
+ Control::dispose();
+}
+
+
+void BrowserDataWin::LeaveUpdateLock()
+{
+ if ( !--nUpdateLock )
+ {
+ DoOutstandingInvalidations();
+ if (bUpdateOnUnlock )
+ {
+ Control::PaintImmediately();
+ bUpdateOnUnlock = false;
+ }
+ }
+}
+
+void InitSettings_Impl(vcl::Window* pWin)
+{
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+
+ pWin->ApplyControlFont(*pWin, rStyleSettings.GetFieldFont());
+ pWin->ApplyControlForeground(*pWin, rStyleSettings.GetWindowTextColor());
+ pWin->ApplyControlBackground(*pWin, rStyleSettings.GetWindowColor());
+}
+
+
+void BrowserDataWin::Update()
+{
+ if ( !nUpdateLock )
+ Control::PaintImmediately();
+ else
+ bUpdateOnUnlock = true;
+}
+
+
+void BrowserDataWin::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
+ (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
+ {
+ InitSettings_Impl(this);
+ Invalidate();
+ InitSettings_Impl(GetParent());
+ GetParent()->Invalidate();
+ GetParent()->Resize();
+ }
+ else
+ Control::DataChanged( rDCEvt );
+}
+
+
+void BrowserDataWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ if (!nUpdateLock && GetUpdateMode())
+ {
+ if (bInPaint)
+ {
+ aInvalidRegion.emplace_back(rRect);
+ return;
+ }
+ bInPaint = true;
+ GetParent()->PaintData(*this, rRenderContext, rRect);
+ bInPaint = false;
+ DoOutstandingInvalidations();
+ }
+ else
+ {
+ aInvalidRegion.emplace_back(rRect);
+ }
+}
+
+
+BrowseEvent BrowserDataWin::CreateBrowseEvent( const Point& rPosPixel )
+{
+ BrowseBox *pBox = GetParent();
+
+ // seek to row under mouse
+ long nRelRow = rPosPixel.Y() < 0
+ ? -1
+ : rPosPixel.Y() / pBox->GetDataRowHeight();
+ long nRow = nRelRow < 0 ? -1 : nRelRow + pBox->nTopRow;
+
+ // find column under mouse
+ long nMouseX = rPosPixel.X();
+ long nColX = 0;
+ size_t nCol;
+ for ( nCol = 0;
+ nCol < pBox->mvCols.size() && nColX < GetSizePixel().Width();
+ ++nCol )
+ if ( pBox->mvCols[ nCol ]->IsFrozen() || nCol >= pBox->nFirstCol )
+ {
+ nColX += pBox->mvCols[ nCol ]->Width();
+ if ( nMouseX < nColX )
+ break;
+ }
+ sal_uInt16 nColId = BROWSER_INVALIDID;
+ if ( nCol < pBox->mvCols.size() )
+ nColId = pBox->mvCols[ nCol ]->GetId();
+
+ // compute the field rectangle and field relative MouseEvent
+ tools::Rectangle aFieldRect;
+ if ( nCol < pBox->mvCols.size() )
+ {
+ nColX -= pBox->mvCols[ nCol ]->Width();
+ aFieldRect = tools::Rectangle(
+ Point( nColX, nRelRow * pBox->GetDataRowHeight() ),
+ Size( pBox->mvCols[ nCol ]->Width(),
+ pBox->GetDataRowHeight() ) );
+ }
+
+ // assemble and return the BrowseEvent
+ return BrowseEvent( this, nRow, nCol, nColId, aFieldRect );
+}
+
+
+sal_Int8 BrowserDataWin::AcceptDrop( const AcceptDropEvent& _rEvt )
+{
+ bCallingDropCallback = true;
+ sal_Int8 nReturn = GetParent()->AcceptDrop( BrowserAcceptDropEvent( this, _rEvt ) );
+ bCallingDropCallback = false;
+ return nReturn;
+}
+
+
+sal_Int8 BrowserDataWin::ExecuteDrop( const ExecuteDropEvent& _rEvt )
+{
+ bCallingDropCallback = true;
+ sal_Int8 nReturn = GetParent()->ExecuteDrop( BrowserExecuteDropEvent( this, _rEvt ) );
+ bCallingDropCallback = false;
+ return nReturn;
+}
+
+
+void BrowserDataWin::StartDrag( sal_Int8 _nAction, const Point& _rPosPixel )
+{
+ if ( !GetParent()->bRowDividerDrag )
+ {
+ Point aEventPos( _rPosPixel );
+ aEventPos.AdjustY(GetParent()->GetTitleHeight() );
+ GetParent()->StartDrag( _nAction, aEventPos );
+ }
+}
+
+
+void BrowserDataWin::Command( const CommandEvent& rEvt )
+{
+ // scroll mouse event?
+ BrowseBox *pBox = GetParent();
+ if ( ( (rEvt.GetCommand() == CommandEventId::Wheel) ||
+ (rEvt.GetCommand() == CommandEventId::StartAutoScroll) ||
+ (rEvt.GetCommand() == CommandEventId::AutoScroll) ) &&
+ ( HandleScrollCommand( rEvt, pBox->aHScroll.get(), pBox->pVScroll ) ) )
+ return;
+
+ Point aEventPos( rEvt.GetMousePosPixel() );
+ long nRow = pBox->GetRowAtYPosPixel( aEventPos.Y(), false);
+ MouseEvent aMouseEvt( aEventPos, 1, MouseEventModifiers::SELECT, MOUSE_LEFT );
+ if ( CommandEventId::ContextMenu == rEvt.GetCommand() && rEvt.IsMouseEvent() &&
+ nRow < pBox->GetRowCount() && !pBox->IsRowSelected(nRow) )
+ {
+ bInCommand = true;
+ MouseButtonDown( aMouseEvt );
+ if( bInDtor )
+ return;
+ MouseButtonUp( aMouseEvt );
+ if( bInDtor )
+ return;
+ bInCommand = false;
+ }
+
+ aEventPos.AdjustY(GetParent()->GetTitleHeight() );
+ CommandEvent aEvt( aEventPos, rEvt.GetCommand(),
+ rEvt.IsMouseEvent(), rEvt.GetEventData() );
+ bInCommand = true;
+ GetParent()->Command( aEvt );
+ if( bInDtor )
+ return;
+ bInCommand = false;
+
+ if ( CommandEventId::StartDrag == rEvt.GetCommand() )
+ MouseButtonUp( aMouseEvt );
+
+ Control::Command( rEvt );
+}
+
+
+bool BrowserDataWin::ImplRowDividerHitTest( const BrowserMouseEvent& _rEvent )
+{
+ if ( ! ( GetParent()->IsInteractiveRowHeightEnabled()
+ && ( _rEvent.GetRow() >= 0 )
+ && ( _rEvent.GetRow() < GetParent()->GetRowCount() )
+ && ( _rEvent.GetColumnId() == BrowseBox::HandleColumnId )
+ )
+ )
+ return false;
+
+ long nDividerDistance = GetParent()->GetDataRowHeight() - ( _rEvent.GetPosPixel().Y() % GetParent()->GetDataRowHeight() );
+ return ( nDividerDistance <= 4 );
+}
+
+
+void BrowserDataWin::MouseButtonDown( const MouseEvent& rEvt )
+{
+ aLastMousePos = OutputToScreenPixel( rEvt.GetPosPixel() );
+
+ BrowserMouseEvent aBrowserEvent( this, rEvt );
+ if ( ( aBrowserEvent.GetClicks() == 1 ) && ImplRowDividerHitTest( aBrowserEvent ) )
+ {
+ StartRowDividerDrag( aBrowserEvent.GetPosPixel() );
+ return;
+ }
+
+ GetParent()->MouseButtonDown( BrowserMouseEvent( this, rEvt ) );
+}
+
+
+void BrowserDataWin::MouseMove( const MouseEvent& rEvt )
+{
+ // avoid pseudo MouseMoves
+ Point aNewPos = OutputToScreenPixel( rEvt.GetPosPixel() );
+ if ( aNewPos == aLastMousePos )
+ return;
+ aLastMousePos = aNewPos;
+
+ // transform to a BrowseEvent
+ BrowserMouseEvent aBrowserEvent( this, rEvt );
+ GetParent()->MouseMove( aBrowserEvent );
+
+ // pointer shape
+ PointerStyle ePointerStyle = PointerStyle::Arrow;
+ if ( ImplRowDividerHitTest( aBrowserEvent ) )
+ ePointerStyle = PointerStyle::VSizeBar;
+ SetPointer( ePointerStyle );
+
+ // dragging out of the visible area?
+ if ( rEvt.IsLeft() &&
+ ( rEvt.GetPosPixel().Y() > GetSizePixel().Height() ||
+ rEvt.GetPosPixel().Y() < 0 ) )
+ {
+ // repeat the event
+ aRepeatEvt = rEvt;
+ aMouseTimer.Start();
+ }
+ else
+ // killing old repeat-event
+ if ( aMouseTimer.IsActive() )
+ aMouseTimer.Stop();
+}
+
+
+IMPL_LINK_NOARG(BrowserDataWin, RepeatedMouseMove, Timer *, void)
+{
+ GetParent()->MouseMove( BrowserMouseEvent( this, aRepeatEvt ) );
+}
+
+void BrowserDataWin::MouseButtonUp( const MouseEvent& rEvt )
+{
+ // avoid pseudo MouseMoves
+ Point aNewPos = OutputToScreenPixel( rEvt.GetPosPixel() );
+ aLastMousePos = aNewPos;
+
+ // simulate a move to the current position
+ MouseMove( rEvt );
+
+ // actual button up handling
+ ReleaseMouse();
+ if ( aMouseTimer.IsActive() )
+ aMouseTimer.Stop();
+ GetParent()->MouseButtonUp( BrowserMouseEvent( this, rEvt ) );
+}
+
+
+void BrowserDataWin::StartRowDividerDrag( const Point& _rStartPos )
+{
+ long nDataRowHeight = GetParent()->GetDataRowHeight();
+ // the exact separation pos of the two rows
+ long nDragRowDividerCurrentPos = _rStartPos.Y();
+ if ( ( nDragRowDividerCurrentPos % nDataRowHeight ) > nDataRowHeight / 2 )
+ nDragRowDividerCurrentPos += nDataRowHeight;
+ nDragRowDividerCurrentPos /= nDataRowHeight;
+ nDragRowDividerCurrentPos *= nDataRowHeight;
+
+ m_nDragRowDividerOffset = nDragRowDividerCurrentPos - _rStartPos.Y();
+
+ m_nDragRowDividerLimit = nDragRowDividerCurrentPos - nDataRowHeight;
+
+ GetParent()->bRowDividerDrag = true;
+ GetParent()->ImplStartTracking();
+
+ tools::Rectangle aDragSplitRect( 0, m_nDragRowDividerLimit, GetOutputSizePixel().Width(), nDragRowDividerCurrentPos );
+ ShowTracking( aDragSplitRect );
+
+ StartTracking();
+}
+
+
+void BrowserDataWin::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( !GetParent()->bRowDividerDrag )
+ return;
+
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+ // stop resizing at our bottom line
+ if ( aMousePos.Y() > GetOutputSizePixel().Height() )
+ aMousePos.setY( GetOutputSizePixel().Height() );
+
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ HideTracking();
+ GetParent()->bRowDividerDrag = false;
+ GetParent()->ImplEndTracking();
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ long nNewRowHeight = aMousePos.Y() + m_nDragRowDividerOffset - m_nDragRowDividerLimit;
+
+ // care for minimum row height
+ if ( nNewRowHeight < GetParent()->QueryMinimumRowHeight() )
+ nNewRowHeight = GetParent()->QueryMinimumRowHeight();
+
+ GetParent()->SetDataRowHeight( nNewRowHeight );
+ GetParent()->RowHeightChanged();
+ }
+ }
+ else
+ {
+ long nDragRowDividerCurrentPos = aMousePos.Y() + m_nDragRowDividerOffset;
+
+ // care for minimum row height
+ if ( nDragRowDividerCurrentPos < m_nDragRowDividerLimit + GetParent()->QueryMinimumRowHeight() )
+ nDragRowDividerCurrentPos = m_nDragRowDividerLimit + GetParent()->QueryMinimumRowHeight();
+
+ tools::Rectangle aDragSplitRect( 0, m_nDragRowDividerLimit, GetOutputSizePixel().Width(), nDragRowDividerCurrentPos );
+ ShowTracking( aDragSplitRect );
+ }
+}
+
+
+void BrowserDataWin::KeyInput( const KeyEvent& rEvt )
+{
+ // pass to parent window
+ if ( !GetParent()->ProcessKey( rEvt ) )
+ Control::KeyInput( rEvt );
+}
+
+
+void BrowserDataWin::RequestHelp( const HelpEvent& rHEvt )
+{
+ GetParent()->RequestHelp( rHEvt );
+}
+
+
+BrowseEvent::BrowseEvent( vcl::Window* pWindow,
+ long nAbsRow, sal_uInt16 nColumn, sal_uInt16 nColumnId,
+ const tools::Rectangle& rRect ):
+ pWin(pWindow),
+ nRow(nAbsRow),
+ aRect(rRect),
+ nCol(nColumn),
+ nColId(nColumnId)
+{
+}
+
+
+BrowserMouseEvent::BrowserMouseEvent( BrowserDataWin *pWindow,
+ const MouseEvent& rEvt ):
+ MouseEvent(rEvt),
+ BrowseEvent( pWindow->CreateBrowseEvent( rEvt.GetPosPixel() ) )
+{
+}
+
+
+BrowserMouseEvent::BrowserMouseEvent( vcl::Window *pWindow, const MouseEvent& rEvt,
+ long nAbsRow, sal_uInt16 nColumn, sal_uInt16 nColumnId,
+ const tools::Rectangle& rRect ):
+ MouseEvent(rEvt),
+ BrowseEvent( pWindow, nAbsRow, nColumn, nColumnId, rRect )
+{
+}
+
+
+BrowserAcceptDropEvent::BrowserAcceptDropEvent( BrowserDataWin *pWindow, const AcceptDropEvent& rEvt )
+ :AcceptDropEvent(rEvt)
+ ,BrowseEvent( pWindow->CreateBrowseEvent( rEvt.maPosPixel ) )
+{
+}
+
+
+BrowserExecuteDropEvent::BrowserExecuteDropEvent( BrowserDataWin *pWindow, const ExecuteDropEvent& rEvt )
+ :ExecuteDropEvent(rEvt)
+ ,BrowseEvent( pWindow->CreateBrowseEvent( rEvt.maPosPixel ) )
+{
+}
+
+
+void BrowserDataWin::SetUpdateMode( bool bMode )
+{
+ DBG_ASSERT( !bUpdateMode || aInvalidRegion.empty(), "invalid region not empty" );
+ if ( bMode == bUpdateMode )
+ return;
+
+ bUpdateMode = bMode;
+ if ( bMode )
+ DoOutstandingInvalidations();
+}
+
+
+void BrowserDataWin::DoOutstandingInvalidations()
+{
+ for (const auto& rRect : aInvalidRegion)
+ Control::Invalidate( rRect );
+ aInvalidRegion.clear();
+}
+
+
+void BrowserDataWin::Invalidate( InvalidateFlags nFlags )
+{
+ if ( !GetUpdateMode() )
+ {
+ aInvalidRegion.clear();
+ aInvalidRegion.emplace_back( Point( 0, 0 ), GetOutputSizePixel() );
+ }
+ else
+ Window::Invalidate( nFlags );
+}
+
+
+void BrowserDataWin::Invalidate( const tools::Rectangle& rRect, InvalidateFlags nFlags )
+{
+ if ( !GetUpdateMode() )
+ aInvalidRegion.emplace_back( rRect );
+ else
+ Window::Invalidate( rRect, nFlags );
+}
+
+BrowserScrollBar::~BrowserScrollBar()
+{
+ disposeOnce();
+}
+
+void BrowserScrollBar::dispose()
+{
+ _pDataWin.clear();
+ ScrollBar::dispose();
+}
+
+void BrowserScrollBar::Tracking( const TrackingEvent& rTEvt )
+{
+ sal_uLong nPos = GetThumbPos();
+ if ( nPos != _nLastPos )
+ {
+ OUString aTip = OUString::number(nPos) + "/";
+ if ( !_pDataWin->GetRealRowCount().isEmpty() )
+ aTip += _pDataWin->GetRealRowCount();
+ else
+ aTip += OUString::number(GetRangeMax());
+
+ tools::Rectangle aRect(GetPointerPosPixel(), Size(GetTextWidth(aTip), GetTextHeight()));
+ Help::ShowQuickHelp(this, aRect, aTip);
+ _nLastPos = nPos;
+ }
+
+ ScrollBar::Tracking( rTEvt );
+}
+
+void BrowserScrollBar::EndScroll()
+{
+ Help::HideBalloonAndQuickHelp();
+ ScrollBar::EndScroll();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */