diff --git a/build/classes/Calc/AddOperation.class b/build/classes/Calc/AddOperation.class
new file mode 100644
index 0000000..2d96ae1
Binary files /dev/null and b/build/classes/Calc/AddOperation.class differ
diff --git a/build/classes/Calc/App.class b/build/classes/Calc/App.class
index da00d82..091a3e3 100644
Binary files a/build/classes/Calc/App.class and b/build/classes/Calc/App.class differ
diff --git a/build/classes/Calc/Calculator$1.class b/build/classes/Calc/Calculator$1.class
index a117654..8603d1c 100644
Binary files a/build/classes/Calc/Calculator$1.class and b/build/classes/Calc/Calculator$1.class differ
diff --git a/build/classes/Calc/Calculator$10.class b/build/classes/Calc/Calculator$10.class
index 49bdff6..9419604 100644
Binary files a/build/classes/Calc/Calculator$10.class and b/build/classes/Calc/Calculator$10.class differ
diff --git a/build/classes/Calc/Calculator$11.class b/build/classes/Calc/Calculator$11.class
index fd25d7a..85a3946 100644
Binary files a/build/classes/Calc/Calculator$11.class and b/build/classes/Calc/Calculator$11.class differ
diff --git a/build/classes/Calc/Calculator$12.class b/build/classes/Calc/Calculator$12.class
index 03ef14d..037822f 100644
Binary files a/build/classes/Calc/Calculator$12.class and b/build/classes/Calc/Calculator$12.class differ
diff --git a/build/classes/Calc/Calculator$13.class b/build/classes/Calc/Calculator$13.class
index 5cca439..4bef4c0 100644
Binary files a/build/classes/Calc/Calculator$13.class and b/build/classes/Calc/Calculator$13.class differ
diff --git a/build/classes/Calc/Calculator$14.class b/build/classes/Calc/Calculator$14.class
index 806ada4..7aa0e62 100644
Binary files a/build/classes/Calc/Calculator$14.class and b/build/classes/Calc/Calculator$14.class differ
diff --git a/build/classes/Calc/Calculator$15.class b/build/classes/Calc/Calculator$15.class
index 0aa9102..01bab5c 100644
Binary files a/build/classes/Calc/Calculator$15.class and b/build/classes/Calc/Calculator$15.class differ
diff --git a/build/classes/Calc/Calculator$16.class b/build/classes/Calc/Calculator$16.class
index c65b9c9..562c020 100644
Binary files a/build/classes/Calc/Calculator$16.class and b/build/classes/Calc/Calculator$16.class differ
diff --git a/build/classes/Calc/Calculator$17.class b/build/classes/Calc/Calculator$17.class
new file mode 100644
index 0000000..f8aae67
Binary files /dev/null and b/build/classes/Calc/Calculator$17.class differ
diff --git a/build/classes/Calc/Calculator$18.class b/build/classes/Calc/Calculator$18.class
new file mode 100644
index 0000000..0461dd7
Binary files /dev/null and b/build/classes/Calc/Calculator$18.class differ
diff --git a/build/classes/Calc/Calculator$2.class b/build/classes/Calc/Calculator$2.class
index 6dac975..93b9705 100644
Binary files a/build/classes/Calc/Calculator$2.class and b/build/classes/Calc/Calculator$2.class differ
diff --git a/build/classes/Calc/Calculator$3.class b/build/classes/Calc/Calculator$3.class
index 63850f2..bf96002 100644
Binary files a/build/classes/Calc/Calculator$3.class and b/build/classes/Calc/Calculator$3.class differ
diff --git a/build/classes/Calc/Calculator$4.class b/build/classes/Calc/Calculator$4.class
index b26adb5..a09c8c5 100644
Binary files a/build/classes/Calc/Calculator$4.class and b/build/classes/Calc/Calculator$4.class differ
diff --git a/build/classes/Calc/Calculator$5.class b/build/classes/Calc/Calculator$5.class
index 82f7ce0..731178e 100644
Binary files a/build/classes/Calc/Calculator$5.class and b/build/classes/Calc/Calculator$5.class differ
diff --git a/build/classes/Calc/Calculator$6.class b/build/classes/Calc/Calculator$6.class
index f3df049..0d871a7 100644
Binary files a/build/classes/Calc/Calculator$6.class and b/build/classes/Calc/Calculator$6.class differ
diff --git a/build/classes/Calc/Calculator$7.class b/build/classes/Calc/Calculator$7.class
index be005d5..b307ae4 100644
Binary files a/build/classes/Calc/Calculator$7.class and b/build/classes/Calc/Calculator$7.class differ
diff --git a/build/classes/Calc/Calculator$8.class b/build/classes/Calc/Calculator$8.class
index e522a87..548a009 100644
Binary files a/build/classes/Calc/Calculator$8.class and b/build/classes/Calc/Calculator$8.class differ
diff --git a/build/classes/Calc/Calculator$9.class b/build/classes/Calc/Calculator$9.class
index c365a00..4632111 100644
Binary files a/build/classes/Calc/Calculator$9.class and b/build/classes/Calc/Calculator$9.class differ
diff --git a/build/classes/Calc/Calculator$AddOperation.class b/build/classes/Calc/Calculator$AddOperation.class
new file mode 100644
index 0000000..9cc8780
Binary files /dev/null and b/build/classes/Calc/Calculator$AddOperation.class differ
diff --git a/build/classes/Calc/Calculator$DivOperation.class b/build/classes/Calc/Calculator$DivOperation.class
new file mode 100644
index 0000000..3d6e534
Binary files /dev/null and b/build/classes/Calc/Calculator$DivOperation.class differ
diff --git a/build/classes/Calc/Calculator$HistoryOperation.class b/build/classes/Calc/Calculator$HistoryOperation.class
new file mode 100644
index 0000000..fdf4946
Binary files /dev/null and b/build/classes/Calc/Calculator$HistoryOperation.class differ
diff --git a/build/classes/Calc/Calculator$LoggingOperation.class b/build/classes/Calc/Calculator$LoggingOperation.class
new file mode 100644
index 0000000..82a802c
Binary files /dev/null and b/build/classes/Calc/Calculator$LoggingOperation.class differ
diff --git a/build/classes/Calc/Calculator$MultOperation.class b/build/classes/Calc/Calculator$MultOperation.class
new file mode 100644
index 0000000..e02eb96
Binary files /dev/null and b/build/classes/Calc/Calculator$MultOperation.class differ
diff --git a/build/classes/Calc/Calculator$Operation.class b/build/classes/Calc/Calculator$Operation.class
new file mode 100644
index 0000000..da08fbf
Binary files /dev/null and b/build/classes/Calc/Calculator$Operation.class differ
diff --git a/build/classes/Calc/Calculator$OperationDecorator.class b/build/classes/Calc/Calculator$OperationDecorator.class
new file mode 100644
index 0000000..01c0e00
Binary files /dev/null and b/build/classes/Calc/Calculator$OperationDecorator.class differ
diff --git a/build/classes/Calc/Calculator$SubOperation.class b/build/classes/Calc/Calculator$SubOperation.class
new file mode 100644
index 0000000..3c8f42e
Binary files /dev/null and b/build/classes/Calc/Calculator$SubOperation.class differ
diff --git a/build/classes/Calc/Calculator.class b/build/classes/Calc/Calculator.class
index 5b5e377..36be565 100644
Binary files a/build/classes/Calc/Calculator.class and b/build/classes/Calc/Calculator.class differ
diff --git a/build/classes/Calc/Calculator.form b/build/classes/Calc/Calculator.form
index bedbeaf..7ed5165 100644
--- a/build/classes/Calc/Calculator.form
+++ b/build/classes/Calc/Calculator.form
@@ -929,6 +929,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/classes/Calc/CalculatorFacade.class b/build/classes/Calc/CalculatorFacade.class
new file mode 100644
index 0000000..c099a4b
Binary files /dev/null and b/build/classes/Calc/CalculatorFacade.class differ
diff --git a/build/classes/Calc/CalculatorState.class b/build/classes/Calc/CalculatorState.class
new file mode 100644
index 0000000..5ecbc8d
Binary files /dev/null and b/build/classes/Calc/CalculatorState.class differ
diff --git a/build/classes/Calc/Command.class b/build/classes/Calc/Command.class
new file mode 100644
index 0000000..4b7261d
Binary files /dev/null and b/build/classes/Calc/Command.class differ
diff --git a/build/classes/Calc/ComputeCommand.class b/build/classes/Calc/ComputeCommand.class
new file mode 100644
index 0000000..a7999e1
Binary files /dev/null and b/build/classes/Calc/ComputeCommand.class differ
diff --git a/build/classes/Calc/DivOperation.class b/build/classes/Calc/DivOperation.class
new file mode 100644
index 0000000..6920a0e
Binary files /dev/null and b/build/classes/Calc/DivOperation.class differ
diff --git a/build/classes/Calc/HistoryOperation.class b/build/classes/Calc/HistoryOperation.class
new file mode 100644
index 0000000..1a91510
Binary files /dev/null and b/build/classes/Calc/HistoryOperation.class differ
diff --git a/build/classes/Calc/IdleState.class b/build/classes/Calc/IdleState.class
new file mode 100644
index 0000000..1817216
Binary files /dev/null and b/build/classes/Calc/IdleState.class differ
diff --git a/build/classes/Calc/LoggingOperation.class b/build/classes/Calc/LoggingOperation.class
new file mode 100644
index 0000000..ab40673
Binary files /dev/null and b/build/classes/Calc/LoggingOperation.class differ
diff --git a/build/classes/Calc/MultOperation.class b/build/classes/Calc/MultOperation.class
new file mode 100644
index 0000000..0fd7bc1
Binary files /dev/null and b/build/classes/Calc/MultOperation.class differ
diff --git a/build/classes/Calc/Operation.class b/build/classes/Calc/Operation.class
new file mode 100644
index 0000000..c6822e7
Binary files /dev/null and b/build/classes/Calc/Operation.class differ
diff --git a/build/classes/Calc/OperationDecorator.class b/build/classes/Calc/OperationDecorator.class
new file mode 100644
index 0000000..306805a
Binary files /dev/null and b/build/classes/Calc/OperationDecorator.class differ
diff --git a/build/classes/Calc/OperationFactory.class b/build/classes/Calc/OperationFactory.class
new file mode 100644
index 0000000..45722d8
Binary files /dev/null and b/build/classes/Calc/OperationFactory.class differ
diff --git a/build/classes/Calc/OperationSelectedState.class b/build/classes/Calc/OperationSelectedState.class
new file mode 100644
index 0000000..7ce0e10
Binary files /dev/null and b/build/classes/Calc/OperationSelectedState.class differ
diff --git a/build/classes/Calc/ResultState.class b/build/classes/Calc/ResultState.class
new file mode 100644
index 0000000..d956e7d
Binary files /dev/null and b/build/classes/Calc/ResultState.class differ
diff --git a/build/classes/Calc/SubOperation.class b/build/classes/Calc/SubOperation.class
new file mode 100644
index 0000000..784512d
Binary files /dev/null and b/build/classes/Calc/SubOperation.class differ
diff --git a/build/classes/Calc/TypingState.class b/build/classes/Calc/TypingState.class
new file mode 100644
index 0000000..e01ac31
Binary files /dev/null and b/build/classes/Calc/TypingState.class differ
diff --git a/nbproject/private/private.properties b/nbproject/private/private.properties
index a6eba98..f778d18 100644
--- a/nbproject/private/private.properties
+++ b/nbproject/private/private.properties
@@ -5,4 +5,4 @@ do.jlink=true
javac.debug=true
javadoc.preview=true
jlink.strip=false
-user.properties.file=C:\\Users\\SasUke UtChiHa\\AppData\\Roaming\\NetBeans\\15\\build.properties
+user.properties.file=C:\\Users\\Sulta\\AppData\\Roaming\\NetBeans\\27\\build.properties
diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml
index 6807a2b..71b1334 100644
--- a/nbproject/private/private.xml
+++ b/nbproject/private/private.xml
@@ -2,6 +2,10 @@
-
+
+ file:/C:/Users/Sulta/OneDrive/Documents/NetBeansProjects/calculator-java-swing-refactor/src/Calc/App.java
+ file:/C:/Users/Sulta/OneDrive/Documents/NetBeansProjects/calculator-java-swing-refactor/src/Calc/Calculator.java
+ file:/C:/Users/Sulta/OneDrive/Documents/NetBeansProjects/calculator-java-swing-refactor/src/Calc/CalculatorFacade.java
+
diff --git a/src/Calc/AddOperation.java b/src/Calc/AddOperation.java
new file mode 100644
index 0000000..0fdecce
--- /dev/null
+++ b/src/Calc/AddOperation.java
@@ -0,0 +1,13 @@
+
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public class AddOperation implements Operation{
+ @Override
+ public float apply(float a, float b) {
+ return a + b;
+ }
+}
diff --git a/src/Calc/App.java b/src/Calc/App.java
index 4101058..f658618 100644
--- a/src/Calc/App.java
+++ b/src/Calc/App.java
@@ -1,14 +1,19 @@
package Calc;
-/**
- *
- * @author youcefhmd
- */
-
public class App {
-
public static void main(String[] args) {
- new Calculator().setVisible(true);
- }
+ javax.swing.SwingUtilities.invokeLater(() -> {
+
+ CalculatorFacade calcFacade = new CalculatorFacade();
+ // بدل ما نستدعي Calculator مباشرة:
+ calcFacade.showCalculator();
+
+ // مثال تشغيل:
+ float result = calcFacade.performOperation("+", 5, 3);
+ System.out.println("Result = " + result);
+ });
+ }
}
+
+//
\ No newline at end of file
diff --git a/src/Calc/Calculator.form b/src/Calc/Calculator.form
index bedbeaf..7ed5165 100644
--- a/src/Calc/Calculator.form
+++ b/src/Calc/Calculator.form
@@ -929,6 +929,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Calc/Calculator.java b/src/Calc/Calculator.java
index 7e2a37c..d9635ba 100644
--- a/src/Calc/Calculator.java
+++ b/src/Calc/Calculator.java
@@ -3,25 +3,169 @@
import java.awt.Color;
import java.awt.event.*;
import javax.swing.JButton;
+import Calc.Operation;
+import Calc.AddOperation;
+import Calc.SubOperation;
+import Calc.MultOperation;
+import Calc.DivOperation;
+import Calc.OperationFactory;
+import Calc.OperationDecorator;
+import Calc.HistoryOperation;
+import Calc.LoggingOperation;
+
/**
*
* @author youcefhmd
*/
public final class Calculator extends javax.swing.JFrame {
-
+
private String currentOperand;
private String previousOperand;
private String operation;
-
private int x, y;
+
+ // --- Singleton Method ---
+ private static Calculator INSTANCE;
- public Calculator() {
- initComponents();
- getContentPane().setSize(400, 700);
- this.clear();
- this.addEvents();
+ public static Calculator getInstance() {
+ if (INSTANCE == null) {
+ INSTANCE = new Calculator();
+ }
+ return INSTANCE;
+ }
+
+
+
+
+ // -------------------- Command Pattern --------------------
+
+public java.util.Stack undoStack = new java.util.Stack<>();
+public java.util.Stack redoStack = new java.util.Stack<>();
+
+public void undoLast() {
+ if (!undoStack.isEmpty()) {
+ Command cmd = undoStack.pop();
+ cmd.undo();
+ redoStack.push(cmd);
}
+}
+
+public void redoLast() {
+ if (!redoStack.isEmpty()) {
+ Command cmd = redoStack.pop();
+ cmd.execute();
+ undoStack.push(cmd);
+ }
+}
+
+
+
+void applyRedo(String curr) {
+ this.currentOperand = curr;
+ this.previousOperand = "";
+ this.operation = "";
+ updateDisplay();
+}
+
+void applyUndo(String prev, String curr, String op) {
+ this.previousOperand = prev;
+ this.currentOperand = curr;
+ this.operation = op;
+ updateDisplay();
+}
+
+ // --------------------END Command Pattern --------------------
+
+
+
+
+
+
+ // -------------------- State Pattern --------------------
+private CalculatorState state = new IdleState();
+
+public void setState(CalculatorState newState) {
+ this.state = newState;
+}
+
+// دوال هندل (واجهة واضحة تُنادى من الأزرار)
+public void handleNumber(String digit) {
+ state.onNumber(this, digit);
+}
+
+public void handleOperation(String op) {
+ state.onOperation(this, op);
+}
+
+public void handleEquals() {
+ state.onEquals(this);
+}
+
+public void handleClear() {
+ state.onClear(this);
+}
+// ---------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+private Calculator() {
+ initComponents();
+ getContentPane().setSize(400, 700);
+ this.clear();
+ this.addEvents();
+}
+
+
+
+
+
+
+
+// --- Helper Methods used by States ---
+
+public void setDisplay(String value) {
+ this.currentOperand = value;
+ updateDisplay();
+}
+
+public void appendDigit(String digit) {
+ this.currentOperand += digit;
+ updateDisplay();
+}
+
+public void clearDisplay() {
+ this.currentOperand = "";
+ this.previousOperand = "";
+ updateDisplay();
+}
+
+public void saveFirstOperand() {
+ this.previousOperand = this.currentOperand;
+}
+
+public void setOperation(String op) {
+ this.operation = op;
+ updateDisplay();
+}
+// ---------------- END STATE PATTERN ---------------
+
+
+
+
+
+
+
+
public void addEvents() {
JButton[] btns = {
@@ -35,12 +179,27 @@ public void addEvents() {
btn0, btn1, btn2, btn3, btn4,
btn5, btn6, btn7, btn8, btn9
};
+
+
+
+
+
+
+
+
+for (JButton number : numbers) {
+ number.addActionListener((ActionEvent e) -> {
+ handleNumber(((JButton) e.getSource()).getText());
+ });
+}
+
+
+
+
+
+
+
- for (JButton number : numbers) {
- number.addActionListener((ActionEvent e) -> {
- appendNumber(((JButton) e.getSource()).getText());
- });
- }
for (JButton btn : btns) {
btn.addMouseListener(new MouseAdapter() {
@@ -61,7 +220,7 @@ public void mouseExited(MouseEvent e) {
}
});
}
- }
+ }
public void clear() {
this.currentOperand = "";
@@ -108,43 +267,77 @@ public void chooseOperation(String operation) {
this.updateDisplay();
}
- public void compute() {
- float computation;
- if (this.currentOperand.equals("") || this.previousOperand.equals("")) {
- return;
- }
+public void compute() {
+
+
+
+String beforePrev = this.previousOperand;
+String beforeCurr = this.currentOperand;
+String beforeOp = this.operation;
+
+
+
+
+
+ if (this.currentOperand.equals("") || this.previousOperand.equals("")) {
+ return;
+ }
+ try {
float curr = Float.parseFloat(this.currentOperand);
float prev = Float.parseFloat(this.previousOperand);
- if (Float.isNaN(curr) || Float.isNaN(prev)) {
- return;
- }
- switch (this.operation) {
- case "+" ->
- computation = prev + curr;
- case "-" ->
- computation = prev - curr;
- case "×" ->
- computation = prev * curr;
- case "÷" -> {
- if (curr == 0) {
- this.clear();
- this.currentOperand = "Error";
- return;
- }
- computation = prev / curr;
- }
- default -> {
- return;
- }
- }
+ // نجيب العملية الأساسية من الفاكتوري
+ Operation op = OperationFactory.getOperation(this.operation);
- this.currentOperand = (computation - (int) computation) != 0 ? Float.toString(computation) : Integer.toString((int) computation);
- this.previousOperand = "";
- this.operation = "";
+ // نغلفها بـ History + Logging (Decorator Pattern)
+ op = new HistoryOperation(op);
+ op = new LoggingOperation(op);
+
+ float result = op.apply(prev, curr);
+
+ this.currentOperand = (result - (int) result) != 0
+ ? Float.toString(result )
+ : Integer.toString((int) result );
+
+ } catch (IllegalArgumentException | ArithmeticException ex) {
+ this.clear();
+ this.currentOperand = "Error";
+ return;
}
+
+
+
+
+
+ //هنا تنفيذ الكوماند باترن
+ String afterCurr = this.currentOperand;
+
+Command cmd = new ComputeCommand(
+ this,
+ OperationFactory.getOperation(beforeOp),
+ beforePrev,
+ beforeCurr,
+ beforeOp,
+ afterCurr
+);
+
+undoStack.push(cmd);
+redoStack.clear();
+
+
+
+
+
+
+
+
+ this.previousOperand = "";
+ this.operation = "";
+}
+
+
public void updateDisplay() {
current.setText(this.currentOperand);
previous.setText(previousOperand + " " + this.operation);
@@ -178,6 +371,9 @@ private void initComponents() {
btn0 = new javax.swing.JButton();
btnDot = new javax.swing.JButton();
btnEqual = new javax.swing.JButton();
+ jButton1 = new javax.swing.JButton();
+ btnUndo = new javax.swing.JButton();
+ btnRedo = new javax.swing.JButton();
titleBar = new javax.swing.JPanel();
title = new javax.swing.JLabel();
btnMini = new javax.swing.JButton();
@@ -492,6 +688,25 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
});
buttonsPanel.add(btnEqual, new org.netbeans.lib.awtextra.AbsoluteConstraints(230, 300, -1, -1));
+ jButton1.setText("jButton1");
+ buttonsPanel.add(jButton1, new org.netbeans.lib.awtextra.AbsoluteConstraints(130, 50, -1, -1));
+
+ btnUndo.setText("Undo");
+ btnUndo.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btnUndoActionPerformed(evt);
+ }
+ });
+ buttonsPanel.add(btnUndo, new org.netbeans.lib.awtextra.AbsoluteConstraints(20, 0, -1, 20));
+
+ btnRedo.setText("Redo");
+ btnRedo.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btnRedoActionPerformed(evt);
+ }
+ });
+ buttonsPanel.add(btnRedo, new org.netbeans.lib.awtextra.AbsoluteConstraints(100, 0, -1, 20));
+
app.add(buttonsPanel, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 140, 320, 390));
titleBar.setBackground(new java.awt.Color(21, 20, 22));
@@ -581,7 +796,7 @@ private void btnDotActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:
}//GEN-LAST:event_btnDotActionPerformed
private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed
- clear();
+ handleClear();
}//GEN-LAST:event_btnClearActionPerformed
private void btnDelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDelActionPerformed
@@ -592,24 +807,40 @@ private void btnDelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:
}//GEN-LAST:event_btnDelActionPerformed
private void btnPlusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPlusActionPerformed
- chooseOperation("+");
+ handleOperation("+");
}//GEN-LAST:event_btnPlusActionPerformed
private void btnMultActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMultActionPerformed
- chooseOperation("×");
+ handleOperation("×");
}//GEN-LAST:event_btnMultActionPerformed
private void btnSubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSubActionPerformed
- chooseOperation("-");
+ handleOperation("-");
}//GEN-LAST:event_btnSubActionPerformed
private void btnDivActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDivActionPerformed
- chooseOperation("÷");
+ handleOperation("÷");
}//GEN-LAST:event_btnDivActionPerformed
private void btnEqualActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEqualActionPerformed
- this.compute();
- this.updateDisplay();
+handleEquals();
+
+
+
+
+ System.out.println("---- History ----");
+for (String h : HistoryOperation.getHistory()) {
+ System.out.println(h);
+}
+
+
+
+
+
+
+
+
+
if (this.currentOperand.equals("Error"))
this.currentOperand = "";
}//GEN-LAST:event_btnEqualActionPerformed
@@ -659,6 +890,16 @@ private void titleBarMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:ev
this.setLocation(xx - x, yy - y);
}//GEN-LAST:event_titleBarMouseDragged
+ private void btnUndoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnUndoActionPerformed
+ // TODO add your handling code here:
+ undoLast();
+ }//GEN-LAST:event_btnUndoActionPerformed
+
+ private void btnRedoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRedoActionPerformed
+ // TODO add your handling code here:
+ redoLast();
+ }//GEN-LAST:event_btnRedoActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel app;
private static javax.swing.JButton btn0;
@@ -681,9 +922,12 @@ private void titleBarMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:ev
private static javax.swing.JButton btnMult;
private static javax.swing.JButton btnPlus;
private static javax.swing.JButton btnPlusSub;
+ private javax.swing.JButton btnRedo;
private static javax.swing.JButton btnSub;
+ private javax.swing.JButton btnUndo;
private javax.swing.JPanel buttonsPanel;
private javax.swing.JTextField current;
+ private javax.swing.JButton jButton1;
private javax.swing.JTextField previous;
private javax.swing.JPanel resultsPanel;
private javax.swing.JLabel title;
diff --git a/src/Calc/CalculatorFacade.java b/src/Calc/CalculatorFacade.java
new file mode 100644
index 0000000..a43218c
--- /dev/null
+++ b/src/Calc/CalculatorFacade.java
@@ -0,0 +1,39 @@
+package Calc;
+
+
+import Calc.Operation;
+import Calc.OperationFactory;
+import java.util.List;
+import Calc.HistoryOperation;
+public class CalculatorFacade {
+
+ private Calculator calculator;
+
+ public CalculatorFacade() {
+ calculator = Calculator.getInstance(); // Singleton
+ }
+
+ // تفتح واجهة الآلة الحاسبة
+ public void showCalculator() {
+ calculator.setVisible(true);
+ }
+
+ // تنفّذ عملية رياضية وتُرجع الناتج
+ public float performOperation(String operation, float a, float b) {
+ Operation op = OperationFactory.getOperation(operation);
+ if (op == null) {
+ throw new IllegalArgumentException("Invalid operation: " + operation);
+ }
+ return op.apply(a, b);
+ }
+
+ // تمسح كل شي من الشاشة (Clear)
+ public void clearCalculator() {
+ calculator.clear();
+ }
+
+ // تعرض الـ History (من Decorator)
+ public java.util.List getHistory() {
+ return HistoryOperation.getHistory();
+ }
+}
diff --git a/src/Calc/CalculatorState.java b/src/Calc/CalculatorState.java
new file mode 100644
index 0000000..05bb85f
--- /dev/null
+++ b/src/Calc/CalculatorState.java
@@ -0,0 +1,16 @@
+package Calc;
+
+/**
+ * واجهة تمثل حالة الآلة الحاسبة.
+ * كل حالة تحدد كيف تتصرف الآلة عند ضغط رقم / عملية / يساوي / مسح.
+ */
+public interface CalculatorState {
+
+ void onNumber(Calculator calc, String digit);
+
+ void onOperation(Calculator calc, String op);
+
+ void onEquals(Calculator calc);
+
+ void onClear(Calculator calc);
+}
diff --git a/src/Calc/Command.java b/src/Calc/Command.java
new file mode 100644
index 0000000..a798aed
--- /dev/null
+++ b/src/Calc/Command.java
@@ -0,0 +1,10 @@
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public interface Command {
+ void execute();
+ void undo();
+}
diff --git a/src/Calc/ComputeCommand.java b/src/Calc/ComputeCommand.java
new file mode 100644
index 0000000..0b54b0e
--- /dev/null
+++ b/src/Calc/ComputeCommand.java
@@ -0,0 +1,47 @@
+package Calc;
+import javax.swing.JTextField;
+
+public class ComputeCommand implements Command{
+ private final Calculator calc;
+ private final Operation operation;
+
+ // قيم قبل العملية
+ private final String beforePrev;
+ private final String beforeCurr;
+ private final String beforeOp;
+
+ // قيم بعد العملية (النتيجة)
+ private final String afterCurr;
+
+ public ComputeCommand(
+ Calculator calc,
+ Operation operation,
+ String beforePrev,
+ String beforeCurr,
+ String beforeOp,
+ String afterCurr) {
+
+ this.calc = calc;
+ this.operation = operation;
+
+ this.beforePrev = beforePrev;
+ this.beforeCurr = beforeCurr;
+ this.beforeOp = beforeOp;
+ this.afterCurr = afterCurr;
+ }
+
+ @Override
+ public void execute() {
+ calc.applyRedo(afterCurr);
+ HistoryOperation.addEntry("Redo : " + afterCurr);
+
+ }
+
+ @Override
+ public void undo() {
+ // إعادة حالة قبل العملية
+ calc.applyUndo(beforePrev, beforeCurr, beforeOp);
+ HistoryOperation.addEntry("Undo → "
+ + beforePrev + " " + beforeOp + " " + beforeCurr);
+ }
+}
diff --git a/src/Calc/DivOperation.java b/src/Calc/DivOperation.java
new file mode 100644
index 0000000..daa39a5
--- /dev/null
+++ b/src/Calc/DivOperation.java
@@ -0,0 +1,16 @@
+
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public class DivOperation implements Operation{
+ @Override
+ public float apply(float a, float b) {
+ if (b == 0f) {
+ throw new ArithmeticException("Error! Division by zero is not accepted");
+ }
+ return a / b;
+ }
+}
diff --git a/src/Calc/HistoryOperation.java b/src/Calc/HistoryOperation.java
new file mode 100644
index 0000000..69d7915
--- /dev/null
+++ b/src/Calc/HistoryOperation.java
@@ -0,0 +1,35 @@
+
+package Calc;
+
+import java.util.ArrayList;
+import java.util.List;
+public class HistoryOperation extends OperationDecorator {
+ private static final List history = new ArrayList<>();
+
+ public HistoryOperation(Operation decoratedOperation) {
+ super(decoratedOperation);
+ }
+
+ @Override
+ public float apply(float a, float b) {
+ float result = super.apply(a, b);
+ history.add(a + " " + getSymbol(decoratedOperation) + " " + b + " = " + result);
+ return result;
+ }
+
+ private String getSymbol(Operation op) {
+ if (op instanceof AddOperation) return "+";
+ if (op instanceof SubOperation) return "-";
+ if (op instanceof MultOperation) return "×";
+ if (op instanceof DivOperation) return "÷";
+ return "?";
+ }
+ //اضفنا الدالة عشان تتعامل مع الكوماند باترن
+ public static void addEntry(String entry) {
+ history.add(entry);
+}
+
+ public static List getHistory() {
+ return history;
+ }
+}
diff --git a/src/Calc/IdleState.java b/src/Calc/IdleState.java
new file mode 100644
index 0000000..6062c41
--- /dev/null
+++ b/src/Calc/IdleState.java
@@ -0,0 +1,26 @@
+package Calc;
+
+public class IdleState implements CalculatorState {
+
+ @Override
+ public void onNumber(Calculator calc, String digit) {
+ calc.setDisplay(digit);
+ calc.setState(new TypingState());
+ }
+
+ @Override
+ public void onOperation(Calculator calc, String op) {
+ // لا يمكن اختيار عملية قبل كتابه اول رقم
+ }
+
+ @Override
+ public void onEquals(Calculator calc) {
+ // ولا شي
+ }
+
+ @Override
+ public void onClear(Calculator calc) {
+ calc.clear();
+ calc.setState(new IdleState());
+ }
+}
diff --git a/src/Calc/LoggingOperation.java b/src/Calc/LoggingOperation.java
new file mode 100644
index 0000000..78e5fa5
--- /dev/null
+++ b/src/Calc/LoggingOperation.java
@@ -0,0 +1,27 @@
+
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public class LoggingOperation extends OperationDecorator{
+ public LoggingOperation(Operation decoratedOperation) {
+ super(decoratedOperation);
+ }
+
+ @Override
+ public float apply(float a, float b) {
+ float result = super.apply(a, b);
+ System.out.println("[LOG] " + a + " " + getSymbol(decoratedOperation) + " " + b + " = " + result);
+ return result;
+ }
+
+ private String getSymbol(Operation op) {
+ if (op instanceof AddOperation) return "+";
+ if (op instanceof SubOperation) return "-";
+ if (op instanceof MultOperation) return "×";
+ if (op instanceof DivOperation) return "÷";
+ return "?";
+ }
+}
diff --git a/src/Calc/MultOperation.java b/src/Calc/MultOperation.java
new file mode 100644
index 0000000..b2489e9
--- /dev/null
+++ b/src/Calc/MultOperation.java
@@ -0,0 +1,13 @@
+
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public class MultOperation implements Operation{
+ @Override
+ public float apply(float a, float b) {
+ return a * b;
+ }
+}
diff --git a/src/Calc/Operation.java b/src/Calc/Operation.java
new file mode 100644
index 0000000..c1d5203
--- /dev/null
+++ b/src/Calc/Operation.java
@@ -0,0 +1,10 @@
+
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public interface Operation {
+ float apply(float a, float b);
+}
diff --git a/src/Calc/OperationDecorator.java b/src/Calc/OperationDecorator.java
new file mode 100644
index 0000000..a977965
--- /dev/null
+++ b/src/Calc/OperationDecorator.java
@@ -0,0 +1,19 @@
+
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public class OperationDecorator implements Operation{
+ protected Operation decoratedOperation;
+
+ public OperationDecorator(Operation decoratedOperation) {
+ this.decoratedOperation = decoratedOperation;
+ }
+
+ @Override
+ public float apply(float a, float b) {
+ return decoratedOperation.apply(a, b);
+ }
+}
diff --git a/src/Calc/OperationFactory.java b/src/Calc/OperationFactory.java
new file mode 100644
index 0000000..ed4d114
--- /dev/null
+++ b/src/Calc/OperationFactory.java
@@ -0,0 +1,23 @@
+
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public class OperationFactory {
+ public static Operation getOperation(String op) {
+ switch (op) {
+ case "+":
+ return new AddOperation();
+ case "-":
+ return new SubOperation();
+ case "×":
+ return new MultOperation();
+ case "÷":
+ return new DivOperation();
+ default:
+ throw new IllegalArgumentException("Unknown operation: " + op);
+ }
+ }
+}
diff --git a/src/Calc/OperationSelectedState.java b/src/Calc/OperationSelectedState.java
new file mode 100644
index 0000000..c9639fd
--- /dev/null
+++ b/src/Calc/OperationSelectedState.java
@@ -0,0 +1,26 @@
+package Calc;
+
+public class OperationSelectedState implements CalculatorState {
+
+ @Override
+ public void onNumber(Calculator calc, String digit) {
+ calc.setDisplay(digit);
+ calc.setState(new TypingState());
+ }
+
+ @Override
+ public void onOperation(Calculator calc, String op) {
+ calc.setOperation(op);
+ }
+
+ @Override
+ public void onEquals(Calculator calc) {
+ // لا يوجد رقم ثاني → تجاهل فقط
+ }
+
+ @Override
+ public void onClear(Calculator calc) {
+ calc.clear();
+ calc.setState(new IdleState());
+ }
+}
diff --git a/src/Calc/ResultState.java b/src/Calc/ResultState.java
new file mode 100644
index 0000000..0cb289e
--- /dev/null
+++ b/src/Calc/ResultState.java
@@ -0,0 +1,28 @@
+package Calc;
+
+public class ResultState implements CalculatorState {
+
+ @Override
+ public void onNumber(Calculator calc, String digit) {
+ calc.setDisplay(digit);
+ calc.setState(new TypingState());
+ }
+
+ @Override
+ public void onOperation(Calculator calc, String op) {
+ calc.saveFirstOperand();
+ calc.setOperation(op);
+ calc.setState(new OperationSelectedState());
+ }
+
+ @Override
+ public void onEquals(Calculator calc) {
+ // تجاهل
+ }
+
+ @Override
+ public void onClear(Calculator calc) {
+ calc.clear();
+ calc.setState(new IdleState());
+ }
+}
diff --git a/src/Calc/SubOperation.java b/src/Calc/SubOperation.java
new file mode 100644
index 0000000..ea4b515
--- /dev/null
+++ b/src/Calc/SubOperation.java
@@ -0,0 +1,13 @@
+
+package Calc;
+
+/**
+ *
+ * @author Sulta
+ */
+public class SubOperation implements Operation{
+ @Override
+ public float apply(float a, float b) {
+ return a - b;
+ }
+}
diff --git a/src/Calc/TypingState.java b/src/Calc/TypingState.java
new file mode 100644
index 0000000..921c2f5
--- /dev/null
+++ b/src/Calc/TypingState.java
@@ -0,0 +1,29 @@
+package Calc;
+
+public class TypingState implements CalculatorState {
+
+ @Override
+ public void onNumber(Calculator calc, String digit) {
+ calc.appendDigit(digit);
+ }
+
+ @Override
+ public void onOperation(Calculator calc, String op) {
+ calc.saveFirstOperand();
+ calc.setOperation(op);
+ calc.setState(new OperationSelectedState());
+ }
+
+ @Override
+ public void onEquals(Calculator calc) {
+ calc.compute();
+ calc.updateDisplay();
+ calc.setState(new ResultState());
+ }
+
+ @Override
+ public void onClear(Calculator calc) {
+ calc.clear();
+ calc.setState(new IdleState());
+ }
+}