]> git.saurik.com Git - wxWidgets.git/blame - src/generic/scrolwin.cpp
Fixed wxHTML code in a Watcom Win32 DLL
[wxWidgets.git] / src / generic / scrolwin.cpp
CommitLineData
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
59IMPLEMENT_CLASS(wxScrolledWindow, wxGenericScrolledWindow)
60#endif
61
d80cd92a
VZ
62// ----------------------------------------------------------------------------
63// event tables
64// ----------------------------------------------------------------------------
65
fa3541bd
JS
66BEGIN_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
71END_EVENT_TABLE()
72
fa3541bd 73IMPLEMENT_DYNAMIC_CLASS(wxGenericScrolledWindow, wxPanel)
d80cd92a
VZ
74
75// ============================================================================
76// implementation
77// ============================================================================
78
79// ----------------------------------------------------------------------------
fa3541bd 80// wxGenericScrolledWindow creation
d80cd92a
VZ
81// ----------------------------------------------------------------------------
82
fa3541bd 83wxGenericScrolledWindow::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 100bool 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 132wxGenericScrolledWindow::~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 144void 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 228void 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 234wxWindow *wxGenericScrolledWindow::GetTargetWindow()
ecab4dba
RR
235{
236 return m_targetWindow;
237}
238
d80cd92a
VZ
239// ----------------------------------------------------------------------------
240// scrolling implementation itself
241// ----------------------------------------------------------------------------
242
fa3541bd 243void 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 289int 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 385void 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 456void 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 464void 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 470void 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 479void 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 487int 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 495void 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 506void 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 563void 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 569void 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 578void 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 586void 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 594void 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 607void 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 619void 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 631void 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}