~ubuntu-branches/ubuntu/hoary/gimp/hoary

« back to all changes in this revision

Viewing changes to app/widgets/gimppropwidgets.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2005-04-04 14:51:23 UTC
  • Revision ID: james.westby@ubuntu.com-20050404145123-9py049eeelfymur8
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* The GIMP -- an image manipulation program
 
2
 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * gimppropwidgets.c
 
5
 * Copyright (C) 2002-2004  Michael Natterer <mitch@gimp.org>
 
6
 *                          Sven Neumann <sven@gimp.org>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <string.h>
 
26
 
 
27
#include <gtk/gtk.h>
 
28
 
 
29
#include "libgimpcolor/gimpcolor.h"
 
30
#include "libgimpmath/gimpmath.h"
 
31
#include "libgimpbase/gimpbase.h"
 
32
#include "libgimpwidgets/gimpwidgets.h"
 
33
 
 
34
#include "widgets-types.h"
 
35
 
 
36
#include "config/gimpconfig-params.h"
 
37
#include "config/gimpconfig-path.h"
 
38
 
 
39
#include "core/gimpviewable.h"
 
40
 
 
41
#include "gimpcolorpanel.h"
 
42
#include "gimpdnd.h"
 
43
#include "gimpenumcombobox.h"
 
44
#include "gimpenumstore.h"
 
45
#include "gimpenumwidgets.h"
 
46
#include "gimpview.h"
 
47
#include "gimppropwidgets.h"
 
48
#include "gimpwidgets-constructors.h"
 
49
 
 
50
#include "gimp-intl.h"
 
51
 
 
52
 
 
53
/*  utility function prototypes  */
 
54
 
 
55
static void         set_param_spec     (GObject     *object,
 
56
                                        GtkWidget   *widget,
 
57
                                        GParamSpec  *param_spec);
 
58
static void         set_radio_spec     (GObject     *object,
 
59
                                        GParamSpec  *param_spec);
 
60
static GParamSpec * get_param_spec     (GObject     *object);
 
61
 
 
62
static GParamSpec * find_param_spec    (GObject     *object,
 
63
                                        const gchar *property_name,
 
64
                                        const gchar *strloc);
 
65
static GParamSpec * check_param_spec   (GObject     *object,
 
66
                                        const gchar *property_name,
 
67
                                        GType         type,
 
68
                                        const gchar *strloc);
 
69
 
 
70
static gboolean     get_numeric_values (GObject     *object,
 
71
                                        GParamSpec  *param_spec,
 
72
                                        gdouble     *value,
 
73
                                        gdouble     *lower,
 
74
                                        gdouble     *upper,
 
75
                                        const gchar *strloc);
 
76
 
 
77
static void         connect_notify     (GObject     *config,
 
78
                                        const gchar *property_name,
 
79
                                        GCallback    callback,
 
80
                                        gpointer     callback_data);
 
81
 
 
82
 
 
83
/******************/
 
84
/*  check button  */
 
85
/******************/
 
86
 
 
87
static void   gimp_prop_check_button_callback (GtkWidget  *widget,
 
88
                                               GObject    *config);
 
89
static void   gimp_prop_check_button_notify   (GObject    *config,
 
90
                                               GParamSpec *param_spec,
 
91
                                               GtkWidget  *button);
 
92
 
 
93
GtkWidget *
 
94
gimp_prop_check_button_new (GObject     *config,
 
95
                            const gchar *property_name,
 
96
                            const gchar *label)
 
97
{
 
98
  GParamSpec  *param_spec;
 
99
  GtkWidget   *button;
 
100
  gboolean     value;
 
101
 
 
102
  param_spec = check_param_spec (config, property_name,
 
103
                                 G_TYPE_PARAM_BOOLEAN, G_STRFUNC);
 
104
  if (! param_spec)
 
105
    return NULL;
 
106
 
 
107
  g_object_get (config,
 
108
                property_name, &value,
 
109
                NULL);
 
110
 
 
111
  button = gtk_check_button_new_with_mnemonic (label);
 
112
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), value);
 
113
 
 
114
  set_param_spec (G_OBJECT (button), button, param_spec);
 
115
 
 
116
  g_signal_connect (button, "toggled",
 
117
                    G_CALLBACK (gimp_prop_check_button_callback),
 
118
                    config);
 
119
 
 
120
  connect_notify (config, property_name,
 
121
                  G_CALLBACK (gimp_prop_check_button_notify),
 
122
                  button);
 
123
 
 
124
  return button;
 
125
}
 
126
 
 
127
static void
 
128
gimp_prop_check_button_callback (GtkWidget *widget,
 
129
                                 GObject   *config)
 
130
{
 
131
  GParamSpec *param_spec;
 
132
 
 
133
  param_spec = get_param_spec (G_OBJECT (widget));
 
134
  if (! param_spec)
 
135
    return;
 
136
 
 
137
  g_object_set (config,
 
138
                param_spec->name, GTK_TOGGLE_BUTTON (widget)->active,
 
139
                NULL);
 
140
 
 
141
  gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (widget));
 
142
}
 
143
 
 
144
static void
 
145
gimp_prop_check_button_notify (GObject    *config,
 
146
                               GParamSpec *param_spec,
 
147
                               GtkWidget  *button)
 
148
{
 
149
  gboolean value;
 
150
 
 
151
  g_object_get (config,
 
152
                param_spec->name, &value,
 
153
                NULL);
 
154
 
 
155
  if (GTK_TOGGLE_BUTTON (button)->active != value)
 
156
    {
 
157
      g_signal_handlers_block_by_func (button,
 
158
                                       gimp_prop_check_button_callback,
 
159
                                       config);
 
160
 
 
161
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), value);
 
162
      gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (button));
 
163
 
 
164
      g_signal_handlers_unblock_by_func (button,
 
165
                                         gimp_prop_check_button_callback,
 
166
                                         config);
 
167
    }
 
168
}
 
169
 
 
170
 
 
171
static void   gimp_prop_enum_check_button_callback (GtkWidget  *widget,
 
172
                                                    GObject    *config);
 
173
static void   gimp_prop_enum_check_button_notify   (GObject    *config,
 
174
                                                    GParamSpec *param_spec,
 
175
                                                    GtkWidget  *button);
 
176
 
 
177
GtkWidget *
 
178
gimp_prop_enum_check_button_new (GObject     *config,
 
179
                                 const gchar *property_name,
 
180
                                 const gchar *label,
 
181
                                 gint         false_value,
 
182
                                 gint         true_value)
 
183
{
 
184
  GParamSpec  *param_spec;
 
185
  GtkWidget   *button;
 
186
  gint        value;
 
187
 
 
188
  param_spec = check_param_spec (config, property_name,
 
189
                                 G_TYPE_PARAM_ENUM, G_STRFUNC);
 
190
  if (! param_spec)
 
191
    return NULL;
 
192
 
 
193
  g_object_get (config,
 
194
                property_name, &value,
 
195
                NULL);
 
196
 
 
197
  button = gtk_check_button_new_with_mnemonic (label);
 
198
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), value == true_value);
 
199
 
 
200
  if (value != false_value && value != true_value)
 
201
    gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
 
202
 
 
203
  set_param_spec (G_OBJECT (button), button, param_spec);
 
204
 
 
205
  g_object_set_data (G_OBJECT (button), "false-value",
 
206
                     GINT_TO_POINTER (false_value));
 
207
  g_object_set_data (G_OBJECT (button), "true-value",
 
208
                     GINT_TO_POINTER (true_value));
 
209
 
 
210
  g_signal_connect (button, "toggled",
 
211
                    G_CALLBACK (gimp_prop_enum_check_button_callback),
 
212
                    config);
 
213
 
 
214
  connect_notify (config, property_name,
 
215
                  G_CALLBACK (gimp_prop_enum_check_button_notify),
 
216
                  button);
 
217
 
 
218
  return button;
 
219
}
 
220
 
 
221
static void
 
222
gimp_prop_enum_check_button_callback (GtkWidget *widget,
 
223
                                      GObject   *config)
 
224
{
 
225
  GParamSpec *param_spec;
 
226
  gint        false_value;
 
227
  gint        true_value;
 
228
 
 
229
  param_spec = get_param_spec (G_OBJECT (widget));
 
230
  if (! param_spec)
 
231
    return;
 
232
 
 
233
  false_value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
 
234
                                                    "false-value"));
 
235
  true_value  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
 
236
                                                    "true-value"));
 
237
 
 
238
  g_object_set (config,
 
239
                param_spec->name,
 
240
                GTK_TOGGLE_BUTTON (widget)->active ? true_value : false_value,
 
241
                NULL);
 
242
 
 
243
  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (widget), FALSE);
 
244
 
 
245
  gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (widget));
 
246
}
 
247
 
 
248
static void
 
249
gimp_prop_enum_check_button_notify (GObject    *config,
 
250
                                    GParamSpec *param_spec,
 
251
                                    GtkWidget  *button)
 
252
{
 
253
  gint     value;
 
254
  gint     false_value;
 
255
  gint     true_value;
 
256
  gboolean active       = FALSE;
 
257
  gboolean inconsistent = FALSE;
 
258
 
 
259
  g_object_get (config,
 
260
                param_spec->name, &value,
 
261
                NULL);
 
262
 
 
263
  false_value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
 
264
                                                    "false-value"));
 
265
  true_value  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
 
266
                                                    "true-value"));
 
267
 
 
268
  if (value == true_value)
 
269
    active = TRUE;
 
270
  else if (value != false_value)
 
271
    inconsistent = TRUE;
 
272
 
 
273
  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button),
 
274
                                      inconsistent);
 
275
 
 
276
  if (GTK_TOGGLE_BUTTON (button)->active != active)
 
277
    {
 
278
      g_signal_handlers_block_by_func (button,
 
279
                                       gimp_prop_enum_check_button_callback,
 
280
                                       config);
 
281
 
 
282
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active);
 
283
      gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (button));
 
284
 
 
285
      g_signal_handlers_unblock_by_func (button,
 
286
                                         gimp_prop_enum_check_button_callback,
 
287
                                         config);
 
288
    }
 
289
}
 
290
 
 
291
 
 
292
/*************************/
 
293
/*  int/enum combo box   */
 
294
/*************************/
 
295
 
 
296
static void   gimp_prop_int_combo_box_callback (GtkWidget   *widget,
 
297
                                                GObject     *config);
 
298
static void   gimp_prop_int_combo_box_notify   (GObject     *config,
 
299
                                                GParamSpec  *param_spec,
 
300
                                                GtkWidget   *widget);
 
301
 
 
302
GtkWidget *
 
303
gimp_prop_int_combo_box_new (GObject      *config,
 
304
                             const gchar  *property_name,
 
305
                             GimpIntStore *store)
 
306
{
 
307
  GParamSpec *param_spec;
 
308
  GtkWidget  *combo_box;
 
309
  GtkWidget  *widget;
 
310
  gint        value;
 
311
 
 
312
  param_spec = check_param_spec (config, property_name,
 
313
                                 G_TYPE_PARAM_INT, G_STRFUNC);
 
314
  if (! param_spec)
 
315
    return NULL;
 
316
 
 
317
  g_object_get (config,
 
318
                property_name, &value,
 
319
                NULL);
 
320
 
 
321
  combo_box = g_object_new (GIMP_TYPE_INT_COMBO_BOX,
 
322
                            "model", store,
 
323
                            NULL);
 
324
 
 
325
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo_box), value);
 
326
 
 
327
  g_signal_connect (combo_box, "changed",
 
328
                    G_CALLBACK (gimp_prop_int_combo_box_callback),
 
329
                    config);
 
330
 
 
331
  /*  can't set a tooltip on a combo_box  */
 
332
  if (g_param_spec_get_blurb (param_spec))
 
333
    {
 
334
      widget = gtk_event_box_new ();
 
335
      gtk_container_add (GTK_CONTAINER (widget), combo_box);
 
336
      gtk_widget_show (combo_box);
 
337
    }
 
338
  else
 
339
    {
 
340
      widget = combo_box;
 
341
    }
 
342
 
 
343
  set_param_spec (G_OBJECT (combo_box), widget, param_spec);
 
344
 
 
345
  connect_notify (config, property_name,
 
346
                  G_CALLBACK (gimp_prop_int_combo_box_notify),
 
347
                  combo_box);
 
348
 
 
349
  return widget;
 
350
}
 
351
 
 
352
GtkWidget *
 
353
gimp_prop_enum_combo_box_new (GObject     *config,
 
354
                              const gchar *property_name,
 
355
                              gint         minimum,
 
356
                              gint         maximum)
 
357
{
 
358
  GParamSpec *param_spec;
 
359
  GtkWidget  *combo_box;
 
360
  GtkWidget  *widget;
 
361
  gint        value;
 
362
 
 
363
  param_spec = check_param_spec (config, property_name,
 
364
                                 G_TYPE_PARAM_ENUM, G_STRFUNC);
 
365
  if (! param_spec)
 
366
    return NULL;
 
367
 
 
368
  g_object_get (config,
 
369
                property_name, &value,
 
370
                NULL);
 
371
 
 
372
  if (minimum != maximum)
 
373
    {
 
374
      GtkListStore *store;
 
375
 
 
376
      store = gimp_enum_store_new_with_range (param_spec->value_type,
 
377
                                              minimum, maximum);
 
378
 
 
379
      combo_box = g_object_new (GIMP_TYPE_ENUM_COMBO_BOX,
 
380
                                "model", store,
 
381
                                NULL);
 
382
 
 
383
      g_object_unref (store);
 
384
    }
 
385
  else
 
386
    {
 
387
      combo_box = gimp_enum_combo_box_new (param_spec->value_type);
 
388
    }
 
389
 
 
390
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo_box), value);
 
391
 
 
392
  g_signal_connect (combo_box, "changed",
 
393
                    G_CALLBACK (gimp_prop_int_combo_box_callback),
 
394
                    config);
 
395
 
 
396
  /*  can't set a tooltip on a combo_box  */
 
397
  if (g_param_spec_get_blurb (param_spec))
 
398
    {
 
399
      widget = gtk_event_box_new ();
 
400
      gtk_container_add (GTK_CONTAINER (widget), combo_box);
 
401
      gtk_widget_show (combo_box);
 
402
    }
 
403
  else
 
404
    {
 
405
      widget = combo_box;
 
406
    }
 
407
 
 
408
  set_param_spec (G_OBJECT (combo_box), widget, param_spec);
 
409
 
 
410
  connect_notify (config, property_name,
 
411
                  G_CALLBACK (gimp_prop_int_combo_box_notify),
 
412
                  combo_box);
 
413
 
 
414
  return widget;
 
415
}
 
416
 
 
417
static void
 
418
gimp_prop_int_combo_box_callback (GtkWidget *widget,
 
419
                                  GObject   *config)
 
420
{
 
421
  GParamSpec  *param_spec;
 
422
  gint         value;
 
423
 
 
424
  param_spec = get_param_spec (G_OBJECT (widget));
 
425
  if (! param_spec)
 
426
    return;
 
427
 
 
428
  if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value))
 
429
    {
 
430
      g_object_set (config,
 
431
                    param_spec->name, value,
 
432
                    NULL);
 
433
    }
 
434
}
 
435
 
 
436
static void
 
437
gimp_prop_int_combo_box_notify (GObject    *config,
 
438
                                GParamSpec *param_spec,
 
439
                                GtkWidget  *combo_box)
 
