Use searchable and categorizable combobox for material panel
This commit is contained in:
parent
3f8a118298
commit
4411cb1b35
@ -1,5 +1,6 @@
|
||||
package info.openrocket.core.database;
|
||||
|
||||
import info.openrocket.core.material.MaterialGroup;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -40,89 +41,89 @@ public class Databases {
|
||||
static {
|
||||
|
||||
// Add default materials
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Acrylic", 1190));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Aluminum", 2700));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Balsa", 170));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Basswood", 500));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Birch", 670));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Brass", 8600));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Cardboard", 680));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Carbon fiber", 1780));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Cork", 240));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Delrin", 1420));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Depron (XPS)", 40));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Fiberglass", 1850));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Kraft phenolic", 950));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Maple", 755));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Nylon", 1150));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Paper (office)", 820));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Pine", 530));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Plywood (birch)", 630));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Polycarbonate (Lexan)", 1200));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Polystyrene", 1050));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "PVC", 1390));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Spruce", 450));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Steel", 7850));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Styrofoam (generic EPS)", 20));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Styrofoam \"Blue foam\" (XPS)", 32));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Titanium", 4500));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Quantum tubing", 1050));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Blue tube", 1300));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "PLA - 100% infill", 1250));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "PETG - 100% infill", 1250));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "ABS - 100% infill", 1050));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Acrylic", 1190, MaterialGroup.PLASTICS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Aluminum", 2700, MaterialGroup.METALS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Balsa", 170, MaterialGroup.WOODS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Basswood", 500, MaterialGroup.WOODS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Birch", 670, MaterialGroup.WOODS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Brass", 8600, MaterialGroup.METALS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Cardboard", 680, MaterialGroup.PAPER));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Carbon fiber", 1780, MaterialGroup.COMPOSITES));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Cork", 240, MaterialGroup.WOODS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Delrin", 1420, MaterialGroup.PLASTICS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Depron (XPS)", 40, MaterialGroup.FOAMS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Fiberglass", 1850, MaterialGroup.COMPOSITES));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Kraft phenolic", 950, MaterialGroup.COMPOSITES));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Maple", 755, MaterialGroup.WOODS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Nylon", 1150, MaterialGroup.FIBERS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Paper (office)", 820, MaterialGroup.PAPER));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Pine", 530, MaterialGroup.WOODS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Plywood (birch)", 630, MaterialGroup.WOODS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Polycarbonate (Lexan)", 1200, MaterialGroup.PLASTICS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Polystyrene", 1050, MaterialGroup.FOAMS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "PVC", 1390, MaterialGroup.PLASTICS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Spruce", 450, MaterialGroup.WOODS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Steel", 7850, MaterialGroup.METALS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Styrofoam (generic EPS)", 20, MaterialGroup.FOAMS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Styrofoam \"Blue foam\" (XPS)", 32, MaterialGroup.FOAMS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Titanium", 4500, MaterialGroup.METALS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Quantum tubing", 1050, MaterialGroup.PLASTICS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "Blue tube", 1300, MaterialGroup.COMPOSITES));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "PLA - 100% infill", 1250, MaterialGroup.PLASTICS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "PETG - 100% infill", 1250, MaterialGroup.PLASTICS));
|
||||
BULK_MATERIAL.add(newMaterial(Material.Type.BULK, "ABS - 100% infill", 1050, MaterialGroup.PLASTICS));
|
||||
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Ripstop nylon", 0.067));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Mylar", 0.021));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Polyethylene (thin)", 0.015));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Polyethylene (heavy)", 0.040));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Silk", 0.060));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Paper (office)", 0.080));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Cellophane", 0.018));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Cr\u00eape paper", 0.025));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Ripstop nylon", 0.067, MaterialGroup.FABRICS));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Mylar", 0.021, MaterialGroup.PLASTICS));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Polyethylene (thin)", 0.015, MaterialGroup.PLASTICS));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Polyethylene (heavy)", 0.040, MaterialGroup.PLASTICS));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Silk", 0.060, MaterialGroup.FABRICS));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Paper (office)", 0.080, MaterialGroup.PAPER));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Cellophane", 0.018, MaterialGroup.PLASTICS));
|
||||
SURFACE_MATERIAL.add(newMaterial(Material.Type.SURFACE, "Cr\u00eape paper", 0.025, MaterialGroup.PAPER));
|
||||
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Thread (heavy-duty)", 0.0003));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (round 2 mm, 1/16 in)", 0.0018));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (flat 6 mm, 1/4 in)", 0.0043));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (flat 12 mm, 1/2 in)", 0.008));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (flat 19 mm, 3/4 in)", 0.0012));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (flat 25 mm, 1 in)", 0.0016));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Braided nylon (2 mm, 1/16 in)", 0.001));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Braided nylon (3 mm, 1/8 in)", 0.0035));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Tubular nylon (11 mm, 7/16 in)", 0.013));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Tubular nylon (14 mm, 9/16 in)", 0.016));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Tubular nylon (25 mm, 1 in)", 0.029));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 138 (0.4 mm, 1/64 in)", 0.00014808));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 207 (0.5 mm, 1/64 in)", 0.00023622));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 346 (0.7 mm, 1/32 in)", 0.00047243));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 415 (0.8 mm, 1/32 in)", 0.00055117));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 800 (1.1 mm, 3/64 in)", 0.00099211));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (3.2 mm, 1/8 in)", 0.00967306));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (4.8 mm, 3/16 in)", 0.01785797));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (6.4 mm, 1/4 in)", 0.02976328));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (7.9 mm, 5/16 in)", 0.04464491));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (10 mm, 3/8 in)", 0.05952655));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (11 mm, 7/16 in)", 0.07440819));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (13 mm, 1/2 in)", 0.11607678));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (14 mm, 9/16 in)", 0.20834293));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (16 mm, 5/8 in)", 0.28721562));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (19 mm, 3/4 in)", 0.3497185));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (25 mm, 1 in)", 0.45686629));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing md. (10 mm, 3/8 in)", 0.00951444));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing md. (13 mm, 1/2 in)", 0.01334208));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing md. (16 mm, 5/8 in)", 0.01618548));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing lg. (14 mm, 9/16 in)", 0.02723097));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing lg. (25 mm, 1 in)", 0.03969816));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Paraline small IIIA (6.4 mm, 1.4 in)", 0.00371829));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic rubber band (flat 3.2 mm, 1/8 in)", 0.00297638));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic rubber band (flat 6.4 mm, 1/4 in)", 0.00613107));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 3.2 mm, 1/8 in)", 0.00106));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 4 mm, 5/32 in)", 0.002));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 6.4 mm, 1/4 in)", 0.00254));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (round 2 mm, 1/16 in)", 0.0035));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (round 2.5 mm, 3/32 in)", 0.0038));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 10 mm, 3/8 in)", 0.00381));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 13 mm, 1/2 in)", 0.00551172));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Thread (heavy-duty)", 0.0003, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (round 2 mm, 1/16 in)", 0.0018, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (flat 6 mm, 1/4 in)", 0.0043, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (flat 12 mm, 1/2 in)", 0.008, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (flat 19 mm, 3/4 in)", 0.0012, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic cord (flat 25 mm, 1 in)", 0.0016, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Braided nylon (2 mm, 1/16 in)", 0.001, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Braided nylon (3 mm, 1/8 in)", 0.0035, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Tubular nylon (11 mm, 7/16 in)", 0.013, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Tubular nylon (14 mm, 9/16 in)", 0.016, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Tubular nylon (25 mm, 1 in)", 0.029, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 138 (0.4 mm, 1/64 in)", 0.00014808, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 207 (0.5 mm, 1/64 in)", 0.00023622, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 346 (0.7 mm, 1/32 in)", 0.00047243, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 415 (0.8 mm, 1/32 in)", 0.00055117, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar thread 800 (1.1 mm, 3/64 in)", 0.00099211, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (3.2 mm, 1/8 in)", 0.00967306, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (4.8 mm, 3/16 in)", 0.01785797, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (6.4 mm, 1/4 in)", 0.02976328, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (7.9 mm, 5/16 in)", 0.04464491, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (10 mm, 3/8 in)", 0.05952655, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (11 mm, 7/16 in)", 0.07440819, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (13 mm, 1/2 in)", 0.11607678, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (14 mm, 9/16 in)", 0.20834293, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (16 mm, 5/8 in)", 0.28721562, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (19 mm, 3/4 in)", 0.3497185, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Kevlar 12-strand (25 mm, 1 in)", 0.45686629, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing md. (10 mm, 3/8 in)", 0.00951444, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing md. (13 mm, 1/2 in)", 0.01334208, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing md. (16 mm, 5/8 in)", 0.01618548, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing lg. (14 mm, 9/16 in)", 0.02723097, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Nylon flat webbing lg. (25 mm, 1 in)", 0.03969816, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Paraline small IIIA (6.4 mm, 1.4 in)", 0.00371829, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic rubber band (flat 3.2 mm, 1/8 in)", 0.00297638, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic rubber band (flat 6.4 mm, 1/4 in)", 0.00613107, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 3.2 mm, 1/8 in)", 0.00106, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 4 mm, 5/32 in)", 0.002, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 6.4 mm, 1/4 in)", 0.00254, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (round 2 mm, 1/16 in)", 0.0035, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (round 2.5 mm, 3/32 in)", 0.0038, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 10 mm, 3/8 in)", 0.00381, MaterialGroup.THREADS_LINES));
|
||||
LINE_MATERIAL.add(newMaterial(Material.Type.LINE, "Elastic braided cord (flat 13 mm, 1/2 in)", 0.00551172, MaterialGroup.THREADS_LINES));
|
||||
|
||||
|
||||
// Add user-defined materials
|
||||
@ -159,9 +160,13 @@ public class Databases {
|
||||
* @param density density
|
||||
* @return a new object with the material data
|
||||
*/
|
||||
private static Material newMaterial(Type type, String baseName, double density) {
|
||||
private static Material newMaterial(Type type, String baseName, double density, MaterialGroup group) {
|
||||
String name = trans.get("material", baseName);
|
||||
return Material.newMaterial(type, name, density, false);
|
||||
return Material.newMaterial(type, name, density, group, false);
|
||||
}
|
||||
|
||||
private static Material newMaterial(Type type, String baseName, double density) {
|
||||
return newMaterial(type, baseName, density, null);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,6 +5,8 @@ import info.openrocket.core.startup.Application;
|
||||
import info.openrocket.core.unit.Unit;
|
||||
import info.openrocket.core.unit.UnitGroup;
|
||||
import info.openrocket.core.util.MathUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A class for different material types. Each material has a name and density.
|
||||
@ -17,8 +19,8 @@ import info.openrocket.core.util.MathUtil;
|
||||
*/
|
||||
|
||||
public abstract class Material implements Comparable<Material> {
|
||||
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
private static final Logger log = LoggerFactory.getLogger(Material.class);
|
||||
|
||||
public enum Type {
|
||||
BULK("Databases.materials.types.Bulk", UnitGroup.UNITS_DENSITY_BULK),
|
||||
@ -48,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) {
|
||||
super(name, density, group, userDefined);
|
||||
}
|
||||
|
||||
Line(String name, double density, boolean userDefined) {
|
||||
super(name, density, userDefined);
|
||||
}
|
||||
@ -59,7 +65,11 @@ public abstract class Material implements Comparable<Material> {
|
||||
}
|
||||
|
||||
public static class Surface extends Material {
|
||||
|
||||
|
||||
Surface(String name, double density, MaterialGroup group, boolean userDefined) {
|
||||
super(name, density, group, userDefined);
|
||||
}
|
||||
|
||||
Surface(String name, double density, boolean userDefined) {
|
||||
super(name, density, userDefined);
|
||||
}
|
||||
@ -76,6 +86,10 @@ public abstract class Material implements Comparable<Material> {
|
||||
}
|
||||
|
||||
public static class Bulk extends Material {
|
||||
Bulk(String name, double density, MaterialGroup group, boolean userDefined) {
|
||||
super(name, density, group, userDefined);
|
||||
}
|
||||
|
||||
Bulk(String name, double density, boolean userDefined) {
|
||||
super(name, density, userDefined);
|
||||
}
|
||||
@ -88,6 +102,10 @@ public abstract class Material implements Comparable<Material> {
|
||||
|
||||
|
||||
public static class Custom extends Material {
|
||||
Custom(String name, double density, MaterialGroup group, boolean userDefined) {
|
||||
super(name, density, group, userDefined);
|
||||
}
|
||||
|
||||
Custom(String name, double density, boolean userDefined) {
|
||||
super(name, density, userDefined);
|
||||
}
|
||||
@ -103,20 +121,26 @@ public abstract class Material implements Comparable<Material> {
|
||||
private final String name;
|
||||
private final double density;
|
||||
private final boolean userDefined;
|
||||
private final MaterialGroup group;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for materials.
|
||||
*
|
||||
* @param name ignored when defining system materials.
|
||||
* @param key ignored when defining user materials.
|
||||
* @param density
|
||||
* @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.
|
||||
*/
|
||||
private Material(String name, double density, boolean userDefined) {
|
||||
private Material(String name, double density, MaterialGroup group, boolean userDefined) {
|
||||
this.name = name;
|
||||
this.userDefined = userDefined;
|
||||
this.density = density;
|
||||
this.group = group;
|
||||
this.userDefined = userDefined;
|
||||
}
|
||||
|
||||
private Material(String name, double density, boolean userDefined) {
|
||||
this(name, density, null, userDefined);
|
||||
}
|
||||
|
||||
public double getDensity() {
|
||||
@ -136,6 +160,17 @@ public abstract class Material implements Comparable<Material> {
|
||||
}
|
||||
|
||||
public abstract Type getType();
|
||||
|
||||
public MaterialGroup getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public int getGroupPriority() {
|
||||
if (group == null) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
return group.getPriority();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -154,7 +189,14 @@ public abstract class Material implements Comparable<Material> {
|
||||
if (this.getClass() != o.getClass())
|
||||
return false;
|
||||
Material m = (Material) o;
|
||||
return ((m.name.equals(this.name)) && MathUtil.equals(m.density, this.density));
|
||||
return ((m.name.equals(this.name)) && MathUtil.equals(m.density, this.density)) && groupsEqual(m);
|
||||
}
|
||||
|
||||
private boolean groupsEqual(Material m) {
|
||||
if (group == null) {
|
||||
return m.group == null;
|
||||
}
|
||||
return group.equals(m.group);
|
||||
}
|
||||
|
||||
|
||||
@ -187,37 +229,37 @@ public abstract class Material implements Comparable<Material> {
|
||||
* @param type the material type
|
||||
* @param name the material name
|
||||
* @param density the material density
|
||||
* @param group the material group
|
||||
* @param userDefined whether the material is user-defined or not
|
||||
* @return the new material
|
||||
*/
|
||||
public static Material newMaterial(Type type, String name, double density, MaterialGroup group, boolean userDefined) {
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
public static Material newMaterial(Type type, String name, double density, boolean userDefined) {
|
||||
switch (type) {
|
||||
case LINE:
|
||||
return new Material.Line(name, density, userDefined);
|
||||
|
||||
case SURFACE:
|
||||
return new Material.Surface(name, density, userDefined);
|
||||
|
||||
case BULK:
|
||||
return new Material.Bulk(name, density, userDefined);
|
||||
|
||||
case CUSTOM:
|
||||
return new Material.Custom(name, density, userDefined);
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown material type: " + type);
|
||||
}
|
||||
return newMaterial(type, name, density, null, userDefined);
|
||||
}
|
||||
|
||||
public String toStorableString() {
|
||||
return getType().name() + "|" + name.replace('|', ' ') + '|' + density;
|
||||
if (group != null) {
|
||||
return getType().name() + "|" + name.replace('|', ' ') + '|' + density + '|' + group.getDatabaseString();
|
||||
} else {
|
||||
return getType().name() + "|" + name.replace('|', ' ') + '|' + density;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a material defined by the provided string.
|
||||
*
|
||||
* @param str the material storage string, formatted as "{type}|{name}|{density}".
|
||||
* @param str the material storage string, formatted as "{type}|{name}|{density}|{group}".
|
||||
* @param userDefined whether the created material is user-defined.
|
||||
* @return a new <code>Material</code> object.
|
||||
* @throws IllegalArgumentException if <code>str</code> is invalid or null.
|
||||
@ -226,13 +268,14 @@ public abstract class Material implements Comparable<Material> {
|
||||
if (str == null)
|
||||
throw new IllegalArgumentException("Material string is null");
|
||||
|
||||
String[] split = str.split("\\|", 3);
|
||||
String[] split = str.split("\\|", 4);
|
||||
if (split.length < 3)
|
||||
throw new IllegalArgumentException("Illegal material string: " + str);
|
||||
|
||||
Type type = null;
|
||||
Type type;
|
||||
String name;
|
||||
double density;
|
||||
MaterialGroup group = null;
|
||||
|
||||
try {
|
||||
type = Type.valueOf(split[0]);
|
||||
@ -247,20 +290,21 @@ public abstract class Material implements Comparable<Material> {
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Illegal material string: " + str, e);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case BULK:
|
||||
return new Material.Bulk(name, density, userDefined);
|
||||
|
||||
case SURFACE:
|
||||
return new Material.Surface(name, density, userDefined);
|
||||
|
||||
case LINE:
|
||||
return new Material.Line(name, density, userDefined);
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal material string: " + str);
|
||||
|
||||
if (split.length == 4) {
|
||||
try {
|
||||
group = MaterialGroup.loadFromDatabaseString(split[3]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.debug(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return switch (type) {
|
||||
case BULK -> new Bulk(name, density, group, userDefined);
|
||||
case SURFACE -> new Surface(name, density, group, userDefined);
|
||||
case LINE -> new Line(name, density, group, userDefined);
|
||||
default -> throw new IllegalArgumentException("Illegal material string: " + str);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
package info.openrocket.core.material;
|
||||
|
||||
import info.openrocket.core.l10n.Translator;
|
||||
import info.openrocket.core.startup.Application;
|
||||
|
||||
/**
|
||||
* A class for categorizing materials.
|
||||
*/
|
||||
public class MaterialGroup implements Comparable<MaterialGroup> {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
public static final MaterialGroup METALS = new MaterialGroup(trans.get("MaterialGroup.Metals"), "Metals", 0, false);
|
||||
public static final MaterialGroup WOODS = new MaterialGroup(trans.get("MaterialGroup.Woods"), "Woods", 10, false);
|
||||
public static final MaterialGroup PLASTICS = new MaterialGroup(trans.get("MaterialGroup.Plastics"), "Plastics", 20, false);
|
||||
public static final MaterialGroup FABRICS = new MaterialGroup(trans.get("MaterialGroup.Fabrics"), "Fabrics", 30, false);
|
||||
public static final MaterialGroup PAPER = new MaterialGroup(trans.get("MaterialGroup.PaperProducts"), "PaperProducts", 40, false);
|
||||
public static final MaterialGroup FOAMS = new MaterialGroup(trans.get("MaterialGroup.Foams"), "Foams", 50, false);
|
||||
public static final MaterialGroup COMPOSITES = new MaterialGroup(trans.get("MaterialGroup.Composites"), "Composites", 60, false);
|
||||
public static final MaterialGroup FIBERS = new MaterialGroup(trans.get("MaterialGroup.Fibers"), "Fibres", 70, false);
|
||||
public static final MaterialGroup THREADS_LINES = new MaterialGroup(trans.get("MaterialGroup.ThreadsLines"), "ThreadsLines", 80, false);
|
||||
public static final MaterialGroup OTHER = new MaterialGroup(trans.get("MaterialGroup.Other"), "Other", 90, false);
|
||||
|
||||
public static final MaterialGroup CUSTOM = new MaterialGroup(trans.get("MaterialGroup.Custom"), "Custom", 1000, true);
|
||||
|
||||
public static final MaterialGroup[] ALL_GROUPS = {
|
||||
METALS,
|
||||
WOODS,
|
||||
PLASTICS,
|
||||
FABRICS,
|
||||
PAPER,
|
||||
FOAMS,
|
||||
COMPOSITES,
|
||||
FIBERS,
|
||||
THREADS_LINES,
|
||||
OTHER,
|
||||
CUSTOM
|
||||
};
|
||||
|
||||
private final String name;
|
||||
private final String databaseString;
|
||||
private final int priority;
|
||||
private final boolean userDefined;
|
||||
|
||||
/**
|
||||
* Create a new material group.
|
||||
* @param name the name of the group
|
||||
* @param dataBaseName the name of the group to be used when saving it in a database
|
||||
* @param priority the priority of the group (lower number = higher priority)
|
||||
* @param userDefined whether the group is user-defined
|
||||
*/
|
||||
private MaterialGroup(String name, String dataBaseName, int priority, boolean userDefined) {
|
||||
this.name = name;
|
||||
this.databaseString = dataBaseName;
|
||||
this.priority = priority;
|
||||
this.userDefined = userDefined;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDatabaseString() {
|
||||
return databaseString;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public boolean isUserDefined() {
|
||||
return userDefined;
|
||||
}
|
||||
|
||||
public static MaterialGroup loadFromDatabaseString(String name) {
|
||||
for (MaterialGroup group : ALL_GROUPS) {
|
||||
if (group.getDatabaseString().equals(name)) {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown material group: " + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof MaterialGroup))
|
||||
return false;
|
||||
return this.compareTo((MaterialGroup) o) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MaterialGroup o) {
|
||||
return this.priority - o.priority;
|
||||
}
|
||||
}
|
@ -1126,6 +1126,8 @@ MaterialPanel.lbl.ComponentFinish.ttip.longA1 = <html>The component finish affec
|
||||
MaterialPanel.lbl.ComponentFinish.ttip.longA2 = The value indicated is the average roughness height of the surface.
|
||||
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.MaterialComboBox.placeholder = Enter the material name
|
||||
|
||||
! PlacementPanel
|
||||
PlacementPanel.title.Placement = Placement
|
||||
@ -1807,6 +1809,19 @@ material.tubular_nylon_11_mm_7_16_in = Tubular nylon (11 mm, 7/16 in)
|
||||
material.tubular_nylon_14_mm_9_16_in = Tubular nylon (14 mm, 9/16 in)
|
||||
material.tubular_nylon_25_mm_1_in = Tubular nylon (25 mm, 1 in)
|
||||
|
||||
!MaterialGroup
|
||||
MaterialGroup.Metals = Metals
|
||||
MaterialGroup.Woods = Woods
|
||||
MaterialGroup.Plastics = Plastics
|
||||
MaterialGroup.Fabrics = Fabrics
|
||||
MaterialGroup.PaperProducts = Paper Products
|
||||
MaterialGroup.Foams = Foams
|
||||
MaterialGroup.Composites = Composites
|
||||
MaterialGroup.Fibers = Fibers
|
||||
MaterialGroup.ThreadsLines = Threads and Lines
|
||||
MaterialGroup.Other = Other
|
||||
MaterialGroup.Custom = Custom
|
||||
|
||||
! ExternalComponent
|
||||
ExternalComponent.Rough = Rough
|
||||
ExternalComponent.Roughunfinished = Rough unfinished
|
||||
|
@ -25,10 +25,6 @@ public class MaterialModel extends AbstractListModel<Material> implements
|
||||
ComboBoxModel<Material>, ComponentChangeListener, DatabaseListener<Material>, Invalidatable {
|
||||
private static final long serialVersionUID = 4552478532933113655L;
|
||||
private final ModelInvalidator modelInvalidator;
|
||||
|
||||
|
||||
private final Material custom;
|
||||
|
||||
|
||||
private final Component parentUIComponent;
|
||||
|
||||
@ -53,23 +49,22 @@ public class MaterialModel extends AbstractListModel<Material> implements
|
||||
this.parentUIComponent = parent;
|
||||
this.rocketComponent = component;
|
||||
this.type = type;
|
||||
this.custom = Material.newMaterial( Material.Type.CUSTOM, trans.get ("Material.CUSTOM"), 1.0, true );
|
||||
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -97,55 +92,53 @@ public class MaterialModel extends AbstractListModel<Material> implements
|
||||
return;
|
||||
}
|
||||
|
||||
if (item == custom) {
|
||||
|
||||
// Open custom material dialog in the future, after combo box has closed
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CustomMaterialDialog dialog = new CustomMaterialDialog(
|
||||
SwingUtilities.getWindowAncestor(parentUIComponent),
|
||||
(Material) getSelectedItem(), true,
|
||||
//// Define custom material
|
||||
trans.get("MaterialModel.title.Defcustmat"));
|
||||
|
||||
dialog.setVisible(true);
|
||||
|
||||
if (!dialog.getOkClicked())
|
||||
return;
|
||||
|
||||
Material material = dialog.getMaterial();
|
||||
setMethod.invoke(rocketComponent, material);
|
||||
|
||||
if (dialog.isAddSelected()) {
|
||||
database.add(material);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} else if (item instanceof Material) {
|
||||
|
||||
if (item instanceof Material) {
|
||||
setMethod.invoke(rocketComponent, item);
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException("Illegal item class " + item.getClass() +
|
||||
" item=" + item);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCustomMaterial() {
|
||||
CustomMaterialDialog dialog = new CustomMaterialDialog(
|
||||
SwingUtilities.getWindowAncestor(parentUIComponent),
|
||||
(Material) getSelectedItem(), true,
|
||||
trans.get("MaterialModel.title.Defcustmat"));
|
||||
|
||||
dialog.setVisible(true);
|
||||
|
||||
if (!dialog.getOkClicked())
|
||||
return;
|
||||
|
||||
Material material = dialog.getMaterial();
|
||||
setMethod.invoke(rocketComponent, material);
|
||||
|
||||
// TODO: add to permanent database if addSelected, add to document database otherwise
|
||||
if (dialog.isAddSelected()) {
|
||||
database.add(material);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getElementAt(int index) {
|
||||
if (index == database.size()) {
|
||||
return custom;
|
||||
} else if (index >= database.size()+1) {
|
||||
if (index >= database.size()) {
|
||||
return null;
|
||||
}
|
||||
return database.get(index);
|
||||
}
|
||||
|
||||
public Material[] getAllMaterials() {
|
||||
Material[] materials = new Material[database.size()];
|
||||
for (int i = 0; i < database.size(); i++) {
|
||||
materials[i] = database.get(i);
|
||||
}
|
||||
return materials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return database.size() + 1;
|
||||
return database.size();
|
||||
}
|
||||
|
||||
public Material.Type getType() {
|
||||
@ -156,7 +149,7 @@ public class MaterialModel extends AbstractListModel<Material> implements
|
||||
|
||||
@Override
|
||||
public void componentChanged(ComponentChangeEvent e) {
|
||||
if (((ComponentChangeEvent)e).isMassChange()) {
|
||||
if (e.isMassChange()) {
|
||||
this.fireContentsChanged(this, 0, 0);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package info.openrocket.swing.gui.configdialog;
|
||||
|
||||
import info.openrocket.core.material.MaterialGroup;
|
||||
import info.openrocket.core.util.Invalidatable;
|
||||
import info.openrocket.swing.gui.widgets.SearchableAndCategorizableComboBox;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import info.openrocket.core.document.OpenRocketDocument;
|
||||
@ -19,12 +21,17 @@ import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Panel for configuring a component's material and finish properties.
|
||||
@ -32,6 +39,7 @@ import java.util.List;
|
||||
public class MaterialPanel extends JPanel implements Invalidatable, InvalidatingWidget {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
private final List<Invalidatable> invalidatables = new ArrayList<>();
|
||||
private SearchableAndCategorizableComboBox<MaterialGroup, Material> materialCombo = null;
|
||||
|
||||
public MaterialPanel(RocketComponent component, OpenRocketDocument document,
|
||||
Material.Type type, String materialString, String finishString,
|
||||
@ -39,24 +47,43 @@ public class MaterialPanel extends JPanel implements Invalidatable, Invalidating
|
||||
super(new MigLayout());
|
||||
this.setBorder(BorderFactory.createTitledBorder(trans.get("MaterialPanel.title.Material")));
|
||||
|
||||
//// Component material
|
||||
JLabel label = new JLabel(materialString);
|
||||
//// The component material affects the weight of the component.
|
||||
label.setToolTipText(trans.get("MaterialPanel.lbl.ttip.ComponentMaterialAffects"));
|
||||
this.add(label, "spanx 4, wrap rel");
|
||||
|
||||
MaterialModel mm = new MaterialModel(this, component, type, partName);
|
||||
register(mm);
|
||||
JComboBox<Material> materialCombo = new JComboBox<>(mm);
|
||||
//// The component material affects the weight of the component.
|
||||
materialCombo.setToolTipText(trans.get("MaterialPanel.combo.ttip.ComponentMaterialAffects"));
|
||||
this.add(materialCombo, "spanx 4, growx, wrap paragraph");
|
||||
order.add(materialCombo);
|
||||
|
||||
// Set custom material button
|
||||
JButton customMaterialButton = new JButton(trans.get("MaterialPanel.but.AddCustomMaterial"));
|
||||
customMaterialButton.addActionListener(e -> {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mm.addCustomMaterial();
|
||||
if (MaterialPanel.this.materialCombo != null) {
|
||||
MaterialComboBox.updateComboBoxItems(MaterialPanel.this.materialCombo, MaterialGroup.ALL_GROUPS, mm.getAllMaterials());
|
||||
MaterialPanel.this.materialCombo.setSelectedItem(mm.getSelectedItem());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Material selection combo box
|
||||
this.materialCombo = MaterialComboBox.createComboBox(MaterialGroup.ALL_GROUPS, mm.getAllMaterials(), customMaterialButton);
|
||||
this.materialCombo.setSelectedItem(mm.getSelectedItem());
|
||||
this.materialCombo.setToolTipText(trans.get("MaterialPanel.combo.ttip.ComponentMaterialAffects"));
|
||||
this.add(this.materialCombo, "spanx 4, growx, wrap paragraph");
|
||||
order.add(this.materialCombo);
|
||||
|
||||
// No surface finish for internal components
|
||||
if (!(component instanceof ExternalComponent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//// Surface finish
|
||||
label = new JLabel(finishString);
|
||||
////<html>The component finish affects the aerodynamic drag of the component.<br>
|
||||
String tip = trans.get("MaterialPanel.lbl.ComponentFinish.ttip.longA1")
|
||||
//// The value indicated is the average roughness height of the surface.
|
||||
+ trans.get("MaterialPanel.lbl.ComponentFinish.ttip.longA2");
|
||||
@ -122,4 +149,63 @@ public class MaterialPanel extends JPanel implements Invalidatable, Invalidating
|
||||
i.invalidateMe();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MaterialComboBox extends JComboBox<Material> {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
public static SearchableAndCategorizableComboBox<MaterialGroup, Material> createComboBox(
|
||||
MaterialGroup[] allGroups, Material[] materials, Component... extraCategoryWidgets) {
|
||||
final Map<MaterialGroup, Material[]> materialGroupMap = createMaterialGroupMap(allGroups, materials);
|
||||
return new SearchableAndCategorizableComboBox<>(materialGroupMap, trans.get("MaterialPanel.MaterialComboBox.placeholder"), extraCategoryWidgets);
|
||||
}
|
||||
|
||||
public static void updateComboBoxItems(SearchableAndCategorizableComboBox<MaterialGroup, Material> comboBox,
|
||||
MaterialGroup[] allGroups, Material[] materials) {
|
||||
final Map<MaterialGroup, Material[]> materialGroupMap = createMaterialGroupMap(allGroups, materials);
|
||||
comboBox.updateItems(materialGroupMap);
|
||||
comboBox.invalidate();
|
||||
comboBox.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a map of material group and corresponding material.
|
||||
* @param groups the groups
|
||||
* @param materials the materials
|
||||
* @return the map linking the materials to their groups
|
||||
*/
|
||||
private static Map<MaterialGroup, Material[]> createMaterialGroupMap(
|
||||
MaterialGroup[] groups, Material[] materials) {
|
||||
// Sort the groups based on priority (lower number = higher priority)
|
||||
MaterialGroup[] sortedGroups = groups.clone();
|
||||
Arrays.sort(sortedGroups, Comparator.comparingInt(MaterialGroup::getPriority));
|
||||
|
||||
Map<MaterialGroup, Material[]> map = new LinkedHashMap<>();
|
||||
MaterialGroup materialGroup;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (materialGroup.equals(group)) {
|
||||
itemsForGroup.add(material);
|
||||
}
|
||||
}
|
||||
// Sort the types within each group based on priority
|
||||
itemsForGroup.sort(Comparator.comparingInt(Material::getGroupPriority));
|
||||
|
||||
map.put(group, itemsForGroup.toArray(new Material[0]));
|
||||
}
|
||||
|
||||
// Remove empty groups
|
||||
map.entrySet().removeIf(entry -> entry.getValue().length == 0);
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
@ -43,17 +45,21 @@ import java.util.TreeSet;
|
||||
* If no text is entered, the combobox items are displayed in a categorized popup menu, grouped according to their groups.
|
||||
* @param <E> The type of the group
|
||||
* @param <T> The type of the items
|
||||
*
|
||||
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
|
||||
*/
|
||||
public class SearchableAndCategorizableComboBox<E, T> extends JComboBox<T> {
|
||||
|
||||
private final JPopupMenu categoryPopup;
|
||||
private final JPopupMenu searchPopup;
|
||||
private final PlaceholderTextField searchFieldCategory;
|
||||
private final PlaceholderTextField searchFieldSearch;
|
||||
private final JList<T> filteredList;
|
||||
private final String placeHolderText;
|
||||
private JPopupMenu categoryPopup;
|
||||
private JPopupMenu searchPopup;
|
||||
private PlaceholderTextField searchFieldCategory;
|
||||
private PlaceholderTextField searchFieldSearch;
|
||||
private final Component[] extraCategoryWidgets;
|
||||
private JList<T> filteredList;
|
||||
|
||||
private final T[] allItems;
|
||||
private final Map<E, T[]> itemGroupMap;
|
||||
private T[] allItems;
|
||||
private Map<E, T[]> itemGroupMap;
|
||||
|
||||
private int highlightedListIdx = -1;
|
||||
|
||||
@ -67,29 +73,17 @@ public class SearchableAndCategorizableComboBox<E, T> extends JComboBox<T> {
|
||||
* Create a searchable and categorizable combo box.
|
||||
* @param itemGroupMap the map of items and their corresponding groups
|
||||
* @param placeHolderText the placeholder text for the search field (when no text is entered)
|
||||
* @param extraCategoryWidgets extra widgets to add to the category popup. Each widget will be added as a separate menu item.
|
||||
*/
|
||||
public SearchableAndCategorizableComboBox(Map<E, T[]> itemGroupMap, String placeHolderText) {
|
||||
public SearchableAndCategorizableComboBox(Map<E, T[]> itemGroupMap, String placeHolderText, Component... extraCategoryWidgets) {
|
||||
super();
|
||||
setEditable(false);
|
||||
|
||||
this.itemGroupMap = itemGroupMap;
|
||||
this.allItems = extractItemsFromMap(itemGroupMap);
|
||||
setModel(new DefaultComboBoxModel<>(allItems));
|
||||
|
||||
initColors();
|
||||
|
||||
// Create the search field widget
|
||||
searchFieldCategory = new PlaceholderTextField();
|
||||
searchFieldCategory.setPlaceholder(placeHolderText);
|
||||
searchFieldSearch = new PlaceholderTextField();
|
||||
|
||||
// Create the filtered list
|
||||
filteredList = createFilteredList();
|
||||
|
||||
// Create the different popups
|
||||
categoryPopup = createCategoryPopup();
|
||||
searchPopup = createSearchPopup();
|
||||
searchPopup.setPreferredSize(categoryPopup.getPreferredSize());
|
||||
this.extraCategoryWidgets = extraCategoryWidgets;
|
||||
this.placeHolderText = placeHolderText;
|
||||
updateItems(itemGroupMap);
|
||||
|
||||
// Add key listener for the search fields
|
||||
searchFieldCategory.addKeyListener(new KeyAdapter() {
|
||||
@ -98,6 +92,7 @@ public class SearchableAndCategorizableComboBox<E, T> extends JComboBox<T> {
|
||||
overrideActionKeys(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
String text = searchFieldCategory.getText();
|
||||
@ -131,6 +126,16 @@ public class SearchableAndCategorizableComboBox<E, T> extends JComboBox<T> {
|
||||
});
|
||||
}
|
||||
});
|
||||
// Fix a bug where the first character would get selected when the search field gets focus (thus deleting it on
|
||||
// the next key press)
|
||||
searchFieldSearch.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
searchFieldSearch.setCaretPosition(searchFieldSearch.getText().length());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Override the mouse listeners to use our custom popup
|
||||
for (MouseListener mouseListener : getMouseListeners()) {
|
||||
@ -149,6 +154,25 @@ public class SearchableAndCategorizableComboBox<E, T> extends JComboBox<T> {
|
||||
textSelectionBackground = GUIUtil.getUITheme().getTextSelectionBackgroundColor();
|
||||
}
|
||||
|
||||
public void updateItems(Map<E, T[]> itemGroupMap) {
|
||||
this.itemGroupMap = itemGroupMap;
|
||||
this.allItems = extractItemsFromMap(itemGroupMap);
|
||||
setModel(new DefaultComboBoxModel<>(this.allItems));
|
||||
|
||||
// Create the search field widget
|
||||
this.searchFieldCategory = new PlaceholderTextField();
|
||||
this.searchFieldCategory.setPlaceholder(this.placeHolderText);
|
||||
this.searchFieldSearch = new PlaceholderTextField();
|
||||
|
||||
// Create the filtered list
|
||||
this.filteredList = createFilteredList();
|
||||
|
||||
// Create the different popups
|
||||
this.categoryPopup = createCategoryPopup();
|
||||
this.searchPopup = createSearchPopup();
|
||||
this.searchPopup.setPreferredSize(this.categoryPopup.getPreferredSize());
|
||||
}
|
||||
|
||||
private T[] extractItemsFromMap(Map<E, T[]> itemGroupMap) {
|
||||
Set<T> uniqueItems = new HashSet<>(); // Use a Set to ensure uniqueness
|
||||
for (E group : itemGroupMap.keySet()) {
|
||||
@ -183,6 +207,13 @@ public class SearchableAndCategorizableComboBox<E, T> extends JComboBox<T> {
|
||||
menu.add(groupList);
|
||||
}
|
||||
|
||||
// Extra widgets
|
||||
if (extraCategoryWidgets != null) {
|
||||
for (Component widget : extraCategoryWidgets) {
|
||||
menu.add(widget);
|
||||
}
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user