gradient_editor.c 154 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * Gradient editor module copyight (C) 1996-1997 Federico Mena Quintero
 * federico@nuclecu.unam.mx
 *
 * 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 PURIGHTE.  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
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
 */

/* Special thanks to:
 *
 * Luis Albarran (luis4@mindspring.com) - Nice UI suggestions
 *
 * Miguel de Icaza (miguel@nuclecu.unam.mx) - Pop-up menu suggestion
 *
 * Marcelo Malheiros (malheiro@dca.fee.unicamp.br) - many, many
 * suggestions, nice gradient files
 *
 * Adam Moss (adam@uunet.pipex.com) - idea for the hint bar
 *
 * Everyone on #gimp - many suggestions
 */

/* TODO:
 *
 * - Fix memory leaks: grad_free_gradient_editor() and any others
 * which I may have missed.
 *
 * - Add all of Marcelo's neat suggestions:
 *   - Hue rotate, saturation, brightness, contrast.
 *
 * - Better handling of bogus gradient files and inconsistent
 *   segments.  Do not loop indefinitely in seg_get_segment_at() if
 *   there is a missing segment between two others.
 *
 * - Add a Gradient brush mode (color changes as you move it).
 */

51
#include "config.h"
Elliot Lee's avatar
Elliot Lee committed
52 53 54 55

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
56
#ifdef HAVE_UNISTD_H
Elliot Lee's avatar
Elliot Lee committed
57
#include <unistd.h>
58
#endif
Elliot Lee's avatar
Elliot Lee committed
59 60 61 62 63 64 65

#include "appenv.h"
#include "colormaps.h"
#include "cursorutil.h"
#include "datafiles.h"
#include "errors.h"
#include "general.h"
66
#include "gimpcontext.h"
Michael Natterer's avatar
Michael Natterer committed
67
#include "gimpdnd.h"
Elliot Lee's avatar
Elliot Lee committed
68
#include "gimprc.h"
69
#include "gimpui.h"
Elliot Lee's avatar
Elliot Lee committed
70
#include "gradient.h"
Michael Natterer's avatar
Michael Natterer committed
71
#include "gradientP.h"
72
#include "gradient_header.h"
Michael Natterer's avatar
Michael Natterer committed
73
#include "gradient_select.h"
Elliot Lee's avatar
Elliot Lee committed
74

Michael Natterer's avatar
Michael Natterer committed
75
#include "libgimp/gimpenv.h"
76
#include "libgimp/gimpintl.h"
Michael Natterer's avatar
Michael Natterer committed
77
#include "libgimp/gimplimits.h"
78
#include "libgimp/gimpmath.h"
Marc Lehmann's avatar
Marc Lehmann committed
79
#include "libgimp/gimpcolorspace.h"
80

81 82 83
#include "pixmaps/zoom_in.xpm"
#include "pixmaps/zoom_out.xpm"

Elliot Lee's avatar
Elliot Lee committed
84 85 86 87
/***** Magic numbers *****/

#define EPSILON 1e-10

Michael Natterer's avatar
Michael Natterer committed
88
#define GRAD_LIST_WIDTH  300
89
#define GRAD_LIST_HEIGHT  80
Michael Natterer's avatar
Michael Natterer committed
90 91 92 93

#define GRAD_SCROLLBAR_STEP_SIZE 0.05
#define GRAD_SCROLLBAR_PAGE_SIZE 0.75

94 95 96
#define GRAD_PREVIEW_WIDTH  600
#define GRAD_PREVIEW_HEIGHT  64
#define GRAD_CONTROL_HEIGHT  10
Michael Natterer's avatar
Michael Natterer committed
97 98 99 100 101 102 103 104

#define GRAD_COLOR_BOX_WIDTH  24
#define GRAD_COLOR_BOX_HEIGHT 16

#define GRAD_NUM_COLORS 10

#define GRAD_MOVE_TIME 150 /* ms between mouse click and detection of movement in gradient control */

105 106 107 108 109 110 111 112 113 114 115 116 117
#define GRAD_PREVIEW_EVENT_MASK (GDK_EXPOSURE_MASK | \
                                 GDK_LEAVE_NOTIFY_MASK | \
				 GDK_POINTER_MOTION_MASK | \
                                 GDK_POINTER_MOTION_HINT_MASK | \
				 GDK_BUTTON_PRESS_MASK | \
                                 GDK_BUTTON_RELEASE_MASK)

#define GRAD_CONTROL_EVENT_MASK (GDK_EXPOSURE_MASK | \
				 GDK_LEAVE_NOTIFY_MASK | \
				 GDK_POINTER_MOTION_MASK | \
				 GDK_POINTER_MOTION_HINT_MASK | \
				 GDK_BUTTON_PRESS_MASK | \
				 GDK_BUTTON_RELEASE_MASK | \
Michael Natterer's avatar
Michael Natterer committed
118 119
				 GDK_BUTTON1_MOTION_MASK)

Michael Natterer's avatar
Michael Natterer committed
120 121 122 123 124 125 126
enum
{
  GRAD_UPDATE_GRADIENT = 1 << 0,
  GRAD_UPDATE_PREVIEW  = 1 << 1,
  GRAD_UPDATE_CONTROL  = 1 << 2,
  GRAD_RESET_CONTROL   = 1 << 3
};
Michael Natterer's avatar
Michael Natterer committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231

/* Gradient editor type */

typedef enum
{
  GRAD_DRAG_NONE = 0,
  GRAD_DRAG_LEFT,
  GRAD_DRAG_MIDDLE,
  GRAD_DRAG_ALL
} control_drag_mode_t;

