]> git.saurik.com Git - wxWidgets.git/blame - src/generic/scrlwing.cpp
added all samples
[wxWidgets.git] / src / generic / scrlwing.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
d80cd92a 2// Name: generic/scrolwin.cpp
fa3541bd 3// Purpose: wxGenericScrolledWindow implementation
c801d85f 4// Author: Julian Smart
566d84a7
RL
5// Modified by: Vadim Zeitlin on 31.08.00: wxScrollHelper allows to implement.
6// Ron Lee on 10.4.02: virtual size / auto scrollbars et al.
c801d85f
KB
7// Created: 01/02/97
8// RCS-ID: $Id$
1e6feb95 9// Copyright: (c) wxWindows team
6aa89a22 10// Licence: wxWindows licence
c801d85f
KB
11/////////////////////////////////////////////////////////////////////////////
12
d80cd92a
VZ
13// ============================================================================
14// declarations
15// ============================================================================
16
17// ----------------------------------------------------------------------------
18// headers
19// ----------------------------------------------------------------------------
20
c801d85f 21#ifdef __GNUG__
3a8c693a 22 #pragma implementation "genscrolwin.h"
c801d85f
KB
23#endif
24
bcd055ae
JJ
25#ifdef __VMS
26#define XtDisplay XTDISPLAY
27#endif
28
c801d85f
KB
29// For compilers that support precompilation, includes "wx.h".
30#include "wx/wxprec.h"
31
c801d85f 32#ifdef __BORLANDC__
d80cd92a 33 #pragma hdrstop
c801d85f
KB
34#endif
35
3a8c693a
VZ
36#if !defined(__WXGTK__) || defined(__WXUNIVERSAL__)
37
d80cd92a
VZ
38#include "wx/utils.h"
39#include "wx/dcclient.h"
40
1e6feb95 41#include "wx/scrolwin.h"
053f9cc1 42#include "wx/panel.h"
1e6feb95 43#include "wx/timer.h"
95d60b24 44#include "wx/sizer.h"
c801d85f 45
48d1144b 46#ifdef __WXMSW__
1e6feb95 47 #include <windows.h> // for DLGC_WANTARROWS
48d1144b
JS
48#endif
49
a91b47e8
JS
50#ifdef __WXMOTIF__
51// For wxRETAINED implementation
338dd992
JJ
52#ifdef __VMS__ //VMS's Xm.h is not (yet) compatible with C++
53 //This code switches off the compiler warnings
54# pragma message disable nosimpint
55#endif
a91b47e8 56#include <Xm/Xm.h>
338dd992
JJ
57#ifdef __VMS__
58# pragma message enable nosimpint
59#endif
a91b47e8
JS
60#endif
61
fa3541bd 62IMPLEMENT_CLASS(wxScrolledWindow, wxGenericScrolledWindow)
fa3541bd 63
066f1b7a
SC
64/*
65 TODO PROPERTIES
66 style wxHSCROLL | wxVSCROLL
67*/
68
d80cd92a 69// ----------------------------------------------------------------------------
1e6feb95
VZ
70// wxScrollHelperEvtHandler: intercept the events from the window and forward
71// them to wxScrollHelper
d80cd92a
VZ
72// ----------------------------------------------------------------------------
73
349efbaa 74class WXDLLEXPORT wxScrollHelperEvtHandler : public wxEvtHandler
1e6feb95
VZ
75{
76public:
77 wxScrollHelperEvtHandler(wxScrollHelper *scrollHelper)
78 {
79 m_scrollHelper = scrollHelper;
80 }
d80cd92a 81
1e6feb95
VZ
82 virtual bool ProcessEvent(wxEvent& event);
83
349efbaa
VZ
84 void ResetDrawnFlag() { m_hasDrawnWindow = FALSE; }
85
1e6feb95
VZ
86private:
87 wxScrollHelper *m_scrollHelper;
349efbaa
VZ
88
89 bool m_hasDrawnWindow;
22f3361e
VZ
90
91 DECLARE_NO_COPY_CLASS(wxScrollHelperEvtHandler)
1e6feb95
VZ
92};
93
94// ----------------------------------------------------------------------------
95// wxAutoScrollTimer: the timer used to generate a stream of scroll events when
96// a captured mouse is held outside the window
97// ----------------------------------------------------------------------------
98
99class wxAutoScrollTimer : public wxTimer
100{
101public:
102 wxAutoScrollTimer(wxWindow *winToScroll, wxScrollHelper *scroll,
103 wxEventType eventTypeToSend,
104 int pos, int orient);
105
106 virtual void Notify();
107
108private:
109 wxWindow *m_win;
110 wxScrollHelper *m_scrollHelper;
111 wxEventType m_eventType;
112 int m_pos,
113 m_orient;
22f3361e
VZ
114
115 DECLARE_NO_COPY_CLASS(wxAutoScrollTimer)
1e6feb95 116};
d80cd92a
VZ
117
118// ============================================================================
119// implementation
120// ============================================================================
121
122// ----------------------------------------------------------------------------
1e6feb95 123// wxAutoScrollTimer
d80cd92a
VZ
124// ----------------------------------------------------------------------------
125
1e6feb95
VZ
126wxAutoScrollTimer::wxAutoScrollTimer(wxWindow *winToScroll,
127 wxScrollHelper *scroll,
128 wxEventType eventTypeToSend,
129 int pos, int orient)
c801d85f 130{
1e6feb95
VZ
131 m_win = winToScroll;
132 m_scrollHelper = scroll;
133 m_eventType = eventTypeToSend;
134 m_pos = pos;
135 m_orient = orient;
c801d85f
KB
136}
137
1e6feb95 138void wxAutoScrollTimer::Notify()
c801d85f 139{
1e6feb95
VZ
140 // only do all this as long as the window is capturing the mouse
141 if ( wxWindow::GetCapture() != m_win )
142 {
143 Stop();
144 }
145 else // we still capture the mouse, continue generating events
146 {
147 // first scroll the window if we are allowed to do it
148 wxScrollWinEvent event1(m_eventType, m_pos, m_orient);
149 event1.SetEventObject(m_win);
150 if ( m_scrollHelper->SendAutoScrollEvents(event1) &&
151 m_win->GetEventHandler()->ProcessEvent(event1) )
152 {
153 // and then send a pseudo mouse-move event to refresh the selection
154 wxMouseEvent event2(wxEVT_MOTION);
155 wxGetMousePosition(&event2.m_x, &event2.m_y);
156
157 // the mouse event coordinates should be client, not screen as
158 // returned by wxGetMousePosition
159 wxWindow *parentTop = m_win;
160 while ( parentTop->GetParent() )
161 parentTop = parentTop->GetParent();
162 wxPoint ptOrig = parentTop->GetPosition();
163 event2.m_x -= ptOrig.x;
164 event2.m_y -= ptOrig.y;
165
166 event2.SetEventObject(m_win);
167
168 // FIXME: we don't fill in the other members - ok?
169
170 m_win->GetEventHandler()->ProcessEvent(event2);
171 }
172 else // can't scroll further, stop
173 {
174 Stop();
175 }
176 }
177}
178
179// ----------------------------------------------------------------------------
180// wxScrollHelperEvtHandler
181// ----------------------------------------------------------------------------
182
183bool wxScrollHelperEvtHandler::ProcessEvent(wxEvent& event)
184{
9a268018 185 wxEventType evType = event.GetEventType();
2feed004 186
349efbaa
VZ
187 // the explanation of wxEVT_PAINT processing hack: for historic reasons
188 // there are 2 ways to process this event in classes deriving from
189 // wxScrolledWindow. The user code may
190 //
191 // 1. override wxScrolledWindow::OnDraw(dc)
192 // 2. define its own OnPaint() handler
193 //
194 // In addition, in wxUniversal wxWindow defines OnPaint() itself and
195 // always processes the draw event, so we can't just try the window
196 // OnPaint() first and call our HandleOnPaint() if it doesn't process it
197 // (the latter would never be called in wxUniversal).
198 //
199 // So the solution is to have a flag telling us whether the user code drew
200 // anything in the window. We set it to true here but reset it to false in
201 // wxScrolledWindow::OnPaint() handler (which wouldn't be called if the
202 // user code defined OnPaint() in the derived class)
203 m_hasDrawnWindow = TRUE;
204
ff186591
VZ
205 // pass it on to the real handler
206 bool processed = wxEvtHandler::ProcessEvent(event);
207
208 // always process the size events ourselves, even if the user code handles
209 // them as well, as we need to AdjustScrollbars()
210 //
211 // NB: it is important to do it after processing the event in the normal
212 // way as HandleOnSize() may generate a wxEVT_SIZE itself if the
213 // scrollbar[s] (dis)appear and it should be seen by the user code
214 // after this one
215 if ( evType == wxEVT_SIZE )
216 {
217 m_scrollHelper->HandleOnSize((wxSizeEvent &)event);
218
219 return TRUE;
220 }
221
222 if ( processed )
349efbaa
VZ
223 {
224 // normally, nothing more to do here - except if it was a paint event
225 // which wasn't really processed, then we'll try to call our
226 // OnDraw() below (from HandleOnPaint)
993cfa87 227 if ( m_hasDrawnWindow )
349efbaa
VZ
228 {
229 return TRUE;
230 }
231 }
2feed004 232
1e6feb95
VZ
233 // reset the skipped flag to FALSE as it might have been set to TRUE in
234 // ProcessEvent() above
235 event.Skip(FALSE);
236
e421922f
VZ
237 if ( evType == wxEVT_PAINT )
238 {
239 m_scrollHelper->HandleOnPaint((wxPaintEvent &)event);
240 return TRUE;
241 }
1e6feb95 242
e421922f
VZ
243 if ( evType == wxEVT_SCROLLWIN_TOP ||
244 evType == wxEVT_SCROLLWIN_BOTTOM ||
245 evType == wxEVT_SCROLLWIN_LINEUP ||
246 evType == wxEVT_SCROLLWIN_LINEDOWN ||
247 evType == wxEVT_SCROLLWIN_PAGEUP ||
248 evType == wxEVT_SCROLLWIN_PAGEDOWN ||
249 evType == wxEVT_SCROLLWIN_THUMBTRACK ||
250 evType == wxEVT_SCROLLWIN_THUMBRELEASE )
251 {
252 m_scrollHelper->HandleOnScroll((wxScrollWinEvent &)event);
1e6feb95 253 return !event.GetSkipped();
e421922f 254 }
1e6feb95 255
e421922f
VZ
256 if ( evType == wxEVT_ENTER_WINDOW )
257 {
258 m_scrollHelper->HandleOnMouseEnter((wxMouseEvent &)event);
259 }
260 else if ( evType == wxEVT_LEAVE_WINDOW )
261 {
262 m_scrollHelper->HandleOnMouseLeave((wxMouseEvent &)event);
263 }
264#if wxUSE_MOUSEWHEEL
265 else if ( evType == wxEVT_MOUSEWHEEL )
266 {
267 m_scrollHelper->HandleOnMouseWheel((wxMouseEvent &)event);
268 }
269#endif // wxUSE_MOUSEWHEEL
e421922f
VZ
270 else if ( evType == wxEVT_CHAR )
271 {
272 m_scrollHelper->HandleOnChar((wxKeyEvent &)event);
273 return !event.GetSkipped();
1e6feb95
VZ
274 }
275
276 return FALSE;
277}
278
279// ----------------------------------------------------------------------------
280// wxScrollHelper construction
281// ----------------------------------------------------------------------------
282
283wxScrollHelper::wxScrollHelper(wxWindow *win)
284{
285 m_xScrollPixelsPerLine =
286 m_yScrollPixelsPerLine =
287 m_xScrollPosition =
288 m_yScrollPosition =
289 m_xScrollLines =
290 m_yScrollLines =
291 m_xScrollLinesPerPage =
139adb6a 292 m_yScrollLinesPerPage = 0;
1e6feb95
VZ
293
294 m_xScrollingEnabled =
295 m_yScrollingEnabled = TRUE;
296
297 m_scaleX =
139adb6a 298 m_scaleY = 1.0;
24ce4c18 299#if wxUSE_MOUSEWHEEL
d2c52078 300 m_wheelRotation = 0;
24ce4c18 301#endif
a58a12e9 302
1e6feb95
VZ
303 m_win =
304 m_targetWindow = (wxWindow *)NULL;
139adb6a 305
1e6feb95 306 m_timerAutoScroll = (wxTimer *)NULL;
d7da9756 307
349efbaa
VZ
308 m_handler = NULL;
309
1e6feb95
VZ
310 if ( win )
311 SetWindow(win);
312}
d7da9756 313
1e6feb95 314wxScrollHelper::~wxScrollHelper()
d80cd92a 315{
1e6feb95
VZ
316 StopAutoScrolling();
317
349efbaa 318 DeleteEvtHandler();
d80cd92a
VZ
319}
320
321// ----------------------------------------------------------------------------
322// setting scrolling parameters
323// ----------------------------------------------------------------------------
324
1e6feb95
VZ
325void wxScrollHelper::SetScrollbars(int pixelsPerUnitX,
326 int pixelsPerUnitY,
327 int noUnitsX,
328 int noUnitsY,
329 int xPos,
330 int yPos,
331 bool noRefresh)
c801d85f 332{
b0486e0d
SN
333 int xpos, ypos;
334
335 CalcUnscrolledPosition(xPos, yPos, &xpos, &ypos);
139adb6a
RR
336 bool do_refresh =
337 (
c801d85f 338 (noUnitsX != 0 && m_xScrollLines == 0) ||
566d84a7 339 (noUnitsX < m_xScrollLines && xpos > pixelsPerUnitX * noUnitsX) ||
b0486e0d 340
c801d85f 341 (noUnitsY != 0 && m_yScrollLines == 0) ||
566d84a7 342 (noUnitsY < m_yScrollLines && ypos > pixelsPerUnitY * noUnitsY) ||
c801d85f 343 (xPos != m_xScrollPosition) ||
b0486e0d 344 (yPos != m_yScrollPosition)
139adb6a 345 );
a58a12e9 346
139adb6a
RR
347 m_xScrollPixelsPerLine = pixelsPerUnitX;
348 m_yScrollPixelsPerLine = pixelsPerUnitY;
349 m_xScrollPosition = xPos;
350 m_yScrollPosition = yPos;
a91b47e8 351
150c8d89
RL
352 int w = noUnitsX * pixelsPerUnitX;
353 int h = noUnitsY * pixelsPerUnitY;
354
2b5f62a0
VZ
355 // For better backward compatibility we set persisting limits
356 // here not just the size. It makes SetScrollbars 'sticky'
357 // emulating the old non-autoscroll behaviour.
358
150c8d89 359 m_targetWindow->SetVirtualSizeHints( w, h );
a58a12e9 360
2b5f62a0
VZ
361 // The above should arguably be deprecated, this however we still need.
362
150c8d89 363 m_targetWindow->SetVirtualSize( w, h );
dc429f89 364
a58a12e9 365 if (do_refresh && !noRefresh)
d5d58a93 366 m_targetWindow->Refresh(TRUE, GetScrollRect());
a58a12e9 367
1f066698
VZ
368#ifndef __WXUNIVERSAL__
369 // If the target is not the same as the window with the scrollbars,
370 // then we need to update the scrollbars here, since they won't have
371 // been updated by SetVirtualSize().
372 if ( m_targetWindow != m_win )
373#endif // !__WXUNIVERSAL__
374 {
375 AdjustScrollbars();
376 }
377#ifndef __WXUNIVERSAL__
378 else
379 {
380 // otherwise this has been done by AdjustScrollbars, above
7c74e7fe 381#ifdef __WXMAC__
1f066698 382 m_targetWindow->Update() ;
03d1ae17 383#endif
1f066698
VZ
384 }
385#endif // !__WXUNIVERSAL__
c801d85f
KB
386}
387
d80cd92a 388// ----------------------------------------------------------------------------
af4088f1 389// [target] window handling
d80cd92a 390// ----------------------------------------------------------------------------
ecab4dba 391
349efbaa 392void wxScrollHelper::DeleteEvtHandler()
ecab4dba 393{
248d771c
VZ
394 // search for m_handler in the handler list
395 if ( m_win && m_handler )
349efbaa 396 {
74f6bbf9 397 if ( m_win->RemoveEventHandler(m_handler) )
248d771c 398 {
74f6bbf9 399 delete m_handler;
248d771c 400 }
74f6bbf9
VZ
401 //else: something is very wrong, so better [maybe] leak memory than
402 // risk a crash because of double deletion
248d771c 403
74f6bbf9 404 m_handler = NULL;
349efbaa
VZ
405 }
406}
407
408void wxScrollHelper::SetWindow(wxWindow *win)
409{
410 wxCHECK_RET( win, _T("wxScrollHelper needs a window to scroll") );
411
412 m_win = win;
413
af4088f1
VZ
414 // by default, the associated window is also the target window
415 DoSetTargetWindow(win);
349efbaa
VZ
416}
417
af4088f1 418void wxScrollHelper::DoSetTargetWindow(wxWindow *target)
349efbaa 419{
ecab4dba 420 m_targetWindow = target;
349efbaa
VZ
421
422 // install the event handler which will intercept the events we're
af4088f1
VZ
423 // interested in (but only do it for our real window, not the target window
424 // which we scroll - we don't need to hijack its events)
425 if ( m_targetWindow == m_win )
13ff9344 426 {
248d771c
VZ
427 // if we already have a handler, delete it first
428 DeleteEvtHandler();
429
13ff9344
JS
430 m_handler = new wxScrollHelperEvtHandler(this);
431 m_targetWindow->PushEventHandler(m_handler);
432 }
349efbaa
VZ
433}
434
af4088f1 435void wxScrollHelper::SetTargetWindow(wxWindow *target)
349efbaa
VZ
436{
437 wxCHECK_RET( target, wxT("target window must not be NULL") );
438
439 if ( target == m_targetWindow )
440 return;
441
af4088f1 442 DoSetTargetWindow(target);
ecab4dba
RR
443}
444
1e6feb95 445wxWindow *wxScrollHelper::GetTargetWindow() const
ecab4dba
RR
446{
447 return m_targetWindow;
448}
449
d80cd92a
VZ
450// ----------------------------------------------------------------------------
451// scrolling implementation itself
452// ----------------------------------------------------------------------------
453
1e6feb95 454void wxScrollHelper::HandleOnScroll(wxScrollWinEvent& event)
c801d85f 455{
139adb6a 456 int nScrollInc = CalcScrollInc(event);
1e6feb95 457 if ( nScrollInc == 0 )
139adb6a 458 {
1e6feb95
VZ
459 // can't scroll further
460 event.Skip();
461
462 return;
139adb6a 463 }
c801d85f 464
1e6feb95 465 int orient = event.GetOrientation();
139adb6a
RR
466 if (orient == wxHORIZONTAL)
467 {
468 m_xScrollPosition += nScrollInc;
5f3286d1 469 m_win->SetScrollPos(wxHORIZONTAL, m_xScrollPosition);
139adb6a 470 }
c801d85f 471 else
139adb6a
RR
472 {
473 m_yScrollPosition += nScrollInc;
5f3286d1 474 m_win->SetScrollPos(wxVERTICAL, m_yScrollPosition);
139adb6a 475 }
a58a12e9 476
1e6feb95
VZ
477 bool needsRefresh = FALSE;
478 int dx = 0,
479 dy = 0;
139adb6a
RR
480 if (orient == wxHORIZONTAL)
481 {
1e6feb95
VZ
482 if ( m_xScrollingEnabled )
483 {
484 dx = -m_xScrollPixelsPerLine * nScrollInc;
485 }
139adb6a 486 else
1e6feb95
VZ
487 {
488 needsRefresh = TRUE;
489 }
139adb6a 490 }
c801d85f 491 else
139adb6a 492 {
1e6feb95
VZ
493 if ( m_yScrollingEnabled )
494 {
495 dy = -m_yScrollPixelsPerLine * nScrollInc;
496 }
139adb6a 497 else
1e6feb95
VZ
498 {
499 needsRefresh = TRUE;
500 }
501 }
502
503 if ( needsRefresh )
504 {
d5d58a93 505 m_targetWindow->Refresh(TRUE, GetScrollRect());
1e6feb95
VZ
506 }
507 else
508 {
d5d58a93 509 m_targetWindow->ScrollWindow(dx, dy, GetScrollRect());
3d2b9c20 510 }
1e6feb95 511
7c74e7fe 512#ifdef __WXMAC__
1f066698 513 m_targetWindow->Update() ;
7c74e7fe 514#endif
c801d85f
KB
515}
516
1e6feb95 517int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event)
c801d85f 518{
ecab4dba
RR
519 int pos = event.GetPosition();
520 int orient = event.GetOrientation();
c801d85f 521
ecab4dba 522 int nScrollInc = 0;
1a8caf94 523 if (event.GetEventType() == wxEVT_SCROLLWIN_TOP)
c801d85f 524 {
ecab4dba
RR
525 if (orient == wxHORIZONTAL)
526 nScrollInc = - m_xScrollPosition;
527 else
528 nScrollInc = - m_yScrollPosition;
1a8caf94
RR
529 } else
530 if (event.GetEventType() == wxEVT_SCROLLWIN_BOTTOM)
531 {
ecab4dba
RR
532 if (orient == wxHORIZONTAL)
533 nScrollInc = m_xScrollLines - m_xScrollPosition;
534 else
535 nScrollInc = m_yScrollLines - m_yScrollPosition;
1a8caf94
RR
536 } else
537 if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP)
538 {
ecab4dba 539 nScrollInc = -1;
1a8caf94
RR
540 } else
541 if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN)
542 {
ecab4dba 543 nScrollInc = 1;
1a8caf94
RR
544 } else
545 if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEUP)
546 {
ecab4dba
RR
547 if (orient == wxHORIZONTAL)
548 nScrollInc = -GetScrollPageSize(wxHORIZONTAL);
549 else
550 nScrollInc = -GetScrollPageSize(wxVERTICAL);
1a8caf94
RR
551 } else
552 if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN)
553 {
ecab4dba
RR
554 if (orient == wxHORIZONTAL)
555 nScrollInc = GetScrollPageSize(wxHORIZONTAL);
556 else
557 nScrollInc = GetScrollPageSize(wxVERTICAL);
1a8caf94
RR
558 } else
559 if ((event.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK) ||
560 (event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE))
561 {
ecab4dba
RR
562 if (orient == wxHORIZONTAL)
563 nScrollInc = pos - m_xScrollPosition;
564 else
565 nScrollInc = pos - m_yScrollPosition;
c801d85f 566 }
88150e60 567
ecab4dba
RR
568 if (orient == wxHORIZONTAL)
569 {
a58a12e9 570 if (m_xScrollPixelsPerLine > 0)
ecab4dba
RR
571 {
572 int w, h;
1e6feb95 573 GetTargetSize(&w, &h);
ecab4dba
RR
574
575 int nMaxWidth = m_xScrollLines*m_xScrollPixelsPerLine;
576 int noPositions = (int) ( ((nMaxWidth - w)/(double)m_xScrollPixelsPerLine) + 0.5 );
577 if (noPositions < 0)
d80cd92a 578 noPositions = 0;
ecab4dba
RR
579
580 if ( (m_xScrollPosition + nScrollInc) < 0 )
d80cd92a 581 nScrollInc = -m_xScrollPosition; // As -ve as we can go
ecab4dba 582 else if ( (m_xScrollPosition + nScrollInc) > noPositions )
d80cd92a 583 nScrollInc = noPositions - m_xScrollPosition; // As +ve as we can go
ecab4dba
RR
584 }
585 else
d5d58a93 586 m_targetWindow->Refresh(TRUE, GetScrollRect());
9d9355c6
VZ
587 }
588 else
ecab4dba 589 {
be9b0663 590 if ( m_yScrollPixelsPerLine > 0 )
d80cd92a 591 {
be9b0663
VZ
592 if ( m_yScrollPosition + nScrollInc < 0 )
593 {
594 // As -ve as we can go
595 nScrollInc = -m_yScrollPosition;
596 }
597 else // check for the other bound
598 {
599 const int posMax = m_yScrollLines - m_yScrollLinesPerPage;
600 if ( m_yScrollPosition + nScrollInc > posMax )
601 {
602 // As +ve as we can go
603 nScrollInc = posMax - m_yScrollPosition;
604 }
605 }
ecab4dba
RR
606 }
607 else
be9b0663
VZ
608 {
609 // VZ: why do we do this? (FIXME)
d5d58a93 610 m_targetWindow->Refresh(TRUE, GetScrollRect());
be9b0663 611 }
9d9355c6 612 }
9d9355c6 613
ecab4dba 614 return nScrollInc;
c801d85f
KB
615}
616
617// Adjust the scrollbars - new version.
1e6feb95 618void wxScrollHelper::AdjustScrollbars()
c801d85f 619{
aeb313f3 620#ifdef __WXMAC__
1f066698 621 m_targetWindow->Update();
aeb313f3
SC
622#endif
623
566d84a7
RL
624 int w = 0, h = 0;
625 int oldw, oldh;
a58a12e9 626
27d029c7
RR
627 int oldXScroll = m_xScrollPosition;
628 int oldYScroll = m_yScrollPosition;
c801d85f 629
be9b0663
VZ
630 // VZ: at least under Windows this loop is useless because when scrollbars
631 // [dis]appear we get a WM_SIZE resulting in another call to
632 // AdjustScrollbars() anyhow. As it doesn't seem to do any harm I leave
633 // it here for now but it would be better to ensure that all ports
634 // generate EVT_SIZE when scrollbars [dis]appear, emulating it if
635 // necessary, and remove it later
636 do
637 {
566d84a7 638 GetTargetSize(&w, 0);
c801d85f 639
566d84a7
RL
640 if (m_xScrollPixelsPerLine == 0)
641 {
642 m_xScrollLines = 0;
643 m_xScrollPosition = 0;
644 m_win->SetScrollbar (wxHORIZONTAL, 0, 0, 0, FALSE);
645 }
646 else
647 {
648 m_xScrollLines = m_targetWindow->GetVirtualSize().GetWidth() / m_xScrollPixelsPerLine;
649
650 // Calculate page size i.e. number of scroll units you get on the
651 // current client window
652 int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 );
653 if (noPagePositions < 1) noPagePositions = 1;
654 if ( noPagePositions > m_xScrollLines )
655 noPagePositions = m_xScrollLines;
656
657 // Correct position if greater than extent of canvas minus
658 // the visible portion of it or if below zero
659 m_xScrollPosition = wxMin( m_xScrollLines - noPagePositions, m_xScrollPosition);
660 m_xScrollPosition = wxMax( 0, m_xScrollPosition );
661
662 m_win->SetScrollbar(wxHORIZONTAL, m_xScrollPosition, noPagePositions, m_xScrollLines);
663 // The amount by which we scroll when paging
664 SetScrollPageSize(wxHORIZONTAL, noPagePositions);
665 }
c801d85f 666
566d84a7 667 GetTargetSize(0, &h);
a58a12e9 668
be9b0663
VZ
669 // scroll lines per page: if 0, no scrolling is needed
670 int linesPerPage;
671
672 if ( m_yScrollPixelsPerLine == 0 )
566d84a7 673 {
be9b0663 674 // scrolling is disabled
566d84a7
RL
675 m_yScrollLines = 0;
676 m_yScrollPosition = 0;
be9b0663 677 linesPerPage = 0;
566d84a7 678 }
be9b0663 679 else // might need scrolling
566d84a7 680 {
be9b0663
VZ
681 int hVirt = m_targetWindow->GetVirtualSize().GetHeight();
682 m_yScrollLines = hVirt / m_yScrollPixelsPerLine;
566d84a7
RL
683
684 // Calculate page size i.e. number of scroll units you get on the
685 // current client window
be9b0663
VZ
686 linesPerPage = h / m_yScrollPixelsPerLine;
687 if ( linesPerPage >= m_yScrollLines )
688 {
689 // we're big enough to not need scrolling
690 linesPerPage =
691 m_yScrollLines =
692 m_yScrollPosition = 0;
693 }
694 else // we do need a scrollbar
695 {
696 if ( linesPerPage < 1 )
697 linesPerPage = 1;
698
699 // Correct position if greater than extent of canvas minus
700 // the visible portion of it or if below zero
701 const int posMax = m_yScrollLines - linesPerPage;
702 if ( m_yScrollPosition > posMax )
703 m_yScrollPosition = posMax;
704 else if ( m_yScrollPosition < 0 )
705 m_yScrollPosition = 0;
706 }
707 }
566d84a7 708
be9b0663
VZ
709 m_win->SetScrollbar(wxVERTICAL, m_yScrollPosition,
710 linesPerPage, m_yScrollLines);
566d84a7 711
be9b0663
VZ
712 // The amount by which we scroll when paging
713 SetScrollPageSize(wxVERTICAL, linesPerPage);
c801d85f 714
139adb6a 715
be9b0663 716 // If a scrollbar (dis)appeared as a result of this, adjust them again.
566d84a7
RL
717 oldw = w;
718 oldh = h;
719
720 GetTargetSize( &w, &h );
721 } while ( w != oldw && h != oldh );
722
723#ifdef __WXMOTIF__
724 // Sorry, some Motif-specific code to implement a backing pixmap
725 // for the wxRETAINED style. Implementing a backing store can't
726 // be entirely generic because it relies on the wxWindowDC implementation
727 // to duplicate X drawing calls for the backing pixmap.
728
729 if ( m_targetWindow->GetWindowStyle() & wxRETAINED )
139adb6a 730 {
566d84a7
RL
731 Display* dpy = XtDisplay((Widget)m_targetWindow->GetMainWidget());
732
733 int totalPixelWidth = m_xScrollLines * m_xScrollPixelsPerLine;
734 int totalPixelHeight = m_yScrollLines * m_yScrollPixelsPerLine;
735 if (m_targetWindow->GetBackingPixmap() &&
736 !((m_targetWindow->GetPixmapWidth() == totalPixelWidth) &&
737 (m_targetWindow->GetPixmapHeight() == totalPixelHeight)))
738 {
739 XFreePixmap (dpy, (Pixmap) m_targetWindow->GetBackingPixmap());
740 m_targetWindow->SetBackingPixmap((WXPixmap) 0);
741 }
742
743 if (!m_targetWindow->GetBackingPixmap() &&
9b66c26a 744 (m_xScrollLines != 0) && (m_yScrollLines != 0))
566d84a7
RL
745 {
746 int depth = wxDisplayDepth();
747 m_targetWindow->SetPixmapWidth(totalPixelWidth);
748 m_targetWindow->SetPixmapHeight(totalPixelHeight);
749 m_targetWindow->SetBackingPixmap((WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
750 m_targetWindow->GetPixmapWidth(), m_targetWindow->GetPixmapHeight(), depth));
751 }
752
139adb6a 753 }
566d84a7 754#endif // Motif
a58a12e9 755
27d029c7
RR
756 if (oldXScroll != m_xScrollPosition)
757 {
758 if (m_xScrollingEnabled)
566d84a7 759 m_targetWindow->ScrollWindow( m_xScrollPixelsPerLine * (oldXScroll - m_xScrollPosition), 0,
d5d58a93 760 GetScrollRect() );
27d029c7 761 else
d5d58a93 762 m_targetWindow->Refresh(TRUE, GetScrollRect());
27d029c7 763 }
a58a12e9 764
27d029c7
RR
765 if (oldYScroll != m_yScrollPosition)
766 {
767 if (m_yScrollingEnabled)
1e6feb95 768 m_targetWindow->ScrollWindow( 0, m_yScrollPixelsPerLine * (oldYScroll-m_yScrollPosition),
d5d58a93 769 GetScrollRect() );
27d029c7 770 else
d5d58a93 771 m_targetWindow->Refresh(TRUE, GetScrollRect());
27d029c7 772 }
aeb313f3
SC
773
774#ifdef __WXMAC__
1f066698 775 m_targetWindow->Update();
aeb313f3 776#endif
c801d85f
KB
777}
778
1e6feb95 779void wxScrollHelper::DoPrepareDC(wxDC& dc)
c801d85f 780{
1e6feb95
VZ
781 wxPoint pt = dc.GetDeviceOrigin();
782 dc.SetDeviceOrigin( pt.x - m_xScrollPosition * m_xScrollPixelsPerLine,
783 pt.y - m_yScrollPosition * m_yScrollPixelsPerLine );
139adb6a 784 dc.SetUserScale( m_scaleX, m_scaleY );
c801d85f
KB
785}
786
566d84a7
RL
787void wxScrollHelper::SetScrollRate( int xstep, int ystep )
788{
789 int old_x = m_xScrollPixelsPerLine * m_xScrollPosition;
790 int old_y = m_yScrollPixelsPerLine * m_yScrollPosition;
791
792 m_xScrollPixelsPerLine = xstep;
793 m_yScrollPixelsPerLine = ystep;
794
795 int new_x = m_xScrollPixelsPerLine * m_xScrollPosition;
796 int new_y = m_yScrollPixelsPerLine * m_yScrollPosition;
797
798 m_win->SetScrollPos( wxHORIZONTAL, m_xScrollPosition );
799 m_win->SetScrollPos( wxVERTICAL, m_yScrollPosition );
800 m_targetWindow->ScrollWindow( old_x - new_x, old_y - new_y );
801
802 AdjustScrollbars();
803}
804
1e6feb95 805void wxScrollHelper::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
c801d85f 806{
a0bc2c1d
VZ
807 if ( x_unit )
808 *x_unit = m_xScrollPixelsPerLine;
809 if ( y_unit )
810 *y_unit = m_yScrollPixelsPerLine;
c801d85f
KB
811}
812
1e6feb95 813int wxScrollHelper::GetScrollPageSize(int orient) const
c801d85f
KB
814{
815 if ( orient == wxHORIZONTAL )
816 return m_xScrollLinesPerPage;
817 else
818 return m_yScrollLinesPerPage;
819}
820
1e6feb95 821void wxScrollHelper::SetScrollPageSize(int orient, int pageSize)
c801d85f
KB
822{
823 if ( orient == wxHORIZONTAL )
824 m_xScrollLinesPerPage = pageSize;
825 else
826 m_yScrollLinesPerPage = pageSize;
827}
828
829/*
830 * Scroll to given position (scroll position, not pixel position)
831 */
1e6feb95 832void wxScrollHelper::Scroll( int x_pos, int y_pos )
c801d85f 833{
8b089c5e
JS
834 if (!m_targetWindow)
835 return;
836
a58a12e9 837 if (((x_pos == -1) || (x_pos == m_xScrollPosition)) &&
139adb6a 838 ((y_pos == -1) || (y_pos == m_yScrollPosition))) return;
a58a12e9 839
aeb313f3 840#ifdef __WXMAC__
1f066698 841 m_targetWindow->Update();
aeb313f3
SC
842#endif
843
139adb6a 844 int w, h;
1e6feb95 845 GetTargetSize(&w, &h);
c801d85f 846
8775b357 847 if ((x_pos != -1) && (m_xScrollPixelsPerLine))
c801d85f 848 {
ed673c6a 849 int old_x = m_xScrollPosition;
139adb6a 850 m_xScrollPosition = x_pos;
a58a12e9 851
3d2b9c20
RR
852 // Calculate page size i.e. number of scroll units you get on the
853 // current client window
ecab4dba 854 int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 );
139adb6a
RR
855 if (noPagePositions < 1) noPagePositions = 1;
856
857 // Correct position if greater than extent of canvas minus
3d2b9c20 858 // the visible portion of it or if below zero
139adb6a
RR
859 m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition );
860 m_xScrollPosition = wxMax( 0, m_xScrollPosition );
a58a12e9 861
f6bcfd97 862 if (old_x != m_xScrollPosition) {
5f3286d1 863 m_win->SetScrollPos( wxHORIZONTAL, m_xScrollPosition );
1e6feb95 864 m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0,
d5d58a93 865 GetScrollRect() );
f6bcfd97 866 }
c801d85f 867 }
8775b357 868 if ((y_pos != -1) && (m_yScrollPixelsPerLine))
c801d85f 869 {
ed673c6a 870 int old_y = m_yScrollPosition;
139adb6a 871 m_yScrollPosition = y_pos;
a58a12e9 872
3d2b9c20
RR
873 // Calculate page size i.e. number of scroll units you get on the
874 // current client window
ecab4dba 875 int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 );
139adb6a
RR
876 if (noPagePositions < 1) noPagePositions = 1;
877
878 // Correct position if greater than extent of canvas minus
3d2b9c20 879 // the visible portion of it or if below zero
139adb6a
RR
880 m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition );
881 m_yScrollPosition = wxMax( 0, m_yScrollPosition );
d2c52078 882
f6bcfd97 883 if (old_y != m_yScrollPosition) {
5f3286d1 884 m_win->SetScrollPos( wxVERTICAL, m_yScrollPosition );
1e6feb95 885 m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine,
d5d58a93 886 GetScrollRect() );
f6bcfd97 887 }
c801d85f 888 }
a58a12e9 889
7c74e7fe 890#ifdef __WXMAC__
1f066698 891 m_targetWindow->Update();
7c74e7fe 892#endif
aeb313f3 893
c801d85f
KB
894}
895
1e6feb95 896void wxScrollHelper::EnableScrolling (bool x_scroll, bool y_scroll)
c801d85f 897{
139adb6a
RR
898 m_xScrollingEnabled = x_scroll;
899 m_yScrollingEnabled = y_scroll;
c801d85f
KB
900}
901
c801d85f 902// Where the current view starts from
1e6feb95 903void wxScrollHelper::GetViewStart (int *x, int *y) const
c801d85f 904{
a0bc2c1d
VZ
905 if ( x )
906 *x = m_xScrollPosition;
907 if ( y )
908 *y = m_yScrollPosition;
c801d85f
KB
909}
910
8c2f3797 911void wxScrollHelper::DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const
c801d85f 912{
a0bc2c1d
VZ
913 if ( xx )
914 *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine;
915 if ( yy )
916 *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine;
c801d85f
KB
917}
918
8c2f3797 919void wxScrollHelper::DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const
c801d85f 920{
a0bc2c1d
VZ
921 if ( xx )
922 *xx = x + m_xScrollPosition * m_xScrollPixelsPerLine;
923 if ( yy )
924 *yy = y + m_yScrollPosition * m_yScrollPixelsPerLine;
c801d85f 925}
d80cd92a
VZ
926
927// ----------------------------------------------------------------------------
928// event handlers
929// ----------------------------------------------------------------------------
930
931// Default OnSize resets scrollbars, if any
1e6feb95 932void wxScrollHelper::HandleOnSize(wxSizeEvent& WXUNUSED(event))
d80cd92a 933{
150c8d89 934 if( m_win->GetAutoLayout() || m_targetWindow->GetAutoLayout() )
2b5f62a0
VZ
935 {
936 if ( m_targetWindow != m_win )
937 m_targetWindow->FitInside();
566d84a7 938
2b5f62a0 939 m_win->FitInside();
dc429f89 940
150c8d89
RL
941 // FIXME: Something is really weird here... This should be
942 // called by FitInside above (and apparently is), yet the
943 // scrollsub sample will get the scrollbar wrong if resized
944 // quickly. This masks the bug, but is surely not the right
945 // answer at all.
946 AdjustScrollbars();
2b5f62a0
VZ
947 }
948 else
949 AdjustScrollbars();
d80cd92a
VZ
950}
951
952// This calls OnDraw, having adjusted the origin according to the current
953// scroll position
1e6feb95 954void wxScrollHelper::HandleOnPaint(wxPaintEvent& WXUNUSED(event))
d80cd92a 955{
af4088f1
VZ
956 // don't use m_targetWindow here, this is always called for ourselves
957 wxPaintDC dc(m_win);
1e6feb95 958 DoPrepareDC(dc);
d80cd92a
VZ
959
960 OnDraw(dc);
961}
962
438e3558
VZ
963// kbd handling: notice that we use OnChar() and not OnKeyDown() for
964// compatibility here - if we used OnKeyDown(), the programs which process
965// arrows themselves in their OnChar() would never get the message and like
966// this they always have the priority
1e6feb95 967void wxScrollHelper::HandleOnChar(wxKeyEvent& event)
d80cd92a
VZ
968{
969 int stx, sty, // view origin
970 szx, szy, // view size (total)
971 clix, cliy; // view size (on screen)
972
1e6feb95
VZ
973 GetViewStart(&stx, &sty);
974 GetTargetSize(&clix, &cliy);
566d84a7 975 m_targetWindow->GetVirtualSize(&szx, &szy);
56dade3c
RL
976
977 if( m_xScrollPixelsPerLine )
978 {
979 clix /= m_xScrollPixelsPerLine;
d7da9756 980 szx /= m_xScrollPixelsPerLine;
56dade3c
RL
981 }
982 else
983 {
984 clix = 0;
d7da9756 985 szx = -1;
56dade3c
RL
986 }
987 if( m_yScrollPixelsPerLine )
988 {
989 cliy /= m_yScrollPixelsPerLine;
990 szy /= m_yScrollPixelsPerLine;
991 }
992 else
993 {
994 cliy = 0;
d7da9756 995 szy = -1;
56dade3c 996 }
d80cd92a 997
39c869a6
VZ
998 int xScrollOld = m_xScrollPosition,
999 yScrollOld = m_yScrollPosition;
1000
ecb01792 1001 int dsty;
4995ca80 1002 switch ( event.GetKeyCode() )
d80cd92a
VZ
1003 {
1004 case WXK_PAGEUP:
1005 case WXK_PRIOR:
ecb01792
RL
1006 dsty = sty - (5 * cliy / 6);
1007 Scroll(-1, (dsty == -1) ? 0 : dsty);
d80cd92a
VZ
1008 break;
1009
1010 case WXK_PAGEDOWN:
1011 case WXK_NEXT:
1012 Scroll(-1, sty + (5 * cliy / 6));
1013 break;
1014
d80cd92a
VZ
1015 case WXK_HOME:
1016 Scroll(0, event.ControlDown() ? 0 : -1);
1017 break;
1018
1019 case WXK_END:
4acd108c 1020 Scroll(szx - clix, event.ControlDown() ? szy - cliy : -1);
d80cd92a
VZ
1021 break;
1022
1023 case WXK_UP:
1024 Scroll(-1, sty - 1);
1025 break;
1026
1027 case WXK_DOWN:
1028 Scroll(-1, sty + 1);
1029 break;
1030
1031 case WXK_LEFT:
1032 Scroll(stx - 1, -1);
1033 break;
1034
1035 case WXK_RIGHT:
1036 Scroll(stx + 1, -1);
1037 break;
1038
1039 default:
1040 // not for us
1041 event.Skip();
1042 }
39c869a6
VZ
1043
1044 if ( m_xScrollPosition != xScrollOld )
1045 {
1046 wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBTRACK, m_xScrollPosition,
1047 wxHORIZONTAL);
1048 event.SetEventObject(m_win);
1049 m_win->GetEventHandler()->ProcessEvent(event);
1050 }
1051
1052 if ( m_yScrollPosition != yScrollOld )
1053 {
1054 wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBTRACK, m_yScrollPosition,
1055 wxVERTICAL);
1056 event.SetEventObject(m_win);
1057 m_win->GetEventHandler()->ProcessEvent(event);
1058 }
d80cd92a 1059}
d2c52078 1060
1e6feb95
VZ
1061// ----------------------------------------------------------------------------
1062// autoscroll stuff: these functions deal with sending fake scroll events when
1063// a captured mouse is being held outside the window
1064// ----------------------------------------------------------------------------
1065
1066bool wxScrollHelper::SendAutoScrollEvents(wxScrollWinEvent& event) const
1067{
1068 // only send the event if the window is scrollable in this direction
1069 wxWindow *win = (wxWindow *)event.GetEventObject();
1070 return win->HasScrollbar(event.GetOrientation());
1071}
1072
1073void wxScrollHelper::StopAutoScrolling()
1074{
1075 if ( m_timerAutoScroll )
1076 {
1077 delete m_timerAutoScroll;
1078 m_timerAutoScroll = (wxTimer *)NULL;
1079 }
1080}
d2c52078 1081
1e6feb95 1082void wxScrollHelper::HandleOnMouseEnter(wxMouseEvent& event)
d2c52078 1083{
1e6feb95
VZ
1084 StopAutoScrolling();
1085
1086 event.Skip();
1087}
d2c52078 1088
1e6feb95
VZ
1089void wxScrollHelper::HandleOnMouseLeave(wxMouseEvent& event)
1090{
1091 // don't prevent the usual processing of the event from taking place
1092 event.Skip();
1093
1094 // when a captured mouse leave a scrolled window we start generate
1095 // scrolling events to allow, for example, extending selection beyond the
1096 // visible area in some controls
1097 if ( wxWindow::GetCapture() == m_targetWindow )
1098 {
1099 // where is the mouse leaving?
1100 int pos, orient;
1101 wxPoint pt = event.GetPosition();
1102 if ( pt.x < 0 )
1103 {
1104 orient = wxHORIZONTAL;
1105 pos = 0;
1106 }
1107 else if ( pt.y < 0 )
1108 {
1109 orient = wxVERTICAL;
1110 pos = 0;
1111 }
1112 else // we're lower or to the right of the window
1113 {
1114 wxSize size = m_targetWindow->GetClientSize();
1115 if ( pt.x > size.x )
1116 {
1117 orient = wxHORIZONTAL;
1118 pos = m_xScrollLines;
1119 }
1120 else if ( pt.y > size.y )
1121 {
1122 orient = wxVERTICAL;
1123 pos = m_yScrollLines;
1124 }
1125 else // this should be impossible
1126 {
1127 // but seems to happen sometimes under wxMSW - maybe it's a bug
1128 // there but for now just ignore it
1129
1130 //wxFAIL_MSG( _T("can't understand where has mouse gone") );
1131
1132 return;
1133 }
1134 }
1135
1136 // only start the auto scroll timer if the window can be scrolled in
1137 // this direction
1138 if ( !m_targetWindow->HasScrollbar(orient) )
1139 return;
1140
1141 delete m_timerAutoScroll;
1142 m_timerAutoScroll = new wxAutoScrollTimer
1143 (
1144 m_targetWindow, this,
1145 pos == 0 ? wxEVT_SCROLLWIN_LINEUP
1146 : wxEVT_SCROLLWIN_LINEDOWN,
1147 pos,
1148 orient
1149 );
1150 m_timerAutoScroll->Start(50); // FIXME: make configurable
1151 }
1152}
1153
e421922f
VZ
1154#if wxUSE_MOUSEWHEEL
1155
1e6feb95
VZ
1156void wxScrollHelper::HandleOnMouseWheel(wxMouseEvent& event)
1157{
d2c52078 1158 m_wheelRotation += event.GetWheelRotation();
1e6feb95 1159 int lines = m_wheelRotation / event.GetWheelDelta();
d2c52078
RD
1160 m_wheelRotation -= lines * event.GetWheelDelta();
1161
1e6feb95
VZ
1162 if (lines != 0)
1163 {
1e6feb95 1164
b6b85bdc
JS
1165 wxScrollWinEvent newEvent;
1166
ac6f6ffc 1167 newEvent.SetPosition(0);
b6b85bdc
JS
1168 newEvent.SetOrientation(wxVERTICAL);
1169 newEvent.m_eventObject = m_win;
b6b85bdc 1170
9b9337da 1171 if (event.IsPageScroll())
4b056ef5
RD
1172 {
1173 if (lines > 0)
1174 newEvent.m_eventType = wxEVT_SCROLLWIN_PAGEUP;
1175 else
1176 newEvent.m_eventType = wxEVT_SCROLLWIN_PAGEDOWN;
1177
b6b85bdc 1178 m_win->GetEventHandler()->ProcessEvent(newEvent);
4b056ef5
RD
1179 }
1180 else
1181 {
1182 lines *= event.GetLinesPerAction();
1183 if (lines > 0)
1184 newEvent.m_eventType = wxEVT_SCROLLWIN_LINEUP;
1185 else
1186 newEvent.m_eventType = wxEVT_SCROLLWIN_LINEDOWN;
b6b85bdc 1187
4b056ef5
RD
1188 int times = abs(lines);
1189 for (; times > 0; times--)
1190 m_win->GetEventHandler()->ProcessEvent(newEvent);
1191 }
d2c52078
RD
1192 }
1193}
1194
e421922f
VZ
1195#endif // wxUSE_MOUSEWHEEL
1196
1e6feb95
VZ
1197// ----------------------------------------------------------------------------
1198// wxGenericScrolledWindow implementation
1199// ----------------------------------------------------------------------------
1200
1201IMPLEMENT_DYNAMIC_CLASS(wxGenericScrolledWindow, wxPanel)
1202
349efbaa
VZ
1203BEGIN_EVENT_TABLE(wxGenericScrolledWindow, wxPanel)
1204 EVT_PAINT(wxGenericScrolledWindow::OnPaint)
1205END_EVENT_TABLE()
1206
1e6feb95
VZ
1207bool wxGenericScrolledWindow::Create(wxWindow *parent,
1208 wxWindowID id,
1209 const wxPoint& pos,
1210 const wxSize& size,
1211 long style,
1212 const wxString& name)
1213{
1214 m_targetWindow = this;
1215
1216 bool ok = wxPanel::Create(parent, id, pos, size, style, name);
1217
1e6feb95
VZ
1218 return ok;
1219}
1220
1221wxGenericScrolledWindow::~wxGenericScrolledWindow()
1222{
1223}
d2c52078 1224
30486297
RD
1225bool wxGenericScrolledWindow::Layout()
1226{
566d84a7 1227 if (GetSizer() && m_targetWindow == this)
30486297 1228 {
566d84a7
RL
1229 // If we're the scroll target, take into account the
1230 // virtual size and scrolled position of the window.
1231
30486297
RD
1232 int x, y, w, h;
1233 CalcScrolledPosition(0,0, &x,&y);
1234 GetVirtualSize(&w, &h);
1235 GetSizer()->SetDimension(x, y, w, h);
1236 return TRUE;
1237 }
7152f0c6
VZ
1238
1239 // fall back to default for LayoutConstraints
1240 return wxPanel::Layout();
30486297
RD
1241}
1242
2b5f62a0
VZ
1243void wxGenericScrolledWindow::DoSetVirtualSize(int x, int y)
1244{
1245 wxPanel::DoSetVirtualSize( x, y );
1246 AdjustScrollbars();
1247
1248#if wxUSE_CONSTRAINTS
1249 if (GetAutoLayout())
1250 Layout();
1251#endif
1252}
1253
349efbaa
VZ
1254void wxGenericScrolledWindow::OnPaint(wxPaintEvent& event)
1255{
1256 // the user code didn't really draw the window if we got here, so set this
1257 // flag to try to call OnDraw() later
1258 m_handler->ResetDrawnFlag();
1259
1260 event.Skip();
1261}
1262
0cf5b099
VZ
1263#ifdef __WXMSW__
1264long
1265wxGenericScrolledWindow::MSWWindowProc(WXUINT nMsg,
1266 WXWPARAM wParam,
1267 WXLPARAM lParam)
1268{
1269 long rc = wxPanel::MSWWindowProc(nMsg, wParam, lParam);
1270
4676948b 1271#ifndef __WXWINCE__
0cf5b099
VZ
1272 // we need to process arrows ourselves for scrolling
1273 if ( nMsg == WM_GETDLGCODE )
1274 {
1275 rc |= DLGC_WANTARROWS;
1276 }
4676948b 1277#endif
0cf5b099
VZ
1278
1279 return rc;
1280}
1281
1282#endif // __WXMSW__
1283
1e6feb95 1284#if WXWIN_COMPATIBILITY
349efbaa 1285
1e6feb95
VZ
1286void wxGenericScrolledWindow::GetScrollUnitsPerPage (int *x_page, int *y_page) const
1287{
1288 *x_page = GetScrollPageSize(wxHORIZONTAL);
1289 *y_page = GetScrollPageSize(wxVERTICAL);
1290}
d2c52078 1291
1e6feb95
VZ
1292void wxGenericScrolledWindow::CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const
1293{
1294 if ( xx )
1295 *xx = (float)(x + m_xScrollPosition * m_xScrollPixelsPerLine);
1296 if ( yy )
1297 *yy = (float)(y + m_yScrollPosition * m_yScrollPixelsPerLine);
1298}
349efbaa 1299
1e6feb95 1300#endif // WXWIN_COMPATIBILITY
d2c52078 1301
3a8c693a
VZ
1302#endif // !wxGTK
1303
566d84a7 1304// vi:sts=4:sw=4:et