syncevolution/src/gtk-ui/mux-icon-button.c

284 lines
9.6 KiB
C

/*
* Copyright (C) 2009 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
/* TODO: should probably ensure specific icon size? */
#include "mux-icon-button.h"
enum {
PROP_0,
PROP_TOGGLEABLE,
PROP_PIXBUF_NORMAL,
PROP_PIXBUF_ACTIVE,
PROP_PIXBUF_PRELIGHT,
PROP_PIXBUF_SELECTED,
PROP_PIXBUF_INSENSITIVE
};
G_DEFINE_TYPE (MuxIconButton, mux_icon_button, GTK_TYPE_BUTTON)
static void
mux_icon_button_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
MuxIconButton *btn = MUX_ICON_BUTTON (object);
switch (property_id) {
case PROP_TOGGLEABLE:
g_value_set_boolean (value, btn->toggleable);
break;
case PROP_PIXBUF_NORMAL:
g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_NORMAL));
break;
case PROP_PIXBUF_ACTIVE:
g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_ACTIVE));
break;
case PROP_PIXBUF_PRELIGHT:
g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_PRELIGHT));
break;
case PROP_PIXBUF_SELECTED:
g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_SELECTED));
break;
case PROP_PIXBUF_INSENSITIVE:
g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_INSENSITIVE));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
mux_icon_button_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
MuxIconButton *btn = MUX_ICON_BUTTON (object);
GdkPixbuf *pixbuf;
switch (property_id) {
case PROP_TOGGLEABLE:
btn->toggleable = g_value_get_boolean (value);
break;
case PROP_PIXBUF_NORMAL:
pixbuf = GDK_PIXBUF (g_value_get_object (value));
mux_icon_button_set_pixbuf (btn, GTK_STATE_NORMAL, pixbuf);
break;
case PROP_PIXBUF_ACTIVE:
pixbuf = GDK_PIXBUF (g_value_get_object (value));
mux_icon_button_set_pixbuf (btn, GTK_STATE_ACTIVE, pixbuf);
break;
case PROP_PIXBUF_PRELIGHT:
pixbuf = GDK_PIXBUF (g_value_get_object (value));
mux_icon_button_set_pixbuf (btn, GTK_STATE_PRELIGHT, pixbuf);
break;
case PROP_PIXBUF_SELECTED:
pixbuf = GDK_PIXBUF (g_value_get_object (value));
mux_icon_button_set_pixbuf (btn, GTK_STATE_SELECTED, pixbuf);
break;
case PROP_PIXBUF_INSENSITIVE:
pixbuf = GDK_PIXBUF (g_value_get_object (value));
mux_icon_button_set_pixbuf (btn, GTK_STATE_INSENSITIVE, pixbuf);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
mux_icon_button_dispose (GObject *object)
{
int i;
MuxIconButton *btn = MUX_ICON_BUTTON (object);
for (i = 0; i < 5; i++) {
if (btn->pixbufs[i]) {
g_object_unref (btn->pixbufs[i]);
btn->pixbufs[i] = NULL;
}
}
G_OBJECT_CLASS (mux_icon_button_parent_class)->dispose (object);
}
static void
mux_icon_button_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
MuxIconButton *btn = MUX_ICON_BUTTON (widget);
if (btn->pixbufs[GTK_STATE_NORMAL]) {
requisition->width = gdk_pixbuf_get_width (btn->pixbufs[GTK_STATE_NORMAL]);
requisition->height = gdk_pixbuf_get_height (btn->pixbufs[GTK_STATE_NORMAL]);
}
}
static gboolean
mux_icon_button_expose (GtkWidget *widget,
GdkEventExpose *event)
{
GdkRectangle dirty_area, btn_area;
MuxIconButton *btn = MUX_ICON_BUTTON (widget);
GdkPixbuf *pixbuf;
GtkStateType state;
if (btn->active) {
/* this is a active toggle button */
state = GTK_STATE_ACTIVE;
} else {
state = GTK_WIDGET_STATE (widget);
}
if (btn->pixbufs[state]) {
pixbuf = btn->pixbufs[state];
} else {
pixbuf = btn->pixbufs[GTK_STATE_NORMAL];
}
if (!pixbuf)
return FALSE;
btn_area.width = gdk_pixbuf_get_width (pixbuf);
btn_area.height = gdk_pixbuf_get_height (pixbuf);
btn_area.x = widget->allocation.x + (widget->allocation.width - btn_area.width) / 2;
btn_area.y = widget->allocation.y + (widget->allocation.height - btn_area.height) / 2;
if (gdk_rectangle_intersect (&event->area, &widget->allocation, &dirty_area) &&
gdk_rectangle_intersect (&btn_area, &dirty_area, &dirty_area)) {
gdk_draw_pixbuf (widget->window, NULL, pixbuf,
dirty_area.x - btn_area.x, dirty_area.y - btn_area.y,
dirty_area.x, dirty_area.y,
dirty_area.width, dirty_area.height,
GDK_RGB_DITHER_NORMAL, 0, 0);
}
return FALSE;
}
static void
mux_icon_button_clicked (GtkButton *button)
{
MuxIconButton *icon_button = MUX_ICON_BUTTON (button);
if (icon_button->toggleable) {
icon_button->active = !icon_button->active;
}
}
static void
mux_icon_button_class_init (MuxIconButtonClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
GParamSpec *pspec;
object_class->get_property = mux_icon_button_get_property;
object_class->set_property = mux_icon_button_set_property;
object_class->dispose = mux_icon_button_dispose;
widget_class->size_request = mux_icon_button_size_request;
widget_class->expose_event = mux_icon_button_expose;
button_class->clicked = mux_icon_button_clicked;
pspec = g_param_spec_boolean ("toggleable",
"Toggleable",
"Is icon button button a toggle or normal",
FALSE,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_TOGGLEABLE, pspec);
pspec = g_param_spec_object ("normal-state-pixbuf",
"Normal state pixbuf",
"GdkPixbuf for GTK_STATE_NORMAL",
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_PIXBUF_NORMAL, pspec);
pspec = g_param_spec_object ("active-state-pixbuf",
"Active state pixbuf",
"GdkPixbuf for GTK_STATE_ACTIVE",
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_PIXBUF_ACTIVE, pspec);
pspec = g_param_spec_object ("prelight-state-pixbuf",
"Prelight state pixbuf",
"GdkPixbuf for GTK_STATE_PRELIGHT",
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_PIXBUF_PRELIGHT, pspec);
pspec = g_param_spec_object ("selected-state-pixbuf",
"Selected state pixbuf",
"GdkPixbuf for GTK_STATE_SELECTED",
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_PIXBUF_SELECTED, pspec);
pspec = g_param_spec_object ("insensitive-state-pixbuf",
"Insensitive state pixbuf",
"GdkPixbuf for GTK_STATE_INSENSITIVE",
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_PIXBUF_INSENSITIVE, pspec);
}
static void
mux_icon_button_init (MuxIconButton *self)
{
}
GtkWidget*
mux_icon_button_new (GdkPixbuf *normal_pixbuf, gboolean toggleable)
{
return g_object_new (MUX_TYPE_ICON_BUTTON,
"normal-state-pixbuf", normal_pixbuf,
"toggleable", toggleable,
NULL);
}
void
mux_icon_button_set_pixbuf (MuxIconButton *button, GtkStateType state, GdkPixbuf *pixbuf)
{
if (button->pixbufs[state]) {
g_object_unref (button->pixbufs[state]);
}
button->pixbufs[state] = g_object_ref (pixbuf);
if (state == GTK_STATE_NORMAL) {
gtk_widget_queue_resize (GTK_WIDGET (button));
} else if (state == GTK_WIDGET_STATE (GTK_WIDGET (button))) {
gtk_widget_queue_draw (GTK_WIDGET (button));
}
}
GdkPixbuf*
mux_icon_button_get_pixbuf (MuxIconButton *button, GtkStateType state)
{
return button->pixbufs[state];
}
void
mux_icon_button_set_active (MuxIconButton *button, gboolean active)
{
button->active = active;
gtk_widget_queue_draw (GTK_WIDGET (button));
}
gboolean
mux_icon_button_get_active (MuxIconButton *button)
{
return button->active;
}