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