[gcalctool] Add GUI for unit conversions (fixes bug #539830)



commit ace020ff3066d2404ba2f5a2724b8fc4c56e6106
Author: Robin Sonefors <ozamosi flukkost nu>
Date:   Sun Oct 10 23:10:30 2010 +0200

    Add GUI for unit conversions (fixes bug #539830)
    
    Removes support for changing angle units outside of preferences window.
    However, adds support for explicit angle unit conversation.

 data/buttons-advanced.ui |  146 ++++++++++----------
 src/math-buttons.c       |  342 +++++++++++++++++++++++++++-------------------
 src/math-equation.c      |   14 ++
 src/mp-equation.c        |   18 +++-
 4 files changed, 305 insertions(+), 215 deletions(-)
---
diff --git a/data/buttons-advanced.ui b/data/buttons-advanced.ui
index 6ac97a0..3b1c241 100644
--- a/data/buttons-advanced.ui
+++ b/data/buttons-advanced.ui
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy toplevel-contextual -->
@@ -12,7 +12,7 @@
             <property name="visible">True</property>
             <property name="spacing">6</property>
             <child>
-              <object class="GtkComboBox" id="angle_units_combo">
+              <object class="GtkComboBox" id="convert_from_combo">
                 <property name="visible">True</property>
                 <property name="focus_on_click">False</property>
               </object>
@@ -22,21 +22,25 @@
               </packing>
             </child>
             <child>
-              <object class="GtkLabel" id="angle_label">
+              <object class="GtkLabel" id="label7">
                 <property name="visible">True</property>
-                <property name="xalign">1</property>
-                <property name="label" comments="Example content">3.14159 radians = 180 degrees</property>
-                <child internal-child="accessible">
-                  <object class="AtkObject" id="angle_label-atkobject">
-                    <property name="AtkObject::accessible-name">angle_label</property>
-                    <property name="AtkObject::accessible-description">Displays an angle unit conversion</property>
-                  </object>
-                </child>
+                <property name="label" translatable="yes">in</property>
               </object>
               <packing>
+                <property name="expand">False</property>
                 <property name="position">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkComboBox" id="convert_to_combo">
+                <property name="visible">True</property>
+                <property name="focus_on_click">False</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -60,11 +64,11 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the inverse button">Inverse</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="label20">
                     <property name="visible">True</property>
-                    <property name="label">&lt;i&gt;x&lt;/i&gt;&lt;sup&gt;&#x2212;1&lt;/sup&gt;</property>
+                    <property name="label">&lt;i&gt;x&lt;/i&gt;&lt;sup&gt;â??1&lt;/sup&gt;</property>
                     <property name="use_markup">True</property>
                     <property name="justify">center</property>
                   </object>
@@ -81,7 +85,7 @@
             </child>
             <child>
               <object class="GtkButton" id="calc_factor_button">
-                <property name="label">a&#xD7;b</property>
+                <property name="label">aÃ?b</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -92,7 +96,7 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the factorize button">Factorize</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="factorize_cb"/>
+                <signal name="clicked" handler="factorize_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">5</property>
@@ -114,7 +118,7 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the factorial button">Factorial</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="label14">
                     <property name="visible">True</property>
@@ -140,7 +144,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">7</property>
@@ -158,7 +162,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="imaginary_label">
                     <property name="visible">True</property>
@@ -184,7 +188,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="top_attach">2</property>
@@ -201,7 +205,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="top_attach">1</property>
@@ -218,7 +222,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">1</property>
@@ -237,7 +241,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">2</property>
@@ -256,7 +260,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">1</property>
@@ -275,7 +279,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">2</property>
@@ -288,13 +292,13 @@
             </child>
             <child>
               <object class="GtkButton" id="calc_divide_button">
-                <property name="label">&#xF7;</property>
+                <property name="label">÷</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">3</property>
@@ -313,7 +317,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="top_attach">3</property>
@@ -330,7 +334,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">1</property>
@@ -349,7 +353,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="top_attach">4</property>
@@ -366,7 +370,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="numeric_point_cb"/>
+                <signal name="clicked" handler="numeric_point_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">1</property>
@@ -385,7 +389,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="digit_cb"/>
+                <signal name="clicked" handler="digit_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">2</property>
@@ -398,13 +402,13 @@
             </child>
             <child>
               <object class="GtkButton" id="calc_multiply_button">
-                <property name="label">&#xD7;</property>
+                <property name="label">Ã?</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">3</property>
@@ -417,13 +421,13 @@
             </child>
             <child>
               <object class="GtkButton" id="calc_subtract_button">
-                <property name="label">&#x2212;</property>
+                <property name="label">â??</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="subtract_cb"/>
+                <signal name="clicked" handler="subtract_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">3</property>
@@ -442,7 +446,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">3</property>
@@ -461,7 +465,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="solve_cb"/>
+                <signal name="clicked" handler="solve_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">4</property>
@@ -480,7 +484,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="clear_cb"/>
+                <signal name="clicked" handler="clear_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">5</property>
@@ -500,11 +504,11 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the subscript mode button">Subscript</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="set_subscript_cb"/>
+                <signal name="clicked" handler="set_subscript_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="label4">
                     <property name="visible">True</property>
-                    <property name="label">&#x2193;n</property>
+                    <property name="label">â??n</property>
                     <property name="use_markup">True</property>
                   </object>
                 </child>
@@ -525,11 +529,11 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the superscript mode button">Superscript</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="set_superscript_cb"/>
+                <signal name="clicked" handler="set_superscript_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="label3">
                     <property name="visible">True</property>
-                    <property name="label">&#x2191;n</property>
+                    <property name="label">â??n</property>
                     <property name="use_markup">True</property>
                   </object>
                 </child>
@@ -553,11 +557,11 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the scientific exponent button">Scientific Exponent</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="exponent_cb"/>
+                <signal name="clicked" handler="exponent_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="label2">
                     <property name="visible">True</property>
-                    <property name="label">&#xD7;10&lt;sup&gt;&lt;i&gt;y&lt;/i&gt;&lt;/sup&gt;</property>
+                    <property name="label">Ã?10&lt;sup&gt;&lt;i&gt;y&lt;/i&gt;&lt;/sup&gt;</property>
                     <property name="use_markup">True</property>
                   </object>
                 </child>
@@ -577,7 +581,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">3</property>
@@ -594,7 +598,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">4</property>
@@ -613,7 +617,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">5</property>
@@ -635,14 +639,14 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the recall value button">Recall</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="recall_cb"/>
+                <signal name="clicked" handler="recall_cb" swapped="no"/>
                 <child>
                   <object class="GtkHBox" id="hbox19">
                     <property name="visible">True</property>
                     <child>
                       <object class="GtkLabel" id="label22">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes" comments="The label on the memory recall button">&#x2190; R</property>
+                        <property name="label" translatable="yes" comments="The label on the memory recall button">â?? R</property>
                       </object>
                       <packing>
                         <property name="position">0</property>
@@ -681,14 +685,14 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the store value button">Store</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="store_cb"/>
+                <signal name="clicked" handler="store_cb" swapped="no"/>
                 <child>
                   <object class="GtkHBox" id="hbox20">
                     <property name="visible">True</property>
                     <child>
                       <object class="GtkLabel" id="label23">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes" comments="The label on the memory store button">&#x2192; R</property>
+                        <property name="label" translatable="yes" comments="The label on the memory store button">â?? R</property>
                       </object>
                       <packing>
                         <property name="position">0</property>
@@ -728,7 +732,7 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the absolute value button">Absolute Value</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="label1">
                     <property name="visible">True</property>
@@ -754,7 +758,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">6</property>
@@ -773,7 +777,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">8</property>
@@ -792,7 +796,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">9</property>
@@ -811,7 +815,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">9</property>
@@ -829,7 +833,7 @@
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">8</property>
@@ -851,7 +855,7 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the exponentiation (x to the power of y) button">Exponent</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="x_pow_y_label">
                     <property name="visible">True</property>
@@ -871,13 +875,13 @@
             </child>
             <child>
               <object class="GtkButton" id="calc_root_button">
-                <property name="label">&#x221A;</property>
+                <property name="label">â??</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">7</property>
@@ -896,7 +900,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="undo_cb"/>
+                <signal name="clicked" handler="undo_cb" swapped="no"/>
               </object>
               <packing>
                 <property name="left_attach">4</property>
@@ -912,11 +916,11 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="pi_label">
                     <property name="visible">True</property>
-                    <property name="label">&#x3C0;</property>
+                    <property name="label">Ï?</property>
                     <property name="use_markup">True</property>
                   </object>
                 </child>
@@ -937,7 +941,7 @@
                 <property name="receives_default">True</property>
                 <property name="use_underline">True</property>
                 <property name="focus_on_click">False</property>
-                <signal name="clicked" handler="button_cb"/>
+                <signal name="clicked" handler="button_cb" swapped="no"/>
                 <child>
                   <object class="GtkLabel" id="eulers_number_label">
                     <property name="visible">True</property>
@@ -968,7 +972,7 @@
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
                     <property name="focus_on_click">False</property>
-                    <signal name="clicked" handler="button_cb"/>
+                    <signal name="clicked" handler="button_cb" swapped="no"/>
                   </object>
                   <packing>
                     <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
@@ -982,7 +986,7 @@
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
                     <property name="focus_on_click">False</property>
-                    <signal name="clicked" handler="button_cb"/>
+                    <signal name="clicked" handler="button_cb" swapped="no"/>
                   </object>
                   <packing>
                     <property name="left_attach">1</property>
@@ -998,7 +1002,7 @@
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
                     <property name="focus_on_click">False</property>
-                    <signal name="clicked" handler="button_cb"/>
+                    <signal name="clicked" handler="button_cb" swapped="no"/>
                   </object>
                   <packing>
                     <property name="left_attach">2</property>
@@ -1014,7 +1018,7 @@
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
                     <property name="focus_on_click">False</property>
-                    <signal name="clicked" handler="button_cb"/>
+                    <signal name="clicked" handler="button_cb" swapped="no"/>
                   </object>
                   <packing>
                     <property name="top_attach">1</property>
@@ -1030,7 +1034,7 @@
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
                     <property name="focus_on_click">False</property>
-                    <signal name="clicked" handler="button_cb"/>
+                    <signal name="clicked" handler="button_cb" swapped="no"/>
                   </object>
                   <packing>
                     <property name="left_attach">1</property>
@@ -1048,7 +1052,7 @@
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
                     <property name="focus_on_click">False</property>
-                    <signal name="clicked" handler="button_cb"/>
+                    <signal name="clicked" handler="button_cb" swapped="no"/>
                   </object>
                   <packing>
                     <property name="left_attach">2</property>
@@ -1077,7 +1081,7 @@
                     <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the store value button">Store</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="function_cb"/>
+                <signal name="clicked" handler="function_cb" swapped="no"/>
                 <child>
                   <object class="GtkHBox" id="hbox2">
                     <property name="visible">True</property>
diff --git a/src/math-buttons.c b/src/math-buttons.c
index a633a1e..b8caff4 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -54,10 +54,11 @@ struct MathButtonsPrivate
     GList *superscript_toggles;
     GList *subscript_toggles;
 
-    GtkWidget *angle_combo;
-    GtkWidget *angle_label;
-  
-    GtkWidget *base_combo;  
+    GtkWidget *convert_from_combo;
+    GtkWidget *convert_to_combo;
+    gchar *previous_ans;
+
+    GtkWidget *base_combo;
     GtkWidget *base_label;
     GtkWidget *bit_panel;
     GtkWidget *bit_labels[MAXBITS];
@@ -310,6 +311,119 @@ static char *finc_dialog_fields[][5] = {
     {NULL,        NULL,          NULL,         NULL,         NULL}
 };
 
+#define MAX_UNITS 20
+struct Unit {
+    char* ui_name;
+    char* internal_name;
+};
+
+struct UnitCategory {
+    char* name;
+    struct Unit units[MAX_UNITS];
+};
+
+static struct UnitCategory categories[] = {
+    {N_("Angle Units"),  {
+                          /* Angle unit */
+                          {N_("Degrees"), "degrees"},
+                          /* Angle unit */
+                          {N_("Radians"), "radians"},
+                          /* Angle unit */
+                          {N_("Gradians"), "gradians"},
+                          {NULL, NULL}}},
+    {N_("Length Units"), {
+                          /* Length unit */
+                          {N_("Parsecs"), "parsecs"},
+                          /* Length unit */
+                          {N_("Light Years"), "lightyears"},
+                          /* Length unit */
+                          {N_("Astronomical Unit"), "au"},
+                          /* Length unit */
+                          {N_("Nautical Miles"), "nm"},
+                          /* Length unit */
+                          {N_("Miles"), "miles"},
+                          /* Length unit */
+                          {N_("Kilometers"), "kilometers"},
+                          /* Length unit */
+                          {N_("Cables"), "cables"},
+                          /* Length unit */
+                          {N_("Fathoms"), "fathoms"},
+                          /* Length unit */
+                          {N_("Meters"), "meters"},
+                          /* Length unit */
+                          {N_("Yards"), "yards"},
+                          /* Length unit */
+                          {N_("Feet"), "feet"},
+                          /* Length unit */
+                          {N_("Inches"), "inches"},
+                          /* Length unit */
+                          {N_("Centimeters"), "centimeters"},
+                          /* Length unit */
+                          {N_("Millimeters"), "millimeters"},
+                          /* Length unit */
+                          {N_("Micrometers"), "micrometers"},
+                          /* Length unit */
+                          {N_("Nanometers"), "nanometers"},
+                          {NULL, NULL}}},
+    {N_("Area Units"),   {
+                          /* Area unit */
+                          {N_("Hectares"), "hectares"},
+                          /* Area unit */
+                          {N_("Acres"), "acres"},
+                          /* Area unit */
+                          {N_("m²"), "m²"},
+                          /* Area unit */
+                          {N_("cm²"), "cm²"},
+                          /* Area unit */
+                          {N_("mm²"), "mm²"},
+                          {NULL, NULL}}},
+    {N_("Volume Units"), {
+                          /* Volume unit */
+                          {N_("m³"), "m³"},
+                          /* Volume unit */
+                          {N_("Gallons"), "gallons"},
+                          /* Volume unit */
+                          {N_("Liters"), "liters"},
+                          /* Volume unit */
+                          {N_("Quarts"), "quarts"},
+                          /* Volume unit */
+                          {N_("Pints"), "pints"},
+                          /* Volume unit */
+                          {N_("Milliliters"), "milliliters"},
+                          /* Volume unit */
+                          {N_("cm³"), "cm³"},
+                          /* Volume unit */
+                          {N_("mm³"), "mm³"},
+                          {NULL, NULL}}},
+    {N_("Weight Units"), {
+                          /* Weight unit */
+                          {N_("Tonnes"), "tonnes"},
+                          /* Weight unit */
+                          {N_("Kilograms"), "kilograms"},
+                          /* Weight unit */
+                          {N_("Pounds"), "pounds"},
+                          /* Weight unit */
+                          {N_("Ounces"), "ounces"},
+                          /* Weight unit */
+                          {N_("Grams"), "grams"},
+                          {NULL, NULL}}},
+    {N_("Time Units"),   {
+                          /* Time unit */
+                          {N_("Years"), "years"},
+                          /* Time unit */
+                          {N_("Days"), "days"},
+                          /* Time unit */
+                          {N_("Hours"), "hours"},
+                          /* Time unit */
+                          {N_("Minutes"), "minutes"},
+                          /* Time unit */
+                          {N_("Seconds"), "seconds"},
+                          /* Time unit */
+                          {N_("Milliseconds"), "milliseconds"},
+                          /* Time unit */
+                          {N_("Microseconds"), "microseconds"},
+                          {NULL, NULL}}}
+};
 
 MathButtons *
 math_buttons_new(MathEquation *equation)
@@ -392,101 +506,6 @@ load_finc_dialogs(MathButtons *buttons)
 
 
 static void
-update_angle_label (MathButtons *buttons)
-{
-    MPNumber x;
-    MPNumber pi, max_value, min_value, fraction, input, output;
-    char *label, input_text[1024], output_text1[1024], output_text2[1024];
-
-    if (!buttons->priv->angle_label)
-        return;
-
-    if (!math_equation_get_number(buttons->priv->equation, &x))
-        return;
-
-    mp_get_pi(&pi);
-    switch (math_equation_get_angle_units(buttons->priv->equation)) {
-    default:
-    case MP_DEGREES:
-        /* Clip to the range ±360 */
-        mp_set_from_integer(360, &max_value);
-        mp_invert_sign(&max_value, &min_value);
-        if (!mp_is_equal(&x, &max_value) && !mp_is_equal(&x, &min_value)) {
-            mp_divide(&x, &max_value, &fraction);
-            mp_fractional_component(&fraction, &fraction);
-            mp_multiply(&fraction, &max_value, &input);
-        }
-        else {
-            mp_set_from_mp(&x, &input);
-            mp_set_from_integer(mp_is_negative(&input) ? -1 : 1, &fraction);
-        }
-        mp_serializer_to_specific_string(&input, 10, 2, false, true, input_text, 1024);
-
-        mp_multiply_integer(&fraction, 2, &output);
-        mp_multiply(&output, &pi, &output);
-        mp_serializer_to_specific_string(&output, 10, 2, false, true, output_text1, 1024);
-
-        mp_multiply_integer(&fraction, 400, &output);
-        mp_serializer_to_specific_string(&output, 10, 2, false, true, output_text2, 1024);
-
-        label = g_strdup_printf(_("%s degrees = %s radians = %s gradians"), input_text, output_text1, output_text2);
-        break;
-    case MP_RADIANS:
-        /* Clip to the range ±2Ï? */
-        mp_multiply_integer(&pi, 2, &max_value);
-        mp_invert_sign(&max_value, &min_value);
-        if (!mp_is_equal(&x, &max_value) && !mp_is_equal(&x, &min_value)) {
-            mp_divide(&x, &max_value, &fraction);
-            mp_fractional_component(&fraction, &fraction);
-            mp_multiply(&fraction, &max_value, &input);
-        }
-        else {
-            mp_set_from_mp(&x, &input);
-            mp_set_from_integer(mp_is_negative(&input) ? -1 : 1, &fraction);
-        }
-        mp_serializer_to_specific_string(&input, 10, 2, false, true, input_text, 1024);
-
-        mp_multiply_integer(&fraction, 360, &output);
-        mp_serializer_to_specific_string(&output, 10, 2, false, true, output_text1, 1024);
-
-        mp_multiply_integer(&fraction, 400, &output);
-        mp_serializer_to_specific_string(&output, 10, 2, false, true, output_text2, 1024);
-
-        label = g_strdup_printf(_("%s radians = %s degrees = %s gradians"), input_text, output_text1, output_text2);
-        break;
-    case MP_GRADIANS:
-        /* Clip to the range ±400 */
-        mp_set_from_integer(400, &max_value);
-        mp_invert_sign(&max_value, &min_value);
-        if (!mp_is_equal(&x, &max_value) && !mp_is_equal(&x, &min_value)) {
-            mp_divide(&x, &max_value, &fraction);
-            mp_fractional_component(&fraction, &fraction);
-            mp_multiply(&fraction, &max_value, &input);
-        }
-        else {
-            mp_set_from_mp(&x, &input);
-            mp_set_from_integer(mp_is_negative(&input) ? -1 : 1, &fraction);
-        }
-
-        mp_serializer_to_specific_string(&input, 10, 2, false, true, input_text, 1024);
-
-        mp_multiply_integer(&fraction, 360, &output);
-        mp_serializer_to_specific_string(&output, 10, 2, false, true, output_text1, 1024);
-
-        mp_multiply_integer(&fraction, 2, &output);
-        mp_multiply(&output, &pi, &output);
-        mp_serializer_to_specific_string(&output, 10, 2, false, true, output_text2, 1024);
-
-        label = g_strdup_printf(_("%s gradians = %s degrees = %s radians"), input_text, output_text1, output_text2);
-        break;
-    }
-
-    gtk_label_set_text(GTK_LABEL(buttons->priv->angle_label), label);
-    g_free(label);
-}
-
-
-static void
 update_bit_panel(MathButtons *buttons)
 {
     MPNumber x;
@@ -598,50 +617,84 @@ update_currency_label(MathButtons *buttons)
 static void
 display_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
 {
-    update_angle_label(buttons);
     update_currency_label(buttons);
     update_bit_panel(buttons);
 }
 
 
 static void
-angle_unit_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
+convert_from_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
 {
-    MPAngleUnit value;
     GtkTreeModel *model;
-    GtkTreeIter iter;
+    GtkTreeIter iter, unittype;
+    int typeindex, i;
 
     model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
     gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
-    gtk_tree_model_get(model, &iter, 1, &value, -1);
-    math_equation_set_angle_units(buttons->priv->equation, value);
+
+    if (!gtk_tree_model_iter_parent(model, &unittype, &iter))
+        return;
+
+    gtk_tree_model_get(model, &unittype, 1, &typeindex, -1);
+
+    model = GTK_TREE_MODEL(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT));
+    for (i = 0; categories[typeindex].units[i].ui_name != NULL; i++) {
+        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, categories[typeindex].units[i].ui_name, 1, i, -1);
+    }
+    gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->convert_to_combo), model);
 }
 
 
 static void
