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}