typedef struct
{
  GtkWidget *shell;
  GdkGC     *gc;
  GtkWidget *hint_label;
  GtkWidget *clist;
  GtkWidget *scrollbar;
  GtkWidget *preview;
  GtkWidget *control;

  /*  Zoom and scrollbar  */
  guint      zoom_factor;
  GtkObject *scroll_data;

  /*  Instant update  */
  gboolean  instant_update;

  /*  Gradient preview  */
  guchar   *preview_rows[2]; /* For caching redraw info */
  gint      preview_last_x;
  gboolean  preview_button_down;

  /*  Gradient control  */
  GdkPixmap           *control_pixmap;
  grad_segment_t      *control_drag_segment; /* Segment which is being dragged */
  grad_segment_t      *control_sel_l;        /* Left segment of selection */
  grad_segment_t      *control_sel_r;        /* Right segment of selection */
  control_drag_mode_t  control_drag_mode;    /* What is being dragged? */
  guint32              control_click_time;   /* Time when mouse was pressed */
  gboolean             control_compress;     /* Compressing/expanding handles */
  gint                 control_last_x;       /* Last mouse position when dragging */
  gdouble              control_last_gx;      /* Last position (wrt gradient) when dragging */
  gdouble              control_orig_pos;     /* Original click position when dragging */

  GtkWidget *control_main_popup;              /* Popup menu */
  GtkWidget *control_blending_label;          /* Blending function label */
  GtkWidget *control_coloring_label;          /* Coloring type label */
  GtkWidget *control_splitm_label;            /* Split at midpoint label */
  GtkWidget *control_splitu_label;            /* Split uniformly label */
  GtkWidget *control_delete_menu_item;        /* Delete menu item */
  GtkWidget *control_delete_label;            /* Delete label */
  GtkWidget *control_recenter_label;          /* Re-center label */
  GtkWidget *control_redistribute_label;      /* Re-distribute label */
  GtkWidget *control_flip_label;              /* Flip label */
  GtkWidget *control_replicate_label;         /* Replicate label */
  GtkWidget *control_blend_colors_menu_item;  /* Blend colors menu item */
  GtkWidget *control_blend_opacity_menu_item; /* Blend opacity menu item */
  GtkWidget *control_left_load_popup;         /* Left endpoint load menu */
  GtkWidget *control_left_save_popup;         /* Left endpoint save menu */
  GtkWidget *control_right_load_popup;        /* Right endpoint load menu */
  GtkWidget *control_right_save_popup;        /* Right endpoint save menu */
  GtkWidget *control_blending_popup;          /* Blending function menu */
  GtkWidget *control_coloring_popup;          /* Coloring type menu */
  GtkWidget *control_sel_ops_popup;           /* Selection ops menu */

  GtkAccelGroup *accel_group;

  /*  Blending and coloring menus  */
  GtkWidget *control_blending_items[5 + 1]; /* Add 1 for the "Varies" item */
  GtkWidget *control_coloring_items[3 + 1];

  /*  Split uniformly dialog  */
  gint split_parts;

  /*  Replicate dialog  */
  gint replicate_times;

  /*  Saved colors  */
  struct
  {
    gdouble r, g, b, a;
  } saved_colors[GRAD_NUM_COLORS];

  GtkWidget *left_load_color_boxes[GRAD_NUM_COLORS + 3];
  GtkWidget *left_load_labels[GRAD_NUM_COLORS + 3];

  GtkWidget *left_save_color_boxes[GRAD_NUM_COLORS];
  GtkWidget *left_save_labels[GRAD_NUM_COLORS];

  GtkWidget *right_load_color_boxes[GRAD_NUM_COLORS + 3];
  GtkWidget *right_load_labels[GRAD_NUM_COLORS + 3];

  GtkWidget *right_save_color_boxes[GRAD_NUM_COLORS];
  GtkWidget *right_save_labels[GRAD_NUM_COLORS];

  /*  Color dialogs  */
  GtkWidget      *left_color_preview;
  grad_segment_t *left_saved_segments;
  gboolean        left_saved_dirty;

  GtkWidget      *right_color_preview;
  grad_segment_t *right_saved_segments;
  gboolean        right_saved_dirty;
} GradientEditor;
Elliot Lee's avatar
Elliot Lee committed
232 233 234

/***** Local functions *****/

235 236 237 238 239 240 241
static gint gradient_editor_clist_button_press (GtkWidget      *widget,
						GdkEventButton *bevent,
						gpointer        data);

static gradient_t * gradient_editor_drag_gradient (GtkWidget  *widget,
						   gpointer    data);

Michael Natterer's avatar
Michael Natterer committed
242 243 244 245
static void  gradient_editor_drop_gradient (GtkWidget  *widget,
					    gradient_t *gradient,
					    gpointer    data);

Elliot Lee's avatar
Elliot Lee committed
246
/* Gradient editor functions */
Michael Natterer's avatar
Michael Natterer committed
247

248
static GtkWidget *ed_create_button (gchar         *label,
249
				    gchar         *help_data,
250 251
				    GtkSignalFunc  signal_func,
				    gpointer       data);
252 253 254

static void  ed_fetch_foreground (double *fg_r, double *fg_g, double *fg_b,
				  double *fg_a);
255
static void  ed_update_editor    (int flags);
256

257
static void  ed_set_hint         (gchar *str);
258 259 260 261 262 263 264 265 266 267


static void  ed_list_item_update (GtkWidget *widget, 
				  gint row,
				  gint column,
				  GdkEventButton *event,
				  gpointer data);

static void  ed_initialize_saved_colors (void);

268
/* Main dialog button callbacks & functions */
269

270
static void  ed_new_gradient_callback       (GtkWidget *, gpointer);
Michael Natterer's avatar
Michael Natterer committed
271
static void  ed_do_new_gradient_callback    (GtkWidget *, gchar *, gpointer);
272

273
static void  ed_copy_gradient_callback      (GtkWidget *, gpointer);
Michael Natterer's avatar
Michael Natterer committed
274
static void  ed_do_copy_gradient_callback   (GtkWidget *, gchar *, gpointer);
275

Michael Natterer's avatar
Michael Natterer committed
276 277 278 279 280
static void  ed_delete_gradient_callback        (GtkWidget *widget,
						 gpointer   data);
static void  ed_do_delete_gradient_callback     (GtkWidget *widget,
						 gboolean   delete,
						 gpointer   data);
281 282

