001package jmri.jmrit.display.logixng.swing;
002
003import java.awt.event.ActionEvent;
004import java.util.*;
005
006import javax.annotation.CheckForNull;
007import javax.annotation.Nonnull;
008import javax.swing.*;
009
010import jmri.InstanceManager;
011import jmri.jmrit.display.Editor;
012import jmri.jmrit.display.EditorManager;
013import jmri.jmrit.logixng.*;
014import jmri.jmrit.display.logixng.ActionPositionableByClass;
015import jmri.jmrit.display.logixng.ActionPositionableByClass.Operation;
016import jmri.jmrit.logixng.actions.swing.AbstractDigitalActionSwing;
017import jmri.jmrit.logixng.swing.SwingConfiguratorInterface;
018import jmri.jmrit.logixng.util.parser.ParserException;
019import jmri.util.swing.JComboBoxUtil;
020
021/**
022 * Configures an ActionPositionableByClass object with a Swing JPanel.
023 *
024 * @author Daniel Bergqvist Copyright (C) 2023
025 */
026public class ActionPositionableByClassSwing extends AbstractDigitalActionSwing {
027
028    private String _selectedEditor;
029
030    private JComboBox<EditorItem> _editorComboBox;
031    private JTabbedPane _tabbedPanePositionable;
032    private JComboBox<String> _classNamesComboBox;
033    private JPanel _panelPositionableDirect;
034    private JPanel _panelPositionableReference;
035    private JPanel _panelPositionableLocalVariable;
036    private JPanel _panelPositionableFormula;
037    private JTextField _positionableReferenceTextField;
038    private JTextField _positionableLocalVariableTextField;
039    private JTextField _positionableFormulaTextField;
040
041    private JTabbedPane _tabbedPanePositionableState;
042    private JComboBox<Operation> _isControllingComboBox;
043    private JPanel _panelPositionableStateDirect;
044    private JPanel _panelPositionableStateReference;
045    private JPanel _panelPositionableStateLocalVariable;
046    private JPanel _panelPositionableStateFormula;
047    private JTextField _positionableStateReferenceTextField;
048    private JTextField _positionableStateLocalVariableTextField;
049    private JTextField _positionableStateFormulaTextField;
050
051
052    @Override
053    protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) {
054        ActionPositionableByClass action = (ActionPositionableByClass)object;
055
056        panel = new JPanel();
057
058        _selectedEditor = action != null ? action.getEditorName() : null;
059
060        _editorComboBox = new JComboBox<>();
061        JComboBoxUtil.setupComboBoxMaxRows(_editorComboBox);
062        for (Editor editor : jmri.InstanceManager.getDefault(EditorManager.class).getAll()) {
063            EditorItem item = new EditorItem(editor);
064            _editorComboBox.addItem(item);
065            if (editor.getName().equals(_selectedEditor)) _editorComboBox.setSelectedItem(item);
066        }
067        _editorComboBox.addActionListener(this::updatePositionables);
068
069        _tabbedPanePositionable = new JTabbedPane();
070        _panelPositionableDirect = new javax.swing.JPanel();
071        _panelPositionableReference = new javax.swing.JPanel();
072        _panelPositionableLocalVariable = new javax.swing.JPanel();
073        _panelPositionableFormula = new javax.swing.JPanel();
074
075        _tabbedPanePositionable.addTab(NamedBeanAddressing.Direct.toString(), _panelPositionableDirect);
076        _tabbedPanePositionable.addTab(NamedBeanAddressing.Reference.toString(), _panelPositionableReference);
077        _tabbedPanePositionable.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelPositionableLocalVariable);
078        _tabbedPanePositionable.addTab(NamedBeanAddressing.Formula.toString(), _panelPositionableFormula);
079
080        _classNamesComboBox = new JComboBox<>();
081        JComboBoxUtil.setupComboBoxMaxRows(_classNamesComboBox);
082        updatePositionables(null);
083        _panelPositionableDirect.add(_classNamesComboBox);
084
085        _positionableReferenceTextField = new JTextField();
086        _positionableReferenceTextField.setColumns(30);
087        _panelPositionableReference.add(_positionableReferenceTextField);
088
089        _positionableLocalVariableTextField = new JTextField();
090        _positionableLocalVariableTextField.setColumns(30);
091        _panelPositionableLocalVariable.add(_positionableLocalVariableTextField);
092
093        _positionableFormulaTextField = new JTextField();
094        _positionableFormulaTextField.setColumns(30);
095        _panelPositionableFormula.add(_positionableFormulaTextField);
096
097
098        _tabbedPanePositionableState = new JTabbedPane();
099        _panelPositionableStateDirect = new javax.swing.JPanel();
100        _panelPositionableStateReference = new javax.swing.JPanel();
101        _panelPositionableStateLocalVariable = new javax.swing.JPanel();
102        _panelPositionableStateFormula = new javax.swing.JPanel();
103
104        _tabbedPanePositionableState.addTab(NamedBeanAddressing.Direct.toString(), _panelPositionableStateDirect);
105        _tabbedPanePositionableState.addTab(NamedBeanAddressing.Reference.toString(), _panelPositionableStateReference);
106        _tabbedPanePositionableState.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelPositionableStateLocalVariable);
107        _tabbedPanePositionableState.addTab(NamedBeanAddressing.Formula.toString(), _panelPositionableStateFormula);
108
109        _isControllingComboBox = new JComboBox<>();
110        for (Operation e : Operation.values()) {
111            _isControllingComboBox.addItem(e);
112        }
113        JComboBoxUtil.setupComboBoxMaxRows(_isControllingComboBox);
114
115        _panelPositionableStateDirect.add(_isControllingComboBox);
116
117        _positionableStateReferenceTextField = new JTextField();
118        _positionableStateReferenceTextField.setColumns(30);
119        _panelPositionableStateReference.add(_positionableStateReferenceTextField);
120
121        _positionableStateLocalVariableTextField = new JTextField();
122        _positionableStateLocalVariableTextField.setColumns(30);
123        _panelPositionableStateLocalVariable.add(_positionableStateLocalVariableTextField);
124
125        _positionableStateFormulaTextField = new JTextField();
126        _positionableStateFormulaTextField.setColumns(30);
127        _panelPositionableStateFormula.add(_positionableStateFormulaTextField);
128
129
130        if (action != null) {
131            switch (action.getAddressing()) {
132                case Direct: _tabbedPanePositionable.setSelectedComponent(_panelPositionableDirect); break;
133                case Reference: _tabbedPanePositionable.setSelectedComponent(_panelPositionableReference); break;
134                case LocalVariable: _tabbedPanePositionable.setSelectedComponent(_panelPositionableLocalVariable); break;
135                case Formula: _tabbedPanePositionable.setSelectedComponent(_panelPositionableFormula); break;
136                default: throw new IllegalArgumentException("invalid _addressing state: " + action.getAddressing().name());
137            }
138            if (action.getClassName() != null) {
139                _classNamesComboBox.setSelectedItem(action.getClassName());
140            }
141            _positionableReferenceTextField.setText(action.getReference());
142            _positionableLocalVariableTextField.setText(action.getLocalVariable());
143            _positionableFormulaTextField.setText(action.getFormula());
144
145            switch (action.getStateAddressing()) {
146                case Direct: _tabbedPanePositionableState.setSelectedComponent(_panelPositionableStateDirect); break;
147                case Reference: _tabbedPanePositionableState.setSelectedComponent(_panelPositionableStateReference); break;
148                case LocalVariable: _tabbedPanePositionableState.setSelectedComponent(_panelPositionableStateLocalVariable); break;
149                case Formula: _tabbedPanePositionableState.setSelectedComponent(_panelPositionableStateFormula); break;
150                default: throw new IllegalArgumentException("invalid _addressing state: " + action.getAddressing().name());
151            }
152            _isControllingComboBox.setSelectedItem(action.getOperation());
153            _positionableStateReferenceTextField.setText(action.getStateReference());
154            _positionableStateLocalVariableTextField.setText(action.getStateLocalVariable());
155            _positionableStateFormulaTextField.setText(action.getStateFormula());
156        }
157
158        JComponent[] components = new JComponent[]{
159            _editorComboBox,
160            _tabbedPanePositionable,
161            _tabbedPanePositionableState};
162
163        List<JComponent> componentList = SwingConfiguratorInterface.parseMessage(
164                Bundle.getMessage("ActionPositionableByClass_Components"), components);
165
166        for (JComponent c : componentList) panel.add(c);
167    }
168
169    private void updatePositionables(ActionEvent e) {
170        _classNamesComboBox.removeAllItems();
171        if (_editorComboBox.getSelectedIndex() == -1) return;
172
173        EditorItem item = _editorComboBox.getItemAt(_editorComboBox.getSelectedIndex());
174        List<String> list = new ArrayList<>();
175        for (String className : item._editor.getClassNames()) {
176            list.add(className);
177        }
178        Collections.sort(list);
179        for (String s : list) {
180            _classNamesComboBox.addItem(s);
181        }
182    }
183
184    /** {@inheritDoc} */
185    @Override
186    public boolean validate(@Nonnull List<String> errorMessages) {
187        // Create a temporary action to test formula
188        ActionPositionableByClass action = new ActionPositionableByClass("IQDA1", null);
189
190        try {
191            if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableReference) {
192                action.setReference(_positionableReferenceTextField.getText());
193            }
194        } catch (IllegalArgumentException e) {
195            errorMessages.add(e.getMessage());
196            return false;
197        }
198
199        try {
200            if (_tabbedPanePositionableState.getSelectedComponent() == _panelPositionableStateReference) {
201                action.setStateReference(_positionableStateReferenceTextField.getText());
202            }
203        } catch (IllegalArgumentException e) {
204            errorMessages.add(e.getMessage());
205            return false;
206        }
207
208        try {
209            action.setFormula(_positionableFormulaTextField.getText());
210            if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableDirect) {
211                action.setAddressing(NamedBeanAddressing.Direct);
212            } else if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableReference) {
213                action.setAddressing(NamedBeanAddressing.Reference);
214            } else if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableLocalVariable) {
215                action.setAddressing(NamedBeanAddressing.LocalVariable);
216            } else if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableFormula) {
217                action.setAddressing(NamedBeanAddressing.Formula);
218            } else {
219                throw new IllegalArgumentException("_tabbedPane has unknown selection");
220            }
221        } catch (ParserException e) {
222            errorMessages.add("Cannot parse formula: " + e.getMessage());
223        }
224        return errorMessages.isEmpty();
225    }
226
227    /** {@inheritDoc} */
228    @Override
229    public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) {
230        ActionPositionableByClass action = new ActionPositionableByClass(systemName, userName);
231        updateObject(action);
232        return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action);
233    }
234
235    /** {@inheritDoc} */
236    @Override
237    public void updateObject(@Nonnull Base object) {
238        if (! (object instanceof ActionPositionableByClass)) {
239            throw new IllegalArgumentException("object must be an ActionPositionableByClass but is a: "+object.getClass().getName());
240        }
241        ActionPositionableByClass action = (ActionPositionableByClass)object;
242        if (_editorComboBox.getSelectedIndex() != -1) {
243            action.setEditor(_editorComboBox.getItemAt(_editorComboBox.getSelectedIndex())._editor.getName());
244        }
245        if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableDirect) {
246            action.setClassName(_classNamesComboBox.getItemAt(_classNamesComboBox.getSelectedIndex()));
247        }
248        try {
249            if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableDirect) {
250                action.setAddressing(NamedBeanAddressing.Direct);
251            } else if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableReference) {
252                action.setAddressing(NamedBeanAddressing.Reference);
253                action.setReference(_positionableReferenceTextField.getText());
254            } else if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableLocalVariable) {
255                action.setAddressing(NamedBeanAddressing.LocalVariable);
256                action.setLocalVariable(_positionableLocalVariableTextField.getText());
257            } else if (_tabbedPanePositionable.getSelectedComponent() == _panelPositionableFormula) {
258                action.setAddressing(NamedBeanAddressing.Formula);
259                action.setFormula(_positionableFormulaTextField.getText());
260            } else {
261                throw new IllegalArgumentException("_tabbedPanePositionable has unknown selection");
262            }
263
264            if (_tabbedPanePositionableState.getSelectedComponent() == _panelPositionableStateDirect) {
265                action.setStateAddressing(NamedBeanAddressing.Direct);
266                action.setOperation(_isControllingComboBox.getItemAt(_isControllingComboBox.getSelectedIndex()));
267            } else if (_tabbedPanePositionableState.getSelectedComponent() == _panelPositionableStateReference) {
268                action.setStateAddressing(NamedBeanAddressing.Reference);
269                action.setStateReference(_positionableStateReferenceTextField.getText());
270            } else if (_tabbedPanePositionableState.getSelectedComponent() == _panelPositionableStateLocalVariable) {
271                action.setStateAddressing(NamedBeanAddressing.LocalVariable);
272                action.setStateLocalVariable(_positionableStateLocalVariableTextField.getText());
273            } else if (_tabbedPanePositionableState.getSelectedComponent() == _panelPositionableStateFormula) {
274                action.setStateAddressing(NamedBeanAddressing.Formula);
275                action.setStateFormula(_positionableStateFormulaTextField.getText());
276            } else {
277                throw new IllegalArgumentException("_tabbedPanePositionableState has unknown selection");
278            }
279        } catch (ParserException e) {
280            throw new RuntimeException("ParserException: "+e.getMessage(), e);
281        }
282    }
283
284    /** {@inheritDoc} */
285    @Override
286    public String toString() {
287        return Bundle.getMessage("ActionPositionableByClass_Short");
288    }
289
290    @Override
291    public void dispose() {
292        // Do nothing
293    }
294
295
296    private static class EditorItem {
297
298        private final Editor _editor;
299
300        public EditorItem(Editor editor) {
301            this._editor = editor;
302        }
303
304        @Override
305        public String toString() {
306            return _editor.getName();
307        }
308    }
309
310
311//    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionPositionableByClassSwing.class);
312
313}