X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ff805cac748d91edbf55d82a7f1b567d5d4d3cc0..89c33c4831a62c628ebdbba02c2c05ec6b9169c0:/src/gtk/textctrl.cpp diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index b44668c172..25186c9d1e 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -149,7 +149,7 @@ static void wxGtkTextApplyTagsFromAttr(GtkWidget *text, gtk_text_iter_get_line(start) ); gtk_text_iter_forward_line(¶_end); - wxGtkTextRemoveTagsWithPrefix(text_buffer, "WXALIGNMENT", start, end); + wxGtkTextRemoveTagsWithPrefix(text_buffer, "WXALIGNMENT", ¶_start, ¶_end); GtkJustification align; switch (attr.GetAlignment()) @@ -195,17 +195,12 @@ static void wxGtkTextApplyTagsFromAttr(GtkWidget *text, gtk_text_iter_get_line(start) ); gtk_text_iter_forward_line(¶_end); - wxGtkTextRemoveTagsWithPrefix(text_buffer, "WXINDENT", start, end); + wxGtkTextRemoveTagsWithPrefix(text_buffer, "WXINDENT", ¶_start, ¶_end); // Convert indent from 1/10th of a mm into pixels - float factor; -#if GTK_CHECK_VERSION(2,2,0) - if (!gtk_check_version(2,2,0)) - factor = (float)gdk_screen_get_width(gtk_widget_get_screen(text)) / + float factor = + (float)gdk_screen_get_width(gtk_widget_get_screen(text)) / gdk_screen_get_width_mm(gtk_widget_get_screen(text)) / 10; - else -#endif - factor = (float)gdk_screen_width() / gdk_screen_width_mm() / 10; const int indent = (int)(factor * attr.GetLeftIndent()); const int subIndent = (int)(factor * attr.GetLeftSubIndent()); @@ -244,7 +239,7 @@ static void wxGtkTextApplyTagsFromAttr(GtkWidget *text, gtk_text_iter_get_line(start) ); gtk_text_iter_forward_line(¶_end); - wxGtkTextRemoveTagsWithPrefix(text_buffer, "WXTABS", start, end); + wxGtkTextRemoveTagsWithPrefix(text_buffer, "WXTABS", ¶_start, ¶_end); const wxArrayInt& tabs = attr.GetTabs(); @@ -260,14 +255,9 @@ static void wxGtkTextApplyTagsFromAttr(GtkWidget *text, if (!tag) { // Factor to convert from 1/10th of a mm into pixels - float factor; -#if GTK_CHECK_VERSION(2,2,0) - if (!gtk_check_version(2,2,0)) - factor = (float)gdk_screen_get_width(gtk_widget_get_screen(text)) / + float factor = + (float)gdk_screen_get_width(gtk_widget_get_screen(text)) / gdk_screen_get_width_mm(gtk_widget_get_screen(text)) / 10; - else -#endif - factor = (float)gdk_screen_width() / gdk_screen_width_mm() / 10; PangoTabArray* tabArray = pango_tab_array_new(tabs.GetCount(), TRUE); for (size_t i = 0; i < tabs.GetCount(); i++) @@ -504,6 +494,27 @@ au_delete_range_callback(GtkTextBuffer * WXUNUSED(buffer), } } +//----------------------------------------------------------------------------- +// "populate_popup" from text control and "unmap" from its poup menu +//----------------------------------------------------------------------------- + +extern "C" { +static void +gtk_textctrl_popup_unmap( GtkMenu *WXUNUSED(menu), wxTextCtrl* win ) +{ + win->GTKEnableFocusOutEvent(); +} +} + +extern "C" { +static void +gtk_textctrl_populate_popup( GtkEntry *WXUNUSED(entry), GtkMenu *menu, wxTextCtrl *win ) +{ + win->GTKDisableFocusOutEvent(); + + g_signal_connect (menu, "unmap", G_CALLBACK (gtk_textctrl_popup_unmap), win ); +} +} //----------------------------------------------------------------------------- // "changed" @@ -511,7 +522,7 @@ au_delete_range_callback(GtkTextBuffer * WXUNUSED(buffer), extern "C" { static void -gtk_text_changed_callback( GtkWidget * WXUNUSED(widget), wxTextCtrl *win ) +gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) { if ( win->IgnoreTextUpdate() ) return; @@ -536,7 +547,7 @@ handle_text_clipboard_callback( GtkWidget *widget, wxTextCtrl *win, { wxClipboardTextEvent event( eventType, win->GetId() ); event.SetEventObject( win ); - if ( win->GetEventHandler()->ProcessEvent( event ) ) + if ( win->HandleWindowEvent( event ) ) { // don't let the default processing to take place if we did something // ourselves in the event handler @@ -567,21 +578,6 @@ gtk_paste_clipboard_callback( GtkWidget *widget, wxTextCtrl *win ) } } -//----------------------------------------------------------------------------- -// "expose_event" from scrolled window and textview -//----------------------------------------------------------------------------- - -extern "C" { -static gboolean -gtk_text_exposed_callback( GtkWidget * WXUNUSED(widget), - GdkEventExpose * WXUNUSED(event), - wxTextCtrl * WXUNUSED(win) ) -{ - return TRUE; -} -} - - //----------------------------------------------------------------------------- // wxTextCtrl //----------------------------------------------------------------------------- @@ -624,7 +620,6 @@ void wxTextCtrl::Init() SetUpdateFont(false); m_text = NULL; - m_freezeCount = 0; m_showPositionOnThaw = NULL; m_gdkHandCursor = NULL; m_gdkXTermCursor = NULL; @@ -697,7 +692,7 @@ bool wxTextCtrl::Create( wxWindow *parent, GTKSetWrapMode(); - GtkScrolledWindowSetBorder(m_widget, style); + GTKScrolledWindowSetBorder(m_widget, style); gtk_widget_add_events( GTK_WIDGET(m_text), GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK ); @@ -711,7 +706,9 @@ bool wxTextCtrl::Create( wxWindow *parent, if (style & wxNO_BORDER) g_object_set (m_text, "has-frame", FALSE, NULL); + } + g_object_ref(m_widget); m_parent->DoAddChild( this ); @@ -736,6 +733,11 @@ bool wxTextCtrl::Create( wxWindow *parent, G_CALLBACK (gtk_text_changed_callback), this); } + // Catch to disable focus out handling + g_signal_connect (m_text, "populate_popup", + G_CALLBACK (gtk_textctrl_populate_popup), + this); + if (!value.empty()) { SetValue( value ); @@ -747,9 +749,6 @@ bool wxTextCtrl::Create( wxWindow *parent, if (style & wxTE_READONLY) GTKSetEditable(); - if (style & wxTE_PROCESS_ENTER) - GTKSetActivatesDefault(); - // left justification (alignment) is the default anyhow if ( style & (wxTE_RIGHT | wxTE_CENTRE) ) GTKSetJustification(); @@ -792,6 +791,13 @@ bool wxTextCtrl::Create( wxWindow *parent, au_check_range(&start, &end); } } + else // single line + { + // do the right thing with Enter presses depending on whether we have + // wxTE_PROCESS_ENTER or not + GTKSetActivatesDefault(); + } + g_signal_connect (m_text, "copy-clipboard", G_CALLBACK (gtk_copy_clipboard_callback), this); @@ -857,17 +863,7 @@ void wxTextCtrl::GTKSetWrapMode() else if ( HasFlag( wxTE_WORDWRAP ) ) wrap = GTK_WRAP_WORD; else // HasFlag(wxTE_BESTWRAP) always true as wxTE_BESTWRAP == 0 - { - // GTK_WRAP_WORD_CHAR seems to be new in GTK+ 2.4 -#ifdef __WXGTK24__ - if ( !gtk_check_version(2,4,0) ) - { - wrap = GTK_WRAP_WORD_CHAR; - } - else -#endif // __WXGTK24__ - wrap = GTK_WRAP_WORD; - } + wrap = GTK_WRAP_WORD_CHAR; gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW( m_text ), wrap ); } @@ -888,23 +884,16 @@ void wxTextCtrl::GTKSetJustification() } else // single line { -#ifdef __WXGTK24__ - // gtk_entry_set_alignment was introduced in gtk+-2.3.5 - if (!gtk_check_version(2,4,0)) - { - gfloat align; - if ( HasFlag(wxTE_RIGHT) ) - align = 1.0; - else if ( HasFlag(wxTE_CENTRE) ) - align = 0.5; - else // single line - align = 0.0; - - gtk_entry_set_alignment(GTK_ENTRY(m_text), align); - } -#endif // __WXGTK24__ - } + gfloat align; + if ( HasFlag(wxTE_RIGHT) ) + align = 1.0; + else if ( HasFlag(wxTE_CENTRE) ) + align = 0.5; + else // single line + align = 0.0; + gtk_entry_set_alignment(GTK_ENTRY(m_text), align); + } } void wxTextCtrl::SetWindowStyleFlag(long style) @@ -993,6 +982,22 @@ void wxTextCtrl::DoSetValue( const wxString &value, int flags ) return; } + if (value.IsEmpty()) + { + if ( !(flags & SetValue_SendEvent) ) + EnableTextChangedEvents(false); + + gtk_text_buffer_set_text( m_buffer, "", 0 ); + + if ( !(flags & SetValue_SendEvent) ) + EnableTextChangedEvents(true); + + return; + } + +#if wxUSE_UNICODE + const wxCharBuffer buffer(value.utf8_str()); +#else wxFontEncoding enc = m_defaultStyle.HasFont() ? m_defaultStyle.GetFont().GetEncoding() : wxFONTENCODING_SYSTEM; @@ -1007,6 +1012,7 @@ void wxTextCtrl::DoSetValue( const wxString &value, int flags ) wxLogWarning(_("Failed to set text in the text control.")); return; } +#endif if ( !(flags & SetValue_SendEvent) ) { @@ -1027,9 +1033,6 @@ void wxTextCtrl::DoSetValue( const wxString &value, int flags ) { EnableTextChangedEvents(true); } - - // This was added after discussion on the list - SetInsertionPoint(0); } void wxTextCtrl::WriteText( const wxString &text ) @@ -1045,6 +1048,9 @@ void wxTextCtrl::WriteText( const wxString &text ) return; } +#if wxUSE_UNICODE + const wxCharBuffer buffer(text.utf8_str()); +#else // check if we have a specific style for the current position wxFontEncoding enc = wxFONTENCODING_SYSTEM; wxTextAttr style; @@ -1065,6 +1071,7 @@ void wxTextCtrl::WriteText( const wxString &text ) wxLogWarning(_("Failed to insert text in the control.")); return; } +#endif // First remove the selection if there is one // TODO: Is there an easier GTK specific way to do this? @@ -1245,6 +1252,7 @@ bool wxTextCtrl::Enable( bool enable ) } gtk_widget_set_sensitive( m_text, enable ); + SetCursor(enable ? wxCursor(wxCURSOR_IBEAM) : wxCursor()); return true; } @@ -1337,8 +1345,7 @@ void wxTextCtrl::SetSelection( long from, long to ) gtk_text_buffer_get_iter_at_offset( m_buffer, &fromi, from ); gtk_text_buffer_get_iter_at_offset( m_buffer, &toi, to ); - gtk_text_buffer_place_cursor( m_buffer, &toi ); - gtk_text_buffer_move_mark_by_name( m_buffer, "selection_bound", &fromi ); + gtk_text_buffer_select_range( m_buffer, &fromi, &toi ); } else // single line { @@ -1550,7 +1557,7 @@ void wxTextCtrl::OnChar( wxKeyEvent &key_event ) wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); event.SetEventObject(this); event.SetString(GetValue()); - if ( GetEventHandler()->ProcessEvent(event) ) + if ( HandleWindowEvent(event) ) return; } } @@ -1741,60 +1748,52 @@ wxSize wxTextCtrl::DoGetBestSize() const // freeze/thaw // ---------------------------------------------------------------------------- -void wxTextCtrl::Freeze() +void wxTextCtrl::DoFreeze() { wxCHECK_RET(m_text != NULL, wxT("invalid text ctrl")); + wxWindow::DoFreeze(); + if ( HasFlag(wxTE_MULTILINE) ) { - if (m_freezeCount++ == 0) - { - // freeze textview updates and remove buffer - g_signal_connect (m_text, "expose_event", - G_CALLBACK (gtk_text_exposed_callback), this); - g_signal_connect (m_widget, "expose_event", - G_CALLBACK (gtk_text_exposed_callback), this); - gtk_widget_set_sensitive(m_widget, false); - g_object_ref(m_buffer); - GtkTextBuffer* buf_new = gtk_text_buffer_new(NULL); - GtkTextMark* mark = GTK_TEXT_VIEW(m_text)->first_para_mark; - gtk_text_view_set_buffer(GTK_TEXT_VIEW(m_text), buf_new); - // gtk_text_view_set_buffer adds its own reference - g_object_unref(buf_new); - // This mark should be deleted when the buffer is changed, - // but it's not (in GTK+ up to at least 2.10.6). - // Otherwise these anonymous marks start to build up in the buffer, - // and Freeze takes longer and longer each time it is called. - if (GTK_IS_TEXT_MARK(mark) && !gtk_text_mark_get_deleted(mark)) - gtk_text_buffer_delete_mark(m_buffer, mark); - } + GTKFreezeWidget(m_text); + + // removing buffer dramatically speeds up insertion: + g_object_ref(m_buffer); + GtkTextBuffer* buf_new = gtk_text_buffer_new(NULL); + GtkTextMark* mark = GTK_TEXT_VIEW(m_text)->first_para_mark; + gtk_text_view_set_buffer(GTK_TEXT_VIEW(m_text), buf_new); + // gtk_text_view_set_buffer adds its own reference + g_object_unref(buf_new); + // This mark should be deleted when the buffer is changed, + // but it's not (in GTK+ up to at least 2.10.6). + // Otherwise these anonymous marks start to build up in the buffer, + // and Freeze takes longer and longer each time it is called. + if (GTK_IS_TEXT_MARK(mark) && !gtk_text_mark_get_deleted(mark)) + gtk_text_buffer_delete_mark(m_buffer, mark); } } -void wxTextCtrl::Thaw() +void wxTextCtrl::DoThaw() { if ( HasFlag(wxTE_MULTILINE) ) { - wxCHECK_RET(m_freezeCount != 0, _T("Thaw() without matching Freeze()")); + // reattach buffer: + gtk_text_view_set_buffer(GTK_TEXT_VIEW(m_text), m_buffer); + g_object_unref(m_buffer); - if (--m_freezeCount == 0) + if (m_showPositionOnThaw != NULL) { - // Reattach buffer and thaw textview updates - gtk_text_view_set_buffer(GTK_TEXT_VIEW(m_text), m_buffer); - g_object_unref(m_buffer); - gtk_widget_set_sensitive(m_widget, true); - g_signal_handlers_disconnect_by_func (m_widget, - (gpointer) gtk_text_exposed_callback, this); - g_signal_handlers_disconnect_by_func (m_text, - (gpointer) gtk_text_exposed_callback, this); - if (m_showPositionOnThaw != NULL) - { - gtk_text_view_scroll_mark_onscreen( - GTK_TEXT_VIEW(m_text), m_showPositionOnThaw); - m_showPositionOnThaw = NULL; - } + gtk_text_view_scroll_mark_onscreen( + GTK_TEXT_VIEW(m_text), m_showPositionOnThaw); + m_showPositionOnThaw = NULL; } + + // and thaw the window + GTKThawWidget(m_text); } + + wxWindow::DoThaw(); } // ---------------------------------------------------------------------------- @@ -1846,8 +1845,8 @@ void wxTextCtrl::OnUrlMouseEvent(wxMouseEvent& event) InitCommandEvent(url_event); // Is that a good idea? Seems not (pleasure with gtk_text_view_start_selection_drag) - //event.Skip(!GetEventHandler()->ProcessEvent(url_event)); - GetEventHandler()->ProcessEvent(url_event); + //event.Skip(!HandleWindowEvent(url_event)); + HandleWindowEvent(url_event); } bool wxTextCtrl::GTKProcessEvent(wxEvent& event) const