440
{
 
441
  gint value;
 
442
 
 
443
  g_object_get (config,
 
444
                param_spec->name, &value,
 
445
                NULL);
 
446
 
 
447
  g_signal_handlers_block_by_func (combo_box,
 
448
                                   gimp_prop_int_combo_box_callback,
 
449
                                   config);
 
450
 
 
451
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo_box), value);
 
452
 
 
453
  g_signal_handlers_unblock_by_func (combo_box,
 
454
                                     gimp_prop_int_combo_box_callback,
 
455
                                     config);
 
456
}
 
457
 
 
458
 
 
459
/************************/
 
460
/*  boolean combo box   */
 
461
/************************/
 
462
 
 
463
static void   gimp_prop_boolean_combo_box_callback (GtkWidget   *widget,
 
464
                                                    GObject     *config);
 
465
static void   gimp_prop_boolean_combo_box_notify   (GObject     *config,
 
466
                                                    GParamSpec  *param_spec,
 
467
                                                    GtkWidget   *widget);
 
468
 
 
469
 
 
470
GtkWidget *
 
471
gimp_prop_boolean_combo_box_new (GObject     *config,
 
472
                                 const gchar *property_name,
 
473
                                 const gchar *true_text,
 
474
                                 const gchar *false_text)
 
475
{
 
476
  GParamSpec *param_spec;
 
477
  GtkWidget  *combo_box;
 
478
  GtkWidget  *widget;
 
479
  gboolean    value;
 
480
 
 
481
  param_spec = check_param_spec (config, property_name,
 
482
                                 G_TYPE_PARAM_BOOLEAN, G_STRFUNC);
 
483
  if (! param_spec)
 
484
    return NULL;
 
485
 
 
486
  g_object_get (config,
 
487
                property_name, &value,
 
488
                NULL);
 
489
 
 
490
  combo_box = gtk_combo_box_new_text ();
 
491
 
 
492
  gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), true_text);
 
493
  gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), false_text);
 
494
 
 
495
  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), value ? 0 : 1);
 
496
 
 
497
  g_signal_connect (combo_box, "changed",
 
498
                    G_CALLBACK (gimp_prop_boolean_combo_box_callback),
 
499
                    config);
 
500
 
 
501
  /*  can't set a tooltip on a combo_box  */
 
502
  if (g_param_spec_get_blurb (param_spec))
 
503
    {
 
504
      widget = gtk_event_box_new ();
 
505
      gtk_container_add (GTK_CONTAINER (widget), combo_box);
 
506
      gtk_widget_show (combo_box);
 
507
    }
 
508
  else
 
509
    {
 
510
      widget = combo_box;
 
511
    }
 
512
 
 
513
  set_param_spec (G_OBJECT (combo_box), widget, param_spec);
 
514
 
 
515
  connect_notify (config, property_name,
 
516
                  G_CALLBACK (gimp_prop_boolean_combo_box_notify),
 
517
                  combo_box);
 
518
 
 
519
  return widget;
 
520
}
 
521
 
 
522
static void
 
523
gimp_prop_boolean_combo_box_callback (GtkWidget *widget,
 
524
                                      GObject   *config)
 
525
{
 
526
  GParamSpec  *param_spec;
 
527
  gint         value;
 
528
 
 
529
  param_spec = get_param_spec (G_OBJECT (widget));
 
530
  if (! param_spec)
 
531
    return;
 
532
 
 
533
  value = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
 
534
 
 
535
  g_object_set (config,
 
536
                param_spec->name, value ? FALSE : TRUE,
 
537
                NULL);
 
538
}
 
539
 
 
540
static void
 
541
gimp_prop_boolean_combo_box_notify (GObject    *config,
 
542
                                    GParamSpec *param_spec,
 
543
                                    GtkWidget  *combo_box)
 
544
{
 
545
  gint value;
 
546
 
 
547
  g_object_get (config,
 
548
                param_spec->name, &value,
 
549
                NULL);
 
550
 
 
551
  g_signal_handlers_block_by_func (combo_box,
 
552
                                   gimp_prop_boolean_combo_box_callback,
 
553
                                   config);
 
554
 
 
555
  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), value ? 0 : 1);
 
556
 
 
557
  g_signal_handlers_unblock_by_func (combo_box,
 
558
                                     gimp_prop_boolean_combo_box_callback,
 
559
                                     config);
 
560
}
 
561
 
 
562
 
 
563
/****************/
 
564
/*  paint menu  */
 
565
/****************/
 
566
 
 
567
static void   gimp_prop_paint_menu_callback (GtkWidget   *widget,
 
568
                                             GObject     *config);
 
569
static void   gimp_prop_paint_menu_notify   (GObject     *config,
 
570
                                             GParamSpec  *param_spec,
 
571
                                             GtkWidget   *menu);
 
572
 
 
573
GtkWidget *
 
574
gimp_prop_paint_mode_menu_new (GObject     *config,
 
575
                               const gchar *property_name,
 
576
                               gboolean     with_behind_mode)
 
577
{
 
578
  GParamSpec *param_spec;
 
579
  GtkWidget  *menu;
 
580
  gint        value;
 
581
 
 
582
  param_spec = check_param_spec (config, property_name,
 
583
                                 G_TYPE_PARAM_ENUM, G_STRFUNC);
 
584
  if (! param_spec)
 
585
    return NULL;
 
586
 
 
587
  g_object_get (config,
 
588
                property_name, &value,
 
589
                NULL);
 
590
 
 
591
  menu = gimp_paint_mode_menu_new (G_CALLBACK (gimp_prop_paint_menu_callback),
 
592
                                   config,
 
593
                                   with_behind_mode,
 
594
                                   value);
 
595
 
 
596
  set_param_spec (G_OBJECT (menu), menu, param_spec);
 
597
 
 
598
  connect_notify (config, property_name,
 
599
                  G_CALLBACK (gimp_prop_paint_menu_notify),
 
600
                  menu);
 
601
 
 
602
  return menu;
 
603
}
 
604
 
 
605
static void
 
606
gimp_prop_paint_menu_callback (GtkWidget *widget,
 
607
                               GObject   *config)
 
608
{
 
609
  if (GTK_IS_MENU (widget->parent))
 
610
    {
 
611
      GtkWidget *menu;
 
612
 
 
613
      menu = gtk_menu_get_attach_widget (GTK_MENU (widget->parent));
 
614
 
 
615
      if (menu)
 
616
        {
 
617
          GParamSpec *param_spec;
 
618
          gint        value;
 
619
 
 
620
          param_spec = get_param_spec (G_OBJECT (menu));
 
621
          if (! param_spec)
 
622
            return;
 
623
 
 
624
          value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
 
625
                                                      "gimp-item-data"));
 
626
 
 
627
          g_object_set (config,
 
628
                        param_spec->name, value,
 
629
                        NULL);
 
630
        }
 
631
    }
 
632
}
 
633
 
 
634
static void
 
635
gimp_prop_paint_menu_notify (GObject    *config,
 
636
                             GParamSpec *param_spec,
 
637
                             GtkWidget  *menu)
 
638
{
 
639
  gint value;
 
640
 
 
641
  g_object_get (config,
 
642
                param_spec->name, &value,
 
643
                NULL);
 
644
 
 
645
  gimp_paint_mode_menu_set_history (GTK_OPTION_MENU (menu), value);
 
646
}
 
647
 
 
648
 
 
649
/*****************/
 
650
/*  radio boxes  */
 
651
/*****************/
 
652
 
 
653
static void  gimp_prop_radio_button_callback (GtkWidget   *widget,
 
654
                                              GObject     *config);
 
655
static void  gimp_prop_radio_button_notify   (GObject     *config,
 
656
                                              GParamSpec  *param_spec,
 
657
                                              GtkWidget   *button);
 
658
 
 
659
 
 
660
GtkWidget *
 
661
gimp_prop_enum_radio_frame_new (GObject     *config,
 
662
                                const gchar *property_name,
 
663
                                const gchar *label,
 
664
                                gint         minimum,
 
665
                                gint         maximum)
 
666
{
 
667
  GParamSpec *param_spec;
 
668
  GtkWidget  *frame;
 
669
  GtkWidget  *button;
 
670
  gint        value;
 
671
 
 
672
  param_spec = check_param_spec (config, property_name,
 
673
                                 G_TYPE_PARAM_ENUM, G_STRFUNC);
 
674
  if (! param_spec)
 
675
    return NULL;
 
676
 
 
677
  g_object_get (config,
 
678
                property_name, &value,
 
679
                NULL);
 
680
 
 
681
  if (minimum != maximum)
 
682
    {
 
683
      frame = gimp_enum_radio_frame_new_with_range (param_spec->value_type,
 
684
                                                    minimum, maximum,
 
685
                                                    gtk_label_new (label),
 
686
                                                    G_CALLBACK (gimp_prop_radio_button_callback),
 
687
                                                    config,
 
688
                                                    &button);
 
689
    }
 
690
  else
 
691
    {
 
692
      frame = gimp_enum_radio_frame_new (param_spec->value_type,
 
693
                                         gtk_label_new (label),
 
694
                                         G_CALLBACK (gimp_prop_radio_button_callback),
 
695
                                         config,
 
696
                                         &button);
 
697
    }
 
698
 
 
699
  gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), value);
 
700
 
 
701
  set_radio_spec (G_OBJECT (button), param_spec);
 
702
 
 
703
  connect_notify (config, property_name,
 
704
                  G_CALLBACK (gimp_prop_radio_button_notify),
 
705
                  button);
 
706
 
 
707
  g_object_set_data (G_OBJECT (frame), "radio-button", button);
 
708
 
 
709
  return frame;
 
710
}
 
711
 
 
712
GtkWidget *
 
713
gimp_prop_enum_radio_box_new (GObject     *config,
 
714
                              const gchar *property_name,
 
715
                              gint         minimum,
 
716
                              gint         maximum)
 
717
{
 
718
  GParamSpec *param_spec;
 
719
  GtkWidget  *vbox;
 
720
  GtkWidget  *button;
 
721
  gint        value;
 
722
 
 
723
  param_spec = check_param_spec (config, property_name,
 
724
                                 G_TYPE_PARAM_ENUM, G_STRFUNC);
 
725
  if (! param_spec)
 
726
    return NULL;
 
727
 
 
728
  g_object_get (config,
 
729
                property_name, &value,
 
730
                NULL);
 
731
 
 
732
  if (minimum != maximum)
 
733
    {
 
734
      vbox = gimp_enum_radio_box_new_with_range (param_spec->value_type,
 
735
                                                 minimum, maximum,
 
736
                                                 G_CALLBACK (gimp_prop_radio_button_callback),
 
737
                                                 config,
 
738
                                                 &button);
 
739
    }
 
740
  else
 
741
    {
 
742
      vbox = gimp_enum_radio_box_new (param_spec->value_type,
 
743
                                      G_CALLBACK (gimp_prop_radio_button_callback),
 
744
                                      config,
 
745
                                      &button);
 
746
    }
 
747
 
 
748
  gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), value);
 
749
 
 
750
  set_radio_spec (G_OBJECT (button), param_spec);
 
751
 
 
752
  connect_notify (config, property_name,
 
753
                  G_CALLBACK (gimp_prop_radio_button_notify),
 
754
                  button);
 
755
 
 
756
  g_object_set_data (G_OBJECT (vbox), "radio-button", button);
 
757
 
 
758
  return vbox;
 
759
}
 
760
 
 
761
GtkWidget *
 
762
gimp_prop_boolean_radio_frame_new (GObject     *config,
 
763
                                   const gchar *property_name,
 
764
                                   const gchar *title,
 
765
                                   const gchar *true_text,
 
766
                                   const gchar *false_text)
 
767
{
 
768
  GParamSpec *param_spec;
 
769
  GtkWidget  *frame;
 
770
  GtkWidget  *button;
 
771
  gboolean    value;
 
772
 
 
773
  param_spec = check_param_spec (config, property_name,
 
774
                                 G_TYPE_PARAM_BOOLEAN, G_STRFUNC);
 
775
  if (! param_spec)
 
776
    return NULL;
 
777
 
 
778
  g_object_get (config,
 
779
                property_name, &value,
 
780
                NULL);
 
781
 
 
782
  frame =
 
783
    gimp_int_radio_group_new (TRUE, title,
 
784
                              G_CALLBACK (gimp_prop_radio_button_callback),
 
785
                              config, value,
 
786
 
 
787
                              false_text, FALSE, &button,
 
788
                              true_text,  TRUE,  NULL,
 
789
 
 
790
                              NULL);
 
791
 
 
792
  set_radio_spec (G_OBJECT (button), param_spec);
 
793
 
 
794
  connect_notify (config, property_name,
 
795
                  G_CALLBACK (gimp_prop_radio_button_notify),
 
796
                  button);
 
797
 
 
798
  g_object_set_data (G_OBJECT (frame), "radio-button", button);
 
799
 
 
800
  return frame;
 
801
}
 
802
 
 
803
GtkWidget *
 
804
gimp_prop_enum_stock_box_new (GObject     *config,
 
805
                              const gchar *property_name,
 
806
                              const gchar *stock_prefix,
 
807
                              gint         minimum,
 
808
                              gint         maximum)
 
809
{
 
810
  GParamSpec *param_spec;
 
811
  GtkWidget  *box;
 
812
  GtkWidget  *button;
 
813
  gint        value;
 
814
 
 
815
  param_spec = check_param_spec (config, property_name,
 
816
                                 G_TYPE_PARAM_ENUM, G_STRFUNC);
 
817
  if (! param_spec)
 
818
    return NULL;
 
819
 
 
820
  g_object_get (config,
 
821
                property_name, &value,
 
822
                NULL);
 
823
 
 
824
  if (minimum != maximum)
 
825
    {
 
826
      box = gimp_enum_stock_box_new_with_range (param_spec->value_type,
 
827
                                                minimum, maximum,
 
828
                                                stock_prefix,
 
829
                                                GTK_ICON_SIZE_MENU,
 
830
                                                G_CALLBACK (gimp_prop_radio_button_callback),
 
831
                                                config,
 
832
                                                &button);
 
833
    }
 
834
  else
 
835
    {
 
836
      box = gimp_enum_stock_box_new (param_spec->value_type,
 
837
                                     stock_prefix,
 
838
                                     GTK_ICON_SIZE_MENU,
 
839
                                     G_CALLBACK (gimp_prop_radio_button_callback),
 
840
                                     config,
 
841
                                     &button);
 
842
    }
 
843
 
 
844
  gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), value);
 
845
 
 
846
  set_radio_spec (G_OBJECT (button), param_spec);
 
847
 
 
848
  connect_notify (config, property_name,
 
849
                  G_CALLBACK (gimp_prop_radio_button_notify),
 
850
                  button);
 
851
 
 
852
  return box;
 
853
}
 
854
 
 
855
static void
 
856
gimp_prop_radio_button_callback (GtkWidget *widget,
 
857
                                 GObject   *config)
 
858
{
 
859
  if (GTK_TOGGLE_BUTTON (widget)->active)
 
860
    {
 
861
      GParamSpec *param_spec;
 
862
      gint        value;
 
863
 
 
864
      param_spec = get_param_spec (G_OBJECT (widget));
 
865
      if (! param_spec)
 
866
        return;
 
867
 
 
868
      value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
 
869
                                                  "gimp-item-data"));
 
870
 
 
871
      g_object_set (config,
 
872
                    param_spec->name, value,
 
873
                    NULL);
 
874
    }
 
875
}
 
876
 
 
877
static void
 
