-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApp.java
More file actions
323 lines (279 loc) · 14 KB
/
App.java
File metadata and controls
323 lines (279 loc) · 14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
package exercise2;
import acm.graphics.GObject;
import acm.program.*;
import java.awt.event.MouseEvent;
public class App extends GraphicsProgram {
private static final double CANVAS_WIDTH = 540; // Calculator width
private static final double CANVAS_HEIGHT = 740; // Calculator height
private CalculatorLayout calculatorLayout; // Instantiate the Layout Object
private char opBuffer; // Stores the operator
private double operand1; // Stores the operand digits
private String result; // Stores the results
private String memoryValue; // Variable to store the value in memory
private boolean isFirstOp; // Checks if first operator
private boolean isPriorEquals; // Checks if it is prior to equal sign
private boolean isFirstPoint; // Checks if first decimal point
private boolean isDeletable; // Checks if it is deletable
private boolean isRadiansMode = false; // Flag for radians (true) or degrees (false)
private boolean isHyperbolicMode = false; // Flag for hyperbolic mode (true) or normal mode (false)
public void run() {
setTitle("LBYCPEI Scientific Calculator");
setCanvasSize(CANVAS_WIDTH, CANVAS_HEIGHT);
calculatorLayout = new CalculatorLayout(getHeight());
add(calculatorLayout);
initBooleans();
addMouseListeners(); // Adds the program as both a MouseListener and MouseMotionListener to the canvas.
}
public void mouseClicked(MouseEvent e) {
GObject element = calculatorLayout.getElementAt(e.getX(), e.getY());
if (element instanceof MyButton) {
String input = ((MyButton) element).getText();
// Handle special cases: Clear Element, Clear All, and Delete
if (input.equals("CE")) {
calculatorLayout.clearMainDisplay();
calculatorLayout.clearMemoElement(opBuffer);
return;
}
if (input.equals("C")) {
calculatorLayout.clearMainDisplay();
calculatorLayout.clearMemoDisplay();
initBooleans();
return;
}
if (input.equals("⌫") && isDeletable) {
calculatorLayout.deleteOneCharacter();
return;
}
// Handle reciprocal function
if (input.equals("1/x")) {
double operand = Double.parseDouble(calculatorLayout.getMainDisplay());
double result = 1.0 / operand;
calculatorLayout.setMainDisplay(String.valueOf(result));
calculatorLayout.clearMemoDisplay();
initBooleans();
return;
}
// Handle square root function
if (input.equals("√")) {
double operand = Double.parseDouble(calculatorLayout.getMainDisplay());
double sqrtResult = Math.sqrt(operand);
calculatorLayout.setMainDisplay(String.valueOf(sqrtResult));
calculatorLayout.clearMemoDisplay();
return;
}
// Handle exponentiation function
if (input.equals("^")) {
operand1 = Double.parseDouble(calculatorLayout.getMainDisplay());
calculatorLayout.setMainDisplay("");
calculatorLayout.clearMemoDisplay();
calculatorLayout.setMemoDisplay(operand1 + " ^ ");
opBuffer = '^';
isFirstOp = false;
isFirstPoint = true;
return;
}
// Handle trigonometric and logarithmic functions
if (input.equals("sin") || input.equals("cos") || input.equals("tan") || input.equals("sinh") || input.equals("cosh") || input.equals("tanh") || input.equals("log") || input.equals("ln")) {
double operand = Double.parseDouble(calculatorLayout.getMainDisplay());
String degreeSymbol = isRadiansMode ? "" : "°";
String functionDisplay = input + "(" + calculatorLayout.getMainDisplay() + degreeSymbol + ")";
calculatorLayout.setMainDisplay("");
if (!isOperator(opBuffer) && !isFirstOp && !isPriorEquals) {
calculatorLayout.setMemoDisplay(calculatorLayout.getMemoDisplay() + " " + functionDisplay);
} else {
calculatorLayout.clearMemoDisplay();
calculatorLayout.setMemoDisplay(functionDisplay);
}
double result = switch (input) {
case "sin" -> isRadiansMode ? Math.sin(operand) : Math.sin(Math.toRadians(operand));
case "cos" -> isRadiansMode ? Math.cos(operand) : Math.cos(Math.toRadians(operand));
case "tan" -> isRadiansMode ? Math.tan(operand) : Math.tan(Math.toRadians(operand));
case "sinh" -> isRadiansMode ? Math.sinh(operand) : Math.sinh(Math.toRadians(operand));
case "cosh" -> isRadiansMode ? Math.cosh(operand) : Math.cosh(Math.toRadians(operand));
case "tanh" -> isRadiansMode ? Math.tanh(operand) : Math.tanh(Math.toRadians(operand));
case "log" -> Math.log10(operand);
case "ln" -> Math.log(operand);
default -> 0.0;
};
calculatorLayout.setMainDisplay(String.valueOf(result));
return;
}
// II. Handle arithmetic symbols and operations
char symbol = input.charAt(0);
if (symbol == '(' || symbol == ')') {
if (calculatorLayout.getMainDisplay().equals("0")) {
calculatorLayout.setMainDisplay(String.valueOf(symbol));
} else {
calculatorLayout.appendMainDisplay(String.valueOf(symbol));
}
return;
}
if (symbol == '±' && isDeletable) {
calculatorLayout.negateElement(opBuffer);
System.out.println("Negation Called");
return;
}
if ((symbol >= '0' && symbol <= '9') || symbol == '.' || symbol == 'e' || symbol == 'π') {
isDeletable = true;
if (symbol == '.') {
if (!isFirstPoint) {
return;
} else {
isFirstPoint = false;
}
}
if (isPriorEquals) {
calculatorLayout.clearMainDisplay();
isPriorEquals = false;
System.out.println("Digit: Prior Equals");
}
if (symbol == 'π') {
double operand = Math.PI;
if (calculatorLayout.getMainDisplay().equals("0")) {
calculatorLayout.setMainDisplay(String.valueOf(operand));
} else {
calculatorLayout.appendMainDisplay(String.valueOf(operand));
}
return;
}
if (symbol == 'e') {
double operand = Math.E;
if (calculatorLayout.getMainDisplay().equals("0")) {
calculatorLayout.setMainDisplay(String.valueOf(operand));
} else {
calculatorLayout.appendMainDisplay(String.valueOf(operand));
}
return;
}
if (calculatorLayout.getMainDisplay().equals("0") && symbol != '.') {
calculatorLayout.setMainDisplay(String.valueOf(symbol));
} else {
calculatorLayout.appendMainDisplay(String.valueOf(symbol));
}
calculatorLayout.setMemoDisplay(symbol);
System.out.println("Digit: Prior Not Equals");
return;
}
// Handle factorial symbol
if (symbol == '!') {
String currentDisplay = calculatorLayout.getMainDisplay();
try {
int number = Integer.parseInt(currentDisplay);
if (number < 0) {
System.out.println("Error: Factorial of a negative number is not defined");
return;
}
long factorial = calculateFactorial(number);
calculatorLayout.setMainDisplay(String.valueOf(factorial));
calculatorLayout.setMemoDisplay("!");
System.out.println("Factorial Calculated: " + factorial);
} catch (NumberFormatException ex) {
System.out.println("Error: Invalid input for factorial");
}
return;
}
if (isOperator(symbol)) {
if (isFirstOp && !isPriorEquals) {
operand1 = Double.parseDouble(calculatorLayout.getMainDisplay());
calculatorLayout.setMemoDisplay(String.valueOf(symbol));
opBuffer = symbol;
isFirstOp = false;
System.out.println("Operator: First Operation and Not prior equals");
} else if (isPriorEquals) {
calculatorLayout.setMemoDisplay(result + symbol);
opBuffer = symbol;
isFirstOp = false;
System.out.println("Operator: Prior equals!");
} else {
double operand2 = Double.parseDouble(calculatorLayout.getMainDisplay());
operand1 = MathHandler.evaluate(operand1, operand2, opBuffer);
result = String.valueOf(operand1);
result = result.contains(".") ? result.replaceAll("0*$", "").replaceAll("\\.$", "") : result;
calculatorLayout.setMainDisplay(result);
calculatorLayout.setMemoDisplay(String.valueOf(symbol));
isDeletable = false;
System.out.println("Operator: Second operator");
}
calculatorLayout.clearNumBuffer();
isFirstPoint = true;
}
if (symbol == '=') {
if (opBuffer == '^') {
double exponent = Double.parseDouble(calculatorLayout.getMainDisplay());
double result = Math.pow(operand1, exponent);
calculatorLayout.setMainDisplay(String.valueOf(result));
initBooleans();
return;
}
double operand2 = Double.parseDouble(calculatorLayout.getMainDisplay());
operand1 = MathHandler.evaluate(operand1, operand2, opBuffer);
result = String.valueOf(operand1);
result = result.contains(".") ? result.replaceAll("0*$", "").replaceAll("\\.$", "") : result;
calculatorLayout.setMainDisplay(result);
calculatorLayout.clearMemoDisplay();
initBooleans();
System.out.println("Equals: evaluated");
System.out.println("operand1 = " + operand1);
System.out.println("operand2 = " + operand2);
}
if (input.equals("DEG") || input.equals("RAD")) {
isRadiansMode = !isRadiansMode;
((MyButton) element).setText(isRadiansMode ? "RAD" : "DEG");
return;
}
if (input.equals("hyp") || input.equals("HYP")) {
isHyperbolicMode = !isHyperbolicMode;
((MyButton) element).setText(isHyperbolicMode ? "HYP" : "hyp");
updateTrigFunctionLabels();
return;
}
}
}
private void initBooleans() {
isFirstOp = true;
isPriorEquals = true;
isDeletable = false;
isFirstPoint = true;
}
private boolean isOperator(char symbol) {
return (symbol == '+' || symbol == '-' || symbol == 'x' || symbol == '÷');
}
private void updateTrigFunctionLabels() {
for (GObject obj : calculatorLayout) {
if (obj instanceof MyButton) {
MyButton button = (MyButton) obj;
String label = button.getText();
switch (label) {
case "sin", "sinh" -> button.setText(isHyperbolicMode ? "sinh" : "sin");
case "cos", "cosh" -> button.setText(isHyperbolicMode ? "cosh" : "cos");
case "tan", "tanh" -> button.setText(isHyperbolicMode ? "tanh" : "tan");
}
}
}
}
private double evaluateExpressionInsideParentheses(String expression) {
if (expression.startsWith("(") && expression.endsWith(")")) {
expression = expression.substring(1, expression.length() - 1);
}
String[] parts = expression.split("\\+");
double sum = 0.0;
for (String part : parts) {
sum += Double.parseDouble(part);
}
return sum;
}
private String formatResult(double result) {
String formattedResult = String.valueOf(result);
return formattedResult.contains(".") ? formattedResult.replaceAll("0*$", "").replaceAll("\\.$", "") : formattedResult;
}
private long calculateFactorial(int number) {
long result = 1;
for (int i = 1; i <= number; i++) {
result *= i;
}
return result;
}
public static void main(String[] args) {
(new App()).start(args);
}
}