~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to libgimpwidgets/gimppropwidgets.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* LIBGIMP - The GIMP Library
 
2
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 
3
 *
 
4
 * gimppropwidgets.c
 
5
 * Copyright (C) 2002-2007  Michael Natterer <mitch@gimp.org>
 
6
 *                          Sven Neumann <sven@gimp.org>
 
7
 *
 
8
 * This library is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
 * Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public
 
14
 * License along with this library; if not, write to the
 
15
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
16
 * Boston, MA 02111-1307, USA.
 
17
 */
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#include <string.h>
 
22
 
 
23
#include <gtk/gtk.h>
 
24
 
 
25
#include "libgimpcolor/gimpcolor.h"
 
26
#include "libgimpmath/gimpmath.h"
 
27
#include "libgimpbase/gimpbase.h"
 
28
#include "libgimpconfig/gimpconfig.h"
 
29
 
 
30
#include "gimpwidgets.h"
 
31
 
 
32
#include "libgimp/libgimp-intl.h"
 
33
 
 
34
 
 
35
/*  utility function prototypes  */
 
36
 
 
37
static void         set_param_spec     (GObject     *object,
 
38
                                        GtkWidget   *widget,
 
39
                                        GParamSpec  *param_spec);
 
40
static void         set_radio_spec     (GObject     *object,
 
41
                                        GParamSpec  *param_spec);
 
42
static GParamSpec * get_param_spec     (GObject     *object);
 
43
 
 
44
static GParamSpec * find_param_spec    (GObject     *object,
 
45
                                        const gchar *property_name,
 
46
                                        const gchar *strloc);
 
47
static GParamSpec * check_param_spec   (GObject     *object,
 
48
                                        const gchar *property_name,
 
49
                                        GType        type,
 
50
                                        const gchar *strloc);
 
51
static GParamSpec * check_param_spec_w (GObject     *object,
 
52
                                        const gchar *property_name,
 
53
                                        GType        type,
 
54
                                        const gchar *strloc);
 
55
 
 
56
static gboolean     get_numeric_values (GObject     *object,
 
57
                                        GParamSpec  *param_spec,
 
58
                                        gdouble     *value,
 
59
                                        gdouble     *lower,
 
60
                                        gdouble     *upper,
 
61
                                        const gchar *strloc);
 
62
 
 
63
static void         connect_notify     (GObject     *config,
 
64
                                        const gchar *property_name,
 
65
                                        GCallback    callback,
 
66
                                        gpointer     callback_data);
 
67
 
 
68
 
 
69
/******************/
 
70
/*  check button  */
 
71
/******************/
 
72
 
 
73
static void   gimp_prop_check_button_callback (GtkWidget  *widget,
 
74
                                               GObject    *config);
 
75
static void   gimp_prop_check_button_notify   (GObject    *config,
 
76
                                               GParamSpec *param_spec,
 
77
                                               GtkWidget  *button);
 
78
 
 
79
/**
 
80
 * gimp_prop_check_button_new:
 
81
 * @config:        Object to which property is attached.
 
82
 * @property_name: Name of boolean property controlled by checkbutton.
 
83
 * @label:         Label to give checkbutton (including mnemonic).
 
84
 *
 
85
 * Creates a #GtkCheckButton that displays and sets the specified
 
86
 * boolean property.
 
87
 *
 
88
 * Return value: The newly created #GtkCheckButton widget.
 
89
 *
 
90
 * Since GIMP 2.4
 
91
 */
 
92
GtkWidget *
 
93
gimp_prop_check_button_new (GObject     *config,
 
94
                            const gchar *property_name,
 
95
                            const gchar *label)
 
96
{
 
97
  GParamSpec  *param_spec;
 
98
  GtkWidget   *button;
 
99
  gboolean     value;
 
100
 
 
101
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
102
  g_return_val_if_fail (property_name != NULL, NULL);
 
103
 
 
104
  param_spec = check_param_spec_w (config, property_name,
 
105
                                   G_TYPE_PARAM_BOOLEAN, G_STRFUNC);
 
106
  if (! param_spec)
 
107
    return NULL;
 
108
 
 
109
  g_object_get (config,
 
110
                property_name, &value,
 
111
                NULL);
 
112
 
 
113
  button = gtk_check_button_new_with_mnemonic (label);
 
114
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), value);
 
115
 
 
116
  set_param_spec (G_OBJECT (button), button, param_spec);
 
117
 
 
118
  g_signal_connect (button, "toggled",
 
119
                    G_CALLBACK (gimp_prop_check_button_callback),
 
120
                    config);
 
121
 
 
122
  connect_notify (config, property_name,
 
123
                  G_CALLBACK (gimp_prop_check_button_notify),
 
124
                  button);
 
125
 
 
126
  return button;
 
127
}
 
128
 
 
129
static void
 
130
gimp_prop_check_button_callback (GtkWidget *widget,
 
131
                                 GObject   *config)
 
132
{
 
133
  GParamSpec *param_spec;
 
134
 
 
135
  param_spec = get_param_spec (G_OBJECT (widget));
 
136
  if (! param_spec)
 
137
    return;
 
138
 
 
139
  g_object_set (config,
 
140
                param_spec->name, GTK_TOGGLE_BUTTON (widget)->active,
 
141
                NULL);
 
142
 
 
143
  gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (widget));
 
144
}
 
145
 
 
146
static void
 
147
gimp_prop_check_button_notify (GObject    *config,
 
148
                               GParamSpec *param_spec,
 
149
                               GtkWidget  *button)
 
150
{
 
151
  gboolean value;
 
152
 
 
153
  g_object_get (config,
 
154
                param_spec->name, &value,
 
155
                NULL);
 
156
 
 
157
  if (GTK_TOGGLE_BUTTON (button)->active != value)
 
158
    {
 
159
      g_signal_handlers_block_by_func (button,
 
160
                                       gimp_prop_check_button_callback,
 
161
                                       config);
 
162
 
 
163
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), value);
 
164
      gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (button));
 
165
 
 
166
      g_signal_handlers_unblock_by_func (button,
 
167
                                         gimp_prop_check_button_callback,
 
168
                                         config);
 
169
    }
 
170
}
 
171
 
 
172
 
 
173
static void   gimp_prop_enum_check_button_callback (GtkWidget  *widget,
 
174
                                                    GObject    *config);
 
175
static void   gimp_prop_enum_check_button_notify   (GObject    *config,
 
176
                                                    GParamSpec *param_spec,
 
177
                                                    GtkWidget  *button);
 
178
 
 
179
/**
 
180
 * gimp_prop_enum_check_button_new:
 
181
 * @config:        Object to which property is attached.
 
182
 * @property_name: Name of enum property controlled by checkbutton.
 
183
 * @label:         Label to give checkbutton (including mnemonic).
 
184
 * @false_value:   Enum value corresponding to unchecked state.
 
185
 * @true_value:    Enum value corresonding to checked state.
 
186
 *
 
187
 * Creates a #GtkCheckButton that displays and sets the specified
 
188
 * property of type Enum.  Note that this widget only allows two values
 
189
 * for the enum, one corresponding to the "checked" state and the
 
190
 * other to the "unchecked" state.
 
191
 *
 
192
 * Return value: The newly created #GtkCheckButton widget.
 
193
 *
 
194
 * Since GIMP 2.4
 
195
 */
 
196
GtkWidget *
 
197
gimp_prop_enum_check_button_new (GObject     *config,
 
198
                                 const gchar *property_name,
 
199
                                 const gchar *label,
 
200
                                 gint         false_value,
 
201
                                 gint         true_value)
 
202
{
 
203
  GParamSpec  *param_spec;
 
204
  GtkWidget   *button;
 
205
  gint        value;
 
206
 
 
207
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
208
  g_return_val_if_fail (property_name != NULL, NULL);
 
209
 
 
210
  param_spec = check_param_spec_w (config, property_name,
 
211
                                   G_TYPE_PARAM_ENUM, G_STRFUNC);
 
212
  if (! param_spec)
 
213
    return NULL;
 
214
 
 
215
  g_object_get (config,
 
216
                property_name, &value,
 
217
                NULL);
 
218
 
 
219
  button = gtk_check_button_new_with_mnemonic (label);
 
220
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
 
221
                                value == true_value);
 
222
 
 
223
  if (value != false_value && value != true_value)
 
224
    gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
 
225
 
 
226
  set_param_spec (G_OBJECT (button), button, param_spec);
 
227
 
 
228
  g_object_set_data (G_OBJECT (button), "false-value",
 
229
                     GINT_TO_POINTER (false_value));
 
230
  g_object_set_data (G_OBJECT (button), "true-value",
 
231
                     GINT_TO_POINTER (true_value));
 
232
 
 
233
  g_signal_connect (button, "toggled",
 
234
                    G_CALLBACK (gimp_prop_enum_check_button_callback),
 
235
                    config);
 
236
 
 
237
  connect_notify (config, property_name,
 
238
                  G_CALLBACK (gimp_prop_enum_check_button_notify),
 
239
                  button);
 
240
 
 
241
  return button;
 
242
}
 
243
 
 
244
static void
 
245
gimp_prop_enum_check_button_callback (GtkWidget *widget,
 
246
                                      GObject   *config)
 
247
{
 
248
  GParamSpec *param_spec;
 
249
  gint        false_value;
 
250
  gint        true_value;
 
251
 
 
252
  param_spec = get_param_spec (G_OBJECT (widget));
 
253
  if (! param_spec)
 
254
    return;
 
255
 
 
256
  false_value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
 
257
                                                    "false-value"));
 
258
  true_value  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
 
259
                                                    "true-value"));
 
260
 
 
261
  g_object_set (config,
 
262
                param_spec->name,
 
263
                GTK_TOGGLE_BUTTON (widget)->active ? true_value : false_value,
 
264
                NULL);
 
265
 
 
266
  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (widget), FALSE);
 
267
 
 
268
  gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (widget));
 
269
}
 
270
 
 
271
static void
 
272
gimp_prop_enum_check_button_notify (GObject    *config,
 
273
                                    GParamSpec *param_spec,
 
274
                                    GtkWidget  *button)
 
275
{
 
276
  gint     value;
 
277
  gint     false_value;
 
278
  gint     true_value;
 
279
  gboolean active       = FALSE;
 
280
  gboolean inconsistent = FALSE;
 
281
 
 
282
  g_object_get (config,
 
283
                param_spec->name, &value,
 
284
                NULL);
 
285
 
 
286
  false_value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
 
287
                                                    "false-value"));
 
288
  true_value  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
 
289
                                                    "true-value"));
 
290
 
 
291
  if (value == true_value)
 
292
    active = TRUE;
 
293
  else if (value != false_value)
 
294
    inconsistent = TRUE;
 
295
 
 
296
  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button),
 
297
                                      inconsistent);
 
298
 
 
299
  if (GTK_TOGGLE_BUTTON (button)->active != active)
 
300
    {
 
301
      g_signal_handlers_block_by_func (button,
 
302
                                       gimp_prop_enum_check_button_callback,
 
303
                                       config);
 
304
 
 
305
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active);
 
306
      gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (button));
 
307
 
 
308
      g_signal_handlers_unblock_by_func (button,
 
309
                                         gimp_prop_enum_check_button_callback,
 
310
                                         config);
 
311
    }
 
312
}
 
313
 
 
314
 
 
315
/*************************/
 
316
/*  int/enum combo box   */
 
317
/*************************/
 
318
 
 
319
static void   gimp_prop_int_combo_box_callback (GtkWidget   *widget,
 
320
                                                GObject     *config);
 
321
static void   gimp_prop_int_combo_box_notify   (GObject     *config,
 
322
                                                GParamSpec  *param_spec,
 
323
                                                GtkWidget   *widget);
 
324
 
 
325
/**
 
326
 * gimp_prop_int_combo_box_new:
 
327
 * @config:        Object to which property is attached.
 
328
 * @property_name: Name of int property controlled by combo box.
 
329
 * @store:         #GimpIntStore holding list of labels, values, etc.
 
330
 *
 
331
 * Creates a #GimpIntComboBox widget to display and set the specified
 
332
 * property.  The contents of the widget are determined by @store,
 
333
 * which should be created using gimp_int_store_new().
 
334
 *
 
335
 * Return value: The newly created #GimpIntComboBox widget, optionally
 
336
 *               wrapped into a #GtkEventBox.
 
337
 *
 
338
 * Since GIMP 2.4
 
339
 */
 
340
GtkWidget *
 
341
gimp_prop_int_combo_box_new (GObject      *config,
 
342
                             const gchar  *property_name,
 
343
                             GimpIntStore *store)
 
344
{
 
345
  GParamSpec *param_spec;
 
346
  GtkWidget  *combo_box;
 
347
  GtkWidget  *widget;
 
348
  gint        value;
 
349
 
 
350
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
351
  g_return_val_if_fail (property_name != NULL, NULL);
 
352
 
 
353
  param_spec = check_param_spec_w (config, property_name,
 
354
                                   G_TYPE_PARAM_INT, G_STRFUNC);
 
355
  if (! param_spec)
 
356
    return NULL;
 
357
 
 
358
  g_object_get (config,
 
359
                property_name, &value,
 
360
                NULL);
 
361
 
 
362
  combo_box = g_object_new (GIMP_TYPE_INT_COMBO_BOX,
 
363
                            "model", store,
 
364
                            NULL);
 
365
 
 
366
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo_box), value);
 
367
 
 
368
  g_signal_connect (combo_box, "changed",
 
369
                    G_CALLBACK (gimp_prop_int_combo_box_callback),
 
370
                    config);
 
371
 
 
372
  /*  can't set a tooltip on a combo_box  */
 
373
  if (g_param_spec_get_blurb (param_spec))
 
374
    {
 
375
      widget = gtk_event_box_new ();
 
376
      gtk_container_add (GTK_CONTAINER (widget), combo_box);
 
377
      gtk_widget_show (combo_box);
 
378
    }
 
379
  else
 
380
    {
 
381
      widget = combo_box;
 
382
    }
 
383
 
 
384
  set_param_spec (G_OBJECT (combo_box), widget, param_spec);
 
385
 
 
386
  connect_notify (config, property_name,
 
387
                  G_CALLBACK (gimp_prop_int_combo_box_notify),
 
388
                  combo_box);
 
389
 
 
390
  return widget;
 
391
}
 
392
 
 
393
/**
 
394
 * gimp_prop_enum_combo_box_new:
 
395
 * @config:        Object to which property is attached.
 
396
 * @property_name: Name of enum property controlled by combo box.
 
397
 * @minimum:       Smallest allowed value of enum.
 
398
 * @maximum:       Largest allowed value of enum.
 
399
 *
 
400
 * Creates a #GimpIntComboBox widget to display and set the specified
 
401
 * enum property.  The @mimimum_value and @maximum_value give the
 
402
 * possibility of restricting the allowed range to a subset of the
 
403
 * enum.  If the two values are equal (e.g., 0, 0), then the full
 
404
 * range of the Enum is used.
 
405
 *
 
406
 * Return value: The newly created #GimpEnumComboBox widget, optionally
 
407
 *               wrapped into a #GtkEventBox.
 
408
 *
 
409
 * Since GIMP 2.4
 
410
 */
 
411
GtkWidget *
 
412
gimp_prop_enum_combo_box_new (GObject     *config,
 
413
                              const gchar *property_name,
 
414
                              gint         minimum,
 
415
                              gint         maximum)
 
416
{
 
417
  GParamSpec *param_spec;
 
418
  GtkWidget  *combo_box;
 
419
  GtkWidget  *widget;
 
420
  gint        value;
 
421
 
 
422
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
423
  g_return_val_if_fail (property_name != NULL, NULL);
 
424
 
 
425
  param_spec = check_param_spec_w (config, property_name,
 
426
                                   G_TYPE_PARAM_ENUM, G_STRFUNC);
 
427
  if (! param_spec)
 
428
    return NULL;
 
429
 
 
430
  g_object_get (config,
 
431
                property_name, &value,
 
432
                NULL);
 
433
 
 
434
  if (minimum != maximum)
 
435
    {
 
436
      GtkListStore *store;
 
437
 
 
438
      store = gimp_enum_store_new_with_range (param_spec->value_type,
 
439
                                              minimum, maximum);
 
440
 
 
441
      combo_box = g_object_new (GIMP_TYPE_ENUM_COMBO_BOX,
 
442
                                "model", store,
 
443
                                NULL);
 
444
 
 
445
      g_object_unref (store);
 
446
    }
 
447
  else
 
448
    {
 
449
      combo_box = gimp_enum_combo_box_new (param_spec->value_type);
 
450
    }
 
451
 
 
452
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo_box), value);
 
453
 
 
454
  g_signal_connect (combo_box, "changed",
 
455
                    G_CALLBACK (gimp_prop_int_combo_box_callback),
 
456
                    config);
 
457
 
 
458
  /*  can't set a tooltip on a combo_box  */
 
459
  if (g_param_spec_get_blurb (param_spec))
 
460
    {
 
461
      widget = gtk_event_box_new ();
 
462
      gtk_container_add (GTK_CONTAINER (widget), combo_box);
 
463
      gtk_widget_show (combo_box);
 
464
    }
 
465
  else
 
466
    {
 
467
      widget = combo_box;
 
468
    }
 
469
 
 
470
  set_param_spec (G_OBJECT (combo_box), widget, param_spec);
 
471
 
 
472
  connect_notify (config, property_name,
 
473
                  G_CALLBACK (gimp_prop_int_combo_box_notify),
 
474
                  combo_box);
 
475
 
 
476
  return widget;
 
477
}
 
478
 
 
479
static void
 
480
gimp_prop_int_combo_box_callback (GtkWidget *widget,
 
481
                                  GObject   *config)
 
482
{
 
483
  GParamSpec  *param_spec;
 
484
  gint         value;
 
485
 
 
486
  param_spec = get_param_spec (G_OBJECT (widget));
 
487
  if (! param_spec)
 
488
    return;
 
489
 
 
490
  if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value))
 
491
    {
 
492
      g_object_set (config,
 
493
                    param_spec->name, value,
 
494
                    NULL);
 
495
    }
 
496
}
 
497
 
 
498
static void
 
499
gimp_prop_int_combo_box_notify (GObject    *config,
 
500
                                GParamSpec *param_spec,
 
501
                                GtkWidget  *combo_box)
 
502
{
 
503
  gint value;
 
504
 
 
505
  g_object_get (config,
 
506
                param_spec->name, &value,
 
507
                NULL);
 
508
 
 
509
  g_signal_handlers_block_by_func (combo_box,
 
510
                                   gimp_prop_int_combo_box_callback,
 
511
                                   config);
 
512
 
 
513
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo_box), value);
 
514
 
 
515
  g_signal_handlers_unblock_by_func (combo_box,
 
516
                                     gimp_prop_int_combo_box_callback,
 
517
                                     config);
 
518
}
 
519
 
 
520
 
 
521
/************************/
 
522
/*  boolean combo box   */
 
523
/************************/
 
524
 
 
525
static void   gimp_prop_boolean_combo_box_callback (GtkWidget   *widget,
 
526
                                                    GObject     *config);
 
