]> git.sur5r.net Git - glabels/blob - glabels2/src/color-combo-menu.c
c96573e0d539a8665ec00fb5f019551b1ddb2e49
[glabels] / glabels2 / src / color-combo-menu.c
1 /*
2  *  color-combo-menu.c
3  *  Copyright (C) 2008  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-menu.h"
24
25 #include "marshal.h"
26 #include <glib/gi18n.h>
27 #include <gtk/gtkmenuitem.h>
28 #include <gtk/gtkseparatormenuitem.h>
29 #include <gtk/gtklabel.h>
30 #include <gtk/gtkimage.h>
31 #include <gtk/gtkcolorseldialog.h>
32 #include "color-combo-color-menu-item.h"
33 #include "color-combo-history.h"
34 #include "color.h"
35
36
37 /*===========================================*/
38 /* Private macros and constants.             */
39 /*===========================================*/
40
41 #define PALETTE_COLS     7
42 #define PALETTE_ROWS    (G_N_ELEMENTS(color_table)/PALETTE_COLS + (G_N_ELEMENTS(color_table)%PALETTE_COLS ? 1 : 0))
43
44 #define ROW_DEFAULT (0)
45 #define ROW_SEP_1   (ROW_DEFAULT + 1)
46 #define ROW_PALETTE (ROW_SEP_1   + 1)
47 #define ROW_SEP_2   (ROW_PALETTE + PALETTE_ROWS)
48 #define ROW_HISTORY (ROW_SEP_2   + 1)
49 #define ROW_SEP_3   (ROW_HISTORY + 1)
50 #define ROW_CUSTOM  (ROW_SEP_3   + 1)
51
52 /*===========================================*/
53 /* Private types                             */
54 /*===========================================*/
55
56 struct _glColorComboMenuPrivate {
57
58         GtkWidget *default_menu_item;
59         GtkWidget *custom_menu_item;
60
61         GtkWidget *history_menu_item[PALETTE_COLS];
62
63         guint      color;
64 };
65
66 enum {
67         COLOR_CHANGED,
68         LAST_SIGNAL
69 };
70
71 typedef struct {
72         guint  color;
73         gchar *name;
74 } ColorTableEntry;
75
76
77 /*===========================================*/
78 /* Private globals                           */
79 /*===========================================*/
80
81 static guint signals[LAST_SIGNAL] = {0};
82
83 static ColorTableEntry color_table[] =
84 {
85
86         { GL_COLOR (139,   0,   0), N_("Dark Red") },
87         { GL_COLOR (165,  42,  42), N_("Brown") },
88         { GL_COLOR (205, 149,  12), N_("Dark Goldenrod") },
89         { GL_COLOR (  0, 100,   0), N_("Dark Green") },
90         { GL_COLOR (  0, 139, 139), N_("Dark Cyan") },
91         { GL_COLOR (  0,   0, 128), N_("Navy Blue") },
92         { GL_COLOR (148,   0, 211), N_("Dark Violet") },
93
94         { GL_COLOR (255,   0,   0), N_("Red") },
95         { GL_COLOR (255, 165,   0), N_("Orange") },
96         { GL_COLOR (205, 205,   0), N_("Dark Yellow") },
97         { GL_COLOR (  0, 205,   0), N_("Medium green") },
98         { GL_COLOR ( 64, 224, 208), N_("Turquoise") },
99         { GL_COLOR (  0,   0, 255), N_("Blue") },
100         { GL_COLOR (160,  32, 240), N_("Purple") },
101
102         { GL_COLOR (250, 128, 114), N_("Salmon") },
103         { GL_COLOR (255, 215,   0), N_("Gold") },
104         { GL_COLOR (255, 255,   0), N_("Yellow") },
105         { GL_COLOR (  0, 255,   0), N_("Green") },
106         { GL_COLOR (  0, 255, 255), N_("Cyan") },
107         { GL_COLOR (135, 206, 235), N_("SkyBlue") },
108         { GL_COLOR (238, 130, 238), N_("Violet") },
109
110         { GL_COLOR (255, 192, 203), N_("Pink") },
111         { GL_COLOR (255, 246, 143), N_("Khaki") },
112         { GL_COLOR (255, 255, 224), N_("Light Yellow") },
113         { GL_COLOR (144, 238, 144), N_("Light Green") },
114         { GL_COLOR (224, 255, 255), N_("Light Cyan") },
115         { GL_COLOR (198, 226, 255), N_("Slate Gray") },
116         { GL_COLOR (216, 191, 216), N_("Thistle") },
117
118         { GL_COLOR (255, 255, 255), N_("White") },
119         { GL_COLOR (230, 230, 230), N_("10% Gray") },
120         { GL_COLOR (192, 192, 192), N_("25% Gray") },
121         { GL_COLOR (153, 153, 153), N_("40% Gray") },
122         { GL_COLOR (128, 128, 128), N_("50% Gray") },
123         { GL_COLOR (102, 102, 102), N_("60% Gray") },
124         { GL_COLOR (  0,   0,   0), N_("Black") },
125
126 };
127
128 static glColorComboHistory *custom_color_history = NULL;
129
130
131 /*===========================================*/
132 /* Local function prototypes                 */
133 /*===========================================*/
134
135 static void gl_color_combo_menu_finalize  (GObject          *object);
136
137 static void load_custom_color_history     (glColorComboMenu *this);
138
139 static gboolean map_event_cb              (GtkWidget    *widget,
140                                            GdkEventAny  *event);
141
142 static void default_menu_item_activate_cb (glColorComboMenu *this);
143 static void custom_menu_item_activate_cb  (glColorComboMenu *this);
144
145 static void palette_menu_item_activate_cb (GtkMenuItem      *item,
146                                            glColorComboMenu *this);
147
148 static void history_menu_item_activate_cb (GtkMenuItem      *item,
149                                            glColorComboMenu *this);
150
151
152 /****************************************************************************/
153 /* Boilerplate Object stuff.                                                */
154 /****************************************************************************/
155 G_DEFINE_TYPE (glColorComboMenu, gl_color_combo_menu, GTK_TYPE_MENU);
156
157
158 /*****************************************************************************/
159 /* Class Init Function.                                                      */
160 /*****************************************************************************/
161 static void
162 gl_color_combo_menu_class_init (glColorComboMenuClass *class)
163 {
164         GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
165         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
166
167         gl_color_combo_menu_parent_class = g_type_class_peek_parent (class);
168
169         gobject_class->finalize = gl_color_combo_menu_finalize;
170
171         widget_class->map_event = map_event_cb;
172
173         signals[COLOR_CHANGED] =
174                 g_signal_new ("color_changed",
175                               G_OBJECT_CLASS_TYPE (gobject_class),
176                               G_SIGNAL_RUN_LAST,
177                               G_STRUCT_OFFSET (glColorComboMenuClass, color_changed),
178                               NULL, NULL,
179                               gl_marshal_VOID__UINT_BOOLEAN,
180                               G_TYPE_NONE,
181                               2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
182 }
183
184
185 /*****************************************************************************/
186 /* Object Instance Init Function.                                            */
187 /*****************************************************************************/
188 static void
189 gl_color_combo_menu_init (glColorComboMenu *this)
190 {
191         GtkWidget *separator_menu_item;
192         gint       i, i_row, i_col;
193         GtkWidget *palette_menu_item;
194
195
196         /*
197          * Initialize history, if needed.
198          */
199         if ( !custom_color_history )
200         {
201                 custom_color_history = gl_color_combo_history_new (PALETTE_COLS);
202         }
203
204
205         this->priv = g_new0 (glColorComboMenuPrivate, 1);
206
207         this->priv->default_menu_item = gtk_menu_item_new_with_label ("");
208         gtk_menu_attach (GTK_MENU (this), this->priv->default_menu_item,
209                          0, PALETTE_COLS, ROW_DEFAULT, ROW_DEFAULT+1);
210
211         separator_menu_item = gtk_separator_menu_item_new ();
212         gtk_menu_attach (GTK_MENU (this), separator_menu_item,
213                          0, PALETTE_COLS, ROW_SEP_1, ROW_SEP_1+1);
214
215         for ( i=0; i < G_N_ELEMENTS(color_table); i++ )
216         {
217
218                 i_row = i / PALETTE_COLS;
219                 i_col = i % PALETTE_COLS;
220
221                 palette_menu_item = gl_color_combo_color_menu_item_new (i,
222                                                                         color_table[i].color,
223                                                                         color_table[i].name);
224                 g_signal_connect (palette_menu_item, "activate",
225                                   G_CALLBACK (palette_menu_item_activate_cb), this);
226
227                 gtk_menu_attach (GTK_MENU (this), palette_menu_item,
228                                  i_col, i_col+1,
229                                  ROW_PALETTE+i_row, ROW_PALETTE+i_row+1);
230         }
231
232         separator_menu_item = gtk_separator_menu_item_new ();
233         gtk_menu_attach (GTK_MENU (this), separator_menu_item,
234                          0, PALETTE_COLS, ROW_SEP_2, ROW_SEP_2+1);
235
236         for ( i=0; i < PALETTE_COLS; i++ )
237         {
238                 this->priv->history_menu_item[i] =
239                         gl_color_combo_color_menu_item_new (i, 0, NULL);
240                 gtk_widget_set_sensitive (this->priv->history_menu_item[i], FALSE);
241                 g_signal_connect (this->priv->history_menu_item[i], "activate",
242                                   G_CALLBACK (history_menu_item_activate_cb), this);
243                 gtk_menu_attach (GTK_MENU (this), this->priv->history_menu_item[i],
244                                  i, i+1,
245                                  ROW_HISTORY, ROW_HISTORY+1);
246         }
247
248         separator_menu_item = gtk_separator_menu_item_new ();
249         gtk_menu_attach (GTK_MENU (this), separator_menu_item,
250                          0, PALETTE_COLS, ROW_SEP_3, ROW_SEP_3+1);
251
252         this->priv->custom_menu_item = gtk_menu_item_new_with_label (_("Custom Color"));
253         gtk_menu_attach (GTK_MENU (this), this->priv->custom_menu_item,
254                          0, PALETTE_COLS, ROW_CUSTOM, ROW_CUSTOM+1);
255
256         g_signal_connect_swapped (this->priv->default_menu_item, "activate",
257                                   G_CALLBACK (default_menu_item_activate_cb), this);
258         g_signal_connect_swapped (this->priv->custom_menu_item, "activate",
259                                   G_CALLBACK (custom_menu_item_activate_cb), this);
260
261 }
262
263
264 /*****************************************************************************/
265 /* Finalize Method.                                                          */
266 /*****************************************************************************/
267 static void
268 gl_color_combo_menu_finalize (GObject *object)
269 {
270         glColorComboMenu *this = GL_COLOR_COMBO_MENU (object);
271
272         g_return_if_fail (object != NULL);
273         g_return_if_fail (GL_IS_COLOR_COMBO_MENU (object));
274
275         g_free (this->priv);
276
277         G_OBJECT_CLASS (gl_color_combo_menu_parent_class)->finalize (object);
278 }
279
280
281 /*****************************************************************************/
282 /** New Object Generator.                                                    */
283 /*****************************************************************************/
284 GtkWidget *
285 gl_color_combo_menu_new (const gchar *default_label,
286                          guint        color)
287 {
288         glColorComboMenu *this;
289
290         this = g_object_new (gl_color_combo_menu_get_type (), NULL);
291
292         gtk_label_set_text ( GTK_LABEL (gtk_bin_get_child (GTK_BIN (this->priv->default_menu_item))),
293                             default_label);
294
295         this->priv->color = color;
296
297         return GTK_WIDGET (this);
298 }
299
300
301 /*****************************************************************************/
302 /* Load menu with custom color history.                                      */
303 /*****************************************************************************/
304 static void
305 load_custom_color_history (glColorComboMenu *this)
306 {
307         guint  i;
308         guint  color;
309         gchar *tip;
310
311         for ( i=0; i < PALETTE_COLS; i++ )
312         {
313                 color = gl_color_combo_history_get_color (custom_color_history, i);
314
315                 if (color)
316                 {
317                         tip = g_strdup_printf (_("Custom Color #%u"), i+1);
318
319                         gl_color_combo_color_menu_item_set_color (GL_COLOR_COMBO_COLOR_MENU_ITEM (this->priv->history_menu_item[i]),
320                                                                   i,
321                                                                   color,
322                                                                   tip);
323                         g_free (tip);
324                         gtk_widget_set_sensitive (this->priv->history_menu_item[i], TRUE);
325                 }
326         }
327 }
328
329
330 /*****************************************************************************/
331 /* Map event callback.                                                       */
332 /*****************************************************************************/
333 static gboolean
334 map_event_cb (GtkWidget    *widget,
335               GdkEventAny  *event)
336 {
337         glColorComboMenu *this = GL_COLOR_COMBO_MENU (widget);
338
339         load_custom_color_history (this);
340
341         return FALSE;
342 }
343
344
345 /*****************************************************************************/
346 /* "Default" menu_item activate callback.                                    */
347 /*****************************************************************************/
348 static void
349 default_menu_item_activate_cb (glColorComboMenu *this)
350 {
351         g_signal_emit (this, signals[COLOR_CHANGED], 0,
352                       NULL, TRUE);
353
354         gtk_widget_hide (GTK_WIDGET (this));
355 }
356
357
358 /*****************************************************************************/
359 /* "Custom color" menu_item activate callback.                               */
360 /*****************************************************************************/
361 static void
362 custom_menu_item_activate_cb (glColorComboMenu *this)
363 {
364         GtkWidget *custom_dialog;
365         GtkWidget *colorsel;
366         gint       response;
367         GdkColor   color;
368
369         gtk_widget_hide (GTK_WIDGET (this));
370
371         custom_dialog = gtk_color_selection_dialog_new (_("Custom Color"));
372
373         colorsel = GTK_COLOR_SELECTION_DIALOG (custom_dialog)->colorsel;
374         color.red   = GL_COLOR_F_RED   (this->priv->color) * 65535;
375         color.green = GL_COLOR_F_GREEN (this->priv->color) * 65535;
376         color.blue  = GL_COLOR_F_BLUE  (this->priv->color) * 65535;
377
378         gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel),
379                                                &color);
380
381         response = gtk_dialog_run (GTK_DIALOG (custom_dialog));
382
383         switch (response) {
384
385         case GTK_RESPONSE_OK:
386                 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel),
387                                                        &color);
388                 this->priv->color = GL_COLOR ((color.red   >>8),
389                                               (color.green >>8),
390                                               (color.blue  >>8));
391
392                 gl_color_combo_history_add_color (custom_color_history,
393                                                   this->priv->color);
394
395                 g_signal_emit (this, signals[COLOR_CHANGED], 0,
396                                this->priv->color, FALSE);
397
398                 gtk_widget_destroy (custom_dialog);
399                 break;
400         default:
401                 gtk_widget_destroy (custom_dialog);
402                 break;
403         }
404 }
405
406
407 /*****************************************************************************/
408 /* Palette color changed callback.                                           */
409 /*****************************************************************************/
410 static void
411 palette_menu_item_activate_cb (GtkMenuItem      *item,
412                                glColorComboMenu *this)
413 {
414         gint i;
415
416         i = gl_color_combo_color_menu_item_get_id (GL_COLOR_COMBO_COLOR_MENU_ITEM (item));
417
418         this->priv->color = color_table[i].color;
419
420         g_signal_emit (this, signals[COLOR_CHANGED], 0,
421                        this->priv->color, FALSE);
422
423         gtk_widget_hide (GTK_WIDGET (this));
424 }
425
426 /*****************************************************************************/
427 /* History color menu item callback.                                         */
428 /*****************************************************************************/
429 static void
430 history_menu_item_activate_cb (GtkMenuItem      *item,
431                                glColorComboMenu *this)
432 {
433         gint i;
434
435         i = gl_color_combo_color_menu_item_get_id (GL_COLOR_COMBO_COLOR_MENU_ITEM (item));
436
437         this->priv->color = gl_color_combo_history_get_color (custom_color_history,
438                                                               i);
439
440         g_signal_emit (this, signals[COLOR_CHANGED], 0,
441                        this->priv->color, FALSE);
442
443         gtk_widget_hide (GTK_WIDGET (this));
444 }
445
446
447
448 /*
449  * Local Variables:       -- emacs
450  * mode: C                -- emacs
451  * c-basic-offset: 8      -- emacs
452  * tab-width: 8           -- emacs
453  * indent-tabs-mode: nil  -- emacs
454  * End:                   -- emacs
455  */