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