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