gimplayermodecombobox.c 14.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* LIBGIMP - The GIMP Library
 * Copyright (C) 1995-1999 Peter Mattis and Spencer Kimball
 *
 * gimplayermodecombobox.c
 * Copyright (C) 2017  Michael Natterer <mitch@gimp.org>
 *
 * 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 3 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
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 20 21 22 23 24 25 26 27 28 29 30
 */

#include "config.h"

#include <gtk/gtk.h>
#include <gegl.h>

#include "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"

#include "widgets-types.h"

31
#include "operations/layer-modes/gimp-layer-modes.h"
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

#include "gimplayermodecombobox.h"


/**
 * SECTION: gimplayermodecombobox
 * @title: GimpLayerModeComboBox
 * @short_description: A #GimpEnumComboBox subclass for selecting a layer mode.
 *
 * A #GtkComboBox subclass for selecting a layer mode
 **/


enum
{
  PROP_0,
48
  PROP_CONTEXT,
49
  PROP_LAYER_MODE,
50
  PROP_GROUP
51 52 53 54 55
};


struct _GimpLayerModeComboBoxPrivate
{
56 57 58
  GimpLayerModeContext context;
  GimpLayerMode        layer_mode;
  GimpLayerModeGroup   group;
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
};


static void     gimp_layer_mode_combo_box_constructed      (GObject               *object);
static void     gimp_layer_mode_combo_box_set_property     (GObject               *object,
                                                            guint                  prop_id,
                                                            const GValue          *value,
                                                            GParamSpec            *pspec);
static void     gimp_layer_mode_combo_box_get_property     (GObject               *object,
                                                            guint                  prop_id,
                                                            GValue                *value,
                                                            GParamSpec            *pspec);

static void     gimp_layer_mode_combo_box_changed          (GtkComboBox           *gtk_combo);

static void     gimp_layer_mode_combo_box_update_model     (GimpLayerModeComboBox *combo,
                                                            gboolean               change_mode);
static gboolean gimp_layer_mode_combo_box_separator_func   (GtkTreeModel          *model,
                                                            GtkTreeIter           *iter,
                                                            gpointer               data);


81 82
G_DEFINE_TYPE_WITH_PRIVATE (GimpLayerModeComboBox, gimp_layer_mode_combo_box,
                            GIMP_TYPE_ENUM_COMBO_BOX)
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98

#define parent_class gimp_layer_mode_combo_box_parent_class


static void
gimp_layer_mode_combo_box_class_init (GimpLayerModeComboBoxClass *klass)
{
  GObjectClass     *object_class = G_OBJECT_CLASS (klass);
  GtkComboBoxClass *combo_class  = GTK_COMBO_BOX_CLASS (klass);

  object_class->constructed  = gimp_layer_mode_combo_box_constructed;
  object_class->set_property = gimp_layer_mode_combo_box_set_property;
  object_class->get_property = gimp_layer_mode_combo_box_get_property;

  combo_class->changed       = gimp_layer_mode_combo_box_changed;

99 100 101 102 103 104 105 106
  g_object_class_install_property (object_class, PROP_CONTEXT,
                                   g_param_spec_flags ("context",
                                                       NULL, NULL,
                                                       GIMP_TYPE_LAYER_MODE_CONTEXT,
                                                       GIMP_LAYER_MODE_CONTEXT_ALL,
                                                       GIMP_PARAM_READWRITE |
                                                       G_PARAM_CONSTRUCT));

107 108 109 110
  g_object_class_install_property (object_class, PROP_LAYER_MODE,
                                   g_param_spec_enum ("layer-mode",
                                                      NULL, NULL,
                                                      GIMP_TYPE_LAYER_MODE,
111
                                                      GIMP_LAYER_MODE_NORMAL,
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
                                                      GIMP_PARAM_READWRITE |
                                                      G_PARAM_CONSTRUCT));

  g_object_class_install_property (object_class, PROP_GROUP,
                                   g_param_spec_enum ("group",
                                                      NULL, NULL,
                                                      GIMP_TYPE_LAYER_MODE_GROUP,
                                                      GIMP_LAYER_MODE_GROUP_DEFAULT,
                                                      GIMP_PARAM_READWRITE |
                                                      G_PARAM_CONSTRUCT));
}

static void
gimp_layer_mode_combo_box_init (GimpLayerModeComboBox *combo)
{
127
  combo->priv = gimp_layer_mode_combo_box_get_instance_private (combo);
128 129 130

  gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
                                        gimp_layer_mode_combo_box_separator_func,
131
                                        GINT_TO_POINTER (GIMP_LAYER_MODE_SEPARATOR),
132 133 134 135 136 137 138 139 140 141
                                        NULL);
}

static void
gimp_layer_mode_combo_box_constructed (GObject *object)
{
  GimpLayerModeComboBox *combo = GIMP_LAYER_MODE_COMBO_BOX (object);

  G_OBJECT_CLASS (parent_class)->constructed (object);

142 143
  gimp_layer_mode_combo_box_update_model (combo, FALSE);

144 145 146 147 148 149 150 151 152 153 154 155 156 157
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo),
                                 combo->priv->layer_mode);
}

