1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/vscroll.cpp
3 // Purpose: wxVScrolledWindow implementation
4 // Author: Vadim Zeitlin
5 // Modified by: Brad Anderson
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #include "wx/vscroll.h"
31 // ----------------------------------------------------------------------------
33 // ----------------------------------------------------------------------------
35 BEGIN_EVENT_TABLE(wxVScrolledWindow
, wxPanel
)
36 EVT_SIZE(wxVScrolledWindow::OnSize
)
37 EVT_SCROLLWIN(wxVScrolledWindow::OnScroll
)
39 EVT_MOUSEWHEEL(wxVScrolledWindow::OnMouseWheel
)
44 // ============================================================================
46 // ============================================================================
48 IMPLEMENT_ABSTRACT_CLASS(wxVScrolledWindow
, wxPanel
)
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 void wxVScrolledWindow::Init()
56 // we're initially empty
60 // this one should always be strictly positive
66 m_sumWheelRotation
= 0;
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 wxCoord
wxVScrolledWindow::EstimateTotalHeight() const
76 // estimate the total height: it is impossible to call
77 // OnGetLineHeight() for every line because there may be too many of
78 // them, so we just make a guess using some lines in the beginning,
79 // some in the end and some in the middle
80 static const size_t NUM_LINES_TO_SAMPLE
= 10;
83 if ( m_lineMax
< 3*NUM_LINES_TO_SAMPLE
)
85 // in this case calculating exactly is faster and more correct than
87 heightTotal
= GetLinesHeight(0, m_lineMax
);
89 else // too many lines to calculate exactly
91 // look at some lines in the beginning/middle/end
93 GetLinesHeight(0, NUM_LINES_TO_SAMPLE
) +
94 GetLinesHeight(m_lineMax
- NUM_LINES_TO_SAMPLE
, m_lineMax
) +
95 GetLinesHeight(m_lineMax
/2 - NUM_LINES_TO_SAMPLE
/2,
96 m_lineMax
/2 + NUM_LINES_TO_SAMPLE
/2);
98 // use the height of the lines we looked as the average
99 heightTotal
= (wxCoord
)
100 (((float)heightTotal
/ (3*NUM_LINES_TO_SAMPLE
)) * m_lineMax
);
106 wxCoord
wxVScrolledWindow::GetLinesHeight(size_t lineMin
, size_t lineMax
) const
108 if ( lineMin
== lineMax
)
110 else if ( lineMin
> lineMax
)
111 return -GetLinesHeight(lineMax
, lineMin
);
112 //else: lineMin < lineMax
114 // let the user code know that we're going to need all these lines
115 OnGetLinesHint(lineMin
, lineMax
);
117 // do sum up their heights
119 for ( size_t line
= lineMin
; line
< lineMax
; line
++ )
121 height
+= OnGetLineHeight(line
);
127 size_t wxVScrolledWindow::FindFirstFromBottom(size_t lineLast
, bool full
)
129 const wxCoord hWindow
= GetClientSize().y
;
131 // go upwards until we arrive at a line such that lineLast is not visible
132 // any more when it is shown
133 size_t lineFirst
= lineLast
;
137 h
+= OnGetLineHeight(lineFirst
);
141 // for this line to be fully visible we need to go one line
142 // down, but if it is enough for it to be only partly visible then
143 // this line will do as well
161 void wxVScrolledWindow::UpdateScrollbar()
163 // see how many lines can we fit on screen
164 const wxCoord hWindow
= GetClientSize().y
;
168 for ( line
= m_lineFirst
; line
< m_lineMax
; line
++ )
173 h
+= OnGetLineHeight(line
);
176 m_nVisible
= line
- m_lineFirst
;
178 int pageSize
= m_nVisible
;
181 // last line is only partially visible, we still need the scrollbar and
182 // so we have to "fix" pageSize because if it is equal to m_lineMax the
183 // scrollbar is not shown at all under MSW
187 // set the scrollbar parameters to reflect this
188 SetScrollbar(wxVERTICAL
, m_lineFirst
, pageSize
, m_lineMax
);
191 // ----------------------------------------------------------------------------
193 // ----------------------------------------------------------------------------
195 void wxVScrolledWindow::SetLineCount(size_t count
)
197 // save the number of lines
200 // and our estimate for their total height
201 m_heightTotal
= EstimateTotalHeight();
203 // recalculate the scrollbars parameters
204 m_lineFirst
= 1; // make sure it is != 0
208 void wxVScrolledWindow::RefreshLine(size_t line
)
210 // is this line visible?
211 if ( !IsVisible(line
) )
213 // no, it is useless to do anything
217 // calculate the rect occupied by this line on screen
219 rect
.width
= GetClientSize().x
;
220 rect
.height
= OnGetLineHeight(line
);
221 for ( size_t n
= GetVisibleBegin(); n
< line
; n
++ )
223 rect
.y
+= OnGetLineHeight(n
);
230 void wxVScrolledWindow::RefreshLines(size_t from
, size_t to
)
232 wxASSERT_MSG( from
<= to
, _T("RefreshLines(): empty range") );
234 // clump the range to just the visible lines -- it is useless to refresh
236 if ( from
< GetVisibleBegin() )
237 from
= GetVisibleBegin();
239 if ( to
>= GetVisibleEnd() )
240 to
= GetVisibleEnd();
244 // calculate the rect occupied by these lines on screen
246 rect
.width
= GetClientSize().x
;
247 for ( size_t nBefore
= GetVisibleBegin(); nBefore
< from
; nBefore
++ )
249 rect
.y
+= OnGetLineHeight(nBefore
);
252 for ( size_t nBetween
= from
; nBetween
< to
; nBetween
++ )
254 rect
.height
+= OnGetLineHeight(nBetween
);
261 void wxVScrolledWindow::RefreshAll()
268 bool wxVScrolledWindow::Layout()
272 // adjust the sizer dimensions/position taking into account the
273 // virtual size and scrolled position of the window.
275 int y
, w
, h
; // x is always 0 so no variable needed
277 y
= -GetLinesHeight(0, GetFirstVisibleLine());
278 GetVirtualSize(&w
, &h
);
279 GetSizer()->SetDimension(0, y
, w
, h
);
283 // fall back to default for LayoutConstraints
284 return wxPanel::Layout();
287 int wxVScrolledWindow::HitTest(wxCoord
WXUNUSED(x
), wxCoord y
) const
289 const size_t lineMax
= GetVisibleEnd();
290 for ( size_t line
= GetVisibleBegin(); line
< lineMax
; line
++ )
292 y
-= OnGetLineHeight(line
);
300 // ----------------------------------------------------------------------------
302 // ----------------------------------------------------------------------------
304 bool wxVScrolledWindow::ScrollToLine(size_t line
)
308 // we're empty, code below doesn't make sense in this case
312 // determine the real first line to scroll to: we shouldn't scroll beyond
314 size_t lineFirstLast
= FindFirstFromBottom(m_lineMax
- 1, true);
315 if ( line
> lineFirstLast
)
316 line
= lineFirstLast
;
319 if ( line
== m_lineFirst
)
326 // remember the currently shown lines for the refresh code below
327 size_t lineFirstOld
= GetVisibleBegin();
332 // the size of scrollbar thumb could have changed
335 // finally, scroll the actual window
336 ScrollWindow(0, GetLinesHeight(GetVisibleBegin(), lineFirstOld
));
341 bool wxVScrolledWindow::ScrollLines(int lines
)
343 lines
+= m_lineFirst
;
347 return ScrollToLine(lines
);
350 bool wxVScrolledWindow::ScrollPages(int pages
)
352 bool didSomething
= false;
359 line
= GetVisibleEnd();
366 line
= FindFirstFromBottom(GetVisibleBegin());
370 didSomething
= ScrollToLine(line
);
376 // ----------------------------------------------------------------------------
378 // ----------------------------------------------------------------------------
380 void wxVScrolledWindow::OnSize(wxSizeEvent
& event
)
387 void wxVScrolledWindow::OnScroll(wxScrollWinEvent
& event
)
391 const wxEventType evtType
= event
.GetEventType();
393 if ( evtType
== wxEVT_SCROLLWIN_TOP
)
397 else if ( evtType
== wxEVT_SCROLLWIN_BOTTOM
)
399 lineFirstNew
= m_lineMax
;
401 else if ( evtType
== wxEVT_SCROLLWIN_LINEUP
)
403 lineFirstNew
= m_lineFirst
? m_lineFirst
- 1 : 0;
405 else if ( evtType
== wxEVT_SCROLLWIN_LINEDOWN
)
407 lineFirstNew
= m_lineFirst
+ 1;
409 else if ( evtType
== wxEVT_SCROLLWIN_PAGEUP
)
411 lineFirstNew
= FindFirstFromBottom(m_lineFirst
);
413 else if ( evtType
== wxEVT_SCROLLWIN_PAGEDOWN
)
415 lineFirstNew
= GetVisibleEnd();
419 else if ( evtType
== wxEVT_SCROLLWIN_THUMBRELEASE
)
421 lineFirstNew
= event
.GetPosition();
423 else if ( evtType
== wxEVT_SCROLLWIN_THUMBTRACK
)
425 lineFirstNew
= event
.GetPosition();
428 else // unknown scroll event?
430 wxFAIL_MSG( _T("unknown scroll event type?") );
434 ScrollToLine(lineFirstNew
);
443 void wxVScrolledWindow::OnMouseWheel(wxMouseEvent
& event
)
445 m_sumWheelRotation
+= event
.GetWheelRotation();
446 int delta
= event
.GetWheelDelta();
448 // how much to scroll this time
449 int units_to_scroll
= -(m_sumWheelRotation
/delta
);
450 if ( !units_to_scroll
)
453 m_sumWheelRotation
+= units_to_scroll
*delta
;
455 if ( !event
.IsPageScroll() )
456 ScrollLines( units_to_scroll
*event
.GetLinesPerAction() );
458 // scroll pages instead of lines
459 ScrollPages( units_to_scroll
);
467 // ----------------------------------------------------------------------------
468 // wxVarScrolled Window event tables
469 // ----------------------------------------------------------------------------
471 BEGIN_EVENT_TABLE(wxHVScrolledWindow
, wxPanel
)
472 EVT_SIZE(wxHVScrolledWindow::OnSize
)
473 EVT_SCROLLWIN(wxHVScrolledWindow::OnScroll
)
475 EVT_MOUSEWHEEL(wxHVScrolledWindow::OnMouseWheel
)
480 // ============================================================================
481 // wxVarScrolled implementation
482 // ============================================================================
484 IMPLEMENT_ABSTRACT_CLASS(wxHVScrolledWindow
, wxPanel
)
486 // ----------------------------------------------------------------------------
488 // ----------------------------------------------------------------------------
490 void wxHVScrolledWindow::Init()
492 // we're initially empty
498 // these should always be strictly positive
500 m_nColumnsVisible
= 1;
505 m_physicalScrolling
= true;
508 m_sumWheelRotation
= 0;
512 // ----------------------------------------------------------------------------
514 // ----------------------------------------------------------------------------
516 wxCoord
wxHVScrolledWindow::EstimateTotalHeight() const
518 // estimate the total height: it is impossible to call
519 // OnGetLineHeight() for every line because there may be too many of
520 // them, so we just make a guess using some lines in the beginning,
521 // some in the end and some in the middle
522 static const size_t NUM_LINES_TO_SAMPLE
= 10;
525 if ( m_rowsMax
< 3*NUM_LINES_TO_SAMPLE
)
527 // in this case calculating exactly is faster and more correct than
529 heightTotal
= GetRowsHeight(0, m_rowsMax
);
531 else // too many lines to calculate exactly
533 // look at some lines in the beginning/middle/end
535 GetRowsHeight(0, NUM_LINES_TO_SAMPLE
) +
536 GetRowsHeight(m_rowsMax
- NUM_LINES_TO_SAMPLE
,
538 GetRowsHeight(m_rowsMax
/2 - NUM_LINES_TO_SAMPLE
/2,
539 m_rowsMax
/2 + NUM_LINES_TO_SAMPLE
/2);
541 // use the height of the lines we looked as the average
542 heightTotal
= (wxCoord
)
543 (((float)heightTotal
/ (3*NUM_LINES_TO_SAMPLE
)) * m_rowsMax
);
549 wxCoord
wxHVScrolledWindow::EstimateTotalWidth() const
551 // estimate the total width: it is impossible to call
552 // OnGetLineWidth() for every line because there may be too many of
553 // them, so we just make a guess using some lines in the beginning,
554 // some in the end and some in the middle
555 static const size_t NUM_LINES_TO_SAMPLE
= 10;
558 if ( m_columnsMax
< 3*NUM_LINES_TO_SAMPLE
)
560 // in this case calculating exactly is faster and more correct than
562 widthTotal
= GetColumnsWidth(0, m_columnsMax
);
564 else // too many lines to calculate exactly
566 // look at some lines in the beginning/middle/end
568 GetColumnsWidth(0, NUM_LINES_TO_SAMPLE
) +
569 GetColumnsWidth(m_columnsMax
- NUM_LINES_TO_SAMPLE
,
571 GetColumnsWidth(m_columnsMax
/2 - NUM_LINES_TO_SAMPLE
/2,
572 m_columnsMax
/2 + NUM_LINES_TO_SAMPLE
/2);
574 // use the width of the lines we looked as the average
575 widthTotal
= (wxCoord
)
576 (((float)widthTotal
/ (3*NUM_LINES_TO_SAMPLE
)) * m_columnsMax
);
582 wxCoord
wxHVScrolledWindow::GetRowsHeight(size_t rowMin
, size_t rowMax
) const
584 if ( rowMin
== rowMax
)
586 else if ( rowMin
> rowMax
)
587 return -GetRowsHeight(rowMax
, rowMin
);
588 //else: lineMin < lineMax
590 // let the user code know that we're going to need all these lines
591 OnGetRowsHeightHint(rowMin
, rowMax
);
593 // do sum up their heights
595 for ( size_t row
= rowMin
; row
< rowMax
; row
++ )
597 height
+= OnGetRowHeight(row
);
603 wxCoord
wxHVScrolledWindow::GetColumnsWidth(size_t columnMin
, size_t columnMax
) const
605 if ( columnMin
== columnMax
)
607 else if ( columnMin
> columnMax
)
608 return -GetColumnsWidth(columnMax
, columnMin
);
609 //else: lineMin < lineMax
611 // let the user code know that we're going to need all these lines
612 OnGetColumnsWidthHint(columnMin
, columnMax
);
614 // do sum up their widths
616 for ( size_t column
= columnMin
; column
< columnMax
; column
++ )
618 width
+= OnGetColumnWidth(column
);
624 size_t wxHVScrolledWindow::FindFirstFromBottom(size_t rowLast
, bool full
)
626 const wxCoord hWindow
= GetClientSize().y
;
628 // go upwards until we arrive at a line such that lineLast is not visible
629 // any more when it is shown
630 size_t lineFirst
= rowLast
;
634 h
+= OnGetRowHeight(lineFirst
);
638 // for this line to be fully visible we need to go one line
639 // down, but if it is enough for it to be only partly visible then
640 // this line will do as well
658 size_t wxHVScrolledWindow::FindFirstFromRight(size_t columnLast
, bool full
)
660 const wxCoord wWindow
= GetClientSize().x
;
662 // go upwards until we arrive at a line such that lineLast is not visible
663 // any more when it is shown
664 size_t lineFirst
= columnLast
;
668 w
+= OnGetColumnWidth(lineFirst
);
672 // for this line to be fully visible we need to go one line
673 // down, but if it is enough for it to be only partly visible then
674 // this line will do as well
692 void wxHVScrolledWindow::UpdateScrollbars()
694 // see how many lines can we fit on screen (on both axes)
695 const wxCoord wWindow
= GetClientSize().x
;
696 const wxCoord hWindow
= GetClientSize().y
;
698 // first do the horizontal calculations
701 for ( column
= m_columnsFirst
; column
< m_columnsMax
; column
++ )
706 w
+= OnGetColumnWidth(column
);
709 m_nColumnsVisible
= column
- m_columnsFirst
;
711 int columnsPageSize
= m_nColumnsVisible
;
714 // last line is only partially visible, we still need the scrollbar and
715 // so we have to "fix" pageSize because if it is equal to
716 // m_horizLineMax the scrollbar is not shown at all under MSW
720 // set the scrollbar parameters to reflect this
721 SetScrollbar(wxHORIZONTAL
, m_columnsFirst
, columnsPageSize
, m_columnsMax
);
724 // now do the vertical calculations
727 for ( row
= m_rowsFirst
; row
< m_rowsMax
; row
++ )
732 h
+= OnGetRowHeight(row
);
735 m_nRowsVisible
= row
- m_rowsFirst
;
737 int rowsPageSize
= m_nRowsVisible
;
740 // last line is only partially visible, we still need the scrollbar and
741 // so we have to "fix" pageSize because if it is equal to m_vertLineMax
742 // the scrollbar is not shown at all under MSW
746 // set the scrollbar parameters to reflect this
747 SetScrollbar(wxVERTICAL
, m_rowsFirst
, rowsPageSize
, m_rowsMax
);
750 void wxHVScrolledWindow::PrepareDC(wxDC
& dc
)
752 if(m_physicalScrolling
)
754 dc
.SetDeviceOrigin(-GetColumnsWidth(0, GetVisibleColumnsBegin()),
755 -GetRowsHeight(0, GetVisibleRowsBegin()));
759 // ----------------------------------------------------------------------------
761 // ----------------------------------------------------------------------------
763 void wxHVScrolledWindow::SetRowColumnCounts(size_t rowCount
, size_t columnCount
)
765 // save the number of lines
766 m_rowsMax
= rowCount
;
767 m_columnsMax
= columnCount
;
769 // and our estimate for their total height and width
770 m_heightTotal
= EstimateTotalHeight();
771 m_widthTotal
= EstimateTotalWidth();
773 // recalculate the scrollbars parameters
774 if(m_rowsFirst
>= rowCount
)
775 m_rowsFirst
= rowCount
-1;
777 if(m_columnsFirst
>= columnCount
)
778 m_columnsFirst
= columnCount
-1;
783 if(m_columnsFirst
< 0)
786 ScrollToRowColumn(m_rowsFirst
, m_columnsFirst
);
789 void wxHVScrolledWindow::RefreshColumn(size_t column
)
791 // is this line visible?
792 if ( !IsColumnVisible(column
) )
794 // no, it is useless to do anything
798 // calculate the rect occupied by this line on screen
800 rect
.width
= OnGetColumnWidth(column
);
801 rect
.height
= GetClientSize().y
;
802 for ( size_t n
= GetVisibleColumnsBegin(); n
< column
; n
++ )
804 rect
.y
+= OnGetColumnWidth(n
);
811 void wxHVScrolledWindow::RefreshRow(size_t row
)
813 // is this line visible?
814 if ( !IsRowVisible(row
) )
816 // no, it is useless to do anything
820 // calculate the rect occupied by this line on screen
822 rect
.width
= GetClientSize().x
;
823 rect
.height
= OnGetRowHeight(row
);
824 for ( size_t n
= GetVisibleRowsBegin(); n
< row
; n
++ )
826 rect
.y
+= OnGetRowHeight(n
);
833 void wxHVScrolledWindow::RefreshRowColumn(size_t row
, size_t column
)
835 // is this line visible?
836 if ( !IsRowVisible(row
) || !IsColumnVisible(column
) )
838 // no, it is useless to do anything
842 // calculate the rect occupied by this cell on screen
844 rect
.height
= OnGetRowHeight(row
);
845 rect
.width
= OnGetColumnWidth(column
);
849 for ( n
= GetVisibleRowsBegin(); n
< row
; n
++ )
851 rect
.y
+= OnGetRowHeight(n
);
854 for ( n
= GetVisibleColumnsBegin(); n
< column
; n
++ )
856 rect
.x
+= OnGetColumnWidth(n
);
863 void wxHVScrolledWindow::RefreshRows(size_t from
, size_t to
)
865 wxASSERT_MSG( from
<= to
, _T("RefreshRows(): empty range") );
867 // clump the range to just the visible lines -- it is useless to refresh
869 if ( from
< GetVisibleRowsBegin() )
870 from
= GetVisibleRowsBegin();
872 if ( to
> GetVisibleRowsEnd() )
873 to
= GetVisibleRowsEnd();
875 // calculate the rect occupied by these lines on screen
877 rect
.width
= GetClientSize().x
;
878 for ( size_t nBefore
= GetVisibleRowsBegin();
882 rect
.y
+= OnGetRowHeight(nBefore
);
885 for ( size_t nBetween
= from
; nBetween
<= to
; nBetween
++ )
887 rect
.height
+= OnGetRowHeight(nBetween
);
894 void wxHVScrolledWindow::RefreshColumns(size_t from
, size_t to
)
896 wxASSERT_MSG( from
<= to
, _T("RefreshColumns(): empty range") );
898 // clump the range to just the visible lines -- it is useless to refresh
900 if ( from
< GetVisibleColumnsBegin() )
901 from
= GetVisibleColumnsBegin();
903 if ( to
> GetVisibleColumnsEnd() )
904 to
= GetVisibleColumnsEnd();
906 // calculate the rect occupied by these lines on screen
908 rect
.height
= GetClientSize().y
;
909 for ( size_t nBefore
= GetVisibleColumnsBegin();
913 rect
.x
+= OnGetColumnWidth(nBefore
);
916 for ( size_t nBetween
= from
; nBetween
<= to
; nBetween
++ )
918 rect
.width
+= OnGetColumnWidth(nBetween
);
925 void wxHVScrolledWindow::RefreshRowsColumns(size_t fromRow
, size_t toRow
,
926 size_t fromColumn
, size_t toColumn
)
928 wxASSERT_MSG( fromRow
<= toRow
|| fromColumn
<= toColumn
,
929 _T("RefreshRowsColumns(): empty range") );
931 // clump the range to just the visible lines -- it is useless to refresh
933 if ( fromRow
< GetVisibleRowsBegin() )
934 fromRow
= GetVisibleRowsBegin();
936 if ( toRow
> GetVisibleRowsEnd() )
937 toRow
= GetVisibleRowsEnd();
939 if ( fromColumn
< GetVisibleColumnsBegin() )
940 fromColumn
= GetVisibleColumnsBegin();
942 if ( toColumn
> GetVisibleColumnsEnd() )
943 toColumn
= GetVisibleColumnsEnd();
945 // calculate the rect occupied by these lines on screen
947 size_t nBefore
, nBetween
;
949 for ( nBefore
= GetVisibleRowsBegin();
953 rect
.y
+= OnGetRowHeight(nBefore
);
956 for ( nBetween
= fromRow
; nBetween
<= toRow
; nBetween
++ )
958 rect
.height
+= OnGetRowHeight(nBetween
);
961 for ( nBefore
= GetVisibleColumnsBegin();
962 nBefore
< fromColumn
;
965 rect
.x
+= OnGetColumnWidth(nBefore
);
968 for ( nBetween
= fromColumn
; nBetween
<= toColumn
; nBetween
++ )
970 rect
.width
+= OnGetColumnWidth(nBetween
);
977 void wxHVScrolledWindow::RefreshAll()
984 bool wxHVScrolledWindow::Layout()
986 if(GetSizer() && m_physicalScrolling
)
988 // adjust the sizer dimensions/position taking into account the
989 // virtual size and scrolled position of the window.
993 y
= -GetRowsHeight(0, GetVisibleRowsBegin());
994 x
= -GetColumnsWidth(0, GetVisibleColumnsBegin());
995 GetVirtualSize(&w
, &h
);
996 GetSizer()->SetDimension(0, y
, w
, h
);
1000 // fall back to default for LayoutConstraints
1001 return wxPanel::Layout();
1004 wxPoint
wxHVScrolledWindow::HitTest(wxCoord x
, wxCoord y
) const
1006 const size_t rowMax
= GetVisibleRowsEnd();
1007 const size_t columnMax
= GetVisibleColumnsEnd();
1009 wxPoint
hit(wxNOT_FOUND
, wxNOT_FOUND
);
1010 for ( size_t row
= GetVisibleRowsBegin();
1014 y
-= OnGetRowHeight(row
);
1019 for ( size_t column
= GetVisibleColumnsBegin();
1020 column
<= columnMax
;
1023 x
-= OnGetColumnWidth(column
);
1031 // ----------------------------------------------------------------------------
1033 // ----------------------------------------------------------------------------
1035 bool wxHVScrolledWindow::ScrollToRowColumn(size_t row
, size_t column
)
1037 if ( !m_rowsMax
&& !m_columnsMax
)
1039 // we're empty, code below doesn't make sense in this case
1043 bool scrolled
= false;
1044 scrolled
|= ScrollToRow(row
);
1045 scrolled
|= ScrollToColumn(column
);
1050 bool wxHVScrolledWindow::ScrollToRow(size_t row
)
1054 // we're empty, code below doesn't make sense in this case
1058 // determine the real first line to scroll to: we shouldn't scroll beyond
1060 size_t lineFirstLast
= FindFirstFromBottom(m_rowsMax
- 1, true);
1061 if ( row
> lineFirstLast
)
1062 row
= lineFirstLast
;
1065 if ( row
== m_rowsFirst
)
1072 // remember the currently shown lines for the refresh code below
1073 size_t lineFirstOld
= GetVisibleRowsBegin();
1078 // the size of scrollbar thumb could have changed
1082 // finally, scroll the actual window contents vertically
1083 if(m_physicalScrolling
)
1084 ScrollWindow(0, GetRowsHeight(GetVisibleRowsBegin(), lineFirstOld
));
1089 bool wxHVScrolledWindow::ScrollToColumn(size_t column
)
1091 if ( !m_columnsMax
)
1093 // we're empty, code below doesn't make sense in this case
1097 // determine the real first line to scroll to: we shouldn't scroll beyond
1099 size_t lineFirstLast
= FindFirstFromRight(m_columnsMax
- 1, true);
1100 if ( column
> lineFirstLast
)
1101 column
= lineFirstLast
;
1104 if ( column
== m_columnsFirst
)
1111 // remember the currently shown lines for the refresh code below
1112 size_t lineFirstOld
= GetVisibleColumnsBegin();
1114 m_columnsFirst
= column
;
1117 // the size of scrollbar thumb could have changed
1120 // finally, scroll the actual window contents horizontally
1121 if(m_physicalScrolling
)
1122 ScrollWindow(GetColumnsWidth(GetVisibleColumnsBegin(), lineFirstOld
), 0);
1127 bool wxHVScrolledWindow::ScrollRows(int rows
)
1129 rows
+= m_rowsFirst
;
1133 return ScrollToRow(rows
);
1136 bool wxHVScrolledWindow::ScrollColumns(int columns
)
1138 columns
+= m_columnsFirst
;
1142 return ScrollToColumn(columns
);
1145 bool wxHVScrolledWindow::ScrollRowsColumns(int rows
, int columns
)
1147 rows
+= m_rowsFirst
;
1151 columns
+= m_columnsFirst
;
1155 return ScrollToRowColumn(rows
, columns
);
1158 bool wxHVScrolledWindow::ScrollRowPages(int pages
)
1160 bool didSomething
= false;
1167 line
= GetVisibleRowsEnd();
1174 line
= FindFirstFromBottom(GetVisibleRowsEnd());
1178 didSomething
= ScrollToRow(line
);
1181 return didSomething
;
1184 bool wxHVScrolledWindow::ScrollColumnPages(int pages
)
1186 bool didSomething
= false;
1193 line
= GetVisibleColumnsEnd();
1200 line
= FindFirstFromRight(GetVisibleColumnsEnd());
1204 didSomething
= ScrollToColumn(line
);
1207 return didSomething
;
1210 bool wxHVScrolledWindow::ScrollPages(int rowPages
, int columnPages
)
1212 bool didSomething
= false;
1219 line
= GetVisibleRowsEnd();
1224 else // rowPages < 0
1226 line
= FindFirstFromBottom(GetVisibleRowsBegin());
1230 didSomething
= ScrollToRow(line
);
1233 while ( columnPages
)
1236 if ( columnPages
> 0 )
1238 line
= GetVisibleColumnsEnd();
1243 else // columnPages < 0
1245 line
= FindFirstFromRight(GetVisibleColumnsBegin());
1249 didSomething
|= ScrollToColumn(line
);
1252 return didSomething
;
1255 // ----------------------------------------------------------------------------
1257 // ----------------------------------------------------------------------------
1259 void wxHVScrolledWindow::OnSize(wxSizeEvent
& event
)
1267 void wxHVScrolledWindow::OnScroll(wxScrollWinEvent
& event
)
1269 if(event
.GetOrientation() == wxHORIZONTAL
)
1271 size_t columnsFirstNew
;
1272 const wxEventType evtType
= event
.GetEventType();
1274 if ( evtType
== wxEVT_SCROLLWIN_TOP
)
1276 columnsFirstNew
= 0;
1278 else if ( evtType
== wxEVT_SCROLLWIN_BOTTOM
)
1280 columnsFirstNew
= m_columnsMax
;
1282 else if ( evtType
== wxEVT_SCROLLWIN_LINEUP
)
1284 columnsFirstNew
= m_columnsFirst
? m_columnsFirst
- 1 : 0;
1286 else if ( evtType
== wxEVT_SCROLLWIN_LINEDOWN
)
1288 columnsFirstNew
= m_columnsFirst
+ 1;
1290 else if ( evtType
== wxEVT_SCROLLWIN_PAGEUP
)
1292 columnsFirstNew
= FindFirstFromRight(m_columnsFirst
);
1294 else if ( evtType
== wxEVT_SCROLLWIN_PAGEDOWN
)
1296 columnsFirstNew
= GetVisibleColumnsEnd();
1297 if ( columnsFirstNew
)
1300 else if ( evtType
== wxEVT_SCROLLWIN_THUMBRELEASE
)
1302 columnsFirstNew
= event
.GetPosition();
1304 else if ( evtType
== wxEVT_SCROLLWIN_THUMBTRACK
)
1306 columnsFirstNew
= event
.GetPosition();
1309 else // unknown scroll event?
1311 wxFAIL_MSG( _T("unknown scroll event type?") );
1315 ScrollToColumn(columnsFirstNew
);
1317 else if(event
.GetOrientation() == wxVERTICAL
)
1319 size_t rowsFirstNew
;
1320 const wxEventType evtType
= event
.GetEventType();
1322 if ( evtType
== wxEVT_SCROLLWIN_TOP
)
1326 else if ( evtType
== wxEVT_SCROLLWIN_BOTTOM
)
1328 rowsFirstNew
= m_rowsMax
;
1330 else if ( evtType
== wxEVT_SCROLLWIN_LINEUP
)
1332 rowsFirstNew
= m_rowsFirst
? m_rowsFirst
- 1 : 0;
1334 else if ( evtType
== wxEVT_SCROLLWIN_LINEDOWN
)
1336 rowsFirstNew
= m_rowsFirst
+ 1;
1338 else if ( evtType
== wxEVT_SCROLLWIN_PAGEUP
)
1340 rowsFirstNew
= FindFirstFromBottom(m_rowsFirst
);
1342 else if ( evtType
== wxEVT_SCROLLWIN_PAGEDOWN
)
1344 rowsFirstNew
= GetVisibleRowsEnd();
1348 else if ( evtType
== wxEVT_SCROLLWIN_THUMBRELEASE
)
1350 rowsFirstNew
= event
.GetPosition();
1352 else if ( evtType
== wxEVT_SCROLLWIN_THUMBTRACK
)
1354 rowsFirstNew
= event
.GetPosition();
1357 else // unknown scroll event?
1359 wxFAIL_MSG( _T("unknown scroll event type?") );
1363 ScrollToRow(rowsFirstNew
);
1372 #if wxUSE_MOUSEWHEEL
1374 void wxHVScrolledWindow::OnMouseWheel(wxMouseEvent
& event
)
1376 m_sumWheelRotation
+= event
.GetWheelRotation();
1377 int delta
= event
.GetWheelDelta();
1379 // how much to scroll this time
1380 int units_to_scroll
= -(m_sumWheelRotation
/delta
);
1381 if ( !units_to_scroll
)
1384 m_sumWheelRotation
+= units_to_scroll
*delta
;
1386 if ( !event
.IsPageScroll() )
1387 ScrollRows( units_to_scroll
*event
.GetLinesPerAction() );
1389 // scroll pages instead of lines
1390 ScrollRowPages( units_to_scroll
);