001package jmri.jmrit.logixng.expressions.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.expressions.ExpressionReporter;
013import jmri.jmrit.logixng.expressions.ExpressionReporter.CompareTo;
014import jmri.jmrit.logixng.expressions.ExpressionReporter.ReporterOperation;
015import jmri.jmrit.logixng.expressions.ExpressionReporter.ReporterValue;
016import jmri.jmrit.logixng.swing.SwingConfiguratorInterface;
017import jmri.jmrit.logixng.util.swing.LogixNG_SelectNamedBeanSwing;
018import jmri.util.swing.BeanSelectPanel;
019import jmri.util.swing.JComboBoxUtil;
020
021/**
022 * Configures an ExpressionReporter object with a Swing JPanel.
023 *
024 * @author Daniel Bergqvist Copyright 2021
025 * @author Dave Sand Copyright 2021
026 */
027public class ExpressionReporterSwing extends AbstractDigitalExpressionSwing {
028
029    private LogixNG_SelectNamedBeanSwing<Reporter> _selectNamedBeanSwing;
030    private JComboBox<ReporterValue> _reporterValueComboBox;
031    private JComboBox<ReporterOperation> _reporterOperationComboBox;
032    private JCheckBox _caseInsensitiveCheckBox;
033
034    private JTabbedPane _tabbedPane;
035
036    private JTabbedPane _tabbedPaneCompareTo;
037    private BeanSelectPanel<Memory> _compareToMemoryBeanPanel;
038    private JPanel _reporterValuePanel;
039    private JPanel _compareToConstant;
040    private JPanel _compareToMemory;
041    private JPanel _compareToLocalVariable;
042    private JPanel _compareToRegEx;
043    private JTextField _compareToConstantTextField;
044    private JTextField _compareToLocalVariableTextField;
045    private JTextField _compareToRegExTextField;
046
047
048    private void enableDisableCompareTo() {
049        ReporterOperation mo = _reporterOperationComboBox.getItemAt(
050                        _reporterOperationComboBox.getSelectedIndex());
051        boolean enable = mo.hasExtraValue();
052        _tabbedPaneCompareTo.setEnabled(enable);
053        ((JPanel)_tabbedPaneCompareTo.getSelectedComponent())
054                .getComponent(0).setEnabled(enable);
055
056        boolean regEx = (mo == ReporterOperation.MatchRegex)
057                || (mo == ReporterOperation.NotMatchRegex);
058        _tabbedPane.setEnabledAt(0, !regEx);
059        _tabbedPane.setEnabledAt(1, regEx);
060        _tabbedPane.setSelectedIndex(regEx ? 1 : 0);
061    }
062
063    @Override
064    protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) {
065        ExpressionReporter expression = (ExpressionReporter)object;
066
067        panel = new JPanel();
068
069        _selectNamedBeanSwing = new LogixNG_SelectNamedBeanSwing<>(
070                InstanceManager.getDefault(ReporterManager.class), getJDialog(), this);
071
072        JPanel _tabbedPaneNamedBean;
073
074        if (expression != null) {
075            _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(expression.getSelectNamedBean());
076        } else {
077            _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(null);
078        }
079
080        _reporterValuePanel = new JPanel();
081        _reporterValueComboBox = new JComboBox<>();
082        for (ReporterValue e : ReporterValue.values()) {
083            _reporterValueComboBox.addItem(e);
084        }
085        JComboBoxUtil.setupComboBoxMaxRows(_reporterValueComboBox);
086        _reporterValuePanel.add(_reporterValueComboBox);
087
088        JPanel operationAndCasePanel = new JPanel();
089        operationAndCasePanel.setLayout(new BoxLayout(operationAndCasePanel, BoxLayout.Y_AXIS));
090
091        _reporterOperationComboBox = new JComboBox<>();
092        for (ReporterOperation e : ReporterOperation.values()) {
093            _reporterOperationComboBox.addItem(e);
094        }
095        JComboBoxUtil.setupComboBoxMaxRows(_reporterOperationComboBox);
096        if (expression == null) {
097            _reporterOperationComboBox.setSelectedItem(ReporterOperation.Equal);
098        }
099        operationAndCasePanel.add(_reporterOperationComboBox);
100
101        _reporterOperationComboBox.addActionListener((e) -> { enableDisableCompareTo(); });
102
103        _caseInsensitiveCheckBox = new JCheckBox(Bundle.getMessage("ExpressionReporter_CaseInsensitive"));
104        operationAndCasePanel.add(_caseInsensitiveCheckBox);
105
106        _tabbedPane = new JTabbedPane();
107
108        _tabbedPaneCompareTo = new JTabbedPane();
109        _tabbedPane.addTab("", _tabbedPaneCompareTo);
110
111        _compareToConstant = new JPanel();
112        _compareToMemory = new JPanel();
113        _compareToLocalVariable = new JPanel();
114        _compareToRegEx = new JPanel();
115
116        _tabbedPaneCompareTo.addTab(CompareTo.Value.toString(), _compareToConstant);
117        _tabbedPaneCompareTo.addTab(CompareTo.Memory.toString(), _compareToMemory);
118        _tabbedPaneCompareTo.addTab(CompareTo.LocalVariable.toString(), _compareToLocalVariable);
119
120        _tabbedPane.addTab(CompareTo.RegEx.toString(), _compareToRegEx);
121
122        _compareToConstantTextField = new JTextField(30);
123        _compareToConstant.add(_compareToConstantTextField);
124
125        _compareToMemoryBeanPanel = new BeanSelectPanel<>(InstanceManager.getDefault(MemoryManager.class), null);
126        _compareToMemory.add(_compareToMemoryBeanPanel);
127
128        _compareToLocalVariableTextField = new JTextField(30);
129        _compareToLocalVariable.add(_compareToLocalVariableTextField);
130
131        _compareToRegExTextField = new JTextField(30);
132        _compareToRegEx.add(_compareToRegExTextField);
133
134
135        if (expression != null) {
136            if (expression.getSelectMemoryNamedBean().getNamedBean() != null) {
137                _compareToMemoryBeanPanel.setDefaultNamedBean(expression.getSelectMemoryNamedBean().getNamedBean().getBean());
138            }
139            switch (expression.getCompareTo()) {
140                case RegEx:
141                case Value: _tabbedPaneCompareTo.setSelectedComponent(_compareToConstant); break;
142                case Memory: _tabbedPaneCompareTo.setSelectedComponent(_compareToMemory); break;
143                case LocalVariable: _tabbedPaneCompareTo.setSelectedComponent(_compareToLocalVariable); break;
144                default: throw new IllegalArgumentException("invalid _addressing state: " + expression.getCompareTo().name());
145            }
146            _reporterValueComboBox.setSelectedItem(expression.getReporterValue());
147            _reporterOperationComboBox.setSelectedItem(expression.getReporterOperation());
148            _caseInsensitiveCheckBox.setSelected(expression.getCaseInsensitive());
149            _compareToConstantTextField.setText(expression.getConstantValue());
150            _compareToLocalVariableTextField.setText(expression.getLocalVariable());
151            _compareToRegExTextField.setText(expression.getRegEx());
152        }
153
154        JComponent[] components = new JComponent[]{
155            _tabbedPaneNamedBean,
156            _reporterValuePanel,
157            operationAndCasePanel,
158            _tabbedPane
159        };
160
161        List<JComponent> componentList = SwingConfiguratorInterface.parseMessage(
162                Bundle.getMessage("ExpressionReporter_Components"), components);
163
164        for (JComponent c : componentList) panel.add(c);
165
166        enableDisableCompareTo();
167    }
168
169    /** {@inheritDoc} */
170    @Override
171    public boolean validate(@Nonnull List<String> errorMessages) {
172        // Create a temporary expression to test formula
173        ExpressionReporter expression = new ExpressionReporter("IQDE1", null);
174
175        if (_selectNamedBeanSwing.getAddressing() == NamedBeanAddressing.Direct
176                && _selectNamedBeanSwing.getBean() == null) {
177            errorMessages.add(Bundle.getMessage("Reporter_No_Reporter"));
178        }
179        _selectNamedBeanSwing.validate(expression.getSelectNamedBean(), errorMessages);
180        return errorMessages.isEmpty();
181    }
182
183    /** {@inheritDoc} */
184    @Override
185    public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) {
186        ExpressionReporter expression = new ExpressionReporter(systemName, userName);
187        updateObject(expression);
188        return InstanceManager.getDefault(DigitalExpressionManager.class).registerExpression(expression);
189    }
190
191    /** {@inheritDoc} */
192    @Override
193    public void updateObject(@Nonnull Base object) {
194        if (! (object instanceof ExpressionReporter)) {
195            throw new IllegalArgumentException("object must be an ExpressionReporter but is a: "+object.getClass().getName());
196        }
197        ExpressionReporter expression = (ExpressionReporter)object;
198        
199        _selectNamedBeanSwing.updateObject(expression.getSelectNamedBean());
200
201        expression.setReporterValue(_reporterValueComboBox.getItemAt(_reporterValueComboBox.getSelectedIndex()));
202        expression.setReporterOperation(_reporterOperationComboBox.getItemAt(_reporterOperationComboBox.getSelectedIndex()));
203        expression.setCaseInsensitive(_caseInsensitiveCheckBox.isSelected());
204
205
206        if (!_compareToMemoryBeanPanel.isEmpty()
207                && (_tabbedPane.getSelectedComponent() == _tabbedPaneCompareTo)
208                && (_tabbedPaneCompareTo.getSelectedComponent() == _compareToMemory)) {
209            Memory memory = _compareToMemoryBeanPanel.getNamedBean();
210            if (memory != null) {
211                NamedBeanHandle<Memory> handle
212                        = InstanceManager.getDefault(NamedBeanHandleManager.class)
213                                .getNamedBeanHandle(memory.getDisplayName(), memory);
214                expression.getSelectMemoryNamedBean().setNamedBean(handle);
215            } else {
216                expression.getSelectMemoryNamedBean().removeNamedBean();
217            }
218        } else {
219            expression.getSelectMemoryNamedBean().removeNamedBean();
220        }
221
222        if (_tabbedPane.getSelectedComponent() == _tabbedPaneCompareTo) {
223            if (_tabbedPaneCompareTo.getSelectedComponent() == _compareToConstant) {
224                expression.setCompareTo(CompareTo.Value);
225                expression.setConstantValue(_compareToConstantTextField.getText());
226            } else if (_tabbedPaneCompareTo.getSelectedComponent() == _compareToMemory) {
227                expression.setCompareTo(CompareTo.Memory);
228            } else if (_tabbedPaneCompareTo.getSelectedComponent() == _compareToLocalVariable) {
229                expression.setCompareTo(CompareTo.LocalVariable);
230                expression.setLocalVariable(_compareToLocalVariableTextField.getText());
231//            } else if (_tabbedPaneCompareTo.getSelectedComponent() == _compareToRegEx) {
232//                expression.setCompareTo(CompareTo.RegEx);
233//                expression.setRegEx(_compareToRegExTextField.getText());
234            } else {
235                throw new IllegalArgumentException("_tabbedPaneLight has unknown selection");
236            }
237        } else {
238            expression.setCompareTo(CompareTo.RegEx);
239            expression.setRegEx(_compareToRegExTextField.getText());
240        }
241    }
242
243    /** {@inheritDoc} */
244    @Override
245    public String toString() {
246        return Bundle.getMessage("Reporter_Short");
247    }
248
249    @Override
250    public void setDefaultValues() {
251        if (_selectNamedBeanSwing.getBean() == null) {
252            SortedSet<Reporter> set = InstanceManager.getDefault(ReporterManager.class).getNamedBeanSet();
253            if (!set.isEmpty()) {
254                Reporter r = set.first();
255                _selectNamedBeanSwing.getBeanSelectPanel().setDefaultNamedBean(r);
256            } else {
257                log.error("Reporter manager has no reporters. Can't set default values");
258            }
259        }
260    }
261
262    @Override
263    public void dispose() {
264        _selectNamedBeanSwing.dispose();
265    }
266
267
268    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ExpressionReporterSwing.class);
269
270}