Index: .cvsignore
===================================================================
--- .cvsignore	(revision 1)
+++ .cvsignore	(revision 1)
@@ -0,0 +1,3 @@
+build
+api
+
Index: source/.cvsignore
===================================================================
--- source/.cvsignore	(revision 1)
+++ source/.cvsignore	(revision 1)
@@ -0,0 +1,1 @@
+script
Index: source/class/pf/Application.js
===================================================================
--- source/class/pf/Application.js	(revision 0)
+++ source/class/pf/Application.js	(revision 1)
@@ -14,4 +14,76 @@
 
 ************************************************************************ */
+
+function NumPrint(v)
+{
+    var s;
+    if (v == 0.0) {
+        s = "0";
+    } else
+    if (Math.abs(v) < 1.e6) {
+        s = sprintf("%.3f", v);
+    } else {
+        s = sprintf("%.3e", v);
+    }
+    
+    return s;
+}
+
+function changeN_e(e)
+{
+    var N_e = this.gui_N_e.getNumValue();
+    
+    if (isFinite(N_e)) {
+        this.N_e = N_e;
+        this.updatePlasmaParameters();
+        this.gui_N_i.setNumValue(this.N_i);
+        this.gui_N_r.setNumValue(this.N_r);
+    }
+}
+
+function changeZ_i(e)
+{
+    var Z_i = parseInt(this.gui_Z_i.getValue());
+    
+    if (isFinite(Z_i)) {
+        this.Z_i = Z_i;
+        this.updatePlasmaParameters();
+        this.gui_N_i.setNumValue(this.N_i);
+        this.gui_N_r.setNumValue(this.N_r);
+    }
+}
+
+function changeZ_r(e)
+{
+    var Z_r = parseInt(this.gui_Z_r.getValue());
+    
+    if (isFinite(Z_r)) {
+        this.Z_r = Z_r;
+        this.updatePlasmaParameters();
+        this.gui_N_i.setNumValue(this.N_i);
+        this.gui_N_r.setNumValue(this.N_r);
+    }
+}
+
+function changeP_r(e)
+{
+    var P_r = parseInt(this.gui_P_r.getValue())/100.0;
+    
+    if (isFinite(P_r)) {
+        this.P_r = P_r;
+        this.updatePlasmaParameters();
+        this.gui_N_i.setNumValue(this.N_i);
+        this.gui_N_r.setNumValue(this.N_r);
+    }
+}
+
+function changeB(e)
+{
+    var v = this.gui_B.getNumValue();
+    
+    if (isFinite(v)) {
+        this.B = v;
+    }
+}
 
 /**
@@ -20,90 +92,300 @@
 qx.Class.define("pf.Application",
 {
-  extend : qx.application.Gui,
-
-
-
-
-  /*
-  *****************************************************************************
-     MEMBERS
-  *****************************************************************************
-  */
-
-  members :
-  {
-    /**
-     * TODOC
-     *
-     * @type member
-     * @param e {Event} TODOC
-     * @return {void}
-     */
-    main : function(e)
+    extend : qx.application.Gui,
+
+    /*
+    *****************************************************************************
+       MEMBERS
+    *****************************************************************************
+    */
+
+    members :
     {
-      this.base(arguments);
-
-      // Define alias for custom resource path
-      qx.io.Alias.getInstance().add("pf", qx.core.Setting.get("pf.resourceUri"));
-
-      // Create button
-      var button1 = new qx.ui.form.Button("First Button", "pf/image/test.png");
-
-      // Set button location
-      button1.setTop(50);
-      button1.setLeft(50);
-
-      // Add button to document
-      button1.addToDocument();
-
-      // Attach a tooltip
-      button1.setToolTip(new qx.ui.popup.ToolTip("A nice tooltip", "icon/32/status/dialog-information.png"));
-
-      // Add an event listener
-      button1.addEventListener("execute", function(e) {
-        alert("Hello World!");
-      });
+        
+        checkPlasmaParameters : function()
+        {
+            if (this.N_e <= 0.0 ||
+                (this.P_r < 0.0 || this.P_r > 1.0) ||
+                this.Z_i < 1 ||
+                this.P_r == 1.0 && this.Z_r == 0) {
+                return false;
+            } else {
+                return true;
+            }
+        },
+
+        updatePlasmaParameters : function()
+        {
+            // Safety measures
+            if (this.checkPlasmaParameters() != true) {
+                return false;
+            }
+            
+            if (this.P_r < 1.0) {
+                this.N_i = this.N_e*(1.0 - this.P_r)/
+                    (this.Z_i*(1.0 - this.P_r) + this.Z_r*this.P_r);
+                
+                this.N_r = this.N_i*this.P_r/(1.0 - this.P_r);
+            } else {
+                this.N_i = 0.0;
+                this.N_r = this.N_e/this.Z_r;
+            }
+            
+            return true;
+        },
+        
+        /**
+         * TODOC
+         *
+         * @type member
+         * @param e {Event} TODOC
+         * @return {void}
+         */
+        main : function(e)
+        {
+            this.base(arguments);
+            
+            // Define alias for custom resource path
+            qx.io.Alias.getInstance().add("pf",
+                qx.core.Setting.get("pf.resourceUri"));
+
+            // Defaults
+            this.N_e = 1e16;
+            this.Z_i = 1;
+            this.Z_r = 0;
+            this.P_r = 0;
+
+            this.T_e = 1;
+            this.T_i = 1;
+            this.T_r = 1;
+
+            this.M_i = 1;
+            this.M_r = 1;
+            
+            this.B   = 0;
+            
+            if (this.updatePlasmaParameters() != true) {
+                alert("Error!");
+            }
+            
+            
+            var fr, gl;
+            var l, e;
+
+            fr = new qx.ui.groupbox.GroupBox("Electrons");
+            fr.setDimension("auto", "auto");
+            fr.setBackgroundColor("#ffeeee");
+
+            fr.addToDocument();
+
+            gl = new qx.ui.layout.GridLayout;
+            gl.setVerticalSpacing(4);
+            gl.setHorizontalSpacing(6);
+            gl.setColumnCount(2);
+            gl.setColumnWidth(0, 100);
+            gl.setColumnWidth(1, 200);
+            gl.setRowCount(2);
+            gl.setRowHeight(0, 30);
+            gl.setRowHeight(1, 30);
+
+            fr.add(gl);
+
+            // N_e
+            l = new qx.ui.basic.Label("N<sub>e</sub> (cm<sup>-3</sup>):");
+            gl.add(l, 0, 0);
+            e = new pf.ui.TextField(this.N_e);
+            gl.add(e, 1, 0);
+            e.setLiveUpdate(true);
+            e.addEventListener("changeValue", changeN_e, this);
+            this.gui_N_e = e;
+
+            // T_e
+            l = new qx.ui.basic.Label("T<sub>e</sub> (eV):");
+            gl.add(l, 0, 1);
+            e = new pf.ui.TextField(this.T_e);
+            gl.add(e, 1, 1);
+
+
+            fr = new qx.ui.groupbox.GroupBox("Ions");
+            fr.setDimension("auto", "auto");
+            fr.setBackgroundColor("#eeeeff");
+
+            fr.addToDocument();
+            fr.setTop(100);
+
+            gl = new qx.ui.layout.GridLayout;
+            gl.setVerticalSpacing(4);
+            gl.setHorizontalSpacing(6);
+            gl.setColumnCount(2);
+            gl.setColumnWidth(0, 100);
+            gl.setColumnWidth(1, 200);
+            gl.setRowCount(4);
+            gl.setRowHeight(0, 30);
+            gl.setRowHeight(1, 30);
+            gl.setRowHeight(2, 30);
+            gl.setRowHeight(3, 30);
+
+            fr.add(gl);
+
+            // Z_i
+            l = new qx.ui.basic.Label("Z<sub>i</sub>:");
+            gl.add(l, 0, 0);
+            e = new qx.ui.form.Spinner(1, this.Z_i, 100);
+            gl.add(e, 1, 0);
+            
+            e.addEventListener("change", changeZ_i, this);
+            
+            this.gui_Z_i = e;
+
+            // M_i
+            l = new qx.ui.basic.Label("M<sub>i</sub>:");
+            gl.add(l, 0, 1);
+            e = new qx.ui.form.Spinner(1, this.M_i, 200);
+            gl.add(e, 1, 1);
+            this.gui_M_i = e;
+            
+            // T_i
+            l = new qx.ui.basic.Label("T<sub>i</sub> (eV):");
+            gl.add(l, 0, 2);
+            e = new pf.ui.TextField(this.T_i);
+            gl.add(e, 1, 2);
+
+            // N_i
+            l = new qx.ui.basic.Label("N<sub>i</sub> (cm<sup>-3</sup>):");
+            gl.add(l, 0, 3);
+            e = new pf.ui.TextField(this.N_i);
+            gl.add(e, 1, 3);
+            e.setReadOnly(true);
+            this.gui_N_i = e;
+            
+            
+            fr = new qx.ui.groupbox.GroupBox("Radiators");
+            fr.setDimension("auto", "auto");
+            fr.setBackgroundColor("#eeffee");
+
+            fr.addToDocument();
+            fr.setLeft(330);
+
+            gl = new qx.ui.layout.GridLayout;
+            gl.setVerticalSpacing(4);
+            gl.setHorizontalSpacing(6);
+            gl.setColumnCount(2);
+            gl.setColumnWidth(0, 100);
+            gl.setColumnWidth(1, 200);
+            gl.setRowCount(5);
+            gl.setRowHeight(0, 30);
+            gl.setRowHeight(1, 30);
+            gl.setRowHeight(2, 30);
+            gl.setRowHeight(3, 30);
+            gl.setRowHeight(4, 30);
+
+            fr.add(gl);
+
+
+            // Z_r
+            l = new qx.ui.basic.Label("Z<sub>r</sub>:");
+            gl.add(l, 0, 0);
+            e = new qx.ui.form.Spinner(0, this.Z_r, 100);
+            gl.add(e, 1, 0);
+            e.addEventListener("change", changeZ_r, this);
+            this.gui_Z_r = e;
+
+            // M_r
+            l = new qx.ui.basic.Label("M<sub>r</sub>:");
+            gl.add(l, 0, 1);
+            e = new qx.ui.form.Spinner(1, this.M_r, 200);
+            gl.add(e, 1, 1);
+            this.gui_M_r = e;
+
+            // T_r
+            l = new qx.ui.basic.Label("T<sub>r</sub> (eV):");
+            gl.add(l, 0, 2);
+            e = new pf.ui.TextField(this.T_r);
+            gl.add(e, 1, 2);
+
+            // P_r
+            l = new qx.ui.basic.Label("P<sub>r</sub> (%):");
+            gl.add(l, 0, 3);
+            e = new qx.ui.form.Spinner(0, this.P_r, 100);
+            gl.add(e, 1, 3);
+            e.addEventListener("change", changeP_r, this);
+            this.gui_P_r = e;
+
+            // N_r
+            l = new qx.ui.basic.Label("N<sub>r</sub> (cm<sup>-3</sup>):");
+            gl.add(l, 0, 4);
+            e = new pf.ui.TextField(this.N_r);
+            e.setReadOnly(true);
+            gl.add(e, 1, 4);
+            this.gui_N_r = e;
+
+
+            fr = new qx.ui.groupbox.GroupBox("Fields");
+            fr.setDimension("auto", "auto");
+            fr.setBackgroundColor("#ffffdd");
+
+            fr.addToDocument();
+
+            gl = new qx.ui.layout.GridLayout;
+            gl.setVerticalSpacing(4);
+            gl.setHorizontalSpacing(6);
+            gl.setColumnCount(2);
+            gl.setColumnWidth(0, 100);
+            gl.setColumnWidth(1, 200);
+            gl.setRowCount(1);
+            gl.setRowHeight(0, 30);
+
+            fr.add(gl);
+            
+            fr.setLeft(330);
+            fr.setTop(202);
+
+            l = new qx.ui.basic.Label("B (T):");
+            gl.add(l, 0, 0);
+            e = new pf.ui.TextField(this.B);
+            gl.add(e, 1, 0);
+            e.setLiveUpdate(true);
+            e.addEventListener("changeValue", changeB, this);
+            this.gui_B = e;
+
+        },
+    
+
+        /**
+         * TODOC
+         *
+         * @type member
+         * @param e {Event} TODOC
+         * @return {void}
+         */
+        close : function(e)
+        {
+            this.base(arguments);
+
+            // Prompt user
+            // return "qooxdoo application: Do you really want to close the application?";
+        },
+
+
+       /**
+        * TODOC
+        *
+        * @type member
+        * @param e {Event} TODOC
+        * @return {void}
+        */
+        terminate : function(e) {
+            this.base(arguments);
+        }
     },
 
-
-    /**
-     * TODOC
-     *
-     * @type member
-     * @param e {Event} TODOC
-     * @return {void}
-     */
-    close : function(e)
-    {
-      this.base(arguments);
-
-      // Prompt user
-      // return "qooxdoo application: Do you really want to close the application?";
-    },
-
-
-    /**
-     * TODOC
-     *
-     * @type member
-     * @param e {Event} TODOC
-     * @return {void}
-     */
-    terminate : function(e) {
-      this.base(arguments);
-    }
-  },
-
-
-
-
-  /*
-  *****************************************************************************
-     SETTINGS
-  *****************************************************************************
-  */
-
-  settings : {
-    "pf.resourceUri" : "./resource"
-  }
+    /*
+    *****************************************************************************
+       SETTINGS
+    *****************************************************************************
+    */
+
+    settings : {
+        "pf.resourceUri" : "./resource"
+    }
 });