527
static void   gimp_prop_boolean_combo_box_notify   (GObject     *config,
 
528
                                                    GParamSpec  *param_spec,
 
529
                                                    GtkWidget   *widget);
 
530
 
 
531
 
 
532
/**
 
533
 * gimp_prop_boolean_combo_box_new:
 
534
 * @config:        Object to which property is attached.
 
535
 * @property_name: Name of boolean property controlled by combo box.
 
536
 * @true_text:     Label used for entry corresponding to %TRUE value.
 
537
 * @false_text:    Label used for entry corresponding to %FALSE value.
 
538
 *
 
539
 * Creates a #GtkComboBox widget to display and set the specified
 
540
 * boolean property.  The combo box will have two entries, one
 
541
 * displaying the @true_text label, the other displaying the
 
542
 * @false_text label.
 
543
 *
 
544
 * Return value: The newly created #GtkComboBox widget, optionally
 
545
 *               wrapped into a #GtkEventBox..
 
546
 *
 
547
 * Since GIMP 2.4
 
548
 */
 
549
GtkWidget *
 
550
gimp_prop_boolean_combo_box_new (GObject     *config,
 
551
                                 const gchar *property_name,
 
552
                                 const gchar *true_text,
 
553
                                 const gchar *false_text)
 
554
{
 
555
  GParamSpec *param_spec;
 
556
  GtkWidget  *combo_box;
 
557
  GtkWidget  *widget;
 
558
  gboolean    value;
 
559
 
 
560
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
561
  g_return_val_if_fail (property_name != NULL, NULL);
 
562
 
 
563
  param_spec = check_param_spec_w (config, property_name,
 
564
                                   G_TYPE_PARAM_BOOLEAN, G_STRFUNC);
 
565
  if (! param_spec)
 
566
    return NULL;
 
567
 
 
568
  g_object_get (config,
 
569
                property_name, &value,
 
570
                NULL);
 
571
 
 
572
  combo_box = gtk_combo_box_new_text ();
 
573
 
 
574
  gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), true_text);
 
575
  gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), false_text);
 
576
 
 
577
  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), value ? 0 : 1);
 
578
 
 
579
  g_signal_connect (combo_box, "changed",
 
580
                    G_CALLBACK (gimp_prop_boolean_combo_box_callback),
 
581
                    config);
 
582
 
 
583
  /*  can't set a tooltip on a combo_box  */
 
584
  if (g_param_spec_get_blurb (param_spec))
 
585
    {
 
586
      widget = gtk_event_box_new ();
 
587
      gtk_container_add (GTK_CONTAINER (widget), combo_box);
 
588
      gtk_widget_show (combo_box);
 
589
    }
 
590
  else
 
591
    {
 
592
      widget = combo_box;
 
593
    }
 
594
 
 
595
  set_param_spec (G_OBJECT (combo_box), widget, param_spec);
 
596
 
 
597
  connect_notify (config, property_name,
 
598
                  G_CALLBACK (gimp_prop_boolean_combo_box_notify),
 
599
                  combo_box);
 
600
 
 
601
  return widget;
 
602
}
 
603
 
 
604
static void
 
605
gimp_prop_boolean_combo_box_callback (GtkWidget *widget,
 
606
                                      GObject   *config)
 
607
{
 
608
  GParamSpec  *param_spec;
 
609
  gint         value;
 
610
 
 
611
  param_spec = get_param_spec (G_OBJECT (widget));
 
612
  if (! param_spec)
 
613
    return;
 
614
 
 
615
  value = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
 
616
 
 
617
  g_object_set (config,
 
618
                param_spec->name, value ? FALSE : TRUE,
 
619
                NULL);
 
620
}
 
621
 
 
622
static void
 
623
gimp_prop_boolean_combo_box_notify (GObject    *config,
 
624
                                    GParamSpec *param_spec,
 
625
                                    GtkWidget  *combo_box)
 
626
{
 
627
  gint value;
 
628
 
 
629
  g_object_get (config,
 
630
                param_spec->name, &value,
 
631
                NULL);
 
632
 
 
633
  g_signal_handlers_block_by_func (combo_box,
 
634
                                   gimp_prop_boolean_combo_box_callback,
 
635
                                   config);
 
636
 
 
637
  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), value ? 0 : 1);
 
638
 
 
639
  g_signal_handlers_unblock_by_func (combo_box,
 
640
                                     gimp_prop_boolean_combo_box_callback,
 
641
                                     config);
 
642
}
 
643
 
 
644
 
 
645
/*****************/
 
646
/*  radio boxes  */
 
647
/*****************/
 
648
 
 
649
static void  gimp_prop_radio_button_callback (GtkWidget   *widget,
 
650
                                              GObject     *config);
 
651
static void  gimp_prop_radio_button_notify   (GObject     *config,
 
652
                                              GParamSpec  *param_spec,
 
653
                                              GtkWidget   *button);
 
654
 
 
655
 
 
656
/**
 
657
 * gimp_prop_enum_radio_frame_new:
 
658
 * @config:        Object to which property is attached.
 
659
 * @property_name: Name of enum property controlled by the radio buttons.
 
660
 * @title:         Label for the frame holding the buttons
 
661
 * @minimum:       Smallest value of enum to be included.
 
662
 * @maximum:       Largest value of enum to be included.
 
663
 *
 
664
 * Creates a group of radio buttons which function to set and display
 
665
 * the specified enum property.  The @minimum and @maximum arguments
 
666
 * allow only a subset of the enum to be used.  If the two arguments
 
667
 * are equal (e.g., 0, 0), then the full range of the enum will be used.
 
668
 *
 
669
 * Return value: A #GimpFrame containing the radio buttons.
 
670
 *
 
671
 * Since GIMP 2.4
 
672
 */
 
673
GtkWidget *
 
674
gimp_prop_enum_radio_frame_new (GObject     *config,
 
675
                                const gchar *property_name,
 
676
                                const gchar *title,
 
677
                                gint         minimum,
 
678
                                gint         maximum)
 
679
{
 
680
  GParamSpec *param_spec;
 
681
  GtkWidget  *frame;
 
682
  GtkWidget  *button;
 
683
  gint        value;
 
684
 
 
685
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
686
  g_return_val_if_fail (property_name != NULL, NULL);
 
687
 
 
688
  param_spec = check_param_spec_w (config, property_name,
 
689
                                   G_TYPE_PARAM_ENUM, G_STRFUNC);
 
690
  if (! param_spec)
 
691
    return NULL;
 
692
 
 
693
  g_object_get (config,
 
694
                property_name, &value,
 
695
                NULL);
 
696
 
 
697
  if (minimum != maximum)
 
698
    {
 
699
      frame = gimp_enum_radio_frame_new_with_range (param_spec->value_type,
 
700
                                                    minimum, maximum,
 
701
                                                    gtk_label_new (title),
 
702
                                                    G_CALLBACK (gimp_prop_radio_button_callback),
 
703
                                                    config,
 
704
                                                    &button);
 
705
    }
 
706
  else
 
707
    {
 
708
      frame = gimp_enum_radio_frame_new (param_spec->value_type,
 
709
                                         gtk_label_new (title),
 
710
                                         G_CALLBACK (gimp_prop_radio_button_callback),
 
711
                                         config,
 
712
                                         &button);
 
713
    }
 
714
 
 
715
  gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), value);
 
716
 
 
717
  set_radio_spec (G_OBJECT (button), param_spec);
 
718
 
 
719
  connect_notify (config, property_name,
 
720
                  G_CALLBACK (gimp_prop_radio_button_notify),
 
721
                  button);
 
722
 
 
723
  g_object_set_data (G_OBJECT (frame), "radio-button", button);
 
724
 
 
725
  return frame;
 
726
}
 
727
 
 
728
/**
 
729
 * gimp_prop_enum_radio_box_new:
 
730
 * @config:        Object to which property is attached.
 
731
 * @property_name: Name of enum property controlled by the radio buttons.
 
732
 * @minimum:       Smallest value of enum to be included.
 
733
 * @maximum:       Largest value of enum to be included.
 
734
 *
 
735
 * Creates a group of radio buttons which function to set and display
 
736
 * the specified enum property.  The @minimum and @maximum arguments
 
737
 * allow only a subset of the enum to be used.  If the two arguments
 
738
 * are equal (e.g., 0, 0), then the full range of the enum will be used.
 
739
 * If you want to assign a label to the group of radio buttons, use
 
740
 * gimp_prop_enum_radio_frame_new() instead of this function.
 
741
 *
 
742
 * Return value: A #GtkVBox containing the radio buttons.
 
743
 *
 
744
 * Since GIMP 2.4
 
745
 */
 
746
GtkWidget *
 
747
gimp_prop_enum_radio_box_new (GObject     *config,
 
748
                              const gchar *property_name,
 
749
                              gint         minimum,
 
750
                              gint         maximum)
 
751
{
 
752
  GParamSpec *param_spec;
 
753
  GtkWidget  *vbox;
 
754
  GtkWidget  *button;
 
755
  gint        value;
 
756
 
 
757
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
758
  g_return_val_if_fail (property_name != NULL, NULL);
 
759
 
 
760
  param_spec = check_param_spec_w (config, property_name,
 
761
                                   G_TYPE_PARAM_ENUM, G_STRFUNC);
 
762
  if (! param_spec)
 
763
    return NULL;
 
764
 
 
765
  g_object_get (config,
 
766
                property_name, &value,
 
767
                NULL);
 
768
 
 
769
  if (minimum != maximum)
 
770
    {
 
771
      vbox = gimp_enum_radio_box_new_with_range (param_spec->value_type,
 
772
                                                 minimum, maximum,
 
773
                                                 G_CALLBACK (gimp_prop_radio_button_callback),
 
774
                                                 config,
 
775
                                                 &button);
 
776
    }
 
777
  else
 
778
    {
 
779
      vbox = gimp_enum_radio_box_new (param_spec->value_type,
 
780
                                      G_CALLBACK (gimp_prop_radio_button_callback),
 
781
                                      config,
 
782
                                      &button);
 
783
    }
 
784
 
 
785
  gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), value);
 
786
 
 
787
  set_radio_spec (G_OBJECT (button), param_spec);
 
788
 
 
789
  connect_notify (config, property_name,
 
790
                  G_CALLBACK (gimp_prop_radio_button_notify),
 
791
                  button);
 
792
 
 
793
  g_object_set_data (G_OBJECT (vbox), "radio-button", button);
 
794
 
 
795
  return vbox;
 
796
}
 
797
 
 
798
 
 
799
/***********/
 
800
/*  label  */
 
801
/***********/
 
802
 
 
803
static void  gimp_prop_enum_label_notify (GObject    *config,
 
804
                                          GParamSpec *param_spec,
 
805
                                          GtkWidget  *label);
 
806
 
 
807
/**
 
808
 * gimp_prop_enum_label_new:
 
809
 * @config:         Object to which property is attached.
 
810
 * @property_name:  Name of enum property to be displayed.
 
811
 *
 
812
 * Return value: The newly created #GimpEnumLabel widget.
 
813
 *
 
814
 * Since GIMP 2.4
 
815
 */
 
816
GtkWidget *
 
817
gimp_prop_enum_label_new (GObject     *config,
 
818
                          const gchar *property_name)
 
819
{
 
820
  GParamSpec *param_spec;
 
821
  GtkWidget  *label;
 
822
  gint        value;
 
823
 
 
824
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
825
  g_return_val_if_fail (property_name != NULL, NULL);
 
826
 
 
827
  param_spec = check_param_spec (config, property_name,
 
828
                                 G_TYPE_PARAM_ENUM, G_STRFUNC);
 
829
  if (! param_spec)
 
830
    return NULL;
 
831
 
 
832
  g_object_get (config,
 
833
                property_name, &value,
 
834
                NULL);
 
835
 
 
836
  label = gimp_enum_label_new (param_spec->value_type, value);
 
837
 
 
838
  set_param_spec (G_OBJECT (label), NULL, param_spec);
 
839
 
 
840
  connect_notify (config, property_name,
 
841
                  G_CALLBACK (gimp_prop_enum_label_notify),
 
842
                  label);
 
843
 
 
844
  return label;
 
845
}
 
846
 
 
847
static void
 
848
gimp_prop_enum_label_notify (GObject    *config,
 
849
                             GParamSpec *param_spec,
 
850
                             GtkWidget  *label)
 
851
{
 
852
  gint value;
 
853
 
 
854
  g_object_get (config,
 
855
                param_spec->name, &value,
 
856
                NULL);
 
857
 
 
858
  gimp_enum_label_set_value (GIMP_ENUM_LABEL (label), value);
 
859
}
 
860
 
 
861
 
 
862
/**
 
863
 * gimp_prop_boolean_radio_frame_new:
 
864
 * @config:        Object to which property is attached.
 
865
 * @property_name: Name of boolean property controlled by the radio buttons.
 
866
 * @title:         Label for the frame.
 
867
 * @true_text:     Label for the button corresponding to %TRUE.
 
868
 * @false_text:    Label for the button corresponding to %FALSE.
 
869
 *
 
870
 * Creates a pair of radio buttons which function to set and display
 
871
 * the specified boolean property.
 
872
 *
 
873
 * Return value: A #GimpFrame containing the radio buttons.
 
874
 *
 
875
 * Since GIMP 2.4
 
876
 */
 
877
GtkWidget *
 
878
gimp_prop_boolean_radio_frame_new (GObject     *config,
 
879
                                   const gchar *property_name,
 
880
                                   const gchar *title,
 
881
                                   const gchar *true_text,
 
882
                                   const gchar *false_text)
 
883
{
 
884
  GParamSpec *param_spec;
 
885
  GtkWidget  *frame;
 
886
  GtkWidget  *button;
 
887
  gboolean    value;
 
888
 
 
889
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
890
  g_return_val_if_fail (property_name != NULL, NULL);
 
891
 
 
892
  param_spec = check_param_spec_w (config, property_name,
 
893
                                   G_TYPE_PARAM_BOOLEAN, G_STRFUNC);
 
894
  if (! param_spec)
 
895
    return NULL;
 
896
 
 
897
  g_object_get (config,
 
898
                property_name, &value,
 
899
                NULL);
 
900
 
 
901
  frame =
 
902
    gimp_int_radio_group_new (TRUE, title,
 
903
                              G_CALLBACK (gimp_prop_radio_button_callback),
 
904
                              config, value,
 
905
 
 
906
                              false_text, FALSE, &button,
 
907
                              true_text,  TRUE,  NULL,
 
908
 
 
909
                              NULL);
 
910
 
 
911
  set_radio_spec (G_OBJECT (button), param_spec);
 
912
 
 
913
  connect_notify (config, property_name,
 
914
                  G_CALLBACK (gimp_prop_radio_button_notify),
 
915
                  button);
 
916
 
 
917
  g_object_set_data (G_OBJECT (frame), "radio-button", button);
 
918
 
 
919
  return frame;
 
920
}
 
921
 
 
922
/**
 
923
 * gimp_prop_enum_stock_box_new:
 
924
 * @config:        Object to which property is attached.
 
925
 * @property_name: Name of enum property controlled by the radio buttons.
 
926
 * @stock_prefix:  The prefix of the group of stock ids to use.
 
927
 * @minimum:       Smallest value of enum to be included.
 
928
 * @maximum:       Largest value of enum to be included.
 
929
 *
 
930
 * Creates a horizontal box of radio buttons with stock icons, which
 
931
 * function to set and display the value of the specified Enum
 
932
 * property.  The stock_id for each icon is created by appending the
 
933
 * enum_value's nick to the given @stock_prefix.  See
 
934
 * gimp_enum_stock_box_new() for more information.
 
935
 *
 
936
 * Return value: A #GimpEnumStockBox containing the radio buttons.
 
937
 *
 
938
 * Since GIMP 2.4
 
939
 */
 
940
GtkWidget *
 
941
gimp_prop_enum_stock_box_new (GObject     *config,
 
942
                              const gchar *property_name,
 
943
                              const gchar *stock_prefix,
 
944
                              gint         minimum,
 
945
                              gint         maximum)
 
946
{
 
947
  GParamSpec *param_spec;
 
948
  GtkWidget  *box;
 
949
  GtkWidget  *button;
 
950
  gint        value;
 
951
 
 
952
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
953
  g_return_val_if_fail (property_name != NULL, NULL);
 
954
 
 
955
  param_spec = check_param_spec_w (config, property_name,
 
956
                                   G_TYPE_PARAM_ENUM, G_STRFUNC);
 
957
  if (! param_spec)
 
958
    return NULL;
 
959
 
 
960
  g_object_get (config,
 
961
                property_name, &value,
 
962
                NULL);
 
963
 
 
964
  if (minimum != maximum)
 
965
    {
 
966
      box = gimp_enum_stock_box_new_with_range (param_spec->value_type,
 
967
                                                minimum, maximum,
 
968
                                                stock_prefix,
 
969
                                                GTK_ICON_SIZE_MENU,
 
970
                                                G_CALLBACK (gimp_prop_radio_button_callback),
 
971
                                                config,
 
972
                                                &button);
 
973
    }
 
974
  else
 
975
    {
 
976
      box = gimp_enum_stock_box_new (param_spec->value_type,
 
977
                                     stock_prefix,
 
978
                                     GTK_ICON_SIZE_MENU,
 
979
                                     G_CALLBACK (gimp_prop_radio_button_callback),
 
980
                                     config,
 
981
                                     &button);
 
982
    }
 
983
 
 
984
  gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), value);
 
985
 
 
986
  set_radio_spec (G_OBJECT (button), param_spec);
 
987
 
 
988
  connect_notify (config, property_name,
 
989
                  G_CALLBACK (gimp_prop_radio_button_notify),
 
990
                  button);
 
991
 
 
992
  return box;
 
993
}
 
994
 
 
995
static void
 
996
gimp_prop_radio_button_callback (GtkWidget *widget,
 
997
                                 GObject   *config)
 
998
{
 
999
  if (GTK_TOGGLE_BUTTON (widget)->active)
 
1000
    {
 
1001
      GParamSpec *param_spec;
 
1002
      gint        value;
 
1003
 
 
1004
      param_spec = get_param_spec (G_OBJECT (widget));
 
1005
      if (! param_spec)
 
1006
        return;
 
1007
 
 
1008
      value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
 
1009
                                                  "gimp-item-data"));
 
1010
 
 
1011
      g_object_set (config,
 
1012
                    param_spec->name, value,
 
1013
                    NULL);
 
1014
    }
 
1015
}
 
1016
 
 
1017
static void
 
1018
gimp_prop_radio_button_notify (GObject    *config,
 
1019
                               GParamSpec *param_spec,
 
1020
                               GtkWidget  *button)
 
1021
{
 
1022
  gint value;
 
1023
 
 
1024
  g_object_get (config,
 
1025
                param_spec->name, &value,
 
1026
                NULL);
 
1027
 
 
1028
  gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), value);
 
1029
}
 
1030
 
 
1031
 
 
1032
/*****************/
 
