1 /*
2 * Copyright (C) 2005 Hiroyuki Ikezoe <poincare@ikezoe.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 /*
19 * The original code is gimpfgbgeditor.c in GIMP-2.3.2.
20 * Copyright (C) 2004 Michael Natterer <mitch@gimp.org>
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28
29 #include "scim_anthy_color_button.h"
30 #include "scim_anthy_intl.h"
31
32
33 enum
34 {
35 PROP_0,
36 PROP_ACTIVE_COLOR
37 };
38
39 enum
40 {
41 COLOR_CHANGED,
42 LAST_SIGNAL
43 };
44
45 typedef enum
46 {
47 INVALID_AREA,
48 FOREGROUND_AREA,
49 BACKGROUND_AREA,
50 SWAP_AREA,
51 DEFAULT_AREA
52 } FgBgTarget;
53
54
55 #define WIDGET_WIDTH 32
56 #define WIDGET_HEIGHT 32
57
58 static void scim_anthy_color_button_class_init (ScimAnthyColorButtonClass *klass);
59 static void scim_anthy_color_button_init (ScimAnthyColorButton *object);
60
61 static void scim_anthy_color_button_destroy (GtkObject *object);
62 static gboolean scim_anthy_color_button_expose (GtkWidget *widget,
63 GdkEventExpose *eevent);
64 static gboolean scim_anthy_color_button_button_press (GtkWidget *widget,
65 GdkEventButton *bevent);
66 static gboolean scim_anthy_color_button_button_release (GtkWidget *widget,
67 GdkEventButton *bevent);
68
69
70 static guint button_signals[LAST_SIGNAL] = { 0 };
71
72 static GtkDrawingAreaClass *parent_class = NULL;
73
74 GType
scim_anthy_color_button_get_type(void)75 scim_anthy_color_button_get_type (void)
76 {
77 static GType type = 0;
78
79 if (!type) {
80 static const GTypeInfo info = {
81 sizeof (ScimAnthyColorButtonClass),
82 NULL, /* base_init */
83 NULL, /* base_finalize */
84 (GClassInitFunc) scim_anthy_color_button_class_init,
85 NULL, /* class_finalize */
86 NULL, /* class_data */
87 sizeof (ScimAnthyColorButton),
88 0, /* n_preallocs */
89 (GInstanceInitFunc) scim_anthy_color_button_init,
90 };
91
92 type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
93 "ScimAnthyColorButton",
94 &info, (GTypeFlags) 0);
95 }
96
97 return type;
98 }
99
100 static void
scim_anthy_color_button_class_init(ScimAnthyColorButtonClass * klass)101 scim_anthy_color_button_class_init (ScimAnthyColorButtonClass *klass)
102 {
103 GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
104 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
105
106 parent_class = (GtkDrawingAreaClass *) g_type_class_peek_parent (klass);
107
108 button_signals[COLOR_CHANGED] =
109 g_signal_new ("color-changed",
110 G_TYPE_FROM_CLASS (klass),
111 G_SIGNAL_RUN_FIRST,
112 G_STRUCT_OFFSET (ScimAnthyColorButtonClass, color_changed),
113 NULL, NULL,
114 g_cclosure_marshal_VOID__VOID,
115 G_TYPE_NONE, 0);
116
117 gtk_object_class->destroy = scim_anthy_color_button_destroy;
118
119 widget_class->expose_event = scim_anthy_color_button_expose;
120 widget_class->button_press_event = scim_anthy_color_button_button_press;
121 widget_class->button_release_event = scim_anthy_color_button_button_release;
122 }
123
124 static void
scim_anthy_color_button_init(ScimAnthyColorButton * object)125 scim_anthy_color_button_init (ScimAnthyColorButton *object)
126 {
127 /*set default color */
128 gdk_color_parse ("#000000", &object->fg_color);
129 gdk_color_parse ("#ffffff", &object->bg_color);
130
131 gtk_widget_add_events (GTK_WIDGET (object),
132 GDK_BUTTON_PRESS_MASK |
133 GDK_BUTTON_RELEASE_MASK);
134 }
135
136
137 static void
scim_anthy_color_button_destroy(GtkObject * object)138 scim_anthy_color_button_destroy (GtkObject *object)
139 {
140 ScimAnthyColorButton *button = SCIM_ANTHY_COLOR_BUTTON (object);
141
142 if (button->render_buf) {
143 g_free (button->render_buf);
144 button->render_buf = NULL;
145 button->render_buf_size = 0;
146 }
147
148 if (button->swap_icon) {
149 g_object_unref (button->swap_icon);
150 button->swap_icon = NULL;
151 }
152
153 GTK_OBJECT_CLASS (parent_class)->destroy (object);
154 }
155
156 static void
scim_anthy_color_button_draw_rect(ScimAnthyColorButton * button,GdkDrawable * drawable,GdkGC * gc,gint x,gint y,gint width,gint height,GdkColor * color)157 scim_anthy_color_button_draw_rect (ScimAnthyColorButton *button,
158 GdkDrawable *drawable,
159 GdkGC *gc,
160 gint x,
161 gint y,
162 gint width,
163 gint height,
164 GdkColor *color)
165 {
166 gint rowstride;
167 guchar r, g, b;
168 gint xx, yy;
169 guchar *bp;
170
171 g_return_if_fail (width > 0 && height > 0);
172
173 r = (color->red >> 8);
174 g = (color->green >> 8);
175 b = (color->blue >> 8);
176
177 rowstride = 3 * ((width + 3) & -4);
178
179 if (! button->render_buf || button->render_buf_size < height * rowstride) {
180 button->render_buf_size = rowstride * height;
181
182 g_free (button->render_buf);
183 button->render_buf = (guchar *) g_malloc (button->render_buf_size);
184 }
185
186 bp = button->render_buf;
187 for (xx = 0; xx < width; xx++) {
188 *bp++ = r;
189 *bp++ = g;
190 *bp++ = b;
191 }
192
193 bp = button->render_buf;
194
195 for (yy = 1; yy < height; yy++) {
196 bp += rowstride;
197 memcpy (bp, button->render_buf, rowstride);
198 }
199
200 gdk_draw_rgb_image (drawable, gc, x, y, width, height,
201 GDK_RGB_DITHER_MAX,
202 button->render_buf,
203 rowstride);
204 }
205
206 static gboolean
scim_anthy_color_button_expose(GtkWidget * widget,GdkEventExpose * eevent)207 scim_anthy_color_button_expose (GtkWidget *widget,
208 GdkEventExpose *eevent)
209 {
210 ScimAnthyColorButton *button = SCIM_ANTHY_COLOR_BUTTON (widget);
211 gint width, height;
212 gint swap_w = 0, swap_h = 0;
213 gint rect_w, rect_h;
214
215 if (!GTK_WIDGET_DRAWABLE (widget))
216 return FALSE;
217
218 width = widget->allocation.width;
219 height = widget->allocation.height;
220
221 /* draw the swap colors pixbuf */
222 if (!button->swap_icon) {
223 button->swap_icon
224 = gdk_pixbuf_new_from_file (SCIM_ICONDIR"/scim-anthy-swap-colors.png",
225 NULL);
226 }
227
228 if (button->swap_icon) {
229 swap_w = gdk_pixbuf_get_width (button->swap_icon);
230 swap_h = gdk_pixbuf_get_height (button->swap_icon);
231 }
232
233 if (swap_w < width / 2 && swap_h < height / 2) {
234 gdk_draw_pixbuf (widget->window, NULL, button->swap_icon,
235 0, 0, width - swap_w, 0, swap_w, swap_h,
236 GDK_RGB_DITHER_NORMAL, 0, 0);
237 } else {
238 swap_w = swap_h = 0;
239 }
240
241 rect_h = height - swap_h - 2;
242 rect_w = width - swap_w - 4;
243
244 if (rect_h > (height * 3 / 4)) {
245 rect_w = MAX (rect_w - (rect_h - ((height * 3 / 4))),
246 width * 2 / 3);
247 }
248
249 button->rect_width = rect_w;
250 button->rect_height = rect_h;
251
252
253 /* draw the background area */
254 scim_anthy_color_button_draw_rect (button,
255 widget->window,
256 widget->style->fg_gc[0],
257 (width - rect_w),
258 (height - rect_h),
259 rect_w, rect_h,
260 &button->bg_color);
261
262 gtk_paint_shadow (widget->style, widget->window, GTK_STATE_NORMAL,
263 GTK_SHADOW_IN,
264 NULL, widget, NULL,
265 (width - rect_w),
266 (height - rect_h),
267 rect_w, rect_h);
268
269
270 /* draw the foreground area */
271 scim_anthy_color_button_draw_rect (button,
272 widget->window,
273 widget->style->fg_gc[0],
274 0, 0,
275 rect_w, rect_h,
276 &button->fg_color);
277
278 gtk_paint_shadow (widget->style, widget->window, GTK_STATE_NORMAL,
279 GTK_SHADOW_IN,
280 NULL, widget, NULL,
281 0, 0,
282 rect_w, rect_h);
283
284 return TRUE;
285 }
286
287 static FgBgTarget
scim_anthy_color_button_target(ScimAnthyColorButton * button,gint x,gint y)288 scim_anthy_color_button_target (ScimAnthyColorButton *button,
289 gint x,
290 gint y)
291 {
292 gint width = GTK_WIDGET (button)->allocation.width;
293 gint height = GTK_WIDGET (button)->allocation.height;
294 gint rect_w = button->rect_width;
295 gint rect_h = button->rect_height;
296
297 if (x > 0 && x < rect_w && y > 0 && y < rect_h)
298 return FOREGROUND_AREA;
299 else if (x > (width - rect_w) && x < width &&
300 y > (height - rect_h) && y < height)
301 return BACKGROUND_AREA;
302 else if (x > 0 && x < (width - rect_w) &&
303 y > rect_h && y < height)
304 return DEFAULT_AREA;
305 else if (x > rect_w && x < width &&
306 y > 0 && y < (height - rect_h))
307 return SWAP_AREA;
308
309 return INVALID_AREA;
310 }
311
312 static void
scim_anthy_color_button_open_color_dialog(ScimAnthyColorButton * button,gboolean fg)313 scim_anthy_color_button_open_color_dialog (ScimAnthyColorButton *button, gboolean fg)
314 {
315 GtkWidget *dialog;
316 const gchar *title;
317 GdkColor *color;
318 gint result;
319
320 title = fg ? _("Foreground color") : _("Background color");
321 color = fg ? &button->fg_color : &button->bg_color;
322
323 dialog = gtk_color_selection_dialog_new (title);
324
325 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dialog)->colorsel),
326 color);
327 gtk_widget_show (dialog);
328
329 result = gtk_dialog_run (GTK_DIALOG (dialog));
330
331 switch (result) {
332 case GTK_RESPONSE_OK:
333 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dialog)->colorsel),
334 color);
335 g_signal_emit (button, button_signals[COLOR_CHANGED], 0);
336 break;
337 default:
338 break;
339 }
340
341 gtk_widget_destroy (dialog);
342 gtk_widget_queue_draw (GTK_WIDGET (button));
343 }
344
345 static void
scim_anthy_color_button_swap_color(ScimAnthyColorButton * button)346 scim_anthy_color_button_swap_color (ScimAnthyColorButton *button)
347 {
348 GdkColor tmp;
349 tmp.red = button->fg_color.red;
350 tmp.green = button->fg_color.green;
351 tmp.blue = button->fg_color.blue;
352
353 button->fg_color.red = button->bg_color.red;
354 button->fg_color.green = button->bg_color.green;
355 button->fg_color.blue = button->bg_color.blue;
356
357 button->bg_color.red = tmp.red;
358 button->bg_color.green = tmp.green;
359 button->bg_color.blue = tmp.blue;
360 g_signal_emit (button, button_signals[COLOR_CHANGED], 0);
361 }
362
363 static gboolean
scim_anthy_color_button_button_press(GtkWidget * widget,GdkEventButton * bevent)364 scim_anthy_color_button_button_press (GtkWidget *widget,
365 GdkEventButton *bevent)
366 {
367 ScimAnthyColorButton *button = SCIM_ANTHY_COLOR_BUTTON (widget);
368 if (bevent->button == 1 && bevent->type == GDK_BUTTON_PRESS) {
369 FgBgTarget target = scim_anthy_color_button_target (button,
370 (gint) bevent->x, (gint) bevent->y);
371
372 button->click_target = INVALID_AREA;
373
374 switch (target) {
375 case FOREGROUND_AREA:
376 button->click_target = FOREGROUND_AREA;
377 scim_anthy_color_button_open_color_dialog (button, TRUE);
378 break;
379
380 case BACKGROUND_AREA:
381 button->click_target = BACKGROUND_AREA;
382 scim_anthy_color_button_open_color_dialog (button, FALSE);
383 break;
384
385 case SWAP_AREA:
386 scim_anthy_color_button_swap_color (button);
387 gtk_widget_queue_draw (GTK_WIDGET (button));
388 break;
389
390 case DEFAULT_AREA:
391 break;
392
393 default:
394 break;
395 }
396 }
397
398 return FALSE;
399 }
400
401 static gboolean
scim_anthy_color_button_button_release(GtkWidget * widget,GdkEventButton * bevent)402 scim_anthy_color_button_button_release (GtkWidget *widget,
403 GdkEventButton *bevent)
404 {
405 ScimAnthyColorButton *button = SCIM_ANTHY_COLOR_BUTTON (widget);
406
407 if (bevent->button == 1) {
408 FgBgTarget target = scim_anthy_color_button_target (button,
409 (gint) bevent->x, (gint) bevent->y);
410
411 if (target == button->click_target) {
412 switch (target)
413 {
414 case FOREGROUND_AREA:
415 break;
416
417 case BACKGROUND_AREA:
418 break;
419
420 default:
421 break;
422 }
423 }
424
425 button->click_target = INVALID_AREA;
426 }
427
428 return FALSE;
429 }
430
431
432 /* public functions */
433
434 GtkWidget *
scim_anthy_color_button_new(void)435 scim_anthy_color_button_new (void)
436 {
437 return GTK_WIDGET(g_object_new (SCIM_ANTHY_TYPE_COLOR_BUTTON,
438 NULL));
439 }
440
441 gboolean
scim_anthy_color_button_get_colors(ScimAnthyColorButton * button,String * fg_value,String * bg_value)442 scim_anthy_color_button_get_colors (ScimAnthyColorButton *button,
443 String *fg_value,
444 String *bg_value)
445 {
446 gchar fg_color_str[8], bg_color_str[8];
447
448 g_snprintf (fg_color_str, G_N_ELEMENTS (fg_color_str),
449 "#%02X%02X%02X",
450 ((button->fg_color.red)>>8),
451 ((button->fg_color.green)>>8),
452 ((button->fg_color.blue)>>8));
453 g_snprintf (bg_color_str, G_N_ELEMENTS (bg_color_str),
454 "#%02X%02X%02X",
455 ((button->bg_color.red)>>8),
456 ((button->bg_color.green)>>8),
457 ((button->bg_color.blue)>>8));
458 *fg_value = String (fg_color_str);
459 *bg_value = String (bg_color_str);
460
461 return TRUE;
462 }
463
464 gboolean
scim_anthy_color_button_set_colors(ScimAnthyColorButton * button,const String & fg_value,const String & bg_value)465 scim_anthy_color_button_set_colors (ScimAnthyColorButton *button,
466 const String &fg_value,
467 const String &bg_value)
468 {
469 GdkColor fg_color, bg_color;
470 gdk_color_parse (fg_value.c_str (), &fg_color);
471 gdk_color_parse (bg_value.c_str (), &bg_color);
472 button->fg_color.red = fg_color.red;
473 button->fg_color.green = fg_color.green;
474 button->fg_color.blue = fg_color.blue;
475
476 button->bg_color.red = bg_color.red;
477 button->bg_color.green = bg_color.green;
478 button->bg_color.blue = bg_color.blue;
479
480 return TRUE;
481 }
482
483 /*
484 vi:ts=4:nowrap:ai:expandtab
485 */
486