001package jmri.jmrit.powerpanel; 002 003import java.awt.Color; 004import java.util.List; 005 006import javax.annotation.Nonnull; 007import javax.swing.*; 008 009import jmri.*; 010import jmri.jmrit.catalog.NamedIcon; 011import jmri.swing.PowerManagerMenu; 012 013/** 014 * Pane for power control 015 * 016 * @author Bob Jacobsen Copyright (C) 2001, 2010 017 */ 018public class PowerPane extends jmri.util.swing.JmriPanel { 019 020 final jmri.swing.PowerManagerMenu selectMenu; 021 final JPanel contentP; 022 final List<SinglePowerPane> mgrList = new java.util.ArrayList<>(); 023 024 /** 025 * Constructor for PowerPane. 026 */ 027 public PowerPane() { 028 this(null); 029 } 030 031 public PowerPane(PowerManager initialMgr){ 032 contentP = new JPanel(); 033 selectMenu = new PowerManagerMenuImpl(initialMgr); 034 contentP.setLayout(new BoxLayout(contentP, BoxLayout.Y_AXIS)); 035 add(contentP); 036 PowerPane.this.managerChanged(); 037 } 038 039 /** 040 * Add Connection menu to choose which to turn on/off. 041 * @return List of menu items (all active connections) 042 */ 043 @Override 044 public List<JMenu> getMenus() { 045 List<JMenu> list = new java.util.ArrayList<>(); 046 list.add(selectMenu); 047 return list; 048 } 049 050 @Override 051 public String getHelpTarget() { 052 return "package.jmri.jmrit.powerpanel.PowerPanelFrame"; 053 } 054 055 @Override 056 public String getTitle() { 057 var mgr = selectMenu.getManager(); 058 return Bundle.getMessage("TitlePowerPanel") + " : " + 059 ( mgr== null ? Bundle.getMessage("AllConnections") : mgr.getUserName()); 060 } 061 062 /** 063 * Reset listener and update status. 064 */ 065 void managerChanged() { 066 log.debug("manager changed to {}", selectMenu.getManager() ); 067 068 mgrList.forEach( SinglePowerPane::dispose); 069 mgrList.clear(); 070 contentP.removeAll(); 071 var mgr = selectMenu.getManager(); 072 if ( mgr != null ){ 073 mgrList.add(new SinglePowerPane(mgr)); 074 } else { 075 List<PowerManager> managers = InstanceManager.getList(PowerManager.class); 076 for (PowerManager pm : managers) { 077 mgrList.add(new SinglePowerPane(pm)); 078 } 079 } 080 for ( SinglePowerPane spp: mgrList){ 081 contentP.add(spp); 082 } 083 084 JFrame f = (JFrame)javax.swing.SwingUtilities.windowForComponent(this); 085 if ( f != null ) { 086 f.pack(); 087 f.setTitle(this.getTitle()); 088 } 089 } 090 091 @Override 092 public void dispose() { 093 mgrList.forEach( SinglePowerPane::dispose); 094 } 095 096 private static final NamedIcon onIcon = new NamedIcon("resources/icons/throttles/power_green.png", "resources/icons/throttles/power_green.png") ; 097 private static final NamedIcon offIcon = new NamedIcon("resources/icons/throttles/power_red.png", "resources/icons/throttles/power_red.png") ; 098 private static final NamedIcon unknownIcon = new NamedIcon("resources/icons/throttles/power_yellow.png", "resources/icons/throttles/power_yellow.png") ; 099 100 class SinglePowerPane extends javax.swing.JPanel implements java.beans.PropertyChangeListener { 101 102 private final PowerManager powerMgr; 103 104 // GUI member declarations 105 private final JLabel onOffStatus = new JLabel(Bundle.getMessage("LabelUnknown")); 106 private final JLabel connLabel = new JLabel(Bundle.getMessage("LabelLayoutPower")); 107 private final JButton onButton = new JButton(Bundle.getMessage("ButtonOn")); 108 private final JButton offButton = new JButton(Bundle.getMessage("ButtonOff")); 109 private final JButton idleButton = new JButton(Bundle.getMessage("ButtonIdle")); 110 111 SinglePowerPane(@Nonnull PowerManager powerManager){ 112 113 super(); 114 powerMgr = powerManager; 115 116 // add listeners to buttons 117 onButton.addActionListener(e -> onButtonPushed()); 118 offButton.addActionListener(e -> offButtonPushed()); 119 idleButton.addActionListener(e -> idleButtonPushed()); 120 idleButton.setToolTipText(Bundle.getMessage("ToolTipIdleButton")); 121 122 // general GUI config 123 setLayout(new java.awt.GridLayout((powerMgr.implementsIdle() ? 3 : 2), 2, 3, 5)); // r, c, hgap , vgap 124 var border = BorderFactory.createLineBorder(Color.BLACK, 1); 125 setBorder(BorderFactory.createTitledBorder(border, 126 PowerManagerMenu.getManagerNameIncludeIfDefault(powerMgr))); 127 128 // set minimum size ( for all 6 cells in the layout ) to prevent twitching 129 onOffStatus.setPreferredSize(new java.awt.Dimension(getLabelMinimumWidth(onOffStatus), onButton.getPreferredSize().height+10 )); 130 131 // install items in GUI 132 add(connLabel); 133 add(onButton); 134 add(onOffStatus); // on row 2 135 add(offButton); 136 137 if ( powerMgr.implementsIdle()) { 138 add(new JLabel("")); // on row 3 139 add(idleButton); 140 } 141 powerMgr.addPropertyChangeListener(SinglePowerPane.this); 142 setStatus(); 143 } 144 145 /** 146 * Respond to Power On button pressed. 147 */ 148 private void onButtonPushed() { 149 if (mgrOK()) { 150 try { 151 powerMgr.setPower(PowerManager.ON); 152 } catch (JmriException e) { 153 couldNotSetPower("Exception trying to turn power on", e); 154 } 155 } 156 } 157 158 /** 159 * Respond to Power Off button pressed. 160 */ 161 private void offButtonPushed() { 162 if (mgrOK()) { 163 try { 164 powerMgr.setPower(PowerManager.OFF); 165 } catch (JmriException e) { 166 couldNotSetPower("Exception trying to turn power off", e); 167 } 168 } 169 } 170 171 /** 172 * Respond to Power Idle button pressed. 173 */ 174 private void idleButtonPushed() { 175 if ( mgrOK() && powerMgr.implementsIdle() ) { 176 try { 177 powerMgr.setPower(PowerManager.IDLE); 178 } catch (JmriException e) { 179 couldNotSetPower("Exception trying to set power to idle", e); 180 } 181 } 182 } 183 184 private void couldNotSetPower( String action, JmriException e){ 185 log.error("PowerPane {}", action, e); 186 jmri.util.swing.JmriJOptionPane.showMessageDialog(this, 187 powerMgr.getUserName() + System.lineSeparator() + 188 action + System.lineSeparator() + e.getMessage(), 189 action, 190 jmri.util.swing.JmriJOptionPane.ERROR_MESSAGE); 191 } 192 193 /** 194 * Get Minimum width for the current power status JLabel. 195 * @return minimum width 196 */ 197 private int getLabelMinimumWidth (JLabel label){ 198 String[] bundleStrings = {"StatusIdle", "StatusOn", "StatusOff", "StatusUnknown"}; 199 int a= 10; 200 for ( String bs : bundleStrings ) { 201 java.awt.FontMetrics fm = label.getFontMetrics(label.getFont()); 202 int wi = fm.stringWidth(Bundle.getMessage(bs)) 203 + onIcon.getIconWidth() + 5; 204 a = Math.max(a, wi); 205 } 206 return a; 207 } 208 209 /** 210 * Display status changes from PowerManager in PowerPane. 211 */ 212 private void setStatus() { 213 // Check to see if the Power Manager has a current status 214 if (mgrOK()) { 215 switch (powerMgr.getPower()) { 216 case PowerManager.ON: 217 onOffStatus.setText(Bundle.getMessage("StatusOn")); 218 onOffStatus.setIcon(onIcon); 219 break; 220 case PowerManager.OFF: 221 onOffStatus.setText(Bundle.getMessage("StatusOff")); 222 onOffStatus.setIcon(offIcon); 223 break; 224 case PowerManager.IDLE: 225 onOffStatus.setText(Bundle.getMessage("StatusIdle")); 226 onOffStatus.setIcon(unknownIcon); 227 break; 228 case PowerManager.UNKNOWN: 229 onOffStatus.setText(Bundle.getMessage("StatusUnknown")); 230 onOffStatus.setIcon(unknownIcon); 231 break; 232 default: 233 onOffStatus.setText(Bundle.getMessage("StatusUnknown")); 234 onOffStatus.setIcon(unknownIcon); 235 log.error("Unexpected state value: {}", selectMenu.getManager()); 236 break; 237 } 238 } 239 } 240 241 /** 242 * Check for presence of PowerManager. 243 * @return True if one is available, false if not 244 */ 245 private boolean mgrOK() { 246 return InstanceManager.getList(PowerManager.class).contains(powerMgr); 247 } 248 249 @Override 250 public void propertyChange(java.beans.PropertyChangeEvent ev) { 251 setStatus(); 252 } 253 254 void dispose() { 255 powerMgr.removePropertyChangeListener(this); 256 } 257 258 } 259 260 class PowerManagerMenuImpl extends PowerManagerMenu { 261 262 PowerManagerMenuImpl(PowerManager mgr) { 263 super(true, mgr); 264 } 265 266 @Override 267 protected void choiceChanged() { 268 managerChanged(); 269 } 270 } 271 272 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PowerPane.class); 273 274}