Tizen 2.0 Release
[framework/uifw/ise-engine-anthy.git] / src / scim_anthy_color_button.cpp
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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 */