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

« back to all changes in this revision

Viewing changes to app/core/gimpundo.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 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 <time.h>
 
22
 
 
23
#include <glib-object.h>
 
24
 
 
25
#include "libgimpbase/gimpbase.h"
 
26
 
 
27
#include "core-types.h"
 
28
 
 
29
#include "base/temp-buf.h"
 
30
 
 
31
#include "config/gimpcoreconfig.h"
 
32
 
 
33
#include "gimp.h"
 
34
#include "gimpimage.h"
 
35
#include "gimpmarshal.h"
 
36
#include "gimpundo.h"
 
37
#include "gimpundostack.h"
 
38
 
 
39
#include "gimp-intl.h"
 
40
 
 
41
 
 
42
enum
 
43
{
 
44
  POP,
 
45
  FREE,
 
46
  LAST_SIGNAL
 
47
};
 
48
 
 
49
enum
 
50
{
 
51
  PROP_0,
 
52
  PROP_IMAGE,
 
53
  PROP_UNDO_TYPE,
 
54
  PROP_DIRTY_MASK,
 
55
  PROP_DATA,
 
56
  PROP_SIZE,
 
57
  PROP_POP_FUNC,
 
58
  PROP_FREE_FUNC
 
59
};
 
60
 
 
61
 
 
62
static void      gimp_undo_class_init          (GimpUndoClass       *klass);
 
63
 
 
64
static GObject * gimp_undo_constructor         (GType                type,
 
65
                                                guint                n_params,
 
66
                                                GObjectConstructParam *params);
 
67
static void      gimp_undo_finalize            (GObject             *object);
 
68
static void      gimp_undo_set_property        (GObject             *object,
 
69
                                                guint                property_id,
 
70
                                                const GValue        *value,
 
71
                                                GParamSpec          *pspec);
 
72
static void      gimp_undo_get_property        (GObject             *object,
 
73
                                                guint                property_id,
 
74
                                                GValue              *value,
 
75
                                                GParamSpec          *pspec);
 
76
 
 
77
static gint64    gimp_undo_get_memsize         (GimpObject          *object,
 
78
                                                gint64              *gui_size);
 
79
 
 
80
static gboolean  gimp_undo_get_popup_size      (GimpViewable        *viewable,
 
81
                                                gint                 width,
 
82
                                                gint                 height,
 
83
                                                gboolean             dot_for_dot,
 
84
                                                gint                *popup_width,
 
85
                                                gint                *popup_height);
 
86
static TempBuf * gimp_undo_get_new_preview     (GimpViewable        *viewable,
 
87
                                                gint                 width,
 
88
                                                gint                 height);
 
89
 
 
90
static void      gimp_undo_real_pop            (GimpUndo            *undo,
 
91
                                                GimpUndoMode         undo_mode,
 
92
                                                GimpUndoAccumulator *accum);
 
93
static void      gimp_undo_real_free           (GimpUndo            *undo,
 
94
                                                GimpUndoMode         undo_mode);
 
95
 
 
96
static gboolean  gimp_undo_create_preview_idle (gpointer             data);
 
97
static void   gimp_undo_create_preview_private (GimpUndo            *undo);
 
98
 
 
99
 
 
100
static guint undo_signals[LAST_SIGNAL] = { 0 };
 
101
 
 
102
static GimpViewableClass *parent_class = NULL;
 
103
 
 
104
 
 
105
GType
 
106
gimp_undo_get_type (void)
 
107
{
 
108
  static GType undo_type = 0;
 
109
 
 
110
  if (! undo_type)
 
111
    {
 
112
      static const GTypeInfo undo_info =
 
113
      {
 
114
        sizeof (GimpUndoClass),
 
115
        (GBaseInitFunc) NULL,
 
116
        (GBaseFinalizeFunc) NULL,
 
117
        (GClassInitFunc) gimp_undo_class_init,
 
118
        NULL,           /* class_finalize */
 
119
        NULL,           /* class_data     */
 
120
        sizeof (GimpUndo),
 
121
        0,              /* n_preallocs    */
 
122
        NULL            /* instance_init  */
 
123
      };
 
124
 
 
125
      undo_type = g_type_register_static (GIMP_TYPE_VIEWABLE,
 
126
                                          "GimpUndo",
 
127
                                          &undo_info, 0);
 
128
  }
 
129
 
 
130
  return undo_type;
 
131
}
 
