gimpitemfactory.c 29.6 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * 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
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
17
 */
Sven Neumann's avatar
Sven Neumann committed
18

19 20
#include "config.h"

21
#include "string.h"
22

Sven Neumann's avatar
Sven Neumann committed
23
#include <gtk/gtk.h>
24
#include <gdk/gdkkeysyms.h>
25

26
#include "libgimpbase/gimpbase.h"
27 28
#include "libgimpwidgets/gimpwidgets.h"

29 30
#include "widgets-types.h"

31 32
#include "config/gimpguiconfig.h"

33 34
#include "core/gimp.h"

35
#include "gimphelp-ids.h"
36
#include "gimpitemfactory.h"
37
#include "gimpwidgets-utils.h"
38

39
#include "gimphelp.h"
40

41
#include "gimp-intl.h"
42 43


44 45
/*  local function prototypes  */

46 47 48
static void     gimp_item_factory_class_init      (GimpItemFactoryClass *klass);
static void     gimp_item_factory_init            (GimpItemFactory      *factory);

49
static void     gimp_item_factory_finalize        (GObject              *object);
50
static void     gimp_item_factory_destroy         (GtkObject            *object);
51 52

static void     gimp_item_factory_create_branches (GimpItemFactory      *factory,
53 54
                                                   GimpItemFactoryEntry *entry,
                                                   const gchar          *textdomain);
55
static void     gimp_item_factory_item_realize    (GtkWidget            *widget,
56
                                                   GimpItemFactory      *factory);
57 58
static gboolean gimp_item_factory_item_key_press  (GtkWidget            *widget,
                                                   GdkEventKey          *kevent,
59
                                                   GimpItemFactory      *factory);
60 61
static gchar *  gimp_item_factory_translate_func  (const gchar          *path,
                                                   gpointer              data);
62

63

64
static GtkItemFactoryClass *parent_class = NULL;
65

66

67 68 69 70
GType
gimp_item_factory_get_type (void)
{
  static GType factory_type = 0;
71

72
  if (! factory_type)
73
    {
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
      static const GTypeInfo factory_info =
      {
        sizeof (GimpItemFactoryClass),
        NULL,           /* base_init */
        NULL,           /* base_finalize */
        (GClassInitFunc) gimp_item_factory_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (GimpItemFactory),
        0,              /* n_preallocs */
        (GInstanceInitFunc) gimp_item_factory_init,
      };

      factory_type = g_type_register_static (GTK_TYPE_ITEM_FACTORY,
					     "GimpItemFactory",
					     &factory_info, 0);
90
    }
91

92
  return factory_type;
93
}
94

95 96
static void
gimp_item_factory_class_init (GimpItemFactoryClass *klass)
97
{
98 99
  GObjectClass   *object_class;
  GtkObjectClass *gtk_object_class;
100

101 102
  object_class     = G_OBJECT_CLASS (klass);
  gtk_object_class = GTK_OBJECT_CLASS (klass);
103

104
  parent_class = g_type_class_peek_parent (klass);
105

106 107 108
  object_class->finalize    = gimp_item_factory_finalize;

  gtk_object_class->destroy = gimp_item_factory_destroy;
109

110 111
  klass->factories = g_hash_table_new_full (g_str_hash, g_str_equal,
                                            g_free, NULL);
Elliot Lee's avatar
Elliot Lee committed
112 113
}

114 115
static void
gimp_item_factory_init (GimpItemFactory *factory)
Elliot Lee's avatar
Elliot Lee committed
116
{
117 118 119 120 121
  factory->gimp              = NULL;
  factory->update_func       = NULL;
  factory->update_on_popup   = FALSE;
  factory->help_id           = NULL;
  factory->translation_trash = NULL;
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
}

static void
gimp_item_factory_finalize (GObject *object)
{
  GimpItemFactory *factory;

  factory = GIMP_ITEM_FACTORY (object);

  if (factory->help_id)
    {
      g_free (factory->help_id);
      factory->help_id = NULL;
    }

  G_OBJECT_CLASS (parent_class)->finalize (object);
138 139
}