1033
/*  adjustments  */
 
1034
/*****************/
 
1035
 
 
1036
static void   gimp_prop_adjustment_callback (GtkAdjustment *adjustment,
 
1037
                                             GObject       *config);
 
1038
static void   gimp_prop_adjustment_notify   (GObject       *config,
 
1039
                                             GParamSpec    *param_spec,
 
1040
                                             GtkAdjustment *adjustment);
 
1041
 
 
1042
/**
 
1043
 * gimp_prop_spin_button_new:
 
1044
 * @config:            Object to which property is attached.
 
1045
 * @property_name:     Name of double property controlled by the spin button.
 
1046
 * @step_increment:    Step size.
 
1047
 * @page_increment:    Page size.
 
1048
 * @digits:            Number of digits after decimal point to display.
 
1049
 *
 
1050
 * Creates a spin button to set and display the value of the
 
1051
 * specified double property.
 
1052
 *
 
1053
 * Return value: A new #GimpSpinButton.
 
1054
 *
 
1055
 * Since GIMP 2.4
 
1056
 */
 
1057
GtkWidget *
 
1058
gimp_prop_spin_button_new (GObject     *config,
 
1059
                           const gchar *property_name,
 
1060
                           gdouble      step_increment,
 
1061
                           gdouble      page_increment,
 
1062
                           gint         digits)
 
1063
{
 
1064
  GParamSpec *param_spec;
 
1065
  GtkWidget  *spinbutton;
 
1066
  GtkObject  *adjustment;
 
1067
  gdouble     value;
 
1068
  gdouble     lower;
 
1069
  gdouble     upper;
 
1070
 
 
1071
  param_spec = find_param_spec (config, property_name, G_STRFUNC);
 
1072
  if (! param_spec)
 
1073
    return NULL;
 
1074
 
 
1075
  if (! get_numeric_values (config,
 
1076
                            param_spec, &value, &lower, &upper, G_STRFUNC))
 
1077
    return NULL;
 
1078
 
 
1079
  if (! G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
1080
    digits = 0;
 
1081
 
 
1082
  spinbutton = gimp_spin_button_new (&adjustment,
 
1083
                                     value, lower, upper,
 
1084
                                     step_increment, page_increment,
 
1085
                                     0.0, 1.0, digits);
 
1086
 
 
1087
  set_param_spec (G_OBJECT (adjustment), spinbutton, param_spec);
 
1088
 
 
1089
  g_signal_connect (adjustment, "value-changed",
 
1090
                    G_CALLBACK (gimp_prop_adjustment_callback),
 
1091
                    config);
 
1092
 
 
1093
  connect_notify (config, property_name,
 
1094
                  G_CALLBACK (gimp_prop_adjustment_notify),
 
1095
                  adjustment);
 
1096
 
 
1097
  return spinbutton;
 
1098
}
 
1099
 
 
1100
/**
 
1101
 * gimp_prop_hscale_new:
 
1102
 * @config:         Object to which property is attached.
 
1103
 * @property_name:  Name of integer or double property controlled by the scale.
 
1104
 * @step_increment: Step size.
 
1105
 * @page_increment: Page size.
 
1106
 * @digits:         Number of digits after decimal point to display.
 
1107
 *
 
1108
 * Creates a horizontal scale to control the value of the specified
 
1109
 * integer or double property.
 
1110
 *
 
1111
 * Return value: A new #GtkScale.
 
1112
 *
 
1113
 * Since GIMP 2.4
 
1114
 */
 
1115
GtkWidget *
 
1116
gimp_prop_hscale_new (GObject     *config,
 
1117
                      const gchar *property_name,
 
1118
                      gdouble      step_increment,
 
1119
                      gdouble      page_increment,
 
1120
                      gint         digits)
 
1121
{
 
1122
  GParamSpec *param_spec;
 
1123
  GtkWidget  *scale;
 
1124
  GtkObject  *adjustment;
 
1125
  gdouble     value;
 
1126
  gdouble     lower;
 
1127
  gdouble     upper;
 
1128
 
 
1129
  param_spec = find_param_spec (config, property_name, G_STRFUNC);
 
1130
  if (! param_spec)
 
1131
    return NULL;
 
1132
 
 
1133
  if (! get_numeric_values (config,
 
1134
                            param_spec, &value, &lower, &upper, G_STRFUNC))
 
1135
    return NULL;
 
1136
 
 
1137
  if (! G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
1138
    digits = 0;
 
1139
 
 
1140
  adjustment = gtk_adjustment_new (value, lower, upper,
 
1141
                                   step_increment, page_increment, 0.0);
 
1142
 
 
1143
  scale = g_object_new (GTK_TYPE_HSCALE,
 
1144
                        "adjustment", adjustment,
 
1145
                        "digits",     digits,
 
1146
                        NULL);
 
1147
 
 
1148
  set_param_spec (G_OBJECT (adjustment), scale, param_spec);
 
1149
 
 
1150
  g_signal_connect (adjustment, "value-changed",
 
1151
                    G_CALLBACK (gimp_prop_adjustment_callback),
 
1152
                    config);
 
1153
 
 
1154
  connect_notify (config, property_name,
 
1155
                  G_CALLBACK (gimp_prop_adjustment_notify),
 
1156
                  adjustment);
 
1157
 
 
1158
  return scale;
 
1159
}
 
1160
 
 
1161
/**
 
1162
 * gimp_prop_scale_entry_new:
 
1163
 * @config:         Object to which property is attached.
 
1164
 * @property_name:  Name of double property controlled by the spin button.
 
1165
 * @table:          The #GtkTable the widgets will be attached to.
 
1166
 * @column:         The column to start with.
 
1167
 * @row:            The row to attach the widgets.
 
1168
 * @label:          The text for the #GtkLabel which will appear left of
 
1169
 *                  the #GtkHScale.
 
1170
 * @step_increment: Step size.
 
1171
 * @page_increment: Page size.
 
1172
 * @digits:         Number of digits after decimal point to display.
 
1173
 * @limit_scale:    %TRUE if the range of possible values of the
 
1174
 *                  GtkSpinButton should be the same as of the GtkHScale.
 
1175
 * @lower_limit:    The spinbutton's lower boundary if @limit_scale is %FALSE.
 
1176
 * @upper_limit:    The spinbutton's upper boundary if @limit_scale is %FALSE.
 
1177
 *
 
1178
 * Creates a #GimpScaleEntry (slider and spin button) to set and
 
1179
 * display the value of the specified double property.  See
 
1180
 * gimp_scale_entry_new() for more information.
 
1181
 *
 
1182
 * Return value: The #GtkSpinButton's #GtkAdjustment.
 
1183
 *
 
1184
 * Since GIMP 2.4
 
1185
 */
 
1186
GtkObject *
 
1187
gimp_prop_scale_entry_new (GObject     *config,
 
1188
                           const gchar *property_name,
 
1189
                           GtkTable    *table,
 
1190
                           gint         column,
 
1191
                           gint         row,
 
1192
                           const gchar *label,
 
1193
                           gdouble      step_increment,
 
1194
                           gdouble      page_increment,
 
1195
                           gint         digits,
 
1196
                           gboolean     limit_scale,
 
1197
                           gdouble      lower_limit,
 
1198
                           gdouble      upper_limit)
 
1199
{
 
1200
  GParamSpec  *param_spec;
 
1201
  GtkObject   *adjustment;
 
1202
  const gchar *tooltip;
 
1203
  gdouble      value;
 
1204
  gdouble      lower;
 
1205
  gdouble      upper;
 
1206
 
 
1207
  param_spec = find_param_spec (config, property_name, G_STRFUNC);
 
1208
  if (! param_spec)
 
1209
    return NULL;
 
1210
 
 
1211
  if (! get_numeric_values (config,
 
1212
                            param_spec, &value, &lower, &upper, G_STRFUNC))
 
1213
    return NULL;
 
1214
 
 
1215
  tooltip = dgettext (gimp_type_get_translation_domain (G_OBJECT_TYPE (config)),
 
1216
                      g_param_spec_get_blurb (param_spec));
 
1217
 
 
1218
  if (! limit_scale)
 
1219
    {
 
1220
      adjustment = gimp_scale_entry_new (table, column, row,
 
1221
                                         label, -1, -1,
 
1222
                                         value, lower, upper,
 
1223
                                         step_increment, page_increment,
 
1224
                                         digits,
 
1225
                                         TRUE, 0.0, 0.0,
 
1226
                                         tooltip,
 
1227
                                         NULL);
 
1228
    }
 
1229
  else
 
1230
    {
 
1231
      adjustment = gimp_scale_entry_new (table, column, row,
 
1232
                                         label, -1, -1,
 
1233
                                         value, lower_limit, upper_limit,
 
1234
                                         step_increment, page_increment,
 
1235
                                         digits,
 
1236
                                         FALSE, lower, upper,
 
1237
                                         tooltip,
 
1238
                                         NULL);
 
1239
    }
 
1240
 
 
1241
  set_param_spec (G_OBJECT (adjustment), NULL,  param_spec);
 
1242
 
 
1243
  g_signal_connect (adjustment, "value-changed",
 
1244
                    G_CALLBACK (gimp_prop_adjustment_callback),
 
1245
                    config);
 
1246
 
 
1247
  connect_notify (config, property_name,
 
1248
                  G_CALLBACK (gimp_prop_adjustment_notify),
 
1249
                  adjustment);
 
1250
 
 
1251
  return adjustment;
 
1252
}
 
1253
 
 
1254
/**
 
1255
 * gimp_prop_opacity_entry_new:
 
1256
 * @config:        Object to which property is attached.
 
1257
 * @property_name: Name of double property controlled by the spin button.
 
1258
 * @table:         The #GtkTable the widgets will be attached to.
 
1259
 * @column:        The column to start with.
 
1260
 * @row:           The row to attach the widgets.
 
1261
 * @label:         The text for the #GtkLabel which will appear left of the
 
1262
 *                 #GtkHScale.
 
1263
 *
 
1264
 * Creates a #GimpScaleEntry (slider and spin button) to set and
 
1265
 * display the value of the specified double property, which should
 
1266
 * represent an "opacity" variable with range 0 to 100.  See
 
1267
 * gimp_scale_entry_new() for more information.
 
1268
 *
 
1269
 * Return value:  The #GtkSpinButton's #GtkAdjustment.
 
1270
 *
 
1271
 * Since GIMP 2.4
 
1272
 */
 
1273
GtkObject *
 
1274
gimp_prop_opacity_entry_new (GObject     *config,
 
1275
                             const gchar *property_name,
 
1276
                             GtkTable    *table,
 
1277
                             gint         column,
 
1278
                             gint         row,
 
1279
                             const gchar *label)
 
1280
{
 
1281
  GParamSpec  *param_spec;
 
1282
  GtkObject   *adjustment;
 
1283
  const gchar *tooltip;
 
1284
  gdouble      value;
 
1285
  gdouble      lower;
 
1286
  gdouble      upper;
 
1287
 
 
1288
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
1289
  g_return_val_if_fail (property_name != NULL, NULL);
 
1290
 
 
1291
  param_spec = check_param_spec_w (config, property_name,
 
1292
                                   G_TYPE_PARAM_DOUBLE, G_STRFUNC);
 
1293
  if (! param_spec)
 
1294
    return NULL;
 
1295
 
 
1296
  g_object_get (config, property_name, &value, NULL);
 
1297
 
 
1298
  tooltip = dgettext (gimp_type_get_translation_domain (G_OBJECT_TYPE (config)),
 
1299
                      g_param_spec_get_blurb (param_spec));
 
1300
 
 
1301
  value *= 100.0;
 
1302
  lower = G_PARAM_SPEC_DOUBLE (param_spec)->minimum * 100.0;
 
1303
  upper = G_PARAM_SPEC_DOUBLE (param_spec)->maximum * 100.0;
 
1304
 
 
1305
  adjustment = gimp_scale_entry_new (table, column, row,
 
1306
                                     label, -1, -1,
 
1307
                                     value, lower, upper,
 
1308
                                     1.0, 10.0, 1,
 
1309
                                     TRUE, 0.0, 0.0,
 
1310
                                     tooltip,
 
1311
                                     NULL);
 
1312
 
 
1313
  set_param_spec (G_OBJECT (adjustment), NULL,  param_spec);
 
1314
  g_object_set_data (G_OBJECT (adjustment),
 
1315
                     "opacity-scale", GINT_TO_POINTER (TRUE));
 
1316
 
 
1317
  g_signal_connect (adjustment, "value-changed",
 
1318
                    G_CALLBACK (gimp_prop_adjustment_callback),
 
1319
                    config);
 
1320
 
 
1321
  connect_notify (config, property_name,
 
1322
                  G_CALLBACK (gimp_prop_adjustment_notify),
 
1323
                  adjustment);
 
1324
 
 
1325
  return adjustment;
 
1326
}
 
1327
 
 
1328
 
 
1329
static void
 
1330
gimp_prop_adjustment_callback (GtkAdjustment *adjustment,
 
1331
                               GObject       *config)
 
1332
{
 
1333
  GParamSpec *param_spec;
 
1334
 
 
1335
  param_spec = get_param_spec (G_OBJECT (adjustment));
 
1336
  if (! param_spec)
 
1337
    return;
 
1338
 
 
1339
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
1340
    {
 
1341
      g_object_set (config,
 
1342
                    param_spec->name, (gint) adjustment->value,
 
1343
                    NULL);
 
1344
    }
 
1345
  else if (G_IS_PARAM_SPEC_UINT (param_spec))
 
1346
    {
 
1347
      g_object_set (config,
 
1348
                    param_spec->name, (guint) adjustment->value,
 
1349
                    NULL);
 
1350
    }
 
1351
  else if (G_IS_PARAM_SPEC_LONG (param_spec))
 
1352
    {
 
1353
      g_object_set (config,
 
1354
                    param_spec->name, (glong) adjustment->value,
 
1355
                    NULL);
 
1356
    }
 
1357
  else if (G_IS_PARAM_SPEC_ULONG (param_spec))
 
1358
    {
 
1359
      g_object_set (config,
 
1360
                    param_spec->name, (gulong) adjustment->value,
 
1361
                    NULL);
 
1362
    }
 
1363
  else if (G_IS_PARAM_SPEC_INT64 (param_spec))
 
1364
    {
 
1365
      g_object_set (config,
 
1366
                    param_spec->name, (gint64) adjustment->value,
 
1367
                    NULL);
 
1368
    }
 
1369
  else if (G_IS_PARAM_SPEC_UINT64 (param_spec))
 
1370
    {
 
1371
      g_object_set (config,
 
1372
                    param_spec->name, (guint64) adjustment->value,
 
1373
                    NULL);
 
1374
    }
 
1375
  else if (G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
1376
    {
 
1377
      gdouble value;
 
1378
 
 
1379
      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (adjustment),
 
1380
                                              "opacity-scale")))
 
1381
        value = adjustment->value / 100.0;
 
1382
      else
 
1383
        value = adjustment->value;
 
1384
 
 
1385
      g_object_set (config, param_spec->name, value, NULL);
 
1386
    }
 
1387
}
 
1388
 
 
1389
static void
 
1390
gimp_prop_adjustment_notify (GObject       *config,
 
1391
                             GParamSpec    *param_spec,
 
1392
                             GtkAdjustment *adjustment)
 
1393
{
 
1394
  gdouble value;
 
1395
 
 
1396
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
1397
    {
 
1398
      gint int_value;
 
1399
 
 
1400
      g_object_get (config, param_spec->name, &int_value, NULL);
 
1401
 
 
1402
      value = int_value;
 
1403
    }
 
1404
  else if (G_IS_PARAM_SPEC_UINT (param_spec))
 
1405
    {
 
1406
      guint uint_value;
 
1407
 
 
1408
      g_object_get (config, param_spec->name, &uint_value, NULL);
 
1409
 
 
1410
      value = uint_value;
 
1411
    }
 
1412
  else if (G_IS_PARAM_SPEC_LONG (param_spec))
 
1413
    {
 
1414
      glong long_value;
 
1415
 
 
1416
      g_object_get (config, param_spec->name, &long_value, NULL);
 
1417
 
 
1418
      value = long_value;
 
1419
    }
 
1420
  else if (G_IS_PARAM_SPEC_ULONG (param_spec))
 
1421
    {
 
1422
      gulong ulong_value;
 
1423
 
 
1424
      g_object_get (config, param_spec->name, &ulong_value, NULL);
 
1425
 
 
1426
      value = ulong_value;
 
1427
    }
 
1428
  else if (G_IS_PARAM_SPEC_INT64 (param_spec))
 
1429
    {
 
1430
      gint64 int64_value;
 
1431
 
 
1432
      g_object_get (config, param_spec->name, &int64_value, NULL);
 
1433
 
 
1434
      value = int64_value;
 
1435
    }
 
1436
  else if (G_IS_PARAM_SPEC_UINT64 (param_spec))
 
1437
    {
 
1438
      guint64 uint64_value;
 
1439
 
 
1440
      g_object_get (config, param_spec->name, &uint64_value, NULL);
 
1441
 
 
1442
#if defined _MSC_VER && (_MSC_VER < 1300)
 
1443
      value = (gint64) uint64_value;
 
1444
#else
 
1445
      value = uint64_value;
 
1446
#endif
 
1447
    }
 
1448
  else if (G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
1449
    {
 
1450
      g_object_get (config, param_spec->name, &value, NULL);
 
1451
 
 
1452
      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (adjustment),
 
1453
                                              "opacity-scale")))
 
1454
        value *= 100.0;
 
1455
    }
 
1456
  else
 
1457
    {
 
1458
      g_warning ("%s: unhandled param spec of type %s",
 
1459
                 G_STRFUNC, G_PARAM_SPEC_TYPE_NAME (param_spec));
 
1460
      return;
 
1461
    }
 
1462
 
 
1463
  if (adjustment->value != value)
 
1464
    {
 
1465
      g_signal_handlers_block_by_func (adjustment,
 
1466
                                       gimp_prop_adjustment_callback,
 
1467
                                       config);
 
1468
 
 
1469
      gtk_adjustment_set_value (adjustment, value);
 
1470
 
 
1471
      g_signal_handlers_unblock_by_func (adjustment,
 
1472
                                         gimp_prop_adjustment_callback,
 
1473
                                         config);
 
1474
    }
 
1475
}
 
1476
 
 
1477
 
 
1478
/*************/
 
1479
/*  memsize  */
 
1480
/*************/
 
1481
 
 
1482
static void   gimp_prop_memsize_callback (GimpMemsizeEntry *entry,
 
1483
                                          GObject          *config);
 
1484
static void   gimp_prop_memsize_notify   (GObject          *config,
 
1485
                                          GParamSpec       *param_spec,
 
1486
                                          GimpMemsizeEntry *entry);
 
