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