// Name: include/wx/vscroll.h
// Purpose: wxVScrolledWindow: generalization of wxScrolledWindow
// Author: Vadim Zeitlin
-// Modified by: Brad Anderson
+// Modified by:
// Created: 30.05.03
// RCS-ID: $Id$
// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwidgets.org>
// is kept for backwards compatibility
size_t GetLastVisibleLine() const { return GetVisibleEnd() - 1; }
- // layout the children (including the sizer if needed)
- virtual bool Layout();
protected:
// this function must be overridden in the derived class and it should
DECLARE_ABSTRACT_CLASS(wxVScrolledWindow)
};
-
-// ----------------------------------------------------------------------------
-// wxHVScrolledWindow
-// ----------------------------------------------------------------------------
-
-/*
- This class is strongly influenced by wxVScrolledWindow. In fact, much of
- code is line for line the same except it explicitly states which axis is
- being worked on. Like wxVScrolledWindow, this class is here to provide
- an easy way to implement variable line sizes. The difference is that
- wxVScrolledWindow only works with vertical scrolling. This class extends
- the behavior of wxVScrolledWindow to the horizontal axis in addition to the
- vertical axis.
-
- The scrolling is also "virtual" in the sense that line widths and heights
- only need to be known for lines that are currently visible.
-
- Like wxVScrolledWindow, this is a generalization of the wxScrolledWindow
- class which can be only used when all horizontal lines have the same width
- and all of the vertical lines have the same height. Like wxVScrolledWinow
- it lacks some of wxScrolledWindow features such as scrolling another window
- or only scrolling a rectangle of the window and not its entire client area.
-
- If only vertical scrolling is needed, wxVScrolledWindow is recommended
- because it is simpler to use (and you get to type less).
-
- There is no wxHScrolledWindow but horizontal only scrolling is implemented
- easily enough with this class. If someone feels the need for such a class,
- implementing it is trivial.
- */
-class WXDLLEXPORT wxHVScrolledWindow : public wxPanel
-{
-public:
- // constructors and such
- // ---------------------
-
- // default ctor, you must call Create() later
- wxHVScrolledWindow() { Init(); }
-
- // normal ctor, no need to call Create() after this one
- //
- // note that wxVSCROLL and wxHSCROLL are always automatically added to our
- // style, there is no need to specify them explicitly
- wxHVScrolledWindow(wxWindow *parent,
- wxWindowID id = wxID_ANY,
- const wxPoint& pos = wxDefaultPosition,
- const wxSize& size = wxDefaultSize,
- long style = 0,
- const wxString& name = wxPanelNameStr)
- {
- Init();
-
- (void)Create(parent, id, pos, size, style, name);
- }
-
- // same as the previous ctor but returns status code: true if ok
- //
- // just as with the ctor above, wxVSCROLL and wxHSCROLL styles are always
- // used, there is no need to specify them
- bool Create(wxWindow *parent,
- wxWindowID id = wxID_ANY,
- const wxPoint& pos = wxDefaultPosition,
- const wxSize& size = wxDefaultSize,
- long style = 0,
- const wxString& name = wxPanelNameStr)
- {
- return wxPanel::Create(parent, id, pos, size,
- style | wxVSCROLL | wxHSCROLL, name);
- }
-
-
- // operations
- // ----------
-
- // set the number of lines the window contains for each axis: the derived
- // class must provide the widths and heights for all lines with indices up
- // to each of the one given here in its OnGetColumnWidth() and
- // OnGetRowHeight()
- void SetRowColumnCounts(size_t rowCount, size_t columnCount);
-
- // with physical scrolling on, the device origin is changed properly when
- // a wxPaintDC is prepared, children are actually moved and layed out
- // properly, and the contents of the window (pixels) are actually moved
- void EnablePhysicalScrolling(bool scrolling = true)
- { m_physicalScrolling = scrolling; }
-
- // scroll to the specified line: it will become the first visible line in
- // the window
- //
- // return true if we scrolled the window, false if nothing was done
- bool ScrollToRow(size_t row);
- bool ScrollToColumn(size_t column);
- bool ScrollToRowColumn(size_t row, size_t column);
-
- // scroll by the specified number of lines/pages
- virtual bool ScrollRows(int rows);
- virtual bool ScrollColumns(int columns);
- virtual bool ScrollRowsColumns(int rows, int columns);
- virtual bool ScrollRowPages(int pages);
- virtual bool ScrollColumnPages(int pages);
- virtual bool ScrollPages(int rowPages, int columnPages);
-
- // redraw the specified line
- virtual void RefreshRow(size_t line);
- virtual void RefreshColumn(size_t line);
- virtual void RefreshRowColumn(size_t row, size_t column);
-
- // redraw all lines in the specified range (inclusive)
- virtual void RefreshRows(size_t from, size_t to);
- virtual void RefreshColumns(size_t from, size_t to);
- virtual void RefreshRowsColumns(size_t fromRow, size_t toRow,
- size_t fromColumn, size_t toColumn);
-
- // return the horizontal and vertical line within a wxPoint at the
- // specified (in physical coordinates) position or.
-
- // wxNOT_FOUND in either or both axes if no line is present at the
- // requested coordinates, i.e. if it is past the last lines
- wxPoint HitTest(wxCoord x, wxCoord y) const;
- wxPoint HitTest(const wxPoint& pt) const { return HitTest(pt.x, pt.y); }
-
- // recalculate all our parameters and redisplay all lines
- virtual void RefreshAll();
-
-
- // accessors
- // ---------
-
- // get the number of lines this window contains (previously set by
- // SetLineCount())
- size_t GetRowCount() const { return m_rowsMax; }
- size_t GetColumnCount() const { return m_columnsMax; }
- wxSize GetRowColumnCounts() const
- { return wxSize((int)m_columnsMax, (int)m_rowsMax); }
-
- // get the first currently visible line/lines
- size_t GetVisibleRowsBegin() const { return m_rowsFirst; }
- size_t GetVisibleColumnsBegin() const { return m_columnsFirst; }
- wxPoint GetVisibleBegin() const
- { return wxPoint((int)m_columnsFirst, (int)m_rowsFirst); }
-
- // get the last currently visible line/lines
- size_t GetVisibleRowsEnd() const
- { return m_rowsFirst + m_nRowsVisible; }
- size_t GetVisibleColumnsEnd() const
- { return m_columnsFirst + m_nColumnsVisible; }
- wxPoint GetVisibleEnd() const
- { return wxPoint((int)(m_columnsFirst + m_nColumnsVisible),
- (int)(m_rowsFirst + m_nRowsVisible)); }
-
- // is this line currently visible?
- bool IsRowVisible(size_t row) const
- { return row >= m_rowsFirst &&
- row < GetVisibleRowsEnd(); }
- bool IsColumnVisible(size_t column) const
- { return column >= m_columnsFirst &&
- column < GetVisibleColumnsEnd(); }
- bool IsVisible(size_t row, size_t column) const
- { return IsRowVisible(row) && IsColumnVisible(column); }
-
- // layout the children (including the sizer if needed)
- virtual bool Layout();
-
-protected:
- // these functions must be overridden in the derived class and they should
- // return the width or height of the given line in pixels
- virtual wxCoord OnGetRowHeight(size_t n) const = 0;
- virtual wxCoord OnGetColumnWidth(size_t n) const = 0;
-
- // the following functions don't need to be overridden but it may be useful
- // to do if calculating the lines widths or heights is a relatively
- // expensive operation as it gives the user code a possibility to calculate
- // several of them at once
- //
- // OnGetRowsHeightHint() and OnGetColumnsWidthHint() are normally called
- // just before OnGetRowHeight() and OnGetColumnWidth(), respectively, but
- // you shouldn't rely on the latter methods being called for all lines in
- // the interval specified here. It is also possible that OnGetRowHeight()
- // or OnGetColumnWidth() will be called for the lines outside of this
- // interval, so this is really just a hint, not a promise.
- //
- // finally note that min is inclusive, while max is exclusive, as usual
- virtual void OnGetRowsHeightHint(size_t WXUNUSED(rowMin),
- size_t WXUNUSED(rowMax)) const { }
- virtual void OnGetColumnsWidthHint(size_t WXUNUSED(columnMin),
- size_t WXUNUSED(columnMax)) const { }
-
- // when the number of lines changes, we try to estimate the total width or
- // height of all lines which is a rather expensive operation in terms of
- // lines access, so if the user code may estimate the average height
- // better/faster than we do, it should override this function to implement
- // its own logic
- //
- // this function should return the best guess for the total height it may
- // make
- virtual wxCoord EstimateTotalHeight() const;
- virtual wxCoord EstimateTotalWidth() const;
-
- // the event handlers
- void OnSize(wxSizeEvent& event);
- void OnScroll(wxScrollWinEvent& event);
-#if wxUSE_MOUSEWHEEL
- void OnMouseWheel(wxMouseEvent& event);
-#endif
-
-
- // find the index of the horizontal line we need to show at the top of the
- // window such that the last (fully or partially) visible line is the given
- // one
- size_t FindFirstFromRight(size_t columnLast, bool fullyVisible = false);
-
- // find the index of the vertical line we need to show at the top of the
- // window such that the last (fully or partially) visible line is the given
- // one
- size_t FindFirstFromBottom(size_t rowLast, bool fullyVisible = false);
-
-
- // get the total width or height of the lines between lineMin (inclusive)
- // and lineMax (exclusive)
- wxCoord GetRowsHeight(size_t rowMin, size_t rowMax) const;
- wxCoord GetColumnsWidth(size_t columnMin, size_t columnMax) const;
-
- // update the thumb size shown by the scrollbar
- void UpdateScrollbars();
-
- // shifts the specified dc by the scroll position
- void PrepareDC(wxDC& dc);
-
-private:
- // common part of all ctors
- void Init();
-
-
- // the total number of (logical) lines for each axis
- size_t m_rowsMax;
- size_t m_columnsMax;
-
- // the total (estimated) height
- wxCoord m_heightTotal;
-
- // the total (estimated) width
- wxCoord m_widthTotal;
-
- // the first currently visible line on each axis
- size_t m_rowsFirst;
- size_t m_columnsFirst;
-
- // the number of currently visible lines for each axis (including the last,
- // possibly only partly, visible one)
- size_t m_nRowsVisible;
- size_t m_nColumnsVisible;
-
- // accumulated mouse wheel rotation
-#if wxUSE_MOUSEWHEEL
- int m_sumWheelRotation;
-#endif
-
- // do child scrolling (used in DoPrepareDC())
- bool m_physicalScrolling;
-
- DECLARE_EVENT_TABLE()
- DECLARE_NO_COPY_CLASS(wxHVScrolledWindow)
- DECLARE_ABSTRACT_CLASS(wxHVScrolledWindow)
-};
-
#endif // _WX_VSCROLL_H_
// Name: src/generic/vscroll.cpp
// Purpose: wxVScrolledWindow implementation
// Author: Vadim Zeitlin
-// Modified by: Brad Anderson
+// Modified by:
// Created: 30.05.03
// RCS-ID: $Id$
// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
#endif
#include "wx/vscroll.h"
-#include "wx/sizer.h"
-#include "wx/dc.h"
// ----------------------------------------------------------------------------
// event tables
Refresh();
}
-bool wxVScrolledWindow::Layout()
-{
- if(GetSizer())
- {
- // adjust the sizer dimensions/position taking into account the
- // virtual size and scrolled position of the window.
-
- int y, w, h; // x is always 0 so no variable needed
-
- y = -GetLinesHeight(0, GetFirstVisibleLine());
- GetVirtualSize(&w, &h);
- GetSizer()->SetDimension(0, y, w, h);
- return true;
- }
-
- // fall back to default for LayoutConstraints
- return wxPanel::Layout();
-}
-
int wxVScrolledWindow::HitTest(wxCoord WXUNUSED(x), wxCoord y) const
{
const size_t lineMax = GetVisibleEnd();
// remember the currently shown lines for the refresh code below
- size_t lineFirstOld = GetVisibleBegin();
+ size_t lineFirstOld = GetVisibleBegin(),
+ lineLastOld = GetVisibleEnd();
m_lineFirst = line;
// the size of scrollbar thumb could have changed
UpdateScrollbar();
- // finally, scroll the actual window
- ScrollWindow(0, GetLinesHeight(GetVisibleBegin(), lineFirstOld));
+
+ // finally refresh the display -- but only redraw as few lines as possible
+ // to avoid flicker
+ if ( GetVisibleBegin() >= lineLastOld ||
+ GetVisibleEnd() <= lineFirstOld )
+ {
+ // the simplest case: we don't have any old lines left, just redraw
+ // everything
+ Refresh();
+ }
+ else // overlap between the lines we showed before and should show now
+ {
+ ScrollWindow(0, GetLinesHeight(GetVisibleBegin(), lineFirstOld));
+ }
return true;
}
ScrollPages( units_to_scroll );
}
-#endif
-
-
-
-
-// ----------------------------------------------------------------------------
-// wxVarScrolled Window event tables
-// ----------------------------------------------------------------------------
-
-BEGIN_EVENT_TABLE(wxHVScrolledWindow, wxPanel)
- EVT_SIZE(wxHVScrolledWindow::OnSize)
- EVT_SCROLLWIN(wxHVScrolledWindow::OnScroll)
-#if wxUSE_MOUSEWHEEL
- EVT_MOUSEWHEEL(wxHVScrolledWindow::OnMouseWheel)
-#endif
-END_EVENT_TABLE()
-
-
-// ============================================================================
-// wxVarScrolled implementation
-// ============================================================================
-
-IMPLEMENT_ABSTRACT_CLASS(wxHVScrolledWindow, wxPanel)
-
-// ----------------------------------------------------------------------------
-// initialization
-// ----------------------------------------------------------------------------
-
-void wxHVScrolledWindow::Init()
-{
- // we're initially empty
- m_rowsMax =
- m_columnsMax =
- m_rowsFirst =
- m_columnsFirst = 0;
-
- // these should always be strictly positive
- m_nRowsVisible =
- m_nColumnsVisible = 1;
-
- m_widthTotal =
- m_heightTotal = 0;
-
- m_physicalScrolling = true;
-
-#if wxUSE_MOUSEWHEEL
- m_sumWheelRotation = 0;
-#endif
-}
-
-// ----------------------------------------------------------------------------
-// various helpers
-// ----------------------------------------------------------------------------
-
-wxCoord wxHVScrolledWindow::EstimateTotalHeight() const
-{
- // estimate the total height: it is impossible to call
- // OnGetLineHeight() for every line because there may be too many of
- // them, so we just make a guess using some lines in the beginning,
- // some in the end and some in the middle
- static const size_t NUM_LINES_TO_SAMPLE = 10;
-
- wxCoord heightTotal;
- if ( m_rowsMax < 3*NUM_LINES_TO_SAMPLE )
- {
- // in this case calculating exactly is faster and more correct than
- // guessing
- heightTotal = GetRowsHeight(0, m_rowsMax);
- }
- else // too many lines to calculate exactly
- {
- // look at some lines in the beginning/middle/end
- heightTotal =
- GetRowsHeight(0, NUM_LINES_TO_SAMPLE) +
- GetRowsHeight(m_rowsMax - NUM_LINES_TO_SAMPLE,
- m_rowsMax) +
- GetRowsHeight(m_rowsMax/2 - NUM_LINES_TO_SAMPLE/2,
- m_rowsMax/2 + NUM_LINES_TO_SAMPLE/2);
-
- // use the height of the lines we looked as the average
- heightTotal = (wxCoord)
- (((float)heightTotal / (3*NUM_LINES_TO_SAMPLE)) * m_rowsMax);
- }
-
- return heightTotal;
-}
-
-wxCoord wxHVScrolledWindow::EstimateTotalWidth() const
-{
- // estimate the total width: it is impossible to call
- // OnGetLineWidth() for every line because there may be too many of
- // them, so we just make a guess using some lines in the beginning,
- // some in the end and some in the middle
- static const size_t NUM_LINES_TO_SAMPLE = 10;
-
- wxCoord widthTotal;
- if ( m_columnsMax < 3*NUM_LINES_TO_SAMPLE )
- {
- // in this case calculating exactly is faster and more correct than
- // guessing
- widthTotal = GetColumnsWidth(0, m_columnsMax);
- }
- else // too many lines to calculate exactly
- {
- // look at some lines in the beginning/middle/end
- widthTotal =
- GetColumnsWidth(0, NUM_LINES_TO_SAMPLE) +
- GetColumnsWidth(m_columnsMax - NUM_LINES_TO_SAMPLE,
- m_columnsMax) +
- GetColumnsWidth(m_columnsMax/2 - NUM_LINES_TO_SAMPLE/2,
- m_columnsMax/2 + NUM_LINES_TO_SAMPLE/2);
-
- // use the width of the lines we looked as the average
- widthTotal = (wxCoord)
- (((float)widthTotal / (3*NUM_LINES_TO_SAMPLE)) * m_columnsMax);
- }
-
- return widthTotal;
-}
-
-wxCoord wxHVScrolledWindow::GetRowsHeight(size_t rowMin, size_t rowMax) const
-{
- if ( rowMin == rowMax )
- return 0;
- else if ( rowMin > rowMax )
- return -GetRowsHeight(rowMax, rowMin);
- //else: lineMin < lineMax
-
- // let the user code know that we're going to need all these lines
- OnGetRowsHeightHint(rowMin, rowMax);
-
- // do sum up their heights
- wxCoord height = 0;
- for ( size_t row = rowMin; row < rowMax; row++ )
- {
- height += OnGetRowHeight(row);
- }
-
- return height;
-}
-
-wxCoord wxHVScrolledWindow::GetColumnsWidth(size_t columnMin, size_t columnMax) const
-{
- if ( columnMin == columnMax )
- return 0;
- else if ( columnMin > columnMax )
- return -GetColumnsWidth(columnMax, columnMin);
- //else: lineMin < lineMax
-
- // let the user code know that we're going to need all these lines
- OnGetColumnsWidthHint(columnMin, columnMax);
-
- // do sum up their widths
- wxCoord width = 0;
- for ( size_t column = columnMin; column < columnMax; column++ )
- {
- width += OnGetColumnWidth(column);
- }
-
- return width;
-}
-
-size_t wxHVScrolledWindow::FindFirstFromBottom(size_t rowLast, bool full)
-{
- const wxCoord hWindow = GetClientSize().y;
-
- // go upwards until we arrive at a line such that lineLast is not visible
- // any more when it is shown
- size_t lineFirst = rowLast;
- wxCoord h = 0;
- for ( ;; )
- {
- h += OnGetRowHeight(lineFirst);
-
- if ( h > hWindow )
- {
- // for this line to be fully visible we need to go one line
- // down, but if it is enough for it to be only partly visible then
- // this line will do as well
- if ( full )
- {
- lineFirst++;
- }
-
- break;
- }
-
- if ( !lineFirst )
- break;
-
- lineFirst--;
- }
-
- return lineFirst;
-}
-
-size_t wxHVScrolledWindow::FindFirstFromRight(size_t columnLast, bool full)
-{
- const wxCoord wWindow = GetClientSize().x;
-
- // go upwards until we arrive at a line such that lineLast is not visible
- // any more when it is shown
- size_t lineFirst = columnLast;
- wxCoord w = 0;
- for ( ;; )
- {
- w += OnGetColumnWidth(lineFirst);
-
- if ( w > wWindow )
- {
- // for this line to be fully visible we need to go one line
- // down, but if it is enough for it to be only partly visible then
- // this line will do as well
- if ( full )
- {
- lineFirst++;
- }
-
- break;
- }
-
- if ( !lineFirst )
- break;
-
- lineFirst--;
- }
-
- return lineFirst;
-}
-
-void wxHVScrolledWindow::UpdateScrollbars()
-{
- // see how many lines can we fit on screen (on both axes)
- const wxCoord wWindow = GetClientSize().x;
- const wxCoord hWindow = GetClientSize().y;
-
- // first do the horizontal calculations
- wxCoord w = 0;
- size_t column;
- for ( column = m_columnsFirst; column < m_columnsMax; column++ )
- {
- if ( w > wWindow )
- break;
-
- w += OnGetColumnWidth(column);
- }
-
- m_nColumnsVisible = column - m_columnsFirst;
-
- int columnsPageSize = m_nColumnsVisible;
- if ( w > wWindow )
- {
- // last line is only partially visible, we still need the scrollbar and
- // so we have to "fix" pageSize because if it is equal to
- // m_horizLineMax the scrollbar is not shown at all under MSW
- columnsPageSize--;
- }
-
- // set the scrollbar parameters to reflect this
- SetScrollbar(wxHORIZONTAL, m_columnsFirst, columnsPageSize, m_columnsMax);
-
-
- // now do the vertical calculations
- wxCoord h = 0;
- size_t row;
- for ( row = m_rowsFirst; row < m_rowsMax; row++ )
- {
- if ( h > hWindow )
- break;
-
- h += OnGetRowHeight(row);
- }
-
- m_nRowsVisible = row - m_rowsFirst;
-
- int rowsPageSize = m_nRowsVisible;
- if ( h > hWindow )
- {
- // last line is only partially visible, we still need the scrollbar and
- // so we have to "fix" pageSize because if it is equal to m_vertLineMax
- // the scrollbar is not shown at all under MSW
- rowsPageSize--;
- }
-
- // set the scrollbar parameters to reflect this
- SetScrollbar(wxVERTICAL, m_rowsFirst, rowsPageSize, m_rowsMax);
-}
-
-void wxHVScrolledWindow::PrepareDC(wxDC& dc)
-{
- if(m_physicalScrolling)
- {
- dc.SetDeviceOrigin(-GetColumnsWidth(0, GetVisibleColumnsBegin()),
- -GetRowsHeight(0, GetVisibleRowsBegin()));
- }
-}
-
-// ----------------------------------------------------------------------------
-// operations
-// ----------------------------------------------------------------------------
-
-void wxHVScrolledWindow::SetRowColumnCounts(size_t rowCount, size_t columnCount)
-{
- // save the number of lines
- m_rowsMax = rowCount;
- m_columnsMax = columnCount;
-
- // and our estimate for their total height and width
- m_heightTotal = EstimateTotalHeight();
- m_widthTotal = EstimateTotalWidth();
-
- // recalculate the scrollbars parameters
- if(m_rowsFirst >= rowCount)
- m_rowsFirst = (rowCount > 0) ? rowCount - 1 : 0;
-
- if(m_columnsFirst >= columnCount)
- m_columnsFirst = (columnCount > 0) ? columnCount - 1 : 0;
-
-#if 0
- // checks disabled due to size_t type of members
- // but leave them here if anyone would want to do some debugging
- if(m_rowsFirst < 0)
- m_rowsFirst = 0;
-
- if(m_columnsFirst < 0)
- m_columnsFirst = 0;
-#endif
-
- ScrollToRowColumn(m_rowsFirst, m_columnsFirst);
-}
-
-void wxHVScrolledWindow::RefreshColumn(size_t column)
-{
- // is this line visible?
- if ( !IsColumnVisible(column) )
- {
- // no, it is useless to do anything
- return;
- }
-
- // calculate the rect occupied by this line on screen
- wxRect rect;
- rect.width = OnGetColumnWidth(column);
- rect.height = GetClientSize().y;
- for ( size_t n = GetVisibleColumnsBegin(); n < column; n++ )
- {
- rect.y += OnGetColumnWidth(n);
- }
-
- // do refresh it
- RefreshRect(rect);
-}
-
-void wxHVScrolledWindow::RefreshRow(size_t row)
-{
- // is this line visible?
- if ( !IsRowVisible(row) )
- {
- // no, it is useless to do anything
- return;
- }
-
- // calculate the rect occupied by this line on screen
- wxRect rect;
- rect.width = GetClientSize().x;
- rect.height = OnGetRowHeight(row);
- for ( size_t n = GetVisibleRowsBegin(); n < row; n++ )
- {
- rect.y += OnGetRowHeight(n);
- }
+#endif // wxUSE_MOUSEWHEEL
- // do refresh it
- RefreshRect(rect);
-}
-
-void wxHVScrolledWindow::RefreshRowColumn(size_t row, size_t column)
-{
- // is this line visible?
- if ( !IsRowVisible(row) || !IsColumnVisible(column) )
- {
- // no, it is useless to do anything
- return;
- }
-
- // calculate the rect occupied by this cell on screen
- wxRect rect;
- rect.height = OnGetRowHeight(row);
- rect.width = OnGetColumnWidth(column);
-
- size_t n;
-
- for ( n = GetVisibleRowsBegin(); n < row; n++ )
- {
- rect.y += OnGetRowHeight(n);
- }
-
- for ( n = GetVisibleColumnsBegin(); n < column; n++ )
- {
- rect.x += OnGetColumnWidth(n);
- }
-
- // do refresh it
- RefreshRect(rect);
-}
-
-void wxHVScrolledWindow::RefreshRows(size_t from, size_t to)
-{
- wxASSERT_MSG( from <= to, _T("RefreshRows(): empty range") );
-
- // clump the range to just the visible lines -- it is useless to refresh
- // the other ones
- if ( from < GetVisibleRowsBegin() )
- from = GetVisibleRowsBegin();
-
- if ( to > GetVisibleRowsEnd() )
- to = GetVisibleRowsEnd();
-
- // calculate the rect occupied by these lines on screen
- wxRect rect;
- rect.width = GetClientSize().x;
- for ( size_t nBefore = GetVisibleRowsBegin();
- nBefore < from;
- nBefore++ )
- {
- rect.y += OnGetRowHeight(nBefore);
- }
-
- for ( size_t nBetween = from; nBetween <= to; nBetween++ )
- {
- rect.height += OnGetRowHeight(nBetween);
- }
-
- // do refresh it
- RefreshRect(rect);
-}
-
-void wxHVScrolledWindow::RefreshColumns(size_t from, size_t to)
-{
- wxASSERT_MSG( from <= to, _T("RefreshColumns(): empty range") );
-
- // clump the range to just the visible lines -- it is useless to refresh
- // the other ones
- if ( from < GetVisibleColumnsBegin() )
- from = GetVisibleColumnsBegin();
-
- if ( to > GetVisibleColumnsEnd() )
- to = GetVisibleColumnsEnd();
-
- // calculate the rect occupied by these lines on screen
- wxRect rect;
- rect.height = GetClientSize().y;
- for ( size_t nBefore = GetVisibleColumnsBegin();
- nBefore < from;
- nBefore++ )
- {
- rect.x += OnGetColumnWidth(nBefore);
- }
-
- for ( size_t nBetween = from; nBetween <= to; nBetween++ )
- {
- rect.width += OnGetColumnWidth(nBetween);
- }
-
- // do refresh it
- RefreshRect(rect);
-}
-
-void wxHVScrolledWindow::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 lines -- 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 lines on screen
- wxRect rect;
- size_t nBefore, nBetween;
-
- for ( nBefore = GetVisibleRowsBegin();
- nBefore < fromRow;
- nBefore++ )
- {
- rect.y += OnGetRowHeight(nBefore);
- }
-
- for ( nBetween = fromRow; nBetween <= toRow; nBetween++ )
- {
- rect.height += OnGetRowHeight(nBetween);
- }
-
- for ( nBefore = GetVisibleColumnsBegin();
- nBefore < fromColumn;
- nBefore++ )
- {
- rect.x += OnGetColumnWidth(nBefore);
- }
-
- for ( nBetween = fromColumn; nBetween <= toColumn; nBetween++ )
- {
- rect.width += OnGetColumnWidth(nBetween);
- }
-
- // do refresh it
- RefreshRect(rect);
-}
-
-void wxHVScrolledWindow::RefreshAll()
-{
- UpdateScrollbars();
-
- Refresh();
-}
-
-bool wxHVScrolledWindow::Layout()
-{
- if(GetSizer() && m_physicalScrolling)
- {
- // adjust the sizer dimensions/position taking into account the
- // virtual size and scrolled position of the window.
-
- int x, y, w, h;
-
- y = -GetRowsHeight(0, GetVisibleRowsBegin());
- x = -GetColumnsWidth(0, GetVisibleColumnsBegin());
- GetVirtualSize(&w, &h);
- GetSizer()->SetDimension(x, y, w, h);
- return true;
- }
-
- // fall back to default for LayoutConstraints
- return wxPanel::Layout();
-}
-
-wxPoint wxHVScrolledWindow::HitTest(wxCoord x, wxCoord y) const
-{
- const size_t rowMax = GetVisibleRowsEnd();
- const size_t columnMax = GetVisibleColumnsEnd();
-
- wxPoint hit(wxNOT_FOUND, wxNOT_FOUND);
- for ( size_t row = GetVisibleRowsBegin();
- row <= rowMax;
- row++ )
- {
- y -= OnGetRowHeight(row);
- if ( y < 0 )
- hit.y = row;
- }
-
- for ( size_t column = GetVisibleColumnsBegin();
- column <= columnMax;
- column++ )
- {
- x -= OnGetColumnWidth(column);
- if ( x < 0 )
- hit.x = column;
- }
-
- return hit;
-}
-
-// ----------------------------------------------------------------------------
-// scrolling
-// ----------------------------------------------------------------------------
-
-bool wxHVScrolledWindow::ScrollToRowColumn(size_t row, size_t column)
-{
- if ( !m_rowsMax && !m_columnsMax )
- {
- // we're empty, code below doesn't make sense in this case
- return false;
- }
-
- bool scrolled = false;
- scrolled |= ScrollToRow(row);
- scrolled |= ScrollToColumn(column);
-
- return scrolled;
-}
-
-bool wxHVScrolledWindow::ScrollToRow(size_t row)
-{
- if ( !m_rowsMax )
- {
- // we're empty, code below doesn't make sense in this case
- return false;
- }
-
- // determine the real first line to scroll to: we shouldn't scroll beyond
- // the end
- size_t lineFirstLast = FindFirstFromBottom(m_rowsMax - 1, true);
- if ( row > lineFirstLast )
- row = lineFirstLast;
-
- // anything to do?
- if ( row == m_rowsFirst )
- {
- // no
- return false;
- }
-
-
- // remember the currently shown lines for the refresh code below
- size_t lineFirstOld = GetVisibleRowsBegin();
-
- m_rowsFirst = row;
-
-
- // the size of scrollbar thumb could have changed
- UpdateScrollbars();
-
-
- // finally, scroll the actual window contents vertically
- if(m_physicalScrolling)
- ScrollWindow(0, GetRowsHeight(GetVisibleRowsBegin(), lineFirstOld));
-
- return true;
-}
-
-bool wxHVScrolledWindow::ScrollToColumn(size_t column)
-{
- if ( !m_columnsMax )
- {
- // we're empty, code below doesn't make sense in this case
- return false;
- }
-
- // determine the real first line to scroll to: we shouldn't scroll beyond
- // the end
- size_t lineFirstLast = FindFirstFromRight(m_columnsMax - 1, true);
- if ( column > lineFirstLast )
- column = lineFirstLast;
-
- // anything to do?
- if ( column == m_columnsFirst )
- {
- // no
- return false;
- }
-
-
- // remember the currently shown lines for the refresh code below
- size_t lineFirstOld = GetVisibleColumnsBegin();
-
- m_columnsFirst = column;
-
-
- // the size of scrollbar thumb could have changed
- UpdateScrollbars();
-
- // finally, scroll the actual window contents horizontally
- if(m_physicalScrolling)
- ScrollWindow(GetColumnsWidth(GetVisibleColumnsBegin(), lineFirstOld), 0);
-
- return true;
-}
-
-bool wxHVScrolledWindow::ScrollRows(int rows)
-{
- rows += m_rowsFirst;
- if ( rows < 0 )
- rows = 0;
-
- return ScrollToRow(rows);
-}
-
-bool wxHVScrolledWindow::ScrollColumns(int columns)
-{
- columns += m_columnsFirst;
- if ( columns < 0 )
- columns = 0;
-
- return ScrollToColumn(columns);
-}
-
-bool wxHVScrolledWindow::ScrollRowsColumns(int rows, int columns)
-{
- rows += m_rowsFirst;
- if ( rows < 0 )
- rows = 0;
-
- columns += m_columnsFirst;
- if ( columns < 0 )
- columns = 0;
-
- return ScrollToRowColumn(rows, columns);
-}
-
-bool wxHVScrolledWindow::ScrollRowPages(int pages)
-{
- bool didSomething = false;
-
- while ( pages )
- {
- int line;
- if ( pages > 0 )
- {
- line = GetVisibleRowsEnd();
- if ( line )
- line--;
- pages--;
- }
- else // pages < 0
- {
- line = FindFirstFromBottom(GetVisibleRowsEnd());
- pages++;
- }
-
- didSomething = ScrollToRow(line);
- }
-
- return didSomething;
-}
-
-bool wxHVScrolledWindow::ScrollColumnPages(int pages)
-{
- bool didSomething = false;
-
- while ( pages )
- {
- int line;
- if ( pages > 0 )
- {
- line = GetVisibleColumnsEnd();
- if ( line )
- line--;
- pages--;
- }
- else // pages < 0
- {
- line = FindFirstFromRight(GetVisibleColumnsEnd());
- pages++;
- }
-
- didSomething = ScrollToColumn(line);
- }
-
- return didSomething;
-}
-
-bool wxHVScrolledWindow::ScrollPages(int rowPages, int columnPages)
-{
- bool didSomething = false;
-
- while ( rowPages )
- {
- int line;
- if ( rowPages > 0 )
- {
- line = GetVisibleRowsEnd();
- if ( line )
- line--;
- rowPages--;
- }
- else // rowPages < 0
- {
- line = FindFirstFromBottom(GetVisibleRowsBegin());
- rowPages++;
- }
-
- didSomething = ScrollToRow(line);
- }
-
- while ( columnPages )
- {
- int line;
- if ( columnPages > 0 )
- {
- line = GetVisibleColumnsEnd();
- if ( line )
- line--;
- columnPages--;
- }
- else // columnPages < 0
- {
- line = FindFirstFromRight(GetVisibleColumnsBegin());
- columnPages++;
- }
-
- didSomething |= ScrollToColumn(line);
- }
-
- return didSomething;
-}
-
-// ----------------------------------------------------------------------------
-// event handling
-// ----------------------------------------------------------------------------
-
-void wxHVScrolledWindow::OnSize(wxSizeEvent& event)
-{
- UpdateScrollbars();
- Layout();
-
- event.Skip();
-}
-
-void wxHVScrolledWindow::OnScroll(wxScrollWinEvent& event)
-{
- if(event.GetOrientation() == wxHORIZONTAL)
- {
- size_t columnsFirstNew;
- const wxEventType evtType = event.GetEventType();
-
- if ( evtType == wxEVT_SCROLLWIN_TOP )
- {
- columnsFirstNew = 0;
- }
- else if ( evtType == wxEVT_SCROLLWIN_BOTTOM )
- {
- columnsFirstNew = m_columnsMax;
- }
- else if ( evtType == wxEVT_SCROLLWIN_LINEUP )
- {
- columnsFirstNew = m_columnsFirst ? m_columnsFirst - 1 : 0;
- }
- else if ( evtType == wxEVT_SCROLLWIN_LINEDOWN )
- {
- columnsFirstNew = m_columnsFirst + 1;
- }
- else if ( evtType == wxEVT_SCROLLWIN_PAGEUP )
- {
- columnsFirstNew = FindFirstFromRight(m_columnsFirst);
- }
- else if ( evtType == wxEVT_SCROLLWIN_PAGEDOWN )
- {
- columnsFirstNew = GetVisibleColumnsEnd();
- if ( columnsFirstNew )
- columnsFirstNew--;
- }
- else if ( evtType == wxEVT_SCROLLWIN_THUMBRELEASE )
- {
- columnsFirstNew = event.GetPosition();
- }
- else if ( evtType == wxEVT_SCROLLWIN_THUMBTRACK )
- {
- columnsFirstNew = event.GetPosition();
- }
-
- else // unknown scroll event?
- {
- wxFAIL_MSG( _T("unknown scroll event type?") );
- return;
- }
-
- ScrollToColumn(columnsFirstNew);
- }
- else if(event.GetOrientation() == wxVERTICAL)
- {
- size_t rowsFirstNew;
- const wxEventType evtType = event.GetEventType();
-
- if ( evtType == wxEVT_SCROLLWIN_TOP )
- {
- rowsFirstNew = 0;
- }
- else if ( evtType == wxEVT_SCROLLWIN_BOTTOM )
- {
- rowsFirstNew = m_rowsMax;
- }
- else if ( evtType == wxEVT_SCROLLWIN_LINEUP )
- {
- rowsFirstNew = m_rowsFirst ? m_rowsFirst - 1 : 0;
- }
- else if ( evtType == wxEVT_SCROLLWIN_LINEDOWN )
- {
- rowsFirstNew = m_rowsFirst + 1;
- }
- else if ( evtType == wxEVT_SCROLLWIN_PAGEUP )
- {
- rowsFirstNew = FindFirstFromBottom(m_rowsFirst);
- }
- else if ( evtType == wxEVT_SCROLLWIN_PAGEDOWN )
- {
- rowsFirstNew = GetVisibleRowsEnd();
- if ( rowsFirstNew )
- rowsFirstNew--;
- }
- else if ( evtType == wxEVT_SCROLLWIN_THUMBRELEASE )
- {
- rowsFirstNew = event.GetPosition();
- }
- else if ( evtType == wxEVT_SCROLLWIN_THUMBTRACK )
- {
- rowsFirstNew = event.GetPosition();
- }
-
- else // unknown scroll event?
- {
- wxFAIL_MSG( _T("unknown scroll event type?") );
- return;
- }
-
- ScrollToRow(rowsFirstNew);
- }
-
-
-#ifdef __WXMAC__
- Update();
-#endif // __WXMAC__
-}
-
-#if wxUSE_MOUSEWHEEL
-
-void wxHVScrolledWindow::OnMouseWheel(wxMouseEvent& event)
-{
- 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() )
- ScrollRows( units_to_scroll*event.GetLinesPerAction() );
- else
- // scroll pages instead of lines
- ScrollRowPages( units_to_scroll );
-}
-
-#endif