gimpbrushselect.c 13.8 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3 4 5 6
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * gimpbrushselect.c
 * Copyright (C) 2004 Michael Natterer <mitch@gimp.org>
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10 11 12 13 14 15 16 17
 * (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 <http://www.gnu.org/licenses/>.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 */

#include "config.h"

#include <gtk/gtk.h>

#include "libgimpwidgets/gimpwidgets.h"

#include "widgets-types.h"

#include "base/temp-buf.h"

#include "core/gimp.h"
#include "core/gimpcontext.h"
#include "core/gimpbrush.h"
34
#include "core/gimpparamspecs.h"
35

36
#include "pdb/gimppdb.h"
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

#include "gimpbrushfactoryview.h"
#include "gimpbrushselect.h"
#include "gimpcontainerbox.h"
#include "gimpwidgets-constructors.h"

#include "gimp-intl.h"


enum
{
  PROP_0,
  PROP_OPACITY,
  PROP_PAINT_MODE,
  PROP_SPACING
};


static GObject  * gimp_brush_select_constructor  (GType            type,
                                                  guint            n_params,
                                                  GObjectConstructParam *params);
static void       gimp_brush_select_set_property (GObject         *object,
                                                  guint            property_id,
                                                  const GValue    *value,
                                                  GParamSpec      *pspec);

63
static GValueArray *
64
                  gimp_brush_select_run_callback (GimpPdbDialog   *dialog,
65
                                                  GimpObject      *object,
66 67
                                                  gboolean         closing,
                                                  GError         **error);
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

static void   gimp_brush_select_opacity_changed  (GimpContext     *context,
                                                  gdouble          opacity,
                                                  GimpBrushSelect *select);
static void   gimp_brush_select_mode_changed     (GimpContext     *context,
                                                  GimpLayerModeEffects  paint_mode,
                                                  GimpBrushSelect *select);

static void   gimp_brush_select_opacity_update   (GtkAdjustment   *adj,
                                                  GimpBrushSelect *select);
static void   gimp_brush_select_mode_update      (GtkWidget       *widget,
                                                  GimpBrushSelect *select);
static void   gimp_brush_select_spacing_update   (GtkAdjustment   *adj,
                                                  GimpBrushSelect *select);


84
G_DEFINE_TYPE (GimpBrushSelect, gimp_brush_select, GIMP_TYPE_PDB_DIALOG)
85

86
#define parent_class gimp_brush_select_parent_class
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104


static void
gimp_brush_select_class_init (GimpBrushSelectClass *klass)
{
  GObjectClass       *object_class = G_OBJECT_CLASS (klass);
  GimpPdbDialogClass *pdb_class    = GIMP_PDB_DIALOG_CLASS (klass);

  object_class->constructor  = gimp_brush_select_constructor;
  object_class->set_property = gimp_brush_select_set_property;

  pdb_class->run_callback    = gimp_brush_select_run_callback;

  g_object_class_install_property (object_class, PROP_OPACITY,
                                   g_param_spec_double ("opacity", NULL, NULL,
                                                        GIMP_OPACITY_TRANSPARENT,
                                                        GIMP_OPACITY_OPAQUE,
                                                        GIMP_OPACITY_OPAQUE,
105
                                                        GIMP_PARAM_WRITABLE |
106 107 108 109 110 111
                                                        G_PARAM_CONSTRUCT));

  g_object_class_install_property (object_class, PROP_PAINT_MODE,
                                   g_param_spec_enum ("paint-mode", NULL, NULL,
                                                      GIMP_TYPE_LAYER_MODE_EFFECTS,
                                                      GIMP_NORMAL_MODE,
112
                                                      GIMP_PARAM_WRITABLE |
113 114 115 116 117
                                                      G_PARAM_CONSTRUCT));

  g_object_class_install_property (object_class, PROP_SPACING,
                                   g_param_spec_int ("spacing", NULL, NULL,
                                                     -G_MAXINT, 1000, -1,
118
                                                     GIMP_PARAM_WRITABLE |
119 120 121
                                                     G_PARAM_CONSTRUCT));
}

122 123 124 125 126
static void
gimp_brush_select_init (GimpBrushSelect *select)
{
}

127 128 129 130 131 132 133 134
static GObject *
gimp_brush_select_constructor (GType                  type,
                               guint                  n_params,
                               GObjectConstructParam *params)
{
  GObject         *object;
  GimpPdbDialog   *dialog;
  GimpBrushSelect *select;
135
  GtkWidget       *content_area;
136 137 138 139 140 141 142 143 144 145 146
  GtkWidget       *table;
  GtkAdjustment   *spacing_adj;

  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);

  dialog = GIMP_PDB_DIALOG (object);
  select = GIMP_BRUSH_SELECT (object);

  gimp_context_set_opacity    (dialog->context, select->initial_opacity);
  gimp_context_set_paint_mode (dialog->context, select->initial_mode);

147
  g_signal_connect (dialog->context, "opacity-changed",
148 149
                    G_CALLBACK (gimp_brush_select_opacity_changed),
                    dialog);
150
  g_signal_connect (dialog->context, "paint-mode-changed",
151 152 153 154 155 156 157 158
                    G_CALLBACK (gimp_brush_select_mode_changed),
                    dialog);

  dialog->view =
    gimp_brush_factory_view_new (GIMP_VIEW_TYPE_GRID,
                                 dialog->context->gimp->brush_factory,
                                 dialog->context,
                                 FALSE,
159
                                 GIMP_VIEW_SIZE_MEDIUM, 1,
160 161 162
                                 dialog->menu_factory);

  gimp_container_box_set_size_request (GIMP_CONTAINER_BOX (GIMP_CONTAINER_EDITOR (dialog->view)->view),
163 164
                                       5 * (GIMP_VIEW_SIZE_MEDIUM + 2),
                                       5 * (GIMP_VIEW_SIZE_MEDIUM + 2));
165 166

  gtk_container_set_border_width (GTK_CONTAINER (dialog->view), 12);
167 168 169

  content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
  gtk_container_add (GTK_CONTAINER (content_area), dialog->view);
170 171 172
  gtk_widget_show (dialog->view);

  /*  Create the frame and the table for the options  */
173
  table = gtk_widget_get_parent (GIMP_BRUSH_FACTORY_VIEW (dialog->view)->spacing_scale);
174 175 176 177 178 179 180 181 182 183 184 185
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  gtk_table_set_row_spacings (GTK_TABLE (table), 2);

  /*  Create the opacity scale widget  */
  select->opacity_data =
    GTK_ADJUSTMENT (gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
                                          _("Opacity:"), -1, 5,
                                          gimp_context_get_opacity (dialog->context) * 100.0,
                                          0.0, 100.0, 1.0, 10.0, 1,
                                          TRUE, 0.0, 0.0,
                                          NULL, NULL));

