]>
Commit | Line | Data |
---|---|---|
cf7d6329 VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/generic/vscroll.cpp | |
3 | // Purpose: wxVScrolledWindow implementation | |
4 | // Author: Vadim Zeitlin | |
d77836e4 | 5 | // Modified by: Brad Anderson |
cf7d6329 VZ |
6 | // Created: 30.05.03 |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org> | |
65571936 | 9 | // Licence: wxWindows licence |
cf7d6329 VZ |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
12 | // ============================================================================ | |
13 | // declarations | |
14 | // ============================================================================ | |
15 | ||
16 | // ---------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ---------------------------------------------------------------------------- | |
19 | ||
687dcff3 VS |
20 | // For compilers that support precompilation, includes "wx.h". |
21 | #include "wx/wxprec.h" | |
22 | ||
23 | #ifdef __BORLANDC__ | |
24 | #pragma hdrstop | |
25 | #endif | |
26 | ||
cf7d6329 | 27 | #include "wx/vscroll.h" |
d77836e4 RR |
28 | #include "wx/sizer.h" |
29 | #include "wx/dc.h" | |
cf7d6329 VZ |
30 | |
31 | // ---------------------------------------------------------------------------- | |
32 | // event tables | |
33 | // ---------------------------------------------------------------------------- | |
34 | ||
35 | BEGIN_EVENT_TABLE(wxVScrolledWindow, wxPanel) | |
36 | EVT_SIZE(wxVScrolledWindow::OnSize) | |
37 | EVT_SCROLLWIN(wxVScrolledWindow::OnScroll) | |
4719e58d RD |
38 | #if wxUSE_MOUSEWHEEL |
39 | EVT_MOUSEWHEEL(wxVScrolledWindow::OnMouseWheel) | |
40 | #endif | |
cf7d6329 VZ |
41 | END_EVENT_TABLE() |
42 | ||
43 | ||
44 | // ============================================================================ | |
45 | // implementation | |
46 | // ============================================================================ | |
47 | ||
0c8392ca RD |
48 | IMPLEMENT_ABSTRACT_CLASS(wxVScrolledWindow, wxPanel) |
49 | ||
cf7d6329 VZ |
50 | // ---------------------------------------------------------------------------- |
51 | // initialization | |
52 | // ---------------------------------------------------------------------------- | |
53 | ||
54 | void wxVScrolledWindow::Init() | |
55 | { | |
56 | // we're initially empty | |
57 | m_lineMax = | |
58 | m_lineFirst = 0; | |
59 | ||
60 | // this one should always be strictly positive | |
61 | m_nVisible = 1; | |
62 | ||
63 | m_heightTotal = 0; | |
4719e58d RD |
64 | |
65 | #if wxUSE_MOUSEWHEEL | |
66 | m_sumWheelRotation = 0; | |
67 | #endif | |
cf7d6329 VZ |
68 | } |
69 | ||
70 | // ---------------------------------------------------------------------------- | |
71 | // various helpers | |
72 | // ---------------------------------------------------------------------------- | |
73 | ||
1e0af0bc VZ |
74 | wxCoord wxVScrolledWindow::EstimateTotalHeight() const |
75 | { | |
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; | |
81 | ||
82 | wxCoord heightTotal; | |
83 | if ( m_lineMax < 3*NUM_LINES_TO_SAMPLE ) | |
84 | { | |
85 | // in this case calculating exactly is faster and more correct than | |
86 | // guessing | |
87 | heightTotal = GetLinesHeight(0, m_lineMax); | |
88 | } | |
89 | else // too many lines to calculate exactly | |
90 | { | |
91 | // look at some lines in the beginning/middle/end | |
92 | heightTotal = | |
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); | |
97 | ||
98 | // use the height of the lines we looked as the average | |
99 | heightTotal = (wxCoord) | |
999836aa | 100 | (((float)heightTotal / (3*NUM_LINES_TO_SAMPLE)) * m_lineMax); |
1e0af0bc VZ |
101 | } |
102 | ||
103 | return heightTotal; | |
104 | } | |
105 | ||
cf7d6329 VZ |
106 | wxCoord wxVScrolledWindow::GetLinesHeight(size_t lineMin, size_t lineMax) const |
107 | { | |
108 | if ( lineMin == lineMax ) | |
109 | return 0; | |
110 | else if ( lineMin > lineMax ) | |
111 | return -GetLinesHeight(lineMax, lineMin); | |
112 | //else: lineMin < lineMax | |
113 | ||
114 | // let the user code know that we're going to need all these lines | |
115 | OnGetLinesHint(lineMin, lineMax); | |
116 | ||
117 | // do sum up their heights | |
118 | wxCoord height = 0; | |
119 | for ( size_t line = lineMin; line < lineMax; line++ ) | |
120 | { | |
121 | height += OnGetLineHeight(line); | |
122 | } | |
123 | ||
124 | return height; | |
125 | } | |
126 | ||
0b49ccf8 | 127 | size_t wxVScrolledWindow::FindFirstFromBottom(size_t lineLast, bool full) |
cf7d6329 VZ |
128 | { |
129 | const wxCoord hWindow = GetClientSize().y; | |
130 | ||
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; | |
134 | wxCoord h = 0; | |
135 | for ( ;; ) | |
136 | { | |
137 | h += OnGetLineHeight(lineFirst); | |
138 | ||
139 | if ( h > hWindow ) | |
140 | { | |
0b49ccf8 VZ |
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 | |
144 | if ( full ) | |
145 | { | |
146 | lineFirst++; | |
147 | } | |
cf7d6329 VZ |
148 | |
149 | break; | |
150 | } | |
151 | ||
152 | if ( !lineFirst ) | |
153 | break; | |
154 | ||
155 | lineFirst--; | |
156 | } | |
157 | ||
158 | return lineFirst; | |
159 | } | |
160 | ||
161 | void wxVScrolledWindow::UpdateScrollbar() | |
162 | { | |
163 | // see how many lines can we fit on screen | |
164 | const wxCoord hWindow = GetClientSize().y; | |
165 | ||
166 | wxCoord h = 0; | |
167 | size_t line; | |
168 | for ( line = m_lineFirst; line < m_lineMax; line++ ) | |
169 | { | |
170 | if ( h > hWindow ) | |
171 | break; | |
172 | ||
173 | h += OnGetLineHeight(line); | |
174 | } | |
175 | ||
176 | m_nVisible = line - m_lineFirst; | |
177 | ||
178 | int pageSize = m_nVisible; | |
179 | if ( h > hWindow ) | |
180 | { | |
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 | |
184 | pageSize--; | |
185 | } | |
186 | ||
187 | // set the scrollbar parameters to reflect this | |
188 | SetScrollbar(wxVERTICAL, m_lineFirst, pageSize, m_lineMax); | |
189 | } | |
190 | ||
191 | // ---------------------------------------------------------------------------- | |
192 | // operations | |
193 | // ---------------------------------------------------------------------------- | |
194 | ||
195 | void wxVScrolledWindow::SetLineCount(size_t count) | |
196 | { | |
197 | // save the number of lines | |
198 | m_lineMax = count; | |
199 | ||
1e0af0bc VZ |
200 | // and our estimate for their total height |
201 | m_heightTotal = EstimateTotalHeight(); | |
cf7d6329 VZ |
202 | |
203 | // recalculate the scrollbars parameters | |
e0c6027b | 204 | m_lineFirst = 1; // make sure it is != 0 |
cf7d6329 VZ |
205 | ScrollToLine(0); |
206 | } | |
207 | ||
e0c6027b VZ |
208 | void wxVScrolledWindow::RefreshLine(size_t line) |
209 | { | |
210 | // is this line visible? | |
211 | if ( !IsVisible(line) ) | |
212 | { | |
213 | // no, it is useless to do anything | |
214 | return; | |
215 | } | |
216 | ||
217 | // calculate the rect occupied by this line on screen | |
218 | wxRect rect; | |
219 | rect.width = GetClientSize().x; | |
220 | rect.height = OnGetLineHeight(line); | |
dd932cbe | 221 | for ( size_t n = GetVisibleBegin(); n < line; n++ ) |
e0c6027b VZ |
222 | { |
223 | rect.y += OnGetLineHeight(n); | |
224 | } | |
ae0f0223 VZ |
225 | |
226 | // do refresh it | |
227 | RefreshRect(rect); | |
228 | } | |
229 | ||
230 | void wxVScrolledWindow::RefreshLines(size_t from, size_t to) | |
231 | { | |
232 | wxASSERT_MSG( from <= to, _T("RefreshLines(): empty range") ); | |
233 | ||
234 | // clump the range to just the visible lines -- it is useless to refresh | |
235 | // the other ones | |
dd932cbe VZ |
236 | if ( from < GetVisibleBegin() ) |
237 | from = GetVisibleBegin(); | |
ae0f0223 | 238 | |
dd932cbe VZ |
239 | if ( to >= GetVisibleEnd() ) |
240 | to = GetVisibleEnd(); | |
241 | else | |
242 | to++; | |
ae0f0223 VZ |
243 | |
244 | // calculate the rect occupied by these lines on screen | |
245 | wxRect rect; | |
246 | rect.width = GetClientSize().x; | |
dd932cbe | 247 | for ( size_t nBefore = GetVisibleBegin(); nBefore < from; nBefore++ ) |
ae0f0223 VZ |
248 | { |
249 | rect.y += OnGetLineHeight(nBefore); | |
250 | } | |
251 | ||
dd932cbe | 252 | for ( size_t nBetween = from; nBetween < to; nBetween++ ) |
ae0f0223 VZ |
253 | { |
254 | rect.height += OnGetLineHeight(nBetween); | |
255 | } | |
e0c6027b VZ |
256 | |
257 | // do refresh it | |
258 | RefreshRect(rect); | |
259 | } | |
260 | ||
8b053348 VZ |
261 | void wxVScrolledWindow::RefreshAll() |
262 | { | |
263 | UpdateScrollbar(); | |
264 | ||
265 | Refresh(); | |
266 | } | |
267 | ||
d77836e4 RR |
268 | bool wxVScrolledWindow::Layout() |
269 | { | |
270 | if(GetSizer()) | |
271 | { | |
272 | // adjust the sizer dimensions/position taking into account the | |
273 | // virtual size and scrolled position of the window. | |
274 | ||
275 | int y, w, h; // x is always 0 so no variable needed | |
276 | ||
277 | y = -GetLinesHeight(0, GetFirstVisibleLine()); | |
278 | GetVirtualSize(&w, &h); | |
279 | GetSizer()->SetDimension(0, y, w, h); | |
280 | return true; | |
281 | } | |
282 | ||
283 | // fall back to default for LayoutConstraints | |
284 | return wxPanel::Layout(); | |
285 | } | |
286 | ||
e0c6027b VZ |
287 | int wxVScrolledWindow::HitTest(wxCoord WXUNUSED(x), wxCoord y) const |
288 | { | |
dd932cbe VZ |
289 | const size_t lineMax = GetVisibleEnd(); |
290 | for ( size_t line = GetVisibleBegin(); line < lineMax; line++ ) | |
e0c6027b VZ |
291 | { |
292 | y -= OnGetLineHeight(line); | |
293 | if ( y < 0 ) | |
294 | return line; | |
295 | } | |
296 | ||
297 | return wxNOT_FOUND; | |
298 | } | |
299 | ||
cf7d6329 VZ |
300 | // ---------------------------------------------------------------------------- |
301 | // scrolling | |
302 | // ---------------------------------------------------------------------------- | |
303 | ||
304 | bool wxVScrolledWindow::ScrollToLine(size_t line) | |
305 | { | |
306 | if ( !m_lineMax ) | |
307 | { | |
308 | // we're empty, code below doesn't make sense in this case | |
309 | return false; | |
310 | } | |
311 | ||
312 | // determine the real first line to scroll to: we shouldn't scroll beyond | |
313 | // the end | |
0b49ccf8 | 314 | size_t lineFirstLast = FindFirstFromBottom(m_lineMax - 1, true); |
cf7d6329 VZ |
315 | if ( line > lineFirstLast ) |
316 | line = lineFirstLast; | |
317 | ||
318 | // anything to do? | |
319 | if ( line == m_lineFirst ) | |
320 | { | |
321 | // no | |
322 | return false; | |
323 | } | |
324 | ||
325 | ||
326 | // remember the currently shown lines for the refresh code below | |
d77836e4 | 327 | size_t lineFirstOld = GetVisibleBegin(); |
cf7d6329 VZ |
328 | |
329 | m_lineFirst = line; | |
330 | ||
331 | ||
332 | // the size of scrollbar thumb could have changed | |
333 | UpdateScrollbar(); | |
334 | ||
d77836e4 RR |
335 | // finally, scroll the actual window |
336 | ScrollWindow(0, GetLinesHeight(GetVisibleBegin(), lineFirstOld)); | |
cf7d6329 VZ |
337 | |
338 | return true; | |
339 | } | |
340 | ||
341 | bool wxVScrolledWindow::ScrollLines(int lines) | |
342 | { | |
343 | lines += m_lineFirst; | |
344 | if ( lines < 0 ) | |
345 | lines = 0; | |
346 | ||
347 | return ScrollToLine(lines); | |
348 | } | |
349 | ||
350 | bool wxVScrolledWindow::ScrollPages(int pages) | |
351 | { | |
352 | bool didSomething = false; | |
353 | ||
354 | while ( pages ) | |
355 | { | |
356 | int line; | |
357 | if ( pages > 0 ) | |
358 | { | |
dd932cbe VZ |
359 | line = GetVisibleEnd(); |
360 | if ( line ) | |
361 | line--; | |
cf7d6329 VZ |
362 | pages--; |
363 | } | |
364 | else // pages < 0 | |
365 | { | |
dd932cbe | 366 | line = FindFirstFromBottom(GetVisibleBegin()); |
cf7d6329 VZ |
367 | pages++; |
368 | } | |
369 | ||
370 | didSomething = ScrollToLine(line); | |
371 | } | |
372 | ||
373 | return didSomething; | |
374 | } | |
375 | ||
376 | // ---------------------------------------------------------------------------- | |
377 | // event handling | |
378 | // ---------------------------------------------------------------------------- | |
379 | ||
380 | void wxVScrolledWindow::OnSize(wxSizeEvent& event) | |
381 | { | |
382 | UpdateScrollbar(); | |
383 | ||
384 | event.Skip(); | |
385 | } | |
386 | ||
387 | void wxVScrolledWindow::OnScroll(wxScrollWinEvent& event) | |
388 | { | |
389 | size_t lineFirstNew; | |
390 | ||
391 | const wxEventType evtType = event.GetEventType(); | |
5d2ad055 | 392 | |
cf7d6329 VZ |
393 | if ( evtType == wxEVT_SCROLLWIN_TOP ) |
394 | { | |
395 | lineFirstNew = 0; | |
396 | } | |
397 | else if ( evtType == wxEVT_SCROLLWIN_BOTTOM ) | |
398 | { | |
399 | lineFirstNew = m_lineMax; | |
400 | } | |
401 | else if ( evtType == wxEVT_SCROLLWIN_LINEUP ) | |
402 | { | |
403 | lineFirstNew = m_lineFirst ? m_lineFirst - 1 : 0; | |
404 | } | |
405 | else if ( evtType == wxEVT_SCROLLWIN_LINEDOWN ) | |
406 | { | |
407 | lineFirstNew = m_lineFirst + 1; | |
408 | } | |
409 | else if ( evtType == wxEVT_SCROLLWIN_PAGEUP ) | |
410 | { | |
411 | lineFirstNew = FindFirstFromBottom(m_lineFirst); | |
412 | } | |
413 | else if ( evtType == wxEVT_SCROLLWIN_PAGEDOWN ) | |
414 | { | |
dd932cbe VZ |
415 | lineFirstNew = GetVisibleEnd(); |
416 | if ( lineFirstNew ) | |
417 | lineFirstNew--; | |
cf7d6329 | 418 | } |
5d2ad055 RD |
419 | else if ( evtType == wxEVT_SCROLLWIN_THUMBRELEASE ) |
420 | { | |
421 | lineFirstNew = event.GetPosition(); | |
422 | } | |
423 | else if ( evtType == wxEVT_SCROLLWIN_THUMBTRACK ) | |
424 | { | |
425 | lineFirstNew = event.GetPosition(); | |
426 | } | |
ca65c044 | 427 | |
cf7d6329 VZ |
428 | else // unknown scroll event? |
429 | { | |
5d2ad055 RD |
430 | wxFAIL_MSG( _T("unknown scroll event type?") ); |
431 | return; | |
cf7d6329 VZ |
432 | } |
433 | ||
434 | ScrollToLine(lineFirstNew); | |
b544a278 VZ |
435 | |
436 | #ifdef __WXMAC__ | |
437 | Update(); | |
438 | #endif // __WXMAC__ | |
cf7d6329 VZ |
439 | } |
440 | ||
4719e58d RD |
441 | #if wxUSE_MOUSEWHEEL |
442 | ||
443 | void wxVScrolledWindow::OnMouseWheel(wxMouseEvent& event) | |
444 | { | |
445 | m_sumWheelRotation += event.GetWheelRotation(); | |
446 | int delta = event.GetWheelDelta(); | |
447 | ||
448 | // how much to scroll this time | |
449 | int units_to_scroll = -(m_sumWheelRotation/delta); | |
450 | if ( !units_to_scroll ) | |
451 | return; | |
452 | ||
453 | m_sumWheelRotation += units_to_scroll*delta; | |
454 | ||
455 | if ( !event.IsPageScroll() ) | |
456 | ScrollLines( units_to_scroll*event.GetLinesPerAction() ); | |
457 | else | |
458 | // scroll pages instead of lines | |
459 | ScrollPages( units_to_scroll ); | |
460 | } | |
461 | ||
462 | #endif | |
d77836e4 RR |
463 | |
464 | ||
465 | ||
466 | ||
467 | // ---------------------------------------------------------------------------- | |
468 | // wxVarScrolled Window event tables | |
469 | // ---------------------------------------------------------------------------- | |
470 | ||
471 | BEGIN_EVENT_TABLE(wxHVScrolledWindow, wxPanel) | |
472 | EVT_SIZE(wxHVScrolledWindow::OnSize) | |
473 | EVT_SCROLLWIN(wxHVScrolledWindow::OnScroll) | |
474 | #if wxUSE_MOUSEWHEEL | |
475 | EVT_MOUSEWHEEL(wxHVScrolledWindow::OnMouseWheel) | |
476 | #endif | |
477 | END_EVENT_TABLE() | |
478 | ||
479 | ||
480 | // ============================================================================ | |
481 | // wxVarScrolled implementation | |
482 | // ============================================================================ | |
483 | ||
484 | IMPLEMENT_ABSTRACT_CLASS(wxHVScrolledWindow, wxPanel) | |
485 | ||
486 | // ---------------------------------------------------------------------------- | |
487 | // initialization | |
488 | // ---------------------------------------------------------------------------- | |
489 | ||
490 | void wxHVScrolledWindow::Init() | |
491 | { | |
492 | // we're initially empty | |
493 | m_rowsMax = | |
494 | m_columnsMax = | |
555b2ce9 | 495 | m_rowsFirst = |
d77836e4 RR |
496 | m_columnsFirst = 0; |
497 | ||
498 | // these should always be strictly positive | |
499 | m_nRowsVisible = | |
500 | m_nColumnsVisible = 1; | |
501 | ||
502 | m_widthTotal = | |
503 | m_heightTotal = 0; | |
504 | ||
505 | m_physicalScrolling = true; | |
506 | ||
507 | #if wxUSE_MOUSEWHEEL | |
508 | m_sumWheelRotation = 0; | |
509 | #endif | |
510 | } | |
511 | ||
512 | // ---------------------------------------------------------------------------- | |
513 | // various helpers | |
514 | // ---------------------------------------------------------------------------- | |
515 | ||
516 | wxCoord wxHVScrolledWindow::EstimateTotalHeight() const | |
517 | { | |
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; | |
523 | ||
524 | wxCoord heightTotal; | |
525 | if ( m_rowsMax < 3*NUM_LINES_TO_SAMPLE ) | |
526 | { | |
527 | // in this case calculating exactly is faster and more correct than | |
528 | // guessing | |
529 | heightTotal = GetRowsHeight(0, m_rowsMax); | |
530 | } | |
531 | else // too many lines to calculate exactly | |
532 | { | |
533 | // look at some lines in the beginning/middle/end | |
534 | heightTotal = | |
535 | GetRowsHeight(0, NUM_LINES_TO_SAMPLE) + | |
536 | GetRowsHeight(m_rowsMax - NUM_LINES_TO_SAMPLE, | |
537 | m_rowsMax) + | |
538 | GetRowsHeight(m_rowsMax/2 - NUM_LINES_TO_SAMPLE/2, | |
539 | m_rowsMax/2 + NUM_LINES_TO_SAMPLE/2); | |
540 | ||
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); | |
544 | } | |
545 | ||
546 | return heightTotal; | |
547 | } | |
548 | ||
549 | wxCoord wxHVScrolledWindow::EstimateTotalWidth() const | |
550 | { | |
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; | |
556 | ||
557 | wxCoord widthTotal; | |
558 | if ( m_columnsMax < 3*NUM_LINES_TO_SAMPLE ) | |
559 | { | |
560 | // in this case calculating exactly is faster and more correct than | |
561 | // guessing | |
562 | widthTotal = GetColumnsWidth(0, m_columnsMax); | |
563 | } | |
564 | else // too many lines to calculate exactly | |
565 | { | |
566 | // look at some lines in the beginning/middle/end | |
567 | widthTotal = | |
568 | GetColumnsWidth(0, NUM_LINES_TO_SAMPLE) + | |
569 | GetColumnsWidth(m_columnsMax - NUM_LINES_TO_SAMPLE, | |
570 | m_columnsMax) + | |
571 | GetColumnsWidth(m_columnsMax/2 - NUM_LINES_TO_SAMPLE/2, | |
572 | m_columnsMax/2 + NUM_LINES_TO_SAMPLE/2); | |
573 | ||
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); | |
577 | } | |
578 | ||
579 | return widthTotal; | |
580 | } | |
581 | ||
582 | wxCoord wxHVScrolledWindow::GetRowsHeight(size_t rowMin, size_t rowMax) const | |
583 | { | |
584 | if ( rowMin == rowMax ) | |
585 | return 0; | |
586 | else if ( rowMin > rowMax ) | |
587 | return -GetRowsHeight(rowMax, rowMin); | |
588 | //else: lineMin < lineMax | |
589 | ||
590 | // let the user code know that we're going to need all these lines | |
591 | OnGetRowsHeightHint(rowMin, rowMax); | |
592 | ||
593 | // do sum up their heights | |
594 | wxCoord height = 0; | |
595 | for ( size_t row = rowMin; row < rowMax; row++ ) | |
596 | { | |
597 | height += OnGetRowHeight(row); | |
598 | } | |
599 | ||
600 | return height; | |
601 | } | |
602 | ||
603 | wxCoord wxHVScrolledWindow::GetColumnsWidth(size_t columnMin, size_t columnMax) const | |
604 | { | |
605 | if ( columnMin == columnMax ) | |
606 | return 0; | |
607 | else if ( columnMin > columnMax ) | |
608 | return -GetColumnsWidth(columnMax, columnMin); | |
609 | //else: lineMin < lineMax | |
610 | ||
611 | // let the user code know that we're going to need all these lines | |
612 | OnGetColumnsWidthHint(columnMin, columnMax); | |
613 | ||
614 | // do sum up their widths | |
615 | wxCoord width = 0; | |
616 | for ( size_t column = columnMin; column < columnMax; column++ ) | |
617 | { | |
618 | width += OnGetColumnWidth(column); | |
619 | } | |
620 | ||
621 | return width; | |
622 | } | |
623 | ||
624 | size_t wxHVScrolledWindow::FindFirstFromBottom(size_t rowLast, bool full) | |
625 | { | |
626 | const wxCoord hWindow = GetClientSize().y; | |
627 | ||
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; | |
631 | wxCoord h = 0; | |
632 | for ( ;; ) | |
633 | { | |
634 | h += OnGetRowHeight(lineFirst); | |
635 | ||
636 | if ( h > hWindow ) | |
637 | { | |
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 | |
641 | if ( full ) | |
642 | { | |
643 | lineFirst++; | |
644 | } | |
645 | ||
646 | break; | |
647 | } | |
648 | ||
649 | if ( !lineFirst ) | |
650 | break; | |
651 | ||
652 | lineFirst--; | |
653 | } | |
654 | ||
655 | return lineFirst; | |
656 | } | |
657 | ||
658 | size_t wxHVScrolledWindow::FindFirstFromRight(size_t columnLast, bool full) | |
659 | { | |
660 | const wxCoord wWindow = GetClientSize().x; | |
661 | ||
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; | |
665 | wxCoord w = 0; | |
666 | for ( ;; ) | |
667 | { | |
668 | w += OnGetColumnWidth(lineFirst); | |
669 | ||
670 | if ( w > wWindow ) | |
671 | { | |
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 | |
675 | if ( full ) | |
676 | { | |
677 | lineFirst++; | |
678 | } | |
679 | ||
680 | break; | |
681 | } | |
682 | ||
683 | if ( !lineFirst ) | |
684 | break; | |
685 | ||
686 | lineFirst--; | |
687 | } | |
688 | ||
689 | return lineFirst; | |
690 | } | |
691 | ||
692 | void wxHVScrolledWindow::UpdateScrollbars() | |
693 | { | |
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; | |
697 | ||
698 | // first do the horizontal calculations | |
699 | wxCoord w = 0; | |
700 | size_t column; | |
701 | for ( column = m_columnsFirst; column < m_columnsMax; column++ ) | |
702 | { | |
703 | if ( w > wWindow ) | |
704 | break; | |
705 | ||
706 | w += OnGetColumnWidth(column); | |
707 | } | |
708 | ||
709 | m_nColumnsVisible = column - m_columnsFirst; | |
710 | ||
711 | int columnsPageSize = m_nColumnsVisible; | |
712 | if ( w > wWindow ) | |
713 | { | |
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 | |
717 | columnsPageSize--; | |
718 | } | |
719 | ||
720 | // set the scrollbar parameters to reflect this | |
721 | SetScrollbar(wxHORIZONTAL, m_columnsFirst, columnsPageSize, m_columnsMax); | |
722 | ||
723 | ||
724 | // now do the vertical calculations | |
725 | wxCoord h = 0; | |
726 | size_t row; | |
727 | for ( row = m_rowsFirst; row < m_rowsMax; row++ ) | |
728 | { | |
729 | if ( h > hWindow ) | |
730 | break; | |
731 | ||
732 | h += OnGetRowHeight(row); | |
733 | } | |
734 | ||
735 | m_nRowsVisible = row - m_rowsFirst; | |
736 | ||
737 | int rowsPageSize = m_nRowsVisible; | |
738 | if ( h > hWindow ) | |
739 | { | |
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 | |
743 | rowsPageSize--; | |
744 | } | |
745 | ||
746 | // set the scrollbar parameters to reflect this | |
747 | SetScrollbar(wxVERTICAL, m_rowsFirst, rowsPageSize, m_rowsMax); | |
748 | } | |
749 | ||
750 | void wxHVScrolledWindow::PrepareDC(wxDC& dc) | |
751 | { | |
752 | if(m_physicalScrolling) | |
753 | { | |
754 | dc.SetDeviceOrigin(-GetColumnsWidth(0, GetVisibleColumnsBegin()), | |
755 | -GetRowsHeight(0, GetVisibleRowsBegin())); | |
756 | } | |
757 | } | |
758 | ||
759 | // ---------------------------------------------------------------------------- | |
760 | // operations | |
761 | // ---------------------------------------------------------------------------- | |
762 | ||
763 | void wxHVScrolledWindow::SetRowColumnCounts(size_t rowCount, size_t columnCount) | |
764 | { | |
765 | // save the number of lines | |
766 | m_rowsMax = rowCount; | |
767 | m_columnsMax = columnCount; | |
768 | ||
769 | // and our estimate for their total height and width | |
770 | m_heightTotal = EstimateTotalHeight(); | |
771 | m_widthTotal = EstimateTotalWidth(); | |
555b2ce9 | 772 | |
d77836e4 RR |
773 | // recalculate the scrollbars parameters |
774 | if(m_rowsFirst >= rowCount) | |
775 | m_rowsFirst = rowCount-1; | |
776 | ||
777 | if(m_columnsFirst >= columnCount) | |
778 | m_columnsFirst = columnCount-1; | |
555b2ce9 | 779 | |
d77836e4 RR |
780 | if(m_rowsFirst < 0) |
781 | m_rowsFirst = 0; | |
555b2ce9 | 782 | |
d77836e4 RR |
783 | if(m_columnsFirst < 0) |
784 | m_columnsFirst = 0; | |
785 | ||
786 | ScrollToRowColumn(m_rowsFirst, m_columnsFirst); | |
787 | } | |
788 | ||
789 | void wxHVScrolledWindow::RefreshColumn(size_t column) | |
790 | { | |
791 | // is this line visible? | |
792 | if ( !IsColumnVisible(column) ) | |
793 | { | |
794 | // no, it is useless to do anything | |
795 | return; | |
796 | } | |
797 | ||
798 | // calculate the rect occupied by this line on screen | |
799 | wxRect rect; | |
800 | rect.width = OnGetColumnWidth(column); | |
801 | rect.height = GetClientSize().y; | |
802 | for ( size_t n = GetVisibleColumnsBegin(); n < column; n++ ) | |
803 | { | |
804 | rect.y += OnGetColumnWidth(n); | |
805 | } | |
806 | ||
807 | // do refresh it | |
808 | RefreshRect(rect); | |
809 | } | |
810 | ||
811 | void wxHVScrolledWindow::RefreshRow(size_t row) | |
812 | { | |
813 | // is this line visible? | |
814 | if ( !IsRowVisible(row) ) | |
815 | { | |
816 | // no, it is useless to do anything | |
817 | return; | |
818 | } | |
819 | ||
820 | // calculate the rect occupied by this line on screen | |
821 | wxRect rect; | |
822 | rect.width = GetClientSize().x; | |
823 | rect.height = OnGetRowHeight(row); | |
824 | for ( size_t n = GetVisibleRowsBegin(); n < row; n++ ) | |
825 | { | |
826 | rect.y += OnGetRowHeight(n); | |
827 | } | |
828 | ||
829 | // do refresh it | |
830 | RefreshRect(rect); | |
831 | } | |
832 | ||
833 | void wxHVScrolledWindow::RefreshRowColumn(size_t row, size_t column) | |
834 | { | |
835 | // is this line visible? | |
836 | if ( !IsRowVisible(row) || !IsColumnVisible(column) ) | |
837 | { | |
838 | // no, it is useless to do anything | |
839 | return; | |
840 | } | |
841 | ||
842 | // calculate the rect occupied by this cell on screen | |
843 | wxRect rect; | |
844 | rect.height = OnGetRowHeight(row); | |
845 | rect.width = OnGetColumnWidth(column); | |
846 | ||
555b2ce9 WS |
847 | size_t n; |
848 | ||
849 | for ( n = GetVisibleRowsBegin(); n < row; n++ ) | |
d77836e4 RR |
850 | { |
851 | rect.y += OnGetRowHeight(n); | |
852 | } | |
853 | ||
555b2ce9 | 854 | for ( n = GetVisibleColumnsBegin(); n < column; n++ ) |
d77836e4 RR |
855 | { |
856 | rect.x += OnGetColumnWidth(n); | |
857 | } | |
858 | ||
859 | // do refresh it | |
860 | RefreshRect(rect); | |
861 | } | |
862 | ||
863 | void wxHVScrolledWindow::RefreshRows(size_t from, size_t to) | |
864 | { | |
865 | wxASSERT_MSG( from <= to, _T("RefreshRows(): empty range") ); | |
866 | ||
867 | // clump the range to just the visible lines -- it is useless to refresh | |
868 | // the other ones | |
869 | if ( from < GetVisibleRowsBegin() ) | |
870 | from = GetVisibleRowsBegin(); | |
871 | ||
872 | if ( to > GetVisibleRowsEnd() ) | |
873 | to = GetVisibleRowsEnd(); | |
874 | ||
875 | // calculate the rect occupied by these lines on screen | |
876 | wxRect rect; | |
877 | rect.width = GetClientSize().x; | |
878 | for ( size_t nBefore = GetVisibleRowsBegin(); | |
879 | nBefore < from; | |
880 | nBefore++ ) | |
881 | { | |
882 | rect.y += OnGetRowHeight(nBefore); | |
883 | } | |
884 | ||
885 | for ( size_t nBetween = from; nBetween <= to; nBetween++ ) | |
886 | { | |
887 | rect.height += OnGetRowHeight(nBetween); | |
888 | } | |
889 | ||
890 | // do refresh it | |
891 | RefreshRect(rect); | |
892 | } | |
893 | ||
894 | void wxHVScrolledWindow::RefreshColumns(size_t from, size_t to) | |
895 | { | |
896 | wxASSERT_MSG( from <= to, _T("RefreshColumns(): empty range") ); | |
897 | ||
898 | // clump the range to just the visible lines -- it is useless to refresh | |
899 | // the other ones | |
900 | if ( from < GetVisibleColumnsBegin() ) | |
901 | from = GetVisibleColumnsBegin(); | |
902 | ||
903 | if ( to > GetVisibleColumnsEnd() ) | |
904 | to = GetVisibleColumnsEnd(); | |
905 | ||
906 | // calculate the rect occupied by these lines on screen | |
907 | wxRect rect; | |
908 | rect.height = GetClientSize().y; | |
909 | for ( size_t nBefore = GetVisibleColumnsBegin(); | |
910 | nBefore < from; | |
911 | nBefore++ ) | |
912 | { | |
913 | rect.x += OnGetColumnWidth(nBefore); | |
914 | } | |
915 | ||
916 | for ( size_t nBetween = from; nBetween <= to; nBetween++ ) | |
917 | { | |
918 | rect.width += OnGetColumnWidth(nBetween); | |
919 | } | |
920 | ||
921 | // do refresh it | |
922 | RefreshRect(rect); | |
923 | } | |
924 | ||
925 | void wxHVScrolledWindow::RefreshRowsColumns(size_t fromRow, size_t toRow, | |
926 | size_t fromColumn, size_t toColumn) | |
927 | { | |
928 | wxASSERT_MSG( fromRow <= toRow || fromColumn <= toColumn, | |
929 | _T("RefreshRowsColumns(): empty range") ); | |
930 | ||
931 | // clump the range to just the visible lines -- it is useless to refresh | |
932 | // the other ones | |
933 | if ( fromRow < GetVisibleRowsBegin() ) | |
934 | fromRow = GetVisibleRowsBegin(); | |
935 | ||
936 | if ( toRow > GetVisibleRowsEnd() ) | |
937 | toRow = GetVisibleRowsEnd(); | |
938 | ||
939 | if ( fromColumn < GetVisibleColumnsBegin() ) | |
940 | fromColumn = GetVisibleColumnsBegin(); | |
941 | ||
942 | if ( toColumn > GetVisibleColumnsEnd() ) | |
943 | toColumn = GetVisibleColumnsEnd(); | |
944 | ||
945 | // calculate the rect occupied by these lines on screen | |
946 | wxRect rect; | |
555b2ce9 WS |
947 | size_t nBefore, nBetween; |
948 | ||
949 | for ( nBefore = GetVisibleRowsBegin(); | |
d77836e4 RR |
950 | nBefore < fromRow; |
951 | nBefore++ ) | |
952 | { | |
953 | rect.y += OnGetRowHeight(nBefore); | |
954 | } | |
955 | ||
555b2ce9 | 956 | for ( nBetween = fromRow; nBetween <= toRow; nBetween++ ) |
d77836e4 RR |
957 | { |
958 | rect.height += OnGetRowHeight(nBetween); | |
959 | } | |
960 | ||
555b2ce9 | 961 | for ( nBefore = GetVisibleColumnsBegin(); |
d77836e4 RR |
962 | nBefore < fromColumn; |
963 | nBefore++ ) | |
964 | { | |
965 | rect.x += OnGetColumnWidth(nBefore); | |
966 | } | |
967 | ||
555b2ce9 | 968 | for ( nBetween = fromColumn; nBetween <= toColumn; nBetween++ ) |
d77836e4 RR |
969 | { |
970 | rect.width += OnGetColumnWidth(nBetween); | |
971 | } | |
972 | ||
973 | // do refresh it | |
974 | RefreshRect(rect); | |
975 | } | |
976 | ||
977 | void wxHVScrolledWindow::RefreshAll() | |
978 | { | |
979 | UpdateScrollbars(); | |
980 | ||
981 | Refresh(); | |
982 | } | |
983 | ||
984 | bool wxHVScrolledWindow::Layout() | |
985 | { | |
986 | if(GetSizer() && m_physicalScrolling) | |
987 | { | |
988 | // adjust the sizer dimensions/position taking into account the | |
989 | // virtual size and scrolled position of the window. | |
990 | ||
991 | int x, y, w, h; | |
555b2ce9 | 992 | |
d77836e4 RR |
993 | y = -GetRowsHeight(0, GetVisibleRowsBegin()); |
994 | x = -GetColumnsWidth(0, GetVisibleColumnsBegin()); | |
995 | GetVirtualSize(&w, &h); | |
996 | GetSizer()->SetDimension(0, y, w, h); | |
997 | return true; | |
998 | } | |
999 | ||
1000 | // fall back to default for LayoutConstraints | |
1001 | return wxPanel::Layout(); | |
1002 | } | |
1003 | ||
1004 | wxPoint wxHVScrolledWindow::HitTest(wxCoord x, wxCoord y) const | |
1005 | { | |
1006 | const size_t rowMax = GetVisibleRowsEnd(); | |
1007 | const size_t columnMax = GetVisibleColumnsEnd(); | |
1008 | ||
1009 | wxPoint hit(wxNOT_FOUND, wxNOT_FOUND); | |
1010 | for ( size_t row = GetVisibleRowsBegin(); | |
1011 | row <= rowMax; | |
1012 | row++ ) | |
1013 | { | |
1014 | y -= OnGetRowHeight(row); | |
1015 | if ( y < 0 ) | |
1016 | hit.y = row; | |
1017 | } | |
555b2ce9 | 1018 | |
d77836e4 RR |
1019 | for ( size_t column = GetVisibleColumnsBegin(); |
1020 | column <= columnMax; | |
1021 | column++ ) | |
1022 | { | |
1023 | x -= OnGetColumnWidth(column); | |
1024 | if ( x < 0 ) | |
1025 | hit.x = column; | |
1026 | } | |
1027 | ||
1028 | return hit; | |
1029 | } | |
1030 | ||
1031 | // ---------------------------------------------------------------------------- | |
1032 | // scrolling | |
1033 | // ---------------------------------------------------------------------------- | |
1034 | ||
1035 | bool wxHVScrolledWindow::ScrollToRowColumn(size_t row, size_t column) | |
1036 | { | |
1037 | if ( !m_rowsMax && !m_columnsMax ) | |
1038 | { | |
1039 | // we're empty, code below doesn't make sense in this case | |
1040 | return false; | |
1041 | } | |
1042 | ||
1043 | bool scrolled = false; | |
1044 | scrolled |= ScrollToRow(row); | |
1045 | scrolled |= ScrollToColumn(column); | |
1046 | ||
1047 | return scrolled; | |
1048 | } | |
1049 | ||
1050 | bool wxHVScrolledWindow::ScrollToRow(size_t row) | |
1051 | { | |
1052 | if ( !m_rowsMax ) | |
1053 | { | |
1054 | // we're empty, code below doesn't make sense in this case | |
1055 | return false; | |
1056 | } | |
1057 | ||
1058 | // determine the real first line to scroll to: we shouldn't scroll beyond | |
1059 | // the end | |
1060 | size_t lineFirstLast = FindFirstFromBottom(m_rowsMax - 1, true); | |
1061 | if ( row > lineFirstLast ) | |
1062 | row = lineFirstLast; | |
555b2ce9 | 1063 | |
d77836e4 RR |
1064 | // anything to do? |
1065 | if ( row == m_rowsFirst ) | |
1066 | { | |
1067 | // no | |
1068 | return false; | |
1069 | } | |
1070 | ||
1071 | ||
1072 | // remember the currently shown lines for the refresh code below | |
1073 | size_t lineFirstOld = GetVisibleRowsBegin(); | |
1074 | ||
1075 | m_rowsFirst = row; | |
1076 | ||
1077 | ||
1078 | // the size of scrollbar thumb could have changed | |
1079 | UpdateScrollbars(); | |
1080 | ||
1081 | ||
1082 | // finally, scroll the actual window contents vertically | |
1083 | if(m_physicalScrolling) | |
1084 | ScrollWindow(0, GetRowsHeight(GetVisibleRowsBegin(), lineFirstOld)); | |
555b2ce9 | 1085 | |
d77836e4 RR |
1086 | return true; |
1087 | } | |
1088 | ||
1089 | bool wxHVScrolledWindow::ScrollToColumn(size_t column) | |
1090 | { | |
1091 | if ( !m_columnsMax ) | |
1092 | { | |
1093 | // we're empty, code below doesn't make sense in this case | |
1094 | return false; | |
1095 | } | |
1096 | ||
1097 | // determine the real first line to scroll to: we shouldn't scroll beyond | |
1098 | // the end | |
1099 | size_t lineFirstLast = FindFirstFromRight(m_columnsMax - 1, true); | |
1100 | if ( column > lineFirstLast ) | |
1101 | column = lineFirstLast; | |
1102 | ||
1103 | // anything to do? | |
1104 | if ( column == m_columnsFirst ) | |
1105 | { | |
1106 | // no | |
1107 | return false; | |
1108 | } | |
1109 | ||
1110 | ||
1111 | // remember the currently shown lines for the refresh code below | |
1112 | size_t lineFirstOld = GetVisibleColumnsBegin(); | |
1113 | ||
1114 | m_columnsFirst = column; | |
1115 | ||
1116 | ||
1117 | // the size of scrollbar thumb could have changed | |
1118 | UpdateScrollbars(); | |
1119 | ||
1120 | // finally, scroll the actual window contents horizontally | |
1121 | if(m_physicalScrolling) | |
1122 | ScrollWindow(GetColumnsWidth(GetVisibleColumnsBegin(), lineFirstOld), 0); | |
1123 | ||
1124 | return true; | |
1125 | } | |
1126 | ||
1127 | bool wxHVScrolledWindow::ScrollRows(int rows) | |
1128 | { | |
1129 | rows += m_rowsFirst; | |
1130 | if ( rows < 0 ) | |
1131 | rows = 0; | |
1132 | ||
1133 | return ScrollToRow(rows); | |
1134 | } | |
1135 | ||
1136 | bool wxHVScrolledWindow::ScrollColumns(int columns) | |
1137 | { | |
1138 | columns += m_columnsFirst; | |
1139 | if ( columns < 0 ) | |
1140 | columns = 0; | |
1141 | ||
1142 | return ScrollToColumn(columns); | |
1143 | } | |
1144 | ||
1145 | bool wxHVScrolledWindow::ScrollRowsColumns(int rows, int columns) | |
1146 | { | |
1147 | rows += m_rowsFirst; | |
1148 | if ( rows < 0 ) | |
1149 | rows = 0; | |
1150 | ||
1151 | columns += m_columnsFirst; | |
1152 | if ( columns < 0 ) | |
1153 | columns = 0; | |
1154 | ||
1155 | return ScrollToRowColumn(rows, columns); | |
1156 | } | |
1157 | ||
1158 | bool wxHVScrolledWindow::ScrollRowPages(int pages) | |
1159 | { | |
1160 | bool didSomething = false; | |
1161 | ||
1162 | while ( pages ) | |
1163 | { | |
1164 | int line; | |
1165 | if ( pages > 0 ) | |
1166 | { | |
1167 | line = GetVisibleRowsEnd(); | |
1168 | if ( line ) | |
1169 | line--; | |
1170 | pages--; | |
1171 | } | |
1172 | else // pages < 0 | |
1173 | { | |
1174 | line = FindFirstFromBottom(GetVisibleRowsEnd()); | |
1175 | pages++; | |
1176 | } | |
1177 | ||
1178 | didSomething = ScrollToRow(line); | |
1179 | } | |
1180 | ||
1181 | return didSomething; | |
1182 | } | |
1183 | ||
1184 | bool wxHVScrolledWindow::ScrollColumnPages(int pages) | |
1185 | { | |
1186 | bool didSomething = false; | |
1187 | ||
1188 | while ( pages ) | |
1189 | { | |
1190 | int line; | |
1191 | if ( pages > 0 ) | |
1192 | { | |
1193 | line = GetVisibleColumnsEnd(); | |
1194 | if ( line ) | |
1195 | line--; | |
1196 | pages--; | |
1197 | } | |
1198 | else // pages < 0 | |
1199 | { | |
1200 | line = FindFirstFromRight(GetVisibleColumnsEnd()); | |
1201 | pages++; | |
1202 | } | |
1203 | ||
1204 | didSomething = ScrollToColumn(line); | |
1205 | } | |
1206 | ||
1207 | return didSomething; | |
1208 | } | |
1209 | ||
1210 | bool wxHVScrolledWindow::ScrollPages(int rowPages, int columnPages) | |
1211 | { | |
1212 | bool didSomething = false; | |
1213 | ||
1214 | while ( rowPages ) | |
1215 | { | |
1216 | int line; | |
1217 | if ( rowPages > 0 ) | |
1218 | { | |
1219 | line = GetVisibleRowsEnd(); | |
1220 | if ( line ) | |
1221 | line--; | |
1222 | rowPages--; | |
1223 | } | |
1224 | else // rowPages < 0 | |
1225 | { | |
1226 | line = FindFirstFromBottom(GetVisibleRowsBegin()); | |
1227 | rowPages++; | |
1228 | } | |
1229 | ||
1230 | didSomething = ScrollToRow(line); | |
1231 | } | |
1232 | ||
1233 | while ( columnPages ) | |
1234 | { | |
1235 | int line; | |
1236 | if ( columnPages > 0 ) | |
1237 | { | |
1238 | line = GetVisibleColumnsEnd(); | |
1239 | if ( line ) | |
1240 | line--; | |
1241 | columnPages--; | |
1242 | } | |
1243 | else // columnPages < 0 | |
1244 | { | |
1245 | line = FindFirstFromRight(GetVisibleColumnsBegin()); | |
1246 | columnPages++; | |
1247 | } | |
1248 | ||
1249 | didSomething |= ScrollToColumn(line); | |
1250 | } | |
1251 | ||
1252 | return didSomething; | |
1253 | } | |
1254 | ||
1255 | // ---------------------------------------------------------------------------- | |
1256 | // event handling | |
1257 | // ---------------------------------------------------------------------------- | |
1258 | ||
1259 | void wxHVScrolledWindow::OnSize(wxSizeEvent& event) | |
1260 | { | |
1261 | UpdateScrollbars(); | |
1262 | Layout(); | |
1263 | ||
1264 | event.Skip(); | |
1265 | } | |
1266 | ||
1267 | void wxHVScrolledWindow::OnScroll(wxScrollWinEvent& event) | |
1268 | { | |
1269 | if(event.GetOrientation() == wxHORIZONTAL) | |
1270 | { | |
1271 | size_t columnsFirstNew; | |
1272 | const wxEventType evtType = event.GetEventType(); | |
1273 | ||
1274 | if ( evtType == wxEVT_SCROLLWIN_TOP ) | |
1275 | { | |
1276 | columnsFirstNew = 0; | |
1277 | } | |
1278 | else if ( evtType == wxEVT_SCROLLWIN_BOTTOM ) | |
1279 | { | |
1280 | columnsFirstNew = m_columnsMax; | |
1281 | } | |
1282 | else if ( evtType == wxEVT_SCROLLWIN_LINEUP ) | |
1283 | { | |
1284 | columnsFirstNew = m_columnsFirst ? m_columnsFirst - 1 : 0; | |
1285 | } | |
1286 | else if ( evtType == wxEVT_SCROLLWIN_LINEDOWN ) | |
1287 | { | |
1288 | columnsFirstNew = m_columnsFirst + 1; | |
1289 | } | |
1290 | else if ( evtType == wxEVT_SCROLLWIN_PAGEUP ) | |
1291 | { | |
1292 | columnsFirstNew = FindFirstFromRight(m_columnsFirst); | |
1293 | } | |
1294 | else if ( evtType == wxEVT_SCROLLWIN_PAGEDOWN ) | |
1295 | { | |
1296 | columnsFirstNew = GetVisibleColumnsEnd(); | |
1297 | if ( columnsFirstNew ) | |
1298 | columnsFirstNew--; | |
1299 | } | |
1300 | else if ( evtType == wxEVT_SCROLLWIN_THUMBRELEASE ) | |
1301 | { | |
1302 | columnsFirstNew = event.GetPosition(); | |
1303 | } | |
1304 | else if ( evtType == wxEVT_SCROLLWIN_THUMBTRACK ) | |
1305 | { | |
1306 | columnsFirstNew = event.GetPosition(); | |
1307 | } | |
1308 | ||
1309 | else // unknown scroll event? | |
1310 | { | |
1311 | wxFAIL_MSG( _T("unknown scroll event type?") ); | |
1312 | return; | |
1313 | } | |
1314 | ||
1315 | ScrollToColumn(columnsFirstNew); | |
1316 | } | |
1317 | else if(event.GetOrientation() == wxVERTICAL) | |
1318 | { | |
1319 | size_t rowsFirstNew; | |
1320 | const wxEventType evtType = event.GetEventType(); | |
1321 | ||
1322 | if ( evtType == wxEVT_SCROLLWIN_TOP ) | |
1323 | { | |
1324 | rowsFirstNew = 0; | |
1325 | } | |
1326 | else if ( evtType == wxEVT_SCROLLWIN_BOTTOM ) | |
1327 | { | |
1328 | rowsFirstNew = m_rowsMax; | |
1329 | } | |
1330 | else if ( evtType == wxEVT_SCROLLWIN_LINEUP ) | |
1331 | { | |
1332 | rowsFirstNew = m_rowsFirst ? m_rowsFirst - 1 : 0; | |
1333 | } | |
1334 | else if ( evtType == wxEVT_SCROLLWIN_LINEDOWN ) | |
1335 | { | |
1336 | rowsFirstNew = m_rowsFirst + 1; | |
1337 | } | |
1338 | else if ( evtType == wxEVT_SCROLLWIN_PAGEUP ) | |
1339 | { | |
1340 | rowsFirstNew = FindFirstFromBottom(m_rowsFirst); | |
1341 | } | |
1342 | else if ( evtType == wxEVT_SCROLLWIN_PAGEDOWN ) | |
1343 | { | |
1344 | rowsFirstNew = GetVisibleRowsEnd(); | |
1345 | if ( rowsFirstNew ) | |
1346 | rowsFirstNew--; | |
1347 | } | |
1348 | else if ( evtType == wxEVT_SCROLLWIN_THUMBRELEASE ) | |
1349 | { | |
1350 | rowsFirstNew = event.GetPosition(); | |
1351 | } | |
1352 | else if ( evtType == wxEVT_SCROLLWIN_THUMBTRACK ) | |
1353 | { | |
1354 | rowsFirstNew = event.GetPosition(); | |
1355 | } | |
1356 | ||
1357 | else // unknown scroll event? | |
1358 | { | |
1359 | wxFAIL_MSG( _T("unknown scroll event type?") ); | |
1360 | return; | |
1361 | } | |
1362 | ||
1363 | ScrollToRow(rowsFirstNew); | |
1364 | } | |
555b2ce9 | 1365 | |
d77836e4 RR |
1366 | |
1367 | #ifdef __WXMAC__ | |
1368 | Update(); | |
1369 | #endif // __WXMAC__ | |
1370 | } | |
1371 | ||
1372 | #if wxUSE_MOUSEWHEEL | |
1373 | ||
1374 | void wxHVScrolledWindow::OnMouseWheel(wxMouseEvent& event) | |
1375 | { | |
1376 | m_sumWheelRotation += event.GetWheelRotation(); | |
1377 | int delta = event.GetWheelDelta(); | |
1378 | ||
1379 | // how much to scroll this time | |
1380 | int units_to_scroll = -(m_sumWheelRotation/delta); | |
1381 | if ( !units_to_scroll ) | |
1382 | return; | |
1383 | ||
1384 | m_sumWheelRotation += units_to_scroll*delta; | |
1385 | ||
1386 | if ( !event.IsPageScroll() ) | |
1387 | ScrollRows( units_to_scroll*event.GetLinesPerAction() ); | |
1388 | else | |
1389 | // scroll pages instead of lines | |
1390 | ScrollRowPages( units_to_scroll ); | |
1391 | } | |
1392 | ||
1393 | #endif |