140
static void
141
gimp_item_factory_destroy (GtkObject *object)
142
{
143
  GimpItemFactory *factory;
144
  gchar           *factory_path;
Elliot Lee's avatar
Elliot Lee committed
145

146
  factory = GIMP_ITEM_FACTORY (object);
147

148 149 150
  factory_path = GTK_ITEM_FACTORY (object)->path;

  if (factory_path)
151
    {
152 153 154 155 156 157
      GimpItemFactoryClass *factory_class;
      GList                *list;

      factory_class = GIMP_ITEM_FACTORY_GET_CLASS (factory);

      list = g_hash_table_lookup (factory_class->factories, factory_path);
158

159 160 161 162 163 164 165 166 167 168 169
      if (list)
        {
          list = g_list_remove (list, factory);

          if (list)
            g_hash_table_replace (factory_class->factories,
                                  g_strdup (factory_path),
                                  list);
          else
            g_hash_table_remove (factory_class->factories, factory_path);
        }
170
    }
171

172
  GTK_OBJECT_CLASS (parent_class)->destroy (object);
173 174 175
}


176 177 178
/*  public functions  */

GimpItemFactory *
179 180
gimp_item_factory_new (Gimp                      *gimp,
                       GType                      container_type,
181
                       const gchar               *factory_path,
182
                       const gchar               *help_id,
183
                       GimpItemFactoryUpdateFunc  update_func,
184
                       gboolean                   update_on_popup,
185 186 187 188
                       guint                      n_entries,
                       GimpItemFactoryEntry      *entries,
                       gpointer                   callback_data,
                       gboolean                   create_tearoff)
189
{
190 191
  GimpItemFactoryClass *factory_class;
  GimpItemFactory      *factory;
192
  GList                *list;
193

194
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
195
  g_return_val_if_fail (factory_path != NULL, NULL);
196
  g_return_val_if_fail (help_id != NULL, NULL);
197 198
  g_return_val_if_fail (factory_path[0] == '<', NULL);
  g_return_val_if_fail (factory_path[strlen (factory_path) - 1] == '>', NULL);
199

200 201 202 203 204 205
  factory_class = g_type_class_ref (GIMP_TYPE_ITEM_FACTORY);

  factory = g_object_new (GIMP_TYPE_ITEM_FACTORY, NULL);

  gtk_item_factory_construct (GTK_ITEM_FACTORY (factory),
                              container_type,
206
                              factory_path,
207 208 209
                              NULL);

  gtk_item_factory_set_translate_func (GTK_ITEM_FACTORY (factory),
210
				       gimp_item_factory_translate_func,
211
				       factory,
212 213
				       NULL);

214 215 216
  factory->gimp            = gimp;
  factory->update_func     = update_func;
  factory->update_on_popup = update_on_popup;
217
  factory->help_id         = g_strdup (help_id);
218 219

  list = g_hash_table_lookup (factory_class->factories, factory_path);
220

221
  list = g_list_append (list, factory);
222

223 224 225
  g_hash_table_replace (factory_class->factories,
                        g_strdup (factory_path),
                        list);
226

227 228 229 230 231 232 233
  gimp_item_factory_create_items (factory,
                                  n_entries,
                                  entries,
                                  callback_data,
                                  2,
                                  create_tearoff,
                                  TRUE);
234

235 236
  g_type_class_unref (factory_class);

237 238 239
  return factory;
}

240 241
GimpItemFactory *
gimp_item_factory_from_path (const gchar *path)
242 243 244 245 246 247 248 249 250 251 252 253 254
{
  GList *list;

  list = gimp_item_factories_from_path (path);

  if (list)
    return list->data;

  return NULL;
}

