gimpimagedock.c 21.3 KB
Newer Older
Michael Natterer's avatar
Michael Natterer committed
1
2
3
4
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * gimpimagedock.c
5
 * Copyright (C) 2001 Michael Natterer <mitch@gimp.org>
Michael Natterer's avatar
Michael Natterer committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "config.h"

24
25
#include <string.h>

Michael Natterer's avatar
Michael Natterer committed
26
27
28
29
#include <gtk/gtk.h>

#include "libgimpwidgets/gimpwidgets.h"

30
#include "widgets-types.h"
Michael Natterer's avatar
Michael Natterer committed
31

32
#include "core/gimp.h"
33
34
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
35
36
#include "core/gimplist.h"

Michael Natterer's avatar
Michael Natterer committed
37
38
39
#include "gimpdialogfactory.h"
#include "gimpimagedock.h"
#include "gimpcontainermenuimpl.h"
40
#include "gimpdockable.h"
Michael Natterer's avatar
Michael Natterer committed
41
#include "gimpdockbook.h"
42
#include "gimphelp-ids.h"
43
#include "gimpsessioninfo.h"
Michael Natterer's avatar
Michael Natterer committed
44

45
#include "gimp-intl.h"
Michael Natterer's avatar
Michael Natterer committed
46
47


48
49
#define DEFAULT_MINIMAL_WIDTH     250
#define DEFAULT_MENU_PREVIEW_SIZE GTK_ICON_SIZE_SMALL_TOOLBAR
50
51


52
53
54
55
56
57
58
59
60
61
static void   gimp_image_dock_class_init          (GimpImageDockClass *klass);
static void   gimp_image_dock_init                (GimpImageDock      *dock);

static void   gimp_image_dock_destroy                 (GtkObject      *object);

static void   gimp_image_dock_style_set               (GtkWidget      *widget,
                                                       GtkStyle       *prev_style);

static void   gimp_image_dock_setup                   (GimpDock       *dock,
                                                       const GimpDock *template);
62
63
64
static void   gimp_image_dock_set_aux_info            (GimpDock       *dock,
                                                       GList          *aux_info);
static GList *gimp_image_dock_get_aux_info            (GimpDock       *dock);
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
static void   gimp_image_dock_book_added              (GimpDock       *dock,
                                                       GimpDockbook   *dockbook);
static void   gimp_image_dock_book_removed            (GimpDock       *dock,
                                                       GimpDockbook   *dockbook);

static void   gimp_image_dock_dockbook_changed        (GimpDockbook   *dockbook,
                                                       GimpDockable   *dockable,
                                                       GimpImageDock  *dock);
static void   gimp_image_dock_update_title            (GimpImageDock  *dock);

static void   gimp_image_dock_factory_display_changed (GimpContext    *context,
                                                       GimpObject     *gdisp,
                                                       GimpDock       *dock);
static void   gimp_image_dock_factory_image_changed   (GimpContext    *context,
                                                       GimpImage      *gimage,
                                                       GimpDock       *dock);
static void   gimp_image_dock_image_changed           (GimpContext    *context,
                                                       GimpImage      *gimage,
                                                       GimpDock       *dock);
static void   gimp_image_dock_auto_clicked            (GtkWidget      *widget,
                                                       GimpDock       *dock);
Michael Natterer's avatar
Michael Natterer committed
86
87
88
89
90


static GimpDockClass *parent_class = NULL;


91
GType
Michael Natterer's avatar
Michael Natterer committed
92
93
gimp_image_dock_get_type (void)
{
94
  static GType dock_type = 0;
Michael Natterer's avatar
Michael Natterer committed
95
96
97

  if (! dock_type)
    {
98
      static const GTypeInfo dock_info =
Michael Natterer's avatar
Michael Natterer committed
99
      {
100
101
102
103
104
105
106
107
108
        sizeof (GimpImageDockClass),
        NULL,           /* base_init */
        NULL,           /* base_finalize */
        (GClassInitFunc) gimp_image_dock_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (GimpImageDock),
        0,              /* n_preallocs */
        (GInstanceInitFunc) gimp_image_dock_init,
Michael Natterer's avatar
Michael Natterer committed
109
110
      };

111
112
113
      dock_type = g_type_register_static (GIMP_TYPE_DOCK,
                                          "GimpImageDock",
                                          &dock_info, 0);
Michael Natterer's avatar
Michael Natterer committed
114
115
116
117
118
119
120
121
122
    }

  return dock_type;
}

