gimppaletteeditor.c 28.5 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
Elliot Lee's avatar
Elliot Lee committed
2 3
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
4
 * This program is free software: you can redistribute it and/or modify
Elliot Lee's avatar
Elliot Lee committed
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
Elliot Lee's avatar
Elliot Lee committed
7 8 9 10 11 12 13 14
 * (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
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
16
 */
Sven Neumann's avatar
Sven Neumann committed
17

18 19
#include "config.h"

20 21
#include <string.h>

22
#include <gegl.h>
Sven Neumann's avatar
Sven Neumann committed
23 24
#include <gtk/gtk.h>

25
#include "libgimpbase/gimpbase.h"
26 27
#include "libgimpmath/gimpmath.h"
#include "libgimpcolor/gimpcolor.h"
28 29
#include "libgimpwidgets/gimpwidgets.h"

30
#include "widgets-types.h"
Sven Neumann's avatar
Sven Neumann committed
31

32
#include "core/gimp.h"
33 34 35 36 37
#include "core/gimpcontainer.h"
#include "core/gimpcontext.h"
#include "core/gimpdatafactory.h"
#include "core/gimppalette.h"

38
#include "gimpdnd.h"
39
#include "gimpdocked.h"
40
#include "gimphelp-ids.h"
41
#include "gimppaletteeditor.h"
42
#include "gimppaletteview.h"
43
#include "gimpsessioninfo-aux.h"
44
#include "gimpuimanager.h"
45
#include "gimpviewrendererpalette.h"
46
#include "gimpwidgets-utils.h"
47

48
#include "gimp-intl.h"
49

50

51
#define ENTRY_WIDTH  12
52
#define ENTRY_HEIGHT 10
53 54 55
#define SPACING       1
#define COLUMNS      16
#define ROWS         11
Elliot Lee's avatar
Elliot Lee committed
56

57 58
#define PREVIEW_WIDTH  ((ENTRY_WIDTH  + SPACING) * COLUMNS + 1)
#define PREVIEW_HEIGHT ((ENTRY_HEIGHT + SPACING) * ROWS    + 1)
Elliot Lee's avatar
Elliot Lee committed
59

60

61
/*  local function prototypes  */
62

63
static void   gimp_palette_editor_docked_iface_init (GimpDockedInterface *face);
64

65
static void   gimp_palette_editor_constructed      (GObject           *object);
66
static void   gimp_palette_editor_dispose          (GObject           *object);
67

68
static void   gimp_palette_editor_unmap            (GtkWidget         *widget);
Elliot Lee's avatar
Elliot Lee committed
69

70 71
static void   gimp_palette_editor_set_data         (GimpDataEditor    *editor,
                                                    GimpData          *data);
72

73 74 75 76 77 78
static void   gimp_palette_editor_set_context      (GimpDocked        *docked,
                                                    GimpContext       *context);
static void   gimp_palette_editor_set_aux_info     (GimpDocked        *docked,
                                                    GList             *aux_info);
static GList *gimp_palette_editor_get_aux_info     (GimpDocked        *docked);

79
static void   palette_editor_invalidate_preview    (GimpPalette       *palette,
80
                                                    GimpPaletteEditor *editor);
81 82 83

static void   palette_editor_viewport_size_allocate(GtkWidget         *widget,
                                                    GtkAllocation     *allocation,
84
                                                    GimpPaletteEditor *editor);
85

86
static void   palette_editor_drop_palette          (GtkWidget         *widget,
87 88
                                                    gint               x,
                                                    gint               y,
89 90
                                                    GimpViewable      *viewable,
                                                    gpointer           data);
91 92 93 94 95
static void   palette_editor_drop_color            (GtkWidget         *widget,
                                                    gint               x,
                                                    gint               y,
                                                    const GimpRGB     *color,
                                                    gpointer           data);
96 97 98 99

static void   palette_editor_entry_clicked         (GimpPaletteView   *view,
                                                    GimpPaletteEntry  *entry,
                                                    GdkModifierType    state,
100
                                                    GimpPaletteEditor *editor);
101 102 103 104 105 106 107 108 109 110 111 112
static void   palette_editor_entry_selected        (GimpPaletteView   *view,
                                                    GimpPaletteEntry  *entry,
                                                    GimpPaletteEditor *editor);
static void   palette_editor_entry_activated       (GimpPaletteView   *view,
                                                    GimpPaletteEntry  *entry,
                                                    GimpPaletteEditor *editor);
static void   palette_editor_entry_context         (GimpPaletteView   *view,
                                                    GimpPaletteEntry  *entry,
                                                    GimpPaletteEditor *editor);
static void   palette_editor_color_dropped         (GimpPaletteView   *view,
                                                    GimpPaletteEntry  *entry,
                                                    const GimpRGB     *color,
113
                                                    GimpPaletteEditor *editor);
114 115

static void   palette_editor_color_name_changed    (GtkWidget         *widget,
116
                                                    GimpPaletteEditor *editor);
117 118 119 120 121 122 123
static void   palette_editor_columns_changed       (GtkAdjustment     *adj,
                                                    GimpPaletteEditor *editor);

static void   palette_editor_resize                (GimpPaletteEditor *editor,
                                                    gint               width,
                                                    gdouble            zoom_factor);
static void   palette_editor_scroll_top_left       (GimpPaletteEditor *editor);
124

Elliot Lee's avatar
Elliot Lee committed
125

126 127 128
G_DEFINE_TYPE_WITH_CODE (GimpPaletteEditor, gimp_palette_editor,
                         GIMP_TYPE_DATA_EDITOR,
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED,
129
                                                gimp_palette_editor_docked_iface_init))
