1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxScrolledWindow sample 
   4 // Author:      Robert Roebling 
   8 // Copyright:   (C) 1998 Robert Roebling, 2002 Ron Lee, 2003 Matt Gregory 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx/wx.h". 
  13 #include "wx/wxprec.h" 
  24 #include "wx/listctrl.h" 
  28 const long ID_QUIT       
= wxID_EXIT
; 
  29 const long ID_ABOUT      
= wxID_ABOUT
; 
  30 const long ID_DELETE_ALL 
= 100; 
  31 const long ID_INSERT_NEW 
= 101; 
  33 // ---------------------------------------------------------------------- 
  35 // ---------------------------------------------------------------------- 
  42 class MySimpleCanvas
: public wxScrolledWindow
 
  46     MySimpleCanvas( wxWindow 
*parent
, wxWindowID
, const wxPoint 
&pos
, const wxSize 
&size 
); 
  48     void OnPaint( wxPaintEvent 
&event 
); 
  51     DECLARE_DYNAMIC_CLASS(MyCanvas
) 
  55 IMPLEMENT_DYNAMIC_CLASS(MySimpleCanvas
, wxScrolledWindow
) 
  57 BEGIN_EVENT_TABLE(MySimpleCanvas
, wxScrolledWindow
) 
  58   EVT_PAINT(      MySimpleCanvas::OnPaint
) 
  61 MySimpleCanvas::MySimpleCanvas( wxWindow 
*parent
, wxWindowID id
, 
  62                     const wxPoint 
&pos
, const wxSize 
&size 
) 
  63     : wxScrolledWindow( parent
, id
, pos
, size
, wxSUNKEN_BORDER
, _T("test canvas") ) 
  65     SetScrollRate( 10, 10 ); 
  66     SetVirtualSize( 92, 97 ); 
  67     SetBackgroundColour( *wxWHITE 
); 
  70 void MySimpleCanvas::OnPaint( wxPaintEvent 
&event 
) 
  75     dc
.SetPen( *wxRED_PEN 
); 
  76     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
  77     dc
.DrawRectangle( 0,0,92,97 ); 
  82 class MySimpleFrame
: public wxFrame
 
  87     void OnQuit( wxCommandEvent 
&event 
); 
  89     MySimpleCanvas         
*m_canvas
; 
  92     DECLARE_DYNAMIC_CLASS(MySimpleFrame
) 
  97 IMPLEMENT_DYNAMIC_CLASS( MySimpleFrame
, wxFrame 
) 
  99 BEGIN_EVENT_TABLE(MySimpleFrame
,wxFrame
) 
 100   EVT_MENU    (ID_QUIT
,  MySimpleFrame::OnQuit
) 
 103 MySimpleFrame::MySimpleFrame() 
 104        : wxFrame( (wxFrame 
*)NULL
, wxID_ANY
, _T("wxScrolledWindow sample"), 
 105                   wxPoint(120,120), wxSize(150,150) ) 
 107     wxMenu 
*file_menu 
= new wxMenu(); 
 108     file_menu
->Append( ID_QUIT
,       _T("E&xit\tAlt-X")); 
 110     wxMenuBar 
*menu_bar 
= new wxMenuBar(); 
 111     menu_bar
->Append(file_menu
, _T("&File")); 
 113     SetMenuBar( menu_bar 
); 
 115     m_canvas 
= new MySimpleCanvas( this, wxID_ANY
, wxPoint(0,0), wxSize(100,100) ); 
 118 void MySimpleFrame::OnQuit( wxCommandEvent 
&WXUNUSED(event
) ) 
 123 // ---------------------------------------------------------------------- 
 125 // ---------------------------------------------------------------------- 
 134 class MyCanvas
