001package jmri.jmrit.logixng.tools.swing; 002 003import java.awt.event.*; 004import java.util.*; 005 006import jmri.Category; 007import jmri.InstanceManager; 008import jmri.jmrit.beantable.BeanTableDataModel; 009import jmri.jmrit.logixng.*; 010import jmri.jmrit.logixng.Module; 011import jmri.jmrit.logixng.implementation.AbstractFemaleSocket; 012import jmri.jmrit.logixng.implementation.DefaultConditionalNG; 013import jmri.jmrit.logixng.swing.SwingConfiguratorInterface; 014import jmri.jmrit.logixng.util.LogixNG_Thread; 015 016/** 017 * Editor of Module 018 * 019 * @author Daniel Bergqvist 2020 020 */ 021public class ModuleEditor extends TreeEditor implements AbstractLogixNGEditor<Module> { 022 023 BeanTableDataModel<Module> beanTableDataModel; 024 025// private final ModuleManager _moduleManager = 026// InstanceManager.getDefault(ModuleManager.class); 027 028 protected final Module _module; 029 030 /** 031 * Maintain a list of listeners -- normally only one. 032 */ 033 private final List<EditorEventListener> listenerList = new ArrayList<>(); 034 035 /** 036 * This contains a list of commands to be processed by the listener 037 * recipient. 038 */ 039 final HashMap<String, String> moduleData = new HashMap<>(); 040 041 /** 042 * Create a new ConditionalNG List View editor. 043 * 044 * @param m the bean table model 045 * @param sName name of the LogixNG being edited 046 */ 047 public ModuleEditor(BeanTableDataModel<Module> m, String sName) { 048 049 super(setupRootSocket(null, sName), 050 EnableClipboard.EnableClipboard, 051 EnableRootRemoveCutCopy.DisableRootRemoveCutCopy, 052 EnableRootPopup.EnableRootPopup, 053 EnableExecuteEvaluate.EnableExecuteEvaluate, 054 EnableChangeUsernameForRoot.DisableChangeUsername 055 ); 056 057 this.beanTableDataModel = m; 058 059 if (!_treePane._femaleRootSocket.isConnected()) { 060 // This should never happen 061 throw new RuntimeException("Module is not connected"); 062 } 063 if (!(_treePane._femaleRootSocket.getConnectedSocket().getObject() instanceof Module)) { 064 // This should never happen 065 throw new RuntimeException("Connected socket is not a Module"); 066 } 067 _module = (Module) _treePane._femaleRootSocket.getConnectedSocket().getObject(); 068 069 if (_module.getUserName() == null) { 070 ModuleEditor.this.setTitle( 071 Bundle.getMessage("TitleEditModule", _module.getSystemName())); 072 } else { 073 ModuleEditor.this.setTitle( 074 Bundle.getMessage("TitleEditModule2", 075 _module.getSystemName(), 076 _module.getUserName())); 077 } 078 } 079 080 @Override 081 protected void executeEvaluate(SwingConfiguratorInterface swi, MaleSocket maleSocket) { 082 Base b = maleSocket; 083 Module module; 084 if (maleSocket.getObject() instanceof Module) { 085 module = (Module)maleSocket.getObject(); 086 } else { 087 while ((b != null) && !(b instanceof Module)) b = b.getParent(); 088 if (b == null) throw new RuntimeException("Module is not found"); 089 module = (Module)b; 090 } 091 092 LogixNG_Thread.getThread(LogixNG_Thread.DEFAULT_LOGIXNG_THREAD).runOnLogixNGEventually(() -> { 093 094 // We need to create a temporary ConditionalNG to be able to 095 // execute/evaluate a module or a part of a module 096 module.setCurrentConditionalNG(new DefaultConditionalNG("IQC1", null)); 097 098 swi.executeEvaluate(maleSocket); 099 }); 100 } 101 102 private static FemaleSocket setupRootSocket(Base parent, String sName) { 103 FemaleSocket socket = new RootSocket(parent, new FemaleSocketListener() { 104 @Override 105 public void connected(FemaleSocket socket) { 106 // Do nothing 107 } 108 109 @Override 110 public void disconnected(FemaleSocket socket) { 111 // Do nothing 112 } 113 }, "Root"); 114 115 Module module = InstanceManager.getDefault(ModuleManager.class).getBySystemName(sName); 116 117 try { 118 socket.connect(new ModuleEditorMaleSocket(null, module)); 119 } catch (SocketAlreadyConnectedException e) { 120 // This should never happen 121 throw new RuntimeException("Socket already connected", e); 122 } 123 124 return socket; 125 } 126 127 /** {@inheritDoc} */ 128 @Override 129 public void windowClosed(WindowEvent e) { 130 moduleData.clear(); 131 moduleData.put("Finish", _module.getSystemName()); // NOI18N 132 fireModuleEvent(); 133 } 134 135 /** 136 * Notify the listeners to check for new data. 137 */ 138 void fireModuleEvent() { 139 for (EditorEventListener l : listenerList) { 140 l.editorEventOccurred(moduleData); 141 } 142 } 143 144 @Override 145 public void addEditorEventListener(EditorEventListener listener) { 146 listenerList.add(listener); 147 } 148 149 @Override 150 public void removeEditorEventListener(EditorEventListener listener) { 151 listenerList.remove(listener); 152 } 153 154 @Override 155 public void bringToFront() { 156 this.setVisible(true); 157 } 158 159 160 private static class RootSocket extends AbstractFemaleSocket { 161 162 public RootSocket(Base parent, FemaleSocketListener listener, String name) { 163 super(parent, listener, name); 164 } 165 166 @Override 167 public boolean canDisconnect() { 168 return false; 169 } 170 171 @Override 172 public void disposeMe() { 173 throw new UnsupportedOperationException("Not supported"); 174 } 175 176 @Override 177 public boolean isCompatible(MaleSocket socket) { 178 return socket instanceof ModuleEditorMaleSocket; 179 } 180 181 @Override 182 public Map<Category, List<Class<? extends Base>>> getConnectableClasses() { 183// Map<Category, List<Class<? extends Base>>> map = new HashMap<>(); 184// List<Class<? extends Base>> list = new ArrayList<>(); 185// map.put(Category.OTHER, list); 186// list.add(Module.class); 187// return map; 188 throw new UnsupportedOperationException("Not supported"); 189 } 190 191 @Override 192 public String getShortDescription(Locale locale) { 193 return Bundle.getMessage(locale, "ModuleEditor_RootSocket_Short"); 194 } 195 196 @Override 197 public String getLongDescription(Locale locale) { 198 return Bundle.getMessage(locale, "ModuleEditor_RootSocket_Long", getName()); 199 } 200 201 } 202 203}