source: source/class/pf/Application.js @ 278:9c1b65fb4a09

Last change on this file since 278:9c1b65fb4a09 was 278:9c1b65fb4a09, checked in by Evgeny Stambulchik <Evgeny.Stambulchik@…>, 13 years ago

qx.util.Json -> qx.lang.Json.

File size: 93.2 KB
Line 
1/* ************************************************************************
2
3   Copyright: Weizmann Institute of Science
4
5   License: GPL
6
7   Authors: Evgeny Stambulchik
8
9************************************************************************ */
10
11/* ************************************************************************
12
13#asset(pf/image/*.png)
14#asset(pf/html/*.html)
15
16************************************************************************ */
17
18// global
19var plasma_entities;
20
21function changeN_e(ev)
22{
23    var e = ev.getTarget();
24    var N_e = e.getNumValue();
25   
26    if (isFinite(N_e) && this.plasma.e.setN(N_e)) {
27        this.updatePlasmaParameters();
28        this.updateGUI();
29    }
30}
31
32function changeT_e(ev)
33{
34    var e = ev.getTarget();
35    var T_e = e.getNumValue();
36   
37    if (isFinite(T_e)) {
38        this.plasma.e.setT(T_e);
39        if (!this.gui_locked) {
40            this.plasma.i.setT(T_e);
41            this.plasma.r.setT(T_e);
42            this.updateGUI();
43        }
44    }
45}
46
47function changeZ_i(ev)
48{
49    var e = ev.getTarget();
50    var Z_i = parseInt(e.getValue());
51   
52    if (isFinite(Z_i)) {
53        this.plasma.i.setQ(Z_i);
54        this.updatePlasmaParameters();
55        this.updateGUI();
56    }
57}
58
59function changeT_i(ev)
60{
61    var e = ev.getTarget();
62    var T_i = e.getNumValue();
63   
64    if (isFinite(T_i)) {
65        this.plasma.i.setT(T_i);
66        if (!this.gui_locked) {
67            this.plasma.r.setT(T_i);
68            this.updateGUI();
69        }
70    }
71}
72
73function changeZ_r(ev)
74{
75    var e = ev.getTarget();
76    var Z_r = parseInt(e.getValue());
77   
78    if (isFinite(Z_r)) {
79        this.plasma.r.setQ(Z_r);
80        this.updatePlasmaParameters();
81        this.updateGUI();
82    }
83}
84
85function changeP_r(ev)
86{
87    var e = ev.getTarget();
88    var P_r = parseInt(e.getValue())/100.0;
89   
90    if (isFinite(P_r)) {
91        this.plasma.P_r = P_r;
92        this.updatePlasmaParameters();
93        this.updateGUI();
94    }
95}
96
97function changeT_r(ev)
98{
99    var e = ev.getTarget();
100    var T_r = e.getNumValue();
101   
102    if (isFinite(T_r)) {
103        this.plasma.r.setT(T_r);
104        this.updateGUI();
105    }
106}
107
108function changeM_i(ev)
109{
110    var e = ev.getTarget();
111    var M_i = e.getNumValue();
112   
113    if (isFinite(M_i)) {
114        this.plasma.i.setM(M_i);
115        this.updateGUI();
116    }
117}
118
119function changeM_r(ev)
120{
121    var e = ev.getTarget();
122    var M_r = e.getNumValue();
123   
124    if (isFinite(M_r)) {
125        this.plasma.r.setM(M_r);
126        this.updateGUI();
127    }
128}
129
130function changeN_u(ev)
131{
132    var e = ev.getTarget();
133    var n_u = parseInt(e.getValue());
134   
135    this.gui_n_l.setMaximum(n_u - 1);
136   
137    this.plasma.n_u = n_u;
138    this.updateGUI();
139}
140
141function changeN_l(ev)
142{
143    var e = ev.getTarget();
144    var n_l = parseInt(e.getValue());
145   
146    this.gui_n_u.setMinimum(n_l + 1);
147   
148    this.plasma.n_l = n_l;
149    this.updateGUI();
150}
151
152function changeB(ev)
153{
154    var e = ev.getTarget();
155    var v = e.getNumValue();
156   
157    if (isFinite(v)) {
158        this.plasma.B = v;
159        this.updateGUI();
160    }
161}
162
163function viewMenuCB(ev)
164{
165    var explorer_is_seen;
166   
167    if (this.entity_tree.isSeeable()) {
168        explorer_is_seen = true;
169    } else {
170        explorer_is_seen = false;
171    }
172   
173    this.showSectionsButton.setEnabled(explorer_is_seen);
174    this.showSpeciesButton.setEnabled(explorer_is_seen);
175    this.redrawButton.setEnabled(this.canvas.isSeeable());
176
177    if (this.prefs.autoLoadWiki) {
178        this.loadWikiButton.setEnabled(false);
179    } else {
180        var tree = this.entity_tree;
181        var leaf = getSingleTreeSelectedItem(tree);
182        if (leaf && leaf.classname == "qx.ui.tree.TreeFile" && explorer_is_seen) {
183            this.loadWikiButton.setEnabled(true);
184        } else {
185            this.loadWikiButton.setEnabled(false);
186        }
187    }
188}
189
190function editMenuCB(ev)
191{
192    var explorer_is_seen;
193   
194    if (this.entity_tree.isSeeable()) {
195        explorer_is_seen = true;
196    } else {
197        explorer_is_seen = false;
198    }
199
200    var tree = this.entity_tree;
201    var leaf = getSingleTreeSelectedItem(tree);
202
203    if (leaf && leaf.classname == "qx.ui.tree.TreeFile" && explorer_is_seen) {
204        if (this.isFavorite(leaf)) {
205            this.editMenuButtonAddToFav.setEnabled(false);
206            this.editMenuButtonRemFromFav.setEnabled(true);
207        } else {
208            this.editMenuButtonAddToFav.setEnabled(true);
209            this.editMenuButtonRemFromFav.setEnabled(false);
210        }
211    } else {
212        this.editMenuButtonAddToFav.setEnabled(false);
213        this.editMenuButtonRemFromFav.setEnabled(false);
214    }
215}
216
217function getSingleTreeSelectedItem(tree)
218{
219    var sels = tree.getSelection();
220    if (sels && sels.length == 1) {
221        return sels[0];
222    } else {
223        return null;
224    }
225}
226
227function treeMenuCB(ev)
228{
229    if (ev.getButton() == "right") {
230        var menu = this.treeMenu;
231
232        if (menu.isSeeable()) {
233            menu.hide();
234        } else {
235            var w = ev.getTarget();
236            var leaf = null;
237            if (w.classname == "qx.ui.tree.TreeFile") {
238                leaf = w;
239            } else
240            if (w.getLayoutParent().classname == "qx.ui.tree.TreeFile") {
241                leaf = w.getLayoutParent();
242            }
243           
244            if (leaf) {
245                if (this.isFavorite(leaf)) {
246                    this.treeMenuButtonAddToFav.setEnabled(false);
247                    this.treeMenuButtonRemFromFav.setEnabled(true);
248                } else {
249                    this.treeMenuButtonAddToFav.setEnabled(true);
250                    this.treeMenuButtonRemFromFav.setEnabled(false);
251                }
252            } else {
253                this.treeMenuButtonAddToFav.setEnabled(false);
254                this.treeMenuButtonRemFromFav.setEnabled(false);
255            }
256           
257            // position & show the menu
258            menu.placeToMouse(ev);
259            menu.show();
260        };
261
262        // ev.stopPropagation();
263    }
264}
265
266function showFundamentalCB(ev)
267{
268    this.showFundamental = !this.showFundamental;
269    this.rePopulateTree();
270}
271
272function showSpectroscopyCB(ev)
273{
274    this.showSpectroscopy = !this.showSpectroscopy;
275    this.rePopulateTree();
276}
277
278function showWavesCB(ev)
279{
280    this.showWaves = !this.showWaves;
281    this.rePopulateTree();
282}
283
284function showCollisionsCB(ev)
285{
286    this.showCollisions = !this.showCollisions;
287    this.rePopulateTree();
288}
289
290function showRadiationCB(ev)
291{
292    this.showRadiation = !this.showRadiation;
293    this.rePopulateTree();
294}
295
296function showElectronsCB(ev)
297{
298    this.showElectrons = !this.showElectrons;
299    this.rePopulateTree();
300}
301
302function showIonsCB(ev)
303{
304    this.showIons = !this.showIons;
305    this.rePopulateTree();
306}
307
308function showRadiatorsCB(ev)
309{
310    this.showRadiators = !this.showRadiators;
311    this.rePopulateTree();
312}
313
314function addToFavCB(ev)
315{
316    var tree = this.entity_tree;
317    var leaf = getSingleTreeSelectedItem(tree);
318
319    if (!leaf) {
320        return;
321    }
322
323    leaf.setTextColor(this.leafFavColor);
324
325    // Add to the list of favorites
326    var fav = new Object;
327    fav.entity = leaf.getUserData("entity");
328    fav.s1     = leaf.getUserData("s1");
329    fav.s2     = leaf.getUserData("s2");
330    fav.color  = this.nextColor();
331    this.favorites.push(fav);
332   
333    // Switch the dimension selector ...
334    this.gui_compare_dim.selectByValue(fav.entity.dimension);
335    // ... and update the list of favorites
336    this.updateFavoritesListView();
337    this.updateLegendListView();
338   
339    this.saveFavorites();
340}
341
342function removeFromFavCB(ev)
343{
344    var tree = this.entity_tree;
345    var leaf = getSingleTreeSelectedItem(tree);
346
347    if (!leaf) {
348        return;
349    }
350    leaf.setTextColor(this.leafColor);
351
352    var entity = leaf.getUserData("entity");
353    var s1     = leaf.getUserData("s1");
354    var s2     = leaf.getUserData("s2");
355
356    // Remove from the list of favorites
357    for (var k = 0; k < this.favorites.length; k++) {
358        var fav = this.favorites[k];
359        if (fav.entity  == entity && fav.s1 == s1 && fav.s2 == s2) {
360            this.favorites.splice(k, 1);
361            break;
362        }
363    }
364
365    // Switch the dimension selector ...
366    this.gui_compare_dim.selectByValue(entity.dimension);
367    // ... and update the list of favorites
368    this.updateFavoritesListView();
369    this.updateLegendListView();
370   
371    this.saveFavorites();
372}
373
374function clickTreeCB(ev)
375{
376    var tree = ev.getTarget();
377    var e = getSingleTreeSelectedItem(tree);
378    if (e) {
379        var entity = e.getUserData("entity");
380       
381        if (entity) {
382            this.gui_entity_units.update(entity.dimension,
383                this.prefs.units[entity.dimension]);
384        } else {
385            this.gui_entity_units.update(null, null);
386        }
387       
388        this.updateEntityValue();
389    }
390}
391
392function changeUnitsCB(ev)
393{
394    this.updateEntityValue();
395}
396
397/**
398 * The application
399 */
400qx.Class.define("pf.Application",
401{
402    extend : qx.application.Standalone,
403
404    /*
405    *****************************************************************************
406       MEMBERS
407    *****************************************************************************
408    */
409
410    members :
411    {
412        showFundamental  : true,
413        showSpectroscopy : true,
414        showWaves        : true,
415        showCollisions   : true,
416        showRadiation    : true,
417
418        showElectrons  : true,
419        showIons       : true,
420        showRadiators  : true,
421       
422        leafColor      : "black",
423        leafFavColor   : "red",
424       
425        plasma : null,
426
427        updatePlasmaParameters : function()
428        {
429            return this.plasma.updateParameters();
430        },
431       
432        updateGUI : function()
433        {
434            if (this.gui_locked) {
435                return;
436            }
437           
438            this.gui_locked = true;
439           
440            if (this.prefs.currentConfigName) {
441                this.gui_configName.setLabel(this.prefs.currentConfigName);
442            }
443           
444            this.gui_N_e.setNumValue(this.plasma.e.getN());
445            this.gui_T_e.setNumValue(this.plasma.e.getT());
446           
447            this.gui_N_i.setNumValue(this.plasma.i.getN());
448            this.gui_T_i.setNumValue(this.plasma.i.getT());
449            this.gui_Z_i.setValue(this.plasma.i.getQ());
450            this.gui_M_i.setNumValue(this.plasma.i.getM());
451
452            this.gui_P_r.setValue(100*this.plasma.P_r);
453           
454            this.gui_N_r.setNumValue(this.plasma.r.getN());
455            this.gui_T_r.setNumValue(this.plasma.r.getT());
456            this.gui_Z_r.setValue(this.plasma.r.getQ());
457            this.gui_Zcore.setValue((this.plasma.r.getQ() + 1) + '');
458            this.gui_M_r.setNumValue(this.plasma.r.getM());
459           
460            this.gui_B.setNumValue(this.plasma.B);
461           
462            this.gui_n_u.setValue(this.plasma.n_u);
463            this.gui_n_l.setValue(this.plasma.n_l);
464           
465            // Update the currently selected entity
466            this.updateEntityValue();
467           
468            // Update the list of favorites
469            this.updateFavoritesListView();
470            this.updateLegendListView();
471           
472            this.gui_locked = false;
473        },
474       
475
476        getSpeciesName : function(species) {
477            var name;
478           
479            switch (species.id) {
480            case "e":
481                name = "electrons";
482                break;
483            case "i":
484                name = "ions";
485                break;
486            case "r":
487                name = "radiators";
488                break;
489            default:
490                name = null;
491                break;
492            }
493           
494            return name;
495        },
496       
497        getEntityFullName : function(entity, s1, s2)
498        {
499            var name = entity.name;
500            switch (entity.nspecies) { 
501            case 2:
502                name += " (" + this.getSpeciesName(s1) + "/" +
503                               this.getSpeciesName(s2) + ")";
504                break;
505            case 1:
506                var prepos = entity.prepos;
507                if (!prepos) {
508                    prepos = "of";
509                }
510                name += " " + prepos + " " + this.getSpeciesName(s1);
511                break;
512            default:
513                break;
514            }
515           
516            return name;
517        },
518       
519        evaluateEntityValue : function(entity, s1, s2)
520        {
521            var formula;
522            switch (entity.nspecies) {
523            case 1:
524                var s1_str = "this.plasma." + s1.id;
525                formula = entity.formula.replace(/\%s1/g, s1_str);
526                break;
527            case 2:
528                var s1_str = "this.plasma." + s1.id;
529                var s2_str = "this.plasma." + s2.id;
530                formula = entity.formula.replace(/\%s1/g, s1_str);
531                formula = formula.replace(/\%s2/g, s2_str);
532                break;
533            default:
534                formula = entity.formula;
535                break;
536            }
537            var v = eval(formula);
538           
539            return v;
540        },
541       
542        updateEntityValue : function()
543        {
544            var tree = this.entity_tree;
545            var leaf = getSingleTreeSelectedItem(tree);
546           
547            if (!leaf) {
548                return;
549            }
550           
551            var entity = leaf.getUserData("entity");
552            var s1     = leaf.getUserData("s1");
553            var s2     = leaf.getUserData("s2");
554           
555            var name, section, value;
556            if (entity) {
557                var v     = this.evaluateEntityValue(entity, s1, s2);
558                var scale = this.gui_entity_units.getSelectedValue();
559               
560                name    = this.getEntityFullName(entity, s1, s2);
561                section = entity.section;
562                value   = v*scale
563            } else {
564                name    = null;
565                section = null;
566                value   = 0;
567            }
568           
569            this.gui_entity_name.setValue(name);
570
571            this.gui_entity_section.setValue(section);
572
573            if (isFinite(value)) {
574                this.gui_entity_value.setNumValue(value);
575            } else {
576                this.gui_entity_value.setValue("");
577            }
578           
579            if (this.prefs.autoLoadWiki) {
580                this.showWikiPage(entity);
581            } else {
582                this.showWikiPage(null);
583            }
584        },
585
586        isFavorite : function(leaf)
587        {
588            var entity = leaf.getUserData("entity");
589            var s1     = leaf.getUserData("s1");
590            var s2     = leaf.getUserData("s2");
591
592            for (var k = 0; k < this.favorites.length; k++) {
593                var fav = this.favorites[k];
594                if (fav.entity  == entity && fav.s1 == s1 && fav.s2 == s2) {
595                    return true;
596                    break;
597                }
598            }
599           
600            return false;
601        },
602       
603        addEntityLeaf : function(entity, s1, s2)
604        {
605            var icon;
606           
607            if (s1 && s2) {
608                icon = "pf/image/" + s1.id + s2.id + "_small.png";
609            } else
610            if (s1) {
611                icon = "pf/image/" + s1.id + "_small.png";
612            } else {
613                icon = "pf/image/all_small.png";
614            }
615           
616            var leaf = new qx.ui.tree.TreeFile(entity.name);
617            leaf.setIcon(icon);
618            leaf.addListener("contextmenu", treeMenuCB, this);
619
620            leaf.setUserData("entity", entity);
621            leaf.setUserData("s1", s1);
622            leaf.setUserData("s2", s2);
623
624            if (this.isFavorite(leaf)) {
625                leaf.setTextColor(this.leafFavColor);
626            } else {
627                leaf.setTextColor(this.leafColor);
628            }
629           
630            return leaf;
631        },
632
633        populateTree : function()
634        {
635            var n = plasma_entities.length;
636            var sa = new Array;
637            if (this.showElectrons) {
638                sa.push(this.plasma.e)
639            }
640            if (this.showIons) {
641                sa.push(this.plasma.i)
642            }
643            if (this.showRadiators) {
644                sa.push(this.plasma.r)
645            }
646           
647            for (var i = 0; i < n; i++) {
648                var entity = plasma_entities[i];
649               
650                if (entity.section == "fundamental" &&
651                    this.showFundamental != true) {
652                    continue;
653                }
654                if (entity.section == "spectroscopy" &&
655                    this.showSpectroscopy != true) {
656                    continue;
657                }
658                if (entity.section == "waves" &&
659                    this.showWaves != true) {
660                    continue;
661                }
662                if (entity.section == "collisions" &&
663                    this.showCollisions != true) {
664                    continue;
665                }
666                if (entity.section == "radiation" &&
667                    this.showRadiation != true) {
668                    continue;
669                }
670               
671                var folder;
672                switch (entity.dimension) {
673                case "frequency":
674                    folder = this.gui_folder_freq;
675                    break;
676                case "length":
677                    folder = this.gui_folder_length;
678                    break;
679                case "velocity":
680                    folder = this.gui_folder_vel;
681                    break;
682                case "energy":
683                    folder = this.gui_folder_energy;
684                    break;
685                case "mass_density":
686                    folder = this.gui_folder_mass_density;
687                    break;
688                case "pressure":
689                    folder = this.gui_folder_pressure;
690                    break;
691                case "area":
692                    folder = this.gui_folder_area;
693                    break;
694                case "power_density":
695                    folder = this.gui_folder_power_density;
696                    break;
697                case "spectral_power_density":
698                    folder = this.gui_folder_spectral_power_density;
699                    break;
700                case "efield":
701                    folder = this.gui_folder_efield;
702                    break;
703                case "none":
704                    folder = this.gui_folder_none;
705                    break;
706                default:
707                    continue;
708                    break;
709                }
710               
711                var leaf;
712               
713                switch (entity.nspecies) {
714                case 1:
715                    for (var j = 0; j < sa.length; j++) {
716                        var s = sa[j];
717                        leaf = this.addEntityLeaf(entity, s, null);
718                        folder.add(leaf);
719                    }
720                    break;
721                case 2:
722                    for (var j = 0; j < sa.length; j++) {
723                        var s1 = sa[j];
724                        for (var k = j; k < sa.length; k++) {
725                            var s2 = sa[k];
726                            leaf = this.addEntityLeaf(entity, s1, s2);
727                            folder.add(leaf);
728                        }
729                    }
730                    break;
731                default:
732                    leaf = this.addEntityLeaf(entity, null, null);
733                    folder.add(leaf);
734                    break;
735                }
736            }
737        }, 
738
739        cleanTree : function()
740        {
741            this.gui_folder_freq.removeAll();
742           
743            this.gui_folder_length.removeAll();
744           
745            this.gui_folder_vel.removeAll();
746           
747            this.gui_folder_none.removeAll();
748           
749            this.gui_folder_energy.removeAll();
750           
751            this.gui_folder_mass_density.removeAll();
752
753            this.gui_folder_pressure.removeAll();
754           
755            this.gui_folder_area.removeAll();
756           
757            this.gui_folder_power_density.removeAll();
758
759            this.gui_folder_spectral_power_density.removeAll();
760           
761            this.gui_folder_efield.removeAll();
762        },
763
764        rePopulateTree : function()
765        {
766            this.cleanTree();
767           
768            this.populateTree();
769        },
770
771
772        updateFavoritesListView : function()
773        {
774            var lv = this.favoritesListView;
775            var tm = lv.getTableModel();
776           
777            var dimension = this.gui_compare_dim.getSelectedValue();
778           
779            var scale = this.gui_compare_units.getSelectedValue();
780           
781            var rowData = new Array();
782           
783            for (var i = 0; i < this.favorites.length; i++) {
784                var fav = this.favorites[i];
785                var entity = fav.entity;
786               
787                if (entity.dimension != dimension) {
788                    continue;
789                }
790               
791                var s1 = fav.s1;
792                var s2 = fav.s2;
793
794                var icon;
795                if (s1 && s2) {
796                    icon = "pf/image/" + s1.id + s2.id + "_small.png";
797                } else
798                if (s1) {
799                    icon = "pf/image/" + s1.id + "_small.png";
800                } else {
801                    icon = "pf/image/all_small.png";
802                }
803                var name = this.getEntityFullName(entity, s1, s2);
804                var value = scale*this.evaluateEntityValue(entity, s1, s2);
805
806                rowData.push([icon, name, entity.section,
807                    pf.util.Format.numPrint(value)]);
808            }
809           
810            tm.setData(rowData, false);
811            var sidx = tm.getSortColumnIndex();
812            tm.sortByColumn(sidx, tm.isSortAscending());
813           
814            lv.updateContent();
815            // lv.updateSort();
816            // lv.update();
817        },
818
819        updateLegendListView : function()
820        {
821            var lv = this.legendListView;
822            var tm = lv.getTableModel();
823
824            var rowData = new Array();
825           
826            var dimension = this.gui_compare_dim.getSelectedValue();
827           
828            for (var i = 0; i < this.favorites.length; i++) {
829                var fav = this.favorites[i];
830                var entity = fav.entity;
831               
832                if (entity.dimension != dimension) {
833                    continue;
834                }
835               
836                var s1    = fav.s1;
837                var s2    = fav.s2;
838
839                var name  = this.getEntityFullName(entity, s1, s2);
840                var color = fav.color;
841
842                rowData.push({"color": color, "name": name, "favorite": fav});
843            }
844           
845            tm.setDataAsMapArray(rowData);
846            // lv.updateContent();
847        },
848
849
850        renderTabPage : function(label, icon, checked)
851        {
852            var page_id;
853           
854            page_id = new qx.ui.tabview.Page(label, icon);
855            this.tabview.add(page_id, {height: "100%"});
856
857            if (checked) {
858                this.tabview.setSelection(page_id);
859            }
860           
861            return page_id;
862        },
863
864        renderParametersTab : function()
865        {
866            var fr, gl, rc, rc1, rc2;
867           
868            var page_id = this.renderTabPage("Parameters",
869                "pf/image/tab-parameters.png", true);
870            page_id.setLayout(new qx.ui.layout.VBox(10));
871
872            fr = new qx.ui.groupbox.GroupBox("Configuration name",
873                "pf/image/info.png");
874            fr.setLayout(new qx.ui.layout.VBox());
875
876            this.gui_configName =
877                new qx.ui.basic.Atom(this.prefs.currentConfigName);
878            this.gui_configName.setRich(true)
879            fr.add(this.gui_configName);
880            page_id.add(fr);
881           
882
883            rc = new qx.ui.container.Composite(new qx.ui.layout.HBox(10));
884            page_id.add(rc);
885           
886            rc1 = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
887            rc.add(rc1, {flex : 1});
888           
889            rc2 = new qx.ui.container.Composite(new qx.ui.layout.VBox(27));
890            rc.add(rc2, {flex : 1});
891           
892           
893            fr = new qx.ui.groupbox.GroupBox("Electrons",
894                "pf/image/e_small.png");
895            fr.setLayout(new qx.ui.layout.VBox());
896
897            rc1.add(fr);
898
899            var layout = new qx.ui.layout.Grid(4, 6);
900            layout.setColumnWidth(0, 80);
901            layout.setColumnFlex(1, 1);
902            gl = new qx.ui.container.Composite(layout);
903
904            fr.add(gl);
905
906            var l, e, au_fn, au_fT;
907           
908            au_fn = pf.base.Bohr.n0;
909            au_fT = pf.base.Bohr.E0;
910
911            // N_e
912            l = new qx.ui.basic.Label("N<sub>e</sub> (cm<sup>-3</sup>):");
913            l.setRich(true);
914            gl.add(l, {row: 0, column: 0});
915            e = new pf.ui.TextField(this.plasma.e.getN(), au_fn);
916            gl.add(e, {row: 0, column: 1});
917            e.addListener("changeValue", changeN_e, this);
918            this.gui_N_e = e;
919
920            // T_e
921            l = new qx.ui.basic.Label("T<sub>e</sub> (eV):");
922            l.setRich(true);
923            gl.add(l, {row: 1, column: 0});
924            e = new pf.ui.TextField(this.plasma.e.getT(), au_fT);
925            gl.add(e, {row: 1, column: 1});
926            e.addListener("changeValue", changeT_e, this);
927            this.gui_T_e = e;
928           
929            fr = new qx.ui.groupbox.GroupBox("Ions",
930                "pf/image/i_small.png");
931            fr.setLayout(new qx.ui.layout.VBox());
932
933            rc1.add(fr);
934
935            layout = new qx.ui.layout.Grid(4, 6);
936            layout.setColumnWidth(0, 80);
937            layout.setColumnFlex(1, 1);
938            gl = new qx.ui.container.Composite(layout);
939
940            fr.add(gl);
941
942            // Z_i
943            l = new qx.ui.basic.Label("Z<sub>i</sub>:");
944            l.setRich(true);
945            gl.add(l, {row: 0, column: 0});
946            e = new qx.ui.form.Spinner(1, this.plasma.i.getQ(), 100);
947            gl.add(e, {row: 0, column: 1});
948            e.addListener("changeValue", changeZ_i, this);
949            this.gui_Z_i = e;
950           
951            // M_i
952            l = new qx.ui.basic.Label("M<sub>i</sub>:");
953            l.setRich(true);
954            gl.add(l, {row: 1, column: 0});
955            e = new pf.ui.TextField(this.plasma.i.getM(), 1/pf.base.Bohr.m_p);
956            gl.add(e, {row: 1, column: 1});
957            e.addListener("changeValue", changeM_i, this);
958            this.gui_M_i = e;
959           
960            // T_i
961            l = new qx.ui.basic.Label("T<sub>i</sub> (eV):");
962            l.setRich(true);
963            gl.add(l, {row: 2, column: 0});
964            e = new pf.ui.TextField(this.plasma.i.getT(), au_fT);
965            gl.add(e, {row: 2, column: 1});
966            e.addListener("changeValue", changeT_i, this);
967            this.gui_T_i = e;
968
969            // N_i
970            l = new qx.ui.basic.Label("N<sub>i</sub> (cm<sup>-3</sup>):");
971            l.setRich(true);
972            gl.add(l, {row: 3, column: 0});
973            e = new pf.ui.TextField(this.plasma.i.getN(), au_fn);
974            gl.add(e, {row: 3, column: 1});
975            e.setReadOnly(true);
976            this.gui_N_i = e;
977           
978            fr = new qx.ui.groupbox.GroupBox("Radiators",
979                "pf/image/r_small.png");
980            fr.setLayout(new qx.ui.layout.VBox());
981
982            rc2.add(fr);
983
984            layout = new qx.ui.layout.Grid(4, 6);
985            layout.setColumnWidth(0, 80);
986            layout.setColumnFlex(1, 1);
987            gl = new qx.ui.container.Composite(layout);
988
989            fr.add(gl);
990
991            // Z_r
992            l = new qx.ui.basic.Label("Z<sub>r</sub>:");
993            l.setRich(true);
994            gl.add(l, {row: 0, column: 0});
995            e = new qx.ui.form.Spinner(0, this.plasma.r.getQ(), 100);
996            gl.add(e, {row: 0, column: 1});
997            e.addListener("changeValue", changeZ_r, this);
998            this.gui_Z_r = e;
999
1000            // M_r
1001            l = new qx.ui.basic.Label("M<sub>r</sub>:");
1002            l.setRich(true);
1003            gl.add(l, {row: 1, column: 0});
1004            e = new pf.ui.TextField(this.plasma.r.getM(), 1/pf.base.Bohr.m_p);
1005            gl.add(e, {row: 1, column: 1});
1006            e.addListener("changeValue", changeM_r, this);
1007            this.gui_M_r = e;
1008
1009            // T_r
1010            l = new qx.ui.basic.Label("T<sub>r</sub> (eV):");
1011            l.setRich(true);
1012            gl.add(l, {row: 2, column: 0});
1013            e = new pf.ui.TextField(this.plasma.r.getT(), au_fT);
1014            gl.add(e, {row: 2, column: 1});
1015            e.addListener("changeValue", changeT_r, this);
1016            this.gui_T_r = e;
1017
1018            // P_r
1019            l = new qx.ui.basic.Label("P<sub>r</sub> (%):");
1020            l.setRich(true);
1021            gl.add(l, {row: 3, column: 0});
1022            e = new qx.ui.form.Spinner(0, 100*this.plasma.P_r, 100);
1023            gl.add(e, {row: 3, column: 1});
1024            e.addListener("changeValue", changeP_r, this);
1025            this.gui_P_r = e;
1026
1027            // N_r
1028            l = new qx.ui.basic.Label("N<sub>r</sub> (cm<sup>-3</sup>):");
1029            l.setRich(true);
1030            gl.add(l, {row: 4, column: 0});
1031            e = new pf.ui.TextField(this.plasma.r.getN(), au_fn);
1032            e.setReadOnly(true);
1033            gl.add(e, {row: 4, column: 1});
1034            this.gui_N_r = e;
1035
1036
1037            fr = new qx.ui.groupbox.GroupBox("Fields",
1038                "pf/image/field_small.png");
1039            fr.setLayout(new qx.ui.layout.VBox());
1040
1041            rc1.add(fr);
1042
1043            layout = new qx.ui.layout.Grid(4, 6);
1044            layout.setColumnWidth(0, 80);
1045            layout.setColumnFlex(1, 1);
1046            gl = new qx.ui.container.Composite(layout);
1047
1048            fr.add(gl);
1049
1050
1051            l = new qx.ui.basic.Label("B (T):");
1052            l.setRich(true);
1053            gl.add(l, {row: 0, column: 0});
1054            e = new pf.ui.TextField(this.plasma.B, pf.base.Bohr.B0);
1055            gl.add(e, {row: 0, column: 1});
1056            e.addListener("changeValue", changeB, this);
1057            this.gui_B = e;
1058
1059            // Atomic system frame
1060            fr = new qx.ui.groupbox.GroupBox("Atomic system",
1061                "pf/image/all_small.png");
1062            fr.setLayout(new qx.ui.layout.VBox());
1063
1064            rc2.add(fr);
1065
1066            layout = new qx.ui.layout.Grid(4, 6);
1067            layout.setColumnWidth(0, 80);
1068            layout.setColumnFlex(1, 1);
1069            gl = new qx.ui.container.Composite(layout);
1070
1071            fr.add(gl);
1072
1073            l = new qx.ui.basic.Label("Z<sub>core</sub>:");
1074            l.setRich(true);
1075            gl.add(l, {row: 0, column: 0});
1076            e = new qx.ui.form.TextField((this.plasma.r.getQ() + 1) + '');
1077            e.setReadOnly(true);
1078            gl.add(e, {row: 0, column: 1});
1079            this.gui_Zcore = e;
1080
1081            l = new qx.ui.basic.Label("n<sub>u</sub>:");
1082            l.setRich(true);
1083            gl.add(l, {row: 1, column: 0});
1084            e = new qx.ui.form.Spinner(this.plasma.n_l + 1, this.plasma.n_u, 1000);
1085            gl.add(e, {row: 1, column: 1});
1086            e.addListener("changeValue", changeN_u, this);
1087            this.gui_n_u = e;
1088
1089            l = new qx.ui.basic.Label("n<sub>l</sub>:");
1090            l.setRich(true);
1091            gl.add(l, {row: 2, column: 0});
1092            e = new qx.ui.form.Spinner(1, this.plasma.n_l, this.plasma.n_u - 1);
1093            gl.add(e, {row: 2, column: 1});
1094            e.addListener("changeValue", changeN_l, this);
1095            this.gui_n_l = e;
1096        },
1097
1098        renderExplorerTab : function()
1099        {
1100            var page_id = this.renderTabPage("Explorer",
1101                "pf/image/tab-explorer.png", false);
1102            page_id.setLayout(new qx.ui.layout.VBox);
1103
1104            var sp = new qx.ui.splitpane.Pane("horizontal");
1105            sp.setDecorator("main");
1106            page_id.add(sp, {height: "100%"});
1107           
1108            // Create container with fixed dimensions for the left:
1109            var left_pane = new qx.ui.container.Composite(new qx.ui.layout.Grow).set({
1110              width: 250
1111            });
1112
1113            // Create container for the right:
1114            var right_pane = new qx.ui.container.Composite(new qx.ui.layout.VBox(4)).set({
1115              padding : 4
1116            });
1117
1118            sp.add(left_pane,  0, {flex: 1});
1119            sp.add(right_pane, 1, {flex: 2});
1120
1121           
1122            var tree = new qx.ui.tree.Tree("Browser");
1123            tree.setDecorator(null);
1124            left_pane.add(tree);
1125           
1126            this.entity_tree = tree;
1127           
1128            var folder;
1129           
1130            var root = new qx.ui.tree.TreeFolder("Root");
1131            root.setOpen(true);
1132            tree.setRoot(root);
1133            tree.setHideRoot(true);
1134            tree.setRootOpenClose(true);
1135            tree.setOpenMode("dblclick");
1136
1137            tree.addListener("changeSelection", clickTreeCB, this);
1138           
1139            folder = new qx.ui.tree.TreeFolder("Dimensionless");
1140            root.add(folder);
1141            this.gui_folder_none = folder;
1142
1143            folder = new qx.ui.tree.TreeFolder("Length");
1144            root.add(folder);
1145            this.gui_folder_length = folder;
1146           
1147            folder = new qx.ui.tree.TreeFolder("Frequency");
1148            root.add(folder);
1149            this.gui_folder_freq = folder;
1150
1151            folder = new qx.ui.tree.TreeFolder("Velocity");
1152            root.add(folder);
1153            this.gui_folder_vel = folder;
1154           
1155            folder = new qx.ui.tree.TreeFolder("Area");
1156            root.add(folder);
1157            this.gui_folder_area = folder;
1158
1159            folder = new qx.ui.tree.TreeFolder("Mass density");
1160            root.add(folder);
1161            this.gui_folder_mass_density = folder;
1162
1163            folder = new qx.ui.tree.TreeFolder("Energy");
1164            root.add(folder);
1165            this.gui_folder_energy = folder;
1166
1167            folder = new qx.ui.tree.TreeFolder("Pressure");
1168            root.add(folder);
1169            this.gui_folder_pressure = folder;
1170
1171            folder = new qx.ui.tree.TreeFolder("Power density");
1172            root.add(folder);
1173            this.gui_folder_power_density = folder;
1174
1175            folder = new qx.ui.tree.TreeFolder("Power spectral density");
1176            root.add(folder);
1177            this.gui_folder_spectral_power_density = folder;
1178
1179            folder = new qx.ui.tree.TreeFolder("Electric field");
1180            root.add(folder);
1181            this.gui_folder_efield = folder;
1182
1183           
1184
1185            this.populateTree();
1186
1187            // Build context-sensitive popup menu
1188            this.treeMenu = new qx.ui.menu.Menu;
1189            var button;
1190           
1191            button = new qx.ui.menu.Button("Add to Favorites",
1192                "pf/image/favorite-add.png");
1193            button.addListener("execute", addToFavCB, this);
1194            this.treeMenu.add(button);
1195            this.treeMenuButtonAddToFav = button;
1196            button = new qx.ui.menu.Button("Remove from Favorites",
1197                "pf/image/favorite-delete.png");
1198            button.addListener("execute", removeFromFavCB, this);
1199            this.treeMenu.add(button);
1200            this.treeMenuButtonRemFromFav = button;
1201           
1202            this.doc.add(this.treeMenu);
1203
1204
1205            var layout = new qx.ui.layout.Grid(4, 6);
1206            layout.setColumnFlex(0, 3);
1207            layout.setColumnFlex(1, 12);
1208            layout.setColumnFlex(2, 4);
1209            layout.setColumnMinWidth(0,  50);
1210            layout.setColumnMaxWidth(2, 150);
1211            var gl = new qx.ui.container.Composite(layout);
1212           
1213            var l, e;
1214           
1215
1216            l = new qx.ui.basic.Label("Name:");
1217            gl.add(l, {row: 0, column: 0});
1218            e = new qx.ui.form.TextField();
1219            e.setReadOnly(true);
1220            this.gui_entity_name = e;
1221            gl.add(e, {row: 0, column: 1, colSpan: 2});
1222
1223            l = new qx.ui.basic.Label("Value:");
1224            gl.add(l, {row: 1, column: 0});
1225            e = new pf.ui.TextField("");
1226            e.setReadOnly(true);
1227            gl.add(e, {row: 1, column: 1});
1228            this.gui_entity_value = e;
1229
1230            e = new pf.UnitSelector();
1231            e.addListener("changeSelection", changeUnitsCB, this);
1232            gl.add(e, {row: 1, column: 2});
1233            this.gui_entity_units = e;
1234
1235            l = new qx.ui.basic.Label("Section:");
1236            gl.add(l, {row: 2, column: 0});
1237            e = new qx.ui.form.TextField();
1238            e.setReadOnly(true);
1239            this.gui_entity_section = e;
1240            gl.add(e, {row: 2, column: 1, colSpan: 2});
1241
1242            right_pane.add(gl);
1243
1244            var fr = new qx.ui.groupbox.GroupBox("Wikipedia article",
1245                "pf/image/wikipedia.png");
1246            fr.setLayout(new qx.ui.layout.Grow());
1247           
1248            var iframe = new qx.ui.embed.Iframe();
1249            iframe.addListener("load", function(ev) {
1250                    this.setCursor("default");
1251                });
1252           
1253            fr.add(iframe);
1254            right_pane.add(fr, {flex: 1});
1255           
1256            this.gui_wiki = iframe;
1257        },
1258       
1259        renderCompareTab : function()
1260        {
1261            var page_id = this.renderTabPage("Compare",
1262                "pf/image/tab-compare.png");
1263            page_id.setLayout(new qx.ui.layout.VBox(1));
1264           
1265            var bl = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
1266            page_id.add(bl, {height: "100%"});
1267           
1268            var rc = new qx.ui.container.Composite(new qx.ui.layout.HBox(10));
1269            bl.add(rc);
1270
1271            var l, e;
1272            l = new qx.ui.basic.Label("Dimension:");
1273            rc.add(l);
1274            e = new pf.ui.SelectBox;
1275            e.addItem("None", "none");
1276            e.addItem("Length", "length");
1277            e.addItem("Frequency", "frequency");
1278            e.addItem("Velocity", "velocity");
1279            e.addItem("Area", "area");
1280            e.addItem("Energy", "energy");
1281            e.addItem("Mass density", "mass_density");
1282            e.addItem("Pressure", "pressure");
1283            e.addItem("Power density", "power_density");
1284            e.addItem("Power spectral density", "spectral_power_density");
1285            e.addItem("Electric field", "efield");
1286            e.addListener("changeSelection", function(ev) {
1287                    var dimension = this.gui_compare_dim.getSelectedValue();
1288                    this.gui_compare_units.update(dimension,
1289                        this.prefs.units[dimension]);
1290                    this.updateFavoritesListView();
1291                    this.updateLegendListView();
1292                }, this);
1293            rc.add(e);
1294            this.gui_compare_dim = e;
1295           
1296            l = new qx.ui.basic.Label("Units:");
1297            rc.add(l);
1298            e = new pf.UnitSelector();
1299            e.update("none");
1300            e.addListener("changeSelection", function(ev) {
1301                    this.updateFavoritesListView();
1302                }, this);
1303            rc.add(e);
1304            this.gui_compare_units = e;
1305
1306            // table model
1307            var tm = new qx.ui.table.model.Simple();
1308            tm.setColumns([ "", "Name", "Section", "Value" ]);
1309           
1310            tm.setColumnEditable(0, false);
1311            tm.setColumnEditable(1, false);
1312            tm.setColumnEditable(2, false);
1313            tm.setColumnEditable(3, false);
1314           
1315            tm.setColumnSortable(0, false);
1316           
1317            tm.setSortMethods(3, function(row1, row2) {
1318                var obj1 = parseFloat(row1[arguments.callee.columnIndex]);
1319                var obj2 = parseFloat(row2[arguments.callee.columnIndex]);
1320                return (obj1 > obj2) ? 1 : ((obj1 == obj2) ? 0 : -1);
1321            });
1322           
1323            // table list
1324            var lv = new qx.ui.table.Table(tm);
1325
1326            lv.setStatusBarVisible(false);
1327            lv.setShowCellFocusIndicator(false);
1328            lv.setColumnVisibilityButtonVisible(false);
1329           
1330            lv.setColumnWidth(0,  24);
1331            lv.setColumnWidth(1, 300);
1332            lv.setColumnWidth(2, 120);
1333           
1334            var renderer = new qx.ui.table.cellrenderer.Image(16, 16);
1335            lv.getTableColumnModel().setDataCellRenderer(0, renderer);
1336
1337            bl.add(lv, {flex: 1});
1338           
1339            this.favoritesListView = lv;
1340        },
1341       
1342        drawAll : function(ev)
1343        {
1344            var canvas = this.canvas;
1345           
1346            canvas.setPrintable(true);
1347           
1348            var pname = this.guiParameter.getSelectedValue();
1349            var vmin = this.guiMinParam.getNumValue();
1350            var vmax = this.guiMaxParam.getNumValue();
1351            var npoints = this.guiParamPoints.getValue();
1352           
1353            if (npoints < 2 || !pname) {
1354                return;
1355            }
1356
1357            var dimension = this.gui_compare_dim.getSelectedValue();
1358            var scale = this.gui_compare_units.getSelectedValue();
1359
1360            var par0, au_f;
1361            var xlabel, ylabel;
1362            if (dimension == "none") {
1363                ylabel = "";
1364            } else {
1365                ylabel = this.gui_compare_dim.getSelectedLabel() + " (" +
1366                         this.gui_compare_units.getSelectedLabel() + ")";
1367            }
1368            switch (pname) {
1369            case "N_e":
1370                par0 = this.plasma.e.getN();
1371                au_f = pf.base.Bohr.n0;
1372                xlabel = "N<sub>e</sub> (cm<sup>-3</sup>)"
1373                break;
1374            case "T":
1375                par0 = this.plasma.e.getT();
1376                if (par0 != this.plasma.i.getT()) {
1377                    this.msgWindow.error("Cannot vary T since T<sub>e</sub> &ne; T<sub>i</sub>");
1378                    return;
1379                }
1380                if (par0 != this.plasma.r.getT()) {
1381                    this.msgWindow.error("Cannot vary T since T<sub>e</sub> &ne; T<sub>r</sub>");
1382                    return;
1383                }
1384                au_f = pf.base.Bohr.E0;
1385                xlabel = "T (eV)"
1386                break;
1387            case "T_e":
1388                par0 = this.plasma.e.getT();
1389                au_f = pf.base.Bohr.E0;
1390                xlabel = "T<sub>e</sub> (eV)"
1391                break;
1392            case "T_i":
1393                par0 = this.plasma.i.getT();
1394                au_f = pf.base.Bohr.E0;
1395                xlabel = "T<sub>i</sub> (eV)"
1396                break;
1397            case "T_r":
1398                par0 = this.plasma.r.getT();
1399                au_f = pf.base.Bohr.E0;
1400                xlabel = "T<sub>r</sub> (eV)"
1401                break;
1402            case "T_i,r":
1403                par0 = this.plasma.i.getT();
1404                if (par0 != this.plasma.r.getT()) {
1405                    this.msgWindow.error("Cannot vary T<sub>i,r</sub> since T<sub>i</sub> &ne; T<sub>r</sub>");
1406                    return;
1407                }
1408                au_f = pf.base.Bohr.E0;
1409                xlabel = "T<sub>i,r</sub> (eV)"
1410                break;
1411            case "B":
1412                par0 = this.plasma.B;
1413                au_f = pf.base.Bohr.B0;
1414                xlabel = "B (T)"
1415                break;
1416            default:
1417                return;
1418            }
1419           
1420            if (par0 == 0) {
1421                this.msgWindow.error("Cannot vary a null parameter</sub>");
1422                return;
1423            }
1424            if (vmin >= vmax) {
1425                this.msgWindow.error("Min. scale must be less than max. one");
1426                return;
1427            }
1428            if (vmin <= 0) {
1429                this.msgWindow.error("Non-positive scale values are not allowed");
1430                return;
1431            }
1432           
1433            var x_au  = new Array;
1434            var xdata = new Array;
1435            for (var j = 0; j < npoints; j++) {
1436                var x = par0*(vmin + (vmax - vmin)*j/(npoints - 1));
1437                x_au.push(x);
1438                xdata.push(au_f*x);
1439            }
1440                       
1441            var wxmin = xdata[0];
1442            var wxmax = xdata[xdata.length - 1];
1443
1444            var wymin = 0;
1445            var wymax = 0;
1446
1447            var sets = new Array;
1448            var first = true;
1449            for (var i = 0; i < this.favorites.length; i++) {
1450                var fav = this.favorites[i];
1451                var entity = fav.entity;
1452               
1453                if (entity.dimension != dimension) {
1454                    continue;
1455                }
1456               
1457                var s1    = fav.s1;
1458                var s2    = fav.s2;
1459                var vname = this.getEntityFullName(entity, s1, s2);
1460
1461                var set   = new Object;
1462                var ydata = new Array;
1463                for (var j = 0; j < npoints; j++) {
1464                    var par = x_au[j];
1465
1466                    switch (pname) {
1467                    case "N_e":
1468                        this.plasma.e.setN(par);
1469                        this.updatePlasmaParameters();
1470                        break;
1471                    case "T_e":
1472                        this.plasma.e.setT(par);
1473                        break;
1474                    case "T_i":
1475                        this.plasma.i.setT(par);
1476                        break;
1477                    case "T_r":
1478                        this.plasma.r.setT(par);
1479                        break;
1480                    case "T_i,r":
1481                        this.plasma.i.setT(par);
1482                        this.plasma.r.setT(par);
1483                        break;
1484                    case "T":
1485                        this.plasma.e.setT(par);
1486                        this.plasma.i.setT(par);
1487                        this.plasma.r.setT(par);
1488                        break;
1489                    case "B":
1490                        this.plasma.B = par;
1491                        break;
1492                    }
1493                   
1494                    var value = scale*this.evaluateEntityValue(entity, s1, s2);
1495                   
1496                    if (first) {
1497                        wymin = value;
1498                        wymax = value;
1499                        first = false;
1500                    } else {
1501                        if (value < wymin) {
1502                            wymin = value;
1503                        }
1504                        if (value > wymax) {
1505                            wymax = value;
1506                        }
1507                    }
1508                   
1509                    ydata.push(value);
1510                }
1511                set.x = xdata;
1512                set.y = ydata;
1513                set.legend = vname;
1514                set.color = fav.color;
1515                sets.push(set);
1516            }
1517           
1518            // Restore parameter
1519            switch (pname) {
1520            case "N_e":
1521                this.plasma.e.setN(par0);
1522                this.updatePlasmaParameters();
1523                break;
1524            case "T_e":
1525                this.plasma.e.setT(par0);
1526                break;
1527            case "T_i":
1528                this.plasma.i.setT(par0);
1529                break;
1530            case "T_r":
1531                this.plasma.r.setT(par0);
1532                break;
1533            case "T_i,r":
1534                this.plasma.i.setT(par0);
1535                this.plasma.r.setT(par0);
1536                break;
1537            case "T":
1538                this.plasma.e.setT(par0);
1539                this.plasma.i.setT(par0);
1540                this.plasma.r.setT(par0);
1541                break;
1542            case "B":
1543                this.plasma.B = par0;
1544                break;
1545            }
1546           
1547            canvas.clear();
1548           
1549            canvas.setViewportCoordinates(0.15, 0.1, 0.9, 0.9);
1550            var dwx = Math.abs(wxmax - wxmin);
1551            if (dwx == 0) {
1552                dwx = wxmax;
1553            }
1554            var dwy = Math.abs(wymax - wymin);
1555            if (dwy == 0) {
1556                wymin = 0.0;
1557                if (wymax == 0) {
1558                    wymax = 1.0;
1559                } else {
1560                    wymax *= 2;
1561                }
1562            }
1563           
1564            // If Y max & min of the same sign and differ significantly, set
1565            // the smallest (by abs value) limit to 0
1566            var wymin_r, wymax_r;
1567            if (wymin > 0 && wymax/wymin > 3) {
1568                wymin_r = 0;
1569                wymax_r = wymax + 0.05*dwy;
1570            } else
1571            if (wymax < 0 && wymin/wymax > 3) {
1572                wymin_r = wymin - 0.05*dwy
1573                wymax_r = 0;
1574            } else {
1575                wymin_r = wymin < 0 ?
1576                    (wymin - 0.05*dwy) : Math.max(0, wymin - 0.05*dwy);
1577                wymax_r = wymax + 0.05*dwy;
1578            }
1579           
1580            var wxmin_r =
1581                wxmin < 0 ? (wxmin - 0.05*dwx) : Math.max(0, wxmin - 0.05*dwx);
1582            canvas.setWorldCoordinates(wxmin_r, wymin_r,
1583                wxmax + 0.05*dwx, wymax_r);
1584           
1585            // Draw frame
1586            canvas.setStroke(1);
1587            canvas.drawFrame("black");
1588
1589            // Mark initial value of the varied parameter
1590            canvas.setColor("#c0c0c0");
1591            canvas.setStroke(-1);
1592            canvas.drawPolyLineW([par0*au_f, par0*au_f], [wymin_r, wymax_r]);
1593           
1594            // Draw title
1595            canvas.drawTitle(this.prefs.currentConfigName, "black");
1596           
1597            // Draw axis ticks
1598            canvas.setStroke(1);
1599            canvas.drawTicks("x", "blue");
1600            canvas.drawTicks("y", "blue");
1601
1602            // Draw axis labels
1603            canvas.drawLabel("x", xlabel, "black");
1604            canvas.drawLabel("y", ylabel, "black");
1605           
1606            // Draw sets
1607            canvas.setStroke(2);
1608            for (var i = 0; i < sets.length; i++) {
1609                var set = sets[i];
1610                canvas.setColor(set.color);
1611                canvas.drawPolyLineW(set.x, set.y);
1612               
1613                delete set;
1614            }
1615           
1616            delete sets;
1617           
1618            canvas.paint();
1619        },
1620
1621        showWikiPage : function(entity)
1622        {
1623            var url = "about:blank";
1624            if (entity && entity.wikiLink) {
1625                url = "http://en.wikipedia.org/w/index.php?title=" +
1626                      entity.wikiLink + "&printable=yes";
1627            }
1628           
1629            this.gui_wiki.setCursor("wait");
1630            this.gui_wiki.setSource(url);
1631        },
1632       
1633        loadWikiCB : function(ev)
1634        {
1635            var tree = this.entity_tree;
1636            var leaf = getSingleTreeSelectedItem(tree);
1637           
1638            if (!leaf) {
1639                return;
1640            }
1641           
1642            var entity = leaf.getUserData("entity");
1643           
1644            this.showWikiPage(entity);
1645        },
1646       
1647        drawCB : function(ev)
1648        {
1649            this.drawAll();
1650        },
1651       
1652        renderPlotTab : function()
1653        {
1654            var page_id = this.renderTabPage("Plot",
1655                "pf/image/tab-plot.png");
1656            page_id.setLayout(new qx.ui.layout.VBox);
1657
1658            var sp = new qx.ui.splitpane.Pane("horizontal");
1659            sp.setDecorator("main");
1660            page_id.add(sp, {height: "100%"});
1661                       
1662            var left_pane = new qx.ui.container.Composite(new qx.ui.layout.Grow);
1663            var right_pane = new qx.ui.container.Composite(new qx.ui.layout.VBox(4)).set({
1664              padding : 4
1665            });
1666
1667            sp.add(left_pane,  2);
1668            sp.add(right_pane, 1);
1669           
1670            var canvas = new pf.ui.canvas.Plotter();
1671            left_pane.add(canvas);
1672            this.canvas = canvas;
1673
1674            var layout = new qx.ui.layout.Grid(4, 6);
1675            layout.setColumnWidth(0, 100);
1676            layout.setColumnFlex(1, 1);
1677            var gl = new qx.ui.container.Composite(layout);
1678
1679            var l, e;
1680
1681            var btn = new qx.ui.form.Button("Redraw", "pf/image/tab-plot.png");
1682            btn.addListener("execute", this.drawCB, this);
1683            gl.add(btn, {row: 0, column: 0});
1684
1685            l = new qx.ui.basic.Label("Parameter to vary:");
1686            e = new pf.ui.SelectBox;
1687            e.addItem("N<sub>e</sub>",   "N_e", true);
1688            e.addItem("T",               "T");
1689            e.addItem("T<sub>e</sub>",   "T_e", true);
1690            e.addItem("T<sub>i</sub>",   "T_i", true);
1691            e.addItem("T<sub>r</sub>",   "T_r", true);
1692            e.addItem("T<sub>i,r</sub>", "T_i,r", true);
1693            e.addItem("B",               "B");
1694            e.selectByValue("N_e");
1695            this.guiParameter = e;
1696            gl.add(l, {row: 1, column: 0});
1697            gl.add(e, {row: 1, column: 1});
1698
1699            l = new qx.ui.basic.Label("Minimum scale:");
1700            e = new pf.ui.TextField(0.5);
1701            this.guiMinParam = e;
1702            gl.add(l, {row: 2, column: 0});
1703            gl.add(e, {row: 2, column: 1});
1704
1705            l = new qx.ui.basic.Label("Maximum scale:");
1706            e = new pf.ui.TextField(2.0);
1707            this.guiMaxParam = e;
1708            gl.add(l, {row: 3, column: 0});
1709            gl.add(e, {row: 3, column: 1});
1710
1711            l = new qx.ui.basic.Label("Number of points:");
1712            e = new qx.ui.form.Spinner(2, 20, 100);
1713            this.guiParamPoints = e;
1714            gl.add(l, {row: 4, column: 0});
1715            gl.add(e, {row: 4, column: 1});
1716
1717            right_pane.add(gl);
1718
1719
1720
1721            var tm = new qx.ui.table.model.Simple();
1722            tm.setColumns(["", "Name", "Favorite"],
1723                          ["color", "name", "favorite"]);
1724           
1725            tm.setColumnEditable(0, false);
1726            tm.setColumnEditable(1, false);
1727           
1728            tm.setColumnSortable(0, false);
1729           
1730            // table list
1731            var lv = new qx.ui.table.Table(tm);
1732
1733            var cm = lv.getTableColumnModel();
1734            cm.setColumnVisible(2, false);
1735           
1736            lv.setStatusBarVisible(false);
1737            lv.setShowCellFocusIndicator(false);
1738            lv.setColumnVisibilityButtonVisible(false);
1739           
1740            lv.setColumnWidth(0,  22);
1741            lv.setColumnWidth(1, 220);
1742           
1743            var renderer = new pf.ui.table.cellrenderer.BgColor();
1744            lv.getTableColumnModel().setDataCellRenderer(0, renderer);
1745
1746            right_pane.add(lv, {flex: 1});
1747            this.legendListView = lv;
1748           
1749            var sm = lv.getSelectionModel();
1750           
1751            lv.addListener("dblclick", function(ev) {
1752                    ev.stopPropagation();
1753
1754                    if (sm.isSelectionEmpty()) {
1755                        return;
1756                    }
1757                   
1758                    var index = sm.getLeadSelectionIndex();
1759                    var item = tm.getRowDataAsMap(index);
1760
1761                    var favorite = item.favorite;
1762                    if (!favorite) {
1763                        return;
1764                    }
1765                    cpop.setUserData("favorite", null); // avoid loop call
1766                    cpop.setValue(favorite.color);
1767                    cpop.setUserData("favorite", favorite);
1768                   
1769                    cpop.placeToMouse(ev);
1770                    cpop.open();
1771                });
1772
1773            var cpop = new pf.ui.ColorPopup(this.colorMap);
1774            cpop.exclude();
1775
1776            this.doc.add(cpop);
1777
1778            cpop.addListener("changeValue", function(ev) {
1779                    var color = ev.getData();
1780                    var cpop = ev.getTarget();
1781                    var favorite = cpop.getUserData("favorite");
1782                    if (!favorite || !color) {
1783                        return;
1784                    }
1785                    favorite.color = color;
1786                    this.updateLegendListView();
1787                    this.drawAll();
1788                    this.saveFavorites();
1789                }, this);
1790       
1791            // drawAll is an expensive operation, so call it only when
1792            // this tab is selected
1793            this.tabview.addListener("changeSelection", function(ev) {
1794                    if (ev.getData()[0] == page_id) {
1795                        this.drawAll();
1796                    }
1797                }, this);
1798        },
1799
1800
1801        aboutCB : function(ev)
1802        {
1803            this.aboutWindow.open();
1804        },
1805       
1806        prefsCB : function(ev)
1807        {
1808            this.prefsWindow.open();
1809        },
1810       
1811        updateSaveLoadList : function()
1812        {
1813            var lv = this.saveLoadConfigList;
1814            var tm = lv.getTableModel();
1815           
1816            var configPtrs = this.prefs.configPtrs;
1817           
1818            var rowData = new Array();
1819
1820            var i;
1821            var d = new Date();
1822            var df = new qx.util.format.DateFormat("yyyy-MM-dd HH:mm:ss");
1823           
1824            for (i = 0; i < configPtrs.length; i++) {
1825                var configPtr = configPtrs[i];
1826
1827                d.setTime(configPtr.time);
1828
1829                rowData.push([configPtr.name, df.format(d)]);
1830            }
1831           
1832            tm.setData(rowData, false);
1833            var sidx = tm.getSortColumnIndex();
1834            tm.sortByColumn(sidx, tm.isSortAscending());
1835           
1836            lv.updateContent();
1837        },
1838       
1839        saveAsCB : function(ev)
1840        {
1841            var w = this.saveLoadWindow;
1842           
1843            this.updateSaveLoadList();
1844            this.saveLoadTextField.setValue(null);
1845            this.saveLoadTextField.setReadOnly(false);
1846           
1847            w.setCaption("Save configuration")
1848            w.setIcon("pf/image/save.png");
1849            w.setUserData("type", "save");
1850           
1851            w.open();
1852        },
1853       
1854        saveConfigCB : function(ev)
1855        {
1856            if (this.prefs.currentConfigName &&
1857                this.prefs.currentConfigName != "Untitled") {
1858                if (this.saveConfig(this.prefs.currentConfigName) != true) {
1859                    this.msgWindow.error("Save failed!");
1860                }
1861            } else {
1862                this.saveAsCB(ev);
1863            }
1864        },
1865       
1866        openCB : function(ev)
1867        {
1868            var w = this.saveLoadWindow;
1869           
1870            this.updateSaveLoadList();
1871            this.saveLoadTextField.setValue(null);
1872            this.saveLoadTextField.setReadOnly(true);
1873           
1874            w.setCaption("Open configuration")
1875            w.setIcon("pf/image/open.png");
1876            w.setUserData("type", "open");
1877           
1878            w.open();
1879        },
1880       
1881        restart : function(force)
1882        {
1883            if (force || this.intendedExit || !this.prefs.warnOnExit) {
1884                location.reload(true);
1885            } else {
1886                this.confirmDialog.confirm("Restart Plasma Formulary?",
1887                    function(yesno) {
1888                            if (yesno) {
1889                                this.intendedExit = true;
1890                                this.restart(true);
1891                            }
1892                        }, this);
1893            }
1894        },
1895       
1896        quit : function(force)
1897        {
1898            if (force || this.intendedExit || !this.prefs.warnOnExit) {
1899                window.close(true);
1900            } else {
1901                this.confirmDialog.confirm("Quit Plasma Formulary?",
1902                    function(yesno) {
1903                            if (yesno) {
1904                                this.intendedExit = true;
1905                                this.quit(true);
1906                            }
1907                        }, this);
1908            }
1909        },
1910       
1911        buildMenu : function()
1912        {
1913            var menubar = this.menubar;
1914           
1915            var submenu, btn, q;
1916
1917            submenu = new qx.ui.menu.Menu;
1918            this.doc.add(submenu);
1919            q = new qx.ui.core.Command("Ctrl+O");
1920            q.addListener("execute", this.openCB, this);
1921            btn = new qx.ui.menu.Button("Open...", "pf/image/open.png", q);
1922            submenu.add(btn);
1923            q = new qx.ui.core.Command("Ctrl+S");
1924            q.addListener("execute", this.saveConfigCB, this);
1925            btn = new qx.ui.menu.Button("Save", "pf/image/save.png", q);
1926            submenu.add(btn);
1927            btn = new qx.ui.menu.Button("Save as...", "pf/image/save.png");
1928            btn.addListener("execute", this.saveAsCB, this);
1929            submenu.add(btn);
1930            submenu.add(new qx.ui.menu.Separator);
1931            q = new qx.ui.core.Command("Ctrl+P");
1932            q.addListener("execute", function(ev) {
1933                window.print();
1934            });
1935            btn = new qx.ui.menu.Button("Print...", "pf/image/print.png", q);
1936            submenu.add(btn);
1937            submenu.add(new qx.ui.menu.Separator);
1938            q = new qx.ui.core.Command("Ctrl+R");
1939            q.addListener("execute", function(ev) {
1940                    this.restart(false);
1941                }, this);
1942            btn = new qx.ui.menu.Button("Restart", "pf/image/reset.png", q);
1943            submenu.add(btn);
1944            submenu.add(new qx.ui.menu.Separator);
1945            q = new qx.ui.core.Command("Ctrl+Q");
1946            q.addListener("execute", function(ev) {
1947                    this.quit(false);
1948                }, this);
1949            btn = new qx.ui.menu.Button("Quit", "pf/image/exit.png", q);
1950            submenu.add(btn);
1951               
1952            btn = new qx.ui.menubar.Button("File", null, submenu);
1953            menubar.add(btn);
1954
1955
1956            submenu = new qx.ui.menu.Menu;
1957            submenu.addListener("appear", editMenuCB, this);
1958            this.doc.add(submenu);
1959            btn = new qx.ui.menu.Button("Add to Favorites",
1960                "pf/image/favorite-add.png");
1961            btn.addListener("execute", addToFavCB, this);
1962            this.editMenuButtonAddToFav = btn;
1963            submenu.add(btn);
1964            btn = new qx.ui.menu.Button("Remove from Favorites",
1965                "pf/image/favorite-delete.png");
1966            btn.addListener("execute", removeFromFavCB, this);
1967            this.editMenuButtonRemFromFav = btn;
1968            submenu.add(btn);
1969            submenu.add(new qx.ui.menu.Separator);
1970            btn = new qx.ui.menu.Button("Preferences",
1971                "pf/image/preferences.png");
1972            btn.addListener("execute", this.prefsCB, this);
1973            submenu.add(btn);
1974
1975            btn = new qx.ui.menubar.Button("Edit", null, submenu);
1976            menubar.add(btn);
1977
1978
1979            submenu = new qx.ui.menu.Menu;
1980            submenu.addListener("appear", viewMenuCB, this);
1981
1982            var subMenu1 = new qx.ui.menu.Menu;
1983            btn = new qx.ui.menu.CheckBox("Fundamental");
1984            btn.setValue(this.showFundamental);
1985            btn.addListener("execute", showFundamentalCB, this);
1986            subMenu1.add(btn);
1987            btn = new qx.ui.menu.CheckBox("Spectroscopy");
1988            btn.setValue(this.showSpectroscopy);
1989            btn.addListener("execute", showSpectroscopyCB, this);
1990            subMenu1.add(btn);
1991            btn = new qx.ui.menu.CheckBox("Waves");
1992            btn.setValue(this.showWaves);
1993            btn.addListener("execute", showWavesCB, this);
1994            subMenu1.add(btn);
1995            btn = new qx.ui.menu.CheckBox("Collisions");
1996            btn.setValue(this.showCollisions);
1997            btn.addListener("execute", showCollisionsCB, this);
1998            subMenu1.add(btn);
1999            btn = new qx.ui.menu.CheckBox("Radiation");
2000            btn.setValue(this.showRadiation);
2001            btn.addListener("execute", showRadiationCB, this);
2002            subMenu1.add(btn);
2003            this.showSectionsButton = new qx.ui.menu.Button("Show Sections",
2004                null, null, subMenu1);
2005            submenu.add(this.showSectionsButton);
2006           
2007            submenu.add(new qx.ui.menu.Separator);
2008
2009            var subMenu2 = new qx.ui.menu.Menu;
2010            btn = new qx.ui.menu.CheckBox("Electrons");
2011            btn.setValue(this.showElectrons);
2012            btn.addListener("execute", showElectronsCB, this);
2013            subMenu2.add(btn);
2014            btn = new qx.ui.menu.CheckBox("Ions");
2015            btn.setValue(this.showIons);
2016            btn.addListener("execute", showIonsCB, this);
2017            subMenu2.add(btn);
2018            btn = new qx.ui.menu.CheckBox("Radiators");
2019            btn.setValue(this.showRadiators);
2020            btn.addListener("execute", showRadiatorsCB, this);
2021            subMenu2.add(btn);
2022            this.showSpeciesButton = new qx.ui.menu.Button("Show Species",
2023                null, null, subMenu2);
2024            submenu.add(this.showSpeciesButton);
2025           
2026            submenu.add(new qx.ui.menu.Separator);
2027            q = new qx.ui.core.Command("Ctrl+W");
2028            q.addListener("execute", this.loadWikiCB, this);
2029            btn = new qx.ui.menu.Button("Load Wikipedia Article",
2030                "pf/image/wikipedia.png", q);
2031            submenu.add(btn);
2032            this.loadWikiButton = btn;
2033            this.doc.add(submenu);
2034            this.doc.add(subMenu1);
2035            this.doc.add(subMenu2);
2036
2037            submenu.add(new qx.ui.menu.Separator);
2038            q = new qx.ui.core.Command("Ctrl+L");
2039            q.addListener("execute", this.drawCB, this);
2040            btn = new qx.ui.menu.Button("Redraw Plot",
2041                "pf/image/tab-plot.png", q);
2042            submenu.add(btn);
2043            this.redrawButton = btn;
2044           
2045           
2046            btn = new qx.ui.menubar.Button("View", null, submenu);
2047            menubar.add(btn);
2048
2049
2050            var nvOptions = {
2051                width: 850,
2052                scrollbars : true,
2053                resizable : true,
2054                menubar : false,
2055                status : false
2056            };
2057            submenu = new qx.ui.menu.Menu;
2058            this.doc.add(submenu);
2059            q = new qx.ui.core.Command("F1");
2060            q.addListener("execute", function(ev) {
2061                    var url = "resource/pf/html/ug.html";
2062                    var w = qx.bom.Window.open(url, null, nvOptions);
2063                }, this);
2064            btn = new qx.ui.menu.Button("Help Contents",
2065                "pf/image/help.png", q);
2066            submenu.add(btn);
2067            btn = new qx.ui.menu.Button("NRL Plasma Formulary",
2068                "pf/image/nrl.png");
2069            btn.addListener("execute", function (ev) {
2070                    var url = "http://wwwppd.nrl.navy.mil/nrlformulary/";
2071                    var w = qx.bom.Window.open(url, null, nvOptions);
2072                }, this);
2073            submenu.add(btn);
2074            btn = new qx.ui.menu.Button("Plasma at Wikipedia",
2075                "pf/image/wikipedia.png");
2076            btn.addListener("execute", function (ev) {
2077                    var url = "http://en.wikipedia.org/wiki/Plasma_%28physics%29";
2078                    var w = qx.bom.Window.open(url, null, nvOptions);
2079                }, this);
2080            submenu.add(btn);
2081            submenu.add(new qx.ui.menu.Separator);
2082            btn = new qx.ui.menu.Button("License Terms",
2083                "pf/image/gnu.png");
2084            btn.addListener("execute", function (ev) {
2085                    var url = "resource/pf/html/GPL.html";
2086                    var w = qx.bom.Window.open(url, null, nvOptions);
2087                }, this);
2088            submenu.add(btn);
2089            btn = new qx.ui.menu.Button("About...",
2090                "pf/image/about.png");
2091            btn.addListener("execute", this.aboutCB, this);
2092            submenu.add(btn);
2093
2094            btn = new qx.ui.menubar.Button("Help", null, submenu);
2095            menubar.add(btn);
2096        },
2097       
2098        getEntityById : function(id)
2099        {
2100            var len = plasma_entities.length;
2101           
2102            for (var i = 0; i < len; i++) {
2103                var entity = plasma_entities[i];
2104                if (entity.id == id) {
2105                    return entity;
2106                }
2107            }
2108           
2109            return null;
2110        },
2111       
2112        getSpeciesById : function(id)
2113        {
2114            switch (id) {
2115            case "e":
2116                return this.plasma.e;
2117                break;
2118            case "i":
2119                return this.plasma.i;
2120                break;
2121            case "r":
2122                return this.plasma.r;
2123                break;
2124            default:
2125                return null;
2126                break;
2127            }
2128        },
2129       
2130        nextColor : function()
2131        {
2132            var color = this.colorMap[this.ncolor];
2133            this.ncolor++;
2134            if (this.ncolor == this.colorMap.length) {
2135                this.ncolor = 0;
2136            }
2137           
2138            return color;
2139        },
2140
2141        exportFavorites : function()
2142        {
2143            var sfavs = new Array;
2144            var len = this.favorites.length;
2145           
2146            for (var k = 0; k < len; k++) {
2147                var fav  = this.favorites[k];
2148                var sfav = new Object;
2149                sfav.entity_id  = fav.entity.id;
2150                if (fav.s1) {
2151                    sfav.s1_id = fav.s1.id;
2152                } else {
2153                    sfav.s1_id = null;
2154                }
2155                if (fav.s2) {
2156                    sfav.s2_id = fav.s2.id;
2157                } else {
2158                    sfav.s2_id = null;
2159                }
2160                sfav.color     = fav.color;
2161                sfavs.push(sfav);
2162            }
2163           
2164            return sfavs;
2165        },
2166
2167        importFavorites : function(sfavs)
2168        {
2169            if (!sfavs) {
2170                return false;
2171            }
2172
2173            this.favorites = new Array;
2174           
2175            var len = sfavs.length;
2176            for (var k = 0; k < len; k++) {
2177                var sfav = sfavs[k];
2178                var fav  = new Object;
2179                fav.entity = this.getEntityById(sfav.entity_id);
2180                // old format
2181                if (sfav.species_id) {
2182                    fav.s1 = this.getSpeciesById(sfav.species_id);
2183                } else
2184                if (sfav.s1_id) {
2185                    fav.s1 = this.getSpeciesById(sfav.s1_id);
2186                }
2187
2188                if (sfav.s2_id) {
2189                    fav.s2 = this.getSpeciesById(sfav.s2_id);
2190                }
2191                fav.color = sfav.color;
2192
2193                if (fav.entity && fav.color) {
2194                    this.favorites.push(fav);
2195                }
2196            }
2197           
2198            return true;
2199        },
2200
2201        getConfig : function(name)
2202        {
2203            if (!name) {
2204                return null;
2205            }
2206
2207            var configPtrs = this.prefs.configPtrs;
2208           
2209            var i, configPtr = null;
2210            for (i = 0; i < configPtrs.length; i++) {
2211                if (configPtrs[i].name == name) {
2212                    configPtr = configPtrs[i];
2213                    return configPtr;
2214                    break;
2215                }
2216            }
2217           
2218            return null;
2219        },
2220       
2221        savePreferences : function()
2222        {
2223            if (this.prefs) {
2224                var prefstr = qx.lang.Json.stringify(this.prefs);
2225                qx.bom.Cookie.set("pf_prefs", prefstr, 3650);
2226            }
2227        },
2228       
2229        loadPreferences : function()
2230        {
2231            var prefstr = qx.bom.Cookie.get("pf_prefs");
2232           
2233            if (prefstr) {
2234                this.prefs = qx.lang.Json.parse(prefstr);
2235            }
2236           
2237            if (!this.prefs) {
2238                this.prefs = new Object;
2239            }
2240 
2241            if (undefined === this.prefs.saveFavsWithConfig) {
2242                this.prefs.saveFavsWithConfig = true;
2243            }
2244           
2245            if (undefined === this.prefs.rememberWindowSize) {
2246                this.prefs.rememberWindowSize = false;
2247            }
2248
2249            if (undefined === this.prefs.autoLoadWiki) {
2250                this.prefs.autoLoadWiki = true;
2251            }
2252           
2253            if (undefined === this.prefs.warnOnExit) {
2254                this.prefs.warnOnExit = true;
2255            }
2256           
2257            if (!this.prefs.units) {
2258                this.prefs.units = new Object;
2259            }
2260           
2261            if (!this.prefs.currentConfigName) {
2262                this.prefs.currentConfigName = "Untitled";
2263            }
2264           
2265            if (!this.prefs.configPtrs) {
2266                this.prefs.configPtrs = new Array;
2267            }
2268        },
2269       
2270        saveFavorites : function()
2271        {
2272            var sfavs = this.exportFavorites();
2273           
2274            var favstr = qx.lang.Json.stringify(sfavs);
2275           
2276            qx.bom.Cookie.set("pf_favs", favstr, 3650);
2277        },
2278       
2279        loadFavorites : function()
2280        {
2281            this.favorites = new Array;
2282           
2283            var favstr = qx.bom.Cookie.get("pf_favs");
2284           
2285            if (favstr) {
2286                var sfavs = qx.lang.Json.parse(favstr);
2287               
2288                this.importFavorites(sfavs);
2289            }
2290        },
2291       
2292        saveConfig : function(name)
2293        {
2294            if (!name) {
2295                return false;
2296            }
2297
2298            var configPtr = this.getConfig(name);
2299           
2300            var d = new Date();
2301            var time = d.getTime();
2302           
2303            if (!configPtr) {
2304                configPtr = new Object;
2305                configPtr.name = name;
2306                configPtr.hash = time;
2307                this.prefs.configPtrs.push(configPtr);
2308            }
2309           
2310            configPtr.time = time;
2311           
2312            var cookie_name = "pf_config_" + configPtr.hash;
2313           
2314            var config = new Object;
2315           
2316            // version of config format
2317            config.format_v = 1;
2318           
2319            config.N_e = this.plasma.e.getN();
2320
2321            config.T_e = this.plasma.e.getT();
2322            config.T_i = this.plasma.i.getT();
2323            config.T_r = this.plasma.r.getT();
2324
2325            config.M_i = this.plasma.i.getM();
2326            config.M_r = this.plasma.r.getM();
2327           
2328            config.Q_i = this.plasma.i.getQ();
2329            config.Q_r = this.plasma.r.getQ();
2330
2331            config.P_r = this.plasma.P_r;
2332
2333            config.B   = this.plasma.B  ;
2334
2335            config.n_u = this.plasma.n_u;
2336            config.n_l = this.plasma.n_l;
2337           
2338            if (this.prefs.saveFavsWithConfig) {
2339                config.favorites = this.exportFavorites();
2340            }
2341           
2342            var configstr = qx.lang.Json.stringify(config);
2343            qx.bom.Cookie.set(cookie_name, configstr, 3650);
2344           
2345            this.prefs.currentConfigName = name;
2346            this.savePreferences();
2347           
2348            return true;
2349        },
2350       
2351        loadConfig : function(name)
2352        {
2353            var configPtr = this.getConfig(name);
2354            if (!configPtr) {
2355                return false;
2356            }
2357
2358            var cookie_name = "pf_config_" + configPtr.hash;
2359
2360            var configstr = qx.bom.Cookie.get(cookie_name);
2361            if (!configstr) {
2362                // Cookie was deleted???
2363                qx.lang.Array.remove(this.prefs.configPtrs, configPtr);
2364                return false;
2365            }
2366
2367            var config = qx.lang.Json.parse(configstr);
2368           
2369            if (config) {
2370                var au_fn, au_fT, au_fM, au_fB;
2371                if (!config.format_v) {
2372                    // old format, rescale data
2373                    au_fn = pf.base.Bohr.n0;
2374                    au_fT = pf.base.Bohr.E0;
2375                    au_fM = 1/pf.base.Bohr.m_p;
2376                    au_fB = pf.base.Bohr.B0;
2377                } else {
2378                    au_fn = 1;
2379                    au_fT = 1;
2380                    au_fM = 1;
2381                    au_fB = 1;
2382                }
2383               
2384                this.plasma.e.setN(config.N_e/au_fn);
2385
2386                this.plasma.e.setT(config.T_e/au_fT);
2387                this.plasma.i.setT(config.T_i/au_fT);
2388                this.plasma.r.setT(config.T_r/au_fT);
2389
2390                this.plasma.i.setM(config.M_i/au_fM);
2391                this.plasma.r.setM(config.M_r/au_fM);
2392
2393                this.plasma.i.setQ(config.Q_i);
2394                this.plasma.r.setQ(config.Q_r);
2395
2396                this.plasma.P_r = config.P_r;
2397
2398                this.plasma.B   = config.B/au_fB;
2399
2400                this.plasma.n_u = config.n_u;
2401                this.plasma.n_l = config.n_l;
2402               
2403                if (this.prefs.saveFavsWithConfig && config.favorites) {
2404                    this.importFavorites(config.favorites);
2405                }
2406
2407                this.prefs.currentConfigName = name;
2408               
2409                this.savePreferences();
2410
2411                return true;
2412            } else {
2413                return false;
2414            }
2415        },
2416       
2417        removeConfig : function(name)
2418        {
2419            var configPtr = this.getConfig(name);
2420            if (configPtr) {
2421                qx.lang.Array.remove(this.prefs.configPtrs, configPtr);
2422                var cookie_name = "pf_config_" + configPtr.hash;
2423                qx.bom.Cookie.del(cookie_name);
2424                this.savePreferences();
2425            }
2426        },
2427       
2428        renameConfig : function(oldname, newname)
2429        {
2430            var configPtr = this.getConfig(oldname);
2431            if (configPtr) {
2432                configPtr.name = newname;
2433                this.savePreferences();
2434            }
2435        },
2436       
2437        createSaveLoadDialog : function()
2438        {
2439            var w, rc1, e, btn;
2440            // "Save as..." dialog
2441            w = new pf.ui.DialogWindow();
2442            w.setLayout(new qx.ui.layout.VBox(0));
2443            w.setContentPadding(0);
2444               
2445            this.doc.add(w);
2446            this.saveLoadWindow = w;
2447
2448            var tb = new qx.ui.toolbar.ToolBar();
2449            var tbpart = new qx.ui.toolbar.Part();
2450            var btn_delete = new qx.ui.toolbar.Button("Delete",
2451                "pf/image/delete.png");
2452            var btn_rename = new qx.ui.toolbar.Button("Rename",
2453                "pf/image/rename.png");
2454            btn_delete.setEnabled(false);
2455            btn_rename.setEnabled(false);
2456            tbpart.add(btn_delete);
2457            tbpart.add(btn_rename);
2458            tb.add(tbpart);
2459            w.add(tb);
2460
2461            // table model
2462            var tm = new qx.ui.table.model.Simple();
2463            tm.setColumns([ "Configuration", "Last Modified" ]);
2464           
2465            tm.setColumnEditable(0, false);
2466            tm.setColumnEditable(1, false);
2467           
2468            // table list
2469            var lv = new qx.ui.table.Table(tm);
2470            lv.set({
2471                height: 250
2472            });
2473
2474            lv.setStatusBarVisible(false);
2475            lv.setShowCellFocusIndicator(false);
2476            lv.setColumnVisibilityButtonVisible(false);
2477           
2478            lv.setColumnWidth(0, 250);
2479            lv.setColumnWidth(1, 150);
2480           
2481            var renderer = new qx.ui.table.cellrenderer.Html();
2482            lv.getTableColumnModel().setDataCellRenderer(0, renderer);
2483           
2484            this.saveLoadConfigList = lv;
2485            w.add(lv);
2486
2487            var sm = lv.getSelectionModel();
2488            sm.setSelectionMode(qx.ui.table.selection.Model.SINGLE_SELECTION);
2489
2490            btn_delete.addListener("execute", function(ev) {
2491                    if (!sm.isSelectionEmpty()) {
2492                        var index = sm.getLeadSelectionIndex();
2493                        var rowData = tm.getRowData(index);
2494                        var name = rowData[0];
2495                        if (name == this.prefs.currentConfigName) {
2496                            this.msgWindow.error("Cannot delete current configuration!");
2497                        } else {
2498                            this.confirmDialog.confirm("Delete \"" + name + "\"?",
2499                                function(yesno) {
2500                                        if (yesno) {
2501                                            this.removeConfig(name);
2502                                            this.updateSaveLoadList();
2503                                        }
2504                                    }, this);
2505                        }
2506                    }
2507                }, this);
2508
2509            btn_rename.addListener("execute", function(ev) {
2510                    if (!sm.isSelectionEmpty()) {
2511                        var index = sm.getLeadSelectionIndex();
2512                        var rowData = tm.getRowData(index);
2513                        var name = rowData[0];
2514                       
2515                       
2516                        this.promptDialog.prompt("Rename \"" + name + "\" to",
2517                            name, function(newname) {
2518                                    if (newname  && newname != name) {
2519                                        this.renameConfig(name, newname);
2520                                        this.updateSaveLoadList();
2521                                        if (name == this.prefs.currentConfigName) {
2522                                            this.prefs.currentConfigName = newname;
2523                                            this.gui_configName.setLabel(newname);
2524                                        }
2525                                        this.saveLoadTextField.setValue(newname);
2526                                    }
2527                                }, this);
2528                    }
2529                }, this);
2530
2531            e = new qx.ui.form.TextField();
2532            e.setMarginTop(1);
2533            w.add(e);
2534            this.saveLoadTextField = e;
2535           
2536            sm.addListener("changeSelection", function(ev) {
2537                    if (sm.isSelectionEmpty()) {
2538                        e.setValue(null);
2539                        btn_delete.setEnabled(false);
2540                        btn_rename.setEnabled(false);
2541                    } else {
2542                        var index = sm.getLeadSelectionIndex();
2543                        var rowData = tm.getRowData(index);
2544                        e.setValue(rowData[0]);
2545                        btn_rename.setEnabled(true);
2546                        btn_delete.setEnabled(true);
2547                    }
2548                });
2549           
2550            var layout = new qx.ui.layout.HBox(10, "right");
2551            rc1 = new qx.ui.container.Composite(layout);
2552            rc1.setMargin(10, 10, 10, 10);
2553            w.add(rc1);
2554
2555            btn = new qx.ui.form.Button("Cancel",
2556                "pf/image/cancel.png");
2557            btn.addListener("execute", function(ev) {
2558                    this.saveLoadWindow.close();
2559                }, this);
2560            rc1.add(btn);
2561
2562            btn = new qx.ui.form.Button("OK",
2563                "pf/image/ok.png");
2564            btn.setEnabled(false);
2565            btn.addListener("execute", function(ev) {
2566                    var cfgname = this.saveLoadTextField.getValue(); 
2567                    if (!cfgname) {
2568                        this.msgWindow.error("Please enter a name!");
2569                    } else {
2570                        var type = w.getUserData("type");
2571                        if (type == "save") {
2572                            if (this.saveConfig(cfgname) == true) {
2573                                this.saveLoadWindow.close();
2574                                if (this.prefs.currentConfigName) {
2575                                    this.gui_configName.setLabel(this.prefs.currentConfigName);
2576                                }
2577                            } else {
2578                                this.msgWindow.error("Save failed!");
2579                            }
2580                        } else {
2581                            if (this.loadConfig(cfgname) == true) {
2582                                this.updatePlasmaParameters();
2583                                this.updateGUI();
2584                                if (this.prefs.saveFavsWithConfig) {
2585                                    this.rePopulateTree();
2586                                }
2587                                this.drawAll();
2588                                this.saveLoadWindow.close();
2589                            } else {
2590                                this.msgWindow.error("Load failed!");
2591                            }
2592                        }
2593                    }
2594                }, this);
2595            rc1.add(btn);
2596
2597            e.setLiveUpdate(true);
2598            e.addListener("changeValue", function(ev) {
2599                    var name = this.getValue();
2600                    btn.setEnabled(null != name && name.length != 0);
2601                });
2602        },
2603
2604        createPrefsDialog : function()
2605        {
2606            // "Preferences..." dialog
2607            var w = new pf.ui.DialogWindow("Preferences",
2608                "pf/image/preferences.png");
2609            w.setLayout(new qx.ui.layout.VBox(10));
2610
2611            this.doc.add(w);
2612            this.prefsWindow = w;
2613           
2614            var fr, l, e;
2615
2616            fr = new qx.ui.groupbox.GroupBox("General");
2617            fr.setLayout(new qx.ui.layout.VBox(10));
2618            w.add(fr);
2619
2620            e = new qx.ui.form.CheckBox("Save favorites with configurations");
2621            e.setValue(this.prefs.saveFavsWithConfig);
2622            e.addListener("changeValue", function(ev) {
2623                this.prefs.saveFavsWithConfig = ev.getTarget().getValue();
2624                this.savePreferences();
2625            }, this);
2626            fr.add(e);
2627           
2628            fr = new qx.ui.groupbox.GroupBox("Default units");
2629            fr.setLayout(new qx.ui.layout.HBox(10));
2630            w.add(fr);
2631           
2632            var unit_cb_enabled = false;
2633           
2634            l = new qx.ui.basic.Label("Dimension:");
2635            e = new pf.ui.SelectBox;
2636            e.addItem("Length", "length");
2637            e.addItem("Frequency", "frequency");
2638            e.addItem("Velocity", "velocity");
2639            e.addItem("Energy", "energy");
2640            e.addItem("Mass density", "mass_density");
2641            e.addItem("Pressure", "pressure");
2642            e.addItem("Area", "area");
2643            e.addItem("Power density", "power_density");
2644            e.addItem("Power spectral density", "spectral_power_density");
2645            e.addItem("Electric field", "efield");
2646            e.addListener("changeSelection", function(ev) {
2647                    var dimension = ev.getTarget().getSelectedValue();
2648                    unit_cb_enabled = false;
2649                    this.gui_prefs_units.update(dimension,
2650                        this.prefs.units[dimension]);
2651                    unit_cb_enabled = true;
2652                }, this);
2653            fr.add(l);
2654            fr.add(e);
2655            this.gui_prefs_dim = e;
2656
2657            l = new qx.ui.basic.Label("Units:");
2658            e = new pf.UnitSelector();
2659            e.addListener("changeSelection", function(ev) {
2660                    if (unit_cb_enabled) {
2661                        var dimension = this.gui_prefs_dim.getSelectedValue();
2662                        var units = ev.getTarget().getSelectedValue();
2663                        this.prefs.units[dimension] = units;
2664                        this.savePreferences();
2665                    }
2666                }, this);
2667            fr.add(l);
2668            fr.add(e);
2669            e.update("length", this.prefs.units["length"]);
2670            this.gui_prefs_units = e;
2671           
2672            unit_cb_enabled = true;
2673
2674            fr = new qx.ui.groupbox.GroupBox("Interface");
2675            fr.setLayout(new qx.ui.layout.VBox(10));
2676            w.add(fr);
2677
2678            e = new qx.ui.form.CheckBox("Load Wikipedia articles automatically");
2679            e.setValue(this.prefs.autoLoadWiki);
2680            e.addListener("changeValue", function(ev) {
2681                this.prefs.autoLoadWiki = ev.getTarget().getValue();
2682                this.savePreferences();
2683            }, this);
2684            fr.add(e);
2685
2686            e = new qx.ui.form.CheckBox("Remember window dimensions on exit");
2687            e.setValue(this.prefs.rememberWindowSize);
2688            e.addListener("changeValue", function(ev) {
2689                this.prefs.rememberWindowSize = ev.getTarget().getValue();
2690                this.savePreferences();
2691            }, this);
2692            fr.add(e);
2693
2694            e = new qx.ui.form.CheckBox("Warn on exit or restart");
2695            e.setValue(this.prefs.warnOnExit);
2696            e.addListener("changeValue", function(ev) {
2697                this.prefs.warnOnExit = ev.getTarget().getValue();
2698                this.savePreferences();
2699            }, this);
2700            fr.add(e);
2701
2702            fr = new qx.ui.groupbox.GroupBox("Theme");
2703            fr.setLayout(new qx.ui.layout.VBox(10));
2704            w.add(fr);
2705           
2706            var btn1 = new qx.ui.form.RadioButton("Modern");
2707            btn1.setModel("modern");
2708            var btn2 = new qx.ui.form.RadioButton("Classic");
2709            btn2.setModel("classic");
2710            var btn3 = new qx.ui.form.RadioButton("Simple");
2711            btn3.setModel("simple");
2712           
2713            fr.add(btn1);
2714            fr.add(btn2);
2715            fr.add(btn3);
2716           
2717            var rm = new qx.ui.form.RadioGroup(btn1, btn2, btn3);
2718            var sels;
2719            switch (this.prefs.themeName) {
2720            case "classic":
2721                sels = new Array(btn2);
2722                break;
2723            case "simple":
2724                sels = new Array(btn3);
2725                break;
2726            default:
2727                sels = new Array(btn1);
2728                break;
2729            }
2730            rm.setSelection(sels);
2731            rm.addListener("changeSelection", function(ev) {
2732                    var btn = ev.getData()[0];
2733                    this.prefs.themeName = btn.getModel();
2734                    this.savePreferences();
2735                   
2736                    this.msgWindow.info("New theme will be applied after restart of the application");
2737                }, this);
2738
2739        },
2740
2741        applyTheme : function()
2742        {
2743            var theme;
2744            switch (this.prefs.themeName) {
2745            case "classic":
2746                theme = pf.theme.Classic;
2747                break;
2748            case "simple":
2749                theme = qx.theme.Simple;
2750                break;
2751            default:
2752                theme = pf.theme.Modern;
2753                break;
2754            }
2755            var thm = qx.theme.manager.Meta.getInstance();
2756            thm.setTheme(theme);
2757        },
2758
2759        /**
2760         * TODOC
2761         *
2762         * @type member
2763         * @param e {Event} TODOC
2764         * @return {void}
2765         */
2766        main : function(e)
2767        {
2768            this.base(arguments);
2769
2770            // Enable logging in debug variant
2771            if (qx.core.Environment.get("qx.debug")) {
2772                // support native logging capabilities, e.g. Firebug
2773                qx.log.appender.Native;
2774                // support additional cross-browser console. (Press F7)
2775                qx.log.appender.Console;
2776            }
2777           
2778            this.doc = this.getRoot();
2779           
2780            // Load prefs
2781            this.loadPreferences();
2782           
2783            // Apply theme
2784            this.applyTheme();
2785           
2786            if (this.prefs.rememberWindowSize && this.prefs.dims) {
2787                self.resizeTo(this.prefs.dims.width, this.prefs.dims.height);
2788            }
2789
2790            this.plasma = new pf.Plasma();
2791           
2792            // Load config from the previous session
2793            if (this.prefs.currentConfigName) {
2794                this.loadConfig(this.prefs.currentConfigName);
2795            }
2796           
2797            if (this.updatePlasmaParameters() != true) {
2798                this.error("Error updating plasma parameters!");
2799            }
2800           
2801            // Favorites
2802            this.loadFavorites();
2803           
2804            this.colorMap = new Array("red", "blue", "green", "orange",
2805                "brown", "olive", "teal", "magenta", "gray", "black");
2806            this.ncolor = 0;
2807
2808            // Top-level container
2809            var layout = new qx.ui.layout.VBox;
2810            this.bl_top = new qx.ui.container.Composite(layout);
2811
2812            this.doc.add(this.bl_top, {width :'100%', height: "100%"});
2813
2814            // The menubar
2815            this.menubar = new qx.ui.menubar.MenuBar;
2816            this.bl_top.add(this.menubar);
2817           
2818            // The menu items
2819            this.buildMenu();
2820           
2821            this.tabview = new qx.ui.tabview.TabView;
2822            this.tabview.setContentPadding(6);
2823           
2824            this.bl_top.add(this.tabview, {flex: 1});
2825            // The "Parameters" tab
2826            this.renderParametersTab();
2827           
2828            // The "Explorer" tab
2829            this.renderExplorerTab();
2830           
2831            // The "Compare" tab
2832            this.renderCompareTab();
2833            this.updateFavoritesListView();
2834           
2835            // The "Plot" tab
2836            this.renderPlotTab();
2837            this.updateLegendListView();
2838           
2839            // "Preferences" dialog
2840            this.createPrefsDialog();
2841
2842            // "Save as" dialog
2843            this.createSaveLoadDialog();
2844
2845            // "About..." dialog
2846            var w = new pf.ui.DialogWindow("About Plasma Formulary",
2847                "pf/image/about.png");
2848            w.setLayout(new qx.ui.layout.VBox(10));
2849
2850            var pf_version = qx.core.Environment.get("pf.version");
2851            var qx_version = qx.core.Environment.get("qx.version");
2852            var str = 'Plasma Formulary Interactive '            +
2853                      pf_version + '.<br/>'                      +
2854                      '<p>Created by Evgeny Stambulchik.</p>'    +
2855                      'GUI built with the qooxdoo-' + qx_version +
2856                      ' toolkit.<br/>'                           + 
2857                      'Using Walter Zorn jsGraphics for drawing.';
2858
2859            var a = new qx.ui.basic.Atom(str);
2860            a.setRich(true);
2861            w.add(a);
2862
2863            this.doc.add(w);
2864            this.aboutWindow = w;
2865           
2866            this.msgWindow = new pf.ui.MessageWindow();
2867            this.doc.add(this.msgWindow);
2868            this.confirmDialog = new pf.ui.ConfirmDialog();
2869            this.doc.add(this.confirmDialog);
2870            this.promptDialog = new pf.ui.PromptDialog();
2871            this.doc.add(this.promptDialog);
2872           
2873            // Handle resize events
2874            this.doc.addListener("resize", function(e) {
2875                if (this.prefs.rememberWindowSize) {
2876                    this.prefs.dims = this.doc.getInnerSize();
2877                    this.savePreferences();
2878                }
2879                this.drawAll();
2880            }, this);
2881        },
2882   
2883
2884        /**
2885         * TODOC
2886         *
2887         * @type member
2888         * @param e {Event} TODOC
2889         * @return {void}
2890         */
2891        close : function(e)
2892        {
2893            this.base(arguments);
2894           
2895            // Prompt user
2896            if (this.prefs.warnOnExit && !this.intendedExit) {
2897                return "This will end your Plasma Formulary session.";
2898            }
2899        }
2900    }
2901});
Note: See TracBrowser for help on using the repository browser.