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.EditorManager; 012import jmri.jmrit.display.layoutEditor.LayoutEditor; 013import jmri.jmrit.display.layoutEditor.LayoutTurnout; 014import jmri.jmrit.display.logixng.ActionLayoutTurnout; 015import jmri.jmrit.display.logixng.ActionLayoutTurnout.Operation; 016import jmri.jmrit.logixng.*; 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 ActionLayoutTurnout object with a Swing JPanel. 024 * 025 * @author Daniel Bergqvist Copyright (C) 2022 026 */ 027public class ActionLayoutTurnoutSwing extends AbstractDigitalActionSwing { 028 029 private String _selectedLayoutEditor; 030 031 private JComboBox<EditorItem> _layoutEditorComboBox; 032 private JTabbedPane _tabbedPaneLayoutTurnout; 033 private JComboBox<Turnout> _layoutTurnoutComboBox; 034 private JPanel _panelLayoutTurnoutDirect; 035 private JPanel _panelLayoutTurnoutReference; 036 private JPanel _panelLayoutTurnoutLocalVariable; 037 private JPanel _panelLayoutTurnoutFormula; 038 private JTextField _layoutTurnoutReferenceTextField; 039 private JTextField _layoutTurnoutLocalVariableTextField; 040 private JTextField _layoutTurnoutFormulaTextField; 041 042 private JTabbedPane _tabbedPaneLayoutTurnoutState; 043 private JComboBox<Operation> _isControllingComboBox; 044 private JPanel _panelLayoutTurnoutStateDirect; 045 private JPanel _panelLayoutTurnoutStateReference; 046 private JPanel _panelLayoutTurnoutStateLocalVariable; 047 private JPanel _panelLayoutTurnoutStateFormula; 048 private JTextField _layoutTurnoutStateReferenceTextField; 049 private JTextField _layoutTurnoutStateLocalVariableTextField; 050 private JTextField _layoutTurnoutStateFormulaTextField; 051 052 053 @Override 054 protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) { 055 ActionLayoutTurnout action = (ActionLayoutTurnout)object; 056 057 panel = new JPanel(); 058 059 _selectedLayoutEditor = action != null ? action.getLayoutEditorName() : null; 060 061 _layoutEditorComboBox = new JComboBox<>(); 062 JComboBoxUtil.setupComboBoxMaxRows(_layoutEditorComboBox); 063 for (LayoutEditor layoutEditor : jmri.InstanceManager.getDefault(EditorManager.class).getAll(LayoutEditor.class)) { 064 EditorItem item = new EditorItem(layoutEditor); 065 _layoutEditorComboBox.addItem(item); 066 if (layoutEditor.getName().equals(_selectedLayoutEditor)) _layoutEditorComboBox.setSelectedItem(item); 067 } 068 _layoutEditorComboBox.addActionListener(this::updateLayoutTurnouts); 069 070 _tabbedPaneLayoutTurnout = new JTabbedPane(); 071 _panelLayoutTurnoutDirect = new javax.swing.JPanel(); 072 _panelLayoutTurnoutReference = new javax.swing.JPanel(); 073 _panelLayoutTurnoutLocalVariable = new javax.swing.JPanel(); 074 _panelLayoutTurnoutFormula = new javax.swing.JPanel(); 075 076 _tabbedPaneLayoutTurnout.addTab(NamedBeanAddressing.Direct.toString(), _panelLayoutTurnoutDirect); 077 _tabbedPaneLayoutTurnout.addTab(NamedBeanAddressing.Reference.toString(), _panelLayoutTurnoutReference); 078 _tabbedPaneLayoutTurnout.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelLayoutTurnoutLocalVariable); 079 _tabbedPaneLayoutTurnout.addTab(NamedBeanAddressing.Formula.toString(), _panelLayoutTurnoutFormula); 080 081 _layoutTurnoutComboBox = new JComboBox<>(); 082 JComboBoxUtil.setupComboBoxMaxRows(_layoutTurnoutComboBox); 083 updateLayoutTurnouts(null); 084 _panelLayoutTurnoutDirect.add(_layoutTurnoutComboBox); 085 086 _layoutTurnoutReferenceTextField = new JTextField(); 087 _layoutTurnoutReferenceTextField.setColumns(30); 088 _panelLayoutTurnoutReference.add(_layoutTurnoutReferenceTextField); 089 090 _layoutTurnoutLocalVariableTextField = new JTextField(); 091 _layoutTurnoutLocalVariableTextField.setColumns(30); 092 _panelLayoutTurnoutLocalVariable.add(_layoutTurnoutLocalVariableTextField); 093 094 _layoutTurnoutFormulaTextField = new JTextField(); 095 _layoutTurnoutFormulaTextField.setColumns(30); 096 _panelLayoutTurnoutFormula.add(_layoutTurnoutFormulaTextField); 097 098 099 _tabbedPaneLayoutTurnoutState = new JTabbedPane(); 100 _panelLayoutTurnoutStateDirect = new javax.swing.JPanel(); 101 _panelLayoutTurnoutStateReference = new javax.swing.JPanel(); 102 _panelLayoutTurnoutStateLocalVariable = new javax.swing.JPanel(); 103 _panelLayoutTurnoutStateFormula = new javax.swing.JPanel(); 104 105 _tabbedPaneLayoutTurnoutState.addTab(NamedBeanAddressing.Direct.toString(), _panelLayoutTurnoutStateDirect); 106 _tabbedPaneLayoutTurnoutState.addTab(NamedBeanAddressing.Reference.toString(), _panelLayoutTurnoutStateReference); 107 _tabbedPaneLayoutTurnoutState.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelLayoutTurnoutStateLocalVariable); 108 _tabbedPaneLayoutTurnoutState.addTab(NamedBeanAddressing.Formula.toString(), _panelLayoutTurnoutStateFormula); 109 110 _isControllingComboBox = new JComboBox<>(); 111 for (Operation e : Operation.values()) { 112 _isControllingComboBox.addItem(e); 113 } 114 JComboBoxUtil.setupComboBoxMaxRows(_isControllingComboBox); 115 116 _panelLayoutTurnoutStateDirect.add(_isControllingComboBox); 117 118 _layoutTurnoutStateReferenceTextField = new JTextField(); 119 _layoutTurnoutStateReferenceTextField.setColumns(30); 120 _panelLayoutTurnoutStateReference.add(_layoutTurnoutStateReferenceTextField); 121 122 _layoutTurnoutStateLocalVariableTextField = new JTextField(); 123 _layoutTurnoutStateLocalVariableTextField.setColumns(30); 124 _panelLayoutTurnoutStateLocalVariable.add(_layoutTurnoutStateLocalVariableTextField); 125 126 _layoutTurnoutStateFormulaTextField = new JTextField(); 127 _layoutTurnoutStateFormulaTextField.setColumns(30); 128 _panelLayoutTurnoutStateFormula.add(_layoutTurnoutStateFormulaTextField); 129 130 131 if (action != null) { 132 switch (action.getAddressing()) { 133 case Direct: _tabbedPaneLayoutTurnout.setSelectedComponent(_panelLayoutTurnoutDirect); break; 134 case Reference: _tabbedPaneLayoutTurnout.setSelectedComponent(_panelLayoutTurnoutReference); break; 135 case LocalVariable: _tabbedPaneLayoutTurnout.setSelectedComponent(_panelLayoutTurnoutLocalVariable); break; 136 case Formula: _tabbedPaneLayoutTurnout.setSelectedComponent(_panelLayoutTurnoutFormula); break; 137 default: throw new IllegalArgumentException("invalid _addressing state: " + action.getAddressing().name()); 138 } 139 if (action.getLayoutTurnout() != null) { 140 _layoutTurnoutComboBox.setSelectedItem(action.getLayoutTurnout()); 141 } 142 _layoutTurnoutReferenceTextField.setText(action.getReference()); 143 _layoutTurnoutLocalVariableTextField.setText(action.getLocalVariable()); 144 _layoutTurnoutFormulaTextField.setText(action.getFormula()); 145 146 switch (action.getStateAddressing()) { 147 case Direct: _tabbedPaneLayoutTurnoutState.setSelectedComponent(_panelLayoutTurnoutStateDirect); break; 148 case Reference: _tabbedPaneLayoutTurnoutState.setSelectedComponent(_panelLayoutTurnoutStateReference); break; 149 case LocalVariable: _tabbedPaneLayoutTurnoutState.setSelectedComponent(_panelLayoutTurnoutStateLocalVariable); break; 150 case Formula: _tabbedPaneLayoutTurnoutState.setSelectedComponent(_panelLayoutTurnoutStateFormula); break; 151 default: throw new IllegalArgumentException("invalid _addressing state: " + action.getAddressing().name()); 152 } 153 _isControllingComboBox.setSelectedItem(action.getOperation()); 154 _layoutTurnoutStateReferenceTextField.setText(action.getStateReference()); 155 _layoutTurnoutStateLocalVariableTextField.setText(action.getStateLocalVariable()); 156 _layoutTurnoutStateFormulaTextField.setText(action.getStateFormula()); 157 } 158 159 JComponent[] components = new JComponent[]{ 160 _layoutEditorComboBox, 161 _tabbedPaneLayoutTurnout, 162 _tabbedPaneLayoutTurnoutState}; 163 164 List<JComponent> componentList = SwingConfiguratorInterface.parseMessage( 165 Bundle.getMessage("ActionLayoutTurnout_Components"), components); 166 167 for (JComponent c : componentList) panel.add(c); 168 } 169 170 private void updateLayoutTurnouts(ActionEvent e) { 171 _layoutTurnoutComboBox.removeAllItems(); 172 if (_layoutEditorComboBox.getSelectedIndex() == -1) return; 173 174 EditorItem item = _layoutEditorComboBox.getItemAt(_layoutEditorComboBox.getSelectedIndex()); 175 List<LayoutTurnout> list = new ArrayList<>(); 176 for (LayoutTurnout layoutTurnout : item._layoutEditor.getLayoutTurnouts()) { 177 if (!layoutTurnout.getTurnoutName().isBlank()) { 178 list.add(layoutTurnout); 179 } 180 } 181 Collections.sort(list, (o1,o2) -> o1.getTurnoutName().compareTo(o2.getTurnoutName())); 182 for (LayoutTurnout lt : list) { 183 _layoutTurnoutComboBox.addItem(new Turnout(lt)); 184 } 185 } 186 187 /** {@inheritDoc} */ 188 @Override 189 public boolean validate(@Nonnull List<String> errorMessages) { 190 // Create a temporary action to test formula 191 ActionLayoutTurnout action = new ActionLayoutTurnout("IQDA1", null); 192 193 try { 194 if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutReference) { 195 action.setReference(_layoutTurnoutReferenceTextField.getText()); 196 } 197 } catch (IllegalArgumentException e) { 198 errorMessages.add(e.getMessage()); 199 return false; 200 } 201 202 try { 203 if (_tabbedPaneLayoutTurnoutState.getSelectedComponent() == _panelLayoutTurnoutStateReference) { 204 action.setStateReference(_layoutTurnoutStateReferenceTextField.getText()); 205 } 206 } catch (IllegalArgumentException e) { 207 errorMessages.add(e.getMessage()); 208 return false; 209 } 210 211 try { 212 action.setFormula(_layoutTurnoutFormulaTextField.getText()); 213 if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutDirect) { 214 action.setAddressing(NamedBeanAddressing.Direct); 215 } else if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutReference) { 216 action.setAddressing(NamedBeanAddressing.Reference); 217 } else if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutLocalVariable) { 218 action.setAddressing(NamedBeanAddressing.LocalVariable); 219 } else if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutFormula) { 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 ActionLayoutTurnout action = new ActionLayoutTurnout(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 ActionLayoutTurnout)) { 242 throw new IllegalArgumentException("object must be an ActionLayoutTurnout but is a: "+object.getClass().getName()); 243 } 244 ActionLayoutTurnout action = (ActionLayoutTurnout)object; 245 if (_layoutEditorComboBox.getSelectedIndex() != -1) { 246 action.setLayoutEditor(_layoutEditorComboBox.getItemAt(_layoutEditorComboBox.getSelectedIndex())._layoutEditor.getName()); 247 } 248 if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutDirect) { 249 if (_layoutTurnoutComboBox.getSelectedIndex() != -1) { 250 action.setLayoutTurnout(_layoutTurnoutComboBox.getItemAt(_layoutTurnoutComboBox.getSelectedIndex())._lt); 251 } else { 252 action.setLayoutTurnout((LayoutTurnout)null); 253 } 254 } 255 try { 256 if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutDirect) { 257 action.setAddressing(NamedBeanAddressing.Direct); 258 } else if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutReference) { 259 action.setAddressing(NamedBeanAddressing.Reference); 260 action.setReference(_layoutTurnoutReferenceTextField.getText()); 261 } else if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutLocalVariable) { 262 action.setAddressing(NamedBeanAddressing.LocalVariable); 263 action.setLocalVariable(_layoutTurnoutLocalVariableTextField.getText()); 264 } else if (_tabbedPaneLayoutTurnout.getSelectedComponent() == _panelLayoutTurnoutFormula) { 265 action.setAddressing(NamedBeanAddressing.Formula); 266 action.setFormula(_layoutTurnoutFormulaTextField.getText()); 267 } else { 268 throw new IllegalArgumentException("_tabbedPaneLayoutTurnout has unknown selection"); 269 } 270 271 if (_tabbedPaneLayoutTurnoutState.getSelectedComponent() == _panelLayoutTurnoutStateDirect) { 272 action.setStateAddressing(NamedBeanAddressing.Direct); 273 action.setOperation(_isControllingComboBox.getItemAt(_isControllingComboBox.getSelectedIndex())); 274 } else if (_tabbedPaneLayoutTurnoutState.getSelectedComponent() == _panelLayoutTurnoutStateReference) { 275 action.setStateAddressing(NamedBeanAddressing.Reference); 276 action.setStateReference(_layoutTurnoutStateReferenceTextField.getText()); 277 } else if (_tabbedPaneLayoutTurnoutState.getSelectedComponent() == _panelLayoutTurnoutStateLocalVariable) { 278 action.setStateAddressing(NamedBeanAddressing.LocalVariable); 279 action.setStateLocalVariable(_layoutTurnoutStateLocalVariableTextField.getText()); 280 } else if (_tabbedPaneLayoutTurnoutState.getSelectedComponent() == _panelLayoutTurnoutStateFormula) { 281 action.setStateAddressing(NamedBeanAddressing.Formula); 282 action.setStateFormula(_layoutTurnoutStateFormulaTextField.getText()); 283 } else { 284 throw new IllegalArgumentException("_tabbedPaneLayoutTurnoutState has unknown selection"); 285 } 286 } catch (ParserException e) { 287 throw new RuntimeException("ParserException: "+e.getMessage(), e); 288 } 289 } 290 291 /** {@inheritDoc} */ 292 @Override 293 public String toString() { 294 return Bundle.getMessage("ActionLayoutTurnout_Short"); 295 } 296 297 @Override 298 public void dispose() { 299 // Do nothing 300 } 301 302 303 private static class EditorItem { 304 305 private final LayoutEditor _layoutEditor; 306 307 public EditorItem(LayoutEditor layoutEditor) { 308 this._layoutEditor = layoutEditor; 309 } 310 311 @Override 312 public String toString() { 313 return _layoutEditor.getName(); 314 } 315 } 316 317 318 private static class Turnout { 319 private final LayoutTurnout _lt; 320 321 public Turnout(LayoutTurnout turnout) { 322 _lt = turnout; 323 } 324 325 @Override 326 public String toString() { 327 return _lt.getTurnoutName(); 328 } 329 } 330 331// private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionLayoutTurnoutSwing.class); 332 333}