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