static void  ed_rename_gradient_callback    (GtkWidget *, gpointer);
Michael Natterer's avatar
Michael Natterer committed
283
static void  ed_do_rename_gradient_callback (GtkWidget *, gchar *, gpointer);
284

285 286 287 288
static void  ed_save_pov_callback           (GtkWidget *, gpointer);
static void  ed_do_save_pov_callback        (GtkWidget *, gpointer);
static void  ed_cancel_save_pov_callback    (GtkWidget *, gpointer);
static gint  ed_delete_save_pov_callback    (GtkWidget *, GdkEvent *, gpointer);
289

290 291 292 293
static void  ed_refresh_grads_callback      (GtkWidget *, gpointer);
static void  ed_close_callback              (GtkWidget *, gpointer);

/* Zoom, scrollbar & instant update callbacks */
294 295 296 297 298 299

static void  ed_scrollbar_update      (GtkAdjustment *, gpointer);
static void  ed_zoom_all_callback     (GtkWidget *, gpointer);
static void  ed_zoom_out_callback     (GtkWidget *, gpointer);
static void  ed_zoom_in_callback      (GtkWidget *, gpointer);
static void  ed_instant_update_update (GtkWidget *, gpointer);
Elliot Lee's avatar
Elliot Lee committed
300 301 302

/* Gradient preview functions */

303 304
static gint prev_events         (GtkWidget *, GdkEvent *, gpointer);
static void prev_set_hint       (gint x);
305 306 307 308

static void prev_set_foreground (gint x);
static void prev_set_background (gint x);

309
static void gradient_update     (void);
310 311 312
static void prev_update         (gboolean recalculate);
static void prev_fill_image     (int width, int height,
				 double left, double right);
Elliot Lee's avatar
Elliot Lee committed
313 314 315

/* Gradient control functions */

316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
static gint     control_events                (GtkWidget *, GdkEvent *,
					       gpointer);
static void     control_do_hint               (gint x, gint y);
static void     control_button_press          (gint x, gint y,
					       guint button, guint state);
static gboolean control_point_in_handle       (gint x, gint y,
					       grad_segment_t *seg,
					       control_drag_mode_t handle);
static void     control_select_single_segment (grad_segment_t *seg);
static void     control_extend_selection      (grad_segment_t *seg, double pos);
static void     control_motion                (gint x);

static void     control_compress_left         (grad_segment_t *range_l,
					       grad_segment_t *range_r,
					       grad_segment_t *drag_seg,
331
					       double pos);
332 333 334
static void     control_compress_range        (grad_segment_t *range_l,
					       grad_segment_t *range_r,
					       double new_l, double new_r);
335

336 337 338
static double   control_move                  (grad_segment_t *range_l,
					       grad_segment_t *range_r,
					       double delta);
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355

/* Control update/redraw functions */

static void   control_update             (gboolean recalculate);
static void   control_draw               (GdkPixmap *pixmap,
					  int width, int height,
					  double left, double right);
static void   control_draw_normal_handle (GdkPixmap *pixmap,
					  double pos, int height);
static void   control_draw_middle_handle (GdkPixmap *pixmap,
					  double pos, int height);
static void   control_draw_handle        (GdkPixmap *pixmap,
					  GdkGC *border_gc, GdkGC *fill_gc,
					  int xpos, int height);

static int    control_calc_p_pos         (double pos);
static double control_calc_g_pos         (int pos);
Elliot Lee's avatar
Elliot Lee committed
356 357 358

/* Control popup functions */

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
static void       cpopup_create_main_menu  (void);
static void       cpopup_do_popup          (void);

static GtkWidget *cpopup_create_color_item           (GtkWidget **color_box,
						      GtkWidget **label);
static GtkWidget *cpopup_create_menu_item_with_label (gchar      *str,
						      GtkWidget **label);

static void  cpopup_adjust_menus           (void);
static void  cpopup_adjust_blending_menu   (void);
static void  cpopup_adjust_coloring_menu   (void);
static void  cpopup_check_selection_params (gint *equal_blending,
					    gint *equal_coloring);

static void  cpopup_render_color_box (GtkPreview *preview,
				      double r, double g, double b, double a);

static GtkWidget *cpopup_create_load_menu (GtkWidget **color_boxes,
					   GtkWidget **labels,
					   gchar *label1, gchar *label2,
					   GtkSignalFunc callback,
					   gchar accel_key_0,
					   guint8 accel_mods_0,
					   gchar accel_key_1,
					   guint8 accel_mods_1,
					   gchar accel_key_2,
					   guint8 accel_mods_2);
static GtkWidget *cpopup_create_save_menu (GtkWidget **color_boxes,
					   GtkWidget **labels,
					   GtkSignalFunc callback);

static void  cpopup_update_saved_color  (int n,
					 double r, double g, double b, double a);

static void  cpopup_load_left_callback  (GtkWidget *, gpointer);
static void  cpopup_save_left_callback  (GtkWidget *, gpointer);
static void  cpopup_load_right_callback (GtkWidget *, gpointer);
static void  cpopup_save_right_callback (GtkWidget *, gpointer);

static void  cpopup_set_color_selection_color (GtkColorSelection *cs,
					       double r, double g,
					       double b, double a);
static void  cpopup_get_color_selection_color (GtkColorSelection *cs,
					       double *r, double *g,
					       double *b, double *a);

static grad_segment_t *cpopup_save_selection    (void);
static void            cpopup_free_selection    (grad_segment_t *seg);
static void            cpopup_replace_selection (grad_segment_t *replace_seg);

/* ----- */

static void  cpopup_create_color_dialog (gchar *title,
					 double r, double g, double b, double a,
					 GtkSignalFunc color_changed_callback,
					 GtkSignalFunc ok_callback,
					 GtkSignalFunc cancel_callback,
					 GtkSignalFunc delete_callback);

static void  cpopup_set_left_color_callback  (GtkWidget *, gpointer);
static void  cpopup_left_color_changed       (GtkWidget *, gpointer);
static void  cpopup_left_color_dialog_ok     (GtkWidget *, gpointer);
static void  cpopup_left_color_dialog_cancel (GtkWidget *, gpointer);
static int   cpopup_left_color_dialog_delete (GtkWidget *, GdkEvent *,
					      gpointer);

