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