]> git.saurik.com Git - wxWidgets.git/blame - tests/controls/textctrltest.cpp
Update configure.in to use pkg_config to find the webkit hearers and libraries. Regen...
[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 );
be74a2a2 60 CPPUNIT_TEST( FontStyle );
232fdc63
VZ
61 CPPUNIT_TEST( Lines );
62 CPPUNIT_TEST( LogTextCtrl );
6ce83213
VZ
63 CPPUNIT_TEST( PositionToCoords );
64 CPPUNIT_TEST( PositionToCoordsRich );
65 CPPUNIT_TEST( PositionToCoordsRich2 );
c0d9b217
VZ
66 CPPUNIT_TEST_SUITE_END();
67
d911dc04 68 void MultiLineReplace();
232fdc63
VZ
69 void ReadOnly();
70 void MaxLength();
71 void StreamInput();
72 void Redirector();
73 //void ProcessEnter();
74 void Url();
75 void Style();
be74a2a2 76 void FontStyle();
232fdc63
VZ
77 void Lines();
78 void LogTextCtrl();
6ce83213
VZ
79 void PositionToCoords();
80 void PositionToCoordsRich();
81 void PositionToCoordsRich2();
82
83 void DoPositionToCoordsTestWithStyle(long style);
d911dc04 84
c0d9b217 85 wxTextCtrl *m_text;
c0d9b217
VZ
86
87 DECLARE_NO_COPY_CLASS(TextCtrlTestCase)
88};
89
90// register in the unnamed registry so that these tests are run by default
91CPPUNIT_TEST_SUITE_REGISTRATION( TextCtrlTestCase );
92
e3778b4d 93// also include in its own registry so that these tests can be run alone
c0d9b217
VZ
94CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( TextCtrlTestCase, "TextCtrlTestCase" );
95
96// ----------------------------------------------------------------------------
97// test initialization
98// ----------------------------------------------------------------------------
99
100void TextCtrlTestCase::setUp()
101{
102 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
103}
104
105void TextCtrlTestCase::tearDown()
106{
232fdc63 107 wxDELETE(m_text);
c0d9b217
VZ
108}
109
110// ----------------------------------------------------------------------------
111// tests themselves
112// ----------------------------------------------------------------------------
113
d911dc04
VZ
114void TextCtrlTestCase::MultiLineReplace()
115{
116 // we need a multiline control for this test so recreate it
117 delete m_text;
118 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
119 wxDefaultPosition, wxDefaultSize,
120 wxTE_MULTILINE);
121
122 m_text->SetValue("Hello replace\n"
123 "0123456789012");
124 m_text->SetInsertionPoint(0);
125
126 m_text->Replace(6, 13, "changed");
127
128 CPPUNIT_ASSERT_EQUAL("Hello changed\n"
129 "0123456789012",
130 m_text->GetValue());
131 CPPUNIT_ASSERT_EQUAL(13, m_text->GetInsertionPoint());
132
133 m_text->Replace(13, -1, "");
134 CPPUNIT_ASSERT_EQUAL("Hello changed", m_text->GetValue());
135 CPPUNIT_ASSERT_EQUAL(13, m_text->GetInsertionPoint());
232fdc63
VZ
136
137 delete m_text;
138 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
139}
140
141void TextCtrlTestCase::ReadOnly()
142{
143#if wxUSE_UIACTIONSIMULATOR
144 // we need a read only control for this test so recreate it
145 delete m_text;
146 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
147 wxDefaultPosition, wxDefaultSize,
148 wxTE_READONLY);
149
150 wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
151 wxTestableFrame);
152
153 EventCounter count(m_text, wxEVT_COMMAND_TEXT_UPDATED);
154
155 m_text->SetFocus();
156
157 wxUIActionSimulator sim;
158 sim.Text("abcdef");
159 wxYield();
160
161 CPPUNIT_ASSERT_EQUAL("", m_text->GetValue());
162 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount());
163
164 // SetEditable() is supposed to override wxTE_READONLY
165 m_text->SetEditable(true);
166
167 sim.Text("abcdef");
168 wxYield();
169
170 CPPUNIT_ASSERT_EQUAL("abcdef", m_text->GetValue());
171 CPPUNIT_ASSERT_EQUAL(6, frame->GetEventCount());
172
173 delete m_text;
174 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
175#endif
176}
177
178void TextCtrlTestCase::MaxLength()
179{
180#if wxUSE_UIACTIONSIMULATOR
181 wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
182 wxTestableFrame);
183
184 EventCounter count(m_text, wxEVT_COMMAND_TEXT_UPDATED);
185 EventCounter count1(m_text, wxEVT_COMMAND_TEXT_MAXLEN);
186
187 m_text->SetFocus();
188 m_text->SetMaxLength(10);
189
190 wxUIActionSimulator sim;
191 sim.Text("abcdef");
192 wxYield();
193
194 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_MAXLEN));
195
196 sim.Text("ghij");
197 wxYield();
198
199 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_MAXLEN));
200 CPPUNIT_ASSERT_EQUAL(10, frame->GetEventCount(wxEVT_COMMAND_TEXT_UPDATED));
201
202 sim.Text("k");
203 wxYield();
204
205 CPPUNIT_ASSERT_EQUAL(1, frame->GetEventCount(wxEVT_COMMAND_TEXT_MAXLEN));
206 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_UPDATED));
207
208 m_text->SetMaxLength(0);
209
210 sim.Text("k");
211 wxYield();
212
213 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_MAXLEN));
214 CPPUNIT_ASSERT_EQUAL(1, frame->GetEventCount(wxEVT_COMMAND_TEXT_UPDATED));
215#endif
216}
217
218void TextCtrlTestCase::StreamInput()
219{
220#ifndef __WXOSX__
8859c729
VZ
221 {
222 // Ensure we use decimal point and not a comma.
223 char * const locOld = setlocale(LC_NUMERIC, "C");
224 wxON_BLOCK_EXIT2( setlocale, (int)LC_NUMERIC, locOld );
225
226 *m_text << "stringinput"
227 << 10
228 << 1000L
229 << 3.14f
230 << 2.71
231 << 'a'
232 << L'b';
233 }
232fdc63
VZ
234
235 CPPUNIT_ASSERT_EQUAL("stringinput1010003.142.71ab", m_text->GetValue());
236
237 m_text->SetValue("");
238
239#if wxHAS_TEXT_WINDOW_STREAM
240
241 std::ostream stream(m_text);
242
243 // We don't test a wide character as this is not a wide stream
244 stream << "stringinput"
245 << 10
246 << 1000L
247 << 3.14f
248 << 2.71
249 << 'a';
250
251 stream.flush();
252
253 CPPUNIT_ASSERT_EQUAL("stringinput1010003.142.71a", m_text->GetValue());
254
8859c729
VZ
255#endif // wxHAS_TEXT_WINDOW_STREAM
256#endif // !__WXOSX__
232fdc63
VZ
257}
258
259void TextCtrlTestCase::Redirector()
260{
261#if wxHAS_TEXT_WINDOW_STREAM && wxUSE_STD_IOSTREAM
262
263 wxStreamToTextRedirector redirect(m_text);
264
265 std::cout << "stringinput"
266 << 10
267 << 1000L
268 << 3.14f
269 << 2.71
270 << 'a';
271
272 CPPUNIT_ASSERT_EQUAL("stringinput1010003.142.71a", m_text->GetValue());
273
274#endif
275}
276
277#if 0
278void TextCtrlTestCase::ProcessEnter()
279{
280#if wxUSE_UIACTIONSIMULATOR
281 wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
282 wxTestableFrame);
283
284 EventCounter count(m_text, wxEVT_COMMAND_TEXT_ENTER);
285
286 m_text->SetFocus();
287
288 wxUIActionSimulator sim;
289 sim.Char(WXK_RETURN);
290 wxYield();
291
292 CPPUNIT_ASSERT_EQUAL(0, frame->GetEventCount(wxEVT_COMMAND_TEXT_ENTER));
293
294 // we need a text control with wxTE_PROCESS_ENTER for this test
295 delete m_text;
296 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
297 wxDefaultPosition, wxDefaultSize,
298 wxTE_PROCESS_ENTER);
299
300 m_text->SetFocus();
301
302 sim.Char(WXK_RETURN);
303 wxYield();
304
305 CPPUNIT_ASSERT_EQUAL(1, frame->GetEventCount(wxEVT_COMMAND_TEXT_ENTER));
306#endif
307}
308#endif
309
310void TextCtrlTestCase::Url()
311{
312#if wxUSE_UIACTIONSIMULATOR && defined(__WXMSW__)
313 delete m_text;
314 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
315 wxDefaultPosition, wxDefaultSize,
316 wxTE_MULTILINE | wxTE_RICH | wxTE_AUTO_URL);
317
318 wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
319 wxTestableFrame);
320
321 EventCounter count(m_text, wxEVT_COMMAND_TEXT_URL);
322
323 m_text->AppendText("http://www.wxwidgets.org");
324
325 wxUIActionSimulator sim;
326 sim.MouseMove(m_text->ClientToScreen(wxPoint(5, 5)));
327 sim.MouseClick();
328 wxYield();
329
330 CPPUNIT_ASSERT_EQUAL(1, frame->GetEventCount());
331#endif
332}
333
334void TextCtrlTestCase::Style()
335{
336#ifndef __WXOSX__
337 delete m_text;
338 // We need wxTE_RICH under windows for style support
339 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
340 wxDefaultPosition, wxDefaultSize, wxTE_RICH);
341
342 // Red text on a white background
343 m_text->SetDefaultStyle(wxTextAttr(*wxRED, *wxWHITE));
344
345 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetTextColour(), *wxRED);
346 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetBackgroundColour(),
347 *wxWHITE);
348
349 m_text->AppendText("red on white ");
350
351 // Red text on a grey background
352 m_text->SetDefaultStyle(wxTextAttr(wxNullColour, *wxLIGHT_GREY));
353
354 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetTextColour(), *wxRED);
355 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetBackgroundColour(),
356 *wxLIGHT_GREY);
357
358 m_text->AppendText("red on grey ");
359
360 // Blue text on a grey background
361 m_text->SetDefaultStyle(wxTextAttr(*wxBLUE));
362
363
364 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetTextColour(), *wxBLUE);
365 CPPUNIT_ASSERT_EQUAL(m_text->GetDefaultStyle().GetBackgroundColour(),
366 *wxLIGHT_GREY);
367
368 m_text->AppendText("blue on grey");
369
370 // Get getting the style at a specific location
371 wxTextAttr style;
372
373 // We have to check that styles are supported
374 if(m_text->GetStyle(3, style))
375 {
376 CPPUNIT_ASSERT_EQUAL(style.GetTextColour(), *wxRED);
377 CPPUNIT_ASSERT_EQUAL(style.GetBackgroundColour(), *wxWHITE);
378 }
379
380 // And then setting the style
381 if(m_text->SetStyle(15, 18, style))
382 {
383 m_text->GetStyle(17, style);
384
385 CPPUNIT_ASSERT_EQUAL(style.GetTextColour(), *wxRED);
386 CPPUNIT_ASSERT_EQUAL(style.GetBackgroundColour(), *wxWHITE);
387 }
388#endif
389}
390
be74a2a2
VZ
391void TextCtrlTestCase::FontStyle()
392{
393 // We need wxTE_RICH under MSW and wxTE_MULTILINE under GTK for style
394 // support so recreate the control with these styles.
395 delete m_text;
396 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
397 wxDefaultPosition, wxDefaultSize,
398 wxTE_MULTILINE | wxTE_RICH);
399
400 // Check that we get back the same font from GetStyle() after setting it
401 // with SetDefaultStyle().
402 wxFont fontIn(14,
403 wxFONTFAMILY_DEFAULT,
404 wxFONTSTYLE_NORMAL,
405 wxFONTWEIGHT_NORMAL);
406 wxTextAttr attrIn;
407 attrIn.SetFont(fontIn);
408 if ( !m_text->SetDefaultStyle(attrIn) )
409 {
410 // Skip the test if the styles are not supported.
411 return;
412 }
413
414 m_text->AppendText("Default font size 14");
415
416 wxTextAttr attrOut;
417 m_text->GetStyle(5, attrOut);
418
419 CPPUNIT_ASSERT( attrOut.HasFont() );
420
421 wxFont fontOut = attrOut.GetFont();
422#ifdef __WXMSW__
423 // Under MSW we get back an encoding in the font even though we hadn't
424 // specified it originally. It's not really a problem but we need this hack
425 // to prevent the assert below from failing because of it.
426 fontOut.SetEncoding(fontIn.GetEncoding());
427#endif
428 CPPUNIT_ASSERT_EQUAL( fontIn, fontOut );
429
430
431 // Also check the same for SetStyle().
432 fontIn.SetPointSize(10);
433 fontIn.SetWeight(wxFONTWEIGHT_BOLD);
434 attrIn.SetFont(fontIn);
435 m_text->SetStyle(0, 6, attrIn);
436
437 m_text->GetStyle(4, attrOut);
438 CPPUNIT_ASSERT( attrOut.HasFont() );
439
440 fontOut = attrOut.GetFont();
441#ifdef __WXMSW__
442 fontOut.SetEncoding(fontIn.GetEncoding());
443#endif
444 CPPUNIT_ASSERT_EQUAL( fontIn, fontOut );
445}
446
232fdc63
VZ
447void TextCtrlTestCase::Lines()
448{
232fdc63
VZ
449 delete m_text;
450 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
bfbd873b 451 wxDefaultPosition, wxSize(400, 200), wxTE_MULTILINE);
232fdc63
VZ
452
453 m_text->SetValue("line1\nline2\nlong long line 3");
454 m_text->Refresh();
455 m_text->Update();
456
457 CPPUNIT_ASSERT_EQUAL(3, m_text->GetNumberOfLines());
458 CPPUNIT_ASSERT_EQUAL(5, m_text->GetLineLength(0));
459 CPPUNIT_ASSERT_EQUAL("line2", m_text->GetLineText(1));
460 CPPUNIT_ASSERT_EQUAL(16, m_text->GetLineLength(2));
461
462 m_text->AppendText("\n\nMore text on line 5");
463
464 CPPUNIT_ASSERT_EQUAL(5, m_text->GetNumberOfLines());
465 CPPUNIT_ASSERT_EQUAL(0, m_text->GetLineLength(3));
466 CPPUNIT_ASSERT_EQUAL("", m_text->GetLineText(3));
567e5e47
VZ
467
468 // Verify that wrapped lines count as 2 lines.
469 //
470 // This currently doesn't work neither in wxGTK nor wxOSX/Cocoa, see
471 // #12366, where GetNumberOfLines() always returns the number of logical,
472 // not physical, lines.
473 m_text->AppendText("\n" + wxString(50, '1') + ' ' + wxString(50, '2'));
474#if defined(__WXGTK__) || defined(__WXOSX_COCOA__)
475 CPPUNIT_ASSERT_EQUAL(6, m_text->GetNumberOfLines());
476#else
477 CPPUNIT_ASSERT_EQUAL(7, m_text->GetNumberOfLines());
232fdc63
VZ
478#endif
479}
480
481void TextCtrlTestCase::LogTextCtrl()
482{
483 delete m_text;
484 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
485 wxDefaultPosition, wxSize(400, 200),
486 wxTE_MULTILINE);
487
488 CPPUNIT_ASSERT(m_text->IsEmpty());
489
490 wxLogTextCtrl* logtext = new wxLogTextCtrl(m_text);
491
492 wxLog* old = wxLog::SetActiveTarget(logtext);
493
494 logtext->LogText("text");
495
496 delete wxLog::SetActiveTarget(old);
497
498 CPPUNIT_ASSERT(!m_text->IsEmpty());
d911dc04
VZ
499}
500
6ce83213
VZ
501void TextCtrlTestCase::PositionToCoords()
502{
503 DoPositionToCoordsTestWithStyle(0);
504}
505
506void TextCtrlTestCase::PositionToCoordsRich()
507{
508 DoPositionToCoordsTestWithStyle(wxTE_RICH);
509}
510
511void TextCtrlTestCase::PositionToCoordsRich2()
512{
513 DoPositionToCoordsTestWithStyle(wxTE_RICH2);
514}
515
516void TextCtrlTestCase::DoPositionToCoordsTestWithStyle(long style)
517{
518 static const int TEXT_HEIGHT = 200;
519
520 delete m_text;
521 m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
522 wxDefaultPosition, wxSize(400, TEXT_HEIGHT),
523 wxTE_MULTILINE | style);
524
525 // Asking for invalid index should fail.
526 WX_ASSERT_FAILS_WITH_ASSERT( m_text->PositionToCoords(1) );
527
528 // Getting position shouldn't return wxDefaultPosition except if the method
529 // is not implemented at all in the current port.
530 const wxPoint pos0 = m_text->PositionToCoords(0);
531 if ( pos0 == wxDefaultPosition )
532 {
533#if defined(__WXMSW__) || defined(__WXGTK20__)
534 CPPUNIT_FAIL( "PositionToCoords() unexpectedly failed." );
535#endif
536 return;
537 }
538
539 CPPUNIT_ASSERT(pos0.x >= 0);
540 CPPUNIT_ASSERT(pos0.y >= 0);
541
542
543 m_text->SetValue("Hello");
544 wxYield(); // Let GTK layout the control correctly.
545
546 // Position of non-first character should be positive.
547 const long posHello4 = m_text->PositionToCoords(4).x;
548 CPPUNIT_ASSERT( posHello4 > 0 );
549
550 // Asking for position beyond the last character should succeed and return
551 // reasonable result.
552 CPPUNIT_ASSERT( m_text->PositionToCoords(5).x > posHello4 );
553
554 // But asking for the next position should fail.
555 WX_ASSERT_FAILS_WITH_ASSERT( m_text->PositionToCoords(6) );
556
557 // Test getting the coordinates of the last character when it is in the
558 // beginning of a new line to exercise MSW code which has specific logic
559 // for it.
560 m_text->AppendText("\n");
561 const wxPoint posLast = m_text->PositionToCoords(m_text->GetLastPosition());
562 CPPUNIT_ASSERT_EQUAL( pos0.x, posLast.x );
563 CPPUNIT_ASSERT( posLast.y > 0 );
564
565
566 // Add enough contents to the control to make sure it has a scrollbar.
567 m_text->SetValue("First line" + wxString(50, '\n') + "Last line");
568 m_text->SetInsertionPoint(0);
569 wxYield(); // Let GTK layout the control correctly.
570
571 // This shouldn't change anything for the first position coordinates.
572 CPPUNIT_ASSERT_EQUAL( pos0, m_text->PositionToCoords(0) );
573
574 // And the last one must be beyond the window boundary and so not be
575 // visible -- but getting its coordinate should still work.
576 CPPUNIT_ASSERT
577 (
578 m_text->PositionToCoords(m_text->GetLastPosition()).y > TEXT_HEIGHT
579 );
580
581
582 // Now make it scroll to the end and check that the first position now has
583 // negative offset as its above the visible part of the window while the
584 // last position is in its bounds.
585 m_text->SetInsertionPointEnd();
586
587 CPPUNIT_ASSERT( m_text->PositionToCoords(0).y < 0 );
588 CPPUNIT_ASSERT
589 (
590 m_text->PositionToCoords(m_text->GetInsertionPoint()).y <= TEXT_HEIGHT
591 );
592}
593
594
232fdc63 595#endif //wxUSE_TEXTCTRL