]> git.saurik.com Git - wxWidgets.git/blob - include/wx/scrolwin.h
Option for variable line heights (MSW and GTK+ sofar)
[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 virtual void Scroll(int x, int y);
66
67 // get/set the page size for this orientation (wxVERTICAL/wxHORIZONTAL)
68 int GetScrollPageSize(int orient) const;
69 void SetScrollPageSize(int orient, int pageSize);
70
71 // get the number of lines the window can scroll,
72 // returns 0 if no scrollbars are there.
73 int GetScrollLines( int orient ) const;
74
75 // Set the x, y scrolling increments.
76 void SetScrollRate( int xstep, int ystep );
77
78 // get the size of one logical unit in physical ones
79 virtual void GetScrollPixelsPerUnit(int *pixelsPerUnitX,
80 int *pixelsPerUnitY) const;
81
82 // Enable/disable Windows scrolling in either direction. If true, wxWidgets
83 // scrolls the canvas and only a bit of the canvas is invalidated; no
84 // Clear() is necessary. If false, the whole canvas is invalidated and a
85 // Clear() is necessary. Disable for when the scroll increment is used to
86 // actually scroll a non-constant distance
87 virtual void EnableScrolling(bool x_scrolling, bool y_scrolling);
88
89 // Get the view start
90 virtual void GetViewStart(int *x, int *y) const;
91
92 // Set the scale factor, used in PrepareDC
93 void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; }
94 double GetScaleX() const { return m_scaleX; }
95 double GetScaleY() const { return m_scaleY; }
96
97 // translate between scrolled and unscrolled coordinates
98 void CalcScrolledPosition(int x, int y, int *xx, int *yy) const
99 { DoCalcScrolledPosition(x, y, xx, yy); }
100 wxPoint CalcScrolledPosition(const wxPoint& pt) const
101 {
102 wxPoint p2;
103 DoCalcScrolledPosition(pt.x, pt.y, &p2.x, &p2.y);
104 return p2;
105 }
106
107 void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const
108 { DoCalcUnscrolledPosition(x, y, xx, yy); }
109 wxPoint CalcUnscrolledPosition(const wxPoint& pt) const
110 {
111 wxPoint p2;
112 DoCalcUnscrolledPosition(pt.x, pt.y, &p2.x, &p2.y);
113 return p2;
114 }
115
116 virtual void DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const;
117 virtual void DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const;
118
119 // Adjust the scrollbars
120 virtual void AdjustScrollbars(void);
121
122 // Calculate scroll increment
123 virtual int CalcScrollInc(wxScrollWinEvent& event);
124
125 // Normally the wxScrolledWindow will scroll itself, but in some rare
126 // occasions you might want it to scroll [part of] another window (e.g. a
127 // child of it in order to scroll only a portion the area between the
128 // scrollbars (spreadsheet: only cell area will move).
129 virtual void SetTargetWindow(wxWindow *target);
130 virtual wxWindow *GetTargetWindow() const;
131
132 void SetTargetRect(const wxRect& rect) { m_rectToScroll = rect; }
133 wxRect GetTargetRect() const { return m_rectToScroll; }
134
135 // Override this function to draw the graphic (or just process EVT_PAINT)
136 virtual void OnDraw(wxDC& WXUNUSED(dc)) { }
137
138 // change the DC origin according to the scroll position.
139 virtual void DoPrepareDC(wxDC& dc);
140
141 // are we generating the autoscroll events?
142 bool IsAutoScrolling() const { return m_timerAutoScroll != NULL; }
143
144 // stop generating the scroll events when mouse is held outside the window
145 void StopAutoScrolling();
146
147 // this method can be overridden in a derived class to forbid sending the
148 // auto scroll events - note that unlike StopAutoScrolling() it doesn't
149 // stop the timer, so it will be called repeatedly and will typically
150 // return different values depending on the current mouse position
151 //
152 // the base class version just returns true
153 virtual bool SendAutoScrollEvents(wxScrollWinEvent& event) const;
154
155 // the methods to be called from the window event handlers
156 void HandleOnScroll(wxScrollWinEvent& event);
157 void HandleOnSize(wxSizeEvent& event);
158 void HandleOnPaint(wxPaintEvent& event);
159 void HandleOnChar(wxKeyEvent& event);
160 void HandleOnMouseEnter(wxMouseEvent& event);
161 void HandleOnMouseLeave(wxMouseEvent& event);
162 #if wxUSE_MOUSEWHEEL
163 void HandleOnMouseWheel(wxMouseEvent& event);
164 #endif // wxUSE_MOUSEWHEEL
165 void HandleOnChildFocus(wxChildFocusEvent& event);
166
167 // FIXME: this is needed for now for wxPlot compilation, should be removed
168 // once it is fixed!
169 void OnScroll(wxScrollWinEvent& event) { HandleOnScroll(event); }
170
171 protected:
172 // get pointer to our scroll rect if we use it or NULL
173 const wxRect *GetScrollRect() const
174 {
175 return m_rectToScroll.width != 0 ? &m_rectToScroll : NULL;
176 }
177
178 // get the size of the target window
179 wxSize GetTargetSize() const
180 {
181 return m_rectToScroll.width != 0 ? m_rectToScroll.GetSize()
182 : m_targetWindow->GetClientSize();
183 }
184
185 void GetTargetSize(int *w, int *h) const
186 {
187 wxSize size = GetTargetSize();
188 if ( w )
189 *w = size.x;
190 if ( h )
191 *h = size.y;
192 }
193
194 // implementations of various wxWindow virtual methods which should be
195 // forwarded to us (this can be done by WX_FORWARD_TO_SCROLL_HELPER())
196 bool ScrollLayout();
197 void ScrollDoSetVirtualSize(int x, int y);
198 wxSize ScrollGetBestVirtualSize() const;
199
200 // change just the target window (unlike SetWindow which changes m_win as
201 // well)
202 void DoSetTargetWindow(wxWindow *target);
203
204 // delete the event handler we installed
205 void DeleteEvtHandler();
206
207 // calls wxScrollHelperEvtHandler::ResetDrawnFlag(), see explanation
208 // in wxScrollHelperEvtHandler::ProcessEvent()
209 void ResetDrawnFlag();
210
211
212 double m_scaleX;
213 double m_scaleY;
214
215 wxWindow *m_win,
216 *m_targetWindow;
217
218 wxRect m_rectToScroll;
219
220 wxTimer *m_timerAutoScroll;
221
222 int m_xScrollPixelsPerLine;
223 int m_yScrollPixelsPerLine;
224 int m_xScrollPosition;
225 int m_yScrollPosition;
226 int m_xScrollLines;
227 int m_yScrollLines;
228 int m_xScrollLinesPerPage;
229 int m_yScrollLinesPerPage;
230
231 bool m_xScrollingEnabled;
232 bool m_yScrollingEnabled;
233
234 #if wxUSE_MOUSEWHEEL
235 int m_wheelRotation;
236 #endif // wxUSE_MOUSEWHEEL
237
238 wxScrollHelperEvtHandler *m_handler;
239
240 DECLARE_NO_COPY_CLASS(wxScrollHelper)
241 };
242
243 // this macro can be used in a wxScrollHelper-derived class to forward wxWindow
244 // methods to corresponding wxScrollHelper methods
245 #define WX_FORWARD_TO_SCROLL_HELPER() \
246 public: \
247 virtual void PrepareDC(wxDC& dc) { DoPrepareDC(dc); } \
248 virtual bool Layout() { return ScrollLayout(); } \
249 virtual void DoSetVirtualSize(int x, int y) \
250 { ScrollDoSetVirtualSize(x, y); } \
251 virtual wxSize GetBestVirtualSize() const \
252 { return ScrollGetBestVirtualSize(); }
253
254 // include the declaration of wxScrollHelperNative if needed
255 #if defined(__WXGTK20__) && !defined(__WXUNIVERSAL__)
256 #include "wx/gtk/scrolwin.h"
257 #elif defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
258 #include "wx/gtk1/scrolwin.h"
259 #else
260 typedef wxScrollHelper wxScrollHelperNative;
261 #endif
262
263 // ----------------------------------------------------------------------------
264 // wxScrolled<T>: a wxWindow which knows how to scroll
265 // ----------------------------------------------------------------------------
266
267 // helper class for wxScrolled<T> below
268 struct WXDLLIMPEXP_CORE wxScrolledT_Helper
269 {
270 static wxSize FilterBestSize(const wxWindow *win,
271 const wxScrollHelperNative *helper,
272 const wxSize& origBest);
273 #ifdef __WXMSW__
274 static WXLRESULT FilterMSWWindowProc(WXUINT nMsg, WXLRESULT origResult);
275 #endif
276 };
277
278 // Scrollable window base on window type T. This used to be wxScrolledWindow,
279 // but wxScrolledWindow includes wxControlContainer functionality and that's
280 // not always desirable.
281 template<class T>
282 class WXDLLIMPEXP_CORE wxScrolled : public T,
283 public wxScrollHelperNative,
284 private wxScrolledT_Helper
285 {
286 public:
287 wxScrolled() : wxScrollHelperNative(this) { }
288 wxScrolled(wxWindow *parent,
289 wxWindowID winid = wxID_ANY,
290 const wxPoint& pos = wxDefaultPosition,
291 const wxSize& size = wxDefaultSize,
292 long style = wxScrolledWindowStyle,
293 const wxString& name = wxPanelNameStr)
294 : wxScrollHelperNative(this)
295 {
296 Create(parent, winid, pos, size, style, name);
297 }
298
299 bool Create(wxWindow *parent,
300 wxWindowID winid,
301 const wxPoint& pos = wxDefaultPosition,
302 const wxSize& size = wxDefaultSize,
303 long style = wxScrolledWindowStyle,
304 const wxString& name = wxPanelNameStr)
305 {
306 m_targetWindow = this;
307
308 #ifdef __WXMAC__
309 this->MacSetClipChildren(true);
310 #endif
311
312 this->Connect(wxEVT_PAINT, wxPaintEventHandler(wxScrolled::OnPaint));
313
314 // by default, we're scrollable in both directions (but if one of the
315 // styles is specified explicitly, we shouldn't add the other one
316 // automatically)
317 if ( !(style & (wxHSCROLL | wxVSCROLL)) )
318 style |= wxHSCROLL | wxVSCROLL;
319
320 return T::Create(parent, winid, pos, size, style, name);
321 }
322
323 // we need to return a special WM_GETDLGCODE value to process just the
324 // arrows but let the other navigation characters through
325 #ifdef __WXMSW__
326 virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
327 {
328 return FilterMSWWindowProc(nMsg, T::MSWWindowProc(nMsg, wParam, lParam));
329 }
330 #endif // __WXMSW__
331
332 WX_FORWARD_TO_SCROLL_HELPER()
333
334 protected:
335 virtual wxSize DoGetBestSize() const
336 {
337 return FilterBestSize(this, this, T::DoGetBestSize());
338 }
339
340 private:
341 // this is needed for wxEVT_PAINT processing hack described in
342 // wxScrollHelperEvtHandler::ProcessEvent()
343 void OnPaint(wxPaintEvent& event)
344 {
345 // the user code didn't really draw the window if we got here, so set
346 // this flag to try to call OnDraw() later
347 ResetDrawnFlag();
348 event.Skip();
349 }
350
351 DECLARE_NO_COPY_CLASS(wxScrolled)
352 };
353
354 // VC++ <= 6 requires this; it's unlikely any other specializations would
355 // be needed by user code _and_ they were using VC6, so we list only wxWindow
356 // (typical use) and wxPanel (wxScrolledWindow use) specializations here
357 WXDLLIMPEXP_TEMPLATE_INSTANCE_CORE( wxScrolled<wxPanel> )
358 WXDLLIMPEXP_TEMPLATE_INSTANCE_CORE( wxScrolled<wxWindow> )
359
360 // for compatibility with existing code, we provide wxScrolledWindow
361 // "typedef" for wxScrolled<wxPanel>. It's not a real typedef because we
362 // want wxScrolledWindow to show in wxRTTI information (the class is widely
363 // used and likelihood of its wxRTTI information being used too is high):
364 class WXDLLIMPEXP_CORE wxScrolledWindow : public wxScrolled<wxPanel>
365 {
366 public:
367 wxScrolledWindow() : wxScrolled<wxPanel>() {}
368 wxScrolledWindow(wxWindow *parent,
369 wxWindowID winid = wxID_ANY,
370 const wxPoint& pos = wxDefaultPosition,
371 const wxSize& size = wxDefaultSize,
372 long style = wxScrolledWindowStyle,
373 const wxString& name = wxPanelNameStr)
374 : wxScrolled<wxPanel>(parent, winid, pos, size, style, name) {}
375
376 DECLARE_DYNAMIC_CLASS_NO_COPY(wxScrolledWindow)
377 };
378
379 typedef wxScrolled<wxWindow> wxScrolledCanvas;
380
381 #endif // _WX_SCROLWIN_H_BASE_