[gtk+/buttons: 2/5] More GtkButton cleanup



commit 1a423ac7666c6bb43c4616fa0349453dc561a204
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Dec 1 01:10:41 2010 -0500

    More GtkButton cleanup
    
    Patch from Matthias in bug #636101 to merge drawing code up and turn the
    subclasses into empty shells.

 gtk/gtkbutton.c          |   58 +++++
 gtk/gtkbutton.h          |    4 +
 gtk/gtkbuttonprivate.h   |    1 +
 gtk/gtkcheckbutton.c     |  405 +----------------------------------
 gtk/gtkcheckbutton.h     |   15 +--
 gtk/gtkenums.h           |    9 +
 gtk/gtkradiobutton.c     |   91 +--------
 gtk/gtkradiotoolbutton.c |    3 +-
 gtk/gtktogglebutton.c    |  542 +++++++++++++++++++++++++++++++++++-----------
 gtk/gtktogglebutton.h    |   40 ++--
 10 files changed, 516 insertions(+), 652 deletions(-)
---
diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c
index 5337887..9faabcf 100644
--- a/gtk/gtkbutton.c
+++ b/gtk/gtkbutton.c
@@ -92,6 +92,7 @@ enum {
   PROP_IMAGE_POSITION,
   PROP_IS_TOGGLE,
   PROP_ACTION,
+  PROP_INDICATOR_STYLE,
 
   /* activatable properties */
   PROP_ACTIVATABLE_RELATED_ACTION,
@@ -364,6 +365,14 @@ gtk_button_class_init (GtkButtonClass *klass)
                                                         G_TYPE_ACTION,
                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
+  g_object_class_install_property (gobject_class, PROP_INDICATOR_STYLE,
+    g_param_spec_enum ("indicator-style",
+                       P_("Indicator style"),
+                       P_("Whether the button looks like a plain button, check or radio button"),
+                       GTK_TYPE_INDICATOR_STYLE,
+                       GTK_INDICATOR_STYLE_PLAIN,
+                       GTK_PARAM_READWRITE));
+
   g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
   g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
 
@@ -560,6 +569,20 @@ gtk_button_class_init (GtkButtonClass *klass)
 							     2,
 							     GTK_PARAM_READABLE));
 
+  gtk_widget_class_install_style_property (widget_class,
+    g_param_spec_int ("indicator-size",
+                      P_("Indicator Size"),
+                      P_("Size of check or radio indicator"),
+                      0, G_MAXINT, 13,
+                      GTK_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+    g_param_spec_int ("indicator-spacing",
+                      P_("Indicator Spacing"),
+                      P_("Spacing around check or radio indicator"),
+                      0, G_MAXINT, 2,
+                      GTK_PARAM_READABLE));
+
   g_type_class_add_private (gobject_class, sizeof (GtkButtonPrivate));
 }
 
@@ -595,6 +618,7 @@ gtk_button_init (GtkButton *button)
   priv->image_is_stock = TRUE;
   priv->image_position = GTK_POS_LEFT;
   priv->use_action_appearance = TRUE;
+  priv->indicator_style = GTK_INDICATOR_STYLE_PLAIN;
 }
 
 static void
@@ -853,6 +877,9 @@ gtk_button_set_property (GObject         *object,
       if (g_value_get_object (value) != NULL)
         gtk_button_set_action (button, g_value_get_object (value));
       break;
+    case PROP_INDICATOR_STYLE:
+      gtk_button_set_indicator_style (button, g_value_get_enum (value));
+      break;
     case PROP_ACTIVATABLE_RELATED_ACTION:
       gtk_button_set_related_action (button, g_value_get_object (value));
       break;
@@ -906,6 +933,9 @@ gtk_button_get_property (GObject         *object,
     case PROP_ACTION:
       g_value_set_object (value, priv->g_action);
       break;
+    case PROP_INDICATOR_STYLE:
+      g_value_set_enum (value, priv->indicator_style);
+      break;
     case PROP_ACTIVATABLE_RELATED_ACTION:
       g_value_set_object (value, priv->action);
       break;
@@ -2690,3 +2720,31 @@ gtk_button_get_event_window (GtkButton *button)
 
   return button->priv->event_window;
 }
+
+void
+gtk_button_set_indicator_style (GtkButton         *button,
+                                GtkIndicatorStyle  style)
+{
+  GtkButtonPrivate *priv;
+
+  g_return_if_fail (GTK_IS_BUTTON (button));
+
+  priv = button->priv;
+
+  if (priv->indicator_style != style)
+    {
+      priv->indicator_style = style;
+
+      gtk_widget_queue_resize (GTK_WIDGET (button));
+
+      g_object_notify (G_OBJECT (button), "indicator-style");
+    }
+}
+
+GtkIndicatorStyle
+gtk_button_get_indicator_style (GtkButton *button)
+{
+  g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_INDICATOR_STYLE_PLAIN);
+
+  return button->priv->indicator_style;
+}
diff --git a/gtk/gtkbutton.h b/gtk/gtkbutton.h
index 3e2fee8..1e5b514 100644
--- a/gtk/gtkbutton.h
+++ b/gtk/gtkbutton.h
@@ -34,6 +34,7 @@
 
 #include <gtk/gtkbin.h>
 #include <gtk/gtkimage.h>
+#include <gtk/gtkenums.h>
 
 
 G_BEGIN_DECLS
@@ -125,6 +126,9 @@ void                  gtk_button_set_action         (GtkButton      *button,
                                                      GAction        *action);
 GAction *             gtk_button_get_action         (GtkButton      *button);
 
+void                  gtk_button_set_indicator_style (GtkButton         *button,
+                                                      GtkIndicatorStyle  style);
+GtkIndicatorStyle     gtk_button_get_indicator_style (GtkButton         *button);
 void _gtk_button_set_depressed             (GtkButton          *button,
 					    gboolean            depressed);
 void _gtk_button_paint                     (GtkButton          *button,
diff --git a/gtk/gtkbuttonprivate.h b/gtk/gtkbuttonprivate.h
index da5f56b..edcdcf5 100644
--- a/gtk/gtkbuttonprivate.h
+++ b/gtk/gtkbuttonprivate.h
@@ -55,6 +55,7 @@ struct _GtkButtonPrivate
   guint          use_stock             : 1;
   guint          use_underline         : 1;
   guint          is_toggle             : 1;
+  guint          indicator_style       : 2;
 };
 
 #endif /* __GTK_BUTTON_PRIVATE_H__ */
diff --git a/gtk/gtkcheckbutton.c b/gtk/gtkcheckbutton.c
index f9087b5..3ee43cd 100644
--- a/gtk/gtkcheckbutton.c
+++ b/gtk/gtkcheckbutton.c
@@ -34,68 +34,17 @@
 #include "gtkprivate.h"
 #include "gtkintl.h"
 
