001package jmri.jmrit.logixng.actions.swing; 002 003import java.util.List; 004 005import javax.annotation.CheckForNull; 006import javax.annotation.Nonnull; 007import javax.swing.*; 008 009import jmri.*; 010import jmri.jmrit.logixng.*; 011import jmri.jmrit.logixng.actions.ForEachWithDelay; 012import jmri.jmrit.logixng.actions.CommonManager; 013import jmri.jmrit.logixng.actions.ForEachWithDelay.UserSpecifiedSource; 014import jmri.jmrit.logixng.util.parser.ParserException; 015import jmri.jmrit.logixng.util.swing.LogixNG_SelectNamedBeanSwing; 016import jmri.jmrit.logixng.util.swing.LogixNG_SelectStringSwing; 017import jmri.util.TimerUnit; 018import jmri.util.swing.JComboBoxUtil; 019 020/** 021 * Configures an ForEachWithDelay object with a Swing JPanel. 022 * 023 * @author Daniel Bergqvist Copyright 2025 024 */ 025public class ForEachWithDelaySwing extends AbstractDigitalActionSwing { 026 027 private LogixNG_SelectStringSwing _selectVariableSwing; 028 private LogixNG_SelectNamedBeanSwing<Memory> _selectMemorySwing; 029 030 private JTabbedPane _commonOrUserSpecifiedPane; 031 private JPanel _commonPanel; 032 private JComboBox<CommonManager> _commonManagersComboBox; 033 034 private JTabbedPane _tabbedPaneUserSpecifiedSource; 035 JPanel _tabbedPaneMemoryBean; 036 JPanel _tabbedPaneVariable; 037 private JPanel _calculateFormula; 038 private JTextField _calculateFormulaTextField; 039 040 private JTextField _localVariable; 041 042 private JFormattedTextField _timerDelay; 043 private JComboBox<TimerUnit> _unitComboBox; 044 private JCheckBox _resetIfAlreadyStarted; 045 private JCheckBox _useIndividualTimers; 046 047 048 @Override 049 protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) { 050 if ((object != null) && !(object instanceof ForEachWithDelay)) { 051 throw new IllegalArgumentException("object must be an ForEachWithDelay but is a: "+object.getClass().getName()); 052 } 053 054 ForEachWithDelay action = (ForEachWithDelay)object; 055 056 _selectVariableSwing = new LogixNG_SelectStringSwing(getJDialog(), this); 057 058 _selectMemorySwing = new LogixNG_SelectNamedBeanSwing<>( 059 InstanceManager.getDefault(MemoryManager.class), getJDialog(), this); 060 061 panel = new JPanel(); 062 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 063 064 if (action != null) { 065 _tabbedPaneMemoryBean = _selectMemorySwing.createPanel(action.getSelectMemoryNamedBean()); 066 _tabbedPaneVariable = _selectVariableSwing.createPanel(action.getSelectVariable()); 067 } else { 068 _tabbedPaneMemoryBean = _selectMemorySwing.createPanel(null); 069 _tabbedPaneVariable = _selectVariableSwing.createPanel(null); 070 } 071 072 _commonOrUserSpecifiedPane = new JTabbedPane(); 073 074 _commonPanel = new JPanel(); 075 _commonOrUserSpecifiedPane.addTab(Bundle.getMessage("ForEachWithDelaySwing_Common"), _commonPanel); 076 _commonManagersComboBox = new JComboBox<>(); 077 for (CommonManager commonManager : CommonManager.values()) { 078 _commonManagersComboBox.addItem(commonManager); 079 } 080 JComboBoxUtil.setupComboBoxMaxRows(_commonManagersComboBox); 081 082 _commonPanel.add(_commonManagersComboBox); 083 084 085 _tabbedPaneUserSpecifiedSource = new JTabbedPane(); 086 _commonOrUserSpecifiedPane.addTab(Bundle.getMessage("ForEachWithDelaySwing_UserSpecified"), _tabbedPaneUserSpecifiedSource); 087 088 _calculateFormula = new JPanel(); 089 090 _tabbedPaneUserSpecifiedSource.addTab(UserSpecifiedSource.Memory.toString(), _tabbedPaneMemoryBean); 091 _tabbedPaneUserSpecifiedSource.addTab(UserSpecifiedSource.Variable.toString(), _tabbedPaneVariable); 092 _tabbedPaneUserSpecifiedSource.addTab(UserSpecifiedSource.Formula.toString(), _calculateFormula); 093 094 _calculateFormulaTextField = new JTextField(30); 095 _calculateFormula.add(_calculateFormulaTextField); 096 097 JPanel localVariablePanel = new JPanel(); 098 localVariablePanel.add(new JLabel(Bundle.getMessage("ForEachWithDelaySwing_LocalVariable"))); 099 _localVariable = new JTextField(20); 100 localVariablePanel.add(_localVariable); 101 panel.add(localVariablePanel); 102 103 panel.add(_commonOrUserSpecifiedPane); 104 panel.add(localVariablePanel); 105 106 JPanel panelDelay = new javax.swing.JPanel(); 107 panelDelay.add(new JLabel(Bundle.getMessage("ForEachWithDelaySwing_Time"))); 108 _timerDelay = new JFormattedTextField("0"); 109 _timerDelay.setColumns(7); 110 panelDelay.add(_timerDelay); 111 panel.add(panelDelay); 112 113 JPanel unitPanel = new JPanel(); 114 unitPanel.add(new JLabel(Bundle.getMessage("ForEachWithDelaySwing_Unit"))); 115 panel.add(unitPanel); 116 117 _unitComboBox = new JComboBox<>(); 118 for (TimerUnit u : TimerUnit.values()) _unitComboBox.addItem(u); 119 JComboBoxUtil.setupComboBoxMaxRows(_unitComboBox); 120 if (action != null) _unitComboBox.setSelectedItem(action.getUnit()); 121 unitPanel.add(_unitComboBox); 122 panel.add(unitPanel); 123 124 _resetIfAlreadyStarted = new JCheckBox(Bundle.getMessage("ForEachWithDelaySwing_ResetIfAlreadyStarted")); 125 panel.add(_resetIfAlreadyStarted); 126 127 _useIndividualTimers = new JCheckBox(Bundle.getMessage("ForEachWithDelaySwing_UseIndividualTimers")); 128 _useIndividualTimers.addActionListener((evt)->{ 129 if (_useIndividualTimers.isSelected()) { 130 _resetIfAlreadyStarted.setEnabled(false); 131 _resetIfAlreadyStarted.setSelected(false); 132 } else { 133 _resetIfAlreadyStarted.setEnabled(true); 134 } 135 }); 136 panel.add(_useIndividualTimers); 137 138 139 if (action != null) { 140 if (!action.isUseCommonSource()) { 141 _commonOrUserSpecifiedPane.setSelectedComponent(_tabbedPaneUserSpecifiedSource); 142 } 143 _commonManagersComboBox.setSelectedItem(action.getCommonManager()); 144 145 switch (action.getUserSpecifiedSource()) { 146 case Memory: _tabbedPaneUserSpecifiedSource.setSelectedComponent(_tabbedPaneMemoryBean); break; 147 case Variable: _tabbedPaneUserSpecifiedSource.setSelectedComponent(_tabbedPaneVariable); break; 148 case Formula: _tabbedPaneUserSpecifiedSource.setSelectedComponent(_calculateFormula); break; 149 default: throw new IllegalArgumentException("invalid _addressing state: " + action.getUserSpecifiedSource().name()); 150 } 151 _calculateFormulaTextField.setText(action.getFormula()); 152 _timerDelay.setText(Integer.toString(action.getDelay())); 153 _localVariable.setText(action.getLocalVariableName()); 154 _resetIfAlreadyStarted.setSelected(action.getResetIfAlreadyStarted()); 155 _useIndividualTimers.setSelected(action.getUseIndividualTimers()); 156 _resetIfAlreadyStarted.setEnabled(!action.getUseIndividualTimers()); 157 } 158 } 159 160 /** {@inheritDoc} */ 161 @Override 162 public boolean validate(@Nonnull List<String> errorMessages) { 163 // Create a temporary action to test formula 164 ForEachWithDelay action = new ForEachWithDelay("IQDA1", null); 165 166 if (_commonOrUserSpecifiedPane.getSelectedComponent() == _tabbedPaneUserSpecifiedSource) { 167 // If using the Memory tab, validate the memory variable selection. 168 if (_tabbedPaneUserSpecifiedSource.getSelectedComponent() == _tabbedPaneMemoryBean) { 169 _selectMemorySwing.validate(action.getSelectMemoryNamedBean(), errorMessages); 170 } 171 172 // If using the Variable tab, validate the memory variable selection. 173 if (_tabbedPaneUserSpecifiedSource.getSelectedComponent() == _tabbedPaneVariable) { 174 _selectVariableSwing.validate(action.getSelectVariable(), errorMessages); 175 } 176 177 if (_tabbedPaneUserSpecifiedSource.getSelectedComponent() == _calculateFormula) { 178 try { 179 action.setUserSpecifiedSource(UserSpecifiedSource.Formula); 180 action.setFormula(_calculateFormulaTextField.getText()); 181 } catch (ParserException e) { 182 errorMessages.add(e.getMessage()); 183 } 184 } 185 } 186 187 try { 188 action.setDelay(Integer.parseInt(_timerDelay.getText())); 189 } catch (NumberFormatException e) { 190 errorMessages.add(e.getLocalizedMessage()); 191 } 192 193 return errorMessages.isEmpty(); 194 } 195 196 /** {@inheritDoc} */ 197 @Override 198 public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) { 199 ForEachWithDelay action = new ForEachWithDelay(systemName, userName); 200 updateObject(action); 201 return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action); 202 } 203 204 /** {@inheritDoc} */ 205 @Override 206 public void updateObject(@Nonnull Base object) { 207 if (!(object instanceof ForEachWithDelay)) { 208 throw new IllegalArgumentException("object must be an ForEachWithDelay but is a: "+object.getClass().getName()); 209 } 210 211 ForEachWithDelay action = (ForEachWithDelay)object; 212 213 try { 214 if (_commonOrUserSpecifiedPane.getSelectedComponent() == _commonPanel) { 215 216 action.setUseCommonSource(true); 217 action.setCommonManager(_commonManagersComboBox.getItemAt( 218 _commonManagersComboBox.getSelectedIndex())); 219 220 } else if (_commonOrUserSpecifiedPane.getSelectedComponent() == _tabbedPaneUserSpecifiedSource) { 221 222 action.setUseCommonSource(false); 223 224 try { 225 if (_tabbedPaneUserSpecifiedSource.getSelectedComponent() == _tabbedPaneMemoryBean) { 226 action.setUserSpecifiedSource(UserSpecifiedSource.Memory); 227 _selectMemorySwing.updateObject(action.getSelectMemoryNamedBean()); 228 } else if (_tabbedPaneUserSpecifiedSource.getSelectedComponent() == _tabbedPaneVariable) { 229 action.setUserSpecifiedSource(UserSpecifiedSource.Variable); 230 _selectVariableSwing.updateObject(action.getSelectVariable()); 231 } else if (_tabbedPaneUserSpecifiedSource.getSelectedComponent() == _calculateFormula) { 232 action.setUserSpecifiedSource(UserSpecifiedSource.Formula); 233 action.setFormula(_calculateFormulaTextField.getText()); 234 } else { 235 throw new IllegalArgumentException("_tabbedPaneUserSpecifiedSource has unknown selection"); 236 } 237 } catch (ParserException e) { 238 throw new RuntimeException("ParserException: "+e.getMessage(), e); 239 } 240 241 } else { 242 throw new IllegalArgumentException("_tabbedPaneUserSpecifiedSource has unknown selection"); 243 } 244 } catch (ParserException e) { 245 throw new RuntimeException("ParserException: "+e.getMessage(), e); 246 } 247 248 action.setLocalVariableName(_localVariable.getText()); 249 250 action.setDelay(Integer.parseInt(_timerDelay.getText())); 251 action.setUnit(_unitComboBox.getItemAt(_unitComboBox.getSelectedIndex())); 252 action.setResetIfAlreadyStarted(_resetIfAlreadyStarted.isSelected()); 253 action.setUseIndividualTimers(_useIndividualTimers.isSelected()); 254 } 255 256 /** {@inheritDoc} */ 257 @Override 258 public String toString() { 259 return Bundle.getMessage("ForEachWithDelay_Short"); 260 } 261 262 @Override 263 public void dispose() { 264 } 265 266// private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ForEachSwing.class); 267 268}