--- /dev/null
+package de.diejungsvondertanke.tankstelle;
+
+import de.diejungsvondertanke.tankstelle.error.NoSuchFuelTypeError;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.List;
+
+/**
+ * GUI for fuel stations
+ *
+ * @author Sergej Pavlenko
+ */
+public class FuelStationUI extends JFrame {
+
+ private JComboBox<String> comboFuelStations;
+ private JComboBox<FuelType> comboFuelTypes;
+ private JTextArea outputArea;
+ private JPanel contentPane;
+
+ public FuelStationUI() {
+ setContentPane(contentPane);
+ setTitle("Fuel Station Management System");
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setSize(800, 600);
+ setLocationRelativeTo(null);
+
+ initComponents();
+ }
+
+ /**
+ * Layout for GUI
+ *
+ * @author Sergej Pavlenko
+ */
+ private void initComponents() {
+ setLayout(new BorderLayout());
+
+ JPanel selectionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+
+ comboFuelStations = new JComboBox<>(buildStationNames());
+ comboFuelTypes = new JComboBox<>(FuelType.values());
+
+ selectionPanel.add(new JLabel("Fuel station:"));
+ selectionPanel.add(comboFuelStations);
+ selectionPanel.add(new JLabel("Fuel type:"));
+ selectionPanel.add(comboFuelTypes);
+
+ add(selectionPanel, BorderLayout.NORTH);
+
+ JTabbedPane tabbedPane = new JTabbedPane();
+ tabbedPane.addTab("Result", createResultPanel());
+ tabbedPane.addTab("Change price", createPricePanel());
+ tabbedPane.addTab("Change stock", createStockPanel());
+ tabbedPane.addTab("Search", createSearchPanel());
+ tabbedPane.addTab("New fuel station", createNewFuelStationPanel());
+
+ add(tabbedPane, BorderLayout.CENTER);
+
+ outputArea = new JTextArea();
+ outputArea.setEditable(false);
+ outputArea.setLineWrap(true);
+ outputArea.setWrapStyleWord(true);
+ JScrollPane scrollPane = new JScrollPane(outputArea);
+ scrollPane.setPreferredSize(new Dimension(800, 150));
+ add(scrollPane, BorderLayout.SOUTH);
+ }
+
+ /**
+ * Creates names for the fuel stations
+ *
+ * @return fuel station names
+ *
+ * @author Sergej Pavlenko
+ */
+ private String[] buildStationNames() {
+ List<FuelStation> stations = Main.fuelStations;
+ String[] names = new String[stations.size()];
+ for (int i = 0; i < stations.size(); i++) {
+ FuelStation fs = stations.get(i);
+ String typeName = fs.getClass().getSimpleName();
+ names[i] = "Station " + (i + 1) + " (" + typeName + ")";
+ }
+ return names;
+ }
+
+ /**
+ * Getter method
+ *
+ * @return selected fuel station
+ *
+ * @author Sergej Pavlenko
+ */
+ private FuelStation getSelectedStation() {
+ int idx = comboFuelStations.getSelectedIndex();
+ if (idx < 0 || idx >= Main.fuelStations.size()) {
+ return null;
+ }
+ return Main.fuelStations.get(idx);
+ }
+
+ /**
+ * Create Panel for results of arithmetic operations
+ *
+ * @return result panel
+ *
+ * @author Sergej Pavlenko
+ */
+ private JPanel createResultPanel() {
+ JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
+
+ JButton btnTotalPrice = new JButton("Total selling value of all available fuel types");
+ btnTotalPrice.addActionListener(e -> {
+ float sum = 0f;
+ for (FuelStation station : Main.fuelStations) {
+ sum += station.get_cumulative_retail_price();
+ }
+ appendOutput(String.format(
+ "Total selling value of all available fuel types: %.2f €", sum));
+ });
+
+ JButton btnHighestPrice = new JButton("Fuel station with highest price (chosen fuel type)");
+ btnHighestPrice.addActionListener(e -> {
+ FuelType type = (FuelType) comboFuelTypes.getSelectedItem();
+ try {
+ FuelStation fs = Main.getHighestPrice(type);
+ appendOutput("Fuel station with highest price for " + type + ": "
+ + getDisplayName(fs));
+ } catch (NoSuchFuelTypeError ex) {
+ showError("No fitting fuel station with chosen fuel type " + type + " found.");
+ }
+ });
+
+ JButton btnHighestTotalValue = new JButton("Fuel station with highest total value of all available fuel types");
+ btnHighestTotalValue.addActionListener(e -> {
+ try {
+ FuelStation fs = Main.getHighestAccumulatedValue();
+ appendOutput("Fuel station with highest total value of all available fuel types: "
+ + getDisplayName(fs));
+ } catch (NoSuchFuelTypeError ex) {
+ showError("Error when calculating highest total value.");
+ }
+ });
+
+ JButton btnStock = new JButton("Highest / lowest stock (chosen fuel type)");
+ btnStock.addActionListener(e -> {
+ FuelType type = (FuelType) comboFuelTypes.getSelectedItem();
+ try {
+ FuelStation max = Main.getHighestStoredAmount(type);
+ FuelStation min = Main.getLowestStoredAmount(type);
+ appendOutput("For fuel type " + type + ":\n" +
+ " Highest stock: " + getDisplayName(max) + "\n" +
+ " Lowest stock: " + getDisplayName(min));
+ } catch (NoSuchFuelTypeError ex) {
+ showError("No fitting fuel station with fuel type " + type + " found.");
+ }
+ });
+
+ panel.add(btnTotalPrice);
+ panel.add(btnHighestPrice);
+ panel.add(btnHighestTotalValue);
+ panel.add(btnStock);
+
+ return panel;
+ }
+
+ /**
+ * Create Panel for price changing
+ *
+ * @return price changing Panel
+ *
+ * @author Sergej Pavlenko
+ */
+ private JPanel createPricePanel() {
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.insets = new Insets(5,5,5,5);
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+
+ JLabel lblPrice = new JLabel("New price per litre (€):");
+ JTextField txtPrice = new JTextField(10);
+ JButton btnSave = new JButton("Change price");
+
+ btnSave.addActionListener(e -> {
+ FuelStation station = getSelectedStation();
+ FuelType type = (FuelType) comboFuelTypes.getSelectedItem();
+ if (station == null) {
+ showError("No fuel station chosen.");
+ return;
+ }
+ try {
+ float newPrice = Float.parseFloat(txtPrice.getText().replace(",", "."));
+ station.set_price(type, newPrice);
+ appendOutput(String.format(
+ "Price changed of %s at %s to %.3f €/L.",
+ type, getDisplayName(station), newPrice
+ ));
+ txtPrice.setText("");
+ } catch (NumberFormatException ex) {
+ showError("Please enter a valid number for the price.");
+ } catch (NoSuchFuelTypeError ex) {
+ showError("This fuel station does not offer the fuel type " + type);
+ }
+ });
+
+ gbc.gridx = 0; gbc.gridy = 0;
+ panel.add(lblPrice, gbc);
+ gbc.gridx = 1;
+ panel.add(txtPrice, gbc);
+
+ gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 2;
+ panel.add(btnSave, gbc);
+
+ return panel;
+ }
+
+ /**
+ * Create Panel to change stock
+ *
+ * @author Sergej Pavlenko
+ */
+ private JPanel createStockPanel() {
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.insets = new Insets(5,5,5,5);
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+
+ JLabel lblAmount = new JLabel("Amount (litre):");
+ JTextField txtAmount = new JTextField(10);
+ JRadioButton rbAbsolute = new JRadioButton("Set absolute amount", true);
+ JRadioButton rbDelta = new JRadioButton("Change amount (+/-)");
+ ButtonGroup group = new ButtonGroup();
+ group.add(rbAbsolute);
+ group.add(rbDelta);
+
+ JButton btnSave = new JButton("Change stock");
+
+ btnSave.addActionListener(e -> {
+ FuelStation station = getSelectedStation();
+ FuelType type = (FuelType) comboFuelTypes.getSelectedItem();
+ if (station == null) {
+ showError("No fuel station chosen.");
+ return;
+ }
+ try {
+ float value = Float.parseFloat(txtAmount.getText().replace(",", "."));
+ int capacity = getCapacity(station, type);
+ float current = station.getStored_amount(type);
+
+ if (rbAbsolute.isSelected()) {
+ if (value < 0) {
+ showError("Please enter a positive number");
+ return;
+ }
+ if (value > capacity) {
+ showError("Maximum capacity of " + capacity + " L is being crossed.");
+ return;
+ }
+ station.set_stored_amount(value, type);
+ appendOutput(String.format(
+ "Changed stock of %s at %s to %.2f litre.",
+ type, getDisplayName(station), value
+ ));
+ txtAmount.setText("");
+ } else {
+ float updated = current + value;
+ if (updated < 0) {
+ showError("The amount of fuel may not be negative.");
+ return;
+ }
+ if (updated > capacity) {
+ showError("Maximum capacity of " + capacity + " L is being crossed.");
+ return;
+ }
+
+ station.add_stored_amount(value, type);
+ appendOutput(String.format(
+ "Stock changed of %s at %s by %.2f litre.",
+ type, getDisplayName(station), value
+ ));
+ txtAmount.setText("");
+ }
+ } catch (NumberFormatException ex) {
+ showError("Please enter a valid number for the amount.");
+ } catch (ArithmeticException ex) {
+ showError("Error: " + ex.getMessage());
+ } catch (NoSuchFuelTypeError ex) {
+ showError("This fuel station does not offer the fuel type " + type);
+ }
+ });
+
+ int y = 0;
+ gbc.gridx = 0; gbc.gridy = y;
+ panel.add(lblAmount, gbc);
+ gbc.gridx = 1;
+ panel.add(txtAmount, gbc);
+
+ y++;
+ gbc.gridx = 0; gbc.gridy = y; gbc.gridwidth = 2;
+ panel.add(rbAbsolute, gbc);
+
+ y++;
+ gbc.gridy = y;
+ panel.add(rbDelta, gbc);
+
+ y++;
+ gbc.gridy = y;
+ panel.add(btnSave, gbc);
+
+ return panel;
+ }
+
+ private int getCapacity(FuelStation station, FuelType type) throws NoSuchFuelTypeError {
+ for (Fuel f : station.fuels) {
+ if (f.FUEL_TYPE == type) {
+ return f.CAPACITY;
+ }
+ }
+ throw new NoSuchFuelTypeError("This fuel station does not offer the fuel type " + type);
+ }
+
+ /**
+ * Updates the selection of fuel stations for the ComboBox
+ *
+ * @author Sergej Pavlenko
+ */
+ private void updateStations() {
+ String[] names = buildStationNames();
+ DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>(names);
+ comboFuelStations.setModel(model);
+ }
+
+ /**
+ * Create Panel for searching for a fuel station with a specific fuel type
+ *
+ * @author Sergej Pavlenko
+ */
+ private JPanel createSearchPanel() {
+ JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+
+ JButton btnListFuelStations = new JButton("Show fuel stations with chosen fuel type");
+ btnListFuelStations.addActionListener(e -> {
+ FuelType type = (FuelType) comboFuelTypes.getSelectedItem();
+ StringBuilder sb = new StringBuilder();
+ sb.append("Fuel station with fuel type ").append(type).append(":\n");
+ for (FuelStation station : Main.fuelStations) {
+ try {
+ station.getStored_amount(type);
+ sb.append(" - ").append(getDisplayName(station)).append("\n");
+ } catch (NoSuchFuelTypeError ex) {
+ }
+ }
+ appendOutput(sb.toString());
+ });
+
+ panel.add(btnListFuelStations);
+ return panel;
+ }
+
+ /**
+ * Create Panel for making new fuel stations
+ *
+ * @author Sergej Pavlenko
+ */
+ private JPanel createNewFuelStationPanel() {
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.insets = new Insets(5, 5, 5, 5);
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.anchor = GridBagConstraints.WEST;
+
+ JRadioButton rbSmall = new JRadioButton("Small fuel station", true);
+ JRadioButton rbMedium = new JRadioButton("Medium fuel station", true);
+ JRadioButton rbLarge = new JRadioButton("Large fuel station", true);
+
+ ButtonGroup buttonGroup = new ButtonGroup();
+ buttonGroup.add(rbSmall);
+ buttonGroup.add(rbMedium);
+ buttonGroup.add(rbLarge);
+
+ JLabel lblAtrributes = new JLabel("Special attribute:");
+ JTextField txtAtrributes = new JTextField(15);
+ JLabel lblHint = new JLabel("Small: amount of vending machines, Medium: m^2, Large: supermarket-company");
+
+ JButton btnAdd = new JButton("Add fuel station");
+ btnAdd.addActionListener(e -> {
+ try {
+ if (rbSmall.isSelected()) {
+ short vendingMachines = Short.parseShort(txtAtrributes.getText().trim());
+ Main.addNewFuelStation(vendingMachines);
+ appendOutput("Fuel station with " + vendingMachines + " vending machines has been added.");
+ } else if (rbMedium.isSelected()) {
+ float retailSpace = Float.parseFloat(txtAtrributes.getText().replace(",", ".").trim());
+ Main.addNewFuelStation(retailSpace);
+ appendOutput("Fuel station with " + retailSpace + " m^2 retail space has been added.");
+ } else if (rbLarge.isSelected()) {
+ String supermarketCompany = txtAtrributes.getText().trim();
+ Main.addNewFuelStation(supermarketCompany);
+ appendOutput("Fuel station with supermarket-company" + supermarketCompany + " has been added.");
+ }
+ updateStations();
+ txtAtrributes.setText("");
+ } catch (NumberFormatException ex) {
+ showError("Please enter a valid number (for small / medium).");
+ } catch (IllegalArgumentException ex) {
+ showError(ex.getMessage());
+ }
+ });
+
+ int y = 0;
+ gbc.gridx = 0; gbc.gridy = y;
+ gbc.gridwidth = 3;
+ panel.add(new JLabel("Type of new fuel station:"), gbc);
+
+ y++;
+ gbc.gridy = y;
+ gbc.gridwidth = 1;
+ panel.add(rbSmall, gbc);
+ gbc.gridx = 1;
+ panel.add(rbMedium, gbc);
+ gbc.gridx = 2;
+ panel.add(rbLarge, gbc);
+
+ y++;
+ gbc.gridx = 0; gbc.gridy = y;
+ panel.add(lblAtrributes, gbc);
+ gbc.gridx = 1; gbc.gridwidth = 2;
+ panel.add(txtAtrributes, gbc);
+
+ y++;
+ gbc.gridx = 0; gbc.gridy = y;
+ gbc.gridwidth = 3;
+ panel.add(lblHint, gbc);
+
+ y++;
+ gbc.gridy = y;
+ panel.add(btnAdd, gbc);
+
+ return panel;
+ }
+
+ // ------------------ HILFSMETHODEN ------------------
+
+ private String getDisplayName(FuelStation station) {
+ int index = Main.fuelStations.indexOf(station);
+ if (index >= 0 && index < comboFuelStations.getItemCount()) {
+ return comboFuelStations.getItemAt(index);
+ }
+ return station.getClass().getSimpleName();
+ }
+
+ private void appendOutput(String text) {
+ outputArea.append(text + "\n\n");
+ outputArea.setCaretPosition(outputArea.getDocument().getLength());
+ }
+
+ private void showError(String message) {
+ JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE);
+ }
+}