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 String name = actions.getSelectedValue(); 070 Optional<StartupActionsManager> manager = InstanceManager.getOptionalDefault(StartupActionsManager.class); 071 if (!name.equals(model.getName())) { 072 model.setName(name); 073 manager.ifPresent(StartupActionsManager::setRestartRequired); 074 } 075 if ((userName.isEmpty() && connections.getSelectedItem() != null) 076 || !userName.equals(connections.getSelectedItem())) { 077 ((AbstractActionModel) model).setSystemPrefix(ConnectionNameFromSystemName.getPrefixFromName((String) connections.getSelectedItem())); 078 manager.ifPresent(StartupActionsManager::setRestartRequired); 079 } 080 } 081 } 082 } 083 084 @Override 085 public void initialize() { 086 // nothing to do 087 } 088 089 private JPanel getDialogMessage(JList<String> actions, JComboBox<String> connections) { 090 JLabel connectionsLabel = new JLabel(Bundle.getMessage("AbstractActionModelFactory.getDialogMessage.connectionsLabel", SwingConstants.LEADING)); // NOI18N 091 actions.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> { 092 if (!e.getValueIsAdjusting()) { 093 connections.removeAllItems(); 094 connections.setEnabled(false); 095 connectionsLabel.setEnabled(false); 096 String name = actions.getSelectedValue(); 097 if (name != null) { 098 String className = StartupActionModelUtil.getDefault().getClassName(name); 099 if (className != null && StartupActionModelUtil.getDefault().isSystemConnectionAction(className)) { 100 try { 101 Action action = (Action) Class.forName(className).getDeclaredConstructor().newInstance(); 102 if (action instanceof SystemConnectionAction) { 103 ((SystemConnectionAction<?>) action).getSystemConnectionMemoClasses().forEach(clazz 104 -> InstanceManager.getList(SystemConnectionMemo.class).stream() 105 .filter(memo -> clazz.isAssignableFrom(memo.getClass())) 106 .forEach(memo -> { 107 connections.addItem(memo.getUserName()); 108 connections.setEnabled(true); 109 connectionsLabel.setEnabled(true); 110 })); 111 } 112 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) { 113 log.error("Unable to create Action", ex); 114 } 115 } 116 } 117 } 118 }); 119 connections.setEnabled(false); 120 connectionsLabel.setEnabled(false); 121 JPanel panel = new JPanel(); 122 panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); 123 panel.add(new JLabel(this.getEditModelMessage(), SwingConstants.LEADING)); 124 panel.add(new JScrollPane(actions)); 125 panel.add(connectionsLabel); 126 panel.add(connections); 127 return panel; 128 } 129 130 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractActionModelFactory.class); 131 132}