2 * Copyright (C) 2008-2012 Robert Ancell
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation, either version 2 of the License, or (at your option) any later
7 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
11 public class MathConverter
: Gtk
.Box
13 private MathEquation equation
;
15 private string category
;
17 private Gtk
.ComboBox from_combo
;
18 private Gtk
.ComboBox to_combo
;
20 private Gtk
.Label result_label
;
22 public signal void changed ();
24 public MathConverter (MathEquation equation
)
26 Object (orientation
: Gtk
.Orientation
.HORIZONTAL
);
27 this
.equation
= equation
;
31 var hbox
= new Gtk
.Box (Gtk
.Orientation
.HORIZONTAL
, 0);
33 pack_start (hbox
, false, true, 0);
35 from_combo
= new Gtk
.ComboBox ();
37 var renderer
= new Gtk
.CellRendererText ();
38 from_combo
.pack_start (renderer
, true);
39 from_combo
.add_attribute (renderer
, "text", 0);
40 from_combo
.set_cell_data_func (renderer
, from_cell_data_func
);
41 from_combo
.changed
.connect (from_combobox_changed_cb
);
43 hbox
.pack_start (from_combo
, false, true, 0);
45 var label
= new Gtk
.Label (/* Label that is displayed between the two conversion combo boxes, e.g. "[degrees] in [radians]" */
48 hbox
.pack_start (label
, false, true, 5);
50 to_combo
= new Gtk
.ComboBox ();
51 renderer
= new Gtk
.CellRendererText ();
52 to_combo
.pack_start (renderer
, true);
53 to_combo
.add_attribute (renderer
, "text", 0);
54 to_combo
.changed
.connect (to_combobox_changed_cb
);
56 hbox
.pack_start (to_combo
, false, true, 0);
58 var swap_button
= new Gtk
.Button
.with_label ("⇆");
59 swap_button
.set_tooltip_text (/* Tooltip for swap conversion button */
60 _("Switch conversion units"));
61 swap_button
.set_relief (Gtk
.ReliefStyle
.NONE
);
62 swap_button
.clicked
.connect (swap_button_clicked_cb
);
64 hbox
.pack_start (swap_button
, false, true, 0);
66 result_label
= new Gtk
.Label ("");
67 result_label
.set_alignment (1.0f
, 0.5f
);
68 result_label
.sensitive
= false;
70 pack_start (result_label
, true, true, 0);
72 CurrencyManager
.get_default ().updated
.connect (() => { update_result_label (); });
73 equation
.notify
["display"].connect ((pspec
) => { update_result_label (); });
78 public void set_category (string? category
)
80 if (this
.category
== category
)
82 this
.category
= category
;
87 public string get_category ()
92 public void set_conversion (/*string category,*/ string unit_a
, string unit_b
)
94 var ua
= UnitManager
.get_default ().get_unit_by_name (unit_a
);
95 var ub
= UnitManager
.get_default ().get_unit_by_name (unit_b
);
96 if (ua
== null || ub
== null)
98 /* Select the first unit */
99 var model
= from_combo
.get_model ();
101 if (model
.get_iter_first (out iter
))
103 Gtk
.TreeIter child_iter
;
104 while (model
.iter_children (out child_iter
, iter
))
106 from_combo
.set_active_iter (iter
);
111 set_active_unit (from_combo
, null, ua
);
112 set_active_unit (to_combo
, null, ub
);
115 public void get_conversion (out Unit from_unit
, out Unit to_unit
)
117 Gtk
.TreeIter from_iter
, to_iter
;
119 from_combo
.get_active_iter (out from_iter
);
120 to_combo
.get_active_iter (out to_iter
);
122 from_combo
.get_model ().get (from_iter
, 2, out from_unit
, -1);
123 to_combo
.get_model ().get (to_iter
, 2, out to_unit
, -1);
126 private void update_result_label ()
128 var x
= equation
.number
;
132 var z
= convert_equation (x
);
133 result_label
.sensitive
= z
!= null;
136 Unit source_unit
, target_unit
;
137 get_conversion (out source_unit
, out target_unit
);
139 var source_text
= source_unit
.format (x
);
140 var target_text
= target_unit
.format (z
);
141 result_label
.set_text ("%s = %s".printf (source_text
, target_text
));
145 private void update_from_model ()
147 var from_model
= new Gtk
.TreeStore (3, typeof (string), typeof (UnitCategory
), typeof (Unit
));
149 if (category
== null)
151 var categories
= UnitManager
.get_default ().get_categories ();
152 foreach (var category
in categories
)
155 from_model
.append (out parent
, null);
156 from_model
.set (parent
, 0, category
.display_name
, 1, category
, -1);
158 foreach (var unit
in category
.get_units ())
161 from_model
.append (out iter
, parent
);
162 from_model
.set (iter
, 0, unit
.display_name
, 1, category
, 2, unit
, -1);
168 var c
= UnitManager
.get_default ().get_category (category
);
169 foreach (var unit
in c
.get_units ())
172 from_model
.append (out iter
, null);
173 from_model
.set (iter
, 0, unit
.display_name
, 1, c
, 2, unit
, -1);
177 from_combo
.model
= from_model
;
180 private bool iter_is_unit (Gtk
.TreeModel model
, Gtk
.TreeIter iter
, Unit unit
)
183 model
.get (iter
, 2, out u
, -1);
187 private bool set_active_unit (Gtk
.ComboBox combo
, Gtk
.TreeIter? iter
, Unit unit
)
189 var model
= combo
.get_model ();
190 if (iter
!= null && iter_is_unit (model
, iter
, unit
))
192 combo
.set_active_iter (iter
);
196 Gtk
.TreeIter child_iter
;
197 if (!model
.iter_children (out child_iter
, iter
))
202 if (set_active_unit (combo
, child_iter
, unit
))
204 } while (model
.iter_next (ref child_iter
));
209 private void from_combobox_changed_cb ()
211 var model
= from_combo
.get_model ();
213 if (!from_combo
.get_active_iter (out iter
))
215 UnitCategory category
;
217 model
.get (iter
, 1, out category
, 2, out unit
, -1);
219 /* Set the to combobox to be the list of units can be converted to */
220 var to_model
= new Gtk
.ListStore (3, typeof (string), typeof (UnitCategory
), typeof (Unit
));
221 foreach (var u
in category
.get_units ())
225 to_model
.append (out iter
);
226 to_model
.set (iter
, 0, u
.display_name
, 1, category
, 2, u
, -1);
228 to_combo
.model
= to_model
;
230 /* Select the first possible unit */
231 to_combo
.set_active (0);
234 private void to_combobox_changed_cb ()
236 /* Conversion must have changed */
237 update_result_label ();
241 private void from_cell_data_func (Gtk
.CellLayout cell_layout
, Gtk
.CellRenderer cell
, Gtk
.TreeModel tree_model
, Gtk
.TreeIter iter
)
243 cell
.set ("sensitive", !tree_model
.iter_has_child (iter
));
246 private void swap_button_clicked_cb ()
248 var x
= equation
.number
;
251 var z
= convert_equation (x
);
253 equation
.set_number (z
);
256 Unit from_unit
, to_unit
;
257 get_conversion (out from_unit
, out to_unit
);
258 set_active_unit (from_combo
, null, to_unit
);
259 set_active_unit (to_combo
, null, from_unit
);
261 update_result_label ();
264 private Number?
convert_equation (Number x
)
266 Gtk
.TreeIter from_iter
, to_iter
;
267 if (!from_combo
.get_active_iter (out from_iter
))
269 if (!to_combo
.get_active_iter (out to_iter
))
272 UnitCategory category
;
273 Unit source_unit
, target_unit
;
274 from_combo
.model
.get (from_iter
, 1, out category
, 2, out source_unit
, -1);
275 to_combo
.model
.get (to_iter
, 2, out target_unit
, -1);
277 return category
.convert (x
, source_unit
, target_unit
);