GList *
gimp_item_factories_from_path (const gchar *path)
255
{
256
  GimpItemFactoryClass *factory_class;
257
  GList                *list;
258 259
  gchar                *base_path;
  gchar                *p;
260

261
  g_return_val_if_fail (path != NULL, NULL);
262

263
  base_path = g_strdup (path);
264

265
  p = strchr (base_path, '>');
266

267 268
  if (p)
    p[1] = '\0';
269

270 271
  factory_class = g_type_class_ref (GIMP_TYPE_ITEM_FACTORY);

272
  list = g_hash_table_lookup (factory_class->factories, base_path);
273 274 275 276 277

  g_type_class_unref (factory_class);

  g_free (base_path);

278
  return list;
279 280
}

281
void
282
gimp_item_factory_create_item (GimpItemFactory       *item_factory,
283
                               GimpItemFactoryEntry  *entry,
284
                               const gchar           *textdomain,
285 286 287 288 289 290
                               gpointer               callback_data,
                               guint                  callback_type,
                               gboolean               create_tearoff,
                               gboolean               static_entry)
{
  GtkWidget *menu_item;
291
  gchar     *menu_path;
292
  gboolean   tearoffs;
293

294
  g_return_if_fail (GIMP_IS_ITEM_FACTORY (item_factory));
295 296
  g_return_if_fail (entry != NULL);

297 298
  tearoffs = GIMP_GUI_CONFIG (item_factory->gimp->config)->tearoff_menus;

299
  if (! (strstr (entry->entry.path, "tearoff")))
300
    {
301
      if (tearoffs && create_tearoff)
302
	{
303
	  gimp_item_factory_create_branches (item_factory, entry, textdomain);
304
	}
305
    }
306
  else if (! tearoffs || ! create_tearoff)
307
    {
308
      return;
309
    }
310

311
  if (entry->quark_string)
312
    {
313 314 315 316 317 318 319 320
      GQuark quark;

      if (static_entry)
	quark = g_quark_from_static_string (entry->quark_string);
      else
	quark = g_quark_from_string (entry->quark_string);

      entry->entry.callback_action = (guint) quark;
321 322
    }

323 324 325 326
  if (textdomain)
    g_object_set_data (G_OBJECT (item_factory), "textdomain",
                       (gpointer) textdomain);

327
  gtk_item_factory_create_item (GTK_ITEM_FACTORY (item_factory),
328 329 330 331
				(GtkItemFactoryEntry *) entry,
				callback_data,
				callback_type);

332 333 334
  if (textdomain)
    g_object_set_data (G_OBJECT (item_factory), "textdomain", NULL);

335 336 337 338 339 340 341
  if (item_factory->translation_trash)
    {
      g_list_foreach (item_factory->translation_trash, (GFunc) g_free, NULL);
      g_list_free (item_factory->translation_trash);
      item_factory->translation_trash = NULL;
    }

342
  menu_path = gimp_strip_uline (((GtkItemFactoryEntry *) entry)->path);
343

344
  menu_item = gtk_item_factory_get_item (GTK_ITEM_FACTORY (item_factory),
345 346 347
                                         menu_path);

  g_free (menu_path);
348 349

  if (menu_item)
350
    {
351
      g_signal_connect_after (menu_item, "realize",
352 353 354
			      G_CALLBACK (gimp_item_factory_item_realize),
			      item_factory);

355
      if (entry->help_id)
356 357
        {
          if (static_entry)
358 359
            g_object_set_data (G_OBJECT (menu_item), "gimp-help-id",
                               (gpointer) entry->help_id);
360
          else
361 362
            g_object_set_data_full (G_OBJECT (menu_item), "gimp-help-id",
                                    g_strdup (entry->help_id),
363 364
                                    g_free);
        }
365
    }
366
}
367

368
void
369
gimp_item_factory_create_items (GimpItemFactory      *item_factory,
370 371 372 373 374 375 376 377 378 379
                                guint                 n_entries,
                                GimpItemFactoryEntry *entries,
                                gpointer              callback_data,
                                guint                 callback_type,
                                gboolean              create_tearoff,
                                gboolean              static_entries)
{
  gint i;

  for (i = 0; i < n_entries; i++)
380
    {
381 382
      gimp_item_factory_create_item (item_factory,
                                     entries + i,
383
                                     NULL,
384 385 386 387
                                     callback_data,
                                     callback_type,
                                     create_tearoff,
                                     static_entries);
388
    }
389
}
390

