package net.knarcraft.minecraftserverlauncher.userinterface; import net.knarcraft.minecraftserverlauncher.Main; import net.knarcraft.minecraftserverlauncher.profile.Collection; import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController; import net.knarcraft.minecraftserverlauncher.server.Server; import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions; import javax.imageio.ImageIO; import javax.naming.ConfigurationException; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.concurrent.Executors; import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE; import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsScanner; import static net.knarcraft.minecraftserverlauncher.utility.CommonFunctions.getResourceAsStream; /** * Generates a ServerLauncherGUI. * * @author Kristian Knarvik * @version 1.0.0 * @since 1.0.0 */ public class ServerLauncherGUI extends MessageHandler implements ActionListener, GUI { private final JLabel lblStatuslabel = new JLabel("Servers are stopped"); private final ServerLauncherController controller; private Map textStrings; private Tray applicationTray; private JFrame frame; private JTabbedPane tabbedPane; private JTabbedPane serversPane; private ServerControlTab serverControlTab; private ServerLauncherMenu serverLauncherMenu; //Basic controls private JButton startServerButton; private JButton stopServerButton; private JButton addServerButton; private JButton backupButton; private JButton addProfileButton; private JButton deleteProfileButton; private JComboBox profiles; /** * Creates the application window */ public ServerLauncherGUI() throws IOException { super(false); initialize(440, 170); loadMessages(); this.controller = Main.getController(); } /** * Creates the application window * * @param silent

Whether to make the GUI silent (hidden, for testing)

*/ public ServerLauncherGUI(boolean silent) throws IOException { super(silent); if (!silent) { initialize(440, 170); } loadMessages(); this.controller = Main.getController(); } /** * Creates the application window with a preferred width and height * * @param width

The preferred width

* @param height

The preferred height

*/ public ServerLauncherGUI(int width, int height) throws IOException { super(false); initialize(width, height); loadMessages(); this.controller = Main.getController(); } /** * Gets the pane used for server configurations * * @return

The pane used for server configurations

*/ public JTabbedPane getPane() { return this.serversPane; } @Override public void setStatus(String text) { this.lblStatuslabel.setText(text); try (PrintWriter file = new PrintWriter(new FileWriter(Main.getApplicationWorkDirectory() + File.separator + "latestrun.log", true))) { file.println(text); } catch (IOException e) { e.printStackTrace(); } } @Override public File askForDirectory(String prompt) { JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(new java.io.File(".")); chooser.setDialogTitle(prompt); chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); chooser.setAcceptAllFileFilterUsed(false); if (chooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) { setStatus("Choice aborted by user"); return null; } return chooser.getSelectedFile(); } /** * Updates the profiles combo */ public void updateProfiles() { String selectedProfile = Main.getController().getCurrentProfile().getName(); this.profiles.removeAllItems(); for (String profile : Main.getController().getProfileNames()) { this.profiles.addItem(profile); } this.profiles.setSelectedItem(selectedProfile); } /** * Gets the server control tab used by this GUI * * @return

The server control tab used by this GUI

*/ public ServerControlTab getServerControlTab() { return this.serverControlTab; } /** * Gets the size of the main JFrame * * @return

The Dimension of the main JFrame

*/ public Dimension getSize() { return frame.getContentPane().getSize(); } /** * Updates ServerLauncherGUI according to current profile settings */ public void updateWithSavedProfileData() { ServerLauncherController controller = Main.getController(); serversPane.removeAll(); serverLauncherMenu.update(); serverControlTab.update(); for (Collection collection : controller.getCurrentProfile().getCollections()) { serversPane.addTab(collection.getName(), collection.getServerTab().getPanel()); } } /** * Initializes the server launcher GUI * * @param width

The width of the GUI

* @param height

The height of the GUI

* @throws IOException

If unable to load the GUI icon

*/ private void initialize(int width, int height) throws IOException { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | UnsupportedLookAndFeelException | InstantiationException | IllegalAccessException e ) { e.printStackTrace(); } frame = new JFrame("Minecraft server launcher"); frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); frame.getContentPane().setPreferredSize(new Dimension(width, height)); ImageIcon img = new ImageIcon(ImageIO.read(getResourceAsStream("GUIIcon.png"))); frame.setIconImage(img.getImage()); JMenuBar menuBar = new JMenuBar(); frame.setJMenuBar(menuBar); this.serverLauncherMenu = new ServerLauncherMenu(menuBar, this); tabbedPane = new JTabbedPane(JTabbedPane.TOP); frame.getContentPane().add(tabbedPane); JPanel panelBasic = new JPanel(); tabbedPane.addTab("Control panel", null, panelBasic, null); SpringLayout sl_panel = new SpringLayout(); panelBasic.setLayout(sl_panel); JLabel lblBasicControls = new JLabel("Basic controls"); sl_panel.putConstraint(SpringLayout.NORTH, lblBasicControls, 10, SpringLayout.NORTH, panelBasic); panelBasic.add(lblBasicControls); startServerButton = new JButton("Start servers"); sl_panel.putConstraint(SpringLayout.WEST, lblBasicControls, 0, SpringLayout.WEST, startServerButton); sl_panel.putConstraint(SpringLayout.NORTH, startServerButton, 6, SpringLayout.SOUTH, lblBasicControls); sl_panel.putConstraint(SpringLayout.WEST, startServerButton, 10, SpringLayout.WEST, panelBasic); panelBasic.add(startServerButton); startServerButton.addActionListener(this); stopServerButton = new JButton("Stop servers"); sl_panel.putConstraint(SpringLayout.NORTH, stopServerButton, 0, SpringLayout.NORTH, startServerButton); sl_panel.putConstraint(SpringLayout.WEST, stopServerButton, 6, SpringLayout.EAST, startServerButton); panelBasic.add(stopServerButton); stopServerButton.addActionListener(this); JLabel lblProfile = new JLabel("Profile"); sl_panel.putConstraint(SpringLayout.NORTH, lblProfile, 6, SpringLayout.SOUTH, startServerButton); sl_panel.putConstraint(SpringLayout.WEST, lblProfile, 10, SpringLayout.WEST, panelBasic); panelBasic.add(lblProfile); addProfileButton = new JButton("+"); sl_panel.putConstraint(SpringLayout.NORTH, addProfileButton, 6, SpringLayout.SOUTH, lblProfile); sl_panel.putConstraint(SpringLayout.WEST, addProfileButton, 10, SpringLayout.WEST, panelBasic); panelBasic.add(addProfileButton); addProfileButton.addActionListener(this); deleteProfileButton = new JButton("-"); sl_panel.putConstraint(SpringLayout.NORTH, deleteProfileButton, 0, SpringLayout.NORTH, addProfileButton); sl_panel.putConstraint(SpringLayout.WEST, deleteProfileButton, 6, SpringLayout.EAST, addProfileButton); panelBasic.add(deleteProfileButton); deleteProfileButton.addActionListener(this); profiles = new JComboBox<>(); sl_panel.putConstraint(SpringLayout.NORTH, profiles, 0, SpringLayout.NORTH, addProfileButton); sl_panel.putConstraint(SpringLayout.WEST, profiles, 6, SpringLayout.EAST, deleteProfileButton); sl_panel.putConstraint(SpringLayout.EAST, profiles, 124, SpringLayout.EAST, deleteProfileButton); panelBasic.add(profiles); profiles.addActionListener(this); sl_panel.putConstraint(SpringLayout.NORTH, lblStatuslabel, 6, SpringLayout.SOUTH, addProfileButton); sl_panel.putConstraint(SpringLayout.SOUTH, lblStatuslabel, -10, SpringLayout.SOUTH, panelBasic); sl_panel.putConstraint(SpringLayout.WEST, lblStatuslabel, 10, SpringLayout.WEST, panelBasic); sl_panel.putConstraint(SpringLayout.EAST, lblStatuslabel, -10, SpringLayout.EAST, panelBasic); panelBasic.add(lblStatuslabel); addServerButton = new JButton("Add server"); sl_panel.putConstraint(SpringLayout.NORTH, addServerButton, 0, SpringLayout.NORTH, startServerButton); sl_panel.putConstraint(SpringLayout.WEST, addServerButton, 6, SpringLayout.EAST, stopServerButton); panelBasic.add(addServerButton); addServerButton.addActionListener(this); backupButton = new JButton("Backup"); sl_panel.putConstraint(SpringLayout.NORTH, backupButton, 0, SpringLayout.NORTH, startServerButton); sl_panel.putConstraint(SpringLayout.WEST, backupButton, 6, SpringLayout.EAST, addServerButton); panelBasic.add(backupButton); backupButton.addActionListener(this); JPanel controlServers = new JPanel(); tabbedPane.addTab("Control servers", null, controlServers, null); serverControlTab = new ServerControlTab(frame, controlServers); JPanel panel_2 = new JPanel(); tabbedPane.addTab("Servers", null, panel_2, null); SpringLayout sl_panel_2 = new SpringLayout(); panel_2.setLayout(sl_panel_2); JTabbedPane tabbedPane_1 = new JTabbedPane(JTabbedPane.TOP); sl_panel_2.putConstraint(SpringLayout.NORTH, tabbedPane_1, 0, SpringLayout.NORTH, panel_2); sl_panel_2.putConstraint(SpringLayout.WEST, tabbedPane_1, 0, SpringLayout.WEST, panel_2); sl_panel_2.putConstraint(SpringLayout.SOUTH, tabbedPane_1, 0, SpringLayout.SOUTH, panel_2); sl_panel_2.putConstraint(SpringLayout.EAST, tabbedPane_1, 0, SpringLayout.EAST, panel_2); panel_2.add(tabbedPane_1); this.serversPane = tabbedPane_1; tabbedPane_1.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); frame.validate(); frame.pack(); frame.setVisible(true); applicationTray = new Tray(frame, this); updateGUIElementsWhenServersStartOrStop(false); } /** * Hides the GUI to the system tray */ public void hideToTray() { applicationTray.hideToTray(); } /** * Gets the currently selected profile * * @return

The currently selected profile or null

*/ public String getSelectedProfile() { Object selectedProfile = profiles.getSelectedItem(); if (selectedProfile != null) { return selectedProfile.toString(); } else { return null; } } @Override public void actionPerformed(ActionEvent e) { Object actionSource = e.getSource(); //Registers actions on the main tab handleMainTabButtons(actionSource); } /** * Handles buttons and the combo on the main tab * * @param actionSource

The object being interacted with

*/ private void handleMainTabButtons(Object actionSource) { if (actionSource == startServerButton) { controller.saveState(); Executors.newSingleThreadExecutor().execute(Server::startServers); } else if (actionSource == stopServerButton) { stopServers(); } else if (actionSource == addServerButton) { addServer(); } else if (actionSource == backupButton) { CommonFunctions.backup(this); } else if (actionSource == addProfileButton) { controller.addProfile(JOptionPane.showInputDialog("Profile name: ")); updateProfiles(); } else if (actionSource == deleteProfileButton) { deleteProfile(); } else if (actionSource == profiles) { changeProfile(); } } /** * Deletes the selected profile */ private void deleteProfile() { Object selected = profiles.getSelectedItem(); if (selected != null) { controller.removeProfile(selected.toString()); updateProfiles(); } } /** * Adds a new server with a server tab */ private void addServer() { String serverName = JOptionPane.showInputDialog("Name of server: "); try { controller.getCurrentProfile().addCollection(serverName); } catch (ConfigurationException e1) { e1.printStackTrace(); } this.updateWithSavedProfileData(); controller.getCurrentProfile().updateConsoles(); } /** * Updates the ServerLauncherGUI components to block a user from doing illegal actions * * @param running

Whether the servers are currently running

*/ public void updateGUIElementsWhenServersStartOrStop(boolean running) { boolean stopped = !running; //Most gui is only enabled when the server is stopped rather than running. profiles.setEnabled(stopped); addProfileButton.setEnabled(stopped); deleteProfileButton.setEnabled(stopped); startServerButton.setEnabled(stopped); addServerButton.setEnabled(stopped); tabbedPane.setEnabledAt(2, stopped); stopServerButton.setEnabled(running); } /** * Saves the previous profile and loads data from the new profile */ private void changeProfile() { controller.saveState(); Object current = this.profiles.getSelectedItem(); if (current != null) { controller.setCurrentProfile(current.toString()); } this.updateWithSavedProfileData(); controller.getCurrentProfile().updateConsoles(); } /** * Stops all servers */ public void stopServers() { try { setStatus("Servers are stopping..."); Server.stop(); } catch (IOException e1) { showError("Could not stop server."); e1.printStackTrace(); } catch (InterruptedException e) { showError("Could not kill server."); e.printStackTrace(); } } /** * Gets a specific message from its key * * @param stringKey

The key for the string to get

* @return

The corresponding string

*/ public String getMessage(String stringKey) { return textStrings.get(stringKey); } /** * Loads popup messages from a text file */ private void loadMessages() throws FileNotFoundException { textStrings = new HashMap<>(); Scanner file = getResourceAsScanner("menumsg.csv"); while (file.hasNextLine()) { String nextLine = file.nextLine(); String[] line = nextLine.split("="); String content = line[1].replaceAll("_BREAK_", System.getProperty("line.separator")); textStrings.put(line[0], content); } } }