1 /*! \file <gtk-pcb-route-style-selector.c>
2 * \brief Implementation of GHidRouteStyleSelector widget
3 * \par Description
4 * Please write description here.
5 */
6
7 #include <glib.h>
8 #include <glib-object.h>
9 #include <gdk/gdkkeysyms.h>
10 #include <gtk/gtk.h>
11
12 #include "global.h"
13 #include "gtkhid.h"
14 #include "gui.h"
15 #include "pcb-printf.h"
16
17 #include "ghid-route-style-selector.h"
18
19 /* Forward dec'ls */
20 struct _route_style;
21 struct _route_style *ghid_route_style_selector_real_add_route_style
22 (GHidRouteStyleSelector *, RouteStyleType *, gboolean temp);
23 static void ghid_route_style_selector_finalize (GObject *object);
24
25 /*! \brief Global action creation counter */
26 static gint action_count;
27
28 /*! \brief Signals exposed by the widget */
29 enum {
30 SELECT_STYLE_SIGNAL,
31 STYLE_EDITED_SIGNAL,
32 LAST_SIGNAL
33 };
34
35 /*! \brief Columns used for internal data store */
36 enum {
37 TEXT_COL,
38 DATA_COL,
39 N_COLS
40 };
41
42 static GtkVBox *ghid_route_style_selector_parent_class;
43 static guint ghid_route_style_selector_signals[LAST_SIGNAL] = { 0 };
44
45 struct _GHidRouteStyleSelector
46 {
47 GtkVBox parent;
48
49 GSList *button_radio_group;
50 GSList *action_radio_group;
51 GtkWidget *edit_button;
52
53 GtkActionGroup *action_group;
54 GtkAccelGroup *accel_group;
55 GtkRadioAction *null_action;
56 GtkWidget *null_button;
57 gint shortcut_key_idx;
58
59 GtkListStore *model;
60 struct _route_style *active_style;
61 };
62
63 struct _GHidRouteStyleSelectorClass
64 {
65 GtkVBoxClass parent_class;
66
67 void (* select_style) (GHidRouteStyleSelector *, RouteStyleType *);
68 void (* style_edited) (GHidRouteStyleSelector *, gboolean);
69 };
70
71 struct _route_style
72 {
73 gboolean temporary;
74 GtkRadioAction *action;
75 GtkWidget *button;
76 GtkWidget *menu_item;
77 GtkTreeRowReference *rref;
78 RouteStyleType *rst;
79 gulong sig_id;
80 };
81
82 static void
init_radio_groups(GHidRouteStyleSelector * rss)83 init_radio_groups (GHidRouteStyleSelector *rss)
84 {
85 gtk_radio_action_set_group (rss->null_action, rss->action_radio_group);
86 rss->action_radio_group = gtk_radio_action_get_group (rss->null_action);
87 gtk_radio_button_set_group (GTK_RADIO_BUTTON (rss->null_button),
88 rss->button_radio_group);
89 rss->button_radio_group = gtk_radio_button_get_group
90 (GTK_RADIO_BUTTON (rss->null_button));
91 }
92
93 /* SIGNAL HANDLERS */
94 /*! \brief Callback for user selection of a route style */
95 static void
radio_select_cb(GtkToggleAction * action,GHidRouteStyleSelector * rss)96 radio_select_cb (GtkToggleAction *action, GHidRouteStyleSelector *rss)
97 {
98 rss->active_style = g_object_get_data (G_OBJECT (action), "route-style");
99 if (gtk_toggle_action_get_active (action))
100 g_signal_emit (rss, ghid_route_style_selector_signals[SELECT_STYLE_SIGNAL],
101 0, rss->active_style->rst);
102 }
103
104 /* EDIT DIALOG */
105 struct _dialog
106 {
107 GHidRouteStyleSelector *rss;
108 GtkWidget *name_entry;
109 GtkWidget *line_entry;
110 GtkWidget *via_hole_entry;
111 GtkWidget *via_size_entry;
112 GtkWidget *clearance_entry;
113 GtkWidget *mask_aperture_entry;
114 };
115
116 /*! \brief Callback for dialog box's combobox being changed
117 * \par Function Description
118 * When a different layer is selected, this function loads
119 * that layer's data into the dialog. Alternately, if the
120 * "New layer" option is selected, this loads a new name
121 * but no other data.
122 *
123 * \param [in] combo The combobox
124 * \param [in] dialog The rest of the widgets to be updated
125 */
126 static void
dialog_style_changed_cb(GtkComboBox * combo,struct _dialog * dialog)127 dialog_style_changed_cb (GtkComboBox *combo, struct _dialog *dialog)
128 {
129 struct _route_style *style;
130 GtkTreeIter iter;
131 gtk_combo_box_get_active_iter (combo, &iter);
132 gtk_tree_model_get (GTK_TREE_MODEL (dialog->rss->model),
133 &iter, DATA_COL, &style, -1);
134
135 if (style == NULL)
136 {
137 gtk_entry_set_text (GTK_ENTRY (dialog->name_entry),
138 _("New Style"));
139 return;
140 }
141
142 gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), style->rst->Name);
143 ghid_coord_entry_set_value (GHID_COORD_ENTRY (dialog->line_entry),
144 style->rst->Thick);
145 ghid_coord_entry_set_value (GHID_COORD_ENTRY (dialog->via_hole_entry),
146 style->rst->Hole);
147 ghid_coord_entry_set_value (GHID_COORD_ENTRY (dialog->via_size_entry),
148 style->rst->Diameter);
149 ghid_coord_entry_set_value (GHID_COORD_ENTRY (dialog->clearance_entry),
150 style->rst->Keepaway);
151 ghid_coord_entry_set_value (GHID_COORD_ENTRY (dialog->mask_aperture_entry),
152 style->rst->ViaMask);
153
154 }
155
156 /* \brief Helper for edit_button_cb */
157 static void
_table_attach(GtkWidget * table,gint row,const gchar * label,GtkWidget ** entry,Coord min,Coord max)158 _table_attach (GtkWidget *table, gint row, const gchar *label,
159 GtkWidget **entry, Coord min, Coord max)
160 {
161 GtkWidget *label_w = gtk_label_new (label);
162 gtk_misc_set_alignment (GTK_MISC (label_w), 1.0, 0.5);
163
164 *entry = ghid_coord_entry_new (min, max, 0, Settings.grid_unit, CE_SMALL);
165 gtk_table_attach (GTK_TABLE (table), label_w, 0, 1, row, row + 1,
166 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
167 gtk_table_attach (GTK_TABLE (table), *entry, 1, 2, row, row + 1,
168 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
169 }
170
171 /* \brief Builds and runs the "edit route styles" dialog */
172 void
ghid_route_style_selector_edit_dialog(GHidRouteStyleSelector * rss)173 ghid_route_style_selector_edit_dialog (GHidRouteStyleSelector *rss)
174 {
175 GtkTreePath *path;
176 GtkTreeIter iter, tmp_iter;
177 struct _dialog dialog_data;
178 GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
179 GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (rss));
180 GtkWidget *dialog;
181 GtkWidget *content_area;
182 GtkWidget *vbox, *hbox, *sub_vbox, *table;
183 GtkWidget *label, *select_box, *check_box;
184
185 /* Build dialog */
186 dialog = gtk_dialog_new_with_buttons (_("Edit Route Styles"),
187 GTK_WINDOW (window),
188 GTK_DIALOG_DESTROY_WITH_PARENT,
189 GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
190 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
191
192 label = gtk_label_new (_("Edit Style:"));
193 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
194
195 select_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (rss->model));
196 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (select_box), renderer, TRUE);
197 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(select_box), renderer,
198 "text", TEXT_COL, NULL);
199
200 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
201
202 hbox = gtk_hbox_new (FALSE, 4);
203 gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 4);
204 vbox = gtk_vbox_new (FALSE, 4);
205 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 4);
206
207 hbox = gtk_hbox_new (FALSE, 4);
208 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
209 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
210 gtk_box_pack_start (GTK_BOX (hbox), select_box, TRUE, TRUE, 0);
211
212 sub_vbox = ghid_category_vbox (vbox, _("Route Style Data"),
213 4, 2, TRUE, TRUE);
214 table = gtk_table_new (6, 2, FALSE);
215 gtk_box_pack_start (GTK_BOX (sub_vbox), table, TRUE, TRUE, 4);
216 label = gtk_label_new (_("Name:"));
217 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
218 dialog_data.name_entry = gtk_entry_new ();
219 gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
220 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
221 gtk_table_attach (GTK_TABLE (table), dialog_data.name_entry, 1, 2, 0, 1,
222 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
223
224 _table_attach (table, 1, _("Line width:"),
225 &dialog_data.line_entry,
226 MIN_LINESIZE, MAX_LINESIZE);
227 _table_attach (table, 2, _("Via hole size:"),
228 &dialog_data.via_hole_entry,
229 MIN_PINORVIAHOLE, MAX_PINORVIASIZE);
230 _table_attach (table, 3, _("Via ring size:"),
231 &dialog_data.via_size_entry,
232 MIN_PINORVIAHOLE, MAX_PINORVIASIZE);
233 _table_attach (table, 4, _("Clearance:"),
234 &dialog_data.clearance_entry,
235 MIN_LINESIZE, MAX_LINESIZE);
236 _table_attach (table, 5, _("Mask aperture:"),
237 &dialog_data.mask_aperture_entry,
238 0, MAX_LINESIZE);
239
240 sub_vbox = ghid_category_vbox (vbox, _("Set as Default"),
241 4, 2, TRUE, TRUE);
242 check_box = gtk_check_button_new_with_label
243 (_("Save route style settings as default"));
244 gtk_box_pack_start (GTK_BOX (sub_vbox), check_box, TRUE, TRUE, 0);
245
246 /* Add "new style" option to list */
247 gtk_list_store_append (rss->model, &tmp_iter);
248 gtk_list_store_set (rss->model, &tmp_iter, TEXT_COL,
249 _("New (this session only)"), DATA_COL, NULL, -1);
250
251 /* Display dialog */
252 dialog_data.rss = rss;
253 path = gtk_tree_row_reference_get_path (rss->active_style->rref);
254 gtk_tree_model_get_iter (GTK_TREE_MODEL (rss->model), &iter, path);
255 g_signal_connect (G_OBJECT (select_box), "changed",
256 G_CALLBACK (dialog_style_changed_cb), &dialog_data);
257 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (select_box), &iter);
258 gtk_widget_show_all (dialog);
259 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
260 {
261 RouteStyleType *rst;
262 struct _route_style *style;
263 gboolean save;
264 gtk_combo_box_get_active_iter (GTK_COMBO_BOX (select_box), &iter);
265 gtk_tree_model_get (GTK_TREE_MODEL (rss->model),
266 &iter, DATA_COL, &style, -1);
267 if (style == NULL)
268 rst = g_malloc (sizeof *rst);
269 else
270 {
271 rst = style->rst;
272 free (rst->Name);
273 }
274
275 rst->Name = StripWhiteSpaceAndDup
276 (gtk_entry_get_text (GTK_ENTRY (dialog_data.name_entry)));
277 rst->Thick = ghid_coord_entry_get_value
278 (GHID_COORD_ENTRY (dialog_data.line_entry));
279 rst->Hole = ghid_coord_entry_get_value
280 (GHID_COORD_ENTRY (dialog_data.via_hole_entry));
281 rst->Diameter = ghid_coord_entry_get_value
282 (GHID_COORD_ENTRY (dialog_data.via_size_entry));
283 rst->Keepaway = ghid_coord_entry_get_value
284 (GHID_COORD_ENTRY (dialog_data.clearance_entry));
285 rst->ViaMask = ghid_coord_entry_get_value
286 (GHID_COORD_ENTRY (dialog_data.mask_aperture_entry));
287 save = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_box));
288
289 if (style == NULL)
290 style = ghid_route_style_selector_real_add_route_style
291 (rss, rst, TRUE);
292 else
293 {
294 gtk_action_set_label (GTK_ACTION (style->action), rst->Name);
295 gtk_list_store_set (rss->model, &iter, TEXT_COL, rst->Name, -1);
296 }
297
298 /* Cleanup */
299 gtk_widget_destroy (dialog);
300 gtk_list_store_remove (rss->model, &tmp_iter);
301 /* Emit change signals */
302 ghid_route_style_selector_select_style (rss, rst);
303 g_signal_emit
304 (rss, ghid_route_style_selector_signals[STYLE_EDITED_SIGNAL],
305 0, save);
306 }
307 else
308 {
309 gtk_widget_destroy (dialog);
310 gtk_list_store_remove (rss->model, &tmp_iter);
311 }
312 }
313 /* end EDIT DIALOG */
314
315 static void
edit_button_cb(GtkButton * btn,GHidRouteStyleSelector * rss)316 edit_button_cb (GtkButton *btn, GHidRouteStyleSelector *rss)
317 {
318 ghid_route_style_selector_edit_dialog (rss);
319 }
320
321 /* CONSTRUCTOR */
322 static void
ghid_route_style_selector_init(GHidRouteStyleSelector * rss)323 ghid_route_style_selector_init (GHidRouteStyleSelector *rss)
324 {
325 }
326
327 static void
ghid_route_style_selector_class_init(GHidRouteStyleSelectorClass * klass)328 ghid_route_style_selector_class_init (GHidRouteStyleSelectorClass *klass)
329 {
330 GObjectClass *object_class = (GObjectClass *) klass;
331
332 ghid_route_style_selector_parent_class = g_type_class_peek_parent (klass);
333
334 ghid_route_style_selector_signals[SELECT_STYLE_SIGNAL] =
335 g_signal_new ("select-style",
336 G_TYPE_FROM_CLASS (klass),
337 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
338 G_STRUCT_OFFSET (GHidRouteStyleSelectorClass, select_style),
339 NULL, NULL,
340 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE,
341 1, G_TYPE_POINTER);
342 ghid_route_style_selector_signals[STYLE_EDITED_SIGNAL] =
343 g_signal_new ("style-edited",
344 G_TYPE_FROM_CLASS (klass),
345 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
346 G_STRUCT_OFFSET (GHidRouteStyleSelectorClass, style_edited),
347 NULL, NULL,
348 g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE,
349 1, G_TYPE_BOOLEAN);
350
351 object_class->finalize = ghid_route_style_selector_finalize;
352 }
353
354 /*! \brief Clean up object before garbage collection
355 */
356 static void
ghid_route_style_selector_finalize(GObject * object)357 ghid_route_style_selector_finalize (GObject *object)
358 {
359 GHidRouteStyleSelector *rss = (GHidRouteStyleSelector *) object;
360
361 ghid_route_style_selector_empty (rss);
362
363 g_object_unref (rss->accel_group);
364 g_object_unref (rss->action_group);
365
366 G_OBJECT_CLASS (ghid_route_style_selector_parent_class)->finalize (object);
367 }
368
369 /* PUBLIC FUNCTIONS */
370 GType
ghid_route_style_selector_get_type(void)371 ghid_route_style_selector_get_type (void)
372 {
373 static GType rss_type = 0;
374
375 if (!rss_type)
376 {
377 const GTypeInfo rss_info =
378 {
379 sizeof (GHidRouteStyleSelectorClass),
380 NULL, /* base_init */
381 NULL, /* base_finalize */
382 (GClassInitFunc) ghid_route_style_selector_class_init,
383 NULL, /* class_finalize */
384 NULL, /* class_data */
385 sizeof (GHidRouteStyleSelector),
386 0, /* n_preallocs */
387 (GInstanceInitFunc) ghid_route_style_selector_init,
388 };
389
390 rss_type = g_type_register_static (GTK_TYPE_VBOX,
391 "GHidRouteStyleSelector",
392 &rss_info,
393 0);
394 }
395
396 return rss_type;
397 }
398
399 /*! \brief Create a new GHidRouteStyleSelector
400 *
401 * \return a freshly-allocated GHidRouteStyleSelector.
402 */
403 GtkWidget *
ghid_route_style_selector_new()404 ghid_route_style_selector_new ()
405 {
406 GHidRouteStyleSelector *rss =
407 g_object_new (GHID_ROUTE_STYLE_SELECTOR_TYPE, NULL);
408
409 rss->active_style = NULL;
410 rss->action_radio_group = NULL;
411 rss->button_radio_group = NULL;
412 rss->model = gtk_list_store_new (N_COLS, G_TYPE_STRING, G_TYPE_POINTER);
413
414 rss->accel_group = gtk_accel_group_new ();
415 rss->action_group = gtk_action_group_new ("RouteStyleSelector");
416 rss->null_action = gtk_radio_action_new ("RouteStyleXX", "",
417 NULL, NULL, -1);
418 rss->null_button = gtk_radio_button_new (rss->button_radio_group);
419 init_radio_groups (rss);
420 gtk_activatable_set_related_action (GTK_ACTIVATABLE (rss->null_button),
421 GTK_ACTION (rss->null_action));
422 rss->shortcut_key_idx = 1;
423
424 /* Create edit button */
425 rss->edit_button = gtk_button_new_with_label (_("Route Styles"));
426 g_signal_connect (G_OBJECT (rss->edit_button), "clicked",
427 G_CALLBACK (edit_button_cb), rss);
428 gtk_box_pack_start (GTK_BOX (rss), rss->edit_button, FALSE, FALSE, 0);
429
430 return GTK_WIDGET (rss);
431 }
432
433 /*! \brief Create a new GHidRouteStyleSelector
434 *
435 * \param [in] rss The selector to be acted on
436 * \param [in] data PCB's route style object that will be edited
437 * \param [in] temp Whether the style is "real" or session-only
438 */
439 struct _route_style *
ghid_route_style_selector_real_add_route_style(GHidRouteStyleSelector * rss,RouteStyleType * data,gboolean temp)440 ghid_route_style_selector_real_add_route_style (GHidRouteStyleSelector *rss,
441 RouteStyleType *data,
442 gboolean temp)
443 {
444 GtkTreeIter iter;
445 GtkTreePath *path;
446 gchar *action_name = g_strdup_printf ("RouteStyle%d", action_count);
447 struct _route_style *new_style = g_malloc (sizeof (*new_style));
448
449 /* Key the route style data with the RouteStyleType it controls */
450 new_style->rst = data;
451 new_style->temporary = temp;
452 new_style->action = gtk_radio_action_new (action_name, data->Name,
453 NULL, NULL, action_count);
454 gtk_radio_action_set_group (new_style->action, rss->action_radio_group);
455 rss->action_radio_group = gtk_radio_action_get_group (new_style->action);
456 new_style->button = gtk_radio_button_new (rss->button_radio_group);
457 rss->button_radio_group = gtk_radio_button_get_group
458 (GTK_RADIO_BUTTON (new_style->button));
459 gtk_activatable_set_related_action (GTK_ACTIVATABLE (new_style->button),
460 GTK_ACTION (new_style->action));
461
462 gtk_list_store_append (rss->model, &iter);
463 gtk_list_store_set (rss->model, &iter, TEXT_COL, data->Name,
464 DATA_COL, new_style, -1);
465 path = gtk_tree_model_get_path (GTK_TREE_MODEL (rss->model), &iter);
466 new_style->rref = gtk_tree_row_reference_new (GTK_TREE_MODEL (rss->model),
467 path);
468 gtk_tree_path_free (path);
469
470 /* Setup accelerator */
471 if (rss->shortcut_key_idx < 12)
472 {
473 gchar *accel = g_strdup_printf ("<Ctrl>F%d", rss->shortcut_key_idx);
474 gtk_action_set_accel_group (GTK_ACTION (new_style->action),
475 rss->accel_group);
476 gtk_action_group_add_action_with_accel (rss->action_group,
477 GTK_ACTION (new_style->action),
478 accel);
479 g_free (accel);
480 ++rss->shortcut_key_idx;
481 }
482
483 /* Hookup and install radio button */
484 g_object_set_data (G_OBJECT (new_style->action), "route-style", new_style);
485 new_style->sig_id = g_signal_connect (G_OBJECT (new_style->action),
486 "activate",
487 G_CALLBACK (radio_select_cb), rss);
488 gtk_box_pack_start (GTK_BOX (rss), new_style->button, FALSE, FALSE, 0);
489
490 g_free (action_name);
491 ++action_count;
492 return new_style;
493 }
494
495 /*! \brief Adds a route style to a GHidRouteStyleSelector
496 * \par Function Description
497 * Adds a new route style to be managed by this selector. Note
498 * that the route style object passed to this function will be
499 * updated directly.
500 *
501 * \param [in] rss The selector to be acted on
502 * \param [in] data PCB's route style object describing the style
503 */
504 void
ghid_route_style_selector_add_route_style(GHidRouteStyleSelector * rss,RouteStyleType * data)505 ghid_route_style_selector_add_route_style (GHidRouteStyleSelector *rss,
506 RouteStyleType *data)
507 {
508 ghid_route_style_selector_real_add_route_style (rss, data, FALSE);
509 }
510
511
512 /*! \brief Install the "Route Style" menu items
513 * \par Function Description
514 * Takes a menu shell and installs menu items for route style selection in
515 * the shell, at the given position. Note that we aren't really guaranteed
516 * the ordering of these items, since our internal data structure is a hash
517 * table. This shouldn't be a problem.
518 *
519 * \param [in] rss The selector to be acted on
520 * \param [in] shell The menu to install the items in
521 * \param [in] pos The position in the menu to install items
522 *
523 * \return the number of items installed
524 */
525 gint
ghid_route_style_selector_install_items(GHidRouteStyleSelector * rss,GtkMenuShell * shell,gint pos)526 ghid_route_style_selector_install_items (GHidRouteStyleSelector *rss,
527 GtkMenuShell *shell, gint pos)
528 {
529 gint n = 0;
530 GtkTreeIter iter;
531
532 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (rss->model), &iter);
533 do
534 {
535 GtkAction *action;
536 struct _route_style *style;
537
538 gtk_tree_model_get (GTK_TREE_MODEL (rss->model),
539 &iter, DATA_COL, &style, -1);
540 action = GTK_ACTION (style->action);
541 style->menu_item = gtk_action_create_menu_item (action);
542 gtk_menu_shell_insert (shell, style->menu_item, pos + n);
543 ++n;
544 }
545 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (rss->model), &iter));
546
547 return n;
548 }
549
550 /*! \brief Selects a route style and emits a select-style signal
551 *
552 * \param [in] rss The selector to be acted on
553 * \param [in] rst The style to select
554 *
555 * \return TRUE if a style was selected, FALSE otherwise
556 */
557 gboolean
ghid_route_style_selector_select_style(GHidRouteStyleSelector * rss,RouteStyleType * rst)558 ghid_route_style_selector_select_style (GHidRouteStyleSelector *rss,
559 RouteStyleType *rst)
560 {
561 GtkTreeIter iter;
562 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (rss->model), &iter);
563 do
564 {
565 struct _route_style *style;
566 gtk_tree_model_get (GTK_TREE_MODEL (rss->model),
567 &iter, DATA_COL, &style, -1);
568 if (style->rst == rst)
569 {
570 g_signal_handler_block (G_OBJECT (style->action), style->sig_id);
571 gtk_toggle_action_set_active
572 (GTK_TOGGLE_ACTION (style->action), TRUE);
573 g_signal_handler_unblock (G_OBJECT (style->action), style->sig_id);
574 rss->active_style = style;
575 g_signal_emit
576 (rss, ghid_route_style_selector_signals[SELECT_STYLE_SIGNAL],
577 0, rss->active_style->rst);
578 return TRUE;
579 }
580 }
581 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (rss->model), &iter));
582
583 return FALSE;
584 }
585
586 /*! \brief Returns the GtkAccelGroup of a route style selector
587 * \par Function Description
588 *
589 * \param [in] rss The selector to be acted on
590 *
591 * \return the accel group of the selector
592 */
593 GtkAccelGroup *
ghid_route_style_selector_get_accel_group(GHidRouteStyleSelector * rss)594 ghid_route_style_selector_get_accel_group (GHidRouteStyleSelector *rss)
595 {
596 return rss->accel_group;
597 }
598
599 /*! \brief Sets a GHidRouteStyleSelector selection to given values
600 * \par Function Description
601 * Given the line thickness, via size and clearance values of a route
602 * style, this function selects a route style with the given values.
603 * If there is no such style registered with the selector, nothing
604 * will happen. This function does not emit any signals.
605 *
606 * \param [in] rss The selector to be acted on
607 * \param [in] Thick Coord to match selection to
608 * \param [in] Hole Coord to match selection to
609 * \param [in] Diameter Coord to match selection to
610 * \param [in] Keepaway Coord to match selection to
611 * \param [in] ViaMask Coord to match selection to
612 */
613 void
ghid_route_style_selector_sync(GHidRouteStyleSelector * rss,Coord Thick,Coord Hole,Coord Diameter,Coord Keepaway,Coord ViaMask)614 ghid_route_style_selector_sync (GHidRouteStyleSelector *rss,
615 Coord Thick, Coord Hole,
616 Coord Diameter, Coord Keepaway, Coord ViaMask)
617 {
618 gboolean found_match = FALSE;
619 GtkTreeIter iter;
620 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (rss->model), &iter);
621 do
622 {
623 struct _route_style *style;
624 gtk_tree_model_get (GTK_TREE_MODEL (rss->model),
625 &iter, DATA_COL, &style, -1);
626 if (style->rst->Thick == Thick &&
627 style->rst->Hole == Hole &&
628 style->rst->Diameter == Diameter &&
629 style->rst->Keepaway == Keepaway &&
630 style->rst->ViaMask == ViaMask)
631 {
632 g_signal_handler_block (G_OBJECT (style->action), style->sig_id);
633 gtk_toggle_action_set_active
634 (GTK_TOGGLE_ACTION (style->action), TRUE);
635 g_signal_handler_unblock (G_OBJECT (style->action), style->sig_id);
636 rss->active_style = style;
637 found_match = TRUE;
638 }
639 }
640 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (rss->model), &iter));
641
642 if (!found_match)
643 gtk_radio_action_set_current_value (rss->null_action, -1);
644 }
645
646 /*! \brief Removes all styles from a route style selector */
647 void
ghid_route_style_selector_empty(GHidRouteStyleSelector * rss)648 ghid_route_style_selector_empty (GHidRouteStyleSelector *rss)
649 {
650 GtkTreeIter iter;
651 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (rss->model), &iter);
652 do
653 {
654 struct _route_style *rsdata;
655 gtk_tree_model_get (GTK_TREE_MODEL (rss->model),
656 &iter, DATA_COL, &rsdata, -1);
657 if (rsdata->action)
658 {
659 gtk_action_group_remove_action (rss->action_group,
660 GTK_ACTION (rsdata->action));
661 g_object_unref (G_OBJECT (rsdata->action));
662 }
663 if (rsdata->button)
664 gtk_widget_destroy (GTK_WIDGET (rsdata->button));
665 if (rsdata->menu_item)
666 gtk_widget_destroy (GTK_WIDGET (rsdata->menu_item));
667 if (rsdata->temporary)
668 {
669 free (rsdata->rst->Name);
670 g_free (rsdata->rst);
671 }
672 gtk_tree_row_reference_free (rsdata->rref);
673 free (rsdata);
674 }
675 while (gtk_list_store_remove (rss->model, &iter));
676 rss->action_radio_group = NULL;
677 rss->button_radio_group = NULL;
678 rss->shortcut_key_idx = 1;
679 init_radio_groups (rss);
680 }
681
682