1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/textentrycmn.cpp
3 // Purpose: wxTextEntryBase implementation
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
26 #if wxUSE_TEXTCTRL || wxUSE_COMBOBOX
29 #include "wx/window.h"
30 #include "wx/dataobj.h"
33 #include "wx/textentry.h"
34 #include "wx/textcompleter.h"
35 #include "wx/clipbrd.h"
37 // ----------------------------------------------------------------------------
38 // wxTextEntryHintData
39 // ----------------------------------------------------------------------------
41 class WXDLLIMPEXP_CORE wxTextEntryHintData wxBIND_OR_CONNECT_HACK_ONLY_BASE_CLASS
44 wxTextEntryHintData(wxTextEntryBase
*entry
, wxWindow
*win
)
47 m_text(m_entry
->GetValue())
49 wxBIND_OR_CONNECT_HACK(win
, wxEVT_SET_FOCUS
, wxFocusEventHandler
,
50 wxTextEntryHintData::OnSetFocus
, this);
51 wxBIND_OR_CONNECT_HACK(win
, wxEVT_KILL_FOCUS
, wxFocusEventHandler
,
52 wxTextEntryHintData::OnKillFocus
, this);
53 wxBIND_OR_CONNECT_HACK(win
, wxEVT_COMMAND_TEXT_UPDATED
,
54 wxCommandEventHandler
,
55 wxTextEntryHintData::OnTextChanged
, this);
60 // Get the real text of the control such as it was before we replaced it
62 const wxString
& GetText() const { return m_text
; }
64 // Set the hint to show, shouldn't be empty normally.
66 // This should be called after creating a new wxTextEntryHintData object
67 // and may be called more times in the future.
68 void SetHintString(const wxString
& hint
)
72 if ( !m_win
->HasFocus() )
73 ShowHintIfAppropriate();
74 //else: The new hint will be shown later when we lose focus.
77 const wxString
& GetHintString() const { return m_hint
; }
79 // This is called whenever the text control contents changes.
81 // We call it ourselves when this change generates an event but it's also
82 // necessary to call it explicitly from wxTextEntry::ChangeValue() as it,
83 // by design, does not generate any events.
84 void HandleTextUpdate(const wxString
& text
)
88 // If we're called because of a call to Set or ChangeValue(), the
89 // control may still have the hint text colour, reset it in this case.
90 RestoreTextColourIfNecessary();
94 // Show the hint in the window if we should do it, i.e. if the window
95 // doesn't have any text of its own.
96 void ShowHintIfAppropriate()
98 // Never overwrite existing window text.
99 if ( !m_text
.empty() )
102 // Save the old text colour and set a more inconspicuous one for the
104 m_colFg
= m_win
->GetForegroundColour();
105 m_win
->SetForegroundColour(*wxLIGHT_GREY
);
107 m_entry
->DoSetValue(m_hint
, wxTextEntryBase::SetValue_NoEvent
);
110 // Restore the original text colour if we had changed it to show the hint
111 // and not restored it yet.
112 void RestoreTextColourIfNecessary()
114 if ( m_colFg
.IsOk() )
116 m_win
->SetForegroundColour(m_colFg
);
117 m_colFg
= wxColour();
121 void OnSetFocus(wxFocusEvent
& event
)
123 // If we had been showing the hint before, remove it now and restore
124 // the normal colour.
125 if ( m_text
.empty() )
127 RestoreTextColourIfNecessary();
129 m_entry
->DoSetValue(wxString(), wxTextEntryBase::SetValue_NoEvent
);
135 void OnKillFocus(wxFocusEvent
& event
)
137 // Restore the hint if the user didn't enter anything.
138 ShowHintIfAppropriate();
143 void OnTextChanged(wxCommandEvent
& event
)
145 // Update the stored window text.
147 // Notice that we can't use GetValue() nor wxCommandEvent::GetString()
148 // which uses it internally because this would just forward back to us
149 // so go directly to the private method which returns the real control
151 HandleTextUpdate(m_entry
->DoGetValue());
157 // the text control we're associated with (as its interface and its window)
158 wxTextEntryBase
* const m_entry
;
159 wxWindow
* const m_win
;
161 // the original foreground colour of m_win before we changed it
164 // The hint passed to wxTextEntry::SetHint(), never empty.
167 // The real text of the window.
171 wxDECLARE_NO_COPY_CLASS(wxTextEntryHintData
);
174 // ============================================================================
175 // wxTextEntryBase implementation
176 // ============================================================================
178 wxTextEntryBase::~wxTextEntryBase()
183 // ----------------------------------------------------------------------------
185 // ----------------------------------------------------------------------------
187 wxString
wxTextEntryBase::GetValue() const
189 return m_hintData
? m_hintData
->GetText() : DoGetValue();
192 wxString
wxTextEntryBase::GetRange(long from
, long to
) const
195 wxString value
= GetValue();
197 if ( from
< to
&& (long)value
.length() >= to
)
199 sel
= value
.substr(from
, to
- from
);
205 // ----------------------------------------------------------------------------
207 // ----------------------------------------------------------------------------
209 void wxTextEntryBase::ChangeValue(const wxString
& value
)
211 DoSetValue(value
, SetValue_NoEvent
);
213 // As we didn't generate any events for wxTextEntryHintData to catch,
214 // notify it explicitly about our changed contents.
216 m_hintData
->HandleTextUpdate(value
);
219 void wxTextEntryBase::AppendText(const wxString
& text
)
221 SetInsertionPointEnd();
225 void wxTextEntryBase::DoSetValue(const wxString
& value
, int flags
)
227 if ( value
!= DoGetValue() )
229 EventsSuppressor
noeventsIf(this, !(flags
& SetValue_SendEvent
));
234 else // Same value, no need to do anything.
236 // Except that we still need to generate the event for consistency with
237 // the normal case when the text does change.
238 if ( flags
& SetValue_SendEvent
)
239 SendTextUpdatedEvent(GetEditableWindow());
242 SetInsertionPoint(0);
245 void wxTextEntryBase::Replace(long from
, long to
, const wxString
& value
)
248 EventsSuppressor
noevents(this);
252 SetInsertionPoint(from
);
256 // ----------------------------------------------------------------------------
258 // ----------------------------------------------------------------------------
260 bool wxTextEntryBase::HasSelection() const
263 GetSelection(&from
, &to
);
268 void wxTextEntryBase::RemoveSelection()
271 GetSelection(& from
, & to
);
272 if (from
!= -1 && to
!= -1)
276 wxString
wxTextEntryBase::GetStringSelection() const
279 GetSelection(&from
, &to
);
281 return GetRange(from
, to
);
284 // ----------------------------------------------------------------------------
286 // ----------------------------------------------------------------------------
288 bool wxTextEntryBase::CanCopy() const
290 return HasSelection();
293 bool wxTextEntryBase::CanCut() const
295 return CanCopy() && IsEditable();
298 bool wxTextEntryBase::CanPaste() const
303 // check if there is any text on the clipboard
304 if ( wxTheClipboard
->IsSupported(wxDF_TEXT
)
306 || wxTheClipboard
->IsSupported(wxDF_UNICODETEXT
)
307 #endif // wxUSE_UNICODE
312 #endif // wxUSE_CLIPBOARD
318 // ----------------------------------------------------------------------------
320 // ----------------------------------------------------------------------------
322 bool wxTextEntryBase::SetHint(const wxString
& hint
)
327 m_hintData
= new wxTextEntryHintData(this, GetEditableWindow());
329 m_hintData
->SetHintString(hint
);
331 else if ( m_hintData
)
333 // Setting empty hint removes any currently set one.
337 //else: Setting empty hint when we don't have any doesn't do anything.
342 wxString
wxTextEntryBase::GetHint() const
344 return m_hintData
? m_hintData
->GetHintString() : wxString();
347 // ----------------------------------------------------------------------------
349 // ----------------------------------------------------------------------------
351 bool wxTextEntryBase::DoSetMargins(const wxPoint
& WXUNUSED(pt
))
356 wxPoint
wxTextEntryBase::DoGetMargins() const
358 return wxPoint(-1, -1);
361 // ----------------------------------------------------------------------------
363 // ----------------------------------------------------------------------------
366 bool wxTextEntryBase::SendTextUpdatedEvent(wxWindow
*win
)
368 wxCHECK_MSG( win
, false, "can't send an event without a window" );
370 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, win
->GetId());
372 // do not do this as it could be very inefficient if the text control
373 // contains a lot of text and we're not using ref-counted wxString
374 // implementation -- instead, event.GetString() will query the control for
375 // its current text if needed
376 //event.SetString(win->GetValue());
378 event
.SetEventObject(win
);
379 return win
->HandleWindowEvent(event
);
382 // ----------------------------------------------------------------------------
383 // auto-completion stubs
384 // ----------------------------------------------------------------------------
386 wxTextCompleter::~wxTextCompleter()
390 bool wxTextCompleterSimple::Start(const wxString
& prefix
)
393 m_completions
.clear();
394 GetCompletions(prefix
, m_completions
);
396 return !m_completions
.empty();
399 wxString
wxTextCompleterSimple::GetNext()
401 if ( m_index
== m_completions
.size() )
404 return m_completions
[m_index
++];
407 bool wxTextEntryBase::DoAutoCompleteCustom(wxTextCompleter
*completer
)
409 // We don't do anything here but we still need to delete the completer for
410 // consistency with the ports that do implement this method and take
411 // ownership of the pointer.
417 #endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX