]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtklabel.c
Deprecate widget flag: GTK_WIDGET_MAPPED
[~andy/gtk] / gtk / gtklabel.c
index 8342b8af27bde8fa2c03a7b6264cf26c02bfb2a1..c439280d4e73d4338ac6bdfb27067ed0f92bb1b9 100644 (file)
@@ -60,6 +60,7 @@ typedef struct
   gint width_chars;
   gint max_width_chars;
   gboolean full_size;
+  gboolean mnemonics_visible;
 } GtkLabelPrivate;
 
 /* Notes about the handling of links:
@@ -217,7 +218,8 @@ static void gtk_label_set_attributes_internal    (GtkLabel      *label,
 static void gtk_label_set_uline_text_internal    (GtkLabel      *label,
                                                  const gchar   *str);
 static void gtk_label_set_pattern_internal       (GtkLabel      *label,
-                                                 const gchar   *pattern);
+                                                 const gchar   *pattern,
+                                                  gboolean       is_mnemonic);
 static void gtk_label_set_markup_internal        (GtkLabel      *label,
                                                  const gchar   *str,
                                                  gboolean       with_uline);
@@ -265,6 +267,13 @@ static void     gtk_label_buildable_custom_finished    (GtkBuildable     *builda
                                                        gpointer          user_data);
 
 
+static void connect_mnemonics_visible_notify    (GtkLabel   *label);
+static gboolean      separate_uline_pattern     (const gchar  *str,
+                                                 guint        *accel_key,
+                                                 gchar       **new_str,
+                                                 gchar       **pattern);
+
+
 /* For selectable labels: */
 static void gtk_label_move_cursor        (GtkLabel        *label,
                                          GtkMovementStep  step,
@@ -1085,6 +1094,8 @@ gtk_label_init (GtkLabel *label)
   label->mnemonic_widget = NULL;
   label->mnemonic_window = NULL;
 
+  priv->mnemonics_visible = TRUE;
+
   gtk_label_set_text (label, "");
 }
 