-
-#define INDICATOR_SIZE     13
-#define INDICATOR_SPACING  2
-
-
-static void gtk_check_button_get_preferred_width  (GtkWidget          *widget,
-                                                   gint               *minimum,
-                                                   gint               *natural);
-static void gtk_check_button_get_preferred_height (GtkWidget          *widget,
-                                                   gint               *minimum,
-                                                   gint               *natural);
-static void gtk_check_button_size_allocate       (GtkWidget           *widget,
-						  GtkAllocation       *allocation);
-static gboolean gtk_check_button_draw            (GtkWidget           *widget,
-						  cairo_t             *cr);
-static void gtk_check_button_paint               (GtkWidget           *widget,
-						  cairo_t             *cr);
-static void gtk_check_button_draw_indicator      (GtkCheckButton      *check_button,
-						  cairo_t             *cr);
-static void gtk_real_check_button_draw_indicator (GtkCheckButton      *check_button,
-						  cairo_t             *cr);
-
 G_DEFINE_TYPE (GtkCheckButton, gtk_check_button, GTK_TYPE_TOGGLE_BUTTON)
 
 static void
 gtk_check_button_class_init (GtkCheckButtonClass *class)
 {
-  GtkWidgetClass *widget_class;
-
-  widget_class = (GtkWidgetClass*) class;
-
-  widget_class->get_preferred_width = gtk_check_button_get_preferred_width;
-  widget_class->get_preferred_height = gtk_check_button_get_preferred_height;
-  widget_class->size_allocate = gtk_check_button_size_allocate;
-  widget_class->draw = gtk_check_button_draw;
-
-  class->draw_indicator = gtk_real_check_button_draw_indicator;
-
-  gtk_widget_class_install_style_property (widget_class,
-					   g_param_spec_int ("indicator-size",
-							     P_("Indicator Size"),
-							     P_("Size of check or radio indicator"),
-							     0,
-							     G_MAXINT,
-							     INDICATOR_SIZE,
-							     GTK_PARAM_READABLE));
-  gtk_widget_class_install_style_property (widget_class,
-					   g_param_spec_int ("indicator-spacing",
-							     P_("Indicator Spacing"),
-							     P_("Spacing around check or radio indicator"),
-							     0,
-							     G_MAXINT,
-							     INDICATOR_SPACING,
-							     GTK_PARAM_READABLE));
 }
 
 static void
-gtk_check_button_init (GtkCheckButton *check_button)
+gtk_check_button_init (GtkCheckButton *button)
 {
-  gtk_widget_set_has_window (GTK_WIDGET (check_button), FALSE);
-  gtk_widget_set_receives_default (GTK_WIDGET (check_button), FALSE);
-  gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (check_button), TRUE);
+  gtk_button_set_indicator_style (GTK_BUTTON (button), GTK_INDICATOR_STYLE_CHECK);
 }
 
 GtkWidget*
@@ -135,353 +84,3 @@ gtk_check_button_new_with_mnemonic (const gchar *label)
 }
 
 
