]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/textctrl.cpp
Second part of #15224 fix: AddRows, AddColumns (dghart)
[wxWidgets.git] / src / gtk / textctrl.cpp
index 12d35c479b482cd8252891f4271387d602881faf..bce644abf474e58611ac79fe59d18dc5955363f5 100644 (file)
@@ -2,7 +2,6 @@
 // Name:        src/gtk/textctrl.cpp
 // Purpose:
 // Author:      Robert Roebling
-// Id:          $Id$
 // Copyright:   (c) 1998 Robert Roebling, Vadim Zeitlin, 2005 Mart Raudsepp
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
@@ -30,7 +29,9 @@
 #include <sys/stat.h>
 #include <ctype.h>
 
+#include <gtk/gtk.h>
 #include "wx/gtk/private.h"
+#include "wx/gtk/private/gtk2-compat.h"
 
 // ----------------------------------------------------------------------------
 // helpers
@@ -167,25 +168,29 @@ static void wxGtkTextApplyTagsFromAttr(GtkWidget *text,
         GtkJustification align;
         switch (attr.GetAlignment())
         {
-            default:
-                align = GTK_JUSTIFY_LEFT;
-                break;
             case wxTEXT_ALIGNMENT_RIGHT:
                 align = GTK_JUSTIFY_RIGHT;
                 break;
             case wxTEXT_ALIGNMENT_CENTER:
                 align = GTK_JUSTIFY_CENTER;
                 break;
+            case wxTEXT_ALIGNMENT_JUSTIFIED:
+#ifdef __WXGTK3__
+                align = GTK_JUSTIFY_FILL;
+                break;
+#elif GTK_CHECK_VERSION(2,11,0)
 // gtk+ doesn't support justify before gtk+-2.11.0 with pango-1.17 being available
 // (but if new enough pango isn't available it's a mere gtk warning)
-#if GTK_CHECK_VERSION(2,11,0)
-            case wxTEXT_ALIGNMENT_JUSTIFIED:
                 if (!gtk_check_version(2,11,0))
+                {
                     align = GTK_JUSTIFY_FILL;
-                else
-                    align = GTK_JUSTIFY_LEFT;
-                break;
+                    break;
+                }
+                // fallthrough
 #endif
+            default:
+                align = GTK_JUSTIFY_LEFT;
+                break;
         }
 
         g_snprintf(buf, sizeof(buf), "WXALIGNMENT %d", align);
@@ -455,6 +460,25 @@ au_check_range(GtkTextIter *s,
 //-----------------------------------------------------------------------------
 
 extern "C" {
+
+// Normal version used for detecting IME input and generating appropriate
+// events for it.
+void
+wx_insert_text_callback(GtkTextBuffer* buffer,
+                        GtkTextIter* WXUNUSED(end),
+                        gchar *text,
+                        gint WXUNUSED(len),
+                        wxTextCtrl *win)
+{
+    if ( win->GTKOnInsertText(text) )
+    {
+        // If we already handled the new text insertion, don't do it again.
+        g_signal_stop_emission_by_name (buffer, "insert_text");
+    }
+}
+
+
+// And an "after" version used for detecting URLs in the text.
 static void
 au_insert_text_callback(GtkTextBuffer * WXUNUSED(buffer),
                         GtkTextIter *end,
@@ -540,8 +564,6 @@ gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
     if ( win->IgnoreTextUpdate() )
         return;
 
-    if (!win->m_hasVMT) return;
-
     if ( win->MarkDirtyOnChange() )
         win->MarkDirty();
 
@@ -549,48 +571,6 @@ gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
 }
 }
 
-//-----------------------------------------------------------------------------
-//  clipboard events: "copy-clipboard", "cut-clipboard", "paste-clipboard"
-//-----------------------------------------------------------------------------
-
-// common part of the event handlers below
-static void
-handle_text_clipboard_callback( GtkWidget *widget, wxTextCtrl *win,
-                                wxEventType eventType, const gchar * signal_name)
-{
-    wxClipboardTextEvent event( eventType, win->GetId() );
-    event.SetEventObject( win );
-    if ( win->HandleWindowEvent( event ) )
-    {
-        // don't let the default processing to take place if we did something
-        // ourselves in the event handler
-        g_signal_stop_emission_by_name (widget, signal_name);
-    }
-}
-
-extern "C" {
-static void
-gtk_copy_clipboard_callback( GtkWidget *widget, wxTextCtrl *win )
-{
-    handle_text_clipboard_callback(
-        widget, win, wxEVT_COMMAND_TEXT_COPY, "copy-clipboard" );
-}
-
-static void
-gtk_cut_clipboard_callback( GtkWidget *widget, wxTextCtrl *win )
-{
-    handle_text_clipboard_callback(
-        widget, win, wxEVT_COMMAND_TEXT_CUT, "cut-clipboard" );
-}
-
-static void
-gtk_paste_clipboard_callback( GtkWidget *widget, wxTextCtrl *win )
-{
-    handle_text_clipboard_callback(
-        widget, win, wxEVT_COMMAND_TEXT_PASTE, "paste-clipboard" );
-}
-}
-
 //-----------------------------------------------------------------------------
 //  "mark_set"
 //-----------------------------------------------------------------------------
@@ -643,12 +623,23 @@ void wxTextCtrl::Init()
     SetUpdateFont(false);
 
     m_text = NULL;
+    m_buffer = NULL;
     m_showPositionOnThaw = NULL;
     m_anonymousMarkList = NULL;
 }
 
 wxTextCtrl::~wxTextCtrl()
 {
+    if (m_text)
+        GTKDisconnect(m_text);
+    if (m_buffer)
+        GTKDisconnect(m_buffer);
+
+    // this is also done by wxWindowGTK dtor, but has to be done here so our
+    // DoThaw() override is called
+    while (IsFrozen())
+        Thaw();
+
     if (m_anonymousMarkList)
         g_slist_free(m_anonymousMarkList);
 }
@@ -814,21 +805,23 @@ bool wxTextCtrl::Create( wxWindow *parent,
             gtk_text_buffer_get_end_iter(m_buffer, &end);
             au_check_range(&start, &end);
         }
+
+        // Also connect a normal (not "after") signal handler for checking for
+        // the IME-generated input.
+        g_signal_connect(m_buffer, "insert_text",
+                         G_CALLBACK(wx_insert_text_callback), this);
     }
     else // single line
     {
         // do the right thing with Enter presses depending on whether we have
         // wxTE_PROCESS_ENTER or not
         GTKSetActivatesDefault();
+
+        GTKConnectInsertTextSignal(GTK_ENTRY(m_text));
     }
 
 
