1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
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.
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.
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
20 /*! \file gschem_integer_combo_box.c
22 * \brief A GtkComboBox with and entry for integer values.
24 * This widget allows the user to type in an integer values or select a common
25 * integer value from a drop down menu.
45 add_widget (GschemIntegerComboBox
*combo
, GtkWidget
*widget
, gpointer unused
);
48 focus_out_event (GtkEntry
*entry
, GdkEvent
*event
, GschemIntegerComboBox
*combo
);
51 gschem_integer_combo_box_class_init (GschemIntegerComboBoxClass
*klass
);
54 gschem_integer_combo_box_init (GschemIntegerComboBox
*combo
);
57 notify_active (GschemIntegerComboBox
*combo
, GParamSpec
*pspec
, gpointer unused
);
60 remove_widget (GschemIntegerComboBox
*combo
, GtkWidget
*widget
, gpointer unused
);
63 value_changed (GschemIntegerComboBox
*combo
, gpointer unused
);
67 /*! \brief The entry widget is added to the combo box.
69 * The combo box must keep a signal handler connected for the focus
70 * out event for the instant apply functionality.
72 * \param [in] combo This combo box
73 * \param [in] widget The entry widget added to the combo box
77 add_widget (GschemIntegerComboBox
*combo
, GtkWidget
*widget
, gpointer unused
)
79 g_return_if_fail (combo
!= NULL
);
80 g_return_if_fail (widget
!= NULL
);
82 g_signal_connect(G_OBJECT (widget
),
84 G_CALLBACK (focus_out_event
),
90 /*! \brief The entry widget inside the combo box lost focus.
92 * \param [in] entry The entry inside the combo box
93 * \param [in] event The focus out event
94 * \param [in] combo The combo box
97 focus_out_event (GtkEntry
*entry
, GdkEvent
*event
, GschemIntegerComboBox
*combo
)
99 g_return_val_if_fail (entry
!= NULL
, FALSE
);
100 g_return_val_if_fail (combo
!= NULL
, FALSE
);
102 if (combo
->changed
) {
103 g_signal_emit_by_name (combo
, "apply");
104 combo
->changed
= FALSE
;
112 /*! \brief Initialize GschemIntegerComboBoxClass class
114 * \param [in] klass The class for the GschemIntegerComboBoxClass
117 gschem_integer_combo_box_class_init (GschemIntegerComboBoxClass
*klass
)
119 g_return_if_fail (klass
!= NULL
);
121 g_signal_new ("apply", /* signal_name */
122 G_OBJECT_CLASS_TYPE (klass
), /* itype */
123 0, /* signal_flags */
124 0, /* class_offset */
125 NULL
, /* accumulator */
126 NULL
, /* accu_data */
127 g_cclosure_marshal_VOID__VOID
, /* c_marshaller */
128 G_TYPE_NONE
, /* return_type */
135 /*! \brief Get the GschemIntegerComboBox type
137 * \return The GschemIntegerComboBox type
140 gschem_integer_combo_box_get_type()
142 static GType type
= 0;
145 static const GTypeInfo info
= {
146 sizeof(GschemIntegerComboBoxClass
),
147 NULL
, /* base_init */
148 NULL
, /* base_finalize */
149 (GClassInitFunc
) gschem_integer_combo_box_class_init
,
150 NULL
, /* class_finalize */
151 NULL
, /* class_data */
152 sizeof(GschemIntegerComboBox
),
154 (GInstanceInitFunc
) gschem_integer_combo_box_init
,
157 #if GTK_CHECK_VERSION (2, 24, 0)
158 type
= g_type_register_static (GTK_TYPE_COMBO_BOX
, "GschemIntegerComboBox", &info
, 0);
160 type
= g_type_register_static (GTK_TYPE_COMBO_BOX_ENTRY
, "GschemIntegerComboBox", &info
, 0);
168 /*! \brief Get the entry associated with this combo box
170 * \param [in] widget The integer combo box
174 gschem_integer_combo_box_get_entry (GtkWidget
*widget
)
176 g_return_val_if_fail (widget
!= NULL
, NULL
);
178 return GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget
)));
182 /*! \brief Get the integer value
184 * \param [in,out] widget The integer combo box
185 * \return The integer. If the value is invalid, this function returns -1.
188 gschem_integer_combo_box_get_value (GtkWidget
*widget
)
190 GtkWidget
*entry
= GTK_WIDGET (gschem_integer_combo_box_get_entry (widget
));
192 const char *text0
= gtk_entry_get_text (GTK_ENTRY (entry
));
201 temp
= strtol (text0
, &text1
, 0);
203 if ((errno
== 0) && (text1
!= NULL
) && (*text1
== '\0') && (temp
>= 0)) {
213 /*! \brief Initialize a GschemIntegerComboBox
215 * \param [in] klass The instance of a GschemIntegerComboBox
218 gschem_integer_combo_box_init (GschemIntegerComboBox
*combo
)
220 g_return_if_fail (combo
!= NULL
);
222 combo
->changed
= FALSE
;
224 g_signal_connect(G_OBJECT (combo
),
226 G_CALLBACK (notify_active
),
229 g_signal_connect(G_OBJECT (combo
),
231 G_CALLBACK (add_widget
),
234 g_signal_connect(G_OBJECT (combo
),
236 G_CALLBACK (value_changed
),
239 g_signal_connect(G_OBJECT (combo
),
241 G_CALLBACK (remove_widget
),
247 /*! \brief Create a ComboBox with an entry for integer values.
249 * \return A GtkWidget for entering integer values
252 gschem_integer_combo_box_new ()
254 #if GTK_CHECK_VERSION (2, 24, 0)
255 return GTK_WIDGET (g_object_new (GSCHEM_TYPE_INTEGER_COMBO_BOX
, "has-entry", TRUE
, NULL
));
257 return GTK_WIDGET (g_object_new (GSCHEM_TYPE_INTEGER_COMBO_BOX
, NULL
));
263 /*! \brief Set the list store containing the common values
265 * \param [in,out] widget The integer combo box
266 * \param [in] store The list containing the common values
269 gschem_integer_combo_box_set_model (GtkWidget
*widget
, GtkListStore
*store
)
271 g_return_if_fail (widget
!= NULL
);
273 gtk_combo_box_set_model (GTK_COMBO_BOX (widget
), GTK_TREE_MODEL (store
));
276 #if GTK_CHECK_VERSION (2, 24, 0)
277 gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (widget
), x_integerls_get_value_column ());
279 gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (widget
), x_integerls_get_value_column ());
286 /*! \brief Set the integer value
288 * \param [in,out] widget The integer combo box
289 * \param [in] size The value
292 gschem_integer_combo_box_set_value (GtkWidget
*widget
, int value
)
295 g_return_if_fail (widget
!= NULL
);
296 entry
= gtk_bin_get_child (GTK_BIN (widget
));
297 g_return_if_fail (entry
!= NULL
);
302 string
= g_string_new (NULL
);
303 g_string_printf (string
, "%d", value
);
304 gtk_entry_set_text (GTK_ENTRY (entry
), string
->str
);
306 g_string_free (string
, TRUE
);
308 gtk_entry_set_text (GTK_ENTRY (entry
), "");
313 /*! \brief The active item in the combo box has changed
316 notify_active (GschemIntegerComboBox
*combo
, GParamSpec
*pspec
, gpointer unused
)
318 g_return_if_fail (combo
!= NULL
);
320 g_signal_emit_by_name (combo
, "apply");
321 combo
->changed
= FALSE
;
326 /*! \brief The entry widget is removed from the combo box.
328 * The combo box must keep a signal handler connected for the focus
329 * out event for the instant apply functionality.
331 * \param [in] combo This combo box
332 * \param [in] widget The netry widget added to the combo box
336 remove_widget (GschemIntegerComboBox
*combo
, GtkWidget
*widget
, gpointer unused
)
338 g_return_if_fail (combo
!= NULL
);
339 g_return_if_fail (widget
!= NULL
);
341 g_signal_handlers_disconnect_by_func(G_OBJECT (widget
),
342 G_CALLBACK (focus_out_event
),
348 /*! \brief Respond to a change in the value
350 * The function checks the focus to determine the source of the event.
351 * If the entry has focus, the user changed the value, possibly by one
352 * keystroke, and the dialog box should not update the selection. If the
353 * entry does not have focus, the user changed the value in the dropdown
354 * menu, and the dialog box must update the selection.
356 * \param [in] combo This widget
360 value_changed (GschemIntegerComboBox
*combo
, gpointer unused
)
362 g_return_if_fail (combo
!= NULL
);
364 if (gtk_widget_is_focus (GTK_WIDGET (gschem_integer_combo_box_get_entry (GTK_WIDGET (combo
))))) {
365 combo
->changed
= TRUE
;
368 /* This code was getting called before the value changed. The signal handler
369 * was fetching data from one selection in the past.
371 * This code is here in case of compatibility issues pre and post 2.24, that
372 * there will be some info for addressing the issue.
377 g_signal_emit_by_name (combo
, "apply");
378 combo
->changed
= FALSE
;