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    @Override
097    public jmri.NamedBean getNamedBean() {
098        return getReporter();
099    }
100
101    // update icon as state changes
102    @Override
103    public void propertyChange(java.beans.PropertyChangeEvent e) {
104        if (log.isDebugEnabled()) {
105            log.debug("property change: {} is now {}", e.getPropertyName(), e.getNewValue());
106        }
107        displayState();
108    }
109
110    @Override
111    @Nonnull
112    public String getTypeString() {
113        return Bundle.getMessage("PositionableType_ReporterIcon");
114    }
115
116    @Override
117    public String getNameString() {
118        String name;
119        if (reporter == null) {
120            name = Bundle.getMessage("NotConnected");
121        } else {
122            name = reporter.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME);
123        }
124        return name;
125    }
126
127    /**
128     * Drive the current state of the display from the state of the Reporter.
129     */
130    void displayState() {
131        Object currentReport = reporter.getCurrentReport();
132        if ( currentReport != null) {
133            String reportString = null;
134            if(currentReport instanceof jmri.Reportable) {
135              reportString = ((jmri.Reportable)currentReport).toReportString();
136            } else {
137              reportString = currentReport.toString();
138            }
139            if (currentReport.equals("")) {
140                setText(Bundle.getMessage("Blank"));
141            } else {
142                setText(reportString);
143            }
144        } else {
145            setText(Bundle.getMessage("NoReport"));
146        }
147        updateSize();
148    }
149
150    @Override
151    protected void edit() {
152        makeIconEditorFrame(this, "Reporter", true, null);
153        _iconEditor.setPickList(jmri.jmrit.picker.PickListModel.reporterPickModelInstance());
154        ActionListener addIconAction = a -> editReporter();
155        _iconEditor.complete(addIconAction, false, true, true);
156        _iconEditor.setSelection(reporter);
157
158    }
159
160    void editReporter() {
161        setReporter((Reporter) _iconEditor.getTableSelection());
162        setSize(getPreferredSize().width, getPreferredSize().height);
163        _iconEditorFrame.dispose();
164        _iconEditorFrame = null;
165        _iconEditor = null;
166        invalidate();
167    }
168
169    @Override
170    public void dispose() {
171        reporter.removePropertyChangeListener(this);
172        reporter = null;
173
174        super.dispose();
175    }
176
177    @Override
178    public int maxHeight() {
179        return getMaximumSize().height;  // defer to superclass
180    }
181
182    @Override
183    public int maxWidth() {
184        return getMaximumSize().width;  // defer to superclass
185    }
186
187    private static final Logger log = LoggerFactory.getLogger(ReporterIcon.class);
188}