wxWidgets/src/generic/vscroll.cpp

983 lines
27 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/generic/vscroll.cpp
// Purpose: wxVScrolledWindow implementation
// Author: Vadim Zeitlin
// Modified by: Brad Anderson
// Created: 30.05.03
// RCS-ID: $Id$
// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/dc.h"
#include "wx/sizer.h"
#endif
#include "wx/vscroll.h"
// ============================================================================
// wxVarScrollHelperEvtHandler declaration
// ============================================================================
// ----------------------------------------------------------------------------
// wxScrollHelperEvtHandler: intercept the events from the window and forward
// them to wxVarScrollHelperBase
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxVarScrollHelperEvtHandler : public wxEvtHandler
{
public:
wxVarScrollHelperEvtHandler(wxVarScrollHelperBase *scrollHelper)
{
m_scrollHelper = scrollHelper;
}
virtual bool ProcessEvent(wxEvent& event);
private:
wxVarScrollHelperBase *m_scrollHelper;
DECLARE_NO_COPY_CLASS(wxVarScrollHelperEvtHandler)
};
// ============================================================================
// wxVarScrollHelperEvtHandler implementation
// ============================================================================
bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event)
{
wxEventType evType = event.GetEventType();
// pass it on to the real handler
bool processed = wxEvtHandler::ProcessEvent(event);
// always process the size events ourselves, even if the user code handles
// them as well, as we need to AdjustScrollbars()
//
// NB: it is important to do it after processing the event in the normal
// way as HandleOnSize() may generate a wxEVT_SIZE itself if the
// scrollbar[s] (dis)appear and it should be seen by the user code
// after this one
if ( evType == wxEVT_SIZE )
{
m_scrollHelper->HandleOnSize((wxSizeEvent &)event);
return !event.GetSkipped();
}
if ( processed )
{
// normally, nothing more to do here - except if we have a command
// event
if ( event.IsCommandEvent() )
{
return true;
}
}
// reset the skipped flag (which might have been set to true in
// ProcessEvent() above) to be able to test it below
bool wasSkipped = event.GetSkipped();
if ( wasSkipped )
event.Skip(false);
// reset the skipped flag to false as it might have been set to true in
// ProcessEvent() above
event.Skip(false);
if ( evType == wxEVT_SCROLLWIN_TOP ||
evType == wxEVT_SCROLLWIN_BOTTOM ||
evType == wxEVT_SCROLLWIN_LINEUP ||
evType == wxEVT_SCROLLWIN_LINEDOWN ||
evType == wxEVT_SCROLLWIN_PAGEUP ||
evType == wxEVT_SCROLLWIN_PAGEDOWN ||
evType == wxEVT_SCROLLWIN_THUMBTRACK ||
evType == wxEVT_SCROLLWIN_THUMBRELEASE )
{
m_scrollHelper->HandleOnScroll((wxScrollWinEvent &)event);
if ( !event.GetSkipped() )
{
// it makes sense to indicate that we processed the message as we
// did scroll the window (and also notice that wxAutoScrollTimer
// relies on our return value for continuous scrolling)
processed = true;
wasSkipped = false;
}
}
#if wxUSE_MOUSEWHEEL
else if ( evType == wxEVT_MOUSEWHEEL )
{
m_scrollHelper->HandleOnMouseWheel((wxMouseEvent &)event);
}
#endif // wxUSE_MOUSEWHEEL
if ( processed )
event.Skip(wasSkipped);
return processed;
}
// ============================================================================
// wxVarScrollHelperBase implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxVarScrollHelperBase initialization
// ----------------------------------------------------------------------------
wxVarScrollHelperBase::wxVarScrollHelperBase(wxWindow *win)
{
wxASSERT_MSG( win, _T("associated window can't be NULL in wxVarScrollHelperBase") );
#if wxUSE_MOUSEWHEEL
m_sumWheelRotation = 0;
#endif
m_unitMax = 0;
m_sizeTotal = 0;
m_unitFirst = 0;
m_win =
m_targetWindow = (wxWindow *)NULL;
m_handler = NULL;
m_win = win;
// by default, the associated window is also the target window
DoSetTargetWindow(win);
}
wxVarScrollHelperBase::~wxVarScrollHelperBase()
{
DeleteEvtHandler();
}
// ----------------------------------------------------------------------------
// wxVarScrollHelperBase various helpers
// ----------------------------------------------------------------------------
void
wxVarScrollHelperBase::AssignOrient(wxCoord& x,
wxCoord& y,
wxCoord first,
wxCoord second)
{
if ( GetOrientation() == wxVERTICAL )
{
x = first;
y = second;
}
else // horizontal
{
x = second;
y = first;
}
}
void
wxVarScrollHelperBase::IncOrient(wxCoord& x, wxCoord& y, wxCoord inc)
{
if ( GetOrientation() == wxVERTICAL )
y += inc;
else
x += inc;
}
wxCoord wxVarScrollHelperBase::DoEstimateTotalSize() const
{
// estimate the total height: it is impossible to call
// OnGetUnitSize() for every unit because there may be too many of
// them, so we just make a guess using some units in the beginning,
// some in the end and some in the middle
static const size_t NUM_UNITS_TO_SAMPLE = 10;
wxCoord sizeTotal;
if ( m_unitMax < 3*NUM_UNITS_TO_SAMPLE )
{
// in this case, full calculations are faster and more correct than
// guessing
sizeTotal = GetUnitsSize(0, m_unitMax);
}
else // too many units to calculate exactly
{
// look at some units in the beginning/middle/end
sizeTotal =
GetUnitsSize(0, NUM_UNITS_TO_SAMPLE) +
GetUnitsSize(m_unitMax - NUM_UNITS_TO_SAMPLE,
m_unitMax) +
GetUnitsSize(m_unitMax/2 - NUM_UNITS_TO_SAMPLE/2,
m_unitMax/2 + NUM_UNITS_TO_SAMPLE/2);
// use the height of the units we looked as the average
sizeTotal = (wxCoord)
(((float)sizeTotal / (3*NUM_UNITS_TO_SAMPLE)) * m_unitMax);
}
return sizeTotal;
}
wxCoord wxVarScrollHelperBase::GetUnitsSize(size_t unitMin, size_t unitMax) const
{
if ( unitMin == unitMax )
return 0;
else if ( unitMin > unitMax )
return -GetUnitsSize(unitMax, unitMin);
//else: unitMin < unitMax
// let the user code know that we're going to need all these units
OnGetUnitsSizeHint(unitMin, unitMax);
// sum up their sizes
wxCoord size = 0;
for ( size_t unit = unitMin; unit < unitMax; ++unit )
{
size += OnGetUnitSize(unit);
}
return size;
}
size_t wxVarScrollHelperBase::FindFirstVisibleFromLast(size_t unitLast, bool full) const
{
const wxCoord sWindow = GetOrientationTargetSize();
// go upwards until we arrive at a unit such that unitLast is not visible
// any more when it is shown
size_t unitFirst = unitLast;
wxCoord s = 0;
for ( ;; )
{
s += OnGetUnitSize(unitFirst);
if ( s > sWindow )
{
// for this unit to be fully visible we need to go one unit
// down, but if it is enough for it to be only partly visible then
// this unit will do as well
if ( full )
{
++unitFirst;
}
break;
}
if ( !unitFirst )
break;
--unitFirst;
}
return unitFirst;
}
size_t wxVarScrollHelperBase::GetNewScrollPosition(wxScrollWinEvent& event) const
{
wxEventType evtType = event.GetEventType();
if ( evtType == wxEVT_SCROLLWIN_TOP )
{
return 0;
}
else if ( evtType == wxEVT_SCROLLWIN_BOTTOM )
{
return m_unitMax;
}
else if ( evtType == wxEVT_SCROLLWIN_LINEUP )
{
return m_unitFirst ? m_unitFirst - 1 : 0;
}
else if ( evtType == wxEVT_SCROLLWIN_LINEDOWN )
{
return m_unitFirst + 1;
}
else if ( evtType == wxEVT_SCROLLWIN_PAGEUP )
{
return FindFirstVisibleFromLast(m_unitFirst);
}
else if ( evtType == wxEVT_SCROLLWIN_PAGEDOWN )
{
if ( GetVisibleEnd() )
return GetVisibleEnd() - 1;
else
return GetVisibleEnd();
}
else if ( evtType == wxEVT_SCROLLWIN_THUMBRELEASE )
{
return event.GetPosition();
}
else if ( evtType == wxEVT_SCROLLWIN_THUMBTRACK )
{
return event.GetPosition();
}
// unknown scroll event?
wxFAIL_MSG( _T("unknown scroll event type?") );
return 0;
}
void wxVarScrollHelperBase::UpdateScrollbar()
{
// if there is nothing to scroll, remove the scrollbar
if ( !m_unitMax )
{
RemoveScrollbar();
return;
}
// see how many units can we fit on screen
const wxCoord sWindow = GetOrientationTargetSize();
// do vertical calculations
wxCoord s = 0;
size_t unit;
for ( unit = m_unitFirst; unit < m_unitMax; ++unit )
{
if ( s > sWindow )
break;
s += OnGetUnitSize(unit);
}
m_nUnitsVisible = unit - m_unitFirst;
int unitsPageSize = m_nUnitsVisible;
if ( s > sWindow )
{
// last unit is only partially visible, we still need the scrollbar and
// so we have to "fix" pageSize because if it is equal to m_unitMax
// the scrollbar is not shown at all under MSW
--unitsPageSize;
}
// set the scrollbar parameters to reflect this
m_win->SetScrollbar(GetOrientation(), m_unitFirst, unitsPageSize, m_unitMax);
}
void wxVarScrollHelperBase::RemoveScrollbar()
{
m_unitFirst = 0;
m_nUnitsVisible = m_unitMax;
m_win->SetScrollbar(GetOrientation(), 0, 0, 0);
}
void wxVarScrollHelperBase::DeleteEvtHandler()
{
// search for m_handler in the handler list
if ( m_win && m_handler )
{
if ( m_win->RemoveEventHandler(m_handler) )
{
delete m_handler;
}
//else: something is very wrong, so better [maybe] leak memory than
// risk a crash because of double deletion
m_handler = NULL;
}
}
void wxVarScrollHelperBase::DoSetTargetWindow(wxWindow *target)
{
m_targetWindow = target;
#ifdef __WXMAC__
target->MacSetClipChildren( true ) ;
#endif
// install the event handler which will intercept the events we're
// interested in (but only do it for our real window, not the target window
// which we scroll - we don't need to hijack its events)
if ( m_targetWindow == m_win )
{
// if we already have a handler, delete it first
DeleteEvtHandler();
m_handler = new wxVarScrollHelperEvtHandler(this);
m_targetWindow->PushEventHandler(m_handler);
}
}
// ----------------------------------------------------------------------------
// wxVarScrollHelperBase operations
// ----------------------------------------------------------------------------
void wxVarScrollHelperBase::SetTargetWindow(wxWindow *target)
{
wxCHECK_RET( target, wxT("target window must not be NULL") );
if ( target == m_targetWindow )
return;
DoSetTargetWindow(target);
}
void wxVarScrollHelperBase::SetUnitCount(size_t count)
{
// save the number of units
m_unitMax = count;
// and our estimate for their total height
m_sizeTotal = EstimateTotalSize();
// ScrollToUnit() will update the scrollbar itself if it changes the unit
// we pass to it because it's out of [new] range
size_t oldScrollPos = m_unitFirst;
DoScrollToUnit(m_unitFirst);
if ( oldScrollPos == m_unitFirst )
{
// but if it didn't do it, we still need to update the scrollbar to
// reflect the changed number of units ourselves
UpdateScrollbar();
}
}
void wxVarScrollHelperBase::RefreshUnit(size_t unit)
{
// is this unit visible?
if ( !IsVisible(unit) )
{
// no, it is useless to do anything
return;
}
// calculate the rect occupied by this unit on screen
wxRect rect;
AssignOrient(rect.width, rect.height,
GetNonOrientationTargetSize(), OnGetUnitSize(unit));
for ( size_t n = GetVisibleBegin(); n < unit; ++n )
{
IncOrient(rect.x, rect.y, OnGetUnitSize(n));
}
// do refresh it
m_targetWindow->RefreshRect(rect);
}
void wxVarScrollHelperBase::RefreshUnits(size_t from, size_t to)
{
wxASSERT_MSG( from <= to, _T("RefreshUnits(): empty range") );
// clump the range to just the visible units -- it is useless to refresh
// the other ones
if ( from < GetVisibleBegin() )
from = GetVisibleBegin();
if ( to > GetVisibleEnd() )
to = GetVisibleEnd();
// calculate the rect occupied by these units on screen
int orient_size, nonorient_size, orient_pos;
orient_size = nonorient_size = orient_pos = 0;
nonorient_size = GetNonOrientationTargetSize();
for ( size_t nBefore = GetVisibleBegin();
nBefore < from;
nBefore++ )
{
orient_pos += OnGetUnitSize(nBefore);
}
for ( size_t nBetween = from; nBetween <= to; nBetween++ )
{
orient_size += OnGetUnitSize(nBetween);
}
wxRect rect;
AssignOrient(rect.x, rect.y, 0, orient_pos);
AssignOrient(rect.width, rect.height, nonorient_size, orient_size);
// do refresh it
m_targetWindow->RefreshRect(rect);
}
void wxVarScrollHelperBase::RefreshAll()
{
UpdateScrollbar();
m_targetWindow->Refresh();
}
bool wxVarScrollHelperBase::ScrollLayout()
{
if ( m_targetWindow->GetSizer() && m_physicalScrolling )
{
// adjust the sizer dimensions/position taking into account the
// virtual size and scrolled position of the window.
int x, y;
AssignOrient(x, y, 0, -GetScrollOffset());
int w, h;
m_targetWindow->GetVirtualSize(&w, &h);
m_targetWindow->GetSizer()->SetDimension(x, y, w, h);
return true;
}
// fall back to default for LayoutConstraints
return m_targetWindow->wxWindow::Layout();
}
int wxVarScrollHelperBase::VirtualHitTest(wxCoord coord) const
{
const size_t unitMax = GetVisibleEnd();
for ( size_t unit = GetVisibleBegin(); unit < unitMax; ++unit )
{
coord -= OnGetUnitSize(unit);
if ( coord < 0 )
return unit;
}
return wxNOT_FOUND;
}
// ----------------------------------------------------------------------------
// wxVarScrollHelperBase scrolling
// ----------------------------------------------------------------------------
bool wxVarScrollHelperBase::DoScrollToUnit(size_t unit)
{
if ( !m_unitMax )
{
// we're empty, code below doesn't make sense in this case
return false;
}
// determine the real first unit to scroll to: we shouldn't scroll beyond
// the end
size_t unitFirstLast = FindFirstVisibleFromLast(m_unitMax - 1, true);
if ( unit > unitFirstLast )
unit = unitFirstLast;
// anything to do?
if ( unit == m_unitFirst )
{
// no
return false;
}
// remember the currently shown units for the refresh code below
size_t unitFirstOld = GetVisibleBegin(),
unitLastOld = GetVisibleEnd();
m_unitFirst = unit;
// the size of scrollbar thumb could have changed
UpdateScrollbar();
// finally refresh the display -- but only redraw as few units as possible
// to avoid flicker. We can't do this if we have children because they
// won't be scrolled
if ( m_targetWindow->GetChildren().empty() &&
GetVisibleBegin() >= unitLastOld || GetVisibleEnd() <= unitFirstOld )
{
// the simplest case: we don't have any old units left, just redraw
// everything
m_targetWindow->Refresh();
}
else // scroll the window
{
if ( m_physicalScrolling )
{
wxCoord dx = 0,
dy = GetUnitsSize(GetVisibleBegin(), unitFirstOld);
if ( GetOrientation() == wxHORIZONTAL )
{
wxCoord tmp = dx;
dx = dy;
dy = tmp;
}
m_targetWindow->ScrollWindow(dx, dy);
}
else // !m_physicalScrolling
{
// we still need to invalidate but we can't use ScrollWindow
// because physical scrolling is disabled (the user either didn't
// want children scrolled and/or doesn't want pixels to be
// physically scrolled).
m_targetWindow->Refresh();
}
}
return true;
}
bool wxVarScrollHelperBase::DoScrollUnits(int units)
{
units += m_unitFirst;
if ( units < 0 )
units = 0;
return DoScrollToUnit(units);
}
bool wxVarScrollHelperBase::DoScrollPages(int pages)
{
bool didSomething = false;
while ( pages )
{
int unit;
if ( pages > 0 )
{
unit = GetVisibleEnd();
if ( unit )
--unit;
--pages;
}
else // pages < 0
{
unit = FindFirstVisibleFromLast(GetVisibleEnd());
++pages;
}
didSomething = DoScrollToUnit(unit);
}
return didSomething;
}
// ----------------------------------------------------------------------------
// event handling
// ----------------------------------------------------------------------------
void wxVarScrollHelperBase::HandleOnSize(wxSizeEvent& event)
{
UpdateScrollbar();
event.Skip();
}
void wxVarScrollHelperBase::HandleOnScroll(wxScrollWinEvent& event)
{
if (GetOrientation() != event.GetOrientation())
{
event.Skip();
return;
}
DoScrollToUnit(GetNewScrollPosition(event));
#ifdef __WXMAC__
UpdateMacScrollWindow();
#endif // __WXMAC__
}
void wxVarScrollHelperBase::DoPrepareDC(wxDC& dc)
{
if ( m_physicalScrolling )
{
wxPoint pt = dc.GetDeviceOrigin();
IncOrient(pt.x, pt.y, -GetScrollOffset());
dc.SetDeviceOrigin(pt.x, pt.y);
}
}
int wxVarScrollHelperBase::DoCalcScrolledPosition(int coord) const
{
return coord - GetScrollOffset();
}
int wxVarScrollHelperBase::DoCalcUnscrolledPosition(int coord) const
{
return coord + GetScrollOffset();
}
#if wxUSE_MOUSEWHEEL
void wxVarScrollHelperBase::HandleOnMouseWheel(wxMouseEvent& event)
{
// we only want to process wheel events for vertical implementations.
// There is no way to determine wheel orientation (and on MSW horizontal
// wheel rotation just fakes scroll events, rather than sending a MOUSEWHEEL
// event).
if ( GetOrientation() != wxVERTICAL )
return;
m_sumWheelRotation += event.GetWheelRotation();
int delta = event.GetWheelDelta();
// how much to scroll this time
int units_to_scroll = -(m_sumWheelRotation/delta);
if ( !units_to_scroll )
return;
m_sumWheelRotation += units_to_scroll*delta;
if ( !event.IsPageScroll() )
DoScrollUnits( units_to_scroll*event.GetLinesPerAction() );
else // scroll pages instead of units
DoScrollPages( units_to_scroll );
}
#endif // wxUSE_MOUSEWHEEL
// ============================================================================
// wxVarHVScrollHelper implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxVarHVScrollHelper operations
// ----------------------------------------------------------------------------
void wxVarHVScrollHelper::SetRowColumnCount(size_t rowCount, size_t columnCount)
{
SetRowCount(rowCount);
SetColumnCount(columnCount);
}
bool wxVarHVScrollHelper::ScrollToRowColumn(size_t row, size_t column)
{
bool result = false;
result |= ScrollToRow(row);
result |= ScrollToColumn(column);
return result;
}
void wxVarHVScrollHelper::RefreshRowColumn(size_t row, size_t column)
{
// is this unit visible?
if ( !IsRowVisible(row) || !IsColumnVisible(column) )
{
// no, it is useless to do anything
return;
}
// calculate the rect occupied by this cell on screen
wxRect v_rect, h_rect;
v_rect.height = OnGetRowHeight(row);
h_rect.width = OnGetColumnWidth(column);
size_t n;
for ( n = GetVisibleRowsBegin(); n < row; n++ )
{
v_rect.y += OnGetRowHeight(n);
}
for ( n = GetVisibleColumnsBegin(); n < column; n++ )
{
h_rect.x += OnGetColumnWidth(n);
}
// refresh but specialize the behavior if we have a single target window
if ( wxVarVScrollHelper::GetTargetWindow() == wxVarHScrollHelper::GetTargetWindow() )
{
v_rect.x = h_rect.x;
v_rect.width = h_rect.width;
wxVarVScrollHelper::GetTargetWindow()->RefreshRect(v_rect);
}
else
{
v_rect.x = 0;
v_rect.width = wxVarVScrollHelper::GetNonOrientationTargetSize();
h_rect.y = 0;
h_rect.width = wxVarHScrollHelper::GetNonOrientationTargetSize();
wxVarVScrollHelper::GetTargetWindow()->RefreshRect(v_rect);
wxVarHScrollHelper::GetTargetWindow()->RefreshRect(h_rect);
}
}
void wxVarHVScrollHelper::RefreshRowsColumns(size_t fromRow, size_t toRow,
size_t fromColumn, size_t toColumn)
{
wxASSERT_MSG( fromRow <= toRow || fromColumn <= toColumn,
_T("RefreshRowsColumns(): empty range") );
// clump the range to just the visible units -- it is useless to refresh
// the other ones
if ( fromRow < GetVisibleRowsBegin() )
fromRow = GetVisibleRowsBegin();
if ( toRow > GetVisibleRowsEnd() )
toRow = GetVisibleRowsEnd();
if ( fromColumn < GetVisibleColumnsBegin() )
fromColumn = GetVisibleColumnsBegin();
if ( toColumn > GetVisibleColumnsEnd() )
toColumn = GetVisibleColumnsEnd();
// calculate the rect occupied by these units on screen
wxRect v_rect, h_rect;
size_t nBefore, nBetween;
for ( nBefore = GetVisibleRowsBegin();
nBefore < fromRow;
nBefore++ )
{
v_rect.y += OnGetRowHeight(nBefore);
}
for ( nBetween = fromRow; nBetween <= toRow; nBetween++ )
{
v_rect.height += OnGetRowHeight(nBetween);
}
for ( nBefore = GetVisibleColumnsBegin();
nBefore < fromColumn;
nBefore++ )
{
h_rect.x += OnGetColumnWidth(nBefore);
}
for ( nBetween = fromColumn; nBetween <= toColumn; nBetween++ )
{
h_rect.width += OnGetColumnWidth(nBetween);
}
// refresh but specialize the behavior if we have a single target window
if ( wxVarVScrollHelper::GetTargetWindow() == wxVarHScrollHelper::GetTargetWindow() )
{
v_rect.x = h_rect.x;
v_rect.width = h_rect.width;
wxVarVScrollHelper::GetTargetWindow()->RefreshRect(v_rect);
}
else
{
v_rect.x = 0;
v_rect.width = wxVarVScrollHelper::GetNonOrientationTargetSize();
h_rect.y = 0;
h_rect.width = wxVarHScrollHelper::GetNonOrientationTargetSize();
wxVarVScrollHelper::GetTargetWindow()->RefreshRect(v_rect);
wxVarHScrollHelper::GetTargetWindow()->RefreshRect(h_rect);
}
}
wxPosition wxVarHVScrollHelper::VirtualHitTest(wxCoord x, wxCoord y) const
{
return wxPosition(wxVarVScrollHelper::VirtualHitTest(y),
wxVarHScrollHelper::VirtualHitTest(x));
}
void wxVarHVScrollHelper::DoPrepareDC(wxDC& dc)
{
wxVarVScrollHelper::DoPrepareDC(dc);
wxVarHScrollHelper::DoPrepareDC(dc);
}
bool wxVarHVScrollHelper::ScrollLayout()
{
bool layout_result = false;
layout_result |= wxVarVScrollHelper::ScrollLayout();
layout_result |= wxVarHScrollHelper::ScrollLayout();
return layout_result;
}
wxSize wxVarHVScrollHelper::GetRowColumnCount() const
{
return wxSize(GetColumnCount(), GetRowCount());
}
wxPosition wxVarHVScrollHelper::GetVisibleBegin() const
{
return wxPosition(GetVisibleRowsBegin(), GetVisibleColumnsBegin());
}
wxPosition wxVarHVScrollHelper::GetVisibleEnd() const
{
return wxPosition(GetVisibleRowsEnd(), GetVisibleColumnsEnd());
}
bool wxVarHVScrollHelper::IsVisible(size_t row, size_t column) const
{
return IsRowVisible(row) && IsColumnVisible(column);
}
// ============================================================================
// wx[V/H/HV]ScrolledWindow implementations
// ============================================================================
IMPLEMENT_ABSTRACT_CLASS(wxVScrolledWindow, wxPanel)
IMPLEMENT_ABSTRACT_CLASS(wxHScrolledWindow, wxPanel)
IMPLEMENT_ABSTRACT_CLASS(wxHVScrolledWindow, wxPanel)
#if WXWIN_COMPATIBILITY_2_8
// ===========================================================================
// wxVarVScrollLegacyAdaptor
// ===========================================================================
size_t wxVarVScrollLegacyAdaptor::GetFirstVisibleLine() const
{ return GetVisibleRowsBegin(); }
size_t wxVarVScrollLegacyAdaptor::GetLastVisibleLine() const
{ return GetVisibleRowsEnd() - 1; }
size_t wxVarVScrollLegacyAdaptor::GetLineCount() const
{ return GetRowCount(); }
void wxVarVScrollLegacyAdaptor::SetLineCount(size_t count)
{ SetRowCount(count); }
void wxVarVScrollLegacyAdaptor::RefreshLine(size_t line)
{ RefreshRow(line); }
void wxVarVScrollLegacyAdaptor::RefreshLines(size_t from, size_t to)
{ RefreshRows(from, to); }
bool wxVarVScrollLegacyAdaptor::ScrollToLine(size_t line)
{ return ScrollToRow(line); }
bool wxVarVScrollLegacyAdaptor::ScrollLines(int lines)
{ return ScrollRows(lines); }
bool wxVarVScrollLegacyAdaptor::ScrollPages(int pages)
{ return ScrollRowPages(pages); }
wxCoord wxVarVScrollLegacyAdaptor::OnGetLineHeight(size_t WXUNUSED(n)) const
{
wxFAIL_MSG( _T("OnGetLineHeight() must be overridden if OnGetRowHeight() isn't!") );
return -1;
}
void wxVarVScrollLegacyAdaptor::OnGetLinesHint(size_t WXUNUSED(lineMin),
size_t WXUNUSED(lineMax)) const
{
}
wxCoord wxVarVScrollLegacyAdaptor::OnGetRowHeight(size_t n) const
{
return OnGetLineHeight(n);
}
void wxVarVScrollLegacyAdaptor::OnGetRowsHeightHint(size_t rowMin,
size_t rowMax) const
{
OnGetLinesHint(rowMin, rowMax);
}
#endif // WXWIN_COMPATIBILITY_2_8