Index: source/class/pf/ui/TextField.js
===================================================================
--- source/class/pf/ui/TextField.js	(revision 1)
+++ source/class/pf/ui/TextField.js	(revision 1)
@@ -0,0 +1,23 @@
+
+qx.Class.define("pf.ui.TextField",
+{
+    extend: qx.ui.form.TextField,
+    
+    construct: function(v) {
+        this.base(arguments, NumPrint(v));
+    },
+    
+    members:
+    {
+        setNumValue: function(v)
+        {
+            this.setValue(NumPrint(v));
+        },
+
+        getNumValue: function()
+        {
+            return parseFloat(this.getValue());
+        }
+    }
+        
+});
Index: source/index.html
===================================================================
--- source/index.html	(revision 0)
+++ source/index.html	(revision 1)
@@ -2,6 +2,10 @@
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    <title>Custom Application</title>
+    <title>Plasma Formularly Interactive</title>
     <script type="text/javascript" src="script/pf.js"></script>
+    <script type="text/javascript" src="sprintf.js"></script>
+    <script type="text/javascript">
+        qx.log.Logger.ROOT_LOGGER.setMinLevel(qx.log.Logger.LEVEL_WARN);
+    </script>
   </head>
 </html>
Index: source/sprintf.js
===================================================================
--- source/sprintf.js	(revision 1)
+++ source/sprintf.js	(revision 1)
@@ -0,0 +1,51 @@
+/**
+ * sprintf() for JavaScript v.0.1
+ *
+ * Copyright (c) 2007 Alexandru Marasteanu <http://alexei.417.ro/>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+function str_repeat(i, m) { for (var o = []; m > 0; o[--m] = i); return(o.join('')); }
+
+function sprintf() {
+	var i = 0, f = arguments[i++], o = [], m, a, p;
+	while (f) {
+		if (m = /^[^\x25]+/.exec(f)) o.push(m[0]);
+		else if (m = /^\x25{2}/.exec(f)) o.push('%');
+		else if (m = /^\x25(\+)?(0|'[^$])?(-)?(\d+)?(\.\d+)?([b-fosuxX])/.exec(f)) {
+			if (!(a = arguments[i++])) throw("Too few arguments.");
+			if (/[^s]/.test(m[6]) && (typeof(a) != 'number'))
+				throw("Expecting number but found " + typeof(a));
+			switch (m[6]) {
+				case 'b': a = a.toString(2); break;
+				case 'c': a = String.fromCharCode(a); break;
+				case 'd': a = parseInt(a); break;
+				case 'e': a = m[5] ? a.toExponential(m[5].charAt(1)) : a.toExponential(); break;
+				case 'f': a = m[5] ? parseFloat(a).toFixed(m[5].charAt(1)) : parseFloat(a); break;
+				case 'o': a = a.toString(8); break;
+				case 's': a = ((a = String(a)) && m[5] ? a.substring(0, m[5].charAt(1)) : a); break;
+				case 'u': a = Math.abs(a); break;
+				case 'x': a = a.toString(16); break;
+				case 'X': a = a.toString(16).toUpperCase(); break;
+			}
+			a = (/[def]/.test(m[6]) && m[1] && a > 0 ? '+' + a : a);
+			p = m[4] ? str_repeat(m[2] ? m[2] == '0' ? '0' : m[2].charAt(1) : ' ', m[5] ? m[4] - String(a).length : m[4]) : '';
+			o.push(m[3] ? a + p : p + a);
+		} else throw("Huh ?");
+		f = f.substring(m[0].length);
+	}
+	return(o.join(''));
+}