878
gimp_prop_radio_button_notify (GObject    *config,
 
879
                               GParamSpec *param_spec,
 
880
                               GtkWidget  *button)
 
881
{
 
882
  gint value;
 
883
 
 
884
  g_object_get (config,
 
885
                param_spec->name, &value,
 
886
                NULL);
 
887
 
 
888
  gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), value);
 
889
}
 
890
 
 
891
 
 
892
/*****************/
 
893
/*  adjustments  */
 
894
/*****************/
 
895
 
 
896
static void   gimp_prop_adjustment_callback (GtkAdjustment *adjustment,
 
897
                                             GObject       *config);
 
898
static void   gimp_prop_adjustment_notify   (GObject       *config,
 
899
                                             GParamSpec    *param_spec,
 
900
                                             GtkAdjustment *adjustment);
 
901
 
 
902
GtkWidget *
 
903
gimp_prop_spin_button_new (GObject     *config,
 
904
                           const gchar *property_name,
 
905
                           gdouble      step_increment,
 
906
                           gdouble      page_increment,
 
907
                           gint         digits)
 
908
{
 
909
  GParamSpec *param_spec;
 
910
  GtkWidget  *spinbutton;
 
911
  GtkObject  *adjustment;
 
912
  gdouble     value;
 
913
  gdouble     lower;
 
914
  gdouble     upper;
 
915
 
 
916
  param_spec = find_param_spec (config, property_name, G_STRFUNC);
 
917
  if (! param_spec)
 
918
    return NULL;
 
919
 
 
920
  if (! get_numeric_values (config,
 
921
                            param_spec, &value, &lower, &upper, G_STRFUNC))
 
922
    return NULL;
 
923
 
 
924
  if (! G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
925
    digits = 0;
 
926
 
 
927
  spinbutton = gimp_spin_button_new (&adjustment,
 
928
                                     value, lower, upper,
 
929
                                     step_increment, page_increment,
 
930
                                     0.0, 1.0, digits);
 
931
 
 
932
  set_param_spec (G_OBJECT (adjustment), spinbutton, param_spec);
 
933
 
 
934
  g_signal_connect (adjustment, "value_changed",
 
935
                    G_CALLBACK (gimp_prop_adjustment_callback),
 
936
                    config);
 
937
 
 
938
  connect_notify (config, property_name,
 
939
                  G_CALLBACK (gimp_prop_adjustment_notify),
 
940
                  adjustment);
 
941
 
 
942
  return spinbutton;
 
943
}
 
944
 
 
945
GtkObject *
 
946
gimp_prop_scale_entry_new (GObject     *config,
 
947
                           const gchar *property_name,
 
948
                           GtkTable    *table,
 
949
                           gint         column,
 
950
                           gint         row,
 
951
                           const gchar *label,
 
952
                           gdouble      step_increment,
 
953
                           gdouble      page_increment,
 
954
                           gint         digits,
 
955
                           gboolean     restrict_scale,
 
956
                           gdouble      restricted_lower,
 
957
                           gdouble      restricted_upper)
 
958
{
 
959
  GParamSpec  *param_spec;
 
960
  GtkObject   *adjustment;
 
961
  const gchar *tooltip;
 
962
  gdouble      value;
 
963
  gdouble      lower;
 
964
  gdouble      upper;
 
965
 
 
966
  param_spec = find_param_spec (config, property_name, G_STRFUNC);
 
967
  if (! param_spec)
 
968
    return NULL;
 
969
 
 
970
  if (! get_numeric_values (config,
 
971
                            param_spec, &value, &lower, &upper, G_STRFUNC))
 
972
    return NULL;
 
973
 
 
974
  tooltip = gettext (g_param_spec_get_blurb (param_spec));
 
975
 
 
976
  if (! restrict_scale)
 
977
    {
 
978
      adjustment = gimp_scale_entry_new (table, column, row,
 
979
                                         label, -1, -1,
 
980
                                         value, lower, upper,
 
981
                                         step_increment, page_increment, digits,
 
982
                                         TRUE, 0.0, 0.0,
 
983
                                         tooltip,
 
984
                                         NULL);
 
985
    }
 
986
  else
 
987
    {
 
988
      adjustment = gimp_scale_entry_new (table, column, row,
 
989
                                         label, -1, -1,
 
990
                                         value,
 
991
                                         restricted_lower,
 
992
                                         restricted_upper,
 
993
                                         step_increment, page_increment, digits,
 
994
                                         FALSE, lower, upper,
 
995
                                         tooltip,
 
996
                                         NULL);
 
997
    }
 
998
 
 
999
  set_param_spec (G_OBJECT (adjustment), NULL,  param_spec);
 
1000
 
 
1001
  g_signal_connect (adjustment, "value_changed",
 
1002
                    G_CALLBACK (gimp_prop_adjustment_callback),
 
1003
                    config);
 
1004
 
 
1005
  connect_notify (config, property_name,
 
1006
                  G_CALLBACK (gimp_prop_adjustment_notify),
 
1007
                  adjustment);
 
1008
 
 
1009
  return adjustment;
 
1010
}
 
1011
 
 
1012
GtkObject *
 
1013
gimp_prop_opacity_entry_new (GObject     *config,
 
1014
                             const gchar *property_name,
 
1015
                             GtkTable    *table,
 
1016
                             gint         column,
 
1017
                             gint         row,
 
1018
                             const gchar *label)
 
1019
{
 
1020
  GParamSpec  *param_spec;
 
1021
  GtkObject   *adjustment;
 
1022
  const gchar *tooltip;
 
1023
  gdouble      value;
 
1024
  gdouble      lower;
 
1025
  gdouble      upper;
 
1026
 
 
1027
  param_spec = check_param_spec (config, property_name,
 
1028
                                 G_TYPE_PARAM_DOUBLE, G_STRFUNC);
 
1029
  if (! param_spec)
 
1030
    return NULL;
 
1031
 
 
1032
  g_object_get (config, property_name, &value, NULL);
 
1033
 
 
1034
  tooltip = gettext (g_param_spec_get_blurb (param_spec));
 
1035
 
 
1036
  value *= 100.0;
 
1037
  lower = G_PARAM_SPEC_DOUBLE (param_spec)->minimum * 100.0;
 
1038
  upper = G_PARAM_SPEC_DOUBLE (param_spec)->maximum * 100.0;
 
1039
 
 
1040
  adjustment = gimp_scale_entry_new (table, column, row,
 
1041
                                     label, -1, -1,
 
1042
                                     value, lower, upper,
 
1043
                                     1.0, 10.0, 1,
 
1044
                                     TRUE, 0.0, 0.0,
 
1045
                                     tooltip,
 
1046
                                     NULL);
 
1047
 
 
1048
  set_param_spec (G_OBJECT (adjustment), NULL,  param_spec);
 
1049
  g_object_set_data (G_OBJECT (adjustment),
 
1050
                     "opacity-scale", GINT_TO_POINTER (TRUE));
 
1051
 
 
1052
  g_signal_connect (adjustment, "value_changed",
 
1053
                    G_CALLBACK (gimp_prop_adjustment_callback),
 
1054
                    config);
 
1055
 
 
1056
  connect_notify (config, property_name,
 
1057
                  G_CALLBACK (gimp_prop_adjustment_notify),
 
1058
                  adjustment);
 
1059
 
 
1060
  return adjustment;
 
1061
}
 
1062
 
 
1063
 
 
1064
static void
 
1065
gimp_prop_adjustment_callback (GtkAdjustment *adjustment,
 
1066
                               GObject       *config)
 
1067
{
 
1068
  GParamSpec *param_spec;
 
1069
 
 
1070
  param_spec = get_param_spec (G_OBJECT (adjustment));
 
1071
  if (! param_spec)
 
1072
    return;
 
1073
 
 
1074
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
1075
    {
 
1076
      g_object_set (config,
 
1077
                    param_spec->name, (gint) adjustment->value,
 
1078
                    NULL);
 
1079
    }
 
1080
  else if (G_IS_PARAM_SPEC_UINT (param_spec))
 
1081
    {
 
1082
      g_object_set (config,
 
1083
                    param_spec->name, (guint) adjustment->value,
 
1084
                    NULL);
 
1085
    }
 
1086
  else if (G_IS_PARAM_SPEC_LONG (param_spec))
 
1087
    {
 
1088
      g_object_set (config,
 
1089
                    param_spec->name, (glong) adjustment->value,
 
1090
                    NULL);
 
1091
    }
 
1092
  else if (G_IS_PARAM_SPEC_ULONG (param_spec))
 
1093
    {
 
1094
      g_object_set (config,
 
1095
                    param_spec->name, (gulong) adjustment->value,
 
1096
                    NULL);
 
1097
    }
 
1098
  else if (G_IS_PARAM_SPEC_INT64 (param_spec))
 
1099
    {
 
1100
      g_object_set (config,
 
1101
                    param_spec->name, (gint64) adjustment->value,
 
1102
                    NULL);
 
1103
    }
 
1104
  else if (G_IS_PARAM_SPEC_UINT64 (param_spec))
 
1105
    {
 
1106
      g_object_set (config,
 
1107
                    param_spec->name, (guint64) adjustment->value,
 
1108
                    NULL);
 
1109
    }
 
1110
  else if (G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
1111
    {
 
1112
      gdouble value;
 
1113
 
 
1114
      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (adjustment),
 
1115
                                              "opacity-scale")))
 
1116
        value = adjustment->value / 100.0;
 
1117
      else
 
1118
        value = adjustment->value;
 
1119
 
 
1120
      g_object_set (config, param_spec->name, value, NULL);
 
1121
    }
 
1122
}
 
1123
 
 
1124
static void
 
1125
gimp_prop_adjustment_notify (GObject       *config,
 
1126
                             GParamSpec    *param_spec,
 
1127
                             GtkAdjustment *adjustment)
 
1128
{
 
1129
  gdouble value;
 
1130
 
 
1131
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
1132
    {
 
1133
      gint int_value;
 
1134
 
 
1135
      g_object_get (config, param_spec->name, &int_value, NULL);
 
1136
 
 
1137
      value = int_value;
 
1138
    }
 
1139
  else if (G_IS_PARAM_SPEC_UINT (param_spec))
 
1140
    {
 
1141
      guint uint_value;
 
1142
 
 
1143
      g_object_get (config, param_spec->name, &uint_value, NULL);
 
1144
 
 
1145
      value = uint_value;
 
1146
    }
 
1147
  else if (G_IS_PARAM_SPEC_LONG (param_spec))
 
1148
    {
 
1149
      glong long_value;
 
1150
 
 
1151
      g_object_get (config, param_spec->name, &long_value, NULL);
 
1152
 
 
1153
      value = long_value;
 
1154
    }
 
1155
  else if (G_IS_PARAM_SPEC_ULONG (param_spec))
 
1156
    {
 
1157
      gulong ulong_value;
 
1158
 
 
1159
      g_object_get (config, param_spec->name, &ulong_value, NULL);
 
1160
 
 
1161
      value = ulong_value;
 
1162
    }
 
1163
  else if (G_IS_PARAM_SPEC_INT64 (param_spec))
 
1164
    {
 
1165
      gint64 int64_value;
 
1166
 
 
1167
      g_object_get (config, param_spec->name, &int64_value, NULL);
 
1168
 
 
1169
      value = int64_value;
 
1170
    }
 
1171
  else if (G_IS_PARAM_SPEC_UINT64 (param_spec))
 
1172
    {
 
1173
      guint64 uint64_value;
 
1174
 
 
1175
      g_object_get (config, param_spec->name, &uint64_value, NULL);
 
1176
 
 
1177
#if defined _MSC_VER && (_MSC_VER < 1300)
 
1178
      value = (gint64) uint64_value;
 
1179
#else
 
1180
      value = uint64_value;
 
1181
#endif
 
1182
    }
 
1183
  else if (G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
1184
    {
 
1185
      g_object_get (config, param_spec->name, &value, NULL);
 
1186
 
 
1187
      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (adjustment),
 
1188
                                              "opacity-scale")))
 
1189
        value *= 100.0;
 
1190
    }
 
1191
  else
 
1192
    {
 
1193
      g_warning ("%s: unhandled param spec of type %s",
 
1194
                 G_STRFUNC, G_PARAM_SPEC_TYPE_NAME (param_spec));
 
1195
      return;
 
1196
    }
 
1197
 
 
1198
  if (adjustment->value != value)
 
1199
    {
 
1200
      g_signal_handlers_block_by_func (adjustment,
 
1201
                                       gimp_prop_adjustment_callback,
 
1202
                                       config);
 
1203
 
 
1204
      gtk_adjustment_set_value (adjustment, value);
 
1205
 
 
1206
      g_signal_handlers_unblock_by_func (adjustment,
 
1207
                                         gimp_prop_adjustment_callback,
 
1208
                                         config);
 
1209
    }
 
1210
}
 
1211
 
 
1212
 
 
1213
/*************/
 
1214
/*  memsize  */
 
1215
/*************/
 
1216
 
 
1217
static void   gimp_prop_memsize_callback (GimpMemsizeEntry *entry,
 
1218
                                          GObject          *config);
 
1219
static void   gimp_prop_memsize_notify   (GObject          *config,
 
1220
                                          GParamSpec       *param_spec,
 
1221
                                          GimpMemsizeEntry *entry);
 
1222
 
 
1223
GtkWidget *
 
1224
gimp_prop_memsize_entry_new (GObject     *config,
 
1225
                             const gchar *property_name)
 
1226
{
 
1227
  GParamSpec       *param_spec;
 
1228
  GParamSpecUInt64 *uint64_spec;
 
1229
  GtkWidget        *entry;
 
1230
  guint64           value;
 
1231
 
 
1232
  param_spec = check_param_spec (config, property_name,
 
1233
                                 GIMP_TYPE_PARAM_MEMSIZE, G_STRFUNC);
 
1234
  if (! param_spec)
 
1235
    return NULL;
 
1236
 
 
1237
  g_object_get (config,
 
1238
                property_name, &value,
 
1239
                NULL);
 
1240
 
 
1241
  uint64_spec = G_PARAM_SPEC_UINT64 (param_spec);
 
1242
 
 
1243
  g_return_val_if_fail (uint64_spec->minimum <= GIMP_MAX_MEMSIZE, NULL);
 
1244
  g_return_val_if_fail (uint64_spec->maximum <= GIMP_MAX_MEMSIZE, NULL);
 
1245
 
 
1246
  entry = gimp_memsize_entry_new (value,
 
1247
                                  uint64_spec->minimum,
 
1248
                                  uint64_spec->maximum);
 
1249
 
 
1250
  set_param_spec (G_OBJECT (entry),
 
1251
                  GIMP_MEMSIZE_ENTRY (entry)->spinbutton,
 
1252
                  param_spec);
 
1253
 
 
1254
  g_signal_connect (entry, "value_changed",
 
1255
                    G_CALLBACK (gimp_prop_memsize_callback),
 
1256
                    config);
 
1257
 
 
1258
  connect_notify (config, property_name,
 
1259
                  G_CALLBACK (gimp_prop_memsize_notify),
 
1260
                  entry);
 
1261
 
 
1262
  return entry;
 
1263
}
 
1264
 
 
1265
 
 
1266
static void
 
1267
gimp_prop_memsize_callback (GimpMemsizeEntry *entry,
 
1268
                            GObject          *config)
 
