001package jmri.jmrit.operations.locations.gui;
002
003import java.awt.Color;
004import java.awt.GridBagLayout;
005
006import javax.swing.*;
007
008import jmri.InstanceManager;
009import jmri.jmrit.operations.locations.Location;
010import jmri.jmrit.operations.locations.Track;
011import jmri.jmrit.operations.locations.schedules.*;
012import jmri.jmrit.operations.locations.tools.*;
013import jmri.jmrit.operations.setup.Control;
014import jmri.jmrit.operations.setup.Setup;
015import jmri.util.swing.JmriJOptionPane;
016
017import org.slf4j.Logger;
018import org.slf4j.LoggerFactory;
019
020/**
021 * Frame for user edit of a spur.
022 *
023 * @author Dan Boudreau Copyright (C) 2008, 2011, 2023, 2025
024 */
025public class SpurEditFrame extends TrackEditFrame {
026
027    ScheduleManager scheduleManager = InstanceManager.getDefault(ScheduleManager.class);
028
029    // labels, buttons, etc. for spurs
030    JLabel textSchedule = new JLabel(Bundle.getMessage("DeliverySchedule"));
031    JLabel textSchError = new JLabel();
032    JButton editScheduleButton = new JButton();
033    JComboBox<Schedule> comboBoxSchedules = scheduleManager.getComboBox();
034
035    JPanel panelSchedule = panelOpt4;
036
037    public SpurEditFrame() {
038        super(Bundle.getMessage("AddSpur"));
039    }
040    
041    public SpurEditFrame(Location location) {
042        super(Bundle.getMessage("AddSpur"));
043        initComponents(location, null);
044    }
045    
046    public SpurEditFrame(Track track) {
047        super(Bundle.getMessage("EditSpur", track.getLocation().getName()));
048        initComponents(track.getLocation(), track);
049    }
050
051    @Override
052    protected void initComponents(Location location, Track track) {
053        _type = Track.SPUR;
054
055        // setup the optional panel with schedule stuff
056        panelSchedule.setLayout(new GridBagLayout());
057        panelSchedule.setBorder(BorderFactory.createTitledBorder(Bundle
058                .getMessage("DeliverySchedule")));
059        addItem(panelSchedule, comboBoxSchedules, 0, 0);
060        addItem(panelSchedule, editScheduleButton, 1, 0);
061        addItem(panelSchedule, textSchError, 2, 0);
062        textSchError.setForeground(Color.RED);
063
064        super.initComponents(location, track);
065
066        _toolMenu.insert(new AlternateTrackAction(this), 0);
067        _toolMenu.insert(new TrackPriorityAction(_track), 1);
068        _toolMenu.insert(new ChangeTrackTypeAction(this), TOOL_MENU_OFFSET + 2);
069        addHelpMenu("package.jmri.jmrit.operations.Operations_Spurs", true); // NOI18N
070
071        // override text strings for tracks
072        panelTrainDir.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainSpur")));
073        paneCheckBoxes.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TypesSpur")));
074        deleteTrackButton.setText(Bundle.getMessage("DeleteSpur"));
075        addTrackButton.setText(Bundle.getMessage("AddSpur"));
076        saveTrackButton.setText(Bundle.getMessage("SaveSpur"));
077        
078        // tool tips
079        autoSelectButton.setToolTipText(Bundle.getMessage("TipAutoSelectSchedule"));
080
081        // setup buttons
082        addButtonAction(autoSelectButton);
083        addButtonAction(editScheduleButton);
084        addComboBoxAction(comboBoxSchedules);
085        
086        // Select the spur's Schedule
087        updateScheduleComboBox();
088
089        scheduleManager.addPropertyChangeListener(this);
090        
091        // finish
092        panelOrder.setVisible(false); // Car order out of spurs is not available
093        panelQuickService.setVisible(Setup.isBuildOnTime());
094        pack();
095        setVisible(true);
096    }
097
098    @Override
099    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
100        if (ae.getSource() == autoSelectButton) {
101            autoSelectCheckboxes();
102        }
103        if (ae.getSource() == editScheduleButton) {
104            editAddSchedule();
105        }
106        super.buttonActionPerformed(ae);
107    }
108    
109    @Override
110    public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) {
111        removeSchedulePropertyListener();
112        updateScheduleButtonText();
113    }
114    
115    private void updateScheduleButtonText() {
116        if (comboBoxSchedules.getSelectedItem() == null) {
117            editScheduleButton.setText(Bundle.getMessage("Add"));
118        } else {
119            editScheduleButton.setText(Bundle.getMessage("ButtonEdit"));
120        }
121    }
122    
123    private void autoSelectCheckboxes() {
124        if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("TipAutoSelectSchedule"),
125                Bundle.getMessage("AutoSelect"), JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
126            for (int i = 0; i < checkBoxes.size(); i++) {
127                JCheckBox checkBox = checkBoxes.get(i);
128                if (_track != null && _track.getSchedule() != null) {
129                    Schedule schedule = _track.getSchedule();
130                    if (schedule.checkScheduleAttribute(Track.TYPE, checkBox.getText(), null)) {
131                        _track.addTypeName(checkBox.getText());
132                    } else {
133                        _track.deleteTypeName(checkBox.getText());
134                    }
135                }
136            }
137        }
138    }
139
140
141    ScheduleEditFrame sef = null;
142
143    private void editAddSchedule() {
144        log.debug("Edit/add schedule");
145        if (sef != null) {
146            sef.dispose();
147        }
148        Schedule schedule = (Schedule) comboBoxSchedules.getSelectedItem();
149        sef = new ScheduleEditFrame(schedule, _track);
150    }
151
152    @Override
153    protected void enableButtons(boolean enabled) {
154        autoSelectButton.setEnabled(enabled && _track.getSchedule() != null);
155        editScheduleButton.setEnabled(enabled);
156        comboBoxSchedules.setEnabled(enabled);
157        if (!enabled) {
158            comboBoxSchedules.setSelectedItem(null);
159        }
160        super.enableButtons(enabled);
161    }
162
163    @Override
164    protected void saveTrack(Track track) {
165        // save the schedule
166        Schedule schedule = (Schedule) comboBoxSchedules.getSelectedItem();
167        track.setSchedule(schedule);
168        textSchError.setText(track.checkScheduleValid());
169        super.saveTrack(track);
170    }
171
172    @Override
173    protected void addNewTrack() {
174        super.addNewTrack();
175        updateScheduleComboBox(); // reset schedule and error text
176    }
177    
178    @Override
179    protected void deleteTrack() {
180        removeSchedulePropertyListener();
181        super.deleteTrack();
182    }
183
184    private void updateScheduleComboBox() {
185        scheduleManager.updateComboBox(comboBoxSchedules);
186        if (_track != null) {
187            Schedule sch = scheduleManager.getScheduleById(_track.getScheduleId());
188            comboBoxSchedules.setSelectedItem(sch);
189            textSchError.setText(_track.checkScheduleValid());
190            if (sch != null) {
191                sch.removePropertyChangeListener(this);
192                sch.addPropertyChangeListener(this);
193            }
194        }
195    }
196
197    @Override
198    public void dispose() {
199        scheduleManager.removePropertyChangeListener(this);
200        removeSchedulePropertyListener();
201        super.dispose();
202    }
203    
204    private void removeSchedulePropertyListener() {
205        if (_track != null) {
206            Schedule sch = scheduleManager.getScheduleById(_track.getScheduleId());
207            if (sch != null)
208                sch.removePropertyChangeListener(this);
209        }
210    }
211
212    @Override
213    public void propertyChange(java.beans.PropertyChangeEvent e) {
214        if (Control.SHOW_PROPERTY) {
215            log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e
216                    .getNewValue());
217        }
218        if (e.getPropertyName().equals(ScheduleManager.LISTLENGTH_CHANGED_PROPERTY)
219                || e.getPropertyName().equals(Track.SCHEDULE_ID_CHANGED_PROPERTY)) {
220            updateScheduleComboBox();
221        }
222        if (e.getSource().getClass().equals(Schedule.class) && _track != null  ||
223                e.getPropertyName().equals(Track.LOADS_CHANGED_PROPERTY) ||
224                e.getPropertyName().equals(Track.ROADS_CHANGED_PROPERTY) ||
225                e.getPropertyName().equals(Track.TYPES_CHANGED_PROPERTY)) {
226            textSchError.setText(_track.checkScheduleValid());
227        }
228        super.propertyChange(e);
229    }
230
231    private static final Logger log = LoggerFactory.getLogger(SpurEditFrame.class);
232}