1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxScrolledWindow sample 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (C) 1998 Robert Roebling, 2002 Ron Lee, 2003 Matt Gregory 
   7 //              (C) 2008 Vadim Zeitlin 
   8 // Licence:     wxWindows license 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 #include "wx/wxprec.h" 
  23 #include "wx/tglbtn.h" 
  25 // ---------------------------------------------------------------------------- 
  27 // ---------------------------------------------------------------------------- 
  29 // MySimpleCanvas: a scrolled window which draws a simple rectangle 
  30 class MySimpleCanvas 
: public wxScrolledWindow
 
  35         // these numbers are not multiple of 10 (our scroll step) to test for 
  36         // the absence of rounding errors (e.g. we should have one more page 
  37         // than WIDTH/10 to show the right side of the rectangle) 
  42     MySimpleCanvas(wxWindow 
*parent
) 
  43         : wxScrolledWindow(parent
, wxID_ANY
) 
  45         SetScrollRate( 10, 10 ); 
  46         SetVirtualSize( WIDTH
, HEIGHT 
); 
  47         SetBackgroundColour( *wxWHITE 
); 
  49         Connect(wxEVT_PAINT
, wxPaintEventHandler(MySimpleCanvas::OnPaint
)); 
  53     void OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
  57         // this call is vital: it adjusts the dc to account for the current 
  61         dc
.SetPen( *wxRED_PEN 
); 
  62         dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
  63         dc
.DrawRectangle( 0, 0, WIDTH
, HEIGHT 
); 
  68 // MySimpleFrame: a frame which contains a MySimpleCanvas 
  69 class MySimpleFrame 
: public wxFrame
 
  72     MySimpleFrame(wxWindow 
*parent
) 
  73         : wxFrame(parent
, wxID_ANY
, "MySimpleCanvas") 
  75         new MySimpleCanvas(this); 
  77         // ensure that we have scrollbars initially 
  78         SetClientSize(MySimpleCanvas::WIDTH
/2, MySimpleCanvas::HEIGHT
/2); 
  84 // ---------------------------------------------------------------------- 
  85 // a more complex example 
  86 // ---------------------------------------------------------------------- 
  89 class MyCanvas 
: public wxScrolledWindow
 
  92     MyCanvas(wxWindow 
*parent
); 
  95     void OnPaint(wxPaintEvent
& event
); 
  96     void OnQueryPosition(wxCommandEvent
& event
); 
  97     void OnAddButton(wxCommandEvent
& event
); 
  98     void OnDeleteButton(wxCommandEvent
& event
); 
  99     void OnMoveButton(wxCommandEvent
& event
); 
 100     void OnScrollWin(wxCommandEvent
& event
); 
 101     void OnMouseRightDown(wxMouseEvent
& event
); 
 102     void OnMouseWheel(wxMouseEvent
& event
); 
 106     DECLARE_EVENT_TABLE() 
 109 class MyCanvasFrame 
: public wxFrame
 
 112     MyCanvasFrame(wxWindow 
*parent
) 
 113         : wxFrame(parent
, wxID_ANY
, "MyCanvas") 
 115         m_canvas 
= new MyCanvas(this); 
 117         wxMenu 
*menuFile 
= new wxMenu(); 
 118         menuFile
->Append(wxID_DELETE
, "&Delete all"); 
 119         menuFile
->Append(wxID_NEW
, "Insert &new"); 
 121         wxMenuBar 
*mbar 
= new wxMenuBar(); 
 122         mbar
->Append(menuFile
, "&File"); 
 125         Connect(wxID_DELETE
, wxEVT_COMMAND_MENU_SELECTED
, 
 126                 wxCommandEventHandler(MyCanvasFrame::OnDeleteAll
)); 
 127         Connect(wxID_NEW
, wxEVT_COMMAND_MENU_SELECTED
, 
 128                 wxCommandEventHandler(MyCanvasFrame::OnInsertNew
)); 
 134     void OnDeleteAll(wxCommandEvent
& WXUNUSED(event
)) 
 136         m_canvas
->DestroyChildren(); 
 139     void OnInsertNew(wxCommandEvent
& WXUNUSED(event
)) 
 141         (void)new wxButton(m_canvas
, wxID_ANY
, "Hello", wxPoint(100,100)); 
 147 // ---------------------------------------------------------------------------- 
 148 // example using sizers with wxScrolledWindow 
 149 // ---------------------------------------------------------------------------- 
 151 const wxSize 
SMALL_BUTTON( 100, 50 ); 
 152 const wxSize 
LARGE_BUTTON( 300, 200 ); 
 154 class MySizerScrolledWindow 
: public wxScrolledWindow
 
 157     MySizerScrolledWindow(wxWindow 
*parent
); 
 160     // this button can be clicked to change its own size in the handler below, 
 161     // the window size will be automatically adjusted to fit the button 
 164     void OnResizeClick(wxCommandEvent
& event
); 
 167 class MySizerFrame 
: public wxFrame
 
 170     MySizerFrame(wxWindow 
*parent
) 
 171         : wxFrame(parent
, wxID_ANY
, "MySizerScrolledWindow") 
 173         new MySizerScrolledWindow(this); 
 175         // ensure that the scrollbars appear when the button becomes large 
 176         SetClientSize(LARGE_BUTTON
/2); 
 181 // ---------------------------------------------------------------------------- 
 182 // example showing scrolling only part of the window 
 183 // ---------------------------------------------------------------------------- 
 185 // this window consists of an empty space in its corner, column labels window 
 186 // along its top, row labels window along its left hand side and a canvas in 
 187 // the remaining space 
 189 class MySubColLabels 
: public wxWindow
 
 192     MySubColLabels(wxScrolledWindow 
*parent
) 
 193         : wxWindow(parent
, wxID_ANY
) 
 197         Connect(wxEVT_PAINT
, wxPaintEventHandler(MySubColLabels::OnPaint
)); 
 201     void OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 205         // This is wrong..  it will translate both x and y if the 
 206         // window is scrolled, the label windows are active in one 
 207         // direction only.  Do the action below instead -- RL. 
 208         //m_owner->PrepareDC( dc ); 
 210         int xScrollUnits
, xOrigin
; 
 212         m_owner
->GetViewStart( &xOrigin
, 0 ); 
 213         m_owner
->GetScrollPixelsPerUnit( &xScrollUnits
, 0 ); 
 214         dc
.SetDeviceOrigin( -xOrigin 
* xScrollUnits
, 0 ); 
 216         dc
.DrawText("Column 1", 5, 5); 
 217         dc
.DrawText("Column 2", 105, 5); 
 218         dc
.DrawText("Column 3", 205, 5); 
 221     wxScrolledWindow 
*m_owner
; 
 224 class MySubRowLabels 
: public wxWindow
 
 227     MySubRowLabels(wxScrolledWindow 
*parent
) 
 228         : wxWindow(parent
, wxID_ANY
) 
 232         Connect(wxEVT_PAINT
, wxPaintEventHandler(MySubRowLabels::OnPaint
)); 
 236     void OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 240         // This is wrong..  it will translate both x and y if the 
 241         // window is scrolled, the label windows are active in one 
 242         // direction only.  Do the action below instead -- RL. 
 243         //m_owner->PrepareDC( dc ); 
 245         int yScrollUnits
