~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to app/core/gimpobject.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* The GIMP -- an image manipulation program
 
2
 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
17
 */
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#include <string.h>
 
22
 
 
23
#include <glib-object.h>
 
24
 
 
25
#include "libgimpbase/gimpbase.h"
 
26
 
 
27
#include "core-types.h"
 
28
 
 
29
#include "gimp-utils.h"
 
30
#include "gimpmarshal.h"
 
31
#include "gimpobject.h"
 
32
 
 
33
 
 
34
enum
 
35
{
 
36
  DISCONNECT,
 
37
  NAME_CHANGED,
 
38
  LAST_SIGNAL
 
39
};
 
40
 
 
41
enum
 
42
{
 
43
  PROP_0,
 
44
  PROP_NAME
 
45
};
 
46
 
 
47
 
 
48
static void    gimp_object_class_init        (GimpObjectClass *klass);
 
49
static void    gimp_object_init              (GimpObject      *object);
 
50
 
 
51
static void    gimp_object_dispose           (GObject         *object);
 
52
static void    gimp_object_finalize          (GObject         *object);
 
53
static void    gimp_object_set_property      (GObject         *object,
 
54
                                              guint            property_id,
 
55
                                              const GValue    *value,
 
56
                                              GParamSpec      *pspec);
 
57
static void    gimp_object_get_property      (GObject         *object,
 
58
                                              guint            property_id,
 
59
                                              GValue          *value,
 
60
                                              GParamSpec      *pspec);
 
61
static gint64  gimp_object_real_get_memsize  (GimpObject      *object,
 
62
                                              gint64          *gui_size);
 
63
static void    gimp_object_name_normalize    (GimpObject      *object);
 
64
 
 
65
 
 
66
static guint   object_signals[LAST_SIGNAL] = { 0 };
 
67
 
 
68
static GObjectClass *parent_class = NULL;
 
69
 
 
70
 
 
71
GType
 
72
gimp_object_get_type (void)
 
73
{
 
74
  static GType object_type = 0;
 
75
 
 
76
  if (! object_type)
 
77
    {
 
78
      static const GTypeInfo object_info =
 
79
      {
 
80
        sizeof (GimpObjectClass),
 
81
        (GBaseInitFunc) NULL,
 
82
        (GBaseFinalizeFunc) NULL,
 
83
        (GClassInitFunc) gimp_object_class_init,
 
84
        NULL,           /* class_finalize */
 
85
        NULL,           /* class_data     */
 
86
        sizeof (GimpObject),
 
87
        0,              /* n_preallocs    */
 
88
        (GInstanceInitFunc) gimp_object_init,
 
89
      };
 
90
 
 
91
      object_type = g_type_register_static (G_TYPE_OBJECT,
 
92
                                            "GimpObject",
 
93
                                            &object_info, 0);
 
94
    }
 
95
 
 
96
  return object_type;
 
97
}
 
98
 
 
99
static void
 
100
gimp_object_class_init (GimpObjectClass *klass)
 
101
{
 
102
  GObjectClass *object_class;
 
103
 
 
104
  object_class = G_OBJECT_CLASS (klass);
 
105
 
 
106
  parent_class = g_type_class_peek_parent (klass);
 
107
 
 
108
  object_signals[DISCONNECT] =
 
109
    g_signal_new ("disconnect",
 
110
                  G_TYPE_FROM_CLASS (klass),
 
111
                  G_SIGNAL_RUN_FIRST,
 
112
                  G_STRUCT_OFFSET (GimpObjectClass, disconnect),
 
113
                  NULL, NULL,
 
114
                  gimp_marshal_VOID__VOID,
 
115
                  G_TYPE_NONE, 0);
 
116
 
 
117
  object_signals[NAME_CHANGED] =
 
118
    g_signal_new ("name_changed",
 
119
                  G_TYPE_FROM_CLASS (klass),
 
120
                  G_SIGNAL_RUN_FIRST,
 
121
                  G_STRUCT_OFFSET (GimpObjectClass, name_changed),
 
122
                  NULL, NULL,
 
123
                  gimp_marshal_VOID__VOID,
 
124
                  G_TYPE_NONE, 0);
 
125
 
 
126
  object_class->dispose      = gimp_object_dispose;
 
127
  object_class->finalize     = gimp_object_finalize;
 
128
  object_class->set_property = gimp_object_set_property;
 
129
  object_class->get_property = gimp_object_get_property;
 
130
 
 
131
  klass->disconnect          = NULL;
 
132
  klass->name_changed        = NULL;
 
133
  klass->get_memsize         = gimp_object_real_get_memsize;
 
134
 
 
135
  g_object_class_install_property (object_class,
 
136
                                   PROP_NAME,
 
137
                                   g_param_spec_string ("name",
 
138
                                                        NULL, NULL,
 
139
                                                        NULL,
 
140
                                                        G_PARAM_READWRITE));
 
141
}
 