130

131 132 133
#define parent_class gimp_palette_editor_parent_class

static GimpDockedInterface *parent_docked_iface = NULL;
134

135

136 137 138
static void
gimp_palette_editor_class_init (GimpPaletteEditorClass *klass)
{
139 140 141
  GObjectClass        *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass      *widget_class = GTK_WIDGET_CLASS (klass);
  GimpDataEditorClass *editor_class = GIMP_DATA_EDITOR_CLASS (klass);
142

143
  object_class->constructed = gimp_palette_editor_constructed;
144
  object_class->dispose     = gimp_palette_editor_dispose;
145

146
  widget_class->unmap       = gimp_palette_editor_unmap;
Elliot Lee's avatar
Elliot Lee committed
147

148 149
  editor_class->set_data    = gimp_palette_editor_set_data;
  editor_class->title       = _("Palette Editor");
Elliot Lee's avatar
Elliot Lee committed
150 151
}

152 153 154 155 156 157 158 159 160 161 162 163 164
static void
gimp_palette_editor_docked_iface_init (GimpDockedInterface *iface)
{
  parent_docked_iface = g_type_interface_peek_parent (iface);

  if (! parent_docked_iface)
    parent_docked_iface = g_type_default_interface_peek (GIMP_TYPE_DOCKED);

  iface->set_context  = gimp_palette_editor_set_context;
  iface->set_aux_info = gimp_palette_editor_set_aux_info;
  iface->get_aux_info = gimp_palette_editor_get_aux_info;
}

165 166
static void
gimp_palette_editor_init (GimpPaletteEditor *editor)
167
{
168
  GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
169
  GtkWidget      *viewport;
170 171 172
  GtkWidget      *hbox;
  GtkWidget      *label;
  GtkWidget      *spinbutton;
173

174 175 176 177
  editor->zoom_factor = 1.0;
  editor->col_width   = 0;
  editor->last_width  = 0;
  editor->columns     = COLUMNS;
178

179 180 181
  data_editor->view = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_set_size_request (data_editor->view, -1, PREVIEW_HEIGHT);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (data_editor->view),
182 183
                                  GTK_POLICY_AUTOMATIC,
                                  GTK_POLICY_AUTOMATIC);
