]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcellrenderertext.c
Add GtkBubbleWindow
[~andy/gtk] / gtk / gtkcellrenderertext.c
index e15deb7e8c0fd4595f6cc14aad19c25e5f5aa327..3399bb2be0450e7f63164e1200b3fb9b4a7e9a00 100644 (file)
@@ -12,9 +12,7 @@
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
@@ -30,6 +28,7 @@
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtktreeprivate.h"
+#include "a11y/gtktextcellaccessible.h"
 
 
 /**
@@ -108,7 +107,8 @@ enum {
   PROP_MAX_WIDTH_CHARS,
   PROP_WRAP_WIDTH,
   PROP_ALIGN,
-  
+  PROP_PLACEHOLDER_TEXT,
+
   /* Style args */
   PROP_BACKGROUND,
   PROP_FOREGROUND,
@@ -161,19 +161,18 @@ struct _GtkCellRendererTextPrivate
 {
   GtkWidget *entry;
 
-  PangoAlignment        align;
   PangoAttrList        *extra_attrs;
   GdkRGBA               foreground;
   GdkRGBA               background;
+  PangoAlignment        align;
   PangoEllipsizeMode    ellipsize;
   PangoFontDescription *font;
   PangoLanguage        *language;
   PangoUnderline        underline_style;
   PangoWrapMode         wrap_mode;
 
-  gboolean in_entry_menu;
-
   gchar *text;
+  gchar *placeholder_text;
 
   gdouble font_scale;
 
@@ -183,6 +182,7 @@ struct _GtkCellRendererTextPrivate
   gint max_width_chars;
   gint wrap_width;
 
+  guint in_entry_menu     : 1;
   guint strikethrough     : 1;
   guint editable          : 1;
   guint scale_set         : 1;
@@ -290,13 +290,20 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
                                                         NULL,
                                                         GTK_PARAM_WRITABLE));
 
+  /**
+   * GtkCellRendererText:background-gdk:
+   *
+   * Background color as a #GdkColor
+   *
+   * Deprecated: 3.4: Use #GtkCellRendererText:background-rgba instead.
+   */
   g_object_class_install_property (object_class,
                                    PROP_BACKGROUND_GDK,
                                    g_param_spec_boxed ("background-gdk",
                                                        P_("Background color"),
                                                        P_("Background color as a GdkColor"),
                                                        GDK_TYPE_COLOR,
-                                                       GTK_PARAM_READWRITE));  
+                                                       GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
 
   /**
    * GtkCellRendererText:background-rgba:
@@ -320,13 +327,20 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
                                                         NULL,
                                                         GTK_PARAM_WRITABLE));
 
+  /**
+   * GtkCellRendererText:foreground-gdk:
+   *
+   * Foreground color as a #GdkColor
+   *
+   * Deprecated: 3.4: Use #GtkCellRendererText:foreground-rgba instead.
+   */
   g_object_class_install_property (object_class,
                                    PROP_FOREGROUND_GDK,
                                    g_param_spec_boxed ("foreground-gdk",
                                                        P_("Foreground color"),
                                                        P_("Foreground color as a GdkColor"),
                                                        GDK_TYPE_COLOR,
-                                                       GTK_PARAM_READWRITE));
+                                                       GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
 
   /**
    * GtkCellRendererText:foreground-rgba:
@@ -607,7 +621,22 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
                                                      PANGO_TYPE_ALIGNMENT,
                                                      PANGO_ALIGN_LEFT,
                                                      GTK_PARAM_READWRITE));
-  
+
+  /**
+   * GtkCellRendererText:placeholder-text:
+   *
+   * The text that will be displayed in the #GtkCellRenderer if
+   * #GtkCellRendererText:editable is %TRUE and the cell is empty.
+   *
+   * Since 3.6
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_PLACEHOLDER_TEXT,
+                                   g_param_spec_string ("placeholder-text",
+                                                        P_("Placeholder text"),
+                                                        P_("Text rendered when an editable cell is empty"),
+                                                        NULL,
+                                                        GTK_PARAM_READWRITE));
 
 
   /* Style props are set or not */
