Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
69 views19 pages

MVC Calculator Java Implementation

The document defines classes for a calculator application using the MVC design pattern. The CalculatorView class represents the graphical user interface and handles button clicks and key presses. CalculatorViewEvents are fired in response and handled by the CalculatorController. The CalculatorModel manages the calculation state and notifies observers like the controller of changes. When events occur, the controller updates the model and view accordingly to perform calculations and display results.

Uploaded by

quytruyenkiep
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
69 views19 pages

MVC Calculator Java Implementation

The document defines classes for a calculator application using the MVC design pattern. The CalculatorView class represents the graphical user interface and handles button clicks and key presses. CalculatorViewEvents are fired in response and handled by the CalculatorController. The CalculatorModel manages the calculation state and notifies observers like the controller of changes. When events occur, the controller updates the model and view accordingly to perform calculations and display results.

Uploaded by

quytruyenkiep
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 19

public interface CalculatorViewListener {

void handleCalculatorViewEvent(CalculatorViewEvent e);

package lec20.v10;

abstract public class CalculatorViewEvent {


public boolean isDigitEvent() {
return false;
}

public boolean isOperationEvent() {


return false;
}
public boolean isInversionEvent() {
return false;
}

public boolean isPointEvent() {


return false;
}

class DigitEvent extends CalculatorViewEvent {


private int value;
public DigitEvent(int value) {
this.value = value;
}
public int getValue() {
return value;
}

public String getString() {


return Integer.toString(value);
}
public boolean isDigitEvent() {
return true;
}
}

class OperationEvent extends CalculatorViewEvent {


private Operation.OpType op_type;
public OperationEvent(Operation.OpType op_type) {
this.op_type = op_type;
}

public Operation.OpType getOpType() {

return op_type;
}
public boolean isOperationEvent() {
return true;
}
}

class InversionEvent extends CalculatorViewEvent {


public boolean isInversionEvent() {
return true;
}
}

class PointEvent extends CalculatorViewEvent {


public boolean isPointEvent() {
return true;
}
}

public class Operation {

public enum OpType {ADD, MULT, DIV, SUB, SET}


private OpType type;
private double operand;
public Operation(OpType type, double operand) {

this.type = type;
this.operand = operand;
}
public OpType getType() {
return type;
}
public double getOperand() {
return operand;
}
public String toString() {
String str = "";
switch (type) {
case ADD:
str = "+ "; break;
case MULT:
str = "* "; break;
case DIV:
str = "/ "; break;
case SUB:
str = "- "; break;
case SET:
str = "= "; break;
}
str += operand;
return str;

}
}

public class CalculatorView extends JPanel implements ActionListener, KeyListener {


private JTextArea tape;
private JLabel display;
private JPanel button_panel;
private List<CalculatorViewListener> listeners;

public CalculatorView() {
setLayout(new BorderLayout());
tape = new JTextArea(10,20);
tape.setEditable(false);
add(new JScrollPane(tape), BorderLayout.CENTER);
JPanel subpanel = new JPanel();
subpanel.setLayout(new BorderLayout());
display = new JLabel("0");
display.setHorizontalAlignment(SwingConstants.RIGHT);
subpanel.add(display, BorderLayout.NORTH);

button_panel = new JPanel();


button_panel.setLayout(new GridLayout(5,4));

// First row of buttons

button_panel.add(new JButton("7"));
button_panel.add(new JButton("8"));
button_panel.add(new JButton("9"));
button_panel.add(new JButton("+"));

// Second row of buttons

button_panel.add(new JButton("4"));
button_panel.add(new JButton("5"));

button_panel.add(new JButton("6"));
button_panel.add(new JButton("-"));

// Third row of buttons

button_panel.add(new JButton("1"));
button_panel.add(new JButton("2"));
button_panel.add(new JButton("3"));
button_panel.add(new JButton("*"));

// Fourth row of buttons


button_panel.add(new JButton("."));
button_panel.add(new JButton("0"));
button_panel.add(new JButton("+/-"));
button_panel.add(new JButton("/"));

// Fifth row of buttons


button_panel.add(new JButton("C"));
button_panel.add(new JButton("CE"));
button_panel.add(new JButton("CT"));
button_panel.add(new JButton("="));

subpanel.add(button_panel, BorderLayout.SOUTH);
add(subpanel, BorderLayout.SOUTH);
for(Component c: button_panel.getComponents()) {

JButton b = (JButton) c;
b.addActionListener(this);
}
listeners = new ArrayList<CalculatorViewListener>();
this.setFocusable(true);
this.grabFocus();
this.addKeyListener(this);
}
public void setDisplay(String s) {
display.setText(s);
}
public void appendToDisplay(String s) {
display.setText(display.getText()+s);
}
public String getDisplay() {
return display.getText();
}

public void appendToTape(String s) {


tape.append(s);
}

@Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();

char first_char = button.getText().charAt(0);


if (first_char == '+') {
if (button.getText().equals("+/-")) {
first_char = 'i';
}
}
dispatchEventByChar(first_char);
}
private void dispatchEventByChar(char c) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
fireEvent(new DigitEvent(Integer.parseInt(Character.toString(c))));
break;
case '+':
fireEvent(new OperationEvent(Operation.OpType.ADD));
break;

case '-':
fireEvent(new OperationEvent(Operation.OpType.SUB));
break;
case '/':
fireEvent(new OperationEvent(Operation.OpType.DIV));
break;
case '*':
fireEvent(new OperationEvent(Operation.OpType.MULT));
break;
case '=':
fireEvent(new OperationEvent(Operation.OpType.SET));
break;
case 'i':
fireEvent(new InversionEvent());
break;
case '.':
fireEvent(new PointEvent());
break;

}
}
public void addCalculatorViewListener(CalculatorViewListener l) {
listeners.add(l);
}
public void removeCalculatorViewListener(CalculatorViewListener l) {

listeners.remove(l);
}
public void fireEvent(CalculatorViewEvent e) {
for (CalculatorViewListener l : listeners) {
l.handleCalculatorViewEvent(e);
}
}

