\twocolwidtha{7cm}%
\begin{twocollist}\itemsep=0pt
\twocolitem{{\bf EVT\_TEXT(id, func)}}{Respond to a wxEVT\_COMMAND\_TEXT\_UPDATED event,
-generated when the text changes. Notice that this event will always be sent
+generated when the text changes. Notice that this event will be sent
when the text controls contents changes - whether this is due to user input or
-comes from the program itself (for example, if SetValue() is called)}
+comes from the program itself (for example, if SetValue() is called); see ChangeValue() for
+a function which does not send this event.}
\twocolitem{{\bf EVT\_TEXT\_ENTER(id, func)}}{Respond to a wxEVT\_COMMAND\_TEXT\_ENTER event,
generated when enter is pressed in a text control (which must have
wxTE\_PROCESS\_ENTER style for this event to be generated).}
Note that this function will generate a {\tt wxEVT\_COMMAND\_TEXT\_UPDATED}
event.
+This function is deprecated and should not be used in new code. Please use the
+\helpref{ChangeValue}{wxtextctrlchangevalue} function instead.
+
+\wxheading{Parameters}
+
+\docparam{value}{The new value to set. It may contain newline characters if the text control is multi-line.}
+
+
+\membersection{wxTextCtrl::ChangeValue}\label{wxtextctrlchangevalue}
+
+\func{virtual void}{ChangeValue}{\param{const wxString\& }{ value}}
+
+Sets the text value and marks the control as not-modified (which means that
+\helpref{IsModified}{wxtextctrlismodified} would return {\tt false} immediately
+after the call to SetValue).
+
+Note that this function will \emph{not} generate the {\tt wxEVT\_COMMAND\_TEXT\_UPDATED}
+event.
+This is the only difference with \helpref{SetValue}{wxtextctrlsetvalue}.
+See \helpref{this topic}{progevent} for more info.
+
\wxheading{Parameters}
\docparam{value}{The new value to set. It may contain newline characters if the text control is multi-line.}
virtual wxString GetValue() const;
virtual void SetValue(const wxString& value);
+ virtual void ChangeValue(const wxString &value);
+
virtual int GetLineLength(long lineNo) const;
virtual wxString GetLineText(long lineNo) const;
virtual int GetNumberOfLines() const;
// ----------------------------------
virtual wxString GetValue() const;
- virtual void SetValue(const wxString& value);
+ virtual void SetValue(const wxString& value) { DoSetValue(value, SetValue_SendEvent); }
+
+ virtual void ChangeValue(const wxString &value) { DoSetValue(value); }
virtual int GetLineLength(long lineNo) const;
virtual wxString GetLineText(long lineNo) const;
virtual void OnParentEnable( bool enable ) ;
// tell the control to ignore next text changed signal
- void IgnoreNextTextUpdate() { m_ignoreNextUpdate = true; }
+ void IgnoreNextTextUpdate(int n = 1) { m_countUpdatesToIgnore = n; }
// should we ignore the changed signal? always resets the flag
bool IgnoreTextUpdate();
// has the control been frozen by Freeze()?
bool IsFrozen() const { return m_frozenness > 0; }
+ void DoSetValue(const wxString &value, int flags = 0);
+
private:
// change the font for everything in this control
void ChangeFontGlobally();
GtkWidget *m_text;
bool m_modified:1;
- bool m_ignoreNextUpdate:1;
bool m_dontMarkDirty:1;
+ int m_countUpdatesToIgnore;
+
// Our text buffer. Convenient, and holds the buffer while using
// a dummy one when m_frozenness > 0
GtkTextBuffer *m_buffer;
// ----------------------------------
virtual wxString GetValue() const;
- virtual void SetValue(const wxString& value);
+ virtual void SetValue(const wxString& value) { DoSetValue(value, SetValue_SendEvent); }
+
+ virtual void ChangeValue(const wxString &value) { DoSetValue(value); }
virtual int GetLineLength(long lineNo) const;
virtual wxString GetLineText(long lineNo) const;
// override this and return true.
virtual bool UseGTKStyleBase() const { return true; }
+ void DoSetValue(const wxString &value, int flags = 0);
+
private:
// change the font for everything in this control
void ChangeFontGlobally();
virtual wxString GetValue() const;
virtual void SetValue(const wxString& value);
+ virtual void ChangeValue(const wxString &value);
+
virtual int GetLineLength(long lineNo) const;
virtual wxString GetLineText(long lineNo) const;
virtual int GetNumberOfLines() const;
// accessors
// ---------
virtual wxString GetValue() const;
- virtual void SetValue(const wxString& value);
+ virtual void SetValue(const wxString& value)
+ { ChangeValue(value); SendTextUpdatedEvent(); }
+
+ virtual void ChangeValue(const wxString &value);
virtual int GetLineLength(long lineNo) const;
virtual wxString GetLineText(long lineNo) const;
// ----------------------------------
virtual wxString GetValue() const;
- virtual void SetValue(const wxString& value);
+ virtual void SetValue(const wxString& value) { DoSetValue(value, SetValue_SendEvent); }
+ virtual void ChangeValue(const wxString &value) { DoSetValue(value); }
virtual wxString GetRange(long from, long to) const;
// common part of all ctors
void Init();
+ void DoSetValue(const wxString &value, int flags = 0);
+
// return true if this control has a user-set limit on amount of text (i.e.
// the limit is due to a previous call to SetMaxLength() and not built in)
bool HasSpaceLimit(unsigned int *len) const;
// replace the contents of the selection or of the entire control with the
// given text
- void DoWriteText(const wxString& text, bool selectionOnly = true);
+ void DoWriteText(const wxString& text, int flags = SetValue_SelectionOnly);
// set the selection possibly without scrolling the caret into view
void DoSetSelection(long from, long to, bool scrollCaret = true);
// ----------------------------------
virtual wxString GetValue() const;
- virtual void SetValue(const wxString& value);
+ virtual void SetValue(const wxString& value) { DoSetValue(value, SetValue_SendEvent); }
+
+ virtual void ChangeValue(const wxString &value) { DoSetValue(value); }
virtual wxString GetRange(long from, long to) const;
// false if we hit the limit set by SetMaxLength() and so didn't change it
bool AdjustSpaceLimit();
+ void DoSetValue(const wxString &value, int flags = 0);
+
// replace the contents of the selection or of the entire control with the
// given text
- void DoWriteText(const wxString& text, bool selectionOnly = true);
+ void DoWriteText(const wxString& text, int flags = SetValue_SelectionOnly);
// set the selection possibly without scrolling the caret into view
void DoSetSelection(long from, long to, bool scrollCaret = true);
// ----------------------------------
//
virtual wxString GetValue(void) const;
- virtual void SetValue(const wxString& rsValue);
+ virtual void SetValue(const wxString& value) { DoSetValue(value, SetValue_SendEvent); }
+
+ virtual void ChangeValue(const wxString &value) { DoSetValue(value); }
virtual int GetLineLength(long nLineNo) const;
virtual wxString GetLineText(long nLineNo) const;
virtual WXDWORD OS2GetStyle( long lStyle
,WXDWORD* dwExstyle
) const;
+
+ void DoSetValue(const wxString &value, int flags = 0);
+
+ bool m_bSkipUpdate;
+
private:
bool m_bIsMLE;
DECLARE_EVENT_TABLE()
virtual wxString GetValue() const;
virtual void SetValue(const wxString& value);
+ virtual void ChangeValue(const wxString &value);
+
virtual int GetLineLength(long lineNo) const;
virtual wxString GetLineText(long lineNo) const;
virtual int GetNumberOfLines() const;
virtual wxString GetValue() const = 0;
virtual void SetValue(const wxString& value) = 0;
+ virtual void ChangeValue(const wxString &value) = 0;
+
virtual wxString GetRange(long from, long to) const;
virtual int GetLineLength(long lineNo) const = 0;
int overflow(int i);
#endif // wxHAS_TEXT_WINDOW_STREAM
+ // typically, wxTextCtrl classes will use a DoSetValue() function to
+ // implement both SetValue() and ChangeValue() functions and these
+ // flags are meant to be passed to such DoSetValue()
+ enum
+ {
+ SetValue_SendEvent = 1,
+ SetValue_SelectionOnly = 2
+ };
+
+ // generate the wxEVT_COMMAND_TEXT_UPDATED event
+ void SendTextUpdatedEvent();
+
// the name of the last file loaded with LoadFile() which will be used by
// SaveFile() by default
wxString m_filename;
virtual wxString GetValue() const;
virtual void SetValue(const wxString& value);
+ virtual void ChangeValue(const wxString &value);
+
virtual int GetLineLength(wxTextCoord lineNo) const;
virtual wxString GetLineText(wxTextCoord lineNo) const;
virtual int GetNumberOfLines() const;
// ----------------------------------
virtual wxString GetValue() const;
- virtual void SetValue(const wxString& value);
+ virtual void SetValue(const wxString& value)
+ { ChangeValue(value); SendTextUpdatedEvent(); }
+
+ virtual void ChangeValue(const wxString &value);
virtual int GetLineLength(long lineNo) const;
virtual wxString GetLineText(long lineNo) const;
case WXK_F6:
wxLogMessage(_T("IsModified() before SetValue(): %d"),
IsModified());
- SetValue(_T("SetValue() has been called"));
+ ChangeValue(_T("ChangeValue() has been called"));
wxLogMessage(_T("IsModified() after SetValue(): %d"),
IsModified());
break;
void wxTextCtrl::Init()
{
m_dontMarkDirty =
- m_ignoreNextUpdate =
m_modified = false;
+ m_countUpdatesToIgnore = 0;
+
SetUpdateFont(false);
m_text = NULL;
return enc;
}
-void wxTextCtrl::SetValue( const wxString &value )
+void wxTextCtrl::DoSetValue( const wxString &value, int flags )
{
wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
return;
}
- if (gtk_text_buffer_get_char_count(m_buffer) != 0)
- IgnoreNextTextUpdate();
+
+ // if the control is not empty, two "changed" signals are emitted
+ if ( flags & SetValue_SendEvent )
+ {
+ if ( gtk_text_buffer_get_char_count(m_buffer) != 0 )
+ IgnoreNextTextUpdate();
+ }
+ else
+ {
+ if ( gtk_text_buffer_get_char_count(m_buffer) != 0 )
+ IgnoreNextTextUpdate(2);
+ else
+ IgnoreNextTextUpdate(1); // skip only one
+ }
gtk_text_buffer_set_text( m_buffer, buffer, strlen(buffer) );
}
{
// gtk_entry_set_text() emits two "changed" signals if the control is
// not empty because internally it calls gtk_editable_delete_text() and
- // gtk_editable_insert_text() but we want to have only one event
- if ( !GetValue().empty() )
- IgnoreNextTextUpdate();
+ // gtk_editable_insert_text()
+ if ( flags & SetValue_SendEvent )
+ {
+ if ( !GetValue().empty() )
+ IgnoreNextTextUpdate();
+ }
+ else
+ {
+ if ( !GetValue().empty() )
+ IgnoreNextTextUpdate(2);
+ else
+ IgnoreNextTextUpdate(1); // if we are empty, skip only one event
+ }
gtk_entry_set_text( GTK_ENTRY(m_text), wxGTK_CONV(value) );
}
bool wxTextCtrl::IgnoreTextUpdate()
{
- if ( m_ignoreNextUpdate )
+ if ( m_countUpdatesToIgnore > 0 )
{
- m_ignoreNextUpdate = false;
+ m_countUpdatesToIgnore--;
return true;
}
return tmp;
}
-void wxTextCtrl::SetValue( const wxString &value )
+void wxTextCtrl::DoSetValue( const wxString &value, int flags )
{
wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
+ if ( !(flags & SetValue_SendEvent) )
+ {
+ // do not generate events
+ IgnoreNextTextUpdate();
+ }
+
if (m_windowStyle & wxTE_MULTILINE)
{
gint len = gtk_text_get_length( GTK_TEXT(m_text) );
}
}
+void wxTextCtrl::ChangeValue(const wxString& str)
+{
+ // optimize redraws
+ if ( GetValue() == str )
+ return ;
+
+ GetPeer()->SetStringValue( str ) ;
+}
+
void wxTextCtrl::SetMaxLength(unsigned long len)
{
m_maxLength = len ;
return str;
}
-void wxTextCtrl::SetValue(const wxString& text)
+void wxTextCtrl::ChangeValue(const wxString& text)
{
m_inSetValue = true;
UpdatesCountFilter(int& count)
: m_count(count)
{
- wxASSERT_MSG( m_count == -1, _T("wrong initial m_updatesCount value") );
+ wxASSERT_MSG( m_count == -1 || m_count == -2,
+ _T("wrong initial m_updatesCount value") );
- m_count = 0;
+ if (m_count != -2)
+ m_count = 0;
+ //else: we don't want to count how many update events we get as we're going
+ // to ignore all of them
}
~UpdatesCountFilter()
return str;
}
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::DoSetValue(const wxString& value, int flags)
{
// if the text is long enough, it's faster to just set it instead of first
// comparing it with the old one (chances are that it will be different
// edit controls mostly)
if ( (value.length() > 0x400) || (value != GetValue()) )
{
- DoWriteText(value, false /* not selection only */);
+ DoWriteText(value, flags);
// mark the control as being not dirty - we changed its text, not the
// user
DiscardEdits();
// still send an event for consistency
- SendUpdateEvent();
+ if (flags & SetValue_SendEvent)
+ SendUpdateEvent();
}
}
DoWriteText(value);
}
-void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly)
+void wxTextCtrl::DoWriteText(const wxString& value, int flags)
{
+ bool selectionOnly = (flags & SetValue_SelectionOnly) != 0;
wxString valueDos;
if ( m_windowStyle & wxTE_MULTILINE )
valueDos = wxTextFile::Translate(value, wxTextFileType_Dos);
// we generate exactly one of them by ignoring all but the first one in
// SendUpdateEvent() and generating one ourselves if we hadn't got any
// notifications from Windows
+ if ( !(flags & SetValue_SendEvent) )
+ m_updatesCount = -2; // suppress any update event
+
UpdatesCountFilter ucf(m_updatesCount);
::SendMessage(GetHwnd(), selectionOnly ? EM_REPLACESEL : WM_SETTEXT,
// EM_REPLACESEL takes 1 to indicate the operation should be redoable
selectionOnly ? 1 : 0, (LPARAM)valueDos.c_str());
- if ( !ucf.GotUpdate() )
+ if ( !ucf.GotUpdate() && (flags & SetValue_SendEvent) )
{
SendUpdateEvent();
}
// Set selection and remove it
DoSetSelection(from, to, false /* don't scroll caret into view */);
- DoWriteText(value, true /* selection only */);
+ DoWriteText(value, SetValue_SelectionOnly);
}
void wxTextCtrl::Remove(long from, long to)
// we hadn't updated the control ourselves, this event comes from
// the user, don't need to ignore it nor update the count
break;
+
+ case -2:
+ // the control was updated programmatically and we do NOT want to
+ // send events
+ return false;
}
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
return str;
}
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::DoSetValue(const wxString& value, int flags)
{
// if the text is long enough, it's faster to just set it instead of first
// comparing it with the old one (chances are that it will be different
// edit controls mostly)
if ( (value.length() > 0x400) || (value != GetValue()) )
{
- DoWriteText(value, false);
+ DoWriteText(value, flags);
// for compatibility, don't move the cursor when doing SetValue()
SetInsertionPoint(0);
else // same text
{
// still send an event for consistency
- SendUpdateEvent();
+ if ( flags & SetValue_SendEvent )
+ SendUpdateEvent();
}
// we should reset the modified flag even if the value didn't really change
DoWriteText(value);
}
-void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly)
+void wxTextCtrl::DoWriteText(const wxString& value, int flags)
{
+ bool selectionOnly = (flags & SetValue_SelectionOnly) != 0;
wxString valueDos;
if ( m_windowStyle & wxTE_MULTILINE )
valueDos = wxTextFile::Translate(value, wxTextFileType_Dos);
// call below which is confusing for the client code and so should be
// avoided
//
- if ( ( selectionOnly && HasSelection() ) )
+ if ( selectionOnly && HasSelection() )
{
m_suppressNextUpdate = true;
}
::SendMessage(GetBuddyHwnd(), selectionOnly ? EM_REPLACESEL : WM_SETTEXT,
0, (LPARAM)valueDos.c_str());
- if ( !selectionOnly )
+ if ( !selectionOnly && !( flags & SetValue_SendEvent ) )
{
// Windows already sends an update event for single-line
// controls.
// Set selection and remove it
DoSetSelection(from, to, false);
- DoWriteText(value, true);
+ DoWriteText(value, SetValue_SelectionOnly);
}
void wxTextCtrl::Remove(long from, long to)
m_windowStyle = lStyle;
m_bIsMLE = false;
+ m_bSkipUpdate = false;
long lSstyle = WS_VISIBLE | WS_TABSTOP;
return sStr;
} // end of wxTextCtrl::GetValue
-void wxTextCtrl::SetValue(
- const wxString& rsValue
+void wxTextCtrl::DoSetValue(
+ const wxString& rsValue,
+ int flags
)
{
//
//
if ((rsValue.length() > 0x400) || (rsValue != GetValue()))
{
+ if ( flags & SetValue_SendEvent )
+ m_bSkipUpdate = true;
+
::WinSetWindowText(GetHwnd(), (PSZ)rsValue.c_str());
AdjustSpaceLimit();
}
case EN_CHANGE:
{
+ if (m_bSkipUpdate)
+ {
+ m_bSkipUpdate = false;
+ break;
+ }
+
wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED
,m_windowId
);
{
}
+void wxTextCtrl::ChangeValue(const wxString& value)
+{
+}
+
#if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU)
// TODO: using memcpy() would improve performance a lot for big amounts of text
// set/get the value
// ----------------------------------------------------------------------------
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::ChangeValue(const wxString& value)
{
if ( IsSingleLine() && (value == GetValue()) )
{
{
SetInsertionPoint(0);
}
+}
- // TODO: should we generate the event or not, finally?
+void wxTextCtrl::SetValue(const wxString& value)
+{
+ ChangeValue(value);
+ SendTextUpdatedEvent();
}
const wxArrayString& wxTextCtrl::GetLines() const
return ret;
}
-void wxTextCtrl::SetValue(const wxString& value)
+void wxTextCtrl::ChangeValue(const wxString& value)
{
m_modified = false;