1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWindows 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 wxWindows 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
))