/* * 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; }
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; }
void ghid_netlist_window_create (GHidPort * out) { GtkWidget *vbox, *hbox, *button, *label, *sep; GtkTreeView *treeview; GtkTreeModel *model; GtkCellRenderer *renderer; GtkTreeViewColumn *column; if (netlist_window) return; netlist_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (netlist_window), "destroy", G_CALLBACK (netlist_destroy_cb), out); gtk_window_set_title (GTK_WINDOW (netlist_window), _("PCB Netlist")); gtk_window_set_wmclass (GTK_WINDOW (netlist_window), "PCB_Netlist", "PCB"); g_signal_connect (G_OBJECT (netlist_window), "configure_event", G_CALLBACK (netlist_window_configure_event_cb), NULL); gtk_window_set_default_size (GTK_WINDOW (netlist_window), -1, ghidgui->netlist_window_height); gtk_container_set_border_width (GTK_CONTAINER (netlist_window), 2); vbox = gtk_vbox_new (FALSE, 4); gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); gtk_container_add (GTK_CONTAINER (netlist_window), vbox); hbox = gtk_hbox_new (FALSE, 8); gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 4); model = net_model_create (); treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model (model)); net_model = model; net_treeview = treeview; gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (net_model), NET_NAME_COLUMN, GTK_SORT_ASCENDING); gtk_tree_view_set_rules_hint (treeview, FALSE); g_object_set (treeview, "enable-tree-lines", TRUE, NULL); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (treeview, -1, _(" "), renderer, "text", NET_ENABLED_COLUMN, NULL); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Net Name"), renderer, "text", NET_NAME_COLUMN, NULL); gtk_tree_view_insert_column (treeview, column, -1); gtk_tree_view_set_expander_column (treeview, column); /* TODO: dont expand all, but record expanded states when window is | destroyed and restore state here. */ gtk_tree_view_expand_all (treeview); ghid_scrolled_selection (treeview, hbox, GTK_SELECTION_SINGLE, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC, net_selection_changed_cb, NULL); /* Connect to the double click event. */ g_signal_connect (G_OBJECT (treeview), "row-activated", G_CALLBACK (net_selection_double_click_cb), NULL); /* Create the elements treeview and wait for a callback to populate it. */ treeview = GTK_TREE_VIEW (gtk_tree_view_new ()); node_treeview = treeview; gtk_tree_view_set_rules_hint (treeview, FALSE); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (treeview, -1, _("Nodes"), renderer, "text", NODE_NAME_COLUMN, NULL); ghid_scrolled_selection (treeview, hbox, GTK_SELECTION_SINGLE, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC, node_selection_changed_cb, NULL); hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); label = gtk_label_new (_("Operations on selected 'Net Name':")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4); button = gtk_button_new_with_label (_("Select")); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (netlist_select_cb), GINT_TO_POINTER (1)); button = gtk_button_new_with_label (_("Unselect")); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (netlist_select_cb), GINT_TO_POINTER (0)); button = gtk_button_new_with_label (_("Find")); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (netlist_find_cb), GINT_TO_POINTER (0)); button = gtk_button_new_with_label (_("Rip Up")); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (netlist_rip_up_cb), GINT_TO_POINTER (0)); ghid_check_button_connected (vbox, &disable_all_button, FALSE, TRUE, FALSE, FALSE, 0, netlist_disable_all_cb, NULL, _("Disable all nets for adding rats")); sep = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (vbox), sep, FALSE, FALSE, 3); hbox = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4); button = gtk_button_new_from_stock (GTK_STOCK_CLOSE); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (netlist_close_cb), NULL); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); gtk_widget_realize (netlist_window); if (Settings.AutoPlace) gtk_window_move (GTK_WINDOW (netlist_window), 10, 10); }