Newer
Older
package no.ntnu.idatt1002.demo.controller;
import java.awt.event.ActionEvent;
import java.io.IOException;
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
import java.util.Optional;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudget;
import no.ntnu.idatt1002.demo.data.Budget.GeneralBudget;
import no.ntnu.idatt1002.demo.data.Economics.Expense;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseRegister;
import no.ntnu.idatt1002.demo.data.Economics.FileHandling;
import no.ntnu.idatt1002.demo.data.Economics.Income;
import no.ntnu.idatt1002.demo.data.Economics.IncomeCategory;
import no.ntnu.idatt1002.demo.data.Economics.IncomeRegister;
public class IncomeExpenseController implements FinanceController {
@FXML
private TableColumn<Expense, Double> expAmountCol;
@FXML
private TableColumn<Expense, ExpenseCategory> expCategoryCol;
@FXML
private TableColumn<Expense, String> expDateCol;
@FXML
private TableColumn<Expense, String> expDescriptionCol;
@FXML
private TableColumn<Expense, Boolean> expRecurringCol;
@FXML
private TableColumn<Income, Double> inAmountCol;
@FXML
private TableColumn<Income, IncomeCategory> inCategoryCol;
@FXML
private TableColumn<Income, String> inDateCol;
@FXML
private TableColumn<Income, String> inDescriptionCol;
@FXML
private TableColumn<Income, Boolean> inRecurringCol;
@FXML
private TableView<Expense> expenseTableView;
@FXML
private TableView<Income> incomeTableView;
@FXML
private Text inSum;
@FXML
private Text expSum;
@FXML
private MenuItem addExpense;
@FXML
private MenuItem addIncome;
@FXML
private ProgressBar budgetProgress;
@FXML
private DatePicker date;
@FXML
private Label daysLeftLbl;
@FXML
private ComboBox<?> filter;
@FXML
private Button returnBtn;
@FXML
private Label title;
@FXML
private MenuItem editIncomeMenu;
@FXML
private MenuItem deleteIncomeMenu;
@FXML
private MenuItem editExpenseMenu;
@FXML
private MenuItem deleteExpenseMenu;
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
private IncomeRegister incomeRegister;
private ExpenseRegister expenseRegister;
private GeneralBudget generalBudget;
private ObservableList<Income> income;
private ObservableList<Expense> expenses;
@FXML
private PieChart expensePieChart;
@FXML
private PieChart incomePieChart;
FileHandling fileHandling;
@FXML
public void initialize() throws IOException {
fileHandling = new FileHandling();
//Initialize columns
setColumns();
//Initialize registers and tableview
incomeRegister = loadIncomeDataFromFile("Income");
income = FXCollections.observableArrayList(incomeRegister.getItems());
incomeTableView.setItems(income);
expenseRegister = loadExpenseDataFromFile("Expense");
expenses = FXCollections.observableArrayList(expenseRegister.getItems());
expenseTableView.setItems(expenses);
//Setting pie chart values to correspond with the registers
incomePieChart.setLegendSide(Side.RIGHT);
expensePieChart.setLegendSide(Side.RIGHT);
expensePieChart.setLabelLineLength(10);
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
//Initialize sum field under the tableview
// inSum.setText(String.valueOf(incomeRegister.getTotalSum()));
//expSum.setText(String.valueOf(expenseRegister.getTotalSum()));
}
private void setColumns() {
inDateCol.setCellValueFactory(new PropertyValueFactory<Income, String>("date"));
inAmountCol.setCellValueFactory(new PropertyValueFactory<Income, Double>("amount"));
inCategoryCol.setCellValueFactory(new PropertyValueFactory<Income, IncomeCategory>("category"));
inDescriptionCol.setCellValueFactory(new PropertyValueFactory<Income, String>("description"));
inRecurringCol.setCellValueFactory(new PropertyValueFactory<Income, Boolean>("recurring"));
expDateCol.setCellValueFactory(new PropertyValueFactory<Expense, String>("date"));
expAmountCol.setCellValueFactory(new PropertyValueFactory<Expense, Double>("amount"));
expCategoryCol.setCellValueFactory(new PropertyValueFactory<Expense, ExpenseCategory>("category"));
expDescriptionCol.setCellValueFactory(new PropertyValueFactory<Expense, String>("description"));
expRecurringCol.setCellValueFactory(new PropertyValueFactory<Expense, Boolean>("recurring"));
}
private ObservableList<PieChart.Data> createExpensePieChart() {
return FXCollections.observableArrayList(
new Data("Food", expenseRegister.getExpenseByCategory(ExpenseCategory.FOOD).getTotalSum()),
new Data("Books", expenseRegister.getExpenseByCategory(ExpenseCategory.BOOKS).getTotalSum()),
new Data("Clothes", expenseRegister.getExpenseByCategory(ExpenseCategory.CLOTHES).getTotalSum()),
new Data("Other", expenseRegister.getExpenseByCategory(ExpenseCategory.OTHER).getTotalSum())
);
}
private ObservableList<PieChart.Data> createIncomePieChart() {
return FXCollections.observableArrayList(
new Data("Gift", incomeRegister.getIncomeByCategory(IncomeCategory.GIFT).getTotalSum()),
new Data("Salary", incomeRegister.getIncomeByCategory(IncomeCategory.SALARY).getTotalSum()),
new Data("Loans", incomeRegister.getIncomeByCategory(IncomeCategory.STUDENT_LOAN).getTotalSum())
);
}
/**
* Method for disabling the date picker, yet having its opacity at max.
*/
private void formatDatePicker() {
date.setValue(LocalDate.now());
date.setDisable(true);
date.setStyle("-fx-opacity: 1");
date.getEditor().setStyle("-fx-opacity: 1");
}
/**
* Method for handling the adding of new entries in the tableview.
* @param event A button click on the add button.
*/
@Override
public void handleAddBtn(javafx.event.ActionEvent event) {
int sizeBf = (expenseRegister.getItems().size() + incomeRegister.getItems().size());
if (event.getSource() == addIncome) {
handleAddIncome();
} else if (event.getSource() == addExpense){
handleAddExpense();
}
int sizeAf = (expenseRegister.getItems().size() + incomeRegister.getItems().size());
if (sizeAf != sizeBf) {
refreshTableView();
refreshProgress();
}
}
/**
* Method for handling the editing of a chosen entry in the tableview.
*
* @param event A button click on the edit button.
*/
@Override
public void handleEditBtn(javafx.event.ActionEvent event) {
System.out.println(event.getSource());
Income chosenIncome = incomeTableView.getSelectionModel().getSelectedItem();
Expense chosenExpense = expenseTableView.getSelectionModel().getSelectedItem();
boolean isEditIncome = event.getSource() == editIncomeMenu;
boolean isDeleteIncome = event.getSource() == deleteIncomeMenu;
boolean isEditExpense = event.getSource() == editExpenseMenu;
boolean isDeleteExpense = event.getSource() == deleteExpenseMenu;
System.out.println(chosenIncome);
System.out.println(chosenExpense);
if (isEditIncome) {
handleEditIncome(chosenIncome);
} else if (isDeleteIncome) {
handleDeleteIncome(chosenIncome);
} else if (isEditExpense) {
handleEditExpense(chosenExpense);
} else if (isDeleteExpense) {
handleDeleteExpense(chosenExpense);
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
//Updates the tableview and pie chart using the register
refreshTableView();
refreshProgress();
}
/**
* Deletes an entry from the tableview, if an entry has been selected. The method brings up a
* popup window, asking for confirmation for deleting the entry.
*
* @param event A button click on the delete button
*/
@Override
public void handleDeleteBtn(javafx.event.ActionEvent event) {
handleEditBtn(event);
}
/**
* Method for synching the register with the tableview. The observable list to which the tableview
* is set, is being refilled with all the entries in the register, keeping it updated with new
* changes.
*/
@Override
public void refreshTableView() {
this.income.setAll(incomeRegister.getItems());
//this.sum.setText(String.valueOf(incomeRegister.getTotalSum()));
this.expenses.setAll(expenseRegister.getItems());
//this.sum.setText(String.valueOf(incomeRegister.getTotalSum()));
}
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
324
325
326
327
328
329
330
331
332
333
334
335
private void refreshPieCharts() {
this.incomePieChart.setData(createIncomePieChart());
this.expensePieChart.setData(createExpensePieChart());
}
private void refreshProgress() {
budgetProgress.setProgress(expenseRegister.getTotalSum()/incomeRegister.getTotalSum());
}
@FXML
private void handleAddIncome() {
//Instantiate FXML loader and loads the popup for adding income
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddIncome.fxml"));
Income newIncome = null;
String dialogTitle = "Add income";
// Load the FXML file for your dialog box
Dialog<Income> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
e.printStackTrace();
}
// Get the controller for the loaded FXML file
AddIncomeController dialogController = loader.getController();
//Sets the title of the dialog box
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
//Get the newly created income from the dialog pane
newIncome = dialogController.getNewIncome();
//Adds the new item to the register
if (newIncome != null) {
incomeRegister.addItem(newIncome);
incomePieChart.setData(createIncomePieChart());
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
}
}
@FXML
private void handleAddExpense() {
//Instantiate FXML loader and loads the popup for adding expense
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddExpense.fxml"));
Expense newExpense = null;
String dialogTitle = "Add expense";
// Load the FXML file for your dialog box
Dialog<Expense> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
e.printStackTrace();
}
// Get the controller for the loaded FXML file
AddExpenseController dialogController = loader.getController();
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
//Get the newly created expense from the dialog pane
newExpense = dialogController.getNewExpense();
//Adds the new item to the register
if (newExpense != null) {
expenseRegister.addItem(newExpense);
expensePieChart.setData(createExpensePieChart());
}
}
@FXML
private void handleEditIncome(Income chosenIncome) {
//Create copy of chosenIncome before changes
//Instantiate FXML loader and loads the popup for adding income
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddIncome.fxml"));
String dialogTitle = "Edit income";
// Load the FXML file for your dialog box
Dialog<Income> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
e.printStackTrace();
}
// Get the controller for the loaded FXML file
AddIncomeController dialogController = loader.getController();
//Binds the selected item to another item which is defined in the ItemController
dialogController.setIncome(chosenIncome);
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
this.incomePieChart.setData(createIncomePieChart());
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
}
@FXML
private void handleEditExpense(Expense chosenExpense) {
//Instantiate FXML loader and loads the popup for adding expense
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddExpense.fxml"));
String dialogTitle = "Edit expense";
// Load the FXML file for your dialog box
Dialog<Expense> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
e.printStackTrace();
}
// Get the controller for the loaded FXML file
AddExpenseController dialogController = loader.getController();
//Binds the selected item to another item which is defined in the ItemController
dialogController.setExpense(chosenExpense);
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
this.expensePieChart.setData(createExpensePieChart());
}
@FXML
private void handleDeleteIncome(Income chosenIncome) {
Optional<ButtonType> isConfirmed = showConfirmationDialog();
if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
incomeRegister.removeItem(chosenIncome);
}
this.incomePieChart.setData(createIncomePieChart());
}
@FXML
private void handleDeleteExpense(Expense chosenExpense) {
Optional<ButtonType> isConfirmed = showConfirmationDialog();
if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
expenseRegister.removeItem(chosenExpense);
}
this.expensePieChart.setData(createExpensePieChart());
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
}
/**
* Returns an optional, which is a popup alert box, asking for confirmation for deleting an
* entry.
*
* @return An alert box, asking for confirmation for deleting the selected entry of the tableview.
*/
@Override
public Optional<ButtonType> showConfirmationDialog() {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm Delete");
alert.setHeaderText("Delete Confirmation");
alert.setContentText("Are you sure you would like to delete the selected entry?");
return alert.showAndWait();
}
/**
* Saves the changes made to the tableview by writing the information to a file.
* @throws IOException If an error occurs while writing to the file.
*/
@Override
public void saveDataToFile() throws IOException {
fileHandling.writeItemRegisterToFile(incomeRegister, "Income");
fileHandling.writeItemRegisterToFile(expenseRegister, "Expense");
}
/**
* Method that either reads data from a file with which it fills an income register, if older changes exist, or instantiates an income register if the file is empty.
* @param fileName The name of the file that is being read from.
* @return An object of type IncomeRegister.
* @throws IOException If an error occurs while reading from the file.
*/
public IncomeRegister loadIncomeDataFromFile(String fileName) throws IOException {
//Instantiate new incomeRegister
if (fileHandling.isEmpty(fileName)) {
incomeRegister = new IncomeRegister();
} else { //Load previous income register
try {
incomeRegister = fileHandling.readIncomeRegisterFromFile(fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
return incomeRegister;
}
/**
* Method that either reads data from a file with which it fills an expense register, if older changes exist, or instantiates an expense register if the file is empty.
* @param fileName The name of the file that is being read from.
* @return An object of type IncomeRegister.
* @throws IOException If an error occurs while reading from the file.
*/
public ExpenseRegister loadExpenseDataFromFile(String fileName) throws IOException {
//ItemRegister<T extends Item>
if (fileHandling.isEmpty(fileName)) {
expenseRegister = new ExpenseRegister();
} else {
try {
expenseRegister = fileHandling.readExpenseRegisterFromFile(fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
return expenseRegister;
}
/**
* Method that either reads data from a file with which it fills a budget register, if this is an old budget, or instantiates a budget register if this is a new budget.
* @param fileName The name of the file that is being read from.
* @return An object of type GeneralBudget.
* @throws IOException If an error occurs while reading from the file.
*/
public GeneralBudget loadBudgetDataFromFile(String fileName) throws IOException {
FileHandlingBudget fileHandlingBudget = new FileHandlingBudget();
//Instantiate new budget
if (fileHandlingBudget.isEmpty(fileName)) {
generalBudget = new GeneralBudget(31, 1000);
} else { //Load previous budget
try {
generalBudget = fileHandlingBudget.readGeneralBudgetFromFile(fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
return generalBudget;
}
/**
* Switches scenes back to main menu, by loading a new FXML file and setting the scene to this location.
* @param event A button click on the return to main menu button
* @throws IOException If an error occurs with loading any of the FXML files.
public void returnToMainMenu(javafx.event.ActionEvent event) throws IOException {
saveDataToFile();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/MainMenuNew.fxml"));
Parent root = loader.load();
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}