001package jmri.jmrit.logixng.expressions.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.expressions.LogData; 014import jmri.jmrit.logixng.util.parser.ParserException; 015import jmri.util.swing.JComboBoxUtil; 016 017/** 018 * Table model for LogData 019 * 020 * @author Daniel Bergqvist Copyright 2021 021 */ 022public class LogDataTableModel extends AbstractTableModel { 023 024 // COLUMN_DUMMY is "hidden" but used when the panel is closed to 025 // ensure that the last edited cell is saved. 026 public static final int COLUMN_TYPE = 0; 027 public static final int COLUMN_DATA = 1; 028 public static final int COLUMN_DELETE = 2; 029 public static final int COLUMN_DUMMY = 3; 030 031 private final List<LogData.Data> _dataList = new ArrayList<>(); 032 033 034 public LogDataTableModel(Collection<LogData.Data> namedBeanReference) { 035 if (namedBeanReference != null) _dataList.addAll(namedBeanReference); 036 } 037 038 /** {@inheritDoc} */ 039 @Override 040 public int getRowCount() { 041 return _dataList.size(); 042 } 043 044 /** {@inheritDoc} */ 045 @Override 046 public int getColumnCount() { 047 return COLUMN_DUMMY+1; 048 } 049 050 /** {@inheritDoc} */ 051 @Override 052 public String getColumnName(int col) { 053 switch (col) { 054 case COLUMN_TYPE: 055 return Bundle.getMessage("LogData_ColumnType"); 056 case COLUMN_DATA: 057 return Bundle.getMessage("LogData_ColumnData"); 058 case COLUMN_DELETE: 059 return ""; // no label 060 case COLUMN_DUMMY: 061 return ""; // no label 062 default: 063 throw new IllegalArgumentException("Invalid column"); 064 } 065 } 066 067 /** {@inheritDoc} */ 068 @Override 069 public Class<?> getColumnClass(int col) { 070 switch (col) { 071 case COLUMN_TYPE: 072 return LogData.DataType.class; 073 case COLUMN_DATA: 074 return String.class; 075 case COLUMN_DELETE: 076 return JButton.class; 077 case COLUMN_DUMMY: 078 return String.class; 079 default: 080 throw new IllegalArgumentException("Invalid column"); 081 } 082 } 083 084 /** {@inheritDoc} */ 085 @Override 086 public boolean isCellEditable(int row, int col) { 087 return true; 088 } 089 090 /** {@inheritDoc} */ 091 @Override 092 public void setValueAt(Object value, int rowIndex, int columnIndex) { 093 LogData.Data ref = _dataList.get(rowIndex); 094 095 switch (columnIndex) { 096 case COLUMN_TYPE: 097 LogData.DataType oldType = ref.getDataType(); 098 ref.setDataType((LogData.DataType) value); 099 if (oldType != ref.getDataType()) ref.setData(""); 100 break; 101 case COLUMN_DATA: 102 ref.setData((String) value); 103 break; 104 case COLUMN_DELETE: 105 delete(rowIndex); 106 break; 107 case COLUMN_DUMMY: 108 break; 109 default: 110 throw new IllegalArgumentException("Invalid column"); 111 } 112 } 113 114 /** {@inheritDoc} */ 115 @Override 116 public Object getValueAt(int rowIndex, int columnIndex) { 117 if (rowIndex >= _dataList.size()) throw new IllegalArgumentException("Invalid row"); 118 119 switch (columnIndex) { 120 case COLUMN_TYPE: 121 return _dataList.get(rowIndex).getDataType(); 122 case COLUMN_DATA: 123 return _dataList.get(rowIndex).getData(); 124 case COLUMN_DELETE: 125 return Bundle.getMessage("ButtonDelete"); // NOI18N 126 case COLUMN_DUMMY: 127 return ""; 128 default: 129 throw new IllegalArgumentException("Invalid column"); 130 } 131 } 132 133 public void setColumnsForComboBoxes(JTable table) { 134 JComboBox<LogData.DataType> beanTypeComboBox = new JComboBox<>(); 135 table.setRowHeight(beanTypeComboBox.getPreferredSize().height); 136 table.getColumnModel().getColumn(COLUMN_TYPE) 137 .setPreferredWidth((beanTypeComboBox.getPreferredSize().width) + 4); 138 } 139 140 public void add() { 141 int row = _dataList.size(); 142 try { 143 _dataList.add(new LogData.Data(LogData.DataType.LocalVariable, "")); 144 } catch (ParserException e) { 145 throw new RuntimeException(e); // This should never happen 146 } 147 fireTableRowsInserted(row, row); 148 } 149 150 private void delete(int row) { 151 _dataList.remove(row); 152 fireTableRowsDeleted(row, row); 153 } 154 155 public List<LogData.Data> getDataList() { 156 return _dataList; 157 } 158 159 160 public static class CellRenderer extends DefaultTableCellRenderer { 161 162 @Override 163 public Component getTableCellRendererComponent(JTable table, Object value, 164 boolean isSelected, boolean hasFocus, int row, int column) { 165 166 if (column == COLUMN_TYPE) { 167 if (value == null) value = LogData.DataType.LocalVariable; 168 169 if (! (value instanceof LogData.DataType)) { 170 throw new IllegalArgumentException("value is not an LogData.DataType: " + value.getClass().getName()); 171 } 172 setText(((LogData.DataType) value).toString()); 173 } else { 174 throw new RuntimeException("Unknown column: "+Integer.toString(column)); 175 } 176 return this; 177 } 178 } 179 180 181 public static class DataTypeCellEditor extends AbstractCellEditor 182 implements TableCellEditor, ActionListener { 183 184 private LogData.DataType _beanType; 185 186 @Override 187 public Object getCellEditorValue() { 188 return this._beanType; 189 } 190 191 @Override 192 public Component getTableCellEditorComponent(JTable table, Object value, 193 boolean isSelected, int row, int column) { 194 195 if (value == null) value = LogData.DataType.LocalVariable; 196 197 if (! (value instanceof LogData.DataType)) { 198 throw new IllegalArgumentException("value is not an LogData.DataType: " + value.getClass().getName()); 199 } 200 201 JComboBox<LogData.DataType> returnValueTypeComboBox = new JComboBox<>(); 202 203 for (LogData.DataType type : LogData.DataType.values()) { 204 returnValueTypeComboBox.addItem(type); 205 } 206 JComboBoxUtil.setupComboBoxMaxRows(returnValueTypeComboBox); 207 208 returnValueTypeComboBox.setSelectedItem(value); 209 returnValueTypeComboBox.addActionListener(this); 210 211 return returnValueTypeComboBox; 212 } 213 214 @Override 215 @SuppressWarnings("unchecked") // Not possible to check that event.getSource() is instanceof JComboBox<LogData.DataType> 216 public void actionPerformed(ActionEvent event) { 217 if (! (event.getSource() instanceof JComboBox)) { 218 throw new IllegalArgumentException("value is not an JComboBox: " + event.getSource().getClass().getName()); 219 } 220 JComboBox<LogData.DataType> returnValueTypeComboBox = 221 (JComboBox<LogData.DataType>) event.getSource(); 222 _beanType = returnValueTypeComboBox.getItemAt(returnValueTypeComboBox.getSelectedIndex()); 223 224 } 225 226 } 227 228/* 229 public NamedBeanCellEditor getNamedBeanCellEditor() { 230 return new NamedBeanCellEditor(); 231 } 232 233 234 public class NamedBeanCellEditor extends AbstractCellEditor 235 implements TableCellEditor, ActionListener { 236 237 private String _namedBean; 238 239 @Override 240 public Object getCellEditorValue() { 241 return this._namedBean; 242 } 243 244 @Override 245 public Component getTableCellEditorComponent(JTable table, Object value, 246 boolean isSelected, int row, int column) { 247 248 if ((value != null) && (! (value instanceof String))) { 249 throw new IllegalArgumentException("value is not a String: " + value.getClass().getName()); 250 } 251 252 JComboBox<String> namedBeanComboBox = new JComboBox<>(); 253 SortedSet<? extends NamedBean> set = 254 _dataList.get(row).getDataType().getManager().getNamedBeanSet(); 255 256 String name = _dataList.get(row).getData(); 257 258 if (!set.isEmpty()) { 259 for (NamedBean bean : set) { 260 namedBeanComboBox.addItem(bean.getDisplayName()); 261 262 if (name != null) { 263 if (name.equals(bean.getUserName()) || name.equals(bean.getSystemName())) { 264 namedBeanComboBox.setSelectedItem(bean.getDisplayName()); 265 } 266 } 267 } 268 JComboBoxUtil.setupComboBoxMaxRows(namedBeanComboBox); 269 } else { 270 namedBeanComboBox.addItem(""); 271 } 272 273// namedBeanComboBox.setSelectedItem(value); 274 namedBeanComboBox.addActionListener(this); 275 276 return namedBeanComboBox; 277 } 278 279 @Override 280 @SuppressWarnings("unchecked") // Not possible to check that event.getSource() is instanceof JComboBox<LogData.DataType> 281 public void actionPerformed(ActionEvent event) { 282 if (! (event.getSource() instanceof JComboBox)) { 283 throw new IllegalArgumentException("value is not an JComboBox: " + event.getSource().getClass().getName()); 284 } 285 JComboBox<String> namedBeanComboBox = (JComboBox<String>) event.getSource(); 286 int index = namedBeanComboBox.getSelectedIndex(); 287 _namedBean = (index != -1) ? namedBeanComboBox.getItemAt(index) : null; 288 } 289 290 } 291*/ 292}