-/* This should only be called when toggle_button->draw_indicator
- * is true.
- */
-static void
-gtk_check_button_paint (GtkWidget    *widget,
-			cairo_t      *cr)
-{
-  GtkCheckButton *check_button = GTK_CHECK_BUTTON (widget);
-  gint border_width;
-  gint interior_focus;
-  gint focus_width;
-  gint focus_pad;
-      
-  gtk_widget_style_get (widget,
-                        "interior-focus", &interior_focus,
-                        "focus-line-width", &focus_width,
-                        "focus-padding", &focus_pad,
-                        NULL);
-
-  gtk_check_button_draw_indicator (check_button, cr);
-
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-  if (gtk_widget_has_focus (widget))
-    {
-      GtkStateType state = gtk_widget_get_state (widget);
-      GtkStyle *style = gtk_widget_get_style (widget);
-      GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
-      GtkAllocation allocation;
-
-      gtk_widget_get_allocation (widget, &allocation);
-
-      if (interior_focus && child && gtk_widget_get_visible (child))
-        {
-          GtkAllocation child_allocation;
-
-          gtk_widget_get_allocation (child, &child_allocation);
-          gtk_paint_focus (style, cr, state,
-                           widget, "checkbutton",
-                           child_allocation.x - allocation.x - focus_width - focus_pad,
-                           child_allocation.y - allocation.y - focus_width - focus_pad,
-                           child_allocation.width + 2 * (focus_width + focus_pad),
-                           child_allocation.height + 2 * (focus_width + focus_pad));
-        }
-      else
-        {
-          gtk_paint_focus (style, cr, state,
-                           widget, "checkbutton",
-                           border_width,
-                           border_width,
-                           allocation.width - 2 * border_width,
-                           allocation.height - 2 * border_width);
-        }
-    }
-}
-
-void
-_gtk_check_button_get_props (GtkCheckButton *check_button,
-			     gint           *indicator_size,
-			     gint           *indicator_spacing)
-{
-  GtkWidget *widget =  GTK_WIDGET (check_button);
-
-  if (indicator_size)
-    gtk_widget_style_get (widget, "indicator-size", indicator_size, NULL);
-
-  if (indicator_spacing)
-    gtk_widget_style_get (widget, "indicator-spacing", indicator_spacing, NULL);
-}
-
-static void
-gtk_check_button_get_preferred_width (GtkWidget *widget,
-                                      gint      *minimum,
-                                      gint      *natural)
-{
-  GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (widget);
-  
-  if (gtk_toggle_button_get_mode (toggle_button))
-    {
-      GtkWidget *child;
-      gint indicator_size;
-      gint indicator_spacing;
-      gint focus_width;
-      gint focus_pad;
-      guint border_width;
-
-      border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-
-      gtk_widget_style_get (GTK_WIDGET (widget),
-                            "focus-line-width", &focus_width,
-                            "focus-padding", &focus_pad,
-                            NULL);
-      *minimum = 2 * border_width;
-      *natural = 2 * border_width;
-
-      _gtk_check_button_get_props (GTK_CHECK_BUTTON (widget),
-                                   &indicator_size, &indicator_spacing);
-
-      child = gtk_bin_get_child (GTK_BIN (widget));
-      if (child && gtk_widget_get_visible (child))
-        {
-          gint child_min, child_nat;
-
-          gtk_widget_get_preferred_width (child, &child_min, &child_nat);
-
-          *minimum += child_min + indicator_spacing;
-          *natural += child_nat + indicator_spacing;
-        }
-
-      *minimum += (indicator_size + indicator_spacing * 2 + 2 * (focus_width + focus_pad));
-      *natural += (indicator_size + indicator_spacing * 2 + 2 * (focus_width + focus_pad));
-    }
-  else
-    GTK_WIDGET_CLASS (gtk_check_button_parent_class)->get_preferred_width (widget, minimum, natural);
-}
-
-static void
-gtk_check_button_get_preferred_height (GtkWidget *widget,
-                                       gint      *minimum,
-                                       gint      *natural)
-{
-  GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (widget);
-
-  if (gtk_toggle_button_get_mode (toggle_button))
-    {
-      GtkWidget *child;
-      gint temp;
-      gint indicator_size;
-      gint indicator_spacing;
-      gint focus_width;
-      gint focus_pad;
-      guint border_width;
-
-      border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-
-      gtk_widget_style_get (GTK_WIDGET (widget),
-                            "focus-line-width", &focus_width,
-                            "focus-padding", &focus_pad,
-                            NULL);
-
-      *minimum = border_width * 2;
-      *natural = border_width * 2;
-
-      _gtk_check_button_get_props (GTK_CHECK_BUTTON (widget),
-                                   &indicator_size, &indicator_spacing);
-
-      child = gtk_bin_get_child (GTK_BIN (widget));
-      if (child && gtk_widget_get_visible (child))
-        {
-          gint child_min, child_nat;
-
-          gtk_widget_get_preferred_height (child, &child_min, &child_nat);
-
-          *minimum += child_min;
-          *natural += child_nat;
-        }
-
-      temp = indicator_size + indicator_spacing * 2;
-      *minimum = MAX (*minimum, temp) + 2 * (focus_width + focus_pad);
-      *natural = MAX (*natural, temp) + 2 * (focus_width + focus_pad);
-    }
-  else
-    GTK_WIDGET_CLASS (gtk_check_button_parent_class)->get_preferred_height (widget, minimum, natural);
-}
-
-static void
-gtk_check_button_size_allocate (GtkWidget     *widget,
-				GtkAllocation *allocation)
-{
-  GtkCheckButton *check_button;
-  GtkToggleButton *toggle_button;
-  GtkButton *button;
-  GtkAllocation child_allocation;
-
-  button = GTK_BUTTON (widget);
-  check_button = GTK_CHECK_BUTTON (widget);
-  toggle_button = GTK_TOGGLE_BUTTON (widget);
-
-  if (gtk_toggle_button_get_mode (toggle_button))
-    {
-      GtkWidget *child;
-      gint indicator_size;
-      gint indicator_spacing;
-      gint focus_width;
-      gint focus_pad;
-      
-      _gtk_check_button_get_props (check_button, &indicator_size, &indicator_spacing);
-      gtk_widget_style_get (widget,
-			    "focus-line-width", &focus_width,
-			    "focus-padding", &focus_pad,
-			    NULL);
-
-      gtk_widget_set_allocation (widget, allocation);
-
-      if (gtk_widget_get_realized (widget))
-	gdk_window_move_resize (gtk_button_get_event_window (button),
-				allocation->x, allocation->y,
-				allocation->width, allocation->height);
-
-      child = gtk_bin_get_child (GTK_BIN (button));
-      if (child && gtk_widget_get_visible (child))
-	{
-	  GtkRequisition child_requisition;
-          guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-
-          gtk_widget_get_preferred_size (child, &child_requisition, NULL);
-
-	  child_allocation.width = MIN (child_requisition.width,
-					allocation->width -
-					((border_width + focus_width + focus_pad) * 2
-					 + indicator_size + indicator_spacing * 3));
-	  child_allocation.width = MAX (child_allocation.width, 1);
-
-	  child_allocation.height = MIN (child_requisition.height,
-					 allocation->height - (border_width + focus_width + focus_pad) * 2);
-	  child_allocation.height = MAX (child_allocation.height, 1);
-	  
-	  child_allocation.x = (border_width + indicator_size + indicator_spacing * 3 +
-                                allocation->x + focus_width + focus_pad);
-          child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
-
-	  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-	    child_allocation.x = allocation->x + allocation->width
-	      - (child_allocation.x - allocation->x + child_allocation.width);
-	  
-	  gtk_widget_size_allocate (child, &child_allocation);
-	}
-    }
-  else
-    GTK_WIDGET_CLASS (gtk_check_button_parent_class)->size_allocate (widget, allocation);
-}
-
-static gint
-gtk_check_button_draw (GtkWidget *widget,
-                       cairo_t   *cr)
-{
-  GtkToggleButton *toggle_button;
-  GtkBin *bin;
-  GtkWidget *child;
-  
-  toggle_button = GTK_TOGGLE_BUTTON (widget);
-  bin = GTK_BIN (widget);
-
-  if (gtk_toggle_button_get_mode (toggle_button))
-    {
-      gtk_check_button_paint (widget, cr);
-
-      child = gtk_bin_get_child (bin);
-      if (child)
-        gtk_container_propagate_draw (GTK_CONTAINER (widget),
-                                      child,
-                                      cr);
-    }
-  else if (GTK_WIDGET_CLASS (gtk_check_button_parent_class)->draw)
-    GTK_WIDGET_CLASS (gtk_check_button_parent_class)->draw (widget, cr);
-
-  return FALSE;
-}
-
-
-static void
-gtk_check_button_draw_indicator (GtkCheckButton *check_button,
-				 cairo_t        *cr)
-{
-  GtkCheckButtonClass *class = GTK_CHECK_BUTTON_GET_CLASS (check_button);
-
-  if (class->draw_indicator)
-    class->draw_indicator (check_button, cr);
-}
-
-static void
-gtk_real_check_button_draw_indicator (GtkCheckButton *check_button,
-				      cairo_t        *cr)
-{
-  GtkWidget *widget;
-  GtkWidget *child;
-  GtkButton *button;
-  GtkToggleButton *toggle_button;
-  GtkStateType state_type;
-  GtkShadowType shadow_type;
-  gint x, y;
-  gint indicator_size;
-  gint indicator_spacing;
-  gint focus_width;
-  gint focus_pad;
-  guint border_width;
-  gboolean interior_focus;
-  GtkAllocation allocation;
-  GtkStyle *style;
-  GdkWindow *window;
-
-  widget = GTK_WIDGET (check_button);
-  button = GTK_BUTTON (check_button);
-  toggle_button = GTK_TOGGLE_BUTTON (check_button);
-
-  gtk_widget_get_allocation (widget, &allocation);
-  style = gtk_widget_get_style (widget);
-  window = gtk_widget_get_window (widget);
-
-  gtk_widget_style_get (widget, 
-                        "interior-focus", &interior_focus,
-                        "focus-line-width", &focus_width, 
-                        "focus-padding", &focus_pad, 
-                        NULL);
-
-  _gtk_check_button_get_props (check_button, &indicator_size, &indicator_spacing);
-
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-
-  x = indicator_spacing + border_width;
-  y = (allocation.height - indicator_size) / 2;
-
-  child = gtk_bin_get_child (GTK_BIN (check_button));
-  if (!interior_focus || !(child && gtk_widget_get_visible (child)))
-    x += focus_width + focus_pad;      
-
-  if (gtk_toggle_button_get_inconsistent (toggle_button))
-    shadow_type = GTK_SHADOW_ETCHED_IN;
-  else if (gtk_toggle_button_get_active (toggle_button))
-    shadow_type = GTK_SHADOW_IN;
-  else
-    shadow_type = GTK_SHADOW_OUT;
-
-  if (button->priv->activate_timeout || (button->priv->button_down && button->priv->in_button))
-    state_type = GTK_STATE_ACTIVE;
-  else if (button->priv->in_button)
-    state_type = GTK_STATE_PRELIGHT;
-  else if (!gtk_widget_is_sensitive (widget))
-    state_type = GTK_STATE_INSENSITIVE;
-  else
-    state_type = GTK_STATE_NORMAL;
-  
-  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-    x = allocation.width - (indicator_size + x);
-
-  if (gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT)
-    {
-
-      gtk_paint_flat_box (style, cr, GTK_STATE_PRELIGHT,
-                          GTK_SHADOW_ETCHED_OUT, 
-                          widget, "checkbutton",
-                          border_width, border_width,
-                          allocation.width - (2 * border_width),
-                          allocation.height - (2 * border_width));
-    }
-
-  gtk_paint_check (style, cr,
-                   state_type, shadow_type,
-                   widget, "checkbutton",
-                   x, y, indicator_size, indicator_size);
-}
diff --git a/gtk/gtkcheckbutton.h b/gtk/gtkcheckbutton.h
index 1ea6e31..887b356 100644
--- a/gtk/gtkcheckbutton.h
+++ b/gtk/gtkcheckbutton.h
@@ -56,27 +56,14 @@ struct _GtkCheckButton
 struct _GtkCheckButtonClass
 {
   GtkToggleButtonClass parent_class;
-
-  void (* draw_indicator) (GtkCheckButton *check_button,
-			   cairo_t        *cr);
-
-  /* Padding for future expansion */
-  void (*_gtk_reserved1) (void);
-  void (*_gtk_reserved2) (void);
-  void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
 };
 
 
-GType      gtk_check_button_get_type       (void) G_GNUC_CONST;
+GType      gtk_check_button_get_type          (void) G_GNUC_CONST;
 GtkWidget* gtk_check_button_new               (void);
 GtkWidget* gtk_check_button_new_with_label    (const gchar *label);
 GtkWidget* gtk_check_button_new_with_mnemonic (const gchar *label);
 
-void _gtk_check_button_get_props (GtkCheckButton *check_button,
-				  gint           *indicator_size,
-				  gint           *indicator_spacing);
-
 G_END_DECLS
 
 #endif /* __GTK_CHECK_BUTTON_H__ */
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index 9dbab6d..6abd2bf 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -558,6 +558,15 @@ typedef enum
 } GtkScrollablePolicy;
 
 
