[gtk+/wip/baedert/drawing: 13/130] accellabel: Inherit from GtkWidget



commit e424646978bcf68d2b4cd45011427e08f1cd9322
Author: Timm Bäder <mail baedert org>
Date:   Wed May 24 15:39:39 2017 +0200

    accellabel: Inherit from GtkWidget
    
    Use a box and 2 labels.

 docs/reference/gtk/gtk4-sections.txt |    2 +
 gtk/gtkaccellabel.c                  |  254 +++++++++++++--------------------
 gtk/gtkaccellabel.h                  |   11 ++-
 gtk/gtklabel.c                       |   11 --
 gtk/gtkmenuitem.c                    |   24 ++-
 5 files changed, 127 insertions(+), 175 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 1bc1d5e..b99227b 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -143,6 +143,8 @@ gtk_accel_label_get_accel_width
 gtk_accel_label_set_accel
 gtk_accel_label_get_accel
 gtk_accel_label_refetch
+gtk_accel_label_set_label
+gtk_accel_label_get_label
 <SUBSECTION Standard>
 GTK_ACCEL_LABEL
 GTK_IS_ACCEL_LABEL
diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c
index b1a95b8..6aed168 100644
--- a/gtk/gtkaccellabel.c
+++ b/gtk/gtkaccellabel.c
@@ -40,6 +40,7 @@
 #include "gtkwidgetprivate.h"
 #include "gtkcssnodeprivate.h"
 #include "gtkcssstylepropertyprivate.h"
+#include "gtkbox.h"
 
 /**
  * SECTION:gtkaccellabel
@@ -99,30 +100,33 @@
  * # CSS nodes
  *
  * |[<!-- language="plain" -->
- * label
- * ╰── accelerator
+ * accellabel
+ * ╰── box
+ *     ├── label
+ *     ╰── accelerator
  * ]|
  *
- * Like #GtkLabel, GtkAccelLabel has a main CSS node with the name label.
- * It adds a subnode with name accelerator.
+ * #GtkAccelLabel has a main CSS node with the name accellabel.
+ * It adds a subnode with name label and another one with name accelerator.
  */
 
 enum {
   PROP_0,
   PROP_ACCEL_CLOSURE,
   PROP_ACCEL_WIDGET,
+  PROP_LABEL,
   LAST_PROP
 };
 
 struct _GtkAccelLabelPrivate
 {
+  GtkWidget     *box;
+  GtkWidget     *text_label;
+  GtkWidget     *accel_label;
+
   GtkWidget     *accel_widget;       /* done */
   GClosure      *accel_closure;      /* has set function */
   GtkAccelGroup *accel_group;        /* set by set_accel_closure() */
-  gchar         *accel_string;       /* has set function */
-  GtkCssNode    *accel_node;
-  guint          accel_padding;      /* should be style property? */
-  guint16        accel_string_width; /* seems to be private */
 
   guint           accel_key;         /* manual accel key specification if != 0 */
   GdkModifierType accel_mods;
@@ -142,7 +146,6 @@ static void         gtk_accel_label_destroy      (GtkWidget          *widget);
 static void         gtk_accel_label_finalize     (GObject            *object);
 static void         gtk_accel_label_snapshot     (GtkWidget          *widget,
                                                   GtkSnapshot        *snapshot);
-static const gchar *gtk_accel_label_get_string   (GtkAccelLabel      *accel_label);
 static void gtk_accel_label_measure (GtkWidget      *widget,
                                      GtkOrientation  orientation,
                                      int             for_size,
@@ -152,7 +155,17 @@ static void gtk_accel_label_measure (GtkWidget      *widget,
                                      int            *natural_baseline);
 
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelLabel, gtk_accel_label, GTK_TYPE_LABEL)
+G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelLabel, gtk_accel_label, GTK_TYPE_WIDGET)
+
+static void
+gtk_accel_label_size_allocate (GtkWidget     *widget,
+                               GtkAllocation *allocation)
+{
+  GtkAccelLabel *al = GTK_ACCEL_LABEL (widget);
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (al);
+
+  gtk_widget_size_allocate (priv->box, allocation);
+}
 
 static void
 gtk_accel_label_class_init (GtkAccelLabelClass *class)
@@ -164,8 +177,9 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
   gobject_class->set_property = gtk_accel_label_set_property;
   gobject_class->get_property = gtk_accel_label_get_property;
 
