X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9cd6d737d5adc5fe415cddb3ef0024b9da2b9e08..adac097759c089b3d47f48c7756ace4f0b8df879:/src/gtk1/textctrl.cpp diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp index 05ccf01a77..35de57809a 100644 --- a/src/gtk1/textctrl.cpp +++ b/src/gtk1/textctrl.cpp @@ -21,6 +21,7 @@ #include #include #include +#include // for fabs #include "gdk/gdk.h" #include "gtk/gtk.h" @@ -40,6 +41,46 @@ 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) +{ + if (g_isIdle) + wxapp_install_idle_handler(); + + // 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" //----------------------------------------------------------------------------- @@ -47,6 +88,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) @@ -56,8 +100,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 ); } @@ -76,115 +120,6 @@ gtk_scrollbar_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) win->CalculateScrollbar(); } -//----------------------------------------------------------------------------- -// "focus_in_event" -//----------------------------------------------------------------------------- - -extern wxWindow *g_focusWindow; -extern bool g_blockEventsOnDrag; -// extern bool g_isIdle; - -static gint gtk_text_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win ) -{ - // Necessary? -#if 0 - if (g_isIdle) - wxapp_install_idle_handler(); -#endif - if (!win->m_hasVMT) return FALSE; - if (g_blockEventsOnDrag) return FALSE; - - g_focusWindow = win; - - wxPanel *panel = wxDynamicCast(win->GetParent(), wxPanel); - if (panel) - { - panel->SetLastFocus(win); - } - -#ifdef HAVE_XIM - if (win->m_ic) - gdk_im_begin(win->m_ic, win->m_wxwindow->window); -#endif - -#if 0 -#ifdef wxUSE_CARET - // caret needs to be informed about focus change - wxCaret *caret = win->GetCaret(); - if ( caret ) - { - caret->OnSetFocus(); - } -#endif // wxUSE_CARET -#endif - - wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() ); - event.SetEventObject( win ); - - if (win->GetEventHandler()->ProcessEvent( event )) - { - gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" ); - return TRUE; - } - - return FALSE; -} - -//----------------------------------------------------------------------------- -// "focus_out_event" -//----------------------------------------------------------------------------- - -static gint gtk_text_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win ) -{ -#if 0 - if (g_isIdle) - wxapp_install_idle_handler(); -#endif - - if (!win->m_hasVMT) return FALSE; - if (g_blockEventsOnDrag) return FALSE; - -#if 0 - // if the focus goes out of our app alltogether, OnIdle() will send - // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset - // g_sendActivateEvent to -1 - g_sendActivateEvent = 0; -#endif - - wxWindow *winFocus = wxFindFocusedChild(win); - if ( winFocus ) - win = winFocus; - - g_focusWindow = (wxWindow *)NULL; - -#ifdef HAVE_XIM - if (win->m_ic) - gdk_im_end(); -#endif - -#if 0 -#ifdef wxUSE_CARET - // caret needs to be informed about focus change - wxCaret *caret = win->GetCaret(); - if ( caret ) - { - caret->OnKillFocus(); - } -#endif // wxUSE_CARET -#endif - - wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() ); - event.SetEventObject( win ); - - if (win->GetEventHandler()->ProcessEvent( event )) - { - gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" ); - return TRUE; - } - - return FALSE; -} - //----------------------------------------------------------------------------- // wxTextCtrl //----------------------------------------------------------------------------- @@ -209,6 +144,7 @@ END_EVENT_TABLE() void wxTextCtrl::Init() { + m_ignoreNextUpdate = m_modified = FALSE; m_updateFont = FALSE; m_text = @@ -309,6 +245,8 @@ bool wxTextCtrl::Create( wxWindow *parent, } m_parent->DoAddChild( this ); + + m_focusWidget = m_text; PostCreation(); @@ -330,20 +268,6 @@ bool wxTextCtrl::Create( wxWindow *parent, { gtk_signal_connect(GTK_OBJECT(GTK_TEXT(m_text)->vadj), "changed", (GtkSignalFunc) gtk_scrollbar_changed_callback, (gpointer) this ); - - gtk_signal_connect( GTK_OBJECT(GTK_TEXT(m_text)), "focus_in_event", - GTK_SIGNAL_FUNC(gtk_text_focus_in_callback), (gpointer)this ); - - gtk_signal_connect( GTK_OBJECT(GTK_TEXT(m_text)), "focus_out_event", - GTK_SIGNAL_FUNC(gtk_text_focus_out_callback), (gpointer)this ); - } - else - { - gtk_signal_connect( GTK_OBJECT(m_text), "focus_in_event", - GTK_SIGNAL_FUNC(gtk_text_focus_in_callback), (gpointer)this ); - - gtk_signal_connect( GTK_OBJECT(m_text), "focus_out_event", - GTK_SIGNAL_FUNC(gtk_text_focus_out_callback), (gpointer)this ); } if (!value.IsEmpty()) @@ -829,6 +753,61 @@ 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 + ); + } + } +} + void wxTextCtrl::SetSelection( long from, long to ) { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); @@ -1078,10 +1057,10 @@ void wxTextCtrl::ChangeFontGlobally() wxString value = GetValue(); if ( !value.IsEmpty() ) { + m_updateFont = FALSE; + Clear(); AppendText(value); - - m_updateFont = FALSE; } } @@ -1312,6 +1291,8 @@ void wxTextCtrl::Thaw() { if ( HasFlag(wxTE_MULTILINE) ) { + GTK_TEXT(m_text)->vadj->value = 0.0; + gtk_text_thaw(GTK_TEXT(m_text)); } } @@ -1368,6 +1349,6 @@ bool wxTextCtrl::ScrollPages(int pages) if ( !adj ) return FALSE; - return DoScroll(adj, pages*adj->page_increment); + return DoScroll(adj, (int)ceil(pages*adj->page_increment)); }