1487
 
 
1488
/**
 
1489
 * gimp_prop_memsize_entry_new:
 
1490
 * @config:        Object to which property is attached.
 
1491
 * @property_name: Name of memsize property.
 
1492
 *
 
1493
 * Creates a #GimpMemsizeEntry (spin button and option menu) to set
 
1494
 * and display the value of the specified memsize property.  See
 
1495
 * gimp_memsize_entry_new() for more information.
 
1496
 *
 
1497
 * Return value:  A new #GimpMemsizeEntry.
 
1498
 *
 
1499
 * Since GIMP 2.4
 
1500
 */
 
1501
GtkWidget *
 
1502
gimp_prop_memsize_entry_new (GObject     *config,
 
1503
                             const gchar *property_name)
 
1504
{
 
1505
  GParamSpec       *param_spec;
 
1506
  GParamSpecUInt64 *uint64_spec;
 
1507
  GtkWidget        *entry;
 
1508
  guint64           value;
 
1509
 
 
1510
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
1511
  g_return_val_if_fail (property_name != NULL, NULL);
 
1512
 
 
1513
  param_spec = check_param_spec_w (config, property_name,
 
1514
                                   GIMP_TYPE_PARAM_MEMSIZE, G_STRFUNC);
 
1515
  if (! param_spec)
 
1516
    return NULL;
 
1517
 
 
1518
  g_object_get (config,
 
1519
                property_name, &value,
 
1520
                NULL);
 
1521
 
 
1522
  uint64_spec = G_PARAM_SPEC_UINT64 (param_spec);
 
1523
 
 
1524
  g_return_val_if_fail (uint64_spec->minimum <= GIMP_MAX_MEMSIZE, NULL);
 
1525
  g_return_val_if_fail (uint64_spec->maximum <= GIMP_MAX_MEMSIZE, NULL);
 
1526
 
 
1527
  entry = gimp_memsize_entry_new (value,
 
1528
                                  uint64_spec->minimum,
 
1529
                                  uint64_spec->maximum);
 
1530
 
 
1531
  set_param_spec (G_OBJECT (entry),
 
1532
                  GIMP_MEMSIZE_ENTRY (entry)->spinbutton,
 
1533
                  param_spec);
 
1534
 
 
1535
  g_signal_connect (entry, "value-changed",
 
1536
                    G_CALLBACK (gimp_prop_memsize_callback),
 
1537
                    config);
 
1538
 
 
1539
  connect_notify (config, property_name,
 
1540
                  G_CALLBACK (gimp_prop_memsize_notify),
 
1541
                  entry);
 
1542
 
 
1543
  return entry;
 
1544
}
 
1545
 
 
1546
 
 
1547
static void
 
1548
gimp_prop_memsize_callback (GimpMemsizeEntry *entry,
 
1549
                            GObject          *config)
 
1550
{
 
1551
  GParamSpec *param_spec;
 
1552
 
 
1553
  param_spec = get_param_spec (G_OBJECT (entry));
 
1554
  if (! param_spec)
 
1555
    return;
 
1556
 
 
1557
  g_return_if_fail (G_IS_PARAM_SPEC_UINT64 (param_spec));
 
1558
 
 
1559
  g_object_set (config,
 
1560
                param_spec->name, gimp_memsize_entry_get_value (entry),
 
1561
                NULL);
 
1562
}
 
1563
 
 
1564
static void
 
1565
gimp_prop_memsize_notify (GObject          *config,
 
1566
                          GParamSpec       *param_spec,
 
1567
                          GimpMemsizeEntry *entry)
 
1568
{
 
1569
  guint64  value;
 
1570
 
 
1571
  g_return_if_fail (G_IS_PARAM_SPEC_UINT64 (param_spec));
 
1572
 
 
1573
  g_object_get (config,
 
1574
                param_spec->name, &value,
 
1575
                NULL);
 
1576
 
 
1577
  if (entry->value != value)
 
1578
    {
 
1579
      g_signal_handlers_block_by_func (entry,
 
1580
                                       gimp_prop_memsize_callback,
 
1581
                                       config);
 
1582
 
 
1583
      gimp_memsize_entry_set_value (entry, value);
 
1584
 
 
1585
      g_signal_handlers_unblock_by_func (entry,
 
1586
                                         gimp_prop_memsize_callback,
 
1587
                                         config);
 
1588
    }
 
1589
}
 
1590
 
 
1591
 
 
1592
/***********/
 
1593
/*  label  */
 
1594
/***********/
 
1595
 
 
1596
static void   gimp_prop_label_notify (GObject    *config,
 
1597
                                      GParamSpec *param_spec,
 
1598
                                      GtkWidget  *label);
 
1599
 
 
1600
/**
 
1601
 * gimp_prop_label_new:
 
1602
 * @config:        Object to which property is attached.
 
1603
 * @property_name: Name of string property.
 
1604
 *
 
1605
 * Creates a #GtkLabel to display the value of the specified property.
 
1606
 * The property should be a string property or at least transformable
 
1607
 * to a string.  If the user should be able to edit the string, use
 
1608
 * gimp_prop_entry_new() instead.
 
1609
 *
 
1610
 * Return value:  A new #GtkLabel widget.
 
1611
 *
 
1612
 * Since GIMP 2.4
 
1613
 */
 
1614
GtkWidget *
 
1615
gimp_prop_label_new (GObject     *config,
 
1616
                     const gchar *property_name)
 
1617
{
 
1618
  GParamSpec *param_spec;
 
1619
  GtkWidget  *label;
 
1620
 
 
1621
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
1622
  g_return_val_if_fail (property_name != NULL, NULL);
 
1623
 
 
1624
  param_spec = find_param_spec (config, property_name, G_STRFUNC);
 
1625
 
 
1626
  if (! param_spec)
 
1627
    return NULL;
 
1628
 
 
1629
  if (! g_value_type_transformable (param_spec->value_type, G_TYPE_STRING))
 
1630
    {
 
1631
      g_warning ("%s: property '%s' of %s is not transformable to string",
 
1632
                 G_STRLOC,
 
1633
                 param_spec->name,
 
1634
                 g_type_name (param_spec->owner_type));
 
1635
      return NULL;
 
1636
    }
 
1637
 
 
1638
  label = gtk_label_new (NULL);
 
1639
 
 
1640
  set_param_spec (G_OBJECT (label), label, param_spec);
 
1641
 
 
1642
  connect_notify (config, property_name,
 
1643
                  G_CALLBACK (gimp_prop_label_notify),
 
1644
                  label);
 
1645
 
 
1646
  gimp_prop_label_notify (config, param_spec, label);
 
1647
 
 
1648
  return label;
 
1649
}
 
1650
 
 
1651
static void
 
1652
gimp_prop_label_notify (GObject    *config,
 
1653
                        GParamSpec *param_spec,
 
1654
                        GtkWidget  *label)
 
1655
{
 
1656
  GValue  value = { 0, };
 
1657
 
 
1658
  g_value_init (&value, param_spec->value_type);
 
1659
 
 
1660
  g_object_get_property (config, param_spec->name, &value);
 
1661
 
 
1662
  if (G_VALUE_HOLDS_STRING (&value))
 
1663
    {
 
1664
      const gchar *str = g_value_get_string (&value);
 
1665
 
 
1666
      gtk_label_set_text (GTK_LABEL (label), str ? str : "");
 
1667
    }
 
1668
  else
 
1669
    {
 
1670
      GValue       str_value = { 0, };
 
1671
      const gchar *str;
 
1672
 
 
1673
      g_value_init (&str_value, G_TYPE_STRING);
 
1674
      g_value_transform (&value, &str_value);
 
1675
 
 
1676
      str = g_value_get_string (&str_value);
 
1677
 
 
1678
      gtk_label_set_text (GTK_LABEL (label), str ? str : "");
 
1679
 
 
1680
      g_value_unset (&str_value);
 
1681
    }
 
1682
 
 
1683
  g_value_unset (&value);
 
1684
}
 
1685
 
 
1686
 
 
1687
/***********/
 
1688
/*  entry  */
 
1689
/***********/
 
1690
 
 
1691
static void   gimp_prop_entry_callback (GtkWidget  *entry,
 
1692
                                        GObject    *config);
 
1693
static void   gimp_prop_entry_notify   (GObject    *config,
 
1694
                                        GParamSpec *param_spec,
 
1695
                                        GtkWidget  *entry);
 
1696
 
 
1697
/**
 
1698
 * gimp_prop_entry_new:
 
1699
 * @config:        Object to which property is attached.
 
1700
 * @property_name: Name of string property.
 
1701
 * @max_len:       Maximum allowed length of string.
 
1702
 *
 
1703
 * Creates a #GtkEntry to set and display the value of the specified
 
1704
 * string property.
 
1705
 *
 
1706
 * Return value:  A new #GtkEntry widget.
 
1707
 *
 
1708
 * Since GIMP 2.4
 
1709
 */
 
1710
GtkWidget *
 
1711
gimp_prop_entry_new (GObject     *config,
 
1712
                     const gchar *property_name,
 
1713
                     gint         max_len)
 
1714
{
 
1715
  GParamSpec *param_spec;
 
1716
  GtkWidget  *entry;
 
1717
  gchar      *value;
 
1718
 
 
1719
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
1720
  g_return_val_if_fail (property_name != NULL, NULL);
 
1721
 
 
1722
  param_spec = check_param_spec (config, property_name,
 
1723
                                 G_TYPE_PARAM_STRING, G_STRFUNC);
 
1724
  if (! param_spec)
 
1725
    return NULL;
 
1726
 
 
1727
  g_object_get (config,
 
1728
                property_name, &value,
 
1729
                NULL);
 
1730
 
 
1731
  entry = gtk_entry_new ();
 
1732
  gtk_entry_set_text (GTK_ENTRY (entry), value ? value : "");
 
1733
 
 
1734
  g_free (value);
 
1735
 
 
1736
  if (max_len > 0)
 
1737
    gtk_entry_set_max_length (GTK_ENTRY (entry), max_len);
 
1738
 
 
1739
  gtk_editable_set_editable (GTK_EDITABLE (entry),
 
1740
                             param_spec->flags & G_PARAM_WRITABLE);
 
1741
 
 
1742
  set_param_spec (G_OBJECT (entry), entry, param_spec);
 
1743
 
 
1744
  g_signal_connect (entry, "changed",
 
1745
                    G_CALLBACK (gimp_prop_entry_callback),
 
1746
                    config);
 
1747
 
 
1748
  connect_notify (config, property_name,
 
1749
                  G_CALLBACK (gimp_prop_entry_notify),
 
1750
                  entry);
 
1751
 
 
1752
  return entry;
 
1753
}
 
1754
 
 
1755
static void
 
1756
gimp_prop_entry_callback (GtkWidget *entry,
 
1757
                          GObject   *config)
 
1758
{
 
1759
  GParamSpec  *param_spec;
 
1760
  const gchar *text;
 
1761
 
 
1762
  param_spec = get_param_spec (G_OBJECT (entry));
 
1763
  if (! param_spec)
 
1764
    return;
 
1765
 
 
1766
  text = gtk_entry_get_text (GTK_ENTRY (entry));
 
1767
 
 
1768
  g_signal_handlers_block_by_func (config,
 
1769
                                   gimp_prop_entry_notify,
 
1770
                                   entry);
 
1771
 
 
1772
  g_object_set (config,
 
1773
                param_spec->name, text,
 
1774
                NULL);
 
1775
 
 
1776
  g_signal_handlers_unblock_by_func (config,
 
1777
                                     gimp_prop_entry_notify,
 
1778
                                     entry);
 
1779
}
 
1780
 
 
1781
static void
 
1782
gimp_prop_entry_notify (GObject    *config,
 
1783
                        GParamSpec *param_spec,
 
1784
                        GtkWidget  *entry)
 
1785
{
 
1786
  gchar *value;
 
1787
 
 
1788
  g_object_get (config,
 
1789
                param_spec->name, &value,
 
1790
                NULL);
 
1791
 
 
1792
  g_signal_handlers_block_by_func (entry,
 
1793
                                   gimp_prop_entry_callback,
 
1794
                                   config);
 
1795
 
 
1796
  gtk_entry_set_text (GTK_ENTRY (entry), value ? value : "");
 
1797
 
 
1798
  g_signal_handlers_unblock_by_func (entry,
 
1799
                                     gimp_prop_entry_callback,
 
1800
                                     config);
 
1801
 
 
1802
  g_free (value);
 
1803
}
 
1804
 
 
1805
 
 
1806
/*****************/
 
1807
/*  text buffer  */
 
1808
/*****************/
 
1809
 
 
1810
static void   gimp_prop_text_buffer_callback (GtkTextBuffer *text_buffer,
 
1811
                                              GObject       *config);
 
1812
static void   gimp_prop_text_buffer_notify   (GObject       *config,
 
1813
                                              GParamSpec    *param_spec,
 
1814
                                              GtkTextBuffer *text_buffer);
 
1815
 
 
1816
/**
 
1817
 * gimp_prop_text_buffer_new:
 
1818
 * @config:        Object to which property is attached.
 
1819
 * @property_name: Name of string property.
 
1820
 * @max_len:       Maximum allowed length of text (in characters).
 
1821
 *
 
1822
 * Creates a #GtkTextBuffer to set and display the value of the
 
1823
 * specified string property.  Unless the string is expected to
 
1824
 * contain multiple lines or a large amount of text, use
 
1825
 * gimp_prop_entry_new() instead.  See #GtkTextView for information on
 
1826
 * how to insert a text buffer into a visible widget.
 
1827
 *
 
1828
 * If @max_len is 0 or negative, the text buffer allows an unlimited
 
1829
 * number of characters to be entered.
 
1830
 *
 
1831
 * Return value:  A new #GtkTextBuffer.
 
1832
 *
 
1833
 * Since GIMP 2.4
 
1834
 */
 
1835
GtkTextBuffer *
 
1836
gimp_prop_text_buffer_new (GObject     *config,
 
1837
                           const gchar *property_name,
 
1838
                           gint         max_len)
 
1839
{
 
1840
  GParamSpec    *param_spec;
 
1841
  GtkTextBuffer *text_buffer;
 
1842
  gchar         *value;
 
1843
 
 
1844
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
1845
  g_return_val_if_fail (property_name != NULL, NULL);
 
1846
 
 
1847
  param_spec = check_param_spec_w (config, property_name,
 
1848
                                   G_TYPE_PARAM_STRING, G_STRFUNC);
 
1849
  if (! param_spec)
 
1850
    return NULL;
 
1851
 
 
1852
  g_object_get (config,
 
1853
                property_name, &value,
 
1854
                NULL);
 
1855
 
 
1856
  text_buffer = gtk_text_buffer_new (NULL);
 
1857
  gtk_text_buffer_set_text (text_buffer, value ? value : "", -1);
 
1858
 
 
1859
  g_free (value);
 
1860
 
 
1861
  if (max_len > 0)
 
1862
    g_object_set_data (G_OBJECT (text_buffer), "max-len",
 
1863
                       GINT_TO_POINTER (max_len));
 
1864
 
 
1865
  set_param_spec (G_OBJECT (text_buffer), NULL, param_spec);
 
1866
 
 
1867
  g_signal_connect (text_buffer, "changed",
 
1868
                    G_CALLBACK (gimp_prop_text_buffer_callback),
 
1869
                    config);
 
1870
 
 
1871
  connect_notify (config, property_name,
 
1872
                  G_CALLBACK (gimp_prop_text_buffer_notify),
 
1873
                  text_buffer);
 
1874
 
 
1875
  return text_buffer;
 
1876
}
 
1877
 
 
1878
static void
 
1879
gimp_prop_text_buffer_callback (GtkTextBuffer *text_buffer,
 
1880
                                GObject       *config)
 
1881
{
 
1882
  GParamSpec  *param_spec;
 
1883
  GtkTextIter  start_iter;
 
1884
  GtkTextIter  end_iter;
 
1885
  gchar       *text;
 
1886
  gint         max_len;
 
1887
 
 
1888
  param_spec = get_param_spec (G_OBJECT (text_buffer));
 
1889
  if (! param_spec)
 
1890
    return;
 
1891
 
 
1892
  gtk_text_buffer_get_bounds (text_buffer, &start_iter, &end_iter);
 
1893
  text = gtk_text_buffer_get_text (text_buffer, &start_iter, &end_iter, FALSE);
 
1894
 
 
1895
  max_len = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (text_buffer),
 
1896
                                                "max-length"));
 
1897
 
 
1898
  if (max_len > 0 && g_utf8_strlen (text, -1) > max_len)
 
1899
    {
 
1900
      g_message (dngettext (GETTEXT_PACKAGE "-libgimp",
 
1901
                            "This text input field is limited to %d character.",
 
1902
                            "This text input field is limited to %d characters.",
 
1903
                            max_len), max_len);
 
1904
 
 
1905
      gtk_text_buffer_get_iter_at_offset (text_buffer,
 
1906
                                          &start_iter, max_len - 1);
 
1907
      gtk_text_buffer_get_end_iter (text_buffer, &end_iter);
 
1908
 
 
1909
      /*  this calls us recursively, but in the else branch  */
 
1910
      gtk_text_buffer_delete (text_buffer, &start_iter, &end_iter);
 
1911
    }
 
1912
  else
 
1913
    {
 
1914
      g_signal_handlers_block_by_func (config,
 
1915
                                       gimp_prop_text_buffer_notify,
 
1916
                                       text_buffer);
 
1917
 
 
1918
      g_object_set (config,
 
1919
                    param_spec->name, text,
 
1920
                    NULL);
 
1921
 
 
1922
      g_signal_handlers_unblock_by_func (config,
 
1923
                                         gimp_prop_text_buffer_notify,
 
1924
                                         text_buffer);
 
1925
    }
 
1926
 
 
1927
  g_free (text);
 
1928
}
 
1929
 
 
1930
static void
 
1931
gimp_prop_text_buffer_notify (GObject       *config,
 
1932
                              GParamSpec    *param_spec,
 
1933
                              GtkTextBuffer *text_buffer)
 
1934
{
 
1935
  gchar *value;
 
1936
 
 
1937
  g_object_get (config,
 
1938
                param_spec->name, &value,
 
1939
                NULL);
 
1940
 
 
1941
  g_signal_handlers_block_by_func (text_buffer,
 
1942
                                   gimp_prop_text_buffer_callback,
 
1943
                                   config);
 
1944
 
 
1945
  gtk_text_buffer_set_text (text_buffer, value ? value : "", -1);
 
1946
 
 
1947
  g_signal_handlers_unblock_by_func (text_buffer,
 
1948
                                     gimp_prop_text_buffer_callback,
 
1949
                                     config);
 
1950
 
 
1951
  g_free (value);
 
1952
}
 
1953
 
 
1954
 
 
1955
/***********************/
 
1956
/*  string combo box   */
 
1957
/***********************/
 
1958
 
 
1959
static void   gimp_prop_string_combo_box_callback (GtkWidget   *widget,
 
1960
                                                   GObject     *config);
 
1961
static void   gimp_prop_string_combo_box_notify   (GObject     *config,
 
1962
                                                   GParamSpec  *param_spec,
 
1963
                                                   GtkWidget   *widget);
 
