001package jmri.jmrit.throttle.buttons;
002
003import java.beans.PropertyChangeListener;
004
005import javax.annotation.CheckForNull;
006import javax.swing.JButton;
007
008import jmri.InstanceManager;
009import jmri.JmriException;
010import jmri.PowerManager;
011import jmri.jmrit.catalog.NamedIcon;
012
013/**
014 * 
015 * A button handling layout power
016 * 
017 * <hr>
018 * This file is part of JMRI.
019 * <p>
020 * JMRI is free software; you can redistribute it and/or modify it under the
021 * terms of version 2 of the GNU General Public License as published by the Free
022 * Software Foundation. See the "COPYING" file for a copy of this license.
023 * <p>
024 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
025 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
026 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
027 *
028 */
029
030public abstract class PowerManagerButton extends JButton {
031
032    private final transient PropertyChangeListener listener;
033    private final PowerManager powerMgr;
034    private boolean fullText = true;
035    private NamedIcon powerUnknownIcon;
036    private NamedIcon powerOffIcon;
037    private NamedIcon powerOnIcon;
038    private NamedIcon powerIdleIcon;
039
040    public PowerManagerButton() {
041        this(true);
042    }
043
044    public PowerManagerButton(Boolean fullText) {
045        this(fullText, InstanceManager.getNullableDefault(PowerManager.class));
046    }
047
048    PowerManagerButton(boolean fullText, @CheckForNull PowerManager powerMgr) {
049        this.fullText = fullText;
050        this.powerMgr = powerMgr;
051        this.listener = evt -> this.setPowerIcons();
052
053        if (powerMgr == null) {
054            log.info("No power manager instance found, panel not active");
055        } else {
056            powerMgr.addPropertyChangeListener(this.listener);
057        }
058        super.addActionListener( e -> this.setPower());
059
060        this.initComponentsImpl();
061    }
062
063    public void dispose() {
064        if (powerMgr != null) {
065            powerMgr.removePropertyChangeListener(this.listener);
066        }
067    }
068
069    private void initComponentsImpl() {
070        this.initComponents();
071        this.loadIcons();
072        this.setPowerIcons();
073    }
074
075    /**
076     * Initialize any components within the button or aspects of the button
077     * itself. The default implementation does nothing.
078     */
079    protected void initComponents() {
080        // empty implementation to be overloaded if needed
081    }
082
083    /**
084     * Must be overridden to provide icons for power state indicators.
085     */
086    abstract void loadIcons();
087
088    protected void setPowerIcons() {
089        if (powerMgr == null) {
090            return;
091        }
092        switch (powerMgr.getPower()) {
093            case PowerManager.ON:
094                setIcon(getPowerOnIcon());
095                setToolTipText(Bundle.getMessage("LayoutPowerOn"));
096                if (getFullText()) {
097                    setText(Bundle.getMessage("PowerStateOn"));
098                }
099                break;
100            case PowerManager.OFF:
101                setIcon(getPowerOffIcon());
102                setToolTipText(Bundle.getMessage("LayoutPowerOff"));
103                if (getFullText()) {
104                    setText(Bundle.getMessage("PowerStateOff"));
105                }
106                break;
107            case PowerManager.IDLE:
108                setIcon(getPowerIdleIcon());
109                setToolTipText(Bundle.getMessage("LayoutPowerIdle"));
110                if (getFullText()) {
111                    setText(Bundle.getMessage("PowerStateIdle"));
112                }
113                break;
114            case PowerManager.UNKNOWN:
115                setIcon(getPowerUnknownIcon());
116                setToolTipText(Bundle.getMessage("LayoutPowerUnknown"));
117                if (getFullText()) {
118                    setText(Bundle.getMessage("PowerStateUnknown"));
119                }
120                break;
121            default:
122                setIcon(getPowerUnknownIcon());
123                setToolTipText(Bundle.getMessage("LayoutPowerUnknown"));
124                log.error("Unexpected state value: {}", powerMgr.getPower());
125                if (getFullText()) {
126                    setText(Bundle.getMessage("PowerStateUnknown"));
127                }
128                break;
129        }
130    }
131
132    private void setPower() {
133        if (powerMgr != null) {
134            try {
135                switch (powerMgr.getPower()) {
136                    case PowerManager.OFF:
137                        powerMgr.setPower(PowerManager.ON);
138                        break;
139                    case PowerManager.ON:
140                    case PowerManager.IDLE:
141                    case PowerManager.UNKNOWN:
142                    default:
143                        powerMgr.setPower(PowerManager.OFF);
144                        break;
145                }
146            } catch (JmriException ex) {
147                setIcon(getPowerUnknownIcon());
148                setToolTipText(Bundle.getMessage("LayoutPowerUnknown"));
149                if (getFullText()) {
150                    setText(Bundle.getMessage("PowerStateUnknown"));
151                }
152                log.error("Could not set Power to {}",powerMgr,ex);
153            }
154        }
155    }
156
157    /**
158     * @return the icon that represents an unknown power state
159     */
160    public NamedIcon getPowerUnknownIcon() {
161        return powerUnknownIcon;
162    }
163
164    /**
165     * @param powerUnknownIcon the icon that represents an unknown power state
166     */
167    public void setPowerUnknownIcon(NamedIcon powerUnknownIcon) {
168        this.powerUnknownIcon = powerUnknownIcon;
169        this.setPowerIcons();
170    }
171
172    /**
173     * @return the icon that represents a power off state
174     */
175    public NamedIcon getPowerOffIcon() {
176        return powerOffIcon;
177    }
178
179    /**
180     * @param powerOffIcon the icon that represents a power off state
181     */
182    public void setPowerOffIcon(NamedIcon powerOffIcon) {
183        this.powerOffIcon = powerOffIcon;
184        this.setPowerIcons();
185    }
186
187    /**
188     * @return the icon that represents a power on state
189     */
190    public NamedIcon getPowerOnIcon() {
191        return powerOnIcon;
192    }
193
194    /**
195     * @param powerOnIcon the icon that represents a power on state
196     */
197    public void setPowerOnIcon(NamedIcon powerOnIcon) {
198        this.powerOnIcon = powerOnIcon;
199        this.setPowerIcons();
200    }
201
202    /**
203     * @return the icon that represents a power on state
204     */
205    public NamedIcon getPowerIdleIcon() {
206        return powerIdleIcon;
207    }
208
209    /**
210     * @param icon the icon that represents a power Idle state.
211     */
212    public void setPowerIdleIcon(NamedIcon icon) {
213        this.powerIdleIcon = icon;
214        this.setPowerIcons();
215    }
216
217    /**
218     * @return true if text should be shown
219     */
220    private boolean getFullText() {
221        return fullText;
222    }
223
224    /**
225     * @param fullText true if text should be shown
226     */
227    protected void setFullText(boolean fullText) {
228        this.fullText = fullText;
229        this.setPowerIcons();
230    }
231
232    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PowerManagerButton.class);
233
234}