1 /* Lepton EDA Schematic Capture
2 * Copyright (C) 1998-2010 Ales Hvezda
3 * Copyright (C) 1998-2014 gEDA Contributors
4 * Copyright (C) 2017-2021 Lepton EDA Contributors
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 /*!
21 * \file gschem_bottom_widget.c
22 *
23 * \brief A widget for the "status bar" at the bottom of the window
24 */
25
26 #include <config.h>
27
28 #include <stdio.h>
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #endif
35 #ifdef HAVE_MATH_H
36 #include <math.h>
37 #endif
38
39 #include "gschem.h"
40
41
42 /* The padding used around labels in the "status bar"
43 */
44
45 #define LABEL_XPAD 10
46 #define LABEL_YPAD 5
47
48
49
50 enum
51 {
52 PROP_0,
53 PROP_GRID_MODE,
54 PROP_GRID_SIZE,
55 PROP_LEFT_BUTTON_TEXT,
56 PROP_MIDDLE_BUTTON_TEXT,
57 PROP_RIGHT_BUTTON_TEXT,
58 PROP_SNAP_MODE,
59 PROP_SNAP_SIZE,
60 PROP_STATUS_TEXT,
61 PROP_STATUS_TEXT_COLOR,
62 PROP_RUBBER_BAND_MODE,
63 PROP_MAGNETIC_NET_MODE,
64 PROP_TOPLEVEL
65 };
66
67
68
69 static void
70 dispose (GObject *object);
71
72 static void
73 finalize (GObject *object);
74
75 static void
76 get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec);
77
78 static void
79 gschem_bottom_widget_class_init (GschemBottomWidgetClass *klass);
80
81 static void
82 gschem_bottom_widget_init (GschemBottomWidget *view);
83
84 static void
85 set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec);
86
87 static void
88 update_grid_label (GschemBottomWidget *widget, GParamSpec *pspec, gpointer unused);
89
90 static void
91 update_rubber_band_label (GschemBottomWidget *widget, GParamSpec *pspec, gpointer unused);
92
93 static void
94 update_magnetic_net_label (GschemBottomWidget *widget, GParamSpec *pspec, gpointer unused);
95
96
97
98 /* convenience macro - gobject type implementation:
99 */
100 #ifdef ENABLE_GTK3
101 G_DEFINE_TYPE (GschemBottomWidget, gschem_bottom_widget, GTK_TYPE_BOX);
102 #else
103 G_DEFINE_TYPE (GschemBottomWidget, gschem_bottom_widget, GTK_TYPE_HBOX);
104 #endif
105
106
107 static gboolean
on_click_rubber_band(GtkWidget * ebox,GdkEvent * e,gpointer data)108 on_click_rubber_band (GtkWidget* ebox, GdkEvent* e, gpointer data)
109 {
110 GschemBottomWidget* widget = (GschemBottomWidget*) data;
111 g_return_val_if_fail (widget != NULL, FALSE);
112
113 GdkEventButton* ebtn = (GdkEventButton*) e;
114 if (ebtn->type == GDK_BUTTON_PRESS && ebtn->button == 1)
115 {
116 gschem_options_cycle_net_rubber_band_mode (widget->toplevel->options);
117 return TRUE;
118 }
119
120 return FALSE;
121 }
122
123
124
125 static gboolean
on_click_magnetic_net(GtkWidget * ebox,GdkEvent * e,gpointer data)126 on_click_magnetic_net (GtkWidget* ebox, GdkEvent* e, gpointer data)
127 {
128 GschemBottomWidget* widget = (GschemBottomWidget*) data;
129 g_return_val_if_fail (widget != NULL, FALSE);
130
131 GdkEventButton* ebtn = (GdkEventButton*) e;
132 if (ebtn->type == GDK_BUTTON_PRESS && ebtn->button == 1)
133 {
134 gschem_options_cycle_magnetic_net_mode (widget->toplevel->options);
135 return TRUE;
136 }
137
138 return FALSE;
139 }
140
141
142
143 static gboolean
on_click_grid_size(GtkWidget * ebox,GdkEvent * e,gpointer data)144 on_click_grid_size (GtkWidget* ebox, GdkEvent* e, gpointer data)
145 {
146 GschemBottomWidget* widget = (GschemBottomWidget*) data;
147 g_return_val_if_fail (widget != NULL, FALSE);
148
149 GdkEventButton* ebtn = (GdkEventButton*) e;
150 if (ebtn->type == GDK_BUTTON_PRESS && ebtn->button == 1)
151 {
152 gschem_options_cycle_grid_mode (widget->toplevel->options);
153 return TRUE;
154 }
155
156 return FALSE;
157 }
158
159
160
161 static gboolean
on_click_snap_info(GtkWidget * ebox,GdkEvent * e,gpointer data)162 on_click_snap_info (GtkWidget* ebox, GdkEvent* e, gpointer data)
163 {
164 GschemBottomWidget* widget = (GschemBottomWidget*) data;
165 g_return_val_if_fail (widget != NULL, FALSE);
166
167 GdkEventButton* ebtn = (GdkEventButton*) e;
168 if (ebtn->type == GDK_BUTTON_PRESS && ebtn->button == 1)
169 {
170 gschem_options_cycle_snap_mode (widget->toplevel->options);
171 return TRUE;
172 }
173
174 return FALSE;
175 }
176
177
178
179 /*! \brief Dispose of the object
180 */
181 static void
dispose(GObject * object)182 dispose (GObject *object)
183 {
184 /* lastly, chain up to the parent dispose */
185
186 GschemBottomWidgetClass* cls = GSCHEM_BOTTOM_WIDGET_GET_CLASS (object);
187 GObjectClass* parent_cls = (GObjectClass*) g_type_class_peek_parent (cls);
188
189 parent_cls->dispose (object);
190 }
191
192
193
194 /*! \brief Finalize object
195 */
196 static void
finalize(GObject * object)197 finalize (GObject *object)
198 {
199 /* lastly, chain up to the parent finalize */
200
201 GschemBottomWidgetClass* cls = GSCHEM_BOTTOM_WIDGET_GET_CLASS (object);
202 GObjectClass* parent_cls = (GObjectClass*) g_type_class_peek_parent (cls);
203
204 parent_cls->finalize (object);
205 }
206
207
208
209 /*! \brief Get a property
210 *
211 * \param [in] object
212 * \param [in] param_id
213 * \param [in,out] value
214 * \param [in] pspec
215 */
216 static void
get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)217 get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec)
218 {
219 GschemBottomWidget *widget = GSCHEM_BOTTOM_WIDGET (object);
220
221 switch (param_id) {
222 case PROP_TOPLEVEL:
223 g_value_set_pointer (value, widget->toplevel);
224 break;
225
226 case PROP_GRID_MODE:
227 g_value_set_int (value, gschem_bottom_widget_get_grid_mode (widget));
228 break;
229
230 case PROP_GRID_SIZE:
231 g_value_set_int (value, gschem_bottom_widget_get_grid_size (widget));
232 break;
233
234 case PROP_LEFT_BUTTON_TEXT:
235 g_value_set_string (value, gschem_bottom_widget_get_left_button_text (widget));
236 break;
237
238 case PROP_MIDDLE_BUTTON_TEXT:
239 g_value_set_string (value, gschem_bottom_widget_get_middle_button_text (widget));
240 break;
241
242 case PROP_RIGHT_BUTTON_TEXT:
243 g_value_set_string (value, gschem_bottom_widget_get_right_button_text (widget));
244 break;
245
246 case PROP_SNAP_MODE:
247 g_value_set_int (value, gschem_bottom_widget_get_snap_mode (widget));
248 break;
249
250 case PROP_SNAP_SIZE:
251 g_value_set_int (value, gschem_bottom_widget_get_snap_size (widget));
252 break;
253
254 case PROP_STATUS_TEXT:
255 g_value_set_string (value, gschem_bottom_widget_get_status_text (widget));
256 break;
257
258 case PROP_RUBBER_BAND_MODE:
259 g_value_set_boolean (value, gschem_bottom_widget_get_rubber_band_mode (widget));
260 break;
261
262 case PROP_MAGNETIC_NET_MODE:
263 g_value_set_boolean (value, gschem_bottom_widget_get_magnetic_net_mode (widget));
264 break;
265
266 default:
267 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
268 }
269 }
270
271
272
273 /*! \brief Initialize GschemBottomWidget class
274 *
275 * \param [in] klass The class for the GschemBottomWidget
276 */
277 static void
gschem_bottom_widget_class_init(GschemBottomWidgetClass * klass)278 gschem_bottom_widget_class_init (GschemBottomWidgetClass *klass)
279 {
280 G_OBJECT_CLASS (klass)->dispose = dispose;
281 G_OBJECT_CLASS (klass)->finalize = finalize;
282
283 G_OBJECT_CLASS (klass)->get_property = get_property;
284 G_OBJECT_CLASS (klass)->set_property = set_property;
285
286 GParamFlags flags = (GParamFlags) (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
287 GParamSpec* spec = g_param_spec_pointer ("toplevel", "", "", flags);
288 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TOPLEVEL, spec);
289
290 g_object_class_install_property (G_OBJECT_CLASS (klass),
291 PROP_GRID_MODE,
292 g_param_spec_int ("grid-mode",
293 "Grid Mode",
294 "Grid Mode",
295 0,
296 (GRID_MODE_COUNT - 1),
297 GRID_MODE_NONE,
298 (GParamFlags) (G_PARAM_READWRITE
299 | G_PARAM_CONSTRUCT)));
300
301 g_object_class_install_property (G_OBJECT_CLASS (klass),
302 PROP_GRID_SIZE,
303 g_param_spec_int ("grid-size",
304 "Grid Size",
305 "Grid Size",
306 G_MININT,
307 G_MAXINT,
308 0,
309 (GParamFlags) (G_PARAM_READWRITE
310 | G_PARAM_CONSTRUCT)));
311
312 g_object_class_install_property (G_OBJECT_CLASS (klass),
313 PROP_LEFT_BUTTON_TEXT,
314 g_param_spec_string ("left-button-text",
315 "Left Button Text",
316 "Left Button Text",
317 "none",
318 (GParamFlags) (G_PARAM_READWRITE
319 | G_PARAM_CONSTRUCT)));
320
321 g_object_class_install_property (G_OBJECT_CLASS (klass),
322 PROP_MIDDLE_BUTTON_TEXT,
323 g_param_spec_string ("middle-button-text",
324 "Middle Button Text",
325 "Middle Button Text",
326 "none",
327 (GParamFlags) (G_PARAM_READWRITE
328 | G_PARAM_CONSTRUCT)));
329
330 g_object_class_install_property (G_OBJECT_CLASS (klass),
331 PROP_RIGHT_BUTTON_TEXT,
332 g_param_spec_string ("right-button-text",
333 "Right Button Text",
334 "Right Button Text",
335 "none",
336 (GParamFlags) (G_PARAM_READWRITE
337 | G_PARAM_CONSTRUCT)));
338
339 g_object_class_install_property (G_OBJECT_CLASS (klass),
340 PROP_SNAP_MODE,
341 g_param_spec_int ("snap-mode",
342 "Snap Mode",
343 "Snap Mode",
344 G_MININT,
345 G_MAXINT,
346 0,
347 (GParamFlags) (G_PARAM_READWRITE
348 | G_PARAM_CONSTRUCT)));
349
350 g_object_class_install_property (G_OBJECT_CLASS (klass),
351 PROP_SNAP_SIZE,
352 g_param_spec_int ("snap-size",
353 "Snap Size",
354 "Snap Size",
355 G_MININT,
356 G_MAXINT,
357 0,
358 (GParamFlags) (G_PARAM_READWRITE
359 | G_PARAM_CONSTRUCT)));
360
361 g_object_class_install_property (G_OBJECT_CLASS (klass),
362 PROP_STATUS_TEXT,
363 g_param_spec_string ("status-text",
364 "Status Text",
365 "Status Text",
366 "none",
367 (GParamFlags) (G_PARAM_READWRITE
368 | G_PARAM_CONSTRUCT)));
369
370 g_object_class_install_property (G_OBJECT_CLASS (klass),
371 PROP_STATUS_TEXT_COLOR,
372 g_param_spec_boolean ("status-text-color",
373 "Status State",
374 "Status State",
375 FALSE,
376 (GParamFlags) (G_PARAM_READWRITE
377 | G_PARAM_CONSTRUCT)));
378
379 g_object_class_install_property (G_OBJECT_CLASS (klass),
380 PROP_RUBBER_BAND_MODE,
381 g_param_spec_boolean ("net-rubber-band-mode",
382 "Rubber Band Mode",
383 "Rubber Band Mode",
384 TRUE,
385 (GParamFlags) (G_PARAM_READWRITE
386 | G_PARAM_CONSTRUCT)));
387
388 g_object_class_install_property (G_OBJECT_CLASS (klass),
389 PROP_MAGNETIC_NET_MODE,
390 g_param_spec_boolean ("magnetic-net-mode",
391 "Magnetic Net Mode",
392 "Magnetic Net Mode",
393 TRUE,
394 (GParamFlags) (G_PARAM_READWRITE
395 | G_PARAM_CONSTRUCT)));
396
397 }
398
399
400
401 /*! \brief Get the grid mode
402 *
403 * \param [in] widget This GschemBottomWidget
404 * \return The grid mode
405 */
406 int
gschem_bottom_widget_get_grid_mode(GschemBottomWidget * widget)407 gschem_bottom_widget_get_grid_mode (GschemBottomWidget *widget)
408 {
409 g_return_val_if_fail (widget != NULL, 0);
410
411 return widget->grid_mode;
412 }
413
414
415
416 /*! \brief Get the grid size
417 *
418 * \param [in] widget This GschemBottomWidget
419 * \return The grid size
420 */
421 int
gschem_bottom_widget_get_grid_size(GschemBottomWidget * widget)422 gschem_bottom_widget_get_grid_size (GschemBottomWidget *widget)
423 {
424 g_return_val_if_fail (widget != NULL, 0);
425
426 return widget->grid_size;
427 }
428
429
430
431 /*! \brief Get the left button text
432 *
433 * \param [in] widget This GschemBottomWidget
434 * \return The left button text
435 */
436 const char*
gschem_bottom_widget_get_left_button_text(GschemBottomWidget * widget)437 gschem_bottom_widget_get_left_button_text (GschemBottomWidget *widget)
438 {
439 g_return_val_if_fail (widget != NULL, NULL);
440
441 return gtk_label_get_text (GTK_LABEL (widget->left_button_label));
442 }
443
444
445
446 /*! \brief Get the middle button text
447 *
448 * \param [in] widget This GschemBottomWidget
449 * \return The middle button text
450 */
451 const char*
gschem_bottom_widget_get_middle_button_text(GschemBottomWidget * widget)452 gschem_bottom_widget_get_middle_button_text (GschemBottomWidget *widget)
453 {
454 g_return_val_if_fail (widget != NULL, NULL);
455
456 return gtk_label_get_text (GTK_LABEL (widget->middle_button_label));
457 }
458
459
460
461 /*! \brief Get the right button text
462 *
463 * \param [in] widget This GschemBottomWidget
464 * \return The right button text
465 */
466 const char*
gschem_bottom_widget_get_right_button_text(GschemBottomWidget * widget)467 gschem_bottom_widget_get_right_button_text (GschemBottomWidget *widget)
468 {
469 g_return_val_if_fail (widget != NULL, NULL);
470
471 return gtk_label_get_text (GTK_LABEL (widget->right_button_label));
472 }
473
474
475
476 /*! \brief Get the snap mode
477 *
478 * \param [in] widget This GschemBottomWidget
479 * \return The snap mode
480 */
481 int
gschem_bottom_widget_get_snap_mode(GschemBottomWidget * widget)482 gschem_bottom_widget_get_snap_mode (GschemBottomWidget *widget)
483 {
484 g_return_val_if_fail (widget != NULL, 0);
485
486 return widget->snap_mode;
487 }
488
489
490
491 /*! \brief Get the snap size
492 *
493 * \param [in] widget This GschemBottomWidget
494 * \return The snap size
495 */
496 int
gschem_bottom_widget_get_snap_size(GschemBottomWidget * widget)497 gschem_bottom_widget_get_snap_size (GschemBottomWidget *widget)
498 {
499 g_return_val_if_fail (widget != NULL, 0);
500
501 return widget->snap_size;
502 }
503
504
505
506 /*! \brief Get the status text
507 *
508 * \param [in] widget This GschemBottomWidget
509 * \return The status text
510 */
511 const char*
gschem_bottom_widget_get_status_text(GschemBottomWidget * widget)512 gschem_bottom_widget_get_status_text (GschemBottomWidget *widget)
513 {
514 g_return_val_if_fail (widget != NULL, NULL);
515
516 return gtk_label_get_text (GTK_LABEL (widget->status_label));
517 }
518
519
520
521 /*! \brief Get the rubber band mode
522 *
523 * \param widget This GschemBottomWidget
524 * \return The rubber band mode: on (TRUE) or off (FALSE)
525 */
526 gboolean
gschem_bottom_widget_get_rubber_band_mode(GschemBottomWidget * widget)527 gschem_bottom_widget_get_rubber_band_mode (GschemBottomWidget *widget)
528 {
529 g_return_val_if_fail (widget != NULL, 0);
530
531 return widget->rubber_band_mode;
532 }
533
534
535
536 /*! \brief Get the magnetic net mode
537 *
538 * \param widget This GschemBottomWidget
539 * \return The magnetic net mode: on (TRUE) or off (FALSE)
540 */
541 gboolean
gschem_bottom_widget_get_magnetic_net_mode(GschemBottomWidget * widget)542 gschem_bottom_widget_get_magnetic_net_mode (GschemBottomWidget *widget)
543 {
544 g_return_val_if_fail (widget != NULL, 0);
545
546 return widget->magnetic_net_mode;
547 }
548
549
550
551 static GtkWidget*
separator_new()552 separator_new ()
553 {
554 #ifdef ENABLE_GTK3
555 return gtk_separator_new (GTK_ORIENTATION_VERTICAL);
556 #else
557 return gtk_vseparator_new ();
558 #endif
559 }
560
561
562 /*! \brief Set grid_snap_widget text
563 *
564 * \param widget This GschemBottomWidget
565 * \param str Text to set. Newly-allocated string. Will be g_free()'d
566 */
567 static void
set_snap_info_widget_text(GschemBottomWidget * widget,gchar * str)568 set_snap_info_widget_text (GschemBottomWidget* widget,
569 gchar* str)
570 {
571 g_return_if_fail (widget != NULL);
572
573 gtk_label_set_markup (GTK_LABEL(widget->grid_snap_widget), str);
574 g_free (str);
575 }
576
577
578
579 /*! \brief Set grid_snap_widget color
580 *
581 * \param widget This GschemBottomWidget
582 * \param color_name Color name, e.g. "red", "blue"
583 */
584 static void
set_snap_info_widget_color(GschemBottomWidget * widget,const gchar * color_name)585 set_snap_info_widget_color (GschemBottomWidget* widget,
586 const gchar* color_name)
587 {
588 g_return_if_fail (widget != NULL);
589
590 #ifdef ENABLE_GTK3
591 GdkRGBA color;
592 gdk_rgba_parse (&color, color_name);
593 gtk_widget_override_color (GTK_WIDGET (widget->grid_snap_widget),
594 GTK_STATE_FLAG_NORMAL,
595 &color);
596 #else
597 GdkColor color;
598 gdk_color_parse (color_name, &color);
599 gtk_widget_modify_fg (GTK_WIDGET (widget->grid_snap_widget),
600 GTK_STATE_NORMAL,
601 &color);
602 #endif
603 }
604
605
606
607 /*! \brief Set grid_snap_widget text and color
608 *
609 * \param widget This GschemBottomWidget
610 * \param str Text to set. Newly-allocated string. Will be g_free()'d
611 * \param color_name Color name, e.g. "red", "blue"
612 */
613 static void
set_snap_info_widget(GschemBottomWidget * widget,gchar * str,const gchar * color_name)614 set_snap_info_widget (GschemBottomWidget* widget,
615 gchar* str,
616 const gchar* color_name)
617 {
618 g_return_if_fail (widget != NULL);
619
620 set_snap_info_widget_text (widget, str);
621 set_snap_info_widget_color (widget, color_name);
622 }
623
624
625
626 /*! \brief Reset grid_snap_widget visual state
627 *
628 * \par Function Description
629 * Remove any text decorations, reset text color to black
630 *
631 * \param widget This GschemBottomWidget
632 */
633 static void
reset_snap_info_widget(GschemBottomWidget * widget)634 reset_snap_info_widget (GschemBottomWidget* widget)
635 {
636 g_return_if_fail (widget != NULL);
637
638 gchar* txt = g_strdup_printf ("Snap: %d", widget->snap_size);
639 set_snap_info_widget (widget, txt, "black");
640 }
641
642
643
644 /*! \brief Update info in the grid_snap_widget depending on current snap settings
645 *
646 * \param widget This GschemBottomWidget
647 */
648 static void
update_snap_info_widget(GschemBottomWidget * widget)649 update_snap_info_widget (GschemBottomWidget* widget)
650 {
651 g_return_if_fail (widget != NULL);
652
653 gchar* cwd = g_get_current_dir();
654 EdaConfig* cfg = eda_config_get_context_for_path (cwd);
655 g_free (cwd);
656
657 gint default_snap_size = DEFAULT_SNAP_SIZE;
658
659 if (cfg != NULL)
660 {
661 GError* err = NULL;
662 gint val = eda_config_get_int (cfg,
663 "schematic.gui",
664 "snap-size",
665 &err);
666 if (err == NULL)
667 {
668 default_snap_size = val;
669 }
670
671 g_clear_error (&err);
672 }
673
674
675 reset_snap_info_widget (widget);
676
677 gchar* txt = NULL;
678
679 if (widget->snap_mode == SNAP_OFF)
680 {
681 txt = g_strdup_printf (_("<b>Snap: OFF</b>"));
682 set_snap_info_widget (widget, txt, "blue");
683 }
684 else
685 if (widget->snap_mode == SNAP_GRID)
686 {
687 if (widget->snap_size != default_snap_size)
688 {
689 txt = g_strdup_printf (_("Snap: <b>%d</b>"), widget->snap_size);
690 set_snap_info_widget (widget, txt, "red");
691 }
692 }
693 else
694 if (widget->snap_mode == SNAP_RESNAP)
695 {
696 if (widget->snap_size != default_snap_size)
697 {
698 txt = g_strdup_printf (_("<u>Re</u>snap: <b>%d</b>"), widget->snap_size);
699 set_snap_info_widget(widget, txt, "red");
700 }
701 else
702 {
703 txt = g_strdup_printf (_("<u>Re</u>snap: %d"), widget->snap_size);
704 set_snap_info_widget_text(widget, txt);
705 }
706 }
707 else
708 {
709 g_critical ("%s: update_snap_info_widget(): widget->snap_mode out of range: %d\n",
710 __FILE__,
711 widget->snap_mode);
712 }
713
714
715 if (widget->snap_mode != SNAP_OFF &&
716 widget->snap_size != default_snap_size)
717 {
718 gchar* tooltip = g_strdup_printf(
719 _("Snap size.\n"
720 "Click to change the snapping mode.\n"
721 "Attention: current snap size (%d) differs\n"
722 "from the value set in configuration: %d."),
723 widget->snap_size,
724 default_snap_size);
725
726 gtk_widget_set_tooltip_text (widget->grid_snap_widget,
727 tooltip);
728 g_free (tooltip);
729 }
730 else
731 {
732 gtk_widget_set_tooltip_text (widget->grid_snap_widget,
733 _("Snap size.\n"
734 "Click to change the snapping mode."));
735 }
736
737 } /* update_snap_info_widget() */
738
739
740
741 /*! \brief Create grid_snap_widget
742 *
743 * \param widget This GschemBottomWidget
744 */
745 static void
create_snap_info_widget(GschemBottomWidget * widget)746 create_snap_info_widget (GschemBottomWidget* widget)
747 {
748 g_return_if_fail (widget != NULL);
749
750 widget->grid_snap_widget = gtk_label_new (NULL);
751
752 GtkWidget* ebox = gtk_event_box_new();
753 gtk_container_add (GTK_CONTAINER (ebox), widget->grid_snap_widget);
754 gtk_widget_show_all (ebox);
755
756 gchar* str = g_strdup_printf ("Snap: <b>%d</b>", widget->snap_size);
757 gtk_label_set_markup (GTK_LABEL(widget->grid_snap_widget), str);
758 g_free (str);
759
760 gtk_misc_set_padding (GTK_MISC (widget->grid_snap_widget),
761 LABEL_XPAD,
762 LABEL_YPAD);
763 gtk_box_pack_start (GTK_BOX (widget), ebox, FALSE, FALSE, 0);
764
765 gtk_box_pack_start (GTK_BOX (widget), separator_new(), FALSE, FALSE, 0);
766
767 g_signal_connect (G_OBJECT (ebox),
768 "button-press-event",
769 G_CALLBACK (&on_click_snap_info),
770 widget);
771 }
772
773
774
775 /*! \brief Update info in the grid_size_widget depending on current grid settings
776 *
777 * \param widget This GschemBottomWidget
778 */
779 static void
update_grid_size_widget(GschemBottomWidget * widget)780 update_grid_size_widget (GschemBottomWidget* widget)
781 {
782 g_return_if_fail (widget != NULL);
783
784 gchar* str = NULL;
785
786 if (widget->grid_mode == GRID_MODE_NONE)
787 {
788 str = g_strdup (_("Grid: OFF"));
789 }
790 else
791 if (widget->grid_size <= 0)
792 {
793 str = g_strdup (_("Grid: NONE"));
794 }
795 else
796 {
797 str = g_strdup_printf ("Grid: %d", widget->grid_size);
798 }
799
800 gtk_label_set_label (GTK_LABEL(widget->grid_size_widget), str);
801 gtk_widget_set_tooltip_text (widget->grid_size_widget,
802 _("Grid size.\n"
803 "Click to change the grid style."));
804 g_free (str);
805 }
806
807
808
809 /*! \brief Create grid_size_widget
810 *
811 * \param widget This GschemBottomWidget
812 */
813 static void
create_grid_size_widget(GschemBottomWidget * widget)814 create_grid_size_widget (GschemBottomWidget* widget)
815 {
816 g_return_if_fail (widget != NULL);
817
818 widget->grid_size_widget = gtk_label_new (NULL);
819
820 GtkWidget* ebox = gtk_event_box_new();
821 gtk_container_add (GTK_CONTAINER (ebox), widget->grid_size_widget);
822 gtk_widget_show_all (ebox);
823
824 gchar* str = g_strdup_printf ("Grid: %d", widget->grid_size);
825 gtk_label_set_markup (GTK_LABEL(widget->grid_size_widget),
826 str);
827 g_free (str);
828
829 gtk_misc_set_padding (GTK_MISC (widget->grid_size_widget),
830 LABEL_XPAD,
831 LABEL_YPAD);
832 gtk_box_pack_start (GTK_BOX (widget), ebox, FALSE, FALSE, 0);
833
834 gtk_box_pack_start (GTK_BOX (widget), separator_new(), FALSE, FALSE, 0);
835
836 g_signal_connect (G_OBJECT (ebox),
837 "button-press-event",
838 G_CALLBACK (&on_click_grid_size),
839 widget);
840 }
841
842
843
844 /*! \brief Initialize GschemBottomWidget instance
845 *
846 * \param [in,out] view the gschem page view
847 */
848 static void
gschem_bottom_widget_init(GschemBottomWidget * widget)849 gschem_bottom_widget_init (GschemBottomWidget *widget)
850 {
851 GtkWidget *separator;
852
853 g_return_if_fail (widget != NULL);
854
855 widget->left_button_label = gtk_label_new (NULL);
856 gtk_widget_set_tooltip_text (widget->left_button_label, _("Left mouse button"));
857 gtk_misc_set_padding (GTK_MISC (widget->left_button_label), LABEL_XPAD, LABEL_YPAD);
858
859 widget->middle_button_label = gtk_label_new (NULL);
860 gtk_widget_set_tooltip_text (widget->middle_button_label, _("Middle mouse button"));
861 gtk_misc_set_padding (GTK_MISC (widget->middle_button_label), LABEL_XPAD, LABEL_YPAD);
862
863 widget->right_button_label = gtk_label_new (NULL);
864 gtk_widget_set_tooltip_text (widget->right_button_label, _("Right mouse button"));
865 gtk_misc_set_padding (GTK_MISC (widget->right_button_label), LABEL_XPAD, LABEL_YPAD);
866
867
868 /* default values for configuration settings: */
869 gboolean show_mouse_indicators = TRUE;
870 gboolean show_rubber_band_indicator = FALSE;
871 gboolean show_magnetic_net_indicator = FALSE;
872 #ifdef ENABLE_GTK3
873 gdk_rgba_parse (&widget->status_inactive_color, "black");
874 gdk_rgba_parse (&widget->status_active_color, "green");
875 #else
876 gdk_color_parse ("black", &widget->status_inactive_color);
877 gdk_color_parse ("green", &widget->status_active_color);
878 #endif
879 widget->status_bold_font = FALSE;
880
881 gchar* cwd = g_get_current_dir();
882 EdaConfig* cfg = eda_config_get_context_for_path (cwd);
883 g_free (cwd);
884
885 if (cfg != NULL)
886 {
887 GError* err = NULL;
888 gboolean val = FALSE;
889
890 /* mouse indicators: */
891 val = eda_config_get_boolean (cfg,
892 "schematic.status-bar",
893 "show-mouse-buttons",
894 &err);
895 if (err == NULL)
896 show_mouse_indicators = val;
897 g_clear_error (&err);
898
899 /* net rubber band indicator: */
900 val = eda_config_get_boolean (cfg,
901 "schematic.status-bar",
902 "show-rubber-band",
903 &err);
904 if (err == NULL)
905 show_rubber_band_indicator = val;
906 g_clear_error (&err);
907
908 /* magnetic net indicator: */
909 val = eda_config_get_boolean (cfg,
910 "schematic.status-bar",
911 "show-magnetic-net",
912 &err);
913 if (err == NULL)
914 show_magnetic_net_indicator = val;
915 g_clear_error (&err);
916
917 /* status line active color: */
918 gchar* color = eda_config_get_string (cfg,
919 "schematic.status-bar",
920 "status-active-color",
921 &err);
922 if (color != NULL)
923 {
924 #ifdef ENABLE_GTK3
925 gdk_rgba_parse (&widget->status_active_color, color);
926 #else
927 gdk_color_parse (color, &widget->status_active_color);
928 #endif
929 g_free (color);
930 }
931 g_clear_error (&err);
932
933 /* status line bold font: */
934 val = eda_config_get_boolean (cfg,
935 "schematic.status-bar",
936 "status-bold-font",
937 &err);
938 if (err == NULL)
939 widget->status_bold_font = val;
940 g_clear_error (&err);
941 }
942
943
944 if (show_mouse_indicators)
945 {
946 gtk_box_pack_start (GTK_BOX (widget), widget->left_button_label, FALSE, FALSE, 0);
947 gtk_box_pack_start (GTK_BOX (widget), separator_new(), FALSE, FALSE, 0);
948 gtk_box_pack_start (GTK_BOX (widget), widget->middle_button_label, FALSE, FALSE, 0);
949 gtk_box_pack_start (GTK_BOX (widget), separator_new(), FALSE, FALSE, 0);
950 gtk_box_pack_start (GTK_BOX (widget), widget->right_button_label, FALSE, FALSE, 0);
951 gtk_box_pack_start (GTK_BOX (widget), separator_new(), FALSE, FALSE, 0);
952 }
953
954
955 create_snap_info_widget (widget);
956 create_grid_size_widget (widget);
957
958
959 separator = separator_new ();
960 gtk_box_pack_start (GTK_BOX (widget), separator, FALSE, FALSE, 0);
961
962
963 widget->rubber_band_label = gtk_label_new (NULL);
964 gtk_widget_set_tooltip_text (widget->rubber_band_label,
965 _("Net rubber band mode.\n"
966 "Click to toggle ON/OFF."));
967 gtk_misc_set_padding (GTK_MISC (widget->rubber_band_label), LABEL_XPAD, LABEL_YPAD);
968 if (show_rubber_band_indicator)
969 {
970 GtkWidget* ebox_rubber_band = gtk_event_box_new();
971 gtk_container_add (GTK_CONTAINER (ebox_rubber_band), widget->rubber_band_label);
972 gtk_widget_show_all (ebox_rubber_band);
973 gtk_box_pack_start (GTK_BOX (widget), ebox_rubber_band, FALSE, FALSE, 0);
974
975 g_signal_connect (G_OBJECT (ebox_rubber_band),
976 "button-press-event",
977 G_CALLBACK (&on_click_rubber_band),
978 widget);
979 }
980
981
982 separator = separator_new ();
983 gtk_box_pack_start (GTK_BOX (widget), separator, FALSE, FALSE, 0);
984
985
986 widget->magnetic_net_label = gtk_label_new (NULL);
987 gtk_widget_set_tooltip_text (widget->magnetic_net_label,
988 _("Magnetic net mode.\n"
989 "Click to toggle ON/OFF."));
990 gtk_misc_set_padding (GTK_MISC (widget->magnetic_net_label), LABEL_XPAD, LABEL_YPAD);
991 if (show_magnetic_net_indicator)
992 {
993 GtkWidget* ebox_magnetic_net = gtk_event_box_new();
994 gtk_container_add (GTK_CONTAINER (ebox_magnetic_net), widget->magnetic_net_label);
995 gtk_widget_show_all (ebox_magnetic_net);
996 gtk_box_pack_start (GTK_BOX (widget), ebox_magnetic_net, FALSE, FALSE, 0);
997
998 g_signal_connect (G_OBJECT (ebox_magnetic_net),
999 "button-press-event",
1000 G_CALLBACK (&on_click_magnetic_net),
1001 widget);
1002 }
1003
1004
1005 widget->status_label = gtk_label_new (NULL);
1006 gtk_widget_set_tooltip_text (widget->status_label, _("Current action mode"));
1007 gtk_misc_set_padding (GTK_MISC (widget->status_label), LABEL_XPAD, LABEL_YPAD);
1008 gtk_box_pack_end (GTK_BOX (widget), widget->status_label, FALSE, FALSE, 0);
1009
1010 separator = separator_new ();
1011 gtk_box_pack_start (GTK_BOX (widget), separator, FALSE, FALSE, 0);
1012
1013 g_signal_connect (G_OBJECT (widget),
1014 "notify::grid-mode",
1015 G_CALLBACK (update_grid_label),
1016 NULL);
1017
1018 g_signal_connect (G_OBJECT (widget),
1019 "notify::grid-size",
1020 G_CALLBACK (update_grid_label),
1021 NULL);
1022
1023 g_signal_connect (G_OBJECT (widget),
1024 "notify::snap-mode",
1025 G_CALLBACK (update_grid_label),
1026 NULL);
1027
1028 g_signal_connect (G_OBJECT (widget),
1029 "notify::snap-size",
1030 G_CALLBACK (update_grid_label),
1031 NULL);
1032
1033 g_signal_connect (G_OBJECT (widget),
1034 "notify::net-rubber-band-mode",
1035 G_CALLBACK (update_rubber_band_label),
1036 NULL);
1037
1038 g_signal_connect (G_OBJECT (widget),
1039 "notify::magnetic-net-mode",
1040 G_CALLBACK (update_magnetic_net_label),
1041 NULL);
1042 }
1043
1044
1045
1046 /*! \brief Set the grid mode
1047 *
1048 * \param [in,out] view This GschemBottomWidget
1049 * \param [in] size The grid mode
1050 */
1051 void
gschem_bottom_widget_set_grid_mode(GschemBottomWidget * widget,int mode)1052 gschem_bottom_widget_set_grid_mode (GschemBottomWidget *widget, int mode)
1053 {
1054 g_return_if_fail (widget != NULL);
1055
1056 widget->grid_mode = mode;
1057
1058 g_object_notify (G_OBJECT (widget), "grid-mode");
1059 }
1060
1061
1062
1063 /*! \brief Set the grid size
1064 *
1065 * \param [in,out] view This GschemBottomWidget
1066 * \param [in] size The grid size
1067 */
1068 void
gschem_bottom_widget_set_grid_size(GschemBottomWidget * widget,int size)1069 gschem_bottom_widget_set_grid_size (GschemBottomWidget *widget, int size)
1070 {
1071 g_return_if_fail (widget != NULL);
1072
1073 widget->grid_size = size;
1074
1075 g_object_notify (G_OBJECT (widget), "grid-size");
1076 }
1077
1078
1079
1080 /*! \brief Set the left button text
1081 *
1082 * \param [in,out] view This GschemBottomWidget
1083 * \param [in] text The text
1084 */
1085 void
gschem_bottom_widget_set_left_button_text(GschemBottomWidget * widget,const char * text)1086 gschem_bottom_widget_set_left_button_text (GschemBottomWidget *widget, const char *text)
1087 {
1088 g_return_if_fail (widget != NULL);
1089
1090 gtk_label_set_text (GTK_LABEL (widget->left_button_label), text);
1091
1092 g_object_notify (G_OBJECT (widget), "left-button-text");
1093 }
1094
1095
1096
1097 /*! \brief Set the middle button text
1098 *
1099 * \param [in,out] view This GschemBottomWidget
1100 * \param [in] text The text
1101 */
1102 void
gschem_bottom_widget_set_middle_button_text(GschemBottomWidget * widget,const char * text)1103 gschem_bottom_widget_set_middle_button_text (GschemBottomWidget *widget, const char *text)
1104 {
1105 g_return_if_fail (widget != NULL);
1106
1107 gtk_label_set_text (GTK_LABEL (widget->middle_button_label), text);
1108
1109 g_object_notify (G_OBJECT (widget), "middle-button-text");
1110 }
1111
1112
1113
1114 /*! \brief Set the right button text
1115 *
1116 * \param [in,out] view This GschemBottomWidget
1117 * \param [in] text The text
1118 */
1119 void
gschem_bottom_widget_set_right_button_text(GschemBottomWidget * widget,const char * text)1120 gschem_bottom_widget_set_right_button_text (GschemBottomWidget *widget, const char *text)
1121 {
1122 g_return_if_fail (widget != NULL);
1123
1124 gtk_label_set_text (GTK_LABEL (widget->right_button_label), text);
1125
1126 g_object_notify (G_OBJECT (widget), "right-button-text");
1127 }
1128
1129
1130
1131 /*! \brief Set the snap mode
1132 *
1133 * \param [in,out] view This GschemBottomWidget
1134 * \param [in] size The snap mode
1135 */
1136 void
gschem_bottom_widget_set_snap_mode(GschemBottomWidget * widget,int mode)1137 gschem_bottom_widget_set_snap_mode (GschemBottomWidget *widget, int mode)
1138 {
1139 g_return_if_fail (widget != NULL);
1140
1141 widget->snap_mode = mode;
1142
1143 g_object_notify (G_OBJECT (widget), "snap-mode");
1144 }
1145
1146
1147
1148 /*! \brief Set the snap size
1149 *
1150 * \param [in,out] view This GschemBottomWidget
1151 * \param [in] size The snap size
1152 */
1153 void
gschem_bottom_widget_set_snap_size(GschemBottomWidget * widget,int size)1154 gschem_bottom_widget_set_snap_size (GschemBottomWidget *widget, int size)
1155 {
1156 g_return_if_fail (widget != NULL);
1157
1158 widget->snap_size = size;
1159
1160 g_object_notify (G_OBJECT (widget), "snap-size");
1161 }
1162
1163
1164 /*! \brief Set the status text color
1165 *
1166 * \par Function Description
1167 * Changes the status text color to show if the current editing
1168 * action is active or not.
1169 *
1170 * \param [in,out] view This GschemBottomWidget
1171 * \param [in] active The state to visualise
1172 */
1173 void
gschem_bottom_widget_set_status_text_color(GschemBottomWidget * widget,gboolean active)1174 gschem_bottom_widget_set_status_text_color (GschemBottomWidget *widget, gboolean active)
1175 {
1176 g_return_if_fail (widget != NULL);
1177
1178 #ifdef ENABLE_GTK3
1179 const GdkRGBA* color = NULL;
1180 #else
1181 const GdkColor* color = NULL;
1182 #endif
1183
1184 if (active) {
1185 color = &widget->status_active_color;
1186 } else {
1187 color = &widget->status_inactive_color;
1188 }
1189
1190 #ifdef ENABLE_GTK3
1191 gtk_widget_override_color (GTK_WIDGET (widget->status_label),
1192 GTK_STATE_FLAG_NORMAL,
1193 color);
1194 #else
1195 gtk_widget_modify_fg (GTK_WIDGET (widget->status_label),
1196 GTK_STATE_NORMAL,
1197 color);
1198 #endif
1199 }
1200
1201
1202 /*! \brief Set the status text
1203 *
1204 * \param [in,out] view This GschemBottomWidget
1205 * \param [in] text The status text
1206 */
1207 void
gschem_bottom_widget_set_status_text(GschemBottomWidget * widget,const char * text)1208 gschem_bottom_widget_set_status_text (GschemBottomWidget *widget, const char *text)
1209 {
1210 g_return_if_fail (widget != NULL);
1211
1212 gchar* str = g_markup_printf_escaped (widget->status_bold_font
1213 ? "<b>%s</b>"
1214 : "%s",
1215 text);
1216
1217 gtk_label_set_markup (GTK_LABEL (widget->status_label), str);
1218 g_free (str);
1219
1220 g_object_notify (G_OBJECT (widget), "status-text");
1221 }
1222
1223
1224
1225 /*! \brief Set the rubber band mode
1226 *
1227 * \param [in] widget This GschemBottomWidget
1228 * \param [in] mode The rubber band mode: on (TRUE) or off (FALSE)
1229 */
1230 void
gschem_bottom_widget_set_rubber_band_mode(GschemBottomWidget * widget,gboolean mode)1231 gschem_bottom_widget_set_rubber_band_mode (GschemBottomWidget *widget, gboolean mode)
1232 {
1233 g_return_if_fail (widget != NULL);
1234
1235 widget->rubber_band_mode = mode;
1236
1237 g_object_notify (G_OBJECT (widget), "net-rubber-band-mode");
1238 }
1239
1240
1241
1242 /*! \brief Set the magnetic net mode
1243 *
1244 * \param [in] widget This GschemBottomWidget
1245 * \param [in] mode The magnetic net mode: on (TRUE) or off (FALSE)
1246 */
1247 void
gschem_bottom_widget_set_magnetic_net_mode(GschemBottomWidget * widget,gboolean mode)1248 gschem_bottom_widget_set_magnetic_net_mode (GschemBottomWidget *widget, gboolean mode)
1249 {
1250 g_return_if_fail (widget != NULL);
1251
1252 widget->magnetic_net_mode = mode;
1253
1254 g_object_notify (G_OBJECT (widget), "magnetic-net-mode");
1255 }
1256
1257
1258
1259 /*! \brief Set a gobject property
1260 */
1261 static void
set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)1262 set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec)
1263 {
1264 GschemBottomWidget *widget = GSCHEM_BOTTOM_WIDGET (object);
1265
1266 switch (param_id) {
1267 case PROP_TOPLEVEL:
1268 widget->toplevel = GSCHEM_TOPLEVEL (g_value_get_pointer (value));
1269 break;
1270
1271 case PROP_GRID_MODE:
1272 gschem_bottom_widget_set_grid_mode (widget, g_value_get_int (value));
1273 break;
1274
1275 case PROP_GRID_SIZE:
1276 gschem_bottom_widget_set_grid_size (widget, g_value_get_int (value));
1277 break;
1278
1279 case PROP_LEFT_BUTTON_TEXT:
1280 gschem_bottom_widget_set_left_button_text (widget, g_value_get_string (value));
1281 break;
1282
1283 case PROP_MIDDLE_BUTTON_TEXT:
1284 gschem_bottom_widget_set_middle_button_text (widget, g_value_get_string (value));
1285 break;
1286
1287 case PROP_RIGHT_BUTTON_TEXT:
1288 gschem_bottom_widget_set_right_button_text (widget, g_value_get_string (value));
1289 break;
1290
1291 case PROP_SNAP_MODE:
1292 gschem_bottom_widget_set_snap_mode (widget, g_value_get_int (value));
1293 break;
1294
1295 case PROP_SNAP_SIZE:
1296 gschem_bottom_widget_set_snap_size (widget, g_value_get_int (value));
1297 break;
1298
1299 case PROP_STATUS_TEXT:
1300 gschem_bottom_widget_set_status_text (widget, g_value_get_string (value));
1301 break;
1302
1303 case PROP_STATUS_TEXT_COLOR:
1304 gschem_bottom_widget_set_status_text_color (widget, g_value_get_boolean (value));
1305 break;
1306
1307 case PROP_RUBBER_BAND_MODE:
1308 gschem_bottom_widget_set_rubber_band_mode (widget, g_value_get_boolean (value));
1309 break;
1310
1311 case PROP_MAGNETIC_NET_MODE:
1312 gschem_bottom_widget_set_magnetic_net_mode (widget, g_value_get_boolean (value));
1313 break;
1314
1315 default:
1316 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
1317 }
1318 }
1319
1320
1321
1322 /*! \brief Write the snap and grid settings to the status bar.
1323 *
1324 * \param [in] widget This GschemBottomWidget
1325 * \param [in] pspec The parameter that changed
1326 * \param [in] unused
1327 */
1328 static void
update_grid_label(GschemBottomWidget * widget,GParamSpec * pspec,gpointer unused)1329 update_grid_label (GschemBottomWidget *widget, GParamSpec *pspec, gpointer unused)
1330 {
1331 update_snap_info_widget (widget);
1332 update_grid_size_widget (widget);
1333 }
1334
1335
1336
1337 /*! \brief Display the rubber band indicator in the status bar
1338 *
1339 * \param [in] widget This GschemBottomWidget
1340 * \param [in] pspec The parameter that changed
1341 * \param [in] unused
1342 */
1343 static void
update_rubber_band_label(GschemBottomWidget * widget,GParamSpec * pspec,gpointer unused)1344 update_rubber_band_label (GschemBottomWidget *widget, GParamSpec *pspec, gpointer unused)
1345 {
1346 g_return_if_fail (widget != NULL);
1347
1348 #ifdef ENABLE_GTK3
1349 GdkRGBA color;
1350 gdk_rgba_parse (&color, widget->rubber_band_mode ? "green" : "blue");
1351 gtk_widget_override_color (GTK_WIDGET (widget->rubber_band_label),
1352 GTK_STATE_FLAG_NORMAL,
1353 &color);
1354 #else
1355 GdkColor color;
1356 gdk_color_parse (widget->rubber_band_mode ? "green" : "blue", &color);
1357 gtk_widget_modify_fg (GTK_WIDGET (widget->rubber_band_label),
1358 GTK_STATE_NORMAL,
1359 &color);
1360 #endif
1361
1362 gtk_label_set_markup (GTK_LABEL (widget->rubber_band_label),
1363 widget->rubber_band_mode ?
1364 "RB: <b>ON</b>" : "RB: off");
1365 }
1366
1367
1368
1369 /*! \brief Display the magnetic net indicator in the status bar
1370 *
1371 * \param [in] widget This GschemBottomWidget
1372 * \param [in] pspec The parameter that changed
1373 * \param [in] unused
1374 */
1375 static void
update_magnetic_net_label(GschemBottomWidget * widget,GParamSpec * pspec,gpointer unused)1376 update_magnetic_net_label (GschemBottomWidget *widget, GParamSpec *pspec, gpointer unused)
1377 {
1378 g_return_if_fail (widget != NULL);
1379
1380 #ifdef ENABLE_GTK3
1381 GdkRGBA color;
1382 gdk_rgba_parse (&color, widget->magnetic_net_mode ? "purple" : "darkgray");
1383 gtk_widget_override_color (GTK_WIDGET (widget->magnetic_net_label),
1384 GTK_STATE_FLAG_NORMAL,
1385 &color);
1386 #else
1387 GdkColor color;
1388 gdk_color_parse (widget->magnetic_net_mode ? "purple" : "darkgray", &color);
1389 gtk_widget_modify_fg (GTK_WIDGET (widget->magnetic_net_label),
1390 GTK_STATE_NORMAL,
1391 &color);
1392 #endif
1393
1394 gtk_label_set_markup (GTK_LABEL (widget->magnetic_net_label),
1395 widget->magnetic_net_mode ?
1396 "MN: <b>ON</b>" : "MN: off");
1397 }
1398