184 185
  gtk_box_pack_start (GTK_BOX (editor), data_editor->view, TRUE, TRUE, 0);
  gtk_widget_show (data_editor->view);
186

187 188 189 190
  viewport = gtk_viewport_new (NULL, NULL);
  gtk_container_add (GTK_CONTAINER (data_editor->view), viewport);
  gtk_widget_show (viewport);

191 192
  editor->view = gimp_view_new_full_by_types (NULL,
                                              GIMP_TYPE_PALETTE_VIEW,
193 194 195 196 197 198 199
                                              GIMP_TYPE_PALETTE,
                                              PREVIEW_WIDTH, PREVIEW_HEIGHT, 0,
                                              FALSE, TRUE, FALSE);
  gimp_view_renderer_palette_set_cell_size
    (GIMP_VIEW_RENDERER_PALETTE (GIMP_VIEW (editor->view)->renderer), -1);
  gimp_view_renderer_palette_set_draw_grid
    (GIMP_VIEW_RENDERER_PALETTE (GIMP_VIEW (editor->view)->renderer), TRUE);
200
  gtk_container_add (GTK_CONTAINER (viewport), editor->view);
201 202
  gtk_widget_show (editor->view);

203 204 205 206
  g_signal_connect (gtk_widget_get_parent (editor->view), "size-allocate",
                    G_CALLBACK (palette_editor_viewport_size_allocate),
                    editor);

207
  g_signal_connect (editor->view, "entry-clicked",
208 209
                    G_CALLBACK (palette_editor_entry_clicked),
                    editor);
210
  g_signal_connect (editor->view, "entry-selected",
211 212
                    G_CALLBACK (palette_editor_entry_selected),
                    editor);
213
  g_signal_connect (editor->view, "entry-activated",
214 215
                    G_CALLBACK (palette_editor_entry_activated),
                    editor);
216
  g_signal_connect (editor->view, "entry-context",
217 218
                    G_CALLBACK (palette_editor_entry_context),
                    editor);
219
  g_signal_connect (editor->view, "color-dropped",
220 221
                    G_CALLBACK (palette_editor_color_dropped),
                    editor);
222

223 224
  gimp_dnd_viewable_dest_add (editor->view,
                              GIMP_TYPE_PALETTE,
225
                              palette_editor_drop_palette,
226
                              editor);
227 228 229 230 231 232 233 234
  gimp_dnd_viewable_dest_add (gtk_widget_get_parent (editor->view),
                              GIMP_TYPE_PALETTE,
                              palette_editor_drop_palette,
                              editor);

  gimp_dnd_color_dest_add (gtk_widget_get_parent (editor->view),
                           palette_editor_drop_color,
                           editor);
235

236
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
237 238 239
  gtk_box_pack_start (GTK_BOX (editor), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

240
  /*  The color name entry  */
241 242 243
  editor->color_name = gtk_entry_new ();
  gtk_box_pack_start (GTK_BOX (hbox), editor->color_name, TRUE, TRUE, 0);
  gtk_entry_set_text (GTK_ENTRY (editor->color_name), _("Undefined"));
244
  gtk_editable_set_editable (GTK_EDITABLE (editor->color_name), FALSE);
245
  gtk_widget_show (editor->color_name);
246

247 248 249
  g_signal_connect (editor->color_name, "changed",
                    G_CALLBACK (palette_editor_color_name_changed),
                    editor);
250

251 252 253 254
  label = gtk_label_new (_("Columns:"));
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

255 256 257 258
  editor->columns_adj = (GtkAdjustment *)
    gtk_adjustment_new (0, 0, 64, 1, 4, 0);
  spinbutton = gtk_spin_button_new (editor->columns_adj, 1.0, 0);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
259 260 261
  gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  gtk_widget_show (spinbutton);

262
  g_signal_connect (editor->columns_adj, "value-changed",
263 264
                    G_CALLBACK (palette_editor_columns_changed),
                    editor);
265 266
}