142
 
 
143
static void
 
144
gimp_object_init (GimpObject *object)
 
145
{
 
146
  object->name       = NULL;
 
147
  object->normalized = NULL;
 
148
}
 
149
 
 
150
static void
 
151
gimp_object_dispose (GObject *object)
 
152
{
 
153
  gboolean disconnected;
 
154
 
 
155
  disconnected = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object),
 
156
                                                     "disconnected"));
 
157
 
 
158
  if (! disconnected)
 
159
    {
 
160
      g_signal_emit (object, object_signals[DISCONNECT], 0);
 
161
 
 
162
      g_object_set_data (G_OBJECT (object), "disconnected",
 
163
                         GINT_TO_POINTER (TRUE));
 
164
    }
 
165
 
 
166
  G_OBJECT_CLASS (parent_class)->dispose (object);
 
167
}
 
168
 
 
169
static void
 
170
gimp_object_finalize (GObject *object)
 
171
{
 
172
  gimp_object_name_free (GIMP_OBJECT (object));
 
173
 
 
174
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
175
}
 
176
 
 
177
static void
 
178
gimp_object_set_property (GObject      *object,
 
179
                          guint         property_id,
 
180
                          const GValue *value,
 
181
                          GParamSpec   *pspec)
 
182
{
 
183
  GimpObject *gimp_object = GIMP_OBJECT (object);
 
184
 
 
185
  switch (property_id)
 
186
    {
 
187
    case PROP_NAME:
 
188
      gimp_object_set_name (gimp_object, g_value_get_string (value));
 
189
      break;
 
190
    default:
 
191
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
192
      break;
 
193
    }
 
194
}
 
195
 
 
196
static void
 
197
gimp_object_get_property (GObject    *object,
 
198
                          guint       property_id,
 
199
                          GValue     *value,
 
200
                          GParamSpec *pspec)
 
201
{
 
202
  GimpObject *gimp_object = GIMP_OBJECT (object);
 
203
 
 
204
  switch (property_id)
 
205
    {
 
206
    case PROP_NAME:
 
207
      g_value_set_string (value, gimp_object->name);
 
208
      break;
 
209
    default:
 
210
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
211
      break;
 
212
    }
 
213
}
 
214
 
 
215
/**
 
216
 * gimp_object_set_name:
 
217
 * @object: a #GimpObject
 
218
 * @name: the @object's new name
 
219
 *
 
220
 * Sets the @object's name. Takes care of freeing the old name and
 
221
 * emitting the "name_changed" signal if the old and new name differ.
 
222
 **/
 
223
void
 
224
gimp_object_set_name (GimpObject  *object,
 
225
                      const gchar *name)
 
226
{
 
227
  g_return_if_fail (GIMP_IS_OBJECT (object));
 
228
 
 
229
  if ((!object->name && !name) ||
 
230
      (object->name && name && !strcmp (object->name, name)))
 
231
    return;
 
232
 
 
233
  gimp_object_name_free (object);
 
234
 
 
235
  object->name = g_strdup (name);
 
236
 
 
237
  gimp_object_name_changed (object);
 
238
}
 