-angle_unit_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
+convert_to_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
 {
     GtkTreeModel *model;
-    GtkTreeIter iter;
-    gboolean valid;
+    GtkTreeIter iter, catiter;
+    gchar *from, *to, *display;
+    int category, fromindex, toindex;
 
-    model = gtk_combo_box_get_model(GTK_COMBO_BOX(buttons->priv->angle_combo));
-    valid = gtk_tree_model_get_iter_first(model, &iter);
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
+    gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
+    gtk_tree_model_get(model, &iter, 1, &toindex, -1);
 
-    while (valid) {
-        gint v;
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(buttons->priv->convert_from_combo));
+    gtk_combo_box_get_active_iter(GTK_COMBO_BOX(buttons->priv->convert_from_combo), &iter);
+    if (!gtk_tree_model_iter_parent(model, &catiter, &iter))
+        return;
 
-        gtk_tree_model_get(model, &iter, 1, &v, -1);
-        if (v == math_equation_get_angle_units(buttons->priv->equation))
-            break;
-        valid = gtk_tree_model_iter_next(model, &iter);
-    }
-    if (!valid)
-        valid = gtk_tree_model_get_iter_first(model, &iter);
+    gtk_tree_model_get(model, &catiter, 1, &category, -1);
+    gtk_tree_model_get(model, &iter, 1, &fromindex, -1);
+
+    from = categories[category].units[fromindex].internal_name;
+    to = categories[category].units[toindex].internal_name;
 