1269
{
 
1270
  GParamSpec *param_spec;
 
1271
 
 
1272
  param_spec = get_param_spec (G_OBJECT (entry));
 
1273
  if (! param_spec)
 
1274
    return;
 
1275
 
 
1276
  g_return_if_fail (G_IS_PARAM_SPEC_UINT64 (param_spec));
 
1277
 
 
1278
  g_object_set (config,
 
1279
                param_spec->name, gimp_memsize_entry_get_value (entry),
 
1280
                NULL);
 
1281
}
 
1282
 
 
1283
static void
 
1284
gimp_prop_memsize_notify (GObject          *config,
 
1285
                          GParamSpec       *param_spec,
 
1286
                          GimpMemsizeEntry *entry)
 
1287
{
 
1288
  guint64  value;
 
1289
 
 
1290
  g_return_if_fail (G_IS_PARAM_SPEC_UINT64 (param_spec));
 
1291
 
 
1292
  g_object_get (config,
 
1293
                param_spec->name, &value,
 
1294
                NULL);
 
1295
 
 
1296
  if (entry->value != value)
 
1297
    {
 
1298
      g_signal_handlers_block_by_func (entry,
 
1299
                                       gimp_prop_memsize_callback,
 
1300
                                       config);
 
1301
 
 
1302
      gimp_memsize_entry_set_value (entry, value);
 
1303
 
 
1304
      g_signal_handlers_unblock_by_func (entry,
 
1305
                                         gimp_prop_memsize_callback,
 
1306
                                         config);
 
1307
    }
 
1308
}
 
1309
 
 
1310
 
 
1311
/***********/
 
1312
/*  label  */
 
1313
/***********/
 
1314
 
 
1315
static void   gimp_prop_label_notify (GObject    *config,
 
1316
                                      GParamSpec *param_spec,
 
1317
                                      GtkWidget  *label);
 
1318
 
 
1319
GtkWidget *
 
1320
gimp_prop_label_new (GObject     *config,
 
1321
                     const gchar *property_name)
 
1322
{
 
1323
  GParamSpec *param_spec;
 
1324
  GtkWidget  *label;
 
1325
  gchar      *value;
 
1326
 
 
1327
  param_spec = check_param_spec (config, property_name,
 
1328
                                 G_TYPE_PARAM_STRING, G_STRFUNC);
 
1329
  if (! param_spec)
 
1330
    return NULL;
 
1331
 
 
1332
  g_object_get (config,
 
1333
                property_name, &value,
 
1334
                NULL);
 
1335
 
 
1336
  label = gtk_label_new (value ? value : "");
 
1337
  g_free (value);
 
1338
 
 
1339
  set_param_spec (G_OBJECT (label), label, param_spec);
 
1340
 
 
1341
  connect_notify (config, property_name,
 
1342
                  G_CALLBACK (gimp_prop_label_notify),
 
1343
                  label);
 
1344
 
 
1345
  return label;
 
1346
}
 
1347
 
 
1348
static void
 
1349
gimp_prop_label_notify (GObject    *config,
 
1350
                        GParamSpec *param_spec,
 
1351
                        GtkWidget  *label)
 
1352
{
 
1353
  gchar *value;
 
1354
 
 
1355
  g_object_get (config,
 
1356
                param_spec->name, &value,
 
1357
                NULL);
 
1358
 
 
1359
  gtk_label_set_text (GTK_LABEL (label), value ? value : "");
 
1360
 
 
1361
  g_free (value);
 
1362
}
 
1363
 
 
1364
 
 
1365
/***********/
 
1366
/*  entry  */
 
1367
/***********/
 
1368
 
 
1369
static void   gimp_prop_entry_callback (GtkWidget  *entry,
 
1370
                                        GObject    *config);
 
1371
static void   gimp_prop_entry_notify   (GObject    *config,
 
1372
                                        GParamSpec *param_spec,
 
1373
                                        GtkWidget  *entry);
 
1374
 
 
1375
GtkWidget *
 
1376
gimp_prop_entry_new (GObject     *config,
 
1377
                     const gchar *property_name,
 
1378
                     gint         max_len)
 
1379
{
 
1380
  GParamSpec *param_spec;
 
1381
  GtkWidget  *entry;
 
1382
  gchar      *value;
 
1383
 
 
1384
  param_spec = check_param_spec (config, property_name,
 
1385
                                 G_TYPE_PARAM_STRING, G_STRFUNC);
 
1386
  if (! param_spec)
 
1387
    return NULL;
 
1388
 
 
1389
  g_object_get (config,
 
1390
                property_name, &value,
 
1391
                NULL);
 
1392
 
 
1393
  entry = gtk_entry_new ();
 
1394
  gtk_entry_set_text (GTK_ENTRY (entry), value);
 
1395
 
 
1396
  g_free (value);
 
1397
 
 
1398
  if (max_len > 0)
 
1399
    gtk_entry_set_max_length (GTK_ENTRY (entry), max_len);
 
1400
 
 
1401
  set_param_spec (G_OBJECT (entry), entry, param_spec);
 
1402
 
 
1403
  g_signal_connect (entry, "changed",
 
1404
                    G_CALLBACK (gimp_prop_entry_callback),
 
1405
                    config);
 
1406
 
 
1407
  connect_notify (config, property_name,
 
1408
                  G_CALLBACK (gimp_prop_entry_notify),
 
1409
                  entry);
 
1410
 
 
1411
  return entry;
 
1412
}
 
1413
 
 
1414
static void
 
1415
gimp_prop_entry_callback (GtkWidget *entry,
 
1416
                          GObject   *config)
 
1417
{
 
1418
  GParamSpec  *param_spec;
 
1419
  const gchar *text;
 
1420
 
 
1421
  param_spec = get_param_spec (G_OBJECT (entry));
 
1422
  if (! param_spec)
 
1423
    return;
 
1424
 
 
1425
  text = gtk_entry_get_text (GTK_ENTRY (entry));
 
1426
 
 
1427
  g_signal_handlers_block_by_func (config,
 
1428
                                   gimp_prop_entry_notify,
 
1429
                                   entry);
 
1430
 
 
1431
  g_object_set (config,
 
1432
                param_spec->name, text,
 
1433
                NULL);
 
1434
 
 
1435
  g_signal_handlers_unblock_by_func (config,
 
1436
                                     gimp_prop_entry_notify,
 
1437
                                     entry);
 
1438
}
 
1439
 
 
1440
static void
 
1441
gimp_prop_entry_notify (GObject    *config,
 
1442
                        GParamSpec *param_spec,
 
1443
                        GtkWidget  *entry)
 
1444
{
 
1445
  gchar *value;
 
1446
 
 
1447
  g_object_get (config,
 
1448
                param_spec->name, &value,
 
1449
                NULL);
 
1450
 
 
1451
  g_signal_handlers_block_by_func (entry,
 
1452
                                   gimp_prop_entry_callback,
 
1453
                                   config);
 
1454
 
 
1455
  gtk_entry_set_text (GTK_ENTRY (entry), value);
 
1456
 
 
1457
  g_signal_handlers_unblock_by_func (entry,
 
1458
                                     gimp_prop_entry_callback,
 
1459
                                     config);
 
1460
 
 
1461
  g_free (value);
 
1462
}
 
1463
 
 
1464
 
 
1465
/*****************/
 
1466
/*  text buffer  */
 
1467
/*****************/
 
1468
 
 
1469
static void   gimp_prop_text_buffer_callback (GtkTextBuffer *text_buffer,
 
1470
                                              GObject       *config);
 
1471
static void   gimp_prop_text_buffer_notify   (GObject       *config,
 
1472
                                              GParamSpec    *param_spec,
 
1473
                                              GtkTextBuffer *text_buffer);
 
1474
 
 
1475
GtkTextBuffer *
 
1476
gimp_prop_text_buffer_new (GObject     *config,
 
1477
                           const gchar *property_name,
 
1478
                           gint         max_len)
 
1479
{
 
1480
  GParamSpec    *param_spec;
 
1481
  GtkTextBuffer *text_buffer;
 
1482
  gchar         *value;
 
1483
 
 
1484
  param_spec = check_param_spec (config, property_name,
 
1485
                                 G_TYPE_PARAM_STRING, G_STRFUNC);
 
1486
  if (! param_spec)
 
1487
    return NULL;
 
1488
 
 
1489
  g_object_get (config,
 
1490
                property_name, &value,
 
1491
                NULL);
 
1492
 
 
1493
  text_buffer = gtk_text_buffer_new (NULL);
 
1494
  gtk_text_buffer_set_text (text_buffer, value ? value : "", -1);
 
1495
 
 
1496
  g_free (value);
 
1497
 
 
1498
  if (max_len > 0)
 
1499
    g_object_set_data (G_OBJECT (text_buffer), "max-len",
 
1500
                       GINT_TO_POINTER (max_len));
 
1501
 
 
1502
  set_param_spec (G_OBJECT (text_buffer), NULL, param_spec);
 
1503
 
 
1504
  g_signal_connect (text_buffer, "changed",
 
1505
                    G_CALLBACK (gimp_prop_text_buffer_callback),
 
1506
                    config);
 
1507
 
 
1508
  connect_notify (config, property_name,
 
1509
                  G_CALLBACK (gimp_prop_text_buffer_notify),
 
1510
                  text_buffer);
 
1511
 
 
1512
  return text_buffer;
 
1513
}
 
1514
 
 
1515
static void
 
1516
gimp_prop_text_buffer_callback (GtkTextBuffer *text_buffer,
 
1517
                                GObject       *config)
 
1518
{
 
1519
  GParamSpec  *param_spec;
 
1520
  GtkTextIter  start_iter;
 
1521
  GtkTextIter  end_iter;
 
1522
  gchar       *text;
 
1523
  gint         max_len;
 
1524
 
 
1525
  param_spec = get_param_spec (G_OBJECT (text_buffer));
 
1526
  if (! param_spec)
 
1527
    return;
 
1528
 
 
1529
  gtk_text_buffer_get_bounds (text_buffer, &start_iter, &end_iter);
 
1530
  text = gtk_text_buffer_get_text (text_buffer, &start_iter, &end_iter, FALSE);
 
1531
 
 
1532
  max_len = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (text_buffer),
 
1533
                                                "max-length"));
 
1534
 
 
1535
  if (max_len > 0 && strlen (text) > max_len)
 
1536
    {
 
1537
      g_message (_("This text input field is limited to %d characters."),
 
1538
                 max_len);
 
1539
 
 
1540
      gtk_text_buffer_get_iter_at_offset (text_buffer, &start_iter,
 
1541
                                          max_len - 1);
 
1542
      gtk_text_buffer_get_end_iter (text_buffer, &end_iter);
 
1543
 
 
1544
      /*  this calls us recursivaly, but in the else branch  */
 
1545
      gtk_text_buffer_delete (text_buffer, &start_iter, &end_iter);
 
1546
    }
 
1547
  else
 
1548
    {
 
1549
      g_signal_handlers_block_by_func (config,
 
1550
                                       gimp_prop_text_buffer_notify,
 
1551
                                       text_buffer);
 
1552
 
 
1553
      g_object_set (config,
 
1554
                    param_spec->name, text,
 
1555
                    NULL);
 
1556
 
 
1557
      g_signal_handlers_unblock_by_func (config,
 
1558
                                         gimp_prop_text_buffer_notify,
 
1559
                                         text_buffer);
 
1560
    }
 
1561
 
 
1562
  g_free (text);
 
1563
}
 
1564
 
 
1565
static void
 
1566
gimp_prop_text_buffer_notify (GObject       *config,
 
1567
                              GParamSpec    *param_spec,
 
1568
                              GtkTextBuffer *text_buffer)
 
1569
{
 
1570
  gchar *value;
 
1571
 
 
1572
  g_object_get (config,
 
1573
                param_spec->name, &value,
 
1574
                NULL);
 
1575
 
 
1576
  g_signal_handlers_block_by_func (text_buffer,
 
1577
                                   gimp_prop_text_buffer_callback,
 
1578
                                   config);
 
1579
 
 
1580
  gtk_text_buffer_set_text (text_buffer, value ? value : "", -1);
 
1581
 
 
1582
  g_signal_handlers_unblock_by_func (text_buffer,
 
1583
                                     gimp_prop_text_buffer_callback,
 
1584
                                     config);
 
1585
 
 
1586
  g_free (value);
 
1587
}
 
1588
 
 
1589
 
 
1590
/****************/
 
1591
/*  file entry  */
 
1592
/****************/
 
1593
 
 
1594
 
 
1595
static void   gimp_prop_file_entry_callback (GimpFileEntry *entry,
 
1596
                                             GObject       *config);
 
1597
static void   gimp_prop_file_entry_notify   (GObject       *config,
 
1598
                                             GParamSpec    *param_spec,
 
1599
                                             GimpFileEntry *entry);
 
1600
 
 
1601
GtkWidget *
 
1602
gimp_prop_file_entry_new (GObject     *config,
 
1603
                          const gchar *property_name,
 
1604
                          const gchar *filesel_title,
 
1605
                          gboolean     dir_only,
 
1606
                          gboolean     check_valid)
 
1607
{
 
1608
  GParamSpec *param_spec;
 
1609
  GtkWidget  *entry;
 
1610
  gchar      *filename;
 
1611
  gchar      *value;
 
1612
 
 
1613
  param_spec = check_param_spec (config, property_name,
 
1614
                                 GIMP_TYPE_PARAM_PATH, G_STRFUNC);
 
1615
  if (! param_spec)
 
1616
    return NULL;
 
1617
 
 
1618
  g_object_get (config,
 
1619
                property_name, &value,
 
1620
                NULL);
 
1621
 
 
1622
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
1623
  g_free (value);
 
1624
 
 
1625
  entry = gimp_file_entry_new (filesel_title, filename, dir_only, check_valid);
 
1626
  g_free (filename);
 
1627
 
 
1628
  set_param_spec (G_OBJECT (entry),
 
1629
                  GIMP_FILE_ENTRY (entry)->entry,
 
1630
                  param_spec);
 
1631
 
 
1632
  g_signal_connect (entry, "filename_changed",
 
1633
                    G_CALLBACK (gimp_prop_file_entry_callback),
 
1634
                    config);
 
1635
 
 
1636
  connect_notify (config, property_name,
 
1637
                  G_CALLBACK (gimp_prop_file_entry_notify),
 
1638
                  entry);
 
1639
 
 
1640
  return entry;
 
1641
}
 
1642
 
 
1643
static void
 
1644
gimp_prop_file_entry_callback (GimpFileEntry *entry,
 
1645
                               GObject       *config)
 
1646
{
 
1647
  GParamSpec *param_spec;
 
1648
  gchar      *value;
 
1649
  gchar      *utf8;
 
1650
 
 
1651
  param_spec = get_param_spec (G_OBJECT (entry));
 
1652
  if (! param_spec)
 
1653
    return;
 
1654
 
 
1655
  value = gimp_file_entry_get_filename (entry);
 
1656
  utf8 = g_filename_to_utf8 (value, -1, NULL, NULL, NULL);
 
1657
  g_free (value);
 
1658
 
 
1659
  g_signal_handlers_block_by_func (config,
 
1660
                                   gimp_prop_file_entry_notify,
 
1661
                                   entry);
 
1662
 
 
1663
  g_object_set (config,
 
1664
                param_spec->name, utf8,
 
1665
                NULL);
 
1666
 
 
1667
  g_signal_handlers_block_by_func (config,
 
1668
                                   gimp_prop_file_entry_notify,
 
1669
                                   entry);
 
1670
 
 
1671
  g_free (utf8);
 
1672
}
 
1673
 
 
1674
static void
 
