From d77836e48cf1a0f7575cd1ce66f59f5bc07e5b56 Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Wed, 15 Feb 2006 09:59:39 +0000 Subject: [PATCH] Applied wxVScrolledWindow patch git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37591 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/classes.tex | 1 + docs/latex/wx/hvscroll.tex | 557 +++++++++++++++++++++ docs/latex/wx/vscroll.tex | 2 +- include/wx/vscroll.h | 269 +++++++++- samples/vscroll/vstest.cpp | 249 ++++++++-- src/generic/vscroll.cpp | 970 ++++++++++++++++++++++++++++++++++++- 6 files changed, 1998 insertions(+), 50 deletions(-) create mode 100644 docs/latex/wx/hvscroll.tex diff --git a/docs/latex/wx/classes.tex b/docs/latex/wx/classes.tex index 0deb6b639e..54f94379d5 100644 --- a/docs/latex/wx/classes.tex +++ b/docs/latex/wx/classes.tex @@ -179,6 +179,7 @@ \input htwinprs.tex \input htwinhnd.tex \input http.tex +\input hvscroll.tex \input icon.tex \input iconbndl.tex \input iconloc.tex diff --git a/docs/latex/wx/hvscroll.tex b/docs/latex/wx/hvscroll.tex new file mode 100644 index 0000000000..b75501923c --- /dev/null +++ b/docs/latex/wx/hvscroll.tex @@ -0,0 +1,557 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Name: hvscroll.tex +%% Purpose: wxHVScrolledWindow documentation +%% Author: Vadim Zeitlin +%% Modified by: Brad Anderson +%% Created: 24.01.06 +%% RCS-ID: $Id$ +%% Copyright: (c) 2003 Vadim Zeitlin +%% License: wxWindows license +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{\class{wxHVScrolledWindow}}\label{wxhvscrolledwindow} + +This class is strongly influenced by +\helpref{wxVScrolledWindow}{wxvscrolledwindow}. +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 row widths and column heights +only need to be known for the rows and columns that are currently visible. + +Like \helpref{wxVScrolledWindow}{wxvscrolledwindow}, this is a generalization +of the \helpref{wxScrolledWindow}{wxscrolledwindow} class which can be only +used when all rows have a constant height and columns have a constant width. +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. + +There is no wxHScrolledWindow but horizontal-only scrolling is implemented +easily enough with this class. + +To use this class, you need to derive from it and implement both the +\helpref{OnGetRowHeight()}{wxhvscrolledwindowongetrowheight} and the +\helpref{OnGetColumnWidth()}{wxhvscrolledwindowongetcolumnwidth} pure virtual +methods. You also must call +\helpref{SetRowColumnCounts}{wxhvscrolledwindowsetrowcolumncounts} to let the +base class know how many rows and columns it should display. After these +requirements are met scrolling is handled entirely by wxHVScrolledWindow. You +only need to draw the visible part of contents in your {\tt OnPaint()} method +as usual. You should use +\helpref{GetVisibleRowsBegin()}{wxhvscrolledwindowgetvisiblerowsbegin}, +\helpref{GetVisibleColumnsBegin()}{wxhvscrolledwindowgetvisiblecolumnsbegin}, +\helpref{GetVisibleRowsEnd()}{wxhvscrolledwindowgetvisiblerowsend}, and +\helpref{GetVisibleColumnsEnd()}{wxhvscrolledwindowgetvisiblecolumnsend} to +determine which lines to to display. If physical scrolling is enabled the +device context origin is shifted by the scroll position (through +{\tt PrepareDC()}), child windows are moved as the window scrolls, and the +pixels on the screen are moved to minimize the region that requires painting. +Physical scrolling is enabled by default. + +\wxheading{Derived from} + +\helpref{wxPanel}{wxpanel} + +\wxheading{Include files} + + + + +\latexignore{\rtfignore{\wxheading{Members}}} + + +\membersection{wxHVScrolledWindow::wxHVScrolledWindow}\label{wxhvscrolledwindowctor} + +\func{}{wxHVScrolledWindow}{\param{wxWindow* }{parent}, \param{wxWindowID }{id = wxID\_ANY}, \param{const wxPoint\& }{pos = wxDefaultPosition}, \param{const wxSize\& }{size = wxDefaultSize}, \param{long }{style = 0}, \param{const wxString\& }{name = wxPanelNameStr}} + +This is the normal constructor, no need to call Create() after using this one. + +Note that {\tt wxVSCROLL} and {\tt wxHSCROLL} are always automatically added to +our style, there is no need to specify them explicitly. + +\func{}{wxHVScrolledWindow}{\void} + +Default constructor, you must call \helpref{Create()}{wxhvscrolledwindowcreate} +later. + +\wxheading{Parameters} + +\docparam{parent}{The parent window, must not be {\tt NULL}} + +\docparam{id}{The identifier of this window, {\tt wxID\_ANY} by default} + +\docparam{pos}{The initial window position} + +\docparam{size}{The initial window size} + +\docparam{style}{The window style. There are no special style bits defined for +this class.} + +\docparam{name}{The name for this window; usually not used} + + +\membersection{wxHVScrolledWindow::Create}\label{wxhvscrolledwindowcreate} + +\func{bool}{Create}{\param{wxWindow* }{parent}, \param{wxWindowID }{id = wxID\_ANY}, \param{const wxPoint\& }{pos = wxDefaultPosition}, \param{const wxSize\& }{size = wxDefaultSize}, \param{long }{style = 0}, \param{const wxString\& }{name = wxPanelNameStr}} + +Same as the \helpref{non default ctor}{wxhvscrolledwindowctor} but returns +status code: {\tt true} if ok, {\tt false} if the window couldn't have been created. + +Just as with the ctor above, both the {\tt wxVSCROLL} and the {\tt wxHSCROLL} +styles are always used. There is no need to specify either explicitly. + +\membersection{wxHVScrolledWindow::EnablePhysicalScrolling}\label{wxhvscrolledwindowenablephysicalscrolling} + +\func{\void}{EnablePhysicalScrolling}{\param{bool }{scrolling = true}} + +With physical scrolling enabled the device origin is changed properly when a +wxDC is prepared using {\tt PrepareDC()}, children are actually moved and layed +out according to the current scroll position, and the contents of the window +(pixels) are actually moved to reduce the amount of redraw needed. + +Physical scrolling is enabled by default but can be disable or re-enabled at +any time. An example of when you'd want to disable it would be if you have +statically positioned graphic elements or children you do not want to move +while the window is being scrolled. If you disable physical scrolling you must +manually adjust positioning for items within the scrolled window yourself. +Also note that an unprepared wxDC requires you to do the same, regardless of +the physical scrolling state. + + +\membersection{wxHVScrolledWindow::EstimateTotalHeight}\label{wxhvscrolledwindowestimatetotalheight} + +\constfunc{virtual wxCoord}{EstimateTotalHeight}{\void} + +This protected function is used internally by wxHVScrolledWindow to estimate the +total height of the window when +\helpref{SetRowColumnCounts}{wxhvscrolledwindowsetrowcolumncounts} +is called. The default implementation uses the brute force approach if the +number of the items in the control is small enough. Otherwise, it tries to find +the average row height using some rows in the beginning, middle and the end. + +If it is undesirable to query all these rows (some of which might be never +shown) just for the total height calculation, you may override the function and +provide your own guess using a better and/or faster method. + +Note that although returning a totally wrong value would still work, it risks +causing some very strange scrollbar behaviour so this function should really +try to make the best guess possible. + + +\membersection{wxHVScrolledWindow::EstimateTotalWidth}\label{wxhvscrolledwindowestimatetotalwidth} + +\constfunc{virtual wxCoord}{EstimateTotalWidth}{\void} + +This protected function is used internally by wxHVScrolledWindow to estimate the +total width of the window when +\helpref{SetRowColumnCounts}{wxhvscrolledwindowsetrowcolumncounts} +is called. The default implementation uses the brute force approach if the +number of the items in the control is small enough. Otherwise, it tries to find +the average column width using some columns in the beginning, middle and the end. + +If it is undesirable to query all these columns (some of which might be never +shown) just for the total width calculation, you may override the function and +provide your own guess using a better and/or faster method. + +Note that although returning a totally wrong value would still work, it risks +causing some very strange scrollbar behaviour so this function should really +try to make the best guess possible. + + +\membersection{wxHVScrolledWindow::GetColumnCount}\label{wxhvscrolledwindowgetcolumncount} + +\constfunc{wxSize}{GetColumnCount}{\void} + +Get the number of columns this window contains (previously set by +\helpref{SetRowColumnCounts()}{wxhvscrolledwindowsetrowcolumncounts}) + + +\membersection{wxHVScrolledWindow::GetRowCount}\label{wxhvscrolledwindowgetrowcount} + +\constfunc{wxSize}{GetRowCount}{\void} + +Get the number of rows this window contains (previously set by +\helpref{SetRowColumnCounts()}{wxhvscrolledwindowsetrowcolumncounts}) + + +\membersection{wxHVScrolledWindow::GetRowColumnCounts}\label{wxhvscrolledwindowgetrowcolumncounts} + +\constfunc{wxSize}{GetRowColumnCounts}{\void} + +Get the number of rows (X or width) and columns (Y or height) this window +contains (previously set +by \helpref{SetRowColumnCounts()}{wxhvscrolledwindowsetrowcolumncounts}) + + +\membersection{wxHVScrolledWindow::GetVisibleBegin}\label{wxhvscrolledwindowgetvisiblebegin} + +\constfunc{wxPoint}{GetVisibleBegin}{\void} + +Returns the indicies of the first visible row (Y) and column (X). + +\wxheading{See also} + +\helpref{GetVisibleRowsBegin}{wxhvscrolledwindowgetvisiblerowsbegin}, \helpref{GetVisibleColumnsBegin}{wxhvscrolledwindowgetvisiblecolumnsbegin} + + +\membersection{wxHVScrolledWindow::GetVisibleColumnsBegin}\label{wxhvscrolledwindowgetvisiblecolumnsbegin} + +\constfunc{size\_t}{GetVisibleColumnsBegin}{\void} + +Returns the index of the first currently visible column. + +\wxheading{See also} + +\helpref{GetVisibleColumnsEnd}{wxhvscrolledwindowgetvisiblecolumnsend} + + +\membersection{wxHVScrolledWindow::GetVisibleColumnsEnd}\label{wxhvscrolledwindowgetvisiblecolumnsend} + +\constfunc{size\_t}{GetVisibleColumnsEnd}{\void} + +Returns the index of the first column after the currently visible page. If the +return value is $0$ it means that no columns are currently shown (which only +happens if the control is empty). Note that the index returned by this method +is not always a valid index as it may be equal to +\helpref{GetColumnCount}{wxhvscrolledwindowgetcolumncount}. + +\wxheading{See also} + +\helpref{GetVisibleColumnsBegin}{wxhvscrolledwindowgetvisiblecolumnsbegin} + + +\membersection{wxHVScrolledWindow::GetVisibleEnd}\label{wxhvscrolledwindowgetvisiblebegin} + +\constfunc{wxPoint}{GetVisibleEnd}{\void} + +Returns the indicies of the row and column after the last visible row (Y) and +last visible column (X), respectively. + +\wxheading{See also} + +\helpref{GetVisibleRowsEnd}{wxhvscrolledwindowgetvisiblerowsend}, \helpref{GetVisibleColumnsEnd}{wxhvscrolledwindowgetvisiblecolumnsend} + + +\membersection{wxHVScrolledWindow::GetVisibleRowsBegin}\label{wxhvscrolledwindowgetvisiblerowsbegin} + +\constfunc{size\_t}{GetVisibleRowsBegin}{\void} + +Returns the index of the first currently visible row. + +\wxheading{See also} + +\helpref{GetVisibleRowsEnd}{wxhvscrolledwindowgetvisiblerowsend} + + +\membersection{wxHVScrolledWindow::GetVisibleRowsEnd}\label{wxhvscrolledwindowgetvisiblerowsend} + +\constfunc{size\_t}{GetVisibleRowsEnd}{\void} + +Returns the index of the first row after the currently visible page. If the +return value is $0$ it means that no rows are currently shown (which only +happens if the control is empty). Note that the index returned by this method +is not always a valid index as it may be equal to +\helpref{GetRowCount}{wxhvscrolledwindowgetrowcount}. + +\wxheading{See also} + +\helpref{GetVisibleRowsBegin}{wxhvscrolledwindowgetvisiblerowsbegin} + + +\membersection{wxHVScrolledWindow::HitTest}\label{wxhvscrolledwindowhittest} + +\constfunc{wxPoint}{HitTest}{\param{wxCoord }{x}, \param{wxCoord }{y}} + +\constfunc{wxPoint}{HitTest}{\param{const wxPoint\& }{pt}} + +Return the position (X as column, Y as row) of the cell occupying the specified +position (in physical coordinates). A value of {\tt wxNOT\_FOUND} in either X, +Y, or X and Y means it is outside the range availible rows and/or columns. + + +\membersection{wxHVScrolledWindow::IsColumnVisible}\label{wxhvscrolledwindowiscolumnvisible} + +\constfunc{bool}{IsColumnVisible}{\param{size\_t}{column}} + +Returns {\tt true} if the given column is at least partially visible or +{\tt false} otherwise. + + +\membersection{wxHVScrolledWindow::IsRowVisible}\label{wxhvscrolledwindowisrowvisible} + +\constfunc{bool}{IsRowVisible}{\param{size\_t }{row}} + +Returns {\tt true} if the given row is at least partially visible or {\tt false} +otherwise. + + +\membersection{wxHVScrolledWindow::IsVisible}\label{wxhvscrolledwindowisvisible} + +\constfunc{bool}{IsVisible}{\param{size\_t }{row}, \param{size\_t}{column}} + +Returns {\tt true} if the given row and column are both at least partially +visible or {\tt false} otherwise. + + +\membersection{wxHVScrolledWindow::OnGetColumnWidth}\label{wxhvscrolledwindowongetcolumnwidth} + +\constfunc{wxCoord}{OnGetColumnWidth}{\param{size\_t }{n}} + +This protected pure virtual function must be overridden in the derived class +and should return the width of the given column in pixels. + +\wxheading{See also} + +\helpref{OnGetColumnsWidthHint}{wxhvscrolledwindowongetcolumnswidthhint} + + +\membersection{wxHVScrolledWindow::OnGetColumnsWidthHint}\label{wxhvscrolledwindowongetcolumnswidthhint} + +\constfunc{void}{OnGetColumnsWidthHint}{\param{size\_t }{columnMin}, \param{size\_t }{columnMax}} + +This function doesn't have to be overridden but it may be useful to do +it if calculating the columns' heights is a relatively expensive operation +as it gives the user code a possibility to calculate several of them at +once. + +{\tt OnGetColumnsWidthHint()} is normally called just before +\helpref{OnGetColumnWidth()}{wxhvscrolledwindowongetcolumnwidth} but you +shouldn't rely on the latter being called for all columns in the interval +specified here. It is also possible that OnGetColumnWidth() will be +called for the columns outside of this interval, so this is really just a +hint, not a promise. + +Finally note that {\it columnMin} is inclusive, while {\it columnMax} is exclusive, +as usual. + + +\membersection{wxHVScrolledWindow::OnGetRowHeight}\label{wxhvscrolledwindowongetrowheight} + +\constfunc{wxCoord}{OnGetRowHeight}{\param{size\_t }{n}} + +This protected pure virtual function must be overridden in the derived class +and should return the height of the given row in pixels. + +\wxheading{See also} + +\helpref{OnGetRowsHeightHint}{wxhvscrolledwindowongetrowsheighthint} + + +\membersection{wxHVScrolledWindow::OnGetRowsHeightHint}\label{wxhvscrolledwindowongetrowsheighthint} + +\constfunc{void}{OnGetRowsHeightHint}{\param{size\_t }{rowMin}, \param{size\_t }{rowMax}} + +This function doesn't have to be overridden but it may be useful to do +it if calculating the row's heights is a relatively expensive operation +as it gives the user code a possibility to calculate several of them at +once. + +{\tt OnGetRowsHeightHint()} is normally called just before +\helpref{OnGetRowHeight()}{wxhvscrolledwindowongetrowheight} but you +shouldn't rely on the latter being called for all rows in the interval +specified here. It is also possible that OnGetRowHeight() will be +called for the rows outside of this interval, so this is really just a +hint, not a promise. + +Finally note that {\it rowMin} is inclusive, while {\it rowMax} is exclusive, +as usual. + + +\membersection{wxHVScrolledWindow::RefreshColumn}\label{wxhvscrolledwindowrefreshcolumn} + +\func{void}{RefreshColumn}{\param{size\_t }{column}} + +Refreshes the specified column -- it will be redrawn during the next main loop +iteration. + + +\membersection{wxHVScrolledWindow::RefreshRow}\label{wxhvscrolledwindowrefreshrow} + +\func{void}{RefreshRow}{\param{size\_t }{row}} + +Refreshes the specified row -- it will be redrawn during the next main loop +iteration. + + +\membersection{wxHVScrolledWindow::RefreshRowColumn}\label{wxhvscrolledwindowrefreshrowcolumn} + +\func{void}{RefreshRowColumn}{\param{size\_t }{row}, \param{size\_t }{column}} + +Refreshes the specified cell -- it will be redrawn during the next main loop +iteration. + +\wxheading{See also} + +\helpref{RefreshRowsColumns}{wxhvscrolledwindowrefreshrowscolumns} + + +\membersection{wxHVScrolledWindow::RefreshColumns}\label{wxhvscrolledwindowrefreshcolumns} + +\func{void}{RefreshColumns}{\param{size\_ t}{fromColumn}, \param{size\_t }{toColumn}} + +Refreshes the columns between {\it fromColumn} and {\it toColumn} (inclusive). +{\it fromColumn} should be less than or equal to {\it toColumn}. + +\wxheading{See also} + +\helpref{RefreshColumn}{wxhvscrolledwindowrefreshcolumn} + + +\membersection{wxHVScrolledWindow::RefreshRows}\label{wxhvscrolledwindowrefreshrows} + +\func{void}{RefreshRows}{\param{size\_ t}{fromRow}, \param{size\_t }{toRow}} + +Refreshes the rows between {\it fromRow} and {\it toRow} (inclusive). +{\it fromRow} should be less than or equal to {\it toRow}. + +\wxheading{See also} + +\helpref{RefreshRow}{wxhvscrolledwindowrefreshrow} + + +\membersection{wxHVScrolledWindow::RefreshRowsColumns}\label{wxhvscrolledwindowrefreshrowscolumns} + +\func{void}{RefreshRowsColumns}{\param{size\_t }{fromRow}, \param{size\_t }{toRow}, \param{size\_ t}{fromColumn}, \param{size\_t }{toColumn}} + +Refreshes the region of cells between {\it fromRow}, {\it fromColumn} and +{\it toRow}, {\it toColumn} (inclusive). {\it fromRow} and {\it fromColumn} +should be less than or equal to {\it toRow} and {\it toColumn}, respectively. + +\wxheading{See also} + +\helpref{RefreshRowColumn}{wxhvscrolledwindowrefreshrowcolumn} + + +\membersection{wxHVScrolledWindow::RefreshAll}\label{wxhvscrolledwindowrefreshall} + +\func{void}{RefreshAll}{\void} + +This function completely refreshes the control, recalculating the number of +items shown on screen and repainting them. It should be called when the values +returned by either \helpref{OnGetRowHeight}{wxhvscrolledwindowongetrowheight} or +\helpref{OnGetColumnWidth}{wxhvscrolledwindowongetcolumnwidth} change for some +reason and the window must be updated to reflect this. + + +\membersection{wxHVScrolledWindow::ScrollColumns}\label{wxhvscrolledwindowscrollcolumns} + +\func{bool}{ScrollColumns}{\param{int }{columns}} + +Scroll by the specified number of columns which may be positive (to scroll +right) or negative (to scroll left). + +Returns {\tt true} if the window was scrolled, {\tt false} otherwise (for +example if we're trying to scroll right but we are already showing the last +column). + + +\membersection{wxHVScrolledWindow::ScrollRows}\label{wxhvscrolledwindowscrollrows} + +\func{bool}{ScrollRows}{\param{int }{rows}} + +Scroll by the specified number of rows which may be positive (to scroll +down) or negative (to scroll up). + +Returns {\tt true} if the window was scrolled, {\tt false} otherwise (for +example if we're trying to scroll down but we are already showing the last +row). + +\wxheading{See also} + +\helpref{LineUp}{wxwindowlineup}, \helpref{LineDown}{wxwindowlinedown} + + +\membersection{wxHVScrolledWindow::ScrollRowsColumns}\label{wxhvscrolledwindowscrollrowscolumns} + +\func{bool}{ScrollRowsColumns}{\param{int }{rows}, \param{int }{columns}} + +Scroll by the specified number of rows and columns which may be positive (to +scroll down or right) or negative (to scroll up or left). + +Returns {\tt true} if the window was scrolled, {\tt false} otherwise (for +example if we're trying to scroll down but we are already showing the last +row). + +\wxheading{See also} + +\helpref{LineUp}{wxwindowlineup}, \helpref{LineDown}{wxwindowlinedown} + + +\membersection{wxHVScrolledWindow::ScrollColumnPages}\label{wxhvscrolledwindowscrollcolumnpages} + +\func{bool}{ScrollColumnPages}{\param{int }{columnPages}} + +Scroll by the specified number of column pages, which may be positive (to +scroll right) or negative (to scroll left). + + +\membersection{wxHVScrolledWindow::ScrollPages}\label{wxhvscrolledwindowscrollpages} + +\func{bool}{ScrollPages}{\param{int }{rowPages}, \param{int }{columnPages}} + +Scroll by the specified number of row pages and column pages, both of which may +be positive (to scroll down or right) or negative (to scroll up or left). + +\wxheading{See also} + +\helpref{ScrollRowsColumns}{wxhvscrolledwindowscrollrowscolumns},\\ +\helpref{PageUp}{wxwindowpageup}, \helpref{PageDown}{wxwindowpagedown} + + +\membersection{wxHVScrolledWindow::ScrollRowPages}\label{wxhvscrolledwindowscrollrowpages} + +\func{bool}{ScrollRowPages}{\param{int }{rowPages}} + +Scroll by the specified number of row pages, which may be positive (to scroll +down) or negative (to scroll up). + +\wxheading{See also} + +\helpref{PageUp}{wxwindowpageup}, \helpref{PageDown}{wxwindowpagedown} + + +\membersection{wxHVScrolledWindow::ScrollToColumn}\label{wxhvscrolledwindowscrolltocolumn} + +\func{bool}{ScrollToColumn}{\param{size\_t }{column}} + +Scroll to the specified column. The specified column will be the first visible +column on the left side afterwards. + +Return {\tt true} if we scrolled the window, {\tt false} if nothing was done. + + +\membersection{wxHVScrolledWindow::ScrollToRow}\label{wxhvscrolledwindowscrolltorow} + +\func{bool}{ScrollToRow}{\param{size\_t }{row}} + +Scroll to the specified row. The specified column will be the first visible row +on the top afterwards. + +Return {\tt true} if we scrolled the window, {\tt false} if nothing was done. + + +\membersection{wxHVScrolledWindow::ScrollToRowColumn}\label{wxhvscrolledwindowscrolltorowcolumn} + +\func{bool}{ScrollToRowColumn}{\param{size\_t }{row}, \param{size\_t }{column}} + +Scroll to the specified row and column. The cell described will be the top left +visible cell afterwards. + +Return {\tt true} if we scrolled the window, {\tt false} if nothing was done. + + +\membersection{wxHVScrolledWindow::SetRowColumnCounts}\label{wxhvscrolledwindowsetrowcolumncounts} + +\func{void}{SetLineCount}{\param{size\_t }{row}, \param{size\_t }{column}} + +Set the number of rows and columns the window contains. The derived class must +provide the heights for all rows and the widths for all columns with indices up +to the respective values given here in its +\helpref{OnGetRowHeight()}{wxhvscrolledwindowongetrowheight} and +\helpref{OnGetColumnWidth()}{wxhvscrolledwindowongetcolumnwidth} +implementations. diff --git a/docs/latex/wx/vscroll.tex b/docs/latex/wx/vscroll.tex index d304d6f172..95892a7a01 100644 --- a/docs/latex/wx/vscroll.tex +++ b/docs/latex/wx/vscroll.tex @@ -159,7 +159,7 @@ Returns the index of the first currently visible line. Returns the index of the first line after the currently visible one. If the return value is $0$ it means that no lines are currently shown (which only happens if the control is empty). Note that the index returned by this method -is not always a valid index as it may be equal to \helpref{GetLineCount}{wxvscrolledwindowsetlinecount}. +is not always a valid index as it may be equal to \helpref{GetLineCount}{wxvscrolledwindowgetlinecount}. \wxheading{See also} diff --git a/include/wx/vscroll.h b/include/wx/vscroll.h index b24615f27e..bead562926 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: +// Modified by: Brad Anderson // Created: 30.05.03 // RCS-ID: $Id$ // Copyright: (c) 2003 Vadim Zeitlin @@ -135,6 +135,8 @@ 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 @@ -214,5 +216,270 @@ 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/samples/vscroll/vstest.cpp b/samples/vscroll/vstest.cpp index ff4b716705..2e23b2ec41 100644 --- a/samples/vscroll/vstest.cpp +++ b/samples/vscroll/vstest.cpp @@ -2,7 +2,7 @@ // Name: samples/vscroll/vstest.cpp // Purpose: VScroll wxWidgets sample // Author: Vadim Zeitlin -// Modified by: +// Modified by: Brad Anderson // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) 2003 Vadim Zeitlin @@ -44,12 +44,18 @@ #include "../sample.xpm" #endif +// ---------------------------------------------------------------------------- +// definitions +// ---------------------------------------------------------------------------- + +#define MAX_LINES 200 + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- // Define a new application type, each program should derive a class from wxApp -class VScrollApp : public wxApp +class VarScrollApp : public wxApp { public: // create our main window @@ -57,14 +63,16 @@ public: }; // Define a new frame type: this is going to be our main frame -class VScrollFrame : public wxFrame +class VarScrollFrame : public wxFrame { public: // ctor - VScrollFrame(); + VarScrollFrame(); // event handlers (these functions should _not_ be virtual) void OnQuit(wxCommandEvent& event); + void OnModeVScroll(wxCommandEvent& event); + void OnModeHVScroll(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); void OnSize(wxSizeEvent& event) @@ -84,6 +92,9 @@ public: private: // any class wishing to process wxWidgets events must use this macro DECLARE_EVENT_TABLE() + + // either a wxVScrolledWindow or a wxHVScrolled window, depending on current mode + wxPanel *m_scrollWindow; }; class VScrollWindow : public wxVScrolledWindow @@ -93,8 +104,12 @@ public: { m_frame = frame; - SetLineCount(200); + SetLineCount(MAX_LINES); + int i; + for ( i = 0; i < MAX_LINES; ++i ) + m_heights[i] = rand()%25+16; // low: 15; high: 40 + m_changed = true; } @@ -116,21 +131,23 @@ public: { wxPaintDC dc(this); - dc.SetPen(*wxBLACK_DASHED_PEN); + dc.SetPen(*wxBLACK_PEN); - const size_t lineFirst = GetFirstVisibleLine(), - lineLast = GetLastVisibleLine(); + const size_t lineFirst = GetVisibleBegin(), + lineLast = GetVisibleEnd(); const wxCoord hText = dc.GetCharHeight(); + wxSize clientSize = GetClientSize(); + wxCoord y = 0; - for ( size_t line = lineFirst; line <= lineLast; line++ ) + for ( size_t line = lineFirst; line < lineLast; line++ ) { - dc.DrawLine(0, y, 1000, y); + dc.DrawLine(0, y, clientSize.GetWidth(), y); wxCoord hLine = OnGetLineHeight(line); dc.DrawText(wxString::Format(_T("Line %lu"), (unsigned long)line), - 0, y + (hLine - hText) / 2); + 2, y + (hLine - hText) / 2); y += hLine; dc.DrawLine(0, y, 1000, y); @@ -149,12 +166,14 @@ public: { wxASSERT( n < GetLineCount() ); - return n % 2 ? 15 : 30; // 15 + 2*n + return m_heights[n]; } private: wxFrame *m_frame; + int m_heights[MAX_LINES]; + bool m_changed; DECLARE_EVENT_TABLE() @@ -166,6 +185,126 @@ BEGIN_EVENT_TABLE(VScrollWindow, wxVScrolledWindow) EVT_SCROLLWIN(VScrollWindow::OnScroll) END_EVENT_TABLE() +class HVScrollWindow : public wxHVScrolledWindow +{ +public: + HVScrollWindow(wxFrame *frame) : wxHVScrolledWindow(frame, wxID_ANY) + { + m_frame = frame; + + SetRowColumnCounts(MAX_LINES, MAX_LINES); + + int i; + for ( i = 0; i < MAX_LINES; ++i ) + { + m_heights[i] = rand()%30+31; // low: 30; high: 60 + m_widths[i] = rand()%30+61; // low: 60; high: 90 + } + + m_changed = true; + } + + void OnIdle(wxIdleEvent&) + { +#if wxUSE_STATUSBAR + m_frame->SetStatusText(wxString::Format + ( + _T("Page size = %d rows %d columns; pos = row: %d, column: %d; max = %d rows, %d columns"), + GetScrollThumb(wxVERTICAL), + GetScrollThumb(wxHORIZONTAL), + GetScrollPos(wxVERTICAL), + GetScrollPos(wxHORIZONTAL), + GetScrollRange(wxVERTICAL), + GetScrollRange(wxHORIZONTAL) + )); +#endif // wxUSE_STATUSBAR + m_changed = false; + } + + void OnPaint(wxPaintEvent&) + { + wxPaintDC dc(this); + + dc.SetPen(*wxBLACK_PEN); + + const size_t rowFirst = GetVisibleRowsBegin(), + rowLast = GetVisibleRowsEnd(); + const size_t columnFirst = GetVisibleColumnsBegin(), + columnLast = GetVisibleColumnsEnd(); + + const wxCoord hText = dc.GetCharHeight(); + + wxSize clientSize = GetClientSize(); + + wxCoord y = 0; + wxCoord x = 0; + for ( size_t row = rowFirst; row < rowLast; row++ ) + { + wxCoord rowHeight = OnGetRowHeight(row); + dc.DrawLine(0, y, clientSize.GetWidth(), y); + + x = 0; + for ( size_t col = columnFirst; col < columnLast; col++ ) + { + wxCoord colWidth = OnGetColumnWidth(col); + + if ( row == rowFirst ) + dc.DrawLine(x, 0, x, clientSize.GetHeight()); + + dc.DrawText(wxString::Format(_T("Row %lu"), (unsigned long)row), + x + 2, y + rowHeight / 2 - hText); + dc.DrawText(wxString::Format(_T("Col %lu"), (unsigned long)col), + x + 2, y + rowHeight / 2); + + x += colWidth; + if ( row == rowFirst) + dc.DrawLine(x, 0, x, clientSize.GetHeight()); + } + + y += rowHeight; + dc.DrawLine(0, y, clientSize.GetWidth(), y); + } + } + + void OnScroll(wxScrollWinEvent& event) + { + m_changed = true; + + event.Skip(); + } + + + virtual wxCoord OnGetRowHeight(size_t n) const + { + wxASSERT( n < GetRowCount() ); + + return m_heights[n]; + } + + virtual wxCoord OnGetColumnWidth(size_t n) const + { + wxASSERT( n < GetColumnCount() ); + + return m_widths[n]; + } + +private: + wxFrame *m_frame; + + int m_heights[MAX_LINES]; + int m_widths[MAX_LINES]; + + bool m_changed; + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(HVScrollWindow, wxHVScrolledWindow) + EVT_IDLE(HVScrollWindow::OnIdle) + EVT_PAINT(HVScrollWindow::OnPaint) + EVT_SCROLLWIN(HVScrollWindow::OnScroll) +END_EVENT_TABLE() + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -179,7 +318,10 @@ enum // it is important for the id corresponding to the "About" command to have // this standard value as otherwise it won't be handled properly under Mac // (where it is special and put into the "Apple" menu) - VScroll_About = wxID_ABOUT + VScroll_About = wxID_ABOUT, + + VScroll_VScrollMode = wxID_HIGHEST + 1, + VScroll_HVScrollMode }; // ---------------------------------------------------------------------------- @@ -189,18 +331,20 @@ enum // the event tables connect the wxWidgets events with the functions (event // handlers) which process them. It can be also done at run-time, but for the // simple menu events like this the static method is much simpler. -BEGIN_EVENT_TABLE(VScrollFrame, wxFrame) - EVT_MENU(VScroll_Quit, VScrollFrame::OnQuit) - EVT_MENU(VScroll_About, VScrollFrame::OnAbout) - EVT_SIZE(VScrollFrame::OnSize) +BEGIN_EVENT_TABLE(VarScrollFrame, wxFrame) + EVT_MENU(VScroll_Quit, VarScrollFrame::OnQuit) + EVT_MENU(VScroll_VScrollMode, VarScrollFrame::OnModeVScroll) + EVT_MENU(VScroll_HVScrollMode, VarScrollFrame::OnModeHVScroll) + EVT_MENU(VScroll_About, VarScrollFrame::OnAbout) + EVT_SIZE(VarScrollFrame::OnSize) END_EVENT_TABLE() // Create a new application object: this macro will allow wxWidgets to create // the application object during program execution (it's better than using a // static object for many reasons) and also declares the accessor function -// wxGetApp() which will return the reference of the right type (i.e. VScrollApp and +// wxGetApp() which will return the reference of the right type (i.e. VarScrollApp and // not wxApp) -IMPLEMENT_APP(VScrollApp) +IMPLEMENT_APP(VarScrollApp) // ============================================================================ // implementation @@ -211,10 +355,10 @@ IMPLEMENT_APP(VScrollApp) // ---------------------------------------------------------------------------- // 'Main program' equivalent: the program execution "starts" here -bool VScrollApp::OnInit() +bool VarScrollApp::OnInit() { // create the main application window - VScrollFrame *frame = new VScrollFrame; + VarScrollFrame *frame = new VarScrollFrame; // and show it (the frames, unlike simple controls, are not shown when // created initially) @@ -229,12 +373,13 @@ bool VScrollApp::OnInit() // ---------------------------------------------------------------------------- // frame constructor -VScrollFrame::VScrollFrame() - : wxFrame(NULL, - wxID_ANY, - _T("VScroll wxWidgets Sample"), - wxDefaultPosition, - wxSize(400, 350)) +VarScrollFrame::VarScrollFrame() + : wxFrame(NULL, + wxID_ANY, + _T("VScroll wxWidgets Sample"), + wxDefaultPosition, + wxSize(400, 350)), + m_scrollWindow(NULL) { // set the frame icon SetIcon(wxICON(sample)); @@ -243,15 +388,32 @@ VScrollFrame::VScrollFrame() // create a menu bar wxMenu *menuFile = new wxMenu; + wxMenu *menuMode = new wxMenu; + // the "About" item should be in the help menu wxMenu *menuHelp = new wxMenu; menuHelp->Append(VScroll_About, _T("&About...\tF1"), _T("Show about dialog")); +#ifdef wxHAS_RADIO_MENU_ITEMS + menuMode->AppendRadioItem(VScroll_VScrollMode, _T("&Vertical\tAlt-V"), + _T("Vertical scrolling only")); + menuMode->AppendRadioItem(VScroll_HVScrollMode, + _T("&Horizontal/Vertical\tAlt-H"), + _T("Horizontal and vertical scrolling")); + menuMode->Check(VScroll_VScrollMode, true); +#else + menuMode->Append(VScroll_VScrollMode, _T("&Vertical\tAlt-V"), + _T("Vertical scrolling only")); + menuMode->Append(VScroll_HVScrollMode, _T("&Horizontal/Vertical\tAlt-H"), + _T("Horizontal and vertical scrolling")); +#endif + menuFile->Append(VScroll_Quit, _T("E&xit\tAlt-X"), _T("Quit this program")); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar; menuBar->Append(menuFile, _T("&File")); + menuBar->Append(menuMode, _T("&Mode")); menuBar->Append(menuHelp, _T("&Help")); // ... and attach this menu bar to the frame @@ -262,26 +424,51 @@ VScrollFrame::VScrollFrame() // create a status bar just for fun (by default with 1 pane only) CreateStatusBar(2); SetStatusText(_T("Welcome to wxWidgets!")); + int widths[2]; + widths[0] = -1; + widths[1] = 100; + SetStatusWidths(2, widths); #endif // wxUSE_STATUSBAR // create our one and only child -- it will take our entire client area - new VScrollWindow(this); + if ( menuMode->IsChecked(VScroll_VScrollMode) ) + m_scrollWindow = new VScrollWindow(this); + else if ( menuMode->IsChecked(VScroll_VScrollMode) ) + m_scrollWindow = new HVScrollWindow(this); } // ---------------------------------------------------------------------------- // event handlers // ---------------------------------------------------------------------------- -void VScrollFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +void VarScrollFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { // true is to force the frame to close Close(true); } -void VScrollFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) +void VarScrollFrame::OnModeVScroll(wxCommandEvent& WXUNUSED(event)) +{ + if ( m_scrollWindow ) + m_scrollWindow->Destroy(); + + m_scrollWindow = new VScrollWindow(this); + SendSizeEvent(); +} + +void VarScrollFrame::OnModeHVScroll(wxCommandEvent& WXUNUSED(event)) +{ + if ( m_scrollWindow ) + m_scrollWindow->Destroy(); + + m_scrollWindow = new HVScrollWindow(this); + SendSizeEvent(); +} + +void VarScrollFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("VScroll shows how to implement scrolling with\n") - _T("variable line heights.\n") + _T("variable line widths and heights.\n") _T("(c) 2003 Vadim Zeitlin"), _T("About VScroll"), wxOK | wxICON_INFORMATION, diff --git a/src/generic/vscroll.cpp b/src/generic/vscroll.cpp index 9267c8aad3..17ec846fa7 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: +// Modified by: Brad Anderson // Created: 30.05.03 // RCS-ID: $Id$ // Copyright: (c) 2003 Vadim Zeitlin @@ -25,6 +25,8 @@ #endif #include "wx/vscroll.h" +#include "wx/sizer.h" +#include "wx/dc.h" // ---------------------------------------------------------------------------- // event tables @@ -263,6 +265,25 @@ 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(); @@ -303,8 +324,7 @@ bool wxVScrolledWindow::ScrollToLine(size_t line) // remember the currently shown lines for the refresh code below - size_t lineFirstOld = GetVisibleBegin(), - lineLastOld = GetVisibleEnd(); + size_t lineFirstOld = GetVisibleBegin(); m_lineFirst = line; @@ -312,20 +332,8 @@ bool wxVScrolledWindow::ScrollToLine(size_t line) // the size of scrollbar thumb could have changed UpdateScrollbar(); - - // 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)); - } + // finally, scroll the actual window + ScrollWindow(0, GetLinesHeight(GetVisibleBegin(), lineFirstOld)); return true; } @@ -452,3 +460,931 @@ void wxVScrolledWindow::OnMouseWheel(wxMouseEvent& event) } #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-1; + + if(m_columnsFirst >= columnCount) + m_columnsFirst = columnCount-1; + + if(m_rowsFirst < 0) + m_rowsFirst = 0; + + if(m_columnsFirst < 0) + m_columnsFirst = 0; + + 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); + } + + // 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); + + for ( size_t n = GetVisibleRowsBegin(); n < row; n++ ) + { + rect.y += OnGetRowHeight(n); + } + + for ( size_t 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; + for ( size_t nBefore = GetVisibleRowsBegin(); + nBefore < fromRow; + nBefore++ ) + { + rect.y += OnGetRowHeight(nBefore); + } + + for ( size_t nBetween = fromRow; nBetween <= toRow; nBetween++ ) + { + rect.height += OnGetRowHeight(nBetween); + } + + for ( size_t nBefore = GetVisibleColumnsBegin(); + nBefore < fromColumn; + nBefore++ ) + { + rect.x += OnGetColumnWidth(nBefore); + } + + for ( size_t 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(0, 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