]>
Commit | Line | Data |
---|---|---|
c801d85f | 1 | ///////////////////////////////////////////////////////////////////////////// |
d80cd92a | 2 | // Name: generic/scrolwin.cpp |
fa3541bd | 3 | // Purpose: wxGenericScrolledWindow implementation |
c801d85f KB |
4 | // Author: Julian Smart |
5 | // Modified by: | |
6 | // Created: 01/02/97 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Julian Smart and Markus Holzem | |
a58a12e9 | 9 | // Licence: wxWindows license |
c801d85f KB |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
d80cd92a VZ |
12 | // ============================================================================ |
13 | // declarations | |
14 | // ============================================================================ | |
15 | ||
16 | // ---------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ---------------------------------------------------------------------------- | |
19 | ||
c801d85f | 20 | #ifdef __GNUG__ |
d80cd92a | 21 | #pragma implementation "scrolwin.h" |
c801d85f KB |
22 | #endif |
23 | ||
bcd055ae JJ |
24 | #ifdef __VMS |
25 | #define XtDisplay XTDISPLAY | |
26 | #endif | |
27 | ||
c801d85f KB |
28 | // For compilers that support precompilation, includes "wx.h". |
29 | #include "wx/wxprec.h" | |
30 | ||
c801d85f | 31 | #ifdef __BORLANDC__ |
d80cd92a | 32 | #pragma hdrstop |
c801d85f KB |
33 | #endif |
34 | ||
d80cd92a VZ |
35 | #include "wx/utils.h" |
36 | #include "wx/dcclient.h" | |
37 | ||
c801d85f | 38 | #include "wx/generic/scrolwin.h" |
053f9cc1 | 39 | #include "wx/panel.h" |
c801d85f | 40 | |
48d1144b | 41 | #ifdef __WXMSW__ |
d80cd92a | 42 | #include "windows.h" |
48d1144b JS |
43 | #endif |
44 | ||
a91b47e8 JS |
45 | #ifdef __WXMOTIF__ |
46 | // For wxRETAINED implementation | |
338dd992 JJ |
47 | #ifdef __VMS__ //VMS's Xm.h is not (yet) compatible with C++ |
48 | //This code switches off the compiler warnings | |
49 | # pragma message disable nosimpint | |
50 | #endif | |
a91b47e8 | 51 | #include <Xm/Xm.h> |
338dd992 JJ |
52 | #ifdef __VMS__ |
53 | # pragma message enable nosimpint | |
54 | #endif | |
a91b47e8 JS |
55 | #endif |
56 | ||
fa3541bd | 57 | #ifndef __WXGTK__ |
35b6b7d5 | 58 | #include "wx/scrolwin.h" |
fa3541bd JS |
59 | IMPLEMENT_CLASS(wxScrolledWindow, wxGenericScrolledWindow) |
60 | #endif | |
61 | ||
d80cd92a VZ |
62 | // ---------------------------------------------------------------------------- |
63 | // event tables | |
64 | // ---------------------------------------------------------------------------- | |
65 | ||
fa3541bd JS |
66 | BEGIN_EVENT_TABLE(wxGenericScrolledWindow, wxPanel) |
67 | EVT_SCROLLWIN(wxGenericScrolledWindow::OnScroll) | |
68 | EVT_SIZE(wxGenericScrolledWindow::OnSize) | |
69 | EVT_PAINT(wxGenericScrolledWindow::OnPaint) | |
70 | EVT_CHAR(wxGenericScrolledWindow::OnChar) | |
d80cd92a VZ |
71 | END_EVENT_TABLE() |
72 | ||
fa3541bd | 73 | IMPLEMENT_DYNAMIC_CLASS(wxGenericScrolledWindow, wxPanel) |
d80cd92a VZ |
74 | |
75 | // ============================================================================ | |
76 | // implementation | |
77 | // ============================================================================ | |
78 | ||
79 | // ---------------------------------------------------------------------------- | |
fa3541bd | 80 | // wxGenericScrolledWindow creation |
d80cd92a VZ |
81 | // ---------------------------------------------------------------------------- |
82 | ||
fa3541bd | 83 | wxGenericScrolledWindow::wxGenericScrolledWindow() |
c801d85f | 84 | { |
139adb6a RR |
85 | m_xScrollPixelsPerLine = 0; |
86 | m_yScrollPixelsPerLine = 0; | |
87 | m_xScrollingEnabled = TRUE; | |
88 | m_yScrollingEnabled = TRUE; | |
89 | m_xScrollPosition = 0; | |
90 | m_yScrollPosition = 0; | |
91 | m_xScrollLines = 0; | |
92 | m_yScrollLines = 0; | |
93 | m_xScrollLinesPerPage = 0; | |
94 | m_yScrollLinesPerPage = 0; | |
95 | m_scaleX = 1.0; | |
96 | m_scaleY = 1.0; | |
8b089c5e | 97 | m_targetWindow = (wxWindow*) NULL; |
c801d85f KB |
98 | } |
99 | ||
fa3541bd | 100 | bool wxGenericScrolledWindow::Create(wxWindow *parent, |
d80cd92a VZ |
101 | wxWindowID id, |
102 | const wxPoint& pos, | |
103 | const wxSize& size, | |
104 | long style, | |
105 | const wxString& name) | |
c801d85f | 106 | { |
139adb6a RR |
107 | m_xScrollPixelsPerLine = 0; |
108 | m_yScrollPixelsPerLine = 0; | |
109 | m_xScrollingEnabled = TRUE; | |
110 | m_yScrollingEnabled = TRUE; | |
111 | m_xScrollPosition = 0; | |
112 | m_yScrollPosition = 0; | |
113 | m_xScrollLines = 0; | |
114 | m_yScrollLines = 0; | |
115 | m_xScrollLinesPerPage = 0; | |
116 | m_yScrollLinesPerPage = 0; | |
117 | m_scaleX = 1.0; | |
118 | m_scaleY = 1.0; | |
a58a12e9 | 119 | |
ecab4dba | 120 | m_targetWindow = this; |
139adb6a | 121 | |
d7da9756 VZ |
122 | bool ok = wxPanel::Create(parent, id, pos, size, style, name); |
123 | ||
124 | #ifdef __WXMSW__ | |
125 | // we need to process arrows ourselves for scrolling | |
126 | m_lDlgCode |= DLGC_WANTARROWS; | |
127 | #endif // __WXMSW__ | |
128 | ||
129 | return ok; | |
c801d85f KB |
130 | } |
131 | ||
fa3541bd | 132 | wxGenericScrolledWindow::~wxGenericScrolledWindow() |
d80cd92a VZ |
133 | { |
134 | } | |
135 | ||
136 | // ---------------------------------------------------------------------------- | |
137 | // setting scrolling parameters | |
138 | // ---------------------------------------------------------------------------- | |
139 | ||
c801d85f KB |
140 | /* |
141 | * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) | |
142 | * noUnitsX/noUnitsY: : no. units per scrollbar | |
143 | */ | |
fa3541bd | 144 | void wxGenericScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, |
d80cd92a VZ |
145 | int noUnitsX, int noUnitsY, |
146 | int xPos, int yPos, bool noRefresh ) | |
c801d85f | 147 | { |
b0486e0d SN |
148 | int xpos, ypos; |
149 | ||
150 | CalcUnscrolledPosition(xPos, yPos, &xpos, &ypos); | |
139adb6a RR |
151 | bool do_refresh = |
152 | ( | |
c801d85f | 153 | (noUnitsX != 0 && m_xScrollLines == 0) || |
b0486e0d SN |
154 | (noUnitsX < m_xScrollLines && xpos > pixelsPerUnitX*noUnitsX) || |
155 | ||
c801d85f | 156 | (noUnitsY != 0 && m_yScrollLines == 0) || |
b0486e0d | 157 | (noUnitsY < m_yScrollLines && ypos > pixelsPerUnitY*noUnitsY) || |
c801d85f | 158 | (xPos != m_xScrollPosition) || |
b0486e0d SN |
159 | (yPos != m_yScrollPosition) |
160 | // (pixelsPerUnitX != m_xScrollPixelsPerLine) || | |
161 | // (pixelsPerUnitY != m_yScrollPixelsPerLine) | |
139adb6a | 162 | ); |
a58a12e9 | 163 | |
139adb6a RR |
164 | m_xScrollPixelsPerLine = pixelsPerUnitX; |
165 | m_yScrollPixelsPerLine = pixelsPerUnitY; | |
166 | m_xScrollPosition = xPos; | |
167 | m_yScrollPosition = yPos; | |
168 | m_xScrollLines = noUnitsX; | |
169 | m_yScrollLines = noUnitsY; | |
a91b47e8 JS |
170 | |
171 | #ifdef __WXMOTIF__ | |
172 | // Sorry, some Motif-specific code to implement a backing pixmap | |
173 | // for the wxRETAINED style. Implementing a backing store can't | |
174 | // be entirely generic because it relies on the wxWindowDC implementation | |
175 | // to duplicate X drawing calls for the backing pixmap. | |
176 | ||
177 | if ((m_windowStyle & wxRETAINED) == wxRETAINED) | |
178 | { | |
179 | Display* dpy = XtDisplay((Widget) GetMainWidget()); | |
180 | ||
181 | int totalPixelWidth = m_xScrollLines * m_xScrollPixelsPerLine; | |
182 | int totalPixelHeight = m_yScrollLines * m_yScrollPixelsPerLine; | |
183 | if (m_backingPixmap && | |
184 | !((m_pixmapWidth == totalPixelWidth) && | |
185 | (m_pixmapHeight == totalPixelHeight))) | |
186 | { | |
187 | XFreePixmap (dpy, (Pixmap) m_backingPixmap); | |
188 | m_backingPixmap = (WXPixmap) 0; | |
189 | } | |
190 | ||
191 | if (!m_backingPixmap && | |
192 | (noUnitsX != 0) && (noUnitsY != 0)) | |
193 | { | |
194 | int depth = wxDisplayDepth(); | |
195 | m_pixmapWidth = totalPixelWidth; | |
196 | m_pixmapHeight = totalPixelHeight; | |
197 | m_backingPixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)), | |
198 | m_pixmapWidth, m_pixmapHeight, depth); | |
d80cd92a | 199 | } |
a91b47e8 JS |
200 | |
201 | } | |
d80cd92a | 202 | #endif // Motif |
a58a12e9 | 203 | |
139adb6a | 204 | AdjustScrollbars(); |
a58a12e9 VZ |
205 | |
206 | if (do_refresh && !noRefresh) | |
207 | m_targetWindow->Refresh(); | |
208 | ||
2049ba38 | 209 | #ifdef __WXMSW__ |
d9c09c79 GRG |
210 | // GRG: if this turns out to be really necessary, we could |
211 | // at least move it to the above if { ... } so that it is | |
212 | // only done if noRefresh = FALSE (the default). OTOH, if | |
213 | // this doesn't break anything, which seems to be the | |
214 | // case, we could just leave it out. | |
215 | ||
60fe7303 JS |
216 | // Necessary? |
217 | // UpdateWindow ((HWND) m_targetWindow->GetHWND()); | |
7c74e7fe SC |
218 | #endif |
219 | #ifdef __WXMAC__ | |
d80cd92a | 220 | m_targetWindow->MacUpdateImmediately() ; |
c801d85f KB |
221 | #endif |
222 | } | |
223 | ||
d80cd92a VZ |
224 | // ---------------------------------------------------------------------------- |
225 | // target window handling | |
226 | // ---------------------------------------------------------------------------- | |
ecab4dba | 227 | |
fa3541bd | 228 | void wxGenericScrolledWindow::SetTargetWindow( wxWindow *target ) |
ecab4dba RR |
229 | { |
230 | wxASSERT_MSG( target, wxT("target window must not be NULL") ); | |
231 | m_targetWindow = target; | |
232 | } | |
233 | ||
fa3541bd | 234 | wxWindow *wxGenericScrolledWindow::GetTargetWindow() |
ecab4dba RR |
235 | { |
236 | return m_targetWindow; | |
237 | } | |
238 | ||
d80cd92a VZ |
239 | // ---------------------------------------------------------------------------- |
240 | // scrolling implementation itself | |
241 | // ---------------------------------------------------------------------------- | |
242 | ||
fa3541bd | 243 | void wxGenericScrolledWindow::OnScroll(wxScrollWinEvent& event) |
c801d85f | 244 | { |
139adb6a | 245 | int orient = event.GetOrientation(); |
c801d85f | 246 | |
139adb6a RR |
247 | int nScrollInc = CalcScrollInc(event); |
248 | if (nScrollInc == 0) return; | |
c801d85f | 249 | |
139adb6a RR |
250 | if (orient == wxHORIZONTAL) |
251 | { | |
252 | int newPos = m_xScrollPosition + nScrollInc; | |
253 | SetScrollPos(wxHORIZONTAL, newPos, TRUE ); | |
254 | } | |
255 | else | |
256 | { | |
257 | int newPos = m_yScrollPosition + nScrollInc; | |
258 | SetScrollPos(wxVERTICAL, newPos, TRUE ); | |
259 | } | |
c801d85f | 260 | |
139adb6a RR |
261 | if (orient == wxHORIZONTAL) |
262 | { | |
263 | m_xScrollPosition += nScrollInc; | |
264 | } | |
c801d85f | 265 | else |
139adb6a RR |
266 | { |
267 | m_yScrollPosition += nScrollInc; | |
268 | } | |
a58a12e9 | 269 | |
139adb6a RR |
270 | if (orient == wxHORIZONTAL) |
271 | { | |
272 | if (m_xScrollingEnabled) | |
ecab4dba | 273 | m_targetWindow->ScrollWindow(-m_xScrollPixelsPerLine * nScrollInc, 0, (const wxRect *) NULL); |
139adb6a | 274 | else |
ecab4dba | 275 | m_targetWindow->Refresh(); |
139adb6a | 276 | } |
c801d85f | 277 | else |
139adb6a RR |
278 | { |
279 | if (m_yScrollingEnabled) | |
ecab4dba | 280 | m_targetWindow->ScrollWindow(0, -m_yScrollPixelsPerLine * nScrollInc, (const wxRect *) NULL); |
139adb6a | 281 | else |
ecab4dba | 282 | m_targetWindow->Refresh(); |
3d2b9c20 | 283 | } |
7c74e7fe | 284 | #ifdef __WXMAC__ |
d80cd92a | 285 | m_targetWindow->MacUpdateImmediately() ; |
7c74e7fe | 286 | #endif |
c801d85f KB |
287 | } |
288 | ||
fa3541bd | 289 | int wxGenericScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) |
c801d85f | 290 | { |
ecab4dba RR |
291 | int pos = event.GetPosition(); |
292 | int orient = event.GetOrientation(); | |
c801d85f | 293 | |
ecab4dba | 294 | int nScrollInc = 0; |
1a8caf94 | 295 | if (event.GetEventType() == wxEVT_SCROLLWIN_TOP) |
c801d85f | 296 | { |
ecab4dba RR |
297 | if (orient == wxHORIZONTAL) |
298 | nScrollInc = - m_xScrollPosition; | |
299 | else | |
300 | nScrollInc = - m_yScrollPosition; | |
1a8caf94 RR |
301 | } else |
302 | if (event.GetEventType() == wxEVT_SCROLLWIN_BOTTOM) | |
303 | { | |
ecab4dba RR |
304 | if (orient == wxHORIZONTAL) |
305 | nScrollInc = m_xScrollLines - m_xScrollPosition; | |
306 | else | |
307 | nScrollInc = m_yScrollLines - m_yScrollPosition; | |
1a8caf94 RR |
308 | } else |
309 | if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP) | |
310 | { | |
ecab4dba | 311 | nScrollInc = -1; |
1a8caf94 RR |
312 | } else |
313 | if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN) | |
314 | { | |
ecab4dba | 315 | nScrollInc = 1; |
1a8caf94 RR |
316 | } else |
317 | if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEUP) | |
318 | { | |
ecab4dba RR |
319 | if (orient == wxHORIZONTAL) |
320 | nScrollInc = -GetScrollPageSize(wxHORIZONTAL); | |
321 | else | |
322 | nScrollInc = -GetScrollPageSize(wxVERTICAL); | |
1a8caf94 RR |
323 | } else |
324 | if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN) | |
325 | { | |
ecab4dba RR |
326 | if (orient == wxHORIZONTAL) |
327 | nScrollInc = GetScrollPageSize(wxHORIZONTAL); | |
328 | else | |
329 | nScrollInc = GetScrollPageSize(wxVERTICAL); | |
1a8caf94 RR |
330 | } else |
331 | if ((event.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK) || | |
332 | (event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE)) | |
333 | { | |
ecab4dba RR |
334 | if (orient == wxHORIZONTAL) |
335 | nScrollInc = pos - m_xScrollPosition; | |
336 | else | |
337 | nScrollInc = pos - m_yScrollPosition; | |
c801d85f | 338 | } |
88150e60 | 339 | |
ecab4dba RR |
340 | if (orient == wxHORIZONTAL) |
341 | { | |
a58a12e9 | 342 | if (m_xScrollPixelsPerLine > 0) |
ecab4dba RR |
343 | { |
344 | int w, h; | |
345 | m_targetWindow->GetClientSize(&w, &h); | |
346 | ||
347 | int nMaxWidth = m_xScrollLines*m_xScrollPixelsPerLine; | |
348 | int noPositions = (int) ( ((nMaxWidth - w)/(double)m_xScrollPixelsPerLine) + 0.5 ); | |
349 | if (noPositions < 0) | |
d80cd92a | 350 | noPositions = 0; |
ecab4dba RR |
351 | |
352 | if ( (m_xScrollPosition + nScrollInc) < 0 ) | |
d80cd92a | 353 | nScrollInc = -m_xScrollPosition; // As -ve as we can go |
ecab4dba | 354 | else if ( (m_xScrollPosition + nScrollInc) > noPositions ) |
d80cd92a | 355 | nScrollInc = noPositions - m_xScrollPosition; // As +ve as we can go |
ecab4dba RR |
356 | } |
357 | else | |
358 | m_targetWindow->Refresh(); | |
9d9355c6 VZ |
359 | } |
360 | else | |
ecab4dba | 361 | { |
a58a12e9 | 362 | if (m_yScrollPixelsPerLine > 0) |
d80cd92a | 363 | { |
ecab4dba RR |
364 | int w, h; |
365 | m_targetWindow->GetClientSize(&w, &h); | |
a58a12e9 | 366 | |
ecab4dba RR |
367 | int nMaxHeight = m_yScrollLines*m_yScrollPixelsPerLine; |
368 | int noPositions = (int) ( ((nMaxHeight - h)/(double)m_yScrollPixelsPerLine) + 0.5 ); | |
369 | if (noPositions < 0) | |
d80cd92a | 370 | noPositions = 0; |
a58a12e9 | 371 | |
ecab4dba | 372 | if ( (m_yScrollPosition + nScrollInc) < 0 ) |
d80cd92a | 373 | nScrollInc = -m_yScrollPosition; // As -ve as we can go |
ecab4dba | 374 | else if ( (m_yScrollPosition + nScrollInc) > noPositions ) |
d80cd92a | 375 | nScrollInc = noPositions - m_yScrollPosition; // As +ve as we can go |
ecab4dba RR |
376 | } |
377 | else | |
378 | m_targetWindow->Refresh(); | |
9d9355c6 | 379 | } |
9d9355c6 | 380 | |
ecab4dba | 381 | return nScrollInc; |
c801d85f KB |
382 | } |
383 | ||
384 | // Adjust the scrollbars - new version. | |
fa3541bd | 385 | void wxGenericScrolledWindow::AdjustScrollbars() |
c801d85f | 386 | { |
139adb6a | 387 | int w, h; |
ecab4dba | 388 | m_targetWindow->GetClientSize(&w, &h); |
a58a12e9 | 389 | |
27d029c7 RR |
390 | int oldXScroll = m_xScrollPosition; |
391 | int oldYScroll = m_yScrollPosition; | |
c801d85f | 392 | |
139adb6a RR |
393 | if (m_xScrollLines > 0) |
394 | { | |
3d2b9c20 RR |
395 | // Calculate page size i.e. number of scroll units you get on the |
396 | // current client window | |
ecab4dba | 397 | int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 ); |
139adb6a | 398 | if (noPagePositions < 1) noPagePositions = 1; |
c801d85f | 399 | |
139adb6a | 400 | // Correct position if greater than extent of canvas minus |
3d2b9c20 RR |
401 | // the visible portion of it or if below zero |
402 | m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition); | |
139adb6a | 403 | m_xScrollPosition = wxMax( 0, m_xScrollPosition ); |
c801d85f | 404 | |
139adb6a | 405 | SetScrollbar(wxHORIZONTAL, m_xScrollPosition, noPagePositions, m_xScrollLines); |
88150e60 JS |
406 | // The amount by which we scroll when paging |
407 | SetScrollPageSize(wxHORIZONTAL, noPagePositions); | |
139adb6a RR |
408 | } |
409 | else | |
a58a12e9 | 410 | { |
139adb6a | 411 | m_xScrollPosition = 0; |
a58a12e9 | 412 | SetScrollbar (wxHORIZONTAL, 0, 0, 0, FALSE); |
139adb6a | 413 | } |
a58a12e9 | 414 | |
139adb6a RR |
415 | if (m_yScrollLines > 0) |
416 | { | |
3d2b9c20 RR |
417 | // Calculate page size i.e. number of scroll units you get on the |
418 | // current client window | |
ecab4dba | 419 | int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 ); |
139adb6a | 420 | if (noPagePositions < 1) noPagePositions = 1; |
c801d85f | 421 | |
139adb6a | 422 | // Correct position if greater than extent of canvas minus |
3d2b9c20 | 423 | // the visible portion of it or if below zero |
139adb6a RR |
424 | m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition ); |
425 | m_yScrollPosition = wxMax( 0, m_yScrollPosition ); | |
426 | ||
427 | SetScrollbar(wxVERTICAL, m_yScrollPosition, noPagePositions, m_yScrollLines); | |
88150e60 JS |
428 | // The amount by which we scroll when paging |
429 | SetScrollPageSize(wxVERTICAL, noPagePositions); | |
139adb6a RR |
430 | } |
431 | else | |
432 | { | |
433 | m_yScrollPosition = 0; | |
a58a12e9 | 434 | SetScrollbar (wxVERTICAL, 0, 0, 0, FALSE); |
139adb6a | 435 | } |
a58a12e9 | 436 | |
27d029c7 RR |
437 | if (oldXScroll != m_xScrollPosition) |
438 | { | |
439 | if (m_xScrollingEnabled) | |
ecab4dba | 440 | m_targetWindow->ScrollWindow( m_xScrollPixelsPerLine * (oldXScroll-m_xScrollPosition), 0, (const wxRect *) NULL ); |
27d029c7 | 441 | else |
ecab4dba | 442 | m_targetWindow->Refresh(); |
27d029c7 | 443 | } |
a58a12e9 | 444 | |
27d029c7 RR |
445 | if (oldYScroll != m_yScrollPosition) |
446 | { | |
447 | if (m_yScrollingEnabled) | |
ecab4dba | 448 | m_targetWindow->ScrollWindow( 0, m_yScrollPixelsPerLine * (oldYScroll-m_yScrollPosition), (const wxRect *) NULL ); |
27d029c7 | 449 | else |
ecab4dba | 450 | m_targetWindow->Refresh(); |
27d029c7 | 451 | } |
c801d85f KB |
452 | } |
453 | ||
fa3541bd | 454 | // Override this function if you don't want to have wxGenericScrolledWindow |
c801d85f | 455 | // automatically change the origin according to the scroll position. |
fa3541bd | 456 | void wxGenericScrolledWindow::PrepareDC(wxDC& dc) |
c801d85f | 457 | { |
a58a12e9 | 458 | dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine, |
139adb6a RR |
459 | -m_yScrollPosition * m_yScrollPixelsPerLine ); |
460 | dc.SetUserScale( m_scaleX, m_scaleY ); | |
c801d85f KB |
461 | } |
462 | ||
463 | #if WXWIN_COMPATIBILITY | |
fa3541bd | 464 | void wxGenericScrolledWindow::GetScrollUnitsPerPage (int *x_page, int *y_page) const |
c801d85f KB |
465 | { |
466 | *x_page = GetScrollPageSize(wxHORIZONTAL); | |
467 | *y_page = GetScrollPageSize(wxVERTICAL); | |
468 | } | |
a0bc2c1d | 469 | |
fa3541bd | 470 | void wxGenericScrolledWindow::CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const |
a0bc2c1d VZ |
471 | { |
472 | if ( xx ) | |
473 | *xx = (float)(x + m_xScrollPosition * m_xScrollPixelsPerLine); | |
474 | if ( yy ) | |
475 | *yy = (float)(y + m_yScrollPosition * m_yScrollPixelsPerLine); | |
476 | } | |
477 | #endif // WXWIN_COMPATIBILITY | |
c801d85f | 478 | |
fa3541bd | 479 | void wxGenericScrolledWindow::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const |
c801d85f | 480 | { |
a0bc2c1d VZ |
481 | if ( x_unit ) |
482 | *x_unit = m_xScrollPixelsPerLine; | |
483 | if ( y_unit ) | |
484 | *y_unit = m_yScrollPixelsPerLine; | |
c801d85f KB |
485 | } |
486 | ||
fa3541bd | 487 | int wxGenericScrolledWindow::GetScrollPageSize(int orient) const |
c801d85f KB |
488 | { |
489 | if ( orient == wxHORIZONTAL ) | |
490 | return m_xScrollLinesPerPage; | |
491 | else | |
492 | return m_yScrollLinesPerPage; | |
493 | } | |
494 | ||
fa3541bd | 495 | void wxGenericScrolledWindow::SetScrollPageSize(int orient, int pageSize) |
c801d85f KB |
496 | { |
497 | if ( orient == wxHORIZONTAL ) | |
498 | m_xScrollLinesPerPage = pageSize; | |
499 | else | |
500 | m_yScrollLinesPerPage = pageSize; | |
501 | } | |
502 | ||
503 | /* | |
504 | * Scroll to given position (scroll position, not pixel position) | |
505 | */ | |
fa3541bd | 506 | void wxGenericScrolledWindow::Scroll( int x_pos, int y_pos ) |
c801d85f | 507 | { |
8b089c5e JS |
508 | if (!m_targetWindow) |
509 | return; | |
510 | ||
a58a12e9 | 511 | if (((x_pos == -1) || (x_pos == m_xScrollPosition)) && |
139adb6a | 512 | ((y_pos == -1) || (y_pos == m_yScrollPosition))) return; |
a58a12e9 | 513 | |
139adb6a | 514 | int w, h; |
ecab4dba | 515 | m_targetWindow->GetClientSize(&w, &h); |
c801d85f | 516 | |
8775b357 | 517 | if ((x_pos != -1) && (m_xScrollPixelsPerLine)) |
c801d85f | 518 | { |
ed673c6a | 519 | int old_x = m_xScrollPosition; |
139adb6a | 520 | m_xScrollPosition = x_pos; |
a58a12e9 | 521 | |
3d2b9c20 RR |
522 | // Calculate page size i.e. number of scroll units you get on the |
523 | // current client window | |
ecab4dba | 524 | int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 ); |
139adb6a RR |
525 | if (noPagePositions < 1) noPagePositions = 1; |
526 | ||
527 | // Correct position if greater than extent of canvas minus | |
3d2b9c20 | 528 | // the visible portion of it or if below zero |
139adb6a RR |
529 | m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition ); |
530 | m_xScrollPosition = wxMax( 0, m_xScrollPosition ); | |
a58a12e9 | 531 | |
f6bcfd97 BP |
532 | if (old_x != m_xScrollPosition) { |
533 | m_targetWindow->SetScrollPos( wxHORIZONTAL, m_xScrollPosition, TRUE ); | |
534 | m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 ); | |
535 | } | |
c801d85f | 536 | } |
8775b357 | 537 | if ((y_pos != -1) && (m_yScrollPixelsPerLine)) |
c801d85f | 538 | { |
ed673c6a | 539 | int old_y = m_yScrollPosition; |
139adb6a | 540 | m_yScrollPosition = y_pos; |
a58a12e9 | 541 | |
3d2b9c20 RR |
542 | // Calculate page size i.e. number of scroll units you get on the |
543 | // current client window | |
ecab4dba | 544 | int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 ); |
139adb6a RR |
545 | if (noPagePositions < 1) noPagePositions = 1; |
546 | ||
547 | // Correct position if greater than extent of canvas minus | |
3d2b9c20 | 548 | // the visible portion of it or if below zero |
139adb6a RR |
549 | m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition ); |
550 | m_yScrollPosition = wxMax( 0, m_yScrollPosition ); | |
3d2b9c20 | 551 | |
f6bcfd97 BP |
552 | if (old_y != m_yScrollPosition) { |
553 | m_targetWindow->SetScrollPos( wxVERTICAL, m_yScrollPosition, TRUE ); | |
554 | m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine ); | |
555 | } | |
c801d85f | 556 | } |
a58a12e9 | 557 | |
7c74e7fe | 558 | #ifdef __WXMAC__ |
3d2b9c20 | 559 | m_targetWindow->MacUpdateImmediately(); |
7c74e7fe | 560 | #endif |
c801d85f KB |
561 | } |
562 | ||
fa3541bd | 563 | void wxGenericScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll) |
c801d85f | 564 | { |
139adb6a RR |
565 | m_xScrollingEnabled = x_scroll; |
566 | m_yScrollingEnabled = y_scroll; | |
c801d85f KB |
567 | } |
568 | ||
fa3541bd | 569 | void wxGenericScrolledWindow::GetVirtualSize (int *x, int *y) const |
c801d85f | 570 | { |
a0bc2c1d VZ |
571 | if ( x ) |
572 | *x = m_xScrollPixelsPerLine * m_xScrollLines; | |
573 | if ( y ) | |
574 | *y = m_yScrollPixelsPerLine * m_yScrollLines; | |
c801d85f KB |
575 | } |
576 | ||
577 | // Where the current view starts from | |
fa3541bd | 578 | void wxGenericScrolledWindow::GetViewStart (int *x, int *y) const |
c801d85f | 579 | { |
a0bc2c1d VZ |
580 | if ( x ) |
581 | *x = m_xScrollPosition; | |
582 | if ( y ) | |
583 | *y = m_yScrollPosition; | |
c801d85f KB |
584 | } |
585 | ||
fa3541bd | 586 | void wxGenericScrolledWindow::CalcScrolledPosition(int x, int y, int *xx, int *yy) const |
c801d85f | 587 | { |
a0bc2c1d VZ |
588 | if ( xx ) |
589 | *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine; | |
590 | if ( yy ) | |
591 | *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine; | |
c801d85f KB |
592 | } |
593 | ||
fa3541bd | 594 | void wxGenericScrolledWindow::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const |
c801d85f | 595 | { |
a0bc2c1d VZ |
596 | if ( xx ) |
597 | *xx = x + m_xScrollPosition * m_xScrollPixelsPerLine; | |
598 | if ( yy ) | |
599 | *yy = y + m_yScrollPosition * m_yScrollPixelsPerLine; | |
c801d85f | 600 | } |
d80cd92a VZ |
601 | |
602 | // ---------------------------------------------------------------------------- | |
603 | // event handlers | |
604 | // ---------------------------------------------------------------------------- | |
605 | ||
606 | // Default OnSize resets scrollbars, if any | |
fa3541bd | 607 | void wxGenericScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event)) |
d80cd92a VZ |
608 | { |
609 | #if wxUSE_CONSTRAINTS | |
610 | if (GetAutoLayout()) | |
611 | Layout(); | |
612 | #endif | |
613 | ||
614 | AdjustScrollbars(); | |
615 | } | |
616 | ||
617 | // This calls OnDraw, having adjusted the origin according to the current | |
618 | // scroll position | |
fa3541bd | 619 | void wxGenericScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) |
d80cd92a VZ |
620 | { |
621 | wxPaintDC dc(this); | |
622 | PrepareDC(dc); | |
623 | ||
624 | OnDraw(dc); | |
625 | } | |
626 | ||
438e3558 VZ |
627 | // kbd handling: notice that we use OnChar() and not OnKeyDown() for |
628 | // compatibility here - if we used OnKeyDown(), the programs which process | |
629 | // arrows themselves in their OnChar() would never get the message and like | |
630 | // this they always have the priority | |
fa3541bd | 631 | void wxGenericScrolledWindow::OnChar(wxKeyEvent& event) |
d80cd92a VZ |
632 | { |
633 | int stx, sty, // view origin | |
634 | szx, szy, // view size (total) | |
635 | clix, cliy; // view size (on screen) | |
636 | ||
637 | ViewStart(&stx, &sty); | |
638 | GetClientSize(&clix, &cliy); | |
d80cd92a | 639 | GetVirtualSize(&szx, &szy); |
56dade3c RL |
640 | |
641 | if( m_xScrollPixelsPerLine ) | |
642 | { | |
643 | clix /= m_xScrollPixelsPerLine; | |
d7da9756 | 644 | szx /= m_xScrollPixelsPerLine; |
56dade3c RL |
645 | } |
646 | else | |
647 | { | |
648 | clix = 0; | |
d7da9756 | 649 | szx = -1; |
56dade3c RL |
650 | } |
651 | if( m_yScrollPixelsPerLine ) | |
652 | { | |
653 | cliy /= m_yScrollPixelsPerLine; | |
654 | szy /= m_yScrollPixelsPerLine; | |
655 | } | |
656 | else | |
657 | { | |
658 | cliy = 0; | |
d7da9756 | 659 | szy = -1; |
56dade3c | 660 | } |
d80cd92a | 661 | |
ecb01792 | 662 | int dsty; |
d80cd92a VZ |
663 | switch ( event.KeyCode() ) |
664 | { | |
665 | case WXK_PAGEUP: | |
666 | case WXK_PRIOR: | |
ecb01792 RL |
667 | dsty = sty - (5 * cliy / 6); |
668 | Scroll(-1, (dsty == -1) ? 0 : dsty); | |
d80cd92a VZ |
669 | break; |
670 | ||
671 | case WXK_PAGEDOWN: | |
672 | case WXK_NEXT: | |
673 | Scroll(-1, sty + (5 * cliy / 6)); | |
674 | break; | |
675 | ||
d80cd92a VZ |
676 | case WXK_HOME: |
677 | Scroll(0, event.ControlDown() ? 0 : -1); | |
678 | break; | |
679 | ||
680 | case WXK_END: | |
4acd108c | 681 | Scroll(szx - clix, event.ControlDown() ? szy - cliy : -1); |
d80cd92a VZ |
682 | break; |
683 | ||
684 | case WXK_UP: | |
685 | Scroll(-1, sty - 1); | |
686 | break; | |
687 | ||
688 | case WXK_DOWN: | |
689 | Scroll(-1, sty + 1); | |
690 | break; | |
691 | ||
692 | case WXK_LEFT: | |
693 | Scroll(stx - 1, -1); | |
694 | break; | |
695 | ||
696 | case WXK_RIGHT: | |
697 | Scroll(stx + 1, -1); | |
698 | break; | |
699 | ||
700 | default: | |
701 | // not for us | |
702 | event.Skip(); | |
703 | } | |
704 | } |