1675
gimp_prop_file_entry_notify (GObject       *config,
 
1676
                             GParamSpec    *param_spec,
 
1677
                             GimpFileEntry *entry)
 
1678
{
 
1679
  gchar *value;
 
1680
  gchar *filename;
 
1681
 
 
1682
  g_object_get (config,
 
1683
                param_spec->name, &value,
 
1684
                NULL);
 
1685
 
 
1686
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
1687
  g_free (value);
 
1688
 
 
1689
  g_signal_handlers_block_by_func (entry,
 
1690
                                   gimp_prop_file_entry_callback,
 
1691
                                   config);
 
1692
 
 
1693
  gimp_file_entry_set_filename (entry, filename);
 
1694
 
 
1695
  g_signal_handlers_unblock_by_func (entry,
 
1696
                                     gimp_prop_file_entry_callback,
 
1697
                                     config);
 
1698
 
 
1699
  g_free (filename);
 
1700
}
 
1701
 
 
1702
 
 
1703
/*****************/
 
1704
/*  path editor  */
 
1705
/*****************/
 
1706
 
 
1707
static void   gimp_prop_path_editor_path_callback     (GimpPathEditor *editor,
 
1708
                                                       GObject        *config);
 
1709
static void   gimp_prop_path_editor_writable_callback (GimpPathEditor *editor,
 
1710
                                                       GObject        *config);
 
1711
static void   gimp_prop_path_editor_path_notify       (GObject        *config,
 
1712
                                                       GParamSpec     *param_spec,
 
1713
                                                       GimpPathEditor *editor);
 
1714
static void   gimp_prop_path_editor_writable_notify   (GObject        *config,
 
1715
                                                       GParamSpec     *param_spec,
 
1716
                                                       GimpPathEditor *editor);
 
1717
 
 
1718
GtkWidget *
 
1719
gimp_prop_path_editor_new (GObject     *config,
 
1720
                           const gchar *path_property_name,
 
1721
                           const gchar *writable_property_name,
 
1722
                           const gchar *filesel_title)
 
1723
{
 
1724
  GParamSpec *path_param_spec;
 
1725
  GParamSpec *writable_param_spec = NULL;
 
1726
  GtkWidget  *editor;
 
1727
  gchar      *value;
 
1728
  gchar      *filename;
 
1729
 
 
1730
  path_param_spec = check_param_spec (config, path_property_name,
 
1731
                                      GIMP_TYPE_PARAM_PATH, G_STRFUNC);
 
1732
  if (! path_param_spec)
 
1733
    return NULL;
 
1734
 
 
1735
  if (writable_property_name)
 
1736
    {
 
1737
      writable_param_spec = check_param_spec (config, writable_property_name,
 
1738
                                              GIMP_TYPE_PARAM_PATH, G_STRFUNC);
 
1739
      if (! writable_param_spec)
 
1740
        return NULL;
 
1741
    }
 
1742
 
 
1743
  g_object_get (config,
 
1744
                path_property_name, &value,
 
1745
                NULL);
 
1746
 
 
1747
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
1748
  g_free (value);
 
1749
 
 
1750
  editor = gimp_path_editor_new (filesel_title, filename);
 
1751
  g_free (filename);
 
1752
 
 
1753
  if (writable_property_name)
 
1754
    {
 
1755
      g_object_get (config,
 
1756
                    writable_property_name, &value,
 
1757
                    NULL);
 
1758
 
 
1759
      filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
1760
      g_free (value);
 
1761
 
 
1762
      gimp_path_editor_set_writable_path (GIMP_PATH_EDITOR (editor), filename);
 
1763
      g_free (filename);
 
1764
    }
 
1765
 
 
1766
  g_object_set_data (G_OBJECT (editor), "gimp-config-param-spec-path",
 
1767
                     path_param_spec);
 
1768
 
 
1769
  g_signal_connect (editor, "path_changed",
 
1770
                    G_CALLBACK (gimp_prop_path_editor_path_callback),
 
1771
                    config);
 
1772
 
 
1773
  connect_notify (config, path_property_name,
 
1774
                  G_CALLBACK (gimp_prop_path_editor_path_notify),
 
1775
                  editor);
 
1776
 
 
1777
  if (writable_property_name)
 
1778
    {
 
1779
      g_object_set_data (G_OBJECT (editor), "gimp-config-param-spec-writable",
 
1780
                         writable_param_spec);
 
1781
 
 
1782
      g_signal_connect (editor, "writable_changed",
 
1783
                        G_CALLBACK (gimp_prop_path_editor_writable_callback),
 
1784
                        config);
 
1785
 
 
1786
      connect_notify (config, writable_property_name,
 
1787
                      G_CALLBACK (gimp_prop_path_editor_writable_notify),
 
1788
                      editor);
 
1789
    }
 
1790
 
 
1791
  return editor;
 
1792
}
 
1793
 
 
1794
static void
 
1795
gimp_prop_path_editor_path_callback (GimpPathEditor *editor,
 
1796
                                     GObject        *config)
 
1797
{
 
1798
  GParamSpec *path_param_spec;
 
1799
  GParamSpec *writable_param_spec;
 
1800
  gchar      *value;
 
1801
  gchar      *utf8;
 
1802
 
 
1803
  path_param_spec     = g_object_get_data (G_OBJECT (editor),
 
1804
                                           "gimp-config-param-spec-path");
 
1805
  writable_param_spec = g_object_get_data (G_OBJECT (editor),
 
1806
                                           "gimp-config-param-spec-writable");
 
1807
  if (! path_param_spec)
 
1808
    return;
 
1809
 
 
1810
  value = gimp_path_editor_get_path (editor);
 
1811
  utf8 = g_filename_to_utf8 (value, -1, NULL, NULL, NULL);
 
1812
  g_free (value);
 
1813
 
 
1814
  g_signal_handlers_block_by_func (config,
 
1815
                                   gimp_prop_path_editor_path_notify,
 
1816
                                   editor);
 
1817
 
 
1818
  g_object_set (config,
 
1819
                path_param_spec->name, utf8,
 
1820
                NULL);
 
1821
 
 
1822
  g_signal_handlers_unblock_by_func (config,
 
1823
                                     gimp_prop_path_editor_path_notify,
 
1824
                                     editor);
 
1825
 
 
1826
  g_free (utf8);
 
1827
 
 
1828
  if (writable_param_spec)
 
1829
    {
 
1830
      value = gimp_path_editor_get_writable_path (editor);
 
1831
      utf8 = g_filename_to_utf8 (value, -1, NULL, NULL, NULL);
 
1832
      g_free (value);
 
1833
 
 
1834
      g_signal_handlers_block_by_func (config,
 
1835
                                       gimp_prop_path_editor_writable_notify,
 
1836
                                       editor);
 
1837
 
 
1838
      g_object_set (config,
 
1839
                    writable_param_spec->name, utf8,
 
1840
                    NULL);
 
1841
 
 
1842
      g_signal_handlers_unblock_by_func (config,
 
1843
                                         gimp_prop_path_editor_writable_notify,
 
1844
                                         editor);
 
1845
 
 
1846
      g_free (utf8);
 
1847
    }
 
1848
}
 
1849
 
 
1850
static void
 
1851
gimp_prop_path_editor_writable_callback (GimpPathEditor *editor,
 
1852
                                         GObject        *config)
 
1853
{
 
1854
  GParamSpec *param_spec;
 
1855
  gchar      *value;
 
1856
  gchar      *utf8;
 
1857
 
 
1858
  param_spec = g_object_get_data (G_OBJECT (editor),
 
1859
                                  "gimp-config-param-spec-writable");
 
1860
  if (! param_spec)
 
1861
    return;
 
1862
 
 
1863
  value = gimp_path_editor_get_writable_path (editor);
 
1864
  utf8 = g_filename_to_utf8 (value, -1, NULL, NULL, NULL);
 
1865
  g_free (value);
 
1866
 
 
1867
  g_signal_handlers_block_by_func (config,
 
1868
                                   gimp_prop_path_editor_writable_notify,
 
1869
                                   editor);
 
1870
 
 
1871
  g_object_set (config,
 
1872
                param_spec->name, utf8,
 
1873
                NULL);
 
1874
 
 
1875
  g_signal_handlers_unblock_by_func (config,
 
1876
                                     gimp_prop_path_editor_writable_notify,
 
1877
                                     editor);
 
1878
 
 
1879
  g_free (utf8);
 
1880
}
 
1881
 
 
1882
static void
 
1883
gimp_prop_path_editor_path_notify (GObject        *config,
 
1884
                                   GParamSpec     *param_spec,
 
1885
                                   GimpPathEditor *editor)
 
1886
{
 
1887
  gchar *value;
 
1888
  gchar *filename;
 
1889
 
 
1890
  g_object_get (config,
 
1891
                param_spec->name, &value,
 
1892
                NULL);
 
1893
 
 
1894
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
1895
  g_free (value);
 
1896
 
 
1897
  g_signal_handlers_block_by_func (editor,
 
1898
                                   gimp_prop_path_editor_path_callback,
 
1899
                                   config);
 
1900
 
 
1901
  gimp_path_editor_set_path (editor, filename);
 
1902
 
 
1903
  g_signal_handlers_unblock_by_func (editor,
 
1904
                                     gimp_prop_path_editor_path_callback,
 
1905
                                     config);
 
1906
 
 
1907
  g_free (filename);
 
1908
}
 
1909
 
 
1910
static void
 
1911
gimp_prop_path_editor_writable_notify (GObject        *config,
 
1912
                                       GParamSpec     *param_spec,
 
1913
                                       GimpPathEditor *editor)
 
1914
{
 
1915
  gchar *value;
 
1916
  gchar *filename;
 
1917
 
 
1918
  g_object_get (config,
 
1919
                param_spec->name, &value,
 
1920
                NULL);
 
1921
 
 
1922
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
1923
  g_free (value);
 
1924
 
 
1925
  g_signal_handlers_block_by_func (editor,
 
1926
                                   gimp_prop_path_editor_writable_callback,
 
1927
                                   config);
 
1928
 
 
1929
  gimp_path_editor_set_writable_path (editor, filename);
 
1930
 
 
1931
  g_signal_handlers_unblock_by_func (editor,
 
1932
                                     gimp_prop_path_editor_writable_callback,
 
1933
                                     config);
 
1934
 
 
1935
  g_free (filename);
 
1936
}
 
1937
 
 
1938
 
 
1939
/***************/
 
1940
/*  sizeentry  */
 
1941
/***************/
 
1942
 
 
1943
static void   gimp_prop_size_entry_callback    (GimpSizeEntry *sizeentry,
 
1944
                                                GObject       *config);
 
1945
static void   gimp_prop_size_entry_notify      (GObject       *config,
 
1946
                                                GParamSpec    *param_spec,
 
1947
                                                GimpSizeEntry *sizeentry);
 
1948
static void   gimp_prop_size_entry_notify_unit (GObject       *config,
 
1949
                                                GParamSpec    *param_spec,
 
1950
                                                GimpSizeEntry *sizeentry);
 
1951
 
 
1952
 
 
1953
GtkWidget *
 
1954
gimp_prop_size_entry_new (GObject                   *config,
 
1955
                          const gchar               *property_name,
 
1956
                          const gchar               *unit_property_name,
 
1957
                          const gchar               *unit_format,
 
1958
                          GimpSizeEntryUpdatePolicy  update_policy,
 
1959
                          gdouble                    resolution)
 
1960
{
 
1961
  GtkWidget  *sizeentry;
 
1962
  GParamSpec *param_spec;
 
1963
  GParamSpec *unit_param_spec;
 
1964
  gboolean    show_pixels;
 
1965
  gdouble     value;
 
1966
  gdouble     lower;
 
1967
  gdouble     upper;
 
1968
  GimpUnit    unit_value;
 
1969
 
 
1970
  param_spec = find_param_spec (config, property_name, G_STRFUNC);
 
1971
  if (! param_spec)
 
1972
    return NULL;
 
1973
 
 
1974
  if (! get_numeric_values (config,
 
1975
                            param_spec, &value, &lower, &upper, G_STRFUNC))
 
1976
    return NULL;
 
1977
 
 
1978
  if (unit_property_name)
 
1979
    {
 
1980
      GValue value = { 0 };
 
1981
 
 
1982
      unit_param_spec = check_param_spec (config, unit_property_name,
 
1983
                                          GIMP_TYPE_PARAM_UNIT, G_STRFUNC);
 
1984
      if (! unit_param_spec)
 
1985
        return NULL;
 
1986
 
 
1987
      g_value_init (&value, unit_param_spec->value_type);
 
1988
      g_value_set_int (&value, GIMP_UNIT_PIXEL);
 
1989
      show_pixels =
 
1990
        (g_param_value_validate (unit_param_spec, &value) == FALSE);
 
1991
      g_value_unset (&value);
 
1992
 
 
1993
      g_object_get (config,
 
1994
                    unit_property_name, &unit_value,
 
1995
                    NULL);
 
1996
    }
 
1997
  else
 
1998
    {
 
1999
      unit_param_spec = NULL;
 
2000
      unit_value      = GIMP_UNIT_INCH;
 
2001
      show_pixels     = FALSE;
 
2002
    }
 
2003
 
 
2004
  sizeentry = gimp_size_entry_new (1, unit_value, unit_format,
 
2005
                                   TRUE, FALSE, FALSE,
 
2006
                                   ceil (log (upper) / log (10) + 2),
 
2007
                                   update_policy);
 
2008
  gtk_table_set_col_spacing (GTK_TABLE (sizeentry), 1, 4);
 
2009
 
 
2010
  set_param_spec (NULL,
 
2011
                  gimp_size_entry_get_help_widget (GIMP_SIZE_ENTRY (sizeentry),
 
2012
                                                   0),
 
2013
                  param_spec);
 
2014
 
 
2015
  if (unit_param_spec)
 
2016
    set_param_spec (NULL,
 
2017
                    GIMP_SIZE_ENTRY (sizeentry)->unitmenu, unit_param_spec);
 
2018
 
 
2019
  gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), unit_value);
 
2020
 
 
2021
  if (update_policy == GIMP_SIZE_ENTRY_UPDATE_SIZE)
 
2022
    gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0,
 
2023
                                    resolution, FALSE);
 
2024
 
 
2025
  gimp_size_entry_set_value_boundaries (GIMP_SIZE_ENTRY (sizeentry), 0,
 
2026
                                        lower, upper);
 
2027
 
 
2028
  gimp_size_entry_set_value (GIMP_SIZE_ENTRY (sizeentry), 0, value);
 
2029
 
 
2030
  g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec",
 
2031
                     param_spec);
 
2032
 
 
2033
  g_signal_connect (sizeentry, "value_changed",
 
2034
                    G_CALLBACK (gimp_prop_size_entry_callback),
 
2035
                    config);
 
2036
 
 
2037
  connect_notify (config, property_name,
 
2038
                  G_CALLBACK (gimp_prop_size_entry_notify),
 
2039
                  sizeentry);
 
2040
 
 
2041
  if (unit_property_name)
 
2042
    {
 
2043
      g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-unit",
 
2044
                         unit_param_spec);
 
2045
 
 
2046
      g_signal_connect (sizeentry, "unit_changed",
 
2047
                        G_CALLBACK (gimp_prop_size_entry_callback),
 
2048
                        config);
 
2049
 
 
2050
      connect_notify (config, unit_property_name,
 
2051
                      G_CALLBACK (gimp_prop_size_entry_notify_unit),
 
2052
                      sizeentry);
 
2053
    }
 
