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"
27 #include "wx/generic/scrolwin.h"
30 #if !USE_SHARED_LIBRARY
31 BEGIN_EVENT_TABLE(wxScrolledWindow
, wxPanel
)
32 EVT_SCROLLWIN(wxScrolledWindow::OnScroll
)
33 EVT_SIZE(wxScrolledWindow::OnSize
)
34 EVT_PAINT(wxScrolledWindow::OnPaint
)
37 IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow
, wxPanel
)
45 // For wxRETAINED implementation
46 #ifdef __VMS__ //VMS's Xm.h is not (yet) compatible with C++
47 //This code switches off the compiler warnings
48 # pragma message disable nosimpint
52 # pragma message enable nosimpint
56 wxScrolledWindow::wxScrolledWindow()
58 m_xScrollPixelsPerLine
= 0;
59 m_yScrollPixelsPerLine
= 0;
60 m_xScrollingEnabled
= TRUE
;
61 m_yScrollingEnabled
= TRUE
;
62 m_xScrollPosition
= 0;
63 m_yScrollPosition
= 0;
66 m_xScrollLinesPerPage
= 0;
67 m_yScrollLinesPerPage
= 0;
72 bool wxScrolledWindow::Create(wxWindow
*parent
, wxWindowID id
,
78 m_xScrollPixelsPerLine
= 0;
79 m_yScrollPixelsPerLine
= 0;
80 m_xScrollingEnabled
= TRUE
;
81 m_yScrollingEnabled
= TRUE
;
82 m_xScrollPosition
= 0;
83 m_yScrollPosition
= 0;
86 m_xScrollLinesPerPage
= 0;
87 m_yScrollLinesPerPage
= 0;
91 m_targetWindow
= this;
93 return wxPanel::Create(parent
, id
, pos
, size
, style
, name
);
97 * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line)
98 * noUnitsX/noUnitsY: : no. units per scrollbar
100 void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX
, int pixelsPerUnitY
,
101 int noUnitsX
, int noUnitsY
,
102 int xPos
, int yPos
, bool noRefresh
)
106 (noUnitsX
!= 0 && m_xScrollLines
== 0) ||
107 (noUnitsX
< m_xScrollLines
) ||
108 (noUnitsY
!= 0 && m_yScrollLines
== 0) ||
109 (noUnitsY
< m_yScrollLines
) ||
110 (xPos
!= m_xScrollPosition
) ||
111 (yPos
!= m_yScrollPosition
) ||
112 (pixelsPerUnitX
!= m_xScrollPixelsPerLine
) ||
113 (pixelsPerUnitY
!= m_yScrollPixelsPerLine
)
116 m_xScrollPixelsPerLine
= pixelsPerUnitX
;
117 m_yScrollPixelsPerLine
= pixelsPerUnitY
;
118 m_xScrollPosition
= xPos
;
119 m_yScrollPosition
= yPos
;
120 m_xScrollLines
= noUnitsX
;
121 m_yScrollLines
= noUnitsY
;
124 // Sorry, some Motif-specific code to implement a backing pixmap
125 // for the wxRETAINED style. Implementing a backing store can't
126 // be entirely generic because it relies on the wxWindowDC implementation
127 // to duplicate X drawing calls for the backing pixmap.
129 if ((m_windowStyle
& wxRETAINED
) == wxRETAINED
)
131 Display
* dpy
= XtDisplay((Widget
) GetMainWidget());
133 int totalPixelWidth
= m_xScrollLines
* m_xScrollPixelsPerLine
;
134 int totalPixelHeight
= m_yScrollLines
* m_yScrollPixelsPerLine
;
135 if (m_backingPixmap
&&
136 !((m_pixmapWidth
== totalPixelWidth
) &&
137 (m_pixmapHeight
== totalPixelHeight
)))
139 XFreePixmap (dpy
, (Pixmap
) m_backingPixmap
);
140 m_backingPixmap
= (WXPixmap
) 0;
143 if (!m_backingPixmap
&&
144 (noUnitsX
!= 0) && (noUnitsY
!= 0))
146 int depth
= wxDisplayDepth();
147 m_pixmapWidth
= totalPixelWidth
;
148 m_pixmapHeight
= totalPixelHeight
;
149 m_backingPixmap
= (WXPixmap
) XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
150 m_pixmapWidth
, m_pixmapHeight
, depth
);
158 if (do_refresh
&& !noRefresh
)
159 m_targetWindow
->Refresh();
163 UpdateWindow ((HWND
) m_targetWindow
->GetHWND());
166 m_targetWindow
->MacUpdateImmediately() ;
170 wxScrolledWindow::~wxScrolledWindow()
174 void wxScrolledWindow::SetTargetWindow( wxWindow
*target
)
176 wxASSERT_MSG( target
, wxT("target window must not be NULL") );
177 m_targetWindow
= target
;
180 wxWindow
*wxScrolledWindow::GetTargetWindow()
182 return m_targetWindow
;
185 void wxScrolledWindow::OnScroll(wxScrollWinEvent
& event
)
187 int orient
= event
.GetOrientation();
189 int nScrollInc
= CalcScrollInc(event
);
190 if (nScrollInc
== 0) return;
192 if (orient
== wxHORIZONTAL
)
194 int newPos
= m_xScrollPosition
+ nScrollInc
;
195 SetScrollPos(wxHORIZONTAL
, newPos
, TRUE
);
199 int newPos
= m_yScrollPosition
+ nScrollInc
;
200 SetScrollPos(wxVERTICAL
, newPos
, TRUE
);
203 if (orient
== wxHORIZONTAL
)
205 m_xScrollPosition
+= nScrollInc
;
209 m_yScrollPosition
+= nScrollInc
;
212 if (orient
== wxHORIZONTAL
)
214 if (m_xScrollingEnabled
)
215 m_targetWindow
->ScrollWindow(-m_xScrollPixelsPerLine
* nScrollInc
, 0, (const wxRect
*) NULL
);
217 m_targetWindow
->Refresh();
221 if (m_yScrollingEnabled
)
222 m_targetWindow
->ScrollWindow(0, -m_yScrollPixelsPerLine
* nScrollInc
, (const wxRect
*) NULL
);
224 m_targetWindow
->Refresh();
227 m_targetWindow
->MacUpdateImmediately() ;
231 int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent
& event
)
233 int pos
= event
.GetPosition();
234 int orient
= event
.GetOrientation();
237 switch (event
.GetEventType())
239 case wxEVT_SCROLLWIN_TOP
:
241 if (orient
== wxHORIZONTAL
)
242 nScrollInc
= - m_xScrollPosition
;
244 nScrollInc
= - m_yScrollPosition
;
247 case wxEVT_SCROLLWIN_BOTTOM
:
249 if (orient
== wxHORIZONTAL
)
250 nScrollInc
= m_xScrollLines
- m_xScrollPosition
;
252 nScrollInc
= m_yScrollLines
- m_yScrollPosition
;
255 case wxEVT_SCROLLWIN_LINEUP
:
260 case wxEVT_SCROLLWIN_LINEDOWN
:
265 case wxEVT_SCROLLWIN_PAGEUP
:
267 if (orient
== wxHORIZONTAL
)
268 nScrollInc
= -GetScrollPageSize(wxHORIZONTAL
);
270 nScrollInc
= -GetScrollPageSize(wxVERTICAL
);
273 case wxEVT_SCROLLWIN_PAGEDOWN
:
275 if (orient
== wxHORIZONTAL
)
276 nScrollInc
= GetScrollPageSize(wxHORIZONTAL
);
278 nScrollInc
= GetScrollPageSize(wxVERTICAL
);
281 case wxEVT_SCROLLWIN_THUMBTRACK
:
283 if (orient
== wxHORIZONTAL
)
284 nScrollInc
= pos
- m_xScrollPosition
;
286 nScrollInc
= pos
- m_yScrollPosition
;
295 if (orient
== wxHORIZONTAL
)
297 if (m_xScrollPixelsPerLine
> 0)
300 m_targetWindow
->GetClientSize(&w
, &h
);
302 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
303 int noPositions
= (int) ( ((nMaxWidth
- w
)/(double)m_xScrollPixelsPerLine
) + 0.5 );
307 if ( (m_xScrollPosition
+ nScrollInc
) < 0 )
308 nScrollInc
= -m_xScrollPosition
; // As -ve as we can go
309 else if ( (m_xScrollPosition
+ nScrollInc
) > noPositions
)
310 nScrollInc
= noPositions
- m_xScrollPosition
; // As +ve as we can go
313 m_targetWindow
->Refresh();
317 if (m_yScrollPixelsPerLine
> 0)
320 m_targetWindow
->GetClientSize(&w
, &h
);
322 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
323 int noPositions
= (int) ( ((nMaxHeight
- h
)/(double)m_yScrollPixelsPerLine
) + 0.5 );
327 if ( (m_yScrollPosition
+ nScrollInc
) < 0 )
328 nScrollInc
= -m_yScrollPosition
; // As -ve as we can go
329 else if ( (m_yScrollPosition
+ nScrollInc
) > noPositions
)
330 nScrollInc
= noPositions
- m_yScrollPosition
; // As +ve as we can go
333 m_targetWindow
->Refresh();
339 // Adjust the scrollbars - new version.
340 void wxScrolledWindow::AdjustScrollbars()
343 m_targetWindow
->GetClientSize(&w
, &h
);
345 int oldXScroll
= m_xScrollPosition
;
346 int oldYScroll
= m_yScrollPosition
;
348 if (m_xScrollLines
> 0)
350 // Calculate page size i.e. number of scroll units you get on the
351 // current client window
352 int noPagePositions
= (int) ( (w
/(double)m_xScrollPixelsPerLine
) + 0.5 );
353 if (noPagePositions
< 1) noPagePositions
= 1;
355 // Correct position if greater than extent of canvas minus
356 // the visible portion of it or if below zero
357 m_xScrollPosition
= wxMin( m_xScrollLines
-noPagePositions
, m_xScrollPosition
);
358 m_xScrollPosition
= wxMax( 0, m_xScrollPosition
);
360 SetScrollbar(wxHORIZONTAL
, m_xScrollPosition
, noPagePositions
, m_xScrollLines
);
361 // The amount by which we scroll when paging
362 SetScrollPageSize(wxHORIZONTAL
, noPagePositions
);
366 m_xScrollPosition
= 0;
367 SetScrollbar (wxHORIZONTAL
, 0, 0, 0, FALSE
);
370 if (m_yScrollLines
> 0)
372 // Calculate page size i.e. number of scroll units you get on the
373 // current client window
374 int noPagePositions
= (int) ( (h
/(double)m_yScrollPixelsPerLine
) + 0.5 );
375 if (noPagePositions
< 1) noPagePositions
= 1;
377 // Correct position if greater than extent of canvas minus
378 // the visible portion of it or if below zero
379 m_yScrollPosition
= wxMin( m_yScrollLines
-noPagePositions
, m_yScrollPosition
);
380 m_yScrollPosition
= wxMax( 0, m_yScrollPosition
);
382 SetScrollbar(wxVERTICAL
, m_yScrollPosition
, noPagePositions
, m_yScrollLines
);
383 // The amount by which we scroll when paging
384 SetScrollPageSize(wxVERTICAL
, noPagePositions
);
388 m_yScrollPosition
= 0;
389 SetScrollbar (wxVERTICAL
, 0, 0, 0, FALSE
);
392 if (oldXScroll
!= m_xScrollPosition
)
394 if (m_xScrollingEnabled
)
395 m_targetWindow
->ScrollWindow( m_xScrollPixelsPerLine
* (oldXScroll
-m_xScrollPosition
), 0, (const wxRect
*) NULL
);
397 m_targetWindow
->Refresh();
400 if (oldYScroll
!= m_yScrollPosition
)
402 if (m_yScrollingEnabled
)
403 m_targetWindow
->ScrollWindow( 0, m_yScrollPixelsPerLine
* (oldYScroll
-m_yScrollPosition
), (const wxRect
*) NULL
);
405 m_targetWindow
->Refresh();
409 // Default OnSize resets scrollbars, if any
410 void wxScrolledWindow::OnSize(wxSizeEvent
& WXUNUSED(event
))
412 #if wxUSE_CONSTRAINTS
413 if (GetAutoLayout()) Layout();
419 // This calls OnDraw, having adjusted the origin according to the current
421 void wxScrolledWindow::OnPaint(wxPaintEvent
& WXUNUSED(event
))
429 // Override this function if you don't want to have wxScrolledWindow
430 // automatically change the origin according to the scroll position.
431 void wxScrolledWindow::PrepareDC(wxDC
& dc
)
433 dc
.SetDeviceOrigin( -m_xScrollPosition
* m_xScrollPixelsPerLine
,
434 -m_yScrollPosition
* m_yScrollPixelsPerLine
);
435 dc
.SetUserScale( m_scaleX
, m_scaleY
);
438 #if WXWIN_COMPATIBILITY
439 void wxScrolledWindow::GetScrollUnitsPerPage (int *x_page
, int *y_page
) const
441 *x_page
= GetScrollPageSize(wxHORIZONTAL
);
442 *y_page
= GetScrollPageSize(wxVERTICAL
);
445 void wxScrolledWindow::CalcUnscrolledPosition(int x
, int y
, float *xx
, float *yy
) const
448 *xx
= (float)(x
+ m_xScrollPosition
* m_xScrollPixelsPerLine
);
450 *yy
= (float)(y
+ m_yScrollPosition
* m_yScrollPixelsPerLine
);
452 #endif // WXWIN_COMPATIBILITY
454 void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const
457 *x_unit
= m_xScrollPixelsPerLine
;
459 *y_unit
= m_yScrollPixelsPerLine
;
462 int wxScrolledWindow::GetScrollPageSize(int orient
) const
464 if ( orient
== wxHORIZONTAL
)
465 return m_xScrollLinesPerPage
;
467 return m_yScrollLinesPerPage
;
470 void wxScrolledWindow::SetScrollPageSize(int orient
, int pageSize
)
472 if ( orient
== wxHORIZONTAL
)
473 m_xScrollLinesPerPage
= pageSize
;
475 m_yScrollLinesPerPage
= pageSize
;
479 * Scroll to given position (scroll position, not pixel position)
481 void wxScrolledWindow::Scroll( int x_pos
, int y_pos
)
483 if (((x_pos
== -1) || (x_pos
== m_xScrollPosition
)) &&
484 ((y_pos
== -1) || (y_pos
== m_yScrollPosition
))) return;
487 m_targetWindow
->GetClientSize(&w
, &h
);
491 int old_x
= m_xScrollPosition
;
492 m_xScrollPosition
= x_pos
;
494 // Calculate page size i.e. number of scroll units you get on the
495 // current client window
496 int noPagePositions
= (int) ( (w
/(double)m_xScrollPixelsPerLine
) + 0.5 );
497 if (noPagePositions
< 1) noPagePositions
= 1;
499 // Correct position if greater than extent of canvas minus
500 // the visible portion of it or if below zero
501 m_xScrollPosition
= wxMin( m_xScrollLines
-noPagePositions
, m_xScrollPosition
);
502 m_xScrollPosition
= wxMax( 0, m_xScrollPosition
);
504 m_targetWindow
->SetScrollPos( wxHORIZONTAL
, m_xScrollPosition
, TRUE
);
506 m_targetWindow
->ScrollWindow( (old_x
-m_xScrollPosition
)*m_xScrollPixelsPerLine
, 0 );
510 int old_y
= m_yScrollPosition
;
511 m_yScrollPosition
= y_pos
;
513 // Calculate page size i.e. number of scroll units you get on the
514 // current client window
515 int noPagePositions
= (int) ( (h
/(double)m_yScrollPixelsPerLine
) + 0.5 );
516 if (noPagePositions
< 1) noPagePositions
= 1;
518 // Correct position if greater than extent of canvas minus
519 // the visible portion of it or if below zero
520 m_yScrollPosition
= wxMin( m_yScrollLines
-noPagePositions
, m_yScrollPosition
);
521 m_yScrollPosition
= wxMax( 0, m_yScrollPosition
);
523 m_targetWindow
->SetScrollPos( wxVERTICAL
, m_yScrollPosition
, TRUE
);
525 m_targetWindow
->ScrollWindow( 0, (old_y
-m_yScrollPosition
)*m_yScrollPixelsPerLine
);
530 // ::UpdateWindow ((HWND) GetHWND());
535 m_targetWindow
->MacUpdateImmediately() ;
539 void wxScrolledWindow::EnableScrolling (bool x_scroll
, bool y_scroll
)
541 m_xScrollingEnabled
= x_scroll
;
542 m_yScrollingEnabled
= y_scroll
;
545 void wxScrolledWindow::GetVirtualSize (int *x
, int *y
) const
548 *x
= m_xScrollPixelsPerLine
* m_xScrollLines
;
550 *y
= m_yScrollPixelsPerLine
* m_yScrollLines
;
553 // Where the current view starts from
554 void wxScrolledWindow::ViewStart (int *x
, int *y
) const
557 *x
= m_xScrollPosition
;
559 *y
= m_yScrollPosition
;
562 void wxScrolledWindow::CalcScrolledPosition(int x
, int y
, int *xx
, int *yy
) const
565 *xx
= x
- m_xScrollPosition
* m_xScrollPixelsPerLine
;
567 *yy
= y
- m_yScrollPosition
* m_yScrollPixelsPerLine
;
570 void wxScrolledWindow::CalcUnscrolledPosition(int x
, int y
, int *xx
, int *yy
) const
573 *xx
= x
+ m_xScrollPosition
* m_xScrollPixelsPerLine
;
575 *yy
= y
+ m_yScrollPosition
* m_yScrollPixelsPerLine
;