From a56f89b81264345ee528bef6fd8008979f0487a6 Mon Sep 17 00:00:00 2001 From: Lauri Alanko Date: Thu, 7 Jan 1999 19:53:05 +0000 Subject: [PATCH] Added stuff to make gcg by default (for maintainers) Redid the indexed palette dialog to not crash, to be a bit more usable, and to be a cleaner module. A first shot at using gcg in actual practice.. If something is screwed, let me know! --- app/Makefile.am | 43 +- app/actions/help-commands.c | 28 +- app/app_procs.c | 1 + app/appenv.h | 3 +- app/colormap_dialog.gc | 28 + app/colormap_dialog.i.c | 836 ++++++++++++++++++++++++++++ app/commands.c | 28 +- app/convert.c | 3 +- app/core/gimpimage-convert.c | 3 +- app/core/gimpimage-guides.c | 13 +- app/core/gimpimage-guides.h | 11 +- app/core/gimpimage-merge.c | 13 +- app/core/gimpimage-merge.h | 11 +- app/core/gimpimage-projection.c | 13 +- app/core/gimpimage-projection.h | 11 +- app/core/gimpimage-resize.c | 13 +- app/core/gimpimage-resize.h | 11 +- app/core/gimpimage-scale.c | 13 +- app/core/gimpimage-scale.h | 11 +- app/core/gimpimage-undo-push.c | 3 +- app/core/gimpimage.c | 13 +- app/core/gimpimage.h | 11 +- app/core/gimpprojection-construct.c | 13 +- app/core/gimpprojection-construct.h | 11 +- app/dialogs/preferences-dialog.c | 1 - app/gimage.c | 17 +- app/gimp.gh | 27 + app/gimpimage-convert.c | 3 +- app/gimpimage.c | 13 +- app/gimpimage.h | 11 +- app/gimpset.c | 186 ++++++- app/gimpset.h | 8 + app/gimpsetP.h | 1 + app/gui/commands.c | 28 +- app/gui/help-commands.c | 28 +- app/gui/preferences-dialog.c | 1 - app/indexed_palette.c | 541 ------------------ app/indexed_palette.h | 26 - app/main.c | 20 + app/preferences_dialog.c | 1 - app/undo.c | 3 +- 41 files changed, 1400 insertions(+), 659 deletions(-) create mode 100644 app/colormap_dialog.gc create mode 100644 app/colormap_dialog.i.c create mode 100644 app/gimp.gh delete mode 100644 app/indexed_palette.c delete mode 100644 app/indexed_palette.h diff --git a/app/Makefile.am b/app/Makefile.am index 0d31c59404..6fca90f11b 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -87,6 +87,8 @@ gimp_SOURCES = \ color_transfer.h \ colormaps.c \ colormaps.h \ + colormap_dialog.c \ + colormap_dialog.h \ commands.c \ commands.h \ convert.c \ @@ -202,8 +204,6 @@ gimp_SOURCES = \ image_map.h \ image_render.c \ image_render.h \ - indexed_palette.c \ - indexed_palette.h \ info_dialog.c \ info_dialog.h \ info_window.c \ @@ -383,3 +383,42 @@ files: @files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \ echo $$p; \ done + +# GCG stuff + +SUFFIXES = .gc .gh + +if WITH_GCG +GCG = ../tools/gcg/gcg -I ../tools/gcg/gh +GEN_CODE = colormap_dialog.c +if WITH_GNU_MAKE +GEN_HEADER =$(subst .gc,.t.h,$(GCG_DEFS)) \ + $(subst .gc,.p.h,$(GCG_DEFS)) \ + $(subst .gc,.i.h,$(GCG_DEFS)) \ + $(subst .gc,.h,$(GCG_DEFS)) + +$(GEN_CODE): %.c: %.gc + $(GCG) -o $@ $< +else # WITH_GNU_MAKE +GEN_HEADER = # fill in here manually, if you bother +.gc.c: + $(GCG) -o $@ $< +endif # WITH_GNU_MAKE + +BUILT_SOURCES = $(GEN_CODE) $(GEN_HEADER) + +if ENABLE_GCG_DEPS +if WITH_GNU_MAKE + # dependency magic +GCGMAKEDEPEND = ../tools/gcg/gcgmakedepend +$(DEF_DEPS): .deps/%.d: %.gc + $(GCGMAKEDEPEND) $(DEF_INC) $< >$@ +# automake uses .P for .c files, we use .d for .gc files, should +# be no conflict.. +GCG_DEFS = $(subst .c,.gc,$(GEN_CODE)) +DEF_DEPS = $(patsubst %.gc,.deps/%.d,$(GCG_DEFS)) +-include $(DEF_DEPS) +endif # WITH_GNU_MAKE +endif # ENABLE_GCG_DEPS +endif # WITH_GCG +# end GCG stuff diff --git a/app/actions/help-commands.c b/app/actions/help-commands.c index 912b278b69..91722d394d 100644 --- a/app/actions/help-commands.c +++ b/app/actions/help-commands.c @@ -27,6 +27,8 @@ #include "by_color_select.h" #include "channels_dialog.h" #include "colormaps.h" +#include "colormap_dialog.i.h" +#include "color_area.h" #include "color_balance.h" #include "commands.h" #include "convert.h" @@ -49,7 +51,6 @@ #include "histogram_tool.h" #include "hue_saturation.h" #include "image_render.h" -#include "indexed_palette.h" #include "info_window.h" #include "interface.h" #include "invert.h" @@ -1028,15 +1029,30 @@ dialogs_lc_cmd_callback (GtkWidget *widget, lc_dialog_create (gdisp->gimage); } +static void +cmap_dlg_sel_cb(ColormapDialog* dlg, gpointer user_data) +{ + guchar* c; + + GimpImage* img = colormap_dialog_image(dlg); + c = &img->cmap[colormap_dialog_col_index(dlg) * 3]; + if(active_color == FOREGROUND) + palette_set_foreground (c[0], c[1], c[2]); + else if(active_color == BACKGROUND) + palette_set_background (c[0], c[1], c[2]); +} + void dialogs_indexed_palette_cmd_callback (GtkWidget *widget, gpointer client_data) { - GDisplay *gdisp; - - gdisp = gdisplay_active (); - - indexed_palette_create (gdisp->gimage); + static ColormapDialog* cmap_dlg; + if(!cmap_dlg){ + cmap_dlg = colormap_dialog_create (image_context); + colormap_dialog_connect_selected(cmap_dlg_sel_cb, NULL, + cmap_dlg); + } + gtk_widget_show(GTK_WIDGET(cmap_dlg)); } void diff --git a/app/app_procs.c b/app/app_procs.c index b3bfac31b8..b3ce2b966d 100644 --- a/app/app_procs.c +++ b/app/app_procs.c @@ -65,6 +65,7 @@ #include "xcf.h" #include "errors.h" #include "docindex.h" +#include "colormap_dialog.h" #include "config.h" diff --git a/app/appenv.h b/app/appenv.h index 9613e334b3..17e83ca4b7 100644 --- a/app/appenv.h +++ b/app/appenv.h @@ -22,7 +22,7 @@ #include "gdk/gdkx.h" #include "gtk/gtk.h" #include "gimpsetF.h" - +#include "colormap_dialog.t.h" #define DISPLAY ((Display *) GDK_DISPLAY()) /* important macros - we reuse the ones from glib */ @@ -53,7 +53,6 @@ extern int console_messages; extern int restore_session; extern int we_are_exiting; /* this is used in session_get_window_info() */ extern GimpSet* image_context; - extern MessageHandlerType message_handler; #endif /* APPENV_H */ diff --git a/app/colormap_dialog.gc b/app/colormap_dialog.gc new file mode 100644 index 0000000000..97422ff04a --- /dev/null +++ b/app/colormap_dialog.gc @@ -0,0 +1,28 @@ +#include +#include + +module Gimp.ColormapDialog; + +import Gtk, g; + +class ColormapDialog : Gtk.Dialog { + public static ColormapDialog* create(Set* context); + read-only Image* image; + read-only int col-index; + protected pre-emit void selected (); + Widget* vbox; + Preview* palette; + Widget* image-menu; + OptionMenu* option-menu; + Set* context; + uint event-handler; + int xn; + int yn; + int cellsize; + Entry* index-entry; + Entry* color-entry; + SetHandlerId rename-handler; + SetHandlerId cmap-changed-handler; + Widget* add-item; + .ColorSelectP color-select; +} diff --git a/app/colormap_dialog.i.c b/app/colormap_dialog.i.c new file mode 100644 index 0000000000..70f8830be8 --- /dev/null +++ b/app/colormap_dialog.i.c @@ -0,0 +1,836 @@ +#include +#include +#include +#include +#include "gdk/gdkkeysyms.h" + +#include "actionarea.h" +#include "color_select.h" +#include "image_render.h" +#include "buildmenu.h" +#include "colormaps.h" +#include "color_area.h" +/*#include "gdisplay.h"*/ +#include "general.h" +#include "libgimp/gimpintl.h" + +/* Add these features: + * + * load/save colormaps + * requantize + * add color--by clicking in the checked region + * all changes need to flush colormap lookup cache + */ + + +/* indexed palette routines */ +static void ipal_draw (GimpColormapDialog*); +static void ipal_clear (GimpColormapDialog*); +static void ipal_set_image (GimpColormapDialog*, GimpImage*); +static void ipal_update_entries(GimpColormapDialog* ipal); +static void ipal_set_index (GimpColormapDialog* ipal, gint i); +static void ipal_draw_cell (GimpColormapDialog* ipal, gint col); +static void ipal_update_image_list (GimpColormapDialog* ipal); + + +/* indexed palette menu callbacks */ +static void ipal_add_callback (GtkWidget *, gpointer); +static void ipal_edit_callback (GtkWidget *, gpointer); +static void ipal_close_callback (GtkWidget *, gpointer); +static void ipal_select_callback (int, int, int, ColorSelectState, void *); + +/* event callback */ +static gint ipal_area_events (GtkWidget *, GdkEvent *, GimpColormapDialog *); + +/* create image menu */ +static void image_menu_callback (GtkWidget *, gpointer); +static GtkWidget * create_image_menu (GimpColormapDialog*, + GimpImage**, + int *, + MenuItemCallback); +static void frame_size_alloc_cb(GtkFrame* frame, GtkAllocation* alloc, + GimpColormapDialog* ipal); +static void window_size_req_cb(GtkWindow* win, GtkRequisition* req, + GimpColormapDialog* ipal); + +static void index_entry_change_cb(GtkEntry* entry, GimpColormapDialog* ipal); +static void hex_entry_change_cb(GtkEntry* entry, GimpColormapDialog* ipal); + +static void +set_addrem_cb(GimpSet* set, GimpImage* image, GimpColormapDialog* ipal); +static void +image_rename_cb(GimpImage* img, GimpColormapDialog* ipal); +static void +image_cmap_change_cb(GimpImage* img, gint ncol, GimpColormapDialog* ipal); + + +/**************************************/ +/* Public indexed palette functions */ +/**************************************/ + +#define COLORMAP_DIALOG_CREATE ipal_create + +GimpColormapDialog* +ipal_create (GimpSet* context) +{ + gint i; + GtkWidget *vbox; + GtkWidget *frame; + GtkWidget *util_box; + GtkWidget *label; + GtkWidget *arrow_hbox; + GtkWidget *arrow; + GtkWidget *ops_menu; + GtkWidget *menu_bar; + GtkWidget *menu_bar_item; + GtkWidget *hbox; + GtkWidget *hbox2; + GtkWidget *entry; + GtkWidget *evbox; + GtkAccelGroup *accel_group; + GimpColormapDialog* ipal; + ActionAreaItem action_items[] = + { + { N_("Close"), ipal_close_callback, NULL, NULL }, + }; + + MenuItem indexed_color_ops[] = + { + { N_("Add"), 'N', GDK_CONTROL_MASK, + ipal_add_callback, NULL, NULL, NULL }, + { N_("Edit"), 'E', GDK_CONTROL_MASK, + ipal_edit_callback, NULL, NULL, NULL }, + { N_("Close"), 'W', GDK_CONTROL_MASK, + ipal_close_callback, NULL, NULL, NULL }, + { NULL, 0, 0, NULL, NULL, NULL, NULL }, + }; + + ipal = gtk_type_new(GIMP_TYPE_COLORMAP_DIALOG); + ipal->image = NULL; + ipal->context = context; + ipal->cmap_changed_handler + = gimp_set_add_handler(context, "colormap_changed", + image_cmap_change_cb, ipal); + ipal->rename_handler + = gimp_set_add_handler(context, "rename", + image_rename_cb, ipal); + + accel_group = gtk_accel_group_new (); + gtk_window_set_wmclass (GTK_WINDOW (ipal), "indexed_color_palette", "Gimp"); + gtk_window_set_policy (GTK_WINDOW (ipal), TRUE, TRUE, TRUE); + gtk_window_set_title (GTK_WINDOW (ipal), _("Indexed Color Palette")); + gtk_window_add_accel_group (GTK_WINDOW (ipal), accel_group); + gtk_signal_connect (GTK_OBJECT (ipal), "delete_event", + GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete), + NULL); + + ipal->vbox = vbox = gtk_vbox_new (FALSE, 1); + gtk_container_border_width (GTK_CONTAINER (vbox), 1); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (ipal)->vbox), vbox, TRUE, TRUE, 0); + + /* The hbox to hold the command menu and image option menu box */ + util_box = gtk_hbox_new (FALSE, 1); + gtk_box_pack_start (GTK_BOX (vbox), util_box, FALSE, FALSE, 0); + + /* The GIMP image option menu */ + label = gtk_label_new (_("Image:")); + gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2); + ipal->option_menu = GTK_OPTION_MENU(gtk_option_menu_new ()); + gtk_box_pack_start (GTK_BOX (util_box), + GTK_WIDGET (ipal->option_menu), + TRUE, TRUE, 2); + + /* The indexed palette commands pulldown menu */ + for(i=0;iadd_item = indexed_color_ops[0].widget; + menu_bar = gtk_menu_bar_new (); + gtk_box_pack_start (GTK_BOX (util_box), menu_bar, FALSE, FALSE, 2); + menu_bar_item = gtk_menu_item_new (); + gtk_container_add (GTK_CONTAINER (menu_bar), menu_bar_item); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_bar_item), ops_menu); + arrow_hbox = gtk_hbox_new (FALSE, 1); + gtk_container_add (GTK_CONTAINER (menu_bar_item), arrow_hbox); + label = gtk_label_new (_("Operations")); + arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); + gtk_box_pack_start (GTK_BOX (arrow_hbox), arrow, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (arrow_hbox), label, FALSE, FALSE, 4); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_misc_set_alignment (GTK_MISC (arrow), 0.5, 0.5); + + hbox2 = gtk_hbox_new (TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox2, TRUE, TRUE, 4); + /* The palette frame */ + evbox = gtk_event_box_new (); + gtk_container_set_resize_mode (GTK_CONTAINER(evbox), + GTK_RESIZE_QUEUE); + gtk_signal_connect(GTK_OBJECT(evbox), "size_request", + GTK_SIGNAL_FUNC(window_size_req_cb), ipal); + gtk_signal_connect(GTK_OBJECT(evbox), "size_allocate", + GTK_SIGNAL_FUNC(frame_size_alloc_cb), ipal); + gtk_box_pack_start (GTK_BOX (hbox2), evbox, TRUE, TRUE, 2); + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER(evbox), frame); + ipal->palette = GTK_PREVIEW (gtk_preview_new (GTK_PREVIEW_COLOR)); + gtk_preview_size(ipal->palette, 256, 256); + gtk_widget_set_events (GTK_WIDGET(ipal->palette), GDK_BUTTON_PRESS_MASK); + ipal->event_handler = + gtk_signal_connect (GTK_OBJECT (ipal->palette), "event", + (GtkSignalFunc) ipal_area_events, + ipal); + gtk_signal_handler_block(GTK_OBJECT(ipal->palette), + ipal->event_handler); + + gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(ipal->palette)); + + + /* some helpful hints */ + hbox = gtk_hbox_new(FALSE, 1); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 1); + label = gtk_label_new (_("Index:")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); + entry = gtk_entry_new_with_max_length (3); + ipal->index_entry = GTK_ENTRY(entry); + gtk_signal_connect (GTK_OBJECT(entry), "activate", + GTK_SIGNAL_FUNC(index_entry_change_cb), ipal); + gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 1); + label = gtk_label_new (_("Hex Triplet:")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); + entry = gtk_entry_new_with_max_length (7); + ipal->color_entry = GTK_ENTRY(entry); + gtk_signal_connect (GTK_OBJECT(entry), "activate", + GTK_SIGNAL_FUNC(hex_entry_change_cb), ipal); + gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 1); + + + /* The action area */ + for(i=0;iimage; + ipal->image_menu = + create_image_menu (ipal, + &default_gimage, + &default_index, + image_menu_callback); + gtk_option_menu_set_menu (ipal->option_menu, + ipal->image_menu); + + if (default_index != -1) + { + if (! GTK_WIDGET_IS_SENSITIVE (ipal->vbox)) + gtk_widget_set_sensitive (ipal->vbox, TRUE); + gtk_option_menu_set_history (ipal->option_menu, + default_index); + } + else + { + if (GTK_WIDGET_IS_SENSITIVE (ipal->vbox)) + { + gtk_widget_set_sensitive (ipal->vbox, FALSE); + } + } + ipal_set_image (ipal, default_gimage); +} + +static void +frame_size_alloc_cb(GtkFrame* frame, GtkAllocation* alloc, + GimpColormapDialog* ipal){ + GtkWidget* w = GTK_WIDGET(frame); + GtkAllocation a = *alloc; + GtkRequisition r; + if(ipal->image) + ipal_draw(ipal); + else + ipal_clear(ipal); + w = GTK_BIN(w)->child; + gtk_widget_size_request(w, &r); + a.x = MAX(0, a.width - r.width) / 2; + a.y = MAX(0, a.height - r.height) / 2; + a.width = MIN(a.width, r.width); + a.height = MIN(a.height, r.height); + gtk_widget_size_allocate(w, &a); +} + +static void +window_size_req_cb(GtkWindow* win, GtkRequisition* req, + GimpColormapDialog* ipal){ + req->width = GTK_WIDGET(win)->allocation.width; + req->height = GTK_WIDGET(win)->allocation.height; +} + +#define MIN_CELL_SIZE 4 + +static void +ipal_draw (GimpColormapDialog* ipal) +{ + GimpImage *gimage; + int i, j, k, l, b; + int col; + guchar* row; + gint cellsize, ncol, xn, yn, width, height; + GtkWidget *palette; + GtkContainer *parent; + g_return_if_fail(ipal); + gimage = ipal->image; + + g_return_if_fail(gimage); + + palette = GTK_WIDGET(ipal->palette); + parent = GTK_CONTAINER(palette->parent); + width = GTK_WIDGET(parent)->allocation.width - parent->border_width; + height = GTK_WIDGET(parent)->allocation.height - parent->border_width; + ncol = gimage->num_cols; + + if(!ncol){ + ipal_clear(ipal); + return; + } + + cellsize = sqrt(width * height / ncol); + while(cellsize>= MIN_CELL_SIZE + && (xn = width/cellsize) * (yn = height/cellsize) < ncol) + cellsize--; + + if(cellsize < MIN_CELL_SIZE){ + cellsize = MIN_CELL_SIZE; + xn = yn = ceil(sqrt(ncol)); + } + + yn = ((ncol + xn - 1) / xn); + width = xn * cellsize; + height = yn * cellsize; + ipal->xn = xn; + ipal->yn = yn; + ipal->cellsize = cellsize; + + gtk_preview_size(ipal->palette, width, height); + /*gtk_container_resize_children(GTK_WIDGET(parent)->parent);*/ + + /* req.width = width + parent->border_width; + req.height = height + parent->border_width; + gtk_widget_size_request(palette->parent, &req);*/ + /*gtk_widget_queue_resize (GTK_WIDGET(ipal));*/ + /*gtk_container_check_resize (GTK_WIDGET(parent)->parent);*/ + + + row = g_new (guchar, xn*cellsize*3); + col = 0; + for (i = 0; i < yn; i++) + { + for (j = 0; j < xn && col < ncol; j++, col++) + { + for (k = 0; k < cellsize; k++) + for (b = 0; b < 3; b++) + row[(j * cellsize + k) * 3 + b] = gimage->cmap[col * 3 + b]; + } + + for (k = 0; k < cellsize; k++) + { + for (l = j * cellsize; l < xn * cellsize; l++) + for (b = 0; b < 3; b++) + row[l * 3 + b] = ((((i * cellsize + k) & 0x4) ? (l) : (l + 0x4)) & 0x4) ? + blend_light_check[0] : blend_dark_check[0]; + + gtk_preview_draw_row (ipal->palette, row, 0, + i * cellsize + k, cellsize * xn); + } + } + ipal_draw_cell (ipal, ipal->col_index); + + g_free (row); + gtk_widget_draw (palette, NULL); +} + +static void +ipal_draw_cell (GimpColormapDialog* ipal, gint col) +{ + guchar* row; + gint cellsize, x, y, k; + GdkRectangle rec; + + g_assert (ipal); + g_assert (ipal->image); + g_assert (col < ipal->image->num_cols); + + cellsize = ipal->cellsize; + row = g_new(guchar, cellsize * 3); + x = (col % ipal->xn) * cellsize; + y = (col / ipal->xn) * cellsize; + + if(col == ipal->col_index){ + for(k = 0; k < cellsize; k++) + row[k*3] = row[k*3+1] = row[k*3+2] = (k & 1) * 255; + gtk_preview_draw_row (ipal->palette, row, x, y, cellsize); + if(!(cellsize & 1)) + for(k = 0; k < cellsize; k++) + row[k*3] = row[k*3+1] = row[k*3+2] = ((x+y+1) & 1) * 255; + gtk_preview_draw_row (ipal->palette, row, x, y+cellsize-1, cellsize); + row[0]=row[1]=row[2]=255; + row[cellsize*3-3] = row[cellsize*3-2] = row[cellsize*3-1] + = 255 * (cellsize & 1); + for(k = 1; k < cellsize - 1; k++){ + row[k*3] = ipal->image->cmap[col * 3]; + row[k*3+1] = ipal->image->cmap[col * 3 + 1]; + row[k*3+2] = ipal->image->cmap[col * 3 + 2]; + } + for(k = 1; k < cellsize - 1; k+=2) + gtk_preview_draw_row (ipal->palette, row, x, y+k, cellsize); + row[0] = row[1] = row[2] = 0; + row[cellsize*3-3] = row[cellsize*3-2] = row[cellsize*3-1] + = 255 * ((cellsize+1) & 1); + for(k = 2; k < cellsize - 1; k+=2) + gtk_preview_draw_row (ipal->palette, row, x, y+k, cellsize); + } else { + for (k = 0; k < cellsize; k++){ + row[k*3] = ipal->image->cmap[col * 3]; + row[k*3+1] = ipal->image->cmap[col * 3 + 1]; + row[k*3+2] = ipal->image->cmap[col * 3 + 2]; + } + for (k = 0; k < cellsize; k++) + gtk_preview_draw_row (ipal->palette, row, x, y+k, cellsize); + } + rec.x = x; + rec.y = y; + rec.width = rec.height = cellsize; + gtk_widget_draw(GTK_WIDGET(ipal->palette), &rec); +} + +static void +ipal_clear (GimpColormapDialog* ipal) +{ + int i, j; + int offset; + gint width, height; + guchar* row; + GtkWidget* palette; + + g_return_if_fail(ipal); + + palette = GTK_WIDGET(ipal->palette); + + width = palette->allocation.width; + height = palette->allocation.height; + row = g_new(guchar, width * 3); + + gtk_preview_size(ipal->palette, width, height); + + for (i = 0; i < height; i += 4) + { + offset = (i & 0x4) ? 0x4 : 0x0; + + for (j = 0; j < width; j++) + { + row[j * 3 + 0] = row[j * 3 + 1] = row[j * 3 + 2] = + ((j + offset) & 0x4) ? blend_light_check[0] : blend_dark_check[0]; + } + + for (j = 0; j < 4 && i+j < height; j++) + gtk_preview_draw_row (ipal->palette, row, 0, i + j, width); + } + g_free (row); + gtk_widget_draw (palette, NULL); +} + + +static void +ipal_update_entries(GimpColormapDialog* ipal) +{ + gchar* s; + guchar* c; + + if(!ipal->image){ + gtk_widget_set_sensitive(GTK_WIDGET(ipal->index_entry), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(ipal->color_entry), FALSE); + gtk_entry_set_text(ipal->index_entry, ""); + gtk_entry_set_text(ipal->color_entry, ""); + } else { + s = g_strdup_printf("%d", ipal->col_index); + c = &ipal->image->cmap[ipal->col_index * 3]; + gtk_entry_set_text(ipal->index_entry, s); + g_free(s); + s = g_strdup_printf("#%02x%02x%02x", c[0], c[1], c[2]); + gtk_entry_set_text(ipal->color_entry, s); + g_free(s); + gtk_widget_set_sensitive(GTK_WIDGET(ipal->index_entry), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(ipal->color_entry), TRUE); + } +} + +static void +ipal_set_index (GimpColormapDialog* ipal, gint i) +{ + if(i != ipal->col_index){ + gint old = ipal->col_index; + ipal->col_index = i; + ipal_draw_cell (ipal, old); + ipal_draw_cell (ipal, i); + ipal_update_entries (ipal); + } +} + + +static void +index_entry_change_cb(GtkEntry* entry, GimpColormapDialog* ipal) +{ + gchar* s; + gint i; + + g_return_if_fail(ipal); + g_return_if_fail(ipal->image); + + s = gtk_entry_get_text(entry); + + if(sscanf(s, "%d", &i) && i>=0 && iimage->num_cols) + ipal_set_index (ipal, i); + + ipal_update_entries (ipal); +} + +static void +hex_entry_change_cb(GtkEntry* entry, GimpColormapDialog* ipal) +{ + gchar* s; + gulong i; + + g_return_if_fail(ipal); + g_return_if_fail(ipal->image); + + s = gtk_entry_get_text(entry); + + if(sscanf(s, "#%lx", &i)){ + guchar* c = &ipal->image->cmap[3 * ipal->col_index]; + c[0] = (i & 0xFF0000) >> 16; + c[1] = (i & 0x00FF00) >> 8; + c[2] = (i & 0x0000FF); + gimp_image_colormap_changed (ipal->image, ipal->col_index); + } + + ipal_update_entries (ipal); +} + + +static void +set_addrem_cb(GimpSet* set, GimpImage* image, GimpColormapDialog* ipal) +{ + ipal_update_image_list(ipal); +} + +static void +image_rename_cb(GimpImage* img, GimpColormapDialog* ipal) +{ + ipal_update_image_list(ipal); +} + +static void +image_cmap_change_cb(GimpImage* img, gint ncol, GimpColormapDialog* ipal){ + + if(img == ipal->image && gimp_image_base_type(img) == INDEXED){ + if(ncol<0){ + ipal_draw(ipal); + gtk_container_queue_resize(GTK_CONTAINER(ipal)); + }else{ + ipal_draw_cell(ipal, ncol); + } + if(ncol == ipal->col_index) + ipal_update_entries(ipal); + gtk_widget_set_sensitive(ipal->add_item, (img->num_cols < 256)); + }else{ + ipal_update_image_list(ipal); + } +} + +static void +ipal_set_image (GimpColormapDialog* ipal, GimpImage* gimage) +{ + g_assert(ipal); + + if(ipal->image){ + ipal->image = gimage; + if(!gimage){ + gtk_signal_handler_block(GTK_OBJECT(ipal->palette), + ipal->event_handler); + if(GTK_WIDGET_MAPPED(GTK_WIDGET(ipal))) + ipal_clear(ipal); + } + } + + if(gimage){ + if(!ipal->image) + gtk_signal_handler_unblock(GTK_OBJECT(ipal->palette), + ipal->event_handler); + g_return_if_fail(gimp_set_have(ipal->context, gimage)); + g_return_if_fail(gimage_base_type (gimage) == INDEXED); + ipal->image = gimage; + ipal_draw (ipal); + gtk_container_queue_resize(GTK_CONTAINER(ipal)); + }else{ + if(ipal->color_select) + color_select_hide(ipal->color_select); + } + + ipal->col_index = 0; + gtk_widget_set_sensitive(ipal->add_item, + (gimage && gimage->num_cols < 256)); + ipal_update_entries (ipal); +} + +static void +ipal_add_callback (GtkWidget *w, + gpointer client_data) +{ + GimpColormapDialog* ipal = client_data; + g_return_if_fail (ipal); + g_return_if_fail (ipal->image->num_cols < 256); + memcpy(&ipal->image->cmap[ipal->image->num_cols * 3], + &ipal->image->cmap[ipal->col_index * 3], + 3); + ipal->image->num_cols++; + gimp_image_colormap_changed (ipal->image, -1); +} + +static void +ipal_edit_callback (GtkWidget *w, + gpointer client_data) +{ + GimpColormapDialog* ipal = client_data; + guchar r, g, b; + + g_return_if_fail (ipal); + + r = ipal->image->cmap[ipal->col_index*3]; + g = ipal->image->cmap[ipal->col_index*3+1]; + b = ipal->image->cmap[ipal->col_index*3+2]; + if (! ipal->color_select) + { + ipal->color_select + = color_select_new (r, g, b, + ipal_select_callback, ipal, FALSE); + } + else + { + color_select_show (ipal->color_select); + color_select_set_color (ipal->color_select, r, g, b, 1); + } +} + +static void +ipal_close_callback (GtkWidget *w, + gpointer client_data) +{ + GimpColormapDialog* ipal = client_data; + g_assert(ipal); + gtk_widget_hide (GTK_WIDGET(ipal)); +} + +static void +ipal_select_callback (int r, + int g, + int b, + ColorSelectState state, + void *client_data) +{ + GimpImage *gimage; + GimpColormapDialog* ipal = client_data; + + g_return_if_fail (ipal); + g_return_if_fail (ipal->image); + g_return_if_fail (ipal->color_select); + + gimage = ipal->image; + + switch (state) { + case COLOR_SELECT_UPDATE: + break; + case COLOR_SELECT_OK: + gimage->cmap[ipal->col_index * 3 + 0] = r; + gimage->cmap[ipal->col_index * 3 + 1] = g; + gimage->cmap[ipal->col_index * 3 + 2] = b; + gimp_image_colormap_changed (gimage, ipal->col_index); + break; + case COLOR_SELECT_CANCEL: + color_select_hide (ipal->color_select); + } +} + +static gint +ipal_area_events (GtkWidget *widget, + GdkEvent * event, + GimpColormapDialog* ipal) +{ + GimpImage *gimage; + GdkEventButton *bevent; + guchar r, g, b; + guint col; + + g_assert(ipal); + gimage = ipal->image; + g_assert (gimage); + + + switch (event->type) + { + case GDK_BUTTON_PRESS: + bevent = (GdkEventButton *) event; + + if(bevent->button < 1 || bevent->button > 3) + return FALSE; + + if(!(bevent->y < ipal->cellsize * ipal->yn + && bevent->x < ipal->cellsize * ipal->xn)) + return FALSE; + + col = ipal->xn * ((int)bevent->y / ipal->cellsize) + + ((int)bevent->x / ipal->cellsize); + + if(col >= ipal->image->num_cols) + return FALSE; + + r = gimage->cmap[col * 3 + 0]; + g = gimage->cmap[col * 3 + 1]; + b = gimage->cmap[col * 3 + 2]; + ipal_set_index (ipal, col); + + if(bevent->button == 1) + { + gimp_colormap_dialog_selected(ipal); + } + + if (bevent->button == 3) + { + ipal->col_index = col; + if (! ipal->color_select) + { + ipal->color_select + = color_select_new (r, g, b, + ipal_select_callback, ipal, FALSE); + } + else + { + color_select_show (ipal->color_select); + color_select_set_color (ipal->color_select, r, g, b, 1); + } + } + break; + + default: + break; + } + + return FALSE; +} + +static void +image_menu_callback (GtkWidget *w, + gpointer client_data) +{ + GimpColormapDialog* ipal = gtk_object_get_data(GTK_OBJECT(w), "colormap_dialog"); + GimpImage* image = GIMP_IMAGE(client_data); + g_assert(ipal); + g_assert(image); + ipal_set_image (ipal, image); +} + +typedef struct{ + GimpImage** def; + int* default_index; + MenuItemCallback callback; + GtkWidget* menu; + int num_items; + GimpImage* id; + GimpColormapDialog* ipal; +}IMCBData; + +static void +create_image_menu_cb (gpointer im, gpointer d) +{ + GimpImage* gimage = GIMP_IMAGE (im); + IMCBData* data = (IMCBData*)d; + char* image_name; + char* menu_item_label; + GtkWidget *menu_item; + + if (gimage_base_type(gimage) != INDEXED) + return; + + /* make sure the default index gets set to _something_, if possible */ + if (*data->default_index == -1) + { + data->id = gimage; + *data->default_index = data->num_items; + } + + if (gimage == *data->def) + { + data->id = *data->def; + *data->default_index = data->num_items; + } + + image_name = prune_filename (gimage_filename (gimage)); + menu_item_label = g_strdup_printf ("%s-%d", image_name, + pdb_image_to_id (gimage)); + menu_item = gtk_menu_item_new_with_label (menu_item_label); + gtk_object_set_data(GTK_OBJECT (menu_item), "colormap_dialog", data->ipal); + gtk_signal_connect (GTK_OBJECT (menu_item), "activate", + (GtkSignalFunc) data->callback, + gimage); + gtk_container_add (GTK_CONTAINER (data->menu), menu_item); + gtk_widget_show (menu_item); + + g_free (menu_item_label); + data->num_items ++; +} + + +static GtkWidget * +create_image_menu (GimpColormapDialog* ipal, + GimpImage** def, + int *default_index, + MenuItemCallback callback) +{ + IMCBData data; + + data.def = def; + data.default_index = default_index; + data.callback = callback; + data.menu = gtk_menu_new (); + data.num_items = 0; + data.id = NULL; + data.ipal = ipal; + + *default_index = -1; + + gimp_set_foreach (ipal->context, create_image_menu_cb, &data); + + if (!data.num_items) + { + GtkWidget* menu_item; + menu_item = gtk_menu_item_new_with_label (_("none")); + gtk_container_add (GTK_CONTAINER (data.menu), menu_item); + gtk_widget_show (menu_item); + } + + *def = data.id; + + return data.menu; +} diff --git a/app/commands.c b/app/commands.c index 912b278b69..91722d394d 100644 --- a/app/commands.c +++ b/app/commands.c @@ -27,6 +27,8 @@ #include "by_color_select.h" #include "channels_dialog.h" #include "colormaps.h" +#include "colormap_dialog.i.h" +#include "color_area.h" #include "color_balance.h" #include "commands.h" #include "convert.h" @@ -49,7 +51,6 @@ #include "histogram_tool.h" #include "hue_saturation.h" #include "image_render.h" -#include "indexed_palette.h" #include "info_window.h" #include "interface.h" #include "invert.h" @@ -1028,15 +1029,30 @@ dialogs_lc_cmd_callback (GtkWidget *widget, lc_dialog_create (gdisp->gimage); } +static void +cmap_dlg_sel_cb(ColormapDialog* dlg, gpointer user_data) +{ + guchar* c; + + GimpImage* img = colormap_dialog_image(dlg); + c = &img->cmap[colormap_dialog_col_index(dlg) * 3]; + if(active_color == FOREGROUND) + palette_set_foreground (c[0], c[1], c[2]); + else if(active_color == BACKGROUND) + palette_set_background (c[0], c[1], c[2]); +} + void dialogs_indexed_palette_cmd_callback (GtkWidget *widget, gpointer client_data) { - GDisplay *gdisp; - - gdisp = gdisplay_active (); - - indexed_palette_create (gdisp->gimage); + static ColormapDialog* cmap_dlg; + if(!cmap_dlg){ + cmap_dlg = colormap_dialog_create (image_context); + colormap_dialog_connect_selected(cmap_dlg_sel_cb, NULL, + cmap_dlg); + } + gtk_widget_show(GTK_WIDGET(cmap_dlg)); } void diff --git a/app/convert.c b/app/convert.c index 8261b81647..2672000eee 100644 --- a/app/convert.c +++ b/app/convert.c @@ -74,7 +74,6 @@ #include "floating_sel.h" #include "fsdither.h" #include "gdisplay.h" -#include "indexed_palette.h" #include "interface.h" #include "undo.h" #include "palette.h" @@ -913,7 +912,7 @@ convert_image (GImage *gimage, gdisplays_update_title (gimage); gdisplays_update_full (gimage); - indexed_palette_update_image_list (); + gimp_image_colormap_changed (gimage, -1); } static void diff --git a/app/core/gimpimage-convert.c b/app/core/gimpimage-convert.c index 8261b81647..2672000eee 100644 --- a/app/core/gimpimage-convert.c +++ b/app/core/gimpimage-convert.c @@ -74,7 +74,6 @@ #include "floating_sel.h" #include "fsdither.h" #include "gdisplay.h" -#include "indexed_palette.h" #include "interface.h" #include "undo.h" #include "palette.h" @@ -913,7 +912,7 @@ convert_image (GImage *gimage, gdisplays_update_title (gimage); gdisplays_update_full (gimage); - indexed_palette_update_image_list (); + gimp_image_colormap_changed (gimage, -1); } static void diff --git a/app/core/gimpimage-guides.c b/app/core/gimpimage-guides.c index e7e6b445bd..330b82dba9 100644 --- a/app/core/gimpimage-guides.c +++ b/app/core/gimpimage-guides.c @@ -93,6 +93,7 @@ enum{ RENAME, RESIZE, RESTRUCTURE, + COLORMAP_CHANGED, LAST_SIGNAL }; static void gimp_image_destroy (GtkObject *); @@ -123,6 +124,8 @@ gimp_image_class_init (GimpImageClass *klass) gimp_signal_new ("resize", 0, type, 0, gimp_sigtype_void); gimp_image_signals[RESTRUCTURE] = gimp_signal_new ("restructure", 0, type, 0, gimp_sigtype_void); + gimp_image_signals[COLORMAP_CHANGED] = + gimp_signal_new ("colormap_changed", 0, type, 0, gimp_sigtype_int); gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL); } @@ -923,7 +926,15 @@ gimp_image_get_new_tattoo(GimpImage *image) return (image->tattoo_state); } - +void +gimp_image_colormap_changed (GimpImage *image, gint col){ + g_return_if_fail (image); + g_return_if_fail (col < image->num_cols); + gtk_signal_emit (GTK_OBJECT(image), + gimp_image_signals[COLORMAP_CHANGED], + col); +} + /************************************************************/ /* Projection functions */ /************************************************************/ diff --git a/app/core/gimpimage-guides.h b/app/core/gimpimage-guides.h index 6c27d3ea91..f90a50b5d6 100644 --- a/app/core/gimpimage-guides.h +++ b/app/core/gimpimage-guides.h @@ -18,7 +18,7 @@ #define GIMP_IMAGE(obj) GTK_CHECK_CAST (obj, GIMP_TYPE_IMAGE, GimpImage) -#define GIMP_IS_GIMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) +#define GIMP_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) /* the image types */ @@ -146,6 +146,15 @@ void gimp_image_detach_parasite (GimpImage *, const char *); Tattoo gimp_image_get_new_tattoo (GimpImage *); +/* Temporary hack till colormap manipulation is encapsulated in functions. + Call this whenever you modify an image's colormap. The ncol argument + specifies which color has changed, or negative if there's a bigger change. + Currently, use this also when the image's base type is changed to/from + indexed. */ + +void gimp_image_colormap_changed (GimpImage * image, + gint ncol); + /* layer/channel functions */ diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c index e7e6b445bd..330b82dba9 100644 --- a/app/core/gimpimage-merge.c +++ b/app/core/gimpimage-merge.c @@ -93,6 +93,7 @@ enum{ RENAME, RESIZE, RESTRUCTURE, + COLORMAP_CHANGED, LAST_SIGNAL }; static void gimp_image_destroy (GtkObject *); @@ -123,6 +124,8 @@ gimp_image_class_init (GimpImageClass *klass) gimp_signal_new ("resize", 0, type, 0, gimp_sigtype_void); gimp_image_signals[RESTRUCTURE] = gimp_signal_new ("restructure", 0, type, 0, gimp_sigtype_void); + gimp_image_signals[COLORMAP_CHANGED] = + gimp_signal_new ("colormap_changed", 0, type, 0, gimp_sigtype_int); gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL); } @@ -923,7 +926,15 @@ gimp_image_get_new_tattoo(GimpImage *image) return (image->tattoo_state); } - +void +gimp_image_colormap_changed (GimpImage *image, gint col){ + g_return_if_fail (image); + g_return_if_fail (col < image->num_cols); + gtk_signal_emit (GTK_OBJECT(image), + gimp_image_signals[COLORMAP_CHANGED], + col); +} + /************************************************************/ /* Projection functions */ /************************************************************/ diff --git a/app/core/gimpimage-merge.h b/app/core/gimpimage-merge.h index 6c27d3ea91..f90a50b5d6 100644 --- a/app/core/gimpimage-merge.h +++ b/app/core/gimpimage-merge.h @@ -18,7 +18,7 @@ #define GIMP_IMAGE(obj) GTK_CHECK_CAST (obj, GIMP_TYPE_IMAGE, GimpImage) -#define GIMP_IS_GIMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) +#define GIMP_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) /* the image types */ @@ -146,6 +146,15 @@ void gimp_image_detach_parasite (GimpImage *, const char *); Tattoo gimp_image_get_new_tattoo (GimpImage *); +/* Temporary hack till colormap manipulation is encapsulated in functions. + Call this whenever you modify an image's colormap. The ncol argument + specifies which color has changed, or negative if there's a bigger change. + Currently, use this also when the image's base type is changed to/from + indexed. */ + +void gimp_image_colormap_changed (GimpImage * image, + gint ncol); + /* layer/channel functions */ diff --git a/app/core/gimpimage-projection.c b/app/core/gimpimage-projection.c index e7e6b445bd..330b82dba9 100644 --- a/app/core/gimpimage-projection.c +++ b/app/core/gimpimage-projection.c @@ -93,6 +93,7 @@ enum{ RENAME, RESIZE, RESTRUCTURE, + COLORMAP_CHANGED, LAST_SIGNAL }; static void gimp_image_destroy (GtkObject *); @@ -123,6 +124,8 @@ gimp_image_class_init (GimpImageClass *klass) gimp_signal_new ("resize", 0, type, 0, gimp_sigtype_void); gimp_image_signals[RESTRUCTURE] = gimp_signal_new ("restructure", 0, type, 0, gimp_sigtype_void); + gimp_image_signals[COLORMAP_CHANGED] = + gimp_signal_new ("colormap_changed", 0, type, 0, gimp_sigtype_int); gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL); } @@ -923,7 +926,15 @@ gimp_image_get_new_tattoo(GimpImage *image) return (image->tattoo_state); } - +void +gimp_image_colormap_changed (GimpImage *image, gint col){ + g_return_if_fail (image); + g_return_if_fail (col < image->num_cols); + gtk_signal_emit (GTK_OBJECT(image), + gimp_image_signals[COLORMAP_CHANGED], + col); +} + /************************************************************/ /* Projection functions */ /************************************************************/ diff --git a/app/core/gimpimage-projection.h b/app/core/gimpimage-projection.h index 6c27d3ea91..f90a50b5d6 100644 --- a/app/core/gimpimage-projection.h +++ b/app/core/gimpimage-projection.h @@ -18,7 +18,7 @@ #define GIMP_IMAGE(obj) GTK_CHECK_CAST (obj, GIMP_TYPE_IMAGE, GimpImage) -#define GIMP_IS_GIMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) +#define GIMP_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) /* the image types */ @@ -146,6 +146,15 @@ void gimp_image_detach_parasite (GimpImage *, const char *); Tattoo gimp_image_get_new_tattoo (GimpImage *); +/* Temporary hack till colormap manipulation is encapsulated in functions. + Call this whenever you modify an image's colormap. The ncol argument + specifies which color has changed, or negative if there's a bigger change. + Currently, use this also when the image's base type is changed to/from + indexed. */ + +void gimp_image_colormap_changed (GimpImage * image, + gint ncol); + /* layer/channel functions */ diff --git a/app/core/gimpimage-resize.c b/app/core/gimpimage-resize.c index e7e6b445bd..330b82dba9 100644 --- a/app/core/gimpimage-resize.c +++ b/app/core/gimpimage-resize.c @@ -93,6 +93,7 @@ enum{ RENAME, RESIZE, RESTRUCTURE, + COLORMAP_CHANGED, LAST_SIGNAL }; static void gimp_image_destroy (GtkObject *); @@ -123,6 +124,8 @@ gimp_image_class_init (GimpImageClass *klass) gimp_signal_new ("resize", 0, type, 0, gimp_sigtype_void); gimp_image_signals[RESTRUCTURE] = gimp_signal_new ("restructure", 0, type, 0, gimp_sigtype_void); + gimp_image_signals[COLORMAP_CHANGED] = + gimp_signal_new ("colormap_changed", 0, type, 0, gimp_sigtype_int); gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL); } @@ -923,7 +926,15 @@ gimp_image_get_new_tattoo(GimpImage *image) return (image->tattoo_state); } - +void +gimp_image_colormap_changed (GimpImage *image, gint col){ + g_return_if_fail (image); + g_return_if_fail (col < image->num_cols); + gtk_signal_emit (GTK_OBJECT(image), + gimp_image_signals[COLORMAP_CHANGED], + col); +} + /************************************************************/ /* Projection functions */ /************************************************************/ diff --git a/app/core/gimpimage-resize.h b/app/core/gimpimage-resize.h index 6c27d3ea91..f90a50b5d6 100644 --- a/app/core/gimpimage-resize.h +++ b/app/core/gimpimage-resize.h @@ -18,7 +18,7 @@ #define GIMP_IMAGE(obj) GTK_CHECK_CAST (obj, GIMP_TYPE_IMAGE, GimpImage) -#define GIMP_IS_GIMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) +#define GIMP_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) /* the image types */ @@ -146,6 +146,15 @@ void gimp_image_detach_parasite (GimpImage *, const char *); Tattoo gimp_image_get_new_tattoo (GimpImage *); +/* Temporary hack till colormap manipulation is encapsulated in functions. + Call this whenever you modify an image's colormap. The ncol argument + specifies which color has changed, or negative if there's a bigger change. + Currently, use this also when the image's base type is changed to/from + indexed. */ + +void gimp_image_colormap_changed (GimpImage * image, + gint ncol); + /* layer/channel functions */ diff --git a/app/core/gimpimage-scale.c b/app/core/gimpimage-scale.c index e7e6b445bd..330b82dba9 100644 --- a/app/core/gimpimage-scale.c +++ b/app/core/gimpimage-scale.c @@ -93,6 +93,7 @@ enum{ RENAME, RESIZE, RESTRUCTURE, + COLORMAP_CHANGED, LAST_SIGNAL }; static void gimp_image_destroy (GtkObject *); @@ -123,6 +124,8 @@ gimp_image_class_init (GimpImageClass *klass) gimp_signal_new ("resize", 0, type, 0, gimp_sigtype_void); gimp_image_signals[RESTRUCTURE] = gimp_signal_new ("restructure", 0, type, 0, gimp_sigtype_void); + gimp_image_signals[COLORMAP_CHANGED] = + gimp_signal_new ("colormap_changed", 0, type, 0, gimp_sigtype_int); gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL); } @@ -923,7 +926,15 @@ gimp_image_get_new_tattoo(GimpImage *image) return (image->tattoo_state); } - +void +gimp_image_colormap_changed (GimpImage *image, gint col){ + g_return_if_fail (image); + g_return_if_fail (col < image->num_cols); + gtk_signal_emit (GTK_OBJECT(image), + gimp_image_signals[COLORMAP_CHANGED], + col); +} + /************************************************************/ /* Projection functions */ /************************************************************/ diff --git a/app/core/gimpimage-scale.h b/app/core/gimpimage-scale.h index 6c27d3ea91..f90a50b5d6 100644 --- a/app/core/gimpimage-scale.h +++ b/app/core/gimpimage-scale.h @@ -18,7 +18,7 @@ #define GIMP_IMAGE(obj) GTK_CHECK_CAST (obj, GIMP_TYPE_IMAGE, GimpImage) -#define GIMP_IS_GIMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) +#define GIMP_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) /* the image types */ @@ -146,6 +146,15 @@ void gimp_image_detach_parasite (GimpImage *, const char *); Tattoo gimp_image_get_new_tattoo (GimpImage *); +/* Temporary hack till colormap manipulation is encapsulated in functions. + Call this whenever you modify an image's colormap. The ncol argument + specifies which color has changed, or negative if there's a bigger change. + Currently, use this also when the image's base type is changed to/from + indexed. */ + +void gimp_image_colormap_changed (GimpImage * image, + gint ncol); + /* layer/channel functions */ diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index b2cb9ea104..b6e38f83ed 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -28,7 +28,6 @@ #include "gdisplay_ops.h" #include "gimage_mask.h" #include "gimprc.h" -#include "indexed_palette.h" #include "layer.h" #include "paint_core.h" #include "paint_funcs.h" @@ -1987,7 +1986,7 @@ undo_pop_gimage_mod (GImage *gimage, gdisplays_update_full (gimage); gdisplays_update_title (gimage); - indexed_palette_update_image_list (); + gimp_image_colormap_changed (gimage, -1); if (gimage->width != (int) data[0] || gimage->height != (int) data[1]) shrink_wrap = TRUE; diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index e7e6b445bd..330b82dba9 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -93,6 +93,7 @@ enum{ RENAME, RESIZE, RESTRUCTURE, + COLORMAP_CHANGED, LAST_SIGNAL }; static void gimp_image_destroy (GtkObject *); @@ -123,6 +124,8 @@ gimp_image_class_init (GimpImageClass *klass) gimp_signal_new ("resize", 0, type, 0, gimp_sigtype_void); gimp_image_signals[RESTRUCTURE] = gimp_signal_new ("restructure", 0, type, 0, gimp_sigtype_void); + gimp_image_signals[COLORMAP_CHANGED] = + gimp_signal_new ("colormap_changed", 0, type, 0, gimp_sigtype_int); gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL); } @@ -923,7 +926,15 @@ gimp_image_get_new_tattoo(GimpImage *image) return (image->tattoo_state); } - +void +gimp_image_colormap_changed (GimpImage *image, gint col){ + g_return_if_fail (image); + g_return_if_fail (col < image->num_cols); + gtk_signal_emit (GTK_OBJECT(image), + gimp_image_signals[COLORMAP_CHANGED], + col); +} + /************************************************************/ /* Projection functions */ /************************************************************/ diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h index 6c27d3ea91..f90a50b5d6 100644 --- a/app/core/gimpimage.h +++ b/app/core/gimpimage.h @@ -18,7 +18,7 @@ #define GIMP_IMAGE(obj) GTK_CHECK_CAST (obj, GIMP_TYPE_IMAGE, GimpImage) -#define GIMP_IS_GIMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) +#define GIMP_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) /* the image types */ @@ -146,6 +146,15 @@ void gimp_image_detach_parasite (GimpImage *, const char *); Tattoo gimp_image_get_new_tattoo (GimpImage *); +/* Temporary hack till colormap manipulation is encapsulated in functions. + Call this whenever you modify an image's colormap. The ncol argument + specifies which color has changed, or negative if there's a bigger change. + Currently, use this also when the image's base type is changed to/from + indexed. */ + +void gimp_image_colormap_changed (GimpImage * image, + gint ncol); + /* layer/channel functions */ diff --git a/app/core/gimpprojection-construct.c b/app/core/gimpprojection-construct.c index e7e6b445bd..330b82dba9 100644 --- a/app/core/gimpprojection-construct.c +++ b/app/core/gimpprojection-construct.c @@ -93,6 +93,7 @@ enum{ RENAME, RESIZE, RESTRUCTURE, + COLORMAP_CHANGED, LAST_SIGNAL }; static void gimp_image_destroy (GtkObject *); @@ -123,6 +124,8 @@ gimp_image_class_init (GimpImageClass *klass) gimp_signal_new ("resize", 0, type, 0, gimp_sigtype_void); gimp_image_signals[RESTRUCTURE] = gimp_signal_new ("restructure", 0, type, 0, gimp_sigtype_void); + gimp_image_signals[COLORMAP_CHANGED] = + gimp_signal_new ("colormap_changed", 0, type, 0, gimp_sigtype_int); gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL); } @@ -923,7 +926,15 @@ gimp_image_get_new_tattoo(GimpImage *image) return (image->tattoo_state); } - +void +gimp_image_colormap_changed (GimpImage *image, gint col){ + g_return_if_fail (image); + g_return_if_fail (col < image->num_cols); + gtk_signal_emit (GTK_OBJECT(image), + gimp_image_signals[COLORMAP_CHANGED], + col); +} + /************************************************************/ /* Projection functions */ /************************************************************/ diff --git a/app/core/gimpprojection-construct.h b/app/core/gimpprojection-construct.h index 6c27d3ea91..f90a50b5d6 100644 --- a/app/core/gimpprojection-construct.h +++ b/app/core/gimpprojection-construct.h @@ -18,7 +18,7 @@ #define GIMP_IMAGE(obj) GTK_CHECK_CAST (obj, GIMP_TYPE_IMAGE, GimpImage) -#define GIMP_IS_GIMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) +#define GIMP_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) /* the image types */ @@ -146,6 +146,15 @@ void gimp_image_detach_parasite (GimpImage *, const char *); Tattoo gimp_image_get_new_tattoo (GimpImage *); +/* Temporary hack till colormap manipulation is encapsulated in functions. + Call this whenever you modify an image's colormap. The ncol argument + specifies which color has changed, or negative if there's a bigger change. + Currently, use this also when the image's base type is changed to/from + indexed. */ + +void gimp_image_colormap_changed (GimpImage * image, + gint ncol); + /* layer/channel functions */ diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c index 296d7ef67a..0967af7fb1 100644 --- a/app/dialogs/preferences-dialog.c +++ b/app/dialogs/preferences-dialog.c @@ -28,7 +28,6 @@ #include "histogram_tool.h" #include "hue_saturation.h" #include "image_render.h" -#include "indexed_palette.h" #include "info_window.h" #include "interface.h" #include "invert.h" diff --git a/app/gimage.c b/app/gimage.c index 509802263f..77984afa5a 100644 --- a/app/gimage.c +++ b/app/gimage.c @@ -4,8 +4,6 @@ #include "channels_dialog.h" #include "layers_dialog.h" -#include "indexed_palette.h" - #include "drawable.h" #include "gdisplay.h" #include "procedural_db.h" @@ -27,6 +25,8 @@ static void gimage_dirty_handler (GimpImage* gimage); static void gimage_destroy_handler (GimpImage* gimage); +static void gimage_cmap_change_handler (GimpImage* gimage, gint ncol, + gpointer user_data); static void gimage_rename_handler (GimpImage* gimage); static void gimage_resize_handler (GimpImage* gimage); static void gimage_restructure_handler (GimpImage* gimage); @@ -49,10 +49,11 @@ gimage_new(int width, int height, GimpImageBaseType base_type) GTK_SIGNAL_FUNC(gimage_restructure_handler), NULL); gtk_signal_connect (GTK_OBJECT (gimage), "repaint", GTK_SIGNAL_FUNC(gimage_repaint_handler), NULL); + gtk_signal_connect (GTK_OBJECT (gimage), "colormap_changed", + GTK_SIGNAL_FUNC(gimage_cmap_change_handler), NULL); gimp_set_add(image_context, gimage); - indexed_palette_update_image_list (); palette_import_image_new(gimage); return gimage; @@ -108,17 +109,21 @@ gimage_destroy_handler (GimpImage* gimage) /* free the undo list */ undo_free (gimage); - indexed_palette_update_image_list (); - palette_import_image_destroyed(gimage); } +static void gimage_cmap_change_handler (GimpImage* gimage, gint ncol, + gpointer user_data) +{ + gdisplays_update_full(gimage); +} + + static void gimage_rename_handler (GimpImage* gimage) { gdisplays_update_title (gimage); lc_dialog_update_image_list (); - indexed_palette_update_image_list (); palette_import_image_renamed(gimage); } diff --git a/app/gimp.gh b/app/gimp.gh new file mode 100644 index 0000000000..b564a36c27 --- /dev/null +++ b/app/gimp.gh @@ -0,0 +1,27 @@ +#include + +package Gimp <> { + module { + class Image; + } + module { + class Object; + } + module { + class Layer; + } + module { + class Drawable; + } + module { + class Set; + foreign SetHandlerId; + } + class ColormapDialog; +} + +package { + module { + foreign ColorSelectP; + } +} diff --git a/app/gimpimage-convert.c b/app/gimpimage-convert.c index 8261b81647..2672000eee 100644 --- a/app/gimpimage-convert.c +++ b/app/gimpimage-convert.c @@ -74,7 +74,6 @@ #include "floating_sel.h" #include "fsdither.h" #include "gdisplay.h" -#include "indexed_palette.h" #include "interface.h" #include "undo.h" #include "palette.h" @@ -913,7 +912,7 @@ convert_image (GImage *gimage, gdisplays_update_title (gimage); gdisplays_update_full (gimage); - indexed_palette_update_image_list (); + gimp_image_colormap_changed (gimage, -1); } static void diff --git a/app/gimpimage.c b/app/gimpimage.c index e7e6b445bd..330b82dba9 100644 --- a/app/gimpimage.c +++ b/app/gimpimage.c @@ -93,6 +93,7 @@ enum{ RENAME, RESIZE, RESTRUCTURE, + COLORMAP_CHANGED, LAST_SIGNAL }; static void gimp_image_destroy (GtkObject *); @@ -123,6 +124,8 @@ gimp_image_class_init (GimpImageClass *klass) gimp_signal_new ("resize", 0, type, 0, gimp_sigtype_void); gimp_image_signals[RESTRUCTURE] = gimp_signal_new ("restructure", 0, type, 0, gimp_sigtype_void); + gimp_image_signals[COLORMAP_CHANGED] = + gimp_signal_new ("colormap_changed", 0, type, 0, gimp_sigtype_int); gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL); } @@ -923,7 +926,15 @@ gimp_image_get_new_tattoo(GimpImage *image) return (image->tattoo_state); } - +void +gimp_image_colormap_changed (GimpImage *image, gint col){ + g_return_if_fail (image); + g_return_if_fail (col < image->num_cols); + gtk_signal_emit (GTK_OBJECT(image), + gimp_image_signals[COLORMAP_CHANGED], + col); +} + /************************************************************/ /* Projection functions */ /************************************************************/ diff --git a/app/gimpimage.h b/app/gimpimage.h index 6c27d3ea91..f90a50b5d6 100644 --- a/app/gimpimage.h +++ b/app/gimpimage.h @@ -18,7 +18,7 @@ #define GIMP_IMAGE(obj) GTK_CHECK_CAST (obj, GIMP_TYPE_IMAGE, GimpImage) -#define GIMP_IS_GIMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) +#define GIMP_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, GIMP_TYPE_IMAGE) /* the image types */ @@ -146,6 +146,15 @@ void gimp_image_detach_parasite (GimpImage *, const char *); Tattoo gimp_image_get_new_tattoo (GimpImage *); +/* Temporary hack till colormap manipulation is encapsulated in functions. + Call this whenever you modify an image's colormap. The ncol argument + specifies which color has changed, or negative if there's a bigger change. + Currently, use this also when the image's base type is changed to/from + indexed. */ + +void gimp_image_colormap_changed (GimpImage * image, + gint ncol); + /* layer/channel functions */ diff --git a/app/gimpset.c b/app/gimpset.c index 37711a0adf..0310f23b06 100644 --- a/app/gimpset.c +++ b/app/gimpset.c @@ -3,6 +3,19 @@ /* Yep, this can be optimized quite a lot */ + +typedef struct _GimpSetHandler { + const gchar* signame; + GtkSignalFunc func; + gpointer user_data; +} GimpSetHandler; + +typedef struct { + GimpObject* object; + GArray* handlers; + guint destroy_handler; +} Node; + enum { ADD, @@ -10,6 +23,14 @@ enum LAST_SIGNAL }; +static Node* gimp_set_find_node (GimpSet* set, GimpObject* ob); +static Node* gimp_set_node_new (GimpSet* set, gpointer ob); +static void gimp_set_node_free (GimpSet* set, Node* n); + + + + + static guint gimp_set_signals [LAST_SIGNAL]; static GimpObjectClass* parent_class; @@ -18,15 +39,11 @@ static void gimp_set_destroy (GtkObject* ob) { GimpSet* set=GIMP_SET(ob); - GSList* node; - for(node=set->list;node;node=node->next){ - if(!set->weak) - gtk_object_unref(GTK_OBJECT(node->data)); - gtk_signal_emit (GTK_OBJECT(set), - gimp_set_signals[REMOVE], - node->data); - } + GSList* l; + for(l=set->list;l;l=l->next) + gimp_set_node_free(set, l->data); g_slist_free(set->list); + g_array_free(set->handlers, TRUE); GTK_OBJECT_CLASS(parent_class)->destroy (ob); } @@ -35,6 +52,7 @@ gimp_set_init (GimpSet* set) { set->list=NULL; set->type=GTK_TYPE_OBJECT; + set->handlers=g_array_new(FALSE, FALSE, sizeof(GimpSetHandler)); } static void @@ -83,21 +101,77 @@ gimp_set_destroy_cb (GtkObject* ob, gpointer data){ gimp_set_remove(set, ob); } +static Node* +gimp_set_find_node (GimpSet* set, GimpObject* ob) +{ + GSList* l = set->list; + for(l = set->list; l; l = l->next){ + Node* n = l->data; + if (n->object == ob) + return n; + } + return NULL; +} + +static Node* +gimp_set_node_new (GimpSet* set, gpointer ob) +{ + gint i; + Node* n = g_new(Node, 1); + n->object = ob; + n->handlers = g_array_new(FALSE, FALSE, sizeof(guint)); + g_array_set_size(n->handlers, set->handlers->len); + for(i = 0;i < n->handlers->len; i++){ + GimpSetHandler* h + = &g_array_index(set->handlers, GimpSetHandler, i); + if(h->signame) + g_array_index(n->handlers, guint, i) + = gtk_signal_connect(GTK_OBJECT(ob), + h->signame, + h->func, + h->user_data); + } + if(set->weak) + n->destroy_handler + = gtk_signal_connect(GTK_OBJECT(ob), + "destroy", + GTK_SIGNAL_FUNC(gimp_set_destroy_cb), + set); + return n; +} + +static void +gimp_set_node_free (GimpSet* set, Node* n) +{ + gint i; + GimpObject* ob = n->object; + for(i=0;i < set->handlers->len; i++){ + GimpSetHandler* h + = &g_array_index(set->handlers, GimpSetHandler, i); + if(h->signame) + gtk_signal_disconnect(GTK_OBJECT(ob), + g_array_index(n->handlers, + guint, + i)); + } + if(set->weak) + gtk_signal_disconnect(GTK_OBJECT(ob), + n->destroy_handler); + g_array_free(n->handlers, TRUE); + g_free(n); +} + + gboolean gimp_set_add (GimpSet* set, gpointer val) { g_return_val_if_fail(set, FALSE); g_return_val_if_fail(GTK_CHECK_TYPE(val, set->type), FALSE); - if(g_slist_find(set->list, val)) + if(gimp_set_find_node(set, val)) return FALSE; - set->list=g_slist_prepend(set->list, val); - if(set->weak) - gtk_signal_connect(GTK_OBJECT(val), "destroy", - GTK_SIGNAL_FUNC(gimp_set_destroy_cb), set); - else - gtk_object_ref(GTK_OBJECT(val)); + set->list=g_slist_prepend(set->list, gimp_set_node_new(set, val)); gtk_signal_emit (GTK_OBJECT(set), gimp_set_signals[ADD], val); return TRUE; @@ -105,38 +179,92 @@ gimp_set_add (GimpSet* set, gpointer val) gboolean gimp_set_remove (GimpSet* set, gpointer val) { + Node* n; + g_return_val_if_fail(set, FALSE); - if(!g_slist_find(set->list, val)) - return FALSE; - - set->list=g_slist_remove(set->list, val); + n = gimp_set_find_node (set, val); + g_return_val_if_fail(n, FALSE); gtk_signal_emit (GTK_OBJECT(set), gimp_set_signals[REMOVE], val); - if(set->weak) - gtk_signal_disconnect_by_func - (GTK_OBJECT(val), - GTK_SIGNAL_FUNC(gimp_set_destroy_cb), - set); - else - gtk_object_unref(GTK_OBJECT(val)); - + gimp_set_node_free(set, n); + + set->list=g_slist_remove(set->list, n); return TRUE; } gboolean gimp_set_have (GimpSet* set, gpointer val) { - return g_slist_find(set->list, val)?TRUE:FALSE; + return !!gimp_set_find_node(set, val); } void gimp_set_foreach(GimpSet* set, GFunc func, gpointer user_data) { - g_slist_foreach(set->list, func, user_data); + GSList* l; + for(l=set->list; l;l=l->next){ + Node* n = l->data; + func(n->object, user_data); + } } GtkType gimp_set_type (GimpSet* set){ return set->type; } + +GimpSetHandlerId +gimp_set_add_handler(GimpSet* set, const gchar* signame, + GtkSignalFunc handler, gpointer user_data){ + GimpSetHandler h; + GSList* l; + guint a; + + g_assert(signame); + + h.signame = signame; + h.func = handler; + h.user_data = user_data; + + for(a=0;ahandlers->len;a++) + if(!g_array_index(set->handlers, GimpSetHandler, a).signame) + break; + if(ahandlers->len){ + g_array_index(set->handlers, GimpSetHandler, a) = h; + for(l=set->list;l;l=l->next){ + Node* n = l->data; + guint i = gtk_signal_connect(GTK_OBJECT(n->object), + signame, + handler, + user_data); + g_array_index(n->handlers, guint, a) = i; + } + } else{ + g_array_append_val(set->handlers, h); + for(l=set->list;l;l=l->next){ + Node* n = l->data; + guint i = gtk_signal_connect(GTK_OBJECT(n->object), + signame, + handler, + user_data); + g_array_append_val(n->handlers, i); + } + } + return a; +} + +void +gimp_set_remove_handler(GimpSet* set, GimpSetHandlerId id) +{ + GSList* l; + for(l=set->list;l;l=l->next){ + Node* n = l->data; + gtk_signal_disconnect(GTK_OBJECT(n->object), + g_array_index(n->handlers, guint, id)); + } + g_array_index(set->handlers, GimpSetHandler, id).signame = NULL; +} + + + diff --git a/app/gimpset.h b/app/gimpset.h index 5bf32c2ee4..32a3cc0c0a 100644 --- a/app/gimpset.h +++ b/app/gimpset.h @@ -23,6 +23,7 @@ remove */ +typedef guint GimpSetHandlerId; guint gimp_set_get_type (void); @@ -35,4 +36,11 @@ void gimp_set_foreach(GimpSet* gimpset, GFunc func, gpointer user_data); gint gimp_set_size (GimpSet* gimpset); +GimpSetHandlerId gimp_set_add_handler (GimpSet* set, + const gchar* signame, + GtkSignalFunc handler, + gpointer user_data); +void gimp_set_remove_handler (GimpSet* set, + GimpSetHandlerId id); + #endif diff --git a/app/gimpsetP.h b/app/gimpsetP.h index 1119622bba..9d92dd8cd7 100644 --- a/app/gimpsetP.h +++ b/app/gimpsetP.h @@ -8,6 +8,7 @@ struct _GimpSet{ GimpObject gobject; GtkType type; GSList* list; + GArray* handlers; gboolean weak; }; diff --git a/app/gui/commands.c b/app/gui/commands.c index 912b278b69..91722d394d 100644 --- a/app/gui/commands.c +++ b/app/gui/commands.c @@ -27,6 +27,8 @@ #include "by_color_select.h" #include "channels_dialog.h" #include "colormaps.h" +#include "colormap_dialog.i.h" +#include "color_area.h" #include "color_balance.h" #include "commands.h" #include "convert.h" @@ -49,7 +51,6 @@ #include "histogram_tool.h" #include "hue_saturation.h" #include "image_render.h" -#include "indexed_palette.h" #include "info_window.h" #include "interface.h" #include "invert.h" @@ -1028,15 +1029,30 @@ dialogs_lc_cmd_callback (GtkWidget *widget, lc_dialog_create (gdisp->gimage); } +static void +cmap_dlg_sel_cb(ColormapDialog* dlg, gpointer user_data) +{ + guchar* c; + + GimpImage* img = colormap_dialog_image(dlg); + c = &img->cmap[colormap_dialog_col_index(dlg) * 3]; + if(active_color == FOREGROUND) + palette_set_foreground (c[0], c[1], c[2]); + else if(active_color == BACKGROUND) + palette_set_background (c[0], c[1], c[2]); +} + void dialogs_indexed_palette_cmd_callback (GtkWidget *widget, gpointer client_data) { - GDisplay *gdisp; - - gdisp = gdisplay_active (); - - indexed_palette_create (gdisp->gimage); + static ColormapDialog* cmap_dlg; + if(!cmap_dlg){ + cmap_dlg = colormap_dialog_create (image_context); + colormap_dialog_connect_selected(cmap_dlg_sel_cb, NULL, + cmap_dlg); + } + gtk_widget_show(GTK_WIDGET(cmap_dlg)); } void diff --git a/app/gui/help-commands.c b/app/gui/help-commands.c index 912b278b69..91722d394d 100644 --- a/app/gui/help-commands.c +++ b/app/gui/help-commands.c @@ -27,6 +27,8 @@ #include "by_color_select.h" #include "channels_dialog.h" #include "colormaps.h" +#include "colormap_dialog.i.h" +#include "color_area.h" #include "color_balance.h" #include "commands.h" #include "convert.h" @@ -49,7 +51,6 @@ #include "histogram_tool.h" #include "hue_saturation.h" #include "image_render.h" -#include "indexed_palette.h" #include "info_window.h" #include "interface.h" #include "invert.h" @@ -1028,15 +1029,30 @@ dialogs_lc_cmd_callback (GtkWidget *widget, lc_dialog_create (gdisp->gimage); } +static void +cmap_dlg_sel_cb(ColormapDialog* dlg, gpointer user_data) +{ + guchar* c; + + GimpImage* img = colormap_dialog_image(dlg); + c = &img->cmap[colormap_dialog_col_index(dlg) * 3]; + if(active_color == FOREGROUND) + palette_set_foreground (c[0], c[1], c[2]); + else if(active_color == BACKGROUND) + palette_set_background (c[0], c[1], c[2]); +} + void dialogs_indexed_palette_cmd_callback (GtkWidget *widget, gpointer client_data) { - GDisplay *gdisp; - - gdisp = gdisplay_active (); - - indexed_palette_create (gdisp->gimage); + static ColormapDialog* cmap_dlg; + if(!cmap_dlg){ + cmap_dlg = colormap_dialog_create (image_context); + colormap_dialog_connect_selected(cmap_dlg_sel_cb, NULL, + cmap_dlg); + } + gtk_widget_show(GTK_WIDGET(cmap_dlg)); } void diff --git a/app/gui/preferences-dialog.c b/app/gui/preferences-dialog.c index 296d7ef67a..0967af7fb1 100644 --- a/app/gui/preferences-dialog.c +++ b/app/gui/preferences-dialog.c @@ -28,7 +28,6 @@ #include "histogram_tool.h" #include "hue_saturation.h" #include "image_render.h" -#include "indexed_palette.h" #include "info_window.h" #include "interface.h" #include "invert.h" diff --git a/app/indexed_palette.c b/app/indexed_palette.c deleted file mode 100644 index 4f87e232f4..0000000000 --- a/app/indexed_palette.c +++ /dev/null @@ -1,541 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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. - */ -#include -#include -#include -#include "gdk/gdkkeysyms.h" -#include "appenv.h" -#include "actionarea.h" -#include "buildmenu.h" -#include "colormaps.h" -#include "color_select.h" -#include "color_area.h" -#include "errors.h" -#include "gdisplay.h" -#include "gimage.h" -#include "gimprc.h" -#include "general.h" -#include "image_render.h" -#include "interface.h" -#include "indexed_palette.h" -#include "palette.h" -#include "undo.h" - -#include "libgimp/gimpintl.h" - -#define EVENT_MASK GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK - -#define CELL_WIDTH 12 -#define CELL_HEIGHT 12 -#define P_AREA_WIDTH (CELL_WIDTH * 16) -#define P_AREA_HEIGHT (CELL_HEIGHT * 16) - -/* Add these features: - * - * load/save colormaps - * requantize - * add color--by clicking in the checked region - * all changes need to flush colormap lookup cache - */ - -typedef struct _IndexedPalette IndexedPalette; - -struct _IndexedPalette { - GtkWidget *shell; - GtkWidget *vbox; - GtkWidget *palette; - GtkWidget *image_menu; - GtkWidget *image_option_menu; - - /* state information */ - GimpImage* gimage; - int col_index; -}; - -/* indexed palette routines */ -static void indexed_palette_draw (void); -static void indexed_palette_clear (void); -static void indexed_palette_update (GimpImage*); - -/* indexed palette menu callbacks */ -static void indexed_palette_close_callback (GtkWidget *, gpointer); -static void indexed_palette_select_callback (int, int, int, ColorSelectState, void *); - -/* event callback */ -static gint indexed_palette_area_events (GtkWidget *, GdkEvent *); - -/* create image menu */ -static void image_menu_callback (GtkWidget *, gpointer); -static GtkWidget * create_image_menu (GimpImage**, int *, MenuItemCallback); - -/* Only one indexed palette */ -static IndexedPalette *indexedP = NULL; - -/* Color select dialog */ -static ColorSelectP color_select = NULL; -static int color_select_active = 0; - -/* the action area structure */ -static ActionAreaItem action_items[] = -{ - { N_("Close"), indexed_palette_close_callback, NULL, NULL }, -}; - -static MenuItem indexed_color_ops[] = -{ - { N_("Close"), 'W', GDK_CONTROL_MASK, - indexed_palette_close_callback, NULL, NULL, NULL }, - { NULL, 0, 0, NULL, NULL, NULL, NULL }, -}; - - -/**************************************/ -/* Public indexed palette functions */ -/**************************************/ - -void -indexed_palette_create (GimpImage* gimage) -{ - GtkWidget *vbox; - GtkWidget *frame; - GtkWidget *util_box; - GtkWidget *label; - GtkWidget *arrow_hbox; - GtkWidget *arrow; - GtkWidget *ops_menu; - GtkWidget *menu_bar; - GtkWidget *menu_bar_item; - GtkWidget *hbox; - GtkWidget *hbox2; - GtkWidget *vbox2; - GtkAccelGroup *accel_group; - int default_index; - - if (!indexedP) - { - indexedP = g_malloc (sizeof (IndexedPalette)); - indexedP->gimage = NULL; - - accel_group = gtk_accel_group_new (); - - /* The shell and main vbox */ - indexedP->shell = gtk_dialog_new (); - gtk_window_set_wmclass (GTK_WINDOW (indexedP->shell), "indexed_color_palette", "Gimp"); - gtk_window_set_policy (GTK_WINDOW (indexedP->shell), FALSE, TRUE, TRUE); - gtk_window_set_title (GTK_WINDOW (indexedP->shell), _("Indexed Color Palette")); - gtk_window_add_accel_group (GTK_WINDOW (indexedP->shell), accel_group); - gtk_signal_connect (GTK_OBJECT (indexedP->shell), "delete_event", - GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete), - NULL); - gtk_quit_add_destroy (1, GTK_OBJECT (indexedP->shell)); - - indexedP->vbox = vbox = gtk_vbox_new (FALSE, 1); - gtk_container_border_width (GTK_CONTAINER (vbox), 1); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (indexedP->shell)->vbox), vbox, TRUE, TRUE, 0); - - /* The hbox to hold the command menu and image option menu box */ - util_box = gtk_hbox_new (FALSE, 1); - gtk_box_pack_start (GTK_BOX (vbox), util_box, FALSE, FALSE, 0); - - /* The GIMP image option menu */ - label = gtk_label_new (_("Image:")); - gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2); - indexedP->image_option_menu = gtk_option_menu_new (); - gtk_box_pack_start (GTK_BOX (util_box), indexedP->image_option_menu, TRUE, TRUE, 2); - gtk_widget_show (indexedP->image_option_menu); - indexedP->image_menu = create_image_menu (&gimage, &default_index, image_menu_callback); - gtk_option_menu_set_menu (GTK_OPTION_MENU (indexedP->image_option_menu), indexedP->image_menu); - if (default_index != -1) - gtk_option_menu_set_history (GTK_OPTION_MENU (indexedP->image_option_menu), default_index); - gtk_widget_show (label); - - /* The indexed palette commands pulldown menu */ - ops_menu = build_menu (indexed_color_ops, accel_group); - - menu_bar = gtk_menu_bar_new (); - gtk_box_pack_start (GTK_BOX (util_box), menu_bar, FALSE, FALSE, 2); - menu_bar_item = gtk_menu_item_new (); - gtk_container_add (GTK_CONTAINER (menu_bar), menu_bar_item); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_bar_item), ops_menu); - arrow_hbox = gtk_hbox_new (FALSE, 1); - gtk_container_add (GTK_CONTAINER (menu_bar_item), arrow_hbox); - label = gtk_label_new (_("Operations")); - arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); - gtk_box_pack_start (GTK_BOX (arrow_hbox), arrow, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (arrow_hbox), label, FALSE, FALSE, 4); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_misc_set_alignment (GTK_MISC (arrow), 0.5, 0.5); - - gtk_widget_show (arrow); - gtk_widget_show (label); - gtk_widget_show (arrow_hbox); - gtk_widget_show (menu_bar_item); - gtk_widget_show (menu_bar); - gtk_widget_show (util_box); - - vbox2 = gtk_vbox_new (TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), vbox2, TRUE, FALSE, 4); - hbox2 = gtk_hbox_new (TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox2), hbox2, TRUE, FALSE, 4); - /* The palette frame */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_box_pack_start (GTK_BOX (hbox2), frame, FALSE, FALSE, 2); - indexedP->palette = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_size (GTK_PREVIEW (indexedP->palette), - P_AREA_WIDTH, P_AREA_HEIGHT); - gtk_widget_set_events (indexedP->palette, EVENT_MASK); - gtk_signal_connect (GTK_OBJECT (indexedP->palette), "event", - (GtkSignalFunc) indexed_palette_area_events, - NULL); - gtk_container_add (GTK_CONTAINER (frame), indexedP->palette); - - gtk_widget_show (indexedP->palette); - gtk_widget_show (frame); - gtk_widget_show (hbox2); - gtk_widget_show (vbox2); - - /* some helpful hints */ - hbox = gtk_hbox_new(FALSE, 1); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 1); - label = gtk_label_new (_("Click to select color. Right-click to edit color")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); - - gtk_widget_show (hbox); - gtk_widget_show (label); - /* The action area */ - action_items[0].user_data = indexedP; - build_action_area (GTK_DIALOG (indexedP->shell), action_items, 1, 0); - - gtk_widget_show (vbox); - gtk_widget_show (indexedP->shell); - - indexed_palette_update (gimage); - indexed_palette_update_image_list (); - } - else - { - if (!GTK_WIDGET_VISIBLE (indexedP->shell)) - gtk_widget_show (indexedP->shell); - - indexed_palette_update (gimage); - indexed_palette_update_image_list (); - } -} - -void -indexed_palette_update_image_list () -{ - int default_index; - GimpImage* default_gimage; - - if (! indexedP) - return; - - default_gimage = indexedP->gimage; - indexedP->image_menu = create_image_menu (&default_gimage, &default_index, image_menu_callback); - gtk_option_menu_set_menu (GTK_OPTION_MENU (indexedP->image_option_menu), indexedP->image_menu); - - if (default_index != -1) - { - if (! GTK_WIDGET_IS_SENSITIVE (indexedP->vbox)) - gtk_widget_set_sensitive (indexedP->vbox, TRUE); - gtk_option_menu_set_history (GTK_OPTION_MENU (indexedP->image_option_menu), default_index); - - indexed_palette_update (default_gimage); - } - else - { - if (GTK_WIDGET_IS_SENSITIVE (indexedP->vbox)) - { - gtk_widget_set_sensitive (indexedP->vbox, FALSE); - indexed_palette_clear (); - } - } -} - -static void -indexed_palette_draw () -{ - GImage *gimage; - int i, j, k, l, b; - int col; - guchar row[P_AREA_WIDTH * 3]; - - if (!indexedP) - return; - if ((gimage = indexedP->gimage) == NULL) - return; - - col = 0; - for (i = 0; i < 16; i++) - { - for (j = 0; j < 16 && col < gimage->num_cols; j++, col++) - { - for (k = 0; k < CELL_WIDTH; k++) - for (b = 0; b < 3; b++) - row[(j * CELL_WIDTH + k) * 3 + b] = gimage->cmap[col * 3 + b]; - } - - for (k = 0; k < CELL_HEIGHT; k++) - { - for (l = j * CELL_WIDTH; l < 16 * CELL_WIDTH; l++) - for (b = 0; b < 3; b++) - row[l * 3 + b] = ((((i * CELL_HEIGHT + k) & 0x4) ? (l) : (l + 0x4)) & 0x4) ? - blend_light_check[0] : blend_dark_check[0]; - - gtk_preview_draw_row (GTK_PREVIEW (indexedP->palette), row, 0, - i * CELL_HEIGHT + k, P_AREA_WIDTH); - } - } - - gtk_widget_draw (indexedP->palette, NULL); -} - -static void -indexed_palette_clear () -{ - int i, j; - int offset; - guchar row[P_AREA_WIDTH * 3]; - - if (!indexedP) - return; - - for (i = 0; i < P_AREA_HEIGHT; i += 4) - { - offset = (i & 0x4) ? 0x4 : 0x0; - - for (j = 0; j < P_AREA_WIDTH; j++) - { - row[j * 3 + 0] = row[j * 3 + 1] = row[j * 3 + 2] = - ((j + offset) & 0x4) ? blend_light_check[0] : blend_dark_check[0]; - } - - for (j = 0; j < 4; j++) - gtk_preview_draw_row (GTK_PREVIEW (indexedP->palette), row, 0, i + j, P_AREA_WIDTH); - } - - gtk_widget_draw (indexedP->palette, NULL); -} - -static void -indexed_palette_update (GimpImage* gimage) -{ - if (!indexedP || !gimage) - return; - - if (gimage_base_type (gimage) == INDEXED) - { - indexedP->gimage = gimage; - indexed_palette_draw (); - } -} - -static void -indexed_palette_close_callback (GtkWidget *w, - gpointer client_data) -{ - if (!indexedP) - return; - - gtk_widget_hide (indexedP->shell); -} - -static void -indexed_palette_select_callback (int r, - int g, - int b, - ColorSelectState state, - void *client_data) -{ - GImage *gimage; - - if (!indexedP) - return; - - if ((gimage = indexedP->gimage) == NULL) - return; - - if (color_select ) - { - switch (state) { - case COLOR_SELECT_UPDATE: - break; - case COLOR_SELECT_OK: - gimage->cmap[indexedP->col_index * 3 + 0] = r; - gimage->cmap[indexedP->col_index * 3 + 1] = g; - gimage->cmap[indexedP->col_index * 3 + 2] = b; - - gdisplays_update_full (gimage); - indexed_palette_draw (); - /* Fallthrough */ - case COLOR_SELECT_CANCEL: - color_select_hide (color_select); - color_select_active = FALSE; - } - } -} - -static gint -indexed_palette_area_events (GtkWidget *widget, - GdkEvent * event) -{ - GImage *gimage; - GdkEventButton *bevent; - guchar r, g, b; - - if (!indexedP) - return FALSE; - - if ((gimage = indexedP->gimage) == NULL) - return FALSE; - - switch (event->type) - { - case GDK_BUTTON_PRESS: - bevent = (GdkEventButton *) event; - - if (bevent->button == 1) - { - indexedP->col_index = 16 * ((int)bevent->y / CELL_HEIGHT) + ((int)bevent->x / CELL_WIDTH); - r = gimage->cmap[indexedP->col_index * 3 + 0]; - g = gimage->cmap[indexedP->col_index * 3 + 1]; - b = gimage->cmap[indexedP->col_index * 3 + 2]; - if (active_color == FOREGROUND) - palette_set_foreground (r, g, b); - else if (active_color == BACKGROUND) - palette_set_background (r, g, b); - } - - if (bevent->button == 3) - { - indexedP->col_index = 16 * ((int)bevent->y / CELL_HEIGHT) + ((int)bevent->x / CELL_WIDTH); - r = gimage->cmap[indexedP->col_index * 3 + 0]; - g = gimage->cmap[indexedP->col_index * 3 + 1]; - b = gimage->cmap[indexedP->col_index * 3 + 2]; - - if (! color_select) - { - color_select = color_select_new (r, g, b, indexed_palette_select_callback, NULL, FALSE); - color_select_active = 1; - } - else - { - if (! color_select_active) - color_select_show (color_select); - color_select_set_color (color_select, r, g, b, 1); - } - } - break; - - default: - break; - } - - return FALSE; -} - -static void -image_menu_callback (GtkWidget *w, - gpointer client_data) -{ - if (!indexedP) - return; - indexed_palette_update (GIMP_IMAGE(client_data)); -} - -typedef struct{ - GImage** def; - int* default_index; - MenuItemCallback callback; - GtkWidget* menu; - int num_items; - GImage* id; -}IMCBData; - -static void -create_image_menu_cb (gpointer im, gpointer d) -{ - GimpImage* gimage = GIMP_IMAGE (im); - IMCBData* data = (IMCBData*)d; - char* image_name; - char* menu_item_label; - GtkWidget *menu_item; - - if (gimage_base_type(gimage) != INDEXED) - return; - - /* make sure the default index gets set to _something_, if possible */ - if (*data->default_index == -1) - { - data->id = gimage; - *data->default_index = data->num_items; - } - - if (gimage == *data->def) - { - data->id = *data->def; - *data->default_index = data->num_items; - } - - image_name = prune_filename (gimage_filename (gimage)); - menu_item_label = g_strdup_printf ("%s-%d", image_name, - pdb_image_to_id (gimage)); - menu_item = gtk_menu_item_new_with_label (menu_item_label); - gtk_signal_connect (GTK_OBJECT (menu_item), "activate", - (GtkSignalFunc) data->callback, - (gpointer) ((long) gimage)); - gtk_container_add (GTK_CONTAINER (data->menu), menu_item); - gtk_widget_show (menu_item); - - g_free (menu_item_label); - data->num_items ++; -} - - -static GtkWidget * -create_image_menu (GimpImage** def, - int *default_index, - MenuItemCallback callback) -{ - IMCBData data; - - data.def = def; - data.default_index = default_index; - data.callback = callback; - data.menu = gtk_menu_new (); - data.num_items = 0; - data.id = NULL; - - *default_index = -1; - - gimage_foreach (create_image_menu_cb, &data); - - if (!data.num_items) - { - GtkWidget* menu_item; - menu_item = gtk_menu_item_new_with_label (_("none")); - gtk_container_add (GTK_CONTAINER (data.menu), menu_item); - gtk_widget_show (menu_item); - } - - *def = data.id; - - return data.menu; -} diff --git a/app/indexed_palette.h b/app/indexed_palette.h deleted file mode 100644 index abf8bd18f1..0000000000 --- a/app/indexed_palette.h +++ /dev/null @@ -1,26 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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. - */ -#ifndef __INDEXED_COLOR_H__ -#define __INDEXED_COLOR_H__ - -/* indexed color palette functions */ -void indexed_palette_create (GimpImage*); -void indexed_palette_update_image_list (void); -void indexed_palette_free (void); - -#endif /* __INDEXED_COLOR_H__ */ diff --git a/app/main.c b/app/main.c index 9c5d830570..0450592d85 100644 --- a/app/main.c +++ b/app/main.c @@ -43,6 +43,10 @@ static RETSIGTYPE on_signal (int); static RETSIGTYPE on_sig_child (int); static void init (void); static void test_gserialize(); +static void on_error (const gchar* domain, + GLogLevelFlags flags, + const gchar* msg, + gpointer user_data); /* GLOBAL data */ int no_interface; @@ -309,6 +313,11 @@ main (int argc, char **argv) /* Handle child exits */ signal (SIGCHLD, on_sig_child); + g_log_set_handler(NULL, + G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL, + on_error, + NULL); + /* Keep the command line arguments--for use in gimp_init */ gimp_argc = argc - 1; gimp_argv = argv + 1; @@ -330,6 +339,17 @@ init () gimp_init (gimp_argc, gimp_argv); } + +static void +on_error (const gchar* domain, + GLogLevelFlags flags, + const gchar* msg, + gpointer user_data){ + fprintf(stderr, "%s: fatal error: %s\n", + prog_name, msg); + g_on_error_query(prog_name); +} + static int caught_fatal_sig = 0; static RETSIGTYPE diff --git a/app/preferences_dialog.c b/app/preferences_dialog.c index 296d7ef67a..0967af7fb1 100644 --- a/app/preferences_dialog.c +++ b/app/preferences_dialog.c @@ -28,7 +28,6 @@ #include "histogram_tool.h" #include "hue_saturation.h" #include "image_render.h" -#include "indexed_palette.h" #include "info_window.h" #include "interface.h" #include "invert.h" diff --git a/app/undo.c b/app/undo.c index b2cb9ea104..b6e38f83ed 100644 --- a/app/undo.c +++ b/app/undo.c @@ -28,7 +28,6 @@ #include "gdisplay_ops.h" #include "gimage_mask.h" #include "gimprc.h" -#include "indexed_palette.h" #include "layer.h" #include "paint_core.h" #include "paint_funcs.h" @@ -1987,7 +1986,7 @@ undo_pop_gimage_mod (GImage *gimage, gdisplays_update_full (gimage); gdisplays_update_title (gimage); - indexed_palette_update_image_list (); + gimp_image_colormap_changed (gimage, -1); if (gimage->width != (int) data[0] || gimage->height != (int) data[1]) shrink_wrap = TRUE;