static void  cpopup_set_right_color_callback  (GtkWidget *, gpointer);
static void  cpopup_right_color_changed       (GtkWidget *, gpointer);
static void  cpopup_right_color_dialog_ok     (GtkWidget *, gpointer);
static void  cpopup_right_color_dialog_cancel (GtkWidget *, gpointer);
static int   cpopup_right_color_dialog_delete (GtkWidget *, GdkEvent *,
					       gpointer);

/* ----- */

static GtkWidget *cpopup_create_blending_menu (void);
static void       cpopup_blending_callback    (GtkWidget *, gpointer);
static GtkWidget *cpopup_create_coloring_menu (void);
static void       cpopup_coloring_callback    (GtkWidget *, gpointer);

/* ----- */

static void  cpopup_split_midpoint_callback (GtkWidget *, gpointer);
static void  cpopup_split_midpoint (grad_segment_t *lseg, grad_segment_t **newl,
				    grad_segment_t **newr);

static void  cpopup_split_uniform_callback        (GtkWidget *, gpointer);
static void  cpopup_split_uniform_scale_update    (GtkAdjustment *, gpointer);
static void  cpopup_split_uniform_split_callback  (GtkWidget *, gpointer);
static void  cpopup_split_uniform_cancel_callback (GtkWidget *, gpointer);
static void  cpopup_split_uniform (grad_segment_t *lseg, int parts,
				   grad_segment_t **newl, grad_segment_t **newr);

static void  cpopup_delete_callback       (GtkWidget *, gpointer);
static void  cpopup_recenter_callback     (GtkWidget *, gpointer);
static void  cpopup_redistribute_callback (GtkWidget *, gpointer);

/* Control popup -> Selection operations functions */

static GtkWidget * cpopup_create_sel_ops_menu (void);

static void  cpopup_flip_callback             (GtkWidget *, gpointer);

static void  cpopup_replicate_callback        (GtkWidget *, gpointer);
static void  cpopup_replicate_scale_update    (GtkAdjustment *, gpointer);
static void  cpopup_do_replicate_callback     (GtkWidget *, gpointer);
static void  cpopup_replicate_cancel_callback (GtkWidget *, gpointer);

static void  cpopup_blend_colors              (GtkWidget *, gpointer);
static void  cpopup_blend_opacity             (GtkWidget *, gpointer);

/* Blend function */

static void  cpopup_blend_endpoints (double r0, double g0, double b0, double a0,
				     double r1, double g1, double b1, double a1,
				     int blend_colors, int blend_opacity);
Elliot Lee's avatar
Elliot Lee committed
475 476 477

/* Gradient functions */

478 479 480 481 482 483
static gradient_t *grad_new_gradient             (void);
static void        grad_free_gradient            (gradient_t *grad);
static void        grad_free_gradients           (void);
static void        grad_load_gradient            (char *filename);
static void        grad_save_gradient            (gradient_t *grad,
						  char *filename);
484
static void        grad_save_all                 (gboolean need_free);
Elliot Lee's avatar
Elliot Lee committed
485

486
static gradient_t *grad_create_default_gradient  (void);
Elliot Lee's avatar
Elliot Lee committed
487

488
static int         grad_insert_in_gradients_list (gradient_t *grad);
Elliot Lee's avatar
Elliot Lee committed
489

490
static void        grad_dump_gradient            (gradient_t *grad, FILE *file);
491

Elliot Lee's avatar
Elliot Lee committed
492 493 494

/* Segment functions */

495 496 497
static grad_segment_t *seg_new_segment        (void);
static void            seg_free_segment       (grad_segment_t *seg);
static void            seg_free_segments      (grad_segment_t *seg);
Elliot Lee's avatar
Elliot Lee committed
498

499 500 501 502 503
static grad_segment_t *seg_get_segment_at     (gradient_t *grad, double pos);
static grad_segment_t *seg_get_last_segment   (grad_segment_t *seg);
static void            seg_get_closest_handle (gradient_t *grad, double pos,
					       grad_segment_t **seg,
					       control_drag_mode_t *handle);
Elliot Lee's avatar
Elliot Lee committed
504 505 506

/* Calculation functions */

507 508 509 510 511
static double calc_linear_factor            (double middle, double pos);
static double calc_curved_factor            (double middle, double pos);
static double calc_sine_factor              (double middle, double pos);
static double calc_sphere_increasing_factor (double middle, double pos);
static double calc_sphere_decreasing_factor (double middle, double pos);
Elliot Lee's avatar
Elliot Lee committed
512 513 514

/* Files and paths functions */

515
static gchar *build_user_filename (char *name, char *path_str);
Elliot Lee's avatar
Elliot Lee committed
516

Michael Natterer's avatar
Michael Natterer committed
517 518 519 520 521
/***** Global variables *****/

GSList * gradients_list = NULL; /* The list of gradients */
gint     num_gradients  = 0;

Elliot Lee's avatar
Elliot Lee committed
522 523
/***** Local variables *****/

Michael Natterer's avatar
Michael Natterer committed
524 525
static GdkColor         black;
static gradient_t     * curr_gradient = NULL;
526
static gradient_t     * dnd_gradient  = NULL;
Michael Natterer's avatar
Michael Natterer committed
527
static GradientEditor * g_editor      = NULL;
528 529

static gradient_t * standard_gradient = NULL;
Elliot Lee's avatar
Elliot Lee committed
530

531 532 533 534 535 536 537 538
static const gchar *blending_types[] =
{
  N_("Linear"),
  N_("Curved"),
  N_("Sinusoidal"),
  N_("Spherical (increasing)"),
  N_("Spherical (decreasing)")
};
Elliot Lee's avatar
Elliot Lee committed
539

540 541 542 543 544 545
static const gchar *coloring_types[] =
{
  N_("Plain RGB"),
  N_("HSV (counter-clockwise hue)"),
  N_("HSV (clockwise hue)")
};
Elliot Lee's avatar
Elliot Lee committed
546

