2006-04-06 [mones] 2.1.0cvs7
[claws.git] / src / gtk / colorlabel.c
index aa7c01f576566c1dc8bb12f709d62916d8fbe455..d6ae64f4b68ef47ff4cf6708d5e2cee12236fffd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2001-2003 Hiroyuki Yamamoto & The Sylpheed Claws Team
+ * Copyright (C) 2001-2006 Hiroyuki Yamamoto & The Sylpheed Claws Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 /* (alfons) - based on a contribution by Satoshi Nagayasu; revised for colorful 
 #include "defs.h"
 
 #include <glib.h>
-#include <gdk/gdkx.h>
+#include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <gtk/gtkwidget.h>
-#include <gtk/gtkpixmap.h>
+#include <gtk/gtkimage.h>
 #include <gtk/gtkmenu.h>
 #include <gtk/gtkcheckmenuitem.h>
 #include <gtk/gtklabel.h>
 #include <gtk/gtkmenuitem.h>
 #include <gtk/gtkalignment.h>
 #include <gtk/gtkhbox.h>
+#include <gtk/gtkvbox.h>
 #include <gtk/gtkwindow.h>
 #include <gtk/gtkdrawingarea.h>
 
-#include "intl.h"
 #include "colorlabel.h"
 #include "utils.h"
+#include "gtkutils.h"
+#include "prefs_common.h"
 
-static gchar *labels[] = {
+static gchar *labels[COLORLABELS] = {
        N_("Orange"),
        N_("Red") ,
        N_("Pink"),
@@ -52,6 +54,16 @@ static gchar *labels[] = {
        N_("Brown")
 };
 
+static GdkColor default_colors[COLORLABELS] = {
+       { 0, 0xffff, (0x99 << 8), 0x0 },
+       { 0, 0xffff, 0, 0 },
+       { 0, 0xffff, (0x66 << 8), 0xffff },
+       { 0, 0x0, (0xcc << 8), 0xffff },
+       { 0, 0x0, 0x0, 0xffff },
+       { 0, 0x0, (0x99 << 8), 0x0 },
+       { 0, 0x66 << 8, 0x33 << 8, 0x33 << 8 }
+};
+       
 typedef enum LabelColorChangeFlags_ {
        LCCF_COLOR = 1 << 0,
        LCCF_LABEL = 1 << 1,
@@ -63,30 +75,64 @@ typedef enum LabelColorChangeFlags_ {
 static struct 
 {
        LabelColorChangeFlags   changed; 
+       /* color here is initialized from default_colors[] at startup */
        GdkColor                color;
 
        /* XXX: note that the label member is supposed to be dynamically 
         * allocated and fffreed */
        gchar                   *label;
        GtkWidget               *widget;
-} label_colors[] = {
-       { LCCF_ALL, { 0, 0xffff, (0x99 << 8), 0x0 },            NULL, NULL },
-       { LCCF_ALL, { 0, 0xffff, 0, 0 },                        NULL, NULL },
-       { LCCF_ALL, { 0, 0xffff, (0x66 << 8), 0xffff },         NULL, NULL },
-       { LCCF_ALL, { 0, 0x0, (0xcc << 8), 0xffff },            NULL, NULL },
-       { LCCF_ALL, { 0, 0x0, 0x0, 0xffff },                    NULL, NULL },
-       { LCCF_ALL, { 0, 0x0, 0x99 << 8, 0x0 },                 NULL, NULL },
-       { LCCF_ALL, { 0, 0x66 << 8, 0x33 << 8, 0x33 << 8 },     NULL, NULL }
+} label_colors[NUM_MENUS][COLORLABELS] = {
+    {
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL }},
+    {
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL },
+       { LCCF_ALL, { 0 }, NULL, NULL }}
 };
 
-#define LABEL_COLORS_ELEMS (sizeof label_colors / sizeof label_colors[0])
+#define LABEL_COLOR_WIDTH      28
+#define LABEL_COLOR_HEIGHT     16
+
+#define LABEL_COLORS_ELEMS (sizeof label_colors[0] / sizeof label_colors[0][0])
 
 #define G_RETURN_VAL_IF_INVALID_COLOR(color, val) \
        g_return_val_if_fail((color) >= 0 && (color) < LABEL_COLORS_ELEMS, (val))
 
