]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkbutton.c
Move GtkSizeRequest into GtkWidget
[~andy/gtk] / gtk / gtkbutton.c
index d9d10478d9c583ce66a88f9c5f8e5adc4e43d9b8..e36e8e8211debf42565a45faf1b819c8d0a4152c 100644 (file)
@@ -128,7 +128,7 @@ static void gtk_button_unmap (GtkWidget * widget);
 static void gtk_button_style_set (GtkWidget * widget, GtkStyle * prev_style);
 static void gtk_button_size_allocate (GtkWidget * widget,
                                      GtkAllocation * allocation);
-static gint gtk_button_expose (GtkWidget * widget, GdkEventExpose * event);
+static gint gtk_button_draw (GtkWidget * widget, cairo_t *cr);
 static gint gtk_button_button_press (GtkWidget * widget,
                                     GdkEventButton * event);
 static gint gtk_button_button_release (GtkWidget * widget,
@@ -172,11 +172,10 @@ static void gtk_button_set_related_action        (GtkButton            *button,
 static void gtk_button_set_use_action_appearance (GtkButton            *button,
                                                  gboolean              use_appearance);
 
-static void gtk_button_size_request_init         (GtkSizeRequestIface *iface);
-static void gtk_button_get_width                 (GtkSizeRequest      *widget,
+static void gtk_button_get_preferred_width       (GtkWidget           *widget,
                                                  gint                *minimum_size,
                                                  gint                *natural_size);
-static void gtk_button_get_height                (GtkSizeRequest      *widget,
+static void gtk_button_get_preferred_height      (GtkWidget           *widget,
                                                  gint                *minimum_size,
                                                  gint                *natural_size);
   
@@ -184,9 +183,7 @@ static guint button_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
-                                               gtk_button_activatable_interface_init)
-                        G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST,
-                                               gtk_button_size_request_init))
+                                               gtk_button_activatable_interface_init))
 
 static void
 gtk_button_class_init (GtkButtonClass *klass)
@@ -208,6 +205,8 @@ gtk_button_class_init (GtkButtonClass *klass)
 
   object_class->destroy = gtk_button_destroy;
 
+  widget_class->get_preferred_width  = gtk_button_get_preferred_width;
+  widget_class->get_preferred_height = gtk_button_get_preferred_height;
   widget_class->screen_changed = gtk_button_screen_changed;
   widget_class->realize = gtk_button_realize;
   widget_class->unrealize = gtk_button_unrealize;
@@ -215,7 +214,7 @@ gtk_button_class_init (GtkButtonClass *klass)
   widget_class->unmap = gtk_button_unmap;
   widget_class->style_set = gtk_button_style_set;
   widget_class->size_allocate = gtk_button_size_allocate;
-  widget_class->expose_event = gtk_button_expose;
+  widget_class->draw = gtk_button_draw;
   widget_class->button_press_event = gtk_button_button_press;
   widget_class->button_release_event = gtk_button_button_release;
   widget_class->grab_broken_event = gtk_button_grab_broken;
@@ -227,6 +226,7 @@ gtk_button_class_init (GtkButtonClass *klass)
 
   container_class->child_type = gtk_button_child_type;
   container_class->add = gtk_button_add;
+  gtk_container_class_handle_border_width (container_class);
 
   klass->pressed = gtk_real_button_pressed;
   klass->released = gtk_real_button_released;
@@ -1004,9 +1004,13 @@ gtk_button_construct_child (GtkButton *button)
 
   if (priv->image && !priv->image_is_stock)
     {
+      GtkWidget *parent;
+
       image = g_object_ref (priv->image);
-      if (image->parent)
-       gtk_container_remove (GTK_CONTAINER (image->parent), image);
+
+      parent = gtk_widget_get_parent (image);
+      if (parent)
+       gtk_container_remove (GTK_CONTAINER (parent), image);
     }
 
   priv->image = NULL;
