]> git.saurik.com Git - wxWidgets.git/blob - src/generic/scrolwin.cpp
Made wxGTK dcps.cpp generic.
[wxWidgets.git] / src / generic / scrolwin.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: scrolwin.cpp
3 // Purpose: wxScrolledWindow implementation
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #pragma implementation "scrolwin.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #include "wx/utils.h"
21 #include "wx/dcclient.h"
22
23 #ifdef __WXMSW__
24 #include "windows.h"
25 #endif
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #include "wx/generic/scrolwin.h"
32
33 #if !USE_SHARED_LIBRARY
34 BEGIN_EVENT_TABLE(wxScrolledWindow, wxWindow)
35 EVT_SCROLL(wxScrolledWindow::OnScroll)
36 EVT_SIZE(wxScrolledWindow::OnSize)
37 EVT_PAINT(wxScrolledWindow::OnPaint)
38 END_EVENT_TABLE()
39
40 IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxWindow)
41 #endif
42
43 wxScrolledWindow::wxScrolledWindow(void)
44 {
45 m_xScrollPixelsPerLine = 0;
46 m_yScrollPixelsPerLine = 0;
47 m_xScrollingEnabled = TRUE;
48 m_yScrollingEnabled = TRUE;
49 m_xScrollPosition = 0;
50 m_yScrollPosition = 0;
51 m_xScrollLines = 0;
52 m_yScrollLines = 0;
53 m_xScrollLinesPerPage = 0;
54 m_yScrollLinesPerPage = 0;
55 m_scaleX = 1.0;
56 m_scaleY = 1.0;
57 }
58
59 bool wxScrolledWindow::Create(wxWindow *parent, wxWindowID id,
60 const wxPoint& pos,
61 const wxSize& size,
62 long style,
63 const wxString& name)
64 {
65 m_xScrollPixelsPerLine = 0;
66 m_yScrollPixelsPerLine = 0;
67 m_xScrollingEnabled = TRUE;
68 m_yScrollingEnabled = TRUE;
69 m_xScrollPosition = 0;
70 m_yScrollPosition = 0;
71 m_xScrollLines = 0;
72 m_yScrollLines = 0;
73 m_xScrollLinesPerPage = 0;
74 m_yScrollLinesPerPage = 0;
75 m_scaleX = 1.0;
76 m_scaleY = 1.0;
77
78 return wxWindow::Create(parent, id, pos, size, style, name);
79 }
80
81 /*
82 * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line)
83 * noUnitsX/noUnitsY: : no. units per scrollbar
84 */
85 void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY,
86 int noUnitsX, int noUnitsY,
87 int xPos, int yPos, bool noRefresh )
88 {
89 bool do_refresh =
90 (
91 (noUnitsX != 0 && m_xScrollLines == 0) ||
92 (noUnitsX < m_xScrollPosition) ||
93 (noUnitsY != 0 && m_yScrollLines == 0) ||
94 (noUnitsY < m_yScrollPosition) ||
95 (xPos != m_xScrollPosition) ||
96 (yPos != m_yScrollPosition) ||
97 (pixelsPerUnitX != m_xScrollPixelsPerLine) ||
98 (pixelsPerUnitY != m_yScrollPixelsPerLine)
99 );
100
101 m_xScrollPixelsPerLine = pixelsPerUnitX;
102 m_yScrollPixelsPerLine = pixelsPerUnitY;
103 m_xScrollPosition = xPos;
104 m_yScrollPosition = yPos;
105 m_xScrollLines = noUnitsX;
106 m_yScrollLines = noUnitsY;
107
108 AdjustScrollbars();
109
110 if (do_refresh && !noRefresh) Refresh();
111
112 #ifdef __WXMSW__
113 UpdateWindow ((HWND) GetHWND());
114 #endif
115 }
116
117 void wxScrolledWindow::OnScroll(wxScrollEvent& event)
118 {
119 int orient = event.GetOrientation();
120
121 int nScrollInc = CalcScrollInc(event);
122 if (nScrollInc == 0) return;
123
124 if (orient == wxHORIZONTAL)
125 {
126 int newPos = m_xScrollPosition + nScrollInc;
127 SetScrollPos(wxHORIZONTAL, newPos, TRUE );
128 }
129 else
130 {
131 int newPos = m_yScrollPosition + nScrollInc;
132 SetScrollPos(wxVERTICAL, newPos, TRUE );
133 }
134
135 if (orient == wxHORIZONTAL)
136 {
137 m_xScrollPosition += nScrollInc;
138 }
139 else
140 {
141 m_yScrollPosition += nScrollInc;
142 }
143
144 if (orient == wxHORIZONTAL)
145 {
146 if (m_xScrollingEnabled)
147 ScrollWindow(-m_xScrollPixelsPerLine * nScrollInc, 0, (const wxRect *) NULL);
148 else
149 Refresh();
150 }
151 else
152 {
153 if (m_yScrollingEnabled)
154 ScrollWindow(0, -m_yScrollPixelsPerLine * nScrollInc, (const wxRect *) NULL);
155 else
156 Refresh();
157 }
158 }
159
160 int wxScrolledWindow::CalcScrollInc(wxScrollEvent& event)
161 {
162 int pos = event.GetPosition();
163 int orient = event.GetOrientation();
164
165 int nScrollInc = 0;
166 switch (event.GetEventType())
167 {
168 case wxEVT_SCROLL_TOP:
169 {
170 if (orient == wxHORIZONTAL)
171 nScrollInc = - m_xScrollPosition;
172 else
173 nScrollInc = - m_yScrollPosition;
174 break;
175 }
176 case wxEVT_SCROLL_BOTTOM:
177 {
178 if (orient == wxHORIZONTAL)
179 nScrollInc = m_xScrollLines - m_xScrollPosition;
180 else
181 nScrollInc = m_yScrollLines - m_yScrollPosition;
182 break;
183 }
184 case wxEVT_SCROLL_LINEUP:
185 {
186 nScrollInc = -1;
187 break;
188 }
189 case wxEVT_SCROLL_LINEDOWN:
190 {
191 nScrollInc = 1;
192 break;
193 }
194 case wxEVT_SCROLL_PAGEUP:
195 {
196 if (orient == wxHORIZONTAL)
197 nScrollInc = -GetScrollPageSize(wxHORIZONTAL);
198 else
199 nScrollInc = -GetScrollPageSize(wxVERTICAL);
200 break;
201 }
202 case wxEVT_SCROLL_PAGEDOWN:
203 {
204 if (orient == wxHORIZONTAL)
205 nScrollInc = GetScrollPageSize(wxHORIZONTAL);
206 else
207 nScrollInc = GetScrollPageSize(wxVERTICAL);
208 break;
209 }
210 case wxEVT_SCROLL_THUMBTRACK:
211 {
212 if (orient == wxHORIZONTAL)
213 nScrollInc = pos - m_xScrollPosition;
214 else
215 nScrollInc = pos - m_yScrollPosition;
216 break;
217 }
218 default:
219 {
220 break;
221 }
222 }
223
224 if (orient == wxHORIZONTAL)
225 {
226 if (m_xScrollPixelsPerLine > 0) {
227 int w, h;
228 GetClientSize(&w, &h);
229
230 int nMaxWidth = m_xScrollLines*m_xScrollPixelsPerLine;
231 int noPositions = (int) ( ((nMaxWidth - w)/(float)m_xScrollPixelsPerLine) + 0.5 );
232 if (noPositions < 0)
233 noPositions = 0;
234
235 if ( (m_xScrollPosition + nScrollInc) < 0 )
236 nScrollInc = -m_xScrollPosition; // As -ve as we can go
237 else if ( (m_xScrollPosition + nScrollInc) > noPositions )
238 nScrollInc = noPositions - m_xScrollPosition; // As +ve as we can go
239 }
240 else
241 Refresh();
242 }
243 else
244 {
245 if (m_yScrollPixelsPerLine > 0) {
246 int w, h;
247 GetClientSize(&w, &h);
248
249 int nMaxHeight = m_yScrollLines*m_yScrollPixelsPerLine;
250 int noPositions = (int) ( ((nMaxHeight - h)/(float)m_yScrollPixelsPerLine) + 0.5 );
251 if (noPositions < 0)
252 noPositions = 0;
253
254 if ( (m_yScrollPosition + nScrollInc) < 0 )
255 nScrollInc = -m_yScrollPosition; // As -ve as we can go
256 else if ( (m_yScrollPosition + nScrollInc) > noPositions )
257 nScrollInc = noPositions - m_yScrollPosition; // As +ve as we can go
258 }
259 else
260 Refresh();
261 }
262
263 return nScrollInc;
264 }
265
266 // Adjust the scrollbars - new version.
267 void wxScrolledWindow::AdjustScrollbars(void)
268 {
269 int w, h;
270 GetClientSize(&w, &h);
271
272 if (m_xScrollLines > 0)
273 {
274 // Calculate page size i.e. number of scroll units you get on the
275 // current client window
276 int noPagePositions = (int) ( (w/(float)m_xScrollPixelsPerLine) + 0.5 );
277 if (noPagePositions < 1) noPagePositions = 1;
278
279 // Correct position if greater than extent of canvas minus
280 // the visible portion of it or if below zero
281 m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition);
282 m_xScrollPosition = wxMax( 0, m_xScrollPosition );
283
284 SetScrollbar(wxHORIZONTAL, m_xScrollPosition, noPagePositions, m_xScrollLines);
285 // The amount by which we scroll when paging
286 SetScrollPageSize(wxHORIZONTAL, noPagePositions);
287 }
288 else
289 {
290 m_xScrollPosition = 0;
291 SetScrollbar (wxHORIZONTAL, 0, 0, 0, FALSE);
292 }
293
294 if (m_yScrollLines > 0)
295 {
296 // Calculate page size i.e. number of scroll units you get on the
297 // current client window
298 int noPagePositions = (int) ( (h/(float)m_yScrollPixelsPerLine) + 0.5 );
299 if (noPagePositions < 1) noPagePositions = 1;
300
301 // Correct position if greater than extent of canvas minus
302 // the visible portion of it or if below zero
303 m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition );
304 m_yScrollPosition = wxMax( 0, m_yScrollPosition );
305
306 SetScrollbar(wxVERTICAL, m_yScrollPosition, noPagePositions, m_yScrollLines);
307 // The amount by which we scroll when paging
308 SetScrollPageSize(wxVERTICAL, noPagePositions);
309 }
310 else
311 {
312 m_yScrollPosition = 0;
313 SetScrollbar (wxVERTICAL, 0, 0, 0, FALSE);
314 }
315 }
316
317 // Default OnSize resets scrollbars, if any
318 void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event))
319 {
320 #if wxUSE_CONSTRAINTS
321 if (GetAutoLayout()) Layout();
322 #endif
323
324 AdjustScrollbars();
325 }
326
327 // This calls OnDraw, having adjusted the origin according to the current
328 // scroll position
329 void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
330 {
331 wxPaintDC dc(this);
332 PrepareDC(dc);
333
334 OnDraw(dc);
335 }
336
337 // Override this function if you don't want to have wxScrolledWindow
338 // automatically change the origin according to the scroll position.
339 void wxScrolledWindow::PrepareDC(wxDC& dc)
340 {
341 dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine,
342 -m_yScrollPosition * m_yScrollPixelsPerLine );
343 dc.SetUserScale( m_scaleX, m_scaleY );
344 }
345
346 #if WXWIN_COMPATIBILITY
347 void wxScrolledWindow::GetScrollUnitsPerPage (int *x_page, int *y_page) const
348 {
349 *x_page = GetScrollPageSize(wxHORIZONTAL);
350 *y_page = GetScrollPageSize(wxVERTICAL);
351 }
352 #endif
353
354 void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
355 {
356 *x_unit = m_xScrollPixelsPerLine;
357 *y_unit = m_yScrollPixelsPerLine;
358 }
359
360 int wxScrolledWindow::GetScrollPageSize(int orient) const
361 {
362 if ( orient == wxHORIZONTAL )
363 return m_xScrollLinesPerPage;
364 else
365 return m_yScrollLinesPerPage;
366 }
367
368 void wxScrolledWindow::SetScrollPageSize(int orient, int pageSize)
369 {
370 if ( orient == wxHORIZONTAL )
371 m_xScrollLinesPerPage = pageSize;
372 else
373 m_yScrollLinesPerPage = pageSize;
374 }
375
376 /*
377 * Scroll to given position (scroll position, not pixel position)
378 */
379 void wxScrolledWindow::Scroll( int x_pos, int y_pos )
380 {
381 if (((x_pos == -1) || (x_pos == m_xScrollPosition)) &&
382 ((y_pos == -1) || (y_pos == m_yScrollPosition))) return;
383
384 int w, h;
385 GetClientSize(&w, &h);
386
387 if (x_pos != -1)
388 {
389 m_xScrollPosition = x_pos;
390
391 // Calculate page size i.e. number of scroll units you get on the
392 // current client window
393 int noPagePositions = (int) ( (w/(float)m_xScrollPixelsPerLine) + 0.5 );
394 if (noPagePositions < 1) noPagePositions = 1;
395
396 // Correct position if greater than extent of canvas minus
397 // the visible portion of it or if below zero
398 m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition );
399 m_xScrollPosition = wxMax( 0, m_xScrollPosition );
400
401 SetScrollPos( wxHORIZONTAL, m_xScrollPosition, TRUE );
402 }
403 if (y_pos != -1)
404 {
405 m_yScrollPosition = y_pos;
406
407 // Calculate page size i.e. number of scroll units you get on the
408 // current client window
409 int noPagePositions = (int) ( (h/(float)m_yScrollPixelsPerLine) + 0.5 );
410 if (noPagePositions < 1) noPagePositions = 1;
411
412 // Correct position if greater than extent of canvas minus
413 // the visible portion of it or if below zero
414 m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition );
415 m_yScrollPosition = wxMax( 0, m_yScrollPosition );
416
417 SetScrollPos( wxVERTICAL, m_yScrollPosition, TRUE );
418 }
419
420 Refresh();
421
422 #ifdef __WXMSW__
423 ::UpdateWindow ((HWND) GetHWND());
424 #endif
425 }
426
427 void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll)
428 {
429 m_xScrollingEnabled = x_scroll;
430 m_yScrollingEnabled = y_scroll;
431 }
432
433 void wxScrolledWindow::GetVirtualSize (int *x, int *y) const
434 {
435 *x = m_xScrollPixelsPerLine * m_xScrollLines;
436 *y = m_yScrollPixelsPerLine * m_yScrollLines;
437 }
438
439 // Where the current view starts from
440 void wxScrolledWindow::ViewStart (int *x, int *y) const
441 {
442 *x = m_xScrollPosition;
443 *y = m_yScrollPosition;
444 }
445
446 void wxScrolledWindow::CalcScrolledPosition(int x, int y, int *xx, int *yy) const
447 {
448 *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine;
449 *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine;
450 }
451
452 void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const
453 {
454 *xx = (float)(x + m_xScrollPosition * m_xScrollPixelsPerLine);
455 *yy = (float)(y + m_yScrollPosition * m_yScrollPixelsPerLine);
456 }
457
458