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-history-model.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 /* xgettext: no-c-format */
117 { GL_COLOR (230, 230, 230), N_("10% Gray") },
118 /* xgettext: no-c-format */
119 { GL_COLOR (192, 192, 192), N_("25% Gray") },
120 /* xgettext: no-c-format */
121 { GL_COLOR (153, 153, 153), N_("40% Gray") },
122 /* xgettext: no-c-format */
123 { GL_COLOR (128, 128, 128), N_("50% Gray") },
124 /* xgettext: no-c-format */
125 { GL_COLOR (102, 102, 102), N_("60% Gray") },
126 { GL_COLOR ( 0, 0, 0), N_("Black") },
127
128 };
129
130 static glColorHistoryModel *custom_color_history = NULL;
131
132
133 /*===========================================*/
134 /* Local function prototypes */
135 /*===========================================*/
136
137 static void gl_color_combo_menu_finalize (GObject *object);
138
139 static void load_custom_color_history (glColorComboMenu *this);
140
141 static gboolean map_event_cb (GtkWidget *widget,
142 GdkEventAny *event);
143
144 static void default_menu_item_activate_cb (glColorComboMenu *this);
145 static void custom_menu_item_activate_cb (glColorComboMenu *this);
146
147 static void palette_menu_item_activate_cb (GtkMenuItem *item,
148 glColorComboMenu *this);
149
150 static void history_menu_item_activate_cb (GtkMenuItem *item,
151 glColorComboMenu *this);
152
153
154 /****************************************************************************/
155 /* Boilerplate Object stuff. */
156 /****************************************************************************/
G_DEFINE_TYPE(glColorComboMenu,gl_color_combo_menu,GTK_TYPE_MENU)157 G_DEFINE_TYPE (glColorComboMenu, gl_color_combo_menu, GTK_TYPE_MENU)
158
159
160 /*****************************************************************************/
161 /* Class Init Function. */
162 /*****************************************************************************/
163 static void
164 gl_color_combo_menu_class_init (glColorComboMenuClass *class)
165 {
166 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
167 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
168
169 gl_color_combo_menu_parent_class = g_type_class_peek_parent (class);
170
171 gobject_class->finalize = gl_color_combo_menu_finalize;
172
173 widget_class->map_event = map_event_cb;
174
175 signals[COLOR_CHANGED] =
176 g_signal_new ("color_changed",
177 G_OBJECT_CLASS_TYPE (gobject_class),
178 G_SIGNAL_RUN_LAST,
179 G_STRUCT_OFFSET (glColorComboMenuClass, color_changed),
180 NULL, NULL,
181 gl_marshal_VOID__UINT_BOOLEAN,
182 G_TYPE_NONE,
183 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
184 }
185
186
187 /*****************************************************************************/
188 /* Object Instance Init Function. */
189 /*****************************************************************************/
190 static void
gl_color_combo_menu_init(glColorComboMenu * this)191 gl_color_combo_menu_init (glColorComboMenu *this)
192 {
193 GtkWidget *separator_menu_item;
194 gint i, i_row, i_col;
195 GtkWidget *palette_menu_item;
196
197
198 /*
199 * Initialize history, if needed.
200 */
201 if ( !custom_color_history )
202 {
203 custom_color_history = gl_color_history_model_new (PALETTE_COLS);
204 }
205
206
207 this->priv = g_new0 (glColorComboMenuPrivate, 1);
208
209 this->priv->default_menu_item = gtk_menu_item_new_with_label ("");
210 gtk_menu_attach (GTK_MENU (this), this->priv->default_menu_item,
211 0, PALETTE_COLS, ROW_DEFAULT, ROW_DEFAULT+1);
212
213 separator_menu_item = gtk_separator_menu_item_new ();
214 gtk_menu_attach (GTK_MENU (this), separator_menu_item,
215 0, PALETTE_COLS, ROW_SEP_1, ROW_SEP_1+1);
216
217 for ( i=0; i < G_N_ELEMENTS(color_table); i++ )
218 {
219
220 i_row = i / PALETTE_COLS;
221 i_col = i % PALETTE_COLS;
222
223 palette_menu_item = gl_color_combo_color_menu_item_new (i,
224 color_table[i].color,
225 gettext (color_table[i].name));
226 g_signal_connect (palette_menu_item, "activate",
227 G_CALLBACK (palette_menu_item_activate_cb), this);
228
229 gtk_menu_attach (GTK_MENU (this), palette_menu_item,
230 i_col, i_col+1,
231 ROW_PALETTE+i_row, ROW_PALETTE+i_row+1);
232 }
233
234 separator_menu_item = gtk_separator_menu_item_new ();
235 gtk_menu_attach (GTK_MENU (this), separator_menu_item,
236 0, PALETTE_COLS, ROW_SEP_2, ROW_SEP_2+1);
237
238 for ( i=0; i < PALETTE_COLS; i++ )
239 {
240 this->priv->history_menu_item[i] =
241 gl_color_combo_color_menu_item_new (i, 0, NULL);
242 gtk_widget_set_sensitive (this->priv->history_menu_item[i], FALSE);
243 g_signal_connect (this->priv->history_menu_item[i], "activate",
244 G_CALLBACK (history_menu_item_activate_cb), this);
245 gtk_menu_attach (GTK_MENU (this), this->priv->history_menu_item[i],
246 i, i+1,
247 ROW_HISTORY, ROW_HISTORY+1);
248 }
249
250 separator_menu_item = gtk_separator_menu_item_new ();
251 gtk_menu_attach (GTK_MENU (this), separator_menu_item,
252 0, PALETTE_COLS, ROW_SEP_3, ROW_SEP_3+1);
253
254 this->priv->custom_menu_item = gtk_menu_item_new_with_label (_("Custom Color"));
255 gtk_menu_attach (GTK_MENU (this), this->priv->custom_menu_item,
256 0, PALETTE_COLS, ROW_CUSTOM, ROW_CUSTOM+1);
257
258 g_signal_connect_swapped (this->priv->default_menu_item, "activate",
259 G_CALLBACK (default_menu_item_activate_cb), this);
260 g_signal_connect_swapped (this->priv->custom_menu_item, "activate",
261 G_CALLBACK (custom_menu_item_activate_cb), this);
262
263 }
264
265
266 /*****************************************************************************/
267 /* Finalize Method. */
268 /*****************************************************************************/
269 static void
gl_color_combo_menu_finalize(GObject * object)270 gl_color_combo_menu_finalize (GObject *object)
271 {
272 glColorComboMenu *this = GL_COLOR_COMBO_MENU (object);
273
274 g_return_if_fail (object != NULL);
275 g_return_if_fail (GL_IS_COLOR_COMBO_MENU (object));
276
277 g_free (this->priv);
278
279 G_OBJECT_CLASS (gl_color_combo_menu_parent_class)->finalize (object);
280 }
281
282
283 /*****************************************************************************/
284 /** New Object Generator. */
285 /*****************************************************************************/
286 GtkWidget *
gl_color_combo_menu_new(const gchar * default_label,guint color)287 gl_color_combo_menu_new (const gchar *default_label,
288 guint color)
289 {
290 glColorComboMenu *this;
291
292 this = g_object_new (gl_color_combo_menu_get_type (), NULL);
293
294 gtk_label_set_text ( GTK_LABEL (gtk_bin_get_child (GTK_BIN (this->priv->default_menu_item))),
295 default_label);
296
297 this->priv->color = color;
298
299 return GTK_WIDGET (this);
300 }
301
302
303 /*****************************************************************************/
304 /* Load menu with custom color history. */
305 /*****************************************************************************/
306 static void
load_custom_color_history(glColorComboMenu * this)307 load_custom_color_history (glColorComboMenu *this)
308 {
309 guint i;
310 guint color;
311 gchar *tip;
312
313 for ( i=0; i < PALETTE_COLS; i++ )
314 {
315 color = gl_color_history_model_get_color (custom_color_history, i);
316
317 if (color)
318 {
319 tip = g_strdup_printf (_("Custom Color #%u"), i+1);
320
321 gl_color_combo_color_menu_item_set_color (GL_COLOR_COMBO_COLOR_MENU_ITEM (this->priv->history_menu_item[i]),
322 i,
323 color,
324 tip);
325 g_free (tip);
326 gtk_widget_set_sensitive (this->priv->history_menu_item[i], TRUE);
327 }
328 }
329 }
330
331
332 /*****************************************************************************/
333 /* Map event callback. */
334 /*****************************************************************************/
335 static gboolean
map_event_cb(GtkWidget * widget,GdkEventAny * event)336 map_event_cb (GtkWidget *widget,
337 GdkEventAny *event)
338 {
339 glColorComboMenu *this = GL_COLOR_COMBO_MENU (widget);
340
341 load_custom_color_history (this);
342
343 return FALSE;
344 }
345
346
347 /*****************************************************************************/
348 /* "Default" menu_item activate callback. */
349 /*****************************************************************************/
350 static void
default_menu_item_activate_cb(glColorComboMenu * this)351 default_menu_item_activate_cb (glColorComboMenu *this)
352 {
353 g_signal_emit (this, signals[COLOR_CHANGED], 0,
354 NULL, TRUE);
355
356 gtk_widget_hide (GTK_WIDGET (this));
357 }
358
359
360 /*****************************************************************************/
361 /* "Custom color" menu_item activate callback. */
362 /*****************************************************************************/
363 static void
custom_menu_item_activate_cb(glColorComboMenu * this)364 custom_menu_item_activate_cb (glColorComboMenu *this)
365 {
366 GtkWidget *custom_dialog;
367 GtkWidget *colorsel;
368 gint response;
369 GdkColor color;
370
371 gtk_widget_hide (GTK_WIDGET (this));
372
373 custom_dialog = gtk_color_selection_dialog_new (_("Custom Color"));
374
375 colorsel = gtk_color_selection_dialog_get_color_selection (GTK_COLOR_SELECTION_DIALOG (custom_dialog));
376 color.red = GL_COLOR_F_RED (this->priv->color) * 65535;
377 color.green = GL_COLOR_F_GREEN (this->priv->color) * 65535;
378 color.blue = GL_COLOR_F_BLUE (this->priv->color) * 65535;
379
380 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel),
381 &color);
382
383 response = gtk_dialog_run (GTK_DIALOG (custom_dialog));
384
385 switch (response) {
386
387 case GTK_RESPONSE_OK:
388 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel),
389 &color);
390 this->priv->color = GL_COLOR ((color.red >>8),
391 (color.green >>8),
392 (color.blue >>8));
393
394 gl_color_history_model_add_color (custom_color_history,
395 this->priv->color);
396
397 g_signal_emit (this, signals[COLOR_CHANGED], 0,
398 this->priv->color, FALSE);
399
400 gtk_widget_destroy (custom_dialog);
401 break;
402 default:
403 gtk_widget_destroy (custom_dialog);
404 break;
405 }
406 }
407
408
409 /*****************************************************************************/
410 /* Palette color changed callback. */
411 /*****************************************************************************/
412 static void
palette_menu_item_activate_cb(GtkMenuItem * item,glColorComboMenu * this)413 palette_menu_item_activate_cb (GtkMenuItem *item,
414 glColorComboMenu *this)
415 {
416 gint i;
417
418 i = gl_color_combo_color_menu_item_get_id (GL_COLOR_COMBO_COLOR_MENU_ITEM (item));
419
420 this->priv->color = color_table[i].color;
421
422 g_signal_emit (this, signals[COLOR_CHANGED], 0,
423 this->priv->color, FALSE);
424
425 gtk_widget_hide (GTK_WIDGET (this));
426 }
427
428 /*****************************************************************************/
429 /* History color menu item callback. */
430 /*****************************************************************************/
431 static void
history_menu_item_activate_cb(GtkMenuItem * item,glColorComboMenu * this)432 history_menu_item_activate_cb (GtkMenuItem *item,
433 glColorComboMenu *this)
434 {
435 gint i;
436
437 i = gl_color_combo_color_menu_item_get_id (GL_COLOR_COMBO_COLOR_MENU_ITEM (item));
438
439 this->priv->color = gl_color_history_model_get_color (custom_color_history, i);
440
441 g_signal_emit (this, signals[COLOR_CHANGED], 0,
442 this->priv->color, FALSE);
443
444 gtk_widget_hide (GTK_WIDGET (this));
445 }
446
447
448
449 /*
450 * Local Variables: -- emacs
451 * mode: C -- emacs
452 * c-basic-offset: 8 -- emacs
453 * tab-width: 8 -- emacs
454 * indent-tabs-mode: nil -- emacs
455 * End: -- emacs
456 */
457