]> git.saurik.com Git - wxWidgets.git/blame - tests/controls/textctrltest.cpp
Resolve ambiguity between GetClientXXX() methods in wxOSX wxComboBox.
[wxWidgets.git] / tests / controls / textctrltest.cpp
CommitLineData
c0d9b217 1///////////////////////////////////////////////////////////////////////////////
f0f6a32d 2// Name: tests/controls/textctrltest.cpp
c0d9b217
VZ
3// Purpose: wxTextCtrl unit test
4// Author: Vadim Zeitlin
5// Created: 2007-09-25
6// RCS-ID: $Id$
7// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwidgets.org>
8///////////////////////////////////////////////////////////////////////////////
9
10// ----------------------------------------------------------------------------
11// headers
12// ----------------------------------------------------------------------------
13
14#include "testprec.h"
15
232fdc63
VZ
16#if wxUSE_TEXTCTRL
17
c0d9b217
VZ
18#ifdef __BORLANDC__
19 #pragma hdrstop
20#endif
21
22#ifndef WX_PRECOMP
23 #include "wx/app.h"
24 #include "wx/textctrl.h"
25#endif // WX_PRECOMP
26
8859c729
VZ
27#include "wx/scopeguard.h"
28
f0f6a32d 29#include "textentrytest.h"
232fdc63
VZ
30#include "testableframe.h"
31#include "asserthelper.h"
32#include "wx/uiaction.h"
f0f6a32d 33
c0d9b217
VZ
34// ----------------------------------------------------------------------------
35// test class
36// ----------------------------------------------------------------------------
37
232fdc63 38class TextCtrlTestCase : public TextEntryTestCase, public CppUnit::TestCase
c0d9b217
VZ
39{
40public:
41 TextCtrlTestCase() { }
42
43 virtual void setUp();
44 virtual void tearDown();
45
46private:
f0f6a32d
VZ
47 virtual wxTextEntry *GetTestEntry() const { return m_text; }
48 virtual wxWindow *GetTestWindow() const { return m_text; }
49
c0d9b217 50 CPPUNIT_TEST_SUITE( TextCtrlTestCase );
f0f6a32d 51 wxTEXT_ENTRY_TESTS();
d911dc04 52 CPPUNIT_TEST( MultiLineReplace );
232fdc63
VZ
53 WXUISIM_TEST( ReadOnly );
54 WXUISIM_TEST( MaxLength );
55 CPPUNIT_TEST( StreamInput );
56 CPPUNIT_TEST( Redirector );
57 //WXUISIM_TEST( ProcessEnter );
58 WXUISIM_TEST( Url );
59 CPPUNIT_TEST( Style );
60 CPPUNIT_TEST( Lines );
61 CPPUNIT_TEST( LogTextCtrl );
6ce83213
VZ
62 CPPUNIT_TEST( PositionToCoords );
63 CPPUNIT_TEST( PositionToCoordsRich );
64 CPPUNIT_TEST( PositionToCoordsRich2 );
c0d9b217
VZ
65 CPPUNIT_TEST_SUITE_END();
66
d911dc04 67 void MultiLineReplace();
232fdc63
VZ
68 void ReadOnly();
69 void MaxLength();
70 void StreamInput();
71 void Redirector();
72 //void ProcessEnter();
73 void Url();
74 void Style();
75 void Lines();
76 void LogTextCtrl();
6ce83213
VZ
77 void PositionToCoords();
78 void PositionToCoordsRich();
79 void PositionToCoordsRich2();
80
81 void DoPositionToCoordsTestWithStyle(long style);
d911dc04 82
c0d9b217 83 wxTextCtrl *m_text;
c0d9b217
VZ
84
85 DECLARE_NO_COPY_CLASS(TextCtrlTestCase)
86};
87
88// register in the unnamed registry so that these tests are run by default
89CPPUNIT_TEST_SUITE_REGISTRATION( TextCtrlTestCase );
90
e3778b4d 91// also include in its own registry so that these tests can be run alone
c0d9b217
VZ
92CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( TextCtrlTestCase, "TextCtrlTestCase" );
93
94// ----------------------------------------------------------------------------
95// test initialization
96// ----------------------------------------------------------------------------
97
98void TextCtrlTestCase::setUp()
99{
100 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
101}
102
103void TextCtrlTestCase::tearDown()
104{
232fdc63 105 wxDELETE(m_text);
c0d9b217
VZ
106}
107
108// ----------------------------------------------------------------------------
109// tests themselves
110// ----------------------------------------------------------------------------
111
d911dc04
VZ
112void TextCtrlTestCase::MultiLineReplace()
113{
114 // we need a multiline control for this test so recreate it
115 delete m_text;
116 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
117 wxDefaultPosition, wxDefaultSize,
118 wxTE_MULTILINE);
119
120 m_text->SetValue("Hello replace\n"
121 "0123456789012");
122 m_text->SetInsertionPoint(0);
123
124 m_text->Replace(6, 13, "changed");
125
126 CPPUNIT_ASSERT_EQUAL("Hello changed\n"
127 "0123456789012",
128 m_text->GetValue());
129 CPPUNIT_ASSERT_EQUAL(13, m_text->GetInsertionPoint());
130
131 m_text->Replace(13, -1, "");
132 CPPUNIT_ASSERT_EQUAL("Hello changed", m_text->GetValue());
133 CPPUNIT_ASSERT_EQUAL(13, m_text->GetInsertionPoint());
232fdc63
VZ
134
135 delete m_text;
136 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
137}
138
139void TextCtrlTestCase::ReadOnly()
140{
141#if wxUSE_UIACTIONSIMULATOR
142 // we need a read only control for this test so recreate it
143 delete m_text;
144 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
145 wxDefaultPosition, wxDefaultSize,
146 wxTE_READONLY);
147
148 wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
149 wxTestableFrame);
150
151 EventCounter count(m_text, wxEVT_COMMAND_TEXT_UPDATED);
152
153 m_text->SetFocus();
154
155 wxUIActionSimulator sim;
156 sim.Text("abcdef");
157 wxYield();
158
159 CPPUNIT_ASSERT_EQUAL("", m_text->GetValue());
160 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount());
161
162 // SetEditable() is supposed to override wxTE_READONLY
163 m_text->SetEditable(true);
164
165 sim.Text("abcdef");
166 wxYield();
167
168 CPPUNIT_ASSERT_EQUAL("abcdef", m_text->GetValue());
169 CPPUNIT_ASSERT_EQUAL(6, frame->GetEventCount());
170
171 delete m_text;
172 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
173#endif
174}
175
176void TextCtrlTestCase::MaxLength()
177{
178#if wxUSE_UIACTIONSIMULATOR
179 wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
180 wxTestableFrame);
181
182 EventCounter count(m_text, wxEVT_COMMAND_TEXT_UPDATED);
183 EventCounter count1(m_text, wxEVT_COMMAND_TEXT_MAXLEN);
184
185 m_text->SetFocus();
186 m_text->SetMaxLength(10);
187
188 wxUIActionSimulator sim;
189 sim.Text("abcdef");
190 wxYield();
191
192 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_MAXLEN));
193
194 sim.Text("ghij");
195 wxYield();
196
197 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_MAXLEN));
198 CPPUNIT_ASSERT_EQUAL(10, frame->GetEventCount(wxEVT_COMMAND_TEXT_UPDATED));
199
200 sim.Text("k");
201 wxYield();
202
203 CPPUNIT_ASSERT_EQUAL(1, frame->GetEventCount(wxEVT_COMMAND_TEXT_MAXLEN));
204 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_UPDATED));
205
206 m_text->SetMaxLength(0);
207
208 sim.Text("k");
209 wxYield();
210
211 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_MAXLEN));
212 CPPUNIT_ASSERT_EQUAL(1, frame->GetEventCount(wxEVT_COMMAND_TEXT_UPDATED));
213#endif
214}
215
216void TextCtrlTestCase::StreamInput()
217{
218#ifndef __WXOSX__
8859c729
VZ
219 {
220 // Ensure we use decimal point and not a comma.
221 char * const locOld = setlocale(LC_NUMERIC, "C");
222 wxON_BLOCK_EXIT2( setlocale, (int)LC_NUMERIC, locOld );
223
224 *m_text << "stringinput"
225 << 10
226 << 1000L
227 << 3.14f
228 << 2.71
229 << 'a'
230 << L'b';
231 }
232fdc63
VZ
232
233 CPPUNIT_ASSERT_EQUAL("stringinput1010003.142.71ab", m_text->GetValue());
234
235 m_text->SetValue("");
236
237#if wxHAS_TEXT_WINDOW_STREAM
238
239 std::ostream stream(m_text);
240
241 // We don't test a wide character as this is not a wide stream
242 stream << "stringinput"
243 << 10
244 << 1000L
245 << 3.14f
246 << 2.71
247 << 'a';
248
249 stream.flush();
250
251 CPPUNIT_ASSERT_EQUAL("stringinput1010003.142.71a", m_text->GetValue());
252
8859c729
VZ
253#endif // wxHAS_TEXT_WINDOW_STREAM
254#endif // !__WXOSX__
232fdc63
VZ
255}
256
257void TextCtrlTestCase::Redirector()
258{
259#if wxHAS_TEXT_WINDOW_STREAM && wxUSE_STD_IOSTREAM
260
261 wxStreamToTextRedirector redirect(m_text);
262
263 std::cout << "stringinput"
264 << 10
265 << 1000L
266 << 3.14f
267 << 2.71
268 << 'a';
269
270 CPPUNIT_ASSERT_EQUAL("stringinput1010003.142.71a", m_text->GetValue());
271
272#endif
273}
274
275#if 0
276void TextCtrlTestCase::ProcessEnter()
277{
278#if wxUSE_UIACTIONSIMULATOR
279 wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
280 wxTestableFrame);
281
282 EventCounter count(m_text, wxEVT_COMMAND_TEXT_ENTER);
283
284 m_text->SetFocus();
285
286 wxUIActionSimulator sim;
287 sim.Char(WXK_RETURN);
288 wxYield();
289
290 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_ENTER));
291
292 // we need a text control with wxTE_PROCESS_ENTER for this test
293 delete m_text;
294 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
295 wxDefaultPosition, wxDefaultSize,
296 wxTE_PROCESS_ENTER);
297
298 m_text->SetFocus();
299
300 sim.Char(WXK_RETURN);
301 wxYield();
302
303 CPPUNIT_ASSERT_EQUAL(1, frame->GetEventCount(wxEVT_COMMAND_TEXT_ENTER));
304#endif
305}
306#endif
307
308void TextCtrlTestCase::Url()
309{
310#if wxUSE_UIACTIONSIMULATOR && defined(__WXMSW__)
311 delete m_text;
312 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
313 wxDefaultPosition, wxDefaultSize,
314 wxTE_MULTILINE | wxTE_RICH | wxTE_AUTO_URL);
315
316 wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
317 wxTestableFrame);
318
319 EventCounter count(m_text, wxEVT_COMMAND_TEXT_URL);
320
321 m_text->AppendText("http://www.wxwidgets.org");
322
323 wxUIActionSimulator sim;
324 sim.MouseMove(m_text->ClientToScreen(wxPoint(5, 5)));
325 sim.MouseClick();
326 wxYield();
327
328 CPPUNIT_ASSERT_EQUAL(1, frame->GetEventCount());
329#endif
330}
331
332void TextCtrlTestCase::Style()
333{
334#ifndef __WXOSX__
335 delete m_text;
336 // We need wxTE_RICH under windows for style support
337 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
338 wxDefaultPosition, wxDefaultSize, wxTE_RICH);
339
340 // Red text on a white background
341 m_text->SetDefaultStyle(wxTextAttr(*wxRED, *wxWHITE));
342
343 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetTextColour(), *wxRED);
344 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetBackgroundColour(),
345 *wxWHITE);
346
347 m_text->AppendText("red on white ");
348
349 // Red text on a grey background
350 m_text->SetDefaultStyle(wxTextAttr(wxNullColour, *wxLIGHT_GREY));
351
352 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetTextColour(), *wxRED);
353 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetBackgroundColour(),
354 *wxLIGHT_GREY);
355
356 m_text->AppendText("red on grey ");
357
358 // Blue text on a grey background
359 m_text->SetDefaultStyle(wxTextAttr(*wxBLUE));
360
361
362 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetTextColour(), *wxBLUE);
363 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetBackgroundColour(),
364 *wxLIGHT_GREY);
365
366 m_text->AppendText("blue on grey");
367
368 // Get getting the style at a specific location
369 wxTextAttr style;
370
371 // We have to check that styles are supported
372 if(m_text->GetStyle(3, style))
373 {
374 CPPUNIT_ASSERT_EQUAL(style.GetTextColour(), *wxRED);
375 CPPUNIT_ASSERT_EQUAL(style.GetBackgroundColour(), *wxWHITE);
376 }
377
378 // And then setting the style
379 if(m_text->SetStyle(15, 18, style))
380 {
381 m_text->GetStyle(17, style);
382
383 CPPUNIT_ASSERT_EQUAL(style.GetTextColour(), *wxRED);
384 CPPUNIT_ASSERT_EQUAL(style.GetBackgroundColour(), *wxWHITE);
385 }
386#endif
387}
388
389void TextCtrlTestCase::Lines()
390{
391#ifndef __WXOSX__
392 delete m_text;
393 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
394 wxDefaultPosition, wxSize(400, 200), wxTE_MULTILINE | wxTE_DONTWRAP);
395
396 m_text->SetValue("line1\nline2\nlong long line 3");
397 m_text->Refresh();
398 m_text->Update();
399
400 CPPUNIT_ASSERT_EQUAL(3, m_text->GetNumberOfLines());
401 CPPUNIT_ASSERT_EQUAL(5, m_text->GetLineLength(0));
402 CPPUNIT_ASSERT_EQUAL("line2", m_text->GetLineText(1));
403 CPPUNIT_ASSERT_EQUAL(16, m_text->GetLineLength(2));
404
405 m_text->AppendText("\n\nMore text on line 5");
406
407 CPPUNIT_ASSERT_EQUAL(5, m_text->GetNumberOfLines());
408 CPPUNIT_ASSERT_EQUAL(0, m_text->GetLineLength(3));
409 CPPUNIT_ASSERT_EQUAL("", m_text->GetLineText(3));
410#endif
411}
412
413void TextCtrlTestCase::LogTextCtrl()
414{
415 delete m_text;
416 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
417 wxDefaultPosition, wxSize(400, 200),
418 wxTE_MULTILINE);
419
420 CPPUNIT_ASSERT(m_text->IsEmpty());
421
422 wxLogTextCtrl* logtext = new wxLogTextCtrl(m_text);
423
424 wxLog* old = wxLog::SetActiveTarget(logtext);
425
426 logtext->LogText("text");
427
428 delete wxLog::SetActiveTarget(old);
429
430 CPPUNIT_ASSERT(!m_text->IsEmpty());
d911dc04
VZ
431}
432
6ce83213
VZ
433void TextCtrlTestCase::PositionToCoords()
434{
435 DoPositionToCoordsTestWithStyle(0);
436}
437
438void TextCtrlTestCase::PositionToCoordsRich()
439{
440 DoPositionToCoordsTestWithStyle(wxTE_RICH);
441}
442
443void TextCtrlTestCase::PositionToCoordsRich2()
444{
445 DoPositionToCoordsTestWithStyle(wxTE_RICH2);
446}
447
448void TextCtrlTestCase::DoPositionToCoordsTestWithStyle(long style)
449{
450 static const int TEXT_HEIGHT = 200;
451
452 delete m_text;
453 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
454 wxDefaultPosition, wxSize(400, TEXT_HEIGHT),
455 wxTE_MULTILINE | style);
456
457 // Asking for invalid index should fail.
458 WX_ASSERT_FAILS_WITH_ASSERT( m_text->PositionToCoords(1) );
459
460 // Getting position shouldn't return wxDefaultPosition except if the method
461 // is not implemented at all in the current port.
462 const wxPoint pos0 = m_text->PositionToCoords(0);
463 if ( pos0 == wxDefaultPosition )
464 {
465#if defined(__WXMSW__) || defined(__WXGTK20__)
466 CPPUNIT_FAIL( "PositionToCoords() unexpectedly failed." );
467#endif
468 return;
469 }
470
471 CPPUNIT_ASSERT(pos0.x >= 0);
472 CPPUNIT_ASSERT(pos0.y >= 0);
473
474
475 m_text->SetValue("Hello");
476 wxYield(); // Let GTK layout the control correctly.
477
478 // Position of non-first character should be positive.
479 const long posHello4 = m_text->PositionToCoords(4).x;
480 CPPUNIT_ASSERT( posHello4 > 0 );
481
482 // Asking for position beyond the last character should succeed and return
483 // reasonable result.
484 CPPUNIT_ASSERT( m_text->PositionToCoords(5).x > posHello4 );
485
486 // But asking for the next position should fail.
487 WX_ASSERT_FAILS_WITH_ASSERT( m_text->PositionToCoords(6) );
488
489 // Test getting the coordinates of the last character when it is in the
490 // beginning of a new line to exercise MSW code which has specific logic
491 // for it.
492 m_text->AppendText("\n");
493 const wxPoint posLast = m_text->PositionToCoords(m_text->GetLastPosition());
494 CPPUNIT_ASSERT_EQUAL( pos0.x, posLast.x );
495 CPPUNIT_ASSERT( posLast.y > 0 );
496
497
498 // Add enough contents to the control to make sure it has a scrollbar.
499 m_text->SetValue("First line" + wxString(50, '\n') + "Last line");
500 m_text->SetInsertionPoint(0);
501 wxYield(); // Let GTK layout the control correctly.
502
503 // This shouldn't change anything for the first position coordinates.
504 CPPUNIT_ASSERT_EQUAL( pos0, m_text->PositionToCoords(0) );
505
506 // And the last one must be beyond the window boundary and so not be
507 // visible -- but getting its coordinate should still work.
508 CPPUNIT_ASSERT
509 (
510 m_text->PositionToCoords(m_text->GetLastPosition()).y > TEXT_HEIGHT
511 );
512
513
514 // Now make it scroll to the end and check that the first position now has
515 // negative offset as its above the visible part of the window while the
516 // last position is in its bounds.
517 m_text->SetInsertionPointEnd();
518
519 CPPUNIT_ASSERT( m_text->PositionToCoords(0).y < 0 );
520 CPPUNIT_ASSERT
521 (
522 m_text->PositionToCoords(m_text->GetInsertionPoint()).y <= TEXT_HEIGHT
523 );
524}
525
526
232fdc63 527#endif //wxUSE_TEXTCTRL