[Xfce4-commits] <xfce4-panel:devel> Add blinking support to the arrow button.
Nick Schermer
nick at xfce.org
Tue Aug 11 20:28:26 CEST 2009
Updating branch refs/heads/devel
to e05a73505f76186c6801401cc67473b2b08b5641 (commit)
from aae21cb8a2c4b240825a3adc04e3721237788a1f (commit)
commit e05a73505f76186c6801401cc67473b2b08b5641
Author: Nick Schermer <nick at xfce.org>
Date: Fri Feb 27 18:35:37 2009 +0100
Add blinking support to the arrow button.
The arrow button supports blinking by now. You can create a
normal toggle button by using GTK_ARROW_NONE as arrow type.
It is also possible to add child widgets to the arrow button,
previously this was not possible (and not needed). When both
an arrow is set and a child is added, the arrow will show
shown next to the child, this will be used for group buttons in
the tasklist plugin.
Probably some allocation issues will show up, but it's a good
start for reducing the code complexity in the wnck plugins.
libxfce4panel/Makefile.am | 2 -
libxfce4panel/xfce-arrow-button.c | 326 +++++++++++++++++++++++++++++++------
libxfce4panel/xfce-arrow-button.h | 19 ++-
3 files changed, 285 insertions(+), 62 deletions(-)
diff --git a/libxfce4panel/Makefile.am b/libxfce4panel/Makefile.am
index 106da89..04c3442 100644
--- a/libxfce4panel/Makefile.am
+++ b/libxfce4panel/Makefile.am
@@ -34,8 +34,6 @@ libxfce4panel_la_SOURCES = \
$(libxfce4panel_built_sources) \
$(libxfce4panel_headers) \
xfce-arrow-button.c \
- xfce-blink-button.c \
- xfce-blink-button.h \
xfce-hvbox.c \
xfce-panel-convenience.c \
xfce-panel-plugin.c \
diff --git a/libxfce4panel/xfce-arrow-button.c b/libxfce4panel/xfce-arrow-button.c
index 52608f1..003f8f0 100644
--- a/libxfce4panel/xfce-arrow-button.c
+++ b/libxfce4panel/xfce-arrow-button.c
@@ -31,9 +31,14 @@
#include <gtk/gtk.h>
#include <libxfce4panel/libxfce4panel.h>
+#include <common/panel-private.h>
-#define ARROW_WIDTH (8)
-#define ARROW_PADDING (2)
+#define XFCE_ARROW_BUTTON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+ XFCE_TYPE_ARROW_BUTTON, \
+ XfceArrowButtonPrivate))
+
+#define ARROW_WIDTH (8)
+#define MAX_BLINKING_COUNT (16)
enum
{
@@ -55,13 +60,31 @@ static void xfce_arrow_button_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
+static void xfce_arrow_button_finalize (GObject *object);
static gboolean xfce_arrow_button_expose_event (GtkWidget *widget,
GdkEventExpose *event);
static void xfce_arrow_button_size_request (GtkWidget *widget,
GtkRequisition *requisition);
-static void xfce_arrow_button_add (GtkContainer *container,
- GtkWidget *child);
-static GType xfce_arrow_button_child_type (GtkContainer *container);
+static void xfce_arrow_button_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+
+
+struct _XfceArrowButtonPrivate
+{
+ /* arrow type of the button */
+ GtkArrowType arrow_type;
+
+ /* blinking timeout id */
+ guint blinking_timeout_id;
+
+ /* counter to make the blinking stop when
+ * MAX_BLINKING_COUNT is reached */
+ guint blinking_counter;
+
+ /* button relief when the blinking starts */
+ GtkReliefStyle last_relief;
+};
@@ -76,21 +99,20 @@ G_DEFINE_TYPE (XfceArrowButton, xfce_arrow_button, GTK_TYPE_TOGGLE_BUTTON)
static void
xfce_arrow_button_class_init (XfceArrowButtonClass * klass)
{
- GObjectClass *gobject_class;
- GtkWidgetClass *gtkwidget_class;
- GtkContainerClass *gtkcontainer_class;
+ GObjectClass *gobject_class;
+ GtkWidgetClass *gtkwidget_class;
+
+ g_type_class_add_private (klass, sizeof (XfceArrowButtonPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = xfce_arrow_button_get_property;
gobject_class->set_property = xfce_arrow_button_set_property;
+ gobject_class->finalize = xfce_arrow_button_finalize;
gtkwidget_class = GTK_WIDGET_CLASS (klass);
gtkwidget_class->expose_event = xfce_arrow_button_expose_event;
gtkwidget_class->size_request = xfce_arrow_button_size_request;
-
- gtkcontainer_class = GTK_CONTAINER_CLASS (klass);
- gtkcontainer_class->add = xfce_arrow_button_add;
- gtkcontainer_class->child_type = xfce_arrow_button_child_type;
+ gtkwidget_class->size_allocate = xfce_arrow_button_size_allocate;
/**
* XfceArrowButton::arrow-type-changed
@@ -122,7 +144,8 @@ xfce_arrow_button_class_init (XfceArrowButtonClass * klass)
"The arrow type of the menu button",
GTK_TYPE_ARROW_TYPE,
GTK_ARROW_UP,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ G_PARAM_READWRITE
+ | G_PARAM_STATIC_STRINGS));
}
@@ -130,9 +153,19 @@ xfce_arrow_button_class_init (XfceArrowButtonClass * klass)
static void
xfce_arrow_button_init (XfceArrowButton *button)
{
- GTK_WIDGET_SET_FLAGS (GTK_WIDGET (button), GTK_NO_WINDOW);
+ /* set private pointer */
+ button->priv = XFCE_ARROW_BUTTON_GET_PRIVATE (button);
- button->arrow_type = GTK_ARROW_UP;
+ /* initialize button values */
+ button->priv->arrow_type = GTK_ARROW_UP;
+ button->priv->blinking_timeout_id = 0;
+ button->priv->blinking_counter = 0;
+ button->priv->last_relief = GTK_RELIEF_NORMAL;
+
+ /* set some widget properties */
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (button), GTK_NO_WINDOW);
+ GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_DEFAULT | GTK_CAN_FOCUS);
+ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
}
@@ -181,28 +214,65 @@ xfce_arrow_button_get_property (GObject *object,
-static gboolean
-xfce_arrow_button_expose_event (GtkWidget *widget,
- GdkEventExpose *event)
+static void
+xfce_arrow_button_finalize (GObject *object)
{
- gint x, y, w;
+ XfceArrowButton *button = XFCE_ARROW_BUTTON (object);
- if (G_LIKELY (GTK_WIDGET_DRAWABLE (widget)))
- {
- w = MIN (widget->allocation.height - 2 * widget->style->ythickness,
- widget->allocation.width - 2 * widget->style->xthickness);
- w = MIN (w, ARROW_WIDTH);
+ if (button->priv->blinking_timeout_id != 0)
+ g_source_remove (button->priv->blinking_timeout_id);
- x = widget->allocation.x + (widget->allocation.width - w) / 2;
- y = widget->allocation.y + (widget->allocation.height - w) / 2;
+ (*G_OBJECT_CLASS (xfce_arrow_button_parent_class)->finalize) (object);
+}
- (*GTK_WIDGET_CLASS (xfce_arrow_button_parent_class)->expose_event) (widget, event);
+
+static gboolean
+xfce_arrow_button_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ XfceArrowButton *button = XFCE_ARROW_BUTTON (widget);
+ GtkWidget *child;
+ gint x, y, width;
+
+ /* draw the button */
+ (*GTK_WIDGET_CLASS (xfce_arrow_button_parent_class)->expose_event) (widget, event);
+
+ if (button->priv->arrow_type != GTK_ARROW_NONE
+ && GTK_WIDGET_DRAWABLE (widget))
+ {
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL && GTK_WIDGET_VISIBLE (child))
+ {
+ if (button->priv->arrow_type == GTK_ARROW_UP
+ || button->priv->arrow_type == GTK_ARROW_DOWN)
+ {
+ width = ARROW_WIDTH;
+ x = widget->allocation.x + widget->style->xthickness;
+ y = widget->allocation.y + (widget->allocation.height - width) / 2;
+ }
+ else
+ {
+ width = ARROW_WIDTH;
+ x = widget->allocation.x + (widget->allocation.width - width) / 2;
+ y = widget->allocation.y + widget->style->ythickness;
+ }
+ }
+ else
+ {
+ width = MIN (widget->allocation.height - 2 * widget->style->ythickness,
+ widget->allocation.width - 2 * widget->style->xthickness);
+ width = CLAMP (width, 1, ARROW_WIDTH);
+
+ x = widget->allocation.x + (widget->allocation.width - width) / 2;
+ y = widget->allocation.y + (widget->allocation.height - width) / 2;
+ }
+
gtk_paint_arrow (widget->style, widget->window,
GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE,
&(event->area), widget, "xfce_arrow_button",
- XFCE_ARROW_BUTTON (widget)->arrow_type, FALSE,
- x, y, w, w);
+ button->priv->arrow_type, FALSE,
+ x, y, width, width);
}
return TRUE;
@@ -214,29 +284,119 @@ static void
xfce_arrow_button_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
- gint size;
-
- /* calculate the requested arrow size */
- size = ARROW_WIDTH + ARROW_PADDING + 2 * MAX (widget->style->xthickness, widget->style->ythickness);
+ XfceArrowButton *button = XFCE_ARROW_BUTTON (widget);
+ GtkWidget *child;
- requisition->width = requisition->height = size;
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL && GTK_WIDGET_VISIBLE (child))
+ {
+ /* use gtk for the widget size */
+ (*GTK_WIDGET_CLASS (xfce_arrow_button_parent_class)->size_request) (widget, requisition);
+
+ /* reserve space for the arrow */
+ switch (button->priv->arrow_type)
+ {
+ case GTK_ARROW_UP:
+ case GTK_ARROW_DOWN:
+ requisition->width += ARROW_WIDTH;
+ break;
+
+ case GTK_ARROW_LEFT:
+ case GTK_ARROW_RIGHT:
+ requisition->height += ARROW_WIDTH;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (button->priv->arrow_type != GTK_ARROW_NONE)
+ {
+ requisition->height = ARROW_WIDTH + 2 * widget->style->xthickness;
+ requisition->width = ARROW_WIDTH + 2 * widget->style->ythickness;
+ }
}
static void
-xfce_arrow_button_add (GtkContainer *container,
- GtkWidget *child)
+xfce_arrow_button_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
{
- g_warning ("XfceArrowButton cannot contain any children");
+ XfceArrowButton *button = XFCE_ARROW_BUTTON (widget);
+ GtkWidget *child;
+ GtkAllocation child_allocation;
+
+ /* allocate the button */
+ (*GTK_WIDGET_CLASS (xfce_arrow_button_parent_class)->size_allocate) (widget, allocation);
+
+ if (button->priv->arrow_type != GTK_ARROW_NONE)
+ {
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL && GTK_WIDGET_VISIBLE (child))
+ {
+ /* copy the child allocation */
+ child_allocation = child->allocation;
+
+ /* update the allocation to make space for the arrow */
+ switch (button->priv->arrow_type)
+ {
+ case GTK_ARROW_LEFT:
+ case GTK_ARROW_RIGHT:
+ child_allocation.height -= ARROW_WIDTH;
+ child_allocation.y += ARROW_WIDTH;
+ break;
+
+ default:
+ child_allocation.width -= ARROW_WIDTH;
+ child_allocation.x += ARROW_WIDTH;
+ break;
+ }
+
+ /* set the child allocation again */
+ gtk_widget_size_allocate (child, &child_allocation);
+ }
+ }
}
-static GType
-xfce_arrow_button_child_type (GtkContainer *container)
+static gboolean
+xfce_arrow_button_blinking_timeout (gpointer user_data)
{
- return GTK_TYPE_WIDGET;
+ XfceArrowButton *button = XFCE_ARROW_BUTTON (user_data);
+ GtkStyle *style;
+ GtkRcStyle *rc;
+
+ rc = gtk_widget_get_modifier_style (GTK_WIDGET (button));
+ if(PANEL_HAS_FLAG (rc->color_flags[GTK_STATE_NORMAL], GTK_RC_BG)
+ || button->priv->blinking_timeout_id == 0)
+ {
+ gtk_button_set_relief (GTK_BUTTON (button), button->priv->last_relief);
+ PANEL_UNSET_FLAG (rc->color_flags[GTK_STATE_NORMAL], GTK_RC_BG);
+ gtk_widget_modify_style (GTK_WIDGET (button), rc);
+ }
+ else
+ {
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NORMAL);
+ PANEL_SET_FLAG (rc->color_flags[GTK_STATE_NORMAL], GTK_RC_BG);
+ style = gtk_widget_get_style (GTK_WIDGET (button));
+ rc->bg[GTK_STATE_NORMAL] = style->bg[GTK_STATE_SELECTED];
+ gtk_widget_modify_style(GTK_WIDGET (button), rc);
+ }
+
+ return (button->priv->blinking_counter++ < MAX_BLINKING_COUNT);
+}
+
+
+
+static void
+xfce_arrow_button_blinking_timeout_destroyed (gpointer user_data)
+{
+ XfceArrowButton *button = XFCE_ARROW_BUTTON (user_data);
+
+ button->priv->blinking_timeout_id = 0;
+ button->priv->blinking_counter = 0;
}
@@ -252,7 +412,26 @@ xfce_arrow_button_child_type (GtkContainer *container)
PANEL_SYMBOL_EXPORT GtkWidget *
xfce_arrow_button_new (GtkArrowType arrow_type)
{
- return g_object_new (XFCE_TYPE_ARROW_BUTTON, "arrow-type", arrow_type, NULL);
+ return g_object_new (XFCE_TYPE_ARROW_BUTTON,
+ "arrow-type", arrow_type,
+ NULL);
+}
+
+
+
+/**
+ * xfce_arrow_button_get_arrow_type:
+ * @button : a #XfceArrowButton
+ *
+ * Returns the value of the ::arrow-type property.
+ *
+ * Returns: the #GtkArrowType of @button.
+ **/
+PANEL_SYMBOL_EXPORT GtkArrowType
+xfce_arrow_button_get_arrow_type (XfceArrowButton *button)
+{
+ g_return_val_if_fail (XFCE_IS_ARROW_BUTTON (button), GTK_ARROW_UP);
+ return button->priv->arrow_type;
}
@@ -270,36 +449,77 @@ xfce_arrow_button_set_arrow_type (XfceArrowButton *button,
{
g_return_if_fail (XFCE_IS_ARROW_BUTTON (button));
- if (G_LIKELY (button->arrow_type != arrow_type))
- {
+ if (G_LIKELY (button->priv->arrow_type != arrow_type))
+ {
/* store the new arrow type */
- button->arrow_type = arrow_type;
+ button->priv->arrow_type = arrow_type;
/* emit signal */
- g_signal_emit (G_OBJECT (button), arrow_button_signals[ARROW_TYPE_CHANGED], 0, arrow_type);
+ g_signal_emit (G_OBJECT (button),
+ arrow_button_signals[ARROW_TYPE_CHANGED],
+ 0, arrow_type);
/* notify property change */
g_object_notify (G_OBJECT (button), "arrow-type");
/* redraw the arrow button */
- gtk_widget_queue_draw (GTK_WIDGET (button));
+ gtk_widget_queue_resize (GTK_WIDGET (button));
}
}
/**
- * xfce_arrow_button_get_arrow_type:
+ * xfce_arrow_button_get_blinking:
* @button : a #XfceArrowButton
*
- * Returns the value of the ::arrow-type property.
+ * Whether the button is blinking.
*
- * Returns: the #GtkArrowType of @button.
+ * Returns: %TRUE when @button is blinking.
**/
-PANEL_SYMBOL_EXPORT GtkArrowType
-xfce_arrow_button_get_arrow_type (XfceArrowButton *button)
+PANEL_SYMBOL_EXPORT gboolean
+xfce_arrow_button_get_blinking (XfceArrowButton *button)
{
- g_return_val_if_fail (XFCE_IS_ARROW_BUTTON (button), GTK_ARROW_UP);
+ g_return_val_if_fail (XFCE_IS_ARROW_BUTTON (button), FALSE);
+ return !!(button->priv->blinking_timeout_id != 0);
+}
+
+
+
+/**
+ * xfce_arrow_button_set_blinking:
+ * @button : a #XfceArrowButton
+ * @blinking : %TRUE when the button should start blinking, %FALSE to
+ * stop the blinking.
+ *
+ * Make the button blink.
+ **/
+PANEL_SYMBOL_EXPORT void
+xfce_arrow_button_set_blinking (XfceArrowButton *button,
+ gboolean blinking)
+{
+ g_return_if_fail (XFCE_IS_ARROW_BUTTON (button));
+
+ if (blinking)
+ {
+ /* store the relief of the button */
+ button->priv->last_relief = gtk_button_get_relief (GTK_BUTTON (button));
+
+ if (button->priv->blinking_timeout_id == 0)
+ {
+ /* start blinking timeout */
+ button->priv->blinking_timeout_id =
+ g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 500,
+ xfce_arrow_button_blinking_timeout, button,
+ xfce_arrow_button_blinking_timeout_destroyed);
+ }
+ }
+ else if (button->priv->blinking_timeout_id != 0)
+ {
+ /* stop the blinking timeout */
+ g_source_remove (button->priv->blinking_timeout_id);
+ }
- return button->arrow_type;
+ /* start with a blinking or make sure the button is normal */
+ xfce_arrow_button_blinking_timeout (button);
}
diff --git a/libxfce4panel/xfce-arrow-button.h b/libxfce4panel/xfce-arrow-button.h
index 0f4700d..1f47dcf 100644
--- a/libxfce4panel/xfce-arrow-button.h
+++ b/libxfce4panel/xfce-arrow-button.h
@@ -29,8 +29,9 @@
G_BEGIN_DECLS
-typedef struct _XfceArrowButtonClass XfceArrowButtonClass;
-typedef struct _XfceArrowButton XfceArrowButton;
+typedef struct _XfceArrowButtonPrivate XfceArrowButtonPrivate;
+typedef struct _XfceArrowButtonClass XfceArrowButtonClass;
+typedef struct _XfceArrowButton XfceArrowButton;
#define XFCE_TYPE_ARROW_BUTTON (xfce_arrow_button_get_type ())
#define XFCE_ARROW_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_ARROW_BUTTON, XfceArrowButton))
@@ -54,18 +55,22 @@ struct _XfceArrowButton
/*< private >*/
GtkToggleButton __parent__;
- GtkArrowType arrow_type;
+ /*< private >*/
+ XfceArrowButtonPrivate *priv;
};
PANEL_SYMBOL_EXPORT
GType xfce_arrow_button_get_type (void) G_GNUC_CONST;
-GtkWidget *xfce_arrow_button_new (GtkArrowType arrow_type) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+GtkWidget *xfce_arrow_button_new (GtkArrowType arrow_type) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-void xfce_arrow_button_set_arrow_type (XfceArrowButton *button,
- GtkArrowType arrow_type);
+GtkArrowType xfce_arrow_button_get_arrow_type (XfceArrowButton *button);
+void xfce_arrow_button_set_arrow_type (XfceArrowButton *button,
+ GtkArrowType arrow_type);
-GtkArrowType xfce_arrow_button_get_arrow_type (XfceArrowButton *button);
+gboolean xfce_arrow_button_get_blinking (XfceArrowButton *button);
+void xfce_arrow_button_set_blinking (XfceArrowButton *button,
+ gboolean blinking);
G_END_DECLS
More information about the Xfce4-commits
mailing list