-  widget_class->snapshot = gtk_accel_label_snapshot;
   widget_class->measure = gtk_accel_label_measure;
+  widget_class->size_allocate = gtk_accel_label_size_allocate;
+  widget_class->snapshot = gtk_accel_label_snapshot;
   widget_class->destroy = gtk_accel_label_destroy;
 
   gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_ACCEL_LABEL);
@@ -219,7 +233,16 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
                          GTK_TYPE_WIDGET,
                          GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
+  props[PROP_LABEL] =
+    g_param_spec_string ("label",
+                         P_("Label"),
+                         P_("The text displayed next to the accelerator"),
+                         "",
+                         GTK_PARAM_READWRITE);
+
   g_object_class_install_properties (gobject_class, LAST_PROP, props);
+
+  gtk_widget_class_set_css_name (widget_class, "accellabel");
 }
 
 static void
@@ -240,6 +263,9 @@ gtk_accel_label_set_property (GObject      *object,
     case PROP_ACCEL_WIDGET:
       gtk_accel_label_set_accel_widget (accel_label, g_value_get_object (value));
       break;
+    case PROP_LABEL:
+      gtk_accel_label_set_label (accel_label, g_value_get_string (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -264,6 +290,9 @@ gtk_accel_label_get_property (GObject    *object,
     case PROP_ACCEL_WIDGET:
       g_value_set_object (value, accel_label->priv->accel_widget);
       break;
+    case PROP_LABEL:
+      g_value_set_string (value, gtk_accel_label_get_label (accel_label));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -271,38 +300,32 @@ gtk_accel_label_get_property (GObject    *object,
 }
 
 static void
-node_style_changed_cb (GtkCssNode        *node,
-                       GtkCssStyleChange *change,
-                       GtkWidget         *widget)
-{
-  if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_CLIP))
-    gtk_widget_queue_resize (widget);
-  else
-    gtk_widget_queue_draw (widget);
-}
-
-static void
 gtk_accel_label_init (GtkAccelLabel *accel_label)
 {
   GtkAccelLabelPrivate *priv;
-  GtkCssNode *widget_node;
+
+  gtk_widget_set_has_window (GTK_WIDGET (accel_label), FALSE);
 
   accel_label->priv = gtk_accel_label_get_instance_private (accel_label);
   priv = accel_label->priv;
 
-  priv->accel_padding = 3;
   priv->accel_widget = NULL;
   priv->accel_closure = NULL;
   priv->accel_group = NULL;
-  priv->accel_string = NULL;
-
-  widget_node = gtk_widget_get_css_node (GTK_WIDGET (accel_label));
-  priv->accel_node = gtk_css_node_new ();
-  gtk_css_node_set_name (priv->accel_node, I_("accelerator"));
-  gtk_css_node_set_parent (priv->accel_node, widget_node);
-  gtk_css_node_set_state (priv->accel_node, gtk_css_node_get_state (widget_node));
-  g_signal_connect_object (priv->accel_node, "style-changed", G_CALLBACK (node_style_changed_cb), 
accel_label, 0);
-  g_object_unref (priv->accel_node);
+
+  priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  priv->text_label = gtk_label_new ("");
+  gtk_widget_set_hexpand (priv->text_label, TRUE);
+  gtk_label_set_xalign (GTK_LABEL (priv->text_label), 0.0f);
+  gtk_label_set_use_underline (GTK_LABEL (priv->text_label), TRUE);
+  priv->accel_label = g_object_new (GTK_TYPE_LABEL,
+                                    "css-name", "accelerator",
+                                    NULL);
+
+  gtk_container_add (GTK_CONTAINER (priv->box), priv->text_label);
+  gtk_container_add (GTK_CONTAINER (priv->box), priv->accel_label);
+
+  gtk_widget_set_parent (priv->box, GTK_WIDGET (accel_label));
 }
 
 /**
@@ -322,7 +345,7 @@ gtk_accel_label_new (const gchar *string)
   
   accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
   
-  gtk_label_set_text (GTK_LABEL (accel_label), string);
+  gtk_label_set_label (GTK_LABEL (accel_label->priv->text_label), string);
   
   return GTK_WIDGET (accel_label);
 }
@@ -343,7 +366,7 @@ gtk_accel_label_finalize (GObject *object)
 {
   GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object);
 
-  g_free (accel_label->priv->accel_string);
+  gtk_widget_unparent (accel_label->priv->box);
 
   G_OBJECT_CLASS (gtk_accel_label_parent_class)->finalize (object);
 }
@@ -378,41 +401,15 @@ gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label)
 guint
 gtk_accel_label_get_accel_width (GtkAccelLabel *accel_label)
 {
-  g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), 0);
-
-  return (accel_label->priv->accel_string_width +
-         (accel_label->priv->accel_string_width ? accel_label->priv->accel_padding : 0));
-}
-
-static PangoLayout *
-gtk_accel_label_get_accel_layout (GtkAccelLabel *accel_label)
-{
-  GtkWidget *widget = GTK_WIDGET (accel_label);
-  GtkStyleContext *context;
-  PangoAttrList *attrs;
-  PangoLayout *layout;
-  PangoFontDescription *font_desc;
-
-  context = gtk_widget_get_style_context (widget);
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+  int min;
 
-  gtk_style_context_save_to_node (context, accel_label->priv->accel_node);
-
-  layout = gtk_widget_create_pango_layout (widget, gtk_accel_label_get_string (accel_label));
-
-  attrs = _gtk_style_context_get_pango_attributes (context);
-  if (!attrs)
-    attrs = pango_attr_list_new ();
-  gtk_style_context_get (context,
-                         "font", &font_desc,
-                         NULL);
-  pango_attr_list_change (attrs, pango_attr_font_desc_new (font_desc));
-  pango_font_description_free (font_desc);
-  pango_layout_set_attributes (layout, attrs);
-  pango_attr_list_unref (attrs);
+  g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), 0);
 
-  gtk_style_context_restore (context);
+  gtk_widget_measure (priv->accel_label, GTK_ORIENTATION_HORIZONTAL, -1,
+                      &min, NULL, NULL, NULL);
 
-  return layout;
+  return min;
 }
 
 static void
@@ -425,37 +422,11 @@ gtk_accel_label_measure (GtkWidget      *widget,
                          int            *natural_baseline)
 {
   GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget);
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
 
-  GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->measure (widget,
-                                                            orientation,
-                                                            for_size,
-                                                            minimum, natural,
-                                                            minimum_baseline, natural_baseline);
-
-  if (orientation == GTK_ORIENTATION_HORIZONTAL)
-    {
-      PangoLayout *layout;
-      int width;
-
-      layout = gtk_accel_label_get_accel_layout (accel_label);
-      pango_layout_get_pixel_size (layout, &width, NULL);
-      accel_label->priv->accel_string_width = width;
-
-      g_object_unref (layout);
-    }
-}
-
-static gint
-get_first_baseline (PangoLayout *layout)
-{
-  PangoLayoutIter *iter;
-  gint result;
-
-  iter = pango_layout_get_iter (layout);
-  result = pango_layout_iter_get_baseline (iter);
-  pango_layout_iter_free (iter);
-
-  return PANGO_PIXELS (result);
+  gtk_widget_measure (priv->box, orientation, for_size,
+                      minimum, natural,
+                      minimum_baseline, natural_baseline);
 }
 
 static void
@@ -463,44 +434,9 @@ gtk_accel_label_snapshot (GtkWidget   *widget,
                           GtkSnapshot *snapshot)
 {
   GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget);
-  guint ac_width;
-  GtkAllocation allocation;
-  GtkRequisition requisition;
-
-  GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->snapshot (widget, snapshot);
-
-  ac_width = gtk_accel_label_get_accel_width (accel_label);
-  gtk_widget_get_allocation (widget, &allocation);
-  gtk_widget_get_preferred_size (widget, NULL, &requisition);
-
-  if (allocation.width >= requisition.width + ac_width)
-    {
-      GtkStyleContext *context;
-      PangoLayout *label_layout;
-      PangoLayout *accel_layout;
-      gint x;
-      gint y;
-
-      context = gtk_widget_get_style_context (widget);
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
 
-      label_layout = gtk_label_get_layout (GTK_LABEL (accel_label));
-      accel_layout = gtk_accel_label_get_accel_layout (accel_label);
-
-      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-        x = 0;
-      else
-        x = gtk_widget_get_allocated_width (widget) - ac_width;
-
-      gtk_label_get_layout_offsets (GTK_LABEL (accel_label), NULL, &y);
-
-      y += get_first_baseline (label_layout) - get_first_baseline (accel_layout) - allocation.y;
-
-      gtk_style_context_save_to_node (context, accel_label->priv->accel_node);
-      gtk_snapshot_render_layout (snapshot, context, x, y, accel_layout);
-      gtk_style_context_restore (context);
-
-      g_object_unref (accel_layout);
-    }
+  gtk_widget_snapshot_child (widget, priv->box, snapshot);
 }
 
 static void
@@ -580,9 +516,7 @@ gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
 static void
 gtk_accel_label_reset (GtkAccelLabel *accel_label)
 {
-  g_clear_pointer (&accel_label->priv->accel_string, g_free);
-  
-  gtk_widget_queue_resize (GTK_WIDGET (accel_label));
+  gtk_accel_label_refetch (accel_label);
 }
 
 static void
@@ -644,15 +578,6 @@ find_accel (GtkAccelKey *key,
   return data == (gpointer) closure;
 }
 
-static const gchar *
-gtk_accel_label_get_string (GtkAccelLabel *accel_label)
-{
-  if (!accel_label->priv->accel_string)
-    gtk_accel_label_refetch (accel_label);
-  
-  return accel_label->priv->accel_string;
-}
-
 /* Underscores in key names are better displayed as spaces
  * E.g., Page_Up should be “Page Up”.
  *
@@ -935,11 +860,10 @@ gboolean
 gtk_accel_label_refetch (GtkAccelLabel *accel_label)
 {
   gboolean enable_accels;
+  char *accel_string = NULL;
 
   g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), FALSE);
 
-  g_clear_pointer (&accel_label->priv->accel_string, g_free);
-
   g_object_get (gtk_widget_get_settings (GTK_WIDGET (accel_label)),
                 "gtk-enable-accels", &enable_accels,
                 NULL);
@@ -979,19 +903,20 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
          GtkAccelLabelClass *klass;
 
          klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
-         accel_label->priv->accel_string =
-             _gtk_accel_label_class_get_accelerator_label (klass, accel_key, accel_mods);
+          accel_string = _gtk_accel_label_class_get_accelerator_label (klass, accel_key, accel_mods);
        }
 
       else
         /* Otherwise we have a closure with no key.  Show "-/-". */
-        accel_label->priv->accel_string = g_strdup ("-/-");
+        accel_string = g_strdup ("-/-");
     }
 
-  if (!accel_label->priv->accel_string)
-    accel_label->priv->accel_string = g_strdup ("");
+  if (!accel_string)
+    accel_string = g_strdup ("");
+
+  gtk_label_set_label (GTK_LABEL (accel_label->priv->accel_label), accel_string);
 
-  gtk_widget_queue_resize (GTK_WIDGET (accel_label));
+  g_free (accel_string);
 
   return FALSE;
 }
