001package jmri.jmrit.display; 002 003import java.awt.Color; 004import java.awt.event.ActionEvent; 005import java.awt.event.ActionListener; 006import java.util.List; 007 008import javax.swing.AbstractAction; 009import javax.swing.ButtonGroup; 010import javax.swing.JMenu; 011import javax.swing.JMenuItem; 012import javax.swing.JPopupMenu; 013import javax.swing.JRadioButtonMenuItem; 014 015import jmri.InstanceManager; 016import jmri.jmrit.catalog.NamedIcon; 017import jmri.jmrit.logix.TrackerTableAction; 018import jmri.jmrit.roster.RosterEntry; 019import jmri.jmrit.throttle.ThrottleFrameManager; 020import jmri.util.swing.JmriMouseEvent; 021 022import org.slf4j.Logger; 023import org.slf4j.LoggerFactory; 024 025import jmri.jmrit.throttle.ThrottleControllerUI; 026 027/** 028 * An icon that displays the position of a loco on a panel.<p> 029 * The icon can always be repositioned and its popup menu is always active. 030 * 031 * @author Bob Jacobsen Copyright (c) 2002 032 * @author Daniel Boudreau Copyright (C) 2008, 2010 033 */ 034public class LocoIcon extends PositionableLabel { 035 036 public static final String WHITE = Bundle.getMessage("White"); //loco background colors 037 public static final String GREEN = Bundle.getMessage("Green"); 038 public static final String GRAY = Bundle.getMessage("Gray"); 039 public static final String RED = Bundle.getMessage("Red"); 040 public static final String BLUE = Bundle.getMessage("Blue"); 041 public static final String YELLOW = Bundle.getMessage("Yellow"); 042 043 public static final Color COLOR_BLUE = new Color(40, 140, 255); 044 045 private int _dockX = 0; 046 private int _dockY = 0; 047 private Color _locoColor; 048 049 public LocoIcon(Editor editor) { 050 // super ctor call to make sure this is an icon label 051 super(new NamedIcon("resources/icons/markers/loco-white.gif", 052 "resources/icons/markers/loco-white.gif"), editor); 053 _locoColor = Color.WHITE; 054 setDisplayLevel(Editor.MARKERS); 055 setShowToolTip(false); 056 //setEditable(false); 057 _text = true; //Markers are an icon with text 058 setPopupUtility(new PositionablePopupUtil(this, this) { // need this class for Font Edit 059 @Override 060 public void setFixedTextMenu(JPopupMenu popup) { 061 } 062 063 @Override 064 public void setTextMarginMenu(JPopupMenu popup) { 065 } 066 067 @Override 068 public void setTextBorderMenu(JPopupMenu popup) { 069 } 070 071 @Override 072 public void setTextJustificationMenu(JPopupMenu popup) { 073 } 074 }); 075 } 076 077 @Override 078 public Positionable deepClone() { 079 LocoIcon pos = new LocoIcon(_editor); 080 return finishClone(pos); 081 } 082 083 protected Positionable finishClone(LocoIcon pos) { 084 if (_entry != null) { 085 pos.setRosterEntry(getRosterEntry()); 086 } 087 pos.setText(getText()); 088 return super.finishClone(pos); 089 } 090 091 // Marker tool tips are always disabled 092 @Override 093 public void setShowToolTip(boolean set) { 094 super.setShowToolTip(false); 095 } 096 097 // Markers are always positionable 098 @Override 099 public void setPositionable(boolean enabled) { 100 super.setPositionable(true); 101 } 102 103 // Markers always have a popup menu 104 @Override 105 public boolean doViemMenu() { 106 return false; 107 } 108 109 ThrottleControllerUI tf = null; 110 111 /** 112 * Pop-up only if right click and not dragged 113 */ 114 @Override 115 public boolean showPopUp(JPopupMenu popup) { 116 if (_entry != null) { 117 popup.add(new AbstractAction("Throttle") { 118 @Override 119 public void actionPerformed(ActionEvent e) { 120 tf = InstanceManager.getDefault(ThrottleFrameManager.class).createThrottleController(); 121 tf.setRosterEntry(_entry); 122 tf.toFront(); 123 } 124 }); 125 } 126 popup.add(makeLocoIconMenu()); 127 if (isEditable()) { 128 getEditor().setShowAlignmentMenu(this, popup); 129 getEditor().setShowCoordinatesMenu(this, popup); 130 popup.add(makeDockingMenu()); 131 popup.add(makeDockMenu()); 132 getPopupUtility().setTextFontMenu(popup); 133 } else { 134 setRotateMenu(popup); 135 if (_entry == null) { 136 setTextEditMenu(popup); 137 } 138 popup.add(makeDockMenu()); 139 getPopupUtility().setTextFontMenu(popup); 140 getEditor().setRemoveMenu(this, popup); 141 } 142 return true; 143 } 144 145 ButtonGroup locoButtonGroup = null; 146 147 protected JMenu makeLocoIconMenu() { 148 JMenu iconMenu = new JMenu(Bundle.getMessage("LocoColor")); 149 locoButtonGroup = new ButtonGroup(); 150 String[] colors = getLocoColors(); 151 for (String color : colors) { 152 addLocoMenuEntry(iconMenu, color); 153 } 154 return iconMenu; 155 } 156 157 // loco icons 158 NamedIcon white = new NamedIcon("resources/icons/markers/loco-white.gif", 159 "resources/icons/markers/loco-white.gif"); 160 NamedIcon green = new NamedIcon("resources/icons/markers/loco-green.gif", 161 "resources/icons/markers/loco-green.gif"); 162 NamedIcon gray = new NamedIcon("resources/icons/markers/loco-gray.gif", 163 "resources/icons/markers/loco-gray.gif"); 164 NamedIcon red = new NamedIcon("resources/icons/markers/loco-red.gif", 165 "resources/icons/markers/loco-red.gif"); 166 NamedIcon blue = new NamedIcon("resources/icons/markers/loco-blue.gif", 167 "resources/icons/markers/loco-blue.gif"); 168 NamedIcon yellow = new NamedIcon("resources/icons/markers/loco-yellow.gif", 169 "resources/icons/markers/loco-yellow.gif"); 170 171 public void addLocoMenuEntry(JMenu iconMenu, final String color) { 172 JRadioButtonMenuItem r = new JRadioButtonMenuItem(color); 173 r.addActionListener(new ActionListener() { 174 final String desiredColor = color; 175 176 @Override 177 public void actionPerformed(ActionEvent e) { 178 setLocoColor(desiredColor); 179 } 180 }); 181 locoButtonGroup.add(r); 182 iconMenu.add(r); 183 } 184 185 public void setLocoColor(String color) { 186 log.debug("Set loco color to {}", color); 187 if (color.equals(WHITE)) { 188 super.updateIcon(white); 189 _locoColor = Color.WHITE; 190 setForeground(Color.black); 191 } 192 if (color.equals(GREEN)) { 193 super.updateIcon(green); 194 _locoColor = Color.GREEN; 195 setForeground(Color.black); 196 } 197 if (color.equals(GRAY)) { 198 super.updateIcon(gray); 199 _locoColor = Color.GRAY; 200 setForeground(Color.white); 201 } 202 if (color.equals(RED)) { 203 super.updateIcon(red); 204 _locoColor = Color.RED; 205 setForeground(Color.white); 206 } 207 if (color.equals(BLUE)) { 208 super.updateIcon(blue); 209 _locoColor = COLOR_BLUE; 210 setForeground(Color.white); 211 } 212 if (color.equals(YELLOW)) { 213 super.updateIcon(yellow); 214 _locoColor = Color.YELLOW; 215 setForeground(Color.black); 216 } 217 } 218 219 public static String[] getLocoColors() { 220 return new String[]{WHITE, GREEN, GRAY, RED, BLUE, YELLOW}; 221 } 222 223 public Color getLocoColor() { 224 return _locoColor; 225 } 226 227 protected RosterEntry _entry = null; 228 229 public void setRosterEntry(RosterEntry entry) { 230 _entry = entry; 231 } 232 233 public RosterEntry getRosterEntry() { 234 return _entry; 235 } 236 237 protected JMenuItem makeDockingMenu() { 238 JMenuItem dockingMenu = new JMenuItem(Bundle.getMessage("setDockingLocation")); 239 dockingMenu.addActionListener(new ActionListener() { 240 Editor ed; 241 LocoIcon loco; 242 243 ActionListener init(Editor e, LocoIcon l) { 244 ed = e; 245 loco = l; 246 return this; 247 } 248 249 @Override 250 public void actionPerformed(ActionEvent e) { 251 ed.setSelectionsDockingLocation(loco); 252 } 253 }.init(getEditor(), this)); 254 return dockingMenu; 255 } 256 257 public void setDockingLocation(int x, int y) { 258 _dockX = x; 259 _dockY = y; 260 } 261 262 public int getDockX() { 263 return _dockX; 264 } 265 266 public int getDockY() { 267 return _dockY; 268 } 269 270 public void dock() { 271 setLocation(_dockX, _dockY); 272 } 273 274 protected JMenuItem makeDockMenu() { 275 JMenuItem dockMenu = new JMenuItem(Bundle.getMessage("dockIcon")); 276 dockMenu.addActionListener(new ActionListener() { 277 Editor ed; 278 LocoIcon loco; 279 280 ActionListener init(Editor e, LocoIcon l) { 281 ed = e; 282 loco = l; 283 return this; 284 } 285 286 @Override 287 public void actionPerformed(ActionEvent e) { 288 ed.dockSelections(loco); 289 } 290 }.init(getEditor(), this)); 291 return dockMenu; 292 } 293 294 /** 295 * Called at load time to get "background" color 296 */ 297 public void init() { 298 NamedIcon icon = (NamedIcon) getIcon(); 299 String name = icon.getURL(); 300 if (name != null) { 301 if (name.endsWith("loco-white.gif")) { 302 _locoColor = Color.WHITE; 303 } else if (name.endsWith("loco-green.gif")) { 304 _locoColor = Color.GREEN; 305 } else if (name.endsWith("loco-gray.gif")) { 306 _locoColor = Color.GRAY; 307 } else if (name.endsWith("loco-red.gif")) { 308 _locoColor = Color.RED; 309 } else if (name.endsWith("loco-blue.gif")) { 310 _locoColor = COLOR_BLUE; 311 } else if (name.endsWith("loco-yellow.gif")) { 312 _locoColor = Color.YELLOW; 313 } 314 } 315 } 316 317 /** 318 * Set display attributes for Tracker 319 */ 320 @Override 321 public void doMouseReleased(JmriMouseEvent event) { 322 List<Positionable> selections = _editor.getSelectedItems(event); 323 for (Positionable selection : selections) { 324 if (selection instanceof IndicatorTrack) { 325 IndicatorTrack t = (IndicatorTrack) selection; 326 jmri.jmrit.logix.OBlock block = t.getOccBlock(); 327 if (block != null) { 328 block.setMarkerForeground(getForeground()); 329 block.setMarkerBackground(_locoColor); 330 PositionablePopupUtil util = getPopupUtility(); 331 block.setMarkerFont(util.getFont()); 332 String name = getText(); // rotated icons have null text 333 if (name == null || name.length() == 0) { 334 name = getUnRotatedText(); 335 } 336 InstanceManager.getDefault(TrackerTableAction.class).markNewTracker(block, name, this); 337 dock(); 338 } 339 break; 340 } 341 } 342 } 343 344 private final static Logger log = LoggerFactory.getLogger(LocoIcon.class); 345}