gimpcolordialog.c 10.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * color_notebook module (C) 1998 Austin Donnelly <austin@greenend.org.uk>
 *
 * 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.
 */
20 21
#define __COLOR_NOTEBOOK_C__ 1

Tomas Ogren's avatar
Tomas Ogren committed
22
#include "config.h"
23

Manish Singh's avatar
Manish Singh committed
24
#include <gmodule.h>
25

26 27
#include <stdio.h>
#include <stdlib.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
28 29
#include <string.h>

30
/*#include "appenv.h"*/
31
#include "color_notebook.h"
32
#include "gimpui.h"
33 34 35 36

#include "libgimp/color_selector.h"
#include "libgimp/gimpintl.h"

37 38 39 40 41 42 43 44 45 46
static void color_notebook_ok_callback     (GtkWidget *widget,
					    gpointer   data);
static void color_notebook_cancel_callback (GtkWidget *widget,
					    gpointer   data);
static void color_notebook_update_callback (gpointer,
					    gint,
					    gint,
					    gint);
static void color_notebook_page_switch     (GtkWidget *,
					    GtkNotebookPage *,
47
					    guint);
48
static void color_notebook_help_func       (gchar *help_data);
49 50

/* information we keep on each registered colour selector */
51 52 53
typedef struct _ColorSelectorInfo ColorSelectorInfo;

struct _ColorSelectorInfo
54
{
55 56 57 58 59 60 61 62 63 64 65
  char                      *name;    /* label used in notebook tab */
  char                      *help_page;
  GimpColorSelectorMethods   m;
  int                        refs;    /* number of instances around */
  gboolean                   active;
  void                     (*death_callback) (void *data);
  void                      *death_data;
  ColorSelectorInfo         *next;
};

struct _ColorSelectorInstance
66
{
67 68 69 70 71 72
  ColorNotebook         *color_notebook;
  ColorSelectorInfo     *info;
  GtkWidget             *frame;   /* main widget */
  gpointer               selector_data;
  ColorSelectorInstance *next;
};
73 74 75 76 77 78 79

static void selector_death (ColorSelectorInfo *info);


/* master list of all registered colour selectors */
static ColorSelectorInfo *selector_info = NULL;

80 81 82 83 84 85 86
enum
{
  RED,
  GREEN,
  BLUE,
  NUM_COLORS
};
87 88


89 90 91 92
ColorNotebook *
color_notebook_new (gint                   red,
		    gint                   green,
		    gint                   blue,
93
		    ColorNotebookCallback  callback,
94 95
		    gpointer               client_data,
		    gboolean               wants_updates)
