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.ShowDialog; 015import jmri.jmrit.logixng.actions.ShowDialog.Button; 016import jmri.jmrit.logixng.util.parser.*; 017import jmri.util.table.ButtonEditor; 018import jmri.util.table.ButtonRenderer; 019 020/** 021 * Configures an ShowDialog object with a Swing JPanel. 022 * 023 * @author Daniel Bergqvist Copyright 2021 024 */ 025public class ShowDialogSwing extends AbstractDigitalActionSwing { 026 027 private List<ButtonCheckBox> _buttonCheckBoxes; 028 private JComboBox<ShowDialog.FormatType> _formatType; 029 private JTextField _format; 030 private JTable _showDialogTable; 031 private ShowDialogTableModel _showDialogTableModel; 032 private JCheckBox _modalCheckBox; 033 private JCheckBox _multiLineCheckBox; 034 private JTextField _localVariableForSelectedButton; 035 private JTextField _localVariableForInputString; 036 037 @Override 038 protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) { 039 if ((object != null) && (! (object instanceof ShowDialog))) { 040 throw new IllegalArgumentException("object is not a ShowDialog: " + object.getClass().getName()); 041 } 042 ShowDialog showDialog = (ShowDialog)object; 043 044 panel = new JPanel(); 045 046 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 047 048 049 JPanel buttonCheckBoxPanel = new JPanel(); 050 buttonCheckBoxPanel.setBorder(BorderFactory.createTitledBorder( 051 Bundle.getMessage("ShowDialog_Buttons"))); 052 _buttonCheckBoxes = new ArrayList<>(); 053 for (Button button : ShowDialog.Button.values()) { 054 ButtonCheckBox buttonCheckBox = 055 new ButtonCheckBox(button, 056 new JCheckBox(Integer.toString(button.getValue()) 057 + ": " + button.toString())); 058 _buttonCheckBoxes.add(buttonCheckBox); 059 buttonCheckBoxPanel.add(buttonCheckBox._checkBox); 060 if ((showDialog != null) && (showDialog.getEnabledButtons().contains(button))) { 061 buttonCheckBox._checkBox.setSelected(true); 062 } 063 } 064 panel.add(buttonCheckBoxPanel); 065 066 067 JPanel formatTypePanel = new JPanel(); 068 _formatType = new JComboBox<>(); 069 for (ShowDialog.FormatType formatType : ShowDialog.FormatType.values()) { 070 _formatType.addItem(formatType); 071 } 072 formatTypePanel.add(new JLabel(Bundle.getMessage("ShowDialog_FormatType"))); 073 formatTypePanel.add(_formatType); 074 panel.add(formatTypePanel); 075 076 JPanel formatPanel = new JPanel(); 077 _format = new JTextField(40); 078 formatPanel.add(new JLabel(Bundle.getMessage("ShowDialog_Format"))); 079 formatPanel.add(_format); 080 panel.add(formatPanel); 081 082 083 _showDialogTable = new JTable(); 084 085 if (showDialog != null) { 086 List<ShowDialog.Data> dataList 087 = new ArrayList<>(showDialog.getDataList()); 088 089 _showDialogTableModel = new ShowDialogTableModel(dataList); 090 } else { 091 _showDialogTableModel = new ShowDialogTableModel(null); 092 } 093 094 _showDialogTable.setModel(_showDialogTableModel); 095 _showDialogTable.setDefaultRenderer(ShowDialog.DataType.class, 096 new ShowDialogTableModel.CellRenderer()); 097 _showDialogTable.setDefaultEditor(ShowDialog.DataType.class, 098 new ShowDialogTableModel.DataTypeCellEditor()); 099 _showDialogTableModel.setColumnsForComboBoxes(_showDialogTable); 100 _showDialogTable.setDefaultRenderer(JButton.class, new ButtonRenderer()); 101 _showDialogTable.setDefaultEditor(JButton.class, new ButtonEditor(new JButton())); 102 103 JButton testButton = new JButton("XXXXXX"); // NOI18N 104 _showDialogTable.setRowHeight(testButton.getPreferredSize().height); 105 TableColumn deleteColumn = _showDialogTable.getColumnModel() 106 .getColumn(ShowDialogTableModel.COLUMN_DUMMY); 107 deleteColumn.setMinWidth(testButton.getPreferredSize().width); 108 deleteColumn.setMaxWidth(testButton.getPreferredSize().width); 109 deleteColumn.setResizable(false); 110 111 // The dummy column is used to be able to force update of the 112 // other columns when the panel is closed. 113 TableColumn dummyColumn = _showDialogTable.getColumnModel() 114 .getColumn(ShowDialogTableModel.COLUMN_DUMMY); 115 dummyColumn.setMinWidth(0); 116 dummyColumn.setPreferredWidth(0); 117 dummyColumn.setMaxWidth(0); 118 119 JScrollPane scrollpane = new JScrollPane(_showDialogTable); 120 scrollpane.setPreferredSize(new Dimension(400, 200)); 121 panel.add(scrollpane); 122 123 // Add parameter 124 JButton add = new JButton(Bundle.getMessage("ShowDialog_TableAdd")); 125 buttonPanel.add(add); 126 add.addActionListener((ActionEvent e) -> { 127 _showDialogTableModel.add(); 128 }); 129 130 131 _modalCheckBox = new JCheckBox(Bundle.getMessage("ShowDialog_Modal")); 132 panel.add(_modalCheckBox); 133 134 _multiLineCheckBox = new JCheckBox(Bundle.getMessage("ShowDialog_Multiline")); 135 panel.add(_multiLineCheckBox); 136 137 panel.add(new JLabel(Bundle.getMessage("ShowDialog_MultilineHelp"))); 138 139 140 JPanel localVariableForSelectedButtonPanel = new JPanel(); 141 _localVariableForSelectedButton = new JTextField(20); 142 localVariableForSelectedButtonPanel.add(new JLabel(Bundle.getMessage("ShowDialog_LocalVariableForSelectedButton"))); 143 localVariableForSelectedButtonPanel.add(_localVariableForSelectedButton); 144 panel.add(localVariableForSelectedButtonPanel); 145 146 JPanel localVariableForInputStringPanel = new JPanel(); 147 _localVariableForInputString = new JTextField(20); 148 localVariableForInputStringPanel.add(new JLabel(Bundle.getMessage("ShowDialog_LocalVariableForInputString"))); 149 localVariableForInputStringPanel.add(_localVariableForInputString); 150 panel.add(localVariableForInputStringPanel); 151 152 153 if (showDialog != null) { 154 _modalCheckBox.setSelected(showDialog.getModal()); 155 _multiLineCheckBox.setSelected(showDialog.getMultiLine()); 156 _localVariableForSelectedButton.setText(showDialog.getLocalVariableForSelectedButton()); 157 _localVariableForInputString.setText(showDialog.getLocalVariableForInputString()); 158 _formatType.setSelectedItem(showDialog.getFormatType()); 159 _format.setText(showDialog.getFormat()); 160 } 161 } 162 163 /** {@inheritDoc} */ 164 @Override 165 public boolean validate(@Nonnull List<String> errorMessages) { 166 boolean result = true; 167 boolean hasEnabledButton = false; 168 for (ButtonCheckBox buttonCheckBox : _buttonCheckBoxes) { 169 hasEnabledButton |= buttonCheckBox._checkBox.isSelected(); 170 } 171 if (!hasEnabledButton) { 172 errorMessages.add(Bundle.getMessage("ShowDialog_ErrorNoEnabledButton")); 173 result = false; 174 } 175 176 for (ShowDialog.Data data : _showDialogTableModel.getDataList()) { 177 if (data.getDataType() == ShowDialog.DataType.Formula) { 178 try { 179 Map<String, Variable> variables = new HashMap<>(); 180 RecursiveDescentParser parser = new RecursiveDescentParser(variables); 181 parser.parseExpression(data.getData()); 182 } catch (ParserException e) { 183 errorMessages.add(e.getLocalizedMessage()); 184 result = false; 185 } 186 } 187 } 188 return result; 189 } 190 191 /** {@inheritDoc} */ 192 @Override 193 public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) { 194 ShowDialog action = new ShowDialog(systemName, userName); 195 updateObject(action); 196 return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action); 197 } 198 199 /** {@inheritDoc} */ 200 @Override 201 public void updateObject(@Nonnull Base object) { 202 if (! (object instanceof ShowDialog)) { 203 throw new IllegalArgumentException("object is not a ShowDialog: " + object.getClass().getName()); 204 } 205 ShowDialog showDialog = (ShowDialog)object; 206 207 208 Set<Button> enabledButtons = showDialog.getEnabledButtons(); 209 enabledButtons.clear(); 210 211 for (ButtonCheckBox buttonCheckBox : _buttonCheckBoxes) { 212 if (buttonCheckBox._checkBox.isSelected()) { 213 enabledButtons.add(buttonCheckBox._button); 214 } 215 } 216 217 218 showDialog.setLocalVariableForSelectedButton(_localVariableForSelectedButton.getText()); 219 showDialog.setLocalVariableForInputString(_localVariableForInputString.getText()); 220 221 showDialog.setFormatType(_formatType.getItemAt(_formatType.getSelectedIndex())); 222 showDialog.setFormat(_format.getText()); 223 224 225 showDialog.setModal(_modalCheckBox.isSelected()); 226 showDialog.setMultiLine(_multiLineCheckBox.isSelected()); 227 228 showDialog.setFormatType(_formatType.getItemAt(_formatType.getSelectedIndex())); 229 showDialog.setFormat(_format.getText()); 230 231 232 // Do this to force update of the table 233 _showDialogTable.editCellAt(0, 2); 234 235 showDialog.getDataList().clear(); 236 237 for (ShowDialog.Data data : _showDialogTableModel.getDataList()) { 238 showDialog.getDataList().add(data); 239 } 240 } 241 242 /** {@inheritDoc} */ 243 @Override 244 public String toString() { 245 return Bundle.getMessage("ShowDialog_Short"); 246 } 247 248 @Override 249 public void setDefaultValues() { 250 boolean hasEnabledButton = false; 251 for (ButtonCheckBox buttonCheckBox : _buttonCheckBoxes) { 252 hasEnabledButton |= buttonCheckBox._checkBox.isSelected(); 253 } 254 if (!hasEnabledButton) { 255 _buttonCheckBoxes.get(0)._checkBox.setSelected(true); 256 } 257 } 258 259 @Override 260 public void dispose() { 261 } 262 263 264 private static class ButtonCheckBox { 265 266 private final Button _button; 267 private final JCheckBox _checkBox; 268 269 private ButtonCheckBox(Button button, JCheckBox checkBox) { 270 this._button = button; 271 this._checkBox = checkBox; 272 } 273 274 } 275 276}