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