static void
gimp_image_dock_class_init (GimpImageDockClass *klass)
{
  GtkObjectClass *object_class;
123
  GtkWidgetClass *widget_class;
124
  GimpDockClass  *dock_class;
Michael Natterer's avatar
Michael Natterer committed
125

126
  object_class = GTK_OBJECT_CLASS (klass);
127
  widget_class = GTK_WIDGET_CLASS (klass);
128
  dock_class   = GIMP_DOCK_CLASS (klass);
Michael Natterer's avatar
Michael Natterer committed
129

130
  parent_class = g_type_class_peek_parent (klass);
Michael Natterer's avatar
Michael Natterer committed
131

132
133
134
  object_class->destroy    = gimp_image_dock_destroy;

  widget_class->style_set  = gimp_image_dock_style_set;
135

136
  dock_class->setup        = gimp_image_dock_setup;
137
138
  dock_class->set_aux_info = gimp_image_dock_set_aux_info;
  dock_class->get_aux_info = gimp_image_dock_get_aux_info;
139
140
  dock_class->book_added   = gimp_image_dock_book_added;
  dock_class->book_removed = gimp_image_dock_book_removed;
141
142
143
144
145
146
147
148

  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("minimal_width",
                                                             NULL, NULL,
                                                             0,
                                                             G_MAXINT,
                                                             DEFAULT_MINIMAL_WIDTH,
                                                             G_PARAM_READABLE));
149
  gtk_widget_class_install_style_property (widget_class,
150
151
152
153
154
                                           g_param_spec_enum ("menu_preview_size",
                                                              NULL, NULL,
                                                              GTK_TYPE_ICON_SIZE,
                                                              DEFAULT_MENU_PREVIEW_SIZE,
                                                              G_PARAM_READABLE));
Michael Natterer's avatar
Michael Natterer committed
155
156
157
158
159
}

static void
gimp_image_dock_init (GimpImageDock *dock)
{
Michael Natterer's avatar
Michael Natterer committed
160
161
  GtkWidget *hbox;

162
163
164
165
166
  dock->image_container      = NULL;
  dock->display_container    = NULL;
  dock->show_image_menu      = FALSE;
  dock->auto_follow_active   = TRUE;
  dock->update_title_idle_id = 0;
Michael Natterer's avatar
Michael Natterer committed
167
168
169

  hbox = gtk_hbox_new (FALSE, 2);
  gtk_box_pack_start (GTK_BOX (GIMP_DOCK (dock)->main_vbox), hbox,
Michael Natterer's avatar
Michael Natterer committed
170
                      FALSE, FALSE, 0);
Michael Natterer's avatar
Michael Natterer committed
171
  gtk_box_reorder_child (GTK_BOX (GIMP_DOCK (dock)->main_vbox), hbox, 0);
172
173
174

  if (dock->show_image_menu)
    gtk_widget_show (hbox);
Michael Natterer's avatar
Michael Natterer committed
175
176
177

  dock->option_menu = gtk_option_menu_new ();
  gtk_box_pack_start (GTK_BOX (hbox), dock->option_menu, TRUE, TRUE, 0);
Michael Natterer's avatar
Michael Natterer committed
178
179
  gtk_widget_show (dock->option_menu);

180
  g_signal_connect (dock->option_menu, "destroy",
181
182
183
		    G_CALLBACK (gtk_widget_destroyed),
		    &dock->option_menu);

184
185
186
  gimp_help_set_help_data (dock->option_menu, NULL,
                           GIMP_HELP_DOCK_IMAGE_MENU);

187
188
  dock->auto_button = gtk_toggle_button_new_with_label (_("Auto"));
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dock->auto_button),
Michael Natterer's avatar
Michael Natterer committed
189
				dock->auto_follow_active);
190
191
  gtk_box_pack_start (GTK_BOX (hbox), dock->auto_button, FALSE, FALSE, 0);
  gtk_widget_show (dock->auto_button);
Michael Natterer's avatar
Michael Natterer committed
192

193
  g_signal_connect (dock->auto_button, "clicked",
194
195
		    G_CALLBACK (gimp_image_dock_auto_clicked),
		    dock);
196
197
198

  gimp_help_set_help_data (dock->auto_button, NULL,
                           GIMP_HELP_DOCK_AUTO_BUTTON);
Michael Natterer's avatar
Michael Natterer committed
199
200
201
202
203
204
205
206
207
}