: public wxScrolledWindow
 
 138     MyCanvas( wxWindow 
*parent
, wxWindowID
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 140     void OnPaint( wxPaintEvent 
&event 
); 
 141     void OnQueryPosition( wxCommandEvent 
&event 
); 
 142     void OnAddButton( wxCommandEvent 
&event 
); 
 143     void OnDeleteButton( wxCommandEvent 
&event 
); 
 144     void OnMoveButton( wxCommandEvent 
&event 
); 
 145     void OnScrollWin( wxCommandEvent 
&event 
); 
 146     void OnMouseRightDown( wxMouseEvent 
&event 
); 
 147     void OnMouseWheel( wxMouseEvent 
&event 
); 
 151     DECLARE_DYNAMIC_CLASS(MyCanvas
) 
 152     DECLARE_EVENT_TABLE() 
 156 // ---------------------------------------------------------------------------- 
 157 // Autoscrolling example. 
 158 // ---------------------------------------------------------------------------- 
 160 // this class uses the 'virtual' size attribute along with an internal 
 161 // sizer to automatically set up scrollbars as needed 
 163 class MyAutoScrollWindow 
: public wxScrolledWindow
 
 171     MyAutoScrollWindow( wxWindow 
*parent 
); 
 173     void OnResizeClick( wxCommandEvent 
&WXUNUSED( event 
) ); 
 175     DECLARE_EVENT_TABLE() 
 179 // ---------------------------------------------------------------------------- 
 180 // MyScrolledWindow classes: examples of wxScrolledWindow usage 
 181 // ---------------------------------------------------------------------------- 
 183 // base class for both of them 
 184 class MyScrolledWindowBase 
: public wxScrolledWindow
 
 187     MyScrolledWindowBase(wxWindow 
*parent
) 
 188         : wxScrolledWindow(parent
) 
 192         dc
.GetTextExtent(_T("Line 17"), NULL
, &m_hLine
); 
 196     // the height of one line on screen 
 199     // the number of lines we draw 
 203 // this class does "stupid" redrawing - it redraws everything each time 
 204 // and sets the scrollbar extent directly. 
 206 class MyScrolledWindowDumb 
: public MyScrolledWindowBase
 
 209     MyScrolledWindowDumb(wxWindow 
*parent
) : MyScrolledWindowBase(parent
) 
 212         SetScrollbars(0, m_hLine
, 0, m_nLines 
+ 1, 0, 0, true /* no refresh */); 
 215     virtual void OnDraw(wxDC
& dc
); 
 218 // this class does "smart" redrawing - only redraws the lines which must be 
 219 // redrawn and sets the scroll rate and virtual size to affect the 
 222 // Note that this class should produce identical results to the one above. 
 224 class MyScrolledWindowSmart 
: public MyScrolledWindowBase
 
 227     MyScrolledWindowSmart(wxWindow 
*parent
) : MyScrolledWindowBase(parent
) 
 230         SetScrollRate( 0, m_hLine 
); 
 231         SetVirtualSize( wxDefaultCoord
, ( m_nLines 
+ 1 ) * m_hLine 
); 
 234     virtual void OnDraw(wxDC
& dc
); 
 237 // ---------------------------------------------------------------------------- 
 238 // MyAutoTimedScrollingWindow: implements a text viewer with simple blocksize 
 239 //                             selection to test auto-scrolling functionality 
 240 // ---------------------------------------------------------------------------- 
 242 class MyAutoTimedScrollingWindow 
: public wxScrolledWindow
 
 244 protected:  // member data 
 245     // test data variables 
 246     static const wxChar
* sm_testData
; 
 247     static const int sm_lineCnt
; // line count 
 248     static const int sm_lineLen
; // line length in characters 
 249     // sizes for graphical data 
 250     wxCoord m_fontH
, m_fontW
; 
 251     // selection tracking 
 252     wxPoint m_selStart
; // beginning of blockwise selection 
 253     wxPoint m_cursor
;   // end of blockwise selection (mouse position) 
 255 protected:  // gui stuff 
 259     MyAutoTimedScrollingWindow( wxWindow
* parent 
); 
 260     wxRect 
DeviceCoordsToGraphicalChars(wxRect updRect
) const; 
 261     wxPoint 
DeviceCoordsToGraphicalChars(wxPoint pos
) const; 
 262     wxPoint 
GraphicalCharToDeviceCoords(wxPoint pos
) const; 
 263     wxRect 
LogicalCoordsToGraphicalChars(wxRect updRect
) const; 
 264     wxPoint 
LogicalCoordsToGraphicalChars(wxPoint pos
) const; 
 265     wxPoint 
GraphicalCharToLogicalCoords(wxPoint pos
) const; 
 267     bool IsSelected(int chX
, int chY
) const; 
 268     static bool IsInside(int k
, int bound1
, int bound2
); 
 269     static wxRect 
DCNormalize(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
); 
 271 protected: // event stuff 
 272     void OnDraw(wxDC
& dc
); 
 273     void OnMouseLeftDown(wxMouseEvent
& event
); 
 274     void OnMouseLeftUp(wxMouseEvent
& event
); 
 275     void OnMouseMove(wxMouseEvent
& event
); 
 276     void OnScroll(wxScrollWinEvent
& event
); 
 278     DECLARE_EVENT_TABLE() 
 281 // ---------------------------------------------------------------------------- 
 283 // ---------------------------------------------------------------------------- 
 285 class MyFrame
: public wxFrame
 
 290     void OnAbout( wxCommandEvent 
&event 
); 
 291     void OnQuit( wxCommandEvent 
&event 
); 
 292     void OnDeleteAll( wxCommandEvent 
&event 
); 
 293     void OnInsertNew( wxCommandEvent 
&event 
); 
 298     DECLARE_DYNAMIC_CLASS(MyFrame
) 
 299     DECLARE_EVENT_TABLE() 
 302 // ---------------------------------------------------------------------------- 
 304 // ---------------------------------------------------------------------------- 
 306 class MyApp
: public wxApp
 
 309     virtual bool OnInit(); 
 313 // ---------------------------------------------------------------------------- 
 315 // ---------------------------------------------------------------------------- 
 321 const long   ID_ADDBUTTON   
= wxNewId(); 
 322 const long   ID_DELBUTTON   
= wxNewId(); 
 323 const long   ID_MOVEBUTTON  
= wxNewId(); 
 324 const long   ID_SCROLLWIN   
= wxNewId(); 
 325 const long   ID_QUERYPOS    
= wxNewId(); 
 327 const long   ID_NEWBUTTON   
= wxNewId(); 
 329 // ---------------------------------------------------------------------------- 
 331 // ---------------------------------------------------------------------------- 
 333 IMPLEMENT_DYNAMIC_CLASS(MyCanvas
, wxScrolledWindow
) 
 335 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
) 
 336   EVT_PAINT(                  MyCanvas::OnPaint
) 
 337   EVT_RIGHT_DOWN(             MyCanvas::OnMouseRightDown
) 
 338   EVT_MOUSEWHEEL(             MyCanvas::OnMouseWheel
) 
 339   EVT_BUTTON( ID_QUERYPOS
,    MyCanvas::OnQueryPosition
) 
 340   EVT_BUTTON( ID_ADDBUTTON
,   MyCanvas::OnAddButton
) 
 341   EVT_BUTTON( ID_DELBUTTON
,   MyCanvas::OnDeleteButton
) 
 342   EVT_BUTTON( ID_MOVEBUTTON
,  MyCanvas::OnMoveButton
) 
 343   EVT_BUTTON( ID_SCROLLWIN
,   MyCanvas::OnScrollWin
) 
 346 MyCanvas::MyCanvas( wxWindow 
*parent
, wxWindowID id
, 
 347                     const wxPoint 
&pos
, const wxSize 
&size 
) 
 348     : wxScrolledWindow( parent
, id
, pos
, size
, wxSUNKEN_BORDER 
| wxTAB_TRAVERSAL
, _T("test canvas") ) 
 350     SetScrollRate( 10, 10 ); 
 351     SetVirtualSize( 500, 1000 ); 
 353     (void) new wxButton( this, ID_ADDBUTTON
,  _T("add button"), wxPoint(10,10) ); 
 354     (void) new wxButton( this, ID_DELBUTTON
,  _T("del button"), wxPoint(10,40) ); 
 355     (void) new wxButton( this, ID_MOVEBUTTON
, _T("move button"), wxPoint(150,10) ); 
 356     (void) new wxButton( this, ID_SCROLLWIN
,  _T("scroll win"), wxPoint(250,10) ); 
 369     m_button 