@@ -1275,21 +1279,21 @@ gtk_button_get_relief (GtkButton *button)
 static void
 gtk_button_realize (GtkWidget *widget)
 {
-  GtkButton *button;
+  GtkButton *button = GTK_BUTTON (widget);
+  GtkAllocation allocation;
+  GdkWindow *window;
   GdkWindowAttr attributes;
   gint attributes_mask;
-  gint border_width;
 
-  button = GTK_BUTTON (widget);
-  gtk_widget_set_realized (widget, TRUE);
+  gtk_widget_get_allocation (widget, &allocation);
 
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+  gtk_widget_set_realized (widget, TRUE);
 
   attributes.window_type = GDK_WINDOW_CHILD;
-  attributes.x = widget->allocation.x + border_width;
-  attributes.y = widget->allocation.y + border_width;
-  attributes.width = widget->allocation.width - border_width * 2;
-  attributes.height = widget->allocation.height - border_width * 2;
+  attributes.x = allocation.x;
+  attributes.y = allocation.y;
+  attributes.width = allocation.width;
+  attributes.height = allocation.height;
   attributes.wclass = GDK_INPUT_ONLY;
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
@@ -1299,14 +1303,15 @@ gtk_button_realize (GtkWidget *widget)
 
   attributes_mask = GDK_WA_X | GDK_WA_Y;
 
-  widget->window = gtk_widget_get_parent_window (widget);
-  g_object_ref (widget->window);
-  
-  button->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
+  window = gtk_widget_get_parent_window (widget);
+  gtk_widget_set_window (widget, window);
+  g_object_ref (window);
+
+  button->event_window = gdk_window_new (window,
                                         &attributes, attributes_mask);
   gdk_window_set_user_data (button->event_window, button);
 
-  widget->style = gtk_style_attach (widget->style, widget->window);
+  gtk_widget_style_attach (widget);
 }
 
 static void