391 392 393 394 395 396 397 398 399 400
void
gimp_item_factory_update (GimpItemFactory *item_factory,
                          gpointer         popup_data)
{
  g_return_if_fail (GIMP_IS_ITEM_FACTORY (item_factory));

  if (item_factory->update_func)
    item_factory->update_func (GTK_ITEM_FACTORY (item_factory), popup_data);
}

401
void
402 403 404 405 406
gimp_item_factory_popup_with_data (GimpItemFactory      *item_factory,
				   gpointer              popup_data,
                                   GimpMenuPositionFunc  position_func,
                                   gpointer              position_data,
                                   GtkDestroyNotify      popdown_func)
407
{
408 409 410 411
  GdkEvent *current_event;
  gint      x, y;
  guint     button;
  guint32   activate_time;
412 413 414

  g_return_if_fail (GIMP_IS_ITEM_FACTORY (item_factory));

415
  if (item_factory->update_on_popup)
416
    gimp_item_factory_update (item_factory, popup_data);
417

418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
  if (! position_func)
    {
      position_func = gimp_menu_position;
      position_data = NULL;
    }

  (* position_func) (GTK_MENU (GTK_ITEM_FACTORY (item_factory)->widget),
                     &x, &y, position_data);

  current_event = gtk_get_current_event ();

  if (current_event && current_event->type == GDK_BUTTON_PRESS)
    {
      GdkEventButton *bevent;

      bevent = (GdkEventButton *) current_event;

      button        = bevent->button;
      activate_time = bevent->time;
    }
  else
    {
      button        = 0;
      activate_time = 0;
    }
443 444

  gtk_item_factory_popup_with_data (GTK_ITEM_FACTORY (item_factory),
445
				    popup_data,
446 447 448 449 450 451
				    popdown_func,
				    x, y,
				    button,
				    activate_time);
}

452 453
void
gimp_item_factory_set_active (GtkItemFactory *factory,
454
                              const gchar    *path,
455 456 457 458 459 460 461 462 463 464
                              gboolean        active)
{
  GtkWidget *widget;

  g_return_if_fail (GTK_IS_ITEM_FACTORY (factory));
  g_return_if_fail (path != NULL);

  widget = gtk_item_factory_get_widget (factory, path);

  if (widget)
465
    {
466 467 468 469 470 471
      if (GTK_IS_CHECK_MENU_ITEM (widget))
        {
          gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), active);
        }
      else
        {
472 473 474 475 476
          g_warning ("%s: Unable to set \"active\" for menu item "
                     "of type \"%s\": %s",
                     G_STRLOC,
                     g_type_name (G_TYPE_FROM_INSTANCE (widget)),
                     path);
477
        }
478
    }
479
  else if (! strstr (path, "Script-Fu"))
480
    {
481
      g_warning ("%s: Unable to set \"active\" for menu item "
482
                 "which doesn't exist: %s",
483
                 G_STRLOC, path);
484
    }
485 486
}

487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
void
gimp_item_factories_set_active (const gchar *factory_path,
                                const gchar *path,
                                gboolean     active)
{
  GList *list;

  g_return_if_fail (factory_path != NULL);
  g_return_if_fail (path != NULL);

  for (list = gimp_item_factories_from_path (factory_path);
       list;
       list = g_list_next (list))
    {
      gimp_item_factory_set_active (GTK_ITEM_FACTORY (list->data),
                                    path, active);
    }
}

506
void
507
gimp_item_factory_set_color (GtkItemFactory *factory,
508
                             const gchar    *path,
509 510
                             const GimpRGB  *color,
                             gboolean        set_label)
