001package jmri.jmrit.logixng.actions.swing;
002
003import java.util.List;
004import java.util.SortedSet;
005
006import javax.annotation.CheckForNull;
007import javax.annotation.Nonnull;
008import javax.swing.*;
009
010import jmri.*;
011import jmri.jmrit.logixng.*;
012import jmri.jmrit.logixng.actions.ActionReporter;
013import jmri.jmrit.logixng.actions.ActionReporter.ReporterValue;
014import jmri.jmrit.logixng.swing.SwingConfiguratorInterface;
015import jmri.jmrit.logixng.util.parser.ParserException;
016import jmri.jmrit.logixng.util.swing.LogixNG_SelectNamedBeanSwing;
017import jmri.util.swing.BeanSelectPanel;
018import jmri.util.swing.JComboBoxUtil;
019
020/**
021 * Configures an ActionReporter object with a Swing JPanel.
022 *
023 * @author Daniel Bergqvist  Copyright 2021
024 * @author Dave Sand         Copyright 2021
025 */
026public class ActionReporterSwing extends AbstractDigitalActionSwing {
027
028    private LogixNG_SelectNamedBeanSwing<Reporter> _selectNamedBeanSwing;
029
030    private JPanel _panelReporterValue;
031    private JComboBox<ReporterValue> _reporterValueComboBox;
032
033
034    private JTabbedPane _tabbedPaneData;
035    private JPanel _panelDataDirect;
036    private JPanel _panelDataReference;
037    private JPanel _panelDataLocalVariable;
038    private JPanel _panelDataFormula;
039
040    private BeanSelectPanel<Memory> _memorySelectPanel;
041    private JTextField _dataReferenceTextField;
042    private JTextField _dataLocalVariableTextField;
043    private JTextField _dataFormulaTextField;
044
045    @Override
046    protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) {
047        ActionReporter action = (ActionReporter)object;
048
049        _selectNamedBeanSwing = new LogixNG_SelectNamedBeanSwing<>(
050                InstanceManager.getDefault(ReporterManager.class), getJDialog(), this);
051
052        panel = new JPanel();
053
054        // Left section
055        _panelReporterValue = new javax.swing.JPanel();
056        _reporterValueComboBox = new JComboBox<>();
057        for (ReporterValue e : ReporterValue.values()) {
058            _reporterValueComboBox.addItem(e);
059        }
060        JComboBoxUtil.setupComboBoxMaxRows(_reporterValueComboBox);
061        _panelReporterValue.add(_reporterValueComboBox);
062
063        // Center section
064        JPanel _tabbedPaneNamedBean;
065        if (action != null) {
066            _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(action.getSelectNamedBean());
067        } else {
068            _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(null);
069        }
070
071        // Right section
072        _tabbedPaneData = new JTabbedPane();
073        _panelDataDirect = new javax.swing.JPanel();
074        _panelDataReference = new javax.swing.JPanel();
075        _panelDataLocalVariable = new javax.swing.JPanel();
076        _panelDataFormula = new javax.swing.JPanel();
077
078        _tabbedPaneData.addTab(NamedBeanAddressing.Direct.toString(), _panelDataDirect);
079        _tabbedPaneData.addTab(NamedBeanAddressing.Reference.toString(), _panelDataReference);
080        _tabbedPaneData.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelDataLocalVariable);
081        _tabbedPaneData.addTab(NamedBeanAddressing.Formula.toString(), _panelDataFormula);
082
083        _memorySelectPanel = new BeanSelectPanel<>(InstanceManager.getDefault(MemoryManager.class), null);
084        _panelDataDirect.add(_memorySelectPanel);
085
086        _dataReferenceTextField = new JTextField();
087        _dataReferenceTextField.setColumns(30);
088        _panelDataReference.add(_dataReferenceTextField);
089
090        _dataLocalVariableTextField = new JTextField();
091        _dataLocalVariableTextField.setColumns(30);
092        _panelDataLocalVariable.add(_dataLocalVariableTextField);
093
094        _dataFormulaTextField = new JTextField();
095        _dataFormulaTextField.setColumns(30);
096        _panelDataFormula.add(_dataFormulaTextField);
097
098
099        if (action != null) {
100            _reporterValueComboBox.setSelectedItem(action.getReporterValue());
101
102            switch (action.getDataAddressing()) {
103                case Direct: _tabbedPaneData.setSelectedComponent(_panelDataDirect); break;
104                case Reference: _tabbedPaneData.setSelectedComponent(_panelDataReference); break;
105                case LocalVariable: _tabbedPaneData.setSelectedComponent(_panelDataLocalVariable); break;
106                case Formula: _tabbedPaneData.setSelectedComponent(_panelDataFormula); break;
107                default: throw new IllegalArgumentException("invalid _addressing state: " + action.getDataAddressing().name());
108            }
109            if (action.getSelectMemoryNamedBean().getNamedBean() != null) {
110                _memorySelectPanel.setDefaultNamedBean(action.getSelectMemoryNamedBean().getNamedBean().getBean());
111            }
112            _dataReferenceTextField.setText(action.getDataReference());
113            _dataLocalVariableTextField.setText(action.getDataLocalVariable());
114            _dataFormulaTextField.setText(action.getDataFormula());
115        }
116
117        JComponent[] components = new JComponent[]{
118            _panelReporterValue,
119            _tabbedPaneNamedBean,
120            _tabbedPaneData};
121
122        List<JComponent> componentList = SwingConfiguratorInterface.parseMessage(
123                Bundle.getMessage("ActionReporter_Components"), components);
124
125        for (JComponent c : componentList) panel.add(c);
126    }
127
128    /** {@inheritDoc} */
129    @Override
130    public boolean validate(@Nonnull List<String> errorMessages) {
131        ActionReporter action = new ActionReporter("IQDA1", null);
132        _selectNamedBeanSwing.validate(action.getSelectNamedBean(), errorMessages);
133        validateDataSection(errorMessages);
134        return errorMessages.isEmpty();
135    }
136
137    private void validateDataSection(List<String> errorMessages) {
138        // Create a temporary action to test formula
139        ActionReporter action = new ActionReporter("IQDA3", null);
140
141        try {
142            if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) {
143                action.setDataReference(_dataReferenceTextField.getText());
144            }
145        } catch (IllegalArgumentException e) {
146            errorMessages.add(e.getMessage());
147            return;
148        }
149
150        try {
151            action.setDataFormula(_dataFormulaTextField.getText());
152            if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) {
153                action.setDataAddressing(NamedBeanAddressing.Direct);
154            } else if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) {
155                action.setDataAddressing(NamedBeanAddressing.Reference);
156            } else if (_tabbedPaneData.getSelectedComponent() == _panelDataLocalVariable) {
157                action.setDataAddressing(NamedBeanAddressing.LocalVariable);
158            } else if (_tabbedPaneData.getSelectedComponent() == _panelDataFormula) {
159                action.setDataAddressing(NamedBeanAddressing.Formula);
160            } else {
161                throw new IllegalArgumentException("_tabbedPane has unknown selection");
162            }
163        } catch (ParserException e) {
164            errorMessages.add("Cannot parse formula: " + e.getMessage());
165        }
166
167        if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) {
168            if (_memorySelectPanel.getNamedBean() == null) {
169                errorMessages.add(Bundle.getMessage("ActionReporter_ErrorMemory"));
170            }
171        }
172    }
173
174    /** {@inheritDoc} */
175    @Override
176    public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) {
177        ActionReporter action = new ActionReporter(systemName, userName);
178        updateObject(action);
179        return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action);
180    }
181
182    /** {@inheritDoc} */
183    @Override
184    public void updateObject(@Nonnull Base object) {
185        if (! (object instanceof ActionReporter)) {
186            throw new IllegalArgumentException("object must be an ActionReporter but is a: "+object.getClass().getName());
187        }
188        ActionReporter action = (ActionReporter) object;
189        _selectNamedBeanSwing.updateObject(action.getSelectNamedBean());
190
191        try {
192            // Right section
193            action.getSelectMemoryNamedBean().removeNamedBean();
194            if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) {
195                action.setDataAddressing(NamedBeanAddressing.Direct);
196                Memory memory = _memorySelectPanel.getNamedBean();
197                if (memory != null) {
198                    NamedBeanHandle<Memory> handle
199                            = InstanceManager.getDefault(NamedBeanHandleManager.class)
200                                    .getNamedBeanHandle(memory.getDisplayName(), memory);
201                    action.getSelectMemoryNamedBean().setNamedBean(handle);
202                }
203            } else if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) {
204                action.setDataAddressing(NamedBeanAddressing.Reference);
205                action.setDataReference(_dataReferenceTextField.getText());
206            } else if (_tabbedPaneData.getSelectedComponent() == _panelDataLocalVariable) {
207                action.setDataAddressing(NamedBeanAddressing.LocalVariable);
208                action.setDataLocalVariable(_dataLocalVariableTextField.getText());
209            } else if (_tabbedPaneData.getSelectedComponent() == _panelDataFormula) {
210                action.setDataAddressing(NamedBeanAddressing.Formula);
211                action.setDataFormula(_dataFormulaTextField.getText());
212            } else {
213                throw new IllegalArgumentException("_tabbedPaneBean has unknown selection");
214            }
215
216        } catch (ParserException e) {
217            throw new RuntimeException("ParserException: "+e.getMessage(), e);
218        }
219    }
220
221    /** {@inheritDoc} */
222    @Override
223    public String toString() {
224        return Bundle.getMessage("ActionReporter_Short");
225    }
226
227    @Override
228    public void setDefaultValues() {
229        if (_memorySelectPanel.getNamedBean() == null) {
230            SortedSet<Memory> set = InstanceManager.getDefault(MemoryManager.class).getNamedBeanSet();
231            if (!set.isEmpty()) {
232                Memory m = set.first();
233                _memorySelectPanel.setDefaultNamedBean(m);
234            } else {
235                log.error("Memory manager has no memories. Can't set default values");
236            }
237        }
238    }
239
240    @Override
241    public void dispose() {
242        if (_memorySelectPanel != null) {
243            _memorySelectPanel.dispose();
244        }
245    }
246
247
248     private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionReporterSwing.class);
249
250}