From: Sergej Pavlenko Date: Wed, 19 Nov 2025 20:50:12 +0000 (+0100) Subject: GUI für: X-Git-Url: https://git.eternal.ddnss.de/?a=commitdiff_plain;h=159be744bdf59ed0cae29f552b44090d1409c37f;p=tankstelle.git GUI für: neue Tankstelle Tankstellen mit bestimmter Treibstoffart Treibstoffmenge Treibstoffpreis ändern Tankstelle finden Den Gesamt-Verkaufspreis aller Lagerbestände beim aktuellen Verkaufspreis bestimmen erstellt --- diff --git a/src/main/java/de/diejungsvondertanke/tankstelle/FuelStationUI.java b/src/main/java/de/diejungsvondertanke/tankstelle/FuelStationUI.java new file mode 100644 index 0000000..abfbae9 --- /dev/null +++ b/src/main/java/de/diejungsvondertanke/tankstelle/FuelStationUI.java @@ -0,0 +1,460 @@ +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 comboFuelStations; + private JComboBox 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 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 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); + } +} diff --git a/src/main/java/de/diejungsvondertanke/tankstelle/Main.java b/src/main/java/de/diejungsvondertanke/tankstelle/Main.java index f7edc40..312455b 100644 --- a/src/main/java/de/diejungsvondertanke/tankstelle/Main.java +++ b/src/main/java/de/diejungsvondertanke/tankstelle/Main.java @@ -8,6 +8,8 @@ import java.util.Arrays; import de.diejungsvondertanke.tankstelle.error.NoSuchFuelTypeError; +import javax.swing.*; + /** * Main Class * @@ -36,7 +38,10 @@ public class Main { * @param args Program arguments (not in use) */ public static void main(String[] args) { - + javax.swing.SwingUtilities.invokeLater(() -> { + FuelStationUI ui = new FuelStationUI(); + ui.setVisible(true); + }); } /** @@ -322,5 +327,4 @@ public class Main { return sum; } - } \ No newline at end of file