186
  g_signal_connect (select->opacity_data, "value-changed",
187 188 189 190
                    G_CALLBACK (gimp_brush_select_opacity_update),
                    select);

  /*  Create the paint mode option menu  */
191
  select->paint_mode_menu = gimp_paint_mode_menu_new (TRUE, FALSE);
192
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
193 194
                             _("Mode:"), 0.0, 0.5,
                             select->paint_mode_menu, 2, FALSE);
195

196 197 198
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (select->paint_mode_menu),
                              gimp_context_get_paint_mode (dialog->context),
                              G_CALLBACK (gimp_brush_select_mode_update),
199
                              select);
200

201 202 203 204 205 206
  spacing_adj = GIMP_BRUSH_FACTORY_VIEW (dialog->view)->spacing_adjustment;

  /*  Use passed spacing instead of brushes default  */
  if (select->spacing >= 0)
    gtk_adjustment_set_value (spacing_adj, select->spacing);

207
  g_signal_connect (spacing_adj, "value-changed",
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
                    G_CALLBACK (gimp_brush_select_spacing_update),
                    select);

  gtk_widget_show (table);

  return object;
}

static void
gimp_brush_select_set_property (GObject      *object,
                                guint         property_id,
                                const GValue *value,
                                GParamSpec   *pspec)
{
  GimpPdbDialog   *dialog = GIMP_PDB_DIALOG (object);
  GimpBrushSelect *select = GIMP_BRUSH_SELECT (object);

  switch (property_id)
    {
    case PROP_OPACITY:
      if (dialog->view)
        gimp_context_set_opacity (dialog->context, g_value_get_double (value));
      else
        select->initial_opacity = g_value_get_double (value);
      break;
    case PROP_PAINT_MODE:
      if (dialog->view)
        gimp_context_set_paint_mode (dialog->context, g_value_get_enum (value));
      else
        select->initial_mode = g_value_get_enum (value);
      break;
    case PROP_SPACING:
      if (dialog->view)
        {
          if (g_value_get_int (value) >= 0)
            gtk_adjustment_set_value (GIMP_BRUSH_FACTORY_VIEW (dialog->view)->spacing_adjustment,
                                      g_value_get_int (value));
        }
      else
        {
          select->spacing = g_value_get_int (value);
        }
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

257
static GValueArray *
258 259 260 261
gimp_brush_select_run_callback (GimpPdbDialog  *dialog,
                                GimpObject     *object,
                                gboolean        closing,
                                GError        **error)
262
{
263 264 265
  GimpBrush   *brush = GIMP_BRUSH (object);
  GimpArray   *array;
  GValueArray *return_vals;
266

267
  array = gimp_array_new (temp_buf_get_data (brush->mask),
268
                          temp_buf_get_data_size (brush->mask),
269 270 271
                          TRUE);

  return_vals =
272 273
    gimp_pdb_execute_procedure_by_name (dialog->pdb,
                                        dialog->caller_context,
274
                                        NULL, error,
275 276 277 278 279 280 281 282 283 284 285
                                        dialog->callback_name,
                                        G_TYPE_STRING,        object->name,
                                        G_TYPE_DOUBLE,        gimp_context_get_opacity (dialog->context) * 100.0,
                                        GIMP_TYPE_INT32,      GIMP_BRUSH_SELECT (dialog)->spacing,
                                        GIMP_TYPE_INT32,      gimp_context_get_paint_mode (dialog->context),
                                        GIMP_TYPE_INT32,      brush->mask->width,
                                        GIMP_TYPE_INT32,      brush->mask->height,
                                        GIMP_TYPE_INT32,      array->length,
                                        GIMP_TYPE_INT8_ARRAY, array,
                                        GIMP_TYPE_INT32,      closing,
                                        G_TYPE_NONE);
286 287 288 289

  gimp_array_free (array);

  return return_vals;
290 291 292 293 294 295 296 297 298
}

static void
gimp_brush_select_opacity_changed (GimpContext     *context,
                                   gdouble          opacity,
                                   GimpBrushSelect *select)
{
  g_signal_handlers_block_by_func (select->opacity_data,
                                   gimp_brush_select_opacity_update,
299
                                   select);
300 301

  gtk_adjustment_set_value (GTK_ADJUSTMENT (select->opacity_data),
302
                            opacity * 100.0);
303 304

  g_signal_handlers_unblock_by_func (select->opacity_data,
305 306
                                     gimp_brush_select_opacity_update,
                                     select);
307 308 309 310 311 312 313 314 315

  gimp_pdb_dialog_run_callback (GIMP_PDB_DIALOG (select), FALSE);
}

static void
gimp_brush_select_mode_changed (GimpContext          *context,
                                GimpLayerModeEffects  paint_mode,
                                GimpBrushSelect      *select)
{
316 317
  g_signal_handlers_block_by_func (select->paint_mode_menu,
                                   gimp_brush_select_mode_update,
318
                                   select);
319 320 321 322 323 324 325

  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (select->paint_mode_menu),
                                 paint_mode);

  g_signal_handlers_unblock_by_func (select->paint_mode_menu,
                                     gimp_brush_select_mode_update,
                                     select);
326 327 328 329 330 331 332 333 334

  gimp_pdb_dialog_run_callback (GIMP_PDB_DIALOG (select), FALSE);
}

static void
gimp_brush_select_opacity_update (GtkAdjustment   *adjustment,
                                  GimpBrushSelect *select)
{
  gimp_context_set_opacity (GIMP_PDB_DIALOG (select)->context,
335
                            gtk_adjustment_get_value (adjustment) / 100.0);
336 337 338 339 340 341
}

static void
gimp_brush_select_mode_update (GtkWidget       *widget,
                               GimpBrushSelect *select)
{
342
  gint paint_mode;
343

344 345 346 347 348 349
  if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget),
                                     &paint_mode))
    {
      gimp_context_set_paint_mode (GIMP_PDB_DIALOG (select)->context,
                                   (GimpLayerModeEffects) paint_mode);
    }
350 351 352 353 354 355
}

static void
gimp_brush_select_spacing_update (GtkAdjustment   *adjustment,
                                  GimpBrushSelect *select)
{
356 357 358
  gdouble value = gtk_adjustment_get_value (adjustment);

  if (select->spacing != value)
359
    {
360
      select->spacing = value;
361 362 363 364

      gimp_pdb_dialog_run_callback (GIMP_PDB_DIALOG (select), FALSE);
    }
}