static void
gimp_layer_mode_combo_box_set_property (GObject      *object,
                                        guint         prop_id,
                                        const GValue *value,
                                        GParamSpec   *pspec)
{
  GimpLayerModeComboBox *combo = GIMP_LAYER_MODE_COMBO_BOX (object);

  switch (prop_id)
    {
158 159 160 161
    case PROP_CONTEXT:
      gimp_layer_mode_combo_box_set_context (combo, g_value_get_flags (value));
      break;

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    case PROP_LAYER_MODE:
      gimp_layer_mode_combo_box_set_mode (combo, g_value_get_enum (value));
      break;

    case PROP_GROUP:
      gimp_layer_mode_combo_box_set_group (combo, g_value_get_enum (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gimp_layer_mode_combo_box_get_property (GObject    *object,
                                        guint       prop_id,
                                        GValue     *value,
                                        GParamSpec *pspec)
{
  GimpLayerModeComboBox *combo = GIMP_LAYER_MODE_COMBO_BOX (object);

  switch (prop_id)
    {
186 187 188 189
    case PROP_CONTEXT:
      g_value_set_flags (value, combo->priv->context);
      break;

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
    case PROP_LAYER_MODE:
      g_value_set_enum (value, combo->priv->layer_mode);
      break;

    case PROP_GROUP:
      g_value_set_enum (value, combo->priv->group);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gimp_layer_mode_combo_box_changed (GtkComboBox *gtk_combo)
{
  GimpLayerModeComboBox *combo = GIMP_LAYER_MODE_COMBO_BOX (gtk_combo);
  GimpLayerMode          mode;

  if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo),
                                     (gint *) &mode))
    {
      combo->priv->layer_mode = mode;

      g_object_notify (G_OBJECT (combo), "layer-mode");
    }
}


/**
 * gimp_layer_mode_combo_box_new:
 * Foo.
 *
 * Return value: a new #GimpLayerModeComboBox.
 **/
GtkWidget *
227
gimp_layer_mode_combo_box_new (GimpLayerModeContext context)
228
{
229
  return g_object_new (GIMP_TYPE_LAYER_MODE_COMBO_BOX,
230
                       "context", context,
231
                       NULL);
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 257 258 259 260 261
void
gimp_layer_mode_combo_box_set_context (GimpLayerModeComboBox *combo,
                                       GimpLayerModeContext   context)
{
  g_return_if_fail (GIMP_IS_LAYER_MODE_COMBO_BOX (combo));

  if (context != combo->priv->context)
    {
      g_object_freeze_notify (G_OBJECT (combo));

      combo->priv->context = context;
      g_object_notify (G_OBJECT (combo), "context");

      gimp_layer_mode_combo_box_update_model (combo, TRUE);

      g_object_thaw_notify (G_OBJECT (combo));
    }
}

GimpLayerModeContext
gimp_layer_mode_combo_box_get_context (GimpLayerModeComboBox *combo)
{
  g_return_val_if_fail (GIMP_IS_LAYER_MODE_COMBO_BOX (combo),
                        GIMP_LAYER_MODE_CONTEXT_ALL);

  return combo->priv->context;
}

262 263 264 265 266
void
gimp_layer_mode_combo_box_set_mode (GimpLayerModeComboBox *combo,
                                    GimpLayerMode          mode)
{
  g_return_if_fail (GIMP_IS_LAYER_MODE_COMBO_BOX (combo));
267
  g_return_if_fail (gimp_layer_mode_get_context (mode) & combo->priv->context);
268 269 270 271 272 273 274 275

  if (mode != combo->priv->layer_mode)
    {
      GtkTreeModel *model;
      GtkTreeIter   dummy;

      model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));

276 277
      g_object_freeze_notify (G_OBJECT (combo));

278 279 280
      if (! gimp_int_store_lookup_by_value (model, mode, &dummy))
        {
          combo->priv->group = gimp_layer_mode_get_group (mode);
281
          g_object_notify (G_OBJECT (combo), "group");
282 283 284 285 286

          gimp_layer_mode_combo_box_update_model (combo, FALSE);
        }

      gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), mode);
287 288

      g_object_thaw_notify (G_OBJECT (combo));
289 290 291 292 293 294 295
    }
}

GimpLayerMode
gimp_layer_mode_combo_box_get_mode (GimpLayerModeComboBox *combo)
{
  g_return_val_if_fail (GIMP_IS_LAYER_MODE_COMBO_BOX (combo),
296
                        GIMP_LAYER_MODE_NORMAL);
297 298 299 300 301 302 303 304 305 306 307 308

  return combo->priv->layer_mode;
}

void
gimp_layer_mode_combo_box_set_group (GimpLayerModeComboBox *combo,
                                     GimpLayerModeGroup     group)
{
  g_return_if_fail (GIMP_IS_LAYER_MODE_COMBO_BOX (combo));

  if (group != combo->priv->group)
    {
309 310
      g_object_freeze_notify (G_OBJECT (combo));

311
      combo->priv->group = group;
312
      g_object_notify (G_OBJECT (combo), "group");
313 314

      gimp_layer_mode_combo_box_update_model (combo, TRUE);
315 316

      g_object_thaw_notify (G_OBJECT (combo));
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
    }
}