132
 
 
133
static void
 
134
gimp_undo_class_init (GimpUndoClass *klass)
 
135
{
 
136
  GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
 
137
  GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
 
138
  GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
 
139
 
 
140
  parent_class = g_type_class_peek_parent (klass);
 
141
 
 
142
  undo_signals[POP] =
 
143
    g_signal_new ("pop",
 
144
                  G_TYPE_FROM_CLASS (klass),
 
145
                  G_SIGNAL_RUN_FIRST,
 
146
                  G_STRUCT_OFFSET (GimpUndoClass, pop),
 
147
                  NULL, NULL,
 
148
                  gimp_marshal_VOID__ENUM_POINTER,
 
149
                  G_TYPE_NONE, 2,
 
150
                  GIMP_TYPE_UNDO_MODE,
 
151
                  G_TYPE_POINTER);
 
152
 
 
153
  undo_signals[FREE] =
 
154
    g_signal_new ("free",
 
155
                  G_TYPE_FROM_CLASS (klass),
 
156
                  G_SIGNAL_RUN_FIRST,
 
157
                  G_STRUCT_OFFSET (GimpUndoClass, free),
 
158
                  NULL, NULL,
 
159
                  gimp_marshal_VOID__ENUM,
 
160
                  G_TYPE_NONE, 1,
 
161
                  GIMP_TYPE_UNDO_MODE);
 
162
 
 
163
  object_class->constructor        = gimp_undo_constructor;
 
164
  object_class->finalize           = gimp_undo_finalize;
 
165
  object_class->set_property       = gimp_undo_set_property;
 
166
  object_class->get_property       = gimp_undo_get_property;
 
167
 
 
168
  gimp_object_class->get_memsize   = gimp_undo_get_memsize;
 
169
 
 
170
  viewable_class->default_stock_id = "gtk-undo";
 
171
  viewable_class->get_popup_size   = gimp_undo_get_popup_size;
 
172
  viewable_class->get_new_preview  = gimp_undo_get_new_preview;
 
173
 
 
174
  klass->pop                       = gimp_undo_real_pop;
 
175
  klass->free                      = gimp_undo_real_free;
 
176
 
 
177
  g_object_class_install_property (object_class, PROP_IMAGE,
 
178
                                   g_param_spec_object ("image", NULL, NULL,
 
179
                                                        GIMP_TYPE_IMAGE,
 
180
                                                        G_PARAM_READWRITE |
 
181
                                                        G_PARAM_CONSTRUCT_ONLY));
 
182
 
 
183
  g_object_class_install_property (object_class, PROP_UNDO_TYPE,
 
184
                                   g_param_spec_enum ("undo-type", NULL, NULL,
 
185
                                                      GIMP_TYPE_UNDO_TYPE,
 
186
                                                      GIMP_UNDO_GROUP_NONE,
 
187
                                                      G_PARAM_READWRITE |
 
188
                                                      G_PARAM_CONSTRUCT_ONLY));
 
189
 
 
190
  g_object_class_install_property (object_class, PROP_DIRTY_MASK,
 
191
                                   g_param_spec_flags ("dirty-mask",
 
192
                                                       NULL, NULL,
 
193
                                                       GIMP_TYPE_DIRTY_MASK,
 
194
                                                       GIMP_DIRTY_NONE,
 
195
                                                       G_PARAM_READWRITE |
 
196
                                                       G_PARAM_CONSTRUCT_ONLY));
 
197
 
 
198
  g_object_class_install_property (object_class, PROP_DATA,
 
199
                                   g_param_spec_pointer ("data", NULL, NULL,
 
200
                                                         G_PARAM_READWRITE |
 
201
                                                         G_PARAM_CONSTRUCT_ONLY));
 
202
 
 
203
  g_object_class_install_property (object_class, PROP_SIZE,
 
204
                                   g_param_spec_int64 ("size", NULL, NULL,
 
205
                                                       0, G_MAXINT64, 0,
 
206
                                                       G_PARAM_READWRITE |
 
207
                                                       G_PARAM_CONSTRUCT));
 
208
 
 
209
  g_object_class_install_property (object_class, PROP_POP_FUNC,
 
210
                                   g_param_spec_pointer ("pop-func", NULL, NULL,
 
211
                                                         G_PARAM_READWRITE |
 
212
                                                         G_PARAM_CONSTRUCT_ONLY));
 
213
 
 
214
  g_object_class_install_property (object_class, PROP_FREE_FUNC,
 
215
                                   g_param_spec_pointer ("free-func", NULL, NULL,
 
216
                                                         G_PARAM_READWRITE |
 
217
                                                         G_PARAM_CONSTRUCT_ONLY));
 
218
}
 
