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 createModel() {
064        m = new LogixNGModuleTableAction.TableModel();
065        m.setFilter((Module t) -> t.isVisible());
066    }
067
068    @Override
069    protected void setTitle() {
070        f.setTitle(Bundle.getMessage("TitleLogixNGModuleTable"));
071    }
072
073    @Override
074    public String getClassDescription() {
075        return Bundle.getMessage("TitleLogixNGModuleTable");        // NOI18N
076    }
077
078    @Override
079    protected AbstractLogixNGEditor<Module> getEditor(BeanTableDataModel<Module> m, String sName) {
080        ModuleEditor editor = new ModuleEditor(m, sName);
081        editor.initComponents();
082        return editor;
083    }
084
085    @Override
086    protected Manager<Module> getManager() {
087        return InstanceManager.getDefault(ModuleManager.class);
088    }
089
090    @Override
091    protected void enableAll(boolean enable) {
092        // Not used by the module table
093    }
094
095    @Override
096    protected void setEnabled(Module bean, boolean enable) {
097        // Not used by the module table
098    }
099
100    @Override
101    protected boolean isEnabled(Module bean) {
102        return true;
103    }
104
105    @Override
106    protected Module createBean(String userName) {
107        Module module = InstanceManager.getDefault(ModuleManager.class)
108                .createModule(userName, _femaleSocketType.getItemAt(_femaleSocketType.getSelectedIndex()));
109        return module;
110    }
111
112    @Override
113    protected Module createBean(String systemName, String userName) {
114        Module module = InstanceManager.getDefault(ModuleManager.class)
115                .createModule(systemName, userName,
116                        _femaleSocketType.getItemAt(_femaleSocketType.getSelectedIndex()));
117        return module;
118    }
119
120    @Override
121    protected void deleteBean(Module bean) {
122        try {
123            InstanceManager.getDefault(ModuleManager.class).deleteBean(bean, "DoDelete");
124        } catch (PropertyVetoException e) {
125            //At this stage the DoDelete shouldn't fail, as we have already done a can delete, which would trigger a veto
126            log.error("{} : Could not Delete.", e.getMessage());
127        }
128    }
129
130    @Override
131    protected String getBeanText(Module bean, Base.PrintTreeSettings printTreeSettings) {
132        StringWriter writer = new StringWriter();
133        _curNamedBean.printTree(printTreeSettings, new PrintWriter(writer), "    ", new MutableInt(0));
134        return writer.toString();
135    }
136
137    @Override
138    protected String getBrowserTitle() {
139        return Bundle.getMessage("LogixNG_Module_Browse_Title");
140    }
141
142    @Override
143    protected String getAddTitleKey() {
144        return "TitleAddLogixNGModule";
145    }
146
147    @Override
148    protected String getCreateButtonHintKey() {
149        return "LogixNGModuleCreateButtonHint";
150    }
151
152    @Override
153    protected String helpTarget() {
154        return "package.jmri.jmrit.beantable.LogixNGModuleTable";  // NOI18N
155    }
156
157    /**
158     * Create or copy bean frame.
159     *
160     * @param titleId   property key to fetch as title of the frame (using Bundle)
161     * @param startMessageId part 1 of property key to fetch as user instruction on
162     *                  pane, either 1 or 2 is added to form the whole key
163     * @return the button JPanel
164     */
165    @Override
166    protected JPanel makeAddFrame(String titleId, String startMessageId) {
167        addLogixNGFrame = new JmriJFrame(Bundle.getMessage(titleId));
168        addLogixNGFrame.addHelpMenu(
169                "package.jmri.jmrit.beantable.LogixNGModuleTable", true);     // NOI18N
170        addLogixNGFrame.setLocation(50, 30);
171        Container contentPane = addLogixNGFrame.getContentPane();
172        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
173
174        List<FemaleSocketManager.SocketType> list
175                = new ArrayList<>(InstanceManager.getDefault(FemaleSocketManager.class).getSocketTypes().values());
176        Collections.sort(list, (FemaleSocketManager.SocketType o1, FemaleSocketManager.SocketType o2) -> o1.getDescr().compareTo(o2.getDescr()));
177
178        _femaleSocketType.removeAllItems();
179        for (FemaleSocketManager.SocketType socketType : list) {
180            _femaleSocketType.addItem(socketType);
181            if ("DefaultFemaleDigitalActionSocket".equals(socketType.getName())) {
182                _femaleSocketType.setSelectedItem(socketType);
183            }
184        }
185
186        JPanel p;
187        p = new JPanel();
188        p.setLayout(new FlowLayout());
189        p.setLayout(new java.awt.GridBagLayout());
190        java.awt.GridBagConstraints c = new java.awt.GridBagConstraints();
191        c.gridwidth = 1;
192        c.gridheight = 1;
193        c.gridx = 0;
194        c.gridy = 0;
195        c.anchor = java.awt.GridBagConstraints.EAST;
196        p.add(_sysNameLabel, c);
197        _sysNameLabel.setLabelFor(_systemName);
198        c.gridy = 1;
199        p.add(_userNameLabel, c);
200        _userNameLabel.setLabelFor(_addUserName);
201        c.gridy = 2;
202        p.add(new JLabel(Bundle.getMessage("LogixNG_ModuleSocketType")), c);
203        c.gridx = 1;
204        c.gridy = 0;
205        c.anchor = java.awt.GridBagConstraints.WEST;
206        c.weightx = 1.0;
207        c.fill = java.awt.GridBagConstraints.HORIZONTAL;  // text field will expand
208        p.add(_systemName, c);
209        c.gridy = 1;
210        p.add(_addUserName, c);
211        c.gridy = 2;
212        c.gridwidth = 2;
213        p.add(_femaleSocketType, c);
214        c.gridx = 2;
215        c.gridy = 1;
216        c.anchor = java.awt.GridBagConstraints.WEST;
217        c.weightx = 1.0;
218        c.fill = java.awt.GridBagConstraints.HORIZONTAL;  // text field will expand
219        c.gridy = 0;
220        p.add(_autoSystemName, c);
221        _addUserName.setToolTipText(Bundle.getMessage("LogixNGUserNameHint"));    // NOI18N
222        _systemName.setToolTipText(Bundle.getMessage("LogixNGSystemNameHint"));   // NOI18N
223        contentPane.add(p);
224        // set up message
225        JPanel panel3 = new JPanel();
226        panel3.setLayout(new BoxLayout(panel3, BoxLayout.Y_AXIS));
227        JPanel panel31 = new JPanel();
228        panel31.setLayout(new FlowLayout());
229        JLabel message1 = new JLabel(Bundle.getMessage(startMessageId + "LogixNGModuleMessage1"));  // NOI18N
230        panel31.add(message1);
231        JPanel panel32 = new JPanel();
232        JLabel message2 = new JLabel(Bundle.getMessage(startMessageId + "LogixNGModuleMessage2"));  // NOI18N
233        panel32.add(message2);
234        panel3.add(panel31);
235        panel3.add(panel32);
236        contentPane.add(panel3);
237
238        // set up create and cancel buttons
239        JPanel panel5 = new JPanel();
240        panel5.setLayout(new FlowLayout());
241        // Cancel
242        JButton cancel = new JButton(Bundle.getMessage("ButtonCancel"));    // NOI18N
243        panel5.add(cancel);
244        cancel.addActionListener(this::cancelAddPressed);
245        cancel.setToolTipText(Bundle.getMessage("CancelLogixNGModuleButtonHint"));      // NOI18N
246
247        addLogixNGFrame.addWindowListener(new java.awt.event.WindowAdapter() {
248            @Override
249            public void windowClosing(java.awt.event.WindowEvent e) {
250                cancelAddPressed(null);
251            }
252        });
253        contentPane.add(panel5);
254
255        _autoSystemName.addItemListener((ItemEvent e) -> {
256            autoSystemName();
257        });
258        return panel5;
259    }
260
261    @Override
262    protected void getListenerRefsIncludingChildren(Module module, java.util.List<String> list) {
263        module.getListenerRefsIncludingChildren(list);
264    }
265
266    @Override
267    protected boolean hasChildren(Module module) {
268        return module.getRootSocket().isConnected();
269    }
270
271    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogixNGModuleTableAction.class);
272
273}