001package jmri.jmrit.operations.trains; 002 003import java.awt.Point; 004import java.awt.event.ActionEvent; 005import java.util.List; 006 007import javax.swing.*; 008 009import jmri.InstanceManager; 010import jmri.jmrit.display.Editor; 011import jmri.jmrit.display.LocoIcon; 012import jmri.jmrit.operations.rollingstock.cars.Car; 013import jmri.jmrit.operations.rollingstock.cars.CarManager; 014import jmri.jmrit.operations.routes.Route; 015import jmri.jmrit.operations.routes.RouteLocation; 016import jmri.jmrit.operations.trains.tools.ShowCarsInTrainAction; 017import jmri.jmrit.throttle.ThrottleFrameManager; 018import jmri.util.swing.JmriJOptionPane; 019import jmri.util.swing.JmriMouseEvent; 020 021/** 022 * An icon that displays the position of a train icon on a panel. 023 * <p> 024 * The icon can always be repositioned and its popup menu is always active. 025 * 026 * @author Bob Jacobsen Copyright (c) 2002 027 * @author Daniel Boudreau Copyright (C) 2008 028 */ 029public class TrainIcon extends LocoIcon { 030 031 public TrainIcon(Editor editor) { 032 // super ctor call to make sure this is an icon label 033 super(editor); 034 } 035 036 // train icon tool tips are always enabled 037 @Override 038 public void setShowToolTip(boolean set) { 039 _showTooltip = true; 040 } 041 042 /** 043 * Pop-up only if right click and not dragged return true if a popup item is 044 * set 045 */ 046 @Override 047 public boolean showPopUp(JPopupMenu popup) { 048 if (_train != null) { 049 // first action is either "Move" or "Terminate" train 050 String actionText = (_train.getCurrentRouteLocation() == _train.getTrainTerminatesRouteLocation()) 051 ? Bundle.getMessage("Terminate") : Bundle.getMessage("Move"); 052 popup.add(new AbstractAction(actionText) { 053 @Override 054 public void actionPerformed(ActionEvent e) { 055 _train.move(); 056 } 057 }); 058 popup.add(makeTrainRouteMenu()); 059 popup.add(new TrainConductorAction(_train)); 060 popup.add(new ShowCarsInTrainAction(_train)); 061 if (!isEditable()) { 062 popup.add(new AbstractAction(Bundle.getMessage("SetX&Y")) { 063 @Override 064 public void actionPerformed(ActionEvent e) { 065 if (!_train.setTrainIconCoordinates()) { 066 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("SeeOperationsSettings"), Bundle 067 .getMessage("SetX&YisDisabled"), JmriJOptionPane.ERROR_MESSAGE); 068 } 069 } 070 }); 071 } 072 } 073 popup.add(new ThrottleAction(Bundle.getMessage("Throttle"))); 074 popup.add(makeLocoIconMenu()); 075 if (!isEditable()) { 076 getEditor().setRemoveMenu(this, popup); 077 } 078 return true; 079 } 080 081 Train _train = null; 082 083 public void setTrain(Train train) { 084 _train = train; 085 } 086 087 public Train getTrain() { 088 return _train; 089 } 090 091 int _consistNumber = 0; 092 093 public void setConsistNumber(int cN) { 094 this._consistNumber = cN; 095 } 096 097 private int getConsistNumber() { 098 return _consistNumber; 099 } 100 101 jmri.jmrit.throttle.ThrottleFrame _tf = null; 102 103 private void createThrottle() { 104 _tf = InstanceManager.getDefault(ThrottleFrameManager.class).createThrottleFrame(); 105 if (getConsistNumber() > 0) { 106 _tf.getAddressPanel().setAddress(getConsistNumber(), false); // use consist address 107 if (JmriJOptionPane.showConfirmDialog(null, Bundle.getMessage("SendFunctionCommands"), Bundle 108 .getMessage("ConsistThrottle"), JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 109 _tf.getAddressPanel().setRosterEntry(_entry); // use lead loco address 110 } 111 } else { 112 _tf.getAddressPanel().setRosterEntry(_entry); 113 } 114 _tf.toFront(); 115 } 116 117 private JMenu makeTrainRouteMenu() { 118 JMenu routeMenu = new JMenu(Bundle.getMessage("Route")); 119 Route route = _train.getRoute(); 120 if (route == null) { 121 return routeMenu; 122 } 123 List<Car> carList = InstanceManager.getDefault(CarManager.class).getByTrainList(_train); 124 for (RouteLocation rl : route.getLocationsBySequenceList()) { 125 int pickupCars = 0; 126 int dropCars = 0; 127 String current = " "; 128 if (_train.getCurrentRouteLocation() == rl) { 129 current = "-> "; // NOI18N 130 } 131 for (Car car : carList) { 132 if (car.getRouteLocation() == rl && !car.getTrackName().equals(Car.NONE)) { 133 pickupCars++; 134 } 135 if (car.getRouteDestination() == rl) { 136 dropCars++; 137 } 138 } 139 String rText = ""; 140 String pickups = ""; 141 String drops = ""; 142 if (pickupCars > 0) { 143 pickups = " " + Bundle.getMessage("Pickup") + " " + pickupCars; 144 if (dropCars > 0) { 145 drops = ", " + Bundle.getMessage("SetOut") + " " + dropCars; 146 } 147 } else if (dropCars > 0) { 148 drops = " " + Bundle.getMessage("SetOut") + " " + dropCars; 149 } 150 if (pickupCars > 0 || dropCars > 0) { 151 rText = current + rl.getName() + " (" + pickups + drops + " )"; 152 } else { 153 rText = current + rl.getName(); 154 } 155 routeMenu.add(new RouteAction(rText, rl)); 156 } 157 return routeMenu; 158 } 159 160 public class ThrottleAction extends AbstractAction { 161 public ThrottleAction(String actionName) { 162 super(actionName); 163 if (_entry == null) { 164 setEnabled(false); 165 } 166 } 167 168 @Override 169 public void actionPerformed(ActionEvent e) { 170 createThrottle(); 171 } 172 } 173 174 /** 175 * Moves train from current location to the one selected by user. 176 * 177 */ 178 public class RouteAction extends AbstractAction { 179 RouteLocation _rl; 180 181 public RouteAction(String actionName, RouteLocation rl) { 182 super(actionName); 183 _rl = rl; 184 } 185 186 @Override 187 public void actionPerformed(ActionEvent e) { 188 log.debug("Route location selected {}", _rl.getName()); 189 Route route = _train.getRoute(); 190 List<RouteLocation> routeList = route.getLocationsBySequenceList(); 191 // determine where the train is in the route 192 for (int r = 0; r < routeList.size(); r++) { 193 RouteLocation rl = routeList.get(r); 194 if (_train.getCurrentRouteLocation() == rl) { 195 log.debug("Train is at location {}", rl.getName()); 196 // Is train at this route location? 197 if (rl == _rl) { 198 break; 199 } 200 for (int i = r + 1; i < routeList.size(); i++) { 201 RouteLocation nextRl = routeList.get(i); 202 // did user select the next location in the route? 203 if (nextRl == _rl && i == r + 1) { 204 _train.move(); 205 } else if (nextRl == _rl) { 206 if (JmriJOptionPane.showConfirmDialog(null, Bundle 207 .getMessage("MoveTrainTo", _rl.getName()), 208 Bundle.getMessage("MoveTrain", _train.getIconName()), 209 JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 210 while (_train.getCurrentRouteLocation() != _rl) { 211 _train.move(); 212 } 213 } 214 } 215 } 216 } 217 } 218 } 219 } 220 221 222 // route 223 224 /** 225 * Determine if user moved the train icon to next location in a train's 226 * route. 227 */ 228 @Override 229 public void doMouseDragged(JmriMouseEvent event) { 230 log.debug("Mouse dragged, X={} Y={}", getX(), getY()); 231 if (_train != null) { 232 RouteLocation next = _train.getNextRouteLocation(_train.getCurrentRouteLocation()); 233 if (next != null) { 234 Point nextPoint = next.getTrainIconCoordinates(); 235 log.debug("Next location ({}), X={} Y={}", next.getName(), nextPoint.x, nextPoint.y); 236 if (Math.abs(getX() - nextPoint.x) < next.getTrainIconRangeX() && Math.abs(getY() - nextPoint.y) < next.getTrainIconRangeY()) { 237 log.debug("Train icon ({}) within range of ({})", _train.getName(), next.getName()); 238 if (JmriJOptionPane.showConfirmDialog(null, Bundle.getMessage("MoveTrainTo", 239 next.getName()), Bundle.getMessage("MoveTrain", 240 _train.getIconName()), JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 241 _train.move(); 242 } 243 } 244 } 245 } 246 } 247 248 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrainIcon.class); 249}