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