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