@@ -679,7 +708,7 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
                 P_("Whether this tag affects the alignment mode"));
 
   /**
-   * GtkCellRendererText::edited
+   * GtkCellRendererText::edited:
    * @renderer: the object which received the signal
    * @path: the path identifying the edited cell
    * @new_text: the new text
@@ -701,6 +730,8 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
                  G_TYPE_STRING);
 
   g_type_class_add_private (object_class, sizeof (GtkCellRendererTextPrivate));
+
+  gtk_cell_renderer_class_set_accessible_type (cell_class, GTK_TYPE_TEXT_CELL_ACCESSIBLE);
 }
 
 static void
@@ -712,6 +743,7 @@ gtk_cell_renderer_text_finalize (GObject *object)
   pango_font_description_free (priv->font);
 
   g_free (priv->text);
+  g_free (priv->placeholder_text);
 
   if (priv->extra_attrs)
     pango_attr_list_unref (priv->extra_attrs);
@@ -719,6 +751,8 @@ gtk_cell_renderer_text_finalize (GObject *object)
   if (priv->language)
     g_object_unref (priv->language);
 
+  g_clear_object (&priv->entry);
+
   G_OBJECT_CLASS (gtk_cell_renderer_text_parent_class)->finalize (object);
 }
 
@@ -936,6 +970,10 @@ gtk_cell_renderer_text_get_property (GObject        *object,
       g_value_set_int (value, priv->max_width_chars);
       break;  
 
+    case PROP_PLACEHOLDER_TEXT:
+      g_value_set_string (value, priv->placeholder_text);
+      break;
+
     case PROP_BACKGROUND:
     case PROP_FOREGROUND:
     case PROP_MARKUP:
@@ -1496,7 +1534,12 @@ gtk_cell_renderer_text_set_property (GObject      *object,
     case PROP_ALIGN_SET:
       priv->align_set = g_value_get_boolean (value);
       break;
-      
+
+    case PROP_PLACEHOLDER_TEXT:
+      g_free (priv->placeholder_text);
+      priv->placeholder_text = g_value_dup_string (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -1522,6 +1565,15 @@ gtk_cell_renderer_text_new (void)
   return g_object_new (GTK_TYPE_CELL_RENDERER_TEXT, NULL);
 }
 
+static inline gboolean
+show_placeholder_text (GtkCellRendererText *celltext)
+{
+  GtkCellRendererTextPrivate *priv = celltext->priv;
+
+  return priv->editable && priv->placeholder_text &&
+    (!priv->text || !priv->text[0]);
+}
+
 static void
 add_attr (PangoAttrList  *attr_list,
           PangoAttribute *attr)
@@ -1543,8 +1595,10 @@ get_layout (GtkCellRendererText *celltext,
   PangoLayout *layout;
   PangoUnderline uline;
   gint xpad;
+  gboolean placeholder_layout = show_placeholder_text (celltext);
 
-  layout = gtk_widget_create_pango_layout (widget, priv->text);
+  layout = gtk_widget_create_pango_layout (widget, placeholder_layout ?
+                                           priv->placeholder_text : priv->text);
 
   gtk_cell_renderer_get_padding (GTK_CELL_RENDERER (celltext), &xpad, NULL);
 
@@ -1555,7 +1609,7 @@ get_layout (GtkCellRendererText *celltext,
 
   pango_layout_set_single_paragraph_mode (layout, priv->single_paragraph);
 
-  if (cell_area)
+  if (!placeholder_layout && cell_area)
     {
       /* Add options that affect appearance but not size */
       
@@ -1580,6 +1634,22 @@ get_layout (GtkCellRendererText *celltext,
         add_attr (attr_list,
                   pango_attr_strikethrough_new (priv->strikethrough));
     }
+  else if (placeholder_layout)
+    {
+      PangoColor color;
+      GtkStyleContext *context;
+      GdkRGBA fg = { 0.5, 0.5, 0.5 };
+
+      context = gtk_widget_get_style_context (widget);
+      gtk_style_context_lookup_color (context, "placeholder_text_color", &fg);
+
+      color.red = CLAMP (fg.red * 65535. + 0.5, 0, 65535);
+      color.green = CLAMP (fg.green * 65535. + 0.5, 0, 65535);
+      color.blue = CLAMP (fg.blue * 65535. + 0.5, 0, 65535);
+
+      add_attr (attr_list,
+                pango_attr_foreground_new (color.red, color.green, color.blue));
+    }
 
   add_attr (attr_list, pango_attr_font_desc_new (priv->font));
 
