home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / docindex.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-20  |  19.0 KB  |  839 lines

  1. /* docindex.c - Creates the window used by the document index in go and gimp.
  2.  *
  3.  * Copyright (C) 1998 Chris Lahey.
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  */
  15. #include "config.h"
  16.  
  17. #include <ctype.h>
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21.  
  22. #include <gtk/gtk.h>
  23.  
  24. #include "dialog_handler.h"
  25. #include "docindex.h"
  26. #include "fileops.h"
  27. #include "gdisplay.h"
  28. #include "gimpimageP.h"
  29. #include "gimpui.h"
  30. #include "gimpdnd.h"
  31. #include "ops_buttons.h"
  32. #include "session.h"
  33.  
  34. #include "libgimp/gimpenv.h"
  35.  
  36. #include "libgimp/gimpintl.h"
  37.  
  38. #include "pixmaps/folder.xpm"
  39. #include "pixmaps/raise.xpm"
  40. #include "pixmaps/lower.xpm"
  41. #include "pixmaps/delete.xpm"
  42.  
  43.  
  44. typedef struct
  45. {
  46.   GtkWidget *window;
  47.   GtkWidget *list;
  48. } IdeaManager;
  49.  
  50. typedef struct
  51. {
  52.   gboolean  boole;
  53.   gchar    *string;
  54.   gpointer  data;
  55. } BoolCharPair;
  56.  
  57.  
  58. /*  forward declarations  */
  59.  
  60. static void      create_idea_list                  (void);
  61. static void      idea_add_in_position              (gchar       *label,
  62.                             gint         position);
  63. static void      open_idea_window                  (void);
  64. static void      open_or_raise                     (gchar       *file_name,
  65.                             gboolean    try_raise);
  66.  
  67. static void      idea_open_callback                (GtkWidget   *widget,
  68.                             gpointer     data);
  69. static void      idea_open_or_raise_callback       (GtkWidget   *widget,
  70.                             gpointer     data);
  71. static void      idea_up_callback                  (GtkWidget   *widget,
  72.                             gpointer     data);
  73. static void      idea_to_top_callback              (GtkWidget   *widget,
  74.                             gpointer     data);
  75. static void      idea_down_callback                (GtkWidget   *widget,
  76.                             gpointer     data);
  77. static void      idea_to_bottom_callback           (GtkWidget   *widget,
  78.                             gpointer     data);
  79. static void      idea_remove_callback              (GtkWidget   *widget,
  80.                             gpointer     data);
  81. static void      idea_hide_callback                (GtkWidget   *widget,
  82.                             gpointer     data);
  83.  
  84. static void      load_idea_manager                 (IdeaManager *ideas);
  85. static void      save_idea_manager                 (IdeaManager *ideas);
  86.  
  87. static void      clear_white                       (FILE        *fp);
  88. static gint      getinteger                        (FILE        *fp);
  89.  
  90.  
  91. /*  local variables  */
  92.  
  93. static IdeaManager *ideas     = NULL;
  94. static GList       *idea_list = NULL;
  95.  
  96.  
  97. /*  the ops buttons  */
  98. static GtkSignalFunc open_ext_callbacks[] = 
  99. {
  100.   idea_open_or_raise_callback, file_open_callback, NULL, NULL
  101. };
  102.  
  103. static GtkSignalFunc raise_ext_callbacks[] = 
  104. {
  105.   idea_to_top_callback, NULL, NULL, NULL
  106. };
  107.  
  108. static GtkSignalFunc lower_ext_callbacks[] = 
  109. {
  110.   idea_to_bottom_callback, NULL, NULL, NULL
  111. };
  112.  
  113. static OpsButton ops_buttons[] =
  114. {
  115.   { folder_xpm, idea_open_callback, open_ext_callbacks,
  116.     N_("Open the selected entry\n"
  117.        "<Shift> Raise window if already open\n"
  118.        "<Ctrl> Load Image dialog"), NULL,
  119.     NULL, 0 },
  120.   { raise_xpm, idea_up_callback, raise_ext_callbacks,
  121.     N_("Move the selected entry up in the index\n"
  122.        "<Shift> To top"), NULL,
  123.     NULL, 0 },
  124.   { lower_xpm, idea_down_callback, lower_ext_callbacks,
  125.     N_("Move the selected entry down in the index\n"
  126.        "<Shift> To bottom"), NULL,
  127.     NULL, 0 },
  128.   { delete_xpm, idea_remove_callback, NULL,
  129.     N_("Remove the selected entry from the index"), NULL,
  130.     NULL, 0 },
  131.   { NULL, NULL, NULL, NULL, NULL, NULL, 0 }
  132. };
  133.  
  134.  
  135. /*  dnd stuff  */
  136.  
  137. static GtkTargetEntry drag_types[] =
  138. {
  139.   GIMP_TARGET_URI_LIST,
  140.   GIMP_TARGET_TEXT_PLAIN,
  141.   GIMP_TARGET_NETSCAPE_URL
  142. };
  143. static gint n_drag_types = sizeof (drag_types) / sizeof (drag_types[0]);
  144.  
  145.  
  146. /*  public functions  */
  147.  
  148. void
  149. document_index_create (void)
  150. {
  151.   if (ideas)
  152.     gdk_window_raise (ideas->window->window);
  153.   else
  154.     open_idea_window ();
  155. }
  156.  
  157. void
  158. document_index_free (void)
  159. {
  160.   idea_hide_callback (NULL, NULL);
  161. }
  162.  
  163. void
  164. document_index_add (gchar *title)
  165. {
  166.   idea_add_in_position (title, 0);
  167. }
  168.  
  169. FILE *
  170. document_index_parse_init (void)
  171. {
  172.   FILE  *fp;
  173.   gchar *desktopfile;
  174.   gint   dummy;
  175.  
  176.   desktopfile = gimp_personal_rc_file ("ideas");
  177.  
  178.   fp = fopen (desktopfile, "r");
  179.  
  180.   if (fp != NULL)
  181.     {
  182.       /*  eventually strip away the old file format's first line  */
  183.       if (fscanf (fp, "%i %i %i %i", &dummy, &dummy, &dummy, &dummy) != 4)
  184.     {
  185.       fclose (fp);
  186.       fp = fopen (desktopfile, "r");
  187.     }
  188.     }
  189.  
  190.   g_free (desktopfile);
  191.  
  192.   return fp;
  193. }
  194.  
  195. gchar *
  196. document_index_parse_line (FILE * fp)
  197. {
  198.   gint   length;
  199.   gchar *filename;
  200.  
  201.   length = getinteger (fp);
  202.  
  203.   if (!feof (fp) && !ferror (fp))
  204.     {
  205.       filename = g_malloc0 (length + 1);
  206.       filename[fread (filename, 1, length, fp)] = 0;
  207.       clear_white (fp);
  208.       return filename;
  209.     }
  210.  
  211.   return NULL;
  212. }
  213.  
  214.  
  215. /*  local functions  */
  216.  
  217. static void
  218. load_from_list (gpointer data,
  219.         gpointer data_null)
  220. {
  221.   idea_add_in_position ((gchar *) data, -1);
  222. }
  223.  
  224. static void
  225. load_idea_manager (IdeaManager *ideas)
  226. {
  227.   FILE *fp = NULL;
  228.  
  229.   if (! idea_list)
  230.     fp = document_index_parse_init ();
  231.  
  232.   if (idea_list || fp)
  233.     {
  234.       gtk_widget_show (ideas->window);
  235.  
  236.       if (fp)
  237.     {
  238.       gchar *title;
  239.  
  240.       clear_white (fp);
  241.  
  242.       while ((title = document_index_parse_line (fp)))
  243.         {
  244.           idea_add_in_position (title, -1);
  245.           g_free (title);
  246.         }
  247.       fclose (fp);
  248.     }
  249.       else
  250.     {
  251.       g_list_foreach (idea_list, load_from_list, NULL);
  252.       g_list_foreach (idea_list, (GFunc) g_free, NULL);
  253.       g_list_free (idea_list);
  254.       idea_list = 0;
  255.     }
  256.     }
  257.   else
  258.     {
  259.       gtk_widget_show (ideas->window);
  260.     }
  261. }
  262.  
  263. static void
  264. save_to_ideas (gpointer data,
  265.            gpointer user_data)
  266. {
  267.   gchar *title;
  268.  
  269.   title = GTK_LABEL (GTK_BIN (data)->child)->label;
  270.  
  271.   fprintf ((FILE *) user_data, "%d %s\n", strlen (title), title);
  272. }
  273.  
  274. static void
  275. save_list_to_ideas (gpointer data,
  276.             gpointer user_data)
  277. {
  278.   gchar *title;
  279.  
  280.   title = (gchar *) data;
  281.  
  282.   fprintf ((FILE *) user_data, "%d %s\n", strlen (title), title);
  283. }
  284.  
  285. static void
  286. save_idea_manager (IdeaManager *ideas)
  287. {
  288.   FILE  *fp;
  289.   gchar *desktopfile;
  290.     
  291.   /* open persistant desktop file. */
  292.   desktopfile = gimp_personal_rc_file ("ideas");
  293.   fp = fopen (desktopfile, "w");
  294.   g_free (desktopfile);
  295.  
  296.   if (fp)
  297.     {
  298.       if (ideas)
  299.     {
  300.       g_list_foreach (GTK_LIST (ideas->list)->children, save_to_ideas, fp);
  301.     }
  302.       else if (idea_list)
  303.     {
  304.       g_list_foreach (idea_list, save_list_to_ideas, fp);
  305.     }
  306.  
  307.       fclose (fp);
  308.     }
  309. }
  310.  
  311. static void
  312. save_to_list (gpointer data,
  313.           gpointer null_data)
  314. {
  315.   gchar *title;
  316.  
  317.   title = g_strdup (GTK_LABEL (GTK_BIN (data)->child)->label);
  318.  
  319.   idea_list = g_list_append (idea_list, title);
  320. }
  321.  
  322. static void
  323. create_idea_list (void)
  324. {
  325.   if (idea_list)
  326.     {
  327.       g_list_foreach (idea_list, (GFunc) g_free, NULL);
  328.       g_list_free (idea_list);
  329.       idea_list = 0;
  330.     }
  331.  
  332.   g_list_foreach (GTK_LIST (ideas->list)->children, save_to_list, NULL);
  333. }
  334.  
  335. static gint
  336. list_item_callback (GtkWidget      *widget,
  337.             GdkEventButton *event,
  338.             gpointer        data)
  339. {
  340.   if (GTK_IS_LIST_ITEM (widget) &&
  341.       event->type == GDK_2BUTTON_PRESS)
  342.     {
  343.       open_or_raise (GTK_LABEL (GTK_BIN (widget)->child)->label, FALSE);
  344.     }
  345.  
  346.   return FALSE;
  347.  
  348. static void
  349. check_needed (gpointer data,
  350.           gpointer user_data)
  351. {
  352.   BoolCharPair *pair;
  353.  
  354.   pair = (BoolCharPair *) user_data;
  355.  
  356.   if (strcmp (pair->string, GTK_LABEL (GTK_BIN (data)->child)->label) == 0)
  357.     {
  358.       pair->boole = TRUE;
  359.       pair->data  = data;
  360.     }
  361. }
  362.  
  363. static void
  364. check_needed_list (gpointer data,
  365.            gpointer user_data)
  366. {
  367.   BoolCharPair *pair;
  368.  
  369.   pair = (BoolCharPair *) user_data;
  370.  
  371.   if (strcmp (pair->string, (gchar *) data) == 0)
  372.     {
  373.       pair->boole = TRUE;
  374.       pair->data  = data;
  375.     }
  376. }
  377.  
  378. static void
  379. idea_add_in_position_with_select (gchar    *title,
  380.                   gint      position,
  381.                   gboolean  select)
  382. {
  383.   BoolCharPair  pair;
  384.  
  385.   pair.boole  = FALSE;
  386.   pair.string = title;
  387.   pair.data   = NULL;
  388.  
  389.   if (ideas)
  390.     {
  391.       g_list_foreach (GTK_LIST (ideas->list)->children, check_needed, &pair);
  392.  
  393.       if (! pair.boole)
  394.     {
  395.       GtkWidget *listitem;
  396.       GList     *list = NULL;
  397.  
  398.       listitem = gtk_list_item_new_with_label (title);
  399.       list = g_list_append (list, listitem);
  400.  
  401.       if (position < 0)
  402.         gtk_list_append_items (GTK_LIST (ideas->list), list);
  403.       else
  404.         gtk_list_insert_items (GTK_LIST (ideas->list), list, position);
  405.  
  406.       gtk_signal_connect (GTK_OBJECT (listitem), "button_press_event",
  407.                   GTK_SIGNAL_FUNC (list_item_callback),
  408.                   NULL);
  409.  
  410.       gtk_widget_show (listitem);
  411.  
  412.       if (select)
  413.         gtk_list_item_select (GTK_LIST_ITEM  (listitem));
  414.     }
  415.       else /* move entry to top */
  416.     {
  417.       gchar *title;
  418.  
  419.       title = g_strdup (GTK_LABEL (GTK_BIN (pair.data)->child)->label);
  420.       gtk_container_remove (GTK_CONTAINER (ideas->list),
  421.                 GTK_WIDGET (pair.data));
  422.       idea_add_in_position_with_select (title, 0, TRUE);
  423.       g_free (title); 
  424.     }
  425.     }
  426.   else
  427.     {
  428.       if (! idea_list)
  429.     {
  430.       FILE  *fp;
  431.  
  432.       fp = document_index_parse_init ();
  433.  
  434.       if (fp)
  435.         {  
  436.           gchar *filename;
  437.  
  438.           while ((filename = document_index_parse_line (fp)))
  439.         {
  440.           idea_list = g_list_append (idea_list, g_strdup (filename));
  441.           g_free (filename);
  442.         }
  443.  
  444.           fclose (fp);
  445.         }
  446.     }
  447.  
  448.       g_list_foreach (idea_list, check_needed_list, &pair);
  449.  
  450.       if (! pair.boole)
  451.     {
  452.       if (position < 0)
  453.         idea_list = g_list_prepend (idea_list, g_strdup (title));
  454.       else
  455.         idea_list = g_list_insert (idea_list, g_strdup (title), position);
  456.     }
  457.       else /* move entry to top */
  458.     {
  459.       idea_list = g_list_remove (idea_list, pair.data);
  460.       g_free (pair.data);
  461.       idea_list = g_list_prepend (idea_list, g_strdup (title));
  462.     }
  463.     }
  464. }
  465.  
  466. static void
  467. idea_add_in_position (gchar *title,
  468.               gint   position)
  469. {
  470.   idea_add_in_position_with_select (title, position, TRUE);
  471. }
  472.  
  473. static void
  474. raise_if_match (gpointer data,
  475.         gpointer user_data)
  476. {
  477.   GDisplay     *gdisp;
  478.   BoolCharPair *pair;
  479.  
  480.   gdisp = (GDisplay *) data;
  481.   pair  = (BoolCharPair *) user_data;
  482.  
  483.   if (gdisp->gimage->has_filename &&
  484.       strcmp (pair->string, gdisp->gimage->filename) == 0)
  485.     {
  486.       pair->boole = TRUE;
  487.       gdk_window_raise (gdisp->shell->window);
  488.     }
  489. }
  490.  
  491. static void
  492. open_or_raise (gchar    *file_name,
  493.            gboolean  try_raise)
  494. {
  495.   BoolCharPair pair;
  496.  
  497.   pair.boole  = FALSE;
  498.   pair.string = file_name;
  499.   pair.data   = NULL;
  500.  
  501.   if (try_raise)
  502.     {
  503.       gdisplays_foreach (raise_if_match, &pair);
  504.  
  505.       if (! pair.boole)
  506.     {
  507.       file_open (file_name, file_name);
  508.     }
  509.     }
  510.   else
  511.     {
  512.       file_open (file_name, file_name);
  513.     }
  514. }
  515.  
  516.  
  517. /*  file parsing functions  */
  518.  
  519. static gint
  520. getinteger (FILE *fp)
  521. {
  522.   gchar    nextchar;
  523.   gint     response = 0;
  524.   gboolean negative = FALSE;
  525.  
  526.   while (isspace (nextchar = fgetc (fp)))
  527.     /* empty statement */ ;
  528.  
  529.   if (nextchar == '-')
  530.     {
  531.       negative = TRUE;
  532.       while (isspace (nextchar = fgetc (fp)))
  533.     /* empty statement */ ;
  534.     }
  535.  
  536.   for (; '0' <= nextchar && '9' >= nextchar; nextchar = fgetc (fp))
  537.     {
  538.       response *= 10;
  539.       response += nextchar - '0';
  540.     }
  541.   for (; isspace (nextchar); nextchar = fgetc (fp))
  542.     /* empty statement */ ;
  543.  
  544.   if (!feof(fp))
  545.     ungetc (nextchar, fp);
  546.   if (negative)
  547.     response = -response;
  548.  
  549.   return response;
  550. }
  551.  
  552. static void
  553. clear_white (FILE *fp)
  554. {
  555.   gint nextchar;
  556.  
  557.   while (isspace (nextchar = fgetc (fp)))
  558.     /* empty statement */ ;
  559.  
  560.   if (!feof(fp))
  561.     ungetc (nextchar, fp);
  562. }
  563.  
  564.  
  565. /*  toolbar / dialog callbacks  */
  566.  
  567. static gint
  568. idea_move (GtkWidget *widget,
  569.        gint       distance,
  570.        gboolean   select)
  571. {
  572.   gint   orig_position;
  573.   gint   position;
  574.   gchar *title;
  575.  
  576.   orig_position = g_list_index (GTK_LIST (ideas->list)->children, widget);
  577.   position = orig_position + distance;
  578.  
  579.   if (position < 0)
  580.     position = 0;
  581.  
  582.   if (position >= g_list_length (GTK_LIST (ideas->list)->children))
  583.     position = g_list_length (GTK_LIST (ideas->list)->children) - 1;
  584.  
  585.   if (position != orig_position)
  586.     {
  587.       title = g_strdup (GTK_LABEL (GTK_BIN (widget)->child)->label);
  588.       gtk_container_remove (GTK_CONTAINER (ideas->list), widget);
  589.       idea_add_in_position_with_select (title, position, select);
  590.       g_free (title); 
  591.    }
  592.  
  593.   return position - orig_position;
  594. }
  595.  
  596. static void
  597. idea_open_callback (GtkWidget   *widget,
  598.             gpointer     data)
  599. {
  600.   GtkWidget *selected;
  601.  
  602.   if (GTK_LIST (ideas->list)->selection)
  603.     {
  604.       selected = GTK_LIST (ideas->list)->selection->data;
  605.       open_or_raise (GTK_LABEL (GTK_BIN (selected)->child)->label, FALSE);
  606.     }
  607.   else
  608.     {
  609.       file_open_callback (widget, data);
  610.     }
  611. }
  612.  
  613. static void
  614. idea_open_or_raise_callback (GtkWidget   *widget,
  615.                  gpointer     data)
  616. {
  617.   GtkWidget *selected;
  618.  
  619.   if (GTK_LIST (ideas->list)->selection)
  620.     {
  621.       selected = GTK_LIST (ideas->list)->selection->data;
  622.       open_or_raise (GTK_LABEL (GTK_BIN (selected)->child)->label, TRUE);
  623.     }
  624.   else
  625.     {
  626.       file_open_callback (widget, data);
  627.     }
  628. }
  629.  
  630. static void
  631. idea_up_callback (GtkWidget *widget,
  632.           gpointer   data)
  633. {
  634.   GtkWidget *selected;
  635.  
  636.   if (GTK_LIST (ideas->list)->selection)
  637.     {
  638.       selected = GTK_LIST (ideas->list)->selection->data;
  639.       idea_move (selected, -1, TRUE);
  640.     }
  641. }
  642.  
  643. static void
  644. idea_to_top_callback (GtkWidget   *widget,
  645.               gpointer     data)
  646. {
  647.   GtkWidget *selected;
  648.  
  649.   if (GTK_LIST (ideas->list)->selection)
  650.     {
  651.       selected = GTK_LIST (ideas->list)->selection->data;
  652.       idea_move (selected, - g_list_length (GTK_LIST (ideas->list)->children),
  653.          TRUE);
  654.     }
  655. }
  656.  
  657. static void
  658. idea_down_callback (GtkWidget *widget,
  659.             gpointer   data)
  660. {
  661.   GtkWidget *selected;
  662.  
  663.   if (GTK_LIST (ideas->list)->selection)
  664.     {
  665.       selected = GTK_LIST (ideas->list)->selection->data;
  666.       idea_move (selected, 1, TRUE);
  667.     }
  668. }
  669.  
  670. static void
  671. idea_to_bottom_callback (GtkWidget   *widget,
  672.              gpointer     data)
  673. {
  674.   GtkWidget *selected;
  675.  
  676.   if (GTK_LIST (ideas->list)->selection)
  677.     {
  678.       selected = GTK_LIST (ideas->list)->selection->data;
  679.       idea_move (selected, g_list_length (GTK_LIST (ideas->list)->children),
  680.          TRUE);
  681.     }
  682. }
  683.  
  684. static void
  685. idea_remove (GtkWidget *widget)
  686. {
  687.   gint position;
  688.  
  689.   position = g_list_index (GTK_LIST (ideas->list)->children, widget);
  690.  
  691.   gtk_container_remove (GTK_CONTAINER (ideas->list), widget);
  692.  
  693.   if (g_list_length (GTK_LIST (ideas->list)->children) - 1 < position)
  694.     position = g_list_length (GTK_LIST (ideas->list)->children) - 1;
  695.  
  696.   gtk_list_select_item (GTK_LIST (ideas->list), position);  
  697. }
  698.  
  699. static void
  700. idea_remove_callback (GtkWidget *widget,
  701.               gpointer   data)
  702. {
  703.   GtkWidget *selected;
  704.  
  705.   if (GTK_LIST (ideas->list)->selection)
  706.     {
  707.       selected = GTK_LIST (ideas->list)->selection->data;
  708.       idea_remove (selected);
  709.     }
  710. }
  711.  
  712. static void
  713. idea_hide_callback (GtkWidget *widget,
  714.             gpointer   data)
  715. {
  716.   if (ideas || idea_list)
  717.     save_idea_manager (ideas);
  718.  
  719.   /* False if exiting */
  720.   if (ideas)
  721.     {
  722.       create_idea_list ();
  723.       dialog_unregister (ideas->window);
  724.       session_get_window_info (ideas->window, &document_index_session_info);
  725.       gtk_widget_destroy (ideas->window);
  726.       g_free (ideas);
  727.       ideas = 0;
  728.     }
  729. }
  730.  
  731. static void
  732. ops_buttons_update (GtkWidget *widget,
  733.             gpointer   data)
  734. {
  735.   GtkWidget *selected = NULL;
  736.   gint       length   = 0;
  737.   gint       index    = -1;
  738.  
  739.   length = g_list_length (GTK_LIST (ideas->list)->children);
  740.  
  741.   if (GTK_LIST (ideas->list)->selection)
  742.     {
  743.       selected = GTK_LIST (ideas->list)->selection->data;
  744.       index  = g_list_index  (GTK_LIST (ideas->list)->children, selected);
  745.     }
  746.  
  747. #define SET_OPS_SENSITIVE(button,condition) \
  748.         gtk_widget_set_sensitive (ops_buttons[(button)].widget, \
  749.                                   (condition) != 0)
  750.  
  751.   SET_OPS_SENSITIVE (1, selected && index > 0);
  752.   SET_OPS_SENSITIVE (2, selected && index < (length - 1));
  753.   SET_OPS_SENSITIVE (3, selected);
  754.  
  755. #undef SET_OPS_SENSITIVE
  756. }
  757.  
  758. static void
  759. open_idea_window (void)
  760. {
  761.   GtkWidget *main_vbox;
  762.   GtkWidget *scrolled_win;
  763.   GtkWidget *abox;
  764.   GtkWidget *button_box;
  765.   gint       i;
  766.  
  767.   ideas = g_new0 (IdeaManager, 1);
  768.  
  769.   ideas->window = gimp_dialog_new (_("Document Index"), "docindex",
  770.                    gimp_standard_help_func,
  771.                    "dialogs/document_index.html",
  772.                    GTK_WIN_POS_MOUSE,
  773.                    FALSE, TRUE, FALSE,
  774.  
  775.                    _("Close"), idea_hide_callback,
  776.                    NULL, NULL, NULL, TRUE, TRUE,
  777.  
  778.                    NULL);
  779.  
  780.   gtk_drag_dest_set (ideas->window,
  781.                      GTK_DEST_DEFAULT_ALL,
  782.                      drag_types, n_drag_types,
  783.                      GDK_ACTION_COPY);
  784.  
  785.   gimp_dnd_file_dest_set (ideas->window);
  786.  
  787.   dialog_register (ideas->window);
  788.   session_set_window_geometry (ideas->window, &document_index_session_info,
  789.                    TRUE);
  790.  
  791.   main_vbox = gtk_vbox_new (FALSE, 4);
  792.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
  793.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (ideas->window)->vbox),
  794.              main_vbox);
  795.   gtk_widget_show (main_vbox);
  796.  
  797.   /* Scrolled window */
  798.   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
  799.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
  800.                   GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS );
  801.   gtk_box_pack_start (GTK_BOX (main_vbox), scrolled_win, TRUE, TRUE, 0); 
  802.   gtk_widget_show (scrolled_win);
  803.  
  804.   /* Setup list */
  805.   ideas->list = gtk_list_new ();
  806.   gtk_list_set_selection_mode (GTK_LIST (ideas->list), GTK_SELECTION_BROWSE);
  807.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
  808.                      ideas->list);
  809.   gtk_widget_show (ideas->list);
  810.  
  811.   /*  The ops buttons  */
  812.   abox = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
  813.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (ideas->window)->action_area), abox,
  814.               FALSE, FALSE, 4);
  815.   gtk_widget_show (abox);
  816.  
  817.   button_box = ops_button_box_new (ops_buttons, OPS_BUTTON_NORMAL);
  818.   gtk_container_add (GTK_CONTAINER (abox), button_box);
  819.   gtk_widget_show (button_box);
  820.  
  821.   for (i = 0; ; i++)
  822.     {
  823.       if (ops_buttons[i].widget == NULL)
  824.     break;
  825.  
  826.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (ops_buttons[i].widget)->child),
  827.                 12, 0);
  828.     }
  829.  
  830.   /* Load and Show window */
  831.   load_idea_manager (ideas);
  832.  
  833.   gtk_signal_connect_after (GTK_OBJECT (ideas->list), "selection_changed",
  834.                 GTK_SIGNAL_FUNC (ops_buttons_update),
  835.                 NULL);
  836.   ops_buttons_update (NULL, NULL);
  837. }
  838.