@Override
public void keyPressed(KeyEvent e) {
}

@Override
public void keyReleased(KeyEvent e) {
}

@Override
public void keyTyped(KeyEvent e) {
dispatchEventByChar(e.getKeyChar());
}
}

public class CalculatorModel extends Observable {

private List<Operation> history;


private double value;

public CalculatorModel() {
history = new ArrayList<Operation>();
value = 0.0;

public double getValue() {


return value;
}
public void eval(Operation op) {
history.add(op);
switch (op.getType()) {
case ADD:
value += op.getOperand();
break;
case SUB:
value -= op.getOperand();
break;
case MULT:
value *= op.getOperand();
break;
case DIV:
value /= op.getOperand();
break;
case SET:
value = op.getOperand();
break;
}
setChanged();

notifyObservers(op);
}
public void reset() {
history = new ArrayList<Operation>();
value = 0.0;
}
}

public class CalculatorController implements Observer, CalculatorViewListener {

CalculatorModel model;
CalculatorView view;

boolean start_of_number;
boolean point_pressed;
Operation.OpType in_progress;

public CalculatorController(CalculatorModel model, CalculatorView view) {


this.model = model;
this.view = view;

view.addCalculatorViewListener(this);

start_of_number = true;
point_pressed = false;
view.setDisplay("0");
in_progress = Operation.OpType.SET;

model.addObserver(this);
}

@Override
public void handleCalculatorViewEvent(CalculatorViewEvent e) {
if (e.isDigitEvent()) {
DigitEvent digit = (DigitEvent) e;
if (start_of_number) {
view.setDisplay(digit.getString());
start_of_number = false;
} else {
if (view.getDisplay().equals("0")) {
if (digit.getValue() != 0) {
view.setDisplay(digit.getString());
}
} else {
view.appendToDisplay(digit.getString());
}
}

} else if (e.isOperationEvent()) {
OperationEvent op_event = (OperationEvent) e;

if (!start_of_number) {
double disp_value = Double.parseDouble(view.getDisplay());
model.eval(new Operation(in_progress, disp_value));
}
start_of_number = true;
point_pressed = false;
in_progress = op_event.getOpType();
if (in_progress == Operation.OpType.SET) {
model.eval(new Operation(in_progress, model.getValue()));
}
} else if (e.isInversionEvent()) {
if (Double.parseDouble(view.getDisplay()) != 0) {
String in_display = view.getDisplay();
if (in_display.charAt(0) != '-') {
view.setDisplay("-" + in_display);
} else {
view.setDisplay(in_display.substring(1));
}
}
} else if (e.isPointEvent()) {
if (start_of_number) {
view.setDisplay("0.");

start_of_number = false;
} else if (!point_pressed) {
view.appendToDisplay(".");
}
point_pressed = true;
}
}

@Override
public void update(Observable o, Object arg) {
Operation op = (Operation) arg;

view.appendToTape(op.toString() + "\n");
view.setDisplay(Double.toString(model.getValue()));
start_of_number = true;
point_pressed = false;

}
public class Main {

public static void main(String[] args) {


CalculatorModel model = new CalculatorModel();

CalculatorView view = new CalculatorView();


CalculatorController controller = new CalculatorController(model, view);
JFrame main_frame = new JFrame();
main_frame.setTitle("MVC Calculator");
main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

main_frame.setContentPane(view);

main_frame.pack();
main_frame.setVisible(true);
}
}

You might also like