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 // Delete any existing WiThrottle start up actions. 228 // Manually adding a start up action sets the start up check box active which triggers 229 // the creation of a second start up action. 230 manager.getActions(PerformActionModel.class).stream().filter((model) -> (WiThrottleCreationAction.class.getName().equals(model.getClassName()))).forEach((model) -> { 231 this.startupActionPosition = Arrays.asList(manager.getActions()).indexOf(model); 232 manager.removeAction(model); 233 }); 234 235 PerformActionModel model = new PerformActionModel(); 236 model.setClassName(WiThrottleCreationAction.class.getName()); 237 if (this.startupActionPosition == -1 || this.startupActionPosition >= manager.getActions().length) { 238 manager.addAction(model); 239 } else { 240 manager.setActions(this.startupActionPosition, model); 241 } 242 } else { 243 manager.getActions(PerformActionModel.class).stream().filter((model) -> (WiThrottleCreationAction.class.getName().equals(model.getClassName()))).forEach((model) -> { 244 this.startupActionPosition = Arrays.asList(manager.getActions()).indexOf(model); 245 manager.removeAction(model); 246 }); 247 } 248 this.startupCB.addItemListener(this.startupItemListener); 249 }; 250 this.startupCB.addItemListener(this.startupItemListener); 251 nPanelRow2.add(startupCB); 252 nPanel.add(nPanelRow2); 253 254 useIPv4CB = new JCheckBox(Bundle.getMessage("LabelUseIPv4"), isUseIPv4()); 255 useIPv4CB.setToolTipText(Bundle.getMessage("ToolTipUseIPv4")); 256 nPanelRow3.add(useIPv4CB); 257 useIPv6CB = new JCheckBox(Bundle.getMessage("LabelUseIPv6"), isUseIPv6()); 258 useIPv6CB.setToolTipText(Bundle.getMessage("ToolTipUseIPv6")); 259 nPanelRow3.add(useIPv6CB); 260 nPanel.add(nPanelRow3); 261 262 return nPanel; 263 } 264 265 private JPanel allowedControllers() { 266 JPanel panel = new JPanel(); 267 268 powerCB = new JCheckBox(Bundle.getMessage("LabelTrackPower")); 269 powerCB.setToolTipText(Bundle.getMessage("ToolTipTrackPower")); 270 271 turnoutCB = new JCheckBox(Bundle.getMessage("Turnouts")); 272 turnoutCB.setToolTipText(Bundle.getMessage("ToolTipTurnout")); 273 274 turnoutCreationCB = new JCheckBox(Bundle.getMessage("TurnoutCreation")); 275 turnoutCreationCB.setToolTipText(Bundle.getMessage("ToolTipTurnoutCreation")); 276 277 routeCB = new JCheckBox(Bundle.getMessage("LabelRoute")); 278 routeCB.setToolTipText(Bundle.getMessage("ToolTipRoute")); 279 280 fastClockDisplayCB = new JCheckBox(Bundle.getMessage("LabelFastClockDisplayed")); 281 fastClockDisplayCB.setToolTipText(Bundle.getMessage("ToolTipFastClockDisplayed")); 282 283 consistCB = new JCheckBox(Bundle.getMessage("LabelConsist")); 284 consistCB.setToolTipText(Bundle.getMessage("ToolTipConsist")); 285 286 wifiRB = new JRadioButton(Bundle.getMessage("LabelWiFiConsist")); 287 wifiRB.setToolTipText(Bundle.getMessage("ToolTipWiFiConsist")); 288 dccRB = new JRadioButton(Bundle.getMessage("LabelDCCConsist")); 289 dccRB.setToolTipText(Bundle.getMessage("ToolTipDCCConsist")); 290 291 ButtonGroup group = new ButtonGroup(); 292 group.add(wifiRB); 293 group.add(dccRB); 294 295 JPanel gridPanel = new JPanel(new GridLayout(0, 2)); 296 JPanel conPanel = new JPanel(); 297 298 gridPanel.add(powerCB); 299 gridPanel.add(fastClockDisplayCB); 300 gridPanel.add(turnoutCB); 301 gridPanel.add(turnoutCreationCB); 302 gridPanel.add(routeCB); 303 304 conPanel.setLayout(new BoxLayout(conPanel, BoxLayout.Y_AXIS)); 305 wifiRB.setMargin(new Insets(0, 20, 0, 0)); 306 dccRB.setMargin(new Insets(0, 20, 0, 0)); 307 conPanel.add(consistCB); 308 conPanel.add(wifiRB); 309 conPanel.add(dccRB); 310 311 panel.setLayout(new FlowLayout(FlowLayout.CENTER, 40, 0)); 312 panel.add(gridPanel); 313 panel.add(conPanel); 314 315 return panel; 316 } 317 318 //private final static Logger log = LoggerFactory.getLogger(WiThrottlePrefsPanel.class); 319 @Override 320 public String getPreferencesItem() { 321 return "WITHROTTLE"; // NOI18N 322 } 323 324 @Override 325 public String getPreferencesItemText() { 326 return Bundle.getMessage("MenuMenu"); // NOI18N 327 } 328 329 @Override 330 public String getTabbedPreferencesTitle() { 331 return getPreferencesItemText(); 332 } 333 334 @Override 335 public String getLabelKey() { 336 return null; 337 } 338 339 @Override 340 public JComponent getPreferencesComponent() { 341 return this; 342 } 343 344 @Override 345 public boolean isPersistant() { 346 return false; 347 } 348 349 @Override 350 public String getPreferencesTooltip() { 351 return null; 352 } 353 354 @Override 355 public void savePreferences() { 356 if (setValues()) { 357 this.localPrefs.save(); 358 } 359 } 360 361 @Override 362 public boolean isDirty() { 363 return this.localPrefs.isDirty(); 364 } 365 366 @Override 367 public boolean isRestartRequired() { 368 return this.localPrefs.isRestartRequired(); 369 } 370 371 @Override 372 public boolean isPreferencesValid() { 373 return true; // no validity checking performed 374 } 375 376 private boolean isStartUpAction() { 377 return InstanceManager.getDefault(StartupActionsManager.class).getActions(PerformActionModel.class).stream() 378 .anyMatch((model) -> (WiThrottleCreationAction.class.getName().equals(model.getClassName()))); 379 } 380 381 private boolean isUseIPv4() { 382 return InstanceManager.getDefault(ZeroConfServiceManager.class).getPreferences().isUseIPv4(); 383 } 384 385 private boolean isUseIPv6() { 386 return InstanceManager.getDefault(ZeroConfServiceManager.class).getPreferences().isUseIPv6(); 387 } 388}