267 268
static void
gimp_palette_editor_constructed (GObject *object)
269
{
270
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (object);
271

272
  G_OBJECT_CLASS (parent_class)->constructed (object);
273

274 275 276 277 278 279
  gimp_editor_add_action_button (GIMP_EDITOR (editor), "palette-editor",
                                 "palette-editor-edit-color", NULL);

  gimp_editor_add_action_button (GIMP_EDITOR (editor), "palette-editor",
                                 "palette-editor-new-color-fg",
                                 "palette-editor-new-color-bg",
280
                                 gimp_get_toggle_behavior_mask (),
281 282 283 284 285 286 287 288 289 290 291 292 293
                                 NULL);

  gimp_editor_add_action_button (GIMP_EDITOR (editor), "palette-editor",
                                 "palette-editor-delete-color", NULL);

  gimp_editor_add_action_button (GIMP_EDITOR (editor), "palette-editor",
                                 "palette-editor-zoom-out", NULL);

  gimp_editor_add_action_button (GIMP_EDITOR (editor), "palette-editor",
                                 "palette-editor-zoom-in", NULL);

  gimp_editor_add_action_button (GIMP_EDITOR (editor), "palette-editor",
                                 "palette-editor-zoom-all", NULL);
294 295
}

296
static void
297
gimp_palette_editor_dispose (GObject *object)
298
{
299
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (object);
300

301
  if (editor->color_dialog)
302
    {
303
      gtk_widget_destroy (editor->color_dialog);
304
      editor->color_dialog = NULL;
305
    }
306

307
  G_OBJECT_CLASS (parent_class)->dispose (object);
308
}
309

310 311 312
static void
gimp_palette_editor_unmap (GtkWidget *widget)
{
313
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (widget);
314

315
  if (editor->color_dialog)
316
    gtk_widget_hide (editor->color_dialog);
317

318 319
  GTK_WIDGET_CLASS (parent_class)->unmap (widget);
}
320

