]> Git Server - tankstelle.git/commitdiff
Overview Tab erstellt für die Tankstellen und deren Treibstoffe und Preise
authorSergej Pavlenko <sergepav0@gmail.com>
Thu, 20 Nov 2025 14:03:58 +0000 (15:03 +0100)
committerSergej Pavlenko <sergepav0@gmail.com>
Thu, 20 Nov 2025 14:03:58 +0000 (15:03 +0100)
1  2 
src/main/java/de/diejungsvondertanke/tankstelle/FuelStationUI.java

index 553c7905f6fac92dc6f7892c0140db1a73a86322,0000000000000000000000000000000000000000..02a86761213e58cc8d0476d49ccdcd9c9da0f4dc
mode 100644,000000..100644
--- /dev/null
@@@ -1,499 -1,0 +1,583 @@@
 +package de.diejungsvondertanke.tankstelle;
 +
 +import de.diejungsvondertanke.tankstelle.error.NoSuchFuelTypeError;
 +
 +import javax.swing.*;
++import javax.swing.table.DefaultTableModel;
 +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;
 +    private JList<String> listFuelStations;
++    private JTable tableFuelTypesPerStation;
++    private javax.swing.table.DefaultTableModel fuelTableModel;
 +
 +    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());
 +
 +        listFuelStations = new JList<>();
 +        listFuelStations.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
 +
 +        refreshStationNames();
 +
 +        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());
++        tabbedPane.addTab("Overview", createOverviewPanel());
 +
 +        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 BorderLayout());
 +
 +        JPanel buttonPanel = 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.");
 +            }
 +        });
 +
 +        JButton btnTotalStock = new JButton("Total stock (chosen fuel station, chosen fuel type)");
 +        btnTotalStock.addActionListener(e -> {
 +            FuelType type = (FuelType) comboFuelTypes.getSelectedItem();
 +            int[] indices = listFuelStations.getSelectedIndices();
 +
 +            if (indices.length == 0) {
 +                showError("Please select at least one fuel station.");
 +                return;
 +            }
 +
 +            FuelStation[] selectedStations = new FuelStation[indices.length];
 +            for (int i = 0; i < indices.length; i++) {
 +                selectedStations[i] = Main.fuelStations.get(indices[i]);
 +            }
 +
 +            float total = Main.getTotalStockLevelOfFuel(type, selectedStations);
 +            appendOutput(String.format("Total stock of %s across %d chosen fuel stations: %.2f L", type, indices.length, total));
 +        });
 +
 +        buttonPanel.add(btnTotalPrice);
 +        buttonPanel.add(btnHighestPrice);
 +        buttonPanel.add(btnHighestTotalValue);
 +        buttonPanel.add(btnStock);
 +        buttonPanel.add(btnTotalStock);
 +
 +        JScrollPane listScroller = new JScrollPane(listFuelStations);
 +        listScroller.setPreferredSize(new Dimension(250, 0));
 +
 +        JPanel listPanel = new JPanel(new BorderLayout());
 +        listPanel.add(new JLabel("Fuel station selection (multiple possible):"), BorderLayout.NORTH);
 +        listPanel.add(listFuelStations, BorderLayout.CENTER);
 +
 +        panel.add(buttonPanel, BorderLayout.CENTER);
 +        panel.add(listScroller, BorderLayout.EAST);
 +        panel.add(listPanel, BorderLayout.EAST);
 +
 +        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);
 +    }
 +
 +    /**
 +     * 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.");
 +                }
 +                refreshStationNames();
 +                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;
 +    }
 +
++    /**
++     * Create Panel for overview of fuel stations
++     *
++     * @return overview Panel
++     *
++     * @author Sergej Pavlenko
++     */
++    private JPanel createOverviewPanel() {
++        JPanel panel = new JPanel(new BorderLayout());
++
++        fuelTableModel = new DefaultTableModel(new Object[]{"Fuel station", "Station type", "Fuel", "Amount (L)", "Capacity (L)", "Price (€/L)"}, 0) {
++            @Override
++            public boolean isCellEditable(int row, int column) {
++                return false;
++            }
++        };
++
++        tableFuelTypesPerStation = new JTable(fuelTableModel);
++
++        JScrollPane scrollPane = new JScrollPane(tableFuelTypesPerStation);
++
++        JButton btnRefresh = new JButton("Refresh");
++        btnRefresh.addActionListener(e -> refreshFuelTable());
++
++        JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
++        topPanel.add(new JLabel("Overview of all fuels per fuel station"));
++        topPanel.add(btnRefresh);
++
++        panel.add(topPanel, BorderLayout.NORTH);
++        panel.add(scrollPane, BorderLayout.CENTER);
++
++        refreshFuelTable();
++
++        return panel;
++    }
++
 +    /**
 +     * Updates the selection of fuel stations for ComboBox and List
 +     *
 +     * @author Sergej Pavlenko
 +     */
 +    private void refreshStationNames() {
 +        String[] names = buildStationNames();
 +
 +        comboFuelStations.setModel(new DefaultComboBoxModel<>(names));
 +
 +        listFuelStations.setListData(names);
 +    }
 +
++    /**
++     * Updates table to keep up with changes
++     *
++     * @author Sergej Pavlenko
++     */
++    private void refreshFuelTable() {
++        if (fuelTableModel == null) {
++            return;
++        }
++
++        fuelTableModel.setRowCount(0);
++
++        for (FuelStation station : Main.fuelStations) {
++            String stationName = getDisplayName(station);
++            String stationType = station.getClass().getSimpleName();
++
++            for (Fuel fuel : station.fuels) {
++                Object[] row = new Object[] {
++                        stationName,
++                        stationType,
++                        fuel.FUEL_TYPE,
++                        fuel.getStored_amount(),
++                        fuel.CAPACITY,
++                        fuel.getPrice()
++                };
++                fuelTableModel.addRow(row);
++            }
++        }
++    }
++
 +    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();
 +    }
 +
++    /**
++     * Creates a text output area
++     *
++     * @param text text output area
++     *
++     * @author Sergej Pavlenko
++     */
 +    private void appendOutput(String text) {
 +        outputArea.append(text + "\n\n");
 +        outputArea.setCaretPosition(outputArea.getDocument().getLength());
 +    }
 +
++    /**
++     * Creates an error message
++     *
++     * @param message error message
++     *
++     * @author Sergej Pavlenko
++     */
 +    private void showError(String message) {
 +        JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE);
 +    }
 +}