static void
gimp_image_dock_destroy (GtkObject *object)
{
  GimpImageDock *dock;

  dock = GIMP_IMAGE_DOCK (object);

208
209
210
211
212
213
  if (dock->update_title_idle_id)
    {
      g_source_remove (dock->update_title_idle_id);
      dock->update_title_idle_id = 0;
    }

Michael Natterer's avatar
Michael Natterer committed
214
215
216
  /*  remove the image menu and the auto button manually here because
   *  of weird cross-connections with GimpDock's context
   */
217
218
219
220
221
222
223
  if (GIMP_DOCK (dock)->main_vbox &&
      dock->option_menu           &&
      dock->option_menu->parent)
    {
      gtk_container_remove (GTK_CONTAINER (GIMP_DOCK (dock)->main_vbox),
			    dock->option_menu->parent);
    }
Michael Natterer's avatar
Michael Natterer committed
224

225
  GTK_OBJECT_CLASS (parent_class)->destroy (object);
Michael Natterer's avatar
Michael Natterer committed
226
227
}

228
229
230
231
static void
gimp_image_dock_style_set (GtkWidget *widget,
                           GtkStyle  *prev_style)
{
232
233
  GimpImageDock *image_dock;
  gint           minimal_width;
234
235
236
  GtkIconSize    menu_preview_size;
  gint           menu_preview_width  = 18;
  gint           menu_preview_height = 18;
237
238
239
240
241
  gint           focus_line_width;
  gint           focus_padding;
  gint           ythickness;

  image_dock = GIMP_IMAGE_DOCK (widget);
242
243
244
245
246

  if (GTK_WIDGET_CLASS (parent_class)->style_set)
    GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);

  gtk_widget_style_get (widget,
247
248
                        "minimal_width",     &minimal_width,
                        "menu_preview_size", &menu_preview_size,
249
250
			NULL);

251
252
253
254
  gtk_icon_size_lookup (menu_preview_size,
                        &menu_preview_width,
                        &menu_preview_height);

255
256
257
258
259
260
261
  gtk_widget_style_get (image_dock->auto_button,
                        "focus_line_width", &focus_line_width,
                        "focus_padding",    &focus_padding,
			NULL);

  ythickness = image_dock->auto_button->style->ythickness;

262
  gtk_widget_set_size_request (widget, minimal_width, -1);
263
264

  gimp_container_menu_set_preview_size (GIMP_CONTAINER_MENU (image_dock->menu),
265
                                        menu_preview_height, 1);
266
267
268
269
270
271
272

  gtk_widget_set_size_request (image_dock->auto_button, -1,
                               menu_preview_height +
                               2 * (1 /* CHILD_SPACING */ +
                                    ythickness            +
                                    focus_padding         +
                                    focus_line_width));
273
274
}

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
static void
gimp_image_dock_setup (GimpDock       *dock,
                       const GimpDock *template)
{
  if (GIMP_IS_IMAGE_DOCK (template))
    {
      gboolean auto_follow_active;
      gboolean show_image_menu;

      auto_follow_active = GIMP_IMAGE_DOCK (template)->auto_follow_active;
      show_image_menu    = GIMP_IMAGE_DOCK (template)->show_image_menu;

      gimp_image_dock_set_auto_follow_active (GIMP_IMAGE_DOCK (dock),
                                              auto_follow_active);
      gimp_image_dock_set_show_image_menu (GIMP_IMAGE_DOCK (dock),
                                           show_image_menu);
    }
}

294
295
296
297
298
static void
gimp_image_dock_set_aux_info (GimpDock *dock,
                              GList    *aux_info)
{
  GimpImageDock *image_dock = GIMP_IMAGE_DOCK (dock);
299
  GList         *list;
300
301
302
  gboolean       menu_shown  = image_dock->show_image_menu;
  gboolean       auto_follow = image_dock->auto_follow_active;

303
  for (list = aux_info; list; list = g_list_next (list))
304
    {
305
306
307
308
309
310
311
312
313
314
      GimpSessionInfoAux *aux = list->data;

      if (! strcmp (aux->name, "show-image-menu"))
        {
          menu_shown = ! g_ascii_strcasecmp (aux->value, "true");
        }
      else if (! strcmp (aux->name, "follow-active-image"))
        {
          auto_follow = ! g_ascii_strcasecmp (aux->value, "true");
        }
315
316
317
318
319
320
321
322
323
324
325
326
    }

  if (menu_shown != image_dock->show_image_menu)
    gimp_image_dock_set_show_image_menu (image_dock, menu_shown);

  if (auto_follow != image_dock->auto_follow_active)
    gimp_image_dock_set_auto_follow_active (image_dock, auto_follow);
}