= new wxButton( this, ID_QUERYPOS
, "Query position", wxPoint(10,110) ); 
 371     (void) new wxTextCtrl( this, wxID_ANY
, "wxTextCtrl", wxPoint(10,150), wxSize(80,wxDefaultCoord
) ); 
 373     (void) new wxRadioButton( this, wxID_ANY
, "Disable", wxPoint(10,190) ); 
 375     (void) new wxComboBox( this, wxID_ANY
, "This", wxPoint(10,230), wxDefaultSize
, 5, choices 
); 
 377     (void) new wxRadioBox( this, wxID_ANY
, "This", wxPoint(10,310), wxDefaultSize
, 5, choices
, 2, wxRA_SPECIFY_COLS 
); 
 379     (void) new wxRadioBox( this, wxID_ANY
, "This", wxPoint(10,440), wxDefaultSize
, 5, choices
, 2, wxRA_SPECIFY_ROWS 
); 
 381     wxListCtrl 
*m_listCtrl 
= new wxListCtrl( 
 382             this, wxID_ANY
, wxPoint(200, 110), wxSize(180, 120), 
 383             wxLC_REPORT 
| wxSIMPLE_BORDER 
| wxLC_SINGLE_SEL 
); 
 385     m_listCtrl
->InsertColumn(0, "First", wxLIST_FORMAT_LEFT
, 90); 
 386     m_listCtrl
->InsertColumn(1, "Last", wxLIST_FORMAT_LEFT
, 90); 
 388     for ( int i
=0; i 
< 30; i
++) 
 391         sprintf(buf
, "Item %d", i
); 
 392         m_listCtrl
->InsertItem(i
, buf
); 
 394     m_listCtrl
->SetItemState( 3, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED 
); 
 396     (void) new wxListBox( this, wxID_ANY
, wxPoint(260,280), wxSize(120,120), 5, choices
, wxLB_ALWAYS_SB 
); 
 400     wxPanel 
*test 
= new wxPanel( this, wxID_ANY
, wxPoint(10, 110), wxSize(130,50), wxSIMPLE_BORDER 
| wxTAB_TRAVERSAL 
); 
 401     test
->SetBackgroundColour( wxT("WHEAT") ); 
 405     wxButton 
*test2 
= new wxButton( test
, wxID_ANY
, "Hallo", wxPoint(10,10) ); 
 407     test 
= new wxPanel( this, wxID_ANY
, wxPoint(160, 530), wxSize(130,120), wxSUNKEN_BORDER 
| wxTAB_TRAVERSAL 
); 
 408     test
->SetBackgroundColour( wxT("WHEAT") ); 
 409     test
->SetCursor( wxCursor( wxCURSOR_NO_ENTRY 
) ); 
 410     test2 
= new wxButton( test
, wxID_ANY
, "Hallo", wxPoint(10,10) ); 
 411     test2
->SetCursor( wxCursor( wxCURSOR_PENCIL 
) ); 
 413     test 
= new wxPanel( this, wxID_ANY
, wxPoint(310, 530), wxSize(130,120), wxRAISED_BORDER 
| wxTAB_TRAVERSAL 
); 
 414     test
->SetBackgroundColour( wxT("WHEAT") ); 
 415     test
->SetCursor( wxCursor( wxCURSOR_PENCIL 
) ); 
 416     test2 
= new wxButton( test
, wxID_ANY
, "Hallo", wxPoint(10,10) ); 
 417     test2
->SetCursor( wxCursor( wxCURSOR_NO_ENTRY 
) ); 
 421     SetBackgroundColour( wxT("BLUE") ); 
 423     SetCursor( wxCursor( wxCURSOR_IBEAM 
) ); 
 426 void MyCanvas::OnMouseRightDown( wxMouseEvent 
&event 
) 
 428     wxPoint 
pt( event
.GetPosition() ); 
 430     CalcUnscrolledPosition( pt
.x
, pt
.y
, &x
, &y 
); 
 431     wxLogMessage( wxT("Mouse down event at: %d %d, scrolled: %d %d"), pt
.x
, pt
.y
, x
, y 
); 
 434 void MyCanvas::OnMouseWheel( wxMouseEvent 
&event 
) 
 436     wxPoint 
pt( event
.GetPosition() ); 
 438     CalcUnscrolledPosition( pt
.x
, pt
.y
, &x
, &y 
); 
 439     wxLogMessage( wxT("Mouse wheel event at: %d %d, scrolled: %d %d\n") 
 440                   wxT("Rotation: %d, delta = %d"), 
 442                   event
.GetWheelRotation(), event
.GetWheelDelta() ); 
 447 void MyCanvas::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
 449     wxPaintDC 
dc( this ); 
 452     dc
.DrawText( _T("Press mouse button to test calculations!"), 160, 50 ); 
 454     dc
.DrawText( _T("Some text"), 140, 140 ); 
 456     dc
.DrawRectangle( 100, 160, 200, 200 ); 
 459 void MyCanvas::OnQueryPosition( wxCommandEvent 
&WXUNUSED(event
) ) 
 461     wxPoint 
pt( m_button
->GetPosition() ); 
 462     wxLogMessage( wxT("Position of \"Query position\" is %d %d"), pt
.x
, pt
.y 
); 
 463     pt 
= ClientToScreen( pt 
); 
 464     wxLogMessage( wxT("Position of \"Query position\" on screen is %d %d"), pt
.x
, pt
.y 
); 
 467 void MyCanvas::OnAddButton( wxCommandEvent 
&WXUNUSED(event
) ) 
 469     wxLogMessage( wxT("Inserting button at position 10,70...") ); 
 470     wxButton 
*button 
= new wxButton( this, ID_NEWBUTTON
, wxT("new button"), wxPoint(10,70), wxSize(80,25) ); 
 471     wxPoint 
pt( button
->GetPosition() ); 
 472     wxLogMessage( wxT("-> Position after inserting %d %d"), pt
.x
, pt
.y 
); 
 475 void MyCanvas::OnDeleteButton( wxCommandEvent 
&WXUNUSED(event
) ) 
 477     wxLogMessage( wxT("Deleting button inserted with \"Add button\"...") ); 
 478     wxWindow 
