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