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 if (value != null) { 118 variable._initialValueType = (InitialValueType) value; 119 } else { 120 variable._initialValueType = InitialValueType.None; 121 } 122 break; 123 case COLUMN_INPUT_DATA: 124 variable._initialValueData = (String) value; 125 break; 126 case COLUMN_OUTPUT_TYPE: 127 variable._returnValueType = (ReturnValueType) value; 128 break; 129 case COLUMN_OUTPUT_DATA: 130 variable._returnValueData = (String) value; 131 break; 132 default: 133 throw new IllegalArgumentException("Invalid column"); 134 } 135 } 136 137 /** {@inheritDoc} */ 138 @Override 139 public Object getValueAt(int rowIndex, int columnIndex) { 140 if (rowIndex >= _parameterData.size()) throw new IllegalArgumentException("Invalid row"); 141 142 switch (columnIndex) { 143 case COLUMN_NAME: 144 return _parameterData.get(rowIndex).getName(); 145 case COLUMN_INPUT_TYPE: 146 return _parameterData.get(rowIndex).getInitialValueType(); 147 case COLUMN_INPUT_DATA: 148 return _parameterData.get(rowIndex).getInitialValueData(); 149 case COLUMN_OUTPUT_TYPE: 150 return _parameterData.get(rowIndex).getReturnValueType(); 151 case COLUMN_OUTPUT_DATA: 152 return _parameterData.get(rowIndex).getReturnValueData(); 153 default: 154 throw new IllegalArgumentException("Invalid column"); 155 } 156 } 157 158 public void setColumnsForComboBoxes(JTable table) { 159 JComboBox<InitialValueType> initValueComboBox = new JComboBox<>(); 160 JComboBox<ReturnValueType> returnValueComboBox = new JComboBox<>(); 161 table.setRowHeight(initValueComboBox.getPreferredSize().height); 162 table.getColumnModel().getColumn(COLUMN_INPUT_TYPE) 163 .setPreferredWidth((initValueComboBox.getPreferredSize().width) + 4); 164 table.getColumnModel().getColumn(COLUMN_OUTPUT_TYPE) 165 .setPreferredWidth((returnValueComboBox.getPreferredSize().width) + 4); 166 } 167 168 public void add() { 169 int row = _parameterData.size(); 170 _parameterData.add(new ParameterData("", InitialValueType.None, "", ReturnValueType.None, "")); 171 fireTableRowsInserted(row, row); 172 } 173 174 public List<ParameterData> getParameters() { 175 return _parameterData; 176 } 177 178 179 public static class TypeCellRenderer extends DefaultTableCellRenderer { 180 181 @Override 182 public Component getTableCellRendererComponent(JTable table, Object value, 183 boolean isSelected, boolean hasFocus, int row, int column) { 184 185 if (column == COLUMN_INPUT_TYPE) { 186 if (value == null) value = InitialValueType.None; 187 188 if (! (value instanceof InitialValueType)) { 189 throw new IllegalArgumentException("value is not an InitialValueType: " + value.getClass().getName()); 190 } 191 setText(((InitialValueType) value).toString()); 192 } 193 else if (column == COLUMN_OUTPUT_TYPE) { 194 if (value == null) value = ReturnValueType.None; 195 196 if (! (value instanceof ReturnValueType)) { 197 throw new IllegalArgumentException("value is not an ReturnValueType: " + value.getClass().getName()); 198 } 199 setText(((ReturnValueType) value).getDescr()); 200 } else { 201 throw new RuntimeException("Unknown column: "+Integer.toString(column)); 202 } 203 return this; 204 } 205 } 206 207 208 public static class InitialValueCellEditor extends AbstractCellEditor 209 implements TableCellEditor, ActionListener { 210 211 private InitialValueType _initialValueType; 212 213 @Override 214 public Object getCellEditorValue() { 215 return this._initialValueType; 216 } 217 218 @Override 219 public Component getTableCellEditorComponent(JTable table, Object value, 220 boolean isSelected, int row, int column) { 221 222 if (value == null) value = InitialValueType.None; 223 224 if (! (value instanceof InitialValueType)) { 225 throw new IllegalArgumentException("value is not an InitialValueType: " + value.getClass().getName()); 226 } 227 228 JComboBox<InitialValueType> initialValueTypeComboBox = new JComboBox<>(); 229 230 for (InitialValueType type : InitialValueType.values()) { 231 if (type.isValidAsParameter()) initialValueTypeComboBox.addItem(type); 232 } 233 JComboBoxUtil.setupComboBoxMaxRows(initialValueTypeComboBox); 234 235 initialValueTypeComboBox.setSelectedItem(value); 236 initialValueTypeComboBox.addActionListener(this); 237 238 return initialValueTypeComboBox; 239 } 240 241 @Override 242 @SuppressWarnings("unchecked") // Not possible to check that event.getSource() is instanceof JComboBox<InitialValueType> 243 public void actionPerformed(ActionEvent event) { 244 if (! (event.getSource() instanceof JComboBox<?>)) { 245 throw new IllegalArgumentException("value is not an JComboBox: " + event.getSource().getClass().getName()); 246 } 247 JComboBox<InitialValueType> initialValueTypeComboBox = 248 (JComboBox<InitialValueType>) event.getSource(); 249 _initialValueType = initialValueTypeComboBox.getItemAt(initialValueTypeComboBox.getSelectedIndex()); 250 251 } 252 253 } 254 255 256 public static class ReturnValueCellEditor extends AbstractCellEditor 257 implements TableCellEditor, ActionListener { 258 259 private ReturnValueType _returnValueType; 260 261 @Override 262 public Object getCellEditorValue() { 263 return this._returnValueType; 264 } 265 266 @Override 267 public Component getTableCellEditorComponent(JTable table, Object value, 268 boolean isSelected, int row, int column) { 269 270 if (value == null) value = ReturnValueType.None; 271 272 if (! (value instanceof ReturnValueType)) { 273 throw new IllegalArgumentException("value is not an ReturnValueType: " + value.getClass().getName()); 274 } 275 276 JComboBox<ReturnValueType> returnValueTypeComboBox = new JComboBox<>(); 277 278 for (ReturnValueType type : ReturnValueType.values()) { 279 returnValueTypeComboBox.addItem(type); 280 } 281 JComboBoxUtil.setupComboBoxMaxRows(returnValueTypeComboBox); 282 283 returnValueTypeComboBox.setSelectedItem(value); 284 returnValueTypeComboBox.addActionListener(this); 285 286 return returnValueTypeComboBox; 287 } 288 289 @Override 290 @SuppressWarnings("unchecked") // Not possible to check that event.getSource() is instanceof JComboBox<ReturnValueType> 291 public void actionPerformed(ActionEvent event) { 292 if (! (event.getSource() instanceof JComboBox<?>)) { 293 throw new IllegalArgumentException("value is not an JComboBox: " + event.getSource().getClass().getName()); 294 } 295 JComboBox<ReturnValueType> returnValueTypeComboBox = 296 (JComboBox<ReturnValueType>) event.getSource(); 297 _returnValueType = returnValueTypeComboBox.getItemAt(returnValueTypeComboBox.getSelectedIndex()); 298 299 } 300 301 } 302 303}