~mterry/ubuntu-calculator-app/confined

« back to all changes in this revision

Viewing changes to app/ubuntu-calculator-app.qml

  • Committer: Bartosz Kosiorek
  • Date: 2014-11-28 00:01:50 UTC
  • Revision ID: gang65@poczta.onet.pl-20141128000150-333mfsdnbxxug5u5
Create formula to display and engine formula, add formula validation, improve the history display, add localization of decimal point 

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
import Ubuntu.Components 1.1
20
20
 
21
21
import "ui"
22
 
import "js/math.js" as MathJs
 
22
import "engine/math.js" as MathJs
23
23
 
24
24
MainView {
25
25
    id: mainView
35
35
 
36
36
    // This is our engine
37
37
    property var mathJs: MathJs.mathJs
38
 
    // The formula we save in the storage and we show in the history
39
 
    property var formula: ""
40
 
    // The formula we show while user is typing
 
38
 
 
39
    // The formula we will give to calculation engine, save in the storage
 
40
    // This string needs to be converted to be displayed in history
 
41
    property var engineFormula: ""
 
42
 
 
43
    // The formula or temporary reuslty which will be displayed in text input field
 
44
    property var displayedInputText: ""
 
45
 
 
46
    // The result which we show while user is typing
41
47
    property var tempResult: ""
 
48
 
42
49
    // If this is true we calculate a temporary result to show in the bottom label
43
 
    property bool isTempResultToCalc: false
 
50
    property bool isFormulaIsValidToCalculate: false
 
51
 
44
52
    // Last immission
45
53
    property var previousVisual
 
54
 
46
55
    // Becomes true after an user presses the "="
47
56
    property bool isLastCalculate: false
48
57
 
 
58
    property var numberOfOpenedBrackets: 0
 
59
 
 
60
    function validateStringForAddingToFormula(stringToAddToFormula) {
 
61
        // Check if the value is valid
 
62
        if (isNaN(stringToAddToFormula) && (isNaN(previousVisual) &&
 
63
            previousVisual !== ")")) {
 
64
            // Not two operator one after other
 
65
            return false;
 
66
        }
 
67
 
 
68
        // Do not allow adding too much closing brackets
 
69
        if (stringToAddToFormula === "(") {
 
70
            numberOfOpenedBrackets = numberOfOpenedBrackets + 1
 
71
        } else if (stringToAddToFormula === ")") {
 
72
            if (numberOfOpenedBrackets < 1) {
 
73
                return false
 
74
            }
 
75
            numberOfOpenedBrackets = numberOfOpenedBrackets - 1
 
76
        }
 
77
        return true;
 
78
    }
 
79
 
 
80
    function returnFormulaToDisplay(engineFormulaToDisplay) {
 
81
        var engineToVisualMap = {
 
82
            '-': '−',
 
83
            '/': '÷',
 
84
            '*': '×',
 
85
            '.': Qt.locale().decimalPoint
 
86
        };
 
87
        for (var engineElement in engineToVisualMap) {
 
88
            //FIXME need to add 'g' flag, but "new RegExp(engineElement, 'g');" is not working for me
 
89
            engineFormulaToDisplay = engineFormulaToDisplay.replace(engineElement, engineToVisualMap[engineElement]);
 
90
        }
 
91
        return engineFormulaToDisplay;
 
92
    }
 
93
 
 
94
 
 
95
 
49
96
    function formulaPush(visual) {
50
97
        // If the user press a number after the press of "=" we start a new
51
98
        // formula, otherwise we continue with the old one
52
99
        if (!isNaN(visual) && isLastCalculate) {
53
 
            formula = tempResult = "";
 
100
            engineFormula = displayedInputText = tempResult = "";
54
101
        }
55
102
        isLastCalculate = false;
56
103
 
57
 
        // Check if the value is valid
58
 
        if (isNaN(visual) && (isNaN(previousVisual) &&
59
 
            previousVisual != ")")) {
60
 
            // Not two operator one after other
61
 
            return;
 
104
        try {
 
105
            if (validateStringForAddingToFormula(visual) === false) {
 
106
                return
 
107
            }
 
108
        } catch(exception) {
 
109
            console.log("Error: " + exception.toString());
 
110
            return
62
111
        }
63
112
 
 
113
 
64
114
        // We save the value until next value is pushed
65
115
        previousVisual = visual;
66
116
 
67
117
        // Adding the new operator to the formula
68
 
        formula += visual.toString();
 
118
        engineFormula += visual.toString();
69
119
 
70
120
        // If we add an operator after an operator we know has priority,
71
121
        // we display a temporary result instead the all operation
72
 
        if (isNaN(visual) && isTempResultToCalc) {
73
 
            tempResult = mathJs.eval(tempResult);
74
 
            isTempResultToCalc = false;
 
122
        if (isNaN(visual) && isFormulaIsValidToCalculate) {
 
123
            try {
 
124
                tempResult = mathJs.eval(tempResult);
 
125
            } catch(exception) {
 
126
                console.log("Error: math.js" + exception.toString() + " engine formula:" + tempResult);
 
127
            }
 
128
 
 
129
            isFormulaIsValidToCalculate = false;
75
130
        }
76
131
 
77
132
        tempResult += visual.toString();
78
133
 
 
134
        try {
 
135
            displayedInputText = returnFormulaToDisplay(tempResult)
 
136
        } catch(exception) {
 
137
            console.log("Error: " + exception.toString());
 
138
            return
 
139
        }
 
140
 
79
141
        // Add here operators that have always priority
80
 
        if (visual.toString() == "*") {
81
 
            isTempResultToCalc = true;
 
142
        if ((visual.toString() === "*") || (visual.toString() === ")")) {
 
143
            isFormulaIsValidToCalculate = true;
82
144
        }
83
145
    }
84
146
 
85
147
    function calculate() {
86
 
        if (isNaN(previousVisual) && previousVisual !== ")") {
87
 
            // If the last char isn't a number or a ) we don't calculate the result
88
 
            return;
 
148
        try {
 
149
            var result = mathJs.eval(engineFormula);
 
150
        } catch(exception) {
 
151
            console.log("Error: math.js" + exception.toString() + " engine formula:" + engineFormula);
 
152
            return false;
89
153
        }
 
154
 
90
155
        isLastCalculate = true;
91
 
        var result = mathJs.eval(formula);
 
156
 
92
157
        result = result.toString();
93
 
        console.log(formula +" = " + result);
94
 
        formula = result;
 
158
 
 
159
        try {
 
160
            displayedInputText = returnFormulaToDisplay(result)
 
161
        } catch(exception) {
 
162
            console.log("Error: " + exception.toString());
 
163
            return
 
164
        }
 
165
 
 
166
        historyModel.append({"formulaToDisplay":returnFormulaToDisplay(engineFormula), "result":displayedInputText});
 
167
        engineFormula = result;
95
168
        tempResult = result;
96
 
 
97
 
        historyModel.append({"result":result});
 
169
        numberOfOpenedBrackets = 0;
98
170
    }
99
171
 
100
172
    ListModel {
119
191
            Text {
120
192
                width: parent.width
121
193
                height: units.gu(5)
122
 
                text: tempResult
 
194
                text: displayedInputText
123
195
            }
124
196
 
125
197
            // TODO: insert here actual screen