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 ); 055 056 this.beanTableDataModel = m; 057 058 if (!_treePane._femaleRootSocket.isConnected()) { 059 // This should never happen 060 throw new RuntimeException("Module is not connected"); 061 } 062 if (!(_treePane._femaleRootSocket.getConnectedSocket().getObject() instanceof Module)) { 063 // This should never happen 064 throw new RuntimeException("Connected socket is not a Module"); 065 } 066 _module = (Module) _treePane._femaleRootSocket.getConnectedSocket().getObject(); 067 068 if (_module.getUserName() == null) { 069 ModuleEditor.this.setTitle( 070 Bundle.getMessage("TitleEditModule", _module.getSystemName())); 071 } else { 072 ModuleEditor.this.setTitle( 073 Bundle.getMessage("TitleEditModule2", 074 _module.getSystemName(), 075 _module.getUserName())); 076 } 077 } 078 079 @Override 080 protected void executeEvaluate(SwingConfiguratorInterface swi, MaleSocket maleSocket) { 081 Base b = maleSocket; 082 Module module; 083 if (maleSocket.getObject() instanceof Module) { 084 module = (Module)maleSocket.getObject(); 085 } else { 086 while ((b != null) && !(b instanceof Module)) b = b.getParent(); 087 if (b == null) throw new RuntimeException("Module is not found"); 088 module = (Module)b; 089 } 090 091 LogixNG_Thread.getThread(LogixNG_Thread.DEFAULT_LOGIXNG_THREAD).runOnLogixNGEventually(() -> { 092 093 // We need to create a temporary ConditionalNG to be able to 094 // execute/evaluate a module or a part of a module 095 module.setCurrentConditionalNG(new DefaultConditionalNG("IQC1", null)); 096 097 swi.executeEvaluate(maleSocket); 098 }); 099 } 100 101 private static FemaleSocket setupRootSocket(Base parent, String sName) { 102 FemaleSocket socket = new RootSocket(parent, new FemaleSocketListener() { 103 @Override 104 public void connected(FemaleSocket socket) { 105 // Do nothing 106 } 107 108 @Override 109 public void disconnected(FemaleSocket socket) { 110 // Do nothing 111 } 112 }, "Root"); 113 114 Module module = InstanceManager.getDefault(ModuleManager.class).getBySystemName(sName); 115 116 try { 117 socket.connect(new ModuleEditorMaleSocket(null, module)); 118 } catch (SocketAlreadyConnectedException e) { 119 // This should never happen 120 throw new RuntimeException("Socket already connected", e); 121 } 122 123 return socket; 124 } 125 126 /** {@inheritDoc} */ 127 @Override 128 public void windowClosed(WindowEvent e) { 129 moduleData.clear(); 130 moduleData.put("Finish", _module.getSystemName()); // NOI18N 131 fireModuleEvent(); 132 } 133 134 /** 135 * Notify the listeners to check for new data. 136 */ 137 void fireModuleEvent() { 138 for (EditorEventListener l : listenerList) { 139 l.editorEventOccurred(moduleData); 140 } 141 } 142 143 @Override 144 public void addEditorEventListener(EditorEventListener listener) { 145 listenerList.add(listener); 146 } 147 148 @Override 149 public void removeEditorEventListener(EditorEventListener listener) { 150 listenerList.remove(listener); 151 } 152 153 @Override 154 public void bringToFront() { 155 this.setVisible(true); 156 } 157 158 159 private static class RootSocket extends AbstractFemaleSocket { 160 161 public RootSocket(Base parent, FemaleSocketListener listener, String name) { 162 super(parent, listener, name); 163 } 164 165 @Override 166 public boolean canDisconnect() { 167 return false; 168 } 169 170 @Override 171 public void disposeMe() { 172 throw new UnsupportedOperationException("Not supported"); 173 } 174 175 @Override 176 public boolean isCompatible(MaleSocket socket) { 177 return socket instanceof ModuleEditorMaleSocket; 178 } 179 180 @Override 181 public Map<Category, List<Class<? extends Base>>> getConnectableClasses() { 182// Map<Category, List<Class<? extends Base>>> map = new HashMap<>(); 183// List<Class<? extends Base>> list = new ArrayList<>(); 184// map.put(Category.OTHER, list); 185// list.add(Module.class); 186// return map; 187 throw new UnsupportedOperationException("Not supported"); 188 } 189 190 @Override 191 public String getShortDescription(Locale locale) { 192 return Bundle.getMessage(locale, "ModuleEditor_RootSocket_Short"); 193 } 194 195 @Override 196 public String getLongDescription(Locale locale) { 197 return Bundle.getMessage(locale, "ModuleEditor_RootSocket_Long", getName()); 198 } 199 200 } 201 202}