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