gimppaletteeditor.c 27 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

static void   palette_editor_entry_clicked         (GimpPaletteView   *view,
                                                    GimpPaletteEntry  *entry,
                                                    GdkModifierType    state,
95
                                                    GimpPaletteEditor *editor);
96 97 98 99 100 101 102 103 104 105 106 107
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,
108
                                                    GimpPaletteEditor *editor);
109 110

static void   palette_editor_color_name_changed    (GtkWidget         *widget,
111
                                                    GimpPaletteEditor *editor);
112 113 114 115 116 117 118
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);
119

Elliot Lee's avatar
Elliot Lee committed
120

121 122 123
G_DEFINE_TYPE_WITH_CODE (GimpPaletteEditor, gimp_palette_editor,
                         GIMP_TYPE_DATA_EDITOR,
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED,
124
                                                gimp_palette_editor_docked_iface_init))
125

126 127 128
#define parent_class gimp_palette_editor_parent_class

static GimpDockedInterface *parent_docked_iface = NULL;
129

130

131 132 133
static void
gimp_palette_editor_class_init (GimpPaletteEditorClass *klass)
{
134 135 136
  GObjectClass        *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass      *widget_class = GTK_WIDGET_CLASS (klass);
  GimpDataEditorClass *editor_class = GIMP_DATA_EDITOR_CLASS (klass);
137

138
  object_class->constructed = gimp_palette_editor_constructed;
139
  object_class->dispose     = gimp_palette_editor_dispose;
140

141
  widget_class->unmap       = gimp_palette_editor_unmap;
Elliot Lee's avatar
Elliot Lee committed
142

143 144
  editor_class->set_data    = gimp_palette_editor_set_data;
  editor_class->title       = _("Palette Editor");
Elliot Lee's avatar
Elliot Lee committed
145 146
}

147 148 149 150 151 152 153 154 155 156 157 158 159
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;
}

160 161
static void
gimp_palette_editor_init (GimpPaletteEditor *editor)
162
{
163 164 165 166
  GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
  GtkWidget      *hbox;
  GtkWidget      *label;
  GtkWidget      *spinbutton;
167
  GtkObject      *adj;
168

169 170 171 172
  editor->zoom_factor = 1.0;
  editor->col_width   = 0;
  editor->last_width  = 0;
  editor->columns     = COLUMNS;
173

174 175 176
  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),
177 178
                                  GTK_POLICY_AUTOMATIC,
                                  GTK_POLICY_AUTOMATIC);
179 180
  gtk_box_pack_start (GTK_BOX (editor), data_editor->view, TRUE, TRUE, 0);
  gtk_widget_show (data_editor->view);
181

182 183
  editor->view = gimp_view_new_full_by_types (NULL,
                                              GIMP_TYPE_PALETTE_VIEW,
184 185 186 187 188 189 190
                                              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);
191 192 193

  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (data_editor->view),
                                         editor->view);
194 195
  gtk_widget_show (editor->view);

196 197 198 199
  g_signal_connect (gtk_widget_get_parent (editor->view), "size-allocate",
                    G_CALLBACK (palette_editor_viewport_size_allocate),
                    editor);

200
  g_signal_connect (editor->view, "entry-clicked",
201 202
                    G_CALLBACK (palette_editor_entry_clicked),
                    editor);
203
  g_signal_connect (editor->view, "entry-selected",
204 205
                    G_CALLBACK (palette_editor_entry_selected),
                    editor);
206
  g_signal_connect (editor->view, "entry-activated",
207 208
                    G_CALLBACK (palette_editor_entry_activated),
                    editor);
209
  g_signal_connect (editor->view, "entry-context",
210 211
                    G_CALLBACK (palette_editor_entry_context),
                    editor);
212
  g_signal_connect (editor->view, "color-dropped",
213 214
                    G_CALLBACK (palette_editor_color_dropped),
                    editor);
215

216
  gimp_dnd_viewable_dest_add (editor->view, GIMP_TYPE_PALETTE,
217
                              palette_editor_drop_palette,
218 219
                              editor);

220
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
221 222 223
  gtk_box_pack_start (GTK_BOX (editor), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

224
  /*  The color name entry  */
225 226 227
  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"));
228
  gtk_editable_set_editable (GTK_EDITABLE (editor->color_name), FALSE);
229
  gtk_widget_show (editor->color_name);
230

231 232 233
  g_signal_connect (editor->color_name, "changed",
                    G_CALLBACK (palette_editor_color_name_changed),
                    editor);
234

235 236 237 238
  label = gtk_label_new (_("Columns:"));
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

239
  spinbutton = gimp_spin_button_new (&adj, 0, 0, 64, 1, 4, 0, 1, 0);
240
  editor->columns_data = GTK_ADJUSTMENT (adj);
241 242 243
  gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  gtk_widget_show (spinbutton);

244
  g_signal_connect (editor->columns_data, "value-changed",
245 246
                    G_CALLBACK (palette_editor_columns_changed),
                    editor);
247 248
}