-    gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons->priv->angle_combo), &iter);
+    if (buttons->priv->previous_ans == NULL) {
+        display = math_equation_get_display(buttons->priv->equation);
+        buttons->priv->previous_ans = display;
+    }
+    else {
+        display = buttons->priv->previous_ans;
+    }
+    math_equation_set(buttons->priv->equation, g_strdup_printf("%s %s in %s", display, from, to));
 }
 
+static void
+update_conversion_combos(MathEquation *equation, MathButtons *buttons)
+{
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(buttons->priv->convert_from_combo));
+    gtk_tree_model_get_iter_first(model, &iter);
+    gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons->priv->convert_from_combo), &iter);
+
+    model = GTK_TREE_MODEL(gtk_list_store_new(1, G_TYPE_STRING));
+    gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->convert_to_combo), model);
+
+    g_free(buttons->priv->previous_ans);
+    buttons->priv->previous_ans = NULL;
+}
 
 static void
 base_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
@@ -911,34 +964,37 @@ load_mode(MathButtons *buttons, ButtonMode mode)
     }
   
     if (mode == ADVANCED) {
-        GtkListStore *model;
-        GtkTreeIter iter;
+        GtkTreeStore *from_model;
+        GtkTreeIter iter, parent;
         GtkCellRenderer *renderer;
+        int i, j;
 
-        buttons->priv->angle_label = GET_WIDGET(builder, "angle_label");
+//        buttons->priv->angle_label = GET_WIDGET(builder, "angle_label");
 
-        buttons->priv->angle_combo = GET_WIDGET(builder, "angle_units_combo");
-        model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
-        gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->angle_combo), GTK_TREE_MODEL(model));
-        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
-        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
-                           /* Advanced buttons: Angle unit combo box: Use degrees for trigonometric calculations */
-                           _("Degrees"), 1, MP_DEGREES, -1);
-        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
-        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
-                           /* Advanced buttons: Angle unit combo box: Use radians for trigonometric calculations */
-                           _("Radians"), 1, MP_RADIANS, -1);
-        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
-        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
-                           /* Advanced buttons: Angle unit combo box: Use gradians for trigonometric calculations */
-                           _("Gradians"), 1, MP_GRADIANS, -1);
+        buttons->priv->convert_from_combo = GET_WIDGET(builder, "convert_from_combo");
+        from_model = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
+        gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->convert_from_combo), GTK_TREE_MODEL(from_model));
+
+        for (i = 0; i < sizeof(categories) / sizeof(categories[0]); i++) {
+            gtk_tree_store_append(from_model, &parent, NULL);
+            gtk_tree_store_set(from_model, &parent, 0, categories[i].name, 1, i, -1);
+            for (j = 0; categories[i].units[j].ui_name != NULL; j++) {
+                gtk_tree_store_append(from_model, &iter, &parent);
+                gtk_tree_store_set(from_model, &iter, 0, categories[i].units[j].ui_name, 1, j, -1);
+            }
+        }
+        renderer = gtk_cell_renderer_text_new();
+        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(buttons->priv->convert_from_combo), renderer, TRUE);
+        gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(buttons->priv->convert_from_combo), renderer, "text", 0);
+
+        buttons->priv->convert_to_combo = GET_WIDGET(builder, "convert_to_combo");
         renderer = gtk_cell_renderer_text_new();
