]> git.saurik.com Git - wxWidgets.git/blame - src/generic/vscroll.cpp
initial attempts to get raw bitmaps working under Mac
[wxWidgets.git] / src / generic / vscroll.cpp
CommitLineData
cf7d6329
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/generic/vscroll.cpp
3// Purpose: wxVScrolledWindow implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 30.05.03
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#include "wx/vscroll.h"
21
22// ----------------------------------------------------------------------------
23// event tables
24// ----------------------------------------------------------------------------
25
26BEGIN_EVENT_TABLE(wxVScrolledWindow, wxPanel)
27 EVT_SIZE(wxVScrolledWindow::OnSize)
28 EVT_SCROLLWIN(wxVScrolledWindow::OnScroll)
29END_EVENT_TABLE()
30
31
32// ============================================================================
33// implementation
34// ============================================================================
35
36// ----------------------------------------------------------------------------
37// initialization
38// ----------------------------------------------------------------------------
39
40void wxVScrolledWindow::Init()
41{
42 // we're initially empty
43 m_lineMax =
44 m_lineFirst = 0;
45
46 // this one should always be strictly positive
47 m_nVisible = 1;
48
49 m_heightTotal = 0;
50}
51
52// ----------------------------------------------------------------------------
53// various helpers
54// ----------------------------------------------------------------------------
55
56wxCoord wxVScrolledWindow::GetLinesHeight(size_t lineMin, size_t lineMax) const
57{
58 if ( lineMin == lineMax )
59 return 0;
60 else if ( lineMin > lineMax )
61 return -GetLinesHeight(lineMax, lineMin);
62 //else: lineMin < lineMax
63
64 // let the user code know that we're going to need all these lines
65 OnGetLinesHint(lineMin, lineMax);
66
67 // do sum up their heights
68 wxCoord height = 0;
69 for ( size_t line = lineMin; line < lineMax; line++ )
70 {
71 height += OnGetLineHeight(line);
72 }
73
74 return height;
75}
76
77size_t wxVScrolledWindow::FindFirstFromBottom(size_t lineLast)
78{
79 const wxCoord hWindow = GetClientSize().y;
80
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;
84 wxCoord h = 0;
85 for ( ;; )
86 {
87 h += OnGetLineHeight(lineFirst);
88
89 if ( h > hWindow )
90 {
91 lineFirst++;
92
93 break;
94 }
95
96 if ( !lineFirst )
97 break;
98
99 lineFirst--;
100 }
101
102 return lineFirst;
103}
104
105void wxVScrolledWindow::UpdateScrollbar()
106{
107 // see how many lines can we fit on screen
108 const wxCoord hWindow = GetClientSize().y;
109
110 wxCoord h = 0;
111 size_t line;
112 for ( line = m_lineFirst; line < m_lineMax; line++ )
113 {
114 if ( h > hWindow )
115 break;
116
117 h += OnGetLineHeight(line);
118 }
119
120 m_nVisible = line - m_lineFirst;
121
122 int pageSize = m_nVisible;
123 if ( h > hWindow )
124 {
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
128 pageSize--;
129 }
130
131 // set the scrollbar parameters to reflect this
132 SetScrollbar(wxVERTICAL, m_lineFirst, pageSize, m_lineMax);
133}
134
135// ----------------------------------------------------------------------------
136// operations
137// ----------------------------------------------------------------------------
138
139void wxVScrolledWindow::SetLineCount(size_t count)
140{
141 // save the number of lines
142 m_lineMax = count;
143
144
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;
150
151 if ( count < 3*NUM_LINES_TO_SAMPLE )
152 {
153 // in this case calculating exactly is faster and more correct than
154 // guessing
155 m_heightTotal = GetLinesHeight(0, m_lineMax);
156 }
157 else // too many lines to calculate exactly
158 {
159 // look at some lines in the beginning/middle/end
160 m_heightTotal =
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);
165
166 // use the height of the lines we looked as the average
b544a278
VZ
167 m_heightTotal = (wxCoord)
168 (((float)m_heightTotal / (3*NUM_LINES_TO_SAMPLE)) * m_lineMax);
cf7d6329
VZ
169 }
170
171
172 // recalculate the scrollbars parameters
e0c6027b 173 m_lineFirst = 1; // make sure it is != 0
cf7d6329
VZ
174 ScrollToLine(0);
175}
176
e0c6027b
VZ
177void wxVScrolledWindow::RefreshLine(size_t line)
178{
179 // is this line visible?
180 if ( !IsVisible(line) )
181 {
182 // no, it is useless to do anything
183 return;
184 }
185
186 // calculate the rect occupied by this line on screen
187 wxRect rect;
188 rect.width = GetClientSize().x;
189 rect.height = OnGetLineHeight(line);
190 for ( size_t n = GetFirstVisibleLine(); n < line; n++ )
191 {
192 rect.y += OnGetLineHeight(n);
193 }
194
195 // do refresh it
196 RefreshRect(rect);
197}
198
8b053348
VZ
199void wxVScrolledWindow::RefreshAll()
200{
201 UpdateScrollbar();
202
203 Refresh();
204}
205
e0c6027b
VZ
206int wxVScrolledWindow::HitTest(wxCoord WXUNUSED(x), wxCoord y) const
207{
208 const size_t lineMax = GetLastVisibleLine();
209 for ( size_t line = GetFirstVisibleLine(); line <= lineMax; line++ )
210 {
211 y -= OnGetLineHeight(line);
212 if ( y < 0 )
213 return line;
214 }
215
216 return wxNOT_FOUND;
217}
218
cf7d6329
VZ
219// ----------------------------------------------------------------------------
220// scrolling
221// ----------------------------------------------------------------------------
222
223bool wxVScrolledWindow::ScrollToLine(size_t line)
224{
225 if ( !m_lineMax )
226 {
227 // we're empty, code below doesn't make sense in this case
228 return false;
229 }
230
231 // determine the real first line to scroll to: we shouldn't scroll beyond
232 // the end
233 size_t lineFirstLast = FindFirstFromBottom(m_lineMax - 1);
234 if ( line > lineFirstLast )
235 line = lineFirstLast;
236
237 // anything to do?
238 if ( line == m_lineFirst )
239 {
240 // no
241 return false;
242 }
243
244
245 // remember the currently shown lines for the refresh code below
246 size_t lineFirstOld = GetFirstVisibleLine(),
247 lineLastOld = GetLastVisibleLine();
248
249 m_lineFirst = line;
250
251
252 // the size of scrollbar thumb could have changed
253 UpdateScrollbar();
254
255
256 // finally refresh the display -- but only redraw as few lines as possible
257 // to avoid flicker
258 if ( GetFirstVisibleLine() > lineLastOld ||
259 GetLastVisibleLine() < lineFirstOld )
260 {
261 // the simplest case: we don't have any old lines left, just redraw
262 // everything
263 Refresh();
264 }
265 else // overlap between the lines we showed before and should show now
266 {
267 ScrollWindow(0, GetLinesHeight(GetFirstVisibleLine(), lineFirstOld));
268 }
269
270 return true;
271}
272
273bool wxVScrolledWindow::ScrollLines(int lines)
274{
275 lines += m_lineFirst;
276 if ( lines < 0 )
277 lines = 0;
278
279 return ScrollToLine(lines);
280}
281
282bool wxVScrolledWindow::ScrollPages(int pages)
283{
284 bool didSomething = false;
285
286 while ( pages )
287 {
288 int line;
289 if ( pages > 0 )
290 {
291 line = GetLastVisibleLine();
292 pages--;
293 }
294 else // pages < 0
295 {
296 line = FindFirstFromBottom(GetFirstVisibleLine());
297 pages++;
298 }
299
300 didSomething = ScrollToLine(line);
301 }
302
303 return didSomething;
304}
305
306// ----------------------------------------------------------------------------
307// event handling
308// ----------------------------------------------------------------------------
309
310void wxVScrolledWindow::OnSize(wxSizeEvent& event)
311{
312 UpdateScrollbar();
313
314 event.Skip();
315}
316
317void wxVScrolledWindow::OnScroll(wxScrollWinEvent& event)
318{
319 size_t lineFirstNew;
320
321 const wxEventType evtType = event.GetEventType();
322 if ( evtType == wxEVT_SCROLLWIN_TOP )
323 {
324 lineFirstNew = 0;
325 }
326 else if ( evtType == wxEVT_SCROLLWIN_BOTTOM )
327 {
328 lineFirstNew = m_lineMax;
329 }
330 else if ( evtType == wxEVT_SCROLLWIN_LINEUP )
331 {
332 lineFirstNew = m_lineFirst ? m_lineFirst - 1 : 0;
333 }
334 else if ( evtType == wxEVT_SCROLLWIN_LINEDOWN )
335 {
336 lineFirstNew = m_lineFirst + 1;
337 }
338 else if ( evtType == wxEVT_SCROLLWIN_PAGEUP )
339 {
340 lineFirstNew = FindFirstFromBottom(m_lineFirst);
341 }
342 else if ( evtType == wxEVT_SCROLLWIN_PAGEDOWN )
343 {
344 lineFirstNew = GetLastVisibleLine();
345 }
346 else // unknown scroll event?
347 {
348 if ( evtType == wxEVT_SCROLLWIN_THUMBRELEASE )
349 {
350 lineFirstNew = event.GetPosition();
351 }
352 else
353 {
354 wxASSERT_MSG( evtType == wxEVT_SCROLLWIN_THUMBTRACK,
355 _T("unknown scroll event type?") );
356
357 // don't do anything, otherwise dragging the thumb around would
358 // be too slow
359 return;
360 }
361 }
362
363 ScrollToLine(lineFirstNew);
b544a278
VZ
364
365#ifdef __WXMAC__
366 Update();
367#endif // __WXMAC__
cf7d6329
VZ
368}
369