249 250
static void
gimp_palette_editor_constructed (GObject *object)
251
{
252
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (object);
253

254 255
  if (G_OBJECT_CLASS (parent_class)->constructed)
    G_OBJECT_CLASS (parent_class)->constructed (object);
256

257 258 259 260 261 262
  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",
263
                                 gimp_get_toggle_behavior_mask (),
264 265 266 267 268 269 270 271 272 273 274 275 276
                                 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);
277 278
}

279
static void
280
gimp_palette_editor_dispose (GObject *object)
281
{
282
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (object);
283

284
  if (editor->color_dialog)
285
    {
286
      gtk_widget_destroy (editor->color_dialog);
287
      editor->color_dialog = NULL;
288
    }
289

290
  G_OBJECT_CLASS (parent_class)->dispose (object);
291
}
292

293 294 295
static void
gimp_palette_editor_unmap (GtkWidget *widget)
{
296
  GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (widget);
297

298
  if (editor->color_dialog)
299
    gtk_widget_hide (editor->color_dialog);
300

301 302
  GTK_WIDGET_CLASS (parent_class)->unmap (widget);
}
303

304 305 306 307
static void
gimp_palette_editor_set_data (GimpDataEditor *editor,
                              GimpData       *data)
{
308
  GimpPaletteEditor *palette_editor = GIMP_PALETTE_EDITOR (editor);
309

310
  g_signal_handlers_block_by_func (palette_editor->columns_data,
311 312 313
                                   palette_editor_columns_changed,
                                   editor);

314 315
  if (editor->data)
    {
316
      if (palette_editor->color_dialog)
317
        {
318
          gtk_widget_destroy (palette_editor->color_dialog);
319
          palette_editor->color_dialog = NULL;
320 321
        }

322
      g_signal_handlers_disconnect_by_func (editor->data,
323 324 325
                                            palette_editor_invalidate_preview,
                                            editor);

326
      gtk_adjustment_set_value (palette_editor->columns_data, 0);
327
    }
328

329 330
  GIMP_DATA_EDITOR_CLASS (parent_class)->set_data (editor, data);

331 332 333
  gimp_view_set_viewable (GIMP_VIEW (palette_editor->view),
                          GIMP_VIEWABLE (data));

334 335
  if (editor->data)
    {
336
      GimpPalette *palette = GIMP_PALETTE (editor->data);
337

338
      g_signal_connect (editor->data, "invalidate-preview",
339 340 341
                        G_CALLBACK (palette_editor_invalidate_preview),
                        editor);

342
      gtk_adjustment_set_value (palette_editor->columns_data,
343
                                gimp_palette_get_columns (palette));
344

345 346
      palette_editor_scroll_top_left (palette_editor);

347 348 349
      palette_editor_invalidate_preview (GIMP_PALETTE (editor->data),
                                         palette_editor);
    }
350

351
  g_signal_handlers_unblock_by_func (palette_editor->columns_data,
352 353
                                     palette_editor_columns_changed,
                                     editor);
354 355
}

356 357 358 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
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;
}


417
/*  public functions  */
418

419
GtkWidget *
420
gimp_palette_editor_new (GimpContext     *context,
421
                         GimpMenuFactory *menu_factory)
422
{
423
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
424

425 426 427 428
  return g_object_new (GIMP_TYPE_PALETTE_EDITOR,
                       "menu-factory",    menu_factory,
                       "menu-identifier", "<PaletteEditor>",
                       "ui-path",         "/palette-editor-popup",
429 430 431
                       "data-factory",    context->gimp->palette_factory,
                       "context",         context,
                       "data",            gimp_context_get_palette (context),
432
                       NULL);
433 434
}

435
void
436 437 438
gimp_palette_editor_pick_color (GimpPaletteEditor  *editor,
                                const GimpRGB      *color,
                                GimpColorPickState  pick_state)