219
 
 
220
static GObject *
 
221
gimp_undo_constructor (GType                  type,
 
222
                       guint                  n_params,
 
223
                       GObjectConstructParam *params)
 
224
{
 
225
  GObject  *object;
 
226
  GimpUndo *undo;
 
227
 
 
228
  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
 
229
 
 
230
  undo = GIMP_UNDO (object);
 
231
 
 
232
  g_assert (GIMP_IS_IMAGE (undo->gimage));
 
233
 
 
234
  undo->time = time (NULL);
 
235
 
 
236
  return object;
 
237
}
 
238
 
 
239
static void
 
240
gimp_undo_finalize (GObject *object)
 
241
{
 
242
  GimpUndo *undo = GIMP_UNDO (object);
 
243
 
 
244
  if (undo->preview_idle_id)
 
245
    {
 
246
      g_source_remove (undo->preview_idle_id);
 
247
      undo->preview_idle_id = 0;
 
248
    }
 
249
 
 
250
  if (undo->preview)
 
251
    {
 
252
      temp_buf_free (undo->preview);
 
253
      undo->preview = NULL;
 
254
    }
 
255
 
 
256
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
257
}
 
258
 
 
259
static void
 
260
gimp_undo_set_property (GObject      *object,
 
261
                        guint         property_id,
 
262
                        const GValue *value,
 
263
                        GParamSpec   *pspec)
 
264
{
 
265
  GimpUndo *undo = GIMP_UNDO (object);
 
266
 
 
267
  switch (property_id)
 
268
    {
 
269
    case PROP_IMAGE:
 
270
      /* don't ref */
 
271
      undo->gimage = (GimpImage *) g_value_get_object (value);
 
272
      break;
 
273
    case PROP_UNDO_TYPE:
 
274
      undo->undo_type = g_value_get_enum (value);
 
275
      break;
 
276
    case PROP_DIRTY_MASK:
 
277
      undo->dirty_mask = g_value_get_flags (value);
 
278
      break;
 
279
    case PROP_DATA:
 
280
      undo->data = g_value_get_pointer (value);
 
281
      break;
 
282
    case PROP_SIZE:
 
283
      undo->size = g_value_get_int64 (value);
 
284
      break;
 
285
    case PROP_POP_FUNC:
 
286
      undo->pop_func = g_value_get_pointer (value);
 
287
      break;
 
288
    case PROP_FREE_FUNC:
 
289
      undo->free_func = g_value_get_pointer (value);
 
290
      break;
 
291
    default:
 
292
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
293
      break;
 
294
    }
 
295
}
 
296
 
 
297
static void
 
298
gimp_undo_get_property (GObject    *object,
 
299
                        guint       property_id,
 
300
                        GValue     *value,
 
301
                        GParamSpec *pspec)
 
302
{
 
303
  GimpUndo *undo = GIMP_UNDO (object);
 
304
 
 
305
  switch (property_id)
 
306
    {
 
307
    case PROP_IMAGE:
 
308
      g_value_set_object (value, undo->gimage);
 
309
      break;
 
310
    case PROP_UNDO_TYPE:
 
311
      g_value_set_enum (value, undo->undo_type);
 
312
      break;
 
313
    case PROP_DIRTY_MASK:
 
314
      g_value_set_flags (value, undo->dirty_mask);
 
315
      break;
 
316
    case PROP_DATA:
 
317
      g_value_set_pointer (value, undo->data);
 
318
      break;
 
319
    case PROP_SIZE:
 
320
      g_value_set_int64 (value, undo->size);
 
321
      break;
 
322
    case PROP_POP_FUNC:
 
323
      g_value_set_pointer (value, undo->pop_func);
 
324
      break;
 
325
    case PROP_FREE_FUNC:
 
326
      g_value_set_pointer (value, undo->free_func);
 
327
      break;
 
328
    default:
 
329
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
330
      break;
 
331
    }
 
332
}
 
