1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxScrolledWindow implementation
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation
14 #pragma implementation "scrolwin.h"
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
21 #include "wx/dcclient.h"
31 #include "wx/generic/scrolwin.h"
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
)
40 IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow
, wxWindow
)
43 wxScrolledWindow::wxScrolledWindow(void)
45 m_xScrollPixelsPerLine
= 0;
46 m_yScrollPixelsPerLine
= 0;
47 m_xScrollingEnabled
= TRUE
;
48 m_yScrollingEnabled
= TRUE
;
49 m_xScrollPosition
= 0;
50 m_yScrollPosition
= 0;
53 m_xScrollLinesPerPage
= 0;
54 m_yScrollLinesPerPage
= 0;
57 bool wxScrolledWindow::Create(wxWindow
*parent
, const wxWindowID id
,
63 m_xScrollPixelsPerLine
= 0;
64 m_yScrollPixelsPerLine
= 0;
65 m_xScrollingEnabled
= TRUE
;
66 m_yScrollingEnabled
= TRUE
;
67 m_xScrollPosition
= 0;
68 m_yScrollPosition
= 0;
71 m_xScrollLinesPerPage
= 0;
72 m_yScrollLinesPerPage
= 0;
74 return wxWindow::Create(parent
, id
, pos
, size
, style
, name
);
78 * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line)
79 * noUnitsX/noUnitsY: : no. units per scrollbar
81 void wxScrolledWindow::SetScrollbars (const int pixelsPerUnitX
, const int pixelsPerUnitY
,
82 const int noUnitsX
, const int noUnitsY
,
83 const int xPos
, const int yPos
, const bool noRefresh
)
87 (noUnitsX
!= 0 && m_xScrollLines
== 0) ||
88 (noUnitsX
< m_xScrollPosition
) ||
89 (noUnitsY
!= 0 && m_yScrollLines
== 0) ||
90 (noUnitsY
< m_yScrollPosition
) ||
91 (xPos
!= m_xScrollPosition
) ||
92 (yPos
!= m_yScrollPosition
) ||
93 (pixelsPerUnitX
!= m_xScrollPixelsPerLine
) ||
94 (pixelsPerUnitY
!= m_yScrollPixelsPerLine
)
97 m_xScrollPixelsPerLine
= pixelsPerUnitX
;
98 m_yScrollPixelsPerLine
= pixelsPerUnitY
;
99 m_xScrollLines
= noUnitsX
;
100 m_yScrollLines
= noUnitsY
;
104 if (do_refresh
&& !noRefresh
) Refresh();
107 UpdateWindow ((HWND
) GetHWND());
111 void wxScrolledWindow::OnScroll(wxScrollEvent
& event
)
113 int orient
= event
.GetOrientation();
115 int nScrollInc
= CalcScrollInc(event
);
119 // TODO: should we store the scroll position here as well as in wxWindow?
120 if (orient
== wxHORIZONTAL
)
122 int newPos
= m_xScrollPosition
+ nScrollInc
;
123 SetScrollPos(wxHORIZONTAL
, newPos
, TRUE
);
127 int newPos
= m_yScrollPosition
+ nScrollInc
;
128 SetScrollPos(wxVERTICAL
, newPos
, TRUE
);
132 // TODO We need to multiply the ScrollWindow amount by the scaling
133 // factor, but how do we know what this is in wxWin 2.0???
137 if ( this->IsKindOf(CLASSINFO(wxCanvas)) )
139 wxDC* dc = ((wxCanvas *)this)->GetDC();
140 dc->GetUserScale(&scaleX, &scaleY);
144 if (orient
== wxHORIZONTAL
)
146 m_xScrollPosition
+= nScrollInc
;
150 m_yScrollPosition
+= nScrollInc
;
153 if (orient
== wxHORIZONTAL
)
155 if (m_xScrollingEnabled
)
156 ScrollWindow(-m_xScrollPixelsPerLine
* nScrollInc
, 0, NULL
);
162 if (m_yScrollingEnabled
)
163 ScrollWindow(0, -m_yScrollPixelsPerLine
* nScrollInc
, NULL
);
170 int wxScrolledWindow::CalcScrollInc(wxScrollEvent
& event
)
172 int pos
= event
.GetPosition();
173 int orient
= event
.GetOrientation();
176 switch (event
.GetEventType())
178 case wxEVENT_TYPE_SCROLL_TOP
:
180 if (orient
== wxHORIZONTAL
)
181 nScrollInc
= - m_xScrollPosition
;
183 nScrollInc
= - m_yScrollPosition
;
186 case wxEVENT_TYPE_SCROLL_BOTTOM
:
188 if (orient
== wxHORIZONTAL
)
189 nScrollInc
= m_xScrollLines
- m_xScrollPosition
;
191 nScrollInc
= m_yScrollLines
- m_yScrollPosition
;
194 case wxEVENT_TYPE_SCROLL_LINEUP
:
199 case wxEVENT_TYPE_SCROLL_LINEDOWN
:
204 case wxEVENT_TYPE_SCROLL_PAGEUP
:
206 if (orient
== wxHORIZONTAL
)
207 nScrollInc
= -GetScrollPageSize(wxHORIZONTAL
);
209 nScrollInc
= -GetScrollPageSize(wxVERTICAL
);
212 case wxEVENT_TYPE_SCROLL_PAGEDOWN
:
214 if (orient
== wxHORIZONTAL
)
215 nScrollInc
= GetScrollPageSize(wxHORIZONTAL
);
217 nScrollInc
= GetScrollPageSize(wxVERTICAL
);
220 case wxEVENT_TYPE_SCROLL_THUMBTRACK
:
222 if (orient
== wxHORIZONTAL
)
223 nScrollInc
= pos
- m_xScrollPosition
;
225 nScrollInc
= pos
- m_yScrollPosition
;
233 if (orient
== wxHORIZONTAL
)
236 GetClientSize(&w
, &h
);
238 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
239 int noPositions
= (int) ( ((nMaxWidth
- w
)/(float)m_xScrollPixelsPerLine
) + 0.5 );
243 if ( (m_xScrollPosition
+ nScrollInc
) < 0 )
244 nScrollInc
= -m_xScrollPosition
; // As -ve as we can go
245 else if ( (m_xScrollPosition
+ nScrollInc
) > noPositions
)
246 nScrollInc
= noPositions
- m_xScrollPosition
; // As +ve as we can go
253 GetClientSize(&w
, &h
);
255 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
256 int noPositions
= (int) ( ((nMaxHeight
- h
)/(float)m_yScrollPixelsPerLine
) + 0.5 );
260 if ( (m_yScrollPosition
+ nScrollInc
) < 0 )
261 nScrollInc
= -m_yScrollPosition
; // As -ve as we can go
262 else if ( (m_yScrollPosition
+ nScrollInc
) > noPositions
)
263 nScrollInc
= noPositions
- m_yScrollPosition
; // As +ve as we can go
269 // Adjust the scrollbars - new version.
270 void wxScrolledWindow::AdjustScrollbars(void)
273 GetClientSize(&w
, &h
);
275 // Recalculate scroll bar range and position
276 if (m_xScrollLines
> 0)
278 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
279 int newRange
= (int) ( ((nMaxWidth
)/(float)m_xScrollPixelsPerLine
) + 0.5 );
283 m_xScrollPosition
= wxMin(newRange
, m_xScrollPosition
);
285 // Calculate page size i.e. number of scroll units you get on the
286 // current client window
287 int noPagePositions
= (int) ( (w
/(float)m_xScrollPixelsPerLine
) + 0.5 );
288 if (noPagePositions
< 1)
291 SetScrollbar(wxHORIZONTAL
, m_xScrollPosition
, noPagePositions
, newRange
);
292 SetScrollPageSize(wxHORIZONTAL
, noPagePositions
);
297 m_xScrollPosition
= 0;
298 SetScrollbar (wxHORIZONTAL
, 0, 0, 0, FALSE
);
301 if (m_yScrollLines
> 0)
303 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
304 int newRange
= (int) ( ((nMaxHeight
)/(float)m_yScrollPixelsPerLine
) + 0.5 );
308 m_yScrollPosition
= wxMin(newRange
, m_yScrollPosition
);
310 // Calculate page size i.e. number of scroll units you get on the
311 // current client window
312 int noPagePositions
= (int) ( (h
/(float)m_yScrollPixelsPerLine
) + 0.5 );
313 if (noPagePositions
< 1)
316 SetScrollbar(wxVERTICAL
, m_yScrollPosition
, noPagePositions
, newRange
);
317 SetScrollPageSize(wxVERTICAL
, noPagePositions
);
321 m_yScrollPosition
= 0;
322 SetScrollbar (wxVERTICAL
, 0, 0, 0, FALSE
); // Robert Roebling
327 // Default OnSize resets scrollbars, if any
328 void wxScrolledWindow::OnSize(wxSizeEvent
& WXUNUSED(event
))
338 // This calls OnDraw, having adjusted the origin according to the current
340 void wxScrolledWindow::OnPaint(wxPaintEvent
& WXUNUSED(event
))
348 // Override this function if you don't want to have wxScrolledWindow
349 // automatically change the origin according to the scroll position.
350 void wxScrolledWindow::PrepareDC(wxDC
& dc
)
352 dc
.SetDeviceOrigin(- m_xScrollPosition
* m_xScrollPixelsPerLine
, - m_yScrollPosition
* m_yScrollPixelsPerLine
);
355 #if WXWIN_COMPATIBILITY
356 void wxScrolledWindow::GetScrollUnitsPerPage (int *x_page
, int *y_page
) const
358 *x_page
= GetScrollPageSize(wxHORIZONTAL
);
359 *y_page
= GetScrollPageSize(wxVERTICAL
);
363 void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const
365 *x_unit
= m_xScrollPixelsPerLine
;
366 *y_unit
= m_yScrollPixelsPerLine
;
369 int wxScrolledWindow::GetScrollPageSize(int orient
) const
371 if ( orient
== wxHORIZONTAL
)
372 return m_xScrollLinesPerPage
;
374 return m_yScrollLinesPerPage
;
377 void wxScrolledWindow::SetScrollPageSize(int orient
, int pageSize
)
379 if ( orient
== wxHORIZONTAL
)
380 m_xScrollLinesPerPage
= pageSize
;
382 m_yScrollLinesPerPage
= pageSize
;
386 * Scroll to given position (scroll position, not pixel position)
388 void wxScrolledWindow::Scroll (const int x_pos
, const int y_pos
)
391 ViewStart (&old_x
, &old_y
);
392 if (((x_pos
== -1) || (x_pos
== old_x
)) && ((y_pos
== -1) || (y_pos
== old_y
)))
397 m_xScrollPosition
= x_pos
;
398 SetScrollPos (wxHORIZONTAL
, x_pos
, TRUE
);
402 m_yScrollPosition
= y_pos
;
403 SetScrollPos (wxVERTICAL
, y_pos
, TRUE
);
407 ::UpdateWindow ((HWND
) GetHWND());
411 void wxScrolledWindow::EnableScrolling (const bool x_scroll
, const bool y_scroll
)
413 m_xScrollingEnabled
= x_scroll
;
414 m_yScrollingEnabled
= y_scroll
;
417 void wxScrolledWindow::GetVirtualSize (int *x
, int *y
) const
419 *x
= m_xScrollPixelsPerLine
* m_xScrollLines
;
420 *y
= m_yScrollPixelsPerLine
* m_yScrollLines
;
423 // Where the current view starts from
424 void wxScrolledWindow::ViewStart (int *x
, int *y
) const
426 *x
= m_xScrollPosition
;
427 *y
= m_yScrollPosition
;
430 void wxScrolledWindow::CalcScrolledPosition(const int x
, const int y
, int *xx
, int *yy
) const
432 *xx
= x
- m_xScrollPosition
* m_xScrollPixelsPerLine
;
433 *yy
= y
- m_yScrollPosition
* m_yScrollPixelsPerLine
;
436 void wxScrolledWindow::CalcUnscrolledPosition(const int x
, const int y
, float *xx
, float *yy
) const
438 *xx
= (float)(x
+ m_xScrollPosition
* m_xScrollPixelsPerLine
);
439 *yy
= (float)(y
+ m_yScrollPosition
* m_yScrollPixelsPerLine
);