gimptransformoptions.c 16.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * 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.
 */

#include "config.h"

#include <gtk/gtk.h>

#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"

Michael Natterer's avatar
Michael Natterer committed
26 27
#include "tools-types.h"

28
#include "config/gimpconfig-params.h"
29 30
#include "config/gimpcoreconfig.h"

31
#include "core/gimp.h"
Michael Natterer's avatar
Michael Natterer committed
32
#include "core/gimptoolinfo.h"
33

34
#include "widgets/gimppropwidgets.h"
35
#include "widgets/gimpwidgets-utils.h"
36

37 38
#include "gimprotatetool.h"
#include "gimpscaletool.h"
39
#include "gimptooloptions-gui.h"
40
#include "gimptransformoptions.h"
41

42
#include "gimp-intl.h"
43 44


45 46 47
enum
{
  PROP_0,
48
  PROP_TYPE,
49 50
  PROP_DIRECTION,
  PROP_INTERPOLATION,
51
  PROP_SUPERSAMPLE,
52
  PROP_RECURSION_LEVEL,
53
  PROP_CLIP,
54
  PROP_SHOW_PREVIEW,
55 56 57 58 59 60
  PROP_GRID_TYPE,
  PROP_GRID_SIZE,
  PROP_CONSTRAIN_1,
  PROP_CONSTRAIN_2
};

61

62 63
static void   gimp_transform_options_init       (GimpTransformOptions      *options);
static void   gimp_transform_options_class_init (GimpTransformOptionsClass *options_class);
64

65 66 67 68 69 70 71 72 73
static void   gimp_transform_options_set_property (GObject         *object,
                                                   guint            property_id,
                                                   const GValue    *value,
                                                   GParamSpec      *pspec);
static void   gimp_transform_options_get_property (GObject         *object,
                                                   guint            property_id,
                                                   GValue          *value,
                                                   GParamSpec      *pspec);

74
static void   gimp_transform_options_reset        (GimpToolOptions *tool_options);static void   gimp_transform_options_set_defaults (GimpToolOptions *tool_options);
75

76
static void   gimp_transform_options_grid_notify  (GimpTransformOptions *options,
77 78 79 80 81
                                                   GParamSpec           *pspec,
                                                   GtkWidget            *density_box);


static GimpToolOptionsClass *parent_class = NULL;
82 83


84 85
GType
gimp_transform_options_get_type (void)
86
{
87
  static GType type = 0;
88

89 90 91 92 93
  if (! type)
    {
      static const GTypeInfo info =
      {
        sizeof (GimpTransformOptionsClass),
94 95 96 97 98 99 100 101
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gimp_transform_options_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data     */
        sizeof (GimpTransformOptions),
        0,              /* n_preallocs    */
        (GInstanceInitFunc) gimp_transform_options_init,
102 103 104 105 106 107
      };

      type = g_type_register_static (GIMP_TYPE_TOOL_OPTIONS,
                                     "GimpTransformOptions",
                                     &info, 0);
    }
108

109
  return type;
110 111
}

112
static void
113
gimp_transform_options_class_init (GimpTransformOptionsClass *klass)
114
{
115 116 117 118 119 120 121 122 123 124 125 126 127
  GObjectClass         *object_class;
  GimpToolOptionsClass *options_class;

  object_class  = G_OBJECT_CLASS (klass);
  options_class = GIMP_TOOL_OPTIONS_CLASS (klass);

  parent_class = g_type_class_peek_parent (klass);

  object_class->set_property = gimp_transform_options_set_property;
  object_class->get_property = gimp_transform_options_get_property;

  options_class->reset       = gimp_transform_options_reset;

128 129 130 131 132
  GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_TYPE,
                                 "type", NULL,
                                 GIMP_TYPE_TRANSFORM_TYPE,
                                 GIMP_TRANSFORM_TYPE_LAYER,
                                 0);
133 134 135 136 137 138 139 140
  GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_DIRECTION,
                                 "direction", NULL,
                                 GIMP_TYPE_TRANSFORM_DIRECTION,
                                 GIMP_TRANSFORM_FORWARD,
                                 0);
  GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_INTERPOLATION,
                                 "interpolation", NULL,
                                 GIMP_TYPE_INTERPOLATION_TYPE,
