Add RocketComponent selector in CAExportPanel
This commit is contained in:
		
							parent
							
								
									88f7c7e18d
								
							
						
					
					
						commit
						73981839e6
					
				@ -966,6 +966,9 @@ CAPlotExportDialog.lbl.Delta.ttip = Step size (increments) for the parameter swe
 | 
			
		||||
CAPlotExportDialog.tab.Plot = Plot
 | 
			
		||||
CAPlotExportDialog.tab.Export = Export
 | 
			
		||||
 | 
			
		||||
! CAExportPanel
 | 
			
		||||
CAExportPanel.Col.Components = Components
 | 
			
		||||
 | 
			
		||||
! CADataTypeGroup
 | 
			
		||||
CADataTypeGroup.DOMAIN = Domain Parameter
 | 
			
		||||
CADataTypeGroup.DRAG = Drag Characteristics
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,7 @@ public class CsvOptionPanel extends JPanel {
 | 
			
		||||
	 * @param includeComments	a list of comment inclusion options to provide;
 | 
			
		||||
	 * 							every second item is the option name and every second the tooltip
 | 
			
		||||
	 */
 | 
			
		||||
	public CsvOptionPanel(Class<?> baseClass, String... includeComments) {
 | 
			
		||||
	public CsvOptionPanel(Class<?> baseClass, boolean placeOnNewRows, String... includeComments) {
 | 
			
		||||
		super(new MigLayout("fill, insets 0"));
 | 
			
		||||
		
 | 
			
		||||
		this.baseClassName = baseClass.getSimpleName();
 | 
			
		||||
@ -88,7 +88,11 @@ public class CsvOptionPanel extends JPanel {
 | 
			
		||||
		exponentialNotationCheckbox.setSelected(Application.getPreferences().getBoolean(ApplicationPreferences.EXPORT_EXPONENTIAL_NOTATION, true));
 | 
			
		||||
		panel.add(exponentialNotationCheckbox);
 | 
			
		||||
 | 
			
		||||
		if (placeOnNewRows) {
 | 
			
		||||
			this.add(panel, "growx, wrap unrel");
 | 
			
		||||
		} else {
 | 
			
		||||
			this.add(panel, "growx, gapright unrel");
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -121,7 +125,15 @@ public class CsvOptionPanel extends JPanel {
 | 
			
		||||
		commentCharacter.setToolTipText(tip);
 | 
			
		||||
		panel.add(commentCharacter, "growx");
 | 
			
		||||
 | 
			
		||||
		if (placeOnNewRows) {
 | 
			
		||||
			this.add(panel, "growx, wrap");
 | 
			
		||||
		} else {
 | 
			
		||||
			this.add(panel, "growx");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public CsvOptionPanel(Class<?> baseClass, String... includeComments) {
 | 
			
		||||
		this(baseClass, true, includeComments);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
package info.openrocket.swing.gui.dialogs.componentanalysis;
 | 
			
		||||
 | 
			
		||||
import info.openrocket.core.l10n.Translator;
 | 
			
		||||
import info.openrocket.core.rocketcomponent.RocketComponent;
 | 
			
		||||
import info.openrocket.core.startup.Application;
 | 
			
		||||
import info.openrocket.core.unit.Unit;
 | 
			
		||||
import info.openrocket.swing.gui.components.CsvOptionPanel;
 | 
			
		||||
@ -9,33 +10,96 @@ import info.openrocket.swing.gui.util.SwingPreferences;
 | 
			
		||||
import info.openrocket.swing.gui.widgets.CSVExportPanel;
 | 
			
		||||
import info.openrocket.swing.gui.widgets.SaveFileChooser;
 | 
			
		||||
 | 
			
		||||
import javax.swing.AbstractCellEditor;
 | 
			
		||||
import javax.swing.BorderFactory;
 | 
			
		||||
import javax.swing.JCheckBox;
 | 
			
		||||
import javax.swing.JComponent;
 | 
			
		||||
import javax.swing.JFileChooser;
 | 
			
		||||
import javax.swing.JLabel;
 | 
			
		||||
import javax.swing.JPanel;
 | 
			
		||||
import javax.swing.JTable;
 | 
			
		||||
import javax.swing.table.DefaultTableCellRenderer;
 | 
			
		||||
import javax.swing.table.TableCellEditor;
 | 
			
		||||
import javax.swing.table.TableCellRenderer;
 | 
			
		||||
import javax.swing.table.TableColumn;
 | 
			
		||||
import java.awt.Color;
 | 
			
		||||
import java.awt.Component;
 | 
			
		||||
import java.awt.Graphics;
 | 
			
		||||
import java.awt.GridBagConstraints;
 | 
			
		||||
import java.awt.GridBagLayout;
 | 
			
		||||
import java.awt.Insets;
 | 
			
		||||
import java.awt.event.ItemEvent;
 | 
			
		||||
import java.awt.event.ItemListener;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicBoolean;
 | 
			
		||||
 | 
			
		||||
public class CAExportPanel extends CSVExportPanel<CADataType> {
 | 
			
		||||
	private static final long serialVersionUID = 4423905472892675964L;
 | 
			
		||||
 | 
			
		||||
	private static final Translator trans = Application.getTranslator();
 | 
			
		||||
 | 
			
		||||
	private static final int OPTION_FIELD_DESCRIPTIONS = 0;
 | 
			
		||||
	private static final int FIXED_COMPONENT_COLUMN_WIDTH = 500;
 | 
			
		||||
 | 
			
		||||
	private CAExportPanel(CADataType[] types,
 | 
			
		||||
	private final List<Map<RocketComponent, Boolean>> selectedComponents;
 | 
			
		||||
 | 
			
		||||
	private CAExportPanel(ComponentAnalysisPlotExportPanel parent, CADataType[] types,
 | 
			
		||||
						  boolean[] selected, CsvOptionPanel csvOptions, Component... extraComponents) {
 | 
			
		||||
		super(types, selected, csvOptions, extraComponents);
 | 
			
		||||
		super(types, selected, csvOptions, true, extraComponents);
 | 
			
		||||
 | 
			
		||||
		selectedComponents = new ArrayList<>(types.length);
 | 
			
		||||
		Map<RocketComponent, Boolean> componentSelectedMap;
 | 
			
		||||
		List<RocketComponent> components;
 | 
			
		||||
		for (CADataType type : types) {
 | 
			
		||||
			components = parent.getComponentsForType(type);
 | 
			
		||||
			componentSelectedMap = new HashMap<>(components.size());
 | 
			
		||||
			for (int i = 0; i < components.size(); i++) {
 | 
			
		||||
				// Select the first component by default
 | 
			
		||||
				componentSelectedMap.put(components.get(i), i == 0);
 | 
			
		||||
			}
 | 
			
		||||
			selectedComponents.add(componentSelectedMap);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	public static CAExportPanel create(CADataType[] types) {
 | 
			
		||||
		// Set row heights dynamically
 | 
			
		||||
		for (int row = 0; row < table.getRowCount(); row++) {
 | 
			
		||||
			int numComponents = ((Map<?, ?>) table.getValueAt(row, 3)).size();
 | 
			
		||||
			double correctNumComponents = Math.ceil(numComponents / 3.0);  // 3 components per row
 | 
			
		||||
			double height = Math.round(correctNumComponents * 25) + 10;  // 25 pixels per component + 10 pixel margin
 | 
			
		||||
			int rowHeight = Math.max(table.getRowHeight(), (int) height);
 | 
			
		||||
			table.setRowHeight(row, rowHeight);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static CAExportPanel create(ComponentAnalysisPlotExportPanel parent, CADataType[] types) {
 | 
			
		||||
		boolean[] selected = new boolean[types.length];
 | 
			
		||||
		for (int i = 0; i < types.length; i++) {
 | 
			
		||||
			selected[i] = ((SwingPreferences) Application.getPreferences()).isComponentAnalysisDataTypeExportSelected(types[i]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		CsvOptionPanel csvOptions = new CsvOptionPanel(CAExportPanel.class,
 | 
			
		||||
		CsvOptionPanel csvOptions = new CsvOptionPanel(CAExportPanel.class, false,
 | 
			
		||||
				trans.get("SimExpPan.checkbox.Includefielddesc"),
 | 
			
		||||
				trans.get("SimExpPan.checkbox.ttip.Includefielddesc"));
 | 
			
		||||
 | 
			
		||||
		return new CAExportPanel(types, selected, csvOptions);
 | 
			
		||||
		return new CAExportPanel(parent, types, selected, csvOptions);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected void initializeTable(CADataType[] types) {
 | 
			
		||||
		super.initializeTable(types);
 | 
			
		||||
 | 
			
		||||
		// Set custom renderers for each column
 | 
			
		||||
		table.getColumnModel().getColumn(0).setCellRenderer(new CheckBoxRenderer());
 | 
			
		||||
		table.getColumnModel().getColumn(1).setCellRenderer(new LeftAlignedRenderer());
 | 
			
		||||
		table.getColumnModel().getColumn(2).setCellRenderer(new LeftAlignedRenderer());
 | 
			
		||||
 | 
			
		||||
		TableColumn componentColumn = table.getColumnModel().getColumn(3);
 | 
			
		||||
		componentColumn.setCellRenderer(new ComponentCheckBoxRenderer());
 | 
			
		||||
		componentColumn.setCellEditor(new ComponentCheckBoxEditor());
 | 
			
		||||
		componentColumn.setPreferredWidth(FIXED_COMPONENT_COLUMN_WIDTH);
 | 
			
		||||
 | 
			
		||||
		// Set specific client properties for FlatLaf
 | 
			
		||||
		table.setShowHorizontalLines(true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
@ -98,4 +162,278 @@ public class CAExportPanel extends CSVExportPanel<CADataType> {
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected CSVExportPanel<CADataType>.SelectionTableModel createTableModel() {
 | 
			
		||||
		return new CASelectionTableModel();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected class CASelectionTableModel extends SelectionTableModel {
 | 
			
		||||
		private static final int COMPONENTS = 3;
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public int getColumnCount() {
 | 
			
		||||
			return 4;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String getColumnName(int column) {
 | 
			
		||||
			//// Components
 | 
			
		||||
			if (column == COMPONENTS) {
 | 
			
		||||
				return trans.get("CAExportPanel.Col.Components");
 | 
			
		||||
			}
 | 
			
		||||
			return super.getColumnName(column);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Class<?> getColumnClass(int column) {
 | 
			
		||||
			//// Components
 | 
			
		||||
			if (column == COMPONENTS) {
 | 
			
		||||
				return Map.class;
 | 
			
		||||
			}
 | 
			
		||||
			return super.getColumnClass(column);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Object getValueAt(int row, int column) {
 | 
			
		||||
			if (column == COMPONENTS) {
 | 
			
		||||
				return selectedComponents.get(row);
 | 
			
		||||
			}
 | 
			
		||||
			return super.getValueAt(row, column);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void setValueAt(Object value, int row, int column) {
 | 
			
		||||
			if (column == COMPONENTS) {
 | 
			
		||||
				selectedComponents.set(row, (Map<RocketComponent, Boolean>) value);
 | 
			
		||||
				fireTableCellUpdated(row, column);
 | 
			
		||||
			} else {
 | 
			
		||||
				super.setValueAt(value, row, column);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public boolean isCellEditable(int row, int column) {
 | 
			
		||||
			if (column == COMPONENTS) {
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
			return super.isCellEditable(row, column);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class CheckBoxRenderer extends JCheckBox implements TableCellRenderer {
 | 
			
		||||
		public CheckBoxRenderer() {
 | 
			
		||||
			setHorizontalAlignment(JLabel.CENTER);
 | 
			
		||||
			setVerticalAlignment(JLabel.TOP);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
 | 
			
		||||
			setSelected((Boolean) value);
 | 
			
		||||
			setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
 | 
			
		||||
			setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
 | 
			
		||||
			setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); // Add top padding
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class LeftAlignedRenderer extends DefaultTableCellRenderer {
 | 
			
		||||
		public LeftAlignedRenderer() {
 | 
			
		||||
			setHorizontalAlignment(JLabel.LEFT);
 | 
			
		||||
			setVerticalAlignment(JLabel.TOP);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
 | 
			
		||||
			Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
 | 
			
		||||
			c.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
 | 
			
		||||
			c.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
 | 
			
		||||
			((JComponent) c).setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 0)); // Add top and left padding
 | 
			
		||||
			return c;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class ComponentCheckBoxRenderer implements TableCellRenderer {
 | 
			
		||||
		private ComponentCheckBoxPanel panel;
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
 | 
			
		||||
			if (!(value instanceof Map)) {
 | 
			
		||||
				JLabel errorLabel = new JLabel("Invalid data");
 | 
			
		||||
				errorLabel.setForeground(Color.RED);
 | 
			
		||||
				return errorLabel;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			@SuppressWarnings("unchecked")
 | 
			
		||||
			Map<RocketComponent, Boolean> componentMap = (Map<RocketComponent, Boolean>) value;
 | 
			
		||||
 | 
			
		||||
			if (panel == null) {
 | 
			
		||||
				panel = new ComponentCheckBoxPanel(componentMap);
 | 
			
		||||
			} else {
 | 
			
		||||
				panel.updateComponentStates(componentMap);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			panel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
 | 
			
		||||
			panel.setGridColor(table.getGridColor());
 | 
			
		||||
			panel.setSelected(isSelected);
 | 
			
		||||
 | 
			
		||||
			return panel;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class ComponentCheckBoxPanel extends JPanel {
 | 
			
		||||
		private final Map<RocketComponent, JCheckBox> checkBoxMap = new HashMap<>();
 | 
			
		||||
		private final ItemListener checkBoxListener;
 | 
			
		||||
		private final AtomicBoolean updatingState = new AtomicBoolean(false);
 | 
			
		||||
		private Color gridColor = Color.GRAY;
 | 
			
		||||
		private boolean isSelected = false;
 | 
			
		||||
 | 
			
		||||
		public ComponentCheckBoxPanel(Map<RocketComponent, Boolean> componentMap) {
 | 
			
		||||
			setLayout(new GridBagLayout());
 | 
			
		||||
			GridBagConstraints gbc = new GridBagConstraints();
 | 
			
		||||
			gbc.anchor = GridBagConstraints.NORTHWEST;
 | 
			
		||||
			gbc.fill = GridBagConstraints.HORIZONTAL;
 | 
			
		||||
			gbc.weightx = 1.0;
 | 
			
		||||
			gbc.insets = new Insets(2, 2, 2, 2);
 | 
			
		||||
 | 
			
		||||
			checkBoxListener = e -> {
 | 
			
		||||
				if (updatingState.get()) return;
 | 
			
		||||
 | 
			
		||||
				JCheckBox source = (JCheckBox) e.getSource();
 | 
			
		||||
				if (e.getStateChange() == ItemEvent.DESELECTED) {
 | 
			
		||||
					if (checkBoxMap.values().stream().noneMatch(JCheckBox::isSelected)) {
 | 
			
		||||
						source.setSelected(true);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Notify the table that the value has changed
 | 
			
		||||
				firePropertyChange("value", null, getComponentStates());
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			createCheckBoxes(componentMap, gbc);
 | 
			
		||||
 | 
			
		||||
			// Add an empty component to push everything to the top-left
 | 
			
		||||
			gbc.gridx = 0;
 | 
			
		||||
			gbc.gridy = (componentMap.size() + 2) / 3 + 1;
 | 
			
		||||
			gbc.weighty = 1.0;
 | 
			
		||||
			gbc.fill = GridBagConstraints.BOTH;
 | 
			
		||||
			add(new JPanel(), gbc);
 | 
			
		||||
 | 
			
		||||
			// Ensure at least one checkbox is selected
 | 
			
		||||
			if (checkBoxMap.values().stream().noneMatch(JCheckBox::isSelected) && !checkBoxMap.isEmpty()) {
 | 
			
		||||
				checkBoxMap.values().iterator().next().setSelected(true);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void createCheckBoxes(Map<RocketComponent, Boolean> componentMap, GridBagConstraints gbc) {
 | 
			
		||||
			int row = 0;
 | 
			
		||||
			int col = 0;
 | 
			
		||||
			for (Map.Entry<RocketComponent, Boolean> entry : componentMap.entrySet()) {
 | 
			
		||||
				RocketComponent component = entry.getKey();
 | 
			
		||||
				Boolean isSelected = entry.getValue();
 | 
			
		||||
 | 
			
		||||
				// Skip null components
 | 
			
		||||
				if (component == null) {
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				String componentName = component.getName();
 | 
			
		||||
				// Use a default name if getName() returns null
 | 
			
		||||
				if (componentName == null) {
 | 
			
		||||
					componentName = "Unnamed Component";
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				JCheckBox checkBox = new JCheckBox(componentName, isSelected != null && isSelected);
 | 
			
		||||
				checkBox.setOpaque(false);
 | 
			
		||||
				checkBox.setMargin(new Insets(0, 0, 0, 0));
 | 
			
		||||
				checkBox.addItemListener(checkBoxListener);
 | 
			
		||||
				checkBoxMap.put(component, checkBox);
 | 
			
		||||
 | 
			
		||||
				gbc.gridx = col;
 | 
			
		||||
				gbc.gridy = row;
 | 
			
		||||
				add(checkBox, gbc);
 | 
			
		||||
 | 
			
		||||
				col++;
 | 
			
		||||
				if (col > 2) {
 | 
			
		||||
					col = 0;
 | 
			
		||||
					row++;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void updateComponentStates(Map<RocketComponent, Boolean> newStates) {
 | 
			
		||||
			updatingState.set(true);
 | 
			
		||||
			try {
 | 
			
		||||
				for (Map.Entry<RocketComponent, Boolean> entry : newStates.entrySet()) {
 | 
			
		||||
					JCheckBox checkBox = checkBoxMap.get(entry.getKey());
 | 
			
		||||
					if (checkBox != null) {
 | 
			
		||||
						checkBox.setSelected(entry.getValue());
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} finally {
 | 
			
		||||
				updatingState.set(false);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Map<RocketComponent, Boolean> getComponentStates() {
 | 
			
		||||
			return checkBoxMap.entrySet().stream()
 | 
			
		||||
					.collect(HashMap::new,
 | 
			
		||||
							(m, e) -> m.put(e.getKey(), e.getValue().isSelected()),
 | 
			
		||||
							HashMap::putAll);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void setGridColor(Color color) {
 | 
			
		||||
			this.gridColor = color;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void setSelected(boolean selected) {
 | 
			
		||||
			this.isSelected = selected;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		protected void paintComponent(Graphics g) {
 | 
			
		||||
			super.paintComponent(g);
 | 
			
		||||
 | 
			
		||||
			// Draw the bottom border
 | 
			
		||||
			g.setColor(gridColor);
 | 
			
		||||
			g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1);
 | 
			
		||||
 | 
			
		||||
			// If selected, draw a slight highlight
 | 
			
		||||
			if (isSelected) {
 | 
			
		||||
				g.setColor(new Color(0, 0, 255, 30)); // Semi-transparent blue
 | 
			
		||||
				g.fillRect(0, 0, getWidth(), getHeight() - 1);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class ComponentCheckBoxEditor extends AbstractCellEditor implements TableCellEditor {
 | 
			
		||||
		private ComponentCheckBoxPanel panel;
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
 | 
			
		||||
			if (!(value instanceof Map)) {
 | 
			
		||||
				// Return a default component if value is not a Map
 | 
			
		||||
				JLabel errorLabel = new JLabel("Invalid data");
 | 
			
		||||
				errorLabel.setForeground(Color.RED);
 | 
			
		||||
				return errorLabel;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			@SuppressWarnings("unchecked")
 | 
			
		||||
			Map<RocketComponent, Boolean> componentMap = (Map<RocketComponent, Boolean>) value;
 | 
			
		||||
 | 
			
		||||
			if (panel == null) {
 | 
			
		||||
				panel = new ComponentCheckBoxPanel(componentMap);
 | 
			
		||||
			} else {
 | 
			
		||||
				panel.updateComponentStates(componentMap);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			panel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
 | 
			
		||||
			return panel;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Object getCellEditorValue() {
 | 
			
		||||
			return panel.getComponentStates();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -58,7 +58,7 @@ public class ComponentAnalysisPlotExportPanel extends JPanel {
 | 
			
		||||
 | 
			
		||||
	public ComponentAnalysisPlotExportPanel(ComponentAnalysisDialog parent, CAParameters parameters,
 | 
			
		||||
											AerodynamicCalculator aerodynamicCalculator, Rocket rocket) {
 | 
			
		||||
		super(new MigLayout("fill, height 500px"));
 | 
			
		||||
		super(new MigLayout("fill, height 700px"));
 | 
			
		||||
 | 
			
		||||
		this.parent = parent;
 | 
			
		||||
		this.parameters = parameters;
 | 
			
		||||
@ -80,7 +80,7 @@ public class ComponentAnalysisPlotExportPanel extends JPanel {
 | 
			
		||||
		this.tabbedPane.addTab(trans.get("CAPlotExportDialog.tab.Plot"), null, this.plotTab);
 | 
			
		||||
 | 
			
		||||
		//// Export data
 | 
			
		||||
		this.exportTab = CAExportPanel.create(types);
 | 
			
		||||
		this.exportTab = CAExportPanel.create(this, types);
 | 
			
		||||
		this.tabbedPane.addTab(trans.get("CAPlotExportDialog.tab.Export"), null, this.exportTab);
 | 
			
		||||
 | 
			
		||||
		// Create the OK button
 | 
			
		||||
 | 
			
		||||
@ -32,8 +32,8 @@ public class CSVExportPanel<T extends UnitValue> extends JPanel {
 | 
			
		||||
	protected static final String SPACE = "SPACE";
 | 
			
		||||
	protected static final String TAB = "TAB";
 | 
			
		||||
 | 
			
		||||
	private final JTable table;
 | 
			
		||||
	private final SelectionTableModel tableModel;
 | 
			
		||||
	protected final JTable table;
 | 
			
		||||
	protected final SelectionTableModel tableModel;
 | 
			
		||||
	private final JLabel selectedCountLabel;
 | 
			
		||||
 | 
			
		||||
	protected final boolean[] selected;
 | 
			
		||||
@ -42,7 +42,7 @@ public class CSVExportPanel<T extends UnitValue> extends JPanel {
 | 
			
		||||
 | 
			
		||||
	protected final CsvOptionPanel csvOptions;
 | 
			
		||||
 | 
			
		||||
	public CSVExportPanel(T[] types, boolean[] selected, CsvOptionPanel csvOptions, Component... extraComponents) {
 | 
			
		||||
	public CSVExportPanel(T[] types, boolean[] selected, CsvOptionPanel csvOptions, boolean separateRowForTable, Component... extraComponents) {
 | 
			
		||||
		super(new MigLayout("fill, flowy"));
 | 
			
		||||
 | 
			
		||||
		this.types = types;
 | 
			
		||||
@ -59,39 +59,9 @@ public class CSVExportPanel<T extends UnitValue> extends JPanel {
 | 
			
		||||
		JButton button;
 | 
			
		||||
 | 
			
		||||
		// Set up the variable selection table
 | 
			
		||||
		tableModel = new SelectionTableModel();
 | 
			
		||||
		tableModel = createTableModel();
 | 
			
		||||
		table = new JTable(tableModel);
 | 
			
		||||
		table.setDefaultRenderer(Object.class,
 | 
			
		||||
				new SelectionBackgroundCellRenderer(table.getDefaultRenderer(Object.class)));
 | 
			
		||||
		table.setDefaultRenderer(Boolean.class,
 | 
			
		||||
				new SelectionBackgroundCellRenderer(table.getDefaultRenderer(Boolean.class)));
 | 
			
		||||
		table.setRowSelectionAllowed(false);
 | 
			
		||||
		table.setColumnSelectionAllowed(false);
 | 
			
		||||
 | 
			
		||||
		table.setDefaultEditor(Unit.class, new UnitCellEditor() {
 | 
			
		||||
			private static final long serialVersionUID = 1088570433902420935L;
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
			protected UnitGroup getUnitGroup(Unit value, int row, int column) {
 | 
			
		||||
				return types[row].getUnitGroup();
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		// Set column widths
 | 
			
		||||
		TableColumnModel columnModel = table.getColumnModel();
 | 
			
		||||
		TableColumn col = columnModel.getColumn(0);
 | 
			
		||||
		int w = table.getRowHeight();
 | 
			
		||||
		col.setMinWidth(w);
 | 
			
		||||
		col.setPreferredWidth(w);
 | 
			
		||||
		col.setMaxWidth(w);
 | 
			
		||||
 | 
			
		||||
		col = columnModel.getColumn(1);
 | 
			
		||||
		col.setPreferredWidth(200);
 | 
			
		||||
 | 
			
		||||
		col = columnModel.getColumn(2);
 | 
			
		||||
		col.setPreferredWidth(100);
 | 
			
		||||
 | 
			
		||||
		table.addMouseListener(new GUIUtil.BooleanTableClickListener(table));
 | 
			
		||||
		initializeTable(types);
 | 
			
		||||
 | 
			
		||||
		// Add table
 | 
			
		||||
		panel = new JPanel(new MigLayout("fill"));
 | 
			
		||||
@ -124,22 +94,78 @@ public class CSVExportPanel<T extends UnitValue> extends JPanel {
 | 
			
		||||
		updateSelectedCount();
 | 
			
		||||
		panel.add(selectedCountLabel);
 | 
			
		||||
 | 
			
		||||
		if (separateRowForTable) {
 | 
			
		||||
			this.add(panel, "spanx, grow 100, wrap");
 | 
			
		||||
		} else {
 | 
			
		||||
			this.add(panel, "grow 100, wrap");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Add CSV options
 | 
			
		||||
		if (separateRowForTable) {
 | 
			
		||||
			this.add(csvOptions, "grow 1");
 | 
			
		||||
		} else {
 | 
			
		||||
			this.add(csvOptions, "spany, split, growx 1");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//// Add extra widgets
 | 
			
		||||
		if (extraComponents != null) {
 | 
			
		||||
			for (Component c : extraComponents) {
 | 
			
		||||
				if (separateRowForTable) {
 | 
			
		||||
					this.add(c, "grow 1");
 | 
			
		||||
				} else {
 | 
			
		||||
					this.add(c, "spany, split, growx 1");
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Space-filling panel
 | 
			
		||||
		if (!separateRowForTable) {
 | 
			
		||||
			panel = new JPanel();
 | 
			
		||||
			this.add(panel, "width 1, height 1, grow 1");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public CSVExportPanel(T[] types, boolean[] selected, CsvOptionPanel csvOptions, Component... extraComponents) {
 | 
			
		||||
		this(types, selected, csvOptions, false, extraComponents);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected SelectionTableModel createTableModel() {
 | 
			
		||||
		return new SelectionTableModel();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected void initializeTable(T[] types) {
 | 
			
		||||
		table.setDefaultRenderer(Object.class,
 | 
			
		||||
				new SelectionBackgroundCellRenderer(table.getDefaultRenderer(Object.class)));
 | 
			
		||||
		table.setDefaultRenderer(Boolean.class,
 | 
			
		||||
				new SelectionBackgroundCellRenderer(table.getDefaultRenderer(Boolean.class)));
 | 
			
		||||
		table.setRowSelectionAllowed(false);
 | 
			
		||||
		table.setColumnSelectionAllowed(false);
 | 
			
		||||
 | 
			
		||||
		table.setDefaultEditor(Unit.class, new UnitCellEditor() {
 | 
			
		||||
			private static final long serialVersionUID = 1088570433902420935L;
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
			protected UnitGroup getUnitGroup(Unit value, int row, int column) {
 | 
			
		||||
				return types[row].getUnitGroup();
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		// Set column widths
 | 
			
		||||
		TableColumnModel columnModel = table.getColumnModel();
 | 
			
		||||
		TableColumn col = columnModel.getColumn(0);
 | 
			
		||||
		int w = table.getRowHeight();
 | 
			
		||||
		col.setMinWidth(w);
 | 
			
		||||
		col.setPreferredWidth(w);
 | 
			
		||||
		col.setMaxWidth(w);
 | 
			
		||||
 | 
			
		||||
		col = columnModel.getColumn(1);
 | 
			
		||||
		col.setPreferredWidth(200);
 | 
			
		||||
 | 
			
		||||
		col = columnModel.getColumn(2);
 | 
			
		||||
		col.setPreferredWidth(100);
 | 
			
		||||
 | 
			
		||||
		table.addMouseListener(new GUIUtil.BooleanTableClickListener(table));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean doExport() {
 | 
			
		||||
		throw new RuntimeException("Not implemented");
 | 
			
		||||
@ -171,11 +197,11 @@ public class CSVExportPanel<T extends UnitValue> extends JPanel {
 | 
			
		||||
	/**
 | 
			
		||||
	 * The table model for the variable selection.
 | 
			
		||||
	 */
 | 
			
		||||
	private class SelectionTableModel extends AbstractTableModel {
 | 
			
		||||
	protected class SelectionTableModel extends AbstractTableModel {
 | 
			
		||||
		private static final long serialVersionUID = 493067422917621072L;
 | 
			
		||||
		private static final int SELECTED = 0;
 | 
			
		||||
		private static final int NAME = 1;
 | 
			
		||||
		private static final int UNIT = 2;
 | 
			
		||||
		protected static final int SELECTED = 0;
 | 
			
		||||
		protected static final int NAME = 1;
 | 
			
		||||
		protected static final int UNIT = 2;
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public int getColumnCount() {
 | 
			
		||||
@ -199,7 +225,6 @@ public class CSVExportPanel<T extends UnitValue> extends JPanel {
 | 
			
		||||
						trans.get("SimExpPan.Col.Unit");
 | 
			
		||||
				default -> throw new IndexOutOfBoundsException("column=" + column);
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
@ -214,14 +239,12 @@ public class CSVExportPanel<T extends UnitValue> extends JPanel {
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Object getValueAt(int row, int column) {
 | 
			
		||||
 | 
			
		||||
			return switch (column) {
 | 
			
		||||
				case SELECTED -> selected[row];
 | 
			
		||||
				case NAME -> types[row];
 | 
			
		||||
				case UNIT -> units[row];
 | 
			
		||||
				default -> throw new IndexOutOfBoundsException("column=" + column);
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
@ -243,7 +266,6 @@ public class CSVExportPanel<T extends UnitValue> extends JPanel {
 | 
			
		||||
				default:
 | 
			
		||||
					throw new IndexOutOfBoundsException("column=" + column);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user