001package jmri.jmrit.logixng.tools.swing; 002 003import java.awt.Component; 004import java.awt.event.ActionEvent; 005import java.awt.event.ActionListener; 006import java.util.*; 007 008import javax.swing.*; 009import javax.swing.table.AbstractTableModel; 010import javax.swing.table.DefaultTableCellRenderer; 011import javax.swing.table.TableCellEditor; 012 013import jmri.jmrit.logixng.Module; 014import jmri.jmrit.logixng.Module.Parameter; 015import jmri.jmrit.logixng.Module.ParameterData; 016import jmri.jmrit.logixng.Module.ReturnValueType; 017import jmri.jmrit.logixng.SymbolTable.InitialValueType; 018import jmri.util.swing.JComboBoxUtil; 019 020/** 021 * Table model for CallModule parameters 022 * @author Daniel Bergqvist Copyright 2020 023 */ 024public class CallModuleParameterTableModel extends AbstractTableModel { 025 026 public static final int COLUMN_NAME = 0; 027 public static final int COLUMN_INPUT_TYPE = 1; 028 public static final int COLUMN_INPUT_DATA = 2; 029 public static final int COLUMN_OUTPUT_TYPE = 3; 030 public static final int COLUMN_OUTPUT_DATA = 4; 031 032 private final List<ParameterData> _parameterData = new ArrayList<>(); 033 034 035 public CallModuleParameterTableModel(Module module, List<ParameterData> parameterData) { 036 if (module != null) { 037 Map<String, ParameterData> parameterDataMap = new HashMap<>(); 038 for (ParameterData pd : parameterData) { 039 parameterDataMap.put(pd._name, new ParameterData(pd)); 040 } 041 for (Parameter p : module.getParameters()) { 042 if (parameterDataMap.containsKey(p.getName())) { 043 _parameterData.add(parameterDataMap.get(p.getName())); 044 } else { 045 _parameterData.add(new ParameterData( 046 p.getName(), InitialValueType.None, "", 047 ReturnValueType.None, "")); 048 } 049 } 050 } 051 } 052 053 /** {@inheritDoc} */ 054 @Override 055 public int getRowCount() { 056 return _parameterData.size(); 057 } 058 059 /** {@inheritDoc} */ 060 @Override 061 public int getColumnCount() { 062 return 5; 063 } 064 065 /** {@inheritDoc} */ 066 @Override 067 public String getColumnName(int col) { 068 switch (col) { 069 case COLUMN_NAME: 070 return Bundle.getMessage("ColumnParameterName"); 071 case COLUMN_INPUT_TYPE: 072 return Bundle.getMessage("ColumnInputParameterType"); 073 case COLUMN_INPUT_DATA: 074 return Bundle.getMessage("ColumnInputParameterData"); 075 case COLUMN_OUTPUT_TYPE: 076 return Bundle.getMessage("ColumnOutputParameterType"); 077 case COLUMN_OUTPUT_DATA: 078 return Bundle.getMessage("ColumnOutputParameterData"); 079 default: 080 throw new IllegalArgumentException("Invalid column"); 081 } 082 } 083 084 /** {@inheritDoc} */ 085 @Override 086 public Class<?> getColumnClass(int col) { 087 switch (col) { 088 case COLUMN_INPUT_TYPE: 089 return InitialValueType.class; 090 case COLUMN_OUTPUT_TYPE: 091 return ReturnValueType.class; 092 case COLUMN_NAME: 093 case COLUMN_INPUT_DATA: 094 case COLUMN_OUTPUT_DATA: 095 return String.class; 096 default: 097 throw new IllegalArgumentException("Invalid column"); 098 } 099 } 100 101 /** {@inheritDoc} */ 102 @Override 103 public boolean isCellEditable(int row, int col) { 104 return col != COLUMN_NAME; 105 } 106 107 /** {@inheritDoc} */ 108 @Override 109 public void setValueAt(Object value, int rowIndex, int columnIndex) { 110 ParameterData variable = _parameterData.get(rowIndex); 111 112 switch (columnIndex) { 113 case COLUMN_NAME: 114 variable._name = (String) value; 115 break; 116 case COLUMN_INPUT_TYPE: 117 variable._initialValueType = (InitialValueType) value; 118 break; 119 case COLUMN_INPUT_DATA: 120 variable._initialValueData = (String) value; 121 break; 122 case COLUMN_OUTPUT_TYPE: 123 variable._returnValueType = (ReturnValueType) value; 124 break; 125 case COLUMN_OUTPUT_DATA: 126 variable._returnValueData = (String) value; 127 break; 128 default: 129 throw new IllegalArgumentException("Invalid column"); 130 } 131 } 132 133 /** {@inheritDoc} */ 134 @Override 135 public Object getValueAt(int rowIndex, int columnIndex) { 136 if (rowIndex >= _parameterData.size()) throw new IllegalArgumentException("Invalid row"); 137 138 switch (columnIndex) { 139 case COLUMN_NAME: 140 return _parameterData.get(rowIndex).getName(); 141 case COLUMN_INPUT_TYPE: 142 return _parameterData.get(rowIndex).getInitialValueType(); 143 case COLUMN_INPUT_DATA: 144 return _parameterData.get(rowIndex).getInitialValueData(); 145 case COLUMN_OUTPUT_TYPE: 146 return _parameterData.get(rowIndex).getReturnValueType(); 147 case COLUMN_OUTPUT_DATA: 148 return _parameterData.get(rowIndex).getReturnValueData(); 149 default: 150 throw new IllegalArgumentException("Invalid column"); 151 } 152 } 153 154 public void setColumnsForComboBoxes(JTable table) { 155 JComboBox<InitialValueType> initValueComboBox = new JComboBox<>(); 156 JComboBox<ReturnValueType> returnValueComboBox = new JComboBox<>(); 157 table.setRowHeight(initValueComboBox.getPreferredSize().height); 158 table.getColumnModel().getColumn(COLUMN_INPUT_TYPE) 159 .setPreferredWidth((initValueComboBox.getPreferredSize().width) + 4); 160 table.getColumnModel().getColumn(COLUMN_OUTPUT_TYPE) 161 .setPreferredWidth((returnValueComboBox.getPreferredSize().width) + 4); 162 } 163 164 public void add() { 165 int row = _parameterData.size(); 166 _parameterData.add(new ParameterData("", InitialValueType.None, "", ReturnValueType.None, "")); 167 fireTableRowsInserted(row, row); 168 } 169 170 public List<ParameterData> getParameters() { 171 return _parameterData; 172 } 173 174 175 public static class TypeCellRenderer extends DefaultTableCellRenderer { 176 177 @Override 178 public Component getTableCellRendererComponent(JTable table, Object value, 179 boolean isSelected, boolean hasFocus, int row, int column) { 180 181 if (column == COLUMN_INPUT_TYPE) { 182 if (value == null) value = InitialValueType.None; 183 184 if (! (value instanceof InitialValueType)) { 185 throw new IllegalArgumentException("value is not an InitialValueType: " + value.getClass().getName()); 186 } 187 setText(((InitialValueType) value).toString()); 188 } 189 else if (column == COLUMN_OUTPUT_TYPE) { 190 if (value == null) value = ReturnValueType.None; 191 192 if (! (value instanceof ReturnValueType)) { 193 throw new IllegalArgumentException("value is not an ReturnValueType: " + value.getClass().getName()); 194 } 195 setText(((ReturnValueType) value).getDescr()); 196 } else { 197 throw new RuntimeException("Unknown column: "+Integer.toString(column)); 198 } 199 return this; 200 } 201 } 202 203 204 public static class InitialValueCellEditor extends AbstractCellEditor 205 implements TableCellEditor, ActionListener { 206 207 private InitialValueType _initialValueType; 208 209 @Override 210 public Object getCellEditorValue() { 211 return this._initialValueType; 212 } 213 214 @Override 215 public Component getTableCellEditorComponent(JTable table, Object value, 216 boolean isSelected, int row, int column) { 217 218 if (value == null) value = InitialValueType.None; 219 220 if (! (value instanceof InitialValueType)) { 221 throw new IllegalArgumentException("value is not an InitialValueType: " + value.getClass().getName()); 222 } 223 224 JComboBox<InitialValueType> initialValueTypeComboBox = new JComboBox<>(); 225 226 for (InitialValueType type : InitialValueType.values()) { 227 if (type.isValidAsParameter()) initialValueTypeComboBox.addItem(type); 228 } 229 JComboBoxUtil.setupComboBoxMaxRows(initialValueTypeComboBox); 230 231 initialValueTypeComboBox.setSelectedItem(value); 232 initialValueTypeComboBox.addActionListener(this); 233 234 return initialValueTypeComboBox; 235 } 236 237 @Override 238 @SuppressWarnings("unchecked") // Not possible to check that event.getSource() is instanceof JComboBox<InitialValueType> 239 public void actionPerformed(ActionEvent event) { 240 if (! (event.getSource() instanceof JComboBox)) { 241 throw new IllegalArgumentException("value is not an JComboBox: " + event.getSource().getClass().getName()); 242 } 243 JComboBox<InitialValueType> initialValueTypeComboBox = 244 (JComboBox<InitialValueType>) event.getSource(); 245 _initialValueType = initialValueTypeComboBox.getItemAt(initialValueTypeComboBox.getSelectedIndex()); 246 247 } 248 249 } 250 251 252 public static class ReturnValueCellEditor extends AbstractCellEditor 253 implements TableCellEditor, ActionListener { 254 255 private ReturnValueType _returnValueType; 256 257 @Override 258 public Object getCellEditorValue() { 259 return this._returnValueType; 260 } 261 262 @Override 263 public Component getTableCellEditorComponent(JTable table, Object value, 264 boolean isSelected, int row, int column) { 265 266 if (value == null) value = ReturnValueType.None; 267 268 if (! (value instanceof ReturnValueType)) { 269 throw new IllegalArgumentException("value is not an ReturnValueType: " + value.getClass().getName()); 270 } 271 272 JComboBox<ReturnValueType> returnValueTypeComboBox = new JComboBox<>(); 273 274 for (ReturnValueType type : ReturnValueType.values()) { 275 returnValueTypeComboBox.addItem(type); 276 } 277 JComboBoxUtil.setupComboBoxMaxRows(returnValueTypeComboBox); 278 279 returnValueTypeComboBox.setSelectedItem(value); 280 returnValueTypeComboBox.addActionListener(this); 281 282 return returnValueTypeComboBox; 283 } 284 285 @Override 286 @SuppressWarnings("unchecked") // Not possible to check that event.getSource() is instanceof JComboBox<ReturnValueType> 287 public void actionPerformed(ActionEvent event) { 288 if (! (event.getSource() instanceof JComboBox)) { 289 throw new IllegalArgumentException("value is not an JComboBox: " + event.getSource().getClass().getName()); 290 } 291 JComboBox<ReturnValueType> returnValueTypeComboBox = 292 (JComboBox<ReturnValueType>) event.getSource(); 293 _returnValueType = returnValueTypeComboBox.getItemAt(returnValueTypeComboBox.getSelectedIndex()); 294 295 } 296 297 } 298 299}