321 322 323 324
static void
gimp_palette_editor_set_data (GimpDataEditor *editor,
                              GimpData       *data)
{
325
  GimpPaletteEditor *palette_editor = GIMP_PALETTE_EDITOR (editor);
326

327
  g_signal_handlers_block_by_func (palette_editor->columns_adj,
328 329 330
                                   palette_editor_columns_changed,
                                   editor);

331 332
  if (editor->data)
    {
333
      if (palette_editor->color_dialog)
334
        {
335
          gtk_widget_destroy (palette_editor->color_dialog);
336
          palette_editor->color_dialog = NULL;
337 338
        }

339
      g_signal_handlers_disconnect_by_func (editor->data,
340 341 342
                                            palette_editor_invalidate_preview,
                                            editor);

343
      gtk_adjustment_set_value (palette_editor->columns_adj, 0);
344
    }
345

346 347
  GIMP_DATA_EDITOR_CLASS (parent_class)->set_data (editor, data);

348 349 350
  gimp_view_set_viewable (GIMP_VIEW (palette_editor->view),
                          GIMP_VIEWABLE (data));

351 352
  if (editor->data)
    {
353
      GimpPalette *palette = GIMP_PALETTE (editor->data);
354

355
      g_signal_connect (editor->data, "invalidate-preview",
356 357 358
                        G_CALLBACK (palette_editor_invalidate_preview),
                        editor);

359
      gtk_adjustment_set_value (palette_editor->columns_adj,
360
                                gimp_palette_get_columns (palette));
361

362 363
      palette_editor_scroll_top_left (palette_editor);

364 365 366
      palette_editor_invalidate_preview (GIMP_PALETTE (editor->data),
                                         palette_editor);
    }
367

368
  g_signal_handlers_unblock_by_func (palette_editor->columns_adj,
369 370
                                     palette_editor_columns_changed,
                                     editor);
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
static void
gimp_palette_editor_set_context (GimpDocked  *docked,
                                 GimpContext *context)
{
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (docked);

  parent_docked_iface->set_context (docked, context);

  gimp_view_renderer_set_context (GIMP_VIEW (editor->view)->renderer,
                                  context);
}

#define AUX_INFO_ZOOM_FACTOR "zoom-factor"

static void
gimp_palette_editor_set_aux_info (GimpDocked *docked,
                                  GList      *aux_info)
{
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (docked);
  GList             *list;

  parent_docked_iface->set_aux_info (docked, aux_info);

  for (list = aux_info; list; list = g_list_next (list))
    {
      GimpSessionInfoAux *aux = list->data;

      if (! strcmp (aux->name, AUX_INFO_ZOOM_FACTOR))
        {
          gdouble zoom_factor;

          zoom_factor = g_ascii_strtod (aux->value, NULL);

          editor->zoom_factor = CLAMP (zoom_factor, 0.1, 4.0);
        }
    }
}

static GList *
gimp_palette_editor_get_aux_info (GimpDocked *docked)
{
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (docked);
  GList             *aux_info;

  aux_info = parent_docked_iface->get_aux_info (docked);

  if (editor->zoom_factor != 1.0)
    {
      GimpSessionInfoAux *aux;
      gchar               value[G_ASCII_DTOSTR_BUF_SIZE];

      g_ascii_formatd (value, sizeof (value), "%.2f", editor->zoom_factor);

      aux = gimp_session_info_aux_new (AUX_INFO_ZOOM_FACTOR, value);
      aux_info = g_list_append (aux_info, aux);
    }

  return aux_info;
}


434
/*  public functions  */
435

436
GtkWidget *
437
gimp_palette_editor_new (GimpContext     *context,
438
                         GimpMenuFactory *menu_factory)
439
{
440
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
441

442 443 444 445
  return g_object_new (GIMP_TYPE_PALETTE_EDITOR,
                       "menu-factory",    menu_factory,
                       "menu-identifier", "<PaletteEditor>",
                       "ui-path",         "/palette-editor-popup",
446 447 448
                       "data-factory",    context->gimp->palette_factory,
                       "context",         context,
                       "data",            gimp_context_get_palette (context),
449
                       NULL);
450 451
}

452
void
453 454 455
gimp_palette_editor_pick_color (GimpPaletteEditor  *editor,
                                const GimpRGB      *color,
                                GimpColorPickState  pick_state)
456
{
457 458
  g_return_if_fail (GIMP_IS_PALETTE_EDITOR (editor));
  g_return_if_fail (color != NULL);
459

460 461
  if (GIMP_DATA_EDITOR (editor)->data_editable)
    {
462 463 464 465 466
      GimpPaletteEntry *entry;
      GimpData         *data;
      gint              index = -1;

      data = gimp_data_editor_get_data (GIMP_DATA_EDITOR (editor));
467

468 469
      switch (pick_state)
        {
470
        case GIMP_COLOR_PICK_STATE_START:
471 472 473
          if (editor->color)
            index = editor->color->position + 1;

474 475
          entry = gimp_palette_add_entry (GIMP_PALETTE (data), index,
                                          NULL, color);
476 477
          gimp_palette_view_select_entry (GIMP_PALETTE_VIEW (editor->view),
                                          entry);
478 479 480
          break;

        case GIMP_COLOR_PICK_STATE_UPDATE:
481
        case GIMP_COLOR_PICK_STATE_END:
482 483 484
          gimp_palette_set_entry_color (GIMP_PALETTE (data),
                                        editor->color->position,
                                        color);
485 486
          break;
        }
487
    }
488 489
}

490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
void
gimp_palette_editor_zoom (GimpPaletteEditor  *editor,
                          GimpZoomType        zoom_type)
{
  GimpPalette *palette;
  gdouble      zoom_factor;

  g_return_if_fail (GIMP_IS_PALETTE_EDITOR (editor));

  palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);

  if (! palette)
    return;

  zoom_factor = editor->zoom_factor;

  switch (zoom_type)
    {
508 509
    case GIMP_ZOOM_IN_MAX:
    case GIMP_ZOOM_IN_MORE:
510 511 512 513
    case GIMP_ZOOM_IN:
      zoom_factor += 0.1;
      break;

514
    case GIMP_ZOOM_OUT_MORE:
515 516 517 518
    case GIMP_ZOOM_OUT:
      zoom_factor -= 0.1;
      break;

519 520
    case GIMP_ZOOM_OUT_MAX:
    case GIMP_ZOOM_TO: /* abused as ZOOM_ALL */
521
      {
522 523 524 525 526 527 528
        GtkWidget     *scrolled_win = GIMP_DATA_EDITOR (editor)->view;
        GtkWidget     *viewport     = gtk_bin_get_child (GTK_BIN (scrolled_win));
        GtkAllocation  allocation;
        gint           columns;
        gint           rows;

        gtk_widget_get_allocation (viewport, &allocation);
529

530 531 532
        columns = gimp_palette_get_columns (palette);
        if (columns == 0)
          columns = COLUMNS;
533

534 535
        rows = gimp_palette_get_n_colors (palette) / columns;
        if (gimp_palette_get_n_colors (palette) % columns)
536
          rows += 1;
537 538 539

        rows = MAX (1, rows);

540
        zoom_factor = (((gdouble) allocation.height - 2 * SPACING) /
541 542 543 544 545 546 547
                       (gdouble) rows - SPACING) / ENTRY_HEIGHT;
      }
      break;
    }

  zoom_factor = CLAMP (zoom_factor, 0.1, 4.0);

548 549
  editor->columns = gimp_palette_get_columns (palette);
  if (editor->columns == 0)
550 551
    editor->columns = COLUMNS;

552
  palette_editor_resize (editor, editor->last_width, zoom_factor);
553 554 555 556

  palette_editor_scroll_top_left (editor);
}

