pcb 4.1.1
An interactive printed circuit board layout editor.

gui-dialog-print.c

Go to the documentation of this file.
00001 /*
00002  *                            COPYRIGHT
00003  *
00004  *  PCB, interactive printed circuit board design
00005  *  Copyright (C) 1994,1995,1996 Thomas Nau
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License along
00018  *  with this program; if not, write to the Free Software Foundation, Inc.,
00019  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00020  *
00021  *  Contact addresses for paper mail and Email:
00022  *  Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
00023  *  Thomas.Nau@rz.uni-ulm.de
00024  *
00025  */
00026 
00027 /* This file written by Bill Wilson for the PCB Gtk port. */
00028 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032 
00033 #ifdef HAVE_STDLIB_H
00034 #include <stdlib.h>
00035 #endif
00036 
00037 #include "gui.h"
00038 #include "pcb-printf.h"
00039 
00040 #ifdef HAVE_LIBDMALLOC
00041 #include <dmalloc.h>
00042 #endif
00043 
00044 static GtkWidget *export_dialog = NULL;
00045 
00046 static void
00047 set_flag_cb (GtkToggleButton * button, void * flag)
00048 {
00049   *(gboolean *)flag = gtk_toggle_button_get_active (button);
00050 }
00051 
00052 
00053 static void
00054 intspinner_changed_cb (GtkSpinButton * spin_button, gpointer data)
00055 {
00056   int *ival = (int *)data;
00057 
00058   *ival = gtk_spin_button_get_value (GTK_SPIN_BUTTON ((GtkWidget *)spin_button));
00059 }
00060 
00061 static void
00062 coordentry_changed_cb (GtkEntry * entry, Coord * res)
00063 {
00064   const gchar *s = gtk_entry_get_text (entry);
00065   *res = GetValue (s, NULL, NULL);
00066 }
00067 
00068 static void
00069 dblspinner_changed_cb (GtkSpinButton * spin_button, gpointer data)
00070 {
00071   double *dval = (double *)data;
00072 
00073   *dval = gtk_spin_button_get_value (GTK_SPIN_BUTTON ((GtkWidget *)spin_button));
00074 }
00075 
00076 
00077 static void
00078 entry_changed_cb (GtkEntry * entry, char **str)
00079 {
00080   const gchar *s;
00081 
00082   s = gtk_entry_get_text (entry);
00083 
00084   if (*str)
00085     free (*str);
00086   *str = strdup (s);
00087 }
00088 
00089 static void
00090 enum_changed_cb (GtkWidget * combo_box, int *val)
00091 {
00092   gint active;
00093 
00094   active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box));
00095   *val = active;
00096 }
00097 
00098 
00099 int
00100 ghid_attribute_dialog (HID_Attribute * attrs,
00101                        int n_attrs, HID_Attr_Val * results,
00102                        const char * title,
00103                        const char * descr)
00104 {
00105   GtkWidget *dialog;
00106   GtkWidget *content_area;
00107   GtkWidget *main_vbox, *vbox, *vbox1, *hbox, *entry;
00108   GtkWidget *combo;
00109   GtkWidget *widget;
00110   GHidPort *out = &ghid_port;
00111   int i, j, n;
00112   int rc = 0;
00113 
00114   dialog = gtk_dialog_new_with_buttons (_(title),
00115                                         GTK_WINDOW (out->top_window),
00116                                         (GtkDialogFlags)(GTK_DIALOG_MODAL
00117                                                          | GTK_DIALOG_DESTROY_WITH_PARENT),
00118                                         GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
00119                                         GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
00120   gtk_window_set_wmclass (GTK_WINDOW (dialog), "PCB_attribute_editor", "PCB");
00121 
00122   content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
00123 
00124   main_vbox = gtk_vbox_new (FALSE, 6);
00125   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6);
00126   gtk_container_add (GTK_CONTAINER (content_area), main_vbox);
00127 
00128   vbox = ghid_category_vbox (main_vbox, descr != NULL ? descr : "",
00129                              4, 2, TRUE, TRUE);
00130 
00131   /* 
00132    * Iterate over all the export options and build up a dialog box
00133    * that lets us control all of the options.  By doing things this
00134    * way, any changes to the exporter HID's automatically are
00135    * reflected in this dialog box.
00136    */
00137   for (j = 0; j < n_attrs; j++)
00138     {
00139       const Unit *unit_list;
00140       if (attrs[j].help_text == ATTR_UNDOCUMENTED)
00141         continue;
00142       switch (attrs[j].type)
00143         {
00144         case HID_Label:
00145           widget = gtk_label_new (_(attrs[j].name));
00146           gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
00147           gtk_widget_set_tooltip_text (widget, _(attrs[j].help_text));
00148           break;
00149 
00150         case HID_Integer:
00151           hbox = gtk_hbox_new (FALSE, 4);
00152           gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
00153 
00154           /* 
00155            * FIXME 
00156            * need to pick the "digits" argument based on min/max
00157            * values
00158            */
00159           ghid_spin_button (hbox, &widget, attrs[j].default_val.int_value,
00160                             attrs[j].min_val, attrs[j].max_val, 1.0, 1.0, 0, 0,
00161                             intspinner_changed_cb,
00162                             &(attrs[j].default_val.int_value), FALSE, NULL);
00163           gtk_widget_set_tooltip_text (widget, _(attrs[j].help_text));
00164 
00165           widget = gtk_label_new (_(attrs[j].name));
00166           gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
00167           break;
00168 
00169         case HID_Coord:
00170           hbox = gtk_hbox_new (FALSE, 4);
00171           gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
00172 
00173           entry = ghid_coord_entry_new (attrs[j].min_val, attrs[j].max_val,
00174                                         attrs[j].default_val.coord_value,
00175                                         Settings.grid_unit, CE_SMALL);
00176           gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
00177           if(attrs[j].default_val.str_value != NULL)
00178             gtk_entry_set_text (GTK_ENTRY (entry),
00179                                 attrs[j].default_val.str_value);
00180           gtk_widget_set_tooltip_text (entry, _(attrs[j].help_text));
00181           g_signal_connect (G_OBJECT (entry), "changed",
00182                             G_CALLBACK (coordentry_changed_cb),
00183                             &(attrs[j].default_val.coord_value));
00184 
00185           widget = gtk_label_new (_(attrs[j].name));
00186           gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
00187           break;
00188 
00189         case HID_Real:
00190           hbox = gtk_hbox_new (FALSE, 4);
00191           gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
00192 
00193           /* 
00194            * FIXME 
00195            * need to pick the "digits" and step size argument more
00196            * intelligently
00197            */
00198           ghid_spin_button (hbox, &widget, attrs[j].default_val.real_value,
00199                             attrs[j].min_val, attrs[j].max_val, 0.01, 0.01, 3,
00200                             0, 
00201                             dblspinner_changed_cb,
00202                             &(attrs[j].default_val.real_value), FALSE, NULL);
00203 
00204           gtk_widget_set_tooltip_text (widget, _(attrs[j].help_text));
00205 
00206           widget = gtk_label_new (_(attrs[j].name));
00207           gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
00208           break;
00209 
00210         case HID_String:
00211           hbox = gtk_hbox_new (FALSE, 4);
00212           gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
00213 
00214           entry = gtk_entry_new ();
00215           gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
00216           if(attrs[j].default_val.str_value != NULL)
00217             gtk_entry_set_text (GTK_ENTRY (entry),
00218                                 attrs[j].default_val.str_value);
00219           gtk_widget_set_tooltip_text (entry, _(attrs[j].help_text));
00220           g_signal_connect (G_OBJECT (entry), "changed",
00221                             G_CALLBACK (entry_changed_cb),
00222                             &(attrs[j].default_val.str_value));
00223 
00224           widget = gtk_label_new (_(attrs[j].name));
00225           gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
00226           break;
00227 
00228         case HID_Boolean:
00229           /* put this in a check button */
00230           ghid_check_button_connected (vbox, &widget,
00231                                        attrs[j].default_val.int_value,
00232                                        TRUE, FALSE, FALSE, 0, set_flag_cb,
00233                                        &(attrs[j].default_val.int_value),
00234                                        _(attrs[j].name));
00235           gtk_widget_set_tooltip_text (widget, _(attrs[j].help_text));
00236           break;
00237 
00238         case HID_Enum:
00239           hbox = gtk_hbox_new (FALSE, 4);
00240           gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
00241 
00242         do_enum:
00243           combo = gtk_combo_box_new_text ();
00244           gtk_widget_set_tooltip_text (combo, _(attrs[j].help_text));
00245           gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
00246           g_signal_connect (G_OBJECT (combo), "changed",
00247                             G_CALLBACK (enum_changed_cb),
00248                             &(attrs[j].default_val.int_value));
00249 
00250 
00251           /* 
00252            * Iterate through each value and add them to the
00253            * combo box
00254            */
00255           i = 0;
00256           while (attrs[j].enumerations[i])
00257             {
00258               gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
00259                                          attrs[j].enumerations[i]);
00260               i++;
00261             }
00262           gtk_combo_box_set_active (GTK_COMBO_BOX (combo),
00263                                     attrs[j].default_val.int_value);
00264           widget = gtk_label_new (_(attrs[j].name));
00265           gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
00266           break;
00267 
00268         case HID_Mixed:
00269           hbox = gtk_hbox_new (FALSE, 4);
00270           gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
00271           
00272           /*
00273            * FIXME
00274            * need to pick the "digits" and step size argument more
00275            * intelligently
00276            */
00277           ghid_spin_button (hbox, &widget, attrs[j].default_val.real_value,
00278                             attrs[j].min_val, attrs[j].max_val, 0.01, 0.01, 3,
00279                             0,
00280                             dblspinner_changed_cb,
00281                             &(attrs[j].default_val.real_value), FALSE, NULL);
00282           gtk_widget_set_tooltip_text (widget, _(attrs[j].help_text));
00283 
00284           goto do_enum;
00285           break;
00286 
00287         case HID_Path:
00288           vbox1 = ghid_category_vbox (vbox, _(attrs[j].name), 4, 2, TRUE, TRUE);
00289           entry = gtk_entry_new ();
00290           gtk_box_pack_start (GTK_BOX (vbox1), entry, FALSE, FALSE, 0);
00291           gtk_entry_set_text (GTK_ENTRY (entry),
00292                               attrs[j].default_val.str_value);
00293           g_signal_connect (G_OBJECT (entry), "changed",
00294                             G_CALLBACK (entry_changed_cb),
00295                             &(attrs[j].default_val.str_value));
00296 
00297           gtk_widget_set_tooltip_text (entry, _(attrs[j].help_text));
00298           break;
00299 
00300         case HID_Unit:
00301           unit_list = get_unit_list ();
00302           n = get_n_units ();
00303 
00304           hbox = gtk_hbox_new (FALSE, 4);
00305           gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
00306 
00307           combo = gtk_combo_box_new_text ();
00308           gtk_widget_set_tooltip_text (combo, _(attrs[j].help_text));
00309           gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
00310           g_signal_connect (G_OBJECT (combo), "changed",
00311                             G_CALLBACK (enum_changed_cb),
00312                             &(attrs[j].default_val.int_value));
00313 
00314           /* 
00315            * Iterate through each value and add them to the
00316            * combo box
00317            */
00318           for (i = 0; i < n; ++i)
00319             gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
00320                                         unit_list[i].in_suffix);
00321           gtk_combo_box_set_active (GTK_COMBO_BOX (combo),
00322                                     attrs[j].default_val.int_value);
00323           widget = gtk_label_new (_(attrs[j].name));
00324           gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
00325           break;
00326         default:
00327           printf (_("%s: unknown type of HID attribute\n"), __FUNCTION__);
00328           break;
00329         }
00330     }
00331 
00332 
00333   gtk_widget_show_all (dialog);
00334 
00335   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
00336     {
00337       /* copy over the results */
00338       for (i = 0; i < n_attrs; i++)
00339         {
00340           results[i] = attrs[i].default_val;
00341           if (results[i].str_value)
00342             results[i].str_value = strdup (results[i].str_value);
00343         }
00344       rc = 0;
00345     }
00346   else
00347     rc = 1;
00348 
00349   gtk_widget_destroy (dialog);
00350 
00351   return rc;
00352 }
00353 
00354 
00355 
00356 static void
00357 exporter_clicked_cb (GtkButton * button, HID * exporter)
00358 {
00359   ghid_dialog_print (exporter);
00360 }
00361 
00362 void
00363 ghid_dialog_print (HID *hid)
00364 {
00365   HID_Attribute *attr;
00366   int n = 0;
00367   int i;
00368   HID_Attr_Val * results = NULL;
00369 
00370   /* signal the initial export select dialog that it should close */
00371   if (export_dialog)
00372     gtk_dialog_response (GTK_DIALOG (export_dialog), GTK_RESPONSE_CANCEL);
00373 
00374   exporter = hid;
00375 
00376   attr = exporter->get_export_options (&n);
00377   if (n > 0)
00378     {
00379       results = (HID_Attr_Val *) malloc (n * sizeof (HID_Attr_Val));
00380       if (results == NULL)
00381         {
00382           fprintf (stderr, _("%s() -- malloc failed\n"), __FUNCTION__);
00383           exit (1);
00384         }
00385       
00386       /* non-zero means cancel was picked */
00387       if (ghid_attribute_dialog (attr, n, results,  _("PCB Print Layout"), 
00388                                  exporter->description))
00389         return;
00390           
00391     }
00392 
00393   exporter->do_export (results);
00394   
00395   for (i = 0; i < n; i++)
00396     {
00397       if (results[i].str_value)
00398         free ((void *) results[i].str_value);
00399     }
00400 
00401   if (results)
00402     free (results);
00403 
00404   exporter = NULL;
00405 }
00406 
00407 void
00408 ghid_dialog_export (void)
00409 {
00410   GtkWidget *content_area;
00411   GtkWidget *vbox, *button;
00412   GHidPort *out = &ghid_port;
00413   int i;
00414   HID **hids;
00415   gboolean no_exporter = TRUE;
00416 
00417   export_dialog = gtk_dialog_new_with_buttons (_("PCB Export Layout"),
00418                                                GTK_WINDOW (out->top_window),
00419                                                (GtkDialogFlags)(GTK_DIALOG_MODAL
00420                                                |
00421                                                                 GTK_DIALOG_DESTROY_WITH_PARENT),
00422                                                GTK_STOCK_CANCEL,
00423                                                GTK_RESPONSE_CANCEL, NULL);
00424   gtk_window_set_wmclass (GTK_WINDOW (export_dialog), "PCB_Export", "PCB");
00425 
00426   content_area = gtk_dialog_get_content_area (GTK_DIALOG (export_dialog));
00427 
00428   vbox = gtk_vbox_new (FALSE, 6);
00429   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
00430   gtk_container_add (GTK_CONTAINER (content_area), vbox);
00431 
00432   /* 
00433    * Iterate over all the export HID's and build up a dialog box that
00434    * lets us choose which one we want to use.
00435    * This way, any additions to the exporter HID's automatically are
00436    * reflected in this dialog box.
00437    */
00438 
00439   hids = hid_enumerate ();
00440   for (i = 0; hids[i]; i++)
00441     {
00442       if (hids[i]->exporter)
00443         {
00444           no_exporter = FALSE;
00445           button = gtk_button_new_with_label (_(hids[i]->name));
00446           gtk_widget_set_tooltip_text (button, hids[i]->description);
00447           gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
00448           g_signal_connect (G_OBJECT (button), "clicked",
00449                             G_CALLBACK (exporter_clicked_cb), hids[i]);
00450         }
00451     }
00452 
00453   if (no_exporter)
00454     {
00455       gui->log (_("Can't find a suitable exporter HID"));
00456     }
00457 
00458   gtk_widget_show_all (export_dialog);
00459   gtk_dialog_run (GTK_DIALOG (export_dialog));
00460 
00461   if (export_dialog != NULL)
00462     gtk_widget_destroy (export_dialog);
00463   export_dialog = NULL;
00464 }