239
 
 
240
/**
 
241
 * gimp_object_set_name_safe:
 
242
 * @object: a #GimpObject
 
243
 * @name: the @object's new name
 
244
 *
 
245
 * A safe version of gimp_object_set_name() that takes care of
 
246
 * handling newlines and overly long names. The actual name set
 
247
 * may be different to the @name you pass.
 
248
 **/
 
249
void
 
250
gimp_object_set_name_safe (GimpObject  *object,
 
251
                           const gchar *name)
 
252
{
 
253
  g_return_if_fail (GIMP_IS_OBJECT (object));
 
254
 
 
255
  if ((!object->name && !name) ||
 
256
      (object->name && name && !strcmp (object->name, name)))
 
257
    return;
 
258
 
 
259
  gimp_object_name_free (object);
 
260
 
 
261
  object->name = gimp_utf8_strtrim (name, 30);
 
262
 
 
263
  gimp_object_name_changed (object);
 
264
}
 
265
 
 
266
/**
 
267
 * gimp_object_get_name:
 
268
 * @object: a #GimpObject
 
269
 *
 
270
 * This function gives access to the name of a GimpObject. The
 
271
 * returned name belongs to the object and must not be freed.
 
272
 *
 
273
 * Return value: a pointer to the @object's name
 
274
 **/
 
275
const gchar *
 
276
gimp_object_get_name (const GimpObject *object)
 
277
{
 
278
  g_return_val_if_fail (GIMP_IS_OBJECT (object), NULL);
 
279
 
 
280
  return object->name;
 
281
}
 
282
 
 
283
/**
 
284
 * gimp_object_name_changed:
 
285
 * @object: a #GimpObject
 
286
 *
 
287
 * Causes the "name_changed" signal to be emitted.
 
288
 **/
 
289
void
 
290
gimp_object_name_changed (GimpObject *object)
 
291
{
 
292
  g_return_if_fail (GIMP_IS_OBJECT (object));
 
293
 
 
294
  g_signal_emit (object, object_signals[NAME_CHANGED], 0);
 
295
}
 
296
 
 
297
/**
 
298
 * gimp_object_name_free:
 
299
 * @object: a #GimpObject
 
300
 *
 
301
 * Frees the name of @object and sets the name pointer to %NULL. Also
 
302
 * takes care of the normalized name that the object might be caching.
 
303
 *
 
304
 * In general you should be using gimp_object_set_name() instead. But
 
305
 * if you ever need to free the object name but don't want the
 
306
 * "name_changed" signal to be emitted, then use this function. Never
 
307
 * ever free the object name directly!
 
308
 **/
 
309
void
 
310
gimp_object_name_free (GimpObject *object)
 
311
{
 
312
  if (object->normalized)
 
313
    {
 
314
      if (object->normalized != object->name)
 
315
        g_free (object->normalized);
 
316
 
 
317
      object->normalized = NULL;
 
318
    }
 
319
 
 
320
  if (object->name)
 
321
    {
 
322
      g_free (object->name);
 
323
      object->name = NULL;
 
324
    }
 
325
}
 
326
 
 
327
/**
 
328
 * gimp_object_name_collate:
 
329
 * @object1: a #GimpObject
 
330
 * @object2: another #GimpObject
 
331
 *
 
332
 * Compares two object names for ordering using the linguistically
 
333
 * correct rules for the current locale. It caches the normalized
 
334
 * version of the object name to speed up subsequent calls.
 
335
 *
 
336
 * Return value: -1 if object1 compares before object2,
 
337
 *                0 if they compare equal,
 
338
 *                1 if object1 compares after object2.
 
339
 **/
 
340
gint
 
341
gimp_object_name_collate (GimpObject *object1,
 
342
                          GimpObject *object2)
 
343
{
 
344
  if (! object1->normalized)
 
345
    gimp_object_name_normalize (object1);
 
346
 
 
347
  if (! object2->normalized)
 
348
    gimp_object_name_normalize (object2);
 
349
 
 
350
  return strcmp (object1->normalized, object2->normalized);
 
351
}
 
