package com.google.jstestdriver.idea.server.ui;
import com.google.jstestdriver.idea.server.JstdServerSettings;
import com.google.jstestdriver.idea.server.JstdServerSettingsManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.PortField;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.tabs.TabInfo;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.SwingHelper;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.ParseException;
public class JstdServerSettingsTab {
private static final int GAP = 8;
private final PortField myPortField;
private final JSpinner myBrowserTimeoutSpinner;
private final ComboBox myRunnerModeComboBox;
private final TabInfo myTabInfo;
private boolean myTrackChanges = true;
public JstdServerSettingsTab(@NotNull Disposable parentDisposable) {
myPortField = new PortField();
myBrowserTimeoutSpinner = createBrowserTimeoutSpinner();
myRunnerModeComboBox = new ComboBox(JstdServerSettings.RunnerMode.values());
JPanel form = FormBuilder.createFormBuilder()
.setAlignLabelOnRight(true)
.addLabeledComponent("&Port:", myPortField)
.addLabeledComponent("&Browser timeout:", addMillisDescription(myBrowserTimeoutSpinner))
.addLabeledComponent("&Runner mode:", myRunnerModeComboBox)
.getPanel();
JPanel result = createResultPanel(form);
result.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
myTabInfo = new TabInfo(new JBScrollPane(result));
myTabInfo.setText("Settings");
setSettings(JstdServerSettingsManager.loadSettings());
JstdServerSettingsManager.addListener(new JstdServerSettingsManager.Listener() {
@Override
public void onChanged(@NotNull JstdServerSettings settings) {
setSettings(settings);
}
}, parentDisposable);
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
saveSettings();
}
});
listenForChanges();
}
@NotNull
public TabInfo getTabInfo() {
return myTabInfo;
}
private void listenForChanges() {
myPortField.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
update();
}
});
myBrowserTimeoutSpinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
update();
}
});
myRunnerModeComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
update();
}
});
}
private void update() {
if (myTrackChanges) {
JstdServerSettings settings = getSettings();
JstdServerSettingsManager.saveSettings(settings);
}
}
@NotNull
private static JPanel createResultPanel(@NotNull JPanel form) {
JPanel p = new JPanel(new BorderLayout(0, 0));
p.add(form, BorderLayout.NORTH);
p.add(new JPanel(), BorderLayout.CENTER);
p.add(createHyperlink(), BorderLayout.SOUTH);
return p;
}
@NotNull
private static JComponent addMillisDescription(@NotNull JSpinner spinner) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
panel.add(spinner);
panel.add(Box.createHorizontalStrut(10));
panel.add(new JLabel("ms"));
return panel;
}
@NotNull
private static JSpinner createBrowserTimeoutSpinner() {
JSpinner spinner = new JSpinner();
spinner.setModel(new SpinnerNumberModel(0, 0, null, 1));
JSpinner.NumberEditor numberEditor = new JSpinner.NumberEditor(spinner, "#");
spinner.setEditor(numberEditor);
numberEditor.getTextField().setColumns(5);
return spinner;
}
@NotNull
private static JComponent createHyperlink() {
return SwingHelper.createWebHyperlink(
"JsTestDriver Server Options Help",
"https://code.google.com/p/js-test-driver/wiki/CommandLineFlags"
);
}
@NotNull
private JstdServerSettings getSettings() {
try {
myPortField.commitEdit();
myBrowserTimeoutSpinner.commitEdit();
}
catch (ParseException ignored) {
}
int browserTimeout = ((SpinnerNumberModel)myBrowserTimeoutSpinner.getModel()).getNumber().intValue();
JstdServerSettings.RunnerMode runnerMode = ObjectUtils.tryCast(myRunnerModeComboBox.getSelectedItem(), JstdServerSettings.RunnerMode.class);
runnerMode = ObjectUtils.notNull(runnerMode, JstdServerSettings.RunnerMode.QUIET);
return new JstdServerSettings.Builder()
.setPort(myPortField.getNumber())
.setBrowserTimeoutMillis(browserTimeout)
.setRunnerMode(runnerMode)
.build();
}
private void setSettings(@NotNull JstdServerSettings settings) {
myTrackChanges = false;
try {
myPortField.setNumber(settings.getPort());
myBrowserTimeoutSpinner.setValue(settings.getBrowserTimeoutMillis());
myRunnerModeComboBox.setSelectedItem(settings.getRunnerMode());
}
finally {
myTrackChanges = true;
}
}
public void saveSettings() {
JstdServerSettings settings = getSettings();
JstdServerSettingsManager.saveSettings(settings);
}
}