X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d9f4cc10605b4e68856ea67d9246605bcacab5ff..c29c95fe24973b94fd724db767193171ca7c513d:/samples/scroll/scroll.cpp?ds=sidebyside diff --git a/samples/scroll/scroll.cpp b/samples/scroll/scroll.cpp index a22c23e2a9..281ee38b92 100644 --- a/samples/scroll/scroll.cpp +++ b/samples/scroll/scroll.cpp @@ -1,199 +1,515 @@ ///////////////////////////////////////////////////////////////////////////// // Name: scroll.cpp -// Purpose: wxScrolledWindow sample +// Purpose: wxScrolled sample // Author: Robert Roebling -// Modified by: -// Created: // RCS-ID: $Id$ // Copyright: (C) 1998 Robert Roebling, 2002 Ron Lee, 2003 Matt Gregory -// Licence: wxWindows license +// (C) 2008 Vadim Zeitlin +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -// For compilers that support precompilation, includes "wx/wx.h". #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" -const long ID_QUIT = wxID_EXIT; -const long ID_ABOUT = wxID_ABOUT; -const long ID_DELETE_ALL = 100; -const long ID_INSERT_NEW = 101; +#ifndef __WXMSW__ + #include "../sample.xpm" +#endif -// ---------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // a trivial example -// ---------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // MySimpleCanvas: a scrolled window which draws a simple rectangle -class MySimpleCanvas: public wxScrolledWindow +class MySimpleCanvas : public wxScrolled { public: - MySimpleCanvas() { } - MySimpleCanvas(wxWindow *parent); - -private: - void OnPaint(wxPaintEvent& event); - enum { - CANVAS_WIDTH = 292, - CANVAS_HEIGHT = 297 + // 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 }; - DECLARE_DYNAMIC_CLASS(MyCanvas) - DECLARE_EVENT_TABLE() -}; + MySimpleCanvas(wxWindow *parent) + : wxScrolled(parent, wxID_ANY) + { + SetScrollRate( 10, 10 ); + SetVirtualSize( WIDTH, HEIGHT ); + SetBackgroundColour( *wxWHITE ); -IMPLEMENT_DYNAMIC_CLASS(MySimpleCanvas, wxScrolledWindow) + Connect(wxEVT_PAINT, wxPaintEventHandler(MySimpleCanvas::OnPaint)); + } -BEGIN_EVENT_TABLE(MySimpleCanvas, wxScrolledWindow) - EVT_PAINT( MySimpleCanvas::OnPaint) -END_EVENT_TABLE() +private: + void OnPaint(wxPaintEvent& WXUNUSED(event)) + { + wxPaintDC dc(this); -MySimpleCanvas::MySimpleCanvas(wxWindow *parent) - : wxScrolledWindow(parent, wxID_ANY, - wxDefaultPosition, - wxDefaultSize, - wxSUNKEN_BORDER) -{ - SetScrollRate( 10, 10 ); - SetVirtualSize( CANVAS_WIDTH, CANVAS_HEIGHT ); - SetBackgroundColour( *wxWHITE ); -} + // this call is vital: it adjusts the dc to account for the current + // scroll offset + PrepareDC(dc); -void MySimpleCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) -{ - wxPaintDC dc(this); - PrepareDC( dc ); + dc.SetPen( *wxRED_PEN ); + dc.SetBrush( *wxTRANSPARENT_BRUSH ); + dc.DrawRectangle( 0, 0, WIDTH, HEIGHT ); + } +}; - dc.SetPen( *wxRED_PEN ); - dc.SetBrush( *wxTRANSPARENT_BRUSH ); - dc.DrawRectangle( 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT ); -} // MySimpleFrame: a frame which contains a MySimpleCanvas -class MySimpleFrame: public wxFrame +class MySimpleFrame : public wxFrame { public: - MySimpleFrame(); + MySimpleFrame(wxWindow *parent) + : wxFrame(parent, wxID_ANY, "MySimpleCanvas") + { + new MySimpleCanvas(this); -private: - void OnClose(wxCommandEvent& WXUNUSED(event)) { Close(true); } + // ensure that we have scrollbars initially + SetClientSize(MySimpleCanvas::WIDTH/2, MySimpleCanvas::HEIGHT/2); - DECLARE_DYNAMIC_CLASS(MySimpleFrame) - DECLARE_EVENT_TABLE() + Show(); + } }; +// ---------------------------------------------------------------------- +// a more complex example +// ---------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( MySimpleFrame, wxFrame ) +// MyCanvas +class MyCanvas : public wxScrolled +{ +public: + MyCanvas(wxWindow *parent); -BEGIN_EVENT_TABLE(MySimpleFrame,wxFrame) - EVT_MENU(wxID_CLOSE, MySimpleFrame::OnClose) -END_EVENT_TABLE() +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); -MySimpleFrame::MySimpleFrame() - : wxFrame(NULL, wxID_ANY, _T("wxScrolledWindow sample"), - wxDefaultPosition, wxSize(200, 200)) + wxButton *m_button; + + DECLARE_EVENT_TABLE() +}; + +class MyCanvasFrame : public wxFrame { - wxMenu *file_menu = new wxMenu(); - file_menu->Append(wxID_CLOSE); +public: + MyCanvasFrame(wxWindow *parent) + : wxFrame(parent, wxID_ANY, "MyCanvas") + { + m_canvas = new MyCanvas(this); - wxMenuBar *menu_bar = new wxMenuBar(); - menu_bar->Append(file_menu, _T("&File")); + wxMenu *menuFile = new wxMenu(); + menuFile->Append(wxID_DELETE, "&Delete all"); + menuFile->Append(wxID_NEW, "Insert &new"); - SetMenuBar( menu_bar ); + wxMenuBar *mbar = new wxMenuBar(); + mbar->Append(menuFile, "&File"); + SetMenuBar( mbar ); - new MySimpleCanvas(this); -} + Connect(wxID_DELETE, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyCanvasFrame::OnDeleteAll)); + Connect(wxID_NEW, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyCanvasFrame::OnInsertNew)); -// ---------------------------------------------------------------------- -// a complex example -// ---------------------------------------------------------------------- + Show(); + } -// derived classes +private: + void OnDeleteAll(wxCommandEvent& WXUNUSED(event)) + { + m_canvas->DestroyChildren(); + } -class MyFrame; -class MyApp; + void OnInsertNew(wxCommandEvent& WXUNUSED(event)) + { + (void)new wxButton(m_canvas, wxID_ANY, "Hello", wxPoint(100,100)); + } -// MyCanvas + MyCanvas *m_canvas; +}; + +// ---------------------------------------------------------------------------- +// example using sizers with wxScrolled +// ---------------------------------------------------------------------------- + +const wxSize SMALL_BUTTON( 100, 50 ); +const wxSize LARGE_BUTTON( 300, 200 ); -class MyCanvas: public wxScrolledWindow +class MySizerScrolledWindow : public wxScrolled { 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 OnMouseRightDown( wxMouseEvent &event ); - void OnMouseWheel( wxMouseEvent &event ); + 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; - DECLARE_DYNAMIC_CLASS(MyCanvas) - DECLARE_EVENT_TABLE() + void OnResizeClick(wxCommandEvent& event); }; +class MySizerFrame : public wxFrame +{ +public: + MySizerFrame(wxWindow *parent) + : wxFrame(parent, wxID_ANY, "MySizerScrolledWindow") + { + new MySizerScrolledWindow(this); + + // ensure that the scrollbars appear when the button becomes large + SetClientSize(LARGE_BUTTON/2); + Show(); + } +}; // ---------------------------------------------------------------------------- -// Autoscrolling example. +// example showing scrolling only part of the window // ---------------------------------------------------------------------------- -// this class uses the 'virtual' size attribute along with an internal -// sizer to automatically set up scrollbars as needed +// 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 MyAutoScrollWindow : public wxScrolledWindow +class MySubColLabels : public wxWindow { +public: + MySubColLabels(wxScrolled *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 ); - wxButton *m_button; + 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); + } + + wxScrolled *m_owner; +}; + +class MySubRowLabels : public wxWindow +{ public: + MySubRowLabels(wxScrolled *parent) + : wxWindow(parent, wxID_ANY) + { + m_owner = parent; + + Connect(wxEVT_PAINT, wxPaintEventHandler(MySubRowLabels::OnPaint)); + } + +private: + void OnPaint(wxPaintEvent& WXUNUSED(event)) + { + wxPaintDC dc(this); - MyAutoScrollWindow( wxWindow *parent ); + // 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 ); - void OnResizeClick( wxCommandEvent &WXUNUSED( event ) ); + int yScrollUnits, yOrigin; - DECLARE_EVENT_TABLE() + 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); + } + + wxScrolled *m_owner; }; +class MySubCanvas : public wxPanel +{ +public: + MySubCanvas(wxScrolled *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); + } + } + } + + wxScrolled *m_owner; + wxWindow *m_colLabels, + *m_rowLabels; +}; + +class MySubScrolledWindow : public wxScrolled +{ +public: + enum + { + CORNER_WIDTH = 60, + CORNER_HEIGHT = 25 + }; + + MySubScrolledWindow(wxWindow *parent) + : wxScrolled(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 wxScrolled usage // ---------------------------------------------------------------------------- // base class for both of them -class MyScrolledWindowBase : public wxScrolledWindow +class MyScrolledWindowBase : public wxScrolled { public: MyScrolledWindowBase(wxWindow *parent) - : wxScrolledWindow(parent) - , m_nLines( 100 ) + : wxScrolled(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) + { + wxScrolled::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 @@ -231,28 +547,14 @@ public: }; // ---------------------------------------------------------------------------- -// 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 wxScrolled { -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; @@ -262,9 +564,10 @@ 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 +private: + // event handlers void OnDraw(wxDC& dc); void OnMouseLeftDown(wxMouseEvent& event); void OnMouseLeftUp(wxMouseEvent& event); @@ -272,11 +575,38 @@ protected: // event stuff 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 @@ -284,15 +614,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); } + + void OnToggleSync(wxCommandEvent& event); + void OnScrollbarVisibility(wxCommandEvent& event); - MyCanvas *m_canvas; - wxTextCtrl *m_log; + MyScrolledWindowBase *m_win1, + *m_win2; - DECLARE_DYNAMIC_CLASS(MyFrame) DECLARE_EVENT_TABLE() }; @@ -300,124 +637,63 @@ 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) - -BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) - 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) +const wxWindowIDRef ID_ADDBUTTON = wxWindow::NewControlId(); +const wxWindowIDRef ID_DELBUTTON = wxWindow::NewControlId(); +const wxWindowIDRef ID_MOVEBUTTON = wxWindow::NewControlId(); +const wxWindowIDRef ID_SCROLLWIN = wxWindow::NewControlId(); +const wxWindowIDRef ID_QUERYPOS = wxWindow::NewControlId(); + +const wxWindowIDRef ID_NEWBUTTON = wxWindow::NewControlId(); + +BEGIN_EVENT_TABLE(MyCanvas, wxScrolled) + 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) + : wxScrolled(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") ); - - SetCursor( wxCursor( wxCURSOR_IBEAM ) ); + SetBackgroundColour( "BLUE" ); } void MyCanvas::OnMouseRightDown( wxMouseEvent &event ) @@ -425,7 +701,8 @@ void MyCanvas::OnMouseRightDown( wxMouseEvent &event ) 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 ); + wxLogMessage("Mouse down event at: %d %d, scrolled: %d %d", + pt.x, pt.y, x, y); } void MyCanvas::OnMouseWheel( wxMouseEvent &event ) @@ -433,8 +710,8 @@ void MyCanvas::OnMouseWheel( wxMouseEvent &event ) wxPoint pt( event.GetPosition() ); int x,y; CalcUnscrolledPosition( pt.x, pt.y, &x, &y ); - wxLogMessage( wxT("Mouse wheel event at: %d %d, scrolled: %d %d\n") - wxT("Rotation: %d, delta = %d"), + 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() ); @@ -446,9 +723,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 ); } @@ -456,118 +733,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( wxDefaultCoord, 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, -1, wxDefaultPosition, wxDefaultSize, - wxSUNKEN_BORDER|wxScrolledWindowStyle ) +MySizerScrolledWindow::MySizerScrolledWindow(wxWindow *parent) + : wxScrolled(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 - - wxFlexGridSizer *innersizer = new wxFlexGridSizer( 2, 2 ); + // Populate a sizer with a 'resizing' button and some other static + // decoration - m_button = new wxButton( this, - ID_RESIZEBUTTON, - _T("Press me"), - wxDefaultPosition, - SMALL_BUTTON ); + wxFlexGridSizer *sizer = new wxFlexGridSizer(2); - m_button->SetSizeHints( SMALL_BUTTON.GetWidth(), SMALL_BUTTON.GetHeight() ); + m_button = new wxButton( this, wxID_RESIZE_FRAME, "Press me", + wxDefaultPosition, SMALL_BUTTON ); - innersizer->Add( m_button, - 0, - wxALIGN_CENTER | wxALL, - 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(); } @@ -575,103 +832,161 @@ void MyAutoScrollWindow::OnResizeClick( wxCommandEvent &WXUNUSED( event ) ) // MyFrame // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) +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(); + +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 ); + SetIcon(wxICON(sample)); + + 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( "Scrolled window 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() { if ( !wxApp::OnInit() ) return false; - wxFrame *frame = new MyFrame(); - frame->Show( true ); - - frame = new MySimpleFrame(); - frame->Show(); + new MyFrame(); return true; } @@ -686,13 +1001,13 @@ 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)"), + dc.DrawText(wxString::Format("Line %u (logical %d, physical %d)", unsigned(line), y, yPhys), 0, y); y += m_hLine; } @@ -715,48 +1030,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)"), + 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(MyAutoTimedScrollingWindow::OnMouseLeftDown) - EVT_LEFT_UP(MyAutoTimedScrollingWindow::OnMouseLeftUp) - EVT_MOTION(MyAutoTimedScrollingWindow::OnMouseMove) - EVT_MOUSE_CAPTURE_LOST(MyAutoTimedScrollingWindow::OnMouseCaptureLost) - EVT_SCROLLWIN(MyAutoTimedScrollingWindow::OnScroll) +BEGIN_EVENT_TABLE(MyAutoScrollingWindow, wxScrolled) + 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, wxID_ANY, 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) + : wxScrolled(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); @@ -771,32 +1085,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); @@ -811,23 +1119,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) @@ -848,10 +1156,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)); } @@ -881,7 +1189,7 @@ 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)) { @@ -890,7 +1198,7 @@ bool MyAutoTimedScrollingWindow::IsSelected(int chX, int chY) const 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; @@ -898,8 +1206,8 @@ bool MyAutoTimedScrollingWindow::IsInside(int k, int bound1, int bound2) 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 @@ -922,7 +1230,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) @@ -932,7 +1240,7 @@ void MyAutoTimedScrollingWindow::OnDraw(wxDC& dc) dc.SetPen(*wxTRANSPARENT_PEN); const wxString str = sm_testData; size_t strLength = str.length(); - wxString::const_iterator str_i; + wxString::const_iterator str_i = str.begin(); // draw the characters // 1. for each update region @@ -980,7 +1288,7 @@ void MyAutoTimedScrollingWindow::OnDraw(wxDC& dc) } } -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()); @@ -990,7 +1298,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()) { @@ -999,14 +1307,14 @@ 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()) { // set the new cursor position m_cursor = DeviceCoordsToGraphicalChars(event.GetPosition()); // draw/erase selection - MyRefresh(); + // MyRefresh(); // capture mouse to activate auto-scrolling if (!HasCapture()) { CaptureMouse(); @@ -1014,13 +1322,15 @@ void MyAutoTimedScrollingWindow::OnMouseMove(wxMouseEvent& event) } } -void MyAutoTimedScrollingWindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(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 MyAutoTimedScrollingWindow::OnScroll(wxScrollWinEvent& event) +void MyAutoScrollingWindow::OnScroll(wxScrollWinEvent& event) { // need to move the cursor when autoscrolling // FIXME: the cursor also moves when the scrollbar arrows are clicked @@ -1043,129 +1353,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 ") -_T("nonetheless never suppose ourselves capable of producing a painting like one of ") -_T("Raphael's or a dramatic scene like one of Shakespeare's, we convince ourselves ") -_T("that the capacity to do so is quite extraordinarily marvelous, a wholly ") -_T("uncommon accident, or, if we are still religiously inclined, a mercy from on ") -_T("high. Thus our vanity, our self-love, promotes the cult of the genius: for only ") -_T("if we think of him as being very remote from us, as a miraculum, does he not ") -_T("aggrieve us (even Goethe, who was without envy, called Shakespeare his star of ") -_T("the most distant heights [\"William! Stern der schonsten Ferne\": from Goethe's, ") -_T("\"Between Two Worlds\"]; in regard to which one might recall the lines: \"the ") -_T("stars, these we do not desire\" [from Goethe's, \"Comfort in Tears\"]). But, aside ") -_T("from these suggestions of our vanity, the activity of the genius seems in no ") -_T("way fundamentally different from the activity of the inventor of machines, the ") -_T("scholar of astronomy or history, the master of tactics. All these activities ") -_T("are explicable if one pictures to oneself people whose thinking is active in ") -_T("one direction, who employ everything as material, who always zealously observe ") -_T("their own inner life and that of others, who perceive everywhere models and ") -_T("incentives, who never tire of combining together the means available to them. ") -_T("Genius too does nothing except learn first how to lay bricks then how to build, ") -_T("except continually seek for material and continually form itself around it. ") -_T("Every activity of man is amazingly complicated, not only that of the genius: ") -_T("but none is a \"miracle.\" Whence, then, the belief that genius exists only in ") -_T("the artist, orator and philosopher? that only they have \"intuition\"? (Whereby ") -_T("they are supposed to possess a kind of miraculous eyeglass with which they can ") -_T("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 ") -_T("and where they have no desire to feel envious. To call someone \"divine\" means: ") -_T("\"here there is no need for us to compete.\" Then, everything finished and ") -_T("complete is regarded with admiration, everything still becoming is undervalued. ") -_T("But no one can see in the work of the artist how it has become; that is its ") -_T("advantage, for wherever one can see the act of becoming one grows somewhat ") -_T("cool. The finished and perfect art of representation repulses all thinking as ") -_T("to how it has become; it tyrannizes as present completeness and perfection. ") -_T("That is why the masters of the art of representation count above all as gifted ") -_T("with genius and why men of science do not. In reality, this evaluation of the ") -_T("former and undervaluation of the latter is only a piece of childishness in the ") -_T("realm of reason. ") -_T("\n\n") -_T("163 The serious workman. Do not talk about giftedness, inborn talents! One can ") -_T("name great men of all kinds who were very little gifted. The acquired ") -_T("greatness, became \"geniuses\" (as we put it), through qualities the lack of ") -_T("which no one who knew what they were would boast of: they all possessed that ") -_T("seriousness of the efficient workman which first learns to construct the parts ") -_T("properly before it ventures to fashion a great whole; they allowed themselves ") -_T("time for it, because they took more pleasure in making the little, secondary ") -_T("things well than in the effect of a dazzling whole. the recipe for becoming a ") -_T("good novelist, for example, is easy to give, but to carry it out presupposes ") -_T("qualities one is accustomed to overlook when one says \"I do not have enough ") -_T("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; ") -_T("one should write down anecdotes each day until one has learned how to give them ") -_T("the most pregnant and effective form; one should be tireless in collecting and ") -_T("describing human types and characters; one should above all relate things to ") -_T("others and listen to others relate, keeping one's eyes and ears open for the ") -_T("effect produced on those present, one should travel like a landscape painter or ") -_T("costume designer; one should excerpt for oneself out of the individual sciences ") -_T("everything that will produce an artistic effect when it is well described, one ") -_T("should, finally, reflect on the motives of human actions, disdain no signpost ") -_T("to instruction about them and be a collector of these things by day and night. ") -_T("One should continue in this many-sided exercise some ten years: what is then ") -_T("created in the workshop, however, will be fit to go out into the world. What, ") -_T("however, do most people do? They begin, not with the parts, but with the whole. ") -_T("Perhaps they chance to strike a right note, excite attention and from then on ") -_T("strike worse and worse notes, for good, natural reasons. Sometimes, when the ") -_T("character and intellect needed to formulate such a life-plan are lacking, fate ") -_T("and need take their place and lead the future master step by step through all ") -_T("the stipulations of his trade. ") -_T("\n\n") -_T("164 Peril and profit in the cult of the genius. The belief in great, superior, ") -_T("fruitful spirits is not necessarily, yet nonetheless is very frequently ") -_T("associated with that religious or semi-religious superstition that these ") -_T("spirits are of supra-human origin and possess certain miraculous abilities by ") -_T("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 ") -_T("world, as it were a hole in the cloak of appearance, and believes that, by ") -_T("virtue of this miraculous seer's vision, they are able to communicate something ") -_T("conclusive and decisive about man and the world without the toil and ") -_T("rigorousness required by science. As long as there continue to be those who ") -_T("believe in the miraculous in the domain of knowledge one can perhaps concede ") -_T("that these people themselves derive some benefit from their belief, inasmuch as ") -_T("through their unconditional subjection to the great spirits they create for ") -_T("their own spirit during its time of development the finest form of discipline ") -_T("and schooling. On the other hand, it is at least questionable whether the ") -_T("superstitious belief in genius, in its privileges and special abilities, is of ") -_T("benefit to the genius himself if it takes root in him. It is in any event a ") -_T("dangerous sign when a man is assailed by awe of himself, whether it be the ") -_T("celebrated Caesar's awe of Caesar or the awe of one's own genius now under ") -_T("consideration; when the sacrificial incense which is properly rendered only to ") -_T("a god penetrates the brain of the genius, so that his head begins to swim and ") -_T("he comes to regard himself as something supra-human. The consequences that ") -_T("slowly result are: the feeling of irresponsibility, of exceptional rights, the ") -_T("belief that he confers a favor by his mere presence, insane rage when anyone ") -_T("attempts even to compare him with others, let alone to rate him beneath them, ") -_T("or to draw attention to lapses in his work. Because he ceases to practice ") -_T("criticism of himself, at last one pinion after the other falls out of his ") -_T("plumage: that superstitious eats at the roots of his powers and perhaps even ") -_T("turns him into a hypocrite after his powers have fled from him. For the great ") -_T("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 ") -_T("say, what purely human qualities have come together in them and what fortunate ") -_T("circumstances attended them: in the first place undiminished energy, resolute ") -_T("application to individual goals, great personal courage, then the good fortune ") -_T("to receive an upbringing which offered in the early years the finest teachers, ") -_T("models and methods. To be sure, when their goal is the production of the ") -_T("greatest possible effect, unclarity with regard to oneself and that ") -_T("semi-insanity superadded to it has always achieved much; for what has been ") -_T("admired and envied at all times has been that power in them by virtue of which ") -_T("they render men will-less and sweep them away into the delusion that the ") -_T("leaders they are following are supra-natural. Indeed, it elevates and inspires ") -_T("men to believe that someone is in possession of supra-natural powers: to this ") -_T("extent Plato was right to say [Plato: Phaedrus, 244a] that madness has brought ") -_T("the greatest of blessings upon mankind. In rare individual cases this portion ") -_T("of madness may, indeed, actually have been the means by which such a nature, ") -_T("excessive in all directions, was held firmly together: in the life of ") -_T("individuals, too, illusions that are in themselves poisons often play the role ") -_T("of healers; yet, in the end, in the case of every \"genius\" who believes in his ") -_T("own divinity the poison shows itself to the same degree as his \"genius\" grows ") -_T("old: one may recall, for example, the case of Napoleon, whose nature certainly ") -_T("grew into the mighty unity that sets him apart from all men of modern times ") -_T("precisely through his belief in himself and his star and through the contempt ") -_T("for men that flowed from it; until in the end, however, this same belief went ") -_T("over into an almost insane fatalism, robbed him of his acuteness and swiftness ") -_T("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.";