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