1964
 
 
1965
/**
 
1966
 * gimp_prop_string_combo_box_new:
 
1967
 * @config:        Object to which property is attached.
 
1968
 * @property_name: Name of int property controlled by combo box.
 
1969
 * @model:         #GtkTreeStore holding list of values
 
1970
 * @id_column:     column in @store that holds string IDs
 
1971
 * @label_column:  column in @store that holds labels to use in the combo-box
 
1972
 *
 
1973
 * Creates a #GimpStringComboBox widget to display and set the
 
1974
 * specified property.  The contents of the widget are determined by
 
1975
 * @store.
 
1976
 *
 
1977
 * Return value: The newly created #GimpStringComboBox widget, optionally
 
1978
 *               wrapped into a #GtkEventBox.
 
1979
 *
 
1980
 * Since GIMP 2.4
 
1981
 */
 
1982
GtkWidget *
 
1983
gimp_prop_string_combo_box_new (GObject      *config,
 
1984
                                const gchar  *property_name,
 
1985
                                GtkTreeModel *model,
 
1986
                                gint          id_column,
 
1987
                                gint          label_column)
 
1988
{
 
1989
  GParamSpec *param_spec;
 
1990
  GtkWidget  *combo_box;
 
1991
  GtkWidget  *widget;
 
1992
  gchar      *value;
 
1993
 
 
1994
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
1995
  g_return_val_if_fail (property_name != NULL, NULL);
 
1996
  g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
 
1997
 
 
1998
  param_spec = check_param_spec_w (config, property_name,
 
1999
                                   G_TYPE_PARAM_STRING, G_STRFUNC);
 
2000
  if (! param_spec)
 
2001
    return NULL;
 
2002
 
 
2003
  g_object_get (config,
 
2004
                property_name, &value,
 
2005
                NULL);
 
2006
 
 
2007
  combo_box = gimp_string_combo_box_new (model, id_column, label_column);
 
2008
 
 
2009
  gimp_string_combo_box_set_active (GIMP_STRING_COMBO_BOX (combo_box), value);
 
2010
 
 
2011
  g_signal_connect (combo_box, "changed",
 
2012
                    G_CALLBACK (gimp_prop_string_combo_box_callback),
 
2013
                    config);
 
2014
 
 
2015
  /*  can't set a tooltip on a combo_box  */
 
2016
  if (g_param_spec_get_blurb (param_spec))
 
2017
    {
 
2018
      widget = gtk_event_box_new ();
 
2019
      gtk_container_add (GTK_CONTAINER (widget), combo_box);
 
2020
      gtk_widget_show (combo_box);
 
2021
    }
 
2022
  else
 
2023
    {
 
2024
      widget = combo_box;
 
2025
    }
 
2026
 
 
2027
  set_param_spec (G_OBJECT (combo_box), widget, param_spec);
 
2028
 
 
2029
  connect_notify (config, property_name,
 
2030
                  G_CALLBACK (gimp_prop_string_combo_box_notify),
 
2031
                  combo_box);
 
2032
 
 
2033
  return widget;
 
2034
}
 
2035
 
 
2036
static void
 
2037
gimp_prop_string_combo_box_callback (GtkWidget *widget,
 
2038
                                     GObject   *config)
 
2039
{
 
2040
  GParamSpec  *param_spec;
 
2041
  gchar       *value;
 
2042
 
 
2043
  param_spec = get_param_spec (G_OBJECT (widget));
 
2044
  if (! param_spec)
 
2045
    return;
 
2046
 
 
2047
  value = gimp_string_combo_box_get_active (GIMP_STRING_COMBO_BOX (widget));
 
2048
 
 
2049
  g_object_set (config,
 
2050
                param_spec->name, value,
 
2051
                NULL);
 
2052
 
 
2053
  g_free (value);
 
2054
}
 
2055
 
 
2056
static void
 
2057
gimp_prop_string_combo_box_notify (GObject    *config,
 
2058
                                   GParamSpec *param_spec,
 
2059
                                   GtkWidget  *combo_box)
 
2060
{
 
2061
  gchar *value;
 
2062
 
 
2063
  g_object_get (config,
 
2064
                param_spec->name, &value,
 
2065
                NULL);
 
2066
 
 
2067
  g_signal_handlers_block_by_func (combo_box,
 
2068
                                   gimp_prop_string_combo_box_callback,
 
2069
                                   config);
 
2070
 
 
2071
  gimp_string_combo_box_set_active (GIMP_STRING_COMBO_BOX (combo_box), value);
 
2072
 
 
2073
  g_signal_handlers_unblock_by_func (combo_box,
 
2074
                                     gimp_prop_string_combo_box_callback,
 
2075
                                     config);
 
2076
 
 
2077
  g_free (value);
 
2078
}
 
2079
 
 
2080
 
 
2081
/*************************/
 
2082
/*  file chooser button  */
 
2083
/*************************/
 
2084
 
 
2085
 
 
2086
static GtkWidget * gimp_prop_file_chooser_button_setup    (GtkWidget      *button,
 
2087
                                                           GObject        *config,
 
2088
                                                           GParamSpec     *param_spec);
 
2089
static void        gimp_prop_file_chooser_button_callback (GtkFileChooser *button,
 
2090
                                                           GObject        *config);
 
2091
static void        gimp_prop_file_chooser_button_notify   (GObject        *config,
 
2092
                                                           GParamSpec     *param_spec,
 
2093
                                                           GtkFileChooser *button);
 
2094
 
 
2095
 
 
2096
/**
 
2097
 * gimp_prop_file_chooser_button_new:
 
2098
 * @config:        object to which property is attached.
 
2099
 * @property_name: name of path property.
 
2100
 * @title:         the title of the browse dialog.
 
2101
 * @action:        the open mode for the widget.
 
2102
 *
 
2103
 * Creates a #GtkFileChooserButton to edit the specified path property.
 
2104
 *
 
2105
 * Note that #GtkFileChooserButton implements the #GtkFileChooser
 
2106
 * interface; you can use the #GtkFileChooser API with it.
 
2107
 *
 
2108
 * Return value:  A new #GtkFileChooserButton.
 
2109
 *
 
2110
 * Since GIMP 2.4
 
2111
 */
 
2112
GtkWidget *
 
2113
gimp_prop_file_chooser_button_new (GObject              *config,
 
2114
                                   const gchar          *property_name,
 
2115
                                   const gchar          *title,
 
2116
                                   GtkFileChooserAction  action)
 
2117
{
 
2118
  GParamSpec *param_spec;
 
2119
  GtkWidget  *button;
 
2120
 
 
2121
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
2122
  g_return_val_if_fail (property_name != NULL, NULL);
 
2123
 
 
2124
  param_spec = check_param_spec_w (config, property_name,
 
2125
                                   GIMP_TYPE_PARAM_CONFIG_PATH, G_STRFUNC);
 
2126
  if (! param_spec)
 
2127
    return NULL;
 
2128
 
 
2129
  button = gtk_file_chooser_button_new (title, action);
 
2130
 
 
2131
  return gimp_prop_file_chooser_button_setup (button, config, param_spec);
 
2132
}
 
2133
 
 
2134
/**
 
2135
 * gimp_prop_file_chooser_button_new_with_dialog:
 
2136
 * @config:        object to which property is attached.
 
2137
 * @property_name: name of path property.
 
2138
 * @dialog:        the #GtkFileChooserDialog widget to use.
 
2139
 *
 
2140
 * Creates a #GtkFileChooserButton to edit the specified path property.
 
2141
 *
 
2142
 * The button uses @dialog as it's file-picking window. Note that @dialog
 
2143
 * must be a #GtkFileChooserDialog (or subclass) and must not have
 
2144
 * %GTK_DIALOG_DESTROY_WITH_PARENT set.
 
2145
 *
 
2146
 * Note that #GtkFileChooserButton implements the #GtkFileChooser
 
2147
 * interface; you can use the #GtkFileChooser API with it.
 
2148
 *
 
2149
 * Return value:  A new #GtkFileChooserButton.
 
2150
 *
 
2151
 * Since GIMP 2.4
 
2152
 */
 
2153
GtkWidget *
 
2154
gimp_prop_file_chooser_button_new_with_dialog (GObject     *config,
 
2155
                                               const gchar *property_name,
 
2156
                                               GtkWidget   *dialog)
 
2157
{
 
2158
  GParamSpec *param_spec;
 
2159
  GtkWidget  *button;
 
2160
  gchar      *title;
 
2161
 
 
2162
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
2163
  g_return_val_if_fail (property_name != NULL, NULL);
 
2164
  g_return_val_if_fail (GTK_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
 
2165
 
 
2166
  param_spec = check_param_spec_w (config, property_name,
 
2167
                                   GIMP_TYPE_PARAM_CONFIG_PATH, G_STRFUNC);
 
2168
  if (! param_spec)
 
2169
    return NULL;
 
2170
 
 
2171
  /* work around bug in GtkFileChooserButton */
 
2172
  title = g_strdup (gtk_window_get_title (GTK_WINDOW (dialog)));
 
2173
 
 
2174
  button = gtk_file_chooser_button_new_with_dialog (dialog);
 
2175
 
 
2176
  if (title)
 
2177
    {
 
2178
      gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (button),
 
2179
                                         title);
 
2180
      g_free (title);
 
2181
    }
 
2182
 
 
2183
  return gimp_prop_file_chooser_button_setup (button, config, param_spec);
 
2184
}
 
2185
 
 
2186
static GtkWidget *
 
2187
gimp_prop_file_chooser_button_setup (GtkWidget  *button,
 
2188
                                     GObject    *config,
 
2189
                                     GParamSpec *param_spec)
 
2190
{
 
2191
  GtkWidget *widget;
 
2192
  gchar     *value;
 
2193
  gchar     *filename;
 
2194
 
 
2195
  g_object_get (config,
 
2196
                param_spec->name, &value,
 
2197
                NULL);
 
2198
 
 
2199
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
2200
  g_free (value);
 
2201
 
 
2202
  if (filename)
 
2203
    {
 
2204
      gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (button), filename);
 
2205
      g_free (filename);
 
2206
    }
 
2207
 
 
2208
  /*  can't set a tooltip on a file-chooser button  */
 
2209
  if (g_param_spec_get_blurb (param_spec))
 
2210
    {
 
2211
      widget = gtk_event_box_new ();
 
2212
      gtk_container_add (GTK_CONTAINER (widget), button);
 
2213
      gtk_widget_show (button);
 
2214
    }
 
2215
  else
 
2216
    {
 
2217
      widget = button;
 
2218
    }
 
2219
 
 
2220
  set_param_spec (G_OBJECT (button), widget, param_spec);
 
2221
 
 
2222
  g_signal_connect (button, "selection-changed",
 
2223
                    G_CALLBACK (gimp_prop_file_chooser_button_callback),
 
2224
                    config);
 
2225
 
 
2226
  connect_notify (config, param_spec->name,
 
2227
                  G_CALLBACK (gimp_prop_file_chooser_button_notify),
 
2228
                  button);
 
2229
 
 
2230
  return widget;
 
2231
}
 
2232
 
 
2233
static void
 
2234
gimp_prop_file_chooser_button_callback (GtkFileChooser *button,
 
2235
                                        GObject        *config)
 
2236
{
 
2237
  GParamSpec *param_spec;
 
2238
  gchar      *value;
 
2239
  gchar      *utf8;
 
2240
 
 
2241
  param_spec = get_param_spec (G_OBJECT (button));
 
2242
  if (! param_spec)
 
2243
    return;
 
2244
 
 
2245
  value = gtk_file_chooser_get_filename (button);
 
2246
  utf8 = value ? g_filename_to_utf8 (value, -1, NULL, NULL, NULL) : NULL;
 
2247
  g_free (value);
 
2248
 
 
2249
  g_object_get (config,
 
2250
                param_spec->name, &value,
 
2251
                NULL);
 
2252
 
 
2253
  if (! (value && utf8 && strcmp (value, utf8) == 0))
 
2254
    {
 
2255
      g_signal_handlers_block_by_func (config,
 
2256
                                       gimp_prop_file_chooser_button_notify,
 
2257
                                       button);
 
2258
 
 
2259
      g_object_set (config,
 
2260
                    param_spec->name, utf8,
 
2261
                    NULL);
 
2262
 
 
2263
      g_signal_handlers_unblock_by_func (config,
 
2264
                                         gimp_prop_file_chooser_button_notify,
 
2265
                                         button);
 
2266
    }
 
2267
 
 
2268
  g_free (value);
 
2269
  g_free (utf8);
 
2270
}
 
2271
 
 
2272
static void
 
2273
gimp_prop_file_chooser_button_notify (GObject        *config,
 
2274
                                      GParamSpec     *param_spec,
 
2275
                                      GtkFileChooser *button)
 
2276
{
 
2277
  gchar *value;
 
2278
  gchar *filename;
 
2279
 
 
2280
  g_object_get (config,
 
2281
                param_spec->name, &value,
 
2282
                NULL);
 
2283
 
 
2284
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
2285
  g_free (value);
 
2286
 
 
2287
  g_signal_handlers_block_by_func (button,
 
2288
                                   gimp_prop_file_chooser_button_callback,
 
2289
                                   config);
 
2290
 
 
2291
  if (filename)
 
2292
    gtk_file_chooser_set_filename (button, filename);
 
2293
  else
 
2294
    gtk_file_chooser_unselect_all (button);
 
2295
 
 
2296
  g_signal_handlers_unblock_by_func (button,
 
2297
                                     gimp_prop_file_chooser_button_callback,
 
2298
                                     config);
 
2299
 
 
2300
  g_free (filename);
 
2301
}
 
2302
 
 
2303
 
 
2304
/*****************/
 
2305
/*  path editor  */
 
2306
/*****************/
 
2307
 
 
2308
static void   gimp_prop_path_editor_path_callback     (GimpPathEditor *editor,
 
2309
                                                       GObject        *config);
 
2310
static void   gimp_prop_path_editor_writable_callback (GimpPathEditor *editor,
 
2311
                                                       GObject        *config);
 
2312
static void   gimp_prop_path_editor_path_notify       (GObject        *config,
 
2313
                                                       GParamSpec     *param_spec,
 
2314
                                                       GimpPathEditor *editor);
 
2315
static void   gimp_prop_path_editor_writable_notify   (GObject        *config,
 
2316
                                                       GParamSpec     *param_spec,
 
2317
                                                       GimpPathEditor *editor);
 
2318
 
 
2319
GtkWidget *
 
2320
gimp_prop_path_editor_new (GObject     *config,
 
2321
                           const gchar *path_property_name,
 
2322
                           const gchar *writable_property_name,
 
2323
                           const gchar *filesel_title)
 
2324
{
 
2325
  GParamSpec *path_param_spec;
 
2326
  GParamSpec *writable_param_spec = NULL;
 
2327
  GtkWidget  *editor;
 
2328
  gchar      *value;
 
2329
  gchar      *filename;
 
2330
 
 
2331
  g_return_val_if_fail (G_IS_OBJECT (config), NULL);
 
2332
  g_return_val_if_fail (path_property_name != NULL, NULL);
 
2333
 
 
2334
  path_param_spec = check_param_spec_w (config, path_property_name,
 
2335
                                        GIMP_TYPE_PARAM_CONFIG_PATH, G_STRFUNC);
 
2336
  if (! path_param_spec)
 
2337
    return NULL;
 
2338
 
 
2339
  if (writable_property_name)
 
2340
    {
 
2341
      writable_param_spec = check_param_spec_w (config, writable_property_name,
 
2342
                                                GIMP_TYPE_PARAM_CONFIG_PATH,
 
2343
                                                G_STRFUNC);
 
2344
      if (! writable_param_spec)
 
2345
        return NULL;
 
2346
    }
 
2347
 
 
2348
  g_object_get (config,
 
2349
                path_property_name, &value,
 
2350
                NULL);
 
2351
 
 
2352
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
2353
  g_free (value);
 
2354
 
 
2355
  editor = gimp_path_editor_new (filesel_title, filename);
 
2356
  g_free (filename);
 
2357
 
 
2358
  if (writable_property_name)
 
2359
    {
 
2360
      g_object_get (config,
 
2361
                    writable_property_name, &value,
 
2362
                    NULL);
 
2363
 
 
2364
      filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
2365
      g_free (value);
 
2366
 
 
2367
      gimp_path_editor_set_writable_path (GIMP_PATH_EDITOR (editor), filename);
 
2368
      g_free (filename);
 
2369
    }
 
2370
 
 
2371
  g_object_set_data (G_OBJECT (editor), "gimp-config-param-spec-path",
 
2372
                     path_param_spec);
 
2373
 
 
2374
  g_signal_connect (editor, "path-changed",
 
2375
                    G_CALLBACK (gimp_prop_path_editor_path_callback),
 
2376
                    config);
 
2377
 
 
2378
  connect_notify (config, path_property_name,
 
2379
                  G_CALLBACK (gimp_prop_path_editor_path_notify),
 
2380
                  editor);
 
2381
 
 
2382
  if (writable_property_name)
 
2383
    {
 
2384
      g_object_set_data (G_OBJECT (editor), "gimp-config-param-spec-writable",
 
2385
                         writable_param_spec);
 
2386
 
 
2387
      g_signal_connect (editor, "writable-changed",
 
2388
                        G_CALLBACK (gimp_prop_path_editor_writable_callback),
 
2389
                        config);
 
2390
 
 
2391
      connect_notify (config, writable_property_name,
 
2392
                      G_CALLBACK (gimp_prop_path_editor_writable_notify),
 
2393
                      editor);
 
2394
    }
 
2395
 
 
2396
  return editor;
 
2397
}
 
2398
 
 
2399
static void
 
2400
gimp_prop_path_editor_path_callback (GimpPathEditor *editor,
 
2401
                                     GObject        *config)
 
2402
{
 
2403
  GParamSpec *path_param_spec;
 
2404
  GParamSpec *writable_param_spec;
 
2405
  gchar      *value;
 
2406
  gchar      *utf8;
 
2407
 
 
2408
  path_param_spec     = g_object_get_data (G_OBJECT (editor),
 
2409
                                           "gimp-config-param-spec-path");
 
2410
  writable_param_spec = g_object_get_data (G_OBJECT (editor),
 
2411
                                           "gimp-config-param-spec-writable");
 
2412
  if (! path_param_spec)
 
2413
    return;
 
2414
 
 
2415
  value = gimp_path_editor_get_path (editor);
 
2416
  utf8 = g_filename_to_utf8 (value, -1, NULL, NULL, NULL);
 
2417
  g_free (value);
 
2418
 
 
2419
  g_signal_handlers_block_by_func (config,
 
2420
                                   gimp_prop_path_editor_path_notify,
 
2421
                                   editor);
 
2422
 
 
2423
  g_object_set (config,
 
2424
                path_param_spec->name, utf8,
 
2425
                NULL);
 
2426
 
 
2427
  g_signal_handlers_unblock_by_func (config,
 
2428
                                     gimp_prop_path_editor_path_notify,
 
2429
                                     editor);
 
2430
 
 
2431
  g_free (utf8);
 
2432
 
 
2433
  if (writable_param_spec)
 
2434
    {
 
2435
      value = gimp_path_editor_get_writable_path (editor);
 
2436
      utf8 = g_filename_to_utf8 (value, -1, NULL, NULL, NULL);
 
2437
      g_free (value);
 
2438
 
 
2439
      g_signal_handlers_block_by_func (config,
 
2440
                                       gimp_prop_path_editor_writable_notify,
 
2441
                                       editor);
 
2442
 
 
2443
      g_object_set (config,
 
2444
                    writable_param_spec->name, utf8,
 
2445
                    NULL);
 
2446
 
 
2447
      g_signal_handlers_unblock_by_func (config,
 
2448
                                         gimp_prop_path_editor_writable_notify,
 
2449
                                         editor);
 
2450
 
 
2451
      g_free (utf8);
 
2452
    }
 
2453
}
 