, yOrigin
; 
 247         m_owner
->GetViewStart( 0, &yOrigin 
); 
 248         m_owner
->GetScrollPixelsPerUnit( 0, &yScrollUnits 
); 
 249         dc
.SetDeviceOrigin( 0, -yOrigin 
* yScrollUnits 
); 
 251         dc
.DrawText("Row 1", 5, 5); 
 252         dc
.DrawText("Row 2", 5, 30); 
 253         dc
.DrawText("Row 3", 5, 55); 
 254         dc
.DrawText("Row 4", 5, 80); 
 255         dc
.DrawText("Row 5", 5, 105); 
 256         dc
.DrawText("Row 6", 5, 130); 
 259     wxScrolledWindow 
*m_owner
; 
 262 class MySubCanvas 
: public wxPanel
 
 265     MySubCanvas(wxScrolledWindow 
*parent
, wxWindow 
*cols
, wxWindow 
*rows
) 
 266         : wxPanel(parent
, wxID_ANY
) 
 272         (void)new wxButton(this, wxID_ANY
, "Hallo I", 
 273                            wxPoint(0,50), wxSize(100,25) ); 
 274         (void)new wxButton(this, wxID_ANY
, "Hallo II", 
 275                            wxPoint(200,50), wxSize(100,25) ); 
 277         (void)new wxTextCtrl(this, wxID_ANY
, "Text I", 
 278                              wxPoint(0,100), wxSize(100,25) ); 
 279         (void)new wxTextCtrl(this, wxID_ANY
, "Text II", 
 280                              wxPoint(200,100), wxSize(100,25) ); 
 282         (void)new wxComboBox(this, wxID_ANY
, "ComboBox I", 
 283                              wxPoint(0,150), wxSize(100,25)); 
 284         (void)new wxComboBox(this, wxID_ANY
, "ComboBox II", 
 285                              wxPoint(200,150), wxSize(100,25)); 
 287         SetBackgroundColour("WHEAT"); 
 289         Connect(wxEVT_PAINT
, wxPaintEventHandler(MySubCanvas::OnPaint
)); 
 292     // override the base class function so that when this window is scrolled, 
 293     // the labels are scrolled in sync 
 294     virtual void ScrollWindow(int dx
, int dy
, const wxRect 
*rect
) 
 296         wxPanel::ScrollWindow( dx
, dy
, rect 
); 
 297         m_colLabels
->ScrollWindow( dx
, 0, rect 
); 
 298         m_rowLabels
->ScrollWindow( 0, dy
, rect 
); 
 302     void OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 304         wxPaintDC 
dc( this ); 
 305         m_owner
->PrepareDC( dc 
); 
 307         dc
.SetPen( *wxBLACK_PEN 
); 
 309         // OK, let's assume we are a grid control and we have two 
 310         // grid cells. Here in OnPaint we want to know which cell 
 311         // to redraw so that we prevent redrawing cells that don't 
 312         // need to get redrawn. We have one cell at (0,0) and one 
 313         // more at (200,0), both having a size of (100,25). 
 315         // We can query how much the window has been scrolled 
 316         // by calling CalcUnscrolledPosition() 
 320         m_owner
->CalcUnscrolledPosition( scroll_x
, scroll_y
, &scroll_x
, &scroll_y 
); 
 322         // We also need to know the size of the window to see which 
 323         // cells are completely hidden and not get redrawn 
 327         GetClientSize( &size_x
, &size_y 
); 
 329         // First cell: (0,0)(100,25) 
 331         if ((0+100-scroll_x 
> 0) && (0+25-scroll_y 
> 0) && 
 332             (0-scroll_x 
< size_x
) && (0-scroll_y 
< size_y
)) 
 334             // Has the region on screen been exposed? 
 335             if (IsExposed(0,0,100,25)) 
 337                 dc
.DrawRectangle( 0, 0, 100, 25 ); 
 338                 dc
.DrawText("First Cell", 5, 5); 
 343         // Second cell: (0,200)(100,25) 
 345         if ((200+100-scroll_x 
> 0) && (0+25-scroll_y 
> 0) && 
 346             (200-scroll_x 
< size_x
) && (0-scroll_y 
< size_y
)) 
 348             // Has the region on screen been exposed? 
 349             if (IsExposed(200,0,100,25)) 
 351                 dc
.DrawRectangle( 200, 0, 100, 25 ); 
 352                 dc
.DrawText("Second Cell", 205, 5); 
 357     wxScrolledWindow 
*m_owner
; 
 358     wxWindow 
*m_colLabels
, 
 362 class MySubScrolledWindow 
: public wxScrolledWindow
 
 371     MySubScrolledWindow(wxWindow 
*parent
) 
 372         : wxScrolledWindow(parent
, wxID_ANY
) 
 374         // create the children 
 375         MySubColLabels 
*cols 
= new MySubColLabels(this); 
 376         MySubRowLabels 
*rows 
= new MySubRowLabels(this); 
 378         m_canvas 
= new MySubCanvas(this, cols
, rows
); 
 381         wxFlexGridSizer 
*sizer 
= new wxFlexGridSizer(2, 2, 10, 10); 
 382         sizer
->Add(CORNER_WIDTH
, CORNER_HEIGHT
); // just a spacer 
 383         sizer
->Add(cols
, wxSizerFlags().Expand()); 
 384         sizer
->Add(rows
, wxSizerFlags().Expand()); 
 385         sizer
->Add(m_canvas
, wxSizerFlags().Expand()); 
 386         sizer
->AddGrowableRow(1); 
 387         sizer
->AddGrowableCol(1); 
 390         // this is the key call: it means that only m_canvas will be scrolled 
 391         // and not this window itself 
 392         SetTargetWindow(m_canvas
); 
 394         SetScrollbars(10, 10, 50, 50); 
 396         Connect(wxEVT_SIZE
, wxSizeEventHandler(MySubScrolledWindow::OnSize
)); 
 400     // scrolled windows which use scroll target different from the window 
 401     // itself must override this virtual method 
 402     virtual wxSize 
GetSizeAvailableForScrollTarget(const wxSize
& size
) 
 404         // decrease the total size by the size of the non-scrollable parts 
 405         // above/to the left of the canvas 
 406         wxSize 
sizeCanvas(size
); 
 413     void OnSize(wxSizeEvent
& WXUNUSED(event
)) 
 415         // We need to override OnSize so that our scrolled 
 416         // window a) does call Layout() to use sizers for 
 417         // positioning the controls but b) does not query 
 418         // the sizer for their size and use that for setting 
 419         // the scrollable area as set that ourselves by 
 420         // calling SetScrollbar() further down. 
 427     MySubCanvas 
*m_canvas
; 
 430 class MySubFrame 
