1 /////////////////////////////////////////////////////////////////////////////
2 // Program:     wxWidgets Widgets Sample
3 // Name:        textctrl.cpp
4 // Purpose:     part of the widgets sample showing wxTextCtrl
5 // Author:      Vadim Zeitlin
6 // Created:     27.03.01
7 // Id:          $Id: textctrl.cpp 43755 2006-12-03 13:43:44Z VZ $
8 // Copyright:   (c) 2001 Vadim Zeitlin
9 // License:     wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // ============================================================================
13 // declarations
14 // ============================================================================
15 
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19 
20 // for compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22 
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26 
27 // for all others, include the necessary headers
28 #ifndef WX_PRECOMP
29     #include "wx/log.h"
30     #include "wx/timer.h"
31 
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"
39     #include "wx/msgdlg.h"
40 #endif
41 
42 #include "wx/sizer.h"
43 #include "wx/ioswrap.h"
44 
45 #include "widgets.h"
46 
47 #include "icons/text.xpm"
48 
49 // ----------------------------------------------------------------------------
50 // constants
51 // ----------------------------------------------------------------------------
52 
53 // control ids
54 enum
55 {
56     TextPage_Reset = wxID_HIGHEST,
57 
58     TextPage_Set,
59     TextPage_Add,
60     TextPage_Insert,
61     TextPage_Clear,
62     TextPage_Load,
63 
64     TextPage_StreamRedirector,
65 
66     TextPage_Password,
67     TextPage_WrapLines,
68     TextPage_Textctrl
69 };
70 
71 // textctrl line number radiobox values
72 enum TextLines
73 {
74     TextLines_Single,
75     TextLines_Multi,
76     TextLines_Max
77 };
78 
79 // wrap style radio box
80 enum WrapStyle
81 {
82     WrapStyle_None,
83     WrapStyle_Word,
84     WrapStyle_Char,
85     WrapStyle_Best,
86     WrapStyle_Max
87 };
88 
89 #ifdef __WXMSW__
90 
91 // textctrl kind values
92 enum TextKind
93 {
94     TextKind_Plain,
95     TextKind_Rich,
96     TextKind_Rich2,
97     TextKind_Max
98 };
99 
100 #endif // __WXMSW__
101 
102 // default values for the controls
103 static const struct ControlValues
104 {
105     TextLines textLines;
106 
107     bool password;
108     bool readonly;
109     bool filename;
110 
111     WrapStyle wrapStyle;
112 
113 #ifdef __WXMSW__
114     TextKind textKind;
115 #endif // __WXMSW__
116 } DEFAULTS =
117 {
118     TextLines_Multi,    // multiline
119     false,              // not password
120     false,              // not readonly
121     false,              // not filename
122     WrapStyle_Word,     // wrap on word boundaries
123 #ifdef __WXMSW__
124     TextKind_Plain      // plain EDIT control
125 #endif // __WXMSW__
126 };
127 
128 // ----------------------------------------------------------------------------
129 // TextWidgetsPage
130 // ----------------------------------------------------------------------------
131 
132 // Define a new frame type: this is going to be our main frame
133 class TextWidgetsPage : public WidgetsPage
134 {
135 public:
136     // ctor(s) and dtor
137     TextWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist);
~TextWidgetsPage()138     virtual ~TextWidgetsPage(){};
139 
GetWidget() const140     virtual wxControl *GetWidget() const { return m_text; }
RecreateWidget()141     virtual void RecreateWidget() { CreateText(); }
142 
143     // lazy creation of the content
144     virtual void CreateContent();
145 
146 protected:
147     // create an info text contorl
148     wxTextCtrl *CreateInfoText();
149 
150     // create a horz sizer holding a static text and this text control
151     wxSizer *CreateTextWithLabelSizer(const wxString& label,
152                                       wxTextCtrl *text,
153                                       const wxString& label2 = wxEmptyString,
154                                       wxTextCtrl *text2 = NULL);
155 
156     // event handlers
157     void OnButtonReset(wxCommandEvent& event);
158     void OnButtonClearLog(wxCommandEvent& event);
159 
160     void OnButtonSet(wxCommandEvent& event);
161     void OnButtonAdd(wxCommandEvent& event);
162     void OnButtonInsert(wxCommandEvent& event);
163     void OnButtonClear(wxCommandEvent& event);
164     void OnButtonLoad(wxCommandEvent& event);
165 
166     void OnStreamRedirector(wxCommandEvent& event);
167     void OnButtonQuit(wxCommandEvent& event);
168 
169     void OnText(wxCommandEvent& event);
170     void OnTextEnter(wxCommandEvent& event);
171 
172     void OnCheckOrRadioBox(wxCommandEvent& event);
173 
174     void OnUpdateUIClearButton(wxUpdateUIEvent& event);
175 
176     void OnUpdateUIPasswordCheckbox(wxUpdateUIEvent& event);
177     void OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent& event);
178 
179     void OnUpdateUIResetButton(wxUpdateUIEvent& event);
180 
181     void OnIdle(wxIdleEvent& event);
182 
183     // reset the textctrl parameters
184     void Reset();
185 
186     // (re)create the textctrl
187     void CreateText();
188 
189     // is the control currently single line?
IsSingleLine() const190     bool IsSingleLine() const
191     {
192         return m_radioTextLines->GetSelection() == TextLines_Single;
193     }
194 
195     // the controls
196     // ------------
197 
198     // the radiobox to choose between single and multi line
199     wxRadioBox *m_radioTextLines;
200 
201     // and another one to choose the wrapping style
202     wxRadioBox *m_radioWrap;
203 
204     // the checkboxes controlling text ctrl styles
205     wxCheckBox *m_chkPassword,
206                *m_chkReadonly,
207                *m_chkFilename;
208 
209     // under MSW we test rich edit controls as well here
210 #ifdef __WXMSW__
211     wxRadioBox *m_radioKind;
212 #endif // __WXMSW__
213 
214     // the textctrl itself and the sizer it is in
215     wxTextCtrl *m_text;
216     wxSizer *m_sizerText;
217 
218     // the information text zones
219     wxTextCtrl *m_textPosCur,
220                *m_textRowCur,
221                *m_textColCur,
222                *m_textPosLast,
223                *m_textLineLast,
224                *m_textSelFrom,
225                *m_textSelTo,
226                *m_textRange;
227 
228     // and the data to show in them
229     long m_posCur,
230          m_posLast,
231          m_selFrom,
232          m_selTo;
233 
234     wxString m_range10_20;
235 
236 private:
237     // any class wishing to process wxWidgets events must use this macro
238     DECLARE_EVENT_TABLE()
239     DECLARE_WIDGETS_PAGE(TextWidgetsPage)
240 };
241 
242 // ----------------------------------------------------------------------------
243 // WidgetsTextCtrl
244 // ----------------------------------------------------------------------------
245 
246 class WidgetsTextCtrl : public wxTextCtrl
247 {
248 public:
WidgetsTextCtrl(wxWindow * parent,wxWindowID id,const wxString & value,int flags)249     WidgetsTextCtrl(wxWindow *parent,
250                     wxWindowID id,
251                     const wxString& value,
252                     int flags)
253         : wxTextCtrl(parent, id, value, wxDefaultPosition, wxDefaultSize, flags)
254     {
255     }
256 
257 protected:
OnRightClick(wxMouseEvent & event)258     void OnRightClick(wxMouseEvent& event)
259     {
260         wxString where;
261         wxTextCoord x, y;
262         switch ( HitTest(event.GetPosition(), &x, &y) )
263         {
264             default:
265                 wxFAIL_MSG( _T("unexpected HitTest() result") );
266                 // fall through
267 
268             case wxTE_HT_UNKNOWN:
269                 x = y = -1;
270                 where = _T("nowhere near");
271                 break;
272 
273             case wxTE_HT_BEFORE:
274                 where = _T("before");
275                 break;
276 
277             case wxTE_HT_BELOW:
278                 where = _T("below");
279                 break;
280 
281             case wxTE_HT_BEYOND:
282                 where = _T("beyond");
283                 break;
284 
285             case wxTE_HT_ON_TEXT:
286                 where = _T("at");
287                 break;
288         }
289 
290         wxLogMessage(_T("Mouse is %s (%ld, %ld)"), where.c_str(), x, y);
291 
292         event.Skip();
293     }
294 
295 private:
296     DECLARE_EVENT_TABLE()
297 };
298 
299 // ----------------------------------------------------------------------------
300 // event tables
301 // ----------------------------------------------------------------------------
302 
303 BEGIN_EVENT_TABLE(TextWidgetsPage, WidgetsPage)
304     EVT_IDLE(TextWidgetsPage::OnIdle)
305 
306     EVT_BUTTON(TextPage_Reset, TextWidgetsPage::OnButtonReset)
307 
308     EVT_BUTTON(TextPage_StreamRedirector, TextWidgetsPage::OnStreamRedirector)
309 
310     EVT_BUTTON(TextPage_Clear, TextWidgetsPage::OnButtonClear)
311     EVT_BUTTON(TextPage_Set, TextWidgetsPage::OnButtonSet)
312     EVT_BUTTON(TextPage_Add, TextWidgetsPage::OnButtonAdd)
313     EVT_BUTTON(TextPage_Insert, TextWidgetsPage::OnButtonInsert)
314     EVT_BUTTON(TextPage_Load, TextWidgetsPage::OnButtonLoad)
315 
316     EVT_UPDATE_UI(TextPage_Clear, TextWidgetsPage::OnUpdateUIClearButton)
317 
318     EVT_UPDATE_UI(TextPage_Password, TextWidgetsPage::OnUpdateUIPasswordCheckbox)
319     EVT_UPDATE_UI(TextPage_WrapLines, TextWidgetsPage::OnUpdateUIWrapLinesCheckbox)
320 
321     EVT_UPDATE_UI(TextPage_Reset, TextWidgetsPage::OnUpdateUIResetButton)
322 
323     EVT_TEXT(TextPage_Textctrl, TextWidgetsPage::OnText)
324     EVT_TEXT_ENTER(TextPage_Textctrl, TextWidgetsPage::OnTextEnter)
325 
326     EVT_CHECKBOX(wxID_ANY, TextWidgetsPage::OnCheckOrRadioBox)
327     EVT_RADIOBOX(wxID_ANY, TextWidgetsPage::OnCheckOrRadioBox)
328 END_EVENT_TABLE()
329 
330 BEGIN_EVENT_TABLE(WidgetsTextCtrl, wxTextCtrl)
331     EVT_RIGHT_UP(WidgetsTextCtrl::OnRightClick)
332 END_EVENT_TABLE()
333 
334 // ============================================================================
335 // implementation
336 // ============================================================================
337 
338 #if defined(__WXX11__)
339     #define FAMILY_CTRLS NATIVE_CTRLS
340 #elif defined(__WXUNIVERSAL__)
341     #define FAMILY_CTRLS UNIVERSAL_CTRLS
342 #else
343     #define FAMILY_CTRLS NATIVE_CTRLS
344 #endif
345 
346 IMPLEMENT_WIDGETS_PAGE(TextWidgetsPage, _T("Text"),
347                        FAMILY_CTRLS | EDITABLE_CTRLS
348                        );
349 
350 // ----------------------------------------------------------------------------
351 // TextWidgetsPage creation
352 // ----------------------------------------------------------------------------
353 
TextWidgetsPage(WidgetsBookCtrl * book,wxImageList * imaglist)354 TextWidgetsPage::TextWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist)
355                : WidgetsPage(book, imaglist, text_xpm)
356 {
357     // init everything
358 #ifdef __WXMSW__
359     m_radioKind =
360 #endif // __WXMSW__
361     m_radioWrap =
362     m_radioTextLines = (wxRadioBox *)NULL;
363 
364     m_chkPassword =
365     m_chkReadonly =
366     m_chkFilename = (wxCheckBox *)NULL;
367 
368     m_text =
369     m_textPosCur =
370     m_textRowCur =
371     m_textColCur =
372     m_textPosLast =
373     m_textLineLast =
374     m_textSelFrom =
375     m_textSelTo =
376     m_textRange = (wxTextCtrl *)NULL;
377 
378     m_sizerText = (wxSizer *)NULL;
379 
380     m_posCur =
381     m_posLast =
382     m_selFrom =
383     m_selTo = -2; // not -1 which means "no selection"
384 }
385 
CreateContent()386 void TextWidgetsPage::CreateContent()
387 {
388     // left pane
389     static const wxString modes[] =
390     {
391         _T("single line"),
392         _T("multi line"),
393     };
394 
395     wxStaticBox *box = new wxStaticBox(this, wxID_ANY, _T("&Set textctrl parameters"));
396     m_radioTextLines = new wxRadioBox(this, wxID_ANY, _T("&Number of lines:"),
397                                       wxDefaultPosition, wxDefaultSize,
398                                       WXSIZEOF(modes), modes,
399                                       1, wxRA_SPECIFY_COLS);
400 
401     wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
402 
403     sizerLeft->Add(m_radioTextLines, 0, wxGROW | wxALL, 5);
404     sizerLeft->AddSpacer(5);
405 
406     m_chkPassword = CreateCheckBoxAndAddToSizer(
407                         sizerLeft, _T("&Password control"), TextPage_Password
408                     );
409     m_chkReadonly = CreateCheckBoxAndAddToSizer(
410                         sizerLeft, _T("&Read-only mode")
411                     );
412     m_chkFilename = CreateCheckBoxAndAddToSizer(
413                         sizerLeft, _T("&Filename control")
414                     );
415     m_chkFilename->Disable(); // not implemented yet
416     sizerLeft->AddSpacer(5);
417 
418     static const wxString wrap[] =
419     {
420         _T("no wrap"),
421         _T("word wrap"),
422         _T("char wrap"),
423         _T("best wrap"),
424     };
425 
426     m_radioWrap = new wxRadioBox(this, wxID_ANY, _T("&Wrap style:"),
427                                  wxDefaultPosition, wxDefaultSize,
428                                  WXSIZEOF(wrap), wrap,
429                                  1, wxRA_SPECIFY_COLS);
430     sizerLeft->Add(m_radioWrap, 0, wxGROW | wxALL, 5);
431 
432 #ifdef __WXMSW__
433     static const wxString kinds[] =
434     {
435         _T("plain edit"),
436         _T("rich edit"),
437         _T("rich edit 2.0"),
438     };
439 
440     m_radioKind = new wxRadioBox(this, wxID_ANY, _T("Control &kind"),
441                                  wxDefaultPosition, wxDefaultSize,
442                                  WXSIZEOF(kinds), kinds,
443                                  1, wxRA_SPECIFY_COLS);
444 
445     sizerLeft->AddSpacer(5);
446     sizerLeft->Add(m_radioKind, 0, wxGROW | wxALL, 5);
447 #endif // __WXMSW__
448 
449     wxButton *btn = new wxButton(this, TextPage_Reset, _T("&Reset"));
450     sizerLeft->Add(2, 2, 0, wxGROW | wxALL, 1); // spacer
451     sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
452 
453     // middle pane
454     wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, _T("&Change contents:"));
455     wxSizer *sizerMiddleUp = new wxStaticBoxSizer(box2, wxVERTICAL);
456 
457     btn = new wxButton(this, TextPage_Set, _T("&Set text value"));
458     sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 1);
459 
460     btn = new wxButton(this, TextPage_Add, _T("&Append text"));
461     sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 1);
462 
463     btn = new wxButton(this, TextPage_Insert, _T("&Insert text"));
464     sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 1);
465 
466     btn = new wxButton(this, TextPage_Load, _T("&Load file"));
467     sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 1);
468 
469     btn = new wxButton(this, TextPage_Clear, _T("&Clear"));
470     sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 1);
471 
472     btn = new wxButton(this, TextPage_StreamRedirector, _T("St&ream redirection"));
473     sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 1);
474 
475     wxStaticBox *box4 = new wxStaticBox(this, wxID_ANY, _T("&Info:"));
476     wxSizer *sizerMiddleDown = new wxStaticBoxSizer(box4, wxVERTICAL);
477 
478     m_textPosCur = CreateInfoText();
479     m_textRowCur = CreateInfoText();
480     m_textColCur = CreateInfoText();
481 
482     wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
483     sizerRow->Add(CreateTextWithLabelSizer
484                   (
485                     _T("Current pos:"),
486                     m_textPosCur
487                   ),
488                   0, wxRIGHT, 5);
489     sizerRow->Add(CreateTextWithLabelSizer
490                   (
491                     _T("Col:"),
492                     m_textColCur
493                   ),
494                   0, wxLEFT | wxRIGHT, 5);
495     sizerRow->Add(CreateTextWithLabelSizer
496                   (
497                     _T("Row:"),
498                     m_textRowCur
499                   ),
500                   0, wxLEFT, 5);
501     sizerMiddleDown->Add(sizerRow, 0, wxALL, 5);
502 
503     m_textLineLast = CreateInfoText();
504     m_textPosLast = CreateInfoText();
505     sizerMiddleDown->Add
506                      (
507                         CreateTextWithLabelSizer
508                         (
509                           _T("Number of lines:"),
510                           m_textLineLast,
511                           _T("Last position:"),
512                           m_textPosLast
513                         ),
514                         0, wxALL, 5
515                      );
516 
517     m_textSelFrom = CreateInfoText();
518     m_textSelTo = CreateInfoText();
519     sizerMiddleDown->Add
520                      (
521                         CreateTextWithLabelSizer
522                         (
523                           _T("Selection: from"),
524                           m_textSelFrom,
525                           _T("to"),
526                           m_textSelTo
527                         ),
528                         0, wxALL, 5
529                      );
530 
531     m_textRange = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
532                                  wxDefaultPosition, wxDefaultSize,
533                                  wxTE_READONLY);
534     sizerMiddleDown->Add
535                      (
536                         CreateTextWithLabelSizer
537                         (
538                           _T("Range 10..20:"),
539                           m_textRange
540                         ),
541                         0, wxALL, 5
542                      );
543 
544     wxSizer *sizerMiddle = new wxBoxSizer(wxVERTICAL);
545     sizerMiddle->Add(sizerMiddleUp, 0, wxGROW);
546     sizerMiddle->Add(sizerMiddleDown, 1, wxGROW | wxTOP, 5);
547 
548     // right pane
549     wxStaticBox *box3 = new wxStaticBox(this, wxID_ANY, _T("&Text:"));
550     m_sizerText = new wxStaticBoxSizer(box3, wxHORIZONTAL);
551     Reset();
552     CreateText();
553     m_sizerText->SetMinSize(150, 0);
554 
555     // the 3 panes panes compose the upper part of the window
556     wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
557     sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
558     sizerTop->Add(sizerMiddle, 0, wxGROW | wxALL, 10);
559     sizerTop->Add(m_sizerText, 1, wxGROW | (wxALL & ~wxRIGHT), 10);
560 
561     SetSizer(sizerTop);
562 }
563 
564 // ----------------------------------------------------------------------------
565 // creation helpers
566 // ----------------------------------------------------------------------------
567 
CreateInfoText()568 wxTextCtrl *TextWidgetsPage::CreateInfoText()
569 {
570     static int s_maxWidth = 0;
571     if ( !s_maxWidth )
572     {
573         // calc it once only
574         GetTextExtent(_T("9999999"), &s_maxWidth, NULL);
575     }
576 
577     wxTextCtrl *text = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
578                                       wxDefaultPosition,
579                                       wxSize(s_maxWidth, wxDefaultCoord),
580                                       wxTE_READONLY);
581     return text;
582 }
583 
CreateTextWithLabelSizer(const wxString & label,wxTextCtrl * text,const wxString & label2,wxTextCtrl * text2)584 wxSizer *TextWidgetsPage::CreateTextWithLabelSizer(const wxString& label,
585                                                  wxTextCtrl *text,
586                                                  const wxString& label2,
587                                                  wxTextCtrl *text2)
588 {
589     wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
590     sizerRow->Add(new wxStaticText(this, wxID_ANY, label), 0,
591                   wxALIGN_CENTRE_VERTICAL | wxRIGHT, 5);
592     sizerRow->Add(text, 0, wxALIGN_CENTRE_VERTICAL);
593     if ( text2 )
594     {
595         sizerRow->Add(new wxStaticText(this, wxID_ANY, label2), 0,
596                       wxALIGN_CENTRE_VERTICAL | wxLEFT | wxRIGHT, 5);
597         sizerRow->Add(text2, 0, wxALIGN_CENTRE_VERTICAL);
598     }
599 
600     return sizerRow;
601 }
602 
603 // ----------------------------------------------------------------------------
604 // operations
605 // ----------------------------------------------------------------------------
606 
Reset()607 void TextWidgetsPage::Reset()
608 {
609     m_radioTextLines->SetSelection(DEFAULTS.textLines);
610 
611     m_chkPassword->SetValue(DEFAULTS.password);
612     m_chkReadonly->SetValue(DEFAULTS.readonly);
613     m_chkFilename->SetValue(DEFAULTS.filename);
614 
615     m_radioWrap->SetSelection(DEFAULTS.wrapStyle);
616 
617 #ifdef __WXMSW__
618     m_radioKind->SetSelection(DEFAULTS.textKind);
619 #endif // __WXMSW__
620 }
621 
CreateText()622 void TextWidgetsPage::CreateText()
623 {
624     int flags = ms_defaultFlags;
625     switch ( m_radioTextLines->GetSelection() )
626     {
627         default:
628             wxFAIL_MSG( _T("unexpected lines radio box selection") );
629 
630         case TextLines_Single:
631             break;
632 
633         case TextLines_Multi:
634             flags |= wxTE_MULTILINE;
635             m_chkPassword->SetValue(false);
636             break;
637     }
638 
639     if ( m_chkPassword->GetValue() )
640         flags |= wxTE_PASSWORD;
641     if ( m_chkReadonly->GetValue() )
642         flags |= wxTE_READONLY;
643 
644     switch ( m_radioWrap->GetSelection() )
645     {
646         default:
647             wxFAIL_MSG( _T("unexpected wrap style radio box selection") );
648 
649         case WrapStyle_None:
650             flags |= wxTE_DONTWRAP; // same as wxHSCROLL
651             break;
652 
653         case WrapStyle_Word:
654             flags |= wxTE_WORDWRAP;
655             break;
656 
657         case WrapStyle_Char:
658             flags |= wxTE_CHARWRAP;
659             break;
660 
661         case WrapStyle_Best:
662             // this is default but use symbolic file name for consistency
663             flags |= wxTE_BESTWRAP;
664             break;
665     }
666 
667 #ifdef __WXMSW__
668     switch ( m_radioKind->GetSelection() )
669     {
670         default:
671             wxFAIL_MSG( _T("unexpected kind radio box selection") );
672 
673         case TextKind_Plain:
674             break;
675 
676         case TextKind_Rich:
677             flags |= wxTE_RICH;
678             break;
679 
680         case TextKind_Rich2:
681             flags |= wxTE_RICH2;
682             break;
683     }
684 #endif // __WXMSW__
685 
686     wxString valueOld;
687     if ( m_text )
688     {
689         valueOld = m_text->GetValue();
690 
691         m_sizerText->Detach( m_text );
692         delete m_text;
693     }
694     else
695     {
696         valueOld = _T("Hello, Universe!");
697     }
698 
699     m_text = new WidgetsTextCtrl(this, TextPage_Textctrl, valueOld, flags);
700 
701 #if 0
702     if ( m_chkFilename->GetValue() )
703         ;
704 #endif // TODO
705 
706     // cast to int needed to silence gcc warning about different enums
707     m_sizerText->Add(m_text, 1, wxALL |
708                      (flags & wxTE_MULTILINE ? (int)wxGROW
709                                              : wxALIGN_TOP), 5);
710     m_sizerText->Layout();
711 }
712 
713 // ----------------------------------------------------------------------------
714 // event handlers
715 // ----------------------------------------------------------------------------
716 
OnIdle(wxIdleEvent & WXUNUSED (event))717 void TextWidgetsPage::OnIdle(wxIdleEvent& WXUNUSED(event))
718 {
719     // update all info texts
720 
721     if ( m_textPosCur )
722     {
723         long posCur = m_text->GetInsertionPoint();
724         if ( posCur != m_posCur )
725         {
726             m_textPosCur->Clear();
727             m_textRowCur->Clear();
728             m_textColCur->Clear();
729 
730             long col, row;
731             m_text->PositionToXY(posCur, &col, &row);
732 
733             *m_textPosCur << posCur;
734             *m_textRowCur << row;
735             *m_textColCur << col;
736 
737             m_posCur = posCur;
738         }
739     }
740 
741     if ( m_textPosLast )
742     {
743         long posLast = m_text->GetLastPosition();
744         if ( posLast != m_posLast )
745         {
746             m_textPosLast->Clear();
747             *m_textPosLast << posLast;
748 
749             m_posLast = posLast;
750         }
751     }
752 
753     if ( m_textLineLast )
754     {
755         m_textLineLast->SetValue(
756                 wxString::Format(_T("%d"), m_text->GetNumberOfLines()) );
757     }
758 
759     if ( m_textSelFrom && m_textSelTo )
760     {
761         long selFrom, selTo;
762         m_text->GetSelection(&selFrom, &selTo);
763         if ( selFrom != m_selFrom )
764         {
765             m_textSelFrom->Clear();
766             *m_textSelFrom << selFrom;
767 
768             m_selFrom = selFrom;
769         }
770 
771         if ( selTo != m_selTo )
772         {
773             m_textSelTo->Clear();
774             *m_textSelTo << selTo;
775 
776             m_selTo = selTo;
777         }
778     }
779 
780     if ( m_textRange )
781     {
782         wxString range = m_text->GetRange(10, 20);
783         if ( range != m_range10_20 )
784         {
785             m_range10_20 = range;
786             m_textRange->SetValue(range);
787         }
788     }
789 }
790 
OnButtonReset(wxCommandEvent & WXUNUSED (event))791 void TextWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
792 {
793     Reset();
794 
795     CreateText();
796 }
797 
OnButtonSet(wxCommandEvent & WXUNUSED (event))798 void TextWidgetsPage::OnButtonSet(wxCommandEvent& WXUNUSED(event))
799 {
800     m_text->SetValue(m_text->GetWindowStyle() & wxTE_MULTILINE
801                         ? _T("Here,\nthere and\neverywhere")
802                         : _T("Yellow submarine"));
803 
804     m_text->SetFocus();
805 }
806 
OnButtonAdd(wxCommandEvent & WXUNUSED (event))807 void TextWidgetsPage::OnButtonAdd(wxCommandEvent& WXUNUSED(event))
808 {
809     if ( m_text->GetWindowStyle() & wxTE_MULTILINE )
810     {
811         m_text->AppendText(_T("We all live in a\n"));
812     }
813 
814     m_text->AppendText(_T("Yellow submarine"));
815 }
816 
OnButtonInsert(wxCommandEvent & WXUNUSED (event))817 void TextWidgetsPage::OnButtonInsert(wxCommandEvent& WXUNUSED(event))
818 {
819     m_text->WriteText(_T("Is there anybody going to listen to my story"));
820     if ( m_text->GetWindowStyle() & wxTE_MULTILINE )
821     {
822         m_text->WriteText(_T("\nall about the girl who came to stay"));
823     }
824 }
825 
OnButtonClear(wxCommandEvent & WXUNUSED (event))826 void TextWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
827 {
828     m_text->Clear();
829     m_text->SetFocus();
830 }
831 
OnButtonLoad(wxCommandEvent & WXUNUSED (event))832 void TextWidgetsPage::OnButtonLoad(wxCommandEvent& WXUNUSED(event))
833 {
834     // search for the file in several dirs where it's likely to be
835     wxPathList pathlist;
836     pathlist.Add(_T("."));
837     pathlist.Add(_T(".."));
838     pathlist.Add(_T("../../../samples/widgets"));
839 
840     wxString filename = pathlist.FindValidPath(_T("textctrl.cpp"));
841     if ( !filename )
842     {
843         wxLogError(_T("File textctrl.cpp not found."));
844     }
845     else // load it
846     {
847         wxStopWatch sw;
848         if ( !m_text->LoadFile(filename) )
849         {
850             // this is not supposed to happen ...
851             wxLogError(_T("Error loading file."));
852         }
853         else
854         {
855             long elapsed = sw.Time();
856             wxLogMessage(_T("Loaded file '%s' in %lu.%us"),
857                          filename.c_str(), elapsed / 1000,
858                          (unsigned int) elapsed % 1000);
859         }
860     }
861 }
862 
OnUpdateUIClearButton(wxUpdateUIEvent & event)863 void TextWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
864 {
865     event.Enable(!m_text->GetValue().empty());
866 }
867 
OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent & event)868 void TextWidgetsPage::OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent& event)
869 {
870     event.Enable( !IsSingleLine() );
871 }
872 
OnUpdateUIPasswordCheckbox(wxUpdateUIEvent & event)873 void TextWidgetsPage::OnUpdateUIPasswordCheckbox(wxUpdateUIEvent& event)
874 {
875     // can't put multiline control in password mode
876     event.Enable( IsSingleLine() );
877 }
878 
OnUpdateUIResetButton(wxUpdateUIEvent & event)879 void TextWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
880 {
881     event.Enable( (m_radioTextLines->GetSelection() != DEFAULTS.textLines) ||
882 #ifdef __WXMSW__
883                   (m_radioKind->GetSelection() != DEFAULTS.textKind) ||
884 #endif // __WXMSW__
885                   (m_chkPassword->GetValue() != DEFAULTS.password) ||
886                   (m_chkReadonly->GetValue() != DEFAULTS.readonly) ||
887                   (m_chkFilename->GetValue() != DEFAULTS.filename) ||
888                   (m_radioWrap->GetSelection() != DEFAULTS.wrapStyle) );
889 }
890 
OnText(wxCommandEvent & WXUNUSED (event))891 void TextWidgetsPage::OnText(wxCommandEvent& WXUNUSED(event))
892 {
893     // small hack to suppress the very first message: by then the logging is
894     // not yet redirected and so initial setting of the text value results in
895     // an annoying message box
896     static bool s_firstTime = true;
897     if ( s_firstTime )
898     {
899         s_firstTime = false;
900         return;
901     }
902 
903     wxLogMessage(_T("Text ctrl value changed"));
904 }
905 
OnTextEnter(wxCommandEvent & event)906 void TextWidgetsPage::OnTextEnter(wxCommandEvent& event)
907 {
908     wxLogMessage(_T("Text entered: '%s'"), event.GetString().c_str());
909     event.Skip();
910 }
911 
OnCheckOrRadioBox(wxCommandEvent & WXUNUSED (event))912 void TextWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
913 {
914     CreateText();
915 }
916 
OnStreamRedirector(wxCommandEvent & WXUNUSED (event))917 void TextWidgetsPage::OnStreamRedirector(wxCommandEvent& WXUNUSED(event))
918 {
919 #if wxHAS_TEXT_WINDOW_STREAM
920     wxStreamToTextRedirector redirect(m_text);
921     wxString str( _T("Outputed to cout, appears in wxTextCtrl!") );
922     wxSTD cout << str << wxSTD endl;
923 #else
924     wxMessageBox(_T("This wxWidgets build does not support wxStreamToTextRedirector"));
925 #endif
926 }
927