+
+typedef enum
+{
+  GTK_INDICATOR_STYLE_PLAIN,
+  GTK_INDICATOR_STYLE_CHECK,
+  GTK_INDICATOR_STYLE_RADIO
+} GtkIndicatorStyle;
+
+
 G_END_DECLS
 
 
diff --git a/gtk/gtkradiobutton.c b/gtk/gtkradiobutton.c
index 085f9ee..95b89b2 100644
--- a/gtk/gtkradiobutton.c
+++ b/gtk/gtkradiobutton.c
@@ -121,8 +121,6 @@ static void     gtk_radio_button_destroy        (GtkWidget           *widget);
 static gboolean gtk_radio_button_focus          (GtkWidget           *widget,
 						 GtkDirectionType     direction);
 static void     gtk_radio_button_clicked        (GtkButton           *button);
-static void     gtk_radio_button_draw_indicator (GtkCheckButton      *check_button,
-						 cairo_t             *cr);
 static void     gtk_radio_button_set_property   (GObject             *object,
 						 guint                prop_id,
 						 const GValue        *value,
@@ -169,8 +167,6 @@ gtk_radio_button_class_init (GtkRadioButtonClass *class)
 
   button_class->clicked = gtk_radio_button_clicked;
 
-  check_button_class->draw_indicator = gtk_radio_button_draw_indicator;
-
   class->group_changed = NULL;
 
   /**
@@ -209,8 +205,9 @@ gtk_radio_button_init (GtkRadioButton *radio_button)
 
   gtk_widget_set_has_window (GTK_WIDGET (radio_button), FALSE);
   gtk_widget_set_receives_default (GTK_WIDGET (radio_button), FALSE);
-
   _gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button), TRUE);
+  gtk_button_set_indicator_style (GTK_BUTTON (radio_button),
+                                  GTK_INDICATOR_STYLE_RADIO);
 
   GTK_BUTTON (radio_button)->priv->depress_on_activate = FALSE;
 
@@ -660,7 +657,7 @@ gtk_radio_button_focus (GtkWidget         *widget,
   /* Radio buttons with draw_indicator unset focus "normally", since
    * they look like buttons to the user.
    */
-  if (!gtk_toggle_button_get_mode (GTK_TOGGLE_BUTTON (widget)))
+  if (gtk_button_get_indicator_style (GTK_BUTTON (widget)) == GTK_INDICATOR_STYLE_PLAIN)
     return GTK_WIDGET_CLASS (gtk_radio_button_parent_class)->focus (widget, direction);
   
   if (gtk_widget_is_focus (widget))
@@ -877,85 +874,3 @@ gtk_radio_button_clicked (GtkButton *button)
 
   g_object_unref (button);
 }
-
-static void
-gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
-				 cairo_t        *cr)
-{
-  GtkAllocation allocation;
-  GtkWidget *widget;
-  GtkWidget *child;
-  GtkButton *button;
-  GtkToggleButton *toggle_button;
-  GtkStateType state_type;
-  GtkShadowType shadow_type;
-  GtkStyle *style;
-  GdkWindow *window;
-  gint x, y;
-  gint indicator_size, indicator_spacing;
-  gint focus_width;
-  gint focus_pad;
-  guint border_width;
-  gboolean interior_focus;
-
-  widget = GTK_WIDGET (check_button);
-  button = GTK_BUTTON (check_button);
-  toggle_button = GTK_TOGGLE_BUTTON (check_button);
-
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-
-  style = gtk_widget_get_style (widget);
-  gtk_widget_style_get (widget,
-                        "interior-focus", &interior_focus,
-                        "focus-line-width", &focus_width,
-                        "focus-padding", &focus_pad,
-                        NULL);
-
-  window = gtk_widget_get_window (widget);
-
-  _gtk_check_button_get_props (check_button, &indicator_size, &indicator_spacing);
-
-  gtk_widget_get_allocation (widget, &allocation);
-
-  x = indicator_spacing + border_width;
-  y = (allocation.height - indicator_size) / 2;
-
-  child = gtk_bin_get_child (GTK_BIN (check_button));
-  if (!interior_focus || !(child && gtk_widget_get_visible (child)))
-    x += focus_width + focus_pad;      
-
-  if (gtk_toggle_button_get_inconsistent (toggle_button))
-    shadow_type = GTK_SHADOW_ETCHED_IN;
-  else if (gtk_toggle_button_get_active (toggle_button))
-    shadow_type = GTK_SHADOW_IN;
-  else
-    shadow_type = GTK_SHADOW_OUT;
-
-  if (button->priv->activate_timeout || (button->priv->button_down && button->priv->in_button))
-    state_type = GTK_STATE_ACTIVE;
-  else if (button->priv->in_button)
-    state_type = GTK_STATE_PRELIGHT;
-  else if (!gtk_widget_is_sensitive (widget))
-    state_type = GTK_STATE_INSENSITIVE;
-  else
-    state_type = GTK_STATE_NORMAL;
-
-  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-    x = allocation.width - (indicator_size + x);
-
-  if (gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT)
-    {
-      gtk_paint_flat_box (style, cr,
-                          GTK_STATE_PRELIGHT,
-                          GTK_SHADOW_ETCHED_OUT, 
-                          widget, "checkbutton",
-                          border_width, border_width,
-                          allocation.width - (2 * border_width),
-                          allocation.height - (2 * border_width));
-    }
-
-  gtk_paint_option (style, cr,
-                    state_type, shadow_type,
-                    widget, "radiobutton",
-                    x, y, indicator_size, indicator_size);
-}
diff --git a/gtk/gtkradiotoolbutton.c b/gtk/gtkradiotoolbutton.c
index 9a37c18..b04f86a 100644
--- a/gtk/gtkradiotoolbutton.c
+++ b/gtk/gtkradiotoolbutton.c
@@ -73,7 +73,8 @@ static void
 gtk_radio_tool_button_init (GtkRadioToolButton *button)
 {
   GtkToolButton *tool_button = GTK_TOOL_BUTTON (button);
-  gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (_gtk_tool_button_get_button (tool_button)), FALSE);
+  gtk_button_set_indicator_style (GTK_BUTTON (_gtk_tool_button_get_button (tool_button)),
+                                  GTK_INDICATOR_STYLE_PLAIN);
 }
 
 static void
diff --git a/gtk/gtktogglebutton.c b/gtk/gtktogglebutton.c
index eda7ab3..ecddc5a 100644
--- a/gtk/gtktogglebutton.c
+++ b/gtk/gtktogglebutton.c
@@ -38,15 +38,10 @@
 #include "gtkintl.h"
 
 
-#define DEFAULT_LEFT_POS  4
-#define DEFAULT_TOP_POS   4
-#define DEFAULT_SPACING   7
-
 struct _GtkToggleButtonPrivate
 {
-  guint active         : 1;
-  guint draw_indicator : 1;
-  guint inconsistent   : 1;
+  guint active       : 1;
+  guint inconsistent : 1;
 };
 
 enum {
@@ -61,40 +56,46 @@ enum {
   PROP_DRAW_INDICATOR
 };
 
-
-static gint gtk_toggle_button_draw         (GtkWidget            *widget,
-					    cairo_t              *cr);
-static gboolean gtk_toggle_button_mnemonic_activate  (GtkWidget            *widget,
-                                                      gboolean              group_cycling);
+static void gtk_toggle_button_get_preferred_width   (GtkWidget     *widget,
+                                                     gint          *minimum,
+                                                     gint          *natural);
+static void gtk_toggle_button_get_preferred_height  (GtkWidget     *widget,
+                                                     gint          *minimum,
+                                                     gint          *natural);
+static void gtk_toggle_button_size_allocate         (GtkWidget     *widget,
+                                                     GtkAllocation *allocation);
+static gint gtk_toggle_button_draw                  (GtkWidget     *widget,
+                                                     cairo_t       *cr);
+static gboolean gtk_toggle_button_mnemonic_activate (GtkWidget     *widget,
+                                                     gboolean       group_cycling);
 static void gtk_toggle_button_pressed       (GtkButton            *button);
 static void gtk_toggle_button_released      (GtkButton            *button);
 static void gtk_toggle_button_set_property  (GObject              *object,
-					     guint                 prop_id,
-					     const GValue         *value,
-					     GParamSpec           *pspec);
+                                             guint                 prop_id,
+                                             const GValue         *value,
+                                             GParamSpec           *pspec);
 static void gtk_toggle_button_get_property  (GObject              *object,
-					     guint                 prop_id,
-					     GValue               *value,
-					     GParamSpec           *pspec);
+                                             guint                 prop_id,
+                                             GValue               *value,
+                                             GParamSpec           *pspec);
 static void gtk_toggle_button_update_state  (GtkButton            *button);
 
 static void gtk_toggle_button_action_state_changed (GtkButton     *button,
                                                     GVariant      *state);
 