2054
 
 
2055
  return sizeentry;
 
2056
}
 
2057
 
 
2058
static void
 
2059
gimp_prop_size_entry_callback (GimpSizeEntry *sizeentry,
 
2060
                               GObject       *config)
 
2061
{
 
2062
  GParamSpec *param_spec;
 
2063
  GParamSpec *unit_param_spec;
 
2064
  gdouble     value;
 
2065
  GimpUnit    unit_value;
 
2066
 
 
2067
  param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
2068
                                  "gimp-config-param-spec");
 
2069
  if (! param_spec)
 
2070
    return;
 
2071
 
 
2072
  unit_param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
2073
                                       "gimp-config-param-spec-unit");
 
2074
 
 
2075
  value      = gimp_size_entry_get_value (sizeentry, 0);
 
2076
  unit_value = gimp_size_entry_get_unit (sizeentry);
 
2077
 
 
2078
  if (unit_param_spec)
 
2079
    {
 
2080
      GimpUnit  old_unit;
 
2081
 
 
2082
      g_object_get (config,
 
2083
                    unit_param_spec->name, &old_unit,
 
2084
                    NULL);
 
2085
 
 
2086
      if (unit_value == old_unit)
 
2087
        unit_param_spec = NULL;
 
2088
    }
 
2089
 
 
2090
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
2091
    {
 
2092
      g_object_set (config,
 
2093
                    param_spec->name, ROUND (value),
 
2094
 
 
2095
                    unit_param_spec ?
 
2096
                    unit_param_spec->name : NULL, unit_value,
 
2097
 
 
2098
                    NULL);
 
2099
    }
 
2100
  else if (G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
2101
    {
 
2102
      g_object_set (config,
 
2103
                    param_spec->name, value,
 
2104
 
 
2105
                    unit_param_spec ?
 
2106
                    unit_param_spec->name : NULL, unit_value,
 
2107
 
 
2108
                    NULL);
 
2109
    }
 
2110
}
 
2111
 
 
2112
static void
 
2113
gimp_prop_size_entry_notify (GObject       *config,
 
2114
                             GParamSpec    *param_spec,
 
2115
                             GimpSizeEntry *sizeentry)
 
2116
{
 
2117
  gdouble value;
 
2118
 
 
2119
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
2120
    {
 
2121
      gint int_value;
 
2122
 
 
2123
      g_object_get (config,
 
2124
                    param_spec->name, &int_value,
 
2125
                    NULL);
 
2126
 
 
2127
      value = int_value;
 
2128
    }
 
2129
  else
 
2130
    {
 
2131
      g_object_get (config,
 
2132
                    param_spec->name, &value,
 
2133
                    NULL);
 
2134
    }
 
2135
 
 
2136
  if (value != gimp_size_entry_get_value (sizeentry, 0))
 
2137
    {
 
2138
      g_signal_handlers_block_by_func (sizeentry,
 
2139
                                       gimp_prop_size_entry_callback,
 
2140
                                       config);
 
2141
 
 
2142
      gimp_size_entry_set_value (sizeentry, 0, value);
 
2143
 
 
2144
      g_signal_handlers_unblock_by_func (sizeentry,
 
2145
                                         gimp_prop_size_entry_callback,
 
2146
                                         config);
 
2147
    }
 
2148
}
 
2149
 
 
2150
static void
 
2151
gimp_prop_size_entry_notify_unit (GObject       *config,
 
2152
                                  GParamSpec    *param_spec,
 
2153
                                  GimpSizeEntry *sizeentry)
 
2154
{
 
2155
  GimpUnit value;
 
2156
 
 
2157
  g_object_get (config,
 
2158
                param_spec->name, &value,
 
2159
                NULL);
 
2160
 
 
2161
  if (value != gimp_size_entry_get_unit (sizeentry))
 
2162
    {
 
2163
      g_signal_handlers_block_by_func (sizeentry,
 
2164
                                       gimp_prop_size_entry_callback,
 
2165
                                       config);
 
2166
 
 
2167
      gimp_size_entry_set_unit (sizeentry, value);
 
2168
 
 
2169
      g_signal_handlers_unblock_by_func (sizeentry,
 
2170
                                         gimp_prop_size_entry_callback,
 
2171
                                         config);
 
2172
    }
 
2173
}
 
2174
 
 
2175
 
 
2176
/*****************/
 
2177
/*  coordinates  */
 
2178
/*****************/
 
2179
 
 
2180
static void   gimp_prop_coordinates_callback    (GimpSizeEntry *sizeentry,
 
2181
                                                 GObject       *config);
 
2182
static void   gimp_prop_coordinates_notify_x    (GObject       *config,
 
2183
                                                 GParamSpec    *param_spec,
 
2184
                                                 GimpSizeEntry *sizeentry);
 
2185
static void   gimp_prop_coordinates_notify_y    (GObject       *config,
 
2186
                                                 GParamSpec    *param_spec,
 
2187
                                                 GimpSizeEntry *sizeentry);
 
2188
static void   gimp_prop_coordinates_notify_unit (GObject       *config,
 
2189
                                                 GParamSpec    *param_spec,
 
2190
                                                 GimpSizeEntry *sizeentry);
 
2191
 
 
2192
 
 
2193
GtkWidget *
 
2194
gimp_prop_coordinates_new (GObject                   *config,
 
2195
                           const gchar               *x_property_name,
 
2196
                           const gchar               *y_property_name,
 
2197
                           const gchar               *unit_property_name,
 
2198
                           const gchar               *unit_format,
 
2199
                           GimpSizeEntryUpdatePolicy  update_policy,
 
2200
                           gdouble                    xresolution,
 
2201
                           gdouble                    yresolution,
 
2202
                           gboolean                   has_chainbutton)
 
2203
{
 
2204
  GtkWidget *sizeentry;
 
2205
  GtkWidget *chainbutton = NULL;
 
2206
 
 
2207
  sizeentry = gimp_size_entry_new (2, GIMP_UNIT_INCH, unit_format,
 
2208
                                   FALSE, FALSE, TRUE, 10,
 
2209
                                   update_policy);
 
2210
 
 
2211
  if (has_chainbutton)
 
2212
    {
 
2213
      chainbutton = gimp_chain_button_new (GIMP_CHAIN_BOTTOM);
 
2214
      gtk_table_attach_defaults (GTK_TABLE (sizeentry), chainbutton,
 
2215
                                 1, 3, 3, 4);
 
2216
      gtk_widget_show (chainbutton);
 
2217
    }
 
2218
 
 
2219
  if (! gimp_prop_coordinates_connect (config,
 
2220
                                       x_property_name,
 
2221
                                       y_property_name,
 
2222
                                       unit_property_name,
 
2223
                                       sizeentry,
 
2224
                                       chainbutton,
 
2225
                                       xresolution,
 
2226
                                       yresolution))
 
2227
    {
 
2228
      gtk_widget_destroy (sizeentry);
 
2229
      return NULL;
 
2230
    }
 
2231
 
 
2232
  return sizeentry;
 
2233
}
 
2234
 
 
2235
gboolean
 
2236
gimp_prop_coordinates_connect (GObject     *config,
 
2237
                               const gchar *x_property_name,
 
2238
                               const gchar *y_property_name,
 
2239
                               const gchar *unit_property_name,
 
2240
                               GtkWidget   *sizeentry,
 
2241
                               GtkWidget   *chainbutton,
 
2242
                               gdouble      xresolution,
 
2243
                               gdouble      yresolution)
 
2244
{
 
2245
  GParamSpec *x_param_spec;
 
2246
  GParamSpec *y_param_spec;
 
2247
  GParamSpec *unit_param_spec;
 
2248
  gdouble     x_value, x_lower, x_upper;
 
2249
  gdouble     y_value, y_lower, y_upper;
 
2250
  GimpUnit    unit_value;
 
2251
  gdouble    *old_x_value;
 
2252
  gdouble    *old_y_value;
 
2253
  GimpUnit   *old_unit_value;
 
2254
  gboolean    chain_checked;
 
2255
 
 
2256
  g_return_val_if_fail (GIMP_IS_SIZE_ENTRY (sizeentry), FALSE);
 
2257
  g_return_val_if_fail (GIMP_SIZE_ENTRY (sizeentry)->number_of_fields == 2,
 
2258
                        FALSE);
 
2259
  g_return_val_if_fail (chainbutton == NULL ||
 
2260
                        GIMP_IS_CHAIN_BUTTON (chainbutton), FALSE);
 
2261
 
 
2262
  x_param_spec = find_param_spec (config, x_property_name, G_STRFUNC);
 
2263
  if (! x_param_spec)
 
2264
    return FALSE;
 
2265
 
 
2266
  y_param_spec = find_param_spec (config, y_property_name, G_STRFUNC);
 
2267
  if (! y_param_spec)
 
2268
    return FALSE;
 
2269
 
 
2270
  if (! get_numeric_values (config, x_param_spec,
 
2271
                            &x_value, &x_lower, &x_upper, G_STRFUNC) ||
 
2272
      ! get_numeric_values (config, y_param_spec,
 
2273
                            &y_value, &y_lower, &y_upper, G_STRFUNC))
 
2274
    return FALSE;
 
2275
 
 
2276
  if (unit_property_name)
 
2277
    {
 
2278
      unit_param_spec = check_param_spec (config, unit_property_name,
 
2279
                                          GIMP_TYPE_PARAM_UNIT, G_STRFUNC);
 
2280
      if (! unit_param_spec)
 
2281
        return FALSE;
 
2282
 
 
2283
      g_object_get (config,
 
2284
                    unit_property_name, &unit_value,
 
2285
                    NULL);
 
2286
    }
 
2287
  else
 
2288
    {
 
2289
      unit_param_spec = NULL;
 
2290
      unit_value      = GIMP_UNIT_INCH;
 
2291
    }
 
2292
 
 
2293
  set_param_spec (NULL,
 
2294
                  gimp_size_entry_get_help_widget (GIMP_SIZE_ENTRY (sizeentry),
 
2295
                                                   0),
 
2296
                  x_param_spec);
 
2297
  set_param_spec (NULL,
 
2298
                  gimp_size_entry_get_help_widget (GIMP_SIZE_ENTRY (sizeentry),
 
2299
                                                   1),
 
2300
                  y_param_spec);
 
2301
 
 
2302
  if (unit_param_spec)
 
2303
    set_param_spec (NULL,
 
2304
                    GIMP_SIZE_ENTRY (sizeentry)->unitmenu, unit_param_spec);
 
2305
 
 
2306
  gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), unit_value);
 
2307
 
 
2308
  switch (GIMP_SIZE_ENTRY (sizeentry)->update_policy)
 
2309
    {
 
2310
    case GIMP_SIZE_ENTRY_UPDATE_SIZE:
 
2311
      gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0,
 
2312
                                      xresolution, FALSE);
 
2313
      gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 1,
 
2314
                                      yresolution, FALSE);
 
2315
      chain_checked = (ABS (x_value - y_value) < 1);
 
2316
      break;
 
2317
 
 
2318
    case GIMP_SIZE_ENTRY_UPDATE_RESOLUTION:
 
2319
      chain_checked = (ABS (x_value - y_value) < GIMP_MIN_RESOLUTION);
 
2320
      break;
 
2321
 
 
2322
    default:
 
2323
      chain_checked = (x_value == y_value);
 
2324
      break;
 
2325
    }
 
2326
 
 
2327
  gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 0,
 
2328
                                         x_lower, x_upper);
 
2329
  gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 1,
 
2330
                                         y_lower, y_upper);
 
2331
 
 
2332
  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 0, x_value);
 
2333
  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 1, y_value);
 
2334
 
 
2335
  g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-x",
 
2336
                     x_param_spec);
 
2337
  g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-y",
 
2338
                     y_param_spec);
 
2339
 
 
2340
  old_x_value  = g_new0 (gdouble, 1);
 
2341
  *old_x_value = x_value;
 
2342
  g_object_set_data_full (G_OBJECT (sizeentry), "old-x-value",
 
2343
                          old_x_value,
 
2344
                          (GDestroyNotify) g_free);
 
2345
 
 
2346
  old_y_value  = g_new0 (gdouble, 1);
 
2347
  *old_y_value = y_value;
 
2348
  g_object_set_data_full (G_OBJECT (sizeentry), "old-y-value",
 
2349
                          old_y_value,
 
2350
                          (GDestroyNotify) g_free);
 
2351
 
 
2352
  if (chainbutton)
 
2353
    {
 
2354
      if (chain_checked)
 
2355
        gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chainbutton), TRUE);
 
2356
 
 
2357
      g_object_set_data (G_OBJECT (sizeentry), "chainbutton", chainbutton);
 
2358
    }
 
2359
 
 
2360
  g_signal_connect (sizeentry, "value_changed",
 
2361
                    G_CALLBACK (gimp_prop_coordinates_callback),
 
2362
                    config);
 
2363
  g_signal_connect (sizeentry, "refval_changed",
 
2364
                    G_CALLBACK (gimp_prop_coordinates_callback),
 
2365
                    config);
 
2366
 
 
2367
  connect_notify (config, x_property_name,
 
2368
                  G_CALLBACK (gimp_prop_coordinates_notify_x),
 
2369
                  sizeentry);
 
2370
  connect_notify (config, y_property_name,
 
2371
                  G_CALLBACK (gimp_prop_coordinates_notify_y),
 
2372
                  sizeentry);
 
2373
 
 
2374
  if (unit_property_name)
 
2375
    {
 
2376
      g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-unit",
 
2377
                         unit_param_spec);
 
2378
 
 
2379
      old_unit_value  = g_new0 (GimpUnit, 1);
 
2380
      *old_unit_value = unit_value;
 
2381
      g_object_set_data_full (G_OBJECT (sizeentry), "old-unit-value",
 
2382
                              old_unit_value,
 
2383
                              (GDestroyNotify) g_free);
 
2384
 
 
2385
      g_signal_connect (sizeentry, "unit_changed",
 
2386
                        G_CALLBACK (gimp_prop_coordinates_callback),
 
2387
                        config);
 
2388
 
 
2389
      connect_notify (config, unit_property_name,
 
2390
                      G_CALLBACK (gimp_prop_coordinates_notify_unit),
 
2391
                      sizeentry);
 
2392
    }
 
2393
 
 
2394
  return TRUE;
 
2395
}
 
2396
 
 
2397
static void
 
2398
gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry,
 
2399
                                GObject       *config)
 
2400
{
 
2401
  GParamSpec *x_param_spec;
 
2402
  GParamSpec *y_param_spec;
 
2403
  GParamSpec *unit_param_spec;
 
2404
  gdouble     x_value;
 
2405
  gdouble     y_value;
 
2406
  GimpUnit    unit_value;
 
2407
  gdouble    *old_x_value;
 
2408
  gdouble    *old_y_value;
 
2409
  GimpUnit   *old_unit_value;
 
2410
  gboolean    backwards;
 
2411
 
 
2412
  x_param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
2413
                                    "gimp-config-param-spec-x");
 
2414
  y_param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
2415
                                    "gimp-config-param-spec-y");
 
2416
 
 
2417
  if (! x_param_spec || ! y_param_spec)
 
2418
    return;
 
2419
 
 
2420
  unit_param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
2421
                                       "gimp-config-param-spec-unit");
 
2422
 
 
2423
  x_value    = gimp_size_entry_get_refval (sizeentry, 0);
 
2424
  y_value    = gimp_size_entry_get_refval (sizeentry, 1);
 
2425
  unit_value = gimp_size_entry_get_unit (sizeentry);
 