static GList *
gimp_image_dock_get_aux_info (GimpDock *dock)
{
327
328
329
330
331
332
333
334
335
  GimpImageDock      *image_dock = GIMP_IMAGE_DOCK (dock);
  GList              *aux_info   = NULL;
  GimpSessionInfoAux *aux;

  aux = g_new0 (GimpSessionInfoAux, 1);
  aux->name  = g_strdup ("show-image-menu");
  aux->value = g_strdup (image_dock->show_image_menu ? "true" : "false");

  aux_info = g_list_append (aux_info, aux);
336

337
338
339
  aux = g_new0 (GimpSessionInfoAux, 1);
  aux->name  = g_strdup ("follow-auctive-image");
  aux->value = g_strdup (image_dock->auto_follow_active ? "true" : "false");
340

341
  aux_info = g_list_append (aux_info, aux);
342

343
  return aux_info;
344
345
}

346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
static void
gimp_image_dock_book_added (GimpDock     *dock,
                            GimpDockbook *dockbook)
{
  g_signal_connect (dockbook, "dockable_added",
                    G_CALLBACK (gimp_image_dock_dockbook_changed),
                    dock);
  g_signal_connect (dockbook, "dockable_removed",
                    G_CALLBACK (gimp_image_dock_dockbook_changed),
                    dock);
  g_signal_connect (dockbook, "dockable_reordered",
                    G_CALLBACK (gimp_image_dock_dockbook_changed),
                    dock);

  gimp_image_dock_update_title (GIMP_IMAGE_DOCK (dock));

  GIMP_DOCK_CLASS (parent_class)->book_added (dock, dockbook);
}

static void
gimp_image_dock_book_removed (GimpDock     *dock,
                              GimpDockbook *dockbook)
{
  g_signal_handlers_disconnect_by_func (dockbook,
                                        gimp_image_dock_dockbook_changed,
                                        dock);

  gimp_image_dock_update_title (GIMP_IMAGE_DOCK (dock));

375
  GIMP_DOCK_CLASS (parent_class)->book_removed (dock, dockbook);
376
377
}

Michael Natterer's avatar
Michael Natterer committed
378
GtkWidget *
379
gimp_image_dock_new (GimpDialogFactory *dialog_factory,
380
381
		     GimpContainer     *image_container,
                     GimpContainer     *display_container)
Michael Natterer's avatar
Michael Natterer committed
382
383
{
  GimpImageDock *image_dock;
384
  GimpContext   *context;
385
386
  gint           menu_preview_width;
  gint           menu_preview_height;
387

388
  g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (dialog_factory), NULL);
Michael Natterer's avatar
Michael Natterer committed
389
  g_return_val_if_fail (GIMP_IS_CONTAINER (image_container), NULL);
390
  g_return_val_if_fail (GIMP_IS_CONTAINER (display_container), NULL);
Michael Natterer's avatar
Michael Natterer committed
391

Michael Natterer's avatar
Michael Natterer committed
392
  image_dock = g_object_new (GIMP_TYPE_IMAGE_DOCK, NULL);
Michael Natterer's avatar
Michael Natterer committed
393

394
395
  image_dock->image_container   = image_container;
  image_dock->display_container = display_container;
Michael Natterer's avatar
Michael Natterer committed
396

397
398
399
  context = gimp_context_new (dialog_factory->context->gimp,
                              "Dock Context", NULL);

400
  gimp_dock_construct (GIMP_DOCK (image_dock), dialog_factory, context);
Michael Natterer's avatar
Michael Natterer committed
401

402
403
404
  gimp_help_connect (GTK_WIDGET (image_dock), gimp_standard_help_func,
                     GIMP_HELP_DOCK, NULL);

405
  gimp_context_define_properties (context,
406
407
408
409
				  GIMP_CONTEXT_ALL_PROPS_MASK &
				  ~(GIMP_CONTEXT_IMAGE_MASK |
				    GIMP_CONTEXT_DISPLAY_MASK),
				  FALSE);
410
  gimp_context_set_parent (context, dialog_factory->context);
Michael Natterer's avatar
Michael Natterer committed
411

412
  if (image_dock->auto_follow_active)
413
414
415
416
417
418
419
420
    {
      if (gimp_context_get_display (dialog_factory->context))
        gimp_context_copy_property (dialog_factory->context, context,
                                    GIMP_CONTEXT_PROP_DISPLAY);
      else
        gimp_context_copy_property (dialog_factory->context, context,
                                    GIMP_CONTEXT_PROP_IMAGE);
    }