141
                                 GIMP_INTERPOLATION_LINEAR,
142
                                 0);
143 144 145 146
  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_SUPERSAMPLE,
                                    "supersample", NULL,
                                    FALSE,
                                    0);
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

#if 0
  GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_RECURSION_LEVEL,
                                "recursion-level", NULL,
                                1, 5, 3,
                                0);
#endif

  g_object_class_install_property (object_class, PROP_RECURSION_LEVEL,
                                   g_param_spec_int ("recursion-level",
                                                     NULL, NULL,
                                                     1, 5, 3,
                                                     G_PARAM_READWRITE |
                                                     G_PARAM_CONSTRUCT));

162 163
  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_CLIP,
                                    "clip", NULL,
164
                                    FALSE,
165
                                    0);
166 167 168 169
  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_SHOW_PREVIEW,
                                    "show-preview", NULL,
                                    FALSE,
                                    0);
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
  GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_GRID_TYPE,
                                 "grid-type", NULL,
                                 GIMP_TYPE_TRANSFORM_GRID_TYPE,
                                 GIMP_TRANSFORM_GRID_TYPE_N_LINES,
                                 0);
  GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_GRID_SIZE,
                                "grid-size", NULL,
                                1, 128, 15,
                                0);
  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_CONSTRAIN_1,
                                    "constrain-1", NULL,
                                    FALSE,
                                    0);
  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_CONSTRAIN_2,
                                    "constrain-2", NULL,
                                    FALSE,
                                    0);
187
}
188

189 190 191
static void
gimp_transform_options_init (GimpTransformOptions *options)
{
192 193 194 195 196 197 198 199 200 201 202 203 204 205
}