-
 static void gtk_toggle_button_activatable_interface_init (GtkActivatableIface  *iface);
-static void gtk_toggle_button_update         	     (GtkActivatable       *activatable,
-					 	      GtkAction            *action,
-						      const gchar          *property_name);
+static void gtk_toggle_button_update                 (GtkActivatable       *activatable,
+                                                      GtkAction            *action,
+                                                      const gchar          *property_name);
 static void gtk_toggle_button_sync_action_properties (GtkActivatable       *activatable,
-						      GtkAction            *action);
+                                                      GtkAction            *action);
 
 static GtkActivatableIface *parent_activatable_iface;
 static guint                toggle_button_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkToggleButton, gtk_toggle_button, GTK_TYPE_BUTTON,
-			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
-						gtk_toggle_button_activatable_interface_init))
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+                                                gtk_toggle_button_activatable_interface_init))
 
 static void
 gtk_toggle_button_class_init (GtkToggleButtonClass *class)
@@ -110,6 +111,9 @@ gtk_toggle_button_class_init (GtkToggleButtonClass *class)
   gobject_class->set_property = gtk_toggle_button_set_property;
   gobject_class->get_property = gtk_toggle_button_get_property;
 
+  widget_class->get_preferred_width = gtk_toggle_button_get_preferred_width;
+  widget_class->get_preferred_height = gtk_toggle_button_get_preferred_height;
+  widget_class->size_allocate = gtk_toggle_button_size_allocate;
   widget_class->draw = gtk_toggle_button_draw;
   widget_class->mnemonic_activate = gtk_toggle_button_mnemonic_activate;
 
@@ -124,35 +128,49 @@ gtk_toggle_button_class_init (GtkToggleButtonClass *class)
   g_object_class_install_property (gobject_class,
                                    PROP_ACTIVE,
                                    g_param_spec_boolean ("active",
-							 P_("Active"),
-							 P_("If the toggle button should be pressed in"),
-							 FALSE,
-							 GTK_PARAM_READWRITE));
+                                                         P_("Active"),
+                                                         P_("If the toggle button should be pressed in"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
 
   g_object_class_install_property (gobject_class,
                                    PROP_INCONSISTENT,
                                    g_param_spec_boolean ("inconsistent",
-							 P_("Inconsistent"),
-							 P_("If the toggle button is in an \"in between\" state"),
-							 FALSE,
-							 GTK_PARAM_READWRITE));
+                                                         P_("Inconsistent"),
+                                                         P_("If the toggle button is in an \"in between\" state"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
 
   g_object_class_install_property (gobject_class,
                                    PROP_DRAW_INDICATOR,
                                    g_param_spec_boolean ("draw-indicator",
-							 P_("Draw Indicator"),
-							 P_("If the toggle part of the button is displayed"),
-							 FALSE,
-							 GTK_PARAM_READWRITE));
+                                                         P_("Draw Indicator"),
+                                                         P_("If the toggle part of the button is displayed"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE|G_PARAM_DEPRECATED));
 
   toggle_button_signals[TOGGLED] =
     g_signal_new (I_("toggled"),
-		  G_OBJECT_CLASS_TYPE (gobject_class),
-		  G_SIGNAL_RUN_FIRST,
-		  G_STRUCT_OFFSET (GtkToggleButtonClass, toggled),
-		  NULL, NULL,
-		  _gtk_marshal_VOID__VOID,
-		  G_TYPE_NONE, 0);
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GtkToggleButtonClass, toggled),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  gtk_widget_class_install_style_property (widget_class,
+    g_param_spec_int ("indicator-size",
+                      P_("Indicator Size"),
+                      P_("Size of check or radio indicator"),
+                      0, G_MAXINT, 13,
+                      GTK_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+    g_param_spec_int ("indicator-spacing",
+                      P_("Indicator Spacing"),
+                      P_("Spacing around check or radio indicator"),
+                      0, G_MAXINT, 2,
+                      GTK_PARAM_READABLE));
 
   g_type_class_add_private (class, sizeof (GtkToggleButtonPrivate));
 }
@@ -167,7 +185,6 @@ gtk_toggle_button_init (GtkToggleButton *toggle_button)
                                                      GtkToggleButtonPrivate);
   priv = toggle_button->priv;
 
-  priv->draw_indicator = FALSE;
   GTK_BUTTON (toggle_button)->priv->depress_on_activate = TRUE;
 }
 