421

422
  g_signal_connect_object (dialog_factory->context, "display_changed",
Michael Natterer's avatar
Michael Natterer committed
423
			   G_CALLBACK (gimp_image_dock_factory_display_changed),
424
			   image_dock,
Michael Natterer's avatar
Michael Natterer committed
425
			   0);
426
  g_signal_connect_object (dialog_factory->context, "image_changed",
427
			   G_CALLBACK (gimp_image_dock_factory_image_changed),
428
			   image_dock,
429
			   0);
Michael Natterer's avatar
Michael Natterer committed
430

431
  g_signal_connect_object (context, "image_changed",
432
			   G_CALLBACK (gimp_image_dock_image_changed),
433
			   image_dock,
434
			   0);
Michael Natterer's avatar
Michael Natterer committed
435

436
437
438
  gtk_icon_size_lookup (DEFAULT_MENU_PREVIEW_SIZE,
                        &menu_preview_width, &menu_preview_height);

439
  image_dock->menu = gimp_container_menu_new (image_container, context,
440
                                              menu_preview_height, 1);
Michael Natterer's avatar
Michael Natterer committed
441
442
443
444
  gtk_option_menu_set_menu (GTK_OPTION_MENU (image_dock->option_menu),
			    image_dock->menu);
  gtk_widget_show (image_dock->menu);

445
  g_object_unref (context);
446

Michael Natterer's avatar
Michael Natterer committed
447
448
  return GTK_WIDGET (image_dock);
}
Michael Natterer's avatar
Michael Natterer committed
449

450
451
452
453
454
455
456
457
458
459
void
gimp_image_dock_set_auto_follow_active (GimpImageDock *image_dock,
					gboolean       auto_follow_active)
{
  g_return_if_fail (GIMP_IS_IMAGE_DOCK (image_dock));

  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_dock->auto_button),
				auto_follow_active ? TRUE : FALSE);
}

Michael Natterer's avatar
Michael Natterer committed
460
461
462
463
464
465
466
void
gimp_image_dock_set_show_image_menu (GimpImageDock *image_dock,
				     gboolean       show)
{
  g_return_if_fail (GIMP_IS_IMAGE_DOCK (image_dock));

  if (show)
467
    gtk_widget_show (image_dock->option_menu->parent);
Michael Natterer's avatar
Michael Natterer committed
468
  else
469
    gtk_widget_hide (image_dock->option_menu->parent);
470
471

  image_dock->show_image_menu = show ? TRUE : FALSE;
Michael Natterer's avatar
Michael Natterer committed
472
473
}

474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
static void
gimp_image_dock_dockbook_changed (GimpDockbook  *dockbook,
                                  GimpDockable  *dockable,
                                  GimpImageDock *dock)
{
  gimp_image_dock_update_title (dock);
}

static gboolean
gimp_image_dock_update_title_idle (GimpImageDock *image_dock)
{
  GString *title;
  GList   *list;

  title = g_string_new (NULL);

  for (list = GIMP_DOCK (image_dock)->dockbooks;
       list;
       list = g_list_next (list))
    {
      GimpDockbook *dockbook = list->data;
      GList        *children;
      GList        *child;

      children = gtk_container_get_children (GTK_CONTAINER (dockbook));

      for (child = children; child; child = g_list_next (child))
        {
          GimpDockable *dockable = child->data;

504
          g_string_append (title, dockable->name);
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535

          if (g_list_next (child))
            g_string_append (title, ", ");
        }

      g_list_free (children);

      if (g_list_next (list))
        g_string_append (title, " | ");
    }

  gtk_window_set_title (GTK_WINDOW (image_dock), title->str);

  g_string_free (title, TRUE);

  image_dock->update_title_idle_id = 0;

  return FALSE;
}

static void
gimp_image_dock_update_title (GimpImageDock *image_dock)
{
  if (image_dock->update_title_idle_id)
    g_source_remove (image_dock->update_title_idle_id);

  image_dock->update_title_idle_id =
    g_idle_add ((GSourceFunc) gimp_image_dock_update_title_idle,
                image_dock);
}

Michael Natterer's avatar
Michael Natterer committed
536
537
538
539
540
541
542
543
544
545
static void
gimp_image_dock_factory_display_changed (GimpContext *context,
                                         GimpObject  *gdisp,
                                         GimpDock    *dock)
{
  GimpImageDock *image_dock;

  image_dock = GIMP_IMAGE_DOCK (dock);

  if (gdisp && image_dock->auto_follow_active)
546
    gimp_context_set_display (dock->context, gdisp);
Michael Natterer's avatar
Michael Natterer committed
547
548
}

