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