001package jmri.jmrit.logixng.actions.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.SymbolTable.InitialValueType;
014import jmri.jmrit.logixng.actions.WebRequest;
015import jmri.util.swing.JComboBoxUtil;
016
017/**
018 * Table model for WebRequest
019 *
020 * @author Daniel Bergqvist Copyright 2021
021 */
022public class WebRequestTableModel 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_NAME = 0;
027    public static final int COLUMN_TYPE = 1;
028    public static final int COLUMN_DATA = 2;
029    public static final int COLUMN_DELETE = 3;
030    public static final int COLUMN_DUMMY = 4;
031
032    private final List<WebRequest.Parameter> _parameterList = new ArrayList<>();
033
034
035    public WebRequestTableModel(Collection<WebRequest.Parameter> namedBeanReference) {
036        if (namedBeanReference != null) _parameterList.addAll(namedBeanReference);
037    }
038
039    /** {@inheritDoc} */
040    @Override
041    public int getRowCount() {
042        return _parameterList.size();
043    }
044
045    /** {@inheritDoc} */
046    @Override
047    public int getColumnCount() {
048        return COLUMN_DUMMY+1;
049    }
050
051    /** {@inheritDoc} */
052    @Override
053    public String getColumnName(int col) {
054        switch (col) {
055            case COLUMN_NAME:
056                return Bundle.getMessage("WebRequest_ColumnName");
057            case COLUMN_TYPE:
058                return Bundle.getMessage("WebRequest_ColumnType");
059            case COLUMN_DATA:
060                return Bundle.getMessage("WebRequest_ColumnData");
061            case COLUMN_DELETE:
062                return "";  // no label
063            case COLUMN_DUMMY:
064                return "";  // no label
065            default:
066                throw new IllegalArgumentException("Invalid column");
067        }
068    }
069
070    /** {@inheritDoc} */
071    @Override
072    public Class<?> getColumnClass(int col) {
073        switch (col) {
074            case COLUMN_NAME:
075                return String.class;
076            case COLUMN_TYPE:
077                return InitialValueType.class;
078            case COLUMN_DATA:
079                return String.class;
080            case COLUMN_DELETE:
081                return JButton.class;
082            case COLUMN_DUMMY:
083                return String.class;
084            default:
085                throw new IllegalArgumentException("Invalid column");
086        }
087    }
088
089    /** {@inheritDoc} */
090    @Override
091    public boolean isCellEditable(int row, int col) {
092        return true;
093    }
094
095    /** {@inheritDoc} */
096    @Override
097    public void setValueAt(Object value, int rowIndex, int columnIndex) {
098        WebRequest.Parameter ref = _parameterList.get(rowIndex);
099
100        switch (columnIndex) {
101            case COLUMN_NAME:
102                ref.setName((String) value);
103                break;
104            case COLUMN_TYPE:
105                if (value != null) {
106                    InitialValueType oldType = ref.getType();
107                    ref.setType((InitialValueType) value);
108                    if (oldType != ref.getType()) ref.setData("");
109                } else {
110                    // This happens if the combo box is open when the user clicks on another cell.
111                    log.debug("Cannot set data type to null");
112                }
113                break;
114            case COLUMN_DATA:
115                ref.setData((String) value);
116                break;
117            case COLUMN_DELETE:
118                delete(rowIndex);
119                break;
120            case COLUMN_DUMMY:
121                break;
122            default:
123                throw new IllegalArgumentException("Invalid column");
124        }
125    }
126
127    /** {@inheritDoc} */
128    @Override
129    public Object getValueAt(int rowIndex, int columnIndex) {
130        if (rowIndex >= _parameterList.size()) throw new IllegalArgumentException("Invalid row");
131
132        switch (columnIndex) {
133            case COLUMN_NAME:
134                return _parameterList.get(rowIndex).getName();
135            case COLUMN_TYPE:
136                return _parameterList.get(rowIndex).getType();
137            case COLUMN_DATA:
138                return _parameterList.get(rowIndex).getData();
139            case COLUMN_DELETE:
140                return Bundle.getMessage("ButtonDelete");  // NOI18N
141            case COLUMN_DUMMY:
142                return "";
143            default:
144                throw new IllegalArgumentException("Invalid column");
145        }
146    }
147
148    public void setColumnsForComboBoxes(JTable table) {
149        JComboBox<InitialValueType> beanTypeComboBox = new JComboBox<>();
150        table.setRowHeight(beanTypeComboBox.getPreferredSize().height);
151        table.getColumnModel().getColumn(COLUMN_TYPE)
152                .setPreferredWidth((beanTypeComboBox.getPreferredSize().width) + 4);
153    }
154
155    public void add() {
156        int row = _parameterList.size();
157        _parameterList.add(new WebRequest.Parameter("", InitialValueType.LocalVariable, ""));
158        fireTableRowsInserted(row, row);
159    }
160
161    private void delete(int row) {
162        _parameterList.remove(row);
163        fireTableRowsDeleted(row, row);
164    }
165
166    public List<WebRequest.Parameter> getDataList() {
167        return _parameterList;
168    }
169
170
171    public static class CellRenderer extends DefaultTableCellRenderer {
172
173        @Override
174        public Component getTableCellRendererComponent(JTable table, Object value,
175                boolean isSelected, boolean hasFocus, int row, int column) {
176
177            if (column == COLUMN_TYPE) {
178                if (value == null) value = InitialValueType.LocalVariable;
179
180                if (! (value instanceof InitialValueType)) {
181                    throw new IllegalArgumentException("value is not an InitialValueType: " + value.getClass().getName());
182                }
183                setText(((InitialValueType) value).toString());
184            } else {
185                throw new RuntimeException("Unknown column: "+Integer.toString(column));
186            }
187            return this;
188        }
189    }
190
191
192    public static class DataTypeCellEditor extends AbstractCellEditor
193            implements TableCellEditor, ActionListener {
194
195        private InitialValueType _beanType;
196
197        @Override
198        public Object getCellEditorValue() {
199            return this._beanType;
200        }
201
202        @Override
203        public Component getTableCellEditorComponent(JTable table, Object value,
204                boolean isSelected, int row, int column) {
205
206            if (value == null) value = InitialValueType.LocalVariable;
207
208            if (! (value instanceof InitialValueType)) {
209                throw new IllegalArgumentException("value is not an InitialValueType: " + value.getClass().getName());
210            }
211
212            JComboBox<InitialValueType> returnValueTypeComboBox = new JComboBox<>();
213
214            for (InitialValueType type : InitialValueType.values()) {
215                returnValueTypeComboBox.addItem(type);
216            }
217            JComboBoxUtil.setupComboBoxMaxRows(returnValueTypeComboBox);
218
219            returnValueTypeComboBox.setSelectedItem(value);
220            returnValueTypeComboBox.addActionListener(this);
221
222            return returnValueTypeComboBox;
223        }
224
225        @Override
226        @SuppressWarnings("unchecked")  // Not possible to check that event.getSource() is instanceof JComboBox<InitialValueType>
227        public void actionPerformed(ActionEvent event) {
228            if (! (event.getSource() instanceof JComboBox)) {
229                throw new IllegalArgumentException("value is not an JComboBox: " + event.getSource().getClass().getName());
230            }
231            JComboBox<InitialValueType> returnValueTypeComboBox =
232                    (JComboBox<InitialValueType>) event.getSource();
233            _beanType = returnValueTypeComboBox.getItemAt(returnValueTypeComboBox.getSelectedIndex());
234
235        }
236
237    }
238
239
240    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(WebRequestTableModel.class);
241
242}