@@ -1444,51 +1449,51 @@ gtk_button_size_allocate (GtkWidget     *widget,
 {
   GtkButton *button = GTK_BUTTON (widget);
   GtkAllocation child_allocation;
+  GtkStyle *style;
   GtkWidget *child;
 
-  guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-  gint xthickness = GTK_WIDGET (widget)->style->xthickness;
-  gint ythickness = GTK_WIDGET (widget)->style->ythickness;
+  gint xthickness, ythickness;
   GtkBorder default_border;
   GtkBorder inner_border;
   gint focus_width;
   gint focus_pad;
 
+  style = gtk_widget_get_style (widget);
+  xthickness = style->xthickness;
+  ythickness = style->ythickness;
+
   gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
   gtk_widget_style_get (GTK_WIDGET (widget),
                        "focus-line-width", &focus_width,
                        "focus-padding", &focus_pad,
                        NULL);
-                           
-  widget->allocation = *allocation;
+
+  gtk_widget_set_allocation (widget, allocation);
 
   if (gtk_widget_get_realized (widget))
     gdk_window_move_resize (button->event_window,
-                           widget->allocation.x + border_width,
-                           widget->allocation.y + border_width,
-                           widget->allocation.width - border_width * 2,
-                           widget->allocation.height - border_width * 2);
+                            allocation->x,
+                            allocation->y,
+                            allocation->width,
+                            allocation->height);
 
   child = gtk_bin_get_child (GTK_BIN (button));
   if (child && gtk_widget_get_visible (child))
     {
-      child_allocation.x = widget->allocation.x + border_width + inner_border.left + xthickness;
-      child_allocation.y = widget->allocation.y + border_width + inner_border.top + ythickness;
-      
-      child_allocation.width = 
-       widget->allocation.width -
+      child_allocation.x = allocation->x + inner_border.left + xthickness;
+      child_allocation.y = allocation->y + inner_border.top + ythickness;
+
+      child_allocation.width =
+       allocation->width -
        xthickness * 2 -
        inner_border.left -
-       inner_border.right -
-       border_width * 2;
+       inner_border.right;
 
       child_allocation.height = 
-       widget->allocation.height -
+       allocation->height -
        ythickness * 2 -
        inner_border.top -
-       inner_border.bottom -
-       border_width * 2;
+       inner_border.bottom;
 
       if (gtk_widget_get_can_default (GTK_WIDGET (button)))
        {
@@ -1528,130 +1533,130 @@ gtk_button_size_allocate (GtkWidget     *widget,
 
 void
 _gtk_button_paint (GtkButton          *button,
-                  const GdkRectangle *area,
+                  cairo_t            *cr,
+                   int                 width,
+                   int                 height,
                   GtkStateType        state_type,
                   GtkShadowType       shadow_type,
                   const gchar        *main_detail,
                   const gchar        *default_detail)
 {
   GtkWidget *widget;
-  gint width, height;
   gint x, y;
-  gint border_width;
   GtkBorder default_border;
   GtkBorder default_outside_border;
   gboolean interior_focus;
   gint focus_width;
   gint focus_pad;
+  GtkAllocation allocation;
+  GdkWindow *window;
+  GtkStyle *style;
 
   widget = GTK_WIDGET (button);
 
-  if (gtk_widget_is_drawable (widget))
+  gtk_button_get_props (button, &default_border, &default_outside_border, NULL, &interior_focus);
+  gtk_widget_style_get (widget,
+                        "focus-line-width", &focus_width,
+                        "focus-padding", &focus_pad,
+                        NULL); 
+
+  gtk_widget_get_allocation (widget, &allocation);
+  style = gtk_widget_get_style (widget);
+  window = gtk_widget_get_window (widget);
+
+  x = 0;
+  y = 0;
+
+  if (gtk_widget_has_default (widget) &&
+      GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
+    {
+      gtk_paint_box (style, cr,
+                     GTK_STATE_NORMAL, GTK_SHADOW_IN,
+                     widget, "buttondefault",
+                     x, y, width, height);
+
+      x += default_border.left;
+      y += default_border.top;
+      width -= default_border.left + default_border.right;
+      height -= default_border.top + default_border.bottom;
+    }
+  else if (gtk_widget_get_can_default (widget))
     {
-      border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+      x += default_outside_border.left;
+      y += default_outside_border.top;
+      width -= default_outside_border.left + default_outside_border.right;
+      height -= default_outside_border.top + default_outside_border.bottom;
+    }
+   
+  if (!interior_focus && gtk_widget_has_focus (widget))
+    {
+      x += focus_width + focus_pad;
+      y += focus_width + focus_pad;
+      width -= 2 * (focus_width + focus_pad);
+      height -= 2 * (focus_width + focus_pad);
+    }
 
-      gtk_button_get_props (button, &default_border, &default_outside_border, NULL, &interior_focus);
+  if (button->relief != GTK_RELIEF_NONE || button->depressed ||
+      gtk_widget_get_state(widget) == GTK_STATE_PRELIGHT)
+    gtk_paint_box (style, cr,
+                   state_type,
+                   shadow_type, widget, "button",
+                   x, y, width, height);
+   
+  if (gtk_widget_has_focus (widget))
+    {
+      gint child_displacement_x;
+      gint child_displacement_y;
+      gboolean displace_focus;
+      
       gtk_widget_style_get (widget,
-                           "focus-line-width", &focus_width,
-                           "focus-padding", &focus_pad,
-                           NULL); 
-       
-      x = widget->allocation.x + border_width;
-      y = widget->allocation.y + border_width;
-      width = widget->allocation.width - border_width * 2;
-      height = widget->allocation.height - border_width * 2;
-
-      if (gtk_widget_has_default (widget) &&
-         GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
-       {
-         gtk_paint_box (widget->style, widget->window,
-                        GTK_STATE_NORMAL, GTK_SHADOW_IN,
-                        area, widget, "buttondefault",
-                        x, y, width, height);
-
-         x += default_border.left;
-         y += default_border.top;
-         width -= default_border.left + default_border.right;
-         height -= default_border.top + default_border.bottom;
-       }
-      else if (gtk_widget_get_can_default (widget))
-       {
-         x += default_outside_border.left;
-         y += default_outside_border.top;
-         width -= default_outside_border.left + default_outside_border.right;
-         height -= default_outside_border.top + default_outside_border.bottom;
-       }
-       
-      if (!interior_focus && gtk_widget_has_focus (widget))
-       {
-         x += focus_width + focus_pad;
-         y += focus_width + focus_pad;
-         width -= 2 * (focus_width + focus_pad);
-         height -= 2 * (focus_width + focus_pad);
-       }
+                            "child-displacement-y", &child_displacement_y,
+                            "child-displacement-x", &child_displacement_x,
+                            "displace-focus", &displace_focus,
+                            NULL);
 
-      if (button->relief != GTK_RELIEF_NONE || button->depressed ||
-         gtk_widget_get_state(widget) == GTK_STATE_PRELIGHT)
-       gtk_paint_box (widget->style, widget->window,
-                      state_type,
-                      shadow_type, area, widget, "button",
-                      x, y, width, height);
-       
-      if (gtk_widget_has_focus (widget))
-       {
-         gint child_displacement_x;
-         gint child_displacement_y;
-         gboolean displace_focus;
-         
-         gtk_widget_style_get (widget,
-                               "child-displacement-y", &child_displacement_y,
-                               "child-displacement-x", &child_displacement_x,
-                               "displace-focus", &displace_focus,
-                               NULL);
+      if (interior_focus)
+        {
+          x += style->xthickness + focus_pad;
+          y += style->ythickness + focus_pad;
+          width -= 2 * (style->xthickness + focus_pad);
+          height -=  2 * (style->ythickness + focus_pad);
+        }
+      else
+        {
+          x -= focus_width + focus_pad;
+          y -= focus_width + focus_pad;
+          width += 2 * (focus_width + focus_pad);
+          height += 2 * (focus_width + focus_pad);
+        }
 
-         if (interior_focus)
-           {
-             x += widget->style->xthickness + focus_pad;
-             y += widget->style->ythickness + focus_pad;
-             width -= 2 * (widget->style->xthickness + focus_pad);
-             height -=  2 * (widget->style->ythickness + focus_pad);
-           }
-         else
-           {
-             x -= focus_width + focus_pad;
-             y -= focus_width + focus_pad;
-             width += 2 * (focus_width + focus_pad);
-             height += 2 * (focus_width + focus_pad);
-           }
-
-         if (button->depressed && displace_focus)
-           {
-             x += child_displacement_x;
-             y += child_displacement_y;
-           }
-
-         gtk_paint_focus (widget->style, widget->window, gtk_widget_get_state (widget),
-                          area, widget, "button",
-                          x, y, width, height);
-       }
+      if (button->depressed && displace_focus)
+        {
+          x += child_displacement_x;
+          y += child_displacement_y;
+        }
+
+      gtk_paint_focus (style, cr,
+                       gtk_widget_get_state (widget),
+                       widget, "button",
+                       x, y, width, height);
     }
 }
 
 static gboolean
-gtk_button_expose (GtkWidget      *widget,
-                  GdkEventExpose *event)
+gtk_button_draw (GtkWidget *widget,
+                cairo_t   *cr)
 {
-  if (gtk_widget_is_drawable (widget))
-    {
-      GtkButton *button = GTK_BUTTON (widget);
-      
-      _gtk_button_paint (button, &event->area,
-                        gtk_widget_get_state (widget),
-                        button->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
-                        "button", "buttondefault");
+  GtkButton *button = GTK_BUTTON (widget);
+  
+  _gtk_button_paint (button, cr, 
+                     gtk_widget_get_allocated_width (widget),
+                     gtk_widget_get_allocated_height (widget),
+                     gtk_widget_get_state (widget),
+                     button->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
+                     "button", "buttondefault");
 
-      GTK_WIDGET_CLASS (gtk_button_parent_class)->expose_event (widget, event);
-    }
+  GTK_WIDGET_CLASS (gtk_button_parent_class)->draw (widget, cr);
 
   return FALSE;
 }
@@ -1885,26 +1890,19 @@ gtk_button_finish_activate (GtkButton *button,
 
 
 static void
-gtk_button_size_request_init (GtkSizeRequestIface *iface)
-{
-  iface->get_width  = gtk_button_get_width;
-  iface->get_height = gtk_button_get_height;
-}
-
-static void
-gtk_button_get_size (GtkSizeRequest *widget,
+gtk_button_get_size (GtkWidget      *widget,
                     GtkOrientation  orientation,
                     gint           *minimum_size,
                     gint           *natural_size)
 {
   GtkButton *button = GTK_BUTTON (widget);
+  GtkStyle *style;
   GtkWidget *child;
   GtkBorder default_border;
   GtkBorder inner_border;
   gint focus_width;
   gint focus_pad;
   gint minimum, natural;
-  guint border_width;
 
   gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
   gtk_widget_style_get (GTK_WIDGET (widget),
@@ -1912,11 +1910,11 @@ gtk_button_get_size (GtkSizeRequest *widget,
                        "focus-padding", &focus_pad,
                        NULL);
 
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+  style = gtk_widget_get_style (GTK_WIDGET (widget));
+
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
-      minimum = ((border_width +
-                 GTK_WIDGET (widget)->style->xthickness) * 2 +
+      minimum = (style->xthickness * 2 +
                 inner_border.left + inner_border.right);
 
       if (gtk_widget_get_can_default (GTK_WIDGET (widget)))
@@ -1924,8 +1922,7 @@ gtk_button_get_size (GtkSizeRequest *widget,
     }
   else
     {
-      minimum = ((border_width +
-                 GTK_WIDGET (widget)->style->ythickness) * 2 +
+      minimum = (style->ythickness * 2 +
                 inner_border.top + inner_border.bottom);
 
       if (gtk_widget_get_can_default (GTK_WIDGET (widget)))
@@ -1941,11 +1938,9 @@ gtk_button_get_size (GtkSizeRequest *widget,
       gint child_min, child_nat;
 
       if (orientation == GTK_ORIENTATION_HORIZONTAL)
-       gtk_size_request_get_width (GTK_SIZE_REQUEST (child), 
-                                   &child_min, &child_nat);
+       gtk_widget_get_preferred_width (child, &child_min, &child_nat);
       else
-       gtk_size_request_get_height (GTK_SIZE_REQUEST (child), 
-                                    &child_min, &child_nat);
+       gtk_widget_get_preferred_height (child, &child_min, &child_nat);
 
       minimum += child_min;
       natural += child_nat;
@@ -1959,17 +1954,17 @@ gtk_button_get_size (GtkSizeRequest *widget,
 }
 
 static void 
-gtk_button_get_width (GtkSizeRequest      *widget,
-                     gint                *minimum_size,
-                     gint                *natural_size)
+gtk_button_get_preferred_width (GtkWidget *widget,
+                                gint      *minimum_size,
+                                gint      *natural_size)
 {
   gtk_button_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
 }
 
 static void 
-gtk_button_get_height (GtkSizeRequest      *widget,
-                      gint                *minimum_size,
-                      gint                *natural_size)
+gtk_button_get_preferred_height (GtkWidget *widget,
+                                 gint      *minimum_size,
+                                 gint      *natural_size)
 {
   gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
 }
@@ -2402,14 +2397,19 @@ gtk_button_set_image (GtkButton *button,
                      GtkWidget *image)
 {
   GtkButtonPrivate *priv;
+  GtkWidget *parent;
 
   g_return_if_fail (GTK_IS_BUTTON (button));
   g_return_if_fail (image == NULL || GTK_IS_WIDGET (image));
 
   priv = GTK_BUTTON_GET_PRIVATE (button);
 
-  if (priv->image && priv->image->parent)
-    gtk_container_remove (GTK_CONTAINER (priv->image->parent), priv->image);
+  if (priv->image)
+    {
+      parent = gtk_widget_get_parent (priv->image);
+      if (parent)
+        gtk_container_remove (GTK_CONTAINER (parent), priv->image);
+    }
 
   priv->image = image;
   priv->image_is_stock = (image == NULL);
@@ -2427,7 +2427,7 @@ gtk_button_set_image (GtkButton *button,
  * This may have been explicitly set by gtk_button_set_image()
  * or constructed by gtk_button_new_from_stock().
  *
- * Return value: a #GtkWidget or %NULL in case there is no image
+ * Return value: (transfer none): a #GtkWidget or %NULL in case there is no image
  *
  * Since: 2.6
  */