2426
 
 
2427
  old_x_value    = g_object_get_data (G_OBJECT (sizeentry), "old-x-value");
 
2428
  old_y_value    = g_object_get_data (G_OBJECT (sizeentry), "old-y-value");
 
2429
  old_unit_value = g_object_get_data (G_OBJECT (sizeentry), "old-unit-value");
 
2430
 
 
2431
  if (! old_x_value || ! old_y_value || (unit_param_spec && ! old_unit_value))
 
2432
    return;
 
2433
 
 
2434
  /*
 
2435
   * FIXME: if the entry was created using gimp_coordinates_new, then
 
2436
   * the chain button is handled automatically and the following block
 
2437
   * of code is unnecessary (and, in fact, redundant).
 
2438
   */
 
2439
  if (x_value != y_value)
 
2440
    {
 
2441
      GtkWidget *chainbutton;
 
2442
 
 
2443
      chainbutton = g_object_get_data (G_OBJECT (sizeentry), "chainbutton");
 
2444
 
 
2445
      if (chainbutton &&
 
2446
          gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chainbutton)) &&
 
2447
          ! g_object_get_data (G_OBJECT (chainbutton), "constrains-ratio"))
 
2448
        {
 
2449
          if (x_value != *old_x_value)
 
2450
            y_value = x_value;
 
2451
          else if (y_value != *old_y_value)
 
2452
            x_value = y_value;
 
2453
        }
 
2454
    }
 
2455
 
 
2456
  backwards = (*old_x_value == x_value);
 
2457
 
 
2458
  if (*old_x_value == x_value &&
 
2459
      *old_y_value == y_value &&
 
2460
      (old_unit_value == NULL || *old_unit_value == unit_value))
 
2461
    return;
 
2462
 
 
2463
  *old_x_value = x_value;
 
2464
  *old_y_value = y_value;
 
2465
 
 
2466
  if (old_unit_value)
 
2467
    *old_unit_value = unit_value;
 
2468
 
 
2469
  if (unit_param_spec)
 
2470
    g_object_set (config,
 
2471
                  unit_param_spec->name, unit_value,
 
2472
                  NULL);
 
2473
 
 
2474
  if (G_IS_PARAM_SPEC_INT (x_param_spec) &&
 
2475
      G_IS_PARAM_SPEC_INT (y_param_spec))
 
2476
    {
 
2477
      if (backwards)
 
2478
        g_object_set (config,
 
2479
                      y_param_spec->name, ROUND (y_value),
 
2480
                      x_param_spec->name, ROUND (x_value),
 
2481
                      NULL);
 
2482
      else
 
2483
        g_object_set (config,
 
2484
                      x_param_spec->name, ROUND (x_value),
 
2485
                      y_param_spec->name, ROUND (y_value),
 
2486
                      NULL);
 
2487
 
 
2488
    }
 
2489
  else if (G_IS_PARAM_SPEC_DOUBLE (x_param_spec) &&
 
2490
           G_IS_PARAM_SPEC_DOUBLE (y_param_spec))
 
2491
    {
 
2492
      if (backwards)
 
2493
        g_object_set (config,
 
2494
                      y_param_spec->name, y_value,
 
2495
                      x_param_spec->name, x_value,
 
2496
                      NULL);
 
2497
      else
 
2498
        g_object_set (config,
 
2499
                      x_param_spec->name, x_value,
 
2500
                      y_param_spec->name, y_value,
 
2501
                      NULL);
 
2502
    }
 
2503
}
 
2504
 
 
2505
static void
 
2506
gimp_prop_coordinates_notify_x (GObject       *config,
 
2507
                                GParamSpec    *param_spec,
 
2508
                                GimpSizeEntry *sizeentry)
 
2509
{
 
2510
  gdouble value;
 
2511
 
 
2512
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
2513
    {
 
2514
      gint int_value;
 
2515
 
 
2516
      g_object_get (config,
 
2517
                    param_spec->name, &int_value,
 
2518
                    NULL);
 
2519
 
 
2520
      value = int_value;
 
2521
    }
 
2522
  else
 
2523
    {
 
2524
      g_object_get (config,
 
2525
                    param_spec->name, &value,
 
2526
                    NULL);
 
2527
    }
 
2528
 
 
2529
  if (value != gimp_size_entry_get_refval (sizeentry, 0))
 
2530
    {
 
2531
      g_signal_handlers_block_by_func (sizeentry,
 
2532
                                       gimp_prop_coordinates_callback,
 
2533
                                       config);
 
2534
 
 
2535
      gimp_size_entry_set_refval (sizeentry, 0, value);
 
2536
 
 
2537
      g_signal_handlers_unblock_by_func (sizeentry,
 
2538
                                         gimp_prop_coordinates_callback,
 
2539
                                         config);
 
2540
    }
 
2541
}
 
2542
 
 
2543
static void
 
2544
gimp_prop_coordinates_notify_y (GObject       *config,
 
2545
                                GParamSpec    *param_spec,
 
2546
                                GimpSizeEntry *sizeentry)
 
2547
{
 
2548
  gdouble value;
 
2549
 
 
2550
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
2551
    {
 
2552
      gint int_value;
 
2553
 
 
2554
      g_object_get (config,
 
2555
                    param_spec->name, &int_value,
 
2556
                    NULL);
 
2557
 
 
2558
      value = int_value;
 
2559
    }
 
2560
  else
 
2561
    {
 
2562
      g_object_get (config,
 
2563
                    param_spec->name, &value,
 
2564
                    NULL);
 
2565
    }
 
2566
 
 
2567
  if (value != gimp_size_entry_get_refval (sizeentry, 1))
 
2568
    {
 
2569
      g_signal_handlers_block_by_func (sizeentry,
 
2570
                                       gimp_prop_coordinates_callback,
 
2571
                                       config);
 
2572
 
 
2573
      gimp_size_entry_set_refval (sizeentry, 1, value);
 
2574
 
 
2575
      g_signal_handlers_unblock_by_func (sizeentry,
 
2576
                                         gimp_prop_coordinates_callback,
 
2577
                                         config);
 
2578
    }
 
2579
}
 
2580
 
 
2581
static void
 
2582
gimp_prop_coordinates_notify_unit (GObject       *config,
 
2583
                                   GParamSpec    *param_spec,
 
2584
                                   GimpSizeEntry *sizeentry)
 
2585
{
 
2586
  GimpUnit value;
 
2587
 
 
2588
  g_object_get (config,
 
2589
                param_spec->name, &value,
 
2590
                NULL);
 
2591
 
 
2592
  if (value != gimp_size_entry_get_unit (sizeentry))
 
2593
    {
 
2594
      g_signal_handlers_block_by_func (sizeentry,
 
2595
                                       gimp_prop_coordinates_callback,
 
2596
                                       config);
 
2597
 
 
2598
      gimp_size_entry_set_unit (sizeentry, value);
 
2599
 
 
2600
      g_signal_handlers_unblock_by_func (sizeentry,
 
2601
                                         gimp_prop_coordinates_callback,
 
2602
                                         config);
 
2603
    }
 
2604
}
 
2605
 
 
2606
 
 
2607
/****************/
 
2608
/*  color area  */
 
2609
/****************/
 
2610
 
 
2611
static void   gimp_prop_color_area_callback (GtkWidget  *widget,
 
2612
                                             GObject    *config);
 
2613
static void   gimp_prop_color_area_notify   (GObject    *config,
 
2614
                                             GParamSpec *param_spec,
 
2615
                                             GtkWidget  *area);
 
2616
 
 
2617
GtkWidget *
 
2618
gimp_prop_color_area_new (GObject           *config,
 
2619
                          const gchar       *property_name,
 
2620
                          gint               width,
 
2621
                          gint               height,
 
2622
                          GimpColorAreaType  type)
 
2623
{
 
2624
  GParamSpec *param_spec;
 
2625
  GtkWidget  *area;
 
2626
  GimpRGB    *value;
 
2627
 
 
2628
  param_spec = check_param_spec (config, property_name,
 
2629
                                 GIMP_TYPE_PARAM_RGB, G_STRFUNC);
 
2630
  if (! param_spec)
 
2631
    return NULL;
 
2632
 
 
2633
  g_object_get (config,
 
2634
                property_name, &value,
 
2635
                NULL);
 
2636
 
 
2637
  area = gimp_color_area_new (value, type,
 
2638
                              GDK_BUTTON1_MASK | GDK_BUTTON2_MASK);
 
2639
  gtk_widget_set_size_request (area, width, height);
 
2640
 
 
2641
  g_free (value);
 
2642
 
 
2643
  set_param_spec (G_OBJECT (area), area, param_spec);
 
2644
 
 
2645
  g_signal_connect (area, "color_changed",
 
2646
                    G_CALLBACK (gimp_prop_color_area_callback),
 
2647
                    config);
 
2648
 
 
2649
  connect_notify (config, property_name,
 
2650
                  G_CALLBACK (gimp_prop_color_area_notify),
 
2651
                  area);
 
2652
 
 
2653
  return area;
 
2654
}
 
2655
 
 
2656
static void
 
2657
gimp_prop_color_area_callback (GtkWidget *area,
 
2658
                               GObject   *config)
 
2659
{
 
2660
  GParamSpec *param_spec;
 
2661
  GimpRGB     value;
 
2662
 
 
2663
  param_spec = get_param_spec (G_OBJECT (area));
 
2664
  if (! param_spec)
 
2665
    return;
 
2666
 
 
2667
  gimp_color_area_get_color (GIMP_COLOR_AREA (area), &value);
 
2668
 
 
2669
  g_signal_handlers_block_by_func (config,
 
2670
                                   gimp_prop_color_area_notify,
 
2671
                                   area);
 
2672
 
 
2673
  g_object_set (config,
 
2674
                param_spec->name, &value,
 
2675
                NULL);
 
2676
 
 
2677
  g_signal_handlers_unblock_by_func (config,
 
2678
                                     gimp_prop_color_area_notify,
 
2679
                                     area);
 
2680
}
 
2681
 
 
2682
static void
 
2683
gimp_prop_color_area_notify (GObject    *config,
 
2684
                             GParamSpec *param_spec,
 
2685
                             GtkWidget  *area)
 
2686
{
 
2687
  GimpRGB *value;
 
2688
 
 
2689
  g_object_get (config,
 
2690
                param_spec->name, &value,
 
2691
                NULL);
 
2692
 
 
2693
  g_signal_handlers_block_by_func (area,
 
2694
                                   gimp_prop_color_area_callback,
 
2695
                                   config);
 
2696
 
 
2697
  gimp_color_area_set_color (GIMP_COLOR_AREA (area), value);
 
2698
 
 
2699
  g_free (value);
 
2700
 
 
2701
  g_signal_handlers_unblock_by_func (area,
 
2702
                                     gimp_prop_color_area_callback,
 
2703
                                     config);
 
2704
}
 
2705
 
 
2706
 
 
2707
/******************/
 
2708
/*  color button  */
 
2709
/******************/
 
2710
 
 
2711
static void   gimp_prop_color_button_callback (GtkWidget  *widget,
 
2712
                                               GObject    *config);
 
2713
static void   gimp_prop_color_button_notify   (GObject    *config,
 
2714
                                               GParamSpec *param_spec,
 
2715
                                               GtkWidget  *button);
 
2716
 
 
2717
GtkWidget *
 
2718
gimp_prop_color_button_new (GObject           *config,
 
2719
                            const gchar       *property_name,
 
2720
                            const gchar       *title,
 
2721
                            gint               width,
 
2722
                            gint               height,
 
2723
                            GimpColorAreaType  type)
 
2724
{
 
2725
  GParamSpec *param_spec;
 
2726
  GtkWidget  *button;
 
2727
  GimpRGB    *value;
 
2728
 
 
2729
  param_spec = check_param_spec (config, property_name,
 
2730
                                 GIMP_TYPE_PARAM_RGB, G_STRFUNC);
 
2731
  if (! param_spec)
 
2732
    return NULL;
 
2733
 
 
2734
  g_object_get (config,
 
2735
                property_name, &value,
 
2736
                NULL);
 
2737
 
 
2738
  button = gimp_color_panel_new (title, value, type, width, height);
 
2739
 
 
2740
  g_free (value);
 
2741
 
 
2742
  set_param_spec (G_OBJECT (button), button, param_spec);
 
2743
 
 
2744
  g_signal_connect (button, "color_changed",
 
2745
                    G_CALLBACK (gimp_prop_color_button_callback),
 
2746
                    config);
 
2747
 
 
2748
  connect_notify (config, property_name,
 
2749
                  G_CALLBACK (gimp_prop_color_button_notify),
 
2750
                  button);
 
2751
 
 
2752
  return button;
 
2753
}
 
2754
 
 
2755
static void
 
2756
gimp_prop_color_button_callback (GtkWidget *button,
 
2757
                                 GObject   *config)
 
2758
{
 
2759
  GParamSpec *param_spec;
 
2760
  GimpRGB     value;
 
2761
 
 
2762
  param_spec = get_param_spec (G_OBJECT (button));
 
2763
  if (! param_spec)
 
2764
    return;
 
2765
 
 
2766
  gimp_color_button_get_color (GIMP_COLOR_BUTTON (button), &value);
 
2767
 
 
2768
  g_signal_handlers_block_by_func (config,
 
2769
                                   gimp_prop_color_button_notify,
 
2770
                                   button);
 
2771
 
 
2772
  g_object_set (config,
 
2773
                param_spec->name, &value,
 
2774
                NULL);
 
2775
 
 
2776
  g_signal_handlers_unblock_by_func (config,
 
2777
                                     gimp_prop_color_button_notify,
 
2778
                                     button);
 
2779
}
 
2780
 
 
2781
static void
 
2782
gimp_prop_color_button_notify (GObject    *config,
 
2783
                               GParamSpec *param_spec,
 
2784
                               GtkWidget  *button)
 
2785
{
 
2786
  GimpRGB *value;
 
2787
 
 
2788
  g_object_get (config,
 
2789
                param_spec->name, &value,
 
2790
                NULL);
 
2791
 
 
2792
  g_signal_handlers_block_by_func (button,
 
2793
                                   gimp_prop_color_button_callback,
 
2794
                                   config);
 
2795
 
 
2796
  gimp_color_button_set_color (GIMP_COLOR_BUTTON (button), value);
 
2797
 
 
2798
  g_free (value);
 
2799
 
 
2800
  g_signal_handlers_unblock_by_func (button,
 
2801
                                     gimp_prop_color_button_callback,
 
2802
                                     config);
 
2803
}
 
2804
 
 
2805
 
 
2806
/***************/
 
2807
/*  unit menu  */
 
2808
/***************/
 
2809
 
 
2810
static void   gimp_prop_unit_menu_callback (GtkWidget  *menu,
 
2811
                                            GObject    *config);
 
2812
static void   gimp_prop_unit_menu_notify   (GObject    *config,
 
2813
                                            GParamSpec *param_spec,
 
2814
                                            GtkWidget  *menu);
 
2815
 
 
2816
GtkWidget *
 
2817
gimp_prop_unit_menu_new (GObject     *config,
 
2818
                         const gchar *property_name,
 
2819
                         const gchar *unit_format)
 
