home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / gap / gap_arr_dialog.c next >
Encoding:
C/C++ Source or Header  |  2000-08-28  |  34.6 KB  |  1,088 lines

  1. /* gap_arr_dialog.c
  2.  * 1998.June.29 hof (Wolfgang Hofer)
  3.  *
  4.  * GAP ... Gimp Animation Plugins
  5.  *
  6.  * This is the common GTK Dialog for most of the GAP Functions.
  7.  * (it replaces the older gap_sld_dialog module)
  8.  *
  9.  * - p_array_dialog   Dialog Window with one or more rows
  10.  *                    each row can contain one of the following GAP widgets:
  11.  *                       - float pair widget
  12.  *                         (horizontal slidebar combined with a float input field)
  13.  *                       - int pair widget
  14.  *                         (horizontal slidebar combined with a int input field)
  15.  *                       - Toggle Button widget
  16.  *                       - Textentry widget
  17.  *                       - Float entry widget
  18.  *                       - Int entry widget
  19.  *
  20.  *
  21.  */
  22. /* The GIMP -- an image manipulation program
  23.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  24.  *
  25.  * This program is free software; you can redistribute it and/or modify
  26.  * it under the terms of the GNU General Public License as published by
  27.  * the Free Software Foundation; either version 2 of the License, or
  28.  * (at your option) any later version.
  29.  *
  30.  * This program is distributed in the hope that it will be useful,
  31.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  32.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  33.  * GNU General Public License for more details.
  34.  *
  35.  * You should have received a copy of the GNU General Public License
  36.  * along with this program; if not, write to the Free Software
  37.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  38.  */
  39.  
  40. /* revision history:
  41.  * gimp    1.1.17b; 2000/01/26  hof: bugfix gimp_help_init
  42.  *                                   use gimp_scale_entry_new for WGT_FLT_PAIR, WGT_INT_PAIR
  43.  * gimp    1.1.17a; 2000/02/20  hof: use gimp_help_set_help_data for tooltips
  44.  * gimp    1.1.13b; 1999/12/04  hof: some cosmetic gtk fixes
  45.  *                                   changed border_width spacing and Buttons in action area
  46.  *                                   to same style as used in dialogs of the gimp 1.1.13 main dialogs
  47.  * gimp    1.1.11b; 1999/11/20  hof: some cosmetic gtk fixes:
  48.  *                                   - allow X-expansion (useful for the scale widgets)
  49.  *                                   - use a hbox on WGT_INT_PAIR and WGT_FLT_PAIR
  50.  *                                     (reduces the waste of horizontal space
  51.  *                                      when used together with other widget types in the table)
  52.  * gimp    1.1.5.1; 1999/05/08  hof: call fileselect in gtk+1.2 style 
  53.  * version 0.96.03; 1998/08/15  hof: p_arr_gtk_init 
  54.  * version 0.96.01; 1998/07/09  hof: Bugfix: gtk_init should be called only
  55.  *                                           once in a plugin process 
  56.  * version 0.96.00; 1998/07/09  hof: 1.st release 
  57.  *                                   (re-implementation of gap_sld_dialog.c)
  58.  */
  59.  
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <string.h>
  63. #include <sys/types.h>
  64.  
  65. /* GIMP includes */
  66. #include "gtk/gtk.h"
  67. #include "libgimp/gimp.h"
  68. #include "libgimp/gimpui.h"
  69. #include "libgimp/stdplugins-intl.h"
  70. #include "libgimp/gimp.h"
  71.  
  72. /* private includes */
  73. #include "gap_arr_dialog.h"
  74.  
  75. typedef void (*t_entry_cb_func) (GtkWidget *widget, t_arr_arg *arr_ptr);
  76.  
  77. typedef struct
  78. {
  79.   t_arr_arg *arr_ptr;
  80.   gint       radio_index;
  81. } t_radio_arg;
  82.  
  83. typedef struct {
  84.   GtkWidget *dlg;
  85.   gint run;
  86. } t_arr_interface;
  87.  
  88.  
  89. static gint g_first_call = TRUE;
  90.  
  91. static t_arr_interface g_arrint =
  92. {
  93.   NULL,     /*  dlg  */
  94.   FALSE     /*  run  */
  95. };
  96.  
  97.  
  98. extern      int gap_debug; /* ==0  ... dont print debug infos */
  99.  
  100. /* Declare local functions.
  101.  */
  102.  
  103. static void   arr_close_callback        (GtkWidget *widget, gpointer data);
  104. static void   but_array_callback           (GtkWidget *widget, gpointer data);
  105.  
  106. static void   entry_create_value        (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr,
  107.                                          t_entry_cb_func entry_update_cb, char *init_txt);
  108. static void   label_create_value         (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr,
  109.                                           gfloat align);
  110. static void   text_entry_update_cb       (GtkWidget *widget, t_arr_arg *arr_ptr);
  111. static void   text_create_value          (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr);
  112. static void   filesel_close_cb           (GtkWidget *widget, t_arr_arg *arr_ptr);
  113. static void   filesel_ok_cb              (GtkWidget *widget, t_arr_arg *arr_ptr);
  114. static void   filesel_open_cb            (GtkWidget *widget, t_arr_arg *arr_ptr);
  115. static void   filesel_create_value       (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr);
  116.  
  117. static void   int_entry_update_cb        (GtkWidget *widget, t_arr_arg *arr_ptr);
  118. static void   int_create_value           (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr);
  119. static void   flt_entry_update_cb        (GtkWidget *widget, t_arr_arg *arr_ptr);
  120. static void   flt_create_value           (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr);
  121.  
  122. static void   toggle_update_cb           (GtkWidget *widget, t_arr_arg *arr_ptr);
  123. static void   toggle_create_value        (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr);
  124.  
  125. static void   radio_update_cb            (GtkWidget *widget, t_radio_arg *radio_ptr);
  126. static void   radio_create_value         (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr);
  127. static void   optionmenu_create_value    (char *title, GtkTable *table, int row, t_arr_arg *arr_ptr);
  128.  
  129. static void   pair_int_create_value     (gchar *title, GtkTable *table, gint row, t_arr_arg *arr_ptr);
  130. static void   pair_flt_create_value     (gchar *title, GtkTable *table, gint row, t_arr_arg *arr_ptr);
  131.  
  132.  
  133. gint
  134. p_arr_gtk_init(gint flag)
  135. {
  136.   gint l_prev_value;
  137.  
  138.   l_prev_value = g_first_call;
  139.   if(flag == TRUE) g_first_call = TRUE;
  140.   else             g_first_call = FALSE;
  141.   
  142.   return (l_prev_value);
  143.   
  144. }
  145.  
  146.  
  147. static void
  148. arr_close_callback (GtkWidget *widget,
  149.                gpointer   data)
  150. {
  151.   gtk_widget_destroy (GTK_WIDGET (g_arrint.dlg));  /* close & destroy dialog window */
  152.   gtk_main_quit ();
  153. }
  154.  
  155. static void
  156. but_array_callback (GtkWidget *widget,
  157.             gpointer   data)
  158. {
  159.   g_arrint.run = *((gint *)data);                  /* set returnvalue according to button */
  160.   gtk_widget_destroy (GTK_WIDGET (g_arrint.dlg));  /* close & destroy dialog window */
  161.   gtk_main_quit ();
  162. }
  163.  
  164.  
  165. static void
  166. entry_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr,
  167.                    t_entry_cb_func entry_update_cb, char *init_txt)
  168. {
  169.     GtkWidget *entry;
  170.     GtkWidget *label;
  171.  
  172.  
  173.     label = gtk_label_new(title);
  174.     gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
  175.     gtk_table_attach(table, label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
  176.     gtk_widget_show(label);
  177.  
  178.     entry = gtk_entry_new();
  179.     gtk_widget_set_usize(entry, arr_ptr->entry_width, 0);
  180.     gtk_entry_set_text(GTK_ENTRY(entry), init_txt);
  181.     gtk_signal_connect(GTK_OBJECT(entry), "changed",
  182.                (GtkSignalFunc) entry_update_cb,
  183.                arr_ptr);
  184.     gtk_table_attach(GTK_TABLE(table), entry, 1, 2, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 4, 0);
  185.     if(arr_ptr->help_txt != NULL)
  186.     { 
  187.        gimp_help_set_help_data(entry, arr_ptr->help_txt,NULL);
  188.     }
  189.     gtk_widget_show(entry);
  190.     
  191.     arr_ptr->text_entry = entry;
  192. }
  193.  
  194.  
  195. /* --------------------------
  196.  * LABEL
  197.  * --------------------------
  198.  */
  199.  
  200. static void
  201. label_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr, gfloat align)
  202. {
  203.     GtkWidget *label;
  204.     GtkWidget *hbox;
  205.  
  206.     label = gtk_label_new(title);
  207.     gtk_misc_set_alignment(GTK_MISC(label), align, 0.5);
  208.  
  209.     if(align != 0.5)
  210.     {
  211.       hbox = gtk_hbox_new (FALSE, 2);
  212.       gtk_widget_show (hbox);
  213.       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
  214.       gtk_table_attach(table, hbox, 0, 3, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
  215.     }
  216.     else
  217.     {
  218.       gtk_table_attach(table, label, 0, 3, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
  219.     }
  220.  
  221.     gtk_widget_show(label);
  222. }
  223.  
  224. /* --------------------------
  225.  * FILESEL
  226.  * --------------------------
  227.  */
  228. static void
  229. filesel_close_cb(GtkWidget *widget, t_arr_arg *arr_ptr)
  230. {
  231.   if(arr_ptr->text_filesel == NULL) return;  /* filesel is already open */
  232.  
  233.   gtk_widget_destroy(GTK_WIDGET(arr_ptr->text_filesel));
  234.   arr_ptr->text_filesel = NULL;
  235. }
  236. static void
  237. filesel_ok_cb(GtkWidget *widget, t_arr_arg *arr_ptr)
  238. {
  239.   char        *filename;
  240.  
  241.   if(arr_ptr->text_filesel == NULL) return;  /* filesel is already open */
  242.  
  243.   filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (arr_ptr->text_filesel));
  244.   strncpy(arr_ptr->text_buf_ret, filename, arr_ptr->text_buf_len -1);
  245.  
  246.   gtk_entry_set_text(GTK_ENTRY(arr_ptr->text_entry), filename);
  247.  
  248.   filesel_close_cb(widget, arr_ptr);
  249. }
  250.  
  251. static void
  252. filesel_open_cb(GtkWidget *widget, t_arr_arg *arr_ptr)
  253. {
  254.   GtkWidget *filesel;
  255.  
  256.   if(arr_ptr->text_filesel != NULL) return;  /* filesel is already open */
  257.  
  258.   filesel = gtk_file_selection_new (arr_ptr->label_txt);
  259.   arr_ptr->text_filesel = filesel;
  260.  
  261.   gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE);
  262.  
  263.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button),
  264.               "clicked", (GtkSignalFunc) filesel_ok_cb,
  265.               arr_ptr);
  266.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
  267.               "clicked", (GtkSignalFunc) filesel_close_cb,
  268.               arr_ptr);
  269.  
  270.   /* "destroy" has to be the last signal, 
  271.    * (otherwise the other callbacks are never called)
  272.    */
  273.   gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
  274.               (GtkSignalFunc) filesel_close_cb,
  275.               arr_ptr);
  276.   gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel),
  277.                    arr_ptr->text_buf_ret);
  278.   gtk_widget_show (filesel);
  279. }
  280.  
  281.  
  282. static void
  283. filesel_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr)
  284. {
  285.   GtkWidget *button;
  286.  
  287.   entry_create_value(title, table, row, arr_ptr, text_entry_update_cb, arr_ptr->text_buf_ret);
  288.   arr_ptr->text_filesel = NULL;
  289.     
  290.   /* Button  to invoke filebrowser */  
  291.   button = gtk_button_new_with_label ( _("File-Browser"));
  292.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  293.               (GtkSignalFunc) filesel_open_cb,
  294.               arr_ptr);
  295.   gtk_table_attach( GTK_TABLE(table), button, 2, 3, row, row +1,
  296.             0, 0, 0, 0 );
  297.   gtk_widget_show (button);
  298.     
  299. }
  300.  
  301. /* --------------------------
  302.  * TEXT
  303.  * --------------------------
  304.  */
  305. static void
  306. text_entry_update_cb(GtkWidget *widget, t_arr_arg *arr_ptr)
  307. {
  308.   if((arr_ptr->widget_type != WGT_TEXT)
  309.   && (arr_ptr->widget_type != WGT_FILESEL))
  310.   {
  311.     return;
  312.   }
  313.   
  314.   strncpy(arr_ptr->text_buf_ret,
  315.           gtk_entry_get_text(GTK_ENTRY(widget)), 
  316.           arr_ptr->text_buf_len -1);
  317.   arr_ptr->text_buf_ret[arr_ptr->text_buf_len -1] = '\0';
  318. }
  319.  
  320. static void
  321. text_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr)
  322. {
  323.     entry_create_value(title, table, row, arr_ptr, text_entry_update_cb, arr_ptr->text_buf_ret);
  324. }
  325.  
  326.  
  327. /* --------------------------
  328.  * INT
  329.  * --------------------------
  330.  */
  331.  
  332. static void
  333. int_entry_update_cb(GtkWidget *widget, t_arr_arg *arr_ptr)
  334. {
  335.   if(arr_ptr->widget_type != WGT_INT) return;
  336.  
  337.   arr_ptr->int_ret = atol(gtk_entry_get_text(GTK_ENTRY(widget)));
  338. }
  339.  
  340. static void
  341. int_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr)
  342. {
  343.     char       *buf;
  344.  
  345.     buf = g_strdup_printf("%d", arr_ptr->int_ret);
  346.     entry_create_value(title, table, row, arr_ptr,  int_entry_update_cb, buf);
  347.     g_free(buf);
  348. }
  349.  
  350. /* --------------------------
  351.  * FLOAT
  352.  * --------------------------
  353.  */
  354.  
  355. static void
  356. flt_entry_update_cb(GtkWidget *widget, t_arr_arg *arr_ptr)
  357. {
  358.   if(arr_ptr->widget_type != WGT_FLT) return;
  359.  
  360.   arr_ptr->flt_ret = atof(gtk_entry_get_text(GTK_ENTRY(widget)));
  361. }
  362.  
  363. static void
  364. flt_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr)
  365. {
  366.     char       *buf;
  367.     char       *fmt;
  368.     
  369.     /* fmt should result something like "%.2f"  */ 
  370.     fmt = g_strdup_printf("%%.%df", arr_ptr->flt_digits);
  371.     buf = g_strdup_printf(fmt, arr_ptr->flt_ret);
  372.     entry_create_value(title, table, row, arr_ptr,  flt_entry_update_cb, buf);
  373.     g_free(fmt);
  374.     g_free(buf);
  375. }
  376.  
  377. /* --------------------------
  378.  * TOGGLE
  379.  * --------------------------
  380.  */
  381.  
  382. static void
  383. toggle_update_cb (GtkWidget *widget, t_arr_arg *arr_ptr)
  384. {
  385.   if(arr_ptr->widget_type !=WGT_TOGGLE) return;
  386.  
  387.   if (GTK_TOGGLE_BUTTON (widget)->active)
  388.   {
  389.     arr_ptr->int_ret = 1;
  390.   }
  391.   else
  392.   {
  393.     arr_ptr->int_ret = 0;
  394.   }
  395. }
  396.  
  397. static void
  398. toggle_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr)
  399. {
  400.   GtkWidget *check_button;
  401.   GtkWidget *label;
  402.   char      *l_togg_txt;
  403.  
  404.  
  405.   label = gtk_label_new(title);
  406.   gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
  407.   gtk_table_attach(table, label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
  408.   gtk_widget_show(label);
  409.  
  410.   /* (make sure there is only 0 or 1) */
  411.   if(arr_ptr->int_ret != 0) arr_ptr->int_ret = 1;
  412.  
  413.   if(arr_ptr->togg_label == NULL) l_togg_txt = " ";
  414.   else                            l_togg_txt = arr_ptr->togg_label;
  415.   /* check button */
  416.   check_button = gtk_check_button_new_with_label (l_togg_txt);
  417.   gtk_table_attach ( GTK_TABLE (table), check_button, 1, 3, row, row+1, GTK_FILL, 0, 0, 0);
  418.   gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
  419.                       (GtkSignalFunc) toggle_update_cb,
  420.                        arr_ptr);
  421.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
  422.                 arr_ptr->int_ret);
  423.   if(arr_ptr->help_txt != NULL)
  424.   { 
  425.      gimp_help_set_help_data(check_button, arr_ptr->help_txt,NULL);
  426.   }
  427.   gtk_widget_show (check_button);
  428. }
  429.  
  430.  
  431. /* --------------------------
  432.  * RADIO
  433.  * --------------------------
  434.  */
  435.  
  436. static void
  437. radio_update_cb (GtkWidget *widget, t_radio_arg *radio_ptr)
  438. {
  439.   if(radio_ptr->arr_ptr == NULL) return;
  440.   if((radio_ptr->arr_ptr->widget_type != WGT_RADIO)
  441.   && (radio_ptr->arr_ptr->widget_type != WGT_OPTIONMENU))
  442.   {
  443.     return;
  444.   }
  445.  
  446.   radio_ptr->arr_ptr->int_ret = radio_ptr->radio_index;
  447.   radio_ptr->arr_ptr->radio_ret = radio_ptr->radio_index;
  448. }
  449.  
  450. static void
  451. radio_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr)
  452. {
  453.   GtkWidget *label;
  454.   GtkWidget *radio_table;
  455.   GtkWidget *radio_button;
  456.   GSList    *radio_group = NULL;
  457.   gint       l_idy;
  458.   char      *l_radio_txt;
  459.   char      *l_radio_help_txt;
  460.   gint       l_radio_pressed;
  461.  
  462.   t_radio_arg   *radio_ptr;
  463.  
  464.  
  465.   label = gtk_label_new(title);
  466.   gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.0);
  467.   gtk_table_attach( GTK_TABLE (table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
  468.   gtk_widget_show(label);
  469.  
  470.   /* radio_table */
  471.   radio_table = gtk_table_new (arr_ptr->radio_argc, 2, FALSE);
  472.  
  473.  
  474.   for(l_idy=0; l_idy < arr_ptr->radio_argc; l_idy++)
  475.   {
  476.      radio_ptr          = g_malloc0(sizeof(t_radio_arg));
  477.      radio_ptr->arr_ptr = arr_ptr;
  478.      radio_ptr->radio_index = l_idy;
  479.      
  480.      if(arr_ptr->radio_ret == l_idy) l_radio_pressed  = TRUE;
  481.      else                            l_radio_pressed  = FALSE;
  482.  
  483.      l_radio_txt = "null";
  484.      if (arr_ptr->radio_argv != NULL)
  485.      {
  486.         if (arr_ptr->radio_argv[l_idy] != NULL)
  487.             l_radio_txt = arr_ptr->radio_argv[l_idy];
  488.      }
  489.  
  490.      l_radio_help_txt = arr_ptr->help_txt;
  491.      if (arr_ptr->radio_help_argv != NULL)
  492.      {
  493.          if (arr_ptr->radio_help_argv[l_idy] != NULL)
  494.             l_radio_help_txt = arr_ptr->radio_help_argv[l_idy];
  495.      }
  496.  
  497.      if(gap_debug) printf("radio_create_value: %02d %s\n", l_idy, l_radio_txt);
  498.     
  499.      radio_button = gtk_radio_button_new_with_label ( radio_group, l_radio_txt );
  500.      radio_group = gtk_radio_button_group ( GTK_RADIO_BUTTON (radio_button) );  
  501.      gtk_table_attach ( GTK_TABLE (radio_table), radio_button, 0, 2, l_idy, l_idy+1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
  502.  
  503.      gtk_signal_connect ( GTK_OBJECT (radio_button), "toggled",
  504.                  (GtkSignalFunc) radio_update_cb,
  505.                   radio_ptr);
  506.  
  507.      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button), 
  508.                    l_radio_pressed);
  509.      if(l_radio_help_txt != NULL)
  510.      { 
  511.        gimp_help_set_help_data(radio_button, l_radio_help_txt, NULL);
  512.      }
  513.      gtk_widget_show (radio_button);
  514.   }
  515.  
  516.   
  517.   /* attach radio_table */
  518.   gtk_table_attach ( GTK_TABLE (table), radio_table, 1, 3, row, row+1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
  519.   gtk_widget_show (radio_table);
  520. }
  521.  
  522.  
  523. /* --------------------------
  524.  * OPTIONMENU
  525.  * --------------------------
  526.  */
  527.  
  528. /* optionmenus share callback and data structure with WGT_RADIO */
  529. static void
  530. optionmenu_create_value(char *title, GtkTable *table, int row, t_arr_arg *arr_ptr)
  531. {
  532.   GtkWidget *label;
  533.   GtkWidget  *option_menu;
  534.   GtkWidget  *menu;
  535.   GtkWidget  *menu_item;
  536.   gint       l_idx;
  537.   gint       l_idy;
  538.   char      *l_radio_txt;
  539.   gint       l_radio_pressed;
  540.  
  541.   t_radio_arg *l_menu_ptr;
  542.   
  543.   /* label */
  544.   label = gtk_label_new(title);
  545.   gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
  546.   gtk_table_attach( GTK_TABLE (table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
  547.   gtk_widget_show(label);
  548.  
  549.   /* optionmenu */
  550.   option_menu = gtk_option_menu_new();
  551.   gtk_table_attach(GTK_TABLE(table), option_menu, 1, 2, row, row +1,
  552.            GTK_FILL, GTK_FILL, 0, 0);
  553.   gtk_widget_show(option_menu);
  554.  
  555.   if(arr_ptr->help_txt != NULL)
  556.   { 
  557.        gimp_help_set_help_data(option_menu, arr_ptr->help_txt, NULL);
  558.   }
  559.  
  560.   /* menu (filled with items in loop) */
  561.   menu = gtk_menu_new ();
  562.  
  563.   /* outer loop is done to ensure that the initial "pressed" value
  564.    * is the first entry in the optionmenu
  565.    */
  566.   for(l_idx=0; l_idx < 2; l_idx++)
  567.   {
  568.     for(l_idy=0; l_idy < arr_ptr->radio_argc; l_idy++)
  569.     {
  570.        if(arr_ptr->radio_ret == l_idy) l_radio_pressed  = TRUE;
  571.        else                            l_radio_pressed  = FALSE;
  572.  
  573.        if( ((l_radio_pressed == TRUE) && (l_idx == 0))
  574.        ||  ((l_radio_pressed == FALSE) && (l_idx == 1)))
  575.        {
  576.            l_radio_txt = "null";
  577.           if (arr_ptr->radio_argv != NULL)
  578.           {
  579.              if (arr_ptr->radio_argv[l_idy] != NULL)
  580.                  l_radio_txt = arr_ptr->radio_argv[l_idy];
  581.           }
  582.           l_menu_ptr   = g_malloc0(sizeof(t_radio_arg));
  583.           l_menu_ptr->radio_index  = l_idy;
  584.           l_menu_ptr->arr_ptr  = arr_ptr;
  585.  
  586.  
  587.           menu_item = gtk_menu_item_new_with_label (l_radio_txt);
  588.           gtk_container_add (GTK_CONTAINER (menu), menu_item);
  589.  
  590.           gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  591.                   (GtkSignalFunc) radio_update_cb,
  592.                   l_menu_ptr);
  593.           gtk_widget_show (menu_item);
  594.       }
  595.     }
  596.   }
  597.  
  598.   gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
  599.   gtk_widget_show(option_menu);
  600.  
  601. }
  602.  
  603.  
  604. /* --------------------------
  605.  * FLT_PAIR
  606.  * --------------------------
  607.  */
  608.  
  609. static void
  610. pair_flt_create_value(gchar *title, GtkTable *table, gint row, t_arr_arg *arr_ptr)
  611. {
  612.   GtkObject *adj;
  613.   gfloat     umin, umax;
  614.   
  615.   if(arr_ptr->constraint)
  616.   {
  617.     umin = arr_ptr->flt_min;
  618.     umax = arr_ptr->flt_max;
  619.   }
  620.   else
  621.   {
  622.     umin = arr_ptr->umin;
  623.     umax = arr_ptr->umax;
  624.   }
  625.   
  626.  
  627.   adj = 
  628.   gimp_scale_entry_new( GTK_TABLE (table), 0, row,        /* table col, row */
  629.                 title,                            /* label text */
  630.                 arr_ptr->scale_width,             /* scalesize */
  631.             arr_ptr->entry_width,             /* entrysize */
  632.                (gfloat)arr_ptr->flt_ret,          /* init value */
  633.                (gfloat)arr_ptr->flt_min,          /* lower,  */
  634.                (gfloat)arr_ptr->flt_max,          /* upper */
  635.                 arr_ptr->flt_step,                /* step */
  636.             arr_ptr->pagestep,                /* pagestep */
  637.                 arr_ptr->flt_digits,              /* digits */
  638.                 arr_ptr->constraint,              /* constrain */
  639.                 umin, umax,                       /* lower, upper (unconstrained) */
  640.                 arr_ptr->help_txt,                /* tooltip */
  641.                 NULL);                            /* privatetip */
  642.  
  643.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  644.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  645.               &arr_ptr->flt_ret);
  646. }
  647.  
  648. /* --------------------------
  649.  * INT_PAIR
  650.  * --------------------------
  651.  */
  652.  
  653. static void
  654. pair_int_create_value(gchar *title, GtkTable *table, gint row, t_arr_arg *arr_ptr)
  655. {
  656.   GtkObject *adj;
  657.   gfloat     umin, umax;
  658.   
  659.   if(arr_ptr->constraint)
  660.   {
  661.     umin = (gfloat)arr_ptr->int_min;
  662.     umax = (gfloat)arr_ptr->int_max;
  663.   }
  664.   else
  665.   {
  666.     umin = arr_ptr->umin;
  667.     umax = arr_ptr->umax;
  668.   }
  669.  
  670.   adj = 
  671.   gimp_scale_entry_new( GTK_TABLE (table), 0, row,        /* table col, row */
  672.                 title,                            /* label text */
  673.                 arr_ptr->scale_width,             /* scalesize */
  674.             arr_ptr->entry_width,             /* entrysize */
  675.                (gfloat)arr_ptr->int_ret,          /* init value */
  676.                (gfloat)arr_ptr->int_min,          /* lower,  */
  677.                (gfloat)arr_ptr->int_max,          /* upper */
  678.                 arr_ptr->int_step,                /* step */
  679.             arr_ptr->pagestep,                /* pagestep */
  680.                 0,                                /* digits */
  681.                 arr_ptr->constraint,              /* constrain */
  682.                 umin, umax,                       /* lower, upper (unconstrained) */
  683.                 arr_ptr->help_txt,                /* tooltip */
  684.                 NULL);                            /* privatetip */
  685.  
  686.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  687.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  688.               &arr_ptr->int_ret);
  689.  
  690. }
  691.  
  692.  
  693. /* ============================================================================
  694.  * p_array_std_dialog
  695.  *
  696.  *   GTK dialog window that has argc rows.
  697.  *   each row contains the widget(s) as defined in argv[row]
  698.  *
  699.  *   The Dialog has an Action Area with OK and CANCEL Buttons.
  700.  * ============================================================================
  701.  */
  702. gint p_array_std_dialog(char *title_txt,
  703.                     char *frame_txt,
  704.                     int        argc,
  705.                     t_arr_arg  argv[],
  706.                     int        b_argc,
  707.                     t_but_arg  b_argv[],
  708.                     gint       b_def_val)
  709. {
  710.   GtkWidget *hbbox;
  711.   GtkWidget *button;
  712.   GtkWidget *frame;
  713.   GtkWidget *table;
  714.   gchar **l_argsv;
  715.   gint    l_argsc;
  716.   gint    l_idx;
  717.   gint    l_ok_value;
  718.   char   *l_label_txt;
  719.   t_arr_arg  *arr_ptr;
  720.     
  721.   g_arrint.run = b_def_val;           /* prepare default retcode (if window is closed without button) */
  722.   l_ok_value = 0;
  723.   table = NULL;
  724.   
  725.   if((argc > 0) && (argv == NULL))
  726.   {
  727.     printf("p_array_std_dialog: calling error (widget array == NULL)\n");
  728.     return (g_arrint.run);
  729.   }
  730.   if((b_argc > 0) && (b_argv == NULL))
  731.   {
  732.     printf("p_array_std_dialog: calling error (button array == NULL)\n");
  733.     return (g_arrint.run);
  734.   }
  735.  
  736.   /* gtk init (only once in a plugin-process) */
  737.   if (g_first_call == TRUE)
  738.   {
  739.      l_argsc = 1;
  740.      l_argsv = g_new (gchar *, 1);
  741.      l_argsv[0] = g_strdup ("gap_std_dialog");
  742.      gtk_init (&l_argsc, &l_argsv);
  743.      g_first_call = FALSE;
  744.   }
  745.  
  746.   /* Initialize Tooltips */
  747.   gimp_help_init ();
  748.  
  749.   /* dialog */
  750.   g_arrint.dlg = gtk_dialog_new ();
  751.   gtk_window_set_title (GTK_WINDOW (g_arrint.dlg), title_txt);
  752.   gtk_window_set_position (GTK_WINDOW (g_arrint.dlg), GTK_WIN_POS_MOUSE);
  753.   gtk_signal_connect (GTK_OBJECT (g_arrint.dlg), "destroy",
  754.               (GtkSignalFunc) arr_close_callback,
  755.               NULL);
  756.  
  757.   gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (g_arrint.dlg)->action_area), 2);
  758.   gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (g_arrint.dlg)->action_area), FALSE);
  759.   hbbox = gtk_hbutton_box_new ();
  760.   gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4);
  761.   gtk_box_pack_end (GTK_BOX (GTK_DIALOG (g_arrint.dlg)->action_area), hbbox, FALSE, FALSE, 0);
  762.   gtk_widget_show (hbbox);
  763.  
  764.   /*  Action area  */
  765.   for(l_idx = 0; l_idx < b_argc; l_idx++)
  766.   {
  767.  
  768.      if(b_argv[l_idx].but_txt == NULL)  button = gtk_button_new_with_label ( _("OK"));
  769.      else                               button = gtk_button_new_with_label (b_argv[l_idx].but_txt);
  770.      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  771.      gtk_signal_connect (GTK_OBJECT (button), "clicked",
  772.                  (GtkSignalFunc) but_array_callback,
  773.                  &b_argv[l_idx].but_val);
  774.      gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
  775.      if( b_argv[l_idx].but_val == b_def_val ) gtk_widget_grab_default (button);
  776.      gtk_widget_show (button);
  777.      
  778.   }
  779.  
  780.   if(b_argc < 1)
  781.   {
  782.      /* if no buttons are specified use one CLOSE button per default */
  783.      button = gtk_button_new_with_label ( _("Close"));
  784.      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  785.      gtk_signal_connect (GTK_OBJECT (button), "clicked",
  786.                          (GtkSignalFunc) but_array_callback,
  787.                           &l_ok_value);
  788.      gtk_box_pack_start (GTK_BOX (hbbox), button, TRUE, TRUE, 0);
  789.      gtk_widget_grab_default (button);
  790.      gtk_widget_show (button);
  791.   }
  792.  
  793.   /*  parameter settings  */
  794.   if (frame_txt == NULL)   frame = gtk_frame_new ( _("Enter Values"));
  795.   else                     frame = gtk_frame_new (frame_txt);
  796.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  797.   gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
  798.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (g_arrint.dlg)->vbox), frame, TRUE, TRUE, 0);
  799.  
  800.   if(argc > 0)
  801.   {
  802.     /* table (one row per argv) */
  803.     table = gtk_table_new (argc +1, 3, FALSE);
  804.     gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  805.     gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  806.     gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  807.     gtk_container_add (GTK_CONTAINER (frame), table);
  808.  
  809.     for(l_idx = 0; l_idx < argc; l_idx++)
  810.     {
  811.        arr_ptr = &argv[l_idx];
  812.  
  813.        if(arr_ptr->label_txt == NULL)  l_label_txt = _("Value:");
  814.        else                            l_label_txt = arr_ptr->label_txt;
  815.  
  816.        switch(arr_ptr->widget_type)
  817.        {
  818.          case WGT_FLT_PAIR:
  819.             pair_flt_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1), arr_ptr);
  820.             break;
  821.          case WGT_INT_PAIR:
  822.             pair_int_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1), arr_ptr);
  823.             break;
  824.          case WGT_TOGGLE:
  825.             toggle_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr);
  826.             break;
  827.          case WGT_RADIO:
  828.             radio_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr);
  829.             break;
  830.          case WGT_OPTIONMENU:
  831.             optionmenu_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr);
  832.             break;
  833.          case WGT_FILESEL:
  834.             filesel_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr);
  835.             break;
  836.          case WGT_TEXT:
  837.             text_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr);
  838.             break;
  839.          case WGT_INT:
  840.             int_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr);
  841.             break;
  842.          case WGT_FLT:
  843.             flt_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr);
  844.             break;
  845.          case WGT_LABEL:
  846.             label_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr, 0.5);
  847.             break;
  848.          case WGT_LABEL_LEFT:
  849.             label_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr, 0.0);
  850.             break;
  851.          case WGT_LABEL_RIGHT:
  852.             label_create_value(l_label_txt, GTK_TABLE(table), (l_idx + 1),  arr_ptr, 1.0);
  853.             break;
  854.          case WGT_ACT_BUTTON:
  855.             printf ("WGT_ACT_BUTTON not implemented yet, widget type ignored\n");
  856.             break;
  857.          default:     /* undefined widget type */
  858.             printf ("Unknown widget type %d ignored\n", arr_ptr->widget_type);
  859.             break;
  860.  
  861.        }   /* end switch */
  862.     }      /* end for */
  863.   }
  864.  
  865.   gtk_widget_show (frame);
  866.   if(argc > 0)  {  gtk_widget_show (table); }
  867.   gtk_widget_show (g_arrint.dlg);
  868.  
  869.   gtk_main ();
  870.   gdk_flush ();
  871.  
  872.   if(gap_debug)
  873.   {
  874.      /* for debugging: print results to stdout */
  875.      for(l_idx = 0; l_idx < argc; l_idx++)
  876.      {
  877.         arr_ptr = &argv[l_idx];
  878.  
  879.         if(arr_ptr->label_txt == NULL)  l_label_txt = _("Value: ");
  880.         else                            l_label_txt = arr_ptr->label_txt;
  881.         arr_ptr = &argv[l_idx];
  882.         
  883.         printf("%02d  ", l_idx);
  884.  
  885.         switch(arr_ptr->widget_type)
  886.         {
  887.           case WGT_FLT_PAIR:
  888.           case WGT_FLT:
  889.              printf("FLT  %s : %f\n",  l_label_txt, arr_ptr->flt_ret);
  890.              break;
  891.           case WGT_INT_PAIR:
  892.           case WGT_INT:
  893.           case WGT_TOGGLE:
  894.              printf("INT  %s : %d\n",  l_label_txt, arr_ptr->int_ret);
  895.              break;
  896.           case WGT_TEXT:
  897.           case WGT_FILESEL:
  898.              printf("TEXT  %s : %s\n",  l_label_txt, arr_ptr->text_buf_ret);
  899.              break;
  900.           case WGT_RADIO:
  901.           case WGT_OPTIONMENU:
  902.              printf("RADIO/OPTIONMENU  %s : %d\n",  l_label_txt, arr_ptr->radio_ret);
  903.              break;
  904.           default:
  905.              printf("\n");
  906.              break;
  907.  
  908.         }
  909.  
  910.      }
  911.   }
  912.   
  913.   return (g_arrint.run);
  914. }    /* end p_array_dialog */
  915.  
  916.  
  917.  
  918. void     p_init_arr_arg  (t_arr_arg *arr_ptr,
  919.                           gint       widget_type)
  920. {
  921.    arr_ptr->label_txt   = NULL;
  922.    arr_ptr->help_txt    = NULL;
  923.    arr_ptr->togg_label  = NULL;
  924.    arr_ptr->entry_width = 60;
  925.    arr_ptr->scale_width = 200;
  926.    arr_ptr->constraint  = TRUE;
  927.    arr_ptr->has_default = FALSE;
  928.    arr_ptr->text_entry  = NULL;
  929.  
  930.    switch(widget_type)
  931.    {
  932.      case WGT_LABEL:
  933.      case WGT_LABEL_LEFT:
  934.      case WGT_LABEL_RIGHT:
  935.         arr_ptr->widget_type = widget_type;
  936.         break;
  937.      case WGT_INT_PAIR:
  938.      case WGT_INT:
  939.         arr_ptr->widget_type = widget_type;
  940.         arr_ptr->umin        = (gfloat)G_MININT;
  941.         arr_ptr->umax        = (gfloat)G_MAXINT;
  942.         arr_ptr->int_min     = 0;
  943.         arr_ptr->int_max     = 100;
  944.         arr_ptr->int_step    = 1;
  945.         arr_ptr->pagestep    = 10.0;
  946.         arr_ptr->int_default = 0;
  947.         arr_ptr->int_ret     = 0;
  948.         break;
  949.      case WGT_FLT_PAIR:
  950.      case WGT_FLT:
  951.         arr_ptr->widget_type = widget_type;
  952.         arr_ptr->flt_digits  = 2;
  953.         arr_ptr->umin        = G_MINFLOAT;
  954.         arr_ptr->umax        = G_MAXFLOAT;
  955.         arr_ptr->flt_min     = 0.0;
  956.         arr_ptr->flt_max     = 100.0;
  957.         arr_ptr->flt_step    = 0.1;
  958.         arr_ptr->pagestep    = 10.0;
  959.         arr_ptr->flt_default = 0.0;
  960.         arr_ptr->flt_ret     = 0.0;
  961.         break;
  962.      case WGT_TOGGLE:
  963.         arr_ptr->widget_type = widget_type;
  964.         arr_ptr->int_default = 0;
  965.         arr_ptr->int_ret     = 0;
  966.         break;
  967.      case WGT_RADIO:
  968.      case WGT_OPTIONMENU:
  969.         arr_ptr->widget_type = widget_type;
  970.         arr_ptr->radio_argc    = 0;
  971.         arr_ptr->radio_default = 0;
  972.         arr_ptr->radio_ret     = 0;
  973.         arr_ptr->radio_argv    = NULL;
  974.         arr_ptr->radio_help_argv = NULL;
  975.         break;
  976.      case WGT_TEXT:
  977.      case WGT_FILESEL:
  978.         arr_ptr->widget_type = widget_type;
  979.         arr_ptr->text_buf_len     = 0;
  980.         arr_ptr->text_buf_default = NULL;
  981.         arr_ptr->text_buf_ret     = NULL;
  982.         arr_ptr->text_filesel     = NULL;
  983.         break;
  984.      case WGT_ACT_BUTTON:
  985.         arr_ptr->widget_type = widget_type;
  986.         arr_ptr->action_functon = NULL;
  987.         arr_ptr->action_data    = NULL;
  988.         break;
  989.      default:     /* Calling error: undefined widget type */
  990.         arr_ptr->widget_type = WGT_LABEL;
  991.         break;
  992.  
  993.    }
  994.   
  995. }    /* end p_init_arr_arg */
  996.  
  997. /* ============================================================================
  998.  *   simplified calls of p_array_std_dialog
  999.  * ============================================================================
  1000.  */
  1001.  
  1002.  
  1003. gint p_array_dialog(char *title_txt,
  1004.                     char *frame_txt,
  1005.                     int        argc,
  1006.                     t_arr_arg  argv[])
  1007. {
  1008.     static t_but_arg  b_argv[2];
  1009.  
  1010.     b_argv[0].but_txt  = _("OK");
  1011.     b_argv[0].but_val  = TRUE;
  1012.     b_argv[1].but_txt  = _("Cancel");
  1013.     b_argv[1].but_val  = FALSE;
  1014.   
  1015.     return( p_array_std_dialog(title_txt,
  1016.                        frame_txt,
  1017.                        argc, argv,      /* widget array */
  1018.                        2,    b_argv,    /* button array */
  1019.                        FALSE)
  1020.            );          /* ret value for window close */
  1021. }
  1022.  
  1023. /* ============================================================================
  1024.  * p_buttons_dialog
  1025.  *   dialog window wit 1 upto n buttons
  1026.  *   return: the value aassigned with the pressed button.
  1027.  *           (If window closed by windowmanager return b_def_val)
  1028.  * ============================================================================
  1029.  */
  1030.  
  1031.  
  1032. gint p_buttons_dialog(char *title_txt,
  1033.                          char   *msg_txt,
  1034.                          int        b_argc,
  1035.                          t_but_arg  b_argv[],
  1036.                          gint       b_def_val)
  1037. {
  1038.   static t_arr_arg  argv[1];
  1039.   char   *frame_txt;
  1040.  
  1041.   if(b_argc == 1) frame_txt = _("Press Button");
  1042.   else            frame_txt = _("Select");
  1043.   
  1044.   p_init_arr_arg(&argv[0], WGT_LABEL);
  1045.   argv[0].label_txt = msg_txt;
  1046.  
  1047.   return( p_array_std_dialog(title_txt,
  1048.                      frame_txt,
  1049.                      1, argv,
  1050.                      b_argc, b_argv,
  1051.                      b_def_val)
  1052.            );          /* ret value for window close */
  1053.                        
  1054. }    /* end p_buttons_dialog */
  1055.  
  1056.  
  1057.  
  1058. /* ============================================================================
  1059.  * p_slider_dialog
  1060.  *   simplified call of p_array_dialog, using an array with one value.
  1061.  *
  1062.  *   return  the value of the (only) entryfield 
  1063.  *          or  -1 in case of Error or cancel
  1064.  * ============================================================================
  1065.  */
  1066.  
  1067. long p_slider_dialog(char *title, char *frame, char *label, char *tooltip,
  1068.                      long min, long max, long curr, long constraint)
  1069. {
  1070.   static t_arr_arg  argv[1];
  1071.   
  1072.   p_init_arr_arg(&argv[0], WGT_INT_PAIR);
  1073.   argv[0].label_txt = label;
  1074.   argv[0].help_txt = tooltip;
  1075.   argv[0].constraint = constraint;
  1076.   argv[0].entry_width = 45;
  1077.   argv[0].scale_width = 130;
  1078.   argv[0].int_min    = (gint)min;
  1079.   argv[0].int_max    = (gint)max;
  1080.   argv[0].int_step   = 1;
  1081.   argv[0].int_ret    = (gint)curr;
  1082.   
  1083.   if(TRUE == p_array_dialog(title, frame, 1, argv))
  1084.   {    return (long)(argv[0].int_ret);
  1085.   }
  1086.   else return -1;
  1087. }    /* end p_slider_dialog */
  1088.