@@ -181,8 +198,8 @@ gtk_toggle_button_activatable_interface_init (GtkActivatableIface *iface)
 
 static void
 gtk_toggle_button_update (GtkActivatable *activatable,
-			  GtkAction      *action,
-			  const gchar    *property_name)
+                          GtkAction      *action,
+                          const gchar    *property_name)
 {
   GtkToggleButton *button;
 
@@ -201,7 +218,7 @@ gtk_toggle_button_update (GtkActivatable *activatable,
 
 static void
 gtk_toggle_button_sync_action_properties (GtkActivatable *activatable,
-				          GtkAction      *action)
+                                          GtkAction      *action)
 {
   GtkToggleButton *button;
 
@@ -272,7 +289,10 @@ gtk_toggle_button_set_property (GObject      *object,
       gtk_toggle_button_set_inconsistent (tb, g_value_get_boolean (value));
       break;
     case PROP_DRAW_INDICATOR:
-      gtk_toggle_button_set_mode (tb, g_value_get_boolean (value));
+      gtk_button_set_indicator_style (GTK_BUTTON (tb),
+                                      g_value_get_boolean (value)
+                                              ? GTK_INDICATOR_STYLE_CHECK
+                                              : GTK_INDICATOR_STYLE_PLAIN);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -282,9 +302,9 @@ gtk_toggle_button_set_property (GObject      *object,
 
 static void
 gtk_toggle_button_get_property (GObject      *object,
-				guint         prop_id,
-				GValue       *value,
-				GParamSpec   *pspec)
+                                guint         prop_id,
+                                GValue       *value,
+                                GParamSpec   *pspec)
 {
   GtkToggleButton *tb = GTK_TOGGLE_BUTTON (object);
   GtkToggleButtonPrivate *priv = tb->priv;
@@ -298,7 +318,7 @@ gtk_toggle_button_get_property (GObject      *object,
       g_value_set_boolean (value, priv->inconsistent);
       break;
     case PROP_DRAW_INDICATOR:
-      g_value_set_boolean (value, priv->draw_indicator);
+      g_value_set_boolean (value, gtk_button_get_indicator_style (GTK_BUTTON (object)) != GTK_INDICATOR_STYLE_PLAIN);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -308,7 +328,7 @@ gtk_toggle_button_get_property (GObject      *object,
 
 /**
  * gtk_toggle_button_set_mode:
- * @toggle_button: a #GtkToggleButton
+ * @button: a #GtkToggleButton
  * @draw_indicator: if %TRUE, draw the button as a separate indicator
  * and label; if %FALSE, draw the button like a normal button
  *
@@ -319,94 +339,86 @@ gtk_toggle_button_get_property (GObject      *object,
  * This function only affects instances of classes like #GtkCheckButton
  * and #GtkRadioButton that derive from #GtkToggleButton,
  * not instances of #GtkToggleButton itself.
+ *
+ * Deprecated:3.0: Use gtk_button_set_indicator_style() instead
  */
 void
-gtk_toggle_button_set_mode (GtkToggleButton *toggle_button,
-			    gboolean         draw_indicator)
+gtk_toggle_button_set_mode (GtkToggleButton *button,
+                            gboolean         draw_indicator)
 {
-  GtkToggleButtonPrivate *priv;
-
-  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
+  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
 
-  priv = toggle_button->priv;
-
-  draw_indicator = draw_indicator ? TRUE : FALSE;
-
-  if (priv->draw_indicator != draw_indicator)
-    {
-      priv->draw_indicator = draw_indicator;
-      GTK_BUTTON (toggle_button)->priv->depress_on_activate = !draw_indicator;
-
-      if (gtk_widget_get_visible (GTK_WIDGET (toggle_button)))
-	gtk_widget_queue_resize (GTK_WIDGET (toggle_button));
-
-      g_object_notify (G_OBJECT (toggle_button), "draw-indicator");
-    }
+  gtk_button_set_indicator_style (GTK_BUTTON (button),
+                                  draw_indicator ? GTK_INDICATOR_STYLE_CHECK
+                                                 : GTK_INDICATOR_STYLE_PLAIN);
+  g_object_notify (G_OBJECT (button), "draw-indicator");
 }
 
 /**
  * gtk_toggle_button_get_mode:
- * @toggle_button: a #GtkToggleButton
+ * @button: a #GtkToggleButton
  *
  * Retrieves whether the button is displayed as a separate indicator
  * and label. See gtk_toggle_button_set_mode().
  *
  * Return value: %TRUE if the togglebutton is drawn as a separate indicator
  *   and label.
+ *
+ * Deprecated:3.0: Use gtk_button_get_indicator_style() instead
  **/
 gboolean
-gtk_toggle_button_get_mode (GtkToggleButton *toggle_button)
+gtk_toggle_button_get_mode (GtkToggleButton *button)
 {
-  g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button), FALSE);
+  g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (button), FALSE);
 
-  return toggle_button->priv->draw_indicator;
+  return gtk_button_get_indicator_style (GTK_BUTTON (button)) != GTK_INDICATOR_STYLE_PLAIN;
 }
 
 void
-gtk_toggle_button_set_active (GtkToggleButton *toggle_button,
+gtk_toggle_button_set_active (GtkToggleButton *button,
 			      gboolean         is_active)
 {
   GtkToggleButtonPrivate *priv;
 
-  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
+  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
 
-  priv = toggle_button->priv;
+  priv = button->priv;
 
   is_active = is_active != FALSE;
 
   if (priv->active != is_active)
-    gtk_button_clicked (GTK_BUTTON (toggle_button));
+    gtk_button_clicked (GTK_BUTTON (button));
 }
 
 void
-_gtk_toggle_button_set_active (GtkToggleButton *toggle_button,
+_gtk_toggle_button_set_active (GtkToggleButton *button,
                                gboolean         is_active)
 {
   g_warning ("this is broken...");
-  toggle_button->priv->active = is_active;
+  button->priv->active = is_active;
 }
 
 gboolean
-gtk_toggle_button_get_active (GtkToggleButton *toggle_button)
+gtk_toggle_button_get_active (GtkToggleButton *button)
 {
-  g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button), FALSE);
+  g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (button), FALSE);
 
-  return toggle_button->priv->active;
+  return button->priv->active;
 }
 
 
 void
-gtk_toggle_button_toggled (GtkToggleButton *toggle_button)
+gtk_toggle_button_toggled (GtkToggleButton *button)
 {
-  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
+  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
 
-  g_signal_emit (toggle_button, toggle_button_signals[TOGGLED], 0);
+  g_signal_emit (button, toggle_button_signals[TOGGLED], 0);
 }
 
 /**
  * gtk_toggle_button_set_inconsistent:
- * @toggle_button: a #GtkToggleButton
- * @setting: %TRUE if state is inconsistent
+ * @button: a #GtkToggleButton
+ * @is_inconsistent: %TRUE if state is inconsistent
  *
  * If the user has selected a range of elements (such as some text or
  * spreadsheet cells) that are affected by a toggle button, and the
@@ -416,75 +428,350 @@ gtk_toggle_button_toggled (GtkToggleButton *toggle_button)
  * state again if the user toggles the toggle button. This has to be
  * done manually, gtk_toggle_button_set_inconsistent() only affects
  * visual appearance, it doesn't affect the semantics of the button.
- * 
  **/
 void
-gtk_toggle_button_set_inconsistent (GtkToggleButton *toggle_button,
-                                    gboolean         setting)
+gtk_toggle_button_set_inconsistent (GtkToggleButton *button,
+                                    gboolean         is_inconsistent)
 {
   GtkToggleButtonPrivate *priv;
 
-  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
+  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
 
-  priv = toggle_button->priv;
+  priv = button->priv;
 
-  setting = setting != FALSE;
+  is_inconsistent = is_inconsistent != FALSE;
 
-  if (setting != priv->inconsistent)
+  if (priv->inconsistent != is_inconsistent)
     {
-      priv->inconsistent = setting;
+      priv->inconsistent = is_inconsistent;
 
-      gtk_toggle_button_update_state (GTK_BUTTON (toggle_button));
-      gtk_widget_queue_draw (GTK_WIDGET (toggle_button));
+      gtk_toggle_button_update_state (GTK_BUTTON (button));
+      gtk_widget_queue_draw (GTK_WIDGET (button));
 
-      g_object_notify (G_OBJECT (toggle_button), "inconsistent");      
+      g_object_notify (G_OBJECT (button), "inconsistent");
     }
 }
 
 /**
  * gtk_toggle_button_get_inconsistent:
- * @toggle_button: a #GtkToggleButton
+ * @button: a #GtkToggleButton
  * 
  * Gets the value set by gtk_toggle_button_set_inconsistent().
  * 
- * Return value: %TRUE if the button is displayed as inconsistent, %FALSE otherwise
+ * Return value: %TRUE if the button is displayed as inconsistent,
+ *     %FALSE otherwise
  **/
 gboolean
-gtk_toggle_button_get_inconsistent (GtkToggleButton *toggle_button)
+gtk_toggle_button_get_inconsistent (GtkToggleButton *button)
 {
-  g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button), FALSE);
+  g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (button), FALSE);
 
