]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkbutton.c
Apply a cleanup patch by Kjartan Maraas (#341812)
[~andy/gtk] / gtk / gtkbutton.c
index 6a88043a5aba4308614b3444160ab03b18167310..4c51a47d68493229109b4033cdc053f5a8f2eb7a 100644 (file)
@@ -33,6 +33,7 @@
 #include "gtkmarshalers.h"
 #include "gtkimage.h"
 #include "gtkhbox.h"
+#include "gtkvbox.h"
 #include "gtkstock.h"
 #include "gtkiconfactory.h"
 #include "gtkprivate.h"
@@ -68,6 +69,7 @@ enum {
   PROP_FOCUS_ON_CLICK,
   PROP_XALIGN,
   PROP_YALIGN,
+  PROP_IMAGE_POSITION
 };
 
 #define GTK_BUTTON_GET_PRIVATE(o)       (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_BUTTON, GtkButtonPrivate))
@@ -75,13 +77,14 @@ typedef struct _GtkButtonPrivate GtkButtonPrivate;
 
 struct _GtkButtonPrivate
 {
-  gfloat       xalign;
-  gfloat       yalign;
-  GtkWidget   *image;
-  guint        align_set : 1;
-  guint        image_is_stock : 1;
-  guint        has_grab : 1;
-  guint32      grab_time;
+  gfloat          xalign;
+  gfloat          yalign;
+  GtkWidget      *image;
+  guint           align_set      : 1;
+  guint           image_is_stock : 1;
+  guint           has_grab       : 1;
+  guint32         grab_time;
+  GtkPositionType image_position;
 };
 
 static void gtk_button_destroy        (GtkObject          *object);
@@ -99,6 +102,8 @@ static void gtk_button_realize        (GtkWidget          *widget);
 static void gtk_button_unrealize      (GtkWidget          *widget);
 static void gtk_button_map            (GtkWidget          *widget);
 static void gtk_button_unmap          (GtkWidget          *widget);
+static void gtk_button_style_set      (GtkWidget          *widget,
+                                      GtkStyle           *prev_style);
 static void gtk_button_size_request   (GtkWidget          *widget,
                                       GtkRequisition     *requisition);
 static void gtk_button_size_allocate  (GtkWidget          *widget,
@@ -165,6 +170,7 @@ gtk_button_class_init (GtkButtonClass *klass)
   widget_class->unrealize = gtk_button_unrealize;
   widget_class->map = gtk_button_map;
   widget_class->unmap = gtk_button_unmap;
+  widget_class->style_set = gtk_button_style_set;
   widget_class->size_request = gtk_button_size_request;
   widget_class->size_allocate = gtk_button_size_allocate;
   widget_class->expose_event = gtk_button_expose;
@@ -281,6 +287,22 @@ gtk_button_class_init (GtkButtonClass *klass)
                                                         GTK_TYPE_WIDGET,
                                                         GTK_PARAM_READWRITE));
 
