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.TableForEach; 012import jmri.jmrit.logixng.TableRowOrColumn; 013import jmri.jmrit.logixng.util.parser.ParserException; 014import jmri.jmrit.logixng.util.swing.LogixNG_SelectNamedBeanSwing; 015import jmri.util.swing.JComboBoxUtil; 016 017/** 018 * Configures an TableForEach object with a Swing JPanel. 019 * 020 * @author Daniel Bergqvist Copyright 2021 021 */ 022public class TableForEachSwing extends AbstractDigitalActionSwing { 023 024 private LogixNG_SelectNamedBeanSwing<NamedTable> _selectNamedBeanSwing; 025 026 private JComboBox<TableRowOrColumn> _tableRowOrColumnComboBox; 027 028 private JLabel _panelRowOrColumnLabel; 029 private JTabbedPane _tabbedRowOrColumnPane; 030 private JPanel _panelRowOrColumnName; 031 private JPanel _panelRowOrColumnReference; 032 private JPanel _panelRowOrColumnLocalVariable; 033 private JPanel _panelRowOrColumnFormula; 034 private JComboBox<String> _rowOrColumnNameComboBox; 035 private JTextField _rowOrColumnNameTextField; 036 037 private JTextField _referenceRowOrColumnTextField; 038 private JTextField _localRowOrColumnVariableTextField; 039 private JTextField _formulaRowOrColumnTextField; 040 041 private JTextField _localVariable; 042 043 @Override 044 protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) { 045 if ((object != null) && !(object instanceof TableForEach)) { 046 throw new IllegalArgumentException("object must be an TableForEach but is a: "+object.getClass().getName()); 047 } 048 049 TableForEach action = (TableForEach)object; 050 051 panel = new JPanel(); 052 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 053 054 _selectNamedBeanSwing = new LogixNG_SelectNamedBeanSwing<>( 055 InstanceManager.getDefault(NamedTableManager.class), getJDialog(), this); 056 057 _panelRowOrColumnLabel = new JLabel(Bundle.getMessage("TableForEachSwing_RowName")); 058 059 _tableRowOrColumnComboBox = new JComboBox<>(); 060 for (TableRowOrColumn item : TableRowOrColumn.values()) { 061 _tableRowOrColumnComboBox.addItem(item); 062 } 063 JComboBoxUtil.setupComboBoxMaxRows(_tableRowOrColumnComboBox); 064 _tableRowOrColumnComboBox.addActionListener((evt) -> { 065 setupRowOrColumnNameComboBox(action != null ? action.getRowOrColumnName() : null); 066 067 if (_tableRowOrColumnComboBox.getItemAt(_tableRowOrColumnComboBox.getSelectedIndex()) == TableRowOrColumn.Row) { 068 _panelRowOrColumnLabel.setText(Bundle.getMessage("TableForEachSwing_RowName")); 069 } else { 070 _panelRowOrColumnLabel.setText(Bundle.getMessage("TableForEachSwing_ColumnName")); 071 } 072 }); 073 074 JPanel tableRowOrColumnPanel = new JPanel(); 075 tableRowOrColumnPanel.add(new JLabel(Bundle.getMessage("TableForEachSwing_RowOrColumn"))); 076 tableRowOrColumnPanel.add(_tableRowOrColumnComboBox); 077 panel.add(tableRowOrColumnPanel); 078 079 JPanel tabbedPanesPanel = new JPanel(); 080 tabbedPanesPanel.setLayout(new BoxLayout(tabbedPanesPanel, BoxLayout.X_AXIS)); 081 082 JPanel tabbedTablePane; 083 084 if (action != null) { 085 tabbedTablePane = _selectNamedBeanSwing.createPanel(action.getSelectNamedBean()); 086 } else { 087 tabbedTablePane = _selectNamedBeanSwing.createPanel(null); 088 } 089 090 _selectNamedBeanSwing.addAddressingListener((evt) -> { 091 boolean isDirectAddressing = (_selectNamedBeanSwing.getAddressing() == NamedBeanAddressing.Direct); 092 _rowOrColumnNameComboBox.setVisible(isDirectAddressing); 093 _rowOrColumnNameTextField.setVisible(!isDirectAddressing); 094 }); 095 096 _selectNamedBeanSwing.getBeanSelectPanel().getBeanCombo().addActionListener((evt) -> { 097 setupRowOrColumnNameComboBox(action != null ? action.getRowOrColumnName() : null); 098 }); 099 100 tabbedPanesPanel.add(new JLabel(Bundle.getMessage("TableForEachSwing_Table"))); 101 102 tabbedPanesPanel.add(tabbedTablePane); 103 104 _tabbedRowOrColumnPane = new JTabbedPane(); 105 _panelRowOrColumnName = new javax.swing.JPanel(); 106 _panelRowOrColumnReference = new javax.swing.JPanel(); 107 _panelRowOrColumnLocalVariable = new javax.swing.JPanel(); 108 _panelRowOrColumnFormula = new javax.swing.JPanel(); 109 110 _tabbedRowOrColumnPane.addTab(NamedBeanAddressing.Direct.toString(), _panelRowOrColumnName); 111 _tabbedRowOrColumnPane.addTab(NamedBeanAddressing.Reference.toString(), _panelRowOrColumnReference); 112 _tabbedRowOrColumnPane.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelRowOrColumnLocalVariable); 113 _tabbedRowOrColumnPane.addTab(NamedBeanAddressing.Formula.toString(), _panelRowOrColumnFormula); 114 115 _rowOrColumnNameComboBox = new JComboBox<>(); 116 _panelRowOrColumnName.add(_rowOrColumnNameComboBox); 117 _rowOrColumnNameTextField = new JTextField(20); 118 _rowOrColumnNameTextField.setVisible(false); 119 _panelRowOrColumnName.add(_rowOrColumnNameTextField); 120 JComboBoxUtil.setupComboBoxMaxRows(_rowOrColumnNameComboBox); 121 122 _referenceRowOrColumnTextField = new JTextField(); 123 _referenceRowOrColumnTextField.setColumns(20); 124 _panelRowOrColumnReference.add(_referenceRowOrColumnTextField); 125 126 _localRowOrColumnVariableTextField = new JTextField(); 127 _localRowOrColumnVariableTextField.setColumns(20); 128 _panelRowOrColumnLocalVariable.add(_localRowOrColumnVariableTextField); 129 130 _formulaRowOrColumnTextField = new JTextField(); 131 _formulaRowOrColumnTextField.setColumns(20); 132 _panelRowOrColumnFormula.add(_formulaRowOrColumnTextField); 133 134 tabbedPanesPanel.add(_panelRowOrColumnLabel); 135 136 tabbedPanesPanel.add(_tabbedRowOrColumnPane); 137 138 panel.add(tabbedPanesPanel); 139 140 JPanel localVariablePanel = new JPanel(); 141 localVariablePanel.add(new JLabel(Bundle.getMessage("TableForEachSwing_LocalVariable"))); 142 _localVariable = new JTextField(20); 143 localVariablePanel.add(_localVariable); 144 panel.add(localVariablePanel); 145 146 JPanel infoPanel = new JPanel(); 147 infoPanel.add(new JLabel(Bundle.getMessage("TableForEachSwing_Info"))); 148 panel.add(infoPanel); 149 150 if (action != null) { 151 _tableRowOrColumnComboBox.setSelectedItem(action.getRowOrColumn()); 152 153 switch (action.getRowOrColumnAddressing()) { 154 case Direct: _tabbedRowOrColumnPane.setSelectedComponent(_panelRowOrColumnName); break; 155 case Reference: _tabbedRowOrColumnPane.setSelectedComponent(_panelRowOrColumnReference); break; 156 case LocalVariable: _tabbedRowOrColumnPane.setSelectedComponent(_panelRowOrColumnLocalVariable); break; 157 case Formula: _tabbedRowOrColumnPane.setSelectedComponent(_panelRowOrColumnFormula); break; 158 default: throw new IllegalArgumentException("invalid _rowOrColumnAddressing state: " + action.getRowOrColumnAddressing().name()); 159 } 160 161 _rowOrColumnNameTextField.setText(action.getRowOrColumnName()); 162 _referenceRowOrColumnTextField.setText(action.getRowOrColumnReference()); 163 _localRowOrColumnVariableTextField.setText(action.getRowOrColumnLocalVariable()); 164 _formulaRowOrColumnTextField.setText(action.getRowOrColumnFormula()); 165 166 _localVariable.setText(action.getLocalVariableName()); 167 } 168 } 169 170 private void setupRowOrColumnNameComboBox(String rowOrColumnName) { 171 if (_selectNamedBeanSwing.getAddressing() == NamedBeanAddressing.Direct) { 172 _rowOrColumnNameComboBox.removeAllItems(); 173 NamedTable table = _selectNamedBeanSwing.getBean(); 174 if (table != null) { 175 _rowOrColumnNameComboBox.addItem(Bundle.getMessage("TableForEach_Header")); 176 177 if (_tableRowOrColumnComboBox.getItemAt(_tableRowOrColumnComboBox.getSelectedIndex()) == TableRowOrColumn.Column) { 178 for (int column=0; column <= table.numColumns(); column++) { 179 // If the header is null or empty, treat the row as a comment 180 Object header = table.getCell(0, column); 181 if ((header != null) && (!header.toString().isEmpty())) { 182 _rowOrColumnNameComboBox.addItem(header.toString()); 183 } 184 } 185 } else { 186 for (int row=0; row <= table.numRows(); row++) { 187 // If the header is null or empty, treat the row as a comment 188 Object header = table.getCell(row, 0); 189 if ((header != null) && (!header.toString().isEmpty())) { 190 _rowOrColumnNameComboBox.addItem(header.toString()); 191 } 192 } 193 } 194 if (rowOrColumnName == null || rowOrColumnName.isEmpty()) { // Header row or column 195 _rowOrColumnNameComboBox.setSelectedIndex(0); 196 } else { 197 _rowOrColumnNameComboBox.setSelectedItem(rowOrColumnName); 198 } 199 } 200 } 201 } 202 203 /** {@inheritDoc} */ 204 @Override 205 public boolean validate(@Nonnull List<String> errorMessages) { 206 // Create a temporary action to test formula 207 TableForEach action = new TableForEach("IQDA1", null); 208 209 _selectNamedBeanSwing.validate(action.getSelectNamedBean(), errorMessages); 210 211 try { 212 if (_tabbedRowOrColumnPane.getSelectedComponent() == _panelRowOrColumnName) { 213 action.setRowOrColumnAddressing(NamedBeanAddressing.Direct); 214 } else if (_tabbedRowOrColumnPane.getSelectedComponent() == _panelRowOrColumnReference) { 215 action.setRowOrColumnAddressing(NamedBeanAddressing.Reference); 216 } else if (_tabbedRowOrColumnPane.getSelectedComponent() == _panelRowOrColumnLocalVariable) { 217 action.setRowOrColumnAddressing(NamedBeanAddressing.LocalVariable); 218 } else if (_tabbedRowOrColumnPane.getSelectedComponent() == _panelRowOrColumnFormula) { 219 action.setRowOrColumnFormula(_formulaRowOrColumnTextField.getText()); 220 action.setRowOrColumnAddressing(NamedBeanAddressing.Formula); 221 } else { 222 throw new IllegalArgumentException("_tabbedRowOrColumnPane has unknown selection"); 223 } 224 } catch (ParserException e) { 225 errorMessages.add("Cannot parse formula: " + e.getMessage()); 226 return false; 227 } 228 229 return errorMessages.isEmpty(); 230 } 231 232 /** {@inheritDoc} */ 233 @Override 234 public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) { 235 TableForEach action = new TableForEach(systemName, userName); 236 updateObject(action); 237 return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action); 238 } 239 240 /** {@inheritDoc} */ 241 @Override 242 public void updateObject(@Nonnull Base object) { 243 if (!(object instanceof TableForEach)) { 244 throw new IllegalArgumentException("object must be an TableForEach but is a: "+object.getClass().getName()); 245 } 246 247 248 TableForEach action = (TableForEach)object; 249 action.setRowOrColumn(_tableRowOrColumnComboBox.getItemAt(_tableRowOrColumnComboBox.getSelectedIndex())); 250 _selectNamedBeanSwing.updateObject(action.getSelectNamedBean()); 251 252 try { 253 if (_tabbedRowOrColumnPane.getSelectedComponent() == _panelRowOrColumnName) { 254 action.setRowOrColumnAddressing(NamedBeanAddressing.Direct); 255 if (_selectNamedBeanSwing.getAddressing() == NamedBeanAddressing.Direct) { 256 if (_rowOrColumnNameComboBox.getSelectedIndex() > 0) { 257 action.setRowOrColumnName(_rowOrColumnNameComboBox.getItemAt(_rowOrColumnNameComboBox.getSelectedIndex())); 258 } else { 259 action.setRowOrColumnName(""); // Header row or column 260 } 261 } else { 262 action.setRowOrColumnName(_rowOrColumnNameTextField.getText()); 263 } 264 } else if (_tabbedRowOrColumnPane.getSelectedComponent() == _panelRowOrColumnReference) { 265 action.setRowOrColumnAddressing(NamedBeanAddressing.Reference); 266 action.setRowOrColumnReference(_referenceRowOrColumnTextField.getText()); 267 } else if (_tabbedRowOrColumnPane.getSelectedComponent() == _panelRowOrColumnLocalVariable) { 268 action.setRowOrColumnAddressing(NamedBeanAddressing.LocalVariable); 269 action.setRowOrColumnLocalVariable(_localRowOrColumnVariableTextField.getText()); 270 } else if (_tabbedRowOrColumnPane.getSelectedComponent() == _panelRowOrColumnFormula) { 271 action.setRowOrColumnAddressing(NamedBeanAddressing.Formula); 272 action.setRowOrColumnFormula(_formulaRowOrColumnTextField.getText()); 273 } else { 274 throw new IllegalArgumentException("_tabbedPaneTurnoutState has unknown selection"); 275 } 276 277 action.setLocalVariableName(_localVariable.getText()); 278 } catch (ParserException e) { 279 throw new RuntimeException("ParserException: "+e.getMessage(), e); 280 } 281 } 282 283 /** {@inheritDoc} */ 284 @Override 285 public String toString() { 286 return Bundle.getMessage("TableForEach_Short"); 287 } 288 289 @Override 290 public void dispose() { 291 } 292 293 294// private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TableForEachSwing.class); 295 296}