]>
Commit | Line | Data |
---|---|---|
4e04f777 WS |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: scroll.cpp | |
3 | // Purpose: wxScrolledWindow sample | |
4 | // Author: Robert Roebling | |
5 | // Modified by: | |
6 | // Created: | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (C) 1998 Robert Roebling, 2002 Ron Lee, 2003 Matt Gregory | |
9 | // Licence: wxWindows license | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
fdd3ed7a RR |
11 | |
12 | // For compilers that support precompilation, includes "wx/wx.h". | |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
16 | #pragma hdrstop | |
17 | #endif | |
18 | ||
19 | #ifndef WX_PRECOMP | |
20 | #include "wx/wx.h" | |
21 | #endif | |
22 | ||
23 | #include "wx/image.h" | |
053f9cc1 | 24 | #include "wx/listctrl.h" |
ed673c6a RR |
25 | #include "wx/sizer.h" |
26 | #include "wx/log.h" | |
27 | ||
fdd3ed7a RR |
28 | |
29 | // derived classes | |
30 | ||
31 | class MyFrame; | |
32 | class MyApp; | |
33 | ||
34 | // MyCanvas | |
35 | ||
36 | class MyCanvas: public wxScrolledWindow | |
37 | { | |
38 | public: | |
8a73bf3d | 39 | MyCanvas() {} |
fdd3ed7a | 40 | MyCanvas( wxWindow *parent, wxWindowID, const wxPoint &pos, const wxSize &size ); |
925e9792 | 41 | ~MyCanvas(){}; |
fdd3ed7a | 42 | void OnPaint( wxPaintEvent &event ); |
307f16e8 | 43 | void OnQueryPosition( wxCommandEvent &event ); |
ed673c6a RR |
44 | void OnAddButton( wxCommandEvent &event ); |
45 | void OnDeleteButton( wxCommandEvent &event ); | |
46 | void OnMoveButton( wxCommandEvent &event ); | |
47 | void OnScrollWin( wxCommandEvent &event ); | |
4686e0f6 VZ |
48 | void OnMouseRightDown( wxMouseEvent &event ); |
49 | void OnMouseWheel( wxMouseEvent &event ); | |
ed673c6a RR |
50 | |
51 | wxButton *m_button; | |
fdd3ed7a RR |
52 | |
53 | DECLARE_DYNAMIC_CLASS(MyCanvas) | |
54 | DECLARE_EVENT_TABLE() | |
55 | }; | |
56 | ||
2b5f62a0 VZ |
57 | |
58 | // ---------------------------------------------------------------------------- | |
59 | // Autoscrolling example. | |
60 | // ---------------------------------------------------------------------------- | |
61 | ||
62 | // this class uses the 'virtual' size attribute along with an internal | |
63 | // sizer to automatically set up scrollbars as needed | |
64 | ||
65 | class MyAutoScrollWindow : public wxScrolledWindow | |
66 | { | |
67 | private: | |
68 | ||
69 | wxButton *m_button; | |
70 | ||
71 | public: | |
72 | ||
73 | MyAutoScrollWindow( wxWindow *parent ); | |
74 | ||
75 | void OnResizeClick( wxCommandEvent &WXUNUSED( event ) ); | |
76 | ||
77 | DECLARE_EVENT_TABLE() | |
78 | }; | |
79 | ||
80 | ||
8a73bf3d VZ |
81 | // ---------------------------------------------------------------------------- |
82 | // MyScrolledWindow classes: examples of wxScrolledWindow usage | |
83 | // ---------------------------------------------------------------------------- | |
84 | ||
85 | // base class for both of them | |
86 | class MyScrolledWindowBase : public wxScrolledWindow | |
87 | { | |
88 | public: | |
2b5f62a0 VZ |
89 | MyScrolledWindowBase(wxWindow *parent) |
90 | : wxScrolledWindow(parent) | |
91 | , m_nLines( 100 ) | |
8a73bf3d | 92 | { |
2b5f62a0 VZ |
93 | wxClientDC dc(this); |
94 | dc.GetTextExtent(_T("Line 17"), NULL, &m_hLine); | |
8a73bf3d VZ |
95 | } |
96 | ||
97 | protected: | |
8a73bf3d VZ |
98 | // the height of one line on screen |
99 | wxCoord m_hLine; | |
100 | ||
101 | // the number of lines we draw | |
102 | size_t m_nLines; | |
103 | }; | |
104 | ||
105 | // this class does "stupid" redrawing - it redraws everything each time | |
2b5f62a0 VZ |
106 | // and sets the scrollbar extent directly. |
107 | ||
8a73bf3d VZ |
108 | class MyScrolledWindowDumb : public MyScrolledWindowBase |
109 | { | |
110 | public: | |
2b5f62a0 VZ |
111 | MyScrolledWindowDumb(wxWindow *parent) : MyScrolledWindowBase(parent) |
112 | { | |
113 | // no horz scrolling | |
b62ca03d | 114 | SetScrollbars(0, m_hLine, 0, m_nLines + 1, 0, 0, true /* no refresh */); |
2b5f62a0 | 115 | } |
8a73bf3d VZ |
116 | |
117 | virtual void OnDraw(wxDC& dc); | |
118 | }; | |
119 | ||
120 | // this class does "smart" redrawing - only redraws the lines which must be | |
2b5f62a0 VZ |
121 | // redrawn and sets the scroll rate and virtual size to affect the |
122 | // scrollbars. | |
123 | // | |
124 | // Note that this class should produce identical results to the one above. | |
125 | ||
8a73bf3d VZ |
126 | class MyScrolledWindowSmart : public MyScrolledWindowBase |
127 | { | |
128 | public: | |
2b5f62a0 VZ |
129 | MyScrolledWindowSmart(wxWindow *parent) : MyScrolledWindowBase(parent) |
130 | { | |
131 | // no horz scrolling | |
132 | SetScrollRate( 0, m_hLine ); | |
4e04f777 | 133 | SetVirtualSize( wxDefaultCoord, ( m_nLines + 1 ) * m_hLine ); |
2b5f62a0 | 134 | } |
8a73bf3d VZ |
135 | |
136 | virtual void OnDraw(wxDC& dc); | |
137 | }; | |
138 | ||
57ac1a56 RN |
139 | // ---------------------------------------------------------------------------- |
140 | // MyAutoTimedScrollingWindow: implements a text viewer with simple blocksize | |
141 | // selection to test auto-scrolling functionality | |
142 | // ---------------------------------------------------------------------------- | |
143 | ||
144 | class MyAutoTimedScrollingWindow : public wxScrolledWindow | |
145 | { | |
146 | protected: // member data | |
147 | // test data variables | |
148 | static const wxChar* sm_testData; | |
149 | static const int sm_lineCnt; // line count | |
150 | static const int sm_lineLen; // line length in characters | |
151 | // sizes for graphical data | |
152 | wxCoord m_fontH, m_fontW; | |
153 | // selection tracking | |
154 | wxPoint m_selStart; // beginning of blockwise selection | |
155 | wxPoint m_cursor; // end of blockwise selection (mouse position) | |
156 | ||
157 | protected: // gui stuff | |
158 | wxFont m_font; | |
159 | ||
160 | public: // interface | |
161 | MyAutoTimedScrollingWindow( wxWindow* parent ); | |
162 | wxRect DeviceCoordsToGraphicalChars(wxRect updRect) const; | |
163 | wxPoint DeviceCoordsToGraphicalChars(wxPoint pos) const; | |
164 | wxPoint GraphicalCharToDeviceCoords(wxPoint pos) const; | |
165 | wxRect LogicalCoordsToGraphicalChars(wxRect updRect) const; | |
166 | wxPoint LogicalCoordsToGraphicalChars(wxPoint pos) const; | |
167 | wxPoint GraphicalCharToLogicalCoords(wxPoint pos) const; | |
168 | void MyRefresh(); | |
169 | bool IsSelected(int chX, int chY) const; | |
170 | static bool IsInside(int k, int bound1, int bound2); | |
171 | static wxRect DCNormalize(wxCoord x, wxCoord y, wxCoord w, wxCoord h); | |
172 | ||
173 | protected: // event stuff | |
57ac1a56 RN |
174 | void OnDraw(wxDC& dc); |
175 | void OnMouseLeftDown(wxMouseEvent& event); | |
176 | void OnMouseLeftUp(wxMouseEvent& event); | |
177 | void OnMouseMove(wxMouseEvent& event); | |
178 | void OnScroll(wxScrollWinEvent& event); | |
4686e0f6 VZ |
179 | |
180 | DECLARE_EVENT_TABLE() | |
57ac1a56 | 181 | }; |
2b5f62a0 | 182 | |
8a73bf3d | 183 | // ---------------------------------------------------------------------------- |
fdd3ed7a | 184 | // MyFrame |
8a73bf3d | 185 | // ---------------------------------------------------------------------------- |
fdd3ed7a RR |
186 | |
187 | class MyFrame: public wxFrame | |
188 | { | |
189 | public: | |
190 | MyFrame(); | |
191 | ||
192 | void OnAbout( wxCommandEvent &event ); | |
193 | void OnQuit( wxCommandEvent &event ); | |
8e217128 RR |
194 | void OnDeleteAll( wxCommandEvent &event ); |
195 | void OnInsertNew( wxCommandEvent &event ); | |
fdd3ed7a RR |
196 | |
197 | MyCanvas *m_canvas; | |
ed673c6a | 198 | wxTextCtrl *m_log; |
fdd3ed7a RR |
199 | |
200 | DECLARE_DYNAMIC_CLASS(MyFrame) | |
201 | DECLARE_EVENT_TABLE() | |
202 | }; | |
203 | ||
57ac1a56 | 204 | // ---------------------------------------------------------------------------- |
fdd3ed7a | 205 | // MyApp |
57ac1a56 | 206 | // ---------------------------------------------------------------------------- |
fdd3ed7a RR |
207 | |
208 | class MyApp: public wxApp | |
209 | { | |
210 | public: | |
211 | virtual bool OnInit(); | |
212 | }; | |
213 | ||
57ac1a56 RN |
214 | |
215 | // ---------------------------------------------------------------------------- | |
fdd3ed7a | 216 | // main program |
57ac1a56 | 217 | // ---------------------------------------------------------------------------- |
fdd3ed7a RR |
218 | |
219 | IMPLEMENT_APP(MyApp) | |
220 | ||
ed673c6a RR |
221 | // ids |
222 | ||
2b5f62a0 VZ |
223 | const long ID_ADDBUTTON = wxNewId(); |
224 | const long ID_DELBUTTON = wxNewId(); | |
225 | const long ID_MOVEBUTTON = wxNewId(); | |
226 | const long ID_SCROLLWIN = wxNewId(); | |
227 | const long ID_QUERYPOS = wxNewId(); | |
ed673c6a | 228 | |
2b5f62a0 | 229 | const long ID_NEWBUTTON = wxNewId(); |
ed673c6a | 230 | |
57ac1a56 | 231 | // ---------------------------------------------------------------------------- |
fdd3ed7a | 232 | // MyCanvas |
57ac1a56 | 233 | // ---------------------------------------------------------------------------- |
fdd3ed7a RR |
234 | |
235 | IMPLEMENT_DYNAMIC_CLASS(MyCanvas, wxScrolledWindow) | |
236 | ||
237 | BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) | |
307f16e8 | 238 | EVT_PAINT( MyCanvas::OnPaint) |
4686e0f6 VZ |
239 | EVT_RIGHT_DOWN( MyCanvas::OnMouseRightDown) |
240 | EVT_MOUSEWHEEL( MyCanvas::OnMouseWheel) | |
307f16e8 | 241 | EVT_BUTTON( ID_QUERYPOS, MyCanvas::OnQueryPosition) |
ed673c6a RR |
242 | EVT_BUTTON( ID_ADDBUTTON, MyCanvas::OnAddButton) |
243 | EVT_BUTTON( ID_DELBUTTON, MyCanvas::OnDeleteButton) | |
244 | EVT_BUTTON( ID_MOVEBUTTON, MyCanvas::OnMoveButton) | |
245 | EVT_BUTTON( ID_SCROLLWIN, MyCanvas::OnScrollWin) | |
fdd3ed7a RR |
246 | END_EVENT_TABLE() |
247 | ||
248 | MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id, | |
249 | const wxPoint &pos, const wxSize &size ) | |
2b5f62a0 | 250 | : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER | wxTAB_TRAVERSAL, _T("test canvas") ) |
fdd3ed7a | 251 | { |
2b5f62a0 VZ |
252 | SetScrollRate( 10, 10 ); |
253 | SetVirtualSize( 500, 1000 ); | |
254 | ||
255 | (void) new wxButton( this, ID_ADDBUTTON, _T("add button"), wxPoint(10,10) ); | |
256 | (void) new wxButton( this, ID_DELBUTTON, _T("del button"), wxPoint(10,40) ); | |
257 | (void) new wxButton( this, ID_MOVEBUTTON, _T("move button"), wxPoint(150,10) ); | |
258 | (void) new wxButton( this, ID_SCROLLWIN, _T("scroll win"), wxPoint(250,10) ); | |
ed673c6a | 259 | |
aa06a8fd DW |
260 | #if 0 |
261 | ||
fdd3ed7a RR |
262 | wxString choices[] = |
263 | { | |
264 | "This", | |
265 | "is one of my", | |
266 | "really", | |
267 | "wonderful", | |
268 | "examples." | |
269 | }; | |
aa06a8fd | 270 | |
307f16e8 | 271 | m_button = new wxButton( this, ID_QUERYPOS, "Query position", wxPoint(10,110) ); |
aa06a8fd | 272 | |
422d0ff0 | 273 | (void) new wxTextCtrl( this, wxID_ANY, "wxTextCtrl", wxPoint(10,150), wxSize(80,wxDefaultCoord) ); |
aa06a8fd | 274 | |
b62ca03d | 275 | (void) new wxRadioButton( this, wxID_ANY, "Disable", wxPoint(10,190) ); |
aa06a8fd | 276 | |
b62ca03d | 277 | (void) new wxComboBox( this, wxID_ANY, "This", wxPoint(10,230), wxDefaultSize, 5, choices ); |
aa06a8fd | 278 | |
b62ca03d | 279 | (void) new wxRadioBox( this, wxID_ANY, "This", wxPoint(10,310), wxDefaultSize, 5, choices, 2, wxRA_SPECIFY_COLS ); |
053f9cc1 | 280 | |
b62ca03d | 281 | (void) new wxRadioBox( this, wxID_ANY, "This", wxPoint(10,440), wxDefaultSize, 5, choices, 2, wxRA_SPECIFY_ROWS ); |
e9158f7d | 282 | |
ed673c6a | 283 | wxListCtrl *m_listCtrl = new wxListCtrl( |
b62ca03d | 284 | this, wxID_ANY, wxPoint(200, 110), wxSize(180, 120), |
8a73bf3d | 285 | wxLC_REPORT | wxSIMPLE_BORDER | wxLC_SINGLE_SEL ); |
053f9cc1 | 286 | |
ed673c6a RR |
287 | m_listCtrl->InsertColumn(0, "First", wxLIST_FORMAT_LEFT, 90); |
288 | m_listCtrl->InsertColumn(1, "Last", wxLIST_FORMAT_LEFT, 90); | |
053f9cc1 | 289 | |
ed673c6a RR |
290 | for ( int i=0; i < 30; i++) |
291 | { | |
292 | char buf[20]; | |
293 | sprintf(buf, "Item %d", i); | |
294 | m_listCtrl->InsertItem(i, buf); | |
295 | } | |
296 | m_listCtrl->SetItemState( 3, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); | |
053f9cc1 | 297 | |
b62ca03d | 298 | (void) new wxListBox( this, wxID_ANY, wxPoint(260,280), wxSize(120,120), 5, choices, wxLB_ALWAYS_SB ); |
5e014a0c | 299 | |
aa06a8fd DW |
300 | #endif |
301 | ||
b62ca03d | 302 | wxPanel *test = new wxPanel( this, wxID_ANY, wxPoint(10, 110), wxSize(130,50), wxSIMPLE_BORDER | wxTAB_TRAVERSAL ); |
a60b1f5d | 303 | test->SetBackgroundColour( wxT("WHEAT") ); |
aa06a8fd DW |
304 | |
305 | #if 0 | |
306 | ||
b62ca03d | 307 | wxButton *test2 = new wxButton( test, wxID_ANY, "Hallo", wxPoint(10,10) ); |
aa06a8fd | 308 | |
b62ca03d | 309 | test = new wxPanel( this, wxID_ANY, wxPoint(160, 530), wxSize(130,120), wxSUNKEN_BORDER | wxTAB_TRAVERSAL ); |
a60b1f5d | 310 | test->SetBackgroundColour( wxT("WHEAT") ); |
ed673c6a | 311 | test->SetCursor( wxCursor( wxCURSOR_NO_ENTRY ) ); |
b62ca03d | 312 | test2 = new wxButton( test, wxID_ANY, "Hallo", wxPoint(10,10) ); |
ed673c6a | 313 | test2->SetCursor( wxCursor( wxCURSOR_PENCIL ) ); |
aa06a8fd | 314 | |
b62ca03d | 315 | test = new wxPanel( this, wxID_ANY, wxPoint(310, 530), wxSize(130,120), wxRAISED_BORDER | wxTAB_TRAVERSAL ); |
a60b1f5d | 316 | test->SetBackgroundColour( wxT("WHEAT") ); |
ed673c6a | 317 | test->SetCursor( wxCursor( wxCURSOR_PENCIL ) ); |
b62ca03d | 318 | test2 = new wxButton( test, wxID_ANY, "Hallo", wxPoint(10,10) ); |
ed673c6a | 319 | test2->SetCursor( wxCursor( wxCURSOR_NO_ENTRY ) ); |
5e014a0c | 320 | |
aa06a8fd DW |
321 | #endif |
322 | ||
a60b1f5d | 323 | SetBackgroundColour( wxT("BLUE") ); |
aa06a8fd | 324 | |
ed673c6a | 325 | SetCursor( wxCursor( wxCURSOR_IBEAM ) ); |
fdd3ed7a RR |
326 | } |
327 | ||
4686e0f6 | 328 | void MyCanvas::OnMouseRightDown( wxMouseEvent &event ) |
bf0c00c6 | 329 | { |
4686e0f6 VZ |
330 | wxPoint pt( event.GetPosition() ); |
331 | int x,y; | |
332 | CalcUnscrolledPosition( pt.x, pt.y, &x, &y ); | |
333 | wxLogMessage( wxT("Mouse down event at: %d %d, scrolled: %d %d"), pt.x, pt.y, x, y ); | |
334 | } | |
f6bcfd97 | 335 | |
4686e0f6 VZ |
336 | void MyCanvas::OnMouseWheel( wxMouseEvent &event ) |
337 | { | |
338 | wxPoint pt( event.GetPosition() ); | |
339 | int x,y; | |
340 | CalcUnscrolledPosition( pt.x, pt.y, &x, &y ); | |
341 | wxLogMessage( wxT("Mouse wheel event at: %d %d, scrolled: %d %d\n") | |
342 | wxT("Rotation: %d, delta = %d"), | |
343 | pt.x, pt.y, x, y, | |
344 | event.GetWheelRotation(), event.GetWheelDelta() ); | |
345 | ||
346 | event.Skip(); | |
bf0c00c6 RR |
347 | } |
348 | ||
349 | void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) | |
350 | { | |
351 | wxPaintDC dc( this ); | |
352 | PrepareDC( dc ); | |
353 | ||
2b5f62a0 | 354 | dc.DrawText( _T("Press mouse button to test calculations!"), 160, 50 ); |
bf0c00c6 | 355 | |
2b5f62a0 | 356 | dc.DrawText( _T("Some text"), 140, 140 ); |
aa06a8fd | 357 | |
bf0c00c6 RR |
358 | dc.DrawRectangle( 100, 160, 200, 200 ); |
359 | } | |
360 | ||
307f16e8 RR |
361 | void MyCanvas::OnQueryPosition( wxCommandEvent &WXUNUSED(event) ) |
362 | { | |
363 | wxPoint pt( m_button->GetPosition() ); | |
4693b20c | 364 | wxLogMessage( wxT("Position of \"Query position\" is %d %d"), pt.x, pt.y ); |
bf0c00c6 | 365 | pt = ClientToScreen( pt ); |
4693b20c | 366 | wxLogMessage( wxT("Position of \"Query position\" on screen is %d %d"), pt.x, pt.y ); |
307f16e8 RR |
367 | } |
368 | ||
ed673c6a RR |
369 | void MyCanvas::OnAddButton( wxCommandEvent &WXUNUSED(event) ) |
370 | { | |
4693b20c | 371 | wxLogMessage( wxT("Inserting button at position 10,70...") ); |
2b5f62a0 | 372 | wxButton *button = new wxButton( this, ID_NEWBUTTON, wxT("new button"), wxPoint(10,70), wxSize(80,25) ); |
bf0c00c6 | 373 | wxPoint pt( button->GetPosition() ); |
4693b20c | 374 | wxLogMessage( wxT("-> Position after inserting %d %d"), pt.x, pt.y ); |
ed673c6a RR |
375 | } |
376 | ||
256b8649 | 377 | void MyCanvas::OnDeleteButton( wxCommandEvent &WXUNUSED(event) ) |
ed673c6a | 378 | { |
4693b20c | 379 | wxLogMessage( wxT("Deleting button inserted with \"Add button\"...") ); |
ed673c6a RR |
380 | wxWindow *win = FindWindow( ID_NEWBUTTON ); |
381 | if (win) | |
382 | win->Destroy(); | |
383 | else | |
4693b20c | 384 | wxLogMessage( wxT("-> No window with id = ID_NEWBUTTON found.") ); |
ed673c6a RR |
385 | } |
386 | ||
387 | void MyCanvas::OnMoveButton( wxCommandEvent &event ) | |
388 | { | |
4693b20c | 389 | wxLogMessage( wxT("Moving button 10 pixels downward..") ); |
ed673c6a | 390 | wxWindow *win = FindWindow( event.GetId() ); |
bf0c00c6 | 391 | wxPoint pt( win->GetPosition() ); |
4693b20c | 392 | wxLogMessage( wxT("-> Position before move is %d %d"), pt.x, pt.y ); |
422d0ff0 | 393 | win->Move( wxDefaultCoord, pt.y + 10 ); |
bf0c00c6 | 394 | pt = win->GetPosition(); |
4693b20c | 395 | wxLogMessage( wxT("-> Position after move is %d %d"), pt.x, pt.y ); |
ed673c6a RR |
396 | } |
397 | ||
398 | void MyCanvas::OnScrollWin( wxCommandEvent &WXUNUSED(event) ) | |
399 | { | |
4693b20c | 400 | wxLogMessage( wxT("Scrolling 2 units up.\nThe white square and the controls should move equally!") ); |
ed673c6a | 401 | int x,y; |
8073eb40 | 402 | GetViewStart( &x, &y ); |
4e04f777 | 403 | Scroll( wxDefaultCoord, y+2 ); |
ed673c6a RR |
404 | } |
405 | ||
57ac1a56 | 406 | // ---------------------------------------------------------------------------- |
2b5f62a0 | 407 | // MyAutoScrollWindow |
57ac1a56 | 408 | // ---------------------------------------------------------------------------- |
2b5f62a0 VZ |
409 | |
410 | const long ID_RESIZEBUTTON = wxNewId(); | |
411 | const wxSize SMALL_BUTTON( 100, 50 ); | |
412 | const wxSize LARGE_BUTTON( 300, 100 ); | |
413 | ||
414 | BEGIN_EVENT_TABLE( MyAutoScrollWindow, wxScrolledWindow) | |
415 | EVT_BUTTON( ID_RESIZEBUTTON, MyAutoScrollWindow::OnResizeClick) | |
416 | END_EVENT_TABLE() | |
417 | ||
418 | MyAutoScrollWindow::MyAutoScrollWindow( wxWindow *parent ) | |
3fa5153e RR |
419 | : wxScrolledWindow( parent, -1, wxDefaultPosition, wxDefaultSize, |
420 | wxSUNKEN_BORDER|wxScrolledWindowStyle ) | |
2b5f62a0 VZ |
421 | { |
422 | SetBackgroundColour( wxT("GREEN") ); | |
423 | ||
424 | // Set the rate we'd like for scrolling. | |
425 | ||
426 | SetScrollRate( 5, 5 ); | |
427 | ||
428 | // Populate a sizer with a 'resizing' button and some | |
429 | // other static decoration | |
430 | ||
431 | wxFlexGridSizer *innersizer = new wxFlexGridSizer( 2, 2 ); | |
432 | ||
433 | m_button = new wxButton( this, | |
434 | ID_RESIZEBUTTON, | |
435 | _T("Press me"), | |
436 | wxDefaultPosition, | |
437 | SMALL_BUTTON ); | |
438 | ||
439 | // We need to do this here, because wxADJUST_MINSIZE below | |
440 | // will cause the initial size to be ignored for Best/Min size. | |
441 | // It would be nice to fix the sizers to handle this a little | |
442 | // more cleanly. | |
443 | ||
444 | m_button->SetSizeHints( SMALL_BUTTON.GetWidth(), SMALL_BUTTON.GetHeight() ); | |
445 | ||
446 | innersizer->Add( m_button, | |
447 | 0, | |
448 | wxALIGN_CENTER | wxALL | wxADJUST_MINSIZE, | |
449 | 20 ); | |
450 | ||
b62ca03d | 451 | innersizer->Add( new wxStaticText( this, wxID_ANY, _T("This is just") ), |
2b5f62a0 VZ |
452 | 0, |
453 | wxALIGN_CENTER ); | |
454 | ||
b62ca03d | 455 | innersizer->Add( new wxStaticText( this, wxID_ANY, _T("some decoration") ), |
2b5f62a0 VZ |
456 | 0, |
457 | wxALIGN_CENTER ); | |
458 | ||
b62ca03d | 459 | innersizer->Add( new wxStaticText( this, wxID_ANY, _T("for you to scroll...") ), |
2b5f62a0 VZ |
460 | 0, |
461 | wxALIGN_CENTER ); | |
462 | ||
463 | // Then use the sizer to set the scrolled region size. | |
464 | ||
465 | SetSizer( innersizer ); | |
466 | } | |
467 | ||
468 | void MyAutoScrollWindow::OnResizeClick( wxCommandEvent &WXUNUSED( event ) ) | |
469 | { | |
470 | // Arbitrarily resize the button to change the minimum size of | |
471 | // the (scrolled) sizer. | |
472 | ||
473 | if( m_button->GetSize() == SMALL_BUTTON ) | |
474 | m_button->SetSizeHints( LARGE_BUTTON.GetWidth(), LARGE_BUTTON.GetHeight() ); | |
475 | else | |
476 | m_button->SetSizeHints( SMALL_BUTTON.GetWidth(), SMALL_BUTTON.GetHeight() ); | |
477 | ||
478 | // Force update layout and scrollbars, since nothing we do here | |
479 | // necessarily generates a size event which would do it for us. | |
480 | ||
481 | FitInside(); | |
482 | } | |
483 | ||
57ac1a56 | 484 | // ---------------------------------------------------------------------------- |
fdd3ed7a | 485 | // MyFrame |
57ac1a56 | 486 | // ---------------------------------------------------------------------------- |
fdd3ed7a | 487 | |
91b07357 JS |
488 | const long ID_QUIT = wxID_EXIT; |
489 | const long ID_ABOUT = wxID_ABOUT; | |
490 | const long ID_DELETE_ALL = 100; | |
491 | const long ID_INSERT_NEW = 101; | |
fdd3ed7a RR |
492 | |
493 | IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) | |
494 | ||
495 | BEGIN_EVENT_TABLE(MyFrame,wxFrame) | |
8e217128 RR |
496 | EVT_MENU (ID_DELETE_ALL, MyFrame::OnDeleteAll) |
497 | EVT_MENU (ID_INSERT_NEW, MyFrame::OnInsertNew) | |
fdd3ed7a RR |
498 | EVT_MENU (ID_ABOUT, MyFrame::OnAbout) |
499 | EVT_MENU (ID_QUIT, MyFrame::OnQuit) | |
500 | END_EVENT_TABLE() | |
501 | ||
502 | MyFrame::MyFrame() | |
b62ca03d | 503 | : wxFrame( (wxFrame *)NULL, wxID_ANY, _T("wxScrolledWindow sample"), |
57ac1a56 | 504 | wxPoint(20,20), wxSize(800,500) ) |
fdd3ed7a | 505 | { |
ed673c6a | 506 | wxMenu *file_menu = new wxMenu(); |
2b5f62a0 VZ |
507 | file_menu->Append( ID_DELETE_ALL, _T("Delete all")); |
508 | file_menu->Append( ID_INSERT_NEW, _T("Insert new")); | |
509 | file_menu->Append( ID_ABOUT, _T("&About..")); | |
510 | file_menu->Append( ID_QUIT, _T("E&xit\tAlt-X")); | |
fdd3ed7a | 511 | |
ed673c6a | 512 | wxMenuBar *menu_bar = new wxMenuBar(); |
2b5f62a0 | 513 | menu_bar->Append(file_menu, _T("&File")); |
fdd3ed7a | 514 | |
ed673c6a | 515 | SetMenuBar( menu_bar ); |
fdd3ed7a | 516 | |
8520f137 | 517 | #if wxUSE_STATUSBAR |
ed673c6a RR |
518 | CreateStatusBar(2); |
519 | int widths[] = { -1, 100 }; | |
520 | SetStatusWidths( 2, widths ); | |
8520f137 | 521 | #endif // wxUSE_STATUSBAR |
fdd3ed7a | 522 | |
57ac1a56 RN |
523 | wxBoxSizer *topsizer = new wxBoxSizer( wxHORIZONTAL ); |
524 | // subsizer splits topsizer down the middle | |
525 | wxBoxSizer *subsizer = new wxBoxSizer( wxVERTICAL ); | |
2b5f62a0 VZ |
526 | |
527 | // Setting an explicit size here is superfluous, it will be overridden | |
528 | // by the sizer in any case. | |
b62ca03d | 529 | m_canvas = new MyCanvas( this, wxID_ANY, wxPoint(0,0), wxSize(100,100) ); |
8a73bf3d | 530 | |
2b5f62a0 VZ |
531 | // This is done with ScrollRate/VirtualSize in MyCanvas ctor now, |
532 | // both should produce identical results. | |
533 | //m_canvas->SetScrollbars( 10, 10, 50, 100 ); | |
4e04f777 | 534 | |
57ac1a56 RN |
535 | subsizer->Add( m_canvas, 1, wxEXPAND ); |
536 | subsizer->Add( new MyAutoScrollWindow( this ), 1, wxEXPAND ); | |
8a73bf3d VZ |
537 | |
538 | wxSizer *sizerBtm = new wxBoxSizer(wxHORIZONTAL); | |
539 | sizerBtm->Add( new MyScrolledWindowDumb(this), 1, wxEXPAND ); | |
540 | sizerBtm->Add( new MyScrolledWindowSmart(this), 1, wxEXPAND ); | |
57ac1a56 RN |
541 | subsizer->Add( sizerBtm, 1, wxEXPAND ); |
542 | ||
543 | topsizer->Add( subsizer, 1, wxEXPAND ); | |
544 | topsizer->Add( new MyAutoTimedScrollingWindow( this ), 1, wxEXPAND ); | |
ed673c6a | 545 | |
ed673c6a | 546 | SetSizer( topsizer ); |
fdd3ed7a RR |
547 | } |
548 | ||
8e217128 RR |
549 | void MyFrame::OnDeleteAll( wxCommandEvent &WXUNUSED(event) ) |
550 | { | |
551 | m_canvas->DestroyChildren(); | |
552 | } | |
553 | ||
554 | void MyFrame::OnInsertNew( wxCommandEvent &WXUNUSED(event) ) | |
555 | { | |
b62ca03d | 556 | (void)new wxButton( m_canvas, wxID_ANY, _T("Hello"), wxPoint(100,100) ); |
8e217128 RR |
557 | } |
558 | ||
fdd3ed7a RR |
559 | void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) ) |
560 | { | |
b62ca03d | 561 | Close( true ); |
fdd3ed7a RR |
562 | } |
563 | ||
564 | void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) ) | |
565 | { | |
57ac1a56 RN |
566 | (void)wxMessageBox( _T("wxScroll demo\n") |
567 | _T("Robert Roebling (c) 1998\n") | |
568 | _T("Autoscrolling examples\n") | |
569 | _T("Ron Lee (c) 2002\n") | |
570 | _T("Auto-timed-scrolling example\n") | |
571 | _T("Matt Gregory (c) 2003\n"), | |
572 | _T("About wxScroll Demo"), | |
573 | wxICON_INFORMATION | wxOK ); | |
fdd3ed7a RR |
574 | } |
575 | ||
576 | //----------------------------------------------------------------------------- | |
577 | // MyApp | |
578 | //----------------------------------------------------------------------------- | |
579 | ||
580 | bool MyApp::OnInit() | |
581 | { | |
582 | wxFrame *frame = new MyFrame(); | |
b62ca03d | 583 | frame->Show( true ); |
fdd3ed7a | 584 | |
b62ca03d | 585 | return true; |
fdd3ed7a RR |
586 | } |
587 | ||
8a73bf3d VZ |
588 | // ---------------------------------------------------------------------------- |
589 | // MyScrolledWindowXXX | |
590 | // ---------------------------------------------------------------------------- | |
591 | ||
8a73bf3d VZ |
592 | void MyScrolledWindowDumb::OnDraw(wxDC& dc) |
593 | { | |
594 | // this is useful to see which lines are redrawn | |
595 | static size_t s_redrawCount = 0; | |
596 | dc.SetTextForeground(s_redrawCount++ % 2 ? *wxRED : *wxBLUE); | |
597 | ||
598 | wxCoord y = 0; | |
599 | for ( size_t line = 0; line < m_nLines; line++ ) | |
600 | { | |
601 | wxCoord yPhys; | |
602 | CalcScrolledPosition(0, y, NULL, &yPhys); | |
603 | ||
604 | dc.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"), | |
605 | line, y, yPhys), 0, y); | |
606 | y += m_hLine; | |
607 | } | |
608 | } | |
609 | ||
610 | void MyScrolledWindowSmart::OnDraw(wxDC& dc) | |
611 | { | |
612 | // this is useful to see which lines are redrawn | |
613 | static size_t s_redrawCount = 0; | |
614 | dc.SetTextForeground(s_redrawCount++ % 2 ? *wxRED : *wxBLUE); | |
615 | ||
616 | // update region is always in device coords, translate to logical ones | |
617 | wxRect rectUpdate = GetUpdateRegion().GetBox(); | |
618 | CalcUnscrolledPosition(rectUpdate.x, rectUpdate.y, | |
619 | &rectUpdate.x, &rectUpdate.y); | |
620 | ||
621 | size_t lineFrom = rectUpdate.y / m_hLine, | |
622 | lineTo = rectUpdate.GetBottom() / m_hLine; | |
623 | ||
624 | if ( lineTo > m_nLines - 1) | |
625 | lineTo = m_nLines - 1; | |
626 | ||
627 | wxCoord y = lineFrom*m_hLine; | |
628 | for ( size_t line = lineFrom; line <= lineTo; line++ ) | |
629 | { | |
630 | wxCoord yPhys; | |
631 | CalcScrolledPosition(0, y, NULL, &yPhys); | |
632 | ||
633 | dc.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"), | |
634 | line, y, yPhys), 0, y); | |
635 | y += m_hLine; | |
636 | } | |
637 | } | |
57ac1a56 RN |
638 | |
639 | // ---------------------------------------------------------------------------- | |
640 | // MyAutoTimedScrollingWindow | |
641 | // ---------------------------------------------------------------------------- | |
642 | ||
643 | BEGIN_EVENT_TABLE(MyAutoTimedScrollingWindow, wxScrolledWindow) | |
4ba64bde RR |
644 | EVT_LEFT_DOWN(MyAutoTimedScrollingWindow::OnMouseLeftDown) |
645 | EVT_LEFT_UP(MyAutoTimedScrollingWindow::OnMouseLeftUp) | |
646 | EVT_MOTION(MyAutoTimedScrollingWindow::OnMouseMove) | |
647 | EVT_SCROLLWIN(MyAutoTimedScrollingWindow::OnScroll) | |
57ac1a56 RN |
648 | END_EVENT_TABLE() |
649 | ||
650 | MyAutoTimedScrollingWindow::MyAutoTimedScrollingWindow(wxWindow* parent) | |
4e04f777 | 651 | : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize |
57ac1a56 RN |
652 | //, wxSUNKEN_BORDER) // can't seem to do it this way |
653 | , wxVSCROLL | wxHSCROLL | wxSUNKEN_BORDER) | |
654 | , m_selStart(-1, -1), m_cursor(-1, -1) | |
655 | , m_font(9, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL | |
656 | , wxFONTWEIGHT_NORMAL) | |
657 | { | |
658 | wxClientDC dc(this); | |
659 | // query dc for text size | |
660 | dc.SetFont(m_font); | |
661 | dc.GetTextExtent(wxString(_T("A")), &m_fontW, &m_fontH); | |
662 | // set up the virtual window | |
663 | SetScrollbars(m_fontW, m_fontH, sm_lineLen, sm_lineCnt); | |
664 | } | |
665 | ||
666 | wxRect MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars | |
667 | (wxRect updRect) const | |
668 | { | |
669 | wxPoint pos(updRect.GetPosition()); | |
670 | pos = DeviceCoordsToGraphicalChars(pos); | |
671 | updRect.x = pos.x; | |
672 | updRect.y = pos.y; | |
673 | updRect.width /= m_fontW; | |
674 | updRect.height /= m_fontH; | |
675 | // the *CoordsToGraphicalChars() funcs round down to upper-left corner, | |
676 | // so an off-by-one correction is needed | |
677 | ++updRect.width; // kludge | |
678 | ++updRect.height; // kludge | |
679 | return updRect; | |
680 | } | |
681 | ||
682 | wxPoint MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars | |
683 | (wxPoint pos) const | |
684 | { | |
685 | pos.x /= m_fontW; | |
686 | pos.y /= m_fontH; | |
687 | int vX, vY; | |
688 | GetViewStart(&vX, &vY); | |
689 | pos.x += vX; | |
690 | pos.y += vY; | |
691 | return pos; | |
692 | } | |
693 | ||
694 | wxPoint MyAutoTimedScrollingWindow::GraphicalCharToDeviceCoords | |
695 | (wxPoint pos) const | |
696 | { | |
697 | int vX, vY; | |
698 | GetViewStart(&vX, &vY); | |
699 | pos.x -= vX; | |
700 | pos.y -= vY; | |
701 | pos.x *= m_fontW; | |
702 | pos.y *= m_fontH; | |
703 | return pos; | |
704 | } | |
705 | ||
706 | wxRect MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars | |
707 | (wxRect updRect) const | |
708 | { | |
709 | wxPoint pos(updRect.GetPosition()); | |
710 | pos = LogicalCoordsToGraphicalChars(pos); | |
711 | updRect.x = pos.x; | |
712 | updRect.y = pos.y; | |
713 | updRect.width /= m_fontW; | |
714 | updRect.height /= m_fontH; | |
715 | // the *CoordsToGraphicalChars() funcs round down to upper-left corner, | |
716 | // so an off-by-one correction is needed | |
717 | ++updRect.width; // kludge | |
718 | ++updRect.height; // kludge | |
719 | return updRect; | |
720 | } | |
721 | ||
722 | wxPoint MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars | |
723 | (wxPoint pos) const | |
724 | { | |
725 | pos.x /= m_fontW; | |
726 | pos.y /= m_fontH; | |
727 | return pos; | |
728 | } | |
729 | ||
730 | wxPoint MyAutoTimedScrollingWindow::GraphicalCharToLogicalCoords | |
731 | (wxPoint pos) const | |
732 | { | |
733 | pos.x *= m_fontW; | |
734 | pos.y *= m_fontH; | |
735 | return pos; | |
736 | } | |
737 | ||
738 | void MyAutoTimedScrollingWindow::MyRefresh() | |
739 | { | |
740 | static wxPoint lastSelStart(-1, -1), lastCursor(-1, -1); | |
741 | // refresh last selected area (to deselect previously selected text) | |
742 | wxRect lastUpdRect( | |
743 | GraphicalCharToDeviceCoords(lastSelStart), | |
744 | GraphicalCharToDeviceCoords(lastCursor) | |
745 | ); | |
746 | // off-by-one corrections, necessary because it's not possible to know | |
747 | // when to round up until rect is normalized by lastUpdRect constructor | |
748 | lastUpdRect.width += m_fontW; // kludge | |
749 | lastUpdRect.height += m_fontH; // kludge | |
750 | // refresh currently selected (to select previously unselected text) | |
751 | wxRect updRect( | |
752 | GraphicalCharToDeviceCoords(m_selStart), | |
753 | GraphicalCharToDeviceCoords(m_cursor) | |
754 | ); | |
755 | // off-by-one corrections | |
756 | updRect.width += m_fontW; // kludge | |
757 | updRect.height += m_fontH; // kludge | |
758 | // find necessary refresh areas | |
759 | wxCoord rx = lastUpdRect.x; | |
760 | wxCoord ry = lastUpdRect.y; | |
761 | wxCoord rw = updRect.x - lastUpdRect.x; | |
762 | wxCoord rh = lastUpdRect.height; | |
763 | if (rw && rh) { | |
764 | RefreshRect(DCNormalize(rx, ry, rw, rh)); | |
765 | } | |
766 | rx = updRect.x; | |
767 | ry = updRect.y + updRect.height; | |
768 | rw= updRect.width; | |
769 | rh = (lastUpdRect.y + lastUpdRect.height) - (updRect.y + updRect.height); | |
770 | if (rw && rh) { | |
771 | RefreshRect(DCNormalize(rx, ry, rw, rh)); | |
772 | } | |
773 | rx = updRect.x + updRect.width; | |
774 | ry = lastUpdRect.y; | |
775 | rw = (lastUpdRect.x + lastUpdRect.width) - (updRect.x + updRect.width); | |
776 | rh = lastUpdRect.height; | |
777 | if (rw && rh) { | |
778 | RefreshRect(DCNormalize(rx, ry, rw, rh)); | |
779 | } | |
780 | rx = updRect.x; | |
781 | ry = lastUpdRect.y; | |
782 | rw = updRect.width; | |
783 | rh = updRect.y - lastUpdRect.y; | |
784 | if (rw && rh) { | |
785 | RefreshRect(DCNormalize(rx, ry, rw, rh)); | |
786 | } | |
787 | // update last | |
788 | lastSelStart = m_selStart; | |
789 | lastCursor = m_cursor; | |
790 | } | |
791 | ||
792 | bool MyAutoTimedScrollingWindow::IsSelected(int chX, int chY) const | |
793 | { | |
794 | if (IsInside(chX, m_selStart.x, m_cursor.x) | |
795 | && IsInside(chY, m_selStart.y, m_cursor.y)) { | |
4e04f777 | 796 | return true; |
57ac1a56 | 797 | } |
4e04f777 | 798 | return false; |
57ac1a56 RN |
799 | } |
800 | ||
801 | bool MyAutoTimedScrollingWindow::IsInside(int k, int bound1, int bound2) | |
802 | { | |
803 | if ((k >= bound1 && k <= bound2) || (k >= bound2 && k <= bound1)) { | |
4e04f777 | 804 | return true; |
57ac1a56 | 805 | } |
4e04f777 | 806 | return false; |
57ac1a56 RN |
807 | } |
808 | ||
809 | wxRect MyAutoTimedScrollingWindow::DCNormalize(wxCoord x, wxCoord y | |
810 | , wxCoord w, wxCoord h) | |
811 | { | |
812 | // this is needed to get rid of the graphical remnants from the selection | |
813 | // I think it's because DrawRectangle() excludes a pixel in either direction | |
814 | const int kludge = 1; | |
815 | // make (x, y) the top-left corner | |
816 | if (w < 0) { | |
817 | w = -w + kludge; | |
818 | x -= w; | |
819 | } else { | |
820 | x -= kludge; | |
821 | w += kludge; | |
822 | } | |
823 | if (h < 0) { | |
824 | h = -h + kludge; | |
825 | y -= h; | |
826 | } else { | |
827 | y -= kludge; | |
828 | h += kludge; | |
829 | } | |
830 | return wxRect(x, y, w, h); | |
831 | } | |
832 | ||
833 | void MyAutoTimedScrollingWindow::OnDraw(wxDC& dc) | |
834 | { | |
835 | dc.SetFont(m_font); | |
836 | wxBrush normBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) | |
837 | , wxSOLID); | |
838 | wxBrush selBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT) | |
839 | , wxSOLID); | |
840 | dc.SetPen(*wxTRANSPARENT_PEN); | |
4e04f777 WS |
841 | wxString str = sm_testData; |
842 | ||
57ac1a56 RN |
843 | // draw the characters |
844 | // 1. for each update region | |
845 | for (wxRegionIterator upd(GetUpdateRegion()); upd; ++upd) { | |
57ac1a56 RN |
846 | wxRect updRect = upd.GetRect(); |
847 | wxRect updRectInGChars(DeviceCoordsToGraphicalChars(updRect)); | |
848 | // 2. for each row of chars in the update region | |
849 | for (int chY = updRectInGChars.y | |
850 | ; chY <= updRectInGChars.y + updRectInGChars.height; ++chY) { | |
851 | // 3. for each character in the row | |
852 | for (int chX = updRectInGChars.x | |
853 | ; chX <= updRectInGChars.x + updRectInGChars.width | |
854 | ; ++chX) { | |
855 | // 4. set up dc | |
856 | if (IsSelected(chX, chY)) { | |
857 | dc.SetBrush(selBrush); | |
858 | dc.SetTextForeground( wxSystemSettings::GetColour | |
859 | (wxSYS_COLOUR_HIGHLIGHTTEXT)); | |
860 | } else { | |
861 | dc.SetBrush(normBrush); | |
862 | dc.SetTextForeground( wxSystemSettings::GetColour | |
863 | (wxSYS_COLOUR_WINDOWTEXT)); | |
864 | } | |
865 | // 5. find position info | |
866 | wxPoint charPos = GraphicalCharToLogicalCoords(wxPoint | |
867 | (chX, chY)); | |
868 | // 6. draw! | |
869 | dc.DrawRectangle(charPos.x, charPos.y, m_fontW, m_fontH); | |
4e04f777 WS |
870 | size_t charIndex = chY * sm_lineLen + chX; |
871 | if (chY < sm_lineCnt && | |
872 | chX < sm_lineLen && | |
873 | charIndex < str.Length()) | |
874 | { | |
875 | dc.DrawText(str.Mid(charIndex,1), | |
876 | charPos.x, charPos.y); | |
57ac1a56 RN |
877 | } |
878 | } | |
879 | } | |
880 | } | |
881 | } | |
882 | ||
883 | void MyAutoTimedScrollingWindow::OnMouseLeftDown(wxMouseEvent& event) | |
884 | { | |
885 | // initial press of mouse button sets the beginning of the selection | |
886 | m_selStart = DeviceCoordsToGraphicalChars(event.GetPosition()); | |
887 | // set the cursor to the same position | |
888 | m_cursor = m_selStart; | |
889 | // draw/erase selection | |
890 | MyRefresh(); | |
891 | } | |
892 | ||
893 | void MyAutoTimedScrollingWindow::OnMouseLeftUp(wxMouseEvent& WXUNUSED(event)) | |
894 | { | |
895 | // this test is necessary | |
896 | if (HasCapture()) { | |
897 | // uncapture mouse | |
898 | ReleaseMouse(); | |
899 | } | |
900 | } | |
901 | ||
902 | void MyAutoTimedScrollingWindow::OnMouseMove(wxMouseEvent& event) | |
903 | { | |
904 | // if user is dragging | |
905 | if (event.Dragging() && event.LeftIsDown()) { | |
906 | // set the new cursor position | |
907 | m_cursor = DeviceCoordsToGraphicalChars(event.GetPosition()); | |
908 | // draw/erase selection | |
909 | MyRefresh(); | |
910 | // capture mouse to activate auto-scrolling | |
911 | if (!HasCapture()) { | |
912 | CaptureMouse(); | |
913 | } | |
914 | } | |
915 | } | |
916 | ||
917 | void MyAutoTimedScrollingWindow::OnScroll(wxScrollWinEvent& event) | |
918 | { | |
919 | // need to move the cursor when autoscrolling | |
920 | // FIXME: the cursor also moves when the scrollbar arrows are clicked | |
921 | if (HasCapture()) { | |
922 | if (event.GetOrientation() == wxHORIZONTAL) { | |
687706f5 | 923 | if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP) { |
57ac1a56 | 924 | --m_cursor.x; |
687706f5 | 925 | } else if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN) { |
57ac1a56 RN |
926 | ++m_cursor.x; |
927 | } | |
928 | } else if (event.GetOrientation() == wxVERTICAL) { | |
687706f5 | 929 | if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP) { |
57ac1a56 | 930 | --m_cursor.y; |
687706f5 | 931 | } else if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN) { |
57ac1a56 RN |
932 | ++m_cursor.y; |
933 | } | |
934 | } | |
935 | } | |
936 | MyRefresh(); | |
937 | event.Skip(); | |
938 | } | |
939 | ||
940 | const int MyAutoTimedScrollingWindow::sm_lineCnt = 125; | |
941 | const int MyAutoTimedScrollingWindow::sm_lineLen = 79; | |
4e04f777 | 942 | const wxChar* MyAutoTimedScrollingWindow::sm_testData = |
49e7b7a2 | 943 | _T("162 Cult of the genius out of vanity. Because we think well of ourselves, but ") |
4e04f777 WS |
944 | _T("nonetheless never suppose ourselves capable of producing a painting like one of ") |
945 | _T("Raphael's or a dramatic scene like one of Shakespeare's, we convince ourselves ") | |
946 | _T("that the capacity to do so is quite extraordinarily marvelous, a wholly ") | |
947 | _T("uncommon accident, or, if we are still religiously inclined, a mercy from on ") | |
948 | _T("high. Thus our vanity, our self-love, promotes the cult of the genius: for only ") | |
949 | _T("if we think of him as being very remote from us, as a miraculum, does he not ") | |
950 | _T("aggrieve us (even Goethe, who was without envy, called Shakespeare his star of ") | |
49e7b7a2 | 951 | _T("the most distant heights [\"William! Stern der schonsten Ferne\": from Goethe's, ") |
4e04f777 WS |
952 | _T("\"Between Two Worlds\"]; in regard to which one might recall the lines: \"the ") |
953 | _T("stars, these we do not desire\" [from Goethe's, \"Comfort in Tears\"]). But, aside ") | |
954 | _T("from these suggestions of our vanity, the activity of the genius seems in no ") | |
955 | _T("way fundamentally different from the activity of the inventor of machines, the ") | |
956 | _T("scholar of astronomy or history, the master of tactics. All these activities ") | |
957 | _T("are explicable if one pictures to oneself people whose thinking is active in ") | |
958 | _T("one direction, who employ everything as material, who always zealously observe ") | |
959 | _T("their own inner life and that of others, who perceive everywhere models and ") | |
960 | _T("incentives, who never tire of combining together the means available to them. ") | |
961 | _T("Genius too does nothing except learn first how to lay bricks then how to build, ") | |
962 | _T("except continually seek for material and continually form itself around it. ") | |
963 | _T("Every activity of man is amazingly complicated, not only that of the genius: ") | |
49e7b7a2 | 964 | _T("but none is a \"miracle.\" Whence, then, the belief that genius exists only in ") |
4e04f777 WS |
965 | _T("the artist, orator and philosopher? that only they have \"intuition\"? (Whereby ") |
966 | _T("they are supposed to possess a kind of miraculous eyeglass with which they can ") | |
967 | _T("see directly into \"the essence of the thing\"!) It is clear that people speak of ") | |
968 | _T("genius only where the effects of the great intellect are most pleasant to them ") | |
969 | _T("and where they have no desire to feel envious. To call someone \"divine\" means: ") | |
970 | _T("\"here there is no need for us to compete.\" Then, everything finished and ") | |
971 | _T("complete is regarded with admiration, everything still becoming is undervalued. ") | |
972 | _T("But no one can see in the work of the artist how it has become; that is its ") | |
973 | _T("advantage, for wherever one can see the act of becoming one grows somewhat ") | |
974 | _T("cool. The finished and perfect art of representation repulses all thinking as ") | |
975 | _T("to how it has become; it tyrannizes as present completeness and perfection. ") | |
976 | _T("That is why the masters of the art of representation count above all as gifted ") | |
977 | _T("with genius and why men of science do not. In reality, this evaluation of the ") | |
978 | _T("former and undervaluation of the latter is only a piece of childishness in the ") | |
979 | _T("realm of reason. ") | |
980 | _T("\n\n") | |
49e7b7a2 | 981 | _T("163 The serious workman. Do not talk about giftedness, inborn talents! One can ") |
4e04f777 WS |
982 | _T("name great men of all kinds who were very little gifted. The acquired ") |
983 | _T("greatness, became \"geniuses\" (as we put it), through qualities the lack of ") | |
984 | _T("which no one who knew what they were would boast of: they all possessed that ") | |
985 | _T("seriousness of the efficient workman which first learns to construct the parts ") | |
986 | _T("properly before it ventures to fashion a great whole; they allowed themselves ") | |
987 | _T("time for it, because they took more pleasure in making the little, secondary ") | |
988 | _T("things well than in the effect of a dazzling whole. the recipe for becoming a ") | |
989 | _T("good novelist, for example, is easy to give, but to carry it out presupposes ") | |
990 | _T("qualities one is accustomed to overlook when one says \"I do not have enough ") | |
991 | _T("talent.\" One has only to make a hundred or so sketches for novels, none longer ") | |
992 | _T("than two pages but of such distinctness that every word in them is necessary; ") | |
993 | _T("one should write down anecdotes each day until one has learned how to give them ") | |
994 | _T("the most pregnant and effective form; one should be tireless in collecting and ") | |
995 | _T("describing human types and characters; one should above all relate things to ") | |
996 | _T("others and listen to others relate, keeping one's eyes and ears open for the ") | |
997 | _T("effect produced on those present, one should travel like a landscape painter or ") | |
998 | _T("costume designer; one should excerpt for oneself out of the individual sciences ") | |
999 | _T("everything that will produce an artistic effect when it is well described, one ") | |
1000 | _T("should, finally, reflect on the motives of human actions, disdain no signpost ") | |
1001 | _T("to instruction about them and be a collector of these things by day and night. ") | |
1002 | _T("One should continue in this many-sided exercise some ten years: what is then ") | |
49e7b7a2 | 1003 | _T("created in the workshop, however, will be fit to go out into the world. What, ") |
4e04f777 WS |
1004 | _T("however, do most people do? They begin, not with the parts, but with the whole. ") |
1005 | _T("Perhaps they chance to strike a right note, excite attention and from then on ") | |
49e7b7a2 | 1006 | _T("strike worse and worse notes, for good, natural reasons. Sometimes, when the ") |
4e04f777 WS |
1007 | _T("character and intellect needed to formulate such a life-plan are lacking, fate ") |
1008 | _T("and need take their place and lead the future master step by step through all ") | |
1009 | _T("the stipulations of his trade. ") | |
1010 | _T("\n\n") | |
49e7b7a2 | 1011 | _T("164 Peril and profit in the cult of the genius. The belief in great, superior, ") |
4e04f777 WS |
1012 | _T("fruitful spirits is not necessarily, yet nonetheless is very frequently ") |
1013 | _T("associated with that religious or semi-religious superstition that these ") | |
1014 | _T("spirits are of supra-human origin and possess certain miraculous abilities by ") | |
1015 | _T("virtue of which they acquire their knowledge by quite other means than the rest ") | |
1016 | _T("of mankind. One ascribes to them, it seems, a direct view of the nature of the ") | |
1017 | _T("world, as it were a hole in the cloak of appearance, and believes that, by ") | |
1018 | _T("virtue of this miraculous seer's vision, they are able to communicate something ") | |
1019 | _T("conclusive and decisive about man and the world without the toil and ") | |
1020 | _T("rigorousness required by science. As long as there continue to be those who ") | |
1021 | _T("believe in the miraculous in the domain of knowledge one can perhaps concede ") | |
1022 | _T("that these people themselves derive some benefit from their belief, inasmuch as ") | |
1023 | _T("through their unconditional subjection to the great spirits they create for ") | |
1024 | _T("their own spirit during its time of development the finest form of discipline ") | |
1025 | _T("and schooling. On the other hand, it is at least questionable whether the ") | |
1026 | _T("superstitious belief in genius, in its privileges and special abilities, is of ") | |
1027 | _T("benefit to the genius himself if it takes root in him. It is in any event a ") | |
1028 | _T("dangerous sign when a man is assailed by awe of himself, whether it be the ") | |
1029 | _T("celebrated Caesar's awe of Caesar or the awe of one's own genius now under ") | |
1030 | _T("consideration; when the sacrificial incense which is properly rendered only to ") | |
1031 | _T("a god penetrates the brain of the genius, so that his head begins to swim and ") | |
1032 | _T("he comes to regard himself as something supra-human. The consequences that ") | |
1033 | _T("slowly result are: the feeling of irresponsibility, of exceptional rights, the ") | |
1034 | _T("belief that he confers a favor by his mere presence, insane rage when anyone ") | |
1035 | _T("attempts even to compare him with others, let alone to rate him beneath them, ") | |
1036 | _T("or to draw attention to lapses in his work. Because he ceases to practice ") | |
1037 | _T("criticism of himself, at last one pinion after the other falls out of his ") | |
1038 | _T("plumage: that superstitious eats at the roots of his powers and perhaps even ") | |
1039 | _T("turns him into a hypocrite after his powers have fled from him. For the great ") | |
1040 | _T("spirits themselves it is therefore probably more beneficial if they acquire an ") | |
1041 | _T("insight into the nature and origin of their powers, if they grasp, that is to ") | |
1042 | _T("say, what purely human qualities have come together in them and what fortunate ") | |
1043 | _T("circumstances attended them: in the first place undiminished energy, resolute ") | |
1044 | _T("application to individual goals, great personal courage, then the good fortune ") | |
1045 | _T("to receive an upbringing which offered in the early years the finest teachers, ") | |
1046 | _T("models and methods. To be sure, when their goal is the production of the ") | |
1047 | _T("greatest possible effect, unclarity with regard to oneself and that ") | |
1048 | _T("semi-insanity superadded to it has always achieved much; for what has been ") | |
1049 | _T("admired and envied at all times has been that power in them by virtue of which ") | |
1050 | _T("they render men will-less and sweep them away into the delusion that the ") | |
1051 | _T("leaders they are following are supra-natural. Indeed, it elevates and inspires ") | |
1052 | _T("men to believe that someone is in possession of supra-natural powers: to this ") | |
1053 | _T("extent Plato was right to say [Plato: Phaedrus, 244a] that madness has brought ") | |
49e7b7a2 | 1054 | _T("the greatest of blessings upon mankind. In rare individual cases this portion ") |
4e04f777 WS |
1055 | _T("of madness may, indeed, actually have been the means by which such a nature, ") |
1056 | _T("excessive in all directions, was held firmly together: in the life of ") | |
1057 | _T("individuals, too, illusions that are in themselves poisons often play the role ") | |
1058 | _T("of healers; yet, in the end, in the case of every \"genius\" who believes in his ") | |
1059 | _T("own divinity the poison shows itself to the same degree as his \"genius\" grows ") | |
1060 | _T("old: one may recall, for example, the case of Napoleon, whose nature certainly ") | |
1061 | _T("grew into the mighty unity that sets him apart from all men of modern times ") | |
1062 | _T("precisely through his belief in himself and his star and through the contempt ") | |
1063 | _T("for men that flowed from it; until in the end, however, this same belief went ") | |
1064 | _T("over into an almost insane fatalism, robbed him of his acuteness and swiftness ") | |
1065 | _T("of perception, and became the cause of his destruction."); |