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}