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}