511
{
512
  GtkWidget *widget;
513 514
  GtkWidget *area  = NULL;
  GtkWidget *label = NULL;
515

516 517 518
  g_return_if_fail (GTK_IS_ITEM_FACTORY (factory));
  g_return_if_fail (path != NULL);
  g_return_if_fail (color != NULL);
519

520
  widget = gtk_item_factory_get_widget (factory, path);
521

522
  if (! widget)
523
    {
524
      g_warning ("%s: Unable to set color of menu item "
525
                 "which doesn't exist: %s",
526 527 528
                 G_STRLOC, path);
      return;
    }
529

530 531
  if (GTK_IS_HBOX (GTK_BIN (widget)->child))
    {
532 533
      area = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child),
                                "color_area");
534 535
      label = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child),
                                 "label");
536
    }
537
  else if (GTK_IS_LABEL (GTK_BIN (widget)->child))
538
    {
539
      GtkWidget *hbox;
540
      gint       width, height;
541

542
      label = GTK_BIN (widget)->child;
543

544
      g_object_ref (label);
545

546
      gtk_container_remove (GTK_CONTAINER (widget), label);
547

548 549 550 551
      hbox = gtk_hbox_new (FALSE, 4);
      gtk_container_add (GTK_CONTAINER (widget), hbox);
      gtk_widget_show (hbox);

552
      area = gimp_color_area_new (color, GIMP_COLOR_AREA_SMALL_CHECKS, 0);
553 554
      gimp_color_area_set_draw_border (GIMP_COLOR_AREA (area), TRUE);

555 556 557
      gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);

      gtk_widget_set_size_request (area, width, height);
558 559
      gtk_box_pack_start (GTK_BOX (hbox), area, FALSE, FALSE, 0);
      gtk_widget_show (area);
560

561
      gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
562 563
      gtk_widget_show (label);

564
      g_object_unref (label);
565

566 567
      g_object_set_data (G_OBJECT (hbox), "color_area", area);
      g_object_set_data (G_OBJECT (hbox), "label",      label);
568 569
    }

570 571
  if (area)
    gimp_color_area_set_color (GIMP_COLOR_AREA (area), color);
572

573
  if (label && set_label)
574
    {
575 576 577 578
      gchar *str;

      str = g_strdup_printf (_("RGBA (%0.3f, %0.3f, %0.3f, %0.3f)"),
                             color->r, color->g, color->b, color->a);
579

580 581 582
      gtk_label_set_text (GTK_LABEL (label), str);

      g_free (str);
583
    }
584 585
}

586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
void
gimp_item_factories_set_color (const gchar   *factory_path,
                               const gchar   *path,
                               const GimpRGB *color,
                               gboolean       set_label)
{
  GList *list;

  g_return_if_fail (factory_path != NULL);
  g_return_if_fail (path != NULL);
  g_return_if_fail (color != NULL);

  for (list = gimp_item_factories_from_path (factory_path);
       list;
       list = g_list_next (list))
    {
      gimp_item_factory_set_color (GTK_ITEM_FACTORY (list->data),
                                   path, color, set_label);
    }
}

607 608
void
gimp_item_factory_set_label (GtkItemFactory *factory,
609
                             const gchar    *path,
610 611 612 613 614 615 616 617 618 619 620
                             const gchar    *label)
{
  GtkWidget *widget;

  g_return_if_fail (GTK_IS_ITEM_FACTORY (factory));
  g_return_if_fail (path != NULL);
  g_return_if_fail (label != NULL);

  widget = gtk_item_factory_get_widget (factory, path);

  if (widget)
621
    {
622
      if (GTK_IS_MENU (widget))
623
        widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
624

625
      if (GTK_IS_LABEL (GTK_BIN (widget)->child))
626 627
        gtk_label_set_text_with_mnemonic (GTK_LABEL (GTK_BIN (widget)->child),
                                          label);
628
    }
629
  else
630
    {
631
      g_warning ("%s: Unable to set label of menu item "
632
                 "which doesn't exist: %s",
633 634 635
                 G_STRLOC, path);
    }
}
636

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
void
gimp_item_factories_set_label (const gchar *factory_path,
                               const gchar *path,
                               const gchar *label)
{
  GList *list;

  g_return_if_fail (factory_path != NULL);
  g_return_if_fail (path != NULL);
  g_return_if_fail (label != NULL);

  for (list = gimp_item_factories_from_path (factory_path);
       list;
       list = g_list_next (list))
    {
      gimp_item_factory_set_label (GTK_ITEM_FACTORY (list->data),
                                   path, label);
    }
}