+#define INTCOLOR_TO_GDKCOLOR(intcolor, gdkcolor) \
+       gdkcolor.red   = ((intcolor >> 16UL) & 0xFFUL) << 8UL; \
+       gdkcolor.green = ((intcolor >>  8UL) & 0xFFUL) << 8UL; \
+       gdkcolor.blue  = ((intcolor)         & 0xFFUL) << 8UL;
+
 static void colorlabel_recreate        (gint);
 static void colorlabel_recreate_label  (gint);
 
+void colorlabel_update_colortable_from_prefs(void)
+{
+       gint i, c;
+
+       for (i = 0; i < NUM_MENUS; i++) {
+               for (c = 0; c < COLORLABELS; c++) {
+                       INTCOLOR_TO_GDKCOLOR(prefs_common.custom_colorlabel[c].color,
+                                       label_colors[i][c].color);
+                       g_free(label_colors[i][c].label);
+                       label_colors[i][c].label =
+                                       g_strdup(prefs_common.custom_colorlabel[c].label);
+               }
+       }
+}
+
+
 gint colorlabel_get_color_count(void)
 {
        return LABEL_COLORS_ELEMS;
@@ -98,15 +144,31 @@ GdkColor colorlabel_get_color(gint color_index)
 
        G_RETURN_VAL_IF_INVALID_COLOR(color_index, invalid);
 
-       return label_colors[color_index].color;
+       return label_colors[0][color_index].color;
 }
 
+GdkColor colorlabel_get_default_color(gint color_index)
+{
+       GdkColor invalid = { 0 };
+
+       G_RETURN_VAL_IF_INVALID_COLOR(color_index, invalid);
+
+       return default_colors[color_index];
+}
+               
 gchar *colorlabel_get_color_text(gint color_index)
 {
        G_RETURN_VAL_IF_INVALID_COLOR(color_index, NULL);
 
        colorlabel_recreate_label(color_index);
-       return label_colors[color_index].label;
+       return label_colors[0][color_index].label;
+}
+
+gchar *colorlabel_get_color_default_text(gint color_index)
+{
+       G_RETURN_VAL_IF_INVALID_COLOR(color_index, NULL);
+
+       return labels[color_index];
 }
 
 static gboolean colorlabel_drawing_area_expose_event_cb
@@ -117,24 +179,22 @@ static gboolean colorlabel_drawing_area_expose_event_cb
        GdkColor color;
        GdkGC *gc;
 
-       color.red   = ((c >> 16UL) & 0xFFUL) << 8UL;
-       color.green = ((c >>  8UL) & 0xFFUL) << 8UL;
-       color.blue  = ((c)         & 0xFFUL) << 8UL;
+       INTCOLOR_TO_GDKCOLOR(c, color)
 
        gdk_colormap_alloc_color(gtk_widget_get_colormap(widget), &color, FALSE, TRUE);
 
        gc = gdk_gc_new(drawable);
 
        gdk_gc_set_foreground(gc, &color);
-       gdk_draw_rectangle(drawable, gc,
-                          TRUE, 0, 0, widget->allocation.width,
-                          widget->allocation.height);
        gdk_draw_rectangle(drawable, widget->style->black_gc,
-                          FALSE, 0, 0, widget->allocation.width,
-                          widget->allocation.height);
+                          FALSE, 0, 0, widget->allocation.width - 1,
+                          widget->allocation.height - 1);
+       gdk_draw_rectangle(drawable, gc,
+                          TRUE, 1, 1, widget->allocation.width - 2,
+                          widget->allocation.height - 2);
 
        gdk_gc_unref(gc);                          
-
+       
        return FALSE;
 }
 
@@ -143,17 +203,18 @@ static GtkWidget *colorlabel_create_color_widget(GdkColor color)
        GtkWidget *widget;
 
        widget = gtk_drawing_area_new();
-       gtk_drawing_area_size(GTK_DRAWING_AREA(widget), 16, 16);
+       gtk_widget_set_size_request(widget, LABEL_COLOR_WIDTH - 2, 
+                                   LABEL_COLOR_HEIGHT - 4);
 
 #define CL(x)          (((gulong) (x) >> (gulong) 8) & 0xFFUL) 
 #define CR(r, g, b)    ((CL(r) << (gulong) 16) | \
                         (CL(g) << (gulong)  8) | \
                         (CL(b)))
 