@@ -1690,12 +1760,17 @@ get_size (GtkCellRenderer    *cell,
 
   if (priv->calc_fixed_height)
     {
+      GtkStyleContext *style_context;
+      GtkStateFlags state;
       PangoContext *context;
       PangoFontMetrics *metrics;
       PangoFontDescription *font_desc;
       gint row_height;
 
-      font_desc = pango_font_description_copy_static (gtk_widget_get_style (widget)->font_desc);
+      style_context = gtk_widget_get_style_context (widget);
+      state = gtk_widget_get_state_flags (widget);
+
+      gtk_style_context_get (style_context, state, "font", &font_desc, NULL);
       pango_font_description_merge_static (font_desc, priv->font, TRUE);
 
       if (priv->scale_set)
@@ -1787,8 +1862,8 @@ gtk_cell_renderer_text_render (GtkCellRenderer      *cell,
 {
   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell);
   GtkCellRendererTextPrivate *priv = celltext->priv;
+  GtkStyleContext *context;
   PangoLayout *layout;
-  GtkStateType state;
   gint x_offset = 0;
   gint y_offset = 0;
   gint xpad, ypad;
@@ -1796,30 +1871,7 @@ gtk_cell_renderer_text_render (GtkCellRenderer      *cell,
 
   layout = get_layout (celltext, widget, cell_area, flags);
   get_size (cell, widget, cell_area, layout, &x_offset, &y_offset, NULL, NULL);
-
-  if (!gtk_cell_renderer_get_sensitive (cell))
-    {
-      state = GTK_STATE_INSENSITIVE;
-    }
-  else if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
-    {
-      if (gtk_widget_has_focus (widget))
-       state = GTK_STATE_SELECTED;
-      else
-       state = GTK_STATE_ACTIVE;
-    }
-  else if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT &&
-          gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT)
-    {
-      state = GTK_STATE_PRELIGHT;
-    }
-  else
-    {
-      if (gtk_widget_get_state (widget) == GTK_STATE_INSENSITIVE)
-       state = GTK_STATE_INSENSITIVE;
-      else
-       state = GTK_STATE_NORMAL;
-    }
+  context = gtk_widget_get_style_context (widget);
 
   if (priv->background_set && (flags & GTK_CELL_RENDERER_SELECTED) == 0)
     {
@@ -1844,15 +1896,10 @@ gtk_cell_renderer_text_render (GtkCellRenderer      *cell,
   gdk_cairo_rectangle (cr, cell_area);
   cairo_clip (cr);
 
-  gtk_paint_layout (gtk_widget_get_style (widget),
-                          cr,
-                          state,
-                          TRUE,
-                          widget,
-                          "cellrenderertext",
-                          cell_area->x + x_offset + xpad,
-                          cell_area->y + y_offset + ypad,
-                          layout);
+  gtk_render_layout (context, cr,
+                     cell_area->x + x_offset + xpad,
+                     cell_area->y + y_offset + ypad,
+                     layout);
 
   cairo_restore (cr);
 
@@ -1870,7 +1917,7 @@ gtk_cell_renderer_text_editing_done (GtkCellEditable *entry,
 
   priv = GTK_CELL_RENDERER_TEXT (data)->priv;
 
-  priv->entry = NULL;
+  g_clear_object (&priv->entry);
 
   if (priv->focus_out_id > 0)
     {
@@ -1988,7 +2035,6 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer      *cell,
                                      const GdkRectangle   *cell_area,
                                      GtkCellRendererState  flags)
 {
-  GtkRequisition requisition;
   GtkCellRendererText *celltext;
   GtkCellRendererTextPrivate *priv;
   gfloat xalign, yalign;
@@ -2003,6 +2049,8 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer      *cell,
   gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
 
   priv->entry = gtk_entry_new ();
+  g_object_ref_sink (G_OBJECT (priv->entry));
+
   gtk_entry_set_has_frame (GTK_ENTRY (priv->entry), FALSE);
   gtk_entry_set_alignment (GTK_ENTRY (priv->entry), xalign);
 
@@ -2012,33 +2060,6 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer      *cell,
   
   gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1);
 
-  gtk_widget_get_preferred_size (priv->entry, &requisition, NULL);
-  if (requisition.height < cell_area->height)
-    {
-      GtkBorder *style_border;
-      GtkBorder border;
-
-      gtk_widget_style_get (priv->entry,
-                           "inner-border", &style_border,
-                           NULL);
-
-      if (style_border)
-        {
-         border = *style_border;
-         g_boxed_free (GTK_TYPE_BORDER, style_border);
-       }
-      else
-        {
-         /* Since boxed style properties can't have default values ... */
-         border.left = 2;
-         border.right = 2;
-       }
-
-      border.top = (cell_area->height - requisition.height) / 2;
-      border.bottom = (cell_area->height - requisition.height) / 2;
-      gtk_entry_set_inner_border (GTK_ENTRY (priv->entry), &border);
-    }
-
   priv->in_entry_menu = FALSE;
   if (priv->entry_menu_popdown_timeout)
     {
@@ -2111,7 +2132,6 @@ gtk_cell_renderer_text_get_preferred_width (GtkCellRenderer *cell,
 {
   GtkCellRendererTextPrivate *priv;
   GtkCellRendererText        *celltext;
-  GtkStyle                   *style;
   PangoLayout                *layout;
   PangoContext               *context;
   PangoFontMetrics           *metrics;
@@ -2131,8 +2151,6 @@ gtk_cell_renderer_text_get_preferred_width (GtkCellRenderer *cell,
   celltext = GTK_CELL_RENDERER_TEXT (cell);
   priv = celltext->priv;
 
-  style = gtk_widget_get_style (widget);
-
   gtk_cell_renderer_get_padding (cell, &xpad, NULL);
 
   layout = get_layout (celltext, widget, NULL, 0);
@@ -2144,7 +2162,8 @@ gtk_cell_renderer_text_get_preferred_width (GtkCellRenderer *cell,
 
   /* Fetch the average size of a charachter */
   context = pango_layout_get_context (layout);
-  metrics = pango_context_get_metrics (context, style->font_desc,
+  metrics = pango_context_get_metrics (context,
+                                       pango_context_get_font_description (context),
                                        pango_context_get_language (context));
 
   char_width = pango_font_metrics_get_approximate_char_width (metrics);