-        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(buttons->priv->angle_combo), renderer, TRUE);
-        gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(buttons->priv->angle_combo), renderer, "text", 0);
+        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(buttons->priv->convert_to_combo), renderer, TRUE);
+        gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(buttons->priv->convert_to_combo), renderer, "text", 0);
 
-        g_signal_connect(buttons->priv->angle_combo, "changed", G_CALLBACK(angle_unit_combobox_changed_cb), buttons);
-        g_signal_connect(buttons->priv->equation, "notify::angle-units", G_CALLBACK(angle_unit_cb), buttons);
-        angle_unit_cb(buttons->priv->equation, NULL, buttons);
+        g_signal_connect(buttons->priv->convert_from_combo, "changed", G_CALLBACK(convert_from_combobox_changed_cb), buttons);
+        g_signal_connect(buttons->priv->convert_to_combo, "changed", G_CALLBACK(convert_to_combobox_changed_cb), buttons);
+        g_signal_connect(buttons->priv->equation, "answer-changed", G_CALLBACK(update_conversion_combos), buttons);
     }
 
     if (mode == PROGRAMMING) {
diff --git a/src/math-equation.c b/src/math-equation.c
index 0f33ab2..4481745 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -172,6 +172,8 @@ reformat_display(MathEquation *equation, gint old_base)
 {
     /* Change ans */
     reformat_ans(equation);
+
+    g_signal_emit_by_name(equation, "answer-changed");
 }
 
 
@@ -970,6 +972,8 @@ math_equation_solve(MathEquation *equation)
         math_equation_set_status(equation, message);
         g_free(message);
     }
