pcb 4.1.1
An interactive printed circuit board layout editor.
|
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 }