GimpLayerModeGroup
gimp_layer_mode_combo_box_get_group (GimpLayerModeComboBox *combo)
{
  g_return_val_if_fail (GIMP_IS_LAYER_MODE_COMBO_BOX (combo),
                        GIMP_LAYER_MODE_GROUP_DEFAULT);

  return combo->priv->group;
}


/*  private functions  */

332 333
static void
gimp_enum_store_add_value (GtkListStore *store,
334
                           GEnumClass   *enum_class,
335 336 337 338
                           GEnumValue   *value)
{
  GtkTreeIter  iter = { 0, };
  const gchar *desc;
Ell's avatar
Ell committed
339
  const gchar *abbrev;
340 341
  gchar       *stripped;

342 343
  desc   = gimp_enum_value_get_desc   (enum_class, value);
  abbrev = gimp_enum_value_get_abbrev (enum_class, value);
344 345 346 347 348 349

  /* no mnemonics in combo boxes */
  stripped = gimp_strip_uline (desc);

  gtk_list_store_append (store, &iter);
  gtk_list_store_set (store, &iter,
Ell's avatar
Ell committed
350 351 352
                      GIMP_INT_STORE_VALUE,  value->value,
                      GIMP_INT_STORE_LABEL,  stripped,
                      GIMP_INT_STORE_ABBREV, abbrev,
353 354 355 356 357
                      -1);

  g_free (stripped);
}

358 359 360 361 362 363 364 365 366 367 368
static void
gimp_enum_store_add_separator (GtkListStore *store)
{
  GtkTreeIter  iter = { 0, };

  gtk_list_store_append (store, &iter);
  gtk_list_store_set (store, &iter,
                      GIMP_INT_STORE_VALUE, GIMP_LAYER_MODE_SEPARATOR,
                      -1);
}

369
static GtkListStore *
370 371 372 373
gimp_enum_store_new_from_array (GType                 enum_type,
                                gint                  n_values,
                                const gint           *values,
                                GimpLayerModeContext  context)
374 375
{
  GtkListStore *store;
376
  GEnumClass   *enum_class;
377
  GEnumValue   *value;
378 379
  gboolean      first_item        = TRUE;
  gboolean      prepend_separator = FALSE;
380 381 382 383 384
  gint          i;

  g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
  g_return_val_if_fail (n_values > 1, NULL);
  g_return_val_if_fail (values != NULL, NULL);
385

386 387 388
  store = g_object_new (GIMP_TYPE_ENUM_STORE,
                        "enum-type", enum_type,
                        NULL);
389

390 391
  enum_class = g_type_class_ref (enum_type);

392 393
  for (i = 0; i < n_values; i++)
    {
394 395 396 397
      if (values[i] != GIMP_LAYER_MODE_SEPARATOR)
        {
          if (gimp_layer_mode_get_context (values[i]) & context)
            {
398
              value = g_enum_get_value (enum_class, values[i]);
399 400 401

              if (value)
                {
402 403 404 405 406 407 408
                  if (prepend_separator)
                    {
                      gimp_enum_store_add_separator (store);

                      prepend_separator = FALSE;
                    }

409
                  gimp_enum_store_add_value (store, enum_class, value);
410

411
                  first_item = FALSE;
412 413 414 415 416
                }
            }
        }
      else
        {
417 418
          if (! first_item)
            prepend_separator = TRUE;
419
        }
420 421
    }

422 423
  g_type_class_unref (enum_class);

424
  return store;
425 426 427 428 429 430
}

static void
gimp_layer_mode_combo_box_update_model (GimpLayerModeComboBox *combo,
                                        gboolean               change_mode)
{
431 432 433 434 435 436
  GtkListStore        *store;
  const GimpLayerMode *modes;
  gint                 n_modes;

  modes = gimp_layer_mode_get_group_array (combo->priv->group, &n_modes);
  store = gimp_enum_store_new_from_array (GIMP_TYPE_LAYER_MODE,
437 438
                                          n_modes, (gint *) modes,
                                          combo->priv->context);
439

440 441
  gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
  g_object_unref (store);
442 443 444 445 446 447 448

  if (change_mode)
    {
      GimpLayerMode new_mode;

      if (gimp_layer_mode_get_for_group (combo->priv->layer_mode,
                                         combo->priv->group,
449 450
                                         &new_mode) &&
          (gimp_layer_mode_get_context (new_mode) & combo->priv->context))
451 452 453 454 455 456 457 458
        {
          gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), new_mode);
        }
      else
        {
          GtkTreeIter iter;

          /*  switch to the first mode, which will be one of the "normal"  */
459
          gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
          gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
        }
    }
}

static gboolean
gimp_layer_mode_combo_box_separator_func (GtkTreeModel *model,
                                          GtkTreeIter  *iter,
                                          gpointer      data)
{
  gint value;

  gtk_tree_model_get (model, iter, GIMP_INT_STORE_VALUE, &value, -1);

  return value == GPOINTER_TO_INT (data);
}