UI refactoring

This commit is contained in:
Sampo Niskanen 2013-03-21 09:00:34 +02:00
parent f8d742408e
commit bfa609ebbe
13 changed files with 395 additions and 74 deletions

View File

@ -0,0 +1,157 @@
package net.sf.openrocket.formatting;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.plugin.Plugin;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.Chars;
import com.google.inject.Inject;
@Plugin
public class MotorDescriptionSubstitutor implements RocketSubstitutor {
public static final String SUBSTITUTION = "{motors}";
@Inject
private Translator trans;
@Override
public boolean containsSubstitution(String str) {
return str.contains(SUBSTITUTION);
}
@Override
public String substitute(String str, Rocket rocket, String configId) {
String description = getFlightConfigurationDescription(rocket, configId);
return str.replaceAll(SUBSTITUTION, description);
}
@Override
public Map<String, String> getDescriptions() {
Map<String, String> desc = new HashMap<String, String>();
desc.put(SUBSTITUTION, trans.get("description"));
return null;
}
private String getFlightConfigurationDescription(Rocket rocket, String id) {
String name;
int motorCount = 0;
// Generate the description
// First iterate over each stage and store the designations of each motor
List<List<String>> list = new ArrayList<List<String>>();
List<String> currentList = Collections.emptyList();
Iterator<RocketComponent> iterator = rocket.iterator();
while (iterator.hasNext()) {
RocketComponent c = iterator.next();
if (c instanceof Stage) {
currentList = new ArrayList<String>();
list.add(currentList);
} else if (c instanceof MotorMount) {
MotorMount mount = (MotorMount) c;
Motor motor = mount.getMotor(id);
if (mount.isMotorMount() && motor != null) {
String designation = motor.getDesignation(mount.getMotorDelay(id));
for (int i = 0; i < mount.getMotorCount(); i++) {
currentList.add(designation);
motorCount++;
}
}
}
}
if (motorCount == 0) {
//// [No motors]
return trans.get("Rocket.motorCount.Nomotor");
}
// Change multiple occurrences of a motor to n x motor
List<String> stages = new ArrayList<String>();
for (List<String> stage : list) {
String stageName = "";
String previous = null;
int count = 0;
Collections.sort(stage);
for (String current : stage) {
if (current.equals(previous)) {
count++;
} else {
if (previous != null) {
String s = "";
if (count > 1) {
s = "" + count + Chars.TIMES + previous;
} else {
s = previous;
}
if (stageName.equals(""))
stageName = s;
else
stageName = stageName + "," + s;
}
previous = current;
count = 1;
}
}
if (previous != null) {
String s = "";
if (count > 1) {
s = "" + count + Chars.TIMES + previous;
} else {
s = previous;
}
if (stageName.equals(""))
stageName = s;
else
stageName = stageName + "," + s;
}
stages.add(stageName);
}
name = "[";
for (int i = 0; i < stages.size(); i++) {
String s = stages.get(i);
if (s.equals(""))
s = "None";
if (i == 0)
name = name + s;
else
name = name + "; " + s;
}
name += "]";
return name;
}
}

View File

@ -0,0 +1,17 @@
package net.sf.openrocket.formatting;
import net.sf.openrocket.rocketcomponent.Rocket;
/**
* Interface for formatting a flight configuration into a
* textual string.
*/
public interface RocketFormatter {
/**
* Return a string describing a particular flight configuration
* of the rocket.
*/
public String format(Rocket rocket, String configId);
}

View File

@ -0,0 +1,27 @@
package net.sf.openrocket.formatting;
import java.util.Set;
import net.sf.openrocket.rocketcomponent.Rocket;
import com.google.inject.Inject;
public class RocketFormatterImpl implements RocketFormatter {
@Inject
private Set<RocketSubstitutor> substitutors;
@Override
public String format(Rocket rocket, String configId) {
String name = rocket.getFlightConfigurationName(configId);
for (RocketSubstitutor s : substitutors) {
while (s.containsSubstitution(name)) {
name = s.substitute(name, rocket, configId);
}
}
return name;
}
}

View File

@ -0,0 +1,20 @@
package net.sf.openrocket.formatting;
import java.util.Map;
import net.sf.openrocket.plugin.Plugin;
import net.sf.openrocket.rocketcomponent.Rocket;
/**
* A class that allows substitution to occur in a text string.
*/
@Plugin
public interface RocketSubstitutor {
public boolean containsSubstitution(String str);
public String substitute(String str, Rocket rocket, String configId);
public Map<String, String> getDescriptions();
}

View File

@ -19,8 +19,9 @@ import net.sf.openrocket.gui.adaptors.FlightConfigurationModel;
import net.sf.openrocket.gui.main.BasicFrame;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.FlightConfigurableComponent;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketvisitors.CopyFlightConfigurationVisitor;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
/**
@ -64,7 +65,7 @@ public class FlightConfigurationDialog extends JDialog {
configSelector.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
configurationChanged();
}
});
@ -85,7 +86,7 @@ public class FlightConfigurationDialog extends JDialog {
renameConfButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new RenameConfigDialog(FlightConfigurationDialog.this, rocket).setVisible(true);
renameConfiguration();
}
});
panel.add(renameConfButton);
@ -167,37 +168,32 @@ public class FlightConfigurationDialog extends JDialog {
updateButtonState();
}
public void addConfiguration() {
String id = rocket.newFlightConfigurationID();
rocket.getDefaultConfiguration().setFlightConfigurationID(id);
motorConfigurationPanel.fireTableDataChanged();
recoveryConfigurationPanel.fireTableDataChanged();
separationConfigurationPanel.fireTableDataChanged();
updateButtonState();
private void addConfiguration() {
String newId = rocket.newFlightConfigurationID();
rocket.getDefaultConfiguration().setFlightConfigurationID(newId);
configurationChanged();
}
public void copyConfiguration() {
private void copyConfiguration() {
String currentId = rocket.getDefaultConfiguration().getFlightConfigurationID();
// currentID is the currently selected configuration.
String newConfigId = rocket.newFlightConfigurationID();
String oldName = rocket.getFlightConfigurationName(currentId);
CopyFlightConfigurationVisitor v = new CopyFlightConfigurationVisitor(currentId, newConfigId);
v.visit(rocket);
// Select the new configuration
for (RocketComponent c : rocket) {
if (c instanceof FlightConfigurableComponent) {
((FlightConfigurableComponent) c).cloneFlightConfiguration(currentId, newConfigId);
}
}
rocket.setFlightConfigurationName(currentId, oldName);
rocket.getDefaultConfiguration().setFlightConfigurationID(newConfigId);
// Copy the name.
this.changeConfigurationName(oldName);
motorConfigurationPanel.fireTableDataChanged();
recoveryConfigurationPanel.fireTableDataChanged();
separationConfigurationPanel.fireTableDataChanged();
updateButtonState();
configurationChanged();
}
public void changeConfigurationName(String newName) {
String currentId = rocket.getDefaultConfiguration().getFlightConfigurationID();
rocket.setFlightConfigurationName(currentId, newName);
private void renameConfiguration() {
new RenameConfigDialog(this, rocket).setVisible(true);
}
private void removeConfiguration() {
@ -206,26 +202,13 @@ public class FlightConfigurationDialog extends JDialog {
return;
rocket.removeFlightConfigurationID(currentId);
rocket.getDefaultConfiguration().setFlightConfigurationID(null);
motorConfigurationPanel.fireTableDataChanged();
recoveryConfigurationPanel.fireTableDataChanged();
separationConfigurationPanel.fireTableDataChanged();
updateButtonState();
}
/**
* Call this from other panels when a change might cause the names of the configurations to change.
*/
public void fireContentsUpdated() {
configurationChanged();
}
private void updateButtonState() {
String currentId = rocket.getDefaultConfiguration().getFlightConfigurationID();
removeConfButton.setEnabled(currentId != null);
renameConfButton.setEnabled(currentId != null);
motorConfigurationPanel.updateButtonState();
recoveryConfigurationPanel.updateButtonState();
separationConfigurationPanel.updateButtonState();
}
}

View File

@ -0,0 +1,97 @@
package net.sf.openrocket.gui.dialogs.flightconfiguration;
import java.util.HashMap;
import java.util.Map;
import javax.swing.DefaultComboBoxModel;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.Rocket;
public class FlightConfigurationModelRemoveMe extends DefaultComboBoxModel {
private final Configuration config;
private final Rocket rocket;
private Map<String, ID> map = new HashMap<String, ID>();
private final FlightConfigurationDialog flightConfigurationDialog;
public FlightConfigurationModelRemoveMe(FlightConfigurationDialog flightConfigurationDialog, Configuration config) {
this.flightConfigurationDialog = flightConfigurationDialog;
this.config = config;
this.rocket = config.getRocket();
}
void fireContentsUpdated() {
fireContentsChanged(this, 0, rocket.getFlightConfigurationIDs().length);
}
@Override
public Object getElementAt(int index) {
String[] ids = rocket.getFlightConfigurationIDs();
if (index < 0 || index >= ids.length)
return null;
return get(ids[index]);
}
@Override
public int getSize() {
return rocket.getFlightConfigurationIDs().length;
}
@Override
public Object getSelectedItem() {
return get(config.getFlightConfigurationID());
}
@Override
public void setSelectedItem(Object item) {
if (item == null) {
// Clear selection - huh?
return;
}
if (!(item instanceof ID)) {
throw new IllegalArgumentException("MotorConfigurationModel item=" + item);
}
ID idObject = (ID) item;
// flightConfigurationDialog.selectConfiguration(idObject.getID());
}
/*
* The ID class is an adapter, that contains the actual configuration ID,
* but gives the configuration description as its String representation.
* The get(id) method retrieves ID objects and caches them for reuse.
*/
private ID get(String id) {
ID idObject = map.get(id);
if (idObject != null)
return idObject;
idObject = new ID(id);
map.put(id, idObject);
return idObject;
}
private class ID {
private final String id;
public ID(String id) {
this.id = id;
}
public String getID() {
return id;
}
@Override
public String toString() {
return rocket.getFlightConfigurationNameOrDescription(id);
}
}
}

View File

@ -140,7 +140,7 @@ public class MotorConfigurationPanel extends JPanel {
@Override
public void actionPerformed(ActionEvent e) {
// FIXME
selectIgnition();
resetIgnition();
}
});
this.add(resetIgnitionButton, "sizegroup button, wrap");
@ -157,7 +157,7 @@ public class MotorConfigurationPanel extends JPanel {
updateButtonState();
}
public void updateButtonState() {
private void updateButtonState() {
String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID();
MotorMount currentMount = getCurrentMount();
selectMotorButton.setEnabled(currentMount != null && currentID != null);
@ -220,7 +220,6 @@ public class MotorConfigurationPanel extends JPanel {
mount.getMotorConfiguration().set(id, config);
}
flightConfigurationDialog.fireContentsUpdated();
fireTableDataChanged();
}
@ -232,7 +231,6 @@ public class MotorConfigurationPanel extends JPanel {
mount.getMotorConfiguration().resetDefault(id);
flightConfigurationDialog.fireContentsUpdated();
fireTableDataChanged();
}
@ -248,7 +246,18 @@ public class MotorConfigurationPanel extends JPanel {
currentMount);
dialog.setVisible(true);
flightConfigurationDialog.fireContentsUpdated();
fireTableDataChanged();
}
private void resetIgnition() {
String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID();
MotorMount currentMount = getCurrentMount();
if (currentID == null || currentMount == null)
return;
currentMount.getIgnitionConfiguration().resetDefault(currentID);
fireTableDataChanged();
}

View File

@ -26,6 +26,8 @@ import net.sf.openrocket.unit.UnitGroup;
public class RecoveryConfigurationPanel extends JPanel {
// FIXME: Gray italics for default selection
private Translator trans = Application.getTranslator();

View File

@ -6,12 +6,13 @@ import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.startup.Application;
@ -21,56 +22,51 @@ public class RenameConfigDialog extends JDialog {
RenameConfigDialog(final FlightConfigurationDialog parent, final Rocket rocket) {
super(parent, trans.get("edtmotorconfdlg.title.Renameconf"), Dialog.ModalityType.APPLICATION_MODAL);
final Configuration config = rocket.getDefaultConfiguration();
final String configId = rocket.getDefaultConfiguration().getFlightConfigurationID();
JPanel panel = new JPanel(new MigLayout("fill"));
final JTextArea textbox = new JTextArea(config.getFlightConfigurationDescription());
panel.add(textbox, "span, w 200lp, wrap");
// FIXME: Localize
panel.add(new JLabel("Name for flight configuration:"), "span, wrap rel");
final JTextField textbox = new JTextField(rocket.getFlightConfigurationName(configId));
panel.add(textbox, "span, w 200lp, growx, wrap para");
panel.add(new JPanel(), "growx");
JButton okButton = new JButton("Ok");
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
parent.changeConfigurationName(textbox.getText());
String newName = textbox.getText();
rocket.setFlightConfigurationName(configId, newName);
RenameConfigDialog.this.setVisible(false);
}
});
panel.add(okButton);
JButton defaultButton = new JButton("Reset to default");
defaultButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
parent.changeConfigurationName(null);
rocket.setFlightConfigurationName(configId, null);
RenameConfigDialog.this.setVisible(false);
}
});
panel.add(defaultButton);
JButton cancel = new JButton("Cancel");
cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RenameConfigDialog.this.setVisible(false);
}
});
panel.add(cancel);
this.setContentPane(panel);
this.validate();
this.pack();
this.setLocationByPlatform(true);
this.add(panel);
GUIUtil.setDisposableDialogOptions(this, okButton);
}
}

View File

@ -20,11 +20,14 @@ import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration;
import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration.SeparationEvent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
public class SeparationConfigurationPanel extends JPanel {
// FIXME: Gray italics for default selection
private static final Translator trans = Application.getTranslator();
private final FlightConfigurationDialog flightConfigurationDialog;
@ -164,17 +167,20 @@ public class SeparationConfigurationPanel extends JPanel {
return d.getName();
case 1:
String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
StageSeparationConfiguration separationConfig = d.getStageSeparationConfiguration().get(id);
StageSeparationConfiguration config = d.getStageSeparationConfiguration().get(id);
SeparationEvent event = separationConfig.getSeparationEvent();
String str = event.toString();
String str;
str = config.getSeparationEvent().toString();
if (config.getSeparationDelay() > 0.001) {
str += " + " + UnitGroup.UNITS_SHORT_TIME.toStringUnit(config.getSeparationDelay());
}
if (d.getStageSeparationConfiguration().isDefault(id)) {
str = trans.get("SeparationConfigurationPanel.table.separation.default");
str = str.replace("{0}", event.toString());
} else {
str = event.toString();
String def = trans.get("SeparationConfigurationPanel.table.separation.default");
str = def.replace("{0}", str);
}
return str;
default:

View File

@ -651,7 +651,7 @@ public class Rocket extends RocketComponent {
* @return a textual representation of the configuration
*/
@SuppressWarnings("null")
public String getFlightConfigurationDescription(String id) {
private String getFlightConfigurationDescription(String id) {
checkState();
String name;
int motorCount = 0;

View File

@ -7,6 +7,7 @@ import java.util.List;
import java.util.Random;
import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
import net.sf.openrocket.formatting.MotorDescriptionSubstitutor;
import net.sf.openrocket.masscalc.BasicMassCalculator;
import net.sf.openrocket.models.atmosphere.AtmosphericModel;
import net.sf.openrocket.models.atmosphere.ExtendedISAModel;
@ -402,12 +403,15 @@ public class SimulationOptions implements ChangeSource, Cloneable {
} else {
if (src.rocket.hasMotors(src.motorID)) {
// Try to find a matching motor ID
String motorDesc = src.rocket.getFlightConfigurationDescription(src.motorID);
// Try to find a closely matching motor ID
MotorDescriptionSubstitutor formatter = new MotorDescriptionSubstitutor();
String motorDesc = formatter.substitute(MotorDescriptionSubstitutor.SUBSTITUTION, src.rocket, src.motorID);
String matchID = null;
for (String id : this.rocket.getFlightConfigurationIDs()) {
if (motorDesc.equals(this.rocket.getFlightConfigurationDescription(id))) {
String motorDesc2 = formatter.substitute(MotorDescriptionSubstitutor.SUBSTITUTION, this.rocket, id);
if (motorDesc.equals(motorDesc2)) {
matchID = id;
break;
}

View File

@ -1,5 +1,7 @@
package net.sf.openrocket.startup;
import net.sf.openrocket.formatting.RocketFormatter;
import net.sf.openrocket.formatting.RocketFormatterImpl;
import net.sf.openrocket.gui.watcher.WatchService;
import net.sf.openrocket.gui.watcher.WatchServiceImpl;
import net.sf.openrocket.l10n.Translator;
@ -15,6 +17,7 @@ public class ApplicationModule extends AbstractModule {
bind(Preferences.class).toInstance(Application.getPreferences());
bind(Translator.class).toInstance(Application.getTranslator());
bind(WatchService.class).to(WatchServiceImpl.class);
bind(RocketFormatter.class).to(RocketFormatterImpl.class);
}
}