]> git.sur5r.net Git - glabels/blob - glabels2/src/color-combo.c
6b9e5761260c575a27f367e037fc4a11a3b8a454
[glabels] / glabels2 / src / color-combo.c
1 /*
2  *  color-combo.c
3  *  Copyright (C) 2008-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
21 #include <config.h>
22
23 #include "color-combo.h"
24
25 #include "color-combo-menu.h"
26 #include <glib/gi18n.h>
27 #include <gtk/gtkhbox.h>
28 #include "color-swatch.h"
29 #include <gtk/gtkarrow.h>
30 #include "marshal.h"
31 #include "color.h"
32
33
34 #define IMAGE_W 24
35 #define IMAGE_H 24
36
37
38 /*========================================================*/
39 /* Private types.                                         */
40 /*========================================================*/
41
42 /** GL_COLOR_COMBO Private fields */
43 struct _glColorComboPrivate {
44
45         guint       color;
46         gboolean    is_default_flag;
47
48         guint       default_color;
49
50         GtkWidget  *swatch;
51
52         GtkWidget  *menu;
53 };
54
55 enum {
56         COLOR_CHANGED,
57         LAST_SIGNAL
58 };
59
60
61 /*========================================================*/
62 /* Private globals.                                       */
63 /*========================================================*/
64
65 static guint signals[LAST_SIGNAL] = {0};
66
67
68 /*========================================================*/
69 /* Private function prototypes.                           */
70 /*========================================================*/
71
72 static void gl_color_combo_finalize      (GObject             *object);
73
74 static gboolean
75 button_press_event_cb (GtkWidget      *widget,
76                        GdkEventButton *event,
77                        glColorCombo   *this);
78
79 static GdkPixbuf *
80 create_pixbuf (glColorCombo   *this,
81                gdouble         w,
82                gdouble         h);
83
84 static void
85 menu_color_changed_cb (glColorComboMenu   *object,
86                        guint               color,
87                        gboolean            is_default,
88                        glColorCombo       *this);
89
90 static void
91 menu_selection_done_cb (GtkMenuShell      *object,
92                         glColorCombo      *this);
93
94
95 /*****************************************************************************/
96 /* Object infrastructure.                                                    */
97 /*****************************************************************************/
98 G_DEFINE_TYPE (glColorCombo, gl_color_combo, GTK_TYPE_TOGGLE_BUTTON);
99
100
101 /*****************************************************************************/
102 /* Class Init Function.                                                      */
103 /*****************************************************************************/
104 static void
105 gl_color_combo_class_init (glColorComboClass *class)
106 {
107         GObjectClass       *gobject_class = (GObjectClass *) class;
108         GtkWidgetClass     *widget_class  = (GtkWidgetClass *) class;
109         glColorComboClass  *object_class  = (glColorComboClass *) class;
110
111         gl_color_combo_parent_class = g_type_class_peek_parent (class);
112
113         gobject_class->finalize = gl_color_combo_finalize;
114
115         signals[COLOR_CHANGED] =
116                 g_signal_new ("color_changed",
117                               G_OBJECT_CLASS_TYPE (gobject_class),
118                               G_SIGNAL_RUN_LAST,
119                               G_STRUCT_OFFSET (glColorComboClass, color_changed),
120                               NULL, NULL,
121                               gl_marshal_VOID__UINT_BOOLEAN,
122                               G_TYPE_NONE,
123                               2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
124
125 }
126
127
128 /*****************************************************************************/
129 /* Object Instance Init Function.                                            */
130 /*****************************************************************************/
131 static void
132 gl_color_combo_init (glColorCombo *this)
133 {
134         GtkWidget *hbox;
135         GtkWidget *arrow;
136
137         this->priv = g_new0 (glColorComboPrivate, 1);
138
139         hbox = gtk_hbox_new (FALSE, 3);
140         gtk_container_add (GTK_CONTAINER (this), hbox);
141         
142         this->priv->swatch = gl_color_swatch_new (IMAGE_W, IMAGE_H, GL_COLOR_NONE);
143         gtk_box_pack_start (GTK_BOX (hbox), this->priv->swatch, FALSE, FALSE, 0);
144
145         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
146         gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
147
148         g_signal_connect (this, "button_press_event",
149                           G_CALLBACK(button_press_event_cb), this);
150 }
151
152
153 /*****************************************************************************/
154 /* Finalize Method.                                                          */
155 /*****************************************************************************/
156 static void
157 gl_color_combo_finalize (GObject *object)
158 {
159         glColorCombo    *this;
160
161         g_return_if_fail (object && IS_GL_COLOR_COMBO (object));
162         this = GL_COLOR_COMBO (object);
163
164         g_object_ref_sink (this->priv->menu);
165         g_free (this->priv);
166
167         G_OBJECT_CLASS (gl_color_combo_parent_class)->finalize (object);
168 }
169
170
171 /*****************************************************************************/
172 /** New Object Generator.                                                    */
173 /*****************************************************************************/
174 GtkWidget *
175 gl_color_combo_new (const gchar  *default_label,
176                     guint         default_color,
177                     guint         color)
178 {
179         glColorCombo *this;
180         GdkPixbuf    *pixbuf;
181         GtkWidget    *wimage;
182
183         this = g_object_new (TYPE_GL_COLOR_COMBO, NULL);
184
185         if (!default_label)
186         {
187                 default_label = _("Default Color");
188         }
189
190         this->priv->default_color = default_color;
191         this->priv->color = color;
192
193         gl_color_swatch_set_color (GL_COLOR_SWATCH (this->priv->swatch), color);
194
195         this->priv->menu = gl_color_combo_menu_new (default_label,
196                                                     color);
197         gtk_widget_show_all (this->priv->menu);
198
199         g_signal_connect (this->priv->menu, "color_changed",
200                           G_CALLBACK (menu_color_changed_cb), this);
201         g_signal_connect (this->priv->menu, "selection_done",
202                           G_CALLBACK (menu_selection_done_cb), this);
203
204         return GTK_WIDGET (this);
205 }
206
207
208 /*****************************************************************************/
209 /* Set color.                                                                */
210 /*****************************************************************************/
211 void
212 gl_color_combo_set_color (glColorCombo  *this,
213                           guint          color)
214 {
215         this->priv->color = color;
216
217         gl_color_swatch_set_color (GL_COLOR_SWATCH (this->priv->swatch), color);
218 }
219
220
221 /*****************************************************************************/
222 /* Set to default color.                                                     */
223 /*****************************************************************************/
224 void
225 gl_color_combo_set_to_default (glColorCombo  *this)
226 {
227         gl_color_combo_set_color (this, this->priv->default_color);
228 }
229
230 /*****************************************************************************/
231 /* Get color.                                                                */
232 /*****************************************************************************/
233 guint
234 gl_color_combo_get_color (glColorCombo  *this,
235                           gboolean      *is_default)
236 {
237         if (is_default)
238         {
239                 *is_default = this->priv->is_default_flag;
240         }
241
242         return this->priv->color;
243 }
244
245
246 /*****************************************************************************/
247 /* Menu positioning function.                                                */
248 /*****************************************************************************/
249 static void
250 menu_position_function (GtkMenu  *menu,
251                         gint     *x,
252                         gint     *y,
253                         gboolean *push_in,
254                         gpointer  user_data)
255 {
256         glColorCombo *this = GL_COLOR_COMBO (user_data);
257         gint          x1, y1;
258         gint          menu_h, menu_w;
259
260         gdk_window_get_origin (GTK_WIDGET (this)->window, &x1, &y1);
261         *x = x1 + GTK_WIDGET (this)->allocation.x;
262         *y = y1 + GTK_WIDGET (this)->allocation.y +
263                 GTK_WIDGET (this)->allocation.height;
264                 
265         menu_h = this->priv->menu->allocation.height;
266         menu_w = this->priv->menu->allocation.width;
267
268         if ((*y + menu_h) > gdk_screen_height ())
269         {
270                 *y = y1 + GTK_WIDGET (this)->allocation.y - menu_h;
271                 if ( *y < 0 )
272                 {
273                         *y = gdk_screen_height () - menu_h;
274                 }
275         }
276
277         if ((*x + menu_w) > gdk_screen_width ())
278         {
279                 *x = gdk_screen_width () - menu_w;
280         }
281
282         *push_in = TRUE;
283 }
284
285
286 /*****************************************************************************/
287 /* Button "button_press_event" callback.                                     */
288 /*****************************************************************************/
289 static gboolean
290 button_press_event_cb (GtkWidget      *widget,
291                        GdkEventButton *event,
292                        glColorCombo   *this)
293 {
294         switch (event->button)
295         {
296
297         case 1:
298                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), TRUE);
299
300                 gtk_menu_popup (GTK_MENU (this->priv->menu),
301                                 NULL, NULL,
302                                 menu_position_function, this,
303                                 event->button, event->time);
304                 break;
305
306         default:
307                 break;
308
309         }
310
311         return FALSE;
312 }
313
314
315 /*****************************************************************************/
316 /* Menu "color changed" callback.                                            */
317 /*****************************************************************************/
318 static void
319 menu_color_changed_cb (glColorComboMenu     *object,
320                        guint                 color,
321                        gboolean              is_default,
322                        glColorCombo         *this)
323 {
324         if (is_default)
325         {
326                 this->priv->color = this->priv->default_color;
327         }
328         else
329         {
330                 this->priv->color = color;
331         }
332         this->priv->is_default_flag = is_default;
333
334         gl_color_swatch_set_color (GL_COLOR_SWATCH (this->priv->swatch),
335                                    this->priv->color);
336
337         g_signal_emit (this, signals[COLOR_CHANGED], 0,
338                        this->priv->color,
339                        this->priv->is_default_flag);
340 }
341
342
343 /*****************************************************************************/
344 /* Menu "color changed" callback.                                            */
345 /*****************************************************************************/
346 static void
347 menu_selection_done_cb (GtkMenuShell         *object,
348                         glColorCombo         *this)
349 {
350         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), FALSE);
351 }
352
353
354
355 /*
356  * Local Variables:       -- emacs
357  * mode: C                -- emacs
358  * c-basic-offset: 8      -- emacs
359  * tab-width: 8           -- emacs
360  * indent-tabs-mode: nil  -- emacs
361  * End:                   -- emacs
362  */