Files
droidfish/EngineServer/src/main/java/org/petero/engineserver/MainWindow.java
2022-12-11 10:18:16 +01:00

254 lines
8.7 KiB
Java

/*
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 <http://www.gnu.org/licenses/>.
*/
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 final EngineServer server;
private final 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));
}
}