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