001package jmri.jmrit.beantable;
002
003import java.awt.BorderLayout;
004import java.awt.Color;
005import java.awt.FlowLayout;
006import java.awt.event.ActionEvent;
007import java.util.ArrayList;
008import java.util.HashSet;
009import java.util.List;
010import java.util.ResourceBundle;
011import java.util.Set;
012import javax.annotation.Nonnull;
013import javax.swing.*;
014import javax.swing.table.TableColumn;
015import javax.swing.table.TableColumnModel;
016
017import jmri.*;
018import jmri.NamedBean.DisplayOptions;
019import jmri.jmrit.display.EditorManager;
020import jmri.jmrit.display.layoutEditor.LayoutEditor;
021import jmri.util.JmriJFrame;
022import jmri.swing.NamedBeanComboBox;
023import jmri.util.swing.JComboBoxUtil;
024import jmri.util.swing.JmriJOptionPane;
025
026/**
027 * Swing action to create and register a SectionTable GUI.
028 * <p>
029 * This file is part of JMRI.
030 * <p>
031 * JMRI is open source software; you can redistribute it and/or modify it under
032 * the terms of version 2 of the GNU General Public License as published by the
033 * Free Software Foundation. See the "COPYING" file for a copy of this license.
034 * <p>
035 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
036 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
037 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
038 *
039 * @author Dave Duchamp Copyright (C) 2008, 2011
040 * @author GT 2009
041 */
042public class SectionTableAction extends AbstractTableAction<Section> {
043
044    /**
045     * Create an action with a specific title.
046     * <p>
047     * Note that the argument is the Action title, not the title of the
048     * resulting frame. Perhaps this should be changed?
049     *
050     * @param actionName title of the action
051     */
052    public SectionTableAction(String actionName) {
053        super(actionName);
054        // set manager - no need to use InstanceManager here
055        sectionManager = InstanceManager.getNullableDefault(SectionManager.class);
056        // disable ourself if there is no Section manager available
057        if (sectionManager == null) {
058            super.setEnabled(false);
059        }
060    }
061
062    public SectionTableAction() {
063        this(Bundle.getMessage("TitleSectionTable"));
064    }
065
066    static final ResourceBundle rbx = ResourceBundle.getBundle("jmri.jmrit.beantable.SectionTransitTableBundle");
067
068    /**
069     * Create the JTable DataModel, along with the changes for the specific case
070     * of Section objects.
071     */
072    @Override
073    protected void createModel() {
074        m = new BeanTableDataModel<Section>() {
075
076            static public final int BEGINBLOCKCOL = NUMCOLUMN;
077            static public final int ENDBLOCKCOL = BEGINBLOCKCOL + 1;
078            static public final int EDITCOL = ENDBLOCKCOL + 1;
079
080            @Override
081            public String getValue(String name) {
082                return "";
083            }
084
085            @Override
086            public Manager<Section> getManager() {
087                return InstanceManager.getDefault(SectionManager.class);
088            }
089
090            @Override
091            public Section getBySystemName(@Nonnull String name) {
092                return InstanceManager.getDefault(SectionManager.class).getBySystemName(name);
093            }
094
095            @Override
096            public Section getByUserName(@Nonnull String name) {
097                return InstanceManager.getDefault(SectionManager.class).getByUserName(name);
098            }
099
100            @Override
101            protected String getMasterClassName() {
102                return getClassName();
103            }
104
105            @Override
106            public void clickOn(Section t) {
107            }
108
109            @Override
110            public int getColumnCount() {
111                return EDITCOL + 1;
112            }
113
114            @Override
115            public Object getValueAt(int row, int col) {
116                // some error checking
117                if (row >= sysNameList.size()) {
118                    log.debug("row is greater than name list");
119                    return "";
120                }
121                switch (col) {
122                    case BEGINBLOCKCOL:
123                    {
124                        Section z = getBySystemName(sysNameList.get(row));
125                        if (z != null) {
126                            return z.getBeginBlockName();
127                        }
128                        return "  ";
129                    }
130                    case ENDBLOCKCOL:
131                    {
132                        Section z = getBySystemName(sysNameList.get(row));
133                        if (z != null) {
134                            return z.getEndBlockName();
135                        }
136                        return "  ";
137                    }
138                    case VALUECOL:
139                        {
140                            Section z = getBySystemName(sysNameList.get(row));
141                            if (z == null) {
142                                return "";
143                            } else {
144                                switch (z.getState()) {
145                                    case Section.FREE:
146                                        return (rbx.getString("SectionFree"));
147                                    case Section.FORWARD:
148                                        return (rbx.getString("SectionForward"));
149                                    case Section.REVERSE:
150                                        return (rbx.getString("SectionReverse"));
151                                    default:
152                                        break;
153                                }
154                            }       break;
155                        }
156                    case EDITCOL:
157                        return Bundle.getMessage("ButtonEdit");
158                    default:
159                        return super.getValueAt(row, col);
160                }
161                return null;
162            }
163
164            @Override
165            public void setValueAt(Object value, int row, int col) {
166                if ((col == BEGINBLOCKCOL) || (col == ENDBLOCKCOL)) {
167                } else if (col == EDITCOL) {
168                    SwingUtilities.invokeLater(() -> {
169                        editPressed(((Section) getValueAt(row, SYSNAMECOL)).getSystemName());
170                    });
171                } else if (col == DELETECOL) {
172                    deleteSectionPressed(sysNameList.get(row));
173                } else {
174                    super.setValueAt(value, row, col);
175                }
176            }
177
178            @Override
179            public String getColumnName(int col) {
180                if (col == BEGINBLOCKCOL) {
181                    return (rbx.getString("SectionFirstBlock"));
182                }
183                if (col == ENDBLOCKCOL) {
184                    return (rbx.getString("SectionLastBlock"));
185                }
186                if (col == EDITCOL) {
187                    return "";   // no namne on Edit column
188                }
189                return super.getColumnName(col);
190            }
191
192            @Override
193            public Class<?> getColumnClass(int col) {
194                switch (col) {
195                    case VALUECOL: // not a button
196                    case BEGINBLOCKCOL: // not a button
197                    case ENDBLOCKCOL: // not a button
198                        return String.class;
199                    case EDITCOL:
200                        return JButton.class;
201                    default:
202                        return super.getColumnClass(col);
203                }
204            }
205
206            @Override
207            public boolean isCellEditable(int row, int col) {
208                switch (col) {
209                    case BEGINBLOCKCOL:
210                    case ENDBLOCKCOL:
211                    case VALUECOL:
212                        return false;
213                    case EDITCOL:
214                        return true;
215                    default:
216                        return super.isCellEditable(row, col);
217                }
218            }
219
220            @Override
221            public int getPreferredWidth(int col) {
222                // override default value for SystemName and UserName columns
223                switch (col) {
224                    case SYSNAMECOL:
225                        return new JTextField(9).getPreferredSize().width;
226                    case USERNAMECOL:
227                        return new JTextField(17).getPreferredSize().width;
228                    case VALUECOL:
229                    case EDITCOL:
230                        return new JTextField(6).getPreferredSize().width;
231                    case BEGINBLOCKCOL:
232                    case ENDBLOCKCOL:
233                        return new JTextField(15).getPreferredSize().width;
234                    default:
235                        return super.getPreferredWidth(col);
236                }
237            }
238
239            @Override
240            public void configValueColumn(JTable table) {
241                // value column isn't button, so config is null
242            }
243
244            @Override
245            protected boolean matchPropertyName(java.beans.PropertyChangeEvent e) {
246                return true;
247                // return (e.getPropertyName().indexOf("alue")>=0);
248            }
249        };
250    }
251
252    @Override
253    protected void setTitle() {
254        f.setTitle(Bundle.getMessage("TitleSectionTable"));
255    }
256
257    @Override
258    protected String helpTarget() {
259        return "package.jmri.jmrit.beantable.SectionTable";
260    }
261
262    // instance variables
263    ArrayList<Block> blockList = new ArrayList<>();
264    private BlockTableModel blockTableModel = null;
265    EntryPointTableModel entryPointTableModel = null;
266    SectionManager sectionManager = null;
267    BlockManager blockManager = InstanceManager.getDefault(BlockManager.class);
268    boolean editMode = false;
269    Section curSection = null;
270    boolean addCreateActive = true;
271    ArrayList<LayoutEditor> lePanelList = null;
272    LayoutEditor curLayoutEditor = null;
273    Block beginBlock = null;
274    Block endBlock = null;
275    Sensor fSensor = null;
276    Sensor rSensor = null;
277    Sensor fStopSensor = null;
278    Sensor rStopSensor = null;
279    ArrayList<EntryPoint> entryPointList = new ArrayList<>();
280    boolean manualEntryPoints = true;
281
282    // add/create variables
283    JmriJFrame addFrame = null;
284    JTextField sysName = new JTextField(15);
285    JLabel sysNameFixed = new JLabel("");
286    JTextField userName = new JTextField(17);
287    JLabel sysNameLabel = new JLabel(Bundle.getMessage("LabelSystemName"));
288    JLabel userNameLabel = new JLabel(Bundle.getMessage("LabelUserName"));
289    JCheckBox _autoSystemName = new JCheckBox(Bundle.getMessage("LabelAutoSysName"));
290    UserPreferencesManager pref;
291    JButton create = null;
292    JButton update = null;
293    JButton addBlock = null;
294    JButton deleteBlocks = null;
295    JComboBox<String> layoutEditorBox = new JComboBox<>();
296    NamedBeanComboBox<Block> blockBox;
297    NamedBeanComboBox<Sensor> forwardSensorBox;
298    NamedBeanComboBox<Sensor> reverseSensorBox;
299    NamedBeanComboBox<Sensor> forwardStopSensorBox;
300    NamedBeanComboBox<Sensor> reverseStopSensorBox;
301    JRadioButton manually = new JRadioButton(rbx.getString("SetManually"), true);
302    JRadioButton automatic = new JRadioButton(rbx.getString("UseConnectivity"), false);
303    ButtonGroup entryPointOptions = null;
304    String systemNameAuto = this.getClass().getName() + ".AutoSystemName";
305    JLabel generationStateLabel = new JLabel();
306
307    /**
308     * Responds to the Add...button and the Edit buttons in the Section Table
309     * @param e event which has triggered action
310     */
311    @Override
312    protected void addPressed(ActionEvent e) {
313        editMode = false;
314        if ((blockManager.getNamedBeanSet().size()) > 0) {
315            addEditPressed();
316        } else {
317            JmriJOptionPane.showMessageDialog(null, rbx
318                    .getString("Message1"), Bundle.getMessage("ErrorTitle"),
319                    JmriJOptionPane.ERROR_MESSAGE);
320        }
321    }
322
323    void editPressed(String sName) {
324        curSection = sectionManager.getBySystemName(sName);
325        if (curSection == null) {
326            // no section - should never happen, but protects against a $%^#@ exception
327            return;
328        }
329        sysNameFixed.setText(sName);
330        editMode = true;
331        addEditPressed();
332    }
333
334    void addEditPressed() {
335        pref = InstanceManager.getDefault(UserPreferencesManager.class);
336        if (addFrame == null) {
337            addFrame = new JmriJFrame(Bundle.getMessage("TitleAddSection"));
338            addFrame.addHelpMenu("package.jmri.jmrit.beantable.SectionAddEdit", true);
339            addFrame.getContentPane().setLayout(new BoxLayout(addFrame.getContentPane(), BoxLayout.Y_AXIS));
340            // add system name
341            JPanel p = new JPanel();
342            p.setLayout(new FlowLayout());
343            p.add(sysNameLabel);
344            sysNameLabel.setLabelFor(sysName);
345            p.add(sysNameFixed);
346            p.add(sysName);
347            p.add(_autoSystemName);
348            _autoSystemName.addActionListener((ActionEvent e) -> {
349                autoSystemName();
350            });
351            if (pref.getSimplePreferenceState(systemNameAuto)) {
352                _autoSystemName.setSelected(true);
353            }
354            sysName.setToolTipText(rbx.getString("SectionSystemNameHint"));
355            addFrame.getContentPane().add(p);
356            // add user name
357            JPanel pu = new JPanel();
358            pu.setLayout(new FlowLayout());
359            pu.add(userNameLabel);
360            userNameLabel.setLabelFor(userName);
361            pu.add(userName);
362            userName.setToolTipText(rbx.getString("SectionUserNameHint"));
363            addFrame.getContentPane().add(pu);
364
365            JPanel pa = new JPanel();
366            pa.setLayout(new FlowLayout());
367            pa.add(generationStateLabel);
368            addFrame.getContentPane().add(pa);
369            addFrame.getContentPane().add(new JSeparator());
370            JPanel p1 = new JPanel();
371            p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
372            JPanel p11 = new JPanel();
373            p11.setLayout(new FlowLayout());
374            p11.add(new JLabel(rbx.getString("BlockTableMessage")));
375            p1.add(p11);
376            JPanel p12 = new JPanel();
377            // initialize table of Blocks
378            blockTableModel = new BlockTableModel();
379            JTable blockTable = new JTable(blockTableModel);
380            blockTable.setRowSelectionAllowed(false);
381            blockTable.setPreferredScrollableViewportSize(new java.awt.Dimension(350, 100));
382            TableColumnModel blockColumnModel = blockTable.getColumnModel();
383            TableColumn sNameColumn = blockColumnModel.getColumn(BlockTableModel.SNAME_COLUMN);
384            sNameColumn.setResizable(true);
385            sNameColumn.setMinWidth(90);
386            sNameColumn.setMaxWidth(130);
387            TableColumn uNameColumn = blockColumnModel.getColumn(BlockTableModel.UNAME_COLUMN);
388            uNameColumn.setResizable(true);
389            uNameColumn.setMinWidth(210);
390            uNameColumn.setMaxWidth(260);
391            JScrollPane blockTableScrollPane = new JScrollPane(blockTable);
392            p12.add(blockTableScrollPane, BorderLayout.CENTER);
393            p1.add(p12);
394            JPanel p13 = new JPanel();
395            p13.setLayout(new FlowLayout());
396            p13.add(deleteBlocks = new JButton(rbx.getString("DeleteAllBlocksButton")));
397            deleteBlocks.addActionListener(this::deleteBlocksPressed);
398            deleteBlocks.setToolTipText(rbx.getString("DeleteAllBlocksButtonHint"));
399            p13.add(new JLabel("     "));
400            initializeBlockCombo();
401            p13.add(blockBox);
402            blockBox.setToolTipText(rbx.getString("BlockBoxHint"));
403            p13.add(addBlock = new JButton(rbx.getString("AddBlockButton")));
404            addBlock.addActionListener(this::addBlockPressed);
405            addBlock.setToolTipText(rbx.getString("AddBlockButtonHint"));
406            p1.add(p13);
407            addFrame.getContentPane().add(p1);
408            // add hint for order of blocks irt direction of travel
409            JPanel p34 = new JPanel();
410            p34.setLayout(new FlowLayout());
411            JLabel direction = new JLabel(rbx.getString("DirectionNote")); // placed below first table
412            direction.setFont(direction.getFont().deriveFont(0.9f * blockBox.getFont().getSize())); // a bit smaller
413            direction.setForeground(Color.gray);
414            p34.add(direction);
415            addFrame.getContentPane().add(p34);
416            addFrame.getContentPane().add(new JSeparator());
417            JPanel p31 = new JPanel();
418            p31.setLayout(new FlowLayout());
419            p31.add(new JLabel(rbx.getString("EntryPointTable")));
420            addFrame.getContentPane().add(p31);
421
422            JPanel p32 = new JPanel();
423            p32.setLayout(new FlowLayout());
424            entryPointOptions = new ButtonGroup();
425            p32.add(manually);
426            entryPointOptions.add(manually);
427            manually.addActionListener((ActionEvent e) -> {
428                manualEntryPoints = true;
429            });
430            manually.setToolTipText(rbx.getString("SetManuallyHint"));
431            p32.add(new JLabel("   "));
432            p32.add(automatic);
433            entryPointOptions.add(automatic);
434            automatic.addActionListener((ActionEvent e) -> {
435                manualEntryPoints = false;
436            });
437            automatic.setToolTipText(rbx.getString("SetAutomaticHint"));
438            p32.add(layoutEditorBox);
439            layoutEditorBox.setToolTipText(rbx.getString("LayoutEditorBoxHint"));
440            layoutEditorBox.addActionListener((ActionEvent e) -> {
441                layoutEditorSelectionChanged();
442            });
443            // djd debugging - temporarily hide these items until the automatic setting of entry point direction is ready
444            //   addFrame.getContentPane().add(p32);
445            // end djd debugging
446
447            JPanel p33 = new JPanel();
448            // initialize table of entry points
449            entryPointTableModel = new EntryPointTableModel();
450            JTable entryPointTable = new JTable(entryPointTableModel);
451            entryPointTable.setRowSelectionAllowed(false);
452            entryPointTable.setPreferredScrollableViewportSize(new java.awt.Dimension(550, 100));
453            TableColumnModel entryPointColumnModel = entryPointTable.getColumnModel();
454            // From-Block
455            TableColumn fromBlockColumn = entryPointColumnModel.getColumn(EntryPointTableModel.BLOCK_COLUMN);
456            fromBlockColumn.setResizable(true);
457            fromBlockColumn.setMinWidth(250);
458            fromBlockColumn.setMaxWidth(310);
459            // To-Block
460            TableColumn toBlockColumn = entryPointColumnModel.getColumn(EntryPointTableModel.TO_BLOCK_COLUMN);
461            toBlockColumn.setResizable(true);
462            toBlockColumn.setMinWidth(150);
463            toBlockColumn.setMaxWidth(210);
464
465            JComboBox<String> directionCombo = new JComboBox<>();
466            directionCombo.addItem(rbx.getString("SectionForward"));
467            directionCombo.addItem(rbx.getString("SectionReverse"));
468            directionCombo.addItem(Bundle.getMessage("BeanStateUnknown"));
469            TableColumn directionColumn = entryPointColumnModel.getColumn(EntryPointTableModel.DIRECTION_COLUMN);
470            directionColumn.setCellEditor(new DefaultCellEditor(directionCombo));
471            entryPointTable.setRowHeight(directionCombo.getPreferredSize().height);
472            directionColumn.setPreferredWidth(directionCombo.getPreferredSize().width);
473            directionColumn.setResizable(false);
474            JScrollPane entryPointTableScrollPane = new JScrollPane(entryPointTable);
475            p33.add(entryPointTableScrollPane, BorderLayout.CENTER);
476            addFrame.getContentPane().add(p33);
477            p33.setVisible(true);
478            // hint p34 is displayed 1 table up
479            addFrame.getContentPane().add(new JSeparator());
480            // set up pane for direction sensors
481            forwardSensorBox = new NamedBeanComboBox<>(InstanceManager.sensorManagerInstance());
482            forwardSensorBox.setAllowNull(true);
483            forwardSensorBox.setSelectedItem(null);
484            reverseSensorBox = new NamedBeanComboBox<>(InstanceManager.sensorManagerInstance());
485            reverseSensorBox.setAllowNull(true);
486            reverseSensorBox.setSelectedItem(null);
487            JComboBoxUtil.setupComboBoxMaxRows(forwardSensorBox);
488            JComboBoxUtil.setupComboBoxMaxRows(reverseSensorBox);
489            JPanel p20 = new JPanel();
490            p20.setLayout(new FlowLayout());
491            p20.add(new JLabel(rbx.getString("DirectionSensorLabel")));
492            addFrame.getContentPane().add(p20);
493            JPanel p21 = new JPanel();
494            p21.setLayout(new FlowLayout());
495            p21.add(new JLabel(rbx.getString("ForwardSensor")));
496            p21.add(forwardSensorBox);
497            forwardSensorBox.setToolTipText(rbx.getString("ForwardSensorHint"));
498            p21.add(new JLabel("     "));
499            p21.add(new JLabel(rbx.getString("ReverseSensor")));
500            p21.add(reverseSensorBox);
501            reverseSensorBox.setToolTipText(rbx.getString("ReverseSensorHint"));
502            addFrame.getContentPane().add(p21);
503            addFrame.getContentPane().add(new JSeparator());
504            // set up for stopping sensors
505            forwardStopSensorBox = new NamedBeanComboBox<>(InstanceManager.sensorManagerInstance());
506            forwardStopSensorBox.setAllowNull(true);
507            forwardStopSensorBox.setSelectedItem(null);
508            reverseStopSensorBox = new NamedBeanComboBox<>(InstanceManager.sensorManagerInstance());
509            reverseStopSensorBox.setAllowNull(true);
510            reverseStopSensorBox.setSelectedItem(null);
511            JComboBoxUtil.setupComboBoxMaxRows(forwardStopSensorBox);
512            JComboBoxUtil.setupComboBoxMaxRows(reverseStopSensorBox);
513            JPanel p40 = new JPanel();
514            p40.setLayout(new FlowLayout());
515            p40.add(new JLabel(rbx.getString("StoppingSensorLabel")));
516            addFrame.getContentPane().add(p40);
517            JPanel p41 = new JPanel();
518            p41.setLayout(new FlowLayout());
519            p41.add(new JLabel(rbx.getString("ForwardStopSensor")));
520            p41.add(forwardStopSensorBox);
521            forwardStopSensorBox.setToolTipText(rbx.getString("ForwardStopSensorHint"));
522            p41.add(new JLabel("     "));
523            p41.add(new JLabel(rbx.getString("ReverseStopSensor")));
524            p41.add(reverseStopSensorBox);
525            reverseStopSensorBox.setToolTipText(rbx.getString("ReverseStopSensorHint"));
526            addFrame.getContentPane().add(p41);
527            addFrame.getContentPane().add(new JSeparator());
528            // set up bottom row of buttons
529            JButton cancel = new JButton(Bundle.getMessage("ButtonCancel"));
530            JPanel pb = new JPanel();
531            pb.setLayout(new FlowLayout());
532            pb.add(cancel);
533            cancel.addActionListener(this::cancelPressed);
534            cancel.setToolTipText(rbx.getString("CancelButtonHint"));
535            pb.add(create = new JButton(Bundle.getMessage("ButtonCreate")));
536            create.addActionListener(this::createPressed);
537            create.setToolTipText(rbx.getString("SectionCreateButtonHint"));
538            pb.add(update = new JButton(Bundle.getMessage("ButtonUpdate")));
539            update.addActionListener(this::updatePressed);
540            update.setToolTipText(rbx.getString("SectionUpdateButtonHint"));
541            addFrame.getContentPane().add(pb);
542        }
543        if (editMode) {
544            // setup for edit window
545            _autoSystemName.setVisible(false);
546            sysNameLabel.setEnabled(true);
547            create.setVisible(false);
548            update.setVisible(true);
549            sysName.setVisible(true);
550            sysName.setVisible(false);
551            sysNameFixed.setVisible(true);
552            initializeEditInformation();
553            addFrame.getRootPane().setDefaultButton(update);
554            addFrame.setTitle(Bundle.getMessage("TitleEditSection"));
555        } else {
556            // setup for create window
557            _autoSystemName.setVisible(true);
558            create.setVisible(true);
559            update.setVisible(false);
560            sysName.setVisible(true);
561            sysNameFixed.setVisible(false);
562            autoSystemName();
563            clearForCreate();
564            addFrame.getRootPane().setDefaultButton(create);
565            addFrame.setTitle(Bundle.getMessage("TitleAddSection"));
566        }
567        // initialize layout editor panels
568        if (initializeLayoutEditorCombo(layoutEditorBox)) {
569            manually.setVisible(true);
570            automatic.setVisible(true);
571            layoutEditorBox.setVisible(true);
572        } else {
573            manually.setVisible(false);
574            automatic.setVisible(false);
575            layoutEditorBox.setVisible(false);
576        }
577        // initialize block combo - first time
578        initializeBlockCombo();
579        addFrame.setEscapeKeyClosesWindow(true);
580        addFrame.pack();
581        addFrame.setVisible(true);
582    }
583
584    private void initializeEditInformation() {
585        userName.setText(curSection.getUserName());
586        switch (curSection.getSectionType()) {
587            case SIGNALMASTLOGIC:
588                generationStateLabel.setText(rbx.getString("SectionTypeSMLLabel"));
589                break;
590            case DYNAMICADHOC:
591                generationStateLabel.setText(rbx.getString("SectionTypeDynLabel"));
592                break;
593            case USERDEFINED:
594            default:
595                generationStateLabel.setText("");
596                break;
597        }
598
599        deleteBlocksPressed(null);
600        int i = 0;
601        while (curSection.getBlockBySequenceNumber(i) != null) {
602            Block b = curSection.getBlockBySequenceNumber(i);
603            blockList.add(b);
604            i++;
605            if (blockList.size() == 1) {
606                beginBlock = b;
607            }
608            endBlock = b;
609        }
610        forwardSensorBox.setSelectedItem(curSection.getForwardBlockingSensor());
611        reverseSensorBox.setSelectedItem(curSection.getReverseBlockingSensor());
612        forwardStopSensorBox.setSelectedItem(curSection.getForwardStoppingSensor());
613        reverseStopSensorBox.setSelectedItem(curSection.getReverseStoppingSensor());
614        List<EntryPoint> list = curSection.getForwardEntryPointList();
615        if (list.size() > 0) {
616            for (int j = 0; j < list.size(); j++) {
617                entryPointList.add(list.get(j));
618            }
619        }
620        list = curSection.getReverseEntryPointList();
621        if (list.size() > 0) {
622            for (int j = 0; j < list.size(); j++) {
623                entryPointList.add(list.get(j));
624            }
625        }
626    }
627
628    private void clearForCreate() {
629        deleteBlocksPressed(null);
630        curSection = null;
631        forwardSensorBox.setSelectedItem(null);
632        reverseSensorBox.setSelectedItem(null);
633        forwardStopSensorBox.setSelectedItem(null);
634        reverseStopSensorBox.setSelectedItem(null);
635        generationStateLabel.setText("");
636    }
637
638    void createPressed(ActionEvent e) {
639        if (!checkSectionInformation()) {
640            return;
641        }
642        String uName = userName.getText();
643        if (uName.isEmpty()) {
644            uName = null;
645        }
646
647        // attempt to create the new Section
648        String sName = sysName.getText();
649        try {
650            if (_autoSystemName.isSelected()) {
651                curSection = sectionManager.createNewSection(uName);
652            } else {
653                curSection = sectionManager.createNewSection(sName, uName);
654            }
655        } catch (IllegalArgumentException ex) {
656            // user input no good
657            if (_autoSystemName.isSelected()) {
658                handleCreateException(uName, ex);
659            } else {
660                handleCreateException(sName, ex);
661            }
662            return; // without creating any
663        }
664        sysName.setText(curSection.getSystemName());
665        setSectionInformation();
666        addFrame.setVisible(false);
667        blockTableModel.dispose();
668        addFrame.dispose();
669        addFrame = null;
670        pref.setSimplePreferenceState(systemNameAuto, _autoSystemName.isSelected());
671    }
672
673    void handleCreateException(String sysName, Exception ex) {
674        JmriJOptionPane.showMessageDialog(addFrame,
675                Bundle.getMessage("ErrorSectionAddFailed", sysName) + "\n" + Bundle.getMessage("ErrorAddFailedCheck")
676                + "\n" + ex.getLocalizedMessage(),
677                Bundle.getMessage("ErrorTitle"),
678                JmriJOptionPane.ERROR_MESSAGE);
679    }
680
681    void cancelPressed(ActionEvent e) {
682        addFrame.setVisible(false);
683        blockTableModel.dispose();
684        addFrame.dispose();
685        addFrame = null;
686    }
687
688    void updatePressed(ActionEvent e) {
689        if (!checkSectionInformation()) {
690            return;
691        }
692        // check if user name has been changed
693        String uName = userName.getText();
694        if (uName.isEmpty()) {
695            uName = null;
696        }
697        if ((uName != null) && (!uName.equals(curSection.getUserName()))) {
698            // check that new user name is unique
699            Section tSection = sectionManager.getByUserName(uName);
700            if (tSection != null) {
701                JmriJOptionPane.showMessageDialog(addFrame,
702                        rbx.getString("Message2"),
703                        Bundle.getMessage("ErrorTitle"),
704                        JmriJOptionPane.ERROR_MESSAGE);
705                return;
706            }
707        }
708        curSection.setUserName(uName);
709        if (setSectionInformation()) {
710            // successful update
711            addFrame.setVisible(false);
712            blockTableModel.dispose();
713            addFrame.dispose();
714            addFrame = null;
715        }
716    }
717
718    private boolean checkSectionInformation() {
719        if (blockList.isEmpty()) {
720            JmriJOptionPane.showMessageDialog(addFrame, rbx
721                    .getString("Message6"), Bundle.getMessage("ErrorTitle"),
722                    JmriJOptionPane.ERROR_MESSAGE);
723            return false;
724        }
725        // check entry points
726        boolean unknownPresent = false;
727        for (int i = 0; i < entryPointList.size(); i++) {
728            if (entryPointList.get(i).isUnknownType()) {
729                unknownPresent = true;
730            }
731        }
732        if (unknownPresent) {
733            JmriJOptionPane.showMessageDialog(addFrame, rbx
734                    .getString("Message10"), Bundle.getMessage("ErrorTitle"),
735                    JmriJOptionPane.ERROR_MESSAGE);
736            return false;
737        }
738
739        // check direction sensors
740        fSensor = forwardSensorBox.getSelectedItem();
741        rSensor = reverseSensorBox.getSelectedItem();
742        if ((fSensor != null) && (fSensor.equals(rSensor))) {
743            JmriJOptionPane.showMessageDialog(addFrame, rbx
744                    .getString("Message9"), Bundle.getMessage("ErrorTitle"),
745                    JmriJOptionPane.ERROR_MESSAGE);
746            return false;
747        }
748
749        // check stopping sensors
750        fStopSensor = forwardStopSensorBox.getSelectedItem();
751        rStopSensor = reverseStopSensorBox.getSelectedItem();
752
753        return true;
754    }
755
756    /**
757     * Copy the user input to the Section.
758     *
759     * @return true if completed
760     */
761    private boolean setSectionInformation() {
762        curSection.removeAllBlocksFromSection();
763        for (int i = 0; i < blockList.size(); i++) {
764            if (!curSection.addBlock(blockList.get(i))) {
765                JmriJOptionPane.showMessageDialog(addFrame, rbx
766                        .getString("Message4"), Bundle.getMessage("ErrorTitle"),
767                        JmriJOptionPane.ERROR_MESSAGE);
768            }
769        }
770        curSection.setForwardBlockingSensorName(forwardSensorBox.getSelectedItemDisplayName());
771        curSection.setReverseBlockingSensorName(reverseSensorBox.getSelectedItemDisplayName());
772        curSection.setForwardStoppingSensorName(forwardStopSensorBox.getSelectedItemDisplayName());
773        curSection.setReverseStoppingSensorName(reverseStopSensorBox.getSelectedItemDisplayName());
774        for (int j = 0; j < entryPointList.size(); j++) {
775            EntryPoint ep = entryPointList.get(j);
776            if (ep.isForwardType()) {
777                curSection.addToForwardList(ep);
778            } else if (ep.isReverseType()) {
779                curSection.addToReverseList(ep);
780            }
781        }
782        return true;
783    }
784
785    void deleteBlocksPressed(ActionEvent e) {
786        for (int j = blockList.size(); j > 0; j--) {
787            blockList.remove(j - 1);
788        }
789        beginBlock = null;
790        endBlock = null;
791        initializeBlockCombo();
792        initializeEntryPoints();
793        blockTableModel.fireTableDataChanged();
794    }
795
796    void addBlockPressed(ActionEvent e) {
797        if (blockBox.getItemCount() == 0) {
798            JmriJOptionPane.showMessageDialog(addFrame, rbx
799                    .getString("Message5"), Bundle.getMessage("ErrorTitle"),
800                    JmriJOptionPane.ERROR_MESSAGE);
801            return;
802        }
803        Block b = blockBox.getSelectedItem();
804        if (b != null) {
805            blockList.add(b);
806            if (blockList.size() == 1) {
807                beginBlock = b;
808            }
809            endBlock = b;
810            initializeBlockCombo();
811            initializeEntryPoints();
812            blockTableModel.fireTableDataChanged();
813        }
814    }
815
816    private boolean initializeLayoutEditorCombo(JComboBox<String> box) {
817        // get list of Layout Editor panels
818        lePanelList = new ArrayList<>(InstanceManager.getDefault(EditorManager.class).getAll(LayoutEditor.class));
819        if (lePanelList.isEmpty()) {
820            return false;
821        }
822        box.removeAllItems();
823        box.addItem("<" + Bundle.getMessage("None").toLowerCase() + ">");
824        for (int i = 0; i < lePanelList.size(); i++) {
825            box.addItem(lePanelList.get(i).getTitle());
826        }
827        box.setSelectedIndex(1);
828        return true;
829    }
830
831    private void layoutEditorSelectionChanged() {
832        int i = layoutEditorBox.getSelectedIndex();
833        if ((i <= 0) || (i > lePanelList.size())) {
834            curLayoutEditor = null;
835        } else {
836            curLayoutEditor = lePanelList.get(i - 1);
837        }
838    }
839
840    /**
841     * Build a combo box to select Blocks for this Section.
842     */
843    private void initializeBlockCombo() {
844        if (blockBox == null) {
845            blockBox = new NamedBeanComboBox<>(InstanceManager.getDefault(BlockManager.class));
846        }
847        if (blockList.isEmpty()) {
848            // No blocks selected, all blocks are eligible
849            blockBox.setExcludedItems(new HashSet<>());
850        } else {
851            // limit combo list to Blocks bonded to the currently selected Block that are not already in the Section
852            Set<Block> excludes = new HashSet<>(InstanceManager.getDefault(BlockManager.class).getNamedBeanSet());
853            for (Block b : blockManager.getNamedBeanSet()) {
854                if ((!inSection(b)) && connected(b, endBlock)) {
855                    excludes.remove(b);
856                }
857            }
858            blockBox.setExcludedItems(excludes);
859        }
860        if (blockBox.getItemCount()> 0) {
861            blockBox.setSelectedIndex(0);
862            JComboBoxUtil.setupComboBoxMaxRows(blockBox);
863        }
864    }
865
866    private boolean inSection(Block b) {
867        for (int i = 0; i < blockList.size(); i++) {
868            if (blockList.get(i) == b) {
869                return true;
870            }
871        }
872        return false;
873    }
874
875    private boolean connected(Block b1, Block b2) {
876        if ((b1 != null) && (b2 != null)) {
877            List<Path> paths = b1.getPaths();
878            for (int i = 0; i < paths.size(); i++) {
879                if (paths.get(i).getBlock() == b2) {
880                    return true;
881                }
882            }
883        }
884        return false;
885    }
886
887    private void initializeEntryPoints() {
888        // Copy old Entry Point List, if there are entries, and clear it.
889        ArrayList<EntryPoint> oldList = new ArrayList<>();
890        for (int i = 0; i < entryPointList.size(); i++) {
891            oldList.add(entryPointList.get(i));
892        }
893        entryPointList.clear();
894        if (blockList.size() > 0) {
895            // cycle through Blocks to find Entry Points
896            for (int i = 0; i < blockList.size(); i++) {
897                Block sb = blockList.get(i);
898                List<Path> paths = sb.getPaths();
899                for (int j = 0; j < paths.size(); j++) {
900                    Path p = paths.get(j);
901                    if (!inSection(p.getBlock())) {
902                        // this is path to an outside block, so need an Entry Point
903                        String pbDir = Path.decodeDirection(p.getFromBlockDirection());
904                        EntryPoint ep = getEntryPointInList(oldList, sb, p.getBlock(), pbDir);
905                        if (ep == null) {
906                            ep = new EntryPoint(sb, p.getBlock(), pbDir);
907                        }
908                        entryPointList.add(ep);
909                    }
910                }
911            }
912            // Set directions where possible
913            ArrayList<EntryPoint> epList = getBlockEntryPointsList(beginBlock);
914            if ((epList.size() == 2) && (blockList.size() == 1)) {
915                if (((epList.get(0)).isUnknownType())
916                        && ((epList.get(1)).isUnknownType())) {
917                    (epList.get(0)).setTypeForward();
918                    (epList.get(1)).setTypeReverse();
919                }
920            } else if (epList.size() == 1) {
921                (epList.get(0)).setTypeForward();
922            }
923            epList = getBlockEntryPointsList(endBlock);
924            if (epList.size() == 1) {
925                (epList.get(0)).setTypeReverse();
926            }
927        }
928// djd debugging
929// here add code to use Layout Editor connectivity if desired in the future
930/*  if (!manualEntryPoints) {
931         // use Layout Editor connectivity to set directions of Entry Points that have UNKNOWN direction
932         // check entry points for first Block
933         ArrayList<EntryPoint> tEPList = getSubEPListForBlock(beginBlock);
934         EntryPoint firstEP = null;
935         int numUnknown = 0;
936         for (int i = 0; i<tEPList.size(); i++) {
937         if (tEPList.get(i).getDirection==EntryPoint.UNKNOWN) numUnknown ++;
938         else if (firstEP==null) firstEP = tEPList.get(i);
939         }
940         if (numUnknown>0) {
941         // first Block has unknown entry point(s)
942         if ( (firstEP!=null) && (blockList.getSize()==1) ) {
943         firstEP = tEPList.get(0);
944         firstEP.setTypeForward();
945         }
946         else if (firstEP==null) {
947         // find connection from the second Block
948         }
949         }   */
950        entryPointTableModel.fireTableDataChanged();
951    }
952    /* private ArrayList<EntryPoint> getSubEPListForBlock(Block b) {
953     ArrayList<EntryPoint> tList = new ArrayList<EntryPoint>0;
954     for (int i=0; i<eplist.size(); i++) {
955     EntryPoint tep = epList.get(i);
956     if (epList.getBlock()==b) {
957     tList.add(tep);
958     }
959     }
960     return tList;
961     } */
962// end djd debugging
963
964    private EntryPoint getEntryPointInList(ArrayList<EntryPoint> list, Block b, Block pb, String pbDir) {
965        for (int i = 0; i < list.size(); i++) {
966            EntryPoint ep = list.get(i);
967            if ((ep.getBlock() == b) && (ep.getFromBlock() == pb)
968                    && (pbDir.equals(ep.getFromBlockDirection()))) {
969                return ep;
970            }
971        }
972        return null;
973    }
974
975    private ArrayList<EntryPoint> getBlockEntryPointsList(Block b) {
976        ArrayList<EntryPoint> list = new ArrayList<>();
977        for (int i = 0; i < entryPointList.size(); i++) {
978            EntryPoint ep = entryPointList.get(i);
979            if (ep.getBlock() == b) {
980                list.add(ep);
981            }
982        }
983        return list;
984    }
985
986    /**
987     * Special processing when user requests deletion of a Section.
988     * <p>
989     * Standard BeanTable processing results in misleading information.
990     */
991    private void deleteSectionPressed(String sName) {
992        final Section s = InstanceManager.getDefault(SectionManager.class).getBySystemName(sName);
993        if (s == null){
994            throw new IllegalArgumentException("Not deleting Section :" + sName + ": , Not Found.");
995        }
996        String fullName = s.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME);
997        ArrayList<Transit> affectedTransits = InstanceManager.getDefault(TransitManager.class).getListUsingSection(s);
998        final JDialog dialog = new JDialog();
999        String msg;
1000        dialog.setTitle(Bundle.getMessage("WarningTitle"));
1001        dialog.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);
1002        dialog.getContentPane().setLayout(new BoxLayout(dialog.getContentPane(), BoxLayout.Y_AXIS));
1003        JPanel p1 = new JPanel();
1004        p1.setLayout(new FlowLayout());
1005        if (affectedTransits.size() > 0) {
1006            // special warning if Section is used in Transits
1007            JLabel iLabel = new JLabel(java.text.MessageFormat.format(rbx.getString("Message17"), fullName));
1008            p1.add(iLabel);
1009            dialog.add(p1);
1010            for (int i = 0; i < affectedTransits.size(); i++) {
1011                Transit aTransit = affectedTransits.get(i);
1012                String tFullName = aTransit.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME);
1013                p1 = new JPanel();
1014                p1.setLayout(new FlowLayout());
1015                iLabel = new JLabel("   " + tFullName);
1016                p1.add(iLabel);
1017                dialog.add(p1);
1018            }
1019            dialog.add(p1);
1020            JPanel p3 = new JPanel();
1021            p3.setLayout(new FlowLayout());
1022            JLabel question = new JLabel(rbx.getString("Message18"));
1023            p3.add(question);
1024            dialog.add(p3);
1025            JPanel p4 = new JPanel();
1026            p4.setLayout(new FlowLayout());
1027            question = new JLabel(rbx.getString("Message18a"));
1028            p4.add(question);
1029            dialog.add(p4);
1030        } else {
1031            msg = java.text.MessageFormat.format(rbx.getString("Message19"), fullName);
1032            JLabel question = new JLabel(msg);
1033            p1.add(question);
1034            dialog.add(p1);
1035        }
1036        JPanel p6 = new JPanel();
1037        p6.setLayout(new FlowLayout());
1038        JLabel quest = new JLabel(rbx.getString("Message20"));
1039        p6.add(quest);
1040        dialog.add(p6);
1041        JButton yesButton = new JButton(rbx.getString("YesDeleteIt"));
1042        JButton noButton = new JButton(rbx.getString("NoCancel"));
1043        JPanel button = new JPanel();
1044        button.add(yesButton);
1045        button.add(noButton);
1046        dialog.add(button);
1047
1048        noButton.addActionListener((ActionEvent e) -> {
1049            // user cancelled delete request
1050            dialog.dispose();
1051        });
1052
1053        yesButton.addActionListener((ActionEvent e) -> {
1054            InstanceManager.getDefault(SectionManager.class).deregister(s);
1055            s.dispose();
1056            dialog.dispose();
1057        });
1058        dialog.pack();
1059        dialog.setModal(true);
1060        dialog.setVisible(true);
1061    }
1062
1063    /**
1064     * Insert 2 table specific menus.
1065     * Account for the Window and Help menus, which are already added to the menu bar
1066     * as part of the creation of the JFrame, by adding the menus 2 places earlier
1067     * unless the table is part of the ListedTableFrame, that adds the Help menu later on.
1068     *
1069     * @param f the JFrame of this table
1070     */
1071    @Override
1072    public void setMenuBar(BeanTableFrame<Section> f) {
1073        frame = f;
1074        JMenuBar menuBar = f.getJMenuBar();
1075        int pos = menuBar.getMenuCount() -1; // count the number of menus to insert the TableMenu before 'Window' and 'Help'
1076        int offset = 1;
1077        log.debug("setMenuBar number of menu items = {}", pos);
1078        for (int i = 0; i <= pos; i++) {
1079            if (menuBar.getComponent(i) instanceof JMenu) {
1080                if (((JMenu) menuBar.getComponent(i)).getText().equals(Bundle.getMessage("MenuHelp"))) {
1081                    offset = -1; // correct for use as part of ListedTableAction where the Help Menu is not yet present
1082                }
1083            }
1084        }
1085        JMenu toolsMenu = new JMenu(Bundle.getMessage("MenuTools"));
1086        menuBar.add(toolsMenu, pos + offset);
1087        JMenuItem validate = new JMenuItem(rbx.getString("ValidateAllSections") + "...");
1088        toolsMenu.add(validate);
1089        validate.addActionListener((ActionEvent e) -> {
1090            if (sectionManager != null) {
1091                int n = sectionManager.validateAllSections();
1092                if (n > 0) {
1093                    JmriJOptionPane.showMessageDialog(frame, java.text.MessageFormat.format(
1094                            rbx.getString("Message14"), new Object[]{"" + n}),
1095                            Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
1096                } else if (n == -2) {
1097                    JmriJOptionPane.showMessageDialog(frame, rbx.getString("Message16"),
1098                            Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
1099                } else if (n == 0) {
1100                    JmriJOptionPane.showMessageDialog(frame, rbx.getString("Message15"),
1101                            Bundle.getMessage("MessageTitle"), JmriJOptionPane.INFORMATION_MESSAGE);
1102                }
1103            }
1104        });
1105        JMenuItem setDirSensors = new JMenuItem(rbx.getString("SetupDirectionSensors") + "...");
1106        toolsMenu.add(setDirSensors);
1107        setDirSensors.addActionListener((ActionEvent e) -> {
1108            if (sectionManager != null) {
1109                int n = sectionManager.setupDirectionSensors();
1110                if (n > 0) {
1111                    JmriJOptionPane.showMessageDialog(frame, java.text.MessageFormat.format(
1112                            rbx.getString("Message27"), new Object[]{"" + n}),
1113                            Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
1114                } else if (n == -2) {
1115                    JmriJOptionPane.showMessageDialog(frame, rbx.getString("Message30"),
1116                            Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
1117                } else if (n == 0) {
1118                    JmriJOptionPane.showMessageDialog(frame, rbx.getString("Message28"),
1119                            Bundle.getMessage("MessageTitle"), JmriJOptionPane.INFORMATION_MESSAGE);
1120                }
1121            }
1122        });
1123        JMenuItem removeDirSensors = new JMenuItem(rbx.getString("RemoveDirectionSensors") + "...");
1124        toolsMenu.add(removeDirSensors);
1125        removeDirSensors.addActionListener((ActionEvent e) -> {
1126            if (sectionManager != null) {
1127                int n = sectionManager.removeDirectionSensorsFromSSL();
1128                if (n > 0) {
1129                    JmriJOptionPane.showMessageDialog(frame, java.text.MessageFormat.format(
1130                            rbx.getString("Message33"), new Object[]{"" + n}),
1131                            Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
1132                } else if (n == -2) {
1133                    JmriJOptionPane.showMessageDialog(frame, rbx.getString("Message32"),
1134                            Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
1135                } else if (n == 0) {
1136                    JmriJOptionPane.showMessageDialog(frame, rbx.getString("Message31"),
1137                            Bundle.getMessage("MessageTitle"), JmriJOptionPane.INFORMATION_MESSAGE);
1138                }
1139            }
1140        });
1141    }
1142
1143    JmriJFrame frame = null;
1144
1145    /**
1146     * Table model for Blocks in Create/Edit Section window
1147     */
1148    public class BlockTableModel extends javax.swing.table.AbstractTableModel implements
1149            java.beans.PropertyChangeListener {
1150
1151        public static final int SNAME_COLUMN = 0;
1152
1153        public static final int UNAME_COLUMN = 1;
1154
1155        public BlockTableModel() {
1156            super();
1157            init();
1158        }
1159
1160        final void init(){
1161            blockManager.addPropertyChangeListener(this);
1162        }
1163
1164        public void dispose(){
1165            blockManager.removePropertyChangeListener(this);
1166        }
1167
1168        @Override
1169        public void propertyChange(java.beans.PropertyChangeEvent e) {
1170            if (e.getPropertyName().equals("length")) {
1171                // a new NamedBean is available in the manager
1172                fireTableDataChanged();
1173            }
1174        }
1175
1176        @Override
1177        public Class<?> getColumnClass(int c) {
1178            return String.class;
1179        }
1180
1181        @Override
1182        public int getColumnCount() {
1183            return 2;
1184        }
1185
1186        @Override
1187        public int getRowCount() {
1188            return (blockList.size());
1189        }
1190
1191        @Override
1192        public boolean isCellEditable(int r, int c) {
1193            return (false);
1194        }
1195
1196        @Override
1197        public String getColumnName(int col) {
1198            switch (col) {
1199                case SNAME_COLUMN:
1200                    return Bundle.getMessage("LabelSystemName");
1201                case UNAME_COLUMN:
1202                    return Bundle.getMessage("LabelUserName");
1203                default:
1204                    return "";
1205            }
1206        }
1207
1208        public int getPreferredWidth(int col) {
1209            switch (col) {
1210                case SNAME_COLUMN:
1211                    return new JTextField(8).getPreferredSize().width;
1212                case UNAME_COLUMN:
1213                    return new JTextField(17).getPreferredSize().width;
1214                default:
1215                    return new JTextField(5).getPreferredSize().width;
1216            }
1217        }
1218
1219        @Override
1220        public Object getValueAt(int r, int c) {
1221            int rx = r;
1222            if (rx > blockList.size()) {
1223                return null;
1224            }
1225            switch (c) {
1226                case SNAME_COLUMN:
1227                    return blockList.get(rx).getSystemName();
1228                case UNAME_COLUMN: //
1229                    return blockList.get(rx).getUserName();
1230                default:
1231                    return Bundle.getMessage("BeanStateUnknown");
1232            }
1233        }
1234
1235        @Override
1236        public void setValueAt(Object value, int row, int col) {
1237        }
1238    }
1239
1240    private void autoSystemName() {
1241        if (_autoSystemName.isSelected()) {
1242            sysName.setEnabled(false);
1243            sysName.setText("");
1244            sysNameLabel.setEnabled(false);
1245        } else {
1246            sysName.setEnabled(true);
1247            sysNameLabel.setEnabled(true);
1248        }
1249    }
1250
1251    /**
1252     * Table model for Entry Points in Create/Edit Section window.
1253     */
1254    public class EntryPointTableModel extends javax.swing.table.AbstractTableModel {
1255
1256        public static final int BLOCK_COLUMN = 0;
1257
1258        public static final int TO_BLOCK_COLUMN = 1;
1259
1260        public static final int DIRECTION_COLUMN = 2;
1261
1262        public EntryPointTableModel() {
1263            super();
1264        }
1265
1266        @Override
1267        public Class<?> getColumnClass(int c) {
1268            if (c == DIRECTION_COLUMN) {
1269                return JComboBox.class;
1270            }
1271            return String.class;
1272        }
1273
1274        @Override
1275        public int getColumnCount() {
1276            return 3;
1277        }
1278
1279        @Override
1280        public int getRowCount() {
1281            return (entryPointList.size());
1282        }
1283
1284        @Override
1285        public boolean isCellEditable(int r, int c) {
1286            if (c == DIRECTION_COLUMN) {
1287                if (!manualEntryPoints) {
1288                    return (false);
1289                } else if (r < entryPointList.size()) {
1290                    return (!entryPointList.get(r).isFixed());
1291                }
1292                return (true);
1293            }
1294            return (false);
1295        }
1296
1297        @Override
1298        public String getColumnName(int col) {
1299            switch (col) {
1300                case BLOCK_COLUMN:
1301                    return rbx.getString("FromBlock");
1302
1303                case TO_BLOCK_COLUMN:
1304                    return rbx.getString("ToBlock");
1305
1306                case DIRECTION_COLUMN:
1307                    return rbx.getString("TravelDirection");
1308                default:
1309                    return "";
1310            }
1311        }
1312
1313        public int getPreferredWidth(int col) {
1314            if (col == BLOCK_COLUMN || col == TO_BLOCK_COLUMN)
1315            {
1316                return new JTextField(37).getPreferredSize().width;
1317            }
1318            if (col == DIRECTION_COLUMN) {
1319                return new JTextField(9).getPreferredSize().width;
1320            }
1321            return new JTextField(5).getPreferredSize().width;
1322        }
1323
1324        @Override
1325        public Object getValueAt(int r, int c) {
1326            int rx = r;
1327            if (rx >= entryPointList.size()) {
1328                return null;
1329            }
1330            switch (c) {
1331                case BLOCK_COLUMN:
1332                    return entryPointList.get(rx).getFromBlockName();
1333
1334                case TO_BLOCK_COLUMN:
1335                    return entryPointList.get(rx).getBlock().getDisplayName();
1336
1337                case DIRECTION_COLUMN: //
1338                    if (entryPointList.get(rx).isForwardType()) {
1339                        return rbx.getString("SectionForward");
1340                    } else if (entryPointList.get(rx).isReverseType()) {
1341                        return rbx.getString("SectionReverse");
1342                    } else {
1343                        return Bundle.getMessage("BeanStateUnknown");
1344                    }
1345                default:
1346                    // fall through
1347                    break;
1348            }
1349            return null;
1350        }
1351
1352        @Override
1353        public void setValueAt(Object value, int row, int col) {
1354            if (col == DIRECTION_COLUMN) {
1355                if (((String) value).equals(rbx.getString("SectionForward"))) {
1356                    entryPointList.get(row).setTypeForward();
1357                } else if (((String) value).equals(rbx.getString("SectionReverse"))) {
1358                    entryPointList.get(row).setTypeReverse();
1359                } else if (((String) value).equals(Bundle.getMessage("BeanStateUnknown"))) {
1360                    entryPointList.get(row).setTypeUnknown();
1361                }
1362            }
1363        }
1364
1365    }
1366
1367    @Override
1368    protected String getClassName() {
1369        return SectionTableAction.class.getName();
1370    }
1371
1372    @Override
1373    public String getClassDescription() {
1374        return Bundle.getMessage("TitleSectionTable");
1375    }
1376
1377    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SectionTableAction.class);
1378
1379}