657 658
void
gimp_item_factory_set_sensitive (GtkItemFactory *factory,
659
                                 const gchar    *path,
660 661 662
                                 gboolean        sensitive)
{
  GtkWidget *widget;
663

664 665
  g_return_if_fail (GTK_IS_ITEM_FACTORY (factory));
  g_return_if_fail (path != NULL);
666

667 668 669 670 671 672 673 674
  widget = gtk_item_factory_get_widget (factory, path);

  if (widget)
    {
      gtk_widget_set_sensitive (widget, sensitive);
    }
  else if (! strstr (path, "Script-Fu"))
    {
675
      g_warning ("%s: Unable to set sensitivity of menu item "
676
                 "which doesn't exist: %s",
677
                 G_STRLOC, path);
678
    }
679
}
680

681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
void
gimp_item_factories_set_sensitive (const gchar *factory_path,
                                   const gchar *path,
                                   gboolean     sensitive)
{
  GList *list;

  g_return_if_fail (factory_path != NULL);
  g_return_if_fail (path != NULL);

  for (list = gimp_item_factories_from_path (factory_path);
       list;
       list = g_list_next (list))
    {
      gimp_item_factory_set_sensitive (GTK_ITEM_FACTORY (list->data),
                                       path, sensitive);
    }
}

700 701
void
gimp_item_factory_set_visible (GtkItemFactory *factory,
702
                               const gchar    *path,
703 704 705 706 707 708 709 710
                               gboolean        visible)
{
  GtkWidget *widget;

  g_return_if_fail (GTK_IS_ITEM_FACTORY (factory));
  g_return_if_fail (path != NULL);

  widget = gtk_item_factory_get_widget (factory, path);
711

712
  if (widget)
713
    {
714 715 716
      if (GTK_IS_MENU (widget))
        widget = gtk_menu_get_attach_widget (GTK_MENU (widget));

717 718 719 720 721 722 723
      if (visible)
        gtk_widget_show (widget);
      else
        gtk_widget_hide (widget);
    }
  else
    {
724
      g_warning ("%s: Unable to set visibility of menu item "
725 726 727 728 729
                 "which doesn't exist: %s",
                 G_STRLOC, path);
    }
}

730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
void
gimp_item_factories_set_visible (const gchar *factory_path,
                                 const gchar *path,
                                 gboolean     visible)
{
  GList *list;

  g_return_if_fail (factory_path != NULL);
  g_return_if_fail (path != NULL);

  for (list = gimp_item_factories_from_path (factory_path);
       list;
       list = g_list_next (list))
    {
      gimp_item_factory_set_visible (GTK_ITEM_FACTORY (list->data),
                                     path, visible);
    }
}

749 750 751 752 753 754 755 756 757 758
void
gimp_item_factory_tearoff_callback (GtkWidget *widget,
                                    gpointer   data,
                                    guint      action)
{
  if (GTK_IS_TEAROFF_MENU_ITEM (widget))
    {
      GtkTearoffMenuItem *tomi = (GtkTearoffMenuItem *) widget;

      if (tomi->torn_off)
759
	{
760 761 762
	  GtkWidget *toplevel;

	  toplevel = gtk_widget_get_toplevel (widget);
763

764
	  if (! GTK_IS_WINDOW (toplevel))
765
	    {
766 767 768 769 770 771 772 773 774 775
	      g_warning ("%s: tearoff menu not in top level window",
                         G_STRLOC);
	    }
	  else
	    {
#ifdef __GNUC__
#warning FIXME: register tearoffs
#endif
	      g_object_set_data (G_OBJECT (widget), "tearoff-menu-toplevel",
                                 toplevel);
776
	    }
777 778 779 780
	}
      else
	{
	  GtkWidget *toplevel;
781

782 783
	  toplevel = (GtkWidget *) g_object_get_data (G_OBJECT (widget),
                                                      "tearoff-menu-toplevel");
784

785 786 787 788 789 790 791 792 793 794
	  if (! toplevel)
	    {
	      g_warning ("%s: can't unregister tearoff menu top level window",
                         G_STRLOC);
	    }
	  else
	    {
#ifdef __GNUC__
#warning FIXME: unregister tearoffs
#endif
795 796 797 798 799 800
	    }
	}
    }
}


