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