001package jmri.jmrit.logixng.actions.swing; 002 003import java.awt.Dimension; 004import java.awt.event.ActionEvent; 005import java.util.*; 006 007import javax.annotation.CheckForNull; 008import javax.annotation.Nonnull; 009import javax.swing.*; 010import javax.swing.table.TableColumn; 011 012import jmri.InstanceManager; 013import jmri.jmrit.logixng.*; 014import jmri.jmrit.logixng.actions.LogData; 015import jmri.jmrit.logixng.util.parser.*; 016import jmri.util.table.ButtonEditor; 017import jmri.util.table.ButtonRenderer; 018 019/** 020 * Configures an LogData object with a Swing JPanel. 021 * 022 * @author Daniel Bergqvist Copyright 2021 023 */ 024public class LogDataSwing extends AbstractDigitalActionSwing { 025 026 private JCheckBox _logToLogCheckBox; 027 private JCheckBox _logToScriptOutputCheckBox; 028 private JComboBox<LogData.FormatType> _formatType; 029 private JTextField _format; 030 private JTable _logDataTable; 031 private LogDataTableModel _logDataTableModel; 032 033 @Override 034 protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) { 035 if ((object != null) && (! (object instanceof LogData))) { 036 throw new IllegalArgumentException("object is not a LogData: " + object.getClass().getName()); 037 } 038 LogData logData = (LogData)object; 039 040 panel = new JPanel(); 041 042 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 043 044 045 _logToLogCheckBox = new JCheckBox(Bundle.getMessage("LogData_LogToLog")); 046 panel.add(_logToLogCheckBox); 047 048 _logToScriptOutputCheckBox = new JCheckBox(Bundle.getMessage("LogData_LogToScriptOutput")); 049 panel.add(_logToScriptOutputCheckBox); 050 051 052 JPanel formatTypePanel = new JPanel(); 053 _formatType = new JComboBox<>(); 054 for (LogData.FormatType formatType : LogData.FormatType.values()) { 055 _formatType.addItem(formatType); 056 } 057 formatTypePanel.add(new JLabel(Bundle.getMessage("LogData_FormatType"))); 058 formatTypePanel.add(_formatType); 059 panel.add(formatTypePanel); 060 061 JPanel formatPanel = new JPanel(); 062 _format = new JTextField(20); 063 formatPanel.add(new JLabel(Bundle.getMessage("LogData_Format"))); 064 formatPanel.add(_format); 065 panel.add(formatPanel); 066 067 068 if (logData != null) { 069 _logToLogCheckBox.setSelected(logData.getLogToLog()); 070 _logToScriptOutputCheckBox.setSelected(logData.getLogToScriptOutput()); 071 _formatType.setSelectedItem(logData.getFormatType()); 072 _format.setText(logData.getFormat()); 073 } 074 075 076 _logDataTable = new JTable(); 077 078 if (logData != null) { 079 List<LogData.Data> dataList 080 = new ArrayList<>(logData.getDataList()); 081 082 _logDataTableModel = new LogDataTableModel(dataList); 083 } else { 084 _logDataTableModel = new LogDataTableModel(null); 085 } 086 087 _logDataTable.setModel(_logDataTableModel); 088 _logDataTable.setDefaultRenderer(LogData.DataType.class, 089 new LogDataTableModel.CellRenderer()); 090 _logDataTable.setDefaultEditor(LogData.DataType.class, 091 new LogDataTableModel.DataTypeCellEditor()); 092 _logDataTableModel.setColumnsForComboBoxes(_logDataTable); 093 _logDataTable.setDefaultRenderer(JButton.class, new ButtonRenderer()); 094 _logDataTable.setDefaultEditor(JButton.class, new ButtonEditor(new JButton())); 095 096 JButton testButton = new JButton("XXXXXX"); // NOI18N 097 _logDataTable.setRowHeight(testButton.getPreferredSize().height); 098 TableColumn deleteColumn = _logDataTable.getColumnModel() 099 .getColumn(LogDataTableModel.COLUMN_DUMMY); 100 deleteColumn.setMinWidth(testButton.getPreferredSize().width); 101 deleteColumn.setMaxWidth(testButton.getPreferredSize().width); 102 deleteColumn.setResizable(false); 103 104 // The dummy column is used to be able to force update of the 105 // other columns when the panel is closed. 106 TableColumn dummyColumn = _logDataTable.getColumnModel() 107 .getColumn(LogDataTableModel.COLUMN_DUMMY); 108 dummyColumn.setMinWidth(0); 109 dummyColumn.setPreferredWidth(0); 110 dummyColumn.setMaxWidth(0); 111 112 JScrollPane scrollpane = new JScrollPane(_logDataTable); 113 scrollpane.setPreferredSize(new Dimension(400, 200)); 114 panel.add(scrollpane); 115 116 // Add parameter 117 JButton add = new JButton(Bundle.getMessage("LogData_TableAdd")); 118 buttonPanel.add(add); 119 add.addActionListener((ActionEvent e) -> { 120 _logDataTableModel.add(); 121 }); 122 } 123 124 /** {@inheritDoc} */ 125 @Override 126 public boolean validate(@Nonnull List<String> errorMessages) { 127 boolean result = true; 128 for (LogData.Data data : _logDataTableModel.getDataList()) { 129 if (data.getDataType() == LogData.DataType.Formula) { 130 try { 131 Map<String, Variable> variables = new HashMap<>(); 132 RecursiveDescentParser parser = new RecursiveDescentParser(variables); 133 parser.parseExpression(data.getData()); 134 } catch (ParserException e) { 135 errorMessages.add(e.getLocalizedMessage()); 136 result = false; 137 } 138 } 139 } 140 return result; 141 } 142 143 /** {@inheritDoc} */ 144 @Override 145 public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) { 146 LogData action = new LogData(systemName, userName); 147 updateObject(action); 148 return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action); 149 } 150 151 /** {@inheritDoc} */ 152 @Override 153 public void updateObject(@Nonnull Base object) { 154 if (! (object instanceof LogData)) { 155 throw new IllegalArgumentException("object is not a LogData: " + object.getClass().getName()); 156 } 157 LogData logData = (LogData)object; 158 159 160 logData.setLogToLog(_logToLogCheckBox.isSelected()); 161 logData.setLogToScriptOutput(_logToScriptOutputCheckBox.isSelected()); 162 163 logData.setFormatType(_formatType.getItemAt(_formatType.getSelectedIndex())); 164 logData.setFormat(_format.getText()); 165 166 167 // Do this to force update of the table 168 _logDataTable.editCellAt(0, 2); 169 170 logData.getDataList().clear(); 171 172 for (LogData.Data data : _logDataTableModel.getDataList()) { 173 logData.getDataList().add(data); 174 } 175 } 176 177 /** {@inheritDoc} */ 178 @Override 179 public String toString() { 180 return Bundle.getMessage("LogData_Short"); 181 } 182 183 @Override 184 public void dispose() { 185 } 186 187}