333
 
 
334
static gint64
 
335
gimp_undo_get_memsize (GimpObject *object,
 
336
                       gint64     *gui_size)
 
337
{
 
338
  GimpUndo *undo    = GIMP_UNDO (object);
 
339
  gint64    memsize = undo->size;
 
340
 
 
341
  if (undo->preview)
 
342
    *gui_size += temp_buf_get_memsize (undo->preview);
 
343
 
 
344
  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
 
345
                                                                  gui_size);
 
346
}
 
347
 
 
348
static gboolean
 
349
gimp_undo_get_popup_size (GimpViewable *viewable,
 
350
                          gint          width,
 
351
                          gint          height,
 
352
                          gboolean      dot_for_dot,
 
353
                          gint         *popup_width,
 
354
                          gint         *popup_height)
 
355
{
 
356
  GimpUndo *undo = GIMP_UNDO (viewable);
 
357
 
 
358
  if (undo->preview &&
 
359
      (undo->preview->width > width || undo->preview->height > height))
 
360
    {
 
361
      *popup_width  = undo->preview->width;
 
362
      *popup_height = undo->preview->height;
 
363
 
 
364
      return TRUE;
 
365
    }
 
366
 
 
367
  return FALSE;
 
368
}
 
369
 
 
370
static TempBuf *
 
371
gimp_undo_get_new_preview (GimpViewable *viewable,
 
372
                           gint          width,
 
373
                           gint          height)
 
374
{
 
375
  GimpUndo *undo = GIMP_UNDO (viewable);
 
376
 
 
377
  if (undo->preview)
 
378
    {
 
379
      gint preview_width;
 
380
      gint preview_height;
 
381
 
 
382
      gimp_viewable_calc_preview_size (undo->preview->width,
 
383
                                       undo->preview->height,
 
384
                                       width,
 
385
                                       height,
 
386
                                       TRUE, 1.0, 1.0,
 
387
                                       &preview_width,
 
388
                                       &preview_height,
 
389
                                       NULL);
 
390
 
 
391
      if (preview_width  < undo->preview->width &&
 
392
          preview_height < undo->preview->height)
 
393
        {
 
394
          return temp_buf_scale (undo->preview, preview_width, preview_height);
 
395
        }
 
396
 
 
397
      return temp_buf_copy (undo->preview, NULL);
 
398
    }
 
399
 
 
400
  return NULL;
 
401
}
 
402
 
 
403
static void
 
404
gimp_undo_real_pop (GimpUndo            *undo,
 
405
                    GimpUndoMode         undo_mode,
 
406
                    GimpUndoAccumulator *accum)
 
407
{
 
408
  if (undo->pop_func)
 
409
    undo->pop_func (undo, undo_mode, accum);
 
410
}
 
411
 
 
412
static void
 
413
gimp_undo_real_free (GimpUndo     *undo,
 
414
                     GimpUndoMode  undo_mode)
 
415
{
 
416
  if (undo->free_func)
 
417
    undo->free_func (undo, undo_mode);
 
418
}
 
419
 
 
420
void
 
421
gimp_undo_pop (GimpUndo            *undo,
 
422
               GimpUndoMode         undo_mode,
 
423
               GimpUndoAccumulator *accum)
 
424
{
 
425
  g_return_if_fail (GIMP_IS_UNDO (undo));
 
426
  g_return_if_fail (accum != NULL);
 
427
 
 
428
  if (undo->dirty_mask != GIMP_DIRTY_NONE)
 
429
    {
 
430
      switch (undo_mode)
 
431
        {
 
432
        case GIMP_UNDO_MODE_UNDO:
 
433
          gimp_image_clean (undo->gimage, undo->dirty_mask);
 
434
          break;
 
435
 
 
436
        case GIMP_UNDO_MODE_REDO:
 
437
          gimp_image_dirty (undo->gimage, undo->dirty_mask);
 
438
          break;
 
439
        }
 
440
    }
 
441
 
 
442
  g_signal_emit (undo, undo_signals[POP], 0, undo_mode, accum);
 
443
}
 