@@ -1046,3 +971,24 @@ gtk_accel_label_get_accel (GtkAccelLabel   *accel_label,
   *accelerator_key = accel_label->priv->accel_key;
   *accelerator_mods = accel_label->priv->accel_mods;
 }
+
+void
+gtk_accel_label_set_label (GtkAccelLabel *accel_label,
+                           const char    *text)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+  g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+
+  gtk_label_set_label (GTK_LABEL (priv->text_label), text);
+}
+
+const char *
+gtk_accel_label_get_label (GtkAccelLabel   *accel_label)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+  g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), NULL);
+
+  return gtk_label_get_label (GTK_LABEL (priv->text_label));
+}
diff --git a/gtk/gtkaccellabel.h b/gtk/gtkaccellabel.h
index 3f5a15e..678b081 100644
--- a/gtk/gtkaccellabel.h
+++ b/gtk/gtkaccellabel.h
@@ -56,13 +56,13 @@ typedef struct _GtkAccelLabelPrivate GtkAccelLabelPrivate;
  */
 struct _GtkAccelLabel
 {
-  GtkLabel label;
+  GtkWidget parent_instance;
   GtkAccelLabelPrivate *priv;
 };
 
 struct _GtkAccelLabelClass
 {
-  GtkLabelClass         parent_class;
+  GtkWidgetClass parent_class;
 
   gchar                *signal_quote1;
   gchar                *signal_quote2;
@@ -104,6 +104,13 @@ void       gtk_accel_label_get_accel         (GtkAccelLabel   *accel_label,
                                               guint           *accelerator_key,
                                               GdkModifierType *accelerator_mods);
 
+GDK_AVAILABLE_IN_3_92
+void      gtk_accel_label_set_label          (GtkAccelLabel   *accel_label,
+                                              const char      *text);
+
+GDK_AVAILABLE_IN_3_92
+const char * gtk_accel_label_get_label       (GtkAccelLabel   *accel_label);
+
 /* private */
 gchar *    _gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass,
                                                         guint               accelerator_key,
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index f8cc270..5005434 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -29,7 +29,6 @@
 
 #include "gtklabel.h"
 #include "gtklabelprivate.h"
-#include "gtkaccellabel.h"
 #include "gtkbindings.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
@@ -1829,8 +1828,6 @@ static void
 label_shortcut_setting_apply (GtkLabel *label)
 {
   gtk_label_recalculate (label);
-  if (GTK_IS_ACCEL_LABEL (label))
-    gtk_accel_label_refetch (GTK_ACCEL_LABEL (label));
 }
 
 static void
@@ -3928,14 +3925,6 @@ gtk_label_snapshot (GtkWidget   *widget,
   width = allocation.width;
   height = allocation.height;
 
-  if (GTK_IS_ACCEL_LABEL (widget))
-    {
-      guint ac_width = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
-      width -= ac_width;
-      if (_gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-        x += ac_width;
-    }
-
   if (priv->text && (*priv->text != '\0'))
     {
       lx = ly = 0;
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
index 43efece..ab130da 100644
--- a/gtk/gtkmenuitem.c
+++ b/gtk/gtkmenuitem.c
@@ -1292,9 +1292,10 @@ gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
   gtk_menu_item_ensure_label (menu_item);
 
   child = gtk_bin_get_child (GTK_BIN (menu_item));
-  if (GTK_IS_LABEL (child))
+  if (GTK_IS_LABEL (child) ||
+      GTK_IS_ACCEL_LABEL (child))
     {
-      gtk_label_set_label (GTK_LABEL (child), label ? label : "");
+      g_object_set (child, "label", label ? label : "", NULL);
 
       g_object_notify_by_pspec (G_OBJECT (menu_item), menu_item_props[PROP_LABEL]);
     }
@@ -1308,8 +1309,15 @@ gtk_real_menu_item_get_label (GtkMenuItem *menu_item)
   gtk_menu_item_ensure_label (menu_item);
 
   child = gtk_bin_get_child (GTK_BIN (menu_item));
-  if (GTK_IS_LABEL (child))
-    return gtk_label_get_label (GTK_LABEL (child));
+  if (GTK_IS_LABEL (child) ||
+      GTK_IS_ACCEL_LABEL (child))
+    {
+      const char *label;
+
+      g_object_get (child, "label", &label, NULL);
+
+      return label;
+    }
 
   return NULL;
 }
@@ -1818,7 +1826,7 @@ gtk_menu_item_ensure_label (GtkMenuItem *menu_item)
 
   if (!gtk_bin_get_child (GTK_BIN (menu_item)))
     {
-      accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, "xalign", 0.0, NULL);
+      accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
       gtk_widget_set_halign (accel_label, GTK_ALIGN_FILL);
       gtk_widget_set_valign (accel_label, GTK_ALIGN_CENTER);
 
@@ -1886,10 +1894,10 @@ gtk_menu_item_set_use_underline (GtkMenuItem *menu_item,
   gtk_menu_item_ensure_label (menu_item);
 
   child = gtk_bin_get_child (GTK_BIN (menu_item));
-  if (GTK_IS_LABEL (child) &&
-      gtk_label_get_use_underline (GTK_LABEL (child)) != setting)
+  if (GTK_IS_ACCEL_LABEL (child) &&
+      gtk_accel_label_get_use_underline (GTK_ACCEL_LABEL (child)) != setting)
     {
-      gtk_label_set_use_underline (GTK_LABEL (child), setting);
+      gtk_accel_label_set_use_underline (GTK_ACCEL_LABEL (child), setting);
       g_object_notify_by_pspec (G_OBJECT (menu_item), menu_item_props[PROP_USE_UNDERLINE]);
     }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]