\input htwinprs.tex
\input htwinhnd.tex
\input http.tex
+\input hvscroll.tex
\input icon.tex
\input iconbndl.tex
\input iconloc.tex
--- /dev/null
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 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 <vadim@wxwindows.org>
+%% 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}
+
+<wx/vscroll.h>
+
+
+\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.
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}
// 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 <vadim@wxwidgets.org>
// is kept for backwards compatibility
size_t GetLastVisibleLine() const { return GetVisibleEnd() - 1; }
+ // layout the children (including the sizer if needed)
+ virtual bool Layout();
protected:
// this function must be overridden in the derived class and it should
DECLARE_ABSTRACT_CLASS(wxVScrolledWindow)
};
+
+// ----------------------------------------------------------------------------
+// wxHVScrolledWindow
+// ----------------------------------------------------------------------------
+
+/*
+ This class is strongly influenced by wxVScrolledWindow. In fact, much of
+ code is line for line the same except it explicitly states which axis is
+ being worked on. Like wxVScrolledWindow, this class is here to provide
+ an easy way to implement variable line sizes. The difference is that
+ wxVScrolledWindow only works with vertical scrolling. This class extends
+ the behavior of wxVScrolledWindow to the horizontal axis in addition to the
+ vertical axis.
+
+ The scrolling is also "virtual" in the sense that line widths and heights
+ only need to be known for lines that are currently visible.
+
+ Like wxVScrolledWindow, this is a generalization of the wxScrolledWindow
+ class which can be only used when all horizontal lines have the same width
+ and all of the vertical lines have the same height. Like wxVScrolledWinow
+ it lacks some of wxScrolledWindow features such as scrolling another window
+ or only scrolling a rectangle of the window and not its entire client area.
+
+ If only vertical scrolling is needed, wxVScrolledWindow is recommended
+ because it is simpler to use (and you get to type less).
+
+ There is no wxHScrolledWindow but horizontal only scrolling is implemented
+ easily enough with this class. If someone feels the need for such a class,
+ implementing it is trivial.
+ */
+class WXDLLEXPORT wxHVScrolledWindow : public wxPanel
+{
+public:
+ // constructors and such
+ // ---------------------
+
+ // default ctor, you must call Create() later
+ wxHVScrolledWindow() { Init(); }
+
+ // normal ctor, no need to call Create() after this one
+ //
+ // note that wxVSCROLL and wxHSCROLL are always automatically added to our
+ // style, there is no need to specify them explicitly
+ wxHVScrolledWindow(wxWindow *parent,
+ wxWindowID id = wxID_ANY,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = 0,
+ const wxString& name = wxPanelNameStr)
+ {
+ Init();
+
+ (void)Create(parent, id, pos, size, style, name);
+ }
+
+ // same as the previous ctor but returns status code: true if ok
+ //
+ // just as with the ctor above, wxVSCROLL and wxHSCROLL styles are always
+ // used, there is no need to specify them
+ bool Create(wxWindow *parent,
+ wxWindowID id = wxID_ANY,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = 0,
+ const wxString& name = wxPanelNameStr)
+ {
+ return wxPanel::Create(parent, id, pos, size,
+ style | wxVSCROLL | wxHSCROLL, name);
+ }
+
+
+ // operations
+ // ----------
+
+ // set the number of lines the window contains for each axis: the derived
+ // class must provide the widths and heights for all lines with indices up
+ // to each of the one given here in its OnGetColumnWidth() and
+ // OnGetRowHeight()
+ void SetRowColumnCounts(size_t rowCount, size_t columnCount);
+
+ // with physical scrolling on, the device origin is changed properly when
+ // a wxPaintDC is prepared, children are actually moved and layed out
+ // properly, and the contents of the window (pixels) are actually moved
+ void EnablePhysicalScrolling(bool scrolling = true)
+ { m_physicalScrolling = scrolling; }
+
+ // scroll to the specified line: it will become the first visible line in
+ // the window
+ //
+ // return true if we scrolled the window, false if nothing was done
+ bool ScrollToRow(size_t row);
+ bool ScrollToColumn(size_t column);
+ bool ScrollToRowColumn(size_t row, size_t column);
+
+ // scroll by the specified number of lines/pages
+ virtual bool ScrollRows(int rows);
+ virtual bool ScrollColumns(int columns);
+ virtual bool ScrollRowsColumns(int rows, int columns);
+ virtual bool ScrollRowPages(int pages);
+ virtual bool ScrollColumnPages(int pages);
+ virtual bool ScrollPages(int rowPages, int columnPages);
+
+ // redraw the specified line
+ virtual void RefreshRow(size_t line);
+ virtual void RefreshColumn(size_t line);
+ virtual void RefreshRowColumn(size_t row, size_t column);
+
+ // redraw all lines in the specified range (inclusive)
+ virtual void RefreshRows(size_t from, size_t to);
+ virtual void RefreshColumns(size_t from, size_t to);
+ virtual void RefreshRowsColumns(size_t fromRow, size_t toRow,
+ size_t fromColumn, size_t toColumn);
+
+ // return the horizontal and vertical line within a wxPoint at the
+ // specified (in physical coordinates) position or.
+
+ // wxNOT_FOUND in either or both axes if no line is present at the
+ // requested coordinates, i.e. if it is past the last lines
+ wxPoint HitTest(wxCoord x, wxCoord y) const;
+ wxPoint HitTest(const wxPoint& pt) const { return HitTest(pt.x, pt.y); }
+
+ // recalculate all our parameters and redisplay all lines
+ virtual void RefreshAll();
+
+
+ // accessors
+ // ---------
+
+ // get the number of lines this window contains (previously set by
+ // SetLineCount())
+ size_t GetRowCount() const { return m_rowsMax; }
+ size_t GetColumnCount() const { return m_columnsMax; }
+ wxSize GetRowColumnCounts() const
+ { return wxSize((int)m_columnsMax, (int)m_rowsMax); }
+
+ // get the first currently visible line/lines
+ size_t GetVisibleRowsBegin() const { return m_rowsFirst; }
+ size_t GetVisibleColumnsBegin() const { return m_columnsFirst; }
+ wxPoint GetVisibleBegin() const
+ { return wxPoint((int)m_columnsFirst, (int)m_rowsFirst); }
+
+ // get the last currently visible line/lines
+ size_t GetVisibleRowsEnd() const
+ { return m_rowsFirst + m_nRowsVisible; }
+ size_t GetVisibleColumnsEnd() const
+ { return m_columnsFirst + m_nColumnsVisible; }
+ wxPoint GetVisibleEnd() const
+ { return wxPoint((int)(m_columnsFirst + m_nColumnsVisible),
+ (int)(m_rowsFirst + m_nRowsVisible)); }
+
+ // is this line currently visible?
+ bool IsRowVisible(size_t row) const
+ { return row >= m_rowsFirst &&
+ row < GetVisibleRowsEnd(); }
+ bool IsColumnVisible(size_t column) const
+ { return column >= m_columnsFirst &&
+ column < GetVisibleColumnsEnd(); }
+ bool IsVisible(size_t row, size_t column) const
+ { return IsRowVisible(row) && IsColumnVisible(column); }
+
+ // layout the children (including the sizer if needed)
+ virtual bool Layout();
+
+protected:
+ // these functions must be overridden in the derived class and they should
+ // return the width or height of the given line in pixels
+ virtual wxCoord OnGetRowHeight(size_t n) const = 0;
+ virtual wxCoord OnGetColumnWidth(size_t n) const = 0;
+
+ // the following functions don't need to be overridden but it may be useful
+ // to do if calculating the lines widths or heights is a relatively
+ // expensive operation as it gives the user code a possibility to calculate
+ // several of them at once
+ //
+ // OnGetRowsHeightHint() and OnGetColumnsWidthHint() are normally called
+ // just before OnGetRowHeight() and OnGetColumnWidth(), respectively, but
+ // you shouldn't rely on the latter methods being called for all lines in
+ // the interval specified here. It is also possible that OnGetRowHeight()
+ // or OnGetColumnWidth() will be called for the lines outside of this
+ // interval, so this is really just a hint, not a promise.
+ //
+ // finally note that min is inclusive, while max is exclusive, as usual
+ virtual void OnGetRowsHeightHint(size_t WXUNUSED(rowMin),
+ size_t WXUNUSED(rowMax)) const { }
+ virtual void OnGetColumnsWidthHint(size_t WXUNUSED(columnMin),
+ size_t WXUNUSED(columnMax)) const { }
+
+ // when the number of lines changes, we try to estimate the total width or
+ // height of all lines which is a rather expensive operation in terms of
+ // lines access, so if the user code may estimate the average height
+ // better/faster than we do, it should override this function to implement
+ // its own logic
+ //
+ // this function should return the best guess for the total height it may
+ // make
+ virtual wxCoord EstimateTotalHeight() const;
+ virtual wxCoord EstimateTotalWidth() const;
+
+ // the event handlers
+ void OnSize(wxSizeEvent& event);
+ void OnScroll(wxScrollWinEvent& event);
+#if wxUSE_MOUSEWHEEL
+ void OnMouseWheel(wxMouseEvent& event);
+#endif
+
+
+ // find the index of the horizontal line we need to show at the top of the
+ // window such that the last (fully or partially) visible line is the given
+ // one
+ size_t FindFirstFromRight(size_t columnLast, bool fullyVisible = false);
+
+ // find the index of the vertical line we need to show at the top of the
+ // window such that the last (fully or partially) visible line is the given
+ // one
+ size_t FindFirstFromBottom(size_t rowLast, bool fullyVisible = false);
+
+
+ // get the total width or height of the lines between lineMin (inclusive)
+ // and lineMax (exclusive)
+ wxCoord GetRowsHeight(size_t rowMin, size_t rowMax) const;
+ wxCoord GetColumnsWidth(size_t columnMin, size_t columnMax) const;
+
+ // update the thumb size shown by the scrollbar
+ void UpdateScrollbars();
+
+ // shifts the specified dc by the scroll position
+ void PrepareDC(wxDC& dc);
+
+private:
+ // common part of all ctors
+ void Init();
+
+
+ // the total number of (logical) lines for each axis
+ size_t m_rowsMax;
+ size_t m_columnsMax;
+
+ // the total (estimated) height
+ wxCoord m_heightTotal;
+
+ // the total (estimated) width
+ wxCoord m_widthTotal;
+
+ // the first currently visible line on each axis
+ size_t m_rowsFirst;
+ size_t m_columnsFirst;
+
+ // the number of currently visible lines for each axis (including the last,
+ // possibly only partly, visible one)
+ size_t m_nRowsVisible;
+ size_t m_nColumnsVisible;
+
+ // accumulated mouse wheel rotation
+#if wxUSE_MOUSEWHEEL
+ int m_sumWheelRotation;
+#endif
+
+ // do child scrolling (used in DoPrepareDC())
+ bool m_physicalScrolling;
+
+ DECLARE_EVENT_TABLE()
+ DECLARE_NO_COPY_CLASS(wxHVScrolledWindow)
+ DECLARE_ABSTRACT_CLASS(wxHVScrolledWindow)
+};
+
#endif // _WX_VSCROLL_H_
// Name: 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 <vadim@wxwidgets.org>
#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
};
// 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)
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
{
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;
}
{
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);
{
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()
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
// ----------------------------------------------------------------------------
// 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
};
// ----------------------------------------------------------------------------
// 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
// ----------------------------------------------------------------------------
// '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)
// ----------------------------------------------------------------------------
// 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));
// 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
// 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,
// 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 <vadim@wxwindows.org>
#endif
#include "wx/vscroll.h"
+#include "wx/sizer.h"
+#include "wx/dc.h"
// ----------------------------------------------------------------------------
// event tables
Refresh();
}
+bool wxVScrolledWindow::Layout()
+{
+ if(GetSizer())
+ {
+ // adjust the sizer dimensions/position taking into account the
+ // virtual size and scrolled position of the window.
+
+ int y, w, h; // x is always 0 so no variable needed
+
+ y = -GetLinesHeight(0, GetFirstVisibleLine());
+ GetVirtualSize(&w, &h);
+ GetSizer()->SetDimension(0, y, w, h);
+ return true;
+ }
+
+ // fall back to default for LayoutConstraints
+ return wxPanel::Layout();
+}
+
int wxVScrolledWindow::HitTest(wxCoord WXUNUSED(x), wxCoord y) const
{
const size_t lineMax = GetVisibleEnd();
// remember the currently shown lines for the refresh code below
- size_t lineFirstOld = GetVisibleBegin(),
- lineLastOld = GetVisibleEnd();
+ size_t lineFirstOld = GetVisibleBegin();
m_lineFirst = 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;
}
}
#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
+