X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/57ac1a563e2e0ccaa36472bae30e852d0806bc33..232b2162776e08c0b16d5280b90f5c075f38c667:/samples/scroll/scroll.cpp diff --git a/samples/scroll/scroll.cpp b/samples/scroll/scroll.cpp index f4dd64f70e..98a9d01dad 100644 --- a/samples/scroll/scroll.cpp +++ b/samples/scroll/scroll.cpp @@ -1,84 +1,446 @@ -/* - * Program: scroll - * - * Author: Robert Roebling - * - * Copyright: (C) 1998, Robert Roebling - * 2002, Ron Lee - * 2003, Matt Gregory - * - */ - -// For compilers that support precompilation, includes "wx/wx.h". +///////////////////////////////////////////////////////////////////////////// +// Name: scroll.cpp +// Purpose: wxScrolledWindow sample +// Author: Robert Roebling +// RCS-ID: $Id$ +// Copyright: (C) 1998 Robert Roebling, 2002 Ron Lee, 2003 Matt Gregory +// (C) 2008 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif #ifndef WX_PRECOMP -#include "wx/wx.h" + #include "wx/wx.h" #endif -#include "wx/image.h" -#include "wx/listctrl.h" #include "wx/sizer.h" #include "wx/log.h" +#include "wx/tglbtn.h" +// ---------------------------------------------------------------------------- +// a trivial example +// ---------------------------------------------------------------------------- -// derived classes +// MySimpleCanvas: a scrolled window which draws a simple rectangle +class MySimpleCanvas : public wxScrolledWindow +{ +public: + enum + { + // these numbers are not multiple of 10 (our scroll step) to test for + // the absence of rounding errors (e.g. we should have one more page + // than WIDTH/10 to show the right side of the rectangle) + WIDTH = 292, + HEIGHT = 297 + }; -class MyFrame; -class MyApp; + MySimpleCanvas(wxWindow *parent) + : wxScrolledWindow(parent, wxID_ANY) + { + SetScrollRate( 10, 10 ); + SetVirtualSize( WIDTH, HEIGHT ); + SetBackgroundColour( *wxWHITE ); -// MyCanvas + Connect(wxEVT_PAINT, wxPaintEventHandler(MySimpleCanvas::OnPaint)); + } + +private: + void OnPaint(wxPaintEvent& WXUNUSED(event)) + { + wxPaintDC dc(this); + + // this call is vital: it adjusts the dc to account for the current + // scroll offset + PrepareDC(dc); + + dc.SetPen( *wxRED_PEN ); + dc.SetBrush( *wxTRANSPARENT_BRUSH ); + dc.DrawRectangle( 0, 0, WIDTH, HEIGHT ); + } +}; -class MyCanvas: public wxScrolledWindow + +// MySimpleFrame: a frame which contains a MySimpleCanvas +class MySimpleFrame : public wxFrame { public: - MyCanvas() {} - MyCanvas( wxWindow *parent, wxWindowID, const wxPoint &pos, const wxSize &size ); - ~MyCanvas(){}; - void OnPaint( wxPaintEvent &event ); - void OnQueryPosition( wxCommandEvent &event ); - void OnAddButton( wxCommandEvent &event ); - void OnDeleteButton( wxCommandEvent &event ); - void OnMoveButton( wxCommandEvent &event ); - void OnScrollWin( wxCommandEvent &event ); - void OnMouseDown( wxMouseEvent &event ); + MySimpleFrame(wxWindow *parent) + : wxFrame(parent, wxID_ANY, "MySimpleCanvas") + { + new MySimpleCanvas(this); + + // ensure that we have scrollbars initially + SetClientSize(MySimpleCanvas::WIDTH/2, MySimpleCanvas::HEIGHT/2); + + Show(); + } +}; + +// ---------------------------------------------------------------------- +// a more complex example +// ---------------------------------------------------------------------- + +// MyCanvas +class MyCanvas : public wxScrolledWindow +{ +public: + MyCanvas(wxWindow *parent); + +private: + void OnPaint(wxPaintEvent& event); + void OnQueryPosition(wxCommandEvent& event); + void OnAddButton(wxCommandEvent& event); + void OnDeleteButton(wxCommandEvent& event); + void OnMoveButton(wxCommandEvent& event); + void OnScrollWin(wxCommandEvent& event); + void OnMouseRightDown(wxMouseEvent& event); + void OnMouseWheel(wxMouseEvent& event); wxButton *m_button; - DECLARE_DYNAMIC_CLASS(MyCanvas) DECLARE_EVENT_TABLE() }; +class MyCanvasFrame : public wxFrame +{ +public: + MyCanvasFrame(wxWindow *parent) + : wxFrame(parent, wxID_ANY, "MyCanvas") + { + m_canvas = new MyCanvas(this); + + wxMenu *menuFile = new wxMenu(); + menuFile->Append(wxID_DELETE, "&Delete all"); + menuFile->Append(wxID_NEW, "Insert &new"); + + wxMenuBar *mbar = new wxMenuBar(); + mbar->Append(menuFile, "&File"); + SetMenuBar( mbar ); + + Connect(wxID_DELETE, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyCanvasFrame::OnDeleteAll)); + Connect(wxID_NEW, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyCanvasFrame::OnInsertNew)); + + Show(); + } + +private: + void OnDeleteAll(wxCommandEvent& WXUNUSED(event)) + { + m_canvas->DestroyChildren(); + } + + void OnInsertNew(wxCommandEvent& WXUNUSED(event)) + { + (void)new wxButton(m_canvas, wxID_ANY, "Hello", wxPoint(100,100)); + } + + MyCanvas *m_canvas; +}; // ---------------------------------------------------------------------------- -// Autoscrolling example. +// example using sizers with wxScrolledWindow // ---------------------------------------------------------------------------- -// this class uses the 'virtual' size attribute along with an internal -// sizer to automatically set up scrollbars as needed +const wxSize SMALL_BUTTON( 100, 50 ); +const wxSize LARGE_BUTTON( 300, 200 ); -class MyAutoScrollWindow : public wxScrolledWindow +class MySizerScrolledWindow : public wxScrolledWindow { +public: + MySizerScrolledWindow(wxWindow *parent); + private: + // this button can be clicked to change its own size in the handler below, + // the window size will be automatically adjusted to fit the button + wxButton *m_button; - wxButton *m_button; + void OnResizeClick(wxCommandEvent& event); +}; +class MySizerFrame : public wxFrame +{ public: + MySizerFrame(wxWindow *parent) + : wxFrame(parent, wxID_ANY, "MySizerScrolledWindow") + { + new MySizerScrolledWindow(this); - MyAutoScrollWindow( wxWindow *parent ); + // ensure that the scrollbars appear when the button becomes large + SetClientSize(LARGE_BUTTON/2); + Show(); + } +}; - void OnResizeClick( wxCommandEvent &WXUNUSED( event ) ); +// ---------------------------------------------------------------------------- +// example showing scrolling only part of the window +// ---------------------------------------------------------------------------- - DECLARE_EVENT_TABLE() +// this window consists of an empty space in its corner, column labels window +// along its top, row labels window along its left hand side and a canvas in +// the remaining space + +class MySubColLabels : public wxWindow +{ +public: + MySubColLabels(wxScrolledWindow *parent) + : wxWindow(parent, wxID_ANY) + { + m_owner = parent; + + Connect(wxEVT_PAINT, wxPaintEventHandler(MySubColLabels::OnPaint)); + } + +private: + void OnPaint(wxPaintEvent& WXUNUSED(event)) + { + wxPaintDC dc(this); + + // This is wrong.. it will translate both x and y if the + // window is scrolled, the label windows are active in one + // direction only. Do the action below instead -- RL. + //m_owner->PrepareDC( dc ); + + int xScrollUnits, xOrigin; + + m_owner->GetViewStart( &xOrigin, 0 ); + m_owner->GetScrollPixelsPerUnit( &xScrollUnits, 0 ); + dc.SetDeviceOrigin( -xOrigin * xScrollUnits, 0 ); + + dc.DrawText("Column 1", 5, 5); + dc.DrawText("Column 2", 105, 5); + dc.DrawText("Column 3", 205, 5); + } + + wxScrolledWindow *m_owner; +}; + +class MySubRowLabels : public wxWindow +{ +public: + MySubRowLabels(wxScrolledWindow *parent) + : wxWindow(parent, wxID_ANY) + { + m_owner = parent; + + Connect(wxEVT_PAINT, wxPaintEventHandler(MySubRowLabels::OnPaint)); + } + +private: + void OnPaint(wxPaintEvent& WXUNUSED(event)) + { + wxPaintDC dc(this); + + // This is wrong.. it will translate both x and y if the + // window is scrolled, the label windows are active in one + // direction only. Do the action below instead -- RL. + //m_owner->PrepareDC( dc ); + + int yScrollUnits, yOrigin; + + m_owner->GetViewStart( 0, &yOrigin ); + m_owner->GetScrollPixelsPerUnit( 0, &yScrollUnits ); + dc.SetDeviceOrigin( 0, -yOrigin * yScrollUnits ); + + dc.DrawText("Row 1", 5, 5); + dc.DrawText("Row 2", 5, 30); + dc.DrawText("Row 3", 5, 55); + dc.DrawText("Row 4", 5, 80); + dc.DrawText("Row 5", 5, 105); + dc.DrawText("Row 6", 5, 130); + } + + wxScrolledWindow *m_owner; +}; + +class MySubCanvas : public wxPanel +{ +public: + MySubCanvas(wxScrolledWindow *parent, wxWindow *cols, wxWindow *rows) + : wxPanel(parent, wxID_ANY) + { + m_owner = parent; + m_colLabels = cols; + m_rowLabels = rows; + + (void)new wxButton(this, wxID_ANY, "Hallo I", + wxPoint(0,50), wxSize(100,25) ); + (void)new wxButton(this, wxID_ANY, "Hallo II", + wxPoint(200,50), wxSize(100,25) ); + + (void)new wxTextCtrl(this, wxID_ANY, "Text I", + wxPoint(0,100), wxSize(100,25) ); + (void)new wxTextCtrl(this, wxID_ANY, "Text II", + wxPoint(200,100), wxSize(100,25) ); + + (void)new wxComboBox(this, wxID_ANY, "ComboBox I", + wxPoint(0,150), wxSize(100,25)); + (void)new wxComboBox(this, wxID_ANY, "ComboBox II", + wxPoint(200,150), wxSize(100,25)); + + SetBackgroundColour("WHEAT"); + + Connect(wxEVT_PAINT, wxPaintEventHandler(MySubCanvas::OnPaint)); + } + + // override the base class function so that when this window is scrolled, + // the labels are scrolled in sync + virtual void ScrollWindow(int dx, int dy, const wxRect *rect) + { + wxPanel::ScrollWindow( dx, dy, rect ); + m_colLabels->ScrollWindow( dx, 0, rect ); + m_rowLabels->ScrollWindow( 0, dy, rect ); + } + +private: + void OnPaint(wxPaintEvent& WXUNUSED(event)) + { + wxPaintDC dc( this ); + m_owner->PrepareDC( dc ); + + dc.SetPen( *wxBLACK_PEN ); + + // OK, let's assume we are a grid control and we have two + // grid cells. Here in OnPaint we want to know which cell + // to redraw so that we prevent redrawing cells that don't + // need to get redrawn. We have one cell at (0,0) and one + // more at (200,0), both having a size of (100,25). + + // We can query how much the window has been scrolled + // by calling CalcUnscrolledPosition() + + int scroll_x = 0; + int scroll_y = 0; + m_owner->CalcUnscrolledPosition( scroll_x, scroll_y, &scroll_x, &scroll_y ); + + // We also need to know the size of the window to see which + // cells are completely hidden and not get redrawn + + int size_x = 0; + int size_y = 0; + GetClientSize( &size_x, &size_y ); + + // First cell: (0,0)(100,25) + // It it on screen? + if ((0+100-scroll_x > 0) && (0+25-scroll_y > 0) && + (0-scroll_x < size_x) && (0-scroll_y < size_y)) + { + // Has the region on screen been exposed? + if (IsExposed(0,0,100,25)) + { + dc.DrawRectangle( 0, 0, 100, 25 ); + dc.DrawText("First Cell", 5, 5); + } + } + + + // Second cell: (0,200)(100,25) + // It it on screen? + if ((200+100-scroll_x > 0) && (0+25-scroll_y > 0) && + (200-scroll_x < size_x) && (0-scroll_y < size_y)) + { + // Has the region on screen been exposed? + if (IsExposed(200,0,100,25)) + { + dc.DrawRectangle( 200, 0, 100, 25 ); + dc.DrawText("Second Cell", 205, 5); + } + } + } + + wxScrolledWindow *m_owner; + wxWindow *m_colLabels, + *m_rowLabels; }; +class MySubScrolledWindow : public wxScrolledWindow +{ +public: + enum + { + CORNER_WIDTH = 60, + CORNER_HEIGHT = 25 + }; + + MySubScrolledWindow(wxWindow *parent) + : wxScrolledWindow(parent, wxID_ANY) + { + // create the children + MySubColLabels *cols = new MySubColLabels(this); + MySubRowLabels *rows = new MySubRowLabels(this); + + m_canvas = new MySubCanvas(this, cols, rows); + + // lay them out + wxFlexGridSizer *sizer = new wxFlexGridSizer(2, 2, 10, 10); + sizer->Add(CORNER_WIDTH, CORNER_HEIGHT); // just a spacer + sizer->Add(cols, wxSizerFlags().Expand()); + sizer->Add(rows, wxSizerFlags().Expand()); + sizer->Add(m_canvas, wxSizerFlags().Expand()); + sizer->AddGrowableRow(1); + sizer->AddGrowableCol(1); + SetSizer(sizer); + + // this is the key call: it means that only m_canvas will be scrolled + // and not this window itself + SetTargetWindow(m_canvas); + + SetScrollbars(10, 10, 50, 50); + + Connect(wxEVT_SIZE, wxSizeEventHandler(MySubScrolledWindow::OnSize)); + } + +protected: + // scrolled windows which use scroll target different from the window + // itself must override this virtual method + virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size) + { + // decrease the total size by the size of the non-scrollable parts + // above/to the left of the canvas + wxSize sizeCanvas(size); + sizeCanvas.x -= 60; + sizeCanvas.y -= 25; + return sizeCanvas; + } + +private: + void OnSize(wxSizeEvent& WXUNUSED(event)) + { + // We need to override OnSize so that our scrolled + // window a) does call Layout() to use sizers for + // positioning the controls but b) does not query + // the sizer for their size and use that for setting + // the scrollable area as set that ourselves by + // calling SetScrollbar() further down. + + Layout(); + + AdjustScrollbars(); + } + + MySubCanvas *m_canvas; +}; + +class MySubFrame : public wxFrame +{ +public: + MySubFrame(wxWindow *parent) + : wxFrame(parent, wxID_ANY, "MySubScrolledWindow") + { + new MySubScrolledWindow(this); + + Show(); + } +}; // ---------------------------------------------------------------------------- -// MyScrolledWindow classes: examples of wxScrolledWindow usage +// more simple examples of wxScrolledWindow usage // ---------------------------------------------------------------------------- // base class for both of them @@ -86,19 +448,64 @@ class MyScrolledWindowBase : public wxScrolledWindow { public: MyScrolledWindowBase(wxWindow *parent) - : wxScrolledWindow(parent) - , m_nLines( 100 ) + : wxScrolledWindow(parent, wxID_ANY, + wxDefaultPosition, wxDefaultSize, + wxBORDER_SUNKEN) { + m_nLines = 50; + m_winSync = NULL; + m_inDoSync = false; + wxClientDC dc(this); - dc.GetTextExtent(_T("Line 17"), NULL, &m_hLine); + dc.GetTextExtent("Line 17", NULL, &m_hLine); + } + + // this scrolled window can be synchronized with another one: if this + // function is called with a non-NULL pointer, the given window will be + // scrolled to the same position as this one + void SyncWith(MyScrolledWindowBase *win) + { + m_winSync = win; + + DoSyncIfNecessary(); + } + + virtual void ScrollWindow(int dx, int dy, const wxRect *rect = NULL) + { + wxScrolledWindow::ScrollWindow(dx, dy, rect); + + DoSyncIfNecessary(); } protected: // the height of one line on screen - wxCoord m_hLine; + int m_hLine; // the number of lines we draw size_t m_nLines; + +private: + bool WasScrolledFirst() const { return m_inDoSync; } + + void DoSyncIfNecessary() + { + if ( m_winSync && !m_winSync->WasScrolledFirst() ) + { + m_inDoSync = true; + + m_winSync->Scroll(GetViewStart()); + + m_inDoSync = false; + } + } + + // the window to synchronize with this one or NULL + MyScrolledWindowBase *m_winSync; + + // the flag preventing infinite recursion which would otherwise happen if + // one window synchronized the other one which in turn synchronized this + // one and so on + bool m_inDoSync; }; // this class does "stupid" redrawing - it redraws everything each time @@ -129,35 +536,21 @@ public: { // no horz scrolling SetScrollRate( 0, m_hLine ); - SetVirtualSize( -1, ( m_nLines + 1 ) * m_hLine ); + SetVirtualSize( wxDefaultCoord, ( m_nLines + 1 ) * m_hLine ); } virtual void OnDraw(wxDC& dc); }; // ---------------------------------------------------------------------------- -// MyAutoTimedScrollingWindow: implements a text viewer with simple blocksize -// selection to test auto-scrolling functionality +// implements a text viewer with simple block selection to test auto-scrolling +// functionality // ---------------------------------------------------------------------------- -class MyAutoTimedScrollingWindow : public wxScrolledWindow +class MyAutoScrollingWindow : public wxScrolledWindow { -protected: // member data - // test data variables - static const wxChar* sm_testData; - static const int sm_lineCnt; // line count - static const int sm_lineLen; // line length in characters - // sizes for graphical data - wxCoord m_fontH, m_fontW; - // selection tracking - wxPoint m_selStart; // beginning of blockwise selection - wxPoint m_cursor; // end of blockwise selection (mouse position) - -protected: // gui stuff - wxFont m_font; - -public: // interface - MyAutoTimedScrollingWindow( wxWindow* parent ); +public: + MyAutoScrollingWindow( wxWindow* parent ); wxRect DeviceCoordsToGraphicalChars(wxRect updRect) const; wxPoint DeviceCoordsToGraphicalChars(wxPoint pos) const; wxPoint GraphicalCharToDeviceCoords(wxPoint pos) const; @@ -167,19 +560,49 @@ public: // interface void MyRefresh(); bool IsSelected(int chX, int chY) const; static bool IsInside(int k, int bound1, int bound2); - static wxRect DCNormalize(wxCoord x, wxCoord y, wxCoord w, wxCoord h); + static wxRect DCNormalize(int x, int y, int w, int h); -protected: // event stuff - DECLARE_EVENT_TABLE() +private: + // event handlers void OnDraw(wxDC& dc); void OnMouseLeftDown(wxMouseEvent& event); void OnMouseLeftUp(wxMouseEvent& event); void OnMouseMove(wxMouseEvent& event); + void OnMouseCaptureLost(wxMouseCaptureLostEvent& event); void OnScroll(wxScrollWinEvent& event); + + // test data variables + static const char* sm_testData; + static const int sm_lineCnt; // line count + static const int sm_lineLen; // line length in characters + // sizes for graphical data + int m_fontH, m_fontW; + // selection tracking + wxPoint m_selStart; // beginning of blockwise selection + wxPoint m_cursor; // end of blockwise selection (mouse position) + + // gui stuff + wxFont m_font; + + + DECLARE_EVENT_TABLE() }; +class MyAutoFrame : public wxFrame +{ +public: + MyAutoFrame(wxWindow *parent) + : wxFrame(parent, wxID_ANY, "MyAutoScrollingWindow") + { + new MyAutoScrollingWindow(this); + + Show(); + } +}; + + // ---------------------------------------------------------------------------- -// MyFrame +// MyFrame: the main application frame showing all the classes above // ---------------------------------------------------------------------------- class MyFrame: public wxFrame @@ -187,15 +610,22 @@ class MyFrame: public wxFrame public: MyFrame(); - void OnAbout( wxCommandEvent &event ); - void OnQuit( wxCommandEvent &event ); - void OnDeleteAll( wxCommandEvent &event ); - void OnInsertNew( wxCommandEvent &event ); +private: + void OnAbout(wxCommandEvent& event); + void OnQuit(wxCommandEvent& event); + + void OnTestSimple(wxCommandEvent& WXUNUSED(event)) { new MySimpleFrame(this); } + void OnTestCanvas(wxCommandEvent& WXUNUSED(event)) { new MyCanvasFrame(this); } + void OnTestSizer(wxCommandEvent& WXUNUSED(event)) { new MySizerFrame(this); } + void OnTestSub(wxCommandEvent& WXUNUSED(event)) { new MySubFrame(this); } + void OnTestAuto(wxCommandEvent& WXUNUSED(event)) { new MyAutoFrame(this); } - MyCanvas *m_canvas; - wxTextCtrl *m_log; + void OnToggleSync(wxCommandEvent& event); + void OnScrollbarVisibility(wxCommandEvent& event); + + MyScrolledWindowBase *m_win1, + *m_win2; - DECLARE_DYNAMIC_CLASS(MyFrame) DECLARE_EVENT_TABLE() }; @@ -203,137 +633,85 @@ public: // MyApp // ---------------------------------------------------------------------------- -class MyApp: public wxApp +class MyApp : public wxApp { public: virtual bool OnInit(); }; -// ---------------------------------------------------------------------------- -// main program -// ---------------------------------------------------------------------------- - -IMPLEMENT_APP(MyApp) - -// ids - -const long ID_ADDBUTTON = wxNewId(); -const long ID_DELBUTTON = wxNewId(); -const long ID_MOVEBUTTON = wxNewId(); -const long ID_SCROLLWIN = wxNewId(); -const long ID_QUERYPOS = wxNewId(); - -const long ID_NEWBUTTON = wxNewId(); +// ============================================================================ +// implementation +// ============================================================================ // ---------------------------------------------------------------------------- // MyCanvas // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(MyCanvas, wxScrolledWindow) +const wxWindowID ID_ADDBUTTON = wxWindow::NewControlId(); +const wxWindowID ID_DELBUTTON = wxWindow::NewControlId(); +const wxWindowID ID_MOVEBUTTON = wxWindow::NewControlId(); +const wxWindowID ID_SCROLLWIN = wxWindow::NewControlId(); +const wxWindowID ID_QUERYPOS = wxWindow::NewControlId(); + +const wxWindowID ID_NEWBUTTON = wxWindow::NewControlId(); BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) - EVT_PAINT( MyCanvas::OnPaint) - EVT_MOUSE_EVENTS( MyCanvas::OnMouseDown) - EVT_BUTTON( ID_QUERYPOS, MyCanvas::OnQueryPosition) - EVT_BUTTON( ID_ADDBUTTON, MyCanvas::OnAddButton) - EVT_BUTTON( ID_DELBUTTON, MyCanvas::OnDeleteButton) - EVT_BUTTON( ID_MOVEBUTTON, MyCanvas::OnMoveButton) - EVT_BUTTON( ID_SCROLLWIN, MyCanvas::OnScrollWin) + EVT_PAINT( MyCanvas::OnPaint) + EVT_RIGHT_DOWN( MyCanvas::OnMouseRightDown) + EVT_MOUSEWHEEL( MyCanvas::OnMouseWheel) + EVT_BUTTON( ID_QUERYPOS, MyCanvas::OnQueryPosition) + EVT_BUTTON( ID_ADDBUTTON, MyCanvas::OnAddButton) + EVT_BUTTON( ID_DELBUTTON, MyCanvas::OnDeleteButton) + EVT_BUTTON( ID_MOVEBUTTON, MyCanvas::OnMoveButton) + EVT_BUTTON( ID_SCROLLWIN, MyCanvas::OnScrollWin) END_EVENT_TABLE() -MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id, - const wxPoint &pos, const wxSize &size ) - : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER | wxTAB_TRAVERSAL, _T("test canvas") ) +MyCanvas::MyCanvas(wxWindow *parent) + : wxScrolledWindow(parent, wxID_ANY, + wxDefaultPosition, wxDefaultSize, + wxSUNKEN_BORDER | wxTAB_TRAVERSAL) { + // you can use either a single SetScrollbars() call or these 2 functions, + // usually using them is better because you normally won't need to change + // the scroll rate in the future and the sizer can be used to update the + // virtual size automatically SetScrollRate( 10, 10 ); SetVirtualSize( 500, 1000 ); - (void) new wxButton( this, ID_ADDBUTTON, _T("add button"), wxPoint(10,10) ); - (void) new wxButton( this, ID_DELBUTTON, _T("del button"), wxPoint(10,40) ); - (void) new wxButton( this, ID_MOVEBUTTON, _T("move button"), wxPoint(150,10) ); - (void) new wxButton( this, ID_SCROLLWIN, _T("scroll win"), wxPoint(250,10) ); - -#if 0 - - wxString choices[] = - { - "This", - "is one of my", - "really", - "wonderful", - "examples." - }; - - m_button = new wxButton( this, ID_QUERYPOS, "Query position", wxPoint(10,110) ); - - (void) new wxTextCtrl( this, wxID_ANY, "wxTextCtrl", wxPoint(10,150), wxSize(80,wxDefaultCoord) ); - - (void) new wxRadioButton( this, wxID_ANY, "Disable", wxPoint(10,190) ); - - (void) new wxComboBox( this, wxID_ANY, "This", wxPoint(10,230), wxDefaultSize, 5, choices ); - - (void) new wxRadioBox( this, wxID_ANY, "This", wxPoint(10,310), wxDefaultSize, 5, choices, 2, wxRA_SPECIFY_COLS ); - - (void) new wxRadioBox( this, wxID_ANY, "This", wxPoint(10,440), wxDefaultSize, 5, choices, 2, wxRA_SPECIFY_ROWS ); + (void) new wxButton( this, ID_ADDBUTTON, "add button", wxPoint(10,10) ); + (void) new wxButton( this, ID_DELBUTTON, "del button", wxPoint(10,40) ); + (void) new wxButton( this, ID_MOVEBUTTON, "move button", wxPoint(150,10) ); + (void) new wxButton( this, ID_SCROLLWIN, "scroll win", wxPoint(250,10) ); - wxListCtrl *m_listCtrl = new wxListCtrl( - this, wxID_ANY, wxPoint(200, 110), wxSize(180, 120), - wxLC_REPORT | wxSIMPLE_BORDER | wxLC_SINGLE_SEL ); + wxPanel *test = new wxPanel( this, wxID_ANY, + wxPoint(10, 110), wxSize(130,50), + wxSIMPLE_BORDER | wxTAB_TRAVERSAL ); + test->SetBackgroundColour( "WHEAT" ); - m_listCtrl->InsertColumn(0, "First", wxLIST_FORMAT_LEFT, 90); - m_listCtrl->InsertColumn(1, "Last", wxLIST_FORMAT_LEFT, 90); - - for ( int i=0; i < 30; i++) - { - char buf[20]; - sprintf(buf, "Item %d", i); - m_listCtrl->InsertItem(i, buf); - } - m_listCtrl->SetItemState( 3, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); - - (void) new wxListBox( this, wxID_ANY, wxPoint(260,280), wxSize(120,120), 5, choices, wxLB_ALWAYS_SB ); - -#endif - - wxPanel *test = new wxPanel( this, wxID_ANY, wxPoint(10, 110), wxSize(130,50), wxSIMPLE_BORDER | wxTAB_TRAVERSAL ); - test->SetBackgroundColour( wxT("WHEAT") ); - -#if 0 - - wxButton *test2 = new wxButton( test, wxID_ANY, "Hallo", wxPoint(10,10) ); - - test = new wxPanel( this, wxID_ANY, wxPoint(160, 530), wxSize(130,120), wxSUNKEN_BORDER | wxTAB_TRAVERSAL ); - test->SetBackgroundColour( wxT("WHEAT") ); - test->SetCursor( wxCursor( wxCURSOR_NO_ENTRY ) ); - test2 = new wxButton( test, wxID_ANY, "Hallo", wxPoint(10,10) ); - test2->SetCursor( wxCursor( wxCURSOR_PENCIL ) ); - - test = new wxPanel( this, wxID_ANY, wxPoint(310, 530), wxSize(130,120), wxRAISED_BORDER | wxTAB_TRAVERSAL ); - test->SetBackgroundColour( wxT("WHEAT") ); - test->SetCursor( wxCursor( wxCURSOR_PENCIL ) ); - test2 = new wxButton( test, wxID_ANY, "Hallo", wxPoint(10,10) ); - test2->SetCursor( wxCursor( wxCURSOR_NO_ENTRY ) ); - -#endif - - SetBackgroundColour( wxT("BLUE") ); + SetBackgroundColour( "BLUE" ); +} - SetCursor( wxCursor( wxCURSOR_IBEAM ) ); +void MyCanvas::OnMouseRightDown( wxMouseEvent &event ) +{ + wxPoint pt( event.GetPosition() ); + int x,y; + CalcUnscrolledPosition( pt.x, pt.y, &x, &y ); + wxLogMessage("Mouse down event at: %d %d, scrolled: %d %d", + pt.x, pt.y, x, y); } -void MyCanvas::OnMouseDown( wxMouseEvent &event ) +void MyCanvas::OnMouseWheel( wxMouseEvent &event ) { - if (event.LeftDown()) - { - wxPoint pt( event.GetPosition() ); - int x,y; - CalcUnscrolledPosition( pt.x, pt.y, &x, &y ); - wxLogMessage( wxT("Mouse down event at: %d %d, scrolled: %d %d"), pt.x, pt.y, x, y ); + wxPoint pt( event.GetPosition() ); + int x,y; + CalcUnscrolledPosition( pt.x, pt.y, &x, &y ); + wxLogMessage( "Mouse wheel event at: %d %d, scrolled: %d %d\n" + "Rotation: %d, delta = %d", + pt.x, pt.y, x, y, + event.GetWheelRotation(), event.GetWheelDelta() ); - if ( !event.LeftIsDown() ) - wxLogMessage( wxT("Error: LeftIsDown() should be true if for LeftDown()") ); - } + event.Skip(); } void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) @@ -341,9 +719,9 @@ void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) wxPaintDC dc( this ); PrepareDC( dc ); - dc.DrawText( _T("Press mouse button to test calculations!"), 160, 50 ); + dc.DrawText( "Press right mouse button to test calculations!", 160, 50 ); - dc.DrawText( _T("Some text"), 140, 140 ); + dc.DrawText( "Some text", 140, 140 ); dc.DrawRectangle( 100, 160, 200, 200 ); } @@ -351,122 +729,98 @@ void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) void MyCanvas::OnQueryPosition( wxCommandEvent &WXUNUSED(event) ) { wxPoint pt( m_button->GetPosition() ); - wxLogMessage( wxT("Position of \"Query position\" is %d %d"), pt.x, pt.y ); + wxLogMessage( "Position of \"Query position\" is %d %d", pt.x, pt.y ); pt = ClientToScreen( pt ); - wxLogMessage( wxT("Position of \"Query position\" on screen is %d %d"), pt.x, pt.y ); + wxLogMessage("Position of \"Query position\" on screen is %d %d", + pt.x, pt.y); } void MyCanvas::OnAddButton( wxCommandEvent &WXUNUSED(event) ) { - wxLogMessage( wxT("Inserting button at position 10,70...") ); - wxButton *button = new wxButton( this, ID_NEWBUTTON, wxT("new button"), wxPoint(10,70), wxSize(80,25) ); + wxLogMessage( "Inserting button at position 10,70..." ); + wxButton *button = new wxButton( this, ID_NEWBUTTON, "new button", + wxPoint(10,70), wxSize(80,25) ); wxPoint pt( button->GetPosition() ); - wxLogMessage( wxT("-> Position after inserting %d %d"), pt.x, pt.y ); + wxLogMessage( "-> Position after inserting %d %d", pt.x, pt.y ); } void MyCanvas::OnDeleteButton( wxCommandEvent &WXUNUSED(event) ) { - wxLogMessage( wxT("Deleting button inserted with \"Add button\"...") ); + wxLogMessage( "Deleting button inserted with \"Add button\"..." ); wxWindow *win = FindWindow( ID_NEWBUTTON ); if (win) win->Destroy(); else - wxLogMessage( wxT("-> No window with id = ID_NEWBUTTON found.") ); + wxLogMessage( "-> No window with id = ID_NEWBUTTON found." ); } void MyCanvas::OnMoveButton( wxCommandEvent &event ) { - wxLogMessage( wxT("Moving button 10 pixels downward..") ); + wxLogMessage( "Moving button 10 pixels downward.." ); wxWindow *win = FindWindow( event.GetId() ); wxPoint pt( win->GetPosition() ); - wxLogMessage( wxT("-> Position before move is %d %d"), pt.x, pt.y ); + wxLogMessage( "-> Position before move is %d %d", pt.x, pt.y ); win->Move( wxDefaultCoord, pt.y + 10 ); pt = win->GetPosition(); - wxLogMessage( wxT("-> Position after move is %d %d"), pt.x, pt.y ); + wxLogMessage( "-> Position after move is %d %d", pt.x, pt.y ); } void MyCanvas::OnScrollWin( wxCommandEvent &WXUNUSED(event) ) { - wxLogMessage( wxT("Scrolling 2 units up.\nThe white square and the controls should move equally!") ); - int x,y; - GetViewStart( &x, &y ); - Scroll( -1, y+2 ); + wxLogMessage("Scrolling 2 units up.\n" + "The white square and the controls should move equally!"); + Scroll( wxDefaultCoord, GetViewStart().y+2 ); } // ---------------------------------------------------------------------------- -// MyAutoScrollWindow +// MySizerScrolledWindow // ---------------------------------------------------------------------------- -const long ID_RESIZEBUTTON = wxNewId(); -const wxSize SMALL_BUTTON( 100, 50 ); -const wxSize LARGE_BUTTON( 300, 100 ); - -BEGIN_EVENT_TABLE( MyAutoScrollWindow, wxScrolledWindow) - EVT_BUTTON( ID_RESIZEBUTTON, MyAutoScrollWindow::OnResizeClick) -END_EVENT_TABLE() - -MyAutoScrollWindow::MyAutoScrollWindow( wxWindow *parent ) - : wxScrolledWindow( parent ) +MySizerScrolledWindow::MySizerScrolledWindow(wxWindow *parent) + : wxScrolledWindow(parent) { - SetBackgroundColour( wxT("GREEN") ); + SetBackgroundColour( "GREEN" ); // Set the rate we'd like for scrolling. SetScrollRate( 5, 5 ); - // Populate a sizer with a 'resizing' button and some - // other static decoration + // Populate a sizer with a 'resizing' button and some other static + // decoration - wxFlexGridSizer *innersizer = new wxFlexGridSizer( 2, 2 ); + wxFlexGridSizer *sizer = new wxFlexGridSizer(2); - m_button = new wxButton( this, - ID_RESIZEBUTTON, - _T("Press me"), - wxDefaultPosition, - SMALL_BUTTON ); + m_button = new wxButton( this, wxID_RESIZE_FRAME, "Press me", + wxDefaultPosition, SMALL_BUTTON ); - // We need to do this here, because wxADJUST_MINSIZE below - // will cause the initial size to be ignored for Best/Min size. - // It would be nice to fix the sizers to handle this a little - // more cleanly. - - m_button->SetSizeHints( SMALL_BUTTON.GetWidth(), SMALL_BUTTON.GetHeight() ); - - innersizer->Add( m_button, - 0, - wxALIGN_CENTER | wxALL | wxADJUST_MINSIZE, - 20 ); - - innersizer->Add( new wxStaticText( this, wxID_ANY, _T("This is just") ), - 0, - wxALIGN_CENTER ); - - innersizer->Add( new wxStaticText( this, wxID_ANY, _T("some decoration") ), - 0, - wxALIGN_CENTER ); - - innersizer->Add( new wxStaticText( this, wxID_ANY, _T("for you to scroll...") ), - 0, - wxALIGN_CENTER ); + sizer->Add(m_button, wxSizerFlags().Centre().Border(20)); + sizer->Add(new wxStaticText(this, wxID_ANY, "This is just"), + wxSizerFlags().Centre()); + sizer->Add(new wxStaticText(this, wxID_ANY, "some decoration"), + wxSizerFlags().Centre()); + sizer->Add(new wxStaticText(this, wxID_ANY, "for you to scroll..."), + wxSizerFlags().Centre()); // Then use the sizer to set the scrolled region size. - SetSizer( innersizer ); + SetSizer( sizer ); + + Connect(wxID_RESIZE_FRAME, wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(MySizerScrolledWindow::OnResizeClick)); } -void MyAutoScrollWindow::OnResizeClick( wxCommandEvent &WXUNUSED( event ) ) +void MySizerScrolledWindow::OnResizeClick(wxCommandEvent &WXUNUSED(event)) { // Arbitrarily resize the button to change the minimum size of // the (scrolled) sizer. - if( m_button->GetSize() == SMALL_BUTTON ) - m_button->SetSizeHints( LARGE_BUTTON.GetWidth(), LARGE_BUTTON.GetHeight() ); + if ( m_button->GetSize() == SMALL_BUTTON ) + m_button->SetSizeHints(LARGE_BUTTON); else - m_button->SetSizeHints( SMALL_BUTTON.GetWidth(), SMALL_BUTTON.GetHeight() ); + m_button->SetSizeHints(SMALL_BUTTON); // Force update layout and scrollbars, since nothing we do here // necessarily generates a size event which would do it for us. - FitInside(); } @@ -474,104 +828,161 @@ void MyAutoScrollWindow::OnResizeClick( wxCommandEvent &WXUNUSED( event ) ) // MyFrame // ---------------------------------------------------------------------------- -const long ID_QUIT = wxNewId(); -const long ID_ABOUT = wxNewId(); -const long ID_DELETE_ALL = wxNewId(); -const long ID_INSERT_NEW = wxNewId(); +const wxWindowID Scroll_Test_Simple = wxWindow::NewControlId(); +const wxWindowID Scroll_Test_Canvas = wxWindow::NewControlId(); +const wxWindowID Scroll_Test_Sizers = wxWindow::NewControlId(); +const wxWindowID Scroll_Test_Sub = wxWindow::NewControlId(); +const wxWindowID Scroll_Test_Auto = wxWindow::NewControlId(); -IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) +const wxWindowID Scroll_TglBtn_Sync = wxWindow::NewControlId(); +const wxWindowID Scroll_Radio_ShowScrollbar = wxWindow::NewControlId(); BEGIN_EVENT_TABLE(MyFrame,wxFrame) - EVT_MENU (ID_DELETE_ALL, MyFrame::OnDeleteAll) - EVT_MENU (ID_INSERT_NEW, MyFrame::OnInsertNew) - EVT_MENU (ID_ABOUT, MyFrame::OnAbout) - EVT_MENU (ID_QUIT, MyFrame::OnQuit) + EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) + EVT_MENU(wxID_EXIT, MyFrame::OnQuit) + + EVT_MENU(Scroll_Test_Simple, MyFrame::OnTestSimple) + EVT_MENU(Scroll_Test_Canvas, MyFrame::OnTestCanvas) + EVT_MENU(Scroll_Test_Sizers, MyFrame::OnTestSizer) + EVT_MENU(Scroll_Test_Sub, MyFrame::OnTestSub) + EVT_MENU(Scroll_Test_Auto, MyFrame::OnTestAuto) + + EVT_TOGGLEBUTTON(Scroll_TglBtn_Sync, MyFrame::OnToggleSync) + EVT_RADIOBOX(Scroll_Radio_ShowScrollbar, MyFrame::OnScrollbarVisibility) END_EVENT_TABLE() MyFrame::MyFrame() - : wxFrame( (wxFrame *)NULL, wxID_ANY, _T("wxScrolledWindow sample"), - wxPoint(20,20), wxSize(800,500) ) + : wxFrame(NULL, wxID_ANY, "wxWidgets scroll sample") { - wxMenu *file_menu = new wxMenu(); - file_menu->Append( ID_DELETE_ALL, _T("Delete all")); - file_menu->Append( ID_INSERT_NEW, _T("Insert new")); - file_menu->Append( ID_ABOUT, _T("&About..")); - file_menu->Append( ID_QUIT, _T("E&xit\tAlt-X")); - - wxMenuBar *menu_bar = new wxMenuBar(); - menu_bar->Append(file_menu, _T("&File")); - - SetMenuBar( menu_bar ); - -#if wxUSE_STATUSBAR - CreateStatusBar(2); - int widths[] = { -1, 100 }; - SetStatusWidths( 2, widths ); -#endif // wxUSE_STATUSBAR - - wxBoxSizer *topsizer = new wxBoxSizer( wxHORIZONTAL ); - // subsizer splits topsizer down the middle - wxBoxSizer *subsizer = new wxBoxSizer( wxVERTICAL ); - - // Setting an explicit size here is superfluous, it will be overridden - // by the sizer in any case. - m_canvas = new MyCanvas( this, wxID_ANY, wxPoint(0,0), wxSize(100,100) ); - - // This is done with ScrollRate/VirtualSize in MyCanvas ctor now, - // both should produce identical results. - //m_canvas->SetScrollbars( 10, 10, 50, 100 ); - - subsizer->Add( m_canvas, 1, wxEXPAND ); - subsizer->Add( new MyAutoScrollWindow( this ), 1, wxEXPAND ); - - wxSizer *sizerBtm = new wxBoxSizer(wxHORIZONTAL); - sizerBtm->Add( new MyScrolledWindowDumb(this), 1, wxEXPAND ); - sizerBtm->Add( new MyScrolledWindowSmart(this), 1, wxEXPAND ); - subsizer->Add( sizerBtm, 1, wxEXPAND ); - - topsizer->Add( subsizer, 1, wxEXPAND ); - topsizer->Add( new MyAutoTimedScrollingWindow( this ), 1, wxEXPAND ); - - SetSizer( topsizer ); + wxMenu *menuFile = new wxMenu; + menuFile->Append(wxID_ABOUT, "&About.."); + menuFile->AppendSeparator(); + menuFile->Append(wxID_EXIT, "E&xit\tAlt-X"); + + wxMenu *menuTest = new wxMenu; + menuTest->Append(Scroll_Test_Simple, "&Simple scroll window\tF1", + "Simplest possible scrolled window test."); + menuTest->Append(Scroll_Test_Canvas, "Scrolled window with &children\tF2", + "Scrolled window with controls on it."); + menuTest->Append(Scroll_Test_Sizers, "Scrolled window with si&zer\tF3", + "Scrolled window with children managed by sizer."); + menuTest->Append(Scroll_Test_Sub, "Scrolled s&ub-window\tF4", + "Window only part of which is scrolled."); + menuTest->Append(Scroll_Test_Auto, "&Auto-scrolled window\tF5", + "Window which scrolls when the mouse is held pressed " + "outside of it."); + + wxMenuBar *mbar = new wxMenuBar; + mbar->Append(menuFile, "&File"); + mbar->Append(menuTest, "&Test"); + + SetMenuBar( mbar ); + + + wxPanel *panel = new wxPanel(this); + + const wxSizerFlags flagsExpand(wxSizerFlags(1).Expand()); + + wxSizer *topsizer = new wxBoxSizer(wxVERTICAL); + topsizer->Add(new wxStaticText(panel, wxID_ANY, + "The windows below should behave in the same way, even though\n" + "they're implemented quite differently, see the code for details.\n" + "\n" + "The lines redrawn during odd/even repaint iterations are drawn in\n" + "red/blue colour to allow seeing immediately how much is repainted,\n" + "don't be surprised by this."), + wxSizerFlags().Centre().Border()); + + m_win1 = new MyScrolledWindowDumb(panel); + m_win2 = new MyScrolledWindowSmart(panel); + + wxSizer *sizerScrollWin = new wxBoxSizer(wxHORIZONTAL); + sizerScrollWin->Add(m_win1, flagsExpand); + sizerScrollWin->Add(m_win2, flagsExpand); + topsizer->Add(sizerScrollWin, flagsExpand); + + const wxSizerFlags + flagsHBorder(wxSizerFlags().Centre().Border(wxLEFT | wxRIGHT)); + + wxSizer *sizerBtns = new wxBoxSizer(wxHORIZONTAL); + + // the radio buttons are in the same order as wxSHOW_SB_XXX values but + // offset by 1 + const wxString visibilities[] = { "&never", "&default", "&always" }; + wxRadioBox *radio = new wxRadioBox(panel, Scroll_Radio_ShowScrollbar, + "Left &scrollbar visibility: ", + wxDefaultPosition, wxDefaultSize, + WXSIZEOF(visibilities), visibilities); + radio->SetSelection(wxSHOW_SB_DEFAULT + 1); + sizerBtns->Add(radio, flagsHBorder); + + sizerBtns->Add(new wxToggleButton(panel, Scroll_TglBtn_Sync, "S&ynchronize"), + flagsHBorder); + + topsizer->Add(sizerBtns, wxSizerFlags().Centre().Border()); + + panel->SetSizer(topsizer); + + wxSize size = panel->GetBestSize(); + SetSizeHints(size); + SetClientSize(2*size); + + Show(); } -void MyFrame::OnDeleteAll( wxCommandEvent &WXUNUSED(event) ) +void MyFrame::OnToggleSync(wxCommandEvent& event) { - m_canvas->DestroyChildren(); + if ( event.IsChecked() ) + { + m_win1->SyncWith(m_win2); + m_win2->SyncWith(m_win1); + } + else + { + m_win1->SyncWith(NULL); + m_win2->SyncWith(NULL); + } } -void MyFrame::OnInsertNew( wxCommandEvent &WXUNUSED(event) ) +void MyFrame::OnScrollbarVisibility(wxCommandEvent& event) { - (void)new wxButton( m_canvas, wxID_ANY, _T("Hello"), wxPoint(100,100) ); + m_win1->ShowScrollbars(wxSHOW_SB_NEVER, + wxScrollbarVisibility(event.GetSelection() - 1)); } -void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) ) +void MyFrame::OnQuit(wxCommandEvent &WXUNUSED(event)) { - Close( true ); + Close(true); } void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) ) { - (void)wxMessageBox( _T("wxScroll demo\n") - _T("Robert Roebling (c) 1998\n") - _T("Autoscrolling examples\n") - _T("Ron Lee (c) 2002\n") - _T("Auto-timed-scrolling example\n") - _T("Matt Gregory (c) 2003\n"), - _T("About wxScroll Demo"), - wxICON_INFORMATION | wxOK ); + (void)wxMessageBox( "wxScrolledWindow sample\n" + "\n" + "Robert Roebling (c) 1998\n" + "Vadim Zeitlin (c) 2008\n" + "Autoscrolling examples\n" + "Ron Lee (c) 2002\n" + "Auto-timed-scrolling example\n" + "Matt Gregory (c) 2003\n", + "About wxWidgets scroll sample", + wxICON_INFORMATION | wxOK ); } -//----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // MyApp -//----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +IMPLEMENT_APP(MyApp) bool MyApp::OnInit() { - wxFrame *frame = new MyFrame(); - frame->Show( true ); + if ( !wxApp::OnInit() ) + return false; - return true; + new MyFrame(); + + return true; } // ---------------------------------------------------------------------------- @@ -584,14 +995,14 @@ void MyScrolledWindowDumb::OnDraw(wxDC& dc) static size_t s_redrawCount = 0; dc.SetTextForeground(s_redrawCount++ % 2 ? *wxRED : *wxBLUE); - wxCoord y = 0; + int y = 0; for ( size_t line = 0; line < m_nLines; line++ ) { - wxCoord yPhys; + int yPhys; CalcScrolledPosition(0, y, NULL, &yPhys); - dc.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"), - line, y, yPhys), 0, y); + dc.DrawText(wxString::Format("Line %u (logical %d, physical %d)", + unsigned(line), y, yPhys), 0, y); y += m_hLine; } } @@ -613,47 +1024,47 @@ void MyScrolledWindowSmart::OnDraw(wxDC& dc) if ( lineTo > m_nLines - 1) lineTo = m_nLines - 1; - wxCoord y = lineFrom*m_hLine; + int y = lineFrom*m_hLine; for ( size_t line = lineFrom; line <= lineTo; line++ ) { - wxCoord yPhys; + int yPhys; CalcScrolledPosition(0, y, NULL, &yPhys); - dc.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"), - line, y, yPhys), 0, y); + dc.DrawText(wxString::Format("Line %u (logical %d, physical %d)", + unsigned(line), y, yPhys), 0, y); y += m_hLine; } } // ---------------------------------------------------------------------------- -// MyAutoTimedScrollingWindow +// MyAutoScrollingWindow // ---------------------------------------------------------------------------- -BEGIN_EVENT_TABLE(MyAutoTimedScrollingWindow, wxScrolledWindow) - EVT_LEFT_DOWN(OnMouseLeftDown) - EVT_LEFT_UP(OnMouseLeftUp) - EVT_MOTION(OnMouseMove) - EVT_SCROLLWIN(OnScroll) +BEGIN_EVENT_TABLE(MyAutoScrollingWindow, wxScrolledWindow) + EVT_LEFT_DOWN(MyAutoScrollingWindow::OnMouseLeftDown) + EVT_LEFT_UP(MyAutoScrollingWindow::OnMouseLeftUp) + EVT_MOTION(MyAutoScrollingWindow::OnMouseMove) + EVT_MOUSE_CAPTURE_LOST(MyAutoScrollingWindow::OnMouseCaptureLost) + EVT_SCROLLWIN(MyAutoScrollingWindow::OnScroll) END_EVENT_TABLE() -MyAutoTimedScrollingWindow::MyAutoTimedScrollingWindow(wxWindow* parent) - : wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize - //, wxSUNKEN_BORDER) // can't seem to do it this way - , wxVSCROLL | wxHSCROLL | wxSUNKEN_BORDER) - , m_selStart(-1, -1), m_cursor(-1, -1) - , m_font(9, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL - , wxFONTWEIGHT_NORMAL) +MyAutoScrollingWindow::MyAutoScrollingWindow(wxWindow* parent) + : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, + wxVSCROLL | wxHSCROLL | wxSUNKEN_BORDER), + m_selStart(-1, -1), + m_cursor(-1, -1), + m_font(9, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL) { wxClientDC dc(this); // query dc for text size dc.SetFont(m_font); - dc.GetTextExtent(wxString(_T("A")), &m_fontW, &m_fontH); + dc.GetTextExtent(wxString("A"), &m_fontW, &m_fontH); // set up the virtual window SetScrollbars(m_fontW, m_fontH, sm_lineLen, sm_lineCnt); } -wxRect MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars - (wxRect updRect) const +wxRect +MyAutoScrollingWindow::DeviceCoordsToGraphicalChars(wxRect updRect) const { wxPoint pos(updRect.GetPosition()); pos = DeviceCoordsToGraphicalChars(pos); @@ -668,32 +1079,26 @@ wxRect MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars return updRect; } -wxPoint MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars - (wxPoint pos) const +wxPoint +MyAutoScrollingWindow::DeviceCoordsToGraphicalChars(wxPoint pos) const { pos.x /= m_fontW; pos.y /= m_fontH; - int vX, vY; - GetViewStart(&vX, &vY); - pos.x += vX; - pos.y += vY; + pos += GetViewStart(); return pos; } -wxPoint MyAutoTimedScrollingWindow::GraphicalCharToDeviceCoords - (wxPoint pos) const +wxPoint +MyAutoScrollingWindow::GraphicalCharToDeviceCoords(wxPoint pos) const { - int vX, vY; - GetViewStart(&vX, &vY); - pos.x -= vX; - pos.y -= vY; + pos -= GetViewStart(); pos.x *= m_fontW; pos.y *= m_fontH; return pos; } -wxRect MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars - (wxRect updRect) const +wxRect +MyAutoScrollingWindow::LogicalCoordsToGraphicalChars(wxRect updRect) const { wxPoint pos(updRect.GetPosition()); pos = LogicalCoordsToGraphicalChars(pos); @@ -708,23 +1113,23 @@ wxRect MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars return updRect; } -wxPoint MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars - (wxPoint pos) const +wxPoint +MyAutoScrollingWindow::LogicalCoordsToGraphicalChars(wxPoint pos) const { pos.x /= m_fontW; pos.y /= m_fontH; return pos; } -wxPoint MyAutoTimedScrollingWindow::GraphicalCharToLogicalCoords - (wxPoint pos) const +wxPoint +MyAutoScrollingWindow::GraphicalCharToLogicalCoords(wxPoint pos) const { pos.x *= m_fontW; pos.y *= m_fontH; return pos; } -void MyAutoTimedScrollingWindow::MyRefresh() +void MyAutoScrollingWindow::MyRefresh() { static wxPoint lastSelStart(-1, -1), lastCursor(-1, -1); // refresh last selected area (to deselect previously selected text) @@ -745,10 +1150,10 @@ void MyAutoTimedScrollingWindow::MyRefresh() updRect.width += m_fontW; // kludge updRect.height += m_fontH; // kludge // find necessary refresh areas - wxCoord rx = lastUpdRect.x; - wxCoord ry = lastUpdRect.y; - wxCoord rw = updRect.x - lastUpdRect.x; - wxCoord rh = lastUpdRect.height; + int rx = lastUpdRect.x; + int ry = lastUpdRect.y; + int rw = updRect.x - lastUpdRect.x; + int rh = lastUpdRect.height; if (rw && rh) { RefreshRect(DCNormalize(rx, ry, rw, rh)); } @@ -778,25 +1183,25 @@ void MyAutoTimedScrollingWindow::MyRefresh() lastCursor = m_cursor; } -bool MyAutoTimedScrollingWindow::IsSelected(int chX, int chY) const +bool MyAutoScrollingWindow::IsSelected(int chX, int chY) const { if (IsInside(chX, m_selStart.x, m_cursor.x) && IsInside(chY, m_selStart.y, m_cursor.y)) { - return TRUE; + return true; } - return FALSE; + return false; } -bool MyAutoTimedScrollingWindow::IsInside(int k, int bound1, int bound2) +bool MyAutoScrollingWindow::IsInside(int k, int bound1, int bound2) { if ((k >= bound1 && k <= bound2) || (k >= bound2 && k <= bound1)) { - return TRUE; + return true; } - return FALSE; + return false; } -wxRect MyAutoTimedScrollingWindow::DCNormalize(wxCoord x, wxCoord y - , wxCoord w, wxCoord h) +wxRect +MyAutoScrollingWindow::DCNormalize(int x, int y, int w, int h) { // this is needed to get rid of the graphical remnants from the selection // I think it's because DrawRectangle() excludes a pixel in either direction @@ -819,7 +1224,7 @@ wxRect MyAutoTimedScrollingWindow::DCNormalize(wxCoord x, wxCoord y return wxRect(x, y, w, h); } -void MyAutoTimedScrollingWindow::OnDraw(wxDC& dc) +void MyAutoScrollingWindow::OnDraw(wxDC& dc) { dc.SetFont(m_font); wxBrush normBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) @@ -827,16 +1232,20 @@ void MyAutoTimedScrollingWindow::OnDraw(wxDC& dc) wxBrush selBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT) , wxSOLID); dc.SetPen(*wxTRANSPARENT_PEN); + const wxString str = sm_testData; + size_t strLength = str.length(); + wxString::const_iterator str_i; + // draw the characters // 1. for each update region for (wxRegionIterator upd(GetUpdateRegion()); upd; ++upd) { - wxSize clientSize = GetClientSize(); wxRect updRect = upd.GetRect(); wxRect updRectInGChars(DeviceCoordsToGraphicalChars(updRect)); // 2. for each row of chars in the update region for (int chY = updRectInGChars.y ; chY <= updRectInGChars.y + updRectInGChars.height; ++chY) { // 3. for each character in the row + bool isFirstX = true; for (int chX = updRectInGChars.x ; chX <= updRectInGChars.x + updRectInGChars.width ; ++chX) { @@ -855,17 +1264,25 @@ void MyAutoTimedScrollingWindow::OnDraw(wxDC& dc) (chX, chY)); // 6. draw! dc.DrawRectangle(charPos.x, charPos.y, m_fontW, m_fontH); - if (chY < sm_lineCnt && chX < sm_lineLen) { - int charIndex = chY * sm_lineLen + chX; - dc.DrawText(wxString(sm_testData[charIndex]) - , charPos.x, charPos.y); + size_t charIndex = chY * sm_lineLen + chX; + if (chY < sm_lineCnt && + chX < sm_lineLen && + charIndex < strLength) + { + if (isFirstX) + { + str_i = str.begin() + charIndex; + isFirstX = false; + } + dc.DrawText(*str_i, charPos.x, charPos.y); + ++str_i; } } } } } -void MyAutoTimedScrollingWindow::OnMouseLeftDown(wxMouseEvent& event) +void MyAutoScrollingWindow::OnMouseLeftDown(wxMouseEvent& event) { // initial press of mouse button sets the beginning of the selection m_selStart = DeviceCoordsToGraphicalChars(event.GetPosition()); @@ -875,7 +1292,7 @@ void MyAutoTimedScrollingWindow::OnMouseLeftDown(wxMouseEvent& event) MyRefresh(); } -void MyAutoTimedScrollingWindow::OnMouseLeftUp(wxMouseEvent& WXUNUSED(event)) +void MyAutoScrollingWindow::OnMouseLeftUp(wxMouseEvent& WXUNUSED(event)) { // this test is necessary if (HasCapture()) { @@ -884,7 +1301,7 @@ void MyAutoTimedScrollingWindow::OnMouseLeftUp(wxMouseEvent& WXUNUSED(event)) } } -void MyAutoTimedScrollingWindow::OnMouseMove(wxMouseEvent& event) +void MyAutoScrollingWindow::OnMouseMove(wxMouseEvent& event) { // if user is dragging if (event.Dragging() && event.LeftIsDown()) { @@ -899,21 +1316,29 @@ void MyAutoTimedScrollingWindow::OnMouseMove(wxMouseEvent& event) } } -void MyAutoTimedScrollingWindow::OnScroll(wxScrollWinEvent& event) +void +MyAutoScrollingWindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& + WXUNUSED(event)) +{ + // we only capture mouse for timed scrolling, so nothing is needed here + // other than making sure to not call event.Skip() +} + +void MyAutoScrollingWindow::OnScroll(wxScrollWinEvent& event) { // need to move the cursor when autoscrolling // FIXME: the cursor also moves when the scrollbar arrows are clicked if (HasCapture()) { if (event.GetOrientation() == wxHORIZONTAL) { - if (event.m_eventType == wxEVT_SCROLLWIN_LINEUP) { + if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP) { --m_cursor.x; - } else if (event.m_eventType == wxEVT_SCROLLWIN_LINEDOWN) { + } else if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN) { ++m_cursor.x; } } else if (event.GetOrientation() == wxVERTICAL) { - if (event.m_eventType == wxEVT_SCROLLWIN_LINEUP) { + if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP) { --m_cursor.y; - } else if (event.m_eventType == wxEVT_SCROLLWIN_LINEDOWN) { + } else if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN) { ++m_cursor.y; } } @@ -922,137 +1347,129 @@ void MyAutoTimedScrollingWindow::OnScroll(wxScrollWinEvent& event) event.Skip(); } -const int MyAutoTimedScrollingWindow::sm_lineCnt = 125; -const int MyAutoTimedScrollingWindow::sm_lineLen = 79; -const wxChar* MyAutoTimedScrollingWindow::sm_testData = _T("\ -162 Cult of the genius out of vanity.— Because we think well of ourselves, but \ -nonetheless never suppose ourselves capable of producing a painting like one of\ -Raphael's or a dramatic scene like one of Shakespeare's, we convince ourselves \ -that the capacity to do so is quite extraordinarily marvelous, a wholly \ -uncommon accident, or, if we are still religiously inclined, a mercy from on \ -high. Thus our vanity, our self-love, promotes the cult of the genius: for only\ -if we think of him as being very remote from us, as a miraculum, does he not \ -aggrieve us (even Goethe, who was without envy, called Shakespeare his star of \ -the most distant heights [\"William! Stern der schönsten Ferne\": from Goethe's, \ -\"Between Two Worlds\"]; in regard to which one might recall the lines: \"the \ -stars, these we do not desire\" [from Goethe's, \"Comfort in Tears\"]). But, aside\ -from these suggestions of our vanity, the activity of the genius seems in no \ -way fundamentally different from the activity of the inventor of machines, the \ -scholar of astronomy or history, the master of tactics. All these activities \ -are explicable if one pictures to oneself people whose thinking is active in \ -one direction, who employ everything as material, who always zealously observe \ -their own inner life and that of others, who perceive everywhere models and \ -incentives, who never tire of combining together the means available to them. \ -Genius too does nothing except learn first how to lay bricks then how to build,\ -except continually seek for material and continually form itself around it. \ -Every activity of man is amazingly complicated, not only that of the genius: \ -but none is a \"miracle.\"— Whence, then, the belief that genius exists only in \ -the artist, orator and philosopher? that only they have \"intuition\"? (Whereby \ -they are supposed to possess a kind of miraculous eyeglass with which they can \ -see directly into \"the essence of the thing\"!) It is clear that people speak of\ -") _T("\ -genius only where the effects of the great intellect are most pleasant to them \ -and where they have no desire to feel envious. To call someone \"divine\" means: \ -\"here there is no need for us to compete.\" Then, everything finished and \ -complete is regarded with admiration, everything still becoming is undervalued.\ -But no one can see in the work of the artist how it has become; that is its \ -advantage, for wherever one can see the act of becoming one grows somewhat \ -cool. The finished and perfect art of representation repulses all thinking as \ -to how it has become; it tyrannizes as present completeness and perfection. \ -That is why the masters of the art of representation count above all as gifted \ -with genius and why men of science do not. In reality, this evaluation of the \ -former and undervaluation of the latter is only a piece of childishness in the \ -realm of reason. \ - \ - \ -163 The serious workman.— Do not talk about giftedness, inborn talents! One can\ -name great men of all kinds who were very little gifted. The acquired \ -greatness, became \"geniuses\" (as we put it), through qualities the lack of \ -which no one who knew what they were would boast of: they all possessed that \ -seriousness of the efficient workman which first learns to construct the parts \ -properly before it ventures to fashion a great whole; they allowed themselves \ -time for it, because they took more pleasure in making the little, secondary \ -things well than in the effect of a dazzling whole. the recipe for becoming a \ -good novelist, for example, is easy to give, but to carry it out presupposes \ -qualities one is accustomed to overlook when one says \"I do not have enough \ -talent.\" One has only to make a hundred or so sketches for novels, none longer \ -") _T("\ -than two pages but of such distinctness that every word in them is necessary; \ -one should write down anecdotes each day until one has learned how to give them\ -the most pregnant and effective form; one should be tireless in collecting and \ -describing human types and characters; one should above all relate things to \ -others and listen to others relate, keeping one's eyes and ears open for the \ -effect produced on those present, one should travel like a landscape painter or\ -costume designer; one should excerpt for oneself out of the individual sciences\ -everything that will produce an artistic effect when it is well described, one \ -should, finally, reflect on the motives of human actions, disdain no signpost \ -to instruction about them and be a collector of these things by day and night. \ -One should continue in this many-sided exercise some ten years: what is then \ -created in the workshop, however, will be fit to go out into the world.— What, \ -however, do most people do? They begin, not with the parts, but with the whole.\ -Perhaps they chance to strike a right note, excite attention and from then on \ -strike worse and worse notes, for good, natural reasons.— Sometimes, when the \ -character and intellect needed to formulate such a life-plan are lacking, fate \ -and need take their place and lead the future master step by step through all \ -the stipulations of his trade. \ - \ - \ -164 Peril and profit in the cult of the genius.— The belief in great, superior,\ -fruitful spirits is not necessarily, yet nonetheless is very frequently \ -associated with that religious or semi-religious superstition that these \ -spirits are of supra-human origin and possess certain miraculous abilities by \ -virtue of which they acquire their knowledge by quite other means than the rest\ -") _T("\ -of mankind. One ascribes to them, it seems, a direct view of the nature of the \ -world, as it were a hole in the cloak of appearance, and believes that, by \ -virtue of this miraculous seer's vision, they are able to communicate something\ -conclusive and decisive about man and the world without the toil and \ -rigorousness required by science. As long as there continue to be those who \ -believe in the miraculous in the domain of knowledge one can perhaps concede \ -that these people themselves derive some benefit from their belief, inasmuch as\ -through their unconditional subjection to the great spirits they create for \ -their own spirit during its time of development the finest form of discipline \ -and schooling. On the other hand, it is at least questionable whether the \ -superstitious belief in genius, in its privileges and special abilities, is of \ -benefit to the genius himself if it takes root in him. It is in any event a \ -dangerous sign when a man is assailed by awe of himself, whether it be the \ -celebrated Caesar's awe of Caesar or the awe of one's own genius now under \ -consideration; when the sacrificial incense which is properly rendered only to \ -a god penetrates the brain of the genius, so that his head begins to swim and \ -he comes to regard himself as something supra-human. The consequences that \ -slowly result are: the feeling of irresponsibility, of exceptional rights, the \ -belief that he confers a favor by his mere presence, insane rage when anyone \ -attempts even to compare him with others, let alone to rate him beneath them, \ -or to draw attention to lapses in his work. Because he ceases to practice \ -criticism of himself, at last one pinion after the other falls out of his \ -plumage: that superstitious eats at the roots of his powers and perhaps even \ -turns him into a hypocrite after his powers have fled from him. For the great \ -spirits themselves it is therefore probably more beneficial if they acquire an \ -") _T("\ -insight into the nature and origin of their powers, if they grasp, that is to \ -say, what purely human qualities have come together in them and what fortunate \ -circumstances attended them: in the first place undiminished energy, resolute \ -application to individual goals, great personal courage, then the good fortune \ -to receive an upbringing which offered in the early years the finest teachers, \ -models and methods. To be sure, when their goal is the production of the \ -greatest possible effect, unclarity with regard to oneself and that \ -semi-insanity superadded to it has always achieved much; for what has been \ -admired and envied at all times has been that power in them by virtue of which \ -they render men will-less and sweep them away into the delusion that the \ -leaders they are following are supra-natural. Indeed, it elevates and inspires \ -men to believe that someone is in possession of supra-natural powers: to this \ -extent Plato was right to say [Plato: Phaedrus, 244a] that madness has brought \ -the greatest of blessings upon mankind.— In rare individual cases this portion \ -of madness may, indeed, actually have been the means by which such a nature, \ -excessive in all directions, was held firmly together: in the life of \ -individuals, too, illusions that are in themselves poisons often play the role \ -of healers; yet, in the end, in the case of every \"genius\" who believes in his \ -own divinity the poison shows itself to the same degree as his \"genius\" grows \ -old: one may recall, for example, the case of Napoleon, whose nature certainly \ -grew into the mighty unity that sets him apart from all men of modern times \ -precisely through his belief in himself and his star and through the contempt \ -for men that flowed from it; until in the end, however, this same belief went \ -over into an almost insane fatalism, robbed him of his acuteness and swiftness \ -of perception, and became the cause of his destruction. \ -"); - +const int MyAutoScrollingWindow::sm_lineCnt = 125; +const int MyAutoScrollingWindow::sm_lineLen = 79; +const char *MyAutoScrollingWindow::sm_testData = +"162 Cult of the genius out of vanity. Because we think well of ourselves, but " +"nonetheless never suppose ourselves capable of producing a painting like one of " +"Raphael's or a dramatic scene like one of Shakespeare's, we convince ourselves " +"that the capacity to do so is quite extraordinarily marvelous, a wholly " +"uncommon accident, or, if we are still religiously inclined, a mercy from on " +"high. Thus our vanity, our self-love, promotes the cult of the genius: for only " +"if we think of him as being very remote from us, as a miraculum, does he not " +"aggrieve us (even Goethe, who was without envy, called Shakespeare his star of " +"the most distant heights [\"William! Stern der schonsten Ferne\": from Goethe's, " +"\"Between Two Worlds\"]; in regard to which one might recall the lines: \"the " +"stars, these we do not desire\" [from Goethe's, \"Comfort in Tears\"]). But, aside " +"from these suggestions of our vanity, the activity of the genius seems in no " +"way fundamentally different from the activity of the inventor of machines, the " +"scholar of astronomy or history, the master of tactics. All these activities " +"are explicable if one pictures to oneself people whose thinking is active in " +"one direction, who employ everything as material, who always zealously observe " +"their own inner life and that of others, who perceive everywhere models and " +"incentives, who never tire of combining together the means available to them. " +"Genius too does nothing except learn first how to lay bricks then how to build, " +"except continually seek for material and continually form itself around it. " +"Every activity of man is amazingly complicated, not only that of the genius: " +"but none is a \"miracle.\" Whence, then, the belief that genius exists only in " +"the artist, orator and philosopher? that only they have \"intuition\"? (Whereby " +"they are supposed to possess a kind of miraculous eyeglass with which they can " +"see directly into \"the essence of the thing\"!) It is clear that people speak of " +"genius only where the effects of the great intellect are most pleasant to them " +"and where they have no desire to feel envious. To call someone \"divine\" means: " +"\"here there is no need for us to compete.\" Then, everything finished and " +"complete is regarded with admiration, everything still becoming is undervalued. " +"But no one can see in the work of the artist how it has become; that is its " +"advantage, for wherever one can see the act of becoming one grows somewhat " +"cool. The finished and perfect art of representation repulses all thinking as " +"to how it has become; it tyrannizes as present completeness and perfection. " +"That is why the masters of the art of representation count above all as gifted " +"with genius and why men of science do not. In reality, this evaluation of the " +"former and undervaluation of the latter is only a piece of childishness in the " +"realm of reason. " +"\n\n" +"163 The serious workman. Do not talk about giftedness, inborn talents! One can " +"name great men of all kinds who were very little gifted. The acquired " +"greatness, became \"geniuses\" (as we put it), through qualities the lack of " +"which no one who knew what they were would boast of: they all possessed that " +"seriousness of the efficient workman which first learns to construct the parts " +"properly before it ventures to fashion a great whole; they allowed themselves " +"time for it, because they took more pleasure in making the little, secondary " +"things well than in the effect of a dazzling whole. the recipe for becoming a " +"good novelist, for example, is easy to give, but to carry it out presupposes " +"qualities one is accustomed to overlook when one says \"I do not have enough " +"talent.\" One has only to make a hundred or so sketches for novels, none longer " +"than two pages but of such distinctness that every word in them is necessary; " +"one should write down anecdotes each day until one has learned how to give them " +"the most pregnant and effective form; one should be tireless in collecting and " +"describing human types and characters; one should above all relate things to " +"others and listen to others relate, keeping one's eyes and ears open for the " +"effect produced on those present, one should travel like a landscape painter or " +"costume designer; one should excerpt for oneself out of the individual sciences " +"everything that will produce an artistic effect when it is well described, one " +"should, finally, reflect on the motives of human actions, disdain no signpost " +"to instruction about them and be a collector of these things by day and night. " +"One should continue in this many-sided exercise some ten years: what is then " +"created in the workshop, however, will be fit to go out into the world. What, " +"however, do most people do? They begin, not with the parts, but with the whole. " +"Perhaps they chance to strike a right note, excite attention and from then on " +"strike worse and worse notes, for good, natural reasons. Sometimes, when the " +"character and intellect needed to formulate such a life-plan are lacking, fate " +"and need take their place and lead the future master step by step through all " +"the stipulations of his trade. " +"\n\n" +"164 Peril and profit in the cult of the genius. The belief in great, superior, " +"fruitful spirits is not necessarily, yet nonetheless is very frequently " +"associated with that religious or semi-religious superstition that these " +"spirits are of supra-human origin and possess certain miraculous abilities by " +"virtue of which they acquire their knowledge by quite other means than the rest " +"of mankind. One ascribes to them, it seems, a direct view of the nature of the " +"world, as it were a hole in the cloak of appearance, and believes that, by " +"virtue of this miraculous seer's vision, they are able to communicate something " +"conclusive and decisive about man and the world without the toil and " +"rigorousness required by science. As long as there continue to be those who " +"believe in the miraculous in the domain of knowledge one can perhaps concede " +"that these people themselves derive some benefit from their belief, inasmuch as " +"through their unconditional subjection to the great spirits they create for " +"their own spirit during its time of development the finest form of discipline " +"and schooling. On the other hand, it is at least questionable whether the " +"superstitious belief in genius, in its privileges and special abilities, is of " +"benefit to the genius himself if it takes root in him. It is in any event a " +"dangerous sign when a man is assailed by awe of himself, whether it be the " +"celebrated Caesar's awe of Caesar or the awe of one's own genius now under " +"consideration; when the sacrificial incense which is properly rendered only to " +"a god penetrates the brain of the genius, so that his head begins to swim and " +"he comes to regard himself as something supra-human. The consequences that " +"slowly result are: the feeling of irresponsibility, of exceptional rights, the " +"belief that he confers a favor by his mere presence, insane rage when anyone " +"attempts even to compare him with others, let alone to rate him beneath them, " +"or to draw attention to lapses in his work. Because he ceases to practice " +"criticism of himself, at last one pinion after the other falls out of his " +"plumage: that superstitious eats at the roots of his powers and perhaps even " +"turns him into a hypocrite after his powers have fled from him. For the great " +"spirits themselves it is therefore probably more beneficial if they acquire an " +"insight into the nature and origin of their powers, if they grasp, that is to " +"say, what purely human qualities have come together in them and what fortunate " +"circumstances attended them: in the first place undiminished energy, resolute " +"application to individual goals, great personal courage, then the good fortune " +"to receive an upbringing which offered in the early years the finest teachers, " +"models and methods. To be sure, when their goal is the production of the " +"greatest possible effect, unclarity with regard to oneself and that " +"semi-insanity superadded to it has always achieved much; for what has been " +"admired and envied at all times has been that power in them by virtue of which " +"they render men will-less and sweep them away into the delusion that the " +"leaders they are following are supra-natural. Indeed, it elevates and inspires " +"men to believe that someone is in possession of supra-natural powers: to this " +"extent Plato was right to say [Plato: Phaedrus, 244a] that madness has brought " +"the greatest of blessings upon mankind. In rare individual cases this portion " +"of madness may, indeed, actually have been the means by which such a nature, " +"excessive in all directions, was held firmly together: in the life of " +"individuals, too, illusions that are in themselves poisons often play the role " +"of healers; yet, in the end, in the case of every \"genius\" who believes in his " +"own divinity the poison shows itself to the same degree as his \"genius\" grows " +"old: one may recall, for example, the case of Napoleon, whose nature certainly " +"grew into the mighty unity that sets him apart from all men of modern times " +"precisely through his belief in himself and his star and through the contempt " +"for men that flowed from it; until in the end, however, this same belief went " +"over into an almost insane fatalism, robbed him of his acuteness and swiftness " +"of perception, and became the cause of his destruction.";