+
+    g_signal_emit_by_name(equation, "answer-changed");
 }
 
 
@@ -1349,6 +1353,16 @@ math_equation_class_init (MathEquationClass *klass)
                                                         "Serializer",
                                                         MP_TYPE_SERIALIZER,
                                                         G_PARAM_READABLE));
+
+    g_signal_new ("answer-changed",
+                  G_TYPE_FROM_CLASS(object_class),
+                  G_SIGNAL_RUN_FIRST,
+                  0,
+                  NULL,
+                  NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE,
+                  0);
 }
 
 
diff --git a/src/mp-equation.c b/src/mp-equation.c
index 34f698b..e05500f 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -270,6 +270,21 @@ do_convert(const char *units[][2], const MPNumber *x, const char *x_units, const
 static int
 convert(MPEquationParserState *state, const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
 {
+    const char *angle_units[][2] = {
+        /* FIXME: Approximations of 1/(units in a circle)
+         * Therefore, 360 deg != 400 grads */
+        {"grad",     "0.0025"},
+        {"gradian",  "0.0025"},
+        {"gradians", "0.0025"},
+        {"deg",      "0.002777778"},
+        {"degree",   "0.002777778"},
+        {"degrees",  "0.002777778"},
+        {"rad",      "0.159154943"},
+        {"radian",   "0.159154943"},
+        {"radians",  "0.159154943"},
+        {NULL, NULL}
+    };
+
     const char *length_units[][2] = {
         {"parsec",     "30857000000000000"},
         {"parsecs",    "30857000000000000"},
@@ -397,7 +412,8 @@ convert(MPEquationParserState *state, const MPNumber *x, const char *x_units, co
         {NULL, NULL}
     };
 
-    if (do_convert(length_units, x, x_units, z_units, z) ||
+    if (do_convert(angle_units, x, x_units, z_units, z) ||
+        do_convert(length_units, x, x_units, z_units, z) ||
         do_convert(area_units, x, x_units, z_units, z) ||
         do_convert(volume_units, x, x_units, z_units, z) ||
         do_convert(weight_units, x, x_units, z_units, z) ||



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]