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