From 234b1c01470c3e88931f97bb7ed4fdceead196bf Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 14 Apr 2006 15:55:28 +0000 Subject: [PATCH] reverted wxHVScrolledWindow patch (rev 1.19/1.21 of vscroll.h/.cpp) because not only we don't want to duplicate code like this but it also broke wxHtmlListBox by making scrolling in it O(N) instead of O(1) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38715 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/vscroll.h | 269 +---------- src/generic/vscroll.cpp | 978 +--------------------------------------- 2 files changed, 19 insertions(+), 1228 deletions(-) diff --git a/include/wx/vscroll.h b/include/wx/vscroll.h index bead562926..b24615f27e 100644 --- a/include/wx/vscroll.h +++ b/include/wx/vscroll.h @@ -2,7 +2,7 @@ // 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 @@ -135,8 +135,6 @@ public: // 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 @@ -216,270 +214,5 @@ private: 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_ diff --git a/src/generic/vscroll.cpp b/src/generic/vscroll.cpp index cee98cef45..083e26c801 100644 --- a/src/generic/vscroll.cpp +++ b/src/generic/vscroll.cpp @@ -2,7 +2,7 @@ // 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 @@ -25,8 +25,6 @@ #endif #include "wx/vscroll.h" -#include "wx/sizer.h" -#include "wx/dc.h" // ---------------------------------------------------------------------------- // event tables @@ -265,25 +263,6 @@ void wxVScrolledWindow::RefreshAll() 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(); @@ -324,7 +303,8 @@ bool wxVScrolledWindow::ScrollToLine(size_t line) // remember the currently shown lines for the refresh code below - size_t lineFirstOld = GetVisibleBegin(); + size_t lineFirstOld = GetVisibleBegin(), + lineLastOld = GetVisibleEnd(); m_lineFirst = line; @@ -332,8 +312,20 @@ bool wxVScrolledWindow::ScrollToLine(size_t 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; } @@ -459,939 +451,5 @@ void wxVScrolledWindow::OnMouseWheel(wxMouseEvent& event) 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 -- 2.45.2