Imported Upstream version 1.0beta2a
[platform/upstream/syncevolution.git] / src / gtk-ui / mux-icon-button.c
1 /*
2  * Copyright (C) 2009 Intel Corporation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) version 3.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301  USA
18  */
19
20 /* TODO: should probably ensure specific icon size? */
21
22 #include "mux-icon-button.h"
23
24 enum {
25         PROP_0,
26         PROP_TOGGLEABLE,
27         PROP_PIXBUF_NORMAL,
28         PROP_PIXBUF_ACTIVE,
29         PROP_PIXBUF_PRELIGHT,
30         PROP_PIXBUF_SELECTED,
31         PROP_PIXBUF_INSENSITIVE
32 };
33
34 G_DEFINE_TYPE (MuxIconButton, mux_icon_button, GTK_TYPE_BUTTON)
35
36
37 static void
38 mux_icon_button_get_property (GObject *object, guint property_id,
39                               GValue *value, GParamSpec *pspec)
40 {
41     MuxIconButton *btn = MUX_ICON_BUTTON (object);
42     
43     switch (property_id) {
44     case PROP_TOGGLEABLE:
45         g_value_set_boolean (value, btn->toggleable);
46         break;
47     case PROP_PIXBUF_NORMAL:
48         g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_NORMAL));
49         break;
50     case PROP_PIXBUF_ACTIVE:
51         g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_ACTIVE));
52         break;
53     case PROP_PIXBUF_PRELIGHT:
54         g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_PRELIGHT));
55         break;
56     case PROP_PIXBUF_SELECTED:
57         g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_SELECTED));
58         break;
59     case PROP_PIXBUF_INSENSITIVE:
60         g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_INSENSITIVE));
61         break;
62     default:
63         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
64     }
65 }
66
67 static void
68 mux_icon_button_set_property (GObject *object, guint property_id,
69                               const GValue *value, GParamSpec *pspec)
70 {
71     MuxIconButton *btn = MUX_ICON_BUTTON (object);
72     GdkPixbuf *pixbuf;
73     
74     switch (property_id) {
75     case PROP_TOGGLEABLE:
76         btn->toggleable = g_value_get_boolean (value);
77         break;
78     case PROP_PIXBUF_NORMAL:
79         pixbuf = GDK_PIXBUF (g_value_get_object (value));
80         mux_icon_button_set_pixbuf (btn, GTK_STATE_NORMAL, pixbuf);
81         break;
82     case PROP_PIXBUF_ACTIVE:
83         pixbuf = GDK_PIXBUF (g_value_get_object (value));
84         mux_icon_button_set_pixbuf (btn, GTK_STATE_ACTIVE, pixbuf);
85         break;
86     case PROP_PIXBUF_PRELIGHT:
87         pixbuf = GDK_PIXBUF (g_value_get_object (value));
88         mux_icon_button_set_pixbuf (btn, GTK_STATE_PRELIGHT, pixbuf);
89         break;
90     case PROP_PIXBUF_SELECTED:
91         pixbuf = GDK_PIXBUF (g_value_get_object (value));
92         mux_icon_button_set_pixbuf (btn, GTK_STATE_SELECTED, pixbuf);
93         break;
94     case PROP_PIXBUF_INSENSITIVE:
95         pixbuf = GDK_PIXBUF (g_value_get_object (value));
96         mux_icon_button_set_pixbuf (btn, GTK_STATE_INSENSITIVE, pixbuf);
97         break;
98     default:
99         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
100     }
101 }
102
103 static void
104 mux_icon_button_dispose (GObject *object)
105 {
106     int i;
107     MuxIconButton *btn = MUX_ICON_BUTTON (object);
108     
109     for (i = 0; i < 5; i++) {
110         if (btn->pixbufs[i]) {
111             g_object_unref (btn->pixbufs[i]);
112             btn->pixbufs[i] = NULL;
113         }
114     }
115     G_OBJECT_CLASS (mux_icon_button_parent_class)->dispose (object);
116 }
117
118 static void
119 mux_icon_button_size_request (GtkWidget      *widget,
120                               GtkRequisition *requisition)
121 {
122     MuxIconButton *btn = MUX_ICON_BUTTON (widget);
123
124     if (btn->pixbufs[GTK_STATE_NORMAL]) {
125         requisition->width  = gdk_pixbuf_get_width  (btn->pixbufs[GTK_STATE_NORMAL]);
126         requisition->height = gdk_pixbuf_get_height (btn->pixbufs[GTK_STATE_NORMAL]);
127     }
128 }
129
130 static gboolean
131 mux_icon_button_expose (GtkWidget *widget,
132                         GdkEventExpose *event)
133 {
134     GdkRectangle dirty_area, btn_area;
135     MuxIconButton *btn = MUX_ICON_BUTTON (widget);
136     GdkPixbuf *pixbuf;
137     GtkStateType state;
138
139     if (btn->active) {
140         /* this is a active toggle button */
141         state = GTK_STATE_ACTIVE;
142     } else {
143         state = GTK_WIDGET_STATE (widget);
144     }
145
146     if (btn->pixbufs[state]) {
147         pixbuf = btn->pixbufs[state];
148     } else {
149         pixbuf = btn->pixbufs[GTK_STATE_NORMAL];
150     }
151
152     if (!pixbuf)
153         return FALSE;
154
155     btn_area.width = gdk_pixbuf_get_width (pixbuf);
156     btn_area.height = gdk_pixbuf_get_height (pixbuf);
157     btn_area.x = widget->allocation.x + (widget->allocation.width - btn_area.width) / 2;
158     btn_area.y = widget->allocation.y + (widget->allocation.height - btn_area.height) / 2;
159     
160     if (gdk_rectangle_intersect (&event->area, &widget->allocation, &dirty_area) &&
161         gdk_rectangle_intersect (&btn_area, &dirty_area, &dirty_area)) {
162
163         gdk_draw_pixbuf (widget->window, NULL, pixbuf,
164                          dirty_area.x - btn_area.x, dirty_area.y - btn_area.y,
165                          dirty_area.x, dirty_area.y,
166                          dirty_area.width, dirty_area.height,
167                          GDK_RGB_DITHER_NORMAL, 0, 0);
168     }
169     return FALSE;
170 }
171
172 static void
173 mux_icon_button_clicked (GtkButton *button)
174 {
175     MuxIconButton *icon_button = MUX_ICON_BUTTON (button);
176     
177     if (icon_button->toggleable) {
178         icon_button->active = !icon_button->active;
179     }
180 }
181
182 static void
183 mux_icon_button_class_init (MuxIconButtonClass *klass)
184 {
185     GObjectClass *object_class = G_OBJECT_CLASS (klass);
186     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
187     GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
188     GParamSpec *pspec;
189
190     object_class->get_property = mux_icon_button_get_property;
191     object_class->set_property = mux_icon_button_set_property;
192     object_class->dispose = mux_icon_button_dispose;
193
194     widget_class->size_request = mux_icon_button_size_request;
195     widget_class->expose_event = mux_icon_button_expose;
196
197     button_class->clicked = mux_icon_button_clicked;
198
199     pspec = g_param_spec_boolean ("toggleable",
200                                  "Toggleable",
201                                  "Is icon button button a toggle or normal",
202                                  FALSE,
203                                  G_PARAM_READWRITE);
204     g_object_class_install_property (object_class, PROP_TOGGLEABLE, pspec);
205     pspec = g_param_spec_object ("normal-state-pixbuf",
206                                  "Normal state pixbuf",
207                                  "GdkPixbuf for GTK_STATE_NORMAL",
208                                  GDK_TYPE_PIXBUF,
209                                  G_PARAM_READWRITE);
210     g_object_class_install_property (object_class, PROP_PIXBUF_NORMAL, pspec);
211     pspec = g_param_spec_object ("active-state-pixbuf",
212                                  "Active state pixbuf",
213                                  "GdkPixbuf for GTK_STATE_ACTIVE",
214                                  GDK_TYPE_PIXBUF,
215                                  G_PARAM_READWRITE);
216     g_object_class_install_property (object_class, PROP_PIXBUF_ACTIVE, pspec);
217     pspec = g_param_spec_object ("prelight-state-pixbuf",
218                                  "Prelight state pixbuf",
219                                  "GdkPixbuf for GTK_STATE_PRELIGHT",
220                                  GDK_TYPE_PIXBUF,
221                                  G_PARAM_READWRITE);
222     g_object_class_install_property (object_class, PROP_PIXBUF_PRELIGHT, pspec);
223     pspec = g_param_spec_object ("selected-state-pixbuf",
224                                  "Selected state pixbuf",
225                                  "GdkPixbuf for GTK_STATE_SELECTED",
226                                  GDK_TYPE_PIXBUF,
227                                  G_PARAM_READWRITE);
228     g_object_class_install_property (object_class, PROP_PIXBUF_SELECTED, pspec);
229     pspec = g_param_spec_object ("insensitive-state-pixbuf",
230                                  "Insensitive state pixbuf",
231                                  "GdkPixbuf for GTK_STATE_INSENSITIVE",
232                                  GDK_TYPE_PIXBUF,
233                                  G_PARAM_READWRITE);
234     g_object_class_install_property (object_class, PROP_PIXBUF_INSENSITIVE, pspec);
235 }
236
237 static void
238 mux_icon_button_init (MuxIconButton *self)
239 {
240 }
241
242 GtkWidget*
243 mux_icon_button_new (GdkPixbuf *normal_pixbuf, gboolean toggleable)
244 {
245     return g_object_new (MUX_TYPE_ICON_BUTTON, 
246                          "normal-state-pixbuf", normal_pixbuf,
247                          "toggleable", toggleable,
248                          NULL);
249 }
250
251 void
252 mux_icon_button_set_pixbuf (MuxIconButton *button, GtkStateType state, GdkPixbuf *pixbuf)
253 {
254     if (button->pixbufs[state]) {
255         g_object_unref (button->pixbufs[state]);
256     }
257     button->pixbufs[state] = g_object_ref (pixbuf);
258
259     if (state == GTK_STATE_NORMAL) {
260         gtk_widget_queue_resize (GTK_WIDGET (button));
261     } else if (state == GTK_WIDGET_STATE (GTK_WIDGET (button))) {
262         gtk_widget_queue_draw (GTK_WIDGET (button));
263     }
264 }
265
266 GdkPixbuf*
267 mux_icon_button_get_pixbuf (MuxIconButton *button, GtkStateType state)
268 {
269     return button->pixbufs[state];
270 }
271
272 void
273 mux_icon_button_set_active (MuxIconButton *button, gboolean active)
274 {
275     button->active = active;
276     gtk_widget_queue_draw (GTK_WIDGET (button));
277 }
278
279 gboolean 
280 mux_icon_button_get_active (MuxIconButton *button)
281 {
282     return button->active;
283 }