1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWidgets Widgets Sample
4 // Purpose: part of the widgets sample showing wxTextCtrl
5 // Author: Vadim Zeitlin
8 // Copyright: (c) 2001 Vadim Zeitlin
9 // License: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // for compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
27 // for all others, include the necessary headers
32 #include "wx/bitmap.h"
33 #include "wx/button.h"
34 #include "wx/checkbox.h"
35 #include "wx/radiobox.h"
36 #include "wx/statbox.h"
37 #include "wx/stattext.h"
38 #include "wx/textctrl.h"
45 #include "icons/text.xpm"
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
67 // textctrl line number radiobox values
75 // wrap style radio box
87 // textctrl kind values
98 // default values for the controls
99 static const struct ControlValues
113 TextLines_Multi
, // multiline
114 false, // not password
115 false, // not readonly
116 WrapStyle_Word
, // wrap on word boundaries
118 TextKind_Plain
// plain EDIT control
122 // ----------------------------------------------------------------------------
124 // ----------------------------------------------------------------------------
126 // Define a new frame type: this is going to be our main frame
127 class TextWidgetsPage
: public WidgetsPage
131 TextWidgetsPage(wxBookCtrl
*book
, wxImageList
*imaglist
);
132 virtual ~TextWidgetsPage(){};
134 virtual wxControl
*GetWidget() const { return m_text
; }
137 // create an info text contorl
138 wxTextCtrl
*CreateInfoText();
140 // create a horz sizer holding a static text and this text control
141 wxSizer
*CreateTextWithLabelSizer(const wxString
& label
,
143 const wxString
& label2
= wxEmptyString
,
144 wxTextCtrl
*text2
= NULL
);
147 void OnButtonReset(wxCommandEvent
& event
);
148 void OnButtonClearLog(wxCommandEvent
& event
);
150 void OnButtonSet(wxCommandEvent
& event
);
151 void OnButtonAdd(wxCommandEvent
& event
);
152 void OnButtonInsert(wxCommandEvent
& event
);
153 void OnButtonClear(wxCommandEvent
& event
);
154 void OnButtonLoad(wxCommandEvent
& event
);
156 void OnButtonQuit(wxCommandEvent
& event
);
158 void OnText(wxCommandEvent
& event
);
159 void OnTextEnter(wxCommandEvent
& event
);
161 void OnCheckOrRadioBox(wxCommandEvent
& event
);
163 void OnUpdateUIClearButton(wxUpdateUIEvent
& event
);
165 void OnUpdateUIPasswordCheckbox(wxUpdateUIEvent
& event
);
166 void OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent
& event
);
168 void OnUpdateUIResetButton(wxUpdateUIEvent
& event
);
170 void OnIdle(wxIdleEvent
& event
);
172 // reset the textctrl parameters
175 // (re)create the textctrl
178 // is the control currently single line?
179 bool IsSingleLine() const
181 return m_radioTextLines
->GetSelection() == TextLines_Single
;
187 // the radiobox to choose between single and multi line
188 wxRadioBox
*m_radioTextLines
;
190 // and another one to choose the wrapping style
191 wxRadioBox
*m_radioWrap
;
193 // the checkboxes controlling text ctrl styles
194 wxCheckBox
*m_chkPassword
,
197 // under MSW we test rich edit controls as well here
199 wxRadioBox
*m_radioKind
;
202 // the textctrl itself and the sizer it is in
204 wxSizer
*m_sizerText
;
206 // the information text zones
207 wxTextCtrl
*m_textPosCur
,
216 // and the data to show in them
222 wxString m_range10_20
;
225 // any class wishing to process wxWidgets events must use this macro
226 DECLARE_EVENT_TABLE()
227 DECLARE_WIDGETS_PAGE(TextWidgetsPage
)
230 // ----------------------------------------------------------------------------
232 // ----------------------------------------------------------------------------
234 class WidgetsTextCtrl
: public wxTextCtrl
237 WidgetsTextCtrl(wxWindow
*parent
,
239 const wxString
& value
,
241 : wxTextCtrl(parent
, id
, value
, wxDefaultPosition
, wxDefaultSize
, flags
)
246 void OnRightClick(wxMouseEvent
& event
)
250 switch ( HitTest(event
.GetPosition(), &x
, &y
) )
253 wxFAIL_MSG( _T("unexpected HitTest() result") );
256 case wxTE_HT_UNKNOWN
:
258 where
= _T("nowhere near");
262 where
= _T("before");
270 where
= _T("beyond");
273 case wxTE_HT_ON_TEXT
:
278 wxLogMessage(_T("Mouse is %s (%ld, %ld)"), where
.c_str(), x
, y
);
284 DECLARE_EVENT_TABLE()
287 // ----------------------------------------------------------------------------
289 // ----------------------------------------------------------------------------
291 BEGIN_EVENT_TABLE(TextWidgetsPage
, WidgetsPage
)
292 EVT_IDLE(TextWidgetsPage::OnIdle
)
294 EVT_BUTTON(TextPage_Reset
, TextWidgetsPage::OnButtonReset
)
296 EVT_BUTTON(TextPage_Clear
, TextWidgetsPage::OnButtonClear
)
297 EVT_BUTTON(TextPage_Set
, TextWidgetsPage::OnButtonSet
)
298 EVT_BUTTON(TextPage_Add
, TextWidgetsPage::OnButtonAdd
)
299 EVT_BUTTON(TextPage_Insert
, TextWidgetsPage::OnButtonInsert
)
300 EVT_BUTTON(TextPage_Load
, TextWidgetsPage::OnButtonLoad
)
302 EVT_UPDATE_UI(TextPage_Clear
, TextWidgetsPage::OnUpdateUIClearButton
)
304 EVT_UPDATE_UI(TextPage_Password
, TextWidgetsPage::OnUpdateUIPasswordCheckbox
)
305 EVT_UPDATE_UI(TextPage_WrapLines
, TextWidgetsPage::OnUpdateUIWrapLinesCheckbox
)
307 EVT_UPDATE_UI(TextPage_Reset
, TextWidgetsPage::OnUpdateUIResetButton
)
309 EVT_TEXT(TextPage_Textctrl
, TextWidgetsPage::OnText
)
310 EVT_TEXT_ENTER(TextPage_Textctrl
, TextWidgetsPage::OnTextEnter
)
312 EVT_CHECKBOX(wxID_ANY
, TextWidgetsPage::OnCheckOrRadioBox
)
313 EVT_RADIOBOX(wxID_ANY
, TextWidgetsPage::OnCheckOrRadioBox
)
316 BEGIN_EVENT_TABLE(WidgetsTextCtrl
, wxTextCtrl
)
317 EVT_RIGHT_UP(WidgetsTextCtrl::OnRightClick
)
320 // ============================================================================
322 // ============================================================================
324 IMPLEMENT_WIDGETS_PAGE(TextWidgetsPage
, _T("Text"));
326 // ----------------------------------------------------------------------------
327 // TextWidgetsPage creation
328 // ----------------------------------------------------------------------------
330 TextWidgetsPage::TextWidgetsPage(wxBookCtrl
*book
, wxImageList
*imaglist
)
333 imaglist
->Add(wxBitmap(text_xpm
));
340 m_radioTextLines
= (wxRadioBox
*)NULL
;
343 m_chkReadonly
= (wxCheckBox
*)NULL
;
353 m_textRange
= (wxTextCtrl
*)NULL
;
355 m_sizerText
= (wxSizer
*)NULL
;
360 m_selTo
= -2; // not -1 which means "no selection"
363 static const wxString modes
[] =
369 wxStaticBox
*box
= new wxStaticBox(this, wxID_ANY
, _T("&Set textctrl parameters"));
370 m_radioTextLines
= new wxRadioBox(this, wxID_ANY
, _T("&Number of lines:"),
371 wxDefaultPosition
, wxDefaultSize
,
372 WXSIZEOF(modes
), modes
,
373 1, wxRA_SPECIFY_COLS
);
375 wxSizer
*sizerLeft
= new wxStaticBoxSizer(box
, wxVERTICAL
);
377 sizerLeft
->Add(m_radioTextLines
, 0, wxGROW
| wxALL
, 5);
378 sizerLeft
->AddSpacer(5);
380 m_chkPassword
= CreateCheckBoxAndAddToSizer(
381 sizerLeft
, _T("&Password control"), TextPage_Password
383 m_chkReadonly
= CreateCheckBoxAndAddToSizer(
384 sizerLeft
, _T("&Read-only mode")
386 sizerLeft
->AddSpacer(5);
388 static const wxString wrap
[] =
396 m_radioWrap
= new wxRadioBox(this, wxID_ANY
, _T("&Wrap style:"),
397 wxDefaultPosition
, wxDefaultSize
,
398 WXSIZEOF(wrap
), wrap
,
399 1, wxRA_SPECIFY_COLS
);
400 sizerLeft
->Add(m_radioWrap
, 0, wxGROW
| wxALL
, 5);
403 static const wxString kinds
[] =
410 m_radioKind
= new wxRadioBox(this, wxID_ANY
, _T("Control &kind"),
411 wxDefaultPosition
, wxDefaultSize
,
412 WXSIZEOF(kinds
), kinds
,
413 1, wxRA_SPECIFY_COLS
);
415 sizerLeft
->AddSpacer(5);
416 sizerLeft
->Add(m_radioKind
, 0, wxGROW
| wxALL
, 5);
419 wxButton
*btn
= new wxButton(this, TextPage_Reset
, _T("&Reset"));
420 sizerLeft
->Add(2, 2, 0, wxGROW
| wxALL
, 1); // spacer
421 sizerLeft
->Add(btn
, 0, wxALIGN_CENTRE_HORIZONTAL
| wxALL
, 15);
424 wxStaticBox
*box2
= new wxStaticBox(this, wxID_ANY
, _T("&Change contents:"));
425 wxSizer
*sizerMiddleUp
= new wxStaticBoxSizer(box2
, wxVERTICAL
);
427 btn
= new wxButton(this, TextPage_Set
, _T("&Set text value"));
428 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
430 btn
= new wxButton(this, TextPage_Add
, _T("&Append text"));
431 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
433 btn
= new wxButton(this, TextPage_Insert
, _T("&Insert text"));
434 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
436 btn
= new wxButton(this, TextPage_Load
, _T("&Load file"));
437 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
439 btn
= new wxButton(this, TextPage_Clear
, _T("&Clear"));
440 sizerMiddleUp
->Add(btn
, 0, wxALL
| wxGROW
, 1);
442 wxStaticBox
*box4
= new wxStaticBox(this, wxID_ANY
, _T("&Info:"));
443 wxSizer
*sizerMiddleDown
= new wxStaticBoxSizer(box4
, wxVERTICAL
);
445 m_textPosCur
= CreateInfoText();
446 m_textRowCur
= CreateInfoText();
447 m_textColCur
= CreateInfoText();
449 wxSizer
*sizerRow
= new wxBoxSizer(wxHORIZONTAL
);
450 sizerRow
->Add(CreateTextWithLabelSizer
456 sizerRow
->Add(CreateTextWithLabelSizer
461 0, wxLEFT
| wxRIGHT
, 5);
462 sizerRow
->Add(CreateTextWithLabelSizer
468 sizerMiddleDown
->Add(sizerRow
, 0, wxALL
, 5);
470 m_textLineLast
= CreateInfoText();
471 m_textPosLast
= CreateInfoText();
474 CreateTextWithLabelSizer
476 _T("Number of lines:"),
478 _T("Last position:"),
484 m_textSelFrom
= CreateInfoText();
485 m_textSelTo
= CreateInfoText();
488 CreateTextWithLabelSizer
490 _T("Selection: from"),
498 m_textRange
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
,
499 wxDefaultPosition
, wxDefaultSize
,
503 CreateTextWithLabelSizer
511 wxSizer
*sizerMiddle
= new wxBoxSizer(wxVERTICAL
);
512 sizerMiddle
->Add(sizerMiddleUp
, 0, wxGROW
);
513 sizerMiddle
->Add(sizerMiddleDown
, 1, wxGROW
| wxTOP
, 5);
516 wxStaticBox
*box3
= new wxStaticBox(this, wxID_ANY
, _T("&Text:"));
517 m_sizerText
= new wxStaticBoxSizer(box3
, wxHORIZONTAL
);
520 m_sizerText
->SetMinSize(150, 0);
522 // the 3 panes panes compose the upper part of the window
523 wxSizer
*sizerTop
= new wxBoxSizer(wxHORIZONTAL
);
524 sizerTop
->Add(sizerLeft
, 0, wxGROW
| (wxALL
& ~wxLEFT
), 10);
525 sizerTop
->Add(sizerMiddle
, 0, wxGROW
| wxALL
, 10);
526 sizerTop
->Add(m_sizerText
, 1, wxGROW
| (wxALL
& ~wxRIGHT
), 10);
533 // ----------------------------------------------------------------------------
535 // ----------------------------------------------------------------------------
537 wxTextCtrl
*TextWidgetsPage::CreateInfoText()
539 static int s_maxWidth
= 0;
543 GetTextExtent(_T("9999999"), &s_maxWidth
, NULL
);
546 wxTextCtrl
*text
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
,
548 wxSize(s_maxWidth
, -1),
553 wxSizer
*TextWidgetsPage::CreateTextWithLabelSizer(const wxString
& label
,
555 const wxString
& label2
,
558 wxSizer
*sizerRow
= new wxBoxSizer(wxHORIZONTAL
);
559 sizerRow
->Add(new wxStaticText(this, wxID_ANY
, label
), 0,
560 wxALIGN_CENTRE_VERTICAL
| wxRIGHT
, 5);
561 sizerRow
->Add(text
, 0, wxALIGN_CENTRE_VERTICAL
);
564 sizerRow
->Add(new wxStaticText(this, wxID_ANY
, label2
), 0,
565 wxALIGN_CENTRE_VERTICAL
| wxLEFT
| wxRIGHT
, 5);
566 sizerRow
->Add(text2
, 0, wxALIGN_CENTRE_VERTICAL
);
572 // ----------------------------------------------------------------------------
574 // ----------------------------------------------------------------------------
576 void TextWidgetsPage::Reset()
578 m_radioTextLines
->SetSelection(DEFAULTS
.textLines
);
580 m_chkPassword
->SetValue(DEFAULTS
.password
);
581 m_chkReadonly
->SetValue(DEFAULTS
.readonly
);
583 m_radioWrap
->SetSelection(DEFAULTS
.wrapStyle
);
586 m_radioKind
->SetSelection(DEFAULTS
.textKind
);
590 void TextWidgetsPage::CreateText()
593 switch ( m_radioTextLines
->GetSelection() )
596 wxFAIL_MSG( _T("unexpected lines radio box selection") );
598 case TextLines_Single
:
601 case TextLines_Multi
:
602 flags
|= wxTE_MULTILINE
;
603 m_chkPassword
->SetValue(false);
607 if ( m_chkPassword
->GetValue() )
608 flags
|= wxTE_PASSWORD
;
609 if ( m_chkReadonly
->GetValue() )
610 flags
|= wxTE_READONLY
;
612 switch ( m_radioWrap
->GetSelection() )
615 wxFAIL_MSG( _T("unexpected wrap style radio box selection") );
618 flags
|= wxTE_DONTWRAP
; // same as wxHSCROLL
622 flags
|= wxTE_WORDWRAP
;
626 flags
|= wxTE_LINEWRAP
;
630 // this is default but use symbolic file name for consistency
631 flags
|= wxTE_BESTWRAP
;
636 switch ( m_radioKind
->GetSelection() )
639 wxFAIL_MSG( _T("unexpected kind radio box selection") );
657 valueOld
= m_text
->GetValue();
659 m_sizerText
->Detach( m_text
);
664 valueOld
= _T("Hello, Universe!");
667 m_text
= new WidgetsTextCtrl(this, TextPage_Textctrl
, valueOld
, flags
);
669 // cast to int needed to silence gcc warning about different enums
670 m_sizerText
->Add(m_text
, 1, wxALL
|
671 (flags
& wxTE_MULTILINE
? (int)wxGROW
673 m_sizerText
->Layout();
676 // ----------------------------------------------------------------------------
678 // ----------------------------------------------------------------------------
680 void TextWidgetsPage::OnIdle(wxIdleEvent
& WXUNUSED(event
))
682 // update all info texts
686 long posCur
= m_text
->GetInsertionPoint();
687 if ( posCur
!= m_posCur
)
689 m_textPosCur
->Clear();
690 m_textRowCur
->Clear();
691 m_textColCur
->Clear();
694 m_text
->PositionToXY(posCur
, &col
, &row
);
696 *m_textPosCur
<< posCur
;
697 *m_textRowCur
<< row
;
698 *m_textColCur
<< col
;
706 long posLast
= m_text
->GetLastPosition();
707 if ( posLast
!= m_posLast
)
709 m_textPosLast
->Clear();
710 *m_textPosLast
<< posLast
;
716 if ( m_textLineLast
)
718 m_textLineLast
->SetValue(
719 wxString::Format(_T("%d"), m_text
->GetNumberOfLines()) );
722 if ( m_textSelFrom
&& m_textSelTo
)
725 m_text
->GetSelection(&selFrom
, &selTo
);
726 if ( selFrom
!= m_selFrom
)
728 m_textSelFrom
->Clear();
729 *m_textSelFrom
<< selFrom
;
734 if ( selTo
!= m_selTo
)
736 m_textSelTo
->Clear();
737 *m_textSelTo
<< selTo
;
745 wxString range
= m_text
->GetRange(10, 20);
746 if ( range
!= m_range10_20
)
748 m_range10_20
= range
;
749 m_textRange
->SetValue(range
);
754 void TextWidgetsPage::OnButtonReset(wxCommandEvent
& WXUNUSED(event
))
761 void TextWidgetsPage::OnButtonSet(wxCommandEvent
& WXUNUSED(event
))
763 m_text
->SetValue(m_text
->GetWindowStyle() & wxTE_MULTILINE
764 ? _T("Here,\nthere and\neverywhere")
765 : _T("Yellow submarine"));
770 void TextWidgetsPage::OnButtonAdd(wxCommandEvent
& WXUNUSED(event
))
772 if ( m_text
->GetWindowStyle() & wxTE_MULTILINE
)
774 m_text
->AppendText(_T("We all live in a\n"));
777 m_text
->AppendText(_T("Yellow submarine"));
780 void TextWidgetsPage::OnButtonInsert(wxCommandEvent
& WXUNUSED(event
))
782 m_text
->WriteText(_T("Is there anybody going to listen to my story"));
783 if ( m_text
->GetWindowStyle() & wxTE_MULTILINE
)
785 m_text
->WriteText(_T("\nall about the girl who came to stay"));
789 void TextWidgetsPage::OnButtonClear(wxCommandEvent
& WXUNUSED(event
))
795 void TextWidgetsPage::OnButtonLoad(wxCommandEvent
& WXUNUSED(event
))
797 // search for the file in several dirs where it's likely to be
799 pathlist
.Add(_T("."));
800 pathlist
.Add(_T(".."));
801 pathlist
.Add(_T("../../../samples/widgets"));
803 wxString filename
= pathlist
.FindValidPath(_T("textctrl.cpp"));
806 wxLogError(_T("File textctrl.cpp not found."));
811 if ( !m_text
->LoadFile(filename
) )
813 // this is not supposed to happen ...
814 wxLogError(_T("Error loading file."));
818 long elapsed
= sw
.Time();
819 wxLogMessage(_T("Loaded file '%s' in %lu.%us"),
820 filename
.c_str(), elapsed
/ 1000,
821 (unsigned int) elapsed
% 1000);
826 void TextWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent
& event
)
828 event
.Enable(!m_text
->GetValue().empty());
831 void TextWidgetsPage::OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent
& event
)
833 event
.Enable( !IsSingleLine() );
836 void TextWidgetsPage::OnUpdateUIPasswordCheckbox(wxUpdateUIEvent
& event
)
838 // can't put multiline control in password mode
839 event
.Enable( IsSingleLine() );
842 void TextWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent
& event
)
844 event
.Enable( (m_radioTextLines
->GetSelection() != DEFAULTS
.textLines
) ||
846 (m_radioKind
->GetSelection() != DEFAULTS
.textKind
) ||
848 (m_chkReadonly
->GetValue() != DEFAULTS
.readonly
) ||
849 (m_chkPassword
->GetValue() != DEFAULTS
.password
) ||
850 (m_radioWrap
->GetSelection() != DEFAULTS
.wrapStyle
) );
853 void TextWidgetsPage::OnText(wxCommandEvent
& WXUNUSED(event
))
855 // small hack to suppress the very first message: by then the logging is
856 // not yet redirected and so initial setting of the text value results in
857 // an annoying message box
858 static bool s_firstTime
= true;
865 wxLogMessage(_T("Text ctrl value changed"));
868 void TextWidgetsPage::OnTextEnter(wxCommandEvent
& event
)
870 wxLogMessage(_T("Text entered: '%s'"), event
.GetString().c_str());
874 void TextWidgetsPage::OnCheckOrRadioBox(wxCommandEvent
& WXUNUSED(event
))