2454
 
 
2455
static void
 
2456
gimp_prop_path_editor_writable_callback (GimpPathEditor *editor,
 
2457
                                         GObject        *config)
 
2458
{
 
2459
  GParamSpec *param_spec;
 
2460
  gchar      *value;
 
2461
  gchar      *utf8;
 
2462
 
 
2463
  param_spec = g_object_get_data (G_OBJECT (editor),
 
2464
                                  "gimp-config-param-spec-writable");
 
2465
  if (! param_spec)
 
2466
    return;
 
2467
 
 
2468
  value = gimp_path_editor_get_writable_path (editor);
 
2469
  utf8 = g_filename_to_utf8 (value, -1, NULL, NULL, NULL);
 
2470
  g_free (value);
 
2471
 
 
2472
  g_signal_handlers_block_by_func (config,
 
2473
                                   gimp_prop_path_editor_writable_notify,
 
2474
                                   editor);
 
2475
 
 
2476
  g_object_set (config,
 
2477
                param_spec->name, utf8,
 
2478
                NULL);
 
2479
 
 
2480
  g_signal_handlers_unblock_by_func (config,
 
2481
                                     gimp_prop_path_editor_writable_notify,
 
2482
                                     editor);
 
2483
 
 
2484
  g_free (utf8);
 
2485
}
 
2486
 
 
2487
static void
 
2488
gimp_prop_path_editor_path_notify (GObject        *config,
 
2489
                                   GParamSpec     *param_spec,
 
2490
                                   GimpPathEditor *editor)
 
2491
{
 
2492
  gchar *value;
 
2493
  gchar *filename;
 
2494
 
 
2495
  g_object_get (config,
 
2496
                param_spec->name, &value,
 
2497
                NULL);
 
2498
 
 
2499
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
2500
  g_free (value);
 
2501
 
 
2502
  g_signal_handlers_block_by_func (editor,
 
2503
                                   gimp_prop_path_editor_path_callback,
 
2504
                                   config);
 
2505
 
 
2506
  gimp_path_editor_set_path (editor, filename);
 
2507
 
 
2508
  g_signal_handlers_unblock_by_func (editor,
 
2509
                                     gimp_prop_path_editor_path_callback,
 
2510
                                     config);
 
2511
 
 
2512
  g_free (filename);
 
2513
}
 
2514
 
 
2515
static void
 
2516
gimp_prop_path_editor_writable_notify (GObject        *config,
 
2517
                                       GParamSpec     *param_spec,
 
2518
                                       GimpPathEditor *editor)
 
2519
{
 
2520
  gchar *value;
 
2521
  gchar *filename;
 
2522
 
 
2523
  g_object_get (config,
 
2524
                param_spec->name, &value,
 
2525
                NULL);
 
2526
 
 
2527
  filename = value ? gimp_config_path_expand (value, TRUE, NULL) : NULL;
 
2528
  g_free (value);
 
2529
 
 
2530
  g_signal_handlers_block_by_func (editor,
 
2531
                                   gimp_prop_path_editor_writable_callback,
 
2532
                                   config);
 
2533
 
 
2534
  gimp_path_editor_set_writable_path (editor, filename);
 
2535
 
 
2536
  g_signal_handlers_unblock_by_func (editor,
 
2537
                                     gimp_prop_path_editor_writable_callback,
 
2538
                                     config);
 
2539
 
 
2540
  g_free (filename);
 
2541
}
 
2542
 
 
2543
 
 
2544
/***************/
 
2545
/*  sizeentry  */
 
2546
/***************/
 
2547
 
 
2548
static void   gimp_prop_size_entry_callback    (GimpSizeEntry *sizeentry,
 
2549
                                                GObject       *config);
 
2550
static void   gimp_prop_size_entry_notify      (GObject       *config,
 
2551
                                                GParamSpec    *param_spec,
 
2552
                                                GimpSizeEntry *sizeentry);
 
2553
static void   gimp_prop_size_entry_notify_unit (GObject       *config,
 
2554
                                                GParamSpec    *param_spec,
 
2555
                                                GimpSizeEntry *sizeentry);
 
2556
 
 
2557
 
 
2558
/**
 
2559
 * gimp_prop_size_entry_new:
 
2560
 * @config:             Object to which property is attached.
 
2561
 * @property_name:      Name of int or double property.
 
2562
 * @unit_property_name: Name of unit property.
 
2563
 * @unit_format:        A printf-like unit-format string as is used with
 
2564
 *                      gimp_unit_menu_new().
 
2565
 * @update_policy:      How the automatic pixel <-> real-world-unit
 
2566
 *                      calculations should be done.
 
2567
 * @resolution:         The resolution (in dpi) for the field.
 
2568
 *
 
2569
 * Creates a #GimpSizeEntry to set and display the specified double or
 
2570
 * int property, and its associated unit property.  Note that this
 
2571
 * function is only suitable for creating a size entry holding a
 
2572
 * single value.  Use gimp_prop_coordinates_new() to create a size
 
2573
 * entry holding two values.
 
2574
 *
 
2575
 * Return value:  A new #GimpSizeEntry widget.
 
2576
 *
 
2577
 * Since GIMP 2.4
 
2578
 */
 
2579
GtkWidget *
 
2580
gimp_prop_size_entry_new (GObject                   *config,
 
2581
                          const gchar               *property_name,
 
2582
                          const gchar               *unit_property_name,
 
2583
                          const gchar               *unit_format,
 
2584
                          GimpSizeEntryUpdatePolicy  update_policy,
 
2585
                          gdouble                    resolution)
 
2586
{
 
2587
  GtkWidget  *sizeentry;
 
2588
  GParamSpec *param_spec;
 
2589
  GParamSpec *unit_param_spec;
 
2590
  gboolean    show_pixels;
 
2591
  gdouble     value;
 
2592
  gdouble     lower;
 
2593
  gdouble     upper;
 
2594
  GimpUnit    unit_value;
 
2595
 
 
2596
  param_spec = find_param_spec (config, property_name, G_STRFUNC);
 
2597
  if (! param_spec)
 
2598
    return NULL;
 
2599
 
 
2600
  if (! get_numeric_values (config,
 
2601
                            param_spec, &value, &lower, &upper, G_STRFUNC))
 
2602
    return NULL;
 
2603
 
 
2604
  if (unit_property_name)
 
2605
    {
 
2606
      GValue value = { 0 };
 
2607
 
 
2608
      unit_param_spec = check_param_spec_w (config, unit_property_name,
 
2609
                                            GIMP_TYPE_PARAM_UNIT, G_STRFUNC);
 
2610
      if (! unit_param_spec)
 
2611
        return NULL;
 
2612
 
 
2613
      g_value_init (&value, unit_param_spec->value_type);
 
2614
      g_value_set_int (&value, GIMP_UNIT_PIXEL);
 
2615
      show_pixels =
 
2616
        (g_param_value_validate (unit_param_spec, &value) == FALSE);
 
2617
      g_value_unset (&value);
 
2618
 
 
2619
      g_object_get (config,
 
2620
                    unit_property_name, &unit_value,
 
2621
                    NULL);
 
2622
    }
 
2623
  else
 
2624
    {
 
2625
      unit_param_spec = NULL;
 
2626
      unit_value      = GIMP_UNIT_INCH;
 
2627
      show_pixels     = FALSE;
 
2628
    }
 
2629
 
 
2630
  sizeentry = gimp_size_entry_new (1, unit_value, unit_format,
 
2631
                                   TRUE, FALSE, FALSE,
 
2632
                                   ceil (log (upper) / log (10) + 2),
 
2633
                                   update_policy);
 
2634
  gtk_table_set_col_spacing (GTK_TABLE (sizeentry), 1, 4);
 
2635
 
 
2636
  set_param_spec (NULL,
 
2637
                  gimp_size_entry_get_help_widget (GIMP_SIZE_ENTRY (sizeentry),
 
2638
                                                   0),
 
2639
                  param_spec);
 
2640
 
 
2641
  if (unit_param_spec)
 
2642
    set_param_spec (NULL,
 
2643
                    GIMP_SIZE_ENTRY (sizeentry)->unitmenu, unit_param_spec);
 
2644
 
 
2645
  gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), unit_value);
 
2646
 
 
2647
  if (update_policy == GIMP_SIZE_ENTRY_UPDATE_SIZE)
 
2648
    gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0,
 
2649
                                    resolution, FALSE);
 
2650
 
 
2651
  gimp_size_entry_set_value_boundaries (GIMP_SIZE_ENTRY (sizeentry), 0,
 
2652
                                        lower, upper);
 
2653
 
 
2654
  gimp_size_entry_set_value (GIMP_SIZE_ENTRY (sizeentry), 0, value);
 
2655
 
 
2656
  g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec",
 
2657
                     param_spec);
 
2658
 
 
2659
  g_signal_connect (sizeentry, "value-changed",
 
2660
                    G_CALLBACK (gimp_prop_size_entry_callback),
 
2661
                    config);
 
2662
 
 
2663
  connect_notify (config, property_name,
 
2664
                  G_CALLBACK (gimp_prop_size_entry_notify),
 
2665
                  sizeentry);
 
2666
 
 
2667
  if (unit_property_name)
 
2668
    {
 
2669
      g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-unit",
 
2670
                         unit_param_spec);
 
2671
 
 
2672
      g_signal_connect (sizeentry, "unit-changed",
 
2673
                        G_CALLBACK (gimp_prop_size_entry_callback),
 
2674
                        config);
 
2675
 
 
2676
      connect_notify (config, unit_property_name,
 
2677
                      G_CALLBACK (gimp_prop_size_entry_notify_unit),
 
2678
                      sizeentry);
 
2679
    }
 
2680
 
 
2681
  return sizeentry;
 
2682
}
 
2683
 
 
2684
static void
 
2685
gimp_prop_size_entry_callback (GimpSizeEntry *sizeentry,
 
2686
                               GObject       *config)
 
2687
{
 
2688
  GParamSpec *param_spec;
 
2689
  GParamSpec *unit_param_spec;
 
2690
  gdouble     value;
 
2691
  GimpUnit    unit_value;
 
2692
 
 
2693
  param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
2694
                                  "gimp-config-param-spec");
 
2695
  if (! param_spec)
 
2696
    return;
 
2697
 
 
2698
  unit_param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
2699
                                       "gimp-config-param-spec-unit");
 
2700
 
 
2701
  value      = gimp_size_entry_get_value (sizeentry, 0);
 
2702
  unit_value = gimp_size_entry_get_unit (sizeentry);
 
2703
 
 
2704
  if (unit_param_spec)
 
2705
    {
 
2706
      GimpUnit  old_unit;
 
2707
 
 
2708
      g_object_get (config,
 
2709
                    unit_param_spec->name, &old_unit,
 
2710
                    NULL);
 
2711
 
 
2712
      if (unit_value == old_unit)
 
2713
        unit_param_spec = NULL;
 
2714
    }
 
2715
 
 
2716
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
2717
    {
 
2718
      g_object_set (config,
 
2719
                    param_spec->name, ROUND (value),
 
2720
 
 
2721
                    unit_param_spec ?
 
2722
                    unit_param_spec->name : NULL, unit_value,
 
2723
 
 
2724
                    NULL);
 
2725
    }
 
2726
  else if (G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
2727
    {
 
2728
      g_object_set (config,
 
2729
                    param_spec->name, value,
 
2730
 
 
2731
                    unit_param_spec ?
 
2732
                    unit_param_spec->name : NULL, unit_value,
 
2733
 
 
2734
                    NULL);
 
2735
    }
 
2736
}
 
2737
 
 
2738
static void
 
2739
gimp_prop_size_entry_notify (GObject       *config,
 
2740
                             GParamSpec    *param_spec,
 
2741
                             GimpSizeEntry *sizeentry)
 
2742
{
 
2743
  gdouble value;
 
2744
 
 
2745
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
2746
    {
 
2747
      gint int_value;
 
2748
 
 
2749
      g_object_get (config,
 
2750
                    param_spec->name, &int_value,
 
2751
                    NULL);
 
2752
 
 
2753
      value = int_value;
 
2754
    }
 
2755
  else
 
2756
    {
 
2757
      g_object_get (config,
 
2758
                    param_spec->name, &value,
 
2759
                    NULL);
 
2760
    }
 
2761
 
 
2762
  if (value != gimp_size_entry_get_value (sizeentry, 0))
 
2763
    {
 
2764
      g_signal_handlers_block_by_func (sizeentry,
 
2765
                                       gimp_prop_size_entry_callback,
 
2766
                                       config);
 
2767
 
 
2768
      gimp_size_entry_set_value (sizeentry, 0, value);
 
2769
 
 
2770
      g_signal_handlers_unblock_by_func (sizeentry,
 
2771
                                         gimp_prop_size_entry_callback,
 
2772
                                         config);
 
2773
    }
 
2774
}
 
2775
 
 
2776
static void
 
2777
gimp_prop_size_entry_notify_unit (GObject       *config,
 
2778
                                  GParamSpec    *param_spec,
 
2779
                                  GimpSizeEntry *sizeentry)
 
2780
{
 
2781
  GimpUnit value;
 
2782
 
 
2783
  g_object_get (config,
 
2784
                param_spec->name, &value,
 
2785
                NULL);
 
2786
 
 
2787
  if (value != gimp_size_entry_get_unit (sizeentry))
 
2788
    {
 
2789
      g_signal_handlers_block_by_func (sizeentry,
 
2790
                                       gimp_prop_size_entry_callback,
 
2791
                                       config);
 
2792
 
 
2793
      gimp_size_entry_set_unit (sizeentry, value);
 
2794
 
 
2795
      g_signal_handlers_unblock_by_func (sizeentry,
 
2796
                                         gimp_prop_size_entry_callback,
 
2797
                                         config);
 
2798
    }
 
2799
}
 
2800
 
 
2801
 
 
2802
/*****************/
 
2803
/*  coordinates  */
 
2804
/*****************/
 
2805
 
 
2806
static void   gimp_prop_coordinates_callback    (GimpSizeEntry *sizeentry,
 
2807
                                                 GObject       *config);
 
2808
static void   gimp_prop_coordinates_notify_x    (GObject       *config,
 
2809
                                                 GParamSpec    *param_spec,
 
2810
                                                 GimpSizeEntry *sizeentry);
 
2811
static void   gimp_prop_coordinates_notify_y    (GObject       *config,
 
2812
                                                 GParamSpec    *param_spec,
 
2813
                                                 GimpSizeEntry *sizeentry);
 
2814
static void   gimp_prop_coordinates_notify_unit (GObject       *config,
 
2815
                                                 GParamSpec    *param_spec,
 
2816
                                                 GimpSizeEntry *sizeentry);
 
2817
 
 
2818
 
 
2819
/**
 
2820
 * gimp_prop_coordinates_new:
 
2821
 * @config:             Object to which property is attached.
 
2822
 * @x_property_name:    Name of int or double property for X coordinate.
 
2823
 * @y_property_name:    Name of int or double property for Y coordinate.
 
2824
 * @unit_property_name: Name of unit property.
 
2825
 * @unit_format:        A printf-like unit-format string as is used with
 
2826
 *                      gimp_unit_menu_new().
 
2827
 * @update_policy:      How the automatic pixel <-> real-world-unit
 
2828
 *                      calculations should be done.
 
2829
 * @xresolution:        The resolution (in dpi) for the X coordinate.
 
2830
 * @yresolution:        The resolution (in dpi) for the Y coordinate.
 
2831
 * @has_chainbutton:    Whether to add a chainbutton to the size entry.
 
2832
 *
 
2833
 * Creates a #GimpSizeEntry to set and display two double or int
 
2834
 * properties, which will usually represent X and Y coordinates, and
 
2835
 * their associated unit property.
 
2836
 *
 
2837
 * Return value:  A new #GimpSizeEntry widget.
 
2838
 *
 
2839
 * Since GIMP 2.4
 
2840
 */
 
2841
GtkWidget *
 
2842
gimp_prop_coordinates_new (GObject                   *config,
 
2843
                           const gchar               *x_property_name,
 
2844
                           const gchar               *y_property_name,
 
2845
                           const gchar               *unit_property_name,
 
2846
                           const gchar               *unit_format,
 
2847
                           GimpSizeEntryUpdatePolicy  update_policy,
 
2848
                           gdouble                    xresolution,
 
2849
                           gdouble                    yresolution,
 
2850
                           gboolean                   has_chainbutton)
 
2851
{
 
2852
  GtkWidget *sizeentry;
 
2853
  GtkWidget *chainbutton = NULL;
 
2854
 
 
2855
  sizeentry = gimp_size_entry_new (2, GIMP_UNIT_INCH, unit_format,
 
2856
                                   FALSE, FALSE, TRUE, 10,
 
2857
                                   update_policy);
 
2858
 
 
2859
  if (has_chainbutton)
 
2860
    {
 
2861
      chainbutton = gimp_chain_button_new (GIMP_CHAIN_BOTTOM);
 
2862
      gtk_table_attach_defaults (GTK_TABLE (sizeentry), chainbutton,
 
2863
                                 1, 3, 3, 4);
 
2864
      gtk_widget_show (chainbutton);
 
2865
    }
 
2866
 
 
2867
  if (! gimp_prop_coordinates_connect (config,
 
2868
                                       x_property_name,
 
2869
                                       y_property_name,
 
2870
                                       unit_property_name,
 
2871
                                       sizeentry,
 
2872
                                       chainbutton,
 
2873
                                       xresolution,
 
2874
                                       yresolution))
 
2875
    {
 
2876
      gtk_widget_destroy (sizeentry);
 
2877
      return NULL;
 
2878
    }
 
2879
 
 
2880
  return sizeentry;
 
2881
}
 
2882
 
 
2883
gboolean
 
2884
gimp_prop_coordinates_connect (GObject     *config,
 
2885
                               const gchar *x_property_name,
 
2886
                               const gchar *y_property_name,
 
2887
                               const gchar *unit_property_name,
 
2888
                               GtkWidget   *sizeentry,
 
2889
                               GtkWidget   *chainbutton,
 
2890
                               gdouble      xresolution,
 
2891
                               gdouble      yresolution)
 
