3 * Copyright (C) 2008-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * gLabels is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
23 #include "color-combo-button.h"
25 #include <glib/gi18n.h>
28 #include "color-combo-menu.h"
29 #include "color-swatch.h"
39 /*========================================================*/
41 /*========================================================*/
43 /** GL_COLOR_COMBO_BUTTON Private fields */
44 struct _glColorComboButtonPrivate {
47 gboolean is_default_flag;
52 GtkWidget *button_vbox;
54 GtkWidget *dropdown_button;
65 /*========================================================*/
66 /* Private globals. */
67 /*========================================================*/
69 static guint signals[LAST_SIGNAL] = {0};
72 /*========================================================*/
73 /* Private function prototypes. */
74 /*========================================================*/
77 gl_color_combo_button_finalize (GObject *object);
80 button_clicked_cb (glColorComboButton *this);
83 dropdown_button_press_event_cb (GtkWidget *widget,
84 GdkEventButton *event,
85 glColorComboButton *this);
88 menu_color_changed_cb (glColorComboMenu *object,
91 glColorComboButton *this);
94 menu_selection_done_cb (GtkMenuShell *object,
95 glColorComboButton *this);
98 /*****************************************************************************/
99 /* Object infrastructure. */
100 /*****************************************************************************/
101 G_DEFINE_TYPE (glColorComboButton, gl_color_combo_button, GTK_TYPE_HBOX)
104 /*****************************************************************************/
105 /* Class Init Function. */
106 /*****************************************************************************/
108 gl_color_combo_button_class_init (glColorComboButtonClass *class)
110 GObjectClass *gobject_class = (GObjectClass *) class;
112 gl_color_combo_button_parent_class = g_type_class_peek_parent (class);
114 gobject_class->finalize = gl_color_combo_button_finalize;
116 signals[COLOR_CHANGED] =
117 g_signal_new ("color_changed",
118 G_OBJECT_CLASS_TYPE (gobject_class),
120 G_STRUCT_OFFSET (glColorComboButtonClass, color_changed),
122 gl_marshal_VOID__UINT_BOOLEAN,
124 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
129 /*****************************************************************************/
130 /* Object Instance Init Function. */
131 /*****************************************************************************/
133 gl_color_combo_button_init (glColorComboButton *this)
137 gtk_box_set_spacing (GTK_BOX (this), 0);
139 this->priv = g_new0 (glColorComboButtonPrivate, 1);
141 this->priv->button_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
143 this->priv->button = gtk_toggle_button_new ();
144 gtk_container_add (GTK_CONTAINER (this->priv->button), this->priv->button_vbox);
145 gtk_button_set_focus_on_click (GTK_BUTTON (this->priv->button), FALSE);
146 g_signal_connect_swapped (this->priv->button, "clicked",
147 G_CALLBACK(button_clicked_cb), this);
149 gtk_box_pack_start (GTK_BOX (this), this->priv->button, FALSE, FALSE, 0);
151 this->priv->dropdown_button = gtk_toggle_button_new ();
152 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
153 gtk_container_add (GTK_CONTAINER (this->priv->dropdown_button), arrow);
154 gtk_button_set_relief (GTK_BUTTON (this->priv->dropdown_button), GTK_RELIEF_NONE);
155 gtk_button_set_focus_on_click (GTK_BUTTON (this->priv->dropdown_button), FALSE);
156 g_signal_connect (this->priv->dropdown_button, "button_press_event",
157 G_CALLBACK(dropdown_button_press_event_cb), this);
159 gtk_box_pack_start (GTK_BOX (this), this->priv->dropdown_button, FALSE, FALSE, 0);
163 /*****************************************************************************/
164 /* Finalize Method. */
165 /*****************************************************************************/
167 gl_color_combo_button_finalize (GObject *object)
169 glColorComboButton *this;
171 g_return_if_fail (object && IS_GL_COLOR_COMBO_BUTTON (object));
172 this = GL_COLOR_COMBO_BUTTON (object);
174 g_object_ref_sink (this->priv->menu);
177 G_OBJECT_CLASS (gl_color_combo_button_parent_class)->finalize (object);
181 /*****************************************************************************/
182 /** New Object Generator. */
183 /*****************************************************************************/
185 gl_color_combo_button_new (const gchar *icon_name,
186 const gchar *default_label,
190 glColorComboButton *this;
192 GdkPixbuf *pixbuf1, *pixbuf2;
194 this = g_object_new (TYPE_GL_COLOR_COMBO_BUTTON, NULL);
198 default_label = _("Default Color");
201 this->priv->default_color = default_color;
202 this->priv->color = color;
206 pixbuf1 = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
207 icon_name, IMAGE_W, 0, NULL);
208 pixbuf2 = gdk_pixbuf_new_subpixbuf (pixbuf1, 0, 0, IMAGE_W, IMAGE_H-SWATCH_H);
210 wimage = gtk_image_new_from_pixbuf (pixbuf2);
211 g_object_unref (G_OBJECT (pixbuf1));
212 g_object_unref (G_OBJECT (pixbuf2));
213 gtk_box_pack_start (GTK_BOX (this->priv->button_vbox), wimage, FALSE, FALSE, 0);
215 this->priv->swatch = gl_color_swatch_new (IMAGE_W, SWATCH_H, color);
219 this->priv->swatch = gl_color_swatch_new (IMAGE_W, IMAGE_H, color);
221 gtk_box_pack_start (GTK_BOX (this->priv->button_vbox), this->priv->swatch, FALSE, FALSE, 0);
223 this->priv->menu = gl_color_combo_menu_new (default_label, color);
224 gtk_widget_show_all (this->priv->menu);
226 g_signal_connect (this->priv->menu, "color_changed",
227 G_CALLBACK (menu_color_changed_cb), this);
228 g_signal_connect (this->priv->menu, "selection_done",
229 G_CALLBACK (menu_selection_done_cb), this);
231 return GTK_WIDGET (this);
235 /*****************************************************************************/
237 /*****************************************************************************/
239 gl_color_combo_button_set_color (glColorComboButton *this,
242 this->priv->color = color;
244 gl_color_swatch_set_color (GL_COLOR_SWATCH (this->priv->swatch), color);
248 /*****************************************************************************/
249 /* Set to default color. */
250 /*****************************************************************************/
252 gl_color_combo_button_set_to_default (glColorComboButton *this)
254 gl_color_combo_button_set_color (this, this->priv->default_color);
257 /*****************************************************************************/
259 /*****************************************************************************/
261 gl_color_combo_button_get_color (glColorComboButton *this,
262 gboolean *is_default)
266 *is_default = this->priv->is_default_flag;
269 return this->priv->color;
273 /*****************************************************************************/
274 /** Set relief style. */
275 /*****************************************************************************/
277 gl_color_combo_button_set_relief( glColorComboButton *this,
278 GtkReliefStyle relief )
280 gtk_button_set_relief (GTK_BUTTON (this->priv->button), relief);
284 /*****************************************************************************/
285 /* Color button "clicked" callback. */
286 /*****************************************************************************/
288 button_clicked_cb( glColorComboButton *this )
290 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->button),
293 g_signal_emit (this, signals[COLOR_CHANGED], 0,
295 this->priv->is_default_flag);
299 /*****************************************************************************/
300 /* Menu positioning function. */
301 /*****************************************************************************/
303 menu_position_function (GtkMenu *menu,
307 glColorComboButton *this)
310 gint w_screen, h_screen;
312 gint x_window, y_window;
313 GtkAllocation allocation;
314 gint x_this, y_this, h_this;
315 GtkRequisition menu_requisition;
321 screen = gtk_widget_get_screen (GTK_WIDGET (this));
322 w_screen = gdk_screen_get_width (screen);
323 h_screen = gdk_screen_get_height (screen);
326 * Absolute position of "this" window on screen.
328 window = gtk_widget_get_window (GTK_WIDGET (this));
329 gdk_window_get_origin (window, &x_window, &y_window);
332 * Position and size of "this" inside window
334 gtk_widget_get_allocation (GTK_WIDGET (this), &allocation);
335 x_this = allocation.x;
336 y_this = allocation.y;
337 h_this = allocation.height;
342 gtk_widget_get_preferred_size (this->priv->menu, NULL, &menu_requisition);
343 h_menu = menu_requisition.height;
344 w_menu = menu_requisition.width;
347 * Default position anchored to lower left corner of "this".
349 *x = x_window + x_this;
350 *y = y_window + y_this + h_this;
353 * Adjust vertical position if menu if extends past bottom of screen.
355 if ( (*y + h_menu) > h_screen )
357 *y = y_window + y_this - h_menu;
361 *y = h_screen - h_menu;
366 * Adjust horizontal position if menu if extends past edge of screen.
368 if ( (*x + w_menu) > w_screen )
370 *x = w_screen - w_menu;
378 /*****************************************************************************/
379 /* Dropdown button "button_press_event" callback. */
380 /*****************************************************************************/
382 dropdown_button_press_event_cb (GtkWidget *widget,
383 GdkEventButton *event,
384 glColorComboButton *this)
386 switch (event->button)
390 g_signal_handlers_block_by_func (G_OBJECT (this->priv->button),
391 button_clicked_cb, this);
392 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->button),
394 g_signal_handlers_unblock_by_func (G_OBJECT (this->priv->button),
395 button_clicked_cb, this);
396 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->dropdown_button),
399 gtk_menu_popup (GTK_MENU (this->priv->menu),
401 (GtkMenuPositionFunc)menu_position_function, this,
402 event->button, event->time);
414 /*****************************************************************************/
415 /* Menu "color changed" callback. */
416 /*****************************************************************************/
418 menu_color_changed_cb (glColorComboMenu *object,
421 glColorComboButton *this)
425 this->priv->color = this->priv->default_color;
429 this->priv->color = color;
431 this->priv->is_default_flag = is_default;
433 gl_color_swatch_set_color (GL_COLOR_SWATCH (this->priv->swatch),
436 g_signal_emit (this, signals[COLOR_CHANGED], 0,
438 this->priv->is_default_flag);
442 /*****************************************************************************/
443 /* Menu "color changed" callback. */
444 /*****************************************************************************/
446 menu_selection_done_cb (GtkMenuShell *object,
447 glColorComboButton *this)
449 g_signal_handlers_block_by_func (G_OBJECT (this->priv->button),
450 button_clicked_cb, this);
451 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->button),
453 g_signal_handlers_unblock_by_func (G_OBJECT (this->priv->button),
454 button_clicked_cb, this);
456 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->dropdown_button),
463 * Local Variables: -- emacs
465 * c-basic-offset: 8 -- emacs
466 * tab-width: 8 -- emacs
467 * indent-tabs-mode: nil -- emacs