4 * Author: Robert Roebling
6 * Copyright: (C) 1998, Robert Roebling
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
24 #include "wx/listctrl.h"
36 class MyCanvas
: public wxScrolledWindow
40 MyCanvas( wxWindow
*parent
, wxWindowID
, const wxPoint
&pos
, const wxSize
&size
);
42 void OnPaint( wxPaintEvent
&event
);
43 void OnQueryPosition( wxCommandEvent
&event
);
44 void OnAddButton( wxCommandEvent
&event
);
45 void OnDeleteButton( wxCommandEvent
&event
);
46 void OnMoveButton( wxCommandEvent
&event
);
47 void OnScrollWin( wxCommandEvent
&event
);
48 void OnMouseDown( wxMouseEvent
&event
);
52 DECLARE_DYNAMIC_CLASS(MyCanvas
)
57 // ----------------------------------------------------------------------------
58 // Autoscrolling example.
59 // ----------------------------------------------------------------------------
61 // this class uses the 'virtual' size attribute along with an internal
62 // sizer to automatically set up scrollbars as needed
64 class MyAutoScrollWindow
: public wxScrolledWindow
72 MyAutoScrollWindow( wxWindow
*parent
);
74 void OnResizeClick( wxCommandEvent
&WXUNUSED( event
) );
80 // ----------------------------------------------------------------------------
81 // MyScrolledWindow classes: examples of wxScrolledWindow usage
82 // ----------------------------------------------------------------------------
84 // base class for both of them
85 class MyScrolledWindowBase
: public wxScrolledWindow
88 MyScrolledWindowBase(wxWindow
*parent
)
89 : wxScrolledWindow(parent
)
93 dc
.GetTextExtent(_T("Line 17"), NULL
, &m_hLine
);
97 // the height of one line on screen
100 // the number of lines we draw
104 // this class does "stupid" redrawing - it redraws everything each time
105 // and sets the scrollbar extent directly.
107 class MyScrolledWindowDumb
: public MyScrolledWindowBase
110 MyScrolledWindowDumb(wxWindow
*parent
) : MyScrolledWindowBase(parent
)
113 SetScrollbars(0, m_hLine
, 0, m_nLines
+ 1, 0, 0, true /* no refresh */);
116 virtual void OnDraw(wxDC
& dc
);
119 // this class does "smart" redrawing - only redraws the lines which must be
120 // redrawn and sets the scroll rate and virtual size to affect the
123 // Note that this class should produce identical results to the one above.
125 class MyScrolledWindowSmart
: public MyScrolledWindowBase
128 MyScrolledWindowSmart(wxWindow
*parent
) : MyScrolledWindowBase(parent
)
131 SetScrollRate( 0, m_hLine
);
132 SetVirtualSize( -1, ( m_nLines
+ 1 ) * m_hLine
);
135 virtual void OnDraw(wxDC
& dc
);
138 // ----------------------------------------------------------------------------
139 // MyAutoTimedScrollingWindow: implements a text viewer with simple blocksize
140 // selection to test auto-scrolling functionality
141 // ----------------------------------------------------------------------------
143 class MyAutoTimedScrollingWindow
: public wxScrolledWindow
145 protected: // member data
146 // test data variables
147 static const wxChar
* sm_testData
;
148 static const int sm_lineCnt
; // line count
149 static const int sm_lineLen
; // line length in characters
150 // sizes for graphical data
151 wxCoord m_fontH
, m_fontW
;
152 // selection tracking
153 wxPoint m_selStart
; // beginning of blockwise selection
154 wxPoint m_cursor
; // end of blockwise selection (mouse position)
156 protected: // gui stuff
160 MyAutoTimedScrollingWindow( wxWindow
* parent
);
161 wxRect
DeviceCoordsToGraphicalChars(wxRect updRect
) const;
162 wxPoint
DeviceCoordsToGraphicalChars(wxPoint pos
) const;
163 wxPoint
GraphicalCharToDeviceCoords(wxPoint pos
) const;
164 wxRect
LogicalCoordsToGraphicalChars(wxRect updRect
) const;
165 wxPoint
LogicalCoordsToGraphicalChars(wxPoint pos
) const;
166 wxPoint
GraphicalCharToLogicalCoords(wxPoint pos
) const;
168 bool IsSelected(int chX
, int chY
) const;
169 static bool IsInside(int k
, int bound1
, int bound2
);
170 static wxRect
DCNormalize(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
);
172 protected: // event stuff
173 DECLARE_EVENT_TABLE()
174 void OnDraw(wxDC
& dc
);
175 void OnMouseLeftDown(wxMouseEvent
& event
);
176 void OnMouseLeftUp(wxMouseEvent
& event
);
177 void OnMouseMove(wxMouseEvent
& event
);
178 void OnScroll(wxScrollWinEvent
& event
);
181 // ----------------------------------------------------------------------------
183 // ----------------------------------------------------------------------------
185 class MyFrame
: public wxFrame
190 void OnAbout( wxCommandEvent
&event
);
191 void OnQuit( wxCommandEvent
&event
);
192 void OnDeleteAll( wxCommandEvent
&event
);
193 void OnInsertNew( wxCommandEvent
&event
);
198 DECLARE_DYNAMIC_CLASS(MyFrame
)
199 DECLARE_EVENT_TABLE()
202 // ----------------------------------------------------------------------------
204 // ----------------------------------------------------------------------------
206 class MyApp
: public wxApp
209 virtual bool OnInit();
213 // ----------------------------------------------------------------------------
215 // ----------------------------------------------------------------------------
221 const long ID_ADDBUTTON
= wxNewId();
222 const long ID_DELBUTTON
= wxNewId();
223 const long ID_MOVEBUTTON
= wxNewId();
224 const long ID_SCROLLWIN
= wxNewId();
225 const long ID_QUERYPOS
= wxNewId();
227 const long ID_NEWBUTTON
= wxNewId();
229 // ----------------------------------------------------------------------------
231 // ----------------------------------------------------------------------------
233 IMPLEMENT_DYNAMIC_CLASS(MyCanvas
, wxScrolledWindow
)
235 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
236 EVT_PAINT( MyCanvas::OnPaint
)
237 EVT_MOUSE_EVENTS( MyCanvas::OnMouseDown
)
238 EVT_BUTTON( ID_QUERYPOS
, MyCanvas::OnQueryPosition
)
239 EVT_BUTTON( ID_ADDBUTTON
, MyCanvas::OnAddButton
)
240 EVT_BUTTON( ID_DELBUTTON
, MyCanvas::OnDeleteButton
)
241 EVT_BUTTON( ID_MOVEBUTTON
, MyCanvas::OnMoveButton
)
242 EVT_BUTTON( ID_SCROLLWIN
, MyCanvas::OnScrollWin
)
245 MyCanvas::MyCanvas( wxWindow
*parent
, wxWindowID id
,
246 const wxPoint
&pos
, const wxSize
&size
)
247 : wxScrolledWindow( parent
, id
, pos
, size
, wxSUNKEN_BORDER
| wxTAB_TRAVERSAL
, _T("test canvas") )
249 SetScrollRate( 10, 10 );
250 SetVirtualSize( 500, 1000 );
252 (void) new wxButton( this, ID_ADDBUTTON
, _T("add button"), wxPoint(10,10) );
253 (void) new wxButton( this, ID_DELBUTTON
, _T("del button"), wxPoint(10,40) );
254 (void) new wxButton( this, ID_MOVEBUTTON
, _T("move button"), wxPoint(150,10) );
255 (void) new wxButton( this, ID_SCROLLWIN
, _T("scroll win"), wxPoint(250,10) );
268 m_button
= new wxButton( this, ID_QUERYPOS
, "Query position", wxPoint(10,110) );
270 (void) new wxTextCtrl( this, wxID_ANY
, "wxTextCtrl", wxPoint(10,150), wxSize(80,wxDefaultCoord
) );
272 (void) new wxRadioButton( this, wxID_ANY
, "Disable", wxPoint(10,190) );
274 (void) new wxComboBox( this, wxID_ANY
, "This", wxPoint(10,230), wxDefaultSize
, 5, choices
);
276 (void) new wxRadioBox( this, wxID_ANY
, "This", wxPoint(10,310), wxDefaultSize
, 5, choices
, 2, wxRA_SPECIFY_COLS
);
278 (void) new wxRadioBox( this, wxID_ANY
, "This", wxPoint(10,440), wxDefaultSize
, 5, choices
, 2, wxRA_SPECIFY_ROWS
);
280 wxListCtrl
*m_listCtrl
= new wxListCtrl(
281 this, wxID_ANY
, wxPoint(200, 110), wxSize(180, 120),
282 wxLC_REPORT
| wxSIMPLE_BORDER
| wxLC_SINGLE_SEL
);
284 m_listCtrl
->InsertColumn(0, "First", wxLIST_FORMAT_LEFT
, 90);
285 m_listCtrl
->InsertColumn(1, "Last", wxLIST_FORMAT_LEFT
, 90);
287 for ( int i
=0; i
< 30; i
++)
290 sprintf(buf
, "Item %d", i
);
291 m_listCtrl
->InsertItem(i
, buf
);
293 m_listCtrl
->SetItemState( 3, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
295 (void) new wxListBox( this, wxID_ANY
, wxPoint(260,280), wxSize(120,120), 5, choices
, wxLB_ALWAYS_SB
);
299 wxPanel
*test
= new wxPanel( this, wxID_ANY
, wxPoint(10, 110), wxSize(130,50), wxSIMPLE_BORDER
| wxTAB_TRAVERSAL
);
300 test
->SetBackgroundColour( wxT("WHEAT") );
304 wxButton
*test2
= new wxButton( test
, wxID_ANY
, "Hallo", wxPoint(10,10) );
306 test
= new wxPanel( this, wxID_ANY
, wxPoint(160, 530), wxSize(130,120), wxSUNKEN_BORDER
| wxTAB_TRAVERSAL
);
307 test
->SetBackgroundColour( wxT("WHEAT") );
308 test
->SetCursor( wxCursor( wxCURSOR_NO_ENTRY
) );
309 test2
= new wxButton( test
, wxID_ANY
, "Hallo", wxPoint(10,10) );
310 test2
->SetCursor( wxCursor( wxCURSOR_PENCIL
) );
312 test
= new wxPanel( this, wxID_ANY
, wxPoint(310, 530), wxSize(130,120), wxRAISED_BORDER
| wxTAB_TRAVERSAL
);
313 test
->SetBackgroundColour( wxT("WHEAT") );
314 test
->SetCursor( wxCursor( wxCURSOR_PENCIL
) );
315 test2
= new wxButton( test
, wxID_ANY
, "Hallo", wxPoint(10,10) );
316 test2
->SetCursor( wxCursor( wxCURSOR_NO_ENTRY
) );
320 SetBackgroundColour( wxT("BLUE") );
322 SetCursor( wxCursor( wxCURSOR_IBEAM
) );
325 void MyCanvas::OnMouseDown( wxMouseEvent
&event
)
327 if (event
.LeftDown())
329 wxPoint
pt( event
.GetPosition() );
331 CalcUnscrolledPosition( pt
.x
, pt
.y
, &x
, &y
);
332 wxLogMessage( wxT("Mouse down event at: %d %d, scrolled: %d %d"), pt
.x
, pt
.y
, x
, y
);
334 if ( !event
.LeftIsDown() )
335 wxLogMessage( wxT("Error: LeftIsDown() should be true if for LeftDown()") );
339 void MyCanvas::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
341 wxPaintDC
dc( this );
344 dc
.DrawText( _T("Press mouse button to test calculations!"), 160, 50 );
346 dc
.DrawText( _T("Some text"), 140, 140 );
348 dc
.DrawRectangle( 100, 160, 200, 200 );
351 void MyCanvas::OnQueryPosition( wxCommandEvent
&WXUNUSED(event
) )
353 wxPoint
pt( m_button
->GetPosition() );
354 wxLogMessage( wxT("Position of \"Query position\" is %d %d"), pt
.x
, pt
.y
);
355 pt
= ClientToScreen( pt
);
356 wxLogMessage( wxT("Position of \"Query position\" on screen is %d %d"), pt
.x
, pt
.y
);
359 void MyCanvas::OnAddButton( wxCommandEvent
&WXUNUSED(event
) )
361 wxLogMessage( wxT("Inserting button at position 10,70...") );
362 wxButton
*button
= new wxButton( this, ID_NEWBUTTON
, wxT("new button"), wxPoint(10,70), wxSize(80,25) );
363 wxPoint
pt( button
->GetPosition() );
364 wxLogMessage( wxT("-> Position after inserting %d %d"), pt
.x
, pt
.y
);
367 void MyCanvas::OnDeleteButton( wxCommandEvent
&WXUNUSED(event
) )
369 wxLogMessage( wxT("Deleting button inserted with \"Add button\"...") );
370 wxWindow
*win
= FindWindow( ID_NEWBUTTON
);
374 wxLogMessage( wxT("-> No window with id = ID_NEWBUTTON found.") );
377 void MyCanvas::OnMoveButton( wxCommandEvent
&event
)
379 wxLogMessage( wxT("Moving button 10 pixels downward..") );
380 wxWindow
*win
= FindWindow( event
.GetId() );
381 wxPoint
pt( win
->GetPosition() );
382 wxLogMessage( wxT("-> Position before move is %d %d"), pt
.x
, pt
.y
);
383 win
->Move( wxDefaultCoord
, pt
.y
+ 10 );
384 pt
= win
->GetPosition();
385 wxLogMessage( wxT("-> Position after move is %d %d"), pt
.x
, pt
.y
);
388 void MyCanvas::OnScrollWin( wxCommandEvent
&WXUNUSED(event
) )
390 wxLogMessage( wxT("Scrolling 2 units up.\nThe white square and the controls should move equally!") );
392 GetViewStart( &x
, &y
);
396 // ----------------------------------------------------------------------------
397 // MyAutoScrollWindow
398 // ----------------------------------------------------------------------------
400 const long ID_RESIZEBUTTON
= wxNewId();
401 const wxSize
SMALL_BUTTON( 100, 50 );
402 const wxSize
LARGE_BUTTON( 300, 100 );
404 BEGIN_EVENT_TABLE( MyAutoScrollWindow
, wxScrolledWindow
)
405 EVT_BUTTON( ID_RESIZEBUTTON
, MyAutoScrollWindow::OnResizeClick
)
408 MyAutoScrollWindow::MyAutoScrollWindow( wxWindow
*parent
)
409 : wxScrolledWindow( parent
)
411 SetBackgroundColour( wxT("GREEN") );
413 // Set the rate we'd like for scrolling.
415 SetScrollRate( 5, 5 );
417 // Populate a sizer with a 'resizing' button and some
418 // other static decoration
420 wxFlexGridSizer
*innersizer
= new wxFlexGridSizer( 2, 2 );
422 m_button
= new wxButton( this,
428 // We need to do this here, because wxADJUST_MINSIZE below
429 // will cause the initial size to be ignored for Best/Min size.
430 // It would be nice to fix the sizers to handle this a little
433 m_button
->SetSizeHints( SMALL_BUTTON
.GetWidth(), SMALL_BUTTON
.GetHeight() );
435 innersizer
->Add( m_button
,
437 wxALIGN_CENTER
| wxALL
| wxADJUST_MINSIZE
,
440 innersizer
->Add( new wxStaticText( this, wxID_ANY
, _T("This is just") ),
444 innersizer
->Add( new wxStaticText( this, wxID_ANY
, _T("some decoration") ),
448 innersizer
->Add( new wxStaticText( this, wxID_ANY
, _T("for you to scroll...") ),
452 // Then use the sizer to set the scrolled region size.
454 SetSizer( innersizer
);
457 void MyAutoScrollWindow::OnResizeClick( wxCommandEvent
&WXUNUSED( event
) )
459 // Arbitrarily resize the button to change the minimum size of
460 // the (scrolled) sizer.
462 if( m_button
->GetSize() == SMALL_BUTTON
)
463 m_button
->SetSizeHints( LARGE_BUTTON
.GetWidth(), LARGE_BUTTON
.GetHeight() );
465 m_button
->SetSizeHints( SMALL_BUTTON
.GetWidth(), SMALL_BUTTON
.GetHeight() );
467 // Force update layout and scrollbars, since nothing we do here
468 // necessarily generates a size event which would do it for us.
473 // ----------------------------------------------------------------------------
475 // ----------------------------------------------------------------------------
477 const long ID_QUIT
= wxNewId();
478 const long ID_ABOUT
= wxNewId();
479 const long ID_DELETE_ALL
= wxNewId();
480 const long ID_INSERT_NEW
= wxNewId();
482 IMPLEMENT_DYNAMIC_CLASS( MyFrame
, wxFrame
)
484 BEGIN_EVENT_TABLE(MyFrame
,wxFrame
)
485 EVT_MENU (ID_DELETE_ALL
, MyFrame::OnDeleteAll
)
486 EVT_MENU (ID_INSERT_NEW
, MyFrame::OnInsertNew
)
487 EVT_MENU (ID_ABOUT
, MyFrame::OnAbout
)
488 EVT_MENU (ID_QUIT
, MyFrame::OnQuit
)
492 : wxFrame( (wxFrame
*)NULL
, wxID_ANY
, _T("wxScrolledWindow sample"),
493 wxPoint(20,20), wxSize(800,500) )
495 wxMenu
*file_menu
= new wxMenu();
496 file_menu
->Append( ID_DELETE_ALL
, _T("Delete all"));
497 file_menu
->Append( ID_INSERT_NEW
, _T("Insert new"));
498 file_menu
->Append( ID_ABOUT
, _T("&About.."));
499 file_menu
->Append( ID_QUIT
, _T("E&xit\tAlt-X"));
501 wxMenuBar
*menu_bar
= new wxMenuBar();
502 menu_bar
->Append(file_menu
, _T("&File"));
504 SetMenuBar( menu_bar
);
508 int widths
[] = { -1, 100 };
509 SetStatusWidths( 2, widths
);
510 #endif // wxUSE_STATUSBAR
512 wxBoxSizer
*topsizer
= new wxBoxSizer( wxHORIZONTAL
);
513 // subsizer splits topsizer down the middle
514 wxBoxSizer
*subsizer
= new wxBoxSizer( wxVERTICAL
);
516 // Setting an explicit size here is superfluous, it will be overridden
517 // by the sizer in any case.
518 m_canvas
= new MyCanvas( this, wxID_ANY
, wxPoint(0,0), wxSize(100,100) );
520 // This is done with ScrollRate/VirtualSize in MyCanvas ctor now,
521 // both should produce identical results.
522 //m_canvas->SetScrollbars( 10, 10, 50, 100 );
524 subsizer
->Add( m_canvas
, 1, wxEXPAND
);
525 subsizer
->Add( new MyAutoScrollWindow( this ), 1, wxEXPAND
);
527 wxSizer
*sizerBtm
= new wxBoxSizer(wxHORIZONTAL
);
528 sizerBtm
->Add( new MyScrolledWindowDumb(this), 1, wxEXPAND
);
529 sizerBtm
->Add( new MyScrolledWindowSmart(this), 1, wxEXPAND
);
530 subsizer
->Add( sizerBtm
, 1, wxEXPAND
);
532 topsizer
->Add( subsizer
, 1, wxEXPAND
);
533 topsizer
->Add( new MyAutoTimedScrollingWindow( this ), 1, wxEXPAND
);
535 SetSizer( topsizer
);
538 void MyFrame::OnDeleteAll( wxCommandEvent
&WXUNUSED(event
) )
540 m_canvas
->DestroyChildren();
543 void MyFrame::OnInsertNew( wxCommandEvent
&WXUNUSED(event
) )
545 (void)new wxButton( m_canvas
, wxID_ANY
, _T("Hello"), wxPoint(100,100) );
548 void MyFrame::OnQuit( wxCommandEvent
&WXUNUSED(event
) )
553 void MyFrame::OnAbout( wxCommandEvent
&WXUNUSED(event
) )
555 (void)wxMessageBox( _T("wxScroll demo\n")
556 _T("Robert Roebling (c) 1998\n")
557 _T("Autoscrolling examples\n")
558 _T("Ron Lee (c) 2002\n")
559 _T("Auto-timed-scrolling example\n")
560 _T("Matt Gregory (c) 2003\n"),
561 _T("About wxScroll Demo"),
562 wxICON_INFORMATION
| wxOK
);
565 //-----------------------------------------------------------------------------
567 //-----------------------------------------------------------------------------
571 wxFrame
*frame
= new MyFrame();
577 // ----------------------------------------------------------------------------
578 // MyScrolledWindowXXX
579 // ----------------------------------------------------------------------------
581 void MyScrolledWindowDumb::OnDraw(wxDC
& dc
)
583 // this is useful to see which lines are redrawn
584 static size_t s_redrawCount
= 0;
585 dc
.SetTextForeground(s_redrawCount
++ % 2 ? *wxRED
: *wxBLUE
);
588 for ( size_t line
= 0; line
< m_nLines
; line
++ )
591 CalcScrolledPosition(0, y
, NULL
, &yPhys
);
593 dc
.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"),
594 line
, y
, yPhys
), 0, y
);
599 void MyScrolledWindowSmart::OnDraw(wxDC
& dc
)
601 // this is useful to see which lines are redrawn
602 static size_t s_redrawCount
= 0;
603 dc
.SetTextForeground(s_redrawCount
++ % 2 ? *wxRED
: *wxBLUE
);
605 // update region is always in device coords, translate to logical ones
606 wxRect rectUpdate
= GetUpdateRegion().GetBox();
607 CalcUnscrolledPosition(rectUpdate
.x
, rectUpdate
.y
,
608 &rectUpdate
.x
, &rectUpdate
.y
);
610 size_t lineFrom
= rectUpdate
.y
/ m_hLine
,
611 lineTo
= rectUpdate
.GetBottom() / m_hLine
;
613 if ( lineTo
> m_nLines
- 1)
614 lineTo
= m_nLines
- 1;
616 wxCoord y
= lineFrom
*m_hLine
;
617 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
620 CalcScrolledPosition(0, y
, NULL
, &yPhys
);
622 dc
.DrawText(wxString::Format(_T("Line %u (logical %d, physical %d)"),
623 line
, y
, yPhys
), 0, y
);
628 // ----------------------------------------------------------------------------
629 // MyAutoTimedScrollingWindow
630 // ----------------------------------------------------------------------------
632 BEGIN_EVENT_TABLE(MyAutoTimedScrollingWindow
, wxScrolledWindow
)
633 EVT_LEFT_DOWN(MyAutoTimedScrollingWindow::OnMouseLeftDown
)
634 EVT_LEFT_UP(MyAutoTimedScrollingWindow::OnMouseLeftUp
)
635 EVT_MOTION(MyAutoTimedScrollingWindow::OnMouseMove
)
636 EVT_SCROLLWIN(MyAutoTimedScrollingWindow::OnScroll
)
639 MyAutoTimedScrollingWindow::MyAutoTimedScrollingWindow(wxWindow
* parent
)
640 : wxScrolledWindow(parent
, -1, wxDefaultPosition
, wxDefaultSize
641 //, wxSUNKEN_BORDER) // can't seem to do it this way
642 , wxVSCROLL
| wxHSCROLL
| wxSUNKEN_BORDER
)
643 , m_selStart(-1, -1), m_cursor(-1, -1)
644 , m_font(9, wxFONTFAMILY_TELETYPE
, wxFONTSTYLE_NORMAL
645 , wxFONTWEIGHT_NORMAL
)
648 // query dc for text size
650 dc
.GetTextExtent(wxString(_T("A")), &m_fontW
, &m_fontH
);
651 // set up the virtual window
652 SetScrollbars(m_fontW
, m_fontH
, sm_lineLen
, sm_lineCnt
);
655 wxRect
MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars
656 (wxRect updRect
) const
658 wxPoint
pos(updRect
.GetPosition());
659 pos
= DeviceCoordsToGraphicalChars(pos
);
662 updRect
.width
/= m_fontW
;
663 updRect
.height
/= m_fontH
;
664 // the *CoordsToGraphicalChars() funcs round down to upper-left corner,
665 // so an off-by-one correction is needed
666 ++updRect
.width
; // kludge
667 ++updRect
.height
; // kludge
671 wxPoint
MyAutoTimedScrollingWindow::DeviceCoordsToGraphicalChars
677 GetViewStart(&vX
, &vY
);
683 wxPoint
MyAutoTimedScrollingWindow::GraphicalCharToDeviceCoords
687 GetViewStart(&vX
, &vY
);
695 wxRect
MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars
696 (wxRect updRect
) const
698 wxPoint
pos(updRect
.GetPosition());
699 pos
= LogicalCoordsToGraphicalChars(pos
);
702 updRect
.width
/= m_fontW
;
703 updRect
.height
/= m_fontH
;
704 // the *CoordsToGraphicalChars() funcs round down to upper-left corner,
705 // so an off-by-one correction is needed
706 ++updRect
.width
; // kludge
707 ++updRect
.height
; // kludge
711 wxPoint
MyAutoTimedScrollingWindow::LogicalCoordsToGraphicalChars
719 wxPoint
MyAutoTimedScrollingWindow::GraphicalCharToLogicalCoords
727 void MyAutoTimedScrollingWindow::MyRefresh()
729 static wxPoint
lastSelStart(-1, -1), lastCursor(-1, -1);
730 // refresh last selected area (to deselect previously selected text)
732 GraphicalCharToDeviceCoords(lastSelStart
),
733 GraphicalCharToDeviceCoords(lastCursor
)
735 // off-by-one corrections, necessary because it's not possible to know
736 // when to round up until rect is normalized by lastUpdRect constructor
737 lastUpdRect
.width
+= m_fontW
; // kludge
738 lastUpdRect
.height
+= m_fontH
; // kludge
739 // refresh currently selected (to select previously unselected text)
741 GraphicalCharToDeviceCoords(m_selStart
),
742 GraphicalCharToDeviceCoords(m_cursor
)
744 // off-by-one corrections
745 updRect
.width
+= m_fontW
; // kludge
746 updRect
.height
+= m_fontH
; // kludge
747 // find necessary refresh areas
748 wxCoord rx
= lastUpdRect
.x
;
749 wxCoord ry
= lastUpdRect
.y
;
750 wxCoord rw
= updRect
.x
- lastUpdRect
.x
;
751 wxCoord rh
= lastUpdRect
.height
;
753 RefreshRect(DCNormalize(rx
, ry
, rw
, rh
));
756 ry
= updRect
.y
+ updRect
.height
;
758 rh
= (lastUpdRect
.y
+ lastUpdRect
.height
) - (updRect
.y
+ updRect
.height
);
760 RefreshRect(DCNormalize(rx
, ry
, rw
, rh
));
762 rx
= updRect
.x
+ updRect
.width
;
764 rw
= (lastUpdRect
.x
+ lastUpdRect
.width
) - (updRect
.x
+ updRect
.width
);
765 rh
= lastUpdRect
.height
;
767 RefreshRect(DCNormalize(rx
, ry
, rw
, rh
));
772 rh
= updRect
.y
- lastUpdRect
.y
;
774 RefreshRect(DCNormalize(rx
, ry
, rw
, rh
));
777 lastSelStart
= m_selStart
;
778 lastCursor
= m_cursor
;
781 bool MyAutoTimedScrollingWindow::IsSelected(int chX
, int chY
) const
783 if (IsInside(chX
, m_selStart
.x
, m_cursor
.x
)
784 && IsInside(chY
, m_selStart
.y
, m_cursor
.y
)) {
790 bool MyAutoTimedScrollingWindow::IsInside(int k
, int bound1
, int bound2
)
792 if ((k
>= bound1
&& k
<= bound2
) || (k
>= bound2
&& k
<= bound1
)) {
798 wxRect
MyAutoTimedScrollingWindow::DCNormalize(wxCoord x
, wxCoord y
799 , wxCoord w
, wxCoord h
)
801 // this is needed to get rid of the graphical remnants from the selection
802 // I think it's because DrawRectangle() excludes a pixel in either direction
803 const int kludge
= 1;
804 // make (x, y) the top-left corner
819 return wxRect(x
, y
, w
, h
);
822 void MyAutoTimedScrollingWindow::OnDraw(wxDC
& dc
)
825 wxBrush
normBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)
827 wxBrush
selBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
)
829 dc
.SetPen(*wxTRANSPARENT_PEN
);
830 // draw the characters
831 // 1. for each update region
832 for (wxRegionIterator
upd(GetUpdateRegion()); upd
; ++upd
) {
833 wxSize clientSize
= GetClientSize();
834 wxRect updRect
= upd
.GetRect();
835 wxRect
updRectInGChars(DeviceCoordsToGraphicalChars(updRect
));
836 // 2. for each row of chars in the update region
837 for (int chY
= updRectInGChars
.y
838 ; chY
<= updRectInGChars
.y
+ updRectInGChars
.height
; ++chY
) {
839 // 3. for each character in the row
840 for (int chX
= updRectInGChars
.x
841 ; chX
<= updRectInGChars
.x
+ updRectInGChars
.width
844 if (IsSelected(chX
, chY
)) {
845 dc
.SetBrush(selBrush
);
846 dc
.SetTextForeground( wxSystemSettings::GetColour
847 (wxSYS_COLOUR_HIGHLIGHTTEXT
));
849 dc
.SetBrush(normBrush
);
850 dc
.SetTextForeground( wxSystemSettings::GetColour
851 (wxSYS_COLOUR_WINDOWTEXT
));
853 // 5. find position info
854 wxPoint charPos
= GraphicalCharToLogicalCoords(wxPoint
857 dc
.DrawRectangle(charPos
.x
, charPos
.y
, m_fontW
, m_fontH
);
858 if (chY
< sm_lineCnt
&& chX
< sm_lineLen
) {
859 int charIndex
= chY
* sm_lineLen
+ chX
;
860 dc
.DrawText(wxString(sm_testData
[charIndex
])
861 , charPos
.x
, charPos
.y
);
868 void MyAutoTimedScrollingWindow::OnMouseLeftDown(wxMouseEvent
& event
)
870 // initial press of mouse button sets the beginning of the selection
871 m_selStart
= DeviceCoordsToGraphicalChars(event
.GetPosition());
872 // set the cursor to the same position
873 m_cursor
= m_selStart
;
874 // draw/erase selection
878 void MyAutoTimedScrollingWindow::OnMouseLeftUp(wxMouseEvent
& WXUNUSED(event
))
880 // this test is necessary
887 void MyAutoTimedScrollingWindow::OnMouseMove(wxMouseEvent
& event
)
889 // if user is dragging
890 if (event
.Dragging() && event
.LeftIsDown()) {
891 // set the new cursor position
892 m_cursor
= DeviceCoordsToGraphicalChars(event
.GetPosition());
893 // draw/erase selection
895 // capture mouse to activate auto-scrolling
902 void MyAutoTimedScrollingWindow::OnScroll(wxScrollWinEvent
& event
)
904 // need to move the cursor when autoscrolling
905 // FIXME: the cursor also moves when the scrollbar arrows are clicked
907 if (event
.GetOrientation() == wxHORIZONTAL
) {
908 if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) {
910 } else if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) {
913 } else if (event
.GetOrientation() == wxVERTICAL
) {
914 if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) {
916 } else if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) {
925 const int MyAutoTimedScrollingWindow::sm_lineCnt
= 125;
926 const int MyAutoTimedScrollingWindow::sm_lineLen
= 79;
927 const wxChar
* MyAutoTimedScrollingWindow::sm_testData
= _T("\
928 162 Cult of the genius out of vanity.\97 Because we think well of ourselves, but \
929 nonetheless never suppose ourselves capable of producing a painting like one of\
930 Raphael's or a dramatic scene like one of Shakespeare's, we convince ourselves \
931 that the capacity to do so is quite extraordinarily marvelous, a wholly \
932 uncommon accident, or, if we are still religiously inclined, a mercy from on \
933 high. Thus our vanity, our self-love, promotes the cult of the genius: for only\
934 if we think of him as being very remote from us, as a miraculum, does he not \
935 aggrieve us (even Goethe, who was without envy, called Shakespeare his star of \
936 the most distant heights [\"William! Stern der schönsten Ferne\": from Goethe's, \
937 \"Between Two Worlds\"]; in regard to which one might recall the lines: \"the \
938 stars, these we do not desire\" [from Goethe's, \"Comfort in Tears\"]). But, aside\
939 from these suggestions of our vanity, the activity of the genius seems in no \
940 way fundamentally different from the activity of the inventor of machines, the \
941 scholar of astronomy or history, the master of tactics. All these activities \
942 are explicable if one pictures to oneself people whose thinking is active in \
943 one direction, who employ everything as material, who always zealously observe \
944 their own inner life and that of others, who perceive everywhere models and \
945 incentives, who never tire of combining together the means available to them. \
946 Genius too does nothing except learn first how to lay bricks then how to build,\
947 except continually seek for material and continually form itself around it. \
948 Every activity of man is amazingly complicated, not only that of the genius: \
949 but none is a \"miracle.\"\97 Whence, then, the belief that genius exists only in \
950 the artist, orator and philosopher? that only they have \"intuition\"? (Whereby \
951 they are supposed to possess a kind of miraculous eyeglass with which they can \
952 see directly into \"the essence of the thing\"!) It is clear that people speak of\
954 genius only where the effects of the great intellect are most pleasant to them \
955 and where they have no desire to feel envious. To call someone \"divine\" means: \
956 \"here there is no need for us to compete.\" Then, everything finished and \
957 complete is regarded with admiration, everything still becoming is undervalued.\
958 But no one can see in the work of the artist how it has become; that is its \
959 advantage, for wherever one can see the act of becoming one grows somewhat \
960 cool. The finished and perfect art of representation repulses all thinking as \
961 to how it has become; it tyrannizes as present completeness and perfection. \
962 That is why the masters of the art of representation count above all as gifted \
963 with genius and why men of science do not. In reality, this evaluation of the \
964 former and undervaluation of the latter is only a piece of childishness in the \
968 163 The serious workman.\97 Do not talk about giftedness, inborn talents! One can\
969 name great men of all kinds who were very little gifted. The acquired \
970 greatness, became \"geniuses\" (as we put it), through qualities the lack of \
971 which no one who knew what they were would boast of: they all possessed that \
972 seriousness of the efficient workman which first learns to construct the parts \
973 properly before it ventures to fashion a great whole; they allowed themselves \
974 time for it, because they took more pleasure in making the little, secondary \
975 things well than in the effect of a dazzling whole. the recipe for becoming a \
976 good novelist, for example, is easy to give, but to carry it out presupposes \
977 qualities one is accustomed to overlook when one says \"I do not have enough \
978 talent.\" One has only to make a hundred or so sketches for novels, none longer \
980 than two pages but of such distinctness that every word in them is necessary; \
981 one should write down anecdotes each day until one has learned how to give them\
982 the most pregnant and effective form; one should be tireless in collecting and \
983 describing human types and characters; one should above all relate things to \
984 others and listen to others relate, keeping one's eyes and ears open for the \
985 effect produced on those present, one should travel like a landscape painter or\
986 costume designer; one should excerpt for oneself out of the individual sciences\
987 everything that will produce an artistic effect when it is well described, one \
988 should, finally, reflect on the motives of human actions, disdain no signpost \
989 to instruction about them and be a collector of these things by day and night. \
990 One should continue in this many-sided exercise some ten years: what is then \
991 created in the workshop, however, will be fit to go out into the world.\97 What, \
992 however, do most people do? They begin, not with the parts, but with the whole.\
993 Perhaps they chance to strike a right note, excite attention and from then on \
994 strike worse and worse notes, for good, natural reasons.\97 Sometimes, when the \
995 character and intellect needed to formulate such a life-plan are lacking, fate \
996 and need take their place and lead the future master step by step through all \
997 the stipulations of his trade. \
1000 164 Peril and profit in the cult of the genius.\97 The belief in great, superior,\
1001 fruitful spirits is not necessarily, yet nonetheless is very frequently \
1002 associated with that religious or semi-religious superstition that these \
1003 spirits are of supra-human origin and possess certain miraculous abilities by \
1004 virtue of which they acquire their knowledge by quite other means than the rest\
1006 of mankind. One ascribes to them, it seems, a direct view of the nature of the \
1007 world, as it were a hole in the cloak of appearance, and believes that, by \
1008 virtue of this miraculous seer's vision, they are able to communicate something\
1009 conclusive and decisive about man and the world without the toil and \
1010 rigorousness required by science. As long as there continue to be those who \
1011 believe in the miraculous in the domain of knowledge one can perhaps concede \
1012 that these people themselves derive some benefit from their belief, inasmuch as\
1013 through their unconditional subjection to the great spirits they create for \
1014 their own spirit during its time of development the finest form of discipline \
1015 and schooling. On the other hand, it is at least questionable whether the \
1016 superstitious belief in genius, in its privileges and special abilities, is of \
1017 benefit to the genius himself if it takes root in him. It is in any event a \
1018 dangerous sign when a man is assailed by awe of himself, whether it be the \
1019 celebrated Caesar's awe of Caesar or the awe of one's own genius now under \
1020 consideration; when the sacrificial incense which is properly rendered only to \
1021 a god penetrates the brain of the genius, so that his head begins to swim and \
1022 he comes to regard himself as something supra-human. The consequences that \
1023 slowly result are: the feeling of irresponsibility, of exceptional rights, the \
1024 belief that he confers a favor by his mere presence, insane rage when anyone \
1025 attempts even to compare him with others, let alone to rate him beneath them, \
1026 or to draw attention to lapses in his work. Because he ceases to practice \
1027 criticism of himself, at last one pinion after the other falls out of his \
1028 plumage: that superstitious eats at the roots of his powers and perhaps even \
1029 turns him into a hypocrite after his powers have fled from him. For the great \
1030 spirits themselves it is therefore probably more beneficial if they acquire an \
1032 insight into the nature and origin of their powers, if they grasp, that is to \
1033 say, what purely human qualities have come together in them and what fortunate \
1034 circumstances attended them: in the first place undiminished energy, resolute \
1035 application to individual goals, great personal courage, then the good fortune \
1036 to receive an upbringing which offered in the early years the finest teachers, \
1037 models and methods. To be sure, when their goal is the production of the \
1038 greatest possible effect, unclarity with regard to oneself and that \
1039 semi-insanity superadded to it has always achieved much; for what has been \
1040 admired and envied at all times has been that power in them by virtue of which \
1041 they render men will-less and sweep them away into the delusion that the \
1042 leaders they are following are supra-natural. Indeed, it elevates and inspires \
1043 men to believe that someone is in possession of supra-natural powers: to this \
1044 extent Plato was right to say [Plato: Phaedrus, 244a] that madness has brought \
1045 the greatest of blessings upon mankind.\97 In rare individual cases this portion \
1046 of madness may, indeed, actually have been the means by which such a nature, \
1047 excessive in all directions, was held firmly together: in the life of \
1048 individuals, too, illusions that are in themselves poisons often play the role \
1049 of healers; yet, in the end, in the case of every \"genius\" who believes in his \
1050 own divinity the poison shows itself to the same degree as his \"genius\" grows \
1051 old: one may recall, for example, the case of Napoleon, whose nature certainly \
1052 grew into the mighty unity that sets him apart from all men of modern times \
1053 precisely through his belief in himself and his star and through the contempt \
1054 for men that flowed from it; until in the end, however, this same belief went \
1055 over into an almost insane fatalism, robbed him of his acuteness and swiftness \
1056 of perception, and became the cause of his destruction. \