Michael Natterer's avatar
Michael Natterer committed
547 548 549 550 551 552 553 554
/*  dnd stuff  */
static GtkTargetEntry gradient_target_table[] =
{
  GIMP_TARGET_GRADIENT
};
static guint n_gradient_targets = (sizeof (gradient_target_table) /
				   sizeof (gradient_target_table[0]));

Elliot Lee's avatar
Elliot Lee committed
555 556 557
/***** Public functions *****/

void
558
gradients_init (gint no_data)
Elliot Lee's avatar
Elliot Lee committed
559
{
560 561
  if (gradients_list)
    gradients_free ();
Elliot Lee's avatar
Elliot Lee committed
562

563 564
  if (gradient_path != NULL && !no_data)
    datafiles_read_directories (gradient_path, grad_load_gradient, 0);
Elliot Lee's avatar
Elliot Lee committed
565

566 567
  gimp_context_refresh_gradients ();
}
Elliot Lee's avatar
Elliot Lee committed
568 569

void
570
gradients_free (void)
Elliot Lee's avatar
Elliot Lee committed
571
{
572 573
  grad_free_gradients ();
}
Elliot Lee's avatar
Elliot Lee committed
574

575 576 577 578 579 580 581 582 583 584 585 586 587 588
gradient_t *
gradients_get_standard_gradient (void)
{
  if (! standard_gradient)
    {
      standard_gradient = grad_create_default_gradient ();
      standard_gradient->name     = g_strdup ("Standard");
      standard_gradient->filename = NULL;
      standard_gradient->dirty    = FALSE;
    }

  return standard_gradient;
}

Michael Natterer's avatar
Michael Natterer committed
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
gradient_t *
gradient_list_get_gradient (GSList *list,
			    gchar  *name)
{
  gradient_t *gradient;

  for (; list; list = g_slist_next (list))
    {
      gradient = (gradient_t *) list->data;

      if (strcmp (gradient->name, name) == 0)
	return gradient;
    }

  return NULL;
}

gint
gradient_list_get_gradient_index (GSList     *list,
				  gradient_t *gradient)
{
  gradient_t *cmp_gradient;
  gint index;

  for (index = 0; list; list = g_slist_next (list), index++)
    {
      cmp_gradient = (gradient_t *) list->data;

      if (cmp_gradient == gradient)
	return index;
    }

  return -1;
}

Elliot Lee's avatar
Elliot Lee committed
624 625 626
/*****/

void
627 628 629 630 631 632
gradient_get_color_at (gradient_t *gradient,
		       gdouble     pos,
		       gdouble    *r,
		       gdouble    *g,
		       gdouble    *b,
		       gdouble    *a)
Elliot Lee's avatar
Elliot Lee committed
633
{
634 635 636 637 638
  double          factor = 0.0;
  grad_segment_t *seg;
  double          seg_len, middle;
  double          h0, s0, v0;
  double          h1, s1, v1;
Elliot Lee's avatar
Elliot Lee committed
639

640
  /* if there is no gradient return a totally transparent black */
641
  if (gradient == NULL) 
642 643 644 645
    {
      r = 0; g = 0; b = 0; a = 0;
      return;
    }
Elliot Lee's avatar
Elliot Lee committed
646

647 648 649 650
  if (pos < 0.0)
    pos = 0.0;
  else if (pos > 1.0)
    pos = 1.0;
Elliot Lee's avatar
Elliot Lee committed
651

652
  seg = seg_get_segment_at (gradient, pos);
Elliot Lee's avatar
Elliot Lee committed
653

654
  seg_len = seg->right - seg->left;
Elliot Lee's avatar
Elliot Lee committed
655

656 657 658 659 660 661 662 663 664 665
  if (seg_len < EPSILON)
    {
      middle = 0.5;
      pos    = 0.5;
    }
  else
    {
      middle = (seg->middle - seg->left) / seg_len;
      pos    = (pos - seg->left) / seg_len;
    }
Elliot Lee's avatar
Elliot Lee committed
666

667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
  switch (seg->type)
    {
    case GRAD_LINEAR:
      factor = calc_linear_factor (middle, pos);
      break;

    case GRAD_CURVED:
      factor = calc_curved_factor (middle, pos);
      break;

    case GRAD_SINE:
      factor = calc_sine_factor (middle, pos);
      break;

    case GRAD_SPHERE_INCREASING:
      factor = calc_sphere_increasing_factor (middle, pos);
      break;

    case GRAD_SPHERE_DECREASING:
      factor = calc_sphere_decreasing_factor (middle, pos);
      break;

    default:
690
      grad_dump_gradient (gradient, stderr);
691
      gimp_fatal_error ("gradient_get_color_at(): Unknown gradient type %d",
692 693 694
			(int) seg->type);
      break;
    }
Elliot Lee's avatar
Elliot Lee committed
695

696
  /* Calculate color components */
Elliot Lee's avatar
Elliot Lee committed
697

698
  *a = seg->a0 + (seg->a1 - seg->a0) * factor;
Elliot Lee's avatar
Elliot Lee committed
699

700 701 702 703 704 705 706 707 708 709 710
  if (seg->color == GRAD_RGB)
    {
      *r = seg->r0 + (seg->r1 - seg->r0) * factor;
      *g = seg->g0 + (seg->g1 - seg->g0) * factor;
      *b = seg->b0 + (seg->b1 - seg->b0) * factor;
    }
  else
    {
      h0 = seg->r0;
      s0 = seg->g0;
      v0 = seg->b0;
Elliot Lee's avatar
Elliot Lee committed
711

712 713 714
      h1 = seg->r1;
      s1 = seg->g1;
      v1 = seg->b1;
Elliot Lee's avatar
Elliot Lee committed
715

716 717
      gimp_rgb_to_hsv_double(&h0, &s0, &v0);
      gimp_rgb_to_hsv_double(&h1, &s1, &v1);
Elliot Lee's avatar
Elliot Lee committed
718

719 720
      s0 = s0 + (s1 - s0) * factor;
      v0 = v0 + (v1 - v0) * factor;
Elliot Lee's avatar
Elliot Lee committed
721

722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
      switch (seg->color)
	{
	case GRAD_HSV_CCW:
	  if (h0 < h1)
	    h0 = h0 + (h1 - h0) * factor;
	  else
	    {
	      h0 = h0 + (1.0 - (h0 - h1)) * factor;
	      if (h0 > 1.0)
		h0 -= 1.0;
	    }
	  break;

	case GRAD_HSV_CW:
	  if (h1 < h0)
	    h0 = h0 - (h0 - h1) * factor;
	  else
	    {
	      h0 = h0 - (1.0 - (h1 - h0)) * factor;
	      if (h0 < 0.0)
		h0 += 1.0;
	    }
	  break;

	default:
747
	  grad_dump_gradient (gradient, stderr);
748
	  gimp_fatal_error ("gradient_get_color_at(): Unknown coloring mode %d",
749 750 751
			    (int) seg->color);
	  break;
	}
Elliot Lee's avatar
Elliot Lee committed
752

753 754 755
      *r = h0;
      *g = s0;
      *b = v0;
Elliot Lee's avatar
Elliot Lee committed
756

757
      gimp_hsv_to_rgb_double (r, g, b);
758 759
    }
}
Elliot Lee's avatar
Elliot Lee committed
760

