1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Program:     wxWidgets Widgets Sample 
   4 // Purpose:     part of the widgets sample showing wxTextCtrl 
   5 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2001 Vadim Zeitlin 
   9 // License:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // for compilers that support precompilation, includes "wx/wx.h". 
  21 #include "wx/wxprec.h" 
  27 // for all others, include the necessary headers 
  32     #include "wx/bitmap.h" 
  33     #include "wx/button.h" 
  34     #include "wx/checkbox.h" 
  35     #include "wx/radiobox.h" 
  36     #include "wx/statbox.h" 
  37     #include "wx/stattext.h" 
  38     #include "wx/textctrl.h" 
  45 #include "icons/text.xpm" 
  47 // ---------------------------------------------------------------------------- 
  49 // ---------------------------------------------------------------------------- 
  67 // textctrl line number radiobox values 
  76 // textctrl kind values 
  86 // default values for the controls 
  87 static const struct ControlValues
 
  98     TextLines_Multi
,    // multiline 
  99     false,              // not password 
 100     true,               // do wrap lines 
 101     false,              // not readonly 
 103     TextKind_Plain      
// plain EDIT control 
 107 // ---------------------------------------------------------------------------- 
 109 // ---------------------------------------------------------------------------- 
 111 // Define a new frame type: this is going to be our main frame 
 112 class TextWidgetsPage 
: public WidgetsPage
 
 116     TextWidgetsPage(wxNotebook 
*notebook
, wxImageList 
*imaglist
); 
 117     virtual ~TextWidgetsPage(); 
 120     // create an info text contorl 
 121     wxTextCtrl 
*CreateInfoText(); 
 123     // create a horz sizer holding a static text and this text control 
 124     wxSizer 
*CreateTextWithLabelSizer(const wxString
& label
, 
 126                                       const wxString
& label2 
= wxEmptyString
, 
 127                                       wxTextCtrl 
*text2 
= NULL
); 
 130     void OnButtonReset(wxCommandEvent
& event
); 
 131     void OnButtonClearLog(wxCommandEvent
& event
); 
 133     void OnButtonSet(wxCommandEvent
& event
); 
 134     void OnButtonAdd(wxCommandEvent
& event
); 
 135     void OnButtonInsert(wxCommandEvent
& event
); 
 136     void OnButtonClear(wxCommandEvent
& event
); 
 137     void OnButtonLoad(wxCommandEvent
& event
); 
 139     void OnButtonQuit(wxCommandEvent
& event
); 
 141     void OnText(wxCommandEvent
& event
); 
 142     void OnTextEnter(wxCommandEvent
& event
); 
 144     void OnCheckOrRadioBox(wxCommandEvent
& event
); 
 146     void OnUpdateUIClearButton(wxUpdateUIEvent
& event
); 
 148     void OnUpdateUIPasswordCheckbox(wxUpdateUIEvent
& event
); 
 149     void OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent
& event
); 
 151     void OnUpdateUIResetButton(wxUpdateUIEvent
& event
); 
 153     void OnIdle(wxIdleEvent
& event
); 
 155     // reset the textctrl parameters 
 158     // (re)create the textctrl 
 161     // is the control currently single line? 
 162     bool IsSingleLine() const 
 164         return m_radioTextLines
->GetSelection() == TextLines_Single
; 
 170     // the radiobox to choose between single and multi line 
 171     wxRadioBox 
*m_radioTextLines
; 
 173     // the checkboxes controlling text ctrl styles 
 174     wxCheckBox 
*m_chkPassword
, 
 178     // under MSW we test rich edit controls as well here 
 180     wxRadioBox 
*m_radioKind
; 
 183     // the textctrl itself and the sizer it is in 
 185     wxSizer 
*m_sizerText
; 
 187     // the information text zones 
 188     wxTextCtrl 
*m_textPosCur
, 
 197     // and the data to show in them 
 203     wxString m_range10_20
