001package jmri.jmrit.display.layoutEditor.LayoutEditorDialogs;
002
003import java.awt.Container;
004import java.awt.FlowLayout;
005import java.awt.event.ActionEvent;
006
007import javax.annotation.Nonnull;
008import javax.swing.*;
009
010import jmri.*;
011import jmri.NamedBean.DisplayOptions;
012import jmri.jmrit.display.layoutEditor.*;
013import jmri.swing.NamedBeanComboBox;
014import jmri.util.JmriJFrame;
015import jmri.util.swing.JmriJOptionPane;
016
017/**
018 * MVC Editor component for TrackSegment objects.
019 *
020 * @author Bob Jacobsen  Copyright (c) 2020
021 * 
022 */
023public class TrackSegmentEditor extends LayoutTrackEditor {
024
025    /**
026     * constructor method.
027     * @param layoutEditor main layout editor.
028     */
029    public TrackSegmentEditor(@Nonnull LayoutEditor layoutEditor) {
030        super(layoutEditor);
031    }
032
033    // ********** Members and methods from LayoutTrackEditors 
034    // ********** specific to TrackSegment
035
036    // variables for Edit Track Segment pane
037    private TrackSegmentView trackSegmentView;
038    private TrackSegment trackSegment;
039
040    private JmriJFrame editTrackSegmentFrame = null;
041    private final JComboBox<String> editTrackSegmentMainlineComboBox = new JComboBox<>();
042    private final JComboBox<String> editTrackSegmentDashedComboBox = new JComboBox<>();
043    private final JCheckBox editTrackSegmentHiddenCheckBox = new JCheckBox(Bundle.getMessage("HideTrack"));  // NOI18N
044    private final NamedBeanComboBox<Block> editTrackSegmentBlockNameComboBox = new NamedBeanComboBox<>(
045            InstanceManager.getDefault(BlockManager.class), null, DisplayOptions.DISPLAYNAME);
046    private final JTextField editTrackSegmentArcTextField = new JTextField(5);
047    private JButton editTrackSegmentSegmentEditBlockButton;
048
049    private int editTrackSegmentMainlineTrackIndex;
050    private int editTrackSegmentSideTrackIndex;
051    private int editTrackSegmentDashedIndex;
052    private int editTrackSegmentSolidIndex;
053    private boolean editTrackSegmentOpen = false;
054    private boolean editTrackSegmentNeedsRedraw = false;
055
056
057    /**
058     * Edit a Track Segment.
059     */
060    @InvokeOnGuiThread
061    @Override
062    public void editLayoutTrack(@Nonnull LayoutTrackView layoutTrackView) {
063        if ( layoutTrackView instanceof TrackSegmentView ) {
064            this.trackSegmentView = (TrackSegmentView) layoutTrackView;
065            this.trackSegment = this.trackSegmentView.getTrackSegment();
066        } else {
067            log.error("editLayoutTrack received type {} content {}", 
068                    layoutTrackView.getClass(), layoutTrackView, 
069                    new Exception("traceback"));
070        }
071        sensorList.clear();
072
073        if (editTrackSegmentOpen) {
074            editTrackSegmentFrame.setVisible(true);
075        } else if (editTrackSegmentFrame == null) { // Initialize if needed
076            editTrackSegmentFrame = new JmriJFrame(Bundle.getMessage("EditTrackSegment"), false, true); // key moved to DisplayBundle to be found by CircuitBuilder.java   // NOI18N
077            editTrackSegmentFrame.addHelpMenu("package.jmri.jmrit.display.EditTrackSegment", true);  // NOI18N
078            editTrackSegmentFrame.setLocation(50, 30);
079            Container contentPane = editTrackSegmentFrame.getContentPane();
080            contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
081
082            // add dashed choice
083            JPanel panel31 = new JPanel();
084            panel31.setLayout(new FlowLayout());
085            editTrackSegmentDashedComboBox.removeAllItems();
086            editTrackSegmentDashedComboBox.addItem(Bundle.getMessage("Solid"));  // NOI18N
087            editTrackSegmentSolidIndex = 0;
088            editTrackSegmentDashedComboBox.addItem(Bundle.getMessage("Dashed"));  // NOI18N
089            editTrackSegmentDashedIndex = 1;
090            editTrackSegmentDashedComboBox.setToolTipText(Bundle.getMessage("DashedToolTip"));  // NOI18N
091            JLabel label31a = new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("Style")));
092            panel31.add(label31a);
093            label31a.setLabelFor(editTrackSegmentDashedComboBox);
094            panel31.add(editTrackSegmentDashedComboBox);
095            contentPane.add(panel31);
096
097            // add mainline choice
098            JPanel panel32 = new JPanel();
099            panel32.setLayout(new FlowLayout());
100
101            editTrackSegmentMainlineComboBox.removeAllItems();
102            editTrackSegmentMainlineComboBox.addItem(Bundle.getMessage("Mainline"));  // NOI18N
103            editTrackSegmentMainlineTrackIndex = 0;
104            editTrackSegmentMainlineComboBox.addItem(Bundle.getMessage("NotMainline"));  // NOI18N
105            editTrackSegmentSideTrackIndex = 1;
106            editTrackSegmentMainlineComboBox.setToolTipText(Bundle.getMessage("MainlineToolTip"));  // NOI18N
107            editTrackSegmentMainlineComboBox.setName(Bundle.getMessage("Mainline"));
108            panel32.add(editTrackSegmentMainlineComboBox);
109            contentPane.add(panel32);
110
111            // add hidden choice
112            JPanel panel33 = new JPanel();
113            panel33.setLayout(new FlowLayout());
114            editTrackSegmentHiddenCheckBox.setToolTipText(Bundle.getMessage("HiddenToolTip"));  // NOI18N
115            panel33.add(editTrackSegmentHiddenCheckBox);
116            contentPane.add(panel33);
117
118            // setup block name
119            JPanel panel2 = new JPanel();
120            panel2.setLayout(new FlowLayout());
121            JLabel blockNameLabel = new JLabel(Bundle.getMessage("BlockID"));  // NOI18N
122            panel2.add(blockNameLabel);
123            blockNameLabel.setLabelFor(editTrackSegmentBlockNameComboBox);
124            LayoutEditor.setupComboBox(editTrackSegmentBlockNameComboBox, false, true, true);
125            editTrackSegmentBlockNameComboBox.setToolTipText(Bundle.getMessage("EditBlockNameHint"));  // NOI18N
126
127            panel2.add(editTrackSegmentBlockNameComboBox);
128
129            contentPane.add(panel2);
130
131            JPanel panel20 = new JPanel();
132            panel20.setLayout(new FlowLayout());
133            JLabel arcLabel = new JLabel(Bundle.getMessage("SetArcAngle"));  // NOI18N
134            panel20.add(arcLabel);
135            arcLabel.setLabelFor(editTrackSegmentArcTextField);
136            panel20.add(editTrackSegmentArcTextField);
137            editTrackSegmentArcTextField.setToolTipText(Bundle.getMessage("SetArcAngleHint"));  // NOI18N
138            contentPane.add(panel20);
139
140            // set up Edit Block, Done and Cancel buttons
141            JPanel panel5 = new JPanel();
142            panel5.setLayout(new FlowLayout());
143
144            // Edit Block
145            panel5.add(editTrackSegmentSegmentEditBlockButton = new JButton(Bundle.getMessage("EditBlock", "")));  // NOI18N
146            editTrackSegmentSegmentEditBlockButton.addActionListener(this::editTrackSegmentEditBlockPressed);
147            editTrackSegmentSegmentEditBlockButton.setToolTipText(Bundle.getMessage("EditBlockHint", "")); // empty value for block 1  // NOI18N
148
149            addDoneCancelButtons(panel5, editTrackSegmentFrame.getRootPane(),
150                    this::editTracksegmentDonePressed, this::editTrackSegmentCancelPressed);
151            contentPane.add(panel5);
152        }
153        // Set up for Edit
154        if (trackSegment.isMainline()) {
155            editTrackSegmentMainlineComboBox.setSelectedIndex(editTrackSegmentMainlineTrackIndex);
156        } else {
157            editTrackSegmentMainlineComboBox.setSelectedIndex(editTrackSegmentSideTrackIndex);
158        }
159        if (trackSegmentView.isDashed()) {
160            editTrackSegmentDashedComboBox.setSelectedIndex(editTrackSegmentDashedIndex);
161        } else {
162            editTrackSegmentDashedComboBox.setSelectedIndex(editTrackSegmentSolidIndex);
163        }
164        editTrackSegmentHiddenCheckBox.setSelected(trackSegmentView.isHidden());
165        Block block = InstanceManager.getDefault(BlockManager.class).getBlock(trackSegment.getBlockName());
166        editTrackSegmentBlockNameComboBox.getEditor().setItem(block);   // Select the item via the editor, empty text field if null
167        editTrackSegmentBlockNameComboBox.setEnabled(!hasNxSensorPairs(trackSegment.getLayoutBlock()));
168
169        if (trackSegmentView.isArc() && trackSegmentView.isCircle()) {
170            editTrackSegmentArcTextField.setText("" + trackSegmentView.getAngle());
171            editTrackSegmentArcTextField.setEnabled(true);
172        } else {
173            editTrackSegmentArcTextField.setEnabled(false);
174        }
175
176        editTrackSegmentFrame.addWindowListener(new java.awt.event.WindowAdapter() {
177            @Override
178            public void windowClosing(java.awt.event.WindowEvent e) {
179                editTrackSegmentCancelPressed(null);
180            }
181        });
182        editTrackSegmentFrame.pack();
183        editTrackSegmentFrame.setVisible(true);
184        editTrackSegmentOpen = true;
185
186        showSensorMessage();
187    }   // editTrackSegment
188
189    @InvokeOnGuiThread
190    private void editTrackSegmentEditBlockPressed(ActionEvent a) {
191        // check if a block name has been entered
192        String newName = editTrackSegmentBlockNameComboBox.getSelectedItemDisplayName();
193        if (newName == null) {
194            newName = "";
195        }
196        if ((trackSegment.getBlockName().isEmpty())
197                || !trackSegment.getBlockName().equals(newName)) {
198            // get new block, or null if block has been removed
199            trackSegment.setLayoutBlock(layoutEditor.provideLayoutBlock(newName));
200            editTrackSegmentNeedsRedraw = true;
201            layoutEditor.getLEAuxTools().setBlockConnectivityChanged();
202            trackSegment.updateBlockInfo();
203        }
204        // check if a block exists to edit
205        if (trackSegment.getLayoutBlock() == null) {
206            JmriJOptionPane.showMessageDialog(editTrackSegmentFrame,
207                    Bundle.getMessage("Error1"), // NOI18N
208                    Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);  // NOI18N
209            return;
210        }
211        trackSegment.getLayoutBlock().editLayoutBlock(editTrackSegmentFrame);
212        layoutEditor.setDirty();
213        editTrackSegmentNeedsRedraw = true;
214    }
215
216    @InvokeOnGuiThread
217    private void editTracksegmentDonePressed(ActionEvent a) {
218        // set dashed
219        boolean oldDashed = trackSegmentView.isDashed();
220        trackSegmentView.setDashed(editTrackSegmentDashedComboBox.getSelectedIndex() == editTrackSegmentDashedIndex);
221
222        // set mainline
223        boolean oldMainline = trackSegment.isMainline();
224        trackSegment.setMainline(editTrackSegmentMainlineComboBox.getSelectedIndex() == editTrackSegmentMainlineTrackIndex);
225
226        // set hidden
227        boolean oldHidden = trackSegmentView.isHidden();
228        trackSegmentView.setHidden(editTrackSegmentHiddenCheckBox.isSelected());
229
230        if (trackSegmentView.isArc()) {
231            try {
232                double newAngle = Double.parseDouble(editTrackSegmentArcTextField.getText());
233                trackSegmentView.setAngle(newAngle);
234                editTrackSegmentNeedsRedraw = true;
235            } catch (NumberFormatException e) {
236                editTrackSegmentArcTextField.setText("" + trackSegmentView.getAngle());
237            }
238        }
239        // check if anything changed
240        if ((oldDashed != trackSegmentView.isDashed())
241                || (oldMainline != trackSegment.isMainline())
242                || (oldHidden != trackSegmentView.isHidden())) {
243            editTrackSegmentNeedsRedraw = true;
244        }
245        // check if Block changed
246        String newName = editTrackSegmentBlockNameComboBox.getSelectedItemDisplayName();
247        if (newName == null) {
248            newName = "";
249        }
250        if ((trackSegment.getBlockName().isEmpty())
251                || !trackSegment.getBlockName().equals(newName)) {
252            // get new block, or null if block has been removed
253            trackSegment.setLayoutBlock(layoutEditor.provideLayoutBlock(newName));
254            editTrackSegmentNeedsRedraw = true;
255            layoutEditor.getLEAuxTools().setBlockConnectivityChanged();
256            trackSegment.updateBlockInfo();
257        }
258        editTrackSegmentOpen = false;
259
260        editTrackSegmentFrame.setVisible(false);
261        editTrackSegmentFrame.dispose();
262        editTrackSegmentFrame = null;
263
264        if (editTrackSegmentNeedsRedraw) {
265            layoutEditor.redrawPanel();
266            editTrackSegmentNeedsRedraw = false;
267        }
268        layoutEditor.setDirty();
269    }
270
271    @InvokeOnGuiThread
272    private void editTrackSegmentCancelPressed(ActionEvent a) {
273        editTrackSegmentOpen = false;
274        editTrackSegmentFrame.setVisible(false);
275        editTrackSegmentFrame.dispose();
276        editTrackSegmentFrame = null;
277        if (editTrackSegmentNeedsRedraw) {
278            layoutEditor.setDirty();
279            layoutEditor.redrawPanel();
280            editTrackSegmentNeedsRedraw = false;
281        }
282    }
283
284
285    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrackSegmentEditor.class);
286}