001package jmri.jmrit.withrottle; 002 003import jmri.util.startup.PerformActionModel; 004import jmri.util.startup.StartupActionsManager; 005 006import java.awt.FlowLayout; 007import java.awt.GridLayout; 008import java.awt.Insets; 009import java.awt.event.ItemEvent; 010import java.awt.event.ItemListener; 011import java.beans.PropertyChangeEvent; 012import java.io.File; 013import java.util.Arrays; 014 015import javax.swing.BoxLayout; 016import javax.swing.ButtonGroup; 017import javax.swing.JCheckBox; 018import javax.swing.JComponent; 019import javax.swing.JLabel; 020import javax.swing.JPanel; 021import javax.swing.JRadioButton; 022import javax.swing.JSpinner; 023import javax.swing.SpinnerNumberModel; 024 025import jmri.InstanceManager; 026import jmri.swing.JTitledSeparator; 027import jmri.swing.PreferencesPanel; 028import jmri.util.FileUtil; 029import jmri.util.swing.JmriJOptionPane; 030import jmri.util.zeroconf.ZeroConfPreferences; 031import jmri.util.zeroconf.ZeroConfServiceManager; 032 033import org.openide.util.lookup.ServiceProvider; 034 035/** 036 * @author Brett Hoffman Copyright (C) 2010 037 */ 038@ServiceProvider(service = PreferencesPanel.class) 039public class WiThrottlePrefsPanel extends JPanel implements PreferencesPanel { 040 041 JCheckBox eStopCB; 042 JSpinner delaySpinner; 043 044 JCheckBox momF2CB; 045 046 JCheckBox exclusiveCB; 047 048 JSpinner port; 049 050 JCheckBox powerCB; 051 JCheckBox turnoutCB; 052 JCheckBox turnoutCreationCB; 053 JCheckBox routeCB; 054 JCheckBox consistCB; 055 JCheckBox startupCB; 056 JCheckBox useIPv4CB; 057 JCheckBox useIPv6CB; 058 JCheckBox fastClockDisplayCB; 059 ItemListener startupItemListener; 060 int startupActionPosition = -1; 061 JRadioButton wifiRB; 062 JRadioButton dccRB; 063 064 //early defaults while creating panel 065 int eStopInitialValue = 10; 066 int eStopMinValue = 4; 067 int eStopMaxValue = 180; 068 int eStopStepSize = 2; 069 070 WiThrottlePreferences localPrefs; 071 072 public WiThrottlePrefsPanel() { 073 if (InstanceManager.getNullableDefault(WiThrottlePreferences.class) == null) { 074 InstanceManager.store(new WiThrottlePreferences(FileUtil.getUserFilesPath() + "throttle" + File.separator + "WiThrottlePreferences.xml"), WiThrottlePreferences.class); 075 } 076 localPrefs = InstanceManager.getDefault(WiThrottlePreferences.class); 077 initGUI(); 078 setGUI(); 079 } 080 081 public void initGUI() { 082 setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 083 add(new JTitledSeparator(Bundle.getMessage("TitleDelayPanel"))); 084 add(eStopDelayPanel()); 085 add(new JTitledSeparator(Bundle.getMessage("TitleFunctionsPanel"))); 086 add(functionsPanel()); 087 add(new JTitledSeparator(Bundle.getMessage("TitleExclusivePanel"))); 088 add(exclusivePanel()); 089 add(new JTitledSeparator(Bundle.getMessage("TitleNetworkPanel"))); 090 add(networkPanel()); 091 add(new JTitledSeparator(Bundle.getMessage("TitleControllersPanel"))); 092 add(allowedControllers()); 093 } 094 095 private void setGUI() { 096 eStopCB.setSelected(localPrefs.isUseEStop()); 097 delaySpinner.setValue(localPrefs.getEStopDelay()); 098 099 momF2CB.setSelected(localPrefs.isUseMomF2()); 100 101 exclusiveCB.setSelected(localPrefs.isExclusiveUseOfAddress()); 102 103 port.setValue(localPrefs.getPort()); 104 powerCB.setSelected(localPrefs.isAllowTrackPower()); 105 turnoutCB.setSelected(localPrefs.isAllowTurnout()); 106 turnoutCreationCB.setSelected(localPrefs.isAllowTurnoutCreation()); 107 routeCB.setSelected(localPrefs.isAllowRoute()); 108 fastClockDisplayCB.setSelected(localPrefs.isDisplayFastClock()); 109 consistCB.setSelected(localPrefs.isAllowConsist()); 110 InstanceManager.getDefault(StartupActionsManager.class).addPropertyChangeListener((PropertyChangeEvent evt) -> { 111 startupCB.setSelected(isStartUpAction()); 112 }); 113 useIPv4CB.setSelected(isUseIPv4()); 114 useIPv6CB.setSelected(isUseIPv6()); 115 wifiRB.setSelected(localPrefs.isUseWiFiConsist()); 116 dccRB.setSelected(!localPrefs.isUseWiFiConsist()); 117 } 118 119 /** 120 * set the local prefs to match the GUI Local prefs are independent from the 121 * singleton instance prefs. 122 * 123 * @return true if set, false if values are unacceptable. 124 */ 125 private boolean setValues() { 126 boolean didSet = true; 127 localPrefs.setUseEStop(eStopCB.isSelected()); 128 localPrefs.setEStopDelay((Integer) delaySpinner.getValue()); 129 130 localPrefs.setUseMomF2(momF2CB.isSelected()); 131 132 localPrefs.setExclusiveUseOfAddress(exclusiveCB.isSelected()); 133 134 int portNum; 135 try { 136 portNum = (int) port.getValue(); 137 } catch (NumberFormatException NFE) { // Not a number 138 portNum = 0; 139 } 140 if ((portNum < 1) || (portNum > 65535)) { // Invalid port value 141 JmriJOptionPane.showMessageDialog(this, 142 Bundle.getMessage("WarningInvalidPort"), 143 Bundle.getMessage("TitlePortWarningDialog"), 144 JmriJOptionPane.WARNING_MESSAGE); 145 didSet = false; 146 } else { 147 localPrefs.setPort((int) port.getValue()); 148 } 149 150 localPrefs.setAllowTrackPower(powerCB.isSelected()); 151 localPrefs.setAllowTurnout(turnoutCB.isSelected()); 152 localPrefs.setAllowTurnoutCreation(turnoutCreationCB.isSelected()); 153 localPrefs.setAllowRoute(routeCB.isSelected()); 154 localPrefs.setDisplayFastClock(fastClockDisplayCB.isSelected()); 155 localPrefs.setAllowConsist(consistCB.isSelected()); 156 localPrefs.setUseWiFiConsist(wifiRB.isSelected()); 157 ZeroConfPreferences zeroConfPrefs = InstanceManager.getDefault(ZeroConfServiceManager.class).getPreferences(); 158 zeroConfPrefs.setUseIPv4(useIPv4CB.isSelected()); 159 zeroConfPrefs.setUseIPv6(useIPv6CB.isSelected()); 160 161 return didSet; 162 } 163 164 private JPanel eStopDelayPanel() { 165 JPanel panel = new JPanel(); 166 167 eStopCB = new JCheckBox(Bundle.getMessage("LabelUseEStop")); 168 eStopCB.setToolTipText(Bundle.getMessage("ToolTipUseEStop")); 169 SpinnerNumberModel spinMod = new SpinnerNumberModel(eStopInitialValue, eStopMinValue, eStopMaxValue, eStopStepSize); 170 delaySpinner = new JSpinner(spinMod); 171 ((JSpinner.DefaultEditor) delaySpinner.getEditor()).getTextField().setEditable(false); 172 panel.add(eStopCB); 173 panel.add(delaySpinner); 174 panel.add(new JLabel(Bundle.getMessage("LabelEStopDelay"))); 175 return panel; 176 } 177 178 private JPanel functionsPanel() { 179 JPanel panel = new JPanel(); 180 181 momF2CB = new JCheckBox(Bundle.getMessage("LabelMomF2")); 182 momF2CB.setToolTipText(Bundle.getMessage("ToolTipMomF2")); 183 panel.add(momF2CB); 184 return panel; 185 } 186 187 private JPanel exclusivePanel() { 188 JPanel panel = new JPanel(); 189 190 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 191 JPanel eCbPanel = new JPanel(); 192 exclusiveCB = new JCheckBox(Bundle.getMessage("LabelExclusive")); 193 exclusiveCB.setToolTipText(Bundle.getMessage("ToolTipExclusive")); 194 eCbPanel.add(exclusiveCB); 195 panel.add(eCbPanel); 196 197 // only display hint if silent share option is enabled in main throttle prefs 198 var tm = InstanceManager.getNullableDefault(jmri.ThrottleManager.class); 199 if ( tm != null && tm.enablePrefSilentShareOption() ) { 200 JPanel sscHint = new JPanel(); 201 sscHint.add(new JLabel(Bundle.getMessage("LabelStealShare"))); 202 panel.add(sscHint); 203 } 204 return panel; 205 } 206 207 private JPanel networkPanel() { 208 JPanel nPanelRow1 = new JPanel(); 209 JPanel nPanelRow2 = new JPanel(); 210 JPanel nPanelRow3 = new JPanel(); 211 JPanel nPanel = new JPanel(new GridLayout(3, 1)); 212 213 port = new JSpinner(new SpinnerNumberModel(localPrefs.getPort(), 1, 65535, 1)); 214 port.setToolTipText(Bundle.getMessage("PortToolTip")); 215 port.setEditor(new JSpinner.NumberEditor(port, "#")); 216 JLabel label = new JLabel(Bundle.getMessage("LabelPort")); 217 label.setToolTipText(port.getToolTipText()); 218 nPanelRow1.add(port); 219 nPanelRow1.add(label); 220 nPanel.add(nPanelRow1); 221 222 startupCB = new JCheckBox(Bundle.getMessage("LabelStartup"), isStartUpAction()); 223 startupItemListener = (ItemEvent e) -> { 224 this.startupCB.removeItemListener(this.startupItemListener); 225 StartupActionsManager manager = InstanceManager.getDefault(StartupActionsManager.class); 226 if (this.startupCB.isSelected()) { 227 PerformActionModel model = new PerformActionModel(); 228 model.setClassName(WiThrottleCreationAction.class.getName()); 229 if (this.startupActionPosition == -1 || this.startupActionPosition >= manager.getActions().length) { 230 manager.addAction(model); 231 } else { 232 manager.setActions(this.startupActionPosition, model); 233 } 234 } else { 235 manager.getActions(PerformActionModel.class).stream().filter((model) -> (WiThrottleCreationAction.class.getName().equals(model.getClassName()))).forEach((model) -> { 236 this.startupActionPosition = Arrays.asList(manager.getActions()).indexOf(model); 237 manager.removeAction(model); 238 }); 239 } 240 this.startupCB.addItemListener(this.startupItemListener); 241 }; 242 this.startupCB.addItemListener(this.startupItemListener); 243 nPanelRow2.add(startupCB); 244 nPanel.add(nPanelRow2); 245 246 useIPv4CB = new JCheckBox(Bundle.getMessage("LabelUseIPv4"), isUseIPv4()); 247 useIPv4CB.setToolTipText(Bundle.getMessage("ToolTipUseIPv4")); 248 nPanelRow3.add(useIPv4CB); 249 useIPv6CB = new JCheckBox(Bundle.getMessage("LabelUseIPv6"), isUseIPv6()); 250 useIPv6CB.setToolTipText(Bundle.getMessage("ToolTipUseIPv6")); 251 nPanelRow3.add(useIPv6CB); 252 nPanel.add(nPanelRow3); 253 254 return nPanel; 255 } 256 257 private JPanel allowedControllers() { 258 JPanel panel = new JPanel(); 259 260 powerCB = new JCheckBox(Bundle.getMessage("LabelTrackPower")); 261 powerCB.setToolTipText(Bundle.getMessage("ToolTipTrackPower")); 262 263 turnoutCB = new JCheckBox(Bundle.getMessage("Turnouts")); 264 turnoutCB.setToolTipText(Bundle.getMessage("ToolTipTurnout")); 265 266 turnoutCreationCB = new JCheckBox(Bundle.getMessage("TurnoutCreation")); 267 turnoutCreationCB.setToolTipText(Bundle.getMessage("ToolTipTurnoutCreation")); 268 269 routeCB = new JCheckBox(Bundle.getMessage("LabelRoute")); 270 routeCB.setToolTipText(Bundle.getMessage("ToolTipRoute")); 271 272 fastClockDisplayCB = new JCheckBox(Bundle.getMessage("LabelFastClockDisplayed")); 273 fastClockDisplayCB.setToolTipText(Bundle.getMessage("ToolTipFastClockDisplayed")); 274 275 consistCB = new JCheckBox(Bundle.getMessage("LabelConsist")); 276 consistCB.setToolTipText(Bundle.getMessage("ToolTipConsist")); 277 278 wifiRB = new JRadioButton(Bundle.getMessage("LabelWiFiConsist")); 279 wifiRB.setToolTipText(Bundle.getMessage("ToolTipWiFiConsist")); 280 dccRB = new JRadioButton(Bundle.getMessage("LabelDCCConsist")); 281 dccRB.setToolTipText(Bundle.getMessage("ToolTipDCCConsist")); 282 283 ButtonGroup group = new ButtonGroup(); 284 group.add(wifiRB); 285 group.add(dccRB); 286 287 JPanel gridPanel = new JPanel(new GridLayout(0, 2)); 288 JPanel conPanel = new JPanel(); 289 290 gridPanel.add(powerCB); 291 gridPanel.add(fastClockDisplayCB); 292 gridPanel.add(turnoutCB); 293 gridPanel.add(turnoutCreationCB); 294 gridPanel.add(routeCB); 295 296 conPanel.setLayout(new BoxLayout(conPanel, BoxLayout.Y_AXIS)); 297 wifiRB.setMargin(new Insets(0, 20, 0, 0)); 298 dccRB.setMargin(new Insets(0, 20, 0, 0)); 299 conPanel.add(consistCB); 300 conPanel.add(wifiRB); 301 conPanel.add(dccRB); 302 303 panel.setLayout(new FlowLayout(FlowLayout.CENTER, 40, 0)); 304 panel.add(gridPanel); 305 panel.add(conPanel); 306 307 return panel; 308 } 309 310 //private final static Logger log = LoggerFactory.getLogger(WiThrottlePrefsPanel.class); 311 @Override 312 public String getPreferencesItem() { 313 return "WITHROTTLE"; // NOI18N 314 } 315 316 @Override 317 public String getPreferencesItemText() { 318 return Bundle.getMessage("MenuMenu"); // NOI18N 319 } 320 321 @Override 322 public String getTabbedPreferencesTitle() { 323 return getPreferencesItemText(); 324 } 325 326 @Override 327 public String getLabelKey() { 328 return null; 329 } 330 331 @Override 332 public JComponent getPreferencesComponent() { 333 return this; 334 } 335 336 @Override 337 public boolean isPersistant() { 338 return false; 339 } 340 341 @Override 342 public String getPreferencesTooltip() { 343 return null; 344 } 345 346 @Override 347 public void savePreferences() { 348 if (setValues()) { 349 this.localPrefs.save(); 350 } 351 } 352 353 @Override 354 public boolean isDirty() { 355 return this.localPrefs.isDirty(); 356 } 357 358 @Override 359 public boolean isRestartRequired() { 360 return this.localPrefs.isRestartRequired(); 361 } 362 363 @Override 364 public boolean isPreferencesValid() { 365 return true; // no validity checking performed 366 } 367 368 private boolean isStartUpAction() { 369 return InstanceManager.getDefault(StartupActionsManager.class).getActions(PerformActionModel.class).stream() 370 .anyMatch((model) -> (WiThrottleCreationAction.class.getName().equals(model.getClassName()))); 371 } 372 373 private boolean isUseIPv4() { 374 return InstanceManager.getDefault(ZeroConfServiceManager.class).getPreferences().isUseIPv4(); 375 } 376 377 private boolean isUseIPv6() { 378 return InstanceManager.getDefault(ZeroConfServiceManager.class).getPreferences().isUseIPv6(); 379 } 380}