add convenient GetViewStart() and Scroll() overloads taking wxPoint instead of 2...
[wxWidgets.git] / include / wx / scrolwin.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: include/wx/scrolwin.h
3 // Purpose: wxScrolledWindow, wxScrolledControl and wxScrollHelper
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 30.08.00
7 // RCS-ID: $Id$
8 // Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_SCROLWIN_H_BASE_
13 #define _WX_SCROLWIN_H_BASE_
14
15 #include "wx/panel.h"
16
17 class WXDLLIMPEXP_FWD_CORE wxScrollHelperEvtHandler;
18 class WXDLLIMPEXP_FWD_BASE wxTimer;
19
20 // default scrolled window style: scroll in both directions
21 #define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL)
22
23 // ----------------------------------------------------------------------------
24 // The hierarchy of scrolling classes is a bit complicated because we want to
25 // put as much functionality as possible in a mix-in class not deriving from
26 // wxWindow so that other classes could derive from the same base class on all
27 // platforms irrespectively of whether they are native controls (and hence
28 // don't use our scrolling) or not.
29 //
30 // So we have
31 //
32 // wxScrollHelper
33 // |
34 // |
35 // \|/
36 // wxWindow wxScrollHelperNative
37 // | \ / /
38 // | \ / /
39 // | _| |_ /
40 // | wxScrolledWindow /
41 // | /
42 // \|/ /
43 // wxControl /
44 // \ /
45 // \ /
46 // _| |_
47 // wxScrolledControl
48 //
49 // ----------------------------------------------------------------------------
50
51 class WXDLLIMPEXP_CORE wxScrollHelper
52 {
53 public:
54 // ctor must be given the associated window
55 wxScrollHelper(wxWindow *winToScroll);
56 virtual ~wxScrollHelper();
57
58 // configure the scrolling
59 virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY,
60 int noUnitsX, int noUnitsY,
61 int xPos = 0, int yPos = 0,
62 bool noRefresh = false );
63
64 // scroll to the given (in logical coords) position
65 void Scroll(int x, int y) { DoScroll(x, y); }
66 void Scroll(const wxPoint& pt) { DoScroll(pt.x, pt.y); }
67
68 // get/set the page size for this orientation (wxVERTICAL/wxHORIZONTAL)
69 int GetScrollPageSize(int orient) const;
70 void SetScrollPageSize(int orient, int pageSize);
71
72 // get the number of lines the window can scroll,
73 // returns 0 if no scrollbars are there.
74 int GetScrollLines( int orient ) const;
75
76 // Set the x, y scrolling increments.
77 void SetScrollRate( int xstep, int ystep );
78
79 // get the size of one logical unit in physical ones
80 virtual void GetScrollPixelsPerUnit(int *pixelsPerUnitX,
81 int *pixelsPerUnitY) const;
82
83 // Enable/disable Windows scrolling in either direction. If true, wxWidgets
84 // scrolls the canvas and only a bit of the canvas is invalidated; no
85 // Clear() is necessary. If false, the whole canvas is invalidated and a
86 // Clear() is necessary. Disable for when the scroll increment is used to
87 // actually scroll a non-constant distance
88 virtual void EnableScrolling(bool x_scrolling, bool y_scrolling);
89
90 // Get the view start
91 void GetViewStart(int *x, int *y) const { DoGetViewStart(x, y); }
92
93 wxPoint GetViewStart() const
94 {
95 wxPoint pt;
96 DoGetViewStart(&pt.x, &pt.y);
97 return pt;
98 }
99
100 // Set the scale factor, used in PrepareDC
101 void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; }
102 double GetScaleX() const { return m_scaleX; }
103 double GetScaleY() const { return m_scaleY; }
104
105 // translate between scrolled and unscrolled coordinates
106 void CalcScrolledPosition(int x, int y, int *xx, int *yy) const
107 { DoCalcScrolledPosition(x, y, xx, yy); }
108 wxPoint CalcScrolledPosition(const wxPoint& pt) const
109 {
110 wxPoint p2;
111 DoCalcScrolledPosition(pt.x, pt.y, &p2.x, &p2.y);
112 return p2;
113 }
114
115 void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const
116 { DoCalcUnscrolledPosition(x, y, xx, yy); }
117 wxPoint CalcUnscrolledPosition(const wxPoint& pt) const
118 {
119 wxPoint p2;
120 DoCalcUnscrolledPosition(pt.x, pt.y, &p2.x, &p2.y);
121 return p2;
122 }
123
124 virtual void DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const;
125 virtual void DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const;
126
127 // Adjust the scrollbars
128 virtual void AdjustScrollbars(void);
129
130 // Calculate scroll increment
131 virtual int CalcScrollInc(wxScrollWinEvent& event);
132
133 // Normally the wxScrolledWindow will scroll itself, but in some rare
134 // occasions you might want it to scroll [part of] another window (e.g. a
135 // child of it in order to scroll only a portion the area between the
136 // scrollbars (spreadsheet: only cell area will move).
137 virtual void SetTargetWindow(wxWindow *target);
138 virtual wxWindow *GetTargetWindow() const;
139
140 void SetTargetRect(const wxRect& rect) { m_rectToScroll = rect; }
141 wxRect GetTargetRect() const { return m_rectToScroll; }
142
143 // Override this function to draw the graphic (or just process EVT_PAINT)
144 virtual void OnDraw(wxDC& WXUNUSED(dc)) { }
145
146 // change the DC origin according to the scroll position.
147 virtual void DoPrepareDC(wxDC& dc);
148
149 // are we generating the autoscroll events?
150 bool IsAutoScrolling() const { return m_timerAutoScroll != NULL; }
151
152 // stop generating the scroll events when mouse is held outside the window
153 void StopAutoScrolling();
154
155 // this method can be overridden in a derived class to forbid sending the
156 // auto scroll events - note that unlike StopAutoScrolling() it doesn't
157 // stop the timer, so it will be called repeatedly and will typically
158 // return different values depending on the current mouse position
159 //
160 // the base class version just returns true
161 virtual bool SendAutoScrollEvents(wxScrollWinEvent& event) const;
162
163 // the methods to be called from the window event handlers
164 void HandleOnScroll(wxScrollWinEvent& event);
165 void HandleOnSize(wxSizeEvent& event);
166 void HandleOnPaint(wxPaintEvent& event);
167 void HandleOnChar(wxKeyEvent& event);
168 void HandleOnMouseEnter(wxMouseEvent& event);
169 void HandleOnMouseLeave(wxMouseEvent& event);
170 #if wxUSE_MOUSEWHEEL
171 void HandleOnMouseWheel(wxMouseEvent& event);
172 #endif // wxUSE_MOUSEWHEEL
173 void HandleOnChildFocus(wxChildFocusEvent& event);
174
175 // FIXME: this is needed for now for wxPlot compilation, should be removed
176 // once it is fixed!
177 void OnScroll(wxScrollWinEvent& event) { HandleOnScroll(event); }
178
179 protected:
180 // get pointer to our scroll rect if we use it or NULL
181 const wxRect *GetScrollRect() const
182 {
183 return m_rectToScroll.width != 0 ? &m_rectToScroll : NULL;
184 }
185
186 // get the size of the target window
187 wxSize GetTargetSize() const
188 {
189 return m_rectToScroll.width != 0 ? m_rectToScroll.GetSize()
190 : m_targetWindow->GetClientSize();
191 }
192
193 void GetTargetSize(int *w, int *h) const
194 {
195 wxSize size = GetTargetSize();
196 if ( w )
197 *w = size.x;
198 if ( h )
199 *h = size.y;
200 }
201
202 // implementation of public methods with the same name
203 virtual void DoGetViewStart(int *x, int *y) const;
204 virtual void DoScroll(int x, int y);
205
206 // implementations of various wxWindow virtual methods which should be
207 // forwarded to us (this can be done by WX_FORWARD_TO_SCROLL_HELPER())
208 bool ScrollLayout();
209 void ScrollDoSetVirtualSize(int x, int y);
210 wxSize ScrollGetBestVirtualSize() const;
211
212 // change just the target window (unlike SetWindow which changes m_win as
213 // well)
214 void DoSetTargetWindow(wxWindow *target);
215
216 // delete the event handler we installed
217 void DeleteEvtHandler();
218
219 // calls wxScrollHelperEvtHandler::ResetDrawnFlag(), see explanation
220 // in wxScrollHelperEvtHandler::ProcessEvent()
221 void ResetDrawnFlag();
222
223 // helper of AdjustScrollbars(): does the work for the single scrollbar
224 //
225 // notice that the parameters passed by non-const references are modified
226 // by this function
227 void AdjustScrollbar(int orient,
228 int clientSize,
229 int virtSize,
230 int& pixelsPerUnit,
231 int& scrollUnits,
232 int& scrollPosition);
233
234 // this function should be overridden to return the size available for
235 // m_targetWindow inside m_win of the given size
236 //
237 // the default implementation is only good for m_targetWindow == m_win
238 // case, if we're scrolling a subwindow you must override this method
239 virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size)
240 {
241 // returning just size from here is wrong but it was decided that it is
242 // not wrong enough to break the existing code (which doesn't override
243 // this recently added function at all) by adding this assert
244 //
245 // wxASSERT_MSG( m_targetWindow == m_win, "must be overridden" );
246
247 return size;
248 }
249
250
251 double m_scaleX;
252 double m_scaleY;
253
254 wxWindow *m_win,
255 *m_targetWindow;
256
257 wxRect m_rectToScroll;
258
259 wxTimer *m_timerAutoScroll;
260
261 int m_xScrollPixelsPerLine;
262 int m_yScrollPixelsPerLine;
263 int m_xScrollPosition;
264 int m_yScrollPosition;
265 int m_xScrollLines;
266 int m_yScrollLines;
267 int m_xScrollLinesPerPage;
268 int m_yScrollLinesPerPage;
269
270 bool m_xScrollingEnabled;
271 bool m_yScrollingEnabled;
272
273 #if wxUSE_MOUSEWHEEL
274 int m_wheelRotation;
275 #endif // wxUSE_MOUSEWHEEL
276
277 wxScrollHelperEvtHandler *m_handler;
278
279
280 DECLARE_NO_COPY_CLASS(wxScrollHelper)
281 };
282
283 // this macro can be used in a wxScrollHelper-derived class to forward wxWindow
284 // methods to corresponding wxScrollHelper methods
285 #define WX_FORWARD_TO_SCROLL_HELPER() \
286 public: \
287 virtual void PrepareDC(wxDC& dc) { DoPrepareDC(dc); } \
288 virtual bool Layout() { return ScrollLayout(); } \
289 virtual void DoSetVirtualSize(int x, int y) \
290 { ScrollDoSetVirtualSize(x, y); } \
291 virtual wxSize GetBestVirtualSize() const \
292 { return ScrollGetBestVirtualSize(); }
293
294 // include the declaration of wxScrollHelperNative if needed
295 #if defined(__WXGTK20__) && !defined(__WXUNIVERSAL__)
296 #include "wx/gtk/scrolwin.h"
297 #elif defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
298 #include "wx/gtk1/scrolwin.h"
299 #else
300 typedef wxScrollHelper wxScrollHelperNative;
301 #endif
302
303 // ----------------------------------------------------------------------------
304 // wxScrolled<T>: a wxWindow which knows how to scroll
305 // ----------------------------------------------------------------------------
306
307 // helper class for wxScrolled<T> below
308 struct WXDLLIMPEXP_CORE wxScrolledT_Helper
309 {
310 static wxSize FilterBestSize(const wxWindow *win,
311 const wxScrollHelperNative *helper,
312 const wxSize& origBest);
313 #ifdef __WXMSW__
314 static WXLRESULT FilterMSWWindowProc(WXUINT nMsg, WXLRESULT origResult);
315 #endif
316 };
317
318 // Scrollable window base on window type T. This used to be wxScrolledWindow,
319 // but wxScrolledWindow includes wxControlContainer functionality and that's
320 // not always desirable.
321 template<class T>
322 class WXDLLIMPEXP_CORE wxScrolled : public T,
323 public wxScrollHelperNative,
324 private wxScrolledT_Helper
325 {
326 public:
327 wxScrolled() : wxScrollHelperNative(this) { }
328 wxScrolled(wxWindow *parent,
329 wxWindowID winid = wxID_ANY,
330 const wxPoint& pos = wxDefaultPosition,
331 const wxSize& size = wxDefaultSize,
332 long style = wxScrolledWindowStyle,
333 const wxString& name = wxPanelNameStr)
334 : wxScrollHelperNative(this)
335 {
336 Create(parent, winid, pos, size, style, name);
337 }
338
339 bool Create(wxWindow *parent,
340 wxWindowID winid,
341 const wxPoint& pos = wxDefaultPosition,
342 const wxSize& size = wxDefaultSize,
343 long style = wxScrolledWindowStyle,
344 const wxString& name = wxPanelNameStr)
345 {
346 m_targetWindow = this;
347
348 #ifdef __WXMAC__
349 this->MacSetClipChildren(true);
350 #endif
351
352 this->Connect(wxEVT_PAINT, wxPaintEventHandler(wxScrolled::OnPaint));
353
354 // by default, we're scrollable in both directions (but if one of the
355 // styles is specified explicitly, we shouldn't add the other one
356 // automatically)
357 if ( !(style & (wxHSCROLL | wxVSCROLL)) )
358 style |= wxHSCROLL | wxVSCROLL;
359
360 return T::Create(parent, winid, pos, size, style, name);
361 }
362
363 // we need to return a special WM_GETDLGCODE value to process just the
364 // arrows but let the other navigation characters through
365 #ifdef __WXMSW__
366 virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
367 {
368 return FilterMSWWindowProc(nMsg, T::MSWWindowProc(nMsg, wParam, lParam));
369 }
370 #endif // __WXMSW__
371
372 WX_FORWARD_TO_SCROLL_HELPER()
373
374 protected:
375 virtual wxSize DoGetBestSize() const
376 {
377 return FilterBestSize(this, this, T::DoGetBestSize());
378 }
379
380 private:
381 // this is needed for wxEVT_PAINT processing hack described in
382 // wxScrollHelperEvtHandler::ProcessEvent()
383 void OnPaint(wxPaintEvent& event)
384 {
385 // the user code didn't really draw the window if we got here, so set
386 // this flag to try to call OnDraw() later
387 ResetDrawnFlag();
388 event.Skip();
389 }
390
391 // VC++ 6 gives warning for the declaration of template member function
392 // without definition
393 #if !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7)
394 DECLARE_NO_COPY_CLASS(wxScrolled)
395 #endif
396 };
397
398 // VC++ <= 6 requires this; it's unlikely any other specializations would
399 // be needed by user code _and_ they were using VC6, so we list only wxWindow
400 // (typical use) and wxPanel (wxScrolledWindow use) specializations here
401 WXDLLIMPEXP_TEMPLATE_INSTANCE_CORE( wxScrolled<wxPanel> )
402 WXDLLIMPEXP_TEMPLATE_INSTANCE_CORE( wxScrolled<wxWindow> )
403
404 // for compatibility with existing code, we provide wxScrolledWindow
405 // "typedef" for wxScrolled<wxPanel>. It's not a real typedef because we
406 // want wxScrolledWindow to show in wxRTTI information (the class is widely
407 // used and likelihood of its wxRTTI information being used too is high):
408 class WXDLLIMPEXP_CORE wxScrolledWindow : public wxScrolled<wxPanel>
409 {
410 public:
411 wxScrolledWindow() : wxScrolled<wxPanel>() {}
412 wxScrolledWindow(wxWindow *parent,
413 wxWindowID winid = wxID_ANY,
414 const wxPoint& pos = wxDefaultPosition,
415 const wxSize& size = wxDefaultSize,
416 long style = wxScrolledWindowStyle,
417 const wxString& name = wxPanelNameStr)
418 : wxScrolled<wxPanel>(parent, winid, pos, size, style, name) {}
419
420 DECLARE_DYNAMIC_CLASS_NO_COPY(wxScrolledWindow)
421 };
422
423 typedef wxScrolled<wxWindow> wxScrolledCanvas;
424
425 #endif // _WX_SCROLWIN_H_BASE_