001package jmri.jmrit.logixng.util.swing; 002 003import java.awt.Component; 004import java.awt.event.ActionListener; 005import java.util.List; 006 007import javax.annotation.Nonnull; 008import javax.swing.*; 009import javax.swing.event.ChangeListener; 010 011import jmri.*; 012import jmri.jmrit.logixng.*; 013import jmri.jmrit.logixng.swing.SwingConfiguratorInterface; 014import jmri.jmrit.logixng.util.LogixNG_SelectComboBox; 015import jmri.jmrit.logixng.util.parser.ParserException; 016import jmri.util.swing.BeanSelectPanel; 017import jmri.util.swing.JComboBoxUtil; 018 019/** 020 * Swing class for jmri.jmrit.logixng.util.LogixNG_SelectComboBox. 021 * 022 * @author Daniel Bergqvist (C) 2024 023 */ 024public class LogixNG_SelectComboBoxSwing { 025 026 private final JDialog _dialog; 027 private final LogixNG_SelectTableSwing _selectTableSwing; 028 029 private JTabbedPane _tabbedPane; 030 private JComboBox<String> _valuesComboBox; 031 private JPanel _panelDirect; 032 private JPanel _panelReference; 033 private JPanel _panelMemory; 034 private JPanel _panelLocalVariable; 035 private JPanel _panelFormula; 036 private JPanel _panelTable; 037 private JTextField _referenceTextField; 038 private BeanSelectPanel<Memory> _memoryPanel; 039 private JCheckBox _listenToMemoryCheckBox; 040 private JTextField _localVariableTextField; 041 private JTextField _formulaTextField; 042 043 044 public LogixNG_SelectComboBoxSwing( 045 @Nonnull JDialog dialog, 046 @Nonnull SwingConfiguratorInterface swi) { 047 _dialog = dialog; 048 _selectTableSwing = new LogixNG_SelectTableSwing(_dialog, swi); 049 } 050 051 public JPanel createPanel( 052 @Nonnull LogixNG_SelectComboBox selectComboBox) { 053 return createPanel(selectComboBox, null); 054 } 055 056 public JPanel createPanel( 057 @Nonnull LogixNG_SelectComboBox selectComboBox, String defaultValue) { 058 059 JPanel panel = new JPanel(); 060 061 _tabbedPane = new JTabbedPane(); 062 _panelDirect = new javax.swing.JPanel(); 063 _panelReference = new javax.swing.JPanel(); 064 _panelMemory = new JPanel(); 065 _panelLocalVariable = new javax.swing.JPanel(); 066 _panelFormula = new javax.swing.JPanel(); 067 _panelTable = _selectTableSwing.createPanel(selectComboBox.getSelectTable()); 068 069 _memoryPanel = new BeanSelectPanel<>(InstanceManager.getDefault(MemoryManager.class), null); 070 _listenToMemoryCheckBox = new JCheckBox(Bundle.getMessage("ListenToMemory")); 071 072 _panelMemory.setLayout(new BoxLayout(_panelMemory, BoxLayout.Y_AXIS)); 073 _panelMemory.add(_memoryPanel); 074 _panelMemory.add(_listenToMemoryCheckBox); 075 076 _tabbedPane.addTab(NamedBeanAddressing.Direct.toString(), _panelDirect); 077 _tabbedPane.addTab(NamedBeanAddressing.Reference.toString(), _panelReference); 078 _tabbedPane.addTab(NamedBeanAddressing.Memory.toString(), _panelMemory); 079 _tabbedPane.addTab(NamedBeanAddressing.LocalVariable.toString(), _panelLocalVariable); 080 _tabbedPane.addTab(NamedBeanAddressing.Formula.toString(), _panelFormula); 081 _tabbedPane.addTab(NamedBeanAddressing.Table.toString(), _panelTable); 082 083 _valuesComboBox = new JComboBox<>(); 084 for (String value : selectComboBox.getValues()) { 085 _valuesComboBox.addItem(value); 086 } 087 JComboBoxUtil.setupComboBoxMaxRows(_valuesComboBox); 088 _valuesComboBox.setRenderer(new ComboBoxRenderer<>(_valuesComboBox.getRenderer())); 089 _panelDirect.add(_valuesComboBox); 090 091 _referenceTextField = new JTextField(); 092 _referenceTextField.setColumns(30); 093 _panelReference.add(_referenceTextField); 094 095 _localVariableTextField = new JTextField(); 096 _localVariableTextField.setColumns(30); 097 _panelLocalVariable.add(_localVariableTextField); 098 099 _formulaTextField = new JTextField(); 100 _formulaTextField.setColumns(30); 101 _panelFormula.add(_formulaTextField); 102 103 104 if (defaultValue != null) { 105 _valuesComboBox.setSelectedItem(defaultValue); 106 } 107 108 switch (selectComboBox.getAddressing()) { 109 case Direct: _tabbedPane.setSelectedComponent(_panelDirect); break; 110 case Reference: _tabbedPane.setSelectedComponent(_panelReference); break; 111 case Memory: _tabbedPane.setSelectedComponent(_panelMemory); break; 112 case LocalVariable: _tabbedPane.setSelectedComponent(_panelLocalVariable); break; 113 case Formula: _tabbedPane.setSelectedComponent(_panelFormula); break; 114 case Table: _tabbedPane.setSelectedComponent(_panelTable); break; 115 default: throw new IllegalArgumentException("invalid _addressing state: " + selectComboBox.getAddressing().name()); 116 } 117 if (selectComboBox.getValue() != null) { 118 _valuesComboBox.setSelectedItem(selectComboBox.getValue()); 119 } 120 _referenceTextField.setText(selectComboBox.getReference()); 121 _memoryPanel.setDefaultNamedBean(selectComboBox.getMemory()); 122 _listenToMemoryCheckBox.setSelected(selectComboBox.getListenToMemory()); 123 _localVariableTextField.setText(selectComboBox.getLocalVariable()); 124 _formulaTextField.setText(selectComboBox.getFormula()); 125 126 panel.add(_tabbedPane); 127 return panel; 128 } 129 130 public void addAddressingListener(ChangeListener listener) { 131 _tabbedPane.addChangeListener(listener); 132 } 133 134 public void addEnumListener(ActionListener listener) { 135 _valuesComboBox.addActionListener(listener); 136 } 137 138 public boolean validate( 139 @Nonnull LogixNG_SelectComboBox selectComboBox, 140 @Nonnull List<String> errorMessages) { 141 try { 142 if (_tabbedPane.getSelectedComponent() == _panelReference) { 143 selectComboBox.setReference(_referenceTextField.getText()); 144 } 145 } catch (IllegalArgumentException e) { 146 errorMessages.add(e.getMessage()); 147 return false; 148 } 149 150 try { 151 selectComboBox.setFormula(_formulaTextField.getText()); 152 selectComboBox.setAddressing(getAddressing()); 153 } catch (ParserException e) { 154 errorMessages.add("Cannot parse formula: " + e.getMessage()); 155 return false; 156 } 157 158 _selectTableSwing.validate(selectComboBox.getSelectTable(), errorMessages); 159 160 return errorMessages.isEmpty(); 161 } 162 163 public void updateObject(@Nonnull LogixNG_SelectComboBox selectComboBox) { 164 165 if (_tabbedPane.getSelectedComponent() == _panelDirect) { 166 selectComboBox.setValue(_valuesComboBox.getItemAt(_valuesComboBox.getSelectedIndex())); 167 } 168 169 try { 170 if (_tabbedPane.getSelectedComponent() == _panelDirect) { 171 selectComboBox.setAddressing(NamedBeanAddressing.Direct); 172 } else if (_tabbedPane.getSelectedComponent() == _panelReference) { 173 selectComboBox.setAddressing(NamedBeanAddressing.Reference); 174 selectComboBox.setReference(_referenceTextField.getText()); 175 } else if (_tabbedPane.getSelectedComponent() == _panelMemory) { 176 selectComboBox.setAddressing(NamedBeanAddressing.Memory); 177 selectComboBox.setMemory(_memoryPanel.getNamedBean()); 178 selectComboBox.setListenToMemory(_listenToMemoryCheckBox.isSelected()); 179 } else if (_tabbedPane.getSelectedComponent() == _panelLocalVariable) { 180 selectComboBox.setAddressing(NamedBeanAddressing.LocalVariable); 181 selectComboBox.setLocalVariable(_localVariableTextField.getText()); 182 } else if (_tabbedPane.getSelectedComponent() == _panelFormula) { 183 selectComboBox.setAddressing(NamedBeanAddressing.Formula); 184 selectComboBox.setFormula(_formulaTextField.getText()); 185 } else if (_tabbedPane.getSelectedComponent() == _panelTable) { 186 selectComboBox.setAddressing(NamedBeanAddressing.Table); 187 } else { 188 throw new IllegalArgumentException("_tabbedPaneEnum has unknown selection"); 189 } 190 } catch (ParserException e) { 191 throw new RuntimeException("ParserException: "+e.getMessage(), e); 192 } 193 194 _selectTableSwing.updateObject(selectComboBox.getSelectTable()); 195 } 196 197 public boolean isValueSelected(String value) { 198 if (_tabbedPane.getSelectedComponent() == _panelDirect) { 199 return _valuesComboBox.getItemAt(_valuesComboBox.getSelectedIndex()).equals(value); 200 } else { 201 return false; 202 } 203 } 204 205 public boolean isValueSelectedOrIndirectAddressing(String value) { 206 if (_tabbedPane.getSelectedComponent() == _panelDirect) { 207 return _valuesComboBox.getItemAt(_valuesComboBox.getSelectedIndex()).equals(value); 208 } else { 209 return true; 210 } 211 } 212 213 public NamedBeanAddressing getAddressing() { 214 if (_tabbedPane.getSelectedComponent() == _panelDirect) { 215 return NamedBeanAddressing.Direct; 216 } else if (_tabbedPane.getSelectedComponent() == _panelReference) { 217 return NamedBeanAddressing.Reference; 218 } else if (_tabbedPane.getSelectedComponent() == _panelMemory) { 219 return NamedBeanAddressing.Memory; 220 } else if (_tabbedPane.getSelectedComponent() == _panelLocalVariable) { 221 return NamedBeanAddressing.LocalVariable; 222 } else if (_tabbedPane.getSelectedComponent() == _panelFormula) { 223 return NamedBeanAddressing.Formula; 224 } else if (_tabbedPane.getSelectedComponent() == _panelTable) { 225 return NamedBeanAddressing.Table; 226 } else { 227 throw new IllegalArgumentException("_tabbedPane has unknown selection"); 228 } 229 } 230 231 public String getValue() { 232 return _valuesComboBox.getItemAt(_valuesComboBox.getSelectedIndex()); 233 } 234 235 public void setValue(String value) { 236 _valuesComboBox.setSelectedItem(value); 237 } 238 239 public void setValues(String[] valuesArray) { 240 String selectedValue = _valuesComboBox.getItemAt(_valuesComboBox.getSelectedIndex()); 241 242 _valuesComboBox.removeAllItems(); 243 for (String value : valuesArray) { 244 _valuesComboBox.addItem(value); 245 } 246 247 _valuesComboBox.setSelectedItem(selectedValue); 248 } 249 250 public void dispose() { 251 _selectTableSwing.dispose(); 252 } 253 254 255 private static class ComboBoxRenderer<E> extends JLabel implements ListCellRenderer<E> { 256 257 private final JSeparator _separator = new JSeparator(JSeparator.HORIZONTAL); 258 private final ListCellRenderer<E> _old; 259 260 private ComboBoxRenderer(ListCellRenderer<E> old) { 261 this._old = old; 262 } 263 264 @Override 265 public Component getListCellRendererComponent(JList<? extends E> list, 266 E value, int index, boolean isSelected, boolean cellHasFocus) { 267 if (Base.SEPARATOR.equals(value)) { 268 return _separator; 269 } else { 270 return _old.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 271 } 272 } 273 } 274 275}