summaryrefslogtreecommitdiff
path: root/mate-panel/button-widget.c
diff options
context:
space:
mode:
Diffstat (limited to 'mate-panel/button-widget.c')
-rw-r--r--mate-panel/button-widget.c902
1 files changed, 902 insertions, 0 deletions
diff --git a/mate-panel/button-widget.c b/mate-panel/button-widget.c
new file mode 100644
index 00000000..6f2fd6b8
--- /dev/null
+++ b/mate-panel/button-widget.c
@@ -0,0 +1,902 @@
+#include <config.h>
+#include <math.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#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"
+
+#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)
+{
+ 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));
+
+ 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),
+ button,
+ G_CONNECT_SWAPPED);
+
+ button_widget_reload_pixbuf (BUTTON_WIDGET (widget));
+}
+
+static void
+button_widget_unrealize (GtkWidget *widget)
+{
+ 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;
+ }
+
+ 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
+button_widget_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ ButtonWidget *button_widget;
+ GtkButton *button;
+ GdkWindow *window;
+ GtkAllocation allocation;
+ 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);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (!gtk_widget_get_visible (widget) || !gtk_widget_get_mapped (widget))
+ return FALSE;
+
+ 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);
+ gtk_widget_get_allocation (widget, &allocation);
+
+ /* offset for pressed buttons */
+ off = (button_widget->priv->activatable &&
+ button->in_button && button->button_down) ?
+ BUTTON_WIDGET_DISPLACEMENT * allocation.height / 48.0 : 0;
+
+ 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 () &&
+ (button->in_button || gtk_widget_has_focus (widget)))
+ 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);
+ 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;
+
+ 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);
+
+ g_object_unref (pb);
+
+ style = gtk_widget_get_style (widget);
+
+ if (button_widget->priv->arrow) {
+ GtkArrowType arrow_type;
+ int x, y, width, height;
+
+ x = y = width = height = -1;
+
+ arrow_type = calc_arrow (button_widget->priv->orientation,
+ allocation.width,
+ allocation.height,
+ &x,
+ &y,
+ &width,
+ &height);
+
+ gtk_paint_arrow (style,
+ window,
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE,
+ NULL,
+ widget,
+ "panel-button",
+ arrow_type,
+ TRUE,
+ allocation.x + x,
+ allocation.y + y,
+ width,
+ height);
+ }
+
+ if (button_widget->priv->dnd_highlight) {
+ gdk_draw_rectangle(window, style->black_gc, FALSE,
+ allocation.x, allocation.y,
+ allocation.width - 1,
+ allocation.height - 1);
+ }
+
+ if (gtk_widget_has_focus (widget)) {
+ gint focus_width, focus_pad;
+ gint x, y, width, height;
+
+ gtk_widget_style_get (widget,
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ NULL);
+ x = allocation.x + focus_pad;
+ y = allocation.y + focus_pad;
+ width = allocation.width - 2 * focus_pad;
+ height = allocation.height - 2 * focus_pad;
+ gtk_paint_focus (style, window,
+ GTK_STATE_NORMAL,
+ &event->area, widget, "button",
+ x, y, width, height);
+ }
+
+ 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);
+ }
+}
+
+static void
+button_widget_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ ButtonWidget *button_widget = BUTTON_WIDGET (widget);
+ GtkButton *button = GTK_BUTTON (widget);
+ int size;
+
+ 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);
+ }
+
+ 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);
+ }
+}
+
+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);
+
+ in_button = GTK_BUTTON (widget)->in_button;
+ GTK_WIDGET_CLASS (button_widget_parent_class)->enter_notify_event (widget, event);
+ if (in_button != GTK_BUTTON (widget)->in_button &&
+ 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);
+
+ in_button = GTK_BUTTON (widget)->in_button;
+ GTK_WIDGET_CLASS (button_widget_parent_class)->leave_notify_event (widget, event);
+ if (in_button != GTK_BUTTON (widget)->in_button &&
+ 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;
+ widget_class->size_request = button_widget_size_request;
+ 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;
+ widget_class->expose_event = button_widget_expose;
+
+ 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);
+}