Michael Natterer's avatar
Michael Natterer committed
549
550
551
552
553
554
555
556
557
static void
gimp_image_dock_factory_image_changed (GimpContext *context,
				       GimpImage   *gimage,
				       GimpDock    *dock)
{
  GimpImageDock *image_dock;

  image_dock = GIMP_IMAGE_DOCK (dock);

558
  /*  won't do anything if we already set the display above  */
Michael Natterer's avatar
Michael Natterer committed
559
  if (gimage && image_dock->auto_follow_active)
560
    gimp_context_set_image (dock->context, gimage);
Michael Natterer's avatar
Michael Natterer committed
561
562
563
564
565
566
567
568
569
570
571
}

static void
gimp_image_dock_image_changed (GimpContext *context,
			       GimpImage   *gimage,
			       GimpDock    *dock)
{
  GimpImageDock *image_dock;

  image_dock = GIMP_IMAGE_DOCK (dock);

572
573
  if (gimage == NULL &&
      gimp_container_num_children (image_dock->image_container) > 0)
Michael Natterer's avatar
Michael Natterer committed
574
575
576
    {
      gimage = GIMP_IMAGE (gimp_container_get_child_by_index (image_dock->image_container, 0));

577
578
579
580
581
      if (gimage)
	{
	  /*  this invokes this function recursively but we don't enter
	   *  the if() branch the second time
	   */
582
	  gimp_context_set_image (context, gimage);
583
584
585
586

	  /*  stop the emission of the original signal (the emission of
	   *  the recursive signal is finished)
	   */
587
	  g_signal_stop_emission_by_name (context, "image_changed");
588
	}
Michael Natterer's avatar
Michael Natterer committed
589
    }
590
591
  else if (gimage != NULL &&
           gimp_container_num_children (image_dock->display_container) > 0)
592
593
    {
      GimpObject *gdisp;
594
      GimpImage  *gdisp_gimage;
595
596
597
598
599
600
601
602
      gboolean    find_display = TRUE;

      gdisp = gimp_context_get_display (context);

      if (gdisp)
        {
          g_object_get (gdisp, "image", &gdisp_gimage, NULL);

603
604
605
606
607
608
609
          if (gdisp_gimage)
            {
              g_object_unref (gdisp_gimage);

              if (gdisp_gimage == gimage)
                find_display = FALSE;
            }
610
611
612
613
614
615
616
617
618
619
620
621
622
623
        }

      if (find_display)
        {
          GList *list;

          for (list = GIMP_LIST (image_dock->display_container)->list;
               list;
               list = g_list_next (list))
            {
              gdisp = GIMP_OBJECT (list->data);

              g_object_get (gdisp, "image", &gdisp_gimage, NULL);

624
              if (gdisp_gimage)
625
                {
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
                  g_object_unref (gdisp_gimage);

                  if (gdisp_gimage == gimage)
                    {
                      /*  this invokes this function recursively but we
                       *  don't enter the if(find_display) branch the
                       *  second time
                       */
                      gimp_context_set_display (context, gdisp);

                      /*  don't stop signal emission here because the
                       *  context's image was not changed by the
                       *  recursive call
                       */
                      break;
                    }
642
643
644
645
                }
            }
        }
    }
Michael Natterer's avatar
Michael Natterer committed
646
647
648
649
650
651
652
653
654
655
656
657
658
659
}

static void
gimp_image_dock_auto_clicked (GtkWidget *widget,
			      GimpDock  *dock)
{
  GimpImageDock *image_dock;

  image_dock = GIMP_IMAGE_DOCK (dock);

  gimp_toggle_button_update (widget, &image_dock->auto_follow_active);

  if (image_dock->auto_follow_active)
    {
660
      if (gimp_context_get_display (dock->dialog_factory->context))
661
662
        gimp_context_copy_property (dock->dialog_factory->context,
                                    dock->context,
663
                                    GIMP_CONTEXT_PROP_DISPLAY);
Michael Natterer's avatar
Michael Natterer committed
664
      else
665
666
        gimp_context_copy_property (dock->dialog_factory->context,
                                    dock->context,
667
                                    GIMP_CONTEXT_PROP_IMAGE);
Michael Natterer's avatar
Michael Natterer committed
668
669
    }
}