761
/***** The main gradient editor dialog *****/
Elliot Lee's avatar
Elliot Lee committed
762

763
void 
Michael Natterer's avatar
Michael Natterer committed
764
gradient_editor_create (void)
Elliot Lee's avatar
Elliot Lee committed
765
{
766 767 768 769 770 771
  GtkWidget   *vbox;
  GtkWidget   *hbox;
  GtkWidget   *gvbox;
  GtkWidget   *button;
  GtkWidget   *frame;
  GtkWidget   *scrolled_win;
772
  GdkColormap *colormap;
773 774 775 776
  gchar       *titles[2];
  gint         column_width;
  gint         select_pos;
  gint         i;
777

778
  /* If the editor already exists, just show it */
779 780
  if (g_editor)
    {
781
      if (!GTK_WIDGET_VISIBLE (g_editor->shell))
Michael Natterer's avatar
Michael Natterer committed
782
	gtk_widget_show (g_editor->shell);
783 784
      else
	gdk_window_raise (g_editor->shell->window);
Elliot Lee's avatar
Elliot Lee committed
785

786 787
      return;
    }
Elliot Lee's avatar
Elliot Lee committed
788

Michael Natterer's avatar
Michael Natterer committed
789
  g_editor = g_new (GradientEditor, 1);
Elliot Lee's avatar
Elliot Lee committed
790

791
  /* Shell and main vbox */
Michael Natterer's avatar
Michael Natterer committed
792 793 794 795 796 797
  g_editor->shell =
    gimp_dialog_new (_("Gradient Editor"), "gradient_editor",
		     gimp_standard_help_func,
		     "dialogs/gradient_editor/gradient_editor.html",
		     GTK_WIN_POS_NONE,
		     FALSE, TRUE, FALSE,
798

Michael Natterer's avatar
Michael Natterer committed
799
		     _("Refresh"), ed_refresh_grads_callback,
800
		     NULL, NULL, NULL, FALSE, FALSE,
Michael Natterer's avatar
Michael Natterer committed
801
		     _("Close"), ed_close_callback,
802
		     NULL, NULL, NULL, TRUE, TRUE,
803

Michael Natterer's avatar
Michael Natterer committed
804
		     NULL);
Elliot Lee's avatar
Elliot Lee committed
805

806 807 808
  vbox = gtk_vbox_new (FALSE, 4);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (g_editor->shell)->vbox), vbox);
809
  gtk_widget_show (vbox);
Elliot Lee's avatar
Elliot Lee committed
810

811
  /* Gradients list box */
812
  hbox = gtk_hbox_new (FALSE, 4);
813 814
  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
  gtk_widget_show (hbox);
Elliot Lee's avatar
Elliot Lee committed
815

816 817
  /* clist preview of gradients */
  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
818 819 820 821 822
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
				  GTK_POLICY_AUTOMATIC,
				  GTK_POLICY_ALWAYS);
  gtk_box_pack_start (GTK_BOX (hbox), scrolled_win, TRUE, TRUE, 0); 
  gtk_widget_show (scrolled_win);
823

824 825 826
  titles[0] = _("Gradient");
  titles[1] = _("Name");
  g_editor->clist = gtk_clist_new_with_titles (2, titles);
827
  gtk_clist_set_shadow_type (GTK_CLIST (g_editor->clist), GTK_SHADOW_IN);
828 829
  gtk_clist_set_selection_mode (GTK_CLIST (g_editor->clist),
				GTK_SELECTION_BROWSE);
830
  gtk_clist_set_row_height (GTK_CLIST (g_editor->clist), 18);
831 832
  gtk_clist_set_use_drag_icons (GTK_CLIST (g_editor->clist), FALSE);
  gtk_clist_column_titles_passive (GTK_CLIST (g_editor->clist));
833
  gtk_container_add (GTK_CONTAINER (scrolled_win), g_editor->clist);
834

835 836 837 838 839
  column_width =
    MAX (50, gtk_clist_optimal_column_width (GTK_CLIST (g_editor->clist), 0));
  gtk_clist_set_column_min_width (GTK_CLIST (g_editor->clist), 0, 50);
  gtk_clist_set_column_width (GTK_CLIST (g_editor->clist), 0, column_width);

840
  gtk_widget_show (g_editor->clist);
841

842 843 844
  colormap = gtk_widget_get_colormap (g_editor->clist);
  gdk_color_parse ("black", &black);
  gdk_color_alloc (colormap, &black);
845
	
846 847 848 849
  gtk_signal_connect (GTK_OBJECT (g_editor->clist), "button_press_event",
                      GTK_SIGNAL_FUNC (gradient_editor_clist_button_press),
                      NULL);

