]> git.saurik.com Git - wxWidgets.git/blob - src/common/textcmn.cpp
don't use dynamic handlers for standard buttons as this prevents static event handler...
[wxWidgets.git] / src / common / textcmn.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/textcmn.cpp
3 // Purpose: implementation of platform-independent functions of wxTextCtrl
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 13.07.99
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // for compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/event.h"
25 #endif // WX_PRECOMP
26
27 #if wxUSE_TEXTCTRL
28
29 #include "wx/textctrl.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/intl.h"
33 #include "wx/log.h"
34 #endif // WX_PRECOMP
35
36 #include "wx/ffile.h"
37
38 // ----------------------------------------------------------------------------
39 // macros
40 // ----------------------------------------------------------------------------
41
42 // we don't have any objects of type wxTextCtrlBase in the program, only
43 // wxTextCtrl, so this cast is safe
44 #define TEXTCTRL(ptr) ((wxTextCtrl *)(ptr))
45
46 // ============================================================================
47 // implementation
48 // ============================================================================
49
50 IMPLEMENT_DYNAMIC_CLASS(wxTextUrlEvent, wxCommandEvent)
51
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER)
54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_URL)
55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_MAXLEN)
56
57 IMPLEMENT_ABSTRACT_CLASS(wxTextCtrlBase, wxControl)
58
59 // ----------------------------------------------------------------------------
60 // style functions - not implemented here
61 // ----------------------------------------------------------------------------
62
63 wxTextAttr::wxTextAttr(const wxColour& colText,
64 const wxColour& colBack,
65 const wxFont& font,
66 wxTextAttrAlignment alignment)
67 : m_colText(colText), m_colBack(colBack), m_font(font), m_textAlignment(alignment)
68 {
69 m_flags = 0;
70 m_leftIndent = 0;
71 m_leftSubIndent = 0;
72 m_rightIndent = 0;
73 if (m_colText.Ok()) m_flags |= wxTEXT_ATTR_TEXT_COLOUR;
74 if (m_colBack.Ok()) m_flags |= wxTEXT_ATTR_BACKGROUND_COLOUR;
75 if (m_font.Ok()) m_flags |= wxTEXT_ATTR_FONT;
76 if (alignment != wxTEXT_ALIGNMENT_DEFAULT)
77 m_flags |= wxTEXT_ATTR_ALIGNMENT;
78 }
79
80 void wxTextAttr::Init()
81 {
82 m_textAlignment = wxTEXT_ALIGNMENT_DEFAULT;
83 m_flags = 0;
84 m_leftIndent = 0;
85 m_leftSubIndent = 0;
86 m_rightIndent = 0;
87 }
88
89 /* static */
90 wxTextAttr wxTextAttr::Combine(const wxTextAttr& attr,
91 const wxTextAttr& attrDef,
92 const wxTextCtrlBase *text)
93 {
94 wxFont font = attr.GetFont();
95 if ( !font.Ok() )
96 {
97 font = attrDef.GetFont();
98
99 if ( text && !font.Ok() )
100 font = text->GetFont();
101 }
102
103 wxColour colFg = attr.GetTextColour();
104 if ( !colFg.Ok() )
105 {
106 colFg = attrDef.GetTextColour();
107
108 if ( text && !colFg.Ok() )
109 colFg = text->GetForegroundColour();
110 }
111
112 wxColour colBg = attr.GetBackgroundColour();
113 if ( !colBg.Ok() )
114 {
115 colBg = attrDef.GetBackgroundColour();
116
117 if ( text && !colBg.Ok() )
118 colBg = text->GetBackgroundColour();
119 }
120
121 wxTextAttr newAttr(colFg, colBg, font);
122
123 if (attr.HasAlignment())
124 newAttr.SetAlignment(attr.GetAlignment());
125 else if (attrDef.HasAlignment())
126 newAttr.SetAlignment(attrDef.GetAlignment());
127
128 if (attr.HasTabs())
129 newAttr.SetTabs(attr.GetTabs());
130 else if (attrDef.HasTabs())
131 newAttr.SetTabs(attrDef.GetTabs());
132
133 if (attr.HasLeftIndent())
134 newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
135 else if (attrDef.HasLeftIndent())
136 newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent());
137
138 if (attr.HasRightIndent())
139 newAttr.SetRightIndent(attr.GetRightIndent());
140 else if (attrDef.HasRightIndent())
141 newAttr.SetRightIndent(attrDef.GetRightIndent());
142
143 return newAttr;
144 }
145
146 void wxTextAttr::operator= (const wxTextAttr& attr)
147 {
148 m_font = attr.m_font;
149 m_colText = attr.m_colText;
150 m_colBack = attr.m_colBack;
151 m_textAlignment = attr.m_textAlignment;
152 m_leftIndent = attr.m_leftIndent;
153 m_leftSubIndent = attr.m_leftSubIndent;
154 m_rightIndent = attr.m_rightIndent;
155 m_tabs = attr.m_tabs;
156 m_flags = attr.m_flags;
157 }
158
159
160 // apply styling to text range
161 bool wxTextCtrlBase::SetStyle(long WXUNUSED(start), long WXUNUSED(end),
162 const wxTextAttr& WXUNUSED(style))
163 {
164 // to be implemented in derived TextCtrl classes
165 return false;
166 }
167
168 // get the styling at the given position
169 bool wxTextCtrlBase::GetStyle(long WXUNUSED(position), wxTextAttr& WXUNUSED(style))
170 {
171 // to be implemented in derived TextCtrl classes
172 return false;
173 }
174
175 // change default text attributes
176 bool wxTextCtrlBase::SetDefaultStyle(const wxTextAttr& style)
177 {
178 // keep the old attributes if the new style doesn't specify them unless the
179 // new style is empty - then reset m_defaultStyle (as there is no other way
180 // to do it)
181 if ( style.IsDefault() )
182 m_defaultStyle = style;
183 else
184 m_defaultStyle = wxTextAttr::Combine(style, m_defaultStyle, this);
185
186 return true;
187 }
188
189 // get default text attributes
190 const wxTextAttr& wxTextCtrlBase::GetDefaultStyle() const
191 {
192 return m_defaultStyle;
193 }
194
195 // ----------------------------------------------------------------------------
196 // file IO functions
197 // ----------------------------------------------------------------------------
198
199 bool wxTextCtrlBase::LoadFile(const wxString& filename)
200 {
201 #if wxUSE_FFILE
202 wxFFile file(filename);
203 if ( file.IsOpened() )
204 {
205 wxString text;
206 if ( file.ReadAll(&text) )
207 {
208 SetValue(text);
209
210 DiscardEdits();
211
212 m_filename = filename;
213
214 return true;
215 }
216 }
217
218 wxLogError(_("File couldn't be loaded."));
219 #endif // wxUSE_FFILE
220
221 return false;
222 }
223
224 bool wxTextCtrlBase::SaveFile(const wxString& filename)
225 {
226 wxString filenameToUse = filename.empty() ? m_filename : filename;
227 if ( filenameToUse.empty() )
228 {
229 // what kind of message to give? is it an error or a program bug?
230 wxLogDebug(wxT("Can't save textctrl to file without filename."));
231
232 return false;
233 }
234
235 #if wxUSE_FFILE
236 wxFFile file(filenameToUse, _T("w"));
237 if ( file.IsOpened() && file.Write(GetValue()) )
238 {
239 // it's not modified any longer
240 DiscardEdits();
241
242 // if it worked, save for future calls
243 m_filename = filenameToUse;
244
245 return true;
246 }
247 #endif // wxUSE_FFILE
248
249 wxLogError(_("The text couldn't be saved."));
250
251 return false;
252 }
253
254 // ----------------------------------------------------------------------------
255 // stream-like insertion operator
256 // ----------------------------------------------------------------------------
257
258 wxTextCtrl& wxTextCtrlBase::operator<<(const wxString& s)
259 {
260 AppendText(s);
261 return *TEXTCTRL(this);
262 }
263
264 wxTextCtrl& wxTextCtrlBase::operator<<(float f)
265 {
266 wxString str;
267 str.Printf(wxT("%.2f"), f);
268 AppendText(str);
269 return *TEXTCTRL(this);
270 }
271
272 wxTextCtrl& wxTextCtrlBase::operator<<(double d)
273 {
274 wxString str;
275 str.Printf(wxT("%.2f"), d);
276 AppendText(str);
277 return *TEXTCTRL(this);
278 }
279
280 wxTextCtrl& wxTextCtrlBase::operator<<(int i)
281 {
282 wxString str;
283 str.Printf(wxT("%d"), i);
284 AppendText(str);
285 return *TEXTCTRL(this);
286 }
287
288 wxTextCtrl& wxTextCtrlBase::operator<<(long i)
289 {
290 wxString str;
291 str.Printf(wxT("%ld"), i);
292 AppendText(str);
293 return *TEXTCTRL(this);
294 }
295
296 wxTextCtrl& wxTextCtrlBase::operator<<(const wxChar c)
297 {
298 return operator<<(wxString(c));
299 }
300
301 // ----------------------------------------------------------------------------
302 // streambuf methods implementation
303 // ----------------------------------------------------------------------------
304
305 #if wxHAS_TEXT_WINDOW_STREAM
306
307 int wxTextCtrlBase::overflow(int c)
308 {
309 AppendText((wxChar)c);
310
311 // return something different from EOF
312 return 0;
313 }
314
315 #endif // wxHAS_TEXT_WINDOW_STREAM
316
317 // ----------------------------------------------------------------------------
318 // clipboard stuff
319 // ----------------------------------------------------------------------------
320
321 bool wxTextCtrlBase::CanCopy() const
322 {
323 // can copy if there's a selection
324 long from, to;
325 GetSelection(&from, &to);
326 return from != to;
327 }
328
329 bool wxTextCtrlBase::CanCut() const
330 {
331 // can cut if there's a selection and if we're not read only
332 return CanCopy() && IsEditable();
333 }
334
335 bool wxTextCtrlBase::CanPaste() const
336 {
337 // can paste if we are not read only
338 return IsEditable();
339 }
340
341 // ----------------------------------------------------------------------------
342 // emulating key presses
343 // ----------------------------------------------------------------------------
344
345 #ifdef __WIN32__
346 // the generic version is unused in wxMSW
347 bool wxTextCtrlBase::EmulateKeyPress(const wxKeyEvent& WXUNUSED(event))
348 {
349 return false;
350 }
351 #else // !__WIN32__
352 bool wxTextCtrlBase::EmulateKeyPress(const wxKeyEvent& event)
353 {
354 wxChar ch = 0;
355 int keycode = event.GetKeyCode();
356 switch ( keycode )
357 {
358 case WXK_NUMPAD0:
359 case WXK_NUMPAD1:
360 case WXK_NUMPAD2:
361 case WXK_NUMPAD3:
362 case WXK_NUMPAD4:
363 case WXK_NUMPAD5:
364 case WXK_NUMPAD6:
365 case WXK_NUMPAD7:
366 case WXK_NUMPAD8:
367 case WXK_NUMPAD9:
368 ch = (wxChar)(_T('0') + keycode - WXK_NUMPAD0);
369 break;
370
371 case WXK_MULTIPLY:
372 case WXK_NUMPAD_MULTIPLY:
373 ch = _T('*');
374 break;
375
376 case WXK_ADD:
377 case WXK_NUMPAD_ADD:
378 ch = _T('+');
379 break;
380
381 case WXK_SUBTRACT:
382 case WXK_NUMPAD_SUBTRACT:
383 ch = _T('-');
384 break;
385
386 case WXK_DECIMAL:
387 case WXK_NUMPAD_DECIMAL:
388 ch = _T('.');
389 break;
390
391 case WXK_DIVIDE:
392 case WXK_NUMPAD_DIVIDE:
393 ch = _T('/');
394 break;
395
396 case WXK_DELETE:
397 case WXK_NUMPAD_DELETE:
398 // delete the character at cursor
399 {
400 const long pos = GetInsertionPoint();
401 if ( pos < GetLastPosition() )
402 Remove(pos, pos + 1);
403 }
404 break;
405
406 case WXK_BACK:
407 // delete the character before the cursor
408 {
409 const long pos = GetInsertionPoint();
410 if ( pos > 0 )
411 Remove(pos - 1, pos);
412 }
413 break;
414
415 default:
416 #if wxUSE_UNICODE
417 if ( event.GetUnicodeKey() )
418 {
419 ch = event.GetUnicodeKey();
420 }
421 else
422 #endif
423 if ( keycode < 256 && keycode >= 0 && wxIsprint(keycode) )
424 {
425 // FIXME this is not going to work for non letters...
426 if ( !event.ShiftDown() )
427 {
428 keycode = wxTolower(keycode);
429 }
430
431 ch = (wxChar)keycode;
432 }
433 else
434 {
435 ch = _T('\0');
436 }
437 }
438
439 if ( ch )
440 {
441 WriteText(ch);
442
443 return true;
444 }
445
446 return false;
447 }
448 #endif // !__WIN32__
449
450 // ----------------------------------------------------------------------------
451 // selection and ranges
452 // ----------------------------------------------------------------------------
453
454 void wxTextCtrlBase::SelectAll()
455 {
456 SetSelection(0, GetLastPosition());
457 }
458
459 wxString wxTextCtrlBase::GetStringSelection() const
460 {
461 long from, to;
462 GetSelection(&from, &to);
463
464 return GetRange(from, to);
465 }
466
467 wxString wxTextCtrlBase::GetRange(long from, long to) const
468 {
469 wxString sel;
470 if ( from < to )
471 {
472 sel = GetValue().Mid(from, to - from);
473 }
474
475 return sel;
476 }
477
478 // do the window-specific processing after processing the update event
479 void wxTextCtrlBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
480 {
481 // call inherited, but skip the wxControl's version, and call directly the
482 // wxWindow's one instead, because the only reason why we are overriding this
483 // function is that we want to use SetValue() instead of wxControl::SetLabel()
484 wxWindowBase::DoUpdateWindowUI(event);
485
486 // update text
487 if ( event.GetSetText() )
488 {
489 if ( event.GetText() != GetValue() )
490 SetValue(event.GetText());
491 }
492 }
493
494 // ----------------------------------------------------------------------------
495 // hit testing
496 // ----------------------------------------------------------------------------
497
498 wxTextCtrlHitTestResult
499 wxTextCtrlBase::HitTest(const wxPoint& pt, wxTextCoord *x, wxTextCoord *y) const
500 {
501 // implement in terms of the other overload as the native ports typically
502 // can get the position and not (x, y) pair directly (although wxUniv
503 // directly gets x and y -- and so overrides this method as well)
504 long pos;
505 wxTextCtrlHitTestResult rc = HitTest(pt, &pos);
506
507 if ( rc != wxTE_HT_UNKNOWN )
508 {
509 PositionToXY(pos, x, y);
510 }
511
512 return rc;
513 }
514
515 wxTextCtrlHitTestResult
516 wxTextCtrlBase::HitTest(const wxPoint& WXUNUSED(pt),
517 long * WXUNUSED(pos)) const
518 {
519 // not implemented
520 return wxTE_HT_UNKNOWN;
521 }
522
523 #else // !wxUSE_TEXTCTRL
524
525 // define this one even if !wxUSE_TEXTCTRL because it is also used by other
526 // controls (wxComboBox and wxSpinCtrl)
527
528 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED)
529
530 #endif // wxUSE_TEXTCTRL/!wxUSE_TEXTCTRL