static void
gimp_transform_options_set_property (GObject      *object,
                                     guint         property_id,
                                     const GValue *value,
                                     GParamSpec   *pspec)
{
  GimpTransformOptions *options;

  options = GIMP_TRANSFORM_OPTIONS (object);

  switch (property_id)
    {
206 207 208
    case PROP_TYPE:
      options->type = g_value_get_enum (value);
      break;
209 210 211 212 213 214
    case PROP_DIRECTION:
      options->direction = g_value_get_enum (value);
      break;
    case PROP_INTERPOLATION:
      options->interpolation = g_value_get_enum (value);
      break;
215 216 217
    case PROP_SUPERSAMPLE:
      options->supersample = g_value_get_boolean (value);
      break;
218 219 220
    case PROP_RECURSION_LEVEL:
      options->recursion_level = g_value_get_int (value);
      break;
221 222 223
    case PROP_CLIP:
      options->clip = g_value_get_boolean (value);
      break;
224 225 226
    case PROP_SHOW_PREVIEW:
      options->show_preview = g_value_get_boolean (value);
      break;
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
    case PROP_GRID_TYPE:
      options->grid_type = g_value_get_enum (value);
      break;
    case PROP_GRID_SIZE:
      options->grid_size = g_value_get_int (value);
      break;
    case PROP_CONSTRAIN_1:
      options->constrain_1 = g_value_get_boolean (value);
      break;
    case PROP_CONSTRAIN_2:
      options->constrain_2 = g_value_get_boolean (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_transform_options_get_property (GObject    *object,
                                     guint       property_id,
                                     GValue     *value,
                                     GParamSpec *pspec)
{
  GimpTransformOptions *options;

  options = GIMP_TRANSFORM_OPTIONS (object);

  switch (property_id)
    {
257 258 259
    case PROP_TYPE:
      g_value_set_enum (value, options->type);
      break;
260 261 262 263 264 265
    case PROP_DIRECTION:
      g_value_set_enum (value, options->direction);
      break;
    case PROP_INTERPOLATION:
      g_value_set_enum (value, options->interpolation);
      break;
266 267 268
    case PROP_SUPERSAMPLE:
      g_value_set_boolean (value, options->supersample);
      break;
269 270 271
    case PROP_RECURSION_LEVEL:
      g_value_set_int (value, options->recursion_level);
      break;
272 273 274
    case PROP_CLIP:
      g_value_set_boolean (value, options->clip);
      break;
275 276 277
    case PROP_SHOW_PREVIEW:
      g_value_set_boolean (value, options->show_preview);
      break;
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
    case PROP_GRID_TYPE:
      g_value_set_enum (value, options->grid_type);
      break;
    case PROP_GRID_SIZE:
      g_value_set_int (value, options->grid_size);
      break;
    case PROP_CONSTRAIN_1:
      g_value_set_boolean (value, options->constrain_1);
      break;
    case PROP_CONSTRAIN_2:
      g_value_set_boolean (value, options->constrain_2);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_transform_options_reset (GimpToolOptions *tool_options)
{
299
  gimp_transform_options_set_defaults (tool_options);
300

301 302 303 304 305 306 307
  GIMP_TOOL_OPTIONS_CLASS (parent_class)->reset (tool_options);
}

static void
gimp_transform_options_set_defaults (GimpToolOptions *tool_options)
{
  GParamSpec *pspec;
308 309 310 311 312

  pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (tool_options),
                                        "interpolation");

  if (pspec)
313 314
    G_PARAM_SPEC_ENUM (pspec)->default_value =
      tool_options->tool_info->gimp->config->interpolation_type;
315 316
}

317 318 319 320 321 322 323 324 325 326
static void
gimp_scale_constraints_callback (GtkWidget *widget,
                                 GObject   *config)
{
  gint      value;
  gboolean  c0;
  gboolean  c1;

  value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
                                              "gimp-item-data"));
327

328 329 330 331 332 333
  c0 = c1 = FALSE;

  if (value == 1 || value == 3)
    c0 = TRUE;
  if (value == 2 || value == 3)
    c1 = TRUE;
334

335 336 337 338 339 340
  g_object_set (config,
                "constrain-1", c0,
                "constrain-2", c1,
                NULL);
}

341
GtkWidget *
342 343
gimp_transform_options_gui (GimpToolOptions *tool_options)
{
344
  GObject              *config;
345 346 347 348 349 350
  GimpTransformOptions *options;
  GtkWidget            *vbox;
  GtkWidget            *hbox;
  GtkWidget            *label;
  GtkWidget            *frame;
  GtkWidget            *table;
351
  GtkWidget            *combo;
352
  GtkWidget            *button;
353

354
  config  = G_OBJECT (tool_options);
355 356
  options = GIMP_TRANSFORM_OPTIONS (tool_options);

357
  vbox = gimp_tool_options_gui (tool_options);
358

359 360 361 362 363 364 365 366 367
  hbox = gimp_prop_enum_stock_box_new (config, "type", "gimp", 0, 0);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  label = gtk_label_new (_("Affect:"));
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_box_reorder_child (GTK_BOX (hbox), label, 0);
  gtk_widget_show (label);

368 369
  frame = gimp_prop_enum_radio_frame_new (config, "direction",
                                          _("Transform Direction"), 0, 0);
370
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
371 372
  gtk_widget_show (frame);

373 374 375 376
  /*  the interpolation menu  */
  hbox = gtk_hbox_new (FALSE, 4);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);
377

378 379 380 381
  label = gtk_label_new (_("Interpolation:"));
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

382 383 384
  combo = gimp_prop_enum_combo_box_new (config, "interpolation", 0, 0);
  gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
  gtk_widget_show (combo);
385

386 387
  /*  the supersample toggle button  */
  button = gimp_prop_check_button_new (config, "supersample",
388
                                       _("Supersampling"));
389 390 391
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

392
  /*  the clip resulting image toggle button  */
393
  button = gimp_prop_check_button_new (config, "clip", _("Clip result"));
394 395
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);
396

397 398 399 400
  /* the preview toggle button */
  button = gimp_prop_check_button_new (config, "show-preview", _("Preview"));
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);
401

402
  /*  the grid frame  */
403
  frame = gimp_frame_new (NULL);
404 405
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame);
406

407
  /*  the grid type menu  */
408 409 410
  combo = gimp_prop_enum_combo_box_new (config, "grid-type", 0, 0);
  gtk_frame_set_label_widget (GTK_FRAME (frame), combo);
  gtk_widget_show (combo);
411