96
{
97
  ColorNotebook *cnp;
98 99 100 101 102 103
  GtkWidget *label;
  ColorSelectorInfo *info;
  ColorSelectorInstance *csel;

  g_return_val_if_fail (selector_info != NULL, NULL);

104
  cnp = g_new (ColorNotebook, 1);
105

106 107
  cnp->callback      = callback;
  cnp->client_data   = client_data;
108
  cnp->wants_updates = wants_updates;
109 110
  cnp->selectors     = NULL;
  cnp->cur_page      = NULL;
111

112 113 114
  cnp->values[RED]   = cnp->orig_values[RED]   = red   & 0xff;
  cnp->values[GREEN] = cnp->orig_values[GREEN] = green & 0xff;
  cnp->values[BLUE]  = cnp->orig_values[BLUE]  = blue  & 0xff;
115

116 117
  cnp->shell =
    gimp_dialog_new (_("Color Selection"), "color_selection",
118
		     color_notebook_help_func, (gchar *) cnp,
119 120
		     GTK_WIN_POS_NONE,
		     FALSE, FALSE, FALSE,
121

122 123
		     wants_updates ? _("Close") : _("OK"),
		     color_notebook_ok_callback,
Sven Neumann's avatar
Sven Neumann committed
124
		     cnp, NULL, NULL, TRUE, wants_updates,
125 126
		     wants_updates ? _("Revert to Old Color") : _("Cancel"),
		     color_notebook_cancel_callback,
Sven Neumann's avatar
Sven Neumann committed
127
		     cnp, NULL, NULL, FALSE, !wants_updates,
128 129

		     NULL);
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

  /* do we actually need a notebook? */
  if (selector_info->next)
    {
      cnp->notebook = gtk_notebook_new ();
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (cnp->shell)->vbox),
			  cnp->notebook, TRUE, TRUE, 1);
      gtk_widget_show (cnp->notebook);
    }
  else /* only one selector */
    {
      cnp->notebook = NULL;
    }

  /* create each registered colour selector */
  info = selector_info;
  while (info)
    {
      if (info->active)
	{

151
	  csel = g_new (ColorSelectorInstance, 1);
152 153 154
	  csel->color_notebook = cnp;
	  csel->info = info;
	  info->refs++;
155
	  csel->frame = info->m.new (red, green, blue,
156 157 158 159 160 161 162 163 164
				     color_notebook_update_callback, csel,
				     &csel->selector_data);
	  gtk_object_set_data (GTK_OBJECT (csel->frame), "gimp_color_notebook",
			       csel);

	  if (cnp->notebook)
	    {
	      label = gtk_label_new (info->name);
	      gtk_widget_show (label);
165 166
	      /* hide the frame, so it doesn't get selected by mistake */
	      gtk_widget_hide (csel->frame);
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
	      gtk_notebook_append_page (GTK_NOTEBOOK (cnp->notebook),
					csel->frame, label);
	    }
	  else
	    {
	      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (cnp->shell)->vbox),
				  csel->frame, TRUE, TRUE, 1);
	    }

	  gtk_widget_show (csel->frame);

	  if (!cnp->cur_page)
	    cnp->cur_page = csel;

	  /* link into list of all selectors hanging off the new notebook */
	  csel->next = cnp->selectors;
	  cnp->selectors = csel;
	}

      info = info->next;
    }

  gtk_widget_show (cnp->shell);

  /* this must come after showing the widget, otherwise we get a
   * switch_page signal for a non-visible color selector, which is bad
   * news. */
  if (cnp->notebook)
    {
      gtk_object_set_user_data (GTK_OBJECT (cnp->notebook), cnp);
      gtk_signal_connect (GTK_OBJECT (cnp->notebook), "switch_page",
			  (GtkSignalFunc)color_notebook_page_switch, NULL);
    }

  return cnp;
}

void
205
color_notebook_show (ColorNotebook *cnp)
206 207 208 209 210 211
{
  g_return_if_fail (cnp != NULL);
  gtk_widget_show (cnp->shell);
}

void
212
color_notebook_hide (ColorNotebook *cnp)
213 214 215 216 217 218
{
  g_return_if_fail (cnp != NULL);
  gtk_widget_hide (cnp->shell);
}

void
219
color_notebook_free (ColorNotebook *cnp)
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
{
  ColorSelectorInstance *csel, *next;

  g_return_if_fail (cnp != NULL);

  gtk_widget_destroy (cnp->shell);

  /* call the free functions for all the colour selectors */
  csel = cnp->selectors;
  while (csel)
    {
      next = csel->next;

      csel->info->m.free (csel->selector_data);

      csel->info->refs--;
      if (csel->info->refs == 0 && !csel->info->active)
	selector_death (csel->info);

      g_free (csel);
      csel = next;
    }

  g_free (cnp);
}

void
247 248 249 250 251
color_notebook_set_color (ColorNotebook *cnp,
			  gint           red,
			  gint           green,
			  gint           blue,
			  gboolean       set_current)
252 253 254 255
{
  ColorSelectorInstance *csel;
  g_return_if_fail (cnp != NULL);

256 257 258
  cnp->orig_values[RED]   = red;
  cnp->orig_values[GREEN] = green;
  cnp->orig_values[BLUE]  = blue;
259 260 261

  if (set_current)
    {
262 263 264
      cnp->values[RED]   = red;
      cnp->values[GREEN] = green;
      cnp->values[BLUE]  = blue;
265 266 267
    }

  csel = cnp->cur_page;
268
  csel->info->m.setcolor (csel->selector_data, red, green, blue, set_current);
269 270 271 272
}

/* Called by a colour selector on user selection of a colour */
static void
273 274 275 276
color_notebook_update_callback (gpointer data,
				gint     red,
				gint     green,
				gint     blue)
277 278
{
  ColorSelectorInstance *csel;
279
  ColorNotebook *cnp;
280 281 282 283 284 285

  g_return_if_fail (data != NULL);

  csel = (ColorSelectorInstance *) data;
  cnp = csel->color_notebook;

286 287 288
  cnp->values[RED]   = red;
  cnp->values[GREEN] = green;
  cnp->values[BLUE]  = blue;
289 290 291 292 293 294 295 296 297 298 299 300

  if (cnp->wants_updates && cnp->callback)
    {
      (* cnp->callback) (cnp->values[RED],
			 cnp->values[GREEN],
			 cnp->values[BLUE],
			 COLOR_NOTEBOOK_UPDATE,
			 cnp->client_data);
    }
}

