001package jmri.jmrit.throttle;
002
003import java.awt.event.ActionEvent;
004import java.beans.PropertyChangeEvent;
005import java.beans.PropertyChangeListener;
006import javax.swing.JButton;
007import jmri.InstanceManager;
008import jmri.JmriException;
009import jmri.PowerManager;
010import jmri.jmrit.catalog.NamedIcon;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014public abstract class PowerManagerButton extends JButton implements PropertyChangeListener {
015
016    private final PropertyChangeListener listener;
017    private Boolean fullText = true;
018    private NamedIcon powerUnknownIcon;
019    private NamedIcon powerOffIcon;
020    private NamedIcon powerOnIcon;
021    private final static Logger log = LoggerFactory.getLogger(PowerManagerButton.class);
022
023    public PowerManagerButton() {
024        this(true);
025    }
026
027    public PowerManagerButton(Boolean fullText) {
028        this.fullText = fullText;
029        this.listener = (PropertyChangeEvent evt) -> {
030            this.setPowerIcons();
031        };
032        PowerManager powerMgr = InstanceManager.getNullableDefault(PowerManager.class);
033        if (powerMgr == null) {
034            log.info("No power manager instance found, panel not active");
035        } else {
036            powerMgr.addPropertyChangeListener(this.listener);
037        }
038        super.addActionListener((ActionEvent e) -> {
039            this.setPower();
040        });
041        this.initComponentsImpl();
042    }
043
044    public void dispose() {
045        PowerManager powerMgr = InstanceManager.getNullableDefault(PowerManager.class);
046        if (powerMgr != null) {
047            powerMgr.removePropertyChangeListener(this.listener);
048        }
049    }
050
051    private void initComponentsImpl() {
052        this.initComponents();
053        this.loadIcons();
054        this.setPowerIcons();
055    }
056
057    /**
058     * Initialize any components within the button or aspects of the button
059     * itself. The default implementation does nothing.
060     */
061    protected void initComponents() {
062        // empty implementation to be overloaded if needed
063    }
064
065    /**
066     * Must be overridden to provide icons for power state indicators.
067     */
068    abstract void loadIcons();
069
070    @Override
071    public void propertyChange(PropertyChangeEvent evt) {
072        this.setPowerIcons();
073    }
074
075    protected void setPowerIcons() {
076        PowerManager powerMgr = InstanceManager.getNullableDefault(PowerManager.class);
077        if (powerMgr == null) {
078            return;
079        }
080        switch (powerMgr.getPower()) {
081            case PowerManager.ON:
082                setIcon(getPowerOnIcon());
083                setToolTipText(Bundle.getMessage("LayoutPowerOn"));
084                if (getFullText()) {
085                    setText(Bundle.getMessage("PowerStateOn"));
086                }
087                break;
088            case PowerManager.OFF:
089                setIcon(getPowerOffIcon());
090                setToolTipText(Bundle.getMessage("LayoutPowerOff"));
091                if (getFullText()) {
092                    setText(Bundle.getMessage("PowerStateOff"));
093                }
094                break;
095            case PowerManager.UNKNOWN:
096                setIcon(getPowerUnknownIcon());
097                setToolTipText(Bundle.getMessage("LayoutPowerUnknown"));
098                if (getFullText()) {
099                    setText(Bundle.getMessage("PowerStateUnknown"));
100                }
101                break;
102            default:
103                setIcon(getPowerUnknownIcon());
104                setToolTipText(Bundle.getMessage("LayoutPowerUnknown"));
105                log.error("Unexpected state value: {}", powerMgr.getPower());
106                if (getFullText()) {
107                    setText(Bundle.getMessage("PowerStateUnknown"));
108                }
109                break;
110        }
111    }
112
113    private void setPower() {
114        PowerManager powerMgr = InstanceManager.getNullableDefault(PowerManager.class);
115        if (powerMgr != null) {
116            try {
117                switch (powerMgr.getPower()) {
118                    case PowerManager.ON:
119                        powerMgr.setPower(PowerManager.OFF);
120                        break;
121                    case PowerManager.OFF:
122                        powerMgr.setPower(PowerManager.ON);
123                        break;
124                    case PowerManager.UNKNOWN:
125                    default:
126                        powerMgr.setPower(PowerManager.OFF);
127                        break;
128                }
129            } catch (JmriException ex) {
130                setIcon(getPowerUnknownIcon());
131                setToolTipText(Bundle.getMessage("LayoutPowerUnknown"));
132                if (getFullText()) {
133                    setText(Bundle.getMessage("PowerStateUnknown"));
134                }
135            }
136        }
137    }
138
139    /**
140     * @return the icon that represents an unknown power state
141     */
142    public NamedIcon getPowerUnknownIcon() {
143        return powerUnknownIcon;
144    }
145
146    /**
147     * @param powerUnknownIcon the icon that represents an unknown power state
148     */
149    public void setPowerUnknownIcon(NamedIcon powerUnknownIcon) {
150        this.powerUnknownIcon = powerUnknownIcon;
151        this.setPowerIcons();
152    }
153
154    /**
155     * @return the icon that represents a power off state
156     */
157    public NamedIcon getPowerOffIcon() {
158        return powerOffIcon;
159    }
160
161    /**
162     * @param powerOffIcon the icon that represents a power off state
163     */
164    public void setPowerOffIcon(NamedIcon powerOffIcon) {
165        this.powerOffIcon = powerOffIcon;
166        this.setPowerIcons();
167    }
168
169    /**
170     * @return the icon that represents a power on state
171     */
172    public NamedIcon getPowerOnIcon() {
173        return powerOnIcon;
174    }
175
176    /**
177     * @param powerOnIcon the icon that represents a power on state
178     */
179    public void setPowerOnIcon(NamedIcon powerOnIcon) {
180        this.powerOnIcon = powerOnIcon;
181        this.setPowerIcons();
182    }
183
184    /**
185     * @return true if text should be shown
186     */
187    protected Boolean getFullText() {
188        return fullText;
189    }
190
191    /**
192     * @param fullText true if text should be shown
193     */
194    protected void setFullText(Boolean fullText) {
195        this.fullText = fullText;
196        this.setPowerIcons();
197    }
198}