*win 
= FindWindow( ID_NEWBUTTON 
); 
 482        wxLogMessage( wxT("-> No window with id = ID_NEWBUTTON found.") ); 
 485 void MyCanvas::OnMoveButton( wxCommandEvent 
&event 
) 
 487     wxLogMessage( wxT("Moving button 10 pixels downward..") ); 
 488     wxWindow 
*win 
= FindWindow( event
.GetId() ); 
 489     wxPoint 
pt( win
->GetPosition() ); 
 490     wxLogMessage( wxT("-> Position before move is %d %d"), pt
.x
, pt
.y 
); 
 491     win
->Move( wxDefaultCoord
, pt
.y 
+ 10 ); 
 492     pt 
= win
->GetPosition(); 
 493     wxLogMessage( wxT("-> Position after move is %d %d"), pt
.x
, pt
.y 
); 
 496 void MyCanvas::OnScrollWin( wxCommandEvent 
&WXUNUSED(event
) ) 
 498     wxLogMessage( wxT("Scrolling 2 units up.\nThe white square and the controls should move equally!") ); 
 500     GetViewStart( &x
, &y 
); 
 501     Scroll( wxDefaultCoord
, y
+2 ); 
 504 // ---------------------------------------------------------------------------- 
 505 // MyAutoScrollWindow 
 506 // ---------------------------------------------------------------------------- 
 508 const long   ID_RESIZEBUTTON 
= wxNewId(); 
 509 const wxSize 
SMALL_BUTTON( 100, 50 ); 
 510 const wxSize 
LARGE_BUTTON( 300, 100 ); 
 512 BEGIN_EVENT_TABLE( MyAutoScrollWindow
, wxScrolledWindow
) 
 513   EVT_BUTTON( ID_RESIZEBUTTON
,    MyAutoScrollWindow::OnResizeClick
) 
 516 MyAutoScrollWindow::MyAutoScrollWindow( wxWindow 
*parent 
) 
 517     : wxScrolledWindow( parent
, -1, wxDefaultPosition
, wxDefaultSize
,  
 518                         wxSUNKEN_BORDER
|wxScrolledWindowStyle 
) 
 520     SetBackgroundColour( wxT("GREEN") ); 
 522     // Set the rate we'd like for scrolling. 
 524     SetScrollRate( 5, 5 ); 
 526     // Populate a sizer with a 'resizing' button and some 
 527     // other static decoration 
 529     wxFlexGridSizer  
*innersizer 
= new wxFlexGridSizer( 2, 2 ); 
 531     m_button 
