colormap_dialog.i.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. #include "config.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <gdk/gdkkeysyms.h>
  6. #include "color_notebook.h"
  7. #include "image_render.h"
  8. #include "dialog_handler.h"
  9. #include "colormaps.h"
  10. #include "color_area.h"
  11. #include "gimpdnd.h"
  12. #include "gimpui.h"
  13. #include "libgimp/gimpmath.h"
  14. #include "libgimp/gimpintl.h"
  15. /* Add these features:
  16. *
  17. * load/save colormaps
  18. * requantize
  19. * add color--by clicking in the checked region
  20. * all changes need to flush colormap lookup cache
  21. */
  22. /* indexed palette routines */
  23. static void ipal_draw (GimpColormapDialog *ipal);
  24. static void ipal_clear (GimpColormapDialog *ipal);
  25. static void ipal_set_image (GimpColormapDialog *ipal,
  26. GimpImage *gimage);
  27. static void ipal_update_entries (GimpColormapDialog *ipal);
  28. static void ipal_set_index (GimpColormapDialog *ipal,
  29. gint i);
  30. static void ipal_draw_cell (GimpColormapDialog *ipal,
  31. gint col);
  32. static void ipal_update_image_list (GimpColormapDialog *ipal);
  33. /* indexed palette menu callbacks */
  34. static void ipal_add_callback (GtkWidget *, gpointer);
  35. static void ipal_edit_callback (GtkWidget *, gpointer);
  36. static void ipal_close_callback (GtkWidget *, gpointer);
  37. static void ipal_select_callback (gint, gint, gint, ColorNotebookState,
  38. gpointer);
  39. /* event callback */
  40. static gint ipal_area_events (GtkWidget *, GdkEvent *, GimpColormapDialog *);
  41. /* create image menu */
  42. static void image_menu_callback (GtkWidget *, gpointer);
  43. static GtkWidget * create_image_menu (GimpColormapDialog *,
  44. GimpImage **,
  45. gint *,
  46. GtkSignalFunc);
  47. static void frame_size_alloc_cb (GtkFrame *frame, GtkAllocation *alloc,
  48. GimpColormapDialog *ipal);
  49. static void window_size_req_cb (GtkWindow *win, GtkRequisition *req,
  50. GimpColormapDialog *ipal);
  51. static void index_adjustment_change_cb (GtkAdjustment *adjustment,
  52. GimpColormapDialog *ipal);
  53. static void hex_entry_change_cb (GtkEntry *entry,
  54. GimpColormapDialog *ipal);
  55. static void set_addrem_cb (GimpSet *set, GimpImage *image,
  56. GimpColormapDialog *ipal);
  57. static void image_rename_cb (GimpImage *img, GimpColormapDialog *ipal);
  58. static void image_cmap_change_cb (GimpImage *img, gint ncol,
  59. GimpColormapDialog *ipal);
  60. /* dnd stuff */
  61. static GtkTargetEntry color_palette_target_table[] =
  62. {
  63. GIMP_TARGET_COLOR
  64. };
  65. static guint n_color_palette_targets = (sizeof (color_palette_target_table) /
  66. sizeof (color_palette_target_table[0]));
  67. static void
  68. palette_drag_color (GtkWidget *widget,
  69. guchar *r,
  70. guchar *g,
  71. guchar *b,
  72. gpointer data)
  73. {
  74. GimpColormapDialog *ipal = (GimpColormapDialog *) data;
  75. guint col = ipal->dnd_col_index;
  76. GimpImage *gimage;
  77. gimage = ipal->image;
  78. *r = gimage->cmap[col * 3 + 0];
  79. *g = gimage->cmap[col * 3 + 1];
  80. *b = gimage->cmap[col * 3 + 2];
  81. }
  82. static void
  83. palette_drop_color (GtkWidget *widget,
  84. guchar r,
  85. guchar g,
  86. guchar b,
  87. gpointer data)
  88. {
  89. GimpColormapDialog *ipal = (GimpColormapDialog *) data;
  90. if (!GTK_WIDGET_IS_SENSITIVE (ipal->vbox) ||
  91. !(ipal->image->num_cols < 256))
  92. return;
  93. ipal->image->cmap[ipal->image->num_cols * 3 + 0] = r;
  94. ipal->image->cmap[ipal->image->num_cols * 3 + 1] = g;
  95. ipal->image->cmap[ipal->image->num_cols * 3 + 2] = b;
  96. ipal->image->num_cols++;
  97. gimp_image_colormap_changed (ipal->image, -1);
  98. }
  99. static void
  100. ipal_create_popup_menu (GimpColormapDialog *ipal)
  101. {
  102. GtkWidget *menu;
  103. GtkWidget *menu_item;
  104. ipal->popup_menu = menu = gtk_menu_new ();
  105. menu_item = gtk_menu_item_new_with_label (_("Add"));
  106. gtk_menu_append (GTK_MENU (menu), menu_item);
  107. gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  108. GTK_SIGNAL_FUNC (ipal_add_callback),
  109. (gpointer) ipal);
  110. gtk_widget_show (menu_item);
  111. ipal->add_item = menu_item;
  112. menu_item = gtk_menu_item_new_with_label (_("Edit"));
  113. gtk_menu_append (GTK_MENU (menu), menu_item);
  114. gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  115. GTK_SIGNAL_FUNC (ipal_edit_callback),
  116. (gpointer) ipal);
  117. gtk_widget_show (menu_item);
  118. }
  119. /**************************************/
  120. /* Public indexed palette functions */
  121. /**************************************/
  122. #define COLORMAP_DIALOG_CREATE ipal_create
  123. GimpColormapDialog *
  124. ipal_create (GimpSet *context)
  125. {
  126. GimpColormapDialog *ipal;
  127. GtkWidget *vbox;
  128. GtkWidget *frame;
  129. GtkWidget *util_box;
  130. GtkWidget *label;
  131. GtkWidget *hbox;
  132. GtkWidget *hbox2;
  133. GtkWidget *entry;
  134. GtkWidget *evbox;
  135. GtkAccelGroup *accel_group;
  136. ipal = gtk_type_new (GIMP_TYPE_COLORMAP_DIALOG);
  137. /* The action area */
  138. gimp_dialog_create_action_area (GTK_DIALOG (ipal),
  139. _("Close"), ipal_close_callback,
  140. ipal, NULL, NULL, TRUE, TRUE,
  141. NULL);
  142. ipal->image = NULL;
  143. ipal->context = context;
  144. ipal->cmap_changed_handler
  145. = gimp_set_add_handler (context, "colormap_changed",
  146. image_cmap_change_cb, ipal);
  147. ipal->rename_handler
  148. = gimp_set_add_handler (context, "rename",
  149. image_rename_cb, ipal);
  150. accel_group = gtk_accel_group_new ();
  151. gtk_window_set_wmclass (GTK_WINDOW (ipal), "indexed_color_palette", "Gimp");
  152. dialog_register (GTK_WIDGET (ipal));
  153. gtk_window_set_policy (GTK_WINDOW (ipal), TRUE, TRUE, TRUE);
  154. gtk_window_set_title (GTK_WINDOW (ipal), _("Indexed Color Palette"));
  155. gtk_window_add_accel_group (GTK_WINDOW (ipal), accel_group);
  156. gtk_signal_connect (GTK_OBJECT (ipal), "delete_event",
  157. GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete),
  158. NULL);
  159. ipal->vbox = vbox = gtk_vbox_new (FALSE, 2);
  160. gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  161. gtk_container_add (GTK_CONTAINER (GTK_DIALOG (ipal)->vbox), vbox);
  162. /* The hbox to hold the command menu and image option menu box */
  163. util_box = gtk_hbox_new (FALSE, 4);
  164. gtk_box_pack_start (GTK_BOX (vbox), util_box, FALSE, FALSE, 0);
  165. /* The GIMP image option menu */
  166. label = gtk_label_new (_("Image:"));
  167. gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 0);
  168. ipal->option_menu = GTK_OPTION_MENU (gtk_option_menu_new ());
  169. gtk_box_pack_start (GTK_BOX (util_box),
  170. GTK_WIDGET (ipal->option_menu),
  171. TRUE, TRUE, 0);
  172. hbox2 = gtk_hbox_new (TRUE, 0);
  173. gtk_box_pack_start (GTK_BOX (vbox), hbox2, TRUE, TRUE, 0);
  174. ipal_create_popup_menu (ipal);
  175. /* The palette frame */
  176. evbox = gtk_event_box_new ();
  177. gtk_container_set_resize_mode (GTK_CONTAINER (evbox),
  178. GTK_RESIZE_QUEUE);
  179. gtk_widget_set_usize (GTK_WIDGET (evbox), -1, 60);
  180. gtk_signal_connect (GTK_OBJECT (evbox), "size_request",
  181. GTK_SIGNAL_FUNC (window_size_req_cb),
  182. ipal);
  183. gtk_signal_connect(GTK_OBJECT (evbox), "size_allocate",
  184. GTK_SIGNAL_FUNC (frame_size_alloc_cb),
  185. ipal);
  186. gtk_box_pack_start (GTK_BOX (hbox2), evbox, TRUE, TRUE, 0);
  187. frame = gtk_frame_new (NULL);
  188. gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  189. gtk_container_add (GTK_CONTAINER (evbox), frame);
  190. ipal->palette = GTK_PREVIEW (gtk_preview_new (GTK_PREVIEW_COLOR));
  191. gtk_preview_size (ipal->palette, 256, 256);
  192. gtk_widget_set_events (GTK_WIDGET(ipal->palette), GDK_BUTTON_PRESS_MASK);
  193. ipal->event_handler =
  194. gtk_signal_connect (GTK_OBJECT (ipal->palette), "event",
  195. GTK_SIGNAL_FUNC (ipal_area_events),
  196. ipal);
  197. gtk_signal_handler_block (GTK_OBJECT (ipal->palette),
  198. ipal->event_handler);
  199. gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (ipal->palette));
  200. /* dnd stuff */
  201. gtk_drag_source_set (GTK_WIDGET (ipal->palette),
  202. GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
  203. color_palette_target_table, n_color_palette_targets,
  204. GDK_ACTION_COPY | GDK_ACTION_MOVE);
  205. gimp_dnd_color_source_set (GTK_WIDGET (ipal->palette),
  206. palette_drag_color, ipal);
  207. gtk_drag_dest_set (GTK_WIDGET (ipal->palette),
  208. GTK_DEST_DEFAULT_HIGHLIGHT |
  209. GTK_DEST_DEFAULT_MOTION |
  210. GTK_DEST_DEFAULT_DROP,
  211. color_palette_target_table, n_color_palette_targets,
  212. GDK_ACTION_COPY);
  213. gimp_dnd_color_dest_set (GTK_WIDGET (ipal->palette),
  214. palette_drop_color, ipal);
  215. /* some helpful hints */
  216. hbox = gtk_hbox_new (FALSE, 4);
  217. gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  218. label = gtk_label_new (_("Index:"));
  219. gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  220. ipal->index_spinbutton =
  221. gimp_spin_button_new ((GtkObject **) &ipal->index_adjustment,
  222. 0, 0, 0, 1, 10, 10, 1.0, 0);
  223. gtk_signal_connect (GTK_OBJECT (ipal->index_adjustment), "value_changed",
  224. GTK_SIGNAL_FUNC (index_adjustment_change_cb),
  225. ipal);
  226. gtk_box_pack_start (GTK_BOX (hbox), ipal->index_spinbutton, FALSE, FALSE, 0);
  227. label = gtk_label_new (_("Hex Triplet:"));
  228. gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  229. entry = gtk_entry_new_with_max_length (7);
  230. ipal->color_entry = GTK_ENTRY (entry);
  231. gtk_signal_connect (GTK_OBJECT (entry), "activate",
  232. GTK_SIGNAL_FUNC (hex_entry_change_cb),
  233. ipal);
  234. gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
  235. /* Connect the "F1" help key */
  236. gimp_help_connect_help_accel (GTK_WIDGET (ipal),
  237. gimp_standard_help_func,
  238. "dialogs/indexed_palette.html");
  239. gtk_widget_show_all (vbox);
  240. /* gtk_widget_show (ipal); */
  241. ipal_update_image_list (ipal);
  242. gtk_signal_connect (GTK_OBJECT (context), "add",
  243. GTK_SIGNAL_FUNC (set_addrem_cb),
  244. ipal);
  245. gtk_signal_connect (GTK_OBJECT (context), "remove",
  246. GTK_SIGNAL_FUNC (set_addrem_cb),
  247. ipal);
  248. return ipal;
  249. }
  250. static void
  251. ipal_update_image_list (GimpColormapDialog* ipal)
  252. {
  253. gint default_index;
  254. GimpImage *default_gimage;
  255. default_gimage = ipal->image;
  256. ipal->image_menu =
  257. create_image_menu (ipal,
  258. &default_gimage,
  259. &default_index,
  260. image_menu_callback);
  261. gtk_option_menu_set_menu (ipal->option_menu, ipal->image_menu);
  262. if (default_index != -1)
  263. {
  264. if (! GTK_WIDGET_IS_SENSITIVE (ipal->vbox))
  265. gtk_widget_set_sensitive (ipal->vbox, TRUE);
  266. gtk_option_menu_set_history (ipal->option_menu, default_index);
  267. }
  268. else
  269. {
  270. if (GTK_WIDGET_IS_SENSITIVE (ipal->vbox))
  271. {
  272. gtk_widget_set_sensitive (ipal->vbox, FALSE);
  273. }
  274. }
  275. ipal_set_image (ipal, default_gimage);
  276. }
  277. static void
  278. frame_size_alloc_cb (GtkFrame *frame,
  279. GtkAllocation *alloc,
  280. GimpColormapDialog *ipal)
  281. {
  282. GtkWidget *widget = GTK_WIDGET (frame);
  283. GtkAllocation allocation = *alloc;
  284. GtkRequisition requisition;
  285. if (ipal->image)
  286. ipal_draw (ipal);
  287. else
  288. ipal_clear (ipal);
  289. widget = GTK_BIN (widget)->child;
  290. gtk_widget_size_request (widget, &requisition);
  291. allocation.x = MAX (0, allocation.width - requisition.width) / 2;
  292. allocation.y = MAX (0, allocation.height - requisition.height) / 2;
  293. allocation.width = MIN (allocation.width, requisition.width);
  294. allocation.height = MIN (allocation.height, requisition.height);
  295. gtk_widget_size_allocate (widget, &allocation);
  296. }
  297. static void
  298. window_size_req_cb (GtkWindow *window,
  299. GtkRequisition *requsition,
  300. GimpColormapDialog *ipal)
  301. {
  302. requsition->width = GTK_WIDGET (window)->allocation.width;
  303. requsition->height = GTK_WIDGET (window)->allocation.height;
  304. }
  305. #define MIN_CELL_SIZE 4
  306. static void
  307. ipal_draw (GimpColormapDialog* ipal)
  308. {
  309. GimpImage *gimage;
  310. gint i, j, k, l, b;
  311. gint col;
  312. guchar *row;
  313. gint cellsize, ncol, xn, yn, width, height;
  314. GtkWidget *palette;
  315. GtkContainer *parent;
  316. g_return_if_fail (ipal);
  317. gimage = ipal->image;
  318. g_return_if_fail (gimage);
  319. palette = GTK_WIDGET (ipal->palette);
  320. parent = GTK_CONTAINER (palette->parent);
  321. width = GTK_WIDGET (parent)->allocation.width - parent->border_width;
  322. height = GTK_WIDGET (parent)->allocation.height - parent->border_width;
  323. ncol = gimage->num_cols;
  324. if (!ncol)
  325. {
  326. ipal_clear (ipal);
  327. return;
  328. }
  329. cellsize = sqrt(width * height / ncol);
  330. while (cellsize >= MIN_CELL_SIZE
  331. && (xn = width/cellsize) * (yn = height/cellsize) < ncol)
  332. cellsize--;
  333. if (cellsize < MIN_CELL_SIZE)
  334. {
  335. cellsize = MIN_CELL_SIZE;
  336. xn = yn = ceil (sqrt (ncol));
  337. }
  338. yn = ((ncol + xn - 1) / xn);
  339. width = xn * cellsize;
  340. height = yn * cellsize;
  341. ipal->xn = xn;
  342. ipal->yn = yn;
  343. ipal->cellsize = cellsize;
  344. gtk_preview_size (ipal->palette, width, height);
  345. /*gtk_container_resize_children(GTK_WIDGET(parent)->parent);*/
  346. /* req.width = width + parent->border_width;
  347. req.height = height + parent->border_width;
  348. gtk_widget_size_request(palette->parent, &req);*/
  349. /*gtk_widget_queue_resize (GTK_WIDGET(ipal));*/
  350. /*gtk_container_check_resize (GTK_WIDGET(parent)->parent);*/
  351. row = g_new (guchar, xn * cellsize * 3);
  352. col = 0;
  353. for (i = 0; i < yn; i++)
  354. {
  355. for (j = 0; j < xn && col < ncol; j++, col++)
  356. {
  357. for (k = 0; k < cellsize; k++)
  358. for (b = 0; b < 3; b++)
  359. row[(j * cellsize + k) * 3 + b] = gimage->cmap[col * 3 + b];
  360. }
  361. for (k = 0; k < cellsize; k++)
  362. {
  363. for (l = j * cellsize; l < xn * cellsize; l++)
  364. for (b = 0; b < 3; b++)
  365. row[l * 3 + b] = ((((i * cellsize + k) & 0x4) ? (l) : (l + 0x4)) & 0x4) ?
  366. blend_light_check[0] : blend_dark_check[0];
  367. gtk_preview_draw_row (ipal->palette, row, 0,
  368. i * cellsize + k, cellsize * xn);
  369. }
  370. }
  371. ipal_draw_cell (ipal, ipal->col_index);
  372. g_free (row);
  373. gtk_widget_draw (palette, NULL);
  374. }
  375. static void
  376. ipal_draw_cell (GimpColormapDialog *ipal,
  377. gint col)
  378. {
  379. guchar *row;
  380. gint cellsize, x, y, k;
  381. GdkRectangle rec;
  382. g_assert (ipal);
  383. g_assert (ipal->image);
  384. g_assert (col < ipal->image->num_cols);
  385. cellsize = ipal->cellsize;
  386. row = g_new(guchar, cellsize * 3);
  387. x = (col % ipal->xn) * cellsize;
  388. y = (col / ipal->xn) * cellsize;
  389. if (col == ipal->col_index)
  390. {
  391. for(k = 0; k < cellsize; k++)
  392. row[k*3] = row[k*3+1] = row[k*3+2] = (k & 1) * 255;
  393. gtk_preview_draw_row (ipal->palette, row, x, y, cellsize);
  394. if (!(cellsize & 1))
  395. for (k = 0; k < cellsize; k++)
  396. row[k*3] = row[k*3+1] = row[k*3+2] = ((x+y+1) & 1) * 255;
  397. gtk_preview_draw_row (ipal->palette, row, x, y+cellsize-1, cellsize);
  398. row[0]=row[1]=row[2]=255;
  399. row[cellsize*3-3] = row[cellsize*3-2] = row[cellsize*3-1]
  400. = 255 * (cellsize & 1);
  401. for (k = 1; k < cellsize - 1; k++)
  402. {
  403. row[k*3] = ipal->image->cmap[col * 3];
  404. row[k*3+1] = ipal->image->cmap[col * 3 + 1];
  405. row[k*3+2] = ipal->image->cmap[col * 3 + 2];
  406. }
  407. for (k = 1; k < cellsize - 1; k+=2)
  408. gtk_preview_draw_row (ipal->palette, row, x, y+k, cellsize);
  409. row[0] = row[1] = row[2] = 0;
  410. row[cellsize*3-3] = row[cellsize*3-2] = row[cellsize*3-1]
  411. = 255 * ((cellsize+1) & 1);
  412. for (k = 2; k < cellsize - 1; k += 2)
  413. gtk_preview_draw_row (ipal->palette, row, x, y+k, cellsize);
  414. }
  415. else
  416. {
  417. for (k = 0; k < cellsize; k++)
  418. {
  419. row[k*3] = ipal->image->cmap[col * 3];
  420. row[k*3+1] = ipal->image->cmap[col * 3 + 1];
  421. row[k*3+2] = ipal->image->cmap[col * 3 + 2];
  422. }
  423. for (k = 0; k < cellsize; k++)
  424. gtk_preview_draw_row (ipal->palette, row, x, y+k, cellsize);
  425. }
  426. rec.x = x;
  427. rec.y = y;
  428. rec.width = rec.height = cellsize;
  429. gtk_widget_draw (GTK_WIDGET (ipal->palette), &rec);
  430. }
  431. static void
  432. ipal_clear (GimpColormapDialog* ipal)
  433. {
  434. gint i, j;
  435. gint offset;
  436. gint width, height;
  437. guchar *row = NULL;
  438. GtkWidget *palette;
  439. g_return_if_fail (ipal);
  440. palette = GTK_WIDGET (ipal->palette);
  441. /* Watch out for negative values (at least on Win32) */
  442. width = (int) (gint16) palette->allocation.width;
  443. height = (int) (gint16) palette->allocation.height;
  444. if (width > 0)
  445. row = g_new (guchar, width * 3);
  446. gtk_preview_size (ipal->palette, width, height);
  447. for (i = 0; i < height; i += 4)
  448. {
  449. offset = (i & 0x4) ? 0x4 : 0x0;
  450. for (j = 0; j < width; j++)
  451. {
  452. row[j * 3 + 0] = row[j * 3 + 1] = row[j * 3 + 2] =
  453. ((j + offset) & 0x4) ? blend_light_check[0] : blend_dark_check[0];
  454. }
  455. for (j = 0; j < 4 && i+j < height; j++)
  456. gtk_preview_draw_row (ipal->palette, row, 0, i + j, width);
  457. }
  458. if (width > 0)
  459. g_free (row);
  460. gtk_widget_draw (palette, NULL);
  461. }
  462. static void
  463. ipal_update_entries (GimpColormapDialog *ipal)
  464. {
  465. if (!ipal->image)
  466. {
  467. gtk_widget_set_sensitive (ipal->index_spinbutton, FALSE);
  468. gtk_widget_set_sensitive (GTK_WIDGET (ipal->color_entry), FALSE);
  469. gtk_adjustment_set_value (ipal->index_adjustment, 0);
  470. gtk_entry_set_text (ipal->color_entry, "");
  471. }
  472. else
  473. {
  474. gchar *string;
  475. guchar *col;
  476. gtk_adjustment_set_value (ipal->index_adjustment, ipal->col_index);
  477. col = &ipal->image->cmap[ipal->col_index * 3];
  478. string = g_strdup_printf ("#%02x%02x%02x", col[0], col[1], col[2]);
  479. gtk_entry_set_text (ipal->color_entry, string);
  480. g_free (string);
  481. gtk_widget_set_sensitive (ipal->index_spinbutton, TRUE);
  482. gtk_widget_set_sensitive (GTK_WIDGET (ipal->color_entry), TRUE);
  483. }
  484. }
  485. static void
  486. ipal_set_index (GimpColormapDialog *ipal,
  487. gint i)
  488. {
  489. if (i != ipal->col_index)
  490. {
  491. gint old = ipal->col_index;
  492. ipal->col_index = i;
  493. ipal->dnd_col_index = i;
  494. ipal_draw_cell (ipal, old);
  495. ipal_draw_cell (ipal, i);
  496. ipal_update_entries (ipal);
  497. }
  498. }
  499. static void
  500. index_adjustment_change_cb (GtkAdjustment *adjustment,
  501. GimpColormapDialog *ipal)
  502. {
  503. g_return_if_fail (ipal);
  504. if (!ipal->image)
  505. return;
  506. ipal_set_index (ipal, (gint) (adjustment->value + 0.5));
  507. ipal_update_entries (ipal);
  508. }
  509. static void
  510. hex_entry_change_cb (GtkEntry *entry,
  511. GimpColormapDialog *ipal)
  512. {
  513. gchar *s;
  514. gulong i;
  515. g_return_if_fail (ipal);
  516. g_return_if_fail (ipal->image);
  517. s = gtk_entry_get_text (entry);
  518. if (sscanf (s, "#%lx", &i))
  519. {
  520. guchar *c = &ipal->image->cmap[3 * ipal->col_index];
  521. c[0] = (i & 0xFF0000) >> 16;
  522. c[1] = (i & 0x00FF00) >> 8;
  523. c[2] = (i & 0x0000FF);
  524. gimp_image_colormap_changed (ipal->image, ipal->col_index);
  525. }
  526. ipal_update_entries (ipal);
  527. }
  528. static void
  529. set_addrem_cb (GimpSet *set,
  530. GimpImage *image,
  531. GimpColormapDialog *ipal)
  532. {
  533. ipal_update_image_list (ipal);
  534. }
  535. static void
  536. image_rename_cb (GimpImage *img,
  537. GimpColormapDialog *ipal)
  538. {
  539. ipal_update_image_list (ipal);
  540. }
  541. static void
  542. image_cmap_change_cb (GimpImage *img,
  543. gint ncol,
  544. GimpColormapDialog *ipal)
  545. {
  546. if (img == ipal->image && gimp_image_base_type (img) == INDEXED)
  547. {
  548. if (ncol < 0)
  549. {
  550. ipal_draw (ipal);
  551. gtk_container_queue_resize (GTK_CONTAINER (ipal));
  552. }
  553. else
  554. {
  555. ipal_draw_cell (ipal, ncol);
  556. }
  557. if (ncol == ipal->col_index)
  558. ipal_update_entries (ipal);
  559. gtk_widget_set_sensitive (ipal->add_item, (img->num_cols < 256));
  560. if ((ipal->index_adjustment->upper + 1) < img->num_cols)
  561. {
  562. ipal->index_adjustment->upper = img->num_cols - 1;
  563. gtk_adjustment_changed (ipal->index_adjustment);
  564. }
  565. }
  566. else
  567. {
  568. ipal_update_image_list (ipal);
  569. }
  570. gdisplays_flush_now ();
  571. }
  572. static void
  573. ipal_set_image (GimpColormapDialog *ipal,
  574. GimpImage *gimage)
  575. {
  576. g_assert (ipal);
  577. if (ipal->image)
  578. {
  579. ipal->image = gimage;
  580. if (!gimage)
  581. {
  582. gtk_signal_handler_block (GTK_OBJECT (ipal->palette),
  583. ipal->event_handler);
  584. if (GTK_WIDGET_MAPPED (GTK_WIDGET (ipal)))
  585. ipal_clear (ipal);
  586. }
  587. }
  588. ipal->col_index = 0;
  589. ipal->dnd_col_index = 0;
  590. if (gimage)
  591. {
  592. if (!ipal->image)
  593. gtk_signal_handler_unblock (GTK_OBJECT (ipal->palette),
  594. ipal->event_handler);
  595. g_return_if_fail (gimp_set_have (ipal->context, gimage));
  596. g_return_if_fail (gimage_base_type (gimage) == INDEXED);
  597. ipal->image = gimage;
  598. ipal_draw (ipal);
  599. gtk_container_queue_resize (GTK_CONTAINER (ipal));
  600. ipal->index_adjustment->upper = ipal->image->num_cols - 1;
  601. gtk_adjustment_changed (ipal->index_adjustment);
  602. }
  603. else
  604. {
  605. if (ipal->color_notebook)
  606. color_notebook_hide (ipal->color_notebook);
  607. ipal->index_adjustment->upper = 0;
  608. gtk_adjustment_changed (ipal->index_adjustment);
  609. }
  610. gtk_widget_set_sensitive (ipal->add_item,
  611. (gimage && gimage->num_cols < 256));
  612. ipal_update_entries (ipal);
  613. }
  614. static void
  615. ipal_add_callback (GtkWidget *widget,
  616. gpointer data)
  617. {
  618. GimpColormapDialog *ipal = data;
  619. g_return_if_fail (ipal);
  620. g_return_if_fail (ipal->image->num_cols < 256);
  621. memcpy (&ipal->image->cmap[ipal->image->num_cols * 3],
  622. &ipal->image->cmap[ipal->col_index * 3],
  623. 3);
  624. ipal->image->num_cols++;
  625. gimp_image_colormap_changed (ipal->image, -1);
  626. }
  627. static void
  628. ipal_edit_callback (GtkWidget *widget,
  629. gpointer data)
  630. {
  631. GimpColormapDialog* ipal = data;
  632. guchar r, g, b;
  633. g_return_if_fail (ipal);
  634. r = ipal->image->cmap[ipal->col_index*3];
  635. g = ipal->image->cmap[ipal->col_index*3+1];
  636. b = ipal->image->cmap[ipal->col_index*3+2];
  637. if (! ipal->color_notebook)
  638. {
  639. ipal->color_notebook
  640. = color_notebook_new (r, g, b,
  641. ipal_select_callback, ipal, FALSE);
  642. }
  643. else
  644. {
  645. color_notebook_show (ipal->color_notebook);
  646. color_notebook_set_color (ipal->color_notebook, r, g, b, 1);
  647. }
  648. }
  649. static void
  650. ipal_close_callback (GtkWidget *widget,
  651. gpointer data)
  652. {
  653. GimpColormapDialog* ipal = data;
  654. g_assert (ipal);
  655. gtk_widget_hide (GTK_WIDGET (ipal));
  656. }
  657. static void
  658. ipal_select_callback (gint r,
  659. gint g,
  660. gint b,
  661. ColorNotebookState state,
  662. gpointer data)
  663. {
  664. GimpImage *gimage;
  665. GimpColormapDialog *ipal = data;
  666. g_return_if_fail (ipal);
  667. g_return_if_fail (ipal->image);
  668. g_return_if_fail (ipal->color_notebook);
  669. gimage = ipal->image;
  670. switch (state)
  671. {
  672. case COLOR_NOTEBOOK_UPDATE:
  673. break;
  674. case COLOR_NOTEBOOK_OK:
  675. gimage->cmap[ipal->col_index * 3 + 0] = r;
  676. gimage->cmap[ipal->col_index * 3 + 1] = g;
  677. gimage->cmap[ipal->col_index * 3 + 2] = b;
  678. gimp_image_colormap_changed (gimage, ipal->col_index);
  679. /* Fall through */
  680. case COLOR_NOTEBOOK_CANCEL:
  681. color_notebook_hide (ipal->color_notebook);
  682. }
  683. }
  684. static gint
  685. ipal_area_events (GtkWidget *widget,
  686. GdkEvent *event,
  687. GimpColormapDialog *ipal)
  688. {
  689. GimpImage *gimage;
  690. GdkEventButton *bevent;
  691. guchar r, g, b;
  692. guint col;
  693. g_assert (ipal);
  694. gimage = ipal->image;
  695. g_assert (gimage);
  696. switch (event->type)
  697. {
  698. case GDK_BUTTON_PRESS:
  699. bevent = (GdkEventButton *) event;
  700. if (bevent->button < 1 || bevent->button > 3)
  701. return FALSE;
  702. if (!(bevent->y < ipal->cellsize * ipal->yn
  703. && bevent->x < ipal->cellsize * ipal->xn))
  704. return FALSE;
  705. col = ipal->xn * ((int)bevent->y / ipal->cellsize)
  706. + ((int)bevent->x / ipal->cellsize);
  707. if (col >= ipal->image->num_cols)
  708. return FALSE;
  709. r = gimage->cmap[col * 3 + 0];
  710. g = gimage->cmap[col * 3 + 1];
  711. b = gimage->cmap[col * 3 + 2];
  712. switch (bevent->button)
  713. {
  714. case 1:
  715. ipal_set_index (ipal, col);
  716. gimp_colormap_dialog_selected (ipal);
  717. break;
  718. case 2:
  719. ipal->dnd_col_index = col;
  720. break;
  721. case 3:
  722. ipal_set_index (ipal, col);
  723. gtk_menu_popup (GTK_MENU (ipal->popup_menu), NULL, NULL,
  724. NULL, NULL, 3,
  725. bevent->time);
  726. break;
  727. default:
  728. break;
  729. }
  730. break;
  731. default:
  732. break;
  733. }
  734. return FALSE;
  735. }
  736. static void
  737. image_menu_callback (GtkWidget *widget,
  738. gpointer data)
  739. {
  740. GimpColormapDialog* ipal = gtk_object_get_data (GTK_OBJECT (widget),
  741. "colormap_dialog");
  742. GimpImage* image = GIMP_IMAGE (data);
  743. g_assert (ipal);
  744. g_assert (image);
  745. ipal_set_image (ipal, image);
  746. }
  747. typedef struct
  748. {
  749. GimpImage **def;
  750. gint *default_index;
  751. GtkSignalFunc callback;
  752. GtkWidget *menu;
  753. gint num_items;
  754. GimpImage *id;
  755. GimpColormapDialog *ipal;
  756. } IMCBData;
  757. static void
  758. create_image_menu_cb (gpointer im,
  759. gpointer d)
  760. {
  761. GimpImage* gimage = GIMP_IMAGE (im);
  762. IMCBData* data = (IMCBData *) d;
  763. gchar* image_name;
  764. gchar* menu_item_label;
  765. GtkWidget *menu_item;
  766. if (gimage_base_type (gimage) != INDEXED)
  767. return;
  768. /* make sure the default index gets set to _something_, if possible */
  769. if (*data->default_index == -1)
  770. {
  771. data->id = gimage;
  772. *data->default_index = data->num_items;
  773. }
  774. if (gimage == *data->def)
  775. {
  776. data->id = *data->def;
  777. *data->default_index = data->num_items;
  778. }
  779. image_name = g_basename (gimage_filename (gimage));
  780. menu_item_label = g_strdup_printf ("%s-%d", image_name,
  781. pdb_image_to_id (gimage));
  782. menu_item = gtk_menu_item_new_with_label (menu_item_label);
  783. gtk_object_set_data (GTK_OBJECT (menu_item), "colormap_dialog", data->ipal);
  784. gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  785. (GtkSignalFunc) data->callback,
  786. gimage);
  787. gtk_container_add (GTK_CONTAINER (data->menu), menu_item);
  788. gtk_widget_show (menu_item);
  789. g_free (menu_item_label);
  790. data->num_items ++;
  791. }
  792. static GtkWidget *
  793. create_image_menu (GimpColormapDialog *ipal,
  794. GimpImage **def,
  795. gint *default_index,
  796. GtkSignalFunc callback)
  797. {
  798. IMCBData data;
  799. data.def = def;
  800. data.default_index = default_index;
  801. data.callback = callback;
  802. data.menu = gtk_menu_new ();
  803. data.num_items = 0;
  804. data.id = NULL;
  805. data.ipal = ipal;
  806. *default_index = -1;
  807. gimp_set_foreach (ipal->context, create_image_menu_cb, &data);
  808. if (!data.num_items)
  809. {
  810. GtkWidget* menu_item;
  811. menu_item = gtk_menu_item_new_with_label (_("none"));
  812. gtk_container_add (GTK_CONTAINER (data.menu), menu_item);
  813. gtk_widget_show (menu_item);
  814. }
  815. *def = data.id;
  816. return data.menu;
  817. }