001package jmri.jmrit.display;
002
003import java.awt.event.ActionEvent;
004import java.util.HashMap;
005import java.util.Map;
006
007import javax.annotation.CheckForNull;
008import javax.annotation.Nonnull;
009import javax.swing.AbstractAction;
010import javax.swing.JPopupMenu;
011
012import jmri.jmrit.catalog.NamedIcon;
013import jmri.jmrit.logixng.LogixNG;
014import jmri.util.swing.JmriMouseEvent;
015
016/**
017 * An icon that executes a LogixNG when clicked on.
018 *
019 * @author Daniel Bergqvist (C) 2023
020 */
021public class LogixNGIcon extends PositionableLabel {
022
023    public static final IdentityManager IDENTITY_MANAGER = new IdentityManager();
024
025    private final int _identity;
026    private NamedIcon _originalIcon = new NamedIcon("resources/icons/logixng/logixng_icon.gif", "resources/icons/logixng/logixng_icon.gif");
027    private String _originalText = Bundle.getMessage("LogixNGIcon_Text");
028
029    public LogixNGIcon(String s, @Nonnull Editor editor) {
030        super(s, editor);
031        _identity = IDENTITY_MANAGER.getIdentity(this);
032        _originalText = s;
033    }
034
035    public LogixNGIcon(int identity, String s, @Nonnull Editor editor) {
036        super(s, editor);
037        _identity = IDENTITY_MANAGER.getIdentity(identity, this);
038        _originalText = s;
039    }
040
041    public LogixNGIcon(@CheckForNull NamedIcon s, @Nonnull Editor editor) {
042        super(s, editor);
043        _identity = IDENTITY_MANAGER.getIdentity(this);
044        _originalIcon = _namedIcon;
045    }
046
047    public LogixNGIcon(int identity, @CheckForNull NamedIcon s, @Nonnull Editor editor) {
048        super(s, editor);
049        _identity = IDENTITY_MANAGER.getIdentity(identity, this);
050        _originalIcon = _namedIcon;
051
052        // Please retain the line below. It's used to create the resources/icons/logixng/logixng_icon.gif icon
053        // createLogixNGIconImage();
054    }
055
056    @Override
057    @Nonnull
058    public String getTypeString() {
059        return Bundle.getMessage("PositionableType_LogixNGIcon");
060    }
061
062    public int getIdentity() {
063        return _identity;
064    }
065
066    @Override
067    protected void editIcon() {
068        super.editIcon();
069        // If the icon is changed, we must remember that in case the user
070        // switches between icon -> text -> icon
071        _originalIcon = _namedIcon;
072    }
073
074    @Override
075    public void doMousePressed(JmriMouseEvent e) {
076        log.debug("doMousePressed");
077        if (!e.isMetaDown() && !e.isAltDown()) {
078            executeLogixNG();
079        }
080        super.doMousePressed(e);
081    }
082/*
083    @Override
084    public void doMouseReleased(JmriMouseEvent e) {
085        log.debug("doMouseReleased");
086        if (!e.isMetaDown() && !e.isAltDown()) {
087            executeLogixNG();
088        }
089        super.doMouseReleased(e);
090    }
091
092    @Override
093    public void doMouseClicked(JmriMouseEvent e) {
094        if (true && !true) {
095            // this button responds to clicks
096            if (!e.isMetaDown() && !e.isAltDown()) {
097                try {
098                    if (getSensor().getKnownState() == jmri.Sensor.INACTIVE) {
099                        getSensor().setKnownState(jmri.Sensor.ACTIVE);
100                    } else {
101                        getSensor().setKnownState(jmri.Sensor.INACTIVE);
102                    }
103                } catch (jmri.JmriException reason) {
104                    log.warn("Exception flipping sensor", reason);
105                }
106            }
107        }
108        super.doMouseClicked(e);
109    }
110*/
111    public void executeLogixNG() {
112        LogixNG logixNG = getLogixNG();
113
114        if (logixNG != null) {
115            for (int i=0; i < logixNG.getNumConditionalNGs(); i++) {
116                logixNG.getConditionalNG(i).execute();
117            }
118        }
119    }
120
121    private void changeLogixNGIconType() {
122        _unRotatedText = null;
123        if (isIcon()) {
124            _icon = false;
125            _text = true;
126            setText(_originalText);
127            setIcon(null);
128            setOpaque(true);
129        } else if (isText()) {
130            _icon = true;
131            if (getText() != null) {
132                _originalText = getText();
133            }
134            _text = false;
135            setText(null);
136            setUnRotatedText(null);
137            setOpaque(false);
138            setIcon(_originalIcon);
139        }
140        int deg = getDegrees();
141        rotate(deg);
142    }
143
144    /**
145     * Pop-up just displays the sensor name.
146     *
147     * @param popup the menu to display
148     * @return always true
149     */
150    @Override
151    public boolean showPopUp(JPopupMenu popup) {
152        if (isEditable()) {
153            if (isIcon()) {
154                popup.add(new AbstractAction(Bundle.getMessage("ChangeToText")) {
155                    @Override
156                    public void actionPerformed(ActionEvent e) {
157                        changeLogixNGIconType();
158                    }
159                });
160            } else {
161                popup.add(new AbstractAction(Bundle.getMessage("ChangeToIcon")) {
162                    @Override
163                    public void actionPerformed(ActionEvent e) {
164                        changeLogixNGIconType();
165                    }
166                });
167            }
168        }
169        return true;
170    }
171
172
173/*
174    // Please retain this commented method. It's used to create the resources/icons/logixng/logixng_icon.gif icon
175
176    private void createLogixNGIconImage() {
177
178        try {
179            int width = 90, height = 39;
180
181            // TYPE_INT_ARGB specifies the image format: 8-bit RGBA packed into integer pixels
182            java.awt.image.BufferedImage bi = new java.awt.image.BufferedImage(width, height, java.awt.image.BufferedImage.TYPE_INT_ARGB);
183
184            java.awt.Graphics2D ig2 = bi.createGraphics();
185
186            ig2.setColor(java.awt.Color.WHITE);
187            ig2.fillRect(0, 0, width-1, height-1);
188            ig2.setColor(java.awt.Color.BLACK);
189            ig2.drawRect(0, 0, width-1, height-1);
190
191            java.awt.Font font = new java.awt.Font("Verdana", java.awt.Font.BOLD, 15);
192            ig2.setFont(font);
193            ig2.setPaint(java.awt.Color.black);
194
195            // Draw string twice to get more bold
196            ig2.drawString("LogixNG", 11, 24);
197            ig2.drawString("LogixNG", 12, 24);
198
199            javax.imageio.ImageIO.write(bi, "gif", new java.io.File(jmri.util.FileUtil.getExternalFilename("resources/icons/logixng/logixng_icon.gif")));
200        } catch (java.io.IOException ie) {
201            throw new RuntimeException(ie);
202        }
203    }
204*/
205
206
207    public static class IdentityManager {
208
209        Map<Integer, LogixNGIcon> _identities = new HashMap<>();
210        int _lastIdentity = -1;
211
212        private IdentityManager() {
213            // Private constructor to keep it as a singleton
214        }
215
216        public int getIdentity(LogixNGIcon logixNGIcon) {
217            _lastIdentity++;
218            _identities.put(_lastIdentity, logixNGIcon);
219            return _lastIdentity;
220        }
221
222        public int getIdentity(int identity, LogixNGIcon logixNGIcon) {
223            if (_identities.containsKey(identity)) {
224                log.error("Identity {} already exists", identity);
225                return getIdentity(logixNGIcon);
226            }
227            _identities.put(identity, logixNGIcon);
228            if (identity > _lastIdentity) {
229                _lastIdentity = identity;
230            }
231            return identity;
232        }
233
234        public LogixNGIcon getLogixNGIcon(int identity) {
235            return _identities.get(identity);
236        }
237
238    }
239
240
241    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogixNGIcon.class);
242}