Undo Functionality Design Doc
Requirements
User can remove any transaction altogether by selecting the row.
The remove update is reflected in the Total Cost.
Design
While adding such a functionality, it is always a best practice to use MVC architecture. Given that the rest of the app
follows MVC structure as well, we will be distributing the implementation of Undo feature into Model, View and
Controller sections.
Model
For the undo feature, we are supposed to provide the ability to remove a selected row in the JTable .
Given that the JTable rows are created using the transaction data from ExpenseTrackerModel , we will need to remove
the transaction corresponding to the selected row from ExpenseTrackerModel .
To remove the transaction we will use the public method removeTransaction present in ExpenseTrackerModel Class.
No changes in ExpenseTrackerModel.java
public class ExpenseTrackerModel {
...
public void removeTransaction(Transaction t) {
transactions.remove(t);
}
...
}
View
We will provide a Remove Transaction Button, so that the user can trigger the removal, once they have selected a
specific row.
This button will be placed beside the Add Transaction Button, so that its easily visible to the user.
We will also create a public function getRemoveTransactionButton() , which returns the remove button, so that it can be
paired with an event listener in the controller
ExpenseTrackerView.java will involve the following changes:
// ... refers to the existing untouched code.
public class ExpenseTrackerView extends JFrame {
private JTable transactionsTable;
...
// to remove a transaction
private JButton removeTransactionBtn;
...
Undo Functionality Design Doc 1
public ExpenseTrackerView() {
...
addTransactionBtn = new JButton("Add Transaction");
removeTransactionBtn = new JButton("Remove Selected Transaction");
...
JPanel buttonPanel = new JPanel();
buttonPanel.add(addTransactionBtn);
buttonPanel.add(removeTransactionBtn);
...
public JButton getRemoveTransactionBtn(){
return removeTransactionBtn;
}
}
Since the transactions are displayed in the form of a JTable , user has the ability to select the rows. To remove a
specific row/transaction, we will require the selected data.
We will add an eventListener in ExpenseTrackerApp class (similar to the listener for AddTransactionButton. This listener
will utilise the getSelectedRow() property of JTable to get the required data.
ExpenseTrackerApp.java would involve following changes:
public class ExpenseTrackerApp {
public static void main(String[] args) {
// Create MVC components
ExpenseTrackerModel model = new ExpenseTrackerModel();
ExpenseTrackerView view = new ExpenseTrackerView();
ExpenseTrackerController controller = new ExpenseTrackerController(model, view);
// Initialize view
view.setVisible(true);
// Handle add transaction button clicks
view.getAddTransactionBtn().addActionListener(e -> {
// Get transaction data from view
...
});
// ADDING A LISTENER TO REMOVE TRANSACTION BUTTON
view.getRemoveTransactionBtn().addActionListener(e -> {
// Get transaction data from view
int rowNumber = view.getTransactionsTable().getSelectedRow();
double selected_amount = (double)view.getTransactionsTable().getValueAt(rowNumber, 1);
String selected_category = (String)view.getTransactionsTable().getValueAt(rowNumber, 2);
String selected_date = (String)view.getTransactionsTable().getValueAt(rowNumber, 3);
// pass this data to controller
controller.removeTransaction(selected_amount, selected_category,selected_date);
});
...
Controller
Undo Functionality Design Doc 2
The event listener from ExpenseTrackerApp.java will get the selected amount, category and date-time and pass it to
the removeTransaction function in controller.
In the removeTransaction function, we would get the current list of transactions by querying the model. Once we have
the transaction list, we will remove the first transaction that matches all the selected fields:
amount
category
date-time
We would then call the refresh() method to generate the view with the updated model
The ExpenseTrackerController.java file would look like this:
...
public class ExpenseTrackerController {
private ExpenseTrackerModel model;
private ExpenseTrackerView view;
private TransactionFilter transactionFilter;
public ExpenseTrackerController(ExpenseTrackerModel model, ExpenseTrackerView view) {
this.model = model;
this.view = view;
// Set up view event handlers
}
public void refresh() {
...
}
public void highlightFilters(List<Transaction> transactions) {
...
}
public boolean addTransaction(double amount, String category) {
...
}
public void setStrategy(TransactionFilter transactionFilter) {
...
}
public boolean applyFilter() {
...
}
// REMOVE TRANSACTION METHOD CALLED BY THE EVENT LISTENER
public void removeTransaction(double amount, String category, String date_time){
List<Transaction> transactions = model.getTransactions();
// check if all 3 are equal to any of the transactions
for(Transaction transaction : transactions){
if(transaction.getAmount() == amount && transaction.getCategory() == category && transaction.getTimestamp() == date_time){
model.removeTransaction(transaction);
break;
}
}
refresh();
}
// Other controller methods
}
Remote repo: https://github.com/yashk1900/hw2
Undo Functionality Design Doc 3
Undo Functionality Design Doc 4