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()); + } +}