850 851
  gtk_signal_connect (GTK_OBJECT (g_editor->clist), "select_row",
		      GTK_SIGNAL_FUNC (ed_list_item_update),
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
		      NULL);

  /*  dnd stuff  */
  gtk_drag_source_set (g_editor->clist,
		       GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
		       gradient_target_table, n_gradient_targets,
		       GDK_ACTION_COPY);
  gimp_dnd_gradient_source_set (g_editor->clist, gradient_editor_drag_gradient,
				NULL);

  gtk_drag_dest_set (g_editor->clist,
		     GTK_DEST_DEFAULT_ALL,
		     gradient_target_table, n_gradient_targets,
		     GDK_ACTION_COPY);
  gimp_dnd_gradient_dest_set (g_editor->clist, gradient_editor_drop_gradient,
			      NULL);
868

869 870 871
  /* Frame & vbox for gradient functions */
  frame = gtk_frame_new (_("Gradient Ops"));
  gtk_box_pack_end (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
872

873 874 875
  gvbox = gtk_vbox_new (FALSE, 2);
  gtk_container_set_border_width (GTK_CONTAINER (gvbox), 4);
  gtk_container_add (GTK_CONTAINER (frame), gvbox);
876 877

  /* Buttons for gradient functions */
878 879
  button = ed_create_button (_("New Gradient"),
			     "dialogs/gradient_editor/new_gradient.html",
880 881
			     GTK_SIGNAL_FUNC (ed_new_gradient_callback),
			     NULL);
882
  GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
883
  gtk_box_pack_start (GTK_BOX (gvbox), button, FALSE, FALSE, 0);
884 885
  gtk_widget_show (button);

886 887
  button = ed_create_button (_("Copy Gradient"),
			     "dialogs/gradient_editor/copy_gradient.html",
888 889
			     GTK_SIGNAL_FUNC (ed_copy_gradient_callback),
			     NULL);
890
  GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
891
  gtk_box_pack_start (GTK_BOX (gvbox), button, FALSE, FALSE, 0);
892 893
  gtk_widget_show (button);

894 895
  button = ed_create_button (_("Delete Gradient"),
			     "dialogs/gradient_editor/delete_gradient.html",
896 897
			     GTK_SIGNAL_FUNC (ed_delete_gradient_callback),
			     NULL);
898
  GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
899
  gtk_box_pack_start (GTK_BOX (gvbox), button, FALSE, FALSE, 0);
900 901
  gtk_widget_show (button);

902 903
  button = ed_create_button (_("Rename Gradient"),
			     "dialogs/gradient_editor/rename_gradient.html",
904 905
			     GTK_SIGNAL_FUNC (ed_rename_gradient_callback),
			     NULL);
906
  GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
907
  gtk_box_pack_start (GTK_BOX (gvbox), button, FALSE, FALSE, 0);
908 909
  gtk_widget_show (button);

910 911
  button = ed_create_button (_("Save as POV-Ray"),
			     "dialogs/gradient_editor/save_as_pov_ray.html",
912 913
			     GTK_SIGNAL_FUNC (ed_save_pov_callback),
			     NULL);
914
  GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
915
  gtk_box_pack_start (GTK_BOX (gvbox), button, FALSE, FALSE, 0);
916 917
  gtk_widget_show (button);

918 919
  gtk_widget_show (gvbox);
  gtk_widget_show (frame);
920

921
  /*  Horizontal box for zoom controls, scrollbar and instant update toggle  */
922
  hbox = gtk_hbox_new (FALSE, 4);
923
  gtk_container_set_border_width (GTK_CONTAINER (hbox), 0);
924
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
925 926
  gtk_widget_show (hbox);

927
  /*  Zoom all button */
Marc Lehmann's avatar
Marc Lehmann committed
928
  button = ed_create_button (_("Zoom all"), NULL,
929 930
			     GTK_SIGNAL_FUNC (ed_zoom_all_callback),
			     g_editor);
931
  GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
932 933 934
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

935 936 937
  /*  + and - buttons  */
  gtk_widget_realize (g_editor->shell);

938
  button = gimp_pixmap_button_new (zoom_in_xpm, NULL);
939 940 941 942
  GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (ed_zoom_in_callback),
		      (gpointer) g_editor);
943
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
944 945
  gtk_widget_show (button);

946
  button = gimp_pixmap_button_new (zoom_out_xpm, NULL);
947 948 949 950
  GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (ed_zoom_out_callback),
		      (gpointer) g_editor);
951 952 953
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

954
  /*  Scrollbar  */
955 956 957 958 959 960 961 962
  g_editor->zoom_factor = 1;

  g_editor->scroll_data = gtk_adjustment_new (0.0, 0.0, 1.0,
					      1.0 * GRAD_SCROLLBAR_STEP_SIZE,
					      1.0 * GRAD_SCROLLBAR_PAGE_SIZE,
					      1.0);

  gtk_signal_connect (g_editor->scroll_data, "value_changed",
963
		      GTK_SIGNAL_FUNC (ed_scrollbar_update),
964 965
		      g_editor);
  gtk_signal_connect (g_editor->scroll_data, "changed",
966
		      GTK_SIGNAL_FUNC (ed_scrollbar_update),
967 968
		      g_editor);

969 970 971 972 973
  g_editor->scrollbar =
    gtk_hscrollbar_new (GTK_ADJUSTMENT (g_editor->scroll_data));
  gtk_range_set_update_policy (GTK_RANGE (g_editor->scrollbar),
			       GTK_UPDATE_CONTINUOUS);
  gtk_box_pack_start (GTK_BOX (hbox), g_editor->scrollbar, TRUE, TRUE, 0);
Marc Lehmann's avatar
Marc Lehmann committed
974
  gtk_widget_hide (g_editor->scrollbar);
975 976

  /* Instant update toggle */
Michael Natterer's avatar
Michael Natterer committed
977
  g_editor->instant_update = TRUE;
