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(textTrainStatusPane);
096        add(locoPane);
097        add(pWorkPanes);
098        add(movePane);
099        add(pStatus);
100        add(pRow14);
101
102        // setup buttons
103        addButtonAction(moveButton);
104
105        if (_train != null) {
106            loadTrainDescription();
107            loadTrainComment();
108            loadRouteComment();
109            loadRailroadName();
110            // listen for train changes
111            _train.addPropertyChangeListener(this);
112        }
113        trainManager.addPropertyChangeListener(this);
114        
115        update();
116    }
117
118    @Override
119    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
120        if (ae.getSource() == moveButton) {
121            _train.move();
122            return;
123        }
124        super.buttonActionPerformed(ae);
125    }
126
127    private boolean queued = false;
128
129    @Override
130    protected void update() {
131        log.debug("queue update");
132        if (queued) {
133            return;
134        }
135        queued = true;
136        // use invokeLater to prevent deadlock
137        SwingUtilities.invokeLater(() -> {
138            log.debug("run update, setMode: {}", isSetMode);
139            queued = false;
140            initialize();
141            if (_train != null && _train.getRoute() != null) {
142                textTrainName.setText(_train.getIconName());
143                RouteLocation rl = _train.getCurrentRouteLocation();
144                if (rl != null) {
145                    loadRouteLocationComment(rl);
146
147                    textLocationName.setText(trainManager.isShowLocationHyphenNameEnabled() ? rl.getLocation().getName()
148                            : rl.getLocation().getSplitName());
149                    pTrainDepartureTime.setVisible(_train.isShowArrivalAndDepartureTimesEnabled() &&
150                            !rl.getDepartureTime().equals(RouteLocation.NONE));
151                    textTrainDepartureTime.setText(rl.getFormatedDepartureTime());
152
153                    loadLocationComment(rl.getLocation());
154
155                    textNextLocationName
156                            .setText(trainManager.isShowLocationHyphenNameEnabled() ? _train.getNextLocationName()
157                                    : TrainCommon.splitString(_train.getNextLocationName()));
158                    
159                    updateTrackComments(rl, IS_MANIFEST);
160                    
161                    textTrainStatusPane.setText(TrainCommon.getTrainMessage(_train, rl));
162                            
163                    // check for locos
164                    updateLocoPanes(rl);
165
166                    // now update the car pick ups and set outs
167                    blockCars(rl, IS_MANIFEST);
168                }
169
170                textStatus.setText(getStatus(rl, IS_MANIFEST));
171
172                // adjust move button text
173                if (rl == _train.getTrainTerminatesRouteLocation()) {
174                    moveButton.setText(Bundle.getMessage("Terminate"));
175                } else {
176                    moveButton.setText(Bundle.getMessage("Move"));
177                }
178            }
179            updateComplete();
180        });
181    }
182
183    @Override
184    public void dispose() {
185        trainManager.removePropertyChangeListener(this);
186        removePropertyChangeListerners();
187        if (_train != null) {
188            _train.removePropertyChangeListener(this);
189        }
190        super.dispose();
191    }
192
193    @Override
194    public void propertyChange(java.beans.PropertyChangeEvent e) {
195        if (Control.SHOW_PROPERTY) {
196            log.debug("Property change ({}) for: ({}) old: {}, new: {}", e.getPropertyName(), e.getSource().toString(),
197                    e.getOldValue(), e.getNewValue());
198        }
199        if (e.getPropertyName().equals(Train.TRAIN_MOVE_COMPLETE_CHANGED_PROPERTY) ||
200                e.getPropertyName().equals(Train.BUILT_CHANGED_PROPERTY)) {
201            clearAndUpdate();
202        }
203        if ((e.getPropertyName().equals(RollingStock.ROUTE_LOCATION_CHANGED_PROPERTY) && e.getNewValue() == null) ||
204                (e.getPropertyName().equals(RollingStock.ROUTE_DESTINATION_CHANGED_PROPERTY) &&
205                        e.getNewValue() == null) ||
206                e.getPropertyName().equals(RollingStock.TRAIN_CHANGED_PROPERTY) ||
207                e.getPropertyName().equals(Train.TRAIN_MODIFIED_CHANGED_PROPERTY) ||
208                e.getPropertyName().equals(TrainManager.TRAINS_SHOW_FULL_NAME_PROPERTY)) {
209            // remove car from list so the text get's updated
210            if (e.getSource().getClass().equals(Car.class)) {
211                Car car = (Car) e.getSource();
212                removeCarFromList(car);
213            }
214            update();
215        }
216    }
217
218    private final static Logger log = LoggerFactory.getLogger(TrainConductorPanel.class);
219}