int ghid_attribute_dialog (HID_Attribute * attrs, int n_attrs, HID_Attr_Val * results, const char * title, const char * descr) { GtkWidget *dialog, *main_vbox, *vbox, *vbox1, *hbox, *entry; GtkWidget *combo; GtkWidget *widget; GHidPort *out = &ghid_port; int i, j; GtkTooltips *tips; int rc = 0; tips = gtk_tooltips_new (); dialog = gtk_dialog_new_with_buttons (_(title), GTK_WINDOW (out->top_window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_window_set_wmclass (GTK_WINDOW (dialog), "PCB_attribute_editor", "PCB"); main_vbox = gtk_vbox_new (FALSE, 6); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox); vbox = ghid_category_vbox (main_vbox, descr != NULL ? descr : "", 4, 2, TRUE, TRUE); /* * Iterate over all the export options and build up a dialog box * that lets us control all of the options. By doing things this * way, any changes to the exporter HID's automatically are * reflected in this dialog box. */ for (j = 0; j < n_attrs; j++) { if (attrs[j].help_text == ATTR_UNDOCUMENTED) continue; switch (attrs[j].type) { case HID_Label: widget = gtk_label_new (attrs[j].name); gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); gtk_tooltips_set_tip (tips, widget, attrs[j].help_text, NULL); break; case HID_Integer: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); /* * FIXME * need to pick the "digits" argument based on min/max * values */ ghid_spin_button (hbox, &widget, attrs[j].default_val.int_value, attrs[j].min_val, attrs[j].max_val, 1.0, 1.0, 0, 0, intspinner_changed_cb, &(attrs[j].default_val.int_value), FALSE, NULL); gtk_tooltips_set_tip (tips, widget, attrs[j].help_text, NULL); widget = gtk_label_new (attrs[j].name); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); break; case HID_Real: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); /* * FIXME * need to pick the "digits" and step size argument more * intelligently */ ghid_spin_button (hbox, &widget, attrs[j].default_val.real_value, attrs[j].min_val, attrs[j].max_val, 0.01, 0.01, 3, 0, dblspinner_changed_cb, &(attrs[j].default_val.real_value), FALSE, NULL); gtk_tooltips_set_tip (tips, widget, attrs[j].help_text, NULL); widget = gtk_label_new (attrs[j].name); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); break; case HID_String: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); gtk_entry_set_text (GTK_ENTRY (entry), attrs[j].default_val.str_value); gtk_tooltips_set_tip (tips, entry, attrs[j].help_text, NULL); g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (entry_changed_cb), &(attrs[j].default_val.str_value)); widget = gtk_label_new (attrs[j].name); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); break; case HID_Boolean: /* put this in a check button */ ghid_check_button_connected (vbox, &widget, attrs[j].default_val.int_value, TRUE, FALSE, FALSE, 0, set_flag_cb, &(attrs[j].default_val.int_value), attrs[j].name); gtk_tooltips_set_tip (tips, widget, attrs[j].help_text, NULL); break; case HID_Enum: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); do_enum: /* * We have to put the combo_box inside of an event_box in * order for tooltips to work. */ widget = gtk_event_box_new (); gtk_tooltips_set_tip (tips, widget, attrs[j].help_text, NULL); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); combo = gtk_combo_box_new_text (); gtk_container_add (GTK_CONTAINER (widget), combo); g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (enum_changed_cb), &(attrs[j].default_val.int_value)); /* * Iterate through each value and add them to the * combo box */ i = 0; while (attrs[j].enumerations[i]) { gtk_combo_box_append_text (GTK_COMBO_BOX (combo), attrs[j].enumerations[i]); i++; } gtk_combo_box_set_active (GTK_COMBO_BOX (combo), attrs[j].default_val.int_value); widget = gtk_label_new (attrs[j].name); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); break; case HID_Mixed: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); /* * FIXME * need to pick the "digits" and step size argument more * intelligently */ ghid_spin_button (hbox, &widget, attrs[j].default_val.real_value, attrs[j].min_val, attrs[j].max_val, 0.01, 0.01, 3, 0, dblspinner_changed_cb, &(attrs[j].default_val.real_value), FALSE, NULL); gtk_tooltips_set_tip (tips, widget, attrs[j].help_text, NULL); goto do_enum; break; case HID_Path: vbox1 = ghid_category_vbox (vbox, attrs[j].name, 4, 2, TRUE, TRUE); entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (vbox1), entry, FALSE, FALSE, 0); gtk_entry_set_text (GTK_ENTRY (entry), attrs[j].default_val.str_value); g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (entry_changed_cb), &(attrs[j].default_val.str_value)); gtk_tooltips_set_tip (tips, entry, attrs[j].help_text, NULL); break; default: printf ("%s: unknown type of HID attribute\n", __FUNCTION__); break; } } gtk_widget_show_all (dialog); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { /* copy over the results */ for (i = 0; i < n_attrs; i++) { results[i] = attrs[i].default_val; if (results[i].str_value) results[i].str_value = strdup (results[i].str_value); } rc = 0; } else rc = 1; gtk_widget_destroy (dialog); return rc; }
/* * The following function is taken almost directly from * ghid_attribte_dialog() from pcb. It is a generic attribute editor * gui where the dialog is built on the fly based on a passed in * attribute list. * * Written by Dan McMahill */ int attribute_interface_dialog (gerbv_HID_Attribute * attrs, int n_attrs, gerbv_HID_Attr_Val * results, const char * title, const char * descr) { GtkWidget *dialog, *main_vbox, *vbox, *vbox1, *hbox, *entry; GtkWidget *combo; GtkWidget *widget; int i, j; GtkTooltips *tips; int rc = 0; int set_auto_uncheck = 0; int sen = TRUE; /* * Store how many widgets we'll have in our dialog and keep track of * them. Be sure to free up our list if one existed already. */ n_widgets = n_attrs; if (all_widgets != NULL) free (all_widgets); all_widgets = (GtkWidget **) malloc (n_widgets * sizeof(GtkWidget *)); if (all_widgets == NULL) { fprintf (stderr, _("%s(): malloc failed for an array of size %d\n"), __FUNCTION__, n_widgets); exit (1); } dprintf ("%s(%p, %d, %p, \"%s\", \"%s\")\n", __FUNCTION__, attrs, n_attrs, results, title, descr); auto_uncheck_needed = 0; auto_uncheck_widget = NULL; auto_uncheck_attr = NULL; tips = gtk_tooltips_new (); dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (screen.win.topLevelWindow), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_window_set_wmclass (GTK_WINDOW (dialog), "gerbv_attribute_editor", _("gerbv")); main_vbox = gtk_vbox_new (FALSE, 6); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox); vbox = ghid_category_vbox (main_vbox, descr != NULL ? descr : "", 4, 2, TRUE, TRUE); /* * Iterate over all the attributes and build up a dialog box * that lets us control all of the options. By doing things this * way, any changes to the attributes or if there is a new list of * attributes, everything will automatically be reflected in this * dialog box. */ for (j = 0; j < n_attrs; j++) { dprintf (_("%s(): Adding attribute #%d\n"), __FUNCTION__, j); switch (attrs[j].type) { case HID_Label: widget = gtk_label_new (_(attrs[j].name)); gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); gtk_tooltips_set_tip (tips, widget, _(attrs[j].help_text), NULL); break; case HID_Integer: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); /* * FIXME * need to pick the "digits" argument based on min/max * values */ ghid_spin_button (hbox, &widget, attrs[j].default_val.int_value, attrs[j].min_val, attrs[j].max_val, 1.0, 1.0, 0, 0, intspinner_changed_cb, &(attrs[j].default_val.int_value), FALSE, NULL); gtk_tooltips_set_tip (tips, widget, _(attrs[j].help_text), NULL); all_widgets[j] = widget; widget = gtk_label_new (_(attrs[j].name)); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); break; case HID_Real: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); /* * FIXME * need to pick the "digits" and step size argument more * intelligently */ ghid_spin_button (hbox, &widget, attrs[j].default_val.real_value, attrs[j].min_val, attrs[j].max_val, 0.01, 0.01, 3, 0, dblspinner_changed_cb, &(attrs[j].default_val.real_value), FALSE, NULL); gtk_tooltips_set_tip (tips, widget, _(attrs[j].help_text), NULL); all_widgets[j] = widget; widget = gtk_label_new (_(attrs[j].name)); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); break; case HID_String: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); gtk_entry_set_text (GTK_ENTRY (entry), attrs[j].default_val.str_value); gtk_tooltips_set_tip (tips, entry, _(attrs[j].help_text), NULL); g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (entry_changed_cb), &(attrs[j].default_val.str_value)); all_widgets[j] = entry; widget = gtk_label_new (_(attrs[j].name)); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); break; case HID_Boolean: /* put this in a check button */ ghid_check_button_connected (vbox, &widget, attrs[j].default_val.int_value, TRUE, FALSE, FALSE, 0, set_flag_cb, &(attrs[j].default_val.int_value), _(attrs[j].name)); gtk_tooltips_set_tip (tips, widget, _(attrs[j].help_text), NULL); /* * This is an ugly ugly ugly hack.... If this is * the first in our list of attributes *and* it has a * magic name of "autodetect" then we'll remember it and * all of the other callbacks will cause this button to * come unchecked. Among the other nastiness * involved here, this dialog is now *required* to * be modal since we are using a static variable. * To avoid that, we need a new data type that can hold * more state information. Ideally we need a better * way to capture dependencies between attributes to * allow arbitrary relationships instead of just this * one single "magic" one. */ if (j == 0 && strcmp(attrs[j].name, "autodetect") == 0) { set_auto_uncheck = 1; auto_uncheck_widget = widget; auto_uncheck_attr = &(attrs[j].default_val.int_value); /* if the "auto" button in checked then don't let * anything else be sensitive. */ if (attrs[j].default_val.int_value) sen = FALSE; } all_widgets[j] = widget; break; case HID_Enum: hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); /* * We have to put the combo_box inside of an event_box in * order for tooltips to work. */ widget = gtk_event_box_new (); gtk_tooltips_set_tip (tips, widget, _(attrs[j].help_text), NULL); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); combo = gtk_combo_box_new_text (); gtk_container_add (GTK_CONTAINER (widget), combo); g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (enum_changed_cb), &(attrs[j].default_val.int_value)); /* * Iterate through each value and add them to the * combo box */ i = 0; while (attrs[j].enumerations[i]) { gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _(attrs[j].enumerations[i])); i++; } gtk_combo_box_set_active (GTK_COMBO_BOX (combo), attrs[j].default_val.int_value); all_widgets[j] = combo; widget = gtk_label_new (_(attrs[j].name)); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); break; case HID_Mixed: dprintf ("HID_Mixed\n"); break; case HID_Path: vbox1 = ghid_category_vbox (vbox, _(attrs[j].name), 4, 2, TRUE, TRUE); entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (vbox1), entry, FALSE, FALSE, 0); gtk_entry_set_text (GTK_ENTRY (entry), attrs[j].default_val.str_value); g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (entry_changed_cb), &(attrs[j].default_val.str_value)); gtk_tooltips_set_tip (tips, entry, _(attrs[j].help_text), NULL); all_widgets[j] = entry; break; default: fprintf (stderr, _("%s: unknown type of HID attribute\n"), __FUNCTION__); break; } } gtk_widget_show_all (dialog); auto_uncheck_needed = set_auto_uncheck; /* * part of the "auto" hack. Make everything sensitive or * insensitive based on the state of the "auto" toggle button (if it * exists) */ for (j = 1; j < n_widgets ; j++) { gtk_widget_set_sensitive (all_widgets[j], sen); } if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { /* copy over the results */ for (i = 0; i < n_attrs; i++) { results[i] = attrs[i].default_val; if (results[i].str_value) results[i].str_value = strdup (results[i].str_value); } rc = 0; } else rc = 1; gtk_widget_destroy (dialog); return rc; }