978 979 980 981

  button = gtk_check_button_new_with_label (_("Instant update"));
  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  gtk_signal_connect (GTK_OBJECT (button), "toggled",
982
		      GTK_SIGNAL_FUNC (ed_instant_update_update),
983 984 985 986 987 988 989
		      g_editor);
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
  gtk_widget_show (button);

  /* Frame for gradient preview and gradient control */
  frame = gtk_frame_new (NULL);
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
990
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
991 992 993 994 995 996 997 998 999 1000
  gtk_widget_show (frame);

  gvbox = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (frame), gvbox); 
  gtk_widget_show (gvbox);

  /* Gradient preview */
  g_editor->preview_rows[0]     = NULL;
  g_editor->preview_rows[1]     = NULL;
  g_editor->preview_last_x      = 0;
Michael Natterer's avatar
Michael Natterer committed
1001
  g_editor->preview_button_down = FALSE;
1002 1003

  g_editor->preview = gtk_preview_new (GTK_PREVIEW_COLOR);
1004
  gtk_preview_set_dither (GTK_PREVIEW (g_editor->preview), GDK_RGB_DITHER_MAX);
1005 1006
  gtk_preview_size (GTK_PREVIEW (g_editor->preview),
		    GRAD_PREVIEW_WIDTH, GRAD_PREVIEW_HEIGHT);
1007 1008 1009 1010 1011 1012

  /*  Enable auto-resizing of the preview but ensure a minimal size  */
  gtk_widget_set_usize (g_editor->preview,
			GRAD_PREVIEW_WIDTH, GRAD_PREVIEW_HEIGHT);
  gtk_preview_set_expand (GTK_PREVIEW (g_editor->preview), TRUE);

1013 1014
  gtk_widget_set_events (g_editor->preview, GRAD_PREVIEW_EVENT_MASK);
  gtk_signal_connect (GTK_OBJECT(g_editor->preview), "event",
1015
		      GTK_SIGNAL_FUNC (prev_events),
1016
		      g_editor);
Michael Natterer's avatar
Michael Natterer committed
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027

  gtk_drag_dest_set (g_editor->preview,
		     GTK_DEST_DEFAULT_HIGHLIGHT |
		     GTK_DEST_DEFAULT_MOTION |
		     GTK_DEST_DEFAULT_DROP,
		     gradient_target_table, n_gradient_targets,
		     GDK_ACTION_COPY); 
  gimp_dnd_gradient_dest_set (g_editor->preview,
			      gradient_editor_drop_gradient,
			      NULL);

1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
  gtk_box_pack_start (GTK_BOX (gvbox), g_editor->preview, TRUE, TRUE, 0);
  gtk_widget_show (g_editor->preview);

  /* Gradient control */
  g_editor->control_pixmap                  = NULL;
  g_editor->control_drag_segment            = NULL;
  g_editor->control_sel_l                   = NULL;
  g_editor->control_sel_r                   = NULL;
  g_editor->control_drag_mode               = GRAD_DRAG_NONE;
  g_editor->control_click_time              = 0;
Michael Natterer's avatar
Michael Natterer committed
1038
  g_editor->control_compress                = FALSE;
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
  g_editor->control_last_x                  = 0;
  g_editor->control_last_gx                 = 0.0;
  g_editor->control_orig_pos                = 0.0;
  g_editor->control_main_popup              = NULL;
  g_editor->control_blending_label          = NULL;
  g_editor->control_coloring_label          = NULL;
  g_editor->control_splitm_label            = NULL;
  g_editor->control_splitu_label            = NULL;
  g_editor->control_delete_menu_item        = NULL;
  g_editor->control_delete_label            = NULL;
  g_editor->control_recenter_label          = NULL;
  g_editor->control_redistribute_label      = NULL;
  g_editor->control_flip_label              = NULL;
  g_editor->control_replicate_label         = NULL;
  g_editor->control_blend_colors_menu_item  = NULL;
  g_editor->control_blend_opacity_menu_item = NULL;
  g_editor->control_left_load_popup         = NULL;
  g_editor->control_left_save_popup         = NULL;
  g_editor->control_right_load_popup        = NULL;
  g_editor->control_right_save_popup        = NULL;
  g_editor->control_blending_popup          = NULL;
  g_editor->control_coloring_popup          = NULL;
  g_editor->control_sel_ops_popup           = NULL;

  g_editor->accel_group = NULL;

  for (i = 0;
1066 1067
       i < (sizeof (g_editor->control_blending_items) /
	    sizeof (g_editor->control_blending_items[0]));
1068 1069 1070 1071
       i++)
    g_editor->control_blending_items[i] = NULL;

  for (i = 0;
1072 1073
       i < (sizeof (g_editor->control_coloring_items) /
	    sizeof (g_editor->control_coloring_items[0]));
1074 1075 1076 1077 1078 1079 1080 1081
       i++)
    g_editor->control_coloring_items[i] = NULL;

  g_editor->control = gtk_drawing_area_new ();
  gtk_drawing_area_size (GTK_DRAWING_AREA (g_editor->control),
			 GRAD_PREVIEW_WIDTH, GRAD_CONTROL_HEIGHT);
  gtk_widget_set_events (g_editor->control, GRAD_CONTROL_EVENT_MASK);
  gtk_signal_connect (GTK_OBJECT (g_editor->control), "event",
1082
		      (GdkEventFunc) control_events,
1083
		      g_editor);
1084
  gtk_box_pack_start (GTK_BOX (gvbox), g_editor->control, TRUE, TRUE, 0);
1085 1086
  gtk_widget_show (g_editor->control);

1087 1088 1089 1090 1091 1092 1093
  /* Hint bar and close button */
  g_editor->hint_label = gtk_label_new ("");
  gtk_misc_set_alignment (GTK_MISC (g_editor->hint_label), 0.0, 0.5);
  gtk_box_pack_start (GTK_BOX (vbox), g_editor->hint_label, FALSE, FALSE, 0);
  gtk_widget_show (g_editor->hint_label);

  /* Initialize other data */
Michael Natterer's avatar
Michael Natterer committed
1094