001package jmri.jmrit.operations.trains;
002
003import java.awt.Dimension;
004import java.awt.GridBagLayout;
005
006import javax.swing.*;
007
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011import jmri.jmrit.operations.CommonConductorYardmasterPanel;
012import jmri.jmrit.operations.rollingstock.RollingStock;
013import jmri.jmrit.operations.rollingstock.cars.Car;
014import jmri.jmrit.operations.routes.RouteLocation;
015import jmri.jmrit.operations.setup.Control;
016
017/**
018 * Conductor Panel. Shows work for a train one location at a time.
019 *
020 * @author Dan Boudreau Copyright (C) 2011, 2013
021 * 
022 */
023public class TrainConductorPanel extends CommonConductorYardmasterPanel {
024
025    // labels
026    JLabel textTrainName = new JLabel();
027    JLabel textTrainDepartureTime = new JLabel();
028    JLabel textNextLocationName = new JLabel();
029
030    // panels
031    JPanel pTrainDepartureTime = new JPanel();
032
033    /**
034     * Default constructor required to use as JavaBean.
035     */
036    public TrainConductorPanel() {
037        this(null);
038    }
039
040    public TrainConductorPanel(Train train) {
041        super();
042
043        _train = train;
044
045        // row 2
046        JPanel pRow2 = new JPanel();
047        pRow2.setLayout(new BoxLayout(pRow2, BoxLayout.X_AXIS));
048
049        // row 2a (train name)
050        JPanel pTrainName = new JPanel();
051        pTrainName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Train")));
052        pTrainName.add(textTrainName);
053
054        pRow2.add(pTrainName);
055        pRow2.add(pTrainDescription);
056        pRow2.add(pRailRoadName);
057
058        JPanel pLocation = new JPanel();
059        pLocation.setLayout(new BoxLayout(pLocation, BoxLayout.X_AXIS));
060
061        // row 10b (train departure time)
062        pTrainDepartureTime.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("DepartTime")));
063        pTrainDepartureTime.add(textTrainDepartureTime);
064
065        // row 10c (next location name)
066        JPanel pNextLocationName = new JPanel();
067        pNextLocationName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("NextLocation")));
068        pNextLocationName.add(textNextLocationName);
069
070        pLocation.add(pLocationName); // location name
071        pLocation.add(pTrainDepartureTime);
072        pLocation.add(pNextLocationName);
073
074        // row 14
075        JPanel pRow14 = new JPanel();
076        pRow14.setLayout(new BoxLayout(pRow14, BoxLayout.X_AXIS));
077        pRow14.setMaximumSize(new Dimension(2000, 200));
078
079        // row 14b
080        JPanel pMoveButton = new JPanel();
081        pMoveButton.setLayout(new GridBagLayout());
082        pMoveButton.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Train")));
083        addItem(pMoveButton, moveButton, 1, 0);
084
085        pRow14.add(pButtons);
086        pRow14.add(pMoveButton);
087
088        add(pRow2);
089        add(pLocation);
090        add(textTrainCommentPane);
091        add(textTrainRouteCommentPane); // train route comment
092        add(textTrainRouteLocationCommentPane); // train route location comment
093        add(textLocationCommentPane);
094        add(pTrackComments);
095        add(locoPane);
096        add(pWorkPanes);
097        add(movePane);
098        add(pStatus);
099        add(pRow14);
100
101        // setup buttons
102        addButtonAction(moveButton);
103
104        if (_train != null) {
105            loadTrainDescription();
106            loadTrainComment();
107            loadRouteComment();
108            loadRailroadName();
109            // listen for train changes
110            _train.addPropertyChangeListener(this);
111        }
112        trainManager.addPropertyChangeListener(this);
113        
114        update();
115    }
116
117    @Override
118    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
119        if (ae.getSource() == moveButton) {
120            _train.move();
121            return;
122        }
123        super.buttonActionPerformed(ae);
124    }
125
126    private boolean queued = false;
127
128    @Override
129    protected void update() {
130        log.debug("queue update");
131        if (queued) {
132            return;
133        }
134        queued = true;
135        // use invokeLater to prevent deadlock
136        SwingUtilities.invokeLater(() -> {
137            log.debug("run update, setMode: {}", isSetMode);
138            queued = false;
139            initialize();
140            if (_train != null && _train.getRoute() != null) {
141                textTrainName.setText(_train.getIconName());
142                RouteLocation rl = _train.getCurrentRouteLocation();
143                if (rl != null) {
144                    loadRouteLocationComment(rl);
145
146                    textLocationName.setText(trainManager.isShowLocationHyphenNameEnabled() ? rl.getLocation().getName()
147                            : rl.getLocation().getSplitName());
148                    pTrainDepartureTime.setVisible(_train.isShowArrivalAndDepartureTimesEnabled() &&
149                            !rl.getDepartureTime().equals(RouteLocation.NONE));
150                    textTrainDepartureTime.setText(rl.getFormatedDepartureTime());
151
152                    loadLocationComment(rl.getLocation());
153
154                    textNextLocationName
155                            .setText(trainManager.isShowLocationHyphenNameEnabled() ? _train.getNextLocationName()
156                                    : TrainCommon.splitString(_train.getNextLocationName()));
157                    
158                    updateTrackComments(rl, IS_MANIFEST);
159                            
160                    // check for locos
161                    updateLocoPanes(rl);
162
163                    // now update the car pick ups and set outs
164                    blockCars(rl, IS_MANIFEST);
165                }
166
167                textStatus.setText(getStatus(rl, IS_MANIFEST));
168
169                // adjust move button text
170                if (rl == _train.getTrainTerminatesRouteLocation()) {
171                    moveButton.setText(Bundle.getMessage("Terminate"));
172                } else {
173                    moveButton.setText(Bundle.getMessage("Move"));
174                }
175            }
176            updateComplete();
177        });
178    }
179
180    @Override
181    public void dispose() {
182        trainManager.removePropertyChangeListener(this);
183        removePropertyChangeListerners();
184        if (_train != null) {
185            _train.removePropertyChangeListener(this);
186        }
187        super.dispose();
188    }
189
190    @Override
191    public void propertyChange(java.beans.PropertyChangeEvent e) {
192        if (Control.SHOW_PROPERTY) {
193            log.debug("Property change ({}) for: ({}) old: {}, new: {}", e.getPropertyName(), e.getSource().toString(),
194                    e.getOldValue(), e.getNewValue());
195        }
196        if (e.getPropertyName().equals(Train.TRAIN_MOVE_COMPLETE_CHANGED_PROPERTY) ||
197                e.getPropertyName().equals(Train.BUILT_CHANGED_PROPERTY)) {
198            clearAndUpdate();
199        }
200        if ((e.getPropertyName().equals(RollingStock.ROUTE_LOCATION_CHANGED_PROPERTY) && e.getNewValue() == null) ||
201                (e.getPropertyName().equals(RollingStock.ROUTE_DESTINATION_CHANGED_PROPERTY) &&
202                        e.getNewValue() == null) ||
203                e.getPropertyName().equals(RollingStock.TRAIN_CHANGED_PROPERTY) ||
204                e.getPropertyName().equals(Train.TRAIN_MODIFIED_CHANGED_PROPERTY) ||
205                e.getPropertyName().equals(TrainManager.TRAINS_SHOW_FULL_NAME_PROPERTY)) {
206            // remove car from list so the text get's updated
207            if (e.getSource().getClass().equals(Car.class)) {
208                Car car = (Car) e.getSource();
209                removeCarFromList(car);
210            }
211            update();
212        }
213    }
214
215    private final static Logger log = LoggerFactory.getLogger(TrainConductorPanel.class);
216}