352
 
 
353
static void
 
354
gimp_object_name_normalize (GimpObject *object)
 
355
{
 
356
  g_return_if_fail (object->normalized == NULL);
 
357
 
 
358
  if (object->name)
 
359
    {
 
360
      gchar *key = g_utf8_collate_key (object->name, -1);
 
361
 
 
362
      if (strcmp (key, object->name))
 
363
        {
 
364
          object->normalized = key;
 
365
        }
 
366
      else
 
367
        {
 
368
          g_free (key);
 
369
          object->normalized = object->name;
 
370
        }
 
371
    }
 
372
}
 
373
 
 
374
 
 
375
#define DEBUG_MEMSIZE 1
 
376
 
 
377
#ifdef DEBUG_MEMSIZE
 
378
gboolean gimp_debug_memsize = FALSE;
 
379
#endif
 
380
 
 
381
gint64
 
382
gimp_object_get_memsize (GimpObject *object,
 
383
                         gint64     *gui_size)
 
384
{
 
385
  gint64 my_size     = 0;
 
386
  gint64 my_gui_size = 0;
 
387
 
 
388
  g_return_val_if_fail (GIMP_IS_OBJECT (object), 0);
 
389
 
 
390
#ifdef DEBUG_MEMSIZE
 
391
  if (gimp_debug_memsize)
 
392
    {
 
393
      static gint   indent_level     = 0;
 
394
      static GList *aggregation_tree = NULL;
 
395
      static gchar  indent_buf[256];
 
396
 
 
397
      gint64  memsize;
 
398
      gint64  gui_memsize = 0;
 
399
      gint    i;
 
400
      gint    my_indent_level;
 
401
      gchar  *object_size;
 
402
 
 
403
      indent_level++;
 
404
 
 
405
      my_indent_level = indent_level;
 
406
 
 
407
      memsize = GIMP_OBJECT_GET_CLASS (object)->get_memsize (object,
 
408
                                                             &gui_memsize);
 
409
 
 
410
      indent_level--;
 
411
 
 
412
      for (i = 0; i < MIN (my_indent_level * 2, sizeof (indent_buf) - 1); i++)
 
413
        indent_buf[i] = ' ';
 
414
 
 
415
      indent_buf[i] = '\0';
 
416
 
 
417
      object_size = g_strdup_printf ("%s%s \"%s\": "
 
418
                                     "%" G_GINT64_FORMAT
 
419
                                     "(%" G_GINT64_FORMAT ")\n",
 
420
                                     indent_buf,
 
421
                                     g_type_name (G_TYPE_FROM_INSTANCE (object)),
 
422
                                     object->name,
 
423
                                     memsize,
 
424
                                     gui_memsize);
 
425
 
 
426
      aggregation_tree = g_list_prepend (aggregation_tree, object_size);
 
427
 
 
428
      if (indent_level == 0)
 
429
        {
 
430
          g_list_foreach (aggregation_tree, (GFunc) g_print, NULL);
 
431
          g_list_foreach (aggregation_tree, (GFunc) g_free, NULL);
 
432
          g_list_free (aggregation_tree);
 
433
 
 
434
          aggregation_tree = NULL;
 
435
        }
 
436
 
 
437
      return memsize;
 
438
    }
 
439
#endif /* DEBUG_MEMSIZE */
 
440
 
 
441
  my_size = GIMP_OBJECT_GET_CLASS (object)->get_memsize (object,
 
442
                                                         &my_gui_size);
 
443
 
 
444
  if (gui_size)
 
445
    *gui_size = my_gui_size;
 
446
 
 
447
  return my_size;
 
448
}
 
449
 
 
450
static gint64
 
451
gimp_object_real_get_memsize (GimpObject *object,
 
452
                              gint64     *gui_size)
 
453
{
 
454
  gint64  memsize = 0;
 
455
 
 
456
  if (object->name)
 
457
    memsize += strlen (object->name) + 1;
 
458
 
 
459
  return memsize + gimp_g_object_get_memsize ((GObject *) object);
 
460
}
 
461