diff options
author | Matthias Clasen <mclasen@redhat.com> | 2015-12-05 01:42:41 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2015-12-15 08:41:16 -0500 |
commit | 736d864d18fd2168cbf5e446a515293f994df2d0 (patch) | |
tree | ce40c57244846bf5a06e185a1dc1508c99563443 /gtk/gtkmodelbutton.c | |
parent | 782c2762bf55fb17402f534267c370cf460869af (diff) | |
download | gtk+-736d864d18fd2168cbf5e446a515293f994df2d0.tar.gz |
modelbutton: Port to gadgets
Diffstat (limited to 'gtk/gtkmodelbutton.c')
-rw-r--r-- | gtk/gtkmodelbutton.c | 636 |
1 files changed, 392 insertions, 244 deletions
diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c index e9f3132eeb..4c3399cbe5 100644 --- a/gtk/gtkmodelbutton.c +++ b/gtk/gtkmodelbutton.c @@ -35,8 +35,9 @@ #include "gtkpopover.h" #include "gtkintl.h" #include "gtkcssnodeprivate.h" +#include "gtkcsscustomgadgetprivate.h" #include "gtkstylecontextprivate.h" -#include "gtkcssstylepropertyprivate.h" +#include "gtkcontainerprivate.h" /** * SECTION:gtkmodelbutton @@ -141,7 +142,8 @@ struct _GtkModelButton GtkWidget *box; GtkWidget *image; GtkWidget *label; - GtkCssNode *indicator_node; + GtkCssGadget *gadget; + GtkCssGadget *indicator_gadget; gboolean active; gboolean centered; gboolean inverted; @@ -186,6 +188,8 @@ gtk_model_button_update_state (GtkModelButton *button) state = gtk_widget_get_state_flags (GTK_WIDGET (button)); + gtk_css_node_set_state (gtk_css_gadget_get_node (button->gadget), state); + if (button->role == GTK_BUTTON_ROLE_CHECK || button->role == GTK_BUTTON_ROLE_RADIO) { @@ -204,33 +208,34 @@ gtk_model_button_update_state (GtkModelButton *button) state = state | GTK_STATE_FLAG_DIR_LTR; } - gtk_css_node_set_state (button->indicator_node, state); + gtk_css_node_set_state (gtk_css_gadget_get_node (button->indicator_gadget), state); } static void update_node_ordering (GtkModelButton *button) { - GtkCssNode *widget_node, *node; + GtkCssNode *widget_node, *indicator_node, *node; widget_node = gtk_widget_get_css_node (GTK_WIDGET (button)); + indicator_node = gtk_css_gadget_get_node (button->indicator_gadget); if (indicator_is_left (GTK_WIDGET (button))) { - gtk_css_node_add_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_LEFT)); - gtk_css_node_remove_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_RIGHT)); + gtk_css_gadget_add_class (button->indicator_gadget, GTK_STYLE_CLASS_LEFT); + gtk_css_gadget_remove_class (button->indicator_gadget, GTK_STYLE_CLASS_RIGHT); node = gtk_css_node_get_first_child (widget_node); - if (node != button->indicator_node) - gtk_css_node_insert_before (widget_node, button->indicator_node, node); + if (node != indicator_node) + gtk_css_node_insert_before (widget_node, indicator_node, node); } else { - gtk_css_node_remove_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_LEFT)); - gtk_css_node_add_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_RIGHT)); + gtk_css_gadget_remove_class (button->indicator_gadget, GTK_STYLE_CLASS_LEFT); + gtk_css_gadget_add_class (button->indicator_gadget, GTK_STYLE_CLASS_RIGHT); node = gtk_css_node_get_last_child (widget_node); - if (node != button->indicator_node) - gtk_css_node_insert_after (widget_node, button->indicator_node, node); + if (node != indicator_node) + gtk_css_node_insert_after (widget_node, indicator_node, node); } } @@ -260,8 +265,9 @@ update_node_name (GtkModelButton *button) { AtkObject *accessible; AtkRole a11y_role; - const gchar *name; - gboolean visible; + const gchar *indicator_name; + gboolean indicator_visible; + GtkCssNode *indicator_node; accessible = gtk_widget_get_accessible (GTK_WIDGET (button)); switch (button->role) @@ -270,35 +276,40 @@ update_node_name (GtkModelButton *button) a11y_role = ATK_ROLE_PUSH_BUTTON; if (button->menu_name) { - name = I_("arrow"); - visible = TRUE; + indicator_name = I_("arrow"); + indicator_visible = TRUE; } else { - name = I_("check"); - visible = FALSE; + indicator_name = I_("check"); + indicator_visible = FALSE; } break; case GTK_BUTTON_ROLE_CHECK: a11y_role = ATK_ROLE_CHECK_BOX; - name = I_("check"); - visible = TRUE; + indicator_name = I_("check"); + indicator_visible = TRUE; break; case GTK_BUTTON_ROLE_RADIO: a11y_role = ATK_ROLE_RADIO_BUTTON; - name = I_("radio"); - visible = TRUE; + indicator_name = I_("radio"); + indicator_visible = TRUE; break; default: g_assert_not_reached (); } + if (button->iconic) + indicator_visible = FALSE; + atk_object_set_role (accessible, a11y_role); - gtk_css_node_set_name (button->indicator_node, name); - gtk_css_node_set_visible (button->indicator_node, visible); + + indicator_node = gtk_css_gadget_get_node (button->indicator_gadget); + gtk_css_node_set_name (indicator_node, indicator_name); + gtk_css_node_set_visible (indicator_node, indicator_visible); } static void @@ -372,9 +383,9 @@ gtk_model_button_set_menu_name (GtkModelButton *button, gtk_model_button_update_state (button); if (menu_name) - gtk_css_node_add_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_EXPANDER)); + gtk_css_gadget_add_class (button->indicator_gadget, GTK_STYLE_CLASS_EXPANDER); else - gtk_css_node_remove_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_EXPANDER)); + gtk_css_gadget_remove_class (button->indicator_gadget, GTK_STYLE_CLASS_EXPANDER); gtk_widget_queue_resize (GTK_WIDGET (button)); g_object_notify_by_pspec (G_OBJECT (button), properties[PROP_MENU_NAME]); @@ -412,6 +423,7 @@ gtk_model_button_set_iconic (GtkModelButton *button, gboolean iconic) { GtkCssNode *widget_node; + GtkCssNode *indicator_node; if (button->iconic == iconic) return; @@ -419,17 +431,22 @@ gtk_model_button_set_iconic (GtkModelButton *button, button->iconic = iconic; widget_node = gtk_widget_get_css_node (GTK_WIDGET (button)); + indicator_node = gtk_css_gadget_get_node (button->indicator_gadget); if (iconic) { gtk_css_node_set_name (widget_node, I_("button")); - gtk_css_node_add_class (widget_node, g_quark_from_static_string ("image-button")); + gtk_css_gadget_add_class (button->gadget, "image-button"); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NORMAL); + gtk_css_node_set_visible (indicator_node, FALSE); } else { gtk_css_node_set_name (widget_node, I_("modelbutton")); - gtk_css_node_remove_class (widget_node, g_quark_from_static_string ("image-button")); + gtk_css_gadget_remove_class (button->gadget, "image-button"); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); + gtk_css_node_set_visible (indicator_node, + button->role != GTK_BUTTON_ROLE_NORMAL || + button->menu_name == NULL); } update_visibility (button); @@ -535,30 +552,6 @@ gtk_model_button_set_property (GObject *object, } } -static void -gtk_model_button_get_full_border (GtkModelButton *button, - GtkBorder *border, - gint *indicator) -{ - gint indicator_size, indicator_spacing; - gint border_width; - - border_width = gtk_container_get_border_width (GTK_CONTAINER (button)); - - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &indicator_size, NULL); - indicator_spacing = indicator_size / 8; - - border->left = border_width; - border->right = border_width; - border->top = border_width; - border->bottom = border_width; - - if (button->iconic) - *indicator = 0; - else - *indicator = indicator_size + 2 * indicator_spacing; -} - static gboolean has_sibling_with_indicator (GtkWidget *button) { @@ -610,45 +603,18 @@ gtk_model_button_get_preferred_width_for_height (GtkWidget *widget, gint *minimum, gint *natural) { - GtkModelButton *button = GTK_MODEL_BUTTON (widget); - GtkWidget *child; - GtkBorder border; - gint indicator; - + GtkCssGadget *gadget; - gtk_model_button_get_full_border (button, &border, &indicator); - - child = gtk_bin_get_child (GTK_BIN (widget)); - if (child && gtk_widget_get_visible (child)) - { - if (height > -1) - height -= border.top + border.bottom; - - _gtk_widget_get_preferred_size_for_size (child, - GTK_ORIENTATION_HORIZONTAL, - height, - minimum, natural, - NULL, NULL); - } + if (GTK_MODEL_BUTTON (widget)->iconic) + gadget = GTK_BUTTON (widget)->priv->gadget; else - { - *minimum = 0; - *natural = 0; - } - - *minimum += border.left + border.right; - *natural += border.left + border.right; + gadget = GTK_MODEL_BUTTON (widget)->gadget; - if (button->centered) - { - *minimum += 2 * indicator; - *natural += 2 * indicator; - } - else if (needs_indicator (button)) - { - *minimum += indicator; - *natural += indicator; - } + gtk_css_gadget_get_preferred_size (gadget, + GTK_ORIENTATION_HORIZONTAL, + height, + minimum, natural, + NULL, NULL); } static void @@ -656,7 +622,18 @@ gtk_model_button_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural) { - gtk_model_button_get_preferred_width_for_height (widget, -1, minimum, natural); + GtkCssGadget *gadget; + + if (GTK_MODEL_BUTTON (widget)->iconic) + gadget = GTK_BUTTON (widget)->priv->gadget; + else + gadget = GTK_MODEL_BUTTON (widget)->gadget; + + gtk_css_gadget_get_preferred_size (gadget, + GTK_ORIENTATION_HORIZONTAL, + -1, + minimum, natural, + NULL, NULL); } static void @@ -667,135 +644,291 @@ gtk_model_button_get_preferred_height_and_baseline_for_width (GtkWidget *widget, gint *minimum_baseline, gint *natural_baseline) { - GtkModelButton *button = GTK_MODEL_BUTTON (widget); - GtkWidget *child; - GtkBorder border; - gint indicator; + GtkCssGadget *gadget; + + if (GTK_MODEL_BUTTON (widget)->iconic) + gadget = GTK_BUTTON (widget)->priv->gadget; + else + gadget = GTK_MODEL_BUTTON (widget)->gadget; + + gtk_css_gadget_get_preferred_size (gadget, + GTK_ORIENTATION_VERTICAL, + width, + minimum, natural, + minimum_baseline, natural_baseline); +} + +static void +gtk_model_button_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum, + gint *natural) +{ + GtkCssGadget *gadget; + + if (GTK_MODEL_BUTTON (widget)->iconic) + gadget = GTK_BUTTON (widget)->priv->gadget; + else + gadget = GTK_MODEL_BUTTON (widget)->gadget; + + gtk_css_gadget_get_preferred_size (gadget, + GTK_ORIENTATION_VERTICAL, + width, + minimum, natural, + NULL, NULL); +} + +static void +gtk_model_button_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + GtkCssGadget *gadget; - gtk_model_button_get_full_border (button, &border, &indicator); + if (GTK_MODEL_BUTTON (widget)->iconic) + gadget = GTK_BUTTON (widget)->priv->gadget; + else + gadget = GTK_MODEL_BUTTON (widget)->gadget; + + gtk_css_gadget_get_preferred_size (gadget, + GTK_ORIENTATION_VERTICAL, + -1, + minimum, natural, + NULL, NULL); +} + +static void +gtk_model_button_measure_indicator (GtkCssGadget *gadget, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline, + gpointer data) +{ + gint indicator_size; + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &indicator_size, NULL); + + *minimum = *natural = indicator_size; +} + +static void +gtk_model_button_measure (GtkCssGadget *gadget, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline, + gpointer data) +{ + GtkWidget *widget; + GtkModelButton *button; + GtkWidget *child; + + widget = gtk_css_gadget_get_owner (gadget); + button = GTK_MODEL_BUTTON (widget); child = gtk_bin_get_child (GTK_BIN (widget)); - if (child && gtk_widget_get_visible (child)) + + if (orientation == GTK_ORIENTATION_HORIZONTAL) { - gint child_min, child_nat; - gint child_min_baseline = -1, child_nat_baseline = -1; + gint check_min, check_nat; + + gtk_css_gadget_get_preferred_size (button->indicator_gadget, + GTK_ORIENTATION_HORIZONTAL, + -1, + &check_min, &check_nat, + NULL, NULL); - if (width > -1) + if (child && gtk_widget_get_visible (child)) { - width -= border.left + border.right; - if (button->centered) - width -= 2 * indicator; - else if (needs_indicator (button)) - width -= indicator; + _gtk_widget_get_preferred_size_for_size (child, + GTK_ORIENTATION_HORIZONTAL, + for_size, + minimum, natural, + minimum_baseline, natural_baseline); + } + else + { + *minimum = 0; + *natural = 0; } - - gtk_widget_get_preferred_height_and_baseline_for_width (child, width, - &child_min, &child_nat, - &child_min_baseline, &child_nat_baseline); if (button->centered) { - *minimum = MAX (2 * indicator, child_min); - *natural = MAX (2 * indicator, child_nat); + *minimum += 2 * check_min; + *natural += 2 * check_nat; } else if (needs_indicator (button)) { - *minimum = MAX (indicator, child_min); - *natural = MAX (indicator, child_nat); - } - else - { - *minimum = child_min; - *natural = child_nat; + *minimum += check_min; + *natural += check_nat; } - - if (minimum_baseline && child_min_baseline >= 0) - *minimum_baseline = child_min_baseline + border.top + (*minimum - child_min) / 2; - if (natural_baseline && child_nat_baseline >= 0) - *natural_baseline = child_nat_baseline + border.top + (*natural - child_nat) / 2; } else { - if (button->centered) - { - *minimum = 2 * indicator; - *natural = 2 * indicator; - } - else if (needs_indicator (button)) + gint check_min, check_nat; + + gtk_css_gadget_get_preferred_size (button->indicator_gadget, + GTK_ORIENTATION_VERTICAL, + -1, + &check_min, &check_nat, + NULL, NULL); + + if (child && gtk_widget_get_visible (child)) { - *minimum = indicator; - *natural = indicator; + gint child_min, child_nat; + gint child_min_baseline = -1, child_nat_baseline = -1; + + if (for_size > -1) + { + if (button->centered) + for_size -= 2 * check_nat; + else if (needs_indicator (button)) + for_size -= check_nat; + } + + gtk_widget_get_preferred_height_and_baseline_for_width (child, for_size, + &child_min, &child_nat, + &child_min_baseline, &child_nat_baseline); + + if (button->centered) + { + *minimum = MAX (2 * check_min, child_min); + *natural = MAX (2 * check_nat, child_nat); + } + else if (needs_indicator (button)) + { + *minimum = MAX (check_min, child_min); + *natural = MAX (check_nat, child_nat); + } + else + { + *minimum = child_min; + *natural = child_nat; + } + + if (minimum_baseline && child_min_baseline >= 0) + *minimum_baseline = child_min_baseline + (*minimum - child_min) / 2; + if (natural_baseline && child_nat_baseline >= 0) + *natural_baseline = child_nat_baseline + (*natural - child_nat) / 2; } else { - *minimum = 0; - *natural = 0; + if (button->centered) + { + *minimum = 2 * check_min; + *natural = 2 * check_nat; + } + else if (needs_indicator (button)) + { + *minimum = check_min; + *natural = check_nat; + } + else + { + *minimum = 0; + *natural = 0; + } } } - - *minimum += border.top + border.bottom; - *natural += border.top + border.bottom; } static void -gtk_model_button_get_preferred_height_for_width (GtkWidget *widget, - gint width, - gint *minimum, - gint *natural) +gtk_model_button_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { - gtk_model_button_get_preferred_height_and_baseline_for_width (widget, width, - minimum, natural, - NULL, NULL); -} + GtkCssGadget *gadget; + GdkRectangle clip; -static void -gtk_model_button_get_preferred_height (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - gtk_model_button_get_preferred_height_and_baseline_for_width (widget, -1, - minimum, natural, - NULL, NULL); + if (GTK_MODEL_BUTTON (widget)->iconic) + gadget = GTK_BUTTON (widget)->priv->gadget; + else + gadget = GTK_MODEL_BUTTON (widget)->gadget; + + 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); + + gtk_css_gadget_allocate (gadget, + allocation, + gtk_widget_get_allocated_baseline (widget), + &clip); + + gtk_widget_set_clip (widget, &clip); } static void -gtk_model_button_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +gtk_model_button_allocate (GtkCssGadget *gadget, + const GtkAllocation *allocation, + int baseline, + GtkAllocation *out_clip, + gpointer unused) { - GtkModelButton *button = GTK_MODEL_BUTTON (widget); + GtkWidget *widget; + GtkModelButton *button; PangoContext *pango_context; PangoFontMetrics *metrics; GtkAllocation child_allocation; - gint baseline; GtkWidget *child; + gint spacing; + gint check_min_width, check_nat_width; + gint check_min_height, check_nat_height; + GdkRectangle check_clip; - gtk_widget_set_allocation (widget, allocation); + widget = gtk_css_gadget_get_owner (gadget); + button = GTK_MODEL_BUTTON (widget); + child = gtk_bin_get_child (GTK_BIN (widget)); - 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)); + spacing = 0; + + gtk_css_gadget_get_preferred_size (button->indicator_gadget, + GTK_ORIENTATION_HORIZONTAL, + -1, + &check_min_width, &check_nat_width, + NULL, NULL); + gtk_css_gadget_get_preferred_size (button->indicator_gadget, + GTK_ORIENTATION_VERTICAL, + -1, + &check_min_height, &check_nat_height, + NULL, NULL); + + if (indicator_is_left (widget)) + child_allocation.x = allocation->x + spacing; + else + child_allocation.x = allocation->x + allocation->width - check_nat_width - spacing; + child_allocation.y = allocation->y + (allocation->height - check_nat_height) / 2; + child_allocation.width = check_nat_width; + child_allocation.height = check_nat_height; + + gtk_css_gadget_allocate (button->indicator_gadget, + &child_allocation, + baseline, + &check_clip); + if (child && gtk_widget_get_visible (child)) { - GtkBorder border; - gint indicator; - - gtk_model_button_get_full_border (button, &border, &indicator); + GtkBorder border = { 0, }; if (button->centered) { - border.left += indicator; - border.right += indicator; + border.left = check_nat_width; + border.right = check_nat_width; } else if (needs_indicator (button)) { if (indicator_is_left (widget)) - border.left += indicator; + border.left += check_nat_width; else - border.right += indicator; + border.right += check_nat_width; } + child_allocation.x = allocation->x + border.left; child_allocation.y = allocation->y + border.top; child_allocation.width = allocation->width - border.left - border.right; @@ -804,6 +937,7 @@ gtk_model_button_size_allocate (GtkWidget *widget, baseline = gtk_widget_get_allocated_baseline (widget); if (baseline != -1) baseline -= border.top; + gtk_widget_size_allocate_with_baseline (child, &child_allocation, baseline); } @@ -815,91 +949,92 @@ gtk_model_button_size_allocate (GtkWidget *widget, (double)pango_font_metrics_get_ascent (metrics) / (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics)); pango_font_metrics_unref (metrics); + + gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip); + gdk_rectangle_union (out_clip, &check_clip, out_clip); } static gint gtk_model_button_draw (GtkWidget *widget, cairo_t *cr) { - GtkModelButton *model_button = GTK_MODEL_BUTTON (widget); - GtkButton *button = GTK_BUTTON (widget); - GtkWidget *child; - GtkStyleContext *context; - gint border_width; - gint x, y; - gint width, height; - gint indicator_size, indicator_spacing; - gint baseline; + GtkCssGadget *gadget; - if (model_button->iconic) - return GTK_WIDGET_CLASS (gtk_model_button_parent_class)->draw (widget, cr); + if (GTK_MODEL_BUTTON (widget)->iconic) + gadget = GTK_BUTTON (widget)->priv->gadget; + else + gadget = GTK_MODEL_BUTTON (widget)->gadget; - context = gtk_widget_get_style_context (widget); - width = gtk_widget_get_allocated_width (widget); - height = gtk_widget_get_allocated_height (widget); - border_width = gtk_container_get_border_width (GTK_CONTAINER (widget)); - baseline = gtk_widget_get_allocated_baseline (widget); + gtk_css_gadget_draw (gadget, cr); - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &indicator_size, NULL); - indicator_spacing = indicator_size / 8; + return FALSE; +} + +static gboolean +gtk_model_button_render_indicator (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer data) +{ + GtkWidget *widget; + GtkModelButton *button; + GtkCssNode *indicator_node; + GtkStyleContext *context; - x = width - border_width - indicator_spacing - indicator_size; + widget = gtk_css_gadget_get_owner (gadget); + button = GTK_MODEL_BUTTON (widget); + context = gtk_widget_get_style_context (widget); - if (indicator_is_left (widget)) - x = width - (indicator_size + x); + indicator_node = gtk_css_gadget_get_node (button->indicator_gadget); - if (baseline == -1) - y = (height - indicator_size) / 2; - else - y = CLAMP (baseline - indicator_size * button->priv->baseline_align, - 0, height - indicator_size); - - gtk_render_background (context, cr, - border_width, border_width, - width - 2 * border_width, - height - 2 * border_width); - gtk_render_frame (context, cr, - border_width, border_width, - width - 2 * border_width, - height - 2 * border_width); - - if (model_button->menu_name) + if (button->menu_name) { - gtk_style_context_save_to_node (context, model_button->indicator_node); - gtk_render_expander (context, cr, x, y, indicator_size, indicator_size); + gtk_style_context_save_to_node (context, indicator_node); + gtk_render_expander (context, cr, x, y, width, height); gtk_style_context_restore (context); } - else if (model_button->role == GTK_BUTTON_ROLE_CHECK) + else if (button->role == GTK_BUTTON_ROLE_CHECK) { - gtk_style_context_save_to_node (context, model_button->indicator_node); - gtk_render_check (context, cr, x, y, indicator_size, indicator_size); + gtk_style_context_save_to_node (context, indicator_node); + gtk_render_check (context, cr, x, y, width, height); gtk_style_context_restore (context); } - else if (model_button->role == GTK_BUTTON_ROLE_RADIO) + else if (button->role == GTK_BUTTON_ROLE_RADIO) { - gtk_style_context_save_to_node (context, model_button->indicator_node); - gtk_render_option (context, cr, x, y, indicator_size, indicator_size); + gtk_style_context_save_to_node (context, indicator_node); + gtk_render_option (context, cr, x, y, width, height); gtk_style_context_restore (context); } - if (gtk_widget_has_visible_focus (widget)) - { - GtkBorder border; - - gtk_style_context_get_border (context, gtk_style_context_get_state (context), &border); - - gtk_render_focus (context, cr, - border_width + border.left, - border_width + border.top, - width - 2 * border_width - border.left - border.right, - height - 2 * border_width - border.top - border.bottom); - } + return FALSE; +} + +static gboolean +gtk_model_button_render (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer data) +{ + GtkWidget *widget; + GtkModelButton *button; + GtkWidget *child; + + widget = gtk_css_gadget_get_owner (gadget); + button = GTK_MODEL_BUTTON (widget); + + gtk_css_gadget_draw (button->indicator_gadget, cr); child = gtk_bin_get_child (GTK_BIN (widget)); if (child) gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr); - return FALSE; + return gtk_widget_has_visible_focus (widget); } static void @@ -916,6 +1051,8 @@ static void gtk_model_button_clicked (GtkButton *button) { GtkModelButton *model_button = GTK_MODEL_BUTTON (button); + + g_print ("model button clicked\n"); if (model_button->menu_name != NULL) { GtkWidget *stack; @@ -935,12 +1072,24 @@ gtk_model_button_clicked (GtkButton *button) } static void +gtk_model_button_finalize (GObject *object) +{ + GtkModelButton *button = GTK_MODEL_BUTTON (object); + + g_clear_object (&button->indicator_gadget); + g_clear_object (&button->gadget); + + G_OBJECT_CLASS (gtk_model_button_parent_class)->finalize (object); +} + +static void gtk_model_button_class_init (GtkModelButtonClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); GtkButtonClass *button_class = GTK_BUTTON_CLASS (class); + object_class->finalize = gtk_model_button_finalize; object_class->get_property = gtk_model_button_get_property; object_class->set_property = gtk_model_button_set_property; @@ -1086,17 +1235,6 @@ gtk_model_button_class_init (GtkModelButtonClass *class) } static void -node_style_changed_cb (GtkCssNode *node, - GtkCssStyleChange *change, - GtkWidget *widget) -{ - if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_CLIP)) - gtk_widget_queue_resize (widget); - else - gtk_widget_queue_draw (widget); -} - -static void gtk_model_button_init (GtkModelButton *button) { GtkCssNode *widget_node; @@ -1119,13 +1257,23 @@ gtk_model_button_init (GtkModelButton *button) gtk_container_add (GTK_CONTAINER (button), button->box); widget_node = gtk_widget_get_css_node (GTK_WIDGET (button)); - button->indicator_node = gtk_css_node_new (); - gtk_css_node_set_name (button->indicator_node, I_("check")); - gtk_css_node_set_visible (button->indicator_node, FALSE); - gtk_css_node_set_parent (button->indicator_node, widget_node); - gtk_css_node_set_state (button->indicator_node, gtk_css_node_get_state (widget_node)); - g_signal_connect_object (button->indicator_node, "style-changed", G_CALLBACK (node_style_changed_cb), button, 0); - g_object_unref (button->indicator_node); + button->gadget = gtk_css_custom_gadget_new_for_node (widget_node, + GTK_WIDGET (button), + gtk_model_button_measure, + gtk_model_button_allocate, + gtk_model_button_render, + NULL, + NULL); + + button->indicator_gadget = gtk_css_custom_gadget_new ("check", + GTK_WIDGET (button), + button->gadget, + NULL, + gtk_model_button_measure_indicator, + NULL, + gtk_model_button_render_indicator, + NULL, + NULL); } /** |