-       gtk_signal_connect(GTK_OBJECT(widget), "expose_event", 
-                          GTK_SIGNAL_FUNC
+       g_signal_connect(G_OBJECT(widget), "expose_event", 
+                        G_CALLBACK
                                (colorlabel_drawing_area_expose_event_cb),
-                          GINT_TO_POINTER
+                        GINT_TO_POINTER
                                ((gint)CR(color.red, color.green, color.blue)));
 
        return widget;
@@ -166,7 +227,7 @@ gboolean colorlabel_changed(void)
        gint n;
 
        for (n = 0; n < LABEL_COLORS_ELEMS; n++) {
-               if (label_colors[n].changed) 
+               if (label_colors[0][n].changed) 
                        return TRUE;
        }
 
@@ -179,29 +240,36 @@ gboolean colorlabel_changed(void)
 static void colorlabel_recreate_color(gint color)
 {
        GtkWidget *widget;
+       int i;
+       
+       for (i = 0; i < NUM_MENUS; i++) {
+               if (!(label_colors[i][color].changed & LCCF_COLOR))
+                       continue;
 
-       if (!(label_colors[color].changed & LCCF_COLOR))
-               return;
-
-       widget = colorlabel_create_color_widget(label_colors[color].color);
-       g_return_if_fail(widget);
+               widget = colorlabel_create_color_widget(label_colors[i][color].color);
+               g_return_if_fail(widget);
 
-       if (label_colors[color].widget) 
-               gtk_widget_destroy(label_colors[color].widget);
+               if (label_colors[i][color].widget) 
+                       gtk_widget_destroy(label_colors[i][color].widget);
 
-       label_colors[color].widget = widget;            
-       label_colors[color].changed &= ~LCCF_COLOR;
+               label_colors[i][color].widget = widget;         
+               label_colors[i][color].changed &= ~LCCF_COLOR;
+       }
 }
 
 static void colorlabel_recreate_label(gint color)
 {
-       if (!label_colors[color].changed & LCCF_LABEL)
-               return;
+       int i;
+       
+       for (i = 0; i < NUM_MENUS; i++) {
+               if (!label_colors[i][color].changed & LCCF_LABEL)
+                       continue;
 
-       if (label_colors[color].label == NULL) 
-               label_colors[color].label = g_strdup(gettext(labels[color]));
+               if (label_colors[i][color].label == NULL) 
+                       label_colors[i][color].label = g_strdup(gettext(labels[color]));
 
-       label_colors[color].changed &= ~LCCF_LABEL;
+               label_colors[i][color].changed &= ~LCCF_LABEL;
+       }
 }
 
 /* XXX: call this function everytime when you're doing important
@@ -222,50 +290,70 @@ static void colorlabel_recreate_all(void)
 
 /* colorlabel_create_check_color_menu_item() - creates a color
  * menu item with a check box */
-GtkWidget *colorlabel_create_check_color_menu_item(gint color_index)
+GtkWidget *colorlabel_create_check_color_menu_item(gint color_index, gboolean force, gint menu_index)
 {
        GtkWidget *label; 
        GtkWidget *hbox; 
-       GtkWidget *align
+       GtkWidget *vbox
        GtkWidget *item;
-
+       gchar *accel;
+       
        G_RETURN_VAL_IF_INVALID_COLOR(color_index, NULL);
 
-       item  = gtk_check_menu_item_new();
+       item = gtk_check_menu_item_new();
 
+       if (force) {
+               label_colors[menu_index][color_index].changed |= LCCF_COLOR;
+               label_colors[menu_index][color_index].changed |= LCCF_LABEL;
+       }
        colorlabel_recreate(color_index);
 
        /* XXX: gnome-core::panel::menu.c is a great example of
         * how to create pixmap menus */
-       label = gtk_label_new(label_colors[color_index].label);
+       label = gtk_label_new(label_colors[menu_index][color_index].label);
 
-       gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
        gtk_widget_show(label);
        hbox = gtk_hbox_new(FALSE, 0);
        gtk_widget_show(hbox);
        gtk_container_add(GTK_CONTAINER(item), hbox);
 
-       align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
-       gtk_widget_show(align);
-       gtk_container_set_border_width(GTK_CONTAINER(align), 1);
+       vbox = gtk_vbox_new(TRUE, 0);
+       gtk_widget_show(vbox);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox), 1);
 
-       gtk_container_add(GTK_CONTAINER(align), label_colors[color_index].widget);
-       gtk_widget_show(label_colors[color_index].widget);
-       gtk_widget_set_usize(align, 16, 16);
+       gtk_container_add(GTK_CONTAINER(vbox),
+                         label_colors[menu_index][color_index].widget);
+       gtk_widget_show(label_colors[menu_index][color_index].widget);
 
