/* EngineServer - Network engine server for DroidFish Copyright (C) 2019 Peter Ă–sterlund, peterosterlund2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package org.petero.engineserver; import java.awt.Container; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.net.InetAddress; import java.net.UnknownHostException; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTextField; import javax.swing.SwingUtilities; /** Displays the GUI to configure engine settings. */ public class MainWindow { private JFrame frame; private JCheckBox[] enabled; private JTextField[] port; private JTextField[] filename; private JTextField[] arguments; private EngineServer server; private EngineConfig[] configs; public MainWindow(EngineServer server, EngineConfig[] configs) { this.server = server; this.configs = configs; SwingUtilities.invokeLater(this::initUI); } private void initUI() { final int numEngines = configs.length; frame = new JFrame(); enabled = new JCheckBox[numEngines]; port = new JTextField[numEngines]; filename = new JTextField[numEngines]; arguments = new JTextField[numEngines]; Container pane = frame.getContentPane(); String title = "Chess Engine Server"; try { InetAddress ip = InetAddress.getLocalHost(); String addr = ip.getHostAddress(); if (!"127.0.0.1".equals(addr)) title += " : IP = " + addr; } catch (UnknownHostException ignore) { } frame.setTitle(title); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent event) { server.shutdown(); } }); GridBagLayout layout = new GridBagLayout(); pane.setLayout(layout); int row = 0; GridBagConstraints constr = new GridBagConstraints(); Insets inset = new Insets(0, 0, 5, 5); constr.insets = inset; constr.gridx = 0; constr.gridy = row; pane.add(new JLabel("Enabled"), constr); constr = new GridBagConstraints(); constr.insets = inset; constr.gridx = 1; constr.gridy = row; pane.add(new JLabel("Port"), constr); constr = new GridBagConstraints(); constr.insets = inset; constr.gridx = 2; constr.gridy = row; pane.add(new JLabel("Program and arguments"), constr); row++; for (int r = 0; r < numEngines; r++) { final int engineNo = r; final EngineConfig config = configs[r]; enabled[r] = new JCheckBox(""); constr = new GridBagConstraints(); constr.insets = inset; constr.gridx = 0; constr.gridy = row; pane.add(enabled[r], constr); enabled[r].setSelected(config.enabled); enabled[r].addActionListener(event -> enabledChanged(engineNo)); port[r] = new JTextField(); constr = new GridBagConstraints(); constr.anchor = GridBagConstraints.WEST; constr.insets = inset; constr.gridx = 1; constr.gridy = row; pane.add(port[r], constr); port[r].setColumns(5); port[r].setText(Integer.toString(config.port)); port[r].addActionListener(event -> portChanged(engineNo)); port[r].addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent event) { portChanged(engineNo); } }); filename[r] = new JTextField(); constr = new GridBagConstraints(); constr.insets = inset; constr.fill = GridBagConstraints.HORIZONTAL; constr.gridx = 2; constr.gridy = row; pane.add(filename[r], constr); filename[r].setColumns(40); filename[r].setText(config.filename); filename[r].addActionListener(event -> filenameChanged(engineNo)); filename[r].addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent event) { filenameChanged(engineNo); } }); arguments[r] = new JTextField(); constr = new GridBagConstraints(); constr.insets = inset; constr.fill = GridBagConstraints.HORIZONTAL; constr.gridx = 2; constr.gridy = row + 1; pane.add(arguments[r], constr); arguments[r].setColumns(40); arguments[r].setText(config.arguments); arguments[r].addActionListener(event -> argumentsChanged(engineNo)); arguments[r].addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent event) { argumentsChanged(engineNo); } }); JButton browse = new JButton("Browse"); constr = new GridBagConstraints(); constr.anchor = GridBagConstraints.NORTH; constr.insets = inset; constr.gridx = 3; constr.gridy = row; constr.gridheight = 2; pane.add(browse, constr); browse.addActionListener(event -> browseFile(engineNo)); row += 2; } frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } private void enabledChanged(int engineNo) { EngineConfig config = configs[engineNo]; boolean e = enabled[engineNo].isSelected(); if (e != config.enabled) { config.enabled = e; server.configChanged(engineNo); } } private void portChanged(int engineNo) { EngineConfig config = configs[engineNo]; try { int p = Integer.parseInt(port[engineNo].getText().trim()); if (p >= 1024 && p < 65536 && p != config.port) { config.port = p; server.configChanged(engineNo); } } catch (NumberFormatException ignore) { } } private void filenameChanged(int engineNo) { EngineConfig config = configs[engineNo]; String fn = filename[engineNo].getText().trim(); if (!fn.equals(config.filename)) { config.filename = fn; server.configChanged(engineNo); } } private void browseFile(int engineNo) { String fn = filename[engineNo].getText(); JFileChooser chooser = new JFileChooser(); chooser.setDialogTitle("Select chess engine"); chooser.setSelectedFile(new File(fn)); if (chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) fn = chooser.getSelectedFile().getAbsolutePath(); filename[engineNo].setText(fn); filenameChanged(engineNo); } private void argumentsChanged(int engineNo) { EngineConfig config = configs[engineNo]; String args = arguments[engineNo].getText().trim(); if (!args.equals(config.arguments)) { config.arguments = args; server.configChanged(engineNo); } } public void reportError(String title, String message) { StringBuilder sb = new StringBuilder(); int lineLen = 100; while (message.length() > lineLen) { sb.append(message, 0, lineLen); sb.append('\n'); message = message.substring(lineLen); } sb.append(message); SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(frame, sb.toString(), title, JOptionPane.ERROR_MESSAGE)); } }