557 558 559 560 561 562 563
gint
gimp_palette_editor_get_index (GimpPaletteEditor *editor,
                               const GimpRGB     *search)
{
  GimpPalette *palette;

  g_return_val_if_fail (GIMP_IS_PALETTE_EDITOR (editor), -1);
564
  g_return_val_if_fail (search != NULL, -1);
565 566 567

  palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);

568
  if (palette && gimp_palette_get_n_colors (palette) > 0)
569
    {
570
      GimpPaletteEntry *entry;
571

572
      entry = gimp_palette_find_entry (palette, search, editor->color);
573

574 575
      if (entry)
        return entry->position;
576 577
    }

578
  return -1;
579 580 581 582 583 584 585 586 587 588 589 590 591
}

gboolean
gimp_palette_editor_set_index (GimpPaletteEditor *editor,
                               gint               index,
                               GimpRGB           *color)
{
  GimpPalette *palette;

  g_return_val_if_fail (GIMP_IS_PALETTE_EDITOR (editor), FALSE);

  palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);

592 593 594
  if (palette && gimp_palette_get_n_colors (palette) > 0)
    {
      GimpPaletteEntry *entry;
595

596
      index = CLAMP (index, 0, gimp_palette_get_n_colors (palette) - 1);
597

598
      entry = gimp_palette_get_entry (palette, index);
599

600 601
      gimp_palette_view_select_entry (GIMP_PALETTE_VIEW (editor->view),
                                      entry);
602

603 604
      if (color)
        *color = editor->color->color;
605

606 607 608 609
      return TRUE;
    }

  return FALSE;
610 611 612 613 614 615 616 617 618 619 620
}

gint
gimp_palette_editor_max_index (GimpPaletteEditor *editor)
{
  GimpPalette *palette;

  g_return_val_if_fail (GIMP_IS_PALETTE_EDITOR (editor), -1);

  palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);

621 622 623 624
  if (palette && gimp_palette_get_n_colors (palette) > 0)
    {
      return gimp_palette_get_n_colors (palette) - 1;
    }
625

626
  return -1;
627 628
}

629 630 631

/*  private functions  */

632 633
static void
palette_editor_invalidate_preview (GimpPalette       *palette,
634
                                   GimpPaletteEditor *editor)
