Applied wxVScrolledWindow patch
[wxWidgets.git] / samples / vscroll / vstest.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/vscroll/vstest.cpp
3 // Purpose: VScroll wxWidgets sample
4 // Author: Vadim Zeitlin
5 // Modified by: Brad Anderson
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwidgets.org>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers)
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #include "wx/app.h"
32 #include "wx/frame.h"
33 #endif
34
35 // we need to include the headers not included from wx/wx.h explicitly anyhow
36 #include "wx/vscroll.h"
37
38 // ----------------------------------------------------------------------------
39 // resources
40 // ----------------------------------------------------------------------------
41
42 // the application icon (under Windows and OS/2 it is in resources)
43 #if !defined(__WXMSW__) && !defined(__WXPM__)
44 #include "../sample.xpm"
45 #endif
46
47 // ----------------------------------------------------------------------------
48 // definitions
49 // ----------------------------------------------------------------------------
50
51 #define MAX_LINES 200
52
53 // ----------------------------------------------------------------------------
54 // private classes
55 // ----------------------------------------------------------------------------
56
57 // Define a new application type, each program should derive a class from wxApp
58 class VarScrollApp : public wxApp
59 {
60 public:
61 // create our main window
62 virtual bool OnInit();
63 };
64
65 // Define a new frame type: this is going to be our main frame
66 class VarScrollFrame : public wxFrame
67 {
68 public:
69 // ctor
70 VarScrollFrame();
71
72 // event handlers (these functions should _not_ be virtual)
73 void OnQuit(wxCommandEvent& event);
74 void OnModeVScroll(wxCommandEvent& event);
75 void OnModeHVScroll(wxCommandEvent& event);
76 void OnAbout(wxCommandEvent& event);
77
78 void OnSize(wxSizeEvent& event)
79 {
80 // show current size in the status bar
81 #if wxUSE_STATUSBAR
82 if ( m_frameStatusBar )
83 {
84 wxSize sz = GetClientSize();
85 SetStatusText(wxString::Format(_T("%dx%d"), sz.x, sz.y), 1);
86 }
87 #endif // wxUSE_STATUSBAR
88
89 event.Skip();
90 }
91
92 private:
93 // any class wishing to process wxWidgets events must use this macro
94 DECLARE_EVENT_TABLE()
95
96 // either a wxVScrolledWindow or a wxHVScrolled window, depending on current mode
97 wxPanel *m_scrollWindow;
98 };
99
100 class VScrollWindow : public wxVScrolledWindow
101 {
102 public:
103 VScrollWindow(wxFrame *frame) : wxVScrolledWindow(frame, wxID_ANY)
104 {
105 m_frame = frame;
106
107 SetLineCount(MAX_LINES);
108
109 int i;
110 for ( i = 0; i < MAX_LINES; ++i )
111 m_heights[i] = rand()%25+16; // low: 15; high: 40
112
113 m_changed = true;
114 }
115
116 void OnIdle(wxIdleEvent&)
117 {
118 #if wxUSE_STATUSBAR
119 m_frame->SetStatusText(wxString::Format
120 (
121 _T("Page size = %d, pos = %d, max = %d"),
122 GetScrollThumb(wxVERTICAL),
123 GetScrollPos(wxVERTICAL),
124 GetScrollRange(wxVERTICAL)
125 ));
126 #endif // wxUSE_STATUSBAR
127 m_changed = false;
128 }
129
130 void OnPaint(wxPaintEvent&)
131 {
132 wxPaintDC dc(this);
133
134 dc.SetPen(*wxBLACK_PEN);
135
136 const size_t lineFirst = GetVisibleBegin(),
137 lineLast = GetVisibleEnd();
138
139 const wxCoord hText = dc.GetCharHeight();
140
141 wxSize clientSize = GetClientSize();
142
143 wxCoord y = 0;
144 for ( size_t line = lineFirst; line < lineLast; line++ )
145 {
146 dc.DrawLine(0, y, clientSize.GetWidth(), y);
147
148 wxCoord hLine = OnGetLineHeight(line);
149 dc.DrawText(wxString::Format(_T("Line %lu"), (unsigned long)line),
150 2, y + (hLine - hText) / 2);
151
152 y += hLine;
153 dc.DrawLine(0, y, 1000, y);
154 }
155 }
156
157 void OnScroll(wxScrollWinEvent& event)
158 {
159 m_changed = true;
160
161 event.Skip();
162 }
163
164
165 virtual wxCoord OnGetLineHeight(size_t n) const
166 {
167 wxASSERT( n < GetLineCount() );
168
169 return m_heights[n];
170 }
171
172 private:
173 wxFrame *m_frame;
174
175 int m_heights[MAX_LINES];
176
177 bool m_changed;
178
179 DECLARE_EVENT_TABLE()
180 };
181
182 BEGIN_EVENT_TABLE(VScrollWindow, wxVScrolledWindow)
183 EVT_IDLE(VScrollWindow::OnIdle)
184 EVT_PAINT(VScrollWindow::OnPaint)
185 EVT_SCROLLWIN(VScrollWindow::OnScroll)
186 END_EVENT_TABLE()
187
188 class HVScrollWindow : public wxHVScrolledWindow
189 {
190 public:
191 HVScrollWindow(wxFrame *frame) : wxHVScrolledWindow(frame, wxID_ANY)
192 {
193 m_frame = frame;
194
195 SetRowColumnCounts(MAX_LINES, MAX_LINES);
196
197 int i;
198 for ( i = 0; i < MAX_LINES; ++i )
199 {
200 m_heights[i] = rand()%30+31; // low: 30; high: 60
201 m_widths[i] = rand()%30+61; // low: 60; high: 90
202 }
203
204 m_changed = true;
205 }
206
207 void OnIdle(wxIdleEvent&)
208 {
209 #if wxUSE_STATUSBAR
210 m_frame->SetStatusText(wxString::Format
211 (
212 _T("Page size = %d rows %d columns; pos = row: %d, column: %d; max = %d rows, %d columns"),
213 GetScrollThumb(wxVERTICAL),
214 GetScrollThumb(wxHORIZONTAL),
215 GetScrollPos(wxVERTICAL),
216 GetScrollPos(wxHORIZONTAL),
217 GetScrollRange(wxVERTICAL),
218 GetScrollRange(wxHORIZONTAL)
219 ));
220 #endif // wxUSE_STATUSBAR
221 m_changed = false;
222 }
223
224 void OnPaint(wxPaintEvent&)
225 {
226 wxPaintDC dc(this);
227
228 dc.SetPen(*wxBLACK_PEN);
229
230 const size_t rowFirst = GetVisibleRowsBegin(),
231 rowLast = GetVisibleRowsEnd();
232 const size_t columnFirst = GetVisibleColumnsBegin(),
233 columnLast = GetVisibleColumnsEnd();
234
235 const wxCoord hText = dc.GetCharHeight();
236
237 wxSize clientSize = GetClientSize();
238
239 wxCoord y = 0;
240 wxCoord x = 0;
241 for ( size_t row = rowFirst; row < rowLast; row++ )
242 {
243 wxCoord rowHeight = OnGetRowHeight(row);
244 dc.DrawLine(0, y, clientSize.GetWidth(), y);
245
246 x = 0;
247 for ( size_t col = columnFirst; col < columnLast; col++ )
248 {
249 wxCoord colWidth = OnGetColumnWidth(col);
250
251 if ( row == rowFirst )
252 dc.DrawLine(x, 0, x, clientSize.GetHeight());
253
254 dc.DrawText(wxString::Format(_T("Row %lu"), (unsigned long)row),
255 x + 2, y + rowHeight / 2 - hText);
256 dc.DrawText(wxString::Format(_T("Col %lu"), (unsigned long)col),
257 x + 2, y + rowHeight / 2);
258
259 x += colWidth;
260 if ( row == rowFirst)
261 dc.DrawLine(x, 0, x, clientSize.GetHeight());
262 }
263
264 y += rowHeight;
265 dc.DrawLine(0, y, clientSize.GetWidth(), y);
266 }
267 }
268
269 void OnScroll(wxScrollWinEvent& event)
270 {
271 m_changed = true;
272
273 event.Skip();
274 }
275
276
277 virtual wxCoord OnGetRowHeight(size_t n) const
278 {
279 wxASSERT( n < GetRowCount() );
280
281 return m_heights[n];
282 }
283
284 virtual wxCoord OnGetColumnWidth(size_t n) const
285 {
286 wxASSERT( n < GetColumnCount() );
287
288 return m_widths[n];
289 }
290
291 private:
292 wxFrame *m_frame;
293
294 int m_heights[MAX_LINES];
295 int m_widths[MAX_LINES];
296
297 bool m_changed;
298
299 DECLARE_EVENT_TABLE()
300 };
301
302 BEGIN_EVENT_TABLE(HVScrollWindow, wxHVScrolledWindow)
303 EVT_IDLE(HVScrollWindow::OnIdle)
304 EVT_PAINT(HVScrollWindow::OnPaint)
305 EVT_SCROLLWIN(HVScrollWindow::OnScroll)
306 END_EVENT_TABLE()
307
308 // ----------------------------------------------------------------------------
309 // constants
310 // ----------------------------------------------------------------------------
311
312 // IDs for the controls and the menu commands
313 enum
314 {
315 // menu items
316 VScroll_Quit = wxID_EXIT,
317
318 // it is important for the id corresponding to the "About" command to have
319 // this standard value as otherwise it won't be handled properly under Mac
320 // (where it is special and put into the "Apple" menu)
321 VScroll_About = wxID_ABOUT,
322
323 VScroll_VScrollMode = wxID_HIGHEST + 1,
324 VScroll_HVScrollMode
325 };
326
327 // ----------------------------------------------------------------------------
328 // event tables and other macros for wxWidgets
329 // ----------------------------------------------------------------------------
330
331 // the event tables connect the wxWidgets events with the functions (event
332 // handlers) which process them. It can be also done at run-time, but for the
333 // simple menu events like this the static method is much simpler.
334 BEGIN_EVENT_TABLE(VarScrollFrame, wxFrame)
335 EVT_MENU(VScroll_Quit, VarScrollFrame::OnQuit)
336 EVT_MENU(VScroll_VScrollMode, VarScrollFrame::OnModeVScroll)
337 EVT_MENU(VScroll_HVScrollMode, VarScrollFrame::OnModeHVScroll)
338 EVT_MENU(VScroll_About, VarScrollFrame::OnAbout)
339 EVT_SIZE(VarScrollFrame::OnSize)
340 END_EVENT_TABLE()
341
342 // Create a new application object: this macro will allow wxWidgets to create
343 // the application object during program execution (it's better than using a
344 // static object for many reasons) and also declares the accessor function
345 // wxGetApp() which will return the reference of the right type (i.e. VarScrollApp and
346 // not wxApp)
347 IMPLEMENT_APP(VarScrollApp)
348
349 // ============================================================================
350 // implementation
351 // ============================================================================
352
353 // ----------------------------------------------------------------------------
354 // the application class
355 // ----------------------------------------------------------------------------
356
357 // 'Main program' equivalent: the program execution "starts" here
358 bool VarScrollApp::OnInit()
359 {
360 // create the main application window
361 VarScrollFrame *frame = new VarScrollFrame;
362
363 // and show it (the frames, unlike simple controls, are not shown when
364 // created initially)
365 frame->Show(true);
366
367 // ok
368 return true;
369 }
370
371 // ----------------------------------------------------------------------------
372 // main frame
373 // ----------------------------------------------------------------------------
374
375 // frame constructor
376 VarScrollFrame::VarScrollFrame()
377 : wxFrame(NULL,
378 wxID_ANY,
379 _T("VScroll wxWidgets Sample"),
380 wxDefaultPosition,
381 wxSize(400, 350)),
382 m_scrollWindow(NULL)
383 {
384 // set the frame icon
385 SetIcon(wxICON(sample));
386
387 #if wxUSE_MENUS
388 // create a menu bar
389 wxMenu *menuFile = new wxMenu;
390
391 wxMenu *menuMode = new wxMenu;
392
393 // the "About" item should be in the help menu
394 wxMenu *menuHelp = new wxMenu;
395 menuHelp->Append(VScroll_About, _T("&About...\tF1"), _T("Show about dialog"));
396
397 #ifdef wxHAS_RADIO_MENU_ITEMS
398 menuMode->AppendRadioItem(VScroll_VScrollMode, _T("&Vertical\tAlt-V"),
399 _T("Vertical scrolling only"));
400 menuMode->AppendRadioItem(VScroll_HVScrollMode,
401 _T("&Horizontal/Vertical\tAlt-H"),
402 _T("Horizontal and vertical scrolling"));
403 menuMode->Check(VScroll_VScrollMode, true);
404 #else
405 menuMode->Append(VScroll_VScrollMode, _T("&Vertical\tAlt-V"),
406 _T("Vertical scrolling only"));
407 menuMode->Append(VScroll_HVScrollMode, _T("&Horizontal/Vertical\tAlt-H"),
408 _T("Horizontal and vertical scrolling"));
409 #endif
410
411 menuFile->Append(VScroll_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
412
413 // now append the freshly created menu to the menu bar...
414 wxMenuBar *menuBar = new wxMenuBar;
415 menuBar->Append(menuFile, _T("&File"));
416 menuBar->Append(menuMode, _T("&Mode"));
417 menuBar->Append(menuHelp, _T("&Help"));
418
419 // ... and attach this menu bar to the frame
420 SetMenuBar(menuBar);
421 #endif // wxUSE_MENUS
422
423 #if wxUSE_STATUSBAR
424 // create a status bar just for fun (by default with 1 pane only)
425 CreateStatusBar(2);
426 SetStatusText(_T("Welcome to wxWidgets!"));
427 int widths[2];
428 widths[0] = -1;
429 widths[1] = 100;
430 SetStatusWidths(2, widths);
431 #endif // wxUSE_STATUSBAR
432
433 // create our one and only child -- it will take our entire client area
434 if ( menuMode->IsChecked(VScroll_VScrollMode) )
435 m_scrollWindow = new VScrollWindow(this);
436 else if ( menuMode->IsChecked(VScroll_VScrollMode) )
437 m_scrollWindow = new HVScrollWindow(this);
438 }
439
440 // ----------------------------------------------------------------------------
441 // event handlers
442 // ----------------------------------------------------------------------------
443
444 void VarScrollFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
445 {
446 // true is to force the frame to close
447 Close(true);
448 }
449
450 void VarScrollFrame::OnModeVScroll(wxCommandEvent& WXUNUSED(event))
451 {
452 if ( m_scrollWindow )
453 m_scrollWindow->Destroy();
454
455 m_scrollWindow = new VScrollWindow(this);
456 SendSizeEvent();
457 }
458
459 void VarScrollFrame::OnModeHVScroll(wxCommandEvent& WXUNUSED(event))
460 {
461 if ( m_scrollWindow )
462 m_scrollWindow->Destroy();
463
464 m_scrollWindow = new HVScrollWindow(this);
465 SendSizeEvent();
466 }
467
468 void VarScrollFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
469 {
470 wxMessageBox(_T("VScroll shows how to implement scrolling with\n")
471 _T("variable line widths and heights.\n")
472 _T("(c) 2003 Vadim Zeitlin"),
473 _T("About VScroll"),
474 wxOK | wxICON_INFORMATION,
475 this);
476 }