]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/scroll/scroll.cpp
added library target to regen only lib makefiles
[wxWidgets.git] / samples / scroll / scroll.cpp
... / ...
CommitLineData
1/*
2 * Program: scroll
3 *
4 * Author: Robert Roebling
5 *
6 * Copyright: (C) 1998, Robert Roebling
7 * 2002, Ron Lee
8 *
9 */
10
11// For compilers that support precompilation, includes "wx/wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15#pragma hdrstop
16#endif
17
18#ifndef WX_PRECOMP
19#include "wx/wx.h"
20#endif
21
22#include "wx/image.h"
23#include "wx/listctrl.h"
24#include "wx/sizer.h"
25#include "wx/log.h"
26
27
28// derived classes
29
30class MyFrame;
31class MyApp;
32
33// MyCanvas
34
35class MyCanvas: public wxScrolledWindow
36{
37public:
38 MyCanvas() {}
39 MyCanvas( wxWindow *parent, wxWindowID, const wxPoint &pos, const wxSize &size );
40 ~MyCanvas();
41 void OnPaint( wxPaintEvent &event );
42 void OnQueryPosition( wxCommandEvent &event );
43 void OnAddButton( wxCommandEvent &event );
44 void OnDeleteButton( wxCommandEvent &event );
45 void OnMoveButton( wxCommandEvent &event );
46 void OnScrollWin( wxCommandEvent &event );
47 void OnMouseDown( wxMouseEvent &event );
48
49 wxButton *m_button;
50
51 DECLARE_DYNAMIC_CLASS(MyCanvas)
52 DECLARE_EVENT_TABLE()
53};
54
55
56// ----------------------------------------------------------------------------
57// Autoscrolling example.
58// ----------------------------------------------------------------------------
59
60// this class uses the 'virtual' size attribute along with an internal
61// sizer to automatically set up scrollbars as needed
62
63class MyAutoScrollWindow : public wxScrolledWindow
64{
65private:
66
67 wxButton *m_button;
68
69public:
70
71 MyAutoScrollWindow( wxWindow *parent );
72
73 void OnResizeClick( wxCommandEvent &WXUNUSED( event ) );
74
75 DECLARE_EVENT_TABLE()
76};
77
78
79// ----------------------------------------------------------------------------
80// MyScrolledWindow classes: examples of wxScrolledWindow usage
81// ----------------------------------------------------------------------------
82
83// base class for both of them
84class MyScrolledWindowBase : public wxScrolledWindow
85{
86public:
87 MyScrolledWindowBase(wxWindow *parent)
88 : wxScrolledWindow(parent)
89 , m_nLines( 100 )
90 {
91 wxClientDC dc(this);
92 dc.GetTextExtent(_T("Line 17"), NULL, &m_hLine);
93 }
94
95protected:
96 // the height of one line on screen
97 wxCoord m_hLine;
98
99 // the number of lines we draw
100 size_t m_nLines;
101};
102
103// this class does "stupid" redrawing - it redraws everything each time
104// and sets the scrollbar extent directly.
105
106class MyScrolledWindowDumb : public MyScrolledWindowBase
107{
108public:
109 MyScrolledWindowDumb(wxWindow *parent) : MyScrolledWindowBase(parent)
110 {
111 // no horz scrolling
112 SetScrollbars(0, m_hLine, 0, m_nLines + 1, 0, 0, TRUE /* no refresh */);
113 }
114
115 virtual void OnDraw(wxDC& dc);
116};
117
118// this class does "smart" redrawing - only redraws the lines which must be
119// redrawn and sets the scroll rate and virtual size to affect the
120// scrollbars.
121//
122// Note that this class should produce identical results to the one above.
123
124class MyScrolledWindowSmart : public MyScrolledWindowBase
125{
126public:
127 MyScrolledWindowSmart(wxWindow *parent) : MyScrolledWindowBase(parent)
128 {
129 // no horz scrolling
130 SetScrollRate( 0, m_hLine );
131 SetVirtualSize( -1, ( m_nLines + 1 ) * m_hLine );
132 }
133
134 virtual void OnDraw(wxDC& dc);
135};
136
137
138// ----------------------------------------------------------------------------
139// MyFrame
140// ----------------------------------------------------------------------------
141
142class MyFrame: public wxFrame
143{
144public:
145 MyFrame();
146
147 void OnAbout( wxCommandEvent &event );
148 void OnQuit( wxCommandEvent &event );
149 void OnDeleteAll( wxCommandEvent &event );
150 void OnInsertNew( wxCommandEvent &event );
151
152 MyCanvas *m_canvas;
153 wxTextCtrl *m_log;
154
155 DECLARE_DYNAMIC_CLASS(MyFrame)
156 DECLARE_EVENT_TABLE()
157};
158
159// MyApp
160
161class MyApp: public wxApp
162{
163public:
164 virtual bool OnInit();
165};
166
167// main program
168
169IMPLEMENT_APP(MyApp)
170
171// ids
172
173const long ID_ADDBUTTON = wxNewId();
174const long ID_DELBUTTON = wxNewId();
175const long ID_MOVEBUTTON = wxNewId();
176const long ID_SCROLLWIN = wxNewId();
177const long ID_QUERYPOS = wxNewId();
178
179const long ID_NEWBUTTON = wxNewId();
180
181// MyCanvas
182
183IMPLEMENT_DYNAMIC_CLASS(MyCanvas, wxScrolledWindow)
184
185BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
186 EVT_PAINT( MyCanvas::OnPaint)
187 EVT_MOUSE_EVENTS( MyCanvas::OnMouseDown)
188 EVT_BUTTON( ID_QUERYPOS, MyCanvas::OnQueryPosition)
189 EVT_BUTTON( ID_ADDBUTTON, MyCanvas::OnAddButton)
190 EVT_BUTTON( ID_DELBUTTON, MyCanvas::OnDeleteButton)
191 EVT_BUTTON( ID_MOVEBUTTON, MyCanvas::OnMoveButton)
192 EVT_BUTTON( ID_SCROLLWIN, MyCanvas::OnScrollWin)
193END_EVENT_TABLE()
194
195MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id,
196 const wxPoint &pos, const wxSize &size )
197 : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER | wxTAB_TRAVERSAL, _T("test canvas") )
198{
199 SetScrollRate( 10, 10 );
200 SetVirtualSize( 500, 1000 );
201
202 (void) new wxButton( this, ID_ADDBUTTON, _T("add button"), wxPoint(10,10) );
203 (void) new wxButton( this, ID_DELBUTTON, _T("del button"), wxPoint(10,40) );
204 (void) new wxButton( this, ID_MOVEBUTTON, _T("move button"), wxPoint(150,10) );
205 (void) new wxButton( this, ID_SCROLLWIN, _T("scroll win"), wxPoint(250,10) );
206
207#if 0
208
209 wxString choices[] =
210 {
211 "This",
212 "is one of my",
213 "really",
214 "wonderful",
215 "examples."
216 };
217
218 m_button = new wxButton( this, ID_QUERYPOS, "Query position", wxPoint(10,110) );
219
220 (void) new wxTextCtrl( this, -1, "wxTextCtrl", wxPoint(10,150), wxSize(80,-1) );
221
222 (void) new wxRadioButton( this, -1, "Disable", wxPoint(10,190) );
223
224 (void) new wxComboBox( this, -1, "This", wxPoint(10,230), wxDefaultSize, 5, choices );
225
226 (void) new wxRadioBox( this, -1, "This", wxPoint(10,310), wxDefaultSize, 5, choices, 2, wxRA_SPECIFY_COLS );
227
228 (void) new wxRadioBox( this, -1, "This", wxPoint(10,440), wxDefaultSize, 5, choices, 2, wxRA_SPECIFY_ROWS );
229
230 wxListCtrl *m_listCtrl = new wxListCtrl(
231 this, -1, wxPoint(200, 110), wxSize(180, 120),
232 wxLC_REPORT | wxSIMPLE_BORDER | wxLC_SINGLE_SEL );
233
234 m_listCtrl->InsertColumn(0, "First", wxLIST_FORMAT_LEFT, 90);
235 m_listCtrl->InsertColumn(1, "Last", wxLIST_FORMAT_LEFT, 90);
236
237 for ( int i=0; i < 30; i++)
238 {
239 char buf[20];
240 sprintf(buf, "Item %d", i);
241 m_listCtrl->InsertItem(i, buf);
242 }
243 m_listCtrl->SetItemState( 3, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
244
245 (void) new wxListBox( this, -1, wxPoint(260,280), wxSize(120,120), 5, choices, wxLB_ALWAYS_SB );
246
247#endif
248
249 wxPanel *test = new wxPanel( this, -1, wxPoint(10, 110), wxSize(130,50), wxSIMPLE_BORDER | wxTAB_TRAVERSAL );
250 test->SetBackgroundColour( wxT("WHEAT") );
251
252#if 0
253
254 wxButton *test2 = new wxButton( test, -1, "Hallo", wxPoint(10,10) );
255
256 test = new wxPanel( this, -1, wxPoint(160, 530), wxSize(130,120), wxSUNKEN_BORDER | wxTAB_TRAVERSAL );
257 test->SetBackgroundColour( wxT("WHEAT") );
258 test->SetCursor( wxCursor( wxCURSOR_NO_ENTRY ) );
259 test2 = new wxButton( test, -1, "Hallo", wxPoint(10,10) );
260 test2->SetCursor( wxCursor( wxCURSOR_PENCIL ) );
261
262 test = new wxPanel( this, -1, wxPoint(310, 530), wxSize(130,120), wxRAISED_BORDER | wxTAB_TRAVERSAL );
263 test->SetBackgroundColour( wxT("WHEAT") );
264 test->SetCursor( wxCursor( wxCURSOR_PENCIL ) );
265 test2 = new wxButton( test, -1, "Hallo", wxPoint(10,10) );
266 test2->SetCursor( wxCursor( wxCURSOR_NO_ENTRY ) );
267
268#endif
269
270 SetBackgroundColour( wxT("BLUE") );
271
272 SetCursor( wxCursor( wxCURSOR_IBEAM ) );
273}
274
275MyCanvas::~MyCanvas()
276{
277}
278
279void MyCanvas::OnMouseDown( wxMouseEvent &event )
280{
281 if (event.LeftDown())
282 {
283 wxPoint pt( event.GetPosition() );
284 int x,y;
285 CalcUnscrolledPosition( pt.x, pt.y, &x, &y );
286 wxLogMessage( wxT("Mouse down event at: %d %d, scrolled: %d %d"), pt.x, pt.y, x, y );
287
288 if ( !event.LeftIsDown() )
289 wxLogMessage( wxT("Error: LeftIsDown() should be TRUE if for LeftDown()") );
290 }
291}
292
293void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) )
294{
295 wxPaintDC dc( this );
296 PrepareDC( dc );
297
298 dc.DrawText( _T("Press mouse button to test calculations!"), 160, 50 );
299
300 dc.DrawText( _T("Some text"), 140, 140 );
301
302 dc.DrawRectangle( 100, 160, 200, 200 );
303}
304
305void MyCanvas::OnQueryPosition( wxCommandEvent &WXUNUSED(event) )
306{
307 wxPoint pt( m_button->GetPosition() );
308 wxLogMessage( wxT("Position of \"Query position\" is %d %d"), pt.x, pt.y );
309 pt = ClientToScreen( pt );
310 wxLogMessage( wxT("Position of \"Query position\" on screen is %d %d"), pt.x, pt.y );
311}
312
313void MyCanvas::OnAddButton( wxCommandEvent &WXUNUSED(event) )
314{
315 wxLogMessage( wxT("Inserting button at position 10,70...") );
316 wxButton *button = new wxButton( this, ID_NEWBUTTON, wxT("new button"), wxPoint(10,70), wxSize(80,25) );
317 wxPoint pt( button->GetPosition() );
318 wxLogMessage( wxT("-> Position after inserting %d %d"), pt.x, pt.y );
319}
320
321void MyCanvas::OnDeleteButton( wxCommandEvent &event )
322{
323 wxLogMessage( wxT("Deleting button inserted with \"Add button\"...") );
324 wxWindow *win = FindWindow( ID_NEWBUTTON );
325 if (win)
326 win->Destroy();
327 else
328 wxLogMessage( wxT("-> No window with id = ID_NEWBUTTON found.") );
329}
330
331void MyCanvas::OnMoveButton( wxCommandEvent &event )
332{
333 wxLogMessage( wxT("Moving button 10 pixels downward..") );
334 wxWindow *win = FindWindow( event.GetId() );
335 wxPoint pt( win->GetPosition() );
336 wxLogMessage( wxT("-> Position before move is %d %d"), pt.x, pt.y );
337 win->Move( -1, pt.y + 10 );
338 pt = win->GetPosition();
339 wxLogMessage( wxT("-> Position after move is %d %d"), pt.x, pt.y );
340}
341
342void MyCanvas::OnScrollWin( wxCommandEvent &WXUNUSED(event) )
343{
344 wxLogMessage( wxT("Scrolling 2 units up.\nThe white square and the controls should move equally!") );
345 int x,y;
346 GetViewStart( &x, &y );
347 Scroll( -1, y+2 );
348}
349
350// MyAutoScrollWindow
351
352const long ID_RESIZEBUTTON = wxNewId();
353const wxSize SMALL_BUTTON( 100, 50 );
354const wxSize LARGE_BUTTON( 300, 100 );
355
356BEGIN_EVENT_TABLE( MyAutoScrollWindow, wxScrolledWindow)
357 EVT_BUTTON( ID_RESIZEBUTTON, MyAutoScrollWindow::OnResizeClick)
358END_EVENT_TABLE()
359
360MyAutoScrollWindow::MyAutoScrollWindow( wxWindow *parent )
361 : wxScrolledWindow( parent )
362{
363 SetBackgroundColour( wxT("GREEN") );
364
365 // Set the rate we'd like for scrolling.
366
367 SetScrollRate( 5, 5 );
368
369 // Populate a sizer with a 'resizing' button and some
370 // other static decoration
371
372 wxFlexGridSizer *innersizer = new wxFlexGridSizer( 2, 2 );
373
374 m_button = new wxButton( this,
375 ID_RESIZEBUTTON,
376 _T("Press me"),
377 wxDefaultPosition,
378 SMALL_BUTTON );
379
380 // We need to do this here, because wxADJUST_MINSIZE below
381 // will cause the initial size to be ignored for Best/Min size.
382 // It would be nice to fix the sizers to handle this a little
383 // more cleanly.
384
385 m_button->SetSizeHints( SMALL_BUTTON.GetWidth(), SMALL_BUTTON.GetHeight() );
386
387 innersizer->Add( m_button,
388 0,
389 wxALIGN_CENTER | wxALL | wxADJUST_MINSIZE,
390 20 );
391
392 innersizer->Add( new wxStaticText( this, -1, _T("This is just") ),
393 0,
394 wxALIGN_CENTER );
395
396 innersizer->Add( new wxStaticText( this, -1, _T("some decoration") ),
397 0,
398 wxALIGN_CENTER );
399
400 innersizer->Add( new wxStaticText( this, -1, _T("for you to scroll...") ),
401 0,
402 wxALIGN_CENTER );
403
404 // Then use the sizer to set the scrolled region size.
405
406 SetSizer( innersizer );
407}
408
409void MyAutoScrollWindow::OnResizeClick( wxCommandEvent &WXUNUSED( event ) )
410{
411 // Arbitrarily resize the button to change the minimum size of
412 // the (scrolled) sizer.
413
414 if( m_button->GetSize() == SMALL_BUTTON )
415 m_button->SetSizeHints( LARGE_BUTTON.GetWidth(), LARGE_BUTTON.GetHeight() );
416 else
417 m_button->SetSizeHints( SMALL_BUTTON.GetWidth(), SMALL_BUTTON.GetHeight() );
418
419 // Force update layout and scrollbars, since nothing we do here
420 // necessarily generates a size event which would do it for us.
421
422 FitInside();
423}
424
425// MyFrame
426
427const long ID_QUIT = wxNewId();
428const long ID_ABOUT = wxNewId();
429const long ID_DELETE_ALL = wxNewId();
430const long ID_INSERT_NEW = wxNewId();
431
432IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
433
434BEGIN_EVENT_TABLE(MyFrame,wxFrame)
435 EVT_MENU (ID_DELETE_ALL, MyFrame::OnDeleteAll)
436 EVT_MENU (ID_INSERT_NEW, MyFrame::OnInsertNew)
437 EVT_MENU (ID_ABOUT, MyFrame::OnAbout)
438 EVT_MENU (ID_QUIT, MyFrame::OnQuit)
439END_EVENT_TABLE()
440
441MyFrame::MyFrame()
442 : wxFrame( (wxFrame *)NULL, -1, _T("wxScrolledWindow sample"),
443 wxPoint(20,20), wxSize(470,500) )
444{
445 wxMenu *file_menu = new wxMenu();
446 file_menu->Append( ID_DELETE_ALL, _T("Delete all"));
447 file_menu->Append( ID_INSERT_NEW, _T("Insert new"));
448 file_menu->Append( ID_ABOUT, _T("&About.."));
449 file_menu->Append( ID_QUIT, _T("E&xit\tAlt-X"));
450
451 wxMenuBar *menu_bar = new wxMenuBar();
452 menu_bar->Append(file_menu, _T("&File"));
453
454 SetMenuBar( menu_bar );
455
456 CreateStatusBar(2);
457 int widths[] = { -1, 100 };
458 SetStatusWidths( 2, widths );
459
460 wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
461
462 // Setting an explicit size here is superfluous, it will be overridden
463 // by the sizer in any case.
464 m_canvas = new MyCanvas( this, -1, wxPoint(0,0), wxSize(100,100) );
465
466 // This is done with ScrollRate/VirtualSize in MyCanvas ctor now,
467 // both should produce identical results.
468 //m_canvas->SetScrollbars( 10, 10, 50, 100 );
469
470 topsizer->Add( m_canvas, 1, wxEXPAND );
471 topsizer->Add( new MyAutoScrollWindow( this ), 1, wxEXPAND );
472
473 wxSizer *sizerBtm = new wxBoxSizer(wxHORIZONTAL);
474 sizerBtm->Add( new MyScrolledWindowDumb(this), 1, wxEXPAND );
475 sizerBtm->Add( new MyScrolledWindowSmart(this), 1, wxEXPAND );
476 topsizer->Add( sizerBtm, 1, wxEXPAND );
477
478 SetSizer( topsizer );
479}
480
481void MyFrame::OnDeleteAll( wxCommandEvent &WXUNUSED(event) )
482{
483 m_canvas->DestroyChildren();
484}
485
486void MyFrame::OnInsertNew( wxCommandEvent &WXUNUSED(event) )
487{
488 (void)new wxButton( m_canvas, -1, _T("Hello"), wxPoint(100,100) );
489}
490
491void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
492{
493 Close( TRUE );
494}
495
496void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
497{
498 (void)wxMessageBox( _T("wxScroll demo\n"
499 "Robert Roebling (c) 1998\n"
500 "Autoscrolling examples\n"
501 "Ron Lee (c) 2002"),
502 _T("About wxScroll Demo"),
503 wxICON_INFORMATION | wxOK );
504}
505
506//-----------------------------------------------------------------------------
507// MyApp
508//-----------------------------------------------------------------------------
509
510bool MyApp::OnInit()
511{
512 wxFrame *frame = new MyFrame();
513 frame->Show( TRUE );
514
515 return TRUE;
516}
517
518// ----------------------------------------------------------------------------
519// MyScrolledWindowXXX
520// ----------------------------------------------------------------------------
521
522void MyScrolledWindowDumb::OnDraw(wxDC& dc)
523{
524 // this is useful to see which lines are redrawn
525 static size_t s_redrawCount = 0;
526 dc.SetTextForeground(s_redrawCount++ % 2 ? *wxRED : *wxBLUE);
527
528 wxCoord y = 0;
529 for ( size_t line = 0; line < m_nLines; line++ )
530 {
531 wxCoord yPhys;
532 CalcScrolledPosition(0, y, NULL, &yPhys);
533
534 dc.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"),
535 line, y, yPhys), 0, y);
536 y += m_hLine;
537 }
538}
539
540void MyScrolledWindowSmart::OnDraw(wxDC& dc)
541{
542 // this is useful to see which lines are redrawn
543 static size_t s_redrawCount = 0;
544 dc.SetTextForeground(s_redrawCount++ % 2 ? *wxRED : *wxBLUE);
545
546 // update region is always in device coords, translate to logical ones
547 wxRect rectUpdate = GetUpdateRegion().GetBox();
548 CalcUnscrolledPosition(rectUpdate.x, rectUpdate.y,
549 &rectUpdate.x, &rectUpdate.y);
550
551 size_t lineFrom = rectUpdate.y / m_hLine,
552 lineTo = rectUpdate.GetBottom() / m_hLine;
553
554 if ( lineTo > m_nLines - 1)
555 lineTo = m_nLines - 1;
556
557 wxCoord y = lineFrom*m_hLine;
558 for ( size_t line = lineFrom; line <= lineTo; line++ )
559 {
560 wxCoord yPhys;
561 CalcScrolledPosition(0, y, NULL, &yPhys);
562
563 dc.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"),
564 line, y, yPhys), 0, y);
565 y += m_hLine;
566 }
567}