-  return toggle_button->priv->inconsistent;
+  return button->priv->inconsistent;
+}
+
+static void
+gtk_toggle_button_get_preferred_width (GtkWidget *widget,
+                                       gint      *minimum,
+                                       gint      *natural)
+{
+  GtkToggleButton *button = GTK_TOGGLE_BUTTON (widget);
+  GtkToggleButtonPrivate *priv = button->priv;
+
+  if (gtk_button_get_indicator_style (GTK_BUTTON (widget)) != GTK_INDICATOR_STYLE_PLAIN)
+    {
+      GtkWidget *child;
+      gint indicator_size;
+      gint indicator_spacing;
+      gint focus_width;
+      gint focus_pad;
+      guint border_width;
+
+      border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+      gtk_widget_style_get (GTK_WIDGET (widget),
+                            "focus-line-width", &focus_width,
+                            "focus-padding", &focus_pad,
+                            "indicator-size", &indicator_size,
+                            "indicator-spacing", &indicator_spacing,
+                            NULL);
+      *minimum = 2 * border_width;
+      *natural = 2 * border_width;
+
+      child = gtk_bin_get_child (GTK_BIN (widget));
+      if (child && gtk_widget_get_visible (child))
+        {
+          gint child_min, child_nat;
+
+          gtk_widget_get_preferred_width (child, &child_min, &child_nat);
+
+          *minimum += child_min + indicator_spacing;
+          *natural += child_nat + indicator_spacing;
+        }
+
+      *minimum += (indicator_size + indicator_spacing * 2 + 2 * (focus_width + focus_pad));
+      *natural += (indicator_size + indicator_spacing * 2 + 2 * (focus_width + focus_pad));
+    }
+  else
+    GTK_WIDGET_CLASS (gtk_toggle_button_parent_class)->get_preferred_width (widget, minimum, natural);
+}
+
+static void
+gtk_toggle_button_get_preferred_height (GtkWidget *widget,
+                                        gint      *minimum,
+                                        gint      *natural)
+{
+  GtkToggleButton *button = GTK_TOGGLE_BUTTON (widget);
+  GtkToggleButtonPrivate *priv = button->priv;
+
+  if (gtk_button_get_indicator_style (GTK_BUTTON (widget)) != GTK_INDICATOR_STYLE_PLAIN)
+    {
+      GtkWidget *child;
+      gint temp;
+      gint indicator_size;
+      gint indicator_spacing;
+      gint focus_width;
+      gint focus_pad;
+      guint border_width;
+
+      border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+      gtk_widget_style_get (GTK_WIDGET (widget),
+                            "focus-line-width", &focus_width,
+                            "focus-padding", &focus_pad,
+                            "indicator-size", &indicator_size,
+                            "indicator-spacing", &indicator_spacing,
+                            NULL);
+
+      *minimum = border_width * 2;
+      *natural = border_width * 2;
+
+      child = gtk_bin_get_child (GTK_BIN (widget));
+      if (child && gtk_widget_get_visible (child))
+        {
+          gint child_min, child_nat;
+
+          gtk_widget_get_preferred_height (child, &child_min, &child_nat);
+
+          *minimum += child_min;
+          *natural += child_nat;
+        }
+
+      temp = indicator_size + indicator_spacing * 2;
+      *minimum = MAX (*minimum, temp) + 2 * (focus_width + focus_pad);
+      *natural = MAX (*natural, temp) + 2 * (focus_width + focus_pad);
+    }
+  else
+    GTK_WIDGET_CLASS (gtk_toggle_button_parent_class)->get_preferred_height (widget, minimum, natural);
+}
+
+static void
+gtk_toggle_button_size_allocate (GtkWidget     *widget,
+                                 GtkAllocation *allocation)
+{
+  GtkToggleButton *button = GTK_TOGGLE_BUTTON (widget);
+  GtkToggleButtonPrivate *priv = button->priv;
+  GtkAllocation child_allocation;
+
+  if (gtk_button_get_indicator_style (GTK_BUTTON (widget)) != GTK_INDICATOR_STYLE_PLAIN)
+    {
+      GtkWidget *child;
+      gint indicator_size;
+      gint indicator_spacing;
+      gint focus_width;
+      gint focus_pad;
+
+      gtk_widget_style_get (widget,
+                            "focus-line-width", &focus_width,
+                            "focus-padding", &focus_pad,
+                            "indicator-size", &indicator_size,
+                            "indicator-spacing", &indicator_spacing,
+                            NULL);
+
+      gtk_widget_set_allocation (widget, allocation);
+
+      if (gtk_widget_get_realized (widget))
+        gdk_window_move_resize (gtk_button_get_event_window (GTK_BUTTON (widget)),
+                                allocation->x, allocation->y,
+                                allocation->width, allocation->height);
+
+      child = gtk_bin_get_child (GTK_BIN (widget));
+      if (child && gtk_widget_get_visible (child))
+        {
+          GtkRequisition child_requisition;
+          guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+          gtk_widget_get_preferred_size (child, &child_requisition, NULL);
+          child_allocation.width = MIN (child_requisition.width,
+                                        allocation->width -
+                                        ((border_width + focus_width + focus_pad) * 2
+                                        + indicator_size + indicator_spacing * 3));
+          child_allocation.width = MAX (child_allocation.width, 1);
+
+          child_allocation.height = MIN (child_requisition.height,
+                                         allocation->height - (border_width + focus_width + focus_pad) * 2);
+          child_allocation.height = MAX (child_allocation.height, 1);
+
+          child_allocation.x = (border_width + indicator_size + indicator_spacing * 3 +
+                                allocation->x + focus_width + focus_pad);
+          child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
+
+          if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+            child_allocation.x = allocation->x + allocation->width
+              - (child_allocation.x - allocation->x + child_allocation.width);
+
+          gtk_widget_size_allocate (child, &child_allocation);
+        }
+    }
+  else
+    GTK_WIDGET_CLASS (gtk_toggle_button_parent_class)->size_allocate (widget, allocation);
+}
+
+static void
+gtk_toggle_button_draw_indicator (GtkToggleButton *button,
+                                  cairo_t         *cr)
+{
+  GtkWidget *widget = GTK_WIDGET (button);
+  GtkWidget *child;
+  GtkStateType state_type;
+  GtkShadowType shadow_type;
+  gint x, y;
+  gint indicator_size;
+  gint indicator_spacing;
+  gint focus_width;
+  gint focus_pad;
+  guint border_width;
+  gboolean interior_focus;
+
+  gtk_widget_style_get (widget,
+                        "interior-focus", &interior_focus,
+                        "focus-line-width", &focus_width,
+                        "focus-padding", &focus_pad,
+                        "indicator-size", &indicator_size,
+                        "indicator-spacing", &indicator_spacing,
+                        NULL);
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+  x = indicator_spacing + border_width;
+  y = (gtk_widget_get_allocated_height (widget) - indicator_size) / 2;
+
+  child = gtk_bin_get_child (GTK_BIN (widget));
+  if (!interior_focus || !(child && gtk_widget_get_visible (child)))
+    x += focus_width + focus_pad;
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+    x = gtk_widget_get_allocated_width (widget) - (indicator_size + x);
+
+  if (gtk_toggle_button_get_inconsistent (button))
+    shadow_type = GTK_SHADOW_ETCHED_IN;
+  else if (gtk_toggle_button_get_active (button))
+    shadow_type = GTK_SHADOW_IN;
+  else
+    shadow_type = GTK_SHADOW_OUT;
+
+  if (GTK_BUTTON (widget)->priv->activate_timeout ||
+      (GTK_BUTTON (widget)->priv->button_down && GTK_BUTTON (widget)->priv->in_button))
+    state_type = GTK_STATE_ACTIVE;
+  else if (GTK_BUTTON (widget)->priv->in_button)
+    state_type = GTK_STATE_PRELIGHT;
+  else if (!gtk_widget_is_sensitive (widget))
+    state_type = GTK_STATE_INSENSITIVE;
+  else
+    state_type = GTK_STATE_NORMAL;
+
+  if (gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT)
+    gtk_paint_flat_box (gtk_widget_get_style (widget), cr, GTK_STATE_PRELIGHT,
+                        GTK_SHADOW_ETCHED_OUT,
+                        widget, "checkbutton",
+                        border_width, border_width,
+                        gtk_widget_get_allocated_width (widget) - (2 * border_width),
+                        gtk_widget_get_allocated_height (widget) - (2 * border_width));
+
+  if (gtk_button_get_indicator_style (GTK_BUTTON (widget)) == GTK_INDICATOR_STYLE_CHECK)
+    gtk_paint_check (gtk_widget_get_style (widget), cr,
+                     state_type, shadow_type,
+                     widget, "checkbutton",
+                     x, y, indicator_size, indicator_size);
+  else
+    gtk_paint_option (gtk_widget_get_style (widget), cr,
+                      state_type, shadow_type,
+                      widget, "radiobutton",
+                      x, y, indicator_size, indicator_size);
 }
 
 static gint
 gtk_toggle_button_draw (GtkWidget *widget,
-			cairo_t   *cr)
+                        cairo_t   *cr)
 {
-  GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (widget);
-  GtkToggleButtonPrivate *priv = toggle_button->priv;
-  GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
-  GtkButton *button = GTK_BUTTON (widget);
-  GtkStateType state_type;
+  GtkToggleButton *button = GTK_TOGGLE_BUTTON (widget);
+  GtkToggleButtonPrivate *priv = button->priv;
+  GtkStateType state;
   GtkShadowType shadow_type;
+  GtkWidget *child;
+  gint interior_focus;
+  gint focus_width;
+  gint focus_pad;
+  gint border_width;
+  GtkAllocation allocation;
 
-  state_type = gtk_widget_get_state (widget);
+  gtk_widget_get_allocation (widget, &allocation);
+  state = gtk_widget_get_state (widget);
 
-  if (priv->inconsistent)
+  if (gtk_button_get_indicator_style (GTK_BUTTON (widget)) != GTK_INDICATOR_STYLE_PLAIN)
     {
-      if (state_type == GTK_STATE_ACTIVE)
-        state_type = GTK_STATE_NORMAL;
-      shadow_type = GTK_SHADOW_ETCHED_IN;
+      gtk_toggle_button_draw_indicator (button, cr);
+
+      if (gtk_widget_has_focus (widget))
+        {
+          border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+          gtk_widget_style_get (widget,
+                                "interior-focus", &interior_focus,
+                                "focus-line-width", &focus_width,
+                                "focus-padding", &focus_pad,
+                                NULL);
+
+          child = gtk_bin_get_child (GTK_BIN (widget));
+          if (interior_focus && child && gtk_widget_get_visible (child))
+            {
+              GtkAllocation child_allocation;
+
+              gtk_widget_get_allocation (child, &child_allocation);
+              gtk_paint_focus (gtk_widget_get_style (widget), cr, state,
+                               widget, "checkbutton",
+                               child_allocation.x - allocation.x - focus_width - focus_pad,
+                               child_allocation.y - allocation.y - focus_width - focus_pad,
+                               child_allocation.width + 2 * (focus_width + focus_pad),
+                              child_allocation.height + 2 * (focus_width + focus_pad));
+            }
+          else
+            {
+              gtk_paint_focus (gtk_widget_get_style (widget), cr, state,
+                               widget, "checkbutton",
+                               border_width,
+                               border_width,
+                               allocation.width - 2 * border_width,
+                               allocation.height - 2 * border_width);
+           }
+       }
     }
   else
-    shadow_type = button->priv->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
-
-  _gtk_button_paint (button, cr,
-                     gtk_widget_get_allocated_width (widget),
-                     gtk_widget_get_allocated_height (widget),
-                     state_type, shadow_type,
-                     "togglebutton", "togglebuttondefault");
+    {
+      if (priv->inconsistent)
+        {
+          if (state == GTK_STATE_ACTIVE)
+            state = GTK_STATE_NORMAL;
+          shadow_type = GTK_SHADOW_ETCHED_IN;
+        }
+      else
+        shadow_type = GTK_BUTTON (widget)->priv->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+
+      _gtk_button_paint (GTK_BUTTON (widget), cr,
+                         allocation.width, allocation.height,
+                         state, shadow_type,
+                         "togglebutton", "togglebuttondefault");
+    }
 
+  child = gtk_bin_get_child (GTK_BIN (widget));
   if (child)
     gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
 
@@ -526,7 +813,7 @@ gtk_toggle_button_released (GtkButton *button)
       button->priv->button_down = FALSE;
 
       if (button->priv->in_button)
-	gtk_button_clicked (button);
+        gtk_button_clicked (button);
 
       gtk_toggle_button_update_state (button);
       gtk_widget_queue_draw (GTK_WIDGET (button));
@@ -570,11 +857,12 @@ gtk_toggle_button_update_state (GtkButton *button)
   else
     depressed = priv->active;
 
-  if (!touchscreen && button->priv->in_button && (!button->priv->button_down || priv->draw_indicator))
+  if (!touchscreen && button->priv->in_button &&
+      (!button->priv->button_down || button->priv->indicator_style != GTK_INDICATOR_STYLE_PLAIN))
     new_state = GTK_STATE_PRELIGHT;
   else
     new_state = depressed ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL;
 
-  _gtk_button_set_depressed (button, depressed); 
+  _gtk_button_set_depressed (button, depressed);
   gtk_widget_set_state (GTK_WIDGET (toggle_button), new_state);
 }