@@ -1489,7 +1500,7 @@ gtk_label_mnemonic_activate (GtkWidget *widget,
   
   while (parent)
     {
-      if (GTK_WIDGET_CAN_FOCUS (parent) ||
+      if (gtk_widget_get_can_focus (parent) ||
          (!group_cycling && GTK_WIDGET_GET_CLASS (parent)->activate_signal) ||
           GTK_IS_NOTEBOOK (parent->parent) ||
          GTK_IS_MENU_ITEM (parent))
@@ -1533,10 +1544,12 @@ gtk_label_setup_mnemonic (GtkLabel *label,
     }
   
   if (label->mnemonic_keyval == GDK_VoidSymbol)
-    goto done;
+      goto done;
+
+  connect_mnemonics_visible_notify (GTK_LABEL (widget));
 
   toplevel = gtk_widget_get_toplevel (widget);
-  if (GTK_WIDGET_TOPLEVEL (toplevel))
+  if (gtk_widget_is_toplevel (toplevel))
     {
       GtkWidget *menu_shell;
       
@@ -1611,6 +1624,62 @@ label_shortcut_setting_changed (GtkSettings *settings)
   g_list_free (list);
 }
 
+static void
+mnemonics_visible_apply (GtkWidget *widget,
+                         gboolean   mnemonics_visible)
+{
+  GtkLabel *label;
+  GtkLabelPrivate *priv;
+
+  label = GTK_LABEL (widget);
+
+  priv = GTK_LABEL_GET_PRIVATE (label);
+
+  mnemonics_visible = mnemonics_visible != FALSE;
+
+  if (priv->mnemonics_visible != mnemonics_visible)
+    {
+      priv->mnemonics_visible = mnemonics_visible;
+
+      gtk_label_recalculate (label);
+    }
+}
+
+static void
+label_mnemonics_visible_traverse_container (GtkWidget *widget,
+                                            gpointer   data)
+{
+  gboolean mnemonics_visible = GPOINTER_TO_INT (data);
+
+  _gtk_label_mnemonics_visible_apply_recursively (widget, mnemonics_visible);
+}
+
+void
+_gtk_label_mnemonics_visible_apply_recursively (GtkWidget *widget,
+                                                gboolean   mnemonics_visible)
+{
+  if (GTK_IS_LABEL (widget))
+    mnemonics_visible_apply (widget, mnemonics_visible);
+  else if (GTK_IS_CONTAINER (widget))
+    gtk_container_forall (GTK_CONTAINER (widget),
+                          label_mnemonics_visible_traverse_container,
+                          GINT_TO_POINTER (mnemonics_visible));
+}
+
+static void
+label_mnemonics_visible_changed (GtkWindow  *window,
+                                 GParamSpec *pspec,
+                                 gpointer    data)
+{
+  gboolean mnemonics_visible;
+
+  g_object_get (window, "mnemonics-visible", &mnemonics_visible, NULL);
+
+  gtk_container_forall (GTK_CONTAINER (window),
+                        label_mnemonics_visible_traverse_container,
+                        GINT_TO_POINTER (mnemonics_visible));
+}
+
 static void
 gtk_label_screen_changed (GtkWidget *widget,
                          GdkScreen *old_screen)
@@ -1657,7 +1726,7 @@ label_mnemonic_widget_weak_notify (gpointer      data,
 /**
  * gtk_label_set_mnemonic_widget:
  * @label: a #GtkLabel
- * @widget: the target #GtkWidget 
+ * @widget: (allow-none): the target #GtkWidget
  *
  * If the label has been set so that it has an mnemonic key (using
  * i.e. gtk_label_set_markup_with_mnemonic(),
@@ -1797,20 +1866,23 @@ gtk_label_compose_effective_attrs (GtkLabel *label)
       if (label->effective_attrs)
        {
          if ((iter = pango_attr_list_get_iterator (label->attrs)))
-           do 
-             {
-               iter_attrs = pango_attr_iterator_get_attrs (iter);
-               for (l = iter_attrs; l; l = l->next)
-                 {
-                   attr = l->data;
-                   pango_attr_list_insert (label->effective_attrs, attr);
-                 }
-               g_slist_free (iter_attrs);
-             }
-           while (pango_attr_iterator_next (iter));
+           {
+             do
+               {
+                 iter_attrs = pango_attr_iterator_get_attrs (iter);
+                 for (l = iter_attrs; l; l = l->next)
+                   {
+                     attr = l->data;
+                     pango_attr_list_insert (label->effective_attrs, attr);
+                   }
+                 g_slist_free (iter_attrs);
+               }
+             while (pango_attr_iterator_next (iter));
+             pango_attr_iterator_destroy (iter);
+           }
        }
       else
-       label->effective_attrs = 
+       label->effective_attrs =
          pango_attr_list_ref (label->attrs);
     }
 }
@@ -1839,28 +1911,22 @@ gtk_label_recalculate (GtkLabel *label)
   guint keyval = label->mnemonic_keyval;
 
   if (label->use_markup)
-    {
-      gtk_label_set_markup_internal (label, label->label, label->use_underline);
-      gtk_label_compose_effective_attrs (label);
-    }
+    gtk_label_set_markup_internal (label, label->label, label->use_underline);
   else
     {
       if (label->use_underline)
-       {
-         gtk_label_set_uline_text_internal (label, label->label);
-         gtk_label_compose_effective_attrs (label);
-       }
+       gtk_label_set_uline_text_internal (label, label->label);
       else
-       {
-         gtk_label_set_text_internal (label, g_strdup (label->label));
-         if (label->attrs)
-           pango_attr_list_ref (label->attrs);
-         if (label->effective_attrs)
-           pango_attr_list_unref (label->effective_attrs);
-         label->effective_attrs = label->attrs;
-       }
+        {
+          if (label->effective_attrs)
+            pango_attr_list_unref (label->effective_attrs);
+          label->effective_attrs = NULL;
+          gtk_label_set_text_internal (label, g_strdup (label->label));
+        }
     }
 
+  gtk_label_compose_effective_attrs (label);
+
   if (!label->use_underline)
     label->mnemonic_keyval = GDK_VoidSymbol;
 
@@ -1927,7 +1993,7 @@ gtk_label_set_attributes (GtkLabel         *label,
 
   gtk_label_recalculate (label);
 
-  gtk_label_clear_layout (label);  
+  gtk_label_clear_layout (label);
   gtk_widget_queue_resize (GTK_WIDGET (label));
 }
 
@@ -2283,6 +2349,7 @@ gtk_label_set_markup_internal (GtkLabel    *label,
                                const gchar *str,
                                gboolean     with_uline)
 {
+  GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (label);
   gchar *text = NULL;
   GError *error = NULL;
   PangoAttrList *attrs = NULL;
@@ -2306,6 +2373,35 @@ gtk_label_set_markup_internal (GtkLabel    *label,
       gtk_label_ensure_has_tooltip (label);
     }
 
+  if (with_uline)
+    {
+      gboolean enable_mnemonics;
+      gboolean auto_mnemonics;
+
+      g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
+                    "gtk-enable-mnemonics", &enable_mnemonics,
+                    "gtk-auto-mnemonics", &auto_mnemonics,
+                    NULL);
+
+      if (!(enable_mnemonics && priv->mnemonics_visible &&
+            (!auto_mnemonics ||
+             (gtk_widget_is_sensitive (GTK_WIDGET (label)) &&
+              (!label->mnemonic_widget ||
+               gtk_widget_is_sensitive (label->mnemonic_widget))))))
+        {
+          gchar *tmp;
+          gchar *pattern;
+          guint key;
+
+          if (separate_uline_pattern (new_str, &key, &tmp, &pattern))
+            {
+              g_free (new_str);
+              new_str = tmp;
+              g_free (pattern);
+            }
+        }
+    }
+
   if (!pango_parse_markup (new_str,
                            -1,
                            with_uline ? '_' : 0,
@@ -2465,24 +2561,37 @@ gtk_label_pattern_to_attrs (GtkLabel      *label,
 
 static void
 gtk_label_set_pattern_internal (GtkLabel    *label,
-                               const gchar *pattern)
+                               const gchar *pattern,
+                                gboolean     is_mnemonic)
 {
+  GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (label);
   PangoAttrList *attrs;
   gboolean enable_mnemonics;
+  gboolean auto_mnemonics;
 
   g_return_if_fail (GTK_IS_LABEL (label));
 
   if (label->pattern_set)
     return;
 
-  g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
-               "gtk-enable-mnemonics", &enable_mnemonics,
-               NULL);
+  if (is_mnemonic)
+    {
+      g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
+                   "gtk-enable-mnemonics", &enable_mnemonics,
+                   "gtk-auto-mnemonics", &auto_mnemonics,
+                   NULL);
 
-  if (enable_mnemonics && pattern)
-    attrs = gtk_label_pattern_to_attrs (label, pattern);
+      if (enable_mnemonics && priv->mnemonics_visible && pattern &&
+          (!auto_mnemonics ||
+           (gtk_widget_is_sensitive (GTK_WIDGET (label)) &&
+            (!label->mnemonic_widget ||
+             gtk_widget_is_sensitive (label->mnemonic_widget)))))
+        attrs = gtk_label_pattern_to_attrs (label, pattern);
+      else
+        attrs = NULL;
+    }
   else
-    attrs = NULL;
+    attrs = gtk_label_pattern_to_attrs (label, pattern);
 
   if (label->effective_attrs)
     pango_attr_list_unref (label->effective_attrs);
@@ -2499,13 +2608,13 @@ gtk_label_set_pattern (GtkLabel    *label,
 
   if (pattern)
     {
-      gtk_label_set_pattern_internal (label, pattern);
+      gtk_label_set_pattern_internal (label, pattern, FALSE);
       label->pattern_set = TRUE;
     }
   else
     gtk_label_recalculate (label);
 
-  gtk_label_clear_layout (label);  
+  gtk_label_clear_layout (label);
   gtk_widget_queue_resize (GTK_WIDGET (label));
 }
 
@@ -3309,7 +3418,7 @@ gtk_label_update_cursor (GtkLabel *label)
       GdkDisplay *display;
       GdkCursor *cursor;
 
-      if (GTK_WIDGET_IS_SENSITIVE (label))
+      if (gtk_widget_is_sensitive (GTK_WIDGET (label)))
         {
           display = gtk_widget_get_display (GTK_WIDGET (label));
 
@@ -3493,13 +3602,15 @@ get_cursor_direction (GtkLabel *label)
 static void
 gtk_label_draw_cursor (GtkLabel  *label, gint xoffset, gint yoffset)
 {
+  GtkWidget *widget;
+
   if (label->select_info == NULL)
     return;
+
+  widget = GTK_WIDGET (label);
   
-  if (GTK_WIDGET_DRAWABLE (label))
+  if (gtk_widget_is_drawable (widget))
     {
-      GtkWidget *widget = GTK_WIDGET (label);
-
       PangoDirection keymap_direction;
       PangoDirection cursor_direction;
       PangoRectangle strong_pos, weak_pos;
@@ -3599,7 +3710,7 @@ gtk_label_expose (GtkWidget      *widget,
 
   gtk_label_ensure_layout (label);
   
-  if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
+  if (gtk_widget_get_visible (widget) && gtk_widget_get_mapped (widget) &&
       label->text && (*label->text != '\0'))
     {
       get_layout_location (label, &x, &y);
@@ -3645,7 +3756,7 @@ gtk_label_expose (GtkWidget      *widget,
 
 
          state = GTK_STATE_SELECTED;
-         if (!GTK_WIDGET_HAS_FOCUS (widget))
+         if (!gtk_widget_has_focus (widget))
            state = GTK_STATE_ACTIVE;
 
           gdk_draw_layout_with_colors (widget->window,
@@ -3670,7 +3781,7 @@ gtk_label_expose (GtkWidget      *widget,
           GdkColor *link_color;
           GdkColor *visited_link_color;
 
-          if (info->selectable && GTK_WIDGET_HAS_FOCUS (widget))
+          if (info->selectable && gtk_widget_has_focus (widget))
            gtk_label_draw_cursor (label, x, y);
 
           focus_link = gtk_label_get_focus_link (label);
@@ -3709,7 +3820,7 @@ gtk_label_expose (GtkWidget      *widget,
               gdk_region_destroy (clip);
             }
 
-          if (focus_link && GTK_WIDGET_HAS_FOCUS (widget))
+          if (focus_link && gtk_widget_has_focus (widget))
             {
               range[0] = focus_link->start;
               range[1] = focus_link->end;
@@ -3732,52 +3843,43 @@ gtk_label_expose (GtkWidget      *widget,
   return FALSE;
 }
 
-static void
-gtk_label_set_uline_text_internal (GtkLabel    *label,
-                                  const gchar *str)
+static gboolean
+separate_uline_pattern (const gchar  *str,
+                        guint        *accel_key,
+                        gchar       **new_str,
+                        gchar       **pattern)
 {
-  guint accel_key = GDK_VoidSymbol;
-
-  gchar *new_str;
-  gchar *pattern;
-  const gchar *src;
-  gchar *dest, *pattern_dest;
   gboolean underscore;
-      
-  g_return_if_fail (GTK_IS_LABEL (label));
-  g_return_if_fail (str != NULL);
+  const gchar *src;
+  gchar *dest;
+  gchar *pattern_dest;
+
+  *accel_key = GDK_VoidSymbol;
+  *new_str = g_new (gchar, strlen (str) + 1);
+  *pattern = g_new (gchar, g_utf8_strlen (str, -1) + 1);
 
-  /* Split text into the base text and a separate pattern
-   * of underscores.
-   */
-  
-  new_str = g_new (gchar, strlen (str) + 1);
-  pattern = g_new (gchar, g_utf8_strlen (str, -1) + 1);
-  
   underscore = FALSE;
 
-  if (str == NULL)
-    str = "";
-  
   src = str;
-  dest = new_str;
-  pattern_dest = pattern;
-  
+  dest = *new_str;
+  pattern_dest = *pattern;
+
   while (*src)
     {
       gunichar c;
-      gchar *next_src;
+      const gchar *next_src;
 
       c = g_utf8_get_char (src);
       if (c == (gunichar)-1)
        {
          g_warning ("Invalid input string");
-         g_free (new_str);
-         g_free (pattern);
-         return;
+         g_free (*new_str);
+         g_free (*pattern);
+
+         return FALSE;
        }
       next_src = g_utf8_next_char (src);
-      
+
       if (underscore)
        {
          if (c == '_')
@@ -3785,13 +3887,13 @@ gtk_label_set_uline_text_internal (GtkLabel    *label,
          else
            {
              *pattern_dest++ = '_';
-             if (accel_key == GDK_VoidSymbol)
-               accel_key = gdk_keyval_to_lower (gdk_unicode_to_keyval (c));
+             if (*accel_key == GDK_VoidSymbol)
+               *accel_key = gdk_keyval_to_lower (gdk_unicode_to_keyval (c));
            }
 
          while (src < next_src)
            *dest++ = *src++;
-         
+
          underscore = FALSE;
        }
       else
@@ -3805,23 +3907,43 @@ gtk_label_set_uline_text_internal (GtkLabel    *label,
            {
              while (src < next_src)
                *dest++ = *src++;
-         
+
              *pattern_dest++ = ' ';
            }
        }
     }
+
   *dest = 0;
   *pattern_dest = 0;
-  
-  gtk_label_set_text_internal (label, new_str);
-  gtk_label_set_pattern_internal (label, pattern);
-  
-  g_free (pattern);
 
+  return TRUE;
+}
+
+static void
+gtk_label_set_uline_text_internal (GtkLabel    *label,
+                                  const gchar *str)
+{
+  guint accel_key = GDK_VoidSymbol;
+  gchar *new_str;
+  gchar *pattern;
+
+  g_return_if_fail (GTK_IS_LABEL (label));
+  g_return_if_fail (str != NULL);
+
+  /* Split text into the base text and a separate pattern
+   * of underscores.
+   */
+  if (!separate_uline_pattern (str, &accel_key, &new_str, &pattern))
+    return;
+
+  gtk_label_set_text_internal (label, new_str);
+  gtk_label_set_pattern_internal (label, pattern, TRUE);
   label->mnemonic_keyval = accel_key;
+
+  g_free (pattern);
 }
 
-guint      
+guint
 gtk_label_parse_uline (GtkLabel    *label,
                       const gchar *str)
 {
@@ -4221,7 +4343,7 @@ gtk_label_button_press (GtkWidget      *widget,
 
   if (event->button == 1)
     {
-      if (!GTK_WIDGET_HAS_FOCUS (widget))
+      if (!gtk_widget_has_focus (widget))
        {
          label->in_click = TRUE;
          gtk_widget_grab_focus (widget);
@@ -4332,6 +4454,38 @@ gtk_label_button_release (GtkWidget      *widget,
   return TRUE;
 }
 
+static void
+connect_mnemonics_visible_notify (GtkLabel *label)
+{
+  GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (label);
+  GtkWidget *toplevel;
+  gboolean connected;
+
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
+
+  if (!GTK_IS_WINDOW (toplevel))
+    return;
+
+  /* always set up this widgets initial value */
+  priv->mnemonics_visible =
+    gtk_window_get_mnemonics_visible (GTK_WINDOW (toplevel));
+
+  connected =
+    GPOINTER_TO_INT (g_object_get_data (G_OBJECT (toplevel),
+                                        "gtk-label-mnemonics-visible-connected"));
+
+  if (!connected)
+    {
+      g_signal_connect (toplevel,
+                        "notify::mnemonics-visible",
+                        G_CALLBACK (label_mnemonics_visible_changed),
+                        label);
+      g_object_set_data (G_OBJECT (toplevel),
+                         "gtk-label-mnemonics-visible-connected",
+                         GINT_TO_POINTER (1));
+    }
+}
+
 static void
 drag_begin_cb (GtkWidget      *widget,
                GdkDragContext *context,
@@ -4567,7 +4721,7 @@ gtk_label_create_window (GtkLabel *label)
     GDK_POINTER_MOTION_MASK      |
     GDK_POINTER_MOTION_HINT_MASK;
   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
-  if (GTK_WIDGET_IS_SENSITIVE (widget))
+  if (gtk_widget_is_sensitive (widget))
     {
       attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
                                                      GDK_XTERM);
@@ -4603,12 +4757,12 @@ gtk_label_ensure_select_info (GtkLabel *label)
     {
       label->select_info = g_new0 (GtkLabelSelectionInfo, 1);
 
-      GTK_WIDGET_SET_FLAGS (label, GTK_CAN_FOCUS);
+      gtk_widget_set_can_focus (GTK_WIDGET (label), TRUE);
 
       if (GTK_WIDGET_REALIZED (label))
        gtk_label_create_window (label);
 
-      if (GTK_WIDGET_MAPPED (label))
+      if (gtk_widget_get_mapped (GTK_WIDGET (label)))
         gdk_window_show (label->select_info->window);
     }
 }
@@ -4626,7 +4780,7 @@ gtk_label_clear_select_info (GtkLabel *label)
       g_free (label->select_info);
       label->select_info = NULL;
 
-      GTK_WIDGET_UNSET_FLAGS (label, GTK_CAN_FOCUS);
+      gtk_widget_set_can_focus (GTK_WIDGET (label), FALSE);
     }
 }
 
@@ -5004,8 +5158,8 @@ gtk_label_get_selection_bounds (GtkLabel  *label,
  * pixel positions, in combination with gtk_label_get_layout_offsets().
  * The returned layout is owned by the label so need not be
  * freed by the caller.
- * 
- * Return value: the #PangoLayout for this label
+ *
+ * Return value: (transfer none): the #PangoLayout for this label
  **/
 PangoLayout*
 gtk_label_get_layout (GtkLabel *label)
@@ -5020,8 +5174,8 @@ gtk_label_get_layout (GtkLabel *label)
 /**
  * gtk_label_get_layout_offsets:
  * @label: a #GtkLabel
- * @x: location to store X offset of layout, or %NULL
- * @y: location to store Y offset of layout, or %NULL
+ * @x: (allow-none): location to store X offset of layout, or %NULL
+ * @y: (allow-none): location to store Y offset of layout, or %NULL
  *
  * Obtains the coordinates where the label will draw the #PangoLayout
  * representing the text in the label; useful to convert mouse events
@@ -5887,7 +6041,7 @@ gtk_label_activate_current_link (GtkLabel *label)
           if (window &&
               window->default_widget != widget &&
               !(widget == window->focus_widget &&
-                (!window->default_widget || !GTK_WIDGET_SENSITIVE (window->default_widget))))
+                (!window->default_widget || !gtk_widget_is_sensitive (window->default_widget))))
             gtk_window_activate_default (window);
         }
     }