: public wxFrame
 
 433     MySubFrame(wxWindow 
*parent
) 
 434         : wxFrame(parent
, wxID_ANY
, "MySubScrolledWindow") 
 436         new MySubScrolledWindow(this); 
 442 // ---------------------------------------------------------------------------- 
 443 // more simple examples of wxScrolledWindow usage 
 444 // ---------------------------------------------------------------------------- 
 446 // base class for both of them 
 447 class MyScrolledWindowBase 
: public wxScrolledWindow
 
 450     MyScrolledWindowBase(wxWindow 
*parent
) 
 451         : wxScrolledWindow(parent
, wxID_ANY
, 
 452                            wxDefaultPosition
, wxDefaultSize
, 
 460         dc
.GetTextExtent("Line 17", NULL
, &m_hLine
); 
 463     // this scrolled window can be synchronized with another one: if this 
 464     // function is called with a non-NULL pointer, the given window will be 
 465     // scrolled to the same position as this one 
 466     void SyncWith(MyScrolledWindowBase 
*win
) 
 473     virtual void ScrollWindow(int dx
, int dy
, const wxRect 
*rect 
= NULL
) 
 475         wxScrolledWindow::ScrollWindow(dx
, dy
, rect
); 
 481     // the height of one line on screen 
 484     // the number of lines we draw 
 488     bool WasScrolledFirst() const { return m_inDoSync
; } 
 490     void DoSyncIfNecessary() 
 492         if ( m_winSync 
&& !m_winSync
->WasScrolledFirst() ) 
 496             m_winSync
->Scroll(GetViewStart()); 
 502     // the window to synchronize with this one or NULL 
 503     MyScrolledWindowBase 
*m_winSync
; 
 505     // the flag preventing infinite recursion which would otherwise happen if 
 506     // one window synchronized the other one which in turn synchronized this 
 511 // this class does "stupid" redrawing - it redraws everything each time 
 512 // and sets the scrollbar extent directly. 
 514 class MyScrolledWindowDumb 
: public MyScrolledWindowBase
 
 517     MyScrolledWindowDumb(wxWindow 
*parent
) : MyScrolledWindowBase(parent
) 
 520         SetScrollbars(0, m_hLine
, 0, m_nLines 
+ 1, 0, 0, true /* no refresh */); 
 523     virtual void OnDraw(wxDC
& dc
); 
 526 // this class does "smart" redrawing - only redraws the lines which must be 
 527 // redrawn and sets the scroll rate and virtual size to affect the 
 530 // Note that this class should produce identical results to the one above. 
 532 class MyScrolledWindowSmart 
: public MyScrolledWindowBase
 
 535     MyScrolledWindowSmart(wxWindow 
*parent
) : MyScrolledWindowBase(parent
) 
 538         SetScrollRate( 0, m_hLine 
); 
 539         SetVirtualSize( wxDefaultCoord
, ( m_nLines 
+ 1 ) * m_hLine 
); 
 542     virtual void OnDraw(wxDC
& dc
); 
 545 // ---------------------------------------------------------------------------- 
 546 // implements a text viewer with simple block selection to test auto-scrolling 
 548 // ---------------------------------------------------------------------------- 
 550 class MyAutoScrollingWindow 
: public wxScrolledWindow
 
 553     MyAutoScrollingWindow( wxWindow
* parent 
); 
 554     wxRect 
DeviceCoordsToGraphicalChars(wxRect updRect
) const; 
 555     wxPoint 
DeviceCoordsToGraphicalChars(wxPoint pos
) const; 
 556     wxPoint 
GraphicalCharToDeviceCoords(wxPoint pos
) const; 
 557     wxRect 
LogicalCoordsToGraphicalChars(wxRect updRect
) const; 
 558     wxPoint 
LogicalCoordsToGraphicalChars(wxPoint pos
) const; 
 559     wxPoint 
GraphicalCharToLogicalCoords(wxPoint pos
) const; 
 561     bool IsSelected(int chX
, int chY
) const; 
 562     static bool IsInside(int k
, int bound1
, int bound2
); 
 563     static wxRect 
DCNormalize(int x
, int y
, int w
, int h
); 
 567     void OnDraw(wxDC
& dc
); 
 568     void OnMouseLeftDown(wxMouseEvent
& event
); 
 569     void OnMouseLeftUp(wxMouseEvent
& event
); 
 570     void OnMouseMove(wxMouseEvent
& event
); 
 571     void OnMouseCaptureLost(wxMouseCaptureLostEvent
& event
); 
 572     void OnScroll(wxScrollWinEvent
& event
); 
 574     // test data variables 
 575     static const char* sm_testData
; 
 576     static const int sm_lineCnt
; // line count 
 577     static const int sm_lineLen
; // line length in characters 
 578     // sizes for graphical data 
 579     int m_fontH
, m_fontW
; 
 580     // selection tracking 
 581     wxPoint m_selStart
; // beginning of blockwise selection 
 582     wxPoint m_cursor
;   // end of blockwise selection (mouse position) 
 588     DECLARE_EVENT_TABLE() 
 591 class MyAutoFrame 
: public wxFrame
 
 594     MyAutoFrame(wxWindow 
*parent
) 
 595         : wxFrame(parent
, wxID_ANY
, "MyAutoScrollingWindow") 
 597         new MyAutoScrollingWindow(this); 
 604 // ---------------------------------------------------------------------------- 
 605 // MyFrame: the main application frame showing all the classes above 
 606 // ---------------------------------------------------------------------------- 
 608 class MyFrame
: public wxFrame
 
 614     void OnAbout(wxCommandEvent
& event
); 
 615     void OnQuit(wxCommandEvent
& event
); 
 617     void OnTestSimple(wxCommandEvent
& WXUNUSED(event
)) { new MySimpleFrame(this); } 
 618     void OnTestCanvas(wxCommandEvent
& WXUNUSED(event
)) { new MyCanvasFrame(this); } 
 619     void OnTestSizer(wxCommandEvent
& WXUNUSED(event
)) { new MySizerFrame(this); } 
 620     void OnTestSub(wxCommandEvent
& WXUNUSED(event
)) { new MySubFrame(this); } 
 621     void OnTestAuto(wxCommandEvent
& WXUNUSED(event
)) { new MyAutoFrame(this); } 
 623     void OnToggleSync(wxCommandEvent
& event
); 
 625     MyScrolledWindowBase 
*m_win1
, 
 628     DECLARE_EVENT_TABLE() 
 631 // ---------------------------------------------------------------------------- 
 633 // ---------------------------------------------------------------------------- 
 635 class MyApp 
: public wxApp
 
 638     virtual bool OnInit(); 
 642 // ============================================================================ 
 644 // ============================================================================ 
 646 // ---------------------------------------------------------------------------- 
 648 // ---------------------------------------------------------------------------- 
 650 const wxWindowID ID_ADDBUTTON   
= wxWindow::NewControlId(); 
 651 const wxWindowID ID_DELBUTTON   
= wxWindow::NewControlId(); 
 652 const wxWindowID ID_MOVEBUTTON  
= wxWindow::NewControlId(); 
 653 const wxWindowID ID_SCROLLWIN   
= wxWindow::NewControlId(); 
 654 const wxWindowID ID_QUERYPOS    
= wxWindow::NewControlId(); 
 656 const wxWindowID ID_NEWBUTTON   
= wxWindow::NewControlId(); 
 658 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
) 
 659     EVT_PAINT(                  MyCanvas::OnPaint
) 
 660     EVT_RIGHT_DOWN(             MyCanvas::OnMouseRightDown
) 
 661     EVT_MOUSEWHEEL(             MyCanvas::OnMouseWheel
) 
 662     EVT_BUTTON( ID_QUERYPOS
,    MyCanvas::OnQueryPosition
) 
 663     EVT_BUTTON( ID_ADDBUTTON
,   MyCanvas::OnAddButton
) 
 664     EVT_BUTTON( ID_DELBUTTON
,   MyCanvas::OnDeleteButton
) 
 665     EVT_BUTTON( ID_MOVEBUTTON
,  MyCanvas::OnMoveButton
) 
 666     EVT_BUTTON( ID_SCROLLWIN
,   MyCanvas::OnScrollWin
) 
 669 MyCanvas::MyCanvas(wxWindow 
*parent
) 
 670     : wxScrolledWindow(parent
, wxID_ANY
, 
 671                        wxDefaultPosition
, wxDefaultSize
, 
 672                        wxSUNKEN_BORDER 
| wxTAB_TRAVERSAL
) 
 674     // you can use either a single SetScrollbars() call or these 2 functions, 
 675     // usually using them is better because you normally won't need to change 
 676     // the scroll rate in the future and the sizer can be used to update the 
 677     // virtual size automatically 
 678     SetScrollRate( 10, 10 ); 
 679     SetVirtualSize( 500, 1000 ); 
 681     (void) new wxButton( this, ID_ADDBUTTON
,  "add button", wxPoint(10,10) ); 
 682     (void) new wxButton( this, ID_DELBUTTON
,  "del button", wxPoint(10,40) ); 
 683     (void) new wxButton( this, ID_MOVEBUTTON
, "move button", wxPoint(150,10) ); 
 684     (void) new wxButton( this, ID_SCROLLWIN
,  "scroll win", wxPoint(250,10) ); 
 686     wxPanel 