2892
{
 
2893
  GParamSpec *x_param_spec;
 
2894
  GParamSpec *y_param_spec;
 
2895
  GParamSpec *unit_param_spec;
 
2896
  gdouble     x_value, x_lower, x_upper;
 
2897
  gdouble     y_value, y_lower, y_upper;
 
2898
  GimpUnit    unit_value;
 
2899
  gdouble    *old_x_value;
 
2900
  gdouble    *old_y_value;
 
2901
  GimpUnit   *old_unit_value;
 
2902
  gboolean    chain_checked;
 
2903
 
 
2904
  g_return_val_if_fail (GIMP_IS_SIZE_ENTRY (sizeentry), FALSE);
 
2905
  g_return_val_if_fail (GIMP_SIZE_ENTRY (sizeentry)->number_of_fields == 2,
 
2906
                        FALSE);
 
2907
  g_return_val_if_fail (chainbutton == NULL ||
 
2908
                        GIMP_IS_CHAIN_BUTTON (chainbutton), FALSE);
 
2909
 
 
2910
  x_param_spec = find_param_spec (config, x_property_name, G_STRFUNC);
 
2911
  if (! x_param_spec)
 
2912
    return FALSE;
 
2913
 
 
2914
  y_param_spec = find_param_spec (config, y_property_name, G_STRFUNC);
 
2915
  if (! y_param_spec)
 
2916
    return FALSE;
 
2917
 
 
2918
  if (! get_numeric_values (config, x_param_spec,
 
2919
                            &x_value, &x_lower, &x_upper, G_STRFUNC) ||
 
2920
      ! get_numeric_values (config, y_param_spec,
 
2921
                            &y_value, &y_lower, &y_upper, G_STRFUNC))
 
2922
    return FALSE;
 
2923
 
 
2924
  if (unit_property_name)
 
2925
    {
 
2926
      unit_param_spec = check_param_spec_w (config, unit_property_name,
 
2927
                                            GIMP_TYPE_PARAM_UNIT, G_STRFUNC);
 
2928
      if (! unit_param_spec)
 
2929
        return FALSE;
 
2930
 
 
2931
      g_object_get (config,
 
2932
                    unit_property_name, &unit_value,
 
2933
                    NULL);
 
2934
    }
 
2935
  else
 
2936
    {
 
2937
      unit_param_spec = NULL;
 
2938
      unit_value      = GIMP_UNIT_INCH;
 
2939
    }
 
2940
 
 
2941
  set_param_spec (NULL,
 
2942
                  gimp_size_entry_get_help_widget (GIMP_SIZE_ENTRY (sizeentry),
 
2943
                                                   0),
 
2944
                  x_param_spec);
 
2945
  set_param_spec (NULL,
 
2946
                  gimp_size_entry_get_help_widget (GIMP_SIZE_ENTRY (sizeentry),
 
2947
                                                   1),
 
2948
                  y_param_spec);
 
2949
 
 
2950
  if (unit_param_spec)
 
2951
    set_param_spec (NULL,
 
2952
                    GIMP_SIZE_ENTRY (sizeentry)->unitmenu, unit_param_spec);
 
2953
 
 
2954
  gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), unit_value);
 
2955
 
 
2956
  switch (GIMP_SIZE_ENTRY (sizeentry)->update_policy)
 
2957
    {
 
2958
    case GIMP_SIZE_ENTRY_UPDATE_SIZE:
 
2959
      gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0,
 
2960
                                      xresolution, FALSE);
 
2961
      gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 1,
 
2962
                                      yresolution, FALSE);
 
2963
      chain_checked = (ABS (x_value - y_value) < 1);
 
2964
      break;
 
2965
 
 
2966
    case GIMP_SIZE_ENTRY_UPDATE_RESOLUTION:
 
2967
      chain_checked = (ABS (x_value - y_value) < GIMP_MIN_RESOLUTION);
 
2968
      break;
 
2969
 
 
2970
    default:
 
2971
      chain_checked = (x_value == y_value);
 
2972
      break;
 
2973
    }
 
2974
 
 
2975
  gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 0,
 
2976
                                         x_lower, x_upper);
 
2977
  gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 1,
 
2978
                                         y_lower, y_upper);
 
2979
 
 
2980
  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 0, x_value);
 
2981
  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 1, y_value);
 
2982
 
 
2983
  g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-x",
 
2984
                     x_param_spec);
 
2985
  g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-y",
 
2986
                     y_param_spec);
 
2987
 
 
2988
  old_x_value  = g_new0 (gdouble, 1);
 
2989
  *old_x_value = x_value;
 
2990
  g_object_set_data_full (G_OBJECT (sizeentry), "old-x-value",
 
2991
                          old_x_value,
 
2992
                          (GDestroyNotify) g_free);
 
2993
 
 
2994
  old_y_value  = g_new0 (gdouble, 1);
 
2995
  *old_y_value = y_value;
 
2996
  g_object_set_data_full (G_OBJECT (sizeentry), "old-y-value",
 
2997
                          old_y_value,
 
2998
                          (GDestroyNotify) g_free);
 
2999
 
 
3000
  if (chainbutton)
 
3001
    {
 
3002
      if (chain_checked)
 
3003
        gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chainbutton), TRUE);
 
3004
 
 
3005
      g_object_set_data (G_OBJECT (sizeentry), "chainbutton", chainbutton);
 
3006
    }
 
3007
 
 
3008
  g_signal_connect (sizeentry, "value-changed",
 
3009
                    G_CALLBACK (gimp_prop_coordinates_callback),
 
3010
                    config);
 
3011
  g_signal_connect (sizeentry, "refval-changed",
 
3012
                    G_CALLBACK (gimp_prop_coordinates_callback),
 
3013
                    config);
 
3014
 
 
3015
  connect_notify (config, x_property_name,
 
3016
                  G_CALLBACK (gimp_prop_coordinates_notify_x),
 
3017
                  sizeentry);
 
3018
  connect_notify (config, y_property_name,
 
3019
                  G_CALLBACK (gimp_prop_coordinates_notify_y),
 
3020
                  sizeentry);
 
3021
 
 
3022
  if (unit_property_name)
 
3023
    {
 
3024
      g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-unit",
 
3025
                         unit_param_spec);
 
3026
 
 
3027
      old_unit_value  = g_new0 (GimpUnit, 1);
 
3028
      *old_unit_value = unit_value;
 
3029
      g_object_set_data_full (G_OBJECT (sizeentry), "old-unit-value",
 
3030
                              old_unit_value,
 
3031
                              (GDestroyNotify) g_free);
 
3032
 
 
3033
      g_signal_connect (sizeentry, "unit-changed",
 
3034
                        G_CALLBACK (gimp_prop_coordinates_callback),
 
3035
                        config);
 
3036
 
 
3037
      connect_notify (config, unit_property_name,
 
3038
                      G_CALLBACK (gimp_prop_coordinates_notify_unit),
 
3039
                      sizeentry);
 
3040
    }
 
3041
 
 
3042
  return TRUE;
 
3043
}
 
3044
 
 
3045
static void
 
3046
gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry,
 
3047
                                GObject       *config)
 
3048
{
 
3049
  GParamSpec *x_param_spec;
 
3050
  GParamSpec *y_param_spec;
 
3051
  GParamSpec *unit_param_spec;
 
3052
  gdouble     x_value;
 
3053
  gdouble     y_value;
 
3054
  GimpUnit    unit_value;
 
3055
  gdouble    *old_x_value;
 
3056
  gdouble    *old_y_value;
 
3057
  GimpUnit   *old_unit_value;
 
3058
  gboolean    backwards;
 
3059
 
 
3060
  x_param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
3061
                                    "gimp-config-param-spec-x");
 
3062
  y_param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
3063
                                    "gimp-config-param-spec-y");
 
3064
 
 
3065
  if (! x_param_spec || ! y_param_spec)
 
3066
    return;
 
3067
 
 
3068
  unit_param_spec = g_object_get_data (G_OBJECT (sizeentry),
 
3069
                                       "gimp-config-param-spec-unit");
 
3070
 
 
3071
  x_value    = gimp_size_entry_get_refval (sizeentry, 0);
 
3072
  y_value    = gimp_size_entry_get_refval (sizeentry, 1);
 
3073
  unit_value = gimp_size_entry_get_unit (sizeentry);
 
3074
 
 
3075
  old_x_value    = g_object_get_data (G_OBJECT (sizeentry), "old-x-value");
 
3076
  old_y_value    = g_object_get_data (G_OBJECT (sizeentry), "old-y-value");
 
3077
  old_unit_value = g_object_get_data (G_OBJECT (sizeentry), "old-unit-value");
 
3078
 
 
3079
  if (! old_x_value || ! old_y_value || (unit_param_spec && ! old_unit_value))
 
3080
    return;
 
3081
 
 
3082
  /*
 
3083
   * FIXME: if the entry was created using gimp_coordinates_new, then
 
3084
   * the chain button is handled automatically and the following block
 
3085
   * of code is unnecessary (and, in fact, redundant).
 
3086
   */
 
3087
  if (x_value != y_value)
 
3088
    {
 
3089
      GtkWidget *chainbutton;
 
3090
 
 
3091
      chainbutton = g_object_get_data (G_OBJECT (sizeentry), "chainbutton");
 
3092
 
 
3093
      if (chainbutton &&
 
3094
          gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chainbutton)) &&
 
3095
          ! g_object_get_data (G_OBJECT (chainbutton), "constrains-ratio"))
 
3096
        {
 
3097
          if (x_value != *old_x_value)
 
3098
            y_value = x_value;
 
3099
          else if (y_value != *old_y_value)
 
3100
            x_value = y_value;
 
3101
        }
 
3102
    }
 
3103
 
 
3104
  backwards = (*old_x_value == x_value);
 
3105
 
 
3106
  if (*old_x_value == x_value &&
 
3107
      *old_y_value == y_value &&
 
3108
      (old_unit_value == NULL || *old_unit_value == unit_value))
 
3109
    return;
 
3110
 
 
3111
  *old_x_value = x_value;
 
3112
  *old_y_value = y_value;
 
3113
 
 
3114
  if (old_unit_value)
 
3115
    *old_unit_value = unit_value;
 
3116
 
 
3117
  if (unit_param_spec)
 
3118
    g_object_set (config,
 
3119
                  unit_param_spec->name, unit_value,
 
3120
                  NULL);
 
3121
 
 
3122
  if (G_IS_PARAM_SPEC_INT (x_param_spec) &&
 
3123
      G_IS_PARAM_SPEC_INT (y_param_spec))
 
3124
    {
 
3125
      if (backwards)
 
3126
        g_object_set (config,
 
3127
                      y_param_spec->name, ROUND (y_value),
 
3128
                      x_param_spec->name, ROUND (x_value),
 
3129
                      NULL);
 
3130
      else
 
3131
        g_object_set (config,
 
3132
                      x_param_spec->name, ROUND (x_value),
 
3133
                      y_param_spec->name, ROUND (y_value),
 
3134
                      NULL);
 
3135
 
 
3136
    }
 
3137
  else if (G_IS_PARAM_SPEC_DOUBLE (x_param_spec) &&
 
3138
           G_IS_PARAM_SPEC_DOUBLE (y_param_spec))
 
3139
    {
 
3140
      if (backwards)
 
3141
        g_object_set (config,
 
3142
                      y_param_spec->name, y_value,
 
3143
                      x_param_spec->name, x_value,
 
3144
                      NULL);
 
3145
      else
 
3146
        g_object_set (config,
 
3147
                      x_param_spec->name, x_value,
 
3148
                      y_param_spec->name, y_value,
 
3149
                      NULL);
 
3150
    }
 
3151
}
 
3152
 
 
3153
static void
 
3154
gimp_prop_coordinates_notify_x (GObject       *config,
 
3155
                                GParamSpec    *param_spec,
 
3156
                                GimpSizeEntry *sizeentry)
 
3157
{
 
3158
  gdouble value;
 
3159
 
 
3160
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
3161
    {
 
3162
      gint int_value;
 
3163
 
 
3164
      g_object_get (config,
 
3165
                    param_spec->name, &int_value,
 
3166
                    NULL);
 
3167
 
 
3168
      value = int_value;
 
3169
    }
 
3170
  else
 
3171
    {
 
3172
      g_object_get (config,
 
3173
                    param_spec->name, &value,
 
3174
                    NULL);
 
3175
    }
 
3176
 
 
3177
  if (value != gimp_size_entry_get_refval (sizeentry, 0))
 
3178
    {
 
3179
      g_signal_handlers_block_by_func (sizeentry,
 
3180
                                       gimp_prop_coordinates_callback,
 
3181
                                       config);
 
3182
 
 
3183
      gimp_size_entry_set_refval (sizeentry, 0, value);
 
3184
 
 
3185
      g_signal_handlers_unblock_by_func (sizeentry,
 
3186
                                         gimp_prop_coordinates_callback,
 
3187
                                         config);
 
3188
    }
 
3189
}
 
3190
 
 
3191
static void
 
3192
gimp_prop_coordinates_notify_y (GObject       *config,
 
3193
                                GParamSpec    *param_spec,
 
3194
                                GimpSizeEntry *sizeentry)
 
3195
{
 
3196
  gdouble value;
 
3197
 
 
3198
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
3199
    {
 
3200
      gint int_value;
 
3201
 
 
3202
      g_object_get (config,
 
3203
                    param_spec->name, &int_value,
 
3204
                    NULL);
 
3205
 
 
3206
      value = int_value;
 
3207
    }
 
3208
  else
 
3209
    {
 
3210
      g_object_get (config,
 
3211
                    param_spec->name, &value,
 
3212
                    NULL);
 
3213
    }
 
3214
 
 
3215
  if (value != gimp_size_entry_get_refval (sizeentry, 1))
 
3216
    {
 
3217
      g_signal_handlers_block_by_func (sizeentry,
 
3218
                                       gimp_prop_coordinates_callback,
 
3219
                                       config);
 
3220
 
 
3221
      gimp_size_entry_set_refval (sizeentry, 1, value);
 
3222
 
 
3223
      g_signal_handlers_unblock_by_func (sizeentry,
 
3224
                                         gimp_prop_coordinates_callback,
 
3225
                                         config);
 
3226
    }
 
3227
}
 
3228
 
 
3229
static void
 
3230
gimp_prop_coordinates_notify_unit (GObject       *config,
 
3231
                                   GParamSpec    *param_spec,
 
3232
                                   GimpSizeEntry *sizeentry)
 
3233
{
 
3234
  GimpUnit value;
 
3235
 
 
3236
  g_object_get (config,
 
3237
                param_spec->name, &value,
 
3238
                NULL);
 
3239
 
 
3240
  if (value != gimp_size_entry_get_unit (sizeentry))
 
3241
    {
 
3242
      g_signal_handlers_block_by_func (sizeentry,
 
3243
                                       gimp_prop_coordinates_callback,
 
3244
                                       config);
 
3245
 
 
3246
      gimp_size_entry_set_unit (sizeentry, value);
 
3247
 
 
3248
      g_signal_handlers_unblock_by_func (sizeentry,
 
3249
                                         gimp_prop_coordinates_callback,
 
3250
                                         config);
 
3251
    }
 
3252
}
 
3253
 
 
3254
 
 
3255
/****************/
 
3256
/*  color area  */
 
3257
/****************/
 
3258
 
 
3259
static void   gimp_prop_color_area_callback (GtkWidget  *widget,
 
3260
                                             GObject    *config);
 
3261
static void   gimp_prop_color_area_notify   (GObject    *config,
 
3262
                                             GParamSpec *param_spec,
 
3263
                                             GtkWidget  *area);
 
3264
 
 
3265
/**
 
3266
 * gimp_prop_color_area_new:
 
3267
 * @config:        Object to which property is attached.
 
3268
 * @property_name: Name of RGB property.
 
3269
 * @width:         Width of color area.
 
3270
 * @height:        Height of color area.
 
3271
 * @type:          How transparency is represented.
 
3272
 *
 
3273
 * Creates a #GimpColorArea to set and display the value of an RGB
 
3274
 * property.
 
3275
 *
 
3276
 * Return value:  A new #GimpColorArea widget.
 
3277
 *
 
3278
 * Since GIMP 2.4
 
3279
 */
 
3280
GtkWidget *
 
3281
gimp_prop_color_area_new (GObject           *config,
 
3282
                          const gchar       *property_name,
 
3283
                          gint               width,
 
3284
                          gint               height,
 
3285
                          GimpColorAreaType  type)
 
3286
{
 
3287
  GParamSpec *param_spec;
 
3288
  GtkWidget  *area;
 
3289
  GimpRGB    *value;
 
3290
 
 
3291
  param_spec = check_param_spec_w (config, property_name,
 
3292
                                   GIMP_TYPE_PARAM_RGB, G_STRFUNC);
 
3293
  if (! param_spec)
 
3294
    return NULL;
 
3295
 
 
3296
  g_object_get (config,
 
3297
                property_name, &value,
 
3298
                NULL);
 
3299
 
 
3300
  area = gimp_color_area_new (value, type,
 
3301
                              GDK_BUTTON1_MASK | GDK_BUTTON2_MASK);
 
3302
  gtk_widget_set_size_request (area, width, height);
 
3303
 
 
3304
  g_free (value);
 
3305
 
 
3306
  set_param_spec (G_OBJECT (area), area, param_spec);
 
3307
 
 
3308
  g_signal_connect (area, "color-changed",
 
3309
                    G_CALLBACK (gimp_prop_color_area_callback),
 
3310
                    config);
 
3311
 
 
3312
  connect_notify (config, property_name,
 
3313
                  G_CALLBACK (gimp_prop_color_area_notify),
 
3314
                  area);
 
3315
 
 
3316
  return area;
 
3317
}
 
3318
 
 
3319
static void
 
3320
gimp_prop_color_area_callback (GtkWidget *area,
 
3321
                               GObject   *config)
 
3322
{
 
3323
  GParamSpec *param_spec;
 
3324
  GimpRGB     value;
 
3325
 
 
3326
  param_spec = get_param_spec (G_OBJECT (area));
 
3327
  if (! param_spec)
 
3328
    return;
 
3329
 
 
3330
  gimp_color_area_get_color (GIMP_COLOR_AREA (area), &value);
 
3331
 
 
3332
  g_signal_handlers_block_by_func (config,
 
3333
                                   gimp_prop_color_area_notify,
 
3334
                                   area);
 
3335
 
 
3336
  g_object_set (config,
 
3337
                param_spec->name, &value,
 
3338
                NULL);
 
3339
 
 
3340
  g_signal_handlers_unblock_by_func (config,
 
3341
                                     gimp_prop_color_area_notify,
 
3342
                                     area);
 
3343
}
 
3344
 
 
3345
static void
 
3346
gimp_prop_color_area_notify (GObject    *config,
 
3347
                             GParamSpec *param_spec,
 
3348
                             GtkWidget  *area)
 
