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(locoPane); 096 add(pWorkPanes); 097 add(movePane); 098 add(pStatus); 099 add(pRow14); 100 101 // setup buttons 102 addButtonAction(moveButton); 103 104 if (_train != null) { 105 loadTrainDescription(); 106 loadTrainComment(); 107 loadRouteComment(); 108 loadRailroadName(); 109 // listen for train changes 110 _train.addPropertyChangeListener(this); 111 } 112 trainManager.addPropertyChangeListener(this); 113 114 update(); 115 } 116 117 @Override 118 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 119 if (ae.getSource() == moveButton) { 120 _train.move(); 121 return; 122 } 123 super.buttonActionPerformed(ae); 124 } 125 126 private boolean queued = false; 127 128 @Override 129 protected void update() { 130 log.debug("queue update"); 131 if (queued) { 132 return; 133 } 134 queued = true; 135 // use invokeLater to prevent deadlock 136 SwingUtilities.invokeLater(() -> { 137 log.debug("run update, setMode: {}", isSetMode); 138 queued = false; 139 initialize(); 140 if (_train != null && _train.getRoute() != null) { 141 textTrainName.setText(_train.getIconName()); 142 RouteLocation rl = _train.getCurrentRouteLocation(); 143 if (rl != null) { 144 loadRouteLocationComment(rl); 145 146 textLocationName.setText(trainManager.isShowLocationHyphenNameEnabled() ? rl.getLocation().getName() 147 : rl.getLocation().getSplitName()); 148 pTrainDepartureTime.setVisible(_train.isShowArrivalAndDepartureTimesEnabled() && 149 !rl.getDepartureTime().equals(RouteLocation.NONE)); 150 textTrainDepartureTime.setText(rl.getFormatedDepartureTime()); 151 152 loadLocationComment(rl.getLocation()); 153 154 textNextLocationName 155 .setText(trainManager.isShowLocationHyphenNameEnabled() ? _train.getNextLocationName() 156 : TrainCommon.splitString(_train.getNextLocationName())); 157 158 updateTrackComments(rl, IS_MANIFEST); 159 160 // check for locos 161 updateLocoPanes(rl); 162 163 // now update the car pick ups and set outs 164 blockCars(rl, IS_MANIFEST); 165 } 166 167 textStatus.setText(getStatus(rl, IS_MANIFEST)); 168 169 // adjust move button text 170 if (rl == _train.getTrainTerminatesRouteLocation()) { 171 moveButton.setText(Bundle.getMessage("Terminate")); 172 } else { 173 moveButton.setText(Bundle.getMessage("Move")); 174 } 175 } 176 updateComplete(); 177 }); 178 } 179 180 @Override 181 public void dispose() { 182 trainManager.removePropertyChangeListener(this); 183 removePropertyChangeListerners(); 184 if (_train != null) { 185 _train.removePropertyChangeListener(this); 186 } 187 super.dispose(); 188 } 189 190 @Override 191 public void propertyChange(java.beans.PropertyChangeEvent e) { 192 if (Control.SHOW_PROPERTY) { 193 log.debug("Property change ({}) for: ({}) old: {}, new: {}", e.getPropertyName(), e.getSource().toString(), 194 e.getOldValue(), e.getNewValue()); 195 } 196 if (e.getPropertyName().equals(Train.TRAIN_MOVE_COMPLETE_CHANGED_PROPERTY) || 197 e.getPropertyName().equals(Train.BUILT_CHANGED_PROPERTY)) { 198 clearAndUpdate(); 199 } 200 if ((e.getPropertyName().equals(RollingStock.ROUTE_LOCATION_CHANGED_PROPERTY) && e.getNewValue() == null) || 201 (e.getPropertyName().equals(RollingStock.ROUTE_DESTINATION_CHANGED_PROPERTY) && 202 e.getNewValue() == null) || 203 e.getPropertyName().equals(RollingStock.TRAIN_CHANGED_PROPERTY) || 204 e.getPropertyName().equals(Train.TRAIN_MODIFIED_CHANGED_PROPERTY) || 205 e.getPropertyName().equals(TrainManager.TRAINS_SHOW_FULL_NAME_PROPERTY)) { 206 // remove car from list so the text get's updated 207 if (e.getSource().getClass().equals(Car.class)) { 208 Car car = (Car) e.getSource(); 209 removeCarFromList(car); 210 } 211 update(); 212 } 213 } 214 215 private final static Logger log = LoggerFactory.getLogger(TrainConductorPanel.class); 216}