412 413 414 415 416 417 418
  /*  the grid density scale  */
  table = gtk_table_new (1, 3, FALSE);
  gtk_container_set_border_width (GTK_CONTAINER (table), 2);
  gtk_table_set_col_spacings (GTK_TABLE (table), 2);
  gtk_container_add (GTK_CONTAINER (frame), table);
  gtk_widget_show (table);

419 420
  g_signal_connect (config, "notify::grid-type",
                    G_CALLBACK (gimp_transform_options_grid_notify),
421
                    table);
422

423 424 425 426 427
  gimp_prop_scale_entry_new (config, "grid-size",
                             GTK_TABLE (table), 0, 0,
                             _("Density:"),
                             1.0, 8.0, 0,
                             FALSE, 0.0, 0.0);
428

429 430
  if (tool_options->tool_info->tool_type == GIMP_TYPE_ROTATE_TOOL ||
      tool_options->tool_info->tool_type == GIMP_TYPE_SCALE_TOOL)
431
    {
432
      GtkWidget *vbox2;
433
      GtkWidget *vbox3;
434

435
      /*  the constraints frame  */
436
      frame = gimp_frame_new (_("Constraints"));
437 438 439 440 441 442 443 444
      gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
      gtk_widget_show (frame);

      vbox2 = gtk_vbox_new (FALSE, 2);
      gtk_container_set_border_width (GTK_CONTAINER (vbox2), 2);
      gtk_container_add (GTK_CONTAINER (frame), vbox2);
      gtk_widget_show (vbox2);

445
      if (tool_options->tool_info->tool_type == GIMP_TYPE_ROTATE_TOOL)
446
        {
447 448
          gchar *str;

449
          str = g_strdup_printf (_("15 degrees  %s"),
450
                                 gimp_get_mod_string (GDK_CONTROL_MASK));
451

452 453 454
          button = gimp_prop_check_button_new (config, "constrain-1", str);
          gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
          gtk_widget_show (button);
455

456
          g_free (str);
457
        }
458
      else if (tool_options->tool_info->tool_type == GIMP_TYPE_SCALE_TOOL)
459
        {
460 461 462 463 464
          gchar *str1;
          gchar *str2;
          gchar *str3;

          g_object_set (config,
465 466 467
                        "constrain-1", FALSE,
                        "constrain-2", FALSE,
                        NULL);
468

469
          str1 = g_strdup_printf (_("Keep height  %s"),
Michael Natterer's avatar
Michael Natterer committed
470
                                  gimp_get_mod_string (GDK_CONTROL_MASK));
471
          str2 = g_strdup_printf (_("Keep width  %s"),
472 473 474 475
                                  gimp_get_mod_string (GDK_MOD1_MASK));
          str3 = g_strdup_printf (_("Keep aspect  %s"),
                                  gimp_get_mod_string (GDK_CONTROL_MASK |
                                                       GDK_MOD1_MASK));
476 477 478 479 480 481 482 483 484 485 486

          vbox3 = gimp_int_radio_group_new (FALSE, NULL,
                                            G_CALLBACK (gimp_scale_constraints_callback),
                                            config, 0,

                                            _("None"), 0, NULL,
                                            str1,      1, NULL,
                                            str2,      2, NULL,
                                            str3,      3, NULL,

                                            NULL);
487

488 489 490 491 492 493
          gtk_box_pack_start (GTK_BOX (vbox2), vbox3, FALSE, FALSE, 0);
          gtk_widget_show (vbox3);

          g_free (str1);
          g_free (str2);
          g_free (str3);
494 495
        }
    }
496

497
  gimp_transform_options_set_defaults (tool_options);
498 499

  return vbox;
500 501 502
}


Michael Natterer's avatar
Michael Natterer committed
503 504 505
/*  private functions  */

static void
506 507 508
gimp_transform_options_grid_notify (GimpTransformOptions *options,
                                    GParamSpec           *pspec,
                                    GtkWidget            *density_box)
Michael Natterer's avatar
Michael Natterer committed
509
{
510 511 512
  gtk_widget_set_sensitive (density_box,
                            options->grid_type !=
                            GIMP_TRANSFORM_GRID_TYPE_NONE);
Michael Natterer's avatar
Michael Natterer committed
513
}