1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/textentrycmn.cpp
3 // Purpose: wxTextEntryBase implementation
4 // Author: Vadim Zeitlin
6 // Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
25 #if wxUSE_TEXTCTRL || wxUSE_COMBOBOX
28 #include "wx/window.h"
29 #include "wx/dataobj.h"
32 #include "wx/textentry.h"
33 #include "wx/textcompleter.h"
34 #include "wx/clipbrd.h"
36 // ----------------------------------------------------------------------------
37 // wxTextEntryHintData
38 // ----------------------------------------------------------------------------
40 class WXDLLIMPEXP_CORE wxTextEntryHintData wxBIND_OR_CONNECT_HACK_ONLY_BASE_CLASS
43 wxTextEntryHintData(wxTextEntryBase
*entry
, wxWindow
*win
)
46 m_text(m_entry
->GetValue())
48 wxBIND_OR_CONNECT_HACK(win
, wxEVT_SET_FOCUS
, wxFocusEventHandler
,
49 wxTextEntryHintData::OnSetFocus
, this);
50 wxBIND_OR_CONNECT_HACK(win
, wxEVT_KILL_FOCUS
, wxFocusEventHandler
,
51 wxTextEntryHintData::OnKillFocus
, this);
52 wxBIND_OR_CONNECT_HACK(win
, wxEVT_TEXT
,
53 wxCommandEventHandler
,
54 wxTextEntryHintData::OnTextChanged
, this);
59 // Get the real text of the control such as it was before we replaced it
61 const wxString
& GetText() const { return m_text
; }
63 // Set the hint to show, shouldn't be empty normally.
65 // This should be called after creating a new wxTextEntryHintData object
66 // and may be called more times in the future.
67 void SetHintString(const wxString
& hint
)
71 if ( !m_win
->HasFocus() )
72 ShowHintIfAppropriate();
73 //else: The new hint will be shown later when we lose focus.
76 const wxString
& GetHintString() const { return m_hint
; }
78 // This is called whenever the text control contents changes.
80 // We call it ourselves when this change generates an event but it's also
81 // necessary to call it explicitly from wxTextEntry::ChangeValue() as it,
82 // by design, does not generate any events.
83 void HandleTextUpdate(const wxString
& text
)
87 // If we're called because of a call to Set or ChangeValue(), the
88 // control may still have the hint text colour, reset it in this case.
89 RestoreTextColourIfNecessary();
93 // Show the hint in the window if we should do it, i.e. if the window
94 // doesn't have any text of its own.
95 void ShowHintIfAppropriate()
97 // Never overwrite existing window text.
98 if ( !m_text
.empty() )
101 // Save the old text colour and set a more inconspicuous one for the
103 m_colFg
= m_win
->GetForegroundColour();
104 m_win
->SetForegroundColour(*wxLIGHT_GREY
);
106 m_entry
->DoSetValue(m_hint
, wxTextEntryBase::SetValue_NoEvent
);
109 // Restore the original text colour if we had changed it to show the hint
110 // and not restored it yet.
111 void RestoreTextColourIfNecessary()
113 if ( m_colFg
.IsOk() )
115 m_win
->SetForegroundColour(m_colFg
);
116 m_colFg
= wxColour();
120 void OnSetFocus(wxFocusEvent
& event
)
122 // If we had been showing the hint before, remove it now and restore
123 // the normal colour.
124 if ( m_text
.empty() )
126 RestoreTextColourIfNecessary();
128 m_entry
->DoSetValue(wxString(), wxTextEntryBase::SetValue_NoEvent
);
134 void OnKillFocus(wxFocusEvent
& event
)
136 // Restore the hint if the user didn't enter anything.
137 ShowHintIfAppropriate();
142 void OnTextChanged(wxCommandEvent
& event
)
144 // Update the stored window text.
146 // Notice that we can't use GetValue() nor wxCommandEvent::GetString()
147 // which uses it internally because this would just forward back to us
148 // so go directly to the private method which returns the real control
150 HandleTextUpdate(m_entry
->DoGetValue());
156 // the text control we're associated with (as its interface and its window)
157 wxTextEntryBase
* const m_entry
;
158 wxWindow
* const m_win
;
160 // the original foreground colour of m_win before we changed it
163 // The hint passed to wxTextEntry::SetHint(), never empty.
166 // The real text of the window.
170 wxDECLARE_NO_COPY_CLASS(wxTextEntryHintData
);
173 // ============================================================================
174 // wxTextEntryBase implementation
175 // ============================================================================
177 wxTextEntryBase::~wxTextEntryBase()
182 // ----------------------------------------------------------------------------
184 // ----------------------------------------------------------------------------
186 wxString
wxTextEntryBase::GetValue() const
188 return m_hintData
? m_hintData
->GetText() : DoGetValue();
191 wxString
wxTextEntryBase::GetRange(long from
, long to
) const
194 wxString value
= GetValue();
196 if ( from
< to
&& (long)value
.length() >= to
)
198 sel
= value
.substr(from
, to
- from
);
204 // ----------------------------------------------------------------------------
206 // ----------------------------------------------------------------------------
208 void wxTextEntryBase::ChangeValue(const wxString
& value
)
210 DoSetValue(value
, SetValue_NoEvent
);
212 // As we didn't generate any events for wxTextEntryHintData to catch,
213 // notify it explicitly about our changed contents.
215 m_hintData
->HandleTextUpdate(value
);
218 void wxTextEntryBase::AppendText(const wxString
& text
)
220 SetInsertionPointEnd();
224 void wxTextEntryBase::DoSetValue(const wxString
& value
, int flags
)
226 if ( value
!= DoGetValue() )
228 EventsSuppressor
noeventsIf(this, !(flags
& SetValue_SendEvent
));
233 SetInsertionPoint(0);
235 else // Same value, no need to do anything.
237 // Except that we still need to generate the event for consistency with
238 // the normal case when the text does change.
239 if ( flags
& SetValue_SendEvent
)
240 SendTextUpdatedEvent(GetEditableWindow());
244 void wxTextEntryBase::Replace(long from
, long to
, const wxString
& value
)
247 EventsSuppressor
noevents(this);
251 SetInsertionPoint(from
);
255 // ----------------------------------------------------------------------------
257 // ----------------------------------------------------------------------------
259 bool wxTextEntryBase::HasSelection() const
262 GetSelection(&from
, &to
);
267 void wxTextEntryBase::RemoveSelection()
270 GetSelection(& from
, & to
);
271 if (from
!= -1 && to
!= -1)
275 wxString
wxTextEntryBase::GetStringSelection() const
278 GetSelection(&from
, &to
);
280 return GetRange(from
, to
);
283 // ----------------------------------------------------------------------------
285 // ----------------------------------------------------------------------------
287 bool wxTextEntryBase::CanCopy() const
289 return HasSelection();
292 bool wxTextEntryBase::CanCut() const
294 return CanCopy() && IsEditable();
297 bool wxTextEntryBase::CanPaste() const
302 // check if there is any text on the clipboard
303 if ( wxTheClipboard
->IsSupported(wxDF_TEXT
)
305 || wxTheClipboard
->IsSupported(wxDF_UNICODETEXT
)
306 #endif // wxUSE_UNICODE
311 #endif // wxUSE_CLIPBOARD
317 // ----------------------------------------------------------------------------
319 // ----------------------------------------------------------------------------
321 bool wxTextEntryBase::SetHint(const wxString
& hint
)
326 m_hintData
= new wxTextEntryHintData(this, GetEditableWindow());
328 m_hintData
->SetHintString(hint
);
330 else if ( m_hintData
)
332 // Setting empty hint removes any currently set one.
336 //else: Setting empty hint when we don't have any doesn't do anything.
341 wxString
wxTextEntryBase::GetHint() const
343 return m_hintData
? m_hintData
->GetHintString() : wxString();
346 // ----------------------------------------------------------------------------
348 // ----------------------------------------------------------------------------
350 bool wxTextEntryBase::DoSetMargins(const wxPoint
& WXUNUSED(pt
))
355 wxPoint
wxTextEntryBase::DoGetMargins() const
357 return wxPoint(-1, -1);
360 // ----------------------------------------------------------------------------
362 // ----------------------------------------------------------------------------
365 bool wxTextEntryBase::SendTextUpdatedEvent(wxWindow
*win
)
367 wxCHECK_MSG( win
, false, "can't send an event without a window" );
369 wxCommandEvent
event(wxEVT_TEXT
, win
->GetId());
371 // do not do this as it could be very inefficient if the text control
372 // contains a lot of text and we're not using ref-counted wxString
373 // implementation -- instead, event.GetString() will query the control for
374 // its current text if needed
375 //event.SetString(win->GetValue());
377 event
.SetEventObject(win
);
378 return win
->HandleWindowEvent(event
);
381 // ----------------------------------------------------------------------------
382 // auto-completion stubs
383 // ----------------------------------------------------------------------------
385 wxTextCompleter::~wxTextCompleter()
389 bool wxTextCompleterSimple::Start(const wxString
& prefix
)
392 m_completions
.clear();
393 GetCompletions(prefix
, m_completions
);
395 return !m_completions
.empty();
398 wxString
wxTextCompleterSimple::GetNext()
400 if ( m_index
== m_completions
.size() )
403 return m_completions
[m_index
++];
406 bool wxTextEntryBase::DoAutoCompleteCustom(wxTextCompleter
*completer
)
408 // We don't do anything here but we still need to delete the completer for
409 // consistency with the ports that do implement this method and take
410 // ownership of the pointer.
416 #endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX