Save document materials in document preferences

This commit is contained in:
SiboVG 2024-07-23 00:34:59 +02:00
parent 500c75aeab
commit 5d45d075ce
15 changed files with 449 additions and 183 deletions

View File

@ -178,6 +178,30 @@ public class Databases {
public static void fakeMethod() {
}
/**
* Find a material from the database or return a new user defined material if the specified
* material with the specified density is not found.
* <p>
* This method will attempt to localize the material name to the current locale, or use
* the provided name if unable to do so.
*
* @param type the material type.
* @param baseName the base name of the material.
* @param density the density of the material.
* @return the material object from the database or a new material.
*/
public static Material findMaterial(Material.Type type, String baseName, double density) {
Database<Material> db = getDatabase(type);
String name = trans.get("material", baseName);
for (Material m : db) {
if (m.getName().equalsIgnoreCase(name) && MathUtil.equals(m.getDensity(), density)) {
return m;
}
}
return Material.newMaterial(type, name, density, true);
}
/**
* Find a material from the database with the specified type and name. Returns
@ -207,42 +231,13 @@ public class Databases {
* @param type the desired type
* @return the database of the type given
*/
private static Database<Material> getDatabase(Material.Type type){
switch (type) {
case BULK:
return BULK_MATERIAL;
case SURFACE:
return SURFACE_MATERIAL;
case LINE:
return LINE_MATERIAL;
default:
throw new IllegalArgumentException("Illegal material type: " + type);
}
}
/**
* Find a material from the database or return a new user defined material if the specified
* material with the specified density is not found.
* <p>
* This method will attempt to localize the material name to the current locale, or use
* the provided name if unable to do so.
*
* @param type the material type.
* @param baseName the base name of the material.
* @param density the density of the material.
* @return the material object from the database or a new material.
*/
public static Material findMaterial(Material.Type type, String baseName, double density) {
Database<Material> db = getDatabase(type);
String name = trans.get("material", baseName);
for (Material m : db) {
if (m.getName().equalsIgnoreCase(name) && MathUtil.equals(m.getDensity(), density)) {
return m;
}
}
return Material.newMaterial(type, name, density, true);
public static Database<Material> getDatabase(Material.Type type){
return switch (type) {
case BULK -> BULK_MATERIAL;
case SURFACE -> SURFACE_MATERIAL;
case LINE -> LINE_MATERIAL;
default -> throw new IllegalArgumentException("Illegal material type: " + type);
};
}
}

View File

@ -11,6 +11,7 @@ import info.openrocket.core.file.openrocket.savers.PhotoStudioSaver;
import info.openrocket.core.logging.ErrorSet;
import info.openrocket.core.logging.SimulationAbort;
import info.openrocket.core.logging.WarningSet;
import info.openrocket.core.material.Material;
import info.openrocket.core.preferences.DocumentPreferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -438,12 +439,24 @@ public class OpenRocketSaver extends RocketSaver {
writeln("<docprefs>");
indent++;
// Normal preferences
Map<String, DocumentPreferences.DocumentPreference> prefs = docPrefs.getPreferencesMap();
for (Map.Entry<String, DocumentPreferences.DocumentPreference> entry : prefs.entrySet()) {
DocumentPreferences.DocumentPreference pref = entry.getValue();
writeEntry("pref", entry.getKey(), pref.getValue(), true);
}
// Document materials
if (docPrefs.getTotalMaterialCount() > 0) {
writeln("<docmaterials>");
indent++;
for (Material m : docPrefs.getAllMaterials()) {
writeln("<mat>" + m.toStorableString() + "</mat>");
}
indent--;
writeln("</docmaterials>");
}
indent--;
writeln("</docprefs>");
}

View File

@ -0,0 +1,36 @@
package info.openrocket.core.file.openrocket.importt;
import info.openrocket.core.document.OpenRocketDocument;
import info.openrocket.core.file.simplesax.AbstractElementHandler;
import info.openrocket.core.file.simplesax.ElementHandler;
import info.openrocket.core.file.simplesax.PlainTextHandler;
import info.openrocket.core.logging.WarningSet;
import info.openrocket.core.material.Material;
import org.xml.sax.SAXException;
import java.util.HashMap;
public class DocumentMaterialHandler extends AbstractElementHandler {
private final OpenRocketDocument document;
public DocumentMaterialHandler(OpenRocketDocument document) {
this.document = document;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) throws SAXException {
if (element.equals("mat")) {
return PlainTextHandler.INSTANCE;
}
return null;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
if ("mat".equals(element)) {
Material mat = Material.fromStorableString(content, true);
mat.setDocumentMaterial(true);
document.getDocumentPreferences().getDatabase(mat.getType()).add(mat);
}
}
}

View File

@ -21,6 +21,8 @@ public class DocumentPreferencesHandler extends EntryHandler {
if (element.equals("pref") && "list".equals(attributes.get("type"))) {
listHandler = new ConfigHandler();
return listHandler;
} else if (element.equals("docmaterials")) {
return new DocumentMaterialHandler(document);
} else {
return PlainTextHandler.INSTANCE;
}

View File

@ -50,6 +50,10 @@ public abstract class Material implements Comparable<Material> {
///// Definitions of different material types /////
public static class Line extends Material {
Line(String name, double density, MaterialGroup group, boolean userDefined, boolean documentMaterial) {
super(name, density, group, userDefined, documentMaterial);
}
Line(String name, double density, MaterialGroup group, boolean userDefined) {
super(name, density, group, userDefined);
}
@ -65,6 +69,9 @@ public abstract class Material implements Comparable<Material> {
}
public static class Surface extends Material {
Surface(String name, double density, MaterialGroup group, boolean userDefined, boolean documentMaterial) {
super(name, density, group, userDefined, documentMaterial);
}
Surface(String name, double density, MaterialGroup group, boolean userDefined) {
super(name, density, group, userDefined);
@ -86,6 +93,10 @@ public abstract class Material implements Comparable<Material> {
}
public static class Bulk extends Material {
Bulk(String name, double density, MaterialGroup group, boolean userDefined, boolean documentMaterial) {
super(name, density, group, userDefined, documentMaterial);
}
Bulk(String name, double density, MaterialGroup group, boolean userDefined) {
super(name, density, group, userDefined);
}
@ -102,6 +113,10 @@ public abstract class Material implements Comparable<Material> {
public static class Custom extends Material {
Custom(String name, double density, MaterialGroup group, boolean userDefined, boolean documentMaterial) {
super(name, density, group, userDefined, documentMaterial);
}
Custom(String name, double density, MaterialGroup group, boolean userDefined) {
super(name, density, group, userDefined);
}
@ -121,6 +136,7 @@ public abstract class Material implements Comparable<Material> {
private final String name;
private final double density;
private final boolean userDefined;
private boolean documentMaterial;
private final MaterialGroup group;
@ -131,12 +147,18 @@ public abstract class Material implements Comparable<Material> {
* @param density: the density of the material.
* @param group the material group.
* @param userDefined true if this is a user defined material, false if it is a system material.
* @param documentMaterial true if this material is stored in the document preferences.
*/
private Material(String name, double density, MaterialGroup group, boolean userDefined) {
private Material(String name, double density, MaterialGroup group, boolean userDefined, boolean documentMaterial) {
this.name = name;
this.density = density;
this.group = group;
this.userDefined = userDefined;
this.documentMaterial = documentMaterial;
}
private Material(String name, double density, MaterialGroup group, boolean userDefined) {
this(name, density, group, userDefined, false);
}
private Material(String name, double density, boolean userDefined) {
@ -158,13 +180,36 @@ public abstract class Material implements Comparable<Material> {
public boolean isUserDefined() {
return userDefined;
}
public boolean isDocumentMaterial() {
return documentMaterial;
}
public void setDocumentMaterial(boolean documentMaterial) {
this.documentMaterial = documentMaterial;
}
public abstract Type getType();
public MaterialGroup getGroup() {
return group;
}
/**
* Some materials have a null group. This method returns the equivalent group, i.e. CUSTOM for user-defined materials,
* and OTHER for materials with a null group.
* @return the equivalent group
*/
public MaterialGroup getEquivalentGroup() {
if (group != null) {
return group;
}
if (userDefined) {
return MaterialGroup.CUSTOM;
}
return MaterialGroup.OTHER;
}
public int getGroupPriority() {
if (group == null) {
return Integer.MAX_VALUE;
@ -231,18 +276,23 @@ public abstract class Material implements Comparable<Material> {
* @param density the material density
* @param group the material group
* @param userDefined whether the material is user-defined or not
* @param documentMaterial whether the material is stored in the document preferences
* @return the new material
*/
public static Material newMaterial(Type type, String name, double density, MaterialGroup group, boolean userDefined) {
public static Material newMaterial(Type type, String name, double density, MaterialGroup group, boolean userDefined,
boolean documentMaterial) {
return switch (type) {
case LINE -> new Line(name, density, group, userDefined);
case SURFACE -> new Surface(name, density, group, userDefined);
case BULK -> new Bulk(name, density, group, userDefined);
case CUSTOM -> new Custom(name, density, group, userDefined);
default -> throw new IllegalArgumentException("Unknown material type: " + type);
case LINE -> new Line(name, density, group, userDefined, documentMaterial);
case SURFACE -> new Surface(name, density, group, userDefined, documentMaterial);
case BULK -> new Bulk(name, density, group, userDefined, documentMaterial);
case CUSTOM -> new Custom(name, density, group, userDefined, documentMaterial);
};
}
public static Material newMaterial(Type type, String name, double density, MaterialGroup group, boolean userDefined) {
return newMaterial(type, name, density, group, userDefined, false);
}
public static Material newMaterial(Type type, String name, double density, boolean userDefined) {
return newMaterial(type, name, density, null, userDefined);
}

View File

@ -1,5 +1,7 @@
package info.openrocket.core.preferences;
import info.openrocket.core.database.Database;
import info.openrocket.core.material.Material;
import info.openrocket.core.util.ChangeSource;
import info.openrocket.core.util.StateChangeListener;
import java.util.HashMap;
@ -15,6 +17,20 @@ public class DocumentPreferences implements ChangeSource, ORPreferences {
// Map that stores all the document preferences
private final Map<String, DocumentPreference> preferencesMap = new HashMap<>();
/**
* A database of bulk materials (with bulk densities).
*/
private final Database<Material> BULK_MATERIAL = new Database<>();
/**
* A database of surface materials (with surface densities).
*/
private final Database<Material> SURFACE_MATERIAL = new Database<>();
/**
* A database of linear material (with length densities).
*/
private final Database<Material> LINE_MATERIAL = new Database<>();
@Override
public void addChangeListener(StateChangeListener listener) {
@ -77,6 +93,53 @@ public class DocumentPreferences implements ChangeSource, ORPreferences {
return preferencesMap;
}
public Database<Material> getBulkMaterials() {
return BULK_MATERIAL;
}
public Database<Material> getSurfaceMaterials() {
return SURFACE_MATERIAL;
}
public Database<Material> getLineMaterials() {
return LINE_MATERIAL;
}
/**
* gets the specific database with the given type
* @param type the desired type
* @return the database of the type given
*/
public Database<Material> getDatabase(Material.Type type){
return switch (type) {
case BULK -> BULK_MATERIAL;
case SURFACE -> SURFACE_MATERIAL;
case LINE -> LINE_MATERIAL;
default -> throw new IllegalArgumentException("Illegal material type: " + type);
};
}
/**
* Returns a database with all materials.
* !!! Removing or adding materials to the returned database will not affect the original databases. !!!
* @return A database with all materials
*/
public Database<Material> getAllMaterials() {
Database<Material> allMaterials = new Database<>();
allMaterials.addAll(BULK_MATERIAL);
allMaterials.addAll(SURFACE_MATERIAL);
allMaterials.addAll(LINE_MATERIAL);
return allMaterials;
}
public int getMaterialCount(Material.Type type) {
return getDatabase(type).size();
}
public int getTotalMaterialCount() {
return getMaterialCount(Material.Type.BULK) + getMaterialCount(Material.Type.SURFACE) + getMaterialCount(Material.Type.LINE);
}
public static class DocumentPreference {
private final Object value;
private final Class<?> type;

View File

@ -264,6 +264,10 @@ matedtpan.but.revertall = Revert all
matedtpan.col.Material = Material
matedtpan.col.Type = Type
matedtpan.col.Density = Density
matedtpan.col.Group = Group
matedtpan.col.Scope = Scope
matedtpan.col.Scope.Application = Application
matedtpan.col.Scope.Document = Document
matedtpan.col.but.ttip.New = Add a new material
matedtpan.title.Addcustmaterial = Add a custom material
matedtpan.but.ttip.edit = Edit an existing material
@ -935,7 +939,7 @@ custmatdlg.title.Custommaterial = Custom material
custmatdlg.lbl.Materialname = Material name:
custmatdlg.lbl.Materialtype = Material type:
custmatdlg.lbl.Materialdensity = Material density:
custmatdlg.checkbox.Addmaterial = Add material to database
custmatdlg.checkbox.Addmaterial = Add material to application database
! Ring Component Config
@ -1127,6 +1131,7 @@ MaterialPanel.lbl.ComponentFinish.ttip.longA2 = The value indicated is the avera
MaterialPanel.but.SetForAll = Set for all
MaterialPanel.but.SetForAll.ttip = Set this finish for all components of the rocket.
MaterialPanel.but.AddCustomMaterial = Add custom material
MaterialPanel.but.EditMaterials = Edit materials
MaterialPanel.MaterialComboBox.placeholder = Enter the material name
! PlacementPanel

View File

@ -10,6 +10,7 @@ import javax.swing.SwingUtilities;
import info.openrocket.core.database.Database;
import info.openrocket.core.database.DatabaseListener;
import info.openrocket.core.database.Databases;
import info.openrocket.core.document.OpenRocketDocument;
import info.openrocket.core.l10n.Translator;
import info.openrocket.core.material.Material;
import info.openrocket.core.rocketcomponent.ComponentChangeEvent;
@ -29,47 +30,36 @@ public class MaterialModel extends AbstractListModel<Material> implements
private final Component parentUIComponent;
private final RocketComponent rocketComponent;
private final OpenRocketDocument document;
private final Material.Type type;
private final Database<Material> database;
private final Database<Material> applicationDatabase;
private final Database<Material> documentDatabase;
private final Reflection.Method getMethod;
private final Reflection.Method setMethod;
private static final Translator trans = Application.getTranslator();
public MaterialModel(Component parent, RocketComponent component, Material.Type type) {
public MaterialModel(Component parent, OpenRocketDocument document, RocketComponent component, Material.Type type) {
//// Material
//this(parent, component, type, trans.get("MaterialModel.title.Material"));
this(parent, component, type, "Material");
this(parent, document, component, type, "Material");
}
public MaterialModel(Component parent, RocketComponent component, Material.Type type,
public MaterialModel(Component parent, OpenRocketDocument document, RocketComponent component, Material.Type type,
String name) {
this.modelInvalidator = new ModelInvalidator(component, this);
this.parentUIComponent = parent;
this.document = document;
this.rocketComponent = component;
this.type = type;
switch (type) {
case LINE:
this.database = Databases.LINE_MATERIAL;
break;
case BULK:
this.database = Databases.BULK_MATERIAL;
break;
case SURFACE:
this.database = Databases.SURFACE_MATERIAL;
break;
default:
throw new IllegalArgumentException("Unknown material type:"+type);
}
this.applicationDatabase = Databases.getDatabase(type);
this.documentDatabase = document.getDocumentPreferences().getDatabase(type);
try {
getMethod = new Reflection.Method(component.getClass().getMethod("get"+name));
setMethod = new Reflection.Method(component.getClass().getMethod("set"+name,
getMethod = new Reflection.Method(component.getClass().getMethod("get" + name));
setMethod = new Reflection.Method(component.getClass().getMethod("set" + name,
Material.class));
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("get/is methods for material " +
@ -77,7 +67,8 @@ public class MaterialModel extends AbstractListModel<Material> implements
}
component.addComponentChangeListener(this);
database.addDatabaseListener(this);
applicationDatabase.addDatabaseListener(this);
documentDatabase.addDatabaseListener(this);
}
@Override
@ -103,7 +94,7 @@ public class MaterialModel extends AbstractListModel<Material> implements
public void addCustomMaterial() {
CustomMaterialDialog dialog = new CustomMaterialDialog(
SwingUtilities.getWindowAncestor(parentUIComponent),
(Material) getSelectedItem(), true,
(Material) getSelectedItem(), true, false,
trans.get("MaterialModel.title.Defcustmat"));
dialog.setVisible(true);
@ -112,33 +103,40 @@ public class MaterialModel extends AbstractListModel<Material> implements
return;
Material material = dialog.getMaterial();
setMethod.invoke(rocketComponent, material);
this.setMethod.invoke(this.rocketComponent, material);
// TODO: add to permanent database if addSelected, add to document database otherwise
if (dialog.isAddSelected()) {
database.add(material);
this.applicationDatabase.add(material);
} else {
material.setDocumentMaterial(true);
this.documentDatabase.add(material);
}
}
@Override
public Material getElementAt(int index) {
if (index >= database.size()) {
return null;
if (index < applicationDatabase.size()) {
return applicationDatabase.get(index);
} else if (index < applicationDatabase.size() + documentDatabase.size() - 1) {
return documentDatabase.get(index - applicationDatabase.size());
}
return database.get(index);
return null;
}
public Material[] getAllMaterials() {
Material[] materials = new Material[database.size()];
for (int i = 0; i < database.size(); i++) {
materials[i] = database.get(i);
Material[] materials = new Material[applicationDatabase.size()+documentDatabase.size()];
for (int i = 0; i < applicationDatabase.size(); i++) {
materials[i] = applicationDatabase.get(i);
}
for (int i = 0; i < documentDatabase.size(); i++) {
materials[i+applicationDatabase.size()] = documentDatabase.get(i);
}
return materials;
}
@Override
public int getSize() {
return database.size();
return applicationDatabase.size() + documentDatabase.size();
}
public Material.Type getType() {
@ -156,12 +154,12 @@ public class MaterialModel extends AbstractListModel<Material> implements
@Override
public void elementAdded(Material element, Database<Material> source) {
this.fireContentsChanged(this, 0, database.size());
this.fireContentsChanged(this, 0, applicationDatabase.size() + documentDatabase.size());
}
@Override
public void elementRemoved(Material element, Database<Material> source) {
this.fireContentsChanged(this, 0, database.size());
this.fireContentsChanged(this, 0, applicationDatabase.size() + documentDatabase.size());
}
@Override

View File

@ -627,7 +627,7 @@ public abstract class FinSetConfig extends RocketComponentConfig {
label.setToolTipText(trans.get("MaterialPanel.lbl.ttip.ComponentMaterialAffects"));
filletPanel.add(label, "spanx 4, wrap rel");
MaterialModel mm = new MaterialModel(filletPanel, component, Material.Type.BULK, "FilletMaterial");
MaterialModel mm = new MaterialModel(filletPanel, document, component, Material.Type.BULK, "FilletMaterial");
register(mm);
JComboBox<Material> materialCombo = new JComboBox<>(mm);

View File

@ -2,6 +2,8 @@ package info.openrocket.swing.gui.configdialog;
import info.openrocket.core.material.MaterialGroup;
import info.openrocket.core.util.Invalidatable;
import info.openrocket.swing.gui.dialogs.preferences.PreferencesDialog;
import info.openrocket.swing.gui.main.BasicFrame;
import info.openrocket.swing.gui.widgets.SearchableAndCategorizableComboBox;
import net.miginfocom.swing.MigLayout;
@ -43,7 +45,7 @@ public class MaterialPanel extends JPanel implements Invalidatable, Invalidating
public MaterialPanel(RocketComponent component, OpenRocketDocument document,
Material.Type type, String materialString, String finishString,
String partName, List<Component> order) {
String partName, List<Component> order) {
super(new MigLayout());
this.setBorder(BorderFactory.createTitledBorder(trans.get("MaterialPanel.title.Material")));
@ -52,7 +54,7 @@ public class MaterialPanel extends JPanel implements Invalidatable, Invalidating
label.setToolTipText(trans.get("MaterialPanel.lbl.ttip.ComponentMaterialAffects"));
this.add(label, "spanx 4, wrap rel");
MaterialModel mm = new MaterialModel(this, component, type, partName);
MaterialModel mm = new MaterialModel(this, document, component, type, partName);
register(mm);
// Set custom material button
@ -70,8 +72,25 @@ public class MaterialPanel extends JPanel implements Invalidatable, Invalidating
});
});
// Edit materials button
JButton editMaterialsButton = new JButton(trans.get("MaterialPanel.but.EditMaterials"));
editMaterialsButton.addActionListener(e -> {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (BasicFrame frame : BasicFrame.getAllFrames()) {
if (frame.getRocketPanel().getDocument() == document) {
PreferencesDialog.showPreferences(frame, 5);
return;
}
}
}
});
});
// Material selection combo box
this.materialCombo = MaterialComboBox.createComboBox(MaterialGroup.ALL_GROUPS, mm.getAllMaterials(), customMaterialButton);
this.materialCombo = MaterialComboBox.createComboBox(MaterialGroup.ALL_GROUPS, mm.getAllMaterials(),
customMaterialButton, editMaterialsButton);
this.materialCombo.setSelectedItem(mm.getSelectedItem());
this.materialCombo.setToolTipText(trans.get("MaterialPanel.combo.ttip.ComponentMaterialAffects"));
this.add(this.materialCombo, "spanx 4, growx, wrap paragraph");
@ -184,14 +203,7 @@ public class MaterialPanel extends JPanel implements Invalidatable, Invalidating
for (MaterialGroup group : sortedGroups) {
List<Material> itemsForGroup = new ArrayList<>();
for (Material material : materials) {
materialGroup = material.getGroup();
if (materialGroup == null) {
if (material.isUserDefined()) {
materialGroup = MaterialGroup.CUSTOM;
} else {
materialGroup = MaterialGroup.OTHER;
}
}
materialGroup = material.getEquivalentGroup();
if (materialGroup.equals(group)) {
itemsForGroup.add(material);
}

View File

@ -87,7 +87,7 @@ public class ParachuteConfig extends RecoveryDeviceConfig {
//// Material:
canopyPanel.add(new JLabel(trans.get("ParachuteCfg.lbl.Material")), "wrap rel");
MaterialModel mm = new MaterialModel(canopyPanel, component, Material.Type.SURFACE);
MaterialModel mm = new MaterialModel(canopyPanel, document, component, Material.Type.SURFACE);
register(mm);
JComboBox<Material> surfaceMaterialCombo = new JComboBox<>(mm);
surfaceMaterialCombo.setToolTipText(trans.get("ParachuteCfg.combo.MaterialModel"));
@ -158,7 +158,7 @@ public class ParachuteConfig extends RecoveryDeviceConfig {
//// Material:
shroudPanel.add(new JLabel(trans.get("ParachuteCfg.lbl.Material")), "spanx, wrap rel");
mm = new MaterialModel(shroudPanel, component, Material.Type.LINE, "LineMaterial");
mm = new MaterialModel(shroudPanel, document, component, Material.Type.LINE, "LineMaterial");
register(mm);
JComboBox<Material> shroudMaterialCombo = new JComboBox<>(mm);
shroudPanel.add(shroudMaterialCombo, "spanx, growx");

View File

@ -109,7 +109,7 @@ public class StreamerConfig extends RecoveryDeviceConfig {
//// Material:
panel.add(new JLabel(trans.get("StreamerCfg.lbl.Material")));
MaterialModel mm = new MaterialModel(panel, component, Material.Type.SURFACE);
MaterialModel mm = new MaterialModel(panel, document, component, Material.Type.SURFACE);
register(mm);
JComboBox<Material> streamerMaterialCombo = new JComboBox<>(mm);
//// The component material affects the weight of the component.

View File

@ -44,23 +44,27 @@ public class CustomMaterialDialog extends JDialog {
private JSpinner densitySpinner;
private UnitSelector densityUnit;
private JCheckBox addBox;
public CustomMaterialDialog(Window parent, Material material, boolean saveOption, boolean addToApplicationDatabase,
String title) {
this(parent, material, saveOption, addToApplicationDatabase, title, null);
}
public CustomMaterialDialog(Window parent, Material material, boolean saveOption,
String title) {
this(parent, material, saveOption, title, null);
this(parent, material, saveOption, material != null && !material.isDocumentMaterial(), title);
}
public CustomMaterialDialog(Window parent, Material material, boolean saveOption,
String title, String note) {
public CustomMaterialDialog(Window parent, Material material, boolean saveOption, boolean addToApplicationDatabase,
String title, String note) {
//// Custom material
super(parent, trans.get("custmatdlg.title.Custommaterial"), Dialog.ModalityType.APPLICATION_MODAL);
this.originalMaterial = material;
JPanel panel = new JPanel(new MigLayout("fill, gap rel unrel"));
// Add title and note
if (title != null) {
panel.add(new JLabel("<html><b>" + title + ":"),
@ -69,8 +73,8 @@ public class CustomMaterialDialog extends JDialog {
if (note != null) {
panel.add(new StyledLabel(note, -1), "span, wrap para");
}
//// Material name
panel.add(new JLabel(trans.get("custmatdlg.lbl.Materialname")));
nameField = new JTextField(15);
@ -78,8 +82,8 @@ public class CustomMaterialDialog extends JDialog {
nameField.setText(material.getName());
}
panel.add(nameField, "span, growx, wrap");
// Material type (if not known)
panel.add(new JLabel(trans.get("custmatdlg.lbl.Materialtype")));
if (material == null) {
@ -102,8 +106,8 @@ public class CustomMaterialDialog extends JDialog {
} else {
panel.add(new JLabel(material.getType().toString()), "span, growx, wrap");
}
// Material density:
panel.add(new JLabel(trans.get("custmatdlg.lbl.Materialdensity")));
densitySpinner = new JSpinner();
@ -112,18 +116,19 @@ public class CustomMaterialDialog extends JDialog {
panel.add(densityUnit, "w 30lp");
panel.add(new JPanel(), "growx, wrap");
updateDensityModel();
// Save option
if (saveOption) {
//// Add material to database
//// Add material to application database
addBox = new JCheckBox(trans.get("custmatdlg.checkbox.Addmaterial"));
addBox.setSelected(addToApplicationDatabase);
panel.add(addBox, "span, wrap");
}
//// OK button
JButton okButton = new SelectColorButton(trans.get("dlg.but.ok"));
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@ -132,7 +137,7 @@ public class CustomMaterialDialog extends JDialog {
}
});
panel.add(okButton, "span, split, tag ok");
//// Cancel
JButton closeButton = new SelectColorButton(trans.get("dlg.but.cancel"));
closeButton.addActionListener(new ActionListener() {
@ -143,13 +148,18 @@ public class CustomMaterialDialog extends JDialog {
}
});
panel.add(closeButton, "tag cancel");
this.setContentPane(panel);
this.pack();
this.setLocationByPlatform(true);
GUIUtil.setDisposableDialogOptions(this, okButton);
}
public CustomMaterialDialog(Window parent, Material material, boolean saveOption,
String title, String note) {
this(parent, material, saveOption, material != null && !material.isDocumentMaterial(), title, note);
}
public boolean getOkClicked() {
return okClicked;

View File

@ -19,9 +19,9 @@ import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import info.openrocket.core.document.OpenRocketDocument;
import net.miginfocom.swing.MigLayout;
import info.openrocket.core.database.Database;
import info.openrocket.core.database.Databases;
import info.openrocket.core.l10n.Translator;
import info.openrocket.core.material.Material;
@ -47,10 +47,13 @@ public class MaterialEditPanel extends JPanel {
private final JButton deleteButton;
private final JButton revertButton;
private static final Translator trans = Application.getTranslator();
private final OpenRocketDocument document;
public MaterialEditPanel() {
public MaterialEditPanel(OpenRocketDocument document) {
super(new MigLayout("fill"));
this.document = document;
// TODO: LOW: Create sorter that keeps material types always in order
@ -80,19 +83,12 @@ public class MaterialEditPanel extends JPanel {
public Object getValueAt(int row) {
Material m = getMaterial(row);
double d = m.getDensity();
switch (m.getType()) {
case LINE:
return UnitGroup.UNITS_DENSITY_LINE.toValue(d);
case SURFACE:
return UnitGroup.UNITS_DENSITY_SURFACE.toValue(d);
case BULK:
return UnitGroup.UNITS_DENSITY_BULK.toValue(d);
default:
throw new IllegalStateException("Material type " + m.getType());
}
return switch (m.getType()) {
case LINE -> UnitGroup.UNITS_DENSITY_LINE.toValue(d);
case SURFACE -> UnitGroup.UNITS_DENSITY_SURFACE.toValue(d);
case BULK -> UnitGroup.UNITS_DENSITY_BULK.toValue(d);
default -> throw new IllegalStateException("Material type " + m.getType());
};
}
@Override
@ -104,12 +100,37 @@ public class MaterialEditPanel extends JPanel {
public Class<?> getColumnClass() {
return Value.class;
}
},
//// Group
new Column(trans.get("matedtpan.col.Group")) {
@Override
public Object getValueAt(int row) {
return getMaterial(row).getEquivalentGroup().getName();
}
@Override
public int getDefaultWidth() {
return 20;
}
},
//// Scope
new Column(trans.get("matedtpan.col.Scope")) {
@Override
public Object getValueAt(int row) {
boolean documentMaterial = getMaterial(row).isDocumentMaterial();
return documentMaterial ? trans.get("matedtpan.col.Scope.Document") : trans.get("matedtpan.col.Scope.Application");
}
@Override
public int getDefaultWidth() {
return 15;
}
}
) {
@Override
public int getRowCount() {
return Databases.BULK_MATERIAL.size() + Databases.SURFACE_MATERIAL.size() +
Databases.LINE_MATERIAL.size();
Databases.LINE_MATERIAL.size() + document.getDocumentPreferences().getTotalMaterialCount();
}
};
@ -117,7 +138,7 @@ public class MaterialEditPanel extends JPanel {
model.setColumnWidths(table.getColumnModel());
table.setAutoCreateRowSorter(true);
table.setDefaultRenderer(Object.class, new MaterialCellRenderer());
this.add(new JScrollPane(table), "w 200px, h 100px, grow 100");
this.add(new JScrollPane(table), "spanx, grow 100, wrap");
//// New button
@ -130,17 +151,23 @@ public class MaterialEditPanel extends JPanel {
CustomMaterialDialog dialog = new CustomMaterialDialog(
SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
//// Add a custom material
null, false, trans.get("matedtpan.title.Addcustmaterial"));
null, true, true, trans.get("matedtpan.title.Addcustmaterial"));
dialog.setVisible(true);
if (dialog.getOkClicked()) {
Material mat = dialog.getMaterial();
getDatabase(mat).add(mat);
model.fireTableDataChanged();
setButtonStates();
if (!dialog.getOkClicked()) {
return;
}
Material mat = dialog.getMaterial();
if (dialog.isAddSelected()) {
Databases.getDatabase(mat.getType()).add(mat);
} else {
mat.setDocumentMaterial(true);
document.getDocumentPreferences().getDatabase(mat.getType()).add(mat);
}
model.fireTableDataChanged();
setButtonStates();
}
});
this.add(addButton, "gap rel rel para para, w 70lp, split 5, flowy, growx 1, top");
this.add(addButton, "gap rel rel para para, split 3, growx 1");
//// Edit button
editButton = new SelectColorButton(trans.get("matedtpan.but.edit"));
@ -154,36 +181,47 @@ public class MaterialEditPanel extends JPanel {
return;
sel = table.convertRowIndexToModel(sel);
Material m = getMaterial(sel);
boolean isDocumentMaterialPrior = m.isDocumentMaterial();
CustomMaterialDialog dialog;
if (m.isUserDefined()) {
dialog = new CustomMaterialDialog(
SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
//// Edit material
m, false, trans.get("matedtpan.title.Editmaterial"));
m, true, trans.get("matedtpan.title.Editmaterial"));
} else {
dialog = new CustomMaterialDialog(
SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
//// Add a custom material
m, false, trans.get("matedtpan.title.Addcustmaterial"),
m, true, trans.get("matedtpan.title.Addcustmaterial"),
//// The built-in materials cannot be modified.
trans.get("matedtpan.title2.Editmaterial"));
}
dialog.setVisible(true);
if (dialog.getOkClicked()) {
if (m.isUserDefined()) {
getDatabase(m).remove(m);
}
Material mat = dialog.getMaterial();
getDatabase(mat).add(mat);
model.fireTableDataChanged();
setButtonStates();
if (!dialog.getOkClicked()) {
return;
}
if (m.isUserDefined()) {
if (isDocumentMaterialPrior) {
document.getDocumentPreferences().getDatabase(m.getType()).remove(m);
} else {
Databases.getDatabase(m.getType()).remove(m);
}
}
Material mat = dialog.getMaterial();
if (dialog.isAddSelected()) {
Databases.getDatabase(mat.getType()).add(mat);
} else {
mat.setDocumentMaterial(true);
document.getDocumentPreferences().getDatabase(mat.getType()).add(mat);
}
model.fireTableDataChanged();
setButtonStates();
}
});
this.add(editButton, "gap rel rel para para, growx 1, top");
this.add(editButton, "gap rel rel para para, growx 1");
//// Delete button
deleteButton = new SelectColorButton(trans.get("matedtpan.but.delete"));
@ -199,15 +237,16 @@ public class MaterialEditPanel extends JPanel {
Material m = getMaterial(sel);
if (!m.isUserDefined())
return;
getDatabase(m).remove(m);
if (m.isDocumentMaterial()) {
document.getDocumentPreferences().getDatabase(m.getType()).remove(m);
} else {
Databases.getDatabase(m.getType()).remove(m);
}
model.fireTableDataChanged();
setButtonStates();
}
});
this.add(deleteButton, "gap rel rel para para, growx 1, top");
this.add(new JPanel(), "grow 1");
this.add(deleteButton, "gap rel rel para para, growx 1, wrap unrel");
//// Revert all button
revertButton = new SelectColorButton(trans.get("matedtpan.but.revertall"));
@ -242,12 +281,31 @@ public class MaterialEditPanel extends JPanel {
if (iterator.next().isUserDefined())
iterator.remove();
}
iterator = document.getDocumentPreferences().getBulkMaterials().iterator();
while (iterator.hasNext()) {
if (iterator.next().isUserDefined()) // Not really necessary, but who knows what we end up doing in the future. Better safe than sorry.
iterator.remove();
}
iterator = document.getDocumentPreferences().getSurfaceMaterials().iterator();
while (iterator.hasNext()) {
if (iterator.next().isUserDefined()) // Not really necessary, but who knows what we end up doing in the future. Better safe than sorry.
iterator.remove();
}
iterator = document.getDocumentPreferences().getLineMaterials().iterator();
while (iterator.hasNext()) {
if (iterator.next().isUserDefined()) // Not really necessary, but who knows what we end up doing in the future. Better safe than sorry.
iterator.remove();
}
model.fireTableDataChanged();
setButtonStates();
}
}
});
this.add(revertButton, "gap rel rel para para, growx 1, bottom, wrap unrel");
this.add(revertButton, "gap rel rel para para, w 80lp, right, wrap unrel");
setButtonStates();
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@ -273,23 +331,6 @@ public class MaterialEditPanel extends JPanel {
}
private Database<Material> getDatabase(Material m) {
switch (m.getType()) {
case BULK:
return Databases.BULK_MATERIAL;
case SURFACE:
return Databases.SURFACE_MATERIAL;
case LINE:
return Databases.LINE_MATERIAL;
default:
throw new IllegalArgumentException("Material type invalid, m=" + m);
}
}
private void setButtonStates() {
int sel = table.getSelectedRow();
@ -332,6 +373,14 @@ public class MaterialEditPanel extends JPanel {
}
}
}
if (!found) {
for (Material m : document.getDocumentPreferences().getAllMaterials()) {
if (m.isUserDefined()) {
found = true;
break;
}
}
}
revertButton.setEnabled(found);
}
@ -345,21 +394,43 @@ public class MaterialEditPanel extends JPanel {
return Databases.BULK_MATERIAL.get(row);
}
row -= n;
n = document.getDocumentPreferences().getBulkMaterials().size();
if (row < n) {
return document.getDocumentPreferences().getBulkMaterials().get(row);
}
row -= n;
n = Databases.SURFACE_MATERIAL.size();
if (row < n) {
return Databases.SURFACE_MATERIAL.get(row);
}
row -= n;
n = document.getDocumentPreferences().getSurfaceMaterials().size();
if (row < n) {
return document.getDocumentPreferences().getSurfaceMaterials().get(row);
}
row -= n;
n = Databases.LINE_MATERIAL.size();
if (row < n) {
return Databases.LINE_MATERIAL.get(row);
}
row -= n;
n = document.getDocumentPreferences().getLineMaterials().size();
if (row < n) {
return document.getDocumentPreferences().getLineMaterials().get(row);
}
throw new IndexOutOfBoundsException("row=" + origRow + " while material count" +
" bulk:" + Databases.BULK_MATERIAL.size() +
" bulk document:" + document.getDocumentPreferences().getBulkMaterials().size() +
" surface:" + Databases.SURFACE_MATERIAL.size() +
" line:" + Databases.LINE_MATERIAL.size());
" surface document:" + document.getDocumentPreferences().getSurfaceMaterials().size() +
" line:" + Databases.LINE_MATERIAL.size() +
" line document:" + document.getDocumentPreferences().getLineMaterials().size());
}

View File

@ -48,7 +48,7 @@ public class PreferencesDialog extends JDialog {
private boolean storePreferences = true;
private File initPrefsFile = null;
private PreferencesDialog(BasicFrame parent) {
private PreferencesDialog(BasicFrame parent, int selectedTab) {
// // Preferences
super(parent, trans.get("pref.dlg.title.Preferences"),
Dialog.ModalityType.APPLICATION_MODAL);
@ -84,7 +84,7 @@ public class PreferencesDialog extends JDialog {
trans.get("pref.dlg.tab.Defaultunits"));
// Materials and Custom materials
tabbedPane.addTab(trans.get("pref.dlg.tab.Materials"), null,
new MaterialEditPanel(),
new MaterialEditPanel(parent.getRocketPanel().getDocument()),
trans.get("pref.dlg.tab.Custommaterials"));
// Decal Editor selection
tabbedPane.addTab(trans.get("pref.dlg.tab.Graphics"),
@ -94,6 +94,8 @@ public class PreferencesDialog extends JDialog {
// tabbedPane.addTab(trans.get("pref.dlg.tab.Colors"),
// new DisplayPreferencesPanel());
tabbedPane.setSelectedIndex(selectedTab);
//// Cancel button
JButton cancelButton = new SelectColorButton(trans.get("dlg.but.cancel"));
@ -168,6 +170,10 @@ public class PreferencesDialog extends JDialog {
GUIUtil.setDisposableDialogOptions(this, okButton);
}
private PreferencesDialog(BasicFrame parent) {
this(parent, 0);
}
public BasicFrame getParentFrame() {
return parentFrame;
}
@ -235,12 +241,17 @@ public class PreferencesDialog extends JDialog {
private static PreferencesDialog dialog = null;
public static void showPreferences(BasicFrame parent) {
public static void showPreferences(BasicFrame parent, int selectedTab) {
if (dialog != null) {
dialog.dispose();
}
dialog = new PreferencesDialog(parent);
dialog = new PreferencesDialog(parent, selectedTab);
dialog.setVisible(true);
}
public static void showPreferences(BasicFrame parent) {
showPreferences(parent, 0);
}
}