001package jmri.jmrit.logixng.actions.swing; 002 003import java.awt.event.ActionEvent; 004import java.util.List; 005 006import javax.annotation.CheckForNull; 007import javax.annotation.Nonnull; 008import javax.swing.*; 009import javax.swing.filechooser.FileNameExtensionFilter; 010 011import jmri.InstanceManager; 012import jmri.jmrit.logixng.*; 013import jmri.jmrit.logixng.actions.ActionSound; 014import jmri.jmrit.logixng.actions.ActionSound.Operation; 015import jmri.jmrit.logixng.swing.SwingConfiguratorInterface; 016import jmri.jmrit.logixng.util.parser.ParserException; 017import jmri.jmrit.logixng.util.swing.LogixNG_SelectEnumSwing; 018import jmri.util.FileUtil; 019 020/** 021 * Configures an ActionSound object with a Swing JPanel. 022 * 023 * @author Daniel Bergqvist 2021 024 */ 025public class ActionSoundSwing extends AbstractDigitalActionSwing { 026 027 public static final int NUM_COLUMNS_TEXT_FIELDS = 20; 028 029 private LogixNG_SelectEnumSwing<Operation> _selectOperationSwing; 030 031 private JTabbedPane _tabbedPaneSoundType; 032 private JPanel _panelSoundTypeDirect; 033 private JPanel _panelSoundTypeReference; 034 private JPanel _panelSoundTypeLocalVariable; 035 private JPanel _panelSoundTypeFormula; 036 037 private JFileChooser soundFileChooser; 038 private JTextField _soundTextField; 039 private JTextField _soundReferenceTextField; 040 private JTextField _soundLocalVariableTextField; 041 private JTextField _soundFormulaTextField; 042 043 044 public ActionSoundSwing() { 045 } 046 047 public ActionSoundSwing(JDialog dialog) { 048 super.setJDialog(dialog); 049 } 050 051 @Override 052 protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) { 053 ActionSound action = (ActionSound)object; 054 055 _selectOperationSwing = new LogixNG_SelectEnumSwing<>(getJDialog(), this); 056 057 panel = new JPanel(); 058 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 059 060 JPanel actionPanel = new JPanel(); 061 062 063 // Set up the tabbed pane for selecting the operation 064 JPanel _tabbedPaneOperation; 065 if (action != null) { 066 _tabbedPaneOperation = _selectOperationSwing.createPanel(action.getSelectEnum(), Operation.values()); 067 } else { 068 _tabbedPaneOperation = _selectOperationSwing.createPanel(null, Operation.values()); 069 } 070 071 072 // Set up the tabbed pane for selecting the appearance 073 _tabbedPaneSoundType = new JTabbedPane(); 074 _panelSoundTypeDirect = new javax.swing.JPanel(); 075// _panelSoundTypeDirect.setLayout(new BoxLayout(_panelSoundTypeDirect, BoxLayout.Y_AXIS)); 076 _panelSoundTypeReference = new javax.swing.JPanel(); 077 _panelSoundTypeReference.setLayout(new BoxLayout(_panelSoundTypeReference, BoxLayout.Y_AXIS)); 078 _panelSoundTypeLocalVariable = new javax.swing.JPanel(); 079 _panelSoundTypeLocalVariable.setLayout(new BoxLayout(_panelSoundTypeLocalVariable, BoxLayout.Y_AXIS)); 080 _panelSoundTypeFormula = new javax.swing.JPanel(); 081 _panelSoundTypeFormula.setLayout(new BoxLayout(_panelSoundTypeFormula, BoxLayout.Y_AXIS)); 082 083 _tabbedPaneSoundType.addTab(NamedBeanAddressing.Direct.toString(), _panelSoundTypeDirect); 084 _tabbedPaneSoundType.addTab(NamedBeanAddressing.Reference.toString(), _panelSoundTypeReference); 085 _tabbedPaneSoundType.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelSoundTypeLocalVariable); 086 _tabbedPaneSoundType.addTab(NamedBeanAddressing.Formula.toString(), _panelSoundTypeFormula); 087 088 JButton _actionSelectFileButton = new JButton("..."); // "File" replaced by ... 089 _actionSelectFileButton.setMaximumSize(_actionSelectFileButton.getPreferredSize()); 090 _actionSelectFileButton.setToolTipText(Bundle.getMessage("FileButtonHint")); // NOI18N 091 _actionSelectFileButton.addActionListener((ActionEvent e) -> { 092 soundFileChooser = new jmri.util.swing.JmriJFileChooser(System.getProperty("user.dir") // NOI18N 093 + java.io.File.separator + "resources" // NOI18N 094 + java.io.File.separator + "sounds"); // NOI18N 095 soundFileChooser.setFileFilter(new FileNameExtensionFilter("wav sound files", "wav")); // NOI18N 096 soundFileChooser.rescanCurrentDirectory(); 097 int retVal = soundFileChooser.showOpenDialog(null); 098 // handle selection or cancel 099 if (retVal == JFileChooser.APPROVE_OPTION) { 100 // set selected file location 101 try { 102 _soundTextField.setText(FileUtil.getPortableFilename(soundFileChooser.getSelectedFile().getCanonicalPath())); 103 } catch (java.io.IOException ex) { 104 log.error("exception setting file location", ex); // NOI18N 105 _soundTextField.setText(""); 106 } 107 } 108 }); 109 _panelSoundTypeDirect.add(_actionSelectFileButton); 110 JPanel _soundTextPanel = new JPanel(); 111 _soundTextPanel.setLayout(new BoxLayout(_soundTextPanel, BoxLayout.Y_AXIS)); 112 _soundTextField = new JTextField(30); 113 _soundTextPanel.add(new JLabel(Bundle.getMessage("ActionSound_Sound"))); 114 _soundTextPanel.add(_soundTextField); 115 _panelSoundTypeDirect.add(_soundTextPanel); 116 117 _soundReferenceTextField = new JTextField(); 118 _soundReferenceTextField.setColumns(NUM_COLUMNS_TEXT_FIELDS); 119 _panelSoundTypeReference.add(new JLabel(Bundle.getMessage("ActionSound_Sound"))); 120 _panelSoundTypeReference.add(_soundReferenceTextField); 121 122 _soundLocalVariableTextField = new JTextField(); 123 _soundLocalVariableTextField.setColumns(NUM_COLUMNS_TEXT_FIELDS); 124 _panelSoundTypeLocalVariable.add(new JLabel(Bundle.getMessage("ActionSound_Sound"))); 125 _panelSoundTypeLocalVariable.add(_soundLocalVariableTextField); 126 127 _soundFormulaTextField = new JTextField(); 128 _soundFormulaTextField.setColumns(NUM_COLUMNS_TEXT_FIELDS); 129 _panelSoundTypeFormula.add(new JLabel(Bundle.getMessage("ActionSound_Sound"))); 130 _panelSoundTypeFormula.add(_soundFormulaTextField); 131 132 133 if (action != null) { 134 switch (action.getSoundAddressing()) { 135 case Direct: _tabbedPaneSoundType.setSelectedComponent(_panelSoundTypeDirect); break; 136 case Reference: _tabbedPaneSoundType.setSelectedComponent(_panelSoundTypeReference); break; 137 case LocalVariable: _tabbedPaneSoundType.setSelectedComponent(_panelSoundTypeLocalVariable); break; 138 case Formula: _tabbedPaneSoundType.setSelectedComponent(_panelSoundTypeFormula); break; 139 default: throw new IllegalArgumentException("invalid _addressing state: " + action.getSoundAddressing().name()); 140 } 141 _soundTextField.setText(action.getSound()); 142 _soundReferenceTextField.setText(action.getSoundReference()); 143 _soundLocalVariableTextField.setText(action.getSoundLocalVariable()); 144 _soundFormulaTextField.setText(action.getSoundFormula()); 145 } 146 147 JComponent[] components = new JComponent[]{ 148 _tabbedPaneOperation, 149 _tabbedPaneSoundType 150 }; 151 152 List<JComponent> componentList = SwingConfiguratorInterface.parseMessage( 153 Bundle.getMessage("ActionSound_Components"), components); 154 155 for (JComponent c : componentList) actionPanel.add(c); 156 panel.add(actionPanel); 157 } 158 159 /** {@inheritDoc} */ 160 @Override 161 public boolean validate(@Nonnull List<String> errorMessages) { 162 // Create a temporary action to test formula 163 ActionSound action = new ActionSound("IQDA1", null); 164 165 _selectOperationSwing.validate(action.getSelectEnum(), errorMessages); 166 167 try { 168 action.setSoundFormula(_soundFormulaTextField.getText()); 169 if (_tabbedPaneSoundType.getSelectedComponent() == _panelSoundTypeDirect) { 170 action.setSoundAddressing(NamedBeanAddressing.Direct); 171 } else if (_tabbedPaneSoundType.getSelectedComponent() == _panelSoundTypeReference) { 172 action.setSoundAddressing(NamedBeanAddressing.Reference); 173 } else if (_tabbedPaneSoundType.getSelectedComponent() == _panelSoundTypeLocalVariable) { 174 action.setSoundAddressing(NamedBeanAddressing.LocalVariable); 175 } else if (_tabbedPaneSoundType.getSelectedComponent() == _panelSoundTypeFormula) { 176 action.setSoundAddressing(NamedBeanAddressing.Formula); 177 } else { 178 throw new IllegalArgumentException("_tabbedPaneSoundType has unknown selection"); 179 } 180 } catch (ParserException e) { 181 errorMessages.add("Cannot parse formula: " + e.getMessage()); 182 } 183 return true; 184 } 185 186 /** {@inheritDoc} */ 187 @Override 188 public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) { 189 ActionSound action = new ActionSound(systemName, userName); 190 updateObject(action); 191 return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action); 192 } 193 194 /** {@inheritDoc} */ 195 @Override 196 public void updateObject(@Nonnull Base object) { 197 if (! (object instanceof ActionSound)) { 198 throw new IllegalArgumentException("object must be an ActionSound but is a: "+object.getClass().getName()); 199 } 200 ActionSound action = (ActionSound)object; 201 202 _selectOperationSwing.updateObject(action.getSelectEnum()); 203 204 try { 205 if (_tabbedPaneSoundType.getSelectedComponent() == _panelSoundTypeDirect) { 206 action.setSoundAddressing(NamedBeanAddressing.Direct); 207 action.setSound(_soundTextField.getText()); 208 } else if (_tabbedPaneSoundType.getSelectedComponent() == _panelSoundTypeReference) { 209 action.setSoundAddressing(NamedBeanAddressing.Reference); 210 action.setSoundReference(_soundReferenceTextField.getText()); 211 } else if (_tabbedPaneSoundType.getSelectedComponent() == _panelSoundTypeLocalVariable) { 212 action.setSoundAddressing(NamedBeanAddressing.LocalVariable); 213 action.setSoundLocalVariable(_soundLocalVariableTextField.getText()); 214 } else if (_tabbedPaneSoundType.getSelectedComponent() == _panelSoundTypeFormula) { 215 action.setSoundAddressing(NamedBeanAddressing.Formula); 216 action.setSoundFormula(_soundFormulaTextField.getText()); 217 } else { 218 throw new IllegalArgumentException("_tabbedPaneAspectType has unknown selection"); 219 } 220 } catch (ParserException e) { 221 throw new RuntimeException("ParserException: "+e.getMessage(), e); 222 } 223 } 224 225 /** {@inheritDoc} */ 226 @Override 227 public String toString() { 228 return Bundle.getMessage("ActionSound_Short"); 229 } 230 231 @Override 232 public void dispose() { 233 _selectOperationSwing.dispose(); 234 } 235 236 237 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionSoundSwing.class); 238 239}