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}