Index: trunk/scconfig/Rev.h =================================================================== --- trunk/scconfig/Rev.h (revision 6712) +++ trunk/scconfig/Rev.h (revision 6713) @@ -1 +1 @@ -static const int myrev = 6710; +static const int myrev = 6713; Index: trunk/scconfig/Rev.tab =================================================================== --- trunk/scconfig/Rev.tab (revision 6712) +++ trunk/scconfig/Rev.tab (revision 6713) @@ -1,4 +1,4 @@ -6710 configure gtk splitup +6713 configure gtk splitup 6392 configure draw cross section plugin (gtk and lesstif depend on it) 6365 configure gtk splitup 6111 configure layer vs. layer group code split Index: trunk/src_plugins/hid_gtk/gui.h =================================================================== --- trunk/src_plugins/hid_gtk/gui.h (revision 6712) +++ trunk/src_plugins/hid_gtk/gui.h (revision 6713) @@ -51,7 +51,7 @@ #include "../src_plugins/lib_gtk_common/bu_spin_button.h" #include "../src_plugins/lib_gtk_common/bu_status_line.h" #include "../src_plugins/lib_gtk_common/wt_coord_entry.h" -#include "../src_plugins/lib_gtk_common/wt_route_style.h" +#include "../src_plugins/lib_gtk_common/dlg_route_style.h" #include "../src_plugins/lib_gtk_common/dlg_propedit.h" /* needed for a type in GhidGui */ Index: trunk/src_plugins/lib_gtk_common/Plug.tmpasm =================================================================== --- trunk/src_plugins/lib_gtk_common/Plug.tmpasm (revision 6712) +++ trunk/src_plugins/lib_gtk_common/Plug.tmpasm (revision 6713) @@ -26,6 +26,7 @@ $(PLUGDIR)/lib_gtk_common/dlg_progress.o $(PLUGDIR)/lib_gtk_common/dlg_propedit.o $(PLUGDIR)/lib_gtk_common/dlg_report.o + $(PLUGDIR)/lib_gtk_common/dlg_route_style.o $(PLUGDIR)/lib_gtk_common/dlg_search.o $(PLUGDIR)/lib_gtk_common/in_keyboard.o $(PLUGDIR)/lib_gtk_common/in_mouse.o Index: trunk/src_plugins/lib_gtk_common/dlg_route_style.c =================================================================== --- trunk/src_plugins/lib_gtk_common/dlg_route_style.c (nonexistent) +++ trunk/src_plugins/lib_gtk_common/dlg_route_style.c (revision 6713) @@ -0,0 +1,460 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Alain Vigne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/* route style edit dialog */ + +#include +#include +#include "config.h" + +#include "compat_misc.h" +#include "compat_nls.h" +#include "polygon.h" +#include "obj_all.h" + +#include "bu_box.h" +#include "compat.h" + +/* FIXME: Get rid of that ... means get rid of global ghidgui */ +#include "../hid_gtk/gui.h" + +/* and replace by this one, at least +#include "dlg_route_style.h" +*/ + +/* SIGNAL HANDLERS */ + +/* Rebuild the gtk table for attribute list from style */ +static void update_attrib(pcb_gtk_dlg_route_style_t * dialog, pcb_gtk_obj_route_style_t * style) +{ + GtkTreeIter iter; + int i; + + gtk_list_store_clear(dialog->attr_model); + + for (i = 0; i < style->rst->attr.Number; i++) { + gtk_list_store_append(dialog->attr_model, &iter); + gtk_list_store_set(dialog->attr_model, &iter, 0, style->rst->attr.List[i].name, -1); + gtk_list_store_set(dialog->attr_model, &iter, 1, style->rst->attr.List[i].value, -1); + } + + gtk_list_store_append(dialog->attr_model, &iter); + gtk_list_store_set(dialog->attr_model, &iter, 0, "", -1); + gtk_list_store_set(dialog->attr_model, &iter, 1, "", -1); +} + +/** attr table ? */ +static int get_sel(pcb_gtk_dlg_route_style_t * dlg) +{ + GtkTreeIter iter; + GtkTreeSelection *tsel; + GtkTreeModel *tm; + GtkTreePath *path; + int *i; + + tsel = gtk_tree_view_get_selection(GTK_TREE_VIEW(dlg->attr_table)); + if (tsel == NULL) + return -1; + + gtk_tree_selection_get_selected(tsel, &tm, &iter); + if (iter.stamp == 0) + return -1; + + path = gtk_tree_model_get_path(tm, &iter); + if (path != NULL) { + i = gtk_tree_path_get_indices(path); + if (i != NULL) { +/* gtk_tree_model_get(GTK_TREE_MODEL(dlg->attr_model), &iter, 0, nkey, 1, nval, -1);*/ + return i[0]; + } + } + return -1; +} + +/** Callback for dialog box's combobox being changed + \par Function Description + When a different layer is selected, this function loads + that layer's data into the dialog. Alternately, if the + "New layer" option is selected, this loads a new name + but no other data. + + \param [in] combo The combobox + \param [in] dialog The rest of the widgets to be updated + */ +static void dialog_style_changed_cb(GtkComboBox * combo, pcb_gtk_dlg_route_style_t * dialog) +{ + pcb_gtk_route_style_t *rss; + pcb_gtk_obj_route_style_t *style; + GtkTreeIter iter; + GtkTreeModel *tree_model; + + if (dialog->inhibit_style_change) + return; + + rss = dialog->rss; + tree_model = GTK_TREE_MODEL(rss->model); + gtk_combo_box_get_active_iter(combo, &iter); + gtk_tree_model_get(tree_model, &iter, STYLE_DATA_COL, &style, -1); + + if (style == NULL) { + gtk_entry_set_text(GTK_ENTRY(dialog->name_entry), _("New Style")); + rss->selected = -1; + return; + } + + gtk_entry_set_text(GTK_ENTRY(dialog->name_entry), style->rst->name); + pcb_gtk_coord_entry_set_value(GHID_COORD_ENTRY(dialog->line_entry), style->rst->Thick); + pcb_gtk_coord_entry_set_value(GHID_COORD_ENTRY(dialog->via_hole_entry), style->rst->Hole); + pcb_gtk_coord_entry_set_value(GHID_COORD_ENTRY(dialog->via_size_entry), style->rst->Diameter); + pcb_gtk_coord_entry_set_value(GHID_COORD_ENTRY(dialog->clearance_entry), style->rst->Clearance); + + if (style->hidden) + rss->selected = -1; + else + rss->selected = style->rst - PCB->RouteStyle.array; + + update_attrib(dialog, style); +} + +static void attr_edited(int col, GtkCellRendererText * cell, gchar * path, gchar * new_text, pcb_gtk_dlg_route_style_t * dlg) +{ + GtkTreeIter iter; + pcb_gtk_obj_route_style_t *style; + int idx = get_sel(dlg); + + dlg->attr_editing = 0; + + gtk_combo_box_get_active_iter(GTK_COMBO_BOX(dlg->select_box), &iter); + gtk_tree_model_get(GTK_TREE_MODEL(dlg->rss->model), &iter, STYLE_DATA_COL, &style, -1); + + if (style == NULL) + return; + + if (idx >= style->rst->attr.Number) { /* add new */ + if (col == 0) + pcb_attribute_put(&style->rst->attr, new_text, "n/a", 0); + else + pcb_attribute_put(&style->rst->attr, "n/a", new_text, 0); + } + else { /* overwrite existing */ + char **dest; + if (col == 0) + dest = &style->rst->attr.List[idx].name; + else + dest = &style->rst->attr.List[idx].value; + if (*dest != NULL) + free(*dest); + *dest = pcb_strdup(new_text); + } + + /* rebuild the table to keep it in sync - expensive, but it happens rarely */ + update_attrib(dlg, style); +} + +static void attr_edited_key_cb(GtkCellRendererText * cell, gchar * path, gchar * new_text, pcb_gtk_dlg_route_style_t * dlg) +{ + attr_edited(0, cell, path, new_text, dlg); +} + +static void attr_edited_val_cb(GtkCellRendererText * cell, gchar * path, gchar * new_text, pcb_gtk_dlg_route_style_t * dlg) +{ + attr_edited(1, cell, path, new_text, dlg); +} + +static void attr_edit_started_cb(GtkCellRendererText * cell, GtkCellEditable * e, gchar * path, pcb_gtk_dlg_route_style_t * dlg) +{ + dlg->attr_editing = 1; +} + +static void attr_edit_canceled_cb(GtkCellRendererText * cell, pcb_gtk_dlg_route_style_t * dlg) +{ + dlg->attr_editing = 0; +} + +static gboolean attr_key_release_cb(GtkWidget * widget, GdkEventKey * event, pcb_gtk_dlg_route_style_t * dlg) +{ + unsigned short int kv = event->keyval; + + if (dlg->attr_editing) + return FALSE; + + switch (kv) { +#ifdef GDK_KEY_KP_Delete + case GDK_KEY_KP_Delete: +#endif +#ifdef GDK_KEY_Delete + case GDK_KEY_Delete: +#endif + case 'd': + { + int idx = get_sel(dlg); + GtkTreeIter iter; + pcb_gtk_obj_route_style_t *style; + gtk_combo_box_get_active_iter(GTK_COMBO_BOX(dlg->select_box), &iter); + gtk_tree_model_get(GTK_TREE_MODEL(dlg->rss->model), &iter, STYLE_DATA_COL, &style, -1); + if (style == NULL) + return FALSE; + if ((idx >= 0) && (idx < style->rst->attr.Number)) { + pcb_attribute_remove_idx(&style->rst->attr, idx); + update_attrib(dlg, style); + } + } + break; + } + return FALSE; +} + +static void add_new_iter(pcb_gtk_route_style_t * rss) +{ + /* Add "new style" option to list */ + gtk_list_store_append(rss->model, &rss->new_iter); + gtk_list_store_set(rss->model, &rss->new_iter, STYLE_TEXT_COL, _(""), STYLE_DATA_COL, NULL, -1); +} + +/* Callback for Delete route style button */ +static void delete_button_cb(GtkButton * button, pcb_gtk_dlg_route_style_t * dialog) +{ + if (dialog->rss->selected < 0) + return; + + dialog->inhibit_style_change = 1; + pcb_gtk_route_style_empty(GHID_ROUTE_STYLE(ghidgui->route_style_selector)); + +#warning TODO: some of these should be in core + pcb_gtk_route_style_copy(dialog->rss->selected); + + vtroutestyle_remove(&PCB->RouteStyle, dialog->rss->selected, 1); + dialog->rss->active_style = NULL; + make_route_style_buttons(GHID_ROUTE_STYLE(ghidgui->route_style_selector)); + pcb_trace("Style: %d deleted\n", dialog->rss->selected); + pcb_board_set_changed_flag(pcb_true); + ghid_window_set_name_label(PCB->Name); + add_new_iter(dialog->rss); + dialog->inhibit_style_change = 0; + pcb_gtk_route_style_select_style(dialog->rss, &pcb_custom_route_style); + gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->select_box), 0); +} + +/** Helper for edit_button_cb */ +static void _table_attach_(GtkWidget * table, gint row, const gchar * label, GtkWidget * entry) +{ + GtkWidget *label_w = gtk_label_new(label); + gtk_misc_set_alignment(GTK_MISC(label_w), 1.0, 0.5); + gtk_table_attach(GTK_TABLE(table), label_w, 0, 1, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + gtk_table_attach(GTK_TABLE(table), entry, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); +} + +/** Helper for edit_button_cb */ +static void _table_attach(GtkWidget * table, gint row, const gchar * label, GtkWidget ** entry, pcb_coord_t min, + pcb_coord_t max) +{ + *entry = pcb_gtk_coord_entry_new(min, max, 0, conf_core.editor.grid_unit, CE_SMALL); + _table_attach_(table, row, label, *entry); +} + +void pcb_gtk_route_style_edit_dialog(pcb_gtk_route_style_t * rss) +{ + GtkTreePath *path; + GtkTreeIter iter; + pcb_gtk_dlg_route_style_t dialog_data; + GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); + GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(rss)); + GtkWidget *dialog; + GtkWidget *content_area; + GtkWidget *vbox, *hbox, *sub_vbox, *table; + GtkWidget *label, *select_box, *check_box; + GtkWidget *button; + const char *new_name; + + memset(&dialog_data, 0, sizeof(dialog_data)); /* make sure all flags are cleared */ + + /* Build dialog */ + dialog = gtk_dialog_new_with_buttons(_("Edit Route Styles"), + GTK_WINDOW(window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); + + label = gtk_label_new(_("Edit Style:")); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + + select_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(rss->model)); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(select_box), renderer, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(select_box), renderer, "text", STYLE_TEXT_COL, NULL); + + content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + hbox = gtkc_hbox_new(FALSE, 4); + gtk_box_pack_start(GTK_BOX(content_area), hbox, TRUE, TRUE, 4); + vbox = gtkc_vbox_new(FALSE, 4); + gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 4); + + hbox = gtkc_hbox_new(FALSE, 4); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 4); + gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), select_box, TRUE, TRUE, 0); + + sub_vbox = ghid_category_vbox(vbox, _("Route Style Data"), 4, 2, TRUE, TRUE); + table = gtk_table_new(5, 2, FALSE); + gtk_box_pack_start(GTK_BOX(sub_vbox), table, TRUE, TRUE, 4); + label = gtk_label_new(_("Name:")); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + dialog_data.name_entry = gtk_entry_new(); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + gtk_table_attach(GTK_TABLE(table), dialog_data.name_entry, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + + _table_attach(table, 1, _("Line width:"), &dialog_data.line_entry, PCB_MIN_LINESIZE, PCB_MAX_LINESIZE); + _table_attach(table, 2, _("Via hole size:"), + &dialog_data.via_hole_entry, PCB_MIN_PINORVIAHOLE, PCB_MAX_PINORVIASIZE - PCB_MIN_PINORVIACOPPER); + _table_attach(table, 3, _("Via ring size:"), + &dialog_data.via_size_entry, PCB_MIN_PINORVIAHOLE + PCB_MIN_PINORVIACOPPER, PCB_MAX_PINORVIASIZE); + _table_attach(table, 4, _("Clearance:"), &dialog_data.clearance_entry, PCB_MIN_LINESIZE, PCB_MAX_LINESIZE); + + _table_attach_(table, 5, "", gtk_label_new("")); + + /* create attrib table */ + { + GType *ty; + GtkCellRenderer *renderer; + + dialog_data.attr_table = gtk_tree_view_new(); + + ty = malloc(sizeof(GType) * 2); + ty[0] = G_TYPE_STRING; + ty[1] = G_TYPE_STRING; + dialog_data.attr_model = gtk_list_store_newv(2, ty); + free(ty); + + renderer = gtk_cell_renderer_text_new(); + g_object_set(renderer, "editable", TRUE, NULL); + g_signal_connect(renderer, "edited", G_CALLBACK(attr_edited_key_cb), &dialog_data); + g_signal_connect(renderer, "editing-started", G_CALLBACK(attr_edit_started_cb), &dialog_data); + g_signal_connect(renderer, "editing-canceled", G_CALLBACK(attr_edit_canceled_cb), &dialog_data); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(dialog_data.attr_table), -1, "key", renderer, "text", 0, NULL); + + + renderer = gtk_cell_renderer_text_new(); + g_object_set(renderer, "editable", TRUE, NULL); + g_signal_connect(renderer, "edited", G_CALLBACK(attr_edited_val_cb), &dialog_data); + g_signal_connect(renderer, "editing-started", G_CALLBACK(attr_edit_started_cb), &dialog_data); + g_signal_connect(renderer, "editing-canceled", G_CALLBACK(attr_edit_canceled_cb), &dialog_data); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(dialog_data.attr_table), -1, "value", renderer, "text", 1, NULL); + + gtk_tree_view_set_model(GTK_TREE_VIEW(dialog_data.attr_table), GTK_TREE_MODEL(dialog_data.attr_model)); + g_signal_connect(G_OBJECT(dialog_data.attr_table), "key-release-event", G_CALLBACK(attr_key_release_cb), &dialog_data); + + } + _table_attach_(table, 6, _("Attributes:"), dialog_data.attr_table); + + + /* create delete button */ + button = gtk_button_new_with_label(_("Delete Style")); + g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(delete_button_cb), &dialog_data); + gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, FALSE, 0); + + sub_vbox = ghid_category_vbox(vbox, _("Set as Default"), 4, 2, TRUE, TRUE); + check_box = gtk_check_button_new_with_label(_("Save route style settings as default")); + gtk_box_pack_start(GTK_BOX(sub_vbox), check_box, TRUE, TRUE, 0); + + add_new_iter(rss); + + /* Display dialog */ + dialog_data.rss = rss; + dialog_data.select_box = select_box; + if (rss->active_style != NULL) { + path = gtk_tree_row_reference_get_path(rss->active_style->rref); + gtk_tree_model_get_iter(GTK_TREE_MODEL(rss->model), &iter, path); + g_signal_connect(G_OBJECT(select_box), "changed", G_CALLBACK(dialog_style_changed_cb), &dialog_data); + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(select_box), &iter); + } + gtk_widget_show_all(dialog); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { + int changed = 0; + pcb_route_style_t *rst; + pcb_gtk_obj_route_style_t *style; + gboolean save; + + if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(select_box), &iter)) + goto cancel; + gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, STYLE_DATA_COL, &style, -1); + if (style == NULL) { + int n = vtroutestyle_len(&PCB->RouteStyle); + rst = vtroutestyle_get(&PCB->RouteStyle, n, 1); + } + else { + rst = style->rst; + *rst->name = '\0'; + } + + new_name = gtk_entry_get_text(GTK_ENTRY(dialog_data.name_entry)); + + while (isspace(*new_name)) + new_name++; + if (strcmp(rst->name, new_name) != 0) { + strncpy(rst->name, new_name, sizeof(rst->name) - 1); + rst->name[sizeof(rst->name) - 1] = '0'; + changed = 1; + } + +/* Modify the route style only if there's significant difference (beyond rouding errors) */ +#define rst_modify(changed, dst, src) \ + do { \ + pcb_coord_t __tmp__ = src; \ + if (abs(dst - __tmp__) > 10) { \ + changed = 1; \ + dst = __tmp__; \ + } \ + } while(0) + rst_modify(changed, rst->Thick, pcb_gtk_coord_entry_get_value(GHID_COORD_ENTRY(dialog_data.line_entry))); + rst_modify(changed, rst->Hole, pcb_gtk_coord_entry_get_value(GHID_COORD_ENTRY(dialog_data.via_hole_entry))); + rst_modify(changed, rst->Diameter, pcb_gtk_coord_entry_get_value(GHID_COORD_ENTRY(dialog_data.via_size_entry))); + rst_modify(changed, rst->Clearance, pcb_gtk_coord_entry_get_value(GHID_COORD_ENTRY(dialog_data.clearance_entry))); +#undef rst_modify + save = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_box)); + if (style == NULL) + /*style = ghid_route_style_real_add_route_style(rss, rst, 0); */ + /* FIXME !!! static. function :( + style = ghid_route_style_real_add_route_style(rss, rst, 0); + */ + ; + else { + gtk_action_set_label(GTK_ACTION(style->action), rst->name); + gtk_list_store_set(rss->model, &iter, STYLE_TEXT_COL, rst->name, -1); + } + + /* Cleanup */ + gtk_widget_destroy(dialog); + gtk_list_store_remove(rss->model, &rss->new_iter); + /* Emit change signals */ + pcb_gtk_route_style_select_style(rss, rst); + /*g_signal_emit(rss, ghid_route_style_signals[STYLE_EDITED_SIGNAL], 0, save); */ + g_signal_emit_by_name(rss, "style-edited", 0, save); + + if (changed) { + pcb_board_set_changed_flag(pcb_true); + ghid_window_set_name_label(PCB->Name); + } + } + else { + cancel:; + gtk_widget_destroy(dialog); + gtk_list_store_remove(rss->model, &rss->new_iter); + } +} Index: trunk/src_plugins/lib_gtk_common/dlg_route_style.h =================================================================== --- trunk/src_plugins/lib_gtk_common/dlg_route_style.h (nonexistent) +++ trunk/src_plugins/lib_gtk_common/dlg_route_style.h (revision 6713) @@ -0,0 +1,22 @@ +/* Very linked to the widget ! */ +#include "wt_route_style.h" + +struct pcb_gtk_dlg_route_style_s { + pcb_gtk_route_style_t *rss; + GtkWidget *name_entry; + GtkWidget *line_entry; + GtkWidget *via_hole_entry; + GtkWidget *via_size_entry; + GtkWidget *clearance_entry; + + GtkWidget *select_box; + + GtkWidget *attr_table; /* Attributes gtk_tree_view */ + GtkListStore *attr_model; /* Attributes gtk_tree_model */ + + int inhibit_style_change; /* when 1, do not do anything when style changes */ + int attr_editing; /* set to 1 when an attribute key or value text is being edited */ +}; + +/** Builds and runs the "edit route style" dialog */ +void pcb_gtk_route_style_edit_dialog(pcb_gtk_route_style_t * rss); Index: trunk/src_plugins/lib_gtk_common/wt_route_style.c =================================================================== --- trunk/src_plugins/lib_gtk_common/wt_route_style.c (revision 6712) +++ trunk/src_plugins/lib_gtk_common/wt_route_style.c (revision 6713) @@ -1,174 +1,51 @@ -/*! \file - * \brief Implementation of pcb_gtk_route_style_t widget - * \par Description - * Please write description here. +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Alain Vigne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * */ +/** Implementation of pcb_gtk_route_style_t widget. + This widget is calling another Dialog, upon "Edit" clicked button */ + #include "config.h" #include "conf_core.h" -#include "wt_route_style.h" -//#include "gtkhid.h" +/*FIXME: Remove... */ #include "../hid_gtk/gui.h" +/* and replace with, at least +#include "dlg_route_style.h" +*/ #include "pcb-printf.h" -#include "route_style.h" #include "compat_nls.h" #include -/* Forward dec'ls */ -struct _route_style; -struct _route_style *ghid_route_style_real_add_route_style(pcb_gtk_route_style_t *, pcb_route_style_t *, int); -static void ghid_route_style_finalize(GObject * object); -static void add_new_iter(pcb_gtk_route_style_t * rss); /** Global action creation counter */ static gint action_count; -/** Signals exposed by the widget */ -enum { - SELECT_STYLE_SIGNAL, - STYLE_EDITED_SIGNAL, - LAST_SIGNAL -}; - -/** Columns used for internal data store */ -enum { - TEXT_COL, - DATA_COL, - N_COLS -}; - static GtkVBox *pcb_gtk_route_style_parent_class; -static guint ghid_route_style_signals[LAST_SIGNAL] = { 0 }; +static guint ghid_route_style_signals[STYLE_LAST_SIGNAL] = { 0 }; -struct pcb_gtk_route_style_s { - GtkVBox parent; - GSList *button_radio_group; - GSList *action_radio_group; - GtkWidget *edit_button; - - GtkActionGroup *action_group; - GtkAccelGroup *accel_group; - - int hidden_button; /* whether the hidden button is created */ - int selected; /* index of the currently selected route style */ - - GtkListStore *model; - struct _route_style *active_style; - - GtkTreeIter new_iter; /* iter for the item */ - -}; - -struct pcb_gtk_route_style_class_s { - GtkVBoxClass parent_class; - - void (*select_style) (pcb_gtk_route_style_t *, pcb_route_style_t *); - void (*style_edited) (pcb_gtk_route_style_t *, gboolean); -}; - -struct _route_style { - GtkRadioAction *action; - GtkWidget *button; - GtkWidget *menu_item; - GtkTreeRowReference *rref; - pcb_route_style_t *rst; - gulong sig_id; - int hidden; -}; - -/* SIGNAL HANDLERS */ -/** Callback for user selection of a route style */ -static void radio_select_cb(GtkToggleAction * action, pcb_gtk_route_style_t * rss) -{ - rss->active_style = g_object_get_data(G_OBJECT(action), "route-style"); - if (gtk_toggle_action_get_active(action)) - g_signal_emit(rss, ghid_route_style_signals[SELECT_STYLE_SIGNAL], 0, rss->active_style->rst); -} - -/* EDIT DIALOG */ -struct _dialog { - pcb_gtk_route_style_t *rss; - GtkWidget *name_entry; - GtkWidget *line_entry; - GtkWidget *via_hole_entry; - GtkWidget *via_size_entry; - GtkWidget *clearance_entry; - - GtkWidget *select_box; - - GtkWidget *attr_table; - GtkListStore *attr_model; - - int inhibit_style_change; /* when 1, do not do anything when style changes */ - int attr_editing; /* set to 1 when an attribute key or value text is being edited */ -}; - -/* Rebuild the gtk table for attribute list from style */ -static void update_attrib(struct _dialog *dialog, struct _route_style *style) -{ - GtkTreeIter iter; - int i; - - gtk_list_store_clear(dialog->attr_model); - - for (i = 0; i < style->rst->attr.Number; i++) { - gtk_list_store_append(dialog->attr_model, &iter); - gtk_list_store_set(dialog->attr_model, &iter, 0, style->rst->attr.List[i].name, -1); - gtk_list_store_set(dialog->attr_model, &iter, 1, style->rst->attr.List[i].value, -1); - } - - gtk_list_store_append(dialog->attr_model, &iter); - gtk_list_store_set(dialog->attr_model, &iter, 0, "", -1); - gtk_list_store_set(dialog->attr_model, &iter, 1, "", -1); -} - -/** Callback for dialog box's combobox being changed - \par Function Description - When a different layer is selected, this function loads - that layer's data into the dialog. Alternately, if the - "New layer" option is selected, this loads a new name - but no other data. - - \param [in] combo The combobox - \param [in] dialog The rest of the widgets to be updated - */ -static void dialog_style_changed_cb(GtkComboBox * combo, struct _dialog *dialog) -{ - struct _route_style *style; - GtkTreeIter iter; - - if (dialog->inhibit_style_change) - return; - - gtk_combo_box_get_active_iter(combo, &iter); - gtk_tree_model_get(GTK_TREE_MODEL(dialog->rss->model), &iter, DATA_COL, &style, -1); - - if (style == NULL) { - gtk_entry_set_text(GTK_ENTRY(dialog->name_entry), _("New Style")); - dialog->rss->selected = -1; - return; - } - - gtk_entry_set_text(GTK_ENTRY(dialog->name_entry), style->rst->name); - pcb_gtk_coord_entry_set_value(GHID_COORD_ENTRY(dialog->line_entry), style->rst->Thick); - pcb_gtk_coord_entry_set_value(GHID_COORD_ENTRY(dialog->via_hole_entry), style->rst->Hole); - pcb_gtk_coord_entry_set_value(GHID_COORD_ENTRY(dialog->via_size_entry), style->rst->Diameter); - pcb_gtk_coord_entry_set_value(GHID_COORD_ENTRY(dialog->clearance_entry), style->rst->Clearance); - - if (style->hidden) - dialog->rss->selected = -1; - else - dialog->rss->selected = style->rst - PCB->RouteStyle.array; - - update_attrib(dialog, style); -} - #warning TODO: this should be in core -static void copy_route_style(int idx) +void pcb_gtk_route_style_copy(int idx) { pcb_route_style_t *drst; @@ -181,367 +58,38 @@ pcb_custom_route_style.Hole = drst->Hole; } -/* Callback for Delete route style button */ -static void delete_button_cb(GtkButton * button, struct _dialog *dialog) +/** Launches the Edit dialog */ +static void edit_button_cb(GtkButton * btn, pcb_gtk_route_style_t * rss) { - if (dialog->rss->selected < 0) - return; - - dialog->inhibit_style_change = 1; - pcb_gtk_route_style_empty(GHID_ROUTE_STYLE(ghidgui->route_style_selector)); - -#warning TODO: some of these should be in core - copy_route_style(dialog->rss->selected); - - vtroutestyle_remove(&PCB->RouteStyle, dialog->rss->selected, 1); - dialog->rss->active_style = NULL; - make_route_style_buttons(GHID_ROUTE_STYLE(ghidgui->route_style_selector)); - pcb_trace("Style: %d deleted\n", dialog->rss->selected); - pcb_board_set_changed_flag(pcb_true); - ghid_window_set_name_label(PCB->Name); - add_new_iter(dialog->rss); - dialog->inhibit_style_change = 0; - pcb_gtk_route_style_select_style(dialog->rss, &pcb_custom_route_style); - gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->select_box), 0); + pcb_gtk_route_style_edit_dialog(rss); } -/***** attr table *****/ -static int get_sel(struct _dialog *dlg) +/** Callback for user selection of a route style */ +static void radio_select_cb(GtkToggleAction * action, pcb_gtk_route_style_t * rss) { - GtkTreeIter iter; - GtkTreeSelection *tsel; - GtkTreeModel *tm; - GtkTreePath *path; - int *i; - - tsel = gtk_tree_view_get_selection(GTK_TREE_VIEW(dlg->attr_table)); - if (tsel == NULL) - return -1; - - gtk_tree_selection_get_selected(tsel, &tm, &iter); - if (iter.stamp == 0) - return -1; - - path = gtk_tree_model_get_path(tm, &iter); - if (path != NULL) { - i = gtk_tree_path_get_indices(path); - if (i != NULL) { -/* gtk_tree_model_get(GTK_TREE_MODEL(dlg->attr_model), &iter, 0, nkey, 1, nval, -1);*/ - return i[0]; - } - } - return -1; + rss->active_style = g_object_get_data(G_OBJECT(action), "route-style"); + if (gtk_toggle_action_get_active(action)) + g_signal_emit(rss, ghid_route_style_signals[SELECT_STYLE_SIGNAL], 0, rss->active_style->rst); } -static void attr_edited(int col, GtkCellRendererText * cell, gchar * path, gchar * new_text, struct _dialog *dlg) +/* CONSTRUCTOR */ +static void ghid_route_style_init(pcb_gtk_route_style_t * rss) { - GtkTreeIter iter; - struct _route_style *style; - int idx = get_sel(dlg); - - dlg->attr_editing = 0; - - gtk_combo_box_get_active_iter(GTK_COMBO_BOX(dlg->select_box), &iter); - gtk_tree_model_get(GTK_TREE_MODEL(dlg->rss->model), &iter, DATA_COL, &style, -1); - - if (style == NULL) - return; - - if (idx >= style->rst->attr.Number) { /* add new */ - if (col == 0) - pcb_attribute_put(&style->rst->attr, new_text, "n/a", 0); - else - pcb_attribute_put(&style->rst->attr, "n/a", new_text, 0); - } - else { /* overwrite existing */ - char **dest; - if (col == 0) - dest = &style->rst->attr.List[idx].name; - else - dest = &style->rst->attr.List[idx].value; - if (*dest != NULL) - free(*dest); - *dest = pcb_strdup(new_text); - } - - /* rebuild the table to keep it in sync - expensive, but it happens rarely */ - update_attrib(dlg, style); } -static void attr_edited_key_cb(GtkCellRendererText * cell, gchar * path, gchar * new_text, struct _dialog *dlg) +/** Clean up object before garbage collection */ +static void ghid_route_style_finalize(GObject * object) { - attr_edited(0, cell, path, new_text, dlg); -} + pcb_gtk_route_style_t *rss = (pcb_gtk_route_style_t *) object; -static void attr_edited_val_cb(GtkCellRendererText * cell, gchar * path, gchar * new_text, struct _dialog *dlg) -{ - attr_edited(1, cell, path, new_text, dlg); -} + pcb_gtk_route_style_empty(rss); -static void attr_edit_started_cb(GtkCellRendererText * cell, GtkCellEditable * e, gchar * path, struct _dialog *dlg) -{ - dlg->attr_editing = 1; -} + g_object_unref(rss->accel_group); + g_object_unref(rss->action_group); -static void attr_edit_canceled_cb(GtkCellRendererText * cell, struct _dialog *dlg) -{ - dlg->attr_editing = 0; + G_OBJECT_CLASS(pcb_gtk_route_style_parent_class)->finalize(object); } -static gboolean attr_key_release_cb(GtkWidget * widget, GdkEventKey * event, struct _dialog *dlg) -{ - unsigned short int kv = event->keyval; - - if (dlg->attr_editing) - return FALSE; - - switch (kv) { -#ifdef GDK_KEY_KP_Delete - case GDK_KEY_KP_Delete: -#endif -#ifdef GDK_KEY_Delete - case GDK_KEY_Delete: -#endif - case 'd': - { - int idx = get_sel(dlg); - GtkTreeIter iter; - struct _route_style *style; - gtk_combo_box_get_active_iter(GTK_COMBO_BOX(dlg->select_box), &iter); - gtk_tree_model_get(GTK_TREE_MODEL(dlg->rss->model), &iter, DATA_COL, &style, -1); - if (style == NULL) - return FALSE; - if ((idx >= 0) && (idx < style->rst->attr.Number)) { - pcb_attribute_remove_idx(&style->rst->attr, idx); - update_attrib(dlg, style); - } - } - break; - } - return FALSE; -} - -/**** dialog creation ****/ - -/** Helper for edit_button_cb */ -static void _table_attach_(GtkWidget * table, gint row, const gchar * label, GtkWidget * entry) -{ - GtkWidget *label_w = gtk_label_new(label); - gtk_misc_set_alignment(GTK_MISC(label_w), 1.0, 0.5); - gtk_table_attach(GTK_TABLE(table), label_w, 0, 1, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); -} - -/** Helper for edit_button_cb */ -static void _table_attach(GtkWidget * table, gint row, const gchar * label, GtkWidget ** entry, pcb_coord_t min, - pcb_coord_t max) -{ - *entry = pcb_gtk_coord_entry_new(min, max, 0, conf_core.editor.grid_unit, CE_SMALL); - _table_attach_(table, row, label, *entry); -} - -static void add_new_iter(pcb_gtk_route_style_t * rss) -{ - /* Add "new style" option to list */ - gtk_list_store_append(rss->model, &rss->new_iter); - gtk_list_store_set(rss->model, &rss->new_iter, TEXT_COL, _(""), DATA_COL, NULL, -1); -} - -void pcb_gtk_route_style_edit_dialog(pcb_gtk_route_style_t * rss) -{ - GtkTreePath *path; - GtkTreeIter iter; - struct _dialog dialog_data; - GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); - GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(rss)); - GtkWidget *dialog; - GtkWidget *content_area; - GtkWidget *vbox, *hbox, *sub_vbox, *table; - GtkWidget *label, *select_box, *check_box; - GtkWidget *button; - const char *new_name; - - memset(&dialog_data, 0, sizeof(dialog_data)); /* make sure all flags are cleared */ - - /* Build dialog */ - dialog = gtk_dialog_new_with_buttons(_("Edit Route Styles"), - GTK_WINDOW(window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); - - label = gtk_label_new(_("Edit Style:")); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - - select_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(rss->model)); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(select_box), renderer, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(select_box), renderer, "text", TEXT_COL, NULL); - - content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_box_pack_start(GTK_BOX(content_area), hbox, TRUE, TRUE, 4); - vbox = gtk_vbox_new(FALSE, 4); - gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 4); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 4); - gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), select_box, TRUE, TRUE, 0); - - sub_vbox = ghid_category_vbox(vbox, _("Route Style Data"), 4, 2, TRUE, TRUE); - table = gtk_table_new(5, 2, FALSE); - gtk_box_pack_start(GTK_BOX(sub_vbox), table, TRUE, TRUE, 4); - label = gtk_label_new(_("Name:")); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - dialog_data.name_entry = gtk_entry_new(); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); - gtk_table_attach(GTK_TABLE(table), dialog_data.name_entry, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); - - _table_attach(table, 1, _("Line width:"), &dialog_data.line_entry, PCB_MIN_LINESIZE, PCB_MAX_LINESIZE); - _table_attach(table, 2, _("Via hole size:"), - &dialog_data.via_hole_entry, PCB_MIN_PINORVIAHOLE, PCB_MAX_PINORVIASIZE - PCB_MIN_PINORVIACOPPER); - _table_attach(table, 3, _("Via ring size:"), - &dialog_data.via_size_entry, PCB_MIN_PINORVIAHOLE + PCB_MIN_PINORVIACOPPER, PCB_MAX_PINORVIASIZE); - _table_attach(table, 4, _("Clearance:"), &dialog_data.clearance_entry, PCB_MIN_LINESIZE, PCB_MAX_LINESIZE); - - _table_attach_(table, 5, "", gtk_label_new("")); - - /* create attrib table */ - { - GType *ty; - GtkCellRenderer *renderer; - - dialog_data.attr_table = gtk_tree_view_new(); - - ty = malloc(sizeof(GType) * 2); - ty[0] = G_TYPE_STRING; - ty[1] = G_TYPE_STRING; - dialog_data.attr_model = gtk_list_store_newv(2, ty); - free(ty); - - renderer = gtk_cell_renderer_text_new(); - g_object_set(renderer, "editable", TRUE, NULL); - g_signal_connect(renderer, "edited", G_CALLBACK(attr_edited_key_cb), &dialog_data); - g_signal_connect(renderer, "editing-started", G_CALLBACK(attr_edit_started_cb), &dialog_data); - g_signal_connect(renderer, "editing-canceled", G_CALLBACK(attr_edit_canceled_cb), &dialog_data); - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(dialog_data.attr_table), -1, "key", renderer, "text", 0, NULL); - - - renderer = gtk_cell_renderer_text_new(); - g_object_set(renderer, "editable", TRUE, NULL); - g_signal_connect(renderer, "edited", G_CALLBACK(attr_edited_val_cb), &dialog_data); - g_signal_connect(renderer, "editing-started", G_CALLBACK(attr_edit_started_cb), &dialog_data); - g_signal_connect(renderer, "editing-canceled", G_CALLBACK(attr_edit_canceled_cb), &dialog_data); - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(dialog_data.attr_table), -1, "value", renderer, "text", 1, NULL); - - gtk_tree_view_set_model(GTK_TREE_VIEW(dialog_data.attr_table), GTK_TREE_MODEL(dialog_data.attr_model)); - g_signal_connect(G_OBJECT(dialog_data.attr_table), "key-release-event", G_CALLBACK(attr_key_release_cb), &dialog_data); - - } - _table_attach_(table, 6, _("Attributes:"), dialog_data.attr_table); - - - /* create delete button */ - button = gtk_button_new_with_label(_("Delete Style")); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(delete_button_cb), &dialog_data); - gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, FALSE, 0); - - sub_vbox = ghid_category_vbox(vbox, _("Set as Default"), 4, 2, TRUE, TRUE); - check_box = gtk_check_button_new_with_label(_("Save route style settings as default")); - gtk_box_pack_start(GTK_BOX(sub_vbox), check_box, TRUE, TRUE, 0); - - add_new_iter(rss); - - /* Display dialog */ - dialog_data.rss = rss; - dialog_data.select_box = select_box; - if (rss->active_style != NULL) { - path = gtk_tree_row_reference_get_path(rss->active_style->rref); - gtk_tree_model_get_iter(GTK_TREE_MODEL(rss->model), &iter, path); - g_signal_connect(G_OBJECT(select_box), "changed", G_CALLBACK(dialog_style_changed_cb), &dialog_data); - gtk_combo_box_set_active_iter(GTK_COMBO_BOX(select_box), &iter); - } - gtk_widget_show_all(dialog); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { - int changed = 0; - pcb_route_style_t *rst; - struct _route_style *style; - gboolean save; - if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(select_box), &iter)) - goto cancel; - gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, DATA_COL, &style, -1); - if (style == NULL) { - int n = vtroutestyle_len(&PCB->RouteStyle); - rst = vtroutestyle_get(&PCB->RouteStyle, n, 1); - } - else { - rst = style->rst; - *rst->name = '\0'; - } - - new_name = gtk_entry_get_text(GTK_ENTRY(dialog_data.name_entry)); - - while (isspace(*new_name)) - new_name++; - if (strcmp(rst->name, new_name) != 0) { - strncpy(rst->name, new_name, sizeof(rst->name) - 1); - rst->name[sizeof(rst->name) - 1] = '0'; - changed = 1; - } - -/* Modify the route style only if there's significant difference (beyond rouding errors) */ -#define rst_modify(changed, dst, src) \ - do { \ - pcb_coord_t __tmp__ = src; \ - if (abs(dst - __tmp__) > 10) { \ - changed = 1; \ - dst = __tmp__; \ - } \ - } while(0) - rst_modify(changed, rst->Thick, pcb_gtk_coord_entry_get_value(GHID_COORD_ENTRY(dialog_data.line_entry))); - rst_modify(changed, rst->Hole, pcb_gtk_coord_entry_get_value(GHID_COORD_ENTRY(dialog_data.via_hole_entry))); - rst_modify(changed, rst->Diameter, pcb_gtk_coord_entry_get_value(GHID_COORD_ENTRY(dialog_data.via_size_entry))); - rst_modify(changed, rst->Clearance, pcb_gtk_coord_entry_get_value(GHID_COORD_ENTRY(dialog_data.clearance_entry))); -#undef rst_modify - save = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_box)); - if (style == NULL) - style = ghid_route_style_real_add_route_style(rss, rst, 0); - else { - gtk_action_set_label(GTK_ACTION(style->action), rst->name); - gtk_list_store_set(rss->model, &iter, TEXT_COL, rst->name, -1); - } - - /* Cleanup */ - gtk_widget_destroy(dialog); - gtk_list_store_remove(rss->model, &rss->new_iter); - /* Emit change signals */ - pcb_gtk_route_style_select_style(rss, rst); - g_signal_emit(rss, ghid_route_style_signals[STYLE_EDITED_SIGNAL], 0, save); - - if (changed) { - pcb_board_set_changed_flag(pcb_true); - ghid_window_set_name_label(PCB->Name); - } - } - else { - cancel:; - gtk_widget_destroy(dialog); - gtk_list_store_remove(rss->model, &rss->new_iter); - } -} - -/* end EDIT DIALOG */ - -static void edit_button_cb(GtkButton * btn, pcb_gtk_route_style_t * rss) -{ - pcb_gtk_route_style_edit_dialog(rss); -} - -/* CONSTRUCTOR */ -static void ghid_route_style_init(pcb_gtk_route_style_t * rss) -{ -} - static void ghid_route_style_class_init(pcb_gtk_route_style_class_t * klass) { GObjectClass *object_class = (GObjectClass *) klass; @@ -564,20 +112,7 @@ object_class->finalize = ghid_route_style_finalize; } -/** Clean up object before garbage collection - */ -static void ghid_route_style_finalize(GObject * object) -{ - pcb_gtk_route_style_t *rss = (pcb_gtk_route_style_t *) object; - pcb_gtk_route_style_empty(rss); - - g_object_unref(rss->accel_group); - g_object_unref(rss->action_group); - - G_OBJECT_CLASS(pcb_gtk_route_style_parent_class)->finalize(object); -} - /* PUBLIC FUNCTIONS */ GType pcb_gtk_route_style_get_type(void) { @@ -609,7 +144,7 @@ rss->active_style = NULL; rss->action_radio_group = NULL; rss->button_radio_group = NULL; - rss->model = gtk_list_store_new(N_COLS, G_TYPE_STRING, G_TYPE_POINTER); + rss->model = gtk_list_store_new(STYLE_N_COLS, G_TYPE_STRING, G_TYPE_POINTER); rss->accel_group = gtk_accel_group_new(); rss->action_group = gtk_action_group_new("RouteStyleSelector"); @@ -622,17 +157,18 @@ return GTK_WIDGET(rss); } -/** Create a new pcb_gtk_route_style_t - * - * \param [in] rss The selector to be acted on - * \param [in] data PCB's route style object that will be edited +/** FIXME: Remove comments ? Create a new pcb_gtk_route_style_t + + \param [in] rss The selector to be acted on + \param [in] data PCB's route style object that will be edited */ -struct _route_style *ghid_route_style_real_add_route_style(pcb_gtk_route_style_t * rss, pcb_route_style_t * data, int hide) +static pcb_gtk_dlg_route_style_t *ghid_route_style_real_add_route_style(pcb_gtk_route_style_t * rss, + pcb_route_style_t * data, int hide) { GtkTreeIter iter; GtkTreePath *path; gchar *action_name = g_strdup_printf("RouteStyle%d", action_count); - struct _route_style *new_style = g_malloc(sizeof(*new_style)); + pcb_gtk_obj_route_style_t *new_style = g_malloc(sizeof(*new_style)); /* Key the route style data with the pcb_route_style_t it controls */ new_style->hidden = hide; @@ -645,7 +181,7 @@ gtk_activatable_set_related_action(GTK_ACTIVATABLE(new_style->button), GTK_ACTION(new_style->action)); gtk_list_store_append(rss->model, &iter); - gtk_list_store_set(rss->model, &iter, TEXT_COL, data->name, DATA_COL, new_style, -1); + gtk_list_store_set(rss->model, &iter, STYLE_TEXT_COL, data->name, STYLE_DATA_COL, new_style, -1); path = gtk_tree_model_get_path(GTK_TREE_MODEL(rss->model), &iter); new_style->rref = gtk_tree_row_reference_new(GTK_TREE_MODEL(rss->model), path); gtk_tree_path_free(path); @@ -678,7 +214,7 @@ if (*pcb_custom_route_style.name == '\0') { memset(&pcb_custom_route_style, 0, sizeof(pcb_custom_route_style)); strcpy(pcb_custom_route_style.name, ""); - copy_route_style(0); + pcb_gtk_route_style_copy(0); } ghid_route_style_real_add_route_style(rss, &pcb_custom_route_style, 1); rss->hidden_button = 1; @@ -696,9 +232,9 @@ return 0; do { GtkAction *action; - struct _route_style *style; + pcb_gtk_obj_route_style_t *style; - gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, DATA_COL, &style, -1); + gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, STYLE_DATA_COL, &style, -1); if (style->hidden) continue; action = GTK_ACTION(style->action); @@ -717,8 +253,9 @@ gtk_tree_model_get_iter_first(GTK_TREE_MODEL(rss->model), &iter); do { - struct _route_style *style; - gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, DATA_COL, &style, -1); + pcb_gtk_obj_route_style_t *style; + + gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, STYLE_DATA_COL, &style, -1); if ((style != NULL) && (style->rst == rst)) { g_signal_handler_block(G_OBJECT(style->action), style->sig_id); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(style->action), TRUE); @@ -738,8 +275,8 @@ return rss->accel_group; } -void pcb_gtk_route_style_sync(pcb_gtk_route_style_t * rss, pcb_coord_t Thick, pcb_coord_t Hole, pcb_coord_t Diameter, - pcb_coord_t Clearance) +void pcb_gtk_route_style_sync(pcb_gtk_route_style_t * rss, + pcb_coord_t Thick, pcb_coord_t Hole, pcb_coord_t Diameter, pcb_coord_t Clearance) { GtkTreeIter iter; int target, n; @@ -752,13 +289,13 @@ target = pcb_route_style_lookup(&PCB->RouteStyle, Thick, Diameter, Hole, Clearance, NULL); if (target == -1) { - struct _route_style *style; + pcb_gtk_obj_route_style_t *style; /* None of the styles matched: select the hidden custom button */ if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(rss->model), &iter)) return; - gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, DATA_COL, &style, -1); + gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, STYLE_DATA_COL, &style, -1); g_signal_handler_block(G_OBJECT(style->action), style->sig_id); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(style->action), TRUE); g_signal_handler_unblock(G_OBJECT(style->action), style->sig_id); @@ -770,8 +307,8 @@ /* need to select the style with index stored in target */ n = -1; do { - struct _route_style *style; - gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, DATA_COL, &style, -1); + pcb_gtk_obj_route_style_t *style; + gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, STYLE_DATA_COL, &style, -1); if (n == target) { g_signal_handler_block(G_OBJECT(style->action), style->sig_id); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(style->action), TRUE); @@ -788,8 +325,8 @@ GtkTreeIter iter; if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(rss->model), &iter)) { do { - struct _route_style *rsdata; - gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, DATA_COL, &rsdata, -1); + pcb_gtk_obj_route_style_t *rsdata; + gtk_tree_model_get(GTK_TREE_MODEL(rss->model), &iter, STYLE_DATA_COL, &rsdata, -1); if (rsdata != NULL) { if (rsdata->action) { gtk_action_disconnect_accelerator(GTK_ACTION(rsdata->action)); Index: trunk/src_plugins/lib_gtk_common/wt_route_style.h =================================================================== --- trunk/src_plugins/lib_gtk_common/wt_route_style.h (revision 6712) +++ trunk/src_plugins/lib_gtk_common/wt_route_style.h (revision 6713) @@ -8,15 +8,74 @@ G_BEGIN_DECLS /* keep c++ happy */ #define GHID_ROUTE_STYLE_TYPE (pcb_gtk_route_style_get_type ()) -#define GHID_ROUTE_STYLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GHID_ROUTE_STYLE_TYPE, pcb_gtk_route_style_t)) -#define GHID_ROUTE_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GHID_ROUTE_STYLE_TYPE, pcb_gtk_route_style_class_t)) -#define IS_GHID_ROUTE_STYLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GHID_ROUTE_STYLE_TYPE)) -#define IS_GHID_ROUTE_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GHID_ROUTE_STYLE_TYPE)) -//typedef struct _GHidRouteStyleSelector GHidRouteStyleSelector; -//typedef struct _GHidRouteStyleSelectorClass GHidRouteStyleSelectorClass; +#define GHID_ROUTE_STYLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GHID_ROUTE_STYLE_TYPE, pcb_gtk_route_style_t)) +#define GHID_ROUTE_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GHID_ROUTE_STYLE_TYPE, pcb_gtk_route_style_class_t)) +#define IS_GHID_ROUTE_STYLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GHID_ROUTE_STYLE_TYPE)) +#define IS_GHID_ROUTE_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GHID_ROUTE_STYLE_TYPE)) +/** The widget Object */ + struct pcb_gtk_route_style_s { + GtkVBox parent; + + GSList *button_radio_group; + GSList *action_radio_group; + GtkWidget *edit_button; + + GtkActionGroup *action_group; + GtkAccelGroup *accel_group; + + int hidden_button; /* whether the hidden button is created */ + int selected; /* index of the currently selected route style */ + + GtkListStore *model; /* All the route styles */ + struct pcb_gtk_obj_route_style_s *active_style; /* The current route style */ + + GtkTreeIter new_iter; /* iter for the item */ +}; + typedef struct pcb_gtk_route_style_s pcb_gtk_route_style_t; + +/** The widget Class */ +struct pcb_gtk_route_style_class_s { + GtkVBoxClass parent_class; + + void (*select_style) (pcb_gtk_route_style_t *, pcb_route_style_t *); + void (*style_edited) (pcb_gtk_route_style_t *, gboolean); +}; + typedef struct pcb_gtk_route_style_class_s pcb_gtk_route_style_class_t; +/** Signals exposed by the widget */ +enum { + SELECT_STYLE_SIGNAL, + STYLE_EDITED_SIGNAL, + STYLE_LAST_SIGNAL +}; + +/** Columns used for internal data store */ +enum { + STYLE_TEXT_COL, + STYLE_DATA_COL, + STYLE_N_COLS +}; + +/** Structure for a single Route Style object */ +struct pcb_gtk_obj_route_style_s { + GtkRadioAction *action; + GtkWidget *button; + GtkWidget *menu_item; + GtkTreeRowReference *rref; + pcb_route_style_t *rst; + gulong sig_id; + int hidden; +}; +typedef struct pcb_gtk_obj_route_style_s pcb_gtk_obj_route_style_t; + +/** Structure for "Edit Route Style" Dialog */ +typedef struct pcb_gtk_dlg_route_style_s pcb_gtk_dlg_route_style_t; + +/* API */ + +/** GObject type for this widget */ GType pcb_gtk_route_style_get_type(void); /** Creates and returns a new freshly-allocated pcb_gtk_route_style_t object */ @@ -53,9 +112,6 @@ */ gboolean pcb_gtk_route_style_select_style(pcb_gtk_route_style_t * rss, pcb_route_style_t * rst); -/** Builds and runs the "edit route styles" dialog */ -void pcb_gtk_route_style_edit_dialog(pcb_gtk_route_style_t * rss); - /** Returns the GtkAccelGroup of a route style selector \param [in] rss The selector to be acted on @@ -79,6 +135,9 @@ void pcb_gtk_route_style_sync(pcb_gtk_route_style_t * rss, pcb_coord_t Thick, pcb_coord_t Hole, pcb_coord_t Diameter, pcb_coord_t Clearance); +void pcb_gtk_route_style_copy(int idx); + + /** Removes all styles from a route style selector */ void pcb_gtk_route_style_empty(pcb_gtk_route_style_t * rss);