635
{
636 637
  editor->columns = gimp_palette_get_columns (palette);
  if (editor->columns == 0)
638
    editor->columns = COLUMNS;
639

640
  palette_editor_resize (editor, editor->last_width, editor->zoom_factor);
641
}
642

643 644 645 646
static void
palette_editor_viewport_size_allocate (GtkWidget         *widget,
                                       GtkAllocation     *allocation,
                                       GimpPaletteEditor *editor)
Elliot Lee's avatar
Elliot Lee committed
647
{
648
  if (allocation->width != editor->last_width)
649
    {
650
      palette_editor_resize (editor, allocation->width,
651
                             editor->zoom_factor);
652
    }
Elliot Lee's avatar
Elliot Lee committed
653 654 655
}

static void
656 657 658
palette_editor_drop_palette (GtkWidget    *widget,
                             gint          x,
                             gint          y,
659 660
                             GimpViewable *viewable,
                             gpointer      data)
Elliot Lee's avatar
Elliot Lee committed
661
{
662 663
  gimp_data_editor_set_data (GIMP_DATA_EDITOR (data), GIMP_DATA (viewable));
}
Elliot Lee's avatar
Elliot Lee committed
664

665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
static void
palette_editor_drop_color (GtkWidget     *widget,
                           gint           x,
                           gint           y,
                           const GimpRGB *color,
                           gpointer       data)
{
  GimpPaletteEditor *editor = data;

  if (GIMP_DATA_EDITOR (editor)->data_editable)
    {
      GimpPalette      *palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);
      GimpPaletteEntry *entry;

      entry = gimp_palette_add_entry (palette, -1, NULL, color);
      gimp_palette_view_select_entry (GIMP_PALETTE_VIEW (editor->view), entry);
    }
}

684

685
/*  palette view callbacks  */
Elliot Lee's avatar
Elliot Lee committed
686

687
static void
688 689 690 691
palette_editor_entry_clicked (GimpPaletteView   *view,
                              GimpPaletteEntry  *entry,
                              GdkModifierType    state,
                              GimpPaletteEditor *editor)
692
{
693 694
  if (entry)
    {
695
      GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
696

697
      if (state & gimp_get_toggle_behavior_mask ())
698
        gimp_context_set_background (data_editor->context, &entry->color);
699
      else
700
        gimp_context_set_foreground (data_editor->context, &entry->color);
701
    }
702 703 704
}

static void
705 706 707
palette_editor_entry_selected (GimpPaletteView   *view,
                               GimpPaletteEntry  *entry,
                               GimpPaletteEditor *editor)
708
{
709
  GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
710 711

  if (editor->color != entry)
712
    {
713 714 715 716 717 718 719 720 721 722 723 724 725
      editor->color = entry;

      g_signal_handlers_block_by_func (editor->color_name,
                                       palette_editor_color_name_changed,
                                       editor);

      gtk_entry_set_text (GTK_ENTRY (editor->color_name),
                          entry ? entry->name : _("Undefined"));

      g_signal_handlers_unblock_by_func (editor->color_name,
                                         palette_editor_color_name_changed,
                                         editor);

726 727
      gtk_editable_set_editable (GTK_EDITABLE (editor->color_name),
                                 entry && data_editor->data_editable);
728

729 730
      gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
                              gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
731
    }
Elliot Lee's avatar
Elliot Lee committed
732 733
}

734 735 736 737 738 739 740
static void
palette_editor_entry_activated (GimpPaletteView   *view,
                                GimpPaletteEntry  *entry,
                                GimpPaletteEditor *editor)
{
  if (GIMP_DATA_EDITOR (editor)->data_editable && entry == editor->color)
    {
741
      gimp_ui_manager_activate_action (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
742 743
                                       "palette-editor",
                                       "palette-editor-edit-color");
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
    }
}

static void
palette_editor_entry_context (GimpPaletteView   *view,
                              GimpPaletteEntry  *entry,
                              GimpPaletteEditor *editor)
{
  gimp_editor_popup_menu (GIMP_EDITOR (editor), NULL, NULL);
}

