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}