001package jmri.util.startup; 002 003import java.awt.Component; 004import java.lang.reflect.InvocationTargetException; 005import java.util.Optional; 006 007import javax.swing.Action; 008import javax.swing.BoxLayout; 009import javax.swing.JComboBox; 010import javax.swing.JLabel; 011import javax.swing.JList; 012import javax.swing.JPanel; 013import javax.swing.JScrollPane; 014import javax.swing.SwingConstants; 015import javax.swing.event.ListSelectionEvent; 016 017import jmri.InstanceManager; 018import jmri.SystemConnectionMemo; 019import jmri.jmrix.swing.SystemConnectionAction; 020import jmri.util.ConnectionNameFromSystemName; 021import jmri.util.swing.JmriJOptionPane; 022 023/** 024 * Provide an abstract StartupModelFactory with common methods for factories 025 * that manipulate models that extend {@link jmri.util.startup.AbstractActionModel}. 026 * 027 * @author Randall Wood 028 */ 029public abstract class AbstractActionModelFactory implements StartupModelFactory { 030 031 @Override 032 public String getDescription() { 033 return Bundle.getMessage(this.getModelClass().getCanonicalName()); 034 } 035 036 @Override 037 public String getActionText() { 038 return Bundle.getMessage("EditableStartupAction", this.getDescription()); 039 } 040 041 /** 042 * Get the message text for the dialog created in 043 * {@link #editModel(StartupModel, java.awt.Component)}. 044 * 045 * @return the message text 046 */ 047 public abstract String getEditModelMessage(); 048 049 @Override 050 public void editModel(StartupModel model, Component parent) { 051 if (model instanceof AbstractActionModel && this.getModelClass().isInstance(model)) { 052 JList<String> actions = new JList<>(StartupActionModelUtil.getDefault().getNames()); 053 JComboBox<String> connections = new JComboBox<>(); 054 JPanel message = this.getDialogMessage(actions, connections); 055 actions.setSelectedValue(model.getName(), true); 056 String userName = ConnectionNameFromSystemName.getConnectionName(((AbstractActionModel) model).getSystemPrefix()); 057 if (userName == null) { 058 userName = ""; // make not null to simplify following conditionals 059 } 060 if (!userName.isEmpty()) { 061 connections.setSelectedItem(userName); 062 } 063 int result = JmriJOptionPane.showConfirmDialog(parent, 064 message, 065 this.getDescription(), 066 JmriJOptionPane.OK_CANCEL_OPTION, 067 JmriJOptionPane.PLAIN_MESSAGE); 068 if (result == JmriJOptionPane.OK_OPTION) { 069 if (actions.getSelectedIndex() >= 0) { // checks for nothing selected 070 String name = actions.getSelectedValue(); 071 Optional<StartupActionsManager> manager = InstanceManager.getOptionalDefault(StartupActionsManager.class); 072 if (!name.equals(model.getName())) { 073 model.setName(name); 074 manager.ifPresent(StartupActionsManager::setRestartRequired); 075 } 076 if ((userName.isEmpty() && connections.getSelectedItem() != null) 077 || !userName.equals(connections.getSelectedItem())) { 078 ((AbstractActionModel) model).setSystemPrefix(ConnectionNameFromSystemName.getPrefixFromName((String) connections.getSelectedItem())); 079 manager.ifPresent(StartupActionsManager::setRestartRequired); 080 } 081 } 082 } 083 } 084 } 085 086 @Override 087 public void initialize() { 088 // nothing to do 089 } 090 091 private JPanel getDialogMessage(JList<String> actions, JComboBox<String> connections) { 092 JLabel connectionsLabel = new JLabel(Bundle.getMessage("AbstractActionModelFactory.getDialogMessage.connectionsLabel", SwingConstants.LEADING)); // NOI18N 093 actions.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> { 094 if (!e.getValueIsAdjusting()) { 095 connections.removeAllItems(); 096 connections.setEnabled(false); 097 connectionsLabel.setEnabled(false); 098 String name = actions.getSelectedValue(); 099 if (name != null) { 100 String className = StartupActionModelUtil.getDefault().getClassName(name); 101 if (className != null && StartupActionModelUtil.getDefault().isSystemConnectionAction(className)) { 102 try { 103 Action action = (Action) Class.forName(className).getDeclaredConstructor().newInstance(); 104 if (action instanceof SystemConnectionAction) { 105 ((SystemConnectionAction<?>) action).getSystemConnectionMemoClasses().forEach(clazz 106 -> InstanceManager.getList(SystemConnectionMemo.class).stream() 107 .filter(memo -> clazz.isAssignableFrom(memo.getClass())) 108 .forEach(memo -> { 109 connections.addItem(memo.getUserName()); 110 connections.setEnabled(true); 111 connectionsLabel.setEnabled(true); 112 })); 113 } 114 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) { 115 log.error("Unable to create Action", ex); 116 } 117 } 118 } 119 } 120 }); 121 connections.setEnabled(false); 122 connectionsLabel.setEnabled(false); 123 JPanel panel = new JPanel(); 124 panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); 125 panel.add(new JLabel(this.getEditModelMessage(), SwingConstants.LEADING)); 126 panel.add(new JScrollPane(actions)); 127 panel.add(connectionsLabel); 128 panel.add(connections); 129 return panel; 130 } 131 132 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractActionModelFactory.class); 133 134}