439
{
440 441
  g_return_if_fail (GIMP_IS_PALETTE_EDITOR (editor));
  g_return_if_fail (color != NULL);
442

443 444
  if (GIMP_DATA_EDITOR (editor)->data_editable)
    {
445 446 447 448 449
      GimpPaletteEntry *entry;
      GimpData         *data;
      gint              index = -1;

      data = gimp_data_editor_get_data (GIMP_DATA_EDITOR (editor));
450

451 452 453
      switch (pick_state)
        {
        case GIMP_COLOR_PICK_STATE_NEW:
454 455 456
          if (editor->color)
            index = editor->color->position + 1;

457 458
          entry = gimp_palette_add_entry (GIMP_PALETTE (data), index,
                                          NULL, color);
459 460
          gimp_palette_view_select_entry (GIMP_PALETTE_VIEW (editor->view),
                                          entry);
461 462 463
          break;

        case GIMP_COLOR_PICK_STATE_UPDATE:
464 465 466
          gimp_palette_set_entry_color (GIMP_PALETTE (data),
                                        editor->color->position,
                                        color);
467 468
          break;
        }
469
    }
470 471
}

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
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)
    {
490 491
    case GIMP_ZOOM_IN_MAX:
    case GIMP_ZOOM_IN_MORE:
492 493 494 495
    case GIMP_ZOOM_IN:
      zoom_factor += 0.1;
      break;

496
    case GIMP_ZOOM_OUT_MORE:
497 498 499 500
    case GIMP_ZOOM_OUT:
      zoom_factor -= 0.1;
      break;

501 502
    case GIMP_ZOOM_OUT_MAX:
    case GIMP_ZOOM_TO: /* abused as ZOOM_ALL */
503
      {
504 505 506 507 508 509 510
        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);
511

512 513 514
        columns = gimp_palette_get_columns (palette);
        if (columns == 0)
          columns = COLUMNS;
515

516 517
        rows = gimp_palette_get_n_colors (palette) / columns;
        if (gimp_palette_get_n_colors (palette) % columns)
518
          rows += 1;
519 520 521

        rows = MAX (1, rows);

522
        zoom_factor = (((gdouble) allocation.height - 2 * SPACING) /
523 524 525 526 527 528 529
                       (gdouble) rows - SPACING) / ENTRY_HEIGHT;
      }
      break;
    }

  zoom_factor = CLAMP (zoom_factor, 0.1, 4.0);

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

534
  palette_editor_resize (editor, editor->last_width, zoom_factor);
535 536 537 538

  palette_editor_scroll_top_left (editor);
}

539 540 541 542 543 544 545
gint
gimp_palette_editor_get_index (GimpPaletteEditor *editor,
                               const GimpRGB     *search)
{
  GimpPalette *palette;

  g_return_val_if_fail (GIMP_IS_PALETTE_EDITOR (editor), -1);
546
  g_return_val_if_fail (search != NULL, -1);
547 548 549

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

550
  if (palette && gimp_palette_get_n_colors (palette) > 0)
551
    {
552
      GimpPaletteEntry *entry;
553

554
      entry = gimp_palette_find_entry (palette, search, editor->color);
555

556 557
      if (entry)
        return entry->position;
558 559
    }

560
  return -1;
561 562 563 564 565 566 567 568 569 570 571 572 573
}

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);

574 575 576
  if (palette && gimp_palette_get_n_colors (palette) > 0)
    {
      GimpPaletteEntry *entry;
577

578
      index = CLAMP (index, 0, gimp_palette_get_n_colors (palette) - 1);
579

580
      entry = gimp_palette_get_entry (palette, index);
581

582 583
      gimp_palette_view_select_entry (GIMP_PALETTE_VIEW (editor->view),
                                      entry);
584

585 586
      if (color)
        *color = editor->color->color;
587

588 589 590 591
      return TRUE;
    }

  return FALSE;
592 593 594 595 596 597 598 599 600 601 602
}

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);

603 604 605 606
  if (palette && gimp_palette_get_n_colors (palette) > 0)
    {
      return gimp_palette_get_n_colors (palette) - 1;
    }
607

608
  return -1;
609 610
}

611 612 613

/*  private functions  */

614 615
static void
palette_editor_invalidate_preview (GimpPalette       *palette,
616
                                   GimpPaletteEditor *editor)
617
{
618 619
  editor->columns = gimp_palette_get_columns (palette);
  if (editor->columns == 0)
620
    editor->columns = COLUMNS;
621

622
  palette_editor_resize (editor, editor->last_width, editor->zoom_factor);
623
}
624

625 626 627 628
static void
palette_editor_viewport_size_allocate (GtkWidget         *widget,
                                       GtkAllocation     *allocation,
                                       GimpPaletteEditor *editor)
Elliot Lee's avatar
Elliot Lee committed
629
{
630
  if (allocation->width != editor->last_width)
631
    {
632
      palette_editor_resize (editor, allocation->width,
633
                             editor->zoom_factor);
634
    }
Elliot Lee's avatar
Elliot Lee committed
635 636 637
}

static void
638 639 640
palette_editor_drop_palette (GtkWidget    *widget,
                             gint          x,
                             gint          y,
641 642
                             GimpViewable *viewable,
                             gpointer      data)
Elliot Lee's avatar
Elliot Lee committed
643
{
644 645
  gimp_data_editor_set_data (GIMP_DATA_EDITOR (data), GIMP_DATA (viewable));
}
Elliot Lee's avatar
Elliot Lee committed
646

