]> git.saurik.com Git - wxWidgets.git/blame - samples/widgets/textctrl.cpp
ugh. Nesting the (per class) plugin sentries can require them to
[wxWidgets.git] / samples / widgets / textctrl.cpp
CommitLineData
32b8ec41
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Program: wxWindows 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$
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/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#endif
39
40#include "wx/sizer.h"
41
42#include "widgets.h"
43
44#include "icons/text.xpm"
45
46// ----------------------------------------------------------------------------
47// constants
48// ----------------------------------------------------------------------------
49
50// control ids
51enum
52{
53 TextPage_Reset = 100,
54
55 TextPage_Set,
56 TextPage_Add,
57 TextPage_Insert,
58 TextPage_Clear,
59 TextPage_Load,
60
61 TextPage_Password,
62 TextPage_WrapLines,
63 TextPage_Textctrl
64};
65
66// textctrl line number radiobox values
67enum TextLines
68{
69 TextLines_Single,
70 TextLines_Multi
71};
72
73// default values for the controls
74static const struct ControlValues
75{
76 TextLines textLines;
77 bool password;
78 bool wraplines;
79 bool readonly;
80} DEFAULTS =
81{
82 TextLines_Multi, // multiline
83 FALSE, // not password
84 TRUE, // do wrap lines
85 FALSE // not readonly
86};
87
88// ----------------------------------------------------------------------------
89// TextWidgetsPage
90// ----------------------------------------------------------------------------
91
92// Define a new frame type: this is going to be our main frame
93class TextWidgetsPage : public WidgetsPage
94{
95public:
96 // ctor(s) and dtor
97 TextWidgetsPage(wxNotebook *notebook, wxImageList *imaglist);
98 virtual ~TextWidgetsPage();
99
100protected:
101 // create an info text contorl
102 wxTextCtrl *CreateInfoText();
103
104 // create a horz sizer holding a static text and this text control
105 wxSizer *CreateTextWithLabelSizer(const wxString& label,
106 wxTextCtrl *text,
107 const wxString& label2 = wxEmptyString,
108 wxTextCtrl *text2 = NULL);
109
110 // event handlers
111 void OnButtonReset(wxCommandEvent& event);
112 void OnButtonClearLog(wxCommandEvent& event);
113
114 void OnButtonSet(wxCommandEvent& event);
115 void OnButtonAdd(wxCommandEvent& event);
116 void OnButtonInsert(wxCommandEvent& event);
117 void OnButtonClear(wxCommandEvent& event);
118 void OnButtonLoad(wxCommandEvent& event);
119
120 void OnButtonQuit(wxCommandEvent& event);
121
122 void OnText(wxCommandEvent& event);
123 void OnTextEnter(wxCommandEvent& event);
124
125 void OnCheckOrRadioBox(wxCommandEvent& event);
126
127 void OnUpdateUIClearButton(wxUpdateUIEvent& event);
128
129 void OnUpdateUIPasswordCheckbox(wxUpdateUIEvent& event);
130 void OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent& event);
131
132 void OnUpdateUIResetButton(wxUpdateUIEvent& event);
133
134 void OnIdle(wxIdleEvent& event);
135
136 // reset the textctrl parameters
137 void Reset();
138
139 // (re)create the textctrl
140 void CreateText();
141
142 // is the control currently single line?
143 bool IsSingleLine() const
144 {
145 return m_radioTextLines->GetSelection() == TextLines_Single;
146 }
147
148 // the controls
149 // ------------
150
151 // the radiobox to choose between single and multi line
152 wxRadioBox *m_radioTextLines;
153
154 // the checkboxes controlling text ctrl styles
155 wxCheckBox *m_chkPassword,
156 *m_chkWrapLines,
157 *m_chkReadonly;
158
159 // the textctrl itself and the sizer it is in
160 wxTextCtrl *m_text;
161 wxSizer *m_sizerText;
162
163 // the information text zones
164 wxTextCtrl *m_textPosCur,
165 *m_textRowCur,
166 *m_textColCur,
167 *m_textPosLast,
168 *m_textLineLast,
169 *m_textSelFrom,
170 *m_textSelTo;
171
172 // and the data to show in them
173 long m_posCur,
174 m_posLast,
175 m_selFrom,
176 m_selTo;
177
178private:
179 // any class wishing to process wxWindows events must use this macro
5e173f35
GD
180 DECLARE_EVENT_TABLE()
181 DECLARE_WIDGETS_PAGE(TextWidgetsPage)
32b8ec41
VZ
182};
183
184// ----------------------------------------------------------------------------
185// event tables
186// ----------------------------------------------------------------------------
187
188BEGIN_EVENT_TABLE(TextWidgetsPage, WidgetsPage)
189 EVT_IDLE(TextWidgetsPage::OnIdle)
190
191 EVT_BUTTON(TextPage_Reset, TextWidgetsPage::OnButtonReset)
192
193 EVT_BUTTON(TextPage_Clear, TextWidgetsPage::OnButtonClear)
194 EVT_BUTTON(TextPage_Set, TextWidgetsPage::OnButtonSet)
195 EVT_BUTTON(TextPage_Add, TextWidgetsPage::OnButtonAdd)
196 EVT_BUTTON(TextPage_Insert, TextWidgetsPage::OnButtonInsert)
197 EVT_BUTTON(TextPage_Load, TextWidgetsPage::OnButtonLoad)
198
199 EVT_UPDATE_UI(TextPage_Clear, TextWidgetsPage::OnUpdateUIClearButton)
200
201 EVT_UPDATE_UI(TextPage_Password, TextWidgetsPage::OnUpdateUIPasswordCheckbox)
202 EVT_UPDATE_UI(TextPage_WrapLines, TextWidgetsPage::OnUpdateUIWrapLinesCheckbox)
203
204 EVT_UPDATE_UI(TextPage_Reset, TextWidgetsPage::OnUpdateUIResetButton)
205
206 EVT_TEXT(TextPage_Textctrl, TextWidgetsPage::OnText)
207 EVT_TEXT_ENTER(TextPage_Textctrl, TextWidgetsPage::OnTextEnter)
208
209 EVT_CHECKBOX(-1, TextWidgetsPage::OnCheckOrRadioBox)
210 EVT_RADIOBOX(-1, TextWidgetsPage::OnCheckOrRadioBox)
211END_EVENT_TABLE()
212
213// ============================================================================
214// implementation
215// ============================================================================
216
217IMPLEMENT_WIDGETS_PAGE(TextWidgetsPage, _T("Text"));
218
219// ----------------------------------------------------------------------------
220// TextWidgetsPage creation
221// ----------------------------------------------------------------------------
222
223TextWidgetsPage::TextWidgetsPage(wxNotebook *notebook, wxImageList *imaglist)
224 : WidgetsPage(notebook)
225{
226 imaglist->Add(wxBitmap(text_xpm));
227
228 // init everything
229 m_radioTextLines = (wxRadioBox *)NULL;
230
231 m_chkPassword =
232 m_chkWrapLines =
233 m_chkReadonly = (wxCheckBox *)NULL;
234
235 m_text =
236 m_textPosCur =
237 m_textRowCur =
238 m_textColCur =
239 m_textPosLast =
240 m_textLineLast =
241 m_textSelFrom =
242 m_textSelTo = (wxTextCtrl *)NULL;
243 m_sizerText = (wxSizer *)NULL;
244
245 m_posCur =
246 m_posLast =
247 m_selFrom =
248 m_selTo = -2; // not -1 which means "no selection"
249
250 // left pane
251 static const wxString modes[] =
252 {
253 _T("single line"),
254 _T("multi line"),
255 };
256
257 wxStaticBox *box = new wxStaticBox(this, -1, _T("&Set textctrl parameters"));
258 m_radioTextLines = new wxRadioBox(this, -1, _T("&Number of lines:"),
259 wxDefaultPosition, wxDefaultSize,
260 WXSIZEOF(modes), modes,
261 1, wxRA_SPECIFY_COLS);
262
263 wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
264
265 sizerLeft->Add(m_radioTextLines, 0, wxGROW | wxALL, 5);
266 sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
267
268 m_chkPassword = CreateCheckBoxAndAddToSizer(
269 sizerLeft, _T("&Password control"), TextPage_Password
270 );
271 m_chkWrapLines = CreateCheckBoxAndAddToSizer(
272 sizerLeft, _T("Line &wrap"), TextPage_WrapLines
273 );
274 m_chkReadonly = CreateCheckBoxAndAddToSizer(
275 sizerLeft, _T("&Read-only mode")
276 );
277
278 wxButton *btn = new wxButton(this, TextPage_Reset, _T("&Reset"));
279 sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
280
281 // middle pane
282 wxStaticBox *box2 = new wxStaticBox(this, -1, _T("&Change contents:"));
283 wxSizer *sizerMiddleUp = new wxStaticBoxSizer(box2, wxVERTICAL);
284
285 btn = new wxButton(this, TextPage_Set, _T("&Set text value"));
286 sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 5);
287
288 btn = new wxButton(this, TextPage_Add, _T("&Append text"));
289 sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 5);
290
291 btn = new wxButton(this, TextPage_Insert, _T("&Insert text"));
292 sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 5);
293
294 btn = new wxButton(this, TextPage_Load, _T("&Load file"));
295 sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 5);
296
297 btn = new wxButton(this, TextPage_Clear, _T("&Clear"));
298 sizerMiddleUp->Add(btn, 0, wxALL | wxGROW, 5);
299
300 wxStaticBox *box4 = new wxStaticBox(this, -1, _T("&Info:"));
301 wxSizer *sizerMiddleDown = new wxStaticBoxSizer(box4, wxVERTICAL);
302
303 m_textPosCur = CreateInfoText();
304 m_textRowCur = CreateInfoText();
305 m_textColCur = CreateInfoText();
306
307 wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
308 sizerRow->Add(CreateTextWithLabelSizer
309 (
310 _T("Current pos:"),
311 m_textPosCur
312 ),
313 0, wxRIGHT, 5);
314 sizerRow->Add(CreateTextWithLabelSizer
315 (
316 _T("Col:"),
317 m_textColCur
318 ),
319 0, wxLEFT | wxRIGHT, 5);
320 sizerRow->Add(CreateTextWithLabelSizer
321 (
322 _T("Row:"),
323 m_textRowCur
324 ),
325 0, wxLEFT, 5);
326 sizerMiddleDown->Add(sizerRow, 0, wxALL, 5);
327
328 m_textLineLast = CreateInfoText();
329 m_textPosLast = CreateInfoText();
330 sizerMiddleDown->Add
331 (
332 CreateTextWithLabelSizer
333 (
334 _T("Number of lines:"),
335 m_textLineLast,
336 _T("Last position:"),
337 m_textPosLast
338 ),
339 0, wxALL, 5
340 );
341
342 m_textSelFrom = CreateInfoText();
343 m_textSelTo = CreateInfoText();
344 sizerMiddleDown->Add
345 (
346 CreateTextWithLabelSizer
347 (
348 _T("Selection: from"),
349 m_textSelFrom,
350 _T("to"),
351 m_textSelTo
352 ),
353 0, wxALL, 5
354 );
355 wxSizer *sizerMiddle = new wxBoxSizer(wxVERTICAL);
356 sizerMiddle->Add(sizerMiddleUp, 0, wxGROW);
357 sizerMiddle->Add(sizerMiddleDown, 1, wxGROW | wxTOP, 5);
358
359 // right pane
360 wxStaticBox *box3 = new wxStaticBox(this, -1, _T("&Text:"));
361 m_sizerText = new wxStaticBoxSizer(box3, wxHORIZONTAL);
362 Reset();
363 CreateText();
364 m_sizerText->SetMinSize(250, 0);
365
366 // the 3 panes panes compose the upper part of the window
367 wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
368 sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
369 sizerTop->Add(sizerMiddle, 0, wxGROW | wxALL, 10);
370 sizerTop->Add(m_sizerText, 1, wxGROW | (wxALL & ~wxRIGHT), 10);
371
372 SetAutoLayout(TRUE);
373 SetSizer(sizerTop);
374
375 sizerTop->Fit(this);
376}
377
378TextWidgetsPage::~TextWidgetsPage()
379{
380}
381
382// ----------------------------------------------------------------------------
383// creation helpers
384// ----------------------------------------------------------------------------
385
386wxTextCtrl *TextWidgetsPage::CreateInfoText()
387{
388 static int s_maxWidth = 0;
389 if ( !s_maxWidth )
390 {
391 // calc it once only
392 GetTextExtent(_T("9999999"), &s_maxWidth, NULL);
393 }
394
395 wxTextCtrl *text = new wxTextCtrl(this, -1, _T(""),
396 wxDefaultPosition,
397 wxSize(s_maxWidth, -1),
398 wxTE_READONLY);
399 return text;
400}
401
402wxSizer *TextWidgetsPage::CreateTextWithLabelSizer(const wxString& label,
403 wxTextCtrl *text,
404 const wxString& label2,
405 wxTextCtrl *text2)
406{
407 wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
408 sizerRow->Add(new wxStaticText(this, -1, label), 0,
409 wxALIGN_CENTRE_VERTICAL | wxRIGHT, 5);
410 sizerRow->Add(text, 0, wxALIGN_CENTRE_VERTICAL);
411 if ( text2 )
412 {
413 sizerRow->Add(new wxStaticText(this, -1, label2), 0,
414 wxALIGN_CENTRE_VERTICAL | wxLEFT | wxRIGHT, 5);
415 sizerRow->Add(text2, 0, wxALIGN_CENTRE_VERTICAL);
416 }
417
418 return sizerRow;
419}
420
421// ----------------------------------------------------------------------------
422// operations
423// ----------------------------------------------------------------------------
424
425void TextWidgetsPage::Reset()
426{
427 m_radioTextLines->SetSelection(DEFAULTS.textLines);
428 m_chkPassword->SetValue(DEFAULTS.password);
429 m_chkWrapLines->SetValue(DEFAULTS.wraplines);
430 m_chkReadonly->SetValue(DEFAULTS.readonly);
431}
432
433void TextWidgetsPage::CreateText()
434{
435 int flags = 0;
436 switch ( m_radioTextLines->GetSelection() )
437 {
438 default:
439 wxFAIL_MSG( _T("unexpected radio box selection") );
440
441 case TextLines_Single:
442 break;
443
444 case TextLines_Multi:
445 flags |= wxTE_MULTILINE;
446 m_chkPassword->SetValue(FALSE);
447 break;
448 }
449
450 if ( m_chkPassword->GetValue() )
451 flags |= wxTE_PASSWORD;
452 if ( m_chkReadonly->GetValue() )
453 flags |= wxTE_READONLY;
454 if ( !m_chkWrapLines->GetValue() )
455 flags |= wxHSCROLL;
456
457 wxString valueOld;
458 if ( m_text )
459 {
460 valueOld = m_text->GetValue();
461
462 m_sizerText->Remove(m_text);
463 delete m_text;
464 }
465 else
466 {
467 valueOld = _T("Hello, Universe!");
468 }
469
470 m_text = new wxTextCtrl(this, TextPage_Textctrl,
471 valueOld,
472 wxDefaultPosition, wxDefaultSize,
473 flags);
474 m_sizerText->Add(m_text, 1, wxALL |
475 (flags & wxTE_MULTILINE ? wxGROW
476 : wxALIGN_TOP), 5);
477 m_sizerText->Layout();
478}
479
480// ----------------------------------------------------------------------------
481// event handlers
482// ----------------------------------------------------------------------------
483
484void TextWidgetsPage::OnIdle(wxIdleEvent& WXUNUSED(event))
485{
486 // update all info texts
487
488 if ( m_textPosCur )
489 {
490 long posCur = m_text->GetInsertionPoint();
491 if ( posCur != m_posCur )
492 {
493 m_textPosCur->Clear();
494 m_textRowCur->Clear();
495 m_textColCur->Clear();
496
497 long col, row;
498 m_text->PositionToXY(posCur, &col, &row);
499
500 *m_textPosCur << posCur;
501 *m_textRowCur << row;
502 *m_textColCur << col;
503
504 m_posCur = posCur;
505 }
506 }
507
508 if ( m_textPosLast )
509 {
510 long posLast = m_text->GetLastPosition();
511 if ( posLast != m_posLast )
512 {
513 m_textPosLast->Clear();
514 *m_textPosLast << posLast;
515
516 m_posLast = posLast;
517 }
518 }
519
520 if ( m_textLineLast )
521 {
522 m_textLineLast->SetValue(
523 wxString::Format(_T("%ld"), m_text->GetNumberOfLines()));
524 }
525
526 if ( m_textSelFrom && m_textSelTo )
527 {
528 long selFrom, selTo;
529 m_text->GetSelection(&selFrom, &selTo);
530 if ( selFrom != m_selFrom )
531 {
532 m_textSelFrom->Clear();
533 *m_textSelFrom << selFrom;
534
535 m_selFrom = selFrom;
536 }
537
538 if ( selTo != m_selTo )
539 {
540 m_textSelTo->Clear();
541 *m_textSelTo << selTo;
542
543 m_selTo = selTo;
544 }
545 }
546}
547
548void TextWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
549{
550 Reset();
551
552 CreateText();
553}
554
555void TextWidgetsPage::OnButtonSet(wxCommandEvent& WXUNUSED(event))
556{
557 m_text->SetValue(_T("Yellow submarine"));
558 m_text->SetFocus();
559}
560
561void TextWidgetsPage::OnButtonAdd(wxCommandEvent& WXUNUSED(event))
562{
563 m_text->AppendText(_T("here, there and everywhere"));
564 m_text->SetFocus();
565}
566
567void TextWidgetsPage::OnButtonInsert(wxCommandEvent& WXUNUSED(event))
568{
569 m_text->WriteText(_T("is there anybody going to listen to my story"));
570 m_text->SetFocus();
571}
572
573void TextWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
574{
575 m_text->Clear();
576 m_text->SetFocus();
577}
578
579void TextWidgetsPage::OnButtonLoad(wxCommandEvent& WXUNUSED(event))
580{
581 // search for the file in several dirs where it's likely to be
582 wxPathList pathlist;
583 pathlist.Add(_T("."));
584 pathlist.Add(_T(".."));
585 pathlist.Add(_T("../../../samples/widgets"));
586
587 wxString filename = pathlist.FindValidPath(_T("textctrl.cpp"));
588 if ( !filename )
589 {
590 wxLogError(_T("File textctrl.cpp not found."));
591 }
592 else // load it
593 {
594 wxStopWatch sw;
595 if ( !m_text->LoadFile(filename) )
596 {
597 // this is not supposed to happen ...
598 wxLogError(_T("Error loading file."));
599 }
600 else
601 {
602 long elapsed = sw.Time();
603 wxLogMessage(_T("Loaded file '%s' in %u.%us"),
604 filename.c_str(), elapsed / 1000, elapsed % 1000);
605 }
606 }
607}
608
609void TextWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
610{
611 event.Enable(!m_text->GetValue().empty());
612}
613
614void TextWidgetsPage::OnUpdateUIWrapLinesCheckbox(wxUpdateUIEvent& event)
615{
616 event.Enable( !IsSingleLine() );
617}
618
619void TextWidgetsPage::OnUpdateUIPasswordCheckbox(wxUpdateUIEvent& event)
620{
621 // can't put multiline control in password mode
622 event.Enable( IsSingleLine() );
623}
624
625void TextWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
626{
627 event.Enable( (m_radioTextLines->GetSelection() != DEFAULTS.textLines) ||
628 (m_chkReadonly->GetValue() != DEFAULTS.readonly) ||
629 (m_chkPassword->GetValue() != DEFAULTS.password) ||
630 (m_chkWrapLines->GetValue() != DEFAULTS.wraplines) );
631}
632
633void TextWidgetsPage::OnText(wxCommandEvent& event)
634{
635 // small hack to suppress the very first message: by then the logging is
636 // not yet redirected and so initial setting of the text value results in
637 // an annoying message box
638 static bool s_firstTime = TRUE;
639 if ( s_firstTime )
640 {
641 s_firstTime = FALSE;
642 return;
643 }
644
645 wxLogMessage(_T("Text ctrl value changed"));
646}
647
648void TextWidgetsPage::OnTextEnter(wxCommandEvent& event)
649{
650 wxLogMessage(_T("Text entered: '%s'"), event.GetString().c_str());
651}
652
653void TextWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& event)
654{
655 CreateText();
656}
657