; 
 206     // any class wishing to process wxWidgets events must use this macro 
 207     DECLARE_EVENT_TABLE() 
 208     DECLARE_WIDGETS_PAGE(TextWidgetsPage
) 
 211 // ---------------------------------------------------------------------------- 
 213 // ---------------------------------------------------------------------------- 
 215 class WidgetsTextCtrl 
: public wxTextCtrl
 
 218     WidgetsTextCtrl(wxWindow 
*parent
, 
 220                     const wxString
& value
, 
 222         : wxTextCtrl(parent
, id
, value
, wxDefaultPosition
, wxDefaultSize
, flags
) 
 227     void OnRightClick(wxMouseEvent
& event
) 
 231         switch ( HitTest(event
.GetPosition(), &x
, &y
) ) 
 234                 wxFAIL_MSG( _T("unexpected HitTest() result") ); 
 237             case wxTE_HT_UNKNOWN
: 
 239                 where 
= _T("nowhere near"); 
 243                 where 
= _T("before"); 
 251                 where 
= _T("beyond"); 
 254             case wxTE_HT_ON_TEXT
: 
 259         wxLogMessage(_T("Mouse is %s (%ld, %ld)"), where
.c_str(), x
, y
); 
 265     DECLARE_EVENT_TABLE() 
 268 // ---------------------------------------------------------------------------- 
 270 // ---------------------------------------------------------------------------- 
 272 BEGIN_EVENT_TABLE(TextWidgetsPage
, WidgetsPage
) 
 273     EVT_IDLE(TextWidgetsPage::OnIdle
) 
 275     EVT_BUTTON(TextPage_Reset
, TextWidgetsPage::OnButtonReset
) 
 277     EVT_BUTTON(TextPage_Clear
, TextWidgetsPage::OnButtonClear
) 
 278     EVT_BUTTON(TextPage_Set
, TextWidgetsPage::OnButtonSet
) 
 279     EVT_BUTTON(TextPage_Add
, TextWidgetsPage::OnButtonAdd
) 
 280     EVT_BUTTON(TextPage_Insert
, TextWidgetsPage::OnButtonInsert
) 
 281     EVT_BUTTON(TextPage_Load
, TextWidgetsPage::OnButtonLoad
) 
 283     EVT_UPDATE_UI(TextPage_Clear
, TextWidgetsPage::OnUpdateUIClearButton
) 
 285     EVT_UPDATE_UI(TextPage_Password
, TextWidgetsPage::OnUpdateUIPasswordCheckbox
) 
 286     EVT_UPDATE_UI(TextPage_WrapLines
, TextWidgetsPage::OnUpdateUIWrapLinesCheckbox
) 
 288     EVT_UPDATE_UI(TextPage_Reset
, TextWidgetsPage::OnUpdateUIResetButton
) 
 290     EVT_TEXT(TextPage_Textctrl
, TextWidgetsPage::OnText
) 
 291     EVT_TEXT_ENTER(TextPage_Textctrl
, TextWidgetsPage::OnTextEnter
) 
 293     EVT_CHECKBOX(wxID_ANY
, TextWidgetsPage::OnCheckOrRadioBox
) 
 294     EVT_RADIOBOX(wxID_ANY
, TextWidgetsPage::OnCheckOrRadioBox
) 
 297 BEGIN_EVENT_TABLE(WidgetsTextCtrl
, wxTextCtrl
) 
 298     EVT_RIGHT_UP(WidgetsTextCtrl::OnRightClick
) 
 301 // ============================================================================ 
 303 // ============================================================================ 
 305 IMPLEMENT_WIDGETS_PAGE(TextWidgetsPage
, _T("Text")); 
 307 // ---------------------------------------------------------------------------- 
 308 // TextWidgetsPage creation 
 309 // ---------------------------------------------------------------------------- 
 311 TextWidgetsPage::TextWidgetsPage(wxNotebook 
*notebook
, wxImageList 
*imaglist
) 
 312                : WidgetsPage(notebook
) 
 314     imaglist
->Add(wxBitmap(text_xpm
)); 
 320     m_radioTextLines 
= (wxRadioBox 
*)NULL
; 
 324     m_chkReadonly 
= (wxCheckBox 
*)NULL
; 
 334     m_textRange 
= (wxTextCtrl 
*)NULL
; 
 336     m_sizerText 
= (wxSizer 
*)NULL
; 
 341     m_selTo 
= -2; // not -1 which means "no selection" 
 344     static const wxString modes
[] = 
 350     wxStaticBox 
*box 
= new wxStaticBox(this, wxID_ANY
, _T("&Set textctrl parameters")); 
 351     m_radioTextLines 
= new wxRadioBox(this, wxID_ANY
, _T("&Number of lines:"), 
 352                                       wxDefaultPosition
, wxDefaultSize
, 
 353                                       WXSIZEOF(modes
), modes
, 
 354                                       1, wxRA_SPECIFY_COLS
); 
 356     wxSizer 
*sizerLeft 
= new wxStaticBoxSizer(box
, wxVERTICAL
); 
 358     sizerLeft
->Add(m_radioTextLines
, 0, wxGROW 
| wxALL
, 5); 
 359     sizerLeft
->Add(5, 5, 0, wxGROW 
| wxALL
, 5); // spacer 
 361     m_chkPassword 
= CreateCheckBoxAndAddToSizer( 
 362                         sizerLeft
, _T("&Password control"), TextPage_Password
 
 364     m_chkWrapLines 
= CreateCheckBoxAndAddToSizer( 
 365                         sizerLeft
, _T("Line &wrap"), TextPage_WrapLines
 
 367     m_chkReadonly 
= CreateCheckBoxAndAddToSizer( 
 368                         sizerLeft
, _T("&Read-only mode") 
 372     static const wxString kinds
[] = 
 379     m_radioKind 
= new wxRadioBox(this, wxID_ANY
, _T("Control &kind"), 
 380                                  wxDefaultPosition
, wxDefaultSize
, 
 381                                  WXSIZEOF(kinds
), kinds
, 
 382                                  1, wxRA_SPECIFY_COLS
); 
 384     sizerLeft
->Add(5, 5, 0, wxGROW 
| wxALL
, 5); // spacer 
 385     sizerLeft
->Add(m_radioKind
, 0, wxGROW 
| wxALL
, 5); 
 388     wxButton 
*btn 
= new wxButton(this, TextPage_Reset
, _T("&Reset")); 
 389     sizerLeft
->Add(2, 2, 0, wxGROW 
| wxALL
, 1); // spacer 
 390     sizerLeft
->Add(btn
, 0, wxALIGN_CENTRE_HORIZONTAL 
| wxALL
, 15); 
 393     wxStaticBox 
*box2 
= new wxStaticBox(this, wxID_ANY
, _T("&Change contents:")); 
 394     wxSizer 
*sizerMiddleUp 
= new wxStaticBoxSizer(box2
, wxVERTICAL
); 
 396     btn 
= new wxButton(this, TextPage_Set
, _T("&Set text value")); 
 397     sizerMiddleUp
->Add(btn
, 0, wxALL 
| wxGROW
, 1); 
 399     btn 
= new wxButton(this, TextPage_Add
, _T("&Append text")); 
 400     sizerMiddleUp
->Add(btn
, 0, wxALL 
| wxGROW
, 1); 
 402     btn 
= new wxButton(this, TextPage_Insert
, _T("&Insert text")); 
 403     sizerMiddleUp
->Add(btn
, 0, wxALL 
| wxGROW
, 1); 
 405     btn 
= new wxButton(this, TextPage_Load
, _T("&Load file")); 
 406     sizerMiddleUp
->Add(btn
, 0, wxALL 
| wxGROW
, 1); 
 408     btn 
= new wxButton(this, TextPage_Clear
, _T("&Clear")); 
 409     sizerMiddleUp
->Add(btn
, 0, wxALL 
| wxGROW
, 1); 
 411     wxStaticBox 
*box4 
= new wxStaticBox(this, wxID_ANY
, _T("&Info:")); 
 412     wxSizer 
*sizerMiddleDown 
= new wxStaticBoxSizer(box4
, wxVERTICAL
); 
 414     m_textPosCur 
= CreateInfoText(); 
 415     m_textRowCur 
= CreateInfoText(); 
 416     m_textColCur 
= CreateInfoText(); 
 418     wxSizer 
*sizerRow 
= new wxBoxSizer(wxHORIZONTAL
); 
 419     sizerRow
->Add(CreateTextWithLabelSizer
 
 425     sizerRow
->Add(CreateTextWithLabelSizer
 
 430                   0, wxLEFT 
| wxRIGHT
, 5); 
 431     sizerRow
->Add(CreateTextWithLabelSizer
 
 437     sizerMiddleDown
->Add(sizerRow
, 0, wxALL
, 5); 
 439     m_textLineLast 
= CreateInfoText(); 
 440     m_textPosLast 
= CreateInfoText(); 
 443                         CreateTextWithLabelSizer
 
 445                           _T("Number of lines:"), 
 447                           _T("Last position:"), 
 453     m_textSelFrom 
= CreateInfoText(); 
 454     m_textSelTo 
= CreateInfoText(); 
 457                         CreateTextWithLabelSizer
 
 459                           _T("Selection: from"), 
 467     m_textRange 
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
, 
 468                                  wxDefaultPosition
, wxDefaultSize
, 
 472                         CreateTextWithLabelSizer
 
 480     wxSizer 
*sizerMiddle 
= new wxBoxSizer(wxVERTICAL
); 
 481     sizerMiddle
->Add(sizerMiddleUp
, 0, wxGROW
); 
 482     sizerMiddle
->Add(sizerMiddleDown
, 1, wxGROW 
| wxTOP
, 5); 
 485     wxStaticBox 
*box3 
= new wxStaticBox(this, wxID_ANY
, _T("&Text:")); 
 486     m_sizerText 
= new wxStaticBoxSizer(box3
, wxHORIZONTAL
); 
 489     m_sizerText
->SetMinSize(150, 0); 
 491     // the 3 panes panes compose the upper part of the window 
 492     wxSizer 
*sizerTop 
= new wxBoxSizer(wxHORIZONTAL
); 
 493     sizerTop
->Add(sizerLeft
, 0, wxGROW 
| (wxALL 
& ~wxLEFT
), 10); 
 494     sizerTop
->Add(sizerMiddle
, 0, wxGROW 
| wxALL
, 10); 
 495     sizerTop
->Add(m_sizerText
, 1, wxGROW 
| (wxALL 
& ~wxRIGHT
), 10); 
 502 TextWidgetsPage::~TextWidgetsPage() 
 506 // ---------------------------------------------------------------------------- 
 508 // ---------------------------------------------------------------------------- 
 510 wxTextCtrl 
*TextWidgetsPage::CreateInfoText() 
 512     static int s_maxWidth 
= 0; 
 516         GetTextExtent(_T("9999999"), &s_maxWidth
, NULL
); 
 519     wxTextCtrl 
*text 
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
, 
 521                                       wxSize(s_maxWidth
, -1), 
 526 wxSizer 
*TextWidgetsPage::CreateTextWithLabelSizer(const wxString
& label
, 
 528                                                  const wxString
& label2
, 
 531     wxSizer 
*sizerRow 
= new wxBoxSizer(wxHORIZONTAL
); 
 532     sizerRow
->Add(new wxStaticText(this, wxID_ANY
, label
), 0, 
 533                   wxALIGN_CENTRE_VERTICAL 
| wxRIGHT
, 5); 
 534     sizerRow
->Add(text
, 0, wxALIGN_CENTRE_VERTICAL
); 
 537         sizerRow
->Add(new wxStaticText(this, wxID_ANY
, label2
), 0, 
 538                       wxALIGN_CENTRE_VERTICAL 
| wxLEFT 
| wxRIGHT
, 5); 
 539         sizerRow
->Add(text2
, 0, wxALIGN_CENTRE_VERTICAL
); 
 545 // ---------------------------------------------------------------------------- 
 547 // ---------------------------------------------------------------------------- 
 549 void TextWidgetsPage::Reset() 
 551     m_radioTextLines
->SetSelection(DEFAULTS
.textLines
); 
 552     m_chkPassword
->SetValue(DEFAULTS
.password
); 
 553     m_chkWrapLines
->SetValue(DEFAULTS
.wraplines
); 
 554     m_chkReadonly
->SetValue(DEFAULTS
.readonly
); 
 556     m_radioKind
->SetSelection(DEFAULTS
.textKind
); 
 560 void TextWidgetsPage::CreateText() 
 563     switch ( m_radioTextLines
->GetSelection() ) 
 566             wxFAIL_MSG( _T("unexpected lines radio box selection") ); 
 568         case TextLines_Single
: 
 571         case TextLines_Multi
: 
 572             flags 
|= wxTE_MULTILINE
; 
 573             m_chkPassword
->SetValue(false); 
 577     if ( m_chkPassword
->GetValue() ) 
 578         flags 
|= wxTE_PASSWORD
; 
 579     if ( m_chkReadonly
->GetValue() ) 
 580         flags 
|= wxTE_READONLY
; 
 581     if ( !m_chkWrapLines
->GetValue() ) 
 585     switch ( m_radioKind
->GetSelection() ) 
 588             wxFAIL_MSG( _T("unexpected kind radio box selection") ); 
 606         valueOld 
= m_text
->GetValue(); 
 608         m_sizerText
->Detach( m_text 
); 
 613         valueOld 
= _T("Hello, Universe!"); 
 616     m_text 
= new WidgetsTextCtrl(this, TextPage_Textctrl
, valueOld
, flags
); 
 618     // cast to int needed to silence gcc warning about different enums 
 619     m_sizerText
->Add(m_text
, 1, wxALL 
| 
 620                      (flags 
& wxTE_MULTILINE 
? (int)wxGROW
 
 622     m_sizerText
->Layout(); 
 625 // ---------------------------------------------------------------------------- 
 627 // ---------------------------------------------------------------------------- 
 629 void TextWidgetsPage::OnIdle(wxIdleEvent
& WXUNUSED(event
)) 
 631     // update all info texts 
 635         long posCur 
= m_text
->GetInsertionPoint(); 
 636         if ( posCur 
!= m_posCur 
) 
 638             m_textPosCur
->Clear(); 
 639             m_textRowCur
->Clear(); 
 640             m_textColCur
->Clear(); 
 643             m_text
->PositionToXY(posCur
, &col
, &row
); 
 645             *m_textPosCur 
<< posCur
; 
 646             *m_textRowCur 
<< row
; 
 647             *m_textColCur 
<< col
; 
 655         long posLast 
= m_text
->GetLastPosition(); 
 656         if ( posLast 
!= m_posLast 
) 
 658             m_textPosLast
->Clear(); 
 659             *m_textPosLast 
<< posLast
; 
 665     if ( m_textLineLast 
) 
 667         m_textLineLast
->SetValue( 
 668                 wxString::Format(_T("%d"), m_text
->GetNumberOfLines()) ); 
 671     if ( m_textSelFrom 
&& m_textSelTo 
) 
 674         m_text
->GetSelection(&selFrom
, &selTo
); 
 675         if ( selFrom 
!= m_selFrom 
) 
 677             m_textSelFrom
->Clear(); 
 678             *m_textSelFrom 
<< selFrom
; 
 683         if ( selTo 
!= m_selTo 
) 
 685             m_textSelTo
->Clear(); 
 686             *m_textSelTo 
<< selTo
; 
 694         wxString range 
= m_text
->GetRange(10, 20); 
 695         if ( range 
!= m_range10_20 
) 
 697             m_range10_20 
= range
; 
 698             m_textRange
->SetValue(range
); 
 703 void TextWidgetsPage::OnButtonReset(wxCommandEvent
& WXUNUSED(event
)) 
 710 void TextWidgetsPage::OnButtonSet(wxCommandEvent
& WXUNUSED(event
)) 
 712     m_text
->SetValue(m_text
->GetWindowStyle() & wxTE_MULTILINE
 
 713                         ? _T("Here,\nthere and\neverywhere") 
 714                         : _T("Yellow submarine")); 
 719 void TextWidgetsPage::OnButtonAdd(wxCommandEvent
& WXUNUSED(event
)) 
 721     if ( m_text
->GetWindowStyle() & wxTE_MULTILINE 
) 
 723         m_text
->AppendText(_T("We all live in a\n")); 
 726     m_text
->AppendText(_T("Yellow submarine")); 
 729 void TextWidgetsPage::OnButtonInsert(wxCommandEvent
& WXUNUSED(event
)) 
 731     m_text
->WriteText(_T("Is there anybody going to listen to my story")); 
 732     if ( m_text
->GetWindowStyle() & wxTE_MULTILINE 
) 
 734         m_text
->WriteText(_T("\nall about the girl who came to stay")); 
 738 void TextWidgetsPage::OnButtonClear(wxCommandEvent
& WXUNUSED(event
)) 
 744 void TextWidgetsPage::OnButtonLoad(wxCommandEvent
& WXUNUSED(event
)) 
 746     // search for the file in several dirs where it's likely to be 
 748     pathlist
.Add(_T(".")); 
 749     pathlist
.Add(_T("..")); 
 750     pathlist
.Add(_T("../../../samples/widgets")); 
 752     wxString filename 
= pathlist
.FindValidPath(_T("textctrl.cpp")); 
 755         wxLogError(_T("File textctrl.cpp not found.")); 
 760         if ( !m_text
->LoadFile(filename
) ) 
 762             // this is not supposed to happen ... 
 763             wxLogError(_T("Error loading file.")); 
 767             long elapsed 
= sw
.Time(); 
 768             wxLogMessage(_T("Loaded file '%s' in %lu.%us"), 
 769                          filename
.c_str(), elapsed 
/ 1000, 
 770                          (unsigned int) elapsed 
% 1000); 
 775 void TextWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent
& event
) 
 777     event
.Enable(!m_text
->GetValue().empty()); 
 780 void TextWidgetsPage::OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent
& event
) 
 782     event
.Enable( !IsSingleLine() ); 
 785 void TextWidgetsPage::OnUpdateUIPasswordCheckbox(wxUpdateUIEvent
& event
) 
 787     // can't put multiline control in password mode 
 788     event
.Enable( IsSingleLine() ); 
 791 void TextWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent
& event
) 
 793     event
.Enable( (m_radioTextLines
->GetSelection() != DEFAULTS
.textLines
) || 
 795                   (m_radioKind
->GetSelection() != DEFAULTS
.textKind
) || 
 797                   (m_chkReadonly
->GetValue() != DEFAULTS
.readonly
) || 
 798                   (m_chkPassword
->GetValue() != DEFAULTS
.password
) || 
 799                   (m_chkWrapLines
->GetValue() != DEFAULTS
.wraplines
) ); 
 802 void TextWidgetsPage::OnText(wxCommandEvent
& WXUNUSED(event
)) 
 804     // small hack to suppress the very first message: by then the logging is 
 805     // not yet redirected and so initial setting of the text value results in 
 806     // an annoying message box 
 807     static bool s_firstTime 
= true; 
 814     wxLogMessage(_T("Text ctrl value changed")); 
 817 void TextWidgetsPage::OnTextEnter(wxCommandEvent
& event
) 
 819     wxLogMessage(_T("Text entered: '%s'"), event
.GetString().c_str()); 
 822 void TextWidgetsPage::OnCheckOrRadioBox(wxCommandEvent
& WXUNUSED(event
))