801
/*  private functions  */
802

803
static void
804
gimp_item_factory_create_branches (GimpItemFactory      *factory,
805 806
                                   GimpItemFactoryEntry *entry,
                                   const gchar          *textdomain)
807
{
808 809 810 811 812 813
  GString *tearoff_path;
  gint     factory_length;
  gchar   *p;

  if (! entry->entry.path)
    return;
814

815
  tearoff_path = g_string_new ("");
816

Sven Neumann's avatar
Sven Neumann committed
817
  p = strchr (entry->entry.path, '/');
818
  factory_length = p - entry->entry.path;
819 820 821 822 823 824

  /*  skip the first slash  */
  if (p)
    p = strchr (p + 1, '/');

  while (p)
825
    {
826 827
      g_string_assign (tearoff_path, entry->entry.path + factory_length);
      g_string_truncate (tearoff_path, p - entry->entry.path - factory_length);
828

829 830
      if (! gtk_item_factory_get_widget (GTK_ITEM_FACTORY (factory),
                                         tearoff_path->str))
831
	{
832 833
	  GimpItemFactoryEntry branch_entry =
	  {
834
	    { NULL, NULL, NULL, 0, "<Branch>" },
835 836 837 838
	    NULL,
	    NULL
	  };

839
          branch_entry.entry.path = tearoff_path->str;
840

841
          g_object_set_data (G_OBJECT (factory), "complete", entry->entry.path);
842 843 844

	  gimp_item_factory_create_item (factory,
                                         &branch_entry,
845
                                         textdomain,
846 847 848
                                         NULL, 2, TRUE, FALSE);

	  g_object_set_data (G_OBJECT (factory), "complete", NULL);
849
	}
850

851
      g_string_append (tearoff_path, "/tearoff");
852

853 854
      if (! gtk_item_factory_get_widget (GTK_ITEM_FACTORY (factory),
                                         tearoff_path->str))
855
	{
856 857
	  GimpItemFactoryEntry tearoff_entry =
	  {
858
	    { NULL, NULL,
859
              gimp_item_factory_tearoff_callback, 0, "<Tearoff>" },
860 861 862 863
	    NULL,
	    NULL, NULL
	  };

864 865 866
	  tearoff_entry.entry.path = tearoff_path->str;

          gimp_item_factory_create_item (factory,
867
                                         &tearoff_entry,
868
                                         textdomain,
869
                                         NULL, 2, TRUE, FALSE);
870
	}
871 872

      p = strchr (p + 1, '/');
873
    }
874

875 876 877 878
  g_string_free (tearoff_path, TRUE);
}

static void
879 880
gimp_item_factory_item_realize (GtkWidget       *widget,
                                GimpItemFactory *item_factory)
881 882
{
  if (GTK_IS_MENU_SHELL (widget->parent))
883
    {
884 885 886 887 888 889 890 891
      static GQuark quark_key_press_connected = 0;

      if (! quark_key_press_connected)
        quark_key_press_connected =
          g_quark_from_static_string ("gimp-menu-item-key-press-connected");

      if (! GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (widget->parent),
                                                 quark_key_press_connected)))
892
	{
893
	  g_signal_connect (widget->parent, "key_press_event",