static void
301 302
color_notebook_ok_callback (GtkWidget *widget,
			    gpointer   data)
303
{
304
  ColorNotebook *cnp;
305

306
  cnp = (ColorNotebook *) data;
307 308 309 310 311 312 313 314 315 316

  if (cnp->callback)
    (* cnp->callback) (cnp->values[RED],
		       cnp->values[GREEN],
		       cnp->values[BLUE],
		       COLOR_NOTEBOOK_OK,
		       cnp->client_data);
}

static void
317 318
color_notebook_cancel_callback (GtkWidget *widget,
				gpointer   data)
319
{
320
  ColorNotebook *cnp;
321

322
  cnp = (ColorNotebook *) data;
323 324 325 326 327 328 329 330 331 332

  if (cnp->callback)
    (* cnp->callback) (cnp->orig_values[RED],
		       cnp->orig_values[GREEN],
		       cnp->orig_values[BLUE],
		       COLOR_NOTEBOOK_CANCEL,
		       cnp->client_data);
}

static void
333
color_notebook_page_switch (GtkWidget       *widget,
334 335 336
			    GtkNotebookPage *page,
			    guint            page_num)
{
337
  ColorNotebook *cnp;
338 339
  ColorSelectorInstance *csel;

340
  cnp = gtk_object_get_user_data (GTK_OBJECT (widget));
341 342 343 344 345 346 347 348 349 350 351 352
  csel = gtk_object_get_data (GTK_OBJECT(page->child), "gimp_color_notebook");

  g_return_if_fail (cnp != NULL && csel != NULL);

  cnp->cur_page = csel;
  csel->info->m.setcolor (csel->selector_data,
			  cnp->values[RED], 
			  cnp->values[GREEN],
			  cnp->values[BLUE],
			  TRUE);
}

353
static void
354
color_notebook_help_func (gchar *data)
355
{
356
  ColorNotebook *cnp;
357 358
  gchar *help_path;

359
  cnp = (ColorNotebook *) data;
360 361 362 363 364 365 366 367

  help_path = g_strconcat ("dialogs/color_selectors/",
			   cnp->cur_page->info->help_page,
			   NULL);
  gimp_help (help_path);
  g_free (help_path);
}

368 369 370
/**************************************************************/
/* Registration functions */

371
G_MODULE_EXPORT
372
GimpColorSelectorID
373 374
gimp_color_selector_register (const gchar              *name,
			      const gchar              *help_page,
375 376 377 378 379 380 381 382 383 384 385 386 387
			      GimpColorSelectorMethods *methods)
{
  ColorSelectorInfo *info;

  /* check the name is unique */
  info = selector_info;
  while (info)
    {
      if (!strcmp (info->name, name))
	return NULL;
      info = info->next;
    }

388
  info = g_new (ColorSelectorInfo, 1);
389 390

  info->name = g_strdup (name);
391
  info->help_page = g_strdup (help_page);
392 393 394 395 396 397 398 399 400 401 402
  info->m = *methods;
  info->refs = 0;
  info->active = TRUE;

  info->next = selector_info;
  selector_info = info;
  
  return info;
}


403
G_MODULE_EXPORT
404
gboolean
405 406 407
gimp_color_selector_unregister (GimpColorSelectorID   id,
				void                (*callback) (gpointer data),
				gpointer              data)
408 409 410 411 412 413 414 415
{
  ColorSelectorInfo *info;

  info = selector_info;
  while (info)
    {
      if (info == id)
	{
416
	  info->active         = FALSE;
417
	  info->death_callback = callback;
418
	  info->death_data     = data;
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
	  if (info->refs == 0)
	    selector_death (info);
	  return TRUE;
	}
      info = info->next;
    }

  g_warning ("unknown color selector id %p", id);
  return FALSE;
}

static void
selector_death (ColorSelectorInfo *info)
{
  ColorSelectorInfo *here, *prev;

  here = selector_info;
  prev = NULL;
  while (here)
    {
      if (here == info)
	{	  
	  if (prev)
	    prev->next = info->next;
	  else
	    selector_info = info->next;

	  if (info->death_callback)
	    (*info->death_callback) (info->death_data);

	  g_free (info->name);
	  g_free (info);

	  return;
	}
      prev = here;
      here = here->next;
    }

  g_warning ("color selector %p not found, can't happen!", info);
}