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