diff --git a/core/src/main/java/info/openrocket/core/simulation/FlightDataType.java b/core/src/main/java/info/openrocket/core/simulation/FlightDataType.java index 8a59ea772..91744034e 100644 --- a/core/src/main/java/info/openrocket/core/simulation/FlightDataType.java +++ b/core/src/main/java/info/openrocket/core/simulation/FlightDataType.java @@ -5,6 +5,7 @@ import java.util.Locale; import java.util.Map; import info.openrocket.core.util.Groupable; +import info.openrocket.core.util.UnitValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +34,7 @@ import info.openrocket.core.util.StringUtils; * * @author Sampo Niskanen */ -public class FlightDataType implements Comparable, Groupable { +public class FlightDataType implements Comparable, Groupable, UnitValue { private static final Translator trans = Application.getTranslator(); private static final Logger log = LoggerFactory.getLogger(FlightDataType.class); diff --git a/core/src/main/java/info/openrocket/core/util/UnitValue.java b/core/src/main/java/info/openrocket/core/util/UnitValue.java new file mode 100644 index 000000000..dc3c49476 --- /dev/null +++ b/core/src/main/java/info/openrocket/core/util/UnitValue.java @@ -0,0 +1,11 @@ +package info.openrocket.core.util; + +import info.openrocket.core.unit.UnitGroup; + +public interface UnitValue { + /** + * Returns the unit group that this value belongs to. + * @return the unit group + */ + UnitGroup getUnitGroup(); +} diff --git a/swing/src/main/java/info/openrocket/swing/gui/simulation/SimulationConfigDialog.java b/swing/src/main/java/info/openrocket/swing/gui/simulation/SimulationConfigDialog.java index b3140e4e7..61391be72 100644 --- a/swing/src/main/java/info/openrocket/swing/gui/simulation/SimulationConfigDialog.java +++ b/swing/src/main/java/info/openrocket/swing/gui/simulation/SimulationConfigDialog.java @@ -132,7 +132,7 @@ public class SimulationConfigDialog extends JDialog { //// Export data if (hasData) { - this.exportTab = new SimulationExportPanel(simulationList[0]); + this.exportTab = SimulationExportPanel.create(simulationList[0]); } else { this.exportTab = null; } diff --git a/swing/src/main/java/info/openrocket/swing/gui/simulation/SimulationExportPanel.java b/swing/src/main/java/info/openrocket/swing/gui/simulation/SimulationExportPanel.java index 2ebac6f89..73470eec9 100644 --- a/swing/src/main/java/info/openrocket/swing/gui/simulation/SimulationExportPanel.java +++ b/swing/src/main/java/info/openrocket/swing/gui/simulation/SimulationExportPanel.java @@ -1,27 +1,16 @@ package info.openrocket.swing.gui.simulation; import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import javax.swing.BorderFactory; -import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFileChooser; -import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; import javax.swing.SwingUtilities; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableColumnModel; import info.openrocket.core.document.Simulation; import info.openrocket.core.l10n.Translator; @@ -30,19 +19,17 @@ import info.openrocket.core.simulation.FlightDataBranch; import info.openrocket.core.simulation.FlightDataType; import info.openrocket.core.startup.Application; import info.openrocket.core.unit.Unit; -import info.openrocket.core.unit.UnitGroup; +import info.openrocket.swing.gui.widgets.CSVExportPanel; import net.miginfocom.swing.MigLayout; import info.openrocket.swing.gui.components.CsvOptionPanel; -import info.openrocket.swing.gui.components.UnitCellEditor; import info.openrocket.swing.gui.plot.Util; import info.openrocket.swing.gui.util.FileHelper; -import info.openrocket.swing.gui.util.GUIUtil; import info.openrocket.swing.gui.util.SaveCSVWorker; import info.openrocket.swing.gui.util.SwingPreferences; import info.openrocket.swing.gui.widgets.SaveFileChooser; -public class SimulationExportPanel extends JPanel { +public class SimulationExportPanel extends CSVExportPanel { private static final long serialVersionUID = 3423905472892675964L; private static final String SPACE = "SPACE"; @@ -52,172 +39,73 @@ public class SimulationExportPanel extends JPanel { private static final int OPTION_SIMULATION_COMMENTS = 0; private static final int OPTION_FIELD_DESCRIPTIONS = 1; private static final int OPTION_FLIGHT_EVENTS = 2; - - private final JTable table; - private final SelectionTableModel tableModel; - private final JLabel selectedCountLabel; - + private final Simulation simulation; private FlightDataBranch branch; - private final boolean[] selected; - private final FlightDataType[] types; - private final Unit[] units; - private final CsvOptionPanel csvOptions; - - - public SimulationExportPanel(Simulation sim) { - super(new MigLayout("fill, flowy")); - - JPanel panel; - JButton button; - - this.simulation = sim; - + private SimulationExportPanel(Simulation simulation, FlightDataBranch branch, FlightDataType[] types, + boolean[] selected, CsvOptionPanel csvOptions, Component... extraComponents) { + super(types, selected, csvOptions, extraComponents); + this.simulation = simulation; + this.branch = branch; + } + + public static SimulationExportPanel create(Simulation simulation) { final FlightData data = simulation.getSimulatedData(); - + // Check that data exists if (data == null || data.getBranchCount() == 0 || data.getBranch(0).getTypes().length == 0) { throw new IllegalArgumentException("No data for panel"); } - - - // Create the data model - branch = data.getBranch(0); - - types = branch.getTypes(); - - selected = new boolean[types.length]; - units = new Unit[types.length]; - for (int i = 0; i < types.length; i++) { - selected[i] = ((SwingPreferences) Application.getPreferences()).isExportSelected(types[i]); - units[i] = types[i].getUnitGroup().getDefaultUnit(); - } - - - //// Create the panel - - - // Set up the variable selection table - tableModel = new SelectionTableModel(); - 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)); - - // Add table - panel = new JPanel(new MigLayout("fill")); - panel.setBorder(BorderFactory.createTitledBorder(trans.get("SimExpPan.border.Vartoexport"))); - - panel.add(new JScrollPane(table), "wmin 300lp, width 300lp, height 1, grow 100, wrap"); - - // Select all/none buttons - button = new JButton(trans.get("SimExpPan.but.Selectall")); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - tableModel.selectAll(); - } - }); - panel.add(button, "split 2, growx 1, sizegroup selectbutton"); - - button = new JButton(trans.get("SimExpPan.but.Selectnone")); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - tableModel.selectNone(); - } - }); - panel.add(button, "growx 1, sizegroup selectbutton, wrap"); - - - selectedCountLabel = new JLabel(); - updateSelectedCount(); - panel.add(selectedCountLabel); - - this.add(panel, "grow 100, wrap"); - - - // These need to be in the order of the OPTIONS_XXX indices - csvOptions = new CsvOptionPanel(SimulationExportPanel.class, + // Create the data model + FlightDataBranch branch = data.getBranch(0); + FlightDataType[] types = branch.getTypes(); + + // Get the selected types from the preferences + final boolean[] selected = new boolean[types.length]; + for (int i = 0; i < types.length; i++) { + selected[i] = ((SwingPreferences) Application.getPreferences()).isFlightDataTypeExportSelected(types[i]); + } + + CsvOptionPanel csvOptions = new CsvOptionPanel(SimulationExportPanel.class, trans.get("SimExpPan.checkbox.Includesimudesc"), trans.get("SimExpPan.checkbox.ttip.Includesimudesc"), trans.get("SimExpPan.checkbox.Includefielddesc"), trans.get("SimExpPan.checkbox.ttip.Includefielddesc"), trans.get("SimExpPan.checkbox.Incflightevents"), trans.get("SimExpPan.checkbox.ttip.Incflightevents")); - - this.add(csvOptions, "spany, split, growx 1"); - + //// Add series selection box - ArrayList stages = new ArrayList<>(); - stages.addAll(Util.generateSeriesLabels(simulation)); - - final JComboBox stageSelection = new JComboBox<>(stages.toArray(new String[0])); - stageSelection.addItemListener(new ItemListener() { - - @Override - public void itemStateChanged(ItemEvent e) { - int selectedStage = stageSelection.getSelectedIndex(); - branch = data.getBranch(selectedStage); - } - - }); + ArrayList stages = new ArrayList<>(Util.generateSeriesLabels(simulation)); if (stages.size() > 1) { + final JComboBox stageSelection = new JComboBox<>(stages.toArray(new String[0])); + // Only show the combo box if there are at least 2 entries (ie, "Main", and one other one JPanel stagePanel = new JPanel(new MigLayout("fill")); stagePanel.setBorder(BorderFactory.createTitledBorder(trans.get("SimExpPan.border.Stage"))); stagePanel.add(stageSelection, "growx"); - this.add(stagePanel, "spany, split, growx 1"); + + SimulationExportPanel panel = new SimulationExportPanel(simulation, branch, types, selected, csvOptions, stagePanel); + + stageSelection.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + int selectedStage = stageSelection.getSelectedIndex(); + panel.branch = data.getBranch(selectedStage); + } + + }); + return panel; } - - // Space-filling panel - panel = new JPanel(); - this.add(panel, "width 1, height 1, grow 1"); - - /* - // Export button - button = new JButton(trans.get("SimExpPan.but.Exporttofile")); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - doExport(); - } - }); - this.add(button, "gapbottom para, gapright para, right"); - */ + + return new SimulationExportPanel(simulation, branch, types, selected, csvOptions); } - + + @Override public boolean doExport() { JFileChooser chooser = new SaveFileChooser(); chooser.setFileFilter(FileHelper.CSV_FILTER); @@ -249,7 +137,7 @@ public class SimulationExportPanel extends JPanel { int n = 0; ((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory()); for (int i = 0; i < selected.length; i++) { - ((SwingPreferences) Application.getPreferences()).setExportSelected(types[i], selected[i]); + ((SwingPreferences) Application.getPreferences()).setFlightDataTypeExportSelected(types[i], selected[i]); if (selected[i]) n++; } @@ -279,167 +167,4 @@ public class SimulationExportPanel extends JPanel { return true; } - - - private void updateSelectedCount() { - int total = selected.length; - int n = 0; - String str; - - for (boolean b : selected) { - if (b) - n++; - } - - if (n == 1) { - //// Exporting 1 variable out of - str = trans.get("SimExpPan.ExportingVar.desc1") + " " + total + "."; - } else { - //// Exporting - //// variables out of - str = trans.get("SimExpPan.ExportingVar.desc2") + " " + n + " " + - trans.get("SimExpPan.ExportingVar.desc3") + " " + total + "."; - } - - selectedCountLabel.setText(str); - } - - - - /** - * A table cell renderer that uses another renderer and sets the background and - * foreground of the returned component based on the selection of the variable. - */ - private class SelectionBackgroundCellRenderer implements TableCellRenderer { - - private final TableCellRenderer renderer; - - public SelectionBackgroundCellRenderer(TableCellRenderer renderer) { - this.renderer = renderer; - } - - @Override - public Component getTableCellRendererComponent(JTable myTable, Object value, - boolean isSelected, boolean hasFocus, int row, int column) { - - Component component = renderer.getTableCellRendererComponent(myTable, - value, isSelected, hasFocus, row, column); - - if (selected[row]) { - component.setBackground(myTable.getSelectionBackground()); - component.setForeground(myTable.getSelectionForeground()); - } else { - component.setBackground(myTable.getBackground()); - component.setForeground(myTable.getForeground()); - } - - return component; - } - - } - - - /** - * The table model for the variable selection. - */ - private 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; - - @Override - public int getColumnCount() { - return 3; - } - - @Override - public int getRowCount() { - return types.length; - } - - @Override - public String getColumnName(int column) { - return switch (column) { - case SELECTED -> ""; - case NAME -> - //// Variable - trans.get("SimExpPan.Col.Variable"); - case UNIT -> - //// Unit - trans.get("SimExpPan.Col.Unit"); - default -> throw new IndexOutOfBoundsException("column=" + column); - }; - - } - - @Override - public Class getColumnClass(int column) { - return switch (column) { - case SELECTED -> Boolean.class; - case NAME -> FlightDataType.class; - case UNIT -> Unit.class; - default -> throw new IndexOutOfBoundsException("column=" + column); - }; - } - - @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 - public void setValueAt(Object value, int row, int column) { - - switch (column) { - case SELECTED: - selected[row] = (Boolean) value; - this.fireTableRowsUpdated(row, row); - updateSelectedCount(); - break; - - case NAME: - break; - - case UNIT: - units[row] = (Unit) value; - break; - - default: - throw new IndexOutOfBoundsException("column=" + column); - } - - } - - @Override - public boolean isCellEditable(int row, int column) { - return switch (column) { - case SELECTED -> true; - case NAME -> false; - case UNIT -> types[row].getUnitGroup().getUnitCount() > 1; - default -> throw new IndexOutOfBoundsException("column=" + column); - }; - } - - public void selectAll() { - Arrays.fill(selected, true); - updateSelectedCount(); - this.fireTableDataChanged(); - } - - public void selectNone() { - Arrays.fill(selected, false); - updateSelectedCount(); - this.fireTableDataChanged(); - } - - } - } diff --git a/swing/src/main/java/info/openrocket/swing/gui/util/SwingPreferences.java b/swing/src/main/java/info/openrocket/swing/gui/util/SwingPreferences.java index 200113c95..bafb9d346 100644 --- a/swing/src/main/java/info/openrocket/swing/gui/util/SwingPreferences.java +++ b/swing/src/main/java/info/openrocket/swing/gui/util/SwingPreferences.java @@ -636,12 +636,12 @@ public class SwingPreferences extends ApplicationPreferences implements Simulati ///////// Export variables - public boolean isExportSelected(FlightDataType type) { + public boolean isFlightDataTypeExportSelected(FlightDataType type) { Preferences prefs = PREFNODE.node("exports"); return prefs.getBoolean(type.getName(), false); } - public void setExportSelected(FlightDataType type, boolean selected) { + public void setFlightDataTypeExportSelected(FlightDataType type, boolean selected) { Preferences prefs = PREFNODE.node("exports"); prefs.putBoolean(type.getName(), selected); } diff --git a/swing/src/main/java/info/openrocket/swing/gui/widgets/CSVExportPanel.java b/swing/src/main/java/info/openrocket/swing/gui/widgets/CSVExportPanel.java new file mode 100644 index 000000000..d9c3a5001 --- /dev/null +++ b/swing/src/main/java/info/openrocket/swing/gui/widgets/CSVExportPanel.java @@ -0,0 +1,313 @@ +package info.openrocket.swing.gui.widgets; + +import info.openrocket.core.l10n.Translator; +import info.openrocket.core.startup.Application; +import info.openrocket.core.unit.Unit; +import info.openrocket.core.unit.UnitGroup; +import info.openrocket.core.util.UnitValue; +import info.openrocket.swing.gui.components.CsvOptionPanel; +import info.openrocket.swing.gui.components.UnitCellEditor; +import info.openrocket.swing.gui.util.GUIUtil; +import net.miginfocom.swing.MigLayout; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; + +public class CSVExportPanel extends JPanel { + private static final Translator trans = Application.getTranslator(); + + private final JTable table; + private final SelectionTableModel tableModel; + private final JLabel selectedCountLabel; + + protected final boolean[] selected; + protected final T[] types; + protected final Unit[] units; + + protected final CsvOptionPanel csvOptions; + + public CSVExportPanel(T[] types, boolean[] selected, CsvOptionPanel csvOptions, Component... extraComponents) { + super(new MigLayout("fill, flowy")); + + this.types = types; + this.selected = selected; + this.csvOptions = csvOptions; + + this.units = new Unit[types.length]; + for (int i = 0; i < types.length; i++) { + units[i] = types[i].getUnitGroup().getDefaultUnit(); + } + + //// Create the panel + JPanel panel; + JButton button; + + // Set up the variable selection table + tableModel = new SelectionTableModel(); + 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)); + + // Add table + panel = new JPanel(new MigLayout("fill")); + panel.setBorder(BorderFactory.createTitledBorder(trans.get("SimExpPan.border.Vartoexport"))); + + panel.add(new JScrollPane(table), "wmin 300lp, width 300lp, pushy, grow 100, wrap"); + + // Select all/none buttons + button = new JButton(trans.get("SimExpPan.but.Selectall")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + tableModel.selectAll(); + } + }); + panel.add(button, "split 2, growx 1, sizegroup selectbutton"); + + button = new JButton(trans.get("SimExpPan.but.Selectnone")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + tableModel.selectNone(); + } + }); + panel.add(button, "growx 1, sizegroup selectbutton, wrap"); + + + // Exporting xx variables out of yy + selectedCountLabel = new JLabel(); + updateSelectedCount(); + panel.add(selectedCountLabel); + + this.add(panel, "grow 100, wrap"); + + // Add CSV options + this.add(csvOptions, "spany, split, growx 1"); + + //// Add extra widgets + if (extraComponents != null) { + for (Component c : extraComponents) { + this.add(c, "spany, split, growx 1"); + } + } + + // Space-filling panel + panel = new JPanel(); + this.add(panel, "width 1, height 1, grow 1"); + } + + public boolean doExport() { + // TODO: Implement this method + return false; + } + + private void updateSelectedCount() { + int total = selected.length; + int n = 0; + String str; + + for (boolean b : selected) { + if (b) + n++; + } + + if (n == 1) { + //// Exporting 1 variable out of + str = trans.get("SimExpPan.ExportingVar.desc1") + " " + total + "."; + } else { + //// Exporting + //// variables out of + str = trans.get("SimExpPan.ExportingVar.desc2") + " " + n + " " + + trans.get("SimExpPan.ExportingVar.desc3") + " " + total + "."; + } + + selectedCountLabel.setText(str); + } + + /** + * The table model for the variable selection. + */ + private 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; + + @Override + public int getColumnCount() { + return 3; + } + + @Override + public int getRowCount() { + return types.length; + } + + @Override + public String getColumnName(int column) { + return switch (column) { + case SELECTED -> ""; + case NAME -> + //// Variable + trans.get("SimExpPan.Col.Variable"); + case UNIT -> + //// Unit + trans.get("SimExpPan.Col.Unit"); + default -> throw new IndexOutOfBoundsException("column=" + column); + }; + + } + + @Override + public Class getColumnClass(int column) { + return switch (column) { + case SELECTED -> Boolean.class; + case NAME -> new TypeToken(){}.getType().getClass(); + case UNIT -> Unit.class; + default -> throw new IndexOutOfBoundsException("column=" + column); + }; + } + + @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 + public void setValueAt(Object value, int row, int column) { + switch (column) { + case SELECTED: + selected[row] = (Boolean) value; + this.fireTableRowsUpdated(row, row); + updateSelectedCount(); + break; + + case NAME: + break; + + case UNIT: + units[row] = (Unit) value; + break; + + default: + throw new IndexOutOfBoundsException("column=" + column); + } + + } + + @Override + public boolean isCellEditable(int row, int column) { + return switch (column) { + case SELECTED -> true; + case NAME -> false; + case UNIT -> types[row].getUnitGroup().getUnitCount() > 1; + default -> throw new IndexOutOfBoundsException("column=" + column); + }; + } + + public void selectAll() { + Arrays.fill(selected, true); + updateSelectedCount(); + this.fireTableDataChanged(); + } + + public void selectNone() { + Arrays.fill(selected, false); + updateSelectedCount(); + this.fireTableDataChanged(); + } + + } + + /** + * A table cell renderer that uses another renderer and sets the background and + * foreground of the returned component based on the selection of the variable. + */ + private class SelectionBackgroundCellRenderer implements TableCellRenderer { + private final TableCellRenderer renderer; + + public SelectionBackgroundCellRenderer(TableCellRenderer renderer) { + this.renderer = renderer; + } + + @Override + public Component getTableCellRendererComponent(JTable myTable, Object value, + boolean isSelected, boolean hasFocus, int row, int column) { + Component component = renderer.getTableCellRendererComponent(myTable, + value, isSelected, hasFocus, row, column); + + if (selected[row]) { + component.setBackground(myTable.getSelectionBackground()); + component.setForeground(myTable.getSelectionForeground()); + } else { + component.setBackground(myTable.getBackground()); + component.setForeground(myTable.getForeground()); + } + + return component; + } + } + + public abstract static class TypeToken { + private final Type type; + + protected TypeToken(){ + Type superClass = getClass().getGenericSuperclass(); + this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; + } + + public Type getType() { + return type; + } + } +}