diff --git a/gtk/gtktogglebutton.h b/gtk/gtktogglebutton.h
index 48b477c..0ff9280 100644
--- a/gtk/gtktogglebutton.h
+++ b/gtk/gtktogglebutton.h
@@ -60,7 +60,7 @@ struct _GtkToggleButtonClass
 {
   GtkButtonClass parent_class;
 
-  void (* toggled) (GtkToggleButton *toggle_button);
+  void (* toggled)       (GtkToggleButton *toggle_button);
 
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);
@@ -70,24 +70,26 @@ struct _GtkToggleButtonClass
 };
 
 
-GType      gtk_toggle_button_get_type          (void) G_GNUC_CONST;
-
-GtkWidget* gtk_toggle_button_new               (void);
-GtkWidget* gtk_toggle_button_new_with_label    (const gchar     *label);
-GtkWidget* gtk_toggle_button_new_with_mnemonic (const gchar     *label);
-void       gtk_toggle_button_set_mode          (GtkToggleButton *toggle_button,
-                                                gboolean         draw_indicator);
-gboolean   gtk_toggle_button_get_mode          (GtkToggleButton *toggle_button);
-void       gtk_toggle_button_set_active        (GtkToggleButton *toggle_button,
-                                                gboolean         is_active);
-gboolean   gtk_toggle_button_get_active        (GtkToggleButton *toggle_button);
-void       gtk_toggle_button_toggled           (GtkToggleButton *toggle_button);
-void       gtk_toggle_button_set_inconsistent  (GtkToggleButton *toggle_button,
-                                                gboolean         setting);
-gboolean   gtk_toggle_button_get_inconsistent  (GtkToggleButton *toggle_button);
-
-void       _gtk_toggle_button_set_active       (GtkToggleButton *toggle_button,
-                                                gboolean         is_active);
+GType          gtk_toggle_button_get_type          (void) G_GNUC_CONST;
+
+GtkWidget*     gtk_toggle_button_new               (void);
+GtkWidget*     gtk_toggle_button_new_with_label    (const gchar     *label);
+GtkWidget*     gtk_toggle_button_new_with_mnemonic (const gchar     *label);
+#ifndef GTK_DISABLE_DEPRECATED
+void           gtk_toggle_button_set_mode          (GtkToggleButton *button,
+                                                    gboolean         mode);
+gboolean       gtk_toggle_button_get_mode          (GtkToggleButton *button);
+#endif
+void           gtk_toggle_button_set_active        (GtkToggleButton *button,
+                                                    gboolean         is_active);
+gboolean       gtk_toggle_button_get_active        (GtkToggleButton *button);
+void           gtk_toggle_button_set_inconsistent  (GtkToggleButton *button,
+                                                    gboolean         is_inconsistent);
+gboolean       gtk_toggle_button_get_inconsistent  (GtkToggleButton *button);
+void           gtk_toggle_button_toggled           (GtkToggleButton *button);
+
+void           _gtk_toggle_button_set_active       (GtkToggleButton *button,
+                                                    gboolean         is_active);
 
 
 G_END_DECLS



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