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