--- gtk+-2.6.4/gtk/gtkcheckbutton.c 2004-08-09 19:59:51.000000000 +0300 +++ gtk+-2.6.4/gtk/gtkcheckbutton.c 2005-04-06 16:19:36.317017336 +0300 @@ -31,27 +31,44 @@ #include "gtklabel.h" -#define INDICATOR_SIZE 13 +#define INDICATOR_SIZE 24 #define INDICATOR_SPACING 2 +/* maJiK numbers for indicator */ +#define INDICATOR_SIDE_PADDING 5 +#define FOCUS_TOP_PADDING 7 +#define FOCUS_DOWN_PADDING 1 + +/* spacing to take account of the 1 pixel + transparency of the widgetfocus.png +*/ +#define HILDON_SPACING 1 + +#define TOGGLE_ON_CLICK "toggle-on-click" -static void gtk_check_button_class_init (GtkCheckButtonClass *klass); -static void gtk_check_button_init (GtkCheckButton *check_button); -static void gtk_check_button_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_check_button_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gint gtk_check_button_expose (GtkWidget *widget, - GdkEventExpose *event); -static void gtk_check_button_paint (GtkWidget *widget, - GdkRectangle *area); -static void gtk_check_button_draw_indicator (GtkCheckButton *check_button, - GdkRectangle *area); -static void gtk_real_check_button_draw_indicator (GtkCheckButton *check_button, - GdkRectangle *area); +static void gtk_check_button_class_init (GtkCheckButtonClass *klass); +static void gtk_check_button_init (GtkCheckButton *check_button); +static void gtk_check_button_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_check_button_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gint gtk_check_button_expose (GtkWidget *widget, + GdkEventExpose *event); +static void gtk_check_button_paint (GtkWidget *widget, + GdkRectangle *area); +static void gtk_check_button_draw_indicator (GtkCheckButton *check_button, + GdkRectangle *area); +static void gtk_real_check_button_draw_indicator + (GtkCheckButton *check_button, + GdkRectangle *area); -static GtkToggleButtonClass *parent_class = NULL; +static void gtk_check_button_calc_indicator_size( GtkCheckButton *button, + GdkRectangle *rect ); + +static void gtk_check_button_clicked (GtkButton *button); +static void gtk_check_button_update_state (GtkButton *button); +static GtkToggleButtonClass *parent_class = NULL; GType gtk_check_button_get_type (void) @@ -85,32 +102,36 @@ gtk_check_button_class_init (GtkCheckButtonClass *class) { GtkWidgetClass *widget_class; - + GtkButtonClass *button_class; + widget_class = (GtkWidgetClass*) class; + button_class = (GtkButtonClass*) class; parent_class = g_type_class_peek_parent (class); widget_class->size_request = gtk_check_button_size_request; widget_class->size_allocate = gtk_check_button_size_allocate; widget_class->expose_event = gtk_check_button_expose; + button_class->clicked = gtk_check_button_clicked; + 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, - G_PARAM_READABLE)); + P_("Indicator Size"), + P_("Size of check or radio indicator"), + 0, + G_MAXINT, + INDICATOR_SIZE, + G_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, - G_PARAM_READABLE)); + P_("Indicator Spacing"), + P_("Spacing around check or radio indicator"), + 0, + G_MAXINT, + INDICATOR_SPACING, + G_PARAM_READABLE)); } static void @@ -148,7 +169,8 @@ GtkWidget* gtk_check_button_new_with_mnemonic (const gchar *label) { - return g_object_new (GTK_TYPE_CHECK_BUTTON, "label", label, "use_underline", TRUE, NULL); + return g_object_new (GTK_TYPE_CHECK_BUTTON, "label", label, + "use_underline", TRUE, NULL); } @@ -163,39 +185,70 @@ if (GTK_WIDGET_DRAWABLE (widget)) { - gint border_width; - gint interior_focus; - gint focus_width; - gint focus_pad; - + gint border_width = 0; + gint interior_focus = 0; + gint focus_width = 0; + gint focus_pad = 0; + gint indicator_size = 0; + gint indicator_spacing = 0; + 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); - - gtk_check_button_draw_indicator (check_button, area); border_width = GTK_CONTAINER (widget)->border_width; + + /* Hildon: change the focus so that it draws around the entire + * widget - including both the indicator *and* the label + */ if (GTK_WIDGET_HAS_FOCUS (widget)) { GtkWidget *child = GTK_BIN (widget)->child; + int w = indicator_size + 2 * indicator_spacing + + 2 * (focus_width + focus_pad); + int h = indicator_size + 2 * indicator_spacing + + 2 * (focus_width + focus_pad) + 2 * HILDON_SPACING + - FOCUS_TOP_PADDING; + int x = widget->allocation.x; + int y = widget->allocation.y + (widget->allocation.height - h)/2 + + FOCUS_DOWN_PADDING; + + if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) + x = widget->allocation.x + widget->allocation.width - + (2 * HILDON_SPACING) - (indicator_size + 2) - + (indicator_spacing + 2); + if (interior_focus && child && GTK_WIDGET_VISIBLE (child)) - gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget), - NULL, widget, "checkbutton", - child->allocation.x - focus_width - focus_pad, - child->allocation.y - focus_width - focus_pad, - child->allocation.width + 2 * (focus_width + focus_pad), - child->allocation.height + 2 * (focus_width + focus_pad)); + { + if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) + { + /* Move the "x" to the left, and enlarge the width, + both accounting for the child + */ + x += - child->allocation.width - HILDON_SPACING - + (widget->style->xthickness); + w += child->allocation.width + HILDON_SPACING + + (widget->style->xthickness); + } else { + w = child->allocation.x + child->allocation.width + + 2 * widget->style->xthickness - x; + } + + gtk_paint_focus (widget->style, widget->window, + GTK_WIDGET_STATE (widget), + NULL, widget, "checkbutton", x, y, w, h); + } else - gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget), - NULL, widget, "checkbutton", - border_width + widget->allocation.x, - border_width + widget->allocation.y, - widget->allocation.width - 2 * border_width, - widget->allocation.height - 2 * border_width); + gtk_paint_focus (widget->style, widget->window, + GTK_WIDGET_STATE (widget), + NULL, widget, "checkbutton", x, y, w, h); } + gtk_check_button_draw_indicator (check_button, area); } } @@ -205,10 +258,10 @@ 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); } @@ -233,7 +286,7 @@ "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL); - + requisition->width = border_width * 2; requisition->height = border_width * 2; @@ -246,15 +299,19 @@ GtkRequisition child_requisition; gtk_widget_size_request (child, &child_requisition); - - requisition->width += child_requisition.width + indicator_spacing; + + requisition->width += child_requisition.width + + 2 * widget->style->xthickness; requisition->height += child_requisition.height; + requisition->width += 2 * widget->style->xthickness; } - requisition->width += (indicator_size + indicator_spacing * 2 + 2 * (focus_width + focus_pad)); + requisition->width += (indicator_size + indicator_spacing * 2 + + 2 * (focus_width + focus_pad)); temp = indicator_size + indicator_spacing * 2; - requisition->height = MAX (requisition->height, temp) + 2 * (focus_width + focus_pad); + requisition->height = MAX (requisition->height, temp) + + 2 * (focus_width + focus_pad); } else (* GTK_WIDGET_CLASS (parent_class)->size_request) (widget, requisition); @@ -280,45 +337,59 @@ gint focus_width; gint focus_pad; - _gtk_check_button_get_props (check_button, &indicator_size, &indicator_spacing); + _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); - + widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget)) gdk_window_move_resize (button->event_window, allocation->x, allocation->y, allocation->width, allocation->height); - if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child)) + if (GTK_BIN (button)->child && + GTK_WIDGET_VISIBLE (GTK_BIN (button)->child)) { GtkRequisition child_requisition; gint border_width = GTK_CONTAINER (widget)->border_width; - - gtk_widget_get_child_requisition (GTK_BIN (button)->child, &child_requisition); + + gtk_widget_get_child_requisition (GTK_BIN (button)->child, + &child_requisition); - child_allocation.width = MIN (child_requisition.width, + 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); + ((border_width + focus_width + + focus_pad) * 2 + - 2 * widget->style->xthickness + + indicator_size + + indicator_spacing * 2 ) ); + child_allocation.width = MAX (child_allocation.width, 1); + child_allocation.height = MIN (child_requisition.height, - allocation->height - (border_width + focus_width + focus_pad) * 2); + 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 + - widget->allocation.x + focus_width + focus_pad); + child_allocation.x = (border_width + indicator_size + + indicator_spacing * 2 + + widget->style->xthickness + + widget->allocation.x + + focus_width + focus_pad); child_allocation.y = widget->allocation.y + - (allocation->height - child_allocation.height) / 2; - + (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); + child_allocation.x = allocation->x + allocation->width - + (child_allocation.x - allocation->x + child_allocation.width); - gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation); + gtk_widget_size_allocate (GTK_BIN (button)->child, + &child_allocation); } } else @@ -375,45 +446,33 @@ GdkRectangle *area) { 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; - gboolean interior_focus; + + GdkRectangle indicator = {0, 0, 0, 0}; if (GTK_WIDGET_DRAWABLE (check_button)) { widget = GTK_WIDGET (check_button); button = GTK_BUTTON (check_button); toggle_button = GTK_TOGGLE_BUTTON (check_button); - - 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); - - x = widget->allocation.x + indicator_spacing + GTK_CONTAINER (widget)->border_width; - y = widget->allocation.y + (widget->allocation.height - indicator_size) / 2; - - child = GTK_BIN (check_button)->child; - if (!interior_focus || !(child && GTK_WIDGET_VISIBLE (child))) - x += focus_width + focus_pad; - + gtk_check_button_calc_indicator_size( check_button, &indicator ); + + /* move indicator to root coordinates */ + indicator.x += widget->allocation.x; + indicator.y += widget->allocation.y; + if (toggle_button->inconsistent) shadow_type = GTK_SHADOW_ETCHED_IN; else if (toggle_button->active) shadow_type = GTK_SHADOW_IN; else shadow_type = GTK_SHADOW_OUT; - - if (button->activate_timeout || (button->button_down && button->in_button)) + + if (button->activate_timeout || + (button->button_down && button->in_button)) state_type = GTK_STATE_ACTIVE; else if (button->in_button) state_type = GTK_STATE_PRELIGHT; @@ -422,32 +481,107 @@ else state_type = GTK_STATE_NORMAL; - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) - x = widget->allocation.x + widget->allocation.width - (indicator_size + x - widget->allocation.x); + /* Hildon change. We want to draw active image always when we have + * focus. */ + if (GTK_WIDGET_HAS_FOCUS (widget)) + state_type = GTK_STATE_ACTIVE; - if (GTK_WIDGET_STATE (toggle_button) == GTK_STATE_PRELIGHT) + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) { - GdkRectangle restrict_area; - GdkRectangle new_area; - - restrict_area.x = widget->allocation.x + GTK_CONTAINER (widget)->border_width; - restrict_area.y = widget->allocation.y + GTK_CONTAINER (widget)->border_width; - restrict_area.width = widget->allocation.width - (2 * GTK_CONTAINER (widget)->border_width); - restrict_area.height = widget->allocation.height - (2 * GTK_CONTAINER (widget)->border_width); + indicator.x = widget->allocation.x + widget->allocation.width + - (indicator.width + indicator.x - widget->allocation.x); - if (gdk_rectangle_intersect (area, &restrict_area, &new_area)) - { - gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_PRELIGHT, - GTK_SHADOW_ETCHED_OUT, - area, widget, "checkbutton", - new_area.x, new_area.y, - new_area.width, new_area.height); - } } gtk_paint_check (widget->style, widget->window, state_type, shadow_type, area, widget, "checkbutton", - x, y, indicator_size, indicator_size); + indicator.x, indicator.y, + indicator.width, indicator.height); + } +} + + +/* calculates the size and position of the indicator + * relative to the origin of the check button. + */ +static void gtk_check_button_calc_indicator_size( GtkCheckButton *button, + GdkRectangle *rect ) +{ + gint indicator_size; + gint indicator_spacing; + gint focus_width; + gint focus_pad; + gboolean interior_focus; + GtkWidget *child; + GtkWidget *widget = GTK_WIDGET(button); + + + 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 + ); + + + /* HILDON: We want the indicator to be positioned according to the spec. + * + * NOTE: INDICATOR_SIDE_PADDING and INDICATOR_TOP_PADDING + * are maJiKal numbers that make the indicator to be drawn + * to correct coordinates, 1337 \o/ + */ + rect->x = INDICATOR_SIDE_PADDING; + rect->y = ( widget->allocation.height - indicator_size ) / 2; + + /* Hildon: we always add space for the focus */ + rect->x += focus_width + focus_pad; + + child = GTK_BIN (widget)->child; + if (interior_focus && child && GTK_WIDGET_VISIBLE (child)) + { + rect->y += HILDON_SPACING; } + + rect->width = indicator_size; + rect->height = indicator_size; } + +static void +gtk_check_button_clicked (GtkButton *button) +{ + GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button); + + toggle_button->active = !toggle_button->active; + gtk_toggle_button_toggled (toggle_button); + + gtk_check_button_update_state (button); + + g_object_notify (G_OBJECT (toggle_button), "active"); +} + +static void +gtk_check_button_update_state (GtkButton *button) +{ + GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button); + gboolean depressed; + GtkStateType new_state; + + if (toggle_button->inconsistent) + depressed = FALSE; + else if (button->in_button && button->button_down) + depressed = TRUE; + else + depressed = toggle_button->active; + + if (button->in_button && + (!button->button_down || toggle_button->draw_indicator)) + new_state = GTK_STATE_PRELIGHT; + else + new_state = depressed ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL; + + _gtk_button_set_depressed (button, depressed); + gtk_widget_set_state (GTK_WIDGET (toggle_button), new_state); +} +