Don't support this compiler any more, this allows to get rid of tons of MSVC6-specific workarounds, in particular we can now use Bind() and natural template functions calls in the library code. Also remove MSVC6 project and solution files and don't generate them when bakefile_gen is ran any more (removing the remaining occurrences of msvc6prj from the bakefiles results in weird bake-time errors, so it's simpler to just leave them there). git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76532 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
413 lines
11 KiB
C++
413 lines
11 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/textentrycmn.cpp
|
|
// Purpose: wxTextEntryBase implementation
|
|
// Author: Vadim Zeitlin
|
|
// Created: 2007-09-26
|
|
// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// for compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_TEXTCTRL || wxUSE_COMBOBOX
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/window.h"
|
|
#include "wx/dataobj.h"
|
|
#endif //WX_PRECOMP
|
|
|
|
#include "wx/textentry.h"
|
|
#include "wx/textcompleter.h"
|
|
#include "wx/clipbrd.h"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxTextEntryHintData
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class WXDLLIMPEXP_CORE wxTextEntryHintData
|
|
{
|
|
public:
|
|
wxTextEntryHintData(wxTextEntryBase *entry, wxWindow *win)
|
|
: m_entry(entry),
|
|
m_win(win),
|
|
m_text(m_entry->GetValue())
|
|
{
|
|
win->Bind(wxEVT_SET_FOCUS, &wxTextEntryHintData::OnSetFocus, this);
|
|
win->Bind(wxEVT_KILL_FOCUS, &wxTextEntryHintData::OnKillFocus, this);
|
|
win->Bind(wxEVT_TEXT, &wxTextEntryHintData::OnTextChanged, this);
|
|
}
|
|
|
|
// default dtor is ok
|
|
|
|
// Get the real text of the control such as it was before we replaced it
|
|
// with the hint.
|
|
const wxString& GetText() const { return m_text; }
|
|
|
|
// Set the hint to show, shouldn't be empty normally.
|
|
//
|
|
// This should be called after creating a new wxTextEntryHintData object
|
|
// and may be called more times in the future.
|
|
void SetHintString(const wxString& hint)
|
|
{
|
|
m_hint = hint;
|
|
|
|
if ( !m_win->HasFocus() )
|
|
ShowHintIfAppropriate();
|
|
//else: The new hint will be shown later when we lose focus.
|
|
}
|
|
|
|
const wxString& GetHintString() const { return m_hint; }
|
|
|
|
// This is called whenever the text control contents changes.
|
|
//
|
|
// We call it ourselves when this change generates an event but it's also
|
|
// necessary to call it explicitly from wxTextEntry::ChangeValue() as it,
|
|
// by design, does not generate any events.
|
|
void HandleTextUpdate(const wxString& text)
|
|
{
|
|
m_text = text;
|
|
|
|
// If we're called because of a call to Set or ChangeValue(), the
|
|
// control may still have the hint text colour, reset it in this case.
|
|
RestoreTextColourIfNecessary();
|
|
}
|
|
|
|
private:
|
|
// Show the hint in the window if we should do it, i.e. if the window
|
|
// doesn't have any text of its own.
|
|
void ShowHintIfAppropriate()
|
|
{
|
|
// Never overwrite existing window text.
|
|
if ( !m_text.empty() )
|
|
return;
|
|
|
|
// Save the old text colour and set a more inconspicuous one for the
|
|
// hint.
|
|
m_colFg = m_win->GetForegroundColour();
|
|
m_win->SetForegroundColour(*wxLIGHT_GREY);
|
|
|
|
m_entry->DoSetValue(m_hint, wxTextEntryBase::SetValue_NoEvent);
|
|
}
|
|
|
|
// Restore the original text colour if we had changed it to show the hint
|
|
// and not restored it yet.
|
|
void RestoreTextColourIfNecessary()
|
|
{
|
|
if ( m_colFg.IsOk() )
|
|
{
|
|
m_win->SetForegroundColour(m_colFg);
|
|
m_colFg = wxColour();
|
|
}
|
|
}
|
|
|
|
void OnSetFocus(wxFocusEvent& event)
|
|
{
|
|
// If we had been showing the hint before, remove it now and restore
|
|
// the normal colour.
|
|
if ( m_text.empty() )
|
|
{
|
|
RestoreTextColourIfNecessary();
|
|
|
|
m_entry->DoSetValue(wxString(), wxTextEntryBase::SetValue_NoEvent);
|
|
}
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
void OnKillFocus(wxFocusEvent& event)
|
|
{
|
|
// Restore the hint if the user didn't enter anything.
|
|
ShowHintIfAppropriate();
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
void OnTextChanged(wxCommandEvent& event)
|
|
{
|
|
// Update the stored window text.
|
|
//
|
|
// Notice that we can't use GetValue() nor wxCommandEvent::GetString()
|
|
// which uses it internally because this would just forward back to us
|
|
// so go directly to the private method which returns the real control
|
|
// contents.
|
|
HandleTextUpdate(m_entry->DoGetValue());
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
// the text control we're associated with (as its interface and its window)
|
|
wxTextEntryBase * const m_entry;
|
|
wxWindow * const m_win;
|
|
|
|
// the original foreground colour of m_win before we changed it
|
|
wxColour m_colFg;
|
|
|
|
// The hint passed to wxTextEntry::SetHint(), never empty.
|
|
wxString m_hint;
|
|
|
|
// The real text of the window.
|
|
wxString m_text;
|
|
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxTextEntryHintData);
|
|
};
|
|
|
|
// ============================================================================
|
|
// wxTextEntryBase implementation
|
|
// ============================================================================
|
|
|
|
wxTextEntryBase::~wxTextEntryBase()
|
|
{
|
|
delete m_hintData;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// text accessors
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxString wxTextEntryBase::GetValue() const
|
|
{
|
|
return m_hintData ? m_hintData->GetText() : DoGetValue();
|
|
}
|
|
|
|
wxString wxTextEntryBase::GetRange(long from, long to) const
|
|
{
|
|
wxString sel;
|
|
wxString value = GetValue();
|
|
|
|
if ( from < to && (long)value.length() >= to )
|
|
{
|
|
sel = value.substr(from, to - from);
|
|
}
|
|
|
|
return sel;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// text operations
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxTextEntryBase::ChangeValue(const wxString& value)
|
|
{
|
|
DoSetValue(value, SetValue_NoEvent);
|
|
|
|
// As we didn't generate any events for wxTextEntryHintData to catch,
|
|
// notify it explicitly about our changed contents.
|
|
if ( m_hintData )
|
|
m_hintData->HandleTextUpdate(value);
|
|
}
|
|
|
|
void wxTextEntryBase::AppendText(const wxString& text)
|
|
{
|
|
SetInsertionPointEnd();
|
|
WriteText(text);
|
|
}
|
|
|
|
void wxTextEntryBase::DoSetValue(const wxString& value, int flags)
|
|
{
|
|
if ( value != DoGetValue() )
|
|
{
|
|
EventsSuppressor noeventsIf(this, !(flags & SetValue_SendEvent));
|
|
|
|
SelectAll();
|
|
WriteText(value);
|
|
|
|
SetInsertionPoint(0);
|
|
}
|
|
else // Same value, no need to do anything.
|
|
{
|
|
// Except that we still need to generate the event for consistency with
|
|
// the normal case when the text does change.
|
|
if ( flags & SetValue_SendEvent )
|
|
SendTextUpdatedEvent(GetEditableWindow());
|
|
}
|
|
}
|
|
|
|
void wxTextEntryBase::Replace(long from, long to, const wxString& value)
|
|
{
|
|
{
|
|
EventsSuppressor noevents(this);
|
|
Remove(from, to);
|
|
}
|
|
|
|
SetInsertionPoint(from);
|
|
WriteText(value);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// selection
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool wxTextEntryBase::HasSelection() const
|
|
{
|
|
long from, to;
|
|
GetSelection(&from, &to);
|
|
|
|
return from < to;
|
|
}
|
|
|
|
void wxTextEntryBase::RemoveSelection()
|
|
{
|
|
long from, to;
|
|
GetSelection(& from, & to);
|
|
if (from != -1 && to != -1)
|
|
Remove(from, to);
|
|
}
|
|
|
|
wxString wxTextEntryBase::GetStringSelection() const
|
|
{
|
|
long from, to;
|
|
GetSelection(&from, &to);
|
|
|
|
return GetRange(from, to);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// clipboard
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool wxTextEntryBase::CanCopy() const
|
|
{
|
|
return HasSelection();
|
|
}
|
|
|
|
bool wxTextEntryBase::CanCut() const
|
|
{
|
|
return CanCopy() && IsEditable();
|
|
}
|
|
|
|
bool wxTextEntryBase::CanPaste() const
|
|
{
|
|
if ( IsEditable() )
|
|
{
|
|
#if wxUSE_CLIPBOARD
|
|
// check if there is any text on the clipboard
|
|
if ( wxTheClipboard->IsSupported(wxDF_TEXT)
|
|
#if wxUSE_UNICODE
|
|
|| wxTheClipboard->IsSupported(wxDF_UNICODETEXT)
|
|
#endif // wxUSE_UNICODE
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
#endif // wxUSE_CLIPBOARD
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// hints support
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool wxTextEntryBase::SetHint(const wxString& hint)
|
|
{
|
|
if ( !hint.empty() )
|
|
{
|
|
if ( !m_hintData )
|
|
m_hintData = new wxTextEntryHintData(this, GetEditableWindow());
|
|
|
|
m_hintData->SetHintString(hint);
|
|
}
|
|
else if ( m_hintData )
|
|
{
|
|
// Setting empty hint removes any currently set one.
|
|
delete m_hintData;
|
|
m_hintData = NULL;
|
|
}
|
|
//else: Setting empty hint when we don't have any doesn't do anything.
|
|
|
|
return true;
|
|
}
|
|
|
|
wxString wxTextEntryBase::GetHint() const
|
|
{
|
|
return m_hintData ? m_hintData->GetHintString() : wxString();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// margins support
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool wxTextEntryBase::DoSetMargins(const wxPoint& WXUNUSED(pt))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
wxPoint wxTextEntryBase::DoGetMargins() const
|
|
{
|
|
return wxPoint(-1, -1);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// events
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/* static */
|
|
bool wxTextEntryBase::SendTextUpdatedEvent(wxWindow *win)
|
|
{
|
|
wxCHECK_MSG( win, false, "can't send an event without a window" );
|
|
|
|
wxCommandEvent event(wxEVT_TEXT, win->GetId());
|
|
|
|
// do not do this as it could be very inefficient if the text control
|
|
// contains a lot of text and we're not using ref-counted wxString
|
|
// implementation -- instead, event.GetString() will query the control for
|
|
// its current text if needed
|
|
//event.SetString(win->GetValue());
|
|
|
|
event.SetEventObject(win);
|
|
return win->HandleWindowEvent(event);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// auto-completion stubs
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxTextCompleter::~wxTextCompleter()
|
|
{
|
|
}
|
|
|
|
bool wxTextCompleterSimple::Start(const wxString& prefix)
|
|
{
|
|
m_index = 0;
|
|
m_completions.clear();
|
|
GetCompletions(prefix, m_completions);
|
|
|
|
return !m_completions.empty();
|
|
}
|
|
|
|
wxString wxTextCompleterSimple::GetNext()
|
|
{
|
|
if ( m_index == m_completions.size() )
|
|
return wxString();
|
|
|
|
return m_completions[m_index++];
|
|
}
|
|
|
|
bool wxTextEntryBase::DoAutoCompleteCustom(wxTextCompleter *completer)
|
|
{
|
|
// We don't do anything here but we still need to delete the completer for
|
|
// consistency with the ports that do implement this method and take
|
|
// ownership of the pointer.
|
|
delete completer;
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX
|