-    g_signal_connect (m_text, "copy-clipboard",
-                      G_CALLBACK (gtk_copy_clipboard_callback), this);
-    g_signal_connect (m_text, "cut-clipboard",
-                      G_CALLBACK (gtk_cut_clipboard_callback), this);
-    g_signal_connect (m_text, "paste-clipboard",
-                      G_CALLBACK (gtk_paste_clipboard_callback), this);
+    GTKConnectClipboardSignals(m_text);
 
     m_cursor = wxCursor( wxCURSOR_IBEAM );
 
@@ -847,6 +840,30 @@ GtkEntry *wxTextCtrl::GetEntry() const
     return GTK_ENTRY(m_text);
 }
 
+int wxTextCtrl::GTKIMFilterKeypress(GdkEventKey* event) const
+{
+#if GTK_CHECK_VERSION(2, 22, 0)
+    if ( gtk_check_version(2, 12, 0) == 0 )
+    {
+        if ( IsSingleLine() )
+        {
+            return wxTextEntry::GTKIMFilterKeypress(event);
+        }
+        else
+        {
+            return gtk_text_view_im_context_filter_keypress(
+                        GTK_TEXT_VIEW(m_text),
+                        event
+                    );
+        }
+    }
+#else // GTK+ < 2.22
+    wxUnusedVar(event);
+#endif // GTK+ 2.22+
+
+    return FALSE;
+}
+
 // ----------------------------------------------------------------------------
 // flags handling
 // ----------------------------------------------------------------------------
@@ -1103,11 +1120,7 @@ void wxTextCtrl::WriteText( const wxString &text )
 #endif
 
     // First remove the selection if there is one
-    // TODO:  Is there an easier GTK specific way to do this?
-    long from, to;
-    GetSelection(&from, &to);
-    if (from != to)
-        Remove(from, to);
+    gtk_text_buffer_delete_selection(m_buffer, false, true);
 
     // Insert the text
     wxGtkTextInsert( m_text, m_buffer, m_defaultStyle, buffer );
@@ -1323,26 +1336,6 @@ bool wxTextCtrl::Enable( bool enable )
     return true;
 }
 
