001package jmri.jmrit.logixng.actions.swing;
002
003import java.util.List;
004
005import javax.annotation.CheckForNull;
006import javax.annotation.Nonnull;
007import javax.swing.*;
008
009import jmri.*;
010import jmri.jmrit.logixng.*;
011import jmri.jmrit.logixng.actions.ActionSetReporter;
012import jmri.jmrit.logixng.actions.ActionSetReporter.ReporterOperation;
013import jmri.jmrit.logixng.swing.SwingConfiguratorInterface;
014import jmri.jmrit.logixng.util.swing.LogixNG_SelectTableSwing;
015import jmri.jmrit.logixng.util.parser.ParserException;
016import jmri.jmrit.logixng.util.swing.LogixNG_SelectNamedBeanSwing;
017import jmri.util.swing.BeanSelectPanel;
018
019/**
020 * Configures an ActionSetReporter object with a Swing JPanel.
021 *
022 * @author Daniel Bergqvist Copyright 2024
023 */
024public class ActionSetReporterSwing extends AbstractDigitalActionSwing {
025
026    private LogixNG_SelectTableSwing selectTableSwing;
027
028    private LogixNG_SelectNamedBeanSwing<Reporter> _selectNamedBeanSwing;
029
030    private JTabbedPane _tabbedPaneReporterOperation;
031    private BeanSelectPanel<Memory> _copyMemoryBeanPanel;
032    private JPanel _setToNull;
033    private JPanel _setToConstant;
034    private JPanel _copyMemory;
035    private JPanel _copyTableCell;
036    private JPanel _copyVariable;
037    private JPanel _calculateFormula;
038    private JTextField _setToConstantTextField;
039    private JTextField _copyLocalVariableTextField;
040    private JTextField _calculateFormulaTextField;
041    private JCheckBox _provideAnIdTag;
042
043
044    @Override
045    protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) {
046        ActionSetReporter action = (ActionSetReporter)object;
047
048        _selectNamedBeanSwing = new LogixNG_SelectNamedBeanSwing<>(
049                InstanceManager.getDefault(ReporterManager.class), getJDialog(), this);
050
051        selectTableSwing = new LogixNG_SelectTableSwing(getJDialog(), this);
052
053        panel = new JPanel();
054        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
055
056        JPanel innerPanel = new JPanel();
057
058        JPanel _tabbedPaneNamedBean;
059        if (action != null) {
060            _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(action.getSelectNamedBean());
061        } else {
062            _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(null);
063        }
064
065        _tabbedPaneReporterOperation = new JTabbedPane();
066
067        _setToNull = new JPanel();
068        _setToConstant = new JPanel();
069        _copyMemory = new JPanel();
070        if (action != null) {
071            _copyTableCell = selectTableSwing.createPanel(action.getSelectTable());
072        } else {
073            _copyTableCell = selectTableSwing.createPanel(null);
074        }
075        _copyVariable = new JPanel();
076        _calculateFormula = new JPanel();
077
078        _tabbedPaneReporterOperation.addTab(ReporterOperation.SetToNull.toString(), _setToNull);
079        _tabbedPaneReporterOperation.addTab(ReporterOperation.SetToString.toString(), _setToConstant);
080        _tabbedPaneReporterOperation.addTab(ReporterOperation.CopyMemoryToReporter.toString(), _copyMemory);
081        _tabbedPaneReporterOperation.addTab(ReporterOperation.CopyTableCellToReporter.toString(), _copyTableCell);
082        _tabbedPaneReporterOperation.addTab(ReporterOperation.CopyVariableToReporter.toString(), _copyVariable);
083        _tabbedPaneReporterOperation.addTab(ReporterOperation.CalculateFormula.toString(), _calculateFormula);
084
085        _setToNull.add(new JLabel("Null"));     // No I18N
086
087        _setToConstantTextField = new JTextField(30);
088        _setToConstant.add(_setToConstantTextField);
089
090        _copyMemoryBeanPanel = new BeanSelectPanel<>(InstanceManager.getDefault(MemoryManager.class), null);
091        _copyMemory.add(_copyMemoryBeanPanel);
092
093        _copyLocalVariableTextField = new JTextField(30);
094        _copyVariable.add(_copyLocalVariableTextField);
095
096        _calculateFormulaTextField = new JTextField(30);
097        _calculateFormula.add(_calculateFormulaTextField);
098
099        _provideAnIdTag = new JCheckBox(Bundle.getMessage("ActionSetReporter_ProvideAnIdTag"));
100
101
102        if (action != null) {
103            if (action.getSelectOtherMemoryNamedBean().getNamedBean() != null) {
104                _copyMemoryBeanPanel.setDefaultNamedBean(action.getSelectOtherMemoryNamedBean().getNamedBean().getBean());
105            }
106            switch (action.getReporterOperation()) {
107                case SetToNull: _tabbedPaneReporterOperation.setSelectedComponent(_setToNull); break;
108                case SetToString: _tabbedPaneReporterOperation.setSelectedComponent(_setToConstant); break;
109                case CopyMemoryToReporter: _tabbedPaneReporterOperation.setSelectedComponent(_copyMemory); break;
110                case CopyTableCellToReporter: _tabbedPaneReporterOperation.setSelectedComponent(_copyTableCell); break;
111                case CopyVariableToReporter: _tabbedPaneReporterOperation.setSelectedComponent(_copyVariable); break;
112                case CalculateFormula: _tabbedPaneReporterOperation.setSelectedComponent(_calculateFormula); break;
113                default: throw new IllegalArgumentException("invalid _addressing state: " + action.getReporterOperation().name());
114            }
115            _setToConstantTextField.setText(action.getConstantValue());
116            _copyLocalVariableTextField.setText(action.getOtherLocalVariable());
117            _calculateFormulaTextField.setText(action.getOtherFormula());
118            _provideAnIdTag.setSelected(action.isProvideAnIdTag());
119        }
120
121        JComponent[] components = new JComponent[]{
122            _tabbedPaneNamedBean,
123            _tabbedPaneReporterOperation
124        };
125
126        List<JComponent> componentList = SwingConfiguratorInterface.parseMessage(
127                Bundle.getMessage("ActionSetReporter_Components"), components);
128
129        for (JComponent c : componentList) innerPanel.add(c);
130
131        panel.add(innerPanel);
132        panel.add(_provideAnIdTag);
133    }
134
135    /** {@inheritDoc} */
136    @Override
137    public boolean validate(@Nonnull List<String> errorMessages) {
138        // Create a temporary action to test formula
139        ActionSetReporter action = new ActionSetReporter("IQDA2", null);
140
141        try {
142            action.setMemoryOperation(ReporterOperation.CalculateFormula);
143            action.setOtherFormula(_calculateFormulaTextField.getText());
144        } catch (ParserException e) {
145            errorMessages.add(e.getMessage());
146        }
147
148        _selectNamedBeanSwing.validate(action.getSelectNamedBean(), errorMessages);
149        validateDataSection(action, errorMessages);
150
151        return errorMessages.isEmpty();
152    }
153
154    public void validateDataSection(@Nonnull ActionSetReporter action, @Nonnull List<String> errorMessages) {
155        // If using the Memory tab, validate the memory variable selection.
156        if (_tabbedPaneReporterOperation.getSelectedComponent() == _copyMemory) {
157            if (_copyMemoryBeanPanel.getNamedBean() == null) {
158                errorMessages.add(Bundle.getMessage("ActionSetReporter_CopyErrorMemory"));
159            }
160        }
161
162        // Validate formula parsing via setFormula and tab selection.
163        try {
164            action.setOtherFormula(_calculateFormulaTextField.getText());
165            if (_tabbedPaneReporterOperation.getSelectedComponent() == _calculateFormula) {
166                action.setMemoryOperation(ActionSetReporter.ReporterOperation.CalculateFormula);
167            }
168        } catch (ParserException e) {
169            errorMessages.add("Cannot parse formula: " + e.getMessage());
170        }
171
172        selectTableSwing.validate(action.getSelectTable(), errorMessages);
173    }
174
175    /** {@inheritDoc} */
176    @Override
177    public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) {
178        ActionSetReporter action = new ActionSetReporter(systemName, userName);
179        updateObject(action);
180        return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action);
181    }
182
183    /** {@inheritDoc} */
184    @Override
185    public void updateObject(@Nonnull Base object) {
186        if (! (object instanceof ActionSetReporter)) {
187            throw new IllegalArgumentException("object must be an ActionSetReporter but is a: "+object.getClass().getName());
188        }
189        ActionSetReporter action = (ActionSetReporter)object;
190        _selectNamedBeanSwing.updateObject(action.getSelectNamedBean());
191
192        if (_tabbedPaneReporterOperation.getSelectedComponent() == _copyMemory) {
193            Memory otherMemory = _copyMemoryBeanPanel.getNamedBean();
194            if (otherMemory != null) {
195                NamedBeanHandle<Memory> handle
196                        = InstanceManager.getDefault(NamedBeanHandleManager.class)
197                                .getNamedBeanHandle(otherMemory.getDisplayName(), otherMemory);
198                action.getSelectOtherMemoryNamedBean().setNamedBean(handle);
199            } else {
200                action.getSelectOtherMemoryNamedBean().removeNamedBean();
201            }
202        } else {
203            action.getSelectOtherMemoryNamedBean().removeNamedBean();
204        }
205
206        try {
207            if (_tabbedPaneReporterOperation.getSelectedComponent() == _setToNull) {
208                action.setMemoryOperation(ActionSetReporter.ReporterOperation.SetToNull);
209            } else if (_tabbedPaneReporterOperation.getSelectedComponent() == _setToConstant) {
210                action.setMemoryOperation(ActionSetReporter.ReporterOperation.SetToString);
211                action.setOtherConstantValue(_setToConstantTextField.getText());
212            } else if (_tabbedPaneReporterOperation.getSelectedComponent() == _copyMemory) {
213                action.setMemoryOperation(ActionSetReporter.ReporterOperation.CopyMemoryToReporter);
214            } else if (_tabbedPaneReporterOperation.getSelectedComponent() == _copyTableCell) {
215                action.setMemoryOperation(ActionSetReporter.ReporterOperation.CopyTableCellToReporter);
216            } else if (_tabbedPaneReporterOperation.getSelectedComponent() == _copyVariable) {
217                action.setMemoryOperation(ActionSetReporter.ReporterOperation.CopyVariableToReporter);
218                action.setOtherLocalVariable(_copyLocalVariableTextField.getText());
219            } else if (_tabbedPaneReporterOperation.getSelectedComponent() == _calculateFormula) {
220                action.setMemoryOperation(ActionSetReporter.ReporterOperation.CalculateFormula);
221                action.setOtherFormula(_calculateFormulaTextField.getText());
222            } else {
223                throw new IllegalArgumentException("_tabbedPaneMemoryOperation has unknown selection");
224            }
225        } catch (ParserException e) {
226            throw new RuntimeException("ParserException: "+e.getMessage(), e);
227        }
228
229        selectTableSwing.updateObject(action.getSelectTable());
230
231        action.setProvideAnIdTag(_provideAnIdTag.isSelected());
232    }
233
234    /** {@inheritDoc} */
235    @Override
236    public String toString() {
237        return Bundle.getMessage("ActionSetReporter_Short");
238    }
239
240    /** {@inheritDoc} */
241    @Override
242    public boolean canClose() {
243        return selectTableSwing.canClose();
244    }
245
246    @Override
247    public void dispose() {
248        selectTableSwing.dispose();
249    }
250
251//    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionSetReporterSwing.class);
252
253}