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