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.InstanceManager;
010import jmri.jmrit.logixng.*;
011import jmri.jmrit.logixng.actions.ExecuteDelayed;
012import jmri.jmrit.logixng.swing.SwingConfiguratorInterface;
013import jmri.jmrit.logixng.util.TimerUnit;
014import jmri.jmrit.logixng.util.parser.ParserException;
015import jmri.util.swing.JComboBoxUtil;
016
017/**
018 * Configures an ExecuteDelayed object with a Swing JPanel.
019 * 
020 * @author Daniel Bergqvist Copyright (C) 2021
021 */
022public class ExecuteDelayedSwing extends AbstractDigitalActionSwing {
023
024    private final JLabel _unitLabel = new JLabel(Bundle.getMessage("ExecuteDelayedSwing_Unit"));
025    private JComboBox<TimerUnit> _unitComboBox;
026    private JCheckBox _resetIfAlreadyStarted;
027    private JCheckBox _useIndividualTimers;
028    
029    private JTabbedPane _tabbedPaneDelay;
030    private JFormattedTextField _timerDelay;
031    private JPanel _panelDelayDirect;
032    private JPanel _panelDelayReference;
033    private JPanel _panelDelayLocalVariable;
034    private JPanel _panelDelayFormula;
035    private JTextField _delayReferenceTextField;
036    private JTextField _delayLocalVariableTextField;
037    private JTextField _delayFormulaTextField;
038    
039    @Override
040    protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) {
041        if ((object != null) && !(object instanceof ExecuteDelayed)) {
042            throw new IllegalArgumentException("object must be an ExecuteDelayed but is a: "+object.getClass().getName());
043        }
044        
045        ExecuteDelayed action = (ExecuteDelayed)object;
046        
047        panel = new JPanel();
048        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
049        
050        _tabbedPaneDelay = new JTabbedPane();
051        _panelDelayDirect = new javax.swing.JPanel();
052        _panelDelayReference = new javax.swing.JPanel();
053        _panelDelayLocalVariable = new javax.swing.JPanel();
054        _panelDelayFormula = new javax.swing.JPanel();
055        
056        _tabbedPaneDelay.addTab(NamedBeanAddressing.Direct.toString(), _panelDelayDirect);
057        _tabbedPaneDelay.addTab(NamedBeanAddressing.Reference.toString(), _panelDelayReference);
058        _tabbedPaneDelay.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelDelayLocalVariable);
059        _tabbedPaneDelay.addTab(NamedBeanAddressing.Formula.toString(), _panelDelayFormula);
060        
061        _timerDelay = new JFormattedTextField("0");
062        _timerDelay.setColumns(7);
063        
064        _panelDelayDirect.add(_timerDelay);
065        
066        _delayReferenceTextField = new JTextField();
067        _delayReferenceTextField.setColumns(30);
068        _panelDelayReference.add(_delayReferenceTextField);
069        
070        _delayLocalVariableTextField = new JTextField();
071        _delayLocalVariableTextField.setColumns(30);
072        _panelDelayLocalVariable.add(_delayLocalVariableTextField);
073        
074        _delayFormulaTextField = new JTextField();
075        _delayFormulaTextField.setColumns(30);
076        _panelDelayFormula.add(_delayFormulaTextField);
077        
078        
079        if (action != null) {
080            switch (action.getDelayAddressing()) {
081                case Direct: _tabbedPaneDelay.setSelectedComponent(_panelDelayDirect); break;
082                case Reference: _tabbedPaneDelay.setSelectedComponent(_panelDelayReference); break;
083                case LocalVariable: _tabbedPaneDelay.setSelectedComponent(_panelDelayLocalVariable); break;
084                case Formula: _tabbedPaneDelay.setSelectedComponent(_panelDelayFormula); break;
085                default: throw new IllegalArgumentException("invalid _addressing state: " + action.getDelayAddressing().name());
086            }
087            _timerDelay.setText(Integer.toString(action.getDelay()));
088            _delayReferenceTextField.setText(action.getDelayReference());
089            _delayLocalVariableTextField.setText(action.getDelayLocalVariable());
090            _delayFormulaTextField.setText(action.getDelayFormula());
091        }
092        
093        JComponent[] components = new JComponent[]{
094            _tabbedPaneDelay};
095        
096        List<JComponent> componentList = SwingConfiguratorInterface.parseMessage(
097                Bundle.getMessage("ExecuteDelayed_Components"), components);
098        
099        JPanel delayPanel = new JPanel();
100        for (JComponent c : componentList) delayPanel.add(c);
101        
102        panel.add(delayPanel);
103        
104        
105        JPanel unitPanel = new JPanel();
106        unitPanel.add(_unitLabel);
107        
108        _unitComboBox = new JComboBox<>();
109        for (TimerUnit u : TimerUnit.values()) _unitComboBox.addItem(u);
110        JComboBoxUtil.setupComboBoxMaxRows(_unitComboBox);
111        if (action != null) _unitComboBox.setSelectedItem(action.getUnit());
112        unitPanel.add(_unitComboBox);
113        
114        panel.add(unitPanel);
115        
116        _resetIfAlreadyStarted = new JCheckBox(Bundle.getMessage("ExecuteDelayedSwing_ResetIfAlreadyStarted"));
117        if (action != null) _resetIfAlreadyStarted.setSelected(action.getResetIfAlreadyStarted());
118        panel.add(_resetIfAlreadyStarted);
119        
120        _useIndividualTimers = new JCheckBox(Bundle.getMessage("ExecuteDelayedSwing_UseIndividualTimers"));
121        if (action != null) {
122            _useIndividualTimers.setSelected(action.getUseIndividualTimers());
123            _resetIfAlreadyStarted.setEnabled(!action.getUseIndividualTimers());
124        }
125        _useIndividualTimers.addActionListener((evt)->{
126            if (_useIndividualTimers.isSelected()) {
127                _resetIfAlreadyStarted.setEnabled(false);
128                _resetIfAlreadyStarted.setSelected(false);
129            } else {
130                _resetIfAlreadyStarted.setEnabled(true);
131            }
132        });
133        panel.add(_useIndividualTimers);
134    }
135    
136    /** {@inheritDoc} */
137    @Override
138    public boolean validate(@Nonnull List<String> errorMessages) {
139        // Create a temporary action to test formula
140        ExecuteDelayed action = new ExecuteDelayed("IQDA1", null);
141        
142        try {
143            if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayReference) {
144                action.setDelayReference(_delayReferenceTextField.getText());
145            }
146        } catch (IllegalArgumentException e) {
147            errorMessages.add(e.getMessage());
148            return false;
149        }
150        
151        try {
152            action.setDelayFormula(_delayFormulaTextField.getText());
153            if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayDirect) {
154                action.setDelayAddressing(NamedBeanAddressing.Direct);
155            } else if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayReference) {
156                action.setDelayAddressing(NamedBeanAddressing.Reference);
157            } else if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayLocalVariable) {
158                action.setDelayAddressing(NamedBeanAddressing.LocalVariable);
159            } else if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayFormula) {
160                action.setDelayAddressing(NamedBeanAddressing.Formula);
161            } else {
162                throw new IllegalArgumentException("_tabbedPane has unknown selection");
163            }
164        } catch (ParserException e) {
165            errorMessages.add("Cannot parse formula: " + e.getMessage());
166            return false;
167        }
168        return true;
169    }
170    
171    /** {@inheritDoc} */
172    @Override
173    public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) {
174        ExecuteDelayed action = new ExecuteDelayed(systemName, userName);
175        updateObject(action);
176        return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action);
177    }
178    
179    /** {@inheritDoc} */
180    @Override
181    public void updateObject(@Nonnull Base object) {
182        if (!(object instanceof ExecuteDelayed)) {
183            throw new IllegalArgumentException("object must be an ExecuteDelayed but is a: "+object.getClass().getName());
184        }
185        
186        ExecuteDelayed action = (ExecuteDelayed)object;
187        
188        action.setUnit(_unitComboBox.getItemAt(_unitComboBox.getSelectedIndex()));
189        action.setResetIfAlreadyStarted(_resetIfAlreadyStarted.isSelected());
190        action.setUseIndividualTimers(_useIndividualTimers.isSelected());
191        
192        
193        
194        try {
195            if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayDirect) {
196                action.setDelayAddressing(NamedBeanAddressing.Direct);
197                action.setDelay(Integer.parseInt(_timerDelay.getText()));
198            } else if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayReference) {
199                action.setDelayAddressing(NamedBeanAddressing.Reference);
200                action.setDelayReference(_delayReferenceTextField.getText());
201            } else if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayLocalVariable) {
202                action.setDelayAddressing(NamedBeanAddressing.LocalVariable);
203                action.setDelayLocalVariable(_delayLocalVariableTextField.getText());
204            } else if (_tabbedPaneDelay.getSelectedComponent() == _panelDelayFormula) {
205                action.setDelayAddressing(NamedBeanAddressing.Formula);
206                action.setDelayFormula(_delayFormulaTextField.getText());
207            } else {
208                throw new IllegalArgumentException("_tabbedPaneDelay has unknown selection");
209            }
210        } catch (ParserException e) {
211            throw new RuntimeException("ParserException: "+e.getMessage(), e);
212        }
213    }
214    
215    /** {@inheritDoc} */
216    @Override
217    public String toString() {
218        return Bundle.getMessage("ExecuteDelayed_Short");
219    }
220    
221    @Override
222    public void dispose() {
223    }
224    
225}