= new wxButton( this, 
 537     // We need to do this here, because wxADJUST_MINSIZE below 
 538     // will cause the initial size to be ignored for Best/Min size. 
 539     // It would be nice to fix the sizers to handle this a little 
 542     m_button
->SetSizeHints( SMALL_BUTTON
.GetWidth(), SMALL_BUTTON
.GetHeight() ); 
 544     innersizer
->Add( m_button
, 
 546                      wxALIGN_CENTER 
| wxALL 
| wxADJUST_MINSIZE
, 
 549     innersizer
->Add( new wxStaticText( this, wxID_ANY
, _T("This is just") ), 
 553     innersizer
->Add( new wxStaticText( this, wxID_ANY
, _T("some decoration") ), 
 557     innersizer
->Add( new wxStaticText( this, wxID_ANY
, _T("for you to scroll...") ), 
 561     // Then use the sizer to set the scrolled region size. 
 563     SetSizer( innersizer 
); 
 566 void MyAutoScrollWindow::OnResizeClick( wxCommandEvent 
&WXUNUSED( event 
) ) 
 568     // Arbitrarily resize the button to change the minimum size of 
 569     // the (scrolled) sizer. 
 571     if( m_button
->GetSize() == SMALL_BUTTON 
) 
 572         m_button
->SetSizeHints( LARGE_BUTTON
.GetWidth(), LARGE_BUTTON
.GetHeight() ); 
 574         m_button
->SetSizeHints( SMALL_BUTTON
.GetWidth(), SMALL_BUTTON
.GetHeight() ); 
 576     // Force update layout and scrollbars, since nothing we do here 
 577     // necessarily generates a size event which would do it for us. 
 582 // ---------------------------------------------------------------------------- 
 584 // ---------------------------------------------------------------------------- 
 586 IMPLEMENT_DYNAMIC_CLASS( MyFrame
, wxFrame 
) 
 588 BEGIN_EVENT_TABLE(MyFrame
,wxFrame
) 
 589   EVT_MENU    (ID_DELETE_ALL
, MyFrame::OnDeleteAll
) 
 590   EVT_MENU    (ID_INSERT_NEW
,  MyFrame::OnInsertNew
) 
 591   EVT_MENU    (ID_ABOUT
, MyFrame::OnAbout
) 
 592   EVT_MENU    (ID_QUIT
,  MyFrame::OnQuit
) 
 596        : wxFrame( (wxFrame 
*)NULL
, wxID_ANY
, _T("wxScrolledWindow sample"), 
 597                   wxPoint(20,20), wxSize(800,500) ) 
 599     wxMenu 
*file_menu 
= new wxMenu(); 
 600     file_menu
->Append( ID_DELETE_ALL
, _T("Delete all")); 
 601     file_menu
->Append( ID_INSERT_NEW
, _T("Insert new")); 
 602     file_menu
->Append( ID_ABOUT
,      _T("&About..")); 
 603     file_menu
->Append( ID_QUIT
,       _T("E&xit\tAlt-X")); 
 605     wxMenuBar 
*menu_bar 
= new wxMenuBar(); 
 606     menu_bar
->Append(file_menu
, _T("&File")); 
 608     SetMenuBar( menu_bar 
); 
 612     int widths
[] = { -1, 100 }; 
 613     SetStatusWidths( 2, widths 
); 
 614 #endif // wxUSE_STATUSBAR 
 616      wxBoxSizer 
*topsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 617      // subsizer splits topsizer down the middle 
 618      wxBoxSizer 
*subsizer 
= new wxBoxSizer( wxVERTICAL 
); 
 620     // Setting an explicit size here is superfluous, it will be overridden 
 621     // by the sizer in any case. 
 622     m_canvas 
= new MyCanvas( this, wxID_ANY
, wxPoint(0,0), wxSize(100,100) ); 
 624     // This is done with ScrollRate/VirtualSize in MyCanvas ctor now, 
 625     // both should produce identical results. 
 626     //m_canvas->SetScrollbars( 10, 10, 50, 100 ); 
 628     subsizer
->Add( m_canvas
, 1, wxEXPAND 
); 
 629     subsizer
->Add( new MyAutoScrollWindow( this ), 1, wxEXPAND 
); 
 631     wxSizer 
*sizerBtm 
= new wxBoxSizer(wxHORIZONTAL
); 
 632     sizerBtm
->Add( new MyScrolledWindowDumb(this), 1, wxEXPAND 
); 
 633     sizerBtm
->Add( new MyScrolledWindowSmart(this), 1, wxEXPAND 
); 
 634     subsizer
->Add( sizerBtm
, 1, wxEXPAND 
); 
 636     topsizer
->Add( subsizer
, 1, wxEXPAND 
); 
 637     topsizer
->Add( new MyAutoTimedScrollingWindow( this ), 1, wxEXPAND 
); 
 639     SetSizer( topsizer 
); 
 642 void MyFrame::OnDeleteAll( wxCommandEvent 
&WXUNUSED(event
) ) 
 644     m_canvas
->DestroyChildren(); 
 647 void MyFrame::OnInsertNew( wxCommandEvent 
&WXUNUSED(event
) ) 
 649     (void)new wxButton( m_canvas
, wxID_ANY
, _T("Hello"), wxPoint(100,100) ); 
 652 void MyFrame::OnQuit( wxCommandEvent 
&WXUNUSED(event
) ) 
 657 void MyFrame::OnAbout( wxCommandEvent 
&WXUNUSED(event
) ) 
 659    (void)wxMessageBox( _T("wxScroll demo\n") 
 660                        _T("Robert Roebling (c) 1998\n") 
 661                        _T("Autoscrolling examples\n") 
 662                        _T("Ron Lee (c) 2002\n") 
 663                        _T("Auto-timed-scrolling example\n") 
 664                        _T("Matt Gregory (c) 2003\n"), 
 665                        _T("About wxScroll Demo"), 
 666                        wxICON_INFORMATION 
| wxOK 
); 
 669 //----------------------------------------------------------------------------- 
 671 //----------------------------------------------------------------------------- 
 675     wxFrame 
*frame 
= new MyFrame(); 
 678     frame 
= new MySimpleFrame(); 
 684 // ---------------------------------------------------------------------------- 
 685 // MyScrolledWindowXXX 
 686 // ---------------------------------------------------------------------------- 
 688 void MyScrolledWindowDumb::OnDraw(wxDC
& dc
) 
 690     // this is useful to see which lines are redrawn 
 691     static size_t s_redrawCount 
= 0; 
 692     dc
.SetTextForeground(s_redrawCount
++ % 2 ? *wxRED 
: *wxBLUE
); 
 695     for ( size_t line 
= 0; line 
< m_nLines
; line
++ ) 
 698         CalcScrolledPosition(0, y
, NULL
, &yPhys
); 
 700         dc
.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"), 
 701                                      line
, y
, yPhys
), 0, y
); 
 706 void MyScrolledWindowSmart::OnDraw(wxDC
& dc
) 
 708     // this is useful to see which lines are redrawn 
 709     static size_t s_redrawCount 
= 0; 
 710     dc
.SetTextForeground(s_redrawCount
++ % 2 ? *wxRED 
: *wxBLUE
); 
 712     // update region is always in device coords, translate to logical ones 
 713     wxRect rectUpdate 
= GetUpdateRegion().GetBox(); 
 714     CalcUnscrolledPosition(rectUpdate
.x
, rectUpdate
.y
, 
 715                            &rectUpdate
.x
, &rectUpdate
.y
); 
 717     size_t lineFrom 
= rectUpdate
.y 
/ m_hLine
, 
 718            lineTo 
= rectUpdate
.GetBottom() / m_hLine
; 
 720     if ( lineTo 
> m_nLines 
- 1) 
 721         lineTo 
= m_nLines 
- 1; 
 723     wxCoord y 
= lineFrom
*m_hLine
; 
 724     for ( size_t line 
= lineFrom
; line 
<= lineTo
; line
++ ) 
 727         CalcScrolledPosition(0, y
, NULL
, &yPhys
); 
 729         dc
.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"), 
 730                                      line
, y
, yPhys
), 0, y
); 
 735 // ---------------------------------------------------------------------------- 
 736 // MyAutoTimedScrollingWindow 
 737 // ---------------------------------------------------------------------------- 
 739 BEGIN_EVENT_TABLE(MyAutoTimedScrollingWindow
, wxScrolledWindow
) 
 740     EVT_LEFT_DOWN(MyAutoTimedScrollingWindow::OnMouseLeftDown
) 
 741     EVT_LEFT_UP(MyAutoTimedScrollingWindow::OnMouseLeftUp
) 
 742     EVT_MOTION(MyAutoTimedScrollingWindow::OnMouseMove
) 
 743     EVT_SCROLLWIN(MyAutoTimedScrollingWindow::OnScroll
) 
 746 MyAutoTimedScrollingWindow::MyAutoTimedScrollingWindow(wxWindow
* parent
) 
 747     : wxScrolledWindow(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
 
 748             //, wxSUNKEN_BORDER) // can't seem to do it this way 
 749             , wxVSCROLL 
| wxHSCROLL 
| wxSUNKEN_BORDER
) 
 750     , m_selStart(-1, -1), m_cursor(-1, -1) 
 751     , m_font(9, wxFONTFAMILY_TELETYPE
, wxFONTSTYLE_NORMAL
 
 752             , wxFONTWEIGHT_NORMAL
) 
 755     // query dc for text size 
 757     dc
.GetTextExtent(wxString(_T("A")), &m_fontW
, &m_fontH
); 
 758     // set up the virtual window 
 759     SetScrollbars(m_fontW
, m_fontH
, sm_lineLen
, sm_lineCnt
); 
 762 wxRect 
MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars
 
 763         (wxRect updRect
) const 
 765     wxPoint 
pos(updRect
.GetPosition()); 
 766     pos 
= DeviceCoordsToGraphicalChars(pos
); 
 769     updRect
.width 
/= m_fontW
; 
 770     updRect
.height 
/= m_fontH
; 
 771     // the *CoordsToGraphicalChars() funcs round down to upper-left corner, 
 772     //   so an off-by-one correction is needed 
 773     ++updRect
.width
; // kludge 
 774     ++updRect
.height
; // kludge 
 778 wxPoint 
MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars
 
 784     GetViewStart(&vX
, &vY
); 
 790 wxPoint 
MyAutoTimedScrollingWindow::GraphicalCharToDeviceCoords
 
 794     GetViewStart(&vX
, &vY
); 
 802 wxRect 
MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars
 
 803         (wxRect updRect
) const 
 805     wxPoint 
pos(updRect
.GetPosition()); 
 806     pos 
= LogicalCoordsToGraphicalChars(pos
); 
 809     updRect
.width 
/= m_fontW
; 
 810     updRect
.height 
/= m_fontH
; 
 811     // the *CoordsToGraphicalChars() funcs round down to upper-left corner, 
 812     //   so an off-by-one correction is needed 
 813     ++updRect
.width
; // kludge 
 814     ++updRect
.height
; // kludge 
 818 wxPoint 
MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars
 
 826 wxPoint 
MyAutoTimedScrollingWindow::GraphicalCharToLogicalCoords
 
 834 void MyAutoTimedScrollingWindow::MyRefresh() 
 836     static wxPoint 
lastSelStart(-1, -1), lastCursor(-1, -1); 
 837     // refresh last selected area (to deselect previously selected text) 
 839             GraphicalCharToDeviceCoords(lastSelStart
), 
 840             GraphicalCharToDeviceCoords(lastCursor
) 
 842     // off-by-one corrections, necessary because it's not possible to know 
 843     //   when to round up until rect is normalized by lastUpdRect constructor 
 844     lastUpdRect
.width 
+= m_fontW
; // kludge 
 845     lastUpdRect
.height 
+= m_fontH
; // kludge 
 846     // refresh currently selected (to select previously unselected text) 
 848             GraphicalCharToDeviceCoords(m_selStart
), 
 849             GraphicalCharToDeviceCoords(m_cursor
) 
 851     // off-by-one corrections 
 852     updRect
.width 
+= m_fontW
; // kludge 
 853     updRect
.height 
+= m_fontH
; // kludge 
 854     // find necessary refresh areas 
 855     wxCoord rx 
= lastUpdRect
.x
; 
 856     wxCoord ry 
= lastUpdRect
.y
; 
 857     wxCoord rw 
= updRect
.x 
- lastUpdRect
.x
; 
 858     wxCoord rh 
= lastUpdRect
.height
; 
 860         RefreshRect(DCNormalize(rx
, ry
, rw
, rh
)); 
 863     ry 
= updRect
.y 
+ updRect
.height
; 
 865     rh 
= (lastUpdRect
.y 
+ lastUpdRect
.height
) - (updRect
.y 
+ updRect
.height
); 
 867         RefreshRect(DCNormalize(rx
, ry
, rw
, rh
)); 
 869     rx 
= updRect
.x 
+ updRect
.width
; 
 871     rw 
= (lastUpdRect
.x 
+ lastUpdRect
.width
) - (updRect
.x 
+ updRect
.width
); 
 872     rh 
= lastUpdRect
.height
; 
 874         RefreshRect(DCNormalize(rx
, ry
, rw
, rh
)); 
 879     rh 
= updRect
.y 
- lastUpdRect
.y
; 
 881         RefreshRect(DCNormalize(rx
, ry
, rw
, rh
)); 
 884     lastSelStart 
= m_selStart
; 
 885     lastCursor 
= m_cursor
; 
 888 bool MyAutoTimedScrollingWindow::IsSelected(int chX
, int chY
) const 
 890     if (IsInside(chX
, m_selStart
.x
, m_cursor
.x
) 
 891             && IsInside(chY
, m_selStart
.y
, m_cursor
.y
)) { 
 897 bool MyAutoTimedScrollingWindow::IsInside(int k
, int bound1
, int bound2
) 
 899     if ((k 
>= bound1 
&& k 
<= bound2
) || (k 
>= bound2 
&& k 
<= bound1
)) { 
 905 wxRect 
MyAutoTimedScrollingWindow::DCNormalize(wxCoord x
, wxCoord y
 
 906         , wxCoord w
, wxCoord h
) 
 908     // this is needed to get rid of the graphical remnants from the selection 
 909     // I think it's because DrawRectangle() excludes a pixel in either direction 
 910     const int kludge 
= 1; 
 911     // make (x, y) the top-left corner 
 926     return wxRect(x
, y
, w
, h
); 
 929 void MyAutoTimedScrollingWindow::OnDraw(wxDC
& dc
) 
 932     wxBrush 
normBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
) 
 934     wxBrush 
selBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
) 
 936     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 937     wxString str 
= sm_testData
; 
 939     // draw the characters 
 940     // 1. for each update region 
 941     for (wxRegionIterator 
upd(GetUpdateRegion()); upd
; ++upd
) { 
 942         wxRect updRect 
= upd
.GetRect(); 
 943         wxRect 
updRectInGChars(DeviceCoordsToGraphicalChars(updRect
)); 
 944         // 2. for each row of chars in the update region 
 945         for (int chY 
= updRectInGChars
.y
 
 946                 ; chY 
<= updRectInGChars
.y 
+ updRectInGChars
.height
; ++chY
) { 
 947             // 3. for each character in the row 
 948             for (int chX 
= updRectInGChars
.x
 
 949                     ; chX 
<= updRectInGChars
.x 
+ updRectInGChars
.width
 
 952                 if (IsSelected(chX
, chY
)) { 
 953                     dc
.SetBrush(selBrush
); 
 954                     dc
.SetTextForeground( wxSystemSettings::GetColour
 
 955                             (wxSYS_COLOUR_HIGHLIGHTTEXT
)); 
 957                     dc
.SetBrush(normBrush
); 
 958                     dc
.SetTextForeground( wxSystemSettings::GetColour
 
 959                             (wxSYS_COLOUR_WINDOWTEXT
)); 
 961                 // 5. find position info 
 962                 wxPoint charPos 
= GraphicalCharToLogicalCoords(wxPoint
 
 965                 dc
.DrawRectangle(charPos
.x
, charPos
.y
, m_fontW
, m_fontH
); 
 966                 size_t charIndex 
= chY 
* sm_lineLen 
+ chX
; 
 967                 if (chY 
< sm_lineCnt 
&& 
 969                     charIndex 
< str
.Length()) 
 971                     dc
.DrawText(str
.Mid(charIndex
,1), 
 972                                 charPos
.x
, charPos
.y
); 
 979 void MyAutoTimedScrollingWindow::OnMouseLeftDown(wxMouseEvent
& event
) 
 981     // initial press of mouse button sets the beginning of the selection 
 982     m_selStart 
= DeviceCoordsToGraphicalChars(event
.GetPosition()); 
 983     // set the cursor to the same position 
 984     m_cursor 
= m_selStart
; 
 985     // draw/erase selection 
 989 void MyAutoTimedScrollingWindow::OnMouseLeftUp(wxMouseEvent
& WXUNUSED(event
)) 
 991     // this test is necessary 
 998 void MyAutoTimedScrollingWindow::OnMouseMove(wxMouseEvent
& event
) 
1000     // if user is dragging 
1001     if (event
.Dragging() && event
.LeftIsDown()) { 
1002         // set the new cursor position 
1003         m_cursor 
= DeviceCoordsToGraphicalChars(event
.GetPosition()); 
1004         // draw/erase selection 
1006         // capture mouse to activate auto-scrolling 
1007         if (!HasCapture()) { 
1013 void MyAutoTimedScrollingWindow::OnScroll(wxScrollWinEvent
& event
) 
1015     // need to move the cursor when autoscrolling 
1016     // FIXME: the cursor also moves when the scrollbar arrows are clicked 
1018         if (event
.GetOrientation() == wxHORIZONTAL
) { 
1019             if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) { 
1021             } else if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) { 
1024         } else if (event
.GetOrientation() == wxVERTICAL
) { 
1025             if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) { 
1027             } else if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) { 
1036 const int MyAutoTimedScrollingWindow::sm_lineCnt 
= 125; 
1037 const int MyAutoTimedScrollingWindow::sm_lineLen 
= 79; 
1038 const wxChar
* MyAutoTimedScrollingWindow::sm_testData 
= 
1039 _T("162 Cult of the genius out of vanity. Because we think well of ourselves, but ") 
1040 _T("nonetheless never suppose ourselves capable of producing a painting like one of ") 
1041 _T("Raphael's or a dramatic scene like one of Shakespeare's, we convince ourselves ") 
1042 _T("that the capacity to do so is quite extraordinarily marvelous, a wholly ") 
1043 _T("uncommon accident, or, if we are still religiously inclined, a mercy from on ") 
1044 _T("high. Thus our vanity, our self-love, promotes the cult of the genius: for only ") 
1045 _T("if we think of him as being very remote from us, as a miraculum, does he not ") 
1046 _T("aggrieve us (even Goethe, who was without envy, called Shakespeare his star of ") 
1047 _T("the most distant heights [\"William! Stern der schonsten Ferne\": from Goethe's, ") 
1048 _T("\"Between Two Worlds\"]; in regard to which one might recall the lines: \"the ") 
1049 _T("stars, these we do not desire\" [from Goethe's, \"Comfort in Tears\"]). But, aside ") 
1050 _T("from these suggestions of our vanity, the activity of the genius seems in no ") 
1051 _T("way fundamentally different from the activity of the inventor of machines, the ") 
1052 _T("scholar of astronomy or history, the master of tactics. All these activities ") 
1053 _T("are explicable if one pictures to oneself people whose thinking is active in ") 
1054 _T("one direction, who employ everything as material, who always zealously observe ") 
1055 _T("their own inner life and that of others, who perceive everywhere models and ") 
1056 _T("incentives, who never tire of combining together the means available to them. ") 
1057 _T("Genius too does nothing except learn first how to lay bricks then how to build, ") 
1058 _T("except continually seek for material and continually form itself around it. ") 
1059 _T("Every activity of man is amazingly complicated, not only that of the genius: ") 
1060 _T("but none is a \"miracle.\" Whence, then, the belief that genius exists only in ") 
1061 _T("the artist, orator and philosopher? that only they have \"intuition\"? (Whereby ") 
1062 _T("they are supposed to possess a kind of miraculous eyeglass with which they can ") 
1063 _T("see directly into \"the essence of the thing\"!) It is clear that people speak of ") 
1064 _T("genius only where the effects of the great intellect are most pleasant to them ") 
1065 _T("and where they have no desire to feel envious. To call someone \"divine\" means: ") 
1066 _T("\"here there is no need for us to compete.\" Then, everything finished and ") 
1067 _T("complete is regarded with admiration, everything still becoming is undervalued. ") 
1068 _T("But no one can see in the work of the artist how it has become; that is its ") 
1069 _T("advantage, for wherever one can see the act of becoming one grows somewhat ") 
1070 _T("cool. The finished and perfect art of representation repulses all thinking as ") 
1071 _T("to how it has become; it tyrannizes as present completeness and perfection. ") 
1072 _T("That is why the masters of the art of representation count above all as gifted ") 
1073 _T("with genius and why men of science do not. In reality, this evaluation of the ") 
1074 _T("former and undervaluation of the latter is only a piece of childishness in the ") 
1075 _T("realm of reason. ") 
1077 _T("163 The serious workman. Do not talk about giftedness, inborn talents! One can ") 
1078 _T("name great men of all kinds who were very little gifted. The acquired ") 
1079 _T("greatness, became \"geniuses\" (as we put it), through qualities the lack of ") 
1080 _T("which no one who knew what they were would boast of: they all possessed that ") 
1081 _T("seriousness of the efficient workman which first learns to construct the parts ") 
1082 _T("properly before it ventures to fashion a great whole; they allowed themselves ") 
1083 _T("time for it, because they took more pleasure in making the little, secondary ") 
1084 _T("things well than in the effect of a dazzling whole. the recipe for becoming a ") 
1085 _T("good novelist, for example, is easy to give, but to carry it out presupposes ") 
1086 _T("qualities one is accustomed to overlook when one says \"I do not have enough ") 
1087 _T("talent.\" One has only to make a hundred or so sketches for novels, none longer ") 
1088 _T("than two pages but of such distinctness that every word in them is necessary; ") 
1089 _T("one should write down anecdotes each day until one has learned how to give them ") 
1090 _T("the most pregnant and effective form; one should be tireless in collecting and ") 
1091 _T("describing human types and characters; one should above all relate things to ") 
1092 _T("others and listen to others relate, keeping one's eyes and ears open for the ") 
1093 _T("effect produced on those present, one should travel like a landscape painter or ") 
1094 _T("costume designer; one should excerpt for oneself out of the individual sciences ") 
1095 _T("everything that will produce an artistic effect when it is well described, one ") 
1096 _T("should, finally, reflect on the motives of human actions, disdain no signpost ") 
1097 _T("to instruction about them and be a collector of these things by day and night. ") 
1098 _T("One should continue in this many-sided exercise some ten years: what is then ") 
1099 _T("created in the workshop, however, will be fit to go out into the world. What, ") 
1100 _T("however, do most people do? They begin, not with the parts, but with the whole. ") 
1101 _T("Perhaps they chance to strike a right note, excite attention and from then on ") 
1102 _T("strike worse and worse notes, for good, natural reasons. Sometimes, when the ") 
1103 _T("character and intellect needed to formulate such a life-plan are lacking, fate ") 
1104 _T("and need take their place and lead the future master step by step through all ") 
1105 _T("the stipulations of his trade. ") 
1107 _T("164 Peril and profit in the cult of the genius. The belief in great, superior, ") 
1108 _T("fruitful spirits is not necessarily, yet nonetheless is very frequently ") 
1109 _T("associated with that religious or semi-religious superstition that these ") 
1110 _T("spirits are of supra-human origin and possess certain miraculous abilities by ") 
1111 _T("virtue of which they acquire their knowledge by quite other means than the rest ") 
1112 _T("of mankind. One ascribes to them, it seems, a direct view of the nature of the ") 
1113 _T("world, as it were a hole in the cloak of appearance, and believes that, by ") 
1114 _T("virtue of this miraculous seer's vision, they are able to communicate something ") 
1115 _T("conclusive and decisive about man and the world without the toil and ") 
1116 _T("rigorousness required by science. As long as there continue to be those who ") 
1117 _T("believe in the miraculous in the domain of knowledge one can perhaps concede ") 
1118 _T("that these people themselves derive some benefit from their belief, inasmuch as ") 
1119 _T("through their unconditional subjection to the great spirits they create for ") 
1120 _T("their own spirit during its time of development the finest form of discipline ") 
1121 _T("and schooling. On the other hand, it is at least questionable whether the ") 
1122 _T("superstitious belief in genius, in its privileges and special abilities, is of ") 
1123 _T("benefit to the genius himself if it takes root in him. It is in any event a ") 
1124 _T("dangerous sign when a man is assailed by awe of himself, whether it be the ") 
1125 _T("celebrated Caesar's awe of Caesar or the awe of one's own genius now under ") 
1126 _T("consideration; when the sacrificial incense which is properly rendered only to ") 
1127 _T("a god penetrates the brain of the genius, so that his head begins to swim and ") 
1128 _T("he comes to regard himself as something supra-human. The consequences that ") 
1129 _T("slowly result are: the feeling of irresponsibility, of exceptional rights, the ") 
1130 _T("belief that he confers a favor by his mere presence, insane rage when anyone ") 
1131 _T("attempts even to compare him with others, let alone to rate him beneath them, ") 
1132 _T("or to draw attention to lapses in his work. Because he ceases to practice ") 
1133 _T("criticism of himself, at last one pinion after the other falls out of his ") 
1134 _T("plumage: that superstitious eats at the roots of his powers and perhaps even ") 
1135 _T("turns him into a hypocrite after his powers have fled from him. For the great ") 
1136 _T("spirits themselves it is therefore probably more beneficial if they acquire an ") 
1137 _T("insight into the nature and origin of their powers, if they grasp, that is to ") 
1138 _T("say, what purely human qualities have come together in them and what fortunate ") 
1139 _T("circumstances attended them: in the first place undiminished energy, resolute ") 
1140 _T("application to individual goals, great personal courage, then the good fortune ") 
1141 _T("to receive an upbringing which offered in the early years the finest teachers, ") 
1142 _T("models and methods. To be sure, when their goal is the production of the ") 
1143 _T("greatest possible effect, unclarity with regard to oneself and that ") 
1144 _T("semi-insanity superadded to it has always achieved much; for what has been ") 
1145 _T("admired and envied at all times has been that power in them by virtue of which ") 
1146 _T("they render men will-less and sweep them away into the delusion that the ") 
1147 _T("leaders they are following are supra-natural. Indeed, it elevates and inspires ") 
1148 _T("men to believe that someone is in possession of supra-natural powers: to this ") 
1149 _T("extent Plato was right to say [Plato: Phaedrus, 244a] that madness has brought ") 
1150 _T("the greatest of blessings upon mankind. In rare individual cases this portion ") 
1151 _T("of madness may, indeed, actually have been the means by which such a nature, ") 
1152 _T("excessive in all directions, was held firmly together: in the life of ") 
1153 _T("individuals, too, illusions that are in themselves poisons often play the role ") 
1154 _T("of healers; yet, in the end, in the case of every \"genius\" who believes in his ") 
1155 _T("own divinity the poison shows itself to the same degree as his \"genius\" grows ") 
1156 _T("old: one may recall, for example, the case of Napoleon, whose nature certainly ") 
1157 _T("grew into the mighty unity that sets him apart from all men of modern times ") 
1158 _T("precisely through his belief in himself and his star and through the contempt ") 
1159 _T("for men that flowed from it; until in the end, however, this same belief went ") 
1160 _T("over into an almost insane fatalism, robbed him of his acuteness and swiftness ") 
1161 _T("of perception, and became the cause of his destruction.");