#include #include #include #include #include #include #include #include "button-widget.h" #include "panel-widget.h" #include "panel-types.h" #include "panel-util.h" #include "panel-config-global.h" #include "panel-marshal.h" #include "panel-typebuiltins.h" #include "panel-globals.h" #include "panel-enums.h" #include "panel-enums-gsettings.h" #define BUTTON_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUTTON_TYPE_WIDGET, ButtonWidgetPrivate)) struct _ButtonWidgetPrivate { GtkIconTheme *icon_theme; GdkPixbuf *pixbuf; GdkPixbuf *pixbuf_hc; char *filename; PanelOrientation orientation; int size; guint activatable : 1; guint ignore_leave : 1; guint arrow : 1; guint dnd_highlight : 1; }; static void button_widget_icon_theme_changed (ButtonWidget *button); static void button_widget_reload_pixbuf (ButtonWidget *button); enum { PROP_0, PROP_ACTIVATABLE, PROP_IGNORE_LEAVE, PROP_HAS_ARROW, PROP_DND_HIGHLIGHT, PROP_ORIENTATION, PROP_ICON_NAME }; #define BUTTON_WIDGET_DISPLACEMENT 2 G_DEFINE_TYPE (ButtonWidget, button_widget, GTK_TYPE_BUTTON) /* colorshift a pixbuf */ static void do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift) { gint i, j; gint width, height, has_alpha, srcrowstride, destrowstride; guchar *target_pixels; guchar *original_pixels; guchar *pixsrc; guchar *pixdest; int val; guchar r,g,b; has_alpha = gdk_pixbuf_get_has_alpha (src); width = gdk_pixbuf_get_width (src); height = gdk_pixbuf_get_height (src); srcrowstride = gdk_pixbuf_get_rowstride (src); destrowstride = gdk_pixbuf_get_rowstride (dest); target_pixels = gdk_pixbuf_get_pixels (dest); original_pixels = gdk_pixbuf_get_pixels (src); for (i = 0; i < height; i++) { pixdest = target_pixels + i*destrowstride; pixsrc = original_pixels + i*srcrowstride; for (j = 0; j < width; j++) { r = *(pixsrc++); g = *(pixsrc++); b = *(pixsrc++); val = r + shift; *(pixdest++) = CLAMP(val, 0, 255); val = g + shift; *(pixdest++) = CLAMP(val, 0, 255); val = b + shift; *(pixdest++) = CLAMP(val, 0, 255); if (has_alpha) *(pixdest++) = *(pixsrc++); } } } static GdkPixbuf * make_hc_pixbuf (GdkPixbuf *pb) { GdkPixbuf *new; if (!pb) return NULL; new = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pb), gdk_pixbuf_get_has_alpha (pb), gdk_pixbuf_get_bits_per_sample (pb), gdk_pixbuf_get_width (pb), gdk_pixbuf_get_height (pb)); do_colorshift (new, pb, 30); return new; } static void button_widget_realize(GtkWidget *widget) { #if !GTK_CHECK_VERSION (3, 0, 0) GtkAllocation allocation; GdkWindowAttr attributes; gint attributes_mask; GtkButton *button; g_return_if_fail (widget != NULL); g_return_if_fail (BUTTON_IS_WIDGET (widget)); button = GTK_BUTTON (widget); gtk_widget_set_realized (widget, TRUE); gtk_widget_get_allocation (widget, &allocation); attributes.window_type = GDK_WINDOW_CHILD; attributes.x = allocation.x; attributes.y = allocation.y; attributes.width = allocation.width; attributes.height = allocation.height; attributes.wclass = GDK_INPUT_ONLY; attributes.event_mask = (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_KEY_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); attributes_mask = GDK_WA_X | GDK_WA_Y; gtk_widget_set_window (widget, gtk_widget_get_parent_window (widget)); g_object_ref (gtk_widget_get_window (widget)); button->event_window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (button->event_window, widget); widget->style = gtk_style_attach (widget->style, gtk_widget_get_window (widget)); #else gtk_widget_add_events (widget, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_KEY_PRESS_MASK); GTK_WIDGET_CLASS (button_widget_parent_class)->realize (widget); #endif BUTTON_WIDGET (widget)->priv->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget)); g_signal_connect_object (BUTTON_WIDGET (widget)->priv->icon_theme, "changed", G_CALLBACK (button_widget_icon_theme_changed), #if GTK_CHECK_VERSION (3, 0, 0) widget, #else button, #endif G_CONNECT_SWAPPED); button_widget_reload_pixbuf (BUTTON_WIDGET (widget)); } static void button_widget_unrealize (GtkWidget *widget) { #if GTK_CHECK_VERSION (3, 0, 0) g_signal_handlers_disconnect_by_func (BUTTON_WIDGET (widget)->priv->icon_theme, G_CALLBACK (button_widget_icon_theme_changed), widget); #else GtkButton *button; g_return_if_fail (widget != NULL); g_return_if_fail (BUTTON_IS_WIDGET (widget)); button = GTK_BUTTON (widget); if (button->event_window != NULL) { gdk_window_set_user_data (button->event_window, NULL); gdk_window_destroy (button->event_window); button->event_window = NULL; } #endif GTK_WIDGET_CLASS (button_widget_parent_class)->unrealize (widget); } static void button_widget_unset_pixbufs (ButtonWidget *button) { if (button->priv->pixbuf) g_object_unref (button->priv->pixbuf); button->priv->pixbuf = NULL; if (button->priv->pixbuf_hc) g_object_unref (button->priv->pixbuf_hc); button->priv->pixbuf_hc = NULL; } static void button_widget_reload_pixbuf (ButtonWidget *button) { button_widget_unset_pixbufs (button); if (button->priv->size <= 1 || button->priv->icon_theme == NULL) return; if (button->priv->filename != NULL && button->priv->filename [0] != '\0') { char *error = NULL; button->priv->pixbuf = panel_load_icon (button->priv->icon_theme, button->priv->filename, button->priv->size, button->priv->orientation & PANEL_VERTICAL_MASK ? button->priv->size : -1, button->priv->orientation & PANEL_HORIZONTAL_MASK ? button->priv->size : -1, &error); if (error) { //FIXME: this is not rendered at button->priv->size button->priv->pixbuf = gtk_widget_render_icon (GTK_WIDGET (button), GTK_STOCK_MISSING_IMAGE, (GtkIconSize) -1, NULL); g_free (error); } } button->priv->pixbuf_hc = make_hc_pixbuf (button->priv->pixbuf); gtk_widget_queue_resize (GTK_WIDGET (button)); } static void button_widget_icon_theme_changed (ButtonWidget *button) { if (button->priv->filename != NULL) button_widget_reload_pixbuf (button); } static void button_widget_finalize (GObject *object) { ButtonWidget *button = (ButtonWidget *) object; button_widget_unset_pixbufs (button); g_free (button->priv->filename); button->priv->filename = NULL; G_OBJECT_CLASS (button_widget_parent_class)->finalize (object); } static void button_widget_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { ButtonWidget *button; g_return_if_fail (BUTTON_IS_WIDGET (object)); button = BUTTON_WIDGET (object); switch (prop_id) { case PROP_ACTIVATABLE: g_value_set_boolean (value, button->priv->activatable); break; case PROP_IGNORE_LEAVE: g_value_set_boolean (value, button->priv->ignore_leave); break; case PROP_HAS_ARROW: g_value_set_boolean (value, button->priv->arrow); break; case PROP_DND_HIGHLIGHT: g_value_set_boolean (value, button->priv->dnd_highlight); break; case PROP_ORIENTATION: g_value_set_enum (value, button->priv->orientation); break; case PROP_ICON_NAME: g_value_set_string (value, button->priv->filename); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void button_widget_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { ButtonWidget *button; g_return_if_fail (BUTTON_IS_WIDGET (object)); button = BUTTON_WIDGET (object); switch (prop_id) { case PROP_ACTIVATABLE: button_widget_set_activatable (button, g_value_get_boolean (value)); break; case PROP_IGNORE_LEAVE: button_widget_set_ignore_leave (button, g_value_get_boolean (value)); break; case PROP_HAS_ARROW: button_widget_set_has_arrow (button, g_value_get_boolean (value)); break; case PROP_DND_HIGHLIGHT: button_widget_set_dnd_highlight (button, g_value_get_boolean (value)); break; case PROP_ORIENTATION: button_widget_set_orientation (button, g_value_get_enum (value)); break; case PROP_ICON_NAME: button_widget_set_icon_name (button, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GtkArrowType calc_arrow (PanelOrientation orientation, int button_width, int button_height, int *x, int *y, int *width, int *height) { GtkArrowType retval = GTK_ARROW_UP; double scale; scale = (orientation & PANEL_HORIZONTAL_MASK ? button_height : button_width) / 48.0; *width = 12 * scale; *height = 12 * scale; switch (orientation) { case PANEL_ORIENTATION_TOP: *x = scale * 3; *y = scale * (48 - 13); retval = GTK_ARROW_DOWN; break; case PANEL_ORIENTATION_BOTTOM: *x = scale * (48 - 13); *y = scale * 1; retval = GTK_ARROW_UP; break; case PANEL_ORIENTATION_LEFT: *x = scale * (48 - 13); *y = scale * 3; retval = GTK_ARROW_RIGHT; break; case PANEL_ORIENTATION_RIGHT: *x = scale * 1; *y = scale * 3; retval = GTK_ARROW_LEFT; break; } return retval; } static gboolean #if GTK_CHECK_VERSION (3, 0, 0) button_widget_draw (GtkWidget *widget, cairo_t *cr) #else button_widget_expose (GtkWidget *widget, GdkEventExpose *event) #endif { ButtonWidget *button_widget; GtkButton *button; GdkWindow *window; int width; int height; #if GTK_CHECK_VERSION (3, 0, 0) GtkStateFlags state_flags; #else GtkAllocation allocation; #endif GdkRectangle area, image_bound; GtkStyle *style; int off; int x, y, w, h; GdkPixbuf *pb = NULL; g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE); #if !GTK_CHECK_VERSION (3, 0, 0) g_return_val_if_fail (event != NULL, FALSE); if (!gtk_widget_get_visible (widget) || !gtk_widget_get_mapped (widget)) return FALSE; #endif button_widget = BUTTON_WIDGET (widget); if (!button_widget->priv->pixbuf_hc && !button_widget->priv->pixbuf) return FALSE; button = GTK_BUTTON (widget); window = gtk_widget_get_window (widget); #if GTK_CHECK_VERSION (3, 0, 0) state_flags = gtk_widget_get_state_flags (widget); width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); #else gtk_widget_get_allocation (widget, &allocation); #endif /* offset for pressed buttons */ off = (button_widget->priv->activatable && #if GTK_CHECK_VERSION (3, 0, 0) (state_flags & GTK_STATE_FLAG_PRELIGHT) && (state_flags & GTK_STATE_FLAG_ACTIVE)) ? BUTTON_WIDGET_DISPLACEMENT * height / 48.0 : 0; #else button->in_button && button->button_down) ? BUTTON_WIDGET_DISPLACEMENT * allocation.height / 48.0 : 0; #endif if (!button_widget->priv->activatable) { pb = gdk_pixbuf_copy (button_widget->priv->pixbuf); gdk_pixbuf_saturate_and_pixelate (button_widget->priv->pixbuf, pb, 0.8, TRUE); } else if (panel_global_config_get_highlight_when_over () && #if GTK_CHECK_VERSION (3, 0, 0) (state_flags & GTK_STATE_FLAG_PRELIGHT || gtk_widget_has_focus (widget))) #else (button->in_button || gtk_widget_has_focus (widget))) #endif pb = g_object_ref (button_widget->priv->pixbuf_hc); else pb = g_object_ref (button_widget->priv->pixbuf); g_assert (pb != NULL); w = gdk_pixbuf_get_width (pb); h = gdk_pixbuf_get_height (pb); #if GTK_CHECK_VERSION (3, 0, 0) x = off + (width - w)/2; y = off + (height - h)/2; #else x = allocation.x + off + (allocation.width - w)/2; y = allocation.y + off + (allocation.height - h)/2; image_bound.x = x; image_bound.y = y; image_bound.width = w; image_bound.height = h; area = event->area; #endif #if GTK_CHECK_VERSION (3, 0, 0) cairo_save (cr); gdk_cairo_set_source_pixbuf (cr, pb, x, y); cairo_paint (cr); cairo_restore (cr); #else if (gdk_rectangle_intersect (&area, &allocation, &area) && gdk_rectangle_intersect (&image_bound, &area, &image_bound)) gdk_draw_pixbuf (window, NULL, pb, image_bound.x - x, image_bound.y - y, image_bound.x, image_bound.y, image_bound.width, image_bound.height, GDK_RGB_DITHER_NORMAL, 0, 0); #endif g_object_unref (pb); style = gtk_widget_get_style (widget); if (button_widget->priv->arrow) { GtkArrowType arrow_type; arrow_type = calc_arrow (button_widget->priv->orientation, #if GTK_CHECK_VERSION (3, 0, 0) width, height, &x, &y, &w, &h); #else allocation.width, allocation.height, &x, &y, &width, &height); #endif gtk_paint_arrow (style, #if GTK_CHECK_VERSION (3, 0, 0) cr, #else window, #endif GTK_STATE_NORMAL, GTK_SHADOW_NONE, #if !GTK_CHECK_VERSION (3, 0, 0) NULL, #endif widget, "panel-button", arrow_type, TRUE, #if GTK_CHECK_VERSION (3, 0, 0) x, y, w, h); #else allocation.x + x, allocation.y + y, width, height); #endif } if (button_widget->priv->dnd_highlight) { #if GTK_CHECK_VERSION (3, 0, 0) cairo_save (cr); cairo_set_line_width (cr, 1); gdk_cairo_set_source_color (cr, &style->black); cairo_rectangle (cr, 0.5, 0.5, width - 1, height - 1); cairo_stroke (cr); cairo_restore (cr); #else gdk_draw_rectangle(window, style->black_gc, FALSE, allocation.x, allocation.y, allocation.width - 1, allocation.height - 1); #endif } if (gtk_widget_has_focus (widget)) { gint focus_width, focus_pad; gtk_widget_style_get (widget, "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL); #if GTK_CHECK_VERSION (3, 0, 0) x = focus_pad; y = focus_pad; w= width - 2 * focus_pad; h= height - 2 * focus_pad; #else x = allocation.x + focus_pad; y = allocation.y + focus_pad; width = allocation.width - 2 * focus_pad; height = allocation.height - 2 * focus_pad; #endif gtk_paint_focus (style, #if GTK_CHECK_VERSION (3, 0, 0) cr, #else window, #endif GTK_STATE_NORMAL, #if GTK_CHECK_VERSION (3, 0, 0) widget, "button", x, y, w, h); #else &event->area, widget, "button", x, y, width, height); #endif } return FALSE; } static void button_widget_size_request (GtkWidget *widget, GtkRequisition *requisition) { ButtonWidget *button_widget = BUTTON_WIDGET (widget); if (button_widget->priv->pixbuf) { requisition->width = gdk_pixbuf_get_width (button_widget->priv->pixbuf); requisition->height = gdk_pixbuf_get_height (button_widget->priv->pixbuf); } } #if GTK_CHECK_VERSION (3, 0, 0) static void button_widget_get_preferred_width (GtkWidget *widget, gint *minimum_width, gint *natural_width) { GtkRequisition req; button_widget_size_request (widget, &req); *minimum_width = *natural_width = req.width; } static void button_widget_get_preferred_height (GtkWidget *widget, gint *minimum_height, gint *natural_height) { GtkRequisition req; button_widget_size_request (widget, &req); *minimum_height = *natural_height = req.height; } #endif static void button_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { ButtonWidget *button_widget = BUTTON_WIDGET (widget); GtkButton *button = GTK_BUTTON (widget); int size; #if GTK_CHECK_VERSION (3, 0, 0) GTK_WIDGET_CLASS (button_widget_parent_class)->size_allocate (widget, allocation); #endif if (button_widget->priv->orientation & PANEL_HORIZONTAL_MASK) size = allocation->height; else size = allocation->width; if (size < 22) size = 16; else if (size < 24) size = 22; else if (size < 32) size = 24; else if (size < 48) size = 32; else size = 48; if (button_widget->priv->size != size) { button_widget->priv->size = size; button_widget_reload_pixbuf (button_widget); } #if !GTK_CHECK_VERSION (3, 0, 0) gtk_widget_set_allocation (widget, allocation); if (gtk_widget_get_realized (widget)) { gdk_window_move_resize (button->event_window, allocation->x, allocation->y, allocation->width, allocation->height); } #endif } static void button_widget_activate (GtkButton *button) { ButtonWidget *button_widget = BUTTON_WIDGET (button); if (!button_widget->priv->activatable) return; if (GTK_BUTTON_CLASS (button_widget_parent_class)->activate) GTK_BUTTON_CLASS (button_widget_parent_class)->activate (button); } static gboolean button_widget_button_press (GtkWidget *widget, GdkEventButton *event) { g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (event->button == 1 && BUTTON_WIDGET (widget)->priv->activatable && /* we don't want to have two/three "click" events for double/triple * clicks. FIXME: this is only a workaround, waiting for bug 159101 */ event->type == GDK_BUTTON_PRESS) return GTK_WIDGET_CLASS (button_widget_parent_class)->button_press_event (widget, event); return FALSE; } static gboolean button_widget_enter_notify (GtkWidget *widget, GdkEventCrossing *event) { gboolean in_button; g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE); #if GTK_CHECK_VERSION (3, 0, 0) GtkStateFlags state_flags; in_button = state_flags & GTK_STATE_FLAG_PRELIGHT; #else in_button = GTK_BUTTON (widget)->in_button; #endif GTK_WIDGET_CLASS (button_widget_parent_class)->enter_notify_event (widget, event); #if GTK_CHECK_VERSION (3, 0, 0) state_flags = gtk_widget_get_state_flags (widget); if (in_button != (state_flags & GTK_STATE_FLAG_PRELIGHT) && #else if (in_button != GTK_BUTTON (widget)->in_button && #endif panel_global_config_get_highlight_when_over ()) gtk_widget_queue_draw (widget); return FALSE; } static gboolean button_widget_leave_notify (GtkWidget *widget, GdkEventCrossing *event) { gboolean in_button; g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE); #if GTK_CHECK_VERSION (3, 0, 0) GtkStateFlags state_flags; in_button = state_flags & GTK_STATE_FLAG_PRELIGHT; #else in_button = GTK_BUTTON (widget)->in_button; #endif GTK_WIDGET_CLASS (button_widget_parent_class)->leave_notify_event (widget, event); #if GTK_CHECK_VERSION (3, 0, 0) state_flags = gtk_widget_get_state_flags (widget); if (in_button != (state_flags & GTK_STATE_FLAG_PRELIGHT) && #else if (in_button != GTK_BUTTON (widget)->in_button && #endif panel_global_config_get_highlight_when_over ()) gtk_widget_queue_draw (widget); return FALSE; } static void button_widget_init (ButtonWidget *button) { button->priv = BUTTON_WIDGET_GET_PRIVATE (button); button->priv->icon_theme = NULL; button->priv->pixbuf = NULL; button->priv->pixbuf_hc = NULL; button->priv->filename = NULL; button->priv->orientation = PANEL_ORIENTATION_TOP; button->priv->size = 0; button->priv->activatable = FALSE; button->priv->ignore_leave = FALSE; button->priv->arrow = FALSE; button->priv->dnd_highlight = FALSE; } static void button_widget_class_init (ButtonWidgetClass *klass) { GObjectClass *gobject_class = (GObjectClass *) klass; GtkWidgetClass *widget_class = (GtkWidgetClass *) klass; GtkButtonClass *button_class = (GtkButtonClass *) klass; gobject_class->finalize = button_widget_finalize; gobject_class->get_property = button_widget_get_property; gobject_class->set_property = button_widget_set_property; g_type_class_add_private (klass, sizeof (ButtonWidgetPrivate)); widget_class->realize = button_widget_realize; widget_class->unrealize = button_widget_unrealize; widget_class->size_allocate = button_widget_size_allocate; #if GTK_CHECK_VERSION (3, 0, 0) widget_class->get_preferred_width = button_widget_get_preferred_width; widget_class->get_preferred_height = button_widget_get_preferred_height; #else widget_class->size_request = button_widget_size_request; #endif widget_class->button_press_event = button_widget_button_press; widget_class->enter_notify_event = button_widget_enter_notify; widget_class->leave_notify_event = button_widget_leave_notify; #if GTK_CHECK_VERSION (3, 0, 0) widget_class->draw = button_widget_draw; #else widget_class->expose_event = button_widget_expose; #endif button_class->activate = button_widget_activate; g_object_class_install_property ( gobject_class, PROP_ACTIVATABLE, g_param_spec_boolean ("activatable", "Activatable", "Whether the button is activatable", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property ( gobject_class, PROP_IGNORE_LEAVE, g_param_spec_boolean ("ignore-leave", "Ignore leaving to not unhighlight the icon", "Whether or not to unhighlight the icon when the cursor leaves it", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( gobject_class, PROP_HAS_ARROW, g_param_spec_boolean ("has-arrow", "Has Arrow", "Whether or not to draw an arrow indicator", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( gobject_class, PROP_DND_HIGHLIGHT, g_param_spec_boolean ("dnd-highlight", "Drag and drop Highlight", "Whether or not to highlight the icon during drag and drop", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( gobject_class, PROP_ORIENTATION, g_param_spec_enum ("orientation", "Orientation", "The ButtonWidget orientation", PANEL_TYPE_ORIENTATION, PANEL_ORIENTATION_TOP, G_PARAM_READWRITE)); g_object_class_install_property ( gobject_class, PROP_ICON_NAME, g_param_spec_string ("icon-name", "Icon Name", "The desired icon for the ButtonWidget", NULL, G_PARAM_READWRITE)); } GtkWidget * button_widget_new (const char *filename, gboolean arrow, PanelOrientation orientation) { GtkWidget *retval; retval = g_object_new ( BUTTON_TYPE_WIDGET, "has-arrow", arrow, "orientation", orientation, "icon-name", filename, NULL); return retval; } void button_widget_set_activatable (ButtonWidget *button, gboolean activatable) { g_return_if_fail (BUTTON_IS_WIDGET (button)); activatable = activatable != FALSE; if (button->priv->activatable != activatable) { button->priv->activatable = activatable; if (gtk_widget_is_drawable (GTK_WIDGET (button))) gtk_widget_queue_draw (GTK_WIDGET (button)); g_object_notify (G_OBJECT (button), "activatable"); } } gboolean button_widget_get_activatable (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), FALSE); return button->priv->activatable; } void button_widget_set_icon_name (ButtonWidget *button, const char *icon_name) { g_return_if_fail (BUTTON_IS_WIDGET (button)); if (button->priv->filename && icon_name && !strcmp (button->priv->filename, icon_name)) return; if (button->priv->filename) g_free (button->priv->filename); button->priv->filename = g_strdup (icon_name); button_widget_reload_pixbuf (button); g_object_notify (G_OBJECT (button), "icon-name"); } const char * button_widget_get_icon_name (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), NULL); return button->priv->filename; } void button_widget_set_orientation (ButtonWidget *button, PanelOrientation orientation) { g_return_if_fail (BUTTON_IS_WIDGET (button)); if (button->priv->orientation == orientation) return; button->priv->orientation = orientation; /* Force a re-scale */ button->priv->size = -1; gtk_widget_queue_resize (GTK_WIDGET (button)); g_object_notify (G_OBJECT (button), "orientation"); } PanelOrientation button_widget_get_orientation (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), 0); return button->priv->orientation; } void button_widget_set_has_arrow (ButtonWidget *button, gboolean has_arrow) { g_return_if_fail (BUTTON_IS_WIDGET (button)); has_arrow = has_arrow != FALSE; if (button->priv->arrow == has_arrow) return; button->priv->arrow = has_arrow; gtk_widget_queue_draw (GTK_WIDGET (button)); g_object_notify (G_OBJECT (button), "has-arrow"); } gboolean button_widget_get_has_arrow (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), FALSE); return button->priv->arrow; } void button_widget_set_dnd_highlight (ButtonWidget *button, gboolean dnd_highlight) { g_return_if_fail (BUTTON_IS_WIDGET (button)); dnd_highlight = dnd_highlight != FALSE; if (button->priv->dnd_highlight == dnd_highlight) return; button->priv->dnd_highlight = dnd_highlight; gtk_widget_queue_draw (GTK_WIDGET (button)); g_object_notify (G_OBJECT (button), "dnd-highlight"); } gboolean button_widget_get_dnd_highlight (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), FALSE); return button->priv->dnd_highlight; } void button_widget_set_ignore_leave (ButtonWidget *button, gboolean ignore_leave) { g_return_if_fail (BUTTON_IS_WIDGET (button)); ignore_leave = ignore_leave != FALSE; if (button->priv->ignore_leave == ignore_leave) return; button->priv->ignore_leave = ignore_leave; gtk_widget_queue_draw (GTK_WIDGET (button)); g_object_notify (G_OBJECT (button), "ignore-leave"); } gboolean button_widget_get_ignore_leave (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), FALSE); return button->priv->ignore_leave; } GtkIconTheme * button_widget_get_icon_theme (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), NULL); return button->priv->icon_theme; } GdkPixbuf * button_widget_get_pixbuf (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), NULL); if (!button->priv->pixbuf) return NULL; return g_object_ref (button->priv->pixbuf); }