static void
palette_editor_color_dropped (GimpPaletteView   *view,
                              GimpPaletteEntry  *entry,
                              const GimpRGB     *color,
                              GimpPaletteEditor *editor)
{
  if (GIMP_DATA_EDITOR (editor)->data_editable)
    {
      GimpPalette *palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);
      gint         pos     = -1;

      if (entry)
        pos = entry->position;

      entry = gimp_palette_add_entry (palette, pos, NULL, color);
      gimp_palette_view_select_entry (GIMP_PALETTE_VIEW (editor->view), entry);
    }
}


/*  color name and columns callbacks  */
776

Elliot Lee's avatar
Elliot Lee committed
777
static void
778
palette_editor_color_name_changed (GtkWidget         *widget,
779
                                   GimpPaletteEditor *editor)
Elliot Lee's avatar
Elliot Lee committed
780
{
781 782
  if (GIMP_DATA_EDITOR (editor)->data)
    {
783 784
      GimpPalette *palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);
      const gchar *name;
Michael Natterer's avatar
Michael Natterer committed
785

786
      name = gtk_entry_get_text (GTK_ENTRY (editor->color_name));
Michael Natterer's avatar
Michael Natterer committed
787

788
      gimp_palette_set_entry_name (palette, editor->color->position, name);
789
    }
790
}
Elliot Lee's avatar
Elliot Lee committed
791

792 793 794 795
static void
palette_editor_columns_changed (GtkAdjustment     *adj,
                                GimpPaletteEditor *editor)
{
796 797
  if (GIMP_DATA_EDITOR (editor)->data)
    {
798
      GimpPalette *palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);
799

800 801
      gimp_palette_set_columns (palette,
                                ROUND (gtk_adjustment_get_value (adj)));
802 803 804
    }
}

805

806
/*  misc utils  */
807 808

static void
809 810 811
palette_editor_resize (GimpPaletteEditor *editor,
                       gint               width,
                       gdouble            zoom_factor)
812
{
813 814 815 816
  GimpPalette *palette;
  gint         rows;
  gint         preview_width;
  gint         preview_height;
817

818
  palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);
819

820 821
  if (! palette)
    return;
822

823 824 825
  editor->zoom_factor = zoom_factor;
  editor->last_width  = width;
  editor->col_width   = width / (editor->columns + 1) - SPACING;
826

827 828
  if (editor->col_width < 0)
    editor->col_width = 0;
829

830 831
  rows = gimp_palette_get_n_colors (palette) / editor->columns;
  if (gimp_palette_get_n_colors (palette) % editor->columns)
832
    rows += 1;
833

834 835 836
  preview_width  = (editor->col_width + SPACING) * editor->columns;
  preview_height = (rows *
                    (SPACING + (gint) (ENTRY_HEIGHT * editor->zoom_factor)));
837

838 839
  if (preview_height > GIMP_VIEWABLE_MAX_PREVIEW_SIZE)
    preview_height = ((GIMP_VIEWABLE_MAX_PREVIEW_SIZE - SPACING) / rows) * rows;
840

841 842 843
  gimp_view_renderer_set_size_full (GIMP_VIEW (editor->view)->renderer,
                                    preview_width  + SPACING,
                                    preview_height + SPACING, 0);
844 845 846
}

static void
847
palette_editor_scroll_top_left (GimpPaletteEditor *palette_editor)
848
{
849 850 851
  GimpDataEditor *data_editor = GIMP_DATA_EDITOR (palette_editor);
  GtkAdjustment  *hadj;
  GtkAdjustment  *vadj;
852

853
  if (! data_editor->view)
854 855
    return;

856 857
  hadj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (data_editor->view));
  vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (data_editor->view));
858 859 860 861 862

  if (hadj)
    gtk_adjustment_set_value (hadj, 0.0);
  if (vadj)
    gtk_adjustment_set_value (vadj, 0.0);
863
}