-       gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 4);
-
+       accel = g_strdup_printf("Ctrl+%c", '1'+color_index);
+       label = gtk_label_new(accel);
+       gtk_widget_show(label);
+       gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+       g_free(accel);
+       gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 4);
        return item;
 }
 
+/* Work around a gtk bug (?): without that, the selected menu item's 
+ * colored rectangle is drawn at 0,0 in the window...
+ */
+static void refresh_menu (GtkWidget *menushell, gpointer data)
+{
+       GtkMenu *menu = (GtkMenu *)data;
+       GtkWidget *widget = gtk_menu_get_attach_widget(menu);
+       gtk_widget_hide_all(widget);
+       gtk_widget_unrealize(widget);
+       gtk_widget_show_all(widget);
+       gtk_widget_queue_draw(widget);
+}
+
 /* colorlabel_create_color_menu() - creates a color menu without 
  * checkitems, probably for use in combo items */
 GtkWidget *colorlabel_create_color_menu(void)
 {
        GtkWidget *label; 
-       GtkWidget *hbox; 
-       GtkWidget *align; 
        GtkWidget *item;
        GtkWidget *menu;
        gint i;
@@ -274,43 +362,47 @@ GtkWidget *colorlabel_create_color_menu(void)
 
        /* create the menu items. each item has its color code attached */
        menu = gtk_menu_new();
-       gtk_object_set_data(GTK_OBJECT(menu), "label_color_menu", menu);
+       g_object_set_data(G_OBJECT(menu), "label_color_menu", menu);
 
        item = gtk_menu_item_new_with_label(_("None"));
-       gtk_menu_append(GTK_MENU(menu), item);
-       gtk_object_set_data(GTK_OBJECT(item), "color", GUINT_TO_POINTER(0));
+       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+       g_object_set_data(G_OBJECT(item), "color", GUINT_TO_POINTER(0));
        gtk_widget_show(item);
-       
+
        /* and the color items */
        for (i = 0; i < LABEL_COLORS_ELEMS; i++) {
-               GtkWidget *widget = colorlabel_create_color_widget(label_colors[i].color);
+               GtkWidget *hbox; 
+               GtkWidget *vbox;
+               GtkWidget *widget;
 
                item  = gtk_menu_item_new();
-               gtk_object_set_data(GTK_OBJECT(item), "color", GUINT_TO_POINTER(i + 1));
+               g_object_set_data(G_OBJECT(item), "color",
+                                 GUINT_TO_POINTER(i + 1));
 
-               label = gtk_label_new(label_colors[i].label);
+               label = gtk_label_new(label_colors[0][i].label);
                
-               gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
                gtk_widget_show(label);
                hbox = gtk_hbox_new(FALSE, 0);
                gtk_widget_show(hbox);
                gtk_container_add(GTK_CONTAINER(item), hbox);
 
-               align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
-               gtk_widget_show(align);
-               gtk_container_set_border_width(GTK_CONTAINER(align), 1);
+               vbox = gtk_vbox_new(TRUE, 0);
+               gtk_widget_show(vbox);
+               gtk_container_set_border_width(GTK_CONTAINER(vbox), 1);
 
-               gtk_container_add(GTK_CONTAINER(align), widget);
+               widget = colorlabel_create_color_widget(label_colors[0][i].color);
                gtk_widget_show(widget);
-               gtk_widget_set_usize(align, 16, 16);
+               gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0);
 
-               gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0);
+               gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
                gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 4);
                
-               gtk_menu_append(GTK_MENU(menu), item);
+               gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
                gtk_widget_show(item);
        }
-
+       
+       g_signal_connect(G_OBJECT(menu), "selection-done", 
+                       G_CALLBACK(refresh_menu), menu);
        gtk_widget_show(menu);
 
        return menu;
@@ -319,14 +411,10 @@ GtkWidget *colorlabel_create_color_menu(void)
 guint colorlabel_get_color_menu_active_item(GtkWidget *menu)
 {
        GtkWidget *menuitem;
-       guint      color;
+       guint color;
 
-       g_return_val_if_fail
-               (gtk_object_get_data(GTK_OBJECT(menu), "label_color_menu"), 0);
        menuitem = gtk_menu_get_active(GTK_MENU(menu));
        color = GPOINTER_TO_UINT
-               (gtk_object_get_data(GTK_OBJECT(menuitem), "color"));
+               (g_object_get_data(G_OBJECT(menuitem), "color"));
        return color;
 }
-
-