1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/vscroll.cpp
3 // Purpose: wxVScrolledWindow implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/vscroll.h"
22 // ----------------------------------------------------------------------------
24 // ----------------------------------------------------------------------------
26 BEGIN_EVENT_TABLE(wxVScrolledWindow
, wxPanel
)
27 EVT_SIZE(wxVScrolledWindow::OnSize
)
28 EVT_SCROLLWIN(wxVScrolledWindow::OnScroll
)
32 // ============================================================================
34 // ============================================================================
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 void wxVScrolledWindow::Init()
42 // we're initially empty
46 // this one should always be strictly positive
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 wxCoord
wxVScrolledWindow::GetLinesHeight(size_t lineMin
, size_t lineMax
) const
58 if ( lineMin
== lineMax
)
60 else if ( lineMin
> lineMax
)
61 return -GetLinesHeight(lineMax
, lineMin
);
62 //else: lineMin < lineMax
64 // let the user code know that we're going to need all these lines
65 OnGetLinesHint(lineMin
, lineMax
);
67 // do sum up their heights
69 for ( size_t line
= lineMin
; line
< lineMax
; line
++ )
71 height
+= OnGetLineHeight(line
);
77 size_t wxVScrolledWindow::FindFirstFromBottom(size_t lineLast
)
79 const wxCoord hWindow
= GetClientSize().y
;
81 // go upwards until we arrive at a line such that lineLast is not visible
82 // any more when it is shown
83 size_t lineFirst
= lineLast
;
87 h
+= OnGetLineHeight(lineFirst
);
105 void wxVScrolledWindow::UpdateScrollbar()
107 // see how many lines can we fit on screen
108 const wxCoord hWindow
= GetClientSize().y
;
112 for ( line
= m_lineFirst
; line
< m_lineMax
; line
++ )
117 h
+= OnGetLineHeight(line
);
120 m_nVisible
= line
- m_lineFirst
;
122 int pageSize
= m_nVisible
;
125 // last line is only partially visible, we still need the scrollbar and
126 // so we have to "fix" pageSize because if it is equal to m_lineMax the
127 // scrollbar is not shown at all under MSW
131 // set the scrollbar parameters to reflect this
132 SetScrollbar(wxVERTICAL
, m_lineFirst
, pageSize
, m_lineMax
);
135 // ----------------------------------------------------------------------------
137 // ----------------------------------------------------------------------------
139 void wxVScrolledWindow::SetLineCount(size_t count
)
141 // save the number of lines
145 // estimate the total height: it is impossible to call
146 // OnGetLineHeight() for every line because there may be too many of
147 // them, so we just make a guess using some lines in the beginning,
148 // some in the end and some in the middle
149 static const size_t NUM_LINES_TO_SAMPLE
= 10;
151 if ( count
< 3*NUM_LINES_TO_SAMPLE
)
153 // in this case calculating exactly is faster and more correct than
155 m_heightTotal
= GetLinesHeight(0, m_lineMax
);
157 else // too many lines to calculate exactly
159 // look at some lines in the beginning/middle/end
161 GetLinesHeight(0, NUM_LINES_TO_SAMPLE
) +
162 GetLinesHeight(count
- NUM_LINES_TO_SAMPLE
, count
) +
163 GetLinesHeight(count
/2 - NUM_LINES_TO_SAMPLE
/2,
164 count
/2 + NUM_LINES_TO_SAMPLE
/2);
166 // use the height of the lines we looked as the average
167 m_heightTotal
= ((float)m_heightTotal
/ (3*NUM_LINES_TO_SAMPLE
)) *
172 // recalculate the scrollbars parameters
176 // ----------------------------------------------------------------------------
178 // ----------------------------------------------------------------------------
180 bool wxVScrolledWindow::ScrollToLine(size_t line
)
184 // we're empty, code below doesn't make sense in this case
188 // determine the real first line to scroll to: we shouldn't scroll beyond
190 size_t lineFirstLast
= FindFirstFromBottom(m_lineMax
- 1);
191 if ( line
> lineFirstLast
)
192 line
= lineFirstLast
;
195 if ( line
== m_lineFirst
)
202 // remember the currently shown lines for the refresh code below
203 size_t lineFirstOld
= GetFirstVisibleLine(),
204 lineLastOld
= GetLastVisibleLine();
209 // the size of scrollbar thumb could have changed
213 // finally refresh the display -- but only redraw as few lines as possible
215 if ( GetFirstVisibleLine() > lineLastOld
||
216 GetLastVisibleLine() < lineFirstOld
)
218 // the simplest case: we don't have any old lines left, just redraw
222 else // overlap between the lines we showed before and should show now
224 ScrollWindow(0, GetLinesHeight(GetFirstVisibleLine(), lineFirstOld
));
230 bool wxVScrolledWindow::ScrollLines(int lines
)
232 lines
+= m_lineFirst
;
236 return ScrollToLine(lines
);
239 bool wxVScrolledWindow::ScrollPages(int pages
)
241 bool didSomething
= false;
248 line
= GetLastVisibleLine();
253 line
= FindFirstFromBottom(GetFirstVisibleLine());
257 didSomething
= ScrollToLine(line
);
263 // ----------------------------------------------------------------------------
265 // ----------------------------------------------------------------------------
267 void wxVScrolledWindow::OnSize(wxSizeEvent
& event
)
274 void wxVScrolledWindow::OnScroll(wxScrollWinEvent
& event
)
278 const wxEventType evtType
= event
.GetEventType();
279 if ( evtType
== wxEVT_SCROLLWIN_TOP
)
283 else if ( evtType
== wxEVT_SCROLLWIN_BOTTOM
)
285 lineFirstNew
= m_lineMax
;
287 else if ( evtType
== wxEVT_SCROLLWIN_LINEUP
)
289 lineFirstNew
= m_lineFirst
? m_lineFirst
- 1 : 0;
291 else if ( evtType
== wxEVT_SCROLLWIN_LINEDOWN
)
293 lineFirstNew
= m_lineFirst
+ 1;
295 else if ( evtType
== wxEVT_SCROLLWIN_PAGEUP
)
297 lineFirstNew
= FindFirstFromBottom(m_lineFirst
);
299 else if ( evtType
== wxEVT_SCROLLWIN_PAGEDOWN
)
301 lineFirstNew
= GetLastVisibleLine();
303 else // unknown scroll event?
305 if ( evtType
== wxEVT_SCROLLWIN_THUMBRELEASE
)
307 lineFirstNew
= event
.GetPosition();
311 wxASSERT_MSG( evtType
== wxEVT_SCROLLWIN_THUMBTRACK
,
312 _T("unknown scroll event type?") );
314 // don't do anything, otherwise dragging the thumb around would
320 ScrollToLine(lineFirstNew
);