-// wxGTK-specific: called recursively by Enable,
-// to give widgets an opportunity to correct their colours after they
-// have been changed by Enable
-void wxTextCtrl::OnEnabled(bool WXUNUSED(enable))
-{
-    // If we have a custom background colour, we use this colour in both
-    // disabled and enabled mode, or we end up with a different colour under the
-    // text.
-    wxColour oldColour = GetBackgroundColour();
-    if (oldColour.IsOk())
-    {
-        // Need to set twice or it'll optimize the useful stuff out
-        if (oldColour == * wxWHITE)
-            SetBackgroundColour(*wxBLACK);
-        else
-            SetBackgroundColour(*wxWHITE);
-        SetBackgroundColour(oldColour);
-    }
-}
-
 void wxTextCtrl::MarkDirty()
 {
     m_modified = true;
@@ -1620,7 +1613,7 @@ void wxTextCtrl::OnChar( wxKeyEvent &key_event )
     {
         if ( HasFlag(wxTE_PROCESS_ENTER) )
         {
-            wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
+            wxCommandEvent event(wxEVT_TEXT_ENTER, m_windowId);
             event.SetEventObject(this);
             event.SetString(GetValue());
             if ( HandleWindowEvent(event) )
@@ -1645,7 +1638,12 @@ GdkWindow *wxTextCtrl::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
     }
     else
     {
+#ifdef __WXGTK3__
+        // no access to internal GdkWindows
+        return NULL;
+#else
         return gtk_entry_get_text_window(GTK_ENTRY(m_text));
+#endif
     }
 }
 
@@ -1792,7 +1790,7 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
 
 void wxTextCtrl::DoApplyWidgetStyle(GtkRcStyle *style)
 {
-    gtk_widget_modify_style(m_text, style);
+    GTKApplyStyle(m_text, style);
 }
 
 void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
@@ -1847,13 +1845,71 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
 
 wxSize wxTextCtrl::DoGetBestSize() const
 {
-    // FIXME should be different for multi-line controls...
-    wxSize ret( wxControl::DoGetBestSize() );
-    wxSize best(80, ret.y);
-    CacheBestSize(best);
-    return best;
+    return DoGetSizeFromTextSize(80);
 }
 
+wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const
+{
+    wxASSERT_MSG( m_widget, wxS("GetSizeFromTextSize called before creation") );
+
+    wxSize tsize(xlen, 0);
+    int cHeight = GetCharHeight();
+
+    if ( IsSingleLine() )
+    {
+        if ( HasFlag(wxBORDER_NONE) )
+        {
+            tsize.y = cHeight;
+#ifdef __WXGTK3__
+            tsize.IncBy(9, 0);
+#else
+            tsize.IncBy(4, 0);
+#endif // GTK3
+        }
+        else
+        {
+            // default height
+            tsize.y = GTKGetPreferredSize(m_widget).y;
+            // Add the margins we have previously set, but only the horizontal border
+            // as vertical one has been taken account at GTKGetPreferredSize().
+            // Also get other GTK+ margins.
+            tsize.IncBy( GTKGetEntryMargins(GetEntry()).x, 0);
+        }
+    }
+
+    //multiline
+    else
+    {
+        // add space for vertical scrollbar
+        if ( m_scrollBar[1] && !(m_windowStyle & wxTE_NO_VSCROLL) )
+            tsize.IncBy(GTKGetPreferredSize(GTK_WIDGET(m_scrollBar[1])).x + 3, 0);
+
+        // height
+        tsize.y = cHeight;
+        if ( ylen <= 0 )
+        {
+            tsize.y = 1 + cHeight * wxMax(wxMin(GetNumberOfLines(), 10), 2);
+            // add space for horizontal scrollbar
+            if ( m_scrollBar[0] && (m_windowStyle & wxHSCROLL) )
+                tsize.IncBy(0, GTKGetPreferredSize(GTK_WIDGET(m_scrollBar[0])).y + 3);
+        }
+
+        if ( !HasFlag(wxBORDER_NONE) )
+        {
+            // hardcode borders, margins, etc
+            tsize.IncBy(5, 4);
+        }
+    }
+
+    // Perhaps the user wants something different from CharHeight, or ylen
+    // is used as the height of a multiline text.
+    if ( ylen > 0 )
+        tsize.IncBy(0, ylen - cHeight);
+
+    return tsize;
+}
+
+
 // ----------------------------------------------------------------------------
 // freeze/thaw
 // ----------------------------------------------------------------------------
@@ -1862,12 +1918,10 @@ void wxTextCtrl::DoFreeze()
 {
     wxCHECK_RET(m_text != NULL, wxT("invalid text ctrl"));
 
-    wxWindow::DoFreeze();
+    GTKFreezeWidget(m_text);
 
     if ( HasFlag(wxTE_MULTILINE) )
     {
-        GTKFreezeWidget(m_text);
-
         // removing buffer dramatically speeds up insertion:
         g_object_ref(m_buffer);
         GtkTextBuffer* buf_new = gtk_text_buffer_new(NULL);
@@ -1908,12 +1962,9 @@ void wxTextCtrl::DoThaw()
                 GTK_TEXT_VIEW(m_text), m_showPositionOnThaw);
             m_showPositionOnThaw = NULL;
         }
-
-        // and thaw the window
-        GTKThawWidget(m_text);
     }
 
-    wxWindow::DoThaw();
+    GTKThawWidget(m_text);
 }
 
 // ----------------------------------------------------------------------------
@@ -1983,7 +2034,7 @@ bool wxTextCtrl::GTKProcessEvent(wxEvent& event) const
 wxVisualAttributes
 wxTextCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
 {
-    return GetDefaultAttributesFromGTKWidget(gtk_entry_new, true);
+    return GetDefaultAttributesFromGTKWidget(gtk_entry_new(), true);
 }
 
 #endif // wxUSE_TEXTCTRL