From ce2f50e34a191c323781d4a86aa333b9571b8d76 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 16 Aug 2001 13:18:51 +0000 Subject: [PATCH] added sending of EVT_TEXT_MAXLEN to wxGTK, suppressed sending of dummy EVT_TEXT_UPDATED events when the text doesn't really change git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11390 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/text.tex | 2 - include/wx/gtk/textctrl.h | 16 +++++-- include/wx/gtk1/textctrl.h | 16 +++++-- src/gtk/textctrl.cpp | 90 +++++++++++++++++++++++++++++++++++++- src/gtk1/textctrl.cpp | 90 +++++++++++++++++++++++++++++++++++++- 5 files changed, 204 insertions(+), 10 deletions(-) diff --git a/docs/latex/wx/text.tex b/docs/latex/wx/text.tex index a9c2117f2d..e6dc093d12 100644 --- a/docs/latex/wx/text.tex +++ b/docs/latex/wx/text.tex @@ -534,8 +534,6 @@ Note that this function may only be used with single line text controls. Only implemented in wxMSW/wxGTK starting with wxWindows 2.3.2. -The {\tt wxEVT\_COMMAND\_TEXT\_MAXLEN} event is only sent by wxMSW. - \membersection{wxTextCtrl::SetSelection}\label{wxtextctrlsetselection} \func{virtual void}{SetSelection}{\param{long}{ from}, \param{long}{ to}} diff --git a/include/wx/gtk/textctrl.h b/include/wx/gtk/textctrl.h index 5a5ab756ff..34df4e6839 100644 --- a/include/wx/gtk/textctrl.h +++ b/include/wx/gtk/textctrl.h @@ -154,11 +154,19 @@ public: virtual bool ScrollLines(int lines); virtual bool ScrollPages(int pages); + // implementation only from now on + // wxGTK-specific: called recursively by Enable, // to give widgets an oppprtunity to correct their colours after they // have been changed by Enable virtual void OnParentEnable( bool enable ) ; + // tell the control to ignore next text changed signal + void IgnoreNextTextUpdate(); + + // should we ignore the changed signal? always resets the flag + bool IgnoreTextUpdate(); + protected: virtual wxSize DoGetBestSize() const; @@ -176,11 +184,13 @@ private: // change the font for everything in this control void ChangeFontGlobally(); - bool m_modified; GtkWidget *m_text; GtkWidget *m_vScrollbar; - bool m_vScrollbarVisible; - bool m_updateFont; + + bool m_modified:1; + bool m_vScrollbarVisible:1; + bool m_updateFont:1; + bool m_ignoreNextUpdate:1; DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(wxTextCtrl); diff --git a/include/wx/gtk1/textctrl.h b/include/wx/gtk1/textctrl.h index 5a5ab756ff..34df4e6839 100644 --- a/include/wx/gtk1/textctrl.h +++ b/include/wx/gtk1/textctrl.h @@ -154,11 +154,19 @@ public: virtual bool ScrollLines(int lines); virtual bool ScrollPages(int pages); + // implementation only from now on + // wxGTK-specific: called recursively by Enable, // to give widgets an oppprtunity to correct their colours after they // have been changed by Enable virtual void OnParentEnable( bool enable ) ; + // tell the control to ignore next text changed signal + void IgnoreNextTextUpdate(); + + // should we ignore the changed signal? always resets the flag + bool IgnoreTextUpdate(); + protected: virtual wxSize DoGetBestSize() const; @@ -176,11 +184,13 @@ private: // change the font for everything in this control void ChangeFontGlobally(); - bool m_modified; GtkWidget *m_text; GtkWidget *m_vScrollbar; - bool m_vScrollbarVisible; - bool m_updateFont; + + bool m_modified:1; + bool m_vScrollbarVisible:1; + bool m_updateFont:1; + bool m_ignoreNextUpdate:1; DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(wxTextCtrl); diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 0e2fab3a26..468f7262a2 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -41,6 +41,43 @@ extern bool g_isIdle; extern bool g_blockEventsOnDrag; extern wxCursor g_globalCursor; +// ---------------------------------------------------------------------------- +// "insert_text" for GtkEntry +// ---------------------------------------------------------------------------- + +static void +gtk_insert_text_callback(GtkEditable *editable, + const gchar *new_text, + gint new_text_length, + gint *position, + wxTextCtrl *win) +{ + // we should only be called if we have a max len limit at all + GtkEntry *entry = GTK_ENTRY (editable); + + wxCHECK_RET( entry->text_max_length, _T("shouldn't be called") ); + + // check that we don't overflow the max length limit + // + // FIXME: this doesn't work when we paste a string which is going to be + // truncated + if ( entry->text_length == entry->text_max_length ) + { + // we don't need to run the base class version at all + gtk_signal_emit_stop_by_name(GTK_OBJECT(editable), "insert_text"); + + // remember that the next changed signal is to be ignored to avoid + // generating a dummy wxEVT_COMMAND_TEXT_UPDATED event + win->IgnoreNextTextUpdate(); + + // and generate the correct one ourselves + wxCommandEvent event(wxEVT_COMMAND_TEXT_MAXLEN, win->GetId()); + event.SetEventObject(win); + event.SetString(win->GetValue()); + win->GetEventHandler()->ProcessEvent( event ); + } +} + //----------------------------------------------------------------------------- // "changed" //----------------------------------------------------------------------------- @@ -48,6 +85,9 @@ extern wxCursor g_globalCursor; static void gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) { + if ( win->IgnoreTextUpdate() ) + return; + if (!win->m_hasVMT) return; if (g_isIdle) @@ -57,8 +97,8 @@ gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) win->UpdateFontIfNeeded(); wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, win->GetId() ); - event.SetString( win->GetValue() ); event.SetEventObject( win ); + event.SetString( win->GetValue() ); win->GetEventHandler()->ProcessEvent( event ); } @@ -206,6 +246,7 @@ END_EVENT_TABLE() void wxTextCtrl::Init() { + m_ignoreNextUpdate = m_modified = FALSE; m_updateFont = FALSE; m_text = @@ -826,11 +867,58 @@ void wxTextCtrl::DiscardEdits() m_modified = FALSE; } +// ---------------------------------------------------------------------------- +// max text length support +// ---------------------------------------------------------------------------- + +void wxTextCtrl::IgnoreNextTextUpdate() +{ + m_ignoreNextUpdate = TRUE; +} + +bool wxTextCtrl::IgnoreTextUpdate() +{ + if ( m_ignoreNextUpdate ) + { + m_ignoreNextUpdate = FALSE; + + return TRUE; + } + + return FALSE; +} + void wxTextCtrl::SetMaxLength(unsigned long len) { if ( !HasFlag(wxTE_MULTILINE) ) { gtk_entry_set_max_length(GTK_ENTRY(m_text), len); + + // there is a bug in GTK+ 1.2.x: "changed" signal is emitted even if + // we had tried to enter more text than allowed by max text length and + // the text wasn't really changed + // + // to detect this and generate TEXT_MAXLEN event instead of + // TEXT_CHANGED one in this case we also catch "insert_text" signal + // + // when max len is set to 0 we disconnect our handler as it means that + // we shouldn't check anything any more + if ( len ) + { + gtk_signal_connect( GTK_OBJECT(m_text), + "insert_text", + GTK_SIGNAL_FUNC(gtk_insert_text_callback), + (gpointer)this); + } + else // no checking + { + gtk_signal_disconnect_by_func + ( + GTK_OBJECT(m_text), + GTK_SIGNAL_FUNC(gtk_insert_text_callback), + (gpointer)this + ); + } } } diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp index 0e2fab3a26..468f7262a2 100644 --- a/src/gtk1/textctrl.cpp +++ b/src/gtk1/textctrl.cpp @@ -41,6 +41,43 @@ extern bool g_isIdle; extern bool g_blockEventsOnDrag; extern wxCursor g_globalCursor; +// ---------------------------------------------------------------------------- +// "insert_text" for GtkEntry +// ---------------------------------------------------------------------------- + +static void +gtk_insert_text_callback(GtkEditable *editable, + const gchar *new_text, + gint new_text_length, + gint *position, + wxTextCtrl *win) +{ + // we should only be called if we have a max len limit at all + GtkEntry *entry = GTK_ENTRY (editable); + + wxCHECK_RET( entry->text_max_length, _T("shouldn't be called") ); + + // check that we don't overflow the max length limit + // + // FIXME: this doesn't work when we paste a string which is going to be + // truncated + if ( entry->text_length == entry->text_max_length ) + { + // we don't need to run the base class version at all + gtk_signal_emit_stop_by_name(GTK_OBJECT(editable), "insert_text"); + + // remember that the next changed signal is to be ignored to avoid + // generating a dummy wxEVT_COMMAND_TEXT_UPDATED event + win->IgnoreNextTextUpdate(); + + // and generate the correct one ourselves + wxCommandEvent event(wxEVT_COMMAND_TEXT_MAXLEN, win->GetId()); + event.SetEventObject(win); + event.SetString(win->GetValue()); + win->GetEventHandler()->ProcessEvent( event ); + } +} + //----------------------------------------------------------------------------- // "changed" //----------------------------------------------------------------------------- @@ -48,6 +85,9 @@ extern wxCursor g_globalCursor; static void gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) { + if ( win->IgnoreTextUpdate() ) + return; + if (!win->m_hasVMT) return; if (g_isIdle) @@ -57,8 +97,8 @@ gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) win->UpdateFontIfNeeded(); wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, win->GetId() ); - event.SetString( win->GetValue() ); event.SetEventObject( win ); + event.SetString( win->GetValue() ); win->GetEventHandler()->ProcessEvent( event ); } @@ -206,6 +246,7 @@ END_EVENT_TABLE() void wxTextCtrl::Init() { + m_ignoreNextUpdate = m_modified = FALSE; m_updateFont = FALSE; m_text = @@ -826,11 +867,58 @@ void wxTextCtrl::DiscardEdits() m_modified = FALSE; } +// ---------------------------------------------------------------------------- +// max text length support +// ---------------------------------------------------------------------------- + +void wxTextCtrl::IgnoreNextTextUpdate() +{ + m_ignoreNextUpdate = TRUE; +} + +bool wxTextCtrl::IgnoreTextUpdate() +{ + if ( m_ignoreNextUpdate ) + { + m_ignoreNextUpdate = FALSE; + + return TRUE; + } + + return FALSE; +} + void wxTextCtrl::SetMaxLength(unsigned long len) { if ( !HasFlag(wxTE_MULTILINE) ) { gtk_entry_set_max_length(GTK_ENTRY(m_text), len); + + // there is a bug in GTK+ 1.2.x: "changed" signal is emitted even if + // we had tried to enter more text than allowed by max text length and + // the text wasn't really changed + // + // to detect this and generate TEXT_MAXLEN event instead of + // TEXT_CHANGED one in this case we also catch "insert_text" signal + // + // when max len is set to 0 we disconnect our handler as it means that + // we shouldn't check anything any more + if ( len ) + { + gtk_signal_connect( GTK_OBJECT(m_text), + "insert_text", + GTK_SIGNAL_FUNC(gtk_insert_text_callback), + (gpointer)this); + } + else // no checking + { + gtk_signal_disconnect_by_func + ( + GTK_OBJECT(m_text), + GTK_SIGNAL_FUNC(gtk_insert_text_callback), + (gpointer)this + ); + } } } -- 2.47.2