1 /* Copyright (c) 2008-2009 Robert Ancell
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 #include <glib/gi18n.h>
21 #include "math-converter.h"
22 #include "unit-manager.h"
29 static guint signals
[LAST_SIGNAL
] = { 0, };
31 struct MathConverterPrivate
33 MathEquation
*equation
;
37 GtkWidget
*from_combo
;
40 GtkWidget
*result_label
;
44 G_DEFINE_TYPE (MathConverter
, math_converter
, GTK_TYPE_HBOX
);
46 static void display_changed_cb(MathEquation
*equation
, GParamSpec
*spec
, MathConverter
*converter
);
47 static void update_from_model(MathConverter
*converter
);
51 math_converter_new(MathEquation
*equation
)
53 MathConverter
*converter
= g_object_new(math_converter_get_type(), NULL
);
54 converter
->priv
->equation
= g_object_ref(equation
);
55 g_signal_connect(converter
->priv
->equation
, "notify::display", G_CALLBACK(display_changed_cb
), converter
);
56 update_from_model(converter
);
62 update_result_label(MathConverter
*converter
)
64 GtkTreeIter from_iter
, to_iter
;
65 UnitCategory
*category
= NULL
;
66 Unit
*source_unit
= NULL
, *target_unit
= NULL
;
70 if (!converter
->priv
->result_label
)
73 enabled
= math_equation_get_number(converter
->priv
->equation
, &x
);
76 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(converter
->priv
->from_combo
), &from_iter
) &&
77 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(converter
->priv
->to_combo
), &to_iter
)) {
78 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(converter
->priv
->from_combo
)), &from_iter
, 1, &category
, 2, &source_unit
, -1);
79 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(converter
->priv
->to_combo
)), &to_iter
, 2, &target_unit
, -1);
80 if (!unit_category_convert(category
, &x
, unit_get_name(source_unit
), unit_get_name(target_unit
), &z
))
86 gtk_widget_set_sensitive(converter
->priv
->result_label
, enabled
);
88 gchar
*source_text
, *target_text
, *label
;
89 source_text
= unit_format(source_unit
, &x
);
90 target_text
= unit_format(target_unit
, &z
);
91 label
= g_strdup_printf("%s = %s", source_text
, target_text
);
92 gtk_label_set_text(GTK_LABEL(converter
->priv
->result_label
), label
);
99 g_object_unref(category
);
101 g_object_unref(source_unit
);
103 g_object_unref(target_unit
);
108 display_changed_cb(MathEquation
*equation
, GParamSpec
*spec
, MathConverter
*converter
)
110 update_result_label(converter
);
115 update_from_model(MathConverter
*converter
)
117 GtkTreeStore
*from_model
;
119 from_model
= gtk_tree_store_new(3, G_TYPE_STRING
, G_TYPE_OBJECT
, G_TYPE_OBJECT
);
121 if (converter
->priv
->category
== NULL
) {
122 const GList
*categories
, *iter
;
124 categories
= unit_manager_get_categories(math_equation_get_unit_manager(converter
->priv
->equation
));
125 for (iter
= categories
; iter
; iter
= iter
->next
) {
126 UnitCategory
*category
= iter
->data
;
128 const GList
*unit_iter
;
130 gtk_tree_store_append(from_model
, &parent
, NULL
);
131 gtk_tree_store_set(from_model
, &parent
, 0, unit_category_get_display_name(category
), 1, category
, -1);
133 for (unit_iter
= unit_category_get_units(category
); unit_iter
; unit_iter
= unit_iter
->next
) {
134 Unit
*unit
= unit_iter
->data
;
137 gtk_tree_store_append(from_model
, &iter
, &parent
);
138 gtk_tree_store_set(from_model
, &iter
, 0, unit_get_display_name(unit
), 1, category
, 2, unit
, -1);
143 UnitCategory
*category
;
144 const GList
*unit_iter
;
146 category
= unit_manager_get_category(math_equation_get_unit_manager(converter
->priv
->equation
), converter
->priv
->category
);
147 for (unit_iter
= unit_category_get_units(category
); unit_iter
; unit_iter
= unit_iter
->next
) {
148 Unit
*unit
= unit_iter
->data
;
151 gtk_tree_store_append(from_model
, &iter
, NULL
);
152 gtk_tree_store_set(from_model
, &iter
, 0, unit_get_display_name(unit
), 1, category
, 2, unit
, -1);
156 gtk_combo_box_set_model(GTK_COMBO_BOX(converter
->priv
->from_combo
), GTK_TREE_MODEL(from_model
));
161 math_converter_set_category(MathConverter
*converter
, const gchar
*category
)
163 if (category
== NULL
&& converter
->priv
->category
== NULL
)
165 if (category
!= NULL
&& converter
->priv
->category
!= NULL
&& strcmp(category
, converter
->priv
->category
) == 0)
168 g_free(converter
->priv
->category
);
169 converter
->priv
->category
= g_strdup(category
);
171 update_from_model(converter
);
176 math_converter_get_category(MathConverter
*converter
)
178 return converter
->priv
->category
;
183 iter_is_unit(GtkTreeModel
*model
, GtkTreeIter
*iter
, Unit
*unit
)
187 gtk_tree_model_get(model
, iter
, 2, &u
, -1);
201 set_active_unit(GtkComboBox
*combo
, GtkTreeIter
*iter
, Unit
*unit
)
204 GtkTreeIter child_iter
;
206 model
= gtk_combo_box_get_model(combo
);
208 if (iter
&& iter_is_unit(model
, iter
, unit
)) {
209 gtk_combo_box_set_active_iter(combo
, iter
);
213 if (!gtk_tree_model_iter_children(model
, &child_iter
, iter
))
217 if (set_active_unit(combo
, &child_iter
, unit
))
219 } while (gtk_tree_model_iter_next(model
, &child_iter
));
226 math_converter_set_conversion(MathConverter
*converter
, /*const gchar *category,*/ const gchar
*unit_a
, const gchar
*unit_b
)
231 ua
= unit_manager_get_unit(math_equation_get_unit_manager(converter
->priv
->equation
), unit_a
);
232 ub
= unit_manager_get_unit(math_equation_get_unit_manager(converter
->priv
->equation
), unit_b
);
236 set_active_unit(GTK_COMBO_BOX(converter
->priv
->from_combo
), NULL
, ua
);
237 set_active_unit(GTK_COMBO_BOX(converter
->priv
->to_combo
), NULL
, ub
);
242 math_converter_get_conversion(MathConverter
*converter
, Unit
**from_unit
, Unit
**to_unit
)
244 GtkTreeIter from_iter
, to_iter
;
246 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(converter
->priv
->from_combo
), &from_iter
);
247 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(converter
->priv
->to_combo
), &to_iter
);
249 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(converter
->priv
->from_combo
)), &from_iter
, 2, from_unit
, -1);
250 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(converter
->priv
->to_combo
)), &to_iter
, 2, to_unit
, -1);
255 math_converter_class_init(MathConverterClass
*klass
)
257 g_type_class_add_private(klass
, sizeof(MathConverterPrivate
));
260 g_signal_new("changed",
261 G_TYPE_FROM_CLASS (klass
),
263 G_STRUCT_OFFSET (MathConverterClass
, changed
),
265 g_cclosure_marshal_VOID__VOID
,
271 from_combobox_changed_cb(GtkWidget
*combo
, MathConverter
*converter
)
275 UnitCategory
*category
;
277 const GList
*unit_iter
;
279 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(combo
));
280 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo
), &iter
))
282 gtk_tree_model_get(model
, &iter
, 1, &category
, 2, &unit
, -1);
284 /* Set the to combobox to be the list of units can be converted to */
285 model
= GTK_TREE_MODEL(gtk_list_store_new(3, G_TYPE_STRING
, G_TYPE_OBJECT
, G_TYPE_OBJECT
));
286 for (unit_iter
= unit_category_get_units(category
); unit_iter
; unit_iter
= unit_iter
->next
) {
287 Unit
*u
= unit_iter
->data
;
290 gtk_list_store_append(GTK_LIST_STORE(model
), &iter
);
291 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, 0, unit_get_display_name(u
), 1, category
, 2, u
, -1);
293 gtk_combo_box_set_model(GTK_COMBO_BOX(converter
->priv
->to_combo
), model
);
295 /* Select the first possible unit */
296 gtk_combo_box_set_active(GTK_COMBO_BOX(converter
->priv
->to_combo
), 0);
298 g_object_unref(category
);
299 g_object_unref(unit
);
304 to_combobox_changed_cb(GtkWidget
*combo
, MathConverter
*converter
)
306 /* Conversion must have changed */
307 update_result_label(converter
);
309 g_signal_emit(converter
, signals
[CHANGED
], 0);
314 from_cell_data_func(GtkCellLayout
*cell_layout
,
315 GtkCellRenderer
*cell
,
316 GtkTreeModel
*tree_model
,
320 g_object_set(cell
, "sensitive", !gtk_tree_model_iter_has_child(tree_model
, iter
), NULL
);
325 math_converter_init(MathConverter
*converter
)
327 GtkWidget
*hbox
, *label
;
328 GtkCellRenderer
*renderer
;
330 converter
->priv
= G_TYPE_INSTANCE_GET_PRIVATE(converter
, math_converter_get_type(), MathConverterPrivate
);
332 gtk_box_set_spacing(GTK_BOX(converter
), 6);
334 hbox
= gtk_hbox_new(FALSE
, 0);
335 gtk_widget_show(hbox
);
336 gtk_box_pack_start(GTK_BOX(converter
), hbox
, FALSE
, TRUE
, 0);
338 converter
->priv
->from_combo
= gtk_combo_box_new ();
340 renderer
= gtk_cell_renderer_text_new();
341 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(converter
->priv
->from_combo
), renderer
, TRUE
);
342 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(converter
->priv
->from_combo
), renderer
, "text", 0);
343 gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(converter
->priv
->from_combo
),
347 g_signal_connect(converter
->priv
->from_combo
, "changed", G_CALLBACK(from_combobox_changed_cb
), converter
);
348 gtk_widget_show(converter
->priv
->from_combo
);
349 gtk_box_pack_start(GTK_BOX(hbox
), converter
->priv
->from_combo
, FALSE
, TRUE
, 0);
351 label
= gtk_label_new(/* Label that is displayed between the two conversion combo boxes, e.g. "[degrees] in [radians]" */
353 gtk_widget_show(label
);
354 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, TRUE
, 0);
356 converter
->priv
->to_combo
= gtk_combo_box_new();
357 renderer
= gtk_cell_renderer_text_new();
358 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(converter
->priv
->to_combo
), renderer
, TRUE
);
359 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(converter
->priv
->to_combo
), renderer
, "text", 0);
360 g_signal_connect(converter
->priv
->to_combo
, "changed", G_CALLBACK(to_combobox_changed_cb
), converter
);
361 gtk_widget_show(converter
->priv
->to_combo
);
362 gtk_box_pack_start(GTK_BOX(hbox
), converter
->priv
->to_combo
, FALSE
, TRUE
, 0);
364 converter
->priv
->result_label
= gtk_label_new("");
365 gtk_misc_set_alignment(GTK_MISC(converter
->priv
->result_label
), 1.0, 0.5);
366 gtk_widget_set_sensitive(converter
->priv
->result_label
, FALSE
);
367 gtk_widget_show(converter
->priv
->result_label
);
368 gtk_box_pack_start(GTK_BOX(converter
), converter
->priv
->result_label
, TRUE
, TRUE
, 0);