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