647

648
/*  palette view callbacks  */
Elliot Lee's avatar
Elliot Lee committed
649

650
static void
651 652 653 654
palette_editor_entry_clicked (GimpPaletteView   *view,
                              GimpPaletteEntry  *entry,
                              GdkModifierType    state,
                              GimpPaletteEditor *editor)
655
{
656 657
  if (entry)
    {
658
      GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
659

660
      if (state & gimp_get_toggle_behavior_mask ())
661
        gimp_context_set_background (data_editor->context, &entry->color);
662
      else
663
        gimp_context_set_foreground (data_editor->context, &entry->color);
664
    }
665 666 667
}

static void
668 669 670
palette_editor_entry_selected (GimpPaletteView   *view,
                               GimpPaletteEntry  *entry,
                               GimpPaletteEditor *editor)
671
{
672
  GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
673 674

  if (editor->color != entry)
675
    {
676 677 678 679 680 681 682 683 684 685 686 687 688
      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);

689 690
      gtk_editable_set_editable (GTK_EDITABLE (editor->color_name),
                                 entry && data_editor->data_editable);
691

692 693
      gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
                              gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
694
    }
Elliot Lee's avatar
Elliot Lee committed
695 696
}

697 698 699 700 701 702 703
static void
palette_editor_entry_activated (GimpPaletteView   *view,
                                GimpPaletteEntry  *entry,
                                GimpPaletteEditor *editor)
{
  if (GIMP_DATA_EDITOR (editor)->data_editable && entry == editor->color)
    {
704
      gimp_ui_manager_activate_action (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
705 706
                                       "palette-editor",
                                       "palette-editor-edit-color");
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
    }
}

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  */
739

Elliot Lee's avatar
Elliot Lee committed
740
static void
741
palette_editor_color_name_changed (GtkWidget         *widget,
742
                                   GimpPaletteEditor *editor)
Elliot Lee's avatar
Elliot Lee committed
743
{
744 745
  if (GIMP_DATA_EDITOR (editor)->data)
    {
746 747
      GimpPalette *palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);
      const gchar *name;
Michael Natterer's avatar
Michael Natterer committed
748

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

751
      gimp_palette_set_entry_name (palette, editor->color->position, name);
752
    }
753
}
Elliot Lee's avatar
Elliot Lee committed
754

755 756 757 758
static void
palette_editor_columns_changed (GtkAdjustment     *adj,
                                GimpPaletteEditor *editor)
{
759 760
  if (GIMP_DATA_EDITOR (editor)->data)
    {
761
      GimpPalette *palette = GIMP_PALETTE (GIMP_DATA_EDITOR (editor)->data);
762

763 764
      gimp_palette_set_columns (palette,
                                ROUND (gtk_adjustment_get_value (adj)));
765 766 767
    }
}

768

769
/*  misc utils  */
770 771

static void
772 773 774
palette_editor_resize (GimpPaletteEditor *editor,
                       gint               width,
                       gdouble            zoom_factor)
775
{
776 777 778 779
  GimpPalette *palette;
  gint         rows;
  gint         preview_width;
  gint         preview_height;
780

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

783 784
  if (! palette)
    return;
785

786 787 788
  editor->zoom_factor = zoom_factor;
  editor->last_width  = width;
  editor->col_width   = width / (editor->columns + 1) - SPACING;
789

790 791
  if (editor->col_width < 0)
    editor->col_width = 0;
792

793 794
  rows = gimp_palette_get_n_colors (palette) / editor->columns;
  if (gimp_palette_get_n_colors (palette) % editor->columns)
795
    rows += 1;
796

797 798 799
  preview_width  = (editor->col_width + SPACING) * editor->columns;
  preview_height = (rows *
                    (SPACING + (gint) (ENTRY_HEIGHT * editor->zoom_factor)));
800

801 802
  if (preview_height > GIMP_VIEWABLE_MAX_PREVIEW_SIZE)
    preview_height = ((GIMP_VIEWABLE_MAX_PREVIEW_SIZE - SPACING) / rows) * rows;
803

804 805 806
  gimp_view_renderer_set_size_full (GIMP_VIEW (editor->view)->renderer,
                                    preview_width  + SPACING,
                                    preview_height + SPACING, 0);
807 808 809
}

static void
810
palette_editor_scroll_top_left (GimpPaletteEditor *palette_editor)
811
{
812 813 814
  GimpDataEditor *data_editor = GIMP_DATA_EDITOR (palette_editor);
  GtkAdjustment  *hadj;
  GtkAdjustment  *vadj;
815

816
  if (! data_editor->view)
817 818
    return;

819 820
  hadj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (data_editor->view));
  vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (data_editor->view));
821 822 823 824 825

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