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"
39 #include "wx/msgdlg.h"
43 #include "wx/ioswrap.h"
47 #include "icons/text.xpm"
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
56 TextPage_Reset
= wxID_HIGHEST
,
64 TextPage_StreamRedirector
,
71 // textctrl line number radiobox values
79 // wrap style radio box
91 // textctrl kind values
102 // default values for the controls
103 static const struct ControlValues
117 TextLines_Multi
, // multiline
118 false, // not password
119 false, // not readonly
120 WrapStyle_Word
, // wrap on word boundaries
122 TextKind_Plain
// plain EDIT control
126 // ----------------------------------------------------------------------------
128 // ----------------------------------------------------------------------------
130 // Define a new frame type: this is going to be our main frame
131 class TextWidgetsPage
: public WidgetsPage
135 TextWidgetsPage(WidgetsBookCtrl
*book
, wxImageList
*imaglist
);
136 virtual ~TextWidgetsPage(){};
138 virtual wxControl
*GetWidget() const { return m_text
; }
139 virtual void RecreateWidget() { CreateText(); }
141 // lazy creation of the content
142 virtual void CreateContent();
145 // create an info text contorl
146 wxTextCtrl
*CreateInfoText();
148 // create a horz sizer holding a static text and this text control
149 wxSizer
*CreateTextWithLabelSizer(const wxString
& label
,
151 const wxString
& label2
= wxEmptyString
,
152 wxTextCtrl
*text2
= NULL
);
155 void OnButtonReset(wxCommandEvent
& event
);
156 void OnButtonClearLog(wxCommandEvent
& event
);
158 void OnButtonSet(wxCommandEvent
& event
);
159 void OnButtonAdd(wxCommandEvent
& event
);
160 void OnButtonInsert(wxCommandEvent
& event
);
161 void OnButtonClear(wxCommandEvent
& event
);
162 void OnButtonLoad(wxCommandEvent
& event
);
164 void OnStreamRedirector(wxCommandEvent
& event
);
165 void OnButtonQuit(wxCommandEvent
& event
);
167 void OnText(wxCommandEvent
& event
);
168 void OnTextEnter(wxCommandEvent
& event
);
170 void OnCheckOrRadioBox(wxCommandEvent
& event
);
172 void OnUpdateUIClearButton(wxUpdateUIEvent
& event
);
174 void OnUpdateUIPasswordCheckbox(wxUpdateUIEvent
& event
);
175 void OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent
& event
);
177 void OnUpdateUIResetButton(wxUpdateUIEvent
& event
);
179 void OnIdle(wxIdleEvent
& event
);
181 // reset the textctrl parameters
184 // (re)create the textctrl
187 // is the control currently single line?
188 bool IsSingleLine() const
190 return m_radioTextLines
->GetSelection() == TextLines_Single
;
196 // the radiobox to choose between single and multi line
197 wxRadioBox
*m_radioTextLines
;
199 // and another one to choose the wrapping style
200 wxRadioBox
*m_radioWrap
;
202 // the checkboxes controlling text ctrl styles
203 wxCheckBox
*m_chkPassword
,
206 // under MSW we test rich edit controls as well here
208 wxRadioBox
*m_radioKind
;
211 // the textctrl itself and the sizer it is in
213 wxSizer
*m_sizerText
;
215 // the information text zones
216 wxTextCtrl
*m_textPosCur
,
225 // and the data to show in them
231 wxString m_range10_20
;
234 // any class wishing to process wxWidgets events must use this macro
235 DECLARE_EVENT_TABLE()
236 DECLARE_WIDGETS_PAGE(TextWidgetsPage
)
239 // ----------------------------------------------------------------------------
241 // ----------------------------------------------------------------------------
243 class WidgetsTextCtrl
: public wxTextCtrl
246 WidgetsTextCtrl(wxWindow
*parent
,
248 const wxString
& value
,
250 : wxTextCtrl(parent
, id
, value
, wxDefaultPosition
, wxDefaultSize
, flags
)
255 void OnRightClick(wxMouseEvent
& event
)
259 switch ( HitTest(event
.GetPosition(), &x
, &y
) )
262 wxFAIL_MSG( _T("unexpected HitTest() result") );
265 case wxTE_HT_UNKNOWN
:
267 where
= _T("nowhere near");
271 where
= _T("before");
279 where
= _T("beyond");
282 case wxTE_HT_ON_TEXT
:
287 wxLogMessage(_T("Mouse is %s (%ld, %ld)"), where
.c_str(), x
, y
);
293 DECLARE_EVENT_TABLE()
296 // ----------------------------------------------------------------------------
298 // ----------------------------------------------------------------------------
300 BEGIN_EVENT_TABLE(TextWidgetsPage
, WidgetsPage
)
301 EVT_IDLE(TextWidgetsPage::OnIdle
)
303 EVT_BUTTON(TextPage_Reset
, TextWidgetsPage::OnButtonReset
)
305 EVT_BUTTON(TextPage_StreamRedirector
, TextWidgetsPage::OnStreamRedirector
)
307 EVT_BUTTON(TextPage_Clear
, TextWidgetsPage::OnButtonClear
)
308 EVT_BUTTON(TextPage_Set
, TextWidgetsPage::OnButtonSet
)
309 EVT_BUTTON(TextPage_Add
, TextWidgetsPage::OnButtonAdd
)
310 EVT_BUTTON(TextPage_Insert
, TextWidgetsPage::OnButtonInsert
)
311 EVT_BUTTON(TextPage_Load
, TextWidgetsPage::OnButtonLoad
)
313 EVT_UPDATE_UI(TextPage_Clear
, TextWidgetsPage::OnUpdateUIClearButton
)
315 EVT_UPDATE_UI(TextPage_Password
, TextWidgetsPage::OnUpdateUIPasswordCheckbox
)
316 EVT_UPDATE_UI(TextPage_WrapLines
, TextWidgetsPage::OnUpdateUIWrapLinesCheckbox
)
318 EVT_UPDATE_UI(TextPage_Reset
, TextWidgetsPage::OnUpdateUIResetButton
)
320 EVT_TEXT(TextPage_Textctrl
, TextWidgetsPage::OnText
)
321 EVT_TEXT_ENTER(TextPage_Textctrl
, TextWidgetsPage::OnTextEnter
)
323 EVT_CHECKBOX(wxID_ANY
, TextWidgetsPage::OnCheckOrRadioBox
)
324 EVT_RADIOBOX(wxID_ANY
, TextWidgetsPage::OnCheckOrRadioBox
)
327 BEGIN_EVENT_TABLE(WidgetsTextCtrl
, wxTextCtrl
)
328 EVT_RIGHT_UP(WidgetsTextCtrl::OnRightClick
)
331 // ============================================================================
333 // ============================================================================
335 #if defined(__WXX11__)
336 #define FAMILY_CTRLS NATIVE_CTRLS
337 #elif defined(__WXUNIVERSAL__)
338 #define FAMILY_CTRLS UNIVERSAL_CTRLS
340 #define FAMILY_CTRLS NATIVE_CTRLS
343 IMPLEMENT_WIDGETS_PAGE(TextWidgetsPage
, _T("Text"),
344 FAMILY_CTRLS
| EDITABLE_CTRLS
347 // ----------------------------------------------------------------------------
348 // TextWidgetsPage creation
349 // ----------------------------------------------------------------------------
351 TextWidgetsPage::TextWidgetsPage(WidgetsBookCtrl
*book
, wxImageList
*imaglist
)
352 : WidgetsPage(book
, imaglist
, text_xpm
)
359 m_radioTextLines
= (wxRadioBox
*)NULL
;
362 m_chkReadonly
= (wxCheckBox
*)NULL
;
372 m_textRange
= (wxTextCtrl
*)NULL
;
374 m_sizerText
= (wxSizer
*)NULL
;
379 m_selTo
= -2; // not -1 which means "no selection"
382 void TextWidgetsPage::CreateContent()
385 static const wxString modes
[] =
391 wxStaticBox
*box
= new wxStaticBox(this, wxID_ANY
, _T("&Set textctrl parameters"));
392 m_radioTextLines
= new wxRadioBox(this, wxID_ANY
, _T("&Number of lines:"),
393 wxDefaultPosition
, wxDefaultSize
,
394 WXSIZEOF(modes
), modes
,
395 1, wxRA_SPECIFY_COLS
);
397 wxSizer
*sizerLeft
= new wxStaticBoxSizer(box
, wxVERTICAL
);
399 sizerLeft
->Add(m_radioTextLines
, 0, wxGROW
| wxALL
, 5);
400 sizerLeft
->AddSpacer(5);
402 m_chkPassword
= CreateCheckBoxAndAddToSizer(
403 sizerLeft
, _T("&Password control"), TextPage_Password
405 m_chkReadonly
= CreateCheckBoxAndAddToSizer(
406 sizerLeft
, _T("&Read-only mode")
408 sizerLeft
->AddSpacer(5);
410 static const wxString wrap
[] =
418 m_radioWrap
= new wxRadioBox(this, wxID_ANY
, _T("&Wrap style:"),
419 wxDefaultPosition
, wxDefaultSize
,
420 WXSIZEOF(wrap
), wrap
,
421 1, wxRA_SPECIFY_COLS
);
422 sizerLeft
->Add(m_radioWrap
, 0, wxGROW
| wxALL
, 5);
425 static const wxString kinds
[] =
432 m_radioKind
= new wxRadioBox(this, wxID_ANY
, _T("Control &kind"),
433 wxDefaultPosition
, wxDefaultSize
,
434 WXSIZEOF(kinds
), kinds
,
435 1, wxRA_SPECIFY_COLS
);
437 sizerLeft
->AddSpacer(5);
438 sizerLeft
->Add(m_radioKind
, 0, wxGROW
| wxALL
, 5);
441 wxButton
*btn
= new wxButton(this, TextPage_Reset
, _T("&Reset"));
442 sizerLeft
->Add(2, 2, 0, wxGROW
| wxALL
, 1); // spacer
443 sizerLeft
->Add(btn
, 0, wxALIGN_CENTRE_HORIZONTAL
| wxALL
, 15);
446 wxStaticBox
*box2
= new wxStaticBox(this, wxID_ANY
, _T("&Change contents:"));
447 wxSizer
*sizerMiddleUp
= new wxStaticBoxSizer(box2
, wxVERTICAL
);
449 btn
= new wxButton(this, TextPage_Set
, _T("&Set text value"));
450 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
452 btn
= new wxButton(this, TextPage_Add
, _T("&Append text"));
453 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
455 btn
= new wxButton(this, TextPage_Insert
, _T("&Insert text"));
456 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
458 btn
= new wxButton(this, TextPage_Load
, _T("&Load file"));
459 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
461 btn
= new wxButton(this, TextPage_Clear
, _T("&Clear"));
462 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
464 btn
= new wxButton(this, TextPage_StreamRedirector
, _T("St&ream redirection"));
465 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
467 wxStaticBox
*box4
= new wxStaticBox(this, wxID_ANY
, _T("&Info:"));
468 wxSizer
*sizerMiddleDown
= new wxStaticBoxSizer(box4
, wxVERTICAL
);
470 m_textPosCur
= CreateInfoText();
471 m_textRowCur
= CreateInfoText();
472 m_textColCur
= CreateInfoText();
474 wxSizer
*sizerRow
= new wxBoxSizer(wxHORIZONTAL
);
475 sizerRow
->Add(CreateTextWithLabelSizer
481 sizerRow
->Add(CreateTextWithLabelSizer
486 0, wxLEFT
| wxRIGHT
, 5);
487 sizerRow
->Add(CreateTextWithLabelSizer
493 sizerMiddleDown
->Add(sizerRow
, 0, wxALL
, 5);
495 m_textLineLast
= CreateInfoText();
496 m_textPosLast
= CreateInfoText();
499 CreateTextWithLabelSizer
501 _T("Number of lines:"),
503 _T("Last position:"),
509 m_textSelFrom
= CreateInfoText();
510 m_textSelTo
= CreateInfoText();
513 CreateTextWithLabelSizer
515 _T("Selection: from"),
523 m_textRange
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
,
524 wxDefaultPosition
, wxDefaultSize
,
528 CreateTextWithLabelSizer
536 wxSizer
*sizerMiddle
= new wxBoxSizer(wxVERTICAL
);
537 sizerMiddle
->Add(sizerMiddleUp
, 0, wxGROW
);
538 sizerMiddle
->Add(sizerMiddleDown
, 1, wxGROW
| wxTOP
, 5);
541 wxStaticBox
*box3
= new wxStaticBox(this, wxID_ANY
, _T("&Text:"));
542 m_sizerText
= new wxStaticBoxSizer(box3
, wxHORIZONTAL
);
545 m_sizerText
->SetMinSize(150, 0);
547 // the 3 panes panes compose the upper part of the window
548 wxSizer
*sizerTop
= new wxBoxSizer(wxHORIZONTAL
);
549 sizerTop
->Add(sizerLeft
, 0, wxGROW
| (wxALL
& ~wxLEFT
), 10);
550 sizerTop
->Add(sizerMiddle
, 0, wxGROW
| wxALL
, 10);
551 sizerTop
->Add(m_sizerText
, 1, wxGROW
| (wxALL
& ~wxRIGHT
), 10);
558 // ----------------------------------------------------------------------------
560 // ----------------------------------------------------------------------------
562 wxTextCtrl
*TextWidgetsPage::CreateInfoText()
564 static int s_maxWidth
= 0;
568 GetTextExtent(_T("9999999"), &s_maxWidth
, NULL
);
571 wxTextCtrl
*text
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
,
573 wxSize(s_maxWidth
, wxDefaultCoord
),
578 wxSizer
*TextWidgetsPage::CreateTextWithLabelSizer(const wxString
& label
,
580 const wxString
& label2
,
583 wxSizer
*sizerRow
= new wxBoxSizer(wxHORIZONTAL
);
584 sizerRow
->Add(new wxStaticText(this, wxID_ANY
, label
), 0,
585 wxALIGN_CENTRE_VERTICAL
| wxRIGHT
, 5);
586 sizerRow
->Add(text
, 0, wxALIGN_CENTRE_VERTICAL
);
589 sizerRow
->Add(new wxStaticText(this, wxID_ANY
, label2
), 0,
590 wxALIGN_CENTRE_VERTICAL
| wxLEFT
| wxRIGHT
, 5);
591 sizerRow
->Add(text2
, 0, wxALIGN_CENTRE_VERTICAL
);
597 // ----------------------------------------------------------------------------
599 // ----------------------------------------------------------------------------
601 void TextWidgetsPage::Reset()
603 m_radioTextLines
->SetSelection(DEFAULTS
.textLines
);
605 m_chkPassword
->SetValue(DEFAULTS
.password
);
606 m_chkReadonly
->SetValue(DEFAULTS
.readonly
);
608 m_radioWrap
->SetSelection(DEFAULTS
.wrapStyle
);
611 m_radioKind
->SetSelection(DEFAULTS
.textKind
);
615 void TextWidgetsPage::CreateText()
617 int flags
= ms_defaultFlags
;
618 switch ( m_radioTextLines
->GetSelection() )
621 wxFAIL_MSG( _T("unexpected lines radio box selection") );
623 case TextLines_Single
:
626 case TextLines_Multi
:
627 flags
|= wxTE_MULTILINE
;
628 m_chkPassword
->SetValue(false);
632 if ( m_chkPassword
->GetValue() )
633 flags
|= wxTE_PASSWORD
;
634 if ( m_chkReadonly
->GetValue() )
635 flags
|= wxTE_READONLY
;
637 switch ( m_radioWrap
->GetSelection() )
640 wxFAIL_MSG( _T("unexpected wrap style radio box selection") );
643 flags
|= wxTE_DONTWRAP
; // same as wxHSCROLL
647 flags
|= wxTE_WORDWRAP
;
651 flags
|= wxTE_CHARWRAP
;
655 // this is default but use symbolic file name for consistency
656 flags
|= wxTE_BESTWRAP
;
661 switch ( m_radioKind
->GetSelection() )
664 wxFAIL_MSG( _T("unexpected kind radio box selection") );
682 valueOld
= m_text
->GetValue();
684 m_sizerText
->Detach( m_text
);
689 valueOld
= _T("Hello, Universe!");
692 m_text
= new WidgetsTextCtrl(this, TextPage_Textctrl
, valueOld
, flags
);
694 // cast to int needed to silence gcc warning about different enums
695 m_sizerText
->Add(m_text
, 1, wxALL
|
696 (flags
& wxTE_MULTILINE
? (int)wxGROW
698 m_sizerText
->Layout();
701 // ----------------------------------------------------------------------------
703 // ----------------------------------------------------------------------------
705 void TextWidgetsPage::OnIdle(wxIdleEvent
& WXUNUSED(event
))
707 // update all info texts
711 long posCur
= m_text
->GetInsertionPoint();
712 if ( posCur
!= m_posCur
)
714 m_textPosCur
->Clear();
715 m_textRowCur
->Clear();
716 m_textColCur
->Clear();
719 m_text
->PositionToXY(posCur
, &col
, &row
);
721 *m_textPosCur
<< posCur
;
722 *m_textRowCur
<< row
;
723 *m_textColCur
<< col
;
731 long posLast
= m_text
->GetLastPosition();
732 if ( posLast
!= m_posLast
)
734 m_textPosLast
->Clear();
735 *m_textPosLast
<< posLast
;
741 if ( m_textLineLast
)
743 m_textLineLast
->SetValue(
744 wxString::Format(_T("%d"), m_text
->GetNumberOfLines()) );
747 if ( m_textSelFrom
&& m_textSelTo
)
750 m_text
->GetSelection(&selFrom
, &selTo
);
751 if ( selFrom
!= m_selFrom
)
753 m_textSelFrom
->Clear();
754 *m_textSelFrom
<< selFrom
;
759 if ( selTo
!= m_selTo
)
761 m_textSelTo
->Clear();
762 *m_textSelTo
<< selTo
;
770 wxString range
= m_text
->GetRange(10, 20);
771 if ( range
!= m_range10_20
)
773 m_range10_20
= range
;
774 m_textRange
->SetValue(range
);
779 void TextWidgetsPage::OnButtonReset(wxCommandEvent
& WXUNUSED(event
))
786 void TextWidgetsPage::OnButtonSet(wxCommandEvent
& WXUNUSED(event
))
788 m_text
->SetValue(m_text
->GetWindowStyle() & wxTE_MULTILINE
789 ? _T("Here,\nthere and\neverywhere")
790 : _T("Yellow submarine"));
795 void TextWidgetsPage::OnButtonAdd(wxCommandEvent
& WXUNUSED(event
))
797 if ( m_text
->GetWindowStyle() & wxTE_MULTILINE
)
799 m_text
->AppendText(_T("We all live in a\n"));
802 m_text
->AppendText(_T("Yellow submarine"));
805 void TextWidgetsPage::OnButtonInsert(wxCommandEvent
& WXUNUSED(event
))
807 m_text
->WriteText(_T("Is there anybody going to listen to my story"));
808 if ( m_text
->GetWindowStyle() & wxTE_MULTILINE
)
810 m_text
->WriteText(_T("\nall about the girl who came to stay"));
814 void TextWidgetsPage::OnButtonClear(wxCommandEvent
& WXUNUSED(event
))
820 void TextWidgetsPage::OnButtonLoad(wxCommandEvent
& WXUNUSED(event
))
822 // search for the file in several dirs where it's likely to be
824 pathlist
.Add(_T("."));
825 pathlist
.Add(_T(".."));
826 pathlist
.Add(_T("../../../samples/widgets"));
828 wxString filename
= pathlist
.FindValidPath(_T("textctrl.cpp"));
831 wxLogError(_T("File textctrl.cpp not found."));
836 if ( !m_text
->LoadFile(filename
) )
838 // this is not supposed to happen ...
839 wxLogError(_T("Error loading file."));
843 long elapsed
= sw
.Time();
844 wxLogMessage(_T("Loaded file '%s' in %lu.%us"),
845 filename
.c_str(), elapsed
/ 1000,
846 (unsigned int) elapsed
% 1000);
851 void TextWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent
& event
)
853 event
.Enable(!m_text
->GetValue().empty());
856 void TextWidgetsPage::OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent
& event
)
858 event
.Enable( !IsSingleLine() );
861 void TextWidgetsPage::OnUpdateUIPasswordCheckbox(wxUpdateUIEvent
& event
)
863 // can't put multiline control in password mode
864 event
.Enable( IsSingleLine() );
867 void TextWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent
& event
)
869 event
.Enable( (m_radioTextLines
->GetSelection() != DEFAULTS
.textLines
) ||
871 (m_radioKind
->GetSelection() != DEFAULTS
.textKind
) ||
873 (m_chkReadonly
->GetValue() != DEFAULTS
.readonly
) ||
874 (m_chkPassword
->GetValue() != DEFAULTS
.password
) ||
875 (m_radioWrap
->GetSelection() != DEFAULTS
.wrapStyle
) );
878 void TextWidgetsPage::OnText(wxCommandEvent
& WXUNUSED(event
))
880 // small hack to suppress the very first message: by then the logging is
881 // not yet redirected and so initial setting of the text value results in
882 // an annoying message box
883 static bool s_firstTime
= true;
890 wxLogMessage(_T("Text ctrl value changed"));
893 void TextWidgetsPage::OnTextEnter(wxCommandEvent
& event
)
895 wxLogMessage(_T("Text entered: '%s'"), event
.GetString().c_str());
899 void TextWidgetsPage::OnCheckOrRadioBox(wxCommandEvent
& WXUNUSED(event
))
904 void TextWidgetsPage::OnStreamRedirector(wxCommandEvent
& WXUNUSED(event
))
906 #if wxHAS_TEXT_WINDOW_STREAM
907 wxStreamToTextRedirector
redirect(m_text
);
908 wxString
str( _T("Outputed to cout, appears in wxTextCtrl!") );
909 wxSTD cout
<< str
<< wxSTD endl
;
911 wxMessageBox(_T("This wxWidgets build does not support wxStreamToTextRedirector"));