478 lines
12 KiB
Java
478 lines
12 KiB
Java
/*
|
|
* Copyright © 2012 Keith Packard <keithp@keithp.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 2 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, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
*/
|
|
|
|
package altosui;
|
|
|
|
import java.text.*;
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import javax.swing.*;
|
|
import javax.swing.event.*;
|
|
import org.altusmetrum.altoslib_14.*;
|
|
import org.altusmetrum.altosuilib_14.*;
|
|
|
|
public class AltosConfigPyroUI
|
|
extends AltosUIDialog
|
|
implements ItemListener, DocumentListener, AltosUnitsListener, ActionListener
|
|
{
|
|
AltosConfigFCUI owner;
|
|
Container pane;
|
|
|
|
static Insets il = new Insets(4,4,4,4);
|
|
static Insets ir = new Insets(4,4,4,4);
|
|
|
|
static String[] state_names;
|
|
|
|
static void make_state_names() {
|
|
if (state_names == null) {
|
|
|
|
state_names = new String[AltosLib.ao_flight_landed - AltosLib.ao_flight_boost + 1];
|
|
for (int state = AltosLib.ao_flight_boost; state <= AltosLib.ao_flight_landed; state++)
|
|
state_names[state - AltosLib.ao_flight_boost] = AltosLib.state_name_capital(state);
|
|
}
|
|
}
|
|
|
|
class PyroItem implements ItemListener, DocumentListener, AltosUnitsListener
|
|
{
|
|
public int flag;
|
|
public JCheckBox enable;
|
|
public JTextField value;
|
|
public JComboBox<String> combo;
|
|
AltosConfigPyroUI ui;
|
|
boolean setting;
|
|
|
|
public void set_enable(boolean enable) {
|
|
if (value != null)
|
|
value.setEnabled(enable);
|
|
if (combo != null)
|
|
combo.setEnabled(enable);
|
|
}
|
|
|
|
public void itemStateChanged(ItemEvent e) {
|
|
set_enable(enable.isSelected());
|
|
if (!setting)
|
|
ui.set_dirty();
|
|
}
|
|
|
|
public void changedUpdate(DocumentEvent e) {
|
|
if (!setting)
|
|
ui.set_dirty();
|
|
}
|
|
|
|
public void insertUpdate(DocumentEvent e) {
|
|
if (!setting)
|
|
ui.set_dirty();
|
|
}
|
|
|
|
public void removeUpdate(DocumentEvent e) {
|
|
if (!setting)
|
|
ui.set_dirty();
|
|
}
|
|
|
|
public void units_changed(boolean imperial_units) {
|
|
AltosUnits units = AltosPyro.pyro_to_units(flag);
|
|
|
|
if (units != null) {
|
|
try {
|
|
double v = units.parse_locale(value.getText(), !imperial_units);
|
|
set(enabled(), v);
|
|
} catch (ParseException pe) {
|
|
set(enabled(), 0.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void set(boolean new_enable, double new_value) {
|
|
setting = true;
|
|
enable.setSelected(new_enable);
|
|
set_enable(new_enable);
|
|
if (value != null) {
|
|
double scale = AltosPyro.pyro_to_scale(flag);
|
|
double unit_value = new_value;
|
|
AltosUnits units = AltosPyro.pyro_to_units(flag);
|
|
if (units != null)
|
|
unit_value = units.parse_value(new_value);
|
|
String format;
|
|
if (scale >= 100)
|
|
format = "%6.2f";
|
|
else if (scale >= 10)
|
|
format = "%6.1f";
|
|
else
|
|
format = "%6.0f";
|
|
value.setText(String.format(format, unit_value));
|
|
}
|
|
if (combo != null)
|
|
if (new_value >= AltosLib.ao_flight_boost && new_value <= AltosLib.ao_flight_landed)
|
|
combo.setSelectedIndex((int) new_value - AltosLib.ao_flight_boost);
|
|
setting = false;
|
|
}
|
|
|
|
public boolean enabled() {
|
|
return enable.isSelected();
|
|
}
|
|
|
|
public double value() throws AltosConfigDataException {
|
|
if (value != null) {
|
|
AltosUnits units = AltosPyro.pyro_to_units(flag);
|
|
try {
|
|
if (units != null)
|
|
return units.parse_locale(value.getText());
|
|
return AltosParse.parse_double_locale(value.getText());
|
|
} catch (ParseException e) {
|
|
throw new AltosConfigDataException("\"%s\": %s\n", value.getText(), e.getMessage());
|
|
}
|
|
}
|
|
if (combo != null)
|
|
return combo.getSelectedIndex() + AltosLib.ao_flight_boost;
|
|
return 0;
|
|
}
|
|
|
|
public PyroItem(AltosConfigPyroUI in_ui, int in_flag, int x, int y) {
|
|
|
|
ui = in_ui;
|
|
flag = in_flag;
|
|
|
|
GridBagConstraints c;
|
|
c = new GridBagConstraints();
|
|
c.gridx = x; c.gridy = y;
|
|
c.gridwidth = 1;
|
|
c.fill = GridBagConstraints.NONE;
|
|
c.anchor = GridBagConstraints.LINE_START;
|
|
c.insets = il;
|
|
enable = new JCheckBox();
|
|
enable.addItemListener(this);
|
|
pane.add(enable, c);
|
|
|
|
if ((flag & AltosPyro.pyro_no_value) == 0) {
|
|
c = new GridBagConstraints();
|
|
c.gridx = x+1; c.gridy = y;
|
|
c.gridwidth = 1;
|
|
c.fill = GridBagConstraints.NONE;
|
|
c.anchor = GridBagConstraints.LINE_START;
|
|
c.insets = il;
|
|
if ((flag & AltosPyro.pyro_state_value) != 0) {
|
|
make_state_names();
|
|
combo = new JComboBox<String>(state_names);
|
|
combo.addItemListener(this);
|
|
pane.add(combo, c);
|
|
} else {
|
|
value = new JTextField(10);
|
|
value.getDocument().addDocumentListener(this);
|
|
pane.add(value, c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class PyroColumn implements AltosUnitsListener {
|
|
public PyroItem[] items;
|
|
public JLabel label;
|
|
int channel;
|
|
|
|
public void set(AltosPyro pyro) {
|
|
int row = 0;
|
|
if ((pyro.flags & AltosPyro.pyro_deprecate) != 0) {
|
|
JOptionPane.showMessageDialog(owner,
|
|
String.format("Pyro settings “Ascending” and “Descending” are deprecated.\n" +
|
|
"Clearing %s configuration.", AltosLib.igniter_name(pyro.channel)),
|
|
"Deprecated Pyro Settings",
|
|
JOptionPane.ERROR_MESSAGE);
|
|
pyro.flags = 0;
|
|
owner.set_dirty();
|
|
}
|
|
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
|
|
if ((AltosPyro.pyro_all_useful & flag) != 0) {
|
|
items[row].set((pyro.flags & flag) != 0,
|
|
pyro.get_value(flag));
|
|
row++;
|
|
}
|
|
}
|
|
}
|
|
|
|
public AltosPyro get() throws AltosConfigDataException {
|
|
AltosPyro p = new AltosPyro(channel);
|
|
|
|
int row = 0;
|
|
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
|
|
if ((AltosPyro.pyro_all_useful & flag) != 0) {
|
|
if (items[row].enabled()) {
|
|
try {
|
|
p.flags |= flag;
|
|
p.set_value(flag, items[row].value());
|
|
} catch (AltosConfigDataException ae) {
|
|
throw new AltosConfigDataException("%s, %s",
|
|
AltosPyro.pyro_to_name(flag),
|
|
ae.getMessage());
|
|
}
|
|
}
|
|
row++;
|
|
}
|
|
}
|
|
return p;
|
|
}
|
|
|
|
public void units_changed(boolean imperial_units) {
|
|
int row = 0;
|
|
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
|
|
if ((AltosPyro.pyro_all_useful & flag) != 0) {
|
|
items[row].units_changed(imperial_units);
|
|
row++;
|
|
}
|
|
}
|
|
}
|
|
|
|
public PyroColumn(AltosConfigPyroUI ui, int x, int y, int in_channel) {
|
|
|
|
channel = in_channel;
|
|
|
|
int nrow = 0;
|
|
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
|
|
if ((flag & AltosPyro.pyro_all_useful) != 0)
|
|
nrow++;
|
|
|
|
items = new PyroItem[nrow];
|
|
int row = 0;
|
|
|
|
GridBagConstraints c;
|
|
c = new GridBagConstraints();
|
|
c.gridx = x; c.gridy = y;
|
|
c.gridwidth = 2;
|
|
c.fill = GridBagConstraints.NONE;
|
|
c.anchor = GridBagConstraints.CENTER;
|
|
c.insets = il;
|
|
label = new JLabel(String.format("Pyro Channel %c", 'A' + channel));
|
|
pane.add(label, c);
|
|
y++;
|
|
|
|
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
|
|
if ((flag & AltosPyro.pyro_all_useful) != 0) {
|
|
items[row] = new PyroItem(ui, flag, x, y + row);
|
|
row++;
|
|
}
|
|
}
|
|
}
|
|
|
|
PyroColumn[] columns;
|
|
JLabel[] labels;
|
|
|
|
public void set_pyros(AltosPyro[] pyros) {
|
|
for (int i = 0; i < pyros.length; i++) {
|
|
if (pyros[i].channel < columns.length)
|
|
columns[pyros[i].channel].set(pyros[i]);
|
|
}
|
|
}
|
|
|
|
public AltosPyro[] get_pyros() throws AltosConfigDataException {
|
|
AltosPyro[] pyros = new AltosPyro[columns.length];
|
|
for (int c = 0; c < columns.length; c++) {
|
|
try {
|
|
pyros[c] = columns[c].get();
|
|
} catch (AltosConfigDataException ae) {
|
|
throw new AltosConfigDataException ("Channel %c, %s", c + 'A', ae.getMessage());
|
|
}
|
|
}
|
|
return pyros;
|
|
}
|
|
|
|
JLabel pyro_firing_time_label;
|
|
JComboBox<String> pyro_firing_time_value;
|
|
|
|
static String[] pyro_firing_time_values = {
|
|
"0.050", "0.100", "0.250", "0.500", "1.0", "2.0"
|
|
};
|
|
|
|
boolean initializing;
|
|
|
|
public void set_pyro_firing_time(double new_pyro_firing_time) {
|
|
initializing = true;
|
|
pyro_firing_time_value.setSelectedItem(Double.toString(new_pyro_firing_time));
|
|
pyro_firing_time_value.setEnabled(new_pyro_firing_time >= 0);
|
|
initializing = false;
|
|
}
|
|
|
|
public double get_pyro_firing_time() throws AltosConfigDataException {
|
|
String v = pyro_firing_time_value.getSelectedItem().toString();
|
|
|
|
try {
|
|
return AltosParse.parse_double_locale(v);
|
|
} catch (ParseException e) {
|
|
throw new AltosConfigDataException("Invalid pyro firing time \"%s\"", v);
|
|
}
|
|
}
|
|
|
|
public void set_dirty() {
|
|
if (!initializing)
|
|
owner.set_dirty();
|
|
}
|
|
|
|
public void itemStateChanged(ItemEvent e) {
|
|
if (!initializing)
|
|
owner.set_dirty();
|
|
}
|
|
|
|
public void changedUpdate(DocumentEvent e) {
|
|
if (!initializing)
|
|
owner.set_dirty();
|
|
}
|
|
|
|
public void insertUpdate(DocumentEvent e) {
|
|
if (!initializing)
|
|
owner.set_dirty();
|
|
}
|
|
|
|
public void removeUpdate(DocumentEvent e) {
|
|
if (!initializing)
|
|
owner.set_dirty();
|
|
}
|
|
|
|
public void units_changed(boolean imperial_units) {
|
|
for (int c = 0; c < columns.length; c++)
|
|
columns[c].units_changed(imperial_units);
|
|
int r = 0;
|
|
for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) {
|
|
if ((flag & AltosPyro.pyro_all_useful) != 0) {
|
|
String n = AltosPyro.pyro_to_name(flag);
|
|
if (n != null) {
|
|
labels[r].setText(n);
|
|
r++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* A window listener to catch closing events and tell the config code */
|
|
class ConfigListener extends WindowAdapter {
|
|
AltosConfigPyroUI ui;
|
|
AltosConfigFCUI owner;
|
|
|
|
public ConfigListener(AltosConfigPyroUI this_ui, AltosConfigFCUI this_owner) {
|
|
ui = this_ui;
|
|
owner = this_owner;
|
|
}
|
|
|
|
public void windowClosing(WindowEvent e) {
|
|
ui.setVisible(false);
|
|
}
|
|
}
|
|
|
|
/* Listen for events from our buttons */
|
|
public void actionPerformed(ActionEvent e) {
|
|
String cmd = e.getActionCommand();
|
|
|
|
if (cmd.equals("Close"))
|
|
setVisible(false);
|
|
}
|
|
|
|
public AltosConfigPyroUI(AltosConfigFCUI in_owner, AltosPyro[] pyros, double pyro_firing_time) {
|
|
|
|
super(in_owner, "Configure Pyro Channels", false);
|
|
|
|
owner = in_owner;
|
|
|
|
GridBagConstraints c;
|
|
|
|
pane = getScrollablePane();
|
|
pane.setLayout(new GridBagLayout());
|
|
|
|
int nrow = 0;
|
|
for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
|
|
if ((flag & AltosPyro.pyro_all_useful) != 0)
|
|
nrow++;
|
|
|
|
labels = new JLabel[nrow];
|
|
|
|
int row = 1;
|
|
|
|
for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) {
|
|
String n;
|
|
|
|
if ((flag & AltosPyro.pyro_all_useful) != 0) {
|
|
n = AltosPyro.pyro_to_name(flag);
|
|
if (n != null) {
|
|
c = new GridBagConstraints();
|
|
c.gridx = 0; c.gridy = row;
|
|
c.gridwidth = 1;
|
|
c.fill = GridBagConstraints.NONE;
|
|
c.anchor = GridBagConstraints.LINE_START;
|
|
c.insets = il;
|
|
JLabel label = new JLabel(n);
|
|
pane.add(label, c);
|
|
labels[row-1] = label;
|
|
row++;
|
|
}
|
|
}
|
|
}
|
|
|
|
columns = new PyroColumn[pyros.length];
|
|
|
|
for (int i = 0; i < pyros.length; i++) {
|
|
columns[i] = new PyroColumn(this, i*2 + 1, 0, i);
|
|
columns[i].set(pyros[i]);
|
|
}
|
|
|
|
/* Pyro firing time */
|
|
c = new GridBagConstraints();
|
|
c.gridx = 0; c.gridy = row;
|
|
c.gridwidth = 2;
|
|
c.fill = GridBagConstraints.NONE;
|
|
c.anchor = GridBagConstraints.LINE_START;
|
|
c.insets = il;
|
|
c.ipady = 5;
|
|
pyro_firing_time_label = new JLabel("Pyro Firing Time(s):");
|
|
pane.add(pyro_firing_time_label, c);
|
|
|
|
c = new GridBagConstraints();
|
|
c.gridx = 2; c.gridy = row;
|
|
c.gridwidth = 7;
|
|
c.fill = GridBagConstraints.HORIZONTAL;
|
|
c.weightx = 1;
|
|
c.anchor = GridBagConstraints.LINE_START;
|
|
c.insets = ir;
|
|
c.ipady = 5;
|
|
pyro_firing_time_value = new JComboBox<String>(pyro_firing_time_values);
|
|
pyro_firing_time_value.setEditable(true);
|
|
pyro_firing_time_value.addItemListener(this);
|
|
set_pyro_firing_time(pyro_firing_time);
|
|
pane.add(pyro_firing_time_value, c);
|
|
pyro_firing_time_value.setToolTipText("Length of extra pyro channel firing pulse");
|
|
|
|
c = new GridBagConstraints();
|
|
c.gridx = pyros.length*2-1;
|
|
c.fill = GridBagConstraints.HORIZONTAL;
|
|
c.gridwidth = 2;
|
|
c.gridy = 1000;
|
|
JButton close = new JButton("Close");
|
|
pane.add(close, c);
|
|
close.addActionListener(this);
|
|
close.setActionCommand("Close");
|
|
|
|
addWindowListener(new ConfigListener(this, owner));
|
|
AltosPreferences.register_units_listener(this);
|
|
}
|
|
|
|
public void dispose() {
|
|
AltosPreferences.unregister_units_listener(this);
|
|
super.dispose();
|
|
}
|
|
|
|
public void make_visible() {
|
|
pack();
|
|
setVisible(true);
|
|
}
|
|
}
|