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.InstanceManager; 010import jmri.Light; 011import jmri.LightManager; 012import jmri.jmrit.logixng.*; 013import jmri.jmrit.logixng.actions.ActionLight; 014import jmri.jmrit.logixng.actions.ActionLight.LightState; 015import jmri.jmrit.logixng.swing.SwingConfiguratorInterface; 016import jmri.jmrit.logixng.util.parser.ParserException; 017import jmri.jmrit.logixng.util.swing.LogixNG_SelectNamedBeanSwing; 018import jmri.jmrit.logixng.util.swing.LogixNG_SelectEnumSwing; 019 020/** 021 * Configures an ActionLight object with a Swing JPanel. 022 * 023 * @author Daniel Bergqvist Copyright 2021 024 */ 025public class ActionLightSwing extends AbstractDigitalActionSwing { 026 027 private LogixNG_SelectNamedBeanSwing<Light> _selectNamedBeanSwing; 028 029 private LogixNG_SelectEnumSwing<LightState> _selectEnumSwing; 030 031 private JTabbedPane _tabbedPaneData; 032 private JPanel _panelDataDirect; 033 private JPanel _panelDataReference; 034 private JPanel _panelDataLocalVariable; 035 private JPanel _panelDataFormula; 036 private JTextField _lightDataDirectTextField; 037 private JTextField _lightDataReferenceTextField; 038 private JTextField _lightDataLocalVariableTextField; 039 private JTextField _lightDataFormulaTextField; 040 041 042 public ActionLightSwing() { 043 } 044 045 public ActionLightSwing(JDialog dialog) { 046 super.setJDialog(dialog); 047 } 048 049 @Override 050 protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) { 051 ActionLight action = (ActionLight)object; 052 053 _selectNamedBeanSwing = new LogixNG_SelectNamedBeanSwing<>( 054 InstanceManager.getDefault(LightManager.class), getJDialog(), this); 055 056 _selectEnumSwing = new LogixNG_SelectEnumSwing<>(getJDialog(), this); 057 058 panel = new JPanel(); 059 060 JPanel _tabbedPaneNamedBean; 061 JPanel _tabbedPaneEnum; 062 063 if (action != null) { 064 _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(action.getSelectNamedBean()); 065 _tabbedPaneEnum = _selectEnumSwing.createPanel(action.getSelectEnum(), LightState.values()); 066 } else { 067 _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(null); 068 _tabbedPaneEnum = _selectEnumSwing.createPanel(null, LightState.values()); 069 } 070 071 _selectEnumSwing.addEnumListener(e -> { setDataPanelState(); }); 072 073 // Right section 074 _tabbedPaneData = new JTabbedPane(); 075 _panelDataDirect = new javax.swing.JPanel(); 076 _panelDataReference = new javax.swing.JPanel(); 077 _panelDataLocalVariable = new javax.swing.JPanel(); 078 _panelDataFormula = new javax.swing.JPanel(); 079 080 _tabbedPaneData.addTab(NamedBeanAddressing.Direct.toString(), _panelDataDirect); 081 _tabbedPaneData.addTab(NamedBeanAddressing.Reference.toString(), _panelDataReference); 082 _tabbedPaneData.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelDataLocalVariable); 083 _tabbedPaneData.addTab(NamedBeanAddressing.Formula.toString(), _panelDataFormula); 084 085 _lightDataDirectTextField = new JTextField(); 086 _lightDataDirectTextField.setColumns(30); 087 _panelDataDirect.add(_lightDataDirectTextField); 088 089 _lightDataReferenceTextField = new JTextField(); 090 _lightDataReferenceTextField.setColumns(30); 091 _panelDataReference.add(_lightDataReferenceTextField); 092 093 _lightDataLocalVariableTextField = new JTextField(); 094 _lightDataLocalVariableTextField.setColumns(30); 095 _panelDataLocalVariable.add(_lightDataLocalVariableTextField); 096 097 _lightDataFormulaTextField = new JTextField(); 098 _lightDataFormulaTextField.setColumns(30); 099 _panelDataFormula.add(_lightDataFormulaTextField); 100 101 setDataPanelState(); 102 103 if (action != null) { 104 switch (action.getDataAddressing()) { 105 case Direct: _tabbedPaneData.setSelectedComponent(_panelDataDirect); break; 106 case Reference: _tabbedPaneData.setSelectedComponent(_panelDataReference); break; 107 case LocalVariable: _tabbedPaneData.setSelectedComponent(_panelDataLocalVariable); break; 108 case Formula: _tabbedPaneData.setSelectedComponent(_panelDataFormula); break; 109 default: throw new IllegalArgumentException("invalid _addressing state: " + action.getDataAddressing().name()); 110 } 111 _lightDataReferenceTextField.setText(action.getDataReference()); 112 _lightDataLocalVariableTextField.setText(action.getDataLocalVariable()); 113 _lightDataFormulaTextField.setText(action.getDataFormula()); 114 115 _lightDataDirectTextField.setText(Integer.toString(action.getLightValue())); 116 setDataPanelState(); 117 } 118 119 JComponent[] components = new JComponent[]{ 120 _tabbedPaneNamedBean, 121 _tabbedPaneEnum, 122 _tabbedPaneData}; 123 124 List<JComponent> componentList = SwingConfiguratorInterface.parseMessage( 125 Bundle.getMessage("ActionLight_Components"), components); 126 127 for (JComponent c : componentList) panel.add(c); 128 } 129 130 private void setDataPanelState() { 131 boolean newState = _selectEnumSwing.isEnumSelectedOrIndirectAddressing(LightState.Intensity) || 132 _selectEnumSwing.isEnumSelectedOrIndirectAddressing(LightState.Interval); 133 _tabbedPaneData.setEnabled(newState); 134 _lightDataDirectTextField.setEnabled(newState); 135 _lightDataReferenceTextField.setEnabled(newState); 136 _lightDataLocalVariableTextField.setEnabled(newState); 137 _lightDataFormulaTextField.setEnabled(newState); 138 } 139 140 /** {@inheritDoc} */ 141 @Override 142 public boolean validate(@Nonnull List<String> errorMessages) { 143 // Create a temporary action to test formula 144 ActionLight action = new ActionLight("IQDA1", null); 145 146 _selectNamedBeanSwing.validate(action.getSelectNamedBean(), errorMessages); 147 _selectEnumSwing.validate(action.getSelectEnum(), errorMessages); 148 149 try { 150 if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) { 151 action.setDataReference(_lightDataReferenceTextField.getText()); 152 } 153 } catch (IllegalArgumentException e) { 154 errorMessages.add(e.getMessage()); 155 return false; 156 } 157 158 try { 159 action.setDataFormula(_lightDataFormulaTextField.getText()); 160 if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) { 161 action.setDataAddressing(NamedBeanAddressing.Direct); 162 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) { 163 action.setDataAddressing(NamedBeanAddressing.Reference); 164 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataLocalVariable) { 165 action.setDataAddressing(NamedBeanAddressing.LocalVariable); 166 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataFormula) { 167 action.setDataAddressing(NamedBeanAddressing.Formula); 168 } else { 169 throw new IllegalArgumentException("_tabbedPane has unknown selection"); 170 } 171 } catch (ParserException e) { 172 errorMessages.add("Cannot parse formula: " + e.getMessage()); 173 return false; 174 } 175 176 if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) { 177 178 if (_selectEnumSwing.isEnumSelectedOrIndirectAddressing(LightState.Intensity)) { 179 boolean result = true; 180 try { 181 int value = Integer.parseInt(_lightDataDirectTextField.getText()); 182 if (value < 0 || value > 100) { 183 result = false; 184 } 185 } catch (NumberFormatException ex) { 186 result = false; 187 } 188 if (!result) { 189 errorMessages.add(Bundle.getMessage("Light_Error_Intensity")); 190 return false; 191 } 192 } 193 194 if (_selectEnumSwing.isEnumSelectedOrIndirectAddressing(LightState.Interval)) { 195 boolean result = true; 196 try { 197 int value = Integer.parseInt(_lightDataDirectTextField.getText()); 198 if (value < 0) { 199 result = false; 200 } 201 } catch (NumberFormatException ex) { 202 result = false; 203 } 204 if (!result) { 205 errorMessages.add(Bundle.getMessage("Light_Error_Interval")); 206 return false; 207 } 208 } 209 } 210 211 return errorMessages.isEmpty(); 212 } 213 214 /** {@inheritDoc} */ 215 @Override 216 public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) { 217 ActionLight action = new ActionLight(systemName, userName); 218 updateObject(action); 219 return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action); 220 } 221 222 /** {@inheritDoc} */ 223 @Override 224 public void updateObject(@Nonnull Base object) { 225 if (! (object instanceof ActionLight)) { 226 throw new IllegalArgumentException("object must be an ActionLight but is a: "+object.getClass().getName()); 227 } 228 ActionLight action = (ActionLight)object; 229 _selectNamedBeanSwing.updateObject(action.getSelectNamedBean()); 230 _selectEnumSwing.updateObject(action.getSelectEnum()); 231 232 try { 233 // Right section 234 if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) { 235 action.setDataAddressing(NamedBeanAddressing.Direct); 236 // Handle optional data field 237 if (_selectEnumSwing.isEnumSelectedOrIndirectAddressing(LightState.Intensity) || 238 _selectEnumSwing.isEnumSelectedOrIndirectAddressing(LightState.Interval)) { 239 int value; 240 try { 241 value = Integer.parseInt(_lightDataDirectTextField.getText()); 242 } catch (NumberFormatException ex) { 243 value = 0; 244 } 245 action.setLightValue(value); 246 } 247 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) { 248 action.setDataAddressing(NamedBeanAddressing.Reference); 249 action.setDataReference(_lightDataReferenceTextField.getText()); 250 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataLocalVariable) { 251 action.setDataAddressing(NamedBeanAddressing.LocalVariable); 252 action.setDataLocalVariable(_lightDataLocalVariableTextField.getText()); 253 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataFormula) { 254 action.setDataAddressing(NamedBeanAddressing.Formula); 255 action.setDataFormula(_lightDataFormulaTextField.getText()); 256 } else { 257 throw new IllegalArgumentException("_tabbedPaneData has unknown selection"); 258 } 259 260 } catch (ParserException e) { 261 throw new RuntimeException("ParserException: "+e.getMessage(), e); 262 } 263 } 264 265 /** {@inheritDoc} */ 266 @Override 267 public String toString() { 268 return Bundle.getMessage("Light_Short"); 269 } 270 271 @Override 272 public void dispose() { 273 _selectNamedBeanSwing.dispose(); 274 _selectEnumSwing.dispose(); 275 } 276 277 278// private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionLightSwing.class); 279 280}