3349
{
 
3350
  GimpRGB *value;
 
3351
 
 
3352
  g_object_get (config,
 
3353
                param_spec->name, &value,
 
3354
                NULL);
 
3355
 
 
3356
  g_signal_handlers_block_by_func (area,
 
3357
                                   gimp_prop_color_area_callback,
 
3358
                                   config);
 
3359
 
 
3360
  gimp_color_area_set_color (GIMP_COLOR_AREA (area), value);
 
3361
 
 
3362
  g_free (value);
 
3363
 
 
3364
  g_signal_handlers_unblock_by_func (area,
 
3365
                                     gimp_prop_color_area_callback,
 
3366
                                     config);
 
3367
}
 
3368
 
 
3369
 
 
3370
/***************/
 
3371
/*  unit menu  */
 
3372
/***************/
 
3373
 
 
3374
static void   gimp_prop_unit_menu_callback (GtkWidget  *menu,
 
3375
                                            GObject    *config);
 
3376
static void   gimp_prop_unit_menu_notify   (GObject    *config,
 
3377
                                            GParamSpec *param_spec,
 
3378
                                            GtkWidget  *menu);
 
3379
 
 
3380
/**
 
3381
 * gimp_prop_unit_menu_new:
 
3382
 * @config:        Object to which property is attached.
 
3383
 * @property_name: Name of Unit property.
 
3384
 * @unit_format:   A printf-like format string which is used to create
 
3385
 *                 the unit strings.
 
3386
 *
 
3387
 * Creates a #GimpUnitMenu to set and display the value of a Unit
 
3388
 * property.  See gimp_unit_menu_new() for more information.
 
3389
 *
 
3390
 * Return value:  A new #GimpUnitMenu widget.
 
3391
 *
 
3392
 * Since GIMP 2.4
 
3393
 */
 
3394
GtkWidget *
 
3395
gimp_prop_unit_menu_new (GObject     *config,
 
3396
                         const gchar *property_name,
 
3397
                         const gchar *unit_format)
 
3398
{
 
3399
  GParamSpec *param_spec;
 
3400
  GtkWidget  *menu;
 
3401
  GimpUnit    unit;
 
3402
  GValue      value = { 0, };
 
3403
  gboolean    show_pixels;
 
3404
  gboolean    show_percent;
 
3405
 
 
3406
  param_spec = check_param_spec_w (config, property_name,
 
3407
                                   GIMP_TYPE_PARAM_UNIT, G_STRFUNC);
 
3408
  if (! param_spec)
 
3409
    return NULL;
 
3410
 
 
3411
  g_value_init (&value, param_spec->value_type);
 
3412
 
 
3413
  g_value_set_int (&value, GIMP_UNIT_PIXEL);
 
3414
  show_pixels = (g_param_value_validate (param_spec, &value) == FALSE);
 
3415
 
 
3416
  g_value_set_int (&value, GIMP_UNIT_PERCENT);
 
3417
  show_percent = (g_param_value_validate (param_spec, &value) == FALSE);
 
3418
 
 
3419
  g_value_unset (&value);
 
3420
 
 
3421
  g_object_get (config,
 
3422
                property_name, &unit,
 
3423
                NULL);
 
3424
 
 
3425
  menu = gimp_unit_menu_new (unit_format,
 
3426
                             unit, show_pixels, show_percent, TRUE);
 
3427
 
 
3428
  set_param_spec (G_OBJECT (menu), menu, param_spec);
 
3429
 
 
3430
  g_signal_connect (menu, "unit-changed",
 
3431
                    G_CALLBACK (gimp_prop_unit_menu_callback),
 
3432
                    config);
 
3433
 
 
3434
  connect_notify (config, property_name,
 
3435
                  G_CALLBACK (gimp_prop_unit_menu_notify),
 
3436
                  menu);
 
3437
 
 
3438
  return menu;
 
3439
}
 
3440
 
 
3441
static void
 
3442
gimp_prop_unit_menu_callback (GtkWidget *menu,
 
3443
                              GObject   *config)
 
3444
{
 
3445
  GParamSpec *param_spec;
 
3446
  GimpUnit    unit;
 
3447
 
 
3448
  param_spec = get_param_spec (G_OBJECT (menu));
 
3449
  if (! param_spec)
 
3450
    return;
 
3451
 
 
3452
  gimp_unit_menu_update (menu, &unit);
 
3453
 
 
3454
  g_signal_handlers_block_by_func (config,
 
3455
                                   gimp_prop_unit_menu_notify,
 
3456
                                   menu);
 
3457
 
 
3458
  g_object_set (config,
 
3459
                param_spec->name, unit,
 
3460
                NULL);
 
3461
 
 
3462
  g_signal_handlers_unblock_by_func (config,
 
3463
                                     gimp_prop_unit_menu_notify,
 
3464
                                     menu);
 
3465
}
 
3466
 
 
3467
static void
 
3468
gimp_prop_unit_menu_notify (GObject    *config,
 
3469
                            GParamSpec *param_spec,
 
3470
                            GtkWidget  *menu)
 
3471
{
 
3472
  GimpUnit  unit;
 
3473
 
 
3474
  g_object_get (config,
 
3475
                param_spec->name, &unit,
 
3476
                NULL);
 
3477
 
 
3478
  g_signal_handlers_block_by_func (menu,
 
3479
                                   gimp_prop_unit_menu_callback,
 
3480
                                   config);
 
3481
 
 
3482
  gimp_unit_menu_set_unit (GIMP_UNIT_MENU (menu), unit);
 
3483
  gimp_unit_menu_update (menu, &unit);
 
3484
 
 
3485
  g_signal_handlers_unblock_by_func (menu,
 
3486
                                     gimp_prop_unit_menu_callback,
 
3487
                                     config);
 
3488
}
 
3489
 
 
3490
 
 
3491
/*****************/
 
3492
/*  stock image  */
 
3493
/*****************/
 
3494
 
 
3495
static void   gimp_prop_stock_image_notify (GObject    *config,
 
3496
                                            GParamSpec *param_spec,
 
3497
                                            GtkWidget  *image);
 
3498
 
 
3499
/**
 
3500
 * gimp_prop_stock_image_new:
 
3501
 * @config:        Object to which property is attached.
 
3502
 * @property_name: Name of string property.
 
3503
 * @icon_size:     Size of desired stock image.
 
3504
 *
 
3505
 * Creates a widget to display a stock image representing the value of the
 
3506
 * specified string property, which should encode a Stock ID.
 
3507
 * See gtk_image_new_from_stock() for more information.
 
3508
 *
 
3509
 * Return value:  A new #GtkImage widget.
 
3510
 *
 
3511
 * Since GIMP 2.4
 
3512
 */
 
3513
GtkWidget *
 
3514
gimp_prop_stock_image_new (GObject     *config,
 
3515
                           const gchar *property_name,
 
3516
                           GtkIconSize  icon_size)
 
3517
{
 
3518
  GParamSpec *param_spec;
 
3519
  GtkWidget  *image;
 
3520
  gchar      *stock_id;
 
3521
 
 
3522
  param_spec = check_param_spec (config, property_name,
 
3523
                                 G_TYPE_PARAM_STRING, G_STRFUNC);
 
3524
  if (! param_spec)
 
3525
    return NULL;
 
3526
 
 
3527
  g_object_get (config,
 
3528
                property_name, &stock_id,
 
3529
                NULL);
 
3530
 
 
3531
  image = gtk_image_new_from_stock (stock_id, icon_size);
 
3532
 
 
3533
  if (stock_id)
 
3534
    g_free (stock_id);
 
3535
 
 
3536
  set_param_spec (G_OBJECT (image), image, param_spec);
 
3537
 
 
3538
  connect_notify (config, property_name,
 
3539
                  G_CALLBACK (gimp_prop_stock_image_notify),
 
3540
                  image);
 
3541
 
 
3542
  return image;
 
3543
}
 
3544
 
 
3545
static void
 
3546
gimp_prop_stock_image_notify (GObject    *config,
 
3547
                              GParamSpec *param_spec,
 
3548
                              GtkWidget  *image)
 
3549
{
 
3550
  gchar *stock_id;
 
3551
 
 
3552
  g_object_get (config,
 
3553
                param_spec->name, &stock_id,
 
3554
                NULL);
 
3555
 
 
3556
  gtk_image_set_from_stock (GTK_IMAGE (image), stock_id,
 
3557
                            GTK_IMAGE (image)->icon_size);
 
3558
 
 
3559
  if (stock_id)
 
3560
    g_free (stock_id);
 
3561
}
 
3562
 
 
3563
 
 
3564
/**************/
 
3565
/*  expander  */
 
3566
/**************/
 
3567
 
 
3568
static void   gimp_prop_expanded_notify (GtkExpander *expander,
 
3569
                                         GParamSpec  *param_spec,
 
3570
                                         GObject     *config);
 
3571
static void   gimp_prop_expander_notify (GObject     *config,
 
3572
                                         GParamSpec  *param_spec,
 
3573
                                         GtkExpander *expander);
 
3574
 
 
3575
 
 
3576
/**
 
3577
 * gimp_prop_expander_new:
 
3578
 * @config:        Object to which property is attached.
 
3579
 * @property_name: Name of boolean property.
 
3580
 * @label:         Label for expander.
 
3581
 *
 
3582
 * Creates a #GtkExpander controlled by the specified boolean property.
 
3583
 * A value of %TRUE for the property corresponds to the expanded state
 
3584
 * for the widget.
 
3585
 *
 
3586
 * Return value:  A new #GtkExpander widget.
 
3587
 *
 
3588
 * Since GIMP 2.4
 
3589
 */
 
3590
GtkWidget *
 
3591
gimp_prop_expander_new (GObject     *config,
 
3592
                        const gchar *property_name,
 
3593
                        const gchar *label)
 
3594
{
 
3595
  GParamSpec *param_spec;
 
3596
  GtkWidget  *expander;
 
3597
  gboolean    value;
 
3598
 
 
3599
  param_spec = check_param_spec_w (config, property_name,
 
3600
                                   G_TYPE_PARAM_BOOLEAN, G_STRFUNC);
 
3601
  if (! param_spec)
 
3602
    return NULL;
 
3603
 
 
3604
  g_object_get (config,
 
3605
                property_name, &value,
 
3606
                NULL);
 
3607
 
 
3608
  expander = g_object_new (GTK_TYPE_EXPANDER,
 
3609
                           "label",    label,
 
3610
                           "expanded", value,
 
3611
                           NULL);
 
3612
 
 
3613
  set_param_spec (G_OBJECT (expander), expander, param_spec);
 
3614
 
 
3615
  g_signal_connect (expander, "notify::expanded",
 
3616
                    G_CALLBACK (gimp_prop_expanded_notify),
 
3617
                    config);
 
3618
 
 
3619
  connect_notify (config, property_name,
 
3620
                  G_CALLBACK (gimp_prop_expander_notify),
 
3621
                  expander);
 
3622
 
 
3623
  return expander;
 
3624
}
 
3625
 
 
3626
static void
 
3627
gimp_prop_expanded_notify (GtkExpander *expander,
 
3628
                           GParamSpec  *param_spec,
 
3629
                           GObject     *config)
 
3630
{
 
3631
  param_spec = get_param_spec (G_OBJECT (expander));
 
3632
  if (! param_spec)
 
3633
    return;
 
3634
 
 
3635
  g_object_set (config,
 
3636
                param_spec->name, gtk_expander_get_expanded (expander),
 
3637
                NULL);
 
3638
}
 
3639
 
 
3640
static void
 
3641
gimp_prop_expander_notify (GObject     *config,
 
3642
                           GParamSpec  *param_spec,
 
3643
                           GtkExpander *expander)
 
3644
{
 
3645
  gboolean value;
 
3646
 
 
3647
  g_object_get (config,
 
3648
                param_spec->name, &value,
 
3649
                NULL);
 
3650
 
 
3651
  if (gtk_expander_get_expanded (expander) != value)
 
3652
    {
 
3653
      g_signal_handlers_block_by_func (expander,
 
3654
                                       gimp_prop_expanded_notify,
 
3655
                                       config);
 
3656
 
 
3657
      gtk_expander_set_expanded (expander, value);
 
3658
 
 
3659
      g_signal_handlers_unblock_by_func (expander,
 
3660
                                         gimp_prop_expanded_notify,
 
3661
                                         config);
 
3662
    }
 
3663
}
 
3664
 
 
3665
 
 
3666
/*******************************/
 
3667
/*  private utility functions  */
 
3668
/*******************************/
 
3669
 
 
3670
static GQuark param_spec_quark = 0;
 
3671
 
 
3672
static void
 
3673
set_param_spec (GObject     *object,
 
3674
                GtkWidget   *widget,
 
3675
                GParamSpec  *param_spec)
 
3676
{
 
3677
  if (object)
 
3678
    {
 
3679
      if (! param_spec_quark)
 
3680
        param_spec_quark = g_quark_from_static_string ("gimp-config-param-spec");
 
3681
 
 
3682
      g_object_set_qdata (object, param_spec_quark, param_spec);
 
3683
    }
 
3684
 
 
3685
  if (widget)
 
3686
    {
 
3687
      const gchar *blurb = g_param_spec_get_blurb (param_spec);
 
3688
 
 
3689
      if (blurb)
 
3690
        {
 
3691
          const gchar *domain;
 
3692
 
 
3693
          domain = gimp_type_get_translation_domain (param_spec->owner_type);
 
3694
          gimp_help_set_help_data (widget, dgettext (domain, blurb), NULL);
 
3695
        }
 
3696
    }
 
3697
}
 
3698
 
 
3699
static void
 
3700
set_radio_spec (GObject    *object,
 
3701
                GParamSpec *param_spec)
 
3702
{
 
3703
  GSList *list;
 
3704
 
 
3705
  for (list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (object));
 
3706
       list;
 
3707
       list = g_slist_next (list))
 
3708
    {
 
3709
      set_param_spec (list->data, NULL, param_spec);
 
3710
    }
 
3711
}
 
3712
 
 
3713
static GParamSpec *
 
3714
get_param_spec (GObject *object)
 
3715
{
 
3716
  if (! param_spec_quark)
 
3717
    param_spec_quark = g_quark_from_static_string ("gimp-config-param-spec");
 
3718
 
 
3719
  return g_object_get_qdata (object, param_spec_quark);
 
3720
}
 
3721
 
 
3722
static GParamSpec *
 
3723
find_param_spec (GObject     *object,
 
3724
                 const gchar *property_name,
 
3725
                 const gchar *strloc)
 
3726
{
 
3727
  GParamSpec *param_spec;
 
3728
 
 
3729
  param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
 
3730
                                             property_name);
 
3731
 
 
3732
  if (! param_spec)
 
3733
    g_warning ("%s: %s has no property named '%s'",
 
3734
               strloc,
 
3735
               g_type_name (G_TYPE_FROM_INSTANCE (object)),
 
3736
               property_name);
 
3737
 
 
3738
  return param_spec;
 
3739
}
 
3740
 
 
3741
static GParamSpec *
 
3742
check_param_spec (GObject     *object,
 
3743
                  const gchar *property_name,
 
3744
                  GType        type,
 
3745
                  const gchar *strloc)
 
3746
{
 
3747
  GParamSpec *param_spec;
 
3748
 
 
3749
  param_spec = find_param_spec (object, property_name, strloc);
 
3750
 
 
3751
  if (param_spec && ! g_type_is_a (G_TYPE_FROM_INSTANCE (param_spec), type))
 
3752
    {
 
3753
      g_warning ("%s: property '%s' of %s is not a %s",
 
3754
                 strloc,
 
3755
                 param_spec->name,
 
3756
                 g_type_name (param_spec->owner_type),
 
3757
                 g_type_name (type));
 
3758
      return NULL;
 
3759
    }
 
3760
 
 
3761
  return param_spec;
 
3762
}
 
3763
 
 
3764
static GParamSpec *
 
3765
check_param_spec_w (GObject     *object,
 
3766
                    const gchar *property_name,
 
3767
                    GType        type,
 
3768
                    const gchar *strloc)
 
3769
{
 
3770
  GParamSpec *param_spec;
 
3771
 
 
3772
  param_spec = check_param_spec (object, property_name, type, strloc);
 
3773
 
 
3774
  if (param_spec &&
 
3775
      (param_spec->flags & G_PARAM_WRITABLE) == 0)
 
3776
    {
 
3777
      g_warning ("%s: property '%s' of %s is writable",
 
3778
                 strloc,
 
3779
                 param_spec->name,
 
3780
                 g_type_name (param_spec->owner_type));
 
3781
      return NULL;
 
3782
    }
 
3783
 
 
3784
  return param_spec;
 
3785
}
 
3786
 
 
3787
static gboolean
 
3788
get_numeric_values (GObject     *object,
 
3789
                    GParamSpec  *param_spec,
 
3790
                    gdouble     *value,
 
3791
                    gdouble     *lower,
 
3792
                    gdouble     *upper,
 
3793
                    const gchar *strloc)
 
3794
{
 
3795
  if (G_IS_PARAM_SPEC_INT (param_spec))
 
3796
    {
 
3797
      GParamSpecInt *int_spec = G_PARAM_SPEC_INT (param_spec);
 
3798
      gint           int_value;
 
3799
 
 
3800
      g_object_get (object, param_spec->name, &int_value, NULL);
 
3801
 
 
3802
      *value = int_value;
 
3803
      *lower = int_spec->minimum;
 
3804
      *upper = int_spec->maximum;
 
3805
    }
 
3806
  else if (G_IS_PARAM_SPEC_UINT (param_spec))
 
3807
    {
 
3808
      GParamSpecUInt *uint_spec = G_PARAM_SPEC_UINT (param_spec);
 
3809
      guint           uint_value;
 
3810
 
 
3811
      g_object_get (object, param_spec->name, &uint_value, NULL);
 
3812
 
 
3813
      *value = uint_value;
 
3814
      *lower = uint_spec->minimum;
 
3815
      *upper = uint_spec->maximum;
 
3816
    }
 
3817
  else if (G_IS_PARAM_SPEC_DOUBLE (param_spec))
 
3818
    {
 
3819
      GParamSpecDouble *double_spec = G_PARAM_SPEC_DOUBLE (param_spec);
 
3820
 
 
3821
      g_object_get (object, param_spec->name, value, NULL);
 
3822
 
 
3823
      *lower = double_spec->minimum;
 
3824
      *upper = double_spec->maximum;
 
3825
    }
 
3826
  else
 
3827
    {
 
3828
      g_warning ("%s: property '%s' of %s is not numeric",
 
3829
                 strloc,
 
3830
                 param_spec->name,
 
3831
                 g_type_name (G_TYPE_FROM_INSTANCE (object)));
 
3832
      return FALSE;
 
3833
    }
 
3834
 
 
3835
  return TRUE;
 
3836
}
 
3837
 
 
3838
static void
 
3839
connect_notify (GObject     *config,
 
3840
                const gchar *property_name,
 
3841
                GCallback    callback,
 
3842
                gpointer     callback_data)
 
3843
{
 
3844
  gchar *notify_name;
 
3845
 
 
3846
  notify_name = g_strconcat ("notify::", property_name, NULL);
 
3847
 
 
3848
  g_signal_connect_object (config, notify_name, callback, callback_data, 0);
 
3849
 
 
3850
  g_free (notify_name);
 
3851
}