001package jmri.jmrit.beantable;
002
003import java.awt.Container;
004import java.awt.FlowLayout;
005import java.awt.event.ItemEvent;
006import java.beans.PropertyVetoException;
007import java.io.PrintWriter;
008import java.io.StringWriter;
009import java.util.*;
010
011import javax.swing.*;
012
013import jmri.InstanceManager;
014import jmri.Manager;
015import jmri.util.JmriJFrame;
016
017import jmri.jmrit.logixng.*;
018import jmri.jmrit.logixng.Module;
019
020import jmri.jmrit.logixng.tools.swing.AbstractLogixNGEditor;
021import jmri.jmrit.logixng.tools.swing.ModuleEditor;
022import jmri.jmrit.logixng.ModuleManager;
023
024import org.apache.commons.lang3.mutable.MutableInt;
025
026/**
027 * Swing action to create and register a LogixNG Table.
028 * <p>
029 Also contains the panes to create, edit, and delete a LogixNG.
030 <p>
031 * Most of the text used in this GUI is in BeanTableBundle.properties, accessed
032 * via Bundle.getMessage().
033 *
034 * @author Dave Duchamp Copyright (C) 2007 (LogixTableAction)
035 * @author Pete Cressman Copyright (C) 2009, 2010, 2011 (LogixTableAction)
036 * @author Matthew Harris copyright (c) 2009 (LogixTableAction)
037 * @author Dave Sand copyright (c) 2017 (LogixTableAction)
038 * @author Daniel Bergqvist copyright (c) 2019
039 * @author Dave Sand copyright (c) 2021
040 */
041public class LogixNGModuleTableAction extends AbstractLogixNGTableAction<jmri.jmrit.logixng.Module> {
042
043    JComboBox<FemaleSocketManager.SocketType> _femaleSocketType = new JComboBox<>();
044
045    /**
046     * Create a LogixNGTableAction instance.
047     *
048     * @param s the Action title, not the title of the resulting frame. Perhaps
049     *          this should be changed?
050     */
051    public LogixNGModuleTableAction(String s) {
052        super(s);
053    }
054
055    /**
056     * Create a LogixNGTableAction instance with default title.
057     */
058    public LogixNGModuleTableAction() {
059        this(Bundle.getMessage("TitleLogixNGModuleTable"));
060    }
061
062    @Override
063    protected void setTitle() {
064        f.setTitle(Bundle.getMessage("TitleLogixNGModuleTable"));
065    }
066
067    @Override
068    public String getClassDescription() {
069        return Bundle.getMessage("TitleLogixNGModuleTable");        // NOI18N
070    }
071
072    @Override
073    protected AbstractLogixNGEditor<Module> getEditor(BeanTableDataModel<Module> m, String sName) {
074        ModuleEditor editor = new ModuleEditor(m, sName);
075        editor.initComponents();
076        return editor;
077    }
078
079    @Override
080    protected Manager<Module> getManager() {
081        return InstanceManager.getDefault(ModuleManager.class);
082    }
083
084    @Override
085    protected void enableAll(boolean enable) {
086        // Not used by the module table
087    }
088
089    @Override
090    protected void setEnabled(Module bean, boolean enable) {
091        // Not used by the module table
092    }
093
094    @Override
095    protected boolean isEnabled(Module bean) {
096        return true;
097    }
098
099    @Override
100    protected Module createBean(String userName) {
101        Module module = InstanceManager.getDefault(ModuleManager.class)
102                .createModule(userName, _femaleSocketType.getItemAt(_femaleSocketType.getSelectedIndex()));
103        return module;
104    }
105
106    @Override
107    protected Module createBean(String systemName, String userName) {
108        Module module = InstanceManager.getDefault(ModuleManager.class)
109                .createModule(systemName, userName,
110                        _femaleSocketType.getItemAt(_femaleSocketType.getSelectedIndex()));
111        return module;
112    }
113
114    @Override
115    protected void deleteBean(Module bean) {
116        try {
117            InstanceManager.getDefault(ModuleManager.class).deleteBean(bean, "DoDelete");
118        } catch (PropertyVetoException e) {
119            //At this stage the DoDelete shouldn't fail, as we have already done a can delete, which would trigger a veto
120            log.error("{} : Could not Delete.", e.getMessage());
121        }
122    }
123
124    @Override
125    protected String getBeanText(Module bean) {
126        StringWriter writer = new StringWriter();
127        _curNamedBean.printTree(_printTreeSettings, new PrintWriter(writer), "    ", new MutableInt(0));
128        return writer.toString();
129    }
130
131    @Override
132    protected String getBrowserTitle() {
133        return Bundle.getMessage("LogixNG_Module_Browse_Title");
134    }
135
136    @Override
137    protected String getAddTitleKey() {
138        return "TitleAddLogixNGModule";
139    }
140
141    @Override
142    protected String getCreateButtonHintKey() {
143        return "LogixNGModuleCreateButtonHint";
144    }
145
146    @Override
147    protected String helpTarget() {
148        return "package.jmri.jmrit.beantable.LogixNGModuleTable";  // NOI18N
149    }
150
151    /**
152     * Create or copy bean frame.
153     *
154     * @param titleId   property key to fetch as title of the frame (using Bundle)
155     * @param startMessageId part 1 of property key to fetch as user instruction on
156     *                  pane, either 1 or 2 is added to form the whole key
157     * @return the button JPanel
158     */
159    @Override
160    protected JPanel makeAddFrame(String titleId, String startMessageId) {
161        addLogixNGFrame = new JmriJFrame(Bundle.getMessage(titleId));
162        addLogixNGFrame.addHelpMenu(
163                "package.jmri.jmrit.beantable.LogixNGModuleTable", true);     // NOI18N
164        addLogixNGFrame.setLocation(50, 30);
165        Container contentPane = addLogixNGFrame.getContentPane();
166        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
167
168        List<FemaleSocketManager.SocketType> list
169                = new ArrayList<>(InstanceManager.getDefault(FemaleSocketManager.class).getSocketTypes().values());
170        Collections.sort(list, (FemaleSocketManager.SocketType o1, FemaleSocketManager.SocketType o2) -> o1.getDescr().compareTo(o2.getDescr()));
171
172        _femaleSocketType.removeAllItems();
173        for (FemaleSocketManager.SocketType socketType : list) {
174            _femaleSocketType.addItem(socketType);
175            if ("DefaultFemaleDigitalActionSocket".equals(socketType.getName())) {
176                _femaleSocketType.setSelectedItem(socketType);
177            }
178        }
179
180        JPanel p;
181        p = new JPanel();
182        p.setLayout(new FlowLayout());
183        p.setLayout(new java.awt.GridBagLayout());
184        java.awt.GridBagConstraints c = new java.awt.GridBagConstraints();
185        c.gridwidth = 1;
186        c.gridheight = 1;
187        c.gridx = 0;
188        c.gridy = 0;
189        c.anchor = java.awt.GridBagConstraints.EAST;
190        p.add(_sysNameLabel, c);
191        _sysNameLabel.setLabelFor(_systemName);
192        c.gridy = 1;
193        p.add(_userNameLabel, c);
194        _userNameLabel.setLabelFor(_addUserName);
195        c.gridy = 2;
196        p.add(new JLabel(Bundle.getMessage("LogixNG_ModuleSocketType")), c);
197        c.gridx = 1;
198        c.gridy = 0;
199        c.anchor = java.awt.GridBagConstraints.WEST;
200        c.weightx = 1.0;
201        c.fill = java.awt.GridBagConstraints.HORIZONTAL;  // text field will expand
202        p.add(_systemName, c);
203        c.gridy = 1;
204        p.add(_addUserName, c);
205        c.gridy = 2;
206        c.gridwidth = 2;
207        p.add(_femaleSocketType, c);
208        c.gridx = 2;
209        c.gridy = 1;
210        c.anchor = java.awt.GridBagConstraints.WEST;
211        c.weightx = 1.0;
212        c.fill = java.awt.GridBagConstraints.HORIZONTAL;  // text field will expand
213        c.gridy = 0;
214        p.add(_autoSystemName, c);
215        _addUserName.setToolTipText(Bundle.getMessage("LogixNGUserNameHint"));    // NOI18N
216        _systemName.setToolTipText(Bundle.getMessage("LogixNGSystemNameHint"));   // NOI18N
217        contentPane.add(p);
218        // set up message
219        JPanel panel3 = new JPanel();
220        panel3.setLayout(new BoxLayout(panel3, BoxLayout.Y_AXIS));
221        JPanel panel31 = new JPanel();
222        panel31.setLayout(new FlowLayout());
223        JLabel message1 = new JLabel(Bundle.getMessage(startMessageId + "LogixNGModuleMessage1"));  // NOI18N
224        panel31.add(message1);
225        JPanel panel32 = new JPanel();
226        JLabel message2 = new JLabel(Bundle.getMessage(startMessageId + "LogixNGModuleMessage2"));  // NOI18N
227        panel32.add(message2);
228        panel3.add(panel31);
229        panel3.add(panel32);
230        contentPane.add(panel3);
231
232        // set up create and cancel buttons
233        JPanel panel5 = new JPanel();
234        panel5.setLayout(new FlowLayout());
235        // Cancel
236        JButton cancel = new JButton(Bundle.getMessage("ButtonCancel"));    // NOI18N
237        panel5.add(cancel);
238        cancel.addActionListener(this::cancelAddPressed);
239        cancel.setToolTipText(Bundle.getMessage("CancelLogixButtonHint"));      // NOI18N
240
241        addLogixNGFrame.addWindowListener(new java.awt.event.WindowAdapter() {
242            @Override
243            public void windowClosing(java.awt.event.WindowEvent e) {
244                cancelAddPressed(null);
245            }
246        });
247        contentPane.add(panel5);
248
249        _autoSystemName.addItemListener((ItemEvent e) -> {
250            autoSystemName();
251        });
252        return panel5;
253    }
254
255    @Override
256    protected void getListenerRefsIncludingChildren(Module module, java.util.List<String> list) {
257        module.getListenerRefsIncludingChildren(list);
258    }
259
260    @Override
261    protected boolean hasChildren(Module module) {
262        return module.getRootSocket().isConnected();
263    }
264
265    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogixNGModuleTableAction.class);
266
267}