+  /**
+   * GtkButton:image-position:
+   *
+   * The position of the image relative to the text inside the button.
+   * 
+   * Since: 2.10
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_IMAGE_POSITION,
+                                   g_param_spec_enum ("image-position",
+                                            P_("Image position"),
+                                                      P_("The position of the image relative to the text"),
+                                                      GTK_TYPE_POSITION_TYPE,
+                                                      GTK_POS_LEFT,
+                                                      GTK_PARAM_READWRITE));
+
   /**
    * GtkButton::pressed:
    * @button: the object that received the signal
@@ -442,6 +464,23 @@ gtk_button_class_init (GtkButtonClass *klass)
                                                                GTK_TYPE_BORDER,
                                                                GTK_PARAM_READABLE));
 
+  /**
+   * GtkButton::image-spacing:
+   * 
+   * Spacing in pixels between the image and label.
+   * 
+   * Since: 2.10
+   */
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_int ("image-spacing",
+                                                            P_("Image spacing"),
+                                                            P_("Spacing in pixels between the image and label"),
+                                                            0,
+                                                            G_MAXINT,
+                                                            2,
+                                                            GTK_PARAM_READABLE));
+  
+
   gtk_settings_install_property (g_param_spec_boolean ("gtk-button-images",
                                                       P_("Show button images"),
                                                       P_("Whether stock icons should be shown in buttons"),
@@ -475,6 +514,7 @@ gtk_button_init (GtkButton *button)
   priv->yalign = 0.5;
   priv->align_set = 0;
   priv->image_is_stock = TRUE;
+  priv->image_position = GTK_POS_LEFT;
 }
 
 static void
@@ -589,6 +629,9 @@ gtk_button_set_property (GObject         *object,
     case PROP_YALIGN:
       gtk_button_set_alignment (button, priv->xalign, g_value_get_float (value));
       break;
+    case PROP_IMAGE_POSITION:
+      gtk_button_set_image_position (button, g_value_get_enum (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -630,6 +673,9 @@ gtk_button_get_property (GObject         *object,
     case PROP_YALIGN:
       g_value_set_float (value, priv->yalign);
       break;
+    case PROP_IMAGE_POSITION:
+      g_value_set_enum (value, priv->image_position);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -666,10 +712,11 @@ gtk_button_construct_child (GtkButton *button)
   GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
   GtkStockItem item;
   GtkWidget *label;
-  GtkWidget *hbox;
+  GtkWidget *box;
   GtkWidget *align;
   GtkWidget *image = NULL;
   gchar *label_text = NULL;
+  gint image_spacing;
   
   if (!button->constructed)
     return;
@@ -677,6 +724,10 @@ gtk_button_construct_child (GtkButton *button)
   if (!button->label_text && !priv->image)
     return;
   
+  gtk_widget_style_get (GTK_WIDGET (button), 
+                       "image-spacing", &image_spacing, 
+                       NULL);
+
   if (priv->image && !priv->image_is_stock)
     {
       image = g_object_ref (priv->image);
@@ -705,19 +756,27 @@ gtk_button_construct_child (GtkButton *button)
   if (image)
     {
       priv->image = image;
-
       g_object_set (priv->image, 
                    "visible", show_image (button),
                    "no-show-all", TRUE,
                    NULL);
-      hbox = gtk_hbox_new (FALSE, 2);
+
+      if (priv->image_position == GTK_POS_LEFT ||
+         priv->image_position == GTK_POS_RIGHT)
+       box = gtk_hbox_new (FALSE, image_spacing);
+      else
+       box = gtk_vbox_new (FALSE, image_spacing);
 
       if (priv->align_set)
        align = gtk_alignment_new (priv->xalign, priv->yalign, 0.0, 0.0);
       else
        align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
-       
-      gtk_box_pack_start (GTK_BOX (hbox), priv->image, FALSE, FALSE, 0);
+
+      if (priv->image_position == GTK_POS_LEFT ||
+         priv->image_position == GTK_POS_TOP)
+       gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
+      else
+       gtk_box_pack_end (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
 
       if (label_text)
        {
@@ -725,11 +784,15 @@ gtk_button_construct_child (GtkButton *button)
          gtk_label_set_mnemonic_widget (GTK_LABEL (label), 
                                         GTK_WIDGET (button));
 
-         gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+         if (priv->image_position == GTK_POS_RIGHT ||
+             priv->image_position == GTK_POS_BOTTOM)
+           gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+         else
+           gtk_box_pack_end (GTK_BOX (box), label, FALSE, FALSE, 0);
        }
       
       gtk_container_add (GTK_CONTAINER (button), align);
-      gtk_container_add (GTK_CONTAINER (align), hbox);
+      gtk_container_add (GTK_CONTAINER (align), box);
       gtk_widget_show_all (align);
 
       g_object_unref (image);
@@ -941,6 +1004,42 @@ gtk_button_unmap (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_button_parent_class)->unmap (widget);
 }
 
+static void
+gtk_button_update_image_spacing (GtkButton *button)
+{
+  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+  GtkWidget *child; 
+  gint spacing;
+
+  /* Keep in sync with gtk_button_construct_child,
+   * we only want to update the spacing if the box 
+   * was constructed there.
+   */
+  if (!button->constructed || !priv->image)
+    return;
+
+  child = GTK_BIN (button)->child;
+  if (GTK_IS_ALIGNMENT (child))
+    {
+      child = GTK_BIN (child)->child;
+      if (GTK_IS_BOX (child))
+        {
+          gtk_widget_style_get (GTK_WIDGET (button),
+                                "image-spacing", &spacing,
+                                NULL);
+
+          gtk_box_set_spacing (GTK_BOX (child), spacing);
+        }
+    }   
+}
+
+static void
+gtk_button_style_set (GtkWidget *widget,
+                     GtkStyle  *prev_style)
+{
+  gtk_button_update_image_spacing (GTK_BUTTON (widget));
+}
+
 static void
 gtk_button_get_props (GtkButton *button,
                      GtkBorder *default_border,
@@ -1811,7 +1910,7 @@ gtk_button_screen_changed (GtkWidget *widget,
 
   show_image_connection =
     g_signal_connect (settings, "notify::gtk-button-images",
-                     G_CALLBACK (gtk_button_setting_changed), 0);
+                     G_CALLBACK (gtk_button_setting_changed), NULL);
   g_object_set_data (G_OBJECT (settings), 
                     I_("gtk-button-connection"),
                     GUINT_TO_POINTER (show_image_connection));
@@ -1899,6 +1998,62 @@ gtk_button_get_image (GtkButton *button)
   
   return priv->image;
 }
+
+/**
+ * gtk_button_set_image_position:
+ * @button: a #GtkButton
+ * @position: the position
+ *
+ * Sets the position of the image relative to the text 
+ * inside the button.
+ *
+ * Since: 2.10
+ */ 
+void
+gtk_button_set_image_position (GtkButton       *button,
+                              GtkPositionType  position)
+{
+
+  GtkButtonPrivate *priv;
+
+  g_return_if_fail (GTK_IS_BUTTON (button));
+  g_return_if_fail (position >= GTK_POS_LEFT && position <= GTK_POS_BOTTOM);
+  
+  priv = GTK_BUTTON_GET_PRIVATE (button);
+
+  if (priv->image_position != position)
+    {
+      priv->image_position = position;
+
+      gtk_button_construct_child (button);
+
+      g_object_notify (G_OBJECT (button), "image-position");
+    }
+}
+
+/**
+ * gtk_button_get_image_position:
+ * @button: a #GtkButton
+ *
+ * Gets the position of the image relative to the text 
+ * inside the button.
+ *
+ * Return value: the position
+ *
+ * Since: 2.10
+ */
+GtkPositionType
+gtk_button_get_image_position (GtkButton *button)
+{
+  GtkButtonPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_POS_LEFT);
+
+  priv = GTK_BUTTON_GET_PRIVATE (button);
   
+  return priv->image_position;
+}
+
+
 #define __GTK_BUTTON_C__
 #include "gtkaliasdef.c"