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}