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