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}