001package jmri.jmrit.display;
002
003import java.awt.event.ActionListener;
004
005import javax.annotation.Nonnull;
006import javax.swing.JPopupMenu;
007
008import jmri.InstanceManager;
009import jmri.Reporter;
010import jmri.NamedBean.DisplayOptions;
011
012import org.slf4j.Logger;
013import org.slf4j.LoggerFactory;
014
015/**
016 * An icon to display info from a Reporter, e.g. transponder or RFID reader.
017 *
018 * @author Bob Jacobsen Copyright (c) 2004
019 */
020public class ReporterIcon extends PositionableLabel implements java.beans.PropertyChangeListener {
021
022    public ReporterIcon(Editor editor) {
023        // super ctor call to make sure this is a String label
024        super("???", editor);
025        setText("???");
026        setPopupUtility(new ReporterPopupUtil(this, this));
027    }
028
029    // suppress inappropriate menu items
030    static class ReporterPopupUtil extends PositionablePopupUtil {
031
032        ReporterPopupUtil(Positionable parent, javax.swing.JComponent textComp) {
033            super(parent, textComp);
034        }
035
036        @Override
037        public void setTextJustificationMenu(JPopupMenu popup) {
038        }
039
040        @Override
041        public void setFixedTextMenu(JPopupMenu popup) {
042        }
043
044        @Override
045        public void setTextMarginMenu(JPopupMenu popup) {
046        }
047    }
048    // the associated Reporter object
049    Reporter reporter = null;
050
051    @Override
052    public Positionable deepClone() {
053        ReporterIcon pos = new ReporterIcon(_editor);
054        return finishClone(pos);
055    }
056
057    protected Positionable finishClone(ReporterIcon pos) {
058        pos.setReporter(reporter.getSystemName());
059        return super.finishClone(pos);
060    }
061
062    /**
063     * Attached a named Reporter to this display item
064     *
065     * @param pName Used as a system/user name to lookup the Reporter object
066     */
067    public void setReporter(String pName) {
068        if (InstanceManager.getNullableDefault(jmri.ReporterManager.class) != null) {
069            try {
070                reporter = InstanceManager.getDefault(jmri.ReporterManager.class).
071                    provideReporter(pName);
072                setReporter(reporter);
073            } catch (IllegalArgumentException e) {
074                log.error("Reporter '{}' not available, icon won't see changes", pName);
075            }
076        } else {
077            log.error("No ReporterManager for this protocol, icon won't see changes");
078        }
079    }
080
081    public void setReporter(Reporter r) {
082        if (reporter != null) {
083            reporter.removePropertyChangeListener(this);
084        }
085        reporter = r;
086        if (reporter != null) {
087            displayState();
088            reporter.addPropertyChangeListener(this);
089        }
090    }
091
092    public Reporter getReporter() {
093        return reporter;
094    }
095
096    // update icon as state changes
097    @Override
098    public void propertyChange(java.beans.PropertyChangeEvent e) {
099        if (log.isDebugEnabled()) {
100            log.debug("property change: {} is now {}", e.getPropertyName(), e.getNewValue());
101        }
102        displayState();
103    }
104
105    @Override
106    @Nonnull
107    public String getTypeString() {
108        return Bundle.getMessage("PositionableType_ReporterIcon");
109    }
110
111    @Override
112    public String getNameString() {
113        String name;
114        if (reporter == null) {
115            name = Bundle.getMessage("NotConnected");
116        } else {
117            name = reporter.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME);
118        }
119        return name;
120    }
121
122    /**
123     * Drive the current state of the display from the state of the Reporter.
124     */
125    void displayState() {
126        Object currentReport = reporter.getCurrentReport();
127        if ( currentReport != null) {
128            String reportString = null;
129            if(currentReport instanceof jmri.Reportable) {
130              reportString = ((jmri.Reportable)currentReport).toReportString();
131            } else {
132              reportString = currentReport.toString();
133            }
134            if (currentReport.equals("")) {
135                setText(Bundle.getMessage("Blank"));
136            } else {
137                setText(reportString);
138            }
139        } else {
140            setText(Bundle.getMessage("NoReport"));
141        }
142        updateSize();
143    }
144
145    @Override
146    protected void edit() {
147        makeIconEditorFrame(this, "Reporter", true, null);
148        _iconEditor.setPickList(jmri.jmrit.picker.PickListModel.reporterPickModelInstance());
149        ActionListener addIconAction = a -> editReporter();
150        _iconEditor.complete(addIconAction, false, true, true);
151        _iconEditor.setSelection(reporter);
152
153    }
154
155    void editReporter() {
156        setReporter((Reporter) _iconEditor.getTableSelection());
157        setSize(getPreferredSize().width, getPreferredSize().height);
158        _iconEditorFrame.dispose();
159        _iconEditorFrame = null;
160        _iconEditor = null;
161        invalidate();
162    }
163
164    @Override
165    public void dispose() {
166        reporter.removePropertyChangeListener(this);
167        reporter = null;
168
169        super.dispose();
170    }
171
172    @Override
173    public int maxHeight() {
174        return ((javax.swing.JLabel) this).getMaximumSize().height;  // defer to superclass
175    }
176
177    @Override
178    public int maxWidth() {
179        return ((javax.swing.JLabel) this).getMaximumSize().width;  // defer to superclass
180    }
181
182    private final static Logger log = LoggerFactory.getLogger(ReporterIcon.class);
183}