*test 
= new wxPanel( this, wxID_ANY
, 
 687                                  wxPoint(10, 110), wxSize(130,50), 
 688                                  wxSIMPLE_BORDER 
| wxTAB_TRAVERSAL 
); 
 689     test
->SetBackgroundColour( "WHEAT" ); 
 691     SetBackgroundColour( "BLUE" ); 
 694 void MyCanvas::OnMouseRightDown( wxMouseEvent 
&event 
) 
 696     wxPoint 
pt( event
.GetPosition() ); 
 698     CalcUnscrolledPosition( pt
.x
, pt
.y
, &x
, &y 
); 
 699     wxLogMessage("Mouse down event at: %d %d, scrolled: %d %d", 
 703 void MyCanvas::OnMouseWheel( wxMouseEvent 
&event 
) 
 705     wxPoint 
pt( event
.GetPosition() ); 
 707     CalcUnscrolledPosition( pt
.x
, pt
.y
, &x
, &y 
); 
 708     wxLogMessage( "Mouse wheel event at: %d %d, scrolled: %d %d\n" 
 709                   "Rotation: %d, delta = %d", 
 711                   event
.GetWheelRotation(), event
.GetWheelDelta() ); 
 716 void MyCanvas::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
 718     wxPaintDC 
dc( this ); 
 721     dc
.DrawText( "Press right mouse button to test calculations!", 160, 50 ); 
 723     dc
.DrawText( "Some text", 140, 140 ); 
 725     dc
.DrawRectangle( 100, 160, 200, 200 ); 
 728 void MyCanvas::OnQueryPosition( wxCommandEvent 
&WXUNUSED(event
) ) 
 730     wxPoint 
pt( m_button
->GetPosition() ); 
 731     wxLogMessage( "Position of \"Query position\" is %d %d", pt
.x
, pt
.y 
); 
 732     pt 
= ClientToScreen( pt 
); 
 733     wxLogMessage("Position of \"Query position\" on screen is %d %d", 
 737 void MyCanvas::OnAddButton( wxCommandEvent 
&WXUNUSED(event
) ) 
 739     wxLogMessage( "Inserting button at position 10,70..." ); 
 740     wxButton 
*button 
= new wxButton( this, ID_NEWBUTTON
, "new button", 
 741                                      wxPoint(10,70), wxSize(80,25) ); 
 742     wxPoint 
pt( button
->GetPosition() ); 
 743     wxLogMessage( "-> Position after inserting %d %d", pt
.x
, pt
.y 
); 
 746 void MyCanvas::OnDeleteButton( wxCommandEvent 
&WXUNUSED(event
) ) 
 748     wxLogMessage( "Deleting button inserted with \"Add button\"..." ); 
 749     wxWindow 
*win 
= FindWindow( ID_NEWBUTTON 
); 
 753        wxLogMessage( "-> No window with id = ID_NEWBUTTON found." ); 
 756 void MyCanvas::OnMoveButton( wxCommandEvent 
&event 
) 
 758     wxLogMessage( "Moving button 10 pixels downward.." ); 
 759     wxWindow 
*win 
= FindWindow( event
.GetId() ); 
 760     wxPoint 
pt( win
->GetPosition() ); 
 761     wxLogMessage( "-> Position before move is %d %d", pt
.x
, pt
.y 
); 
 762     win
->Move( wxDefaultCoord
, pt
.y 
+ 10 ); 
 763     pt 
= win
->GetPosition(); 
 764     wxLogMessage( "-> Position after move is %d %d", pt
.x
, pt
.y 
); 
 767 void MyCanvas::OnScrollWin( wxCommandEvent 
&WXUNUSED(event
) ) 
 769     wxLogMessage("Scrolling 2 units up.\n" 
 770                  "The white square and the controls should move equally!"); 
 771     Scroll( wxDefaultCoord
, GetViewStart().y
+2 ); 
 774 // ---------------------------------------------------------------------------- 
 775 // MySizerScrolledWindow 
 776 // ---------------------------------------------------------------------------- 
 778 MySizerScrolledWindow::MySizerScrolledWindow(wxWindow 
*parent
) 
 779     : wxScrolledWindow(parent
) 
 781     SetBackgroundColour( "GREEN" ); 
 783     // Set the rate we'd like for scrolling. 
 785     SetScrollRate( 5, 5 ); 
 787     // Populate a sizer with a 'resizing' button and some other static 
 790     wxFlexGridSizer 
*sizer 
= new wxFlexGridSizer(2); 
 792     m_button 
= new wxButton( this, wxID_RESIZE_FRAME
, "Press me", 
 793                              wxDefaultPosition
, SMALL_BUTTON 
); 
 795     sizer
->Add(m_button
, wxSizerFlags().Centre().Border(20)); 
 796     sizer
->Add(new wxStaticText(this, wxID_ANY
, "This is just"), 
 797                wxSizerFlags().Centre()); 
 798     sizer
->Add(new wxStaticText(this, wxID_ANY
, "some decoration"), 
 799                wxSizerFlags().Centre()); 
 800     sizer
->Add(new wxStaticText(this, wxID_ANY
, "for you to scroll..."), 
 801                wxSizerFlags().Centre()); 
 803     // Then use the sizer to set the scrolled region size. 
 807     Connect(wxID_RESIZE_FRAME
, wxEVT_COMMAND_BUTTON_CLICKED
, 
 808             wxCommandEventHandler(MySizerScrolledWindow::OnResizeClick
)); 
 811 void MySizerScrolledWindow::OnResizeClick(wxCommandEvent 
&WXUNUSED(event
)) 
 813     // Arbitrarily resize the button to change the minimum size of 
 814     // the (scrolled) sizer. 
 816     if ( m_button
->GetSize() == SMALL_BUTTON 
) 
 817         m_button
->SetSizeHints(LARGE_BUTTON
); 
 819         m_button
->SetSizeHints(SMALL_BUTTON
); 
 821     // Force update layout and scrollbars, since nothing we do here 
 822     // necessarily generates a size event which would do it for us. 
 826 // ---------------------------------------------------------------------------- 
 828 // ---------------------------------------------------------------------------- 
 830 const wxWindowID Scroll_Test_Simple 
= wxWindow::NewControlId(); 
 831 const wxWindowID Scroll_Test_Canvas 
= wxWindow::NewControlId(); 
 832 const wxWindowID Scroll_Test_Sizers 
= wxWindow::NewControlId(); 
 833 const wxWindowID Scroll_Test_Sub    
= wxWindow::NewControlId(); 
 834 const wxWindowID Scroll_Test_Auto   
= wxWindow::NewControlId(); 
 836 const wxWindowID Scroll_TglBtn_Sync 
= wxWindow::NewControlId(); 
 838 BEGIN_EVENT_TABLE(MyFrame
,wxFrame
) 
 839     EVT_MENU(wxID_ABOUT
, MyFrame::OnAbout
) 
 840     EVT_MENU(wxID_EXIT
,  MyFrame::OnQuit
) 
 842     EVT_MENU(Scroll_Test_Simple
, MyFrame::OnTestSimple
) 
 843     EVT_MENU(Scroll_Test_Canvas
, MyFrame::OnTestCanvas
) 
 844     EVT_MENU(Scroll_Test_Sizers
, MyFrame::OnTestSizer
) 
 845     EVT_MENU(Scroll_Test_Sub
, MyFrame::OnTestSub
) 
 846     EVT_MENU(Scroll_Test_Auto
, MyFrame::OnTestAuto
) 
 848     EVT_TOGGLEBUTTON(Scroll_TglBtn_Sync
, MyFrame::OnToggleSync
) 
 852        : wxFrame(NULL
, wxID_ANY
, "wxWidgets scroll sample") 
 854     wxMenu 
*menuFile 
= new wxMenu
; 
 855     menuFile
->Append(wxID_ABOUT
, "&About.."); 
 856     menuFile
->AppendSeparator(); 
 857     menuFile
->Append(wxID_EXIT
, "E&xit\tAlt-X"); 
 859     wxMenu 
*menuTest 
= new wxMenu
; 
 860     menuTest
->Append(Scroll_Test_Simple
, "&Simple scroll window\tF1", 
 861                      "Simplest possible scrolled window test."); 
 862     menuTest
->Append(Scroll_Test_Canvas
, "Scrolled window with &children\tF2", 
 863                      "Scrolled window with controls on it."); 
 864     menuTest
->Append(Scroll_Test_Sizers
, "Scrolled window with si&zer\tF3", 
 865                      "Scrolled window with children managed by sizer."); 
 866     menuTest
->Append(Scroll_Test_Sub
, "Scrolled s&ub-window\tF4", 
 867                      "Window only part of which is scrolled."); 
 868     menuTest
->Append(Scroll_Test_Auto
, "&Auto-scrolled window\tF5", 
 869                      "Window which scrolls when the mouse is held pressed " 
 872     wxMenuBar 
*mbar 
= new wxMenuBar
; 
 873     mbar
->Append(menuFile
, "&File"); 
 874     mbar
->Append(menuTest
, "&Test"); 
 879     const wxSizerFlags 
flagsExpand(wxSizerFlags(1).Expand()); 
 881     wxSizer 
*topsizer 
= new wxBoxSizer(wxVERTICAL
); 
 882     topsizer
->Add(new wxStaticText(this, wxID_ANY
, 
 883         "The windows below should behave in the same way, even though\n" 
 884         "they're implemented quite differently, see the code for details.\n" 
 886         "The lines redrawn during odd/even repaint iterations are drawn in\n" 
 887         "red/blue colour to allow seeing immediately how much is repainted,\n" 
 888         "don't be surprised by this."), 
 889         wxSizerFlags().Centre().Border()); 
 891     m_win1 
= new MyScrolledWindowDumb(this); 
 892     m_win2 
= new MyScrolledWindowSmart(this); 
 894     wxSizer 
*sizerScrollWin 
= new wxBoxSizer(wxHORIZONTAL
); 
 895     sizerScrollWin
->Add(m_win1
, flagsExpand
); 
 896     sizerScrollWin
->Add(m_win2
, flagsExpand
); 
 897     topsizer
->Add(sizerScrollWin
, flagsExpand
); 
 899     wxSizer 
*sizerBtns 
= new wxBoxSizer(wxHORIZONTAL
); 
 900     sizerBtns
->Add(new wxToggleButton(this, Scroll_TglBtn_Sync
, "&Synchronize")); 
 901     topsizer
->Add(sizerBtns
, wxSizerFlags().Centre().Border()); 
 909 void MyFrame::OnToggleSync(wxCommandEvent
& event
) 
 911     if ( event
.IsChecked() ) 
 913         m_win1
->SyncWith(m_win2
); 
 914         m_win2
->SyncWith(m_win1
); 
 918         m_win1
->SyncWith(NULL
); 
 919         m_win2
->SyncWith(NULL
); 
 923 void MyFrame::OnQuit(wxCommandEvent 
&WXUNUSED(event
)) 
 928 void MyFrame::OnAbout( wxCommandEvent 
&WXUNUSED(event
) ) 
 930     (void)wxMessageBox( "wxScrolledWindow sample\n" 
 932                         "Robert Roebling (c) 1998\n" 
 933                         "Vadim Zeitlin (c) 2008\n" 
 934                         "Autoscrolling examples\n" 
 936                         "Auto-timed-scrolling example\n" 
 937                         "Matt Gregory (c) 2003\n", 
 938                         "About wxWidgets scroll sample", 
 939                         wxICON_INFORMATION 
| wxOK 
); 
 942 // ---------------------------------------------------------------------------- 
 944 // ---------------------------------------------------------------------------- 
 950     if ( !wxApp::OnInit() ) 
 958 // ---------------------------------------------------------------------------- 
 959 // MyScrolledWindowXXX 
 960 // ---------------------------------------------------------------------------- 
 962 void MyScrolledWindowDumb::OnDraw(wxDC
& dc
) 
 964     // this is useful to see which lines are redrawn 
 965     static size_t s_redrawCount 
= 0; 
 966     dc
.SetTextForeground(s_redrawCount
++ % 2 ? *wxRED 
: *wxBLUE
); 
 969     for ( size_t line 
= 0; line 
< m_nLines
; line
++ ) 
 972         CalcScrolledPosition(0, y
, NULL
, &yPhys
); 
 974         dc
.DrawText(wxString::Format("Line %u (logical %d, physical %d)", 
 975                                      unsigned(line
), y
, yPhys
), 0, y
); 
 980 void MyScrolledWindowSmart::OnDraw(wxDC
& dc
) 
 982     // this is useful to see which lines are redrawn 
 983     static size_t s_redrawCount 
= 0; 
 984     dc
.SetTextForeground(s_redrawCount
++ % 2 ? *wxRED 
: *wxBLUE
); 
 986     // update region is always in device coords, translate to logical ones 
 987     wxRect rectUpdate 
= GetUpdateRegion().GetBox(); 
 988     CalcUnscrolledPosition(rectUpdate
.x
, rectUpdate
.y
, 
 989                            &rectUpdate
.x
, &rectUpdate
.y
); 
 991     size_t lineFrom 
= rectUpdate
.y 
/ m_hLine
, 
 992            lineTo 
= rectUpdate
.GetBottom() / m_hLine
; 
 994     if ( lineTo 
> m_nLines 
- 1) 
 995         lineTo 
= m_nLines 
- 1; 
 997     int y 
= lineFrom
*m_hLine
; 
 998     for ( size_t line 
= lineFrom
; line 
<= lineTo
; line
++ ) 
1001         CalcScrolledPosition(0, y
, NULL
, &yPhys
); 
1003         dc
.DrawText(wxString::Format("Line %u (logical %d, physical %d)", 
1004                                      unsigned(line
), y
, yPhys
), 0, y
); 
1009 // ---------------------------------------------------------------------------- 
1010 // MyAutoScrollingWindow 
1011 // ---------------------------------------------------------------------------- 
1013 BEGIN_EVENT_TABLE(MyAutoScrollingWindow
, wxScrolledWindow
) 
1014     EVT_LEFT_DOWN(MyAutoScrollingWindow::OnMouseLeftDown
) 
1015     EVT_LEFT_UP(MyAutoScrollingWindow::OnMouseLeftUp
) 
1016     EVT_MOTION(MyAutoScrollingWindow::OnMouseMove
) 
1017     EVT_MOUSE_CAPTURE_LOST(MyAutoScrollingWindow::OnMouseCaptureLost
) 
1018     EVT_SCROLLWIN(MyAutoScrollingWindow::OnScroll
) 
1021 MyAutoScrollingWindow::MyAutoScrollingWindow(wxWindow
* parent
) 
1022     : wxScrolledWindow(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 
1023                        wxVSCROLL 
| wxHSCROLL 
| wxSUNKEN_BORDER
), 
1026       m_font(9, wxFONTFAMILY_TELETYPE
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
) 
1028     wxClientDC 
dc(this); 
1029     // query dc for text size 
1031     dc
.GetTextExtent(wxString("A"), &m_fontW
, &m_fontH
); 
1032     // set up the virtual window 
1033     SetScrollbars(m_fontW
, m_fontH
, sm_lineLen
, sm_lineCnt
); 
1037 MyAutoScrollingWindow::DeviceCoordsToGraphicalChars(wxRect updRect
) const 
1039     wxPoint 
pos(updRect
.GetPosition()); 
1040     pos 
= DeviceCoordsToGraphicalChars(pos
); 
1043     updRect
.width 
/= m_fontW
; 
1044     updRect
.height 
/= m_fontH
; 
1045     // the *CoordsToGraphicalChars() funcs round down to upper-left corner, 
1046     //   so an off-by-one correction is needed 
1047     ++updRect
.width
; // kludge 
1048     ++updRect
.height
; // kludge 
1053 MyAutoScrollingWindow::DeviceCoordsToGraphicalChars(wxPoint pos
) const 
1057     pos 
+= GetViewStart(); 
1062 MyAutoScrollingWindow::GraphicalCharToDeviceCoords(wxPoint pos
) const 
1064     pos 
-= GetViewStart(); 
1071 MyAutoScrollingWindow::LogicalCoordsToGraphicalChars(wxRect updRect
) const 
1073     wxPoint 
pos(updRect
.GetPosition()); 
1074     pos 
= LogicalCoordsToGraphicalChars(pos
); 
1077     updRect
.width 
/= m_fontW
; 
1078     updRect
.height 
/= m_fontH
; 
1079     // the *CoordsToGraphicalChars() funcs round down to upper-left corner, 
1080     //   so an off-by-one correction is needed 
1081     ++updRect
.width
; // kludge 
1082     ++updRect
.height
; // kludge 
1087 MyAutoScrollingWindow::LogicalCoordsToGraphicalChars(wxPoint pos
) const 
1095 MyAutoScrollingWindow::GraphicalCharToLogicalCoords(wxPoint pos
) const 
1102 void MyAutoScrollingWindow::MyRefresh() 
1104     static wxPoint 
lastSelStart(-1, -1), lastCursor(-1, -1); 
1105     // refresh last selected area (to deselect previously selected text) 
1107             GraphicalCharToDeviceCoords(lastSelStart
), 
1108             GraphicalCharToDeviceCoords(lastCursor
) 
1110     // off-by-one corrections, necessary because it's not possible to know 
1111     //   when to round up until rect is normalized by lastUpdRect constructor 
1112     lastUpdRect
.width 
+= m_fontW
; // kludge 
1113     lastUpdRect
.height 
+= m_fontH
; // kludge 
1114     // refresh currently selected (to select previously unselected text) 
1116             GraphicalCharToDeviceCoords(m_selStart
), 
1117             GraphicalCharToDeviceCoords(m_cursor
) 
1119     // off-by-one corrections 
1120     updRect
.width 
+= m_fontW
; // kludge 
1121     updRect
.height 
+= m_fontH
; // kludge 
1122     // find necessary refresh areas 
1123     int rx 
= lastUpdRect
.x
; 
1124     int ry 
= lastUpdRect
.y
; 
1125     int rw 
= updRect
.x 
- lastUpdRect
.x
; 
1126     int rh 
= lastUpdRect
.height
; 
1128         RefreshRect(DCNormalize(rx
, ry
, rw
, rh
)); 
1131     ry 
= updRect
.y 
+ updRect
.height
; 
1133     rh 
= (lastUpdRect
.y 
+ lastUpdRect
.height
) - (updRect
.y 
+ updRect
.height
); 
1135         RefreshRect(DCNormalize(rx
, ry
, rw
, rh
)); 
1137     rx 
= updRect
.x 
+ updRect
.width
; 
1139     rw 
= (lastUpdRect
.x 
+ lastUpdRect
.width
) - (updRect
.x 
+ updRect
.width
); 
1140     rh 
= lastUpdRect
.height
; 
1142         RefreshRect(DCNormalize(rx
, ry
, rw
, rh
)); 
1147     rh 
= updRect
.y 
- lastUpdRect
.y
; 
1149         RefreshRect(DCNormalize(rx
, ry
, rw
, rh
)); 
1152     lastSelStart 
= m_selStart
; 
1153     lastCursor 
= m_cursor
; 
1156 bool MyAutoScrollingWindow::IsSelected(int chX
, int chY
) const 
1158     if (IsInside(chX
, m_selStart
.x
, m_cursor
.x
) 
1159             && IsInside(chY
, m_selStart
.y
, m_cursor
.y
)) { 
1165 bool MyAutoScrollingWindow::IsInside(int k
, int bound1
, int bound2
) 
1167     if ((k 
>= bound1 
&& k 
<= bound2
) || (k 
>= bound2 
&& k 
<= bound1
)) { 
1174 MyAutoScrollingWindow::DCNormalize(int x
, int y
, int w
, int h
) 
1176     // this is needed to get rid of the graphical remnants from the selection 
1177     // I think it's because DrawRectangle() excludes a pixel in either direction 
1178     const int kludge 
= 1; 
1179     // make (x, y) the top-left corner 
1194     return wxRect(x
, y
, w
, h
); 
1197 void MyAutoScrollingWindow::OnDraw(wxDC
& dc
) 
1200     wxBrush 
normBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
) 
1202     wxBrush 
selBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
) 
1204     dc
.SetPen(*wxTRANSPARENT_PEN
); 
1205     const wxString str 
= sm_testData
; 
1206     size_t strLength 
= str
.length(); 
1207     wxString::const_iterator str_i
; 
1209     // draw the characters 
1210     // 1. for each update region 
1211     for (wxRegionIterator 
upd(GetUpdateRegion()); upd
; ++upd
) { 
1212         wxRect updRect 
= upd
.GetRect(); 
1213         wxRect 
updRectInGChars(DeviceCoordsToGraphicalChars(updRect
)); 
1214         // 2. for each row of chars in the update region 
1215         for (int chY 
= updRectInGChars
.y
 
1216                 ; chY 
<= updRectInGChars
.y 
+ updRectInGChars
.height
; ++chY
) { 
1217             // 3. for each character in the row 
1218             bool isFirstX 
= true; 
1219             for (int chX 
= updRectInGChars
.x
 
1220                     ; chX 
<= updRectInGChars
.x 
+ updRectInGChars
.width
 
1223                 if (IsSelected(chX
, chY
)) { 
1224                     dc
.SetBrush(selBrush
); 
1225                     dc
.SetTextForeground( wxSystemSettings::GetColour
 
1226                             (wxSYS_COLOUR_HIGHLIGHTTEXT
)); 
1228                     dc
.SetBrush(normBrush
); 
1229                     dc
.SetTextForeground( wxSystemSettings::GetColour
 
1230                             (wxSYS_COLOUR_WINDOWTEXT
)); 
1232                 // 5. find position info 
1233                 wxPoint charPos 
= GraphicalCharToLogicalCoords(wxPoint
 
1236                 dc
.DrawRectangle(charPos
.x
, charPos
.y
, m_fontW
, m_fontH
); 
1237                 size_t charIndex 
= chY 
* sm_lineLen 
+ chX
; 
1238                 if (chY 
< sm_lineCnt 
&& 
1240                     charIndex 
< strLength
) 
1244                         str_i 
= str
.begin() + charIndex
; 
1247                     dc
.DrawText(*str_i
, charPos
.x
, charPos
.y
); 
1255 void MyAutoScrollingWindow::OnMouseLeftDown(wxMouseEvent
& event
) 
1257     // initial press of mouse button sets the beginning of the selection 
1258     m_selStart 
= DeviceCoordsToGraphicalChars(event
.GetPosition()); 
1259     // set the cursor to the same position 
1260     m_cursor 
= m_selStart
; 
1261     // draw/erase selection 
1265 void MyAutoScrollingWindow::OnMouseLeftUp(wxMouseEvent
& WXUNUSED(event
)) 
1267     // this test is necessary 
1274 void MyAutoScrollingWindow::OnMouseMove(wxMouseEvent
& event
) 
1276     // if user is dragging 
1277     if (event
.Dragging() && event
.LeftIsDown()) { 
1278         // set the new cursor position 
1279         m_cursor 
= DeviceCoordsToGraphicalChars(event
.GetPosition()); 
1280         // draw/erase selection 
1282         // capture mouse to activate auto-scrolling 
1283         if (!HasCapture()) { 
1290 MyAutoScrollingWindow::OnMouseCaptureLost(wxMouseCaptureLostEvent
& 
1293     // we only capture mouse for timed scrolling, so nothing is needed here 
1294     // other than making sure to not call event.Skip() 
1297 void MyAutoScrollingWindow::OnScroll(wxScrollWinEvent
& event
) 
1299     // need to move the cursor when autoscrolling 
1300     // FIXME: the cursor also moves when the scrollbar arrows are clicked 
1302         if (event
.GetOrientation() == wxHORIZONTAL
) { 
1303             if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) { 
1305             } else if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) { 
1308         } else if (event
.GetOrientation() == wxVERTICAL
) { 
1309             if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) { 
1311             } else if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) { 
1320 const int MyAutoScrollingWindow::sm_lineCnt 
= 125; 
1321 const int MyAutoScrollingWindow::sm_lineLen 
= 79; 
1322 const char *MyAutoScrollingWindow::sm_testData 
= 
1323 "162 Cult of the genius out of vanity. Because we think well of ourselves, but " 
1324 "nonetheless never suppose ourselves capable of producing a painting like one of " 
1325 "Raphael's or a dramatic scene like one of Shakespeare's, we convince ourselves " 
1326 "that the capacity to do so is quite extraordinarily marvelous, a wholly " 
1327 "uncommon accident, or, if we are still religiously inclined, a mercy from on " 
1328 "high. Thus our vanity, our self-love, promotes the cult of the genius: for only " 
1329 "if we think of him as being very remote from us, as a miraculum, does he not " 
1330 "aggrieve us (even Goethe, who was without envy, called Shakespeare his star of " 
1331 "the most distant heights [\"William! Stern der schonsten Ferne\": from Goethe's, " 
1332 "\"Between Two Worlds\"]; in regard to which one might recall the lines: \"the " 
1333 "stars, these we do not desire\" [from Goethe's, \"Comfort in Tears\"]). But, aside " 
1334 "from these suggestions of our vanity, the activity of the genius seems in no " 
1335 "way fundamentally different from the activity of the inventor of machines, the " 
1336 "scholar of astronomy or history, the master of tactics. All these activities " 
1337 "are explicable if one pictures to oneself people whose thinking is active in " 
1338 "one direction, who employ everything as material, who always zealously observe " 
1339 "their own inner life and that of others, who perceive everywhere models and " 
1340 "incentives, who never tire of combining together the means available to them. " 
1341 "Genius too does nothing except learn first how to lay bricks then how to build, " 
1342 "except continually seek for material and continually form itself around it. " 
1343 "Every activity of man is amazingly complicated, not only that of the genius: " 
1344 "but none is a \"miracle.\" Whence, then, the belief that genius exists only in " 
1345 "the artist, orator and philosopher? that only they have \"intuition\"? (Whereby " 
1346 "they are supposed to possess a kind of miraculous eyeglass with which they can " 
1347 "see directly into \"the essence of the thing\"!) It is clear that people speak of " 
1348 "genius only where the effects of the great intellect are most pleasant to them " 
1349 "and where they have no desire to feel envious. To call someone \"divine\" means: " 
1350 "\"here there is no need for us to compete.\" Then, everything finished and " 
1351 "complete is regarded with admiration, everything still becoming is undervalued. " 
1352 "But no one can see in the work of the artist how it has become; that is its " 
1353 "advantage, for wherever one can see the act of becoming one grows somewhat " 
1354 "cool. The finished and perfect art of representation repulses all thinking as " 
1355 "to how it has become; it tyrannizes as present completeness and perfection. " 
1356 "That is why the masters of the art of representation count above all as gifted " 
1357 "with genius and why men of science do not. In reality, this evaluation of the " 
1358 "former and undervaluation of the latter is only a piece of childishness in the " 
1361 "163 The serious workman. Do not talk about giftedness, inborn talents! One can " 
1362 "name great men of all kinds who were very little gifted. The acquired " 
1363 "greatness, became \"geniuses\" (as we put it), through qualities the lack of " 
1364 "which no one who knew what they were would boast of: they all possessed that " 
1365 "seriousness of the efficient workman which first learns to construct the parts " 
1366 "properly before it ventures to fashion a great whole; they allowed themselves " 
1367 "time for it, because they took more pleasure in making the little, secondary " 
1368 "things well than in the effect of a dazzling whole. the recipe for becoming a " 
1369 "good novelist, for example, is easy to give, but to carry it out presupposes " 
1370 "qualities one is accustomed to overlook when one says \"I do not have enough " 
1371 "talent.\" One has only to make a hundred or so sketches for novels, none longer " 
1372 "than two pages but of such distinctness that every word in them is necessary; " 
1373 "one should write down anecdotes each day until one has learned how to give them " 
1374 "the most pregnant and effective form; one should be tireless in collecting and " 
1375 "describing human types and characters; one should above all relate things to " 
1376 "others and listen to others relate, keeping one's eyes and ears open for the " 
1377 "effect produced on those present, one should travel like a landscape painter or " 
1378 "costume designer; one should excerpt for oneself out of the individual sciences " 
1379 "everything that will produce an artistic effect when it is well described, one " 
1380 "should, finally, reflect on the motives of human actions, disdain no signpost " 
1381 "to instruction about them and be a collector of these things by day and night. " 
1382 "One should continue in this many-sided exercise some ten years: what is then " 
1383 "created in the workshop, however, will be fit to go out into the world. What, " 
1384 "however, do most people do? They begin, not with the parts, but with the whole. " 
1385 "Perhaps they chance to strike a right note, excite attention and from then on " 
1386 "strike worse and worse notes, for good, natural reasons. Sometimes, when the " 
1387 "character and intellect needed to formulate such a life-plan are lacking, fate " 
1388 "and need take their place and lead the future master step by step through all " 
1389 "the stipulations of his trade. " 
1391 "164 Peril and profit in the cult of the genius. The belief in great, superior, " 
1392 "fruitful spirits is not necessarily, yet nonetheless is very frequently " 
1393 "associated with that religious or semi-religious superstition that these " 
1394 "spirits are of supra-human origin and possess certain miraculous abilities by " 
1395 "virtue of which they acquire their knowledge by quite other means than the rest " 
1396 "of mankind. One ascribes to them, it seems, a direct view of the nature of the " 
1397 "world, as it were a hole in the cloak of appearance, and believes that, by " 
1398 "virtue of this miraculous seer's vision, they are able to communicate something " 
1399 "conclusive and decisive about man and the world without the toil and " 
1400 "rigorousness required by science. As long as there continue to be those who " 
1401 "believe in the miraculous in the domain of knowledge one can perhaps concede " 
1402 "that these people themselves derive some benefit from their belief, inasmuch as " 
1403 "through their unconditional subjection to the great spirits they create for " 
1404 "their own spirit during its time of development the finest form of discipline " 
1405 "and schooling. On the other hand, it is at least questionable whether the " 
1406 "superstitious belief in genius, in its privileges and special abilities, is of " 
1407 "benefit to the genius himself if it takes root in him. It is in any event a " 
1408 "dangerous sign when a man is assailed by awe of himself, whether it be the " 
1409 "celebrated Caesar's awe of Caesar or the awe of one's own genius now under " 
1410 "consideration; when the sacrificial incense which is properly rendered only to " 
1411 "a god penetrates the brain of the genius, so that his head begins to swim and " 
1412 "he comes to regard himself as something supra-human. The consequences that " 
1413 "slowly result are: the feeling of irresponsibility, of exceptional rights, the " 
1414 "belief that he confers a favor by his mere presence, insane rage when anyone " 
1415 "attempts even to compare him with others, let alone to rate him beneath them, " 
1416 "or to draw attention to lapses in his work. Because he ceases to practice " 
1417 "criticism of himself, at last one pinion after the other falls out of his " 
1418 "plumage: that superstitious eats at the roots of his powers and perhaps even " 
1419 "turns him into a hypocrite after his powers have fled from him. For the great " 
1420 "spirits themselves it is therefore probably more beneficial if they acquire an " 
1421 "insight into the nature and origin of their powers, if they grasp, that is to " 
1422 "say, what purely human qualities have come together in them and what fortunate " 
1423 "circumstances attended them: in the first place undiminished energy, resolute " 
1424 "application to individual goals, great personal courage, then the good fortune " 
1425 "to receive an upbringing which offered in the early years the finest teachers, " 
1426 "models and methods. To be sure, when their goal is the production of the " 
1427 "greatest possible effect, unclarity with regard to oneself and that " 
1428 "semi-insanity superadded to it has always achieved much; for what has been " 
1429 "admired and envied at all times has been that power in them by virtue of which " 
1430 "they render men will-less and sweep them away into the delusion that the " 
1431 "leaders they are following are supra-natural. Indeed, it elevates and inspires " 
1432 "men to believe that someone is in possession of supra-natural powers: to this " 
1433 "extent Plato was right to say [Plato: Phaedrus, 244a] that madness has brought " 
1434 "the greatest of blessings upon mankind. In rare individual cases this portion " 
1435 "of madness may, indeed, actually have been the means by which such a nature, " 
1436 "excessive in all directions, was held firmly together: in the life of " 
1437 "individuals, too, illusions that are in themselves poisons often play the role " 
1438 "of healers; yet, in the end, in the case of every \"genius\" who believes in his " 
1439 "own divinity the poison shows itself to the same degree as his \"genius\" grows " 
1440 "old: one may recall, for example, the case of Napoleon, whose nature certainly " 
1441 "grew into the mighty unity that sets him apart from all men of modern times " 
1442 "precisely through his belief in himself and his star and through the contempt " 
1443 "for men that flowed from it; until in the end, however, this same belief went " 
1444 "over into an almost insane fatalism, robbed him of his acuteness and swiftness " 
1445 "of perception, and became the cause of his destruction.";