444
 
 
445
void
 
446
gimp_undo_free (GimpUndo     *undo,
 
447
                GimpUndoMode  undo_mode)
 
448
{
 
449
  g_return_if_fail (GIMP_IS_UNDO (undo));
 
450
 
 
451
  g_signal_emit (undo, undo_signals[FREE], 0, undo_mode);
 
452
}
 
453
 
 
454
void
 
455
gimp_undo_create_preview (GimpUndo  *undo,
 
456
                          gboolean   create_now)
 
457
{
 
458
  g_return_if_fail (GIMP_IS_UNDO (undo));
 
459
 
 
460
  if (undo->preview || undo->preview_idle_id)
 
461
    return;
 
462
 
 
463
  if (create_now)
 
464
    gimp_undo_create_preview_private (undo);
 
465
  else
 
466
    undo->preview_idle_id = g_idle_add (gimp_undo_create_preview_idle, undo);
 
467
}
 
468
 
 
469
static gboolean
 
470
gimp_undo_create_preview_idle (gpointer data)
 
471
{
 
472
  GimpUndo *undo = GIMP_UNDO (data);
 
473
 
 
474
  if (undo == gimp_undo_stack_peek (undo->gimage->undo_stack))
 
475
    {
 
476
      gimp_undo_create_preview_private (undo);
 
477
    }
 
478
 
 
479
  undo->preview_idle_id = 0;
 
480
 
 
481
  return FALSE;
 
482
}
 
483
 
 
484
static void
 
485
gimp_undo_create_preview_private (GimpUndo *undo)
 
486
{
 
487
  GimpImage       *image = undo->gimage;
 
488
  GimpViewable    *preview_viewable;
 
489
  GimpViewSize     preview_size;
 
490
  gint             width;
 
491
  gint             height;
 
492
 
 
493
  switch (undo->undo_type)
 
494
    {
 
495
    case GIMP_UNDO_GROUP_IMAGE_QMASK:
 
496
    case GIMP_UNDO_GROUP_MASK:
 
497
    case GIMP_UNDO_MASK:
 
498
      preview_viewable = GIMP_VIEWABLE (gimp_image_get_mask (image));
 
499
      break;
 
500
 
 
501
    default:
 
502
      preview_viewable = GIMP_VIEWABLE (image);
 
503
      break;
 
504
    }
 
505
 
 
506
  preview_size = image->gimp->config->undo_preview_size;
 
507
 
 
508
  if (image->width <= preview_size && image->height <= preview_size)
 
509
    {
 
510
      width  = image->width;
 
511
      height = image->height;
 
512
    }
 
513
  else
 
514
    {
 
515
      if (image->width > image->height)
 
516
        {
 
517
          width  = preview_size;
 
518
          height = MAX (1, (image->height * preview_size / image->width));
 
519
        }
 
520
      else
 
521
        {
 
522
          height = preview_size;
 
523
          width  = MAX (1, (image->width * preview_size / image->height));
 
524
        }
 
525
    }
 
526
 
 
527
  undo->preview = gimp_viewable_get_new_preview (preview_viewable,
 
528
                                                 width, height);
 
529
 
 
530
  gimp_viewable_invalidate_preview (GIMP_VIEWABLE (undo));
 
531
}
 
532
 
 
533
void
 
534
gimp_undo_refresh_preview (GimpUndo *undo)
 
535
{
 
536
  g_return_if_fail (GIMP_IS_UNDO (undo));
 
537
 
 
538
  if (undo->preview_idle_id)
 
539
    return;
 
540
 
 
541
  if (undo->preview)
 
542
    {
 
543
      temp_buf_free (undo->preview);
 
544
      undo->preview = NULL;
 
545
      gimp_undo_create_preview (undo, FALSE);
 
546
    }
 
547
}
 
548
 
 
549
const gchar *
 
550
gimp_undo_type_to_name (GimpUndoType type)
 
551
{
 
552
  const gchar *desc;
 
553
 
 
554
  if (gimp_enum_get_value (GIMP_TYPE_UNDO_TYPE, type, NULL, NULL, &desc, NULL))
 
555
    return desc;
 
556
  else
 
557
    return "";
 
558
}