2820
{
 
2821
  GParamSpec *param_spec;
 
2822
  GtkWidget  *menu;
 
2823
  GimpUnit    unit;
 
2824
  GValue      value = { 0, };
 
2825
  gboolean    show_pixels;
 
2826
  gboolean    show_percent;
 
2827
 
 
2828
  param_spec = check_param_spec (config, property_name,
 
2829
                                 GIMP_TYPE_PARAM_UNIT, G_STRFUNC);
 
2830
  if (! param_spec)
 
2831
    return NULL;
 
2832
 
 
2833
  g_value_init (&value, param_spec->value_type);
 
2834
 
 
2835
  g_value_set_int (&value, GIMP_UNIT_PIXEL);
 
2836
  show_pixels = (g_param_value_validate (param_spec, &value) == FALSE);
 
2837
 
 
2838
  g_value_set_int (&value, GIMP_UNIT_PERCENT);
 
2839
  show_percent = (g_param_value_validate (param_spec, &value) == FALSE);
 
2840
 
 
2841
  g_value_unset (&value);
 
2842
 
 
2843
  g_object_get (config,
 
2844
                property_name, &unit,
 
2845
                NULL);
 
2846
 
 
2847
  menu = gimp_unit_menu_new (unit_format, unit, show_pixels, show_percent, TRUE);
 
2848
 
 
2849
  set_param_spec (G_OBJECT (menu), menu, param_spec);
 
2850
 
 
2851
  g_signal_connect (menu, "unit_changed",
 
2852
                    G_CALLBACK (gimp_prop_unit_menu_callback),
 
2853
                    config);
 
2854
 
 
2855
  connect_notify (config, property_name,
 
2856
                  G_CALLBACK (gimp_prop_unit_menu_notify),
 
2857
                  menu);
 
2858
 
 
2859
  return menu;
 
2860
}
 
2861
 
 
2862
static void
 
2863
gimp_prop_unit_menu_callback (GtkWidget *menu,
 
2864
                              GObject   *config)
 
2865
{
 
2866
  GParamSpec *param_spec;
 
2867
  GimpUnit    unit;
 
2868
 
 
2869
  param_spec = get_param_spec (G_OBJECT (menu));
 
2870
  if (! param_spec)
 
2871
    return;
 
2872
 
 
2873
  gimp_unit_menu_update (menu, &unit);
 
2874
 
 
2875
  g_signal_handlers_block_by_func (config,
 
2876
                                   gimp_prop_unit_menu_notify,
 
2877
                                   menu);
 
2878
 
 
2879
  g_object_set (config,
 
2880
                param_spec->name, unit,
 
2881
                NULL);
 
2882
 
 
2883
  g_signal_handlers_unblock_by_func (config,
 
2884
                                     gimp_prop_unit_menu_notify,
 
2885
                                     menu);
 
2886
}
 
2887
 
 
2888
static void
 
2889
gimp_prop_unit_menu_notify (GObject    *config,
 
2890
                            GParamSpec *param_spec,
 
2891
                            GtkWidget  *menu)
 
2892
{
 
2893
  GimpUnit  unit;
 
2894
 
 
2895
  g_object_get (config,
 
2896
                param_spec->name, &unit,
 
2897
                NULL);
 
2898
 
 
2899
  g_signal_handlers_block_by_func (menu,
 
2900
                                   gimp_prop_unit_menu_callback,
 
2901
                                   config);
 
2902
 
 
2903
  gimp_unit_menu_set_unit (GIMP_UNIT_MENU (menu), unit);
 
2904
  gimp_unit_menu_update (menu, &unit);
 
2905
 
 
2906
  g_signal_handlers_unblock_by_func (menu,
 
2907
                                     gimp_prop_unit_menu_callback,
 
2908
                                     config);
 
2909
}
 
2910
 
 
2911
 
 
2912
/*************/
 
2913
/*  preview  */
 
2914
/*************/
 
2915
 
 
2916
static void   gimp_prop_preview_drop   (GtkWidget    *menu,
 
2917
                                        GimpViewable *viewable,
 
2918
                                        gpointer      data);
 
2919
static void   gimp_prop_preview_notify (GObject      *config,
 
2920
                                        GParamSpec   *param_spec,
 
2921
                                        GtkWidget    *preview);
 
2922
 
 
2923
GtkWidget *
 
2924
gimp_prop_preview_new (GObject     *config,
 
2925
                       const gchar *property_name,
 
2926
                       gint         size)
 
2927
{
 
2928
  GParamSpec   *param_spec;
 
2929
  GtkWidget    *preview;
 
2930
  GimpViewable *viewable;
 
2931
 
 
2932
  param_spec = check_param_spec (config, property_name,
 
2933
                                 G_TYPE_PARAM_OBJECT, G_STRFUNC);
 
2934
  if (! param_spec)
 
2935
    return NULL;
 
2936
 
 
2937
  if (! g_type_is_a (param_spec->value_type, GIMP_TYPE_VIEWABLE))
 
2938
    {
 
2939
      g_warning ("%s: property '%s' of %s is not a GimpViewable",
 
2940
                 G_STRFUNC, property_name,
 
2941
                 g_type_name (G_TYPE_FROM_INSTANCE (config)));
 
2942
      return NULL;
 
2943
    }
 
2944
 
 
2945
  preview = gimp_view_new_by_types (GIMP_TYPE_VIEW,
 
2946
                                    param_spec->value_type,
 
2947
                                    size, 0, FALSE);
 
2948
 
 
2949
  if (! preview)
 
2950
    {
 
2951
      g_warning ("%s: cannot create preview for type '%s'",
 
2952
                 G_STRFUNC, g_type_name (param_spec->value_type));
 
2953
      return NULL;
 
2954
    }
 
2955
 
 
2956
  g_object_get (config,
 
2957
                property_name, &viewable,
 
2958
                NULL);
 
2959
 
 
2960
  if (viewable)
 
2961
    {
 
2962
      gimp_view_set_viewable (GIMP_VIEW (preview), viewable);
 
2963
      g_object_unref (viewable);
 
2964
    }
 
2965
 
 
2966
  set_param_spec (G_OBJECT (preview), preview, param_spec);
 
2967
 
 
2968
  gimp_dnd_viewable_dest_add (preview, param_spec->value_type,
 
2969
                              gimp_prop_preview_drop,
 
2970
                              config);
 
2971
 
 
2972
  connect_notify (config, property_name,
 
2973
                  G_CALLBACK (gimp_prop_preview_notify),
 
2974
                  preview);
 
2975
 
 
2976
  return preview;
 
2977
}
 
2978
 
 
2979
static void
 
2980
gimp_prop_preview_drop (GtkWidget    *preview,
 
2981
                        GimpViewable *viewable,
 
2982
                        gpointer      data)
 
2983
{
 
2984
  GObject    *config;
 
2985
  GParamSpec *param_spec;
 
2986
 
 
2987
  param_spec = get_param_spec (G_OBJECT (preview));
 
2988
  if (! param_spec)
 
2989
    return;
 
2990
 
 
2991
  config = G_OBJECT (data);
 
2992
 
 
2993
  g_object_set (config,
 
2994
                param_spec->name, viewable,
 
2995
                NULL);
 
2996
}
 
2997
 
 
2998
static void
 
2999
gimp_prop_preview_notify (GObject      *config,
 
3000
                          GParamSpec   *param_spec,
 
3001
                          GtkWidget    *preview)
 
3002
{
 
3003
  GimpViewable *viewable;
 
3004
 
 
3005
  g_object_get (config,
 
3006
                param_spec->name, &viewable,
 
3007
                NULL);
 
3008
 
 
3009
  gimp_view_set_viewable (GIMP_VIEW (preview), viewable);
 
3010
 
 
3011
  if (viewable)
 
3012
    g_object_unref (viewable);
 
3013
}
 
3014
 
 
3015
 
 
3016
/*****************/
 
3017
/*  stock image  */
 
3018
/*****************/
 
3019
 
 
3020
static void   gimp_prop_stock_image_notify (GObject    *config,
 
3021
                                            GParamSpec *param_spec,
 
3022
                                            GtkWidget  *image);
 
3023
 
 
3024
GtkWidget *
 
3025
gimp_prop_stock_image_new (GObject     *config,
 
3026
                           const gchar *property_name,
 
3027
                           GtkIconSize  icon_size)
 
3028
{
 
3029
  GParamSpec *param_spec;
 
3030
  GtkWidget  *image;
 
3031
  gchar      *stock_id;
 
3032
 
 
3033
  param_spec = check_param_spec (config, property_name,
 
3034
                                 G_TYPE_PARAM_STRING, G_STRFUNC);
 
3035
  if (! param_spec)
 
3036
    return NULL;
 
3037
 
 
3038
  g_object_get (config,
 
3039
                property_name, &stock_id,
 
3040
                NULL);
 
3041
 
 
3042
  image = gtk_image_new_from_stock (stock_id, icon_size);
 
3043
 
 
3044
  if (stock_id)
 
3045
    g_free (stock_id);
 
3046
 
 
3047
  set_param_spec (G_OBJECT (image), image, param_spec);
 
3048
 
 
3049
  connect_notify (config, property_name,
 
3050
                  G_CALLBACK (gimp_prop_stock_image_notify),
 
3051
                  image);
 
3052
 
 
3053
  return image;
 
3054
}
 
3055
 
 
3056
static void
 
3057
gimp_prop_stock_image_notify (GObject    *config,
 
3058
                              GParamSpec *param_spec,
 
3059
                              GtkWidget  *image)
 
3060
{
 
3061
  gchar *stock_id;
 
3062
 
 
3063
  g_object_get (config,
 
3064
                param_spec->name, &stock_id,
 
3065
                NULL);
 
3066
 
 
3067
  gtk_image_set_from_stock (GTK_IMAGE (image), stock_id,
 
3068
                            GTK_IMAGE (image)->icon_size);
 
3069
 
 
3070
  if (stock_id)
 
3071
    g_free (stock_id);
 
3072
}
 
3073
 
 
3074
 
 
3075
/*******************************/
 
3076
/*  private utility functions  */
 
3077
/*******************************/
 
3078
 
 
3079
static GQuark param_spec_quark = 0;
 
3080
 
 
3081
static void
 
3082
set_param_spec (GObject     *object,
 
3083
                GtkWidget   *widget,
 
3084
                GParamSpec  *param_spec)
 
3085
{
 
3086
  if (object)
 
3087
    {
 
3088
      if (! param_spec_quark)
 
3089
        param_spec_quark = g_quark_from_static_string ("gimp-config-param-spec");
 
3090
 
 
3091
      g_object_set_qdata (object, param_spec_quark, param_spec);
 
3092
    }
 
3093
 
 
3094
  if (widget)
 
3095
    {
 
3096
      const gchar *blurb = g_param_spec_get_blurb (param_spec);
 
3097
 
 
3098
      if (blurb)
 
3099
        gimp_help_set_help_data (widget, gettext (blurb), NULL);
 
3100
    }
 
3101
}
 
3102
 
 
3103
static void
 
3104
set_radio_spec (GObject    *object,
 
3105
                GParamSpec *param_spec)
 
3106
{
 
3107
  GSList *list;
 
3108
 
 
3109
  for (list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (object));
 
3110
       list;
 
3111
       list = g_slist_next (list))
 
3112
    {
 
3113
      set_param_spec (list->data, NULL, param_spec);
 
3114
    }
 
3115
}
 
3116
 
 
3117
static GParamSpec *
 
3118
get_param_spec (GObject *object)
 
3119
{
 
3120
  if (! param_spec_quark)
 
3121
    param_spec_quark = g_quark_from_static_string ("gimp-config-param-spec");
 
3122
 
 
3123
  return g_object_get_qdata (object, param_spec_quark);
 
3124
}
 
3125
 
 
3126
static GParamSpec *
 
3127
find_param_spec (GObject     *object,
 
3128
                 const gchar *property_name,
 
3129
                 const gchar *strloc)
 
3130
{
 
3131
  GParamSpec *param_spec;
 
3132
 
 
3133
  param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
 
3134
                                             property_name);
 
3135
 
 
3136
  if (! param_spec)
 
3137
    g_warning ("%s: %s has no property named '%s'",
 
3138
               strloc,
 
3139
               g_type_name (G_TYPE_FROM_INSTANCE (object)),
 
3140
               property_name);
 
3141
 
 
3142
  return param_spec;
 
3143
}
 
3144
 
 
3145
static GParamSpec *
 
3146
check_param_spec (GObject     *object,
 
3147
                  const gchar *property_name,
 
3148
                  GType        type,
 
3149
                  const gchar *strloc)
 
3150
{
 
3151
  GParamSpec *param_spec;
 
3152
 
 
3153
  param_spec = find_param_spec (object, property_name, strloc);
 
3154
 
 
3155
  if (param_spec && ! g_type_is_a (G_TYPE_FROM_INSTANCE (param_spec), type))
 
3156
    {
 
3157
      g_warning ("%s: property '%s' of %s is not a %s",
 
3158
                 strloc,
 
3159
                 param_spec->name,
 
3160
                 g_type_name (param_spec->owner_type),
 
3161
                 g_type_name (type));
 
3162
      return NULL;
 
3163
    }
 
3164
 
 
3165
  return param_spec;
 
3166
}
 
3167
 
 
3168
static gboolean
 
3169
get_numeric_values (GObject     *object,
 
3170
                    GParamSpec  *param_spec,
 
3171
                    gdouble     *value,
 
3172
                    gdouble     *lower,
 
3173
                    gdouble     *upper,
 
3174
                    const gchar *strloc)
 
3175
{
 
3176
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
3177
    {
 
3178
      GParamSpecInt *int_spec = G_PARAM_SPEC_INT (param_spec);
 
3179
      gint           int_value;
 
3180
 
 
3181
      g_object_get (object, param_spec->name, &int_value, NULL);
 
3182
 
 
3183
      *value = int_value;
 
3184
      *lower = int_spec->minimum;
 
3185
      *upper = int_spec->maximum;
 
3186
    }
 
3187
  else if (G_IS_PARAM_SPEC_UINT (param_spec))
 
3188
    {
 
3189
      GParamSpecUInt *uint_spec = G_PARAM_SPEC_UINT (param_spec);
 
3190
      guint           uint_value;
 
3191
 
 
3192
      g_object_get (object, param_spec->name, &uint_value, NULL);
 
3193
 
 
3194
      *value = uint_value;
 
3195
      *lower = uint_spec->minimum;
 
3196
      *upper = uint_spec->maximum;
 
3197
    }
 
3198
  else if (G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
3199
    {
 
3200
      GParamSpecDouble *double_spec = G_PARAM_SPEC_DOUBLE (param_spec);
 
3201
 
 
3202
      g_object_get (object, param_spec->name, value, NULL);
 
3203
 
 
3204
      *lower = double_spec->minimum;
 
3205
      *upper = double_spec->maximum;
 
3206
    }
 
3207
  else
 
3208
    {
 
3209
      g_warning ("%s: property '%s' of %s is not numeric",
 
3210
                 strloc,
 
3211
                 param_spec->name,
 
3212
                 g_type_name (G_TYPE_FROM_INSTANCE (object)));
 
3213
      return FALSE;
 
3214
    }
 
3215
 
 
3216
  return TRUE;
 
3217
}
 
3218
 
 
3219
static void
 
3220
connect_notify (GObject     *config,
 
3221
                const gchar *property_name,
 
3222
                GCallback    callback,
 
3223
                gpointer     callback_data)
 
3224
{
 
3225
  gchar *notify_name;
 
3226
 
 
3227
  notify_name = g_strconcat ("notify::", property_name, NULL);
 
3228
 
 
3229
  g_signal_connect_object (config, notify_name, callback, callback_data, 0);
 
3230
 
 
3231
  g_free (notify_name);
 
3232
}