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.logix.Warrant; 011import jmri.jmrit.logix.WarrantManager; 012import jmri.jmrit.logixng.*; 013import jmri.jmrit.logixng.actions.ActionWarrant; 014import jmri.jmrit.logixng.actions.ActionWarrant.DirectOperation; 015import jmri.jmrit.logixng.actions.ActionWarrant.ControlAutoTrain; 016import jmri.jmrit.logixng.swing.SwingConfiguratorInterface; 017import jmri.jmrit.logixng.util.LogixNG_SelectEnum; 018import jmri.jmrit.logixng.util.parser.ParserException; 019import jmri.jmrit.logixng.util.swing.LogixNG_SelectNamedBeanSwing; 020import jmri.jmrit.logixng.util.swing.LogixNG_SelectEnumSwing; 021import jmri.util.swing.BeanSelectPanel; 022import jmri.util.swing.JComboBoxUtil; 023 024/** 025 * Configures an ActionWarrant object with a Swing JPanel. 026 * 027 * @author Daniel Bergqvist Copyright 2021 028 * @author Dave Sand Copyright 2021 029 * @author Pete Cressman Copyright (C) 2022 030 */ 031public class ActionWarrantSwing extends AbstractDigitalActionSwing { 032 033 private LogixNG_SelectNamedBeanSwing<Warrant> _selectNamedBeanSwing; 034 035 private LogixNG_SelectEnumSwing<DirectOperation> _selectOperationSwing; 036 037 private JTabbedPane _tabbedPaneData; 038 private JPanel _panelDataDirect; 039 private JPanel _panelDataReference; 040 private JPanel _panelDataLocalVariable; 041 private JPanel _panelDataFormula; 042 private JTextField _warrantDataReferenceTextField; 043 private JTextField _warrantDataLocalVariableTextField; 044 private JTextField _warrantDataFormulaTextField; 045 046 private JPanel _panelControlTrainCombo; 047 private JPanel _panelTrainData; 048 private JTextField _trainIdNameTextField; 049 private JComboBox<ControlAutoTrain> _controlTrainComboBox; 050 private BeanSelectPanel<Memory> _panelMemoryBean; 051 private JPanel _memoryPanel; 052 053 054 public ActionWarrantSwing() { 055 } 056 057 public ActionWarrantSwing(JDialog dialog) { 058 super.setJDialog(dialog); 059 } 060 061 @Override 062 protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) { 063 ActionWarrant action = (ActionWarrant)object; 064 065 _selectNamedBeanSwing = new LogixNG_SelectNamedBeanSwing<>( 066 InstanceManager.getDefault(WarrantManager.class), getJDialog(), this); 067 068 _selectOperationSwing = new LogixNG_SelectEnumSwing<>(getJDialog(), this); 069 070 panel = new JPanel(); 071 _memoryPanel = new JPanel(); 072 073 // Left and center section 074 JPanel _tabbedPaneNamedBean; 075 JPanel _tabbedPaneOperation; 076 077 if (action != null) { 078 _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(action.getSelectNamedBean()); 079 _tabbedPaneOperation = _selectOperationSwing.createPanel(action.getSelectEnum(), DirectOperation.values()); 080 } else { 081 _tabbedPaneNamedBean = _selectNamedBeanSwing.createPanel(null); 082 _tabbedPaneOperation = _selectOperationSwing.createPanel(null, DirectOperation.values()); 083 } 084 085 086 // Right section 087 _tabbedPaneData = new JTabbedPane(); 088 _panelDataDirect = new javax.swing.JPanel(); 089 _panelDataDirect.setLayout(new BoxLayout(_panelDataDirect, BoxLayout.Y_AXIS)); 090 _panelDataReference = new javax.swing.JPanel(); 091 _panelDataLocalVariable = new javax.swing.JPanel(); 092 _panelDataFormula = new javax.swing.JPanel(); 093 094 _tabbedPaneData.addTab(NamedBeanAddressing.Direct.toString(), _panelDataDirect); 095 _tabbedPaneData.addTab(NamedBeanAddressing.Reference.toString(), _panelDataReference); 096 _tabbedPaneData.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelDataLocalVariable); 097 _tabbedPaneData.addTab(NamedBeanAddressing.Formula.toString(), _panelDataFormula); 098 099 _panelMemoryBean = new BeanSelectPanel<>(InstanceManager.getDefault(MemoryManager.class), null); 100 _memoryPanel.add(_panelMemoryBean); 101 _panelDataDirect.add(_panelMemoryBean); 102 103 _controlTrainComboBox = new JComboBox<>(); 104 for (ControlAutoTrain e : ControlAutoTrain.values()) { 105 _controlTrainComboBox.addItem(e); 106 } 107 JComboBoxUtil.setupComboBoxMaxRows(_controlTrainComboBox); 108 _panelControlTrainCombo = new JPanel(); 109 _panelControlTrainCombo.add(_controlTrainComboBox); 110 _panelDataDirect.add(_panelControlTrainCombo); 111 112 _trainIdNameTextField = new JTextField(); 113 _trainIdNameTextField.setColumns(30); 114 _panelTrainData = new JPanel(); 115 _panelTrainData.add(_trainIdNameTextField); 116 _panelDataDirect.add(_panelTrainData); 117 118 _warrantDataReferenceTextField = new JTextField(); 119 _warrantDataReferenceTextField.setColumns(30); 120 _panelDataReference.add(_warrantDataReferenceTextField); 121 122 _warrantDataLocalVariableTextField = new JTextField(); 123 _warrantDataLocalVariableTextField.setColumns(30); 124 _panelDataLocalVariable.add(_warrantDataLocalVariableTextField); 125 126 _warrantDataFormulaTextField = new JTextField(); 127 _warrantDataFormulaTextField.setColumns(30); 128 _panelDataFormula.add(_warrantDataFormulaTextField); 129 130// setDataPanelState(); 131 _panelTrainData.setVisible(false); 132 _panelControlTrainCombo.setVisible(false); 133 _panelMemoryBean.setVisible(false); 134 135 if (action != null) { 136 switch (action.getDataAddressing()) { 137 case Direct: _tabbedPaneData.setSelectedComponent(_panelDataDirect); break; 138 case Reference: _tabbedPaneData.setSelectedComponent(_panelDataReference); break; 139 case LocalVariable: _tabbedPaneData.setSelectedComponent(_panelDataLocalVariable); break; 140 case Formula: _tabbedPaneData.setSelectedComponent(_panelDataFormula); break; 141 default: throw new IllegalArgumentException("invalid _addressing state: " + action.getDataAddressing().name()); 142 } 143 _warrantDataReferenceTextField.setText(action.getDataReference()); 144 _warrantDataLocalVariableTextField.setText(action.getDataLocalVariable()); 145 _warrantDataFormulaTextField.setText(action.getDataFormula()); 146 147 _trainIdNameTextField.setText(action.getTrainData()); 148 _controlTrainComboBox.setSelectedItem(action.getControlAutoTrain()); 149 if (action.getSelectMemoryNamedBean().getNamedBean() != null) { 150 _panelMemoryBean.setDefaultNamedBean(action.getSelectMemoryNamedBean().getNamedBean().getBean()); 151 } 152 153 LogixNG_SelectEnum<DirectOperation> selectEnum = action.getSelectEnum(); 154 if (selectEnum.getEnum() != null) { 155 switch (selectEnum.getEnum()) { 156 case GetTrainLocation: 157 _panelMemoryBean.setVisible(true); 158 break; 159 case SetTrainId: 160 case SetTrainName: 161 _panelTrainData.setVisible(true); 162 break; 163 case ControlAutoTrain: 164 _panelControlTrainCombo.setVisible(true); 165 break; 166 default: 167 } 168 } 169 } 170 171 setDataPanelState(); 172 173 _selectOperationSwing.addAddressingListener((evt) -> { setDataPanelState(); }); 174 _selectOperationSwing.addEnumListener((evt) -> { setDataPanelState(); }); 175 176 JComponent[] components = new JComponent[]{ 177 _tabbedPaneNamedBean, 178 _tabbedPaneOperation, 179 _tabbedPaneData}; 180 181 List<JComponent> componentList = SwingConfiguratorInterface.parseMessage( 182 Bundle.getMessage("ActionWarrant_Components"), components); 183 184 for (JComponent c : componentList) panel.add(c); 185 } 186 187 private void setDataPanelState() { 188 _panelControlTrainCombo.setVisible(false); 189 _panelTrainData.setVisible(false); 190 _panelMemoryBean.setVisible(false); 191 192 boolean newState = false; 193 194 if (_selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.ControlAutoTrain)) { 195 _panelControlTrainCombo.setVisible(true); 196 newState = true; 197 } else if ( _selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.GetTrainLocation)) { 198 _panelMemoryBean.setVisible(true); 199 newState = true; 200 } else if (_selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.SetTrainId) || 201 _selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.SetTrainName)) { 202 _panelTrainData.setVisible(true); 203 newState = true; 204 } 205 206 _tabbedPaneData.setEnabled(newState); 207 _warrantDataReferenceTextField.setEnabled(newState); 208 _warrantDataLocalVariableTextField.setEnabled(newState); 209 _warrantDataFormulaTextField.setEnabled(newState); 210 } 211 212 /** {@inheritDoc} */ 213 @Override 214 public boolean validate(@Nonnull List<String> errorMessages) { 215 ActionWarrant action = new ActionWarrant("IQDA1", null); 216 _selectNamedBeanSwing.validate(action.getSelectNamedBean(), errorMessages); 217 _selectOperationSwing.validate(action.getSelectEnum(), errorMessages); 218 validateDataSection(errorMessages); 219 return errorMessages.isEmpty(); 220 } 221 222 private void validateDataSection(List<String> errorMessages) { 223 // Create a temporary action to test formula 224 ActionWarrant action = new ActionWarrant("IQDA3", null); 225 226 try { 227 if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) { 228 action.setDataReference(_warrantDataReferenceTextField.getText()); 229 } 230 } catch (IllegalArgumentException e) { 231 errorMessages.add(e.getMessage()); 232 return; 233 } 234 235 try { 236 action.setDataFormula(_warrantDataFormulaTextField.getText()); 237 if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) { 238 action.setDataAddressing(NamedBeanAddressing.Direct); 239 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) { 240 action.setDataAddressing(NamedBeanAddressing.Reference); 241 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataLocalVariable) { 242 action.setDataAddressing(NamedBeanAddressing.LocalVariable); 243 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataFormula) { 244 action.setDataAddressing(NamedBeanAddressing.Formula); 245 } else { 246 throw new IllegalArgumentException("_tabbedPane has unknown selection"); 247 } 248 } catch (ParserException e) { 249 errorMessages.add("Cannot parse formula: " + e.getMessage()); 250 } 251 252 if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) { 253 if (_selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.SetTrainId) 254 || _selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.SetTrainName)) { 255 if (_trainIdNameTextField.getText().isEmpty()) { 256 errorMessages.add(Bundle.getMessage("ActionWarrant_ErrorValue")); 257 } 258 } else if (_selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.GetTrainLocation)) { 259 if (_panelMemoryBean.isEmpty() || _panelMemoryBean.getNamedBean() == null) { 260 errorMessages.add(Bundle.getMessage("ActionWarrant_ErrorMemory")); 261 } 262 } 263 } 264 } 265 266 /** {@inheritDoc} */ 267 @Override 268 public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) { 269 ActionWarrant action = new ActionWarrant(systemName, userName); 270 updateObject(action); 271 return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action); 272 } 273 274 /** {@inheritDoc} */ 275 @Override 276 public void updateObject(@Nonnull Base object) { 277 if (! (object instanceof ActionWarrant)) { 278 throw new IllegalArgumentException("object must be an ActionWarrant but is a: "+object.getClass().getName()); 279 } 280 ActionWarrant action = (ActionWarrant) object; 281 _selectNamedBeanSwing.updateObject(action.getSelectNamedBean()); 282 _selectOperationSwing.updateObject(action.getSelectEnum()); 283 284 try { 285 // Right section 286 if (_tabbedPaneData.getSelectedComponent() == _panelDataDirect) { 287 action.setDataAddressing(NamedBeanAddressing.Direct); 288 // Handle optional data field 289 if (_selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.SetTrainId) 290 || _selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.SetTrainName)) { 291 action.setTrainData(_trainIdNameTextField.getText()); 292 } else if (_selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.ControlAutoTrain)) { 293 action.setControlAutoTrain((ControlAutoTrain) _controlTrainComboBox.getSelectedItem()); 294 } else if (_selectOperationSwing.isEnumSelectedOrIndirectAddressing(DirectOperation.GetTrainLocation)) { 295 Memory memory = _panelMemoryBean.getNamedBean(); 296 if (memory != null) { 297 NamedBeanHandle<Memory> handle 298 = InstanceManager.getDefault(NamedBeanHandleManager.class) 299 .getNamedBeanHandle(memory.getDisplayName(), memory); 300 action.getSelectMemoryNamedBean().setNamedBean(handle); 301 } else { 302 action.getSelectMemoryNamedBean().removeNamedBean(); 303 } 304 } 305 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataReference) { 306 action.setDataAddressing(NamedBeanAddressing.Reference); 307 action.setDataReference(_warrantDataReferenceTextField.getText()); 308 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataLocalVariable) { 309 action.setDataAddressing(NamedBeanAddressing.LocalVariable); 310 action.setDataLocalVariable(_warrantDataLocalVariableTextField.getText()); 311 } else if (_tabbedPaneData.getSelectedComponent() == _panelDataFormula) { 312 action.setDataAddressing(NamedBeanAddressing.Formula); 313 action.setDataFormula(_warrantDataFormulaTextField.getText()); 314 } else { 315 throw new IllegalArgumentException("_tabbedPaneData has unknown selection"); 316 } 317 } catch (ParserException e) { 318 throw new RuntimeException("ParserException: "+e.getMessage(), e); 319 } 320 } 321 322 /** {@inheritDoc} */ 323 @Override 324 public String toString() { 325 return Bundle.getMessage("ActionWarrant_Short"); 326 } 327 328 @Override 329 public void dispose() { 330 _selectNamedBeanSwing.dispose(); 331 _selectOperationSwing.dispose(); 332 } 333 334 335// private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionWarrantSwing.class); 336 337}