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}