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}